From b77e00d60e786e1f8078a43752db0be8b8a02198 Mon Sep 17 00:00:00 2001 From: guillaumebarat Date: Thu, 12 Dec 2024 09:01:23 +1000 Subject: [PATCH] bump simplesamlphp to 2.3.5 --- .extlib/simplesamlphp/bin/console | 0 .../simplesamlphp/bin/convertTranslations.php | 0 .../simplesamlphp/bin/importPdoMetadata.php | 0 .extlib/simplesamlphp/bin/initMDSPdo.php | 0 .../simplesamlphp/bin/ldapattrschemaparser.pl | 0 .extlib/simplesamlphp/bin/memcacheSync.php | 0 .extlib/simplesamlphp/bin/pwgen.php | 0 .../simplesamlphp/bin/translateAttributes.php | 0 .extlib/simplesamlphp/bin/translations | 0 .../docs/simplesamlphp-changelog.md | 24 +- .../docs/simplesamlphp-install.md | 1 + .../docs/simplesamlphp-upgrade-notes-2.3.md | 4 +- .../simplesamlphp/extra/simplesamlphp.spec | 2 +- .../metadata/saml20-sp-remote.php.dist | 4 +- .../modules/adfs/.markdownlintignore | 1 + .../modules/adfs/.markdownlintrc | 4 + .extlib/simplesamlphp/modules/adfs/LICENSE | 459 + .extlib/simplesamlphp/modules/adfs/README.md | 42 + .../simplesamlphp/modules/adfs/composer.json | 59 + .../simplesamlphp/modules/adfs/docs/adfs.md | 97 + .../adfs/metadata/adfs-idp-hosted.php.dist | 15 + .../adfs/metadata/adfs-sp-remote.php.dist | 14 + .../simplesamlphp/modules/adfs/psalm-dev.xml | 27 + .../adfs/public/assets/js/postResponse.js | 3 + .../modules/adfs/routing/routes/routes.yml | 29 + .../modules/adfs/src/Controller/Adfs.php | 265 + .../modules/adfs/src/IdP/ADFS.php | 479 ++ .../adfs/src/SAML2/XML/fed/Constants.php | 19 + .../adfs/src/SAML2/XML/fed/Endpoint.php | 38 + .../XML/fed/SecurityTokenServiceType.php | 92 + .../src/SAML2/XML/fed/TokenTypesOffered.php | 34 + .../modules/adfs/templates/postResponse.twig | 16 + .../adfs/tools/composer-require-checker.json | 4 + .../simplesamlphp/modules/cron/bin/cron.php | 0 .../modules/saml/src/Auth/Source/SP.php | 38 +- .../public/assets/base/css/stylesheet.css | 6 +- .../public/assets/base/css/stylesheet.css.map | 2 +- .../public/assets/base/fonts/fa-solid-900.ttf | Bin 423676 -> 426112 bytes .../assets/base/fonts/fa-solid-900.woff2 | Bin 157192 -> 158224 bytes .../src/SimpleSAML/Configuration.php | 11 +- .../src/SimpleSAML/Locale/Language.php | 2 +- .../simplesamlphp/src/SimpleSAML/Session.php | 16 +- .../src/SimpleSAML/Utils/HTTP.php | 7 - .extlib/simplesamlphp/templates/post.twig | 4 +- .extlib/simplesamlphp/vendor/autoload.php | 2 +- .../vendor/bin/export-plural-rules | 0 .../vendor/bin/patch-type-declarations | 0 .extlib/simplesamlphp/vendor/bin/php-parse | 119 + .extlib/simplesamlphp/vendor/bin/phpcbf | 119 + .extlib/simplesamlphp/vendor/bin/phpcs | 119 + .extlib/simplesamlphp/vendor/bin/phpstan | 119 + .extlib/simplesamlphp/vendor/bin/phpstan.phar | 119 + .extlib/simplesamlphp/vendor/bin/phpunit | 122 + .../simplesamlphp/vendor/bin/simple-phpunit | 119 + .../simplesamlphp/vendor/bin/var-dump-server | 0 .extlib/simplesamlphp/vendor/bin/yaml-lint | 0 .../vendor/composer/autoload_classmap.php | 1159 +++ .../vendor/composer/autoload_files.php | 6 + .../vendor/composer/autoload_namespaces.php | 1 + .../vendor/composer/autoload_psr4.php | 22 +- .../vendor/composer/autoload_real.php | 10 +- .../vendor/composer/autoload_static.php | 1289 ++- .../vendor/composer/installed.json | 3448 +++++++- .../vendor/composer/installed.php | 511 +- .../LICENSE.md | 22 + .../README.md | 285 + .../composer.json | 71 + .../src/Plugin.php | 637 ++ .../vendor/gettext/gettext/CHANGELOG.md | 12 + .../gettext/gettext/src/Loader/Loader.php | 6 +- .../gettext/src/Loader/LoaderInterface.php | 4 +- .../gettext/gettext/src/Loader/MoLoader.php | 2 +- .../gettext/gettext/src/Loader/PoLoader.php | 2 +- .../gettext/src/Loader/StrictPoLoader.php | 2 +- .../vendor/gettext/gettext/src/References.php | 2 +- .../src/Scanner/FunctionsHandlersTrait.php | 2 +- .../gettext/src/Scanner/ParsedFunction.php | 2 +- .../gettext/gettext/src/Scanner/Scanner.php | 2 +- .../gettext/gettext/src/Translation.php | 2 +- .../gettext/gettext/src/Translations.php | 2 +- .../gettext/languages/bin/export-plural-rules | 0 .../vendor/gettext/php-scanner/CHANGELOG.md | 65 + .../gettext/php-scanner/CONTRIBUTING.md | 17 + .../vendor/gettext/php-scanner/LICENSE | 21 + .../vendor/gettext/php-scanner/README.md | 64 + .../vendor/gettext/php-scanner/composer.json | 48 + .../php-scanner/src/PhpFunctionsScanner.php | 42 + .../php-scanner/src/PhpNodeVisitor.php | 169 + .../gettext/php-scanner/src/PhpScanner.php | 67 + .../vfsstream/.github/workflows/runTests.yml | 71 + .../vendor/mikey179/vfsstream/CHANGELOG.md | 275 + .../vendor/mikey179/vfsstream/LICENSE | 27 + .../vendor/mikey179/vfsstream/README.md | 8 + .../vendor/mikey179/vfsstream/composer.json | 37 + .../mikey179/vfsstream/phpunit.xml.dist | 43 + .../main/php/org/bovigo/vfs/DotDirectory.php | 36 + .../src/main/php/org/bovigo/vfs/Quota.php | 86 + .../org/bovigo/vfs/content/FileContent.php | 71 + .../bovigo/vfs/content/LargeFileContent.php | 167 + .../vfs/content/SeekableFileContent.php | 134 + .../vfs/content/StringBasedFileContent.php | 97 + .../src/main/php/org/bovigo/vfs/vfsStream.php | 479 ++ .../bovigo/vfs/vfsStreamAbstractContent.php | 418 + .../php/org/bovigo/vfs/vfsStreamBlock.php | 34 + .../php/org/bovigo/vfs/vfsStreamContainer.php | 61 + .../bovigo/vfs/vfsStreamContainerIterator.php | 98 + .../php/org/bovigo/vfs/vfsStreamContent.php | 213 + .../php/org/bovigo/vfs/vfsStreamDirectory.php | 267 + .../php/org/bovigo/vfs/vfsStreamException.php | 19 + .../main/php/org/bovigo/vfs/vfsStreamFile.php | 394 + .../php/org/bovigo/vfs/vfsStreamWrapper.php | 1018 +++ .../vfs/visitor/vfsStreamAbstractVisitor.php | 64 + .../vfs/visitor/vfsStreamPrintVisitor.php | 108 + .../vfs/visitor/vfsStreamStructureVisitor.php | 111 + .../bovigo/vfs/visitor/vfsStreamVisitor.php | 55 + .../mikey179/vfsstream/src/test/bootstrap.php | 46 + .../bovigo/vfs/DirectoryIterationTestCase.php | 318 + .../php/org/bovigo/vfs/FilenameTestCase.php | 88 + .../php/org/bovigo/vfs/Issue104TestCase.php | 52 + .../org/bovigo/vfs/PermissionsTestCase.php | 121 + .../test/php/org/bovigo/vfs/QuotaTestCase.php | 80 + .../php/org/bovigo/vfs/UnlinkTestCase.php | 58 + .../vfs/content/LargeFileContentTestCase.php | 225 + .../StringBasedFileContentTestCase.php | 232 + .../proxy/vfsStreamWrapperRecordingProxy.php | 325 + .../vfs/vfsStreamAbstractContentTestCase.php | 1053 +++ .../org/bovigo/vfs/vfsStreamBlockTestCase.php | 89 + .../vfsStreamContainerIteratorTestCase.php | 111 + .../vfsStreamDirectoryIssue134TestCase.php | 64 + .../vfs/vfsStreamDirectoryIssue18TestCase.php | 80 + .../bovigo/vfs/vfsStreamDirectoryTestCase.php | 334 + .../bovigo/vfs/vfsStreamExLockTestCase.php | 55 + .../org/bovigo/vfs/vfsStreamFileTestCase.php | 337 + .../org/bovigo/vfs/vfsStreamGlobTestCase.php | 28 + .../vfsStreamResolveIncludePathTestCase.php | 61 + .../php/org/bovigo/vfs/vfsStreamTestCase.php | 780 ++ .../org/bovigo/vfs/vfsStreamUmaskTestCase.php | 194 + ...StreamWrapperAlreadyRegisteredTestCase.php | 62 + .../vfs/vfsStreamWrapperBaseTestCase.php | 98 + .../vfsStreamWrapperDirSeparatorTestCase.php | 72 + .../vfs/vfsStreamWrapperDirTestCase.php | 503 ++ .../vfs/vfsStreamWrapperFileTestCase.php | 457 + .../vfs/vfsStreamWrapperFileTimesTestCase.php | 314 + .../vfs/vfsStreamWrapperFlockTestCase.php | 439 + .../vfs/vfsStreamWrapperLargeFileTestCase.php | 81 + .../vfs/vfsStreamWrapperQuotaTestCase.php | 223 + .../vfs/vfsStreamWrapperSetOptionTestCase.php | 75 + .../vfsStreamWrapperStreamSelectTestCase.php | 42 + .../bovigo/vfs/vfsStreamWrapperTestCase.php | 791 ++ .../vfsStreamWrapperUnregisterTestCase.php | 75 + .../vfsStreamWrapperWithoutRootTestCase.php | 63 + .../org/bovigo/vfs/vfsStreamZipTestCase.php | 52 + .../vfsStreamAbstractVisitorTestCase.php | 98 + .../visitor/vfsStreamPrintVisitorTestCase.php | 102 + .../vfsStreamStructureVisitorTestCase.php | 85 + .../vfsstream/src/test/phpt/bug71287.phpt | 29 + .../filesystemcopy/emptyFolder/.gitignore | 0 .../filesystemcopy/withSubfolders/aFile.txt | 1 + .../withSubfolders/subfolder1/file1.txt | 1 + .../withSubfolders/subfolder2/.gitignore | 0 .../vendor/myclabs/deep-copy/LICENSE | 20 + .../vendor/myclabs/deep-copy/README.md | 406 + .../vendor/myclabs/deep-copy/composer.json | 43 + .../deep-copy/src/DeepCopy/DeepCopy.php | 316 + .../src/DeepCopy/Exception/CloneException.php | 9 + .../DeepCopy/Exception/PropertyException.php | 9 + .../src/DeepCopy/Filter/ChainableFilter.php | 24 + .../Doctrine/DoctrineCollectionFilter.php | 33 + .../DoctrineEmptyCollectionFilter.php | 28 + .../Filter/Doctrine/DoctrineProxyFilter.php | 22 + .../deep-copy/src/DeepCopy/Filter/Filter.php | 18 + .../src/DeepCopy/Filter/KeepFilter.php | 16 + .../src/DeepCopy/Filter/ReplaceFilter.php | 39 + .../src/DeepCopy/Filter/SetNullFilter.php | 24 + .../Matcher/Doctrine/DoctrineProxyMatcher.php | 22 + .../src/DeepCopy/Matcher/Matcher.php | 14 + .../src/DeepCopy/Matcher/PropertyMatcher.php | 39 + .../DeepCopy/Matcher/PropertyNameMatcher.php | 32 + .../DeepCopy/Matcher/PropertyTypeMatcher.php | 52 + .../DeepCopy/Reflection/ReflectionHelper.php | 78 + .../TypeFilter/Date/DateIntervalFilter.php | 33 + .../TypeFilter/Date/DatePeriodFilter.php | 42 + .../src/DeepCopy/TypeFilter/ReplaceFilter.php | 30 + .../DeepCopy/TypeFilter/ShallowCopyFilter.php | 17 + .../TypeFilter/Spl/ArrayObjectFilter.php | 36 + .../TypeFilter/Spl/SplDoublyLinkedList.php | 10 + .../Spl/SplDoublyLinkedListFilter.php | 51 + .../src/DeepCopy/TypeFilter/TypeFilter.php | 13 + .../src/DeepCopy/TypeMatcher/TypeMatcher.php | 29 + .../deep-copy/src/DeepCopy/deep_copy.php | 20 + .../vendor/nikic/php-parser/LICENSE | 29 + .../vendor/nikic/php-parser/README.md | 225 + .../vendor/nikic/php-parser/bin/php-parse | 205 + .../vendor/nikic/php-parser/composer.json | 41 + .../php-parser/lib/PhpParser/Builder.php | 13 + .../lib/PhpParser/Builder/ClassConst.php | 148 + .../lib/PhpParser/Builder/Class_.php | 146 + .../lib/PhpParser/Builder/Declaration.php | 43 + .../lib/PhpParser/Builder/EnumCase.php | 85 + .../lib/PhpParser/Builder/Enum_.php | 117 + .../lib/PhpParser/Builder/FunctionLike.php | 73 + .../lib/PhpParser/Builder/Function_.php | 67 + .../lib/PhpParser/Builder/Interface_.php | 93 + .../lib/PhpParser/Builder/Method.php | 146 + .../lib/PhpParser/Builder/Namespace_.php | 45 + .../lib/PhpParser/Builder/Param.php | 168 + .../lib/PhpParser/Builder/Property.php | 161 + .../lib/PhpParser/Builder/TraitUse.php | 64 + .../PhpParser/Builder/TraitUseAdaptation.php | 148 + .../lib/PhpParser/Builder/Trait_.php | 78 + .../php-parser/lib/PhpParser/Builder/Use_.php | 49 + .../lib/PhpParser/BuilderFactory.php | 399 + .../lib/PhpParser/BuilderHelpers.php | 340 + .../php-parser/lib/PhpParser/Comment.php | 239 + .../php-parser/lib/PhpParser/Comment/Doc.php | 7 + .../ConstExprEvaluationException.php | 6 + .../lib/PhpParser/ConstExprEvaluator.php | 229 + .../nikic/php-parser/lib/PhpParser/Error.php | 180 + .../php-parser/lib/PhpParser/ErrorHandler.php | 13 + .../lib/PhpParser/ErrorHandler/Collecting.php | 46 + .../lib/PhpParser/ErrorHandler/Throwing.php | 18 + .../lib/PhpParser/Internal/DiffElem.php | 27 + .../lib/PhpParser/Internal/Differ.php | 164 + .../Internal/PrintableNewAnonClassNode.php | 64 + .../lib/PhpParser/Internal/TokenStream.php | 286 + .../php-parser/lib/PhpParser/JsonDecoder.php | 103 + .../nikic/php-parser/lib/PhpParser/Lexer.php | 560 ++ .../lib/PhpParser/Lexer/Emulative.php | 251 + .../Lexer/TokenEmulator/AttributeEmulator.php | 56 + .../CoaleseEqualTokenEmulator.php | 47 + .../Lexer/TokenEmulator/EnumTokenEmulator.php | 31 + .../TokenEmulator/ExplicitOctalEmulator.php | 44 + .../FlexibleDocStringEmulator.php | 76 + .../Lexer/TokenEmulator/FnTokenEmulator.php | 23 + .../Lexer/TokenEmulator/KeywordEmulator.php | 62 + .../TokenEmulator/MatchTokenEmulator.php | 23 + .../TokenEmulator/NullsafeTokenEmulator.php | 67 + .../NumericLiteralSeparatorEmulator.php | 105 + .../ReadonlyFunctionTokenEmulator.php | 31 + .../TokenEmulator/ReadonlyTokenEmulator.php | 36 + .../Lexer/TokenEmulator/ReverseEmulator.php | 36 + .../Lexer/TokenEmulator/TokenEmulator.php | 25 + .../php-parser/lib/PhpParser/NameContext.php | 285 + .../nikic/php-parser/lib/PhpParser/Node.php | 151 + .../php-parser/lib/PhpParser/Node/Arg.php | 46 + .../lib/PhpParser/Node/Attribute.php | 34 + .../lib/PhpParser/Node/AttributeGroup.php | 29 + .../lib/PhpParser/Node/ComplexType.php | 14 + .../php-parser/lib/PhpParser/Node/Const_.php | 37 + .../php-parser/lib/PhpParser/Node/Expr.php | 9 + .../lib/PhpParser/Node/Expr/ArrayDimFetch.php | 34 + .../lib/PhpParser/Node/Expr/ArrayItem.php | 41 + .../lib/PhpParser/Node/Expr/Array_.php | 34 + .../lib/PhpParser/Node/Expr/ArrowFunction.php | 79 + .../lib/PhpParser/Node/Expr/Assign.php | 34 + .../lib/PhpParser/Node/Expr/AssignOp.php | 30 + .../Node/Expr/AssignOp/BitwiseAnd.php | 12 + .../Node/Expr/AssignOp/BitwiseOr.php | 12 + .../Node/Expr/AssignOp/BitwiseXor.php | 12 + .../PhpParser/Node/Expr/AssignOp/Coalesce.php | 12 + .../PhpParser/Node/Expr/AssignOp/Concat.php | 12 + .../lib/PhpParser/Node/Expr/AssignOp/Div.php | 12 + .../PhpParser/Node/Expr/AssignOp/Minus.php | 12 + .../lib/PhpParser/Node/Expr/AssignOp/Mod.php | 12 + .../lib/PhpParser/Node/Expr/AssignOp/Mul.php | 12 + .../lib/PhpParser/Node/Expr/AssignOp/Plus.php | 12 + .../lib/PhpParser/Node/Expr/AssignOp/Pow.php | 12 + .../Node/Expr/AssignOp/ShiftLeft.php | 12 + .../Node/Expr/AssignOp/ShiftRight.php | 12 + .../lib/PhpParser/Node/Expr/AssignRef.php | 34 + .../lib/PhpParser/Node/Expr/BinaryOp.php | 40 + .../Node/Expr/BinaryOp/BitwiseAnd.php | 16 + .../Node/Expr/BinaryOp/BitwiseOr.php | 16 + .../Node/Expr/BinaryOp/BitwiseXor.php | 16 + .../Node/Expr/BinaryOp/BooleanAnd.php | 16 + .../Node/Expr/BinaryOp/BooleanOr.php | 16 + .../PhpParser/Node/Expr/BinaryOp/Coalesce.php | 16 + .../PhpParser/Node/Expr/BinaryOp/Concat.php | 16 + .../lib/PhpParser/Node/Expr/BinaryOp/Div.php | 16 + .../PhpParser/Node/Expr/BinaryOp/Equal.php | 16 + .../PhpParser/Node/Expr/BinaryOp/Greater.php | 16 + .../Node/Expr/BinaryOp/GreaterOrEqual.php | 16 + .../Node/Expr/BinaryOp/Identical.php | 16 + .../Node/Expr/BinaryOp/LogicalAnd.php | 16 + .../Node/Expr/BinaryOp/LogicalOr.php | 16 + .../Node/Expr/BinaryOp/LogicalXor.php | 16 + .../PhpParser/Node/Expr/BinaryOp/Minus.php | 16 + .../lib/PhpParser/Node/Expr/BinaryOp/Mod.php | 16 + .../lib/PhpParser/Node/Expr/BinaryOp/Mul.php | 16 + .../PhpParser/Node/Expr/BinaryOp/NotEqual.php | 16 + .../Node/Expr/BinaryOp/NotIdentical.php | 16 + .../lib/PhpParser/Node/Expr/BinaryOp/Plus.php | 16 + .../lib/PhpParser/Node/Expr/BinaryOp/Pow.php | 16 + .../Node/Expr/BinaryOp/ShiftLeft.php | 16 + .../Node/Expr/BinaryOp/ShiftRight.php | 16 + .../PhpParser/Node/Expr/BinaryOp/Smaller.php | 16 + .../Node/Expr/BinaryOp/SmallerOrEqual.php | 16 + .../Node/Expr/BinaryOp/Spaceship.php | 16 + .../lib/PhpParser/Node/Expr/BitwiseNot.php | 30 + .../lib/PhpParser/Node/Expr/BooleanNot.php | 30 + .../lib/PhpParser/Node/Expr/CallLike.php | 39 + .../lib/PhpParser/Node/Expr/Cast.php | 26 + .../lib/PhpParser/Node/Expr/Cast/Array_.php | 12 + .../lib/PhpParser/Node/Expr/Cast/Bool_.php | 12 + .../lib/PhpParser/Node/Expr/Cast/Double.php | 17 + .../lib/PhpParser/Node/Expr/Cast/Int_.php | 12 + .../lib/PhpParser/Node/Expr/Cast/Object_.php | 12 + .../lib/PhpParser/Node/Expr/Cast/String_.php | 12 + .../lib/PhpParser/Node/Expr/Cast/Unset_.php | 12 + .../PhpParser/Node/Expr/ClassConstFetch.php | 36 + .../lib/PhpParser/Node/Expr/Clone_.php | 30 + .../lib/PhpParser/Node/Expr/Closure.php | 79 + .../lib/PhpParser/Node/Expr/ClosureUse.php | 34 + .../lib/PhpParser/Node/Expr/ConstFetch.php | 31 + .../lib/PhpParser/Node/Expr/Empty_.php | 30 + .../lib/PhpParser/Node/Expr/Error.php | 31 + .../lib/PhpParser/Node/Expr/ErrorSuppress.php | 30 + .../lib/PhpParser/Node/Expr/Eval_.php | 30 + .../lib/PhpParser/Node/Expr/Exit_.php | 34 + .../lib/PhpParser/Node/Expr/FuncCall.php | 39 + .../lib/PhpParser/Node/Expr/Include_.php | 39 + .../lib/PhpParser/Node/Expr/Instanceof_.php | 35 + .../lib/PhpParser/Node/Expr/Isset_.php | 30 + .../lib/PhpParser/Node/Expr/List_.php | 30 + .../lib/PhpParser/Node/Expr/Match_.php | 31 + .../lib/PhpParser/Node/Expr/MethodCall.php | 45 + .../lib/PhpParser/Node/Expr/New_.php | 41 + .../Node/Expr/NullsafeMethodCall.php | 45 + .../Node/Expr/NullsafePropertyFetch.php | 35 + .../lib/PhpParser/Node/Expr/PostDec.php | 30 + .../lib/PhpParser/Node/Expr/PostInc.php | 30 + .../lib/PhpParser/Node/Expr/PreDec.php | 30 + .../lib/PhpParser/Node/Expr/PreInc.php | 30 + .../lib/PhpParser/Node/Expr/Print_.php | 30 + .../lib/PhpParser/Node/Expr/PropertyFetch.php | 35 + .../lib/PhpParser/Node/Expr/ShellExec.php | 30 + .../lib/PhpParser/Node/Expr/StaticCall.php | 46 + .../Node/Expr/StaticPropertyFetch.php | 36 + .../lib/PhpParser/Node/Expr/Ternary.php | 38 + .../lib/PhpParser/Node/Expr/Throw_.php | 30 + .../lib/PhpParser/Node/Expr/UnaryMinus.php | 30 + .../lib/PhpParser/Node/Expr/UnaryPlus.php | 30 + .../lib/PhpParser/Node/Expr/Variable.php | 30 + .../lib/PhpParser/Node/Expr/YieldFrom.php | 30 + .../lib/PhpParser/Node/Expr/Yield_.php | 34 + .../lib/PhpParser/Node/FunctionLike.php | 43 + .../lib/PhpParser/Node/Identifier.php | 75 + .../lib/PhpParser/Node/IntersectionType.php | 30 + .../lib/PhpParser/Node/MatchArm.php | 31 + .../php-parser/lib/PhpParser/Node/Name.php | 254 + .../PhpParser/Node/Name/FullyQualified.php | 50 + .../lib/PhpParser/Node/Name/Relative.php | 50 + .../lib/PhpParser/Node/NullableType.php | 28 + .../php-parser/lib/PhpParser/Node/Param.php | 60 + .../php-parser/lib/PhpParser/Node/Scalar.php | 7 + .../lib/PhpParser/Node/Scalar/DNumber.php | 77 + .../lib/PhpParser/Node/Scalar/Encapsed.php | 31 + .../Node/Scalar/EncapsedStringPart.php | 30 + .../lib/PhpParser/Node/Scalar/LNumber.php | 80 + .../lib/PhpParser/Node/Scalar/MagicConst.php | 28 + .../Node/Scalar/MagicConst/Class_.php | 16 + .../PhpParser/Node/Scalar/MagicConst/Dir.php | 16 + .../PhpParser/Node/Scalar/MagicConst/File.php | 16 + .../Node/Scalar/MagicConst/Function_.php | 16 + .../PhpParser/Node/Scalar/MagicConst/Line.php | 16 + .../Node/Scalar/MagicConst/Method.php | 16 + .../Node/Scalar/MagicConst/Namespace_.php | 16 + .../Node/Scalar/MagicConst/Trait_.php | 16 + .../lib/PhpParser/Node/Scalar/String_.php | 157 + .../php-parser/lib/PhpParser/Node/Stmt.php | 9 + .../lib/PhpParser/Node/Stmt/Break_.php | 30 + .../lib/PhpParser/Node/Stmt/Case_.php | 34 + .../lib/PhpParser/Node/Stmt/Catch_.php | 41 + .../lib/PhpParser/Node/Stmt/ClassConst.php | 85 + .../lib/PhpParser/Node/Stmt/ClassLike.php | 109 + .../lib/PhpParser/Node/Stmt/ClassMethod.php | 161 + .../lib/PhpParser/Node/Stmt/Class_.php | 137 + .../lib/PhpParser/Node/Stmt/Const_.php | 30 + .../lib/PhpParser/Node/Stmt/Continue_.php | 30 + .../PhpParser/Node/Stmt/DeclareDeclare.php | 34 + .../lib/PhpParser/Node/Stmt/Declare_.php | 34 + .../lib/PhpParser/Node/Stmt/Do_.php | 34 + .../lib/PhpParser/Node/Stmt/Echo_.php | 30 + .../lib/PhpParser/Node/Stmt/ElseIf_.php | 34 + .../lib/PhpParser/Node/Stmt/Else_.php | 30 + .../lib/PhpParser/Node/Stmt/EnumCase.php | 37 + .../lib/PhpParser/Node/Stmt/Enum_.php | 40 + .../lib/PhpParser/Node/Stmt/Expression.php | 33 + .../lib/PhpParser/Node/Stmt/Finally_.php | 30 + .../lib/PhpParser/Node/Stmt/For_.php | 43 + .../lib/PhpParser/Node/Stmt/Foreach_.php | 47 + .../lib/PhpParser/Node/Stmt/Function_.php | 77 + .../lib/PhpParser/Node/Stmt/Global_.php | 30 + .../lib/PhpParser/Node/Stmt/Goto_.php | 31 + .../lib/PhpParser/Node/Stmt/GroupUse.php | 39 + .../lib/PhpParser/Node/Stmt/HaltCompiler.php | 30 + .../lib/PhpParser/Node/Stmt/If_.php | 43 + .../lib/PhpParser/Node/Stmt/InlineHTML.php | 30 + .../lib/PhpParser/Node/Stmt/Interface_.php | 37 + .../lib/PhpParser/Node/Stmt/Label.php | 31 + .../lib/PhpParser/Node/Stmt/Namespace_.php | 38 + .../lib/PhpParser/Node/Stmt/Nop.php | 17 + .../lib/PhpParser/Node/Stmt/Property.php | 91 + .../PhpParser/Node/Stmt/PropertyProperty.php | 34 + .../lib/PhpParser/Node/Stmt/Return_.php | 30 + .../lib/PhpParser/Node/Stmt/StaticVar.php | 37 + .../lib/PhpParser/Node/Stmt/Static_.php | 30 + .../lib/PhpParser/Node/Stmt/Switch_.php | 34 + .../lib/PhpParser/Node/Stmt/Throw_.php | 30 + .../lib/PhpParser/Node/Stmt/TraitUse.php | 34 + .../Node/Stmt/TraitUseAdaptation.php | 13 + .../Node/Stmt/TraitUseAdaptation/Alias.php | 38 + .../Stmt/TraitUseAdaptation/Precedence.php | 34 + .../lib/PhpParser/Node/Stmt/Trait_.php | 32 + .../lib/PhpParser/Node/Stmt/TryCatch.php | 38 + .../lib/PhpParser/Node/Stmt/Unset_.php | 30 + .../lib/PhpParser/Node/Stmt/UseUse.php | 52 + .../lib/PhpParser/Node/Stmt/Use_.php | 47 + .../lib/PhpParser/Node/Stmt/While_.php | 34 + .../lib/PhpParser/Node/UnionType.php | 28 + .../lib/PhpParser/Node/VarLikeIdentifier.php | 17 + .../PhpParser/Node/VariadicPlaceholder.php | 27 + .../php-parser/lib/PhpParser/NodeAbstract.php | 178 + .../php-parser/lib/PhpParser/NodeDumper.php | 206 + .../php-parser/lib/PhpParser/NodeFinder.php | 81 + .../lib/PhpParser/NodeTraverser.php | 291 + .../lib/PhpParser/NodeTraverserInterface.php | 29 + .../php-parser/lib/PhpParser/NodeVisitor.php | 72 + .../PhpParser/NodeVisitor/CloningVisitor.php | 20 + .../PhpParser/NodeVisitor/FindingVisitor.php | 48 + .../NodeVisitor/FirstFindingVisitor.php | 50 + .../PhpParser/NodeVisitor/NameResolver.php | 260 + .../NodeVisitor/NodeConnectingVisitor.php | 52 + .../NodeVisitor/ParentConnectingVisitor.php | 41 + .../lib/PhpParser/NodeVisitorAbstract.php | 25 + .../nikic/php-parser/lib/PhpParser/Parser.php | 18 + .../lib/PhpParser/Parser/Multiple.php | 55 + .../php-parser/lib/PhpParser/Parser/Php5.php | 2682 ++++++ .../php-parser/lib/PhpParser/Parser/Php7.php | 2899 +++++++ .../lib/PhpParser/Parser/Tokens.php | 148 + .../lib/PhpParser/ParserAbstract.php | 1060 +++ .../lib/PhpParser/ParserFactory.php | 76 + .../lib/PhpParser/PrettyPrinter/Standard.php | 1126 +++ .../lib/PhpParser/PrettyPrinterAbstract.php | 1576 ++++ .../phar-io/manifest/.github/FUNDING.yml | 3 + .../phar-io/manifest/.github/workflows/ci.yml | 86 + .../phar-io/manifest/.php-cs-fixer.dist.php | 223 + .../vendor/phar-io/manifest/CHANGELOG.md | 45 + .../vendor/phar-io/manifest/LICENSE | 31 + .../vendor/phar-io/manifest/README.md | 178 + .../vendor/phar-io/manifest/composer.json | 43 + .../vendor/phar-io/manifest/composer.lock | 76 + .../vendor/phar-io/manifest/manifest.xsd | 116 + .../manifest/src/ManifestDocumentMapper.php | 151 + .../phar-io/manifest/src/ManifestLoader.php | 47 + .../manifest/src/ManifestSerializer.php | 172 + .../exceptions/ElementCollectionException.php | 16 + .../manifest/src/exceptions/Exception.php | 16 + .../InvalidApplicationNameException.php | 17 + .../src/exceptions/InvalidEmailException.php | 16 + .../src/exceptions/InvalidUrlException.php | 16 + .../exceptions/ManifestDocumentException.php | 16 + .../ManifestDocumentLoadingException.php | 47 + .../ManifestDocumentMapperException.php | 16 + .../exceptions/ManifestElementException.php | 16 + .../exceptions/ManifestLoaderException.php | 14 + .../exceptions/NoEmailAddressException.php | 16 + .../manifest/src/values/Application.php | 17 + .../manifest/src/values/ApplicationName.php | 41 + .../phar-io/manifest/src/values/Author.php | 57 + .../manifest/src/values/AuthorCollection.php | 40 + .../src/values/AuthorCollectionIterator.php | 47 + .../manifest/src/values/BundledComponent.php | 34 + .../src/values/BundledComponentCollection.php | 40 + .../BundledComponentCollectionIterator.php | 47 + .../src/values/CopyrightInformation.php | 32 + .../phar-io/manifest/src/values/Email.php | 35 + .../phar-io/manifest/src/values/Extension.php | 47 + .../phar-io/manifest/src/values/Library.php | 17 + .../phar-io/manifest/src/values/License.php | 32 + .../phar-io/manifest/src/values/Manifest.php | 93 + .../src/values/PhpExtensionRequirement.php | 24 + .../src/values/PhpVersionRequirement.php | 26 + .../manifest/src/values/Requirement.php | 14 + .../src/values/RequirementCollection.php | 40 + .../values/RequirementCollectionIterator.php | 47 + .../phar-io/manifest/src/values/Type.php | 42 + .../phar-io/manifest/src/values/Url.php | 38 + .../manifest/src/xml/AuthorElement.php | 25 + .../src/xml/AuthorElementCollection.php | 19 + .../manifest/src/xml/BundlesElement.php | 19 + .../manifest/src/xml/ComponentElement.php | 21 + .../src/xml/ComponentElementCollection.php | 19 + .../manifest/src/xml/ContainsElement.php | 31 + .../manifest/src/xml/CopyrightElement.php | 25 + .../manifest/src/xml/ElementCollection.php | 68 + .../phar-io/manifest/src/xml/ExtElement.php | 17 + .../manifest/src/xml/ExtElementCollection.php | 19 + .../manifest/src/xml/ExtensionElement.php | 21 + .../manifest/src/xml/LicenseElement.php | 21 + .../manifest/src/xml/ManifestDocument.php | 115 + .../manifest/src/xml/ManifestElement.php | 72 + .../phar-io/manifest/src/xml/PhpElement.php | 27 + .../manifest/src/xml/RequiresElement.php | 19 + .../PhpdocSingleLineVarFixer.php | 72 + .../manifest/tools/php-cs-fixer.d/header.txt | 6 + .../vendor/phar-io/version/CHANGELOG.md | 142 + .../vendor/phar-io/version/LICENSE | 29 + .../vendor/phar-io/version/README.md | 61 + .../vendor/phar-io/version/composer.json | 34 + .../phar-io/version/src/BuildMetaData.php | 28 + .../phar-io/version/src/PreReleaseSuffix.php | 82 + .../vendor/phar-io/version/src/Version.php | 208 + .../version/src/VersionConstraintParser.php | 115 + .../version/src/VersionConstraintValue.php | 88 + .../phar-io/version/src/VersionNumber.php | 28 + .../constraints/AbstractVersionConstraint.php | 23 + .../constraints/AndVersionConstraintGroup.php | 34 + .../src/constraints/AnyVersionConstraint.php | 20 + .../constraints/ExactVersionConstraint.php | 22 + .../GreaterThanOrEqualToVersionConstraint.php | 26 + .../constraints/OrVersionConstraintGroup.php | 35 + ...SpecificMajorAndMinorVersionConstraint.php | 33 + .../SpecificMajorVersionConstraint.php | 25 + .../src/constraints/VersionConstraint.php | 16 + .../version/src/exceptions/Exception.php | 15 + .../InvalidPreReleaseSuffixException.php | 5 + .../exceptions/InvalidVersionException.php | 5 + .../exceptions/NoBuildMetaDataException.php | 5 + .../NoPreReleaseSuffixException.php | 5 + .../UnsupportedVersionConstraintException.php | 13 + .../phpstan/extension-installer/LICENSE | 21 + .../phpstan/extension-installer/README.md | 93 + .../phpstan/extension-installer/composer.json | 33 + .../src/GeneratedConfig.php | 39 + .../extension-installer/src/Plugin.php | 228 + .../vendor/phpstan/phpdoc-parser/LICENSE | 21 + .../vendor/phpstan/phpdoc-parser/README.md | 121 + .../phpstan/phpdoc-parser/composer.json | 44 + .../src/Ast/AbstractNodeVisitor.php | 34 + .../phpdoc-parser/src/Ast/Attribute.php | 16 + .../Ast/ConstExpr/ConstExprArrayItemNode.php | 36 + .../src/Ast/ConstExpr/ConstExprArrayNode.php | 30 + .../src/Ast/ConstExpr/ConstExprFalseNode.php | 17 + .../src/Ast/ConstExpr/ConstExprFloatNode.php | 26 + .../Ast/ConstExpr/ConstExprIntegerNode.php | 26 + .../src/Ast/ConstExpr/ConstExprNode.php | 10 + .../src/Ast/ConstExpr/ConstExprNullNode.php | 17 + .../src/Ast/ConstExpr/ConstExprStringNode.php | 26 + .../src/Ast/ConstExpr/ConstExprTrueNode.php | 17 + .../src/Ast/ConstExpr/ConstFetchNode.php | 35 + .../ConstExpr/DoctrineConstExprStringNode.php | 42 + .../QuoteAwareConstExprStringNode.php | 78 + .../phpstan/phpdoc-parser/src/Ast/Node.php | 22 + .../phpdoc-parser/src/Ast/NodeAttributes.php | 38 + .../phpdoc-parser/src/Ast/NodeTraverser.php | 312 + .../phpdoc-parser/src/Ast/NodeVisitor.php | 87 + .../src/Ast/NodeVisitor/CloningVisitor.php | 20 + .../Ast/PhpDoc/AssertTagMethodValueNode.php | 50 + .../Ast/PhpDoc/AssertTagPropertyValueNode.php | 50 + .../src/Ast/PhpDoc/AssertTagValueNode.php | 46 + .../src/Ast/PhpDoc/DeprecatedTagValueNode.php | 27 + .../PhpDoc/Doctrine/DoctrineAnnotation.php | 35 + .../Ast/PhpDoc/Doctrine/DoctrineArgument.php | 43 + .../src/Ast/PhpDoc/Doctrine/DoctrineArray.php | 32 + .../Ast/PhpDoc/Doctrine/DoctrineArrayItem.php | 47 + .../PhpDoc/Doctrine/DoctrineTagValueNode.php | 36 + .../src/Ast/PhpDoc/ExtendsTagValueNode.php | 32 + .../src/Ast/PhpDoc/GenericTagValueNode.php | 26 + .../src/Ast/PhpDoc/ImplementsTagValueNode.php | 32 + .../src/Ast/PhpDoc/InvalidTagValueNode.php | 53 + .../src/Ast/PhpDoc/MethodTagValueNode.php | 58 + .../PhpDoc/MethodTagValueParameterNode.php | 49 + .../src/Ast/PhpDoc/MixinTagValueNode.php | 32 + .../PhpDoc/ParamClosureThisTagValueNode.php | 35 + ...ImmediatelyInvokedCallableTagValueNode.php | 30 + .../ParamLaterInvokedCallableTagValueNode.php | 30 + .../src/Ast/PhpDoc/ParamOutTagValueNode.php | 35 + .../src/Ast/PhpDoc/ParamTagValueNode.php | 46 + .../src/Ast/PhpDoc/PhpDocChildNode.php | 10 + .../src/Ast/PhpDoc/PhpDocNode.php | 450 + .../src/Ast/PhpDoc/PhpDocTagNode.php | 36 + .../src/Ast/PhpDoc/PhpDocTagValueNode.php | 10 + .../src/Ast/PhpDoc/PhpDocTextNode.php | 26 + .../src/Ast/PhpDoc/PropertyTagValueNode.php | 36 + ...PureUnlessCallableIsImpureTagValueNode.php | 30 + .../Ast/PhpDoc/RequireExtendsTagValueNode.php | 32 + .../PhpDoc/RequireImplementsTagValueNode.php | 32 + .../src/Ast/PhpDoc/ReturnTagValueNode.php | 32 + .../src/Ast/PhpDoc/SelfOutTagValueNode.php | 32 + .../src/Ast/PhpDoc/TemplateTagValueNode.php | 50 + .../src/Ast/PhpDoc/ThrowsTagValueNode.php | 32 + .../PhpDoc/TypeAliasImportTagValueNode.php | 38 + .../src/Ast/PhpDoc/TypeAliasTagValueNode.php | 32 + .../Ast/PhpDoc/TypelessParamTagValueNode.php | 41 + .../src/Ast/PhpDoc/UsesTagValueNode.php | 32 + .../src/Ast/PhpDoc/VarTagValueNode.php | 36 + .../src/Ast/Type/ArrayShapeItemNode.php | 49 + .../src/Ast/Type/ArrayShapeNode.php | 59 + .../Ast/Type/ArrayShapeUnsealedTypeNode.php | 34 + .../src/Ast/Type/ArrayTypeNode.php | 34 + .../src/Ast/Type/CallableTypeNode.php | 52 + .../Ast/Type/CallableTypeParameterNode.php | 48 + .../Type/ConditionalTypeForParameterNode.php | 49 + .../src/Ast/Type/ConditionalTypeNode.php | 49 + .../src/Ast/Type/ConstTypeNode.php | 26 + .../src/Ast/Type/GenericTypeNode.php | 58 + .../src/Ast/Type/IdentifierTypeNode.php | 26 + .../src/Ast/Type/IntersectionTypeNode.php | 37 + .../src/Ast/Type/InvalidTypeNode.php | 38 + .../src/Ast/Type/NullableTypeNode.php | 26 + .../src/Ast/Type/ObjectShapeItemNode.php | 48 + .../src/Ast/Type/ObjectShapeNode.php | 31 + .../src/Ast/Type/OffsetAccessTypeNode.php | 36 + .../src/Ast/Type/ThisTypeNode.php | 17 + .../phpdoc-parser/src/Ast/Type/TypeNode.php | 10 + .../src/Ast/Type/UnionTypeNode.php | 37 + .../phpstan/phpdoc-parser/src/Lexer/Lexer.php | 198 + .../src/Parser/ConstExprParser.php | 333 + .../src/Parser/ParserException.php | 106 + .../phpdoc-parser/src/Parser/PhpDocParser.php | 1301 +++ .../src/Parser/StringUnescaper.php | 100 + .../src/Parser/TokenIterator.php | 383 + .../phpdoc-parser/src/Parser/TypeParser.php | 1110 +++ .../phpdoc-parser/src/Printer/DiffElem.php | 44 + .../phpdoc-parser/src/Printer/Differ.php | 196 + .../phpdoc-parser/src/Printer/Printer.php | 870 ++ .../phpstan/phpstan-mockery/.editorconfig | 27 + .../vendor/phpstan/phpstan-mockery/LICENSE | 21 + .../vendor/phpstan/phpstan-mockery/README.md | 36 + .../phpstan/phpstan-mockery/composer.json | 45 + .../phpstan/phpstan-mockery/extension.neon | 58 + .../phpstan-mockery/phpstan-baseline.neon | 13 + .../PhpDoc/TypeNodeResolverExtension.php | 54 + .../Reflection/StubMethodReflection.php | 111 + .../StubMethodsClassReflectionExtension.php | 39 + .../src/Mockery/Type/Allows.php | 8 + .../src/Mockery/Type/Expects.php | 8 + ...ockDynamicNamedMockReturnTypeExtension.php | 78 + .../Type/MockDynamicReturnTypeExtension.php | 79 + .../Type/StubDynamicReturnTypeExtension.php | 53 + .../phpstan-mockery/stubs/MockInterface.stub | 71 + .../vendor/phpstan/phpstan/LICENSE | 21 + .../vendor/phpstan/phpstan/README.md | 108 + .../vendor/phpstan/phpstan/bootstrap.php | 135 + .../vendor/phpstan/phpstan/composer.json | 26 + .../phpstan/phpstan/conf/bleedingEdge.neon | 2 + .../vendor/phpstan/phpstan/phpstan | 8 + .../vendor/phpstan/phpstan/phpstan.phar | Bin 0 -> 23697620 bytes .../vendor/phpstan/phpstan/phpstan.phar.asc | 16 + .../php-code-coverage/ChangeLog-10.1.md | 132 + .../vendor/phpunit/php-code-coverage/LICENSE | 29 + .../phpunit/php-code-coverage/README.md | 55 + .../phpunit/php-code-coverage/SECURITY.md | 30 + .../phpunit/php-code-coverage/composer.json | 69 + .../php-code-coverage/src/CodeCoverage.php | 631 ++ .../src/Data/ProcessedCodeCoverageData.php | 278 + .../src/Data/RawCodeCoverageData.php | 281 + .../php-code-coverage/src/Driver/Driver.php | 128 + .../src/Driver/PcovDriver.php | 80 + .../php-code-coverage/src/Driver/Selector.php | 62 + .../src/Driver/XdebugDriver.php | 162 + ...chAndPathCoverageNotSupportedException.php | 16 + ...DeadCodeDetectionNotSupportedException.php | 16 + .../DirectoryCouldNotBeCreatedException.php | 17 + .../src/Exception/Exception.php | 16 + .../FileCouldNotBeWrittenException.php | 16 + .../Exception/InvalidArgumentException.php | 14 + ...NoCodeCoverageDriverAvailableException.php | 20 + ...hPathCoverageSupportAvailableException.php | 20 + .../src/Exception/ParserException.php | 16 + .../PathExistsButIsNotDirectoryException.php | 22 + .../Exception/PcovNotAvailableException.php | 21 + .../src/Exception/ReflectionException.php | 16 + .../ReportAlreadyFinalizedException.php | 20 + ...ticAnalysisCacheNotConfiguredException.php | 16 + .../src/Exception/TestIdMissingException.php | 20 + .../UnintentionallyCoveredCodeException.php | 49 + .../WriteOperationFailedException.php | 22 + .../Exception/XdebugNotAvailableException.php | 21 + .../Exception/XdebugNotEnabledException.php | 21 + .../src/Exception/XmlException.php | 16 + .../phpunit/php-code-coverage/src/Filter.php | 128 + .../src/Node/AbstractNode.php | 250 + .../php-code-coverage/src/Node/Builder.php | 269 + .../php-code-coverage/src/Node/CrapIndex.php | 43 + .../php-code-coverage/src/Node/Directory.php | 370 + .../php-code-coverage/src/Node/File.php | 688 ++ .../php-code-coverage/src/Node/Iterator.php | 87 + .../php-code-coverage/src/Report/Clover.php | 258 + .../src/Report/Cobertura.php | 309 + .../php-code-coverage/src/Report/Crap4j.php | 153 + .../src/Report/Html/Colors.php | 66 + .../src/Report/Html/CustomCssFile.php | 50 + .../src/Report/Html/Facade.php | 153 + .../src/Report/Html/Renderer.php | 286 + .../src/Report/Html/Renderer/Dashboard.php | 298 + .../src/Report/Html/Renderer/Directory.php | 123 + .../src/Report/Html/Renderer/File.php | 1130 +++ .../Html/Renderer/Template/branches.html.dist | 9 + .../Renderer/Template/coverage_bar.html.dist | 5 + .../Template/coverage_bar_branch.html.dist | 5 + .../Renderer/Template/css/bootstrap.min.css | 7 + .../Html/Renderer/Template/css/custom.css | 0 .../Html/Renderer/Template/css/nv.d3.min.css | 1 + .../Html/Renderer/Template/css/octicons.css | 5 + .../Html/Renderer/Template/css/style.css | 158 + .../Renderer/Template/dashboard.html.dist | 281 + .../Template/dashboard_branch.html.dist | 281 + .../Renderer/Template/directory.html.dist | 60 + .../Template/directory_branch.html.dist | 62 + .../Template/directory_item.html.dist | 13 + .../Template/directory_item_branch.html.dist | 19 + .../Html/Renderer/Template/file.html.dist | 65 + .../Renderer/Template/file_branch.html.dist | 67 + .../Renderer/Template/file_item.html.dist | 14 + .../Template/file_item_branch.html.dist | 20 + .../Renderer/Template/icons/file-code.svg | 1 + .../Template/icons/file-directory.svg | 1 + .../Renderer/Template/js/bootstrap.min.js | 7 + .../Html/Renderer/Template/js/d3.min.js | 5 + .../Report/Html/Renderer/Template/js/file.js | 62 + .../Html/Renderer/Template/js/jquery.min.js | 2 + .../Html/Renderer/Template/js/nv.d3.min.js | 8 + .../Html/Renderer/Template/js/popper.min.js | 5 + .../Html/Renderer/Template/line.html.dist | 1 + .../Html/Renderer/Template/lines.html.dist | 5 + .../Renderer/Template/method_item.html.dist | 12 + .../Template/method_item_branch.html.dist | 18 + .../Html/Renderer/Template/paths.html.dist | 9 + .../php-code-coverage/src/Report/PHP.php | 41 + .../php-code-coverage/src/Report/Text.php | 315 + .../src/Report/Thresholds.php | 56 + .../src/Report/Xml/BuildInformation.php | 79 + .../src/Report/Xml/Coverage.php | 63 + .../src/Report/Xml/Directory.php | 17 + .../src/Report/Xml/Facade.php | 304 + .../php-code-coverage/src/Report/Xml/File.php | 80 + .../src/Report/Xml/Method.php | 58 + .../php-code-coverage/src/Report/Xml/Node.php | 86 + .../src/Report/Xml/Project.php | 90 + .../src/Report/Xml/Report.php | 99 + .../src/Report/Xml/Source.php | 41 + .../src/Report/Xml/Tests.php | 44 + .../src/Report/Xml/Totals.php | 123 + .../php-code-coverage/src/Report/Xml/Unit.php | 75 + .../src/StaticAnalysis/CacheWarmer.php | 32 + .../StaticAnalysis/CachingFileAnalyser.php | 182 + .../StaticAnalysis/CodeUnitFindingVisitor.php | 360 + .../ExecutableLinesFindingVisitor.php | 413 + .../src/StaticAnalysis/FileAnalyser.php | 60 + .../IgnoredLinesFindingVisitor.php | 121 + .../StaticAnalysis/ParsingFileAnalyser.php | 247 + .../php-code-coverage/src/TestSize/Known.php | 26 + .../php-code-coverage/src/TestSize/Large.php | 34 + .../php-code-coverage/src/TestSize/Medium.php | 34 + .../php-code-coverage/src/TestSize/Small.php | 34 + .../src/TestSize/TestSize.php | 78 + .../src/TestSize/Unknown.php | 29 + .../src/TestStatus/Failure.php | 29 + .../src/TestStatus/Known.php | 24 + .../src/TestStatus/Success.php | 29 + .../src/TestStatus/TestStatus.php | 65 + .../src/TestStatus/Unknown.php | 29 + .../php-code-coverage/src/Util/Filesystem.php | 37 + .../php-code-coverage/src/Util/Percentage.php | 59 + .../phpunit/php-code-coverage/src/Version.php | 27 + .../phpunit/php-file-iterator/ChangeLog.md | 174 + .../vendor/phpunit/php-file-iterator/LICENSE | 29 + .../phpunit/php-file-iterator/README.md | 17 + .../phpunit/php-file-iterator/SECURITY.md | 30 + .../phpunit/php-file-iterator/composer.json | 46 + .../php-file-iterator/src/ExcludeIterator.php | 80 + .../phpunit/php-file-iterator/src/Facade.php | 52 + .../phpunit/php-file-iterator/src/Factory.php | 106 + .../php-file-iterator/src/Iterator.php | 114 + .../phpunit/php-invoker/.psalm/baseline.xml | 8 + .../phpunit/php-invoker/.psalm/config.xml | 15 + .../vendor/phpunit/php-invoker/ChangeLog.md | 55 + .../vendor/phpunit/php-invoker/LICENSE | 29 + .../vendor/phpunit/php-invoker/README.md | 20 + .../vendor/phpunit/php-invoker/SECURITY.md | 9 + .../vendor/phpunit/php-invoker/composer.json | 54 + .../phpunit/php-invoker/src/Invoker.php | 67 + .../php-invoker/src/exceptions/Exception.php | 16 + ...cessControlExtensionNotLoadedException.php | 16 + .../src/exceptions/TimeoutException.php | 16 + .../phpunit/php-text-template/ChangeLog.md | 57 + .../vendor/phpunit/php-text-template/LICENSE | 29 + .../phpunit/php-text-template/README.md | 17 + .../phpunit/php-text-template/SECURITY.md | 30 + .../phpunit/php-text-template/composer.json | 45 + .../php-text-template/src/Template.php | 108 + .../src/exceptions/Exception.php | 16 + .../exceptions/InvalidArgumentException.php | 14 + .../src/exceptions/RuntimeException.php | 16 + .../vendor/phpunit/php-timer/ChangeLog.md | 145 + .../vendor/phpunit/php-timer/LICENSE | 29 + .../vendor/phpunit/php-timer/README.md | 106 + .../vendor/phpunit/php-timer/SECURITY.md | 9 + .../vendor/phpunit/php-timer/composer.json | 45 + .../vendor/phpunit/php-timer/src/Duration.php | 90 + .../php-timer/src/ResourceUsageFormatter.php | 73 + .../vendor/phpunit/php-timer/src/Timer.php | 40 + .../php-timer/src/exceptions/Exception.php | 16 + .../src/exceptions/NoActiveTimerException.php | 16 + ...nceStartOfRequestNotAvailableException.php | 16 + .../vendor/phpunit/phpunit/ChangeLog-10.5.md | 387 + .../vendor/phpunit/phpunit/DEPRECATIONS.md | 92 + .../vendor/phpunit/phpunit/LICENSE | 29 + .../vendor/phpunit/phpunit/README.md | 34 + .../vendor/phpunit/phpunit/SECURITY.md | 33 + .../vendor/phpunit/phpunit/composer.json | 94 + .../vendor/phpunit/phpunit/composer.lock | 1553 ++++ .../vendor/phpunit/phpunit/phpunit | 104 + .../vendor/phpunit/phpunit/phpunit.xsd | 323 + .../vendor/phpunit/phpunit/schema/10.0.xsd | 284 + .../vendor/phpunit/phpunit/schema/10.1.xsd | 312 + .../vendor/phpunit/phpunit/schema/10.2.xsd | 319 + .../vendor/phpunit/phpunit/schema/10.3.xsd | 321 + .../vendor/phpunit/phpunit/schema/10.4.xsd | 322 + .../vendor/phpunit/phpunit/schema/8.5.xsd | 319 + .../vendor/phpunit/phpunit/schema/9.0.xsd | 315 + .../vendor/phpunit/phpunit/schema/9.1.xsd | 317 + .../vendor/phpunit/phpunit/schema/9.2.xsd | 317 + .../vendor/phpunit/phpunit/schema/9.3.xsd | 327 + .../vendor/phpunit/phpunit/schema/9.4.xsd | 328 + .../vendor/phpunit/phpunit/schema/9.5.xsd | 330 + .../Event/Dispatcher/CollectingDispatcher.php | 39 + .../Event/Dispatcher/DeferringDispatcher.php | 60 + .../src/Event/Dispatcher/DirectDispatcher.php | 139 + .../src/Event/Dispatcher/Dispatcher.php | 23 + .../Dispatcher/SubscribableDispatcher.php | 25 + .../src/Event/Emitter/DispatchingEmitter.php | 1230 +++ .../phpunit/src/Event/Emitter/Emitter.php | 310 + .../src/Event/Events/Application/Finished.php | 49 + .../Events/Application/FinishedSubscriber.php | 20 + .../src/Event/Events/Application/Started.php | 50 + .../Events/Application/StartedSubscriber.php | 20 + .../phpunit/src/Event/Events/Event.php | 20 + .../src/Event/Events/EventCollection.php | 62 + .../Event/Events/EventCollectionIterator.php | 57 + .../Events/Test/Assertion/AssertionFailed.php | 76 + .../Assertion/AssertionFailedSubscriber.php | 22 + .../Test/Assertion/AssertionSucceeded.php | 76 + .../AssertionSucceededSubscriber.php | 22 + .../Events/Test/ComparatorRegistered.php | 59 + .../Test/ComparatorRegisteredSubscriber.php | 20 + .../HookMethod/AfterLastTestMethodCalled.php | 68 + .../AfterLastTestMethodCalledSubscriber.php | 20 + .../AfterLastTestMethodFinished.php | 82 + .../AfterLastTestMethodFinishedSubscriber.php | 20 + .../Test/HookMethod/AfterTestMethodCalled.php | 68 + .../AfterTestMethodCalledSubscriber.php | 20 + .../HookMethod/AfterTestMethodFinished.php | 82 + .../AfterTestMethodFinishedSubscriber.php | 20 + .../BeforeFirstTestMethodCalled.php | 68 + .../BeforeFirstTestMethodCalledSubscriber.php | 20 + .../BeforeFirstTestMethodErrored.php | 84 + ...BeforeFirstTestMethodErroredSubscriber.php | 20 + .../BeforeFirstTestMethodFinished.php | 82 + ...eforeFirstTestMethodFinishedSubscriber.php | 20 + .../HookMethod/BeforeTestMethodCalled.php | 68 + .../BeforeTestMethodCalledSubscriber.php | 20 + .../HookMethod/BeforeTestMethodFinished.php | 82 + .../BeforeTestMethodFinishedSubscriber.php | 20 + .../Test/HookMethod/PostConditionCalled.php | 68 + .../PostConditionCalledSubscriber.php | 20 + .../Test/HookMethod/PostConditionFinished.php | 82 + .../PostConditionFinishedSubscriber.php | 20 + .../Test/HookMethod/PreConditionCalled.php | 68 + .../PreConditionCalledSubscriber.php | 20 + .../Test/HookMethod/PreConditionFinished.php | 82 + .../PreConditionFinishedSubscriber.php | 20 + .../Events/Test/Issue/ConsideredRisky.php | 70 + .../Test/Issue/ConsideredRiskySubscriber.php | 20 + .../Test/Issue/DeprecationTriggered.php | 137 + .../Issue/DeprecationTriggeredSubscriber.php | 20 + .../Events/Test/Issue/ErrorTriggered.php | 113 + .../Test/Issue/ErrorTriggeredSubscriber.php | 20 + .../Events/Test/Issue/NoticeTriggered.php | 128 + .../Test/Issue/NoticeTriggeredSubscriber.php | 20 + .../Test/Issue/PhpDeprecationTriggered.php | 137 + .../PhpDeprecationTriggeredSubscriber.php | 20 + .../Events/Test/Issue/PhpNoticeTriggered.php | 128 + .../Issue/PhpNoticeTriggeredSubscriber.php | 20 + .../Events/Test/Issue/PhpWarningTriggered.php | 128 + .../Issue/PhpWarningTriggeredSubscriber.php | 20 + .../Issue/PhpunitDeprecationTriggered.php | 75 + .../PhpunitDeprecationTriggeredSubscriber.php | 20 + .../Test/Issue/PhpunitErrorTriggered.php | 76 + .../Issue/PhpunitErrorTriggeredSubscriber.php | 20 + .../Test/Issue/PhpunitWarningTriggered.php | 75 + .../PhpunitWarningTriggeredSubscriber.php | 20 + .../Events/Test/Issue/WarningTriggered.php | 128 + .../Test/Issue/WarningTriggeredSubscriber.php | 20 + .../Lifecycle/DataProviderMethodCalled.php | 60 + .../DataProviderMethodCalledSubscriber.php | 20 + .../Lifecycle/DataProviderMethodFinished.php | 77 + .../DataProviderMethodFinishedSubscriber.php | 20 + .../Event/Events/Test/Lifecycle/Finished.php | 57 + .../Test/Lifecycle/FinishedSubscriber.php | 20 + .../Test/Lifecycle/PreparationFailed.php | 50 + .../Lifecycle/PreparationFailedSubscriber.php | 20 + .../Test/Lifecycle/PreparationStarted.php | 50 + .../PreparationStartedSubscriber.php | 20 + .../Event/Events/Test/Lifecycle/Prepared.php | 50 + .../Test/Lifecycle/PreparedSubscriber.php | 20 + .../src/Event/Events/Test/Outcome/Errored.php | 67 + .../Events/Test/Outcome/ErroredSubscriber.php | 20 + .../src/Event/Events/Test/Outcome/Failed.php | 90 + .../Events/Test/Outcome/FailedSubscriber.php | 20 + .../Events/Test/Outcome/MarkedIncomplete.php | 67 + .../Outcome/MarkedIncompleteSubscriber.php | 20 + .../src/Event/Events/Test/Outcome/Passed.php | 50 + .../Events/Test/Outcome/PassedSubscriber.php | 20 + .../src/Event/Events/Test/Outcome/Skipped.php | 65 + .../Events/Test/Outcome/SkippedSubscriber.php | 20 + .../Events/Test/PrintedUnexpectedOutput.php | 61 + .../PrintedUnexpectedOutputSubscriber.php | 20 + .../Test/TestDouble/MockObjectCreated.php | 59 + .../MockObjectCreatedSubscriber.php | 20 + .../MockObjectForAbstractClassCreated.php | 59 + ...bjectForAbstractClassCreatedSubscriber.php | 20 + ...jectForIntersectionOfInterfacesCreated.php | 60 + ...ersectionOfInterfacesCreatedSubscriber.php | 20 + .../TestDouble/MockObjectForTraitCreated.php | 59 + .../MockObjectForTraitCreatedSubscriber.php | 20 + .../TestDouble/MockObjectFromWsdlCreated.php | 109 + .../MockObjectFromWsdlCreatedSubscriber.php | 20 + .../TestDouble/PartialMockObjectCreated.php | 73 + .../PartialMockObjectCreatedSubscriber.php | 20 + .../Test/TestDouble/TestProxyCreated.php | 66 + .../TestDouble/TestProxyCreatedSubscriber.php | 20 + .../Test/TestDouble/TestStubCreated.php | 59 + .../TestDouble/TestStubCreatedSubscriber.php | 20 + ...StubForIntersectionOfInterfacesCreated.php | 60 + ...ersectionOfInterfacesCreatedSubscriber.php | 20 + .../Events/TestRunner/BootstrapFinished.php | 49 + .../BootstrapFinishedSubscriber.php | 20 + .../Event/Events/TestRunner/Configured.php | 44 + .../TestRunner/ConfiguredSubscriber.php | 20 + .../TestRunner/DeprecationTriggered.php | 49 + .../DeprecationTriggeredSubscriber.php | 20 + .../Events/TestRunner/EventFacadeSealed.php | 38 + .../EventFacadeSealedSubscriber.php | 20 + .../Events/TestRunner/ExecutionAborted.php | 38 + .../TestRunner/ExecutionAbortedSubscriber.php | 20 + .../Events/TestRunner/ExecutionFinished.php | 38 + .../ExecutionFinishedSubscriber.php | 20 + .../Events/TestRunner/ExecutionStarted.php | 51 + .../TestRunner/ExecutionStartedSubscriber.php | 20 + .../TestRunner/ExtensionBootstrapped.php | 74 + .../ExtensionBootstrappedSubscriber.php | 20 + .../TestRunner/ExtensionLoadedFromPhar.php | 64 + .../ExtensionLoadedFromPharSubscriber.php | 20 + .../src/Event/Events/TestRunner/Finished.php | 38 + .../Events/TestRunner/FinishedSubscriber.php | 20 + .../TestRunner/GarbageCollectionDisabled.php | 38 + .../GarbageCollectionDisabledSubscriber.php | 20 + .../TestRunner/GarbageCollectionEnabled.php | 38 + .../GarbageCollectionEnabledSubscriber.php | 20 + .../TestRunner/GarbageCollectionTriggered.php | 38 + .../GarbageCollectionTriggeredSubscriber.php | 20 + .../src/Event/Events/TestRunner/Started.php | 38 + .../Events/TestRunner/StartedSubscriber.php | 20 + .../Events/TestRunner/WarningTriggered.php | 49 + .../TestRunner/WarningTriggeredSubscriber.php | 20 + .../src/Event/Events/TestSuite/Filtered.php | 50 + .../Events/TestSuite/FilteredSubscriber.php | 20 + .../src/Event/Events/TestSuite/Finished.php | 51 + .../Events/TestSuite/FinishedSubscriber.php | 20 + .../src/Event/Events/TestSuite/Loaded.php | 50 + .../Events/TestSuite/LoadedSubscriber.php | 20 + .../src/Event/Events/TestSuite/Skipped.php | 57 + .../Events/TestSuite/SkippedSubscriber.php | 20 + .../src/Event/Events/TestSuite/Sorted.php | 59 + .../Events/TestSuite/SortedSubscriber.php | 20 + .../src/Event/Events/TestSuite/Started.php | 51 + .../Events/TestSuite/StartedSubscriber.php | 20 + .../EventAlreadyAssignedException.php | 19 + .../EventFacadeIsSealedException.php | 19 + .../phpunit/src/Event/Exception/Exception.php | 14 + .../Exception/InvalidArgumentException.php | 17 + .../Event/Exception/InvalidEventException.php | 19 + .../Exception/InvalidSubscriberException.php | 19 + .../phpunit/src/Event/Exception/MapError.php | 19 + ...hanOneDataSetFromDataProviderException.php | 20 + .../NoComparisonFailureException.php | 20 + .../NoDataSetFromDataProviderException.php | 20 + .../NoPreviousThrowableException.php | 19 + .../NoTestCaseObjectOnCallStackException.php | 26 + .../src/Event/Exception/RuntimeException.php | 17 + ...bscriberTypeAlreadyRegisteredException.php | 19 + .../Event/Exception/UnknownEventException.php | 19 + .../Exception/UnknownEventTypeException.php | 19 + .../Exception/UnknownSubscriberException.php | 19 + .../UnknownSubscriberTypeException.php | 19 + .../phpunit/phpunit/src/Event/Facade.php | 269 + .../phpunit/phpunit/src/Event/Subscriber.php | 17 + .../phpunit/phpunit/src/Event/Tracer.php | 20 + .../phpunit/phpunit/src/Event/TypeMap.php | 192 + .../phpunit/src/Event/Value/ClassMethod.php | 54 + .../src/Event/Value/ComparisonFailure.php | 44 + .../Event/Value/ComparisonFailureBuilder.php | 70 + .../Event/Value/Runtime/OperatingSystem.php | 40 + .../phpunit/src/Event/Value/Runtime/PHP.php | 105 + .../src/Event/Value/Runtime/PHPUnit.php | 39 + .../src/Event/Value/Runtime/Runtime.php | 59 + .../src/Event/Value/Telemetry/Duration.php | 148 + .../Telemetry/GarbageCollectorStatus.php | 180 + .../GarbageCollectorStatusProvider.php | 20 + .../src/Event/Value/Telemetry/HRTime.php | 106 + .../src/Event/Value/Telemetry/Info.php | 85 + .../src/Event/Value/Telemetry/MemoryMeter.php | 22 + .../src/Event/Value/Telemetry/MemoryUsage.php | 40 + .../Php81GarbageCollectorStatusProvider.php | 42 + .../Php83GarbageCollectorStatusProvider.php | 40 + .../src/Event/Value/Telemetry/Snapshot.php | 51 + .../src/Event/Value/Telemetry/StopWatch.php | 20 + .../src/Event/Value/Telemetry/System.php | 39 + .../Value/Telemetry/SystemMemoryMeter.php | 31 + .../Event/Value/Telemetry/SystemStopWatch.php | 29 + .../Telemetry/SystemStopWatchWithOffset.php | 46 + .../phpunit/src/Event/Value/Test/Phpt.php | 42 + .../phpunit/src/Event/Value/Test/Test.php | 65 + .../src/Event/Value/Test/TestCollection.php | 60 + .../Value/Test/TestCollectionIterator.php | 57 + .../Test/TestData/DataFromDataProvider.php | 55 + .../Test/TestData/DataFromTestDependency.php | 31 + .../Event/Value/Test/TestData/TestData.php | 46 + .../Test/TestData/TestDataCollection.php | 104 + .../TestData/TestDataCollectionIterator.php | 57 + .../phpunit/src/Event/Value/Test/TestDox.php | 43 + .../src/Event/Value/Test/TestDoxBuilder.php | 53 + .../src/Event/Value/Test/TestMethod.php | 155 + .../Event/Value/Test/TestMethodBuilder.php | 99 + .../src/Event/Value/TestSuite/TestSuite.php | 79 + .../Value/TestSuite/TestSuiteBuilder.php | 112 + .../Value/TestSuite/TestSuiteForTestClass.php | 65 + ...TestSuiteForTestMethodWithDataProvider.php | 81 + .../Value/TestSuite/TestSuiteWithName.php | 26 + .../phpunit/src/Event/Value/Throwable.php | 103 + .../src/Event/Value/ThrowableBuilder.php | 44 + .../vendor/phpunit/phpunit/src/Exception.php | 16 + .../phpunit/phpunit/src/Framework/Assert.php | 2332 +++++ .../src/Framework/Assert/Functions.php | 2707 ++++++ .../src/Framework/Attributes/After.php | 22 + .../src/Framework/Attributes/AfterClass.php | 22 + .../Framework/Attributes/BackupGlobals.php | 33 + .../Attributes/BackupStaticProperties.php | 33 + .../src/Framework/Attributes/Before.php | 22 + .../src/Framework/Attributes/BeforeClass.php | 22 + .../Attributes/CodeCoverageIgnore.php | 24 + .../src/Framework/Attributes/CoversClass.php | 42 + .../Framework/Attributes/CoversFunction.php | 42 + .../Framework/Attributes/CoversNothing.php | 22 + .../src/Framework/Attributes/DataProvider.php | 42 + .../Attributes/DataProviderExternal.php | 57 + .../src/Framework/Attributes/Depends.php | 42 + .../Framework/Attributes/DependsExternal.php | 57 + .../DependsExternalUsingDeepClone.php | 57 + .../DependsExternalUsingShallowClone.php | 57 + .../Framework/Attributes/DependsOnClass.php | 42 + .../DependsOnClassUsingDeepClone.php | 42 + .../DependsOnClassUsingShallowClone.php | 42 + .../Attributes/DependsUsingDeepClone.php | 42 + .../Attributes/DependsUsingShallowClone.php | 42 + .../Attributes/DoesNotPerformAssertions.php | 22 + .../ExcludeGlobalVariableFromBackup.php | 42 + .../ExcludeStaticPropertyFromBackup.php | 57 + .../src/Framework/Attributes/Group.php | 42 + .../Attributes/IgnoreClassForCodeCoverage.php | 44 + .../Attributes/IgnoreDeprecations.php | 22 + .../IgnoreFunctionForCodeCoverage.php | 44 + .../IgnoreMethodForCodeCoverage.php | 59 + .../src/Framework/Attributes/Large.php | 22 + .../src/Framework/Attributes/Medium.php | 22 + .../Framework/Attributes/PostCondition.php | 22 + .../src/Framework/Attributes/PreCondition.php | 22 + .../Attributes/PreserveGlobalState.php | 33 + .../Framework/Attributes/RequiresFunction.php | 42 + .../Framework/Attributes/RequiresMethod.php | 57 + .../Attributes/RequiresOperatingSystem.php | 42 + .../RequiresOperatingSystemFamily.php | 42 + .../src/Framework/Attributes/RequiresPhp.php | 42 + .../Attributes/RequiresPhpExtension.php | 57 + .../Framework/Attributes/RequiresPhpunit.php | 42 + .../Framework/Attributes/RequiresSetting.php | 57 + .../Attributes/RunClassInSeparateProcess.php | 22 + .../Attributes/RunInSeparateProcess.php | 22 + .../RunTestsInSeparateProcesses.php | 22 + .../src/Framework/Attributes/Small.php | 22 + .../phpunit/src/Framework/Attributes/Test.php | 22 + .../src/Framework/Attributes/TestDox.php | 42 + .../src/Framework/Attributes/TestWith.php | 33 + .../src/Framework/Attributes/TestWithJson.php | 42 + .../src/Framework/Attributes/Ticket.php | 42 + .../src/Framework/Attributes/UsesClass.php | 42 + .../src/Framework/Attributes/UsesFunction.php | 42 + .../Attributes/WithoutErrorHandler.php | 22 + .../Framework/Constraint/Boolean/IsFalse.php | 33 + .../Framework/Constraint/Boolean/IsTrue.php | 33 + .../src/Framework/Constraint/Callback.php | 73 + .../Constraint/Cardinality/Count.php | 126 + .../Constraint/Cardinality/GreaterThan.php | 42 + .../Constraint/Cardinality/IsEmpty.php | 66 + .../Constraint/Cardinality/LessThan.php | 42 + .../Constraint/Cardinality/SameSize.php | 29 + .../src/Framework/Constraint/Constraint.php | 264 + .../Framework/Constraint/Equality/IsEqual.php | 120 + .../Equality/IsEqualCanonicalizing.php | 103 + .../Equality/IsEqualIgnoringCase.php | 104 + .../Constraint/Equality/IsEqualWithDelta.php | 92 + .../Constraint/Exception/Exception.php | 81 + .../Constraint/Exception/ExceptionCode.php | 57 + .../ExceptionMessageIsOrContains.php | 69 + ...ceptionMessageMatchesRegularExpression.php | 73 + .../Constraint/Filesystem/DirectoryExists.php | 50 + .../Constraint/Filesystem/FileExists.php | 50 + .../Constraint/Filesystem/IsReadable.php | 50 + .../Constraint/Filesystem/IsWritable.php | 50 + .../src/Framework/Constraint/IsAnything.php | 51 + .../src/Framework/Constraint/IsIdentical.php | 123 + .../src/Framework/Constraint/JsonMatches.php | 97 + .../Framework/Constraint/Math/IsFinite.php | 35 + .../Framework/Constraint/Math/IsInfinite.php | 35 + .../src/Framework/Constraint/Math/IsNan.php | 35 + .../Constraint/Object/ObjectEquals.php | 142 + .../Constraint/Object/ObjectHasProperty.php | 80 + .../Constraint/Operator/BinaryOperator.php | 132 + .../Constraint/Operator/LogicalAnd.php | 54 + .../Constraint/Operator/LogicalNot.php | 141 + .../Constraint/Operator/LogicalOr.php | 54 + .../Constraint/Operator/LogicalXor.php | 66 + .../Constraint/Operator/Operator.php | 55 + .../Constraint/Operator/UnaryOperator.php | 128 + .../Framework/Constraint/String/IsJson.php | 91 + .../Constraint/String/RegularExpression.php | 46 + .../Constraint/String/StringContains.php | 160 + .../Constraint/String/StringEndsWith.php | 50 + .../StringEqualsStringIgnoringLineEndings.php | 57 + .../String/StringMatchesFormatDescription.php | 117 + .../Constraint/String/StringStartsWith.php | 50 + .../Constraint/Traversable/ArrayHasKey.php | 64 + .../Constraint/Traversable/IsList.php | 51 + .../Traversable/TraversableContains.php | 55 + .../Traversable/TraversableContainsEqual.php | 38 + .../TraversableContainsIdentical.php | 37 + .../Traversable/TraversableContainsOnly.php | 75 + .../Constraint/Type/IsInstanceOf.php | 79 + .../src/Framework/Constraint/Type/IsNull.php | 33 + .../src/Framework/Constraint/Type/IsType.php | 205 + .../src/Framework/DataProviderTestSuite.php | 76 + .../Exception/AssertionFailedError.php | 26 + .../Exception/CodeCoverageException.php | 19 + .../Exception/EmptyStringException.php | 19 + .../src/Framework/Exception/Exception.php | 82 + .../Exception/ExpectationFailedException.php | 41 + .../GeneratorNotSupportedException.php | 30 + .../Exception/Incomplete/IncompleteTest.php | 21 + .../Incomplete/IncompleteTestError.php | 19 + .../Exception/InvalidArgumentException.php | 19 + .../InvalidCoversTargetException.php | 19 + .../InvalidDataProviderException.php | 19 + .../Exception/InvalidDependencyException.php | 19 + .../Exception/NoChildTestSuiteException.php | 19 + .../ActualValueIsNotAnObjectException.php | 25 + ...hodDoesNotAcceptParameterTypeException.php | 32 + ...dDoesNotDeclareBoolReturnTypeException.php | 31 + ...NotDeclareExactlyOneParameterException.php | 31 + ...odDoesNotDeclareParameterTypeException.php | 31 + .../ComparisonMethodDoesNotExistException.php | 31 + .../Exception/PhptAssertionFailedError.php | 55 + .../Exception/ProcessIsolationException.php | 19 + .../Exception/Skipped/SkippedTest.php | 21 + .../Skipped/SkippedTestSuiteError.php | 19 + .../Skipped/SkippedWithMessageException.php | 19 + .../UnknownClassOrInterfaceException.php | 30 + .../Exception/UnknownTypeException.php | 30 + .../Framework/ExecutionOrderDependency.php | 193 + .../MockObject/ConfigurableMethod.php | 83 + .../Exception/BadMethodCallException.php | 19 + .../CannotUseOnlyMethodsException.php | 31 + .../MockObject/Exception/Exception.php | 21 + .../IncompatibleReturnValueException.php | 33 + .../MatchBuilderNotFoundException.php | 30 + .../MatcherAlreadyRegisteredException.php | 30 + .../MethodCannotBeConfiguredException.php | 30 + .../MethodNameAlreadyConfiguredException.php | 23 + .../MethodNameNotConfiguredException.php | 23 + ...odParametersAlreadyConfiguredException.php | 23 + .../NeverReturningMethodException.php | 34 + .../NoMoreReturnValuesConfiguredException.php | 32 + .../ReturnValueNotConfiguredException.php | 31 + .../MockObject/Exception/RuntimeException.php | 19 + .../CannotUseAddMethodsException.php | 31 + .../Exception/ClassIsEnumerationException.php | 30 + .../Exception/ClassIsFinalException.php | 30 + .../Exception/ClassIsReadonlyException.php | 30 + .../Exception/DuplicateMethodException.php | 37 + .../Generator/Exception/Exception.php | 21 + .../Exception/InvalidMethodNameException.php | 30 + .../Exception/NameAlreadyInUseException.php | 33 + ...ConstructorInvocationRequiredException.php | 23 + .../Exception/ReflectionException.php | 19 + .../Generator/Exception/RuntimeException.php | 19 + .../SoapExtensionNotAvailableException.php | 25 + .../Exception/UnknownClassException.php | 30 + .../Exception/UnknownTraitException.php | 32 + .../Exception/UnknownTypeException.php | 30 + .../MockObject/Generator/Generator.php | 1074 +++ .../MockObject/Generator/MockClass.php | 70 + .../MockObject/Generator/MockMethod.php | 396 + .../MockObject/Generator/MockMethodSet.php | 47 + .../MockObject/Generator/MockTrait.php | 50 + .../MockObject/Generator/MockType.php | 23 + .../MockObject/Generator/TemplateLoader.php | 39 + .../Generator/templates/deprecation.tpl | 2 + .../Generator/templates/doubled_method.tpl | 35 + .../templates/doubled_static_method.tpl | 5 + .../Generator/templates/intersection.tpl | 5 + .../Generator/templates/proxied_method.tpl | 37 + .../Generator/templates/test_double_class.tpl | 5 + .../Generator/templates/trait_class.tpl | 6 + .../Generator/templates/wsdl_class.tpl | 9 + .../Generator/templates/wsdl_method.tpl | 4 + .../src/Framework/MockObject/MockBuilder.php | 491 ++ .../Runtime/Api/DoubledCloneMethod.php | 23 + .../MockObject/Runtime/Api/Method.php | 33 + .../MockObject/Runtime/Api/MockObjectApi.php | 54 + .../Runtime/Api/ProxiedCloneMethod.php | 25 + .../MockObject/Runtime/Api/StubApi.php | 56 + .../MockObject/Runtime/Builder/Identity.php | 25 + .../Runtime/Builder/InvocationMocker.php | 325 + .../Runtime/Builder/InvocationStubber.php | 40 + .../Runtime/Builder/MethodNameMatch.php | 26 + .../Runtime/Builder/ParametersMatch.php | 51 + .../MockObject/Runtime/Builder/Stub.php | 26 + .../Runtime/Interface/MockObject.php | 23 + .../Runtime/Interface/MockObjectInternal.php | 24 + .../MockObject/Runtime/Interface/Stub.php | 21 + .../Runtime/Interface/StubInternal.php | 26 + .../MockObject/Runtime/Invocation.php | 152 + .../MockObject/Runtime/InvocationHandler.php | 154 + .../Framework/MockObject/Runtime/Matcher.php | 212 + .../Runtime/MethodNameConstraint.php | 42 + .../Runtime/ReturnValueGenerator.php | 250 + .../Runtime/Rule/AnyInvokedCount.php | 34 + .../MockObject/Runtime/Rule/AnyParameters.php | 28 + .../Runtime/Rule/InvocationOrder.php | 52 + .../Runtime/Rule/InvokedAtLeastCount.php | 66 + .../Runtime/Rule/InvokedAtLeastOnce.php | 48 + .../Runtime/Rule/InvokedAtMostCount.php | 66 + .../MockObject/Runtime/Rule/InvokedCount.php | 94 + .../MockObject/Runtime/Rule/MethodName.php | 60 + .../MockObject/Runtime/Rule/Parameters.php | 142 + .../Runtime/Rule/ParametersRule.php | 26 + .../Runtime/Stub/ConsecutiveCalls.php | 53 + .../MockObject/Runtime/Stub/Exception.php | 36 + .../Runtime/Stub/ReturnArgument.php | 32 + .../Runtime/Stub/ReturnCallback.php | 36 + .../Runtime/Stub/ReturnReference.php | 32 + .../MockObject/Runtime/Stub/ReturnSelf.php | 29 + .../MockObject/Runtime/Stub/ReturnStub.php | 32 + .../Runtime/Stub/ReturnValueMap.php | 49 + .../MockObject/Runtime/Stub/Stub.php | 26 + .../phpunit/src/Framework/Reorderable.php | 30 + .../phpunit/src/Framework/SelfDescribing.php | 23 + .../phpunit/phpunit/src/Framework/Test.php | 20 + .../phpunit/src/Framework/TestBuilder.php | 282 + .../phpunit/src/Framework/TestCase.php | 2387 ++++++ .../phpunit/src/Framework/TestRunner.php | 472 ++ .../phpunit/src/Framework/TestSize/Known.php | 30 + .../phpunit/src/Framework/TestSize/Large.php | 38 + .../phpunit/src/Framework/TestSize/Medium.php | 38 + .../phpunit/src/Framework/TestSize/Small.php | 38 + .../src/Framework/TestSize/TestSize.php | 82 + .../src/Framework/TestSize/Unknown.php | 33 + .../src/Framework/TestStatus/Deprecation.php | 38 + .../src/Framework/TestStatus/Error.php | 38 + .../src/Framework/TestStatus/Failure.php | 38 + .../src/Framework/TestStatus/Incomplete.php | 38 + .../src/Framework/TestStatus/Known.php | 28 + .../src/Framework/TestStatus/Notice.php | 38 + .../src/Framework/TestStatus/Risky.php | 38 + .../src/Framework/TestStatus/Skipped.php | 38 + .../src/Framework/TestStatus/Success.php | 38 + .../src/Framework/TestStatus/TestStatus.php | 195 + .../src/Framework/TestStatus/Unknown.php | 38 + .../src/Framework/TestStatus/Warning.php | 38 + .../phpunit/src/Framework/TestSuite.php | 716 ++ .../src/Framework/TestSuiteIterator.php | 84 + .../phpunit/src/Logging/EventLogger.php | 68 + .../src/Logging/JUnit/JunitXmlLogger.php | 446 + .../Logging/JUnit/Subscriber/Subscriber.php | 30 + .../Subscriber/TestErroredSubscriber.php | 30 + .../JUnit/Subscriber/TestFailedSubscriber.php | 30 + .../Subscriber/TestFinishedSubscriber.php | 30 + .../TestMarkedIncompleteSubscriber.php | 30 + .../TestPreparationFailedSubscriber.php | 30 + .../TestPreparationStartedSubscriber.php | 30 + .../Subscriber/TestPreparedSubscriber.php | 30 + .../TestRunnerExecutionFinishedSubscriber.php | 26 + .../Subscriber/TestSkippedSubscriber.php | 30 + .../TestSuiteFinishedSubscriber.php | 26 + .../Subscriber/TestSuiteStartedSubscriber.php | 26 + .../TeamCity/Subscriber/Subscriber.php | 30 + .../TestConsideredRiskySubscriber.php | 30 + .../Subscriber/TestErroredSubscriber.php | 30 + .../Subscriber/TestFailedSubscriber.php | 30 + .../Subscriber/TestFinishedSubscriber.php | 30 + .../TestMarkedIncompleteSubscriber.php | 30 + .../Subscriber/TestPreparedSubscriber.php | 26 + .../TestRunnerExecutionFinishedSubscriber.php | 26 + .../Subscriber/TestSkippedSubscriber.php | 30 + .../TestSuiteFinishedSubscriber.php | 26 + .../Subscriber/TestSuiteStartedSubscriber.php | 26 + .../src/Logging/TeamCity/TeamCityLogger.php | 373 + .../src/Logging/TestDox/HtmlRenderer.php | 158 + .../src/Logging/TestDox/NamePrettifier.php | 295 + .../src/Logging/TestDox/PlainTextRenderer.php | 79 + .../TestResult/Subscriber/Subscriber.php | 30 + .../TestConsideredRiskySubscriber.php | 26 + .../Subscriber/TestErroredSubscriber.php | 26 + .../Subscriber/TestFailedSubscriber.php | 26 + .../Subscriber/TestFinishedSubscriber.php | 30 + .../TestMarkedIncompleteSubscriber.php | 26 + .../Subscriber/TestPassedSubscriber.php | 26 + .../Subscriber/TestPreparedSubscriber.php | 26 + .../Subscriber/TestSkippedSubscriber.php | 26 + .../TestTriggeredDeprecationSubscriber.php | 26 + .../TestTriggeredNoticeSubscriber.php | 26 + .../TestTriggeredPhpDeprecationSubscriber.php | 26 + .../TestTriggeredPhpNoticeSubscriber.php | 26 + .../TestTriggeredPhpWarningSubscriber.php | 26 + ...tTriggeredPhpunitDeprecationSubscriber.php | 26 + .../TestTriggeredPhpunitErrorSubscriber.php | 26 + .../TestTriggeredPhpunitWarningSubscriber.php | 26 + .../TestTriggeredWarningSubscriber.php | 26 + .../Logging/TestDox/TestResult/TestResult.php | 58 + .../TestResult/TestResultCollection.php | 55 + .../TestResultCollectionIterator.php | 59 + .../TestResult/TestResultCollector.php | 447 + .../phpunit/phpunit/src/Metadata/After.php | 26 + .../phpunit/src/Metadata/AfterClass.php | 26 + .../phpunit/src/Metadata/Api/CodeCoverage.php | 317 + .../phpunit/src/Metadata/Api/DataProvider.php | 313 + .../phpunit/src/Metadata/Api/Dependencies.php | 57 + .../phpunit/src/Metadata/Api/Groups.php | 132 + .../phpunit/src/Metadata/Api/HookMethods.php | 108 + .../phpunit/src/Metadata/Api/Requirements.php | 154 + .../phpunit/src/Metadata/BackupGlobals.php | 43 + .../src/Metadata/BackupStaticProperties.php | 43 + .../phpunit/phpunit/src/Metadata/Before.php | 26 + .../phpunit/src/Metadata/BeforeClass.php | 26 + .../phpunit/phpunit/src/Metadata/Covers.php | 50 + .../phpunit/src/Metadata/CoversClass.php | 60 + .../src/Metadata/CoversDefaultClass.php | 50 + .../phpunit/src/Metadata/CoversFunction.php | 58 + .../phpunit/src/Metadata/CoversNothing.php | 26 + .../phpunit/src/Metadata/DataProvider.php | 65 + .../phpunit/src/Metadata/DependsOnClass.php | 64 + .../phpunit/src/Metadata/DependsOnMethod.php | 79 + .../src/Metadata/DoesNotPerformAssertions.php | 26 + ...otSupportedForInternalClassesException.php | 35 + .../src/Metadata/Exception/Exception.php | 14 + .../InvalidVersionRequirementException.php | 16 + .../NoVersionRequirementException.php | 16 + .../Exception/ReflectionException.php | 22 + .../ExcludeGlobalVariableFromBackup.php | 50 + .../ExcludeStaticPropertyFromBackup.php | 65 + .../phpunit/phpunit/src/Metadata/Group.php | 50 + .../Metadata/IgnoreClassForCodeCoverage.php | 52 + .../src/Metadata/IgnoreDeprecations.php | 26 + .../IgnoreFunctionForCodeCoverage.php | 52 + .../Metadata/IgnoreMethodForCodeCoverage.php | 67 + .../phpunit/phpunit/src/Metadata/Metadata.php | 835 ++ .../src/Metadata/MetadataCollection.php | 561 ++ .../Metadata/MetadataCollectionIterator.php | 57 + .../Metadata/Parser/Annotation/DocBlock.php | 267 + .../Metadata/Parser/Annotation/Registry.php | 98 + .../src/Metadata/Parser/AnnotationParser.php | 568 ++ .../src/Metadata/Parser/AttributeParser.php | 674 ++ .../src/Metadata/Parser/CachingParser.php | 88 + .../phpunit/src/Metadata/Parser/Parser.php | 37 + .../src/Metadata/Parser/ParserChain.php | 77 + .../phpunit/src/Metadata/Parser/Registry.php | 38 + .../phpunit/src/Metadata/PostCondition.php | 26 + .../phpunit/src/Metadata/PreCondition.php | 26 + .../src/Metadata/PreserveGlobalState.php | 43 + .../phpunit/src/Metadata/RequiresFunction.php | 50 + .../phpunit/src/Metadata/RequiresMethod.php | 65 + .../src/Metadata/RequiresOperatingSystem.php | 50 + .../RequiresOperatingSystemFamily.php | 50 + .../phpunit/src/Metadata/RequiresPhp.php | 45 + .../src/Metadata/RequiresPhpExtension.php | 74 + .../phpunit/src/Metadata/RequiresPhpunit.php | 45 + .../phpunit/src/Metadata/RequiresSetting.php | 65 + .../Metadata/RunClassInSeparateProcess.php | 26 + .../src/Metadata/RunInSeparateProcess.php | 26 + .../Metadata/RunTestsInSeparateProcesses.php | 26 + .../phpunit/phpunit/src/Metadata/Test.php | 26 + .../phpunit/phpunit/src/Metadata/TestDox.php | 50 + .../phpunit/phpunit/src/Metadata/TestWith.php | 43 + .../phpunit/phpunit/src/Metadata/Uses.php | 50 + .../phpunit/src/Metadata/UsesClass.php | 60 + .../phpunit/src/Metadata/UsesDefaultClass.php | 50 + .../phpunit/src/Metadata/UsesFunction.php | 58 + .../Version/ComparisonRequirement.php | 40 + .../Version/ConstraintRequirement.php | 56 + .../src/Metadata/Version/Requirement.php | 57 + .../src/Metadata/WithoutErrorHandler.php | 26 + .../phpunit/src/Runner/Baseline/Baseline.php | 61 + .../Exception/CannotLoadBaselineException.php | 22 + .../FileDoesNotHaveLineException.php | 33 + .../phpunit/src/Runner/Baseline/Generator.php | 120 + .../phpunit/src/Runner/Baseline/Issue.php | 147 + .../phpunit/src/Runner/Baseline/Reader.php | 102 + .../Baseline/RelativePathCalculator.php | 105 + .../Runner/Baseline/Subscriber/Subscriber.php | 30 + .../TestTriggeredDeprecationSubscriber.php | 31 + .../TestTriggeredNoticeSubscriber.php | 31 + .../TestTriggeredPhpDeprecationSubscriber.php | 31 + .../TestTriggeredPhpNoticeSubscriber.php | 31 + .../TestTriggeredPhpWarningSubscriber.php | 31 + .../TestTriggeredWarningSubscriber.php | 31 + .../phpunit/src/Runner/Baseline/Writer.php | 67 + .../phpunit/src/Runner/CodeCoverage.php | 426 + .../phpunit/src/Runner/ErrorHandler.php | 226 + .../Exception/ClassCannotBeFoundException.php | 32 + .../ClassDoesNotExtendTestCaseException.php | 32 + .../Exception/ClassIsAbstractException.php | 32 + .../DirectoryDoesNotExistException.php | 31 + .../src/Runner/Exception/ErrorException.php | 21 + .../src/Runner/Exception/Exception.php | 19 + .../Exception/FileDoesNotExistException.php | 31 + .../Exception/InvalidOrderException.php | 21 + .../Exception/InvalidPhptFileException.php | 21 + .../ParameterDoesNotExistException.php | 31 + ...hptExternalFileCannotBeLoadedException.php | 32 + .../UnsupportedPhptSectionException.php | 31 + .../src/Runner/Extension/Extension.php | 20 + .../Extension/ExtensionBootstrapper.php | 97 + .../phpunit/src/Runner/Extension/Facade.php | 110 + .../Runner/Extension/ParameterCollection.php | 53 + .../src/Runner/Extension/PharLoader.php | 150 + .../Filter/ExcludeGroupFilterIterator.php | 25 + .../phpunit/src/Runner/Filter/Factory.php | 81 + .../src/Runner/Filter/GroupFilterIterator.php | 65 + .../Filter/IncludeGroupFilterIterator.php | 25 + .../src/Runner/Filter/NameFilterIterator.php | 142 + .../Runner/Filter/TestIdFilterIterator.php | 63 + .../GarbageCollectionHandler.php | 89 + .../ExecutionFinishedSubscriber.php | 31 + .../Subscriber/ExecutionStartedSubscriber.php | 31 + .../Subscriber/Subscriber.php | 30 + .../Subscriber/TestFinishedSubscriber.php | 31 + .../phpunit/src/Runner/PhptTestCase.php | 849 ++ .../Runner/ResultCache/DefaultResultCache.php | 155 + .../Runner/ResultCache/NullResultCache.php | 46 + .../src/Runner/ResultCache/ResultCache.php | 32 + .../Runner/ResultCache/ResultCacheHandler.php | 157 + .../ResultCache/Subscriber/Subscriber.php | 30 + .../TestConsideredRiskySubscriber.php | 26 + .../Subscriber/TestErroredSubscriber.php | 26 + .../Subscriber/TestFailedSubscriber.php | 26 + .../Subscriber/TestFinishedSubscriber.php | 31 + .../TestMarkedIncompleteSubscriber.php | 26 + .../Subscriber/TestPreparedSubscriber.php | 26 + .../Subscriber/TestSkippedSubscriber.php | 31 + .../TestSuiteFinishedSubscriber.php | 26 + .../Subscriber/TestSuiteStartedSubscriber.php | 26 + .../src/Runner/TestResult/Collector.php | 660 ++ .../phpunit/src/Runner/TestResult/Facade.php | 105 + .../phpunit/src/Runner/TestResult/Issue.php | 115 + .../src/Runner/TestResult/PassedTests.php | 124 + ...BeforeTestClassMethodErroredSubscriber.php | 26 + .../Subscriber/ExecutionStartedSubscriber.php | 26 + .../TestResult/Subscriber/Subscriber.php | 30 + .../TestConsideredRiskySubscriber.php | 26 + .../Subscriber/TestErroredSubscriber.php | 26 + .../Subscriber/TestFailedSubscriber.php | 26 + .../Subscriber/TestFinishedSubscriber.php | 26 + .../TestMarkedIncompleteSubscriber.php | 26 + .../Subscriber/TestPreparedSubscriber.php | 26 + ...stRunnerTriggeredDeprecationSubscriber.php | 26 + .../TestRunnerTriggeredWarningSubscriber.php | 26 + .../Subscriber/TestSkippedSubscriber.php | 26 + .../TestSuiteFinishedSubscriber.php | 26 + .../Subscriber/TestSuiteSkippedSubscriber.php | 26 + .../Subscriber/TestSuiteStartedSubscriber.php | 26 + .../TestTriggeredDeprecationSubscriber.php | 26 + .../TestTriggeredErrorSubscriber.php | 26 + .../TestTriggeredNoticeSubscriber.php | 26 + .../TestTriggeredPhpDeprecationSubscriber.php | 26 + .../TestTriggeredPhpNoticeSubscriber.php | 26 + .../TestTriggeredPhpWarningSubscriber.php | 26 + ...tTriggeredPhpunitDeprecationSubscriber.php | 26 + .../TestTriggeredPhpunitErrorSubscriber.php | 26 + .../TestTriggeredPhpunitWarningSubscriber.php | 26 + .../TestTriggeredWarningSubscriber.php | 26 + .../src/Runner/TestResult/TestResult.php | 576 ++ .../phpunit/src/Runner/TestSuiteLoader.php | 143 + .../phpunit/src/Runner/TestSuiteSorter.php | 344 + .../phpunit/phpunit/src/Runner/Version.php | 63 + .../phpunit/src/TextUI/Application.php | 754 ++ .../phpunit/src/TextUI/Command/Command.php | 20 + .../Commands/AtLeastVersionCommand.php | 37 + .../Commands/GenerateConfigurationCommand.php | 103 + .../Command/Commands/ListGroupsCommand.php | 83 + .../Commands/ListTestSuitesCommand.php | 74 + .../Commands/ListTestsAsTextCommand.php | 87 + .../Commands/ListTestsAsXmlCommand.php | 142 + .../Commands/MigrateConfigurationCommand.php | 64 + .../Command/Commands/ShowHelpCommand.php | 35 + .../Command/Commands/ShowVersionCommand.php | 23 + .../Command/Commands/VersionCheckCommand.php | 74 + .../Commands/WarmCodeCoverageCacheCommand.php | 81 + .../phpunit/src/TextUI/Command/Result.php | 48 + .../src/TextUI/Configuration/Builder.php | 52 + .../src/TextUI/Configuration/Cli/Builder.php | 1020 +++ .../Configuration/Cli/Configuration.php | 2054 +++++ .../TextUI/Configuration/Cli/Exception.php | 21 + .../Cli/XmlConfigurationFileFinder.php | 69 + .../CodeCoverageFilterRegistry.php | 78 + .../TextUI/Configuration/Configuration.php | 1309 +++ .../Exception/CannotFindSchemaException.php | 22 + ...deCoverageReportNotConfiguredException.php | 21 + .../ConfigurationCannotBeBuiltException.php | 21 + .../Configuration/Exception/Exception.php | 19 + .../FilterNotConfiguredException.php | 21 + .../LoggingNotConfiguredException.php | 21 + .../Exception/NoBaselineException.php | 21 + .../Exception/NoBootstrapException.php | 21 + .../Exception/NoCacheDirectoryException.php | 21 + .../Exception/NoCliArgumentException.php | 21 + .../NoConfigurationFileException.php | 21 + .../NoCoverageCacheDirectoryException.php | 21 + .../Exception/NoCustomCssFileException.php | 21 + .../Exception/NoDefaultTestSuiteException.php | 21 + .../NoPharExtensionDirectoryException.php | 21 + .../src/TextUI/Configuration/Merger.php | 879 ++ .../src/TextUI/Configuration/PhpHandler.php | 123 + .../src/TextUI/Configuration/Registry.php | 111 + .../src/TextUI/Configuration/SourceFilter.php | 25 + .../src/TextUI/Configuration/SourceMapper.php | 99 + .../TextUI/Configuration/TestSuiteBuilder.php | 146 + .../TextUI/Configuration/Value/Constant.php | 37 + .../Value/ConstantCollection.php | 60 + .../Value/ConstantCollectionIterator.php | 64 + .../TextUI/Configuration/Value/Directory.php | 30 + .../Value/DirectoryCollection.php | 65 + .../Value/DirectoryCollectionIterator.php | 64 + .../Value/ExtensionBootstrap.php | 54 + .../Value/ExtensionBootstrapCollection.php | 53 + .../ExtensionBootstrapCollectionIterator.php | 64 + .../src/TextUI/Configuration/Value/File.php | 39 + .../Configuration/Value/FileCollection.php | 65 + .../Value/FileCollectionIterator.php | 64 + .../Configuration/Value/FilterDirectory.php | 53 + .../Value/FilterDirectoryCollection.php | 65 + .../FilterDirectoryCollectionIterator.php | 64 + .../src/TextUI/Configuration/Value/Group.php | 30 + .../Configuration/Value/GroupCollection.php | 72 + .../Value/GroupCollectionIterator.php | 64 + .../TextUI/Configuration/Value/IniSetting.php | 37 + .../Value/IniSettingCollection.php | 60 + .../Value/IniSettingCollectionIterator.php | 64 + .../src/TextUI/Configuration/Value/Php.php | 100 + .../src/TextUI/Configuration/Value/Source.php | 166 + .../Configuration/Value/TestDirectory.php | 69 + .../Value/TestDirectoryCollection.php | 65 + .../Value/TestDirectoryCollectionIterator.php | 64 + .../TextUI/Configuration/Value/TestFile.php | 46 + .../Value/TestFileCollection.php | 65 + .../Value/TestFileCollectionIterator.php | 64 + .../TextUI/Configuration/Value/TestSuite.php | 60 + .../Value/TestSuiteCollection.php | 65 + .../Value/TestSuiteCollectionIterator.php | 64 + .../TextUI/Configuration/Value/Variable.php | 44 + .../Value/VariableCollection.php | 60 + .../Value/VariableCollectionIterator.php | 64 + .../Xml/CodeCoverage/CodeCoverage.php | 295 + .../Xml/CodeCoverage/Report/Clover.php | 34 + .../Xml/CodeCoverage/Report/Cobertura.php | 34 + .../Xml/CodeCoverage/Report/Crap4j.php | 41 + .../Xml/CodeCoverage/Report/Html.php | 106 + .../Xml/CodeCoverage/Report/Php.php | 34 + .../Xml/CodeCoverage/Report/Text.php | 48 + .../Xml/CodeCoverage/Report/Xml.php | 34 + .../Configuration/Xml/Configuration.php | 104 + .../Xml/DefaultConfiguration.php | 163 + .../TextUI/Configuration/Xml/Exception.php | 21 + .../TextUI/Configuration/Xml/Generator.php | 73 + .../src/TextUI/Configuration/Xml/Groups.php | 51 + .../Xml/LoadedFromFileConfiguration.php | 67 + .../src/TextUI/Configuration/Xml/Loader.php | 1049 +++ .../Configuration/Xml/Logging/Junit.php | 34 + .../Configuration/Xml/Logging/Logging.php | 105 + .../Configuration/Xml/Logging/TeamCity.php | 34 + .../Xml/Logging/TestDox/Html.php | 34 + .../Xml/Logging/TestDox/Text.php | 34 + .../Xml/Migration/MigrationBuilder.php | 84 + .../Xml/Migration/MigrationException.php | 22 + .../Migration/Migrations/ConvertLogTypes.php | 55 + .../Migrations/CoverageCloverToReport.php | 34 + .../Migrations/CoverageCrap4jToReport.php | 35 + .../Migrations/CoverageHtmlToReport.php | 35 + .../Migrations/CoveragePhpToReport.php | 33 + .../Migrations/CoverageTextToReport.php | 35 + .../Migrations/CoverageXmlToReport.php | 33 + .../IntroduceCacheDirectoryAttribute.php | 35 + .../Migrations/IntroduceCoverageElement.php | 30 + .../Migrations/LogToReportMigration.php | 81 + .../Xml/Migration/Migrations/Migration.php | 22 + ...ttributesFromFilterWhitelistToCoverage.php | 53 + .../MoveAttributesFromRootToCoverage.php | 52 + .../MoveCoverageDirectoriesToSource.php | 64 + .../MoveWhitelistExcludesToCoverage.php | 73 + .../MoveWhitelistIncludesToCoverage.php | 54 + ...ResourceUsageDuringSmallTestsAttribute.php | 33 + ...StrictAboutTodoAnnotatedTestsAttribute.php | 33 + .../RemoveCacheResultFileAttribute.php | 33 + .../Migrations/RemoveCacheTokensAttribute.php | 33 + ...RemoveConversionToExceptionsAttributes.php | 45 + ...CoverageElementCacheDirectoryAttribute.php | 34 + ...eElementProcessUncoveredFilesAttribute.php | 34 + .../Migrations/RemoveEmptyFilter.php | 56 + .../Migration/Migrations/RemoveListeners.php | 32 + .../Migration/Migrations/RemoveLogTypes.php | 41 + .../Migrations/RemoveLoggingElements.php | 50 + .../RemoveNoInteractionAttribute.php | 33 + .../Migrations/RemovePrinterAttributes.php | 37 + .../Migrations/RemoveTestDoxGroupsElement.php | 32 + .../RemoveTestSuiteLoaderAttributes.php | 37 + .../Migrations/RemoveVerboseAttribute.php | 33 + .../RenameBackupStaticAttributesAttribute.php | 40 + ...BeStrictAboutCoversAnnotationAttribute.php | 40 + .../RenameForceCoversAnnotationAttribute.php | 40 + .../Migrations/UpdateSchemaLocation.php | 36 + .../Configuration/Xml/Migration/Migrator.php | 51 + .../Xml/Migration/SnapshotNodeList.php | 53 + .../src/TextUI/Configuration/Xml/PHPUnit.php | 494 ++ .../FailedSchemaDetectionResult.php | 21 + .../SchemaDetector/SchemaDetectionResult.php | 38 + .../Xml/SchemaDetector/SchemaDetector.php | 41 + .../SuccessfulSchemaDetectionResult.php | 49 + .../TextUI/Configuration/Xml/SchemaFinder.php | 82 + .../Configuration/Xml/TestSuiteMapper.php | 117 + .../Xml/Validator/ValidationResult.php | 73 + .../Configuration/Xml/Validator/Validator.php | 37 + .../Exception/CannotOpenSocketException.php | 32 + .../src/TextUI/Exception/Exception.php | 21 + .../Exception/InvalidSocketException.php | 31 + .../src/TextUI/Exception/RuntimeException.php | 19 + .../TestDirectoryNotFoundException.php | 31 + .../Exception/TestFileNotFoundException.php | 31 + .../phpunit/phpunit/src/TextUI/Help.php | 303 + .../ProgressPrinter/ProgressPrinter.php | 402 + ...BeforeTestClassMethodErroredSubscriber.php | 26 + .../ProgressPrinter/Subscriber/Subscriber.php | 30 + .../TestConsideredRiskySubscriber.php | 26 + .../Subscriber/TestErroredSubscriber.php | 26 + .../Subscriber/TestFailedSubscriber.php | 26 + .../Subscriber/TestFinishedSubscriber.php | 26 + .../TestMarkedIncompleteSubscriber.php | 26 + .../Subscriber/TestPreparedSubscriber.php | 26 + .../TestRunnerExecutionStartedSubscriber.php | 26 + .../Subscriber/TestSkippedSubscriber.php | 26 + .../TestTriggeredDeprecationSubscriber.php | 26 + .../TestTriggeredErrorSubscriber.php | 26 + .../TestTriggeredNoticeSubscriber.php | 26 + .../TestTriggeredPhpDeprecationSubscriber.php | 26 + .../TestTriggeredPhpNoticeSubscriber.php | 26 + .../TestTriggeredPhpWarningSubscriber.php | 26 + ...tTriggeredPhpunitDeprecationSubscriber.php | 26 + .../TestTriggeredPhpunitWarningSubscriber.php | 26 + .../TestTriggeredWarningSubscriber.php | 26 + .../TextUI/Output/Default/ResultPrinter.php | 626 ++ .../Default/UnexpectedOutputPrinter.php | 38 + .../phpunit/src/TextUI/Output/Facade.php | 281 + .../TextUI/Output/Printer/DefaultPrinter.php | 122 + .../src/TextUI/Output/Printer/NullPrinter.php | 26 + .../src/TextUI/Output/Printer/Printer.php | 22 + .../src/TextUI/Output/SummaryPrinter.php | 173 + .../TextUI/Output/TestDox/ResultPrinter.php | 366 + .../src/TextUI/ShellExitCodeCalculator.php | 73 + .../phpunit/phpunit/src/TextUI/TestRunner.php | 76 + .../src/TextUI/TestSuiteFilterProcessor.php | 84 + .../phpunit/phpunit/src/Util/Cloner.php | 36 + .../vendor/phpunit/phpunit/src/Util/Color.php | 181 + .../phpunit/src/Util/Exception/Exception.php | 21 + .../Exception/InvalidDirectoryException.php | 31 + .../Util/Exception/InvalidJsonException.php | 21 + .../InvalidVersionOperatorException.php | 31 + .../Util/Exception/PhpProcessException.php | 22 + .../src/Util/Exception/XmlException.php | 22 + .../phpunit/phpunit/src/Util/ExcludeList.php | 231 + .../phpunit/phpunit/src/Util/Exporter.php | 63 + .../phpunit/phpunit/src/Util/Filesystem.php | 51 + .../phpunit/phpunit/src/Util/Filter.php | 117 + .../phpunit/phpunit/src/Util/GlobalState.php | 289 + .../phpunit/src/Util/Http/Downloader.php | 23 + .../phpunit/src/Util/Http/PhpDownloader.php | 28 + .../vendor/phpunit/phpunit/src/Util/Json.php | 102 + .../src/Util/PHP/AbstractPhpProcess.php | 322 + .../src/Util/PHP/DefaultPhpProcess.php | 148 + .../src/Util/PHP/Template/PhptTestCase.tpl | 56 + .../src/Util/PHP/Template/TestCaseClass.tpl | 116 + .../src/Util/PHP/Template/TestCaseMethod.tpl | 116 + .../phpunit/phpunit/src/Util/Reflection.php | 107 + .../vendor/phpunit/phpunit/src/Util/Test.php | 40 + .../src/Util/ThrowableToStringMapper.php | 52 + .../src/Util/VersionComparisonOperator.php | 57 + .../phpunit/phpunit/src/Util/Xml/Loader.php | 125 + .../phpunit/phpunit/src/Util/Xml/Xml.php | 81 + .../vendor/predis/predis/LICENSE | 22 + .../vendor/predis/predis/README.md | 466 + .../vendor/predis/predis/autoload.php | 12 + .../vendor/predis/predis/composer.json | 51 + .../vendor/predis/predis/src/Autoloader.php | 64 + .../vendor/predis/predis/src/Client.php | 612 ++ .../predis/predis/src/ClientConfiguration.php | 42 + .../predis/src/ClientContextInterface.php | 389 + .../predis/predis/src/ClientException.php | 20 + .../predis/predis/src/ClientInterface.php | 441 + .../predis/src/Cluster/ClusterStrategy.php | 493 ++ .../Distributor/DistributorInterface.php | 81 + .../Distributor/EmptyRingException.php | 22 + .../src/Cluster/Distributor/HashRing.php | 268 + .../src/Cluster/Distributor/KetamaRing.php | 70 + .../predis/predis/src/Cluster/Hash/CRC16.php | 73 + .../Cluster/Hash/HashGeneratorInterface.php | 29 + .../src/Cluster/Hash/PhpiredisCRC16.php | 42 + .../predis/src/Cluster/PredisStrategy.php | 77 + .../predis/src/Cluster/RedisStrategy.php | 55 + .../predis/predis/src/Cluster/SlotMap.php | 209 + .../predis/src/Cluster/StrategyInterface.php | 52 + .../Iterator/CursorBasedIterator.php | 196 + .../src/Collection/Iterator/HashKey.php | 57 + .../src/Collection/Iterator/Keyspace.php | 42 + .../src/Collection/Iterator/ListKey.php | 183 + .../predis/src/Collection/Iterator/SetKey.php | 46 + .../src/Collection/Iterator/SortedSetKey.php | 57 + .../Command/Argument/ArrayableArgument.php | 26 + .../Argument/Geospatial/AbstractBy.php | 46 + .../src/Command/Argument/Geospatial/ByBox.php | 43 + .../Argument/Geospatial/ByInterface.php | 19 + .../Command/Argument/Geospatial/ByRadius.php | 37 + .../Argument/Geospatial/FromInterface.php | 19 + .../Argument/Geospatial/FromLonLat.php | 42 + .../Argument/Geospatial/FromMember.php | 36 + .../Argument/Search/AggregateArguments.php | 161 + .../Argument/Search/AlterArguments.php | 17 + .../Argument/Search/CommonArguments.php | 182 + .../Argument/Search/CreateArguments.php | 191 + .../Argument/Search/CursorArguments.php | 44 + .../Command/Argument/Search/DropArguments.php | 43 + .../Argument/Search/ExplainArguments.php | 17 + .../Argument/Search/ProfileArguments.php | 81 + .../Search/SchemaFields/AbstractField.php | 75 + .../Search/SchemaFields/FieldInterface.php | 22 + .../Argument/Search/SchemaFields/GeoField.php | 33 + .../Search/SchemaFields/GeoShapeField.php | 57 + .../Search/SchemaFields/NumericField.php | 33 + .../Argument/Search/SchemaFields/TagField.php | 51 + .../Search/SchemaFields/TextField.php | 65 + .../Search/SchemaFields/VectorField.php | 47 + .../Argument/Search/SearchArguments.php | 306 + .../Argument/Search/SpellcheckArguments.php | 59 + .../Argument/Search/SugAddArguments.php | 28 + .../Argument/Search/SugGetArguments.php | 41 + .../Argument/Search/SynUpdateArguments.php | 17 + .../Argument/Server/LimitInterface.php | 19 + .../Argument/Server/LimitOffsetCount.php | 42 + .../predis/src/Command/Argument/Server/To.php | 57 + .../Argument/TimeSeries/AddArguments.php | 30 + .../Argument/TimeSeries/AlterArguments.php | 17 + .../Argument/TimeSeries/CommonArguments.php | 162 + .../Argument/TimeSeries/CreateArguments.php | 17 + .../Argument/TimeSeries/DecrByArguments.php | 17 + .../Argument/TimeSeries/GetArguments.php | 17 + .../Argument/TimeSeries/IncrByArguments.php | 41 + .../Argument/TimeSeries/InfoArguments.php | 43 + .../Argument/TimeSeries/MGetArguments.php | 17 + .../Argument/TimeSeries/MRangeArguments.php | 44 + .../Argument/TimeSeries/RangeArguments.php | 85 + .../predis/predis/src/Command/Command.php | 126 + .../predis/src/Command/CommandInterface.php | 80 + .../predis/predis/src/Command/Factory.php | 143 + .../predis/src/Command/FactoryInterface.php | 42 + .../Command/PrefixableCommandInterface.php | 26 + .../Command/Processor/KeyPrefixProcessor.php | 609 ++ .../src/Command/Processor/ProcessorChain.php | 142 + .../Command/Processor/ProcessorInterface.php | 28 + .../predis/predis/src/Command/RawCommand.php | 123 + .../predis/predis/src/Command/RawFactory.php | 43 + .../predis/predis/src/Command/Redis/ACL.php | 53 + .../predis/src/Command/Redis/APPEND.php | 29 + .../predis/predis/src/Command/Redis/AUTH.php | 29 + .../Redis/AbstractCommand/BZPOPBase.php | 43 + .../predis/src/Command/Redis/BGREWRITEAOF.php | 37 + .../predis/src/Command/Redis/BGSAVE.php | 37 + .../predis/src/Command/Redis/BITCOUNT.php | 34 + .../predis/src/Command/Redis/BITFIELD.php | 29 + .../predis/predis/src/Command/Redis/BITOP.php | 43 + .../predis/src/Command/Redis/BITPOS.php | 34 + .../predis/src/Command/Redis/BLMOVE.php | 21 + .../predis/src/Command/Redis/BLMPOP.php | 25 + .../predis/predis/src/Command/Redis/BLPOP.php | 42 + .../predis/predis/src/Command/Redis/BRPOP.php | 42 + .../predis/src/Command/Redis/BRPOPLPUSH.php | 29 + .../predis/src/Command/Redis/BZMPOP.php | 30 + .../predis/src/Command/Redis/BZPOPMAX.php | 33 + .../predis/src/Command/Redis/BZPOPMIN.php | 33 + .../src/Command/Redis/BloomFilter/BFADD.php | 29 + .../Command/Redis/BloomFilter/BFEXISTS.php | 28 + .../src/Command/Redis/BloomFilter/BFINFO.php | 79 + .../Command/Redis/BloomFilter/BFINSERT.php | 72 + .../Command/Redis/BloomFilter/BFLOADCHUNK.php | 28 + .../src/Command/Redis/BloomFilter/BFMADD.php | 29 + .../Command/Redis/BloomFilter/BFMEXISTS.php | 28 + .../Command/Redis/BloomFilter/BFRESERVE.php | 49 + .../Command/Redis/BloomFilter/BFSCANDUMP.php | 29 + .../predis/src/Command/Redis/CLIENT.php | 75 + .../predis/src/Command/Redis/CLUSTER.php | 26 + .../predis/src/Command/Redis/COMMAND.php | 40 + .../predis/src/Command/Redis/CONFIG.php | 54 + .../predis/predis/src/Command/Redis/COPY.php | 47 + .../src/Command/Redis/Container/ACL.php | 28 + .../Redis/Container/AbstractContainer.php | 42 + .../src/Command/Redis/Container/CLUSTER.php | 29 + .../Redis/Container/ContainerFactory.php | 81 + .../Redis/Container/ContainerInterface.php | 33 + .../Redis/Container/FunctionContainer.php | 33 + .../Redis/Container/Json/JSONDEBUG.php | 27 + .../Redis/Container/Search/FTCONFIG.php | 29 + .../Redis/Container/Search/FTCURSOR.php | 29 + .../Redis/CountMinSketch/CMSINCRBY.php | 29 + .../Command/Redis/CountMinSketch/CMSINFO.php | 45 + .../Redis/CountMinSketch/CMSINITBYDIM.php | 28 + .../Redis/CountMinSketch/CMSINITBYPROB.php | 28 + .../Command/Redis/CountMinSketch/CMSMERGE.php | 42 + .../Command/Redis/CountMinSketch/CMSQUERY.php | 28 + .../src/Command/Redis/CuckooFilter/CFADD.php | 28 + .../Command/Redis/CuckooFilter/CFADDNX.php | 28 + .../Command/Redis/CuckooFilter/CFCOUNT.php | 29 + .../src/Command/Redis/CuckooFilter/CFDEL.php | 30 + .../Command/Redis/CuckooFilter/CFEXISTS.php | 28 + .../src/Command/Redis/CuckooFilter/CFINFO.php | 45 + .../Command/Redis/CuckooFilter/CFINSERT.php | 52 + .../Command/Redis/CuckooFilter/CFINSERTNX.php | 27 + .../Redis/CuckooFilter/CFLOADCHUNK.php | 29 + .../Command/Redis/CuckooFilter/CFMEXISTS.php | 28 + .../Command/Redis/CuckooFilter/CFRESERVE.php | 52 + .../Command/Redis/CuckooFilter/CFSCANDUMP.php | 29 + .../predis/src/Command/Redis/DBSIZE.php | 29 + .../predis/predis/src/Command/Redis/DECR.php | 29 + .../predis/src/Command/Redis/DECRBY.php | 29 + .../predis/predis/src/Command/Redis/DEL.php | 39 + .../predis/src/Command/Redis/DISCARD.php | 29 + .../predis/predis/src/Command/Redis/DUMP.php | 29 + .../predis/predis/src/Command/Redis/ECHO_.php | 29 + .../predis/src/Command/Redis/EVALSHA.php | 37 + .../predis/src/Command/Redis/EVALSHA_RO.php | 27 + .../predis/predis/src/Command/Redis/EVAL_.php | 39 + .../predis/src/Command/Redis/EVAL_RO.php | 34 + .../predis/predis/src/Command/Redis/EXEC.php | 29 + .../predis/src/Command/Redis/EXISTS.php | 29 + .../predis/src/Command/Redis/EXPIRE.php | 36 + .../predis/src/Command/Redis/EXPIREAT.php | 35 + .../predis/src/Command/Redis/EXPIRETIME.php | 29 + .../predis/src/Command/Redis/FAILOVER.php | 48 + .../predis/predis/src/Command/Redis/FCALL.php | 33 + .../predis/src/Command/Redis/FCALL_RO.php | 41 + .../predis/src/Command/Redis/FLUSHALL.php | 29 + .../predis/src/Command/Redis/FLUSHDB.php | 29 + .../predis/src/Command/Redis/FUNCTIONS.php | 50 + .../predis/src/Command/Redis/GEOADD.php | 43 + .../predis/src/Command/Redis/GEODIST.php | 29 + .../predis/src/Command/Redis/GEOHASH.php | 42 + .../predis/src/Command/Redis/GEOPOS.php | 42 + .../predis/src/Command/Redis/GEORADIUS.php | 77 + .../src/Command/Redis/GEORADIUSBYMEMBER.php | 32 + .../predis/src/Command/Redis/GEOSEARCH.php | 122 + .../src/Command/Redis/GEOSEARCHSTORE.php | 71 + .../predis/predis/src/Command/Redis/GET.php | 29 + .../predis/src/Command/Redis/GETBIT.php | 29 + .../predis/src/Command/Redis/GETDEL.php | 23 + .../predis/predis/src/Command/Redis/GETEX.php | 63 + .../predis/src/Command/Redis/GETRANGE.php | 29 + .../predis/src/Command/Redis/GETSET.php | 29 + .../predis/predis/src/Command/Redis/HDEL.php | 39 + .../predis/src/Command/Redis/HEXISTS.php | 29 + .../predis/src/Command/Redis/HEXPIRE.php | 51 + .../predis/src/Command/Redis/HEXPIREAT.php | 21 + .../predis/src/Command/Redis/HEXPIRETIME.php | 31 + .../predis/predis/src/Command/Redis/HGET.php | 29 + .../predis/src/Command/Redis/HGETALL.php | 47 + .../predis/src/Command/Redis/HINCRBY.php | 29 + .../predis/src/Command/Redis/HINCRBYFLOAT.php | 29 + .../predis/predis/src/Command/Redis/HKEYS.php | 29 + .../predis/predis/src/Command/Redis/HLEN.php | 29 + .../predis/predis/src/Command/Redis/HMGET.php | 39 + .../predis/predis/src/Command/Redis/HMSET.php | 49 + .../predis/src/Command/Redis/HPERSIST.php | 31 + .../predis/src/Command/Redis/HPEXPIRE.php | 21 + .../predis/src/Command/Redis/HPEXPIREAT.php | 21 + .../predis/src/Command/Redis/HPEXPIRETIME.php | 21 + .../predis/predis/src/Command/Redis/HPTTL.php | 21 + .../predis/src/Command/Redis/HRANDFIELD.php | 53 + .../predis/predis/src/Command/Redis/HSCAN.php | 98 + .../predis/predis/src/Command/Redis/HSET.php | 29 + .../predis/src/Command/Redis/HSETNX.php | 29 + .../predis/src/Command/Redis/HSTRLEN.php | 29 + .../predis/predis/src/Command/Redis/HTTL.php | 31 + .../predis/predis/src/Command/Redis/HVALS.php | 29 + .../predis/predis/src/Command/Redis/INCR.php | 29 + .../predis/src/Command/Redis/INCRBY.php | 29 + .../predis/src/Command/Redis/INCRBYFLOAT.php | 29 + .../predis/predis/src/Command/Redis/INFO.php | 157 + .../src/Command/Redis/Json/JSONARRAPPEND.php | 28 + .../src/Command/Redis/Json/JSONARRINDEX.php | 28 + .../src/Command/Redis/Json/JSONARRINSERT.php | 28 + .../src/Command/Redis/Json/JSONARRLEN.php | 28 + .../src/Command/Redis/Json/JSONARRPOP.php | 28 + .../src/Command/Redis/Json/JSONARRTRIM.php | 28 + .../src/Command/Redis/Json/JSONCLEAR.php | 28 + .../src/Command/Redis/Json/JSONDEBUG.php | 28 + .../predis/src/Command/Redis/Json/JSONDEL.php | 28 + .../src/Command/Redis/Json/JSONFORGET.php | 28 + .../predis/src/Command/Redis/Json/JSONGET.php | 57 + .../src/Command/Redis/Json/JSONMERGE.php | 29 + .../src/Command/Redis/Json/JSONMGET.php | 36 + .../src/Command/Redis/Json/JSONMSET.php | 28 + .../src/Command/Redis/Json/JSONNUMINCRBY.php | 28 + .../src/Command/Redis/Json/JSONOBJKEYS.php | 28 + .../src/Command/Redis/Json/JSONOBJLEN.php | 28 + .../src/Command/Redis/Json/JSONRESP.php | 28 + .../predis/src/Command/Redis/Json/JSONSET.php | 41 + .../src/Command/Redis/Json/JSONSTRAPPEND.php | 28 + .../src/Command/Redis/Json/JSONSTRLEN.php | 28 + .../src/Command/Redis/Json/JSONTOGGLE.php | 28 + .../src/Command/Redis/Json/JSONTYPE.php | 28 + .../predis/predis/src/Command/Redis/KEYS.php | 29 + .../predis/src/Command/Redis/LASTSAVE.php | 29 + .../predis/predis/src/Command/Redis/LCS.php | 69 + .../predis/src/Command/Redis/LINDEX.php | 29 + .../predis/src/Command/Redis/LINSERT.php | 29 + .../predis/predis/src/Command/Redis/LLEN.php | 29 + .../predis/predis/src/Command/Redis/LMOVE.php | 23 + .../predis/predis/src/Command/Redis/LMPOP.php | 61 + .../predis/predis/src/Command/Redis/LPOP.php | 29 + .../predis/predis/src/Command/Redis/LPUSH.php | 39 + .../predis/src/Command/Redis/LPUSHX.php | 29 + .../predis/src/Command/Redis/LRANGE.php | 29 + .../predis/predis/src/Command/Redis/LREM.php | 29 + .../predis/predis/src/Command/Redis/LSET.php | 29 + .../predis/predis/src/Command/Redis/LTRIM.php | 29 + .../predis/predis/src/Command/Redis/MGET.php | 39 + .../predis/src/Command/Redis/MIGRATE.php | 51 + .../predis/src/Command/Redis/MONITOR.php | 29 + .../predis/predis/src/Command/Redis/MOVE.php | 29 + .../predis/predis/src/Command/Redis/MSET.php | 49 + .../predis/src/Command/Redis/MSETNX.php | 27 + .../predis/predis/src/Command/Redis/MULTI.php | 29 + .../predis/src/Command/Redis/OBJECT_.php | 29 + .../predis/src/Command/Redis/PERSIST.php | 29 + .../predis/src/Command/Redis/PEXPIRE.php | 29 + .../predis/src/Command/Redis/PEXPIREAT.php | 29 + .../predis/src/Command/Redis/PEXPIRETIME.php | 29 + .../predis/predis/src/Command/Redis/PFADD.php | 39 + .../predis/src/Command/Redis/PFCOUNT.php | 39 + .../predis/src/Command/Redis/PFMERGE.php | 39 + .../predis/predis/src/Command/Redis/PING.php | 29 + .../predis/src/Command/Redis/PSETEX.php | 29 + .../predis/src/Command/Redis/PSUBSCRIBE.php | 39 + .../predis/predis/src/Command/Redis/PTTL.php | 29 + .../predis/src/Command/Redis/PUBLISH.php | 29 + .../predis/src/Command/Redis/PUBSUB.php | 62 + .../predis/src/Command/Redis/PUNSUBSCRIBE.php | 39 + .../predis/predis/src/Command/Redis/QUIT.php | 29 + .../predis/src/Command/Redis/RANDOMKEY.php | 37 + .../predis/src/Command/Redis/RENAME.php | 29 + .../predis/src/Command/Redis/RENAMENX.php | 29 + .../predis/src/Command/Redis/RESTORE.php | 29 + .../predis/predis/src/Command/Redis/RPOP.php | 29 + .../predis/src/Command/Redis/RPOPLPUSH.php | 29 + .../predis/predis/src/Command/Redis/RPUSH.php | 39 + .../predis/src/Command/Redis/RPUSHX.php | 29 + .../predis/predis/src/Command/Redis/SADD.php | 39 + .../predis/predis/src/Command/Redis/SAVE.php | 29 + .../predis/predis/src/Command/Redis/SCAN.php | 67 + .../predis/predis/src/Command/Redis/SCARD.php | 29 + .../predis/src/Command/Redis/SCRIPT.php | 29 + .../predis/predis/src/Command/Redis/SDIFF.php | 39 + .../predis/src/Command/Redis/SDIFFSTORE.php | 41 + .../predis/src/Command/Redis/SELECT.php | 29 + .../predis/src/Command/Redis/SENTINEL.php | 70 + .../predis/predis/src/Command/Redis/SET.php | 44 + .../predis/src/Command/Redis/SETBIT.php | 29 + .../predis/predis/src/Command/Redis/SETEX.php | 29 + .../predis/predis/src/Command/Redis/SETNX.php | 29 + .../predis/src/Command/Redis/SETRANGE.php | 29 + .../predis/src/Command/Redis/SHUTDOWN.php | 61 + .../predis/src/Command/Redis/SINTER.php | 39 + .../predis/src/Command/Redis/SINTERCARD.php | 43 + .../predis/src/Command/Redis/SINTERSTORE.php | 41 + .../predis/src/Command/Redis/SISMEMBER.php | 29 + .../predis/src/Command/Redis/SLAVEOF.php | 41 + .../predis/src/Command/Redis/SLOWLOG.php | 52 + .../predis/src/Command/Redis/SMEMBERS.php | 29 + .../predis/src/Command/Redis/SMISMEMBER.php | 28 + .../predis/predis/src/Command/Redis/SMOVE.php | 29 + .../predis/predis/src/Command/Redis/SORT.php | 86 + .../predis/src/Command/Redis/SORT_RO.php | 74 + .../predis/predis/src/Command/Redis/SPOP.php | 29 + .../predis/src/Command/Redis/SRANDMEMBER.php | 29 + .../predis/predis/src/Command/Redis/SREM.php | 39 + .../predis/predis/src/Command/Redis/SSCAN.php | 67 + .../predis/src/Command/Redis/STRLEN.php | 29 + .../predis/src/Command/Redis/SUBSCRIBE.php | 39 + .../predis/src/Command/Redis/SUBSTR.php | 29 + .../predis/src/Command/Redis/SUNION.php | 39 + .../predis/src/Command/Redis/SUNIONSTORE.php | 41 + .../src/Command/Redis/Search/FTAGGREGATE.php | 40 + .../src/Command/Redis/Search/FTALIASADD.php | 28 + .../src/Command/Redis/Search/FTALIASDEL.php | 28 + .../Command/Redis/Search/FTALIASUPDATE.php | 29 + .../src/Command/Redis/Search/FTALTER.php | 42 + .../src/Command/Redis/Search/FTCONFIG.php | 30 + .../src/Command/Redis/Search/FTCREATE.php | 47 + .../src/Command/Redis/Search/FTCURSOR.php | 34 + .../src/Command/Redis/Search/FTDICTADD.php | 28 + .../src/Command/Redis/Search/FTDICTDEL.php | 28 + .../src/Command/Redis/Search/FTDICTDUMP.php | 28 + .../src/Command/Redis/Search/FTDROPINDEX.php | 38 + .../src/Command/Redis/Search/FTEXPLAIN.php | 43 + .../src/Command/Redis/Search/FTINFO.php | 28 + .../src/Command/Redis/Search/FTPROFILE.php | 38 + .../src/Command/Redis/Search/FTSEARCH.php | 39 + .../src/Command/Redis/Search/FTSPELLCHECK.php | 38 + .../src/Command/Redis/Search/FTSUGADD.php | 39 + .../src/Command/Redis/Search/FTSUGDEL.php | 28 + .../src/Command/Redis/Search/FTSUGGET.php | 39 + .../src/Command/Redis/Search/FTSUGLEN.php | 28 + .../src/Command/Redis/Search/FTSYNDUMP.php | 28 + .../src/Command/Redis/Search/FTSYNUPDATE.php | 46 + .../src/Command/Redis/Search/FTTAGVALS.php | 28 + .../src/Command/Redis/TDigest/TDIGESTADD.php | 28 + .../Command/Redis/TDigest/TDIGESTBYRANK.php | 55 + .../Redis/TDigest/TDIGESTBYREVRANK.php | 55 + .../src/Command/Redis/TDigest/TDIGESTCDF.php | 57 + .../Command/Redis/TDigest/TDIGESTCREATE.php | 40 + .../src/Command/Redis/TDigest/TDIGESTINFO.php | 41 + .../src/Command/Redis/TDigest/TDIGESTMAX.php | 49 + .../Command/Redis/TDigest/TDIGESTMERGE.php | 43 + .../src/Command/Redis/TDigest/TDIGESTMIN.php | 49 + .../Command/Redis/TDigest/TDIGESTQUANTILE.php | 55 + .../src/Command/Redis/TDigest/TDIGESTRANK.php | 30 + .../Command/Redis/TDigest/TDIGESTRESET.php | 28 + .../Command/Redis/TDigest/TDIGESTREVRANK.php | 30 + .../Redis/TDigest/TDIGESTTRIMMED_MEAN.php | 50 + .../predis/predis/src/Command/Redis/TIME.php | 29 + .../predis/predis/src/Command/Redis/TOUCH.php | 39 + .../predis/predis/src/Command/Redis/TTL.php | 29 + .../predis/predis/src/Command/Redis/TYPE.php | 51 + .../src/Command/Redis/TimeSeries/TSADD.php | 39 + .../src/Command/Redis/TimeSeries/TSALTER.php | 39 + .../src/Command/Redis/TimeSeries/TSCREATE.php | 39 + .../Command/Redis/TimeSeries/TSCREATERULE.php | 40 + .../src/Command/Redis/TimeSeries/TSDECRBY.php | 41 + .../src/Command/Redis/TimeSeries/TSDEL.php | 28 + .../Command/Redis/TimeSeries/TSDELETERULE.php | 28 + .../src/Command/Redis/TimeSeries/TSGET.php | 39 + .../src/Command/Redis/TimeSeries/TSINCRBY.php | 41 + .../src/Command/Redis/TimeSeries/TSINFO.php | 39 + .../src/Command/Redis/TimeSeries/TSMADD.php | 28 + .../src/Command/Redis/TimeSeries/TSMGET.php | 37 + .../src/Command/Redis/TimeSeries/TSMRANGE.php | 39 + .../Command/Redis/TimeSeries/TSMREVRANGE.php | 26 + .../Command/Redis/TimeSeries/TSQUERYINDEX.php | 28 + .../src/Command/Redis/TimeSeries/TSRANGE.php | 39 + .../Command/Redis/TimeSeries/TSREVRANGE.php | 26 + .../predis/src/Command/Redis/TopK/TOPKADD.php | 31 + .../src/Command/Redis/TopK/TOPKINCRBY.php | 30 + .../src/Command/Redis/TopK/TOPKINFO.php | 41 + .../src/Command/Redis/TopK/TOPKLIST.php | 68 + .../src/Command/Redis/TopK/TOPKQUERY.php | 29 + .../src/Command/Redis/TopK/TOPKRESERVE.php | 47 + .../predis/src/Command/Redis/UNSUBSCRIBE.php | 39 + .../predis/src/Command/Redis/UNWATCH.php | 29 + .../predis/src/Command/Redis/WAITAOF.php | 29 + .../predis/predis/src/Command/Redis/WATCH.php | 41 + .../predis/predis/src/Command/Redis/XADD.php | 64 + .../predis/predis/src/Command/Redis/XDEL.php | 39 + .../predis/predis/src/Command/Redis/XLEN.php | 29 + .../predis/src/Command/Redis/XRANGE.php | 62 + .../predis/predis/src/Command/Redis/XREAD.php | 57 + .../predis/src/Command/Redis/XREVRANGE.php | 27 + .../predis/predis/src/Command/Redis/XTRIM.php | 54 + .../predis/predis/src/Command/Redis/ZADD.php | 44 + .../predis/predis/src/Command/Redis/ZCARD.php | 29 + .../predis/src/Command/Redis/ZCOUNT.php | 29 + .../predis/predis/src/Command/Redis/ZDIFF.php | 48 + .../predis/src/Command/Redis/ZDIFFSTORE.php | 40 + .../predis/src/Command/Redis/ZINCRBY.php | 29 + .../predis/src/Command/Redis/ZINTER.php | 35 + .../predis/src/Command/Redis/ZINTERCARD.php | 49 + .../predis/src/Command/Redis/ZINTERSTORE.php | 27 + .../predis/src/Command/Redis/ZLEXCOUNT.php | 29 + .../predis/predis/src/Command/Redis/ZMPOP.php | 79 + .../predis/src/Command/Redis/ZMSCORE.php | 34 + .../predis/src/Command/Redis/ZPOPMAX.php | 47 + .../predis/src/Command/Redis/ZPOPMIN.php | 47 + .../predis/src/Command/Redis/ZRANDMEMBER.php | 36 + .../predis/src/Command/Redis/ZRANGE.php | 109 + .../predis/src/Command/Redis/ZRANGEBYLEX.php | 54 + .../src/Command/Redis/ZRANGEBYSCORE.php | 67 + .../predis/src/Command/Redis/ZRANGESTORE.php | 57 + .../predis/predis/src/Command/Redis/ZRANK.php | 29 + .../predis/predis/src/Command/Redis/ZREM.php | 39 + .../src/Command/Redis/ZREMRANGEBYLEX.php | 29 + .../src/Command/Redis/ZREMRANGEBYRANK.php | 29 + .../src/Command/Redis/ZREMRANGEBYSCORE.php | 29 + .../predis/src/Command/Redis/ZREVRANGE.php | 27 + .../src/Command/Redis/ZREVRANGEBYLEX.php | 27 + .../src/Command/Redis/ZREVRANGEBYSCORE.php | 27 + .../predis/src/Command/Redis/ZREVRANK.php | 29 + .../predis/predis/src/Command/Redis/ZSCAN.php | 86 + .../predis/src/Command/Redis/ZSCORE.php | 29 + .../predis/src/Command/Redis/ZUNION.php | 35 + .../predis/src/Command/Redis/ZUNIONSTORE.php | 67 + .../predis/src/Command/RedisFactory.php | 112 + .../predis/src/Command/ScriptCommand.php | 108 + .../Functions/DeleteStrategy.php | 26 + .../Functions/DumpStrategy.php | 26 + .../Functions/FlushStrategy.php | 32 + .../Functions/KillStrategy.php | 26 + .../Functions/ListStrategy.php | 36 + .../Functions/LoadStrategy.php | 41 + .../Functions/RestoreStrategy.php | 32 + .../Functions/StatsStrategy.php | 26 + .../Strategy/StrategyResolverInterface.php | 25 + .../Strategy/SubcommandStrategyInterface.php | 24 + .../Strategy/SubcommandStrategyResolver.php | 52 + .../predis/src/Command/Traits/Aggregate.php | 66 + .../predis/src/Command/Traits/BitByte.php | 40 + .../Traits/BloomFilters/BucketSize.php | 57 + .../Command/Traits/BloomFilters/Capacity.php | 57 + .../src/Command/Traits/BloomFilters/Error.php | 57 + .../Command/Traits/BloomFilters/Expansion.php | 53 + .../src/Command/Traits/BloomFilters/Items.php | 45 + .../Traits/BloomFilters/MaxIterations.php | 57 + .../Command/Traits/BloomFilters/NoCreate.php | 49 + .../src/Command/Traits/By/ByArgument.php | 40 + .../src/Command/Traits/By/ByLexByScore.php | 49 + .../predis/src/Command/Traits/By/GeoBy.php | 49 + .../predis/src/Command/Traits/Count.php | 71 + .../predis/predis/src/Command/Traits/DB.php | 53 + .../Command/Traits/Expire/ExpireOptions.php | 42 + .../src/Command/Traits/From/GeoFrom.php | 49 + .../predis/src/Command/Traits/Get/Get.php | 47 + .../predis/src/Command/Traits/Json/Indent.php | 54 + .../src/Command/Traits/Json/Newline.php | 54 + .../src/Command/Traits/Json/NxXxArgument.php | 64 + .../predis/src/Command/Traits/Json/Space.php | 54 + .../predis/predis/src/Command/Traits/Keys.php | 47 + .../predis/src/Command/Traits/LeftRight.php | 60 + .../predis/src/Command/Traits/Limit/Limit.php | 54 + .../src/Command/Traits/Limit/LimitObject.php | 50 + .../src/Command/Traits/MinMaxModifier.php | 45 + .../predis/src/Command/Traits/Replace.php | 34 + .../predis/predis/src/Command/Traits/Rev.php | 44 + .../predis/src/Command/Traits/Sorting.php | 57 + .../predis/src/Command/Traits/Storedist.php | 49 + .../predis/src/Command/Traits/Timeout.php | 53 + .../predis/src/Command/Traits/To/ServerTo.php | 48 + .../predis/src/Command/Traits/Weights.php | 61 + .../src/Command/Traits/With/WithCoord.php | 49 + .../src/Command/Traits/With/WithDist.php | 45 + .../src/Command/Traits/With/WithHash.php | 45 + .../src/Command/Traits/With/WithScores.php | 68 + .../src/Command/Traits/With/WithValues.php | 34 + .../predis/src/CommunicationException.php | 85 + .../src/Configuration/Option/Aggregate.php | 114 + .../predis/src/Configuration/Option/CRC16.php | 74 + .../src/Configuration/Option/Cluster.php | 99 + .../src/Configuration/Option/Commands.php | 146 + .../src/Configuration/Option/Connections.php | 152 + .../src/Configuration/Option/Exceptions.php | 39 + .../src/Configuration/Option/Prefix.php | 49 + .../src/Configuration/Option/Replication.php | 126 + .../src/Configuration/OptionInterface.php | 39 + .../predis/src/Configuration/Options.php | 116 + .../src/Configuration/OptionsInterface.php | 63 + .../src/Connection/AbstractConnection.php | 215 + .../AggregateConnectionInterface.php | 56 + .../Connection/Cluster/ClusterInterface.php | 23 + .../src/Connection/Cluster/PredisCluster.php | 244 + .../src/Connection/Cluster/RedisCluster.php | 681 ++ .../CompositeConnectionInterface.php | 48 + .../Connection/CompositeStreamConnection.php | 125 + .../src/Connection/ConnectionException.php | 22 + .../src/Connection/ConnectionInterface.php | 65 + .../predis/predis/src/Connection/Factory.php | 194 + .../src/Connection/FactoryInterface.php | 43 + .../Connection/NodeConnectionInterface.php | 57 + .../predis/src/Connection/Parameters.php | 199 + .../src/Connection/ParametersInterface.php | 72 + .../Connection/PhpiredisSocketConnection.php | 420 + .../Connection/PhpiredisStreamConnection.php | 262 + .../predis/src/Connection/RelayConnection.php | 348 + .../predis/src/Connection/RelayMethods.php | 136 + .../Replication/MasterSlaveReplication.php | 553 ++ .../Replication/ReplicationInterface.php | 53 + .../Replication/SentinelReplication.php | 780 ++ .../src/Connection/StreamConnection.php | 374 + .../src/Connection/WebdisConnection.php | 366 + .../predis/predis/src/Monitor/Consumer.php | 179 + .../predis/src/NotSupportedException.php | 21 + .../predis/predis/src/Pipeline/Atomic.php | 118 + .../src/Pipeline/ConnectionErrorProof.php | 128 + .../predis/src/Pipeline/FireAndForget.php | 36 + .../predis/predis/src/Pipeline/Pipeline.php | 248 + .../predis/src/Pipeline/RelayAtomic.php | 69 + .../predis/src/Pipeline/RelayPipeline.php | 75 + .../predis/predis/src/PredisException.php | 22 + .../predis/src/Protocol/ProtocolException.php | 23 + .../Protocol/ProtocolProcessorInterface.php | 40 + .../Protocol/RequestSerializerInterface.php | 30 + .../src/Protocol/ResponseReaderInterface.php | 31 + .../Text/CompositeProtocolProcessor.php | 106 + .../Protocol/Text/Handler/BulkResponse.php | 54 + .../Protocol/Text/Handler/ErrorResponse.php | 33 + .../Protocol/Text/Handler/IntegerResponse.php | 46 + .../Text/Handler/MultiBulkResponse.php | 67 + .../Text/Handler/ResponseHandlerInterface.php | 32 + .../Protocol/Text/Handler/StatusResponse.php | 34 + .../Handler/StreamableMultiBulkResponse.php | 46 + .../src/Protocol/Text/ProtocolProcessor.php | 120 + .../src/Protocol/Text/RequestSerializer.php | 45 + .../src/Protocol/Text/ResponseReader.php | 110 + .../predis/src/PubSub/AbstractConsumer.php | 226 + .../predis/predis/src/PubSub/Consumer.php | 157 + .../predis/src/PubSub/DispatcherLoop.php | 171 + .../predis/src/PubSub/RelayConsumer.php | 114 + .../Replication/MissingMasterException.php | 22 + .../src/Replication/ReplicationStrategy.php | 292 + .../predis/src/Replication/RoleException.php | 23 + .../predis/predis/src/Response/Error.php | 58 + .../predis/src/Response/ErrorInterface.php | 34 + .../src/Response/Iterator/MultiBulk.php | 76 + .../Response/Iterator/MultiBulkIterator.php | 112 + .../src/Response/Iterator/MultiBulkTuple.php | 95 + .../predis/src/Response/ResponseInterface.php | 20 + .../predis/src/Response/ServerException.php | 43 + .../predis/predis/src/Response/Status.php | 78 + .../predis/predis/src/Session/Handler.php | 146 + .../Transaction/AbortedMultiExecException.php | 45 + .../predis/src/Transaction/MultiExec.php | 492 ++ .../predis/src/Transaction/MultiExecState.php | 162 + .../xmlseclibs/.github/workflows/ci.yml | 112 + .../robrichards/xmlseclibs/CHANGELOG.txt | 10 + .../vendor/robrichards/xmlseclibs/LICENSE | 2 +- .../vendor/robrichards/xmlseclibs/phpunit.xml | 7 + .../robrichards/xmlseclibs/src/XMLSecEnc.php | 6 +- .../xmlseclibs/src/XMLSecurityDSig.php | 6 +- .../xmlseclibs/src/XMLSecurityKey.php | 4 +- .../robrichards/xmlseclibs/xmlseclibs.php | 6 +- .../vendor/sebastian/cli-parser/ChangeLog.md | 30 + .../vendor/sebastian/cli-parser/LICENSE | 29 + .../vendor/sebastian/cli-parser/README.md | 22 + .../vendor/sebastian/cli-parser/SECURITY.md | 30 + .../vendor/sebastian/cli-parser/composer.json | 42 + .../sebastian/cli-parser/src/Parser.php | 206 + .../exceptions/AmbiguousOptionException.php | 26 + .../cli-parser/src/exceptions/Exception.php | 16 + .../OptionDoesNotAllowArgumentException.php | 26 + ...RequiredOptionArgumentMissingException.php | 26 + .../src/exceptions/UnknownOptionException.php | 26 + .../.psalm/baseline.xml | 9 + .../.psalm/config.xml | 15 + .../code-unit-reverse-lookup/ChangeLog.md | 45 + .../code-unit-reverse-lookup/LICENSE | 29 + .../code-unit-reverse-lookup/README.md | 22 + .../code-unit-reverse-lookup/SECURITY.md | 9 + .../code-unit-reverse-lookup/composer.json | 36 + .../code-unit-reverse-lookup/src/Wizard.php | 114 + .../vendor/sebastian/code-unit/ChangeLog.md | 78 + .../vendor/sebastian/code-unit/LICENSE | 29 + .../vendor/sebastian/code-unit/README.md | 22 + .../vendor/sebastian/code-unit/SECURITY.md | 9 + .../vendor/sebastian/code-unit/composer.json | 50 + .../code-unit/src/ClassMethodUnit.php | 24 + .../sebastian/code-unit/src/ClassUnit.php | 24 + .../sebastian/code-unit/src/CodeUnit.php | 478 ++ .../code-unit/src/CodeUnitCollection.php | 74 + .../src/CodeUnitCollectionIterator.php | 54 + .../sebastian/code-unit/src/FileUnit.php | 24 + .../sebastian/code-unit/src/FunctionUnit.php | 24 + .../code-unit/src/InterfaceMethodUnit.php | 24 + .../sebastian/code-unit/src/InterfaceUnit.php | 24 + .../vendor/sebastian/code-unit/src/Mapper.php | 259 + .../code-unit/src/TraitMethodUnit.php | 24 + .../sebastian/code-unit/src/TraitUnit.php | 24 + .../code-unit/src/exceptions/Exception.php | 16 + .../exceptions/InvalidCodeUnitException.php | 16 + .../src/exceptions/NoTraitException.php | 16 + .../src/exceptions/ReflectionException.php | 16 + .../vendor/sebastian/comparator/ChangeLog.md | 181 + .../vendor/sebastian/comparator/LICENSE | 29 + .../vendor/sebastian/comparator/README.md | 43 + .../vendor/sebastian/comparator/SECURITY.md | 30 + .../vendor/sebastian/comparator/composer.json | 63 + .../comparator/src/ArrayComparator.php | 127 + .../sebastian/comparator/src/Comparator.php | 32 + .../comparator/src/ComparisonFailure.php | 68 + .../comparator/src/DOMNodeComparator.php | 80 + .../comparator/src/DateTimeComparator.php | 73 + .../comparator/src/ExceptionComparator.php | 41 + .../sebastian/comparator/src/Factory.php | 114 + .../comparator/src/MockObjectComparator.php | 43 + .../comparator/src/NumericComparator.php | 67 + .../comparator/src/ObjectComparator.php | 88 + .../comparator/src/ResourceComparator.php | 42 + .../comparator/src/ScalarComparator.php | 81 + .../src/SplObjectStorageComparator.php | 57 + .../comparator/src/TypeComparator.php | 43 + .../comparator/src/exceptions/Exception.php | 16 + .../src/exceptions/RuntimeException.php | 14 + .../vendor/sebastian/complexity/ChangeLog.md | 68 + .../vendor/sebastian/complexity/LICENSE | 29 + .../vendor/sebastian/complexity/README.md | 22 + .../vendor/sebastian/complexity/SECURITY.md | 30 + .../vendor/sebastian/complexity/composer.json | 43 + .../sebastian/complexity/src/Calculator.php | 83 + .../complexity/src/Complexity/Complexity.php | 64 + .../src/Complexity/ComplexityCollection.php | 132 + .../ComplexityCollectionIterator.php | 51 + .../complexity/src/Exception/Exception.php | 16 + .../src/Exception/RuntimeException.php | 14 + .../Visitor/ComplexityCalculatingVisitor.php | 132 + ...CyclomaticComplexityCalculatingVisitor.php | 60 + .../vendor/sebastian/diff/ChangeLog.md | 148 + .../vendor/sebastian/diff/LICENSE | 29 + .../vendor/sebastian/diff/README.md | 206 + .../vendor/sebastian/diff/SECURITY.md | 30 + .../vendor/sebastian/diff/composer.json | 51 + .../vendor/sebastian/diff/src/Chunk.php | 124 + .../vendor/sebastian/diff/src/Diff.php | 114 + .../vendor/sebastian/diff/src/Differ.php | 239 + .../src/Exception/ConfigurationException.php | 37 + .../diff/src/Exception/Exception.php | 16 + .../Exception/InvalidArgumentException.php | 14 + .../vendor/sebastian/diff/src/Line.php | 66 + .../LongestCommonSubsequenceCalculator.php | 18 + ...ientLongestCommonSubsequenceCalculator.php | 97 + .../src/Output/AbstractChunkOutputBuilder.php | 52 + .../diff/src/Output/DiffOnlyOutputBuilder.php | 70 + .../src/Output/DiffOutputBuilderInterface.php | 19 + .../Output/StrictUnifiedDiffOutputBuilder.php | 326 + .../src/Output/UnifiedDiffOutputBuilder.php | 257 + .../vendor/sebastian/diff/src/Parser.php | 112 + ...ientLongestCommonSubsequenceCalculator.php | 82 + .../vendor/sebastian/environment/ChangeLog.md | 207 + .../vendor/sebastian/environment/LICENSE | 29 + .../vendor/sebastian/environment/README.md | 22 + .../vendor/sebastian/environment/SECURITY.md | 30 + .../sebastian/environment/composer.json | 44 + .../sebastian/environment/src/Console.php | 187 + .../sebastian/environment/src/Runtime.php | 294 + .../vendor/sebastian/exporter/ChangeLog.md | 117 + .../vendor/sebastian/exporter/LICENSE | 29 + .../vendor/sebastian/exporter/README.md | 176 + .../vendor/sebastian/exporter/SECURITY.md | 30 + .../vendor/sebastian/exporter/composer.json | 65 + .../sebastian/exporter/src/Exporter.php | 339 + .../sebastian/global-state/ChangeLog.md | 108 + .../vendor/sebastian/global-state/LICENSE | 29 + .../vendor/sebastian/global-state/README.md | 22 + .../vendor/sebastian/global-state/SECURITY.md | 30 + .../sebastian/global-state/composer.json | 52 + .../global-state/src/CodeExporter.php | 106 + .../global-state/src/ExcludeList.php | 95 + .../sebastian/global-state/src/Restorer.php | 106 + .../sebastian/global-state/src/Snapshot.php | 371 + .../global-state/src/exceptions/Exception.php | 16 + .../src/exceptions/RuntimeException.php | 14 + .../sebastian/lines-of-code/ChangeLog.md | 55 + .../vendor/sebastian/lines-of-code/LICENSE | 29 + .../vendor/sebastian/lines-of-code/README.md | 22 + .../sebastian/lines-of-code/SECURITY.md | 30 + .../sebastian/lines-of-code/composer.json | 43 + .../sebastian/lines-of-code/src/Counter.php | 90 + .../lines-of-code/src/Exception/Exception.php | 16 + .../Exception/IllogicalValuesException.php | 16 + .../src/Exception/NegativeValueException.php | 16 + .../src/Exception/RuntimeException.php | 14 + .../lines-of-code/src/LineCountingVisitor.php | 93 + .../lines-of-code/src/LinesOfCode.php | 119 + .../sebastian/object-enumerator/ChangeLog.md | 95 + .../sebastian/object-enumerator/LICENSE | 29 + .../sebastian/object-enumerator/README.md | 22 + .../sebastian/object-enumerator/SECURITY.md | 9 + .../sebastian/object-enumerator/composer.json | 43 + .../sebastian/object-enumerator/phpunit.xml | 24 + .../object-enumerator/src/Enumerator.php | 68 + .../sebastian/object-reflector/ChangeLog.md | 66 + .../vendor/sebastian/object-reflector/LICENSE | 29 + .../sebastian/object-reflector/README.md | 22 + .../sebastian/object-reflector/SECURITY.md | 9 + .../sebastian/object-reflector/composer.json | 41 + .../object-reflector/src/ObjectReflector.php | 41 + .../sebastian/recursion-context/ChangeLog.md | 47 + .../sebastian/recursion-context/LICENSE | 29 + .../sebastian/recursion-context/README.md | 20 + .../sebastian/recursion-context/SECURITY.md | 9 + .../sebastian/recursion-context/composer.json | 44 + .../recursion-context/src/Context.php | 141 + .../vendor/sebastian/type/ChangeLog.md | 176 + .../vendor/sebastian/type/LICENSE | 29 + .../vendor/sebastian/type/README.md | 22 + .../vendor/sebastian/type/SECURITY.md | 9 + .../vendor/sebastian/type/composer.json | 50 + .../vendor/sebastian/type/infection.json | 12 + .../vendor/sebastian/type/src/Parameter.php | 38 + .../sebastian/type/src/ReflectionMapper.php | 176 + .../vendor/sebastian/type/src/TypeName.php | 76 + .../type/src/exception/Exception.php | 16 + .../type/src/exception/RuntimeException.php | 14 + .../sebastian/type/src/type/CallableType.php | 182 + .../sebastian/type/src/type/FalseType.php | 42 + .../type/src/type/GenericObjectType.php | 51 + .../type/src/type/IntersectionType.php | 126 + .../sebastian/type/src/type/IterableType.php | 71 + .../sebastian/type/src/type/MixedType.php | 41 + .../sebastian/type/src/type/NeverType.php | 36 + .../sebastian/type/src/type/NullType.php | 41 + .../sebastian/type/src/type/ObjectType.php | 67 + .../sebastian/type/src/type/SimpleType.php | 83 + .../sebastian/type/src/type/StaticType.php | 64 + .../sebastian/type/src/type/TrueType.php | 42 + .../vendor/sebastian/type/src/type/Type.php | 192 + .../sebastian/type/src/type/UnionType.php | 138 + .../sebastian/type/src/type/UnknownType.php | 41 + .../sebastian/type/src/type/VoidType.php | 36 + .../vendor/sebastian/version/ChangeLog.md | 43 + .../vendor/sebastian/version/LICENSE | 29 + .../vendor/sebastian/version/README.md | 50 + .../vendor/sebastian/version/SECURITY.md | 9 + .../vendor/sebastian/version/composer.json | 37 + .../vendor/sebastian/version/src/Version.php | 93 + .../simplesamlphp/assert/src/Assert.php | 7 + .../assert/src/CustomAssertionTrait.php | 15 +- .../composer-module-installer/.gitignore | 8 - .../composer-module-installer/.php_cs.dist | 15 - .../composer-module-installer/README.md | 2 +- .../composer-module-installer/codecov.yml | 16 - .../composer-module-installer/phpcs.xml | 15 - .../composer-module-installer/phpunit.xml | 22 - .../composer-module-installer/psalm.xml | 50 - .../src/ModuleInstaller.php | 4 +- ...daddda070e6fc2370298410b63dbaf3d3a3eb.php} | 4 +- .../saml2-legacy/.github/workflows/php.yml | 195 + .../vendor/simplesamlphp/saml2-legacy/LICENSE | 458 + .../simplesamlphp/saml2-legacy/README.md | 78 + .../simplesamlphp/saml2-legacy/composer.json | 53 + .../schemas/saml-schema-assertion-2.0.xsd | 283 + .../schemas/saml-schema-authn-context-2.0.xsd | 23 + ...chema-authn-context-auth-telephony-2.0.xsd | 81 + .../saml-schema-authn-context-ip-2.0.xsd | 65 + .../saml-schema-authn-context-ippword-2.0.xsd | 67 + ...saml-schema-authn-context-kerberos-2.0.xsd | 83 + ...-authn-context-mobileonefactor-reg-2.0.xsd | 186 + ...uthn-context-mobileonefactor-unreg-2.0.xsd | 183 + ...-authn-context-mobiletwofactor-reg-2.0.xsd | 202 + ...uthn-context-mobiletwofactor-unreg-2.0.xsd | 200 + ...hema-authn-context-nomad-telephony-2.0.xsd | 81 + ...a-authn-context-personal-telephony-2.0.xsd | 80 + .../saml-schema-authn-context-pgp-2.0.xsd | 83 + .../saml-schema-authn-context-ppt-2.0.xsd | 81 + .../saml-schema-authn-context-pword-2.0.xsd | 64 + .../saml-schema-authn-context-session-2.0.xsd | 64 + ...aml-schema-authn-context-smartcard-2.0.xsd | 64 + ...-schema-authn-context-smartcardpki-2.0.xsd | 129 + ...l-schema-authn-context-softwarepki-2.0.xsd | 129 + .../saml-schema-authn-context-spki-2.0.xsd | 83 + .../saml-schema-authn-context-srp-2.0.xsd | 82 + .../saml-schema-authn-context-sslcert-2.0.xsd | 97 + ...aml-schema-authn-context-telephony-2.0.xsd | 79 + ...saml-schema-authn-context-timesync-2.0.xsd | 105 + .../saml-schema-authn-context-types-2.0.xsd | 821 ++ .../saml-schema-authn-context-x509-2.0.xsd | 83 + .../saml-schema-authn-context-xmldsig-2.0.xsd | 83 + .../schemas/saml-schema-dce-2.0.xsd | 29 + .../schemas/saml-schema-ecp-2.0.xsd | 57 + .../schemas/saml-schema-metadata-2.0.xsd | 337 + .../schemas/saml-schema-protocol-2.0.xsd | 302 + .../schemas/saml-schema-x500-2.0.xsd | 20 + .../schemas/saml-schema-xacml-2.0.xsd | 19 + .../saml2-legacy/schemas/xenc-schema.xsd | 146 + .../saml2-legacy/schemas/xml.xsd | 287 + .../schemas/xmldsig-core-schema.xsd | 318 + .../src/SAML2/ArtifactResolve.php | 74 + .../src/SAML2/ArtifactResponse.php | 87 + .../saml2-legacy/src/SAML2/Assertion.php | 1821 ++++ .../src/SAML2/Assertion/Decrypter.php | 108 + .../Exception/InvalidAssertionException.php | 11 + .../InvalidSubjectConfirmationException.php | 11 + .../Exception/NotDecryptedException.php | 11 + .../src/SAML2/Assertion/Processor.php | 198 + .../src/SAML2/Assertion/ProcessorBuilder.php | 160 + .../Transformer/DecodeBase64Transformer.php | 61 + .../NameIdDecryptionTransformer.php | 117 + .../Assertion/Transformer/Transformer.php | 17 + .../Transformer/TransformerChain.php | 77 + .../AssertionConstraintValidator.php | 17 + .../Validation/AssertionValidator.php | 75 + .../ConstraintValidator/NotBefore.php | 29 + .../ConstraintValidator/NotOnOrAfter.php | 29 + .../SessionNotOnOrAfter.php | 30 + .../ConstraintValidator/SpIsValidAudience.php | 54 + .../SubjectConfirmationMethod.php | 30 + .../SubjectConfirmationNotBefore.php | 34 + .../SubjectConfirmationNotOnOrAfter.php | 34 + .../SubjectConfirmationRecipientMatches.php | 53 + .../SubjectConfirmationResponseToMatches.php | 65 + .../src/SAML2/Assertion/Validation/Result.php | 46 + ...SubjectConfirmationConstraintValidator.php | 20 + .../SubjectConfirmationValidator.php | 78 + .../saml2-legacy/src/SAML2/AttributeQuery.php | 187 + .../saml2-legacy/src/SAML2/AuthnRequest.php | 934 ++ .../saml2-legacy/src/SAML2/Binding.php | 167 + .../InvalidCertificateStructureException.php | 16 + .../Exception/InvalidKeyUsageException.php | 29 + .../Exception/NoKeysFoundException.php | 14 + .../src/SAML2/Certificate/Key.php | 129 + .../src/SAML2/Certificate/KeyCollection.php | 31 + .../src/SAML2/Certificate/KeyLoader.php | 166 + .../src/SAML2/Certificate/PrivateKey.php | 44 + .../SAML2/Certificate/PrivateKeyLoader.php | 87 + .../src/SAML2/Certificate/X509.php | 55 + .../src/SAML2/Compat/AbstractContainer.php | 84 + .../src/SAML2/Compat/ContainerSingleton.php | 48 + .../src/SAML2/Compat/MockContainer.php | 136 + .../src/SAML2/Compat/Ssp/Container.php | 135 + .../src/SAML2/Compat/Ssp/Logger.php | 201 + .../src/SAML2/Configuration/ArrayAdapter.php | 50 + .../Configuration/CertificateProvider.php | 37 + .../Configuration/DecryptionProvider.php | 35 + .../src/SAML2/Configuration/Destination.php | 47 + .../SAML2/Configuration/EntityIdProvider.php | 16 + .../SAML2/Configuration/IdentityProvider.php | 124 + .../Configuration/IdentityProviderAware.php | 18 + .../src/SAML2/Configuration/PrivateKey.php | 113 + .../src/SAML2/Configuration/Queryable.php | 31 + .../SAML2/Configuration/ServiceProvider.php | 117 + .../Configuration/ServiceProviderAware.php | 17 + .../Configuration/SimpleSAMLConverter.php | 160 + .../saml2-legacy/src/SAML2/Constants.php | 455 + .../src/SAML2/DOMDocumentFactory.php | 127 + .../src/SAML2/EncryptedAssertion.php | 152 + .../Exception/InvalidArgumentException.php | 27 + .../Exception/MetadataExpiredException.php | 12 + .../Protocol/AuthnFailedException.php | 23 + .../InvalidAttrNameOrValueException.php | 24 + .../Protocol/InvalidNameIDPolicyException.php | 23 + .../Protocol/NoAuthnContextException.php | 23 + .../Protocol/NoAvailableIDPException.php | 24 + .../Exception/Protocol/NoPassiveException.php | 24 + .../Protocol/NoSupportedIDPException.php | 24 + .../Protocol/PartialLogoutException.php | 24 + .../Protocol/ProxyCountExceededException.php | 24 + .../Protocol/RequestDeniedException.php | 24 + .../Protocol/RequestUnsupportedException.php | 23 + .../RequestVersionDeprecatedException.php | 24 + .../RequestVersionTooHighException.php | 24 + .../RequestVersionTooLowException.php | 24 + .../ResourceNotRecognizedException.php | 24 + .../Protocol/TooManyResponsesException.php | 24 + .../Protocol/UnknownAttrProfileException.php | 24 + .../Protocol/UnknownPrincipalException.php | 24 + .../Protocol/UnsupportedBindingException.php | 24 + .../Exception/ProtocolViolationException.php | 14 + .../src/SAML2/Exception/RuntimeException.php | 14 + .../src/SAML2/Exception/Throwable.php | 14 + .../Exception/UnparseableXmlException.php | 38 + .../saml2-legacy/src/SAML2/HTTPArtifact.php | 200 + .../saml2-legacy/src/SAML2/HTTPPost.php | 109 + .../saml2-legacy/src/SAML2/HTTPRedirect.php | 254 + .../saml2-legacy/src/SAML2/LogoutRequest.php | 343 + .../saml2-legacy/src/SAML2/LogoutResponse.php | 27 + .../saml2-legacy/src/SAML2/Message.php | 629 ++ .../saml2-legacy/src/SAML2/Request.php | 18 + .../saml2-legacy/src/SAML2/Response.php | 94 + .../Exception/InvalidResponseException.php | 11 + .../Exception/InvalidSignatureException.php | 9 + .../Exception/NoAssertionsFoundException.php | 9 + .../Exception/PreconditionNotMetException.php | 27 + .../UnencryptedAssertionFoundException.php | 12 + .../Exception/UnsignedResponseException.php | 11 + .../src/SAML2/Response/Processor.php | 173 + .../Validation/ConstraintValidator.php | 17 + .../DestinationMatches.php | 50 + .../ConstraintValidator/IsSuccessful.php | 60 + .../Validation/PreconditionValidator.php | 29 + .../src/SAML2/Response/Validation/Result.php | 47 + .../SAML2/Response/Validation/Validator.php | 40 + .../saml2-legacy/src/SAML2/SOAP.php | 126 + .../saml2-legacy/src/SAML2/SOAPClient.php | 280 + .../Signature/AbstractChainedValidator.php | 77 + .../src/SAML2/Signature/ChainedValidator.php | 29 + .../MissingConfigurationException.php | 11 + .../SAML2/Signature/PublicKeyValidator.php | 85 + .../src/SAML2/Signature/Validator.php | 55 + .../src/SAML2/Signature/ValidatorChain.php | 87 + .../SAML2/Signature/ValidatorInterface.php | 24 + .../saml2-legacy/src/SAML2/SignedElement.php | 92 + .../src/SAML2/SignedElementHelper.php | 275 + .../saml2-legacy/src/SAML2/StatusResponse.php | 199 + .../saml2-legacy/src/SAML2/SubjectQuery.php | 120 + .../src/SAML2/Utilities/ArrayCollection.php | 200 + .../src/SAML2/Utilities/Certificate.php | 39 + .../src/SAML2/Utilities/Collection.php | 91 + .../saml2-legacy/src/SAML2/Utilities/File.php | 39 + .../src/SAML2/Utilities/Temporal.php | 19 + .../saml2-legacy/src/SAML2/Utils.php | 740 ++ .../saml2-legacy/src/SAML2/XML/Chunk.php | 188 + .../saml2-legacy/src/SAML2/XML/alg/Common.php | 17 + .../src/SAML2/XML/alg/DigestMethod.php | 88 + .../src/SAML2/XML/alg/SigningMethod.php | 168 + .../saml2-legacy/src/SAML2/XML/ds/KeyInfo.php | 164 + .../saml2-legacy/src/SAML2/XML/ds/KeyName.php | 75 + .../src/SAML2/XML/ds/X509Certificate.php | 75 + .../src/SAML2/XML/ds/X509Data.php | 120 + .../src/SAML2/XML/ecp/Response.php | 110 + .../XML/md/AdditionalMetadataLocation.php | 114 + .../SAML2/XML/md/AffiliationDescriptor.php | 286 + .../XML/md/AttributeAuthorityDescriptor.php | 286 + .../XML/md/AttributeConsumingService.php | 251 + .../SAML2/XML/md/AuthnAuthorityDescriptor.php | 196 + .../src/SAML2/XML/md/ContactPerson.php | 444 + .../src/SAML2/XML/md/EndpointType.php | 260 + .../src/SAML2/XML/md/EntitiesDescriptor.php | 296 + .../src/SAML2/XML/md/EntityDescriptor.php | 511 ++ .../src/SAML2/XML/md/Extensions.php | 103 + .../src/SAML2/XML/md/IDPSSODescriptor.php | 331 + .../src/SAML2/XML/md/IndexedEndpointType.php | 120 + .../src/SAML2/XML/md/KeyDescriptor.php | 190 + .../src/SAML2/XML/md/Organization.php | 206 + .../src/SAML2/XML/md/PDPDescriptor.php | 196 + .../src/SAML2/XML/md/RequestedAttribute.php | 84 + .../src/SAML2/XML/md/RoleDescriptor.php | 440 + .../src/SAML2/XML/md/SPSSODescriptor.php | 223 + .../src/SAML2/XML/md/SSODescriptorType.php | 243 + .../SAML2/XML/md/UnknownRoleDescriptor.php | 49 + .../src/SAML2/XML/mdattr/EntityAttributes.php | 115 + .../src/SAML2/XML/mdrpi/Common.php | 16 + .../src/SAML2/XML/mdrpi/PublicationInfo.php | 201 + .../src/SAML2/XML/mdrpi/RegistrationInfo.php | 166 + .../src/SAML2/XML/mdui/Common.php | 17 + .../src/SAML2/XML/mdui/DiscoHints.php | 208 + .../src/SAML2/XML/mdui/Keywords.php | 146 + .../saml2-legacy/src/SAML2/XML/mdui/Logo.php | 192 + .../src/SAML2/XML/mdui/UIInfo.php | 345 + .../src/SAML2/XML/saml/Attribute.php | 230 + .../src/SAML2/XML/saml/AttributeValue.php | 188 + .../src/SAML2/XML/saml/BaseIDType.php | 81 + .../SAML2/XML/saml/IDNameQualifiersTrait.php | 80 + .../src/SAML2/XML/saml/Issuer.php | 135 + .../src/SAML2/XML/saml/NameID.php | 22 + .../src/SAML2/XML/saml/NameIDType.php | 270 + .../SAML2/XML/saml/SubjectConfirmation.php | 171 + .../XML/saml/SubjectConfirmationData.php | 302 + .../src/SAML2/XML/samlp/Extensions.php | 58 + .../src/SAML2/XML/shibmd/Scope.php | 127 + .../saml2-legacy/src/_autoload.php | 37 + .../saml2-legacy/tests/autoload.php | 12 + .../corrupted-metadata-selfsigned.xml | 27 + .../xml/metadata/expired-metadata.xml | 23 + .../metadata/valid-metadata-selfsigned.xml | 27 + .../vendor/simplesamlphp/saml2/composer.json | 3 + .../saml2/src/SAML2/DOMDocumentFactory.php | 14 +- .../simplesamlphp-test-framework/LICENSE | 459 + .../simplesamlphp-test-framework/README.md | 2 + .../composer.json | 50 + .../lib/ArrayLogger.php | 34 + .../lib/BuiltInServer.php | 229 + .../lib/ClearStateTestCase.php | 62 + .../lib/InMemoryStore.php | 81 + .../lib/ReduceSpillOverTest.php | 48 + .../lib/SigningTestCase.php | 119 + .../lib/SimpleTestLogger.php | 73 + .../lib/StateClearer.php | 95 + .../saml20-idp-remote_cert_expired.php | 29 + .../saml20-idp-remote_cert_selfsigned.php | 29 + .../saml20-idp-remote_cert_signed.php | 29 + .../saml20-idp-remote_expired.php | 30 + .../phpcs-simplesamlphp.xml | 27 + .../phpstan-dev.neon | 4 + .../simplesamlphp-test-framework/phpstan.neon | 4 + .../src/TemplateTest.php | 82 + .../stubs/krb5.php | 257 + .../stubs/memcache.php | 458 + .../stubs/memcached.php | 1309 +++ .../stubs/predis.php | 299 + .../stubs/radius.php | 441 + .../stubs/soap.php | 882 ++ .../xml-common/src/AbstractElement.php | 2 +- .../xml-common/src/Base64ElementTrait.php | 3 +- .../xml-common/src/BooleanElementTrait.php | 2 +- .../simplesamlphp/xml-common/src/Chunk.php | 6 +- .../xml-common/src/Constants.php | 1 + .../xml-common/src/DOMDocumentFactory.php | 50 +- .../src/ExtendableAttributesTrait.php | 2 +- .../xml-common/src/ExtendableElementTrait.php | 2 +- .../xml-common/src/IntegerElementTrait.php | 35 + .../src/LocalizedStringElementTrait.php | 4 +- .../xml-common/src/QNameElementTrait.php | 4 +- .../src/SerializableElementInterface.php | 2 +- .../src/SerializableElementTrait.php | 2 +- .../xml-common/src/StringElementTrait.php | 4 +- .../xml-common/src/URIElementTrait.php | 2 +- .../simplesamlphp/xml-security/composer.json | 4 +- .../xml-security/src/Constants.php | 3 +- .../xml-security/src/Key/PrivateKey.php | 2 +- .../xml-security/src/Utils/XML.php | 6 +- .../src/XML/EncryptedElementTrait.php | 4 +- .../src/XML/SignedElementInterface.php | 2 +- .../src/XML/SignedElementTrait.php | 2 +- .../src/XML/ds/AbstractKeyInfoType.php | 117 + .../src/XML/ds/CanonicalizationMethod.php | 2 +- .../xml-security/src/XML/ds/DigestMethod.php | 2 +- .../xml-security/src/XML/ds/DsObject.php | 2 +- .../xml-security/src/XML/ds/KeyInfo.php | 97 +- .../xml-security/src/XML/ds/KeyValue.php | 2 +- .../xml-security/src/XML/ds/Manifest.php | 2 +- .../xml-security/src/XML/ds/RSAKeyValue.php | 2 +- .../xml-security/src/XML/ds/Reference.php | 2 +- .../src/XML/ds/RetrievalMethod.php | 2 +- .../xml-security/src/XML/ds/Signature.php | 2 +- .../src/XML/ds/SignatureMethod.php | 2 +- .../src/XML/ds/SignatureProperties.php | 2 +- .../src/XML/ds/SignatureProperty.php | 2 +- .../src/XML/ds/SignatureValue.php | 2 +- .../xml-security/src/XML/ds/SignedInfo.php | 2 +- .../xml-security/src/XML/ds/Transform.php | 8 +- .../xml-security/src/XML/ds/Transforms.php | 2 +- .../xml-security/src/XML/ds/X509Data.php | 2 +- .../src/XML/ds/X509IssuerSerial.php | 2 +- .../src/XML/ds/X509SerialNumber.php | 2 +- .../xml-security/src/XML/ds/XPath.php | 2 +- .../src/XML/dsig11/KeyInfoReference.php | 2 +- .../src/XML/dsig11/X509Digest.php | 2 +- .../src/XML/ec/InclusiveNamespaces.php | 2 +- .../xml-security/src/XML/element.registry.php | 4 +- .../XML/xenc/AbstractAgreementMethodType.php | 159 + .../src/XML/xenc/AbstractDHKeyValueType.php | 188 + .../src/XML/xenc/AbstractEncryptedType.php | 2 +- .../src/XML/xenc/AbstractEncryptionMethod.php | 2 +- .../xenc/AbstractEncryptionPropertiesType.php | 2 +- .../xenc/AbstractEncryptionPropertyType.php | 2 +- .../src/XML/xenc/AbstractReference.php | 2 +- .../src/XML/xenc/AgreementMethod.php | 14 + .../xml-security/src/XML/xenc/CipherData.php | 2 +- .../src/XML/xenc/CipherReference.php | 2 +- .../xml-security/src/XML/xenc/DHKeyValue.php | 14 + .../src/XML/xenc/EncryptedKey.php | 2 +- .../xml-security/src/XML/xenc/Generator.php | 26 + .../xml-security/src/XML/xenc/KANonce.php | 29 + .../xml-security/src/XML/xenc/KeySize.php | 2 +- .../src/XML/xenc/OriginatorKeyInfo.php | 71 + .../xml-security/src/XML/xenc/P.php | 26 + .../xml-security/src/XML/xenc/PgenCounter.php | 29 + .../xml-security/src/XML/xenc/Q.php | 26 + .../src/XML/xenc/RecipientKeyInfo.php | 71 + .../src/XML/xenc/ReferenceList.php | 2 +- .../xml-security/src/XML/xenc/Seed.php | 29 + .../xml-security/src/XML/xenc/Transforms.php | 2 +- .../xml-security/src/XML/xenc/XencPublic.php | 29 + .../resources/xml/xenc_AgreementMethod.xml | 22 + .../tests/resources/xml/xenc_DHKeyValue.xml | 8 + .../tests/resources/xml/xenc_Generator.xml | 1 + .../tests/resources/xml/xenc_KA-Nonce.xml | 1 + .../resources/xml/xenc_OriginatorKeyInfo.xml | 8 + .../tests/resources/xml/xenc_P.xml | 1 + .../tests/resources/xml/xenc_Public.xml | 1 + .../tests/resources/xml/xenc_Q.xml | 1 + .../resources/xml/xenc_RecipientKeyInfo.xml | 8 + .../tests/resources/xml/xenc_pgenCounter.xml | 1 + .../tests/resources/xml/xenc_seed.xml | 1 + .../slevomat/coding-standard/.editorconfig | 10 + .../slevomat/coding-standard/.typos.toml | 10 + .../coding-standard/CODE_OF_CONDUCT.md | 74 + .../slevomat/coding-standard/LICENSE.md | 8 + .../vendor/slevomat/coding-standard/README.md | 319 + .../Helpers/Annotation.php | 66 + .../Helpers/AnnotationHelper.php | 366 + .../Helpers/AnnotationTypeHelper.php | 409 + .../Helpers/ArrayHelper.php | 232 + .../Helpers/ArrayKeyValue.php | 172 + .../Helpers/Attribute.php | 60 + .../Helpers/AttributeHelper.php | 153 + .../Helpers/CatchHelper.php | 83 + .../Helpers/ClassHelper.php | 120 + .../Helpers/Comment.php | 33 + .../Helpers/CommentHelper.php | 102 + .../Helpers/ConditionHelper.php | 355 + .../Helpers/ConstantHelper.php | 79 + .../Helpers/DocCommentHelper.php | 275 + .../Helpers/EmptyFileException.php | 33 + .../Helpers/FixerHelper.php | 55 + .../Helpers/FunctionHelper.php | 572 ++ .../Helpers/IdentificatorHelper.php | 216 + .../Helpers/IndentationHelper.php | 106 + .../Helpers/NamespaceHelper.php | 201 + .../Helpers/ParameterHelper.php | 34 + .../Helpers/ParsedDocComment.php | 108 + .../Helpers/PhpDocParserHelper.php | 82 + .../Helpers/PropertyHelper.php | 140 + .../Helpers/ReferencedName.php | 75 + .../Helpers/ReferencedNameHelper.php | 532 ++ .../Helpers/ScopeHelper.php | 65 + .../Helpers/SniffLocalCache.php | 49 + .../Helpers/SniffSettingsHelper.php | 90 + .../Helpers/StringHelper.php | 25 + .../Helpers/SuppressHelper.php | 83 + .../Helpers/TernaryOperatorHelper.php | 182 + .../Helpers/TokenHelper.php | 534 ++ .../TokenPointerOutOfBoundsException.php | 47 + .../Helpers/TypeHelper.php | 35 + .../Helpers/TypeHint.php | 59 + .../Helpers/TypeHintHelper.php | 417 + .../Helpers/UseStatement.php | 135 + .../Helpers/UseStatementHelper.php | 270 + .../Helpers/VariableHelper.php | 178 + .../Helpers/YodaHelper.php | 358 + .../AlphabeticallySortedByKeysSniff.php | 85 + .../Sniffs/Arrays/ArrayAccessSniff.php | 76 + .../DisallowImplicitArrayCreationSniff.php | 280 + .../Arrays/DisallowPartiallyKeyedSniff.php | 42 + ...MultiLineArrayEndBracketPlacementSniff.php | 60 + .../Arrays/SingleLineArrayWhitespaceSniff.php | 228 + .../Sniffs/Arrays/TrailingArrayCommaSniff.php | 80 + .../AttributeAndTargetSpacingSniff.php | 120 + .../Attributes/AttributesOrderSniff.php | 197 + .../DisallowAttributesJoiningSniff.php | 72 + ...DisallowMultipleAttributesPerLineSniff.php | 82 + .../RequireAttributeAfterDocCommentSniff.php | 86 + .../Classes/AbstractMethodSignature.php | 69 + ...ractPropertyConstantAndEnumCaseSpacing.php | 137 + .../Classes/BackedEnumTypeSpacingSniff.php | 121 + .../Classes/ClassConstantVisibilitySniff.php | 87 + .../Sniffs/Classes/ClassLengthSniff.php | 64 + .../Classes/ClassMemberSpacingSniff.php | 278 + .../Sniffs/Classes/ClassStructureSniff.php | 666 ++ .../Sniffs/Classes/ConstantSpacingSniff.php | 79 + ...allowConstructorPropertyPromotionSniff.php | 69 + ...llowLateStaticBindingForConstantsSniff.php | 71 + .../DisallowMultiConstantDefinitionSniff.php | 128 + .../DisallowMultiPropertyDefinitionSniff.php | 168 + ...llowStringExpressionPropertyFetchSniff.php | 84 + .../EmptyLinesAroundClassBracesSniff.php | 159 + .../Sniffs/Classes/EnumCaseSpacingSniff.php | 54 + .../Classes/ForbiddenPublicPropertySniff.php | 77 + .../Sniffs/Classes/MethodSpacingSniff.php | 133 + .../Classes/MissingClassGroupsException.php | 23 + .../Classes/ModernClassNameReferenceSniff.php | 178 + .../Sniffs/Classes/ParentCallSpacingSniff.php | 122 + .../Classes/PropertyDeclarationSniff.php | 401 + .../Sniffs/Classes/PropertySpacingSniff.php | 87 + .../Classes/RequireAbstractOrFinalSniff.php | 62 + ...quireConstructorPropertyPromotionSniff.php | 398 + .../RequireMultiLineMethodSignatureSniff.php | 176 + .../Classes/RequireSelfReferenceSniff.php | 118 + .../RequireSingleLineMethodSignatureSniff.php | 130 + .../SuperfluousAbstractClassNamingSniff.php | 70 + .../Classes/SuperfluousErrorNamingSniff.php | 55 + .../SuperfluousExceptionNamingSniff.php | 55 + .../SuperfluousInterfaceNamingSniff.php | 63 + .../Classes/SuperfluousTraitNamingSniff.php | 50 + .../Classes/TraitUseDeclarationSniff.php | 101 + .../Sniffs/Classes/TraitUseSpacingSniff.php | 304 + .../UnsupportedClassGroupException.php | 16 + .../Classes/UselessLateStaticBindingSniff.php | 72 + .../AbstractRequireOneLineDocComment.php | 137 + .../Sniffs/Commenting/AnnotationNameSniff.php | 299 + .../DeprecatedAnnotationDeclarationSniff.php | 50 + .../DisallowCommentAfterCodeSniff.php | 135 + ...DisallowOneLinePropertyDocCommentSniff.php | 108 + .../Commenting/DocCommentSpacingSniff.php | 781 ++ .../Sniffs/Commenting/EmptyCommentSniff.php | 198 + .../Commenting/ForbiddenAnnotationsSniff.php | 132 + .../Commenting/ForbiddenCommentsSniff.php | 132 + .../InlineDocCommentDeclarationSniff.php | 495 ++ .../RequireOneLineDocCommentSniff.php | 19 + .../RequireOneLinePropertyDocCommentSniff.php | 61 + .../UselessFunctionDocCommentSniff.php | 143 + .../UselessInheritDocCommentSniff.php | 118 + .../Sniffs/Complexity/CognitiveSniff.php | 310 + .../AbstractControlStructureSpacing.php | 510 ++ .../AbstractLineCondition.php | 128 + .../AssignmentInConditionSniff.php | 115 + .../BlockControlStructureSpacingSniff.php | 113 + ...inueWithoutIntegerOperandInSwitchSniff.php | 63 + .../ControlStructures/DisallowEmptySniff.php | 33 + .../DisallowNullSafeObjectOperatorSniff.php | 33 + .../DisallowShortTernaryOperatorSniff.php | 72 + ...wTrailingMultiLineTernaryOperatorSniff.php | 88 + .../DisallowYodaComparisonSniff.php | 88 + .../ControlStructures/EarlyExitSniff.php | 480 ++ .../JumpStatementsSpacingSniff.php | 282 + .../LanguageConstructWithParenthesesSniff.php | 102 + .../NewWithParenthesesSniff.php | 114 + .../NewWithoutParenthesesSniff.php | 106 + .../RequireMultiLineConditionSniff.php | 188 + .../RequireMultiLineTernaryOperatorSniff.php | 178 + .../RequireNullCoalesceEqualOperatorSniff.php | 99 + .../RequireNullCoalesceOperatorSniff.php | 217 + .../RequireNullSafeObjectOperatorSniff.php | 513 ++ .../RequireShortTernaryOperatorSniff.php | 87 + .../RequireSingleLineConditionSniff.php | 105 + .../RequireTernaryOperatorSniff.php | 266 + .../RequireYodaComparisonSniff.php | 74 + .../UnsupportedKeywordException.php | 17 + .../UselessIfConditionWithReturnSniff.php | 216 + .../UselessTernaryOperatorSniff.php | 105 + .../Sniffs/Exceptions/DeadCatchSniff.php | 56 + .../DisallowNonCapturingCatchSniff.php | 46 + .../ReferenceThrowableOnlySniff.php | 139 + .../RequireNonCapturingCatchSniff.php | 170 + .../Sniffs/Files/FileLengthSniff.php | 63 + .../Files/FilepathNamespaceExtractor.php | 88 + .../Sniffs/Files/LineLengthSniff.php | 138 + .../Files/TypeNameMatchesFileNameSniff.php | 188 + .../Sniffs/Functions/AbstractLineCall.php | 102 + .../ArrowFunctionDeclarationSniff.php | 181 + .../Functions/DisallowArrowFunctionSniff.php | 33 + .../Functions/DisallowEmptyFunctionSniff.php | 69 + .../Functions/DisallowNamedArgumentsSniff.php | 40 + .../DisallowTrailingCommaInCallSniff.php | 95 + ...DisallowTrailingCommaInClosureUseSniff.php | 86 + ...isallowTrailingCommaInDeclarationSniff.php | 74 + .../Sniffs/Functions/FunctionLengthSniff.php | 68 + .../Functions/NamedArgumentSpacingSniff.php | 79 + .../Functions/RequireArrowFunctionSniff.php | 158 + .../Functions/RequireMultiLineCallSniff.php | 243 + .../Functions/RequireSingleLineCallSniff.php | 200 + .../RequireTrailingCommaInCallSniff.php | 104 + .../RequireTrailingCommaInClosureUseSniff.php | 85 + ...RequireTrailingCommaInDeclarationSniff.php | 77 + .../Sniffs/Functions/StaticClosureSniff.php | 103 + .../Sniffs/Functions/StrictCallSniff.php | 127 + ...dInheritedVariablePassedToClosureSniff.php | 150 + .../Sniffs/Functions/UnusedParameterSniff.php | 107 + .../UselessParameterDefaultValueSniff.php | 88 + .../AbstractFullyQualifiedGlobalReference.php | 172 + .../AlphabeticallySortedUsesSniff.php | 240 + .../Namespaces/DisallowGroupUseSniff.php | 37 + ...llyQualifiedClassNameInAnnotationSniff.php | 173 + .../FullyQualifiedExceptionsSniff.php | 162 + .../FullyQualifiedGlobalConstantsSniff.php | 26 + .../FullyQualifiedGlobalFunctionsSniff.php | 45 + .../Namespaces/MultipleUsesPerLineSniff.php | 48 + .../Namespaces/NamespaceDeclarationSniff.php | 147 + .../Namespaces/NamespaceSpacingSniff.php | 164 + .../ReferenceUsedNamesOnlySniff.php | 779 ++ .../RequireOneNamespaceInFileSniff.php | 58 + .../Sniffs/Namespaces/UnusedUsesSniff.php | 294 + .../UseDoesNotStartWithBackslashSniff.php | 74 + .../Namespaces/UseFromSameNamespaceSniff.php | 90 + .../UseOnlyWhitelistedNamespacesSniff.php | 78 + .../Sniffs/Namespaces/UseSpacingSniff.php | 343 + .../Sniffs/Namespaces/UselessAliasSniff.php | 82 + .../DisallowNumericLiteralSeparatorSniff.php | 55 + .../RequireNumericLiteralSeparatorSniff.php | 82 + .../Operators/DisallowEqualOperatorsSniff.php | 60 + ...lowIncrementAndDecrementOperatorsSniff.php | 65 + .../NegationOperatorSpacingSniff.php | 125 + ...RequireCombinedAssignmentOperatorSniff.php | 149 + ...oneIncrementAndDecrementOperatorsSniff.php | 118 + .../Operators/SpreadOperatorSpacingSniff.php | 71 + .../DisallowDirectMagicInvokeCallSniff.php | 67 + .../Sniffs/PHP/DisallowReferenceSniff.php | 99 + .../Sniffs/PHP/ForbiddenClassesSniff.php | 272 + ...ptimizedFunctionsWithoutUnpackingSniff.php | 114 + .../Sniffs/PHP/ReferenceSpacingSniff.php | 131 + .../PHP/RequireExplicitAssertionSniff.php | 472 ++ .../Sniffs/PHP/RequireNowdocSniff.php | 74 + .../Sniffs/PHP/ShortListSniff.php | 50 + .../Sniffs/PHP/TypeCastSniff.php | 119 + .../Sniffs/PHP/UselessParenthesesSniff.php | 579 ++ .../Sniffs/PHP/UselessSemicolonSniff.php | 160 + .../Strings/DisallowVariableParsingSniff.php | 154 + .../Sniffs/TestCase.php | 236 + .../TypeHints/DeclareStrictTypesSniff.php | 262 + .../DisallowArrayTypeHintSyntaxSniff.php | 307 + .../TypeHints/DisallowMixedTypeHintSniff.php | 72 + .../Sniffs/TypeHints/LongTypeHintsSniff.php | 92 + .../NullTypeHintOnLastPositionSniff.php | 109 + .../NullableTypeForNullDefaultValueSniff.php | 125 + .../TypeHints/ParameterTypeHintSniff.php | 688 ++ .../ParameterTypeHintSpacingSniff.php | 154 + .../TypeHints/PropertyTypeHintSniff.php | 692 ++ .../Sniffs/TypeHints/ReturnTypeHintSniff.php | 732 ++ .../TypeHints/ReturnTypeHintSpacingSniff.php | 172 + .../TypeHints/UnionTypeHintFormatSniff.php | 248 + .../UselessConstantTypeHintSniff.php | 85 + .../DisallowSuperGlobalVariableSniff.php | 52 + .../DisallowVariableVariableSniff.php | 35 + .../DuplicateAssignmentToVariableSniff.php | 70 + .../Sniffs/Variables/UnusedVariableSniff.php | 709 ++ .../Sniffs/Variables/UselessVariableSniff.php | 417 + .../Whitespaces/DuplicateSpacesSniff.php | 175 + .../SlevomatCodingStandard/ruleset.xml | 4 + .../coding-standard/autoload-bootstrap.php | 11 + .../slevomat/coding-standard/composer.json | 50 + .../slevomat/coding-standard/doc/arrays.md | 44 + .../coding-standard/doc/attributes.md | 48 + .../slevomat/coding-standard/doc/classes.md | 284 + .../coding-standard/doc/commenting.md | 118 + .../coding-standard/doc/complexity.md | 10 + .../coding-standard/doc/control-structures.md | 258 + .../coding-standard/doc/exceptions.md | 31 + .../slevomat/coding-standard/doc/files.md | 59 + .../slevomat/coding-standard/doc/functions.md | 136 + .../coding-standard/doc/namespaces.md | 186 + .../slevomat/coding-standard/doc/numbers.md | 16 + .../slevomat/coding-standard/doc/operators.md | 33 + .../slevomat/coding-standard/doc/php.md | 80 + .../slevomat/coding-standard/doc/strings.md | 11 + .../coding-standard/doc/type-hints.md | 130 + .../slevomat/coding-standard/doc/variables.md | 31 + .../coding-standard/doc/whitespaces.md | 13 + .../squizlabs/php_codesniffer/CHANGELOG.md | 7501 +++++++++++++++++ .../php_codesniffer/CodeSniffer.conf | 5 + .../php_codesniffer/CodeSniffer.conf.dist | 9 + .../squizlabs/php_codesniffer/README.md | 153 + .../squizlabs/php_codesniffer/autoload.php | 345 + .../squizlabs/php_codesniffer/bin/phpcbf | 15 + .../squizlabs/php_codesniffer/bin/phpcbf.bat | 10 + .../squizlabs/php_codesniffer/bin/phpcs | 15 + .../squizlabs/php_codesniffer/bin/phpcs.bat | 10 + .../squizlabs/php_codesniffer/composer.json | 90 + .../squizlabs/php_codesniffer/licence.txt | 24 + .../squizlabs/php_codesniffer/phpcs.xsd | 136 + .../squizlabs/php_codesniffer/src/Config.php | 1661 ++++ .../src/Exceptions/DeepExitException.php | 20 + .../src/Exceptions/RuntimeException.php | 17 + .../src/Exceptions/TokenizerException.php | 17 + .../php_codesniffer/src/Files/DummyFile.php | 82 + .../php_codesniffer/src/Files/File.php | 2954 +++++++ .../php_codesniffer/src/Files/FileList.php | 261 + .../php_codesniffer/src/Files/LocalFile.php | 219 + .../src/Filters/ExactMatch.php | 156 + .../php_codesniffer/src/Filters/Filter.php | 288 + .../src/Filters/GitModified.php | 124 + .../php_codesniffer/src/Filters/GitStaged.php | 126 + .../squizlabs/php_codesniffer/src/Fixer.php | 846 ++ .../src/Generators/Generator.php | 128 + .../php_codesniffer/src/Generators/HTML.php | 284 + .../src/Generators/Markdown.php | 168 + .../php_codesniffer/src/Generators/Text.php | 255 + .../php_codesniffer/src/Reporter.php | 445 + .../php_codesniffer/src/Reports/Cbf.php | 254 + .../src/Reports/Checkstyle.php | 111 + .../php_codesniffer/src/Reports/Code.php | 365 + .../php_codesniffer/src/Reports/Csv.php | 92 + .../php_codesniffer/src/Reports/Diff.php | 131 + .../php_codesniffer/src/Reports/Emacs.php | 91 + .../php_codesniffer/src/Reports/Full.php | 260 + .../php_codesniffer/src/Reports/Gitblame.php | 91 + .../php_codesniffer/src/Reports/Hgblame.php | 110 + .../php_codesniffer/src/Reports/Info.php | 173 + .../php_codesniffer/src/Reports/Json.php | 107 + .../php_codesniffer/src/Reports/Junit.php | 133 + .../src/Reports/Notifysend.php | 243 + .../src/Reports/Performance.php | 161 + .../php_codesniffer/src/Reports/Report.php | 87 + .../php_codesniffer/src/Reports/Source.php | 337 + .../php_codesniffer/src/Reports/Summary.php | 184 + .../php_codesniffer/src/Reports/Svnblame.php | 73 + .../src/Reports/VersionControl.php | 377 + .../php_codesniffer/src/Reports/Xml.php | 128 + .../squizlabs/php_codesniffer/src/Ruleset.php | 1623 ++++ .../squizlabs/php_codesniffer/src/Runner.php | 992 +++ .../src/Sniffs/AbstractArraySniff.php | 172 + .../src/Sniffs/AbstractPatternSniff.php | 941 +++ .../src/Sniffs/AbstractScopeSniff.php | 189 + .../src/Sniffs/AbstractVariableSniff.php | 230 + .../src/Sniffs/DeprecatedSniff.php | 63 + .../php_codesniffer/src/Sniffs/Sniff.php | 80 + .../Docs/Arrays/ArrayIndentStandard.xml | 107 + .../DisallowLongArraySyntaxStandard.xml | 23 + .../DisallowShortArraySyntaxStandard.xml | 23 + .../Classes/DuplicateClassNameStandard.xml | 27 + .../Classes/OpeningBraceSameLineStandard.xml | 36 + .../AssignmentInConditionStandard.xml | 23 + .../EmptyPHPStatementStandard.xml | 44 + .../CodeAnalysis/EmptyStatementStandard.xml | 23 + .../ForLoopShouldBeWhileLoopStandard.xml | 23 + .../ForLoopWithTestFunctionCallStandard.xml | 24 + .../JumbledIncrementerStandard.xml | 25 + ...licitBooleanOperatorPrecedenceStandard.xml | 44 + .../UnconditionalIfStatementStandard.xml | 39 + .../UnnecessaryFinalModifierStandard.xml | 29 + .../UnusedFunctionParameterStandard.xml | 25 + .../UselessOverridingMethodStandard.xml | 32 + .../Docs/Commenting/DocCommentStandard.xml | 269 + .../Generic/Docs/Commenting/FixmeStandard.xml | 25 + .../Generic/Docs/Commenting/TodoStandard.xml | 25 + .../DisallowYodaConditionsStandard.xml | 23 + .../InlineControlStructureStandard.xml | 22 + .../Generic/Docs/Debug/CSSLintStandard.xml | 19 + .../Docs/Debug/ClosureLinterStandard.xml | 19 + .../Generic/Docs/Debug/JSHintStandard.xml | 19 + .../Docs/Files/ByteOrderMarkStandard.xml | 7 + .../Docs/Files/EndFileNewlineStandard.xml | 7 + .../Docs/Files/EndFileNoNewlineStandard.xml | 7 + .../Docs/Files/ExecutableFileStandard.xml | 7 + .../Generic/Docs/Files/InlineHTMLStandard.xml | 24 + .../Docs/Files/LineEndingsStandard.xml | 7 + .../Generic/Docs/Files/LineLengthStandard.xml | 7 + .../Docs/Files/LowercasedFilenameStandard.xml | 7 + .../Docs/Files/OneClassPerFileStandard.xml | 29 + .../Files/OneInterfacePerFileStandard.xml | 29 + .../OneObjectStructurePerFileStandard.xml | 29 + .../Docs/Files/OneTraitPerFileStandard.xml | 29 + .../DisallowMultipleStatementsStandard.xml | 20 + .../MultipleStatementAlignmentStandard.xml | 56 + .../Formatting/NoSpaceAfterCastStandard.xml | 19 + .../Formatting/SpaceAfterCastStandard.xml | 19 + .../Docs/Formatting/SpaceAfterNotStandard.xml | 22 + .../Formatting/SpaceBeforeCastStandard.xml | 21 + .../CallTimePassByReferenceStandard.xml | 31 + .../FunctionCallArgumentSpacingStandard.xml | 39 + .../OpeningFunctionBraceBsdAllmanStandard.xml | 24 + ...gFunctionBraceKernighanRitchieStandard.xml | 24 + .../Metrics/CyclomaticComplexityStandard.xml | 7 + .../Docs/Metrics/NestingLevelStandard.xml | 7 + .../AbstractClassNamePrefixStandard.xml | 23 + .../CamelCapsFunctionNameStandard.xml | 23 + .../ConstructorNameStandard.xml | 29 + .../InterfaceNameSuffixStandard.xml | 23 + .../TraitNameSuffixStandard.xml | 23 + .../UpperCaseConstantNameStandard.xml | 29 + .../Docs/PHP/BacktickOperatorStandard.xml | 7 + .../CharacterBeforePHPOpeningTagStandard.xml | 22 + .../Docs/PHP/ClosingPHPTagStandard.xml | 22 + .../Docs/PHP/DeprecatedFunctionsStandard.xml | 19 + .../DisallowAlternativePHPTagsStandard.xml | 7 + .../DisallowRequestSuperglobalStandard.xml | 7 + .../Docs/PHP/DisallowShortOpenTagStandard.xml | 7 + .../Docs/PHP/DiscourageGotoStandard.xml | 7 + .../Docs/PHP/ForbiddenFunctionsStandard.xml | 19 + .../Docs/PHP/LowerCaseConstantStandard.xml | 23 + .../Docs/PHP/LowerCaseKeywordStandard.xml | 19 + .../Docs/PHP/LowerCaseTypeStandard.xml | 38 + .../Docs/PHP/NoSilencedErrorsStandard.xml | 23 + .../Docs/PHP/RequireStrictTypesStandard.xml | 38 + .../Generic/Docs/PHP/SAPIUsageStandard.xml | 23 + .../Generic/Docs/PHP/SyntaxStandard.xml | 21 + .../Docs/PHP/UpperCaseConstantStandard.xml | 23 + .../Strings/UnnecessaryHeredocStandard.xml | 39 + .../UnnecessaryStringConcatStandard.xml | 19 + .../SubversionPropertiesStandard.xml | 7 + .../ArbitraryParenthesesSpacingStandard.xml | 23 + .../DisallowSpaceIndentStandard.xml | 7 + .../WhiteSpace/DisallowTabIndentStandard.xml | 7 + .../HereNowdocIdentifierSpacingStandard.xml | 23 + .../IncrementDecrementSpacingStandard.xml | 26 + .../LanguageConstructSpacingStandard.xml | 44 + .../Docs/WhiteSpace/ScopeIndentStandard.xml | 23 + .../SpreadOperatorSpacingAfterStandard.xml | 34 + .../Sniffs/Arrays/ArrayIndentSniff.php | 193 + .../Arrays/DisallowLongArraySyntaxSniff.php | 72 + .../Arrays/DisallowShortArraySyntaxSniff.php | 61 + .../Classes/DuplicateClassNameSniff.php | 126 + .../Classes/OpeningBraceSameLineSniff.php | 124 + .../AssignmentInConditionSniff.php | 171 + .../CodeAnalysis/EmptyPHPStatementSniff.php | 162 + .../CodeAnalysis/EmptyStatementSniff.php | 97 + .../ForLoopShouldBeWhileLoopSniff.php | 91 + .../ForLoopWithTestFunctionCallSniff.php | 101 + .../CodeAnalysis/JumbledIncrementerSniff.php | 134 + ...ExplicitBooleanOperatorPrecedenceSniff.php | 112 + .../UnconditionalIfStatementSniff.php | 93 + .../UnnecessaryFinalModifierSniff.php | 88 + .../UnusedFunctionParameterSniff.php | 307 + .../UselessOverridingMethodSniff.php | 184 + .../Sniffs/Commenting/DocCommentSniff.php | 357 + .../Generic/Sniffs/Commenting/FixmeSniff.php | 78 + .../Generic/Sniffs/Commenting/TodoSniff.php | 77 + .../DisallowYodaConditionsSniff.php | 185 + .../InlineControlStructureSniff.php | 366 + .../Generic/Sniffs/Debug/CSSLintSniff.php | 98 + .../Sniffs/Debug/ClosureLinterSniff.php | 119 + .../Generic/Sniffs/Debug/ESLintSniff.php | 115 + .../Generic/Sniffs/Debug/JSHintSniff.php | 97 + .../Sniffs/Files/ByteOrderMarkSniff.php | 82 + .../Sniffs/Files/EndFileNewlineSniff.php | 84 + .../Sniffs/Files/EndFileNoNewlineSniff.php | 91 + .../Sniffs/Files/ExecutableFileSniff.php | 62 + .../Generic/Sniffs/Files/InlineHTMLSniff.php | 79 + .../Generic/Sniffs/Files/LineEndingsSniff.php | 148 + .../Generic/Sniffs/Files/LineLengthSniff.php | 201 + .../Sniffs/Files/LowercasedFilenameSniff.php | 70 + .../Sniffs/Files/OneClassPerFileSniff.php | 57 + .../Sniffs/Files/OneInterfacePerFileSniff.php | 57 + .../Files/OneObjectStructurePerFileSniff.php | 62 + .../Sniffs/Files/OneTraitPerFileSniff.php | 57 + .../DisallowMultipleStatementsSniff.php | 105 + .../MultipleStatementAlignmentSniff.php | 426 + .../Formatting/NoSpaceAfterCastSniff.php | 61 + .../Sniffs/Formatting/SpaceAfterCastSniff.php | 161 + .../Sniffs/Formatting/SpaceAfterNotSniff.php | 143 + .../Formatting/SpaceBeforeCastSniff.php | 73 + .../CallTimePassByReferenceSniff.php | 141 + .../FunctionCallArgumentSpacingSniff.php | 197 + .../OpeningFunctionBraceBsdAllmanSniff.php | 225 + ...ningFunctionBraceKernighanRitchieSniff.php | 182 + .../Metrics/CyclomaticComplexitySniff.php | 117 + .../Sniffs/Metrics/NestingLevelSniff.php | 100 + .../AbstractClassNamePrefixSniff.php | 60 + .../CamelCapsFunctionNameSniff.php | 222 + .../ConstructorNameSniff.php | 178 + .../InterfaceNameSuffixSniff.php | 55 + .../TraitNameSuffixSniff.php | 55 + .../UpperCaseConstantNameSniff.php | 149 + .../Sniffs/PHP/BacktickOperatorSniff.php | 48 + .../PHP/CharacterBeforePHPOpeningTagSniff.php | 86 + .../Generic/Sniffs/PHP/ClosingPHPTagSniff.php | 54 + .../Sniffs/PHP/DeprecatedFunctionsSniff.php | 75 + .../PHP/DisallowAlternativePHPTagsSniff.php | 253 + .../PHP/DisallowRequestSuperglobalSniff.php | 55 + .../Sniffs/PHP/DisallowShortOpenTagSniff.php | 168 + .../Sniffs/PHP/DiscourageGotoSniff.php | 50 + .../Sniffs/PHP/ForbiddenFunctionsSniff.php | 245 + .../Sniffs/PHP/LowerCaseConstantSniff.php | 244 + .../Sniffs/PHP/LowerCaseKeywordSniff.php | 82 + .../Generic/Sniffs/PHP/LowerCaseTypeSniff.php | 364 + .../Sniffs/PHP/NoSilencedErrorsSniff.php | 77 + .../Sniffs/PHP/RequireStrictTypesSniff.php | 108 + .../Generic/Sniffs/PHP/SAPIUsageSniff.php | 67 + .../Generic/Sniffs/PHP/SyntaxSniff.php | 75 + .../Sniffs/PHP/UpperCaseConstantSniff.php | 57 + .../Strings/UnnecessaryHeredocSniff.php | 97 + .../Strings/UnnecessaryStringConcatSniff.php | 129 + .../VersionControl/GitMergeConflictSniff.php | 228 + .../SubversionPropertiesSniff.php | 186 + .../ArbitraryParenthesesSpacingSniff.php | 239 + .../WhiteSpace/DisallowSpaceIndentSniff.php | 232 + .../WhiteSpace/DisallowTabIndentSniff.php | 201 + .../HereNowdocIdentifierSpacingSniff.php | 69 + .../IncrementDecrementSpacingSniff.php | 174 + .../LanguageConstructSpacingSniff.php | 161 + .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 1591 ++++ .../SpreadOperatorSpacingAfterSniff.php | 159 + .../Tests/Arrays/ArrayIndentUnitTest.inc | 154 + .../Arrays/ArrayIndentUnitTest.inc.fixed | 155 + .../Tests/Arrays/ArrayIndentUnitTest.php | 81 + .../DisallowLongArraySyntaxUnitTest.1.inc | 33 + ...isallowLongArraySyntaxUnitTest.1.inc.fixed | 33 + .../DisallowLongArraySyntaxUnitTest.2.inc | 17 + ...isallowLongArraySyntaxUnitTest.2.inc.fixed | 17 + .../DisallowLongArraySyntaxUnitTest.3.inc | 7 + .../DisallowLongArraySyntaxUnitTest.php | 75 + .../DisallowShortArraySyntaxUnitTest.inc | 12 + ...DisallowShortArraySyntaxUnitTest.inc.fixed | 12 + .../DisallowShortArraySyntaxUnitTest.php | 58 + .../Classes/DuplicateClassNameUnitTest.1.inc | 14 + .../Classes/DuplicateClassNameUnitTest.10.inc | 6 + .../Classes/DuplicateClassNameUnitTest.11.inc | 13 + .../Classes/DuplicateClassNameUnitTest.2.inc | 6 + .../Classes/DuplicateClassNameUnitTest.3.inc | 10 + .../Classes/DuplicateClassNameUnitTest.4.inc | 5 + .../Classes/DuplicateClassNameUnitTest.5.inc | 8 + .../Classes/DuplicateClassNameUnitTest.6.inc | 12 + .../Classes/DuplicateClassNameUnitTest.7.inc | 13 + .../Classes/DuplicateClassNameUnitTest.8.inc | 8 + .../Classes/DuplicateClassNameUnitTest.9.inc | 5 + .../Classes/DuplicateClassNameUnitTest.97.inc | 8 + .../Classes/DuplicateClassNameUnitTest.98.inc | 8 + .../Classes/DuplicateClassNameUnitTest.99.inc | 7 + .../Classes/DuplicateClassNameUnitTest.php | 98 + .../Classes/OpeningBraceSameLineUnitTest.inc | 100 + .../OpeningBraceSameLineUnitTest.inc.fixed | 100 + .../Classes/OpeningBraceSameLineUnitTest.php | 68 + .../AssignmentInConditionUnitTest.1.inc | 95 + .../AssignmentInConditionUnitTest.2.inc | 4 + .../AssignmentInConditionUnitTest.3.inc | 4 + .../AssignmentInConditionUnitTest.4.inc | 6 + .../AssignmentInConditionUnitTest.5.inc | 6 + .../AssignmentInConditionUnitTest.6.inc | 5 + .../AssignmentInConditionUnitTest.php | 96 + .../EmptyPHPStatementUnitTest.inc | 86 + .../EmptyPHPStatementUnitTest.inc.fixed | 80 + .../EmptyPHPStatementUnitTest.php | 73 + .../CodeAnalysis/EmptyStatementUnitTest.inc | 74 + .../CodeAnalysis/EmptyStatementUnitTest.php | 68 + .../ForLoopShouldBeWhileLoopUnitTest.1.inc | 37 + .../ForLoopShouldBeWhileLoopUnitTest.2.inc | 4 + .../ForLoopShouldBeWhileLoopUnitTest.3.inc | 6 + .../ForLoopShouldBeWhileLoopUnitTest.php | 64 + .../ForLoopWithTestFunctionCallUnitTest.1.inc | 95 + .../ForLoopWithTestFunctionCallUnitTest.2.inc | 5 + .../ForLoopWithTestFunctionCallUnitTest.3.inc | 6 + .../ForLoopWithTestFunctionCallUnitTest.php | 75 + .../JumbledIncrementerUnitTest.1.inc | 89 + .../JumbledIncrementerUnitTest.2.inc | 8 + .../JumbledIncrementerUnitTest.3.inc | 6 + .../JumbledIncrementerUnitTest.4.inc | 8 + .../JumbledIncrementerUnitTest.php | 72 + ...licitBooleanOperatorPrecedenceUnitTest.inc | 131 + ...licitBooleanOperatorPrecedenceUnitTest.php | 91 + .../UnconditionalIfStatementUnitTest.1.inc | 13 + .../UnconditionalIfStatementUnitTest.2.inc | 4 + .../UnconditionalIfStatementUnitTest.php | 65 + .../UnnecessaryFinalModifierUnitTest.1.inc | 56 + .../UnnecessaryFinalModifierUnitTest.2.inc | 5 + .../UnnecessaryFinalModifierUnitTest.php | 69 + .../UnusedFunctionParameterUnitTest.1.inc | 274 + .../UnusedFunctionParameterUnitTest.2.inc | 5 + .../UnusedFunctionParameterUnitTest.3.inc | 5 + .../UnusedFunctionParameterUnitTest.php | 78 + .../UselessOverridingMethodUnitTest.1.inc | 173 + .../UselessOverridingMethodUnitTest.2.inc | 7 + .../UselessOverridingMethodUnitTest.3.inc | 10 + .../UselessOverridingMethodUnitTest.4.inc | 10 + .../UselessOverridingMethodUnitTest.5.inc | 10 + .../UselessOverridingMethodUnitTest.6.inc | 10 + .../UselessOverridingMethodUnitTest.php | 72 + .../Tests/Commenting/DocCommentUnitTest.1.inc | 270 + .../Commenting/DocCommentUnitTest.1.inc.fixed | 275 + .../Tests/Commenting/DocCommentUnitTest.1.js | 270 + .../Commenting/DocCommentUnitTest.1.js.fixed | 275 + .../Tests/Commenting/DocCommentUnitTest.2.inc | 6 + .../Tests/Commenting/DocCommentUnitTest.2.js | 4 + .../Tests/Commenting/DocCommentUnitTest.php | 127 + .../Tests/Commenting/FixmeUnitTest.inc | 23 + .../Generic/Tests/Commenting/FixmeUnitTest.js | 23 + .../Tests/Commenting/FixmeUnitTest.php | 63 + .../Generic/Tests/Commenting/TodoUnitTest.inc | 23 + .../Generic/Tests/Commenting/TodoUnitTest.js | 23 + .../Generic/Tests/Commenting/TodoUnitTest.php | 62 + .../DisallowYodaConditionsUnitTest.inc | 187 + .../DisallowYodaConditionsUnitTest.php | 95 + .../InlineControlStructureUnitTest.1.inc | 278 + ...InlineControlStructureUnitTest.1.inc.fixed | 314 + .../InlineControlStructureUnitTest.1.js | 35 + .../InlineControlStructureUnitTest.1.js.fixed | 44 + .../InlineControlStructureUnitTest.2.inc | 8 + .../InlineControlStructureUnitTest.2.js | 5 + .../InlineControlStructureUnitTest.3.inc | 4 + .../InlineControlStructureUnitTest.3.js | 5 + .../InlineControlStructureUnitTest.4.inc | 5 + .../InlineControlStructureUnitTest.5.inc | 4 + .../InlineControlStructureUnitTest.6.inc | 6 + .../InlineControlStructureUnitTest.7.inc | 16 + .../InlineControlStructureUnitTest.php | 119 + .../Generic/Tests/Debug/CSSLintUnitTest.css | 6 + .../Generic/Tests/Debug/CSSLintUnitTest.php | 77 + .../Tests/Debug/ClosureLinterUnitTest.js | 6 + .../Tests/Debug/ClosureLinterUnitTest.php | 74 + .../Generic/Tests/Debug/ESLintUnitTest.js | 1 + .../Generic/Tests/Debug/ESLintUnitTest.php | 122 + .../Generic/Tests/Debug/JSHintUnitTest.js | 3 + .../Generic/Tests/Debug/JSHintUnitTest.php | 71 + .../Tests/Files/ByteOrderMarkUnitTest.1.inc | 4 + .../Tests/Files/ByteOrderMarkUnitTest.2.inc | 3 + .../Tests/Files/ByteOrderMarkUnitTest.3.inc | 1 + .../Tests/Files/ByteOrderMarkUnitTest.4.inc | Bin 0 -> 208 bytes .../Tests/Files/ByteOrderMarkUnitTest.5.inc | Bin 0 -> 202 bytes .../Tests/Files/ByteOrderMarkUnitTest.php | 63 + .../Tests/Files/EndFileNewlineUnitTest.1.css | 3 + .../Tests/Files/EndFileNewlineUnitTest.1.inc | 3 + .../Tests/Files/EndFileNewlineUnitTest.1.js | 3 + .../Tests/Files/EndFileNewlineUnitTest.2.css | 2 + .../Tests/Files/EndFileNewlineUnitTest.2.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.2.js | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.css | 2 + .../Files/EndFileNewlineUnitTest.3.css.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.inc | 2 + .../Files/EndFileNewlineUnitTest.3.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.js | 2 + .../Files/EndFileNewlineUnitTest.3.js.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.4.inc | 2 + .../Files/EndFileNewlineUnitTest.4.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.5.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.6.inc | 1 + .../Files/EndFileNewlineUnitTest.6.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.7.inc | 1 + .../Files/EndFileNewlineUnitTest.7.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.8.inc | 1 + .../Tests/Files/EndFileNewlineUnitTest.php | 68 + .../Files/EndFileNoNewlineUnitTest.1.css | 3 + .../EndFileNoNewlineUnitTest.1.css.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.1.inc | 3 + .../EndFileNoNewlineUnitTest.1.inc.fixed | 2 + .../Tests/Files/EndFileNoNewlineUnitTest.1.js | 3 + .../Files/EndFileNoNewlineUnitTest.1.js.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.10.inc | 1 + .../Files/EndFileNoNewlineUnitTest.2.css | 2 + .../EndFileNoNewlineUnitTest.2.css.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.2.inc | 3 + .../EndFileNoNewlineUnitTest.2.inc.fixed | 3 + .../Tests/Files/EndFileNoNewlineUnitTest.2.js | 2 + .../Files/EndFileNoNewlineUnitTest.2.js.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.3.css | 2 + .../Files/EndFileNoNewlineUnitTest.3.inc | 2 + .../Tests/Files/EndFileNoNewlineUnitTest.3.js | 2 + .../Files/EndFileNoNewlineUnitTest.4.inc | 3 + .../Files/EndFileNoNewlineUnitTest.5.inc | 2 + .../Files/EndFileNoNewlineUnitTest.6.inc | 2 + .../EndFileNoNewlineUnitTest.6.inc.fixed | 2 + .../Files/EndFileNoNewlineUnitTest.7.inc | 6 + .../Files/EndFileNoNewlineUnitTest.8.inc | 1 + .../EndFileNoNewlineUnitTest.8.inc.fixed | 1 + .../Files/EndFileNoNewlineUnitTest.9.inc | 1 + .../EndFileNoNewlineUnitTest.9.inc.fixed | 1 + .../Tests/Files/EndFileNoNewlineUnitTest.php | 72 + .../Tests/Files/ExecutableFileUnitTest.1.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.2.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.3.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.4.inc | 1 + .../Tests/Files/ExecutableFileUnitTest.php | 76 + .../Tests/Files/InlineHTMLUnitTest.1.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.2.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.3.inc | 6 + .../Tests/Files/InlineHTMLUnitTest.4.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.5.inc | 3 + .../Tests/Files/InlineHTMLUnitTest.6.inc | 2 + .../Tests/Files/InlineHTMLUnitTest.7.inc | 2 + .../Tests/Files/InlineHTMLUnitTest.php | 69 + .../Tests/Files/LineEndingsUnitTest.1.inc | 18 + .../Files/LineEndingsUnitTest.1.inc.fixed | 18 + .../Tests/Files/LineEndingsUnitTest.2.inc | 5 + .../Files/LineEndingsUnitTest.2.inc.fixed | 5 + .../Tests/Files/LineEndingsUnitTest.css | 3 + .../Tests/Files/LineEndingsUnitTest.css.fixed | 3 + .../Tests/Files/LineEndingsUnitTest.js | 2 + .../Tests/Files/LineEndingsUnitTest.js.fixed | 2 + .../Tests/Files/LineEndingsUnitTest.php | 68 + .../Tests/Files/LineLengthUnitTest.1.inc | 84 + .../Tests/Files/LineLengthUnitTest.2.inc | 7 + .../Tests/Files/LineLengthUnitTest.3.inc | 16 + .../Tests/Files/LineLengthUnitTest.4.inc | 16 + .../Tests/Files/LineLengthUnitTest.php | 114 + .../Files/LowercasedFilenameUnitTest.1.inc | 7 + .../Files/LowercasedFilenameUnitTest.2.inc | 7 + .../Files/LowercasedFilenameUnitTest.php | 61 + .../Tests/Files/OneClassPerFileUnitTest.inc | 13 + .../Tests/Files/OneClassPerFileUnitTest.php | 56 + .../Files/OneInterfacePerFileUnitTest.inc | 13 + .../Files/OneInterfacePerFileUnitTest.php | 56 + .../OneObjectStructurePerFileUnitTest.inc | 26 + .../OneObjectStructurePerFileUnitTest.php | 59 + .../Tests/Files/OneTraitPerFileUnitTest.inc | 17 + .../Tests/Files/OneTraitPerFileUnitTest.php | 56 + .../DisallowMultipleStatementsUnitTest.inc | 20 + ...sallowMultipleStatementsUnitTest.inc.fixed | 25 + .../DisallowMultipleStatementsUnitTest.php | 59 + .../MultipleStatementAlignmentUnitTest.inc | 504 ++ ...ltipleStatementAlignmentUnitTest.inc.fixed | 504 ++ .../MultipleStatementAlignmentUnitTest.js | 118 + ...ultipleStatementAlignmentUnitTest.js.fixed | 118 + .../MultipleStatementAlignmentUnitTest.php | 170 + .../Formatting/NoSpaceAfterCastUnitTest.inc | 51 + .../NoSpaceAfterCastUnitTest.inc.fixed | 51 + .../Formatting/NoSpaceAfterCastUnitTest.php | 77 + .../Formatting/SpaceAfterCastUnitTest.1.inc | 100 + .../SpaceAfterCastUnitTest.1.inc.fixed | 97 + .../Formatting/SpaceAfterCastUnitTest.2.inc | 3 + .../Formatting/SpaceAfterCastUnitTest.php | 103 + .../Formatting/SpaceAfterNotUnitTest.1.inc | 86 + .../SpaceAfterNotUnitTest.1.inc.fixed | 83 + .../Formatting/SpaceAfterNotUnitTest.2.inc | 7 + .../Tests/Formatting/SpaceAfterNotUnitTest.js | 5 + .../Formatting/SpaceAfterNotUnitTest.js.fixed | 5 + .../Formatting/SpaceAfterNotUnitTest.php | 96 + .../Formatting/SpaceBeforeCastUnitTest.inc | 65 + .../SpaceBeforeCastUnitTest.inc.fixed | 65 + .../Formatting/SpaceBeforeCastUnitTest.php | 83 + .../CallTimePassByReferenceUnitTest.1.inc | 66 + .../CallTimePassByReferenceUnitTest.2.inc | 7 + .../CallTimePassByReferenceUnitTest.3.inc | 7 + .../CallTimePassByReferenceUnitTest.php | 75 + .../FunctionCallArgumentSpacingUnitTest.1.inc | 199 + ...ionCallArgumentSpacingUnitTest.1.inc.fixed | 199 + .../FunctionCallArgumentSpacingUnitTest.2.inc | 7 + .../FunctionCallArgumentSpacingUnitTest.php | 96 + .../OpeningFunctionBraceBsdAllmanUnitTest.inc | 270 + ...ngFunctionBraceBsdAllmanUnitTest.inc.fixed | 287 + .../OpeningFunctionBraceBsdAllmanUnitTest.php | 91 + ...gFunctionBraceKernighanRitchieUnitTest.inc | 214 + ...ionBraceKernighanRitchieUnitTest.inc.fixed | 202 + ...gFunctionBraceKernighanRitchieUnitTest.php | 82 + .../Metrics/CyclomaticComplexityUnitTest.inc | 454 + .../Metrics/CyclomaticComplexityUnitTest.php | 63 + .../Tests/Metrics/NestingLevelUnitTest.inc | 102 + .../Tests/Metrics/NestingLevelUnitTest.php | 56 + .../AbstractClassNamePrefixUnitTest.1.inc | 45 + .../AbstractClassNamePrefixUnitTest.2.inc | 7 + .../AbstractClassNamePrefixUnitTest.php | 67 + .../CamelCapsFunctionNameUnitTest.1.inc | 204 + .../CamelCapsFunctionNameUnitTest.2.inc | 9 + .../CamelCapsFunctionNameUnitTest.3.inc | 7 + .../CamelCapsFunctionNameUnitTest.php | 105 + .../ConstructorNameUnitTest.inc | 130 + .../ConstructorNameUnitTest.php | 66 + .../InterfaceNameSuffixUnitTest.1.inc | 13 + .../InterfaceNameSuffixUnitTest.2.inc | 7 + .../InterfaceNameSuffixUnitTest.php | 62 + .../TraitNameSuffixUnitTest.1.inc | 11 + .../TraitNameSuffixUnitTest.2.inc | 7 + .../TraitNameSuffixUnitTest.php | 63 + .../UpperCaseConstantNameUnitTest.inc | 43 + .../UpperCaseConstantNameUnitTest.php | 63 + .../Tests/PHP/BacktickOperatorUnitTest.inc | 9 + .../Tests/PHP/BacktickOperatorUnitTest.php | 57 + ...CharacterBeforePHPOpeningTagUnitTest.1.inc | 9 + ...CharacterBeforePHPOpeningTagUnitTest.2.inc | 4 + ...CharacterBeforePHPOpeningTagUnitTest.3.inc | 3 + .../CharacterBeforePHPOpeningTagUnitTest.php | 61 + .../Tests/PHP/ClosingPHPTagUnitTest.1.inc | 10 + .../Tests/PHP/ClosingPHPTagUnitTest.2.inc | 5 + .../Tests/PHP/ClosingPHPTagUnitTest.php | 64 + .../Tests/PHP/DeprecatedFunctionsUnitTest.inc | 4 + .../Tests/PHP/DeprecatedFunctionsUnitTest.php | 63 + .../DisallowAlternativePHPTagsUnitTest.1.inc | 14 + ...llowAlternativePHPTagsUnitTest.1.inc.fixed | 14 + .../DisallowAlternativePHPTagsUnitTest.2.inc | 6 + ...llowAlternativePHPTagsUnitTest.2.inc.fixed | 6 + .../DisallowAlternativePHPTagsUnitTest.3.inc | 7 + .../DisallowAlternativePHPTagsUnitTest.php | 110 + .../DisallowRequestSuperglobalUnitTest.inc | 16 + .../DisallowRequestSuperglobalUnitTest.php | 56 + .../PHP/DisallowShortOpenTagUnitTest.1.inc | 11 + .../DisallowShortOpenTagUnitTest.1.inc.fixed | 11 + .../PHP/DisallowShortOpenTagUnitTest.2.inc | 8 + .../DisallowShortOpenTagUnitTest.2.inc.fixed | 8 + .../PHP/DisallowShortOpenTagUnitTest.3.inc | 20 + .../PHP/DisallowShortOpenTagUnitTest.4.inc | 6 + .../PHP/DisallowShortOpenTagUnitTest.php | 110 + .../Tests/PHP/DiscourageGotoUnitTest.inc | 18 + .../Tests/PHP/DiscourageGotoUnitTest.php | 58 + .../Tests/PHP/ForbiddenFunctionsUnitTest.inc | 60 + .../Tests/PHP/ForbiddenFunctionsUnitTest.php | 59 + .../Tests/PHP/LowerCaseConstantUnitTest.1.inc | 153 + .../PHP/LowerCaseConstantUnitTest.1.inc.fixed | 153 + .../Tests/PHP/LowerCaseConstantUnitTest.2.inc | 4 + .../Tests/PHP/LowerCaseConstantUnitTest.js | 14 + .../PHP/LowerCaseConstantUnitTest.js.fixed | 14 + .../Tests/PHP/LowerCaseConstantUnitTest.php | 105 + .../Tests/PHP/LowerCaseKeywordUnitTest.inc | 64 + .../PHP/LowerCaseKeywordUnitTest.inc.fixed | 64 + .../Tests/PHP/LowerCaseKeywordUnitTest.php | 78 + .../Tests/PHP/LowerCaseTypeUnitTest.inc | 145 + .../Tests/PHP/LowerCaseTypeUnitTest.inc.fixed | 145 + .../Tests/PHP/LowerCaseTypeUnitTest.php | 117 + .../Tests/PHP/NoSilencedErrorsUnitTest.inc | 16 + .../Tests/PHP/NoSilencedErrorsUnitTest.php | 57 + .../PHP/RequireStrictTypesUnitTest.1.inc | 8 + .../PHP/RequireStrictTypesUnitTest.10.inc | 5 + .../PHP/RequireStrictTypesUnitTest.11.inc | 5 + .../RequireStrictTypesUnitTest.11.inc.fixed | 5 + .../PHP/RequireStrictTypesUnitTest.12.inc | 5 + .../RequireStrictTypesUnitTest.12.inc.fixed | 5 + .../PHP/RequireStrictTypesUnitTest.13.inc | 3 + .../PHP/RequireStrictTypesUnitTest.14.inc | 5 + .../RequireStrictTypesUnitTest.14.inc.fixed | 5 + .../PHP/RequireStrictTypesUnitTest.15.inc | 5 + .../RequireStrictTypesUnitTest.15.inc.fixed | 5 + .../PHP/RequireStrictTypesUnitTest.2.inc | 2 + .../PHP/RequireStrictTypesUnitTest.3.inc | 5 + .../PHP/RequireStrictTypesUnitTest.4.inc | 10 + .../PHP/RequireStrictTypesUnitTest.5.inc | 6 + .../PHP/RequireStrictTypesUnitTest.6.inc | 4 + .../PHP/RequireStrictTypesUnitTest.7.inc | 4 + .../PHP/RequireStrictTypesUnitTest.8.inc | 5 + .../PHP/RequireStrictTypesUnitTest.9.inc | 5 + .../Tests/PHP/RequireStrictTypesUnitTest.php | 72 + .../Generic/Tests/PHP/SAPIUsageUnitTest.inc | 5 + .../Generic/Tests/PHP/SAPIUsageUnitTest.php | 53 + .../Generic/Tests/PHP/SyntaxUnitTest.1.inc | 4 + .../Generic/Tests/PHP/SyntaxUnitTest.2.inc | 3 + .../Generic/Tests/PHP/SyntaxUnitTest.php | 63 + .../Tests/PHP/UpperCaseConstantUnitTest.inc | 98 + .../PHP/UpperCaseConstantUnitTest.inc.fixed | 98 + .../Tests/PHP/UpperCaseConstantUnitTest.php | 75 + .../Strings/UnnecessaryHeredocUnitTest.1.inc | 108 + .../UnnecessaryHeredocUnitTest.1.inc.fixed | 108 + .../Strings/UnnecessaryHeredocUnitTest.2.inc | 108 + .../UnnecessaryHeredocUnitTest.2.inc.fixed | 108 + .../Strings/UnnecessaryHeredocUnitTest.3.inc | 6 + .../Strings/UnnecessaryHeredocUnitTest.php | 74 + .../UnnecessaryStringConcatUnitTest.1.inc | 34 + .../UnnecessaryStringConcatUnitTest.2.inc | 7 + .../UnnecessaryStringConcatUnitTest.js | 15 + .../UnnecessaryStringConcatUnitTest.php | 87 + .../GitMergeConflictUnitTest.1.css | 35 + .../GitMergeConflictUnitTest.1.inc | 61 + .../GitMergeConflictUnitTest.2.css | 32 + .../GitMergeConflictUnitTest.2.inc | 31 + .../GitMergeConflictUnitTest.3.inc | 43 + .../GitMergeConflictUnitTest.4.inc | 71 + .../GitMergeConflictUnitTest.5.inc | 34 + .../GitMergeConflictUnitTest.6.inc | 34 + .../GitMergeConflictUnitTest.7.inc | 19 + .../GitMergeConflictUnitTest.js | 33 + .../GitMergeConflictUnitTest.php | 175 + .../SubversionPropertiesUnitTest.inc | 3 + .../SubversionPropertiesUnitTest.php | 66 + .../ArbitraryParenthesesSpacingUnitTest.1.inc | 192 + ...raryParenthesesSpacingUnitTest.1.inc.fixed | 180 + .../ArbitraryParenthesesSpacingUnitTest.2.inc | 4 + .../ArbitraryParenthesesSpacingUnitTest.php | 106 + .../DisallowSpaceIndentUnitTest.1.inc | 125 + .../DisallowSpaceIndentUnitTest.1.inc.fixed | 125 + .../DisallowSpaceIndentUnitTest.2.inc | 125 + .../DisallowSpaceIndentUnitTest.2.inc.fixed | 125 + .../DisallowSpaceIndentUnitTest.3.inc | 19 + .../DisallowSpaceIndentUnitTest.3.inc.fixed | 19 + .../DisallowSpaceIndentUnitTest.4.inc | 13 + .../DisallowSpaceIndentUnitTest.css | 4 + .../DisallowSpaceIndentUnitTest.css.fixed | 4 + .../WhiteSpace/DisallowSpaceIndentUnitTest.js | 9 + .../DisallowSpaceIndentUnitTest.js.fixed | 9 + .../DisallowSpaceIndentUnitTest.php | 145 + .../DisallowTabIndentUnitTest.1.inc | 102 + .../DisallowTabIndentUnitTest.1.inc.fixed | 102 + .../DisallowTabIndentUnitTest.2.inc | 19 + .../DisallowTabIndentUnitTest.2.inc.fixed | 19 + .../DisallowTabIndentUnitTest.3.inc | 13 + .../WhiteSpace/DisallowTabIndentUnitTest.css | 5 + .../DisallowTabIndentUnitTest.css.fixed | 5 + .../WhiteSpace/DisallowTabIndentUnitTest.js | 9 + .../DisallowTabIndentUnitTest.js.fixed | 9 + .../WhiteSpace/DisallowTabIndentUnitTest.php | 153 + .../HereNowdocIdentifierSpacingUnitTest.inc | 25 + ...eNowdocIdentifierSpacingUnitTest.inc.fixed | 25 + .../HereNowdocIdentifierSpacingUnitTest.php | 58 + .../IncrementDecrementSpacingUnitTest.inc | 43 + ...ncrementDecrementSpacingUnitTest.inc.fixed | 41 + .../IncrementDecrementSpacingUnitTest.js | 17 + ...IncrementDecrementSpacingUnitTest.js.fixed | 16 + .../IncrementDecrementSpacingUnitTest.php | 86 + .../LanguageConstructSpacingUnitTest.1.inc | 100 + ...nguageConstructSpacingUnitTest.1.inc.fixed | 94 + .../LanguageConstructSpacingUnitTest.2.inc | 4 + .../LanguageConstructSpacingUnitTest.php | 101 + .../WhiteSpace/ScopeIndentUnitTest.1.inc | 1659 ++++ .../ScopeIndentUnitTest.1.inc.fixed | 1659 ++++ .../Tests/WhiteSpace/ScopeIndentUnitTest.1.js | 239 + .../WhiteSpace/ScopeIndentUnitTest.1.js.fixed | 239 + .../WhiteSpace/ScopeIndentUnitTest.2.inc | 1659 ++++ .../ScopeIndentUnitTest.2.inc.fixed | 1659 ++++ .../WhiteSpace/ScopeIndentUnitTest.3.inc | 34 + .../ScopeIndentUnitTest.3.inc.fixed | 34 + .../WhiteSpace/ScopeIndentUnitTest.4.inc | 6 + .../Tests/WhiteSpace/ScopeIndentUnitTest.php | 220 + .../SpreadOperatorSpacingAfterUnitTest.1.inc | 78 + ...adOperatorSpacingAfterUnitTest.1.inc.fixed | 73 + .../SpreadOperatorSpacingAfterUnitTest.2.inc | 4 + .../SpreadOperatorSpacingAfterUnitTest.php | 72 + .../src/Standards/Generic/ruleset.xml | 4 + .../Sniffs/CSS/BrowserSpecificStylesSniff.php | 89 + .../Channels/DisallowSelfActionsSniff.php | 127 + .../Sniffs/Channels/IncludeOwnSystemSniff.php | 100 + .../Sniffs/Channels/IncludeSystemSniff.php | 316 + .../Sniffs/Channels/UnusedSystemSniff.php | 143 + .../Commenting/FunctionCommentSniff.php | 86 + .../MySource/Sniffs/Debug/DebugCodeSniff.php | 57 + .../Sniffs/Debug/FirebugConsoleSniff.php | 66 + .../Sniffs/Objects/AssignThisSniff.php | 83 + .../Objects/CreateWidgetTypeCallbackSniff.php | 220 + .../Sniffs/Objects/DisallowNewWidgetSniff.php | 61 + .../Sniffs/PHP/AjaxNullComparisonSniff.php | 105 + .../Sniffs/PHP/EvalObjectFactorySniff.php | 116 + .../Sniffs/PHP/GetRequestDataSniff.php | 108 + .../Sniffs/PHP/ReturnFunctionValueSniff.php | 65 + .../Sniffs/Strings/JoinStringsSniff.php | 78 + .../CSS/BrowserSpecificStylesUnitTest.css | 13 + .../CSS/BrowserSpecificStylesUnitTest.php | 53 + .../Channels/DisallowSelfActionsUnitTest.inc | 51 + .../Channels/DisallowSelfActionsUnitTest.php | 58 + .../Tests/Channels/IncludeSystemUnitTest.inc | 112 + .../Tests/Channels/IncludeSystemUnitTest.php | 65 + .../Tests/Channels/UnusedSystemUnitTest.inc | 67 + .../Tests/Channels/UnusedSystemUnitTest.php | 60 + .../Commenting/FunctionCommentUnitTest.inc | 101 + .../Commenting/FunctionCommentUnitTest.php | 59 + .../Tests/Debug/DebugCodeUnitTest.inc | 4 + .../Tests/Debug/DebugCodeUnitTest.php | 56 + .../Tests/Debug/FirebugConsoleUnitTest.js | 8 + .../Tests/Debug/FirebugConsoleUnitTest.php | 66 + .../Tests/Objects/AssignThisUnitTest.js | 20 + .../Tests/Objects/AssignThisUnitTest.php | 63 + .../CreateWidgetTypeCallbackUnitTest.js | 186 + .../CreateWidgetTypeCallbackUnitTest.php | 62 + .../Objects/DisallowNewWidgetUnitTest.inc | 6 + .../Objects/DisallowNewWidgetUnitTest.php | 53 + .../Tests/PHP/AjaxNullComparisonUnitTest.inc | 182 + .../Tests/PHP/AjaxNullComparisonUnitTest.php | 60 + .../Tests/PHP/EvalObjectFactoryUnitTest.inc | 26 + .../Tests/PHP/EvalObjectFactoryUnitTest.php | 57 + .../Tests/PHP/GetRequestDataUnitTest.inc | 30 + .../Tests/PHP/GetRequestDataUnitTest.php | 61 + .../Tests/PHP/ReturnFunctionValueUnitTest.inc | 9 + .../Tests/PHP/ReturnFunctionValueUnitTest.php | 57 + .../Tests/Strings/JoinStringsUnitTest.js | 18 + .../Tests/Strings/JoinStringsUnitTest.php | 67 + .../src/Standards/MySource/ruleset.xml | 18 + .../Docs/Classes/ClassDeclarationStandard.xml | 22 + .../Docs/Commenting/ClassCommentStandard.xml | 177 + .../Docs/Commenting/FileCommentStandard.xml | 293 + .../Commenting/FunctionCommentStandard.xml | 230 + .../Docs/Commenting/InlineCommentStandard.xml | 19 + .../ControlSignatureStandard.xml | 36 + .../MultiLineConditionStandard.xml | 60 + .../PEAR/Docs/Files/IncludingFileStandard.xml | 24 + .../PEAR/Docs/Files/LineLengthStandard.xml | 7 + .../MultiLineAssignmentStandard.xml | 35 + .../FunctionCallSignatureStandard.xml | 19 + .../Functions/FunctionDeclarationStandard.xml | 41 + .../Functions/ValidDefaultValueStandard.xml | 25 + .../ValidClassNameStandard.xml | 23 + .../ValidFunctionNameStandard.xml | 23 + .../ValidVariableNameStandard.xml | 29 + .../ObjectOperatorIndentStandard.xml | 39 + .../WhiteSpace/ScopeClosingBraceStandard.xml | 23 + .../Docs/WhiteSpace/ScopeIndentStandard.xml | 29 + .../Sniffs/Classes/ClassDeclarationSniff.php | 150 + .../Sniffs/Commenting/ClassCommentSniff.php | 122 + .../Sniffs/Commenting/FileCommentSniff.php | 583 ++ .../Commenting/FunctionCommentSniff.php | 539 ++ .../Sniffs/Commenting/InlineCommentSniff.php | 68 + .../ControlSignatureSniff.php | 48 + .../MultiLineConditionSniff.php | 283 + .../PEAR/Sniffs/Files/IncludingFileSniff.php | 136 + .../Formatting/MultiLineAssignmentSniff.php | 106 + .../Functions/FunctionCallSignatureSniff.php | 634 ++ .../Functions/FunctionDeclarationSniff.php | 549 ++ .../Functions/ValidDefaultValueSniff.php | 78 + .../NamingConventions/ValidClassNameSniff.php | 98 + .../ValidFunctionNameSniff.php | 284 + .../ValidVariableNameSniff.php | 103 + .../WhiteSpace/ObjectOperatorIndentSniff.php | 204 + .../WhiteSpace/ScopeClosingBraceSniff.php | 182 + .../Sniffs/WhiteSpace/ScopeIndentSniff.php | 24 + .../Classes/ClassDeclarationUnitTest.1.inc | 114 + .../ClassDeclarationUnitTest.1.inc.fixed | 125 + .../Classes/ClassDeclarationUnitTest.2.inc | 11 + .../Classes/ClassDeclarationUnitTest.php | 100 + .../Tests/Commenting/ClassCommentUnitTest.inc | 163 + .../Tests/Commenting/ClassCommentUnitTest.php | 78 + .../Commenting/FileCommentUnitTest.1.inc | 53 + .../Commenting/FileCommentUnitTest.2.inc | 9 + .../Commenting/FileCommentUnitTest.3.inc | 8 + .../Commenting/FileCommentUnitTest.4.inc | 7 + .../Tests/Commenting/FileCommentUnitTest.php | 95 + .../Commenting/FunctionCommentUnitTest.inc | 512 ++ .../FunctionCommentUnitTest.inc.fixed | 491 ++ .../Commenting/FunctionCommentUnitTest.php | 103 + .../Commenting/InlineCommentUnitTest.inc | 29 + .../InlineCommentUnitTest.inc.fixed | 29 + .../Commenting/InlineCommentUnitTest.php | 60 + .../ControlSignatureUnitTest.inc | 165 + .../ControlSignatureUnitTest.php | 77 + .../MultiLineConditionUnitTest.inc | 251 + .../MultiLineConditionUnitTest.inc.fixed | 247 + .../MultiLineConditionUnitTest.js | 251 + .../MultiLineConditionUnitTest.js.fixed | 247 + .../MultiLineConditionUnitTest.php | 96 + .../Tests/Files/IncludingFileUnitTest.inc | 99 + .../Files/IncludingFileUnitTest.inc.fixed | 99 + .../Tests/Files/IncludingFileUnitTest.php | 72 + .../MultiLineAssignmentUnitTest.inc | 22 + .../MultiLineAssignmentUnitTest.php | 57 + .../FunctionCallSignatureUnitTest.inc | 576 ++ .../FunctionCallSignatureUnitTest.inc.fixed | 591 ++ .../FunctionCallSignatureUnitTest.js | 80 + .../FunctionCallSignatureUnitTest.js.fixed | 84 + .../FunctionCallSignatureUnitTest.php | 164 + .../FunctionDeclarationUnitTest.1.inc | 490 ++ .../FunctionDeclarationUnitTest.1.inc.fixed | 487 ++ .../FunctionDeclarationUnitTest.2.inc | 7 + .../Functions/FunctionDeclarationUnitTest.js | 59 + .../FunctionDeclarationUnitTest.js.fixed | 60 + .../Functions/FunctionDeclarationUnitTest.php | 149 + .../Functions/ValidDefaultValueUnitTest.1.inc | 116 + .../Functions/ValidDefaultValueUnitTest.2.inc | 7 + .../Functions/ValidDefaultValueUnitTest.php | 73 + .../ValidClassNameUnitTest.inc | 90 + .../ValidClassNameUnitTest.php | 78 + .../ValidFunctionNameUnitTest.inc | 243 + .../ValidFunctionNameUnitTest.php | 154 + .../ValidVariableNameUnitTest.inc | 101 + .../ValidVariableNameUnitTest.php | 61 + .../ObjectOperatorIndentUnitTest.inc | 142 + .../ObjectOperatorIndentUnitTest.inc.fixed | 142 + .../ObjectOperatorIndentUnitTest.php | 79 + .../WhiteSpace/ScopeClosingBraceUnitTest.inc | 170 + .../ScopeClosingBraceUnitTest.inc.fixed | 177 + .../WhiteSpace/ScopeClosingBraceUnitTest.php | 73 + .../Tests/WhiteSpace/ScopeIndentUnitTest.inc | 314 + .../WhiteSpace/ScopeIndentUnitTest.inc.fixed | 314 + .../Tests/WhiteSpace/ScopeIndentUnitTest.php | 71 + .../src/Standards/PEAR/ruleset.xml | 41 + .../Docs/Classes/ClassDeclarationStandard.xml | 48 + .../PSR1/Docs/Files/SideEffectsStandard.xml | 27 + .../Methods/CamelCapsMethodNameStandard.xml | 29 + .../Sniffs/Classes/ClassDeclarationSniff.php | 75 + .../PSR1/Sniffs/Files/SideEffectsSniff.php | 303 + .../Methods/CamelCapsMethodNameSniff.php | 91 + .../Classes/ClassDeclarationUnitTest.1.inc | 3 + .../Classes/ClassDeclarationUnitTest.2.inc | 4 + .../Classes/ClassDeclarationUnitTest.3.inc | 3 + .../Classes/ClassDeclarationUnitTest.php | 62 + .../Tests/Files/SideEffectsUnitTest.1.inc | 87 + .../Tests/Files/SideEffectsUnitTest.10.inc | 8 + .../Tests/Files/SideEffectsUnitTest.11.inc | 11 + .../Tests/Files/SideEffectsUnitTest.12.inc | 8 + .../Tests/Files/SideEffectsUnitTest.13.inc | 2 + .../Tests/Files/SideEffectsUnitTest.14.inc | 2 + .../Tests/Files/SideEffectsUnitTest.15.inc | 2 + .../Tests/Files/SideEffectsUnitTest.16.inc | 2 + .../Tests/Files/SideEffectsUnitTest.17.inc | 8 + .../Tests/Files/SideEffectsUnitTest.2.inc | 24 + .../Tests/Files/SideEffectsUnitTest.3.inc | 6 + .../Tests/Files/SideEffectsUnitTest.4.inc | 10 + .../Tests/Files/SideEffectsUnitTest.5.inc | 2 + .../Tests/Files/SideEffectsUnitTest.6.inc | 9 + .../Tests/Files/SideEffectsUnitTest.7.inc | 8 + .../Tests/Files/SideEffectsUnitTest.8.inc | 8 + .../Tests/Files/SideEffectsUnitTest.9.inc | 8 + .../PSR1/Tests/Files/SideEffectsUnitTest.php | 85 + .../Methods/CamelCapsMethodNameUnitTest.inc | 81 + .../Methods/CamelCapsMethodNameUnitTest.php | 64 + .../src/Standards/PSR1/ruleset.xml | 47 + .../Classes/ClassInstantiationStandard.xml | 19 + .../Docs/Classes/ClosingBraceStandard.xml | 35 + .../Classes/OpeningBraceSpaceStandard.xml | 32 + .../BooleanOperatorPlacementStandard.xml | 59 + .../ControlStructureSpacingStandard.xml | 124 + .../Docs/Files/ImportStatementStandard.xml | 33 + .../PSR12/Docs/Files/OpenTagStandard.xml | 40 + .../NullableTypeDeclarationStandard.xml | 45 + .../ReturnTypeDeclarationStandard.xml | 41 + .../ShortFormTypeKeywordsStandard.xml | 19 + .../CompoundNamespaceDepthStandard.xml | 28 + .../Operators/OperatorSpacingStandard.xml | 27 + .../Properties/ConstantVisibilityStandard.xml | 27 + .../Classes/AnonClassDeclarationSniff.php | 246 + .../Classes/ClassInstantiationSniff.php | 112 + .../Sniffs/Classes/ClosingBraceSniff.php | 67 + .../Sniffs/Classes/OpeningBraceSpaceSniff.php | 80 + .../BooleanOperatorPlacementSniff.php | 229 + .../ControlStructureSpacingSniff.php | 219 + .../Sniffs/Files/DeclareStatementSniff.php | 262 + .../PSR12/Sniffs/Files/FileHeaderSniff.php | 429 + .../Sniffs/Files/ImportStatementSniff.php | 77 + .../PSR12/Sniffs/Files/OpenTagSniff.php | 76 + .../NullableTypeDeclarationSniff.php | 94 + .../Functions/ReturnTypeDeclarationSniff.php | 110 + .../Keywords/ShortFormTypeKeywordsSniff.php | 75 + .../CompoundNamespaceDepthSniff.php | 80 + .../Sniffs/Operators/OperatorSpacingSniff.php | 128 + .../Properties/ConstantVisibilitySniff.php | 64 + .../Sniffs/Traits/UseDeclarationSniff.php | 700 ++ .../Classes/AnonClassDeclarationUnitTest.inc | 96 + .../AnonClassDeclarationUnitTest.inc.fixed | 98 + .../Classes/AnonClassDeclarationUnitTest.php | 80 + .../Classes/ClassInstantiationUnitTest.inc | 51 + .../ClassInstantiationUnitTest.inc.fixed | 51 + .../Classes/ClassInstantiationUnitTest.php | 72 + .../Tests/Classes/ClosingBraceUnitTest.inc | 52 + .../Tests/Classes/ClosingBraceUnitTest.php | 60 + .../Classes/OpeningBraceSpaceUnitTest.inc | 57 + .../OpeningBraceSpaceUnitTest.inc.fixed | 48 + .../Classes/OpeningBraceSpaceUnitTest.php | 60 + .../BooleanOperatorPlacementUnitTest.inc | 131 + ...BooleanOperatorPlacementUnitTest.inc.fixed | 141 + .../BooleanOperatorPlacementUnitTest.php | 64 + .../ControlStructureSpacingUnitTest.inc | 133 + .../ControlStructureSpacingUnitTest.inc.fixed | 131 + .../ControlStructureSpacingUnitTest.php | 77 + .../Files/DeclareStatementUnitTest.1.inc | 50 + .../DeclareStatementUnitTest.1.inc.fixed | 54 + .../Files/DeclareStatementUnitTest.2.inc | 3 + .../Tests/Files/DeclareStatementUnitTest.php | 84 + .../Tests/Files/FileHeaderUnitTest.1.inc | 29 + .../Tests/Files/FileHeaderUnitTest.10.inc | 4 + .../Files/FileHeaderUnitTest.10.inc.fixed | 5 + .../Tests/Files/FileHeaderUnitTest.11.inc | 21 + .../Files/FileHeaderUnitTest.11.inc.fixed | 22 + .../Tests/Files/FileHeaderUnitTest.12.inc | 17 + .../Files/FileHeaderUnitTest.12.inc.fixed | 18 + .../Tests/Files/FileHeaderUnitTest.13.inc | 24 + .../Tests/Files/FileHeaderUnitTest.14.inc | 7 + .../Tests/Files/FileHeaderUnitTest.15.inc | 5 + .../Tests/Files/FileHeaderUnitTest.16.inc | 13 + .../Tests/Files/FileHeaderUnitTest.17.inc | 13 + .../Tests/Files/FileHeaderUnitTest.18.inc | 16 + .../Tests/Files/FileHeaderUnitTest.2.inc | 33 + .../Files/FileHeaderUnitTest.2.inc.fixed | 29 + .../Tests/Files/FileHeaderUnitTest.3.inc | 27 + .../Tests/Files/FileHeaderUnitTest.4.inc | 15 + .../Files/FileHeaderUnitTest.4.inc.fixed | 19 + .../Tests/Files/FileHeaderUnitTest.5.inc | 18 + .../Tests/Files/FileHeaderUnitTest.6.inc | 13 + .../Tests/Files/FileHeaderUnitTest.7.inc | 2 + .../Files/FileHeaderUnitTest.7.inc.fixed | 3 + .../Tests/Files/FileHeaderUnitTest.8.inc | 5 + .../Tests/Files/FileHeaderUnitTest.9.inc | 7 + .../PSR12/Tests/Files/FileHeaderUnitTest.php | 87 + .../Tests/Files/ImportStatementUnitTest.inc | 26 + .../Files/ImportStatementUnitTest.inc.fixed | 26 + .../Tests/Files/ImportStatementUnitTest.php | 57 + .../PSR12/Tests/Files/OpenTagUnitTest.1.inc | 3 + .../PSR12/Tests/Files/OpenTagUnitTest.2.inc | 1 + .../Tests/Files/OpenTagUnitTest.2.inc.fixed | 2 + .../PSR12/Tests/Files/OpenTagUnitTest.3.inc | 3 + .../PSR12/Tests/Files/OpenTagUnitTest.4.inc | 2 + .../PSR12/Tests/Files/OpenTagUnitTest.5.inc | 1 + .../PSR12/Tests/Files/OpenTagUnitTest.php | 60 + .../NullableTypeDeclarationUnitTest.inc | 95 + .../NullableTypeDeclarationUnitTest.inc.fixed | 92 + .../NullableTypeDeclarationUnitTest.php | 72 + .../ReturnTypeDeclarationUnitTest.inc | 66 + .../ReturnTypeDeclarationUnitTest.inc.fixed | 62 + .../ReturnTypeDeclarationUnitTest.php | 66 + .../ShortFormTypeKeywordsUnitTest.inc | 14 + .../ShortFormTypeKeywordsUnitTest.inc.fixed | 14 + .../ShortFormTypeKeywordsUnitTest.php | 59 + .../CompoundNamespaceDepthUnitTest.inc | 31 + .../CompoundNamespaceDepthUnitTest.php | 57 + .../Operators/OperatorSpacingUnitTest.1.inc | 79 + .../OperatorSpacingUnitTest.1.inc.fixed | 79 + .../Operators/OperatorSpacingUnitTest.2.inc | 3 + .../Operators/OperatorSpacingUnitTest.3.inc | 6 + .../Operators/OperatorSpacingUnitTest.php | 81 + .../Properties/ConstantVisibilityUnitTest.inc | 22 + .../Properties/ConstantVisibilityUnitTest.php | 57 + .../Tests/Traits/UseDeclarationUnitTest.inc | 221 + .../Traits/UseDeclarationUnitTest.inc.fixed | 213 + .../Tests/Traits/UseDeclarationUnitTest.php | 76 + .../src/Standards/PSR12/ruleset.xml | 348 + .../Docs/Classes/ClassDeclarationStandard.xml | 23 + .../Classes/PropertyDeclarationStandard.xml | 81 + .../ControlStructureSpacingStandard.xml | 23 + .../ElseIfDeclarationStandard.xml | 27 + .../SwitchDeclarationStandard.xml | 104 + .../PSR2/Docs/Files/ClosingTagStandard.xml | 23 + .../Docs/Files/EndFileNewlineStandard.xml | 7 + .../Methods/FunctionCallSignatureStandard.xml | 107 + .../Methods/FunctionClosingBraceStandard.xml | 26 + .../Methods/MethodDeclarationStandard.xml | 51 + .../NamespaceDeclarationStandard.xml | 22 + .../Namespaces/UseDeclarationStandard.xml | 57 + .../Sniffs/Classes/ClassDeclarationSniff.php | 540 ++ .../Classes/PropertyDeclarationSniff.php | 226 + .../ControlStructureSpacingSniff.php | 141 + .../ElseIfDeclarationSniff.php | 72 + .../SwitchDeclarationSniff.php | 396 + .../PSR2/Sniffs/Files/ClosingTagSniff.php | 89 + .../PSR2/Sniffs/Files/EndFileNewlineSniff.php | 107 + .../Methods/FunctionCallSignatureSniff.php | 79 + .../Methods/FunctionClosingBraceSniff.php | 91 + .../Sniffs/Methods/MethodDeclarationSniff.php | 162 + .../Namespaces/NamespaceDeclarationSniff.php | 100 + .../Sniffs/Namespaces/UseDeclarationSniff.php | 297 + .../Classes/ClassDeclarationUnitTest.inc | 346 + .../ClassDeclarationUnitTest.inc.fixed | 335 + .../Classes/ClassDeclarationUnitTest.php | 103 + .../Classes/PropertyDeclarationUnitTest.inc | 87 + .../PropertyDeclarationUnitTest.inc.fixed | 84 + .../Classes/PropertyDeclarationUnitTest.php | 84 + .../ControlStructureSpacingUnitTest.inc | 81 + .../ControlStructureSpacingUnitTest.inc.fixed | 80 + .../ControlStructureSpacingUnitTest.php | 67 + .../ElseIfDeclarationUnitTest.inc | 17 + .../ElseIfDeclarationUnitTest.inc.fixed | 17 + .../ElseIfDeclarationUnitTest.php | 56 + .../SwitchDeclarationUnitTest.inc | 598 ++ .../SwitchDeclarationUnitTest.inc.fixed | 593 ++ .../SwitchDeclarationUnitTest.php | 86 + .../PSR2/Tests/Files/ClosingTagUnitTest.1.inc | 12 + .../Files/ClosingTagUnitTest.1.inc.fixed | 12 + .../PSR2/Tests/Files/ClosingTagUnitTest.2.inc | 3 + .../PSR2/Tests/Files/ClosingTagUnitTest.3.inc | 7 + .../PSR2/Tests/Files/ClosingTagUnitTest.4.inc | 1 + .../Files/ClosingTagUnitTest.4.inc.fixed | 1 + .../PSR2/Tests/Files/ClosingTagUnitTest.5.inc | 1 + .../Files/ClosingTagUnitTest.5.inc.fixed | 1 + .../PSR2/Tests/Files/ClosingTagUnitTest.6.inc | 5 + .../Files/ClosingTagUnitTest.6.inc.fixed | 5 + .../PSR2/Tests/Files/ClosingTagUnitTest.7.inc | 5 + .../Files/ClosingTagUnitTest.7.inc.fixed | 5 + .../PSR2/Tests/Files/ClosingTagUnitTest.php | 69 + .../Tests/Files/EndFileNewlineUnitTest.1.inc | 3 + .../Files/EndFileNewlineUnitTest.1.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.10.inc | 3 + .../Files/EndFileNewlineUnitTest.10.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.11.inc | 1 + .../Files/EndFileNewlineUnitTest.11.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.12.inc | 1 + .../Files/EndFileNewlineUnitTest.12.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.13.inc | 5 + .../Files/EndFileNewlineUnitTest.13.inc.fixed | 1 + .../Tests/Files/EndFileNewlineUnitTest.14.inc | 1 + .../Tests/Files/EndFileNewlineUnitTest.2.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.3.inc | 2 + .../Files/EndFileNewlineUnitTest.3.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.4.inc | 4 + .../Tests/Files/EndFileNewlineUnitTest.5.inc | 6 + .../Tests/Files/EndFileNewlineUnitTest.6.inc | 2 + .../Files/EndFileNewlineUnitTest.6.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.7.inc | 11 + .../Files/EndFileNewlineUnitTest.7.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.8.inc | 2 + .../Tests/Files/EndFileNewlineUnitTest.9.inc | 2 + .../Files/EndFileNewlineUnitTest.9.inc.fixed | 2 + .../Tests/Files/EndFileNewlineUnitTest.php | 71 + .../Methods/FunctionCallSignatureUnitTest.inc | 267 + .../FunctionCallSignatureUnitTest.inc.fixed | 283 + .../Methods/FunctionCallSignatureUnitTest.php | 99 + .../Methods/FunctionClosingBraceUnitTest.inc | 70 + .../FunctionClosingBraceUnitTest.inc.fixed | 61 + .../Methods/FunctionClosingBraceUnitTest.php | 60 + .../Methods/MethodDeclarationUnitTest.inc | 75 + .../MethodDeclarationUnitTest.inc.fixed | 75 + .../Methods/MethodDeclarationUnitTest.php | 76 + .../NamespaceDeclarationUnitTest.inc | 26 + .../NamespaceDeclarationUnitTest.inc.fixed | 28 + .../NamespaceDeclarationUnitTest.php | 58 + .../Namespaces/UseDeclarationUnitTest.1.inc | 40 + .../Namespaces/UseDeclarationUnitTest.10.inc | 8 + .../UseDeclarationUnitTest.10.inc.fixed | 9 + .../Namespaces/UseDeclarationUnitTest.11.inc | 2 + .../UseDeclarationUnitTest.11.inc.fixed | 4 + .../Namespaces/UseDeclarationUnitTest.12.inc | 9 + .../UseDeclarationUnitTest.12.inc.fixed | 11 + .../Namespaces/UseDeclarationUnitTest.13.inc | 10 + .../UseDeclarationUnitTest.13.inc.fixed | 11 + .../Namespaces/UseDeclarationUnitTest.14.inc | 8 + .../UseDeclarationUnitTest.14.inc.fixed | 9 + .../Namespaces/UseDeclarationUnitTest.15.inc | 10 + .../Namespaces/UseDeclarationUnitTest.16.inc | 11 + .../UseDeclarationUnitTest.16.inc.fixed | 9 + .../Namespaces/UseDeclarationUnitTest.17.inc | 3 + .../Namespaces/UseDeclarationUnitTest.18.inc | 4 + .../Namespaces/UseDeclarationUnitTest.2.inc | 21 + .../UseDeclarationUnitTest.2.inc.fixed | 27 + .../Namespaces/UseDeclarationUnitTest.3.inc | 16 + .../UseDeclarationUnitTest.3.inc.fixed | 16 + .../Namespaces/UseDeclarationUnitTest.4.inc | 4 + .../Namespaces/UseDeclarationUnitTest.5.inc | 47 + .../UseDeclarationUnitTest.5.inc.fixed | 56 + .../Namespaces/UseDeclarationUnitTest.6.inc | 1 + .../Namespaces/UseDeclarationUnitTest.7.inc | 1 + .../Namespaces/UseDeclarationUnitTest.8.inc | 8 + .../Namespaces/UseDeclarationUnitTest.9.inc | 8 + .../Namespaces/UseDeclarationUnitTest.php | 102 + .../src/Standards/PSR2/ruleset.xml | 218 + .../Arrays/ArrayBracketSpacingStandard.xml | 19 + .../Docs/Arrays/ArrayDeclarationStandard.xml | 117 + .../LowercaseClassKeywordsStandard.xml | 23 + .../Classes/SelfMemberReferenceStandard.xml | 63 + .../DocCommentAlignmentStandard.xml | 39 + .../FunctionCommentThrowTagStandard.xml | 32 + .../ForEachLoopDeclarationStandard.xml | 39 + .../ForLoopDeclarationStandard.xml | 55 + .../LowercaseDeclarationStandard.xml | 23 + .../LowercaseFunctionKeywordsStandard.xml | 25 + .../Squiz/Docs/PHP/HeredocStandard.xml | 32 + .../Docs/Scope/StaticThisUsageStandard.xml | 31 + .../Docs/Strings/EchoedStringsStandard.xml | 19 + .../Docs/WhiteSpace/CastSpacingStandard.xml | 19 + .../FunctionClosingBraceSpaceStandard.xml | 73 + .../FunctionOpeningBraceStandard.xml | 41 + .../LanguageConstructSpacingStandard.xml | 19 + .../WhiteSpace/MemberVarSpacingStandard.xml | 91 + .../ObjectOperatorSpacingStandard.xml | 19 + .../WhiteSpace/ScopeClosingBraceStandard.xml | 59 + .../ScopeKeywordSpacingStandard.xml | 23 + .../WhiteSpace/SemicolonSpacingStandard.xml | 19 + .../SuperfluousWhitespaceStandard.xml | 98 + .../Arrays/ArrayBracketSpacingSniff.php | 95 + .../Sniffs/Arrays/ArrayDeclarationSniff.php | 942 +++ .../ClassDefinitionClosingBraceSpaceSniff.php | 136 + .../CSS/ClassDefinitionNameSpacingSniff.php | 113 + .../ClassDefinitionOpeningBraceSpaceSniff.php | 178 + .../Squiz/Sniffs/CSS/ColonSpacingSniff.php | 109 + .../Sniffs/CSS/ColourDefinitionSniff.php | 90 + .../DisallowMultipleStyleDefinitionsSniff.php | 73 + .../CSS/DuplicateClassDefinitionSniff.php | 118 + .../CSS/DuplicateStyleDefinitionSniff.php | 90 + .../Sniffs/CSS/EmptyClassDefinitionSniff.php | 63 + .../Sniffs/CSS/EmptyStyleDefinitionSniff.php | 66 + .../Squiz/Sniffs/CSS/ForbiddenStylesSniff.php | 179 + .../Squiz/Sniffs/CSS/IndentationSniff.php | 152 + .../CSS/LowercaseStyleDefinitionSniff.php | 99 + .../Squiz/Sniffs/CSS/MissingColonSniff.php | 93 + .../Squiz/Sniffs/CSS/NamedColoursSniff.php | 95 + .../Squiz/Sniffs/CSS/OpacitySniff.php | 103 + .../Sniffs/CSS/SemicolonSpacingSniff.php | 105 + .../Squiz/Sniffs/CSS/ShorthandSizeSniff.php | 183 + .../Sniffs/Classes/ClassDeclarationSniff.php | 207 + .../Sniffs/Classes/ClassFileNameSniff.php | 70 + .../Sniffs/Classes/DuplicatePropertySniff.php | 84 + .../Classes/LowercaseClassKeywordsSniff.php | 73 + .../Classes/SelfMemberReferenceSniff.php | 248 + .../Sniffs/Classes/ValidClassNameSniff.php | 87 + .../Sniffs/Commenting/BlockCommentSniff.php | 401 + .../Sniffs/Commenting/ClassCommentSniff.php | 109 + .../ClosingDeclarationCommentSniff.php | 130 + .../Commenting/DocCommentAlignmentSniff.php | 167 + .../Commenting/EmptyCatchCommentSniff.php | 55 + .../Sniffs/Commenting/FileCommentSniff.php | 228 + .../Commenting/FunctionCommentSniff.php | 800 ++ .../FunctionCommentThrowTagSniff.php | 233 + .../Sniffs/Commenting/InlineCommentSniff.php | 349 + .../LongConditionClosingCommentSniff.php | 218 + .../Commenting/PostStatementCommentSniff.php | 129 + .../Commenting/VariableCommentSniff.php | 201 + .../ControlSignatureSniff.php | 337 + .../ElseIfDeclarationSniff.php | 51 + .../ForEachLoopDeclarationSniff.php | 236 + .../ForLoopDeclarationSniff.php | 316 + .../InlineIfDeclarationSniff.php | 155 + .../LowercaseDeclarationSniff.php | 75 + .../SwitchDeclarationSniff.php | 304 + .../Squiz/Sniffs/Debug/JSLintSniff.php | 88 + .../Sniffs/Debug/JavaScriptLintSniff.php | 91 + .../Squiz/Sniffs/Files/FileExtensionSniff.php | 68 + .../Formatting/OperatorBracketSniff.php | 402 + ...unctionDeclarationArgumentSpacingSniff.php | 398 + .../Functions/FunctionDeclarationSniff.php | 34 + .../FunctionDuplicateArgumentSniff.php | 64 + .../Sniffs/Functions/GlobalFunctionSniff.php | 61 + .../LowercaseFunctionKeywordsSniff.php | 69 + .../MultiLineFunctionDeclarationSniff.php | 262 + .../ValidFunctionNameSniff.php | 54 + .../ValidVariableNameSniff.php | 190 + .../DisallowObjectStringIndexSniff.php | 87 + .../Objects/ObjectInstantiationSniff.php | 85 + .../Sniffs/Objects/ObjectMemberCommaSniff.php | 66 + .../ComparisonOperatorUsageSniff.php | 235 + .../IncrementDecrementUsageSniff.php | 231 + .../Operators/ValidLogicalOperatorsSniff.php | 67 + .../Sniffs/PHP/CommentedOutCodeSniff.php | 283 + .../PHP/DisallowBooleanStatementSniff.php | 59 + .../PHP/DisallowComparisonAssignmentSniff.php | 112 + .../Sniffs/PHP/DisallowInlineIfSniff.php | 57 + .../PHP/DisallowMultipleAssignmentsSniff.php | 196 + .../PHP/DisallowSizeFunctionsInLoopsSniff.php | 116 + .../Sniffs/PHP/DiscouragedFunctionsSniff.php | 38 + .../Squiz/Sniffs/PHP/EmbeddedPhpSniff.php | 516 ++ .../Standards/Squiz/Sniffs/PHP/EvalSniff.php | 48 + .../Squiz/Sniffs/PHP/GlobalKeywordSniff.php | 53 + .../Squiz/Sniffs/PHP/HeredocSniff.php | 51 + .../Squiz/Sniffs/PHP/InnerFunctionsSniff.php | 76 + .../Sniffs/PHP/LowercasePHPFunctionsSniff.php | 167 + .../Sniffs/PHP/NonExecutableCodeSniff.php | 303 + .../Sniffs/Scope/MemberVarScopeSniff.php | 77 + .../Squiz/Sniffs/Scope/MethodScopeSniff.php | 83 + .../Sniffs/Scope/StaticThisUsageSniff.php | 128 + .../Strings/ConcatenationSpacingSniff.php | 164 + .../Sniffs/Strings/DoubleQuoteUsageSniff.php | 144 + .../Sniffs/Strings/EchoedStringsSniff.php | 88 + .../Sniffs/WhiteSpace/CastSpacingSniff.php | 65 + .../ControlStructureSpacingSniff.php | 359 + .../FunctionClosingBraceSpaceSniff.php | 164 + .../FunctionOpeningBraceSpaceSniff.php | 98 + .../WhiteSpace/FunctionSpacingSniff.php | 366 + .../LanguageConstructSpacingSniff.php | 91 + .../LogicalOperatorSpacingSniff.php | 102 + .../WhiteSpace/MemberVarSpacingSniff.php | 252 + .../WhiteSpace/ObjectOperatorSpacingSniff.php | 167 + .../WhiteSpace/OperatorSpacingSniff.php | 409 + .../WhiteSpace/PropertyLabelSpacingSniff.php | 81 + .../WhiteSpace/ScopeClosingBraceSniff.php | 114 + .../WhiteSpace/ScopeKeywordSpacingSniff.php | 172 + .../WhiteSpace/SemicolonSpacingSniff.php | 116 + .../WhiteSpace/SuperfluousWhitespaceSniff.php | 265 + .../Arrays/ArrayBracketSpacingUnitTest.inc | 31 + .../ArrayBracketSpacingUnitTest.inc.fixed | 31 + .../Arrays/ArrayBracketSpacingUnitTest.php | 62 + .../Arrays/ArrayDeclarationUnitTest.1.inc | 549 ++ .../ArrayDeclarationUnitTest.1.inc.fixed | 588 ++ .../Arrays/ArrayDeclarationUnitTest.2.inc | 538 ++ .../ArrayDeclarationUnitTest.2.inc.fixed | 575 ++ .../Tests/Arrays/ArrayDeclarationUnitTest.php | 255 + ...assDefinitionClosingBraceSpaceUnitTest.css | 81 + ...initionClosingBraceSpaceUnitTest.css.fixed | 85 + ...assDefinitionClosingBraceSpaceUnitTest.php | 65 + .../ClassDefinitionNameSpacingUnitTest.css | 66 + .../ClassDefinitionNameSpacingUnitTest.php | 56 + ...assDefinitionOpeningBraceSpaceUnitTest.css | 108 + ...initionOpeningBraceSpaceUnitTest.css.fixed | 106 + ...assDefinitionOpeningBraceSpaceUnitTest.php | 69 + .../Squiz/Tests/CSS/ColonSpacingUnitTest.css | 42 + .../Tests/CSS/ColonSpacingUnitTest.css.fixed | 40 + .../Squiz/Tests/CSS/ColonSpacingUnitTest.php | 65 + .../Tests/CSS/ColourDefinitionUnitTest.css | 16 + .../CSS/ColourDefinitionUnitTest.css.fixed | 16 + .../Tests/CSS/ColourDefinitionUnitTest.php | 57 + ...sallowMultipleStyleDefinitionsUnitTest.css | 17 + ...MultipleStyleDefinitionsUnitTest.css.fixed | 27 + ...sallowMultipleStyleDefinitionsUnitTest.php | 59 + .../CSS/DuplicateClassDefinitionUnitTest.css | 103 + .../CSS/DuplicateClassDefinitionUnitTest.php | 59 + .../CSS/DuplicateStyleDefinitionUnitTest.css | 27 + .../CSS/DuplicateStyleDefinitionUnitTest.php | 53 + .../CSS/EmptyClassDefinitionUnitTest.css | 15 + .../CSS/EmptyClassDefinitionUnitTest.php | 59 + .../CSS/EmptyStyleDefinitionUnitTest.css | 11 + .../CSS/EmptyStyleDefinitionUnitTest.php | 58 + .../Tests/CSS/ForbiddenStylesUnitTest.css | 18 + .../CSS/ForbiddenStylesUnitTest.css.fixed | 18 + .../Tests/CSS/ForbiddenStylesUnitTest.php | 62 + .../Squiz/Tests/CSS/IndentationUnitTest.1.css | 79 + .../Tests/CSS/IndentationUnitTest.1.css.fixed | 73 + .../Squiz/Tests/CSS/IndentationUnitTest.2.css | 3 + .../Squiz/Tests/CSS/IndentationUnitTest.php | 80 + .../CSS/LowercaseStyleDefinitionUnitTest.css | 14 + .../CSS/LowercaseStyleDefinitionUnitTest.php | 58 + .../Squiz/Tests/CSS/MissingColonUnitTest.css | 21 + .../Squiz/Tests/CSS/MissingColonUnitTest.php | 58 + .../Squiz/Tests/CSS/NamedColoursUnitTest.css | 25 + .../Squiz/Tests/CSS/NamedColoursUnitTest.php | 59 + .../Squiz/Tests/CSS/OpacityUnitTest.css | 35 + .../Squiz/Tests/CSS/OpacityUnitTest.css.fixed | 35 + .../Squiz/Tests/CSS/OpacityUnitTest.php | 65 + .../Tests/CSS/SemicolonSpacingUnitTest.css | 61 + .../CSS/SemicolonSpacingUnitTest.css.fixed | 58 + .../Tests/CSS/SemicolonSpacingUnitTest.php | 63 + .../Tests/CSS/ShorthandSizeUnitTest.1.css | 41 + .../CSS/ShorthandSizeUnitTest.1.css.fixed | 37 + .../Tests/CSS/ShorthandSizeUnitTest.2.css | 3 + .../Squiz/Tests/CSS/ShorthandSizeUnitTest.php | 72 + .../Classes/ClassDeclarationUnitTest.inc | 130 + .../ClassDeclarationUnitTest.inc.fixed | 140 + .../Classes/ClassDeclarationUnitTest.php | 91 + .../Tests/Classes/ClassFileNameUnitTest.inc | 45 + .../Tests/Classes/ClassFileNameUnitTest.php | 82 + .../Classes/DuplicatePropertyUnitTest.js | 45 + .../Classes/DuplicatePropertyUnitTest.php | 57 + .../LowercaseClassKeywordsUnitTest.inc | 16 + .../LowercaseClassKeywordsUnitTest.inc.fixed | 16 + .../LowercaseClassKeywordsUnitTest.php | 66 + .../Classes/SelfMemberReferenceUnitTest.inc | 199 + .../SelfMemberReferenceUnitTest.inc.fixed | 187 + .../Classes/SelfMemberReferenceUnitTest.php | 71 + .../Tests/Classes/ValidClassNameUnitTest.inc | 191 + .../Tests/Classes/ValidClassNameUnitTest.php | 80 + .../Tests/Commenting/BlockCommentUnitTest.inc | 309 + .../Commenting/BlockCommentUnitTest.inc.fixed | 311 + .../Tests/Commenting/BlockCommentUnitTest.php | 109 + .../Tests/Commenting/ClassCommentUnitTest.inc | 145 + .../Tests/Commenting/ClassCommentUnitTest.php | 66 + .../ClosingDeclarationCommentUnitTest.1.inc | 124 + ...singDeclarationCommentUnitTest.1.inc.fixed | 117 + .../ClosingDeclarationCommentUnitTest.2.inc | 7 + .../ClosingDeclarationCommentUnitTest.3.inc | 7 + .../ClosingDeclarationCommentUnitTest.4.inc | 8 + ...singDeclarationCommentUnitTest.4.inc.fixed | 8 + .../ClosingDeclarationCommentUnitTest.5.inc | 11 + ...singDeclarationCommentUnitTest.5.inc.fixed | 11 + .../ClosingDeclarationCommentUnitTest.php | 96 + .../DocCommentAlignmentUnitTest.inc | 103 + .../DocCommentAlignmentUnitTest.inc.fixed | 103 + .../Commenting/DocCommentAlignmentUnitTest.js | 76 + .../DocCommentAlignmentUnitTest.js.fixed | 76 + .../DocCommentAlignmentUnitTest.php | 81 + .../Commenting/EmptyCatchCommentUnitTest.inc | 55 + .../Commenting/EmptyCatchCommentUnitTest.php | 60 + .../Commenting/FileCommentUnitTest.1.inc | 43 + .../FileCommentUnitTest.1.inc.fixed | 43 + .../Tests/Commenting/FileCommentUnitTest.1.js | 40 + .../Commenting/FileCommentUnitTest.1.js.fixed | 40 + .../Commenting/FileCommentUnitTest.10.inc | 12 + .../Commenting/FileCommentUnitTest.2.inc | 11 + .../Tests/Commenting/FileCommentUnitTest.2.js | 10 + .../Commenting/FileCommentUnitTest.3.inc | 9 + .../Commenting/FileCommentUnitTest.4.inc | 3 + .../Commenting/FileCommentUnitTest.5.inc | 4 + .../Commenting/FileCommentUnitTest.6.inc | 12 + .../Commenting/FileCommentUnitTest.7.inc | 12 + .../Commenting/FileCommentUnitTest.8.inc | 9 + .../Commenting/FileCommentUnitTest.9.inc | 12 + .../Tests/Commenting/FileCommentUnitTest.php | 82 + .../FunctionCommentThrowTagUnitTest.inc | 511 ++ .../FunctionCommentThrowTagUnitTest.php | 65 + .../Commenting/FunctionCommentUnitTest.inc | 1160 +++ .../FunctionCommentUnitTest.inc.fixed | 1160 +++ .../Commenting/FunctionCommentUnitTest.php | 208 + .../Commenting/InlineCommentUnitTest.inc | 196 + .../InlineCommentUnitTest.inc.fixed | 189 + .../Tests/Commenting/InlineCommentUnitTest.js | 129 + .../Commenting/InlineCommentUnitTest.js.fixed | 125 + .../Commenting/InlineCommentUnitTest.php | 96 + .../LongConditionClosingCommentUnitTest.inc | 1033 +++ ...gConditionClosingCommentUnitTest.inc.fixed | 1033 +++ .../LongConditionClosingCommentUnitTest.js | 444 + ...ngConditionClosingCommentUnitTest.js.fixed | 444 + .../LongConditionClosingCommentUnitTest.php | 107 + .../PostStatementCommentUnitTest.1.js | 36 + .../PostStatementCommentUnitTest.1.js.fixed | 39 + .../PostStatementCommentUnitTest.2.js | 2 + .../PostStatementCommentUnitTest.inc | 64 + .../PostStatementCommentUnitTest.inc.fixed | 71 + .../PostStatementCommentUnitTest.php | 80 + .../Commenting/VariableCommentUnitTest.inc | 456 + .../VariableCommentUnitTest.inc.fixed | 456 + .../Commenting/VariableCommentUnitTest.php | 88 + .../ControlSignatureUnitTest.1.inc | 320 + .../ControlSignatureUnitTest.1.inc.fixed | 324 + .../ControlSignatureUnitTest.2.inc | 5 + .../ControlSignatureUnitTest.js | 135 + .../ControlSignatureUnitTest.js.fixed | 141 + .../ControlSignatureUnitTest.php | 115 + .../ElseIfDeclarationUnitTest.inc | 14 + .../ElseIfDeclarationUnitTest.inc.fixed | 14 + .../ElseIfDeclarationUnitTest.php | 56 + .../ForEachLoopDeclarationUnitTest.inc | 36 + .../ForEachLoopDeclarationUnitTest.inc.fixed | 36 + .../ForEachLoopDeclarationUnitTest.php | 61 + .../ForLoopDeclarationUnitTest.1.inc | 126 + .../ForLoopDeclarationUnitTest.1.inc.fixed | 92 + .../ForLoopDeclarationUnitTest.1.js | 122 + .../ForLoopDeclarationUnitTest.1.js.fixed | 88 + .../ForLoopDeclarationUnitTest.2.inc | 6 + .../ForLoopDeclarationUnitTest.2.js | 2 + .../ForLoopDeclarationUnitTest.3.inc | 6 + .../ForLoopDeclarationUnitTest.php | 138 + .../InlineIfDeclarationUnitTest.inc | 48 + .../InlineIfDeclarationUnitTest.inc.fixed | 48 + .../InlineIfDeclarationUnitTest.php | 80 + .../LowercaseDeclarationUnitTest.inc | 24 + .../LowercaseDeclarationUnitTest.inc.fixed | 24 + .../LowercaseDeclarationUnitTest.php | 66 + .../SwitchDeclarationUnitTest.inc | 333 + .../SwitchDeclarationUnitTest.inc.fixed | 342 + .../SwitchDeclarationUnitTest.js | 287 + .../SwitchDeclarationUnitTest.php | 157 + .../Squiz/Tests/Debug/JSLintUnitTest.js | 2 + .../Squiz/Tests/Debug/JSLintUnitTest.php | 74 + .../Tests/Debug/JavaScriptLintUnitTest.js | 2 + .../Tests/Debug/JavaScriptLintUnitTest.php | 71 + .../Tests/Files/FileExtensionUnitTest.1.inc | 3 + .../Tests/Files/FileExtensionUnitTest.2.inc | 3 + .../Tests/Files/FileExtensionUnitTest.3.inc | 3 + .../Tests/Files/FileExtensionUnitTest.4.inc | 3 + .../Tests/Files/FileExtensionUnitTest.5.inc | 3 + .../Tests/Files/FileExtensionUnitTest.php | 60 + .../Formatting/OperatorBracketUnitTest.1.inc | 203 + .../OperatorBracketUnitTest.1.inc.fixed | 203 + .../Formatting/OperatorBracketUnitTest.2.inc | 7 + .../Formatting/OperatorBracketUnitTest.3.inc | 5 + .../Formatting/OperatorBracketUnitTest.js | 118 + .../OperatorBracketUnitTest.js.fixed | 118 + .../Formatting/OperatorBracketUnitTest.php | 121 + ...tionDeclarationArgumentSpacingUnitTest.inc | 111 + ...clarationArgumentSpacingUnitTest.inc.fixed | 111 + ...tionDeclarationArgumentSpacingUnitTest.php | 91 + .../FunctionDeclarationUnitTest.1.inc | 75 + .../FunctionDeclarationUnitTest.2.inc | 5 + .../FunctionDeclarationUnitTest.3.inc | 5 + .../Functions/FunctionDeclarationUnitTest.php | 64 + .../FunctionDuplicateArgumentUnitTest.inc | 6 + .../FunctionDuplicateArgumentUnitTest.php | 57 + .../Functions/GlobalFunctionUnitTest.inc | 17 + .../Functions/GlobalFunctionUnitTest.php | 53 + .../LowercaseFunctionKeywordsUnitTest.inc | 28 + ...owercaseFunctionKeywordsUnitTest.inc.fixed | 28 + .../LowercaseFunctionKeywordsUnitTest.php | 63 + .../MultiLineFunctionDeclarationUnitTest.inc | 356 + ...iLineFunctionDeclarationUnitTest.inc.fixed | 370 + .../MultiLineFunctionDeclarationUnitTest.js | 73 + ...tiLineFunctionDeclarationUnitTest.js.fixed | 81 + .../MultiLineFunctionDeclarationUnitTest.php | 120 + .../ValidFunctionNameUnitTest.inc | 27 + .../ValidFunctionNameUnitTest.php | 64 + .../ValidVariableNameUnitTest.inc | 157 + .../ValidVariableNameUnitTest.php | 93 + .../DisallowObjectStringIndexUnitTest.js | 37 + .../DisallowObjectStringIndexUnitTest.php | 64 + .../Objects/ObjectInstantiationUnitTest.inc | 49 + .../Objects/ObjectInstantiationUnitTest.php | 58 + .../Objects/ObjectMemberCommaUnitTest.js | 47 + .../ObjectMemberCommaUnitTest.js.fixed | 47 + .../Objects/ObjectMemberCommaUnitTest.php | 58 + .../ComparisonOperatorUsageUnitTest.inc | 138 + .../ComparisonOperatorUsageUnitTest.js | 71 + .../ComparisonOperatorUsageUnitTest.php | 105 + .../IncrementDecrementUsageUnitTest.inc | 56 + .../IncrementDecrementUsageUnitTest.php | 73 + .../ValidLogicalOperatorsUnitTest.inc | 28 + .../ValidLogicalOperatorsUnitTest.php | 57 + .../Tests/PHP/CommentedOutCodeUnitTest.css | 23 + .../Tests/PHP/CommentedOutCodeUnitTest.inc | 158 + .../Tests/PHP/CommentedOutCodeUnitTest.php | 80 + .../PHP/DisallowBooleanStatementUnitTest.inc | 27 + .../PHP/DisallowBooleanStatementUnitTest.php | 58 + .../DisallowComparisonAssignmentUnitTest.inc | 83 + .../DisallowComparisonAssignmentUnitTest.php | 64 + .../Tests/PHP/DisallowInlineIfUnitTest.inc | 18 + .../Tests/PHP/DisallowInlineIfUnitTest.js | 2 + .../Tests/PHP/DisallowInlineIfUnitTest.php | 67 + .../DisallowMultipleAssignmentsUnitTest.1.inc | 150 + .../DisallowMultipleAssignmentsUnitTest.2.inc | 7 + .../DisallowMultipleAssignmentsUnitTest.php | 71 + .../DisallowSizeFunctionsInLoopsUnitTest.inc | 58 + .../DisallowSizeFunctionsInLoopsUnitTest.js | 13 + .../DisallowSizeFunctionsInLoopsUnitTest.php | 77 + .../PHP/DiscouragedFunctionsUnitTest.inc | 7 + .../PHP/DiscouragedFunctionsUnitTest.php | 57 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc | 275 + .../Tests/PHP/EmbeddedPhpUnitTest.1.inc.fixed | 287 + .../Tests/PHP/EmbeddedPhpUnitTest.10.inc | 16 + .../Tests/PHP/EmbeddedPhpUnitTest.11.inc | 14 + .../Tests/PHP/EmbeddedPhpUnitTest.12.inc | 12 + .../PHP/EmbeddedPhpUnitTest.12.inc.fixed | 10 + .../Tests/PHP/EmbeddedPhpUnitTest.13.inc | 12 + .../PHP/EmbeddedPhpUnitTest.13.inc.fixed | 10 + .../Tests/PHP/EmbeddedPhpUnitTest.14.inc | 8 + .../Tests/PHP/EmbeddedPhpUnitTest.15.inc | 9 + .../Tests/PHP/EmbeddedPhpUnitTest.16.inc | 8 + .../Tests/PHP/EmbeddedPhpUnitTest.17.inc | 8 + .../Tests/PHP/EmbeddedPhpUnitTest.18.inc | 15 + .../PHP/EmbeddedPhpUnitTest.18.inc.fixed | 13 + .../Tests/PHP/EmbeddedPhpUnitTest.19.inc | 17 + .../PHP/EmbeddedPhpUnitTest.19.inc.fixed | 15 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc | 7 + .../Tests/PHP/EmbeddedPhpUnitTest.2.inc.fixed | 7 + .../Tests/PHP/EmbeddedPhpUnitTest.20.inc | 15 + .../PHP/EmbeddedPhpUnitTest.20.inc.fixed | 16 + .../Tests/PHP/EmbeddedPhpUnitTest.21.inc | 15 + .../PHP/EmbeddedPhpUnitTest.21.inc.fixed | 16 + .../Tests/PHP/EmbeddedPhpUnitTest.22.inc | 30 + .../PHP/EmbeddedPhpUnitTest.22.inc.fixed | 31 + .../Tests/PHP/EmbeddedPhpUnitTest.23.inc | 23 + .../Tests/PHP/EmbeddedPhpUnitTest.24.inc | 25 + .../PHP/EmbeddedPhpUnitTest.24.inc.fixed | 25 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.3.inc | 123 + .../Tests/PHP/EmbeddedPhpUnitTest.3.inc.fixed | 132 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.4.inc | 7 + .../Tests/PHP/EmbeddedPhpUnitTest.4.inc.fixed | 7 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.5.inc | 48 + .../Tests/PHP/EmbeddedPhpUnitTest.5.inc.fixed | 39 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.6.inc | 8 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.7.inc | 8 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.8.inc | 10 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.9.inc | 10 + .../Squiz/Tests/PHP/EmbeddedPhpUnitTest.php | 226 + .../Squiz/Tests/PHP/EvalUnitTest.inc | 5 + .../Squiz/Tests/PHP/EvalUnitTest.php | 56 + .../Squiz/Tests/PHP/GlobalKeywordUnitTest.inc | 13 + .../Squiz/Tests/PHP/GlobalKeywordUnitTest.php | 56 + .../Squiz/Tests/PHP/HeredocUnitTest.1.inc | 12 + .../Squiz/Tests/PHP/HeredocUnitTest.2.inc | 17 + .../Squiz/Tests/PHP/HeredocUnitTest.php | 64 + .../Tests/PHP/InnerFunctionsUnitTest.inc | 87 + .../Tests/PHP/InnerFunctionsUnitTest.php | 58 + .../PHP/LowercasePHPFunctionsUnitTest.inc | 50 + .../LowercasePHPFunctionsUnitTest.inc.fixed | 50 + .../PHP/LowercasePHPFunctionsUnitTest.php | 60 + .../Tests/PHP/NonExecutableCodeUnitTest.1.inc | 420 + .../Tests/PHP/NonExecutableCodeUnitTest.2.inc | 73 + .../Tests/PHP/NonExecutableCodeUnitTest.3.inc | 64 + .../Tests/PHP/NonExecutableCodeUnitTest.4.inc | 6 + .../Tests/PHP/NonExecutableCodeUnitTest.php | 124 + .../Tests/Scope/MemberVarScopeUnitTest.inc | 72 + .../Tests/Scope/MemberVarScopeUnitTest.php | 63 + .../Squiz/Tests/Scope/MethodScopeUnitTest.inc | 57 + .../Squiz/Tests/Scope/MethodScopeUnitTest.php | 58 + .../Tests/Scope/StaticThisUsageUnitTest.inc | 127 + .../Tests/Scope/StaticThisUsageUnitTest.php | 67 + .../Strings/ConcatenationSpacingUnitTest.inc | 49 + .../ConcatenationSpacingUnitTest.inc.fixed | 47 + .../Strings/ConcatenationSpacingUnitTest.php | 71 + .../Strings/DoubleQuoteUsageUnitTest.inc | 37 + .../DoubleQuoteUsageUnitTest.inc.fixed | 37 + .../Strings/DoubleQuoteUsageUnitTest.php | 67 + .../Tests/Strings/EchoedStringsUnitTest.inc | 13 + .../Strings/EchoedStringsUnitTest.inc.fixed | 13 + .../Tests/Strings/EchoedStringsUnitTest.php | 60 + .../Tests/WhiteSpace/CastSpacingUnitTest.inc | 9 + .../WhiteSpace/CastSpacingUnitTest.inc.fixed | 9 + .../Tests/WhiteSpace/CastSpacingUnitTest.php | 59 + .../ControlStructureSpacingUnitTest.inc | 269 + .../ControlStructureSpacingUnitTest.inc.fixed | 261 + .../ControlStructureSpacingUnitTest.js | 93 + .../ControlStructureSpacingUnitTest.js.fixed | 93 + .../ControlStructureSpacingUnitTest.php | 107 + .../FunctionClosingBraceSpaceUnitTest.inc | 39 + ...unctionClosingBraceSpaceUnitTest.inc.fixed | 45 + .../FunctionClosingBraceSpaceUnitTest.js | 132 + ...FunctionClosingBraceSpaceUnitTest.js.fixed | 133 + .../FunctionClosingBraceSpaceUnitTest.php | 80 + .../FunctionOpeningBraceSpaceUnitTest.inc | 54 + ...unctionOpeningBraceSpaceUnitTest.inc.fixed | 49 + .../FunctionOpeningBraceSpaceUnitTest.js | 115 + ...FunctionOpeningBraceSpaceUnitTest.js.fixed | 109 + .../FunctionOpeningBraceSpaceUnitTest.php | 73 + .../WhiteSpace/FunctionSpacingUnitTest.1.inc | 584 ++ .../FunctionSpacingUnitTest.1.inc.fixed | 673 ++ .../WhiteSpace/FunctionSpacingUnitTest.2.inc | 5 + .../FunctionSpacingUnitTest.2.inc.fixed | 7 + .../WhiteSpace/FunctionSpacingUnitTest.3.inc | 10 + .../FunctionSpacingUnitTest.3.inc.fixed | 7 + .../WhiteSpace/FunctionSpacingUnitTest.4.inc | 7 + .../WhiteSpace/FunctionSpacingUnitTest.5.inc | 8 + .../FunctionSpacingUnitTest.5.inc.fixed | 10 + .../WhiteSpace/FunctionSpacingUnitTest.6.inc | 13 + .../FunctionSpacingUnitTest.6.inc.fixed | 10 + .../WhiteSpace/FunctionSpacingUnitTest.7.inc | 10 + .../WhiteSpace/FunctionSpacingUnitTest.php | 141 + .../LanguageConstructSpacingUnitTest.inc | 43 + ...LanguageConstructSpacingUnitTest.inc.fixed | 41 + .../LanguageConstructSpacingUnitTest.php | 65 + .../LogicalOperatorSpacingUnitTest.inc | 19 + .../LogicalOperatorSpacingUnitTest.inc.fixed | 19 + .../LogicalOperatorSpacingUnitTest.js | 19 + .../LogicalOperatorSpacingUnitTest.js.fixed | 19 + .../LogicalOperatorSpacingUnitTest.php | 59 + .../WhiteSpace/MemberVarSpacingUnitTest.inc | 374 + .../MemberVarSpacingUnitTest.inc.fixed | 359 + .../WhiteSpace/MemberVarSpacingUnitTest.php | 90 + .../ObjectOperatorSpacingUnitTest.inc | 52 + .../ObjectOperatorSpacingUnitTest.inc.fixed | 48 + .../ObjectOperatorSpacingUnitTest.php | 73 + .../WhiteSpace/OperatorSpacingUnitTest.1.inc | 510 ++ .../OperatorSpacingUnitTest.1.inc.fixed | 502 ++ .../WhiteSpace/OperatorSpacingUnitTest.2.inc | 3 + .../WhiteSpace/OperatorSpacingUnitTest.3.inc | 6 + .../WhiteSpace/OperatorSpacingUnitTest.js | 104 + .../OperatorSpacingUnitTest.js.fixed | 98 + .../WhiteSpace/OperatorSpacingUnitTest.php | 180 + .../PropertyLabelSpacingUnitTest.js | 40 + .../PropertyLabelSpacingUnitTest.js.fixed | 39 + .../PropertyLabelSpacingUnitTest.php | 60 + .../WhiteSpace/ScopeClosingBraceUnitTest.inc | 134 + .../ScopeClosingBraceUnitTest.inc.fixed | 138 + .../WhiteSpace/ScopeClosingBraceUnitTest.php | 64 + .../ScopeKeywordSpacingUnitTest.1.inc | 149 + .../ScopeKeywordSpacingUnitTest.1.inc.fixed | 143 + .../ScopeKeywordSpacingUnitTest.2.inc | 6 + .../ScopeKeywordSpacingUnitTest.3.inc | 6 + .../ScopeKeywordSpacingUnitTest.3.inc.fixed | 6 + .../ScopeKeywordSpacingUnitTest.php | 88 + .../WhiteSpace/SemicolonSpacingUnitTest.inc | 42 + .../SemicolonSpacingUnitTest.inc.fixed | 41 + .../WhiteSpace/SemicolonSpacingUnitTest.js | 25 + .../SemicolonSpacingUnitTest.js.fixed | 25 + .../WhiteSpace/SemicolonSpacingUnitTest.php | 87 + .../SuperfluousWhitespaceUnitTest.1.css | 32 + .../SuperfluousWhitespaceUnitTest.1.css.fixed | 30 + .../SuperfluousWhitespaceUnitTest.1.inc | 74 + .../SuperfluousWhitespaceUnitTest.1.inc.fixed | 68 + .../SuperfluousWhitespaceUnitTest.1.js | 56 + .../SuperfluousWhitespaceUnitTest.1.js.fixed | 50 + .../SuperfluousWhitespaceUnitTest.2.css | 3 + .../SuperfluousWhitespaceUnitTest.2.css.fixed | 3 + .../SuperfluousWhitespaceUnitTest.2.inc | 9 + .../SuperfluousWhitespaceUnitTest.2.inc.fixed | 7 + .../SuperfluousWhitespaceUnitTest.2.js | 1 + .../SuperfluousWhitespaceUnitTest.2.js.fixed | 1 + .../SuperfluousWhitespaceUnitTest.3.css | 3 + .../SuperfluousWhitespaceUnitTest.3.css.fixed | 3 + .../SuperfluousWhitespaceUnitTest.3.inc | 14 + .../SuperfluousWhitespaceUnitTest.3.inc.fixed | 5 + .../SuperfluousWhitespaceUnitTest.3.js | 1 + .../SuperfluousWhitespaceUnitTest.3.js.fixed | 1 + .../SuperfluousWhitespaceUnitTest.4.inc | 4 + .../SuperfluousWhitespaceUnitTest.4.inc.fixed | 4 + .../SuperfluousWhitespaceUnitTest.5.inc | 5 + .../SuperfluousWhitespaceUnitTest.5.inc.fixed | 4 + .../SuperfluousWhitespaceUnitTest.php | 117 + .../src/Standards/Squiz/ruleset.xml | 132 + .../Zend/Docs/Debug/CodeAnalyzerStandard.xml | 25 + .../Zend/Docs/Files/ClosingTagStandard.xml | 22 + .../ValidVariableNameStandard.xml | 37 + .../Zend/Sniffs/Debug/CodeAnalyzerSniff.php | 100 + .../Zend/Sniffs/Files/ClosingTagSniff.php | 79 + .../ValidVariableNameSniff.php | 196 + .../Zend/Tests/Debug/CodeAnalyzerUnitTest.inc | 6 + .../Zend/Tests/Debug/CodeAnalyzerUnitTest.php | 71 + .../Zend/Tests/Files/ClosingTagUnitTest.1.inc | 12 + .../Files/ClosingTagUnitTest.1.inc.fixed | 12 + .../Zend/Tests/Files/ClosingTagUnitTest.2.inc | 3 + .../Zend/Tests/Files/ClosingTagUnitTest.3.inc | 1 + .../Files/ClosingTagUnitTest.3.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.4.inc | 1 + .../Files/ClosingTagUnitTest.4.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.5.inc | 1 + .../Files/ClosingTagUnitTest.5.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.6.inc | 3 + .../Files/ClosingTagUnitTest.6.inc.fixed | 3 + .../Zend/Tests/Files/ClosingTagUnitTest.7.inc | 1 + .../Files/ClosingTagUnitTest.7.inc.fixed | 1 + .../Zend/Tests/Files/ClosingTagUnitTest.php | 70 + .../ValidVariableNameUnitTest.inc | 131 + .../ValidVariableNameUnitTest.php | 102 + .../src/Standards/Zend/ruleset.xml | 32 + .../php_codesniffer/src/Tokenizers/CSS.php | 541 ++ .../src/Tokenizers/Comment.php | 283 + .../php_codesniffer/src/Tokenizers/JS.php | 1256 +++ .../php_codesniffer/src/Tokenizers/PHP.php | 4002 +++++++++ .../src/Tokenizers/Tokenizer.php | 1738 ++++ .../php_codesniffer/src/Util/Cache.php | 355 + .../php_codesniffer/src/Util/Common.php | 605 ++ .../php_codesniffer/src/Util/Help.php | 625 ++ .../php_codesniffer/src/Util/Standards.php | 340 + .../php_codesniffer/src/Util/Timing.php | 133 + .../php_codesniffer/src/Util/Tokens.php | 814 ++ .../php_codesniffer/tests/AllTests.php | 58 + .../php_codesniffer/tests/ConfigDouble.php | 212 + .../tests/Core/AbstractMethodUnitTest.php | 223 + .../php_codesniffer/tests/Core/AllTests.php | 63 + .../Autoloader/DetermineLoadedClassTest.php | 126 + .../tests/Core/Autoloader/TestFiles/A.inc | 3 + .../tests/Core/Autoloader/TestFiles/B.inc | 4 + .../tests/Core/Autoloader/TestFiles/C.inc | 4 + .../tests/Core/Autoloader/TestFiles/Sub/C.inc | 5 + .../tests/Core/Config/ReportWidthTest.php | 332 + .../Core/Config/SniffsExcludeArgsTest.php | 200 + .../tests/Core/ErrorSuppressionTest.php | 1278 +++ .../Core/File/FindEndOfStatementTest.inc | 105 + .../Core/File/FindEndOfStatementTest.php | 457 + .../Core/File/FindExtendedClassNameTest.inc | 52 + .../Core/File/FindExtendedClassNameTest.php | 145 + .../FindImplementedInterfaceNamesTest.inc | 47 + .../FindImplementedInterfaceNamesTest.php | 162 + .../Core/File/FindStartOfStatementTest.inc | 200 + .../Core/File/FindStartOfStatementTest.php | 973 +++ .../Core/File/GetClassPropertiesTest.inc | 58 + .../Core/File/GetClassPropertiesTest.php | 192 + .../tests/Core/File/GetConditionTest.inc | 91 + .../tests/Core/File/GetConditionTest.php | 494 ++ .../Core/File/GetDeclarationNameJSTest.js | 23 + .../Core/File/GetDeclarationNameJSTest.php | 158 + .../Core/File/GetDeclarationNameTest.inc | 102 + .../Core/File/GetDeclarationNameTest.php | 225 + .../Core/File/GetMemberPropertiesTest.inc | 356 + .../Core/File/GetMemberPropertiesTest.php | 1191 +++ .../GetMethodParametersParseError1Test.inc | 4 + .../GetMethodParametersParseError1Test.php | 38 + .../GetMethodParametersParseError2Test.inc | 4 + .../GetMethodParametersParseError2Test.php | 38 + .../Core/File/GetMethodParametersTest.inc | 338 + .../Core/File/GetMethodParametersTest.php | 3182 +++++++ .../Core/File/GetMethodPropertiesTest.inc | 226 + .../Core/File/GetMethodPropertiesTest.php | 1562 ++++ .../tests/Core/File/GetTokensAsStringTest.inc | 25 + .../tests/Core/File/GetTokensAsStringTest.php | 334 + .../tests/Core/File/IsReferenceTest.inc | 216 + .../tests/Core/File/IsReferenceTest.php | 396 + .../Core/Filters/AbstractFilterTestCase.php | 250 + .../tests/Core/Filters/Filter/AcceptTest.php | 110 + .../tests/Core/Filters/Filter/AcceptTest.xml | 16 + .../tests/Core/Filters/GitModifiedTest.php | 268 + .../tests/Core/Filters/GitStagedTest.php | 268 + .../GenerateDiffTest-BlankLinesAtEnd.diff | 10 + .../GenerateDiffTest-BlankLinesAtEnd.inc | 11 + .../GenerateDiffTest-BlankLinesAtStart.diff | 9 + .../GenerateDiffTest-BlankLinesAtStart.inc | 10 + .../Fixtures/GenerateDiffTest-LineAdded.diff | 8 + .../Fixtures/GenerateDiffTest-LineAdded.inc | 6 + .../GenerateDiffTest-LineRemoved.diff | 8 + .../Fixtures/GenerateDiffTest-LineRemoved.inc | 8 + .../Fixtures/GenerateDiffTest-NoDiff.diff | 0 .../Fixtures/GenerateDiffTest-NoDiff.inc | 7 + ...GenerateDiffTest-NoTrailingWhitespace.diff | 9 + .../GenerateDiffTest-NoTrailingWhitespace.inc | 7 + .../GenerateDiffTest-TabsToSpaces.diff | 9 + .../GenerateDiffTest-TabsToSpaces.inc | 7 + .../GenerateDiffTest-VarNameChanged.diff | 12 + .../GenerateDiffTest-VarNameChanged.inc | 7 + .../GenerateDiffTest-WhiteSpaceAtEnd.diff | 8 + .../GenerateDiffTest-WhiteSpaceAtEnd.inc | 7 + .../GenerateDiffTest-WhiteSpaceAtStart.diff | 8 + .../GenerateDiffTest-WhiteSpaceAtStart.inc | 7 + .../GenerateDiffTest-WindowsLineEndings.inc | 7 + .../Core/Fixer/Fixtures/GenerateDiffTest.inc | 7 + .../tests/Core/Fixer/GenerateDiffTest.php | 227 + .../Expectations/ExpectedOutputEmpty.txt | 0 .../Expectations/ExpectedOutputNoDocs.html | 78 + .../Expectations/ExpectedOutputNoDocs.md | 2 + .../Expectations/ExpectedOutputOneDoc.html | 82 + .../Expectations/ExpectedOutputOneDoc.md | 5 + .../Expectations/ExpectedOutputOneDoc.txt | 7 + .../ExpectedOutputStructureDocs.html | 191 + .../ExpectedOutputStructureDocs.md | 171 + .../ExpectedOutputStructureDocs.txt | 111 + .../Core/Generators/Fixtures/HTMLDouble.php | 40 + .../Generators/Fixtures/MarkdownDouble.php | 36 + .../Generators/Fixtures/MockGenerator.php | 28 + .../Docs/Structure/NoContentStandard.xml | 2 + .../NoDocumentationElementStandard.xml | 2 + .../OneCodeComparisonNoStandardStandard.xml | 14 + ...OneStandardBlockCodeComparisonStandard.xml | 19 + .../OneStandardBlockNoCodeStandard.xml | 7 + ...tandardBlockTwoCodeComparisonsStandard.xml | 31 + .../TwoStandardBlocksNoCodeStandard.xml | 12 + ...tandardBlocksOneCodeComparisonStandard.xml | 24 + ...dardBlocksThreeCodeComparisonsStandard.xml | 48 + .../StandardWithDocs/Sniffs/DummySniff.php | 25 + .../Structure/DocumentationMissingSniff.php | 12 + .../Sniffs/Structure/NoContentSniff.php | 12 + .../Structure/NoDocumentationElementSniff.php | 12 + .../OneCodeComparisonNoStandardSniff.php | 12 + .../OneStandardBlockCodeComparisonSniff.php | 12 + .../Structure/OneStandardBlockNoCodeSniff.php | 12 + ...neStandardBlockTwoCodeComparisonsSniff.php | 12 + .../TwoStandardBlocksNoCodeSniff.php | 12 + ...woStandardBlocksOneCodeComparisonSniff.php | 12 + ...tandardBlocksThreeCodeComparisonsSniff.php | 12 + .../Fixtures/StandardWithDocs/ruleset.xml | 4 + .../tests/Core/Generators/GeneratorTest.php | 241 + .../tests/Core/Generators/HTMLTest.php | 104 + .../tests/Core/Generators/MarkdownTest.php | 102 + .../tests/Core/Generators/NoDocsTest.xml | 8 + .../tests/Core/Generators/NoValidDocsTest.xml | 8 + .../tests/Core/Generators/OneDocTest.xml | 8 + .../Core/Generators/StructureDocsTest.xml | 10 + .../tests/Core/Generators/TextTest.php | 80 + .../Core/Ruleset/ExplainCustomRulesetTest.xml | 10 + .../Core/Ruleset/ExplainSingleSniffTest.xml | 6 + .../tests/Core/Ruleset/ExplainTest.php | 258 + .../Deprecated/WithLongReplacementSniff.php | 41 + ...eplacementContainingLinuxNewlinesSniff.php | 45 + ...WithReplacementContainingNewlinesSniff.php | 45 + .../Deprecated/WithReplacementSniff.php | 41 + .../Deprecated/WithoutReplacementSniff.php | 41 + .../EmptyDeprecationVersionSniff.php | 41 + .../EmptyRemovalVersionSniff.php | 41 + .../InvalidDeprecationMessageSniff.php | 42 + .../InvalidDeprecationVersionSniff.php | 41 + .../InvalidRemovalVersionSniff.php | 41 + .../SetProperty/AllowedAsDeclaredSniff.php | 28 + .../AllowedViaMagicMethodSniff.php | 40 + .../SetProperty/AllowedViaStdClassSniff.php | 26 + .../NotAllowedViaAttributeSniff.php | 27 + .../tests/Core/Ruleset/Fixtures/ruleset.xml | 4 + .../RuleInclusionAbsoluteLinuxTest.php | 119 + .../RuleInclusionAbsoluteLinuxTest.xml | 11 + .../RuleInclusionAbsoluteWindowsTest.php | 116 + .../RuleInclusionAbsoluteWindowsTest.xml | 11 + .../Ruleset/RuleInclusionTest-include.xml | 10 + .../tests/Core/Ruleset/RuleInclusionTest.php | 486 ++ .../tests/Core/Ruleset/RuleInclusionTest.xml | 58 + .../SetPropertyAllowedAsDeclaredTest.xml | 16 + .../SetPropertyAllowedViaMagicMethodTest.xml | 16 + .../SetPropertyAllowedViaStdClassTest.xml | 16 + ...PropertyToMultipleSniffsInCategoryTest.xml | 9 + ...nInvalidPropertyWhenSetForCategoryTest.xml | 9 + ...nInvalidPropertyWhenSetForStandardTest.xml | 9 + .../SetPropertyNotAllowedViaAttributeTest.xml | 10 + ...opertyThrowsErrorOnInvalidPropertyTest.xml | 9 + .../Core/Ruleset/SetSniffPropertyTest.php | 402 + ...eprecationsEmptyDeprecationVersionTest.xml | 8 + ...iffDeprecationsEmptyRemovalVersionTest.xml | 8 + ...recationsInvalidDeprecationMessageTest.xml | 8 + ...recationsInvalidDeprecationVersionTest.xml | 8 + ...fDeprecationsInvalidRemovalVersionTest.xml | 8 + .../ShowSniffDeprecationsOrderTest.xml | 10 + .../ShowSniffDeprecationsReportWidthTest.xml | 8 + .../Ruleset/ShowSniffDeprecationsTest.php | 510 ++ .../Ruleset/ShowSniffDeprecationsTest.xml | 10 + .../Core/Sniffs/AbstractArraySniffTest.inc | 51 + .../Core/Sniffs/AbstractArraySniffTest.php | 297 + .../Sniffs/AbstractArraySniffTestable.php | 65 + .../Tokenizers/AbstractTokenizerTestCase.php | 126 + .../Tokenizers/Comment/CommentTestCase.php | 117 + .../Tokenizers/Comment/LiveCoding1Test.inc | 6 + .../Tokenizers/Comment/LiveCoding1Test.php | 69 + .../Tokenizers/Comment/LiveCoding2Test.inc | 5 + .../Tokenizers/Comment/LiveCoding2Test.php | 68 + .../Tokenizers/Comment/LiveCoding3Test.inc | 4 + .../Tokenizers/Comment/LiveCoding3Test.php | 62 + .../Tokenizers/Comment/LiveCoding4Test.inc | 7 + .../Tokenizers/Comment/LiveCoding4Test.php | 76 + .../Comment/MultiLineDocBlockTest.inc | 81 + .../Comment/MultiLineDocBlockTest.php | 439 + .../PhpcsAnnotationsInDocBlockTest.inc | 116 + .../PhpcsAnnotationsInDocBlockTest.php | 637 ++ .../Comment/SingleLineDocBlockTest.inc | 26 + .../Comment/SingleLineDocBlockTest.php | 217 + .../PHP/AnonClassParenthesisOwnerTest.inc | 29 + .../PHP/AnonClassParenthesisOwnerTest.php | 158 + .../Core/Tokenizers/PHP/ArrayKeywordTest.inc | 58 + .../Core/Tokenizers/PHP/ArrayKeywordTest.php | 200 + .../Core/Tokenizers/PHP/AttributesTest.inc | 90 + .../Core/Tokenizers/PHP/AttributesTest.php | 704 ++ .../Core/Tokenizers/PHP/BackfillEnumTest.inc | 91 + .../Core/Tokenizers/PHP/BackfillEnumTest.php | 226 + .../PHP/BackfillExplicitOctalNotationTest.inc | 31 + .../PHP/BackfillExplicitOctalNotationTest.php | 120 + .../Tokenizers/PHP/BackfillFnTokenTest.inc | 228 + .../Tokenizers/PHP/BackfillFnTokenTest.php | 967 +++ .../Tokenizers/PHP/BackfillMatchTokenTest.inc | 319 + .../Tokenizers/PHP/BackfillMatchTokenTest.php | 555 ++ .../PHP/BackfillNumericSeparatorTest.inc | 94 + .../PHP/BackfillNumericSeparatorTest.php | 402 + .../Tokenizers/PHP/BackfillReadonlyTest.inc | 156 + .../Tokenizers/PHP/BackfillReadonlyTest.php | 271 + .../Core/Tokenizers/PHP/BitwiseOrTest.inc | 183 + .../Core/Tokenizers/PHP/BitwiseOrTest.php | 160 + .../PHP/ContextSensitiveKeywordsTest.inc | 244 + .../PHP/ContextSensitiveKeywordsTest.php | 548 ++ .../PHP/DNFTypesParseError1Test.inc | 17 + .../PHP/DNFTypesParseError1Test.php | 69 + .../PHP/DNFTypesParseError2Test.inc | 48 + .../PHP/DNFTypesParseError2Test.php | 218 + .../Core/Tokenizers/PHP/DNFTypesTest.inc | 224 + .../Core/Tokenizers/PHP/DNFTypesTest.php | 481 ++ .../Tokenizers/PHP/DefaultKeywordTest.inc | 203 + .../Tokenizers/PHP/DefaultKeywordTest.php | 255 + .../Core/Tokenizers/PHP/DoubleArrowTest.inc | 281 + .../Core/Tokenizers/PHP/DoubleArrowTest.php | 237 + .../Tokenizers/PHP/DoubleQuotedStringTest.inc | 52 + .../Tokenizers/PHP/DoubleQuotedStringTest.php | 144 + .../Core/Tokenizers/PHP/EnumCaseTest.inc | 95 + .../Core/Tokenizers/PHP/EnumCaseTest.php | 150 + .../tests/Core/Tokenizers/PHP/FinallyTest.inc | 40 + .../tests/Core/Tokenizers/PHP/FinallyTest.php | 98 + .../Core/Tokenizers/PHP/GotoLabelTest.inc | 56 + .../Core/Tokenizers/PHP/GotoLabelTest.php | 176 + .../Core/Tokenizers/PHP/HeredocNowdocTest.inc | 39 + .../Core/Tokenizers/PHP/HeredocNowdocTest.php | 213 + .../Tokenizers/PHP/HeredocParseErrorTest.inc | 11 + .../Tokenizers/PHP/HeredocParseErrorTest.php | 41 + .../Core/Tokenizers/PHP/HeredocStringTest.inc | 193 + .../Core/Tokenizers/PHP/HeredocStringTest.php | 161 + .../PHP/NamedFunctionCallArgumentsTest.inc | 407 + .../PHP/NamedFunctionCallArgumentsTest.php | 974 +++ .../PHP/NullsafeObjectOperatorTest.inc | 29 + .../PHP/NullsafeObjectOperatorTest.php | 144 + .../PHP/OtherContextSensitiveKeywordsTest.inc | 247 + .../PHP/OtherContextSensitiveKeywordsTest.php | 721 ++ .../Tokenizers/PHP/ResolveSimpleTokenTest.inc | 51 + .../Tokenizers/PHP/ResolveSimpleTokenTest.php | 433 + .../Core/Tokenizers/PHP/ShortArrayTest.inc | 111 + .../Core/Tokenizers/PHP/ShortArrayTest.php | 141 + .../PHP/StableCommentWhitespaceTest.inc | 139 + .../PHP/StableCommentWhitespaceTest.php | 1064 +++ .../PHP/StableCommentWhitespaceWinTest.inc | 63 + .../PHP/StableCommentWhitespaceWinTest.php | 375 + .../Tokenizers/PHP/TypeIntersectionTest.inc | 161 + .../Tokenizers/PHP/TypeIntersectionTest.php | 157 + .../Tokenizers/PHP/TypedConstantsTest.inc | 156 + .../Tokenizers/PHP/TypedConstantsTest.php | 668 ++ .../PHP/UndoNamespacedNameSingleTokenTest.inc | 147 + .../PHP/UndoNamespacedNameSingleTokenTest.php | 1304 +++ .../tests/Core/Tokenizers/PHP/YieldTest.inc | 77 + .../tests/Core/Tokenizers/PHP/YieldTest.php | 448 + ...reateParenthesisNestingMapDNFTypesTest.inc | 185 + ...reateParenthesisNestingMapDNFTypesTest.php | 374 + ...eatePositionMapHeredocNowdocCloserTest.inc | 43 + ...eatePositionMapHeredocNowdocCloserTest.php | 117 + ...eatePositionMapHeredocNowdocOpenerTest.inc | 31 + ...eatePositionMapHeredocNowdocOpenerTest.php | 122 + .../CreatePositionMapTabWidth0Test.php | 107 + .../CreatePositionMapYieldFromTest.inc | 15 + .../CreatePositionMapYieldFromTest.php | 100 + .../CreateTokenMapArrayParenthesesTest.inc | 58 + .../CreateTokenMapArrayParenthesesTest.php | 212 + ...curseScopeMapCaseKeywordConditionsTest.inc | 95 + ...curseScopeMapCaseKeywordConditionsTest.php | 162 + ...seScopeMapDefaultKeywordConditionsTest.inc | 203 + ...seScopeMapDefaultKeywordConditionsTest.php | 347 + ...curseScopeMapWithNamespaceOperatorTest.inc | 19 + ...curseScopeMapWithNamespaceOperatorTest.php | 98 + .../Tokenizer/ReplaceTabsInTokenMiscTest.php | 124 + .../ReplaceTabsInTokenTabWidth1Test.php | 111 + .../ReplaceTabsInTokenTabWidth2Test.php | 111 + .../ReplaceTabsInTokenTabWidth4Test.php | 111 + .../ReplaceTabsInTokenTabWidth5Test.php | 111 + .../Tokenizer/ReplaceTabsInTokenTest.inc | 46 + .../Tokenizer/ReplaceTabsInTokenTestCase.php | 274 + .../Core/Util/Common/EscapeshellcmdTest.php | 91 + .../Core/Util/Common/GetSniffCodeTest.php | 200 + .../Core/Util/Common/IsCamelCapsTest.php | 140 + .../Core/Util/Common/PrepareForOutputTest.php | 113 + .../Core/Util/Common/StripColorsTest.php | 96 + .../Core/Util/Common/SuggestTypeTest.php | 224 + .../tests/Core/Util/Help/HelpTest.php | 725 ++ .../Timing/GetHumanReadableDurationTest.php | 114 + .../tests/Core/Util/Timing/TimingTest.php | 123 + .../Tokens/GetHighestWeightedTokenTest.php | 162 + .../tests/Core/Util/Tokens/TokenNameTest.php | 81 + .../php_codesniffer/tests/FileList.php | 98 + .../tests/Standards/AbstractSniffUnitTest.php | 468 + .../tests/Standards/AllSniffs.php | 114 + .../php_codesniffer/tests/TestSuite.php | 35 + .../php_codesniffer/tests/TestSuite7.php | 35 + .../php_codesniffer/tests/bootstrap.php | 80 + .../symfony/cache/Traits/Relay/CopyTrait.php | 36 + .../cache/Traits/Relay/GeosearchTrait.php | 36 + .../cache/Traits/Relay/GetrangeTrait.php | 36 + .../symfony/cache/Traits/Relay/HsetTrait.php | 36 + .../symfony/cache/Traits/Relay/MoveTrait.php | 46 + .../Traits/Relay/NullableReturnTrait.php | 96 + .../cache/Traits/Relay/PfcountTrait.php | 36 + .../symfony/cache/Traits/RelayProxy.php | 79 +- .../symfony/cache/Traits/RelayProxyTrait.php | 9 - .../Attribute/AutowireLocator.php | 4 +- .../dependency-injection/ContainerBuilder.php | 2 +- .../bin/extract-tentative-return-types.php | 0 .../Resources/bin/patch-type-declarations | 0 .../symfony/http-foundation/Request.php | 8 +- .../http-kernel/HttpCache/HttpCache.php | 7 +- .../vendor/symfony/http-kernel/Kernel.php | 6 +- .../vendor/symfony/intl/Resources/bin/compile | 0 .../symfony/intl/Resources/bin/compress | 0 .../symfony/phpunit-bridge/CHANGELOG.md | 108 + .../phpunit-bridge/ClassExistsMock.php | 101 + .../symfony/phpunit-bridge/ClockMock.php | 168 + .../phpunit-bridge/ConstraintTrait.php | 32 + .../phpunit-bridge/CoverageListener.php | 119 + .../DeprecationErrorHandler.php | 444 + .../DeprecationErrorHandler/Configuration.php | 388 + .../DeprecationErrorHandler/Deprecation.php | 400 + .../DeprecationGroup.php | 57 + .../DeprecationNotice.php | 49 + .../vendor/symfony/phpunit-bridge/DnsMock.php | 226 + .../phpunit-bridge/ExpectDeprecationTrait.php | 30 + .../ExpectUserDeprecationMessageTrait.php | 30 + .../Extension/DisableClockMockSubscriber.php | 39 + .../Extension/DisableDnsMockSubscriber.php | 39 + .../Extension/EnableClockMockSubscriber.php | 39 + .../Extension/RegisterClockMockSubscriber.php | 39 + .../Extension/RegisterDnsMockSubscriber.php | 39 + .../vendor/symfony/phpunit-bridge/LICENSE | 19 + .../phpunit-bridge/Legacy/CommandForV7.php | 57 + .../phpunit-bridge/Legacy/CommandForV9.php | 64 + .../Legacy/ConstraintLogicTrait.php | 62 + .../Legacy/ConstraintTraitForV7.php | 64 + .../Legacy/ConstraintTraitForV8.php | 53 + .../Legacy/ConstraintTraitForV9.php | 50 + .../ExpectDeprecationTraitBeforeV8_4.php | 45 + .../Legacy/ExpectDeprecationTraitForV8_4.php | 65 + .../Legacy/PolyfillAssertTrait.php | 157 + .../Legacy/PolyfillTestCaseTrait.php | 116 + .../Legacy/SymfonyTestsListenerForV7.php | 61 + .../Legacy/SymfonyTestsListenerTrait.php | 364 + .../vendor/symfony/phpunit-bridge/README.md | 14 + .../phpunit-bridge/SymfonyExtension.php | 52 + .../phpunit-bridge/SymfonyTestsListener.php | 20 + .../symfony/phpunit-bridge/TextUI/Command.php | 24 + .../symfony/phpunit-bridge/bin/simple-phpunit | 13 + .../phpunit-bridge/bin/simple-phpunit.php | 476 ++ .../symfony/phpunit-bridge/bootstrap.php | 51 + .../symfony/phpunit-bridge/composer.json | 49 + .../Loader/Configurator/Traits/HostTrait.php | 5 +- .../vendor/symfony/translation/CHANGELOG.md | 205 + .../Catalogue/AbstractOperation.php | 187 + .../translation/Catalogue/MergeOperation.php | 72 + .../Catalogue/OperationInterface.php | 61 + .../translation/Catalogue/TargetOperation.php | 86 + .../CatalogueMetadataAwareInterface.php | 48 + .../Command/TranslationPullCommand.php | 184 + .../Command/TranslationPushCommand.php | 182 + .../translation/Command/TranslationTrait.php | 77 + .../translation/Command/XliffLintCommand.php | 285 + .../TranslationDataCollector.php | 148 + .../translation/DataCollectorTranslator.php | 143 + .../DataCollectorTranslatorPass.php | 36 + .../LoggingTranslatorPass.php | 59 + .../TranslationDumperPass.php | 38 + .../TranslationExtractorPass.php | 43 + .../DependencyInjection/TranslatorPass.php | 94 + .../TranslatorPathsPass.php | 145 + .../translation/Dumper/CsvFileDumper.php | 56 + .../translation/Dumper/DumperInterface.php | 32 + .../symfony/translation/Dumper/FileDumper.php | 108 + .../translation/Dumper/IcuResFileDumper.php | 95 + .../translation/Dumper/IniFileDumper.php | 39 + .../translation/Dumper/JsonFileDumper.php | 34 + .../translation/Dumper/MoFileDumper.php | 76 + .../translation/Dumper/PhpFileDumper.php | 32 + .../translation/Dumper/PoFileDumper.php | 131 + .../translation/Dumper/QtFileDumper.php | 55 + .../translation/Dumper/XliffFileDumper.php | 221 + .../translation/Dumper/YamlFileDumper.php | 56 + .../Exception/ExceptionInterface.php | 21 + .../Exception/IncompleteDsnException.php | 24 + .../Exception/InvalidArgumentException.php | 21 + .../Exception/InvalidResourceException.php | 21 + .../translation/Exception/LogicException.php | 21 + .../MissingRequiredOptionException.php | 25 + .../Exception/NotFoundResourceException.php | 21 + .../Exception/ProviderException.php | 41 + .../Exception/ProviderExceptionInterface.php | 23 + .../Exception/RuntimeException.php | 21 + .../Exception/UnsupportedSchemeException.php | 58 + .../Extractor/AbstractFileExtractor.php | 67 + .../translation/Extractor/ChainExtractor.php | 59 + .../Extractor/ExtractorInterface.php | 39 + .../translation/Extractor/PhpAstExtractor.php | 85 + .../translation/Extractor/PhpExtractor.php | 333 + .../Extractor/PhpStringTokenParser.php | 141 + .../Extractor/Visitor/AbstractVisitor.php | 135 + .../Extractor/Visitor/ConstraintVisitor.php | 112 + .../Extractor/Visitor/TransMethodVisitor.php | 65 + .../Visitor/TranslatableMessageVisitor.php | 65 + .../translation/Formatter/IntlFormatter.php | 57 + .../Formatter/IntlFormatterInterface.php | 27 + .../Formatter/MessageFormatter.php | 46 + .../Formatter/MessageFormatterInterface.php | 28 + .../translation/IdentityTranslator.php | 26 + .../vendor/symfony/translation/LICENSE | 19 + .../translation/Loader/ArrayLoader.php | 57 + .../translation/Loader/CsvFileLoader.php | 64 + .../symfony/translation/Loader/FileLoader.php | 57 + .../translation/Loader/IcuDatFileLoader.php | 58 + .../translation/Loader/IcuResFileLoader.php | 86 + .../translation/Loader/IniFileLoader.php | 25 + .../translation/Loader/JsonFileLoader.php | 51 + .../translation/Loader/LoaderInterface.php | 32 + .../translation/Loader/MoFileLoader.php | 138 + .../translation/Loader/PhpFileLoader.php | 35 + .../translation/Loader/PoFileLoader.php | 147 + .../translation/Loader/QtFileLoader.php | 78 + .../translation/Loader/XliffFileLoader.php | 241 + .../translation/Loader/YamlFileLoader.php | 51 + .../symfony/translation/LocaleSwitcher.php | 83 + .../symfony/translation/LoggingTranslator.php | 115 + .../symfony/translation/MessageCatalogue.php | 338 + .../translation/MessageCatalogueInterface.php | 134 + .../translation/MetadataAwareInterface.php | 48 + .../Provider/AbstractProviderFactory.php | 37 + .../symfony/translation/Provider/Dsn.php | 110 + .../Provider/FilteringProvider.php | 62 + .../translation/Provider/NullProvider.php | 39 + .../Provider/NullProviderFactory.php | 34 + .../Provider/ProviderFactoryInterface.php | 26 + .../Provider/ProviderInterface.php | 30 + .../TranslationProviderCollection.php | 57 + .../TranslationProviderCollectionFactory.php | 57 + .../PseudoLocalizationTranslator.php | 365 + .../vendor/symfony/translation/README.md | 40 + .../translation/Reader/TranslationReader.php | 64 + .../Reader/TranslationReaderInterface.php | 29 + .../Resources/bin/translation-status.php | 274 + .../translation/Resources/data/parents.json | 142 + .../translation/Resources/functions.php | 22 + .../schemas/xliff-core-1.2-transitional.xsd | 2261 +++++ .../Resources/schemas/xliff-core-2.0.xsd | 411 + .../translation/Resources/schemas/xml.xsd | 309 + .../Test/ProviderFactoryTestCase.php | 153 + .../translation/Test/ProviderTestCase.php | 82 + .../translation/TranslatableMessage.php | 60 + .../vendor/symfony/translation/Translator.php | 472 ++ .../symfony/translation/TranslatorBag.php | 102 + .../translation/TranslatorBagInterface.php | 36 + .../translation/Util/ArrayConverter.php | 142 + .../symfony/translation/Util/XliffUtils.php | 191 + .../translation/Writer/TranslationWriter.php | 75 + .../Writer/TranslationWriterInterface.php | 35 + .../vendor/symfony/translation/composer.json | 60 + .../TranslationDefaultDomainNodeVisitor.php | 7 + .../var-dumper/Resources/bin/var-dump-server | 0 .../symfony/yaml/Resources/bin/yaml-lint | 0 .../vendor/theseer/tokenizer/CHANGELOG.md | 87 + .../vendor/theseer/tokenizer/LICENSE | 30 + .../vendor/theseer/tokenizer/README.md | 47 + .../vendor/theseer/tokenizer/composer.json | 27 + .../vendor/theseer/tokenizer/composer.lock | 22 + .../theseer/tokenizer/src/Exception.php | 5 + .../theseer/tokenizer/src/NamespaceUri.php | 25 + .../tokenizer/src/NamespaceUriException.php | 5 + .../vendor/theseer/tokenizer/src/Token.php | 35 + .../theseer/tokenizer/src/TokenCollection.php | 93 + .../src/TokenCollectionException.php | 5 + .../theseer/tokenizer/src/Tokenizer.php | 147 + .../theseer/tokenizer/src/XMLSerializer.php | 79 + .../simplesamlphp/vendor/twig/twig/CHANGELOG | 47 + .../vendor/twig/twig/composer.json | 3 +- .../vendor/twig/twig/phpstan-baseline.neon | 25 + .../vendor/twig/twig/phpstan.neon.dist | 9 + .../twig/twig/src/AbstractTwigCallable.php | 50 +- .../vendor/twig/twig/src/Cache/ChainCache.php | 11 +- .../twig/twig/src/Cache/FilesystemCache.php | 10 +- .../vendor/twig/twig/src/Cache/NullCache.php | 6 +- .../src/Cache/RemovableCacheInterface.php | 20 + .../vendor/twig/twig/src/Compiler.php | 6 +- .../twig/twig/src/DeprecatedCallableInfo.php | 67 + .../vendor/twig/twig/src/Environment.php | 32 +- .../vendor/twig/twig/src/ExpressionParser.php | 492 +- .../twig/twig/src/Extension/CoreExtension.php | 269 +- .../twig/src/Extension/ExtensionInterface.php | 5 +- .../vendor/twig/twig/src/ExtensionSet.php | 6 +- .../src/FileExtensionEscapingStrategy.php | 1 + .../vendor/twig/twig/src/Lexer.php | 17 +- .../twig/twig/src/Loader/FilesystemLoader.php | 11 +- .../vendor/twig/twig/src/Markup.php | 5 + .../vendor/twig/twig/src/Node/EmbedNode.php | 10 +- .../vendor/twig/twig/src/Node/EmptyNode.php | 33 + .../Node/Expression/AbstractExpression.php | 15 + .../src/Node/Expression/ArrayExpression.php | 13 +- .../Node/Expression/AssignNameExpression.php | 16 + .../Node/Expression/Binary/AbstractBinary.php | 11 + .../Node/Expression/Binary/MatchesBinary.php | 18 + .../src/Node/Expression/Binary/XorBinary.php | 23 + .../Expression/BlockReferenceExpression.php | 7 + .../src/Node/Expression/CallExpression.php | 14 +- .../Node/Expression/Filter/DefaultFilter.php | 11 +- .../src/Node/Expression/Filter/RawFilter.php | 11 +- .../src/Node/Expression/FilterExpression.php | 7 + .../Expression/FunctionNode/EnumFunction.php | 45 + .../src/Node/Expression/GetAttrExpression.php | 8 + .../twig/src/Node/Expression/InlinePrint.php | 5 + .../Expression/MacroReferenceExpression.php | 56 + .../Node/Expression/MethodCallExpression.php | 20 +- .../src/Node/Expression/NameExpression.php | 5 + .../Expression/NullCoalesceExpression.php | 16 +- .../Node/Expression/TempNameExpression.php | 30 +- .../src/Node/Expression/Test/DefinedTest.php | 11 + .../src/Node/Expression/TestExpression.php | 7 + .../Node/Expression/Unary/AbstractUnary.php | 18 +- .../src/Node/Expression/Unary/SpreadUnary.php | 22 + .../Node/Expression/Unary/StringCastUnary.php | 22 + .../Variable/AssignContextVariable.php | 18 + .../Variable/AssignTemplateVariable.php | 44 + .../Expression/Variable/ContextVariable.php | 18 + .../Expression/Variable/LocalVariable.php | 18 + .../Expression/Variable/TemplateVariable.php | 42 + .../vendor/twig/twig/src/Node/ForNode.php | 2 +- .../vendor/twig/twig/src/Node/ImportNode.php | 36 +- .../vendor/twig/twig/src/Node/IncludeNode.php | 8 +- .../vendor/twig/twig/src/Node/MacroNode.php | 61 +- .../vendor/twig/twig/src/Node/ModuleNode.php | 18 +- .../vendor/twig/twig/src/Node/Node.php | 8 +- .../vendor/twig/twig/src/Node/Nodes.php | 28 + .../vendor/twig/twig/src/Node/SetNode.php | 31 +- .../src/NodeVisitor/EscaperNodeVisitor.php | 74 +- .../MacroAutoImportNodeVisitor.php | 74 - .../NodeVisitor/SafeAnalysisNodeVisitor.php | 41 +- .../src/NodeVisitor/SandboxNodeVisitor.php | 5 +- .../NodeVisitor/YieldNotReadyNodeVisitor.php | 4 +- .../twig/src/OperatorPrecedenceChange.php | 42 + .../vendor/twig/twig/src/Parser.php | 49 +- .../NodeVisitor/ProfilerNodeVisitor.php | 5 +- .../vendor/twig/twig/src/Profiler/Profile.php | 16 + .../vendor/twig/twig/src/Resources/core.php | 2 +- .../twig/twig/src/Runtime/EscaperRuntime.php | 7 + .../twig/twig/src/Sandbox/SecurityPolicy.php | 4 +- .../vendor/twig/twig/src/Template.php | 57 +- .../twig/src/Test/IntegrationTestCase.php | 6 +- .../twig/src/TokenParser/ApplyTokenParser.php | 13 +- .../twig/src/TokenParser/BlockTokenParser.php | 6 +- .../src/TokenParser/ExtendsTokenParser.php | 3 +- .../twig/src/TokenParser/ForTokenParser.php | 8 +- .../twig/src/TokenParser/FromTokenParser.php | 15 +- .../twig/src/TokenParser/GuardTokenParser.php | 69 + .../twig/src/TokenParser/IfTokenParser.php | 3 +- .../src/TokenParser/ImportTokenParser.php | 11 +- .../twig/src/TokenParser/MacroTokenParser.php | 63 +- .../src/TokenParser/SandboxTokenParser.php | 2 + .../twig/src/TokenParser/TypesTokenParser.php | 2 +- .../twig/src/TokenParser/UseTokenParser.php | 6 +- .../vendor/twig/twig/src/TokenStream.php | 11 +- .../vendor/twig/twig/src/TwigFilter.php | 6 +- .../src/Util/CallableArgumentsExtractor.php | 55 +- 5170 files changed, 501466 insertions(+), 1550 deletions(-) mode change 100755 => 100644 .extlib/simplesamlphp/bin/console mode change 100755 => 100644 .extlib/simplesamlphp/bin/convertTranslations.php mode change 100755 => 100644 .extlib/simplesamlphp/bin/importPdoMetadata.php mode change 100755 => 100644 .extlib/simplesamlphp/bin/initMDSPdo.php mode change 100755 => 100644 .extlib/simplesamlphp/bin/ldapattrschemaparser.pl mode change 100755 => 100644 .extlib/simplesamlphp/bin/memcacheSync.php mode change 100755 => 100644 .extlib/simplesamlphp/bin/pwgen.php mode change 100755 => 100644 .extlib/simplesamlphp/bin/translateAttributes.php mode change 100755 => 100644 .extlib/simplesamlphp/bin/translations create mode 100644 .extlib/simplesamlphp/modules/adfs/.markdownlintignore create mode 100644 .extlib/simplesamlphp/modules/adfs/.markdownlintrc create mode 100644 .extlib/simplesamlphp/modules/adfs/LICENSE create mode 100644 .extlib/simplesamlphp/modules/adfs/README.md create mode 100644 .extlib/simplesamlphp/modules/adfs/composer.json create mode 100644 .extlib/simplesamlphp/modules/adfs/docs/adfs.md create mode 100644 .extlib/simplesamlphp/modules/adfs/metadata/adfs-idp-hosted.php.dist create mode 100644 .extlib/simplesamlphp/modules/adfs/metadata/adfs-sp-remote.php.dist create mode 100644 .extlib/simplesamlphp/modules/adfs/psalm-dev.xml create mode 100644 .extlib/simplesamlphp/modules/adfs/public/assets/js/postResponse.js create mode 100644 .extlib/simplesamlphp/modules/adfs/routing/routes/routes.yml create mode 100644 .extlib/simplesamlphp/modules/adfs/src/Controller/Adfs.php create mode 100644 .extlib/simplesamlphp/modules/adfs/src/IdP/ADFS.php create mode 100644 .extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/Constants.php create mode 100644 .extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/Endpoint.php create mode 100644 .extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/SecurityTokenServiceType.php create mode 100644 .extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/TokenTypesOffered.php create mode 100644 .extlib/simplesamlphp/modules/adfs/templates/postResponse.twig create mode 100644 .extlib/simplesamlphp/modules/adfs/tools/composer-require-checker.json mode change 100755 => 100644 .extlib/simplesamlphp/modules/cron/bin/cron.php mode change 100755 => 100644 .extlib/simplesamlphp/vendor/bin/export-plural-rules mode change 100755 => 100644 .extlib/simplesamlphp/vendor/bin/patch-type-declarations create mode 100644 .extlib/simplesamlphp/vendor/bin/php-parse create mode 100644 .extlib/simplesamlphp/vendor/bin/phpcbf create mode 100644 .extlib/simplesamlphp/vendor/bin/phpcs create mode 100644 .extlib/simplesamlphp/vendor/bin/phpstan create mode 100644 .extlib/simplesamlphp/vendor/bin/phpstan.phar create mode 100644 .extlib/simplesamlphp/vendor/bin/phpunit create mode 100644 .extlib/simplesamlphp/vendor/bin/simple-phpunit mode change 100755 => 100644 .extlib/simplesamlphp/vendor/bin/var-dump-server mode change 100755 => 100644 .extlib/simplesamlphp/vendor/bin/yaml-lint create mode 100644 .extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md create mode 100644 .extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/README.md create mode 100644 .extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json create mode 100644 .extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php mode change 100755 => 100644 .extlib/simplesamlphp/vendor/gettext/languages/bin/export-plural-rules create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/CONTRIBUTING.md create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/README.md create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/composer.json create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpFunctionsScanner.php create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpNodeVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpScanner.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/.github/workflows/runTests.yml create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/README.md create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/composer.json create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/phpunit.xml.dist create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/DotDirectory.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/Quota.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/FileContent.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/LargeFileContent.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/SeekableFileContent.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/StringBasedFileContent.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStream.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamBlock.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainer.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainerIterator.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContent.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamDirectory.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamException.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamFile.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/bootstrap.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/DirectoryIterationTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/FilenameTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/Issue104TestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/PermissionsTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/QuotaTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/UnlinkTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/LargeFileContentTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/StringBasedFileContentTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/proxy/vfsStreamWrapperRecordingProxy.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamAbstractContentTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamBlockTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamContainerIteratorTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue134TestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue18TestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamExLockTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamFileTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamGlobTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamResolveIncludePathTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamUmaskTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperAlreadyRegisteredTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperBaseTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirSeparatorTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTimesTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFlockTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperLargeFileTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperQuotaTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperSetOptionTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperStreamSelectTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperUnregisterTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperWithoutRootTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamZipTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitorTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitorTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitorTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/phpt/bug71287.phpt create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/emptyFolder/.gitignore create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/aFile.txt create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder1/file1.txt create mode 100644 .extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder2/.gitignore create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/README.md create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/composer.json create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Exception/PropertyException.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/ChainableFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/KeepFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/ReplaceFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Matcher.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyMatcher.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DatePeriodFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/ArrayObjectFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedListFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeMatcher/TypeMatcher.php create mode 100644 .extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/README.md create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/bin/php-parse create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/composer.json create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Error.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NameContext.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php create mode 100644 .extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/.github/FUNDING.yml create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/.github/workflows/ci.yml create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/.php-cs-fixer.dist.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/README.md create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/composer.lock create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/manifest.xsd create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestDocumentMapper.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestLoader.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestSerializer.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/NoEmailAddressException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Application.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/ApplicationName.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Author.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponent.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/CopyrightInformation.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Email.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Extension.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Library.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/License.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Manifest.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Requirement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Type.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Url.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/BundlesElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ContainsElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/CopyrightElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ElementCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElementCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtensionElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/LicenseElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestDocument.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/PhpElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/RequiresElement.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/header.txt create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/README.md create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/BuildMetaData.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/PreReleaseSuffix.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/Version.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintParser.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintValue.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/VersionNumber.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/constraints/VersionConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/InvalidVersionException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/NoBuildMetaDataException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php create mode 100644 .extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/extension-installer/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpstan/extension-installer/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpstan/extension-installer/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpstan/extension-installer/src/GeneratedConfig.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/extension-installer/src/Plugin.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Attribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Node.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/.editorconfig create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/extension.neon create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/phpstan-baseline.neon create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/PhpDoc/TypeNodeResolverExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodReflection.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodsClassReflectionExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/Allows.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/Expects.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/MockDynamicNamedMockReturnTypeExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/MockDynamicReturnTypeExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/StubDynamicReturnTypeExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/stubs/MockInterface.stub create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/bootstrap.php create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/conf/bleedingEdge.neon create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan.phar create mode 100644 .extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan.phar.asc create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/ChangeLog-10.1.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/CodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Driver.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Selector.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Filter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Builder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Directory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/File.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Iterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Clover.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Colors.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/nv.d3.min.js create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/PHP.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Text.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Thresholds.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Known.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Large.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Medium.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Small.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/TestSize.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Unknown.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Failure.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Known.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Success.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/TestStatus.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Unknown.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Percentage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Version.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/ExcludeIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Factory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Iterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/baseline.xml create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/config.xml create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/src/Invoker.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/src/Template.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/src/Duration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/src/Timer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/ChangeLog-10.5.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/DEPRECATIONS.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/README.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/composer.json create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/composer.lock create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.1.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.2.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.3.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.4.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/8.5.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.1.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.2.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.3.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.4.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.5.xsd create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/Emitter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Finished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Started.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Event.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Started.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Started.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidEventException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MapError.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Tracer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/TypeMap.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ClassMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailure.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHP.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Info.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/System.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Phpt.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Test.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDox.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Throwable.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/After.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/AfterClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Before.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Depends.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Group.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Large.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Medium.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PostCondition.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreCondition.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Small.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Test.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestDox.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWith.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Ticket.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/deprecation.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_method.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_static_method.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/intersection.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/proxied_method.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/test_double_class.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/trait_class.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_class.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_method.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Reorderable.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Test.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestCase.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestRunner.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Known.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Large.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Medium.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Small.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/TestSize.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Unknown.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Error.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Failure.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Known.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Notice.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Risky.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Skipped.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Success.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Unknown.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Warning.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuite.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/EventLogger.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/After.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/AfterClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/DataProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Dependencies.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Groups.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/HookMethods.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Requirements.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupGlobals.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupStaticProperties.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Before.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BeforeClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Covers.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversDefaultClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversFunction.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversNothing.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DataProvider.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Group.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Metadata.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/CachingParser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Parser.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/ParserChain.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Registry.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PostCondition.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreCondition.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreserveGlobalState.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresFunction.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresMethod.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhp.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpunit.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresSetting.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Test.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestDox.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestWith.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Uses.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesDefaultClass.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesFunction.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/Requirement.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Baseline.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Generator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Issue.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Reader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Writer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/CodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ErrorHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ErrorException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Extension.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Collector.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Issue.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/PassedTests.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/TestResult.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Version.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Application.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Command.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Result.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Builder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Configuration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Merger.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Registry.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/File.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Help.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Facade.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestRunner.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Cloner.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Color.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/PhpProcessException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/XmlException.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ExcludeList.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exporter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filesystem.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filter.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/GlobalState.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/Downloader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/PhpDownloader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Json.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Reflection.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Test.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ThrowableToStringMapper.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Loader.php create mode 100644 .extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Xml.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/README.md create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/autoload.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/composer.json create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Autoloader.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Client.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/ClientConfiguration.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/ClientContextInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/ClientException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/ClientInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/ClusterStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/DistributorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/EmptyRingException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/HashRing.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/KetamaRing.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/CRC16.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/HashGeneratorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/PhpiredisCRC16.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/PredisStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/RedisStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/SlotMap.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Cluster/StrategyInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/CursorBasedIterator.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/HashKey.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/Keyspace.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/ListKey.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SetKey.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SortedSetKey.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/ArrayableArgument.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/AbstractBy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByBox.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByRadius.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromLonLat.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromMember.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AggregateArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AlterArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CommonArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CreateArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CursorArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/DropArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/ExplainArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/ProfileArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/AbstractField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/FieldInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/GeoField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/GeoShapeField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/NumericField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TagField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TextField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/VectorField.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SearchArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SpellcheckArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugAddArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugGetArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SynUpdateArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Server/LimitInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Server/LimitOffsetCount.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Server/To.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AddArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AlterArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/CommonArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/CreateArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/DecrByArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/GetArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/IncrByArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/InfoArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/MGetArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/MRangeArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/RangeArguments.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Command.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/CommandInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Factory.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/FactoryInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/PrefixableCommandInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/KeyPrefixProcessor.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorChain.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/RawCommand.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/RawFactory.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ACL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/APPEND.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/AUTH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/AbstractCommand/BZPOPBase.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BGREWRITEAOF.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BGSAVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BITCOUNT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BITFIELD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BITOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BITPOS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BLMOVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BLMPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BLPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BRPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BRPOPLPUSH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BZMPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BZPOPMAX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BZPOPMIN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFEXISTS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFINSERT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFLOADCHUNK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFMADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFMEXISTS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFRESERVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFSCANDUMP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CLIENT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CLUSTER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/COMMAND.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CONFIG.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/COPY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ACL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/AbstractContainer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/CLUSTER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ContainerFactory.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ContainerInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/FunctionContainer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/Json/JSONDEBUG.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/Search/FTCONFIG.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/Search/FTCURSOR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINITBYDIM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINITBYPROB.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSMERGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSQUERY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFADDNX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFCOUNT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFEXISTS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERTNX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFLOADCHUNK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFMEXISTS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFRESERVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFSCANDUMP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/DBSIZE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/DECR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/DECRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/DEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/DISCARD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/DUMP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ECHO_.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVALSHA.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVALSHA_RO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVAL_.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVAL_RO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EXEC.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EXISTS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EXPIRE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EXPIREAT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EXPIRETIME.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FAILOVER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FCALL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FCALL_RO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FLUSHALL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FLUSHDB.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FUNCTIONS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEODIST.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOHASH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOPOS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEORADIUS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEORADIUSBYMEMBER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOSEARCH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOSEARCHSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETBIT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXISTS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXPIRE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXPIREAT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXPIRETIME.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HGETALL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HINCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HINCRBYFLOAT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HKEYS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HMGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HMSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPERSIST.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPEXPIRE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPEXPIREAT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPEXPIRETIME.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPTTL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HRANDFIELD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSCAN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSETNX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSTRLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HTTL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HVALS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/INCR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/INCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/INCRBYFLOAT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/INFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRAPPEND.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRINDEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRINSERT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRTRIM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONCLEAR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONDEBUG.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONFORGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONMERGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONMGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONMSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONNUMINCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONOBJKEYS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONOBJLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONRESP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONSTRAPPEND.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONSTRLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONTOGGLE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONTYPE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/KEYS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LASTSAVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LCS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LINDEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LINSERT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LMOVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LMPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LPUSH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LPUSHX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LREM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LTRIM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MIGRATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MONITOR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MOVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MSET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MSETNX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MULTI.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/OBJECT_.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PERSIST.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PEXPIRE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PEXPIREAT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PEXPIRETIME.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PFADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PFCOUNT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PFMERGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PING.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PSETEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PSUBSCRIBE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PTTL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PUBLISH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PUBSUB.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PUNSUBSCRIBE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/QUIT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RANDOMKEY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RENAME.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RENAMENX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RESTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RPOPLPUSH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RPUSH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/RPUSHX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SAVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SCAN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SCARD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SCRIPT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SDIFF.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SDIFFSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SELECT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SENTINEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETBIT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETNX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SHUTDOWN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SINTER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SINTERCARD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SINTERSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SISMEMBER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SLAVEOF.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SLOWLOG.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SMEMBERS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SMISMEMBER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SMOVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SORT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SORT_RO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SRANDMEMBER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SREM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SSCAN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/STRLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SUBSCRIBE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SUBSTR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SUNION.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SUNIONSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTAGGREGATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALIASADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALIASDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALIASUPDATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALTER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCONFIG.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCREATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCURSOR.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDICTADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDICTDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDICTDUMP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDROPINDEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTEXPLAIN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTPROFILE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSEARCH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSPELLCHECK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSYNDUMP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSYNUPDATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTTAGVALS.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTBYRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTBYREVRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTCDF.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTCREATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTMAX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTMERGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTMIN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTQUANTILE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTRESET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTREVRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TDigest/TDIGESTTRIMMED_MEAN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TIME.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TOUCH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TTL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TYPE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSALTER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATERULE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSDECRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSDELETERULE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMGET.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMREVRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSQUERYINDEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSREVRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKINCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKINFO.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKLIST.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKQUERY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKRESERVE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/UNSUBSCRIBE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/UNWATCH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/WAITAOF.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/WATCH.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XDEL.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XLEN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XREAD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XREVRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XTRIM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZADD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZCARD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZCOUNT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZDIFF.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZDIFFSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINCRBY.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINTER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINTERCARD.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINTERSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZLEXCOUNT.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZMPOP.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZMSCORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZPOPMAX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZPOPMIN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANDMEMBER.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGEBYLEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGEBYSCORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGESTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREM.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREMRANGEBYLEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREMRANGEBYRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREMRANGEBYSCORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREVRANGE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREVRANGEBYLEX.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREVRANGEBYSCORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZREVRANK.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZSCAN.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZSCORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZUNION.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZUNIONSTORE.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/RedisFactory.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/ScriptCommand.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/DeleteStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/DumpStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/FlushStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/KillStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/ListStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/LoadStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/RestoreStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/StatsStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/StrategyResolverInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/SubcommandStrategyInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/SubcommandStrategyResolver.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Aggregate.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BitByte.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/BucketSize.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Capacity.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Error.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Expansion.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Items.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/MaxIterations.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/NoCreate.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByArgument.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByLexByScore.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/GeoBy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Count.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/DB.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Expire/ExpireOptions.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/From/GeoFrom.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Get/Get.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Indent.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Newline.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/NxXxArgument.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Space.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Keys.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/LeftRight.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/Limit.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/LimitObject.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/MinMaxModifier.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Replace.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Rev.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Sorting.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Storedist.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Timeout.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/To/ServerTo.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Weights.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithCoord.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithDist.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithHash.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithScores.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithValues.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/CommunicationException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Aggregate.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/CRC16.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Cluster.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Commands.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Connections.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Exceptions.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Prefix.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Replication.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Options.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionsInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/AbstractConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/AggregateConnectionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Cluster/ClusterInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Cluster/PredisCluster.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Cluster/RedisCluster.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/CompositeConnectionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/CompositeStreamConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/ConnectionException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/ConnectionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Factory.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/FactoryInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/NodeConnectionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Parameters.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/ParametersInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/PhpiredisSocketConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/PhpiredisStreamConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayMethods.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/MasterSlaveReplication.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/ReplicationInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/SentinelReplication.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/StreamConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Connection/WebdisConnection.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Monitor/Consumer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/NotSupportedException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/Atomic.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/ConnectionErrorProof.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/FireAndForget.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/Pipeline.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayAtomic.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayPipeline.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/PredisException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/ProtocolException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/ProtocolProcessorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/RequestSerializerInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/ResponseReaderInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/CompositeProtocolProcessor.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/BulkResponse.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ErrorResponse.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/IntegerResponse.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/MultiBulkResponse.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ResponseHandlerInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/StatusResponse.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/StreamableMultiBulkResponse.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ProtocolProcessor.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/RequestSerializer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ResponseReader.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/PubSub/AbstractConsumer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/PubSub/Consumer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/PubSub/DispatcherLoop.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/PubSub/RelayConsumer.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Replication/MissingMasterException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Replication/ReplicationStrategy.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Replication/RoleException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/Error.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/ErrorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulk.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkIterator.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkTuple.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/ResponseInterface.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/ServerException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Response/Status.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Session/Handler.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Transaction/AbortedMultiExecException.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExec.php create mode 100644 .extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExecState.php create mode 100644 .extlib/simplesamlphp/vendor/robrichards/xmlseclibs/.github/workflows/ci.yml create mode 100644 .extlib/simplesamlphp/vendor/robrichards/xmlseclibs/phpunit.xml create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/src/Parser.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/baseline.xml create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/config.xml create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassMethodUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollection.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/FileUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/FunctionUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/Mapper.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitMethodUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitUnit.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/ArrayComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/Comparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/ComparisonFailure.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/DOMNodeComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/DateTimeComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/ExceptionComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/Factory.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/MockObjectComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/NumericComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/ObjectComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/ResourceComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/ScalarComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/SplObjectStorageComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/TypeComparator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Calculator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/Complexity.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Chunk.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Diff.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Differ.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/ConfigurationException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Line.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/Parser.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/src/Console.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/environment/src/Runtime.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/exporter/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/exporter/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/exporter/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/exporter/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/exporter/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/exporter/src/Exporter.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/src/CodeExporter.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/src/ExcludeList.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/src/Restorer.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/src/Snapshot.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Counter.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LinesOfCode.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/phpunit.xml create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-enumerator/src/Enumerator.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-reflector/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-reflector/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-reflector/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-reflector/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-reflector/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/object-reflector/src/ObjectReflector.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/recursion-context/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/recursion-context/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/recursion-context/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/recursion-context/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/recursion-context/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/recursion-context/src/Context.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/infection.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/Parameter.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/ReflectionMapper.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/TypeName.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/exception/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/CallableType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/FalseType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/GenericObjectType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/IntersectionType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/IterableType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/MixedType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/NeverType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/NullType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/ObjectType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/SimpleType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/StaticType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/TrueType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/Type.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/UnionType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/UnknownType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/type/src/type/VoidType.php create mode 100644 .extlib/simplesamlphp/vendor/sebastian/version/ChangeLog.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/version/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/sebastian/version/README.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/version/SECURITY.md create mode 100644 .extlib/simplesamlphp/vendor/sebastian/version/composer.json create mode 100644 .extlib/simplesamlphp/vendor/sebastian/version/src/Version.php delete mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.gitignore delete mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.php_cs.dist delete mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/codecov.yml delete mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpcs.xml delete mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpunit.xml delete mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/psalm.xml rename .extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/{element.registry.e2caf4bd4863521540091558bb31dc3a1899181e.php => element.registry.9eadaddda070e6fc2370298410b63dbaf3d3a3eb.php} (95%) create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/.github/workflows/php.yml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/README.md create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/composer.json create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-assertion-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-auth-telephony-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ip-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ippword-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-kerberos-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-reg-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-unreg-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-reg-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-unreg-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-nomad-telephony-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-personal-telephony-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pgp-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ppt-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pword-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-session-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcard-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcardpki-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-softwarepki-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-spki-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-srp-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-sslcert-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-telephony-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-timesync-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-types-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-x509-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-xmldsig-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-dce-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-ecp-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-metadata-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-protocol-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-x500-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-xacml-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xenc-schema.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xml.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xmldsig-core-schema.xsd create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResolve.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResponse.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Decrypter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Exception/InvalidAssertionException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Exception/InvalidSubjectConfirmationException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Exception/NotDecryptedException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Processor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/ProcessorBuilder.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/DecodeBase64Transformer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/NameIdDecryptionTransformer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/Transformer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/TransformerChain.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/AssertionConstraintValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/AssertionValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotBefore.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/Result.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/SubjectConfirmationConstraintValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/SubjectConfirmationValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AttributeQuery.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AuthnRequest.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Binding.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Exception/InvalidCertificateStructureException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Exception/InvalidKeyUsageException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Exception/NoKeysFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Key.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/KeyCollection.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/KeyLoader.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKey.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKeyLoader.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/X509.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/AbstractContainer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/ContainerSingleton.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/MockContainer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Container.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Logger.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ArrayAdapter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/CertificateProvider.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/DecryptionProvider.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/Destination.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/EntityIdProvider.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/IdentityProvider.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/IdentityProviderAware.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/PrivateKey.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/Queryable.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ServiceProvider.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ServiceProviderAware.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/SimpleSAMLConverter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Constants.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/DOMDocumentFactory.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/EncryptedAssertion.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/MetadataExpiredException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/AuthnFailedException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/InvalidAttrNameOrValueException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/InvalidNameIDPolicyException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/NoAuthnContextException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/NoAvailableIDPException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/NoPassiveException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/NoSupportedIDPException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/PartialLogoutException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/ProxyCountExceededException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/RequestDeniedException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/RequestUnsupportedException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/RequestVersionDeprecatedException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/RequestVersionTooHighException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/RequestVersionTooLowException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/ResourceNotRecognizedException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/TooManyResponsesException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/UnknownAttrProfileException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/UnknownPrincipalException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/UnsupportedBindingException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/ProtocolViolationException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Throwable.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/UnparseableXmlException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPArtifact.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPPost.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPRedirect.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutRequest.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutResponse.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Message.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Request.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/InvalidResponseException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/InvalidSignatureException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/NoAssertionsFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/PreconditionNotMetException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/UnencryptedAssertionFoundException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/UnsignedResponseException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Processor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator/DestinationMatches.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator/IsSuccessful.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/PreconditionValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Result.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Validator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAP.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAPClient.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/AbstractChainedValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ChainedValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/MissingConfigurationException.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/PublicKeyValidator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/Validator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorChain.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SignedElement.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SignedElementHelper.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/StatusResponse.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SubjectQuery.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/ArrayCollection.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/Certificate.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/Collection.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/File.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/Temporal.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utils.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/Chunk.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/Common.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/DigestMethod.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/SigningMethod.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyInfo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyName.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Certificate.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Data.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ecp/Response.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AdditionalMetadataLocation.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AffiliationDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeAuthorityDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeConsumingService.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AuthnAuthorityDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/ContactPerson.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EndpointType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntitiesDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntityDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Extensions.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IDPSSODescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IndexedEndpointType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/KeyDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Organization.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/PDPDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RequestedAttribute.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RoleDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SPSSODescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SSODescriptorType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/UnknownRoleDescriptor.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdattr/EntityAttributes.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/Common.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/PublicationInfo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/RegistrationInfo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Common.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/DiscoHints.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Keywords.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Logo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/UIInfo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Attribute.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/AttributeValue.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/BaseIDType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/IDNameQualifiersTrait.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Issuer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameID.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameIDType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmation.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmationData.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/samlp/Extensions.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/shibmd/Scope.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/_autoload.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/autoload.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/corrupted-metadata-selfsigned.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/expired-metadata.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/valid-metadata-selfsigned.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/README.md create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/composer.json create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ArrayLogger.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/BuiltInServer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ClearStateTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/InMemoryStore.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ReduceSpillOverTest.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SigningTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SimpleTestLogger.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/StateClearer.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_expired.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_selfsigned.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_signed.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_expired.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpcs-simplesamlphp.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan-dev.neon create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan.neon create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/src/TemplateTest.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/krb5.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/memcache.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/memcached.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/predis.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/radius.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/soap.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/IntegerElementTrait.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/AbstractKeyInfoType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractAgreementMethodType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractDHKeyValueType.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AgreementMethod.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/DHKeyValue.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Generator.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KANonce.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/OriginatorKeyInfo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/P.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/PgenCounter.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Q.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/RecipientKeyInfo.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Seed.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/XencPublic.php create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_AgreementMethod.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_DHKeyValue.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Generator.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_KA-Nonce.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_OriginatorKeyInfo.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_P.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Public.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Q.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_RecipientKeyInfo.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_pgenCounter.xml create mode 100644 .extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_seed.xml create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/.editorconfig create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/.typos.toml create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/CODE_OF_CONDUCT.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/LICENSE.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/README.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Annotation.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationTypeHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayKeyValue.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Attribute.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AttributeHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CatchHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ClassHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Comment.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CommentHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConditionHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConstantHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/DocCommentHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/EmptyFileException.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FixerHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FunctionHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IdentificatorHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IndentationHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/NamespaceHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParameterHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParsedDocComment.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PhpDocParserHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PropertyHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedName.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedNameHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ScopeHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffLocalCache.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffSettingsHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/StringHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SuppressHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TernaryOperatorHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenPointerOutOfBoundsException.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHint.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHintHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatement.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatementHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/VariableHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/YodaHelper.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/AlphabeticallySortedByKeysSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/ArrayAccessSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowImplicitArrayCreationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowPartiallyKeyedSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/MultiLineArrayEndBracketPlacementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/SingleLineArrayWhitespaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributeAndTargetSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributesOrderSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowAttributesJoiningSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowMultipleAttributesPerLineSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/RequireAttributeAfterDocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractMethodSignature.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/BackedEnumTypeSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassConstantVisibilitySniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassLengthSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassMemberSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassStructureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ConstantSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowConstructorPropertyPromotionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowLateStaticBindingForConstantsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiConstantDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiPropertyDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowStringExpressionPropertyFetchSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EmptyLinesAroundClassBracesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EnumCaseSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ForbiddenPublicPropertySniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MethodSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MissingClassGroupsException.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ModernClassNameReferenceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ParentCallSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertyDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertySpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireAbstractOrFinalSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireConstructorPropertyPromotionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireMultiLineMethodSignatureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSelfReferenceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSingleLineMethodSignatureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousAbstractClassNamingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousErrorNamingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousExceptionNamingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousInterfaceNamingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousTraitNamingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UnsupportedClassGroupException.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UselessLateStaticBindingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AbstractRequireOneLineDocComment.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AnnotationNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DeprecatedAnnotationDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowCommentAfterCodeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowOneLinePropertyDocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/EmptyCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenCommentsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/InlineDocCommentDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLineDocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLinePropertyDocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessFunctionDocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessInheritDocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Complexity/CognitiveSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractControlStructureSpacing.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractLineCondition.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AssignmentInConditionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/BlockControlStructureSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowContinueWithoutIntegerOperandInSwitchSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowEmptySniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowNullSafeObjectOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowShortTernaryOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowTrailingMultiLineTernaryOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowYodaComparisonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/EarlyExitSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/JumpStatementsSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/LanguageConstructWithParenthesesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithParenthesesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithoutParenthesesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineConditionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineTernaryOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceEqualOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullSafeObjectOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireShortTernaryOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireSingleLineConditionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireTernaryOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireYodaComparisonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UnsupportedKeywordException.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessIfConditionWithReturnSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessTernaryOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DeadCatchSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DisallowNonCapturingCatchSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/ReferenceThrowableOnlySniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/RequireNonCapturingCatchSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FileLengthSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FilepathNamespaceExtractor.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/LineLengthSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/TypeNameMatchesFileNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/AbstractLineCall.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/ArrowFunctionDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowArrowFunctionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowEmptyFunctionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowNamedArgumentsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInClosureUseSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/FunctionLengthSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireArrowFunctionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireMultiLineCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireSingleLineCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInClosureUseSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StaticClosureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StrictCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedInheritedVariablePassedToClosureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedParameterSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UselessParameterDefaultValueSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AbstractFullyQualifiedGlobalReference.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/DisallowGroupUseSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedClassNameInAnnotationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedExceptionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalConstantsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalFunctionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/MultipleUsesPerLineSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/RequireOneNamespaceInFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseFromSameNamespaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseOnlyWhitelistedNamespacesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UselessAliasSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/DisallowNumericLiteralSeparatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/RequireNumericLiteralSeparatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowEqualOperatorsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowIncrementAndDecrementOperatorsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/NegationOperatorSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireCombinedAssignmentOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireOnlyStandaloneIncrementAndDecrementOperatorsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/SpreadOperatorSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowDirectMagicInvokeCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowReferenceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ForbiddenClassesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/OptimizedFunctionsWithoutUnpackingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ReferenceSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireExplicitAssertionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireNowdocSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ShortListSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/TypeCastSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessParenthesesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessSemicolonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Strings/DisallowVariableParsingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TestCase.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DeclareStrictTypesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowArrayTypeHintSyntaxSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowMixedTypeHintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/LongTypeHintsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullTypeHintOnLastPositionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullableTypeForNullDefaultValueSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/PropertyTypeHintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UnionTypeHintFormatSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UselessConstantTypeHintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowSuperGlobalVariableSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowVariableVariableSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DuplicateAssignmentToVariableSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UnusedVariableSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UselessVariableSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Whitespaces/DuplicateSpacesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/autoload-bootstrap.php create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/composer.json create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/arrays.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/attributes.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/classes.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/commenting.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/complexity.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/control-structures.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/exceptions.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/files.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/functions.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/namespaces.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/numbers.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/operators.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/php.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/strings.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/type-hints.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/variables.md create mode 100644 .extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/whitespaces.md create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/README.md create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/autoload.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs.bat create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/composer.json create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/licence.txt create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/phpcs.xsd create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Config.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/File.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Fixer.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Text.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reporter.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Code.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Full.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Info.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Json.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Performance.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Report.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Source.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Ruleset.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Runner.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/DeprecatedSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/ArrayIndentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyPHPStatementStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/DocCommentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceBeforeCastStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/RequireStrictTypesStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SyntaxStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryHeredocStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/HereNowdocIdentifierSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/IncrementDecrementSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowRequestSuperglobalSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowShortOpenTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DiscourageGotoSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ForbiddenFunctionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/LowerCaseConstantSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/LowerCaseTypeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/NoSilencedErrorsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/RequireStrictTypesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/SAPIUsageSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/SyntaxSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/UpperCaseConstantSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Strings/UnnecessaryHeredocSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Strings/UnnecessaryStringConcatSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/VersionControl/GitMergeConflictSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/VersionControl/SubversionPropertiesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/ArbitraryParenthesesSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/HereNowdocIdentifierSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/IncrementDecrementSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/WhiteSpace/SpreadOperatorSpacingAfterSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowLongArraySyntaxUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowShortArraySyntaxUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowShortArraySyntaxUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Arrays/DisallowShortArraySyntaxUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.97.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.98.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.99.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/OpeningBraceSameLineUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/OpeningBraceSameLineUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Classes/OpeningBraceSameLineUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/AssignmentInConditionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyPHPStatementUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyPHPStatementUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyPHPStatementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyStatementUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/EmptyStatementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/DocCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/FixmeUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/FixmeUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/FixmeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/TodoUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/TodoUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Commenting/TodoUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/DisallowYodaConditionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/DisallowYodaConditionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.3.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/CSSLintUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/CSSLintUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ClosureLinterUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ClosureLinterUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ESLintUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/ESLintUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/JSHintUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Debug/JSHintUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.6.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.7.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.6.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.8.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.9.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/ExecutableFileUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/InlineHTMLUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineEndingsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LineLengthUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneClassPerFileUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneClassPerFileUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneInterfacePerFileUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneInterfacePerFileUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneObjectStructurePerFileUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneObjectStructurePerFileUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneTraitPerFileUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Files/OneTraitPerFileUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceAfterNotUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceBeforeCastUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceBeforeCastUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Formatting/SpaceBeforeCastUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/CyclomaticComplexityUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/CyclomaticComplexityUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/NestingLevelUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Metrics/NestingLevelUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/AbstractClassNamePrefixUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/AbstractClassNamePrefixUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/AbstractClassNamePrefixUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/ConstructorNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/ConstructorNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/InterfaceNameSuffixUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/InterfaceNameSuffixUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/InterfaceNameSuffixUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/TraitNameSuffixUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/TraitNameSuffixUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/TraitNameSuffixUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/UpperCaseConstantNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/NamingConventions/UpperCaseConstantNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/BacktickOperatorUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/BacktickOperatorUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DeprecatedFunctionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DeprecatedFunctionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.11.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.12.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.12.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.13.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.14.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.14.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.15.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.15.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/HereNowdocIdentifierSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/HereNowdocIdentifierSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/HereNowdocIdentifierSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.12.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.13.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.17.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClosingBraceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/OpeningBraceSpaceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/BooleanOperatorPlacementStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/ControlStructureSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/ImportStatementStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/OpenTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/ReturnTypeDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Properties/ConstantVisibilityStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.10.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.11.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.12.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.12.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.13.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.14.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.17.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.18.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.7.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/ClosingTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionCallSignatureStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionClosingBraceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.10.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.11.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.14.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.6.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.7.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.9.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.10.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.11.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.12.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.12.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.13.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.13.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.14.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.14.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.15.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.16.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.16.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.17.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.18.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/PHP/HeredocStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionClosingBraceSpaceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/MemberVarSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeClosingBraceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SuperfluousWhitespaceStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.2.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.10.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.11.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.12.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.12.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.13.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.13.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.14.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.15.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.16.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.17.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.22.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.22.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.23.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.24.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.24.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.8.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.9.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.6.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.2.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Cache.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Common.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Help.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Standards.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Timing.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/AllTests.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/ConfigDouble.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/B.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/C.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/Sub/C.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Config/ReportWidthTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Config/SniffsExcludeArgsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/ErrorSuppressionTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetClassPropertiesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetClassPropertiesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.js create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError1Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError1Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError2Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError2Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/AbstractFilterTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitModifiedTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitStagedTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtStart.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtStart.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-LineAdded.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-LineAdded.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-LineRemoved.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-LineRemoved.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-NoDiff.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-NoDiff.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-NoTrailingWhitespace.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-NoTrailingWhitespace.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-TabsToSpaces.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-TabsToSpaces.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-VarNameChanged.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-VarNameChanged.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-WhiteSpaceAtEnd.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-WhiteSpaceAtEnd.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-WhiteSpaceAtStart.diff create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-WhiteSpaceAtStart.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-WindowsLineEndings.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/GenerateDiffTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputEmpty.txt create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/HTMLDouble.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/MarkdownDouble.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/MockGenerator.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneCodeComparisonNoStandardStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/DocumentationMissingSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/NoContentSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/NoDocumentationElementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/OneCodeComparisonNoStandardSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/OneStandardBlockCodeComparisonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/OneStandardBlockNoCodeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/OneStandardBlockTwoCodeComparisonsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/TwoStandardBlocksNoCodeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/TwoStandardBlocksOneCodeComparisonSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/Structure/TwoStandardBlocksThreeCodeComparisonsSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/GeneratorTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/HTMLTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/MarkdownTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoDocsTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoValidDocsTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/OneDocTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/StructureDocsTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/TextTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainCustomRulesetTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainSingleSniffTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithLongReplacementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithReplacementContainingLinuxNewlinesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithReplacementContainingNewlinesSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithReplacementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithoutReplacementSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/DeprecatedInvalid/EmptyDeprecationVersionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/DeprecatedInvalid/EmptyRemovalVersionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/DeprecatedInvalid/InvalidDeprecationMessageSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/DeprecatedInvalid/InvalidDeprecationVersionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/DeprecatedInvalid/InvalidRemovalVersionSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/AllowedAsDeclaredSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/AllowedViaMagicMethodSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/AllowedViaStdClassSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/NotAllowedViaAttributeSniff.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/ruleset.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedAsDeclaredTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaMagicMethodTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaStdClassTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAppliesPropertyToMultipleSniffsInCategoryTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategoryTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyNotAllowedViaAttributeTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyThrowsErrorOnInvalidPropertyTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetSniffPropertyTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyDeprecationVersionTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyRemovalVersionTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationMessageTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationVersionTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidRemovalVersionTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsOrderTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsReportWidthTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/AbstractTokenizerTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/CommentTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding1Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding1Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding2Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding2Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding3Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding3Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding4Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding4Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/MultiLineDocBlockTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/MultiLineDocBlockTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/PhpcsAnnotationsInDocBlockTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/PhpcsAnnotationsInDocBlockTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/SingleLineDocBlockTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/SingleLineDocBlockTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AnonClassParenthesisOwnerTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AnonClassParenthesisOwnerTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillExplicitOctalNotationTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillExplicitOctalNotationTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillNumericSeparatorTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillNumericSeparatorTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError1Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError1Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError2Test.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError2Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/EnumCaseTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/EnumCaseTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocNowdocTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocNowdocTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceWinTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceWinTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/UndoNamespacedNameSingleTokenTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/UndoNamespacedNameSingleTokenTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocCloserTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocCloserTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocOpenerTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocOpenerTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapTabWidth0Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapYieldFromTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapYieldFromTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenMiscTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth1Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth2Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth4Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth5Test.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTest.inc create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/EscapeshellcmdTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/GetSniffCodeTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/IsCamelCapsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/PrepareForOutputTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/StripColorsTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/SuggestTypeTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Help/HelpTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/GetHumanReadableDurationTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/TimingTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/GetHighestWeightedTokenTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/TokenNameTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/FileList.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php create mode 100644 .extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/bootstrap.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/CopyTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/HsetTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/MoveTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/PfcountTrait.php mode change 100755 => 100644 .extlib/simplesamlphp/vendor/symfony/error-handler/Resources/bin/extract-tentative-return-types.php mode change 100755 => 100644 .extlib/simplesamlphp/vendor/symfony/error-handler/Resources/bin/patch-type-declarations mode change 100755 => 100644 .extlib/simplesamlphp/vendor/symfony/intl/Resources/bin/compile mode change 100755 => 100644 .extlib/simplesamlphp/vendor/symfony/intl/Resources/bin/compress create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ClassExistsMock.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ClockMock.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ConstraintTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CoverageListener.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Configuration.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Deprecation.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationGroup.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationNotice.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DnsMock.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ExpectDeprecationTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ExpectUserDeprecationMessageTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableClockMockSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableDnsMockSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/EnableClockMockSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterClockMockSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterDnsMockSubscriber.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV7.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV9.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintLogicTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV7.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV8.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV9.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitBeforeV8_4.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitForV8_4.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillAssertTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillTestCaseTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerForV7.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/README.md create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyExtension.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/TextUI/Command.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bootstrap.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/phpunit-bridge/composer.json create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Catalogue/AbstractOperation.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Catalogue/MergeOperation.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Catalogue/OperationInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Catalogue/TargetOperation.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/CatalogueMetadataAwareInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPullCommand.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPushCommand.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationTrait.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Command/XliffLintCommand.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DataCollector/TranslationDataCollector.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DataCollectorTranslator.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPass.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/CsvFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/DumperInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/FileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/IcuResFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/IniFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/JsonFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/MoFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/PhpFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/PoFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/QtFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/XliffFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Dumper/YamlFileDumper.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/ExceptionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/IncompleteDsnException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidArgumentException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidResourceException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/LogicException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/MissingRequiredOptionException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/NotFoundResourceException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderExceptionInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/RuntimeException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Exception/UnsupportedSchemeException.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/AbstractFileExtractor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/ChainExtractor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/ExtractorInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpAstExtractor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpExtractor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpStringTokenParser.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/AbstractVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/ConstraintVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TransMethodVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatter.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatterInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatter.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatterInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/IdentityTranslator.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/ArrayLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/CsvFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/FileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuDatFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuResFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/IniFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/JsonFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/LoaderInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/MoFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/PhpFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/PoFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/QtFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/XliffFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Loader/YamlFileLoader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/LocaleSwitcher.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/LoggingTranslator.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogue.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogueInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/MetadataAwareInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/AbstractProviderFactory.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/Dsn.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/FilteringProvider.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProvider.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProviderFactory.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderFactoryInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollection.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/PseudoLocalizationTranslator.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/README.md create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReader.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReaderInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Resources/bin/translation-status.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Resources/data/parents.json create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Resources/functions.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-transitional.xsd create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xml.xsd create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderFactoryTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderTestCase.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/TranslatableMessage.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Translator.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/TranslatorBag.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/TranslatorBagInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Util/ArrayConverter.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Util/XliffUtils.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriter.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriterInterface.php create mode 100644 .extlib/simplesamlphp/vendor/symfony/translation/composer.json mode change 100755 => 100644 .extlib/simplesamlphp/vendor/symfony/var-dumper/Resources/bin/var-dump-server mode change 100755 => 100644 .extlib/simplesamlphp/vendor/symfony/yaml/Resources/bin/yaml-lint create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/CHANGELOG.md create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/LICENSE create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/README.md create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/composer.json create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/composer.lock create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/Exception.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/NamespaceUri.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/NamespaceUriException.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/Token.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollection.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollectionException.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/Tokenizer.php create mode 100644 .extlib/simplesamlphp/vendor/theseer/tokenizer/src/XMLSerializer.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/phpstan-baseline.neon create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/phpstan.neon.dist create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Cache/RemovableCacheInterface.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/DeprecatedCallableInfo.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/EmptyNode.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/XorBinary.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FunctionNode/EnumFunction.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MacroReferenceExpression.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/SpreadUnary.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/StringCastUnary.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/AssignContextVariable.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/AssignTemplateVariable.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/ContextVariable.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/LocalVariable.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/TemplateVariable.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/Node/Nodes.php delete mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/OperatorPrecedenceChange.php create mode 100644 .extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/GuardTokenParser.php diff --git a/.extlib/simplesamlphp/bin/console b/.extlib/simplesamlphp/bin/console old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/convertTranslations.php b/.extlib/simplesamlphp/bin/convertTranslations.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/importPdoMetadata.php b/.extlib/simplesamlphp/bin/importPdoMetadata.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/initMDSPdo.php b/.extlib/simplesamlphp/bin/initMDSPdo.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/ldapattrschemaparser.pl b/.extlib/simplesamlphp/bin/ldapattrschemaparser.pl old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/memcacheSync.php b/.extlib/simplesamlphp/bin/memcacheSync.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/pwgen.php b/.extlib/simplesamlphp/bin/pwgen.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/translateAttributes.php b/.extlib/simplesamlphp/bin/translateAttributes.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/bin/translations b/.extlib/simplesamlphp/bin/translations old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/docs/simplesamlphp-changelog.md b/.extlib/simplesamlphp/docs/simplesamlphp-changelog.md index 9ccff5379..76df903fd 100644 --- a/.extlib/simplesamlphp/docs/simplesamlphp-changelog.md +++ b/.extlib/simplesamlphp/docs/simplesamlphp-changelog.md @@ -5,10 +5,32 @@ This document lists the changes between versions of SimpleSAMLphp. See the [upgrade notes](https://simplesamlphp.org/docs/stable/simplesamlphp-upgrade-notes.html) for specific information about upgrading. -## Version 2.3.4 +## Version 2.3.6 Released TBD +## Version 2.3.5 + +Released 2024-12-02 + +* Fix a regression that would cause the translations for modules to revert to English + +## Version 2.3.4 + +Released 2024-12-02 + +`Security` + +* A security bug was patched in the `saml2-library` that allowed for XXE during the parsing + of SAML2-messages (CVE-2024-52596) + +`Other fixes` + +* Attributes translations are now in the "attributes" domain (#2328). +* Add `index` directive to Nginx example configuration (#2329). +* Better error message when using legacy endpoints format (#2335). +* Some minor improvements to the changes in 2.3.3. + ## Version 2.3.3 Released 2024-11-16 diff --git a/.extlib/simplesamlphp/docs/simplesamlphp-install.md b/.extlib/simplesamlphp/docs/simplesamlphp-install.md index 8d1530e61..3283f2531 100644 --- a/.extlib/simplesamlphp/docs/simplesamlphp-install.md +++ b/.extlib/simplesamlphp/docs/simplesamlphp-install.md @@ -181,6 +181,7 @@ look like this: server { listen 443 ssl; server_name idp.example.com; + index index.php; ssl_certificate /etc/pki/tls/certs/idp.example.com.crt; ssl_certificate_key /etc/pki/tls/private/idp.example.com.key; diff --git a/.extlib/simplesamlphp/docs/simplesamlphp-upgrade-notes-2.3.md b/.extlib/simplesamlphp/docs/simplesamlphp-upgrade-notes-2.3.md index e1e88b197..fcf606892 100644 --- a/.extlib/simplesamlphp/docs/simplesamlphp-upgrade-notes-2.3.md +++ b/.extlib/simplesamlphp/docs/simplesamlphp-upgrade-notes-2.3.md @@ -32,7 +32,7 @@ The use of plain-text admin-passwords has been deprecated. Generate a secure has - The language codes `pt-br` and `zh-tw` have been renamed to `pt_BR` and `zh_TW`. Please update your configuration to match the new names. -- Endpoints are now only accepted in array-style. The old string-style was deprecated for 9 yrs - already and was broken anyway. See [endpoints] +- Endpoints in metadata (e.g. "SingleSignOnLocation" and "AssertionCosumerService") can no longer be simple strings and are now only accepted in array-style. The old string-style was deprecated for 9 yrs + already and was broken anyway. See [endpoints] for the current format. [endpoints]: https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-endpoints.html diff --git a/.extlib/simplesamlphp/extra/simplesamlphp.spec b/.extlib/simplesamlphp/extra/simplesamlphp.spec index a725546e1..601fccbd5 100644 --- a/.extlib/simplesamlphp/extra/simplesamlphp.spec +++ b/.extlib/simplesamlphp/extra/simplesamlphp.spec @@ -1,6 +1,6 @@ %define name simplesamlphp %define summary SAML IDP/SP written in PHP -%define version 2.3.3 +%define version 2.3.5 %define release 1 %define license LGPL 2.1 %define group Networking/WWW diff --git a/.extlib/simplesamlphp/metadata/saml20-sp-remote.php.dist b/.extlib/simplesamlphp/metadata/saml20-sp-remote.php.dist index f57382ac3..55d735350 100644 --- a/.extlib/simplesamlphp/metadata/saml20-sp-remote.php.dist +++ b/.extlib/simplesamlphp/metadata/saml20-sp-remote.php.dist @@ -18,7 +18,7 @@ $metadata['https://saml2sp.example.org'] = [ 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', ], ], - 'SingleLogoutService' => => [ + 'SingleLogoutService' => [ [ 'Location' => 'https://saml2sp.example.org/module.php/saml/sp/saml2-logout.php/default-sp', 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', @@ -55,7 +55,7 @@ $metadata['google.com'] = [ $metadata['https://legacy.example.edu'] = [ - 'AssertionConsumerService' => => [ + 'AssertionConsumerService' => [ [ 'index' => 1, 'isDefault' => true, diff --git a/.extlib/simplesamlphp/modules/adfs/.markdownlintignore b/.extlib/simplesamlphp/modules/adfs/.markdownlintignore new file mode 100644 index 000000000..140fada73 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/.markdownlintignore @@ -0,0 +1 @@ +vendor/* diff --git a/.extlib/simplesamlphp/modules/adfs/.markdownlintrc b/.extlib/simplesamlphp/modules/adfs/.markdownlintrc new file mode 100644 index 000000000..b077f0e1d --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/.markdownlintrc @@ -0,0 +1,4 @@ +{ + "default": true, + "MD013": false +} diff --git a/.extlib/simplesamlphp/modules/adfs/LICENSE b/.extlib/simplesamlphp/modules/adfs/LICENSE new file mode 100644 index 000000000..a345e48d0 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/LICENSE @@ -0,0 +1,459 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + \ No newline at end of file diff --git a/.extlib/simplesamlphp/modules/adfs/README.md b/.extlib/simplesamlphp/modules/adfs/README.md new file mode 100644 index 000000000..bffb858a1 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/README.md @@ -0,0 +1,42 @@ +# ADFS Module + +![Build Status](https://github.com/simplesamlphp/simplesamlphp-module-adfs/workflows/CI/badge.svg?branch=master) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp-module-adfs/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp-module-adfs/?branch=master) +[![Coverage Status](https://codecov.io/gh/simplesamlphp/simplesamlphp-module-adfs/branch/master/graph/badge.svg)](https://codecov.io/gh/simplesamlphp/simplesamlphp-module-adfs) +[![Type coverage](https://shepherd.dev/github/simplesamlphp/simplesamlphp-module-adfs/coverage.svg)](https://shepherd.dev/github/simplesamlphp/simplesamlphp-module-adfs) + +## Install + +Install with composer + +```bash + vendor/bin/composer require simplesamlphp/simplesamlphp-module-adfs +``` + +## Configuration + +Next thing you need to do is to enable the module: in + `config.php`, search for the `module.enable` key and set `adfs` to true: + + ```php + 'module.enable' => [ + 'adfs' => true, + … + ], + ``` + +View samples in `metadata-templates` for defining your idp and any relying +parties/sps. + +### Tips for admins new to WS-Fed + +* A `realm` is similar to an entityId from SAML. `adfs-sp-remote.php` metadata + array is based on `realm`. An IP STS is similar to an IdP. + +* Some WS-Fed Relying Party applications want the assertion lifetime to be + longer than the application's session lifetime. If not, the application will + send the user to the IdP to login again, hoping for a longer lived assertion. + SSP's default assertion lifetime is 5 minutes while SharePoint, by default, + wants 10 minutes. Use the `assertion.lifetime` in `adfs-sp-remote.php` to set + the time greater than that set in SharePoint (which can be configured by + adjusting `LogonTokenCacheExpirationWindow`) diff --git a/.extlib/simplesamlphp/modules/adfs/composer.json b/.extlib/simplesamlphp/modules/adfs/composer.json new file mode 100644 index 000000000..7961b165b --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/composer.json @@ -0,0 +1,59 @@ +{ + "name": "simplesamlphp/simplesamlphp-module-adfs", + "description": "A module that implements the WS-federation IDP", + "type": "simplesamlphp-module", + "keywords": ["simplesamlphp", "adfs"], + "license": "LGPL-2.1-or-later", + "authors": [ + { + "name": "Tim van Dijen", + "email": "tvdijen@gmail.com" + } + ], + "config": { + "preferred-install": { + "simplesamlphp/simplesamlphp": "source", + "*": "dist" + }, + "allow-plugins": { + "composer/package-versions-deprecated": true, + "simplesamlphp/composer-module-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + } + }, + "autoload": { + "psr-4": { + "SimpleSAML\\Module\\adfs\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "SimpleSAML\\Test\\Utils\\": "vendor/simplesamlphp/simplesamlphp/tests/Utils" + } + }, + "require": { + "php": "^8.1", + "ext-dom": "*", + + "robrichards/xmlseclibs": "^3.1", + "simplesamlphp/composer-module-installer": "^1.3.2", + "simplesamlphp/assert": "^1.0", + "simplesamlphp/saml2-legacy": "^4.6", + "simplesamlphp/simplesamlphp": "^2.3", + "simplesamlphp/xml-security": "^1.6", + "symfony/http-foundation": "^6.4" + }, + "require-dev": { + "simplesamlphp/simplesamlphp-test-framework": "^1.5.4" + }, + "support": { + "issues": "https://github.com/simplesamlphp/simplesamlphp-module-adfs/issues", + "source": "https://github.com/simplesamlphp/simplesamlphp-module-adfs" + }, + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + } +} diff --git a/.extlib/simplesamlphp/modules/adfs/docs/adfs.md b/.extlib/simplesamlphp/modules/adfs/docs/adfs.md new file mode 100644 index 000000000..ead56cb6c --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/docs/adfs.md @@ -0,0 +1,97 @@ +# ADFS Module + +Enables AD FS IdP +Compatible with VS 2012 Identity and Access + +Basic Setup Companion based on [SimpleSAMLphp IDP configuration][docs] + +1. Enabling the Identity Provider functionality + + In config/config.php, the option will be: + 'enable.adfs-idp' => true + +2. Authentication module + + Follow as is. + +3. Configuring the authentication module + + Next thing you need to do is to enable the module: in `config.php`, + search for the `module.enable` key and set `adfs` to true: + + ```php + 'module.enable' => [ + 'adfs' => true, + … + ], + ``` + +4. Configuring the IdP + + ADFS IdP is configured by metadata stored in /metadata/adfs-idp-hosted.php + and metadata/adfs-sp-remote.php + + If they are not present, copy them from /metadata-templates to the metadata + directory. + +5. Using the uri NameFormat on attributes + + WS-FED likes a few parameters to be very specifically named. This is + especially true if .net clients will be treating this as a Microsoft ADFS + IdP. + + The recommended settings for /metadata/adfs-idp-hosted.php is: + + ```php + 'authproc' => [ + // Convert LDAP names to WS-Fed Claims. + 100 => ['class' => 'core:AttributeMap', 'name2claim'], + ], + ``` + +6. Adding SPs to the IdP + + The minimal configuration for /metadata/adfs-sp-remote.php is: + + ```php + $metadata['urn:federation:localhost'] = [ + 'prp' => 'https://localhost/adfs/ls/', + ]; + ``` + +7. Creating a SSL self signed certificate + + Follow as is. + +8. Adding this IdP to other SPs + + Metadata should be available from /module.php/adfs/idp/metadata.php + +9. This module tries its best to emulate a Microsoft ADFS endpoint, and as + such, it is simplest to test using a .net client. + + To build the test client, follow the tutorial from [Microsoft][ms_docs]. + + This will build a .net app that uses a dev machine running STS (their name for + an IdP). + + To point to your SimpleSamlPHP ADFS IdP, in VS 2012: + + a. Right-click the project in Solution Explorer and select the Identity and + Access option. + + b. In the Identity and Access Window, Select Use a business identity + provider. + + c. Under “Enter the path to the STS metadata document†enter the url you have + + from step 8. Something like + `https://.../module.php/adfs/idp/metadata.php` + + d. Click Ok + +For more information in regards to [.NET][dotnet] + +[dotnet]: http://msdn.microsoft.com/en-us/library/hh377151.aspx +[docs]: http://simplesamlphp.org/docs/stable/simplesamlphp-idp +[ms_docs]: http://code.msdn.microsoft.com/Claims-Aware-Web-d94a89ca diff --git a/.extlib/simplesamlphp/modules/adfs/metadata/adfs-idp-hosted.php.dist b/.extlib/simplesamlphp/modules/adfs/metadata/adfs-idp-hosted.php.dist new file mode 100644 index 000000000..5e271887e --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/metadata/adfs-idp-hosted.php.dist @@ -0,0 +1,15 @@ + '__DEFAULT__', + 'privatekey' => 'server.pem', + 'certificate' => 'server.crt', + // Some WS-Fed relying parties applications set the session lifetime to the assertion lifetime + // 'assertion.lifetime' => 3600, + + 'auth' => 'example-userpass', + 'authproc' => [ + // Convert LDAP names to WS-Fed Claims. + 100 => ['class' => 'core:AttributeMap', 'name2claim'], + ], +]; diff --git a/.extlib/simplesamlphp/modules/adfs/metadata/adfs-sp-remote.php.dist b/.extlib/simplesamlphp/modules/adfs/metadata/adfs-sp-remote.php.dist new file mode 100644 index 000000000..a6a01277c --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/metadata/adfs-sp-remote.php.dist @@ -0,0 +1,14 @@ + 'https://localhost/adfs/ls/', + 'simplesaml.nameidattribute' => 'uid', + // Some WS-Fed relying parties applications set the session lifetime to the assertion lifetime + // 'assertion.lifetime' => 3600, + 'authproc' => [ + 50 => [ + 'class' => 'core:AttributeLimit', + 'cn', 'mail', 'uid', 'eduPersonAffiliation', + ], + ], +]; diff --git a/.extlib/simplesamlphp/modules/adfs/psalm-dev.xml b/.extlib/simplesamlphp/modules/adfs/psalm-dev.xml new file mode 100644 index 000000000..6116331c7 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/psalm-dev.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/modules/adfs/public/assets/js/postResponse.js b/.extlib/simplesamlphp/modules/adfs/public/assets/js/postResponse.js new file mode 100644 index 000000000..a813b92cb --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/public/assets/js/postResponse.js @@ -0,0 +1,3 @@ +document.addEventListener('DOMContentLoaded', function () { + document.forms[0].submit(); +}); diff --git a/.extlib/simplesamlphp/modules/adfs/routing/routes/routes.yml b/.extlib/simplesamlphp/modules/adfs/routing/routes/routes.yml new file mode 100644 index 000000000..01d2fc84e --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/routing/routes/routes.yml @@ -0,0 +1,29 @@ +--- + +adfs-metadata: + path: /metadata + defaults: { + _controller: 'SimpleSAML\Module\adfs\Controller\Adfs::metadata' + } + methods: [GET] + +adfs-prp: + path: /prp + defaults: { + _controller: 'SimpleSAML\Module\adfs\Controller\Adfs::prp' + } + methods: [GET] + +adfs-metadata-legacy: + path: /idp/metadata.php + defaults: { + _controller: 'SimpleSAML\Module\adfs\Controller\Adfs::metadata' + } + methods: [GET] + +adfs-prp-legacy: + path: /idp/prp.php + defaults: { + _controller: 'SimpleSAML\Module\adfs\Controller\Adfs::prp' + } + methods: [GET] diff --git a/.extlib/simplesamlphp/modules/adfs/src/Controller/Adfs.php b/.extlib/simplesamlphp/modules/adfs/src/Controller/Adfs.php new file mode 100644 index 000000000..14290d244 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/src/Controller/Adfs.php @@ -0,0 +1,265 @@ +config = $config; + $this->metadata = Metadata\MetaDataStorageHandler::getMetadataHandler(); + $this->session = $session; + $this->cryptoUtils = new Utils\Crypto(); + } + + + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * @return \Symfony\Component\HttpFoundation\Response|\SimpleSAML\XHTML\Template + */ + public function metadata(Request $request): Response + { + if (!$this->config->getOptionalBoolean('enable.adfs-idp', false)) { + throw new SspError\Error('NOACCESS'); + } + + // check if valid local session exists + $authUtils = new Utils\Auth(); + if ($this->config->getOptionalBoolean('admin.protectmetadata', false) && !$authUtils->isAdmin()) { + return new StreamedResponse([$authUtils, 'requireAdmin']); + } + + try { + if ($request->query->has('idpentityid')) { + $idpentityid = $request->query->get('idpentityid'); + } else { + $idpentityid = $this->metadata->getMetaDataCurrentEntityID('adfs-idp-hosted'); + } + $idpmeta = $this->metadata->getMetaDataConfig($idpentityid, 'adfs-idp-hosted'); + + $availableCerts = []; + $keys = []; + $certInfo = $this->cryptoUtils->loadPublicKey($idpmeta, false, 'new_'); + + if ($certInfo !== null) { + $availableCerts['new_idp.crt'] = $certInfo; + $keys[] = [ + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => true, + 'X509Certificate' => $certInfo['certData'], + ]; + $hasNewCert = true; + } else { + $hasNewCert = false; + } + + /** @var array $certInfo */ + $certInfo = $this->cryptoUtils->loadPublicKey($idpmeta, true); + $availableCerts['idp.crt'] = $certInfo; + $keys[] = [ + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => ($hasNewCert ? false : true), + 'X509Certificate' => $certInfo['certData'], + ]; + + if ($idpmeta->hasValue('https.certificate')) { + /** @var array $httpsCert */ + $httpsCert = $this->cryptoUtils->loadPublicKey($idpmeta, true, 'https.'); + Assert::keyExists($httpsCert, 'certData'); + $availableCerts['https.crt'] = $httpsCert; + $keys[] = [ + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => false, + 'X509Certificate' => $httpsCert['certData'], + ]; + } + + $adfs_service_location = Module::getModuleURL('adfs') . '/idp/prp.php'; + $metaArray = [ + 'metadata-set' => 'adfs-idp-remote', + 'entityid' => $idpentityid, + 'SingleSignOnService' => [ + 0 => [ + 'Binding' => Constants::BINDING_HTTP_REDIRECT, + 'Location' => $adfs_service_location + ] + ], + 'SingleLogoutService' => [ + 0 => [ + 'Binding' => Constants::BINDING_HTTP_REDIRECT, + 'Location' => $adfs_service_location + ] + ], + ]; + + if (count($keys) === 1) { + $metaArray['certData'] = $keys[0]['X509Certificate']; + } else { + $metaArray['keys'] = $keys; + } + + $metaArray['NameIDFormat'] = $idpmeta->getOptionalString( + 'NameIDFormat', + Constants::NAMEID_TRANSIENT + ); + + if ($idpmeta->hasValue('OrganizationName')) { + $metaArray['OrganizationName'] = $idpmeta->getLocalizedString('OrganizationName'); + $metaArray['OrganizationDisplayName'] = $idpmeta->getOptionalLocalizedString( + 'OrganizationDisplayName', + $metaArray['OrganizationName'] + ); + + if (!$idpmeta->hasValue('OrganizationURL')) { + throw new SspError\Exception('If OrganizationName is set, OrganizationURL must also be set.'); + } + $metaArray['OrganizationURL'] = $idpmeta->getLocalizedString('OrganizationURL'); + } + + if ($idpmeta->hasValue('scope')) { + $metaArray['scope'] = $idpmeta->getArray('scope'); + } + + if ($idpmeta->hasValue('EntityAttributes')) { + $metaArray['EntityAttributes'] = $idpmeta->getArray('EntityAttributes'); + } + + if ($idpmeta->hasValue('UIInfo')) { + $metaArray['UIInfo'] = $idpmeta->getArray('UIInfo'); + } + + if ($idpmeta->hasValue('DiscoHints')) { + $metaArray['DiscoHints'] = $idpmeta->getArray('DiscoHints'); + } + + if ($idpmeta->hasValue('RegistrationInfo')) { + $metaArray['RegistrationInfo'] = $idpmeta->getArray('RegistrationInfo'); + } + + $metaBuilder = new Metadata\SAMLBuilder($idpentityid); + $metaBuilder->addSecurityTokenServiceType($metaArray); + $metaBuilder->addOrganizationInfo($metaArray); + $technicalContactEmail = $this->config->getOptionalString('technicalcontact_email', null); + if ($technicalContactEmail !== null && $technicalContactEmail !== 'na@example.org') { + $metaBuilder->addContact(Utils\Config\Metadata::getContact([ + 'emailAddress' => $technicalContactEmail, + 'givenName' => $this->config->getOptionalString('technicalcontact_name', null), + 'contactType' => 'technical', + ])); + } + $metaxml = $metaBuilder->getEntityDescriptorText(); + + // sign the metadata if enabled + $metaxml = Metadata\Signer::sign($metaxml, $idpmeta->toArray(), 'ADFS IdP'); + + $response = new Response(); + $response->setEtag(hash('sha256', $metaxml)); + $response->setCache([ + 'no_cache' => $protectedMetadata === true, + 'public' => $protectedMetadata === false, + 'private' => $protectedMetadata === true, + ]); + + if ($response->isNotModified($request)) { + return $response; + } + $response->headers->set('Content-Type', 'application/samlmetadata+xml'); + $response->headers->set('Content-Disposition', 'attachment; filename="FederationMetadata.xml"'); + $response->setContent($metaxml); + + return $response; + } catch (Exception $exception) { + throw new SspError\Error('METADATA', $exception); + } + } + + + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * @return \Symfony\Component\HttpFoundation\Response + */ + public function prp(Request $request): Response + { + Logger::info('ADFS - IdP.prp: Accessing ADFS IdP endpoint prp'); + + $idpEntityId = $this->metadata->getMetaDataCurrentEntityID('adfs-idp-hosted'); + $idp = IdP::getById('adfs:' . $idpEntityId); + + if ($request->query->has('wa')) { + $wa = $request->query->get('wa'); + if ($wa === 'wsignout1.0') { + return new StreamedResponse( + function () use ($idp) { + ADFS_IDP::receiveLogoutMessage($idp); + } + ); + } elseif ($wa === 'wsignin1.0') { + return ADFS_IDP::receiveAuthnRequest($request, $idp); + } + throw new SspError\BadRequest("Unsupported value for 'wa' specified in request."); + } elseif ($request->query->has('assocId')) { + // logout response from ADFS SP + // Association ID of the SP that sent the logout response + $assocId = $request->query->get('assocId'); + // Data that was sent in the logout request to the SP. Can be null + $relayState = $request->query->get('relayState'); + // null on success, or an instance of a \SimpleSAML\Error\Exception on failure. + $logoutError = null; + + return new StreamedResponse( + function () use ($idp, /** @scrutinizer ignore-type */ $assocId, $relayState, $logoutError) { + $idp->handleLogoutResponse($assocId, $relayState, $logoutError); + } + ); + } + throw new SspError\BadRequest("Missing parameter 'wa' or 'assocId' in request."); + } +} diff --git a/.extlib/simplesamlphp/modules/adfs/src/IdP/ADFS.php b/.extlib/simplesamlphp/modules/adfs/src/IdP/ADFS.php new file mode 100644 index 000000000..4473087e5 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/src/IdP/ADFS.php @@ -0,0 +1,479 @@ +server->get('QUERY_STRING'), $query); + + $requestid = $query['wctx'] ?? null; + $issuer = $query['wtrealm']; + + $metadata = MetaDataStorageHandler::getMetadataHandler(); + $spMetadata = $metadata->getMetaDataConfig($issuer, 'adfs-sp-remote'); + + Logger::info('ADFS - IdP.prp: Incoming Authentication request: ' . $issuer . ' id ' . $requestid); + + if ($request->query->has('username')) { + $username = (string) $request->query->get('username'); + } + + $state = [ + 'Responder' => [ADFS::class, 'sendResponse'], + 'SPMetadata' => $spMetadata->toArray(), + 'ForceAuthn' => false, + 'isPassive' => false, + 'adfs:wctx' => $requestid, + 'adfs:wreply' => false + ]; + + if ($username !== null) { + $state['core:username'] = $username; + } + + if (isset($query['wreply']) && !empty($query['wreply'])) { + $httpUtils = new Utils\HTTP(); + $state['adfs:wreply'] = $httpUtils->checkURLAllowed($query['wreply']); + } + + return new StreamedResponse( + function () use ($idp, $state) { + $idp->handleAuthenticationRequest($state); + } + ); + } + + + /** + * @param string $issuer + * @param string $target + * @param string $nameid + * @param array $attributes + * @param int $assertionLifetime + * @return string + */ + private static function generateResponse( + string $issuer, + string $target, + string $nameid, + array $attributes, + int $assertionLifetime + ): string { + $httpUtils = new Utils\HTTP(); + $randomUtils = new Utils\Random(); + $timeUtils = new Utils\Time(); + + $issueInstant = $timeUtils->generateTimestamp(); + $notBefore = $timeUtils->generateTimestamp(time() - 30); + $assertionExpire = $timeUtils->generateTimestamp(time() + $assertionLifetime); + $assertionID = $randomUtils->generateID(); + $nameidFormat = 'http://schemas.xmlsoap.org/claims/UPN'; + $nameid = htmlspecialchars($nameid); + + if ($httpUtils->isHTTPS()) { + $method = Constants::AC_PASSWORD_PROTECTED_TRANSPORT; + } else { + $method = Constants::AC_PASSWORD; + } + + $result = << + + + + + $target + + + + + $nameid + + + + + $nameid + +MSG; + + $attrUtils = new Utils\Attributes(); + foreach ($attributes as $name => $values) { + if ((!is_array($values)) || (count($values) == 0)) { + continue; + } + + list($namespace, $name) = $attrUtils->getAttributeNamespace( + $name, + 'http://schemas.xmlsoap.org/claims' + ); + $namespace = htmlspecialchars($namespace); + $name = htmlspecialchars($name); + foreach ($values as $value) { + if ((!isset($value)) || ($value === '')) { + continue; + } + $value = htmlspecialchars($value); + + $result .= << + $value + +MSG; + } + } + + $result .= << + + + + + $target + + + +MSG; + + return $result; + } + + + /** + * @param string $response + * @param string $key + * @param string $cert + * @param string $algo + * @param string|null $passphrase + * @return string + */ + private static function signResponse( + string $response, + string $key, + string $cert, + string $algo, + #[\SensitiveParameter] + string $passphrase = null, + ): string { + $objXMLSecDSig = new XMLSecurityDSig(); + $objXMLSecDSig->idKeys = ['AssertionID']; + $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); + $responsedom = DOMDocumentFactory::fromString(str_replace("\r", "", $response)); + $firstassertionroot = $responsedom->getElementsByTagName('Assertion')->item(0); + + if (is_null($firstassertionroot)) { + throw new Exception("No assertion found in response."); + } + + $objXMLSecDSig->addReferenceList( + [$firstassertionroot], + XMLSecurityDSig::SHA256, + ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N], + ['id_name' => 'AssertionID'] + ); + + $objKey = new XMLSecurityKey($algo, ['type' => 'private']); + if (is_string($passphrase)) { + $objKey->passphrase = $passphrase; + } + $objKey->loadKey($key, true); + $objXMLSecDSig->sign($objKey); + if ($cert) { + $public_cert = file_get_contents($cert); + $objXMLSecDSig->add509Cert($public_cert, true); + } + + /** @var \DOMElement $objXMLSecDSig->sigNode */ + $newSig = $responsedom->importNode($objXMLSecDSig->sigNode, true); + $firstassertionroot->appendChild($newSig); + return $responsedom->saveXML(); + } + + + /** + * @param string $wreply + * @param string $wresult + * @param ?string $wctx + */ + private static function postResponse(string $wreply, string $wresult, ?string $wctx): void + { + $config = Configuration::getInstance(); + $t = new Template($config, 'adfs:postResponse.twig'); + $t->data['wreply'] = $wreply; + $t->data['wresult'] = $wresult; + $t->data['wctx'] = $wctx; + $t->send(); + // Idp->postAuthProc expects this function to exit + exit(); + } + + + /** + * Get the metadata of a given hosted ADFS IdP. + * + * @param string $entityid The entity ID of the hosted ADFS IdP whose metadata we want to fetch. + * + * @return array + * @throws \SimpleSAML\Error\Exception + * @throws \SimpleSAML\Error\MetadataNotFound + */ + public static function getHostedMetadata(string $entityid): array + { + $handler = MetaDataStorageHandler::getMetadataHandler(); + $cryptoUtils = new Utils\Crypto(); + $config = $handler->getMetaDataConfig($entityid, 'adfs-idp-hosted'); + + $endpoint = Module::getModuleURL('adfs/idp/prp.php'); + $metadata = [ + 'metadata-set' => 'adfs-idp-hosted', + 'entityid' => $entityid, + 'SingleSignOnService' => [ + [ + 'Binding' => Constants::BINDING_HTTP_REDIRECT, + 'Location' => $endpoint, + ] + ], + 'SingleLogoutService' => [ + 'Binding' => Constants::BINDING_HTTP_REDIRECT, + 'Location' => $endpoint, + ], + 'NameIDFormat' => $config->getOptionalString('NameIDFormat', Constants::NAMEID_TRANSIENT), + 'contacts' => [], + ]; + + // add certificates + $keys = []; + $certInfo = $cryptoUtils->loadPublicKey($config, false, 'new_'); + $hasNewCert = false; + if ($certInfo !== null) { + $keys[] = [ + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => true, + 'X509Certificate' => $certInfo['certData'], + 'prefix' => 'new_', + ]; + $hasNewCert = true; + } + + /** @var array $certInfo */ + $certInfo = $cryptoUtils->loadPublicKey($config, true); + $keys[] = [ + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => $hasNewCert === false, + 'X509Certificate' => $certInfo['certData'], + 'prefix' => '', + ]; + + if ($config->hasValue('https.certificate')) { + /** @var array $httpsCert */ + $httpsCert = $cryptoUtils->loadPublicKey($config, true, 'https.'); + $keys[] = [ + 'type' => 'X509Certificate', + 'signing' => true, + 'encryption' => false, + 'X509Certificate' => $httpsCert['certData'], + 'prefix' => 'https.' + ]; + } + $metadata['keys'] = $keys; + + // add organization information + if ($config->hasValue('OrganizationName')) { + $metadata['OrganizationName'] = $config->getLocalizedString('OrganizationName'); + $metadata['OrganizationDisplayName'] = $config->getOptionalLocalizedString( + 'OrganizationDisplayName', + $metadata['OrganizationName'] + ); + + if (!$config->hasValue('OrganizationURL')) { + throw new Error\Exception('If OrganizationName is set, OrganizationURL must also be set.'); + } + $metadata['OrganizationURL'] = $config->getLocalizedString('OrganizationURL'); + } + + // add scope + if ($config->hasValue('scope')) { + $metadata['scope'] = $config->getArray('scope'); + } + + // add extensions + if ($config->hasValue('EntityAttributes')) { + $metadata['EntityAttributes'] = $config->getArray('EntityAttributes'); + + // check for entity categories + if (Utils\Config\Metadata::isHiddenFromDiscovery($metadata)) { + $metadata['hide.from.discovery'] = true; + } + } + + if ($config->hasValue('UIInfo')) { + $metadata['UIInfo'] = $config->getArray('UIInfo'); + } + + if ($config->hasValue('DiscoHints')) { + $metadata['DiscoHints'] = $config->getArray('DiscoHints'); + } + + if ($config->hasValue('RegistrationInfo')) { + $metadata['RegistrationInfo'] = $config->getArray('RegistrationInfo'); + } + + // add contact information + $globalConfig = Configuration::getInstance(); + $email = $globalConfig->getOptionalString('technicalcontact_email', null); + if ($email !== null && $email !== 'na@example.org') { + $contact = [ + 'emailAddress' => $email, + 'givenName' => $globalConfig->getOptionalString('technicalcontact_name', null), + 'contactType' => 'technical', + ]; + $metadata['contacts'][] = Utils\Config\Metadata::getContact($contact); + } + + return $metadata; + } + + + /** + * @param array $state + * @throws \Exception + */ + public static function sendResponse(array $state): void + { + $spMetadata = $state["SPMetadata"]; + $spEntityId = $spMetadata['entityid']; + $spMetadata = Configuration::loadFromArray( + $spMetadata, + '$metadata[' . var_export($spEntityId, true) . ']' + ); + + $attributes = $state['Attributes']; + + $nameidattribute = $spMetadata->getValue('simplesaml.nameidattribute'); + if (!empty($nameidattribute)) { + if (!array_key_exists($nameidattribute, $attributes)) { + throw new Exception('simplesaml.nameidattribute does not exist in resulting attribute set'); + } + $nameid = $attributes[$nameidattribute][0]; + } else { + $randomUtils = new Utils\Random(); + $nameid = $randomUtils->generateID(); + } + + $idp = IdP::getByState($state); + $idpMetadata = $idp->getConfig(); + $idpEntityId = $idpMetadata->getString('entityid'); + + $idp->addAssociation([ + 'id' => 'adfs:' . $spEntityId, + 'Handler' => ADFS::class, + 'adfs:entityID' => $spEntityId, + ]); + + $assertionLifetime = $spMetadata->getOptionalInteger('assertion.lifetime', null); + if ($assertionLifetime === null) { + $assertionLifetime = $idpMetadata->getOptionalInteger('assertion.lifetime', 300); + } + + $response = ADFS::generateResponse($idpEntityId, $spEntityId, $nameid, $attributes, $assertionLifetime); + + $configUtils = new Utils\Config(); + $privateKeyFile = $configUtils->getCertPath($idpMetadata->getString('privatekey')); + $certificateFile = $configUtils->getCertPath($idpMetadata->getString('certificate')); + $passphrase = $idpMetadata->getOptionalString('privatekey_pass', null); + + $algo = $spMetadata->getOptionalString('signature.algorithm', null); + if ($algo === null) { + $algo = $idpMetadata->getOptionalString('signature.algorithm', XMLSecurityKey::RSA_SHA256); + } + $wresult = ADFS::signResponse($response, $privateKeyFile, $certificateFile, $algo, $passphrase); + + $wctx = $state['adfs:wctx']; + $wreply = $state['adfs:wreply'] ? : $spMetadata->getValue('prp'); + ADFS::postResponse($wreply, $wresult, $wctx); + } + + + /** + * @param \SimpleSAML\IdP $idp + * @param array $state + */ + public static function sendLogoutResponse(IdP $idp, array $state): void + { + // NB:: we don't know from which SP the logout request came from + $idpMetadata = $idp->getConfig(); + $httpUtils = new Utils\HTTP(); + $httpUtils->redirectTrustedURL( + $idpMetadata->getOptionalString('redirect-after-logout', $httpUtils->getBaseURL()) + ); + } + + + /** + * @param \SimpleSAML\IdP $idp + * @throws \Exception + */ + public static function receiveLogoutMessage(IdP $idp): void + { + // if a redirect is to occur based on wreply, we will redirect to url as + // this implies an override to normal sp notification + if (isset($_GET['wreply']) && !empty($_GET['wreply'])) { + $httpUtils = new Utils\HTTP(); + $idp->doLogoutRedirect($httpUtils->checkURLAllowed($_GET['wreply'])); + throw new Exception("Code should never be reached"); + } + + $state = [ + 'Responder' => [ADFS::class, 'sendLogoutResponse'], + ]; + $assocId = null; + // TODO: verify that this is really no problem for: + // a) SSP, because there's no caller SP. + // b) ADFS SP because caller will be called back.. + $idp->handleLogoutRequest($state, $assocId); + } + + + /** + * accepts an association array, and returns a URL that can be accessed to terminate the association + * + * @param \SimpleSAML\IdP $idp + * @param array $association + * @param string $relayState + * @return string + */ + public static function getLogoutURL(IdP $idp, array $association, string $relayState): string + { + $metadata = MetaDataStorageHandler::getMetadataHandler(); + $spMetadata = $metadata->getMetaDataConfig($association['adfs:entityID'], 'adfs-sp-remote'); + $returnTo = Module::getModuleURL( + 'adfs/idp/prp.php?assocId=' . urlencode($association["id"]) . '&relayState=' . urlencode($relayState) + ); + return $spMetadata->getValue('prp') . '?wa=wsignoutcleanup1.0&wreply=' . urlencode($returnTo); + } +} diff --git a/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/Constants.php b/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/Constants.php new file mode 100644 index 000000000..bc4afe629 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/Constants.php @@ -0,0 +1,19 @@ +ownerDocument->createElement($name); + $parent->appendChild($e); + + $endpoint = $parent->ownerDocument->createElementNS(Constants::NS_FED, 'fed:EndpointReference'); + $e->appendChild($endpoint); + + $address = $parent->ownerDocument->createElementNS('http://www.w3.org/2005/08/addressing', 'wsa:Address', $address); + $endpoint->appendChild($address); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/SecurityTokenServiceType.php b/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/SecurityTokenServiceType.php new file mode 100644 index 000000000..cc73052eb --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/SecurityTokenServiceType.php @@ -0,0 +1,92 @@ +protocolSupportEnumeration); + + if ($xml === null) { + return; + } + } + + /** + * Convert this SecurityTokenServiceType RoleDescriptor to XML. + * + * @param \DOMElement $parent The element we should add this contact to. + * @return \DOMElement The new ContactPerson-element. + */ + public function toXML(DOMElement $parent): DOMElement + { + Assert::notEmpty($this->Location, 'Location not set'); + + $e = parent::toXML($parent); + $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:fed', Constants::NS_FED); + $e->setAttributeNS(Constants::NS_XSI, 'xsi:type', 'fed:SecurityTokenServiceType'); + TokenTypesOffered::appendXML($e); + Endpoint::appendXML($e, 'fed:SecurityTokenServiceEndpoint', $this->Location); + Endpoint::appendXML($e, 'fed:PassiveRequestorEndpoint', $this->Location); + + return $e; + } + + + /** + * Get the location of this service. + * + * @return string The full URL where this service can be reached. + */ + public function getLocation(): string + { + Assert::notEmpty($this->Location, 'Location not set'); + + return $this->Location; + } + + + /** + * Set the location of this service. + * + * @param string $location The full URL where this service can be reached. + */ + public function setLocation(string $location): void + { + $this->Location = $location; + } +} diff --git a/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/TokenTypesOffered.php b/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/TokenTypesOffered.php new file mode 100644 index 000000000..118c10371 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/src/SAML2/XML/fed/TokenTypesOffered.php @@ -0,0 +1,34 @@ +ownerDocument->createElementNS(Constants::NS_FED, 'fed:TokenTypesOffered'); + $parent->appendChild($e); + + $tokentype = $parent->ownerDocument->createElementNS(Constants::NS_FED, 'fed:TokenType'); + $tokentype->setAttribute('Uri', 'urn:oasis:names:tc:SAML:1.0:assertion'); + $e->appendChild($tokentype); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/modules/adfs/templates/postResponse.twig b/.extlib/simplesamlphp/modules/adfs/templates/postResponse.twig new file mode 100644 index 000000000..073c7cdb7 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/templates/postResponse.twig @@ -0,0 +1,16 @@ + + + + + + +
+ + + + +
+ + diff --git a/.extlib/simplesamlphp/modules/adfs/tools/composer-require-checker.json b/.extlib/simplesamlphp/modules/adfs/tools/composer-require-checker.json new file mode 100644 index 000000000..eed71aa18 --- /dev/null +++ b/.extlib/simplesamlphp/modules/adfs/tools/composer-require-checker.json @@ -0,0 +1,4 @@ +{ + "symbol-whitelist": [ + ] +} diff --git a/.extlib/simplesamlphp/modules/cron/bin/cron.php b/.extlib/simplesamlphp/modules/cron/bin/cron.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/modules/saml/src/Auth/Source/SP.php b/.extlib/simplesamlphp/modules/saml/src/Auth/Source/SP.php index 0b8e184be..0d1f61992 100644 --- a/.extlib/simplesamlphp/modules/saml/src/Auth/Source/SP.php +++ b/.extlib/simplesamlphp/modules/saml/src/Auth/Source/SP.php @@ -315,10 +315,10 @@ public function getHostedMetadata(): array */ public function getIdPMetadata(string $entityId): Configuration { - // auth_saml2 modification. - // Set the IdP to null, so it can auto-detect. - // Avoid the case where it uses the default IdP data for IdP initiated login. - $this->idp = null; + if ($this->idp !== null && $this->idp !== $entityId) { + throw new Error\Exception('Cannot retrieve metadata for IdP ' . + var_export($entityId, true) . ' because it isn\'t a valid IdP for this SP.'); + } $metadataHandler = MetaDataStorageHandler::getMetadataHandler(); @@ -469,10 +469,7 @@ private function startSSO2(Configuration $idpMetadata, array $state): void $ar = Module\saml\Message::buildAuthnRequest($this->metadata, $idpMetadata); - // auth_saml2 modification - $baseurl = \SimpleSAML\Module::getModuleURL('saml/sp/saml2-acs.php/' . $this->authId); - $baseurl = str_replace('module.php/saml/sp/', '', $baseurl); - $ar->setAssertionConsumerServiceURL($baseurl); + $ar->setAssertionConsumerServiceURL(Module::getModuleURL('saml/sp/saml2-acs.php/' . $this->authId)); if (isset($state['\SimpleSAML\Auth\Source.ReturnURL'])) { $ar->setRelayState($state['\SimpleSAML\Auth\Source.ReturnURL']); @@ -583,8 +580,8 @@ private function startSSO2(Configuration $idpMetadata, array $state): void /* Only check for real info for Scoping element if we are going to send Scoping element */ if ($this->disable_scoping !== true && $idpMetadata->getOptionalBoolean('disable_scoping', false) !== true) { - if (isset($state['IDPList'])) { - $ar->setIDPList($state['IDPList']); + if (isset($state['saml:IDPList'])) { + $ar->setIDPList($state['saml:IDPList']); } elseif (!empty($this->metadata->getOptionalArray('IDPList', []))) { $ar->setIDPList($this->metadata->getArray('IDPList')); } elseif (!empty($idpMetadata->getOptionalArray('IDPList', []))) { @@ -661,8 +658,6 @@ private function startSSO2(Configuration $idpMetadata, array $state): void [ Constants::BINDING_HTTP_REDIRECT, Constants::BINDING_HTTP_POST, - // auth_saml2 modification - Reordered to maintain existing functionality. - Constants::BINDING_HTTP_ARTIFACT, ], ); } @@ -670,12 +665,6 @@ private function startSSO2(Configuration $idpMetadata, array $state): void $b = Binding::getBinding($dst['Binding']); - // This is a Moodle hack. Both moodle and SSPHP rely on automatic - // destructors to cleanup the $DB var and the SSPHP session but - // this order is not guaranteed, so we force session saving here. - $session = \SimpleSAML\Session::getSessionFromRequest(); - $session->save(); - $this->sendSAML2AuthnRequest($b, $ar); Assert::true(false); @@ -1215,22 +1204,9 @@ public function handleLogout(string $idpEntityId): void */ public static function handleUnsolicitedAuth(string $authId, array $state, string $redirectTo): void { - global $SESSION, $saml2auth; - $session = Session::getSessionFromRequest(); $session->doLogin($authId, Auth\State::getPersistentAuthData($state)); - // Moodle hack to handle IdP unsolicited logins. - $wantsurl = (new \moodle_url($redirectTo))->out(false); - $SESSION->wantsurl = $wantsurl; - if (!empty($state['saml:sp:IdP'])) { - $SESSION->saml2idp = md5($state['saml:sp:IdP']); - } else { - unset($SESSION->saml2idp); - } - $saml2auth->saml_login_complete($state['Attributes']); - // Should never get to here. - $httpUtils = new Utils\HTTP(); $httpUtils->redirectUntrustedURL($redirectTo); } diff --git a/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css b/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css index b90c689bc..f373e6d12 100644 --- a/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css +++ b/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css @@ -1527,11 +1527,11 @@ code.hljs { font-weight: bold } /*! - * Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com + * Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) * Copyright 2024 Fonticons, Inc. - */.fa{font-family:var(--fa-style-family, "Font Awesome 6 Free");font-weight:var(--fa-style, 900)}.fa-solid,.fa-regular,.fa-brands,.fas,.far,.fab,.fa-sharp-solid,.fa-classic,.fa{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display, inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fas,.fa-classic,.fa-solid,.far,.fa-regular{font-family:"Font Awesome 6 Free"}.fab,.fa-brands{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.0833333337em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.0714285718em;vertical-align:.0535714295em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.0416666682em;vertical-align:-0.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-0.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin, 2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(-1*var(--fa-li-width, 2em));position:absolute;text-align:center;width:var(--fa-li-width, 2em);line-height:inherit}.fa-border{border-color:var(--fa-border-color, #eee);border-radius:var(--fa-border-radius, 0.1em);border-style:var(--fa-border-style, solid);border-width:var(--fa-border-width, 0.08em);padding:var(--fa-border-padding, 0.2em 0.25em 0.15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin, 0.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin, 0.3em)}.fa-beat{animation-name:fa-beat;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, ease-in-out)}.fa-bounce{animation-name:fa-bounce;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1))}.fa-fade{animation-name:fa-fade;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1))}.fa-beat-fade{animation-name:fa-beat-fade;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1))}.fa-flip{animation-name:fa-flip;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, ease-in-out)}.fa-shake{animation-name:fa-shake;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, linear)}.fa-spin{animation-name:fa-spin;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 2s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, linear)}.fa-spin-reverse{--fa-animation-direction: reverse}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, steps(8))}@media(prefers-reduced-motion: reduce){.fa-beat,.fa-bounce,.fa-fade,.fa-beat-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@keyframes fa-beat{0%,90%{transform:scale(1)}45%{transform:scale(var(--fa-beat-scale, 1.25))}}@keyframes fa-bounce{0%{transform:scale(1, 1) translateY(0)}10%{transform:scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0)}30%{transform:scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em))}50%{transform:scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0)}57%{transform:scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em))}64%{transform:scale(1, 1) translateY(0)}100%{transform:scale(1, 1) translateY(0)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity, 0.4)}}@keyframes fa-beat-fade{0%,100%{opacity:var(--fa-beat-fade-opacity, 0.4);transform:scale(1)}50%{opacity:1;transform:scale(var(--fa-beat-fade-scale, 1.125))}}@keyframes fa-flip{50%{transform:rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg))}}@keyframes fa-shake{0%{transform:rotate(-15deg)}4%{transform:rotate(15deg)}8%,24%{transform:rotate(-18deg)}12%,28%{transform:rotate(18deg)}16%{transform:rotate(-22deg)}20%{transform:rotate(22deg)}32%{transform:rotate(-12deg)}36%{transform:rotate(12deg)}40%,100%{transform:rotate(0deg)}}@keyframes fa-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.fa-rotate-90{transform:rotate(90deg)}.fa-rotate-180{transform:rotate(180deg)}.fa-rotate-270{transform:rotate(270deg)}.fa-flip-horizontal{transform:scale(-1, 1)}.fa-flip-vertical{transform:scale(1, -1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1, -1)}.fa-rotate-by{transform:rotate(var(--fa-rotate-angle, 0))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index, auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse, #fff)}.fa-0::before{content:"\30 "}.fa-1::before{content:"\31 "}.fa-2::before{content:"\32 "}.fa-3::before{content:"\33 "}.fa-4::before{content:"\34 "}.fa-5::before{content:"\35 "}.fa-6::before{content:"\36 "}.fa-7::before{content:"\37 "}.fa-8::before{content:"\38 "}.fa-9::before{content:"\39 "}.fa-fill-drip::before{content:""}.fa-arrows-to-circle::before{content:"î’½"}.fa-circle-chevron-right::before{content:""}.fa-chevron-circle-right::before{content:""}.fa-at::before{content:"\@"}.fa-trash-can::before{content:"ï‹­"}.fa-trash-alt::before{content:"ï‹­"}.fa-text-height::before{content:""}.fa-user-xmark::before{content:""}.fa-user-times::before{content:""}.fa-stethoscope::before{content:""}.fa-message::before{content:""}.fa-comment-alt::before{content:""}.fa-info::before{content:"ï„©"}.fa-down-left-and-up-right-to-center::before{content:"ï¢"}.fa-compress-alt::before{content:"ï¢"}.fa-explosion::before{content:"î“©"}.fa-file-lines::before{content:"ï…œ"}.fa-file-alt::before{content:"ï…œ"}.fa-file-text::before{content:"ï…œ"}.fa-wave-square::before{content:"ï ¾"}.fa-ring::before{content:""}.fa-building-un::before{content:"î“™"}.fa-dice-three::before{content:""}.fa-calendar-days::before{content:"ï³"}.fa-calendar-alt::before{content:"ï³"}.fa-anchor-circle-check::before{content:"î’ª"}.fa-building-circle-arrow-right::before{content:"î“‘"}.fa-volleyball::before{content:"ï‘Ÿ"}.fa-volleyball-ball::before{content:"ï‘Ÿ"}.fa-arrows-up-to-line::before{content:"î“‚"}.fa-sort-down::before{content:"ïƒ"}.fa-sort-desc::before{content:"ïƒ"}.fa-circle-minus::before{content:"ï–"}.fa-minus-circle::before{content:"ï–"}.fa-door-open::before{content:""}.fa-right-from-bracket::before{content:""}.fa-sign-out-alt::before{content:""}.fa-atom::before{content:"ï—’"}.fa-soap::before{content:"î®"}.fa-icons::before{content:"ï¡­"}.fa-heart-music-camera-bolt::before{content:"ï¡­"}.fa-microphone-lines-slash::before{content:""}.fa-microphone-alt-slash::before{content:""}.fa-bridge-circle-check::before{content:""}.fa-pump-medical::before{content:"îª"}.fa-fingerprint::before{content:"ï•·"}.fa-hand-point-right::before{content:""}.fa-magnifying-glass-location::before{content:""}.fa-search-location::before{content:""}.fa-forward-step::before{content:"ï‘"}.fa-step-forward::before{content:"ï‘"}.fa-face-smile-beam::before{content:"ï–¸"}.fa-smile-beam::before{content:"ï–¸"}.fa-flag-checkered::before{content:"ï„ž"}.fa-football::before{content:"ï‘Ž"}.fa-football-ball::before{content:"ï‘Ž"}.fa-school-circle-exclamation::before{content:""}.fa-crop::before{content:"ï„¥"}.fa-angles-down::before{content:""}.fa-angle-double-down::before{content:""}.fa-users-rectangle::before{content:"î–”"}.fa-people-roof::before{content:"î”·"}.fa-people-line::before{content:"î”´"}.fa-beer-mug-empty::before{content:""}.fa-beer::before{content:""}.fa-diagram-predecessor::before{content:"î‘·"}.fa-arrow-up-long::before{content:"ï…¶"}.fa-long-arrow-up::before{content:"ï…¶"}.fa-fire-flame-simple::before{content:""}.fa-burn::before{content:""}.fa-person::before{content:""}.fa-male::before{content:""}.fa-laptop::before{content:""}.fa-file-csv::before{content:"ï›"}.fa-menorah::before{content:""}.fa-truck-plane::before{content:"î–"}.fa-record-vinyl::before{content:""}.fa-face-grin-stars::before{content:"ï–‡"}.fa-grin-stars::before{content:"ï–‡"}.fa-bong::before{content:"ï•œ"}.fa-spaghetti-monster-flying::before{content:"ï™»"}.fa-pastafarianism::before{content:"ï™»"}.fa-arrow-down-up-across-line::before{content:"î’¯"}.fa-spoon::before{content:"ï‹¥"}.fa-utensil-spoon::before{content:"ï‹¥"}.fa-jar-wheat::before{content:"î”—"}.fa-envelopes-bulk::before{content:"ï™´"}.fa-mail-bulk::before{content:"ï™´"}.fa-file-circle-exclamation::before{content:"î“«"}.fa-circle-h::before{content:""}.fa-hospital-symbol::before{content:""}.fa-pager::before{content:"ï •"}.fa-address-book::before{content:""}.fa-contact-book::before{content:""}.fa-strikethrough::before{content:""}.fa-k::before{content:"K"}.fa-landmark-flag::before{content:""}.fa-pencil::before{content:""}.fa-pencil-alt::before{content:""}.fa-backward::before{content:"ïŠ"}.fa-caret-right::before{content:""}.fa-comments::before{content:""}.fa-paste::before{content:""}.fa-file-clipboard::before{content:""}.fa-code-pull-request::before{content:""}.fa-clipboard-list::before{content:"ï‘­"}.fa-truck-ramp-box::before{content:"ï“ž"}.fa-truck-loading::before{content:"ï“ž"}.fa-user-check::before{content:""}.fa-vial-virus::before{content:"î–—"}.fa-sheet-plastic::before{content:""}.fa-blog::before{content:"ïž"}.fa-user-ninja::before{content:""}.fa-person-arrow-up-from-line::before{content:""}.fa-scroll-torah::before{content:"ïš "}.fa-torah::before{content:"ïš "}.fa-broom-ball::before{content:""}.fa-quidditch::before{content:""}.fa-quidditch-broom-ball::before{content:""}.fa-toggle-off::before{content:""}.fa-box-archive::before{content:""}.fa-archive::before{content:""}.fa-person-drowning::before{content:"î•…"}.fa-arrow-down-9-1::before{content:""}.fa-sort-numeric-desc::before{content:""}.fa-sort-numeric-down-alt::before{content:""}.fa-face-grin-tongue-squint::before{content:"ï–Š"}.fa-grin-tongue-squint::before{content:"ï–Š"}.fa-spray-can::before{content:"ï–½"}.fa-truck-monster::before{content:""}.fa-w::before{content:"W"}.fa-earth-africa::before{content:""}.fa-globe-africa::before{content:""}.fa-rainbow::before{content:"ï›"}.fa-circle-notch::before{content:""}.fa-tablet-screen-button::before{content:"ïº"}.fa-tablet-alt::before{content:"ïº"}.fa-paw::before{content:""}.fa-cloud::before{content:""}.fa-trowel-bricks::before{content:"î–Š"}.fa-face-flushed::before{content:""}.fa-flushed::before{content:""}.fa-hospital-user::before{content:"ï "}.fa-tent-arrow-left-right::before{content:"î•¿"}.fa-gavel::before{content:""}.fa-legal::before{content:""}.fa-binoculars::before{content:""}.fa-microphone-slash::before{content:""}.fa-box-tissue::before{content:"î›"}.fa-motorcycle::before{content:""}.fa-bell-concierge::before{content:"ï•¢"}.fa-concierge-bell::before{content:"ï•¢"}.fa-pen-ruler::before{content:"ï–®"}.fa-pencil-ruler::before{content:"ï–®"}.fa-people-arrows::before{content:"î¨"}.fa-people-arrows-left-right::before{content:"î¨"}.fa-mars-and-venus-burst::before{content:""}.fa-square-caret-right::before{content:"ï…’"}.fa-caret-square-right::before{content:"ï…’"}.fa-scissors::before{content:""}.fa-cut::before{content:""}.fa-sun-plant-wilt::before{content:""}.fa-toilets-portable::before{content:"î–„"}.fa-hockey-puck::before{content:"ï‘“"}.fa-table::before{content:""}.fa-magnifying-glass-arrow-right::before{content:""}.fa-tachograph-digital::before{content:""}.fa-digital-tachograph::before{content:""}.fa-users-slash::before{content:"î³"}.fa-clover::before{content:""}.fa-reply::before{content:"ï¥"}.fa-mail-reply::before{content:"ï¥"}.fa-star-and-crescent::before{content:"ïš™"}.fa-house-fire::before{content:""}.fa-square-minus::before{content:"ï…†"}.fa-minus-square::before{content:"ï…†"}.fa-helicopter::before{content:""}.fa-compass::before{content:"ï…Ž"}.fa-square-caret-down::before{content:"ï…"}.fa-caret-square-down::before{content:"ï…"}.fa-file-circle-question::before{content:""}.fa-laptop-code::before{content:"ï—¼"}.fa-swatchbook::before{content:"ï—ƒ"}.fa-prescription-bottle::before{content:"ï’…"}.fa-bars::before{content:""}.fa-navicon::before{content:""}.fa-people-group::before{content:""}.fa-hourglass-end::before{content:""}.fa-hourglass-3::before{content:""}.fa-heart-crack::before{content:"ïž©"}.fa-heart-broken::before{content:"ïž©"}.fa-square-up-right::before{content:"ï "}.fa-external-link-square-alt::before{content:"ï "}.fa-face-kiss-beam::before{content:"ï–—"}.fa-kiss-beam::before{content:"ï–—"}.fa-film::before{content:""}.fa-ruler-horizontal::before{content:""}.fa-people-robbery::before{content:""}.fa-lightbulb::before{content:""}.fa-caret-left::before{content:""}.fa-circle-exclamation::before{content:"ïª"}.fa-exclamation-circle::before{content:"ïª"}.fa-school-circle-xmark::before{content:"î•­"}.fa-arrow-right-from-bracket::before{content:"ï‚‹"}.fa-sign-out::before{content:"ï‚‹"}.fa-circle-chevron-down::before{content:""}.fa-chevron-circle-down::before{content:""}.fa-unlock-keyhole::before{content:""}.fa-unlock-alt::before{content:""}.fa-cloud-showers-heavy::before{content:"ï€"}.fa-headphones-simple::before{content:"ï–"}.fa-headphones-alt::before{content:"ï–"}.fa-sitemap::before{content:""}.fa-circle-dollar-to-slot::before{content:"ï’¹"}.fa-donate::before{content:"ï’¹"}.fa-memory::before{content:""}.fa-road-spikes::before{content:""}.fa-fire-burner::before{content:""}.fa-flag::before{content:""}.fa-hanukiah::before{content:""}.fa-feather::before{content:"ï”­"}.fa-volume-low::before{content:""}.fa-volume-down::before{content:""}.fa-comment-slash::before{content:"ï’³"}.fa-cloud-sun-rain::before{content:"ïƒ"}.fa-compress::before{content:"ï¦"}.fa-wheat-awn::before{content:"î‹"}.fa-wheat-alt::before{content:"î‹"}.fa-ankh::before{content:""}.fa-hands-holding-child::before{content:""}.fa-asterisk::before{content:"\*"}.fa-square-check::before{content:"ï…Š"}.fa-check-square::before{content:"ï…Š"}.fa-peseta-sign::before{content:""}.fa-heading::before{content:""}.fa-header::before{content:""}.fa-ghost::before{content:""}.fa-list::before{content:""}.fa-list-squares::before{content:""}.fa-square-phone-flip::before{content:"ï¡»"}.fa-phone-square-alt::before{content:"ï¡»"}.fa-cart-plus::before{content:""}.fa-gamepad::before{content:"ï„›"}.fa-circle-dot::before{content:""}.fa-dot-circle::before{content:""}.fa-face-dizzy::before{content:""}.fa-dizzy::before{content:""}.fa-egg::before{content:""}.fa-house-medical-circle-xmark::before{content:""}.fa-campground::before{content:"ïš»"}.fa-folder-plus::before{content:""}.fa-futbol::before{content:""}.fa-futbol-ball::before{content:""}.fa-soccer-ball::before{content:""}.fa-paintbrush::before{content:""}.fa-paint-brush::before{content:""}.fa-lock::before{content:""}.fa-gas-pump::before{content:""}.fa-hot-tub-person::before{content:"ï–“"}.fa-hot-tub::before{content:"ï–“"}.fa-map-location::before{content:"ï–Ÿ"}.fa-map-marked::before{content:"ï–Ÿ"}.fa-house-flood-water::before{content:""}.fa-tree::before{content:""}.fa-bridge-lock::before{content:"î“Œ"}.fa-sack-dollar::before{content:"ï "}.fa-pen-to-square::before{content:"ï„"}.fa-edit::before{content:"ï„"}.fa-car-side::before{content:"ï—¤"}.fa-share-nodes::before{content:""}.fa-share-alt::before{content:""}.fa-heart-circle-minus::before{content:"î“¿"}.fa-hourglass-half::before{content:""}.fa-hourglass-2::before{content:""}.fa-microscope::before{content:"ï˜"}.fa-sink::before{content:"î­"}.fa-bag-shopping::before{content:"ïŠ"}.fa-shopping-bag::before{content:"ïŠ"}.fa-arrow-down-z-a::before{content:"ï¢"}.fa-sort-alpha-desc::before{content:"ï¢"}.fa-sort-alpha-down-alt::before{content:"ï¢"}.fa-mitten::before{content:"ïžµ"}.fa-person-rays::before{content:"î•"}.fa-users::before{content:""}.fa-eye-slash::before{content:"ï°"}.fa-flask-vial::before{content:""}.fa-hand::before{content:""}.fa-hand-paper::before{content:""}.fa-om::before{content:""}.fa-worm::before{content:"î–™"}.fa-house-circle-xmark::before{content:""}.fa-plug::before{content:""}.fa-chevron-up::before{content:"ï·"}.fa-hand-spock::before{content:""}.fa-stopwatch::before{content:""}.fa-face-kiss::before{content:"ï––"}.fa-kiss::before{content:"ï––"}.fa-bridge-circle-xmark::before{content:"î“‹"}.fa-face-grin-tongue::before{content:"ï–‰"}.fa-grin-tongue::before{content:"ï–‰"}.fa-chess-bishop::before{content:"ïº"}.fa-face-grin-wink::before{content:"ï–Œ"}.fa-grin-wink::before{content:"ï–Œ"}.fa-ear-deaf::before{content:""}.fa-deaf::before{content:""}.fa-deafness::before{content:""}.fa-hard-of-hearing::before{content:""}.fa-road-circle-check::before{content:""}.fa-dice-five::before{content:""}.fa-square-rss::before{content:"ï…ƒ"}.fa-rss-square::before{content:"ï…ƒ"}.fa-land-mine-on::before{content:"î”›"}.fa-i-cursor::before{content:""}.fa-stamp::before{content:"ï–¿"}.fa-stairs::before{content:""}.fa-i::before{content:"I"}.fa-hryvnia-sign::before{content:""}.fa-hryvnia::before{content:""}.fa-pills::before{content:"ï’„"}.fa-face-grin-wide::before{content:"ï–"}.fa-grin-alt::before{content:"ï–"}.fa-tooth::before{content:"ï—‰"}.fa-v::before{content:"V"}.fa-bangladeshi-taka-sign::before{content:""}.fa-bicycle::before{content:""}.fa-staff-snake::before{content:""}.fa-rod-asclepius::before{content:""}.fa-rod-snake::before{content:""}.fa-staff-aesculapius::before{content:""}.fa-head-side-cough-slash::before{content:"î¢"}.fa-truck-medical::before{content:""}.fa-ambulance::before{content:""}.fa-wheat-awn-circle-exclamation::before{content:"î–˜"}.fa-snowman::before{content:"ïŸ"}.fa-mortar-pestle::before{content:"ï–§"}.fa-road-barrier::before{content:"î•¢"}.fa-school::before{content:""}.fa-igloo::before{content:"ïž®"}.fa-joint::before{content:"ï–•"}.fa-angle-right::before{content:"ï„…"}.fa-horse::before{content:"ï›°"}.fa-q::before{content:"Q"}.fa-g::before{content:"G"}.fa-notes-medical::before{content:"ï’"}.fa-temperature-half::before{content:""}.fa-temperature-2::before{content:""}.fa-thermometer-2::before{content:""}.fa-thermometer-half::before{content:""}.fa-dong-sign::before{content:"î…©"}.fa-capsules::before{content:"ï‘«"}.fa-poo-storm::before{content:"ïš"}.fa-poo-bolt::before{content:"ïš"}.fa-face-frown-open::before{content:""}.fa-frown-open::before{content:""}.fa-hand-point-up::before{content:""}.fa-money-bill::before{content:""}.fa-bookmark::before{content:""}.fa-align-justify::before{content:""}.fa-umbrella-beach::before{content:"ï—Š"}.fa-helmet-un::before{content:""}.fa-bullseye::before{content:"ï…€"}.fa-bacon::before{content:""}.fa-hand-point-down::before{content:""}.fa-arrow-up-from-bracket::before{content:"î‚š"}.fa-folder::before{content:"ï»"}.fa-folder-blank::before{content:"ï»"}.fa-file-waveform::before{content:""}.fa-file-medical-alt::before{content:""}.fa-radiation::before{content:"ïž¹"}.fa-chart-simple::before{content:""}.fa-mars-stroke::before{content:""}.fa-vial::before{content:"ï’’"}.fa-gauge::before{content:""}.fa-dashboard::before{content:""}.fa-gauge-med::before{content:""}.fa-tachometer-alt-average::before{content:""}.fa-wand-magic-sparkles::before{content:"î‹Š"}.fa-magic-wand-sparkles::before{content:"î‹Š"}.fa-e::before{content:"E"}.fa-pen-clip::before{content:""}.fa-pen-alt::before{content:""}.fa-bridge-circle-exclamation::before{content:"î“Š"}.fa-user::before{content:""}.fa-school-circle-check::before{content:"î•«"}.fa-dumpster::before{content:"ïž“"}.fa-van-shuttle::before{content:"ï–¶"}.fa-shuttle-van::before{content:"ï–¶"}.fa-building-user::before{content:"î“š"}.fa-square-caret-left::before{content:""}.fa-caret-square-left::before{content:""}.fa-highlighter::before{content:"ï–‘"}.fa-key::before{content:"ï‚„"}.fa-bullhorn::before{content:"ï‚¡"}.fa-globe::before{content:""}.fa-synagogue::before{content:"ïš›"}.fa-person-half-dress::before{content:""}.fa-road-bridge::before{content:"î•£"}.fa-location-arrow::before{content:""}.fa-c::before{content:"C"}.fa-tablet-button::before{content:"ï„Š"}.fa-building-lock::before{content:"î“–"}.fa-pizza-slice::before{content:"ï ˜"}.fa-money-bill-wave::before{content:""}.fa-chart-area::before{content:""}.fa-area-chart::before{content:""}.fa-house-flag::before{content:"î”"}.fa-person-circle-minus::before{content:"î•€"}.fa-ban::before{content:"ïž"}.fa-cancel::before{content:"ïž"}.fa-camera-rotate::before{content:""}.fa-spray-can-sparkles::before{content:"ï—"}.fa-air-freshener::before{content:"ï—"}.fa-star::before{content:""}.fa-repeat::before{content:"ï£"}.fa-cross::before{content:"ï™”"}.fa-box::before{content:""}.fa-venus-mars::before{content:""}.fa-arrow-pointer::before{content:""}.fa-mouse-pointer::before{content:""}.fa-maximize::before{content:""}.fa-expand-arrows-alt::before{content:""}.fa-charging-station::before{content:"ï—§"}.fa-shapes::before{content:""}.fa-triangle-circle-square::before{content:""}.fa-shuffle::before{content:"ï´"}.fa-random::before{content:"ï´"}.fa-person-running::before{content:""}.fa-running::before{content:""}.fa-mobile-retro::before{content:""}.fa-grip-lines-vertical::before{content:""}.fa-spider::before{content:""}.fa-hands-bound::before{content:""}.fa-file-invoice-dollar::before{content:""}.fa-plane-circle-exclamation::before{content:"î•–"}.fa-x-ray::before{content:"ï’—"}.fa-spell-check::before{content:""}.fa-slash::before{content:""}.fa-computer-mouse::before{content:""}.fa-mouse::before{content:""}.fa-arrow-right-to-bracket::before{content:"ï‚"}.fa-sign-in::before{content:"ï‚"}.fa-shop-slash::before{content:"î°"}.fa-store-alt-slash::before{content:"î°"}.fa-server::before{content:""}.fa-virus-covid-slash::before{content:"î’©"}.fa-shop-lock::before{content:"î’¥"}.fa-hourglass-start::before{content:""}.fa-hourglass-1::before{content:""}.fa-blender-phone::before{content:""}.fa-building-wheat::before{content:"î“›"}.fa-person-breastfeeding::before{content:""}.fa-right-to-bracket::before{content:""}.fa-sign-in-alt::before{content:""}.fa-venus::before{content:""}.fa-passport::before{content:"ï–«"}.fa-thumbtack-slash::before{content:"îš"}.fa-thumb-tack-slash::before{content:"îš"}.fa-heart-pulse::before{content:""}.fa-heartbeat::before{content:""}.fa-people-carry-box::before{content:"ï“Ž"}.fa-people-carry::before{content:"ï“Ž"}.fa-temperature-high::before{content:"ï©"}.fa-microchip::before{content:"ï‹›"}.fa-crown::before{content:""}.fa-weight-hanging::before{content:"ï—"}.fa-xmarks-lines::before{content:"î–š"}.fa-file-prescription::before{content:""}.fa-weight-scale::before{content:"ï’–"}.fa-weight::before{content:"ï’–"}.fa-user-group::before{content:""}.fa-user-friends::before{content:""}.fa-arrow-up-a-z::before{content:"ï…ž"}.fa-sort-alpha-up::before{content:"ï…ž"}.fa-chess-knight::before{content:"ï‘"}.fa-face-laugh-squint::before{content:"ï–›"}.fa-laugh-squint::before{content:"ï–›"}.fa-wheelchair::before{content:""}.fa-circle-arrow-up::before{content:""}.fa-arrow-circle-up::before{content:""}.fa-toggle-on::before{content:""}.fa-person-walking::before{content:"ï•”"}.fa-walking::before{content:"ï•”"}.fa-l::before{content:"L"}.fa-fire::before{content:"ï­"}.fa-bed-pulse::before{content:"ï’‡"}.fa-procedures::before{content:"ï’‡"}.fa-shuttle-space::before{content:""}.fa-space-shuttle::before{content:""}.fa-face-laugh::before{content:"ï–™"}.fa-laugh::before{content:"ï–™"}.fa-folder-open::before{content:"ï¼"}.fa-heart-circle-plus::before{content:""}.fa-code-fork::before{content:"î„»"}.fa-city::before{content:"ï™"}.fa-microphone-lines::before{content:"ï‰"}.fa-microphone-alt::before{content:"ï‰"}.fa-pepper-hot::before{content:"ï –"}.fa-unlock::before{content:"ï‚œ"}.fa-colon-sign::before{content:"î…€"}.fa-headset::before{content:"ï–"}.fa-store-slash::before{content:"î±"}.fa-road-circle-xmark::before{content:""}.fa-user-minus::before{content:""}.fa-mars-stroke-up::before{content:""}.fa-mars-stroke-v::before{content:""}.fa-champagne-glasses::before{content:""}.fa-glass-cheers::before{content:""}.fa-clipboard::before{content:""}.fa-house-circle-exclamation::before{content:""}.fa-file-arrow-up::before{content:"ï•´"}.fa-file-upload::before{content:"ï•´"}.fa-wifi::before{content:""}.fa-wifi-3::before{content:""}.fa-wifi-strong::before{content:""}.fa-bath::before{content:"ï‹"}.fa-bathtub::before{content:"ï‹"}.fa-underline::before{content:"ïƒ"}.fa-user-pen::before{content:"ï“¿"}.fa-user-edit::before{content:"ï“¿"}.fa-signature::before{content:"ï–·"}.fa-stroopwafel::before{content:"ï•‘"}.fa-bold::before{content:""}.fa-anchor-lock::before{content:"î’­"}.fa-building-ngo::before{content:"î“—"}.fa-manat-sign::before{content:""}.fa-not-equal::before{content:""}.fa-border-top-left::before{content:"ï¡“"}.fa-border-style::before{content:"ï¡“"}.fa-map-location-dot::before{content:"ï– "}.fa-map-marked-alt::before{content:"ï– "}.fa-jedi::before{content:""}.fa-square-poll-vertical::before{content:"ïš"}.fa-poll::before{content:"ïš"}.fa-mug-hot::before{content:""}.fa-car-battery::before{content:"ï—Ÿ"}.fa-battery-car::before{content:"ï—Ÿ"}.fa-gift::before{content:"ï«"}.fa-dice-two::before{content:""}.fa-chess-queen::before{content:"ï‘…"}.fa-glasses::before{content:"ï”°"}.fa-chess-board::before{content:"ï¼"}.fa-building-circle-check::before{content:"î“’"}.fa-person-chalkboard::before{content:""}.fa-mars-stroke-right::before{content:""}.fa-mars-stroke-h::before{content:""}.fa-hand-back-fist::before{content:""}.fa-hand-rock::before{content:""}.fa-square-caret-up::before{content:"ï…‘"}.fa-caret-square-up::before{content:"ï…‘"}.fa-cloud-showers-water::before{content:""}.fa-chart-bar::before{content:"ï‚€"}.fa-bar-chart::before{content:"ï‚€"}.fa-hands-bubbles::before{content:"îž"}.fa-hands-wash::before{content:"îž"}.fa-less-than-equal::before{content:"ï”·"}.fa-train::before{content:""}.fa-eye-low-vision::before{content:""}.fa-low-vision::before{content:""}.fa-crow::before{content:"ï” "}.fa-sailboat::before{content:"î‘…"}.fa-window-restore::before{content:"ï‹’"}.fa-square-plus::before{content:""}.fa-plus-square::before{content:""}.fa-torii-gate::before{content:"ïš¡"}.fa-frog::before{content:"ï”®"}.fa-bucket::before{content:"î“"}.fa-image::before{content:""}.fa-microphone::before{content:"ï„°"}.fa-cow::before{content:""}.fa-caret-up::before{content:""}.fa-screwdriver::before{content:"ï•Š"}.fa-folder-closed::before{content:""}.fa-house-tsunami::before{content:""}.fa-square-nfi::before{content:""}.fa-arrow-up-from-ground-water::before{content:"î’µ"}.fa-martini-glass::before{content:"ï•»"}.fa-glass-martini-alt::before{content:"ï•»"}.fa-rotate-left::before{content:""}.fa-rotate-back::before{content:""}.fa-rotate-backward::before{content:""}.fa-undo-alt::before{content:""}.fa-table-columns::before{content:""}.fa-columns::before{content:""}.fa-lemon::before{content:"ï‚”"}.fa-head-side-mask::before{content:"î£"}.fa-handshake::before{content:""}.fa-gem::before{content:""}.fa-dolly::before{content:""}.fa-dolly-box::before{content:""}.fa-smoking::before{content:"ï’"}.fa-minimize::before{content:""}.fa-compress-arrows-alt::before{content:""}.fa-monument::before{content:"ï–¦"}.fa-snowplow::before{content:""}.fa-angles-right::before{content:"ï„"}.fa-angle-double-right::before{content:"ï„"}.fa-cannabis::before{content:"ï•Ÿ"}.fa-circle-play::before{content:"ï…„"}.fa-play-circle::before{content:"ï…„"}.fa-tablets::before{content:"ï’"}.fa-ethernet::before{content:"ïž–"}.fa-euro-sign::before{content:"ï…“"}.fa-eur::before{content:"ï…“"}.fa-euro::before{content:"ï…“"}.fa-chair::before{content:""}.fa-circle-check::before{content:"ï˜"}.fa-check-circle::before{content:"ï˜"}.fa-circle-stop::before{content:"ïŠ"}.fa-stop-circle::before{content:"ïŠ"}.fa-compass-drafting::before{content:""}.fa-drafting-compass::before{content:""}.fa-plate-wheat::before{content:"î•š"}.fa-icicles::before{content:"ïž­"}.fa-person-shelter::before{content:"î•"}.fa-neuter::before{content:""}.fa-id-badge::before{content:"ï‹"}.fa-marker::before{content:"ï–¡"}.fa-face-laugh-beam::before{content:"ï–š"}.fa-laugh-beam::before{content:"ï–š"}.fa-helicopter-symbol::before{content:""}.fa-universal-access::before{content:""}.fa-circle-chevron-up::before{content:""}.fa-chevron-circle-up::before{content:""}.fa-lari-sign::before{content:""}.fa-volcano::before{content:"ï°"}.fa-person-walking-dashed-line-arrow-right::before{content:"î•“"}.fa-sterling-sign::before{content:"ï…”"}.fa-gbp::before{content:"ï…”"}.fa-pound-sign::before{content:"ï…”"}.fa-viruses::before{content:"î¶"}.fa-square-person-confined::before{content:"î•·"}.fa-user-tie::before{content:""}.fa-arrow-down-long::before{content:"ï…µ"}.fa-long-arrow-down::before{content:"ï…µ"}.fa-tent-arrow-down-to-line::before{content:""}.fa-certificate::before{content:"ï‚£"}.fa-reply-all::before{content:"ï„¢"}.fa-mail-reply-all::before{content:"ï„¢"}.fa-suitcase::before{content:""}.fa-person-skating::before{content:""}.fa-skating::before{content:""}.fa-filter-circle-dollar::before{content:""}.fa-funnel-dollar::before{content:""}.fa-camera-retro::before{content:""}.fa-circle-arrow-down::before{content:"ï‚«"}.fa-arrow-circle-down::before{content:"ï‚«"}.fa-file-import::before{content:""}.fa-arrow-right-to-file::before{content:""}.fa-square-arrow-up-right::before{content:"ï…Œ"}.fa-external-link-square::before{content:"ï…Œ"}.fa-box-open::before{content:"ï’ž"}.fa-scroll::before{content:""}.fa-spa::before{content:"ï–»"}.fa-location-pin-lock::before{content:""}.fa-pause::before{content:"ïŒ"}.fa-hill-avalanche::before{content:""}.fa-temperature-empty::before{content:"ï‹‹"}.fa-temperature-0::before{content:"ï‹‹"}.fa-thermometer-0::before{content:"ï‹‹"}.fa-thermometer-empty::before{content:"ï‹‹"}.fa-bomb::before{content:""}.fa-registered::before{content:"ï‰"}.fa-address-card::before{content:""}.fa-contact-card::before{content:""}.fa-vcard::before{content:""}.fa-scale-unbalanced-flip::before{content:"ï”–"}.fa-balance-scale-right::before{content:"ï”–"}.fa-subscript::before{content:""}.fa-diamond-turn-right::before{content:"ï—«"}.fa-directions::before{content:"ï—«"}.fa-burst::before{content:"î“œ"}.fa-house-laptop::before{content:"î¦"}.fa-laptop-house::before{content:"î¦"}.fa-face-tired::before{content:"ï—ˆ"}.fa-tired::before{content:"ï—ˆ"}.fa-money-bills::before{content:""}.fa-smog::before{content:"ïŸ"}.fa-crutch::before{content:""}.fa-cloud-arrow-up::before{content:""}.fa-cloud-upload::before{content:""}.fa-cloud-upload-alt::before{content:""}.fa-palette::before{content:""}.fa-arrows-turn-right::before{content:"î“€"}.fa-vest::before{content:"î‚…"}.fa-ferry::before{content:""}.fa-arrows-down-to-people::before{content:"î’¹"}.fa-seedling::before{content:""}.fa-sprout::before{content:""}.fa-left-right::before{content:""}.fa-arrows-alt-h::before{content:""}.fa-boxes-packing::before{content:""}.fa-circle-arrow-left::before{content:""}.fa-arrow-circle-left::before{content:""}.fa-group-arrows-rotate::before{content:""}.fa-bowl-food::before{content:""}.fa-candy-cane::before{content:""}.fa-arrow-down-wide-short::before{content:"ï… "}.fa-sort-amount-asc::before{content:"ï… "}.fa-sort-amount-down::before{content:"ï… "}.fa-cloud-bolt::before{content:"ï¬"}.fa-thunderstorm::before{content:"ï¬"}.fa-text-slash::before{content:""}.fa-remove-format::before{content:""}.fa-face-smile-wink::before{content:"ï“š"}.fa-smile-wink::before{content:"ï“š"}.fa-file-word::before{content:""}.fa-file-powerpoint::before{content:""}.fa-arrows-left-right::before{content:"ï¾"}.fa-arrows-h::before{content:"ï¾"}.fa-house-lock::before{content:"î”"}.fa-cloud-arrow-down::before{content:""}.fa-cloud-download::before{content:""}.fa-cloud-download-alt::before{content:""}.fa-children::before{content:"î“¡"}.fa-chalkboard::before{content:"ï”›"}.fa-blackboard::before{content:"ï”›"}.fa-user-large-slash::before{content:""}.fa-user-alt-slash::before{content:""}.fa-envelope-open::before{content:""}.fa-handshake-simple-slash::before{content:"îŸ"}.fa-handshake-alt-slash::before{content:"îŸ"}.fa-mattress-pillow::before{content:""}.fa-guarani-sign::before{content:""}.fa-arrows-rotate::before{content:""}.fa-refresh::before{content:""}.fa-sync::before{content:""}.fa-fire-extinguisher::before{content:"ï„´"}.fa-cruzeiro-sign::before{content:"î…’"}.fa-greater-than-equal::before{content:""}.fa-shield-halved::before{content:"ï­"}.fa-shield-alt::before{content:"ï­"}.fa-book-atlas::before{content:""}.fa-atlas::before{content:""}.fa-virus::before{content:"î´"}.fa-envelope-circle-check::before{content:""}.fa-layer-group::before{content:"ï—½"}.fa-arrows-to-dot::before{content:"î’¾"}.fa-archway::before{content:"ï•—"}.fa-heart-circle-check::before{content:""}.fa-house-chimney-crack::before{content:"ï›±"}.fa-house-damage::before{content:"ï›±"}.fa-file-zipper::before{content:""}.fa-file-archive::before{content:""}.fa-square::before{content:""}.fa-martini-glass-empty::before{content:""}.fa-glass-martini::before{content:""}.fa-couch::before{content:"ï’¸"}.fa-cedi-sign::before{content:""}.fa-italic::before{content:""}.fa-table-cells-column-lock::before{content:""}.fa-church::before{content:"ï”"}.fa-comments-dollar::before{content:""}.fa-democrat::before{content:"ï‡"}.fa-z::before{content:"Z"}.fa-person-skiing::before{content:""}.fa-skiing::before{content:""}.fa-road-lock::before{content:""}.fa-a::before{content:"A"}.fa-temperature-arrow-down::before{content:""}.fa-temperature-down::before{content:""}.fa-feather-pointed::before{content:"ï•«"}.fa-feather-alt::before{content:"ï•«"}.fa-p::before{content:"P"}.fa-snowflake::before{content:"ï‹œ"}.fa-newspaper::before{content:""}.fa-rectangle-ad::before{content:"ï™"}.fa-ad::before{content:"ï™"}.fa-circle-arrow-right::before{content:"ï‚©"}.fa-arrow-circle-right::before{content:"ï‚©"}.fa-filter-circle-xmark::before{content:"î…»"}.fa-locust::before{content:"î” "}.fa-sort::before{content:""}.fa-unsorted::before{content:""}.fa-list-ol::before{content:""}.fa-list-1-2::before{content:""}.fa-list-numeric::before{content:""}.fa-person-dress-burst::before{content:"î•„"}.fa-money-check-dollar::before{content:""}.fa-money-check-alt::before{content:""}.fa-vector-square::before{content:"ï—‹"}.fa-bread-slice::before{content:""}.fa-language::before{content:""}.fa-face-kiss-wink-heart::before{content:"ï–˜"}.fa-kiss-wink-heart::before{content:"ï–˜"}.fa-filter::before{content:"ï‚°"}.fa-question::before{content:"\?"}.fa-file-signature::before{content:""}.fa-up-down-left-right::before{content:""}.fa-arrows-alt::before{content:""}.fa-house-chimney-user::before{content:"î¥"}.fa-hand-holding-heart::before{content:"ï’¾"}.fa-puzzle-piece::before{content:"ï„®"}.fa-money-check::before{content:""}.fa-star-half-stroke::before{content:"ï—€"}.fa-star-half-alt::before{content:"ï—€"}.fa-code::before{content:"ï„¡"}.fa-whiskey-glass::before{content:"ïž "}.fa-glass-whiskey::before{content:"ïž "}.fa-building-circle-exclamation::before{content:"î““"}.fa-magnifying-glass-chart::before{content:""}.fa-arrow-up-right-from-square::before{content:"ï‚Ž"}.fa-external-link::before{content:"ï‚Ž"}.fa-cubes-stacked::before{content:""}.fa-won-sign::before{content:"ï…™"}.fa-krw::before{content:"ï…™"}.fa-won::before{content:"ï…™"}.fa-virus-covid::before{content:"î’¨"}.fa-austral-sign::before{content:"î‚©"}.fa-f::before{content:"F"}.fa-leaf::before{content:"ï¬"}.fa-road::before{content:""}.fa-taxi::before{content:""}.fa-cab::before{content:""}.fa-person-circle-plus::before{content:"î•"}.fa-chart-pie::before{content:""}.fa-pie-chart::before{content:""}.fa-bolt-lightning::before{content:"î‚·"}.fa-sack-xmark::before{content:""}.fa-file-excel::before{content:""}.fa-file-contract::before{content:""}.fa-fish-fins::before{content:""}.fa-building-flag::before{content:"î“•"}.fa-face-grin-beam::before{content:"ï–‚"}.fa-grin-beam::before{content:"ï–‚"}.fa-object-ungroup::before{content:""}.fa-poop::before{content:""}.fa-location-pin::before{content:"ï"}.fa-map-marker::before{content:"ï"}.fa-kaaba::before{content:""}.fa-toilet-paper::before{content:""}.fa-helmet-safety::before{content:"ï ‡"}.fa-hard-hat::before{content:"ï ‡"}.fa-hat-hard::before{content:"ï ‡"}.fa-eject::before{content:"ï’"}.fa-circle-right::before{content:"ïš"}.fa-arrow-alt-circle-right::before{content:"ïš"}.fa-plane-circle-check::before{content:"î••"}.fa-face-rolling-eyes::before{content:"ï–¥"}.fa-meh-rolling-eyes::before{content:"ï–¥"}.fa-object-group::before{content:""}.fa-chart-line::before{content:"ïˆ"}.fa-line-chart::before{content:"ïˆ"}.fa-mask-ventilator::before{content:""}.fa-arrow-right::before{content:"ï¡"}.fa-signs-post::before{content:""}.fa-map-signs::before{content:""}.fa-cash-register::before{content:""}.fa-person-circle-question::before{content:"î•‚"}.fa-h::before{content:"H"}.fa-tarp::before{content:"î•»"}.fa-screwdriver-wrench::before{content:""}.fa-tools::before{content:""}.fa-arrows-to-eye::before{content:"î’¿"}.fa-plug-circle-bolt::before{content:"î•›"}.fa-heart::before{content:""}.fa-mars-and-venus::before{content:""}.fa-house-user::before{content:""}.fa-home-user::before{content:""}.fa-dumpster-fire::before{content:"ïž”"}.fa-house-crack::before{content:""}.fa-martini-glass-citrus::before{content:"ï•¡"}.fa-cocktail::before{content:"ï•¡"}.fa-face-surprise::before{content:"ï—‚"}.fa-surprise::before{content:"ï—‚"}.fa-bottle-water::before{content:"î“…"}.fa-circle-pause::before{content:""}.fa-pause-circle::before{content:""}.fa-toilet-paper-slash::before{content:"î²"}.fa-apple-whole::before{content:"ï—‘"}.fa-apple-alt::before{content:"ï—‘"}.fa-kitchen-set::before{content:""}.fa-r::before{content:"R"}.fa-temperature-quarter::before{content:"ï‹Š"}.fa-temperature-1::before{content:"ï‹Š"}.fa-thermometer-1::before{content:"ï‹Š"}.fa-thermometer-quarter::before{content:"ï‹Š"}.fa-cube::before{content:""}.fa-bitcoin-sign::before{content:"î‚´"}.fa-shield-dog::before{content:""}.fa-solar-panel::before{content:"ï–º"}.fa-lock-open::before{content:"ï"}.fa-elevator::before{content:"î…­"}.fa-money-bill-transfer::before{content:""}.fa-money-bill-trend-up::before{content:""}.fa-house-flood-water-circle-arrow-right::before{content:"î”"}.fa-square-poll-horizontal::before{content:"ïš‚"}.fa-poll-h::before{content:"ïš‚"}.fa-circle::before{content:"ï„‘"}.fa-backward-fast::before{content:"ï‰"}.fa-fast-backward::before{content:"ï‰"}.fa-recycle::before{content:""}.fa-user-astronaut::before{content:"ï“»"}.fa-plane-slash::before{content:"î©"}.fa-trademark::before{content:""}.fa-basketball::before{content:"ï´"}.fa-basketball-ball::before{content:"ï´"}.fa-satellite-dish::before{content:""}.fa-circle-up::before{content:"ï›"}.fa-arrow-alt-circle-up::before{content:"ï›"}.fa-mobile-screen-button::before{content:"ï"}.fa-mobile-alt::before{content:"ï"}.fa-volume-high::before{content:""}.fa-volume-up::before{content:""}.fa-users-rays::before{content:"î–“"}.fa-wallet::before{content:"ï••"}.fa-clipboard-check::before{content:""}.fa-file-audio::before{content:""}.fa-burger::before{content:"ï …"}.fa-hamburger::before{content:"ï …"}.fa-wrench::before{content:"ï‚­"}.fa-bugs::before{content:"î“"}.fa-rupee-sign::before{content:"ï…–"}.fa-rupee::before{content:"ï…–"}.fa-file-image::before{content:""}.fa-circle-question::before{content:"ï™"}.fa-question-circle::before{content:"ï™"}.fa-plane-departure::before{content:"ï–°"}.fa-handshake-slash::before{content:"î "}.fa-book-bookmark::before{content:"î‚»"}.fa-code-branch::before{content:""}.fa-hat-cowboy::before{content:""}.fa-bridge::before{content:""}.fa-phone-flip::before{content:""}.fa-phone-alt::before{content:""}.fa-truck-front::before{content:""}.fa-cat::before{content:"ïš¾"}.fa-anchor-circle-exclamation::before{content:"î’«"}.fa-truck-field::before{content:"î–"}.fa-route::before{content:"ï“—"}.fa-clipboard-question::before{content:"î“£"}.fa-panorama::before{content:""}.fa-comment-medical::before{content:""}.fa-teeth-open::before{content:""}.fa-file-circle-minus::before{content:"î“­"}.fa-tags::before{content:""}.fa-wine-glass::before{content:"ï“£"}.fa-forward-fast::before{content:"ï"}.fa-fast-forward::before{content:"ï"}.fa-face-meh-blank::before{content:"ï–¤"}.fa-meh-blank::before{content:"ï–¤"}.fa-square-parking::before{content:"ï•€"}.fa-parking::before{content:"ï•€"}.fa-house-signal::before{content:""}.fa-bars-progress::before{content:"ï ¨"}.fa-tasks-alt::before{content:"ï ¨"}.fa-faucet-drip::before{content:""}.fa-cart-flatbed::before{content:"ï‘´"}.fa-dolly-flatbed::before{content:"ï‘´"}.fa-ban-smoking::before{content:"ï•"}.fa-smoking-ban::before{content:"ï•"}.fa-terminal::before{content:"ï„ "}.fa-mobile-button::before{content:"ï„‹"}.fa-house-medical-flag::before{content:"î””"}.fa-basket-shopping::before{content:""}.fa-shopping-basket::before{content:""}.fa-tape::before{content:"ï“›"}.fa-bus-simple::before{content:"ï•ž"}.fa-bus-alt::before{content:"ï•ž"}.fa-eye::before{content:"ï®"}.fa-face-sad-cry::before{content:"ï–³"}.fa-sad-cry::before{content:"ï–³"}.fa-audio-description::before{content:""}.fa-person-military-to-person::before{content:"î•Œ"}.fa-file-shield::before{content:"î“°"}.fa-user-slash::before{content:""}.fa-pen::before{content:""}.fa-tower-observation::before{content:"î–†"}.fa-file-code::before{content:""}.fa-signal::before{content:""}.fa-signal-5::before{content:""}.fa-signal-perfect::before{content:""}.fa-bus::before{content:""}.fa-heart-circle-xmark::before{content:"î”"}.fa-house-chimney::before{content:""}.fa-home-lg::before{content:""}.fa-window-maximize::before{content:"ï‹"}.fa-face-frown::before{content:"ï„™"}.fa-frown::before{content:"ï„™"}.fa-prescription::before{content:"ï–±"}.fa-shop::before{content:"ï•"}.fa-store-alt::before{content:"ï•"}.fa-floppy-disk::before{content:""}.fa-save::before{content:""}.fa-vihara::before{content:""}.fa-scale-unbalanced::before{content:""}.fa-balance-scale-left::before{content:""}.fa-sort-up::before{content:""}.fa-sort-asc::before{content:""}.fa-comment-dots::before{content:"ï’­"}.fa-commenting::before{content:"ï’­"}.fa-plant-wilt::before{content:"î–ª"}.fa-diamond::before{content:""}.fa-face-grin-squint::before{content:"ï–…"}.fa-grin-squint::before{content:"ï–…"}.fa-hand-holding-dollar::before{content:"ï“€"}.fa-hand-holding-usd::before{content:"ï“€"}.fa-bacterium::before{content:"îš"}.fa-hand-pointer::before{content:""}.fa-drum-steelpan::before{content:""}.fa-hand-scissors::before{content:""}.fa-hands-praying::before{content:"ïš„"}.fa-praying-hands::before{content:"ïš„"}.fa-arrow-rotate-right::before{content:""}.fa-arrow-right-rotate::before{content:""}.fa-arrow-rotate-forward::before{content:""}.fa-redo::before{content:""}.fa-biohazard::before{content:""}.fa-location-crosshairs::before{content:"ï˜"}.fa-location::before{content:"ï˜"}.fa-mars-double::before{content:""}.fa-child-dress::before{content:"î–œ"}.fa-users-between-lines::before{content:"î–‘"}.fa-lungs-virus::before{content:"î§"}.fa-face-grin-tears::before{content:"ï–ˆ"}.fa-grin-tears::before{content:"ï–ˆ"}.fa-phone::before{content:"ï‚•"}.fa-calendar-xmark::before{content:""}.fa-calendar-times::before{content:""}.fa-child-reaching::before{content:"î–"}.fa-head-side-virus::before{content:"î¤"}.fa-user-gear::before{content:""}.fa-user-cog::before{content:""}.fa-arrow-up-1-9::before{content:"ï…£"}.fa-sort-numeric-up::before{content:"ï…£"}.fa-door-closed::before{content:""}.fa-shield-virus::before{content:"î¬"}.fa-dice-six::before{content:""}.fa-mosquito-net::before{content:""}.fa-bridge-water::before{content:"î“Ž"}.fa-person-booth::before{content:"ï–"}.fa-text-width::before{content:""}.fa-hat-wizard::before{content:""}.fa-pen-fancy::before{content:"ï–¬"}.fa-person-digging::before{content:"ï¡ž"}.fa-digging::before{content:"ï¡ž"}.fa-trash::before{content:""}.fa-gauge-simple::before{content:""}.fa-gauge-simple-med::before{content:""}.fa-tachometer-average::before{content:""}.fa-book-medical::before{content:""}.fa-poo::before{content:""}.fa-quote-right::before{content:"ï„Ž"}.fa-quote-right-alt::before{content:"ï„Ž"}.fa-shirt::before{content:"ï•“"}.fa-t-shirt::before{content:"ï•“"}.fa-tshirt::before{content:"ï•“"}.fa-cubes::before{content:""}.fa-divide::before{content:""}.fa-tenge-sign::before{content:""}.fa-tenge::before{content:""}.fa-headphones::before{content:""}.fa-hands-holding::before{content:"ï“‚"}.fa-hands-clapping::before{content:""}.fa-republican::before{content:"ïž"}.fa-arrow-left::before{content:"ï "}.fa-person-circle-xmark::before{content:""}.fa-ruler::before{content:"ï•…"}.fa-align-left::before{content:""}.fa-dice-d6::before{content:""}.fa-restroom::before{content:"ïž½"}.fa-j::before{content:"J"}.fa-users-viewfinder::before{content:"î–•"}.fa-file-video::before{content:""}.fa-up-right-from-square::before{content:"ï"}.fa-external-link-alt::before{content:"ï"}.fa-table-cells::before{content:""}.fa-th::before{content:""}.fa-file-pdf::before{content:"ï‡"}.fa-book-bible::before{content:""}.fa-bible::before{content:""}.fa-o::before{content:"O"}.fa-suitcase-medical::before{content:""}.fa-medkit::before{content:""}.fa-user-secret::before{content:""}.fa-otter::before{content:""}.fa-person-dress::before{content:""}.fa-female::before{content:""}.fa-comment-dollar::before{content:""}.fa-business-time::before{content:""}.fa-briefcase-clock::before{content:""}.fa-table-cells-large::before{content:""}.fa-th-large::before{content:""}.fa-book-tanakh::before{content:"ï §"}.fa-tanakh::before{content:"ï §"}.fa-phone-volume::before{content:""}.fa-volume-control-phone::before{content:""}.fa-hat-cowboy-side::before{content:"ï£"}.fa-clipboard-user::before{content:""}.fa-child::before{content:""}.fa-lira-sign::before{content:""}.fa-satellite::before{content:"ïž¿"}.fa-plane-lock::before{content:""}.fa-tag::before{content:""}.fa-comment::before{content:"ïµ"}.fa-cake-candles::before{content:""}.fa-birthday-cake::before{content:""}.fa-cake::before{content:""}.fa-envelope::before{content:""}.fa-angles-up::before{content:"ï„‚"}.fa-angle-double-up::before{content:"ï„‚"}.fa-paperclip::before{content:""}.fa-arrow-right-to-city::before{content:"î’³"}.fa-ribbon::before{content:"ï“–"}.fa-lungs::before{content:""}.fa-arrow-up-9-1::before{content:""}.fa-sort-numeric-up-alt::before{content:""}.fa-litecoin-sign::before{content:""}.fa-border-none::before{content:"ï¡"}.fa-circle-nodes::before{content:"î“¢"}.fa-parachute-box::before{content:"ï“"}.fa-indent::before{content:""}.fa-truck-field-un::before{content:"î–Ž"}.fa-hourglass::before{content:""}.fa-hourglass-empty::before{content:""}.fa-mountain::before{content:""}.fa-user-doctor::before{content:""}.fa-user-md::before{content:""}.fa-circle-info::before{content:"ïš"}.fa-info-circle::before{content:"ïš"}.fa-cloud-meatball::before{content:""}.fa-camera::before{content:""}.fa-camera-alt::before{content:""}.fa-square-virus::before{content:""}.fa-meteor::before{content:"ï“"}.fa-car-on::before{content:"î“"}.fa-sleigh::before{content:""}.fa-arrow-down-1-9::before{content:"ï…¢"}.fa-sort-numeric-asc::before{content:"ï…¢"}.fa-sort-numeric-down::before{content:"ï…¢"}.fa-hand-holding-droplet::before{content:"ï“"}.fa-hand-holding-water::before{content:"ï“"}.fa-water::before{content:"ï³"}.fa-calendar-check::before{content:""}.fa-braille::before{content:""}.fa-prescription-bottle-medical::before{content:"ï’†"}.fa-prescription-bottle-alt::before{content:"ï’†"}.fa-landmark::before{content:""}.fa-truck::before{content:""}.fa-crosshairs::before{content:"ï›"}.fa-person-cane::before{content:""}.fa-tent::before{content:""}.fa-vest-patches::before{content:""}.fa-check-double::before{content:"ï• "}.fa-arrow-down-a-z::before{content:"ï…"}.fa-sort-alpha-asc::before{content:"ï…"}.fa-sort-alpha-down::before{content:"ï…"}.fa-money-bill-wheat::before{content:""}.fa-cookie::before{content:"ï•£"}.fa-arrow-rotate-left::before{content:""}.fa-arrow-left-rotate::before{content:""}.fa-arrow-rotate-back::before{content:""}.fa-arrow-rotate-backward::before{content:""}.fa-undo::before{content:""}.fa-hard-drive::before{content:"ï‚ "}.fa-hdd::before{content:"ï‚ "}.fa-face-grin-squint-tears::before{content:"ï–†"}.fa-grin-squint-tears::before{content:"ï–†"}.fa-dumbbell::before{content:"ï‘‹"}.fa-rectangle-list::before{content:""}.fa-list-alt::before{content:""}.fa-tarp-droplet::before{content:""}.fa-house-medical-circle-check::before{content:""}.fa-person-skiing-nordic::before{content:""}.fa-skiing-nordic::before{content:""}.fa-calendar-plus::before{content:""}.fa-plane-arrival::before{content:"ï–¯"}.fa-circle-left::before{content:"ï™"}.fa-arrow-alt-circle-left::before{content:"ï™"}.fa-train-subway::before{content:""}.fa-subway::before{content:""}.fa-chart-gantt::before{content:""}.fa-indian-rupee-sign::before{content:""}.fa-indian-rupee::before{content:""}.fa-inr::before{content:""}.fa-crop-simple::before{content:"ï•¥"}.fa-crop-alt::before{content:"ï•¥"}.fa-money-bill-1::before{content:"ï‘"}.fa-money-bill-alt::before{content:"ï‘"}.fa-left-long::before{content:""}.fa-long-arrow-alt-left::before{content:""}.fa-dna::before{content:""}.fa-virus-slash::before{content:"îµ"}.fa-minus::before{content:"ï¨"}.fa-subtract::before{content:"ï¨"}.fa-chess::before{content:"ï¹"}.fa-arrow-left-long::before{content:"ï…·"}.fa-long-arrow-left::before{content:"ï…·"}.fa-plug-circle-check::before{content:"î•œ"}.fa-street-view::before{content:"ïˆ"}.fa-franc-sign::before{content:"î†"}.fa-volume-off::before{content:""}.fa-hands-asl-interpreting::before{content:""}.fa-american-sign-language-interpreting::before{content:""}.fa-asl-interpreting::before{content:""}.fa-hands-american-sign-language-interpreting::before{content:""}.fa-gear::before{content:""}.fa-cog::before{content:""}.fa-droplet-slash::before{content:"ï—‡"}.fa-tint-slash::before{content:"ï—‡"}.fa-mosque::before{content:""}.fa-mosquito::before{content:""}.fa-star-of-david::before{content:"ïšš"}.fa-person-military-rifle::before{content:"î•‹"}.fa-cart-shopping::before{content:"ïº"}.fa-shopping-cart::before{content:"ïº"}.fa-vials::before{content:"ï’“"}.fa-plug-circle-plus::before{content:"î•Ÿ"}.fa-place-of-worship::before{content:""}.fa-grip-vertical::before{content:"ï–Ž"}.fa-arrow-turn-up::before{content:"ï…ˆ"}.fa-level-up::before{content:"ï…ˆ"}.fa-u::before{content:"U"}.fa-square-root-variable::before{content:""}.fa-square-root-alt::before{content:""}.fa-clock::before{content:""}.fa-clock-four::before{content:""}.fa-backward-step::before{content:"ïˆ"}.fa-step-backward::before{content:"ïˆ"}.fa-pallet::before{content:"ï’‚"}.fa-faucet::before{content:""}.fa-baseball-bat-ball::before{content:"ï²"}.fa-s::before{content:"S"}.fa-timeline::before{content:""}.fa-keyboard::before{content:"ï„œ"}.fa-caret-down::before{content:""}.fa-house-chimney-medical::before{content:""}.fa-clinic-medical::before{content:""}.fa-temperature-three-quarters::before{content:""}.fa-temperature-3::before{content:""}.fa-thermometer-3::before{content:""}.fa-thermometer-three-quarters::before{content:""}.fa-mobile-screen::before{content:"ï"}.fa-mobile-android-alt::before{content:"ï"}.fa-plane-up::before{content:""}.fa-piggy-bank::before{content:"ï““"}.fa-battery-half::before{content:""}.fa-battery-3::before{content:""}.fa-mountain-city::before{content:"î”®"}.fa-coins::before{content:""}.fa-khanda::before{content:"ï™­"}.fa-sliders::before{content:""}.fa-sliders-h::before{content:""}.fa-folder-tree::before{content:"ï ‚"}.fa-network-wired::before{content:""}.fa-map-pin::before{content:""}.fa-hamsa::before{content:""}.fa-cent-sign::before{content:"îµ"}.fa-flask::before{content:""}.fa-person-pregnant::before{content:""}.fa-wand-sparkles::before{content:""}.fa-ellipsis-vertical::before{content:"ï…‚"}.fa-ellipsis-v::before{content:"ï…‚"}.fa-ticket::before{content:"ï……"}.fa-power-off::before{content:""}.fa-right-long::before{content:""}.fa-long-arrow-alt-right::before{content:""}.fa-flag-usa::before{content:"ï"}.fa-laptop-file::before{content:"î”"}.fa-tty::before{content:""}.fa-teletype::before{content:""}.fa-diagram-next::before{content:""}.fa-person-rifle::before{content:"î•Ž"}.fa-house-medical-circle-exclamation::before{content:"î”’"}.fa-closed-captioning::before{content:""}.fa-person-hiking::before{content:""}.fa-hiking::before{content:""}.fa-venus-double::before{content:""}.fa-images::before{content:""}.fa-calculator::before{content:""}.fa-people-pulling::before{content:""}.fa-n::before{content:"N"}.fa-cable-car::before{content:""}.fa-tram::before{content:""}.fa-cloud-rain::before{content:""}.fa-building-circle-xmark::before{content:"î“”"}.fa-ship::before{content:""}.fa-arrows-down-to-line::before{content:"î’¸"}.fa-download::before{content:""}.fa-face-grin::before{content:"ï–€"}.fa-grin::before{content:"ï–€"}.fa-delete-left::before{content:"ï•š"}.fa-backspace::before{content:"ï•š"}.fa-eye-dropper::before{content:""}.fa-eye-dropper-empty::before{content:""}.fa-eyedropper::before{content:""}.fa-file-circle-check::before{content:"î– "}.fa-forward::before{content:"ïŽ"}.fa-mobile::before{content:"ïŽ"}.fa-mobile-android::before{content:"ïŽ"}.fa-mobile-phone::before{content:"ïŽ"}.fa-face-meh::before{content:"ï„š"}.fa-meh::before{content:"ï„š"}.fa-align-center::before{content:""}.fa-book-skull::before{content:"ïš·"}.fa-book-dead::before{content:"ïš·"}.fa-id-card::before{content:"ï‹‚"}.fa-drivers-license::before{content:"ï‹‚"}.fa-outdent::before{content:""}.fa-dedent::before{content:""}.fa-heart-circle-exclamation::before{content:""}.fa-house::before{content:""}.fa-home::before{content:""}.fa-home-alt::before{content:""}.fa-home-lg-alt::before{content:""}.fa-calendar-week::before{content:"ïž„"}.fa-laptop-medical::before{content:"ï ’"}.fa-b::before{content:"B"}.fa-file-medical::before{content:"ï‘·"}.fa-dice-one::before{content:""}.fa-kiwi-bird::before{content:""}.fa-arrow-right-arrow-left::before{content:""}.fa-exchange::before{content:""}.fa-rotate-right::before{content:""}.fa-redo-alt::before{content:""}.fa-rotate-forward::before{content:""}.fa-utensils::before{content:""}.fa-cutlery::before{content:""}.fa-arrow-up-wide-short::before{content:"ï…¡"}.fa-sort-amount-up::before{content:"ï…¡"}.fa-mill-sign::before{content:""}.fa-bowl-rice::before{content:"î‹«"}.fa-skull::before{content:"ï•Œ"}.fa-tower-broadcast::before{content:"ï”™"}.fa-broadcast-tower::before{content:"ï”™"}.fa-truck-pickup::before{content:""}.fa-up-long::before{content:""}.fa-long-arrow-alt-up::before{content:""}.fa-stop::before{content:"ï"}.fa-code-merge::before{content:""}.fa-upload::before{content:"ï‚“"}.fa-hurricane::before{content:"ï‘"}.fa-mound::before{content:"î”­"}.fa-toilet-portable::before{content:"î–ƒ"}.fa-compact-disc::before{content:""}.fa-file-arrow-down::before{content:"ï•­"}.fa-file-download::before{content:"ï•­"}.fa-caravan::before{content:""}.fa-shield-cat::before{content:""}.fa-bolt::before{content:""}.fa-zap::before{content:""}.fa-glass-water::before{content:"î“´"}.fa-oil-well::before{content:""}.fa-vault::before{content:"î‹…"}.fa-mars::before{content:""}.fa-toilet::before{content:""}.fa-plane-circle-xmark::before{content:"î•—"}.fa-yen-sign::before{content:"ï…—"}.fa-cny::before{content:"ï…—"}.fa-jpy::before{content:"ï…—"}.fa-rmb::before{content:"ï…—"}.fa-yen::before{content:"ï…—"}.fa-ruble-sign::before{content:"ï…˜"}.fa-rouble::before{content:"ï…˜"}.fa-rub::before{content:"ï…˜"}.fa-ruble::before{content:"ï…˜"}.fa-sun::before{content:""}.fa-guitar::before{content:""}.fa-face-laugh-wink::before{content:"ï–œ"}.fa-laugh-wink::before{content:"ï–œ"}.fa-horse-head::before{content:"ïž«"}.fa-bore-hole::before{content:""}.fa-industry::before{content:""}.fa-circle-down::before{content:"ï˜"}.fa-arrow-alt-circle-down::before{content:"ï˜"}.fa-arrows-turn-to-dots::before{content:"î“"}.fa-florin-sign::before{content:""}.fa-arrow-down-short-wide::before{content:""}.fa-sort-amount-desc::before{content:""}.fa-sort-amount-down-alt::before{content:""}.fa-less-than::before{content:"\<"}.fa-angle-down::before{content:""}.fa-car-tunnel::before{content:"î“ž"}.fa-head-side-cough::before{content:"î¡"}.fa-grip-lines::before{content:""}.fa-thumbs-down::before{content:"ï…¥"}.fa-user-lock::before{content:""}.fa-arrow-right-long::before{content:"ï…¸"}.fa-long-arrow-right::before{content:"ï…¸"}.fa-anchor-circle-xmark::before{content:"î’¬"}.fa-ellipsis::before{content:"ï…"}.fa-ellipsis-h::before{content:"ï…"}.fa-chess-pawn::before{content:""}.fa-kit-medical::before{content:""}.fa-first-aid::before{content:""}.fa-person-through-window::before{content:"î–©"}.fa-toolbox::before{content:"ï•’"}.fa-hands-holding-circle::before{content:"î“»"}.fa-bug::before{content:""}.fa-credit-card::before{content:"ï‚"}.fa-credit-card-alt::before{content:"ï‚"}.fa-car::before{content:""}.fa-automobile::before{content:""}.fa-hand-holding-hand::before{content:"î“·"}.fa-book-open-reader::before{content:"ï—š"}.fa-book-reader::before{content:"ï—š"}.fa-mountain-sun::before{content:""}.fa-arrows-left-right-to-line::before{content:"î’º"}.fa-dice-d20::before{content:"ï›"}.fa-truck-droplet::before{content:"î–Œ"}.fa-file-circle-xmark::before{content:"î–¡"}.fa-temperature-arrow-up::before{content:"î€"}.fa-temperature-up::before{content:"î€"}.fa-medal::before{content:"ï–¢"}.fa-bed::before{content:""}.fa-square-h::before{content:""}.fa-h-square::before{content:""}.fa-podcast::before{content:"ï‹Ž"}.fa-temperature-full::before{content:""}.fa-temperature-4::before{content:""}.fa-thermometer-4::before{content:""}.fa-thermometer-full::before{content:""}.fa-bell::before{content:""}.fa-superscript::before{content:"ï„«"}.fa-plug-circle-xmark::before{content:"î• "}.fa-star-of-life::before{content:""}.fa-phone-slash::before{content:"ï"}.fa-paint-roller::before{content:"ï–ª"}.fa-handshake-angle::before{content:"ï“„"}.fa-hands-helping::before{content:"ï“„"}.fa-location-dot::before{content:"ï…"}.fa-map-marker-alt::before{content:"ï…"}.fa-file::before{content:"ï…›"}.fa-greater-than::before{content:"\>"}.fa-person-swimming::before{content:"ï—„"}.fa-swimmer::before{content:"ï—„"}.fa-arrow-down::before{content:"ï£"}.fa-droplet::before{content:"ïƒ"}.fa-tint::before{content:"ïƒ"}.fa-eraser::before{content:"ï„­"}.fa-earth-americas::before{content:""}.fa-earth::before{content:""}.fa-earth-america::before{content:""}.fa-globe-americas::before{content:""}.fa-person-burst::before{content:"î”»"}.fa-dove::before{content:"ï’º"}.fa-battery-empty::before{content:""}.fa-battery-0::before{content:""}.fa-socks::before{content:"ïš–"}.fa-inbox::before{content:""}.fa-section::before{content:""}.fa-gauge-high::before{content:""}.fa-tachometer-alt::before{content:""}.fa-tachometer-alt-fast::before{content:""}.fa-envelope-open-text::before{content:""}.fa-hospital::before{content:""}.fa-hospital-alt::before{content:""}.fa-hospital-wide::before{content:""}.fa-wine-bottle::before{content:""}.fa-chess-rook::before{content:""}.fa-bars-staggered::before{content:"ï•"}.fa-reorder::before{content:"ï•"}.fa-stream::before{content:"ï•"}.fa-dharmachakra::before{content:""}.fa-hotdog::before{content:"ï "}.fa-person-walking-with-cane::before{content:"ïŠ"}.fa-blind::before{content:"ïŠ"}.fa-drum::before{content:"ï•©"}.fa-ice-cream::before{content:"ï "}.fa-heart-circle-bolt::before{content:""}.fa-fax::before{content:""}.fa-paragraph::before{content:"ï‡"}.fa-check-to-slot::before{content:"ï²"}.fa-vote-yea::before{content:"ï²"}.fa-star-half::before{content:""}.fa-boxes-stacked::before{content:""}.fa-boxes::before{content:""}.fa-boxes-alt::before{content:""}.fa-link::before{content:"ïƒ"}.fa-chain::before{content:"ïƒ"}.fa-ear-listen::before{content:""}.fa-assistive-listening-systems::before{content:""}.fa-tree-city::before{content:"î–‡"}.fa-play::before{content:"ï‹"}.fa-font::before{content:""}.fa-table-cells-row-lock::before{content:""}.fa-rupiah-sign::before{content:""}.fa-magnifying-glass::before{content:""}.fa-search::before{content:""}.fa-table-tennis-paddle-ball::before{content:"ï‘"}.fa-ping-pong-paddle-ball::before{content:"ï‘"}.fa-table-tennis::before{content:"ï‘"}.fa-person-dots-from-line::before{content:"ï‘°"}.fa-diagnoses::before{content:"ï‘°"}.fa-trash-can-arrow-up::before{content:"ï ª"}.fa-trash-restore-alt::before{content:"ï ª"}.fa-naira-sign::before{content:""}.fa-cart-arrow-down::before{content:""}.fa-walkie-talkie::before{content:""}.fa-file-pen::before{content:""}.fa-file-edit::before{content:""}.fa-receipt::before{content:""}.fa-square-pen::before{content:"ï…‹"}.fa-pen-square::before{content:"ï…‹"}.fa-pencil-square::before{content:"ï…‹"}.fa-suitcase-rolling::before{content:"ï—"}.fa-person-circle-exclamation::before{content:""}.fa-chevron-down::before{content:"ï¸"}.fa-battery-full::before{content:""}.fa-battery::before{content:""}.fa-battery-5::before{content:""}.fa-skull-crossbones::before{content:""}.fa-code-compare::before{content:""}.fa-list-ul::before{content:""}.fa-list-dots::before{content:""}.fa-school-lock::before{content:""}.fa-tower-cell::before{content:"î–…"}.fa-down-long::before{content:""}.fa-long-arrow-alt-down::before{content:""}.fa-ranking-star::before{content:"î•¡"}.fa-chess-king::before{content:"ï¿"}.fa-person-harassing::before{content:""}.fa-brazilian-real-sign::before{content:""}.fa-landmark-dome::before{content:"ï’"}.fa-landmark-alt::before{content:"ï’"}.fa-arrow-up::before{content:"ï¢"}.fa-tv::before{content:""}.fa-television::before{content:""}.fa-tv-alt::before{content:""}.fa-shrimp::before{content:""}.fa-list-check::before{content:"ï‚®"}.fa-tasks::before{content:"ï‚®"}.fa-jug-detergent::before{content:"î”™"}.fa-circle-user::before{content:""}.fa-user-circle::before{content:""}.fa-user-shield::before{content:"ï”…"}.fa-wind::before{content:""}.fa-car-burst::before{content:"ï—¡"}.fa-car-crash::before{content:"ï—¡"}.fa-y::before{content:"Y"}.fa-person-snowboarding::before{content:""}.fa-snowboarding::before{content:""}.fa-truck-fast::before{content:"ï’‹"}.fa-shipping-fast::before{content:"ï’‹"}.fa-fish::before{content:""}.fa-user-graduate::before{content:"ï”"}.fa-circle-half-stroke::before{content:"ï‚"}.fa-adjust::before{content:"ï‚"}.fa-clapperboard::before{content:""}.fa-circle-radiation::before{content:""}.fa-radiation-alt::before{content:""}.fa-baseball::before{content:"ï³"}.fa-baseball-ball::before{content:"ï³"}.fa-jet-fighter-up::before{content:""}.fa-diagram-project::before{content:"ï•‚"}.fa-project-diagram::before{content:"ï•‚"}.fa-copy::before{content:""}.fa-volume-xmark::before{content:"ïš©"}.fa-volume-mute::before{content:"ïš©"}.fa-volume-times::before{content:"ïš©"}.fa-hand-sparkles::before{content:"î"}.fa-grip::before{content:"ï–"}.fa-grip-horizontal::before{content:"ï–"}.fa-share-from-square::before{content:"ï…"}.fa-share-square::before{content:"ï…"}.fa-child-combatant::before{content:"î“ "}.fa-child-rifle::before{content:"î“ "}.fa-gun::before{content:""}.fa-square-phone::before{content:""}.fa-phone-square::before{content:""}.fa-plus::before{content:"\+"}.fa-add::before{content:"\+"}.fa-expand::before{content:"ï¥"}.fa-computer::before{content:"î“¥"}.fa-xmark::before{content:"ï€"}.fa-close::before{content:"ï€"}.fa-multiply::before{content:"ï€"}.fa-remove::before{content:"ï€"}.fa-times::before{content:"ï€"}.fa-arrows-up-down-left-right::before{content:"ï‡"}.fa-arrows::before{content:"ï‡"}.fa-chalkboard-user::before{content:""}.fa-chalkboard-teacher::before{content:""}.fa-peso-sign::before{content:""}.fa-building-shield::before{content:""}.fa-baby::before{content:"ï¼"}.fa-users-line::before{content:"î–’"}.fa-quote-left::before{content:"ï„"}.fa-quote-left-alt::before{content:"ï„"}.fa-tractor::before{content:""}.fa-trash-arrow-up::before{content:"ï ©"}.fa-trash-restore::before{content:"ï ©"}.fa-arrow-down-up-lock::before{content:"î’°"}.fa-lines-leaning::before{content:""}.fa-ruler-combined::before{content:""}.fa-copyright::before{content:""}.fa-equals::before{content:"\="}.fa-blender::before{content:"ï”—"}.fa-teeth::before{content:""}.fa-shekel-sign::before{content:""}.fa-ils::before{content:""}.fa-shekel::before{content:""}.fa-sheqel::before{content:""}.fa-sheqel-sign::before{content:""}.fa-map::before{content:""}.fa-rocket::before{content:""}.fa-photo-film::before{content:""}.fa-photo-video::before{content:""}.fa-folder-minus::before{content:"ï™"}.fa-store::before{content:"ï•Ž"}.fa-arrow-trend-up::before{content:""}.fa-plug-circle-minus::before{content:"î•ž"}.fa-sign-hanging::before{content:"ï“™"}.fa-sign::before{content:"ï“™"}.fa-bezier-curve::before{content:"ï•›"}.fa-bell-slash::before{content:""}.fa-tablet::before{content:"ï»"}.fa-tablet-android::before{content:"ï»"}.fa-school-flag::before{content:"î•®"}.fa-fill::before{content:""}.fa-angle-up::before{content:""}.fa-drumstick-bite::before{content:"ï›—"}.fa-holly-berry::before{content:""}.fa-chevron-left::before{content:"ï“"}.fa-bacteria::before{content:"î™"}.fa-hand-lizard::before{content:""}.fa-notdef::before{content:""}.fa-disease::before{content:""}.fa-briefcase-medical::before{content:"ï‘©"}.fa-genderless::before{content:""}.fa-chevron-right::before{content:"ï”"}.fa-retweet::before{content:"ï¹"}.fa-car-rear::before{content:"ï—ž"}.fa-car-alt::before{content:"ï—ž"}.fa-pump-soap::before{content:"î«"}.fa-video-slash::before{content:"ï“¢"}.fa-battery-quarter::before{content:""}.fa-battery-2::before{content:""}.fa-radio::before{content:""}.fa-baby-carriage::before{content:"ï½"}.fa-carriage-baby::before{content:"ï½"}.fa-traffic-light::before{content:""}.fa-thermometer::before{content:"ï’‘"}.fa-vr-cardboard::before{content:""}.fa-hand-middle-finger::before{content:"ï †"}.fa-percent::before{content:"\%"}.fa-percentage::before{content:"\%"}.fa-truck-moving::before{content:"ï“Ÿ"}.fa-glass-water-droplet::before{content:""}.fa-display::before{content:"î…£"}.fa-face-smile::before{content:""}.fa-smile::before{content:""}.fa-thumbtack::before{content:"ï‚"}.fa-thumb-tack::before{content:"ï‚"}.fa-trophy::before{content:"ï‚‘"}.fa-person-praying::before{content:""}.fa-pray::before{content:""}.fa-hammer::before{content:""}.fa-hand-peace::before{content:""}.fa-rotate::before{content:""}.fa-sync-alt::before{content:""}.fa-spinner::before{content:"ï„"}.fa-robot::before{content:"ï•„"}.fa-peace::before{content:""}.fa-gears::before{content:"ï‚…"}.fa-cogs::before{content:"ï‚…"}.fa-warehouse::before{content:"ï’”"}.fa-arrow-up-right-dots::before{content:"î’·"}.fa-splotch::before{content:"ï–¼"}.fa-face-grin-hearts::before{content:"ï–„"}.fa-grin-hearts::before{content:"ï–„"}.fa-dice-four::before{content:""}.fa-sim-card::before{content:""}.fa-transgender::before{content:""}.fa-transgender-alt::before{content:""}.fa-mercury::before{content:""}.fa-arrow-turn-down::before{content:"ï…‰"}.fa-level-down::before{content:"ï…‰"}.fa-person-falling-burst::before{content:""}.fa-award::before{content:"ï•™"}.fa-ticket-simple::before{content:"ï¿"}.fa-ticket-alt::before{content:"ï¿"}.fa-building::before{content:""}.fa-angles-left::before{content:"ï„€"}.fa-angle-double-left::before{content:"ï„€"}.fa-qrcode::before{content:""}.fa-clock-rotate-left::before{content:""}.fa-history::before{content:""}.fa-face-grin-beam-sweat::before{content:"ï–ƒ"}.fa-grin-beam-sweat::before{content:"ï–ƒ"}.fa-file-export::before{content:"ï•®"}.fa-arrow-right-from-file::before{content:"ï•®"}.fa-shield::before{content:""}.fa-shield-blank::before{content:""}.fa-arrow-up-short-wide::before{content:""}.fa-sort-amount-up-alt::before{content:""}.fa-house-medical::before{content:""}.fa-golf-ball-tee::before{content:"ï‘"}.fa-golf-ball::before{content:"ï‘"}.fa-circle-chevron-left::before{content:"ï„·"}.fa-chevron-circle-left::before{content:"ï„·"}.fa-house-chimney-window::before{content:"î€"}.fa-pen-nib::before{content:"ï–­"}.fa-tent-arrow-turn-left::before{content:"î–€"}.fa-tents::before{content:"î–‚"}.fa-wand-magic::before{content:"ïƒ"}.fa-magic::before{content:"ïƒ"}.fa-dog::before{content:""}.fa-carrot::before{content:""}.fa-moon::before{content:""}.fa-wine-glass-empty::before{content:"ï—Ž"}.fa-wine-glass-alt::before{content:"ï—Ž"}.fa-cheese::before{content:""}.fa-yin-yang::before{content:"ïš­"}.fa-music::before{content:"ï€"}.fa-code-commit::before{content:""}.fa-temperature-low::before{content:"ï«"}.fa-person-biking::before{content:"ï¡Š"}.fa-biking::before{content:"ï¡Š"}.fa-broom::before{content:""}.fa-shield-heart::before{content:"î•´"}.fa-gopuram::before{content:""}.fa-earth-oceania::before{content:"î‘»"}.fa-globe-oceania::before{content:"î‘»"}.fa-square-xmark::before{content:"ï‹“"}.fa-times-square::before{content:"ï‹“"}.fa-xmark-square::before{content:"ï‹“"}.fa-hashtag::before{content:"\#"}.fa-up-right-and-down-left-from-center::before{content:"ï¤"}.fa-expand-alt::before{content:"ï¤"}.fa-oil-can::before{content:""}.fa-t::before{content:"T"}.fa-hippo::before{content:"ï›­"}.fa-chart-column::before{content:""}.fa-infinity::before{content:"ï”´"}.fa-vial-circle-check::before{content:"î––"}.fa-person-arrow-down-to-line::before{content:""}.fa-voicemail::before{content:""}.fa-fan::before{content:"ï¡£"}.fa-person-walking-luggage::before{content:"î•”"}.fa-up-down::before{content:""}.fa-arrows-alt-v::before{content:""}.fa-cloud-moon-rain::before{content:""}.fa-calendar::before{content:""}.fa-trailer::before{content:"î"}.fa-bahai::before{content:""}.fa-haykal::before{content:""}.fa-sd-card::before{content:""}.fa-dragon::before{content:""}.fa-shoe-prints::before{content:"ï•‹"}.fa-circle-plus::before{content:"ï•"}.fa-plus-circle::before{content:"ï•"}.fa-face-grin-tongue-wink::before{content:"ï–‹"}.fa-grin-tongue-wink::before{content:"ï–‹"}.fa-hand-holding::before{content:"ï’½"}.fa-plug-circle-exclamation::before{content:"î•"}.fa-link-slash::before{content:""}.fa-chain-broken::before{content:""}.fa-chain-slash::before{content:""}.fa-unlink::before{content:""}.fa-clone::before{content:"ï‰"}.fa-person-walking-arrow-loop-left::before{content:"î•‘"}.fa-arrow-up-z-a::before{content:""}.fa-sort-alpha-up-alt::before{content:""}.fa-fire-flame-curved::before{content:""}.fa-fire-alt::before{content:""}.fa-tornado::before{content:"ï¯"}.fa-file-circle-plus::before{content:"î’”"}.fa-book-quran::before{content:""}.fa-quran::before{content:""}.fa-anchor::before{content:""}.fa-border-all::before{content:"ï¡Œ"}.fa-face-angry::before{content:"ï•–"}.fa-angry::before{content:"ï•–"}.fa-cookie-bite::before{content:""}.fa-arrow-trend-down::before{content:"î‚—"}.fa-rss::before{content:"ï‚ž"}.fa-feed::before{content:"ï‚ž"}.fa-draw-polygon::before{content:"ï—®"}.fa-scale-balanced::before{content:""}.fa-balance-scale::before{content:""}.fa-gauge-simple-high::before{content:""}.fa-tachometer::before{content:""}.fa-tachometer-fast::before{content:""}.fa-shower::before{content:"ï‹Œ"}.fa-desktop::before{content:"ïŽ"}.fa-desktop-alt::before{content:"ïŽ"}.fa-m::before{content:"M"}.fa-table-list::before{content:""}.fa-th-list::before{content:""}.fa-comment-sms::before{content:"ïŸ"}.fa-sms::before{content:"ïŸ"}.fa-book::before{content:""}.fa-user-plus::before{content:""}.fa-check::before{content:""}.fa-battery-three-quarters::before{content:"ï‰"}.fa-battery-4::before{content:"ï‰"}.fa-house-circle-check::before{content:""}.fa-angle-left::before{content:"ï„„"}.fa-diagram-successor::before{content:""}.fa-truck-arrow-right::before{content:"î–‹"}.fa-arrows-split-up-and-left::before{content:"î’¼"}.fa-hand-fist::before{content:""}.fa-fist-raised::before{content:""}.fa-cloud-moon::before{content:""}.fa-briefcase::before{content:""}.fa-person-falling::before{content:""}.fa-image-portrait::before{content:"ï "}.fa-portrait::before{content:"ï "}.fa-user-tag::before{content:""}.fa-rug::before{content:"î•©"}.fa-earth-europe::before{content:""}.fa-globe-europe::before{content:""}.fa-cart-flatbed-suitcase::before{content:"ï–"}.fa-luggage-cart::before{content:"ï–"}.fa-rectangle-xmark::before{content:"ï"}.fa-rectangle-times::before{content:"ï"}.fa-times-rectangle::before{content:"ï"}.fa-window-close::before{content:"ï"}.fa-baht-sign::before{content:""}.fa-book-open::before{content:""}.fa-book-journal-whills::before{content:""}.fa-journal-whills::before{content:""}.fa-handcuffs::before{content:""}.fa-triangle-exclamation::before{content:"ï±"}.fa-exclamation-triangle::before{content:"ï±"}.fa-warning::before{content:"ï±"}.fa-database::before{content:""}.fa-share::before{content:"ï¤"}.fa-mail-forward::before{content:"ï¤"}.fa-bottle-droplet::before{content:"î“„"}.fa-mask-face::before{content:""}.fa-hill-rockslide::before{content:""}.fa-right-left::before{content:"ï¢"}.fa-exchange-alt::before{content:"ï¢"}.fa-paper-plane::before{content:""}.fa-road-circle-exclamation::before{content:"î•¥"}.fa-dungeon::before{content:"ï›™"}.fa-align-right::before{content:""}.fa-money-bill-1-wave::before{content:"ï”»"}.fa-money-bill-wave-alt::before{content:"ï”»"}.fa-life-ring::before{content:"ï‡"}.fa-hands::before{content:""}.fa-sign-language::before{content:""}.fa-signing::before{content:""}.fa-calendar-day::before{content:""}.fa-water-ladder::before{content:"ï—…"}.fa-ladder-water::before{content:"ï—…"}.fa-swimming-pool::before{content:"ï—…"}.fa-arrows-up-down::before{content:"ï½"}.fa-arrows-v::before{content:"ï½"}.fa-face-grimace::before{content:"ï•¿"}.fa-grimace::before{content:"ï•¿"}.fa-wheelchair-move::before{content:"î‹Ž"}.fa-wheelchair-alt::before{content:"î‹Ž"}.fa-turn-down::before{content:""}.fa-level-down-alt::before{content:""}.fa-person-walking-arrow-right::before{content:"î•’"}.fa-square-envelope::before{content:""}.fa-envelope-square::before{content:""}.fa-dice::before{content:""}.fa-bowling-ball::before{content:"ï¶"}.fa-brain::before{content:"ï—œ"}.fa-bandage::before{content:"ï‘¢"}.fa-band-aid::before{content:"ï‘¢"}.fa-calendar-minus::before{content:""}.fa-circle-xmark::before{content:"ï—"}.fa-times-circle::before{content:"ï—"}.fa-xmark-circle::before{content:"ï—"}.fa-gifts::before{content:"ïžœ"}.fa-hotel::before{content:"ï–”"}.fa-earth-asia::before{content:""}.fa-globe-asia::before{content:""}.fa-id-card-clip::before{content:"ï‘¿"}.fa-id-card-alt::before{content:"ï‘¿"}.fa-magnifying-glass-plus::before{content:""}.fa-search-plus::before{content:""}.fa-thumbs-up::before{content:"ï…¤"}.fa-user-clock::before{content:""}.fa-hand-dots::before{content:"ï‘¡"}.fa-allergies::before{content:"ï‘¡"}.fa-file-invoice::before{content:"ï•°"}.fa-window-minimize::before{content:"ï‹‘"}.fa-mug-saucer::before{content:""}.fa-coffee::before{content:""}.fa-brush::before{content:"ï•"}.fa-mask::before{content:""}.fa-magnifying-glass-minus::before{content:"ï€"}.fa-search-minus::before{content:"ï€"}.fa-ruler-vertical::before{content:""}.fa-user-large::before{content:"ï†"}.fa-user-alt::before{content:"ï†"}.fa-train-tram::before{content:"î–´"}.fa-user-nurse::before{content:"ï ¯"}.fa-syringe::before{content:"ï’Ž"}.fa-cloud-sun::before{content:""}.fa-stopwatch-20::before{content:"î¯"}.fa-square-full::before{content:"ï‘œ"}.fa-magnet::before{content:"ï¶"}.fa-jar::before{content:"î”–"}.fa-note-sticky::before{content:""}.fa-sticky-note::before{content:""}.fa-bug-slash::before{content:"î’"}.fa-arrow-up-from-water-pump::before{content:"î’¶"}.fa-bone::before{content:"ï——"}.fa-table-cells-row-unlock::before{content:"îš‘"}.fa-user-injured::before{content:""}.fa-face-sad-tear::before{content:"ï–´"}.fa-sad-tear::before{content:"ï–´"}.fa-plane::before{content:"ï²"}.fa-tent-arrows-down::before{content:"î–"}.fa-exclamation::before{content:"\!"}.fa-arrows-spin::before{content:"î’»"}.fa-print::before{content:""}.fa-turkish-lira-sign::before{content:""}.fa-try::before{content:""}.fa-turkish-lira::before{content:""}.fa-dollar-sign::before{content:"\$"}.fa-dollar::before{content:"\$"}.fa-usd::before{content:"\$"}.fa-x::before{content:"X"}.fa-magnifying-glass-dollar::before{content:""}.fa-search-dollar::before{content:""}.fa-users-gear::before{content:""}.fa-users-cog::before{content:""}.fa-person-military-pointing::before{content:"î•Š"}.fa-building-columns::before{content:""}.fa-bank::before{content:""}.fa-institution::before{content:""}.fa-museum::before{content:""}.fa-university::before{content:""}.fa-umbrella::before{content:""}.fa-trowel::before{content:"î–‰"}.fa-d::before{content:"D"}.fa-stapler::before{content:"î–¯"}.fa-masks-theater::before{content:""}.fa-theater-masks::before{content:""}.fa-kip-sign::before{content:""}.fa-hand-point-left::before{content:"ï‚¥"}.fa-handshake-simple::before{content:""}.fa-handshake-alt::before{content:""}.fa-jet-fighter::before{content:""}.fa-fighter-jet::before{content:""}.fa-square-share-nodes::before{content:""}.fa-share-alt-square::before{content:""}.fa-barcode::before{content:""}.fa-plus-minus::before{content:"î¼"}.fa-video::before{content:""}.fa-video-camera::before{content:""}.fa-graduation-cap::before{content:"ï†"}.fa-mortar-board::before{content:"ï†"}.fa-hand-holding-medical::before{content:"îœ"}.fa-person-circle-check::before{content:""}.fa-turn-up::before{content:""}.fa-level-up-alt::before{content:""}.sr-only,.fa-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.sr-only-focusable:not(:focus),.fa-sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}/*! - * Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com + */.fa{font-family:var(--fa-style-family, "Font Awesome 6 Free");font-weight:var(--fa-style, 900)}.fas,.far,.fab,.fa-solid,.fa-regular,.fa-brands,.fa{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display, inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fas::before,.far::before,.fab::before,.fa-solid::before,.fa-regular::before,.fa-brands::before,.fa::before{content:var(--fa)}.fa-classic,.fas,.fa-solid,.far,.fa-regular{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.0833333337em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.0714285718em;vertical-align:.0535714295em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.0416666682em;vertical-align:-0.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-0.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin, 2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(-1*var(--fa-li-width, 2em));position:absolute;text-align:center;width:var(--fa-li-width, 2em);line-height:inherit}.fa-border{border-color:var(--fa-border-color, #eee);border-radius:var(--fa-border-radius, 0.1em);border-style:var(--fa-border-style, solid);border-width:var(--fa-border-width, 0.08em);padding:var(--fa-border-padding, 0.2em 0.25em 0.15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin, 0.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin, 0.3em)}.fa-beat{animation-name:fa-beat;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, ease-in-out)}.fa-bounce{animation-name:fa-bounce;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1))}.fa-fade{animation-name:fa-fade;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1))}.fa-beat-fade{animation-name:fa-beat-fade;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1))}.fa-flip{animation-name:fa-flip;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, ease-in-out)}.fa-shake{animation-name:fa-shake;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, linear)}.fa-spin{animation-name:fa-spin;animation-delay:var(--fa-animation-delay, 0s);animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 2s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, linear)}.fa-spin-reverse{--fa-animation-direction: reverse}.fa-pulse,.fa-spin-pulse{animation-name:fa-spin;animation-direction:var(--fa-animation-direction, normal);animation-duration:var(--fa-animation-duration, 1s);animation-iteration-count:var(--fa-animation-iteration-count, infinite);animation-timing-function:var(--fa-animation-timing, steps(8))}@media(prefers-reduced-motion: reduce){.fa-beat,.fa-bounce,.fa-fade,.fa-beat-fade,.fa-flip,.fa-pulse,.fa-shake,.fa-spin,.fa-spin-pulse{animation-delay:-1ms;animation-duration:1ms;animation-iteration-count:1;transition-delay:0s;transition-duration:0s}}@keyframes fa-beat{0%,90%{transform:scale(1)}45%{transform:scale(var(--fa-beat-scale, 1.25))}}@keyframes fa-bounce{0%{transform:scale(1, 1) translateY(0)}10%{transform:scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0)}30%{transform:scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em))}50%{transform:scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0)}57%{transform:scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em))}64%{transform:scale(1, 1) translateY(0)}100%{transform:scale(1, 1) translateY(0)}}@keyframes fa-fade{50%{opacity:var(--fa-fade-opacity, 0.4)}}@keyframes fa-beat-fade{0%,100%{opacity:var(--fa-beat-fade-opacity, 0.4);transform:scale(1)}50%{opacity:1;transform:scale(var(--fa-beat-fade-scale, 1.125))}}@keyframes fa-flip{50%{transform:rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg))}}@keyframes fa-shake{0%{transform:rotate(-15deg)}4%{transform:rotate(15deg)}8%,24%{transform:rotate(-18deg)}12%,28%{transform:rotate(18deg)}16%{transform:rotate(-22deg)}20%{transform:rotate(22deg)}32%{transform:rotate(-12deg)}36%{transform:rotate(12deg)}40%,100%{transform:rotate(0deg)}}@keyframes fa-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.fa-rotate-90{transform:rotate(90deg)}.fa-rotate-180{transform:rotate(180deg)}.fa-rotate-270{transform:rotate(270deg)}.fa-flip-horizontal{transform:scale(-1, 1)}.fa-flip-vertical{transform:scale(1, -1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1, -1)}.fa-rotate-by{transform:rotate(var(--fa-rotate-angle, 0))}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%;z-index:var(--fa-stack-z-index, auto)}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:var(--fa-inverse, #fff)}.fa-0{--fa:"\30 ";--fa--fa:"\30 \30 "}.fa-1{--fa:"\31 ";--fa--fa:"\31 \31 "}.fa-2{--fa:"\32 ";--fa--fa:"\32 \32 "}.fa-3{--fa:"\33 ";--fa--fa:"\33 \33 "}.fa-4{--fa:"\34 ";--fa--fa:"\34 \34 "}.fa-5{--fa:"\35 ";--fa--fa:"\35 \35 "}.fa-6{--fa:"\36 ";--fa--fa:"\36 \36 "}.fa-7{--fa:"\37 ";--fa--fa:"\37 \37 "}.fa-8{--fa:"\38 ";--fa--fa:"\38 \38 "}.fa-9{--fa:"\39 ";--fa--fa:"\39 \39 "}.fa-fill-drip{--fa:"";--fa--fa:""}.fa-arrows-to-circle{--fa:"î’½";--fa--fa:""}.fa-circle-chevron-right{--fa:"";--fa--fa:""}.fa-chevron-circle-right{--fa:"";--fa--fa:""}.fa-at{--fa:"\@";--fa--fa:"\@\@"}.fa-trash-can{--fa:"ï‹­";--fa--fa:"ï‹­ï‹­"}.fa-trash-alt{--fa:"ï‹­";--fa--fa:"ï‹­ï‹­"}.fa-text-height{--fa:"";--fa--fa:""}.fa-user-xmark{--fa:"";--fa--fa:""}.fa-user-times{--fa:"";--fa--fa:""}.fa-stethoscope{--fa:"";--fa--fa:""}.fa-message{--fa:"";--fa--fa:""}.fa-comment-alt{--fa:"";--fa--fa:""}.fa-info{--fa:"ï„©";--fa--fa:"ï„©ï„©"}.fa-down-left-and-up-right-to-center{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-compress-alt{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-explosion{--fa:"î“©";--fa--fa:"î“©î“©"}.fa-file-lines{--fa:"ï…œ";--fa--fa:""}.fa-file-alt{--fa:"ï…œ";--fa--fa:""}.fa-file-text{--fa:"ï…œ";--fa--fa:""}.fa-wave-square{--fa:"ï ¾";--fa--fa:""}.fa-ring{--fa:"";--fa--fa:""}.fa-building-un{--fa:"î“™";--fa--fa:""}.fa-dice-three{--fa:"";--fa--fa:""}.fa-calendar-days{--fa:"ï³";--fa--fa:"ï³ï³"}.fa-calendar-alt{--fa:"ï³";--fa--fa:"ï³ï³"}.fa-anchor-circle-check{--fa:"î’ª";--fa--fa:""}.fa-building-circle-arrow-right{--fa:"î“‘";--fa--fa:"î“‘î“‘"}.fa-volleyball{--fa:"ï‘Ÿ";--fa--fa:"ï‘Ÿï‘Ÿ"}.fa-volleyball-ball{--fa:"ï‘Ÿ";--fa--fa:"ï‘Ÿï‘Ÿ"}.fa-arrows-up-to-line{--fa:"î“‚";--fa--fa:"î“‚î“‚"}.fa-sort-down{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-sort-desc{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-circle-minus{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-minus-circle{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-door-open{--fa:"";--fa--fa:""}.fa-right-from-bracket{--fa:"";--fa--fa:""}.fa-sign-out-alt{--fa:"";--fa--fa:""}.fa-atom{--fa:"ï—’";--fa--fa:"ï—’ï—’"}.fa-soap{--fa:"î®";--fa--fa:"î®î®"}.fa-icons{--fa:"ï¡­";--fa--fa:"ï¡­ï¡­"}.fa-heart-music-camera-bolt{--fa:"ï¡­";--fa--fa:"ï¡­ï¡­"}.fa-microphone-lines-slash{--fa:"";--fa--fa:""}.fa-microphone-alt-slash{--fa:"";--fa--fa:""}.fa-bridge-circle-check{--fa:"";--fa--fa:""}.fa-pump-medical{--fa:"îª";--fa--fa:"îªîª"}.fa-fingerprint{--fa:"ï•·";--fa--fa:"ï•·ï•·"}.fa-hand-point-right{--fa:"";--fa--fa:""}.fa-magnifying-glass-location{--fa:"";--fa--fa:""}.fa-search-location{--fa:"";--fa--fa:""}.fa-forward-step{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-step-forward{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-face-smile-beam{--fa:"ï–¸";--fa--fa:""}.fa-smile-beam{--fa:"ï–¸";--fa--fa:""}.fa-flag-checkered{--fa:"ï„ž";--fa--fa:"ï„žï„ž"}.fa-football{--fa:"ï‘Ž";--fa--fa:"ï‘Žï‘Ž"}.fa-football-ball{--fa:"ï‘Ž";--fa--fa:"ï‘Žï‘Ž"}.fa-school-circle-exclamation{--fa:"";--fa--fa:""}.fa-crop{--fa:"ï„¥";--fa--fa:""}.fa-angles-down{--fa:"";--fa--fa:""}.fa-angle-double-down{--fa:"";--fa--fa:""}.fa-users-rectangle{--fa:"î–”";--fa--fa:""}.fa-people-roof{--fa:"î”·";--fa--fa:"î”·î”·"}.fa-people-line{--fa:"î”´";--fa--fa:"î”´î”´"}.fa-beer-mug-empty{--fa:"";--fa--fa:""}.fa-beer{--fa:"";--fa--fa:""}.fa-diagram-predecessor{--fa:"î‘·";--fa--fa:"î‘·î‘·"}.fa-arrow-up-long{--fa:"ï…¶";--fa--fa:""}.fa-long-arrow-up{--fa:"ï…¶";--fa--fa:""}.fa-fire-flame-simple{--fa:"";--fa--fa:""}.fa-burn{--fa:"";--fa--fa:""}.fa-person{--fa:"";--fa--fa:""}.fa-male{--fa:"";--fa--fa:""}.fa-laptop{--fa:"";--fa--fa:""}.fa-file-csv{--fa:"ï›";--fa--fa:"ï›ï›"}.fa-menorah{--fa:"";--fa--fa:""}.fa-truck-plane{--fa:"î–";--fa--fa:"î–î–"}.fa-record-vinyl{--fa:"";--fa--fa:""}.fa-face-grin-stars{--fa:"ï–‡";--fa--fa:""}.fa-grin-stars{--fa:"ï–‡";--fa--fa:""}.fa-bong{--fa:"ï•œ";--fa--fa:""}.fa-spaghetti-monster-flying{--fa:"ï™»";--fa--fa:""}.fa-pastafarianism{--fa:"ï™»";--fa--fa:""}.fa-arrow-down-up-across-line{--fa:"î’¯";--fa--fa:""}.fa-spoon{--fa:"ï‹¥";--fa--fa:""}.fa-utensil-spoon{--fa:"ï‹¥";--fa--fa:""}.fa-jar-wheat{--fa:"î”—";--fa--fa:"î”—î”—"}.fa-envelopes-bulk{--fa:"ï™´";--fa--fa:"ï™´ï™´"}.fa-mail-bulk{--fa:"ï™´";--fa--fa:"ï™´ï™´"}.fa-file-circle-exclamation{--fa:"î“«";--fa--fa:"î“«î“«"}.fa-circle-h{--fa:"";--fa--fa:""}.fa-hospital-symbol{--fa:"";--fa--fa:""}.fa-pager{--fa:"ï •";--fa--fa:"ï •ï •"}.fa-address-book{--fa:"";--fa--fa:""}.fa-contact-book{--fa:"";--fa--fa:""}.fa-strikethrough{--fa:"";--fa--fa:""}.fa-k{--fa:"K";--fa--fa:"KK"}.fa-landmark-flag{--fa:"";--fa--fa:""}.fa-pencil{--fa:"";--fa--fa:""}.fa-pencil-alt{--fa:"";--fa--fa:""}.fa-backward{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-caret-right{--fa:"";--fa--fa:""}.fa-comments{--fa:"";--fa--fa:""}.fa-paste{--fa:"";--fa--fa:""}.fa-file-clipboard{--fa:"";--fa--fa:""}.fa-code-pull-request{--fa:"";--fa--fa:""}.fa-clipboard-list{--fa:"ï‘­";--fa--fa:"ï‘­ï‘­"}.fa-truck-ramp-box{--fa:"ï“ž";--fa--fa:"ï“žï“ž"}.fa-truck-loading{--fa:"ï“ž";--fa--fa:"ï“žï“ž"}.fa-user-check{--fa:"";--fa--fa:""}.fa-vial-virus{--fa:"î–—";--fa--fa:"î–—î–—"}.fa-sheet-plastic{--fa:"";--fa--fa:""}.fa-blog{--fa:"ïž";--fa--fa:"ïžïž"}.fa-user-ninja{--fa:"";--fa--fa:""}.fa-person-arrow-up-from-line{--fa:"";--fa--fa:""}.fa-scroll-torah{--fa:"ïš ";--fa--fa:"ïš ïš "}.fa-torah{--fa:"ïš ";--fa--fa:"ïš ïš "}.fa-broom-ball{--fa:"";--fa--fa:""}.fa-quidditch{--fa:"";--fa--fa:""}.fa-quidditch-broom-ball{--fa:"";--fa--fa:""}.fa-toggle-off{--fa:"";--fa--fa:""}.fa-box-archive{--fa:"";--fa--fa:""}.fa-archive{--fa:"";--fa--fa:""}.fa-person-drowning{--fa:"î•…";--fa--fa:"î•…î•…"}.fa-arrow-down-9-1{--fa:"";--fa--fa:""}.fa-sort-numeric-desc{--fa:"";--fa--fa:""}.fa-sort-numeric-down-alt{--fa:"";--fa--fa:""}.fa-face-grin-tongue-squint{--fa:"ï–Š";--fa--fa:"ï–Šï–Š"}.fa-grin-tongue-squint{--fa:"ï–Š";--fa--fa:"ï–Šï–Š"}.fa-spray-can{--fa:"ï–½";--fa--fa:""}.fa-truck-monster{--fa:"";--fa--fa:""}.fa-w{--fa:"W";--fa--fa:"WW"}.fa-earth-africa{--fa:"";--fa--fa:""}.fa-globe-africa{--fa:"";--fa--fa:""}.fa-rainbow{--fa:"ï›";--fa--fa:"ï›ï›"}.fa-circle-notch{--fa:"";--fa--fa:""}.fa-tablet-screen-button{--fa:"ïº";--fa--fa:"ïºïº"}.fa-tablet-alt{--fa:"ïº";--fa--fa:"ïºïº"}.fa-paw{--fa:"";--fa--fa:""}.fa-cloud{--fa:"";--fa--fa:""}.fa-trowel-bricks{--fa:"î–Š";--fa--fa:"î–Šî–Š"}.fa-face-flushed{--fa:"";--fa--fa:""}.fa-flushed{--fa:"";--fa--fa:""}.fa-hospital-user{--fa:"ï ";--fa--fa:"ï ï "}.fa-tent-arrow-left-right{--fa:"î•¿";--fa--fa:"î•¿î•¿"}.fa-gavel{--fa:"";--fa--fa:""}.fa-legal{--fa:"";--fa--fa:""}.fa-binoculars{--fa:"";--fa--fa:""}.fa-microphone-slash{--fa:"";--fa--fa:""}.fa-box-tissue{--fa:"î›";--fa--fa:"î›î›"}.fa-motorcycle{--fa:"";--fa--fa:""}.fa-bell-concierge{--fa:"ï•¢";--fa--fa:""}.fa-concierge-bell{--fa:"ï•¢";--fa--fa:""}.fa-pen-ruler{--fa:"ï–®";--fa--fa:""}.fa-pencil-ruler{--fa:"ï–®";--fa--fa:""}.fa-people-arrows{--fa:"î¨";--fa--fa:"î¨î¨"}.fa-people-arrows-left-right{--fa:"î¨";--fa--fa:"î¨î¨"}.fa-mars-and-venus-burst{--fa:"";--fa--fa:""}.fa-square-caret-right{--fa:"ï…’";--fa--fa:"ï…’ï…’"}.fa-caret-square-right{--fa:"ï…’";--fa--fa:"ï…’ï…’"}.fa-scissors{--fa:"";--fa--fa:""}.fa-cut{--fa:"";--fa--fa:""}.fa-sun-plant-wilt{--fa:"";--fa--fa:""}.fa-toilets-portable{--fa:"î–„";--fa--fa:"î–„î–„"}.fa-hockey-puck{--fa:"ï‘“";--fa--fa:"ï‘“ï‘“"}.fa-table{--fa:"";--fa--fa:""}.fa-magnifying-glass-arrow-right{--fa:"";--fa--fa:""}.fa-tachograph-digital{--fa:"";--fa--fa:""}.fa-digital-tachograph{--fa:"";--fa--fa:""}.fa-users-slash{--fa:"î³";--fa--fa:"î³î³"}.fa-clover{--fa:"";--fa--fa:""}.fa-reply{--fa:"ï¥";--fa--fa:"ï¥ï¥"}.fa-mail-reply{--fa:"ï¥";--fa--fa:"ï¥ï¥"}.fa-star-and-crescent{--fa:"ïš™";--fa--fa:""}.fa-house-fire{--fa:"";--fa--fa:""}.fa-square-minus{--fa:"ï…†";--fa--fa:""}.fa-minus-square{--fa:"ï…†";--fa--fa:""}.fa-helicopter{--fa:"";--fa--fa:""}.fa-compass{--fa:"ï…Ž";--fa--fa:"ï…Žï…Ž"}.fa-square-caret-down{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-caret-square-down{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-file-circle-question{--fa:"";--fa--fa:""}.fa-laptop-code{--fa:"ï—¼";--fa--fa:""}.fa-swatchbook{--fa:"ï—ƒ";--fa--fa:""}.fa-prescription-bottle{--fa:"ï’…";--fa--fa:"ï’…ï’…"}.fa-bars{--fa:"";--fa--fa:""}.fa-navicon{--fa:"";--fa--fa:""}.fa-people-group{--fa:"";--fa--fa:""}.fa-hourglass-end{--fa:"";--fa--fa:""}.fa-hourglass-3{--fa:"";--fa--fa:""}.fa-heart-crack{--fa:"ïž©";--fa--fa:"ïž©ïž©"}.fa-heart-broken{--fa:"ïž©";--fa--fa:"ïž©ïž©"}.fa-square-up-right{--fa:"ï ";--fa--fa:"ï ï "}.fa-external-link-square-alt{--fa:"ï ";--fa--fa:"ï ï "}.fa-face-kiss-beam{--fa:"ï–—";--fa--fa:"ï–—ï–—"}.fa-kiss-beam{--fa:"ï–—";--fa--fa:"ï–—ï–—"}.fa-film{--fa:"";--fa--fa:""}.fa-ruler-horizontal{--fa:"";--fa--fa:""}.fa-people-robbery{--fa:"";--fa--fa:""}.fa-lightbulb{--fa:"";--fa--fa:""}.fa-caret-left{--fa:"";--fa--fa:""}.fa-circle-exclamation{--fa:"ïª";--fa--fa:"ïªïª"}.fa-exclamation-circle{--fa:"ïª";--fa--fa:"ïªïª"}.fa-school-circle-xmark{--fa:"î•­";--fa--fa:"î•­î•­"}.fa-arrow-right-from-bracket{--fa:"ï‚‹";--fa--fa:"ï‚‹ï‚‹"}.fa-sign-out{--fa:"ï‚‹";--fa--fa:"ï‚‹ï‚‹"}.fa-circle-chevron-down{--fa:"";--fa--fa:""}.fa-chevron-circle-down{--fa:"";--fa--fa:""}.fa-unlock-keyhole{--fa:"";--fa--fa:""}.fa-unlock-alt{--fa:"";--fa--fa:""}.fa-cloud-showers-heavy{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-headphones-simple{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-headphones-alt{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-sitemap{--fa:"";--fa--fa:""}.fa-circle-dollar-to-slot{--fa:"ï’¹";--fa--fa:""}.fa-donate{--fa:"ï’¹";--fa--fa:""}.fa-memory{--fa:"";--fa--fa:""}.fa-road-spikes{--fa:"";--fa--fa:""}.fa-fire-burner{--fa:"";--fa--fa:""}.fa-flag{--fa:"";--fa--fa:""}.fa-hanukiah{--fa:"";--fa--fa:""}.fa-feather{--fa:"ï”­";--fa--fa:"ï”­ï”­"}.fa-volume-low{--fa:"";--fa--fa:""}.fa-volume-down{--fa:"";--fa--fa:""}.fa-comment-slash{--fa:"ï’³";--fa--fa:""}.fa-cloud-sun-rain{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-compress{--fa:"ï¦";--fa--fa:"ï¦ï¦"}.fa-wheat-awn{--fa:"î‹";--fa--fa:"î‹î‹"}.fa-wheat-alt{--fa:"î‹";--fa--fa:"î‹î‹"}.fa-ankh{--fa:"";--fa--fa:""}.fa-hands-holding-child{--fa:"";--fa--fa:""}.fa-asterisk{--fa:"\*";--fa--fa:"\*\*"}.fa-square-check{--fa:"ï…Š";--fa--fa:"ï…Šï…Š"}.fa-check-square{--fa:"ï…Š";--fa--fa:"ï…Šï…Š"}.fa-peseta-sign{--fa:"";--fa--fa:""}.fa-heading{--fa:"";--fa--fa:""}.fa-header{--fa:"";--fa--fa:""}.fa-ghost{--fa:"";--fa--fa:""}.fa-list{--fa:"";--fa--fa:""}.fa-list-squares{--fa:"";--fa--fa:""}.fa-square-phone-flip{--fa:"ï¡»";--fa--fa:""}.fa-phone-square-alt{--fa:"ï¡»";--fa--fa:""}.fa-cart-plus{--fa:"";--fa--fa:""}.fa-gamepad{--fa:"ï„›";--fa--fa:""}.fa-circle-dot{--fa:"";--fa--fa:""}.fa-dot-circle{--fa:"";--fa--fa:""}.fa-face-dizzy{--fa:"";--fa--fa:""}.fa-dizzy{--fa:"";--fa--fa:""}.fa-egg{--fa:"";--fa--fa:""}.fa-house-medical-circle-xmark{--fa:"";--fa--fa:""}.fa-campground{--fa:"ïš»";--fa--fa:""}.fa-folder-plus{--fa:"";--fa--fa:""}.fa-futbol{--fa:"";--fa--fa:""}.fa-futbol-ball{--fa:"";--fa--fa:""}.fa-soccer-ball{--fa:"";--fa--fa:""}.fa-paintbrush{--fa:"";--fa--fa:""}.fa-paint-brush{--fa:"";--fa--fa:""}.fa-lock{--fa:"";--fa--fa:""}.fa-gas-pump{--fa:"";--fa--fa:""}.fa-hot-tub-person{--fa:"ï–“";--fa--fa:"ï–“ï–“"}.fa-hot-tub{--fa:"ï–“";--fa--fa:"ï–“ï–“"}.fa-map-location{--fa:"ï–Ÿ";--fa--fa:"ï–Ÿï–Ÿ"}.fa-map-marked{--fa:"ï–Ÿ";--fa--fa:"ï–Ÿï–Ÿ"}.fa-house-flood-water{--fa:"";--fa--fa:""}.fa-tree{--fa:"";--fa--fa:""}.fa-bridge-lock{--fa:"î“Œ";--fa--fa:""}.fa-sack-dollar{--fa:"ï ";--fa--fa:"ï ï "}.fa-pen-to-square{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-edit{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-car-side{--fa:"ï—¤";--fa--fa:""}.fa-share-nodes{--fa:"";--fa--fa:""}.fa-share-alt{--fa:"";--fa--fa:""}.fa-heart-circle-minus{--fa:"î“¿";--fa--fa:"î“¿î“¿"}.fa-hourglass-half{--fa:"";--fa--fa:""}.fa-hourglass-2{--fa:"";--fa--fa:""}.fa-microscope{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-sink{--fa:"î­";--fa--fa:"î­î­"}.fa-bag-shopping{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-shopping-bag{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-arrow-down-z-a{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-sort-alpha-desc{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-sort-alpha-down-alt{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-mitten{--fa:"ïžµ";--fa--fa:""}.fa-person-rays{--fa:"î•";--fa--fa:"î•î•"}.fa-users{--fa:"";--fa--fa:""}.fa-eye-slash{--fa:"ï°";--fa--fa:"ï°ï°"}.fa-flask-vial{--fa:"";--fa--fa:""}.fa-hand{--fa:"";--fa--fa:""}.fa-hand-paper{--fa:"";--fa--fa:""}.fa-om{--fa:"";--fa--fa:""}.fa-worm{--fa:"î–™";--fa--fa:""}.fa-house-circle-xmark{--fa:"";--fa--fa:""}.fa-plug{--fa:"";--fa--fa:""}.fa-chevron-up{--fa:"ï·";--fa--fa:"ï·ï·"}.fa-hand-spock{--fa:"";--fa--fa:""}.fa-stopwatch{--fa:"";--fa--fa:""}.fa-face-kiss{--fa:"ï––";--fa--fa:"ï––ï––"}.fa-kiss{--fa:"ï––";--fa--fa:"ï––ï––"}.fa-bridge-circle-xmark{--fa:"î“‹";--fa--fa:"î“‹î“‹"}.fa-face-grin-tongue{--fa:"ï–‰";--fa--fa:""}.fa-grin-tongue{--fa:"ï–‰";--fa--fa:""}.fa-chess-bishop{--fa:"ïº";--fa--fa:"ïºïº"}.fa-face-grin-wink{--fa:"ï–Œ";--fa--fa:""}.fa-grin-wink{--fa:"ï–Œ";--fa--fa:""}.fa-ear-deaf{--fa:"";--fa--fa:""}.fa-deaf{--fa:"";--fa--fa:""}.fa-deafness{--fa:"";--fa--fa:""}.fa-hard-of-hearing{--fa:"";--fa--fa:""}.fa-road-circle-check{--fa:"";--fa--fa:""}.fa-dice-five{--fa:"";--fa--fa:""}.fa-square-rss{--fa:"ï…ƒ";--fa--fa:""}.fa-rss-square{--fa:"ï…ƒ";--fa--fa:""}.fa-land-mine-on{--fa:"î”›";--fa--fa:""}.fa-i-cursor{--fa:"";--fa--fa:""}.fa-stamp{--fa:"ï–¿";--fa--fa:"ï–¿ï–¿"}.fa-stairs{--fa:"";--fa--fa:""}.fa-i{--fa:"I";--fa--fa:"II"}.fa-hryvnia-sign{--fa:"";--fa--fa:""}.fa-hryvnia{--fa:"";--fa--fa:""}.fa-pills{--fa:"ï’„";--fa--fa:"ï’„ï’„"}.fa-face-grin-wide{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-grin-alt{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-tooth{--fa:"ï—‰";--fa--fa:""}.fa-v{--fa:"V";--fa--fa:"VV"}.fa-bangladeshi-taka-sign{--fa:"";--fa--fa:""}.fa-bicycle{--fa:"";--fa--fa:""}.fa-staff-snake{--fa:"";--fa--fa:""}.fa-rod-asclepius{--fa:"";--fa--fa:""}.fa-rod-snake{--fa:"";--fa--fa:""}.fa-staff-aesculapius{--fa:"";--fa--fa:""}.fa-head-side-cough-slash{--fa:"î¢";--fa--fa:"î¢î¢"}.fa-truck-medical{--fa:"";--fa--fa:""}.fa-ambulance{--fa:"";--fa--fa:""}.fa-wheat-awn-circle-exclamation{--fa:"î–˜";--fa--fa:""}.fa-snowman{--fa:"ïŸ";--fa--fa:"ïŸïŸ"}.fa-mortar-pestle{--fa:"ï–§";--fa--fa:""}.fa-road-barrier{--fa:"î•¢";--fa--fa:""}.fa-school{--fa:"";--fa--fa:""}.fa-igloo{--fa:"ïž®";--fa--fa:""}.fa-joint{--fa:"ï–•";--fa--fa:"ï–•ï–•"}.fa-angle-right{--fa:"ï„…";--fa--fa:"ï„…ï„…"}.fa-horse{--fa:"ï›°";--fa--fa:"ï›°ï›°"}.fa-q{--fa:"Q";--fa--fa:"QQ"}.fa-g{--fa:"G";--fa--fa:"GG"}.fa-notes-medical{--fa:"ï’";--fa--fa:"ï’ï’"}.fa-temperature-half{--fa:"";--fa--fa:""}.fa-temperature-2{--fa:"";--fa--fa:""}.fa-thermometer-2{--fa:"";--fa--fa:""}.fa-thermometer-half{--fa:"";--fa--fa:""}.fa-dong-sign{--fa:"î…©";--fa--fa:"î…©î…©"}.fa-capsules{--fa:"ï‘«";--fa--fa:"ï‘«ï‘«"}.fa-poo-storm{--fa:"ïš";--fa--fa:"ïšïš"}.fa-poo-bolt{--fa:"ïš";--fa--fa:"ïšïš"}.fa-face-frown-open{--fa:"";--fa--fa:""}.fa-frown-open{--fa:"";--fa--fa:""}.fa-hand-point-up{--fa:"";--fa--fa:""}.fa-money-bill{--fa:"";--fa--fa:""}.fa-bookmark{--fa:"";--fa--fa:""}.fa-align-justify{--fa:"";--fa--fa:""}.fa-umbrella-beach{--fa:"ï—Š";--fa--fa:"ï—Šï—Š"}.fa-helmet-un{--fa:"";--fa--fa:""}.fa-bullseye{--fa:"ï…€";--fa--fa:""}.fa-bacon{--fa:"";--fa--fa:""}.fa-hand-point-down{--fa:"";--fa--fa:""}.fa-arrow-up-from-bracket{--fa:"î‚š";--fa--fa:"î‚šî‚š"}.fa-folder{--fa:"ï»";--fa--fa:"ï»ï»"}.fa-folder-blank{--fa:"ï»";--fa--fa:"ï»ï»"}.fa-file-waveform{--fa:"";--fa--fa:""}.fa-file-medical-alt{--fa:"";--fa--fa:""}.fa-radiation{--fa:"ïž¹";--fa--fa:""}.fa-chart-simple{--fa:"";--fa--fa:""}.fa-mars-stroke{--fa:"";--fa--fa:""}.fa-vial{--fa:"ï’’";--fa--fa:"ï’’ï’’"}.fa-gauge{--fa:"";--fa--fa:""}.fa-dashboard{--fa:"";--fa--fa:""}.fa-gauge-med{--fa:"";--fa--fa:""}.fa-tachometer-alt-average{--fa:"";--fa--fa:""}.fa-wand-magic-sparkles{--fa:"î‹Š";--fa--fa:"î‹Šî‹Š"}.fa-magic-wand-sparkles{--fa:"î‹Š";--fa--fa:"î‹Šî‹Š"}.fa-e{--fa:"E";--fa--fa:"EE"}.fa-pen-clip{--fa:"";--fa--fa:""}.fa-pen-alt{--fa:"";--fa--fa:""}.fa-bridge-circle-exclamation{--fa:"î“Š";--fa--fa:"î“Šî“Š"}.fa-user{--fa:"";--fa--fa:""}.fa-school-circle-check{--fa:"î•«";--fa--fa:"î•«î•«"}.fa-dumpster{--fa:"ïž“";--fa--fa:"ïž“ïž“"}.fa-van-shuttle{--fa:"ï–¶";--fa--fa:""}.fa-shuttle-van{--fa:"ï–¶";--fa--fa:""}.fa-building-user{--fa:"î“š";--fa--fa:"î“šî“š"}.fa-square-caret-left{--fa:"";--fa--fa:""}.fa-caret-square-left{--fa:"";--fa--fa:""}.fa-highlighter{--fa:"ï–‘";--fa--fa:"ï–‘ï–‘"}.fa-key{--fa:"ï‚„";--fa--fa:"ï‚„ï‚„"}.fa-bullhorn{--fa:"ï‚¡";--fa--fa:"ï‚¡ï‚¡"}.fa-globe{--fa:"";--fa--fa:""}.fa-synagogue{--fa:"ïš›";--fa--fa:""}.fa-person-half-dress{--fa:"";--fa--fa:""}.fa-road-bridge{--fa:"î•£";--fa--fa:""}.fa-location-arrow{--fa:"";--fa--fa:""}.fa-c{--fa:"C";--fa--fa:"CC"}.fa-tablet-button{--fa:"ï„Š";--fa--fa:"ï„Šï„Š"}.fa-building-lock{--fa:"î“–";--fa--fa:"î“–î“–"}.fa-pizza-slice{--fa:"ï ˜";--fa--fa:""}.fa-money-bill-wave{--fa:"";--fa--fa:""}.fa-chart-area{--fa:"";--fa--fa:""}.fa-area-chart{--fa:"";--fa--fa:""}.fa-house-flag{--fa:"î”";--fa--fa:"î”î”"}.fa-person-circle-minus{--fa:"î•€";--fa--fa:""}.fa-ban{--fa:"ïž";--fa--fa:"ïžïž"}.fa-cancel{--fa:"ïž";--fa--fa:"ïžïž"}.fa-camera-rotate{--fa:"";--fa--fa:""}.fa-spray-can-sparkles{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-air-freshener{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-star{--fa:"";--fa--fa:""}.fa-repeat{--fa:"ï£";--fa--fa:"ï£ï£"}.fa-cross{--fa:"ï™”";--fa--fa:""}.fa-box{--fa:"";--fa--fa:""}.fa-venus-mars{--fa:"";--fa--fa:""}.fa-arrow-pointer{--fa:"";--fa--fa:""}.fa-mouse-pointer{--fa:"";--fa--fa:""}.fa-maximize{--fa:"";--fa--fa:""}.fa-expand-arrows-alt{--fa:"";--fa--fa:""}.fa-charging-station{--fa:"ï—§";--fa--fa:""}.fa-shapes{--fa:"";--fa--fa:""}.fa-triangle-circle-square{--fa:"";--fa--fa:""}.fa-shuffle{--fa:"ï´";--fa--fa:"ï´ï´"}.fa-random{--fa:"ï´";--fa--fa:"ï´ï´"}.fa-person-running{--fa:"";--fa--fa:""}.fa-running{--fa:"";--fa--fa:""}.fa-mobile-retro{--fa:"";--fa--fa:""}.fa-grip-lines-vertical{--fa:"";--fa--fa:""}.fa-spider{--fa:"";--fa--fa:""}.fa-hands-bound{--fa:"";--fa--fa:""}.fa-file-invoice-dollar{--fa:"";--fa--fa:""}.fa-plane-circle-exclamation{--fa:"î•–";--fa--fa:"î•–î•–"}.fa-x-ray{--fa:"ï’—";--fa--fa:"ï’—ï’—"}.fa-spell-check{--fa:"";--fa--fa:""}.fa-slash{--fa:"";--fa--fa:""}.fa-computer-mouse{--fa:"";--fa--fa:""}.fa-mouse{--fa:"";--fa--fa:""}.fa-arrow-right-to-bracket{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-sign-in{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-shop-slash{--fa:"î°";--fa--fa:"î°î°"}.fa-store-alt-slash{--fa:"î°";--fa--fa:"î°î°"}.fa-server{--fa:"";--fa--fa:""}.fa-virus-covid-slash{--fa:"î’©";--fa--fa:"î’©î’©"}.fa-shop-lock{--fa:"î’¥";--fa--fa:""}.fa-hourglass-start{--fa:"";--fa--fa:""}.fa-hourglass-1{--fa:"";--fa--fa:""}.fa-blender-phone{--fa:"";--fa--fa:""}.fa-building-wheat{--fa:"î“›";--fa--fa:""}.fa-person-breastfeeding{--fa:"";--fa--fa:""}.fa-right-to-bracket{--fa:"";--fa--fa:""}.fa-sign-in-alt{--fa:"";--fa--fa:""}.fa-venus{--fa:"";--fa--fa:""}.fa-passport{--fa:"ï–«";--fa--fa:"ï–«ï–«"}.fa-thumbtack-slash{--fa:"îš";--fa--fa:"îšîš"}.fa-thumb-tack-slash{--fa:"îš";--fa--fa:"îšîš"}.fa-heart-pulse{--fa:"";--fa--fa:""}.fa-heartbeat{--fa:"";--fa--fa:""}.fa-people-carry-box{--fa:"ï“Ž";--fa--fa:"ï“Žï“Ž"}.fa-people-carry{--fa:"ï“Ž";--fa--fa:"ï“Žï“Ž"}.fa-temperature-high{--fa:"ï©";--fa--fa:"ï©ï©"}.fa-microchip{--fa:"ï‹›";--fa--fa:""}.fa-crown{--fa:"";--fa--fa:""}.fa-weight-hanging{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-xmarks-lines{--fa:"î–š";--fa--fa:"î–šî–š"}.fa-file-prescription{--fa:"";--fa--fa:""}.fa-weight-scale{--fa:"ï’–";--fa--fa:"ï’–ï’–"}.fa-weight{--fa:"ï’–";--fa--fa:"ï’–ï’–"}.fa-user-group{--fa:"";--fa--fa:""}.fa-user-friends{--fa:"";--fa--fa:""}.fa-arrow-up-a-z{--fa:"ï…ž";--fa--fa:"ï…žï…ž"}.fa-sort-alpha-up{--fa:"ï…ž";--fa--fa:"ï…žï…ž"}.fa-chess-knight{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-face-laugh-squint{--fa:"ï–›";--fa--fa:""}.fa-laugh-squint{--fa:"ï–›";--fa--fa:""}.fa-wheelchair{--fa:"";--fa--fa:""}.fa-circle-arrow-up{--fa:"";--fa--fa:""}.fa-arrow-circle-up{--fa:"";--fa--fa:""}.fa-toggle-on{--fa:"";--fa--fa:""}.fa-person-walking{--fa:"ï•”";--fa--fa:""}.fa-walking{--fa:"ï•”";--fa--fa:""}.fa-l{--fa:"L";--fa--fa:"LL"}.fa-fire{--fa:"ï­";--fa--fa:"ï­ï­"}.fa-bed-pulse{--fa:"ï’‡";--fa--fa:""}.fa-procedures{--fa:"ï’‡";--fa--fa:""}.fa-shuttle-space{--fa:"";--fa--fa:""}.fa-space-shuttle{--fa:"";--fa--fa:""}.fa-face-laugh{--fa:"ï–™";--fa--fa:""}.fa-laugh{--fa:"ï–™";--fa--fa:""}.fa-folder-open{--fa:"ï¼";--fa--fa:"ï¼ï¼"}.fa-heart-circle-plus{--fa:"";--fa--fa:""}.fa-code-fork{--fa:"î„»";--fa--fa:""}.fa-city{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-microphone-lines{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-microphone-alt{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-pepper-hot{--fa:"ï –";--fa--fa:"ï –ï –"}.fa-unlock{--fa:"ï‚œ";--fa--fa:""}.fa-colon-sign{--fa:"î…€";--fa--fa:""}.fa-headset{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-store-slash{--fa:"î±";--fa--fa:"î±î±"}.fa-road-circle-xmark{--fa:"";--fa--fa:""}.fa-user-minus{--fa:"";--fa--fa:""}.fa-mars-stroke-up{--fa:"";--fa--fa:""}.fa-mars-stroke-v{--fa:"";--fa--fa:""}.fa-champagne-glasses{--fa:"";--fa--fa:""}.fa-glass-cheers{--fa:"";--fa--fa:""}.fa-clipboard{--fa:"";--fa--fa:""}.fa-house-circle-exclamation{--fa:"";--fa--fa:""}.fa-file-arrow-up{--fa:"ï•´";--fa--fa:"ï•´ï•´"}.fa-file-upload{--fa:"ï•´";--fa--fa:"ï•´ï•´"}.fa-wifi{--fa:"";--fa--fa:""}.fa-wifi-3{--fa:"";--fa--fa:""}.fa-wifi-strong{--fa:"";--fa--fa:""}.fa-bath{--fa:"ï‹";--fa--fa:"ï‹ï‹"}.fa-bathtub{--fa:"ï‹";--fa--fa:"ï‹ï‹"}.fa-underline{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-user-pen{--fa:"ï“¿";--fa--fa:"ï“¿ï“¿"}.fa-user-edit{--fa:"ï“¿";--fa--fa:"ï“¿ï“¿"}.fa-signature{--fa:"ï–·";--fa--fa:"ï–·ï–·"}.fa-stroopwafel{--fa:"ï•‘";--fa--fa:"ï•‘ï•‘"}.fa-bold{--fa:"";--fa--fa:""}.fa-anchor-lock{--fa:"î’­";--fa--fa:"î’­î’­"}.fa-building-ngo{--fa:"î“—";--fa--fa:"î“—î“—"}.fa-manat-sign{--fa:"";--fa--fa:""}.fa-not-equal{--fa:"";--fa--fa:""}.fa-border-top-left{--fa:"ï¡“";--fa--fa:"ï¡“ï¡“"}.fa-border-style{--fa:"ï¡“";--fa--fa:"ï¡“ï¡“"}.fa-map-location-dot{--fa:"ï– ";--fa--fa:"ï– ï– "}.fa-map-marked-alt{--fa:"ï– ";--fa--fa:"ï– ï– "}.fa-jedi{--fa:"";--fa--fa:""}.fa-square-poll-vertical{--fa:"ïš";--fa--fa:"ïšïš"}.fa-poll{--fa:"ïš";--fa--fa:"ïšïš"}.fa-mug-hot{--fa:"";--fa--fa:""}.fa-car-battery{--fa:"ï—Ÿ";--fa--fa:"ï—Ÿï—Ÿ"}.fa-battery-car{--fa:"ï—Ÿ";--fa--fa:"ï—Ÿï—Ÿ"}.fa-gift{--fa:"ï«";--fa--fa:"ï«ï«"}.fa-dice-two{--fa:"";--fa--fa:""}.fa-chess-queen{--fa:"ï‘…";--fa--fa:"ï‘…ï‘…"}.fa-glasses{--fa:"ï”°";--fa--fa:"ï”°ï”°"}.fa-chess-board{--fa:"ï¼";--fa--fa:"ï¼ï¼"}.fa-building-circle-check{--fa:"î“’";--fa--fa:"î“’î“’"}.fa-person-chalkboard{--fa:"";--fa--fa:""}.fa-mars-stroke-right{--fa:"";--fa--fa:""}.fa-mars-stroke-h{--fa:"";--fa--fa:""}.fa-hand-back-fist{--fa:"";--fa--fa:""}.fa-hand-rock{--fa:"";--fa--fa:""}.fa-square-caret-up{--fa:"ï…‘";--fa--fa:"ï…‘ï…‘"}.fa-caret-square-up{--fa:"ï…‘";--fa--fa:"ï…‘ï…‘"}.fa-cloud-showers-water{--fa:"";--fa--fa:""}.fa-chart-bar{--fa:"ï‚€";--fa--fa:""}.fa-bar-chart{--fa:"ï‚€";--fa--fa:""}.fa-hands-bubbles{--fa:"îž";--fa--fa:"îžîž"}.fa-hands-wash{--fa:"îž";--fa--fa:"îžîž"}.fa-less-than-equal{--fa:"ï”·";--fa--fa:"ï”·ï”·"}.fa-train{--fa:"";--fa--fa:""}.fa-eye-low-vision{--fa:"";--fa--fa:""}.fa-low-vision{--fa:"";--fa--fa:""}.fa-crow{--fa:"ï” ";--fa--fa:"ï” ï” "}.fa-sailboat{--fa:"î‘…";--fa--fa:"î‘…î‘…"}.fa-window-restore{--fa:"ï‹’";--fa--fa:"ï‹’ï‹’"}.fa-square-plus{--fa:"";--fa--fa:""}.fa-plus-square{--fa:"";--fa--fa:""}.fa-torii-gate{--fa:"ïš¡";--fa--fa:"ïš¡ïš¡"}.fa-frog{--fa:"ï”®";--fa--fa:""}.fa-bucket{--fa:"î“";--fa--fa:"î“î“"}.fa-image{--fa:"";--fa--fa:""}.fa-microphone{--fa:"ï„°";--fa--fa:"ï„°ï„°"}.fa-cow{--fa:"";--fa--fa:""}.fa-caret-up{--fa:"";--fa--fa:""}.fa-screwdriver{--fa:"ï•Š";--fa--fa:"ï•Šï•Š"}.fa-folder-closed{--fa:"";--fa--fa:""}.fa-house-tsunami{--fa:"";--fa--fa:""}.fa-square-nfi{--fa:"";--fa--fa:""}.fa-arrow-up-from-ground-water{--fa:"î’µ";--fa--fa:""}.fa-martini-glass{--fa:"ï•»";--fa--fa:""}.fa-glass-martini-alt{--fa:"ï•»";--fa--fa:""}.fa-square-binary{--fa:"îš›";--fa--fa:""}.fa-rotate-left{--fa:"";--fa--fa:""}.fa-rotate-back{--fa:"";--fa--fa:""}.fa-rotate-backward{--fa:"";--fa--fa:""}.fa-undo-alt{--fa:"";--fa--fa:""}.fa-table-columns{--fa:"";--fa--fa:""}.fa-columns{--fa:"";--fa--fa:""}.fa-lemon{--fa:"ï‚”";--fa--fa:""}.fa-head-side-mask{--fa:"î£";--fa--fa:"î£î£"}.fa-handshake{--fa:"";--fa--fa:""}.fa-gem{--fa:"";--fa--fa:""}.fa-dolly{--fa:"";--fa--fa:""}.fa-dolly-box{--fa:"";--fa--fa:""}.fa-smoking{--fa:"ï’";--fa--fa:"ï’ï’"}.fa-minimize{--fa:"";--fa--fa:""}.fa-compress-arrows-alt{--fa:"";--fa--fa:""}.fa-monument{--fa:"ï–¦";--fa--fa:""}.fa-snowplow{--fa:"";--fa--fa:""}.fa-angles-right{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-angle-double-right{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-cannabis{--fa:"ï•Ÿ";--fa--fa:"ï•Ÿï•Ÿ"}.fa-circle-play{--fa:"ï…„";--fa--fa:"ï…„ï…„"}.fa-play-circle{--fa:"ï…„";--fa--fa:"ï…„ï…„"}.fa-tablets{--fa:"ï’";--fa--fa:"ï’ï’"}.fa-ethernet{--fa:"ïž–";--fa--fa:"ïž–ïž–"}.fa-euro-sign{--fa:"ï…“";--fa--fa:"ï…“ï…“"}.fa-eur{--fa:"ï…“";--fa--fa:"ï…“ï…“"}.fa-euro{--fa:"ï…“";--fa--fa:"ï…“ï…“"}.fa-chair{--fa:"";--fa--fa:""}.fa-circle-check{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-check-circle{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-circle-stop{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-stop-circle{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-compass-drafting{--fa:"";--fa--fa:""}.fa-drafting-compass{--fa:"";--fa--fa:""}.fa-plate-wheat{--fa:"î•š";--fa--fa:"î•šî•š"}.fa-icicles{--fa:"ïž­";--fa--fa:"ïž­ïž­"}.fa-person-shelter{--fa:"î•";--fa--fa:"î•î•"}.fa-neuter{--fa:"";--fa--fa:""}.fa-id-badge{--fa:"ï‹";--fa--fa:"ï‹ï‹"}.fa-marker{--fa:"ï–¡";--fa--fa:"ï–¡ï–¡"}.fa-face-laugh-beam{--fa:"ï–š";--fa--fa:"ï–šï–š"}.fa-laugh-beam{--fa:"ï–š";--fa--fa:"ï–šï–š"}.fa-helicopter-symbol{--fa:"";--fa--fa:""}.fa-universal-access{--fa:"";--fa--fa:""}.fa-circle-chevron-up{--fa:"";--fa--fa:""}.fa-chevron-circle-up{--fa:"";--fa--fa:""}.fa-lari-sign{--fa:"";--fa--fa:""}.fa-volcano{--fa:"ï°";--fa--fa:"ï°ï°"}.fa-person-walking-dashed-line-arrow-right{--fa:"î•“";--fa--fa:"î•“î•“"}.fa-sterling-sign{--fa:"ï…”";--fa--fa:""}.fa-gbp{--fa:"ï…”";--fa--fa:""}.fa-pound-sign{--fa:"ï…”";--fa--fa:""}.fa-viruses{--fa:"î¶";--fa--fa:"î¶î¶"}.fa-square-person-confined{--fa:"î•·";--fa--fa:"î•·î•·"}.fa-user-tie{--fa:"";--fa--fa:""}.fa-arrow-down-long{--fa:"ï…µ";--fa--fa:""}.fa-long-arrow-down{--fa:"ï…µ";--fa--fa:""}.fa-tent-arrow-down-to-line{--fa:"";--fa--fa:""}.fa-certificate{--fa:"ï‚£";--fa--fa:""}.fa-reply-all{--fa:"ï„¢";--fa--fa:""}.fa-mail-reply-all{--fa:"ï„¢";--fa--fa:""}.fa-suitcase{--fa:"";--fa--fa:""}.fa-person-skating{--fa:"";--fa--fa:""}.fa-skating{--fa:"";--fa--fa:""}.fa-filter-circle-dollar{--fa:"";--fa--fa:""}.fa-funnel-dollar{--fa:"";--fa--fa:""}.fa-camera-retro{--fa:"";--fa--fa:""}.fa-circle-arrow-down{--fa:"ï‚«";--fa--fa:"ï‚«ï‚«"}.fa-arrow-circle-down{--fa:"ï‚«";--fa--fa:"ï‚«ï‚«"}.fa-file-import{--fa:"";--fa--fa:""}.fa-arrow-right-to-file{--fa:"";--fa--fa:""}.fa-square-arrow-up-right{--fa:"ï…Œ";--fa--fa:""}.fa-external-link-square{--fa:"ï…Œ";--fa--fa:""}.fa-box-open{--fa:"ï’ž";--fa--fa:"ï’žï’ž"}.fa-scroll{--fa:"";--fa--fa:""}.fa-spa{--fa:"ï–»";--fa--fa:""}.fa-location-pin-lock{--fa:"";--fa--fa:""}.fa-pause{--fa:"ïŒ";--fa--fa:"ïŒïŒ"}.fa-hill-avalanche{--fa:"";--fa--fa:""}.fa-temperature-empty{--fa:"ï‹‹";--fa--fa:"ï‹‹ï‹‹"}.fa-temperature-0{--fa:"ï‹‹";--fa--fa:"ï‹‹ï‹‹"}.fa-thermometer-0{--fa:"ï‹‹";--fa--fa:"ï‹‹ï‹‹"}.fa-thermometer-empty{--fa:"ï‹‹";--fa--fa:"ï‹‹ï‹‹"}.fa-bomb{--fa:"";--fa--fa:""}.fa-registered{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-address-card{--fa:"";--fa--fa:""}.fa-contact-card{--fa:"";--fa--fa:""}.fa-vcard{--fa:"";--fa--fa:""}.fa-scale-unbalanced-flip{--fa:"ï”–";--fa--fa:"ï”–ï”–"}.fa-balance-scale-right{--fa:"ï”–";--fa--fa:"ï”–ï”–"}.fa-subscript{--fa:"";--fa--fa:""}.fa-diamond-turn-right{--fa:"ï—«";--fa--fa:"ï—«ï—«"}.fa-directions{--fa:"ï—«";--fa--fa:"ï—«ï—«"}.fa-burst{--fa:"î“œ";--fa--fa:""}.fa-house-laptop{--fa:"î¦";--fa--fa:"î¦î¦"}.fa-laptop-house{--fa:"î¦";--fa--fa:"î¦î¦"}.fa-face-tired{--fa:"ï—ˆ";--fa--fa:""}.fa-tired{--fa:"ï—ˆ";--fa--fa:""}.fa-money-bills{--fa:"";--fa--fa:""}.fa-smog{--fa:"ïŸ";--fa--fa:"ïŸïŸ"}.fa-crutch{--fa:"";--fa--fa:""}.fa-cloud-arrow-up{--fa:"";--fa--fa:""}.fa-cloud-upload{--fa:"";--fa--fa:""}.fa-cloud-upload-alt{--fa:"";--fa--fa:""}.fa-palette{--fa:"";--fa--fa:""}.fa-arrows-turn-right{--fa:"î“€";--fa--fa:""}.fa-vest{--fa:"î‚…";--fa--fa:"î‚…î‚…"}.fa-ferry{--fa:"";--fa--fa:""}.fa-arrows-down-to-people{--fa:"î’¹";--fa--fa:""}.fa-seedling{--fa:"";--fa--fa:""}.fa-sprout{--fa:"";--fa--fa:""}.fa-left-right{--fa:"";--fa--fa:""}.fa-arrows-alt-h{--fa:"";--fa--fa:""}.fa-boxes-packing{--fa:"";--fa--fa:""}.fa-circle-arrow-left{--fa:"";--fa--fa:""}.fa-arrow-circle-left{--fa:"";--fa--fa:""}.fa-group-arrows-rotate{--fa:"";--fa--fa:""}.fa-bowl-food{--fa:"";--fa--fa:""}.fa-candy-cane{--fa:"";--fa--fa:""}.fa-arrow-down-wide-short{--fa:"ï… ";--fa--fa:"ï… ï… "}.fa-sort-amount-asc{--fa:"ï… ";--fa--fa:"ï… ï… "}.fa-sort-amount-down{--fa:"ï… ";--fa--fa:"ï… ï… "}.fa-cloud-bolt{--fa:"ï¬";--fa--fa:"ï¬ï¬"}.fa-thunderstorm{--fa:"ï¬";--fa--fa:"ï¬ï¬"}.fa-text-slash{--fa:"";--fa--fa:""}.fa-remove-format{--fa:"";--fa--fa:""}.fa-face-smile-wink{--fa:"ï“š";--fa--fa:"ï“šï“š"}.fa-smile-wink{--fa:"ï“š";--fa--fa:"ï“šï“š"}.fa-file-word{--fa:"";--fa--fa:""}.fa-file-powerpoint{--fa:"";--fa--fa:""}.fa-arrows-left-right{--fa:"ï¾";--fa--fa:"ï¾ï¾"}.fa-arrows-h{--fa:"ï¾";--fa--fa:"ï¾ï¾"}.fa-house-lock{--fa:"î”";--fa--fa:"î”î”"}.fa-cloud-arrow-down{--fa:"";--fa--fa:""}.fa-cloud-download{--fa:"";--fa--fa:""}.fa-cloud-download-alt{--fa:"";--fa--fa:""}.fa-children{--fa:"î“¡";--fa--fa:"î“¡î“¡"}.fa-chalkboard{--fa:"ï”›";--fa--fa:""}.fa-blackboard{--fa:"ï”›";--fa--fa:""}.fa-user-large-slash{--fa:"";--fa--fa:""}.fa-user-alt-slash{--fa:"";--fa--fa:""}.fa-envelope-open{--fa:"";--fa--fa:""}.fa-handshake-simple-slash{--fa:"îŸ";--fa--fa:"îŸîŸ"}.fa-handshake-alt-slash{--fa:"îŸ";--fa--fa:"îŸîŸ"}.fa-mattress-pillow{--fa:"";--fa--fa:""}.fa-guarani-sign{--fa:"";--fa--fa:""}.fa-arrows-rotate{--fa:"";--fa--fa:""}.fa-refresh{--fa:"";--fa--fa:""}.fa-sync{--fa:"";--fa--fa:""}.fa-fire-extinguisher{--fa:"ï„´";--fa--fa:"ï„´ï„´"}.fa-cruzeiro-sign{--fa:"î…’";--fa--fa:"î…’î…’"}.fa-greater-than-equal{--fa:"";--fa--fa:""}.fa-shield-halved{--fa:"ï­";--fa--fa:"ï­ï­"}.fa-shield-alt{--fa:"ï­";--fa--fa:"ï­ï­"}.fa-book-atlas{--fa:"";--fa--fa:""}.fa-atlas{--fa:"";--fa--fa:""}.fa-virus{--fa:"î´";--fa--fa:"î´î´"}.fa-envelope-circle-check{--fa:"";--fa--fa:""}.fa-layer-group{--fa:"ï—½";--fa--fa:""}.fa-arrows-to-dot{--fa:"î’¾";--fa--fa:""}.fa-archway{--fa:"ï•—";--fa--fa:"ï•—ï•—"}.fa-heart-circle-check{--fa:"";--fa--fa:""}.fa-house-chimney-crack{--fa:"ï›±";--fa--fa:""}.fa-house-damage{--fa:"ï›±";--fa--fa:""}.fa-file-zipper{--fa:"";--fa--fa:""}.fa-file-archive{--fa:"";--fa--fa:""}.fa-square{--fa:"";--fa--fa:""}.fa-martini-glass-empty{--fa:"";--fa--fa:""}.fa-glass-martini{--fa:"";--fa--fa:""}.fa-couch{--fa:"ï’¸";--fa--fa:""}.fa-cedi-sign{--fa:"";--fa--fa:""}.fa-italic{--fa:"";--fa--fa:""}.fa-table-cells-column-lock{--fa:"";--fa--fa:""}.fa-church{--fa:"ï”";--fa--fa:"ï”ï”"}.fa-comments-dollar{--fa:"";--fa--fa:""}.fa-democrat{--fa:"ï‡";--fa--fa:"ï‡ï‡"}.fa-z{--fa:"Z";--fa--fa:"ZZ"}.fa-person-skiing{--fa:"";--fa--fa:""}.fa-skiing{--fa:"";--fa--fa:""}.fa-road-lock{--fa:"";--fa--fa:""}.fa-a{--fa:"A";--fa--fa:"AA"}.fa-temperature-arrow-down{--fa:"";--fa--fa:""}.fa-temperature-down{--fa:"";--fa--fa:""}.fa-feather-pointed{--fa:"ï•«";--fa--fa:"ï•«ï•«"}.fa-feather-alt{--fa:"ï•«";--fa--fa:"ï•«ï•«"}.fa-p{--fa:"P";--fa--fa:"PP"}.fa-snowflake{--fa:"ï‹œ";--fa--fa:""}.fa-newspaper{--fa:"";--fa--fa:""}.fa-rectangle-ad{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-ad{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-circle-arrow-right{--fa:"ï‚©";--fa--fa:"ï‚©ï‚©"}.fa-arrow-circle-right{--fa:"ï‚©";--fa--fa:"ï‚©ï‚©"}.fa-filter-circle-xmark{--fa:"î…»";--fa--fa:""}.fa-locust{--fa:"î” ";--fa--fa:"î” î” "}.fa-sort{--fa:"";--fa--fa:""}.fa-unsorted{--fa:"";--fa--fa:""}.fa-list-ol{--fa:"";--fa--fa:""}.fa-list-1-2{--fa:"";--fa--fa:""}.fa-list-numeric{--fa:"";--fa--fa:""}.fa-person-dress-burst{--fa:"î•„";--fa--fa:"î•„î•„"}.fa-money-check-dollar{--fa:"";--fa--fa:""}.fa-money-check-alt{--fa:"";--fa--fa:""}.fa-vector-square{--fa:"ï—‹";--fa--fa:"ï—‹ï—‹"}.fa-bread-slice{--fa:"";--fa--fa:""}.fa-language{--fa:"";--fa--fa:""}.fa-face-kiss-wink-heart{--fa:"ï–˜";--fa--fa:""}.fa-kiss-wink-heart{--fa:"ï–˜";--fa--fa:""}.fa-filter{--fa:"ï‚°";--fa--fa:"ï‚°ï‚°"}.fa-question{--fa:"\?";--fa--fa:"\?\?"}.fa-file-signature{--fa:"";--fa--fa:""}.fa-up-down-left-right{--fa:"";--fa--fa:""}.fa-arrows-alt{--fa:"";--fa--fa:""}.fa-house-chimney-user{--fa:"î¥";--fa--fa:"î¥î¥"}.fa-hand-holding-heart{--fa:"ï’¾";--fa--fa:""}.fa-puzzle-piece{--fa:"ï„®";--fa--fa:""}.fa-money-check{--fa:"";--fa--fa:""}.fa-star-half-stroke{--fa:"ï—€";--fa--fa:""}.fa-star-half-alt{--fa:"ï—€";--fa--fa:""}.fa-code{--fa:"ï„¡";--fa--fa:"ï„¡ï„¡"}.fa-whiskey-glass{--fa:"ïž ";--fa--fa:"ïž ïž "}.fa-glass-whiskey{--fa:"ïž ";--fa--fa:"ïž ïž "}.fa-building-circle-exclamation{--fa:"î““";--fa--fa:"î““î““"}.fa-magnifying-glass-chart{--fa:"";--fa--fa:""}.fa-arrow-up-right-from-square{--fa:"ï‚Ž";--fa--fa:"ï‚Žï‚Ž"}.fa-external-link{--fa:"ï‚Ž";--fa--fa:"ï‚Žï‚Ž"}.fa-cubes-stacked{--fa:"";--fa--fa:""}.fa-won-sign{--fa:"ï…™";--fa--fa:""}.fa-krw{--fa:"ï…™";--fa--fa:""}.fa-won{--fa:"ï…™";--fa--fa:""}.fa-virus-covid{--fa:"î’¨";--fa--fa:""}.fa-austral-sign{--fa:"î‚©";--fa--fa:"î‚©î‚©"}.fa-f{--fa:"F";--fa--fa:"FF"}.fa-leaf{--fa:"ï¬";--fa--fa:"ï¬ï¬"}.fa-road{--fa:"";--fa--fa:""}.fa-taxi{--fa:"";--fa--fa:""}.fa-cab{--fa:"";--fa--fa:""}.fa-person-circle-plus{--fa:"î•";--fa--fa:"î•î•"}.fa-chart-pie{--fa:"";--fa--fa:""}.fa-pie-chart{--fa:"";--fa--fa:""}.fa-bolt-lightning{--fa:"î‚·";--fa--fa:"î‚·î‚·"}.fa-sack-xmark{--fa:"";--fa--fa:""}.fa-file-excel{--fa:"";--fa--fa:""}.fa-file-contract{--fa:"";--fa--fa:""}.fa-fish-fins{--fa:"";--fa--fa:""}.fa-building-flag{--fa:"î“•";--fa--fa:"î“•î“•"}.fa-face-grin-beam{--fa:"ï–‚";--fa--fa:"ï–‚ï–‚"}.fa-grin-beam{--fa:"ï–‚";--fa--fa:"ï–‚ï–‚"}.fa-object-ungroup{--fa:"";--fa--fa:""}.fa-poop{--fa:"";--fa--fa:""}.fa-location-pin{--fa:"ï";--fa--fa:"ïï"}.fa-map-marker{--fa:"ï";--fa--fa:"ïï"}.fa-kaaba{--fa:"";--fa--fa:""}.fa-toilet-paper{--fa:"";--fa--fa:""}.fa-helmet-safety{--fa:"ï ‡";--fa--fa:""}.fa-hard-hat{--fa:"ï ‡";--fa--fa:""}.fa-hat-hard{--fa:"ï ‡";--fa--fa:""}.fa-eject{--fa:"ï’";--fa--fa:"ï’ï’"}.fa-circle-right{--fa:"ïš";--fa--fa:"ïšïš"}.fa-arrow-alt-circle-right{--fa:"ïš";--fa--fa:"ïšïš"}.fa-plane-circle-check{--fa:"î••";--fa--fa:"î••î••"}.fa-face-rolling-eyes{--fa:"ï–¥";--fa--fa:""}.fa-meh-rolling-eyes{--fa:"ï–¥";--fa--fa:""}.fa-object-group{--fa:"";--fa--fa:""}.fa-chart-line{--fa:"ïˆ";--fa--fa:"ïˆïˆ"}.fa-line-chart{--fa:"ïˆ";--fa--fa:"ïˆïˆ"}.fa-mask-ventilator{--fa:"";--fa--fa:""}.fa-arrow-right{--fa:"ï¡";--fa--fa:"ï¡ï¡"}.fa-signs-post{--fa:"";--fa--fa:""}.fa-map-signs{--fa:"";--fa--fa:""}.fa-cash-register{--fa:"";--fa--fa:""}.fa-person-circle-question{--fa:"î•‚";--fa--fa:"î•‚î•‚"}.fa-h{--fa:"H";--fa--fa:"HH"}.fa-tarp{--fa:"î•»";--fa--fa:""}.fa-screwdriver-wrench{--fa:"";--fa--fa:""}.fa-tools{--fa:"";--fa--fa:""}.fa-arrows-to-eye{--fa:"î’¿";--fa--fa:"î’¿î’¿"}.fa-plug-circle-bolt{--fa:"î•›";--fa--fa:""}.fa-heart{--fa:"";--fa--fa:""}.fa-mars-and-venus{--fa:"";--fa--fa:""}.fa-house-user{--fa:"";--fa--fa:""}.fa-home-user{--fa:"";--fa--fa:""}.fa-dumpster-fire{--fa:"ïž”";--fa--fa:""}.fa-house-crack{--fa:"";--fa--fa:""}.fa-martini-glass-citrus{--fa:"ï•¡";--fa--fa:"ï•¡ï•¡"}.fa-cocktail{--fa:"ï•¡";--fa--fa:"ï•¡ï•¡"}.fa-face-surprise{--fa:"ï—‚";--fa--fa:"ï—‚ï—‚"}.fa-surprise{--fa:"ï—‚";--fa--fa:"ï—‚ï—‚"}.fa-bottle-water{--fa:"î“…";--fa--fa:"î“…î“…"}.fa-circle-pause{--fa:"";--fa--fa:""}.fa-pause-circle{--fa:"";--fa--fa:""}.fa-toilet-paper-slash{--fa:"î²";--fa--fa:"î²î²"}.fa-apple-whole{--fa:"ï—‘";--fa--fa:"ï—‘ï—‘"}.fa-apple-alt{--fa:"ï—‘";--fa--fa:"ï—‘ï—‘"}.fa-kitchen-set{--fa:"";--fa--fa:""}.fa-r{--fa:"R";--fa--fa:"RR"}.fa-temperature-quarter{--fa:"ï‹Š";--fa--fa:"ï‹Šï‹Š"}.fa-temperature-1{--fa:"ï‹Š";--fa--fa:"ï‹Šï‹Š"}.fa-thermometer-1{--fa:"ï‹Š";--fa--fa:"ï‹Šï‹Š"}.fa-thermometer-quarter{--fa:"ï‹Š";--fa--fa:"ï‹Šï‹Š"}.fa-cube{--fa:"";--fa--fa:""}.fa-bitcoin-sign{--fa:"î‚´";--fa--fa:"î‚´î‚´"}.fa-shield-dog{--fa:"";--fa--fa:""}.fa-solar-panel{--fa:"ï–º";--fa--fa:""}.fa-lock-open{--fa:"ï";--fa--fa:"ïï"}.fa-elevator{--fa:"î…­";--fa--fa:"î…­î…­"}.fa-money-bill-transfer{--fa:"";--fa--fa:""}.fa-money-bill-trend-up{--fa:"";--fa--fa:""}.fa-house-flood-water-circle-arrow-right{--fa:"î”";--fa--fa:"î”î”"}.fa-square-poll-horizontal{--fa:"ïš‚";--fa--fa:"ïš‚ïš‚"}.fa-poll-h{--fa:"ïš‚";--fa--fa:"ïš‚ïš‚"}.fa-circle{--fa:"ï„‘";--fa--fa:"ï„‘ï„‘"}.fa-backward-fast{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-fast-backward{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-recycle{--fa:"";--fa--fa:""}.fa-user-astronaut{--fa:"ï“»";--fa--fa:""}.fa-plane-slash{--fa:"î©";--fa--fa:"î©î©"}.fa-trademark{--fa:"";--fa--fa:""}.fa-basketball{--fa:"ï´";--fa--fa:"ï´ï´"}.fa-basketball-ball{--fa:"ï´";--fa--fa:"ï´ï´"}.fa-satellite-dish{--fa:"";--fa--fa:""}.fa-circle-up{--fa:"ï›";--fa--fa:"ï›ï›"}.fa-arrow-alt-circle-up{--fa:"ï›";--fa--fa:"ï›ï›"}.fa-mobile-screen-button{--fa:"ï";--fa--fa:"ïï"}.fa-mobile-alt{--fa:"ï";--fa--fa:"ïï"}.fa-volume-high{--fa:"";--fa--fa:""}.fa-volume-up{--fa:"";--fa--fa:""}.fa-users-rays{--fa:"î–“";--fa--fa:"î–“î–“"}.fa-wallet{--fa:"ï••";--fa--fa:"ï••ï••"}.fa-clipboard-check{--fa:"";--fa--fa:""}.fa-file-audio{--fa:"";--fa--fa:""}.fa-burger{--fa:"ï …";--fa--fa:"ï …ï …"}.fa-hamburger{--fa:"ï …";--fa--fa:"ï …ï …"}.fa-wrench{--fa:"ï‚­";--fa--fa:"ï‚­ï‚­"}.fa-bugs{--fa:"î“";--fa--fa:"î“î“"}.fa-rupee-sign{--fa:"ï…–";--fa--fa:"ï…–ï…–"}.fa-rupee{--fa:"ï…–";--fa--fa:"ï…–ï…–"}.fa-file-image{--fa:"";--fa--fa:""}.fa-circle-question{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-question-circle{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-plane-departure{--fa:"ï–°";--fa--fa:"ï–°ï–°"}.fa-handshake-slash{--fa:"î ";--fa--fa:"î î "}.fa-book-bookmark{--fa:"î‚»";--fa--fa:""}.fa-code-branch{--fa:"";--fa--fa:""}.fa-hat-cowboy{--fa:"";--fa--fa:""}.fa-bridge{--fa:"";--fa--fa:""}.fa-phone-flip{--fa:"";--fa--fa:""}.fa-phone-alt{--fa:"";--fa--fa:""}.fa-truck-front{--fa:"";--fa--fa:""}.fa-cat{--fa:"ïš¾";--fa--fa:""}.fa-anchor-circle-exclamation{--fa:"î’«";--fa--fa:"î’«î’«"}.fa-truck-field{--fa:"î–";--fa--fa:"î–î–"}.fa-route{--fa:"ï“—";--fa--fa:"ï“—ï“—"}.fa-clipboard-question{--fa:"î“£";--fa--fa:""}.fa-panorama{--fa:"";--fa--fa:""}.fa-comment-medical{--fa:"";--fa--fa:""}.fa-teeth-open{--fa:"";--fa--fa:""}.fa-file-circle-minus{--fa:"î“­";--fa--fa:"î“­î“­"}.fa-tags{--fa:"";--fa--fa:""}.fa-wine-glass{--fa:"ï“£";--fa--fa:""}.fa-forward-fast{--fa:"ï";--fa--fa:"ïï"}.fa-fast-forward{--fa:"ï";--fa--fa:"ïï"}.fa-face-meh-blank{--fa:"ï–¤";--fa--fa:""}.fa-meh-blank{--fa:"ï–¤";--fa--fa:""}.fa-square-parking{--fa:"ï•€";--fa--fa:""}.fa-parking{--fa:"ï•€";--fa--fa:""}.fa-house-signal{--fa:"";--fa--fa:""}.fa-bars-progress{--fa:"ï ¨";--fa--fa:""}.fa-tasks-alt{--fa:"ï ¨";--fa--fa:""}.fa-faucet-drip{--fa:"";--fa--fa:""}.fa-cart-flatbed{--fa:"ï‘´";--fa--fa:"ï‘´ï‘´"}.fa-dolly-flatbed{--fa:"ï‘´";--fa--fa:"ï‘´ï‘´"}.fa-ban-smoking{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-smoking-ban{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-terminal{--fa:"ï„ ";--fa--fa:"ï„ ï„ "}.fa-mobile-button{--fa:"ï„‹";--fa--fa:"ï„‹ï„‹"}.fa-house-medical-flag{--fa:"î””";--fa--fa:""}.fa-basket-shopping{--fa:"";--fa--fa:""}.fa-shopping-basket{--fa:"";--fa--fa:""}.fa-tape{--fa:"ï“›";--fa--fa:""}.fa-bus-simple{--fa:"ï•ž";--fa--fa:"ï•žï•ž"}.fa-bus-alt{--fa:"ï•ž";--fa--fa:"ï•žï•ž"}.fa-eye{--fa:"ï®";--fa--fa:"ï®ï®"}.fa-face-sad-cry{--fa:"ï–³";--fa--fa:""}.fa-sad-cry{--fa:"ï–³";--fa--fa:""}.fa-audio-description{--fa:"";--fa--fa:""}.fa-person-military-to-person{--fa:"î•Œ";--fa--fa:""}.fa-file-shield{--fa:"î“°";--fa--fa:"î“°î“°"}.fa-user-slash{--fa:"";--fa--fa:""}.fa-pen{--fa:"";--fa--fa:""}.fa-tower-observation{--fa:"î–†";--fa--fa:""}.fa-file-code{--fa:"";--fa--fa:""}.fa-signal{--fa:"";--fa--fa:""}.fa-signal-5{--fa:"";--fa--fa:""}.fa-signal-perfect{--fa:"";--fa--fa:""}.fa-bus{--fa:"";--fa--fa:""}.fa-heart-circle-xmark{--fa:"î”";--fa--fa:"î”î”"}.fa-house-chimney{--fa:"";--fa--fa:""}.fa-home-lg{--fa:"";--fa--fa:""}.fa-window-maximize{--fa:"ï‹";--fa--fa:"ï‹ï‹"}.fa-face-frown{--fa:"ï„™";--fa--fa:""}.fa-frown{--fa:"ï„™";--fa--fa:""}.fa-prescription{--fa:"ï–±";--fa--fa:""}.fa-shop{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-store-alt{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-floppy-disk{--fa:"";--fa--fa:""}.fa-save{--fa:"";--fa--fa:""}.fa-vihara{--fa:"";--fa--fa:""}.fa-scale-unbalanced{--fa:"";--fa--fa:""}.fa-balance-scale-left{--fa:"";--fa--fa:""}.fa-sort-up{--fa:"";--fa--fa:""}.fa-sort-asc{--fa:"";--fa--fa:""}.fa-comment-dots{--fa:"ï’­";--fa--fa:"ï’­ï’­"}.fa-commenting{--fa:"ï’­";--fa--fa:"ï’­ï’­"}.fa-plant-wilt{--fa:"î–ª";--fa--fa:""}.fa-diamond{--fa:"";--fa--fa:""}.fa-face-grin-squint{--fa:"ï–…";--fa--fa:"ï–…ï–…"}.fa-grin-squint{--fa:"ï–…";--fa--fa:"ï–…ï–…"}.fa-hand-holding-dollar{--fa:"ï“€";--fa--fa:""}.fa-hand-holding-usd{--fa:"ï“€";--fa--fa:""}.fa-chart-diagram{--fa:"îš•";--fa--fa:"îš•îš•"}.fa-bacterium{--fa:"îš";--fa--fa:"îšîš"}.fa-hand-pointer{--fa:"";--fa--fa:""}.fa-drum-steelpan{--fa:"";--fa--fa:""}.fa-hand-scissors{--fa:"";--fa--fa:""}.fa-hands-praying{--fa:"ïš„";--fa--fa:"ïš„ïš„"}.fa-praying-hands{--fa:"ïš„";--fa--fa:"ïš„ïš„"}.fa-arrow-rotate-right{--fa:"";--fa--fa:""}.fa-arrow-right-rotate{--fa:"";--fa--fa:""}.fa-arrow-rotate-forward{--fa:"";--fa--fa:""}.fa-redo{--fa:"";--fa--fa:""}.fa-biohazard{--fa:"";--fa--fa:""}.fa-location-crosshairs{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-location{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-mars-double{--fa:"";--fa--fa:""}.fa-child-dress{--fa:"î–œ";--fa--fa:""}.fa-users-between-lines{--fa:"î–‘";--fa--fa:"î–‘î–‘"}.fa-lungs-virus{--fa:"î§";--fa--fa:"î§î§"}.fa-face-grin-tears{--fa:"ï–ˆ";--fa--fa:""}.fa-grin-tears{--fa:"ï–ˆ";--fa--fa:""}.fa-phone{--fa:"ï‚•";--fa--fa:"ï‚•ï‚•"}.fa-calendar-xmark{--fa:"";--fa--fa:""}.fa-calendar-times{--fa:"";--fa--fa:""}.fa-child-reaching{--fa:"î–";--fa--fa:"î–î–"}.fa-head-side-virus{--fa:"î¤";--fa--fa:"î¤î¤"}.fa-user-gear{--fa:"";--fa--fa:""}.fa-user-cog{--fa:"";--fa--fa:""}.fa-arrow-up-1-9{--fa:"ï…£";--fa--fa:""}.fa-sort-numeric-up{--fa:"ï…£";--fa--fa:""}.fa-door-closed{--fa:"";--fa--fa:""}.fa-shield-virus{--fa:"î¬";--fa--fa:"î¬î¬"}.fa-dice-six{--fa:"";--fa--fa:""}.fa-mosquito-net{--fa:"";--fa--fa:""}.fa-file-fragment{--fa:"îš—";--fa--fa:"îš—îš—"}.fa-bridge-water{--fa:"î“Ž";--fa--fa:"î“Žî“Ž"}.fa-person-booth{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-text-width{--fa:"";--fa--fa:""}.fa-hat-wizard{--fa:"";--fa--fa:""}.fa-pen-fancy{--fa:"ï–¬";--fa--fa:""}.fa-person-digging{--fa:"ï¡ž";--fa--fa:"ï¡žï¡ž"}.fa-digging{--fa:"ï¡ž";--fa--fa:"ï¡žï¡ž"}.fa-trash{--fa:"";--fa--fa:""}.fa-gauge-simple{--fa:"";--fa--fa:""}.fa-gauge-simple-med{--fa:"";--fa--fa:""}.fa-tachometer-average{--fa:"";--fa--fa:""}.fa-book-medical{--fa:"";--fa--fa:""}.fa-poo{--fa:"";--fa--fa:""}.fa-quote-right{--fa:"ï„Ž";--fa--fa:"ï„Žï„Ž"}.fa-quote-right-alt{--fa:"ï„Ž";--fa--fa:"ï„Žï„Ž"}.fa-shirt{--fa:"ï•“";--fa--fa:"ï•“ï•“"}.fa-t-shirt{--fa:"ï•“";--fa--fa:"ï•“ï•“"}.fa-tshirt{--fa:"ï•“";--fa--fa:"ï•“ï•“"}.fa-cubes{--fa:"";--fa--fa:""}.fa-divide{--fa:"";--fa--fa:""}.fa-tenge-sign{--fa:"";--fa--fa:""}.fa-tenge{--fa:"";--fa--fa:""}.fa-headphones{--fa:"";--fa--fa:""}.fa-hands-holding{--fa:"ï“‚";--fa--fa:"ï“‚ï“‚"}.fa-hands-clapping{--fa:"";--fa--fa:""}.fa-republican{--fa:"ïž";--fa--fa:"ïžïž"}.fa-arrow-left{--fa:"ï ";--fa--fa:"ï ï "}.fa-person-circle-xmark{--fa:"";--fa--fa:""}.fa-ruler{--fa:"ï•…";--fa--fa:"ï•…ï•…"}.fa-align-left{--fa:"";--fa--fa:""}.fa-dice-d6{--fa:"";--fa--fa:""}.fa-restroom{--fa:"ïž½";--fa--fa:""}.fa-j{--fa:"J";--fa--fa:"JJ"}.fa-users-viewfinder{--fa:"î–•";--fa--fa:"î–•î–•"}.fa-file-video{--fa:"";--fa--fa:""}.fa-up-right-from-square{--fa:"ï";--fa--fa:"ïï"}.fa-external-link-alt{--fa:"ï";--fa--fa:"ïï"}.fa-table-cells{--fa:"";--fa--fa:""}.fa-th{--fa:"";--fa--fa:""}.fa-file-pdf{--fa:"ï‡";--fa--fa:"ï‡ï‡"}.fa-book-bible{--fa:"";--fa--fa:""}.fa-bible{--fa:"";--fa--fa:""}.fa-o{--fa:"O";--fa--fa:"OO"}.fa-suitcase-medical{--fa:"";--fa--fa:""}.fa-medkit{--fa:"";--fa--fa:""}.fa-user-secret{--fa:"";--fa--fa:""}.fa-otter{--fa:"";--fa--fa:""}.fa-person-dress{--fa:"";--fa--fa:""}.fa-female{--fa:"";--fa--fa:""}.fa-comment-dollar{--fa:"";--fa--fa:""}.fa-business-time{--fa:"";--fa--fa:""}.fa-briefcase-clock{--fa:"";--fa--fa:""}.fa-table-cells-large{--fa:"";--fa--fa:""}.fa-th-large{--fa:"";--fa--fa:""}.fa-book-tanakh{--fa:"ï §";--fa--fa:""}.fa-tanakh{--fa:"ï §";--fa--fa:""}.fa-phone-volume{--fa:"";--fa--fa:""}.fa-volume-control-phone{--fa:"";--fa--fa:""}.fa-hat-cowboy-side{--fa:"ï£";--fa--fa:"ï£ï£"}.fa-clipboard-user{--fa:"";--fa--fa:""}.fa-child{--fa:"";--fa--fa:""}.fa-lira-sign{--fa:"";--fa--fa:""}.fa-satellite{--fa:"ïž¿";--fa--fa:"ïž¿ïž¿"}.fa-plane-lock{--fa:"";--fa--fa:""}.fa-tag{--fa:"";--fa--fa:""}.fa-comment{--fa:"ïµ";--fa--fa:"ïµïµ"}.fa-cake-candles{--fa:"";--fa--fa:""}.fa-birthday-cake{--fa:"";--fa--fa:""}.fa-cake{--fa:"";--fa--fa:""}.fa-envelope{--fa:"";--fa--fa:""}.fa-angles-up{--fa:"ï„‚";--fa--fa:"ï„‚ï„‚"}.fa-angle-double-up{--fa:"ï„‚";--fa--fa:"ï„‚ï„‚"}.fa-paperclip{--fa:"";--fa--fa:""}.fa-arrow-right-to-city{--fa:"î’³";--fa--fa:""}.fa-ribbon{--fa:"ï“–";--fa--fa:"ï“–ï“–"}.fa-lungs{--fa:"";--fa--fa:""}.fa-arrow-up-9-1{--fa:"";--fa--fa:""}.fa-sort-numeric-up-alt{--fa:"";--fa--fa:""}.fa-litecoin-sign{--fa:"";--fa--fa:""}.fa-border-none{--fa:"ï¡";--fa--fa:"ï¡ï¡"}.fa-circle-nodes{--fa:"î“¢";--fa--fa:""}.fa-parachute-box{--fa:"ï“";--fa--fa:"ï“ï“"}.fa-indent{--fa:"";--fa--fa:""}.fa-truck-field-un{--fa:"î–Ž";--fa--fa:"î–Žî–Ž"}.fa-hourglass{--fa:"";--fa--fa:""}.fa-hourglass-empty{--fa:"";--fa--fa:""}.fa-mountain{--fa:"";--fa--fa:""}.fa-user-doctor{--fa:"";--fa--fa:""}.fa-user-md{--fa:"";--fa--fa:""}.fa-circle-info{--fa:"ïš";--fa--fa:"ïšïš"}.fa-info-circle{--fa:"ïš";--fa--fa:"ïšïš"}.fa-cloud-meatball{--fa:"";--fa--fa:""}.fa-camera{--fa:"";--fa--fa:""}.fa-camera-alt{--fa:"";--fa--fa:""}.fa-square-virus{--fa:"";--fa--fa:""}.fa-meteor{--fa:"ï“";--fa--fa:"ï“ï“"}.fa-car-on{--fa:"î“";--fa--fa:"î“î“"}.fa-sleigh{--fa:"";--fa--fa:""}.fa-arrow-down-1-9{--fa:"ï…¢";--fa--fa:""}.fa-sort-numeric-asc{--fa:"ï…¢";--fa--fa:""}.fa-sort-numeric-down{--fa:"ï…¢";--fa--fa:""}.fa-hand-holding-droplet{--fa:"ï“";--fa--fa:"ï“ï“"}.fa-hand-holding-water{--fa:"ï“";--fa--fa:"ï“ï“"}.fa-water{--fa:"ï³";--fa--fa:"ï³ï³"}.fa-calendar-check{--fa:"";--fa--fa:""}.fa-braille{--fa:"";--fa--fa:""}.fa-prescription-bottle-medical{--fa:"ï’†";--fa--fa:""}.fa-prescription-bottle-alt{--fa:"ï’†";--fa--fa:""}.fa-landmark{--fa:"";--fa--fa:""}.fa-truck{--fa:"";--fa--fa:""}.fa-crosshairs{--fa:"ï›";--fa--fa:"ï›ï›"}.fa-person-cane{--fa:"";--fa--fa:""}.fa-tent{--fa:"";--fa--fa:""}.fa-vest-patches{--fa:"";--fa--fa:""}.fa-check-double{--fa:"ï• ";--fa--fa:"ï• ï• "}.fa-arrow-down-a-z{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-sort-alpha-asc{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-sort-alpha-down{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-money-bill-wheat{--fa:"";--fa--fa:""}.fa-cookie{--fa:"ï•£";--fa--fa:""}.fa-arrow-rotate-left{--fa:"";--fa--fa:""}.fa-arrow-left-rotate{--fa:"";--fa--fa:""}.fa-arrow-rotate-back{--fa:"";--fa--fa:""}.fa-arrow-rotate-backward{--fa:"";--fa--fa:""}.fa-undo{--fa:"";--fa--fa:""}.fa-hard-drive{--fa:"ï‚ ";--fa--fa:"ï‚ ï‚ "}.fa-hdd{--fa:"ï‚ ";--fa--fa:"ï‚ ï‚ "}.fa-face-grin-squint-tears{--fa:"ï–†";--fa--fa:""}.fa-grin-squint-tears{--fa:"ï–†";--fa--fa:""}.fa-dumbbell{--fa:"ï‘‹";--fa--fa:"ï‘‹ï‘‹"}.fa-rectangle-list{--fa:"";--fa--fa:""}.fa-list-alt{--fa:"";--fa--fa:""}.fa-tarp-droplet{--fa:"";--fa--fa:""}.fa-house-medical-circle-check{--fa:"";--fa--fa:""}.fa-person-skiing-nordic{--fa:"";--fa--fa:""}.fa-skiing-nordic{--fa:"";--fa--fa:""}.fa-calendar-plus{--fa:"";--fa--fa:""}.fa-plane-arrival{--fa:"ï–¯";--fa--fa:""}.fa-circle-left{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-arrow-alt-circle-left{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-train-subway{--fa:"";--fa--fa:""}.fa-subway{--fa:"";--fa--fa:""}.fa-chart-gantt{--fa:"";--fa--fa:""}.fa-indian-rupee-sign{--fa:"";--fa--fa:""}.fa-indian-rupee{--fa:"";--fa--fa:""}.fa-inr{--fa:"";--fa--fa:""}.fa-crop-simple{--fa:"ï•¥";--fa--fa:""}.fa-crop-alt{--fa:"ï•¥";--fa--fa:""}.fa-money-bill-1{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-money-bill-alt{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-left-long{--fa:"";--fa--fa:""}.fa-long-arrow-alt-left{--fa:"";--fa--fa:""}.fa-dna{--fa:"";--fa--fa:""}.fa-virus-slash{--fa:"îµ";--fa--fa:"îµîµ"}.fa-minus{--fa:"ï¨";--fa--fa:"ï¨ï¨"}.fa-subtract{--fa:"ï¨";--fa--fa:"ï¨ï¨"}.fa-chess{--fa:"ï¹";--fa--fa:"ï¹ï¹"}.fa-arrow-left-long{--fa:"ï…·";--fa--fa:"ï…·ï…·"}.fa-long-arrow-left{--fa:"ï…·";--fa--fa:"ï…·ï…·"}.fa-plug-circle-check{--fa:"î•œ";--fa--fa:""}.fa-street-view{--fa:"ïˆ";--fa--fa:"ïˆïˆ"}.fa-franc-sign{--fa:"î†";--fa--fa:"î†î†"}.fa-volume-off{--fa:"";--fa--fa:""}.fa-hands-asl-interpreting{--fa:"";--fa--fa:""}.fa-american-sign-language-interpreting{--fa:"";--fa--fa:""}.fa-asl-interpreting{--fa:"";--fa--fa:""}.fa-hands-american-sign-language-interpreting{--fa:"";--fa--fa:""}.fa-gear{--fa:"";--fa--fa:""}.fa-cog{--fa:"";--fa--fa:""}.fa-droplet-slash{--fa:"ï—‡";--fa--fa:""}.fa-tint-slash{--fa:"ï—‡";--fa--fa:""}.fa-mosque{--fa:"";--fa--fa:""}.fa-mosquito{--fa:"";--fa--fa:""}.fa-star-of-david{--fa:"ïšš";--fa--fa:"ïššïšš"}.fa-person-military-rifle{--fa:"î•‹";--fa--fa:"î•‹î•‹"}.fa-cart-shopping{--fa:"ïº";--fa--fa:"ïºïº"}.fa-shopping-cart{--fa:"ïº";--fa--fa:"ïºïº"}.fa-vials{--fa:"ï’“";--fa--fa:"ï’“ï’“"}.fa-plug-circle-plus{--fa:"î•Ÿ";--fa--fa:"î•Ÿî•Ÿ"}.fa-place-of-worship{--fa:"";--fa--fa:""}.fa-grip-vertical{--fa:"ï–Ž";--fa--fa:"ï–Žï–Ž"}.fa-hexagon-nodes{--fa:"îš™";--fa--fa:""}.fa-arrow-turn-up{--fa:"ï…ˆ";--fa--fa:""}.fa-level-up{--fa:"ï…ˆ";--fa--fa:""}.fa-u{--fa:"U";--fa--fa:"UU"}.fa-square-root-variable{--fa:"";--fa--fa:""}.fa-square-root-alt{--fa:"";--fa--fa:""}.fa-clock{--fa:"";--fa--fa:""}.fa-clock-four{--fa:"";--fa--fa:""}.fa-backward-step{--fa:"ïˆ";--fa--fa:"ïˆïˆ"}.fa-step-backward{--fa:"ïˆ";--fa--fa:"ïˆïˆ"}.fa-pallet{--fa:"ï’‚";--fa--fa:"ï’‚ï’‚"}.fa-faucet{--fa:"";--fa--fa:""}.fa-baseball-bat-ball{--fa:"ï²";--fa--fa:"ï²ï²"}.fa-s{--fa:"S";--fa--fa:"SS"}.fa-timeline{--fa:"";--fa--fa:""}.fa-keyboard{--fa:"ï„œ";--fa--fa:""}.fa-caret-down{--fa:"";--fa--fa:""}.fa-house-chimney-medical{--fa:"";--fa--fa:""}.fa-clinic-medical{--fa:"";--fa--fa:""}.fa-temperature-three-quarters{--fa:"";--fa--fa:""}.fa-temperature-3{--fa:"";--fa--fa:""}.fa-thermometer-3{--fa:"";--fa--fa:""}.fa-thermometer-three-quarters{--fa:"";--fa--fa:""}.fa-mobile-screen{--fa:"ï";--fa--fa:"ïï"}.fa-mobile-android-alt{--fa:"ï";--fa--fa:"ïï"}.fa-plane-up{--fa:"";--fa--fa:""}.fa-piggy-bank{--fa:"ï““";--fa--fa:"ï““ï““"}.fa-battery-half{--fa:"";--fa--fa:""}.fa-battery-3{--fa:"";--fa--fa:""}.fa-mountain-city{--fa:"î”®";--fa--fa:""}.fa-coins{--fa:"";--fa--fa:""}.fa-khanda{--fa:"ï™­";--fa--fa:"ï™­ï™­"}.fa-sliders{--fa:"";--fa--fa:""}.fa-sliders-h{--fa:"";--fa--fa:""}.fa-folder-tree{--fa:"ï ‚";--fa--fa:"ï ‚ï ‚"}.fa-network-wired{--fa:"";--fa--fa:""}.fa-map-pin{--fa:"";--fa--fa:""}.fa-hamsa{--fa:"";--fa--fa:""}.fa-cent-sign{--fa:"îµ";--fa--fa:"îµîµ"}.fa-flask{--fa:"";--fa--fa:""}.fa-person-pregnant{--fa:"";--fa--fa:""}.fa-wand-sparkles{--fa:"";--fa--fa:""}.fa-ellipsis-vertical{--fa:"ï…‚";--fa--fa:"ï…‚ï…‚"}.fa-ellipsis-v{--fa:"ï…‚";--fa--fa:"ï…‚ï…‚"}.fa-ticket{--fa:"ï……";--fa--fa:"ï……ï……"}.fa-power-off{--fa:"";--fa--fa:""}.fa-right-long{--fa:"";--fa--fa:""}.fa-long-arrow-alt-right{--fa:"";--fa--fa:""}.fa-flag-usa{--fa:"ï";--fa--fa:"ïï"}.fa-laptop-file{--fa:"î”";--fa--fa:"î”î”"}.fa-tty{--fa:"";--fa--fa:""}.fa-teletype{--fa:"";--fa--fa:""}.fa-diagram-next{--fa:"";--fa--fa:""}.fa-person-rifle{--fa:"î•Ž";--fa--fa:"î•Žî•Ž"}.fa-house-medical-circle-exclamation{--fa:"î”’";--fa--fa:"î”’î”’"}.fa-closed-captioning{--fa:"";--fa--fa:""}.fa-person-hiking{--fa:"";--fa--fa:""}.fa-hiking{--fa:"";--fa--fa:""}.fa-venus-double{--fa:"";--fa--fa:""}.fa-images{--fa:"";--fa--fa:""}.fa-calculator{--fa:"";--fa--fa:""}.fa-people-pulling{--fa:"";--fa--fa:""}.fa-n{--fa:"N";--fa--fa:"NN"}.fa-cable-car{--fa:"";--fa--fa:""}.fa-tram{--fa:"";--fa--fa:""}.fa-cloud-rain{--fa:"";--fa--fa:""}.fa-building-circle-xmark{--fa:"î“”";--fa--fa:""}.fa-ship{--fa:"";--fa--fa:""}.fa-arrows-down-to-line{--fa:"î’¸";--fa--fa:""}.fa-download{--fa:"";--fa--fa:""}.fa-face-grin{--fa:"ï–€";--fa--fa:""}.fa-grin{--fa:"ï–€";--fa--fa:""}.fa-delete-left{--fa:"ï•š";--fa--fa:"ï•šï•š"}.fa-backspace{--fa:"ï•š";--fa--fa:"ï•šï•š"}.fa-eye-dropper{--fa:"";--fa--fa:""}.fa-eye-dropper-empty{--fa:"";--fa--fa:""}.fa-eyedropper{--fa:"";--fa--fa:""}.fa-file-circle-check{--fa:"î– ";--fa--fa:"î– î– "}.fa-forward{--fa:"ïŽ";--fa--fa:"ïŽïŽ"}.fa-mobile{--fa:"ïŽ";--fa--fa:"ïŽïŽ"}.fa-mobile-android{--fa:"ïŽ";--fa--fa:"ïŽïŽ"}.fa-mobile-phone{--fa:"ïŽ";--fa--fa:"ïŽïŽ"}.fa-face-meh{--fa:"ï„š";--fa--fa:"ï„šï„š"}.fa-meh{--fa:"ï„š";--fa--fa:"ï„šï„š"}.fa-align-center{--fa:"";--fa--fa:""}.fa-book-skull{--fa:"ïš·";--fa--fa:"ïš·ïš·"}.fa-book-dead{--fa:"ïš·";--fa--fa:"ïš·ïš·"}.fa-id-card{--fa:"ï‹‚";--fa--fa:"ï‹‚ï‹‚"}.fa-drivers-license{--fa:"ï‹‚";--fa--fa:"ï‹‚ï‹‚"}.fa-outdent{--fa:"";--fa--fa:""}.fa-dedent{--fa:"";--fa--fa:""}.fa-heart-circle-exclamation{--fa:"";--fa--fa:""}.fa-house{--fa:"";--fa--fa:""}.fa-home{--fa:"";--fa--fa:""}.fa-home-alt{--fa:"";--fa--fa:""}.fa-home-lg-alt{--fa:"";--fa--fa:""}.fa-calendar-week{--fa:"ïž„";--fa--fa:"ïž„ïž„"}.fa-laptop-medical{--fa:"ï ’";--fa--fa:"ï ’ï ’"}.fa-b{--fa:"B";--fa--fa:"BB"}.fa-file-medical{--fa:"ï‘·";--fa--fa:"ï‘·ï‘·"}.fa-dice-one{--fa:"";--fa--fa:""}.fa-kiwi-bird{--fa:"";--fa--fa:""}.fa-arrow-right-arrow-left{--fa:"";--fa--fa:""}.fa-exchange{--fa:"";--fa--fa:""}.fa-rotate-right{--fa:"";--fa--fa:""}.fa-redo-alt{--fa:"";--fa--fa:""}.fa-rotate-forward{--fa:"";--fa--fa:""}.fa-utensils{--fa:"";--fa--fa:""}.fa-cutlery{--fa:"";--fa--fa:""}.fa-arrow-up-wide-short{--fa:"ï…¡";--fa--fa:"ï…¡ï…¡"}.fa-sort-amount-up{--fa:"ï…¡";--fa--fa:"ï…¡ï…¡"}.fa-mill-sign{--fa:"";--fa--fa:""}.fa-bowl-rice{--fa:"î‹«";--fa--fa:"î‹«î‹«"}.fa-skull{--fa:"ï•Œ";--fa--fa:""}.fa-tower-broadcast{--fa:"ï”™";--fa--fa:""}.fa-broadcast-tower{--fa:"ï”™";--fa--fa:""}.fa-truck-pickup{--fa:"";--fa--fa:""}.fa-up-long{--fa:"";--fa--fa:""}.fa-long-arrow-alt-up{--fa:"";--fa--fa:""}.fa-stop{--fa:"ï";--fa--fa:"ïï"}.fa-code-merge{--fa:"";--fa--fa:""}.fa-upload{--fa:"ï‚“";--fa--fa:"ï‚“ï‚“"}.fa-hurricane{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-mound{--fa:"î”­";--fa--fa:"î”­î”­"}.fa-toilet-portable{--fa:"î–ƒ";--fa--fa:""}.fa-compact-disc{--fa:"";--fa--fa:""}.fa-file-arrow-down{--fa:"ï•­";--fa--fa:"ï•­ï•­"}.fa-file-download{--fa:"ï•­";--fa--fa:"ï•­ï•­"}.fa-caravan{--fa:"";--fa--fa:""}.fa-shield-cat{--fa:"";--fa--fa:""}.fa-bolt{--fa:"";--fa--fa:""}.fa-zap{--fa:"";--fa--fa:""}.fa-glass-water{--fa:"î“´";--fa--fa:"î“´î“´"}.fa-oil-well{--fa:"";--fa--fa:""}.fa-vault{--fa:"î‹…";--fa--fa:"î‹…î‹…"}.fa-mars{--fa:"";--fa--fa:""}.fa-toilet{--fa:"";--fa--fa:""}.fa-plane-circle-xmark{--fa:"î•—";--fa--fa:"î•—î•—"}.fa-yen-sign{--fa:"ï…—";--fa--fa:"ï…—ï…—"}.fa-cny{--fa:"ï…—";--fa--fa:"ï…—ï…—"}.fa-jpy{--fa:"ï…—";--fa--fa:"ï…—ï…—"}.fa-rmb{--fa:"ï…—";--fa--fa:"ï…—ï…—"}.fa-yen{--fa:"ï…—";--fa--fa:"ï…—ï…—"}.fa-ruble-sign{--fa:"ï…˜";--fa--fa:""}.fa-rouble{--fa:"ï…˜";--fa--fa:""}.fa-rub{--fa:"ï…˜";--fa--fa:""}.fa-ruble{--fa:"ï…˜";--fa--fa:""}.fa-sun{--fa:"";--fa--fa:""}.fa-guitar{--fa:"";--fa--fa:""}.fa-face-laugh-wink{--fa:"ï–œ";--fa--fa:""}.fa-laugh-wink{--fa:"ï–œ";--fa--fa:""}.fa-horse-head{--fa:"ïž«";--fa--fa:"ïž«ïž«"}.fa-bore-hole{--fa:"";--fa--fa:""}.fa-industry{--fa:"";--fa--fa:""}.fa-circle-down{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-arrow-alt-circle-down{--fa:"ï˜";--fa--fa:"ï˜ï˜"}.fa-arrows-turn-to-dots{--fa:"î“";--fa--fa:"î“î“"}.fa-florin-sign{--fa:"";--fa--fa:""}.fa-arrow-down-short-wide{--fa:"";--fa--fa:""}.fa-sort-amount-desc{--fa:"";--fa--fa:""}.fa-sort-amount-down-alt{--fa:"";--fa--fa:""}.fa-less-than{--fa:"\<";--fa--fa:"\<\<"}.fa-angle-down{--fa:"";--fa--fa:""}.fa-car-tunnel{--fa:"î“ž";--fa--fa:"î“žî“ž"}.fa-head-side-cough{--fa:"î¡";--fa--fa:"î¡î¡"}.fa-grip-lines{--fa:"";--fa--fa:""}.fa-thumbs-down{--fa:"ï…¥";--fa--fa:""}.fa-user-lock{--fa:"";--fa--fa:""}.fa-arrow-right-long{--fa:"ï…¸";--fa--fa:""}.fa-long-arrow-right{--fa:"ï…¸";--fa--fa:""}.fa-anchor-circle-xmark{--fa:"î’¬";--fa--fa:""}.fa-ellipsis{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-ellipsis-h{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-chess-pawn{--fa:"";--fa--fa:""}.fa-kit-medical{--fa:"";--fa--fa:""}.fa-first-aid{--fa:"";--fa--fa:""}.fa-person-through-window{--fa:"î–©";--fa--fa:"î–©î–©"}.fa-toolbox{--fa:"ï•’";--fa--fa:"ï•’ï•’"}.fa-hands-holding-circle{--fa:"î“»";--fa--fa:""}.fa-bug{--fa:"";--fa--fa:""}.fa-credit-card{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-credit-card-alt{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-car{--fa:"";--fa--fa:""}.fa-automobile{--fa:"";--fa--fa:""}.fa-hand-holding-hand{--fa:"î“·";--fa--fa:"î“·î“·"}.fa-book-open-reader{--fa:"ï—š";--fa--fa:"ï—šï—š"}.fa-book-reader{--fa:"ï—š";--fa--fa:"ï—šï—š"}.fa-mountain-sun{--fa:"";--fa--fa:""}.fa-arrows-left-right-to-line{--fa:"î’º";--fa--fa:""}.fa-dice-d20{--fa:"ï›";--fa--fa:"ï›ï›"}.fa-truck-droplet{--fa:"î–Œ";--fa--fa:""}.fa-file-circle-xmark{--fa:"î–¡";--fa--fa:"î–¡î–¡"}.fa-temperature-arrow-up{--fa:"î€";--fa--fa:"î€î€"}.fa-temperature-up{--fa:"î€";--fa--fa:"î€î€"}.fa-medal{--fa:"ï–¢";--fa--fa:""}.fa-bed{--fa:"";--fa--fa:""}.fa-square-h{--fa:"";--fa--fa:""}.fa-h-square{--fa:"";--fa--fa:""}.fa-podcast{--fa:"ï‹Ž";--fa--fa:"ï‹Žï‹Ž"}.fa-temperature-full{--fa:"";--fa--fa:""}.fa-temperature-4{--fa:"";--fa--fa:""}.fa-thermometer-4{--fa:"";--fa--fa:""}.fa-thermometer-full{--fa:"";--fa--fa:""}.fa-bell{--fa:"";--fa--fa:""}.fa-superscript{--fa:"ï„«";--fa--fa:"ï„«ï„«"}.fa-plug-circle-xmark{--fa:"î• ";--fa--fa:"î• î• "}.fa-star-of-life{--fa:"";--fa--fa:""}.fa-phone-slash{--fa:"ï";--fa--fa:"ïï"}.fa-paint-roller{--fa:"ï–ª";--fa--fa:""}.fa-handshake-angle{--fa:"ï“„";--fa--fa:"ï“„ï“„"}.fa-hands-helping{--fa:"ï“„";--fa--fa:"ï“„ï“„"}.fa-location-dot{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-map-marker-alt{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-file{--fa:"ï…›";--fa--fa:""}.fa-greater-than{--fa:"\>";--fa--fa:"\>\>"}.fa-person-swimming{--fa:"ï—„";--fa--fa:"ï—„ï—„"}.fa-swimmer{--fa:"ï—„";--fa--fa:"ï—„ï—„"}.fa-arrow-down{--fa:"ï£";--fa--fa:"ï£ï£"}.fa-droplet{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-tint{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-eraser{--fa:"ï„­";--fa--fa:"ï„­ï„­"}.fa-earth-americas{--fa:"";--fa--fa:""}.fa-earth{--fa:"";--fa--fa:""}.fa-earth-america{--fa:"";--fa--fa:""}.fa-globe-americas{--fa:"";--fa--fa:""}.fa-person-burst{--fa:"î”»";--fa--fa:""}.fa-dove{--fa:"ï’º";--fa--fa:""}.fa-battery-empty{--fa:"";--fa--fa:""}.fa-battery-0{--fa:"";--fa--fa:""}.fa-socks{--fa:"ïš–";--fa--fa:"ïš–ïš–"}.fa-inbox{--fa:"";--fa--fa:""}.fa-section{--fa:"";--fa--fa:""}.fa-gauge-high{--fa:"";--fa--fa:""}.fa-tachometer-alt{--fa:"";--fa--fa:""}.fa-tachometer-alt-fast{--fa:"";--fa--fa:""}.fa-envelope-open-text{--fa:"";--fa--fa:""}.fa-hospital{--fa:"";--fa--fa:""}.fa-hospital-alt{--fa:"";--fa--fa:""}.fa-hospital-wide{--fa:"";--fa--fa:""}.fa-wine-bottle{--fa:"";--fa--fa:""}.fa-chess-rook{--fa:"";--fa--fa:""}.fa-bars-staggered{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-reorder{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-stream{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-dharmachakra{--fa:"";--fa--fa:""}.fa-hotdog{--fa:"ï ";--fa--fa:"ï ï "}.fa-person-walking-with-cane{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-blind{--fa:"ïŠ";--fa--fa:"ïŠïŠ"}.fa-drum{--fa:"ï•©";--fa--fa:"ï•©ï•©"}.fa-ice-cream{--fa:"ï ";--fa--fa:"ï ï "}.fa-heart-circle-bolt{--fa:"";--fa--fa:""}.fa-fax{--fa:"";--fa--fa:""}.fa-paragraph{--fa:"ï‡";--fa--fa:"ï‡ï‡"}.fa-check-to-slot{--fa:"ï²";--fa--fa:"ï²ï²"}.fa-vote-yea{--fa:"ï²";--fa--fa:"ï²ï²"}.fa-star-half{--fa:"";--fa--fa:""}.fa-boxes-stacked{--fa:"";--fa--fa:""}.fa-boxes{--fa:"";--fa--fa:""}.fa-boxes-alt{--fa:"";--fa--fa:""}.fa-link{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-chain{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-ear-listen{--fa:"";--fa--fa:""}.fa-assistive-listening-systems{--fa:"";--fa--fa:""}.fa-tree-city{--fa:"î–‡";--fa--fa:""}.fa-play{--fa:"ï‹";--fa--fa:"ï‹ï‹"}.fa-font{--fa:"";--fa--fa:""}.fa-table-cells-row-lock{--fa:"";--fa--fa:""}.fa-rupiah-sign{--fa:"";--fa--fa:""}.fa-magnifying-glass{--fa:"";--fa--fa:""}.fa-search{--fa:"";--fa--fa:""}.fa-table-tennis-paddle-ball{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-ping-pong-paddle-ball{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-table-tennis{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-person-dots-from-line{--fa:"ï‘°";--fa--fa:"ï‘°ï‘°"}.fa-diagnoses{--fa:"ï‘°";--fa--fa:"ï‘°ï‘°"}.fa-trash-can-arrow-up{--fa:"ï ª";--fa--fa:""}.fa-trash-restore-alt{--fa:"ï ª";--fa--fa:""}.fa-naira-sign{--fa:"";--fa--fa:""}.fa-cart-arrow-down{--fa:"";--fa--fa:""}.fa-walkie-talkie{--fa:"";--fa--fa:""}.fa-file-pen{--fa:"";--fa--fa:""}.fa-file-edit{--fa:"";--fa--fa:""}.fa-receipt{--fa:"";--fa--fa:""}.fa-square-pen{--fa:"ï…‹";--fa--fa:"ï…‹ï…‹"}.fa-pen-square{--fa:"ï…‹";--fa--fa:"ï…‹ï…‹"}.fa-pencil-square{--fa:"ï…‹";--fa--fa:"ï…‹ï…‹"}.fa-suitcase-rolling{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-person-circle-exclamation{--fa:"";--fa--fa:""}.fa-chevron-down{--fa:"ï¸";--fa--fa:"ï¸ï¸"}.fa-battery-full{--fa:"";--fa--fa:""}.fa-battery{--fa:"";--fa--fa:""}.fa-battery-5{--fa:"";--fa--fa:""}.fa-skull-crossbones{--fa:"";--fa--fa:""}.fa-code-compare{--fa:"";--fa--fa:""}.fa-list-ul{--fa:"";--fa--fa:""}.fa-list-dots{--fa:"";--fa--fa:""}.fa-school-lock{--fa:"";--fa--fa:""}.fa-tower-cell{--fa:"î–…";--fa--fa:"î–…î–…"}.fa-down-long{--fa:"";--fa--fa:""}.fa-long-arrow-alt-down{--fa:"";--fa--fa:""}.fa-ranking-star{--fa:"î•¡";--fa--fa:"î•¡î•¡"}.fa-chess-king{--fa:"ï¿";--fa--fa:"ï¿ï¿"}.fa-person-harassing{--fa:"";--fa--fa:""}.fa-brazilian-real-sign{--fa:"";--fa--fa:""}.fa-landmark-dome{--fa:"ï’";--fa--fa:"ï’ï’"}.fa-landmark-alt{--fa:"ï’";--fa--fa:"ï’ï’"}.fa-arrow-up{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-tv{--fa:"";--fa--fa:""}.fa-television{--fa:"";--fa--fa:""}.fa-tv-alt{--fa:"";--fa--fa:""}.fa-shrimp{--fa:"";--fa--fa:""}.fa-list-check{--fa:"ï‚®";--fa--fa:""}.fa-tasks{--fa:"ï‚®";--fa--fa:""}.fa-jug-detergent{--fa:"î”™";--fa--fa:""}.fa-circle-user{--fa:"";--fa--fa:""}.fa-user-circle{--fa:"";--fa--fa:""}.fa-user-shield{--fa:"ï”…";--fa--fa:"ï”…ï”…"}.fa-wind{--fa:"";--fa--fa:""}.fa-car-burst{--fa:"ï—¡";--fa--fa:"ï—¡ï—¡"}.fa-car-crash{--fa:"ï—¡";--fa--fa:"ï—¡ï—¡"}.fa-y{--fa:"Y";--fa--fa:"YY"}.fa-person-snowboarding{--fa:"";--fa--fa:""}.fa-snowboarding{--fa:"";--fa--fa:""}.fa-truck-fast{--fa:"ï’‹";--fa--fa:"ï’‹ï’‹"}.fa-shipping-fast{--fa:"ï’‹";--fa--fa:"ï’‹ï’‹"}.fa-fish{--fa:"";--fa--fa:""}.fa-user-graduate{--fa:"ï”";--fa--fa:"ï”ï”"}.fa-circle-half-stroke{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-adjust{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-clapperboard{--fa:"";--fa--fa:""}.fa-circle-radiation{--fa:"";--fa--fa:""}.fa-radiation-alt{--fa:"";--fa--fa:""}.fa-baseball{--fa:"ï³";--fa--fa:"ï³ï³"}.fa-baseball-ball{--fa:"ï³";--fa--fa:"ï³ï³"}.fa-jet-fighter-up{--fa:"";--fa--fa:""}.fa-diagram-project{--fa:"ï•‚";--fa--fa:"ï•‚ï•‚"}.fa-project-diagram{--fa:"ï•‚";--fa--fa:"ï•‚ï•‚"}.fa-copy{--fa:"";--fa--fa:""}.fa-volume-xmark{--fa:"ïš©";--fa--fa:"ïš©ïš©"}.fa-volume-mute{--fa:"ïš©";--fa--fa:"ïš©ïš©"}.fa-volume-times{--fa:"ïš©";--fa--fa:"ïš©ïš©"}.fa-hand-sparkles{--fa:"î";--fa--fa:"îî"}.fa-grip{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-grip-horizontal{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-share-from-square{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-share-square{--fa:"ï…";--fa--fa:"ï…ï…"}.fa-child-combatant{--fa:"î“ ";--fa--fa:"î“ î“ "}.fa-child-rifle{--fa:"î“ ";--fa--fa:"î“ î“ "}.fa-gun{--fa:"";--fa--fa:""}.fa-square-phone{--fa:"";--fa--fa:""}.fa-phone-square{--fa:"";--fa--fa:""}.fa-plus{--fa:"\+";--fa--fa:"\+\+"}.fa-add{--fa:"\+";--fa--fa:"\+\+"}.fa-expand{--fa:"ï¥";--fa--fa:"ï¥ï¥"}.fa-computer{--fa:"î“¥";--fa--fa:""}.fa-xmark{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-close{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-multiply{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-remove{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-times{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-arrows-up-down-left-right{--fa:"ï‡";--fa--fa:"ï‡ï‡"}.fa-arrows{--fa:"ï‡";--fa--fa:"ï‡ï‡"}.fa-chalkboard-user{--fa:"";--fa--fa:""}.fa-chalkboard-teacher{--fa:"";--fa--fa:""}.fa-peso-sign{--fa:"";--fa--fa:""}.fa-building-shield{--fa:"";--fa--fa:""}.fa-baby{--fa:"ï¼";--fa--fa:"ï¼ï¼"}.fa-users-line{--fa:"î–’";--fa--fa:"î–’î–’"}.fa-quote-left{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-quote-left-alt{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-tractor{--fa:"";--fa--fa:""}.fa-trash-arrow-up{--fa:"ï ©";--fa--fa:"ï ©ï ©"}.fa-trash-restore{--fa:"ï ©";--fa--fa:"ï ©ï ©"}.fa-arrow-down-up-lock{--fa:"î’°";--fa--fa:"î’°î’°"}.fa-lines-leaning{--fa:"";--fa--fa:""}.fa-ruler-combined{--fa:"";--fa--fa:""}.fa-copyright{--fa:"";--fa--fa:""}.fa-equals{--fa:"\=";--fa--fa:"\=\="}.fa-blender{--fa:"ï”—";--fa--fa:"ï”—ï”—"}.fa-teeth{--fa:"";--fa--fa:""}.fa-shekel-sign{--fa:"";--fa--fa:""}.fa-ils{--fa:"";--fa--fa:""}.fa-shekel{--fa:"";--fa--fa:""}.fa-sheqel{--fa:"";--fa--fa:""}.fa-sheqel-sign{--fa:"";--fa--fa:""}.fa-map{--fa:"";--fa--fa:""}.fa-rocket{--fa:"";--fa--fa:""}.fa-photo-film{--fa:"";--fa--fa:""}.fa-photo-video{--fa:"";--fa--fa:""}.fa-folder-minus{--fa:"ï™";--fa--fa:"ï™ï™"}.fa-hexagon-nodes-bolt{--fa:"îšš";--fa--fa:"îššîšš"}.fa-store{--fa:"ï•Ž";--fa--fa:"ï•Žï•Ž"}.fa-arrow-trend-up{--fa:"";--fa--fa:""}.fa-plug-circle-minus{--fa:"î•ž";--fa--fa:"î•žî•ž"}.fa-sign-hanging{--fa:"ï“™";--fa--fa:""}.fa-sign{--fa:"ï“™";--fa--fa:""}.fa-bezier-curve{--fa:"ï•›";--fa--fa:""}.fa-bell-slash{--fa:"";--fa--fa:""}.fa-tablet{--fa:"ï»";--fa--fa:"ï»ï»"}.fa-tablet-android{--fa:"ï»";--fa--fa:"ï»ï»"}.fa-school-flag{--fa:"î•®";--fa--fa:""}.fa-fill{--fa:"";--fa--fa:""}.fa-angle-up{--fa:"";--fa--fa:""}.fa-drumstick-bite{--fa:"ï›—";--fa--fa:"ï›—ï›—"}.fa-holly-berry{--fa:"";--fa--fa:""}.fa-chevron-left{--fa:"ï“";--fa--fa:"ï“ï“"}.fa-bacteria{--fa:"î™";--fa--fa:"î™î™"}.fa-hand-lizard{--fa:"";--fa--fa:""}.fa-notdef{--fa:"";--fa--fa:""}.fa-disease{--fa:"";--fa--fa:""}.fa-briefcase-medical{--fa:"ï‘©";--fa--fa:"ï‘©ï‘©"}.fa-genderless{--fa:"";--fa--fa:""}.fa-chevron-right{--fa:"ï”";--fa--fa:"ï”ï”"}.fa-retweet{--fa:"ï¹";--fa--fa:"ï¹ï¹"}.fa-car-rear{--fa:"ï—ž";--fa--fa:"ï—žï—ž"}.fa-car-alt{--fa:"ï—ž";--fa--fa:"ï—žï—ž"}.fa-pump-soap{--fa:"î«";--fa--fa:"î«î«"}.fa-video-slash{--fa:"ï“¢";--fa--fa:""}.fa-battery-quarter{--fa:"";--fa--fa:""}.fa-battery-2{--fa:"";--fa--fa:""}.fa-radio{--fa:"";--fa--fa:""}.fa-baby-carriage{--fa:"ï½";--fa--fa:"ï½ï½"}.fa-carriage-baby{--fa:"ï½";--fa--fa:"ï½ï½"}.fa-traffic-light{--fa:"";--fa--fa:""}.fa-thermometer{--fa:"ï’‘";--fa--fa:"ï’‘ï’‘"}.fa-vr-cardboard{--fa:"";--fa--fa:""}.fa-hand-middle-finger{--fa:"ï †";--fa--fa:""}.fa-percent{--fa:"\%";--fa--fa:"\%\%"}.fa-percentage{--fa:"\%";--fa--fa:"\%\%"}.fa-truck-moving{--fa:"ï“Ÿ";--fa--fa:"ï“Ÿï“Ÿ"}.fa-glass-water-droplet{--fa:"";--fa--fa:""}.fa-display{--fa:"î…£";--fa--fa:""}.fa-face-smile{--fa:"";--fa--fa:""}.fa-smile{--fa:"";--fa--fa:""}.fa-thumbtack{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-thumb-tack{--fa:"ï‚";--fa--fa:"ï‚ï‚"}.fa-trophy{--fa:"ï‚‘";--fa--fa:"ï‚‘ï‚‘"}.fa-person-praying{--fa:"";--fa--fa:""}.fa-pray{--fa:"";--fa--fa:""}.fa-hammer{--fa:"";--fa--fa:""}.fa-hand-peace{--fa:"";--fa--fa:""}.fa-rotate{--fa:"";--fa--fa:""}.fa-sync-alt{--fa:"";--fa--fa:""}.fa-spinner{--fa:"ï„";--fa--fa:"ï„ï„"}.fa-robot{--fa:"ï•„";--fa--fa:"ï•„ï•„"}.fa-peace{--fa:"";--fa--fa:""}.fa-gears{--fa:"ï‚…";--fa--fa:"ï‚…ï‚…"}.fa-cogs{--fa:"ï‚…";--fa--fa:"ï‚…ï‚…"}.fa-warehouse{--fa:"ï’”";--fa--fa:""}.fa-arrow-up-right-dots{--fa:"î’·";--fa--fa:"î’·î’·"}.fa-splotch{--fa:"ï–¼";--fa--fa:""}.fa-face-grin-hearts{--fa:"ï–„";--fa--fa:"ï–„ï–„"}.fa-grin-hearts{--fa:"ï–„";--fa--fa:"ï–„ï–„"}.fa-dice-four{--fa:"";--fa--fa:""}.fa-sim-card{--fa:"";--fa--fa:""}.fa-transgender{--fa:"";--fa--fa:""}.fa-transgender-alt{--fa:"";--fa--fa:""}.fa-mercury{--fa:"";--fa--fa:""}.fa-arrow-turn-down{--fa:"ï…‰";--fa--fa:""}.fa-level-down{--fa:"ï…‰";--fa--fa:""}.fa-person-falling-burst{--fa:"";--fa--fa:""}.fa-award{--fa:"ï•™";--fa--fa:""}.fa-ticket-simple{--fa:"ï¿";--fa--fa:"ï¿ï¿"}.fa-ticket-alt{--fa:"ï¿";--fa--fa:"ï¿ï¿"}.fa-building{--fa:"";--fa--fa:""}.fa-angles-left{--fa:"ï„€";--fa--fa:""}.fa-angle-double-left{--fa:"ï„€";--fa--fa:""}.fa-qrcode{--fa:"";--fa--fa:""}.fa-clock-rotate-left{--fa:"";--fa--fa:""}.fa-history{--fa:"";--fa--fa:""}.fa-face-grin-beam-sweat{--fa:"ï–ƒ";--fa--fa:""}.fa-grin-beam-sweat{--fa:"ï–ƒ";--fa--fa:""}.fa-file-export{--fa:"ï•®";--fa--fa:""}.fa-arrow-right-from-file{--fa:"ï•®";--fa--fa:""}.fa-shield{--fa:"";--fa--fa:""}.fa-shield-blank{--fa:"";--fa--fa:""}.fa-arrow-up-short-wide{--fa:"";--fa--fa:""}.fa-sort-amount-up-alt{--fa:"";--fa--fa:""}.fa-comment-nodes{--fa:"îš–";--fa--fa:"îš–îš–"}.fa-house-medical{--fa:"";--fa--fa:""}.fa-golf-ball-tee{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-golf-ball{--fa:"ï‘";--fa--fa:"ï‘ï‘"}.fa-circle-chevron-left{--fa:"ï„·";--fa--fa:"ï„·ï„·"}.fa-chevron-circle-left{--fa:"ï„·";--fa--fa:"ï„·ï„·"}.fa-house-chimney-window{--fa:"î€";--fa--fa:"î€î€"}.fa-pen-nib{--fa:"ï–­";--fa--fa:"ï–­ï–­"}.fa-tent-arrow-turn-left{--fa:"î–€";--fa--fa:""}.fa-tents{--fa:"î–‚";--fa--fa:"î–‚î–‚"}.fa-wand-magic{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-magic{--fa:"ïƒ";--fa--fa:"ïƒïƒ"}.fa-dog{--fa:"";--fa--fa:""}.fa-carrot{--fa:"";--fa--fa:""}.fa-moon{--fa:"";--fa--fa:""}.fa-wine-glass-empty{--fa:"ï—Ž";--fa--fa:"ï—Žï—Ž"}.fa-wine-glass-alt{--fa:"ï—Ž";--fa--fa:"ï—Žï—Ž"}.fa-cheese{--fa:"";--fa--fa:""}.fa-yin-yang{--fa:"ïš­";--fa--fa:"ïš­ïš­"}.fa-music{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-code-commit{--fa:"";--fa--fa:""}.fa-temperature-low{--fa:"ï«";--fa--fa:"ï«ï«"}.fa-person-biking{--fa:"ï¡Š";--fa--fa:"ï¡Šï¡Š"}.fa-biking{--fa:"ï¡Š";--fa--fa:"ï¡Šï¡Š"}.fa-broom{--fa:"";--fa--fa:""}.fa-shield-heart{--fa:"î•´";--fa--fa:"î•´î•´"}.fa-gopuram{--fa:"";--fa--fa:""}.fa-earth-oceania{--fa:"î‘»";--fa--fa:""}.fa-globe-oceania{--fa:"î‘»";--fa--fa:""}.fa-square-xmark{--fa:"ï‹“";--fa--fa:"ï‹“ï‹“"}.fa-times-square{--fa:"ï‹“";--fa--fa:"ï‹“ï‹“"}.fa-xmark-square{--fa:"ï‹“";--fa--fa:"ï‹“ï‹“"}.fa-hashtag{--fa:"\#";--fa--fa:"\#\#"}.fa-up-right-and-down-left-from-center{--fa:"ï¤";--fa--fa:"ï¤ï¤"}.fa-expand-alt{--fa:"ï¤";--fa--fa:"ï¤ï¤"}.fa-oil-can{--fa:"";--fa--fa:""}.fa-t{--fa:"T";--fa--fa:"TT"}.fa-hippo{--fa:"ï›­";--fa--fa:"ï›­ï›­"}.fa-chart-column{--fa:"";--fa--fa:""}.fa-infinity{--fa:"ï”´";--fa--fa:"ï”´ï”´"}.fa-vial-circle-check{--fa:"î––";--fa--fa:"î––î––"}.fa-person-arrow-down-to-line{--fa:"";--fa--fa:""}.fa-voicemail{--fa:"";--fa--fa:""}.fa-fan{--fa:"ï¡£";--fa--fa:""}.fa-person-walking-luggage{--fa:"î•”";--fa--fa:""}.fa-up-down{--fa:"";--fa--fa:""}.fa-arrows-alt-v{--fa:"";--fa--fa:""}.fa-cloud-moon-rain{--fa:"";--fa--fa:""}.fa-calendar{--fa:"";--fa--fa:""}.fa-trailer{--fa:"î";--fa--fa:"îî"}.fa-bahai{--fa:"";--fa--fa:""}.fa-haykal{--fa:"";--fa--fa:""}.fa-sd-card{--fa:"";--fa--fa:""}.fa-dragon{--fa:"";--fa--fa:""}.fa-shoe-prints{--fa:"ï•‹";--fa--fa:"ï•‹ï•‹"}.fa-circle-plus{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-plus-circle{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-face-grin-tongue-wink{--fa:"ï–‹";--fa--fa:"ï–‹ï–‹"}.fa-grin-tongue-wink{--fa:"ï–‹";--fa--fa:"ï–‹ï–‹"}.fa-hand-holding{--fa:"ï’½";--fa--fa:""}.fa-plug-circle-exclamation{--fa:"î•";--fa--fa:"î•î•"}.fa-link-slash{--fa:"";--fa--fa:""}.fa-chain-broken{--fa:"";--fa--fa:""}.fa-chain-slash{--fa:"";--fa--fa:""}.fa-unlink{--fa:"";--fa--fa:""}.fa-clone{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-person-walking-arrow-loop-left{--fa:"î•‘";--fa--fa:"î•‘î•‘"}.fa-arrow-up-z-a{--fa:"";--fa--fa:""}.fa-sort-alpha-up-alt{--fa:"";--fa--fa:""}.fa-fire-flame-curved{--fa:"";--fa--fa:""}.fa-fire-alt{--fa:"";--fa--fa:""}.fa-tornado{--fa:"ï¯";--fa--fa:"ï¯ï¯"}.fa-file-circle-plus{--fa:"î’”";--fa--fa:""}.fa-book-quran{--fa:"";--fa--fa:""}.fa-quran{--fa:"";--fa--fa:""}.fa-anchor{--fa:"";--fa--fa:""}.fa-border-all{--fa:"ï¡Œ";--fa--fa:""}.fa-face-angry{--fa:"ï•–";--fa--fa:"ï•–ï•–"}.fa-angry{--fa:"ï•–";--fa--fa:"ï•–ï•–"}.fa-cookie-bite{--fa:"";--fa--fa:""}.fa-arrow-trend-down{--fa:"î‚—";--fa--fa:"î‚—î‚—"}.fa-rss{--fa:"ï‚ž";--fa--fa:"ï‚žï‚ž"}.fa-feed{--fa:"ï‚ž";--fa--fa:"ï‚žï‚ž"}.fa-draw-polygon{--fa:"ï—®";--fa--fa:""}.fa-scale-balanced{--fa:"";--fa--fa:""}.fa-balance-scale{--fa:"";--fa--fa:""}.fa-gauge-simple-high{--fa:"";--fa--fa:""}.fa-tachometer{--fa:"";--fa--fa:""}.fa-tachometer-fast{--fa:"";--fa--fa:""}.fa-shower{--fa:"ï‹Œ";--fa--fa:""}.fa-desktop{--fa:"ïŽ";--fa--fa:"ïŽïŽ"}.fa-desktop-alt{--fa:"ïŽ";--fa--fa:"ïŽïŽ"}.fa-m{--fa:"M";--fa--fa:"MM"}.fa-table-list{--fa:"";--fa--fa:""}.fa-th-list{--fa:"";--fa--fa:""}.fa-comment-sms{--fa:"ïŸ";--fa--fa:"ïŸïŸ"}.fa-sms{--fa:"ïŸ";--fa--fa:"ïŸïŸ"}.fa-book{--fa:"";--fa--fa:""}.fa-user-plus{--fa:"";--fa--fa:""}.fa-check{--fa:"";--fa--fa:""}.fa-battery-three-quarters{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-battery-4{--fa:"ï‰";--fa--fa:"ï‰ï‰"}.fa-house-circle-check{--fa:"";--fa--fa:""}.fa-angle-left{--fa:"ï„„";--fa--fa:"ï„„ï„„"}.fa-diagram-successor{--fa:"";--fa--fa:""}.fa-truck-arrow-right{--fa:"î–‹";--fa--fa:"î–‹î–‹"}.fa-arrows-split-up-and-left{--fa:"î’¼";--fa--fa:""}.fa-hand-fist{--fa:"";--fa--fa:""}.fa-fist-raised{--fa:"";--fa--fa:""}.fa-cloud-moon{--fa:"";--fa--fa:""}.fa-briefcase{--fa:"";--fa--fa:""}.fa-person-falling{--fa:"";--fa--fa:""}.fa-image-portrait{--fa:"ï ";--fa--fa:"ï ï "}.fa-portrait{--fa:"ï ";--fa--fa:"ï ï "}.fa-user-tag{--fa:"";--fa--fa:""}.fa-rug{--fa:"î•©";--fa--fa:"î•©î•©"}.fa-earth-europe{--fa:"";--fa--fa:""}.fa-globe-europe{--fa:"";--fa--fa:""}.fa-cart-flatbed-suitcase{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-luggage-cart{--fa:"ï–";--fa--fa:"ï–ï–"}.fa-rectangle-xmark{--fa:"ï";--fa--fa:"ïï"}.fa-rectangle-times{--fa:"ï";--fa--fa:"ïï"}.fa-times-rectangle{--fa:"ï";--fa--fa:"ïï"}.fa-window-close{--fa:"ï";--fa--fa:"ïï"}.fa-baht-sign{--fa:"";--fa--fa:""}.fa-book-open{--fa:"";--fa--fa:""}.fa-book-journal-whills{--fa:"";--fa--fa:""}.fa-journal-whills{--fa:"";--fa--fa:""}.fa-handcuffs{--fa:"";--fa--fa:""}.fa-triangle-exclamation{--fa:"ï±";--fa--fa:"ï±ï±"}.fa-exclamation-triangle{--fa:"ï±";--fa--fa:"ï±ï±"}.fa-warning{--fa:"ï±";--fa--fa:"ï±ï±"}.fa-database{--fa:"";--fa--fa:""}.fa-share{--fa:"ï¤";--fa--fa:"ï¤ï¤"}.fa-mail-forward{--fa:"ï¤";--fa--fa:"ï¤ï¤"}.fa-bottle-droplet{--fa:"î“„";--fa--fa:"î“„î“„"}.fa-mask-face{--fa:"";--fa--fa:""}.fa-hill-rockslide{--fa:"";--fa--fa:""}.fa-right-left{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-exchange-alt{--fa:"ï¢";--fa--fa:"ï¢ï¢"}.fa-paper-plane{--fa:"";--fa--fa:""}.fa-road-circle-exclamation{--fa:"î•¥";--fa--fa:""}.fa-dungeon{--fa:"ï›™";--fa--fa:""}.fa-align-right{--fa:"";--fa--fa:""}.fa-money-bill-1-wave{--fa:"ï”»";--fa--fa:""}.fa-money-bill-wave-alt{--fa:"ï”»";--fa--fa:""}.fa-life-ring{--fa:"ï‡";--fa--fa:"ï‡ï‡"}.fa-hands{--fa:"";--fa--fa:""}.fa-sign-language{--fa:"";--fa--fa:""}.fa-signing{--fa:"";--fa--fa:""}.fa-calendar-day{--fa:"";--fa--fa:""}.fa-water-ladder{--fa:"ï—…";--fa--fa:"ï—…ï—…"}.fa-ladder-water{--fa:"ï—…";--fa--fa:"ï—…ï—…"}.fa-swimming-pool{--fa:"ï—…";--fa--fa:"ï—…ï—…"}.fa-arrows-up-down{--fa:"ï½";--fa--fa:"ï½ï½"}.fa-arrows-v{--fa:"ï½";--fa--fa:"ï½ï½"}.fa-face-grimace{--fa:"ï•¿";--fa--fa:"ï•¿ï•¿"}.fa-grimace{--fa:"ï•¿";--fa--fa:"ï•¿ï•¿"}.fa-wheelchair-move{--fa:"î‹Ž";--fa--fa:"î‹Žî‹Ž"}.fa-wheelchair-alt{--fa:"î‹Ž";--fa--fa:"î‹Žî‹Ž"}.fa-turn-down{--fa:"";--fa--fa:""}.fa-level-down-alt{--fa:"";--fa--fa:""}.fa-person-walking-arrow-right{--fa:"î•’";--fa--fa:"î•’î•’"}.fa-square-envelope{--fa:"";--fa--fa:""}.fa-envelope-square{--fa:"";--fa--fa:""}.fa-dice{--fa:"";--fa--fa:""}.fa-bowling-ball{--fa:"ï¶";--fa--fa:"ï¶ï¶"}.fa-brain{--fa:"ï—œ";--fa--fa:""}.fa-bandage{--fa:"ï‘¢";--fa--fa:""}.fa-band-aid{--fa:"ï‘¢";--fa--fa:""}.fa-calendar-minus{--fa:"";--fa--fa:""}.fa-circle-xmark{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-times-circle{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-xmark-circle{--fa:"ï—";--fa--fa:"ï—ï—"}.fa-gifts{--fa:"ïžœ";--fa--fa:""}.fa-hotel{--fa:"ï–”";--fa--fa:""}.fa-earth-asia{--fa:"";--fa--fa:""}.fa-globe-asia{--fa:"";--fa--fa:""}.fa-id-card-clip{--fa:"ï‘¿";--fa--fa:"ï‘¿ï‘¿"}.fa-id-card-alt{--fa:"ï‘¿";--fa--fa:"ï‘¿ï‘¿"}.fa-magnifying-glass-plus{--fa:"";--fa--fa:""}.fa-search-plus{--fa:"";--fa--fa:""}.fa-thumbs-up{--fa:"ï…¤";--fa--fa:""}.fa-user-clock{--fa:"";--fa--fa:""}.fa-hand-dots{--fa:"ï‘¡";--fa--fa:"ï‘¡ï‘¡"}.fa-allergies{--fa:"ï‘¡";--fa--fa:"ï‘¡ï‘¡"}.fa-file-invoice{--fa:"ï•°";--fa--fa:"ï•°ï•°"}.fa-window-minimize{--fa:"ï‹‘";--fa--fa:"ï‹‘ï‹‘"}.fa-mug-saucer{--fa:"";--fa--fa:""}.fa-coffee{--fa:"";--fa--fa:""}.fa-brush{--fa:"ï•";--fa--fa:"ï•ï•"}.fa-file-half-dashed{--fa:"";--fa--fa:""}.fa-mask{--fa:"";--fa--fa:""}.fa-magnifying-glass-minus{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-search-minus{--fa:"ï€";--fa--fa:"ï€ï€"}.fa-ruler-vertical{--fa:"";--fa--fa:""}.fa-user-large{--fa:"ï†";--fa--fa:"ï†ï†"}.fa-user-alt{--fa:"ï†";--fa--fa:"ï†ï†"}.fa-train-tram{--fa:"î–´";--fa--fa:"î–´î–´"}.fa-user-nurse{--fa:"ï ¯";--fa--fa:""}.fa-syringe{--fa:"ï’Ž";--fa--fa:"ï’Žï’Ž"}.fa-cloud-sun{--fa:"";--fa--fa:""}.fa-stopwatch-20{--fa:"î¯";--fa--fa:"î¯î¯"}.fa-square-full{--fa:"ï‘œ";--fa--fa:""}.fa-magnet{--fa:"ï¶";--fa--fa:"ï¶ï¶"}.fa-jar{--fa:"î”–";--fa--fa:"î”–î”–"}.fa-note-sticky{--fa:"";--fa--fa:""}.fa-sticky-note{--fa:"";--fa--fa:""}.fa-bug-slash{--fa:"î’";--fa--fa:"î’î’"}.fa-arrow-up-from-water-pump{--fa:"î’¶";--fa--fa:""}.fa-bone{--fa:"ï——";--fa--fa:"ï——ï——"}.fa-table-cells-row-unlock{--fa:"îš‘";--fa--fa:"îš‘îš‘"}.fa-user-injured{--fa:"";--fa--fa:""}.fa-face-sad-tear{--fa:"ï–´";--fa--fa:"ï–´ï–´"}.fa-sad-tear{--fa:"ï–´";--fa--fa:"ï–´ï–´"}.fa-plane{--fa:"ï²";--fa--fa:"ï²ï²"}.fa-tent-arrows-down{--fa:"î–";--fa--fa:"î–î–"}.fa-exclamation{--fa:"\!";--fa--fa:"\!\!"}.fa-arrows-spin{--fa:"î’»";--fa--fa:""}.fa-print{--fa:"";--fa--fa:""}.fa-turkish-lira-sign{--fa:"";--fa--fa:""}.fa-try{--fa:"";--fa--fa:""}.fa-turkish-lira{--fa:"";--fa--fa:""}.fa-dollar-sign{--fa:"\$";--fa--fa:"\$\$"}.fa-dollar{--fa:"\$";--fa--fa:"\$\$"}.fa-usd{--fa:"\$";--fa--fa:"\$\$"}.fa-x{--fa:"X";--fa--fa:"XX"}.fa-magnifying-glass-dollar{--fa:"";--fa--fa:""}.fa-search-dollar{--fa:"";--fa--fa:""}.fa-users-gear{--fa:"";--fa--fa:""}.fa-users-cog{--fa:"";--fa--fa:""}.fa-person-military-pointing{--fa:"î•Š";--fa--fa:"î•Šî•Š"}.fa-building-columns{--fa:"";--fa--fa:""}.fa-bank{--fa:"";--fa--fa:""}.fa-institution{--fa:"";--fa--fa:""}.fa-museum{--fa:"";--fa--fa:""}.fa-university{--fa:"";--fa--fa:""}.fa-umbrella{--fa:"";--fa--fa:""}.fa-trowel{--fa:"î–‰";--fa--fa:""}.fa-d{--fa:"D";--fa--fa:"DD"}.fa-stapler{--fa:"î–¯";--fa--fa:""}.fa-masks-theater{--fa:"";--fa--fa:""}.fa-theater-masks{--fa:"";--fa--fa:""}.fa-kip-sign{--fa:"";--fa--fa:""}.fa-hand-point-left{--fa:"ï‚¥";--fa--fa:""}.fa-handshake-simple{--fa:"";--fa--fa:""}.fa-handshake-alt{--fa:"";--fa--fa:""}.fa-jet-fighter{--fa:"";--fa--fa:""}.fa-fighter-jet{--fa:"";--fa--fa:""}.fa-square-share-nodes{--fa:"";--fa--fa:""}.fa-share-alt-square{--fa:"";--fa--fa:""}.fa-barcode{--fa:"";--fa--fa:""}.fa-plus-minus{--fa:"î¼";--fa--fa:"î¼î¼"}.fa-video{--fa:"";--fa--fa:""}.fa-video-camera{--fa:"";--fa--fa:""}.fa-graduation-cap{--fa:"ï†";--fa--fa:"ï†ï†"}.fa-mortar-board{--fa:"ï†";--fa--fa:"ï†ï†"}.fa-hand-holding-medical{--fa:"îœ";--fa--fa:"îœîœ"}.fa-person-circle-check{--fa:"";--fa--fa:""}.fa-turn-up{--fa:"";--fa--fa:""}.fa-level-up-alt{--fa:"";--fa--fa:""}.sr-only,.fa-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.sr-only-focusable:not(:focus),.fa-sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}/*! + * Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) * Copyright 2024 Fonticons, Inc. */:root,:host{--fa-style-family-classic: "Font Awesome 6 Free";--fa-font-solid: normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url("../fonts/fa-solid-900.woff2") format("woff2"),url("../fonts/fa-solid-900.ttf") format("truetype")}.fas,.fa-solid{font-weight:900}*{margin:0;padding:0}html,body{height:100%}body{font-family:sans-serif;line-height:1.5;min-height:100%}.wrap{width:80%;max-width:1100px;margin:auto;position:relative}.logospace{float:left}html[dir=rtl] .logospace{float:right}.menuspace{float:right}html[dir=rtl] .menuspace{float:left}.center{text-align:center}.v-center{display:table-cell;vertical-align:middle}i{font-style:italic}h1{margin:1em 0;font-size:2em;font-weight:900}h2{margin:1em 0;font-size:1.5em;font-weight:700;color:#1c1c1c;border-bottom:solid 1px #bbb}h3{font-weight:500;color:#2e3436;padding:0;margin-top:0}p{padding:.5em 0;margin-bottom:1em}a{color:#191970}a:hover,a:focus,a.pure-menu-link:hover,a.pure-menu-link:focus,.pure-menu-selected a.pure-menu-link:hover,.pure-menu-selected a.pure-menu-link:focus{color:#fff;background-color:#444;padding:.5em 1em}a:hover,a:focus{padding:.15rem}.overflow{overflow:hidden}ul{padding-left:1.5em}strong,b{font-weight:bold}pre,code,kbd,samp,tt{font-family:monospace;font-size:.9rem;padding:0 .2rem}.xmldata{font-family:monospace}#layout,#menu,#foot,.menu-link{-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-ms-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}#layout.active #menu{right:11em;width:11em}#menu{margin-right:-11em;width:11em;position:fixed;top:0;right:0;bottom:0;z-index:1000;background:#e8410c;overflow-y:auto;-webkit-overflow-scrolling:touch}#menu a{color:#fff;border:none;padding:.6em 0 .6em .6em}#menu .pure-menu,#menu .pure-menu ul{border:none;background:rgba(0,0,0,0)}#menu .pure-menu ul,#menu .pure-menu .menu-item-divided{border-top:1px solid #db0100}#menu .pure-menu-selected,#menu .pure-menu-heading{background:#b8002c;color:#000}#menu .pure-menu-selected a{color:#fff}#menu .pure-menu-heading{font-size:110%;color:#fff;margin:0;text-transform:none}.menu-link{position:relative;display:block;top:0;right:0;background:rgba(0,0,0,0);z-index:10;height:2rem;padding:2rem 0;text-decoration:none}.menu-link:hover,.menu-link:focus{padding:2rem 0;background:none !important}.menu-link span{position:relative;display:block;color:#fff}.menu-link span,.menu-link span::before,.menu-link span::after{background-color:rgba(0,0,0,0)}.menu-link span:focus,.menu-link span:hover{color:rgba(1,1,1,.8)}@media screen and (max-width: 40em){#layout.active{position:relative;right:11em}#menuLink.menu-link.active{position:fixed;right:13em}#foot.active{margin-right:11em}}#header{height:6rem;background:linear-gradient(141deg, #b8002c 0%, #db0100 51%, #e8410c 75%)}.logo-header{min-width:8em;height:6rem;max-width:70%}#logo{font-family:sans-serif;font-size:2.5em;color:#fff;text-shadow:0 3px 2px #532900}.simple{font-weight:300}.saml{font-family:Verdana,sans-serif;letter-spacing:-0.12em;font-weight:600;margin-left:-0.05em}.language-menu{font-family:sans-serif;font-weight:400;min-width:10rem;padding:0em .6em !important}.language-bar{height:6rem}#layout{right:0;padding-right:0;min-height:100%;margin:0 auto -6rem}#content{padding-top:2em;padding-bottom:2rem}.message-box{background-color:#f4f4f4;border-left:.3125rem solid #444;box-shadow:0 5px 8px -6px rgba(0,0,0,.2);margin:1rem 0;padding:1.3rem;position:relative}.message-box.error{background-color:#f7e4e1;border-left-color:#cc4b37}.message-box.warning{background-color:#fffdbf;border-left-color:#f9f56b}.message-box.success{background-color:#daf7e6;border-left-color:#46cc48}.auth_methods{margin-top:2em;width:35%}.code-box{margin-bottom:1em;border:1px solid #ccc}.code-box a{padding:.5em}.code-box-content{word-break:break-all;font-size:1em;line-height:1.15;padding:.5em 1em;display:inline-block;min-height:1em;height:100%;white-space:pre-wrap;font-family:monospace}.code-box-content::selection{color:#000;background:#fffdbf}.code-box-title{border-bottom:1px solid #ccc;background-color:#e0e0e0;padding:.5em 0 .5em .5em}pre#xmlmetadata{width:98%}#bottom,#push{height:6rem}#footer{width:100%;background:linear-gradient(141deg, #b8002c 0%, #db0100 51%, #e8410c 75%);height:4rem;padding:2rem 0 0;text-align:center;color:#fff}#footer a,#footer a:visited{color:#fff}#footer a:focus,#footer a:hover,#footer a:visited:focus,#footer a:visited:hover{background-color:#fff;color:#000;padding:.15rem;margin-left:-0.15rem;margin-top:-0.15rem;text-decoration:none}.copyrights{padding-top:.5rem;height:3.5rem;font-size:.8rem}.logo-footer-space{position:absolute;right:0;top:50%;transform:translate(0, -50%)}html[dir=rtl] .logo-footer-space{right:auto;left:0}.logo-footer{height:4rem}.text-area{margin-top:.5em;width:100%;font-size:.9em;line-height:1.15}.file-upload input[type=url][disabled]{cursor:pointer;color:inherit}input[type=file]{color:#000}.center-form{display:flex;justify-content:center}.login-form-start,.login-form-submit{margin-top:3ex}input#username:disabled{color:#000}.v-center-right{position:absolute;left:0;top:50%;transform:translate(0, -50%)}.pure-button,.pure-form input.edge,.pure-form textarea.edge{border-radius:0}.pure-form input[type=checkbox]{margin-right:.8ex;vertical-align:baseline}.pure-control-group{margin-bottom:1ex}.pure-form-aligned .pure-controls{margin:0 0 0 11em}.pure-select{float:right}html[dir=rtl] .pure-select{float:left}.code-box-title .clipboard-btn{background-color:#f0f0f0;border:1px solid #ccc;position:absolute;right:0;height:inherit;margin-top:-2em;margin-right:4px}.pure-button{margin-left:1ex}.pure-button:hover,.pure-button:focus{background-color:#555;padding:.5em 1em;color:#fff}.pure-button-red{background-color:#db0100;color:#fff}.pure-button-red:hover,.pure-button-red:focus{background-color:#555;padding:.5em 1em}.pure-button.hollow{background-color:#fff;color:#6f6f6f;border:solid 1px #e6e6e6}.pure-button.hollow:hover{background-image:none}.pure-button.hollow[disabled]{cursor:auto;opacity:initial;pointer-events:auto;-webkit-user-drag:auto;-webkit-user-select:auto;-moz-user-select:text;-ms-user-select:text;user-select:text}.pure-button.hljs{display:inline-block;border:0;background-color:rgba(0,0,0,0)}.pure-button.hljs:hover,.pure-button.hljs:focus{background-color:#f0f0f0;color:#000}.pure-button-group .pure-button:first-child,.pure-button-group .pure-button:last-child{border-radius:0}.pure-button-group.two-elements .pure-button{margin:0;line-height:unset;border:1px solid #e6e6e6}.pure-button-group.two-elements form{display:inline}.pure-button-group.two-elements .pure-button:first-child{border-right:none}.pure-button-group.two-elements .pure-button:last-child{border-right:1px solid #e6e6e6}.pure-button-group .pure-button.show-files{max-width:450px;overflow:hidden}.top-right-corner{position:absolute;right:1.75em}input#postLoginSubmitButton{display:none}.fa{font-family:"Font Awesome 6 Free",sans-serif !important;font-weight:400}span.fa,i.fa{padding:0 .5em}.message-box span.fa,.message-box i.fa{padding:0}.pure-table-attributes{table-layout:fixed;width:100%}.attrname{text-align:right}.attrvalue{overflow-wrap:break-word}table.attributes ul{padding:inherit}@media screen and (max-width: 40em){.pure-form .pure-input-sm-1-1{width:100%}}@media screen and (max-width: 40em){.wrap{width:90%}.pure-form-aligned .pure-controls{margin:.5em 0 0;float:left}#layout{padding-top:0;margin-bottom:-4rem}.auth_methods{width:60%}#logo{font-size:1.8em}#footer{height:2.5rem;padding-top:1.5rem}#footer .copyrights{height:1rem;padding-top:0}}@media screen and (max-width: 0),screen and (min-width: 40em){.show-for-small-only{display:none !important}.input-sm-placeholder{display:inline-block}}@media screen and (min-width: 40em){.hide-for-large{display:none !important}}@media screen and (max-width: 40em){.show-for-large{display:none !important}}div.preferredidp{border:1px dashed #ccc;background:#eee;padding:2px 2em}.clear{clear:both}.breathe-top{margin-top:1em}.expandable{border:solid 1px #bbb;width:100%}.expandable .general{padding:1em}.expandable .content{display:none;padding:1em}.expandable .expander{cursor:pointer;text-align:center;padding:.25em;display:block;color:#000;background-color:#f4f4f4;border-top:solid 1px #bbb}.expandable .expander:focus,.expandable .expander:hover{background-color:#555;color:#fff}.expandable .expander::after{content:"ï¸";font-family:"Font Awesome 6 Free",sans-serif;font-weight:400}.expandable.expanded .content{display:block;border-left:solid .25em #555;border-right:solid .25em #555}.expandable.expanded .expander{border-bottom:none;border-top:solid 1px #bbb;border-left:solid .25em #555;border-right:solid .25em #555}.expandable.expanded .expander::after{content:"ï·"}.hidden{display:none}.idp{border:1px solid silver;padding:1ex;margin:1ex}.idp .idpname{font-size:larger;font-weight:bold}.idp .idpdesc{font-size:small;color:gray}.right{float:right}.left{float:left} diff --git a/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css.map b/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css.map index 6b894663d..5ff09a658 100644 --- a/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css.map +++ b/.extlib/simplesamlphp/public/assets/base/css/stylesheet.css.map @@ -1 +1 @@ -{"version":3,"file":"css/stylesheet.css","mappings":"AAAA;;;CAGC;;AAED;;;;;;;;;;;;;CAaC,SAAS;CACT,UAAU;CACV,SAAS;CACT,eAAe;CACf,aAAa;CACb,wBAAwB;AACzB;AACA,gDAAgD;AAChD;;CAEC,cAAc;AACf;AACA,kDAAkD;AAClD;IACI,aAAa;AACjB;AACA;CACC,cAAc;AACf;AACA;CACC,gBAAgB;AACjB;AACA;CACC,YAAY;AACb;AACA;;CAEC,WAAW;CACX,aAAa;AACd;AACA;CACC,yBAAyB;CACzB,iBAAiB;AAClB;;ACnDA;;;;;CAKC;AACD;;;CAGC;AACD,2EAA2E;;AAE3E;+EAC+E;;AAE/E;;;EAGE;;AAEF;EACE,iBAAiB,EAAE,MAAM;EACzB,8BAA8B,EAAE,MAAM;AACxC;;AAEA;+EAC+E;;AAE/E;;EAEE;;AAEF;EACE,SAAS;AACX;;AAEA;;EAEE;;AAEF;EACE,cAAc;AAChB;;AAEA;;;EAGE;;AAEF;EACE,cAAc;EACd,gBAAgB;AAClB;;AAEA;+EAC+E;;AAE/E;;;EAGE;;AAEF;EACE,uBAAuB,EAAE,MAAM;EAC/B,SAAS,EAAE,MAAM;EACjB,iBAAiB,EAAE,MAAM;AAC3B;;AAEA;;;EAGE;;AAEF;EACE,iCAAiC,EAAE,MAAM;EACzC,cAAc,EAAE,MAAM;AACxB;;AAEA;+EAC+E;;AAE/E;;EAEE;;AAEF;EACE,6BAA6B;AAC/B;;AAEA;;;EAGE;;AAEF;EACE,mBAAmB,EAAE,MAAM;EAC3B,0BAA0B,EAAE,MAAM;EAClC,yCAAyC;UACjC,iCAAiC,EAAE,MAAM;AACnD;;AAEA;;EAEE;;AAEF;;EAEE,mBAAmB;AACrB;;AAEA;;;EAGE;;AAEF;;;EAGE,iCAAiC,EAAE,MAAM;EACzC,cAAc,EAAE,MAAM;AACxB;;AAEA;;EAEE;;AAEF;EACE,cAAc;AAChB;;AAEA;;;EAGE;;AAEF;;EAEE,cAAc;EACd,cAAc;EACd,kBAAkB;EAClB,wBAAwB;AAC1B;;AAEA;EACE,eAAe;AACjB;;AAEA;EACE,WAAW;AACb;;AAEA;+EAC+E;;AAE/E;;EAEE;;AAEF;EACE,kBAAkB;AACpB;;AAEA;+EAC+E;;AAE/E;;;EAGE;;AAEF;;;;;EAKE,oBAAoB,EAAE,MAAM;EAC5B,eAAe,EAAE,MAAM;EACvB,iBAAiB,EAAE,MAAM;EACzB,SAAS,EAAE,MAAM;AACnB;;AAEA;;;EAGE;;AAEF;QACQ,MAAM;EACZ,iBAAiB;AACnB;;AAEA;;;EAGE;;AAEF;SACS,MAAM;EACb,oBAAoB;AACtB;;AAEA;;EAEE;;AAEF;;;;EAIE,0BAA0B;AAC5B;;AAEA;;EAEE;;AAEF;;;;EAIE,kBAAkB;EAClB,UAAU;AACZ;;AAEA;;EAEE;;AAEF;;;;EAIE,8BAA8B;AAChC;;AAEA;;EAEE;;AAEF;EACE,8BAA8B;AAChC;;AAEA;;;;;EAKE;;AAEF;EACE,sBAAsB,EAAE,MAAM;EAC9B,cAAc,EAAE,MAAM;EACtB,cAAc,EAAE,MAAM;EACtB,eAAe,EAAE,MAAM;EACvB,UAAU,EAAE,MAAM;EAClB,mBAAmB,EAAE,MAAM;AAC7B;;AAEA;;EAEE;;AAEF;EACE,wBAAwB;AAC1B;;AAEA;;EAEE;;AAEF;EACE,cAAc;AAChB;;AAEA;;;EAGE;;AAEF;;EAEE,sBAAsB,EAAE,MAAM;EAC9B,UAAU,EAAE,MAAM;AACpB;;AAEA;;EAEE;;AAEF;;EAEE,YAAY;AACd;;AAEA;;;EAGE;;AAEF;EACE,6BAA6B,EAAE,MAAM;EACrC,oBAAoB,EAAE,MAAM;AAC9B;;AAEA;;EAEE;;AAEF;EACE,wBAAwB;AAC1B;;AAEA;;;EAGE;;AAEF;EACE,0BAA0B,EAAE,MAAM;EAClC,aAAa,EAAE,MAAM;AACvB;;AAEA;+EAC+E;;AAE/E;;EAEE;;AAEF;EACE,cAAc;AAChB;;AAEA;;EAEE;;AAEF;EACE,kBAAkB;AACpB;;AAEA;+EAC+E;;AAE/E;;EAEE;;AAEF;EACE,aAAa;AACf;;AAEA;;EAEE;;AAEF;EACE,aAAa;AACf;;AAEA,0BAA0B;;AAE1B;;+EAE+E;;AAE/E;;EAEE;;AAEF;IACI,uBAAuB;AAC3B;;AAEA;;EAEE;;AAEF;;IAEI,wBAAwB;AAC5B;;AAEA;;;EAGE;AACF;IACI,eAAe;IACf,YAAY;IACZ,cAAc;AAClB;;AAEA,oFAAoF;;AAEpF;IACI,aAAa;IACb,mBAAmB;;IAEnB,6CAA6C;IAC7C,yBAAyB;AAC7B;;AAEA;IACI,qBAAqB;IACrB,mBAAmB;AACvB;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8CI,qBAAqB;IACrB,sBAAsB;IACtB,oBAAoB;IACpB,mBAAmB;IACnB,oBAAoB;AACxB;;AAEA;IACI,cAAc;AAClB;;AAEA;;IAEI,cAAc;AAClB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;IACI,UAAU;AACd;;AAEA;IACI,eAAe;AACnB;;AAEA;;IAEI,UAAU;AACd;;AAEA;IACI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;IACI,UAAU;AACd;;AAEA;;IAEI,eAAe;AACnB;;AAEA;IACI,eAAe;AACnB;;AAEA;;IAEI,UAAU;AACd;;AAEA;IACI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;IACI,UAAU;AACd;;AAEA;;IAEI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;IACI,eAAe;AACnB;;AAEA;;IAEI,UAAU;AACd;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,UAAU;AACd;;AAEA;;IAEI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;;IAEI,eAAe;AACnB;;AAEA;IACI,eAAe;AACnB;;AAEA;;;;IAII,WAAW;AACf;AACA;IACI,cAAc;IACd,qBAAqB;IACrB,mBAAmB;IACnB,mBAAmB;IACnB,sBAAsB;IACtB,kBAAkB;IAClB,eAAe;IACf,uBAAuB;IACvB,yBAAyB;YACjB,iBAAiB;IACzB,sBAAsB;AAC1B;;AAEA,+CAA+C;AAC/C;IACI,UAAU;IACV,SAAS;AACb;;AAEA,2BAA2B;AAC3B;IACI,uBAAuB,EAAE,+CAA+C;IACxE,6BAA6B,EAAE,qDAAqD;AACxF;;AAEA;;IAEI,qBAAqB;AACzB;;AAEA;IACI,sBAAsB;IACtB,oBAAoB;IACpB,mBAAmB;IACnB,oBAAoB;AACxB;;AAEA,6BAA6B;;AAE7B;IACI,oBAAoB;IACpB,eAAe;IACf,kBAAkB;IAClB,0BAA0B;IAC1B,6BAA6B;IAC7B,yBAAyB;IACzB,qBAAqB;IACrB,kBAAkB;AACtB;;AAEA;;;IAGI,wFAAwF;AAC5F;AACA;IACI,UAAU;AACd;AACA;;IAEI,8EAA8E;IAC9E,kBAAkB;AACtB;;AAEA;;;;;IAKI,YAAY;IACZ,sBAAsB;IACtB,aAAa;IACb,mBAAmB;IACnB,gBAAgB;IAChB,oBAAoB;AACxB;;AAEA;IACI,aAAa;AACjB;;AAEA;;;;IAII,kCAAkC;IAClC,WAAW;AACf;;AAEA,kBAAkB;AAClB;IACI,SAAS;IACT,gBAAgB;IAChB,0CAA0C;;AAE9C;;AAEA;IACI,2BAA2B;IAC3B,8BAA8B;AAClC;AACA;IACI,4BAA4B;IAC5B,+BAA+B;IAC/B,kBAAkB;AACtB;;AAEA,0BAA0B;AAC1B;;;;;CAKC;;AAED;;;;;;;;;;;;;;;;IAgBI,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;IACtB,gCAAgC;IAChC,kBAAkB;IAClB,sBAAsB;IACtB,sBAAsB;AAC1B;;AAEA;;;CAGC;AACD;IACI,oBAAoB;IACpB,qBAAqB;IACrB,sBAAsB;IACtB,gCAAgC;IAChC,kBAAkB;IAClB,sBAAsB;AAC1B;;;AAGA,+EAA+E;AAC/E,+FAA+F;AAC/F;IACI,oBAAoB;AACxB;;;AAGA;;;;;;;;;;;;;;;;IAgBI,UAAU;IACV,qBAAqB;AACzB;;AAEA;;;CAGC;AACD;IACI,UAAU;IACV,qBAAqB;AACzB;;AAEA;;;IAGI,2BAA2B;IAC3B,yBAAyB;AAC7B;AACA;;IAEI,eAAe;IACf,cAAc;AAClB;;AAEA;;;;;;;;;;;;;;;;IAgBI,mBAAmB;IACnB,yBAAyB;IACzB,cAAc;AAClB;;AAEA;;;CAGC;AACD;IACI,mBAAmB;IACnB,yBAAyB;IACzB,cAAc;AAClB;AACA;;;IAGI,sBAAsB,EAAE,wBAAwB;IAChD,WAAW,EAAE,oBAAoB;IACjC,kBAAkB;AACtB;;AAEA;;;IAGI,cAAc;IACd,qBAAqB;AACzB;AACA;;;IAGI,sBAAsB;AAC1B;AACA;IACI,sDAAsD;IACtD,cAAc;IACd,sBAAsB;IACtB,uBAAuB;AAC3B;AACA;IACI,YAAY;AAChB;AACA;IACI,qBAAqB;AACzB;AACA;IACI,SAAS;IACT,wBAAwB;IACxB,SAAS;AACb;AACA;IACI,cAAc;IACd,WAAW;IACX,gBAAgB;IAChB,oBAAoB;IACpB,WAAW;IACX,gCAAgC;AACpC;;AAEA;;;;;;;;;;;;;;;;;;IAkBI,cAAc;IACd,gBAAgB;AACpB;;AAEA;;;CAGC;AACD;IACI,cAAc;IACd,gBAAgB;AACpB;AACA;;;;IAII,qBAAqB;IACrB,sBAAsB;AAC1B;AACA;IACI,mBAAmB;AACvB;;AAEA,kBAAkB;AAClB;IACI,oBAAoB;AACxB;AACA;IACI,iBAAiB;IACjB,qBAAqB;IACrB,sBAAsB;IACtB,WAAW;IACX,iBAAiB;AACrB;AACA;IACI,sBAAsB;AAC1B;;AAEA,mBAAmB;AACnB;;IAEI,kBAAkB;IAClB,kBAAkB;AACtB;;AAEA,mBAAmB;AACnB;IACI,mBAAmB;AACvB;AACA;;IAEI,cAAc;IACd,aAAa;IACb,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;AACb;AACA;;IAEI,UAAU;AACd;AACA;;IAEI,QAAQ;IACR,0BAA0B;IAC1B,SAAS;AACb;AACA;;IAEI,QAAQ;IACR,kBAAkB;IAClB,SAAS;AACb;AACA;;IAEI,SAAS;IACT,0BAA0B;IAC1B,SAAS;AACb;AACA;IACI,gBAAgB;AACpB;;AAEA;IACI,WAAW;AACf;AACA;IACI,UAAU;AACd;AACA;IACI,UAAU;AACd;AACA;IACI,UAAU;AACd;AACA;IACI,UAAU;AACd;AACA;IACI,UAAU;AACd;;AAEA,0BAA0B;AAC1B;IACI,qBAAqB;IACrB,mBAAmB;IACnB,WAAW;IACX,sBAAsB;IACtB,kBAAkB;AACtB;;AAEA,yBAAyB;AACzB;IACI,cAAc;IACd,WAAW;IACX,kBAAkB;AACtB;;AAEA;IACI;QACI,iBAAiB;IACrB;;IAEA;;;;;;;;;;;;;;;;QAgBI,oBAAoB;QACpB,cAAc;IAClB;;IAEA;;;;;;;;;;;;;;;QAeI,gBAAgB;IACpB;;IAEA;QACI,oBAAoB;QACpB,gBAAgB;QAChB,cAAc;QACd,WAAW;IACf;;IAEA;QACI,mBAAmB;IACvB;;IAEA;;QAEI,cAAc;QACd,iBAAiB;QACjB,8EAA8E;QAC9E,sBAAsB;IAC1B;AACJ;;AAEA,oDAAoD;AACpD;IACI,sBAAsB;AAC1B;;AAEA;IACI,eAAe;IACf,OAAO;IACP,MAAM;IACN,UAAU;AACd;;AAEA;;IAEI,kBAAkB;AACtB;;AAEA;IACI,gBAAgB;IAChB,SAAS;IACT,UAAU;AACd;;AAEA;IACI,UAAU;IACV,SAAS;IACT,YAAY;AAChB;;AAEA;;IAEI,cAAc;IACd,qBAAqB;IACrB,mBAAmB;AACvB;;AAEA,oBAAoB;AACpB;IACI,WAAW;IACX,mBAAmB;AACvB;;AAEA;IACI,qBAAqB;AACzB;;AAEA,qEAAqE;AACrE;;;IAGI,qBAAqB;IACrB,sBAAsB;AAC1B;;AAEA,6CAA6C;AAC7C;IACI,cAAc;AAClB;;AAEA;IACI,aAAa;IACb,kBAAkB;IAClB,UAAU;IACV,MAAM;IACN,SAAS;IACT,UAAU;IACV,UAAU;AACd;;AAEA;IACI,OAAO;IACP,SAAS;IACT,cAAc;AAClB;;AAEA;;IAEI,cAAc;IACd,kBAAkB;AACtB;;AAEA,6CAA6C;AAC7C;IACI,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;AACpB;;AAEA,+CAA+C;AAC/C;IACI,gBAAgB;AACpB;;AAEA,qBAAqB;AACrB;IACI,kBAAkB;IAClB,kBAAkB;AACtB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,qBAAqB;AACzB;;AAEA;IACI,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,kEAAkE;IAClE,eAAe;AACnB;;AAEA,yBAAyB;;AAEzB;;IAEI,sBAAsB;IACtB,WAAW;IACX,cAAc;AAClB;;AAEA;IACI,UAAU;IACV,aAAa;IACb,eAAe;AACnB;;AAEA,0DAA0D;AAC1D;IACI,cAAc;IACd,WAAW;AACf;;AAEA;IACI,yBAAyB;IACzB,cAAc;AAClB;;AAEA;IACI,WAAW;AACf;;AAEA;IACI,sBAAsB;AAC1B;;AAEA;;IAEI,iBAAiB;AACrB;;AAEA;IACI,WAAW;AACf;;AAEA;IACI,6BAA6B;IAC7B,eAAe;AACnB;;AAEA;;;IAGI,sBAAsB;AAC1B;;AAEA;;IAEI,WAAW;AACf;;AAEA;IACI,4DAA4D;IAC5D,yBAAyB;IACzB,iBAAiB;IACjB,iBAAiB;IACjB,yBAAyB;AAC7B;;AAEA;IACI,WAAW;IACX,oCAAoC;IACpC,cAAc;IACd,kBAAkB;AACtB;;AAEA;;IAEI,8BAA8B,CAAC,yBAAyB;IACxD,uBAAuB;IACvB,kBAAkB;IAClB,SAAS;IACT,iBAAiB,EAAE,kDAAkD;IACrE,kBAAkB,EAAE,iBAAiB;AACzC;;AAEA;IACI,yBAAyB;IACzB,WAAW;IACX,gBAAgB;IAChB,sBAAsB;AAC1B;;AAEA;;;;CAIC;AACD;IACI,6BAA6B;AACjC;AACA;IACI,yBAAyB;AAC7B;;AAEA,2CAA2C;AAC3C;IACI,yBAAyB;AAC7B;;AAEA,oBAAoB;AACpB;IACI,gCAAgC;AACpC;AACA;IACI,sBAAsB;AAC1B;;;AAGA,+BAA+B;;AAE/B;;IAEI,uBAAuB;IACvB,gCAAgC;AACpC;AACA;IACI,sBAAsB;AAC1B;;AC9xCA;EACE,cAAc;EACd,gBAAgB;EAChB;AACF;AACA;EACE;AACF;AACA;;;;;;CAMC;AACD;;;;;;;CAOC;AACD;;;;;;;;;;;;;;;;;CAiBC;AACD;EACE,cAAc;EACd,gBAAgB;EAChB;AACF;AACA;EACE;AACF;AACA;EACE,cAAc;EACd;AACF;AACA;;EAEE,yBAAyB;EACzB;AACF;AACA,4CAA4C;AAC5C;;;;AAIA;AACA,gEAAgE;AAChE;EACE;AACF;AACA,+DAA+D;AAC/D;EACE;AACF;AACA,yEAAyE;AACzE;;;EAGE;AACF;AACA;EACE;AACF;AACA,+EAA+E;AAC/E;;;;;;EAME;AACF;AACA,2EAA2E;AAC3E;;;;;;EAME;AACF;AACA,0DAA0D;AAC1D;;;EAGE;AACF;AACA;EACE,iBAAiB;EACjB;AACF;AACA,kEAAkE;AAClE;;;;EAIE;AACF;AACA,4EAA4E;AAC5E,aAAa;AACb;;;;;EAKE;AACF;AACA,yDAAyD;AACzD;;;;;EAKE;AACF;AACA,sEAAsE;AACtE,uBAAuB;AACvB,0BAA0B;AAC1B,yBAAyB;AACzB,2BAA2B;AAC3B;;;;EAIE;AACF;AACA;EACE,cAAc;EACd;AACF;AACA,+EAA+E;AAC/E;;;CAGC;AACD;;;EAGE;AACF;AACA,8BAA8B;AAC9B;;EAEE;AACF,C;AChKQ;;;;ECFR,CCGA,IACE,0DACA,iCAGF,gFASE,kCACA,mCACA,wCACA,kBACA,oBACA,cACA,oBAGF,4CAKE,kCAGF,gBAEE,oCC/BA,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,QACE,eAMF,QCIA,iBACA,iBACA,sBDNA,OCIA,gBACA,0BACA,sBDNA,OCIA,iBACA,0BACA,6BDNA,OCIA,iBACA,kBACA,uBDNA,OCIA,gBACA,0BACA,wBDNA,QCIA,cACA,qBACA,yBCfF,OACE,kBACA,YCIwB,CCN1B,OACE,qBACA,uCACA,eAEA,4BAGF,OACE,sCACA,kBACA,kBACA,8BACA,oBCbF,WACE,0CACA,6CACA,2CACA,4CACA,sDAGF,cACE,WACA,0CAGF,eACE,YACA,yCCfF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,kEAGF,WACE,yBACA,8CACA,0DACA,oDACA,wEACA,wFAGF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,mFAGF,cACE,4BACA,8CACA,0DACA,oDACA,wEACA,mFAGF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,kEAGF,UACE,wBACA,8CACA,0DACA,oDACA,wEACA,6DAGF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,6DAGF,iBACE,kCAGF,yBAEE,uBACA,0DACA,oDACA,wEACA,+DAMF,uCACE,gGASE,qBACA,uBACA,4BACA,oBACA,wBAIJ,mBACE,0BACA,iDAGF,qBACE,uCACA,4GACA,wIACA,4GACA,yEACA,wCACA,0CAGF,mBACE,yCAGF,wBACE,QACE,yCACA,mBAEF,IACE,UACA,mDAIJ,mBACE,IACE,kHAIJ,oBACE,4BACA,2BACA,gCACA,gCACA,6BACA,4BACA,6BACA,4BACA,iCAGF,mBACE,0BACA,+BCnJF,cACE,wBAGF,eACE,yBAGF,eACE,yBAGF,oBACE,uBAGF,kBACE,uBAGF,mDAEE,wBAGF,cACE,4CC1BF,UACE,qBACA,WACA,gBACA,kBACA,qBLmCwB,CKlCxB,WLmCwB,CKhC1B,0BAEE,OACA,kBACA,kBACA,WACA,sCAGF,aACE,oBAGF,aACE,cAGF,YACE,8BCvBA,opqECHF,qBTqBE,kBACA,UACA,WACA,UACA,YACA,gBACA,sBACA,mBACA,eAKA,iEAbA,kBACA,UACA,WACA,UACA,YACA,gBACA,sBACA,mBACA,eUjCF;;;;EAAA,CAQA,YACE,iDACA,wDAIF,WACE,kCACA,kBACA,gBACA,kBR6BwB,CQ5BxB,2GAIF,eAEE,gBdRF,EACE,SACA,UAGF,UAEE,YAGF,KACE,uBACA,gBACA,gBAGF,MACE,UACA,iBACA,YACA,kBAGF,WACE,WAGF,yBACE,YAGF,WACE,YAGF,yBACE,WAGF,QACE,kBAGF,UAEE,mBACA,sBAGF,EACE,kBAGF,GACE,aACA,cACA,gBAGF,GACE,aACA,gBACA,gBACA,cACA,6BAGF,GACE,gBACA,cACA,UACA,aAGF,EACE,eACA,kBAGF,EACE,cAEA,oJAME,WACA,sBACA,iBAGF,gBAEE,eAIJ,UACE,gBAGF,GACE,mBAGF,SAEE,iBAGF,qBAKE,sBACA,gBACA,gBAGF,SACE,sBAUF,+BAIE,oCACA,iCACA,gCACA,+BACA,4BAMF,qBACE,WACA,WAOF,MACE,mBACA,WACA,eACA,MACA,QACA,SACA,aACA,kBArLiF,CAsLjF,gBACA,iCAMF,QACE,WACA,YACA,yBAMF,qCAEE,YACA,yBAMF,wDAEE,6BAMF,mDAEE,kBAzNkB,CA0NlB,WAMF,4BACE,WAMF,yBACE,eACA,WACA,SACA,oBAcF,WACE,kBACA,cACA,MACA,QACA,yBACA,WACA,YACA,eACA,qBAEA,kCAEE,eACA,2BAIJ,gBACE,kBACA,cACA,WAGF,+DAGE,+BAGF,4CAEE,qBAKF,oCACE,eACE,kBACA,WAKF,2BACE,eACA,WAGF,aACE,mBAOJ,QACE,YACA,yEAGF,aACE,cACA,YACA,cAGF,MACE,uBACA,gBACA,WACA,8BAGF,QACE,gBAGF,MACE,+BACA,uBACA,gBACA,oBAGF,eACE,uBACA,gBACA,gBACA,4BAGF,cACE,YAMF,QACE,QACA,gBACA,gBAGA,oBAGF,SACE,gBACA,oBAGF,aACE,yBACA,gCACA,yCACA,cACA,eACA,kBAGF,mBACE,yBACA,0BAGF,qBACE,wBA/Wa,CAgXb,0BAGF,qBACE,yBACA,0BAGF,cACE,eACA,UAGF,UACE,kBACA,sBAEA,YACE,aAIJ,kBACE,qBACA,cACA,iBACA,iBACA,qBACA,eACA,YACA,qBACA,sBAEA,6BACE,WACA,kBAnZW,CAuZf,gBACE,6BACA,yBACA,yBAGF,gBACE,UAOF,cAEE,YAGF,QACE,WACA,yEACA,YACA,iBACA,kBACA,WAEA,4BAEE,WAEA,gFAEE,sBACA,WACA,eACA,qBACA,oBACA,qBAKN,YACE,kBACA,cACA,gBAGF,mBACE,kBACA,QACA,QACA,6BAGF,iCACE,WACA,OAGF,aACE,YAMF,WACE,gBACA,WACA,eACA,iBAGF,uCACE,eACA,cAGF,iBACE,WAGF,aACE,aACA,uBAGF,qCAEE,eAGF,wBACE,WAGF,gBACE,kBACA,OACA,QACA,6BAIF,4DAGE,gBAGF,gCACE,kBACA,wBAGF,oBACE,kBAGF,kCACE,kBAGF,aACE,YAGF,2BACE,WAMF,+BACE,yBACA,sBACA,kBACA,QACA,eACA,gBACA,iBAGF,aACE,gBAEA,sCAEE,sBACA,iBACA,WAIJ,iBACE,yBACA,WAEA,8CAEE,sBACA,iBAIJ,oBACE,sBACA,cACA,yBAGF,0BACE,sBAGF,8BACE,YACA,gBACA,oBACA,uBACA,yBACA,sBACA,qBACA,iBAGF,kBACE,qBACA,SACA,+BAEA,gDAEE,yBACA,WAIJ,uFAEE,gBAGF,6CACE,SACA,kBACA,yBAGF,qCACE,eAGF,yDACE,kBAGF,wDACE,+BAGF,2CACE,gBACA,gBAGF,kBACE,kBACA,aAGF,4BACE,aAMF,IACE,wDACA,gBAGF,aAEE,eAGF,uCAEE,UAMF,uBACE,mBACA,WAGF,UACE,iBAGF,WACE,yBAGF,oBACE,gBAOF,oCACE,8BACE,YAIJ,oCACE,MACE,UAGF,kCACE,gBACA,WAGF,QACE,cACA,oBAGF,cACE,UAGF,MACE,gBAGF,QACE,cACA,mBAEA,oBACE,YACA,eAKN,8DACE,qBACE,wBAGF,sBACE,sBAIJ,oCACE,gBACE,yBAIJ,oCACE,gBACE,yBAQJ,iBACE,uBACA,gBACA,gBAGF,OACE,WAGF,aACE,eAGF,YACE,sBACA,WAEA,qBACE,YAGF,qBACE,aACA,YAGF,sBACE,eACA,kBACA,cACA,cACA,WACA,yBACA,0BAEA,wDAEE,sBACA,WAGF,6BACE,YACA,6CACA,gBAKF,8BACE,cACA,6BACA,8BAGF,+BACE,mBACA,0BACA,6BACA,8BAEA,sCACE,YAMR,QACE,aAGF,KACE,wBACA,YACA,WAGF,cACE,iBACA,iBAGF,cACE,gBACA,WAGF,OACE,YAGF,MACE,W","sources":["webpack://simplesamlphp-assets/./node_modules/reset-css/reset.css","webpack://simplesamlphp-assets/./node_modules/purecss/build/pure.css","webpack://simplesamlphp-assets/./node_modules/highlight.js/styles/base16/zenburn.css","webpack://simplesamlphp-assets/./resources/css/default.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_core.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_sizing.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_mixins.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_fixed-width.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_variables.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_list.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_bordered-pulled.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_animated.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_rotated-flipped.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_stacked.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_icons.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_screen-reader.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/solid.scss"],"sourcesContent":["/* http://meyerweb.com/eric/tools/css/reset/\n v5.0.1 | 20191019\n License: none (public domain)\n*/\n\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmain, menu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfont-size: 100%;\n\tfont: inherit;\n\tvertical-align: baseline;\n}\n/* HTML5 display-role reset for older browsers */\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, main, menu, nav, section {\n\tdisplay: block;\n}\n/* HTML5 hidden-attribute fix for newer browsers */\n*[hidden] {\n display: none;\n}\nbody {\n\tline-height: 1;\n}\nmenu, ol, ul {\n\tlist-style: none;\n}\nblockquote, q {\n\tquotes: none;\n}\nblockquote:before, blockquote:after,\nq:before, q:after {\n\tcontent: '';\n\tcontent: none;\n}\ntable {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n","/*!\nPure v3.0.0\nCopyright 2013 Yahoo!\nLicensed under the BSD License.\nhttps://github.com/pure-css/pure/blob/master/LICENSE\n*/\n/*!\nnormalize.css v | MIT License | https://necolas.github.io/normalize.css/\nCopyright (c) Nicolas Gallagher and Jonathan Neal\n*/\n/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n\n/*csslint important:false*/\n\n/* ==========================================================================\n Pure Base Extras\n ========================================================================== */\n\n/**\n * Extra rules that Pure adds on top of Normalize.css\n */\n\nhtml {\n font-family: sans-serif;\n}\n\n/**\n * Always hide an element when it has the `hidden` HTML attribute.\n */\n\n.hidden,\n[hidden] {\n display: none !important;\n}\n\n/**\n * Add this class to an image to make it fit within it's fluid parent wrapper while maintaining\n * aspect ratio.\n */\n.pure-img {\n max-width: 100%;\n height: auto;\n display: block;\n}\n\n/*csslint regex-selectors:false, known-properties:false, duplicate-properties:false*/\n\n.pure-g {\n display: flex;\n flex-flow: row wrap;\n\n /* Prevents distributing space between rows */\n align-content: flex-start;\n}\n\n.pure-u {\n display: inline-block;\n vertical-align: top;\n}\n\n.pure-u-1,\n.pure-u-1-1,\n.pure-u-1-2,\n.pure-u-1-3,\n.pure-u-2-3,\n.pure-u-1-4,\n.pure-u-3-4,\n.pure-u-1-5,\n.pure-u-2-5,\n.pure-u-3-5,\n.pure-u-4-5,\n.pure-u-5-5,\n.pure-u-1-6,\n.pure-u-5-6,\n.pure-u-1-8,\n.pure-u-3-8,\n.pure-u-5-8,\n.pure-u-7-8,\n.pure-u-1-12,\n.pure-u-5-12,\n.pure-u-7-12,\n.pure-u-11-12,\n.pure-u-1-24,\n.pure-u-2-24,\n.pure-u-3-24,\n.pure-u-4-24,\n.pure-u-5-24,\n.pure-u-6-24,\n.pure-u-7-24,\n.pure-u-8-24,\n.pure-u-9-24,\n.pure-u-10-24,\n.pure-u-11-24,\n.pure-u-12-24,\n.pure-u-13-24,\n.pure-u-14-24,\n.pure-u-15-24,\n.pure-u-16-24,\n.pure-u-17-24,\n.pure-u-18-24,\n.pure-u-19-24,\n.pure-u-20-24,\n.pure-u-21-24,\n.pure-u-22-24,\n.pure-u-23-24,\n.pure-u-24-24 {\n display: inline-block;\n letter-spacing: normal;\n word-spacing: normal;\n vertical-align: top;\n text-rendering: auto;\n}\n\n.pure-u-1-24 {\n width: 4.1667%;\n}\n\n.pure-u-1-12,\n.pure-u-2-24 {\n width: 8.3333%;\n}\n\n.pure-u-1-8,\n.pure-u-3-24 {\n width: 12.5000%;\n}\n\n.pure-u-1-6,\n.pure-u-4-24 {\n width: 16.6667%;\n}\n\n.pure-u-1-5 {\n width: 20%;\n}\n\n.pure-u-5-24 {\n width: 20.8333%;\n}\n\n.pure-u-1-4,\n.pure-u-6-24 {\n width: 25%;\n}\n\n.pure-u-7-24 {\n width: 29.1667%;\n}\n\n.pure-u-1-3,\n.pure-u-8-24 {\n width: 33.3333%;\n}\n\n.pure-u-3-8,\n.pure-u-9-24 {\n width: 37.5000%;\n}\n\n.pure-u-2-5 {\n width: 40%;\n}\n\n.pure-u-5-12,\n.pure-u-10-24 {\n width: 41.6667%;\n}\n\n.pure-u-11-24 {\n width: 45.8333%;\n}\n\n.pure-u-1-2,\n.pure-u-12-24 {\n width: 50%;\n}\n\n.pure-u-13-24 {\n width: 54.1667%;\n}\n\n.pure-u-7-12,\n.pure-u-14-24 {\n width: 58.3333%;\n}\n\n.pure-u-3-5 {\n width: 60%;\n}\n\n.pure-u-5-8,\n.pure-u-15-24 {\n width: 62.5000%;\n}\n\n.pure-u-2-3,\n.pure-u-16-24 {\n width: 66.6667%;\n}\n\n.pure-u-17-24 {\n width: 70.8333%;\n}\n\n.pure-u-3-4,\n.pure-u-18-24 {\n width: 75%;\n}\n\n.pure-u-19-24 {\n width: 79.1667%;\n}\n\n.pure-u-4-5 {\n width: 80%;\n}\n\n.pure-u-5-6,\n.pure-u-20-24 {\n width: 83.3333%;\n}\n\n.pure-u-7-8,\n.pure-u-21-24 {\n width: 87.5000%;\n}\n\n.pure-u-11-12,\n.pure-u-22-24 {\n width: 91.6667%;\n}\n\n.pure-u-23-24 {\n width: 95.8333%;\n}\n\n.pure-u-1,\n.pure-u-1-1,\n.pure-u-5-5,\n.pure-u-24-24 {\n width: 100%;\n}\n.pure-button {\n /* Structure */\n display: inline-block;\n line-height: normal;\n white-space: nowrap;\n vertical-align: middle;\n text-align: center;\n cursor: pointer;\n -webkit-user-drag: none;\n -webkit-user-select: none;\n user-select: none;\n box-sizing: border-box;\n}\n\n/* Firefox: Get rid of the inner focus border */\n.pure-button::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\n\n/* Inherit .pure-g styles */\n.pure-button-group {\n letter-spacing: -0.31em; /* Webkit: collapse white-space between units */\n text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */\n}\n\n.opera-only :-o-prefocus,\n.pure-button-group {\n word-spacing: -0.43em;\n}\n\n.pure-button-group .pure-button {\n letter-spacing: normal;\n word-spacing: normal;\n vertical-align: top;\n text-rendering: auto;\n}\n\n/*csslint outline-none:false*/\n\n.pure-button {\n font-family: inherit;\n font-size: 100%;\n padding: 0.5em 1em;\n color: rgba(0, 0, 0, 0.80);\n border: none rgba(0, 0, 0, 0);\n background-color: #E6E6E6;\n text-decoration: none;\n border-radius: 2px;\n}\n\n.pure-button-hover,\n.pure-button:hover,\n.pure-button:focus {\n background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));\n}\n.pure-button:focus {\n outline: 0;\n}\n.pure-button-active,\n.pure-button:active {\n box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;\n border-color: #000;\n}\n\n.pure-button[disabled],\n.pure-button-disabled,\n.pure-button-disabled:hover,\n.pure-button-disabled:focus,\n.pure-button-disabled:active {\n border: none;\n background-image: none;\n opacity: 0.40;\n cursor: not-allowed;\n box-shadow: none;\n pointer-events: none;\n}\n\n.pure-button-hidden {\n display: none;\n}\n\n.pure-button-primary,\n.pure-button-selected,\na.pure-button-primary,\na.pure-button-selected {\n background-color: rgb(0, 120, 231);\n color: #fff;\n}\n\n/* Button Groups */\n.pure-button-group .pure-button {\n margin: 0;\n border-radius: 0;\n border-right: 1px solid rgba(0, 0, 0, 0.2);\n\n}\n\n.pure-button-group .pure-button:first-child {\n border-top-left-radius: 2px;\n border-bottom-left-radius: 2px;\n}\n.pure-button-group .pure-button:last-child {\n border-top-right-radius: 2px;\n border-bottom-right-radius: 2px;\n border-right: none;\n}\n\n/*csslint box-model:false*/\n/*\nBox-model set to false because we're setting a height on select elements, which\nalso have border and padding. This is done because some browsers don't render\nthe padding. We explicitly set the box-model for select elements to border-box,\nso we can ignore the csslint warning.\n*/\n\n.pure-form input[type=\"text\"],\n.pure-form input[type=\"password\"],\n.pure-form input[type=\"email\"],\n.pure-form input[type=\"url\"],\n.pure-form input[type=\"date\"],\n.pure-form input[type=\"month\"],\n.pure-form input[type=\"time\"],\n.pure-form input[type=\"datetime\"],\n.pure-form input[type=\"datetime-local\"],\n.pure-form input[type=\"week\"],\n.pure-form input[type=\"number\"],\n.pure-form input[type=\"search\"],\n.pure-form input[type=\"tel\"],\n.pure-form input[type=\"color\"],\n.pure-form select,\n.pure-form textarea {\n padding: 0.5em 0.6em;\n display: inline-block;\n border: 1px solid #ccc;\n box-shadow: inset 0 1px 3px #ddd;\n border-radius: 4px;\n vertical-align: middle;\n box-sizing: border-box;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form input:not([type]) {\n padding: 0.5em 0.6em;\n display: inline-block;\n border: 1px solid #ccc;\n box-shadow: inset 0 1px 3px #ddd;\n border-radius: 4px;\n box-sizing: border-box;\n}\n\n\n/* Chrome (as of v.32/34 on OS X) needs additional room for color to display. */\n/* May be able to remove this tweak as color inputs become more standardized across browsers. */\n.pure-form input[type=\"color\"] {\n padding: 0.2em 0.5em;\n}\n\n\n.pure-form input[type=\"text\"]:focus,\n.pure-form input[type=\"password\"]:focus,\n.pure-form input[type=\"email\"]:focus,\n.pure-form input[type=\"url\"]:focus,\n.pure-form input[type=\"date\"]:focus,\n.pure-form input[type=\"month\"]:focus,\n.pure-form input[type=\"time\"]:focus,\n.pure-form input[type=\"datetime\"]:focus,\n.pure-form input[type=\"datetime-local\"]:focus,\n.pure-form input[type=\"week\"]:focus,\n.pure-form input[type=\"number\"]:focus,\n.pure-form input[type=\"search\"]:focus,\n.pure-form input[type=\"tel\"]:focus,\n.pure-form input[type=\"color\"]:focus,\n.pure-form select:focus,\n.pure-form textarea:focus {\n outline: 0;\n border-color: #129FEA;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form input:not([type]):focus {\n outline: 0;\n border-color: #129FEA;\n}\n\n.pure-form input[type=\"file\"]:focus,\n.pure-form input[type=\"radio\"]:focus,\n.pure-form input[type=\"checkbox\"]:focus {\n outline: thin solid #129FEA;\n outline: 1px auto #129FEA;\n}\n.pure-form .pure-checkbox,\n.pure-form .pure-radio {\n margin: 0.5em 0;\n display: block;\n}\n\n.pure-form input[type=\"text\"][disabled],\n.pure-form input[type=\"password\"][disabled],\n.pure-form input[type=\"email\"][disabled],\n.pure-form input[type=\"url\"][disabled],\n.pure-form input[type=\"date\"][disabled],\n.pure-form input[type=\"month\"][disabled],\n.pure-form input[type=\"time\"][disabled],\n.pure-form input[type=\"datetime\"][disabled],\n.pure-form input[type=\"datetime-local\"][disabled],\n.pure-form input[type=\"week\"][disabled],\n.pure-form input[type=\"number\"][disabled],\n.pure-form input[type=\"search\"][disabled],\n.pure-form input[type=\"tel\"][disabled],\n.pure-form input[type=\"color\"][disabled],\n.pure-form select[disabled],\n.pure-form textarea[disabled] {\n cursor: not-allowed;\n background-color: #eaeded;\n color: #cad2d3;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form input:not([type])[disabled] {\n cursor: not-allowed;\n background-color: #eaeded;\n color: #cad2d3;\n}\n.pure-form input[readonly],\n.pure-form select[readonly],\n.pure-form textarea[readonly] {\n background-color: #eee; /* menu hover bg color */\n color: #777; /* menu text color */\n border-color: #ccc;\n}\n\n.pure-form input:focus:invalid,\n.pure-form textarea:focus:invalid,\n.pure-form select:focus:invalid {\n color: #b94a48;\n border-color: #e9322d;\n}\n.pure-form input[type=\"file\"]:focus:invalid:focus,\n.pure-form input[type=\"radio\"]:focus:invalid:focus,\n.pure-form input[type=\"checkbox\"]:focus:invalid:focus {\n outline-color: #e9322d;\n}\n.pure-form select {\n /* Normalizes the height; padding is not sufficient. */\n height: 2.25em;\n border: 1px solid #ccc;\n background-color: white;\n}\n.pure-form select[multiple] {\n height: auto;\n}\n.pure-form label {\n margin: 0.5em 0 0.2em;\n}\n.pure-form fieldset {\n margin: 0;\n padding: 0.35em 0 0.75em;\n border: 0;\n}\n.pure-form legend {\n display: block;\n width: 100%;\n padding: 0.3em 0;\n margin-bottom: 0.3em;\n color: #333;\n border-bottom: 1px solid #e5e5e5;\n}\n\n.pure-form-stacked input[type=\"text\"],\n.pure-form-stacked input[type=\"password\"],\n.pure-form-stacked input[type=\"email\"],\n.pure-form-stacked input[type=\"url\"],\n.pure-form-stacked input[type=\"date\"],\n.pure-form-stacked input[type=\"month\"],\n.pure-form-stacked input[type=\"time\"],\n.pure-form-stacked input[type=\"datetime\"],\n.pure-form-stacked input[type=\"datetime-local\"],\n.pure-form-stacked input[type=\"week\"],\n.pure-form-stacked input[type=\"number\"],\n.pure-form-stacked input[type=\"search\"],\n.pure-form-stacked input[type=\"tel\"],\n.pure-form-stacked input[type=\"color\"],\n.pure-form-stacked input[type=\"file\"],\n.pure-form-stacked select,\n.pure-form-stacked label,\n.pure-form-stacked textarea {\n display: block;\n margin: 0.25em 0;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form-stacked input:not([type]) {\n display: block;\n margin: 0.25em 0;\n}\n.pure-form-aligned input,\n.pure-form-aligned textarea,\n.pure-form-aligned select,\n.pure-form-message-inline {\n display: inline-block;\n vertical-align: middle;\n}\n.pure-form-aligned textarea {\n vertical-align: top;\n}\n\n/* Aligned Forms */\n.pure-form-aligned .pure-control-group {\n margin-bottom: 0.5em;\n}\n.pure-form-aligned .pure-control-group label {\n text-align: right;\n display: inline-block;\n vertical-align: middle;\n width: 10em;\n margin: 0 1em 0 0;\n}\n.pure-form-aligned .pure-controls {\n margin: 1.5em 0 0 11em;\n}\n\n/* Rounded Inputs */\n.pure-form input.pure-input-rounded,\n.pure-form .pure-input-rounded {\n border-radius: 2em;\n padding: 0.5em 1em;\n}\n\n/* Grouped Inputs */\n.pure-form .pure-group fieldset {\n margin-bottom: 10px;\n}\n.pure-form .pure-group input,\n.pure-form .pure-group textarea {\n display: block;\n padding: 10px;\n margin: 0 0 -1px;\n border-radius: 0;\n position: relative;\n top: -1px;\n}\n.pure-form .pure-group input:focus,\n.pure-form .pure-group textarea:focus {\n z-index: 3;\n}\n.pure-form .pure-group input:first-child,\n.pure-form .pure-group textarea:first-child {\n top: 1px;\n border-radius: 4px 4px 0 0;\n margin: 0;\n}\n.pure-form .pure-group input:first-child:last-child,\n.pure-form .pure-group textarea:first-child:last-child {\n top: 1px;\n border-radius: 4px;\n margin: 0;\n}\n.pure-form .pure-group input:last-child,\n.pure-form .pure-group textarea:last-child {\n top: -2px;\n border-radius: 0 0 4px 4px;\n margin: 0;\n}\n.pure-form .pure-group button {\n margin: 0.35em 0;\n}\n\n.pure-form .pure-input-1 {\n width: 100%;\n}\n.pure-form .pure-input-3-4 {\n width: 75%;\n}\n.pure-form .pure-input-2-3 {\n width: 66%;\n}\n.pure-form .pure-input-1-2 {\n width: 50%;\n}\n.pure-form .pure-input-1-3 {\n width: 33%;\n}\n.pure-form .pure-input-1-4 {\n width: 25%;\n}\n\n/* Inline help for forms */\n.pure-form-message-inline {\n display: inline-block;\n padding-left: 0.3em;\n color: #666;\n vertical-align: middle;\n font-size: 0.875em;\n}\n\n/* Block help for forms */\n.pure-form-message {\n display: block;\n color: #666;\n font-size: 0.875em;\n}\n\n@media only screen and (max-width : 480px) {\n .pure-form button[type=\"submit\"] {\n margin: 0.7em 0 0;\n }\n\n .pure-form input:not([type]),\n .pure-form input[type=\"text\"],\n .pure-form input[type=\"password\"],\n .pure-form input[type=\"email\"],\n .pure-form input[type=\"url\"],\n .pure-form input[type=\"date\"],\n .pure-form input[type=\"month\"],\n .pure-form input[type=\"time\"],\n .pure-form input[type=\"datetime\"],\n .pure-form input[type=\"datetime-local\"],\n .pure-form input[type=\"week\"],\n .pure-form input[type=\"number\"],\n .pure-form input[type=\"search\"],\n .pure-form input[type=\"tel\"],\n .pure-form input[type=\"color\"],\n .pure-form label {\n margin-bottom: 0.3em;\n display: block;\n }\n\n .pure-group input:not([type]),\n .pure-group input[type=\"text\"],\n .pure-group input[type=\"password\"],\n .pure-group input[type=\"email\"],\n .pure-group input[type=\"url\"],\n .pure-group input[type=\"date\"],\n .pure-group input[type=\"month\"],\n .pure-group input[type=\"time\"],\n .pure-group input[type=\"datetime\"],\n .pure-group input[type=\"datetime-local\"],\n .pure-group input[type=\"week\"],\n .pure-group input[type=\"number\"],\n .pure-group input[type=\"search\"],\n .pure-group input[type=\"tel\"],\n .pure-group input[type=\"color\"] {\n margin-bottom: 0;\n }\n\n .pure-form-aligned .pure-control-group label {\n margin-bottom: 0.3em;\n text-align: left;\n display: block;\n width: 100%;\n }\n\n .pure-form-aligned .pure-controls {\n margin: 1.5em 0 0 0;\n }\n\n .pure-form-message-inline,\n .pure-form-message {\n display: block;\n font-size: 0.75em;\n /* Increased bottom padding to make it group with its related input element. */\n padding: 0.2em 0 0.8em;\n }\n}\n\n/*csslint adjoining-classes: false, box-model:false*/\n.pure-menu {\n box-sizing: border-box;\n}\n\n.pure-menu-fixed {\n position: fixed;\n left: 0;\n top: 0;\n z-index: 3;\n}\n\n.pure-menu-list,\n.pure-menu-item {\n position: relative;\n}\n\n.pure-menu-list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.pure-menu-item {\n padding: 0;\n margin: 0;\n height: 100%;\n}\n\n.pure-menu-link,\n.pure-menu-heading {\n display: block;\n text-decoration: none;\n white-space: nowrap;\n}\n\n/* HORIZONTAL MENU */\n.pure-menu-horizontal {\n width: 100%;\n white-space: nowrap;\n}\n\n.pure-menu-horizontal .pure-menu-list {\n display: inline-block;\n}\n\n/* Initial menus should be inline-block so that they are horizontal */\n.pure-menu-horizontal .pure-menu-item,\n.pure-menu-horizontal .pure-menu-heading,\n.pure-menu-horizontal .pure-menu-separator {\n display: inline-block;\n vertical-align: middle;\n}\n\n/* Submenus should still be display: block; */\n.pure-menu-item .pure-menu-item {\n display: block;\n}\n\n.pure-menu-children {\n display: none;\n position: absolute;\n left: 100%;\n top: 0;\n margin: 0;\n padding: 0;\n z-index: 3;\n}\n\n.pure-menu-horizontal .pure-menu-children {\n left: 0;\n top: auto;\n width: inherit;\n}\n\n.pure-menu-allow-hover:hover > .pure-menu-children,\n.pure-menu-active > .pure-menu-children {\n display: block;\n position: absolute;\n}\n\n/* Vertical Menus - show the dropdown arrow */\n.pure-menu-has-children > .pure-menu-link:after {\n padding-left: 0.5em;\n content: \"\\25B8\";\n font-size: small;\n}\n\n/* Horizontal Menus - show the dropdown arrow */\n.pure-menu-horizontal .pure-menu-has-children > .pure-menu-link:after {\n content: \"\\25BE\";\n}\n\n/* scrollable menus */\n.pure-menu-scrollable {\n overflow-y: scroll;\n overflow-x: hidden;\n}\n\n.pure-menu-scrollable .pure-menu-list {\n display: block;\n}\n\n.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list {\n display: inline-block;\n}\n\n.pure-menu-horizontal.pure-menu-scrollable {\n white-space: nowrap;\n overflow-y: hidden;\n overflow-x: auto;\n /* a little extra padding for this style to allow for scrollbars */\n padding: .5em 0;\n}\n\n/* misc default styling */\n\n.pure-menu-separator,\n.pure-menu-horizontal .pure-menu-children .pure-menu-separator {\n background-color: #ccc;\n height: 1px;\n margin: .3em 0;\n}\n\n.pure-menu-horizontal .pure-menu-separator {\n width: 1px;\n height: 1.3em;\n margin: 0 .3em ;\n}\n\n/* Need to reset the separator since submenu is vertical */\n.pure-menu-horizontal .pure-menu-children .pure-menu-separator {\n display: block;\n width: auto;\n}\n\n.pure-menu-heading {\n text-transform: uppercase;\n color: #565d64;\n}\n\n.pure-menu-link {\n color: #777;\n}\n\n.pure-menu-children {\n background-color: #fff;\n}\n\n.pure-menu-link,\n.pure-menu-heading {\n padding: .5em 1em;\n}\n\n.pure-menu-disabled {\n opacity: .5;\n}\n\n.pure-menu-disabled .pure-menu-link:hover {\n background-color: transparent;\n cursor: default;\n}\n\n.pure-menu-active > .pure-menu-link,\n.pure-menu-link:hover,\n.pure-menu-link:focus {\n background-color: #eee;\n}\n\n.pure-menu-selected > .pure-menu-link,\n.pure-menu-selected > .pure-menu-link:visited {\n color: #000;\n}\n\n.pure-table {\n /* Remove spacing between table cells (from Normalize.css) */\n border-collapse: collapse;\n border-spacing: 0;\n empty-cells: show;\n border: 1px solid #cbcbcb;\n}\n\n.pure-table caption {\n color: #000;\n font: italic 85%/1 arial, sans-serif;\n padding: 1em 0;\n text-align: center;\n}\n\n.pure-table td,\n.pure-table th {\n border-left: 1px solid #cbcbcb;/* inner column border */\n border-width: 0 0 0 1px;\n font-size: inherit;\n margin: 0;\n overflow: visible; /*to make ths where the title is really long work*/\n padding: 0.5em 1em; /* cell padding */\n}\n\n.pure-table thead {\n background-color: #e0e0e0;\n color: #000;\n text-align: left;\n vertical-align: bottom;\n}\n\n/*\nstriping:\n even - #fff (white)\n odd - #f2f2f2 (light gray)\n*/\n.pure-table td {\n background-color: transparent;\n}\n.pure-table-odd td {\n background-color: #f2f2f2;\n}\n\n/* nth-child selector for modern browsers */\n.pure-table-striped tr:nth-child(2n-1) td {\n background-color: #f2f2f2;\n}\n\n/* BORDERED TABLES */\n.pure-table-bordered td {\n border-bottom: 1px solid #cbcbcb;\n}\n.pure-table-bordered tbody > tr:last-child > td {\n border-bottom-width: 0;\n}\n\n\n/* HORIZONTAL BORDERED TABLES */\n\n.pure-table-horizontal td,\n.pure-table-horizontal th {\n border-width: 0 0 1px 0;\n border-bottom: 1px solid #cbcbcb;\n}\n.pure-table-horizontal tbody > tr:last-child > td {\n border-bottom-width: 0;\n}\n","pre code.hljs {\n display: block;\n overflow-x: auto;\n padding: 1em\n}\ncode.hljs {\n padding: 3px 5px\n}\n/*!\n Theme: Zenburn\n Author: elnawe\n License: ~ MIT (or more permissive) [via base16-schemes-source]\n Maintainer: @highlightjs/core-team\n Version: 2021.09.0\n*/\n/*\n WARNING: DO NOT EDIT THIS FILE DIRECTLY.\n\n This theme file was auto-generated from the Base16 scheme zenburn\n by the Highlight.js Base16 template builder.\n\n - https://github.com/highlightjs/base16-highlightjs\n*/\n/*\nbase00 #383838 Default Background\nbase01 #404040 Lighter Background (Used for status bars, line number and folding marks)\nbase02 #606060 Selection Background\nbase03 #6f6f6f Comments, Invisibles, Line Highlighting\nbase04 #808080 Dark Foreground (Used for status bars)\nbase05 #dcdccc Default Foreground, Caret, Delimiters, Operators\nbase06 #c0c0c0 Light Foreground (Not often used)\nbase07 #ffffff Light Background (Not often used)\nbase08 #dca3a3 Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted\nbase09 #dfaf8f Integers, Boolean, Constants, XML Attributes, Markup Link Url\nbase0A #e0cf9f Classes, Markup Bold, Search Text Background\nbase0B #5f7f5f Strings, Inherited Class, Markup Code, Diff Inserted\nbase0C #93e0e3 Support, Regular Expressions, Escape Characters, Markup Quotes\nbase0D #7cb8bb Functions, Methods, Attribute IDs, Headings\nbase0E #dc8cc3 Keywords, Storage, Selector, Markup Italic, Diff Changed\nbase0F #000000 Deprecated, Opening/Closing Embedded Language Tags, e.g. \n*/\npre code.hljs {\n display: block;\n overflow-x: auto;\n padding: 1em\n}\ncode.hljs {\n padding: 3px 5px\n}\n.hljs {\n color: #dcdccc;\n background: #383838\n}\n.hljs::selection,\n.hljs ::selection {\n background-color: #606060;\n color: #dcdccc\n}\n/* purposely do not highlight these things */\n.hljs-formula,\n.hljs-params,\n.hljs-property {\n \n}\n/* base03 - #6f6f6f - Comments, Invisibles, Line Highlighting */\n.hljs-comment {\n color: #6f6f6f\n}\n/* base04 - #808080 - Dark Foreground (Used for status bars) */\n.hljs-tag {\n color: #808080\n}\n/* base05 - #dcdccc - Default Foreground, Caret, Delimiters, Operators */\n.hljs-subst,\n.hljs-punctuation,\n.hljs-operator {\n color: #dcdccc\n}\n.hljs-operator {\n opacity: 0.7\n}\n/* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */\n.hljs-bullet,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-selector-tag,\n.hljs-name,\n.hljs-deletion {\n color: #dca3a3\n}\n/* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */\n.hljs-symbol,\n.hljs-number,\n.hljs-link,\n.hljs-attr,\n.hljs-variable.constant_,\n.hljs-literal {\n color: #dfaf8f\n}\n/* base0A - Classes, Markup Bold, Search Text Background */\n.hljs-title,\n.hljs-class .hljs-title,\n.hljs-title.class_ {\n color: #e0cf9f\n}\n.hljs-strong {\n font-weight: bold;\n color: #e0cf9f\n}\n/* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */\n.hljs-code,\n.hljs-addition,\n.hljs-title.class_.inherited__,\n.hljs-string {\n color: #5f7f5f\n}\n/* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */\n/* guessing */\n.hljs-built_in,\n.hljs-doctag,\n.hljs-quote,\n.hljs-keyword.hljs-atrule,\n.hljs-regexp {\n color: #93e0e3\n}\n/* base0D - Functions, Methods, Attribute IDs, Headings */\n.hljs-function .hljs-title,\n.hljs-attribute,\n.ruby .hljs-property,\n.hljs-title.function_,\n.hljs-section {\n color: #7cb8bb\n}\n/* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */\n/* .hljs-selector-id, */\n/* .hljs-selector-class, */\n/* .hljs-selector-attr, */\n/* .hljs-selector-pseudo, */\n.hljs-type,\n.hljs-template-tag,\n.diff .hljs-meta,\n.hljs-keyword {\n color: #dc8cc3\n}\n.hljs-emphasis {\n color: #dc8cc3;\n font-style: italic\n}\n/* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. */\n/*\n prevent top level .keyword and .string scopes\n from leaking into meta by accident\n*/\n.hljs-meta,\n.hljs-meta .hljs-keyword,\n.hljs-meta .hljs-string {\n color: #000000\n}\n/* for v10 compatible themes */\n.hljs-meta .hljs-keyword,\n.hljs-meta-keyword {\n font-weight: bold\n}","$primaryBackground: #b8002c; $transitionBackground: #db0100; $secondaryBackground: #e8410c;\n@import \"../../node_modules/reset-css/reset.css\";\n@import \"../../node_modules/purecss/build/pure.css\";\n$fa-font-path: '../fonts';\n@import \"../../node_modules/\\@fortawesome/fontawesome-free/scss/fontawesome\";\n@import \"../../node_modules/\\@fortawesome/fontawesome-free/scss/solid\";\n@import \"../../node_modules/highlight.js/styles/base16/zenburn.css\";\n\n/*************\n * VARIABLES *\n *************/\n\n$light-yellow: #fffdbf;\n\n/************************************************************\n * GENERAL\n ************************************************************/\n* {\n margin: 0;\n padding: 0;\n}\n\nhtml,\nbody {\n height: 100%;\n}\n\nbody {\n font-family: sans-serif;\n line-height: 1.5;\n min-height: 100%;\n}\n\n.wrap {\n width: 80%;\n max-width: 1100px;\n margin: auto;\n position: relative;\n}\n\n.logospace {\n float: left;\n}\n\nhtml[dir=\"rtl\"] .logospace {\n float: right;\n}\n\n.menuspace {\n float: right;\n}\n\nhtml[dir=\"rtl\"] .menuspace {\n float: left;\n}\n\n.center {\n text-align: center;\n}\n\n.v-center {\n /* specify a height to center vertically */\n display: table-cell;\n vertical-align: middle;\n}\n\ni {\n font-style: italic;\n}\n\nh1 {\n margin: 1em 0;\n font-size: 2em;\n font-weight: 900;\n}\n\nh2 {\n margin: 1em 0;\n font-size: 1.5em;\n font-weight: 700;\n color: #1c1c1c;\n border-bottom: solid 1px #bbb;\n}\n\nh3 {\n font-weight: 500;\n color: #2e3436;\n padding: 0;\n margin-top: 0;\n}\n\np {\n padding: 0.5em 0;\n margin-bottom: 1em;\n}\n\na {\n color: midnightblue;\n\n &:hover,\n &:focus,\n &.pure-menu-link:hover,\n &.pure-menu-link:focus,\n .pure-menu-selected &.pure-menu-link:hover,\n .pure-menu-selected &.pure-menu-link:focus {\n color: white;\n background-color: #444;\n padding: 0.5em 1em;\n }\n\n &:hover,\n &:focus {\n padding: 0.15rem;\n }\n}\n\n.overflow {\n overflow: hidden;\n}\n\nul {\n padding-left: 1.5em;\n}\n\nstrong,\nb {\n font-weight: bold;\n}\n\npre,\ncode,\nkbd,\nsamp,\ntt {\n font-family: monospace;\n font-size: 0.9rem;\n padding: 0 0.2rem;\n}\n\n.xmldata {\n font-family: monospace;\n}\n\n/* ***********************************************************\n * SLIDING SIDE-MENU FOR SMALL SCREENS\n *************************************************************/\n\n/*\nAdd transition to containers so they can push in and out.\n*/\n#layout,\n#menu,\n#foot,\n.menu-link {\n -webkit-transition: all 0.2s ease-out;\n -moz-transition: all 0.2s ease-out;\n -ms-transition: all 0.2s ease-out;\n -o-transition: all 0.2s ease-out;\n transition: all 0.2s ease-out;\n}\n\n/*\nThis is the parent `
` that contains the menu and the content area.\n*/\n#layout.active #menu {\n right: 11em;\n width: 11em;\n}\n\n/*\nThe `#menu` `
` is the parent `
` that contains the `.pure-menu` that\nappears on the left side of the page.\n*/\n#menu {\n margin-right: -11em; /* \"#menu\" width */\n width: 11em;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 1000; /* so the menu or its navicon stays above all content */\n background: $secondaryBackground;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n/*\nAll anchors inside the menu should be styled like this.\n*/\n#menu a {\n color: #fff;\n border: none;\n padding: 0.6em 0 0.6em 0.6em;\n}\n\n/*\nRemove all background/borders, since we are applying them to #menu.\n*/\n#menu .pure-menu,\n#menu .pure-menu ul {\n border: none;\n background: transparent;\n}\n\n/*\nAdd that light border to separate items into groups.\n*/\n#menu .pure-menu ul,\n#menu .pure-menu .menu-item-divided {\n border-top: 1px solid $transitionBackground;\n}\n\n/*\nThis styles the selected menu item `
  • `.\n*/\n#menu .pure-menu-selected,\n#menu .pure-menu-heading {\n background: $primaryBackground;\n color: black;\n}\n\n/*\nThis styles a link within a selected menu item `
  • `.\n*/\n#menu .pure-menu-selected a {\n color: #fff;\n}\n\n/*\nThis styles the menu heading.\n*/\n#menu .pure-menu-heading {\n font-size: 110%;\n color: #fff;\n margin: 0;\n text-transform: none;\n}\n\n/* -- Dynamic Button For Responsive Menu -- */\n\n/*\nThe button to open/close the Menu is custom-made and not part of Pure. Here's\nhow it works:\n*/\n\n/*\n`.menu-link` represents the responsive menu toggle that shows/hides on\nsmall screens.\n*/\n.menu-link {\n position: relative;\n display: block; /* show this only on small screens */\n top: 0;\n right: 0; /* \"#menu width\" */\n background: transparent;\n z-index: 10;\n height: 2rem;\n padding: 2rem 0;\n text-decoration: none;\n\n &:hover,\n &:focus {\n padding: 2rem 0;\n background: none !important;\n }\n}\n\n.menu-link span {\n position: relative;\n display: block;\n color: #fff;\n}\n\n.menu-link span,\n.menu-link span::before,\n.menu-link span::after {\n background-color: transparent;\n}\n\n.menu-link span:focus,\n.menu-link span:hover {\n color: #010101cc;\n}\n\n/* -- Responsive Styles (Media Queries) ------------------------------------- */\n\n@media screen and (max-width: 40em) {\n #layout.active {\n position: relative;\n right: 11em;\n\n /* moves to right as many ems as the one used by the menu */\n }\n\n #menuLink.menu-link.active {\n position: fixed;\n right: 13em;\n }\n\n #foot.active {\n margin-right: 11em;\n }\n}\n\n/************************************************************\nHEADER\n*************************************************************/\n#header {\n height: 6rem;\n background: linear-gradient(141deg, $primaryBackground 0%, $transitionBackground 51%, $secondaryBackground 75%);\n}\n\n.logo-header {\n min-width: 8em;\n height: 6rem;\n max-width: 70%;\n}\n\n#logo {\n font-family: sans-serif;\n font-size: 2.5em;\n color: white;\n text-shadow: 0 3px 2px #532900;\n}\n\n.simple {\n font-weight: 300;\n}\n\n.saml {\n font-family: Verdana, sans-serif;\n letter-spacing: -0.12em;\n font-weight: 600;\n margin-left: -0.05em;\n}\n\n.language-menu {\n font-family: sans-serif;\n font-weight: 400;\n min-width: 10rem;\n padding: 0em 0.6em !important;\n}\n\n.language-bar {\n height: 6rem;\n}\n\n/************************************************************\nCONTENT\n*************************************************************/\n#layout {\n right: 0;\n padding-right: 0;\n min-height: 100%;\n\n /* negative margin = footer height + padding-top + padding-bottom */\n margin: 0 auto -6rem;\n}\n\n#content {\n padding-top: 2em;\n padding-bottom: 2rem;\n}\n\n.message-box {\n background-color: #f4f4f4;\n border-left: 0.3125rem solid #444;\n box-shadow: 0 5px 8px -6px #0003;\n margin: 1rem 0;\n padding: 1.3rem;\n position: relative;\n}\n\n.message-box.error {\n background-color: #f7e4e1;\n border-left-color: #cc4b37;\n}\n\n.message-box.warning {\n background-color: $light-yellow;\n border-left-color: #f9f56b;\n}\n\n.message-box.success {\n background-color: #daf7e6;\n border-left-color: #46cc48;\n}\n\n.auth_methods {\n margin-top: 2em;\n width: 35%;\n}\n\n.code-box {\n margin-bottom: 1em;\n border: 1px solid #ccc;\n\n a {\n padding: 0.5em;\n }\n}\n\n.code-box-content {\n word-break: break-all;\n font-size: 1em;\n line-height: 1.15;\n padding: 0.5em 1em;\n display: inline-block;\n min-height: 1em;\n height: 100%;\n white-space: pre-wrap;\n font-family: monospace;\n\n &::selection {\n color: black;\n background: $light-yellow;\n }\n}\n\n.code-box-title {\n border-bottom: 1px solid #ccc;\n background-color: #e0e0e0;\n padding: 0.5em 0 0.5em 0.5em;\n}\n\npre#xmlmetadata {\n width: 98%;\n}\n\n/************************************************************\n * FOOTER\n ************************************************************/\n\n#bottom,\n#push {\n height: 6rem;\n}\n\n#footer {\n width: 100%;\n background: linear-gradient(141deg, $primaryBackground 0%, $transitionBackground 51%, $secondaryBackground 75%);\n height: 4rem;\n padding: 2rem 0 0;\n text-align: center;\n color: white;\n\n a,\n a:visited {\n color: white;\n\n &:focus,\n &:hover {\n background-color: white;\n color: black;\n padding: 0.15rem;\n margin-left: -0.15rem;\n margin-top: -0.15rem;\n text-decoration: none;\n }\n }\n}\n\n.copyrights {\n padding-top: 0.5rem;\n height: 3.5rem;\n font-size: 0.8rem;\n}\n\n.logo-footer-space {\n position: absolute;\n right: 0;\n top: 50%;\n transform: translate(0, -50%);\n}\n\nhtml[dir=\"rtl\"] .logo-footer-space {\n right: auto;\n left: 0;\n}\n\n.logo-footer {\n height: 4rem;\n}\n\n/* ***********************************************************\nFORMS\n************************************************************ */\n.text-area {\n margin-top: 0.5em;\n width: 100%;\n font-size: 0.9em;\n line-height: 1.15;\n}\n\n.file-upload input[type=\"url\"][disabled] {\n cursor: pointer;\n color: inherit;\n}\n\ninput[type=\"file\"] {\n color: black;\n}\n\n.center-form {\n display: flex;\n justify-content: center;\n}\n\n.login-form-start,\n.login-form-submit {\n margin-top: 3ex;\n}\n\ninput#username:disabled {\n color: #000000;\n}\n\n.v-center-right {\n position: absolute;\n left: 0;\n top: 50%;\n transform: translate(0, -50%);\n}\n\n/* PURE */\n.pure-button,\n.pure-form input.edge,\n.pure-form textarea.edge {\n border-radius: 0;\n}\n\n.pure-form input[type=\"checkbox\"] {\n margin-right: 0.8ex;\n vertical-align: baseline;\n}\n\n.pure-control-group {\n margin-bottom: 1ex;\n}\n\n.pure-form-aligned .pure-controls {\n margin: 0 0 0 11em;\n}\n\n.pure-select {\n float: right;\n}\n\nhtml[dir=\"rtl\"] .pure-select {\n float: left;\n}\n\n/************************************************************\n * BUTTONS\n ************************************************************/\n.code-box-title .clipboard-btn {\n background-color: #f0f0f0;\n border: 1px solid #ccc;\n position: absolute;\n right: 0;\n height: inherit;\n margin-top: -2em;\n margin-right: 4px;\n}\n\n.pure-button {\n margin-left: 1ex;\n\n &:hover,\n &:focus {\n background-color: #555;\n padding: 0.5em 1em;\n color: #fff;\n }\n}\n\n.pure-button-red {\n background-color: #db0100;\n color: #fff;\n\n &:hover,\n &:focus {\n background-color: #555;\n padding: 0.5em 1em;\n }\n}\n\n.pure-button.hollow {\n background-color: #fff;\n color: #6f6f6f;\n border: solid 1px #e6e6e6;\n}\n\n.pure-button.hollow:hover {\n background-image: none;\n}\n\n.pure-button.hollow[disabled] {\n cursor: auto;\n opacity: initial;\n pointer-events: auto;\n -webkit-user-drag: auto;\n -webkit-user-select: auto;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n}\n\n.pure-button.hljs {\n display: inline-block;\n border: 0;\n background-color: transparent;\n\n &:hover,\n &:focus {\n background-color: #f0f0f0;\n color: black;\n }\n}\n\n.pure-button-group .pure-button:first-child,\n.pure-button-group .pure-button:last-child {\n border-radius: 0;\n}\n\n.pure-button-group.two-elements .pure-button {\n margin: 0;\n line-height: unset;\n border: 1px solid #e6e6e6;\n}\n\n.pure-button-group.two-elements form {\n display: inline;\n}\n\n.pure-button-group.two-elements .pure-button:first-child {\n border-right: none;\n}\n\n.pure-button-group.two-elements .pure-button:last-child {\n border-right: 1px solid #e6e6e6;\n}\n\n.pure-button-group .pure-button.show-files {\n max-width: 450px;\n overflow: hidden;\n}\n\n.top-right-corner {\n position: absolute;\n right: 1.75em;\n}\n\ninput#postLoginSubmitButton {\n display: none;\n}\n\n/************************************************************\n * IMAGES\n ************************************************************/\n.fa {\n font-family: \"Font Awesome 6 Free\", sans-serif !important;\n font-weight: 400;\n}\n\nspan.fa,\ni.fa {\n padding: 0 0.5em;\n}\n\n.message-box span.fa,\n.message-box i.fa {\n padding: 0;\n}\n\n/************************************************************\n * TABLES\n ************************************************************/\n.pure-table-attributes {\n table-layout: fixed;\n width: 100%;\n}\n\n.attrname {\n text-align: right;\n}\n\n.attrvalue {\n overflow-wrap: break-word;\n}\n\ntable.attributes ul {\n padding: inherit;\n}\n\n/************************************************************\n * MEDIA QUERIES\n ************************************************************/\n\n@media screen and (max-width: 40em) {\n .pure-form .pure-input-sm-1-1 {\n width: 100%;\n }\n}\n\n@media screen and (max-width: 40em) {\n .wrap {\n width: 90%;\n }\n\n .pure-form-aligned .pure-controls {\n margin: 0.5em 0 0;\n float: left;\n }\n\n #layout {\n padding-top: 0;\n margin-bottom: -4rem;\n }\n\n .auth_methods {\n width: 60%;\n }\n\n #logo {\n font-size: 1.8em;\n }\n\n #footer {\n height: 2.5rem;\n padding-top: 1.5rem;\n\n .copyrights {\n height: 1rem;\n padding-top: 0;\n }\n }\n}\n\n@media screen and (max-width: 0), screen and (min-width: 40em) {\n .show-for-small-only {\n display: none !important;\n }\n\n .input-sm-placeholder {\n display: inline-block;\n }\n}\n\n@media screen and (min-width: 40em) {\n .hide-for-large {\n display: none !important;\n }\n}\n\n@media screen and (max-width: 40em) {\n .show-for-large {\n display: none !important;\n }\n}\n\n/*********\n * Utils *\n *********/\n\ndiv.preferredidp {\n border: 1px dashed #ccc;\n background: #eee;\n padding: 2px 2em;\n}\n\n.clear {\n clear: both;\n}\n\n.breathe-top {\n margin-top: 1em;\n}\n\n.expandable {\n border: solid 1px #bbb;\n width: 100%;\n\n .general {\n padding: 1em;\n }\n\n .content {\n display: none;\n padding: 1em;\n }\n\n .expander {\n cursor: pointer;\n text-align: center;\n padding: 0.25em;\n display: block;\n color: black;\n background-color: #f4f4f4;\n border-top: solid 1px #bbb;\n\n &:focus,\n &:hover {\n background-color: #555;\n color: white;\n }\n\n &::after {\n content: \"\\f078\";\n font-family: \"Font Awesome 6 Free\", sans-serif;\n font-weight: 400;\n }\n }\n\n &.expanded {\n .content {\n display: block;\n border-left: solid 0.25em #555;\n border-right: solid 0.25em #555;\n }\n\n .expander {\n border-bottom: none;\n border-top: solid 1px #bbb;\n border-left: solid 0.25em #555;\n border-right: solid 0.25em #555;\n\n &::after {\n content: \"\\f077\";\n }\n }\n }\n}\n\n.hidden {\n display: none;\n}\n\n.idp {\n border: 1px solid silver;\n padding: 1ex;\n margin: 1ex;\n}\n\n.idp .idpname {\n font-size: larger;\n font-weight: bold;\n}\n\n.idp .idpdesc {\n font-size: small;\n color: gray;\n}\n\n.right {\n float: right;\n}\n\n.left {\n float: left;\n}\n","/*!\n * Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)\n * Copyright 2024 Fonticons, Inc.\n */\n// Font Awesome core compile (Web Fonts-based)\n// -------------------------\n\n@import 'functions';\n@import 'variables';\n@import 'mixins';\n@import 'core';\n@import 'sizing';\n@import 'fixed-width';\n@import 'list';\n@import 'bordered-pulled';\n@import 'animated';\n@import 'rotated-flipped';\n@import 'stacked';\n@import 'icons';\n@import 'screen-reader';\n","// base icon class definition\n// -------------------------\n\n.#{$fa-css-prefix} {\n font-family: var(--#{$fa-css-prefix}-style-family, '#{$fa-style-family}');\n font-weight: var(--#{$fa-css-prefix}-style, #{$fa-style});\n}\n\n.#{$fa-css-prefix}-solid,\n.#{$fa-css-prefix}-regular,\n.#{$fa-css-prefix}-brands,\n.fas,\n.far,\n.fab,\n.#{$fa-css-prefix}-sharp-solid,\n.#{$fa-css-prefix}-classic,\n.#{$fa-css-prefix} {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n display: var(--#{$fa-css-prefix}-display, #{$fa-display});\n font-style: normal;\n font-variant: normal;\n line-height: 1;\n text-rendering: auto;\n}\n\n.fas,\n.#{$fa-css-prefix}-classic,\n.#{$fa-css-prefix}-solid,\n.far,\n.#{$fa-css-prefix}-regular {\n font-family: 'Font Awesome 6 Free';\n}\n\n.fab,\n.#{$fa-css-prefix}-brands {\n font-family: 'Font Awesome 6 Brands';\n}\n\n\n%fa-icon {\n @include fa-icon;\n}\n","// sizing icons\n// -------------------------\n\n// literal magnification scale\n@for $i from 1 through 10 {\n .#{$fa-css-prefix}-#{$i}x {\n font-size: $i * 1em;\n }\n}\n\n// step-based scale (with alignment)\n@each $size, $value in $fa-sizes {\n .#{$fa-css-prefix}-#{$size} {\n @include fa-size($value);\n }\n}\n","// mixins\n// --------------------------\n\n// base rendering for an icon\n@mixin fa-icon {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n display: inline-block;\n font-style: normal;\n font-variant: normal;\n font-weight: normal;\n line-height: 1;\n}\n\n// sets relative font-sizing and alignment (in _sizing)\n@mixin fa-size ($font-size) {\n font-size: fa-divide($font-size, $fa-size-scale-base) * 1em; // converts step in sizing scale into an em-based value that's relative to the scale's base\n line-height: fa-divide(1, $font-size) * 1em; // sets the line-height of the icon back to that of it's parent\n vertical-align: (fa-divide(6, $font-size) - fa-divide(3, 8)) * 1em; // vertically centers the icon taking into account the surrounding text's descender\n}\n\n// only display content to screen readers\n// see: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/\n// see: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/\n@mixin fa-sr-only() {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n\n// use in conjunction with .sr-only to only display content when it's focused\n@mixin fa-sr-only-focusable() {\n &:not(:focus) {\n @include fa-sr-only();\n }\n}\n\n// sets a specific icon family to use alongside style + icon mixins\n\n// convenience mixins for declaring pseudo-elements by CSS variable,\n// including all style-specific font properties, and both the ::before\n// and ::after elements in the duotone case.\n@mixin fa-icon-solid($fa-var) {\n @extend %fa-icon;\n @extend .fa-solid;\n\n &::before {\n content: unquote(\"\\\"#{ $fa-var }\\\"\");\n }\n}\n@mixin fa-icon-regular($fa-var) {\n @extend %fa-icon;\n @extend .fa-regular;\n\n &::before {\n content: unquote(\"\\\"#{ $fa-var }\\\"\");\n }\n}\n@mixin fa-icon-brands($fa-var) {\n @extend %fa-icon;\n @extend .fa-brands;\n\n &::before {\n content: unquote(\"\\\"#{ $fa-var }\\\"\");\n }\n}\n","// fixed-width icons\n// -------------------------\n\n.#{$fa-css-prefix}-fw {\n text-align: center;\n width: $fa-fw-width;\n}\n","// variables\n// --------------------------\n\n$fa-css-prefix : fa !default;\n$fa-style : 900 !default;\n$fa-style-family : \"Font Awesome 6 Free\" !default;\n\n$fa-display : inline-block !default;\n\n$fa-fw-width : fa-divide(20em, 16) !default;\n$fa-inverse : #fff !default;\n\n$fa-border-color : #eee !default;\n$fa-border-padding : .2em .25em .15em !default;\n$fa-border-radius : .1em !default;\n$fa-border-style : solid !default;\n$fa-border-width : .08em !default;\n\n$fa-size-scale-2xs : 10 !default;\n$fa-size-scale-xs : 12 !default;\n$fa-size-scale-sm : 14 !default;\n$fa-size-scale-base : 16 !default;\n$fa-size-scale-lg : 20 !default;\n$fa-size-scale-xl : 24 !default;\n$fa-size-scale-2xl : 32 !default;\n\n$fa-sizes: (\n \"2xs\" : $fa-size-scale-2xs,\n \"xs\" : $fa-size-scale-xs,\n \"sm\" : $fa-size-scale-sm,\n \"lg\" : $fa-size-scale-lg,\n \"xl\" : $fa-size-scale-xl,\n \"2xl\" : $fa-size-scale-2xl\n) !default;\n\n$fa-li-width : 2em !default;\n$fa-li-margin : $fa-li-width * fa-divide(5, 4) !default;\n\n$fa-pull-margin : .3em !default;\n\n$fa-primary-opacity : 1 !default;\n$fa-secondary-opacity : .4 !default;\n\n$fa-stack-vertical-align: middle !default;\n$fa-stack-width : ($fa-fw-width * 2) !default;\n$fa-stack-z-index : auto !default;\n\n$fa-font-display : block !default;\n$fa-font-path : \"../webfonts\" !default;\n\n$fa-var-0: \\30;\n$fa-var-1: \\31;\n$fa-var-2: \\32;\n$fa-var-3: \\33;\n$fa-var-4: \\34;\n$fa-var-5: \\35;\n$fa-var-6: \\36;\n$fa-var-7: \\37;\n$fa-var-8: \\38;\n$fa-var-9: \\39;\n$fa-var-fill-drip: \\f576;\n$fa-var-arrows-to-circle: \\e4bd;\n$fa-var-circle-chevron-right: \\f138;\n$fa-var-chevron-circle-right: \\f138;\n$fa-var-at: \\40;\n$fa-var-trash-can: \\f2ed;\n$fa-var-trash-alt: \\f2ed;\n$fa-var-text-height: \\f034;\n$fa-var-user-xmark: \\f235;\n$fa-var-user-times: \\f235;\n$fa-var-stethoscope: \\f0f1;\n$fa-var-message: \\f27a;\n$fa-var-comment-alt: \\f27a;\n$fa-var-info: \\f129;\n$fa-var-down-left-and-up-right-to-center: \\f422;\n$fa-var-compress-alt: \\f422;\n$fa-var-explosion: \\e4e9;\n$fa-var-file-lines: \\f15c;\n$fa-var-file-alt: \\f15c;\n$fa-var-file-text: \\f15c;\n$fa-var-wave-square: \\f83e;\n$fa-var-ring: \\f70b;\n$fa-var-building-un: \\e4d9;\n$fa-var-dice-three: \\f527;\n$fa-var-calendar-days: \\f073;\n$fa-var-calendar-alt: \\f073;\n$fa-var-anchor-circle-check: \\e4aa;\n$fa-var-building-circle-arrow-right: \\e4d1;\n$fa-var-volleyball: \\f45f;\n$fa-var-volleyball-ball: \\f45f;\n$fa-var-arrows-up-to-line: \\e4c2;\n$fa-var-sort-down: \\f0dd;\n$fa-var-sort-desc: \\f0dd;\n$fa-var-circle-minus: \\f056;\n$fa-var-minus-circle: \\f056;\n$fa-var-door-open: \\f52b;\n$fa-var-right-from-bracket: \\f2f5;\n$fa-var-sign-out-alt: \\f2f5;\n$fa-var-atom: \\f5d2;\n$fa-var-soap: \\e06e;\n$fa-var-icons: \\f86d;\n$fa-var-heart-music-camera-bolt: \\f86d;\n$fa-var-microphone-lines-slash: \\f539;\n$fa-var-microphone-alt-slash: \\f539;\n$fa-var-bridge-circle-check: \\e4c9;\n$fa-var-pump-medical: \\e06a;\n$fa-var-fingerprint: \\f577;\n$fa-var-hand-point-right: \\f0a4;\n$fa-var-magnifying-glass-location: \\f689;\n$fa-var-search-location: \\f689;\n$fa-var-forward-step: \\f051;\n$fa-var-step-forward: \\f051;\n$fa-var-face-smile-beam: \\f5b8;\n$fa-var-smile-beam: \\f5b8;\n$fa-var-flag-checkered: \\f11e;\n$fa-var-football: \\f44e;\n$fa-var-football-ball: \\f44e;\n$fa-var-school-circle-exclamation: \\e56c;\n$fa-var-crop: \\f125;\n$fa-var-angles-down: \\f103;\n$fa-var-angle-double-down: \\f103;\n$fa-var-users-rectangle: \\e594;\n$fa-var-people-roof: \\e537;\n$fa-var-people-line: \\e534;\n$fa-var-beer-mug-empty: \\f0fc;\n$fa-var-beer: \\f0fc;\n$fa-var-diagram-predecessor: \\e477;\n$fa-var-arrow-up-long: \\f176;\n$fa-var-long-arrow-up: \\f176;\n$fa-var-fire-flame-simple: \\f46a;\n$fa-var-burn: \\f46a;\n$fa-var-person: \\f183;\n$fa-var-male: \\f183;\n$fa-var-laptop: \\f109;\n$fa-var-file-csv: \\f6dd;\n$fa-var-menorah: \\f676;\n$fa-var-truck-plane: \\e58f;\n$fa-var-record-vinyl: \\f8d9;\n$fa-var-face-grin-stars: \\f587;\n$fa-var-grin-stars: \\f587;\n$fa-var-bong: \\f55c;\n$fa-var-spaghetti-monster-flying: \\f67b;\n$fa-var-pastafarianism: \\f67b;\n$fa-var-arrow-down-up-across-line: \\e4af;\n$fa-var-spoon: \\f2e5;\n$fa-var-utensil-spoon: \\f2e5;\n$fa-var-jar-wheat: \\e517;\n$fa-var-envelopes-bulk: \\f674;\n$fa-var-mail-bulk: \\f674;\n$fa-var-file-circle-exclamation: \\e4eb;\n$fa-var-circle-h: \\f47e;\n$fa-var-hospital-symbol: \\f47e;\n$fa-var-pager: \\f815;\n$fa-var-address-book: \\f2b9;\n$fa-var-contact-book: \\f2b9;\n$fa-var-strikethrough: \\f0cc;\n$fa-var-k: \\4b;\n$fa-var-landmark-flag: \\e51c;\n$fa-var-pencil: \\f303;\n$fa-var-pencil-alt: \\f303;\n$fa-var-backward: \\f04a;\n$fa-var-caret-right: \\f0da;\n$fa-var-comments: \\f086;\n$fa-var-paste: \\f0ea;\n$fa-var-file-clipboard: \\f0ea;\n$fa-var-code-pull-request: \\e13c;\n$fa-var-clipboard-list: \\f46d;\n$fa-var-truck-ramp-box: \\f4de;\n$fa-var-truck-loading: \\f4de;\n$fa-var-user-check: \\f4fc;\n$fa-var-vial-virus: \\e597;\n$fa-var-sheet-plastic: \\e571;\n$fa-var-blog: \\f781;\n$fa-var-user-ninja: \\f504;\n$fa-var-person-arrow-up-from-line: \\e539;\n$fa-var-scroll-torah: \\f6a0;\n$fa-var-torah: \\f6a0;\n$fa-var-broom-ball: \\f458;\n$fa-var-quidditch: \\f458;\n$fa-var-quidditch-broom-ball: \\f458;\n$fa-var-toggle-off: \\f204;\n$fa-var-box-archive: \\f187;\n$fa-var-archive: \\f187;\n$fa-var-person-drowning: \\e545;\n$fa-var-arrow-down-9-1: \\f886;\n$fa-var-sort-numeric-desc: \\f886;\n$fa-var-sort-numeric-down-alt: \\f886;\n$fa-var-face-grin-tongue-squint: \\f58a;\n$fa-var-grin-tongue-squint: \\f58a;\n$fa-var-spray-can: \\f5bd;\n$fa-var-truck-monster: \\f63b;\n$fa-var-w: \\57;\n$fa-var-earth-africa: \\f57c;\n$fa-var-globe-africa: \\f57c;\n$fa-var-rainbow: \\f75b;\n$fa-var-circle-notch: \\f1ce;\n$fa-var-tablet-screen-button: \\f3fa;\n$fa-var-tablet-alt: \\f3fa;\n$fa-var-paw: \\f1b0;\n$fa-var-cloud: \\f0c2;\n$fa-var-trowel-bricks: \\e58a;\n$fa-var-face-flushed: \\f579;\n$fa-var-flushed: \\f579;\n$fa-var-hospital-user: \\f80d;\n$fa-var-tent-arrow-left-right: \\e57f;\n$fa-var-gavel: \\f0e3;\n$fa-var-legal: \\f0e3;\n$fa-var-binoculars: \\f1e5;\n$fa-var-microphone-slash: \\f131;\n$fa-var-box-tissue: \\e05b;\n$fa-var-motorcycle: \\f21c;\n$fa-var-bell-concierge: \\f562;\n$fa-var-concierge-bell: \\f562;\n$fa-var-pen-ruler: \\f5ae;\n$fa-var-pencil-ruler: \\f5ae;\n$fa-var-people-arrows: \\e068;\n$fa-var-people-arrows-left-right: \\e068;\n$fa-var-mars-and-venus-burst: \\e523;\n$fa-var-square-caret-right: \\f152;\n$fa-var-caret-square-right: \\f152;\n$fa-var-scissors: \\f0c4;\n$fa-var-cut: \\f0c4;\n$fa-var-sun-plant-wilt: \\e57a;\n$fa-var-toilets-portable: \\e584;\n$fa-var-hockey-puck: \\f453;\n$fa-var-table: \\f0ce;\n$fa-var-magnifying-glass-arrow-right: \\e521;\n$fa-var-tachograph-digital: \\f566;\n$fa-var-digital-tachograph: \\f566;\n$fa-var-users-slash: \\e073;\n$fa-var-clover: \\e139;\n$fa-var-reply: \\f3e5;\n$fa-var-mail-reply: \\f3e5;\n$fa-var-star-and-crescent: \\f699;\n$fa-var-house-fire: \\e50c;\n$fa-var-square-minus: \\f146;\n$fa-var-minus-square: \\f146;\n$fa-var-helicopter: \\f533;\n$fa-var-compass: \\f14e;\n$fa-var-square-caret-down: \\f150;\n$fa-var-caret-square-down: \\f150;\n$fa-var-file-circle-question: \\e4ef;\n$fa-var-laptop-code: \\f5fc;\n$fa-var-swatchbook: \\f5c3;\n$fa-var-prescription-bottle: \\f485;\n$fa-var-bars: \\f0c9;\n$fa-var-navicon: \\f0c9;\n$fa-var-people-group: \\e533;\n$fa-var-hourglass-end: \\f253;\n$fa-var-hourglass-3: \\f253;\n$fa-var-heart-crack: \\f7a9;\n$fa-var-heart-broken: \\f7a9;\n$fa-var-square-up-right: \\f360;\n$fa-var-external-link-square-alt: \\f360;\n$fa-var-face-kiss-beam: \\f597;\n$fa-var-kiss-beam: \\f597;\n$fa-var-film: \\f008;\n$fa-var-ruler-horizontal: \\f547;\n$fa-var-people-robbery: \\e536;\n$fa-var-lightbulb: \\f0eb;\n$fa-var-caret-left: \\f0d9;\n$fa-var-circle-exclamation: \\f06a;\n$fa-var-exclamation-circle: \\f06a;\n$fa-var-school-circle-xmark: \\e56d;\n$fa-var-arrow-right-from-bracket: \\f08b;\n$fa-var-sign-out: \\f08b;\n$fa-var-circle-chevron-down: \\f13a;\n$fa-var-chevron-circle-down: \\f13a;\n$fa-var-unlock-keyhole: \\f13e;\n$fa-var-unlock-alt: \\f13e;\n$fa-var-cloud-showers-heavy: \\f740;\n$fa-var-headphones-simple: \\f58f;\n$fa-var-headphones-alt: \\f58f;\n$fa-var-sitemap: \\f0e8;\n$fa-var-circle-dollar-to-slot: \\f4b9;\n$fa-var-donate: \\f4b9;\n$fa-var-memory: \\f538;\n$fa-var-road-spikes: \\e568;\n$fa-var-fire-burner: \\e4f1;\n$fa-var-flag: \\f024;\n$fa-var-hanukiah: \\f6e6;\n$fa-var-feather: \\f52d;\n$fa-var-volume-low: \\f027;\n$fa-var-volume-down: \\f027;\n$fa-var-comment-slash: \\f4b3;\n$fa-var-cloud-sun-rain: \\f743;\n$fa-var-compress: \\f066;\n$fa-var-wheat-awn: \\e2cd;\n$fa-var-wheat-alt: \\e2cd;\n$fa-var-ankh: \\f644;\n$fa-var-hands-holding-child: \\e4fa;\n$fa-var-asterisk: \\2a;\n$fa-var-square-check: \\f14a;\n$fa-var-check-square: \\f14a;\n$fa-var-peseta-sign: \\e221;\n$fa-var-heading: \\f1dc;\n$fa-var-header: \\f1dc;\n$fa-var-ghost: \\f6e2;\n$fa-var-list: \\f03a;\n$fa-var-list-squares: \\f03a;\n$fa-var-square-phone-flip: \\f87b;\n$fa-var-phone-square-alt: \\f87b;\n$fa-var-cart-plus: \\f217;\n$fa-var-gamepad: \\f11b;\n$fa-var-circle-dot: \\f192;\n$fa-var-dot-circle: \\f192;\n$fa-var-face-dizzy: \\f567;\n$fa-var-dizzy: \\f567;\n$fa-var-egg: \\f7fb;\n$fa-var-house-medical-circle-xmark: \\e513;\n$fa-var-campground: \\f6bb;\n$fa-var-folder-plus: \\f65e;\n$fa-var-futbol: \\f1e3;\n$fa-var-futbol-ball: \\f1e3;\n$fa-var-soccer-ball: \\f1e3;\n$fa-var-paintbrush: \\f1fc;\n$fa-var-paint-brush: \\f1fc;\n$fa-var-lock: \\f023;\n$fa-var-gas-pump: \\f52f;\n$fa-var-hot-tub-person: \\f593;\n$fa-var-hot-tub: \\f593;\n$fa-var-map-location: \\f59f;\n$fa-var-map-marked: \\f59f;\n$fa-var-house-flood-water: \\e50e;\n$fa-var-tree: \\f1bb;\n$fa-var-bridge-lock: \\e4cc;\n$fa-var-sack-dollar: \\f81d;\n$fa-var-pen-to-square: \\f044;\n$fa-var-edit: \\f044;\n$fa-var-car-side: \\f5e4;\n$fa-var-share-nodes: \\f1e0;\n$fa-var-share-alt: \\f1e0;\n$fa-var-heart-circle-minus: \\e4ff;\n$fa-var-hourglass-half: \\f252;\n$fa-var-hourglass-2: \\f252;\n$fa-var-microscope: \\f610;\n$fa-var-sink: \\e06d;\n$fa-var-bag-shopping: \\f290;\n$fa-var-shopping-bag: \\f290;\n$fa-var-arrow-down-z-a: \\f881;\n$fa-var-sort-alpha-desc: \\f881;\n$fa-var-sort-alpha-down-alt: \\f881;\n$fa-var-mitten: \\f7b5;\n$fa-var-person-rays: \\e54d;\n$fa-var-users: \\f0c0;\n$fa-var-eye-slash: \\f070;\n$fa-var-flask-vial: \\e4f3;\n$fa-var-hand: \\f256;\n$fa-var-hand-paper: \\f256;\n$fa-var-om: \\f679;\n$fa-var-worm: \\e599;\n$fa-var-house-circle-xmark: \\e50b;\n$fa-var-plug: \\f1e6;\n$fa-var-chevron-up: \\f077;\n$fa-var-hand-spock: \\f259;\n$fa-var-stopwatch: \\f2f2;\n$fa-var-face-kiss: \\f596;\n$fa-var-kiss: \\f596;\n$fa-var-bridge-circle-xmark: \\e4cb;\n$fa-var-face-grin-tongue: \\f589;\n$fa-var-grin-tongue: \\f589;\n$fa-var-chess-bishop: \\f43a;\n$fa-var-face-grin-wink: \\f58c;\n$fa-var-grin-wink: \\f58c;\n$fa-var-ear-deaf: \\f2a4;\n$fa-var-deaf: \\f2a4;\n$fa-var-deafness: \\f2a4;\n$fa-var-hard-of-hearing: \\f2a4;\n$fa-var-road-circle-check: \\e564;\n$fa-var-dice-five: \\f523;\n$fa-var-square-rss: \\f143;\n$fa-var-rss-square: \\f143;\n$fa-var-land-mine-on: \\e51b;\n$fa-var-i-cursor: \\f246;\n$fa-var-stamp: \\f5bf;\n$fa-var-stairs: \\e289;\n$fa-var-i: \\49;\n$fa-var-hryvnia-sign: \\f6f2;\n$fa-var-hryvnia: \\f6f2;\n$fa-var-pills: \\f484;\n$fa-var-face-grin-wide: \\f581;\n$fa-var-grin-alt: \\f581;\n$fa-var-tooth: \\f5c9;\n$fa-var-v: \\56;\n$fa-var-bangladeshi-taka-sign: \\e2e6;\n$fa-var-bicycle: \\f206;\n$fa-var-staff-snake: \\e579;\n$fa-var-rod-asclepius: \\e579;\n$fa-var-rod-snake: \\e579;\n$fa-var-staff-aesculapius: \\e579;\n$fa-var-head-side-cough-slash: \\e062;\n$fa-var-truck-medical: \\f0f9;\n$fa-var-ambulance: \\f0f9;\n$fa-var-wheat-awn-circle-exclamation: \\e598;\n$fa-var-snowman: \\f7d0;\n$fa-var-mortar-pestle: \\f5a7;\n$fa-var-road-barrier: \\e562;\n$fa-var-school: \\f549;\n$fa-var-igloo: \\f7ae;\n$fa-var-joint: \\f595;\n$fa-var-angle-right: \\f105;\n$fa-var-horse: \\f6f0;\n$fa-var-q: \\51;\n$fa-var-g: \\47;\n$fa-var-notes-medical: \\f481;\n$fa-var-temperature-half: \\f2c9;\n$fa-var-temperature-2: \\f2c9;\n$fa-var-thermometer-2: \\f2c9;\n$fa-var-thermometer-half: \\f2c9;\n$fa-var-dong-sign: \\e169;\n$fa-var-capsules: \\f46b;\n$fa-var-poo-storm: \\f75a;\n$fa-var-poo-bolt: \\f75a;\n$fa-var-face-frown-open: \\f57a;\n$fa-var-frown-open: \\f57a;\n$fa-var-hand-point-up: \\f0a6;\n$fa-var-money-bill: \\f0d6;\n$fa-var-bookmark: \\f02e;\n$fa-var-align-justify: \\f039;\n$fa-var-umbrella-beach: \\f5ca;\n$fa-var-helmet-un: \\e503;\n$fa-var-bullseye: \\f140;\n$fa-var-bacon: \\f7e5;\n$fa-var-hand-point-down: \\f0a7;\n$fa-var-arrow-up-from-bracket: \\e09a;\n$fa-var-folder: \\f07b;\n$fa-var-folder-blank: \\f07b;\n$fa-var-file-waveform: \\f478;\n$fa-var-file-medical-alt: \\f478;\n$fa-var-radiation: \\f7b9;\n$fa-var-chart-simple: \\e473;\n$fa-var-mars-stroke: \\f229;\n$fa-var-vial: \\f492;\n$fa-var-gauge: \\f624;\n$fa-var-dashboard: \\f624;\n$fa-var-gauge-med: \\f624;\n$fa-var-tachometer-alt-average: \\f624;\n$fa-var-wand-magic-sparkles: \\e2ca;\n$fa-var-magic-wand-sparkles: \\e2ca;\n$fa-var-e: \\45;\n$fa-var-pen-clip: \\f305;\n$fa-var-pen-alt: \\f305;\n$fa-var-bridge-circle-exclamation: \\e4ca;\n$fa-var-user: \\f007;\n$fa-var-school-circle-check: \\e56b;\n$fa-var-dumpster: \\f793;\n$fa-var-van-shuttle: \\f5b6;\n$fa-var-shuttle-van: \\f5b6;\n$fa-var-building-user: \\e4da;\n$fa-var-square-caret-left: \\f191;\n$fa-var-caret-square-left: \\f191;\n$fa-var-highlighter: \\f591;\n$fa-var-key: \\f084;\n$fa-var-bullhorn: \\f0a1;\n$fa-var-globe: \\f0ac;\n$fa-var-synagogue: \\f69b;\n$fa-var-person-half-dress: \\e548;\n$fa-var-road-bridge: \\e563;\n$fa-var-location-arrow: \\f124;\n$fa-var-c: \\43;\n$fa-var-tablet-button: \\f10a;\n$fa-var-building-lock: \\e4d6;\n$fa-var-pizza-slice: \\f818;\n$fa-var-money-bill-wave: \\f53a;\n$fa-var-chart-area: \\f1fe;\n$fa-var-area-chart: \\f1fe;\n$fa-var-house-flag: \\e50d;\n$fa-var-person-circle-minus: \\e540;\n$fa-var-ban: \\f05e;\n$fa-var-cancel: \\f05e;\n$fa-var-camera-rotate: \\e0d8;\n$fa-var-spray-can-sparkles: \\f5d0;\n$fa-var-air-freshener: \\f5d0;\n$fa-var-star: \\f005;\n$fa-var-repeat: \\f363;\n$fa-var-cross: \\f654;\n$fa-var-box: \\f466;\n$fa-var-venus-mars: \\f228;\n$fa-var-arrow-pointer: \\f245;\n$fa-var-mouse-pointer: \\f245;\n$fa-var-maximize: \\f31e;\n$fa-var-expand-arrows-alt: \\f31e;\n$fa-var-charging-station: \\f5e7;\n$fa-var-shapes: \\f61f;\n$fa-var-triangle-circle-square: \\f61f;\n$fa-var-shuffle: \\f074;\n$fa-var-random: \\f074;\n$fa-var-person-running: \\f70c;\n$fa-var-running: \\f70c;\n$fa-var-mobile-retro: \\e527;\n$fa-var-grip-lines-vertical: \\f7a5;\n$fa-var-spider: \\f717;\n$fa-var-hands-bound: \\e4f9;\n$fa-var-file-invoice-dollar: \\f571;\n$fa-var-plane-circle-exclamation: \\e556;\n$fa-var-x-ray: \\f497;\n$fa-var-spell-check: \\f891;\n$fa-var-slash: \\f715;\n$fa-var-computer-mouse: \\f8cc;\n$fa-var-mouse: \\f8cc;\n$fa-var-arrow-right-to-bracket: \\f090;\n$fa-var-sign-in: \\f090;\n$fa-var-shop-slash: \\e070;\n$fa-var-store-alt-slash: \\e070;\n$fa-var-server: \\f233;\n$fa-var-virus-covid-slash: \\e4a9;\n$fa-var-shop-lock: \\e4a5;\n$fa-var-hourglass-start: \\f251;\n$fa-var-hourglass-1: \\f251;\n$fa-var-blender-phone: \\f6b6;\n$fa-var-building-wheat: \\e4db;\n$fa-var-person-breastfeeding: \\e53a;\n$fa-var-right-to-bracket: \\f2f6;\n$fa-var-sign-in-alt: \\f2f6;\n$fa-var-venus: \\f221;\n$fa-var-passport: \\f5ab;\n$fa-var-thumbtack-slash: \\e68f;\n$fa-var-thumb-tack-slash: \\e68f;\n$fa-var-heart-pulse: \\f21e;\n$fa-var-heartbeat: \\f21e;\n$fa-var-people-carry-box: \\f4ce;\n$fa-var-people-carry: \\f4ce;\n$fa-var-temperature-high: \\f769;\n$fa-var-microchip: \\f2db;\n$fa-var-crown: \\f521;\n$fa-var-weight-hanging: \\f5cd;\n$fa-var-xmarks-lines: \\e59a;\n$fa-var-file-prescription: \\f572;\n$fa-var-weight-scale: \\f496;\n$fa-var-weight: \\f496;\n$fa-var-user-group: \\f500;\n$fa-var-user-friends: \\f500;\n$fa-var-arrow-up-a-z: \\f15e;\n$fa-var-sort-alpha-up: \\f15e;\n$fa-var-chess-knight: \\f441;\n$fa-var-face-laugh-squint: \\f59b;\n$fa-var-laugh-squint: \\f59b;\n$fa-var-wheelchair: \\f193;\n$fa-var-circle-arrow-up: \\f0aa;\n$fa-var-arrow-circle-up: \\f0aa;\n$fa-var-toggle-on: \\f205;\n$fa-var-person-walking: \\f554;\n$fa-var-walking: \\f554;\n$fa-var-l: \\4c;\n$fa-var-fire: \\f06d;\n$fa-var-bed-pulse: \\f487;\n$fa-var-procedures: \\f487;\n$fa-var-shuttle-space: \\f197;\n$fa-var-space-shuttle: \\f197;\n$fa-var-face-laugh: \\f599;\n$fa-var-laugh: \\f599;\n$fa-var-folder-open: \\f07c;\n$fa-var-heart-circle-plus: \\e500;\n$fa-var-code-fork: \\e13b;\n$fa-var-city: \\f64f;\n$fa-var-microphone-lines: \\f3c9;\n$fa-var-microphone-alt: \\f3c9;\n$fa-var-pepper-hot: \\f816;\n$fa-var-unlock: \\f09c;\n$fa-var-colon-sign: \\e140;\n$fa-var-headset: \\f590;\n$fa-var-store-slash: \\e071;\n$fa-var-road-circle-xmark: \\e566;\n$fa-var-user-minus: \\f503;\n$fa-var-mars-stroke-up: \\f22a;\n$fa-var-mars-stroke-v: \\f22a;\n$fa-var-champagne-glasses: \\f79f;\n$fa-var-glass-cheers: \\f79f;\n$fa-var-clipboard: \\f328;\n$fa-var-house-circle-exclamation: \\e50a;\n$fa-var-file-arrow-up: \\f574;\n$fa-var-file-upload: \\f574;\n$fa-var-wifi: \\f1eb;\n$fa-var-wifi-3: \\f1eb;\n$fa-var-wifi-strong: \\f1eb;\n$fa-var-bath: \\f2cd;\n$fa-var-bathtub: \\f2cd;\n$fa-var-underline: \\f0cd;\n$fa-var-user-pen: \\f4ff;\n$fa-var-user-edit: \\f4ff;\n$fa-var-signature: \\f5b7;\n$fa-var-stroopwafel: \\f551;\n$fa-var-bold: \\f032;\n$fa-var-anchor-lock: \\e4ad;\n$fa-var-building-ngo: \\e4d7;\n$fa-var-manat-sign: \\e1d5;\n$fa-var-not-equal: \\f53e;\n$fa-var-border-top-left: \\f853;\n$fa-var-border-style: \\f853;\n$fa-var-map-location-dot: \\f5a0;\n$fa-var-map-marked-alt: \\f5a0;\n$fa-var-jedi: \\f669;\n$fa-var-square-poll-vertical: \\f681;\n$fa-var-poll: \\f681;\n$fa-var-mug-hot: \\f7b6;\n$fa-var-car-battery: \\f5df;\n$fa-var-battery-car: \\f5df;\n$fa-var-gift: \\f06b;\n$fa-var-dice-two: \\f528;\n$fa-var-chess-queen: \\f445;\n$fa-var-glasses: \\f530;\n$fa-var-chess-board: \\f43c;\n$fa-var-building-circle-check: \\e4d2;\n$fa-var-person-chalkboard: \\e53d;\n$fa-var-mars-stroke-right: \\f22b;\n$fa-var-mars-stroke-h: \\f22b;\n$fa-var-hand-back-fist: \\f255;\n$fa-var-hand-rock: \\f255;\n$fa-var-square-caret-up: \\f151;\n$fa-var-caret-square-up: \\f151;\n$fa-var-cloud-showers-water: \\e4e4;\n$fa-var-chart-bar: \\f080;\n$fa-var-bar-chart: \\f080;\n$fa-var-hands-bubbles: \\e05e;\n$fa-var-hands-wash: \\e05e;\n$fa-var-less-than-equal: \\f537;\n$fa-var-train: \\f238;\n$fa-var-eye-low-vision: \\f2a8;\n$fa-var-low-vision: \\f2a8;\n$fa-var-crow: \\f520;\n$fa-var-sailboat: \\e445;\n$fa-var-window-restore: \\f2d2;\n$fa-var-square-plus: \\f0fe;\n$fa-var-plus-square: \\f0fe;\n$fa-var-torii-gate: \\f6a1;\n$fa-var-frog: \\f52e;\n$fa-var-bucket: \\e4cf;\n$fa-var-image: \\f03e;\n$fa-var-microphone: \\f130;\n$fa-var-cow: \\f6c8;\n$fa-var-caret-up: \\f0d8;\n$fa-var-screwdriver: \\f54a;\n$fa-var-folder-closed: \\e185;\n$fa-var-house-tsunami: \\e515;\n$fa-var-square-nfi: \\e576;\n$fa-var-arrow-up-from-ground-water: \\e4b5;\n$fa-var-martini-glass: \\f57b;\n$fa-var-glass-martini-alt: \\f57b;\n$fa-var-rotate-left: \\f2ea;\n$fa-var-rotate-back: \\f2ea;\n$fa-var-rotate-backward: \\f2ea;\n$fa-var-undo-alt: \\f2ea;\n$fa-var-table-columns: \\f0db;\n$fa-var-columns: \\f0db;\n$fa-var-lemon: \\f094;\n$fa-var-head-side-mask: \\e063;\n$fa-var-handshake: \\f2b5;\n$fa-var-gem: \\f3a5;\n$fa-var-dolly: \\f472;\n$fa-var-dolly-box: \\f472;\n$fa-var-smoking: \\f48d;\n$fa-var-minimize: \\f78c;\n$fa-var-compress-arrows-alt: \\f78c;\n$fa-var-monument: \\f5a6;\n$fa-var-snowplow: \\f7d2;\n$fa-var-angles-right: \\f101;\n$fa-var-angle-double-right: \\f101;\n$fa-var-cannabis: \\f55f;\n$fa-var-circle-play: \\f144;\n$fa-var-play-circle: \\f144;\n$fa-var-tablets: \\f490;\n$fa-var-ethernet: \\f796;\n$fa-var-euro-sign: \\f153;\n$fa-var-eur: \\f153;\n$fa-var-euro: \\f153;\n$fa-var-chair: \\f6c0;\n$fa-var-circle-check: \\f058;\n$fa-var-check-circle: \\f058;\n$fa-var-circle-stop: \\f28d;\n$fa-var-stop-circle: \\f28d;\n$fa-var-compass-drafting: \\f568;\n$fa-var-drafting-compass: \\f568;\n$fa-var-plate-wheat: \\e55a;\n$fa-var-icicles: \\f7ad;\n$fa-var-person-shelter: \\e54f;\n$fa-var-neuter: \\f22c;\n$fa-var-id-badge: \\f2c1;\n$fa-var-marker: \\f5a1;\n$fa-var-face-laugh-beam: \\f59a;\n$fa-var-laugh-beam: \\f59a;\n$fa-var-helicopter-symbol: \\e502;\n$fa-var-universal-access: \\f29a;\n$fa-var-circle-chevron-up: \\f139;\n$fa-var-chevron-circle-up: \\f139;\n$fa-var-lari-sign: \\e1c8;\n$fa-var-volcano: \\f770;\n$fa-var-person-walking-dashed-line-arrow-right: \\e553;\n$fa-var-sterling-sign: \\f154;\n$fa-var-gbp: \\f154;\n$fa-var-pound-sign: \\f154;\n$fa-var-viruses: \\e076;\n$fa-var-square-person-confined: \\e577;\n$fa-var-user-tie: \\f508;\n$fa-var-arrow-down-long: \\f175;\n$fa-var-long-arrow-down: \\f175;\n$fa-var-tent-arrow-down-to-line: \\e57e;\n$fa-var-certificate: \\f0a3;\n$fa-var-reply-all: \\f122;\n$fa-var-mail-reply-all: \\f122;\n$fa-var-suitcase: \\f0f2;\n$fa-var-person-skating: \\f7c5;\n$fa-var-skating: \\f7c5;\n$fa-var-filter-circle-dollar: \\f662;\n$fa-var-funnel-dollar: \\f662;\n$fa-var-camera-retro: \\f083;\n$fa-var-circle-arrow-down: \\f0ab;\n$fa-var-arrow-circle-down: \\f0ab;\n$fa-var-file-import: \\f56f;\n$fa-var-arrow-right-to-file: \\f56f;\n$fa-var-square-arrow-up-right: \\f14c;\n$fa-var-external-link-square: \\f14c;\n$fa-var-box-open: \\f49e;\n$fa-var-scroll: \\f70e;\n$fa-var-spa: \\f5bb;\n$fa-var-location-pin-lock: \\e51f;\n$fa-var-pause: \\f04c;\n$fa-var-hill-avalanche: \\e507;\n$fa-var-temperature-empty: \\f2cb;\n$fa-var-temperature-0: \\f2cb;\n$fa-var-thermometer-0: \\f2cb;\n$fa-var-thermometer-empty: \\f2cb;\n$fa-var-bomb: \\f1e2;\n$fa-var-registered: \\f25d;\n$fa-var-address-card: \\f2bb;\n$fa-var-contact-card: \\f2bb;\n$fa-var-vcard: \\f2bb;\n$fa-var-scale-unbalanced-flip: \\f516;\n$fa-var-balance-scale-right: \\f516;\n$fa-var-subscript: \\f12c;\n$fa-var-diamond-turn-right: \\f5eb;\n$fa-var-directions: \\f5eb;\n$fa-var-burst: \\e4dc;\n$fa-var-house-laptop: \\e066;\n$fa-var-laptop-house: \\e066;\n$fa-var-face-tired: \\f5c8;\n$fa-var-tired: \\f5c8;\n$fa-var-money-bills: \\e1f3;\n$fa-var-smog: \\f75f;\n$fa-var-crutch: \\f7f7;\n$fa-var-cloud-arrow-up: \\f0ee;\n$fa-var-cloud-upload: \\f0ee;\n$fa-var-cloud-upload-alt: \\f0ee;\n$fa-var-palette: \\f53f;\n$fa-var-arrows-turn-right: \\e4c0;\n$fa-var-vest: \\e085;\n$fa-var-ferry: \\e4ea;\n$fa-var-arrows-down-to-people: \\e4b9;\n$fa-var-seedling: \\f4d8;\n$fa-var-sprout: \\f4d8;\n$fa-var-left-right: \\f337;\n$fa-var-arrows-alt-h: \\f337;\n$fa-var-boxes-packing: \\e4c7;\n$fa-var-circle-arrow-left: \\f0a8;\n$fa-var-arrow-circle-left: \\f0a8;\n$fa-var-group-arrows-rotate: \\e4f6;\n$fa-var-bowl-food: \\e4c6;\n$fa-var-candy-cane: \\f786;\n$fa-var-arrow-down-wide-short: \\f160;\n$fa-var-sort-amount-asc: \\f160;\n$fa-var-sort-amount-down: \\f160;\n$fa-var-cloud-bolt: \\f76c;\n$fa-var-thunderstorm: \\f76c;\n$fa-var-text-slash: \\f87d;\n$fa-var-remove-format: \\f87d;\n$fa-var-face-smile-wink: \\f4da;\n$fa-var-smile-wink: \\f4da;\n$fa-var-file-word: \\f1c2;\n$fa-var-file-powerpoint: \\f1c4;\n$fa-var-arrows-left-right: \\f07e;\n$fa-var-arrows-h: \\f07e;\n$fa-var-house-lock: \\e510;\n$fa-var-cloud-arrow-down: \\f0ed;\n$fa-var-cloud-download: \\f0ed;\n$fa-var-cloud-download-alt: \\f0ed;\n$fa-var-children: \\e4e1;\n$fa-var-chalkboard: \\f51b;\n$fa-var-blackboard: \\f51b;\n$fa-var-user-large-slash: \\f4fa;\n$fa-var-user-alt-slash: \\f4fa;\n$fa-var-envelope-open: \\f2b6;\n$fa-var-handshake-simple-slash: \\e05f;\n$fa-var-handshake-alt-slash: \\e05f;\n$fa-var-mattress-pillow: \\e525;\n$fa-var-guarani-sign: \\e19a;\n$fa-var-arrows-rotate: \\f021;\n$fa-var-refresh: \\f021;\n$fa-var-sync: \\f021;\n$fa-var-fire-extinguisher: \\f134;\n$fa-var-cruzeiro-sign: \\e152;\n$fa-var-greater-than-equal: \\f532;\n$fa-var-shield-halved: \\f3ed;\n$fa-var-shield-alt: \\f3ed;\n$fa-var-book-atlas: \\f558;\n$fa-var-atlas: \\f558;\n$fa-var-virus: \\e074;\n$fa-var-envelope-circle-check: \\e4e8;\n$fa-var-layer-group: \\f5fd;\n$fa-var-arrows-to-dot: \\e4be;\n$fa-var-archway: \\f557;\n$fa-var-heart-circle-check: \\e4fd;\n$fa-var-house-chimney-crack: \\f6f1;\n$fa-var-house-damage: \\f6f1;\n$fa-var-file-zipper: \\f1c6;\n$fa-var-file-archive: \\f1c6;\n$fa-var-square: \\f0c8;\n$fa-var-martini-glass-empty: \\f000;\n$fa-var-glass-martini: \\f000;\n$fa-var-couch: \\f4b8;\n$fa-var-cedi-sign: \\e0df;\n$fa-var-italic: \\f033;\n$fa-var-table-cells-column-lock: \\e678;\n$fa-var-church: \\f51d;\n$fa-var-comments-dollar: \\f653;\n$fa-var-democrat: \\f747;\n$fa-var-z: \\5a;\n$fa-var-person-skiing: \\f7c9;\n$fa-var-skiing: \\f7c9;\n$fa-var-road-lock: \\e567;\n$fa-var-a: \\41;\n$fa-var-temperature-arrow-down: \\e03f;\n$fa-var-temperature-down: \\e03f;\n$fa-var-feather-pointed: \\f56b;\n$fa-var-feather-alt: \\f56b;\n$fa-var-p: \\50;\n$fa-var-snowflake: \\f2dc;\n$fa-var-newspaper: \\f1ea;\n$fa-var-rectangle-ad: \\f641;\n$fa-var-ad: \\f641;\n$fa-var-circle-arrow-right: \\f0a9;\n$fa-var-arrow-circle-right: \\f0a9;\n$fa-var-filter-circle-xmark: \\e17b;\n$fa-var-locust: \\e520;\n$fa-var-sort: \\f0dc;\n$fa-var-unsorted: \\f0dc;\n$fa-var-list-ol: \\f0cb;\n$fa-var-list-1-2: \\f0cb;\n$fa-var-list-numeric: \\f0cb;\n$fa-var-person-dress-burst: \\e544;\n$fa-var-money-check-dollar: \\f53d;\n$fa-var-money-check-alt: \\f53d;\n$fa-var-vector-square: \\f5cb;\n$fa-var-bread-slice: \\f7ec;\n$fa-var-language: \\f1ab;\n$fa-var-face-kiss-wink-heart: \\f598;\n$fa-var-kiss-wink-heart: \\f598;\n$fa-var-filter: \\f0b0;\n$fa-var-question: \\3f;\n$fa-var-file-signature: \\f573;\n$fa-var-up-down-left-right: \\f0b2;\n$fa-var-arrows-alt: \\f0b2;\n$fa-var-house-chimney-user: \\e065;\n$fa-var-hand-holding-heart: \\f4be;\n$fa-var-puzzle-piece: \\f12e;\n$fa-var-money-check: \\f53c;\n$fa-var-star-half-stroke: \\f5c0;\n$fa-var-star-half-alt: \\f5c0;\n$fa-var-code: \\f121;\n$fa-var-whiskey-glass: \\f7a0;\n$fa-var-glass-whiskey: \\f7a0;\n$fa-var-building-circle-exclamation: \\e4d3;\n$fa-var-magnifying-glass-chart: \\e522;\n$fa-var-arrow-up-right-from-square: \\f08e;\n$fa-var-external-link: \\f08e;\n$fa-var-cubes-stacked: \\e4e6;\n$fa-var-won-sign: \\f159;\n$fa-var-krw: \\f159;\n$fa-var-won: \\f159;\n$fa-var-virus-covid: \\e4a8;\n$fa-var-austral-sign: \\e0a9;\n$fa-var-f: \\46;\n$fa-var-leaf: \\f06c;\n$fa-var-road: \\f018;\n$fa-var-taxi: \\f1ba;\n$fa-var-cab: \\f1ba;\n$fa-var-person-circle-plus: \\e541;\n$fa-var-chart-pie: \\f200;\n$fa-var-pie-chart: \\f200;\n$fa-var-bolt-lightning: \\e0b7;\n$fa-var-sack-xmark: \\e56a;\n$fa-var-file-excel: \\f1c3;\n$fa-var-file-contract: \\f56c;\n$fa-var-fish-fins: \\e4f2;\n$fa-var-building-flag: \\e4d5;\n$fa-var-face-grin-beam: \\f582;\n$fa-var-grin-beam: \\f582;\n$fa-var-object-ungroup: \\f248;\n$fa-var-poop: \\f619;\n$fa-var-location-pin: \\f041;\n$fa-var-map-marker: \\f041;\n$fa-var-kaaba: \\f66b;\n$fa-var-toilet-paper: \\f71e;\n$fa-var-helmet-safety: \\f807;\n$fa-var-hard-hat: \\f807;\n$fa-var-hat-hard: \\f807;\n$fa-var-eject: \\f052;\n$fa-var-circle-right: \\f35a;\n$fa-var-arrow-alt-circle-right: \\f35a;\n$fa-var-plane-circle-check: \\e555;\n$fa-var-face-rolling-eyes: \\f5a5;\n$fa-var-meh-rolling-eyes: \\f5a5;\n$fa-var-object-group: \\f247;\n$fa-var-chart-line: \\f201;\n$fa-var-line-chart: \\f201;\n$fa-var-mask-ventilator: \\e524;\n$fa-var-arrow-right: \\f061;\n$fa-var-signs-post: \\f277;\n$fa-var-map-signs: \\f277;\n$fa-var-cash-register: \\f788;\n$fa-var-person-circle-question: \\e542;\n$fa-var-h: \\48;\n$fa-var-tarp: \\e57b;\n$fa-var-screwdriver-wrench: \\f7d9;\n$fa-var-tools: \\f7d9;\n$fa-var-arrows-to-eye: \\e4bf;\n$fa-var-plug-circle-bolt: \\e55b;\n$fa-var-heart: \\f004;\n$fa-var-mars-and-venus: \\f224;\n$fa-var-house-user: \\e1b0;\n$fa-var-home-user: \\e1b0;\n$fa-var-dumpster-fire: \\f794;\n$fa-var-house-crack: \\e3b1;\n$fa-var-martini-glass-citrus: \\f561;\n$fa-var-cocktail: \\f561;\n$fa-var-face-surprise: \\f5c2;\n$fa-var-surprise: \\f5c2;\n$fa-var-bottle-water: \\e4c5;\n$fa-var-circle-pause: \\f28b;\n$fa-var-pause-circle: \\f28b;\n$fa-var-toilet-paper-slash: \\e072;\n$fa-var-apple-whole: \\f5d1;\n$fa-var-apple-alt: \\f5d1;\n$fa-var-kitchen-set: \\e51a;\n$fa-var-r: \\52;\n$fa-var-temperature-quarter: \\f2ca;\n$fa-var-temperature-1: \\f2ca;\n$fa-var-thermometer-1: \\f2ca;\n$fa-var-thermometer-quarter: \\f2ca;\n$fa-var-cube: \\f1b2;\n$fa-var-bitcoin-sign: \\e0b4;\n$fa-var-shield-dog: \\e573;\n$fa-var-solar-panel: \\f5ba;\n$fa-var-lock-open: \\f3c1;\n$fa-var-elevator: \\e16d;\n$fa-var-money-bill-transfer: \\e528;\n$fa-var-money-bill-trend-up: \\e529;\n$fa-var-house-flood-water-circle-arrow-right: \\e50f;\n$fa-var-square-poll-horizontal: \\f682;\n$fa-var-poll-h: \\f682;\n$fa-var-circle: \\f111;\n$fa-var-backward-fast: \\f049;\n$fa-var-fast-backward: \\f049;\n$fa-var-recycle: \\f1b8;\n$fa-var-user-astronaut: \\f4fb;\n$fa-var-plane-slash: \\e069;\n$fa-var-trademark: \\f25c;\n$fa-var-basketball: \\f434;\n$fa-var-basketball-ball: \\f434;\n$fa-var-satellite-dish: \\f7c0;\n$fa-var-circle-up: \\f35b;\n$fa-var-arrow-alt-circle-up: \\f35b;\n$fa-var-mobile-screen-button: \\f3cd;\n$fa-var-mobile-alt: \\f3cd;\n$fa-var-volume-high: \\f028;\n$fa-var-volume-up: \\f028;\n$fa-var-users-rays: \\e593;\n$fa-var-wallet: \\f555;\n$fa-var-clipboard-check: \\f46c;\n$fa-var-file-audio: \\f1c7;\n$fa-var-burger: \\f805;\n$fa-var-hamburger: \\f805;\n$fa-var-wrench: \\f0ad;\n$fa-var-bugs: \\e4d0;\n$fa-var-rupee-sign: \\f156;\n$fa-var-rupee: \\f156;\n$fa-var-file-image: \\f1c5;\n$fa-var-circle-question: \\f059;\n$fa-var-question-circle: \\f059;\n$fa-var-plane-departure: \\f5b0;\n$fa-var-handshake-slash: \\e060;\n$fa-var-book-bookmark: \\e0bb;\n$fa-var-code-branch: \\f126;\n$fa-var-hat-cowboy: \\f8c0;\n$fa-var-bridge: \\e4c8;\n$fa-var-phone-flip: \\f879;\n$fa-var-phone-alt: \\f879;\n$fa-var-truck-front: \\e2b7;\n$fa-var-cat: \\f6be;\n$fa-var-anchor-circle-exclamation: \\e4ab;\n$fa-var-truck-field: \\e58d;\n$fa-var-route: \\f4d7;\n$fa-var-clipboard-question: \\e4e3;\n$fa-var-panorama: \\e209;\n$fa-var-comment-medical: \\f7f5;\n$fa-var-teeth-open: \\f62f;\n$fa-var-file-circle-minus: \\e4ed;\n$fa-var-tags: \\f02c;\n$fa-var-wine-glass: \\f4e3;\n$fa-var-forward-fast: \\f050;\n$fa-var-fast-forward: \\f050;\n$fa-var-face-meh-blank: \\f5a4;\n$fa-var-meh-blank: \\f5a4;\n$fa-var-square-parking: \\f540;\n$fa-var-parking: \\f540;\n$fa-var-house-signal: \\e012;\n$fa-var-bars-progress: \\f828;\n$fa-var-tasks-alt: \\f828;\n$fa-var-faucet-drip: \\e006;\n$fa-var-cart-flatbed: \\f474;\n$fa-var-dolly-flatbed: \\f474;\n$fa-var-ban-smoking: \\f54d;\n$fa-var-smoking-ban: \\f54d;\n$fa-var-terminal: \\f120;\n$fa-var-mobile-button: \\f10b;\n$fa-var-house-medical-flag: \\e514;\n$fa-var-basket-shopping: \\f291;\n$fa-var-shopping-basket: \\f291;\n$fa-var-tape: \\f4db;\n$fa-var-bus-simple: \\f55e;\n$fa-var-bus-alt: \\f55e;\n$fa-var-eye: \\f06e;\n$fa-var-face-sad-cry: \\f5b3;\n$fa-var-sad-cry: \\f5b3;\n$fa-var-audio-description: \\f29e;\n$fa-var-person-military-to-person: \\e54c;\n$fa-var-file-shield: \\e4f0;\n$fa-var-user-slash: \\f506;\n$fa-var-pen: \\f304;\n$fa-var-tower-observation: \\e586;\n$fa-var-file-code: \\f1c9;\n$fa-var-signal: \\f012;\n$fa-var-signal-5: \\f012;\n$fa-var-signal-perfect: \\f012;\n$fa-var-bus: \\f207;\n$fa-var-heart-circle-xmark: \\e501;\n$fa-var-house-chimney: \\e3af;\n$fa-var-home-lg: \\e3af;\n$fa-var-window-maximize: \\f2d0;\n$fa-var-face-frown: \\f119;\n$fa-var-frown: \\f119;\n$fa-var-prescription: \\f5b1;\n$fa-var-shop: \\f54f;\n$fa-var-store-alt: \\f54f;\n$fa-var-floppy-disk: \\f0c7;\n$fa-var-save: \\f0c7;\n$fa-var-vihara: \\f6a7;\n$fa-var-scale-unbalanced: \\f515;\n$fa-var-balance-scale-left: \\f515;\n$fa-var-sort-up: \\f0de;\n$fa-var-sort-asc: \\f0de;\n$fa-var-comment-dots: \\f4ad;\n$fa-var-commenting: \\f4ad;\n$fa-var-plant-wilt: \\e5aa;\n$fa-var-diamond: \\f219;\n$fa-var-face-grin-squint: \\f585;\n$fa-var-grin-squint: \\f585;\n$fa-var-hand-holding-dollar: \\f4c0;\n$fa-var-hand-holding-usd: \\f4c0;\n$fa-var-bacterium: \\e05a;\n$fa-var-hand-pointer: \\f25a;\n$fa-var-drum-steelpan: \\f56a;\n$fa-var-hand-scissors: \\f257;\n$fa-var-hands-praying: \\f684;\n$fa-var-praying-hands: \\f684;\n$fa-var-arrow-rotate-right: \\f01e;\n$fa-var-arrow-right-rotate: \\f01e;\n$fa-var-arrow-rotate-forward: \\f01e;\n$fa-var-redo: \\f01e;\n$fa-var-biohazard: \\f780;\n$fa-var-location-crosshairs: \\f601;\n$fa-var-location: \\f601;\n$fa-var-mars-double: \\f227;\n$fa-var-child-dress: \\e59c;\n$fa-var-users-between-lines: \\e591;\n$fa-var-lungs-virus: \\e067;\n$fa-var-face-grin-tears: \\f588;\n$fa-var-grin-tears: \\f588;\n$fa-var-phone: \\f095;\n$fa-var-calendar-xmark: \\f273;\n$fa-var-calendar-times: \\f273;\n$fa-var-child-reaching: \\e59d;\n$fa-var-head-side-virus: \\e064;\n$fa-var-user-gear: \\f4fe;\n$fa-var-user-cog: \\f4fe;\n$fa-var-arrow-up-1-9: \\f163;\n$fa-var-sort-numeric-up: \\f163;\n$fa-var-door-closed: \\f52a;\n$fa-var-shield-virus: \\e06c;\n$fa-var-dice-six: \\f526;\n$fa-var-mosquito-net: \\e52c;\n$fa-var-bridge-water: \\e4ce;\n$fa-var-person-booth: \\f756;\n$fa-var-text-width: \\f035;\n$fa-var-hat-wizard: \\f6e8;\n$fa-var-pen-fancy: \\f5ac;\n$fa-var-person-digging: \\f85e;\n$fa-var-digging: \\f85e;\n$fa-var-trash: \\f1f8;\n$fa-var-gauge-simple: \\f629;\n$fa-var-gauge-simple-med: \\f629;\n$fa-var-tachometer-average: \\f629;\n$fa-var-book-medical: \\f7e6;\n$fa-var-poo: \\f2fe;\n$fa-var-quote-right: \\f10e;\n$fa-var-quote-right-alt: \\f10e;\n$fa-var-shirt: \\f553;\n$fa-var-t-shirt: \\f553;\n$fa-var-tshirt: \\f553;\n$fa-var-cubes: \\f1b3;\n$fa-var-divide: \\f529;\n$fa-var-tenge-sign: \\f7d7;\n$fa-var-tenge: \\f7d7;\n$fa-var-headphones: \\f025;\n$fa-var-hands-holding: \\f4c2;\n$fa-var-hands-clapping: \\e1a8;\n$fa-var-republican: \\f75e;\n$fa-var-arrow-left: \\f060;\n$fa-var-person-circle-xmark: \\e543;\n$fa-var-ruler: \\f545;\n$fa-var-align-left: \\f036;\n$fa-var-dice-d6: \\f6d1;\n$fa-var-restroom: \\f7bd;\n$fa-var-j: \\4a;\n$fa-var-users-viewfinder: \\e595;\n$fa-var-file-video: \\f1c8;\n$fa-var-up-right-from-square: \\f35d;\n$fa-var-external-link-alt: \\f35d;\n$fa-var-table-cells: \\f00a;\n$fa-var-th: \\f00a;\n$fa-var-file-pdf: \\f1c1;\n$fa-var-book-bible: \\f647;\n$fa-var-bible: \\f647;\n$fa-var-o: \\4f;\n$fa-var-suitcase-medical: \\f0fa;\n$fa-var-medkit: \\f0fa;\n$fa-var-user-secret: \\f21b;\n$fa-var-otter: \\f700;\n$fa-var-person-dress: \\f182;\n$fa-var-female: \\f182;\n$fa-var-comment-dollar: \\f651;\n$fa-var-business-time: \\f64a;\n$fa-var-briefcase-clock: \\f64a;\n$fa-var-table-cells-large: \\f009;\n$fa-var-th-large: \\f009;\n$fa-var-book-tanakh: \\f827;\n$fa-var-tanakh: \\f827;\n$fa-var-phone-volume: \\f2a0;\n$fa-var-volume-control-phone: \\f2a0;\n$fa-var-hat-cowboy-side: \\f8c1;\n$fa-var-clipboard-user: \\f7f3;\n$fa-var-child: \\f1ae;\n$fa-var-lira-sign: \\f195;\n$fa-var-satellite: \\f7bf;\n$fa-var-plane-lock: \\e558;\n$fa-var-tag: \\f02b;\n$fa-var-comment: \\f075;\n$fa-var-cake-candles: \\f1fd;\n$fa-var-birthday-cake: \\f1fd;\n$fa-var-cake: \\f1fd;\n$fa-var-envelope: \\f0e0;\n$fa-var-angles-up: \\f102;\n$fa-var-angle-double-up: \\f102;\n$fa-var-paperclip: \\f0c6;\n$fa-var-arrow-right-to-city: \\e4b3;\n$fa-var-ribbon: \\f4d6;\n$fa-var-lungs: \\f604;\n$fa-var-arrow-up-9-1: \\f887;\n$fa-var-sort-numeric-up-alt: \\f887;\n$fa-var-litecoin-sign: \\e1d3;\n$fa-var-border-none: \\f850;\n$fa-var-circle-nodes: \\e4e2;\n$fa-var-parachute-box: \\f4cd;\n$fa-var-indent: \\f03c;\n$fa-var-truck-field-un: \\e58e;\n$fa-var-hourglass: \\f254;\n$fa-var-hourglass-empty: \\f254;\n$fa-var-mountain: \\f6fc;\n$fa-var-user-doctor: \\f0f0;\n$fa-var-user-md: \\f0f0;\n$fa-var-circle-info: \\f05a;\n$fa-var-info-circle: \\f05a;\n$fa-var-cloud-meatball: \\f73b;\n$fa-var-camera: \\f030;\n$fa-var-camera-alt: \\f030;\n$fa-var-square-virus: \\e578;\n$fa-var-meteor: \\f753;\n$fa-var-car-on: \\e4dd;\n$fa-var-sleigh: \\f7cc;\n$fa-var-arrow-down-1-9: \\f162;\n$fa-var-sort-numeric-asc: \\f162;\n$fa-var-sort-numeric-down: \\f162;\n$fa-var-hand-holding-droplet: \\f4c1;\n$fa-var-hand-holding-water: \\f4c1;\n$fa-var-water: \\f773;\n$fa-var-calendar-check: \\f274;\n$fa-var-braille: \\f2a1;\n$fa-var-prescription-bottle-medical: \\f486;\n$fa-var-prescription-bottle-alt: \\f486;\n$fa-var-landmark: \\f66f;\n$fa-var-truck: \\f0d1;\n$fa-var-crosshairs: \\f05b;\n$fa-var-person-cane: \\e53c;\n$fa-var-tent: \\e57d;\n$fa-var-vest-patches: \\e086;\n$fa-var-check-double: \\f560;\n$fa-var-arrow-down-a-z: \\f15d;\n$fa-var-sort-alpha-asc: \\f15d;\n$fa-var-sort-alpha-down: \\f15d;\n$fa-var-money-bill-wheat: \\e52a;\n$fa-var-cookie: \\f563;\n$fa-var-arrow-rotate-left: \\f0e2;\n$fa-var-arrow-left-rotate: \\f0e2;\n$fa-var-arrow-rotate-back: \\f0e2;\n$fa-var-arrow-rotate-backward: \\f0e2;\n$fa-var-undo: \\f0e2;\n$fa-var-hard-drive: \\f0a0;\n$fa-var-hdd: \\f0a0;\n$fa-var-face-grin-squint-tears: \\f586;\n$fa-var-grin-squint-tears: \\f586;\n$fa-var-dumbbell: \\f44b;\n$fa-var-rectangle-list: \\f022;\n$fa-var-list-alt: \\f022;\n$fa-var-tarp-droplet: \\e57c;\n$fa-var-house-medical-circle-check: \\e511;\n$fa-var-person-skiing-nordic: \\f7ca;\n$fa-var-skiing-nordic: \\f7ca;\n$fa-var-calendar-plus: \\f271;\n$fa-var-plane-arrival: \\f5af;\n$fa-var-circle-left: \\f359;\n$fa-var-arrow-alt-circle-left: \\f359;\n$fa-var-train-subway: \\f239;\n$fa-var-subway: \\f239;\n$fa-var-chart-gantt: \\e0e4;\n$fa-var-indian-rupee-sign: \\e1bc;\n$fa-var-indian-rupee: \\e1bc;\n$fa-var-inr: \\e1bc;\n$fa-var-crop-simple: \\f565;\n$fa-var-crop-alt: \\f565;\n$fa-var-money-bill-1: \\f3d1;\n$fa-var-money-bill-alt: \\f3d1;\n$fa-var-left-long: \\f30a;\n$fa-var-long-arrow-alt-left: \\f30a;\n$fa-var-dna: \\f471;\n$fa-var-virus-slash: \\e075;\n$fa-var-minus: \\f068;\n$fa-var-subtract: \\f068;\n$fa-var-chess: \\f439;\n$fa-var-arrow-left-long: \\f177;\n$fa-var-long-arrow-left: \\f177;\n$fa-var-plug-circle-check: \\e55c;\n$fa-var-street-view: \\f21d;\n$fa-var-franc-sign: \\e18f;\n$fa-var-volume-off: \\f026;\n$fa-var-hands-asl-interpreting: \\f2a3;\n$fa-var-american-sign-language-interpreting: \\f2a3;\n$fa-var-asl-interpreting: \\f2a3;\n$fa-var-hands-american-sign-language-interpreting: \\f2a3;\n$fa-var-gear: \\f013;\n$fa-var-cog: \\f013;\n$fa-var-droplet-slash: \\f5c7;\n$fa-var-tint-slash: \\f5c7;\n$fa-var-mosque: \\f678;\n$fa-var-mosquito: \\e52b;\n$fa-var-star-of-david: \\f69a;\n$fa-var-person-military-rifle: \\e54b;\n$fa-var-cart-shopping: \\f07a;\n$fa-var-shopping-cart: \\f07a;\n$fa-var-vials: \\f493;\n$fa-var-plug-circle-plus: \\e55f;\n$fa-var-place-of-worship: \\f67f;\n$fa-var-grip-vertical: \\f58e;\n$fa-var-arrow-turn-up: \\f148;\n$fa-var-level-up: \\f148;\n$fa-var-u: \\55;\n$fa-var-square-root-variable: \\f698;\n$fa-var-square-root-alt: \\f698;\n$fa-var-clock: \\f017;\n$fa-var-clock-four: \\f017;\n$fa-var-backward-step: \\f048;\n$fa-var-step-backward: \\f048;\n$fa-var-pallet: \\f482;\n$fa-var-faucet: \\e005;\n$fa-var-baseball-bat-ball: \\f432;\n$fa-var-s: \\53;\n$fa-var-timeline: \\e29c;\n$fa-var-keyboard: \\f11c;\n$fa-var-caret-down: \\f0d7;\n$fa-var-house-chimney-medical: \\f7f2;\n$fa-var-clinic-medical: \\f7f2;\n$fa-var-temperature-three-quarters: \\f2c8;\n$fa-var-temperature-3: \\f2c8;\n$fa-var-thermometer-3: \\f2c8;\n$fa-var-thermometer-three-quarters: \\f2c8;\n$fa-var-mobile-screen: \\f3cf;\n$fa-var-mobile-android-alt: \\f3cf;\n$fa-var-plane-up: \\e22d;\n$fa-var-piggy-bank: \\f4d3;\n$fa-var-battery-half: \\f242;\n$fa-var-battery-3: \\f242;\n$fa-var-mountain-city: \\e52e;\n$fa-var-coins: \\f51e;\n$fa-var-khanda: \\f66d;\n$fa-var-sliders: \\f1de;\n$fa-var-sliders-h: \\f1de;\n$fa-var-folder-tree: \\f802;\n$fa-var-network-wired: \\f6ff;\n$fa-var-map-pin: \\f276;\n$fa-var-hamsa: \\f665;\n$fa-var-cent-sign: \\e3f5;\n$fa-var-flask: \\f0c3;\n$fa-var-person-pregnant: \\e31e;\n$fa-var-wand-sparkles: \\f72b;\n$fa-var-ellipsis-vertical: \\f142;\n$fa-var-ellipsis-v: \\f142;\n$fa-var-ticket: \\f145;\n$fa-var-power-off: \\f011;\n$fa-var-right-long: \\f30b;\n$fa-var-long-arrow-alt-right: \\f30b;\n$fa-var-flag-usa: \\f74d;\n$fa-var-laptop-file: \\e51d;\n$fa-var-tty: \\f1e4;\n$fa-var-teletype: \\f1e4;\n$fa-var-diagram-next: \\e476;\n$fa-var-person-rifle: \\e54e;\n$fa-var-house-medical-circle-exclamation: \\e512;\n$fa-var-closed-captioning: \\f20a;\n$fa-var-person-hiking: \\f6ec;\n$fa-var-hiking: \\f6ec;\n$fa-var-venus-double: \\f226;\n$fa-var-images: \\f302;\n$fa-var-calculator: \\f1ec;\n$fa-var-people-pulling: \\e535;\n$fa-var-n: \\4e;\n$fa-var-cable-car: \\f7da;\n$fa-var-tram: \\f7da;\n$fa-var-cloud-rain: \\f73d;\n$fa-var-building-circle-xmark: \\e4d4;\n$fa-var-ship: \\f21a;\n$fa-var-arrows-down-to-line: \\e4b8;\n$fa-var-download: \\f019;\n$fa-var-face-grin: \\f580;\n$fa-var-grin: \\f580;\n$fa-var-delete-left: \\f55a;\n$fa-var-backspace: \\f55a;\n$fa-var-eye-dropper: \\f1fb;\n$fa-var-eye-dropper-empty: \\f1fb;\n$fa-var-eyedropper: \\f1fb;\n$fa-var-file-circle-check: \\e5a0;\n$fa-var-forward: \\f04e;\n$fa-var-mobile: \\f3ce;\n$fa-var-mobile-android: \\f3ce;\n$fa-var-mobile-phone: \\f3ce;\n$fa-var-face-meh: \\f11a;\n$fa-var-meh: \\f11a;\n$fa-var-align-center: \\f037;\n$fa-var-book-skull: \\f6b7;\n$fa-var-book-dead: \\f6b7;\n$fa-var-id-card: \\f2c2;\n$fa-var-drivers-license: \\f2c2;\n$fa-var-outdent: \\f03b;\n$fa-var-dedent: \\f03b;\n$fa-var-heart-circle-exclamation: \\e4fe;\n$fa-var-house: \\f015;\n$fa-var-home: \\f015;\n$fa-var-home-alt: \\f015;\n$fa-var-home-lg-alt: \\f015;\n$fa-var-calendar-week: \\f784;\n$fa-var-laptop-medical: \\f812;\n$fa-var-b: \\42;\n$fa-var-file-medical: \\f477;\n$fa-var-dice-one: \\f525;\n$fa-var-kiwi-bird: \\f535;\n$fa-var-arrow-right-arrow-left: \\f0ec;\n$fa-var-exchange: \\f0ec;\n$fa-var-rotate-right: \\f2f9;\n$fa-var-redo-alt: \\f2f9;\n$fa-var-rotate-forward: \\f2f9;\n$fa-var-utensils: \\f2e7;\n$fa-var-cutlery: \\f2e7;\n$fa-var-arrow-up-wide-short: \\f161;\n$fa-var-sort-amount-up: \\f161;\n$fa-var-mill-sign: \\e1ed;\n$fa-var-bowl-rice: \\e2eb;\n$fa-var-skull: \\f54c;\n$fa-var-tower-broadcast: \\f519;\n$fa-var-broadcast-tower: \\f519;\n$fa-var-truck-pickup: \\f63c;\n$fa-var-up-long: \\f30c;\n$fa-var-long-arrow-alt-up: \\f30c;\n$fa-var-stop: \\f04d;\n$fa-var-code-merge: \\f387;\n$fa-var-upload: \\f093;\n$fa-var-hurricane: \\f751;\n$fa-var-mound: \\e52d;\n$fa-var-toilet-portable: \\e583;\n$fa-var-compact-disc: \\f51f;\n$fa-var-file-arrow-down: \\f56d;\n$fa-var-file-download: \\f56d;\n$fa-var-caravan: \\f8ff;\n$fa-var-shield-cat: \\e572;\n$fa-var-bolt: \\f0e7;\n$fa-var-zap: \\f0e7;\n$fa-var-glass-water: \\e4f4;\n$fa-var-oil-well: \\e532;\n$fa-var-vault: \\e2c5;\n$fa-var-mars: \\f222;\n$fa-var-toilet: \\f7d8;\n$fa-var-plane-circle-xmark: \\e557;\n$fa-var-yen-sign: \\f157;\n$fa-var-cny: \\f157;\n$fa-var-jpy: \\f157;\n$fa-var-rmb: \\f157;\n$fa-var-yen: \\f157;\n$fa-var-ruble-sign: \\f158;\n$fa-var-rouble: \\f158;\n$fa-var-rub: \\f158;\n$fa-var-ruble: \\f158;\n$fa-var-sun: \\f185;\n$fa-var-guitar: \\f7a6;\n$fa-var-face-laugh-wink: \\f59c;\n$fa-var-laugh-wink: \\f59c;\n$fa-var-horse-head: \\f7ab;\n$fa-var-bore-hole: \\e4c3;\n$fa-var-industry: \\f275;\n$fa-var-circle-down: \\f358;\n$fa-var-arrow-alt-circle-down: \\f358;\n$fa-var-arrows-turn-to-dots: \\e4c1;\n$fa-var-florin-sign: \\e184;\n$fa-var-arrow-down-short-wide: \\f884;\n$fa-var-sort-amount-desc: \\f884;\n$fa-var-sort-amount-down-alt: \\f884;\n$fa-var-less-than: \\3c;\n$fa-var-angle-down: \\f107;\n$fa-var-car-tunnel: \\e4de;\n$fa-var-head-side-cough: \\e061;\n$fa-var-grip-lines: \\f7a4;\n$fa-var-thumbs-down: \\f165;\n$fa-var-user-lock: \\f502;\n$fa-var-arrow-right-long: \\f178;\n$fa-var-long-arrow-right: \\f178;\n$fa-var-anchor-circle-xmark: \\e4ac;\n$fa-var-ellipsis: \\f141;\n$fa-var-ellipsis-h: \\f141;\n$fa-var-chess-pawn: \\f443;\n$fa-var-kit-medical: \\f479;\n$fa-var-first-aid: \\f479;\n$fa-var-person-through-window: \\e5a9;\n$fa-var-toolbox: \\f552;\n$fa-var-hands-holding-circle: \\e4fb;\n$fa-var-bug: \\f188;\n$fa-var-credit-card: \\f09d;\n$fa-var-credit-card-alt: \\f09d;\n$fa-var-car: \\f1b9;\n$fa-var-automobile: \\f1b9;\n$fa-var-hand-holding-hand: \\e4f7;\n$fa-var-book-open-reader: \\f5da;\n$fa-var-book-reader: \\f5da;\n$fa-var-mountain-sun: \\e52f;\n$fa-var-arrows-left-right-to-line: \\e4ba;\n$fa-var-dice-d20: \\f6cf;\n$fa-var-truck-droplet: \\e58c;\n$fa-var-file-circle-xmark: \\e5a1;\n$fa-var-temperature-arrow-up: \\e040;\n$fa-var-temperature-up: \\e040;\n$fa-var-medal: \\f5a2;\n$fa-var-bed: \\f236;\n$fa-var-square-h: \\f0fd;\n$fa-var-h-square: \\f0fd;\n$fa-var-podcast: \\f2ce;\n$fa-var-temperature-full: \\f2c7;\n$fa-var-temperature-4: \\f2c7;\n$fa-var-thermometer-4: \\f2c7;\n$fa-var-thermometer-full: \\f2c7;\n$fa-var-bell: \\f0f3;\n$fa-var-superscript: \\f12b;\n$fa-var-plug-circle-xmark: \\e560;\n$fa-var-star-of-life: \\f621;\n$fa-var-phone-slash: \\f3dd;\n$fa-var-paint-roller: \\f5aa;\n$fa-var-handshake-angle: \\f4c4;\n$fa-var-hands-helping: \\f4c4;\n$fa-var-location-dot: \\f3c5;\n$fa-var-map-marker-alt: \\f3c5;\n$fa-var-file: \\f15b;\n$fa-var-greater-than: \\3e;\n$fa-var-person-swimming: \\f5c4;\n$fa-var-swimmer: \\f5c4;\n$fa-var-arrow-down: \\f063;\n$fa-var-droplet: \\f043;\n$fa-var-tint: \\f043;\n$fa-var-eraser: \\f12d;\n$fa-var-earth-americas: \\f57d;\n$fa-var-earth: \\f57d;\n$fa-var-earth-america: \\f57d;\n$fa-var-globe-americas: \\f57d;\n$fa-var-person-burst: \\e53b;\n$fa-var-dove: \\f4ba;\n$fa-var-battery-empty: \\f244;\n$fa-var-battery-0: \\f244;\n$fa-var-socks: \\f696;\n$fa-var-inbox: \\f01c;\n$fa-var-section: \\e447;\n$fa-var-gauge-high: \\f625;\n$fa-var-tachometer-alt: \\f625;\n$fa-var-tachometer-alt-fast: \\f625;\n$fa-var-envelope-open-text: \\f658;\n$fa-var-hospital: \\f0f8;\n$fa-var-hospital-alt: \\f0f8;\n$fa-var-hospital-wide: \\f0f8;\n$fa-var-wine-bottle: \\f72f;\n$fa-var-chess-rook: \\f447;\n$fa-var-bars-staggered: \\f550;\n$fa-var-reorder: \\f550;\n$fa-var-stream: \\f550;\n$fa-var-dharmachakra: \\f655;\n$fa-var-hotdog: \\f80f;\n$fa-var-person-walking-with-cane: \\f29d;\n$fa-var-blind: \\f29d;\n$fa-var-drum: \\f569;\n$fa-var-ice-cream: \\f810;\n$fa-var-heart-circle-bolt: \\e4fc;\n$fa-var-fax: \\f1ac;\n$fa-var-paragraph: \\f1dd;\n$fa-var-check-to-slot: \\f772;\n$fa-var-vote-yea: \\f772;\n$fa-var-star-half: \\f089;\n$fa-var-boxes-stacked: \\f468;\n$fa-var-boxes: \\f468;\n$fa-var-boxes-alt: \\f468;\n$fa-var-link: \\f0c1;\n$fa-var-chain: \\f0c1;\n$fa-var-ear-listen: \\f2a2;\n$fa-var-assistive-listening-systems: \\f2a2;\n$fa-var-tree-city: \\e587;\n$fa-var-play: \\f04b;\n$fa-var-font: \\f031;\n$fa-var-table-cells-row-lock: \\e67a;\n$fa-var-rupiah-sign: \\e23d;\n$fa-var-magnifying-glass: \\f002;\n$fa-var-search: \\f002;\n$fa-var-table-tennis-paddle-ball: \\f45d;\n$fa-var-ping-pong-paddle-ball: \\f45d;\n$fa-var-table-tennis: \\f45d;\n$fa-var-person-dots-from-line: \\f470;\n$fa-var-diagnoses: \\f470;\n$fa-var-trash-can-arrow-up: \\f82a;\n$fa-var-trash-restore-alt: \\f82a;\n$fa-var-naira-sign: \\e1f6;\n$fa-var-cart-arrow-down: \\f218;\n$fa-var-walkie-talkie: \\f8ef;\n$fa-var-file-pen: \\f31c;\n$fa-var-file-edit: \\f31c;\n$fa-var-receipt: \\f543;\n$fa-var-square-pen: \\f14b;\n$fa-var-pen-square: \\f14b;\n$fa-var-pencil-square: \\f14b;\n$fa-var-suitcase-rolling: \\f5c1;\n$fa-var-person-circle-exclamation: \\e53f;\n$fa-var-chevron-down: \\f078;\n$fa-var-battery-full: \\f240;\n$fa-var-battery: \\f240;\n$fa-var-battery-5: \\f240;\n$fa-var-skull-crossbones: \\f714;\n$fa-var-code-compare: \\e13a;\n$fa-var-list-ul: \\f0ca;\n$fa-var-list-dots: \\f0ca;\n$fa-var-school-lock: \\e56f;\n$fa-var-tower-cell: \\e585;\n$fa-var-down-long: \\f309;\n$fa-var-long-arrow-alt-down: \\f309;\n$fa-var-ranking-star: \\e561;\n$fa-var-chess-king: \\f43f;\n$fa-var-person-harassing: \\e549;\n$fa-var-brazilian-real-sign: \\e46c;\n$fa-var-landmark-dome: \\f752;\n$fa-var-landmark-alt: \\f752;\n$fa-var-arrow-up: \\f062;\n$fa-var-tv: \\f26c;\n$fa-var-television: \\f26c;\n$fa-var-tv-alt: \\f26c;\n$fa-var-shrimp: \\e448;\n$fa-var-list-check: \\f0ae;\n$fa-var-tasks: \\f0ae;\n$fa-var-jug-detergent: \\e519;\n$fa-var-circle-user: \\f2bd;\n$fa-var-user-circle: \\f2bd;\n$fa-var-user-shield: \\f505;\n$fa-var-wind: \\f72e;\n$fa-var-car-burst: \\f5e1;\n$fa-var-car-crash: \\f5e1;\n$fa-var-y: \\59;\n$fa-var-person-snowboarding: \\f7ce;\n$fa-var-snowboarding: \\f7ce;\n$fa-var-truck-fast: \\f48b;\n$fa-var-shipping-fast: \\f48b;\n$fa-var-fish: \\f578;\n$fa-var-user-graduate: \\f501;\n$fa-var-circle-half-stroke: \\f042;\n$fa-var-adjust: \\f042;\n$fa-var-clapperboard: \\e131;\n$fa-var-circle-radiation: \\f7ba;\n$fa-var-radiation-alt: \\f7ba;\n$fa-var-baseball: \\f433;\n$fa-var-baseball-ball: \\f433;\n$fa-var-jet-fighter-up: \\e518;\n$fa-var-diagram-project: \\f542;\n$fa-var-project-diagram: \\f542;\n$fa-var-copy: \\f0c5;\n$fa-var-volume-xmark: \\f6a9;\n$fa-var-volume-mute: \\f6a9;\n$fa-var-volume-times: \\f6a9;\n$fa-var-hand-sparkles: \\e05d;\n$fa-var-grip: \\f58d;\n$fa-var-grip-horizontal: \\f58d;\n$fa-var-share-from-square: \\f14d;\n$fa-var-share-square: \\f14d;\n$fa-var-child-combatant: \\e4e0;\n$fa-var-child-rifle: \\e4e0;\n$fa-var-gun: \\e19b;\n$fa-var-square-phone: \\f098;\n$fa-var-phone-square: \\f098;\n$fa-var-plus: \\2b;\n$fa-var-add: \\2b;\n$fa-var-expand: \\f065;\n$fa-var-computer: \\e4e5;\n$fa-var-xmark: \\f00d;\n$fa-var-close: \\f00d;\n$fa-var-multiply: \\f00d;\n$fa-var-remove: \\f00d;\n$fa-var-times: \\f00d;\n$fa-var-arrows-up-down-left-right: \\f047;\n$fa-var-arrows: \\f047;\n$fa-var-chalkboard-user: \\f51c;\n$fa-var-chalkboard-teacher: \\f51c;\n$fa-var-peso-sign: \\e222;\n$fa-var-building-shield: \\e4d8;\n$fa-var-baby: \\f77c;\n$fa-var-users-line: \\e592;\n$fa-var-quote-left: \\f10d;\n$fa-var-quote-left-alt: \\f10d;\n$fa-var-tractor: \\f722;\n$fa-var-trash-arrow-up: \\f829;\n$fa-var-trash-restore: \\f829;\n$fa-var-arrow-down-up-lock: \\e4b0;\n$fa-var-lines-leaning: \\e51e;\n$fa-var-ruler-combined: \\f546;\n$fa-var-copyright: \\f1f9;\n$fa-var-equals: \\3d;\n$fa-var-blender: \\f517;\n$fa-var-teeth: \\f62e;\n$fa-var-shekel-sign: \\f20b;\n$fa-var-ils: \\f20b;\n$fa-var-shekel: \\f20b;\n$fa-var-sheqel: \\f20b;\n$fa-var-sheqel-sign: \\f20b;\n$fa-var-map: \\f279;\n$fa-var-rocket: \\f135;\n$fa-var-photo-film: \\f87c;\n$fa-var-photo-video: \\f87c;\n$fa-var-folder-minus: \\f65d;\n$fa-var-store: \\f54e;\n$fa-var-arrow-trend-up: \\e098;\n$fa-var-plug-circle-minus: \\e55e;\n$fa-var-sign-hanging: \\f4d9;\n$fa-var-sign: \\f4d9;\n$fa-var-bezier-curve: \\f55b;\n$fa-var-bell-slash: \\f1f6;\n$fa-var-tablet: \\f3fb;\n$fa-var-tablet-android: \\f3fb;\n$fa-var-school-flag: \\e56e;\n$fa-var-fill: \\f575;\n$fa-var-angle-up: \\f106;\n$fa-var-drumstick-bite: \\f6d7;\n$fa-var-holly-berry: \\f7aa;\n$fa-var-chevron-left: \\f053;\n$fa-var-bacteria: \\e059;\n$fa-var-hand-lizard: \\f258;\n$fa-var-notdef: \\e1fe;\n$fa-var-disease: \\f7fa;\n$fa-var-briefcase-medical: \\f469;\n$fa-var-genderless: \\f22d;\n$fa-var-chevron-right: \\f054;\n$fa-var-retweet: \\f079;\n$fa-var-car-rear: \\f5de;\n$fa-var-car-alt: \\f5de;\n$fa-var-pump-soap: \\e06b;\n$fa-var-video-slash: \\f4e2;\n$fa-var-battery-quarter: \\f243;\n$fa-var-battery-2: \\f243;\n$fa-var-radio: \\f8d7;\n$fa-var-baby-carriage: \\f77d;\n$fa-var-carriage-baby: \\f77d;\n$fa-var-traffic-light: \\f637;\n$fa-var-thermometer: \\f491;\n$fa-var-vr-cardboard: \\f729;\n$fa-var-hand-middle-finger: \\f806;\n$fa-var-percent: \\25;\n$fa-var-percentage: \\25;\n$fa-var-truck-moving: \\f4df;\n$fa-var-glass-water-droplet: \\e4f5;\n$fa-var-display: \\e163;\n$fa-var-face-smile: \\f118;\n$fa-var-smile: \\f118;\n$fa-var-thumbtack: \\f08d;\n$fa-var-thumb-tack: \\f08d;\n$fa-var-trophy: \\f091;\n$fa-var-person-praying: \\f683;\n$fa-var-pray: \\f683;\n$fa-var-hammer: \\f6e3;\n$fa-var-hand-peace: \\f25b;\n$fa-var-rotate: \\f2f1;\n$fa-var-sync-alt: \\f2f1;\n$fa-var-spinner: \\f110;\n$fa-var-robot: \\f544;\n$fa-var-peace: \\f67c;\n$fa-var-gears: \\f085;\n$fa-var-cogs: \\f085;\n$fa-var-warehouse: \\f494;\n$fa-var-arrow-up-right-dots: \\e4b7;\n$fa-var-splotch: \\f5bc;\n$fa-var-face-grin-hearts: \\f584;\n$fa-var-grin-hearts: \\f584;\n$fa-var-dice-four: \\f524;\n$fa-var-sim-card: \\f7c4;\n$fa-var-transgender: \\f225;\n$fa-var-transgender-alt: \\f225;\n$fa-var-mercury: \\f223;\n$fa-var-arrow-turn-down: \\f149;\n$fa-var-level-down: \\f149;\n$fa-var-person-falling-burst: \\e547;\n$fa-var-award: \\f559;\n$fa-var-ticket-simple: \\f3ff;\n$fa-var-ticket-alt: \\f3ff;\n$fa-var-building: \\f1ad;\n$fa-var-angles-left: \\f100;\n$fa-var-angle-double-left: \\f100;\n$fa-var-qrcode: \\f029;\n$fa-var-clock-rotate-left: \\f1da;\n$fa-var-history: \\f1da;\n$fa-var-face-grin-beam-sweat: \\f583;\n$fa-var-grin-beam-sweat: \\f583;\n$fa-var-file-export: \\f56e;\n$fa-var-arrow-right-from-file: \\f56e;\n$fa-var-shield: \\f132;\n$fa-var-shield-blank: \\f132;\n$fa-var-arrow-up-short-wide: \\f885;\n$fa-var-sort-amount-up-alt: \\f885;\n$fa-var-house-medical: \\e3b2;\n$fa-var-golf-ball-tee: \\f450;\n$fa-var-golf-ball: \\f450;\n$fa-var-circle-chevron-left: \\f137;\n$fa-var-chevron-circle-left: \\f137;\n$fa-var-house-chimney-window: \\e00d;\n$fa-var-pen-nib: \\f5ad;\n$fa-var-tent-arrow-turn-left: \\e580;\n$fa-var-tents: \\e582;\n$fa-var-wand-magic: \\f0d0;\n$fa-var-magic: \\f0d0;\n$fa-var-dog: \\f6d3;\n$fa-var-carrot: \\f787;\n$fa-var-moon: \\f186;\n$fa-var-wine-glass-empty: \\f5ce;\n$fa-var-wine-glass-alt: \\f5ce;\n$fa-var-cheese: \\f7ef;\n$fa-var-yin-yang: \\f6ad;\n$fa-var-music: \\f001;\n$fa-var-code-commit: \\f386;\n$fa-var-temperature-low: \\f76b;\n$fa-var-person-biking: \\f84a;\n$fa-var-biking: \\f84a;\n$fa-var-broom: \\f51a;\n$fa-var-shield-heart: \\e574;\n$fa-var-gopuram: \\f664;\n$fa-var-earth-oceania: \\e47b;\n$fa-var-globe-oceania: \\e47b;\n$fa-var-square-xmark: \\f2d3;\n$fa-var-times-square: \\f2d3;\n$fa-var-xmark-square: \\f2d3;\n$fa-var-hashtag: \\23;\n$fa-var-up-right-and-down-left-from-center: \\f424;\n$fa-var-expand-alt: \\f424;\n$fa-var-oil-can: \\f613;\n$fa-var-t: \\54;\n$fa-var-hippo: \\f6ed;\n$fa-var-chart-column: \\e0e3;\n$fa-var-infinity: \\f534;\n$fa-var-vial-circle-check: \\e596;\n$fa-var-person-arrow-down-to-line: \\e538;\n$fa-var-voicemail: \\f897;\n$fa-var-fan: \\f863;\n$fa-var-person-walking-luggage: \\e554;\n$fa-var-up-down: \\f338;\n$fa-var-arrows-alt-v: \\f338;\n$fa-var-cloud-moon-rain: \\f73c;\n$fa-var-calendar: \\f133;\n$fa-var-trailer: \\e041;\n$fa-var-bahai: \\f666;\n$fa-var-haykal: \\f666;\n$fa-var-sd-card: \\f7c2;\n$fa-var-dragon: \\f6d5;\n$fa-var-shoe-prints: \\f54b;\n$fa-var-circle-plus: \\f055;\n$fa-var-plus-circle: \\f055;\n$fa-var-face-grin-tongue-wink: \\f58b;\n$fa-var-grin-tongue-wink: \\f58b;\n$fa-var-hand-holding: \\f4bd;\n$fa-var-plug-circle-exclamation: \\e55d;\n$fa-var-link-slash: \\f127;\n$fa-var-chain-broken: \\f127;\n$fa-var-chain-slash: \\f127;\n$fa-var-unlink: \\f127;\n$fa-var-clone: \\f24d;\n$fa-var-person-walking-arrow-loop-left: \\e551;\n$fa-var-arrow-up-z-a: \\f882;\n$fa-var-sort-alpha-up-alt: \\f882;\n$fa-var-fire-flame-curved: \\f7e4;\n$fa-var-fire-alt: \\f7e4;\n$fa-var-tornado: \\f76f;\n$fa-var-file-circle-plus: \\e494;\n$fa-var-book-quran: \\f687;\n$fa-var-quran: \\f687;\n$fa-var-anchor: \\f13d;\n$fa-var-border-all: \\f84c;\n$fa-var-face-angry: \\f556;\n$fa-var-angry: \\f556;\n$fa-var-cookie-bite: \\f564;\n$fa-var-arrow-trend-down: \\e097;\n$fa-var-rss: \\f09e;\n$fa-var-feed: \\f09e;\n$fa-var-draw-polygon: \\f5ee;\n$fa-var-scale-balanced: \\f24e;\n$fa-var-balance-scale: \\f24e;\n$fa-var-gauge-simple-high: \\f62a;\n$fa-var-tachometer: \\f62a;\n$fa-var-tachometer-fast: \\f62a;\n$fa-var-shower: \\f2cc;\n$fa-var-desktop: \\f390;\n$fa-var-desktop-alt: \\f390;\n$fa-var-m: \\4d;\n$fa-var-table-list: \\f00b;\n$fa-var-th-list: \\f00b;\n$fa-var-comment-sms: \\f7cd;\n$fa-var-sms: \\f7cd;\n$fa-var-book: \\f02d;\n$fa-var-user-plus: \\f234;\n$fa-var-check: \\f00c;\n$fa-var-battery-three-quarters: \\f241;\n$fa-var-battery-4: \\f241;\n$fa-var-house-circle-check: \\e509;\n$fa-var-angle-left: \\f104;\n$fa-var-diagram-successor: \\e47a;\n$fa-var-truck-arrow-right: \\e58b;\n$fa-var-arrows-split-up-and-left: \\e4bc;\n$fa-var-hand-fist: \\f6de;\n$fa-var-fist-raised: \\f6de;\n$fa-var-cloud-moon: \\f6c3;\n$fa-var-briefcase: \\f0b1;\n$fa-var-person-falling: \\e546;\n$fa-var-image-portrait: \\f3e0;\n$fa-var-portrait: \\f3e0;\n$fa-var-user-tag: \\f507;\n$fa-var-rug: \\e569;\n$fa-var-earth-europe: \\f7a2;\n$fa-var-globe-europe: \\f7a2;\n$fa-var-cart-flatbed-suitcase: \\f59d;\n$fa-var-luggage-cart: \\f59d;\n$fa-var-rectangle-xmark: \\f410;\n$fa-var-rectangle-times: \\f410;\n$fa-var-times-rectangle: \\f410;\n$fa-var-window-close: \\f410;\n$fa-var-baht-sign: \\e0ac;\n$fa-var-book-open: \\f518;\n$fa-var-book-journal-whills: \\f66a;\n$fa-var-journal-whills: \\f66a;\n$fa-var-handcuffs: \\e4f8;\n$fa-var-triangle-exclamation: \\f071;\n$fa-var-exclamation-triangle: \\f071;\n$fa-var-warning: \\f071;\n$fa-var-database: \\f1c0;\n$fa-var-share: \\f064;\n$fa-var-mail-forward: \\f064;\n$fa-var-bottle-droplet: \\e4c4;\n$fa-var-mask-face: \\e1d7;\n$fa-var-hill-rockslide: \\e508;\n$fa-var-right-left: \\f362;\n$fa-var-exchange-alt: \\f362;\n$fa-var-paper-plane: \\f1d8;\n$fa-var-road-circle-exclamation: \\e565;\n$fa-var-dungeon: \\f6d9;\n$fa-var-align-right: \\f038;\n$fa-var-money-bill-1-wave: \\f53b;\n$fa-var-money-bill-wave-alt: \\f53b;\n$fa-var-life-ring: \\f1cd;\n$fa-var-hands: \\f2a7;\n$fa-var-sign-language: \\f2a7;\n$fa-var-signing: \\f2a7;\n$fa-var-calendar-day: \\f783;\n$fa-var-water-ladder: \\f5c5;\n$fa-var-ladder-water: \\f5c5;\n$fa-var-swimming-pool: \\f5c5;\n$fa-var-arrows-up-down: \\f07d;\n$fa-var-arrows-v: \\f07d;\n$fa-var-face-grimace: \\f57f;\n$fa-var-grimace: \\f57f;\n$fa-var-wheelchair-move: \\e2ce;\n$fa-var-wheelchair-alt: \\e2ce;\n$fa-var-turn-down: \\f3be;\n$fa-var-level-down-alt: \\f3be;\n$fa-var-person-walking-arrow-right: \\e552;\n$fa-var-square-envelope: \\f199;\n$fa-var-envelope-square: \\f199;\n$fa-var-dice: \\f522;\n$fa-var-bowling-ball: \\f436;\n$fa-var-brain: \\f5dc;\n$fa-var-bandage: \\f462;\n$fa-var-band-aid: \\f462;\n$fa-var-calendar-minus: \\f272;\n$fa-var-circle-xmark: \\f057;\n$fa-var-times-circle: \\f057;\n$fa-var-xmark-circle: \\f057;\n$fa-var-gifts: \\f79c;\n$fa-var-hotel: \\f594;\n$fa-var-earth-asia: \\f57e;\n$fa-var-globe-asia: \\f57e;\n$fa-var-id-card-clip: \\f47f;\n$fa-var-id-card-alt: \\f47f;\n$fa-var-magnifying-glass-plus: \\f00e;\n$fa-var-search-plus: \\f00e;\n$fa-var-thumbs-up: \\f164;\n$fa-var-user-clock: \\f4fd;\n$fa-var-hand-dots: \\f461;\n$fa-var-allergies: \\f461;\n$fa-var-file-invoice: \\f570;\n$fa-var-window-minimize: \\f2d1;\n$fa-var-mug-saucer: \\f0f4;\n$fa-var-coffee: \\f0f4;\n$fa-var-brush: \\f55d;\n$fa-var-mask: \\f6fa;\n$fa-var-magnifying-glass-minus: \\f010;\n$fa-var-search-minus: \\f010;\n$fa-var-ruler-vertical: \\f548;\n$fa-var-user-large: \\f406;\n$fa-var-user-alt: \\f406;\n$fa-var-train-tram: \\e5b4;\n$fa-var-user-nurse: \\f82f;\n$fa-var-syringe: \\f48e;\n$fa-var-cloud-sun: \\f6c4;\n$fa-var-stopwatch-20: \\e06f;\n$fa-var-square-full: \\f45c;\n$fa-var-magnet: \\f076;\n$fa-var-jar: \\e516;\n$fa-var-note-sticky: \\f249;\n$fa-var-sticky-note: \\f249;\n$fa-var-bug-slash: \\e490;\n$fa-var-arrow-up-from-water-pump: \\e4b6;\n$fa-var-bone: \\f5d7;\n$fa-var-table-cells-row-unlock: \\e691;\n$fa-var-user-injured: \\f728;\n$fa-var-face-sad-tear: \\f5b4;\n$fa-var-sad-tear: \\f5b4;\n$fa-var-plane: \\f072;\n$fa-var-tent-arrows-down: \\e581;\n$fa-var-exclamation: \\21;\n$fa-var-arrows-spin: \\e4bb;\n$fa-var-print: \\f02f;\n$fa-var-turkish-lira-sign: \\e2bb;\n$fa-var-try: \\e2bb;\n$fa-var-turkish-lira: \\e2bb;\n$fa-var-dollar-sign: \\24;\n$fa-var-dollar: \\24;\n$fa-var-usd: \\24;\n$fa-var-x: \\58;\n$fa-var-magnifying-glass-dollar: \\f688;\n$fa-var-search-dollar: \\f688;\n$fa-var-users-gear: \\f509;\n$fa-var-users-cog: \\f509;\n$fa-var-person-military-pointing: \\e54a;\n$fa-var-building-columns: \\f19c;\n$fa-var-bank: \\f19c;\n$fa-var-institution: \\f19c;\n$fa-var-museum: \\f19c;\n$fa-var-university: \\f19c;\n$fa-var-umbrella: \\f0e9;\n$fa-var-trowel: \\e589;\n$fa-var-d: \\44;\n$fa-var-stapler: \\e5af;\n$fa-var-masks-theater: \\f630;\n$fa-var-theater-masks: \\f630;\n$fa-var-kip-sign: \\e1c4;\n$fa-var-hand-point-left: \\f0a5;\n$fa-var-handshake-simple: \\f4c6;\n$fa-var-handshake-alt: \\f4c6;\n$fa-var-jet-fighter: \\f0fb;\n$fa-var-fighter-jet: \\f0fb;\n$fa-var-square-share-nodes: \\f1e1;\n$fa-var-share-alt-square: \\f1e1;\n$fa-var-barcode: \\f02a;\n$fa-var-plus-minus: \\e43c;\n$fa-var-video: \\f03d;\n$fa-var-video-camera: \\f03d;\n$fa-var-graduation-cap: \\f19d;\n$fa-var-mortar-board: \\f19d;\n$fa-var-hand-holding-medical: \\e05c;\n$fa-var-person-circle-check: \\e53e;\n$fa-var-turn-up: \\f3bf;\n$fa-var-level-up-alt: \\f3bf;\n\n$fa-var-monero: \\f3d0;\n$fa-var-hooli: \\f427;\n$fa-var-yelp: \\f1e9;\n$fa-var-cc-visa: \\f1f0;\n$fa-var-lastfm: \\f202;\n$fa-var-shopware: \\f5b5;\n$fa-var-creative-commons-nc: \\f4e8;\n$fa-var-aws: \\f375;\n$fa-var-redhat: \\f7bc;\n$fa-var-yoast: \\f2b1;\n$fa-var-cloudflare: \\e07d;\n$fa-var-ups: \\f7e0;\n$fa-var-pixiv: \\e640;\n$fa-var-wpexplorer: \\f2de;\n$fa-var-dyalog: \\f399;\n$fa-var-bity: \\f37a;\n$fa-var-stackpath: \\f842;\n$fa-var-buysellads: \\f20d;\n$fa-var-first-order: \\f2b0;\n$fa-var-modx: \\f285;\n$fa-var-guilded: \\e07e;\n$fa-var-vnv: \\f40b;\n$fa-var-square-js: \\f3b9;\n$fa-var-js-square: \\f3b9;\n$fa-var-microsoft: \\f3ca;\n$fa-var-qq: \\f1d6;\n$fa-var-orcid: \\f8d2;\n$fa-var-java: \\f4e4;\n$fa-var-invision: \\f7b0;\n$fa-var-creative-commons-pd-alt: \\f4ed;\n$fa-var-centercode: \\f380;\n$fa-var-glide-g: \\f2a6;\n$fa-var-drupal: \\f1a9;\n$fa-var-jxl: \\e67b;\n$fa-var-dart-lang: \\e693;\n$fa-var-hire-a-helper: \\f3b0;\n$fa-var-creative-commons-by: \\f4e7;\n$fa-var-unity: \\e049;\n$fa-var-whmcs: \\f40d;\n$fa-var-rocketchat: \\f3e8;\n$fa-var-vk: \\f189;\n$fa-var-untappd: \\f405;\n$fa-var-mailchimp: \\f59e;\n$fa-var-css3-alt: \\f38b;\n$fa-var-square-reddit: \\f1a2;\n$fa-var-reddit-square: \\f1a2;\n$fa-var-vimeo-v: \\f27d;\n$fa-var-contao: \\f26d;\n$fa-var-square-font-awesome: \\e5ad;\n$fa-var-deskpro: \\f38f;\n$fa-var-brave: \\e63c;\n$fa-var-sistrix: \\f3ee;\n$fa-var-square-instagram: \\e055;\n$fa-var-instagram-square: \\e055;\n$fa-var-battle-net: \\f835;\n$fa-var-the-red-yeti: \\f69d;\n$fa-var-square-hacker-news: \\f3af;\n$fa-var-hacker-news-square: \\f3af;\n$fa-var-edge: \\f282;\n$fa-var-threads: \\e618;\n$fa-var-napster: \\f3d2;\n$fa-var-square-snapchat: \\f2ad;\n$fa-var-snapchat-square: \\f2ad;\n$fa-var-google-plus-g: \\f0d5;\n$fa-var-artstation: \\f77a;\n$fa-var-markdown: \\f60f;\n$fa-var-sourcetree: \\f7d3;\n$fa-var-google-plus: \\f2b3;\n$fa-var-diaspora: \\f791;\n$fa-var-foursquare: \\f180;\n$fa-var-stack-overflow: \\f16c;\n$fa-var-github-alt: \\f113;\n$fa-var-phoenix-squadron: \\f511;\n$fa-var-pagelines: \\f18c;\n$fa-var-algolia: \\f36c;\n$fa-var-red-river: \\f3e3;\n$fa-var-creative-commons-sa: \\f4ef;\n$fa-var-safari: \\f267;\n$fa-var-google: \\f1a0;\n$fa-var-square-font-awesome-stroke: \\f35c;\n$fa-var-font-awesome-alt: \\f35c;\n$fa-var-atlassian: \\f77b;\n$fa-var-linkedin-in: \\f0e1;\n$fa-var-digital-ocean: \\f391;\n$fa-var-nimblr: \\f5a8;\n$fa-var-chromecast: \\f838;\n$fa-var-evernote: \\f839;\n$fa-var-hacker-news: \\f1d4;\n$fa-var-creative-commons-sampling: \\f4f0;\n$fa-var-adversal: \\f36a;\n$fa-var-creative-commons: \\f25e;\n$fa-var-watchman-monitoring: \\e087;\n$fa-var-fonticons: \\f280;\n$fa-var-weixin: \\f1d7;\n$fa-var-shirtsinbulk: \\f214;\n$fa-var-codepen: \\f1cb;\n$fa-var-git-alt: \\f841;\n$fa-var-lyft: \\f3c3;\n$fa-var-rev: \\f5b2;\n$fa-var-windows: \\f17a;\n$fa-var-wizards-of-the-coast: \\f730;\n$fa-var-square-viadeo: \\f2aa;\n$fa-var-viadeo-square: \\f2aa;\n$fa-var-meetup: \\f2e0;\n$fa-var-centos: \\f789;\n$fa-var-adn: \\f170;\n$fa-var-cloudsmith: \\f384;\n$fa-var-opensuse: \\e62b;\n$fa-var-pied-piper-alt: \\f1a8;\n$fa-var-square-dribbble: \\f397;\n$fa-var-dribbble-square: \\f397;\n$fa-var-codiepie: \\f284;\n$fa-var-node: \\f419;\n$fa-var-mix: \\f3cb;\n$fa-var-steam: \\f1b6;\n$fa-var-cc-apple-pay: \\f416;\n$fa-var-scribd: \\f28a;\n$fa-var-debian: \\e60b;\n$fa-var-openid: \\f19b;\n$fa-var-instalod: \\e081;\n$fa-var-expeditedssl: \\f23e;\n$fa-var-sellcast: \\f2da;\n$fa-var-square-twitter: \\f081;\n$fa-var-twitter-square: \\f081;\n$fa-var-r-project: \\f4f7;\n$fa-var-delicious: \\f1a5;\n$fa-var-freebsd: \\f3a4;\n$fa-var-vuejs: \\f41f;\n$fa-var-accusoft: \\f369;\n$fa-var-ioxhost: \\f208;\n$fa-var-fonticons-fi: \\f3a2;\n$fa-var-app-store: \\f36f;\n$fa-var-cc-mastercard: \\f1f1;\n$fa-var-itunes-note: \\f3b5;\n$fa-var-golang: \\e40f;\n$fa-var-kickstarter: \\f3bb;\n$fa-var-square-kickstarter: \\f3bb;\n$fa-var-grav: \\f2d6;\n$fa-var-weibo: \\f18a;\n$fa-var-uncharted: \\e084;\n$fa-var-firstdraft: \\f3a1;\n$fa-var-square-youtube: \\f431;\n$fa-var-youtube-square: \\f431;\n$fa-var-wikipedia-w: \\f266;\n$fa-var-wpressr: \\f3e4;\n$fa-var-rendact: \\f3e4;\n$fa-var-angellist: \\f209;\n$fa-var-galactic-republic: \\f50c;\n$fa-var-nfc-directional: \\e530;\n$fa-var-skype: \\f17e;\n$fa-var-joget: \\f3b7;\n$fa-var-fedora: \\f798;\n$fa-var-stripe-s: \\f42a;\n$fa-var-meta: \\e49b;\n$fa-var-laravel: \\f3bd;\n$fa-var-hotjar: \\f3b1;\n$fa-var-bluetooth-b: \\f294;\n$fa-var-square-letterboxd: \\e62e;\n$fa-var-sticker-mule: \\f3f7;\n$fa-var-creative-commons-zero: \\f4f3;\n$fa-var-hips: \\f452;\n$fa-var-behance: \\f1b4;\n$fa-var-reddit: \\f1a1;\n$fa-var-discord: \\f392;\n$fa-var-chrome: \\f268;\n$fa-var-app-store-ios: \\f370;\n$fa-var-cc-discover: \\f1f2;\n$fa-var-wpbeginner: \\f297;\n$fa-var-confluence: \\f78d;\n$fa-var-shoelace: \\e60c;\n$fa-var-mdb: \\f8ca;\n$fa-var-dochub: \\f394;\n$fa-var-accessible-icon: \\f368;\n$fa-var-ebay: \\f4f4;\n$fa-var-amazon: \\f270;\n$fa-var-unsplash: \\e07c;\n$fa-var-yarn: \\f7e3;\n$fa-var-square-steam: \\f1b7;\n$fa-var-steam-square: \\f1b7;\n$fa-var-500px: \\f26e;\n$fa-var-square-vimeo: \\f194;\n$fa-var-vimeo-square: \\f194;\n$fa-var-asymmetrik: \\f372;\n$fa-var-font-awesome: \\f2b4;\n$fa-var-font-awesome-flag: \\f2b4;\n$fa-var-font-awesome-logo-full: \\f2b4;\n$fa-var-gratipay: \\f184;\n$fa-var-apple: \\f179;\n$fa-var-hive: \\e07f;\n$fa-var-gitkraken: \\f3a6;\n$fa-var-keybase: \\f4f5;\n$fa-var-apple-pay: \\f415;\n$fa-var-padlet: \\e4a0;\n$fa-var-amazon-pay: \\f42c;\n$fa-var-square-github: \\f092;\n$fa-var-github-square: \\f092;\n$fa-var-stumbleupon: \\f1a4;\n$fa-var-fedex: \\f797;\n$fa-var-phoenix-framework: \\f3dc;\n$fa-var-shopify: \\e057;\n$fa-var-neos: \\f612;\n$fa-var-square-threads: \\e619;\n$fa-var-hackerrank: \\f5f7;\n$fa-var-researchgate: \\f4f8;\n$fa-var-swift: \\f8e1;\n$fa-var-angular: \\f420;\n$fa-var-speakap: \\f3f3;\n$fa-var-angrycreative: \\f36e;\n$fa-var-y-combinator: \\f23b;\n$fa-var-empire: \\f1d1;\n$fa-var-envira: \\f299;\n$fa-var-google-scholar: \\e63b;\n$fa-var-square-gitlab: \\e5ae;\n$fa-var-gitlab-square: \\e5ae;\n$fa-var-studiovinari: \\f3f8;\n$fa-var-pied-piper: \\f2ae;\n$fa-var-wordpress: \\f19a;\n$fa-var-product-hunt: \\f288;\n$fa-var-firefox: \\f269;\n$fa-var-linode: \\f2b8;\n$fa-var-goodreads: \\f3a8;\n$fa-var-square-odnoklassniki: \\f264;\n$fa-var-odnoklassniki-square: \\f264;\n$fa-var-jsfiddle: \\f1cc;\n$fa-var-sith: \\f512;\n$fa-var-themeisle: \\f2b2;\n$fa-var-page4: \\f3d7;\n$fa-var-hashnode: \\e499;\n$fa-var-react: \\f41b;\n$fa-var-cc-paypal: \\f1f4;\n$fa-var-squarespace: \\f5be;\n$fa-var-cc-stripe: \\f1f5;\n$fa-var-creative-commons-share: \\f4f2;\n$fa-var-bitcoin: \\f379;\n$fa-var-keycdn: \\f3ba;\n$fa-var-opera: \\f26a;\n$fa-var-itch-io: \\f83a;\n$fa-var-umbraco: \\f8e8;\n$fa-var-galactic-senate: \\f50d;\n$fa-var-ubuntu: \\f7df;\n$fa-var-draft2digital: \\f396;\n$fa-var-stripe: \\f429;\n$fa-var-houzz: \\f27c;\n$fa-var-gg: \\f260;\n$fa-var-dhl: \\f790;\n$fa-var-square-pinterest: \\f0d3;\n$fa-var-pinterest-square: \\f0d3;\n$fa-var-xing: \\f168;\n$fa-var-blackberry: \\f37b;\n$fa-var-creative-commons-pd: \\f4ec;\n$fa-var-playstation: \\f3df;\n$fa-var-quinscape: \\f459;\n$fa-var-less: \\f41d;\n$fa-var-blogger-b: \\f37d;\n$fa-var-opencart: \\f23d;\n$fa-var-vine: \\f1ca;\n$fa-var-signal-messenger: \\e663;\n$fa-var-paypal: \\f1ed;\n$fa-var-gitlab: \\f296;\n$fa-var-typo3: \\f42b;\n$fa-var-reddit-alien: \\f281;\n$fa-var-yahoo: \\f19e;\n$fa-var-dailymotion: \\e052;\n$fa-var-affiliatetheme: \\f36b;\n$fa-var-pied-piper-pp: \\f1a7;\n$fa-var-bootstrap: \\f836;\n$fa-var-odnoklassniki: \\f263;\n$fa-var-nfc-symbol: \\e531;\n$fa-var-mintbit: \\e62f;\n$fa-var-ethereum: \\f42e;\n$fa-var-speaker-deck: \\f83c;\n$fa-var-creative-commons-nc-eu: \\f4e9;\n$fa-var-patreon: \\f3d9;\n$fa-var-avianex: \\f374;\n$fa-var-ello: \\f5f1;\n$fa-var-gofore: \\f3a7;\n$fa-var-bimobject: \\f378;\n$fa-var-brave-reverse: \\e63d;\n$fa-var-facebook-f: \\f39e;\n$fa-var-square-google-plus: \\f0d4;\n$fa-var-google-plus-square: \\f0d4;\n$fa-var-web-awesome: \\e682;\n$fa-var-mandalorian: \\f50f;\n$fa-var-first-order-alt: \\f50a;\n$fa-var-osi: \\f41a;\n$fa-var-google-wallet: \\f1ee;\n$fa-var-d-and-d-beyond: \\f6ca;\n$fa-var-periscope: \\f3da;\n$fa-var-fulcrum: \\f50b;\n$fa-var-cloudscale: \\f383;\n$fa-var-forumbee: \\f211;\n$fa-var-mizuni: \\f3cc;\n$fa-var-schlix: \\f3ea;\n$fa-var-square-xing: \\f169;\n$fa-var-xing-square: \\f169;\n$fa-var-bandcamp: \\f2d5;\n$fa-var-wpforms: \\f298;\n$fa-var-cloudversify: \\f385;\n$fa-var-usps: \\f7e1;\n$fa-var-megaport: \\f5a3;\n$fa-var-magento: \\f3c4;\n$fa-var-spotify: \\f1bc;\n$fa-var-optin-monster: \\f23c;\n$fa-var-fly: \\f417;\n$fa-var-aviato: \\f421;\n$fa-var-itunes: \\f3b4;\n$fa-var-cuttlefish: \\f38c;\n$fa-var-blogger: \\f37c;\n$fa-var-flickr: \\f16e;\n$fa-var-viber: \\f409;\n$fa-var-soundcloud: \\f1be;\n$fa-var-digg: \\f1a6;\n$fa-var-tencent-weibo: \\f1d5;\n$fa-var-letterboxd: \\e62d;\n$fa-var-symfony: \\f83d;\n$fa-var-maxcdn: \\f136;\n$fa-var-etsy: \\f2d7;\n$fa-var-facebook-messenger: \\f39f;\n$fa-var-audible: \\f373;\n$fa-var-think-peaks: \\f731;\n$fa-var-bilibili: \\e3d9;\n$fa-var-erlang: \\f39d;\n$fa-var-x-twitter: \\e61b;\n$fa-var-cotton-bureau: \\f89e;\n$fa-var-dashcube: \\f210;\n$fa-var-42-group: \\e080;\n$fa-var-innosoft: \\e080;\n$fa-var-stack-exchange: \\f18d;\n$fa-var-elementor: \\f430;\n$fa-var-square-pied-piper: \\e01e;\n$fa-var-pied-piper-square: \\e01e;\n$fa-var-creative-commons-nd: \\f4eb;\n$fa-var-palfed: \\f3d8;\n$fa-var-superpowers: \\f2dd;\n$fa-var-resolving: \\f3e7;\n$fa-var-xbox: \\f412;\n$fa-var-square-web-awesome-stroke: \\e684;\n$fa-var-searchengin: \\f3eb;\n$fa-var-tiktok: \\e07b;\n$fa-var-square-facebook: \\f082;\n$fa-var-facebook-square: \\f082;\n$fa-var-renren: \\f18b;\n$fa-var-linux: \\f17c;\n$fa-var-glide: \\f2a5;\n$fa-var-linkedin: \\f08c;\n$fa-var-hubspot: \\f3b2;\n$fa-var-deploydog: \\f38e;\n$fa-var-twitch: \\f1e8;\n$fa-var-flutter: \\e694;\n$fa-var-ravelry: \\f2d9;\n$fa-var-mixer: \\e056;\n$fa-var-square-lastfm: \\f203;\n$fa-var-lastfm-square: \\f203;\n$fa-var-vimeo: \\f40a;\n$fa-var-mendeley: \\f7b3;\n$fa-var-uniregistry: \\f404;\n$fa-var-figma: \\f799;\n$fa-var-creative-commons-remix: \\f4ee;\n$fa-var-cc-amazon-pay: \\f42d;\n$fa-var-dropbox: \\f16b;\n$fa-var-instagram: \\f16d;\n$fa-var-cmplid: \\e360;\n$fa-var-upwork: \\e641;\n$fa-var-facebook: \\f09a;\n$fa-var-gripfire: \\f3ac;\n$fa-var-jedi-order: \\f50e;\n$fa-var-uikit: \\f403;\n$fa-var-fort-awesome-alt: \\f3a3;\n$fa-var-phabricator: \\f3db;\n$fa-var-ussunnah: \\f407;\n$fa-var-earlybirds: \\f39a;\n$fa-var-trade-federation: \\f513;\n$fa-var-autoprefixer: \\f41c;\n$fa-var-whatsapp: \\f232;\n$fa-var-square-upwork: \\e67c;\n$fa-var-slideshare: \\f1e7;\n$fa-var-google-play: \\f3ab;\n$fa-var-viadeo: \\f2a9;\n$fa-var-line: \\f3c0;\n$fa-var-google-drive: \\f3aa;\n$fa-var-servicestack: \\f3ec;\n$fa-var-simplybuilt: \\f215;\n$fa-var-bitbucket: \\f171;\n$fa-var-imdb: \\f2d8;\n$fa-var-deezer: \\e077;\n$fa-var-raspberry-pi: \\f7bb;\n$fa-var-jira: \\f7b1;\n$fa-var-docker: \\f395;\n$fa-var-screenpal: \\e570;\n$fa-var-bluetooth: \\f293;\n$fa-var-gitter: \\f426;\n$fa-var-d-and-d: \\f38d;\n$fa-var-microblog: \\e01a;\n$fa-var-cc-diners-club: \\f24c;\n$fa-var-gg-circle: \\f261;\n$fa-var-pied-piper-hat: \\f4e5;\n$fa-var-kickstarter-k: \\f3bc;\n$fa-var-yandex: \\f413;\n$fa-var-readme: \\f4d5;\n$fa-var-html5: \\f13b;\n$fa-var-sellsy: \\f213;\n$fa-var-square-web-awesome: \\e683;\n$fa-var-sass: \\f41e;\n$fa-var-wirsindhandwerk: \\e2d0;\n$fa-var-wsh: \\e2d0;\n$fa-var-buromobelexperte: \\f37f;\n$fa-var-salesforce: \\f83b;\n$fa-var-octopus-deploy: \\e082;\n$fa-var-medapps: \\f3c6;\n$fa-var-ns8: \\f3d5;\n$fa-var-pinterest-p: \\f231;\n$fa-var-apper: \\f371;\n$fa-var-fort-awesome: \\f286;\n$fa-var-waze: \\f83f;\n$fa-var-bluesky: \\e671;\n$fa-var-cc-jcb: \\f24b;\n$fa-var-snapchat: \\f2ab;\n$fa-var-snapchat-ghost: \\f2ab;\n$fa-var-fantasy-flight-games: \\f6dc;\n$fa-var-rust: \\e07a;\n$fa-var-wix: \\f5cf;\n$fa-var-square-behance: \\f1b5;\n$fa-var-behance-square: \\f1b5;\n$fa-var-supple: \\f3f9;\n$fa-var-webflow: \\e65c;\n$fa-var-rebel: \\f1d0;\n$fa-var-css3: \\f13c;\n$fa-var-staylinked: \\f3f5;\n$fa-var-kaggle: \\f5fa;\n$fa-var-space-awesome: \\e5ac;\n$fa-var-deviantart: \\f1bd;\n$fa-var-cpanel: \\f388;\n$fa-var-goodreads-g: \\f3a9;\n$fa-var-square-git: \\f1d2;\n$fa-var-git-square: \\f1d2;\n$fa-var-square-tumblr: \\f174;\n$fa-var-tumblr-square: \\f174;\n$fa-var-trello: \\f181;\n$fa-var-creative-commons-nc-jp: \\f4ea;\n$fa-var-get-pocket: \\f265;\n$fa-var-perbyte: \\e083;\n$fa-var-grunt: \\f3ad;\n$fa-var-weebly: \\f5cc;\n$fa-var-connectdevelop: \\f20e;\n$fa-var-leanpub: \\f212;\n$fa-var-black-tie: \\f27e;\n$fa-var-themeco: \\f5c6;\n$fa-var-python: \\f3e2;\n$fa-var-android: \\f17b;\n$fa-var-bots: \\e340;\n$fa-var-free-code-camp: \\f2c5;\n$fa-var-hornbill: \\f592;\n$fa-var-js: \\f3b8;\n$fa-var-ideal: \\e013;\n$fa-var-git: \\f1d3;\n$fa-var-dev: \\f6cc;\n$fa-var-sketch: \\f7c6;\n$fa-var-yandex-international: \\f414;\n$fa-var-cc-amex: \\f1f3;\n$fa-var-uber: \\f402;\n$fa-var-github: \\f09b;\n$fa-var-php: \\f457;\n$fa-var-alipay: \\f642;\n$fa-var-youtube: \\f167;\n$fa-var-skyatlas: \\f216;\n$fa-var-firefox-browser: \\e007;\n$fa-var-replyd: \\f3e6;\n$fa-var-suse: \\f7d6;\n$fa-var-jenkins: \\f3b6;\n$fa-var-twitter: \\f099;\n$fa-var-rockrms: \\f3e9;\n$fa-var-pinterest: \\f0d2;\n$fa-var-buffer: \\f837;\n$fa-var-npm: \\f3d4;\n$fa-var-yammer: \\f840;\n$fa-var-btc: \\f15a;\n$fa-var-dribbble: \\f17d;\n$fa-var-stumbleupon-circle: \\f1a3;\n$fa-var-internet-explorer: \\f26b;\n$fa-var-stubber: \\e5c7;\n$fa-var-telegram: \\f2c6;\n$fa-var-telegram-plane: \\f2c6;\n$fa-var-old-republic: \\f510;\n$fa-var-odysee: \\e5c6;\n$fa-var-square-whatsapp: \\f40c;\n$fa-var-whatsapp-square: \\f40c;\n$fa-var-node-js: \\f3d3;\n$fa-var-edge-legacy: \\e078;\n$fa-var-slack: \\f198;\n$fa-var-slack-hash: \\f198;\n$fa-var-medrt: \\f3c8;\n$fa-var-usb: \\f287;\n$fa-var-tumblr: \\f173;\n$fa-var-vaadin: \\f408;\n$fa-var-quora: \\f2c4;\n$fa-var-square-x-twitter: \\e61a;\n$fa-var-reacteurope: \\f75d;\n$fa-var-medium: \\f23a;\n$fa-var-medium-m: \\f23a;\n$fa-var-amilia: \\f36d;\n$fa-var-mixcloud: \\f289;\n$fa-var-flipboard: \\f44d;\n$fa-var-viacoin: \\f237;\n$fa-var-critical-role: \\f6c9;\n$fa-var-sitrox: \\e44a;\n$fa-var-discourse: \\f393;\n$fa-var-joomla: \\f1aa;\n$fa-var-mastodon: \\f4f6;\n$fa-var-airbnb: \\f834;\n$fa-var-wolf-pack-battalion: \\f514;\n$fa-var-buy-n-large: \\f8a6;\n$fa-var-gulp: \\f3ae;\n$fa-var-creative-commons-sampling-plus: \\f4f1;\n$fa-var-strava: \\f428;\n$fa-var-ember: \\f423;\n$fa-var-canadian-maple-leaf: \\f785;\n$fa-var-teamspeak: \\f4f9;\n$fa-var-pushed: \\f3e1;\n$fa-var-wordpress-simple: \\f411;\n$fa-var-nutritionix: \\f3d6;\n$fa-var-wodu: \\e088;\n$fa-var-google-pay: \\e079;\n$fa-var-intercom: \\f7af;\n$fa-var-zhihu: \\f63f;\n$fa-var-korvue: \\f42f;\n$fa-var-pix: \\e43a;\n$fa-var-steam-symbol: \\f3f6;\n\n$fa-icons: (\n \"0\": $fa-var-0,\n \"1\": $fa-var-1,\n \"2\": $fa-var-2,\n \"3\": $fa-var-3,\n \"4\": $fa-var-4,\n \"5\": $fa-var-5,\n \"6\": $fa-var-6,\n \"7\": $fa-var-7,\n \"8\": $fa-var-8,\n \"9\": $fa-var-9,\n \"fill-drip\": $fa-var-fill-drip,\n \"arrows-to-circle\": $fa-var-arrows-to-circle,\n \"circle-chevron-right\": $fa-var-circle-chevron-right,\n \"chevron-circle-right\": $fa-var-chevron-circle-right,\n \"at\": $fa-var-at,\n \"trash-can\": $fa-var-trash-can,\n \"trash-alt\": $fa-var-trash-alt,\n \"text-height\": $fa-var-text-height,\n \"user-xmark\": $fa-var-user-xmark,\n \"user-times\": $fa-var-user-times,\n \"stethoscope\": $fa-var-stethoscope,\n \"message\": $fa-var-message,\n \"comment-alt\": $fa-var-comment-alt,\n \"info\": $fa-var-info,\n \"down-left-and-up-right-to-center\": $fa-var-down-left-and-up-right-to-center,\n \"compress-alt\": $fa-var-compress-alt,\n \"explosion\": $fa-var-explosion,\n \"file-lines\": $fa-var-file-lines,\n \"file-alt\": $fa-var-file-alt,\n \"file-text\": $fa-var-file-text,\n \"wave-square\": $fa-var-wave-square,\n \"ring\": $fa-var-ring,\n \"building-un\": $fa-var-building-un,\n \"dice-three\": $fa-var-dice-three,\n \"calendar-days\": $fa-var-calendar-days,\n \"calendar-alt\": $fa-var-calendar-alt,\n \"anchor-circle-check\": $fa-var-anchor-circle-check,\n \"building-circle-arrow-right\": $fa-var-building-circle-arrow-right,\n \"volleyball\": $fa-var-volleyball,\n \"volleyball-ball\": $fa-var-volleyball-ball,\n \"arrows-up-to-line\": $fa-var-arrows-up-to-line,\n \"sort-down\": $fa-var-sort-down,\n \"sort-desc\": $fa-var-sort-desc,\n \"circle-minus\": $fa-var-circle-minus,\n \"minus-circle\": $fa-var-minus-circle,\n \"door-open\": $fa-var-door-open,\n \"right-from-bracket\": $fa-var-right-from-bracket,\n \"sign-out-alt\": $fa-var-sign-out-alt,\n \"atom\": $fa-var-atom,\n \"soap\": $fa-var-soap,\n \"icons\": $fa-var-icons,\n \"heart-music-camera-bolt\": $fa-var-heart-music-camera-bolt,\n \"microphone-lines-slash\": $fa-var-microphone-lines-slash,\n \"microphone-alt-slash\": $fa-var-microphone-alt-slash,\n \"bridge-circle-check\": $fa-var-bridge-circle-check,\n \"pump-medical\": $fa-var-pump-medical,\n \"fingerprint\": $fa-var-fingerprint,\n \"hand-point-right\": $fa-var-hand-point-right,\n \"magnifying-glass-location\": $fa-var-magnifying-glass-location,\n \"search-location\": $fa-var-search-location,\n \"forward-step\": $fa-var-forward-step,\n \"step-forward\": $fa-var-step-forward,\n \"face-smile-beam\": $fa-var-face-smile-beam,\n \"smile-beam\": $fa-var-smile-beam,\n \"flag-checkered\": $fa-var-flag-checkered,\n \"football\": $fa-var-football,\n \"football-ball\": $fa-var-football-ball,\n \"school-circle-exclamation\": $fa-var-school-circle-exclamation,\n \"crop\": $fa-var-crop,\n \"angles-down\": $fa-var-angles-down,\n \"angle-double-down\": $fa-var-angle-double-down,\n \"users-rectangle\": $fa-var-users-rectangle,\n \"people-roof\": $fa-var-people-roof,\n \"people-line\": $fa-var-people-line,\n \"beer-mug-empty\": $fa-var-beer-mug-empty,\n \"beer\": $fa-var-beer,\n \"diagram-predecessor\": $fa-var-diagram-predecessor,\n \"arrow-up-long\": $fa-var-arrow-up-long,\n \"long-arrow-up\": $fa-var-long-arrow-up,\n \"fire-flame-simple\": $fa-var-fire-flame-simple,\n \"burn\": $fa-var-burn,\n \"person\": $fa-var-person,\n \"male\": $fa-var-male,\n \"laptop\": $fa-var-laptop,\n \"file-csv\": $fa-var-file-csv,\n \"menorah\": $fa-var-menorah,\n \"truck-plane\": $fa-var-truck-plane,\n \"record-vinyl\": $fa-var-record-vinyl,\n \"face-grin-stars\": $fa-var-face-grin-stars,\n \"grin-stars\": $fa-var-grin-stars,\n \"bong\": $fa-var-bong,\n \"spaghetti-monster-flying\": $fa-var-spaghetti-monster-flying,\n \"pastafarianism\": $fa-var-pastafarianism,\n \"arrow-down-up-across-line\": $fa-var-arrow-down-up-across-line,\n \"spoon\": $fa-var-spoon,\n \"utensil-spoon\": $fa-var-utensil-spoon,\n \"jar-wheat\": $fa-var-jar-wheat,\n \"envelopes-bulk\": $fa-var-envelopes-bulk,\n \"mail-bulk\": $fa-var-mail-bulk,\n \"file-circle-exclamation\": $fa-var-file-circle-exclamation,\n \"circle-h\": $fa-var-circle-h,\n \"hospital-symbol\": $fa-var-hospital-symbol,\n \"pager\": $fa-var-pager,\n \"address-book\": $fa-var-address-book,\n \"contact-book\": $fa-var-contact-book,\n \"strikethrough\": $fa-var-strikethrough,\n \"k\": $fa-var-k,\n \"landmark-flag\": $fa-var-landmark-flag,\n \"pencil\": $fa-var-pencil,\n \"pencil-alt\": $fa-var-pencil-alt,\n \"backward\": $fa-var-backward,\n \"caret-right\": $fa-var-caret-right,\n \"comments\": $fa-var-comments,\n \"paste\": $fa-var-paste,\n \"file-clipboard\": $fa-var-file-clipboard,\n \"code-pull-request\": $fa-var-code-pull-request,\n \"clipboard-list\": $fa-var-clipboard-list,\n \"truck-ramp-box\": $fa-var-truck-ramp-box,\n \"truck-loading\": $fa-var-truck-loading,\n \"user-check\": $fa-var-user-check,\n \"vial-virus\": $fa-var-vial-virus,\n \"sheet-plastic\": $fa-var-sheet-plastic,\n \"blog\": $fa-var-blog,\n \"user-ninja\": $fa-var-user-ninja,\n \"person-arrow-up-from-line\": $fa-var-person-arrow-up-from-line,\n \"scroll-torah\": $fa-var-scroll-torah,\n \"torah\": $fa-var-torah,\n \"broom-ball\": $fa-var-broom-ball,\n \"quidditch\": $fa-var-quidditch,\n \"quidditch-broom-ball\": $fa-var-quidditch-broom-ball,\n \"toggle-off\": $fa-var-toggle-off,\n \"box-archive\": $fa-var-box-archive,\n \"archive\": $fa-var-archive,\n \"person-drowning\": $fa-var-person-drowning,\n \"arrow-down-9-1\": $fa-var-arrow-down-9-1,\n \"sort-numeric-desc\": $fa-var-sort-numeric-desc,\n \"sort-numeric-down-alt\": $fa-var-sort-numeric-down-alt,\n \"face-grin-tongue-squint\": $fa-var-face-grin-tongue-squint,\n \"grin-tongue-squint\": $fa-var-grin-tongue-squint,\n \"spray-can\": $fa-var-spray-can,\n \"truck-monster\": $fa-var-truck-monster,\n \"w\": $fa-var-w,\n \"earth-africa\": $fa-var-earth-africa,\n \"globe-africa\": $fa-var-globe-africa,\n \"rainbow\": $fa-var-rainbow,\n \"circle-notch\": $fa-var-circle-notch,\n \"tablet-screen-button\": $fa-var-tablet-screen-button,\n \"tablet-alt\": $fa-var-tablet-alt,\n \"paw\": $fa-var-paw,\n \"cloud\": $fa-var-cloud,\n \"trowel-bricks\": $fa-var-trowel-bricks,\n \"face-flushed\": $fa-var-face-flushed,\n \"flushed\": $fa-var-flushed,\n \"hospital-user\": $fa-var-hospital-user,\n \"tent-arrow-left-right\": $fa-var-tent-arrow-left-right,\n \"gavel\": $fa-var-gavel,\n \"legal\": $fa-var-legal,\n \"binoculars\": $fa-var-binoculars,\n \"microphone-slash\": $fa-var-microphone-slash,\n \"box-tissue\": $fa-var-box-tissue,\n \"motorcycle\": $fa-var-motorcycle,\n \"bell-concierge\": $fa-var-bell-concierge,\n \"concierge-bell\": $fa-var-concierge-bell,\n \"pen-ruler\": $fa-var-pen-ruler,\n \"pencil-ruler\": $fa-var-pencil-ruler,\n \"people-arrows\": $fa-var-people-arrows,\n \"people-arrows-left-right\": $fa-var-people-arrows-left-right,\n \"mars-and-venus-burst\": $fa-var-mars-and-venus-burst,\n \"square-caret-right\": $fa-var-square-caret-right,\n \"caret-square-right\": $fa-var-caret-square-right,\n \"scissors\": $fa-var-scissors,\n \"cut\": $fa-var-cut,\n \"sun-plant-wilt\": $fa-var-sun-plant-wilt,\n \"toilets-portable\": $fa-var-toilets-portable,\n \"hockey-puck\": $fa-var-hockey-puck,\n \"table\": $fa-var-table,\n \"magnifying-glass-arrow-right\": $fa-var-magnifying-glass-arrow-right,\n \"tachograph-digital\": $fa-var-tachograph-digital,\n \"digital-tachograph\": $fa-var-digital-tachograph,\n \"users-slash\": $fa-var-users-slash,\n \"clover\": $fa-var-clover,\n \"reply\": $fa-var-reply,\n \"mail-reply\": $fa-var-mail-reply,\n \"star-and-crescent\": $fa-var-star-and-crescent,\n \"house-fire\": $fa-var-house-fire,\n \"square-minus\": $fa-var-square-minus,\n \"minus-square\": $fa-var-minus-square,\n \"helicopter\": $fa-var-helicopter,\n \"compass\": $fa-var-compass,\n \"square-caret-down\": $fa-var-square-caret-down,\n \"caret-square-down\": $fa-var-caret-square-down,\n \"file-circle-question\": $fa-var-file-circle-question,\n \"laptop-code\": $fa-var-laptop-code,\n \"swatchbook\": $fa-var-swatchbook,\n \"prescription-bottle\": $fa-var-prescription-bottle,\n \"bars\": $fa-var-bars,\n \"navicon\": $fa-var-navicon,\n \"people-group\": $fa-var-people-group,\n \"hourglass-end\": $fa-var-hourglass-end,\n \"hourglass-3\": $fa-var-hourglass-3,\n \"heart-crack\": $fa-var-heart-crack,\n \"heart-broken\": $fa-var-heart-broken,\n \"square-up-right\": $fa-var-square-up-right,\n \"external-link-square-alt\": $fa-var-external-link-square-alt,\n \"face-kiss-beam\": $fa-var-face-kiss-beam,\n \"kiss-beam\": $fa-var-kiss-beam,\n \"film\": $fa-var-film,\n \"ruler-horizontal\": $fa-var-ruler-horizontal,\n \"people-robbery\": $fa-var-people-robbery,\n \"lightbulb\": $fa-var-lightbulb,\n \"caret-left\": $fa-var-caret-left,\n \"circle-exclamation\": $fa-var-circle-exclamation,\n \"exclamation-circle\": $fa-var-exclamation-circle,\n \"school-circle-xmark\": $fa-var-school-circle-xmark,\n \"arrow-right-from-bracket\": $fa-var-arrow-right-from-bracket,\n \"sign-out\": $fa-var-sign-out,\n \"circle-chevron-down\": $fa-var-circle-chevron-down,\n \"chevron-circle-down\": $fa-var-chevron-circle-down,\n \"unlock-keyhole\": $fa-var-unlock-keyhole,\n \"unlock-alt\": $fa-var-unlock-alt,\n \"cloud-showers-heavy\": $fa-var-cloud-showers-heavy,\n \"headphones-simple\": $fa-var-headphones-simple,\n \"headphones-alt\": $fa-var-headphones-alt,\n \"sitemap\": $fa-var-sitemap,\n \"circle-dollar-to-slot\": $fa-var-circle-dollar-to-slot,\n \"donate\": $fa-var-donate,\n \"memory\": $fa-var-memory,\n \"road-spikes\": $fa-var-road-spikes,\n \"fire-burner\": $fa-var-fire-burner,\n \"flag\": $fa-var-flag,\n \"hanukiah\": $fa-var-hanukiah,\n \"feather\": $fa-var-feather,\n \"volume-low\": $fa-var-volume-low,\n \"volume-down\": $fa-var-volume-down,\n \"comment-slash\": $fa-var-comment-slash,\n \"cloud-sun-rain\": $fa-var-cloud-sun-rain,\n \"compress\": $fa-var-compress,\n \"wheat-awn\": $fa-var-wheat-awn,\n \"wheat-alt\": $fa-var-wheat-alt,\n \"ankh\": $fa-var-ankh,\n \"hands-holding-child\": $fa-var-hands-holding-child,\n \"asterisk\": $fa-var-asterisk,\n \"square-check\": $fa-var-square-check,\n \"check-square\": $fa-var-check-square,\n \"peseta-sign\": $fa-var-peseta-sign,\n \"heading\": $fa-var-heading,\n \"header\": $fa-var-header,\n \"ghost\": $fa-var-ghost,\n \"list\": $fa-var-list,\n \"list-squares\": $fa-var-list-squares,\n \"square-phone-flip\": $fa-var-square-phone-flip,\n \"phone-square-alt\": $fa-var-phone-square-alt,\n \"cart-plus\": $fa-var-cart-plus,\n \"gamepad\": $fa-var-gamepad,\n \"circle-dot\": $fa-var-circle-dot,\n \"dot-circle\": $fa-var-dot-circle,\n \"face-dizzy\": $fa-var-face-dizzy,\n \"dizzy\": $fa-var-dizzy,\n \"egg\": $fa-var-egg,\n \"house-medical-circle-xmark\": $fa-var-house-medical-circle-xmark,\n \"campground\": $fa-var-campground,\n \"folder-plus\": $fa-var-folder-plus,\n \"futbol\": $fa-var-futbol,\n \"futbol-ball\": $fa-var-futbol-ball,\n \"soccer-ball\": $fa-var-soccer-ball,\n \"paintbrush\": $fa-var-paintbrush,\n \"paint-brush\": $fa-var-paint-brush,\n \"lock\": $fa-var-lock,\n \"gas-pump\": $fa-var-gas-pump,\n \"hot-tub-person\": $fa-var-hot-tub-person,\n \"hot-tub\": $fa-var-hot-tub,\n \"map-location\": $fa-var-map-location,\n \"map-marked\": $fa-var-map-marked,\n \"house-flood-water\": $fa-var-house-flood-water,\n \"tree\": $fa-var-tree,\n \"bridge-lock\": $fa-var-bridge-lock,\n \"sack-dollar\": $fa-var-sack-dollar,\n \"pen-to-square\": $fa-var-pen-to-square,\n \"edit\": $fa-var-edit,\n \"car-side\": $fa-var-car-side,\n \"share-nodes\": $fa-var-share-nodes,\n \"share-alt\": $fa-var-share-alt,\n \"heart-circle-minus\": $fa-var-heart-circle-minus,\n \"hourglass-half\": $fa-var-hourglass-half,\n \"hourglass-2\": $fa-var-hourglass-2,\n \"microscope\": $fa-var-microscope,\n \"sink\": $fa-var-sink,\n \"bag-shopping\": $fa-var-bag-shopping,\n \"shopping-bag\": $fa-var-shopping-bag,\n \"arrow-down-z-a\": $fa-var-arrow-down-z-a,\n \"sort-alpha-desc\": $fa-var-sort-alpha-desc,\n \"sort-alpha-down-alt\": $fa-var-sort-alpha-down-alt,\n \"mitten\": $fa-var-mitten,\n \"person-rays\": $fa-var-person-rays,\n \"users\": $fa-var-users,\n \"eye-slash\": $fa-var-eye-slash,\n \"flask-vial\": $fa-var-flask-vial,\n \"hand\": $fa-var-hand,\n \"hand-paper\": $fa-var-hand-paper,\n \"om\": $fa-var-om,\n \"worm\": $fa-var-worm,\n \"house-circle-xmark\": $fa-var-house-circle-xmark,\n \"plug\": $fa-var-plug,\n \"chevron-up\": $fa-var-chevron-up,\n \"hand-spock\": $fa-var-hand-spock,\n \"stopwatch\": $fa-var-stopwatch,\n \"face-kiss\": $fa-var-face-kiss,\n \"kiss\": $fa-var-kiss,\n \"bridge-circle-xmark\": $fa-var-bridge-circle-xmark,\n \"face-grin-tongue\": $fa-var-face-grin-tongue,\n \"grin-tongue\": $fa-var-grin-tongue,\n \"chess-bishop\": $fa-var-chess-bishop,\n \"face-grin-wink\": $fa-var-face-grin-wink,\n \"grin-wink\": $fa-var-grin-wink,\n \"ear-deaf\": $fa-var-ear-deaf,\n \"deaf\": $fa-var-deaf,\n \"deafness\": $fa-var-deafness,\n \"hard-of-hearing\": $fa-var-hard-of-hearing,\n \"road-circle-check\": $fa-var-road-circle-check,\n \"dice-five\": $fa-var-dice-five,\n \"square-rss\": $fa-var-square-rss,\n \"rss-square\": $fa-var-rss-square,\n \"land-mine-on\": $fa-var-land-mine-on,\n \"i-cursor\": $fa-var-i-cursor,\n \"stamp\": $fa-var-stamp,\n \"stairs\": $fa-var-stairs,\n \"i\": $fa-var-i,\n \"hryvnia-sign\": $fa-var-hryvnia-sign,\n \"hryvnia\": $fa-var-hryvnia,\n \"pills\": $fa-var-pills,\n \"face-grin-wide\": $fa-var-face-grin-wide,\n \"grin-alt\": $fa-var-grin-alt,\n \"tooth\": $fa-var-tooth,\n \"v\": $fa-var-v,\n \"bangladeshi-taka-sign\": $fa-var-bangladeshi-taka-sign,\n \"bicycle\": $fa-var-bicycle,\n \"staff-snake\": $fa-var-staff-snake,\n \"rod-asclepius\": $fa-var-rod-asclepius,\n \"rod-snake\": $fa-var-rod-snake,\n \"staff-aesculapius\": $fa-var-staff-aesculapius,\n \"head-side-cough-slash\": $fa-var-head-side-cough-slash,\n \"truck-medical\": $fa-var-truck-medical,\n \"ambulance\": $fa-var-ambulance,\n \"wheat-awn-circle-exclamation\": $fa-var-wheat-awn-circle-exclamation,\n \"snowman\": $fa-var-snowman,\n \"mortar-pestle\": $fa-var-mortar-pestle,\n \"road-barrier\": $fa-var-road-barrier,\n \"school\": $fa-var-school,\n \"igloo\": $fa-var-igloo,\n \"joint\": $fa-var-joint,\n \"angle-right\": $fa-var-angle-right,\n \"horse\": $fa-var-horse,\n \"q\": $fa-var-q,\n \"g\": $fa-var-g,\n \"notes-medical\": $fa-var-notes-medical,\n \"temperature-half\": $fa-var-temperature-half,\n \"temperature-2\": $fa-var-temperature-2,\n \"thermometer-2\": $fa-var-thermometer-2,\n \"thermometer-half\": $fa-var-thermometer-half,\n \"dong-sign\": $fa-var-dong-sign,\n \"capsules\": $fa-var-capsules,\n \"poo-storm\": $fa-var-poo-storm,\n \"poo-bolt\": $fa-var-poo-bolt,\n \"face-frown-open\": $fa-var-face-frown-open,\n \"frown-open\": $fa-var-frown-open,\n \"hand-point-up\": $fa-var-hand-point-up,\n \"money-bill\": $fa-var-money-bill,\n \"bookmark\": $fa-var-bookmark,\n \"align-justify\": $fa-var-align-justify,\n \"umbrella-beach\": $fa-var-umbrella-beach,\n \"helmet-un\": $fa-var-helmet-un,\n \"bullseye\": $fa-var-bullseye,\n \"bacon\": $fa-var-bacon,\n \"hand-point-down\": $fa-var-hand-point-down,\n \"arrow-up-from-bracket\": $fa-var-arrow-up-from-bracket,\n \"folder\": $fa-var-folder,\n \"folder-blank\": $fa-var-folder-blank,\n \"file-waveform\": $fa-var-file-waveform,\n \"file-medical-alt\": $fa-var-file-medical-alt,\n \"radiation\": $fa-var-radiation,\n \"chart-simple\": $fa-var-chart-simple,\n \"mars-stroke\": $fa-var-mars-stroke,\n \"vial\": $fa-var-vial,\n \"gauge\": $fa-var-gauge,\n \"dashboard\": $fa-var-dashboard,\n \"gauge-med\": $fa-var-gauge-med,\n \"tachometer-alt-average\": $fa-var-tachometer-alt-average,\n \"wand-magic-sparkles\": $fa-var-wand-magic-sparkles,\n \"magic-wand-sparkles\": $fa-var-magic-wand-sparkles,\n \"e\": $fa-var-e,\n \"pen-clip\": $fa-var-pen-clip,\n \"pen-alt\": $fa-var-pen-alt,\n \"bridge-circle-exclamation\": $fa-var-bridge-circle-exclamation,\n \"user\": $fa-var-user,\n \"school-circle-check\": $fa-var-school-circle-check,\n \"dumpster\": $fa-var-dumpster,\n \"van-shuttle\": $fa-var-van-shuttle,\n \"shuttle-van\": $fa-var-shuttle-van,\n \"building-user\": $fa-var-building-user,\n \"square-caret-left\": $fa-var-square-caret-left,\n \"caret-square-left\": $fa-var-caret-square-left,\n \"highlighter\": $fa-var-highlighter,\n \"key\": $fa-var-key,\n \"bullhorn\": $fa-var-bullhorn,\n \"globe\": $fa-var-globe,\n \"synagogue\": $fa-var-synagogue,\n \"person-half-dress\": $fa-var-person-half-dress,\n \"road-bridge\": $fa-var-road-bridge,\n \"location-arrow\": $fa-var-location-arrow,\n \"c\": $fa-var-c,\n \"tablet-button\": $fa-var-tablet-button,\n \"building-lock\": $fa-var-building-lock,\n \"pizza-slice\": $fa-var-pizza-slice,\n \"money-bill-wave\": $fa-var-money-bill-wave,\n \"chart-area\": $fa-var-chart-area,\n \"area-chart\": $fa-var-area-chart,\n \"house-flag\": $fa-var-house-flag,\n \"person-circle-minus\": $fa-var-person-circle-minus,\n \"ban\": $fa-var-ban,\n \"cancel\": $fa-var-cancel,\n \"camera-rotate\": $fa-var-camera-rotate,\n \"spray-can-sparkles\": $fa-var-spray-can-sparkles,\n \"air-freshener\": $fa-var-air-freshener,\n \"star\": $fa-var-star,\n \"repeat\": $fa-var-repeat,\n \"cross\": $fa-var-cross,\n \"box\": $fa-var-box,\n \"venus-mars\": $fa-var-venus-mars,\n \"arrow-pointer\": $fa-var-arrow-pointer,\n \"mouse-pointer\": $fa-var-mouse-pointer,\n \"maximize\": $fa-var-maximize,\n \"expand-arrows-alt\": $fa-var-expand-arrows-alt,\n \"charging-station\": $fa-var-charging-station,\n \"shapes\": $fa-var-shapes,\n \"triangle-circle-square\": $fa-var-triangle-circle-square,\n \"shuffle\": $fa-var-shuffle,\n \"random\": $fa-var-random,\n \"person-running\": $fa-var-person-running,\n \"running\": $fa-var-running,\n \"mobile-retro\": $fa-var-mobile-retro,\n \"grip-lines-vertical\": $fa-var-grip-lines-vertical,\n \"spider\": $fa-var-spider,\n \"hands-bound\": $fa-var-hands-bound,\n \"file-invoice-dollar\": $fa-var-file-invoice-dollar,\n \"plane-circle-exclamation\": $fa-var-plane-circle-exclamation,\n \"x-ray\": $fa-var-x-ray,\n \"spell-check\": $fa-var-spell-check,\n \"slash\": $fa-var-slash,\n \"computer-mouse\": $fa-var-computer-mouse,\n \"mouse\": $fa-var-mouse,\n \"arrow-right-to-bracket\": $fa-var-arrow-right-to-bracket,\n \"sign-in\": $fa-var-sign-in,\n \"shop-slash\": $fa-var-shop-slash,\n \"store-alt-slash\": $fa-var-store-alt-slash,\n \"server\": $fa-var-server,\n \"virus-covid-slash\": $fa-var-virus-covid-slash,\n \"shop-lock\": $fa-var-shop-lock,\n \"hourglass-start\": $fa-var-hourglass-start,\n \"hourglass-1\": $fa-var-hourglass-1,\n \"blender-phone\": $fa-var-blender-phone,\n \"building-wheat\": $fa-var-building-wheat,\n \"person-breastfeeding\": $fa-var-person-breastfeeding,\n \"right-to-bracket\": $fa-var-right-to-bracket,\n \"sign-in-alt\": $fa-var-sign-in-alt,\n \"venus\": $fa-var-venus,\n \"passport\": $fa-var-passport,\n \"thumbtack-slash\": $fa-var-thumbtack-slash,\n \"thumb-tack-slash\": $fa-var-thumb-tack-slash,\n \"heart-pulse\": $fa-var-heart-pulse,\n \"heartbeat\": $fa-var-heartbeat,\n \"people-carry-box\": $fa-var-people-carry-box,\n \"people-carry\": $fa-var-people-carry,\n \"temperature-high\": $fa-var-temperature-high,\n \"microchip\": $fa-var-microchip,\n \"crown\": $fa-var-crown,\n \"weight-hanging\": $fa-var-weight-hanging,\n \"xmarks-lines\": $fa-var-xmarks-lines,\n \"file-prescription\": $fa-var-file-prescription,\n \"weight-scale\": $fa-var-weight-scale,\n \"weight\": $fa-var-weight,\n \"user-group\": $fa-var-user-group,\n \"user-friends\": $fa-var-user-friends,\n \"arrow-up-a-z\": $fa-var-arrow-up-a-z,\n \"sort-alpha-up\": $fa-var-sort-alpha-up,\n \"chess-knight\": $fa-var-chess-knight,\n \"face-laugh-squint\": $fa-var-face-laugh-squint,\n \"laugh-squint\": $fa-var-laugh-squint,\n \"wheelchair\": $fa-var-wheelchair,\n \"circle-arrow-up\": $fa-var-circle-arrow-up,\n \"arrow-circle-up\": $fa-var-arrow-circle-up,\n \"toggle-on\": $fa-var-toggle-on,\n \"person-walking\": $fa-var-person-walking,\n \"walking\": $fa-var-walking,\n \"l\": $fa-var-l,\n \"fire\": $fa-var-fire,\n \"bed-pulse\": $fa-var-bed-pulse,\n \"procedures\": $fa-var-procedures,\n \"shuttle-space\": $fa-var-shuttle-space,\n \"space-shuttle\": $fa-var-space-shuttle,\n \"face-laugh\": $fa-var-face-laugh,\n \"laugh\": $fa-var-laugh,\n \"folder-open\": $fa-var-folder-open,\n \"heart-circle-plus\": $fa-var-heart-circle-plus,\n \"code-fork\": $fa-var-code-fork,\n \"city\": $fa-var-city,\n \"microphone-lines\": $fa-var-microphone-lines,\n \"microphone-alt\": $fa-var-microphone-alt,\n \"pepper-hot\": $fa-var-pepper-hot,\n \"unlock\": $fa-var-unlock,\n \"colon-sign\": $fa-var-colon-sign,\n \"headset\": $fa-var-headset,\n \"store-slash\": $fa-var-store-slash,\n \"road-circle-xmark\": $fa-var-road-circle-xmark,\n \"user-minus\": $fa-var-user-minus,\n \"mars-stroke-up\": $fa-var-mars-stroke-up,\n \"mars-stroke-v\": $fa-var-mars-stroke-v,\n \"champagne-glasses\": $fa-var-champagne-glasses,\n \"glass-cheers\": $fa-var-glass-cheers,\n \"clipboard\": $fa-var-clipboard,\n \"house-circle-exclamation\": $fa-var-house-circle-exclamation,\n \"file-arrow-up\": $fa-var-file-arrow-up,\n \"file-upload\": $fa-var-file-upload,\n \"wifi\": $fa-var-wifi,\n \"wifi-3\": $fa-var-wifi-3,\n \"wifi-strong\": $fa-var-wifi-strong,\n \"bath\": $fa-var-bath,\n \"bathtub\": $fa-var-bathtub,\n \"underline\": $fa-var-underline,\n \"user-pen\": $fa-var-user-pen,\n \"user-edit\": $fa-var-user-edit,\n \"signature\": $fa-var-signature,\n \"stroopwafel\": $fa-var-stroopwafel,\n \"bold\": $fa-var-bold,\n \"anchor-lock\": $fa-var-anchor-lock,\n \"building-ngo\": $fa-var-building-ngo,\n \"manat-sign\": $fa-var-manat-sign,\n \"not-equal\": $fa-var-not-equal,\n \"border-top-left\": $fa-var-border-top-left,\n \"border-style\": $fa-var-border-style,\n \"map-location-dot\": $fa-var-map-location-dot,\n \"map-marked-alt\": $fa-var-map-marked-alt,\n \"jedi\": $fa-var-jedi,\n \"square-poll-vertical\": $fa-var-square-poll-vertical,\n \"poll\": $fa-var-poll,\n \"mug-hot\": $fa-var-mug-hot,\n \"car-battery\": $fa-var-car-battery,\n \"battery-car\": $fa-var-battery-car,\n \"gift\": $fa-var-gift,\n \"dice-two\": $fa-var-dice-two,\n \"chess-queen\": $fa-var-chess-queen,\n \"glasses\": $fa-var-glasses,\n \"chess-board\": $fa-var-chess-board,\n \"building-circle-check\": $fa-var-building-circle-check,\n \"person-chalkboard\": $fa-var-person-chalkboard,\n \"mars-stroke-right\": $fa-var-mars-stroke-right,\n \"mars-stroke-h\": $fa-var-mars-stroke-h,\n \"hand-back-fist\": $fa-var-hand-back-fist,\n \"hand-rock\": $fa-var-hand-rock,\n \"square-caret-up\": $fa-var-square-caret-up,\n \"caret-square-up\": $fa-var-caret-square-up,\n \"cloud-showers-water\": $fa-var-cloud-showers-water,\n \"chart-bar\": $fa-var-chart-bar,\n \"bar-chart\": $fa-var-bar-chart,\n \"hands-bubbles\": $fa-var-hands-bubbles,\n \"hands-wash\": $fa-var-hands-wash,\n \"less-than-equal\": $fa-var-less-than-equal,\n \"train\": $fa-var-train,\n \"eye-low-vision\": $fa-var-eye-low-vision,\n \"low-vision\": $fa-var-low-vision,\n \"crow\": $fa-var-crow,\n \"sailboat\": $fa-var-sailboat,\n \"window-restore\": $fa-var-window-restore,\n \"square-plus\": $fa-var-square-plus,\n \"plus-square\": $fa-var-plus-square,\n \"torii-gate\": $fa-var-torii-gate,\n \"frog\": $fa-var-frog,\n \"bucket\": $fa-var-bucket,\n \"image\": $fa-var-image,\n \"microphone\": $fa-var-microphone,\n \"cow\": $fa-var-cow,\n \"caret-up\": $fa-var-caret-up,\n \"screwdriver\": $fa-var-screwdriver,\n \"folder-closed\": $fa-var-folder-closed,\n \"house-tsunami\": $fa-var-house-tsunami,\n \"square-nfi\": $fa-var-square-nfi,\n \"arrow-up-from-ground-water\": $fa-var-arrow-up-from-ground-water,\n \"martini-glass\": $fa-var-martini-glass,\n \"glass-martini-alt\": $fa-var-glass-martini-alt,\n \"rotate-left\": $fa-var-rotate-left,\n \"rotate-back\": $fa-var-rotate-back,\n \"rotate-backward\": $fa-var-rotate-backward,\n \"undo-alt\": $fa-var-undo-alt,\n \"table-columns\": $fa-var-table-columns,\n \"columns\": $fa-var-columns,\n \"lemon\": $fa-var-lemon,\n \"head-side-mask\": $fa-var-head-side-mask,\n \"handshake\": $fa-var-handshake,\n \"gem\": $fa-var-gem,\n \"dolly\": $fa-var-dolly,\n \"dolly-box\": $fa-var-dolly-box,\n \"smoking\": $fa-var-smoking,\n \"minimize\": $fa-var-minimize,\n \"compress-arrows-alt\": $fa-var-compress-arrows-alt,\n \"monument\": $fa-var-monument,\n \"snowplow\": $fa-var-snowplow,\n \"angles-right\": $fa-var-angles-right,\n \"angle-double-right\": $fa-var-angle-double-right,\n \"cannabis\": $fa-var-cannabis,\n \"circle-play\": $fa-var-circle-play,\n \"play-circle\": $fa-var-play-circle,\n \"tablets\": $fa-var-tablets,\n \"ethernet\": $fa-var-ethernet,\n \"euro-sign\": $fa-var-euro-sign,\n \"eur\": $fa-var-eur,\n \"euro\": $fa-var-euro,\n \"chair\": $fa-var-chair,\n \"circle-check\": $fa-var-circle-check,\n \"check-circle\": $fa-var-check-circle,\n \"circle-stop\": $fa-var-circle-stop,\n \"stop-circle\": $fa-var-stop-circle,\n \"compass-drafting\": $fa-var-compass-drafting,\n \"drafting-compass\": $fa-var-drafting-compass,\n \"plate-wheat\": $fa-var-plate-wheat,\n \"icicles\": $fa-var-icicles,\n \"person-shelter\": $fa-var-person-shelter,\n \"neuter\": $fa-var-neuter,\n \"id-badge\": $fa-var-id-badge,\n \"marker\": $fa-var-marker,\n \"face-laugh-beam\": $fa-var-face-laugh-beam,\n \"laugh-beam\": $fa-var-laugh-beam,\n \"helicopter-symbol\": $fa-var-helicopter-symbol,\n \"universal-access\": $fa-var-universal-access,\n \"circle-chevron-up\": $fa-var-circle-chevron-up,\n \"chevron-circle-up\": $fa-var-chevron-circle-up,\n \"lari-sign\": $fa-var-lari-sign,\n \"volcano\": $fa-var-volcano,\n \"person-walking-dashed-line-arrow-right\": $fa-var-person-walking-dashed-line-arrow-right,\n \"sterling-sign\": $fa-var-sterling-sign,\n \"gbp\": $fa-var-gbp,\n \"pound-sign\": $fa-var-pound-sign,\n \"viruses\": $fa-var-viruses,\n \"square-person-confined\": $fa-var-square-person-confined,\n \"user-tie\": $fa-var-user-tie,\n \"arrow-down-long\": $fa-var-arrow-down-long,\n \"long-arrow-down\": $fa-var-long-arrow-down,\n \"tent-arrow-down-to-line\": $fa-var-tent-arrow-down-to-line,\n \"certificate\": $fa-var-certificate,\n \"reply-all\": $fa-var-reply-all,\n \"mail-reply-all\": $fa-var-mail-reply-all,\n \"suitcase\": $fa-var-suitcase,\n \"person-skating\": $fa-var-person-skating,\n \"skating\": $fa-var-skating,\n \"filter-circle-dollar\": $fa-var-filter-circle-dollar,\n \"funnel-dollar\": $fa-var-funnel-dollar,\n \"camera-retro\": $fa-var-camera-retro,\n \"circle-arrow-down\": $fa-var-circle-arrow-down,\n \"arrow-circle-down\": $fa-var-arrow-circle-down,\n \"file-import\": $fa-var-file-import,\n \"arrow-right-to-file\": $fa-var-arrow-right-to-file,\n \"square-arrow-up-right\": $fa-var-square-arrow-up-right,\n \"external-link-square\": $fa-var-external-link-square,\n \"box-open\": $fa-var-box-open,\n \"scroll\": $fa-var-scroll,\n \"spa\": $fa-var-spa,\n \"location-pin-lock\": $fa-var-location-pin-lock,\n \"pause\": $fa-var-pause,\n \"hill-avalanche\": $fa-var-hill-avalanche,\n \"temperature-empty\": $fa-var-temperature-empty,\n \"temperature-0\": $fa-var-temperature-0,\n \"thermometer-0\": $fa-var-thermometer-0,\n \"thermometer-empty\": $fa-var-thermometer-empty,\n \"bomb\": $fa-var-bomb,\n \"registered\": $fa-var-registered,\n \"address-card\": $fa-var-address-card,\n \"contact-card\": $fa-var-contact-card,\n \"vcard\": $fa-var-vcard,\n \"scale-unbalanced-flip\": $fa-var-scale-unbalanced-flip,\n \"balance-scale-right\": $fa-var-balance-scale-right,\n \"subscript\": $fa-var-subscript,\n \"diamond-turn-right\": $fa-var-diamond-turn-right,\n \"directions\": $fa-var-directions,\n \"burst\": $fa-var-burst,\n \"house-laptop\": $fa-var-house-laptop,\n \"laptop-house\": $fa-var-laptop-house,\n \"face-tired\": $fa-var-face-tired,\n \"tired\": $fa-var-tired,\n \"money-bills\": $fa-var-money-bills,\n \"smog\": $fa-var-smog,\n \"crutch\": $fa-var-crutch,\n \"cloud-arrow-up\": $fa-var-cloud-arrow-up,\n \"cloud-upload\": $fa-var-cloud-upload,\n \"cloud-upload-alt\": $fa-var-cloud-upload-alt,\n \"palette\": $fa-var-palette,\n \"arrows-turn-right\": $fa-var-arrows-turn-right,\n \"vest\": $fa-var-vest,\n \"ferry\": $fa-var-ferry,\n \"arrows-down-to-people\": $fa-var-arrows-down-to-people,\n \"seedling\": $fa-var-seedling,\n \"sprout\": $fa-var-sprout,\n \"left-right\": $fa-var-left-right,\n \"arrows-alt-h\": $fa-var-arrows-alt-h,\n \"boxes-packing\": $fa-var-boxes-packing,\n \"circle-arrow-left\": $fa-var-circle-arrow-left,\n \"arrow-circle-left\": $fa-var-arrow-circle-left,\n \"group-arrows-rotate\": $fa-var-group-arrows-rotate,\n \"bowl-food\": $fa-var-bowl-food,\n \"candy-cane\": $fa-var-candy-cane,\n \"arrow-down-wide-short\": $fa-var-arrow-down-wide-short,\n \"sort-amount-asc\": $fa-var-sort-amount-asc,\n \"sort-amount-down\": $fa-var-sort-amount-down,\n \"cloud-bolt\": $fa-var-cloud-bolt,\n \"thunderstorm\": $fa-var-thunderstorm,\n \"text-slash\": $fa-var-text-slash,\n \"remove-format\": $fa-var-remove-format,\n \"face-smile-wink\": $fa-var-face-smile-wink,\n \"smile-wink\": $fa-var-smile-wink,\n \"file-word\": $fa-var-file-word,\n \"file-powerpoint\": $fa-var-file-powerpoint,\n \"arrows-left-right\": $fa-var-arrows-left-right,\n \"arrows-h\": $fa-var-arrows-h,\n \"house-lock\": $fa-var-house-lock,\n \"cloud-arrow-down\": $fa-var-cloud-arrow-down,\n \"cloud-download\": $fa-var-cloud-download,\n \"cloud-download-alt\": $fa-var-cloud-download-alt,\n \"children\": $fa-var-children,\n \"chalkboard\": $fa-var-chalkboard,\n \"blackboard\": $fa-var-blackboard,\n \"user-large-slash\": $fa-var-user-large-slash,\n \"user-alt-slash\": $fa-var-user-alt-slash,\n \"envelope-open\": $fa-var-envelope-open,\n \"handshake-simple-slash\": $fa-var-handshake-simple-slash,\n \"handshake-alt-slash\": $fa-var-handshake-alt-slash,\n \"mattress-pillow\": $fa-var-mattress-pillow,\n \"guarani-sign\": $fa-var-guarani-sign,\n \"arrows-rotate\": $fa-var-arrows-rotate,\n \"refresh\": $fa-var-refresh,\n \"sync\": $fa-var-sync,\n \"fire-extinguisher\": $fa-var-fire-extinguisher,\n \"cruzeiro-sign\": $fa-var-cruzeiro-sign,\n \"greater-than-equal\": $fa-var-greater-than-equal,\n \"shield-halved\": $fa-var-shield-halved,\n \"shield-alt\": $fa-var-shield-alt,\n \"book-atlas\": $fa-var-book-atlas,\n \"atlas\": $fa-var-atlas,\n \"virus\": $fa-var-virus,\n \"envelope-circle-check\": $fa-var-envelope-circle-check,\n \"layer-group\": $fa-var-layer-group,\n \"arrows-to-dot\": $fa-var-arrows-to-dot,\n \"archway\": $fa-var-archway,\n \"heart-circle-check\": $fa-var-heart-circle-check,\n \"house-chimney-crack\": $fa-var-house-chimney-crack,\n \"house-damage\": $fa-var-house-damage,\n \"file-zipper\": $fa-var-file-zipper,\n \"file-archive\": $fa-var-file-archive,\n \"square\": $fa-var-square,\n \"martini-glass-empty\": $fa-var-martini-glass-empty,\n \"glass-martini\": $fa-var-glass-martini,\n \"couch\": $fa-var-couch,\n \"cedi-sign\": $fa-var-cedi-sign,\n \"italic\": $fa-var-italic,\n \"table-cells-column-lock\": $fa-var-table-cells-column-lock,\n \"church\": $fa-var-church,\n \"comments-dollar\": $fa-var-comments-dollar,\n \"democrat\": $fa-var-democrat,\n \"z\": $fa-var-z,\n \"person-skiing\": $fa-var-person-skiing,\n \"skiing\": $fa-var-skiing,\n \"road-lock\": $fa-var-road-lock,\n \"a\": $fa-var-a,\n \"temperature-arrow-down\": $fa-var-temperature-arrow-down,\n \"temperature-down\": $fa-var-temperature-down,\n \"feather-pointed\": $fa-var-feather-pointed,\n \"feather-alt\": $fa-var-feather-alt,\n \"p\": $fa-var-p,\n \"snowflake\": $fa-var-snowflake,\n \"newspaper\": $fa-var-newspaper,\n \"rectangle-ad\": $fa-var-rectangle-ad,\n \"ad\": $fa-var-ad,\n \"circle-arrow-right\": $fa-var-circle-arrow-right,\n \"arrow-circle-right\": $fa-var-arrow-circle-right,\n \"filter-circle-xmark\": $fa-var-filter-circle-xmark,\n \"locust\": $fa-var-locust,\n \"sort\": $fa-var-sort,\n \"unsorted\": $fa-var-unsorted,\n \"list-ol\": $fa-var-list-ol,\n \"list-1-2\": $fa-var-list-1-2,\n \"list-numeric\": $fa-var-list-numeric,\n \"person-dress-burst\": $fa-var-person-dress-burst,\n \"money-check-dollar\": $fa-var-money-check-dollar,\n \"money-check-alt\": $fa-var-money-check-alt,\n \"vector-square\": $fa-var-vector-square,\n \"bread-slice\": $fa-var-bread-slice,\n \"language\": $fa-var-language,\n \"face-kiss-wink-heart\": $fa-var-face-kiss-wink-heart,\n \"kiss-wink-heart\": $fa-var-kiss-wink-heart,\n \"filter\": $fa-var-filter,\n \"question\": $fa-var-question,\n \"file-signature\": $fa-var-file-signature,\n \"up-down-left-right\": $fa-var-up-down-left-right,\n \"arrows-alt\": $fa-var-arrows-alt,\n \"house-chimney-user\": $fa-var-house-chimney-user,\n \"hand-holding-heart\": $fa-var-hand-holding-heart,\n \"puzzle-piece\": $fa-var-puzzle-piece,\n \"money-check\": $fa-var-money-check,\n \"star-half-stroke\": $fa-var-star-half-stroke,\n \"star-half-alt\": $fa-var-star-half-alt,\n \"code\": $fa-var-code,\n \"whiskey-glass\": $fa-var-whiskey-glass,\n \"glass-whiskey\": $fa-var-glass-whiskey,\n \"building-circle-exclamation\": $fa-var-building-circle-exclamation,\n \"magnifying-glass-chart\": $fa-var-magnifying-glass-chart,\n \"arrow-up-right-from-square\": $fa-var-arrow-up-right-from-square,\n \"external-link\": $fa-var-external-link,\n \"cubes-stacked\": $fa-var-cubes-stacked,\n \"won-sign\": $fa-var-won-sign,\n \"krw\": $fa-var-krw,\n \"won\": $fa-var-won,\n \"virus-covid\": $fa-var-virus-covid,\n \"austral-sign\": $fa-var-austral-sign,\n \"f\": $fa-var-f,\n \"leaf\": $fa-var-leaf,\n \"road\": $fa-var-road,\n \"taxi\": $fa-var-taxi,\n \"cab\": $fa-var-cab,\n \"person-circle-plus\": $fa-var-person-circle-plus,\n \"chart-pie\": $fa-var-chart-pie,\n \"pie-chart\": $fa-var-pie-chart,\n \"bolt-lightning\": $fa-var-bolt-lightning,\n \"sack-xmark\": $fa-var-sack-xmark,\n \"file-excel\": $fa-var-file-excel,\n \"file-contract\": $fa-var-file-contract,\n \"fish-fins\": $fa-var-fish-fins,\n \"building-flag\": $fa-var-building-flag,\n \"face-grin-beam\": $fa-var-face-grin-beam,\n \"grin-beam\": $fa-var-grin-beam,\n \"object-ungroup\": $fa-var-object-ungroup,\n \"poop\": $fa-var-poop,\n \"location-pin\": $fa-var-location-pin,\n \"map-marker\": $fa-var-map-marker,\n \"kaaba\": $fa-var-kaaba,\n \"toilet-paper\": $fa-var-toilet-paper,\n \"helmet-safety\": $fa-var-helmet-safety,\n \"hard-hat\": $fa-var-hard-hat,\n \"hat-hard\": $fa-var-hat-hard,\n \"eject\": $fa-var-eject,\n \"circle-right\": $fa-var-circle-right,\n \"arrow-alt-circle-right\": $fa-var-arrow-alt-circle-right,\n \"plane-circle-check\": $fa-var-plane-circle-check,\n \"face-rolling-eyes\": $fa-var-face-rolling-eyes,\n \"meh-rolling-eyes\": $fa-var-meh-rolling-eyes,\n \"object-group\": $fa-var-object-group,\n \"chart-line\": $fa-var-chart-line,\n \"line-chart\": $fa-var-line-chart,\n \"mask-ventilator\": $fa-var-mask-ventilator,\n \"arrow-right\": $fa-var-arrow-right,\n \"signs-post\": $fa-var-signs-post,\n \"map-signs\": $fa-var-map-signs,\n \"cash-register\": $fa-var-cash-register,\n \"person-circle-question\": $fa-var-person-circle-question,\n \"h\": $fa-var-h,\n \"tarp\": $fa-var-tarp,\n \"screwdriver-wrench\": $fa-var-screwdriver-wrench,\n \"tools\": $fa-var-tools,\n \"arrows-to-eye\": $fa-var-arrows-to-eye,\n \"plug-circle-bolt\": $fa-var-plug-circle-bolt,\n \"heart\": $fa-var-heart,\n \"mars-and-venus\": $fa-var-mars-and-venus,\n \"house-user\": $fa-var-house-user,\n \"home-user\": $fa-var-home-user,\n \"dumpster-fire\": $fa-var-dumpster-fire,\n \"house-crack\": $fa-var-house-crack,\n \"martini-glass-citrus\": $fa-var-martini-glass-citrus,\n \"cocktail\": $fa-var-cocktail,\n \"face-surprise\": $fa-var-face-surprise,\n \"surprise\": $fa-var-surprise,\n \"bottle-water\": $fa-var-bottle-water,\n \"circle-pause\": $fa-var-circle-pause,\n \"pause-circle\": $fa-var-pause-circle,\n \"toilet-paper-slash\": $fa-var-toilet-paper-slash,\n \"apple-whole\": $fa-var-apple-whole,\n \"apple-alt\": $fa-var-apple-alt,\n \"kitchen-set\": $fa-var-kitchen-set,\n \"r\": $fa-var-r,\n \"temperature-quarter\": $fa-var-temperature-quarter,\n \"temperature-1\": $fa-var-temperature-1,\n \"thermometer-1\": $fa-var-thermometer-1,\n \"thermometer-quarter\": $fa-var-thermometer-quarter,\n \"cube\": $fa-var-cube,\n \"bitcoin-sign\": $fa-var-bitcoin-sign,\n \"shield-dog\": $fa-var-shield-dog,\n \"solar-panel\": $fa-var-solar-panel,\n \"lock-open\": $fa-var-lock-open,\n \"elevator\": $fa-var-elevator,\n \"money-bill-transfer\": $fa-var-money-bill-transfer,\n \"money-bill-trend-up\": $fa-var-money-bill-trend-up,\n \"house-flood-water-circle-arrow-right\": $fa-var-house-flood-water-circle-arrow-right,\n \"square-poll-horizontal\": $fa-var-square-poll-horizontal,\n \"poll-h\": $fa-var-poll-h,\n \"circle\": $fa-var-circle,\n \"backward-fast\": $fa-var-backward-fast,\n \"fast-backward\": $fa-var-fast-backward,\n \"recycle\": $fa-var-recycle,\n \"user-astronaut\": $fa-var-user-astronaut,\n \"plane-slash\": $fa-var-plane-slash,\n \"trademark\": $fa-var-trademark,\n \"basketball\": $fa-var-basketball,\n \"basketball-ball\": $fa-var-basketball-ball,\n \"satellite-dish\": $fa-var-satellite-dish,\n \"circle-up\": $fa-var-circle-up,\n \"arrow-alt-circle-up\": $fa-var-arrow-alt-circle-up,\n \"mobile-screen-button\": $fa-var-mobile-screen-button,\n \"mobile-alt\": $fa-var-mobile-alt,\n \"volume-high\": $fa-var-volume-high,\n \"volume-up\": $fa-var-volume-up,\n \"users-rays\": $fa-var-users-rays,\n \"wallet\": $fa-var-wallet,\n \"clipboard-check\": $fa-var-clipboard-check,\n \"file-audio\": $fa-var-file-audio,\n \"burger\": $fa-var-burger,\n \"hamburger\": $fa-var-hamburger,\n \"wrench\": $fa-var-wrench,\n \"bugs\": $fa-var-bugs,\n \"rupee-sign\": $fa-var-rupee-sign,\n \"rupee\": $fa-var-rupee,\n \"file-image\": $fa-var-file-image,\n \"circle-question\": $fa-var-circle-question,\n \"question-circle\": $fa-var-question-circle,\n \"plane-departure\": $fa-var-plane-departure,\n \"handshake-slash\": $fa-var-handshake-slash,\n \"book-bookmark\": $fa-var-book-bookmark,\n \"code-branch\": $fa-var-code-branch,\n \"hat-cowboy\": $fa-var-hat-cowboy,\n \"bridge\": $fa-var-bridge,\n \"phone-flip\": $fa-var-phone-flip,\n \"phone-alt\": $fa-var-phone-alt,\n \"truck-front\": $fa-var-truck-front,\n \"cat\": $fa-var-cat,\n \"anchor-circle-exclamation\": $fa-var-anchor-circle-exclamation,\n \"truck-field\": $fa-var-truck-field,\n \"route\": $fa-var-route,\n \"clipboard-question\": $fa-var-clipboard-question,\n \"panorama\": $fa-var-panorama,\n \"comment-medical\": $fa-var-comment-medical,\n \"teeth-open\": $fa-var-teeth-open,\n \"file-circle-minus\": $fa-var-file-circle-minus,\n \"tags\": $fa-var-tags,\n \"wine-glass\": $fa-var-wine-glass,\n \"forward-fast\": $fa-var-forward-fast,\n \"fast-forward\": $fa-var-fast-forward,\n \"face-meh-blank\": $fa-var-face-meh-blank,\n \"meh-blank\": $fa-var-meh-blank,\n \"square-parking\": $fa-var-square-parking,\n \"parking\": $fa-var-parking,\n \"house-signal\": $fa-var-house-signal,\n \"bars-progress\": $fa-var-bars-progress,\n \"tasks-alt\": $fa-var-tasks-alt,\n \"faucet-drip\": $fa-var-faucet-drip,\n \"cart-flatbed\": $fa-var-cart-flatbed,\n \"dolly-flatbed\": $fa-var-dolly-flatbed,\n \"ban-smoking\": $fa-var-ban-smoking,\n \"smoking-ban\": $fa-var-smoking-ban,\n \"terminal\": $fa-var-terminal,\n \"mobile-button\": $fa-var-mobile-button,\n \"house-medical-flag\": $fa-var-house-medical-flag,\n \"basket-shopping\": $fa-var-basket-shopping,\n \"shopping-basket\": $fa-var-shopping-basket,\n \"tape\": $fa-var-tape,\n \"bus-simple\": $fa-var-bus-simple,\n \"bus-alt\": $fa-var-bus-alt,\n \"eye\": $fa-var-eye,\n \"face-sad-cry\": $fa-var-face-sad-cry,\n \"sad-cry\": $fa-var-sad-cry,\n \"audio-description\": $fa-var-audio-description,\n \"person-military-to-person\": $fa-var-person-military-to-person,\n \"file-shield\": $fa-var-file-shield,\n \"user-slash\": $fa-var-user-slash,\n \"pen\": $fa-var-pen,\n \"tower-observation\": $fa-var-tower-observation,\n \"file-code\": $fa-var-file-code,\n \"signal\": $fa-var-signal,\n \"signal-5\": $fa-var-signal-5,\n \"signal-perfect\": $fa-var-signal-perfect,\n \"bus\": $fa-var-bus,\n \"heart-circle-xmark\": $fa-var-heart-circle-xmark,\n \"house-chimney\": $fa-var-house-chimney,\n \"home-lg\": $fa-var-home-lg,\n \"window-maximize\": $fa-var-window-maximize,\n \"face-frown\": $fa-var-face-frown,\n \"frown\": $fa-var-frown,\n \"prescription\": $fa-var-prescription,\n \"shop\": $fa-var-shop,\n \"store-alt\": $fa-var-store-alt,\n \"floppy-disk\": $fa-var-floppy-disk,\n \"save\": $fa-var-save,\n \"vihara\": $fa-var-vihara,\n \"scale-unbalanced\": $fa-var-scale-unbalanced,\n \"balance-scale-left\": $fa-var-balance-scale-left,\n \"sort-up\": $fa-var-sort-up,\n \"sort-asc\": $fa-var-sort-asc,\n \"comment-dots\": $fa-var-comment-dots,\n \"commenting\": $fa-var-commenting,\n \"plant-wilt\": $fa-var-plant-wilt,\n \"diamond\": $fa-var-diamond,\n \"face-grin-squint\": $fa-var-face-grin-squint,\n \"grin-squint\": $fa-var-grin-squint,\n \"hand-holding-dollar\": $fa-var-hand-holding-dollar,\n \"hand-holding-usd\": $fa-var-hand-holding-usd,\n \"bacterium\": $fa-var-bacterium,\n \"hand-pointer\": $fa-var-hand-pointer,\n \"drum-steelpan\": $fa-var-drum-steelpan,\n \"hand-scissors\": $fa-var-hand-scissors,\n \"hands-praying\": $fa-var-hands-praying,\n \"praying-hands\": $fa-var-praying-hands,\n \"arrow-rotate-right\": $fa-var-arrow-rotate-right,\n \"arrow-right-rotate\": $fa-var-arrow-right-rotate,\n \"arrow-rotate-forward\": $fa-var-arrow-rotate-forward,\n \"redo\": $fa-var-redo,\n \"biohazard\": $fa-var-biohazard,\n \"location-crosshairs\": $fa-var-location-crosshairs,\n \"location\": $fa-var-location,\n \"mars-double\": $fa-var-mars-double,\n \"child-dress\": $fa-var-child-dress,\n \"users-between-lines\": $fa-var-users-between-lines,\n \"lungs-virus\": $fa-var-lungs-virus,\n \"face-grin-tears\": $fa-var-face-grin-tears,\n \"grin-tears\": $fa-var-grin-tears,\n \"phone\": $fa-var-phone,\n \"calendar-xmark\": $fa-var-calendar-xmark,\n \"calendar-times\": $fa-var-calendar-times,\n \"child-reaching\": $fa-var-child-reaching,\n \"head-side-virus\": $fa-var-head-side-virus,\n \"user-gear\": $fa-var-user-gear,\n \"user-cog\": $fa-var-user-cog,\n \"arrow-up-1-9\": $fa-var-arrow-up-1-9,\n \"sort-numeric-up\": $fa-var-sort-numeric-up,\n \"door-closed\": $fa-var-door-closed,\n \"shield-virus\": $fa-var-shield-virus,\n \"dice-six\": $fa-var-dice-six,\n \"mosquito-net\": $fa-var-mosquito-net,\n \"bridge-water\": $fa-var-bridge-water,\n \"person-booth\": $fa-var-person-booth,\n \"text-width\": $fa-var-text-width,\n \"hat-wizard\": $fa-var-hat-wizard,\n \"pen-fancy\": $fa-var-pen-fancy,\n \"person-digging\": $fa-var-person-digging,\n \"digging\": $fa-var-digging,\n \"trash\": $fa-var-trash,\n \"gauge-simple\": $fa-var-gauge-simple,\n \"gauge-simple-med\": $fa-var-gauge-simple-med,\n \"tachometer-average\": $fa-var-tachometer-average,\n \"book-medical\": $fa-var-book-medical,\n \"poo\": $fa-var-poo,\n \"quote-right\": $fa-var-quote-right,\n \"quote-right-alt\": $fa-var-quote-right-alt,\n \"shirt\": $fa-var-shirt,\n \"t-shirt\": $fa-var-t-shirt,\n \"tshirt\": $fa-var-tshirt,\n \"cubes\": $fa-var-cubes,\n \"divide\": $fa-var-divide,\n \"tenge-sign\": $fa-var-tenge-sign,\n \"tenge\": $fa-var-tenge,\n \"headphones\": $fa-var-headphones,\n \"hands-holding\": $fa-var-hands-holding,\n \"hands-clapping\": $fa-var-hands-clapping,\n \"republican\": $fa-var-republican,\n \"arrow-left\": $fa-var-arrow-left,\n \"person-circle-xmark\": $fa-var-person-circle-xmark,\n \"ruler\": $fa-var-ruler,\n \"align-left\": $fa-var-align-left,\n \"dice-d6\": $fa-var-dice-d6,\n \"restroom\": $fa-var-restroom,\n \"j\": $fa-var-j,\n \"users-viewfinder\": $fa-var-users-viewfinder,\n \"file-video\": $fa-var-file-video,\n \"up-right-from-square\": $fa-var-up-right-from-square,\n \"external-link-alt\": $fa-var-external-link-alt,\n \"table-cells\": $fa-var-table-cells,\n \"th\": $fa-var-th,\n \"file-pdf\": $fa-var-file-pdf,\n \"book-bible\": $fa-var-book-bible,\n \"bible\": $fa-var-bible,\n \"o\": $fa-var-o,\n \"suitcase-medical\": $fa-var-suitcase-medical,\n \"medkit\": $fa-var-medkit,\n \"user-secret\": $fa-var-user-secret,\n \"otter\": $fa-var-otter,\n \"person-dress\": $fa-var-person-dress,\n \"female\": $fa-var-female,\n \"comment-dollar\": $fa-var-comment-dollar,\n \"business-time\": $fa-var-business-time,\n \"briefcase-clock\": $fa-var-briefcase-clock,\n \"table-cells-large\": $fa-var-table-cells-large,\n \"th-large\": $fa-var-th-large,\n \"book-tanakh\": $fa-var-book-tanakh,\n \"tanakh\": $fa-var-tanakh,\n \"phone-volume\": $fa-var-phone-volume,\n \"volume-control-phone\": $fa-var-volume-control-phone,\n \"hat-cowboy-side\": $fa-var-hat-cowboy-side,\n \"clipboard-user\": $fa-var-clipboard-user,\n \"child\": $fa-var-child,\n \"lira-sign\": $fa-var-lira-sign,\n \"satellite\": $fa-var-satellite,\n \"plane-lock\": $fa-var-plane-lock,\n \"tag\": $fa-var-tag,\n \"comment\": $fa-var-comment,\n \"cake-candles\": $fa-var-cake-candles,\n \"birthday-cake\": $fa-var-birthday-cake,\n \"cake\": $fa-var-cake,\n \"envelope\": $fa-var-envelope,\n \"angles-up\": $fa-var-angles-up,\n \"angle-double-up\": $fa-var-angle-double-up,\n \"paperclip\": $fa-var-paperclip,\n \"arrow-right-to-city\": $fa-var-arrow-right-to-city,\n \"ribbon\": $fa-var-ribbon,\n \"lungs\": $fa-var-lungs,\n \"arrow-up-9-1\": $fa-var-arrow-up-9-1,\n \"sort-numeric-up-alt\": $fa-var-sort-numeric-up-alt,\n \"litecoin-sign\": $fa-var-litecoin-sign,\n \"border-none\": $fa-var-border-none,\n \"circle-nodes\": $fa-var-circle-nodes,\n \"parachute-box\": $fa-var-parachute-box,\n \"indent\": $fa-var-indent,\n \"truck-field-un\": $fa-var-truck-field-un,\n \"hourglass\": $fa-var-hourglass,\n \"hourglass-empty\": $fa-var-hourglass-empty,\n \"mountain\": $fa-var-mountain,\n \"user-doctor\": $fa-var-user-doctor,\n \"user-md\": $fa-var-user-md,\n \"circle-info\": $fa-var-circle-info,\n \"info-circle\": $fa-var-info-circle,\n \"cloud-meatball\": $fa-var-cloud-meatball,\n \"camera\": $fa-var-camera,\n \"camera-alt\": $fa-var-camera-alt,\n \"square-virus\": $fa-var-square-virus,\n \"meteor\": $fa-var-meteor,\n \"car-on\": $fa-var-car-on,\n \"sleigh\": $fa-var-sleigh,\n \"arrow-down-1-9\": $fa-var-arrow-down-1-9,\n \"sort-numeric-asc\": $fa-var-sort-numeric-asc,\n \"sort-numeric-down\": $fa-var-sort-numeric-down,\n \"hand-holding-droplet\": $fa-var-hand-holding-droplet,\n \"hand-holding-water\": $fa-var-hand-holding-water,\n \"water\": $fa-var-water,\n \"calendar-check\": $fa-var-calendar-check,\n \"braille\": $fa-var-braille,\n \"prescription-bottle-medical\": $fa-var-prescription-bottle-medical,\n \"prescription-bottle-alt\": $fa-var-prescription-bottle-alt,\n \"landmark\": $fa-var-landmark,\n \"truck\": $fa-var-truck,\n \"crosshairs\": $fa-var-crosshairs,\n \"person-cane\": $fa-var-person-cane,\n \"tent\": $fa-var-tent,\n \"vest-patches\": $fa-var-vest-patches,\n \"check-double\": $fa-var-check-double,\n \"arrow-down-a-z\": $fa-var-arrow-down-a-z,\n \"sort-alpha-asc\": $fa-var-sort-alpha-asc,\n \"sort-alpha-down\": $fa-var-sort-alpha-down,\n \"money-bill-wheat\": $fa-var-money-bill-wheat,\n \"cookie\": $fa-var-cookie,\n \"arrow-rotate-left\": $fa-var-arrow-rotate-left,\n \"arrow-left-rotate\": $fa-var-arrow-left-rotate,\n \"arrow-rotate-back\": $fa-var-arrow-rotate-back,\n \"arrow-rotate-backward\": $fa-var-arrow-rotate-backward,\n \"undo\": $fa-var-undo,\n \"hard-drive\": $fa-var-hard-drive,\n \"hdd\": $fa-var-hdd,\n \"face-grin-squint-tears\": $fa-var-face-grin-squint-tears,\n \"grin-squint-tears\": $fa-var-grin-squint-tears,\n \"dumbbell\": $fa-var-dumbbell,\n \"rectangle-list\": $fa-var-rectangle-list,\n \"list-alt\": $fa-var-list-alt,\n \"tarp-droplet\": $fa-var-tarp-droplet,\n \"house-medical-circle-check\": $fa-var-house-medical-circle-check,\n \"person-skiing-nordic\": $fa-var-person-skiing-nordic,\n \"skiing-nordic\": $fa-var-skiing-nordic,\n \"calendar-plus\": $fa-var-calendar-plus,\n \"plane-arrival\": $fa-var-plane-arrival,\n \"circle-left\": $fa-var-circle-left,\n \"arrow-alt-circle-left\": $fa-var-arrow-alt-circle-left,\n \"train-subway\": $fa-var-train-subway,\n \"subway\": $fa-var-subway,\n \"chart-gantt\": $fa-var-chart-gantt,\n \"indian-rupee-sign\": $fa-var-indian-rupee-sign,\n \"indian-rupee\": $fa-var-indian-rupee,\n \"inr\": $fa-var-inr,\n \"crop-simple\": $fa-var-crop-simple,\n \"crop-alt\": $fa-var-crop-alt,\n \"money-bill-1\": $fa-var-money-bill-1,\n \"money-bill-alt\": $fa-var-money-bill-alt,\n \"left-long\": $fa-var-left-long,\n \"long-arrow-alt-left\": $fa-var-long-arrow-alt-left,\n \"dna\": $fa-var-dna,\n \"virus-slash\": $fa-var-virus-slash,\n \"minus\": $fa-var-minus,\n \"subtract\": $fa-var-subtract,\n \"chess\": $fa-var-chess,\n \"arrow-left-long\": $fa-var-arrow-left-long,\n \"long-arrow-left\": $fa-var-long-arrow-left,\n \"plug-circle-check\": $fa-var-plug-circle-check,\n \"street-view\": $fa-var-street-view,\n \"franc-sign\": $fa-var-franc-sign,\n \"volume-off\": $fa-var-volume-off,\n \"hands-asl-interpreting\": $fa-var-hands-asl-interpreting,\n \"american-sign-language-interpreting\": $fa-var-american-sign-language-interpreting,\n \"asl-interpreting\": $fa-var-asl-interpreting,\n \"hands-american-sign-language-interpreting\": $fa-var-hands-american-sign-language-interpreting,\n \"gear\": $fa-var-gear,\n \"cog\": $fa-var-cog,\n \"droplet-slash\": $fa-var-droplet-slash,\n \"tint-slash\": $fa-var-tint-slash,\n \"mosque\": $fa-var-mosque,\n \"mosquito\": $fa-var-mosquito,\n \"star-of-david\": $fa-var-star-of-david,\n \"person-military-rifle\": $fa-var-person-military-rifle,\n \"cart-shopping\": $fa-var-cart-shopping,\n \"shopping-cart\": $fa-var-shopping-cart,\n \"vials\": $fa-var-vials,\n \"plug-circle-plus\": $fa-var-plug-circle-plus,\n \"place-of-worship\": $fa-var-place-of-worship,\n \"grip-vertical\": $fa-var-grip-vertical,\n \"arrow-turn-up\": $fa-var-arrow-turn-up,\n \"level-up\": $fa-var-level-up,\n \"u\": $fa-var-u,\n \"square-root-variable\": $fa-var-square-root-variable,\n \"square-root-alt\": $fa-var-square-root-alt,\n \"clock\": $fa-var-clock,\n \"clock-four\": $fa-var-clock-four,\n \"backward-step\": $fa-var-backward-step,\n \"step-backward\": $fa-var-step-backward,\n \"pallet\": $fa-var-pallet,\n \"faucet\": $fa-var-faucet,\n \"baseball-bat-ball\": $fa-var-baseball-bat-ball,\n \"s\": $fa-var-s,\n \"timeline\": $fa-var-timeline,\n \"keyboard\": $fa-var-keyboard,\n \"caret-down\": $fa-var-caret-down,\n \"house-chimney-medical\": $fa-var-house-chimney-medical,\n \"clinic-medical\": $fa-var-clinic-medical,\n \"temperature-three-quarters\": $fa-var-temperature-three-quarters,\n \"temperature-3\": $fa-var-temperature-3,\n \"thermometer-3\": $fa-var-thermometer-3,\n \"thermometer-three-quarters\": $fa-var-thermometer-three-quarters,\n \"mobile-screen\": $fa-var-mobile-screen,\n \"mobile-android-alt\": $fa-var-mobile-android-alt,\n \"plane-up\": $fa-var-plane-up,\n \"piggy-bank\": $fa-var-piggy-bank,\n \"battery-half\": $fa-var-battery-half,\n \"battery-3\": $fa-var-battery-3,\n \"mountain-city\": $fa-var-mountain-city,\n \"coins\": $fa-var-coins,\n \"khanda\": $fa-var-khanda,\n \"sliders\": $fa-var-sliders,\n \"sliders-h\": $fa-var-sliders-h,\n \"folder-tree\": $fa-var-folder-tree,\n \"network-wired\": $fa-var-network-wired,\n \"map-pin\": $fa-var-map-pin,\n \"hamsa\": $fa-var-hamsa,\n \"cent-sign\": $fa-var-cent-sign,\n \"flask\": $fa-var-flask,\n \"person-pregnant\": $fa-var-person-pregnant,\n \"wand-sparkles\": $fa-var-wand-sparkles,\n \"ellipsis-vertical\": $fa-var-ellipsis-vertical,\n \"ellipsis-v\": $fa-var-ellipsis-v,\n \"ticket\": $fa-var-ticket,\n \"power-off\": $fa-var-power-off,\n \"right-long\": $fa-var-right-long,\n \"long-arrow-alt-right\": $fa-var-long-arrow-alt-right,\n \"flag-usa\": $fa-var-flag-usa,\n \"laptop-file\": $fa-var-laptop-file,\n \"tty\": $fa-var-tty,\n \"teletype\": $fa-var-teletype,\n \"diagram-next\": $fa-var-diagram-next,\n \"person-rifle\": $fa-var-person-rifle,\n \"house-medical-circle-exclamation\": $fa-var-house-medical-circle-exclamation,\n \"closed-captioning\": $fa-var-closed-captioning,\n \"person-hiking\": $fa-var-person-hiking,\n \"hiking\": $fa-var-hiking,\n \"venus-double\": $fa-var-venus-double,\n \"images\": $fa-var-images,\n \"calculator\": $fa-var-calculator,\n \"people-pulling\": $fa-var-people-pulling,\n \"n\": $fa-var-n,\n \"cable-car\": $fa-var-cable-car,\n \"tram\": $fa-var-tram,\n \"cloud-rain\": $fa-var-cloud-rain,\n \"building-circle-xmark\": $fa-var-building-circle-xmark,\n \"ship\": $fa-var-ship,\n \"arrows-down-to-line\": $fa-var-arrows-down-to-line,\n \"download\": $fa-var-download,\n \"face-grin\": $fa-var-face-grin,\n \"grin\": $fa-var-grin,\n \"delete-left\": $fa-var-delete-left,\n \"backspace\": $fa-var-backspace,\n \"eye-dropper\": $fa-var-eye-dropper,\n \"eye-dropper-empty\": $fa-var-eye-dropper-empty,\n \"eyedropper\": $fa-var-eyedropper,\n \"file-circle-check\": $fa-var-file-circle-check,\n \"forward\": $fa-var-forward,\n \"mobile\": $fa-var-mobile,\n \"mobile-android\": $fa-var-mobile-android,\n \"mobile-phone\": $fa-var-mobile-phone,\n \"face-meh\": $fa-var-face-meh,\n \"meh\": $fa-var-meh,\n \"align-center\": $fa-var-align-center,\n \"book-skull\": $fa-var-book-skull,\n \"book-dead\": $fa-var-book-dead,\n \"id-card\": $fa-var-id-card,\n \"drivers-license\": $fa-var-drivers-license,\n \"outdent\": $fa-var-outdent,\n \"dedent\": $fa-var-dedent,\n \"heart-circle-exclamation\": $fa-var-heart-circle-exclamation,\n \"house\": $fa-var-house,\n \"home\": $fa-var-home,\n \"home-alt\": $fa-var-home-alt,\n \"home-lg-alt\": $fa-var-home-lg-alt,\n \"calendar-week\": $fa-var-calendar-week,\n \"laptop-medical\": $fa-var-laptop-medical,\n \"b\": $fa-var-b,\n \"file-medical\": $fa-var-file-medical,\n \"dice-one\": $fa-var-dice-one,\n \"kiwi-bird\": $fa-var-kiwi-bird,\n \"arrow-right-arrow-left\": $fa-var-arrow-right-arrow-left,\n \"exchange\": $fa-var-exchange,\n \"rotate-right\": $fa-var-rotate-right,\n \"redo-alt\": $fa-var-redo-alt,\n \"rotate-forward\": $fa-var-rotate-forward,\n \"utensils\": $fa-var-utensils,\n \"cutlery\": $fa-var-cutlery,\n \"arrow-up-wide-short\": $fa-var-arrow-up-wide-short,\n \"sort-amount-up\": $fa-var-sort-amount-up,\n \"mill-sign\": $fa-var-mill-sign,\n \"bowl-rice\": $fa-var-bowl-rice,\n \"skull\": $fa-var-skull,\n \"tower-broadcast\": $fa-var-tower-broadcast,\n \"broadcast-tower\": $fa-var-broadcast-tower,\n \"truck-pickup\": $fa-var-truck-pickup,\n \"up-long\": $fa-var-up-long,\n \"long-arrow-alt-up\": $fa-var-long-arrow-alt-up,\n \"stop\": $fa-var-stop,\n \"code-merge\": $fa-var-code-merge,\n \"upload\": $fa-var-upload,\n \"hurricane\": $fa-var-hurricane,\n \"mound\": $fa-var-mound,\n \"toilet-portable\": $fa-var-toilet-portable,\n \"compact-disc\": $fa-var-compact-disc,\n \"file-arrow-down\": $fa-var-file-arrow-down,\n \"file-download\": $fa-var-file-download,\n \"caravan\": $fa-var-caravan,\n \"shield-cat\": $fa-var-shield-cat,\n \"bolt\": $fa-var-bolt,\n \"zap\": $fa-var-zap,\n \"glass-water\": $fa-var-glass-water,\n \"oil-well\": $fa-var-oil-well,\n \"vault\": $fa-var-vault,\n \"mars\": $fa-var-mars,\n \"toilet\": $fa-var-toilet,\n \"plane-circle-xmark\": $fa-var-plane-circle-xmark,\n \"yen-sign\": $fa-var-yen-sign,\n \"cny\": $fa-var-cny,\n \"jpy\": $fa-var-jpy,\n \"rmb\": $fa-var-rmb,\n \"yen\": $fa-var-yen,\n \"ruble-sign\": $fa-var-ruble-sign,\n \"rouble\": $fa-var-rouble,\n \"rub\": $fa-var-rub,\n \"ruble\": $fa-var-ruble,\n \"sun\": $fa-var-sun,\n \"guitar\": $fa-var-guitar,\n \"face-laugh-wink\": $fa-var-face-laugh-wink,\n \"laugh-wink\": $fa-var-laugh-wink,\n \"horse-head\": $fa-var-horse-head,\n \"bore-hole\": $fa-var-bore-hole,\n \"industry\": $fa-var-industry,\n \"circle-down\": $fa-var-circle-down,\n \"arrow-alt-circle-down\": $fa-var-arrow-alt-circle-down,\n \"arrows-turn-to-dots\": $fa-var-arrows-turn-to-dots,\n \"florin-sign\": $fa-var-florin-sign,\n \"arrow-down-short-wide\": $fa-var-arrow-down-short-wide,\n \"sort-amount-desc\": $fa-var-sort-amount-desc,\n \"sort-amount-down-alt\": $fa-var-sort-amount-down-alt,\n \"less-than\": $fa-var-less-than,\n \"angle-down\": $fa-var-angle-down,\n \"car-tunnel\": $fa-var-car-tunnel,\n \"head-side-cough\": $fa-var-head-side-cough,\n \"grip-lines\": $fa-var-grip-lines,\n \"thumbs-down\": $fa-var-thumbs-down,\n \"user-lock\": $fa-var-user-lock,\n \"arrow-right-long\": $fa-var-arrow-right-long,\n \"long-arrow-right\": $fa-var-long-arrow-right,\n \"anchor-circle-xmark\": $fa-var-anchor-circle-xmark,\n \"ellipsis\": $fa-var-ellipsis,\n \"ellipsis-h\": $fa-var-ellipsis-h,\n \"chess-pawn\": $fa-var-chess-pawn,\n \"kit-medical\": $fa-var-kit-medical,\n \"first-aid\": $fa-var-first-aid,\n \"person-through-window\": $fa-var-person-through-window,\n \"toolbox\": $fa-var-toolbox,\n \"hands-holding-circle\": $fa-var-hands-holding-circle,\n \"bug\": $fa-var-bug,\n \"credit-card\": $fa-var-credit-card,\n \"credit-card-alt\": $fa-var-credit-card-alt,\n \"car\": $fa-var-car,\n \"automobile\": $fa-var-automobile,\n \"hand-holding-hand\": $fa-var-hand-holding-hand,\n \"book-open-reader\": $fa-var-book-open-reader,\n \"book-reader\": $fa-var-book-reader,\n \"mountain-sun\": $fa-var-mountain-sun,\n \"arrows-left-right-to-line\": $fa-var-arrows-left-right-to-line,\n \"dice-d20\": $fa-var-dice-d20,\n \"truck-droplet\": $fa-var-truck-droplet,\n \"file-circle-xmark\": $fa-var-file-circle-xmark,\n \"temperature-arrow-up\": $fa-var-temperature-arrow-up,\n \"temperature-up\": $fa-var-temperature-up,\n \"medal\": $fa-var-medal,\n \"bed\": $fa-var-bed,\n \"square-h\": $fa-var-square-h,\n \"h-square\": $fa-var-h-square,\n \"podcast\": $fa-var-podcast,\n \"temperature-full\": $fa-var-temperature-full,\n \"temperature-4\": $fa-var-temperature-4,\n \"thermometer-4\": $fa-var-thermometer-4,\n \"thermometer-full\": $fa-var-thermometer-full,\n \"bell\": $fa-var-bell,\n \"superscript\": $fa-var-superscript,\n \"plug-circle-xmark\": $fa-var-plug-circle-xmark,\n \"star-of-life\": $fa-var-star-of-life,\n \"phone-slash\": $fa-var-phone-slash,\n \"paint-roller\": $fa-var-paint-roller,\n \"handshake-angle\": $fa-var-handshake-angle,\n \"hands-helping\": $fa-var-hands-helping,\n \"location-dot\": $fa-var-location-dot,\n \"map-marker-alt\": $fa-var-map-marker-alt,\n \"file\": $fa-var-file,\n \"greater-than\": $fa-var-greater-than,\n \"person-swimming\": $fa-var-person-swimming,\n \"swimmer\": $fa-var-swimmer,\n \"arrow-down\": $fa-var-arrow-down,\n \"droplet\": $fa-var-droplet,\n \"tint\": $fa-var-tint,\n \"eraser\": $fa-var-eraser,\n \"earth-americas\": $fa-var-earth-americas,\n \"earth\": $fa-var-earth,\n \"earth-america\": $fa-var-earth-america,\n \"globe-americas\": $fa-var-globe-americas,\n \"person-burst\": $fa-var-person-burst,\n \"dove\": $fa-var-dove,\n \"battery-empty\": $fa-var-battery-empty,\n \"battery-0\": $fa-var-battery-0,\n \"socks\": $fa-var-socks,\n \"inbox\": $fa-var-inbox,\n \"section\": $fa-var-section,\n \"gauge-high\": $fa-var-gauge-high,\n \"tachometer-alt\": $fa-var-tachometer-alt,\n \"tachometer-alt-fast\": $fa-var-tachometer-alt-fast,\n \"envelope-open-text\": $fa-var-envelope-open-text,\n \"hospital\": $fa-var-hospital,\n \"hospital-alt\": $fa-var-hospital-alt,\n \"hospital-wide\": $fa-var-hospital-wide,\n \"wine-bottle\": $fa-var-wine-bottle,\n \"chess-rook\": $fa-var-chess-rook,\n \"bars-staggered\": $fa-var-bars-staggered,\n \"reorder\": $fa-var-reorder,\n \"stream\": $fa-var-stream,\n \"dharmachakra\": $fa-var-dharmachakra,\n \"hotdog\": $fa-var-hotdog,\n \"person-walking-with-cane\": $fa-var-person-walking-with-cane,\n \"blind\": $fa-var-blind,\n \"drum\": $fa-var-drum,\n \"ice-cream\": $fa-var-ice-cream,\n \"heart-circle-bolt\": $fa-var-heart-circle-bolt,\n \"fax\": $fa-var-fax,\n \"paragraph\": $fa-var-paragraph,\n \"check-to-slot\": $fa-var-check-to-slot,\n \"vote-yea\": $fa-var-vote-yea,\n \"star-half\": $fa-var-star-half,\n \"boxes-stacked\": $fa-var-boxes-stacked,\n \"boxes\": $fa-var-boxes,\n \"boxes-alt\": $fa-var-boxes-alt,\n \"link\": $fa-var-link,\n \"chain\": $fa-var-chain,\n \"ear-listen\": $fa-var-ear-listen,\n \"assistive-listening-systems\": $fa-var-assistive-listening-systems,\n \"tree-city\": $fa-var-tree-city,\n \"play\": $fa-var-play,\n \"font\": $fa-var-font,\n \"table-cells-row-lock\": $fa-var-table-cells-row-lock,\n \"rupiah-sign\": $fa-var-rupiah-sign,\n \"magnifying-glass\": $fa-var-magnifying-glass,\n \"search\": $fa-var-search,\n \"table-tennis-paddle-ball\": $fa-var-table-tennis-paddle-ball,\n \"ping-pong-paddle-ball\": $fa-var-ping-pong-paddle-ball,\n \"table-tennis\": $fa-var-table-tennis,\n \"person-dots-from-line\": $fa-var-person-dots-from-line,\n \"diagnoses\": $fa-var-diagnoses,\n \"trash-can-arrow-up\": $fa-var-trash-can-arrow-up,\n \"trash-restore-alt\": $fa-var-trash-restore-alt,\n \"naira-sign\": $fa-var-naira-sign,\n \"cart-arrow-down\": $fa-var-cart-arrow-down,\n \"walkie-talkie\": $fa-var-walkie-talkie,\n \"file-pen\": $fa-var-file-pen,\n \"file-edit\": $fa-var-file-edit,\n \"receipt\": $fa-var-receipt,\n \"square-pen\": $fa-var-square-pen,\n \"pen-square\": $fa-var-pen-square,\n \"pencil-square\": $fa-var-pencil-square,\n \"suitcase-rolling\": $fa-var-suitcase-rolling,\n \"person-circle-exclamation\": $fa-var-person-circle-exclamation,\n \"chevron-down\": $fa-var-chevron-down,\n \"battery-full\": $fa-var-battery-full,\n \"battery\": $fa-var-battery,\n \"battery-5\": $fa-var-battery-5,\n \"skull-crossbones\": $fa-var-skull-crossbones,\n \"code-compare\": $fa-var-code-compare,\n \"list-ul\": $fa-var-list-ul,\n \"list-dots\": $fa-var-list-dots,\n \"school-lock\": $fa-var-school-lock,\n \"tower-cell\": $fa-var-tower-cell,\n \"down-long\": $fa-var-down-long,\n \"long-arrow-alt-down\": $fa-var-long-arrow-alt-down,\n \"ranking-star\": $fa-var-ranking-star,\n \"chess-king\": $fa-var-chess-king,\n \"person-harassing\": $fa-var-person-harassing,\n \"brazilian-real-sign\": $fa-var-brazilian-real-sign,\n \"landmark-dome\": $fa-var-landmark-dome,\n \"landmark-alt\": $fa-var-landmark-alt,\n \"arrow-up\": $fa-var-arrow-up,\n \"tv\": $fa-var-tv,\n \"television\": $fa-var-television,\n \"tv-alt\": $fa-var-tv-alt,\n \"shrimp\": $fa-var-shrimp,\n \"list-check\": $fa-var-list-check,\n \"tasks\": $fa-var-tasks,\n \"jug-detergent\": $fa-var-jug-detergent,\n \"circle-user\": $fa-var-circle-user,\n \"user-circle\": $fa-var-user-circle,\n \"user-shield\": $fa-var-user-shield,\n \"wind\": $fa-var-wind,\n \"car-burst\": $fa-var-car-burst,\n \"car-crash\": $fa-var-car-crash,\n \"y\": $fa-var-y,\n \"person-snowboarding\": $fa-var-person-snowboarding,\n \"snowboarding\": $fa-var-snowboarding,\n \"truck-fast\": $fa-var-truck-fast,\n \"shipping-fast\": $fa-var-shipping-fast,\n \"fish\": $fa-var-fish,\n \"user-graduate\": $fa-var-user-graduate,\n \"circle-half-stroke\": $fa-var-circle-half-stroke,\n \"adjust\": $fa-var-adjust,\n \"clapperboard\": $fa-var-clapperboard,\n \"circle-radiation\": $fa-var-circle-radiation,\n \"radiation-alt\": $fa-var-radiation-alt,\n \"baseball\": $fa-var-baseball,\n \"baseball-ball\": $fa-var-baseball-ball,\n \"jet-fighter-up\": $fa-var-jet-fighter-up,\n \"diagram-project\": $fa-var-diagram-project,\n \"project-diagram\": $fa-var-project-diagram,\n \"copy\": $fa-var-copy,\n \"volume-xmark\": $fa-var-volume-xmark,\n \"volume-mute\": $fa-var-volume-mute,\n \"volume-times\": $fa-var-volume-times,\n \"hand-sparkles\": $fa-var-hand-sparkles,\n \"grip\": $fa-var-grip,\n \"grip-horizontal\": $fa-var-grip-horizontal,\n \"share-from-square\": $fa-var-share-from-square,\n \"share-square\": $fa-var-share-square,\n \"child-combatant\": $fa-var-child-combatant,\n \"child-rifle\": $fa-var-child-rifle,\n \"gun\": $fa-var-gun,\n \"square-phone\": $fa-var-square-phone,\n \"phone-square\": $fa-var-phone-square,\n \"plus\": $fa-var-plus,\n \"add\": $fa-var-add,\n \"expand\": $fa-var-expand,\n \"computer\": $fa-var-computer,\n \"xmark\": $fa-var-xmark,\n \"close\": $fa-var-close,\n \"multiply\": $fa-var-multiply,\n \"remove\": $fa-var-remove,\n \"times\": $fa-var-times,\n \"arrows-up-down-left-right\": $fa-var-arrows-up-down-left-right,\n \"arrows\": $fa-var-arrows,\n \"chalkboard-user\": $fa-var-chalkboard-user,\n \"chalkboard-teacher\": $fa-var-chalkboard-teacher,\n \"peso-sign\": $fa-var-peso-sign,\n \"building-shield\": $fa-var-building-shield,\n \"baby\": $fa-var-baby,\n \"users-line\": $fa-var-users-line,\n \"quote-left\": $fa-var-quote-left,\n \"quote-left-alt\": $fa-var-quote-left-alt,\n \"tractor\": $fa-var-tractor,\n \"trash-arrow-up\": $fa-var-trash-arrow-up,\n \"trash-restore\": $fa-var-trash-restore,\n \"arrow-down-up-lock\": $fa-var-arrow-down-up-lock,\n \"lines-leaning\": $fa-var-lines-leaning,\n \"ruler-combined\": $fa-var-ruler-combined,\n \"copyright\": $fa-var-copyright,\n \"equals\": $fa-var-equals,\n \"blender\": $fa-var-blender,\n \"teeth\": $fa-var-teeth,\n \"shekel-sign\": $fa-var-shekel-sign,\n \"ils\": $fa-var-ils,\n \"shekel\": $fa-var-shekel,\n \"sheqel\": $fa-var-sheqel,\n \"sheqel-sign\": $fa-var-sheqel-sign,\n \"map\": $fa-var-map,\n \"rocket\": $fa-var-rocket,\n \"photo-film\": $fa-var-photo-film,\n \"photo-video\": $fa-var-photo-video,\n \"folder-minus\": $fa-var-folder-minus,\n \"store\": $fa-var-store,\n \"arrow-trend-up\": $fa-var-arrow-trend-up,\n \"plug-circle-minus\": $fa-var-plug-circle-minus,\n \"sign-hanging\": $fa-var-sign-hanging,\n \"sign\": $fa-var-sign,\n \"bezier-curve\": $fa-var-bezier-curve,\n \"bell-slash\": $fa-var-bell-slash,\n \"tablet\": $fa-var-tablet,\n \"tablet-android\": $fa-var-tablet-android,\n \"school-flag\": $fa-var-school-flag,\n \"fill\": $fa-var-fill,\n \"angle-up\": $fa-var-angle-up,\n \"drumstick-bite\": $fa-var-drumstick-bite,\n \"holly-berry\": $fa-var-holly-berry,\n \"chevron-left\": $fa-var-chevron-left,\n \"bacteria\": $fa-var-bacteria,\n \"hand-lizard\": $fa-var-hand-lizard,\n \"notdef\": $fa-var-notdef,\n \"disease\": $fa-var-disease,\n \"briefcase-medical\": $fa-var-briefcase-medical,\n \"genderless\": $fa-var-genderless,\n \"chevron-right\": $fa-var-chevron-right,\n \"retweet\": $fa-var-retweet,\n \"car-rear\": $fa-var-car-rear,\n \"car-alt\": $fa-var-car-alt,\n \"pump-soap\": $fa-var-pump-soap,\n \"video-slash\": $fa-var-video-slash,\n \"battery-quarter\": $fa-var-battery-quarter,\n \"battery-2\": $fa-var-battery-2,\n \"radio\": $fa-var-radio,\n \"baby-carriage\": $fa-var-baby-carriage,\n \"carriage-baby\": $fa-var-carriage-baby,\n \"traffic-light\": $fa-var-traffic-light,\n \"thermometer\": $fa-var-thermometer,\n \"vr-cardboard\": $fa-var-vr-cardboard,\n \"hand-middle-finger\": $fa-var-hand-middle-finger,\n \"percent\": $fa-var-percent,\n \"percentage\": $fa-var-percentage,\n \"truck-moving\": $fa-var-truck-moving,\n \"glass-water-droplet\": $fa-var-glass-water-droplet,\n \"display\": $fa-var-display,\n \"face-smile\": $fa-var-face-smile,\n \"smile\": $fa-var-smile,\n \"thumbtack\": $fa-var-thumbtack,\n \"thumb-tack\": $fa-var-thumb-tack,\n \"trophy\": $fa-var-trophy,\n \"person-praying\": $fa-var-person-praying,\n \"pray\": $fa-var-pray,\n \"hammer\": $fa-var-hammer,\n \"hand-peace\": $fa-var-hand-peace,\n \"rotate\": $fa-var-rotate,\n \"sync-alt\": $fa-var-sync-alt,\n \"spinner\": $fa-var-spinner,\n \"robot\": $fa-var-robot,\n \"peace\": $fa-var-peace,\n \"gears\": $fa-var-gears,\n \"cogs\": $fa-var-cogs,\n \"warehouse\": $fa-var-warehouse,\n \"arrow-up-right-dots\": $fa-var-arrow-up-right-dots,\n \"splotch\": $fa-var-splotch,\n \"face-grin-hearts\": $fa-var-face-grin-hearts,\n \"grin-hearts\": $fa-var-grin-hearts,\n \"dice-four\": $fa-var-dice-four,\n \"sim-card\": $fa-var-sim-card,\n \"transgender\": $fa-var-transgender,\n \"transgender-alt\": $fa-var-transgender-alt,\n \"mercury\": $fa-var-mercury,\n \"arrow-turn-down\": $fa-var-arrow-turn-down,\n \"level-down\": $fa-var-level-down,\n \"person-falling-burst\": $fa-var-person-falling-burst,\n \"award\": $fa-var-award,\n \"ticket-simple\": $fa-var-ticket-simple,\n \"ticket-alt\": $fa-var-ticket-alt,\n \"building\": $fa-var-building,\n \"angles-left\": $fa-var-angles-left,\n \"angle-double-left\": $fa-var-angle-double-left,\n \"qrcode\": $fa-var-qrcode,\n \"clock-rotate-left\": $fa-var-clock-rotate-left,\n \"history\": $fa-var-history,\n \"face-grin-beam-sweat\": $fa-var-face-grin-beam-sweat,\n \"grin-beam-sweat\": $fa-var-grin-beam-sweat,\n \"file-export\": $fa-var-file-export,\n \"arrow-right-from-file\": $fa-var-arrow-right-from-file,\n \"shield\": $fa-var-shield,\n \"shield-blank\": $fa-var-shield-blank,\n \"arrow-up-short-wide\": $fa-var-arrow-up-short-wide,\n \"sort-amount-up-alt\": $fa-var-sort-amount-up-alt,\n \"house-medical\": $fa-var-house-medical,\n \"golf-ball-tee\": $fa-var-golf-ball-tee,\n \"golf-ball\": $fa-var-golf-ball,\n \"circle-chevron-left\": $fa-var-circle-chevron-left,\n \"chevron-circle-left\": $fa-var-chevron-circle-left,\n \"house-chimney-window\": $fa-var-house-chimney-window,\n \"pen-nib\": $fa-var-pen-nib,\n \"tent-arrow-turn-left\": $fa-var-tent-arrow-turn-left,\n \"tents\": $fa-var-tents,\n \"wand-magic\": $fa-var-wand-magic,\n \"magic\": $fa-var-magic,\n \"dog\": $fa-var-dog,\n \"carrot\": $fa-var-carrot,\n \"moon\": $fa-var-moon,\n \"wine-glass-empty\": $fa-var-wine-glass-empty,\n \"wine-glass-alt\": $fa-var-wine-glass-alt,\n \"cheese\": $fa-var-cheese,\n \"yin-yang\": $fa-var-yin-yang,\n \"music\": $fa-var-music,\n \"code-commit\": $fa-var-code-commit,\n \"temperature-low\": $fa-var-temperature-low,\n \"person-biking\": $fa-var-person-biking,\n \"biking\": $fa-var-biking,\n \"broom\": $fa-var-broom,\n \"shield-heart\": $fa-var-shield-heart,\n \"gopuram\": $fa-var-gopuram,\n \"earth-oceania\": $fa-var-earth-oceania,\n \"globe-oceania\": $fa-var-globe-oceania,\n \"square-xmark\": $fa-var-square-xmark,\n \"times-square\": $fa-var-times-square,\n \"xmark-square\": $fa-var-xmark-square,\n \"hashtag\": $fa-var-hashtag,\n \"up-right-and-down-left-from-center\": $fa-var-up-right-and-down-left-from-center,\n \"expand-alt\": $fa-var-expand-alt,\n \"oil-can\": $fa-var-oil-can,\n \"t\": $fa-var-t,\n \"hippo\": $fa-var-hippo,\n \"chart-column\": $fa-var-chart-column,\n \"infinity\": $fa-var-infinity,\n \"vial-circle-check\": $fa-var-vial-circle-check,\n \"person-arrow-down-to-line\": $fa-var-person-arrow-down-to-line,\n \"voicemail\": $fa-var-voicemail,\n \"fan\": $fa-var-fan,\n \"person-walking-luggage\": $fa-var-person-walking-luggage,\n \"up-down\": $fa-var-up-down,\n \"arrows-alt-v\": $fa-var-arrows-alt-v,\n \"cloud-moon-rain\": $fa-var-cloud-moon-rain,\n \"calendar\": $fa-var-calendar,\n \"trailer\": $fa-var-trailer,\n \"bahai\": $fa-var-bahai,\n \"haykal\": $fa-var-haykal,\n \"sd-card\": $fa-var-sd-card,\n \"dragon\": $fa-var-dragon,\n \"shoe-prints\": $fa-var-shoe-prints,\n \"circle-plus\": $fa-var-circle-plus,\n \"plus-circle\": $fa-var-plus-circle,\n \"face-grin-tongue-wink\": $fa-var-face-grin-tongue-wink,\n \"grin-tongue-wink\": $fa-var-grin-tongue-wink,\n \"hand-holding\": $fa-var-hand-holding,\n \"plug-circle-exclamation\": $fa-var-plug-circle-exclamation,\n \"link-slash\": $fa-var-link-slash,\n \"chain-broken\": $fa-var-chain-broken,\n \"chain-slash\": $fa-var-chain-slash,\n \"unlink\": $fa-var-unlink,\n \"clone\": $fa-var-clone,\n \"person-walking-arrow-loop-left\": $fa-var-person-walking-arrow-loop-left,\n \"arrow-up-z-a\": $fa-var-arrow-up-z-a,\n \"sort-alpha-up-alt\": $fa-var-sort-alpha-up-alt,\n \"fire-flame-curved\": $fa-var-fire-flame-curved,\n \"fire-alt\": $fa-var-fire-alt,\n \"tornado\": $fa-var-tornado,\n \"file-circle-plus\": $fa-var-file-circle-plus,\n \"book-quran\": $fa-var-book-quran,\n \"quran\": $fa-var-quran,\n \"anchor\": $fa-var-anchor,\n \"border-all\": $fa-var-border-all,\n \"face-angry\": $fa-var-face-angry,\n \"angry\": $fa-var-angry,\n \"cookie-bite\": $fa-var-cookie-bite,\n \"arrow-trend-down\": $fa-var-arrow-trend-down,\n \"rss\": $fa-var-rss,\n \"feed\": $fa-var-feed,\n \"draw-polygon\": $fa-var-draw-polygon,\n \"scale-balanced\": $fa-var-scale-balanced,\n \"balance-scale\": $fa-var-balance-scale,\n \"gauge-simple-high\": $fa-var-gauge-simple-high,\n \"tachometer\": $fa-var-tachometer,\n \"tachometer-fast\": $fa-var-tachometer-fast,\n \"shower\": $fa-var-shower,\n \"desktop\": $fa-var-desktop,\n \"desktop-alt\": $fa-var-desktop-alt,\n \"m\": $fa-var-m,\n \"table-list\": $fa-var-table-list,\n \"th-list\": $fa-var-th-list,\n \"comment-sms\": $fa-var-comment-sms,\n \"sms\": $fa-var-sms,\n \"book\": $fa-var-book,\n \"user-plus\": $fa-var-user-plus,\n \"check\": $fa-var-check,\n \"battery-three-quarters\": $fa-var-battery-three-quarters,\n \"battery-4\": $fa-var-battery-4,\n \"house-circle-check\": $fa-var-house-circle-check,\n \"angle-left\": $fa-var-angle-left,\n \"diagram-successor\": $fa-var-diagram-successor,\n \"truck-arrow-right\": $fa-var-truck-arrow-right,\n \"arrows-split-up-and-left\": $fa-var-arrows-split-up-and-left,\n \"hand-fist\": $fa-var-hand-fist,\n \"fist-raised\": $fa-var-fist-raised,\n \"cloud-moon\": $fa-var-cloud-moon,\n \"briefcase\": $fa-var-briefcase,\n \"person-falling\": $fa-var-person-falling,\n \"image-portrait\": $fa-var-image-portrait,\n \"portrait\": $fa-var-portrait,\n \"user-tag\": $fa-var-user-tag,\n \"rug\": $fa-var-rug,\n \"earth-europe\": $fa-var-earth-europe,\n \"globe-europe\": $fa-var-globe-europe,\n \"cart-flatbed-suitcase\": $fa-var-cart-flatbed-suitcase,\n \"luggage-cart\": $fa-var-luggage-cart,\n \"rectangle-xmark\": $fa-var-rectangle-xmark,\n \"rectangle-times\": $fa-var-rectangle-times,\n \"times-rectangle\": $fa-var-times-rectangle,\n \"window-close\": $fa-var-window-close,\n \"baht-sign\": $fa-var-baht-sign,\n \"book-open\": $fa-var-book-open,\n \"book-journal-whills\": $fa-var-book-journal-whills,\n \"journal-whills\": $fa-var-journal-whills,\n \"handcuffs\": $fa-var-handcuffs,\n \"triangle-exclamation\": $fa-var-triangle-exclamation,\n \"exclamation-triangle\": $fa-var-exclamation-triangle,\n \"warning\": $fa-var-warning,\n \"database\": $fa-var-database,\n \"share\": $fa-var-share,\n \"mail-forward\": $fa-var-mail-forward,\n \"bottle-droplet\": $fa-var-bottle-droplet,\n \"mask-face\": $fa-var-mask-face,\n \"hill-rockslide\": $fa-var-hill-rockslide,\n \"right-left\": $fa-var-right-left,\n \"exchange-alt\": $fa-var-exchange-alt,\n \"paper-plane\": $fa-var-paper-plane,\n \"road-circle-exclamation\": $fa-var-road-circle-exclamation,\n \"dungeon\": $fa-var-dungeon,\n \"align-right\": $fa-var-align-right,\n \"money-bill-1-wave\": $fa-var-money-bill-1-wave,\n \"money-bill-wave-alt\": $fa-var-money-bill-wave-alt,\n \"life-ring\": $fa-var-life-ring,\n \"hands\": $fa-var-hands,\n \"sign-language\": $fa-var-sign-language,\n \"signing\": $fa-var-signing,\n \"calendar-day\": $fa-var-calendar-day,\n \"water-ladder\": $fa-var-water-ladder,\n \"ladder-water\": $fa-var-ladder-water,\n \"swimming-pool\": $fa-var-swimming-pool,\n \"arrows-up-down\": $fa-var-arrows-up-down,\n \"arrows-v\": $fa-var-arrows-v,\n \"face-grimace\": $fa-var-face-grimace,\n \"grimace\": $fa-var-grimace,\n \"wheelchair-move\": $fa-var-wheelchair-move,\n \"wheelchair-alt\": $fa-var-wheelchair-alt,\n \"turn-down\": $fa-var-turn-down,\n \"level-down-alt\": $fa-var-level-down-alt,\n \"person-walking-arrow-right\": $fa-var-person-walking-arrow-right,\n \"square-envelope\": $fa-var-square-envelope,\n \"envelope-square\": $fa-var-envelope-square,\n \"dice\": $fa-var-dice,\n \"bowling-ball\": $fa-var-bowling-ball,\n \"brain\": $fa-var-brain,\n \"bandage\": $fa-var-bandage,\n \"band-aid\": $fa-var-band-aid,\n \"calendar-minus\": $fa-var-calendar-minus,\n \"circle-xmark\": $fa-var-circle-xmark,\n \"times-circle\": $fa-var-times-circle,\n \"xmark-circle\": $fa-var-xmark-circle,\n \"gifts\": $fa-var-gifts,\n \"hotel\": $fa-var-hotel,\n \"earth-asia\": $fa-var-earth-asia,\n \"globe-asia\": $fa-var-globe-asia,\n \"id-card-clip\": $fa-var-id-card-clip,\n \"id-card-alt\": $fa-var-id-card-alt,\n \"magnifying-glass-plus\": $fa-var-magnifying-glass-plus,\n \"search-plus\": $fa-var-search-plus,\n \"thumbs-up\": $fa-var-thumbs-up,\n \"user-clock\": $fa-var-user-clock,\n \"hand-dots\": $fa-var-hand-dots,\n \"allergies\": $fa-var-allergies,\n \"file-invoice\": $fa-var-file-invoice,\n \"window-minimize\": $fa-var-window-minimize,\n \"mug-saucer\": $fa-var-mug-saucer,\n \"coffee\": $fa-var-coffee,\n \"brush\": $fa-var-brush,\n \"mask\": $fa-var-mask,\n \"magnifying-glass-minus\": $fa-var-magnifying-glass-minus,\n \"search-minus\": $fa-var-search-minus,\n \"ruler-vertical\": $fa-var-ruler-vertical,\n \"user-large\": $fa-var-user-large,\n \"user-alt\": $fa-var-user-alt,\n \"train-tram\": $fa-var-train-tram,\n \"user-nurse\": $fa-var-user-nurse,\n \"syringe\": $fa-var-syringe,\n \"cloud-sun\": $fa-var-cloud-sun,\n \"stopwatch-20\": $fa-var-stopwatch-20,\n \"square-full\": $fa-var-square-full,\n \"magnet\": $fa-var-magnet,\n \"jar\": $fa-var-jar,\n \"note-sticky\": $fa-var-note-sticky,\n \"sticky-note\": $fa-var-sticky-note,\n \"bug-slash\": $fa-var-bug-slash,\n \"arrow-up-from-water-pump\": $fa-var-arrow-up-from-water-pump,\n \"bone\": $fa-var-bone,\n \"table-cells-row-unlock\": $fa-var-table-cells-row-unlock,\n \"user-injured\": $fa-var-user-injured,\n \"face-sad-tear\": $fa-var-face-sad-tear,\n \"sad-tear\": $fa-var-sad-tear,\n \"plane\": $fa-var-plane,\n \"tent-arrows-down\": $fa-var-tent-arrows-down,\n \"exclamation\": $fa-var-exclamation,\n \"arrows-spin\": $fa-var-arrows-spin,\n \"print\": $fa-var-print,\n \"turkish-lira-sign\": $fa-var-turkish-lira-sign,\n \"try\": $fa-var-try,\n \"turkish-lira\": $fa-var-turkish-lira,\n \"dollar-sign\": $fa-var-dollar-sign,\n \"dollar\": $fa-var-dollar,\n \"usd\": $fa-var-usd,\n \"x\": $fa-var-x,\n \"magnifying-glass-dollar\": $fa-var-magnifying-glass-dollar,\n \"search-dollar\": $fa-var-search-dollar,\n \"users-gear\": $fa-var-users-gear,\n \"users-cog\": $fa-var-users-cog,\n \"person-military-pointing\": $fa-var-person-military-pointing,\n \"building-columns\": $fa-var-building-columns,\n \"bank\": $fa-var-bank,\n \"institution\": $fa-var-institution,\n \"museum\": $fa-var-museum,\n \"university\": $fa-var-university,\n \"umbrella\": $fa-var-umbrella,\n \"trowel\": $fa-var-trowel,\n \"d\": $fa-var-d,\n \"stapler\": $fa-var-stapler,\n \"masks-theater\": $fa-var-masks-theater,\n \"theater-masks\": $fa-var-theater-masks,\n \"kip-sign\": $fa-var-kip-sign,\n \"hand-point-left\": $fa-var-hand-point-left,\n \"handshake-simple\": $fa-var-handshake-simple,\n \"handshake-alt\": $fa-var-handshake-alt,\n \"jet-fighter\": $fa-var-jet-fighter,\n \"fighter-jet\": $fa-var-fighter-jet,\n \"square-share-nodes\": $fa-var-square-share-nodes,\n \"share-alt-square\": $fa-var-share-alt-square,\n \"barcode\": $fa-var-barcode,\n \"plus-minus\": $fa-var-plus-minus,\n \"video\": $fa-var-video,\n \"video-camera\": $fa-var-video-camera,\n \"graduation-cap\": $fa-var-graduation-cap,\n \"mortar-board\": $fa-var-mortar-board,\n \"hand-holding-medical\": $fa-var-hand-holding-medical,\n \"person-circle-check\": $fa-var-person-circle-check,\n \"turn-up\": $fa-var-turn-up,\n \"level-up-alt\": $fa-var-level-up-alt,\n);\n\n$fa-brand-icons: (\n \"monero\": $fa-var-monero,\n \"hooli\": $fa-var-hooli,\n \"yelp\": $fa-var-yelp,\n \"cc-visa\": $fa-var-cc-visa,\n \"lastfm\": $fa-var-lastfm,\n \"shopware\": $fa-var-shopware,\n \"creative-commons-nc\": $fa-var-creative-commons-nc,\n \"aws\": $fa-var-aws,\n \"redhat\": $fa-var-redhat,\n \"yoast\": $fa-var-yoast,\n \"cloudflare\": $fa-var-cloudflare,\n \"ups\": $fa-var-ups,\n \"pixiv\": $fa-var-pixiv,\n \"wpexplorer\": $fa-var-wpexplorer,\n \"dyalog\": $fa-var-dyalog,\n \"bity\": $fa-var-bity,\n \"stackpath\": $fa-var-stackpath,\n \"buysellads\": $fa-var-buysellads,\n \"first-order\": $fa-var-first-order,\n \"modx\": $fa-var-modx,\n \"guilded\": $fa-var-guilded,\n \"vnv\": $fa-var-vnv,\n \"square-js\": $fa-var-square-js,\n \"js-square\": $fa-var-js-square,\n \"microsoft\": $fa-var-microsoft,\n \"qq\": $fa-var-qq,\n \"orcid\": $fa-var-orcid,\n \"java\": $fa-var-java,\n \"invision\": $fa-var-invision,\n \"creative-commons-pd-alt\": $fa-var-creative-commons-pd-alt,\n \"centercode\": $fa-var-centercode,\n \"glide-g\": $fa-var-glide-g,\n \"drupal\": $fa-var-drupal,\n \"jxl\": $fa-var-jxl,\n \"dart-lang\": $fa-var-dart-lang,\n \"hire-a-helper\": $fa-var-hire-a-helper,\n \"creative-commons-by\": $fa-var-creative-commons-by,\n \"unity\": $fa-var-unity,\n \"whmcs\": $fa-var-whmcs,\n \"rocketchat\": $fa-var-rocketchat,\n \"vk\": $fa-var-vk,\n \"untappd\": $fa-var-untappd,\n \"mailchimp\": $fa-var-mailchimp,\n \"css3-alt\": $fa-var-css3-alt,\n \"square-reddit\": $fa-var-square-reddit,\n \"reddit-square\": $fa-var-reddit-square,\n \"vimeo-v\": $fa-var-vimeo-v,\n \"contao\": $fa-var-contao,\n \"square-font-awesome\": $fa-var-square-font-awesome,\n \"deskpro\": $fa-var-deskpro,\n \"brave\": $fa-var-brave,\n \"sistrix\": $fa-var-sistrix,\n \"square-instagram\": $fa-var-square-instagram,\n \"instagram-square\": $fa-var-instagram-square,\n \"battle-net\": $fa-var-battle-net,\n \"the-red-yeti\": $fa-var-the-red-yeti,\n \"square-hacker-news\": $fa-var-square-hacker-news,\n \"hacker-news-square\": $fa-var-hacker-news-square,\n \"edge\": $fa-var-edge,\n \"threads\": $fa-var-threads,\n \"napster\": $fa-var-napster,\n \"square-snapchat\": $fa-var-square-snapchat,\n \"snapchat-square\": $fa-var-snapchat-square,\n \"google-plus-g\": $fa-var-google-plus-g,\n \"artstation\": $fa-var-artstation,\n \"markdown\": $fa-var-markdown,\n \"sourcetree\": $fa-var-sourcetree,\n \"google-plus\": $fa-var-google-plus,\n \"diaspora\": $fa-var-diaspora,\n \"foursquare\": $fa-var-foursquare,\n \"stack-overflow\": $fa-var-stack-overflow,\n \"github-alt\": $fa-var-github-alt,\n \"phoenix-squadron\": $fa-var-phoenix-squadron,\n \"pagelines\": $fa-var-pagelines,\n \"algolia\": $fa-var-algolia,\n \"red-river\": $fa-var-red-river,\n \"creative-commons-sa\": $fa-var-creative-commons-sa,\n \"safari\": $fa-var-safari,\n \"google\": $fa-var-google,\n \"square-font-awesome-stroke\": $fa-var-square-font-awesome-stroke,\n \"font-awesome-alt\": $fa-var-font-awesome-alt,\n \"atlassian\": $fa-var-atlassian,\n \"linkedin-in\": $fa-var-linkedin-in,\n \"digital-ocean\": $fa-var-digital-ocean,\n \"nimblr\": $fa-var-nimblr,\n \"chromecast\": $fa-var-chromecast,\n \"evernote\": $fa-var-evernote,\n \"hacker-news\": $fa-var-hacker-news,\n \"creative-commons-sampling\": $fa-var-creative-commons-sampling,\n \"adversal\": $fa-var-adversal,\n \"creative-commons\": $fa-var-creative-commons,\n \"watchman-monitoring\": $fa-var-watchman-monitoring,\n \"fonticons\": $fa-var-fonticons,\n \"weixin\": $fa-var-weixin,\n \"shirtsinbulk\": $fa-var-shirtsinbulk,\n \"codepen\": $fa-var-codepen,\n \"git-alt\": $fa-var-git-alt,\n \"lyft\": $fa-var-lyft,\n \"rev\": $fa-var-rev,\n \"windows\": $fa-var-windows,\n \"wizards-of-the-coast\": $fa-var-wizards-of-the-coast,\n \"square-viadeo\": $fa-var-square-viadeo,\n \"viadeo-square\": $fa-var-viadeo-square,\n \"meetup\": $fa-var-meetup,\n \"centos\": $fa-var-centos,\n \"adn\": $fa-var-adn,\n \"cloudsmith\": $fa-var-cloudsmith,\n \"opensuse\": $fa-var-opensuse,\n \"pied-piper-alt\": $fa-var-pied-piper-alt,\n \"square-dribbble\": $fa-var-square-dribbble,\n \"dribbble-square\": $fa-var-dribbble-square,\n \"codiepie\": $fa-var-codiepie,\n \"node\": $fa-var-node,\n \"mix\": $fa-var-mix,\n \"steam\": $fa-var-steam,\n \"cc-apple-pay\": $fa-var-cc-apple-pay,\n \"scribd\": $fa-var-scribd,\n \"debian\": $fa-var-debian,\n \"openid\": $fa-var-openid,\n \"instalod\": $fa-var-instalod,\n \"expeditedssl\": $fa-var-expeditedssl,\n \"sellcast\": $fa-var-sellcast,\n \"square-twitter\": $fa-var-square-twitter,\n \"twitter-square\": $fa-var-twitter-square,\n \"r-project\": $fa-var-r-project,\n \"delicious\": $fa-var-delicious,\n \"freebsd\": $fa-var-freebsd,\n \"vuejs\": $fa-var-vuejs,\n \"accusoft\": $fa-var-accusoft,\n \"ioxhost\": $fa-var-ioxhost,\n \"fonticons-fi\": $fa-var-fonticons-fi,\n \"app-store\": $fa-var-app-store,\n \"cc-mastercard\": $fa-var-cc-mastercard,\n \"itunes-note\": $fa-var-itunes-note,\n \"golang\": $fa-var-golang,\n \"kickstarter\": $fa-var-kickstarter,\n \"square-kickstarter\": $fa-var-square-kickstarter,\n \"grav\": $fa-var-grav,\n \"weibo\": $fa-var-weibo,\n \"uncharted\": $fa-var-uncharted,\n \"firstdraft\": $fa-var-firstdraft,\n \"square-youtube\": $fa-var-square-youtube,\n \"youtube-square\": $fa-var-youtube-square,\n \"wikipedia-w\": $fa-var-wikipedia-w,\n \"wpressr\": $fa-var-wpressr,\n \"rendact\": $fa-var-rendact,\n \"angellist\": $fa-var-angellist,\n \"galactic-republic\": $fa-var-galactic-republic,\n \"nfc-directional\": $fa-var-nfc-directional,\n \"skype\": $fa-var-skype,\n \"joget\": $fa-var-joget,\n \"fedora\": $fa-var-fedora,\n \"stripe-s\": $fa-var-stripe-s,\n \"meta\": $fa-var-meta,\n \"laravel\": $fa-var-laravel,\n \"hotjar\": $fa-var-hotjar,\n \"bluetooth-b\": $fa-var-bluetooth-b,\n \"square-letterboxd\": $fa-var-square-letterboxd,\n \"sticker-mule\": $fa-var-sticker-mule,\n \"creative-commons-zero\": $fa-var-creative-commons-zero,\n \"hips\": $fa-var-hips,\n \"behance\": $fa-var-behance,\n \"reddit\": $fa-var-reddit,\n \"discord\": $fa-var-discord,\n \"chrome\": $fa-var-chrome,\n \"app-store-ios\": $fa-var-app-store-ios,\n \"cc-discover\": $fa-var-cc-discover,\n \"wpbeginner\": $fa-var-wpbeginner,\n \"confluence\": $fa-var-confluence,\n \"shoelace\": $fa-var-shoelace,\n \"mdb\": $fa-var-mdb,\n \"dochub\": $fa-var-dochub,\n \"accessible-icon\": $fa-var-accessible-icon,\n \"ebay\": $fa-var-ebay,\n \"amazon\": $fa-var-amazon,\n \"unsplash\": $fa-var-unsplash,\n \"yarn\": $fa-var-yarn,\n \"square-steam\": $fa-var-square-steam,\n \"steam-square\": $fa-var-steam-square,\n \"500px\": $fa-var-500px,\n \"square-vimeo\": $fa-var-square-vimeo,\n \"vimeo-square\": $fa-var-vimeo-square,\n \"asymmetrik\": $fa-var-asymmetrik,\n \"font-awesome\": $fa-var-font-awesome,\n \"font-awesome-flag\": $fa-var-font-awesome-flag,\n \"font-awesome-logo-full\": $fa-var-font-awesome-logo-full,\n \"gratipay\": $fa-var-gratipay,\n \"apple\": $fa-var-apple,\n \"hive\": $fa-var-hive,\n \"gitkraken\": $fa-var-gitkraken,\n \"keybase\": $fa-var-keybase,\n \"apple-pay\": $fa-var-apple-pay,\n \"padlet\": $fa-var-padlet,\n \"amazon-pay\": $fa-var-amazon-pay,\n \"square-github\": $fa-var-square-github,\n \"github-square\": $fa-var-github-square,\n \"stumbleupon\": $fa-var-stumbleupon,\n \"fedex\": $fa-var-fedex,\n \"phoenix-framework\": $fa-var-phoenix-framework,\n \"shopify\": $fa-var-shopify,\n \"neos\": $fa-var-neos,\n \"square-threads\": $fa-var-square-threads,\n \"hackerrank\": $fa-var-hackerrank,\n \"researchgate\": $fa-var-researchgate,\n \"swift\": $fa-var-swift,\n \"angular\": $fa-var-angular,\n \"speakap\": $fa-var-speakap,\n \"angrycreative\": $fa-var-angrycreative,\n \"y-combinator\": $fa-var-y-combinator,\n \"empire\": $fa-var-empire,\n \"envira\": $fa-var-envira,\n \"google-scholar\": $fa-var-google-scholar,\n \"square-gitlab\": $fa-var-square-gitlab,\n \"gitlab-square\": $fa-var-gitlab-square,\n \"studiovinari\": $fa-var-studiovinari,\n \"pied-piper\": $fa-var-pied-piper,\n \"wordpress\": $fa-var-wordpress,\n \"product-hunt\": $fa-var-product-hunt,\n \"firefox\": $fa-var-firefox,\n \"linode\": $fa-var-linode,\n \"goodreads\": $fa-var-goodreads,\n \"square-odnoklassniki\": $fa-var-square-odnoklassniki,\n \"odnoklassniki-square\": $fa-var-odnoklassniki-square,\n \"jsfiddle\": $fa-var-jsfiddle,\n \"sith\": $fa-var-sith,\n \"themeisle\": $fa-var-themeisle,\n \"page4\": $fa-var-page4,\n \"hashnode\": $fa-var-hashnode,\n \"react\": $fa-var-react,\n \"cc-paypal\": $fa-var-cc-paypal,\n \"squarespace\": $fa-var-squarespace,\n \"cc-stripe\": $fa-var-cc-stripe,\n \"creative-commons-share\": $fa-var-creative-commons-share,\n \"bitcoin\": $fa-var-bitcoin,\n \"keycdn\": $fa-var-keycdn,\n \"opera\": $fa-var-opera,\n \"itch-io\": $fa-var-itch-io,\n \"umbraco\": $fa-var-umbraco,\n \"galactic-senate\": $fa-var-galactic-senate,\n \"ubuntu\": $fa-var-ubuntu,\n \"draft2digital\": $fa-var-draft2digital,\n \"stripe\": $fa-var-stripe,\n \"houzz\": $fa-var-houzz,\n \"gg\": $fa-var-gg,\n \"dhl\": $fa-var-dhl,\n \"square-pinterest\": $fa-var-square-pinterest,\n \"pinterest-square\": $fa-var-pinterest-square,\n \"xing\": $fa-var-xing,\n \"blackberry\": $fa-var-blackberry,\n \"creative-commons-pd\": $fa-var-creative-commons-pd,\n \"playstation\": $fa-var-playstation,\n \"quinscape\": $fa-var-quinscape,\n \"less\": $fa-var-less,\n \"blogger-b\": $fa-var-blogger-b,\n \"opencart\": $fa-var-opencart,\n \"vine\": $fa-var-vine,\n \"signal-messenger\": $fa-var-signal-messenger,\n \"paypal\": $fa-var-paypal,\n \"gitlab\": $fa-var-gitlab,\n \"typo3\": $fa-var-typo3,\n \"reddit-alien\": $fa-var-reddit-alien,\n \"yahoo\": $fa-var-yahoo,\n \"dailymotion\": $fa-var-dailymotion,\n \"affiliatetheme\": $fa-var-affiliatetheme,\n \"pied-piper-pp\": $fa-var-pied-piper-pp,\n \"bootstrap\": $fa-var-bootstrap,\n \"odnoklassniki\": $fa-var-odnoklassniki,\n \"nfc-symbol\": $fa-var-nfc-symbol,\n \"mintbit\": $fa-var-mintbit,\n \"ethereum\": $fa-var-ethereum,\n \"speaker-deck\": $fa-var-speaker-deck,\n \"creative-commons-nc-eu\": $fa-var-creative-commons-nc-eu,\n \"patreon\": $fa-var-patreon,\n \"avianex\": $fa-var-avianex,\n \"ello\": $fa-var-ello,\n \"gofore\": $fa-var-gofore,\n \"bimobject\": $fa-var-bimobject,\n \"brave-reverse\": $fa-var-brave-reverse,\n \"facebook-f\": $fa-var-facebook-f,\n \"square-google-plus\": $fa-var-square-google-plus,\n \"google-plus-square\": $fa-var-google-plus-square,\n \"web-awesome\": $fa-var-web-awesome,\n \"mandalorian\": $fa-var-mandalorian,\n \"first-order-alt\": $fa-var-first-order-alt,\n \"osi\": $fa-var-osi,\n \"google-wallet\": $fa-var-google-wallet,\n \"d-and-d-beyond\": $fa-var-d-and-d-beyond,\n \"periscope\": $fa-var-periscope,\n \"fulcrum\": $fa-var-fulcrum,\n \"cloudscale\": $fa-var-cloudscale,\n \"forumbee\": $fa-var-forumbee,\n \"mizuni\": $fa-var-mizuni,\n \"schlix\": $fa-var-schlix,\n \"square-xing\": $fa-var-square-xing,\n \"xing-square\": $fa-var-xing-square,\n \"bandcamp\": $fa-var-bandcamp,\n \"wpforms\": $fa-var-wpforms,\n \"cloudversify\": $fa-var-cloudversify,\n \"usps\": $fa-var-usps,\n \"megaport\": $fa-var-megaport,\n \"magento\": $fa-var-magento,\n \"spotify\": $fa-var-spotify,\n \"optin-monster\": $fa-var-optin-monster,\n \"fly\": $fa-var-fly,\n \"aviato\": $fa-var-aviato,\n \"itunes\": $fa-var-itunes,\n \"cuttlefish\": $fa-var-cuttlefish,\n \"blogger\": $fa-var-blogger,\n \"flickr\": $fa-var-flickr,\n \"viber\": $fa-var-viber,\n \"soundcloud\": $fa-var-soundcloud,\n \"digg\": $fa-var-digg,\n \"tencent-weibo\": $fa-var-tencent-weibo,\n \"letterboxd\": $fa-var-letterboxd,\n \"symfony\": $fa-var-symfony,\n \"maxcdn\": $fa-var-maxcdn,\n \"etsy\": $fa-var-etsy,\n \"facebook-messenger\": $fa-var-facebook-messenger,\n \"audible\": $fa-var-audible,\n \"think-peaks\": $fa-var-think-peaks,\n \"bilibili\": $fa-var-bilibili,\n \"erlang\": $fa-var-erlang,\n \"x-twitter\": $fa-var-x-twitter,\n \"cotton-bureau\": $fa-var-cotton-bureau,\n \"dashcube\": $fa-var-dashcube,\n \"42-group\": $fa-var-42-group,\n \"innosoft\": $fa-var-innosoft,\n \"stack-exchange\": $fa-var-stack-exchange,\n \"elementor\": $fa-var-elementor,\n \"square-pied-piper\": $fa-var-square-pied-piper,\n \"pied-piper-square\": $fa-var-pied-piper-square,\n \"creative-commons-nd\": $fa-var-creative-commons-nd,\n \"palfed\": $fa-var-palfed,\n \"superpowers\": $fa-var-superpowers,\n \"resolving\": $fa-var-resolving,\n \"xbox\": $fa-var-xbox,\n \"square-web-awesome-stroke\": $fa-var-square-web-awesome-stroke,\n \"searchengin\": $fa-var-searchengin,\n \"tiktok\": $fa-var-tiktok,\n \"square-facebook\": $fa-var-square-facebook,\n \"facebook-square\": $fa-var-facebook-square,\n \"renren\": $fa-var-renren,\n \"linux\": $fa-var-linux,\n \"glide\": $fa-var-glide,\n \"linkedin\": $fa-var-linkedin,\n \"hubspot\": $fa-var-hubspot,\n \"deploydog\": $fa-var-deploydog,\n \"twitch\": $fa-var-twitch,\n \"flutter\": $fa-var-flutter,\n \"ravelry\": $fa-var-ravelry,\n \"mixer\": $fa-var-mixer,\n \"square-lastfm\": $fa-var-square-lastfm,\n \"lastfm-square\": $fa-var-lastfm-square,\n \"vimeo\": $fa-var-vimeo,\n \"mendeley\": $fa-var-mendeley,\n \"uniregistry\": $fa-var-uniregistry,\n \"figma\": $fa-var-figma,\n \"creative-commons-remix\": $fa-var-creative-commons-remix,\n \"cc-amazon-pay\": $fa-var-cc-amazon-pay,\n \"dropbox\": $fa-var-dropbox,\n \"instagram\": $fa-var-instagram,\n \"cmplid\": $fa-var-cmplid,\n \"upwork\": $fa-var-upwork,\n \"facebook\": $fa-var-facebook,\n \"gripfire\": $fa-var-gripfire,\n \"jedi-order\": $fa-var-jedi-order,\n \"uikit\": $fa-var-uikit,\n \"fort-awesome-alt\": $fa-var-fort-awesome-alt,\n \"phabricator\": $fa-var-phabricator,\n \"ussunnah\": $fa-var-ussunnah,\n \"earlybirds\": $fa-var-earlybirds,\n \"trade-federation\": $fa-var-trade-federation,\n \"autoprefixer\": $fa-var-autoprefixer,\n \"whatsapp\": $fa-var-whatsapp,\n \"square-upwork\": $fa-var-square-upwork,\n \"slideshare\": $fa-var-slideshare,\n \"google-play\": $fa-var-google-play,\n \"viadeo\": $fa-var-viadeo,\n \"line\": $fa-var-line,\n \"google-drive\": $fa-var-google-drive,\n \"servicestack\": $fa-var-servicestack,\n \"simplybuilt\": $fa-var-simplybuilt,\n \"bitbucket\": $fa-var-bitbucket,\n \"imdb\": $fa-var-imdb,\n \"deezer\": $fa-var-deezer,\n \"raspberry-pi\": $fa-var-raspberry-pi,\n \"jira\": $fa-var-jira,\n \"docker\": $fa-var-docker,\n \"screenpal\": $fa-var-screenpal,\n \"bluetooth\": $fa-var-bluetooth,\n \"gitter\": $fa-var-gitter,\n \"d-and-d\": $fa-var-d-and-d,\n \"microblog\": $fa-var-microblog,\n \"cc-diners-club\": $fa-var-cc-diners-club,\n \"gg-circle\": $fa-var-gg-circle,\n \"pied-piper-hat\": $fa-var-pied-piper-hat,\n \"kickstarter-k\": $fa-var-kickstarter-k,\n \"yandex\": $fa-var-yandex,\n \"readme\": $fa-var-readme,\n \"html5\": $fa-var-html5,\n \"sellsy\": $fa-var-sellsy,\n \"square-web-awesome\": $fa-var-square-web-awesome,\n \"sass\": $fa-var-sass,\n \"wirsindhandwerk\": $fa-var-wirsindhandwerk,\n \"wsh\": $fa-var-wsh,\n \"buromobelexperte\": $fa-var-buromobelexperte,\n \"salesforce\": $fa-var-salesforce,\n \"octopus-deploy\": $fa-var-octopus-deploy,\n \"medapps\": $fa-var-medapps,\n \"ns8\": $fa-var-ns8,\n \"pinterest-p\": $fa-var-pinterest-p,\n \"apper\": $fa-var-apper,\n \"fort-awesome\": $fa-var-fort-awesome,\n \"waze\": $fa-var-waze,\n \"bluesky\": $fa-var-bluesky,\n \"cc-jcb\": $fa-var-cc-jcb,\n \"snapchat\": $fa-var-snapchat,\n \"snapchat-ghost\": $fa-var-snapchat-ghost,\n \"fantasy-flight-games\": $fa-var-fantasy-flight-games,\n \"rust\": $fa-var-rust,\n \"wix\": $fa-var-wix,\n \"square-behance\": $fa-var-square-behance,\n \"behance-square\": $fa-var-behance-square,\n \"supple\": $fa-var-supple,\n \"webflow\": $fa-var-webflow,\n \"rebel\": $fa-var-rebel,\n \"css3\": $fa-var-css3,\n \"staylinked\": $fa-var-staylinked,\n \"kaggle\": $fa-var-kaggle,\n \"space-awesome\": $fa-var-space-awesome,\n \"deviantart\": $fa-var-deviantart,\n \"cpanel\": $fa-var-cpanel,\n \"goodreads-g\": $fa-var-goodreads-g,\n \"square-git\": $fa-var-square-git,\n \"git-square\": $fa-var-git-square,\n \"square-tumblr\": $fa-var-square-tumblr,\n \"tumblr-square\": $fa-var-tumblr-square,\n \"trello\": $fa-var-trello,\n \"creative-commons-nc-jp\": $fa-var-creative-commons-nc-jp,\n \"get-pocket\": $fa-var-get-pocket,\n \"perbyte\": $fa-var-perbyte,\n \"grunt\": $fa-var-grunt,\n \"weebly\": $fa-var-weebly,\n \"connectdevelop\": $fa-var-connectdevelop,\n \"leanpub\": $fa-var-leanpub,\n \"black-tie\": $fa-var-black-tie,\n \"themeco\": $fa-var-themeco,\n \"python\": $fa-var-python,\n \"android\": $fa-var-android,\n \"bots\": $fa-var-bots,\n \"free-code-camp\": $fa-var-free-code-camp,\n \"hornbill\": $fa-var-hornbill,\n \"js\": $fa-var-js,\n \"ideal\": $fa-var-ideal,\n \"git\": $fa-var-git,\n \"dev\": $fa-var-dev,\n \"sketch\": $fa-var-sketch,\n \"yandex-international\": $fa-var-yandex-international,\n \"cc-amex\": $fa-var-cc-amex,\n \"uber\": $fa-var-uber,\n \"github\": $fa-var-github,\n \"php\": $fa-var-php,\n \"alipay\": $fa-var-alipay,\n \"youtube\": $fa-var-youtube,\n \"skyatlas\": $fa-var-skyatlas,\n \"firefox-browser\": $fa-var-firefox-browser,\n \"replyd\": $fa-var-replyd,\n \"suse\": $fa-var-suse,\n \"jenkins\": $fa-var-jenkins,\n \"twitter\": $fa-var-twitter,\n \"rockrms\": $fa-var-rockrms,\n \"pinterest\": $fa-var-pinterest,\n \"buffer\": $fa-var-buffer,\n \"npm\": $fa-var-npm,\n \"yammer\": $fa-var-yammer,\n \"btc\": $fa-var-btc,\n \"dribbble\": $fa-var-dribbble,\n \"stumbleupon-circle\": $fa-var-stumbleupon-circle,\n \"internet-explorer\": $fa-var-internet-explorer,\n \"stubber\": $fa-var-stubber,\n \"telegram\": $fa-var-telegram,\n \"telegram-plane\": $fa-var-telegram-plane,\n \"old-republic\": $fa-var-old-republic,\n \"odysee\": $fa-var-odysee,\n \"square-whatsapp\": $fa-var-square-whatsapp,\n \"whatsapp-square\": $fa-var-whatsapp-square,\n \"node-js\": $fa-var-node-js,\n \"edge-legacy\": $fa-var-edge-legacy,\n \"slack\": $fa-var-slack,\n \"slack-hash\": $fa-var-slack-hash,\n \"medrt\": $fa-var-medrt,\n \"usb\": $fa-var-usb,\n \"tumblr\": $fa-var-tumblr,\n \"vaadin\": $fa-var-vaadin,\n \"quora\": $fa-var-quora,\n \"square-x-twitter\": $fa-var-square-x-twitter,\n \"reacteurope\": $fa-var-reacteurope,\n \"medium\": $fa-var-medium,\n \"medium-m\": $fa-var-medium-m,\n \"amilia\": $fa-var-amilia,\n \"mixcloud\": $fa-var-mixcloud,\n \"flipboard\": $fa-var-flipboard,\n \"viacoin\": $fa-var-viacoin,\n \"critical-role\": $fa-var-critical-role,\n \"sitrox\": $fa-var-sitrox,\n \"discourse\": $fa-var-discourse,\n \"joomla\": $fa-var-joomla,\n \"mastodon\": $fa-var-mastodon,\n \"airbnb\": $fa-var-airbnb,\n \"wolf-pack-battalion\": $fa-var-wolf-pack-battalion,\n \"buy-n-large\": $fa-var-buy-n-large,\n \"gulp\": $fa-var-gulp,\n \"creative-commons-sampling-plus\": $fa-var-creative-commons-sampling-plus,\n \"strava\": $fa-var-strava,\n \"ember\": $fa-var-ember,\n \"canadian-maple-leaf\": $fa-var-canadian-maple-leaf,\n \"teamspeak\": $fa-var-teamspeak,\n \"pushed\": $fa-var-pushed,\n \"wordpress-simple\": $fa-var-wordpress-simple,\n \"nutritionix\": $fa-var-nutritionix,\n \"wodu\": $fa-var-wodu,\n \"google-pay\": $fa-var-google-pay,\n \"intercom\": $fa-var-intercom,\n \"zhihu\": $fa-var-zhihu,\n \"korvue\": $fa-var-korvue,\n \"pix\": $fa-var-pix,\n \"steam-symbol\": $fa-var-steam-symbol,\n);\n","// icons in a list\n// -------------------------\n\n.#{$fa-css-prefix}-ul {\n list-style-type: none;\n margin-left: var(--#{$fa-css-prefix}-li-margin, #{$fa-li-margin});\n padding-left: 0;\n\n > li { position: relative; }\n}\n\n.#{$fa-css-prefix}-li {\n left: calc(-1 * var(--#{$fa-css-prefix}-li-width, #{$fa-li-width}));\n position: absolute;\n text-align: center;\n width: var(--#{$fa-css-prefix}-li-width, #{$fa-li-width});\n line-height: inherit;\n}\n","// bordered + pulled icons\n// -------------------------\n\n.#{$fa-css-prefix}-border {\n border-color: var(--#{$fa-css-prefix}-border-color, #{$fa-border-color});\n border-radius: var(--#{$fa-css-prefix}-border-radius, #{$fa-border-radius});\n border-style: var(--#{$fa-css-prefix}-border-style, #{$fa-border-style});\n border-width: var(--#{$fa-css-prefix}-border-width, #{$fa-border-width});\n padding: var(--#{$fa-css-prefix}-border-padding, #{$fa-border-padding});\n}\n\n.#{$fa-css-prefix}-pull-left {\n float: left;\n margin-right: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin}); \n}\n\n.#{$fa-css-prefix}-pull-right {\n float: right;\n margin-left: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin}); \n}\n","// animating icons\n// --------------------------\n\n.#{$fa-css-prefix}-beat {\n animation-name: #{$fa-css-prefix}-beat;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);\n}\n\n.#{$fa-css-prefix}-bounce {\n animation-name: #{$fa-css-prefix}-bounce;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(0.280, 0.840, 0.420, 1));\n}\n\n.#{$fa-css-prefix}-fade {\n animation-name: #{$fa-css-prefix}-fade;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));\n}\n\n.#{$fa-css-prefix}-beat-fade {\n animation-name: #{$fa-css-prefix}-beat-fade;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));\n}\n\n.#{$fa-css-prefix}-flip {\n animation-name: #{$fa-css-prefix}-flip;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);\n}\n\n.#{$fa-css-prefix}-shake {\n animation-name: #{$fa-css-prefix}-shake;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);\n}\n\n.#{$fa-css-prefix}-spin {\n animation-name: #{$fa-css-prefix}-spin;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 2s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);\n}\n\n.#{$fa-css-prefix}-spin-reverse {\n --#{$fa-css-prefix}-animation-direction: reverse;\n}\n\n.#{$fa-css-prefix}-pulse,\n.#{$fa-css-prefix}-spin-pulse {\n animation-name: #{$fa-css-prefix}-spin;\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, steps(8));\n}\n\n// if agent or operating system prefers reduced motion, disable animations\n// see: https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/\n// see: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion\n@media (prefers-reduced-motion: reduce) {\n .#{$fa-css-prefix}-beat,\n .#{$fa-css-prefix}-bounce,\n .#{$fa-css-prefix}-fade,\n .#{$fa-css-prefix}-beat-fade,\n .#{$fa-css-prefix}-flip,\n .#{$fa-css-prefix}-pulse,\n .#{$fa-css-prefix}-shake,\n .#{$fa-css-prefix}-spin,\n .#{$fa-css-prefix}-spin-pulse {\n animation-delay: -1ms;\n animation-duration: 1ms;\n animation-iteration-count: 1;\n transition-delay: 0s;\n transition-duration: 0s;\n }\n}\n\n@keyframes #{$fa-css-prefix}-beat {\n 0%, 90% { transform: scale(1); }\n 45% { transform: scale(var(--#{$fa-css-prefix}-beat-scale, 1.25)); }\n}\n\n@keyframes #{$fa-css-prefix}-bounce {\n 0% { transform: scale(1,1) translateY(0); }\n 10% { transform: scale(var(--#{$fa-css-prefix}-bounce-start-scale-x, 1.1),var(--#{$fa-css-prefix}-bounce-start-scale-y, 0.9)) translateY(0); }\n 30% { transform: scale(var(--#{$fa-css-prefix}-bounce-jump-scale-x, 0.9),var(--#{$fa-css-prefix}-bounce-jump-scale-y, 1.1)) translateY(var(--#{$fa-css-prefix}-bounce-height, -0.5em)); }\n 50% { transform: scale(var(--#{$fa-css-prefix}-bounce-land-scale-x, 1.05),var(--#{$fa-css-prefix}-bounce-land-scale-y, 0.95)) translateY(0); }\n 57% { transform: scale(1,1) translateY(var(--#{$fa-css-prefix}-bounce-rebound, -0.125em)); }\n 64% { transform: scale(1,1) translateY(0); }\n 100% { transform: scale(1,1) translateY(0); }\n}\n\n@keyframes #{$fa-css-prefix}-fade {\n 50% { opacity: var(--#{$fa-css-prefix}-fade-opacity, 0.4); }\n}\n\n@keyframes #{$fa-css-prefix}-beat-fade {\n 0%, 100% {\n opacity: var(--#{$fa-css-prefix}-beat-fade-opacity, 0.4);\n transform: scale(1);\n }\n 50% {\n opacity: 1;\n transform: scale(var(--#{$fa-css-prefix}-beat-fade-scale, 1.125));\n }\n}\n\n@keyframes #{$fa-css-prefix}-flip {\n 50% {\n transform: rotate3d(var(--#{$fa-css-prefix}-flip-x, 0), var(--#{$fa-css-prefix}-flip-y, 1), var(--#{$fa-css-prefix}-flip-z, 0), var(--#{$fa-css-prefix}-flip-angle, -180deg));\n }\n}\n\n@keyframes #{$fa-css-prefix}-shake {\n 0% { transform: rotate(-15deg); }\n 4% { transform: rotate(15deg); }\n 8%, 24% { transform: rotate(-18deg); }\n 12%, 28% { transform: rotate(18deg); }\n 16% { transform: rotate(-22deg); }\n 20% { transform: rotate(22deg); }\n 32% { transform: rotate(-12deg); }\n 36% { transform: rotate(12deg); }\n 40%, 100% { transform: rotate(0deg); }\n}\n\n@keyframes #{$fa-css-prefix}-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n","// rotating + flipping icons\n// -------------------------\n\n.#{$fa-css-prefix}-rotate-90 {\n transform: rotate(90deg);\n}\n\n.#{$fa-css-prefix}-rotate-180 {\n transform: rotate(180deg);\n}\n\n.#{$fa-css-prefix}-rotate-270 {\n transform: rotate(270deg);\n}\n\n.#{$fa-css-prefix}-flip-horizontal {\n transform: scale(-1, 1);\n}\n\n.#{$fa-css-prefix}-flip-vertical {\n transform: scale(1, -1);\n}\n\n.#{$fa-css-prefix}-flip-both,\n.#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical {\n transform: scale(-1, -1);\n}\n\n.#{$fa-css-prefix}-rotate-by {\n transform: rotate(var(--#{$fa-css-prefix}-rotate-angle, 0));\n}\n","// stacking icons\n// -------------------------\n\n.#{$fa-css-prefix}-stack {\n display: inline-block;\n height: 2em;\n line-height: 2em;\n position: relative;\n vertical-align: $fa-stack-vertical-align;\n width: $fa-stack-width;\n}\n\n.#{$fa-css-prefix}-stack-1x,\n.#{$fa-css-prefix}-stack-2x {\n left: 0;\n position: absolute;\n text-align: center;\n width: 100%;\n z-index: var(--#{$fa-css-prefix}-stack-z-index, #{$fa-stack-z-index});\n}\n\n.#{$fa-css-prefix}-stack-1x {\n line-height: inherit;\n}\n\n.#{$fa-css-prefix}-stack-2x {\n font-size: 2em;\n}\n\n.#{$fa-css-prefix}-inverse {\n color: var(--#{$fa-css-prefix}-inverse, #{$fa-inverse});\n}\n","// specific icon class definition\n// -------------------------\n\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\nreaders do not read off random characters that represent icons */\n\n@each $name, $icon in $fa-icons {\n .#{$fa-css-prefix}-#{$name}::before { content: unquote(\"\\\"#{ $icon }\\\"\"); }\n}\n\n","// screen-reader utilities\n// -------------------------\n\n// only display content to screen readers\n.sr-only,\n.#{$fa-css-prefix}-sr-only {\n @include fa-sr-only;\n}\n\n// use in conjunction with .sr-only to only display content when it's focused\n.sr-only-focusable,\n.#{$fa-css-prefix}-sr-only-focusable {\n @include fa-sr-only-focusable;\n}\n","/*!\n * Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)\n * Copyright 2024 Fonticons, Inc.\n */\n@import 'functions';\n@import 'variables';\n\n:root, :host {\n --#{$fa-css-prefix}-style-family-classic: '#{ $fa-style-family }';\n --#{$fa-css-prefix}-font-solid: normal 900 1em/1 '#{ $fa-style-family }';\n}\n\n\n@font-face {\n font-family: 'Font Awesome 6 Free';\n font-style: normal;\n font-weight: 900;\n font-display: $fa-font-display;\n src: url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),\n url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype');\n}\n\n.fas,\n.#{$fa-css-prefix}-solid {\n font-weight: 900;\n}\n"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"css/stylesheet.css","mappings":"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;AACF;AACA;EACE,iBAAiB;EACjB;AACF;AACA,kEAAkE;AAClE;;;;EAIE;AACF;AACA,4EAA4E;AAC5E,aAAa;AACb;;;;;EAKE;AACF;AACA,yDAAyD;AACzD;;;;;EAKE;AACF;AACA,sEAAsE;AACtE,uBAAuB;AACvB,0BAA0B;AAC1B,yBAAyB;AACzB,2BAA2B;AAC3B;;;;EAIE;AACF;AACA;EACE,cAAc;EACd;AACF;AACA,+EAA+E;AAC/E;;;CAGC;AACD;;;EAGE;AACF;AACA,8BAA8B;AAC9B;;EAEE;AACF,C;AChKQ;;;;ECFR,CCGA,IACE,0DACA,iCAGF,oDAOE,kCACA,mCACA,wCACA,kBACA,oBACA,cACA,oBAGF,4GAOE,kBAGF,4CAKE,kCAEF,gBAEE,oCCtCA,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,OACE,cADF,QACE,eAMF,QCIA,iBACA,iBACA,sBDNA,OCIA,gBACA,0BACA,sBDNA,OCIA,iBACA,0BACA,6BDNA,OCIA,iBACA,kBACA,uBDNA,OCIA,gBACA,0BACA,wBDNA,QCIA,cACA,qBACA,yBCfF,OACE,kBACA,YCO0B,CCT5B,OACE,qBACA,uCACA,eAEA,4BAGF,OACE,sCACA,kBACA,kBACA,8BACA,oBCbF,WACE,0CACA,6CACA,2CACA,4CACA,sDAGF,cACE,WACA,0CAGF,eACE,YACA,yCCfF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,kEAGF,WACE,yBACA,8CACA,0DACA,oDACA,wEACA,wFAGF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,mFAGF,cACE,4BACA,8CACA,0DACA,oDACA,wEACA,mFAGF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,kEAGF,UACE,wBACA,8CACA,0DACA,oDACA,wEACA,6DAGF,SACE,uBACA,8CACA,0DACA,oDACA,wEACA,6DAGF,iBACE,kCAGF,yBAEE,uBACA,0DACA,oDACA,wEACA,+DAMF,uCACE,gGASE,qBACA,uBACA,4BACA,oBACA,wBAIJ,mBACE,0BACA,iDAGF,qBACE,uCACA,4GACA,wIACA,4GACA,yEACA,wCACA,0CAGF,mBACE,yCAGF,wBACE,QACE,yCACA,mBAEF,IACE,UACA,mDAIJ,mBACE,IACE,kHAIJ,oBACE,4BACA,2BACA,gCACA,gCACA,6BACA,4BACA,6BACA,4BACA,iCAGF,mBACE,0BACA,+BCnJF,cACE,wBAGF,eACE,yBAGF,eACE,yBAGF,oBACE,uBAGF,kBACE,uBAGF,mDAEE,wBAGF,cACE,4CC1BF,UACE,qBACA,WACA,gBACA,kBACA,qBLsC0B,CKrC1B,WLsC0B,CKnC5B,0BAEE,OACA,kBACA,kBACA,WACA,sCAGF,aACE,oBAGF,aACE,cAGF,YACE,8BCvBA,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,MACE,YACA,oBAFF,cACE,SACA,cAFF,qBACE,SACA,cAFF,yBACE,SACA,cAFF,yBACE,SACA,cAFF,OACE,UACA,gBAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,qCACE,SACA,cAFF,iBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,wBACE,SACA,cAFF,gCACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,sBACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,cACE,SACA,cAFF,uBACE,SACA,cAFF,iBACE,SACA,cAFF,SACE,SACA,cAFF,SACE,SACA,cAFF,UACE,SACA,cAFF,4BACE,SACA,cAFF,2BACE,SACA,cAFF,yBACE,SACA,cAFF,wBACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,qBACE,SACA,cAFF,8BACE,SACA,cAFF,oBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,8BACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,mBACE,SACA,cAFF,SACE,SACA,cAFF,wBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,SACE,SACA,cAFF,6BACE,SACA,cAFF,mBACE,SACA,cAFF,8BACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,4BACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,MACE,SACA,cAFF,kBACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,sBACE,SACA,cAFF,mBACE,SACA,cAFF,mBACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,8BACE,SACA,cAFF,iBACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,yBACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,oBACE,SACA,cAFF,mBACE,SACA,cAFF,sBACE,SACA,cAFF,0BACE,SACA,cAFF,4BACE,SACA,cAFF,uBACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,MACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,yBACE,SACA,cAFF,eACE,SACA,cAFF,QACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,kBACE,SACA,cAFF,0BACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,qBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,6BACE,SACA,cAFF,yBACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,QACE,SACA,cAFF,mBACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,iCACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,yBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,wBACE,SACA,cAFF,SACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,6BACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,qBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,wBACE,SACA,cAFF,6BACE,SACA,cAFF,aACE,SACA,cAFF,wBACE,SACA,cAFF,wBACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,wBACE,SACA,cAFF,sBACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,0BACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,wBACE,SACA,cAFF,aACE,UACA,gBAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,sBACE,SACA,cAFF,qBACE,SACA,cAFF,cACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,QACE,SACA,cAFF,+BACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,uBACE,SACA,cAFF,mBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,oBACE,SACA,cAFF,wBACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,OACE,SACA,cAFF,SACE,SACA,cAFF,uBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,wBACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,sBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,WACE,SACA,cAFF,MACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,MACE,SACA,cAFF,0BACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,sBACE,SACA,cAFF,0BACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,iCACE,SACA,cAFF,YACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,MACE,SACA,cAFF,MACE,SACA,cAFF,kBACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,qBACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,oBACE,SACA,cAFF,0BACE,SACA,cAFF,WACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,qBACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,2BACE,SACA,cAFF,wBACE,SACA,cAFF,wBACE,SACA,cAFF,MACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,8BACE,SACA,cAFF,SACE,SACA,cAFF,wBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,sBACE,SACA,cAFF,gBACE,SACA,cAFF,mBACE,SACA,cAFF,MACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,wBACE,SACA,cAFF,QACE,SACA,cAFF,WACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,QACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,sBACE,SACA,cAFF,qBACE,SACA,cAFF,WACE,SACA,cAFF,2BACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,wBACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,wBACE,SACA,cAFF,6BACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,UACE,SACA,cAFF,2BACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,WACE,SACA,cAFF,sBACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,yBACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,qBACE,SACA,cAFF,iBACE,SACA,cAFF,qBACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,iBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,MACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,qBACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,cACE,SACA,cAFF,6BACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,YACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,iBACE,SACA,cAFF,qBACE,SACA,cAFF,mBACE,SACA,cAFF,SACE,SACA,cAFF,yBACE,SACA,cAFF,SACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,wBACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,QACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,+BACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,QACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,wBACE,SACA,cAFF,aACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,QACE,SACA,cAFF,SACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,qBACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,mBACE,SACA,cAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,WACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,qBACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,cACE,SACA,cAFF,YACE,SACA,cAFF,2CACE,SACA,cAFF,kBACE,SACA,cAFF,QACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,2BACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,4BACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,yBACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,gBACE,SACA,cAFF,wBACE,SACA,cAFF,0BACE,SACA,cAFF,yBACE,SACA,cAFF,aACE,SACA,cAFF,WACE,SACA,cAFF,QACE,SACA,cAFF,sBACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,sBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,UACE,SACA,cAFF,0BACE,SACA,cAFF,wBACE,SACA,cAFF,cACE,SACA,cAFF,uBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,iBACE,SACA,cAFF,qBACE,SACA,cAFF,YACE,SACA,cAFF,sBACE,SACA,cAFF,SACE,SACA,cAFF,UACE,SACA,cAFF,0BACE,SACA,cAFF,aACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,wBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,0BACE,SACA,cAFF,oBACE,SACA,cAFF,qBACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,sBACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,qBACE,SACA,cAFF,mBACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,qBACE,SACA,cAFF,mBACE,SACA,cAFF,kBACE,SACA,cAFF,2BACE,SACA,cAFF,wBACE,SACA,cAFF,oBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,SACE,SACA,cAFF,sBACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,0BACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,uBACE,SACA,cAFF,wBACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,wBACE,SACA,cAFF,kBACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,WACE,SACA,cAFF,4BACE,SACA,cAFF,WACE,SACA,cAFF,oBACE,SACA,cAFF,aACE,SACA,cAFF,MACE,SACA,cAFF,kBACE,SACA,cAFF,WACE,SACA,cAFF,cACE,SACA,cAFF,MACE,SACA,cAFF,2BACE,SACA,cAFF,qBACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,MACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,OACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,wBACE,SACA,cAFF,WACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,aACE,SACA,cAFF,yBACE,SACA,cAFF,oBACE,SACA,cAFF,WACE,SACA,cAFF,aACE,UACA,gBAFF,mBACE,SACA,cAFF,uBACE,SACA,cAFF,eACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,gCACE,SACA,cAFF,2BACE,SACA,cAFF,+BACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,QACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,MACE,SACA,cAFF,SACE,SACA,cAFF,SACE,SACA,cAFF,SACE,SACA,cAFF,QACE,SACA,cAFF,uBACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,2BACE,SACA,cAFF,uBACE,SACA,cAFF,sBACE,SACA,cAFF,qBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,2BACE,SACA,cAFF,MACE,SACA,cAFF,SACE,SACA,cAFF,uBACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,qBACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,yBACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,uBACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,MACE,SACA,cAFF,wBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,wBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,wBACE,SACA,cAFF,wBACE,SACA,cAFF,yCACE,SACA,cAFF,2BACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,mBACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,yBACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,cACE,SACA,cAFF,WACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,8BACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,QACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,sBACE,SACA,cAFF,8BACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,QACE,SACA,cAFF,sBACE,SACA,cAFF,cACE,SACA,cAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,QACE,SACA,cAFF,uBACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,qBACE,SACA,cAFF,uBACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,wBACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,uBACE,SACA,cAFF,yBACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,wBACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,mBACE,SACA,cAFF,mBACE,SACA,cAFF,oBACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,qBACE,SACA,cAFF,uBACE,SACA,cAFF,iBACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,UACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,wBACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,MACE,SACA,cAFF,qBACE,SACA,cAFF,eACE,SACA,cAFF,yBACE,SACA,cAFF,sBACE,SACA,cAFF,gBACE,SACA,cAFF,OACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,MACE,SACA,cAFF,qBACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,kBACE,SACA,cAFF,oBACE,SACA,cAFF,sBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,iBACE,SACA,cAFF,yBACE,SACA,cAFF,oBACE,SACA,cAFF,mBACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,QACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,wBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,mBACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,qBACE,SACA,cAFF,sBACE,SACA,cAFF,yBACE,SACA,cAFF,uBACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,gCACE,SACA,cAFF,4BACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,mBACE,SACA,cAFF,oBACE,SACA,cAFF,qBACE,SACA,cAFF,WACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,0BACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,QACE,SACA,cAFF,2BACE,SACA,cAFF,sBACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,+BACE,SACA,cAFF,yBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,sBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,2BACE,SACA,cAFF,wCACE,SACA,cAFF,qBACE,SACA,cAFF,8CACE,SACA,cAFF,SACE,SACA,cAFF,QACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,0BACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,UACE,SACA,cAFF,qBACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,MACE,SACA,cAFF,yBACE,SACA,cAFF,oBACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,sBACE,SACA,cAFF,MACE,SACA,cAFF,aACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,0BACE,SACA,cAFF,mBACE,SACA,cAFF,+BACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,+BACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,UACE,SACA,cAFF,WACE,SACA,cAFF,YACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,yBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,qCACE,SACA,cAFF,sBACE,SACA,cAFF,kBACE,SACA,cAFF,WACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,MACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,0BACE,SACA,cAFF,SACE,SACA,cAFF,wBACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,QACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,YACE,SACA,cAFF,oBACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,6BACE,SACA,cAFF,UACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,MACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,2BACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,wBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,sBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,oBACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,SACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,QACE,SACA,cAFF,QACE,SACA,cAFF,QACE,SACA,cAFF,QACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,QACE,SACA,cAFF,UACE,SACA,cAFF,QACE,SACA,cAFF,WACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,wBACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,qBACE,SACA,cAFF,yBACE,SACA,cAFF,cACE,UACA,gBAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,qBACE,SACA,cAFF,qBACE,SACA,cAFF,wBACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,0BACE,SACA,cAFF,YACE,SACA,cAFF,yBACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,QACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,8BACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,yBACE,SACA,cAFF,mBACE,SACA,cAFF,UACE,SACA,cAFF,QACE,SACA,cAFF,aACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,qBACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,UACA,gBAFF,oBACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,iBACE,SACA,cAFF,SACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,wBACE,SACA,cAFF,uBACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,iBACE,SACA,cAFF,WACE,SACA,cAFF,6BACE,SACA,cAFF,UACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,sBACE,SACA,cAFF,QACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,kBACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,gCACE,SACA,cAFF,cACE,SACA,cAFF,SACE,SACA,cAFF,SACE,SACA,cAFF,yBACE,SACA,cAFF,gBACE,SACA,cAFF,qBACE,SACA,cAFF,WACE,SACA,cAFF,6BACE,SACA,cAFF,0BACE,SACA,cAFF,iBACE,SACA,cAFF,0BACE,SACA,cAFF,cACE,SACA,cAFF,uBACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,cACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,qBACE,SACA,cAFF,8BACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,cACE,SACA,cAFF,qBACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,qBACE,SACA,cAFF,wBACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,OACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,MACE,SACA,cAFF,wBACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,WACE,SACA,cAFF,iBACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,SACE,SACA,cAFF,oBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,SACE,UACA,gBAFF,QACE,UACA,gBAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,aACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,8BACE,SACA,cAFF,WACE,SACA,cAFF,oBACE,SACA,cAFF,uBACE,SACA,cAFF,cACE,SACA,cAFF,oBACE,SACA,cAFF,SACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,mBACE,SACA,cAFF,YACE,SACA,cAFF,mBACE,SACA,cAFF,kBACE,SACA,cAFF,uBACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,WACE,UACA,gBAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,WACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,uBACE,SACA,cAFF,UACE,SACA,cAFF,mBACE,SACA,cAFF,sBACE,SACA,cAFF,iBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,gBACE,SACA,cAFF,SACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,YACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,iBACE,SACA,cAFF,uBACE,SACA,cAFF,YACE,UACA,gBAFF,eACE,UACA,gBAFF,iBACE,SACA,cAFF,wBACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,mBACE,SACA,cAFF,SACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,YACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,YACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,yBACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,aACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,WACE,SACA,cAFF,sBACE,SACA,cAFF,YACE,SACA,cAFF,yBACE,SACA,cAFF,oBACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,WACE,SACA,cAFF,iBACE,SACA,cAFF,wBACE,SACA,cAFF,uBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,wBACE,SACA,cAFF,yBACE,SACA,cAFF,YACE,SACA,cAFF,yBACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,QACE,SACA,cAFF,WACE,SACA,cAFF,SACE,SACA,cAFF,qBACE,SACA,cAFF,mBACE,SACA,cAFF,WACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,oBACE,SACA,cAFF,kBACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,UACA,gBAFF,uCACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,MACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,aACE,SACA,cAFF,sBACE,SACA,cAFF,8BACE,SACA,cAFF,cACE,SACA,cAFF,QACE,SACA,cAFF,2BACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,UACE,SACA,cAFF,WACE,SACA,cAFF,YACE,SACA,cAFF,WACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,qBACE,SACA,cAFF,iBACE,SACA,cAFF,4BACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,mCACE,SACA,cAFF,iBACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,aACE,SACA,cAFF,YACE,SACA,cAFF,qBACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,gBACE,SACA,cAFF,qBACE,SACA,cAFF,QACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,kBACE,SACA,cAFF,sBACE,SACA,cAFF,eACE,SACA,cAFF,oBACE,SACA,cAFF,WACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,MACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,QACE,SACA,cAFF,SACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,2BACE,SACA,cAFF,cACE,SACA,cAFF,uBACE,SACA,cAFF,eACE,SACA,cAFF,sBACE,SACA,cAFF,sBACE,SACA,cAFF,6BACE,SACA,cAFF,cACE,SACA,cAFF,gBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,aACE,SACA,cAFF,QACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,0BACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,iBACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,wBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,yBACE,SACA,cAFF,yBACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,4BACE,SACA,cAFF,YACE,SACA,cAFF,gBACE,SACA,cAFF,sBACE,SACA,cAFF,wBACE,SACA,cAFF,cACE,SACA,cAFF,UACE,SACA,cAFF,kBACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,mBACE,SACA,cAFF,aACE,SACA,cAFF,iBACE,SACA,cAFF,YACE,SACA,cAFF,oBACE,SACA,cAFF,mBACE,SACA,cAFF,cACE,SACA,cAFF,mBACE,SACA,cAFF,+BACE,SACA,cAFF,oBACE,SACA,cAFF,oBACE,SACA,cAFF,SACE,SACA,cAFF,iBACE,SACA,cAFF,UACE,SACA,cAFF,YACE,SACA,cAFF,aACE,SACA,cAFF,mBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,iBACE,SACA,cAFF,UACE,SACA,cAFF,UACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,0BACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,oBACE,SACA,cAFF,eACE,SACA,cAFF,WACE,SACA,cAFF,UACE,SACA,cAFF,qBACE,SACA,cAFF,SACE,SACA,cAFF,2BACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,eACE,SACA,cAFF,aACE,SACA,cAFF,eACE,SACA,cAFF,eACE,SACA,cAFF,YACE,SACA,cAFF,cACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,QACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,cACE,SACA,cAFF,6BACE,SACA,cAFF,SACE,SACA,cAFF,2BACE,SACA,cAFF,iBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,UACE,SACA,cAFF,qBACE,SACA,cAFF,gBACE,UACA,gBAFF,gBACE,SACA,cAFF,UACE,SACA,cAFF,sBACE,SACA,cAFF,QACE,SACA,cAFF,iBACE,SACA,cAFF,gBACE,UACA,gBAFF,WACE,UACA,gBAFF,QACE,UACA,gBAFF,MACE,SACA,cAFF,4BACE,SACA,cAFF,kBACE,SACA,cAFF,eACE,SACA,cAFF,cACE,SACA,cAFF,6BACE,SACA,cAFF,qBACE,SACA,cAFF,SACE,SACA,cAFF,gBACE,SACA,cAFF,WACE,SACA,cAFF,eACE,SACA,cAFF,aACE,SACA,cAFF,WACE,SACA,cAFF,MACE,SACA,cAFF,YACE,SACA,cAFF,kBACE,SACA,cAFF,kBACE,SACA,cAFF,aACE,SACA,cAFF,oBACE,SACA,cAFF,qBACE,SACA,cAFF,kBACE,SACA,cAFF,gBACE,SACA,cAFF,gBACE,SACA,cAFF,uBACE,SACA,cAFF,qBACE,SACA,cAFF,YACE,SACA,cAFF,eACE,SACA,cAFF,UACE,SACA,cAFF,iBACE,SACA,cAFF,mBACE,SACA,cAFF,iBACE,SACA,cAFF,yBACE,SACA,cAFF,wBACE,SACA,cAFF,YACE,SACA,cAFF,iBACE,SACA,cCLJ,qBTqBE,kBACA,UACA,WACA,UACA,YACA,gBACA,sBACA,mBACA,eAKA,iEAbA,kBACA,UACA,WACA,UACA,YACA,gBACA,sBACA,mBACA,eUjCF;;;;EAAA,CAQA,YACE,iDACA,wDAIF,WACE,kCACA,kBACA,gBACA,kBRgC0B,CQ/B1B,2GAIF,eAEE,gBdRF,EACE,SACA,UAGF,UAEE,YAGF,KACE,uBACA,gBACA,gBAGF,MACE,UACA,iBACA,YACA,kBAGF,WACE,WAGF,yBACE,YAGF,WACE,YAGF,yBACE,WAGF,QACE,kBAGF,UAEE,mBACA,sBAGF,EACE,kBAGF,GACE,aACA,cACA,gBAGF,GACE,aACA,gBACA,gBACA,cACA,6BAGF,GACE,gBACA,cACA,UACA,aAGF,EACE,eACA,kBAGF,EACE,cAEA,oJAME,WACA,sBACA,iBAGF,gBAEE,eAIJ,UACE,gBAGF,GACE,mBAGF,SAEE,iBAGF,qBAKE,sBACA,gBACA,gBAGF,SACE,sBAUF,+BAIE,oCACA,iCACA,gCACA,+BACA,4BAMF,qBACE,WACA,WAOF,MACE,mBACA,WACA,eACA,MACA,QACA,SACA,aACA,kBArLiF,CAsLjF,gBACA,iCAMF,QACE,WACA,YACA,yBAMF,qCAEE,YACA,yBAMF,wDAEE,6BAMF,mDAEE,kBAzNkB,CA0NlB,WAMF,4BACE,WAMF,yBACE,eACA,WACA,SACA,oBAcF,WACE,kBACA,cACA,MACA,QACA,yBACA,WACA,YACA,eACA,qBAEA,kCAEE,eACA,2BAIJ,gBACE,kBACA,cACA,WAGF,+DAGE,+BAGF,4CAEE,qBAKF,oCACE,eACE,kBACA,WAKF,2BACE,eACA,WAGF,aACE,mBAOJ,QACE,YACA,yEAGF,aACE,cACA,YACA,cAGF,MACE,uBACA,gBACA,WACA,8BAGF,QACE,gBAGF,MACE,+BACA,uBACA,gBACA,oBAGF,eACE,uBACA,gBACA,gBACA,4BAGF,cACE,YAMF,QACE,QACA,gBACA,gBAGA,oBAGF,SACE,gBACA,oBAGF,aACE,yBACA,gCACA,yCACA,cACA,eACA,kBAGF,mBACE,yBACA,0BAGF,qBACE,wBA/Wa,CAgXb,0BAGF,qBACE,yBACA,0BAGF,cACE,eACA,UAGF,UACE,kBACA,sBAEA,YACE,aAIJ,kBACE,qBACA,cACA,iBACA,iBACA,qBACA,eACA,YACA,qBACA,sBAEA,6BACE,WACA,kBAnZW,CAuZf,gBACE,6BACA,yBACA,yBAGF,gBACE,UAOF,cAEE,YAGF,QACE,WACA,yEACA,YACA,iBACA,kBACA,WAEA,4BAEE,WAEA,gFAEE,sBACA,WACA,eACA,qBACA,oBACA,qBAKN,YACE,kBACA,cACA,gBAGF,mBACE,kBACA,QACA,QACA,6BAGF,iCACE,WACA,OAGF,aACE,YAMF,WACE,gBACA,WACA,eACA,iBAGF,uCACE,eACA,cAGF,iBACE,WAGF,aACE,aACA,uBAGF,qCAEE,eAGF,wBACE,WAGF,gBACE,kBACA,OACA,QACA,6BAIF,4DAGE,gBAGF,gCACE,kBACA,wBAGF,oBACE,kBAGF,kCACE,kBAGF,aACE,YAGF,2BACE,WAMF,+BACE,yBACA,sBACA,kBACA,QACA,eACA,gBACA,iBAGF,aACE,gBAEA,sCAEE,sBACA,iBACA,WAIJ,iBACE,yBACA,WAEA,8CAEE,sBACA,iBAIJ,oBACE,sBACA,cACA,yBAGF,0BACE,sBAGF,8BACE,YACA,gBACA,oBACA,uBACA,yBACA,sBACA,qBACA,iBAGF,kBACE,qBACA,SACA,+BAEA,gDAEE,yBACA,WAIJ,uFAEE,gBAGF,6CACE,SACA,kBACA,yBAGF,qCACE,eAGF,yDACE,kBAGF,wDACE,+BAGF,2CACE,gBACA,gBAGF,kBACE,kBACA,aAGF,4BACE,aAMF,IACE,wDACA,gBAGF,aAEE,eAGF,uCAEE,UAMF,uBACE,mBACA,WAGF,UACE,iBAGF,WACE,yBAGF,oBACE,gBAOF,oCACE,8BACE,YAIJ,oCACE,MACE,UAGF,kCACE,gBACA,WAGF,QACE,cACA,oBAGF,cACE,UAGF,MACE,gBAGF,QACE,cACA,mBAEA,oBACE,YACA,eAKN,8DACE,qBACE,wBAGF,sBACE,sBAIJ,oCACE,gBACE,yBAIJ,oCACE,gBACE,yBAQJ,iBACE,uBACA,gBACA,gBAGF,OACE,WAGF,aACE,eAGF,YACE,sBACA,WAEA,qBACE,YAGF,qBACE,aACA,YAGF,sBACE,eACA,kBACA,cACA,cACA,WACA,yBACA,0BAEA,wDAEE,sBACA,WAGF,6BACE,YACA,6CACA,gBAKF,8BACE,cACA,6BACA,8BAGF,+BACE,mBACA,0BACA,6BACA,8BAEA,sCACE,YAMR,QACE,aAGF,KACE,wBACA,YACA,WAGF,cACE,iBACA,iBAGF,cACE,gBACA,WAGF,OACE,YAGF,MACE,W","sources":["webpack://simplesamlphp-assets/./node_modules/reset-css/reset.css","webpack://simplesamlphp-assets/./node_modules/purecss/build/pure.css","webpack://simplesamlphp-assets/./node_modules/highlight.js/styles/base16/zenburn.css","webpack://simplesamlphp-assets/./resources/css/default.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_core.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_sizing.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_mixins.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_fixed-width.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_variables.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_list.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_bordered-pulled.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_animated.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_rotated-flipped.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_stacked.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_icons.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/_screen-reader.scss","webpack://simplesamlphp-assets/./node_modules/@fortawesome/fontawesome-free/scss/solid.scss"],"sourcesContent":["/* http://meyerweb.com/eric/tools/css/reset/\n v5.0.1 | 20191019\n License: none (public domain)\n*/\n\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmain, menu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tfont-size: 100%;\n\tfont: inherit;\n\tvertical-align: baseline;\n}\n/* HTML5 display-role reset for older browsers */\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, main, menu, nav, section {\n\tdisplay: block;\n}\n/* HTML5 hidden-attribute fix for newer browsers */\n*[hidden] {\n display: none;\n}\nbody {\n\tline-height: 1;\n}\nmenu, ol, ul {\n\tlist-style: none;\n}\nblockquote, q {\n\tquotes: none;\n}\nblockquote:before, blockquote:after,\nq:before, q:after {\n\tcontent: '';\n\tcontent: none;\n}\ntable {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n","/*!\nPure v3.0.0\nCopyright 2013 Yahoo!\nLicensed under the BSD License.\nhttps://github.com/pure-css/pure/blob/master/LICENSE\n*/\n/*!\nnormalize.css v | MIT License | https://necolas.github.io/normalize.css/\nCopyright (c) Nicolas Gallagher and Jonathan Neal\n*/\n/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n\n/*csslint important:false*/\n\n/* ==========================================================================\n Pure Base Extras\n ========================================================================== */\n\n/**\n * Extra rules that Pure adds on top of Normalize.css\n */\n\nhtml {\n font-family: sans-serif;\n}\n\n/**\n * Always hide an element when it has the `hidden` HTML attribute.\n */\n\n.hidden,\n[hidden] {\n display: none !important;\n}\n\n/**\n * Add this class to an image to make it fit within it's fluid parent wrapper while maintaining\n * aspect ratio.\n */\n.pure-img {\n max-width: 100%;\n height: auto;\n display: block;\n}\n\n/*csslint regex-selectors:false, known-properties:false, duplicate-properties:false*/\n\n.pure-g {\n display: flex;\n flex-flow: row wrap;\n\n /* Prevents distributing space between rows */\n align-content: flex-start;\n}\n\n.pure-u {\n display: inline-block;\n vertical-align: top;\n}\n\n.pure-u-1,\n.pure-u-1-1,\n.pure-u-1-2,\n.pure-u-1-3,\n.pure-u-2-3,\n.pure-u-1-4,\n.pure-u-3-4,\n.pure-u-1-5,\n.pure-u-2-5,\n.pure-u-3-5,\n.pure-u-4-5,\n.pure-u-5-5,\n.pure-u-1-6,\n.pure-u-5-6,\n.pure-u-1-8,\n.pure-u-3-8,\n.pure-u-5-8,\n.pure-u-7-8,\n.pure-u-1-12,\n.pure-u-5-12,\n.pure-u-7-12,\n.pure-u-11-12,\n.pure-u-1-24,\n.pure-u-2-24,\n.pure-u-3-24,\n.pure-u-4-24,\n.pure-u-5-24,\n.pure-u-6-24,\n.pure-u-7-24,\n.pure-u-8-24,\n.pure-u-9-24,\n.pure-u-10-24,\n.pure-u-11-24,\n.pure-u-12-24,\n.pure-u-13-24,\n.pure-u-14-24,\n.pure-u-15-24,\n.pure-u-16-24,\n.pure-u-17-24,\n.pure-u-18-24,\n.pure-u-19-24,\n.pure-u-20-24,\n.pure-u-21-24,\n.pure-u-22-24,\n.pure-u-23-24,\n.pure-u-24-24 {\n display: inline-block;\n letter-spacing: normal;\n word-spacing: normal;\n vertical-align: top;\n text-rendering: auto;\n}\n\n.pure-u-1-24 {\n width: 4.1667%;\n}\n\n.pure-u-1-12,\n.pure-u-2-24 {\n width: 8.3333%;\n}\n\n.pure-u-1-8,\n.pure-u-3-24 {\n width: 12.5000%;\n}\n\n.pure-u-1-6,\n.pure-u-4-24 {\n width: 16.6667%;\n}\n\n.pure-u-1-5 {\n width: 20%;\n}\n\n.pure-u-5-24 {\n width: 20.8333%;\n}\n\n.pure-u-1-4,\n.pure-u-6-24 {\n width: 25%;\n}\n\n.pure-u-7-24 {\n width: 29.1667%;\n}\n\n.pure-u-1-3,\n.pure-u-8-24 {\n width: 33.3333%;\n}\n\n.pure-u-3-8,\n.pure-u-9-24 {\n width: 37.5000%;\n}\n\n.pure-u-2-5 {\n width: 40%;\n}\n\n.pure-u-5-12,\n.pure-u-10-24 {\n width: 41.6667%;\n}\n\n.pure-u-11-24 {\n width: 45.8333%;\n}\n\n.pure-u-1-2,\n.pure-u-12-24 {\n width: 50%;\n}\n\n.pure-u-13-24 {\n width: 54.1667%;\n}\n\n.pure-u-7-12,\n.pure-u-14-24 {\n width: 58.3333%;\n}\n\n.pure-u-3-5 {\n width: 60%;\n}\n\n.pure-u-5-8,\n.pure-u-15-24 {\n width: 62.5000%;\n}\n\n.pure-u-2-3,\n.pure-u-16-24 {\n width: 66.6667%;\n}\n\n.pure-u-17-24 {\n width: 70.8333%;\n}\n\n.pure-u-3-4,\n.pure-u-18-24 {\n width: 75%;\n}\n\n.pure-u-19-24 {\n width: 79.1667%;\n}\n\n.pure-u-4-5 {\n width: 80%;\n}\n\n.pure-u-5-6,\n.pure-u-20-24 {\n width: 83.3333%;\n}\n\n.pure-u-7-8,\n.pure-u-21-24 {\n width: 87.5000%;\n}\n\n.pure-u-11-12,\n.pure-u-22-24 {\n width: 91.6667%;\n}\n\n.pure-u-23-24 {\n width: 95.8333%;\n}\n\n.pure-u-1,\n.pure-u-1-1,\n.pure-u-5-5,\n.pure-u-24-24 {\n width: 100%;\n}\n.pure-button {\n /* Structure */\n display: inline-block;\n line-height: normal;\n white-space: nowrap;\n vertical-align: middle;\n text-align: center;\n cursor: pointer;\n -webkit-user-drag: none;\n -webkit-user-select: none;\n user-select: none;\n box-sizing: border-box;\n}\n\n/* Firefox: Get rid of the inner focus border */\n.pure-button::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\n\n/* Inherit .pure-g styles */\n.pure-button-group {\n letter-spacing: -0.31em; /* Webkit: collapse white-space between units */\n text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */\n}\n\n.opera-only :-o-prefocus,\n.pure-button-group {\n word-spacing: -0.43em;\n}\n\n.pure-button-group .pure-button {\n letter-spacing: normal;\n word-spacing: normal;\n vertical-align: top;\n text-rendering: auto;\n}\n\n/*csslint outline-none:false*/\n\n.pure-button {\n font-family: inherit;\n font-size: 100%;\n padding: 0.5em 1em;\n color: rgba(0, 0, 0, 0.80);\n border: none rgba(0, 0, 0, 0);\n background-color: #E6E6E6;\n text-decoration: none;\n border-radius: 2px;\n}\n\n.pure-button-hover,\n.pure-button:hover,\n.pure-button:focus {\n background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));\n}\n.pure-button:focus {\n outline: 0;\n}\n.pure-button-active,\n.pure-button:active {\n box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;\n border-color: #000;\n}\n\n.pure-button[disabled],\n.pure-button-disabled,\n.pure-button-disabled:hover,\n.pure-button-disabled:focus,\n.pure-button-disabled:active {\n border: none;\n background-image: none;\n opacity: 0.40;\n cursor: not-allowed;\n box-shadow: none;\n pointer-events: none;\n}\n\n.pure-button-hidden {\n display: none;\n}\n\n.pure-button-primary,\n.pure-button-selected,\na.pure-button-primary,\na.pure-button-selected {\n background-color: rgb(0, 120, 231);\n color: #fff;\n}\n\n/* Button Groups */\n.pure-button-group .pure-button {\n margin: 0;\n border-radius: 0;\n border-right: 1px solid rgba(0, 0, 0, 0.2);\n\n}\n\n.pure-button-group .pure-button:first-child {\n border-top-left-radius: 2px;\n border-bottom-left-radius: 2px;\n}\n.pure-button-group .pure-button:last-child {\n border-top-right-radius: 2px;\n border-bottom-right-radius: 2px;\n border-right: none;\n}\n\n/*csslint box-model:false*/\n/*\nBox-model set to false because we're setting a height on select elements, which\nalso have border and padding. This is done because some browsers don't render\nthe padding. We explicitly set the box-model for select elements to border-box,\nso we can ignore the csslint warning.\n*/\n\n.pure-form input[type=\"text\"],\n.pure-form input[type=\"password\"],\n.pure-form input[type=\"email\"],\n.pure-form input[type=\"url\"],\n.pure-form input[type=\"date\"],\n.pure-form input[type=\"month\"],\n.pure-form input[type=\"time\"],\n.pure-form input[type=\"datetime\"],\n.pure-form input[type=\"datetime-local\"],\n.pure-form input[type=\"week\"],\n.pure-form input[type=\"number\"],\n.pure-form input[type=\"search\"],\n.pure-form input[type=\"tel\"],\n.pure-form input[type=\"color\"],\n.pure-form select,\n.pure-form textarea {\n padding: 0.5em 0.6em;\n display: inline-block;\n border: 1px solid #ccc;\n box-shadow: inset 0 1px 3px #ddd;\n border-radius: 4px;\n vertical-align: middle;\n box-sizing: border-box;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form input:not([type]) {\n padding: 0.5em 0.6em;\n display: inline-block;\n border: 1px solid #ccc;\n box-shadow: inset 0 1px 3px #ddd;\n border-radius: 4px;\n box-sizing: border-box;\n}\n\n\n/* Chrome (as of v.32/34 on OS X) needs additional room for color to display. */\n/* May be able to remove this tweak as color inputs become more standardized across browsers. */\n.pure-form input[type=\"color\"] {\n padding: 0.2em 0.5em;\n}\n\n\n.pure-form input[type=\"text\"]:focus,\n.pure-form input[type=\"password\"]:focus,\n.pure-form input[type=\"email\"]:focus,\n.pure-form input[type=\"url\"]:focus,\n.pure-form input[type=\"date\"]:focus,\n.pure-form input[type=\"month\"]:focus,\n.pure-form input[type=\"time\"]:focus,\n.pure-form input[type=\"datetime\"]:focus,\n.pure-form input[type=\"datetime-local\"]:focus,\n.pure-form input[type=\"week\"]:focus,\n.pure-form input[type=\"number\"]:focus,\n.pure-form input[type=\"search\"]:focus,\n.pure-form input[type=\"tel\"]:focus,\n.pure-form input[type=\"color\"]:focus,\n.pure-form select:focus,\n.pure-form textarea:focus {\n outline: 0;\n border-color: #129FEA;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form input:not([type]):focus {\n outline: 0;\n border-color: #129FEA;\n}\n\n.pure-form input[type=\"file\"]:focus,\n.pure-form input[type=\"radio\"]:focus,\n.pure-form input[type=\"checkbox\"]:focus {\n outline: thin solid #129FEA;\n outline: 1px auto #129FEA;\n}\n.pure-form .pure-checkbox,\n.pure-form .pure-radio {\n margin: 0.5em 0;\n display: block;\n}\n\n.pure-form input[type=\"text\"][disabled],\n.pure-form input[type=\"password\"][disabled],\n.pure-form input[type=\"email\"][disabled],\n.pure-form input[type=\"url\"][disabled],\n.pure-form input[type=\"date\"][disabled],\n.pure-form input[type=\"month\"][disabled],\n.pure-form input[type=\"time\"][disabled],\n.pure-form input[type=\"datetime\"][disabled],\n.pure-form input[type=\"datetime-local\"][disabled],\n.pure-form input[type=\"week\"][disabled],\n.pure-form input[type=\"number\"][disabled],\n.pure-form input[type=\"search\"][disabled],\n.pure-form input[type=\"tel\"][disabled],\n.pure-form input[type=\"color\"][disabled],\n.pure-form select[disabled],\n.pure-form textarea[disabled] {\n cursor: not-allowed;\n background-color: #eaeded;\n color: #cad2d3;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form input:not([type])[disabled] {\n cursor: not-allowed;\n background-color: #eaeded;\n color: #cad2d3;\n}\n.pure-form input[readonly],\n.pure-form select[readonly],\n.pure-form textarea[readonly] {\n background-color: #eee; /* menu hover bg color */\n color: #777; /* menu text color */\n border-color: #ccc;\n}\n\n.pure-form input:focus:invalid,\n.pure-form textarea:focus:invalid,\n.pure-form select:focus:invalid {\n color: #b94a48;\n border-color: #e9322d;\n}\n.pure-form input[type=\"file\"]:focus:invalid:focus,\n.pure-form input[type=\"radio\"]:focus:invalid:focus,\n.pure-form input[type=\"checkbox\"]:focus:invalid:focus {\n outline-color: #e9322d;\n}\n.pure-form select {\n /* Normalizes the height; padding is not sufficient. */\n height: 2.25em;\n border: 1px solid #ccc;\n background-color: white;\n}\n.pure-form select[multiple] {\n height: auto;\n}\n.pure-form label {\n margin: 0.5em 0 0.2em;\n}\n.pure-form fieldset {\n margin: 0;\n padding: 0.35em 0 0.75em;\n border: 0;\n}\n.pure-form legend {\n display: block;\n width: 100%;\n padding: 0.3em 0;\n margin-bottom: 0.3em;\n color: #333;\n border-bottom: 1px solid #e5e5e5;\n}\n\n.pure-form-stacked input[type=\"text\"],\n.pure-form-stacked input[type=\"password\"],\n.pure-form-stacked input[type=\"email\"],\n.pure-form-stacked input[type=\"url\"],\n.pure-form-stacked input[type=\"date\"],\n.pure-form-stacked input[type=\"month\"],\n.pure-form-stacked input[type=\"time\"],\n.pure-form-stacked input[type=\"datetime\"],\n.pure-form-stacked input[type=\"datetime-local\"],\n.pure-form-stacked input[type=\"week\"],\n.pure-form-stacked input[type=\"number\"],\n.pure-form-stacked input[type=\"search\"],\n.pure-form-stacked input[type=\"tel\"],\n.pure-form-stacked input[type=\"color\"],\n.pure-form-stacked input[type=\"file\"],\n.pure-form-stacked select,\n.pure-form-stacked label,\n.pure-form-stacked textarea {\n display: block;\n margin: 0.25em 0;\n}\n\n/*\nNeed to separate out the :not() selector from the rest of the CSS 2.1 selectors\nsince IE8 won't execute CSS that contains a CSS3 selector.\n*/\n.pure-form-stacked input:not([type]) {\n display: block;\n margin: 0.25em 0;\n}\n.pure-form-aligned input,\n.pure-form-aligned textarea,\n.pure-form-aligned select,\n.pure-form-message-inline {\n display: inline-block;\n vertical-align: middle;\n}\n.pure-form-aligned textarea {\n vertical-align: top;\n}\n\n/* Aligned Forms */\n.pure-form-aligned .pure-control-group {\n margin-bottom: 0.5em;\n}\n.pure-form-aligned .pure-control-group label {\n text-align: right;\n display: inline-block;\n vertical-align: middle;\n width: 10em;\n margin: 0 1em 0 0;\n}\n.pure-form-aligned .pure-controls {\n margin: 1.5em 0 0 11em;\n}\n\n/* Rounded Inputs */\n.pure-form input.pure-input-rounded,\n.pure-form .pure-input-rounded {\n border-radius: 2em;\n padding: 0.5em 1em;\n}\n\n/* Grouped Inputs */\n.pure-form .pure-group fieldset {\n margin-bottom: 10px;\n}\n.pure-form .pure-group input,\n.pure-form .pure-group textarea {\n display: block;\n padding: 10px;\n margin: 0 0 -1px;\n border-radius: 0;\n position: relative;\n top: -1px;\n}\n.pure-form .pure-group input:focus,\n.pure-form .pure-group textarea:focus {\n z-index: 3;\n}\n.pure-form .pure-group input:first-child,\n.pure-form .pure-group textarea:first-child {\n top: 1px;\n border-radius: 4px 4px 0 0;\n margin: 0;\n}\n.pure-form .pure-group input:first-child:last-child,\n.pure-form .pure-group textarea:first-child:last-child {\n top: 1px;\n border-radius: 4px;\n margin: 0;\n}\n.pure-form .pure-group input:last-child,\n.pure-form .pure-group textarea:last-child {\n top: -2px;\n border-radius: 0 0 4px 4px;\n margin: 0;\n}\n.pure-form .pure-group button {\n margin: 0.35em 0;\n}\n\n.pure-form .pure-input-1 {\n width: 100%;\n}\n.pure-form .pure-input-3-4 {\n width: 75%;\n}\n.pure-form .pure-input-2-3 {\n width: 66%;\n}\n.pure-form .pure-input-1-2 {\n width: 50%;\n}\n.pure-form .pure-input-1-3 {\n width: 33%;\n}\n.pure-form .pure-input-1-4 {\n width: 25%;\n}\n\n/* Inline help for forms */\n.pure-form-message-inline {\n display: inline-block;\n padding-left: 0.3em;\n color: #666;\n vertical-align: middle;\n font-size: 0.875em;\n}\n\n/* Block help for forms */\n.pure-form-message {\n display: block;\n color: #666;\n font-size: 0.875em;\n}\n\n@media only screen and (max-width : 480px) {\n .pure-form button[type=\"submit\"] {\n margin: 0.7em 0 0;\n }\n\n .pure-form input:not([type]),\n .pure-form input[type=\"text\"],\n .pure-form input[type=\"password\"],\n .pure-form input[type=\"email\"],\n .pure-form input[type=\"url\"],\n .pure-form input[type=\"date\"],\n .pure-form input[type=\"month\"],\n .pure-form input[type=\"time\"],\n .pure-form input[type=\"datetime\"],\n .pure-form input[type=\"datetime-local\"],\n .pure-form input[type=\"week\"],\n .pure-form input[type=\"number\"],\n .pure-form input[type=\"search\"],\n .pure-form input[type=\"tel\"],\n .pure-form input[type=\"color\"],\n .pure-form label {\n margin-bottom: 0.3em;\n display: block;\n }\n\n .pure-group input:not([type]),\n .pure-group input[type=\"text\"],\n .pure-group input[type=\"password\"],\n .pure-group input[type=\"email\"],\n .pure-group input[type=\"url\"],\n .pure-group input[type=\"date\"],\n .pure-group input[type=\"month\"],\n .pure-group input[type=\"time\"],\n .pure-group input[type=\"datetime\"],\n .pure-group input[type=\"datetime-local\"],\n .pure-group input[type=\"week\"],\n .pure-group input[type=\"number\"],\n .pure-group input[type=\"search\"],\n .pure-group input[type=\"tel\"],\n .pure-group input[type=\"color\"] {\n margin-bottom: 0;\n }\n\n .pure-form-aligned .pure-control-group label {\n margin-bottom: 0.3em;\n text-align: left;\n display: block;\n width: 100%;\n }\n\n .pure-form-aligned .pure-controls {\n margin: 1.5em 0 0 0;\n }\n\n .pure-form-message-inline,\n .pure-form-message {\n display: block;\n font-size: 0.75em;\n /* Increased bottom padding to make it group with its related input element. */\n padding: 0.2em 0 0.8em;\n }\n}\n\n/*csslint adjoining-classes: false, box-model:false*/\n.pure-menu {\n box-sizing: border-box;\n}\n\n.pure-menu-fixed {\n position: fixed;\n left: 0;\n top: 0;\n z-index: 3;\n}\n\n.pure-menu-list,\n.pure-menu-item {\n position: relative;\n}\n\n.pure-menu-list {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.pure-menu-item {\n padding: 0;\n margin: 0;\n height: 100%;\n}\n\n.pure-menu-link,\n.pure-menu-heading {\n display: block;\n text-decoration: none;\n white-space: nowrap;\n}\n\n/* HORIZONTAL MENU */\n.pure-menu-horizontal {\n width: 100%;\n white-space: nowrap;\n}\n\n.pure-menu-horizontal .pure-menu-list {\n display: inline-block;\n}\n\n/* Initial menus should be inline-block so that they are horizontal */\n.pure-menu-horizontal .pure-menu-item,\n.pure-menu-horizontal .pure-menu-heading,\n.pure-menu-horizontal .pure-menu-separator {\n display: inline-block;\n vertical-align: middle;\n}\n\n/* Submenus should still be display: block; */\n.pure-menu-item .pure-menu-item {\n display: block;\n}\n\n.pure-menu-children {\n display: none;\n position: absolute;\n left: 100%;\n top: 0;\n margin: 0;\n padding: 0;\n z-index: 3;\n}\n\n.pure-menu-horizontal .pure-menu-children {\n left: 0;\n top: auto;\n width: inherit;\n}\n\n.pure-menu-allow-hover:hover > .pure-menu-children,\n.pure-menu-active > .pure-menu-children {\n display: block;\n position: absolute;\n}\n\n/* Vertical Menus - show the dropdown arrow */\n.pure-menu-has-children > .pure-menu-link:after {\n padding-left: 0.5em;\n content: \"\\25B8\";\n font-size: small;\n}\n\n/* Horizontal Menus - show the dropdown arrow */\n.pure-menu-horizontal .pure-menu-has-children > .pure-menu-link:after {\n content: \"\\25BE\";\n}\n\n/* scrollable menus */\n.pure-menu-scrollable {\n overflow-y: scroll;\n overflow-x: hidden;\n}\n\n.pure-menu-scrollable .pure-menu-list {\n display: block;\n}\n\n.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list {\n display: inline-block;\n}\n\n.pure-menu-horizontal.pure-menu-scrollable {\n white-space: nowrap;\n overflow-y: hidden;\n overflow-x: auto;\n /* a little extra padding for this style to allow for scrollbars */\n padding: .5em 0;\n}\n\n/* misc default styling */\n\n.pure-menu-separator,\n.pure-menu-horizontal .pure-menu-children .pure-menu-separator {\n background-color: #ccc;\n height: 1px;\n margin: .3em 0;\n}\n\n.pure-menu-horizontal .pure-menu-separator {\n width: 1px;\n height: 1.3em;\n margin: 0 .3em ;\n}\n\n/* Need to reset the separator since submenu is vertical */\n.pure-menu-horizontal .pure-menu-children .pure-menu-separator {\n display: block;\n width: auto;\n}\n\n.pure-menu-heading {\n text-transform: uppercase;\n color: #565d64;\n}\n\n.pure-menu-link {\n color: #777;\n}\n\n.pure-menu-children {\n background-color: #fff;\n}\n\n.pure-menu-link,\n.pure-menu-heading {\n padding: .5em 1em;\n}\n\n.pure-menu-disabled {\n opacity: .5;\n}\n\n.pure-menu-disabled .pure-menu-link:hover {\n background-color: transparent;\n cursor: default;\n}\n\n.pure-menu-active > .pure-menu-link,\n.pure-menu-link:hover,\n.pure-menu-link:focus {\n background-color: #eee;\n}\n\n.pure-menu-selected > .pure-menu-link,\n.pure-menu-selected > .pure-menu-link:visited {\n color: #000;\n}\n\n.pure-table {\n /* Remove spacing between table cells (from Normalize.css) */\n border-collapse: collapse;\n border-spacing: 0;\n empty-cells: show;\n border: 1px solid #cbcbcb;\n}\n\n.pure-table caption {\n color: #000;\n font: italic 85%/1 arial, sans-serif;\n padding: 1em 0;\n text-align: center;\n}\n\n.pure-table td,\n.pure-table th {\n border-left: 1px solid #cbcbcb;/* inner column border */\n border-width: 0 0 0 1px;\n font-size: inherit;\n margin: 0;\n overflow: visible; /*to make ths where the title is really long work*/\n padding: 0.5em 1em; /* cell padding */\n}\n\n.pure-table thead {\n background-color: #e0e0e0;\n color: #000;\n text-align: left;\n vertical-align: bottom;\n}\n\n/*\nstriping:\n even - #fff (white)\n odd - #f2f2f2 (light gray)\n*/\n.pure-table td {\n background-color: transparent;\n}\n.pure-table-odd td {\n background-color: #f2f2f2;\n}\n\n/* nth-child selector for modern browsers */\n.pure-table-striped tr:nth-child(2n-1) td {\n background-color: #f2f2f2;\n}\n\n/* BORDERED TABLES */\n.pure-table-bordered td {\n border-bottom: 1px solid #cbcbcb;\n}\n.pure-table-bordered tbody > tr:last-child > td {\n border-bottom-width: 0;\n}\n\n\n/* HORIZONTAL BORDERED TABLES */\n\n.pure-table-horizontal td,\n.pure-table-horizontal th {\n border-width: 0 0 1px 0;\n border-bottom: 1px solid #cbcbcb;\n}\n.pure-table-horizontal tbody > tr:last-child > td {\n border-bottom-width: 0;\n}\n","pre code.hljs {\n display: block;\n overflow-x: auto;\n padding: 1em\n}\ncode.hljs {\n padding: 3px 5px\n}\n/*!\n Theme: Zenburn\n Author: elnawe\n License: ~ MIT (or more permissive) [via base16-schemes-source]\n Maintainer: @highlightjs/core-team\n Version: 2021.09.0\n*/\n/*\n WARNING: DO NOT EDIT THIS FILE DIRECTLY.\n\n This theme file was auto-generated from the Base16 scheme zenburn\n by the Highlight.js Base16 template builder.\n\n - https://github.com/highlightjs/base16-highlightjs\n*/\n/*\nbase00 #383838 Default Background\nbase01 #404040 Lighter Background (Used for status bars, line number and folding marks)\nbase02 #606060 Selection Background\nbase03 #6f6f6f Comments, Invisibles, Line Highlighting\nbase04 #808080 Dark Foreground (Used for status bars)\nbase05 #dcdccc Default Foreground, Caret, Delimiters, Operators\nbase06 #c0c0c0 Light Foreground (Not often used)\nbase07 #ffffff Light Background (Not often used)\nbase08 #dca3a3 Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted\nbase09 #dfaf8f Integers, Boolean, Constants, XML Attributes, Markup Link Url\nbase0A #e0cf9f Classes, Markup Bold, Search Text Background\nbase0B #5f7f5f Strings, Inherited Class, Markup Code, Diff Inserted\nbase0C #93e0e3 Support, Regular Expressions, Escape Characters, Markup Quotes\nbase0D #7cb8bb Functions, Methods, Attribute IDs, Headings\nbase0E #dc8cc3 Keywords, Storage, Selector, Markup Italic, Diff Changed\nbase0F #000000 Deprecated, Opening/Closing Embedded Language Tags, e.g. \n*/\npre code.hljs {\n display: block;\n overflow-x: auto;\n padding: 1em\n}\ncode.hljs {\n padding: 3px 5px\n}\n.hljs {\n color: #dcdccc;\n background: #383838\n}\n.hljs::selection,\n.hljs ::selection {\n background-color: #606060;\n color: #dcdccc\n}\n/* purposely do not highlight these things */\n.hljs-formula,\n.hljs-params,\n.hljs-property {\n \n}\n/* base03 - #6f6f6f - Comments, Invisibles, Line Highlighting */\n.hljs-comment {\n color: #6f6f6f\n}\n/* base04 - #808080 - Dark Foreground (Used for status bars) */\n.hljs-tag {\n color: #808080\n}\n/* base05 - #dcdccc - Default Foreground, Caret, Delimiters, Operators */\n.hljs-subst,\n.hljs-punctuation,\n.hljs-operator {\n color: #dcdccc\n}\n.hljs-operator {\n opacity: 0.7\n}\n/* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */\n.hljs-bullet,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-selector-tag,\n.hljs-name,\n.hljs-deletion {\n color: #dca3a3\n}\n/* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */\n.hljs-symbol,\n.hljs-number,\n.hljs-link,\n.hljs-attr,\n.hljs-variable.constant_,\n.hljs-literal {\n color: #dfaf8f\n}\n/* base0A - Classes, Markup Bold, Search Text Background */\n.hljs-title,\n.hljs-class .hljs-title,\n.hljs-title.class_ {\n color: #e0cf9f\n}\n.hljs-strong {\n font-weight: bold;\n color: #e0cf9f\n}\n/* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */\n.hljs-code,\n.hljs-addition,\n.hljs-title.class_.inherited__,\n.hljs-string {\n color: #5f7f5f\n}\n/* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */\n/* guessing */\n.hljs-built_in,\n.hljs-doctag,\n.hljs-quote,\n.hljs-keyword.hljs-atrule,\n.hljs-regexp {\n color: #93e0e3\n}\n/* base0D - Functions, Methods, Attribute IDs, Headings */\n.hljs-function .hljs-title,\n.hljs-attribute,\n.ruby .hljs-property,\n.hljs-title.function_,\n.hljs-section {\n color: #7cb8bb\n}\n/* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */\n/* .hljs-selector-id, */\n/* .hljs-selector-class, */\n/* .hljs-selector-attr, */\n/* .hljs-selector-pseudo, */\n.hljs-type,\n.hljs-template-tag,\n.diff .hljs-meta,\n.hljs-keyword {\n color: #dc8cc3\n}\n.hljs-emphasis {\n color: #dc8cc3;\n font-style: italic\n}\n/* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. */\n/*\n prevent top level .keyword and .string scopes\n from leaking into meta by accident\n*/\n.hljs-meta,\n.hljs-meta .hljs-keyword,\n.hljs-meta .hljs-string {\n color: #000000\n}\n/* for v10 compatible themes */\n.hljs-meta .hljs-keyword,\n.hljs-meta-keyword {\n font-weight: bold\n}","$primaryBackground: #b8002c; $transitionBackground: #db0100; $secondaryBackground: #e8410c;\n@import \"../../node_modules/reset-css/reset.css\";\n@import \"../../node_modules/purecss/build/pure.css\";\n$fa-font-path: '../fonts';\n@import \"../../node_modules/\\@fortawesome/fontawesome-free/scss/fontawesome\";\n@import \"../../node_modules/\\@fortawesome/fontawesome-free/scss/solid\";\n@import \"../../node_modules/highlight.js/styles/base16/zenburn.css\";\n\n/*************\n * VARIABLES *\n *************/\n\n$light-yellow: #fffdbf;\n\n/************************************************************\n * GENERAL\n ************************************************************/\n* {\n margin: 0;\n padding: 0;\n}\n\nhtml,\nbody {\n height: 100%;\n}\n\nbody {\n font-family: sans-serif;\n line-height: 1.5;\n min-height: 100%;\n}\n\n.wrap {\n width: 80%;\n max-width: 1100px;\n margin: auto;\n position: relative;\n}\n\n.logospace {\n float: left;\n}\n\nhtml[dir=\"rtl\"] .logospace {\n float: right;\n}\n\n.menuspace {\n float: right;\n}\n\nhtml[dir=\"rtl\"] .menuspace {\n float: left;\n}\n\n.center {\n text-align: center;\n}\n\n.v-center {\n /* specify a height to center vertically */\n display: table-cell;\n vertical-align: middle;\n}\n\ni {\n font-style: italic;\n}\n\nh1 {\n margin: 1em 0;\n font-size: 2em;\n font-weight: 900;\n}\n\nh2 {\n margin: 1em 0;\n font-size: 1.5em;\n font-weight: 700;\n color: #1c1c1c;\n border-bottom: solid 1px #bbb;\n}\n\nh3 {\n font-weight: 500;\n color: #2e3436;\n padding: 0;\n margin-top: 0;\n}\n\np {\n padding: 0.5em 0;\n margin-bottom: 1em;\n}\n\na {\n color: midnightblue;\n\n &:hover,\n &:focus,\n &.pure-menu-link:hover,\n &.pure-menu-link:focus,\n .pure-menu-selected &.pure-menu-link:hover,\n .pure-menu-selected &.pure-menu-link:focus {\n color: white;\n background-color: #444;\n padding: 0.5em 1em;\n }\n\n &:hover,\n &:focus {\n padding: 0.15rem;\n }\n}\n\n.overflow {\n overflow: hidden;\n}\n\nul {\n padding-left: 1.5em;\n}\n\nstrong,\nb {\n font-weight: bold;\n}\n\npre,\ncode,\nkbd,\nsamp,\ntt {\n font-family: monospace;\n font-size: 0.9rem;\n padding: 0 0.2rem;\n}\n\n.xmldata {\n font-family: monospace;\n}\n\n/* ***********************************************************\n * SLIDING SIDE-MENU FOR SMALL SCREENS\n *************************************************************/\n\n/*\nAdd transition to containers so they can push in and out.\n*/\n#layout,\n#menu,\n#foot,\n.menu-link {\n -webkit-transition: all 0.2s ease-out;\n -moz-transition: all 0.2s ease-out;\n -ms-transition: all 0.2s ease-out;\n -o-transition: all 0.2s ease-out;\n transition: all 0.2s ease-out;\n}\n\n/*\nThis is the parent `
    ` that contains the menu and the content area.\n*/\n#layout.active #menu {\n right: 11em;\n width: 11em;\n}\n\n/*\nThe `#menu` `
    ` is the parent `
    ` that contains the `.pure-menu` that\nappears on the left side of the page.\n*/\n#menu {\n margin-right: -11em; /* \"#menu\" width */\n width: 11em;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 1000; /* so the menu or its navicon stays above all content */\n background: $secondaryBackground;\n overflow-y: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n/*\nAll anchors inside the menu should be styled like this.\n*/\n#menu a {\n color: #fff;\n border: none;\n padding: 0.6em 0 0.6em 0.6em;\n}\n\n/*\nRemove all background/borders, since we are applying them to #menu.\n*/\n#menu .pure-menu,\n#menu .pure-menu ul {\n border: none;\n background: transparent;\n}\n\n/*\nAdd that light border to separate items into groups.\n*/\n#menu .pure-menu ul,\n#menu .pure-menu .menu-item-divided {\n border-top: 1px solid $transitionBackground;\n}\n\n/*\nThis styles the selected menu item `
  • `.\n*/\n#menu .pure-menu-selected,\n#menu .pure-menu-heading {\n background: $primaryBackground;\n color: black;\n}\n\n/*\nThis styles a link within a selected menu item `
  • `.\n*/\n#menu .pure-menu-selected a {\n color: #fff;\n}\n\n/*\nThis styles the menu heading.\n*/\n#menu .pure-menu-heading {\n font-size: 110%;\n color: #fff;\n margin: 0;\n text-transform: none;\n}\n\n/* -- Dynamic Button For Responsive Menu -- */\n\n/*\nThe button to open/close the Menu is custom-made and not part of Pure. Here's\nhow it works:\n*/\n\n/*\n`.menu-link` represents the responsive menu toggle that shows/hides on\nsmall screens.\n*/\n.menu-link {\n position: relative;\n display: block; /* show this only on small screens */\n top: 0;\n right: 0; /* \"#menu width\" */\n background: transparent;\n z-index: 10;\n height: 2rem;\n padding: 2rem 0;\n text-decoration: none;\n\n &:hover,\n &:focus {\n padding: 2rem 0;\n background: none !important;\n }\n}\n\n.menu-link span {\n position: relative;\n display: block;\n color: #fff;\n}\n\n.menu-link span,\n.menu-link span::before,\n.menu-link span::after {\n background-color: transparent;\n}\n\n.menu-link span:focus,\n.menu-link span:hover {\n color: #010101cc;\n}\n\n/* -- Responsive Styles (Media Queries) ------------------------------------- */\n\n@media screen and (max-width: 40em) {\n #layout.active {\n position: relative;\n right: 11em;\n\n /* moves to right as many ems as the one used by the menu */\n }\n\n #menuLink.menu-link.active {\n position: fixed;\n right: 13em;\n }\n\n #foot.active {\n margin-right: 11em;\n }\n}\n\n/************************************************************\nHEADER\n*************************************************************/\n#header {\n height: 6rem;\n background: linear-gradient(141deg, $primaryBackground 0%, $transitionBackground 51%, $secondaryBackground 75%);\n}\n\n.logo-header {\n min-width: 8em;\n height: 6rem;\n max-width: 70%;\n}\n\n#logo {\n font-family: sans-serif;\n font-size: 2.5em;\n color: white;\n text-shadow: 0 3px 2px #532900;\n}\n\n.simple {\n font-weight: 300;\n}\n\n.saml {\n font-family: Verdana, sans-serif;\n letter-spacing: -0.12em;\n font-weight: 600;\n margin-left: -0.05em;\n}\n\n.language-menu {\n font-family: sans-serif;\n font-weight: 400;\n min-width: 10rem;\n padding: 0em 0.6em !important;\n}\n\n.language-bar {\n height: 6rem;\n}\n\n/************************************************************\nCONTENT\n*************************************************************/\n#layout {\n right: 0;\n padding-right: 0;\n min-height: 100%;\n\n /* negative margin = footer height + padding-top + padding-bottom */\n margin: 0 auto -6rem;\n}\n\n#content {\n padding-top: 2em;\n padding-bottom: 2rem;\n}\n\n.message-box {\n background-color: #f4f4f4;\n border-left: 0.3125rem solid #444;\n box-shadow: 0 5px 8px -6px #0003;\n margin: 1rem 0;\n padding: 1.3rem;\n position: relative;\n}\n\n.message-box.error {\n background-color: #f7e4e1;\n border-left-color: #cc4b37;\n}\n\n.message-box.warning {\n background-color: $light-yellow;\n border-left-color: #f9f56b;\n}\n\n.message-box.success {\n background-color: #daf7e6;\n border-left-color: #46cc48;\n}\n\n.auth_methods {\n margin-top: 2em;\n width: 35%;\n}\n\n.code-box {\n margin-bottom: 1em;\n border: 1px solid #ccc;\n\n a {\n padding: 0.5em;\n }\n}\n\n.code-box-content {\n word-break: break-all;\n font-size: 1em;\n line-height: 1.15;\n padding: 0.5em 1em;\n display: inline-block;\n min-height: 1em;\n height: 100%;\n white-space: pre-wrap;\n font-family: monospace;\n\n &::selection {\n color: black;\n background: $light-yellow;\n }\n}\n\n.code-box-title {\n border-bottom: 1px solid #ccc;\n background-color: #e0e0e0;\n padding: 0.5em 0 0.5em 0.5em;\n}\n\npre#xmlmetadata {\n width: 98%;\n}\n\n/************************************************************\n * FOOTER\n ************************************************************/\n\n#bottom,\n#push {\n height: 6rem;\n}\n\n#footer {\n width: 100%;\n background: linear-gradient(141deg, $primaryBackground 0%, $transitionBackground 51%, $secondaryBackground 75%);\n height: 4rem;\n padding: 2rem 0 0;\n text-align: center;\n color: white;\n\n a,\n a:visited {\n color: white;\n\n &:focus,\n &:hover {\n background-color: white;\n color: black;\n padding: 0.15rem;\n margin-left: -0.15rem;\n margin-top: -0.15rem;\n text-decoration: none;\n }\n }\n}\n\n.copyrights {\n padding-top: 0.5rem;\n height: 3.5rem;\n font-size: 0.8rem;\n}\n\n.logo-footer-space {\n position: absolute;\n right: 0;\n top: 50%;\n transform: translate(0, -50%);\n}\n\nhtml[dir=\"rtl\"] .logo-footer-space {\n right: auto;\n left: 0;\n}\n\n.logo-footer {\n height: 4rem;\n}\n\n/* ***********************************************************\nFORMS\n************************************************************ */\n.text-area {\n margin-top: 0.5em;\n width: 100%;\n font-size: 0.9em;\n line-height: 1.15;\n}\n\n.file-upload input[type=\"url\"][disabled] {\n cursor: pointer;\n color: inherit;\n}\n\ninput[type=\"file\"] {\n color: black;\n}\n\n.center-form {\n display: flex;\n justify-content: center;\n}\n\n.login-form-start,\n.login-form-submit {\n margin-top: 3ex;\n}\n\ninput#username:disabled {\n color: #000000;\n}\n\n.v-center-right {\n position: absolute;\n left: 0;\n top: 50%;\n transform: translate(0, -50%);\n}\n\n/* PURE */\n.pure-button,\n.pure-form input.edge,\n.pure-form textarea.edge {\n border-radius: 0;\n}\n\n.pure-form input[type=\"checkbox\"] {\n margin-right: 0.8ex;\n vertical-align: baseline;\n}\n\n.pure-control-group {\n margin-bottom: 1ex;\n}\n\n.pure-form-aligned .pure-controls {\n margin: 0 0 0 11em;\n}\n\n.pure-select {\n float: right;\n}\n\nhtml[dir=\"rtl\"] .pure-select {\n float: left;\n}\n\n/************************************************************\n * BUTTONS\n ************************************************************/\n.code-box-title .clipboard-btn {\n background-color: #f0f0f0;\n border: 1px solid #ccc;\n position: absolute;\n right: 0;\n height: inherit;\n margin-top: -2em;\n margin-right: 4px;\n}\n\n.pure-button {\n margin-left: 1ex;\n\n &:hover,\n &:focus {\n background-color: #555;\n padding: 0.5em 1em;\n color: #fff;\n }\n}\n\n.pure-button-red {\n background-color: #db0100;\n color: #fff;\n\n &:hover,\n &:focus {\n background-color: #555;\n padding: 0.5em 1em;\n }\n}\n\n.pure-button.hollow {\n background-color: #fff;\n color: #6f6f6f;\n border: solid 1px #e6e6e6;\n}\n\n.pure-button.hollow:hover {\n background-image: none;\n}\n\n.pure-button.hollow[disabled] {\n cursor: auto;\n opacity: initial;\n pointer-events: auto;\n -webkit-user-drag: auto;\n -webkit-user-select: auto;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n}\n\n.pure-button.hljs {\n display: inline-block;\n border: 0;\n background-color: transparent;\n\n &:hover,\n &:focus {\n background-color: #f0f0f0;\n color: black;\n }\n}\n\n.pure-button-group .pure-button:first-child,\n.pure-button-group .pure-button:last-child {\n border-radius: 0;\n}\n\n.pure-button-group.two-elements .pure-button {\n margin: 0;\n line-height: unset;\n border: 1px solid #e6e6e6;\n}\n\n.pure-button-group.two-elements form {\n display: inline;\n}\n\n.pure-button-group.two-elements .pure-button:first-child {\n border-right: none;\n}\n\n.pure-button-group.two-elements .pure-button:last-child {\n border-right: 1px solid #e6e6e6;\n}\n\n.pure-button-group .pure-button.show-files {\n max-width: 450px;\n overflow: hidden;\n}\n\n.top-right-corner {\n position: absolute;\n right: 1.75em;\n}\n\ninput#postLoginSubmitButton {\n display: none;\n}\n\n/************************************************************\n * IMAGES\n ************************************************************/\n.fa {\n font-family: \"Font Awesome 6 Free\", sans-serif !important;\n font-weight: 400;\n}\n\nspan.fa,\ni.fa {\n padding: 0 0.5em;\n}\n\n.message-box span.fa,\n.message-box i.fa {\n padding: 0;\n}\n\n/************************************************************\n * TABLES\n ************************************************************/\n.pure-table-attributes {\n table-layout: fixed;\n width: 100%;\n}\n\n.attrname {\n text-align: right;\n}\n\n.attrvalue {\n overflow-wrap: break-word;\n}\n\ntable.attributes ul {\n padding: inherit;\n}\n\n/************************************************************\n * MEDIA QUERIES\n ************************************************************/\n\n@media screen and (max-width: 40em) {\n .pure-form .pure-input-sm-1-1 {\n width: 100%;\n }\n}\n\n@media screen and (max-width: 40em) {\n .wrap {\n width: 90%;\n }\n\n .pure-form-aligned .pure-controls {\n margin: 0.5em 0 0;\n float: left;\n }\n\n #layout {\n padding-top: 0;\n margin-bottom: -4rem;\n }\n\n .auth_methods {\n width: 60%;\n }\n\n #logo {\n font-size: 1.8em;\n }\n\n #footer {\n height: 2.5rem;\n padding-top: 1.5rem;\n\n .copyrights {\n height: 1rem;\n padding-top: 0;\n }\n }\n}\n\n@media screen and (max-width: 0), screen and (min-width: 40em) {\n .show-for-small-only {\n display: none !important;\n }\n\n .input-sm-placeholder {\n display: inline-block;\n }\n}\n\n@media screen and (min-width: 40em) {\n .hide-for-large {\n display: none !important;\n }\n}\n\n@media screen and (max-width: 40em) {\n .show-for-large {\n display: none !important;\n }\n}\n\n/*********\n * Utils *\n *********/\n\ndiv.preferredidp {\n border: 1px dashed #ccc;\n background: #eee;\n padding: 2px 2em;\n}\n\n.clear {\n clear: both;\n}\n\n.breathe-top {\n margin-top: 1em;\n}\n\n.expandable {\n border: solid 1px #bbb;\n width: 100%;\n\n .general {\n padding: 1em;\n }\n\n .content {\n display: none;\n padding: 1em;\n }\n\n .expander {\n cursor: pointer;\n text-align: center;\n padding: 0.25em;\n display: block;\n color: black;\n background-color: #f4f4f4;\n border-top: solid 1px #bbb;\n\n &:focus,\n &:hover {\n background-color: #555;\n color: white;\n }\n\n &::after {\n content: \"\\f078\";\n font-family: \"Font Awesome 6 Free\", sans-serif;\n font-weight: 400;\n }\n }\n\n &.expanded {\n .content {\n display: block;\n border-left: solid 0.25em #555;\n border-right: solid 0.25em #555;\n }\n\n .expander {\n border-bottom: none;\n border-top: solid 1px #bbb;\n border-left: solid 0.25em #555;\n border-right: solid 0.25em #555;\n\n &::after {\n content: \"\\f077\";\n }\n }\n }\n}\n\n.hidden {\n display: none;\n}\n\n.idp {\n border: 1px solid silver;\n padding: 1ex;\n margin: 1ex;\n}\n\n.idp .idpname {\n font-size: larger;\n font-weight: bold;\n}\n\n.idp .idpdesc {\n font-size: small;\n color: gray;\n}\n\n.right {\n float: right;\n}\n\n.left {\n float: left;\n}\n","/*!\n * Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)\n * Copyright 2024 Fonticons, Inc.\n */\n// Font Awesome core compile (Web Fonts-based)\n// -------------------------\n\n@import 'functions';\n@import 'variables';\n@import 'mixins';\n@import 'core';\n@import 'sizing';\n@import 'fixed-width';\n@import 'list';\n@import 'bordered-pulled';\n@import 'animated';\n@import 'rotated-flipped';\n@import 'stacked';\n@import 'icons';\n@import 'screen-reader';\n","// base icon class definition\n// -------------------------\n\n.#{$fa-css-prefix} {\n font-family: var(--#{$fa-css-prefix}-style-family, '#{$fa-style-family}');\n font-weight: var(--#{$fa-css-prefix}-style, #{$fa-style});\n}\n\n.fas,\n.far,\n.fab,\n.#{$fa-css-prefix}-solid,\n.#{$fa-css-prefix}-regular,\n.#{$fa-css-prefix}-brands,\n.#{$fa-css-prefix} {\n -moz-osx-font-smoothing: grayscale;\n -webkit-font-smoothing: antialiased;\n display: var(--#{$fa-css-prefix}-display, #{$fa-display});\n font-style: normal;\n font-variant: normal;\n line-height: 1;\n text-rendering: auto;\n}\n\n.fas::before,\n.far::before,\n.fab::before,\n.#{$fa-css-prefix}-solid::before,\n.#{$fa-css-prefix}-regular::before,\n.#{$fa-css-prefix}-brands::before,\n.fa::before {\n content: var(#{$fa-icon-property});\n}\n\n.#{$fa-css-prefix}-classic,\n.fas,\n.#{$fa-css-prefix}-solid,\n.far,\n.#{$fa-css-prefix}-regular {\n font-family: 'Font Awesome 6 Free';\n}\n.#{$fa-css-prefix}-brands,\n.fab {\n font-family: 'Font Awesome 6 Brands';\n}\n\n%fa-icon {\n @include fa-icon;\n}\n","// sizing icons\n// -------------------------\n\n// literal magnification scale\n@for $i from 1 through 10 {\n .#{$fa-css-prefix}-#{$i}x {\n font-size: $i * 1em;\n }\n}\n\n// step-based scale (with alignment)\n@each $size, $value in $fa-sizes {\n .#{$fa-css-prefix}-#{$size} {\n @include fa-size($value);\n }\n}\n","// mixins\n// --------------------------\n\n// base rendering for an icon\n@mixin fa-icon {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n display: inline-block;\n font-style: normal;\n font-variant: normal;\n font-weight: normal;\n line-height: 1;\n}\n\n// sets relative font-sizing and alignment (in _sizing)\n@mixin fa-size ($font-size) {\n font-size: fa-divide($font-size, $fa-size-scale-base) * 1em; // converts step in sizing scale into an em-based value that's relative to the scale's base\n line-height: fa-divide(1, $font-size) * 1em; // sets the line-height of the icon back to that of it's parent\n vertical-align: (fa-divide(6, $font-size) - fa-divide(3, 8)) * 1em; // vertically centers the icon taking into account the surrounding text's descender\n}\n\n// only display content to screen readers\n// see: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/\n// see: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/\n@mixin fa-sr-only() {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n\n// use in conjunction with .sr-only to only display content when it's focused\n@mixin fa-sr-only-focusable() {\n &:not(:focus) {\n @include fa-sr-only();\n }\n}\n\n// sets a specific icon family to use alongside style + icon mixins\n@mixin fa-family-classic() {\n @extend .fa-classic;\n}\n\n// convenience mixins for declaring pseudo-elements by CSS variable,\n// including all style-specific font properties\n@mixin fa-icon-solid($fa-var) {\n @extend .fa-solid;\n\n & { #{$fa-icon-property}: unquote(\"\\\"#{ $fa-var }\\\"\"); #{$fa-duotone-icon-property}: unquote(\"\\\"#{ $fa-var }#{ $fa-var }\\\"\"); }\n}\n@mixin fa-icon-regular($fa-var) {\n @extend .fa-regular;\n\n & { #{$fa-icon-property}: unquote(\"\\\"#{ $fa-var }\\\"\"); #{$fa-duotone-icon-property}: unquote(\"\\\"#{ $fa-var }#{ $fa-var }\\\"\"); }\n}\n@mixin fa-icon-brands($fa-var) {\n @extend .fa-brands;\n\n & { #{$fa-icon-property}: unquote(\"\\\"#{ $fa-var }\\\"\"); #{$fa-duotone-icon-property}: unquote(\"\\\"#{ $fa-var }#{ $fa-var }\\\"\"); }\n}\n","// fixed-width icons\n// -------------------------\n\n.#{$fa-css-prefix}-fw {\n text-align: center;\n width: $fa-fw-width;\n}\n","// variables\n// --------------------------\n\n$fa-css-prefix : fa !default;\n$fa-style : 900 !default;\n$fa-style-family : \"Font Awesome 6 Free\" !default;\n\n$fa-icon-property : --fa;\n$fa-duotone-icon-property : --fa--fa;\n\n$fa-display : inline-block !default;\n\n$fa-fw-width : fa-divide(20em, 16) !default;\n$fa-inverse : #fff !default;\n\n$fa-border-color : #eee !default;\n$fa-border-padding : .2em .25em .15em !default;\n$fa-border-radius : .1em !default;\n$fa-border-style : solid !default;\n$fa-border-width : .08em !default;\n\n$fa-size-scale-2xs : 10 !default;\n$fa-size-scale-xs : 12 !default;\n$fa-size-scale-sm : 14 !default;\n$fa-size-scale-base : 16 !default;\n$fa-size-scale-lg : 20 !default;\n$fa-size-scale-xl : 24 !default;\n$fa-size-scale-2xl : 32 !default;\n\n$fa-sizes: (\n \"2xs\" : $fa-size-scale-2xs,\n \"xs\" : $fa-size-scale-xs,\n \"sm\" : $fa-size-scale-sm,\n \"lg\" : $fa-size-scale-lg,\n \"xl\" : $fa-size-scale-xl,\n \"2xl\" : $fa-size-scale-2xl\n) !default;\n\n$fa-li-width : 2em !default;\n$fa-li-margin : $fa-li-width * fa-divide(5, 4) !default;\n\n$fa-pull-margin : .3em !default;\n\n$fa-primary-opacity : 1 !default;\n$fa-secondary-opacity : .4 !default;\n\n$fa-stack-vertical-align : middle !default;\n$fa-stack-width : ($fa-fw-width * 2) !default;\n$fa-stack-z-index : auto !default;\n\n$fa-font-display : block !default;\n$fa-font-path : \"../webfonts\" !default;\n\n$fa-var-0: \\30;\n$fa-var-1: \\31;\n$fa-var-2: \\32;\n$fa-var-3: \\33;\n$fa-var-4: \\34;\n$fa-var-5: \\35;\n$fa-var-6: \\36;\n$fa-var-7: \\37;\n$fa-var-8: \\38;\n$fa-var-9: \\39;\n$fa-var-fill-drip: \\f576;\n$fa-var-arrows-to-circle: \\e4bd;\n$fa-var-circle-chevron-right: \\f138;\n$fa-var-chevron-circle-right: \\f138;\n$fa-var-at: \\40;\n$fa-var-trash-can: \\f2ed;\n$fa-var-trash-alt: \\f2ed;\n$fa-var-text-height: \\f034;\n$fa-var-user-xmark: \\f235;\n$fa-var-user-times: \\f235;\n$fa-var-stethoscope: \\f0f1;\n$fa-var-message: \\f27a;\n$fa-var-comment-alt: \\f27a;\n$fa-var-info: \\f129;\n$fa-var-down-left-and-up-right-to-center: \\f422;\n$fa-var-compress-alt: \\f422;\n$fa-var-explosion: \\e4e9;\n$fa-var-file-lines: \\f15c;\n$fa-var-file-alt: \\f15c;\n$fa-var-file-text: \\f15c;\n$fa-var-wave-square: \\f83e;\n$fa-var-ring: \\f70b;\n$fa-var-building-un: \\e4d9;\n$fa-var-dice-three: \\f527;\n$fa-var-calendar-days: \\f073;\n$fa-var-calendar-alt: \\f073;\n$fa-var-anchor-circle-check: \\e4aa;\n$fa-var-building-circle-arrow-right: \\e4d1;\n$fa-var-volleyball: \\f45f;\n$fa-var-volleyball-ball: \\f45f;\n$fa-var-arrows-up-to-line: \\e4c2;\n$fa-var-sort-down: \\f0dd;\n$fa-var-sort-desc: \\f0dd;\n$fa-var-circle-minus: \\f056;\n$fa-var-minus-circle: \\f056;\n$fa-var-door-open: \\f52b;\n$fa-var-right-from-bracket: \\f2f5;\n$fa-var-sign-out-alt: \\f2f5;\n$fa-var-atom: \\f5d2;\n$fa-var-soap: \\e06e;\n$fa-var-icons: \\f86d;\n$fa-var-heart-music-camera-bolt: \\f86d;\n$fa-var-microphone-lines-slash: \\f539;\n$fa-var-microphone-alt-slash: \\f539;\n$fa-var-bridge-circle-check: \\e4c9;\n$fa-var-pump-medical: \\e06a;\n$fa-var-fingerprint: \\f577;\n$fa-var-hand-point-right: \\f0a4;\n$fa-var-magnifying-glass-location: \\f689;\n$fa-var-search-location: \\f689;\n$fa-var-forward-step: \\f051;\n$fa-var-step-forward: \\f051;\n$fa-var-face-smile-beam: \\f5b8;\n$fa-var-smile-beam: \\f5b8;\n$fa-var-flag-checkered: \\f11e;\n$fa-var-football: \\f44e;\n$fa-var-football-ball: \\f44e;\n$fa-var-school-circle-exclamation: \\e56c;\n$fa-var-crop: \\f125;\n$fa-var-angles-down: \\f103;\n$fa-var-angle-double-down: \\f103;\n$fa-var-users-rectangle: \\e594;\n$fa-var-people-roof: \\e537;\n$fa-var-people-line: \\e534;\n$fa-var-beer-mug-empty: \\f0fc;\n$fa-var-beer: \\f0fc;\n$fa-var-diagram-predecessor: \\e477;\n$fa-var-arrow-up-long: \\f176;\n$fa-var-long-arrow-up: \\f176;\n$fa-var-fire-flame-simple: \\f46a;\n$fa-var-burn: \\f46a;\n$fa-var-person: \\f183;\n$fa-var-male: \\f183;\n$fa-var-laptop: \\f109;\n$fa-var-file-csv: \\f6dd;\n$fa-var-menorah: \\f676;\n$fa-var-truck-plane: \\e58f;\n$fa-var-record-vinyl: \\f8d9;\n$fa-var-face-grin-stars: \\f587;\n$fa-var-grin-stars: \\f587;\n$fa-var-bong: \\f55c;\n$fa-var-spaghetti-monster-flying: \\f67b;\n$fa-var-pastafarianism: \\f67b;\n$fa-var-arrow-down-up-across-line: \\e4af;\n$fa-var-spoon: \\f2e5;\n$fa-var-utensil-spoon: \\f2e5;\n$fa-var-jar-wheat: \\e517;\n$fa-var-envelopes-bulk: \\f674;\n$fa-var-mail-bulk: \\f674;\n$fa-var-file-circle-exclamation: \\e4eb;\n$fa-var-circle-h: \\f47e;\n$fa-var-hospital-symbol: \\f47e;\n$fa-var-pager: \\f815;\n$fa-var-address-book: \\f2b9;\n$fa-var-contact-book: \\f2b9;\n$fa-var-strikethrough: \\f0cc;\n$fa-var-k: \\4b;\n$fa-var-landmark-flag: \\e51c;\n$fa-var-pencil: \\f303;\n$fa-var-pencil-alt: \\f303;\n$fa-var-backward: \\f04a;\n$fa-var-caret-right: \\f0da;\n$fa-var-comments: \\f086;\n$fa-var-paste: \\f0ea;\n$fa-var-file-clipboard: \\f0ea;\n$fa-var-code-pull-request: \\e13c;\n$fa-var-clipboard-list: \\f46d;\n$fa-var-truck-ramp-box: \\f4de;\n$fa-var-truck-loading: \\f4de;\n$fa-var-user-check: \\f4fc;\n$fa-var-vial-virus: \\e597;\n$fa-var-sheet-plastic: \\e571;\n$fa-var-blog: \\f781;\n$fa-var-user-ninja: \\f504;\n$fa-var-person-arrow-up-from-line: \\e539;\n$fa-var-scroll-torah: \\f6a0;\n$fa-var-torah: \\f6a0;\n$fa-var-broom-ball: \\f458;\n$fa-var-quidditch: \\f458;\n$fa-var-quidditch-broom-ball: \\f458;\n$fa-var-toggle-off: \\f204;\n$fa-var-box-archive: \\f187;\n$fa-var-archive: \\f187;\n$fa-var-person-drowning: \\e545;\n$fa-var-arrow-down-9-1: \\f886;\n$fa-var-sort-numeric-desc: \\f886;\n$fa-var-sort-numeric-down-alt: \\f886;\n$fa-var-face-grin-tongue-squint: \\f58a;\n$fa-var-grin-tongue-squint: \\f58a;\n$fa-var-spray-can: \\f5bd;\n$fa-var-truck-monster: \\f63b;\n$fa-var-w: \\57;\n$fa-var-earth-africa: \\f57c;\n$fa-var-globe-africa: \\f57c;\n$fa-var-rainbow: \\f75b;\n$fa-var-circle-notch: \\f1ce;\n$fa-var-tablet-screen-button: \\f3fa;\n$fa-var-tablet-alt: \\f3fa;\n$fa-var-paw: \\f1b0;\n$fa-var-cloud: \\f0c2;\n$fa-var-trowel-bricks: \\e58a;\n$fa-var-face-flushed: \\f579;\n$fa-var-flushed: \\f579;\n$fa-var-hospital-user: \\f80d;\n$fa-var-tent-arrow-left-right: \\e57f;\n$fa-var-gavel: \\f0e3;\n$fa-var-legal: \\f0e3;\n$fa-var-binoculars: \\f1e5;\n$fa-var-microphone-slash: \\f131;\n$fa-var-box-tissue: \\e05b;\n$fa-var-motorcycle: \\f21c;\n$fa-var-bell-concierge: \\f562;\n$fa-var-concierge-bell: \\f562;\n$fa-var-pen-ruler: \\f5ae;\n$fa-var-pencil-ruler: \\f5ae;\n$fa-var-people-arrows: \\e068;\n$fa-var-people-arrows-left-right: \\e068;\n$fa-var-mars-and-venus-burst: \\e523;\n$fa-var-square-caret-right: \\f152;\n$fa-var-caret-square-right: \\f152;\n$fa-var-scissors: \\f0c4;\n$fa-var-cut: \\f0c4;\n$fa-var-sun-plant-wilt: \\e57a;\n$fa-var-toilets-portable: \\e584;\n$fa-var-hockey-puck: \\f453;\n$fa-var-table: \\f0ce;\n$fa-var-magnifying-glass-arrow-right: \\e521;\n$fa-var-tachograph-digital: \\f566;\n$fa-var-digital-tachograph: \\f566;\n$fa-var-users-slash: \\e073;\n$fa-var-clover: \\e139;\n$fa-var-reply: \\f3e5;\n$fa-var-mail-reply: \\f3e5;\n$fa-var-star-and-crescent: \\f699;\n$fa-var-house-fire: \\e50c;\n$fa-var-square-minus: \\f146;\n$fa-var-minus-square: \\f146;\n$fa-var-helicopter: \\f533;\n$fa-var-compass: \\f14e;\n$fa-var-square-caret-down: \\f150;\n$fa-var-caret-square-down: \\f150;\n$fa-var-file-circle-question: \\e4ef;\n$fa-var-laptop-code: \\f5fc;\n$fa-var-swatchbook: \\f5c3;\n$fa-var-prescription-bottle: \\f485;\n$fa-var-bars: \\f0c9;\n$fa-var-navicon: \\f0c9;\n$fa-var-people-group: \\e533;\n$fa-var-hourglass-end: \\f253;\n$fa-var-hourglass-3: \\f253;\n$fa-var-heart-crack: \\f7a9;\n$fa-var-heart-broken: \\f7a9;\n$fa-var-square-up-right: \\f360;\n$fa-var-external-link-square-alt: \\f360;\n$fa-var-face-kiss-beam: \\f597;\n$fa-var-kiss-beam: \\f597;\n$fa-var-film: \\f008;\n$fa-var-ruler-horizontal: \\f547;\n$fa-var-people-robbery: \\e536;\n$fa-var-lightbulb: \\f0eb;\n$fa-var-caret-left: \\f0d9;\n$fa-var-circle-exclamation: \\f06a;\n$fa-var-exclamation-circle: \\f06a;\n$fa-var-school-circle-xmark: \\e56d;\n$fa-var-arrow-right-from-bracket: \\f08b;\n$fa-var-sign-out: \\f08b;\n$fa-var-circle-chevron-down: \\f13a;\n$fa-var-chevron-circle-down: \\f13a;\n$fa-var-unlock-keyhole: \\f13e;\n$fa-var-unlock-alt: \\f13e;\n$fa-var-cloud-showers-heavy: \\f740;\n$fa-var-headphones-simple: \\f58f;\n$fa-var-headphones-alt: \\f58f;\n$fa-var-sitemap: \\f0e8;\n$fa-var-circle-dollar-to-slot: \\f4b9;\n$fa-var-donate: \\f4b9;\n$fa-var-memory: \\f538;\n$fa-var-road-spikes: \\e568;\n$fa-var-fire-burner: \\e4f1;\n$fa-var-flag: \\f024;\n$fa-var-hanukiah: \\f6e6;\n$fa-var-feather: \\f52d;\n$fa-var-volume-low: \\f027;\n$fa-var-volume-down: \\f027;\n$fa-var-comment-slash: \\f4b3;\n$fa-var-cloud-sun-rain: \\f743;\n$fa-var-compress: \\f066;\n$fa-var-wheat-awn: \\e2cd;\n$fa-var-wheat-alt: \\e2cd;\n$fa-var-ankh: \\f644;\n$fa-var-hands-holding-child: \\e4fa;\n$fa-var-asterisk: \\2a;\n$fa-var-square-check: \\f14a;\n$fa-var-check-square: \\f14a;\n$fa-var-peseta-sign: \\e221;\n$fa-var-heading: \\f1dc;\n$fa-var-header: \\f1dc;\n$fa-var-ghost: \\f6e2;\n$fa-var-list: \\f03a;\n$fa-var-list-squares: \\f03a;\n$fa-var-square-phone-flip: \\f87b;\n$fa-var-phone-square-alt: \\f87b;\n$fa-var-cart-plus: \\f217;\n$fa-var-gamepad: \\f11b;\n$fa-var-circle-dot: \\f192;\n$fa-var-dot-circle: \\f192;\n$fa-var-face-dizzy: \\f567;\n$fa-var-dizzy: \\f567;\n$fa-var-egg: \\f7fb;\n$fa-var-house-medical-circle-xmark: \\e513;\n$fa-var-campground: \\f6bb;\n$fa-var-folder-plus: \\f65e;\n$fa-var-futbol: \\f1e3;\n$fa-var-futbol-ball: \\f1e3;\n$fa-var-soccer-ball: \\f1e3;\n$fa-var-paintbrush: \\f1fc;\n$fa-var-paint-brush: \\f1fc;\n$fa-var-lock: \\f023;\n$fa-var-gas-pump: \\f52f;\n$fa-var-hot-tub-person: \\f593;\n$fa-var-hot-tub: \\f593;\n$fa-var-map-location: \\f59f;\n$fa-var-map-marked: \\f59f;\n$fa-var-house-flood-water: \\e50e;\n$fa-var-tree: \\f1bb;\n$fa-var-bridge-lock: \\e4cc;\n$fa-var-sack-dollar: \\f81d;\n$fa-var-pen-to-square: \\f044;\n$fa-var-edit: \\f044;\n$fa-var-car-side: \\f5e4;\n$fa-var-share-nodes: \\f1e0;\n$fa-var-share-alt: \\f1e0;\n$fa-var-heart-circle-minus: \\e4ff;\n$fa-var-hourglass-half: \\f252;\n$fa-var-hourglass-2: \\f252;\n$fa-var-microscope: \\f610;\n$fa-var-sink: \\e06d;\n$fa-var-bag-shopping: \\f290;\n$fa-var-shopping-bag: \\f290;\n$fa-var-arrow-down-z-a: \\f881;\n$fa-var-sort-alpha-desc: \\f881;\n$fa-var-sort-alpha-down-alt: \\f881;\n$fa-var-mitten: \\f7b5;\n$fa-var-person-rays: \\e54d;\n$fa-var-users: \\f0c0;\n$fa-var-eye-slash: \\f070;\n$fa-var-flask-vial: \\e4f3;\n$fa-var-hand: \\f256;\n$fa-var-hand-paper: \\f256;\n$fa-var-om: \\f679;\n$fa-var-worm: \\e599;\n$fa-var-house-circle-xmark: \\e50b;\n$fa-var-plug: \\f1e6;\n$fa-var-chevron-up: \\f077;\n$fa-var-hand-spock: \\f259;\n$fa-var-stopwatch: \\f2f2;\n$fa-var-face-kiss: \\f596;\n$fa-var-kiss: \\f596;\n$fa-var-bridge-circle-xmark: \\e4cb;\n$fa-var-face-grin-tongue: \\f589;\n$fa-var-grin-tongue: \\f589;\n$fa-var-chess-bishop: \\f43a;\n$fa-var-face-grin-wink: \\f58c;\n$fa-var-grin-wink: \\f58c;\n$fa-var-ear-deaf: \\f2a4;\n$fa-var-deaf: \\f2a4;\n$fa-var-deafness: \\f2a4;\n$fa-var-hard-of-hearing: \\f2a4;\n$fa-var-road-circle-check: \\e564;\n$fa-var-dice-five: \\f523;\n$fa-var-square-rss: \\f143;\n$fa-var-rss-square: \\f143;\n$fa-var-land-mine-on: \\e51b;\n$fa-var-i-cursor: \\f246;\n$fa-var-stamp: \\f5bf;\n$fa-var-stairs: \\e289;\n$fa-var-i: \\49;\n$fa-var-hryvnia-sign: \\f6f2;\n$fa-var-hryvnia: \\f6f2;\n$fa-var-pills: \\f484;\n$fa-var-face-grin-wide: \\f581;\n$fa-var-grin-alt: \\f581;\n$fa-var-tooth: \\f5c9;\n$fa-var-v: \\56;\n$fa-var-bangladeshi-taka-sign: \\e2e6;\n$fa-var-bicycle: \\f206;\n$fa-var-staff-snake: \\e579;\n$fa-var-rod-asclepius: \\e579;\n$fa-var-rod-snake: \\e579;\n$fa-var-staff-aesculapius: \\e579;\n$fa-var-head-side-cough-slash: \\e062;\n$fa-var-truck-medical: \\f0f9;\n$fa-var-ambulance: \\f0f9;\n$fa-var-wheat-awn-circle-exclamation: \\e598;\n$fa-var-snowman: \\f7d0;\n$fa-var-mortar-pestle: \\f5a7;\n$fa-var-road-barrier: \\e562;\n$fa-var-school: \\f549;\n$fa-var-igloo: \\f7ae;\n$fa-var-joint: \\f595;\n$fa-var-angle-right: \\f105;\n$fa-var-horse: \\f6f0;\n$fa-var-q: \\51;\n$fa-var-g: \\47;\n$fa-var-notes-medical: \\f481;\n$fa-var-temperature-half: \\f2c9;\n$fa-var-temperature-2: \\f2c9;\n$fa-var-thermometer-2: \\f2c9;\n$fa-var-thermometer-half: \\f2c9;\n$fa-var-dong-sign: \\e169;\n$fa-var-capsules: \\f46b;\n$fa-var-poo-storm: \\f75a;\n$fa-var-poo-bolt: \\f75a;\n$fa-var-face-frown-open: \\f57a;\n$fa-var-frown-open: \\f57a;\n$fa-var-hand-point-up: \\f0a6;\n$fa-var-money-bill: \\f0d6;\n$fa-var-bookmark: \\f02e;\n$fa-var-align-justify: \\f039;\n$fa-var-umbrella-beach: \\f5ca;\n$fa-var-helmet-un: \\e503;\n$fa-var-bullseye: \\f140;\n$fa-var-bacon: \\f7e5;\n$fa-var-hand-point-down: \\f0a7;\n$fa-var-arrow-up-from-bracket: \\e09a;\n$fa-var-folder: \\f07b;\n$fa-var-folder-blank: \\f07b;\n$fa-var-file-waveform: \\f478;\n$fa-var-file-medical-alt: \\f478;\n$fa-var-radiation: \\f7b9;\n$fa-var-chart-simple: \\e473;\n$fa-var-mars-stroke: \\f229;\n$fa-var-vial: \\f492;\n$fa-var-gauge: \\f624;\n$fa-var-dashboard: \\f624;\n$fa-var-gauge-med: \\f624;\n$fa-var-tachometer-alt-average: \\f624;\n$fa-var-wand-magic-sparkles: \\e2ca;\n$fa-var-magic-wand-sparkles: \\e2ca;\n$fa-var-e: \\45;\n$fa-var-pen-clip: \\f305;\n$fa-var-pen-alt: \\f305;\n$fa-var-bridge-circle-exclamation: \\e4ca;\n$fa-var-user: \\f007;\n$fa-var-school-circle-check: \\e56b;\n$fa-var-dumpster: \\f793;\n$fa-var-van-shuttle: \\f5b6;\n$fa-var-shuttle-van: \\f5b6;\n$fa-var-building-user: \\e4da;\n$fa-var-square-caret-left: \\f191;\n$fa-var-caret-square-left: \\f191;\n$fa-var-highlighter: \\f591;\n$fa-var-key: \\f084;\n$fa-var-bullhorn: \\f0a1;\n$fa-var-globe: \\f0ac;\n$fa-var-synagogue: \\f69b;\n$fa-var-person-half-dress: \\e548;\n$fa-var-road-bridge: \\e563;\n$fa-var-location-arrow: \\f124;\n$fa-var-c: \\43;\n$fa-var-tablet-button: \\f10a;\n$fa-var-building-lock: \\e4d6;\n$fa-var-pizza-slice: \\f818;\n$fa-var-money-bill-wave: \\f53a;\n$fa-var-chart-area: \\f1fe;\n$fa-var-area-chart: \\f1fe;\n$fa-var-house-flag: \\e50d;\n$fa-var-person-circle-minus: \\e540;\n$fa-var-ban: \\f05e;\n$fa-var-cancel: \\f05e;\n$fa-var-camera-rotate: \\e0d8;\n$fa-var-spray-can-sparkles: \\f5d0;\n$fa-var-air-freshener: \\f5d0;\n$fa-var-star: \\f005;\n$fa-var-repeat: \\f363;\n$fa-var-cross: \\f654;\n$fa-var-box: \\f466;\n$fa-var-venus-mars: \\f228;\n$fa-var-arrow-pointer: \\f245;\n$fa-var-mouse-pointer: \\f245;\n$fa-var-maximize: \\f31e;\n$fa-var-expand-arrows-alt: \\f31e;\n$fa-var-charging-station: \\f5e7;\n$fa-var-shapes: \\f61f;\n$fa-var-triangle-circle-square: \\f61f;\n$fa-var-shuffle: \\f074;\n$fa-var-random: \\f074;\n$fa-var-person-running: \\f70c;\n$fa-var-running: \\f70c;\n$fa-var-mobile-retro: \\e527;\n$fa-var-grip-lines-vertical: \\f7a5;\n$fa-var-spider: \\f717;\n$fa-var-hands-bound: \\e4f9;\n$fa-var-file-invoice-dollar: \\f571;\n$fa-var-plane-circle-exclamation: \\e556;\n$fa-var-x-ray: \\f497;\n$fa-var-spell-check: \\f891;\n$fa-var-slash: \\f715;\n$fa-var-computer-mouse: \\f8cc;\n$fa-var-mouse: \\f8cc;\n$fa-var-arrow-right-to-bracket: \\f090;\n$fa-var-sign-in: \\f090;\n$fa-var-shop-slash: \\e070;\n$fa-var-store-alt-slash: \\e070;\n$fa-var-server: \\f233;\n$fa-var-virus-covid-slash: \\e4a9;\n$fa-var-shop-lock: \\e4a5;\n$fa-var-hourglass-start: \\f251;\n$fa-var-hourglass-1: \\f251;\n$fa-var-blender-phone: \\f6b6;\n$fa-var-building-wheat: \\e4db;\n$fa-var-person-breastfeeding: \\e53a;\n$fa-var-right-to-bracket: \\f2f6;\n$fa-var-sign-in-alt: \\f2f6;\n$fa-var-venus: \\f221;\n$fa-var-passport: \\f5ab;\n$fa-var-thumbtack-slash: \\e68f;\n$fa-var-thumb-tack-slash: \\e68f;\n$fa-var-heart-pulse: \\f21e;\n$fa-var-heartbeat: \\f21e;\n$fa-var-people-carry-box: \\f4ce;\n$fa-var-people-carry: \\f4ce;\n$fa-var-temperature-high: \\f769;\n$fa-var-microchip: \\f2db;\n$fa-var-crown: \\f521;\n$fa-var-weight-hanging: \\f5cd;\n$fa-var-xmarks-lines: \\e59a;\n$fa-var-file-prescription: \\f572;\n$fa-var-weight-scale: \\f496;\n$fa-var-weight: \\f496;\n$fa-var-user-group: \\f500;\n$fa-var-user-friends: \\f500;\n$fa-var-arrow-up-a-z: \\f15e;\n$fa-var-sort-alpha-up: \\f15e;\n$fa-var-chess-knight: \\f441;\n$fa-var-face-laugh-squint: \\f59b;\n$fa-var-laugh-squint: \\f59b;\n$fa-var-wheelchair: \\f193;\n$fa-var-circle-arrow-up: \\f0aa;\n$fa-var-arrow-circle-up: \\f0aa;\n$fa-var-toggle-on: \\f205;\n$fa-var-person-walking: \\f554;\n$fa-var-walking: \\f554;\n$fa-var-l: \\4c;\n$fa-var-fire: \\f06d;\n$fa-var-bed-pulse: \\f487;\n$fa-var-procedures: \\f487;\n$fa-var-shuttle-space: \\f197;\n$fa-var-space-shuttle: \\f197;\n$fa-var-face-laugh: \\f599;\n$fa-var-laugh: \\f599;\n$fa-var-folder-open: \\f07c;\n$fa-var-heart-circle-plus: \\e500;\n$fa-var-code-fork: \\e13b;\n$fa-var-city: \\f64f;\n$fa-var-microphone-lines: \\f3c9;\n$fa-var-microphone-alt: \\f3c9;\n$fa-var-pepper-hot: \\f816;\n$fa-var-unlock: \\f09c;\n$fa-var-colon-sign: \\e140;\n$fa-var-headset: \\f590;\n$fa-var-store-slash: \\e071;\n$fa-var-road-circle-xmark: \\e566;\n$fa-var-user-minus: \\f503;\n$fa-var-mars-stroke-up: \\f22a;\n$fa-var-mars-stroke-v: \\f22a;\n$fa-var-champagne-glasses: \\f79f;\n$fa-var-glass-cheers: \\f79f;\n$fa-var-clipboard: \\f328;\n$fa-var-house-circle-exclamation: \\e50a;\n$fa-var-file-arrow-up: \\f574;\n$fa-var-file-upload: \\f574;\n$fa-var-wifi: \\f1eb;\n$fa-var-wifi-3: \\f1eb;\n$fa-var-wifi-strong: \\f1eb;\n$fa-var-bath: \\f2cd;\n$fa-var-bathtub: \\f2cd;\n$fa-var-underline: \\f0cd;\n$fa-var-user-pen: \\f4ff;\n$fa-var-user-edit: \\f4ff;\n$fa-var-signature: \\f5b7;\n$fa-var-stroopwafel: \\f551;\n$fa-var-bold: \\f032;\n$fa-var-anchor-lock: \\e4ad;\n$fa-var-building-ngo: \\e4d7;\n$fa-var-manat-sign: \\e1d5;\n$fa-var-not-equal: \\f53e;\n$fa-var-border-top-left: \\f853;\n$fa-var-border-style: \\f853;\n$fa-var-map-location-dot: \\f5a0;\n$fa-var-map-marked-alt: \\f5a0;\n$fa-var-jedi: \\f669;\n$fa-var-square-poll-vertical: \\f681;\n$fa-var-poll: \\f681;\n$fa-var-mug-hot: \\f7b6;\n$fa-var-car-battery: \\f5df;\n$fa-var-battery-car: \\f5df;\n$fa-var-gift: \\f06b;\n$fa-var-dice-two: \\f528;\n$fa-var-chess-queen: \\f445;\n$fa-var-glasses: \\f530;\n$fa-var-chess-board: \\f43c;\n$fa-var-building-circle-check: \\e4d2;\n$fa-var-person-chalkboard: \\e53d;\n$fa-var-mars-stroke-right: \\f22b;\n$fa-var-mars-stroke-h: \\f22b;\n$fa-var-hand-back-fist: \\f255;\n$fa-var-hand-rock: \\f255;\n$fa-var-square-caret-up: \\f151;\n$fa-var-caret-square-up: \\f151;\n$fa-var-cloud-showers-water: \\e4e4;\n$fa-var-chart-bar: \\f080;\n$fa-var-bar-chart: \\f080;\n$fa-var-hands-bubbles: \\e05e;\n$fa-var-hands-wash: \\e05e;\n$fa-var-less-than-equal: \\f537;\n$fa-var-train: \\f238;\n$fa-var-eye-low-vision: \\f2a8;\n$fa-var-low-vision: \\f2a8;\n$fa-var-crow: \\f520;\n$fa-var-sailboat: \\e445;\n$fa-var-window-restore: \\f2d2;\n$fa-var-square-plus: \\f0fe;\n$fa-var-plus-square: \\f0fe;\n$fa-var-torii-gate: \\f6a1;\n$fa-var-frog: \\f52e;\n$fa-var-bucket: \\e4cf;\n$fa-var-image: \\f03e;\n$fa-var-microphone: \\f130;\n$fa-var-cow: \\f6c8;\n$fa-var-caret-up: \\f0d8;\n$fa-var-screwdriver: \\f54a;\n$fa-var-folder-closed: \\e185;\n$fa-var-house-tsunami: \\e515;\n$fa-var-square-nfi: \\e576;\n$fa-var-arrow-up-from-ground-water: \\e4b5;\n$fa-var-martini-glass: \\f57b;\n$fa-var-glass-martini-alt: \\f57b;\n$fa-var-square-binary: \\e69b;\n$fa-var-rotate-left: \\f2ea;\n$fa-var-rotate-back: \\f2ea;\n$fa-var-rotate-backward: \\f2ea;\n$fa-var-undo-alt: \\f2ea;\n$fa-var-table-columns: \\f0db;\n$fa-var-columns: \\f0db;\n$fa-var-lemon: \\f094;\n$fa-var-head-side-mask: \\e063;\n$fa-var-handshake: \\f2b5;\n$fa-var-gem: \\f3a5;\n$fa-var-dolly: \\f472;\n$fa-var-dolly-box: \\f472;\n$fa-var-smoking: \\f48d;\n$fa-var-minimize: \\f78c;\n$fa-var-compress-arrows-alt: \\f78c;\n$fa-var-monument: \\f5a6;\n$fa-var-snowplow: \\f7d2;\n$fa-var-angles-right: \\f101;\n$fa-var-angle-double-right: \\f101;\n$fa-var-cannabis: \\f55f;\n$fa-var-circle-play: \\f144;\n$fa-var-play-circle: \\f144;\n$fa-var-tablets: \\f490;\n$fa-var-ethernet: \\f796;\n$fa-var-euro-sign: \\f153;\n$fa-var-eur: \\f153;\n$fa-var-euro: \\f153;\n$fa-var-chair: \\f6c0;\n$fa-var-circle-check: \\f058;\n$fa-var-check-circle: \\f058;\n$fa-var-circle-stop: \\f28d;\n$fa-var-stop-circle: \\f28d;\n$fa-var-compass-drafting: \\f568;\n$fa-var-drafting-compass: \\f568;\n$fa-var-plate-wheat: \\e55a;\n$fa-var-icicles: \\f7ad;\n$fa-var-person-shelter: \\e54f;\n$fa-var-neuter: \\f22c;\n$fa-var-id-badge: \\f2c1;\n$fa-var-marker: \\f5a1;\n$fa-var-face-laugh-beam: \\f59a;\n$fa-var-laugh-beam: \\f59a;\n$fa-var-helicopter-symbol: \\e502;\n$fa-var-universal-access: \\f29a;\n$fa-var-circle-chevron-up: \\f139;\n$fa-var-chevron-circle-up: \\f139;\n$fa-var-lari-sign: \\e1c8;\n$fa-var-volcano: \\f770;\n$fa-var-person-walking-dashed-line-arrow-right: \\e553;\n$fa-var-sterling-sign: \\f154;\n$fa-var-gbp: \\f154;\n$fa-var-pound-sign: \\f154;\n$fa-var-viruses: \\e076;\n$fa-var-square-person-confined: \\e577;\n$fa-var-user-tie: \\f508;\n$fa-var-arrow-down-long: \\f175;\n$fa-var-long-arrow-down: \\f175;\n$fa-var-tent-arrow-down-to-line: \\e57e;\n$fa-var-certificate: \\f0a3;\n$fa-var-reply-all: \\f122;\n$fa-var-mail-reply-all: \\f122;\n$fa-var-suitcase: \\f0f2;\n$fa-var-person-skating: \\f7c5;\n$fa-var-skating: \\f7c5;\n$fa-var-filter-circle-dollar: \\f662;\n$fa-var-funnel-dollar: \\f662;\n$fa-var-camera-retro: \\f083;\n$fa-var-circle-arrow-down: \\f0ab;\n$fa-var-arrow-circle-down: \\f0ab;\n$fa-var-file-import: \\f56f;\n$fa-var-arrow-right-to-file: \\f56f;\n$fa-var-square-arrow-up-right: \\f14c;\n$fa-var-external-link-square: \\f14c;\n$fa-var-box-open: \\f49e;\n$fa-var-scroll: \\f70e;\n$fa-var-spa: \\f5bb;\n$fa-var-location-pin-lock: \\e51f;\n$fa-var-pause: \\f04c;\n$fa-var-hill-avalanche: \\e507;\n$fa-var-temperature-empty: \\f2cb;\n$fa-var-temperature-0: \\f2cb;\n$fa-var-thermometer-0: \\f2cb;\n$fa-var-thermometer-empty: \\f2cb;\n$fa-var-bomb: \\f1e2;\n$fa-var-registered: \\f25d;\n$fa-var-address-card: \\f2bb;\n$fa-var-contact-card: \\f2bb;\n$fa-var-vcard: \\f2bb;\n$fa-var-scale-unbalanced-flip: \\f516;\n$fa-var-balance-scale-right: \\f516;\n$fa-var-subscript: \\f12c;\n$fa-var-diamond-turn-right: \\f5eb;\n$fa-var-directions: \\f5eb;\n$fa-var-burst: \\e4dc;\n$fa-var-house-laptop: \\e066;\n$fa-var-laptop-house: \\e066;\n$fa-var-face-tired: \\f5c8;\n$fa-var-tired: \\f5c8;\n$fa-var-money-bills: \\e1f3;\n$fa-var-smog: \\f75f;\n$fa-var-crutch: \\f7f7;\n$fa-var-cloud-arrow-up: \\f0ee;\n$fa-var-cloud-upload: \\f0ee;\n$fa-var-cloud-upload-alt: \\f0ee;\n$fa-var-palette: \\f53f;\n$fa-var-arrows-turn-right: \\e4c0;\n$fa-var-vest: \\e085;\n$fa-var-ferry: \\e4ea;\n$fa-var-arrows-down-to-people: \\e4b9;\n$fa-var-seedling: \\f4d8;\n$fa-var-sprout: \\f4d8;\n$fa-var-left-right: \\f337;\n$fa-var-arrows-alt-h: \\f337;\n$fa-var-boxes-packing: \\e4c7;\n$fa-var-circle-arrow-left: \\f0a8;\n$fa-var-arrow-circle-left: \\f0a8;\n$fa-var-group-arrows-rotate: \\e4f6;\n$fa-var-bowl-food: \\e4c6;\n$fa-var-candy-cane: \\f786;\n$fa-var-arrow-down-wide-short: \\f160;\n$fa-var-sort-amount-asc: \\f160;\n$fa-var-sort-amount-down: \\f160;\n$fa-var-cloud-bolt: \\f76c;\n$fa-var-thunderstorm: \\f76c;\n$fa-var-text-slash: \\f87d;\n$fa-var-remove-format: \\f87d;\n$fa-var-face-smile-wink: \\f4da;\n$fa-var-smile-wink: \\f4da;\n$fa-var-file-word: \\f1c2;\n$fa-var-file-powerpoint: \\f1c4;\n$fa-var-arrows-left-right: \\f07e;\n$fa-var-arrows-h: \\f07e;\n$fa-var-house-lock: \\e510;\n$fa-var-cloud-arrow-down: \\f0ed;\n$fa-var-cloud-download: \\f0ed;\n$fa-var-cloud-download-alt: \\f0ed;\n$fa-var-children: \\e4e1;\n$fa-var-chalkboard: \\f51b;\n$fa-var-blackboard: \\f51b;\n$fa-var-user-large-slash: \\f4fa;\n$fa-var-user-alt-slash: \\f4fa;\n$fa-var-envelope-open: \\f2b6;\n$fa-var-handshake-simple-slash: \\e05f;\n$fa-var-handshake-alt-slash: \\e05f;\n$fa-var-mattress-pillow: \\e525;\n$fa-var-guarani-sign: \\e19a;\n$fa-var-arrows-rotate: \\f021;\n$fa-var-refresh: \\f021;\n$fa-var-sync: \\f021;\n$fa-var-fire-extinguisher: \\f134;\n$fa-var-cruzeiro-sign: \\e152;\n$fa-var-greater-than-equal: \\f532;\n$fa-var-shield-halved: \\f3ed;\n$fa-var-shield-alt: \\f3ed;\n$fa-var-book-atlas: \\f558;\n$fa-var-atlas: \\f558;\n$fa-var-virus: \\e074;\n$fa-var-envelope-circle-check: \\e4e8;\n$fa-var-layer-group: \\f5fd;\n$fa-var-arrows-to-dot: \\e4be;\n$fa-var-archway: \\f557;\n$fa-var-heart-circle-check: \\e4fd;\n$fa-var-house-chimney-crack: \\f6f1;\n$fa-var-house-damage: \\f6f1;\n$fa-var-file-zipper: \\f1c6;\n$fa-var-file-archive: \\f1c6;\n$fa-var-square: \\f0c8;\n$fa-var-martini-glass-empty: \\f000;\n$fa-var-glass-martini: \\f000;\n$fa-var-couch: \\f4b8;\n$fa-var-cedi-sign: \\e0df;\n$fa-var-italic: \\f033;\n$fa-var-table-cells-column-lock: \\e678;\n$fa-var-church: \\f51d;\n$fa-var-comments-dollar: \\f653;\n$fa-var-democrat: \\f747;\n$fa-var-z: \\5a;\n$fa-var-person-skiing: \\f7c9;\n$fa-var-skiing: \\f7c9;\n$fa-var-road-lock: \\e567;\n$fa-var-a: \\41;\n$fa-var-temperature-arrow-down: \\e03f;\n$fa-var-temperature-down: \\e03f;\n$fa-var-feather-pointed: \\f56b;\n$fa-var-feather-alt: \\f56b;\n$fa-var-p: \\50;\n$fa-var-snowflake: \\f2dc;\n$fa-var-newspaper: \\f1ea;\n$fa-var-rectangle-ad: \\f641;\n$fa-var-ad: \\f641;\n$fa-var-circle-arrow-right: \\f0a9;\n$fa-var-arrow-circle-right: \\f0a9;\n$fa-var-filter-circle-xmark: \\e17b;\n$fa-var-locust: \\e520;\n$fa-var-sort: \\f0dc;\n$fa-var-unsorted: \\f0dc;\n$fa-var-list-ol: \\f0cb;\n$fa-var-list-1-2: \\f0cb;\n$fa-var-list-numeric: \\f0cb;\n$fa-var-person-dress-burst: \\e544;\n$fa-var-money-check-dollar: \\f53d;\n$fa-var-money-check-alt: \\f53d;\n$fa-var-vector-square: \\f5cb;\n$fa-var-bread-slice: \\f7ec;\n$fa-var-language: \\f1ab;\n$fa-var-face-kiss-wink-heart: \\f598;\n$fa-var-kiss-wink-heart: \\f598;\n$fa-var-filter: \\f0b0;\n$fa-var-question: \\3f;\n$fa-var-file-signature: \\f573;\n$fa-var-up-down-left-right: \\f0b2;\n$fa-var-arrows-alt: \\f0b2;\n$fa-var-house-chimney-user: \\e065;\n$fa-var-hand-holding-heart: \\f4be;\n$fa-var-puzzle-piece: \\f12e;\n$fa-var-money-check: \\f53c;\n$fa-var-star-half-stroke: \\f5c0;\n$fa-var-star-half-alt: \\f5c0;\n$fa-var-code: \\f121;\n$fa-var-whiskey-glass: \\f7a0;\n$fa-var-glass-whiskey: \\f7a0;\n$fa-var-building-circle-exclamation: \\e4d3;\n$fa-var-magnifying-glass-chart: \\e522;\n$fa-var-arrow-up-right-from-square: \\f08e;\n$fa-var-external-link: \\f08e;\n$fa-var-cubes-stacked: \\e4e6;\n$fa-var-won-sign: \\f159;\n$fa-var-krw: \\f159;\n$fa-var-won: \\f159;\n$fa-var-virus-covid: \\e4a8;\n$fa-var-austral-sign: \\e0a9;\n$fa-var-f: \\46;\n$fa-var-leaf: \\f06c;\n$fa-var-road: \\f018;\n$fa-var-taxi: \\f1ba;\n$fa-var-cab: \\f1ba;\n$fa-var-person-circle-plus: \\e541;\n$fa-var-chart-pie: \\f200;\n$fa-var-pie-chart: \\f200;\n$fa-var-bolt-lightning: \\e0b7;\n$fa-var-sack-xmark: \\e56a;\n$fa-var-file-excel: \\f1c3;\n$fa-var-file-contract: \\f56c;\n$fa-var-fish-fins: \\e4f2;\n$fa-var-building-flag: \\e4d5;\n$fa-var-face-grin-beam: \\f582;\n$fa-var-grin-beam: \\f582;\n$fa-var-object-ungroup: \\f248;\n$fa-var-poop: \\f619;\n$fa-var-location-pin: \\f041;\n$fa-var-map-marker: \\f041;\n$fa-var-kaaba: \\f66b;\n$fa-var-toilet-paper: \\f71e;\n$fa-var-helmet-safety: \\f807;\n$fa-var-hard-hat: \\f807;\n$fa-var-hat-hard: \\f807;\n$fa-var-eject: \\f052;\n$fa-var-circle-right: \\f35a;\n$fa-var-arrow-alt-circle-right: \\f35a;\n$fa-var-plane-circle-check: \\e555;\n$fa-var-face-rolling-eyes: \\f5a5;\n$fa-var-meh-rolling-eyes: \\f5a5;\n$fa-var-object-group: \\f247;\n$fa-var-chart-line: \\f201;\n$fa-var-line-chart: \\f201;\n$fa-var-mask-ventilator: \\e524;\n$fa-var-arrow-right: \\f061;\n$fa-var-signs-post: \\f277;\n$fa-var-map-signs: \\f277;\n$fa-var-cash-register: \\f788;\n$fa-var-person-circle-question: \\e542;\n$fa-var-h: \\48;\n$fa-var-tarp: \\e57b;\n$fa-var-screwdriver-wrench: \\f7d9;\n$fa-var-tools: \\f7d9;\n$fa-var-arrows-to-eye: \\e4bf;\n$fa-var-plug-circle-bolt: \\e55b;\n$fa-var-heart: \\f004;\n$fa-var-mars-and-venus: \\f224;\n$fa-var-house-user: \\e1b0;\n$fa-var-home-user: \\e1b0;\n$fa-var-dumpster-fire: \\f794;\n$fa-var-house-crack: \\e3b1;\n$fa-var-martini-glass-citrus: \\f561;\n$fa-var-cocktail: \\f561;\n$fa-var-face-surprise: \\f5c2;\n$fa-var-surprise: \\f5c2;\n$fa-var-bottle-water: \\e4c5;\n$fa-var-circle-pause: \\f28b;\n$fa-var-pause-circle: \\f28b;\n$fa-var-toilet-paper-slash: \\e072;\n$fa-var-apple-whole: \\f5d1;\n$fa-var-apple-alt: \\f5d1;\n$fa-var-kitchen-set: \\e51a;\n$fa-var-r: \\52;\n$fa-var-temperature-quarter: \\f2ca;\n$fa-var-temperature-1: \\f2ca;\n$fa-var-thermometer-1: \\f2ca;\n$fa-var-thermometer-quarter: \\f2ca;\n$fa-var-cube: \\f1b2;\n$fa-var-bitcoin-sign: \\e0b4;\n$fa-var-shield-dog: \\e573;\n$fa-var-solar-panel: \\f5ba;\n$fa-var-lock-open: \\f3c1;\n$fa-var-elevator: \\e16d;\n$fa-var-money-bill-transfer: \\e528;\n$fa-var-money-bill-trend-up: \\e529;\n$fa-var-house-flood-water-circle-arrow-right: \\e50f;\n$fa-var-square-poll-horizontal: \\f682;\n$fa-var-poll-h: \\f682;\n$fa-var-circle: \\f111;\n$fa-var-backward-fast: \\f049;\n$fa-var-fast-backward: \\f049;\n$fa-var-recycle: \\f1b8;\n$fa-var-user-astronaut: \\f4fb;\n$fa-var-plane-slash: \\e069;\n$fa-var-trademark: \\f25c;\n$fa-var-basketball: \\f434;\n$fa-var-basketball-ball: \\f434;\n$fa-var-satellite-dish: \\f7c0;\n$fa-var-circle-up: \\f35b;\n$fa-var-arrow-alt-circle-up: \\f35b;\n$fa-var-mobile-screen-button: \\f3cd;\n$fa-var-mobile-alt: \\f3cd;\n$fa-var-volume-high: \\f028;\n$fa-var-volume-up: \\f028;\n$fa-var-users-rays: \\e593;\n$fa-var-wallet: \\f555;\n$fa-var-clipboard-check: \\f46c;\n$fa-var-file-audio: \\f1c7;\n$fa-var-burger: \\f805;\n$fa-var-hamburger: \\f805;\n$fa-var-wrench: \\f0ad;\n$fa-var-bugs: \\e4d0;\n$fa-var-rupee-sign: \\f156;\n$fa-var-rupee: \\f156;\n$fa-var-file-image: \\f1c5;\n$fa-var-circle-question: \\f059;\n$fa-var-question-circle: \\f059;\n$fa-var-plane-departure: \\f5b0;\n$fa-var-handshake-slash: \\e060;\n$fa-var-book-bookmark: \\e0bb;\n$fa-var-code-branch: \\f126;\n$fa-var-hat-cowboy: \\f8c0;\n$fa-var-bridge: \\e4c8;\n$fa-var-phone-flip: \\f879;\n$fa-var-phone-alt: \\f879;\n$fa-var-truck-front: \\e2b7;\n$fa-var-cat: \\f6be;\n$fa-var-anchor-circle-exclamation: \\e4ab;\n$fa-var-truck-field: \\e58d;\n$fa-var-route: \\f4d7;\n$fa-var-clipboard-question: \\e4e3;\n$fa-var-panorama: \\e209;\n$fa-var-comment-medical: \\f7f5;\n$fa-var-teeth-open: \\f62f;\n$fa-var-file-circle-minus: \\e4ed;\n$fa-var-tags: \\f02c;\n$fa-var-wine-glass: \\f4e3;\n$fa-var-forward-fast: \\f050;\n$fa-var-fast-forward: \\f050;\n$fa-var-face-meh-blank: \\f5a4;\n$fa-var-meh-blank: \\f5a4;\n$fa-var-square-parking: \\f540;\n$fa-var-parking: \\f540;\n$fa-var-house-signal: \\e012;\n$fa-var-bars-progress: \\f828;\n$fa-var-tasks-alt: \\f828;\n$fa-var-faucet-drip: \\e006;\n$fa-var-cart-flatbed: \\f474;\n$fa-var-dolly-flatbed: \\f474;\n$fa-var-ban-smoking: \\f54d;\n$fa-var-smoking-ban: \\f54d;\n$fa-var-terminal: \\f120;\n$fa-var-mobile-button: \\f10b;\n$fa-var-house-medical-flag: \\e514;\n$fa-var-basket-shopping: \\f291;\n$fa-var-shopping-basket: \\f291;\n$fa-var-tape: \\f4db;\n$fa-var-bus-simple: \\f55e;\n$fa-var-bus-alt: \\f55e;\n$fa-var-eye: \\f06e;\n$fa-var-face-sad-cry: \\f5b3;\n$fa-var-sad-cry: \\f5b3;\n$fa-var-audio-description: \\f29e;\n$fa-var-person-military-to-person: \\e54c;\n$fa-var-file-shield: \\e4f0;\n$fa-var-user-slash: \\f506;\n$fa-var-pen: \\f304;\n$fa-var-tower-observation: \\e586;\n$fa-var-file-code: \\f1c9;\n$fa-var-signal: \\f012;\n$fa-var-signal-5: \\f012;\n$fa-var-signal-perfect: \\f012;\n$fa-var-bus: \\f207;\n$fa-var-heart-circle-xmark: \\e501;\n$fa-var-house-chimney: \\e3af;\n$fa-var-home-lg: \\e3af;\n$fa-var-window-maximize: \\f2d0;\n$fa-var-face-frown: \\f119;\n$fa-var-frown: \\f119;\n$fa-var-prescription: \\f5b1;\n$fa-var-shop: \\f54f;\n$fa-var-store-alt: \\f54f;\n$fa-var-floppy-disk: \\f0c7;\n$fa-var-save: \\f0c7;\n$fa-var-vihara: \\f6a7;\n$fa-var-scale-unbalanced: \\f515;\n$fa-var-balance-scale-left: \\f515;\n$fa-var-sort-up: \\f0de;\n$fa-var-sort-asc: \\f0de;\n$fa-var-comment-dots: \\f4ad;\n$fa-var-commenting: \\f4ad;\n$fa-var-plant-wilt: \\e5aa;\n$fa-var-diamond: \\f219;\n$fa-var-face-grin-squint: \\f585;\n$fa-var-grin-squint: \\f585;\n$fa-var-hand-holding-dollar: \\f4c0;\n$fa-var-hand-holding-usd: \\f4c0;\n$fa-var-chart-diagram: \\e695;\n$fa-var-bacterium: \\e05a;\n$fa-var-hand-pointer: \\f25a;\n$fa-var-drum-steelpan: \\f56a;\n$fa-var-hand-scissors: \\f257;\n$fa-var-hands-praying: \\f684;\n$fa-var-praying-hands: \\f684;\n$fa-var-arrow-rotate-right: \\f01e;\n$fa-var-arrow-right-rotate: \\f01e;\n$fa-var-arrow-rotate-forward: \\f01e;\n$fa-var-redo: \\f01e;\n$fa-var-biohazard: \\f780;\n$fa-var-location-crosshairs: \\f601;\n$fa-var-location: \\f601;\n$fa-var-mars-double: \\f227;\n$fa-var-child-dress: \\e59c;\n$fa-var-users-between-lines: \\e591;\n$fa-var-lungs-virus: \\e067;\n$fa-var-face-grin-tears: \\f588;\n$fa-var-grin-tears: \\f588;\n$fa-var-phone: \\f095;\n$fa-var-calendar-xmark: \\f273;\n$fa-var-calendar-times: \\f273;\n$fa-var-child-reaching: \\e59d;\n$fa-var-head-side-virus: \\e064;\n$fa-var-user-gear: \\f4fe;\n$fa-var-user-cog: \\f4fe;\n$fa-var-arrow-up-1-9: \\f163;\n$fa-var-sort-numeric-up: \\f163;\n$fa-var-door-closed: \\f52a;\n$fa-var-shield-virus: \\e06c;\n$fa-var-dice-six: \\f526;\n$fa-var-mosquito-net: \\e52c;\n$fa-var-file-fragment: \\e697;\n$fa-var-bridge-water: \\e4ce;\n$fa-var-person-booth: \\f756;\n$fa-var-text-width: \\f035;\n$fa-var-hat-wizard: \\f6e8;\n$fa-var-pen-fancy: \\f5ac;\n$fa-var-person-digging: \\f85e;\n$fa-var-digging: \\f85e;\n$fa-var-trash: \\f1f8;\n$fa-var-gauge-simple: \\f629;\n$fa-var-gauge-simple-med: \\f629;\n$fa-var-tachometer-average: \\f629;\n$fa-var-book-medical: \\f7e6;\n$fa-var-poo: \\f2fe;\n$fa-var-quote-right: \\f10e;\n$fa-var-quote-right-alt: \\f10e;\n$fa-var-shirt: \\f553;\n$fa-var-t-shirt: \\f553;\n$fa-var-tshirt: \\f553;\n$fa-var-cubes: \\f1b3;\n$fa-var-divide: \\f529;\n$fa-var-tenge-sign: \\f7d7;\n$fa-var-tenge: \\f7d7;\n$fa-var-headphones: \\f025;\n$fa-var-hands-holding: \\f4c2;\n$fa-var-hands-clapping: \\e1a8;\n$fa-var-republican: \\f75e;\n$fa-var-arrow-left: \\f060;\n$fa-var-person-circle-xmark: \\e543;\n$fa-var-ruler: \\f545;\n$fa-var-align-left: \\f036;\n$fa-var-dice-d6: \\f6d1;\n$fa-var-restroom: \\f7bd;\n$fa-var-j: \\4a;\n$fa-var-users-viewfinder: \\e595;\n$fa-var-file-video: \\f1c8;\n$fa-var-up-right-from-square: \\f35d;\n$fa-var-external-link-alt: \\f35d;\n$fa-var-table-cells: \\f00a;\n$fa-var-th: \\f00a;\n$fa-var-file-pdf: \\f1c1;\n$fa-var-book-bible: \\f647;\n$fa-var-bible: \\f647;\n$fa-var-o: \\4f;\n$fa-var-suitcase-medical: \\f0fa;\n$fa-var-medkit: \\f0fa;\n$fa-var-user-secret: \\f21b;\n$fa-var-otter: \\f700;\n$fa-var-person-dress: \\f182;\n$fa-var-female: \\f182;\n$fa-var-comment-dollar: \\f651;\n$fa-var-business-time: \\f64a;\n$fa-var-briefcase-clock: \\f64a;\n$fa-var-table-cells-large: \\f009;\n$fa-var-th-large: \\f009;\n$fa-var-book-tanakh: \\f827;\n$fa-var-tanakh: \\f827;\n$fa-var-phone-volume: \\f2a0;\n$fa-var-volume-control-phone: \\f2a0;\n$fa-var-hat-cowboy-side: \\f8c1;\n$fa-var-clipboard-user: \\f7f3;\n$fa-var-child: \\f1ae;\n$fa-var-lira-sign: \\f195;\n$fa-var-satellite: \\f7bf;\n$fa-var-plane-lock: \\e558;\n$fa-var-tag: \\f02b;\n$fa-var-comment: \\f075;\n$fa-var-cake-candles: \\f1fd;\n$fa-var-birthday-cake: \\f1fd;\n$fa-var-cake: \\f1fd;\n$fa-var-envelope: \\f0e0;\n$fa-var-angles-up: \\f102;\n$fa-var-angle-double-up: \\f102;\n$fa-var-paperclip: \\f0c6;\n$fa-var-arrow-right-to-city: \\e4b3;\n$fa-var-ribbon: \\f4d6;\n$fa-var-lungs: \\f604;\n$fa-var-arrow-up-9-1: \\f887;\n$fa-var-sort-numeric-up-alt: \\f887;\n$fa-var-litecoin-sign: \\e1d3;\n$fa-var-border-none: \\f850;\n$fa-var-circle-nodes: \\e4e2;\n$fa-var-parachute-box: \\f4cd;\n$fa-var-indent: \\f03c;\n$fa-var-truck-field-un: \\e58e;\n$fa-var-hourglass: \\f254;\n$fa-var-hourglass-empty: \\f254;\n$fa-var-mountain: \\f6fc;\n$fa-var-user-doctor: \\f0f0;\n$fa-var-user-md: \\f0f0;\n$fa-var-circle-info: \\f05a;\n$fa-var-info-circle: \\f05a;\n$fa-var-cloud-meatball: \\f73b;\n$fa-var-camera: \\f030;\n$fa-var-camera-alt: \\f030;\n$fa-var-square-virus: \\e578;\n$fa-var-meteor: \\f753;\n$fa-var-car-on: \\e4dd;\n$fa-var-sleigh: \\f7cc;\n$fa-var-arrow-down-1-9: \\f162;\n$fa-var-sort-numeric-asc: \\f162;\n$fa-var-sort-numeric-down: \\f162;\n$fa-var-hand-holding-droplet: \\f4c1;\n$fa-var-hand-holding-water: \\f4c1;\n$fa-var-water: \\f773;\n$fa-var-calendar-check: \\f274;\n$fa-var-braille: \\f2a1;\n$fa-var-prescription-bottle-medical: \\f486;\n$fa-var-prescription-bottle-alt: \\f486;\n$fa-var-landmark: \\f66f;\n$fa-var-truck: \\f0d1;\n$fa-var-crosshairs: \\f05b;\n$fa-var-person-cane: \\e53c;\n$fa-var-tent: \\e57d;\n$fa-var-vest-patches: \\e086;\n$fa-var-check-double: \\f560;\n$fa-var-arrow-down-a-z: \\f15d;\n$fa-var-sort-alpha-asc: \\f15d;\n$fa-var-sort-alpha-down: \\f15d;\n$fa-var-money-bill-wheat: \\e52a;\n$fa-var-cookie: \\f563;\n$fa-var-arrow-rotate-left: \\f0e2;\n$fa-var-arrow-left-rotate: \\f0e2;\n$fa-var-arrow-rotate-back: \\f0e2;\n$fa-var-arrow-rotate-backward: \\f0e2;\n$fa-var-undo: \\f0e2;\n$fa-var-hard-drive: \\f0a0;\n$fa-var-hdd: \\f0a0;\n$fa-var-face-grin-squint-tears: \\f586;\n$fa-var-grin-squint-tears: \\f586;\n$fa-var-dumbbell: \\f44b;\n$fa-var-rectangle-list: \\f022;\n$fa-var-list-alt: \\f022;\n$fa-var-tarp-droplet: \\e57c;\n$fa-var-house-medical-circle-check: \\e511;\n$fa-var-person-skiing-nordic: \\f7ca;\n$fa-var-skiing-nordic: \\f7ca;\n$fa-var-calendar-plus: \\f271;\n$fa-var-plane-arrival: \\f5af;\n$fa-var-circle-left: \\f359;\n$fa-var-arrow-alt-circle-left: \\f359;\n$fa-var-train-subway: \\f239;\n$fa-var-subway: \\f239;\n$fa-var-chart-gantt: \\e0e4;\n$fa-var-indian-rupee-sign: \\e1bc;\n$fa-var-indian-rupee: \\e1bc;\n$fa-var-inr: \\e1bc;\n$fa-var-crop-simple: \\f565;\n$fa-var-crop-alt: \\f565;\n$fa-var-money-bill-1: \\f3d1;\n$fa-var-money-bill-alt: \\f3d1;\n$fa-var-left-long: \\f30a;\n$fa-var-long-arrow-alt-left: \\f30a;\n$fa-var-dna: \\f471;\n$fa-var-virus-slash: \\e075;\n$fa-var-minus: \\f068;\n$fa-var-subtract: \\f068;\n$fa-var-chess: \\f439;\n$fa-var-arrow-left-long: \\f177;\n$fa-var-long-arrow-left: \\f177;\n$fa-var-plug-circle-check: \\e55c;\n$fa-var-street-view: \\f21d;\n$fa-var-franc-sign: \\e18f;\n$fa-var-volume-off: \\f026;\n$fa-var-hands-asl-interpreting: \\f2a3;\n$fa-var-american-sign-language-interpreting: \\f2a3;\n$fa-var-asl-interpreting: \\f2a3;\n$fa-var-hands-american-sign-language-interpreting: \\f2a3;\n$fa-var-gear: \\f013;\n$fa-var-cog: \\f013;\n$fa-var-droplet-slash: \\f5c7;\n$fa-var-tint-slash: \\f5c7;\n$fa-var-mosque: \\f678;\n$fa-var-mosquito: \\e52b;\n$fa-var-star-of-david: \\f69a;\n$fa-var-person-military-rifle: \\e54b;\n$fa-var-cart-shopping: \\f07a;\n$fa-var-shopping-cart: \\f07a;\n$fa-var-vials: \\f493;\n$fa-var-plug-circle-plus: \\e55f;\n$fa-var-place-of-worship: \\f67f;\n$fa-var-grip-vertical: \\f58e;\n$fa-var-hexagon-nodes: \\e699;\n$fa-var-arrow-turn-up: \\f148;\n$fa-var-level-up: \\f148;\n$fa-var-u: \\55;\n$fa-var-square-root-variable: \\f698;\n$fa-var-square-root-alt: \\f698;\n$fa-var-clock: \\f017;\n$fa-var-clock-four: \\f017;\n$fa-var-backward-step: \\f048;\n$fa-var-step-backward: \\f048;\n$fa-var-pallet: \\f482;\n$fa-var-faucet: \\e005;\n$fa-var-baseball-bat-ball: \\f432;\n$fa-var-s: \\53;\n$fa-var-timeline: \\e29c;\n$fa-var-keyboard: \\f11c;\n$fa-var-caret-down: \\f0d7;\n$fa-var-house-chimney-medical: \\f7f2;\n$fa-var-clinic-medical: \\f7f2;\n$fa-var-temperature-three-quarters: \\f2c8;\n$fa-var-temperature-3: \\f2c8;\n$fa-var-thermometer-3: \\f2c8;\n$fa-var-thermometer-three-quarters: \\f2c8;\n$fa-var-mobile-screen: \\f3cf;\n$fa-var-mobile-android-alt: \\f3cf;\n$fa-var-plane-up: \\e22d;\n$fa-var-piggy-bank: \\f4d3;\n$fa-var-battery-half: \\f242;\n$fa-var-battery-3: \\f242;\n$fa-var-mountain-city: \\e52e;\n$fa-var-coins: \\f51e;\n$fa-var-khanda: \\f66d;\n$fa-var-sliders: \\f1de;\n$fa-var-sliders-h: \\f1de;\n$fa-var-folder-tree: \\f802;\n$fa-var-network-wired: \\f6ff;\n$fa-var-map-pin: \\f276;\n$fa-var-hamsa: \\f665;\n$fa-var-cent-sign: \\e3f5;\n$fa-var-flask: \\f0c3;\n$fa-var-person-pregnant: \\e31e;\n$fa-var-wand-sparkles: \\f72b;\n$fa-var-ellipsis-vertical: \\f142;\n$fa-var-ellipsis-v: \\f142;\n$fa-var-ticket: \\f145;\n$fa-var-power-off: \\f011;\n$fa-var-right-long: \\f30b;\n$fa-var-long-arrow-alt-right: \\f30b;\n$fa-var-flag-usa: \\f74d;\n$fa-var-laptop-file: \\e51d;\n$fa-var-tty: \\f1e4;\n$fa-var-teletype: \\f1e4;\n$fa-var-diagram-next: \\e476;\n$fa-var-person-rifle: \\e54e;\n$fa-var-house-medical-circle-exclamation: \\e512;\n$fa-var-closed-captioning: \\f20a;\n$fa-var-person-hiking: \\f6ec;\n$fa-var-hiking: \\f6ec;\n$fa-var-venus-double: \\f226;\n$fa-var-images: \\f302;\n$fa-var-calculator: \\f1ec;\n$fa-var-people-pulling: \\e535;\n$fa-var-n: \\4e;\n$fa-var-cable-car: \\f7da;\n$fa-var-tram: \\f7da;\n$fa-var-cloud-rain: \\f73d;\n$fa-var-building-circle-xmark: \\e4d4;\n$fa-var-ship: \\f21a;\n$fa-var-arrows-down-to-line: \\e4b8;\n$fa-var-download: \\f019;\n$fa-var-face-grin: \\f580;\n$fa-var-grin: \\f580;\n$fa-var-delete-left: \\f55a;\n$fa-var-backspace: \\f55a;\n$fa-var-eye-dropper: \\f1fb;\n$fa-var-eye-dropper-empty: \\f1fb;\n$fa-var-eyedropper: \\f1fb;\n$fa-var-file-circle-check: \\e5a0;\n$fa-var-forward: \\f04e;\n$fa-var-mobile: \\f3ce;\n$fa-var-mobile-android: \\f3ce;\n$fa-var-mobile-phone: \\f3ce;\n$fa-var-face-meh: \\f11a;\n$fa-var-meh: \\f11a;\n$fa-var-align-center: \\f037;\n$fa-var-book-skull: \\f6b7;\n$fa-var-book-dead: \\f6b7;\n$fa-var-id-card: \\f2c2;\n$fa-var-drivers-license: \\f2c2;\n$fa-var-outdent: \\f03b;\n$fa-var-dedent: \\f03b;\n$fa-var-heart-circle-exclamation: \\e4fe;\n$fa-var-house: \\f015;\n$fa-var-home: \\f015;\n$fa-var-home-alt: \\f015;\n$fa-var-home-lg-alt: \\f015;\n$fa-var-calendar-week: \\f784;\n$fa-var-laptop-medical: \\f812;\n$fa-var-b: \\42;\n$fa-var-file-medical: \\f477;\n$fa-var-dice-one: \\f525;\n$fa-var-kiwi-bird: \\f535;\n$fa-var-arrow-right-arrow-left: \\f0ec;\n$fa-var-exchange: \\f0ec;\n$fa-var-rotate-right: \\f2f9;\n$fa-var-redo-alt: \\f2f9;\n$fa-var-rotate-forward: \\f2f9;\n$fa-var-utensils: \\f2e7;\n$fa-var-cutlery: \\f2e7;\n$fa-var-arrow-up-wide-short: \\f161;\n$fa-var-sort-amount-up: \\f161;\n$fa-var-mill-sign: \\e1ed;\n$fa-var-bowl-rice: \\e2eb;\n$fa-var-skull: \\f54c;\n$fa-var-tower-broadcast: \\f519;\n$fa-var-broadcast-tower: \\f519;\n$fa-var-truck-pickup: \\f63c;\n$fa-var-up-long: \\f30c;\n$fa-var-long-arrow-alt-up: \\f30c;\n$fa-var-stop: \\f04d;\n$fa-var-code-merge: \\f387;\n$fa-var-upload: \\f093;\n$fa-var-hurricane: \\f751;\n$fa-var-mound: \\e52d;\n$fa-var-toilet-portable: \\e583;\n$fa-var-compact-disc: \\f51f;\n$fa-var-file-arrow-down: \\f56d;\n$fa-var-file-download: \\f56d;\n$fa-var-caravan: \\f8ff;\n$fa-var-shield-cat: \\e572;\n$fa-var-bolt: \\f0e7;\n$fa-var-zap: \\f0e7;\n$fa-var-glass-water: \\e4f4;\n$fa-var-oil-well: \\e532;\n$fa-var-vault: \\e2c5;\n$fa-var-mars: \\f222;\n$fa-var-toilet: \\f7d8;\n$fa-var-plane-circle-xmark: \\e557;\n$fa-var-yen-sign: \\f157;\n$fa-var-cny: \\f157;\n$fa-var-jpy: \\f157;\n$fa-var-rmb: \\f157;\n$fa-var-yen: \\f157;\n$fa-var-ruble-sign: \\f158;\n$fa-var-rouble: \\f158;\n$fa-var-rub: \\f158;\n$fa-var-ruble: \\f158;\n$fa-var-sun: \\f185;\n$fa-var-guitar: \\f7a6;\n$fa-var-face-laugh-wink: \\f59c;\n$fa-var-laugh-wink: \\f59c;\n$fa-var-horse-head: \\f7ab;\n$fa-var-bore-hole: \\e4c3;\n$fa-var-industry: \\f275;\n$fa-var-circle-down: \\f358;\n$fa-var-arrow-alt-circle-down: \\f358;\n$fa-var-arrows-turn-to-dots: \\e4c1;\n$fa-var-florin-sign: \\e184;\n$fa-var-arrow-down-short-wide: \\f884;\n$fa-var-sort-amount-desc: \\f884;\n$fa-var-sort-amount-down-alt: \\f884;\n$fa-var-less-than: \\3c;\n$fa-var-angle-down: \\f107;\n$fa-var-car-tunnel: \\e4de;\n$fa-var-head-side-cough: \\e061;\n$fa-var-grip-lines: \\f7a4;\n$fa-var-thumbs-down: \\f165;\n$fa-var-user-lock: \\f502;\n$fa-var-arrow-right-long: \\f178;\n$fa-var-long-arrow-right: \\f178;\n$fa-var-anchor-circle-xmark: \\e4ac;\n$fa-var-ellipsis: \\f141;\n$fa-var-ellipsis-h: \\f141;\n$fa-var-chess-pawn: \\f443;\n$fa-var-kit-medical: \\f479;\n$fa-var-first-aid: \\f479;\n$fa-var-person-through-window: \\e5a9;\n$fa-var-toolbox: \\f552;\n$fa-var-hands-holding-circle: \\e4fb;\n$fa-var-bug: \\f188;\n$fa-var-credit-card: \\f09d;\n$fa-var-credit-card-alt: \\f09d;\n$fa-var-car: \\f1b9;\n$fa-var-automobile: \\f1b9;\n$fa-var-hand-holding-hand: \\e4f7;\n$fa-var-book-open-reader: \\f5da;\n$fa-var-book-reader: \\f5da;\n$fa-var-mountain-sun: \\e52f;\n$fa-var-arrows-left-right-to-line: \\e4ba;\n$fa-var-dice-d20: \\f6cf;\n$fa-var-truck-droplet: \\e58c;\n$fa-var-file-circle-xmark: \\e5a1;\n$fa-var-temperature-arrow-up: \\e040;\n$fa-var-temperature-up: \\e040;\n$fa-var-medal: \\f5a2;\n$fa-var-bed: \\f236;\n$fa-var-square-h: \\f0fd;\n$fa-var-h-square: \\f0fd;\n$fa-var-podcast: \\f2ce;\n$fa-var-temperature-full: \\f2c7;\n$fa-var-temperature-4: \\f2c7;\n$fa-var-thermometer-4: \\f2c7;\n$fa-var-thermometer-full: \\f2c7;\n$fa-var-bell: \\f0f3;\n$fa-var-superscript: \\f12b;\n$fa-var-plug-circle-xmark: \\e560;\n$fa-var-star-of-life: \\f621;\n$fa-var-phone-slash: \\f3dd;\n$fa-var-paint-roller: \\f5aa;\n$fa-var-handshake-angle: \\f4c4;\n$fa-var-hands-helping: \\f4c4;\n$fa-var-location-dot: \\f3c5;\n$fa-var-map-marker-alt: \\f3c5;\n$fa-var-file: \\f15b;\n$fa-var-greater-than: \\3e;\n$fa-var-person-swimming: \\f5c4;\n$fa-var-swimmer: \\f5c4;\n$fa-var-arrow-down: \\f063;\n$fa-var-droplet: \\f043;\n$fa-var-tint: \\f043;\n$fa-var-eraser: \\f12d;\n$fa-var-earth-americas: \\f57d;\n$fa-var-earth: \\f57d;\n$fa-var-earth-america: \\f57d;\n$fa-var-globe-americas: \\f57d;\n$fa-var-person-burst: \\e53b;\n$fa-var-dove: \\f4ba;\n$fa-var-battery-empty: \\f244;\n$fa-var-battery-0: \\f244;\n$fa-var-socks: \\f696;\n$fa-var-inbox: \\f01c;\n$fa-var-section: \\e447;\n$fa-var-gauge-high: \\f625;\n$fa-var-tachometer-alt: \\f625;\n$fa-var-tachometer-alt-fast: \\f625;\n$fa-var-envelope-open-text: \\f658;\n$fa-var-hospital: \\f0f8;\n$fa-var-hospital-alt: \\f0f8;\n$fa-var-hospital-wide: \\f0f8;\n$fa-var-wine-bottle: \\f72f;\n$fa-var-chess-rook: \\f447;\n$fa-var-bars-staggered: \\f550;\n$fa-var-reorder: \\f550;\n$fa-var-stream: \\f550;\n$fa-var-dharmachakra: \\f655;\n$fa-var-hotdog: \\f80f;\n$fa-var-person-walking-with-cane: \\f29d;\n$fa-var-blind: \\f29d;\n$fa-var-drum: \\f569;\n$fa-var-ice-cream: \\f810;\n$fa-var-heart-circle-bolt: \\e4fc;\n$fa-var-fax: \\f1ac;\n$fa-var-paragraph: \\f1dd;\n$fa-var-check-to-slot: \\f772;\n$fa-var-vote-yea: \\f772;\n$fa-var-star-half: \\f089;\n$fa-var-boxes-stacked: \\f468;\n$fa-var-boxes: \\f468;\n$fa-var-boxes-alt: \\f468;\n$fa-var-link: \\f0c1;\n$fa-var-chain: \\f0c1;\n$fa-var-ear-listen: \\f2a2;\n$fa-var-assistive-listening-systems: \\f2a2;\n$fa-var-tree-city: \\e587;\n$fa-var-play: \\f04b;\n$fa-var-font: \\f031;\n$fa-var-table-cells-row-lock: \\e67a;\n$fa-var-rupiah-sign: \\e23d;\n$fa-var-magnifying-glass: \\f002;\n$fa-var-search: \\f002;\n$fa-var-table-tennis-paddle-ball: \\f45d;\n$fa-var-ping-pong-paddle-ball: \\f45d;\n$fa-var-table-tennis: \\f45d;\n$fa-var-person-dots-from-line: \\f470;\n$fa-var-diagnoses: \\f470;\n$fa-var-trash-can-arrow-up: \\f82a;\n$fa-var-trash-restore-alt: \\f82a;\n$fa-var-naira-sign: \\e1f6;\n$fa-var-cart-arrow-down: \\f218;\n$fa-var-walkie-talkie: \\f8ef;\n$fa-var-file-pen: \\f31c;\n$fa-var-file-edit: \\f31c;\n$fa-var-receipt: \\f543;\n$fa-var-square-pen: \\f14b;\n$fa-var-pen-square: \\f14b;\n$fa-var-pencil-square: \\f14b;\n$fa-var-suitcase-rolling: \\f5c1;\n$fa-var-person-circle-exclamation: \\e53f;\n$fa-var-chevron-down: \\f078;\n$fa-var-battery-full: \\f240;\n$fa-var-battery: \\f240;\n$fa-var-battery-5: \\f240;\n$fa-var-skull-crossbones: \\f714;\n$fa-var-code-compare: \\e13a;\n$fa-var-list-ul: \\f0ca;\n$fa-var-list-dots: \\f0ca;\n$fa-var-school-lock: \\e56f;\n$fa-var-tower-cell: \\e585;\n$fa-var-down-long: \\f309;\n$fa-var-long-arrow-alt-down: \\f309;\n$fa-var-ranking-star: \\e561;\n$fa-var-chess-king: \\f43f;\n$fa-var-person-harassing: \\e549;\n$fa-var-brazilian-real-sign: \\e46c;\n$fa-var-landmark-dome: \\f752;\n$fa-var-landmark-alt: \\f752;\n$fa-var-arrow-up: \\f062;\n$fa-var-tv: \\f26c;\n$fa-var-television: \\f26c;\n$fa-var-tv-alt: \\f26c;\n$fa-var-shrimp: \\e448;\n$fa-var-list-check: \\f0ae;\n$fa-var-tasks: \\f0ae;\n$fa-var-jug-detergent: \\e519;\n$fa-var-circle-user: \\f2bd;\n$fa-var-user-circle: \\f2bd;\n$fa-var-user-shield: \\f505;\n$fa-var-wind: \\f72e;\n$fa-var-car-burst: \\f5e1;\n$fa-var-car-crash: \\f5e1;\n$fa-var-y: \\59;\n$fa-var-person-snowboarding: \\f7ce;\n$fa-var-snowboarding: \\f7ce;\n$fa-var-truck-fast: \\f48b;\n$fa-var-shipping-fast: \\f48b;\n$fa-var-fish: \\f578;\n$fa-var-user-graduate: \\f501;\n$fa-var-circle-half-stroke: \\f042;\n$fa-var-adjust: \\f042;\n$fa-var-clapperboard: \\e131;\n$fa-var-circle-radiation: \\f7ba;\n$fa-var-radiation-alt: \\f7ba;\n$fa-var-baseball: \\f433;\n$fa-var-baseball-ball: \\f433;\n$fa-var-jet-fighter-up: \\e518;\n$fa-var-diagram-project: \\f542;\n$fa-var-project-diagram: \\f542;\n$fa-var-copy: \\f0c5;\n$fa-var-volume-xmark: \\f6a9;\n$fa-var-volume-mute: \\f6a9;\n$fa-var-volume-times: \\f6a9;\n$fa-var-hand-sparkles: \\e05d;\n$fa-var-grip: \\f58d;\n$fa-var-grip-horizontal: \\f58d;\n$fa-var-share-from-square: \\f14d;\n$fa-var-share-square: \\f14d;\n$fa-var-child-combatant: \\e4e0;\n$fa-var-child-rifle: \\e4e0;\n$fa-var-gun: \\e19b;\n$fa-var-square-phone: \\f098;\n$fa-var-phone-square: \\f098;\n$fa-var-plus: \\2b;\n$fa-var-add: \\2b;\n$fa-var-expand: \\f065;\n$fa-var-computer: \\e4e5;\n$fa-var-xmark: \\f00d;\n$fa-var-close: \\f00d;\n$fa-var-multiply: \\f00d;\n$fa-var-remove: \\f00d;\n$fa-var-times: \\f00d;\n$fa-var-arrows-up-down-left-right: \\f047;\n$fa-var-arrows: \\f047;\n$fa-var-chalkboard-user: \\f51c;\n$fa-var-chalkboard-teacher: \\f51c;\n$fa-var-peso-sign: \\e222;\n$fa-var-building-shield: \\e4d8;\n$fa-var-baby: \\f77c;\n$fa-var-users-line: \\e592;\n$fa-var-quote-left: \\f10d;\n$fa-var-quote-left-alt: \\f10d;\n$fa-var-tractor: \\f722;\n$fa-var-trash-arrow-up: \\f829;\n$fa-var-trash-restore: \\f829;\n$fa-var-arrow-down-up-lock: \\e4b0;\n$fa-var-lines-leaning: \\e51e;\n$fa-var-ruler-combined: \\f546;\n$fa-var-copyright: \\f1f9;\n$fa-var-equals: \\3d;\n$fa-var-blender: \\f517;\n$fa-var-teeth: \\f62e;\n$fa-var-shekel-sign: \\f20b;\n$fa-var-ils: \\f20b;\n$fa-var-shekel: \\f20b;\n$fa-var-sheqel: \\f20b;\n$fa-var-sheqel-sign: \\f20b;\n$fa-var-map: \\f279;\n$fa-var-rocket: \\f135;\n$fa-var-photo-film: \\f87c;\n$fa-var-photo-video: \\f87c;\n$fa-var-folder-minus: \\f65d;\n$fa-var-hexagon-nodes-bolt: \\e69a;\n$fa-var-store: \\f54e;\n$fa-var-arrow-trend-up: \\e098;\n$fa-var-plug-circle-minus: \\e55e;\n$fa-var-sign-hanging: \\f4d9;\n$fa-var-sign: \\f4d9;\n$fa-var-bezier-curve: \\f55b;\n$fa-var-bell-slash: \\f1f6;\n$fa-var-tablet: \\f3fb;\n$fa-var-tablet-android: \\f3fb;\n$fa-var-school-flag: \\e56e;\n$fa-var-fill: \\f575;\n$fa-var-angle-up: \\f106;\n$fa-var-drumstick-bite: \\f6d7;\n$fa-var-holly-berry: \\f7aa;\n$fa-var-chevron-left: \\f053;\n$fa-var-bacteria: \\e059;\n$fa-var-hand-lizard: \\f258;\n$fa-var-notdef: \\e1fe;\n$fa-var-disease: \\f7fa;\n$fa-var-briefcase-medical: \\f469;\n$fa-var-genderless: \\f22d;\n$fa-var-chevron-right: \\f054;\n$fa-var-retweet: \\f079;\n$fa-var-car-rear: \\f5de;\n$fa-var-car-alt: \\f5de;\n$fa-var-pump-soap: \\e06b;\n$fa-var-video-slash: \\f4e2;\n$fa-var-battery-quarter: \\f243;\n$fa-var-battery-2: \\f243;\n$fa-var-radio: \\f8d7;\n$fa-var-baby-carriage: \\f77d;\n$fa-var-carriage-baby: \\f77d;\n$fa-var-traffic-light: \\f637;\n$fa-var-thermometer: \\f491;\n$fa-var-vr-cardboard: \\f729;\n$fa-var-hand-middle-finger: \\f806;\n$fa-var-percent: \\25;\n$fa-var-percentage: \\25;\n$fa-var-truck-moving: \\f4df;\n$fa-var-glass-water-droplet: \\e4f5;\n$fa-var-display: \\e163;\n$fa-var-face-smile: \\f118;\n$fa-var-smile: \\f118;\n$fa-var-thumbtack: \\f08d;\n$fa-var-thumb-tack: \\f08d;\n$fa-var-trophy: \\f091;\n$fa-var-person-praying: \\f683;\n$fa-var-pray: \\f683;\n$fa-var-hammer: \\f6e3;\n$fa-var-hand-peace: \\f25b;\n$fa-var-rotate: \\f2f1;\n$fa-var-sync-alt: \\f2f1;\n$fa-var-spinner: \\f110;\n$fa-var-robot: \\f544;\n$fa-var-peace: \\f67c;\n$fa-var-gears: \\f085;\n$fa-var-cogs: \\f085;\n$fa-var-warehouse: \\f494;\n$fa-var-arrow-up-right-dots: \\e4b7;\n$fa-var-splotch: \\f5bc;\n$fa-var-face-grin-hearts: \\f584;\n$fa-var-grin-hearts: \\f584;\n$fa-var-dice-four: \\f524;\n$fa-var-sim-card: \\f7c4;\n$fa-var-transgender: \\f225;\n$fa-var-transgender-alt: \\f225;\n$fa-var-mercury: \\f223;\n$fa-var-arrow-turn-down: \\f149;\n$fa-var-level-down: \\f149;\n$fa-var-person-falling-burst: \\e547;\n$fa-var-award: \\f559;\n$fa-var-ticket-simple: \\f3ff;\n$fa-var-ticket-alt: \\f3ff;\n$fa-var-building: \\f1ad;\n$fa-var-angles-left: \\f100;\n$fa-var-angle-double-left: \\f100;\n$fa-var-qrcode: \\f029;\n$fa-var-clock-rotate-left: \\f1da;\n$fa-var-history: \\f1da;\n$fa-var-face-grin-beam-sweat: \\f583;\n$fa-var-grin-beam-sweat: \\f583;\n$fa-var-file-export: \\f56e;\n$fa-var-arrow-right-from-file: \\f56e;\n$fa-var-shield: \\f132;\n$fa-var-shield-blank: \\f132;\n$fa-var-arrow-up-short-wide: \\f885;\n$fa-var-sort-amount-up-alt: \\f885;\n$fa-var-comment-nodes: \\e696;\n$fa-var-house-medical: \\e3b2;\n$fa-var-golf-ball-tee: \\f450;\n$fa-var-golf-ball: \\f450;\n$fa-var-circle-chevron-left: \\f137;\n$fa-var-chevron-circle-left: \\f137;\n$fa-var-house-chimney-window: \\e00d;\n$fa-var-pen-nib: \\f5ad;\n$fa-var-tent-arrow-turn-left: \\e580;\n$fa-var-tents: \\e582;\n$fa-var-wand-magic: \\f0d0;\n$fa-var-magic: \\f0d0;\n$fa-var-dog: \\f6d3;\n$fa-var-carrot: \\f787;\n$fa-var-moon: \\f186;\n$fa-var-wine-glass-empty: \\f5ce;\n$fa-var-wine-glass-alt: \\f5ce;\n$fa-var-cheese: \\f7ef;\n$fa-var-yin-yang: \\f6ad;\n$fa-var-music: \\f001;\n$fa-var-code-commit: \\f386;\n$fa-var-temperature-low: \\f76b;\n$fa-var-person-biking: \\f84a;\n$fa-var-biking: \\f84a;\n$fa-var-broom: \\f51a;\n$fa-var-shield-heart: \\e574;\n$fa-var-gopuram: \\f664;\n$fa-var-earth-oceania: \\e47b;\n$fa-var-globe-oceania: \\e47b;\n$fa-var-square-xmark: \\f2d3;\n$fa-var-times-square: \\f2d3;\n$fa-var-xmark-square: \\f2d3;\n$fa-var-hashtag: \\23;\n$fa-var-up-right-and-down-left-from-center: \\f424;\n$fa-var-expand-alt: \\f424;\n$fa-var-oil-can: \\f613;\n$fa-var-t: \\54;\n$fa-var-hippo: \\f6ed;\n$fa-var-chart-column: \\e0e3;\n$fa-var-infinity: \\f534;\n$fa-var-vial-circle-check: \\e596;\n$fa-var-person-arrow-down-to-line: \\e538;\n$fa-var-voicemail: \\f897;\n$fa-var-fan: \\f863;\n$fa-var-person-walking-luggage: \\e554;\n$fa-var-up-down: \\f338;\n$fa-var-arrows-alt-v: \\f338;\n$fa-var-cloud-moon-rain: \\f73c;\n$fa-var-calendar: \\f133;\n$fa-var-trailer: \\e041;\n$fa-var-bahai: \\f666;\n$fa-var-haykal: \\f666;\n$fa-var-sd-card: \\f7c2;\n$fa-var-dragon: \\f6d5;\n$fa-var-shoe-prints: \\f54b;\n$fa-var-circle-plus: \\f055;\n$fa-var-plus-circle: \\f055;\n$fa-var-face-grin-tongue-wink: \\f58b;\n$fa-var-grin-tongue-wink: \\f58b;\n$fa-var-hand-holding: \\f4bd;\n$fa-var-plug-circle-exclamation: \\e55d;\n$fa-var-link-slash: \\f127;\n$fa-var-chain-broken: \\f127;\n$fa-var-chain-slash: \\f127;\n$fa-var-unlink: \\f127;\n$fa-var-clone: \\f24d;\n$fa-var-person-walking-arrow-loop-left: \\e551;\n$fa-var-arrow-up-z-a: \\f882;\n$fa-var-sort-alpha-up-alt: \\f882;\n$fa-var-fire-flame-curved: \\f7e4;\n$fa-var-fire-alt: \\f7e4;\n$fa-var-tornado: \\f76f;\n$fa-var-file-circle-plus: \\e494;\n$fa-var-book-quran: \\f687;\n$fa-var-quran: \\f687;\n$fa-var-anchor: \\f13d;\n$fa-var-border-all: \\f84c;\n$fa-var-face-angry: \\f556;\n$fa-var-angry: \\f556;\n$fa-var-cookie-bite: \\f564;\n$fa-var-arrow-trend-down: \\e097;\n$fa-var-rss: \\f09e;\n$fa-var-feed: \\f09e;\n$fa-var-draw-polygon: \\f5ee;\n$fa-var-scale-balanced: \\f24e;\n$fa-var-balance-scale: \\f24e;\n$fa-var-gauge-simple-high: \\f62a;\n$fa-var-tachometer: \\f62a;\n$fa-var-tachometer-fast: \\f62a;\n$fa-var-shower: \\f2cc;\n$fa-var-desktop: \\f390;\n$fa-var-desktop-alt: \\f390;\n$fa-var-m: \\4d;\n$fa-var-table-list: \\f00b;\n$fa-var-th-list: \\f00b;\n$fa-var-comment-sms: \\f7cd;\n$fa-var-sms: \\f7cd;\n$fa-var-book: \\f02d;\n$fa-var-user-plus: \\f234;\n$fa-var-check: \\f00c;\n$fa-var-battery-three-quarters: \\f241;\n$fa-var-battery-4: \\f241;\n$fa-var-house-circle-check: \\e509;\n$fa-var-angle-left: \\f104;\n$fa-var-diagram-successor: \\e47a;\n$fa-var-truck-arrow-right: \\e58b;\n$fa-var-arrows-split-up-and-left: \\e4bc;\n$fa-var-hand-fist: \\f6de;\n$fa-var-fist-raised: \\f6de;\n$fa-var-cloud-moon: \\f6c3;\n$fa-var-briefcase: \\f0b1;\n$fa-var-person-falling: \\e546;\n$fa-var-image-portrait: \\f3e0;\n$fa-var-portrait: \\f3e0;\n$fa-var-user-tag: \\f507;\n$fa-var-rug: \\e569;\n$fa-var-earth-europe: \\f7a2;\n$fa-var-globe-europe: \\f7a2;\n$fa-var-cart-flatbed-suitcase: \\f59d;\n$fa-var-luggage-cart: \\f59d;\n$fa-var-rectangle-xmark: \\f410;\n$fa-var-rectangle-times: \\f410;\n$fa-var-times-rectangle: \\f410;\n$fa-var-window-close: \\f410;\n$fa-var-baht-sign: \\e0ac;\n$fa-var-book-open: \\f518;\n$fa-var-book-journal-whills: \\f66a;\n$fa-var-journal-whills: \\f66a;\n$fa-var-handcuffs: \\e4f8;\n$fa-var-triangle-exclamation: \\f071;\n$fa-var-exclamation-triangle: \\f071;\n$fa-var-warning: \\f071;\n$fa-var-database: \\f1c0;\n$fa-var-share: \\f064;\n$fa-var-mail-forward: \\f064;\n$fa-var-bottle-droplet: \\e4c4;\n$fa-var-mask-face: \\e1d7;\n$fa-var-hill-rockslide: \\e508;\n$fa-var-right-left: \\f362;\n$fa-var-exchange-alt: \\f362;\n$fa-var-paper-plane: \\f1d8;\n$fa-var-road-circle-exclamation: \\e565;\n$fa-var-dungeon: \\f6d9;\n$fa-var-align-right: \\f038;\n$fa-var-money-bill-1-wave: \\f53b;\n$fa-var-money-bill-wave-alt: \\f53b;\n$fa-var-life-ring: \\f1cd;\n$fa-var-hands: \\f2a7;\n$fa-var-sign-language: \\f2a7;\n$fa-var-signing: \\f2a7;\n$fa-var-calendar-day: \\f783;\n$fa-var-water-ladder: \\f5c5;\n$fa-var-ladder-water: \\f5c5;\n$fa-var-swimming-pool: \\f5c5;\n$fa-var-arrows-up-down: \\f07d;\n$fa-var-arrows-v: \\f07d;\n$fa-var-face-grimace: \\f57f;\n$fa-var-grimace: \\f57f;\n$fa-var-wheelchair-move: \\e2ce;\n$fa-var-wheelchair-alt: \\e2ce;\n$fa-var-turn-down: \\f3be;\n$fa-var-level-down-alt: \\f3be;\n$fa-var-person-walking-arrow-right: \\e552;\n$fa-var-square-envelope: \\f199;\n$fa-var-envelope-square: \\f199;\n$fa-var-dice: \\f522;\n$fa-var-bowling-ball: \\f436;\n$fa-var-brain: \\f5dc;\n$fa-var-bandage: \\f462;\n$fa-var-band-aid: \\f462;\n$fa-var-calendar-minus: \\f272;\n$fa-var-circle-xmark: \\f057;\n$fa-var-times-circle: \\f057;\n$fa-var-xmark-circle: \\f057;\n$fa-var-gifts: \\f79c;\n$fa-var-hotel: \\f594;\n$fa-var-earth-asia: \\f57e;\n$fa-var-globe-asia: \\f57e;\n$fa-var-id-card-clip: \\f47f;\n$fa-var-id-card-alt: \\f47f;\n$fa-var-magnifying-glass-plus: \\f00e;\n$fa-var-search-plus: \\f00e;\n$fa-var-thumbs-up: \\f164;\n$fa-var-user-clock: \\f4fd;\n$fa-var-hand-dots: \\f461;\n$fa-var-allergies: \\f461;\n$fa-var-file-invoice: \\f570;\n$fa-var-window-minimize: \\f2d1;\n$fa-var-mug-saucer: \\f0f4;\n$fa-var-coffee: \\f0f4;\n$fa-var-brush: \\f55d;\n$fa-var-file-half-dashed: \\e698;\n$fa-var-mask: \\f6fa;\n$fa-var-magnifying-glass-minus: \\f010;\n$fa-var-search-minus: \\f010;\n$fa-var-ruler-vertical: \\f548;\n$fa-var-user-large: \\f406;\n$fa-var-user-alt: \\f406;\n$fa-var-train-tram: \\e5b4;\n$fa-var-user-nurse: \\f82f;\n$fa-var-syringe: \\f48e;\n$fa-var-cloud-sun: \\f6c4;\n$fa-var-stopwatch-20: \\e06f;\n$fa-var-square-full: \\f45c;\n$fa-var-magnet: \\f076;\n$fa-var-jar: \\e516;\n$fa-var-note-sticky: \\f249;\n$fa-var-sticky-note: \\f249;\n$fa-var-bug-slash: \\e490;\n$fa-var-arrow-up-from-water-pump: \\e4b6;\n$fa-var-bone: \\f5d7;\n$fa-var-table-cells-row-unlock: \\e691;\n$fa-var-user-injured: \\f728;\n$fa-var-face-sad-tear: \\f5b4;\n$fa-var-sad-tear: \\f5b4;\n$fa-var-plane: \\f072;\n$fa-var-tent-arrows-down: \\e581;\n$fa-var-exclamation: \\21;\n$fa-var-arrows-spin: \\e4bb;\n$fa-var-print: \\f02f;\n$fa-var-turkish-lira-sign: \\e2bb;\n$fa-var-try: \\e2bb;\n$fa-var-turkish-lira: \\e2bb;\n$fa-var-dollar-sign: \\24;\n$fa-var-dollar: \\24;\n$fa-var-usd: \\24;\n$fa-var-x: \\58;\n$fa-var-magnifying-glass-dollar: \\f688;\n$fa-var-search-dollar: \\f688;\n$fa-var-users-gear: \\f509;\n$fa-var-users-cog: \\f509;\n$fa-var-person-military-pointing: \\e54a;\n$fa-var-building-columns: \\f19c;\n$fa-var-bank: \\f19c;\n$fa-var-institution: \\f19c;\n$fa-var-museum: \\f19c;\n$fa-var-university: \\f19c;\n$fa-var-umbrella: \\f0e9;\n$fa-var-trowel: \\e589;\n$fa-var-d: \\44;\n$fa-var-stapler: \\e5af;\n$fa-var-masks-theater: \\f630;\n$fa-var-theater-masks: \\f630;\n$fa-var-kip-sign: \\e1c4;\n$fa-var-hand-point-left: \\f0a5;\n$fa-var-handshake-simple: \\f4c6;\n$fa-var-handshake-alt: \\f4c6;\n$fa-var-jet-fighter: \\f0fb;\n$fa-var-fighter-jet: \\f0fb;\n$fa-var-square-share-nodes: \\f1e1;\n$fa-var-share-alt-square: \\f1e1;\n$fa-var-barcode: \\f02a;\n$fa-var-plus-minus: \\e43c;\n$fa-var-video: \\f03d;\n$fa-var-video-camera: \\f03d;\n$fa-var-graduation-cap: \\f19d;\n$fa-var-mortar-board: \\f19d;\n$fa-var-hand-holding-medical: \\e05c;\n$fa-var-person-circle-check: \\e53e;\n$fa-var-turn-up: \\f3bf;\n$fa-var-level-up-alt: \\f3bf;\n\n$fa-var-monero: \\f3d0;\n$fa-var-hooli: \\f427;\n$fa-var-yelp: \\f1e9;\n$fa-var-cc-visa: \\f1f0;\n$fa-var-lastfm: \\f202;\n$fa-var-shopware: \\f5b5;\n$fa-var-creative-commons-nc: \\f4e8;\n$fa-var-aws: \\f375;\n$fa-var-redhat: \\f7bc;\n$fa-var-yoast: \\f2b1;\n$fa-var-cloudflare: \\e07d;\n$fa-var-ups: \\f7e0;\n$fa-var-pixiv: \\e640;\n$fa-var-wpexplorer: \\f2de;\n$fa-var-dyalog: \\f399;\n$fa-var-bity: \\f37a;\n$fa-var-stackpath: \\f842;\n$fa-var-buysellads: \\f20d;\n$fa-var-first-order: \\f2b0;\n$fa-var-modx: \\f285;\n$fa-var-guilded: \\e07e;\n$fa-var-vnv: \\f40b;\n$fa-var-square-js: \\f3b9;\n$fa-var-js-square: \\f3b9;\n$fa-var-microsoft: \\f3ca;\n$fa-var-qq: \\f1d6;\n$fa-var-orcid: \\f8d2;\n$fa-var-java: \\f4e4;\n$fa-var-invision: \\f7b0;\n$fa-var-creative-commons-pd-alt: \\f4ed;\n$fa-var-centercode: \\f380;\n$fa-var-glide-g: \\f2a6;\n$fa-var-drupal: \\f1a9;\n$fa-var-jxl: \\e67b;\n$fa-var-dart-lang: \\e693;\n$fa-var-hire-a-helper: \\f3b0;\n$fa-var-creative-commons-by: \\f4e7;\n$fa-var-unity: \\e049;\n$fa-var-whmcs: \\f40d;\n$fa-var-rocketchat: \\f3e8;\n$fa-var-vk: \\f189;\n$fa-var-untappd: \\f405;\n$fa-var-mailchimp: \\f59e;\n$fa-var-css3-alt: \\f38b;\n$fa-var-square-reddit: \\f1a2;\n$fa-var-reddit-square: \\f1a2;\n$fa-var-vimeo-v: \\f27d;\n$fa-var-contao: \\f26d;\n$fa-var-square-font-awesome: \\e5ad;\n$fa-var-deskpro: \\f38f;\n$fa-var-brave: \\e63c;\n$fa-var-sistrix: \\f3ee;\n$fa-var-square-instagram: \\e055;\n$fa-var-instagram-square: \\e055;\n$fa-var-battle-net: \\f835;\n$fa-var-the-red-yeti: \\f69d;\n$fa-var-square-hacker-news: \\f3af;\n$fa-var-hacker-news-square: \\f3af;\n$fa-var-edge: \\f282;\n$fa-var-threads: \\e618;\n$fa-var-napster: \\f3d2;\n$fa-var-square-snapchat: \\f2ad;\n$fa-var-snapchat-square: \\f2ad;\n$fa-var-google-plus-g: \\f0d5;\n$fa-var-artstation: \\f77a;\n$fa-var-markdown: \\f60f;\n$fa-var-sourcetree: \\f7d3;\n$fa-var-google-plus: \\f2b3;\n$fa-var-diaspora: \\f791;\n$fa-var-foursquare: \\f180;\n$fa-var-stack-overflow: \\f16c;\n$fa-var-github-alt: \\f113;\n$fa-var-phoenix-squadron: \\f511;\n$fa-var-pagelines: \\f18c;\n$fa-var-algolia: \\f36c;\n$fa-var-red-river: \\f3e3;\n$fa-var-creative-commons-sa: \\f4ef;\n$fa-var-safari: \\f267;\n$fa-var-google: \\f1a0;\n$fa-var-square-font-awesome-stroke: \\f35c;\n$fa-var-font-awesome-alt: \\f35c;\n$fa-var-atlassian: \\f77b;\n$fa-var-linkedin-in: \\f0e1;\n$fa-var-digital-ocean: \\f391;\n$fa-var-nimblr: \\f5a8;\n$fa-var-chromecast: \\f838;\n$fa-var-evernote: \\f839;\n$fa-var-hacker-news: \\f1d4;\n$fa-var-creative-commons-sampling: \\f4f0;\n$fa-var-adversal: \\f36a;\n$fa-var-creative-commons: \\f25e;\n$fa-var-watchman-monitoring: \\e087;\n$fa-var-fonticons: \\f280;\n$fa-var-weixin: \\f1d7;\n$fa-var-shirtsinbulk: \\f214;\n$fa-var-codepen: \\f1cb;\n$fa-var-git-alt: \\f841;\n$fa-var-lyft: \\f3c3;\n$fa-var-rev: \\f5b2;\n$fa-var-windows: \\f17a;\n$fa-var-wizards-of-the-coast: \\f730;\n$fa-var-square-viadeo: \\f2aa;\n$fa-var-viadeo-square: \\f2aa;\n$fa-var-meetup: \\f2e0;\n$fa-var-centos: \\f789;\n$fa-var-adn: \\f170;\n$fa-var-cloudsmith: \\f384;\n$fa-var-opensuse: \\e62b;\n$fa-var-pied-piper-alt: \\f1a8;\n$fa-var-square-dribbble: \\f397;\n$fa-var-dribbble-square: \\f397;\n$fa-var-codiepie: \\f284;\n$fa-var-node: \\f419;\n$fa-var-mix: \\f3cb;\n$fa-var-steam: \\f1b6;\n$fa-var-cc-apple-pay: \\f416;\n$fa-var-scribd: \\f28a;\n$fa-var-debian: \\e60b;\n$fa-var-openid: \\f19b;\n$fa-var-instalod: \\e081;\n$fa-var-files-pinwheel: \\e69f;\n$fa-var-expeditedssl: \\f23e;\n$fa-var-sellcast: \\f2da;\n$fa-var-square-twitter: \\f081;\n$fa-var-twitter-square: \\f081;\n$fa-var-r-project: \\f4f7;\n$fa-var-delicious: \\f1a5;\n$fa-var-freebsd: \\f3a4;\n$fa-var-vuejs: \\f41f;\n$fa-var-accusoft: \\f369;\n$fa-var-ioxhost: \\f208;\n$fa-var-fonticons-fi: \\f3a2;\n$fa-var-app-store: \\f36f;\n$fa-var-cc-mastercard: \\f1f1;\n$fa-var-itunes-note: \\f3b5;\n$fa-var-golang: \\e40f;\n$fa-var-kickstarter: \\f3bb;\n$fa-var-square-kickstarter: \\f3bb;\n$fa-var-grav: \\f2d6;\n$fa-var-weibo: \\f18a;\n$fa-var-uncharted: \\e084;\n$fa-var-firstdraft: \\f3a1;\n$fa-var-square-youtube: \\f431;\n$fa-var-youtube-square: \\f431;\n$fa-var-wikipedia-w: \\f266;\n$fa-var-wpressr: \\f3e4;\n$fa-var-rendact: \\f3e4;\n$fa-var-angellist: \\f209;\n$fa-var-galactic-republic: \\f50c;\n$fa-var-nfc-directional: \\e530;\n$fa-var-skype: \\f17e;\n$fa-var-joget: \\f3b7;\n$fa-var-fedora: \\f798;\n$fa-var-stripe-s: \\f42a;\n$fa-var-meta: \\e49b;\n$fa-var-laravel: \\f3bd;\n$fa-var-hotjar: \\f3b1;\n$fa-var-bluetooth-b: \\f294;\n$fa-var-square-letterboxd: \\e62e;\n$fa-var-sticker-mule: \\f3f7;\n$fa-var-creative-commons-zero: \\f4f3;\n$fa-var-hips: \\f452;\n$fa-var-css: \\e6a2;\n$fa-var-behance: \\f1b4;\n$fa-var-reddit: \\f1a1;\n$fa-var-discord: \\f392;\n$fa-var-chrome: \\f268;\n$fa-var-app-store-ios: \\f370;\n$fa-var-cc-discover: \\f1f2;\n$fa-var-wpbeginner: \\f297;\n$fa-var-confluence: \\f78d;\n$fa-var-shoelace: \\e60c;\n$fa-var-mdb: \\f8ca;\n$fa-var-dochub: \\f394;\n$fa-var-accessible-icon: \\f368;\n$fa-var-ebay: \\f4f4;\n$fa-var-amazon: \\f270;\n$fa-var-unsplash: \\e07c;\n$fa-var-yarn: \\f7e3;\n$fa-var-square-steam: \\f1b7;\n$fa-var-steam-square: \\f1b7;\n$fa-var-500px: \\f26e;\n$fa-var-square-vimeo: \\f194;\n$fa-var-vimeo-square: \\f194;\n$fa-var-asymmetrik: \\f372;\n$fa-var-font-awesome: \\f2b4;\n$fa-var-font-awesome-flag: \\f2b4;\n$fa-var-font-awesome-logo-full: \\f2b4;\n$fa-var-gratipay: \\f184;\n$fa-var-apple: \\f179;\n$fa-var-hive: \\e07f;\n$fa-var-gitkraken: \\f3a6;\n$fa-var-keybase: \\f4f5;\n$fa-var-apple-pay: \\f415;\n$fa-var-padlet: \\e4a0;\n$fa-var-amazon-pay: \\f42c;\n$fa-var-square-github: \\f092;\n$fa-var-github-square: \\f092;\n$fa-var-stumbleupon: \\f1a4;\n$fa-var-fedex: \\f797;\n$fa-var-phoenix-framework: \\f3dc;\n$fa-var-shopify: \\e057;\n$fa-var-neos: \\f612;\n$fa-var-square-threads: \\e619;\n$fa-var-hackerrank: \\f5f7;\n$fa-var-researchgate: \\f4f8;\n$fa-var-swift: \\f8e1;\n$fa-var-angular: \\f420;\n$fa-var-speakap: \\f3f3;\n$fa-var-angrycreative: \\f36e;\n$fa-var-y-combinator: \\f23b;\n$fa-var-empire: \\f1d1;\n$fa-var-envira: \\f299;\n$fa-var-google-scholar: \\e63b;\n$fa-var-square-gitlab: \\e5ae;\n$fa-var-gitlab-square: \\e5ae;\n$fa-var-studiovinari: \\f3f8;\n$fa-var-pied-piper: \\f2ae;\n$fa-var-wordpress: \\f19a;\n$fa-var-product-hunt: \\f288;\n$fa-var-firefox: \\f269;\n$fa-var-linode: \\f2b8;\n$fa-var-goodreads: \\f3a8;\n$fa-var-square-odnoklassniki: \\f264;\n$fa-var-odnoklassniki-square: \\f264;\n$fa-var-jsfiddle: \\f1cc;\n$fa-var-sith: \\f512;\n$fa-var-themeisle: \\f2b2;\n$fa-var-page4: \\f3d7;\n$fa-var-hashnode: \\e499;\n$fa-var-react: \\f41b;\n$fa-var-cc-paypal: \\f1f4;\n$fa-var-squarespace: \\f5be;\n$fa-var-cc-stripe: \\f1f5;\n$fa-var-creative-commons-share: \\f4f2;\n$fa-var-bitcoin: \\f379;\n$fa-var-keycdn: \\f3ba;\n$fa-var-opera: \\f26a;\n$fa-var-itch-io: \\f83a;\n$fa-var-umbraco: \\f8e8;\n$fa-var-galactic-senate: \\f50d;\n$fa-var-ubuntu: \\f7df;\n$fa-var-draft2digital: \\f396;\n$fa-var-stripe: \\f429;\n$fa-var-houzz: \\f27c;\n$fa-var-gg: \\f260;\n$fa-var-dhl: \\f790;\n$fa-var-square-pinterest: \\f0d3;\n$fa-var-pinterest-square: \\f0d3;\n$fa-var-xing: \\f168;\n$fa-var-blackberry: \\f37b;\n$fa-var-creative-commons-pd: \\f4ec;\n$fa-var-playstation: \\f3df;\n$fa-var-quinscape: \\f459;\n$fa-var-less: \\f41d;\n$fa-var-blogger-b: \\f37d;\n$fa-var-opencart: \\f23d;\n$fa-var-vine: \\f1ca;\n$fa-var-signal-messenger: \\e663;\n$fa-var-paypal: \\f1ed;\n$fa-var-gitlab: \\f296;\n$fa-var-typo3: \\f42b;\n$fa-var-reddit-alien: \\f281;\n$fa-var-yahoo: \\f19e;\n$fa-var-dailymotion: \\e052;\n$fa-var-affiliatetheme: \\f36b;\n$fa-var-pied-piper-pp: \\f1a7;\n$fa-var-bootstrap: \\f836;\n$fa-var-odnoklassniki: \\f263;\n$fa-var-nfc-symbol: \\e531;\n$fa-var-mintbit: \\e62f;\n$fa-var-ethereum: \\f42e;\n$fa-var-speaker-deck: \\f83c;\n$fa-var-creative-commons-nc-eu: \\f4e9;\n$fa-var-patreon: \\f3d9;\n$fa-var-avianex: \\f374;\n$fa-var-ello: \\f5f1;\n$fa-var-gofore: \\f3a7;\n$fa-var-bimobject: \\f378;\n$fa-var-brave-reverse: \\e63d;\n$fa-var-facebook-f: \\f39e;\n$fa-var-square-google-plus: \\f0d4;\n$fa-var-google-plus-square: \\f0d4;\n$fa-var-web-awesome: \\e682;\n$fa-var-mandalorian: \\f50f;\n$fa-var-first-order-alt: \\f50a;\n$fa-var-osi: \\f41a;\n$fa-var-google-wallet: \\f1ee;\n$fa-var-d-and-d-beyond: \\f6ca;\n$fa-var-periscope: \\f3da;\n$fa-var-fulcrum: \\f50b;\n$fa-var-cloudscale: \\f383;\n$fa-var-forumbee: \\f211;\n$fa-var-mizuni: \\f3cc;\n$fa-var-schlix: \\f3ea;\n$fa-var-square-xing: \\f169;\n$fa-var-xing-square: \\f169;\n$fa-var-bandcamp: \\f2d5;\n$fa-var-wpforms: \\f298;\n$fa-var-cloudversify: \\f385;\n$fa-var-usps: \\f7e1;\n$fa-var-megaport: \\f5a3;\n$fa-var-magento: \\f3c4;\n$fa-var-spotify: \\f1bc;\n$fa-var-optin-monster: \\f23c;\n$fa-var-fly: \\f417;\n$fa-var-square-bluesky: \\e6a3;\n$fa-var-aviato: \\f421;\n$fa-var-itunes: \\f3b4;\n$fa-var-cuttlefish: \\f38c;\n$fa-var-blogger: \\f37c;\n$fa-var-flickr: \\f16e;\n$fa-var-viber: \\f409;\n$fa-var-soundcloud: \\f1be;\n$fa-var-digg: \\f1a6;\n$fa-var-tencent-weibo: \\f1d5;\n$fa-var-letterboxd: \\e62d;\n$fa-var-symfony: \\f83d;\n$fa-var-maxcdn: \\f136;\n$fa-var-etsy: \\f2d7;\n$fa-var-facebook-messenger: \\f39f;\n$fa-var-audible: \\f373;\n$fa-var-think-peaks: \\f731;\n$fa-var-bilibili: \\e3d9;\n$fa-var-erlang: \\f39d;\n$fa-var-x-twitter: \\e61b;\n$fa-var-cotton-bureau: \\f89e;\n$fa-var-dashcube: \\f210;\n$fa-var-42-group: \\e080;\n$fa-var-innosoft: \\e080;\n$fa-var-stack-exchange: \\f18d;\n$fa-var-elementor: \\f430;\n$fa-var-square-pied-piper: \\e01e;\n$fa-var-pied-piper-square: \\e01e;\n$fa-var-creative-commons-nd: \\f4eb;\n$fa-var-palfed: \\f3d8;\n$fa-var-superpowers: \\f2dd;\n$fa-var-resolving: \\f3e7;\n$fa-var-xbox: \\f412;\n$fa-var-square-web-awesome-stroke: \\e684;\n$fa-var-searchengin: \\f3eb;\n$fa-var-tiktok: \\e07b;\n$fa-var-square-facebook: \\f082;\n$fa-var-facebook-square: \\f082;\n$fa-var-renren: \\f18b;\n$fa-var-linux: \\f17c;\n$fa-var-glide: \\f2a5;\n$fa-var-linkedin: \\f08c;\n$fa-var-hubspot: \\f3b2;\n$fa-var-deploydog: \\f38e;\n$fa-var-twitch: \\f1e8;\n$fa-var-flutter: \\e694;\n$fa-var-ravelry: \\f2d9;\n$fa-var-mixer: \\e056;\n$fa-var-square-lastfm: \\f203;\n$fa-var-lastfm-square: \\f203;\n$fa-var-vimeo: \\f40a;\n$fa-var-mendeley: \\f7b3;\n$fa-var-uniregistry: \\f404;\n$fa-var-figma: \\f799;\n$fa-var-creative-commons-remix: \\f4ee;\n$fa-var-cc-amazon-pay: \\f42d;\n$fa-var-dropbox: \\f16b;\n$fa-var-instagram: \\f16d;\n$fa-var-cmplid: \\e360;\n$fa-var-upwork: \\e641;\n$fa-var-facebook: \\f09a;\n$fa-var-gripfire: \\f3ac;\n$fa-var-jedi-order: \\f50e;\n$fa-var-uikit: \\f403;\n$fa-var-fort-awesome-alt: \\f3a3;\n$fa-var-phabricator: \\f3db;\n$fa-var-ussunnah: \\f407;\n$fa-var-earlybirds: \\f39a;\n$fa-var-trade-federation: \\f513;\n$fa-var-autoprefixer: \\f41c;\n$fa-var-whatsapp: \\f232;\n$fa-var-square-upwork: \\e67c;\n$fa-var-slideshare: \\f1e7;\n$fa-var-google-play: \\f3ab;\n$fa-var-viadeo: \\f2a9;\n$fa-var-line: \\f3c0;\n$fa-var-google-drive: \\f3aa;\n$fa-var-servicestack: \\f3ec;\n$fa-var-simplybuilt: \\f215;\n$fa-var-bitbucket: \\f171;\n$fa-var-imdb: \\f2d8;\n$fa-var-deezer: \\e077;\n$fa-var-raspberry-pi: \\f7bb;\n$fa-var-jira: \\f7b1;\n$fa-var-docker: \\f395;\n$fa-var-screenpal: \\e570;\n$fa-var-bluetooth: \\f293;\n$fa-var-gitter: \\f426;\n$fa-var-d-and-d: \\f38d;\n$fa-var-microblog: \\e01a;\n$fa-var-cc-diners-club: \\f24c;\n$fa-var-gg-circle: \\f261;\n$fa-var-pied-piper-hat: \\f4e5;\n$fa-var-kickstarter-k: \\f3bc;\n$fa-var-yandex: \\f413;\n$fa-var-readme: \\f4d5;\n$fa-var-html5: \\f13b;\n$fa-var-sellsy: \\f213;\n$fa-var-square-web-awesome: \\e683;\n$fa-var-sass: \\f41e;\n$fa-var-wirsindhandwerk: \\e2d0;\n$fa-var-wsh: \\e2d0;\n$fa-var-buromobelexperte: \\f37f;\n$fa-var-salesforce: \\f83b;\n$fa-var-octopus-deploy: \\e082;\n$fa-var-medapps: \\f3c6;\n$fa-var-ns8: \\f3d5;\n$fa-var-pinterest-p: \\f231;\n$fa-var-apper: \\f371;\n$fa-var-fort-awesome: \\f286;\n$fa-var-waze: \\f83f;\n$fa-var-bluesky: \\e671;\n$fa-var-cc-jcb: \\f24b;\n$fa-var-snapchat: \\f2ab;\n$fa-var-snapchat-ghost: \\f2ab;\n$fa-var-fantasy-flight-games: \\f6dc;\n$fa-var-rust: \\e07a;\n$fa-var-wix: \\f5cf;\n$fa-var-square-behance: \\f1b5;\n$fa-var-behance-square: \\f1b5;\n$fa-var-supple: \\f3f9;\n$fa-var-webflow: \\e65c;\n$fa-var-rebel: \\f1d0;\n$fa-var-css3: \\f13c;\n$fa-var-staylinked: \\f3f5;\n$fa-var-kaggle: \\f5fa;\n$fa-var-space-awesome: \\e5ac;\n$fa-var-deviantart: \\f1bd;\n$fa-var-cpanel: \\f388;\n$fa-var-goodreads-g: \\f3a9;\n$fa-var-square-git: \\f1d2;\n$fa-var-git-square: \\f1d2;\n$fa-var-square-tumblr: \\f174;\n$fa-var-tumblr-square: \\f174;\n$fa-var-trello: \\f181;\n$fa-var-creative-commons-nc-jp: \\f4ea;\n$fa-var-get-pocket: \\f265;\n$fa-var-perbyte: \\e083;\n$fa-var-grunt: \\f3ad;\n$fa-var-weebly: \\f5cc;\n$fa-var-connectdevelop: \\f20e;\n$fa-var-leanpub: \\f212;\n$fa-var-black-tie: \\f27e;\n$fa-var-themeco: \\f5c6;\n$fa-var-python: \\f3e2;\n$fa-var-android: \\f17b;\n$fa-var-bots: \\e340;\n$fa-var-free-code-camp: \\f2c5;\n$fa-var-hornbill: \\f592;\n$fa-var-js: \\f3b8;\n$fa-var-ideal: \\e013;\n$fa-var-git: \\f1d3;\n$fa-var-dev: \\f6cc;\n$fa-var-sketch: \\f7c6;\n$fa-var-yandex-international: \\f414;\n$fa-var-cc-amex: \\f1f3;\n$fa-var-uber: \\f402;\n$fa-var-github: \\f09b;\n$fa-var-php: \\f457;\n$fa-var-alipay: \\f642;\n$fa-var-youtube: \\f167;\n$fa-var-skyatlas: \\f216;\n$fa-var-firefox-browser: \\e007;\n$fa-var-replyd: \\f3e6;\n$fa-var-suse: \\f7d6;\n$fa-var-jenkins: \\f3b6;\n$fa-var-twitter: \\f099;\n$fa-var-rockrms: \\f3e9;\n$fa-var-pinterest: \\f0d2;\n$fa-var-buffer: \\f837;\n$fa-var-npm: \\f3d4;\n$fa-var-yammer: \\f840;\n$fa-var-btc: \\f15a;\n$fa-var-dribbble: \\f17d;\n$fa-var-stumbleupon-circle: \\f1a3;\n$fa-var-internet-explorer: \\f26b;\n$fa-var-stubber: \\e5c7;\n$fa-var-telegram: \\f2c6;\n$fa-var-telegram-plane: \\f2c6;\n$fa-var-old-republic: \\f510;\n$fa-var-odysee: \\e5c6;\n$fa-var-square-whatsapp: \\f40c;\n$fa-var-whatsapp-square: \\f40c;\n$fa-var-node-js: \\f3d3;\n$fa-var-edge-legacy: \\e078;\n$fa-var-slack: \\f198;\n$fa-var-slack-hash: \\f198;\n$fa-var-medrt: \\f3c8;\n$fa-var-usb: \\f287;\n$fa-var-tumblr: \\f173;\n$fa-var-vaadin: \\f408;\n$fa-var-quora: \\f2c4;\n$fa-var-square-x-twitter: \\e61a;\n$fa-var-reacteurope: \\f75d;\n$fa-var-medium: \\f23a;\n$fa-var-medium-m: \\f23a;\n$fa-var-amilia: \\f36d;\n$fa-var-mixcloud: \\f289;\n$fa-var-flipboard: \\f44d;\n$fa-var-viacoin: \\f237;\n$fa-var-critical-role: \\f6c9;\n$fa-var-sitrox: \\e44a;\n$fa-var-discourse: \\f393;\n$fa-var-joomla: \\f1aa;\n$fa-var-mastodon: \\f4f6;\n$fa-var-airbnb: \\f834;\n$fa-var-wolf-pack-battalion: \\f514;\n$fa-var-buy-n-large: \\f8a6;\n$fa-var-gulp: \\f3ae;\n$fa-var-creative-commons-sampling-plus: \\f4f1;\n$fa-var-strava: \\f428;\n$fa-var-ember: \\f423;\n$fa-var-canadian-maple-leaf: \\f785;\n$fa-var-teamspeak: \\f4f9;\n$fa-var-pushed: \\f3e1;\n$fa-var-wordpress-simple: \\f411;\n$fa-var-nutritionix: \\f3d6;\n$fa-var-wodu: \\e088;\n$fa-var-google-pay: \\e079;\n$fa-var-intercom: \\f7af;\n$fa-var-zhihu: \\f63f;\n$fa-var-korvue: \\f42f;\n$fa-var-pix: \\e43a;\n$fa-var-steam-symbol: \\f3f6;\n\n$fa-icons: (\n \"0\": $fa-var-0,\n \"1\": $fa-var-1,\n \"2\": $fa-var-2,\n \"3\": $fa-var-3,\n \"4\": $fa-var-4,\n \"5\": $fa-var-5,\n \"6\": $fa-var-6,\n \"7\": $fa-var-7,\n \"8\": $fa-var-8,\n \"9\": $fa-var-9,\n \"fill-drip\": $fa-var-fill-drip,\n \"arrows-to-circle\": $fa-var-arrows-to-circle,\n \"circle-chevron-right\": $fa-var-circle-chevron-right,\n \"chevron-circle-right\": $fa-var-chevron-circle-right,\n \"at\": $fa-var-at,\n \"trash-can\": $fa-var-trash-can,\n \"trash-alt\": $fa-var-trash-alt,\n \"text-height\": $fa-var-text-height,\n \"user-xmark\": $fa-var-user-xmark,\n \"user-times\": $fa-var-user-times,\n \"stethoscope\": $fa-var-stethoscope,\n \"message\": $fa-var-message,\n \"comment-alt\": $fa-var-comment-alt,\n \"info\": $fa-var-info,\n \"down-left-and-up-right-to-center\": $fa-var-down-left-and-up-right-to-center,\n \"compress-alt\": $fa-var-compress-alt,\n \"explosion\": $fa-var-explosion,\n \"file-lines\": $fa-var-file-lines,\n \"file-alt\": $fa-var-file-alt,\n \"file-text\": $fa-var-file-text,\n \"wave-square\": $fa-var-wave-square,\n \"ring\": $fa-var-ring,\n \"building-un\": $fa-var-building-un,\n \"dice-three\": $fa-var-dice-three,\n \"calendar-days\": $fa-var-calendar-days,\n \"calendar-alt\": $fa-var-calendar-alt,\n \"anchor-circle-check\": $fa-var-anchor-circle-check,\n \"building-circle-arrow-right\": $fa-var-building-circle-arrow-right,\n \"volleyball\": $fa-var-volleyball,\n \"volleyball-ball\": $fa-var-volleyball-ball,\n \"arrows-up-to-line\": $fa-var-arrows-up-to-line,\n \"sort-down\": $fa-var-sort-down,\n \"sort-desc\": $fa-var-sort-desc,\n \"circle-minus\": $fa-var-circle-minus,\n \"minus-circle\": $fa-var-minus-circle,\n \"door-open\": $fa-var-door-open,\n \"right-from-bracket\": $fa-var-right-from-bracket,\n \"sign-out-alt\": $fa-var-sign-out-alt,\n \"atom\": $fa-var-atom,\n \"soap\": $fa-var-soap,\n \"icons\": $fa-var-icons,\n \"heart-music-camera-bolt\": $fa-var-heart-music-camera-bolt,\n \"microphone-lines-slash\": $fa-var-microphone-lines-slash,\n \"microphone-alt-slash\": $fa-var-microphone-alt-slash,\n \"bridge-circle-check\": $fa-var-bridge-circle-check,\n \"pump-medical\": $fa-var-pump-medical,\n \"fingerprint\": $fa-var-fingerprint,\n \"hand-point-right\": $fa-var-hand-point-right,\n \"magnifying-glass-location\": $fa-var-magnifying-glass-location,\n \"search-location\": $fa-var-search-location,\n \"forward-step\": $fa-var-forward-step,\n \"step-forward\": $fa-var-step-forward,\n \"face-smile-beam\": $fa-var-face-smile-beam,\n \"smile-beam\": $fa-var-smile-beam,\n \"flag-checkered\": $fa-var-flag-checkered,\n \"football\": $fa-var-football,\n \"football-ball\": $fa-var-football-ball,\n \"school-circle-exclamation\": $fa-var-school-circle-exclamation,\n \"crop\": $fa-var-crop,\n \"angles-down\": $fa-var-angles-down,\n \"angle-double-down\": $fa-var-angle-double-down,\n \"users-rectangle\": $fa-var-users-rectangle,\n \"people-roof\": $fa-var-people-roof,\n \"people-line\": $fa-var-people-line,\n \"beer-mug-empty\": $fa-var-beer-mug-empty,\n \"beer\": $fa-var-beer,\n \"diagram-predecessor\": $fa-var-diagram-predecessor,\n \"arrow-up-long\": $fa-var-arrow-up-long,\n \"long-arrow-up\": $fa-var-long-arrow-up,\n \"fire-flame-simple\": $fa-var-fire-flame-simple,\n \"burn\": $fa-var-burn,\n \"person\": $fa-var-person,\n \"male\": $fa-var-male,\n \"laptop\": $fa-var-laptop,\n \"file-csv\": $fa-var-file-csv,\n \"menorah\": $fa-var-menorah,\n \"truck-plane\": $fa-var-truck-plane,\n \"record-vinyl\": $fa-var-record-vinyl,\n \"face-grin-stars\": $fa-var-face-grin-stars,\n \"grin-stars\": $fa-var-grin-stars,\n \"bong\": $fa-var-bong,\n \"spaghetti-monster-flying\": $fa-var-spaghetti-monster-flying,\n \"pastafarianism\": $fa-var-pastafarianism,\n \"arrow-down-up-across-line\": $fa-var-arrow-down-up-across-line,\n \"spoon\": $fa-var-spoon,\n \"utensil-spoon\": $fa-var-utensil-spoon,\n \"jar-wheat\": $fa-var-jar-wheat,\n \"envelopes-bulk\": $fa-var-envelopes-bulk,\n \"mail-bulk\": $fa-var-mail-bulk,\n \"file-circle-exclamation\": $fa-var-file-circle-exclamation,\n \"circle-h\": $fa-var-circle-h,\n \"hospital-symbol\": $fa-var-hospital-symbol,\n \"pager\": $fa-var-pager,\n \"address-book\": $fa-var-address-book,\n \"contact-book\": $fa-var-contact-book,\n \"strikethrough\": $fa-var-strikethrough,\n \"k\": $fa-var-k,\n \"landmark-flag\": $fa-var-landmark-flag,\n \"pencil\": $fa-var-pencil,\n \"pencil-alt\": $fa-var-pencil-alt,\n \"backward\": $fa-var-backward,\n \"caret-right\": $fa-var-caret-right,\n \"comments\": $fa-var-comments,\n \"paste\": $fa-var-paste,\n \"file-clipboard\": $fa-var-file-clipboard,\n \"code-pull-request\": $fa-var-code-pull-request,\n \"clipboard-list\": $fa-var-clipboard-list,\n \"truck-ramp-box\": $fa-var-truck-ramp-box,\n \"truck-loading\": $fa-var-truck-loading,\n \"user-check\": $fa-var-user-check,\n \"vial-virus\": $fa-var-vial-virus,\n \"sheet-plastic\": $fa-var-sheet-plastic,\n \"blog\": $fa-var-blog,\n \"user-ninja\": $fa-var-user-ninja,\n \"person-arrow-up-from-line\": $fa-var-person-arrow-up-from-line,\n \"scroll-torah\": $fa-var-scroll-torah,\n \"torah\": $fa-var-torah,\n \"broom-ball\": $fa-var-broom-ball,\n \"quidditch\": $fa-var-quidditch,\n \"quidditch-broom-ball\": $fa-var-quidditch-broom-ball,\n \"toggle-off\": $fa-var-toggle-off,\n \"box-archive\": $fa-var-box-archive,\n \"archive\": $fa-var-archive,\n \"person-drowning\": $fa-var-person-drowning,\n \"arrow-down-9-1\": $fa-var-arrow-down-9-1,\n \"sort-numeric-desc\": $fa-var-sort-numeric-desc,\n \"sort-numeric-down-alt\": $fa-var-sort-numeric-down-alt,\n \"face-grin-tongue-squint\": $fa-var-face-grin-tongue-squint,\n \"grin-tongue-squint\": $fa-var-grin-tongue-squint,\n \"spray-can\": $fa-var-spray-can,\n \"truck-monster\": $fa-var-truck-monster,\n \"w\": $fa-var-w,\n \"earth-africa\": $fa-var-earth-africa,\n \"globe-africa\": $fa-var-globe-africa,\n \"rainbow\": $fa-var-rainbow,\n \"circle-notch\": $fa-var-circle-notch,\n \"tablet-screen-button\": $fa-var-tablet-screen-button,\n \"tablet-alt\": $fa-var-tablet-alt,\n \"paw\": $fa-var-paw,\n \"cloud\": $fa-var-cloud,\n \"trowel-bricks\": $fa-var-trowel-bricks,\n \"face-flushed\": $fa-var-face-flushed,\n \"flushed\": $fa-var-flushed,\n \"hospital-user\": $fa-var-hospital-user,\n \"tent-arrow-left-right\": $fa-var-tent-arrow-left-right,\n \"gavel\": $fa-var-gavel,\n \"legal\": $fa-var-legal,\n \"binoculars\": $fa-var-binoculars,\n \"microphone-slash\": $fa-var-microphone-slash,\n \"box-tissue\": $fa-var-box-tissue,\n \"motorcycle\": $fa-var-motorcycle,\n \"bell-concierge\": $fa-var-bell-concierge,\n \"concierge-bell\": $fa-var-concierge-bell,\n \"pen-ruler\": $fa-var-pen-ruler,\n \"pencil-ruler\": $fa-var-pencil-ruler,\n \"people-arrows\": $fa-var-people-arrows,\n \"people-arrows-left-right\": $fa-var-people-arrows-left-right,\n \"mars-and-venus-burst\": $fa-var-mars-and-venus-burst,\n \"square-caret-right\": $fa-var-square-caret-right,\n \"caret-square-right\": $fa-var-caret-square-right,\n \"scissors\": $fa-var-scissors,\n \"cut\": $fa-var-cut,\n \"sun-plant-wilt\": $fa-var-sun-plant-wilt,\n \"toilets-portable\": $fa-var-toilets-portable,\n \"hockey-puck\": $fa-var-hockey-puck,\n \"table\": $fa-var-table,\n \"magnifying-glass-arrow-right\": $fa-var-magnifying-glass-arrow-right,\n \"tachograph-digital\": $fa-var-tachograph-digital,\n \"digital-tachograph\": $fa-var-digital-tachograph,\n \"users-slash\": $fa-var-users-slash,\n \"clover\": $fa-var-clover,\n \"reply\": $fa-var-reply,\n \"mail-reply\": $fa-var-mail-reply,\n \"star-and-crescent\": $fa-var-star-and-crescent,\n \"house-fire\": $fa-var-house-fire,\n \"square-minus\": $fa-var-square-minus,\n \"minus-square\": $fa-var-minus-square,\n \"helicopter\": $fa-var-helicopter,\n \"compass\": $fa-var-compass,\n \"square-caret-down\": $fa-var-square-caret-down,\n \"caret-square-down\": $fa-var-caret-square-down,\n \"file-circle-question\": $fa-var-file-circle-question,\n \"laptop-code\": $fa-var-laptop-code,\n \"swatchbook\": $fa-var-swatchbook,\n \"prescription-bottle\": $fa-var-prescription-bottle,\n \"bars\": $fa-var-bars,\n \"navicon\": $fa-var-navicon,\n \"people-group\": $fa-var-people-group,\n \"hourglass-end\": $fa-var-hourglass-end,\n \"hourglass-3\": $fa-var-hourglass-3,\n \"heart-crack\": $fa-var-heart-crack,\n \"heart-broken\": $fa-var-heart-broken,\n \"square-up-right\": $fa-var-square-up-right,\n \"external-link-square-alt\": $fa-var-external-link-square-alt,\n \"face-kiss-beam\": $fa-var-face-kiss-beam,\n \"kiss-beam\": $fa-var-kiss-beam,\n \"film\": $fa-var-film,\n \"ruler-horizontal\": $fa-var-ruler-horizontal,\n \"people-robbery\": $fa-var-people-robbery,\n \"lightbulb\": $fa-var-lightbulb,\n \"caret-left\": $fa-var-caret-left,\n \"circle-exclamation\": $fa-var-circle-exclamation,\n \"exclamation-circle\": $fa-var-exclamation-circle,\n \"school-circle-xmark\": $fa-var-school-circle-xmark,\n \"arrow-right-from-bracket\": $fa-var-arrow-right-from-bracket,\n \"sign-out\": $fa-var-sign-out,\n \"circle-chevron-down\": $fa-var-circle-chevron-down,\n \"chevron-circle-down\": $fa-var-chevron-circle-down,\n \"unlock-keyhole\": $fa-var-unlock-keyhole,\n \"unlock-alt\": $fa-var-unlock-alt,\n \"cloud-showers-heavy\": $fa-var-cloud-showers-heavy,\n \"headphones-simple\": $fa-var-headphones-simple,\n \"headphones-alt\": $fa-var-headphones-alt,\n \"sitemap\": $fa-var-sitemap,\n \"circle-dollar-to-slot\": $fa-var-circle-dollar-to-slot,\n \"donate\": $fa-var-donate,\n \"memory\": $fa-var-memory,\n \"road-spikes\": $fa-var-road-spikes,\n \"fire-burner\": $fa-var-fire-burner,\n \"flag\": $fa-var-flag,\n \"hanukiah\": $fa-var-hanukiah,\n \"feather\": $fa-var-feather,\n \"volume-low\": $fa-var-volume-low,\n \"volume-down\": $fa-var-volume-down,\n \"comment-slash\": $fa-var-comment-slash,\n \"cloud-sun-rain\": $fa-var-cloud-sun-rain,\n \"compress\": $fa-var-compress,\n \"wheat-awn\": $fa-var-wheat-awn,\n \"wheat-alt\": $fa-var-wheat-alt,\n \"ankh\": $fa-var-ankh,\n \"hands-holding-child\": $fa-var-hands-holding-child,\n \"asterisk\": $fa-var-asterisk,\n \"square-check\": $fa-var-square-check,\n \"check-square\": $fa-var-check-square,\n \"peseta-sign\": $fa-var-peseta-sign,\n \"heading\": $fa-var-heading,\n \"header\": $fa-var-header,\n \"ghost\": $fa-var-ghost,\n \"list\": $fa-var-list,\n \"list-squares\": $fa-var-list-squares,\n \"square-phone-flip\": $fa-var-square-phone-flip,\n \"phone-square-alt\": $fa-var-phone-square-alt,\n \"cart-plus\": $fa-var-cart-plus,\n \"gamepad\": $fa-var-gamepad,\n \"circle-dot\": $fa-var-circle-dot,\n \"dot-circle\": $fa-var-dot-circle,\n \"face-dizzy\": $fa-var-face-dizzy,\n \"dizzy\": $fa-var-dizzy,\n \"egg\": $fa-var-egg,\n \"house-medical-circle-xmark\": $fa-var-house-medical-circle-xmark,\n \"campground\": $fa-var-campground,\n \"folder-plus\": $fa-var-folder-plus,\n \"futbol\": $fa-var-futbol,\n \"futbol-ball\": $fa-var-futbol-ball,\n \"soccer-ball\": $fa-var-soccer-ball,\n \"paintbrush\": $fa-var-paintbrush,\n \"paint-brush\": $fa-var-paint-brush,\n \"lock\": $fa-var-lock,\n \"gas-pump\": $fa-var-gas-pump,\n \"hot-tub-person\": $fa-var-hot-tub-person,\n \"hot-tub\": $fa-var-hot-tub,\n \"map-location\": $fa-var-map-location,\n \"map-marked\": $fa-var-map-marked,\n \"house-flood-water\": $fa-var-house-flood-water,\n \"tree\": $fa-var-tree,\n \"bridge-lock\": $fa-var-bridge-lock,\n \"sack-dollar\": $fa-var-sack-dollar,\n \"pen-to-square\": $fa-var-pen-to-square,\n \"edit\": $fa-var-edit,\n \"car-side\": $fa-var-car-side,\n \"share-nodes\": $fa-var-share-nodes,\n \"share-alt\": $fa-var-share-alt,\n \"heart-circle-minus\": $fa-var-heart-circle-minus,\n \"hourglass-half\": $fa-var-hourglass-half,\n \"hourglass-2\": $fa-var-hourglass-2,\n \"microscope\": $fa-var-microscope,\n \"sink\": $fa-var-sink,\n \"bag-shopping\": $fa-var-bag-shopping,\n \"shopping-bag\": $fa-var-shopping-bag,\n \"arrow-down-z-a\": $fa-var-arrow-down-z-a,\n \"sort-alpha-desc\": $fa-var-sort-alpha-desc,\n \"sort-alpha-down-alt\": $fa-var-sort-alpha-down-alt,\n \"mitten\": $fa-var-mitten,\n \"person-rays\": $fa-var-person-rays,\n \"users\": $fa-var-users,\n \"eye-slash\": $fa-var-eye-slash,\n \"flask-vial\": $fa-var-flask-vial,\n \"hand\": $fa-var-hand,\n \"hand-paper\": $fa-var-hand-paper,\n \"om\": $fa-var-om,\n \"worm\": $fa-var-worm,\n \"house-circle-xmark\": $fa-var-house-circle-xmark,\n \"plug\": $fa-var-plug,\n \"chevron-up\": $fa-var-chevron-up,\n \"hand-spock\": $fa-var-hand-spock,\n \"stopwatch\": $fa-var-stopwatch,\n \"face-kiss\": $fa-var-face-kiss,\n \"kiss\": $fa-var-kiss,\n \"bridge-circle-xmark\": $fa-var-bridge-circle-xmark,\n \"face-grin-tongue\": $fa-var-face-grin-tongue,\n \"grin-tongue\": $fa-var-grin-tongue,\n \"chess-bishop\": $fa-var-chess-bishop,\n \"face-grin-wink\": $fa-var-face-grin-wink,\n \"grin-wink\": $fa-var-grin-wink,\n \"ear-deaf\": $fa-var-ear-deaf,\n \"deaf\": $fa-var-deaf,\n \"deafness\": $fa-var-deafness,\n \"hard-of-hearing\": $fa-var-hard-of-hearing,\n \"road-circle-check\": $fa-var-road-circle-check,\n \"dice-five\": $fa-var-dice-five,\n \"square-rss\": $fa-var-square-rss,\n \"rss-square\": $fa-var-rss-square,\n \"land-mine-on\": $fa-var-land-mine-on,\n \"i-cursor\": $fa-var-i-cursor,\n \"stamp\": $fa-var-stamp,\n \"stairs\": $fa-var-stairs,\n \"i\": $fa-var-i,\n \"hryvnia-sign\": $fa-var-hryvnia-sign,\n \"hryvnia\": $fa-var-hryvnia,\n \"pills\": $fa-var-pills,\n \"face-grin-wide\": $fa-var-face-grin-wide,\n \"grin-alt\": $fa-var-grin-alt,\n \"tooth\": $fa-var-tooth,\n \"v\": $fa-var-v,\n \"bangladeshi-taka-sign\": $fa-var-bangladeshi-taka-sign,\n \"bicycle\": $fa-var-bicycle,\n \"staff-snake\": $fa-var-staff-snake,\n \"rod-asclepius\": $fa-var-rod-asclepius,\n \"rod-snake\": $fa-var-rod-snake,\n \"staff-aesculapius\": $fa-var-staff-aesculapius,\n \"head-side-cough-slash\": $fa-var-head-side-cough-slash,\n \"truck-medical\": $fa-var-truck-medical,\n \"ambulance\": $fa-var-ambulance,\n \"wheat-awn-circle-exclamation\": $fa-var-wheat-awn-circle-exclamation,\n \"snowman\": $fa-var-snowman,\n \"mortar-pestle\": $fa-var-mortar-pestle,\n \"road-barrier\": $fa-var-road-barrier,\n \"school\": $fa-var-school,\n \"igloo\": $fa-var-igloo,\n \"joint\": $fa-var-joint,\n \"angle-right\": $fa-var-angle-right,\n \"horse\": $fa-var-horse,\n \"q\": $fa-var-q,\n \"g\": $fa-var-g,\n \"notes-medical\": $fa-var-notes-medical,\n \"temperature-half\": $fa-var-temperature-half,\n \"temperature-2\": $fa-var-temperature-2,\n \"thermometer-2\": $fa-var-thermometer-2,\n \"thermometer-half\": $fa-var-thermometer-half,\n \"dong-sign\": $fa-var-dong-sign,\n \"capsules\": $fa-var-capsules,\n \"poo-storm\": $fa-var-poo-storm,\n \"poo-bolt\": $fa-var-poo-bolt,\n \"face-frown-open\": $fa-var-face-frown-open,\n \"frown-open\": $fa-var-frown-open,\n \"hand-point-up\": $fa-var-hand-point-up,\n \"money-bill\": $fa-var-money-bill,\n \"bookmark\": $fa-var-bookmark,\n \"align-justify\": $fa-var-align-justify,\n \"umbrella-beach\": $fa-var-umbrella-beach,\n \"helmet-un\": $fa-var-helmet-un,\n \"bullseye\": $fa-var-bullseye,\n \"bacon\": $fa-var-bacon,\n \"hand-point-down\": $fa-var-hand-point-down,\n \"arrow-up-from-bracket\": $fa-var-arrow-up-from-bracket,\n \"folder\": $fa-var-folder,\n \"folder-blank\": $fa-var-folder-blank,\n \"file-waveform\": $fa-var-file-waveform,\n \"file-medical-alt\": $fa-var-file-medical-alt,\n \"radiation\": $fa-var-radiation,\n \"chart-simple\": $fa-var-chart-simple,\n \"mars-stroke\": $fa-var-mars-stroke,\n \"vial\": $fa-var-vial,\n \"gauge\": $fa-var-gauge,\n \"dashboard\": $fa-var-dashboard,\n \"gauge-med\": $fa-var-gauge-med,\n \"tachometer-alt-average\": $fa-var-tachometer-alt-average,\n \"wand-magic-sparkles\": $fa-var-wand-magic-sparkles,\n \"magic-wand-sparkles\": $fa-var-magic-wand-sparkles,\n \"e\": $fa-var-e,\n \"pen-clip\": $fa-var-pen-clip,\n \"pen-alt\": $fa-var-pen-alt,\n \"bridge-circle-exclamation\": $fa-var-bridge-circle-exclamation,\n \"user\": $fa-var-user,\n \"school-circle-check\": $fa-var-school-circle-check,\n \"dumpster\": $fa-var-dumpster,\n \"van-shuttle\": $fa-var-van-shuttle,\n \"shuttle-van\": $fa-var-shuttle-van,\n \"building-user\": $fa-var-building-user,\n \"square-caret-left\": $fa-var-square-caret-left,\n \"caret-square-left\": $fa-var-caret-square-left,\n \"highlighter\": $fa-var-highlighter,\n \"key\": $fa-var-key,\n \"bullhorn\": $fa-var-bullhorn,\n \"globe\": $fa-var-globe,\n \"synagogue\": $fa-var-synagogue,\n \"person-half-dress\": $fa-var-person-half-dress,\n \"road-bridge\": $fa-var-road-bridge,\n \"location-arrow\": $fa-var-location-arrow,\n \"c\": $fa-var-c,\n \"tablet-button\": $fa-var-tablet-button,\n \"building-lock\": $fa-var-building-lock,\n \"pizza-slice\": $fa-var-pizza-slice,\n \"money-bill-wave\": $fa-var-money-bill-wave,\n \"chart-area\": $fa-var-chart-area,\n \"area-chart\": $fa-var-area-chart,\n \"house-flag\": $fa-var-house-flag,\n \"person-circle-minus\": $fa-var-person-circle-minus,\n \"ban\": $fa-var-ban,\n \"cancel\": $fa-var-cancel,\n \"camera-rotate\": $fa-var-camera-rotate,\n \"spray-can-sparkles\": $fa-var-spray-can-sparkles,\n \"air-freshener\": $fa-var-air-freshener,\n \"star\": $fa-var-star,\n \"repeat\": $fa-var-repeat,\n \"cross\": $fa-var-cross,\n \"box\": $fa-var-box,\n \"venus-mars\": $fa-var-venus-mars,\n \"arrow-pointer\": $fa-var-arrow-pointer,\n \"mouse-pointer\": $fa-var-mouse-pointer,\n \"maximize\": $fa-var-maximize,\n \"expand-arrows-alt\": $fa-var-expand-arrows-alt,\n \"charging-station\": $fa-var-charging-station,\n \"shapes\": $fa-var-shapes,\n \"triangle-circle-square\": $fa-var-triangle-circle-square,\n \"shuffle\": $fa-var-shuffle,\n \"random\": $fa-var-random,\n \"person-running\": $fa-var-person-running,\n \"running\": $fa-var-running,\n \"mobile-retro\": $fa-var-mobile-retro,\n \"grip-lines-vertical\": $fa-var-grip-lines-vertical,\n \"spider\": $fa-var-spider,\n \"hands-bound\": $fa-var-hands-bound,\n \"file-invoice-dollar\": $fa-var-file-invoice-dollar,\n \"plane-circle-exclamation\": $fa-var-plane-circle-exclamation,\n \"x-ray\": $fa-var-x-ray,\n \"spell-check\": $fa-var-spell-check,\n \"slash\": $fa-var-slash,\n \"computer-mouse\": $fa-var-computer-mouse,\n \"mouse\": $fa-var-mouse,\n \"arrow-right-to-bracket\": $fa-var-arrow-right-to-bracket,\n \"sign-in\": $fa-var-sign-in,\n \"shop-slash\": $fa-var-shop-slash,\n \"store-alt-slash\": $fa-var-store-alt-slash,\n \"server\": $fa-var-server,\n \"virus-covid-slash\": $fa-var-virus-covid-slash,\n \"shop-lock\": $fa-var-shop-lock,\n \"hourglass-start\": $fa-var-hourglass-start,\n \"hourglass-1\": $fa-var-hourglass-1,\n \"blender-phone\": $fa-var-blender-phone,\n \"building-wheat\": $fa-var-building-wheat,\n \"person-breastfeeding\": $fa-var-person-breastfeeding,\n \"right-to-bracket\": $fa-var-right-to-bracket,\n \"sign-in-alt\": $fa-var-sign-in-alt,\n \"venus\": $fa-var-venus,\n \"passport\": $fa-var-passport,\n \"thumbtack-slash\": $fa-var-thumbtack-slash,\n \"thumb-tack-slash\": $fa-var-thumb-tack-slash,\n \"heart-pulse\": $fa-var-heart-pulse,\n \"heartbeat\": $fa-var-heartbeat,\n \"people-carry-box\": $fa-var-people-carry-box,\n \"people-carry\": $fa-var-people-carry,\n \"temperature-high\": $fa-var-temperature-high,\n \"microchip\": $fa-var-microchip,\n \"crown\": $fa-var-crown,\n \"weight-hanging\": $fa-var-weight-hanging,\n \"xmarks-lines\": $fa-var-xmarks-lines,\n \"file-prescription\": $fa-var-file-prescription,\n \"weight-scale\": $fa-var-weight-scale,\n \"weight\": $fa-var-weight,\n \"user-group\": $fa-var-user-group,\n \"user-friends\": $fa-var-user-friends,\n \"arrow-up-a-z\": $fa-var-arrow-up-a-z,\n \"sort-alpha-up\": $fa-var-sort-alpha-up,\n \"chess-knight\": $fa-var-chess-knight,\n \"face-laugh-squint\": $fa-var-face-laugh-squint,\n \"laugh-squint\": $fa-var-laugh-squint,\n \"wheelchair\": $fa-var-wheelchair,\n \"circle-arrow-up\": $fa-var-circle-arrow-up,\n \"arrow-circle-up\": $fa-var-arrow-circle-up,\n \"toggle-on\": $fa-var-toggle-on,\n \"person-walking\": $fa-var-person-walking,\n \"walking\": $fa-var-walking,\n \"l\": $fa-var-l,\n \"fire\": $fa-var-fire,\n \"bed-pulse\": $fa-var-bed-pulse,\n \"procedures\": $fa-var-procedures,\n \"shuttle-space\": $fa-var-shuttle-space,\n \"space-shuttle\": $fa-var-space-shuttle,\n \"face-laugh\": $fa-var-face-laugh,\n \"laugh\": $fa-var-laugh,\n \"folder-open\": $fa-var-folder-open,\n \"heart-circle-plus\": $fa-var-heart-circle-plus,\n \"code-fork\": $fa-var-code-fork,\n \"city\": $fa-var-city,\n \"microphone-lines\": $fa-var-microphone-lines,\n \"microphone-alt\": $fa-var-microphone-alt,\n \"pepper-hot\": $fa-var-pepper-hot,\n \"unlock\": $fa-var-unlock,\n \"colon-sign\": $fa-var-colon-sign,\n \"headset\": $fa-var-headset,\n \"store-slash\": $fa-var-store-slash,\n \"road-circle-xmark\": $fa-var-road-circle-xmark,\n \"user-minus\": $fa-var-user-minus,\n \"mars-stroke-up\": $fa-var-mars-stroke-up,\n \"mars-stroke-v\": $fa-var-mars-stroke-v,\n \"champagne-glasses\": $fa-var-champagne-glasses,\n \"glass-cheers\": $fa-var-glass-cheers,\n \"clipboard\": $fa-var-clipboard,\n \"house-circle-exclamation\": $fa-var-house-circle-exclamation,\n \"file-arrow-up\": $fa-var-file-arrow-up,\n \"file-upload\": $fa-var-file-upload,\n \"wifi\": $fa-var-wifi,\n \"wifi-3\": $fa-var-wifi-3,\n \"wifi-strong\": $fa-var-wifi-strong,\n \"bath\": $fa-var-bath,\n \"bathtub\": $fa-var-bathtub,\n \"underline\": $fa-var-underline,\n \"user-pen\": $fa-var-user-pen,\n \"user-edit\": $fa-var-user-edit,\n \"signature\": $fa-var-signature,\n \"stroopwafel\": $fa-var-stroopwafel,\n \"bold\": $fa-var-bold,\n \"anchor-lock\": $fa-var-anchor-lock,\n \"building-ngo\": $fa-var-building-ngo,\n \"manat-sign\": $fa-var-manat-sign,\n \"not-equal\": $fa-var-not-equal,\n \"border-top-left\": $fa-var-border-top-left,\n \"border-style\": $fa-var-border-style,\n \"map-location-dot\": $fa-var-map-location-dot,\n \"map-marked-alt\": $fa-var-map-marked-alt,\n \"jedi\": $fa-var-jedi,\n \"square-poll-vertical\": $fa-var-square-poll-vertical,\n \"poll\": $fa-var-poll,\n \"mug-hot\": $fa-var-mug-hot,\n \"car-battery\": $fa-var-car-battery,\n \"battery-car\": $fa-var-battery-car,\n \"gift\": $fa-var-gift,\n \"dice-two\": $fa-var-dice-two,\n \"chess-queen\": $fa-var-chess-queen,\n \"glasses\": $fa-var-glasses,\n \"chess-board\": $fa-var-chess-board,\n \"building-circle-check\": $fa-var-building-circle-check,\n \"person-chalkboard\": $fa-var-person-chalkboard,\n \"mars-stroke-right\": $fa-var-mars-stroke-right,\n \"mars-stroke-h\": $fa-var-mars-stroke-h,\n \"hand-back-fist\": $fa-var-hand-back-fist,\n \"hand-rock\": $fa-var-hand-rock,\n \"square-caret-up\": $fa-var-square-caret-up,\n \"caret-square-up\": $fa-var-caret-square-up,\n \"cloud-showers-water\": $fa-var-cloud-showers-water,\n \"chart-bar\": $fa-var-chart-bar,\n \"bar-chart\": $fa-var-bar-chart,\n \"hands-bubbles\": $fa-var-hands-bubbles,\n \"hands-wash\": $fa-var-hands-wash,\n \"less-than-equal\": $fa-var-less-than-equal,\n \"train\": $fa-var-train,\n \"eye-low-vision\": $fa-var-eye-low-vision,\n \"low-vision\": $fa-var-low-vision,\n \"crow\": $fa-var-crow,\n \"sailboat\": $fa-var-sailboat,\n \"window-restore\": $fa-var-window-restore,\n \"square-plus\": $fa-var-square-plus,\n \"plus-square\": $fa-var-plus-square,\n \"torii-gate\": $fa-var-torii-gate,\n \"frog\": $fa-var-frog,\n \"bucket\": $fa-var-bucket,\n \"image\": $fa-var-image,\n \"microphone\": $fa-var-microphone,\n \"cow\": $fa-var-cow,\n \"caret-up\": $fa-var-caret-up,\n \"screwdriver\": $fa-var-screwdriver,\n \"folder-closed\": $fa-var-folder-closed,\n \"house-tsunami\": $fa-var-house-tsunami,\n \"square-nfi\": $fa-var-square-nfi,\n \"arrow-up-from-ground-water\": $fa-var-arrow-up-from-ground-water,\n \"martini-glass\": $fa-var-martini-glass,\n \"glass-martini-alt\": $fa-var-glass-martini-alt,\n \"square-binary\": $fa-var-square-binary,\n \"rotate-left\": $fa-var-rotate-left,\n \"rotate-back\": $fa-var-rotate-back,\n \"rotate-backward\": $fa-var-rotate-backward,\n \"undo-alt\": $fa-var-undo-alt,\n \"table-columns\": $fa-var-table-columns,\n \"columns\": $fa-var-columns,\n \"lemon\": $fa-var-lemon,\n \"head-side-mask\": $fa-var-head-side-mask,\n \"handshake\": $fa-var-handshake,\n \"gem\": $fa-var-gem,\n \"dolly\": $fa-var-dolly,\n \"dolly-box\": $fa-var-dolly-box,\n \"smoking\": $fa-var-smoking,\n \"minimize\": $fa-var-minimize,\n \"compress-arrows-alt\": $fa-var-compress-arrows-alt,\n \"monument\": $fa-var-monument,\n \"snowplow\": $fa-var-snowplow,\n \"angles-right\": $fa-var-angles-right,\n \"angle-double-right\": $fa-var-angle-double-right,\n \"cannabis\": $fa-var-cannabis,\n \"circle-play\": $fa-var-circle-play,\n \"play-circle\": $fa-var-play-circle,\n \"tablets\": $fa-var-tablets,\n \"ethernet\": $fa-var-ethernet,\n \"euro-sign\": $fa-var-euro-sign,\n \"eur\": $fa-var-eur,\n \"euro\": $fa-var-euro,\n \"chair\": $fa-var-chair,\n \"circle-check\": $fa-var-circle-check,\n \"check-circle\": $fa-var-check-circle,\n \"circle-stop\": $fa-var-circle-stop,\n \"stop-circle\": $fa-var-stop-circle,\n \"compass-drafting\": $fa-var-compass-drafting,\n \"drafting-compass\": $fa-var-drafting-compass,\n \"plate-wheat\": $fa-var-plate-wheat,\n \"icicles\": $fa-var-icicles,\n \"person-shelter\": $fa-var-person-shelter,\n \"neuter\": $fa-var-neuter,\n \"id-badge\": $fa-var-id-badge,\n \"marker\": $fa-var-marker,\n \"face-laugh-beam\": $fa-var-face-laugh-beam,\n \"laugh-beam\": $fa-var-laugh-beam,\n \"helicopter-symbol\": $fa-var-helicopter-symbol,\n \"universal-access\": $fa-var-universal-access,\n \"circle-chevron-up\": $fa-var-circle-chevron-up,\n \"chevron-circle-up\": $fa-var-chevron-circle-up,\n \"lari-sign\": $fa-var-lari-sign,\n \"volcano\": $fa-var-volcano,\n \"person-walking-dashed-line-arrow-right\": $fa-var-person-walking-dashed-line-arrow-right,\n \"sterling-sign\": $fa-var-sterling-sign,\n \"gbp\": $fa-var-gbp,\n \"pound-sign\": $fa-var-pound-sign,\n \"viruses\": $fa-var-viruses,\n \"square-person-confined\": $fa-var-square-person-confined,\n \"user-tie\": $fa-var-user-tie,\n \"arrow-down-long\": $fa-var-arrow-down-long,\n \"long-arrow-down\": $fa-var-long-arrow-down,\n \"tent-arrow-down-to-line\": $fa-var-tent-arrow-down-to-line,\n \"certificate\": $fa-var-certificate,\n \"reply-all\": $fa-var-reply-all,\n \"mail-reply-all\": $fa-var-mail-reply-all,\n \"suitcase\": $fa-var-suitcase,\n \"person-skating\": $fa-var-person-skating,\n \"skating\": $fa-var-skating,\n \"filter-circle-dollar\": $fa-var-filter-circle-dollar,\n \"funnel-dollar\": $fa-var-funnel-dollar,\n \"camera-retro\": $fa-var-camera-retro,\n \"circle-arrow-down\": $fa-var-circle-arrow-down,\n \"arrow-circle-down\": $fa-var-arrow-circle-down,\n \"file-import\": $fa-var-file-import,\n \"arrow-right-to-file\": $fa-var-arrow-right-to-file,\n \"square-arrow-up-right\": $fa-var-square-arrow-up-right,\n \"external-link-square\": $fa-var-external-link-square,\n \"box-open\": $fa-var-box-open,\n \"scroll\": $fa-var-scroll,\n \"spa\": $fa-var-spa,\n \"location-pin-lock\": $fa-var-location-pin-lock,\n \"pause\": $fa-var-pause,\n \"hill-avalanche\": $fa-var-hill-avalanche,\n \"temperature-empty\": $fa-var-temperature-empty,\n \"temperature-0\": $fa-var-temperature-0,\n \"thermometer-0\": $fa-var-thermometer-0,\n \"thermometer-empty\": $fa-var-thermometer-empty,\n \"bomb\": $fa-var-bomb,\n \"registered\": $fa-var-registered,\n \"address-card\": $fa-var-address-card,\n \"contact-card\": $fa-var-contact-card,\n \"vcard\": $fa-var-vcard,\n \"scale-unbalanced-flip\": $fa-var-scale-unbalanced-flip,\n \"balance-scale-right\": $fa-var-balance-scale-right,\n \"subscript\": $fa-var-subscript,\n \"diamond-turn-right\": $fa-var-diamond-turn-right,\n \"directions\": $fa-var-directions,\n \"burst\": $fa-var-burst,\n \"house-laptop\": $fa-var-house-laptop,\n \"laptop-house\": $fa-var-laptop-house,\n \"face-tired\": $fa-var-face-tired,\n \"tired\": $fa-var-tired,\n \"money-bills\": $fa-var-money-bills,\n \"smog\": $fa-var-smog,\n \"crutch\": $fa-var-crutch,\n \"cloud-arrow-up\": $fa-var-cloud-arrow-up,\n \"cloud-upload\": $fa-var-cloud-upload,\n \"cloud-upload-alt\": $fa-var-cloud-upload-alt,\n \"palette\": $fa-var-palette,\n \"arrows-turn-right\": $fa-var-arrows-turn-right,\n \"vest\": $fa-var-vest,\n \"ferry\": $fa-var-ferry,\n \"arrows-down-to-people\": $fa-var-arrows-down-to-people,\n \"seedling\": $fa-var-seedling,\n \"sprout\": $fa-var-sprout,\n \"left-right\": $fa-var-left-right,\n \"arrows-alt-h\": $fa-var-arrows-alt-h,\n \"boxes-packing\": $fa-var-boxes-packing,\n \"circle-arrow-left\": $fa-var-circle-arrow-left,\n \"arrow-circle-left\": $fa-var-arrow-circle-left,\n \"group-arrows-rotate\": $fa-var-group-arrows-rotate,\n \"bowl-food\": $fa-var-bowl-food,\n \"candy-cane\": $fa-var-candy-cane,\n \"arrow-down-wide-short\": $fa-var-arrow-down-wide-short,\n \"sort-amount-asc\": $fa-var-sort-amount-asc,\n \"sort-amount-down\": $fa-var-sort-amount-down,\n \"cloud-bolt\": $fa-var-cloud-bolt,\n \"thunderstorm\": $fa-var-thunderstorm,\n \"text-slash\": $fa-var-text-slash,\n \"remove-format\": $fa-var-remove-format,\n \"face-smile-wink\": $fa-var-face-smile-wink,\n \"smile-wink\": $fa-var-smile-wink,\n \"file-word\": $fa-var-file-word,\n \"file-powerpoint\": $fa-var-file-powerpoint,\n \"arrows-left-right\": $fa-var-arrows-left-right,\n \"arrows-h\": $fa-var-arrows-h,\n \"house-lock\": $fa-var-house-lock,\n \"cloud-arrow-down\": $fa-var-cloud-arrow-down,\n \"cloud-download\": $fa-var-cloud-download,\n \"cloud-download-alt\": $fa-var-cloud-download-alt,\n \"children\": $fa-var-children,\n \"chalkboard\": $fa-var-chalkboard,\n \"blackboard\": $fa-var-blackboard,\n \"user-large-slash\": $fa-var-user-large-slash,\n \"user-alt-slash\": $fa-var-user-alt-slash,\n \"envelope-open\": $fa-var-envelope-open,\n \"handshake-simple-slash\": $fa-var-handshake-simple-slash,\n \"handshake-alt-slash\": $fa-var-handshake-alt-slash,\n \"mattress-pillow\": $fa-var-mattress-pillow,\n \"guarani-sign\": $fa-var-guarani-sign,\n \"arrows-rotate\": $fa-var-arrows-rotate,\n \"refresh\": $fa-var-refresh,\n \"sync\": $fa-var-sync,\n \"fire-extinguisher\": $fa-var-fire-extinguisher,\n \"cruzeiro-sign\": $fa-var-cruzeiro-sign,\n \"greater-than-equal\": $fa-var-greater-than-equal,\n \"shield-halved\": $fa-var-shield-halved,\n \"shield-alt\": $fa-var-shield-alt,\n \"book-atlas\": $fa-var-book-atlas,\n \"atlas\": $fa-var-atlas,\n \"virus\": $fa-var-virus,\n \"envelope-circle-check\": $fa-var-envelope-circle-check,\n \"layer-group\": $fa-var-layer-group,\n \"arrows-to-dot\": $fa-var-arrows-to-dot,\n \"archway\": $fa-var-archway,\n \"heart-circle-check\": $fa-var-heart-circle-check,\n \"house-chimney-crack\": $fa-var-house-chimney-crack,\n \"house-damage\": $fa-var-house-damage,\n \"file-zipper\": $fa-var-file-zipper,\n \"file-archive\": $fa-var-file-archive,\n \"square\": $fa-var-square,\n \"martini-glass-empty\": $fa-var-martini-glass-empty,\n \"glass-martini\": $fa-var-glass-martini,\n \"couch\": $fa-var-couch,\n \"cedi-sign\": $fa-var-cedi-sign,\n \"italic\": $fa-var-italic,\n \"table-cells-column-lock\": $fa-var-table-cells-column-lock,\n \"church\": $fa-var-church,\n \"comments-dollar\": $fa-var-comments-dollar,\n \"democrat\": $fa-var-democrat,\n \"z\": $fa-var-z,\n \"person-skiing\": $fa-var-person-skiing,\n \"skiing\": $fa-var-skiing,\n \"road-lock\": $fa-var-road-lock,\n \"a\": $fa-var-a,\n \"temperature-arrow-down\": $fa-var-temperature-arrow-down,\n \"temperature-down\": $fa-var-temperature-down,\n \"feather-pointed\": $fa-var-feather-pointed,\n \"feather-alt\": $fa-var-feather-alt,\n \"p\": $fa-var-p,\n \"snowflake\": $fa-var-snowflake,\n \"newspaper\": $fa-var-newspaper,\n \"rectangle-ad\": $fa-var-rectangle-ad,\n \"ad\": $fa-var-ad,\n \"circle-arrow-right\": $fa-var-circle-arrow-right,\n \"arrow-circle-right\": $fa-var-arrow-circle-right,\n \"filter-circle-xmark\": $fa-var-filter-circle-xmark,\n \"locust\": $fa-var-locust,\n \"sort\": $fa-var-sort,\n \"unsorted\": $fa-var-unsorted,\n \"list-ol\": $fa-var-list-ol,\n \"list-1-2\": $fa-var-list-1-2,\n \"list-numeric\": $fa-var-list-numeric,\n \"person-dress-burst\": $fa-var-person-dress-burst,\n \"money-check-dollar\": $fa-var-money-check-dollar,\n \"money-check-alt\": $fa-var-money-check-alt,\n \"vector-square\": $fa-var-vector-square,\n \"bread-slice\": $fa-var-bread-slice,\n \"language\": $fa-var-language,\n \"face-kiss-wink-heart\": $fa-var-face-kiss-wink-heart,\n \"kiss-wink-heart\": $fa-var-kiss-wink-heart,\n \"filter\": $fa-var-filter,\n \"question\": $fa-var-question,\n \"file-signature\": $fa-var-file-signature,\n \"up-down-left-right\": $fa-var-up-down-left-right,\n \"arrows-alt\": $fa-var-arrows-alt,\n \"house-chimney-user\": $fa-var-house-chimney-user,\n \"hand-holding-heart\": $fa-var-hand-holding-heart,\n \"puzzle-piece\": $fa-var-puzzle-piece,\n \"money-check\": $fa-var-money-check,\n \"star-half-stroke\": $fa-var-star-half-stroke,\n \"star-half-alt\": $fa-var-star-half-alt,\n \"code\": $fa-var-code,\n \"whiskey-glass\": $fa-var-whiskey-glass,\n \"glass-whiskey\": $fa-var-glass-whiskey,\n \"building-circle-exclamation\": $fa-var-building-circle-exclamation,\n \"magnifying-glass-chart\": $fa-var-magnifying-glass-chart,\n \"arrow-up-right-from-square\": $fa-var-arrow-up-right-from-square,\n \"external-link\": $fa-var-external-link,\n \"cubes-stacked\": $fa-var-cubes-stacked,\n \"won-sign\": $fa-var-won-sign,\n \"krw\": $fa-var-krw,\n \"won\": $fa-var-won,\n \"virus-covid\": $fa-var-virus-covid,\n \"austral-sign\": $fa-var-austral-sign,\n \"f\": $fa-var-f,\n \"leaf\": $fa-var-leaf,\n \"road\": $fa-var-road,\n \"taxi\": $fa-var-taxi,\n \"cab\": $fa-var-cab,\n \"person-circle-plus\": $fa-var-person-circle-plus,\n \"chart-pie\": $fa-var-chart-pie,\n \"pie-chart\": $fa-var-pie-chart,\n \"bolt-lightning\": $fa-var-bolt-lightning,\n \"sack-xmark\": $fa-var-sack-xmark,\n \"file-excel\": $fa-var-file-excel,\n \"file-contract\": $fa-var-file-contract,\n \"fish-fins\": $fa-var-fish-fins,\n \"building-flag\": $fa-var-building-flag,\n \"face-grin-beam\": $fa-var-face-grin-beam,\n \"grin-beam\": $fa-var-grin-beam,\n \"object-ungroup\": $fa-var-object-ungroup,\n \"poop\": $fa-var-poop,\n \"location-pin\": $fa-var-location-pin,\n \"map-marker\": $fa-var-map-marker,\n \"kaaba\": $fa-var-kaaba,\n \"toilet-paper\": $fa-var-toilet-paper,\n \"helmet-safety\": $fa-var-helmet-safety,\n \"hard-hat\": $fa-var-hard-hat,\n \"hat-hard\": $fa-var-hat-hard,\n \"eject\": $fa-var-eject,\n \"circle-right\": $fa-var-circle-right,\n \"arrow-alt-circle-right\": $fa-var-arrow-alt-circle-right,\n \"plane-circle-check\": $fa-var-plane-circle-check,\n \"face-rolling-eyes\": $fa-var-face-rolling-eyes,\n \"meh-rolling-eyes\": $fa-var-meh-rolling-eyes,\n \"object-group\": $fa-var-object-group,\n \"chart-line\": $fa-var-chart-line,\n \"line-chart\": $fa-var-line-chart,\n \"mask-ventilator\": $fa-var-mask-ventilator,\n \"arrow-right\": $fa-var-arrow-right,\n \"signs-post\": $fa-var-signs-post,\n \"map-signs\": $fa-var-map-signs,\n \"cash-register\": $fa-var-cash-register,\n \"person-circle-question\": $fa-var-person-circle-question,\n \"h\": $fa-var-h,\n \"tarp\": $fa-var-tarp,\n \"screwdriver-wrench\": $fa-var-screwdriver-wrench,\n \"tools\": $fa-var-tools,\n \"arrows-to-eye\": $fa-var-arrows-to-eye,\n \"plug-circle-bolt\": $fa-var-plug-circle-bolt,\n \"heart\": $fa-var-heart,\n \"mars-and-venus\": $fa-var-mars-and-venus,\n \"house-user\": $fa-var-house-user,\n \"home-user\": $fa-var-home-user,\n \"dumpster-fire\": $fa-var-dumpster-fire,\n \"house-crack\": $fa-var-house-crack,\n \"martini-glass-citrus\": $fa-var-martini-glass-citrus,\n \"cocktail\": $fa-var-cocktail,\n \"face-surprise\": $fa-var-face-surprise,\n \"surprise\": $fa-var-surprise,\n \"bottle-water\": $fa-var-bottle-water,\n \"circle-pause\": $fa-var-circle-pause,\n \"pause-circle\": $fa-var-pause-circle,\n \"toilet-paper-slash\": $fa-var-toilet-paper-slash,\n \"apple-whole\": $fa-var-apple-whole,\n \"apple-alt\": $fa-var-apple-alt,\n \"kitchen-set\": $fa-var-kitchen-set,\n \"r\": $fa-var-r,\n \"temperature-quarter\": $fa-var-temperature-quarter,\n \"temperature-1\": $fa-var-temperature-1,\n \"thermometer-1\": $fa-var-thermometer-1,\n \"thermometer-quarter\": $fa-var-thermometer-quarter,\n \"cube\": $fa-var-cube,\n \"bitcoin-sign\": $fa-var-bitcoin-sign,\n \"shield-dog\": $fa-var-shield-dog,\n \"solar-panel\": $fa-var-solar-panel,\n \"lock-open\": $fa-var-lock-open,\n \"elevator\": $fa-var-elevator,\n \"money-bill-transfer\": $fa-var-money-bill-transfer,\n \"money-bill-trend-up\": $fa-var-money-bill-trend-up,\n \"house-flood-water-circle-arrow-right\": $fa-var-house-flood-water-circle-arrow-right,\n \"square-poll-horizontal\": $fa-var-square-poll-horizontal,\n \"poll-h\": $fa-var-poll-h,\n \"circle\": $fa-var-circle,\n \"backward-fast\": $fa-var-backward-fast,\n \"fast-backward\": $fa-var-fast-backward,\n \"recycle\": $fa-var-recycle,\n \"user-astronaut\": $fa-var-user-astronaut,\n \"plane-slash\": $fa-var-plane-slash,\n \"trademark\": $fa-var-trademark,\n \"basketball\": $fa-var-basketball,\n \"basketball-ball\": $fa-var-basketball-ball,\n \"satellite-dish\": $fa-var-satellite-dish,\n \"circle-up\": $fa-var-circle-up,\n \"arrow-alt-circle-up\": $fa-var-arrow-alt-circle-up,\n \"mobile-screen-button\": $fa-var-mobile-screen-button,\n \"mobile-alt\": $fa-var-mobile-alt,\n \"volume-high\": $fa-var-volume-high,\n \"volume-up\": $fa-var-volume-up,\n \"users-rays\": $fa-var-users-rays,\n \"wallet\": $fa-var-wallet,\n \"clipboard-check\": $fa-var-clipboard-check,\n \"file-audio\": $fa-var-file-audio,\n \"burger\": $fa-var-burger,\n \"hamburger\": $fa-var-hamburger,\n \"wrench\": $fa-var-wrench,\n \"bugs\": $fa-var-bugs,\n \"rupee-sign\": $fa-var-rupee-sign,\n \"rupee\": $fa-var-rupee,\n \"file-image\": $fa-var-file-image,\n \"circle-question\": $fa-var-circle-question,\n \"question-circle\": $fa-var-question-circle,\n \"plane-departure\": $fa-var-plane-departure,\n \"handshake-slash\": $fa-var-handshake-slash,\n \"book-bookmark\": $fa-var-book-bookmark,\n \"code-branch\": $fa-var-code-branch,\n \"hat-cowboy\": $fa-var-hat-cowboy,\n \"bridge\": $fa-var-bridge,\n \"phone-flip\": $fa-var-phone-flip,\n \"phone-alt\": $fa-var-phone-alt,\n \"truck-front\": $fa-var-truck-front,\n \"cat\": $fa-var-cat,\n \"anchor-circle-exclamation\": $fa-var-anchor-circle-exclamation,\n \"truck-field\": $fa-var-truck-field,\n \"route\": $fa-var-route,\n \"clipboard-question\": $fa-var-clipboard-question,\n \"panorama\": $fa-var-panorama,\n \"comment-medical\": $fa-var-comment-medical,\n \"teeth-open\": $fa-var-teeth-open,\n \"file-circle-minus\": $fa-var-file-circle-minus,\n \"tags\": $fa-var-tags,\n \"wine-glass\": $fa-var-wine-glass,\n \"forward-fast\": $fa-var-forward-fast,\n \"fast-forward\": $fa-var-fast-forward,\n \"face-meh-blank\": $fa-var-face-meh-blank,\n \"meh-blank\": $fa-var-meh-blank,\n \"square-parking\": $fa-var-square-parking,\n \"parking\": $fa-var-parking,\n \"house-signal\": $fa-var-house-signal,\n \"bars-progress\": $fa-var-bars-progress,\n \"tasks-alt\": $fa-var-tasks-alt,\n \"faucet-drip\": $fa-var-faucet-drip,\n \"cart-flatbed\": $fa-var-cart-flatbed,\n \"dolly-flatbed\": $fa-var-dolly-flatbed,\n \"ban-smoking\": $fa-var-ban-smoking,\n \"smoking-ban\": $fa-var-smoking-ban,\n \"terminal\": $fa-var-terminal,\n \"mobile-button\": $fa-var-mobile-button,\n \"house-medical-flag\": $fa-var-house-medical-flag,\n \"basket-shopping\": $fa-var-basket-shopping,\n \"shopping-basket\": $fa-var-shopping-basket,\n \"tape\": $fa-var-tape,\n \"bus-simple\": $fa-var-bus-simple,\n \"bus-alt\": $fa-var-bus-alt,\n \"eye\": $fa-var-eye,\n \"face-sad-cry\": $fa-var-face-sad-cry,\n \"sad-cry\": $fa-var-sad-cry,\n \"audio-description\": $fa-var-audio-description,\n \"person-military-to-person\": $fa-var-person-military-to-person,\n \"file-shield\": $fa-var-file-shield,\n \"user-slash\": $fa-var-user-slash,\n \"pen\": $fa-var-pen,\n \"tower-observation\": $fa-var-tower-observation,\n \"file-code\": $fa-var-file-code,\n \"signal\": $fa-var-signal,\n \"signal-5\": $fa-var-signal-5,\n \"signal-perfect\": $fa-var-signal-perfect,\n \"bus\": $fa-var-bus,\n \"heart-circle-xmark\": $fa-var-heart-circle-xmark,\n \"house-chimney\": $fa-var-house-chimney,\n \"home-lg\": $fa-var-home-lg,\n \"window-maximize\": $fa-var-window-maximize,\n \"face-frown\": $fa-var-face-frown,\n \"frown\": $fa-var-frown,\n \"prescription\": $fa-var-prescription,\n \"shop\": $fa-var-shop,\n \"store-alt\": $fa-var-store-alt,\n \"floppy-disk\": $fa-var-floppy-disk,\n \"save\": $fa-var-save,\n \"vihara\": $fa-var-vihara,\n \"scale-unbalanced\": $fa-var-scale-unbalanced,\n \"balance-scale-left\": $fa-var-balance-scale-left,\n \"sort-up\": $fa-var-sort-up,\n \"sort-asc\": $fa-var-sort-asc,\n \"comment-dots\": $fa-var-comment-dots,\n \"commenting\": $fa-var-commenting,\n \"plant-wilt\": $fa-var-plant-wilt,\n \"diamond\": $fa-var-diamond,\n \"face-grin-squint\": $fa-var-face-grin-squint,\n \"grin-squint\": $fa-var-grin-squint,\n \"hand-holding-dollar\": $fa-var-hand-holding-dollar,\n \"hand-holding-usd\": $fa-var-hand-holding-usd,\n \"chart-diagram\": $fa-var-chart-diagram,\n \"bacterium\": $fa-var-bacterium,\n \"hand-pointer\": $fa-var-hand-pointer,\n \"drum-steelpan\": $fa-var-drum-steelpan,\n \"hand-scissors\": $fa-var-hand-scissors,\n \"hands-praying\": $fa-var-hands-praying,\n \"praying-hands\": $fa-var-praying-hands,\n \"arrow-rotate-right\": $fa-var-arrow-rotate-right,\n \"arrow-right-rotate\": $fa-var-arrow-right-rotate,\n \"arrow-rotate-forward\": $fa-var-arrow-rotate-forward,\n \"redo\": $fa-var-redo,\n \"biohazard\": $fa-var-biohazard,\n \"location-crosshairs\": $fa-var-location-crosshairs,\n \"location\": $fa-var-location,\n \"mars-double\": $fa-var-mars-double,\n \"child-dress\": $fa-var-child-dress,\n \"users-between-lines\": $fa-var-users-between-lines,\n \"lungs-virus\": $fa-var-lungs-virus,\n \"face-grin-tears\": $fa-var-face-grin-tears,\n \"grin-tears\": $fa-var-grin-tears,\n \"phone\": $fa-var-phone,\n \"calendar-xmark\": $fa-var-calendar-xmark,\n \"calendar-times\": $fa-var-calendar-times,\n \"child-reaching\": $fa-var-child-reaching,\n \"head-side-virus\": $fa-var-head-side-virus,\n \"user-gear\": $fa-var-user-gear,\n \"user-cog\": $fa-var-user-cog,\n \"arrow-up-1-9\": $fa-var-arrow-up-1-9,\n \"sort-numeric-up\": $fa-var-sort-numeric-up,\n \"door-closed\": $fa-var-door-closed,\n \"shield-virus\": $fa-var-shield-virus,\n \"dice-six\": $fa-var-dice-six,\n \"mosquito-net\": $fa-var-mosquito-net,\n \"file-fragment\": $fa-var-file-fragment,\n \"bridge-water\": $fa-var-bridge-water,\n \"person-booth\": $fa-var-person-booth,\n \"text-width\": $fa-var-text-width,\n \"hat-wizard\": $fa-var-hat-wizard,\n \"pen-fancy\": $fa-var-pen-fancy,\n \"person-digging\": $fa-var-person-digging,\n \"digging\": $fa-var-digging,\n \"trash\": $fa-var-trash,\n \"gauge-simple\": $fa-var-gauge-simple,\n \"gauge-simple-med\": $fa-var-gauge-simple-med,\n \"tachometer-average\": $fa-var-tachometer-average,\n \"book-medical\": $fa-var-book-medical,\n \"poo\": $fa-var-poo,\n \"quote-right\": $fa-var-quote-right,\n \"quote-right-alt\": $fa-var-quote-right-alt,\n \"shirt\": $fa-var-shirt,\n \"t-shirt\": $fa-var-t-shirt,\n \"tshirt\": $fa-var-tshirt,\n \"cubes\": $fa-var-cubes,\n \"divide\": $fa-var-divide,\n \"tenge-sign\": $fa-var-tenge-sign,\n \"tenge\": $fa-var-tenge,\n \"headphones\": $fa-var-headphones,\n \"hands-holding\": $fa-var-hands-holding,\n \"hands-clapping\": $fa-var-hands-clapping,\n \"republican\": $fa-var-republican,\n \"arrow-left\": $fa-var-arrow-left,\n \"person-circle-xmark\": $fa-var-person-circle-xmark,\n \"ruler\": $fa-var-ruler,\n \"align-left\": $fa-var-align-left,\n \"dice-d6\": $fa-var-dice-d6,\n \"restroom\": $fa-var-restroom,\n \"j\": $fa-var-j,\n \"users-viewfinder\": $fa-var-users-viewfinder,\n \"file-video\": $fa-var-file-video,\n \"up-right-from-square\": $fa-var-up-right-from-square,\n \"external-link-alt\": $fa-var-external-link-alt,\n \"table-cells\": $fa-var-table-cells,\n \"th\": $fa-var-th,\n \"file-pdf\": $fa-var-file-pdf,\n \"book-bible\": $fa-var-book-bible,\n \"bible\": $fa-var-bible,\n \"o\": $fa-var-o,\n \"suitcase-medical\": $fa-var-suitcase-medical,\n \"medkit\": $fa-var-medkit,\n \"user-secret\": $fa-var-user-secret,\n \"otter\": $fa-var-otter,\n \"person-dress\": $fa-var-person-dress,\n \"female\": $fa-var-female,\n \"comment-dollar\": $fa-var-comment-dollar,\n \"business-time\": $fa-var-business-time,\n \"briefcase-clock\": $fa-var-briefcase-clock,\n \"table-cells-large\": $fa-var-table-cells-large,\n \"th-large\": $fa-var-th-large,\n \"book-tanakh\": $fa-var-book-tanakh,\n \"tanakh\": $fa-var-tanakh,\n \"phone-volume\": $fa-var-phone-volume,\n \"volume-control-phone\": $fa-var-volume-control-phone,\n \"hat-cowboy-side\": $fa-var-hat-cowboy-side,\n \"clipboard-user\": $fa-var-clipboard-user,\n \"child\": $fa-var-child,\n \"lira-sign\": $fa-var-lira-sign,\n \"satellite\": $fa-var-satellite,\n \"plane-lock\": $fa-var-plane-lock,\n \"tag\": $fa-var-tag,\n \"comment\": $fa-var-comment,\n \"cake-candles\": $fa-var-cake-candles,\n \"birthday-cake\": $fa-var-birthday-cake,\n \"cake\": $fa-var-cake,\n \"envelope\": $fa-var-envelope,\n \"angles-up\": $fa-var-angles-up,\n \"angle-double-up\": $fa-var-angle-double-up,\n \"paperclip\": $fa-var-paperclip,\n \"arrow-right-to-city\": $fa-var-arrow-right-to-city,\n \"ribbon\": $fa-var-ribbon,\n \"lungs\": $fa-var-lungs,\n \"arrow-up-9-1\": $fa-var-arrow-up-9-1,\n \"sort-numeric-up-alt\": $fa-var-sort-numeric-up-alt,\n \"litecoin-sign\": $fa-var-litecoin-sign,\n \"border-none\": $fa-var-border-none,\n \"circle-nodes\": $fa-var-circle-nodes,\n \"parachute-box\": $fa-var-parachute-box,\n \"indent\": $fa-var-indent,\n \"truck-field-un\": $fa-var-truck-field-un,\n \"hourglass\": $fa-var-hourglass,\n \"hourglass-empty\": $fa-var-hourglass-empty,\n \"mountain\": $fa-var-mountain,\n \"user-doctor\": $fa-var-user-doctor,\n \"user-md\": $fa-var-user-md,\n \"circle-info\": $fa-var-circle-info,\n \"info-circle\": $fa-var-info-circle,\n \"cloud-meatball\": $fa-var-cloud-meatball,\n \"camera\": $fa-var-camera,\n \"camera-alt\": $fa-var-camera-alt,\n \"square-virus\": $fa-var-square-virus,\n \"meteor\": $fa-var-meteor,\n \"car-on\": $fa-var-car-on,\n \"sleigh\": $fa-var-sleigh,\n \"arrow-down-1-9\": $fa-var-arrow-down-1-9,\n \"sort-numeric-asc\": $fa-var-sort-numeric-asc,\n \"sort-numeric-down\": $fa-var-sort-numeric-down,\n \"hand-holding-droplet\": $fa-var-hand-holding-droplet,\n \"hand-holding-water\": $fa-var-hand-holding-water,\n \"water\": $fa-var-water,\n \"calendar-check\": $fa-var-calendar-check,\n \"braille\": $fa-var-braille,\n \"prescription-bottle-medical\": $fa-var-prescription-bottle-medical,\n \"prescription-bottle-alt\": $fa-var-prescription-bottle-alt,\n \"landmark\": $fa-var-landmark,\n \"truck\": $fa-var-truck,\n \"crosshairs\": $fa-var-crosshairs,\n \"person-cane\": $fa-var-person-cane,\n \"tent\": $fa-var-tent,\n \"vest-patches\": $fa-var-vest-patches,\n \"check-double\": $fa-var-check-double,\n \"arrow-down-a-z\": $fa-var-arrow-down-a-z,\n \"sort-alpha-asc\": $fa-var-sort-alpha-asc,\n \"sort-alpha-down\": $fa-var-sort-alpha-down,\n \"money-bill-wheat\": $fa-var-money-bill-wheat,\n \"cookie\": $fa-var-cookie,\n \"arrow-rotate-left\": $fa-var-arrow-rotate-left,\n \"arrow-left-rotate\": $fa-var-arrow-left-rotate,\n \"arrow-rotate-back\": $fa-var-arrow-rotate-back,\n \"arrow-rotate-backward\": $fa-var-arrow-rotate-backward,\n \"undo\": $fa-var-undo,\n \"hard-drive\": $fa-var-hard-drive,\n \"hdd\": $fa-var-hdd,\n \"face-grin-squint-tears\": $fa-var-face-grin-squint-tears,\n \"grin-squint-tears\": $fa-var-grin-squint-tears,\n \"dumbbell\": $fa-var-dumbbell,\n \"rectangle-list\": $fa-var-rectangle-list,\n \"list-alt\": $fa-var-list-alt,\n \"tarp-droplet\": $fa-var-tarp-droplet,\n \"house-medical-circle-check\": $fa-var-house-medical-circle-check,\n \"person-skiing-nordic\": $fa-var-person-skiing-nordic,\n \"skiing-nordic\": $fa-var-skiing-nordic,\n \"calendar-plus\": $fa-var-calendar-plus,\n \"plane-arrival\": $fa-var-plane-arrival,\n \"circle-left\": $fa-var-circle-left,\n \"arrow-alt-circle-left\": $fa-var-arrow-alt-circle-left,\n \"train-subway\": $fa-var-train-subway,\n \"subway\": $fa-var-subway,\n \"chart-gantt\": $fa-var-chart-gantt,\n \"indian-rupee-sign\": $fa-var-indian-rupee-sign,\n \"indian-rupee\": $fa-var-indian-rupee,\n \"inr\": $fa-var-inr,\n \"crop-simple\": $fa-var-crop-simple,\n \"crop-alt\": $fa-var-crop-alt,\n \"money-bill-1\": $fa-var-money-bill-1,\n \"money-bill-alt\": $fa-var-money-bill-alt,\n \"left-long\": $fa-var-left-long,\n \"long-arrow-alt-left\": $fa-var-long-arrow-alt-left,\n \"dna\": $fa-var-dna,\n \"virus-slash\": $fa-var-virus-slash,\n \"minus\": $fa-var-minus,\n \"subtract\": $fa-var-subtract,\n \"chess\": $fa-var-chess,\n \"arrow-left-long\": $fa-var-arrow-left-long,\n \"long-arrow-left\": $fa-var-long-arrow-left,\n \"plug-circle-check\": $fa-var-plug-circle-check,\n \"street-view\": $fa-var-street-view,\n \"franc-sign\": $fa-var-franc-sign,\n \"volume-off\": $fa-var-volume-off,\n \"hands-asl-interpreting\": $fa-var-hands-asl-interpreting,\n \"american-sign-language-interpreting\": $fa-var-american-sign-language-interpreting,\n \"asl-interpreting\": $fa-var-asl-interpreting,\n \"hands-american-sign-language-interpreting\": $fa-var-hands-american-sign-language-interpreting,\n \"gear\": $fa-var-gear,\n \"cog\": $fa-var-cog,\n \"droplet-slash\": $fa-var-droplet-slash,\n \"tint-slash\": $fa-var-tint-slash,\n \"mosque\": $fa-var-mosque,\n \"mosquito\": $fa-var-mosquito,\n \"star-of-david\": $fa-var-star-of-david,\n \"person-military-rifle\": $fa-var-person-military-rifle,\n \"cart-shopping\": $fa-var-cart-shopping,\n \"shopping-cart\": $fa-var-shopping-cart,\n \"vials\": $fa-var-vials,\n \"plug-circle-plus\": $fa-var-plug-circle-plus,\n \"place-of-worship\": $fa-var-place-of-worship,\n \"grip-vertical\": $fa-var-grip-vertical,\n \"hexagon-nodes\": $fa-var-hexagon-nodes,\n \"arrow-turn-up\": $fa-var-arrow-turn-up,\n \"level-up\": $fa-var-level-up,\n \"u\": $fa-var-u,\n \"square-root-variable\": $fa-var-square-root-variable,\n \"square-root-alt\": $fa-var-square-root-alt,\n \"clock\": $fa-var-clock,\n \"clock-four\": $fa-var-clock-four,\n \"backward-step\": $fa-var-backward-step,\n \"step-backward\": $fa-var-step-backward,\n \"pallet\": $fa-var-pallet,\n \"faucet\": $fa-var-faucet,\n \"baseball-bat-ball\": $fa-var-baseball-bat-ball,\n \"s\": $fa-var-s,\n \"timeline\": $fa-var-timeline,\n \"keyboard\": $fa-var-keyboard,\n \"caret-down\": $fa-var-caret-down,\n \"house-chimney-medical\": $fa-var-house-chimney-medical,\n \"clinic-medical\": $fa-var-clinic-medical,\n \"temperature-three-quarters\": $fa-var-temperature-three-quarters,\n \"temperature-3\": $fa-var-temperature-3,\n \"thermometer-3\": $fa-var-thermometer-3,\n \"thermometer-three-quarters\": $fa-var-thermometer-three-quarters,\n \"mobile-screen\": $fa-var-mobile-screen,\n \"mobile-android-alt\": $fa-var-mobile-android-alt,\n \"plane-up\": $fa-var-plane-up,\n \"piggy-bank\": $fa-var-piggy-bank,\n \"battery-half\": $fa-var-battery-half,\n \"battery-3\": $fa-var-battery-3,\n \"mountain-city\": $fa-var-mountain-city,\n \"coins\": $fa-var-coins,\n \"khanda\": $fa-var-khanda,\n \"sliders\": $fa-var-sliders,\n \"sliders-h\": $fa-var-sliders-h,\n \"folder-tree\": $fa-var-folder-tree,\n \"network-wired\": $fa-var-network-wired,\n \"map-pin\": $fa-var-map-pin,\n \"hamsa\": $fa-var-hamsa,\n \"cent-sign\": $fa-var-cent-sign,\n \"flask\": $fa-var-flask,\n \"person-pregnant\": $fa-var-person-pregnant,\n \"wand-sparkles\": $fa-var-wand-sparkles,\n \"ellipsis-vertical\": $fa-var-ellipsis-vertical,\n \"ellipsis-v\": $fa-var-ellipsis-v,\n \"ticket\": $fa-var-ticket,\n \"power-off\": $fa-var-power-off,\n \"right-long\": $fa-var-right-long,\n \"long-arrow-alt-right\": $fa-var-long-arrow-alt-right,\n \"flag-usa\": $fa-var-flag-usa,\n \"laptop-file\": $fa-var-laptop-file,\n \"tty\": $fa-var-tty,\n \"teletype\": $fa-var-teletype,\n \"diagram-next\": $fa-var-diagram-next,\n \"person-rifle\": $fa-var-person-rifle,\n \"house-medical-circle-exclamation\": $fa-var-house-medical-circle-exclamation,\n \"closed-captioning\": $fa-var-closed-captioning,\n \"person-hiking\": $fa-var-person-hiking,\n \"hiking\": $fa-var-hiking,\n \"venus-double\": $fa-var-venus-double,\n \"images\": $fa-var-images,\n \"calculator\": $fa-var-calculator,\n \"people-pulling\": $fa-var-people-pulling,\n \"n\": $fa-var-n,\n \"cable-car\": $fa-var-cable-car,\n \"tram\": $fa-var-tram,\n \"cloud-rain\": $fa-var-cloud-rain,\n \"building-circle-xmark\": $fa-var-building-circle-xmark,\n \"ship\": $fa-var-ship,\n \"arrows-down-to-line\": $fa-var-arrows-down-to-line,\n \"download\": $fa-var-download,\n \"face-grin\": $fa-var-face-grin,\n \"grin\": $fa-var-grin,\n \"delete-left\": $fa-var-delete-left,\n \"backspace\": $fa-var-backspace,\n \"eye-dropper\": $fa-var-eye-dropper,\n \"eye-dropper-empty\": $fa-var-eye-dropper-empty,\n \"eyedropper\": $fa-var-eyedropper,\n \"file-circle-check\": $fa-var-file-circle-check,\n \"forward\": $fa-var-forward,\n \"mobile\": $fa-var-mobile,\n \"mobile-android\": $fa-var-mobile-android,\n \"mobile-phone\": $fa-var-mobile-phone,\n \"face-meh\": $fa-var-face-meh,\n \"meh\": $fa-var-meh,\n \"align-center\": $fa-var-align-center,\n \"book-skull\": $fa-var-book-skull,\n \"book-dead\": $fa-var-book-dead,\n \"id-card\": $fa-var-id-card,\n \"drivers-license\": $fa-var-drivers-license,\n \"outdent\": $fa-var-outdent,\n \"dedent\": $fa-var-dedent,\n \"heart-circle-exclamation\": $fa-var-heart-circle-exclamation,\n \"house\": $fa-var-house,\n \"home\": $fa-var-home,\n \"home-alt\": $fa-var-home-alt,\n \"home-lg-alt\": $fa-var-home-lg-alt,\n \"calendar-week\": $fa-var-calendar-week,\n \"laptop-medical\": $fa-var-laptop-medical,\n \"b\": $fa-var-b,\n \"file-medical\": $fa-var-file-medical,\n \"dice-one\": $fa-var-dice-one,\n \"kiwi-bird\": $fa-var-kiwi-bird,\n \"arrow-right-arrow-left\": $fa-var-arrow-right-arrow-left,\n \"exchange\": $fa-var-exchange,\n \"rotate-right\": $fa-var-rotate-right,\n \"redo-alt\": $fa-var-redo-alt,\n \"rotate-forward\": $fa-var-rotate-forward,\n \"utensils\": $fa-var-utensils,\n \"cutlery\": $fa-var-cutlery,\n \"arrow-up-wide-short\": $fa-var-arrow-up-wide-short,\n \"sort-amount-up\": $fa-var-sort-amount-up,\n \"mill-sign\": $fa-var-mill-sign,\n \"bowl-rice\": $fa-var-bowl-rice,\n \"skull\": $fa-var-skull,\n \"tower-broadcast\": $fa-var-tower-broadcast,\n \"broadcast-tower\": $fa-var-broadcast-tower,\n \"truck-pickup\": $fa-var-truck-pickup,\n \"up-long\": $fa-var-up-long,\n \"long-arrow-alt-up\": $fa-var-long-arrow-alt-up,\n \"stop\": $fa-var-stop,\n \"code-merge\": $fa-var-code-merge,\n \"upload\": $fa-var-upload,\n \"hurricane\": $fa-var-hurricane,\n \"mound\": $fa-var-mound,\n \"toilet-portable\": $fa-var-toilet-portable,\n \"compact-disc\": $fa-var-compact-disc,\n \"file-arrow-down\": $fa-var-file-arrow-down,\n \"file-download\": $fa-var-file-download,\n \"caravan\": $fa-var-caravan,\n \"shield-cat\": $fa-var-shield-cat,\n \"bolt\": $fa-var-bolt,\n \"zap\": $fa-var-zap,\n \"glass-water\": $fa-var-glass-water,\n \"oil-well\": $fa-var-oil-well,\n \"vault\": $fa-var-vault,\n \"mars\": $fa-var-mars,\n \"toilet\": $fa-var-toilet,\n \"plane-circle-xmark\": $fa-var-plane-circle-xmark,\n \"yen-sign\": $fa-var-yen-sign,\n \"cny\": $fa-var-cny,\n \"jpy\": $fa-var-jpy,\n \"rmb\": $fa-var-rmb,\n \"yen\": $fa-var-yen,\n \"ruble-sign\": $fa-var-ruble-sign,\n \"rouble\": $fa-var-rouble,\n \"rub\": $fa-var-rub,\n \"ruble\": $fa-var-ruble,\n \"sun\": $fa-var-sun,\n \"guitar\": $fa-var-guitar,\n \"face-laugh-wink\": $fa-var-face-laugh-wink,\n \"laugh-wink\": $fa-var-laugh-wink,\n \"horse-head\": $fa-var-horse-head,\n \"bore-hole\": $fa-var-bore-hole,\n \"industry\": $fa-var-industry,\n \"circle-down\": $fa-var-circle-down,\n \"arrow-alt-circle-down\": $fa-var-arrow-alt-circle-down,\n \"arrows-turn-to-dots\": $fa-var-arrows-turn-to-dots,\n \"florin-sign\": $fa-var-florin-sign,\n \"arrow-down-short-wide\": $fa-var-arrow-down-short-wide,\n \"sort-amount-desc\": $fa-var-sort-amount-desc,\n \"sort-amount-down-alt\": $fa-var-sort-amount-down-alt,\n \"less-than\": $fa-var-less-than,\n \"angle-down\": $fa-var-angle-down,\n \"car-tunnel\": $fa-var-car-tunnel,\n \"head-side-cough\": $fa-var-head-side-cough,\n \"grip-lines\": $fa-var-grip-lines,\n \"thumbs-down\": $fa-var-thumbs-down,\n \"user-lock\": $fa-var-user-lock,\n \"arrow-right-long\": $fa-var-arrow-right-long,\n \"long-arrow-right\": $fa-var-long-arrow-right,\n \"anchor-circle-xmark\": $fa-var-anchor-circle-xmark,\n \"ellipsis\": $fa-var-ellipsis,\n \"ellipsis-h\": $fa-var-ellipsis-h,\n \"chess-pawn\": $fa-var-chess-pawn,\n \"kit-medical\": $fa-var-kit-medical,\n \"first-aid\": $fa-var-first-aid,\n \"person-through-window\": $fa-var-person-through-window,\n \"toolbox\": $fa-var-toolbox,\n \"hands-holding-circle\": $fa-var-hands-holding-circle,\n \"bug\": $fa-var-bug,\n \"credit-card\": $fa-var-credit-card,\n \"credit-card-alt\": $fa-var-credit-card-alt,\n \"car\": $fa-var-car,\n \"automobile\": $fa-var-automobile,\n \"hand-holding-hand\": $fa-var-hand-holding-hand,\n \"book-open-reader\": $fa-var-book-open-reader,\n \"book-reader\": $fa-var-book-reader,\n \"mountain-sun\": $fa-var-mountain-sun,\n \"arrows-left-right-to-line\": $fa-var-arrows-left-right-to-line,\n \"dice-d20\": $fa-var-dice-d20,\n \"truck-droplet\": $fa-var-truck-droplet,\n \"file-circle-xmark\": $fa-var-file-circle-xmark,\n \"temperature-arrow-up\": $fa-var-temperature-arrow-up,\n \"temperature-up\": $fa-var-temperature-up,\n \"medal\": $fa-var-medal,\n \"bed\": $fa-var-bed,\n \"square-h\": $fa-var-square-h,\n \"h-square\": $fa-var-h-square,\n \"podcast\": $fa-var-podcast,\n \"temperature-full\": $fa-var-temperature-full,\n \"temperature-4\": $fa-var-temperature-4,\n \"thermometer-4\": $fa-var-thermometer-4,\n \"thermometer-full\": $fa-var-thermometer-full,\n \"bell\": $fa-var-bell,\n \"superscript\": $fa-var-superscript,\n \"plug-circle-xmark\": $fa-var-plug-circle-xmark,\n \"star-of-life\": $fa-var-star-of-life,\n \"phone-slash\": $fa-var-phone-slash,\n \"paint-roller\": $fa-var-paint-roller,\n \"handshake-angle\": $fa-var-handshake-angle,\n \"hands-helping\": $fa-var-hands-helping,\n \"location-dot\": $fa-var-location-dot,\n \"map-marker-alt\": $fa-var-map-marker-alt,\n \"file\": $fa-var-file,\n \"greater-than\": $fa-var-greater-than,\n \"person-swimming\": $fa-var-person-swimming,\n \"swimmer\": $fa-var-swimmer,\n \"arrow-down\": $fa-var-arrow-down,\n \"droplet\": $fa-var-droplet,\n \"tint\": $fa-var-tint,\n \"eraser\": $fa-var-eraser,\n \"earth-americas\": $fa-var-earth-americas,\n \"earth\": $fa-var-earth,\n \"earth-america\": $fa-var-earth-america,\n \"globe-americas\": $fa-var-globe-americas,\n \"person-burst\": $fa-var-person-burst,\n \"dove\": $fa-var-dove,\n \"battery-empty\": $fa-var-battery-empty,\n \"battery-0\": $fa-var-battery-0,\n \"socks\": $fa-var-socks,\n \"inbox\": $fa-var-inbox,\n \"section\": $fa-var-section,\n \"gauge-high\": $fa-var-gauge-high,\n \"tachometer-alt\": $fa-var-tachometer-alt,\n \"tachometer-alt-fast\": $fa-var-tachometer-alt-fast,\n \"envelope-open-text\": $fa-var-envelope-open-text,\n \"hospital\": $fa-var-hospital,\n \"hospital-alt\": $fa-var-hospital-alt,\n \"hospital-wide\": $fa-var-hospital-wide,\n \"wine-bottle\": $fa-var-wine-bottle,\n \"chess-rook\": $fa-var-chess-rook,\n \"bars-staggered\": $fa-var-bars-staggered,\n \"reorder\": $fa-var-reorder,\n \"stream\": $fa-var-stream,\n \"dharmachakra\": $fa-var-dharmachakra,\n \"hotdog\": $fa-var-hotdog,\n \"person-walking-with-cane\": $fa-var-person-walking-with-cane,\n \"blind\": $fa-var-blind,\n \"drum\": $fa-var-drum,\n \"ice-cream\": $fa-var-ice-cream,\n \"heart-circle-bolt\": $fa-var-heart-circle-bolt,\n \"fax\": $fa-var-fax,\n \"paragraph\": $fa-var-paragraph,\n \"check-to-slot\": $fa-var-check-to-slot,\n \"vote-yea\": $fa-var-vote-yea,\n \"star-half\": $fa-var-star-half,\n \"boxes-stacked\": $fa-var-boxes-stacked,\n \"boxes\": $fa-var-boxes,\n \"boxes-alt\": $fa-var-boxes-alt,\n \"link\": $fa-var-link,\n \"chain\": $fa-var-chain,\n \"ear-listen\": $fa-var-ear-listen,\n \"assistive-listening-systems\": $fa-var-assistive-listening-systems,\n \"tree-city\": $fa-var-tree-city,\n \"play\": $fa-var-play,\n \"font\": $fa-var-font,\n \"table-cells-row-lock\": $fa-var-table-cells-row-lock,\n \"rupiah-sign\": $fa-var-rupiah-sign,\n \"magnifying-glass\": $fa-var-magnifying-glass,\n \"search\": $fa-var-search,\n \"table-tennis-paddle-ball\": $fa-var-table-tennis-paddle-ball,\n \"ping-pong-paddle-ball\": $fa-var-ping-pong-paddle-ball,\n \"table-tennis\": $fa-var-table-tennis,\n \"person-dots-from-line\": $fa-var-person-dots-from-line,\n \"diagnoses\": $fa-var-diagnoses,\n \"trash-can-arrow-up\": $fa-var-trash-can-arrow-up,\n \"trash-restore-alt\": $fa-var-trash-restore-alt,\n \"naira-sign\": $fa-var-naira-sign,\n \"cart-arrow-down\": $fa-var-cart-arrow-down,\n \"walkie-talkie\": $fa-var-walkie-talkie,\n \"file-pen\": $fa-var-file-pen,\n \"file-edit\": $fa-var-file-edit,\n \"receipt\": $fa-var-receipt,\n \"square-pen\": $fa-var-square-pen,\n \"pen-square\": $fa-var-pen-square,\n \"pencil-square\": $fa-var-pencil-square,\n \"suitcase-rolling\": $fa-var-suitcase-rolling,\n \"person-circle-exclamation\": $fa-var-person-circle-exclamation,\n \"chevron-down\": $fa-var-chevron-down,\n \"battery-full\": $fa-var-battery-full,\n \"battery\": $fa-var-battery,\n \"battery-5\": $fa-var-battery-5,\n \"skull-crossbones\": $fa-var-skull-crossbones,\n \"code-compare\": $fa-var-code-compare,\n \"list-ul\": $fa-var-list-ul,\n \"list-dots\": $fa-var-list-dots,\n \"school-lock\": $fa-var-school-lock,\n \"tower-cell\": $fa-var-tower-cell,\n \"down-long\": $fa-var-down-long,\n \"long-arrow-alt-down\": $fa-var-long-arrow-alt-down,\n \"ranking-star\": $fa-var-ranking-star,\n \"chess-king\": $fa-var-chess-king,\n \"person-harassing\": $fa-var-person-harassing,\n \"brazilian-real-sign\": $fa-var-brazilian-real-sign,\n \"landmark-dome\": $fa-var-landmark-dome,\n \"landmark-alt\": $fa-var-landmark-alt,\n \"arrow-up\": $fa-var-arrow-up,\n \"tv\": $fa-var-tv,\n \"television\": $fa-var-television,\n \"tv-alt\": $fa-var-tv-alt,\n \"shrimp\": $fa-var-shrimp,\n \"list-check\": $fa-var-list-check,\n \"tasks\": $fa-var-tasks,\n \"jug-detergent\": $fa-var-jug-detergent,\n \"circle-user\": $fa-var-circle-user,\n \"user-circle\": $fa-var-user-circle,\n \"user-shield\": $fa-var-user-shield,\n \"wind\": $fa-var-wind,\n \"car-burst\": $fa-var-car-burst,\n \"car-crash\": $fa-var-car-crash,\n \"y\": $fa-var-y,\n \"person-snowboarding\": $fa-var-person-snowboarding,\n \"snowboarding\": $fa-var-snowboarding,\n \"truck-fast\": $fa-var-truck-fast,\n \"shipping-fast\": $fa-var-shipping-fast,\n \"fish\": $fa-var-fish,\n \"user-graduate\": $fa-var-user-graduate,\n \"circle-half-stroke\": $fa-var-circle-half-stroke,\n \"adjust\": $fa-var-adjust,\n \"clapperboard\": $fa-var-clapperboard,\n \"circle-radiation\": $fa-var-circle-radiation,\n \"radiation-alt\": $fa-var-radiation-alt,\n \"baseball\": $fa-var-baseball,\n \"baseball-ball\": $fa-var-baseball-ball,\n \"jet-fighter-up\": $fa-var-jet-fighter-up,\n \"diagram-project\": $fa-var-diagram-project,\n \"project-diagram\": $fa-var-project-diagram,\n \"copy\": $fa-var-copy,\n \"volume-xmark\": $fa-var-volume-xmark,\n \"volume-mute\": $fa-var-volume-mute,\n \"volume-times\": $fa-var-volume-times,\n \"hand-sparkles\": $fa-var-hand-sparkles,\n \"grip\": $fa-var-grip,\n \"grip-horizontal\": $fa-var-grip-horizontal,\n \"share-from-square\": $fa-var-share-from-square,\n \"share-square\": $fa-var-share-square,\n \"child-combatant\": $fa-var-child-combatant,\n \"child-rifle\": $fa-var-child-rifle,\n \"gun\": $fa-var-gun,\n \"square-phone\": $fa-var-square-phone,\n \"phone-square\": $fa-var-phone-square,\n \"plus\": $fa-var-plus,\n \"add\": $fa-var-add,\n \"expand\": $fa-var-expand,\n \"computer\": $fa-var-computer,\n \"xmark\": $fa-var-xmark,\n \"close\": $fa-var-close,\n \"multiply\": $fa-var-multiply,\n \"remove\": $fa-var-remove,\n \"times\": $fa-var-times,\n \"arrows-up-down-left-right\": $fa-var-arrows-up-down-left-right,\n \"arrows\": $fa-var-arrows,\n \"chalkboard-user\": $fa-var-chalkboard-user,\n \"chalkboard-teacher\": $fa-var-chalkboard-teacher,\n \"peso-sign\": $fa-var-peso-sign,\n \"building-shield\": $fa-var-building-shield,\n \"baby\": $fa-var-baby,\n \"users-line\": $fa-var-users-line,\n \"quote-left\": $fa-var-quote-left,\n \"quote-left-alt\": $fa-var-quote-left-alt,\n \"tractor\": $fa-var-tractor,\n \"trash-arrow-up\": $fa-var-trash-arrow-up,\n \"trash-restore\": $fa-var-trash-restore,\n \"arrow-down-up-lock\": $fa-var-arrow-down-up-lock,\n \"lines-leaning\": $fa-var-lines-leaning,\n \"ruler-combined\": $fa-var-ruler-combined,\n \"copyright\": $fa-var-copyright,\n \"equals\": $fa-var-equals,\n \"blender\": $fa-var-blender,\n \"teeth\": $fa-var-teeth,\n \"shekel-sign\": $fa-var-shekel-sign,\n \"ils\": $fa-var-ils,\n \"shekel\": $fa-var-shekel,\n \"sheqel\": $fa-var-sheqel,\n \"sheqel-sign\": $fa-var-sheqel-sign,\n \"map\": $fa-var-map,\n \"rocket\": $fa-var-rocket,\n \"photo-film\": $fa-var-photo-film,\n \"photo-video\": $fa-var-photo-video,\n \"folder-minus\": $fa-var-folder-minus,\n \"hexagon-nodes-bolt\": $fa-var-hexagon-nodes-bolt,\n \"store\": $fa-var-store,\n \"arrow-trend-up\": $fa-var-arrow-trend-up,\n \"plug-circle-minus\": $fa-var-plug-circle-minus,\n \"sign-hanging\": $fa-var-sign-hanging,\n \"sign\": $fa-var-sign,\n \"bezier-curve\": $fa-var-bezier-curve,\n \"bell-slash\": $fa-var-bell-slash,\n \"tablet\": $fa-var-tablet,\n \"tablet-android\": $fa-var-tablet-android,\n \"school-flag\": $fa-var-school-flag,\n \"fill\": $fa-var-fill,\n \"angle-up\": $fa-var-angle-up,\n \"drumstick-bite\": $fa-var-drumstick-bite,\n \"holly-berry\": $fa-var-holly-berry,\n \"chevron-left\": $fa-var-chevron-left,\n \"bacteria\": $fa-var-bacteria,\n \"hand-lizard\": $fa-var-hand-lizard,\n \"notdef\": $fa-var-notdef,\n \"disease\": $fa-var-disease,\n \"briefcase-medical\": $fa-var-briefcase-medical,\n \"genderless\": $fa-var-genderless,\n \"chevron-right\": $fa-var-chevron-right,\n \"retweet\": $fa-var-retweet,\n \"car-rear\": $fa-var-car-rear,\n \"car-alt\": $fa-var-car-alt,\n \"pump-soap\": $fa-var-pump-soap,\n \"video-slash\": $fa-var-video-slash,\n \"battery-quarter\": $fa-var-battery-quarter,\n \"battery-2\": $fa-var-battery-2,\n \"radio\": $fa-var-radio,\n \"baby-carriage\": $fa-var-baby-carriage,\n \"carriage-baby\": $fa-var-carriage-baby,\n \"traffic-light\": $fa-var-traffic-light,\n \"thermometer\": $fa-var-thermometer,\n \"vr-cardboard\": $fa-var-vr-cardboard,\n \"hand-middle-finger\": $fa-var-hand-middle-finger,\n \"percent\": $fa-var-percent,\n \"percentage\": $fa-var-percentage,\n \"truck-moving\": $fa-var-truck-moving,\n \"glass-water-droplet\": $fa-var-glass-water-droplet,\n \"display\": $fa-var-display,\n \"face-smile\": $fa-var-face-smile,\n \"smile\": $fa-var-smile,\n \"thumbtack\": $fa-var-thumbtack,\n \"thumb-tack\": $fa-var-thumb-tack,\n \"trophy\": $fa-var-trophy,\n \"person-praying\": $fa-var-person-praying,\n \"pray\": $fa-var-pray,\n \"hammer\": $fa-var-hammer,\n \"hand-peace\": $fa-var-hand-peace,\n \"rotate\": $fa-var-rotate,\n \"sync-alt\": $fa-var-sync-alt,\n \"spinner\": $fa-var-spinner,\n \"robot\": $fa-var-robot,\n \"peace\": $fa-var-peace,\n \"gears\": $fa-var-gears,\n \"cogs\": $fa-var-cogs,\n \"warehouse\": $fa-var-warehouse,\n \"arrow-up-right-dots\": $fa-var-arrow-up-right-dots,\n \"splotch\": $fa-var-splotch,\n \"face-grin-hearts\": $fa-var-face-grin-hearts,\n \"grin-hearts\": $fa-var-grin-hearts,\n \"dice-four\": $fa-var-dice-four,\n \"sim-card\": $fa-var-sim-card,\n \"transgender\": $fa-var-transgender,\n \"transgender-alt\": $fa-var-transgender-alt,\n \"mercury\": $fa-var-mercury,\n \"arrow-turn-down\": $fa-var-arrow-turn-down,\n \"level-down\": $fa-var-level-down,\n \"person-falling-burst\": $fa-var-person-falling-burst,\n \"award\": $fa-var-award,\n \"ticket-simple\": $fa-var-ticket-simple,\n \"ticket-alt\": $fa-var-ticket-alt,\n \"building\": $fa-var-building,\n \"angles-left\": $fa-var-angles-left,\n \"angle-double-left\": $fa-var-angle-double-left,\n \"qrcode\": $fa-var-qrcode,\n \"clock-rotate-left\": $fa-var-clock-rotate-left,\n \"history\": $fa-var-history,\n \"face-grin-beam-sweat\": $fa-var-face-grin-beam-sweat,\n \"grin-beam-sweat\": $fa-var-grin-beam-sweat,\n \"file-export\": $fa-var-file-export,\n \"arrow-right-from-file\": $fa-var-arrow-right-from-file,\n \"shield\": $fa-var-shield,\n \"shield-blank\": $fa-var-shield-blank,\n \"arrow-up-short-wide\": $fa-var-arrow-up-short-wide,\n \"sort-amount-up-alt\": $fa-var-sort-amount-up-alt,\n \"comment-nodes\": $fa-var-comment-nodes,\n \"house-medical\": $fa-var-house-medical,\n \"golf-ball-tee\": $fa-var-golf-ball-tee,\n \"golf-ball\": $fa-var-golf-ball,\n \"circle-chevron-left\": $fa-var-circle-chevron-left,\n \"chevron-circle-left\": $fa-var-chevron-circle-left,\n \"house-chimney-window\": $fa-var-house-chimney-window,\n \"pen-nib\": $fa-var-pen-nib,\n \"tent-arrow-turn-left\": $fa-var-tent-arrow-turn-left,\n \"tents\": $fa-var-tents,\n \"wand-magic\": $fa-var-wand-magic,\n \"magic\": $fa-var-magic,\n \"dog\": $fa-var-dog,\n \"carrot\": $fa-var-carrot,\n \"moon\": $fa-var-moon,\n \"wine-glass-empty\": $fa-var-wine-glass-empty,\n \"wine-glass-alt\": $fa-var-wine-glass-alt,\n \"cheese\": $fa-var-cheese,\n \"yin-yang\": $fa-var-yin-yang,\n \"music\": $fa-var-music,\n \"code-commit\": $fa-var-code-commit,\n \"temperature-low\": $fa-var-temperature-low,\n \"person-biking\": $fa-var-person-biking,\n \"biking\": $fa-var-biking,\n \"broom\": $fa-var-broom,\n \"shield-heart\": $fa-var-shield-heart,\n \"gopuram\": $fa-var-gopuram,\n \"earth-oceania\": $fa-var-earth-oceania,\n \"globe-oceania\": $fa-var-globe-oceania,\n \"square-xmark\": $fa-var-square-xmark,\n \"times-square\": $fa-var-times-square,\n \"xmark-square\": $fa-var-xmark-square,\n \"hashtag\": $fa-var-hashtag,\n \"up-right-and-down-left-from-center\": $fa-var-up-right-and-down-left-from-center,\n \"expand-alt\": $fa-var-expand-alt,\n \"oil-can\": $fa-var-oil-can,\n \"t\": $fa-var-t,\n \"hippo\": $fa-var-hippo,\n \"chart-column\": $fa-var-chart-column,\n \"infinity\": $fa-var-infinity,\n \"vial-circle-check\": $fa-var-vial-circle-check,\n \"person-arrow-down-to-line\": $fa-var-person-arrow-down-to-line,\n \"voicemail\": $fa-var-voicemail,\n \"fan\": $fa-var-fan,\n \"person-walking-luggage\": $fa-var-person-walking-luggage,\n \"up-down\": $fa-var-up-down,\n \"arrows-alt-v\": $fa-var-arrows-alt-v,\n \"cloud-moon-rain\": $fa-var-cloud-moon-rain,\n \"calendar\": $fa-var-calendar,\n \"trailer\": $fa-var-trailer,\n \"bahai\": $fa-var-bahai,\n \"haykal\": $fa-var-haykal,\n \"sd-card\": $fa-var-sd-card,\n \"dragon\": $fa-var-dragon,\n \"shoe-prints\": $fa-var-shoe-prints,\n \"circle-plus\": $fa-var-circle-plus,\n \"plus-circle\": $fa-var-plus-circle,\n \"face-grin-tongue-wink\": $fa-var-face-grin-tongue-wink,\n \"grin-tongue-wink\": $fa-var-grin-tongue-wink,\n \"hand-holding\": $fa-var-hand-holding,\n \"plug-circle-exclamation\": $fa-var-plug-circle-exclamation,\n \"link-slash\": $fa-var-link-slash,\n \"chain-broken\": $fa-var-chain-broken,\n \"chain-slash\": $fa-var-chain-slash,\n \"unlink\": $fa-var-unlink,\n \"clone\": $fa-var-clone,\n \"person-walking-arrow-loop-left\": $fa-var-person-walking-arrow-loop-left,\n \"arrow-up-z-a\": $fa-var-arrow-up-z-a,\n \"sort-alpha-up-alt\": $fa-var-sort-alpha-up-alt,\n \"fire-flame-curved\": $fa-var-fire-flame-curved,\n \"fire-alt\": $fa-var-fire-alt,\n \"tornado\": $fa-var-tornado,\n \"file-circle-plus\": $fa-var-file-circle-plus,\n \"book-quran\": $fa-var-book-quran,\n \"quran\": $fa-var-quran,\n \"anchor\": $fa-var-anchor,\n \"border-all\": $fa-var-border-all,\n \"face-angry\": $fa-var-face-angry,\n \"angry\": $fa-var-angry,\n \"cookie-bite\": $fa-var-cookie-bite,\n \"arrow-trend-down\": $fa-var-arrow-trend-down,\n \"rss\": $fa-var-rss,\n \"feed\": $fa-var-feed,\n \"draw-polygon\": $fa-var-draw-polygon,\n \"scale-balanced\": $fa-var-scale-balanced,\n \"balance-scale\": $fa-var-balance-scale,\n \"gauge-simple-high\": $fa-var-gauge-simple-high,\n \"tachometer\": $fa-var-tachometer,\n \"tachometer-fast\": $fa-var-tachometer-fast,\n \"shower\": $fa-var-shower,\n \"desktop\": $fa-var-desktop,\n \"desktop-alt\": $fa-var-desktop-alt,\n \"m\": $fa-var-m,\n \"table-list\": $fa-var-table-list,\n \"th-list\": $fa-var-th-list,\n \"comment-sms\": $fa-var-comment-sms,\n \"sms\": $fa-var-sms,\n \"book\": $fa-var-book,\n \"user-plus\": $fa-var-user-plus,\n \"check\": $fa-var-check,\n \"battery-three-quarters\": $fa-var-battery-three-quarters,\n \"battery-4\": $fa-var-battery-4,\n \"house-circle-check\": $fa-var-house-circle-check,\n \"angle-left\": $fa-var-angle-left,\n \"diagram-successor\": $fa-var-diagram-successor,\n \"truck-arrow-right\": $fa-var-truck-arrow-right,\n \"arrows-split-up-and-left\": $fa-var-arrows-split-up-and-left,\n \"hand-fist\": $fa-var-hand-fist,\n \"fist-raised\": $fa-var-fist-raised,\n \"cloud-moon\": $fa-var-cloud-moon,\n \"briefcase\": $fa-var-briefcase,\n \"person-falling\": $fa-var-person-falling,\n \"image-portrait\": $fa-var-image-portrait,\n \"portrait\": $fa-var-portrait,\n \"user-tag\": $fa-var-user-tag,\n \"rug\": $fa-var-rug,\n \"earth-europe\": $fa-var-earth-europe,\n \"globe-europe\": $fa-var-globe-europe,\n \"cart-flatbed-suitcase\": $fa-var-cart-flatbed-suitcase,\n \"luggage-cart\": $fa-var-luggage-cart,\n \"rectangle-xmark\": $fa-var-rectangle-xmark,\n \"rectangle-times\": $fa-var-rectangle-times,\n \"times-rectangle\": $fa-var-times-rectangle,\n \"window-close\": $fa-var-window-close,\n \"baht-sign\": $fa-var-baht-sign,\n \"book-open\": $fa-var-book-open,\n \"book-journal-whills\": $fa-var-book-journal-whills,\n \"journal-whills\": $fa-var-journal-whills,\n \"handcuffs\": $fa-var-handcuffs,\n \"triangle-exclamation\": $fa-var-triangle-exclamation,\n \"exclamation-triangle\": $fa-var-exclamation-triangle,\n \"warning\": $fa-var-warning,\n \"database\": $fa-var-database,\n \"share\": $fa-var-share,\n \"mail-forward\": $fa-var-mail-forward,\n \"bottle-droplet\": $fa-var-bottle-droplet,\n \"mask-face\": $fa-var-mask-face,\n \"hill-rockslide\": $fa-var-hill-rockslide,\n \"right-left\": $fa-var-right-left,\n \"exchange-alt\": $fa-var-exchange-alt,\n \"paper-plane\": $fa-var-paper-plane,\n \"road-circle-exclamation\": $fa-var-road-circle-exclamation,\n \"dungeon\": $fa-var-dungeon,\n \"align-right\": $fa-var-align-right,\n \"money-bill-1-wave\": $fa-var-money-bill-1-wave,\n \"money-bill-wave-alt\": $fa-var-money-bill-wave-alt,\n \"life-ring\": $fa-var-life-ring,\n \"hands\": $fa-var-hands,\n \"sign-language\": $fa-var-sign-language,\n \"signing\": $fa-var-signing,\n \"calendar-day\": $fa-var-calendar-day,\n \"water-ladder\": $fa-var-water-ladder,\n \"ladder-water\": $fa-var-ladder-water,\n \"swimming-pool\": $fa-var-swimming-pool,\n \"arrows-up-down\": $fa-var-arrows-up-down,\n \"arrows-v\": $fa-var-arrows-v,\n \"face-grimace\": $fa-var-face-grimace,\n \"grimace\": $fa-var-grimace,\n \"wheelchair-move\": $fa-var-wheelchair-move,\n \"wheelchair-alt\": $fa-var-wheelchair-alt,\n \"turn-down\": $fa-var-turn-down,\n \"level-down-alt\": $fa-var-level-down-alt,\n \"person-walking-arrow-right\": $fa-var-person-walking-arrow-right,\n \"square-envelope\": $fa-var-square-envelope,\n \"envelope-square\": $fa-var-envelope-square,\n \"dice\": $fa-var-dice,\n \"bowling-ball\": $fa-var-bowling-ball,\n \"brain\": $fa-var-brain,\n \"bandage\": $fa-var-bandage,\n \"band-aid\": $fa-var-band-aid,\n \"calendar-minus\": $fa-var-calendar-minus,\n \"circle-xmark\": $fa-var-circle-xmark,\n \"times-circle\": $fa-var-times-circle,\n \"xmark-circle\": $fa-var-xmark-circle,\n \"gifts\": $fa-var-gifts,\n \"hotel\": $fa-var-hotel,\n \"earth-asia\": $fa-var-earth-asia,\n \"globe-asia\": $fa-var-globe-asia,\n \"id-card-clip\": $fa-var-id-card-clip,\n \"id-card-alt\": $fa-var-id-card-alt,\n \"magnifying-glass-plus\": $fa-var-magnifying-glass-plus,\n \"search-plus\": $fa-var-search-plus,\n \"thumbs-up\": $fa-var-thumbs-up,\n \"user-clock\": $fa-var-user-clock,\n \"hand-dots\": $fa-var-hand-dots,\n \"allergies\": $fa-var-allergies,\n \"file-invoice\": $fa-var-file-invoice,\n \"window-minimize\": $fa-var-window-minimize,\n \"mug-saucer\": $fa-var-mug-saucer,\n \"coffee\": $fa-var-coffee,\n \"brush\": $fa-var-brush,\n \"file-half-dashed\": $fa-var-file-half-dashed,\n \"mask\": $fa-var-mask,\n \"magnifying-glass-minus\": $fa-var-magnifying-glass-minus,\n \"search-minus\": $fa-var-search-minus,\n \"ruler-vertical\": $fa-var-ruler-vertical,\n \"user-large\": $fa-var-user-large,\n \"user-alt\": $fa-var-user-alt,\n \"train-tram\": $fa-var-train-tram,\n \"user-nurse\": $fa-var-user-nurse,\n \"syringe\": $fa-var-syringe,\n \"cloud-sun\": $fa-var-cloud-sun,\n \"stopwatch-20\": $fa-var-stopwatch-20,\n \"square-full\": $fa-var-square-full,\n \"magnet\": $fa-var-magnet,\n \"jar\": $fa-var-jar,\n \"note-sticky\": $fa-var-note-sticky,\n \"sticky-note\": $fa-var-sticky-note,\n \"bug-slash\": $fa-var-bug-slash,\n \"arrow-up-from-water-pump\": $fa-var-arrow-up-from-water-pump,\n \"bone\": $fa-var-bone,\n \"table-cells-row-unlock\": $fa-var-table-cells-row-unlock,\n \"user-injured\": $fa-var-user-injured,\n \"face-sad-tear\": $fa-var-face-sad-tear,\n \"sad-tear\": $fa-var-sad-tear,\n \"plane\": $fa-var-plane,\n \"tent-arrows-down\": $fa-var-tent-arrows-down,\n \"exclamation\": $fa-var-exclamation,\n \"arrows-spin\": $fa-var-arrows-spin,\n \"print\": $fa-var-print,\n \"turkish-lira-sign\": $fa-var-turkish-lira-sign,\n \"try\": $fa-var-try,\n \"turkish-lira\": $fa-var-turkish-lira,\n \"dollar-sign\": $fa-var-dollar-sign,\n \"dollar\": $fa-var-dollar,\n \"usd\": $fa-var-usd,\n \"x\": $fa-var-x,\n \"magnifying-glass-dollar\": $fa-var-magnifying-glass-dollar,\n \"search-dollar\": $fa-var-search-dollar,\n \"users-gear\": $fa-var-users-gear,\n \"users-cog\": $fa-var-users-cog,\n \"person-military-pointing\": $fa-var-person-military-pointing,\n \"building-columns\": $fa-var-building-columns,\n \"bank\": $fa-var-bank,\n \"institution\": $fa-var-institution,\n \"museum\": $fa-var-museum,\n \"university\": $fa-var-university,\n \"umbrella\": $fa-var-umbrella,\n \"trowel\": $fa-var-trowel,\n \"d\": $fa-var-d,\n \"stapler\": $fa-var-stapler,\n \"masks-theater\": $fa-var-masks-theater,\n \"theater-masks\": $fa-var-theater-masks,\n \"kip-sign\": $fa-var-kip-sign,\n \"hand-point-left\": $fa-var-hand-point-left,\n \"handshake-simple\": $fa-var-handshake-simple,\n \"handshake-alt\": $fa-var-handshake-alt,\n \"jet-fighter\": $fa-var-jet-fighter,\n \"fighter-jet\": $fa-var-fighter-jet,\n \"square-share-nodes\": $fa-var-square-share-nodes,\n \"share-alt-square\": $fa-var-share-alt-square,\n \"barcode\": $fa-var-barcode,\n \"plus-minus\": $fa-var-plus-minus,\n \"video\": $fa-var-video,\n \"video-camera\": $fa-var-video-camera,\n \"graduation-cap\": $fa-var-graduation-cap,\n \"mortar-board\": $fa-var-mortar-board,\n \"hand-holding-medical\": $fa-var-hand-holding-medical,\n \"person-circle-check\": $fa-var-person-circle-check,\n \"turn-up\": $fa-var-turn-up,\n \"level-up-alt\": $fa-var-level-up-alt,\n);\n\n$fa-brand-icons: (\n \"monero\": $fa-var-monero,\n \"hooli\": $fa-var-hooli,\n \"yelp\": $fa-var-yelp,\n \"cc-visa\": $fa-var-cc-visa,\n \"lastfm\": $fa-var-lastfm,\n \"shopware\": $fa-var-shopware,\n \"creative-commons-nc\": $fa-var-creative-commons-nc,\n \"aws\": $fa-var-aws,\n \"redhat\": $fa-var-redhat,\n \"yoast\": $fa-var-yoast,\n \"cloudflare\": $fa-var-cloudflare,\n \"ups\": $fa-var-ups,\n \"pixiv\": $fa-var-pixiv,\n \"wpexplorer\": $fa-var-wpexplorer,\n \"dyalog\": $fa-var-dyalog,\n \"bity\": $fa-var-bity,\n \"stackpath\": $fa-var-stackpath,\n \"buysellads\": $fa-var-buysellads,\n \"first-order\": $fa-var-first-order,\n \"modx\": $fa-var-modx,\n \"guilded\": $fa-var-guilded,\n \"vnv\": $fa-var-vnv,\n \"square-js\": $fa-var-square-js,\n \"js-square\": $fa-var-js-square,\n \"microsoft\": $fa-var-microsoft,\n \"qq\": $fa-var-qq,\n \"orcid\": $fa-var-orcid,\n \"java\": $fa-var-java,\n \"invision\": $fa-var-invision,\n \"creative-commons-pd-alt\": $fa-var-creative-commons-pd-alt,\n \"centercode\": $fa-var-centercode,\n \"glide-g\": $fa-var-glide-g,\n \"drupal\": $fa-var-drupal,\n \"jxl\": $fa-var-jxl,\n \"dart-lang\": $fa-var-dart-lang,\n \"hire-a-helper\": $fa-var-hire-a-helper,\n \"creative-commons-by\": $fa-var-creative-commons-by,\n \"unity\": $fa-var-unity,\n \"whmcs\": $fa-var-whmcs,\n \"rocketchat\": $fa-var-rocketchat,\n \"vk\": $fa-var-vk,\n \"untappd\": $fa-var-untappd,\n \"mailchimp\": $fa-var-mailchimp,\n \"css3-alt\": $fa-var-css3-alt,\n \"square-reddit\": $fa-var-square-reddit,\n \"reddit-square\": $fa-var-reddit-square,\n \"vimeo-v\": $fa-var-vimeo-v,\n \"contao\": $fa-var-contao,\n \"square-font-awesome\": $fa-var-square-font-awesome,\n \"deskpro\": $fa-var-deskpro,\n \"brave\": $fa-var-brave,\n \"sistrix\": $fa-var-sistrix,\n \"square-instagram\": $fa-var-square-instagram,\n \"instagram-square\": $fa-var-instagram-square,\n \"battle-net\": $fa-var-battle-net,\n \"the-red-yeti\": $fa-var-the-red-yeti,\n \"square-hacker-news\": $fa-var-square-hacker-news,\n \"hacker-news-square\": $fa-var-hacker-news-square,\n \"edge\": $fa-var-edge,\n \"threads\": $fa-var-threads,\n \"napster\": $fa-var-napster,\n \"square-snapchat\": $fa-var-square-snapchat,\n \"snapchat-square\": $fa-var-snapchat-square,\n \"google-plus-g\": $fa-var-google-plus-g,\n \"artstation\": $fa-var-artstation,\n \"markdown\": $fa-var-markdown,\n \"sourcetree\": $fa-var-sourcetree,\n \"google-plus\": $fa-var-google-plus,\n \"diaspora\": $fa-var-diaspora,\n \"foursquare\": $fa-var-foursquare,\n \"stack-overflow\": $fa-var-stack-overflow,\n \"github-alt\": $fa-var-github-alt,\n \"phoenix-squadron\": $fa-var-phoenix-squadron,\n \"pagelines\": $fa-var-pagelines,\n \"algolia\": $fa-var-algolia,\n \"red-river\": $fa-var-red-river,\n \"creative-commons-sa\": $fa-var-creative-commons-sa,\n \"safari\": $fa-var-safari,\n \"google\": $fa-var-google,\n \"square-font-awesome-stroke\": $fa-var-square-font-awesome-stroke,\n \"font-awesome-alt\": $fa-var-font-awesome-alt,\n \"atlassian\": $fa-var-atlassian,\n \"linkedin-in\": $fa-var-linkedin-in,\n \"digital-ocean\": $fa-var-digital-ocean,\n \"nimblr\": $fa-var-nimblr,\n \"chromecast\": $fa-var-chromecast,\n \"evernote\": $fa-var-evernote,\n \"hacker-news\": $fa-var-hacker-news,\n \"creative-commons-sampling\": $fa-var-creative-commons-sampling,\n \"adversal\": $fa-var-adversal,\n \"creative-commons\": $fa-var-creative-commons,\n \"watchman-monitoring\": $fa-var-watchman-monitoring,\n \"fonticons\": $fa-var-fonticons,\n \"weixin\": $fa-var-weixin,\n \"shirtsinbulk\": $fa-var-shirtsinbulk,\n \"codepen\": $fa-var-codepen,\n \"git-alt\": $fa-var-git-alt,\n \"lyft\": $fa-var-lyft,\n \"rev\": $fa-var-rev,\n \"windows\": $fa-var-windows,\n \"wizards-of-the-coast\": $fa-var-wizards-of-the-coast,\n \"square-viadeo\": $fa-var-square-viadeo,\n \"viadeo-square\": $fa-var-viadeo-square,\n \"meetup\": $fa-var-meetup,\n \"centos\": $fa-var-centos,\n \"adn\": $fa-var-adn,\n \"cloudsmith\": $fa-var-cloudsmith,\n \"opensuse\": $fa-var-opensuse,\n \"pied-piper-alt\": $fa-var-pied-piper-alt,\n \"square-dribbble\": $fa-var-square-dribbble,\n \"dribbble-square\": $fa-var-dribbble-square,\n \"codiepie\": $fa-var-codiepie,\n \"node\": $fa-var-node,\n \"mix\": $fa-var-mix,\n \"steam\": $fa-var-steam,\n \"cc-apple-pay\": $fa-var-cc-apple-pay,\n \"scribd\": $fa-var-scribd,\n \"debian\": $fa-var-debian,\n \"openid\": $fa-var-openid,\n \"instalod\": $fa-var-instalod,\n \"files-pinwheel\": $fa-var-files-pinwheel,\n \"expeditedssl\": $fa-var-expeditedssl,\n \"sellcast\": $fa-var-sellcast,\n \"square-twitter\": $fa-var-square-twitter,\n \"twitter-square\": $fa-var-twitter-square,\n \"r-project\": $fa-var-r-project,\n \"delicious\": $fa-var-delicious,\n \"freebsd\": $fa-var-freebsd,\n \"vuejs\": $fa-var-vuejs,\n \"accusoft\": $fa-var-accusoft,\n \"ioxhost\": $fa-var-ioxhost,\n \"fonticons-fi\": $fa-var-fonticons-fi,\n \"app-store\": $fa-var-app-store,\n \"cc-mastercard\": $fa-var-cc-mastercard,\n \"itunes-note\": $fa-var-itunes-note,\n \"golang\": $fa-var-golang,\n \"kickstarter\": $fa-var-kickstarter,\n \"square-kickstarter\": $fa-var-square-kickstarter,\n \"grav\": $fa-var-grav,\n \"weibo\": $fa-var-weibo,\n \"uncharted\": $fa-var-uncharted,\n \"firstdraft\": $fa-var-firstdraft,\n \"square-youtube\": $fa-var-square-youtube,\n \"youtube-square\": $fa-var-youtube-square,\n \"wikipedia-w\": $fa-var-wikipedia-w,\n \"wpressr\": $fa-var-wpressr,\n \"rendact\": $fa-var-rendact,\n \"angellist\": $fa-var-angellist,\n \"galactic-republic\": $fa-var-galactic-republic,\n \"nfc-directional\": $fa-var-nfc-directional,\n \"skype\": $fa-var-skype,\n \"joget\": $fa-var-joget,\n \"fedora\": $fa-var-fedora,\n \"stripe-s\": $fa-var-stripe-s,\n \"meta\": $fa-var-meta,\n \"laravel\": $fa-var-laravel,\n \"hotjar\": $fa-var-hotjar,\n \"bluetooth-b\": $fa-var-bluetooth-b,\n \"square-letterboxd\": $fa-var-square-letterboxd,\n \"sticker-mule\": $fa-var-sticker-mule,\n \"creative-commons-zero\": $fa-var-creative-commons-zero,\n \"hips\": $fa-var-hips,\n \"css\": $fa-var-css,\n \"behance\": $fa-var-behance,\n \"reddit\": $fa-var-reddit,\n \"discord\": $fa-var-discord,\n \"chrome\": $fa-var-chrome,\n \"app-store-ios\": $fa-var-app-store-ios,\n \"cc-discover\": $fa-var-cc-discover,\n \"wpbeginner\": $fa-var-wpbeginner,\n \"confluence\": $fa-var-confluence,\n \"shoelace\": $fa-var-shoelace,\n \"mdb\": $fa-var-mdb,\n \"dochub\": $fa-var-dochub,\n \"accessible-icon\": $fa-var-accessible-icon,\n \"ebay\": $fa-var-ebay,\n \"amazon\": $fa-var-amazon,\n \"unsplash\": $fa-var-unsplash,\n \"yarn\": $fa-var-yarn,\n \"square-steam\": $fa-var-square-steam,\n \"steam-square\": $fa-var-steam-square,\n \"500px\": $fa-var-500px,\n \"square-vimeo\": $fa-var-square-vimeo,\n \"vimeo-square\": $fa-var-vimeo-square,\n \"asymmetrik\": $fa-var-asymmetrik,\n \"font-awesome\": $fa-var-font-awesome,\n \"font-awesome-flag\": $fa-var-font-awesome-flag,\n \"font-awesome-logo-full\": $fa-var-font-awesome-logo-full,\n \"gratipay\": $fa-var-gratipay,\n \"apple\": $fa-var-apple,\n \"hive\": $fa-var-hive,\n \"gitkraken\": $fa-var-gitkraken,\n \"keybase\": $fa-var-keybase,\n \"apple-pay\": $fa-var-apple-pay,\n \"padlet\": $fa-var-padlet,\n \"amazon-pay\": $fa-var-amazon-pay,\n \"square-github\": $fa-var-square-github,\n \"github-square\": $fa-var-github-square,\n \"stumbleupon\": $fa-var-stumbleupon,\n \"fedex\": $fa-var-fedex,\n \"phoenix-framework\": $fa-var-phoenix-framework,\n \"shopify\": $fa-var-shopify,\n \"neos\": $fa-var-neos,\n \"square-threads\": $fa-var-square-threads,\n \"hackerrank\": $fa-var-hackerrank,\n \"researchgate\": $fa-var-researchgate,\n \"swift\": $fa-var-swift,\n \"angular\": $fa-var-angular,\n \"speakap\": $fa-var-speakap,\n \"angrycreative\": $fa-var-angrycreative,\n \"y-combinator\": $fa-var-y-combinator,\n \"empire\": $fa-var-empire,\n \"envira\": $fa-var-envira,\n \"google-scholar\": $fa-var-google-scholar,\n \"square-gitlab\": $fa-var-square-gitlab,\n \"gitlab-square\": $fa-var-gitlab-square,\n \"studiovinari\": $fa-var-studiovinari,\n \"pied-piper\": $fa-var-pied-piper,\n \"wordpress\": $fa-var-wordpress,\n \"product-hunt\": $fa-var-product-hunt,\n \"firefox\": $fa-var-firefox,\n \"linode\": $fa-var-linode,\n \"goodreads\": $fa-var-goodreads,\n \"square-odnoklassniki\": $fa-var-square-odnoklassniki,\n \"odnoklassniki-square\": $fa-var-odnoklassniki-square,\n \"jsfiddle\": $fa-var-jsfiddle,\n \"sith\": $fa-var-sith,\n \"themeisle\": $fa-var-themeisle,\n \"page4\": $fa-var-page4,\n \"hashnode\": $fa-var-hashnode,\n \"react\": $fa-var-react,\n \"cc-paypal\": $fa-var-cc-paypal,\n \"squarespace\": $fa-var-squarespace,\n \"cc-stripe\": $fa-var-cc-stripe,\n \"creative-commons-share\": $fa-var-creative-commons-share,\n \"bitcoin\": $fa-var-bitcoin,\n \"keycdn\": $fa-var-keycdn,\n \"opera\": $fa-var-opera,\n \"itch-io\": $fa-var-itch-io,\n \"umbraco\": $fa-var-umbraco,\n \"galactic-senate\": $fa-var-galactic-senate,\n \"ubuntu\": $fa-var-ubuntu,\n \"draft2digital\": $fa-var-draft2digital,\n \"stripe\": $fa-var-stripe,\n \"houzz\": $fa-var-houzz,\n \"gg\": $fa-var-gg,\n \"dhl\": $fa-var-dhl,\n \"square-pinterest\": $fa-var-square-pinterest,\n \"pinterest-square\": $fa-var-pinterest-square,\n \"xing\": $fa-var-xing,\n \"blackberry\": $fa-var-blackberry,\n \"creative-commons-pd\": $fa-var-creative-commons-pd,\n \"playstation\": $fa-var-playstation,\n \"quinscape\": $fa-var-quinscape,\n \"less\": $fa-var-less,\n \"blogger-b\": $fa-var-blogger-b,\n \"opencart\": $fa-var-opencart,\n \"vine\": $fa-var-vine,\n \"signal-messenger\": $fa-var-signal-messenger,\n \"paypal\": $fa-var-paypal,\n \"gitlab\": $fa-var-gitlab,\n \"typo3\": $fa-var-typo3,\n \"reddit-alien\": $fa-var-reddit-alien,\n \"yahoo\": $fa-var-yahoo,\n \"dailymotion\": $fa-var-dailymotion,\n \"affiliatetheme\": $fa-var-affiliatetheme,\n \"pied-piper-pp\": $fa-var-pied-piper-pp,\n \"bootstrap\": $fa-var-bootstrap,\n \"odnoklassniki\": $fa-var-odnoklassniki,\n \"nfc-symbol\": $fa-var-nfc-symbol,\n \"mintbit\": $fa-var-mintbit,\n \"ethereum\": $fa-var-ethereum,\n \"speaker-deck\": $fa-var-speaker-deck,\n \"creative-commons-nc-eu\": $fa-var-creative-commons-nc-eu,\n \"patreon\": $fa-var-patreon,\n \"avianex\": $fa-var-avianex,\n \"ello\": $fa-var-ello,\n \"gofore\": $fa-var-gofore,\n \"bimobject\": $fa-var-bimobject,\n \"brave-reverse\": $fa-var-brave-reverse,\n \"facebook-f\": $fa-var-facebook-f,\n \"square-google-plus\": $fa-var-square-google-plus,\n \"google-plus-square\": $fa-var-google-plus-square,\n \"web-awesome\": $fa-var-web-awesome,\n \"mandalorian\": $fa-var-mandalorian,\n \"first-order-alt\": $fa-var-first-order-alt,\n \"osi\": $fa-var-osi,\n \"google-wallet\": $fa-var-google-wallet,\n \"d-and-d-beyond\": $fa-var-d-and-d-beyond,\n \"periscope\": $fa-var-periscope,\n \"fulcrum\": $fa-var-fulcrum,\n \"cloudscale\": $fa-var-cloudscale,\n \"forumbee\": $fa-var-forumbee,\n \"mizuni\": $fa-var-mizuni,\n \"schlix\": $fa-var-schlix,\n \"square-xing\": $fa-var-square-xing,\n \"xing-square\": $fa-var-xing-square,\n \"bandcamp\": $fa-var-bandcamp,\n \"wpforms\": $fa-var-wpforms,\n \"cloudversify\": $fa-var-cloudversify,\n \"usps\": $fa-var-usps,\n \"megaport\": $fa-var-megaport,\n \"magento\": $fa-var-magento,\n \"spotify\": $fa-var-spotify,\n \"optin-monster\": $fa-var-optin-monster,\n \"fly\": $fa-var-fly,\n \"square-bluesky\": $fa-var-square-bluesky,\n \"aviato\": $fa-var-aviato,\n \"itunes\": $fa-var-itunes,\n \"cuttlefish\": $fa-var-cuttlefish,\n \"blogger\": $fa-var-blogger,\n \"flickr\": $fa-var-flickr,\n \"viber\": $fa-var-viber,\n \"soundcloud\": $fa-var-soundcloud,\n \"digg\": $fa-var-digg,\n \"tencent-weibo\": $fa-var-tencent-weibo,\n \"letterboxd\": $fa-var-letterboxd,\n \"symfony\": $fa-var-symfony,\n \"maxcdn\": $fa-var-maxcdn,\n \"etsy\": $fa-var-etsy,\n \"facebook-messenger\": $fa-var-facebook-messenger,\n \"audible\": $fa-var-audible,\n \"think-peaks\": $fa-var-think-peaks,\n \"bilibili\": $fa-var-bilibili,\n \"erlang\": $fa-var-erlang,\n \"x-twitter\": $fa-var-x-twitter,\n \"cotton-bureau\": $fa-var-cotton-bureau,\n \"dashcube\": $fa-var-dashcube,\n \"42-group\": $fa-var-42-group,\n \"innosoft\": $fa-var-innosoft,\n \"stack-exchange\": $fa-var-stack-exchange,\n \"elementor\": $fa-var-elementor,\n \"square-pied-piper\": $fa-var-square-pied-piper,\n \"pied-piper-square\": $fa-var-pied-piper-square,\n \"creative-commons-nd\": $fa-var-creative-commons-nd,\n \"palfed\": $fa-var-palfed,\n \"superpowers\": $fa-var-superpowers,\n \"resolving\": $fa-var-resolving,\n \"xbox\": $fa-var-xbox,\n \"square-web-awesome-stroke\": $fa-var-square-web-awesome-stroke,\n \"searchengin\": $fa-var-searchengin,\n \"tiktok\": $fa-var-tiktok,\n \"square-facebook\": $fa-var-square-facebook,\n \"facebook-square\": $fa-var-facebook-square,\n \"renren\": $fa-var-renren,\n \"linux\": $fa-var-linux,\n \"glide\": $fa-var-glide,\n \"linkedin\": $fa-var-linkedin,\n \"hubspot\": $fa-var-hubspot,\n \"deploydog\": $fa-var-deploydog,\n \"twitch\": $fa-var-twitch,\n \"flutter\": $fa-var-flutter,\n \"ravelry\": $fa-var-ravelry,\n \"mixer\": $fa-var-mixer,\n \"square-lastfm\": $fa-var-square-lastfm,\n \"lastfm-square\": $fa-var-lastfm-square,\n \"vimeo\": $fa-var-vimeo,\n \"mendeley\": $fa-var-mendeley,\n \"uniregistry\": $fa-var-uniregistry,\n \"figma\": $fa-var-figma,\n \"creative-commons-remix\": $fa-var-creative-commons-remix,\n \"cc-amazon-pay\": $fa-var-cc-amazon-pay,\n \"dropbox\": $fa-var-dropbox,\n \"instagram\": $fa-var-instagram,\n \"cmplid\": $fa-var-cmplid,\n \"upwork\": $fa-var-upwork,\n \"facebook\": $fa-var-facebook,\n \"gripfire\": $fa-var-gripfire,\n \"jedi-order\": $fa-var-jedi-order,\n \"uikit\": $fa-var-uikit,\n \"fort-awesome-alt\": $fa-var-fort-awesome-alt,\n \"phabricator\": $fa-var-phabricator,\n \"ussunnah\": $fa-var-ussunnah,\n \"earlybirds\": $fa-var-earlybirds,\n \"trade-federation\": $fa-var-trade-federation,\n \"autoprefixer\": $fa-var-autoprefixer,\n \"whatsapp\": $fa-var-whatsapp,\n \"square-upwork\": $fa-var-square-upwork,\n \"slideshare\": $fa-var-slideshare,\n \"google-play\": $fa-var-google-play,\n \"viadeo\": $fa-var-viadeo,\n \"line\": $fa-var-line,\n \"google-drive\": $fa-var-google-drive,\n \"servicestack\": $fa-var-servicestack,\n \"simplybuilt\": $fa-var-simplybuilt,\n \"bitbucket\": $fa-var-bitbucket,\n \"imdb\": $fa-var-imdb,\n \"deezer\": $fa-var-deezer,\n \"raspberry-pi\": $fa-var-raspberry-pi,\n \"jira\": $fa-var-jira,\n \"docker\": $fa-var-docker,\n \"screenpal\": $fa-var-screenpal,\n \"bluetooth\": $fa-var-bluetooth,\n \"gitter\": $fa-var-gitter,\n \"d-and-d\": $fa-var-d-and-d,\n \"microblog\": $fa-var-microblog,\n \"cc-diners-club\": $fa-var-cc-diners-club,\n \"gg-circle\": $fa-var-gg-circle,\n \"pied-piper-hat\": $fa-var-pied-piper-hat,\n \"kickstarter-k\": $fa-var-kickstarter-k,\n \"yandex\": $fa-var-yandex,\n \"readme\": $fa-var-readme,\n \"html5\": $fa-var-html5,\n \"sellsy\": $fa-var-sellsy,\n \"square-web-awesome\": $fa-var-square-web-awesome,\n \"sass\": $fa-var-sass,\n \"wirsindhandwerk\": $fa-var-wirsindhandwerk,\n \"wsh\": $fa-var-wsh,\n \"buromobelexperte\": $fa-var-buromobelexperte,\n \"salesforce\": $fa-var-salesforce,\n \"octopus-deploy\": $fa-var-octopus-deploy,\n \"medapps\": $fa-var-medapps,\n \"ns8\": $fa-var-ns8,\n \"pinterest-p\": $fa-var-pinterest-p,\n \"apper\": $fa-var-apper,\n \"fort-awesome\": $fa-var-fort-awesome,\n \"waze\": $fa-var-waze,\n \"bluesky\": $fa-var-bluesky,\n \"cc-jcb\": $fa-var-cc-jcb,\n \"snapchat\": $fa-var-snapchat,\n \"snapchat-ghost\": $fa-var-snapchat-ghost,\n \"fantasy-flight-games\": $fa-var-fantasy-flight-games,\n \"rust\": $fa-var-rust,\n \"wix\": $fa-var-wix,\n \"square-behance\": $fa-var-square-behance,\n \"behance-square\": $fa-var-behance-square,\n \"supple\": $fa-var-supple,\n \"webflow\": $fa-var-webflow,\n \"rebel\": $fa-var-rebel,\n \"css3\": $fa-var-css3,\n \"staylinked\": $fa-var-staylinked,\n \"kaggle\": $fa-var-kaggle,\n \"space-awesome\": $fa-var-space-awesome,\n \"deviantart\": $fa-var-deviantart,\n \"cpanel\": $fa-var-cpanel,\n \"goodreads-g\": $fa-var-goodreads-g,\n \"square-git\": $fa-var-square-git,\n \"git-square\": $fa-var-git-square,\n \"square-tumblr\": $fa-var-square-tumblr,\n \"tumblr-square\": $fa-var-tumblr-square,\n \"trello\": $fa-var-trello,\n \"creative-commons-nc-jp\": $fa-var-creative-commons-nc-jp,\n \"get-pocket\": $fa-var-get-pocket,\n \"perbyte\": $fa-var-perbyte,\n \"grunt\": $fa-var-grunt,\n \"weebly\": $fa-var-weebly,\n \"connectdevelop\": $fa-var-connectdevelop,\n \"leanpub\": $fa-var-leanpub,\n \"black-tie\": $fa-var-black-tie,\n \"themeco\": $fa-var-themeco,\n \"python\": $fa-var-python,\n \"android\": $fa-var-android,\n \"bots\": $fa-var-bots,\n \"free-code-camp\": $fa-var-free-code-camp,\n \"hornbill\": $fa-var-hornbill,\n \"js\": $fa-var-js,\n \"ideal\": $fa-var-ideal,\n \"git\": $fa-var-git,\n \"dev\": $fa-var-dev,\n \"sketch\": $fa-var-sketch,\n \"yandex-international\": $fa-var-yandex-international,\n \"cc-amex\": $fa-var-cc-amex,\n \"uber\": $fa-var-uber,\n \"github\": $fa-var-github,\n \"php\": $fa-var-php,\n \"alipay\": $fa-var-alipay,\n \"youtube\": $fa-var-youtube,\n \"skyatlas\": $fa-var-skyatlas,\n \"firefox-browser\": $fa-var-firefox-browser,\n \"replyd\": $fa-var-replyd,\n \"suse\": $fa-var-suse,\n \"jenkins\": $fa-var-jenkins,\n \"twitter\": $fa-var-twitter,\n \"rockrms\": $fa-var-rockrms,\n \"pinterest\": $fa-var-pinterest,\n \"buffer\": $fa-var-buffer,\n \"npm\": $fa-var-npm,\n \"yammer\": $fa-var-yammer,\n \"btc\": $fa-var-btc,\n \"dribbble\": $fa-var-dribbble,\n \"stumbleupon-circle\": $fa-var-stumbleupon-circle,\n \"internet-explorer\": $fa-var-internet-explorer,\n \"stubber\": $fa-var-stubber,\n \"telegram\": $fa-var-telegram,\n \"telegram-plane\": $fa-var-telegram-plane,\n \"old-republic\": $fa-var-old-republic,\n \"odysee\": $fa-var-odysee,\n \"square-whatsapp\": $fa-var-square-whatsapp,\n \"whatsapp-square\": $fa-var-whatsapp-square,\n \"node-js\": $fa-var-node-js,\n \"edge-legacy\": $fa-var-edge-legacy,\n \"slack\": $fa-var-slack,\n \"slack-hash\": $fa-var-slack-hash,\n \"medrt\": $fa-var-medrt,\n \"usb\": $fa-var-usb,\n \"tumblr\": $fa-var-tumblr,\n \"vaadin\": $fa-var-vaadin,\n \"quora\": $fa-var-quora,\n \"square-x-twitter\": $fa-var-square-x-twitter,\n \"reacteurope\": $fa-var-reacteurope,\n \"medium\": $fa-var-medium,\n \"medium-m\": $fa-var-medium-m,\n \"amilia\": $fa-var-amilia,\n \"mixcloud\": $fa-var-mixcloud,\n \"flipboard\": $fa-var-flipboard,\n \"viacoin\": $fa-var-viacoin,\n \"critical-role\": $fa-var-critical-role,\n \"sitrox\": $fa-var-sitrox,\n \"discourse\": $fa-var-discourse,\n \"joomla\": $fa-var-joomla,\n \"mastodon\": $fa-var-mastodon,\n \"airbnb\": $fa-var-airbnb,\n \"wolf-pack-battalion\": $fa-var-wolf-pack-battalion,\n \"buy-n-large\": $fa-var-buy-n-large,\n \"gulp\": $fa-var-gulp,\n \"creative-commons-sampling-plus\": $fa-var-creative-commons-sampling-plus,\n \"strava\": $fa-var-strava,\n \"ember\": $fa-var-ember,\n \"canadian-maple-leaf\": $fa-var-canadian-maple-leaf,\n \"teamspeak\": $fa-var-teamspeak,\n \"pushed\": $fa-var-pushed,\n \"wordpress-simple\": $fa-var-wordpress-simple,\n \"nutritionix\": $fa-var-nutritionix,\n \"wodu\": $fa-var-wodu,\n \"google-pay\": $fa-var-google-pay,\n \"intercom\": $fa-var-intercom,\n \"zhihu\": $fa-var-zhihu,\n \"korvue\": $fa-var-korvue,\n \"pix\": $fa-var-pix,\n \"steam-symbol\": $fa-var-steam-symbol,\n);\n","// icons in a list\n// -------------------------\n\n.#{$fa-css-prefix}-ul {\n list-style-type: none;\n margin-left: var(--#{$fa-css-prefix}-li-margin, #{$fa-li-margin});\n padding-left: 0;\n\n > li { position: relative; }\n}\n\n.#{$fa-css-prefix}-li {\n left: calc(-1 * var(--#{$fa-css-prefix}-li-width, #{$fa-li-width}));\n position: absolute;\n text-align: center;\n width: var(--#{$fa-css-prefix}-li-width, #{$fa-li-width});\n line-height: inherit;\n}\n","// bordered + pulled icons\n// -------------------------\n\n.#{$fa-css-prefix}-border {\n border-color: var(--#{$fa-css-prefix}-border-color, #{$fa-border-color});\n border-radius: var(--#{$fa-css-prefix}-border-radius, #{$fa-border-radius});\n border-style: var(--#{$fa-css-prefix}-border-style, #{$fa-border-style});\n border-width: var(--#{$fa-css-prefix}-border-width, #{$fa-border-width});\n padding: var(--#{$fa-css-prefix}-border-padding, #{$fa-border-padding});\n}\n\n.#{$fa-css-prefix}-pull-left {\n float: left;\n margin-right: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin}); \n}\n\n.#{$fa-css-prefix}-pull-right {\n float: right;\n margin-left: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin}); \n}\n","// animating icons\n// --------------------------\n\n.#{$fa-css-prefix}-beat {\n animation-name: #{$fa-css-prefix}-beat;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);\n}\n\n.#{$fa-css-prefix}-bounce {\n animation-name: #{$fa-css-prefix}-bounce;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(0.280, 0.840, 0.420, 1));\n}\n\n.#{$fa-css-prefix}-fade {\n animation-name: #{$fa-css-prefix}-fade;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));\n}\n\n.#{$fa-css-prefix}-beat-fade {\n animation-name: #{$fa-css-prefix}-beat-fade;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));\n}\n\n.#{$fa-css-prefix}-flip {\n animation-name: #{$fa-css-prefix}-flip;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);\n}\n\n.#{$fa-css-prefix}-shake {\n animation-name: #{$fa-css-prefix}-shake;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);\n}\n\n.#{$fa-css-prefix}-spin {\n animation-name: #{$fa-css-prefix}-spin;\n animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0s);\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 2s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);\n}\n\n.#{$fa-css-prefix}-spin-reverse {\n --#{$fa-css-prefix}-animation-direction: reverse;\n}\n\n.#{$fa-css-prefix}-pulse,\n.#{$fa-css-prefix}-spin-pulse {\n animation-name: #{$fa-css-prefix}-spin;\n animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);\n animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);\n animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);\n animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, steps(8));\n}\n\n// if agent or operating system prefers reduced motion, disable animations\n// see: https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/\n// see: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion\n@media (prefers-reduced-motion: reduce) {\n .#{$fa-css-prefix}-beat,\n .#{$fa-css-prefix}-bounce,\n .#{$fa-css-prefix}-fade,\n .#{$fa-css-prefix}-beat-fade,\n .#{$fa-css-prefix}-flip,\n .#{$fa-css-prefix}-pulse,\n .#{$fa-css-prefix}-shake,\n .#{$fa-css-prefix}-spin,\n .#{$fa-css-prefix}-spin-pulse {\n animation-delay: -1ms;\n animation-duration: 1ms;\n animation-iteration-count: 1;\n transition-delay: 0s;\n transition-duration: 0s;\n }\n}\n\n@keyframes #{$fa-css-prefix}-beat {\n 0%, 90% { transform: scale(1); }\n 45% { transform: scale(var(--#{$fa-css-prefix}-beat-scale, 1.25)); }\n}\n\n@keyframes #{$fa-css-prefix}-bounce {\n 0% { transform: scale(1,1) translateY(0); }\n 10% { transform: scale(var(--#{$fa-css-prefix}-bounce-start-scale-x, 1.1),var(--#{$fa-css-prefix}-bounce-start-scale-y, 0.9)) translateY(0); }\n 30% { transform: scale(var(--#{$fa-css-prefix}-bounce-jump-scale-x, 0.9),var(--#{$fa-css-prefix}-bounce-jump-scale-y, 1.1)) translateY(var(--#{$fa-css-prefix}-bounce-height, -0.5em)); }\n 50% { transform: scale(var(--#{$fa-css-prefix}-bounce-land-scale-x, 1.05),var(--#{$fa-css-prefix}-bounce-land-scale-y, 0.95)) translateY(0); }\n 57% { transform: scale(1,1) translateY(var(--#{$fa-css-prefix}-bounce-rebound, -0.125em)); }\n 64% { transform: scale(1,1) translateY(0); }\n 100% { transform: scale(1,1) translateY(0); }\n}\n\n@keyframes #{$fa-css-prefix}-fade {\n 50% { opacity: var(--#{$fa-css-prefix}-fade-opacity, 0.4); }\n}\n\n@keyframes #{$fa-css-prefix}-beat-fade {\n 0%, 100% {\n opacity: var(--#{$fa-css-prefix}-beat-fade-opacity, 0.4);\n transform: scale(1);\n }\n 50% {\n opacity: 1;\n transform: scale(var(--#{$fa-css-prefix}-beat-fade-scale, 1.125));\n }\n}\n\n@keyframes #{$fa-css-prefix}-flip {\n 50% {\n transform: rotate3d(var(--#{$fa-css-prefix}-flip-x, 0), var(--#{$fa-css-prefix}-flip-y, 1), var(--#{$fa-css-prefix}-flip-z, 0), var(--#{$fa-css-prefix}-flip-angle, -180deg));\n }\n}\n\n@keyframes #{$fa-css-prefix}-shake {\n 0% { transform: rotate(-15deg); }\n 4% { transform: rotate(15deg); }\n 8%, 24% { transform: rotate(-18deg); }\n 12%, 28% { transform: rotate(18deg); }\n 16% { transform: rotate(-22deg); }\n 20% { transform: rotate(22deg); }\n 32% { transform: rotate(-12deg); }\n 36% { transform: rotate(12deg); }\n 40%, 100% { transform: rotate(0deg); }\n}\n\n@keyframes #{$fa-css-prefix}-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n","// rotating + flipping icons\n// -------------------------\n\n.#{$fa-css-prefix}-rotate-90 {\n transform: rotate(90deg);\n}\n\n.#{$fa-css-prefix}-rotate-180 {\n transform: rotate(180deg);\n}\n\n.#{$fa-css-prefix}-rotate-270 {\n transform: rotate(270deg);\n}\n\n.#{$fa-css-prefix}-flip-horizontal {\n transform: scale(-1, 1);\n}\n\n.#{$fa-css-prefix}-flip-vertical {\n transform: scale(1, -1);\n}\n\n.#{$fa-css-prefix}-flip-both,\n.#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical {\n transform: scale(-1, -1);\n}\n\n.#{$fa-css-prefix}-rotate-by {\n transform: rotate(var(--#{$fa-css-prefix}-rotate-angle, 0));\n}\n","// stacking icons\n// -------------------------\n\n.#{$fa-css-prefix}-stack {\n display: inline-block;\n height: 2em;\n line-height: 2em;\n position: relative;\n vertical-align: $fa-stack-vertical-align;\n width: $fa-stack-width;\n}\n\n.#{$fa-css-prefix}-stack-1x,\n.#{$fa-css-prefix}-stack-2x {\n left: 0;\n position: absolute;\n text-align: center;\n width: 100%;\n z-index: var(--#{$fa-css-prefix}-stack-z-index, #{$fa-stack-z-index});\n}\n\n.#{$fa-css-prefix}-stack-1x {\n line-height: inherit;\n}\n\n.#{$fa-css-prefix}-stack-2x {\n font-size: 2em;\n}\n\n.#{$fa-css-prefix}-inverse {\n color: var(--#{$fa-css-prefix}-inverse, #{$fa-inverse});\n}\n","// specific icon class definition\n// -------------------------\n\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\nreaders do not read off random characters that represent icons */\n\n@each $name, $icon in $fa-icons {\n .#{$fa-css-prefix}-#{$name} {\n #{$fa-icon-property}: unquote(\"\\\"#{ $icon }\\\"\");\n #{$fa-duotone-icon-property}: unquote(\"\\\"#{$icon}#{$icon}\\\"\");\n }\n}\n\n","// screen-reader utilities\n// -------------------------\n\n// only display content to screen readers\n.sr-only,\n.#{$fa-css-prefix}-sr-only {\n @include fa-sr-only;\n}\n\n// use in conjunction with .sr-only to only display content when it's focused\n.sr-only-focusable,\n.#{$fa-css-prefix}-sr-only-focusable {\n @include fa-sr-only-focusable;\n}\n","/*!\n * Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)\n * Copyright 2024 Fonticons, Inc.\n */\n@import 'functions';\n@import 'variables';\n\n:root, :host {\n --#{$fa-css-prefix}-style-family-classic: '#{ $fa-style-family }';\n --#{$fa-css-prefix}-font-solid: normal 900 1em/1 '#{ $fa-style-family }';\n}\n\n\n@font-face {\n font-family: 'Font Awesome 6 Free';\n font-style: normal;\n font-weight: 900;\n font-display: $fa-font-display;\n src: url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),\n url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype');\n}\n\n.fas,\n.#{$fa-css-prefix}-solid {\n font-weight: 900;\n}\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/.extlib/simplesamlphp/public/assets/base/fonts/fa-solid-900.ttf b/.extlib/simplesamlphp/public/assets/base/fonts/fa-solid-900.ttf index e7e2ecfa341157f2a42ec210bf82cc0156a5540b..f3b468e5b25582f4c0042e950826284ab9b708d9 100644 GIT binary patch delta 19382 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 delta 17240 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

    jwicFM;mt~nKS6zuK0vKlD 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

    8BC^!BI#_0UW9ia1p5G*c|qTx5tf3z)F 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[$endpointType]; - Assert::isArray($eps, Error\CriticalConfigurationError::class); + if (!is_array($eps)) { + $filename = explode('/', $loc)[0]; + throw new Error\CriticalConfigurationError( + "Endpoint of type $endpointType is not an array in $loc.", + $filename, + ); + } $eps_count = count($eps); diff --git a/.extlib/simplesamlphp/src/SimpleSAML/Locale/Language.php b/.extlib/simplesamlphp/src/SimpleSAML/Locale/Language.php index 23d247165..b4e295257 100644 --- a/.extlib/simplesamlphp/src/SimpleSAML/Locale/Language.php +++ b/.extlib/simplesamlphp/src/SimpleSAML/Locale/Language.php @@ -172,7 +172,7 @@ private function getInstalledLanguages(): array ); // @deprecated - remove entire if-block in a new major release - if (array_intersect(['pt-br', 'st', 'zh-tw'], $configuredAvailableLanguages)) { + if (array_intersect(['pt-br', 'zh-tw'], $configuredAvailableLanguages)) { Logger::warning( "Deprecated locales found in `language.available`. " . "Please replace 'pt-br' with 'pt_BR'," diff --git a/.extlib/simplesamlphp/src/SimpleSAML/Session.php b/.extlib/simplesamlphp/src/SimpleSAML/Session.php index f79dec9fd..51f6e4f16 100644 --- a/.extlib/simplesamlphp/src/SimpleSAML/Session.php +++ b/.extlib/simplesamlphp/src/SimpleSAML/Session.php @@ -154,14 +154,6 @@ private function __construct(bool $transient = false) { $this->setConfiguration(Configuration::getInstance()); - // Moodle custom: Try saving session BEFORE $DB gets destroyed. The __destructor() call to save will be clean. - \core_shutdown_manager::register_function( - function($session) { - $session->save(); - }, - [$this] - ); - if (php_sapi_name() === 'cli' || defined('STDIN')) { $this->trackid = 'CL' . bin2hex(openssl_random_pseudo_bytes(4)); Logger::setTrackId($this->trackid); @@ -508,10 +500,6 @@ public function markDirty(): void $this->dirty = true; - // Moodle auth_saml2 hack, because we register a shutdown handler in - // moodle in the constructor we don't need to register a callback here. - return; - if ($this->callback_registered) { // we already have a shutdown callback registered for this object, no need to add another one return; @@ -528,9 +516,7 @@ public function markDirty(): void */ public function __destruct() { - // Moodle auth_saml2 hack, we don't need to save here because we have - // a custom shutdown handle registered with moodle. - // $this->save(); + $this->save(); } diff --git a/.extlib/simplesamlphp/src/SimpleSAML/Utils/HTTP.php b/.extlib/simplesamlphp/src/SimpleSAML/Utils/HTTP.php index 11eaa082b..82ff4ea8d 100644 --- a/.extlib/simplesamlphp/src/SimpleSAML/Utils/HTTP.php +++ b/.extlib/simplesamlphp/src/SimpleSAML/Utils/HTTP.php @@ -956,13 +956,6 @@ public function parseQueryString(string $query_string): array public function redirectTrustedURL(string $url, array $parameters = []): void { $url = $this->normalizeURL($url); - - // This is a Moodle hack. Both moodle and SSPHP rely on automatic - // destructors to cleanup the $DB var and the SSPHP session but - // this order is not guaranteed, so we force session saving here. - $session = \SimpleSAML\Session::getSessionFromRequest(); - $session->save(); - $this->redirect($url, $parameters); } diff --git a/.extlib/simplesamlphp/templates/post.twig b/.extlib/simplesamlphp/templates/post.twig index 614d79944..5072e8dda 100644 --- a/.extlib/simplesamlphp/templates/post.twig +++ b/.extlib/simplesamlphp/templates/post.twig @@ -6,8 +6,8 @@ {% trans %}Sending message{% endtrans %} - - + +

    diff --git a/.extlib/simplesamlphp/vendor/autoload.php b/.extlib/simplesamlphp/vendor/autoload.php index 14b40e3e6..c8708a09e 100644 --- a/.extlib/simplesamlphp/vendor/autoload.php +++ b/.extlib/simplesamlphp/vendor/autoload.php @@ -22,4 +22,4 @@ require_once __DIR__ . '/composer/autoload_real.php'; -return ComposerAutoloaderInitd92254016c92c1549c1187a87107524d::getLoader(); +return ComposerAutoloaderIniteb8044a5f31df9017f83ac696a2e46a4::getLoader(); diff --git a/.extlib/simplesamlphp/vendor/bin/export-plural-rules b/.extlib/simplesamlphp/vendor/bin/export-plural-rules old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/bin/patch-type-declarations b/.extlib/simplesamlphp/vendor/bin/patch-type-declarations old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/bin/php-parse b/.extlib/simplesamlphp/vendor/bin/php-parse new file mode 100644 index 000000000..61566e60c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/php-parse @@ -0,0 +1,119 @@ +#!/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__ . '/..'.'/nikic/php-parser/bin/php-parse'); + } +} + +return include __DIR__ . '/..'.'/nikic/php-parser/bin/php-parse'; diff --git a/.extlib/simplesamlphp/vendor/bin/phpcbf b/.extlib/simplesamlphp/vendor/bin/phpcbf new file mode 100644 index 000000000..1c0c79c40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/phpcbf @@ -0,0 +1,119 @@ +#!/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/bin/phpcbf'); + } +} + +return include __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcbf'; diff --git a/.extlib/simplesamlphp/vendor/bin/phpcs b/.extlib/simplesamlphp/vendor/bin/phpcs new file mode 100644 index 000000000..04e658cf9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/phpcs @@ -0,0 +1,119 @@ +#!/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/bin/phpcs'); + } +} + +return include __DIR__ . '/..'.'/squizlabs/php_codesniffer/bin/phpcs'; diff --git a/.extlib/simplesamlphp/vendor/bin/phpstan b/.extlib/simplesamlphp/vendor/bin/phpstan new file mode 100644 index 000000000..d76c0be76 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/phpstan @@ -0,0 +1,119 @@ +#!/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__ . '/..'.'/phpstan/phpstan/phpstan'); + } +} + +return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan'; diff --git a/.extlib/simplesamlphp/vendor/bin/phpstan.phar b/.extlib/simplesamlphp/vendor/bin/phpstan.phar new file mode 100644 index 000000000..fecf96f69 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/phpstan.phar @@ -0,0 +1,119 @@ +#!/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__ . '/..'.'/phpstan/phpstan/phpstan.phar'); + } +} + +return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar'; diff --git a/.extlib/simplesamlphp/vendor/bin/phpunit b/.extlib/simplesamlphp/vendor/bin/phpunit new file mode 100644 index 000000000..b5b530a8f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/phpunit @@ -0,0 +1,122 @@ +#!/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/.extlib/simplesamlphp/vendor/bin/simple-phpunit b/.extlib/simplesamlphp/vendor/bin/simple-phpunit new file mode 100644 index 000000000..b79ecf361 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/bin/simple-phpunit @@ -0,0 +1,119 @@ +#!/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__ . '/..'.'/symfony/phpunit-bridge/bin/simple-phpunit'); + } +} + +return include __DIR__ . '/..'.'/symfony/phpunit-bridge/bin/simple-phpunit'; diff --git a/.extlib/simplesamlphp/vendor/bin/var-dump-server b/.extlib/simplesamlphp/vendor/bin/var-dump-server old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/bin/yaml-lint b/.extlib/simplesamlphp/vendor/bin/yaml-lint old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/composer/autoload_classmap.php b/.extlib/simplesamlphp/vendor/composer/autoload_classmap.php index a7acf51e6..b35cb9ef9 100644 --- a/.extlib/simplesamlphp/vendor/composer/autoload_classmap.php +++ b/.extlib/simplesamlphp/vendor/composer/autoload_classmap.php @@ -23,7 +23,1166 @@ 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'NumberFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php', 'Override' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/Override.php', + 'PHPUnit\\Event\\Application\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/Finished.php', + 'PHPUnit\\Event\\Application\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php', + 'PHPUnit\\Event\\Application\\Started' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/Started.php', + 'PHPUnit\\Event\\Application\\StartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php', + 'PHPUnit\\Event\\Code\\ClassMethod' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ClassMethod.php', + 'PHPUnit\\Event\\Code\\ComparisonFailure' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ComparisonFailure.php', + 'PHPUnit\\Event\\Code\\ComparisonFailureBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php', + 'PHPUnit\\Event\\Code\\NoTestCaseObjectOnCallStackException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php', + 'PHPUnit\\Event\\Code\\Phpt' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/Phpt.php', + 'PHPUnit\\Event\\Code\\Test' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/Test.php', + 'PHPUnit\\Event\\Code\\TestCollection' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestCollection.php', + 'PHPUnit\\Event\\Code\\TestCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php', + 'PHPUnit\\Event\\Code\\TestDox' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestDox.php', + 'PHPUnit\\Event\\Code\\TestDoxBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php', + 'PHPUnit\\Event\\Code\\TestMethod' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestMethod.php', + 'PHPUnit\\Event\\Code\\TestMethodBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php', + 'PHPUnit\\Event\\Code\\Throwable' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Throwable.php', + 'PHPUnit\\Event\\Code\\ThrowableBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php', + 'PHPUnit\\Event\\CollectingDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php', + 'PHPUnit\\Event\\DeferringDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php', + 'PHPUnit\\Event\\DirectDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php', + 'PHPUnit\\Event\\Dispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php', + 'PHPUnit\\Event\\DispatchingEmitter' => $vendorDir . '/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php', + 'PHPUnit\\Event\\Emitter' => $vendorDir . '/phpunit/phpunit/src/Event/Emitter/Emitter.php', + 'PHPUnit\\Event\\Event' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Event.php', + 'PHPUnit\\Event\\EventAlreadyAssignedException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php', + 'PHPUnit\\Event\\EventCollection' => $vendorDir . '/phpunit/phpunit/src/Event/Events/EventCollection.php', + 'PHPUnit\\Event\\EventCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php', + 'PHPUnit\\Event\\EventFacadeIsSealedException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php', + 'PHPUnit\\Event\\Exception' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/Exception.php', + 'PHPUnit\\Event\\Facade' => $vendorDir . '/phpunit/phpunit/src/Event/Facade.php', + 'PHPUnit\\Event\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php', + 'PHPUnit\\Event\\InvalidEventException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/InvalidEventException.php', + 'PHPUnit\\Event\\InvalidSubscriberException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php', + 'PHPUnit\\Event\\MapError' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/MapError.php', + 'PHPUnit\\Event\\NoPreviousThrowableException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php', + 'PHPUnit\\Event\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/RuntimeException.php', + 'PHPUnit\\Event\\Runtime\\OperatingSystem' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php', + 'PHPUnit\\Event\\Runtime\\PHP' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/PHP.php', + 'PHPUnit\\Event\\Runtime\\PHPUnit' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php', + 'PHPUnit\\Event\\Runtime\\Runtime' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php', + 'PHPUnit\\Event\\SubscribableDispatcher' => $vendorDir . '/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php', + 'PHPUnit\\Event\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Subscriber.php', + 'PHPUnit\\Event\\SubscriberTypeAlreadyRegisteredException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php', + 'PHPUnit\\Event\\Telemetry\\Duration' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php', + 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatus' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php', + 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatusProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php', + 'PHPUnit\\Event\\Telemetry\\HRTime' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php', + 'PHPUnit\\Event\\Telemetry\\Info' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Info.php', + 'PHPUnit\\Event\\Telemetry\\MemoryMeter' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php', + 'PHPUnit\\Event\\Telemetry\\MemoryUsage' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php', + 'PHPUnit\\Event\\Telemetry\\Php81GarbageCollectorStatusProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php', + 'PHPUnit\\Event\\Telemetry\\Php83GarbageCollectorStatusProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php', + 'PHPUnit\\Event\\Telemetry\\Snapshot' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php', + 'PHPUnit\\Event\\Telemetry\\StopWatch' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php', + 'PHPUnit\\Event\\Telemetry\\System' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/System.php', + 'PHPUnit\\Event\\Telemetry\\SystemMemoryMeter' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php', + 'PHPUnit\\Event\\Telemetry\\SystemStopWatch' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php', + 'PHPUnit\\Event\\Telemetry\\SystemStopWatchWithOffset' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php', + 'PHPUnit\\Event\\TestData\\DataFromDataProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php', + 'PHPUnit\\Event\\TestData\\DataFromTestDependency' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php', + 'PHPUnit\\Event\\TestData\\MoreThanOneDataSetFromDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php', + 'PHPUnit\\Event\\TestData\\NoDataSetFromDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php', + 'PHPUnit\\Event\\TestData\\TestData' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php', + 'PHPUnit\\Event\\TestData\\TestDataCollection' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php', + 'PHPUnit\\Event\\TestData\\TestDataCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php', + 'PHPUnit\\Event\\TestRunner\\BootstrapFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php', + 'PHPUnit\\Event\\TestRunner\\BootstrapFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\Configured' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php', + 'PHPUnit\\Event\\TestRunner\\ConfiguredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\DeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php', + 'PHPUnit\\Event\\TestRunner\\DeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\EventFacadeSealed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php', + 'PHPUnit\\Event\\TestRunner\\EventFacadeSealedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionAborted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionAbortedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionStarted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrapped' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrappedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPhar' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPharSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php', + 'PHPUnit\\Event\\TestRunner\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\Started' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/Started.php', + 'PHPUnit\\Event\\TestRunner\\StartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\WarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php', + 'PHPUnit\\Event\\TestRunner\\WarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Filtered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php', + 'PHPUnit\\Event\\TestSuite\\FilteredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php', + 'PHPUnit\\Event\\TestSuite\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Loaded' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php', + 'PHPUnit\\Event\\TestSuite\\LoadedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Skipped' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php', + 'PHPUnit\\Event\\TestSuite\\SkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Sorted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php', + 'PHPUnit\\Event\\TestSuite\\SortedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Started' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/Started.php', + 'PHPUnit\\Event\\TestSuite\\StartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteBuilder' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestClass' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestMethodWithDataProvider' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteWithName' => $vendorDir . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\AssertionFailed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php', + 'PHPUnit\\Event\\Test\\AssertionFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php', + 'PHPUnit\\Event\\Test\\AssertionSucceeded' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php', + 'PHPUnit\\Event\\Test\\AssertionSucceededSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErrored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\ComparatorRegistered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php', + 'PHPUnit\\Event\\Test\\ComparatorRegisteredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php', + 'PHPUnit\\Event\\Test\\ConsideredRisky' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php', + 'PHPUnit\\Event\\Test\\ConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\DeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php', + 'PHPUnit\\Event\\Test\\DeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\ErrorTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php', + 'PHPUnit\\Event\\Test\\ErrorTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\Errored' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php', + 'PHPUnit\\Event\\Test\\ErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php', + 'PHPUnit\\Event\\Test\\Failed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php', + 'PHPUnit\\Event\\Test\\FailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php', + 'PHPUnit\\Event\\Test\\Finished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php', + 'PHPUnit\\Event\\Test\\FinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\MarkedIncomplete' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php', + 'PHPUnit\\Event\\Test\\MarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectForTraitCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectForTraitCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\NoComparisonFailureException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php', + 'PHPUnit\\Event\\Test\\NoticeTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php', + 'PHPUnit\\Event\\Test\\NoticeTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PartialMockObjectCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php', + 'PHPUnit\\Event\\Test\\PartialMockObjectCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\Passed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php', + 'PHPUnit\\Event\\Test\\PassedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpDeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php', + 'PHPUnit\\Event\\Test\\PhpDeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpNoticeTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php', + 'PHPUnit\\Event\\Test\\PhpNoticeTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpWarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php', + 'PHPUnit\\Event\\Test\\PhpWarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php', + 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpunitErrorTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php', + 'PHPUnit\\Event\\Test\\PhpunitErrorTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpunitWarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php', + 'PHPUnit\\Event\\Test\\PhpunitWarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PostConditionCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php', + 'PHPUnit\\Event\\Test\\PostConditionCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\PostConditionFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php', + 'PHPUnit\\Event\\Test\\PostConditionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\PreConditionCalled' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php', + 'PHPUnit\\Event\\Test\\PreConditionCalledSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\PreConditionFinished' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php', + 'PHPUnit\\Event\\Test\\PreConditionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\PreparationFailed' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php', + 'PHPUnit\\Event\\Test\\PreparationFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php', + 'PHPUnit\\Event\\Test\\PreparationStarted' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php', + 'PHPUnit\\Event\\Test\\PreparationStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php', + 'PHPUnit\\Event\\Test\\Prepared' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php', + 'PHPUnit\\Event\\Test\\PreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php', + 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutput' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php', + 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutputSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php', + 'PHPUnit\\Event\\Test\\Skipped' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php', + 'PHPUnit\\Event\\Test\\SkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php', + 'PHPUnit\\Event\\Test\\TestProxyCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php', + 'PHPUnit\\Event\\Test\\TestProxyCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\TestStubCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php', + 'PHPUnit\\Event\\Test\\TestStubCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreated' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php', + 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreatedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\WarningTriggered' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php', + 'PHPUnit\\Event\\Test\\WarningTriggeredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\Tracer\\Tracer' => $vendorDir . '/phpunit/phpunit/src/Event/Tracer.php', + 'PHPUnit\\Event\\TypeMap' => $vendorDir . '/phpunit/phpunit/src/Event/TypeMap.php', + 'PHPUnit\\Event\\UnknownEventException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownEventException.php', + 'PHPUnit\\Event\\UnknownEventTypeException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php', + 'PHPUnit\\Event\\UnknownSubscriberException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php', + 'PHPUnit\\Event\\UnknownSubscriberTypeException' => $vendorDir . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php', + 'PHPUnit\\Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php', + 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php', + 'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php', + 'PHPUnit\\Framework\\AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php', + 'PHPUnit\\Framework\\Attributes\\After' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/After.php', + 'PHPUnit\\Framework\\Attributes\\AfterClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/AfterClass.php', + 'PHPUnit\\Framework\\Attributes\\BackupGlobals' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php', + 'PHPUnit\\Framework\\Attributes\\BackupStaticProperties' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php', + 'PHPUnit\\Framework\\Attributes\\Before' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Before.php', + 'PHPUnit\\Framework\\Attributes\\BeforeClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php', + 'PHPUnit\\Framework\\Attributes\\CodeCoverageIgnore' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php', + 'PHPUnit\\Framework\\Attributes\\CoversClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CoversClass.php', + 'PHPUnit\\Framework\\Attributes\\CoversFunction' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php', + 'PHPUnit\\Framework\\Attributes\\CoversNothing' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php', + 'PHPUnit\\Framework\\Attributes\\DataProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DataProvider.php', + 'PHPUnit\\Framework\\Attributes\\DataProviderExternal' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php', + 'PHPUnit\\Framework\\Attributes\\Depends' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Depends.php', + 'PHPUnit\\Framework\\Attributes\\DependsExternal' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php', + 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingDeepClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingShallowClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsOnClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php', + 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingDeepClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingShallowClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsUsingDeepClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsUsingShallowClone' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php', + 'PHPUnit\\Framework\\Attributes\\DoesNotPerformAssertions' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php', + 'PHPUnit\\Framework\\Attributes\\ExcludeGlobalVariableFromBackup' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php', + 'PHPUnit\\Framework\\Attributes\\ExcludeStaticPropertyFromBackup' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php', + 'PHPUnit\\Framework\\Attributes\\Group' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Group.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreClassForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreDeprecations' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreFunctionForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreMethodForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php', + 'PHPUnit\\Framework\\Attributes\\Large' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Large.php', + 'PHPUnit\\Framework\\Attributes\\Medium' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Medium.php', + 'PHPUnit\\Framework\\Attributes\\PostCondition' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/PostCondition.php', + 'PHPUnit\\Framework\\Attributes\\PreCondition' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/PreCondition.php', + 'PHPUnit\\Framework\\Attributes\\PreserveGlobalState' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php', + 'PHPUnit\\Framework\\Attributes\\RequiresFunction' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php', + 'PHPUnit\\Framework\\Attributes\\RequiresMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php', + 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystem' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php', + 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystemFamily' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php', + 'PHPUnit\\Framework\\Attributes\\RequiresPhp' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php', + 'PHPUnit\\Framework\\Attributes\\RequiresPhpExtension' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php', + 'PHPUnit\\Framework\\Attributes\\RequiresPhpunit' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php', + 'PHPUnit\\Framework\\Attributes\\RequiresSetting' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php', + 'PHPUnit\\Framework\\Attributes\\RunClassInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php', + 'PHPUnit\\Framework\\Attributes\\RunInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php', + 'PHPUnit\\Framework\\Attributes\\RunTestsInSeparateProcesses' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php', + 'PHPUnit\\Framework\\Attributes\\Small' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Small.php', + 'PHPUnit\\Framework\\Attributes\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Test.php', + 'PHPUnit\\Framework\\Attributes\\TestDox' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/TestDox.php', + 'PHPUnit\\Framework\\Attributes\\TestWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/TestWith.php', + 'PHPUnit\\Framework\\Attributes\\TestWithJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php', + 'PHPUnit\\Framework\\Attributes\\Ticket' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/Ticket.php', + 'PHPUnit\\Framework\\Attributes\\UsesClass' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/UsesClass.php', + 'PHPUnit\\Framework\\Attributes\\UsesFunction' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php', + 'PHPUnit\\Framework\\Attributes\\WithoutErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php', + 'PHPUnit\\Framework\\CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php', + 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php', + 'PHPUnit\\Framework\\Constraint\\BinaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php', + 'PHPUnit\\Framework\\Constraint\\Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', + 'PHPUnit\\Framework\\Constraint\\Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php', + 'PHPUnit\\Framework\\Constraint\\Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php', + 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php', + 'PHPUnit\\Framework\\Constraint\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessageIsOrContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessageMatchesRegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php', + 'PHPUnit\\Framework\\Constraint\\GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php', + 'PHPUnit\\Framework\\Constraint\\IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', + 'PHPUnit\\Framework\\Constraint\\IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php', + 'PHPUnit\\Framework\\Constraint\\IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php', + 'PHPUnit\\Framework\\Constraint\\IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php', + 'PHPUnit\\Framework\\Constraint\\IsFinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php', + 'PHPUnit\\Framework\\Constraint\\IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\IsInfinite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php', + 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php', + 'PHPUnit\\Framework\\Constraint\\IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php', + 'PHPUnit\\Framework\\Constraint\\IsList' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php', + 'PHPUnit\\Framework\\Constraint\\IsNan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php', + 'PHPUnit\\Framework\\Constraint\\IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php', + 'PHPUnit\\Framework\\Constraint\\IsReadable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php', + 'PHPUnit\\Framework\\Constraint\\IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php', + 'PHPUnit\\Framework\\Constraint\\IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php', + 'PHPUnit\\Framework\\Constraint\\IsWritable' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php', + 'PHPUnit\\Framework\\Constraint\\JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', + 'PHPUnit\\Framework\\Constraint\\LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php', + 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php', + 'PHPUnit\\Framework\\Constraint\\LogicalNot' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php', + 'PHPUnit\\Framework\\Constraint\\LogicalOr' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php', + 'PHPUnit\\Framework\\Constraint\\LogicalXor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php', + 'PHPUnit\\Framework\\Constraint\\ObjectEquals' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php', + 'PHPUnit\\Framework\\Constraint\\ObjectHasProperty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php', + 'PHPUnit\\Framework\\Constraint\\Operator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php', + 'PHPUnit\\Framework\\Constraint\\RegularExpression' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php', + 'PHPUnit\\Framework\\Constraint\\StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php', + 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php', + 'PHPUnit\\Framework\\Constraint\\StringEqualsStringIgnoringLineEndings' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php', + 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php', + 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php', + 'PHPUnit\\Framework\\Constraint\\UnaryOperator' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php', + 'PHPUnit\\Framework\\DataProviderTestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php', + 'PHPUnit\\Framework\\EmptyStringException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php', + 'PHPUnit\\Framework\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Exception.php', + 'PHPUnit\\Framework\\ExecutionOrderDependency' => $vendorDir . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php', + 'PHPUnit\\Framework\\ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php', + 'PHPUnit\\Framework\\GeneratorNotSupportedException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php', + 'PHPUnit\\Framework\\IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php', + 'PHPUnit\\Framework\\IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php', + 'PHPUnit\\Framework\\InvalidArgumentException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php', + 'PHPUnit\\Framework\\InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php', + 'PHPUnit\\Framework\\InvalidDataProviderException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php', + 'PHPUnit\\Framework\\InvalidDependencyException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php', + 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php', + 'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php', + 'PHPUnit\\Framework\\MockObject\\DoubledCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php', + 'PHPUnit\\Framework\\MockObject\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\CannotUseAddMethodsException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsEnumerationException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsFinalException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsReadonlyException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\DuplicateMethodException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\Generator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\InvalidMethodNameException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockClass' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethodSet' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockTrait' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockType' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\NameAlreadyInUseException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\OriginalConstructorInvocationRequiredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\SoapExtensionNotAvailableException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\TemplateLoader' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownClassException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTraitException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php', + 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php', + 'PHPUnit\\Framework\\MockObject\\Invocation' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php', + 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php', + 'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php', + 'PHPUnit\\Framework\\MockObject\\Matcher' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php', + 'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php', + 'PHPUnit\\Framework\\MockObject\\Method' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php', + 'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MockBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php', + 'PHPUnit\\Framework\\MockObject\\MockObject' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php', + 'PHPUnit\\Framework\\MockObject\\MockObjectApi' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php', + 'PHPUnit\\Framework\\MockObject\\MockObjectInternal' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php', + 'PHPUnit\\Framework\\MockObject\\NeverReturningMethodException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php', + 'PHPUnit\\Framework\\MockObject\\NoMoreReturnValuesConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\ProxiedCloneMethod' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php', + 'PHPUnit\\Framework\\MockObject\\ReturnValueGenerator' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php', + 'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php', + 'PHPUnit\\Framework\\MockObject\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php', + 'PHPUnit\\Framework\\MockObject\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php', + 'PHPUnit\\Framework\\MockObject\\StubApi' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php', + 'PHPUnit\\Framework\\MockObject\\StubInternal' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => $vendorDir . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php', + 'PHPUnit\\Framework\\NoChildTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php', + 'PHPUnit\\Framework\\PhptAssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php', + 'PHPUnit\\Framework\\ProcessIsolationException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php', + 'PHPUnit\\Framework\\Reorderable' => $vendorDir . '/phpunit/phpunit/src/Framework/Reorderable.php', + 'PHPUnit\\Framework\\SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php', + 'PHPUnit\\Framework\\SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php', + 'PHPUnit\\Framework\\SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php', + 'PHPUnit\\Framework\\SkippedWithMessageException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php', + 'PHPUnit\\Framework\\Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php', + 'PHPUnit\\Framework\\TestBuilder' => $vendorDir . '/phpunit/phpunit/src/Framework/TestBuilder.php', + 'PHPUnit\\Framework\\TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php', + 'PHPUnit\\Framework\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/Framework/TestRunner.php', + 'PHPUnit\\Framework\\TestSize\\Known' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Known.php', + 'PHPUnit\\Framework\\TestSize\\Large' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Large.php', + 'PHPUnit\\Framework\\TestSize\\Medium' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Medium.php', + 'PHPUnit\\Framework\\TestSize\\Small' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Small.php', + 'PHPUnit\\Framework\\TestSize\\TestSize' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/TestSize.php', + 'PHPUnit\\Framework\\TestSize\\Unknown' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSize/Unknown.php', + 'PHPUnit\\Framework\\TestStatus\\Deprecation' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php', + 'PHPUnit\\Framework\\TestStatus\\Error' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Error.php', + 'PHPUnit\\Framework\\TestStatus\\Failure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Failure.php', + 'PHPUnit\\Framework\\TestStatus\\Incomplete' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php', + 'PHPUnit\\Framework\\TestStatus\\Known' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Known.php', + 'PHPUnit\\Framework\\TestStatus\\Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Notice.php', + 'PHPUnit\\Framework\\TestStatus\\Risky' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Risky.php', + 'PHPUnit\\Framework\\TestStatus\\Skipped' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Skipped.php', + 'PHPUnit\\Framework\\TestStatus\\Success' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Success.php', + 'PHPUnit\\Framework\\TestStatus\\TestStatus' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php', + 'PHPUnit\\Framework\\TestStatus\\Unknown' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Unknown.php', + 'PHPUnit\\Framework\\TestStatus\\Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/TestStatus/Warning.php', + 'PHPUnit\\Framework\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php', + 'PHPUnit\\Framework\\TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php', + 'PHPUnit\\Framework\\UnknownClassOrInterfaceException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php', + 'PHPUnit\\Framework\\UnknownTypeException' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php', + 'PHPUnit\\Logging\\EventLogger' => $vendorDir . '/phpunit/phpunit/src/Logging/EventLogger.php', + 'PHPUnit\\Logging\\JUnit\\JunitXmlLogger' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php', + 'PHPUnit\\Logging\\JUnit\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestPreparationFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestPreparationStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestRunnerExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TeamCityLogger' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php', + 'PHPUnit\\Logging\\TeamCity\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestRunnerExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\HtmlRenderer' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php', + 'PHPUnit\\Logging\\TestDox\\NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php', + 'PHPUnit\\Logging\\TestDox\\PlainTextRenderer' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php', + 'PHPUnit\\Logging\\TestDox\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestPassedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php', + 'PHPUnit\\Logging\\TestDox\\TestResultCollection' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php', + 'PHPUnit\\Logging\\TestDox\\TestResultCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php', + 'PHPUnit\\Logging\\TestDox\\TestResultCollector' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php', + 'PHPUnit\\Logging\\TestDox\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\Metadata\\After' => $vendorDir . '/phpunit/phpunit/src/Metadata/After.php', + 'PHPUnit\\Metadata\\AfterClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/AfterClass.php', + 'PHPUnit\\Metadata\\Annotation\\Parser\\DocBlock' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php', + 'PHPUnit\\Metadata\\Annotation\\Parser\\Registry' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php', + 'PHPUnit\\Metadata\\AnnotationsAreNotSupportedForInternalClassesException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php', + 'PHPUnit\\Metadata\\Api\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php', + 'PHPUnit\\Metadata\\Api\\DataProvider' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/DataProvider.php', + 'PHPUnit\\Metadata\\Api\\Dependencies' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/Dependencies.php', + 'PHPUnit\\Metadata\\Api\\Groups' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/Groups.php', + 'PHPUnit\\Metadata\\Api\\HookMethods' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/HookMethods.php', + 'PHPUnit\\Metadata\\Api\\Requirements' => $vendorDir . '/phpunit/phpunit/src/Metadata/Api/Requirements.php', + 'PHPUnit\\Metadata\\BackupGlobals' => $vendorDir . '/phpunit/phpunit/src/Metadata/BackupGlobals.php', + 'PHPUnit\\Metadata\\BackupStaticProperties' => $vendorDir . '/phpunit/phpunit/src/Metadata/BackupStaticProperties.php', + 'PHPUnit\\Metadata\\Before' => $vendorDir . '/phpunit/phpunit/src/Metadata/Before.php', + 'PHPUnit\\Metadata\\BeforeClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/BeforeClass.php', + 'PHPUnit\\Metadata\\Covers' => $vendorDir . '/phpunit/phpunit/src/Metadata/Covers.php', + 'PHPUnit\\Metadata\\CoversClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversClass.php', + 'PHPUnit\\Metadata\\CoversDefaultClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversDefaultClass.php', + 'PHPUnit\\Metadata\\CoversFunction' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversFunction.php', + 'PHPUnit\\Metadata\\CoversNothing' => $vendorDir . '/phpunit/phpunit/src/Metadata/CoversNothing.php', + 'PHPUnit\\Metadata\\DataProvider' => $vendorDir . '/phpunit/phpunit/src/Metadata/DataProvider.php', + 'PHPUnit\\Metadata\\DependsOnClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/DependsOnClass.php', + 'PHPUnit\\Metadata\\DependsOnMethod' => $vendorDir . '/phpunit/phpunit/src/Metadata/DependsOnMethod.php', + 'PHPUnit\\Metadata\\DoesNotPerformAssertions' => $vendorDir . '/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php', + 'PHPUnit\\Metadata\\Exception' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/Exception.php', + 'PHPUnit\\Metadata\\ExcludeGlobalVariableFromBackup' => $vendorDir . '/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php', + 'PHPUnit\\Metadata\\ExcludeStaticPropertyFromBackup' => $vendorDir . '/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php', + 'PHPUnit\\Metadata\\Group' => $vendorDir . '/phpunit/phpunit/src/Metadata/Group.php', + 'PHPUnit\\Metadata\\IgnoreClassForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php', + 'PHPUnit\\Metadata\\IgnoreDeprecations' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php', + 'PHPUnit\\Metadata\\IgnoreFunctionForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php', + 'PHPUnit\\Metadata\\IgnoreMethodForCodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php', + 'PHPUnit\\Metadata\\InvalidVersionRequirementException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php', + 'PHPUnit\\Metadata\\Metadata' => $vendorDir . '/phpunit/phpunit/src/Metadata/Metadata.php', + 'PHPUnit\\Metadata\\MetadataCollection' => $vendorDir . '/phpunit/phpunit/src/Metadata/MetadataCollection.php', + 'PHPUnit\\Metadata\\MetadataCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php', + 'PHPUnit\\Metadata\\NoVersionRequirementException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php', + 'PHPUnit\\Metadata\\Parser\\AnnotationParser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php', + 'PHPUnit\\Metadata\\Parser\\AttributeParser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php', + 'PHPUnit\\Metadata\\Parser\\CachingParser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/CachingParser.php', + 'PHPUnit\\Metadata\\Parser\\Parser' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Parser.php', + 'PHPUnit\\Metadata\\Parser\\ParserChain' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/ParserChain.php', + 'PHPUnit\\Metadata\\Parser\\Registry' => $vendorDir . '/phpunit/phpunit/src/Metadata/Parser/Registry.php', + 'PHPUnit\\Metadata\\PostCondition' => $vendorDir . '/phpunit/phpunit/src/Metadata/PostCondition.php', + 'PHPUnit\\Metadata\\PreCondition' => $vendorDir . '/phpunit/phpunit/src/Metadata/PreCondition.php', + 'PHPUnit\\Metadata\\PreserveGlobalState' => $vendorDir . '/phpunit/phpunit/src/Metadata/PreserveGlobalState.php', + 'PHPUnit\\Metadata\\ReflectionException' => $vendorDir . '/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php', + 'PHPUnit\\Metadata\\RequiresFunction' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresFunction.php', + 'PHPUnit\\Metadata\\RequiresMethod' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresMethod.php', + 'PHPUnit\\Metadata\\RequiresOperatingSystem' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php', + 'PHPUnit\\Metadata\\RequiresOperatingSystemFamily' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php', + 'PHPUnit\\Metadata\\RequiresPhp' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresPhp.php', + 'PHPUnit\\Metadata\\RequiresPhpExtension' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php', + 'PHPUnit\\Metadata\\RequiresPhpunit' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresPhpunit.php', + 'PHPUnit\\Metadata\\RequiresSetting' => $vendorDir . '/phpunit/phpunit/src/Metadata/RequiresSetting.php', + 'PHPUnit\\Metadata\\RunClassInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php', + 'PHPUnit\\Metadata\\RunInSeparateProcess' => $vendorDir . '/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php', + 'PHPUnit\\Metadata\\RunTestsInSeparateProcesses' => $vendorDir . '/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php', + 'PHPUnit\\Metadata\\Test' => $vendorDir . '/phpunit/phpunit/src/Metadata/Test.php', + 'PHPUnit\\Metadata\\TestDox' => $vendorDir . '/phpunit/phpunit/src/Metadata/TestDox.php', + 'PHPUnit\\Metadata\\TestWith' => $vendorDir . '/phpunit/phpunit/src/Metadata/TestWith.php', + 'PHPUnit\\Metadata\\Uses' => $vendorDir . '/phpunit/phpunit/src/Metadata/Uses.php', + 'PHPUnit\\Metadata\\UsesClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/UsesClass.php', + 'PHPUnit\\Metadata\\UsesDefaultClass' => $vendorDir . '/phpunit/phpunit/src/Metadata/UsesDefaultClass.php', + 'PHPUnit\\Metadata\\UsesFunction' => $vendorDir . '/phpunit/phpunit/src/Metadata/UsesFunction.php', + 'PHPUnit\\Metadata\\Version\\ComparisonRequirement' => $vendorDir . '/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php', + 'PHPUnit\\Metadata\\Version\\ConstraintRequirement' => $vendorDir . '/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php', + 'PHPUnit\\Metadata\\Version\\Requirement' => $vendorDir . '/phpunit/phpunit/src/Metadata/Version/Requirement.php', + 'PHPUnit\\Metadata\\WithoutErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php', + 'PHPUnit\\Runner\\Baseline\\Baseline' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Baseline.php', + 'PHPUnit\\Runner\\Baseline\\CannotLoadBaselineException' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php', + 'PHPUnit\\Runner\\Baseline\\FileDoesNotHaveLineException' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php', + 'PHPUnit\\Runner\\Baseline\\Generator' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Generator.php', + 'PHPUnit\\Runner\\Baseline\\Issue' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Issue.php', + 'PHPUnit\\Runner\\Baseline\\Reader' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Reader.php', + 'PHPUnit\\Runner\\Baseline\\RelativePathCalculator' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php', + 'PHPUnit\\Runner\\Baseline\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\Writer' => $vendorDir . '/phpunit/phpunit/src/Runner/Baseline/Writer.php', + 'PHPUnit\\Runner\\ClassCannotBeFoundException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php', + 'PHPUnit\\Runner\\ClassDoesNotExtendTestCaseException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php', + 'PHPUnit\\Runner\\ClassIsAbstractException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php', + 'PHPUnit\\Runner\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/Runner/CodeCoverage.php', + 'PHPUnit\\Runner\\DirectoryDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php', + 'PHPUnit\\Runner\\ErrorException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ErrorException.php', + 'PHPUnit\\Runner\\ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/ErrorHandler.php', + 'PHPUnit\\Runner\\Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/Exception.php', + 'PHPUnit\\Runner\\Extension\\Extension' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/Extension.php', + 'PHPUnit\\Runner\\Extension\\ExtensionBootstrapper' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php', + 'PHPUnit\\Runner\\Extension\\Facade' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/Facade.php', + 'PHPUnit\\Runner\\Extension\\ParameterCollection' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php', + 'PHPUnit\\Runner\\Extension\\PharLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php', + 'PHPUnit\\Runner\\FileDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php', + 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php', + 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\TestIdFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php', + 'PHPUnit\\Runner\\GarbageCollection\\ExecutionFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php', + 'PHPUnit\\Runner\\GarbageCollection\\ExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php', + 'PHPUnit\\Runner\\GarbageCollection\\GarbageCollectionHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php', + 'PHPUnit\\Runner\\GarbageCollection\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php', + 'PHPUnit\\Runner\\GarbageCollection\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Runner\\InvalidOrderException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php', + 'PHPUnit\\Runner\\InvalidPhptFileException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php', + 'PHPUnit\\Runner\\ParameterDoesNotExistException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php', + 'PHPUnit\\Runner\\PhptExternalFileCannotBeLoadedException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php', + 'PHPUnit\\Runner\\PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Runner/PhptTestCase.php', + 'PHPUnit\\Runner\\ResultCache\\DefaultResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php', + 'PHPUnit\\Runner\\ResultCache\\NullResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php', + 'PHPUnit\\Runner\\ResultCache\\ResultCache' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php', + 'PHPUnit\\Runner\\ResultCache\\ResultCacheHandler' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php', + 'PHPUnit\\Runner\\ResultCache\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\Runner\\TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', + 'PHPUnit\\Runner\\TestSuiteSorter' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php', + 'PHPUnit\\Runner\\UnsupportedPhptSectionException' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php', + 'PHPUnit\\Runner\\Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php', + 'PHPUnit\\TestRunner\\TestResult\\BeforeTestClassMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\Collector' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Collector.php', + 'PHPUnit\\TestRunner\\TestResult\\ExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\Facade' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Facade.php', + 'PHPUnit\\TestRunner\\TestResult\\Issues\\Issue' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Issue.php', + 'PHPUnit\\TestRunner\\TestResult\\PassedTests' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/PassedTests.php', + 'PHPUnit\\TestRunner\\TestResult\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestResult' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/TestResult.php', + 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSuiteFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSuiteSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSuiteStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\TextUI\\Application' => $vendorDir . '/phpunit/phpunit/src/TextUI/Application.php', + 'PHPUnit\\TextUI\\CannotOpenSocketException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php', + 'PHPUnit\\TextUI\\CliArguments\\Builder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php', + 'PHPUnit\\TextUI\\CliArguments\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php', + 'PHPUnit\\TextUI\\CliArguments\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php', + 'PHPUnit\\TextUI\\CliArguments\\XmlConfigurationFileFinder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php', + 'PHPUnit\\TextUI\\Command\\AtLeastVersionCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php', + 'PHPUnit\\TextUI\\Command\\Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Command.php', + 'PHPUnit\\TextUI\\Command\\GenerateConfigurationCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php', + 'PHPUnit\\TextUI\\Command\\ListGroupsCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php', + 'PHPUnit\\TextUI\\Command\\ListTestSuitesCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php', + 'PHPUnit\\TextUI\\Command\\ListTestsAsTextCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php', + 'PHPUnit\\TextUI\\Command\\ListTestsAsXmlCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php', + 'PHPUnit\\TextUI\\Command\\MigrateConfigurationCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php', + 'PHPUnit\\TextUI\\Command\\Result' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Result.php', + 'PHPUnit\\TextUI\\Command\\ShowHelpCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php', + 'PHPUnit\\TextUI\\Command\\ShowVersionCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php', + 'PHPUnit\\TextUI\\Command\\VersionCheckCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php', + 'PHPUnit\\TextUI\\Command\\WarmCodeCoverageCacheCommand' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php', + 'PHPUnit\\TextUI\\Configuration\\Builder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Builder.php', + 'PHPUnit\\TextUI\\Configuration\\CodeCoverageFilterRegistry' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php', + 'PHPUnit\\TextUI\\Configuration\\CodeCoverageReportNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php', + 'PHPUnit\\TextUI\\Configuration\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Configuration.php', + 'PHPUnit\\TextUI\\Configuration\\ConfigurationCannotBeBuiltException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php', + 'PHPUnit\\TextUI\\Configuration\\Constant' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php', + 'PHPUnit\\TextUI\\Configuration\\ConstantCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php', + 'PHPUnit\\TextUI\\Configuration\\ConstantCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\Directory' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php', + 'PHPUnit\\TextUI\\Configuration\\DirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php', + 'PHPUnit\\TextUI\\Configuration\\DirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php', + 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrap' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php', + 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php', + 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\File' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/File.php', + 'PHPUnit\\TextUI\\Configuration\\FileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php', + 'PHPUnit\\TextUI\\Configuration\\FileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\FilterDirectory' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php', + 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php', + 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\FilterNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php', + 'PHPUnit\\TextUI\\Configuration\\Group' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php', + 'PHPUnit\\TextUI\\Configuration\\GroupCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php', + 'PHPUnit\\TextUI\\Configuration\\GroupCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\IniSetting' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php', + 'PHPUnit\\TextUI\\Configuration\\IniSettingCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php', + 'PHPUnit\\TextUI\\Configuration\\IniSettingCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\LoggingNotConfiguredException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php', + 'PHPUnit\\TextUI\\Configuration\\Merger' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Merger.php', + 'PHPUnit\\TextUI\\Configuration\\NoBaselineException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php', + 'PHPUnit\\TextUI\\Configuration\\NoBootstrapException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCacheDirectoryException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCliArgumentException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php', + 'PHPUnit\\TextUI\\Configuration\\NoConfigurationFileException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCoverageCacheDirectoryException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCustomCssFileException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php', + 'PHPUnit\\TextUI\\Configuration\\NoDefaultTestSuiteException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php', + 'PHPUnit\\TextUI\\Configuration\\NoPharExtensionDirectoryException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php', + 'PHPUnit\\TextUI\\Configuration\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php', + 'PHPUnit\\TextUI\\Configuration\\PhpHandler' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php', + 'PHPUnit\\TextUI\\Configuration\\Registry' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Registry.php', + 'PHPUnit\\TextUI\\Configuration\\Source' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php', + 'PHPUnit\\TextUI\\Configuration\\SourceFilter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php', + 'PHPUnit\\TextUI\\Configuration\\SourceMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php', + 'PHPUnit\\TextUI\\Configuration\\TestDirectory' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php', + 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php', + 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\TestFile' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php', + 'PHPUnit\\TextUI\\Configuration\\TestFileCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php', + 'PHPUnit\\TextUI\\Configuration\\TestFileCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuiteBuilder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\Variable' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php', + 'PHPUnit\\TextUI\\Configuration\\VariableCollection' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php', + 'PHPUnit\\TextUI\\Configuration\\VariableCollectionIterator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php', + 'PHPUnit\\TextUI\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/Exception.php', + 'PHPUnit\\TextUI\\Help' => $vendorDir . '/phpunit/phpunit/src/TextUI/Help.php', + 'PHPUnit\\TextUI\\InvalidSocketException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php', + 'PHPUnit\\TextUI\\Output\\DefaultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\BeforeTestClassMethodErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\ProgressPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\Subscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestConsideredRiskySubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestErroredSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFailedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFinishedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestMarkedIncompleteSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestPreparedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestRunnerExecutionStartedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestSkippedSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredErrorSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpNoticeSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitDeprecationSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredWarningSubscriber' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php', + 'PHPUnit\\TextUI\\Output\\Default\\UnexpectedOutputPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php', + 'PHPUnit\\TextUI\\Output\\Facade' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Facade.php', + 'PHPUnit\\TextUI\\Output\\NullPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php', + 'PHPUnit\\TextUI\\Output\\Printer' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php', + 'PHPUnit\\TextUI\\Output\\SummaryPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php', + 'PHPUnit\\TextUI\\Output\\TestDox\\ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php', + 'PHPUnit\\TextUI\\RuntimeException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php', + 'PHPUnit\\TextUI\\ShellExitCodeCalculator' => $vendorDir . '/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php', + 'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php', + 'PHPUnit\\TextUI\\TestFileNotFoundException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php', + 'PHPUnit\\TextUI\\TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php', + 'PHPUnit\\TextUI\\TestSuiteFilterProcessor' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CannotFindSchemaException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\DefaultConfiguration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\FailedSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCacheDirectoryAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\LoadedFromFileConfiguration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveCoverageDirectoriesToSource' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistIncludesToCoverage' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutTodoAnnotatedTestsAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheResultFileAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveConversionToExceptionsAttributes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementCacheDirectoryAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementProcessUncoveredFilesAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveListeners' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLoggingElements' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveNoInteractionAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemovePrinterAttributes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestDoxGroupsElement' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestSuiteLoaderAttributes' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveVerboseAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBackupStaticAttributesAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBeStrictAboutCoversAnnotationAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RenameForceCoversAnnotationAttribute' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetector' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaFinder' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SnapshotNodeList' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SuccessfulSchemaDetectionResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteMapper' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocation' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ValidationResult' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Validator' => $vendorDir . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php', + 'PHPUnit\\Util\\Cloner' => $vendorDir . '/phpunit/phpunit/src/Util/Cloner.php', + 'PHPUnit\\Util\\Color' => $vendorDir . '/phpunit/phpunit/src/Util/Color.php', + 'PHPUnit\\Util\\Exception' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/Exception.php', + 'PHPUnit\\Util\\ExcludeList' => $vendorDir . '/phpunit/phpunit/src/Util/ExcludeList.php', + 'PHPUnit\\Util\\Exporter' => $vendorDir . '/phpunit/phpunit/src/Util/Exporter.php', + 'PHPUnit\\Util\\Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php', + 'PHPUnit\\Util\\Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php', + 'PHPUnit\\Util\\GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php', + 'PHPUnit\\Util\\Http\\Downloader' => $vendorDir . '/phpunit/phpunit/src/Util/Http/Downloader.php', + 'PHPUnit\\Util\\Http\\PhpDownloader' => $vendorDir . '/phpunit/phpunit/src/Util/Http/PhpDownloader.php', + 'PHPUnit\\Util\\InvalidDirectoryException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php', + 'PHPUnit\\Util\\InvalidJsonException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php', + 'PHPUnit\\Util\\InvalidVersionOperatorException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php', + 'PHPUnit\\Util\\Json' => $vendorDir . '/phpunit/phpunit/src/Util/Json.php', + 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php', + 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php', + 'PHPUnit\\Util\\PHP\\PhpProcessException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/PhpProcessException.php', + 'PHPUnit\\Util\\Reflection' => $vendorDir . '/phpunit/phpunit/src/Util/Reflection.php', + 'PHPUnit\\Util\\Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php', + 'PHPUnit\\Util\\ThrowableToStringMapper' => $vendorDir . '/phpunit/phpunit/src/Util/ThrowableToStringMapper.php', + 'PHPUnit\\Util\\VersionComparisonOperator' => $vendorDir . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php', + 'PHPUnit\\Util\\Xml' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Xml.php', + 'PHPUnit\\Util\\Xml\\Loader' => $vendorDir . '/phpunit/phpunit/src/Util/Xml/Loader.php', + 'PHPUnit\\Util\\Xml\\XmlException' => $vendorDir . '/phpunit/phpunit/src/Util/Exception/XmlException.php', + 'PharIo\\Manifest\\Application' => $vendorDir . '/phar-io/manifest/src/values/Application.php', + 'PharIo\\Manifest\\ApplicationName' => $vendorDir . '/phar-io/manifest/src/values/ApplicationName.php', + 'PharIo\\Manifest\\Author' => $vendorDir . '/phar-io/manifest/src/values/Author.php', + 'PharIo\\Manifest\\AuthorCollection' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollection.php', + 'PharIo\\Manifest\\AuthorCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/AuthorCollectionIterator.php', + 'PharIo\\Manifest\\AuthorElement' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElement.php', + 'PharIo\\Manifest\\AuthorElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/AuthorElementCollection.php', + 'PharIo\\Manifest\\BundledComponent' => $vendorDir . '/phar-io/manifest/src/values/BundledComponent.php', + 'PharIo\\Manifest\\BundledComponentCollection' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollection.php', + 'PharIo\\Manifest\\BundledComponentCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php', + 'PharIo\\Manifest\\BundlesElement' => $vendorDir . '/phar-io/manifest/src/xml/BundlesElement.php', + 'PharIo\\Manifest\\ComponentElement' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElement.php', + 'PharIo\\Manifest\\ComponentElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ComponentElementCollection.php', + 'PharIo\\Manifest\\ContainsElement' => $vendorDir . '/phar-io/manifest/src/xml/ContainsElement.php', + 'PharIo\\Manifest\\CopyrightElement' => $vendorDir . '/phar-io/manifest/src/xml/CopyrightElement.php', + 'PharIo\\Manifest\\CopyrightInformation' => $vendorDir . '/phar-io/manifest/src/values/CopyrightInformation.php', + 'PharIo\\Manifest\\ElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ElementCollection.php', + 'PharIo\\Manifest\\ElementCollectionException' => $vendorDir . '/phar-io/manifest/src/exceptions/ElementCollectionException.php', + 'PharIo\\Manifest\\Email' => $vendorDir . '/phar-io/manifest/src/values/Email.php', + 'PharIo\\Manifest\\Exception' => $vendorDir . '/phar-io/manifest/src/exceptions/Exception.php', + 'PharIo\\Manifest\\ExtElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtElement.php', + 'PharIo\\Manifest\\ExtElementCollection' => $vendorDir . '/phar-io/manifest/src/xml/ExtElementCollection.php', + 'PharIo\\Manifest\\Extension' => $vendorDir . '/phar-io/manifest/src/values/Extension.php', + 'PharIo\\Manifest\\ExtensionElement' => $vendorDir . '/phar-io/manifest/src/xml/ExtensionElement.php', + 'PharIo\\Manifest\\InvalidApplicationNameException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php', + 'PharIo\\Manifest\\InvalidEmailException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidEmailException.php', + 'PharIo\\Manifest\\InvalidUrlException' => $vendorDir . '/phar-io/manifest/src/exceptions/InvalidUrlException.php', + 'PharIo\\Manifest\\Library' => $vendorDir . '/phar-io/manifest/src/values/Library.php', + 'PharIo\\Manifest\\License' => $vendorDir . '/phar-io/manifest/src/values/License.php', + 'PharIo\\Manifest\\LicenseElement' => $vendorDir . '/phar-io/manifest/src/xml/LicenseElement.php', + 'PharIo\\Manifest\\Manifest' => $vendorDir . '/phar-io/manifest/src/values/Manifest.php', + 'PharIo\\Manifest\\ManifestDocument' => $vendorDir . '/phar-io/manifest/src/xml/ManifestDocument.php', + 'PharIo\\Manifest\\ManifestDocumentException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php', + 'PharIo\\Manifest\\ManifestDocumentLoadingException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php', + 'PharIo\\Manifest\\ManifestDocumentMapper' => $vendorDir . '/phar-io/manifest/src/ManifestDocumentMapper.php', + 'PharIo\\Manifest\\ManifestDocumentMapperException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php', + 'PharIo\\Manifest\\ManifestElement' => $vendorDir . '/phar-io/manifest/src/xml/ManifestElement.php', + 'PharIo\\Manifest\\ManifestElementException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestElementException.php', + 'PharIo\\Manifest\\ManifestLoader' => $vendorDir . '/phar-io/manifest/src/ManifestLoader.php', + 'PharIo\\Manifest\\ManifestLoaderException' => $vendorDir . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php', + 'PharIo\\Manifest\\ManifestSerializer' => $vendorDir . '/phar-io/manifest/src/ManifestSerializer.php', + 'PharIo\\Manifest\\NoEmailAddressException' => $vendorDir . '/phar-io/manifest/src/exceptions/NoEmailAddressException.php', + 'PharIo\\Manifest\\PhpElement' => $vendorDir . '/phar-io/manifest/src/xml/PhpElement.php', + 'PharIo\\Manifest\\PhpExtensionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpExtensionRequirement.php', + 'PharIo\\Manifest\\PhpVersionRequirement' => $vendorDir . '/phar-io/manifest/src/values/PhpVersionRequirement.php', + 'PharIo\\Manifest\\Requirement' => $vendorDir . '/phar-io/manifest/src/values/Requirement.php', + 'PharIo\\Manifest\\RequirementCollection' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollection.php', + 'PharIo\\Manifest\\RequirementCollectionIterator' => $vendorDir . '/phar-io/manifest/src/values/RequirementCollectionIterator.php', + 'PharIo\\Manifest\\RequiresElement' => $vendorDir . '/phar-io/manifest/src/xml/RequiresElement.php', + 'PharIo\\Manifest\\Type' => $vendorDir . '/phar-io/manifest/src/values/Type.php', + 'PharIo\\Manifest\\Url' => $vendorDir . '/phar-io/manifest/src/values/Url.php', + 'PharIo\\Version\\AbstractVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AbstractVersionConstraint.php', + 'PharIo\\Version\\AndVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php', + 'PharIo\\Version\\AnyVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/AnyVersionConstraint.php', + 'PharIo\\Version\\BuildMetaData' => $vendorDir . '/phar-io/version/src/BuildMetaData.php', + 'PharIo\\Version\\ExactVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/ExactVersionConstraint.php', + 'PharIo\\Version\\Exception' => $vendorDir . '/phar-io/version/src/exceptions/Exception.php', + 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php', + 'PharIo\\Version\\InvalidPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php', + 'PharIo\\Version\\InvalidVersionException' => $vendorDir . '/phar-io/version/src/exceptions/InvalidVersionException.php', + 'PharIo\\Version\\NoBuildMetaDataException' => $vendorDir . '/phar-io/version/src/exceptions/NoBuildMetaDataException.php', + 'PharIo\\Version\\NoPreReleaseSuffixException' => $vendorDir . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php', + 'PharIo\\Version\\OrVersionConstraintGroup' => $vendorDir . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php', + 'PharIo\\Version\\PreReleaseSuffix' => $vendorDir . '/phar-io/version/src/PreReleaseSuffix.php', + 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php', + 'PharIo\\Version\\SpecificMajorVersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php', + 'PharIo\\Version\\UnsupportedVersionConstraintException' => $vendorDir . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php', + 'PharIo\\Version\\Version' => $vendorDir . '/phar-io/version/src/Version.php', + 'PharIo\\Version\\VersionConstraint' => $vendorDir . '/phar-io/version/src/constraints/VersionConstraint.php', + 'PharIo\\Version\\VersionConstraintParser' => $vendorDir . '/phar-io/version/src/VersionConstraintParser.php', + 'PharIo\\Version\\VersionConstraintValue' => $vendorDir . '/phar-io/version/src/VersionConstraintValue.php', + 'PharIo\\Version\\VersionNumber' => $vendorDir . '/phar-io/version/src/VersionNumber.php', 'ReturnTypeWillChange' => $vendorDir . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', + 'SebastianBergmann\\CliParser\\AmbiguousOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php', + 'SebastianBergmann\\CliParser\\Exception' => $vendorDir . '/sebastian/cli-parser/src/exceptions/Exception.php', + 'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php', + 'SebastianBergmann\\CliParser\\Parser' => $vendorDir . '/sebastian/cli-parser/src/Parser.php', + 'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php', + 'SebastianBergmann\\CliParser\\UnknownOptionException' => $vendorDir . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php', + 'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php', + 'SebastianBergmann\\CodeCoverage\\Data\\ProcessedCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\Data\\RawCodeCoverageData' => $vendorDir . '/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/Selector.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugDriver' => $vendorDir . '/phpunit/php-code-coverage/src/Driver/XdebugDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotEnabledException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php', + 'SebastianBergmann\\CodeCoverage\\Exception' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/Exception.php', + 'SebastianBergmann\\CodeCoverage\\FileCouldNotBeWrittenException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php', + 'SebastianBergmann\\CodeCoverage\\Filter' => $vendorDir . '/phpunit/php-code-coverage/src/Filter.php', + 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => $vendorDir . '/phpunit/php-code-coverage/src/Node/AbstractNode.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Builder.php', + 'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => $vendorDir . '/phpunit/php-code-coverage/src/Node/CrapIndex.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Node\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Node/File.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/Node/Iterator.php', + 'SebastianBergmann\\CodeCoverage\\ParserException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ParserException.php', + 'SebastianBergmann\\CodeCoverage\\ReflectionException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php', + 'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Clover.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Cobertura.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Crap4j.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Colors' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Colors.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\CustomCssFile' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php', + 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => $vendorDir . '/phpunit/php-code-coverage/src/Report/PHP.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Text' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Text.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Thresholds' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Thresholds.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Method.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Node.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Project.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Report.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Source.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => $vendorDir . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => $vendorDir . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Known' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Known.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Large' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Large.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Medium' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Medium.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Small' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Small.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\TestSize' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/TestSize.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Unknown' => $vendorDir . '/phpunit/php-code-coverage/src/TestSize/Unknown.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Failure' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Failure.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Known' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Known.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Success' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Success.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\TestStatus' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/TestStatus.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Unknown' => $vendorDir . '/phpunit/php-code-coverage/src/TestStatus/Unknown.php', + 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Filesystem.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => $vendorDir . '/phpunit/php-code-coverage/src/Util/Percentage.php', + 'SebastianBergmann\\CodeCoverage\\Version' => $vendorDir . '/phpunit/php-code-coverage/src/Version.php', + 'SebastianBergmann\\CodeCoverage\\XmlException' => $vendorDir . '/phpunit/php-code-coverage/src/Exception/XmlException.php', + 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => $vendorDir . '/sebastian/code-unit-reverse-lookup/src/Wizard.php', + 'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => $vendorDir . '/sebastian/code-unit/src/ClassMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\ClassUnit' => $vendorDir . '/sebastian/code-unit/src/ClassUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnit' => $vendorDir . '/sebastian/code-unit/src/CodeUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollection.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => $vendorDir . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php', + 'SebastianBergmann\\CodeUnit\\Exception' => $vendorDir . '/sebastian/code-unit/src/exceptions/Exception.php', + 'SebastianBergmann\\CodeUnit\\FileUnit' => $vendorDir . '/sebastian/code-unit/src/FileUnit.php', + 'SebastianBergmann\\CodeUnit\\FunctionUnit' => $vendorDir . '/sebastian/code-unit/src/FunctionUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceUnit' => $vendorDir . '/sebastian/code-unit/src/InterfaceUnit.php', + 'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php', + 'SebastianBergmann\\CodeUnit\\Mapper' => $vendorDir . '/sebastian/code-unit/src/Mapper.php', + 'SebastianBergmann\\CodeUnit\\NoTraitException' => $vendorDir . '/sebastian/code-unit/src/exceptions/NoTraitException.php', + 'SebastianBergmann\\CodeUnit\\ReflectionException' => $vendorDir . '/sebastian/code-unit/src/exceptions/ReflectionException.php', + 'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => $vendorDir . '/sebastian/code-unit/src/TraitMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\TraitUnit' => $vendorDir . '/sebastian/code-unit/src/TraitUnit.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', + 'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php', + 'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php', + 'SebastianBergmann\\Comparator\\Exception' => $vendorDir . '/sebastian/comparator/src/exceptions/Exception.php', + 'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php', + 'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php', + 'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php', + 'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php', + 'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php', + 'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php', + 'SebastianBergmann\\Comparator\\RuntimeException' => $vendorDir . '/sebastian/comparator/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php', + 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php', + 'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php', + 'SebastianBergmann\\Complexity\\Calculator' => $vendorDir . '/sebastian/complexity/src/Calculator.php', + 'SebastianBergmann\\Complexity\\Complexity' => $vendorDir . '/sebastian/complexity/src/Complexity/Complexity.php', + 'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\ComplexityCollection' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollection.php', + 'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => $vendorDir . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php', + 'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => $vendorDir . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\Exception' => $vendorDir . '/sebastian/complexity/src/Exception/Exception.php', + 'SebastianBergmann\\Complexity\\RuntimeException' => $vendorDir . '/sebastian/complexity/src/Exception/RuntimeException.php', + 'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php', + 'SebastianBergmann\\Diff\\ConfigurationException' => $vendorDir . '/sebastian/diff/src/Exception/ConfigurationException.php', + 'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php', + 'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php', + 'SebastianBergmann\\Diff\\Exception' => $vendorDir . '/sebastian/diff/src/Exception/Exception.php', + 'SebastianBergmann\\Diff\\InvalidArgumentException' => $vendorDir . '/sebastian/diff/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php', + 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => $vendorDir . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', + 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => $vendorDir . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php', + 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => $vendorDir . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php', + 'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php', + 'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php', + 'SebastianBergmann\\FileIterator\\ExcludeIterator' => $vendorDir . '/phpunit/php-file-iterator/src/ExcludeIterator.php', + 'SebastianBergmann\\FileIterator\\Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php', + 'SebastianBergmann\\FileIterator\\Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php', + 'SebastianBergmann\\FileIterator\\Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php', + 'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php', + 'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/exceptions/Exception.php', + 'SebastianBergmann\\GlobalState\\ExcludeList' => $vendorDir . '/sebastian/global-state/src/ExcludeList.php', + 'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php', + 'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php', + 'SebastianBergmann\\Invoker\\Exception' => $vendorDir . '/phpunit/php-invoker/src/exceptions/Exception.php', + 'SebastianBergmann\\Invoker\\Invoker' => $vendorDir . '/phpunit/php-invoker/src/Invoker.php', + 'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php', + 'SebastianBergmann\\Invoker\\TimeoutException' => $vendorDir . '/phpunit/php-invoker/src/exceptions/TimeoutException.php', + 'SebastianBergmann\\LinesOfCode\\Counter' => $vendorDir . '/sebastian/lines-of-code/src/Counter.php', + 'SebastianBergmann\\LinesOfCode\\Exception' => $vendorDir . '/sebastian/lines-of-code/src/Exception/Exception.php', + 'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php', + 'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => $vendorDir . '/sebastian/lines-of-code/src/LineCountingVisitor.php', + 'SebastianBergmann\\LinesOfCode\\LinesOfCode' => $vendorDir . '/sebastian/lines-of-code/src/LinesOfCode.php', + 'SebastianBergmann\\LinesOfCode\\NegativeValueException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php', + 'SebastianBergmann\\LinesOfCode\\RuntimeException' => $vendorDir . '/sebastian/lines-of-code/src/Exception/RuntimeException.php', + 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => $vendorDir . '/sebastian/object-enumerator/src/Enumerator.php', + 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => $vendorDir . '/sebastian/object-reflector/src/ObjectReflector.php', + 'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php', + 'SebastianBergmann\\Template\\Exception' => $vendorDir . '/phpunit/php-text-template/src/exceptions/Exception.php', + 'SebastianBergmann\\Template\\InvalidArgumentException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php', + 'SebastianBergmann\\Template\\RuntimeException' => $vendorDir . '/phpunit/php-text-template/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Template\\Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php', + 'SebastianBergmann\\Timer\\Duration' => $vendorDir . '/phpunit/php-timer/src/Duration.php', + 'SebastianBergmann\\Timer\\Exception' => $vendorDir . '/phpunit/php-timer/src/exceptions/Exception.php', + 'SebastianBergmann\\Timer\\NoActiveTimerException' => $vendorDir . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php', + 'SebastianBergmann\\Timer\\ResourceUsageFormatter' => $vendorDir . '/phpunit/php-timer/src/ResourceUsageFormatter.php', + 'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => $vendorDir . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php', + 'SebastianBergmann\\Timer\\Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php', + 'SebastianBergmann\\Type\\CallableType' => $vendorDir . '/sebastian/type/src/type/CallableType.php', + 'SebastianBergmann\\Type\\Exception' => $vendorDir . '/sebastian/type/src/exception/Exception.php', + 'SebastianBergmann\\Type\\FalseType' => $vendorDir . '/sebastian/type/src/type/FalseType.php', + 'SebastianBergmann\\Type\\GenericObjectType' => $vendorDir . '/sebastian/type/src/type/GenericObjectType.php', + 'SebastianBergmann\\Type\\IntersectionType' => $vendorDir . '/sebastian/type/src/type/IntersectionType.php', + 'SebastianBergmann\\Type\\IterableType' => $vendorDir . '/sebastian/type/src/type/IterableType.php', + 'SebastianBergmann\\Type\\MixedType' => $vendorDir . '/sebastian/type/src/type/MixedType.php', + 'SebastianBergmann\\Type\\NeverType' => $vendorDir . '/sebastian/type/src/type/NeverType.php', + 'SebastianBergmann\\Type\\NullType' => $vendorDir . '/sebastian/type/src/type/NullType.php', + 'SebastianBergmann\\Type\\ObjectType' => $vendorDir . '/sebastian/type/src/type/ObjectType.php', + 'SebastianBergmann\\Type\\Parameter' => $vendorDir . '/sebastian/type/src/Parameter.php', + 'SebastianBergmann\\Type\\ReflectionMapper' => $vendorDir . '/sebastian/type/src/ReflectionMapper.php', + 'SebastianBergmann\\Type\\RuntimeException' => $vendorDir . '/sebastian/type/src/exception/RuntimeException.php', + 'SebastianBergmann\\Type\\SimpleType' => $vendorDir . '/sebastian/type/src/type/SimpleType.php', + 'SebastianBergmann\\Type\\StaticType' => $vendorDir . '/sebastian/type/src/type/StaticType.php', + 'SebastianBergmann\\Type\\TrueType' => $vendorDir . '/sebastian/type/src/type/TrueType.php', + 'SebastianBergmann\\Type\\Type' => $vendorDir . '/sebastian/type/src/type/Type.php', + 'SebastianBergmann\\Type\\TypeName' => $vendorDir . '/sebastian/type/src/TypeName.php', + 'SebastianBergmann\\Type\\UnionType' => $vendorDir . '/sebastian/type/src/type/UnionType.php', + 'SebastianBergmann\\Type\\UnknownType' => $vendorDir . '/sebastian/type/src/type/UnknownType.php', + 'SebastianBergmann\\Type\\VoidType' => $vendorDir . '/sebastian/type/src/type/VoidType.php', + 'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php', + 'TheSeer\\Tokenizer\\Exception' => $vendorDir . '/theseer/tokenizer/src/Exception.php', + 'TheSeer\\Tokenizer\\NamespaceUri' => $vendorDir . '/theseer/tokenizer/src/NamespaceUri.php', + 'TheSeer\\Tokenizer\\NamespaceUriException' => $vendorDir . '/theseer/tokenizer/src/NamespaceUriException.php', + 'TheSeer\\Tokenizer\\Token' => $vendorDir . '/theseer/tokenizer/src/Token.php', + 'TheSeer\\Tokenizer\\TokenCollection' => $vendorDir . '/theseer/tokenizer/src/TokenCollection.php', + 'TheSeer\\Tokenizer\\TokenCollectionException' => $vendorDir . '/theseer/tokenizer/src/TokenCollectionException.php', + 'TheSeer\\Tokenizer\\Tokenizer' => $vendorDir . '/theseer/tokenizer/src/Tokenizer.php', + 'TheSeer\\Tokenizer\\XMLSerializer' => $vendorDir . '/theseer/tokenizer/src/XMLSerializer.php', '©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php', ); diff --git a/.extlib/simplesamlphp/vendor/composer/autoload_files.php b/.extlib/simplesamlphp/vendor/composer/autoload_files.php index 0d72a4847..583c54c51 100644 --- a/.extlib/simplesamlphp/vendor/composer/autoload_files.php +++ b/.extlib/simplesamlphp/vendor/composer/autoload_files.php @@ -9,16 +9,22 @@ '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + '9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', + '6124b4c8570aa390c21fafd04a26c69f' => $vendorDir . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', '89efb1254ef2d1c5d80096acd12c4098' => $vendorDir . '/twig/twig/src/Resources/core.php', 'ffecb95d45175fd40f75be8a23b34f90' => $vendorDir . '/twig/twig/src/Resources/debug.php', 'c7baa00073ee9c61edf148c51917cfb4' => $vendorDir . '/twig/twig/src/Resources/escaper.php', 'f844ccf1d25df8663951193c3fc307c8' => $vendorDir . '/twig/twig/src/Resources/string_loader.php', + 'ec07570ca5a812141189b1fa81503674' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert/Functions.php', + '92c8763cd6170fce6fcfe7e26b4e8c10' => $vendorDir . '/symfony/phpunit-bridge/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '6a47392539ca2329373e0d33e1dba053' => $vendorDir . '/symfony/polyfill-intl-icu/bootstrap.php', + 'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php', '334983c1b64a31de3c73827b7a6a1e88' => $baseDir . '/src/_autoload_modules.php', + '12e461cfb3ae7ce5f3445cf5ccd80c31' => $baseDir . '/tests/_autoload_modules.php', ); diff --git a/.extlib/simplesamlphp/vendor/composer/autoload_namespaces.php b/.extlib/simplesamlphp/vendor/composer/autoload_namespaces.php index 15a2ff3ad..5c24fb52c 100644 --- a/.extlib/simplesamlphp/vendor/composer/autoload_namespaces.php +++ b/.extlib/simplesamlphp/vendor/composer/autoload_namespaces.php @@ -6,4 +6,5 @@ $baseDir = dirname($vendorDir); return array( + 'org\\bovigo\\vfs\\' => array($vendorDir . '/mikey179/vfsstream/src/main/php'), ); diff --git a/.extlib/simplesamlphp/vendor/composer/autoload_psr4.php b/.extlib/simplesamlphp/vendor/composer/autoload_psr4.php index 990185254..200683772 100644 --- a/.extlib/simplesamlphp/vendor/composer/autoload_psr4.php +++ b/.extlib/simplesamlphp/vendor/composer/autoload_psr4.php @@ -23,6 +23,7 @@ 'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'), 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), + 'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'), 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), 'Symfony\\Component\\PasswordHasher\\' => array($vendorDir . '/symfony/password-hasher'), @@ -39,26 +40,45 @@ 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), 'Symfony\\Bridge\\Twig\\' => array($vendorDir . '/symfony/twig-bridge'), + 'Symfony\\Bridge\\PhpUnit\\' => array($vendorDir . '/symfony/phpunit-bridge'), + 'SlevomatCodingStandard\\' => array($vendorDir . '/slevomat/coding-standard/SlevomatCodingStandard'), 'SimpleSAML\\XML\\' => array($vendorDir . '/simplesamlphp/xml-common/src'), 'SimpleSAML\\XMLSecurity\\' => array($vendorDir . '/simplesamlphp/xml-security/src'), + 'SimpleSAML\\Test\\Module\\saml\\' => array($baseDir . '/tests/modules/saml/src'), + 'SimpleSAML\\Test\\Module\\multiauth\\' => array($baseDir . '/tests/modules/multiauth/src'), + 'SimpleSAML\\Test\\Module\\exampleauth\\' => array($baseDir . '/tests/modules/exampleauth/src'), + 'SimpleSAML\\Test\\Module\\cron\\' => array($baseDir . '/tests/modules/cron/src'), + 'SimpleSAML\\Test\\Module\\core\\' => array($baseDir . '/tests/modules/core/src'), + 'SimpleSAML\\Test\\Module\\admin\\' => array($baseDir . '/tests/modules/admin/src'), + 'SimpleSAML\\Test\\' => array($baseDir . '/tests', $baseDir . '/tests/src/SimpleSAML'), + 'SimpleSAML\\TestUtils\\' => array($vendorDir . '/simplesamlphp/simplesamlphp-test-framework/lib'), 'SimpleSAML\\Module\\saml\\' => array($baseDir . '/modules/saml/src'), 'SimpleSAML\\Module\\multiauth\\' => array($baseDir . '/modules/multiauth/src'), 'SimpleSAML\\Module\\exampleauth\\' => array($baseDir . '/modules/exampleauth/src'), 'SimpleSAML\\Module\\cron\\' => array($baseDir . '/modules/cron/src'), 'SimpleSAML\\Module\\core\\' => array($baseDir . '/modules/core/src'), 'SimpleSAML\\Module\\admin\\' => array($baseDir . '/modules/admin/src'), + 'SimpleSAML\\Module\\adfs\\' => array($baseDir . '/modules/adfs/src'), 'SimpleSAML\\Composer\\XMLProvider\\' => array($vendorDir . '/simplesamlphp/composer-xmlprovider-installer/src'), 'SimpleSAML\\Composer\\' => array($vendorDir . '/simplesamlphp/composer-module-installer/src'), 'SimpleSAML\\Assert\\' => array($vendorDir . '/simplesamlphp/assert/src'), 'SimpleSAML\\' => array($baseDir . '/src/SimpleSAML'), - 'SAML2\\' => array($vendorDir . '/simplesamlphp/saml2/src/SAML2'), + 'SAML2\\' => array($vendorDir . '/simplesamlphp/saml2/src/SAML2', $vendorDir . '/simplesamlphp/saml2-legacy/src/SAML2'), 'RobRichards\\XMLSecLibs\\' => array($vendorDir . '/robrichards/xmlseclibs/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), + 'Predis\\' => array($vendorDir . '/predis/predis/src'), + 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), + 'PHPStan\\PhpDocParser\\' => array($vendorDir . '/phpstan/phpdoc-parser/src'), + 'PHPStan\\ExtensionInstaller\\' => array($vendorDir . '/phpstan/extension-installer/src'), + 'PHPStan\\' => array($vendorDir . '/phpstan/phpstan-mockery/src'), + 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => array($vendorDir . '/dealerdirect/phpcodesniffer-composer-installer/src'), 'League\\Uri\\' => array($vendorDir . '/league/uri-interfaces'), + 'Gettext\\Scanner\\' => array($vendorDir . '/gettext/php-scanner/src'), 'Gettext\\Languages\\' => array($vendorDir . '/gettext/languages/src'), 'Gettext\\' => array($vendorDir . '/gettext/gettext/src', $vendorDir . '/gettext/translator/src'), + 'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'), ); diff --git a/.extlib/simplesamlphp/vendor/composer/autoload_real.php b/.extlib/simplesamlphp/vendor/composer/autoload_real.php index 5b0b2327a..27114e969 100644 --- a/.extlib/simplesamlphp/vendor/composer/autoload_real.php +++ b/.extlib/simplesamlphp/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitd92254016c92c1549c1187a87107524d +class ComposerAutoloaderIniteb8044a5f31df9017f83ac696a2e46a4 { private static $loader; @@ -24,16 +24,16 @@ public static function getLoader() require __DIR__ . '/platform_check.php'; - spl_autoload_register(array('ComposerAutoloaderInitd92254016c92c1549c1187a87107524d', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderIniteb8044a5f31df9017f83ac696a2e46a4', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); - spl_autoload_unregister(array('ComposerAutoloaderInitd92254016c92c1549c1187a87107524d', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderIniteb8044a5f31df9017f83ac696a2e46a4', 'loadClassLoader')); require __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInitd92254016c92c1549c1187a87107524d::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4::getInitializer($loader)); $loader->register(true); - $filesToLoad = \Composer\Autoload\ComposerStaticInitd92254016c92c1549c1187a87107524d::$files; + $filesToLoad = \Composer\Autoload\ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4::$files; $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; diff --git a/.extlib/simplesamlphp/vendor/composer/autoload_static.php b/.extlib/simplesamlphp/vendor/composer/autoload_static.php index 5e2ec9feb..273eb9748 100644 --- a/.extlib/simplesamlphp/vendor/composer/autoload_static.php +++ b/.extlib/simplesamlphp/vendor/composer/autoload_static.php @@ -4,24 +4,30 @@ namespace Composer\Autoload; -class ComposerStaticInitd92254016c92c1549c1187a87107524d +class ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4 { public static $files = array ( '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + '9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', + '6124b4c8570aa390c21fafd04a26c69f' => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy/deep_copy.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', '89efb1254ef2d1c5d80096acd12c4098' => __DIR__ . '/..' . '/twig/twig/src/Resources/core.php', 'ffecb95d45175fd40f75be8a23b34f90' => __DIR__ . '/..' . '/twig/twig/src/Resources/debug.php', 'c7baa00073ee9c61edf148c51917cfb4' => __DIR__ . '/..' . '/twig/twig/src/Resources/escaper.php', 'f844ccf1d25df8663951193c3fc307c8' => __DIR__ . '/..' . '/twig/twig/src/Resources/string_loader.php', + 'ec07570ca5a812141189b1fa81503674' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert/Functions.php', + '92c8763cd6170fce6fcfe7e26b4e8c10' => __DIR__ . '/..' . '/symfony/phpunit-bridge/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '6a47392539ca2329373e0d33e1dba053' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/bootstrap.php', + 'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php', '334983c1b64a31de3c73827b7a6a1e88' => __DIR__ . '/../..' . '/src/_autoload_modules.php', + '12e461cfb3ae7ce5f3445cf5ccd80c31' => __DIR__ . '/../..' . '/tests/_autoload_modules.php', ); public static $prefixLengthsPsr4 = array ( @@ -50,6 +56,7 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d 'Symfony\\Component\\Yaml\\' => 23, 'Symfony\\Component\\VarExporter\\' => 30, 'Symfony\\Component\\VarDumper\\' => 28, + 'Symfony\\Component\\Translation\\' => 30, 'Symfony\\Component\\String\\' => 25, 'Symfony\\Component\\Routing\\' => 26, 'Symfony\\Component\\PasswordHasher\\' => 33, @@ -66,14 +73,25 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d 'Symfony\\Component\\Cache\\' => 24, 'Symfony\\Bundle\\FrameworkBundle\\' => 31, 'Symfony\\Bridge\\Twig\\' => 20, + 'Symfony\\Bridge\\PhpUnit\\' => 23, + 'SlevomatCodingStandard\\' => 23, 'SimpleSAML\\XML\\' => 15, 'SimpleSAML\\XMLSecurity\\' => 23, + 'SimpleSAML\\Test\\Module\\saml\\' => 28, + 'SimpleSAML\\Test\\Module\\multiauth\\' => 33, + 'SimpleSAML\\Test\\Module\\exampleauth\\' => 35, + 'SimpleSAML\\Test\\Module\\cron\\' => 28, + 'SimpleSAML\\Test\\Module\\core\\' => 28, + 'SimpleSAML\\Test\\Module\\admin\\' => 29, + 'SimpleSAML\\Test\\' => 16, + 'SimpleSAML\\TestUtils\\' => 21, 'SimpleSAML\\Module\\saml\\' => 23, 'SimpleSAML\\Module\\multiauth\\' => 28, 'SimpleSAML\\Module\\exampleauth\\' => 30, 'SimpleSAML\\Module\\cron\\' => 23, 'SimpleSAML\\Module\\core\\' => 23, 'SimpleSAML\\Module\\admin\\' => 24, + 'SimpleSAML\\Module\\adfs\\' => 23, 'SimpleSAML\\Composer\\XMLProvider\\' => 32, 'SimpleSAML\\Composer\\' => 20, 'SimpleSAML\\Assert\\' => 18, @@ -91,6 +109,12 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d 'Psr\\EventDispatcher\\' => 20, 'Psr\\Container\\' => 14, 'Psr\\Cache\\' => 10, + 'Predis\\' => 7, + 'PhpParser\\' => 10, + 'PHPStan\\PhpDocParser\\' => 21, + 'PHPStan\\ExtensionInstaller\\' => 27, + 'PHPStan\\' => 8, + 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 57, ), 'L' => array ( @@ -98,9 +122,14 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d ), 'G' => array ( + 'Gettext\\Scanner\\' => 16, 'Gettext\\Languages\\' => 18, 'Gettext\\' => 8, ), + 'D' => + array ( + 'DeepCopy\\' => 9, + ), ); public static $prefixDirsPsr4 = array ( @@ -172,6 +201,10 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d array ( 0 => __DIR__ . '/..' . '/symfony/var-dumper', ), + 'Symfony\\Component\\Translation\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/translation', + ), 'Symfony\\Component\\String\\' => array ( 0 => __DIR__ . '/..' . '/symfony/string', @@ -236,6 +269,14 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d array ( 0 => __DIR__ . '/..' . '/symfony/twig-bridge', ), + 'Symfony\\Bridge\\PhpUnit\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/phpunit-bridge', + ), + 'SlevomatCodingStandard\\' => + array ( + 0 => __DIR__ . '/..' . '/slevomat/coding-standard/SlevomatCodingStandard', + ), 'SimpleSAML\\XML\\' => array ( 0 => __DIR__ . '/..' . '/simplesamlphp/xml-common/src', @@ -244,6 +285,39 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d array ( 0 => __DIR__ . '/..' . '/simplesamlphp/xml-security/src', ), + 'SimpleSAML\\Test\\Module\\saml\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/modules/saml/src', + ), + 'SimpleSAML\\Test\\Module\\multiauth\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/modules/multiauth/src', + ), + 'SimpleSAML\\Test\\Module\\exampleauth\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/modules/exampleauth/src', + ), + 'SimpleSAML\\Test\\Module\\cron\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/modules/cron/src', + ), + 'SimpleSAML\\Test\\Module\\core\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/modules/core/src', + ), + 'SimpleSAML\\Test\\Module\\admin\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests/modules/admin/src', + ), + 'SimpleSAML\\Test\\' => + array ( + 0 => __DIR__ . '/../..' . '/tests', + 1 => __DIR__ . '/../..' . '/tests/src/SimpleSAML', + ), + 'SimpleSAML\\TestUtils\\' => + array ( + 0 => __DIR__ . '/..' . '/simplesamlphp/simplesamlphp-test-framework/lib', + ), 'SimpleSAML\\Module\\saml\\' => array ( 0 => __DIR__ . '/../..' . '/modules/saml/src', @@ -268,6 +342,10 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d array ( 0 => __DIR__ . '/../..' . '/modules/admin/src', ), + 'SimpleSAML\\Module\\adfs\\' => + array ( + 0 => __DIR__ . '/../..' . '/modules/adfs/src', + ), 'SimpleSAML\\Composer\\XMLProvider\\' => array ( 0 => __DIR__ . '/..' . '/simplesamlphp/composer-xmlprovider-installer/src', @@ -287,6 +365,7 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d 'SAML2\\' => array ( 0 => __DIR__ . '/..' . '/simplesamlphp/saml2/src/SAML2', + 1 => __DIR__ . '/..' . '/simplesamlphp/saml2-legacy/src/SAML2', ), 'RobRichards\\XMLSecLibs\\' => array ( @@ -313,10 +392,38 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d array ( 0 => __DIR__ . '/..' . '/psr/cache/src', ), + 'Predis\\' => + array ( + 0 => __DIR__ . '/..' . '/predis/predis/src', + ), + 'PhpParser\\' => + array ( + 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', + ), + 'PHPStan\\PhpDocParser\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src', + ), + 'PHPStan\\ExtensionInstaller\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/extension-installer/src', + ), + 'PHPStan\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/phpstan-mockery/src', + ), + 'PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => + array ( + 0 => __DIR__ . '/..' . '/dealerdirect/phpcodesniffer-composer-installer/src', + ), 'League\\Uri\\' => array ( 0 => __DIR__ . '/..' . '/league/uri-interfaces', ), + 'Gettext\\Scanner\\' => + array ( + 0 => __DIR__ . '/..' . '/gettext/php-scanner/src', + ), 'Gettext\\Languages\\' => array ( 0 => __DIR__ . '/..' . '/gettext/languages/src', @@ -326,6 +433,20 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d 0 => __DIR__ . '/..' . '/gettext/gettext/src', 1 => __DIR__ . '/..' . '/gettext/translator/src', ), + 'DeepCopy\\' => + array ( + 0 => __DIR__ . '/..' . '/myclabs/deep-copy/src/DeepCopy', + ), + ); + + public static $prefixesPsr0 = array ( + 'o' => + array ( + 'org\\bovigo\\vfs\\' => + array ( + 0 => __DIR__ . '/..' . '/mikey179/vfsstream/src/main/php', + ), + ), ); public static $classMap = array ( @@ -346,17 +467,1177 @@ class ComposerStaticInitd92254016c92c1549c1187a87107524d 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', 'NumberFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/NumberFormatter.php', 'Override' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/Override.php', + 'PHPUnit\\Event\\Application\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/Finished.php', + 'PHPUnit\\Event\\Application\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php', + 'PHPUnit\\Event\\Application\\Started' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/Started.php', + 'PHPUnit\\Event\\Application\\StartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php', + 'PHPUnit\\Event\\Code\\ClassMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ClassMethod.php', + 'PHPUnit\\Event\\Code\\ComparisonFailure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ComparisonFailure.php', + 'PHPUnit\\Event\\Code\\ComparisonFailureBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php', + 'PHPUnit\\Event\\Code\\NoTestCaseObjectOnCallStackException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php', + 'PHPUnit\\Event\\Code\\Phpt' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/Phpt.php', + 'PHPUnit\\Event\\Code\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/Test.php', + 'PHPUnit\\Event\\Code\\TestCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestCollection.php', + 'PHPUnit\\Event\\Code\\TestCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php', + 'PHPUnit\\Event\\Code\\TestDox' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestDox.php', + 'PHPUnit\\Event\\Code\\TestDoxBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php', + 'PHPUnit\\Event\\Code\\TestMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestMethod.php', + 'PHPUnit\\Event\\Code\\TestMethodBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php', + 'PHPUnit\\Event\\Code\\Throwable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Throwable.php', + 'PHPUnit\\Event\\Code\\ThrowableBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php', + 'PHPUnit\\Event\\CollectingDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php', + 'PHPUnit\\Event\\DeferringDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php', + 'PHPUnit\\Event\\DirectDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php', + 'PHPUnit\\Event\\Dispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php', + 'PHPUnit\\Event\\DispatchingEmitter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php', + 'PHPUnit\\Event\\Emitter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Emitter/Emitter.php', + 'PHPUnit\\Event\\Event' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Event.php', + 'PHPUnit\\Event\\EventAlreadyAssignedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php', + 'PHPUnit\\Event\\EventCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/EventCollection.php', + 'PHPUnit\\Event\\EventCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php', + 'PHPUnit\\Event\\EventFacadeIsSealedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php', + 'PHPUnit\\Event\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/Exception.php', + 'PHPUnit\\Event\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Facade.php', + 'PHPUnit\\Event\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php', + 'PHPUnit\\Event\\InvalidEventException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/InvalidEventException.php', + 'PHPUnit\\Event\\InvalidSubscriberException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php', + 'PHPUnit\\Event\\MapError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/MapError.php', + 'PHPUnit\\Event\\NoPreviousThrowableException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php', + 'PHPUnit\\Event\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/RuntimeException.php', + 'PHPUnit\\Event\\Runtime\\OperatingSystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php', + 'PHPUnit\\Event\\Runtime\\PHP' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/PHP.php', + 'PHPUnit\\Event\\Runtime\\PHPUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php', + 'PHPUnit\\Event\\Runtime\\Runtime' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php', + 'PHPUnit\\Event\\SubscribableDispatcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php', + 'PHPUnit\\Event\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Subscriber.php', + 'PHPUnit\\Event\\SubscriberTypeAlreadyRegisteredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php', + 'PHPUnit\\Event\\Telemetry\\Duration' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php', + 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatus' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php', + 'PHPUnit\\Event\\Telemetry\\GarbageCollectorStatusProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php', + 'PHPUnit\\Event\\Telemetry\\HRTime' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php', + 'PHPUnit\\Event\\Telemetry\\Info' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Info.php', + 'PHPUnit\\Event\\Telemetry\\MemoryMeter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php', + 'PHPUnit\\Event\\Telemetry\\MemoryUsage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php', + 'PHPUnit\\Event\\Telemetry\\Php81GarbageCollectorStatusProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php', + 'PHPUnit\\Event\\Telemetry\\Php83GarbageCollectorStatusProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php', + 'PHPUnit\\Event\\Telemetry\\Snapshot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php', + 'PHPUnit\\Event\\Telemetry\\StopWatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php', + 'PHPUnit\\Event\\Telemetry\\System' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/System.php', + 'PHPUnit\\Event\\Telemetry\\SystemMemoryMeter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php', + 'PHPUnit\\Event\\Telemetry\\SystemStopWatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php', + 'PHPUnit\\Event\\Telemetry\\SystemStopWatchWithOffset' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php', + 'PHPUnit\\Event\\TestData\\DataFromDataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php', + 'PHPUnit\\Event\\TestData\\DataFromTestDependency' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php', + 'PHPUnit\\Event\\TestData\\MoreThanOneDataSetFromDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php', + 'PHPUnit\\Event\\TestData\\NoDataSetFromDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php', + 'PHPUnit\\Event\\TestData\\TestData' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php', + 'PHPUnit\\Event\\TestData\\TestDataCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php', + 'PHPUnit\\Event\\TestData\\TestDataCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php', + 'PHPUnit\\Event\\TestRunner\\BootstrapFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php', + 'PHPUnit\\Event\\TestRunner\\BootstrapFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\Configured' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php', + 'PHPUnit\\Event\\TestRunner\\ConfiguredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\DeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php', + 'PHPUnit\\Event\\TestRunner\\DeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\EventFacadeSealed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php', + 'PHPUnit\\Event\\TestRunner\\EventFacadeSealedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionAborted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionAbortedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionStarted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php', + 'PHPUnit\\Event\\TestRunner\\ExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrapped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionBootstrappedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPhar' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php', + 'PHPUnit\\Event\\TestRunner\\ExtensionLoadedFromPharSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php', + 'PHPUnit\\Event\\TestRunner\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionDisabledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionEnabledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php', + 'PHPUnit\\Event\\TestRunner\\GarbageCollectionTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\Started' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/Started.php', + 'PHPUnit\\Event\\TestRunner\\StartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php', + 'PHPUnit\\Event\\TestRunner\\WarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php', + 'PHPUnit\\Event\\TestRunner\\WarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Filtered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php', + 'PHPUnit\\Event\\TestSuite\\FilteredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php', + 'PHPUnit\\Event\\TestSuite\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Loaded' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php', + 'PHPUnit\\Event\\TestSuite\\LoadedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Skipped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php', + 'PHPUnit\\Event\\TestSuite\\SkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Sorted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php', + 'PHPUnit\\Event\\TestSuite\\SortedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\Started' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/Started.php', + 'PHPUnit\\Event\\TestSuite\\StartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php', + 'PHPUnit\\Event\\TestSuite\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteForTestMethodWithDataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php', + 'PHPUnit\\Event\\TestSuite\\TestSuiteWithName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\AfterLastTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\AfterTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\AssertionFailed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php', + 'PHPUnit\\Event\\Test\\AssertionFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php', + 'PHPUnit\\Event\\Test\\AssertionSucceeded' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php', + 'PHPUnit\\Event\\Test\\AssertionSucceededSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErrored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\BeforeFirstTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php', + 'PHPUnit\\Event\\Test\\BeforeTestMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\ComparatorRegistered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php', + 'PHPUnit\\Event\\Test\\ComparatorRegisteredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php', + 'PHPUnit\\Event\\Test\\ConsideredRisky' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php', + 'PHPUnit\\Event\\Test\\ConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php', + 'PHPUnit\\Event\\Test\\DataProviderMethodFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\DeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php', + 'PHPUnit\\Event\\Test\\DeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\ErrorTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php', + 'PHPUnit\\Event\\Test\\ErrorTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\Errored' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php', + 'PHPUnit\\Event\\Test\\ErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php', + 'PHPUnit\\Event\\Test\\Failed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php', + 'PHPUnit\\Event\\Test\\FailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php', + 'PHPUnit\\Event\\Test\\Finished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php', + 'PHPUnit\\Event\\Test\\FinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\MarkedIncomplete' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php', + 'PHPUnit\\Event\\Test\\MarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectForAbstractClassCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectForIntersectionOfInterfacesCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectForTraitCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectForTraitCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php', + 'PHPUnit\\Event\\Test\\MockObjectFromWsdlCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\NoComparisonFailureException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php', + 'PHPUnit\\Event\\Test\\NoticeTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php', + 'PHPUnit\\Event\\Test\\NoticeTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PartialMockObjectCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php', + 'PHPUnit\\Event\\Test\\PartialMockObjectCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\Passed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php', + 'PHPUnit\\Event\\Test\\PassedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpDeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php', + 'PHPUnit\\Event\\Test\\PhpDeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpNoticeTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php', + 'PHPUnit\\Event\\Test\\PhpNoticeTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpWarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php', + 'PHPUnit\\Event\\Test\\PhpWarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php', + 'PHPUnit\\Event\\Test\\PhpunitDeprecationTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpunitErrorTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php', + 'PHPUnit\\Event\\Test\\PhpunitErrorTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PhpunitWarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php', + 'PHPUnit\\Event\\Test\\PhpunitWarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\Test\\PostConditionCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php', + 'PHPUnit\\Event\\Test\\PostConditionCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\PostConditionFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php', + 'PHPUnit\\Event\\Test\\PostConditionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\PreConditionCalled' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php', + 'PHPUnit\\Event\\Test\\PreConditionCalledSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php', + 'PHPUnit\\Event\\Test\\PreConditionFinished' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php', + 'PHPUnit\\Event\\Test\\PreConditionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php', + 'PHPUnit\\Event\\Test\\PreparationFailed' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php', + 'PHPUnit\\Event\\Test\\PreparationFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php', + 'PHPUnit\\Event\\Test\\PreparationStarted' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php', + 'PHPUnit\\Event\\Test\\PreparationStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php', + 'PHPUnit\\Event\\Test\\Prepared' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php', + 'PHPUnit\\Event\\Test\\PreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php', + 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutput' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php', + 'PHPUnit\\Event\\Test\\PrintedUnexpectedOutputSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php', + 'PHPUnit\\Event\\Test\\Skipped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php', + 'PHPUnit\\Event\\Test\\SkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php', + 'PHPUnit\\Event\\Test\\TestProxyCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php', + 'PHPUnit\\Event\\Test\\TestProxyCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\TestStubCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php', + 'PHPUnit\\Event\\Test\\TestStubCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php', + 'PHPUnit\\Event\\Test\\TestStubForIntersectionOfInterfacesCreatedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php', + 'PHPUnit\\Event\\Test\\WarningTriggered' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php', + 'PHPUnit\\Event\\Test\\WarningTriggeredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php', + 'PHPUnit\\Event\\Tracer\\Tracer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Tracer.php', + 'PHPUnit\\Event\\TypeMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/TypeMap.php', + 'PHPUnit\\Event\\UnknownEventException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownEventException.php', + 'PHPUnit\\Event\\UnknownEventTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php', + 'PHPUnit\\Event\\UnknownSubscriberException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php', + 'PHPUnit\\Event\\UnknownSubscriberTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php', + 'PHPUnit\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php', + 'PHPUnit\\Framework\\ActualValueIsNotAnObjectException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php', + 'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php', + 'PHPUnit\\Framework\\AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php', + 'PHPUnit\\Framework\\Attributes\\After' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/After.php', + 'PHPUnit\\Framework\\Attributes\\AfterClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/AfterClass.php', + 'PHPUnit\\Framework\\Attributes\\BackupGlobals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php', + 'PHPUnit\\Framework\\Attributes\\BackupStaticProperties' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php', + 'PHPUnit\\Framework\\Attributes\\Before' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Before.php', + 'PHPUnit\\Framework\\Attributes\\BeforeClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php', + 'PHPUnit\\Framework\\Attributes\\CodeCoverageIgnore' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php', + 'PHPUnit\\Framework\\Attributes\\CoversClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CoversClass.php', + 'PHPUnit\\Framework\\Attributes\\CoversFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php', + 'PHPUnit\\Framework\\Attributes\\CoversNothing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php', + 'PHPUnit\\Framework\\Attributes\\DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DataProvider.php', + 'PHPUnit\\Framework\\Attributes\\DataProviderExternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php', + 'PHPUnit\\Framework\\Attributes\\Depends' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Depends.php', + 'PHPUnit\\Framework\\Attributes\\DependsExternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php', + 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingDeepClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsExternalUsingShallowClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsOnClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php', + 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingDeepClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsOnClassUsingShallowClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsUsingDeepClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php', + 'PHPUnit\\Framework\\Attributes\\DependsUsingShallowClone' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php', + 'PHPUnit\\Framework\\Attributes\\DoesNotPerformAssertions' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php', + 'PHPUnit\\Framework\\Attributes\\ExcludeGlobalVariableFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php', + 'PHPUnit\\Framework\\Attributes\\ExcludeStaticPropertyFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php', + 'PHPUnit\\Framework\\Attributes\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Group.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreClassForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreDeprecations' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreFunctionForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php', + 'PHPUnit\\Framework\\Attributes\\IgnoreMethodForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php', + 'PHPUnit\\Framework\\Attributes\\Large' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Large.php', + 'PHPUnit\\Framework\\Attributes\\Medium' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Medium.php', + 'PHPUnit\\Framework\\Attributes\\PostCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/PostCondition.php', + 'PHPUnit\\Framework\\Attributes\\PreCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/PreCondition.php', + 'PHPUnit\\Framework\\Attributes\\PreserveGlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php', + 'PHPUnit\\Framework\\Attributes\\RequiresFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php', + 'PHPUnit\\Framework\\Attributes\\RequiresMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php', + 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php', + 'PHPUnit\\Framework\\Attributes\\RequiresOperatingSystemFamily' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php', + 'PHPUnit\\Framework\\Attributes\\RequiresPhp' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php', + 'PHPUnit\\Framework\\Attributes\\RequiresPhpExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php', + 'PHPUnit\\Framework\\Attributes\\RequiresPhpunit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php', + 'PHPUnit\\Framework\\Attributes\\RequiresSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php', + 'PHPUnit\\Framework\\Attributes\\RunClassInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php', + 'PHPUnit\\Framework\\Attributes\\RunInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php', + 'PHPUnit\\Framework\\Attributes\\RunTestsInSeparateProcesses' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php', + 'PHPUnit\\Framework\\Attributes\\Small' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Small.php', + 'PHPUnit\\Framework\\Attributes\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Test.php', + 'PHPUnit\\Framework\\Attributes\\TestDox' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/TestDox.php', + 'PHPUnit\\Framework\\Attributes\\TestWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/TestWith.php', + 'PHPUnit\\Framework\\Attributes\\TestWithJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php', + 'PHPUnit\\Framework\\Attributes\\Ticket' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/Ticket.php', + 'PHPUnit\\Framework\\Attributes\\UsesClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/UsesClass.php', + 'PHPUnit\\Framework\\Attributes\\UsesFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php', + 'PHPUnit\\Framework\\Attributes\\WithoutErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php', + 'PHPUnit\\Framework\\CodeCoverageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotAcceptParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareBoolReturnTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareExactlyOneParameterException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotDeclareParameterTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php', + 'PHPUnit\\Framework\\ComparisonMethodDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php', + 'PHPUnit\\Framework\\Constraint\\ArrayHasKey' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php', + 'PHPUnit\\Framework\\Constraint\\BinaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php', + 'PHPUnit\\Framework\\Constraint\\Callback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Callback.php', + 'PHPUnit\\Framework\\Constraint\\Constraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Constraint.php', + 'PHPUnit\\Framework\\Constraint\\Count' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php', + 'PHPUnit\\Framework\\Constraint\\DirectoryExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php', + 'PHPUnit\\Framework\\Constraint\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionCode' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessageIsOrContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php', + 'PHPUnit\\Framework\\Constraint\\ExceptionMessageMatchesRegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\FileExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php', + 'PHPUnit\\Framework\\Constraint\\GreaterThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php', + 'PHPUnit\\Framework\\Constraint\\IsAnything' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php', + 'PHPUnit\\Framework\\Constraint\\IsEmpty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php', + 'PHPUnit\\Framework\\Constraint\\IsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualCanonicalizing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualIgnoringCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php', + 'PHPUnit\\Framework\\Constraint\\IsEqualWithDelta' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php', + 'PHPUnit\\Framework\\Constraint\\IsFalse' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php', + 'PHPUnit\\Framework\\Constraint\\IsFinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php', + 'PHPUnit\\Framework\\Constraint\\IsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\IsInfinite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php', + 'PHPUnit\\Framework\\Constraint\\IsInstanceOf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php', + 'PHPUnit\\Framework\\Constraint\\IsJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php', + 'PHPUnit\\Framework\\Constraint\\IsList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php', + 'PHPUnit\\Framework\\Constraint\\IsNan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php', + 'PHPUnit\\Framework\\Constraint\\IsNull' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php', + 'PHPUnit\\Framework\\Constraint\\IsReadable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php', + 'PHPUnit\\Framework\\Constraint\\IsTrue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php', + 'PHPUnit\\Framework\\Constraint\\IsType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php', + 'PHPUnit\\Framework\\Constraint\\IsWritable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php', + 'PHPUnit\\Framework\\Constraint\\JsonMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php', + 'PHPUnit\\Framework\\Constraint\\LessThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php', + 'PHPUnit\\Framework\\Constraint\\LogicalAnd' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php', + 'PHPUnit\\Framework\\Constraint\\LogicalNot' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php', + 'PHPUnit\\Framework\\Constraint\\LogicalOr' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php', + 'PHPUnit\\Framework\\Constraint\\LogicalXor' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php', + 'PHPUnit\\Framework\\Constraint\\ObjectEquals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php', + 'PHPUnit\\Framework\\Constraint\\ObjectHasProperty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php', + 'PHPUnit\\Framework\\Constraint\\Operator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php', + 'PHPUnit\\Framework\\Constraint\\RegularExpression' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php', + 'PHPUnit\\Framework\\Constraint\\SameSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php', + 'PHPUnit\\Framework\\Constraint\\StringContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php', + 'PHPUnit\\Framework\\Constraint\\StringEndsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php', + 'PHPUnit\\Framework\\Constraint\\StringEqualsStringIgnoringLineEndings' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php', + 'PHPUnit\\Framework\\Constraint\\StringMatchesFormatDescription' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php', + 'PHPUnit\\Framework\\Constraint\\StringStartsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php', + 'PHPUnit\\Framework\\Constraint\\TraversableContainsOnly' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php', + 'PHPUnit\\Framework\\Constraint\\UnaryOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php', + 'PHPUnit\\Framework\\DataProviderTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/DataProviderTestSuite.php', + 'PHPUnit\\Framework\\EmptyStringException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php', + 'PHPUnit\\Framework\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Exception.php', + 'PHPUnit\\Framework\\ExecutionOrderDependency' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php', + 'PHPUnit\\Framework\\ExpectationFailedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php', + 'PHPUnit\\Framework\\GeneratorNotSupportedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php', + 'PHPUnit\\Framework\\IncompleteTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php', + 'PHPUnit\\Framework\\IncompleteTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php', + 'PHPUnit\\Framework\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php', + 'PHPUnit\\Framework\\InvalidCoversTargetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php', + 'PHPUnit\\Framework\\InvalidDataProviderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php', + 'PHPUnit\\Framework\\InvalidDependencyException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php', + 'PHPUnit\\Framework\\MockObject\\BadMethodCallException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Identity' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\InvocationStubber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\MethodNameMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\ParametersMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php', + 'PHPUnit\\Framework\\MockObject\\Builder\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php', + 'PHPUnit\\Framework\\MockObject\\CannotUseOnlyMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\ConfigurableMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php', + 'PHPUnit\\Framework\\MockObject\\DoubledCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php', + 'PHPUnit\\Framework\\MockObject\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\CannotUseAddMethodsException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsEnumerationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsFinalException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ClassIsReadonlyException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\DuplicateMethodException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\InvalidMethodNameException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockMethodSet' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockTrait' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\MockType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\NameAlreadyInUseException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\OriginalConstructorInvocationRequiredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\SoapExtensionNotAvailableException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\TemplateLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownClassException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTraitException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php', + 'PHPUnit\\Framework\\MockObject\\Generator\\UnknownTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php', + 'PHPUnit\\Framework\\MockObject\\IncompatibleReturnValueException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php', + 'PHPUnit\\Framework\\MockObject\\Invocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php', + 'PHPUnit\\Framework\\MockObject\\InvocationHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php', + 'PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php', + 'PHPUnit\\Framework\\MockObject\\Matcher' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php', + 'PHPUnit\\Framework\\MockObject\\MatcherAlreadyRegisteredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php', + 'PHPUnit\\Framework\\MockObject\\Method' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php', + 'PHPUnit\\Framework\\MockObject\\MethodCannotBeConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameConstraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php', + 'PHPUnit\\Framework\\MockObject\\MethodNameNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MethodParametersAlreadyConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\MockBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php', + 'PHPUnit\\Framework\\MockObject\\MockObject' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php', + 'PHPUnit\\Framework\\MockObject\\MockObjectApi' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php', + 'PHPUnit\\Framework\\MockObject\\MockObjectInternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php', + 'PHPUnit\\Framework\\MockObject\\NeverReturningMethodException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php', + 'PHPUnit\\Framework\\MockObject\\NoMoreReturnValuesConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\ProxiedCloneMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php', + 'PHPUnit\\Framework\\MockObject\\ReturnValueGenerator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php', + 'PHPUnit\\Framework\\MockObject\\ReturnValueNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyInvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\AnyParameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvocationOrder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtLeastOnce' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedAtMostCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\InvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\MethodName' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\Parameters' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php', + 'PHPUnit\\Framework\\MockObject\\Rule\\ParametersRule' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php', + 'PHPUnit\\Framework\\MockObject\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php', + 'PHPUnit\\Framework\\MockObject\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php', + 'PHPUnit\\Framework\\MockObject\\StubApi' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php', + 'PHPUnit\\Framework\\MockObject\\StubInternal' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ConsecutiveCalls' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnArgument' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnReference' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnSelf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnStub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php', + 'PHPUnit\\Framework\\MockObject\\Stub\\Stub' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php', + 'PHPUnit\\Framework\\NoChildTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php', + 'PHPUnit\\Framework\\PhptAssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php', + 'PHPUnit\\Framework\\ProcessIsolationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php', + 'PHPUnit\\Framework\\Reorderable' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Reorderable.php', + 'PHPUnit\\Framework\\SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php', + 'PHPUnit\\Framework\\SkippedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php', + 'PHPUnit\\Framework\\SkippedTestSuiteError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php', + 'PHPUnit\\Framework\\SkippedWithMessageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php', + 'PHPUnit\\Framework\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Test.php', + 'PHPUnit\\Framework\\TestBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestBuilder.php', + 'PHPUnit\\Framework\\TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestCase.php', + 'PHPUnit\\Framework\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestRunner.php', + 'PHPUnit\\Framework\\TestSize\\Known' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Known.php', + 'PHPUnit\\Framework\\TestSize\\Large' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Large.php', + 'PHPUnit\\Framework\\TestSize\\Medium' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Medium.php', + 'PHPUnit\\Framework\\TestSize\\Small' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Small.php', + 'PHPUnit\\Framework\\TestSize\\TestSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/TestSize.php', + 'PHPUnit\\Framework\\TestSize\\Unknown' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSize/Unknown.php', + 'PHPUnit\\Framework\\TestStatus\\Deprecation' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php', + 'PHPUnit\\Framework\\TestStatus\\Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Error.php', + 'PHPUnit\\Framework\\TestStatus\\Failure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Failure.php', + 'PHPUnit\\Framework\\TestStatus\\Incomplete' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php', + 'PHPUnit\\Framework\\TestStatus\\Known' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Known.php', + 'PHPUnit\\Framework\\TestStatus\\Notice' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Notice.php', + 'PHPUnit\\Framework\\TestStatus\\Risky' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Risky.php', + 'PHPUnit\\Framework\\TestStatus\\Skipped' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Skipped.php', + 'PHPUnit\\Framework\\TestStatus\\Success' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Success.php', + 'PHPUnit\\Framework\\TestStatus\\TestStatus' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php', + 'PHPUnit\\Framework\\TestStatus\\Unknown' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Unknown.php', + 'PHPUnit\\Framework\\TestStatus\\Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestStatus/Warning.php', + 'PHPUnit\\Framework\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite.php', + 'PHPUnit\\Framework\\TestSuiteIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuiteIterator.php', + 'PHPUnit\\Framework\\UnknownClassOrInterfaceException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php', + 'PHPUnit\\Framework\\UnknownTypeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php', + 'PHPUnit\\Logging\\EventLogger' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/EventLogger.php', + 'PHPUnit\\Logging\\JUnit\\JunitXmlLogger' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php', + 'PHPUnit\\Logging\\JUnit\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestPreparationFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestPreparationStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestRunnerExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\Logging\\JUnit\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TeamCityLogger' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php', + 'PHPUnit\\Logging\\TeamCity\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestRunnerExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\Logging\\TeamCity\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\HtmlRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php', + 'PHPUnit\\Logging\\TestDox\\NamePrettifier' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php', + 'PHPUnit\\Logging\\TestDox\\PlainTextRenderer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php', + 'PHPUnit\\Logging\\TestDox\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestPassedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php', + 'PHPUnit\\Logging\\TestDox\\TestResultCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php', + 'PHPUnit\\Logging\\TestDox\\TestResultCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php', + 'PHPUnit\\Logging\\TestDox\\TestResultCollector' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php', + 'PHPUnit\\Logging\\TestDox\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredPhpunitWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', + 'PHPUnit\\Logging\\TestDox\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\Metadata\\After' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/After.php', + 'PHPUnit\\Metadata\\AfterClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/AfterClass.php', + 'PHPUnit\\Metadata\\Annotation\\Parser\\DocBlock' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php', + 'PHPUnit\\Metadata\\Annotation\\Parser\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php', + 'PHPUnit\\Metadata\\AnnotationsAreNotSupportedForInternalClassesException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php', + 'PHPUnit\\Metadata\\Api\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php', + 'PHPUnit\\Metadata\\Api\\DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/DataProvider.php', + 'PHPUnit\\Metadata\\Api\\Dependencies' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/Dependencies.php', + 'PHPUnit\\Metadata\\Api\\Groups' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/Groups.php', + 'PHPUnit\\Metadata\\Api\\HookMethods' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/HookMethods.php', + 'PHPUnit\\Metadata\\Api\\Requirements' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Api/Requirements.php', + 'PHPUnit\\Metadata\\BackupGlobals' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/BackupGlobals.php', + 'PHPUnit\\Metadata\\BackupStaticProperties' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/BackupStaticProperties.php', + 'PHPUnit\\Metadata\\Before' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Before.php', + 'PHPUnit\\Metadata\\BeforeClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/BeforeClass.php', + 'PHPUnit\\Metadata\\Covers' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Covers.php', + 'PHPUnit\\Metadata\\CoversClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversClass.php', + 'PHPUnit\\Metadata\\CoversDefaultClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversDefaultClass.php', + 'PHPUnit\\Metadata\\CoversFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversFunction.php', + 'PHPUnit\\Metadata\\CoversNothing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/CoversNothing.php', + 'PHPUnit\\Metadata\\DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DataProvider.php', + 'PHPUnit\\Metadata\\DependsOnClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DependsOnClass.php', + 'PHPUnit\\Metadata\\DependsOnMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DependsOnMethod.php', + 'PHPUnit\\Metadata\\DoesNotPerformAssertions' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php', + 'PHPUnit\\Metadata\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/Exception.php', + 'PHPUnit\\Metadata\\ExcludeGlobalVariableFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php', + 'PHPUnit\\Metadata\\ExcludeStaticPropertyFromBackup' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php', + 'PHPUnit\\Metadata\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Group.php', + 'PHPUnit\\Metadata\\IgnoreClassForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php', + 'PHPUnit\\Metadata\\IgnoreDeprecations' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php', + 'PHPUnit\\Metadata\\IgnoreFunctionForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php', + 'PHPUnit\\Metadata\\IgnoreMethodForCodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php', + 'PHPUnit\\Metadata\\InvalidVersionRequirementException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php', + 'PHPUnit\\Metadata\\Metadata' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Metadata.php', + 'PHPUnit\\Metadata\\MetadataCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/MetadataCollection.php', + 'PHPUnit\\Metadata\\MetadataCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php', + 'PHPUnit\\Metadata\\NoVersionRequirementException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php', + 'PHPUnit\\Metadata\\Parser\\AnnotationParser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php', + 'PHPUnit\\Metadata\\Parser\\AttributeParser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php', + 'PHPUnit\\Metadata\\Parser\\CachingParser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/CachingParser.php', + 'PHPUnit\\Metadata\\Parser\\Parser' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Parser.php', + 'PHPUnit\\Metadata\\Parser\\ParserChain' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/ParserChain.php', + 'PHPUnit\\Metadata\\Parser\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Parser/Registry.php', + 'PHPUnit\\Metadata\\PostCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/PostCondition.php', + 'PHPUnit\\Metadata\\PreCondition' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/PreCondition.php', + 'PHPUnit\\Metadata\\PreserveGlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/PreserveGlobalState.php', + 'PHPUnit\\Metadata\\ReflectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php', + 'PHPUnit\\Metadata\\RequiresFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresFunction.php', + 'PHPUnit\\Metadata\\RequiresMethod' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresMethod.php', + 'PHPUnit\\Metadata\\RequiresOperatingSystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php', + 'PHPUnit\\Metadata\\RequiresOperatingSystemFamily' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php', + 'PHPUnit\\Metadata\\RequiresPhp' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresPhp.php', + 'PHPUnit\\Metadata\\RequiresPhpExtension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php', + 'PHPUnit\\Metadata\\RequiresPhpunit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresPhpunit.php', + 'PHPUnit\\Metadata\\RequiresSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RequiresSetting.php', + 'PHPUnit\\Metadata\\RunClassInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php', + 'PHPUnit\\Metadata\\RunInSeparateProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php', + 'PHPUnit\\Metadata\\RunTestsInSeparateProcesses' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php', + 'PHPUnit\\Metadata\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Test.php', + 'PHPUnit\\Metadata\\TestDox' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/TestDox.php', + 'PHPUnit\\Metadata\\TestWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/TestWith.php', + 'PHPUnit\\Metadata\\Uses' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Uses.php', + 'PHPUnit\\Metadata\\UsesClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/UsesClass.php', + 'PHPUnit\\Metadata\\UsesDefaultClass' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/UsesDefaultClass.php', + 'PHPUnit\\Metadata\\UsesFunction' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/UsesFunction.php', + 'PHPUnit\\Metadata\\Version\\ComparisonRequirement' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php', + 'PHPUnit\\Metadata\\Version\\ConstraintRequirement' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php', + 'PHPUnit\\Metadata\\Version\\Requirement' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/Version/Requirement.php', + 'PHPUnit\\Metadata\\WithoutErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php', + 'PHPUnit\\Runner\\Baseline\\Baseline' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Baseline.php', + 'PHPUnit\\Runner\\Baseline\\CannotLoadBaselineException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php', + 'PHPUnit\\Runner\\Baseline\\FileDoesNotHaveLineException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php', + 'PHPUnit\\Runner\\Baseline\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Generator.php', + 'PHPUnit\\Runner\\Baseline\\Issue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Issue.php', + 'PHPUnit\\Runner\\Baseline\\Reader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Reader.php', + 'PHPUnit\\Runner\\Baseline\\RelativePathCalculator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php', + 'PHPUnit\\Runner\\Baseline\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\Runner\\Baseline\\Writer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Baseline/Writer.php', + 'PHPUnit\\Runner\\ClassCannotBeFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php', + 'PHPUnit\\Runner\\ClassDoesNotExtendTestCaseException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php', + 'PHPUnit\\Runner\\ClassIsAbstractException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php', + 'PHPUnit\\Runner\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/CodeCoverage.php', + 'PHPUnit\\Runner\\DirectoryDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php', + 'PHPUnit\\Runner\\ErrorException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ErrorException.php', + 'PHPUnit\\Runner\\ErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ErrorHandler.php', + 'PHPUnit\\Runner\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/Exception.php', + 'PHPUnit\\Runner\\Extension\\Extension' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/Extension.php', + 'PHPUnit\\Runner\\Extension\\ExtensionBootstrapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php', + 'PHPUnit\\Runner\\Extension\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/Facade.php', + 'PHPUnit\\Runner\\Extension\\ParameterCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php', + 'PHPUnit\\Runner\\Extension\\PharLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Extension/PharLoader.php', + 'PHPUnit\\Runner\\FileDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php', + 'PHPUnit\\Runner\\Filter\\ExcludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\Factory' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Factory.php', + 'PHPUnit\\Runner\\Filter\\GroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\IncludeGroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\NameFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php', + 'PHPUnit\\Runner\\Filter\\TestIdFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php', + 'PHPUnit\\Runner\\GarbageCollection\\ExecutionFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php', + 'PHPUnit\\Runner\\GarbageCollection\\ExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php', + 'PHPUnit\\Runner\\GarbageCollection\\GarbageCollectionHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php', + 'PHPUnit\\Runner\\GarbageCollection\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php', + 'PHPUnit\\Runner\\GarbageCollection\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Runner\\InvalidOrderException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php', + 'PHPUnit\\Runner\\InvalidPhptFileException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php', + 'PHPUnit\\Runner\\ParameterDoesNotExistException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php', + 'PHPUnit\\Runner\\PhptExternalFileCannotBeLoadedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php', + 'PHPUnit\\Runner\\PhptTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/PhptTestCase.php', + 'PHPUnit\\Runner\\ResultCache\\DefaultResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php', + 'PHPUnit\\Runner\\ResultCache\\NullResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php', + 'PHPUnit\\Runner\\ResultCache\\ResultCache' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php', + 'PHPUnit\\Runner\\ResultCache\\ResultCacheHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php', + 'PHPUnit\\Runner\\ResultCache\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\Runner\\ResultCache\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\Runner\\TestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php', + 'PHPUnit\\Runner\\TestSuiteSorter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteSorter.php', + 'PHPUnit\\Runner\\UnsupportedPhptSectionException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php', + 'PHPUnit\\Runner\\Version' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Version.php', + 'PHPUnit\\TestRunner\\TestResult\\BeforeTestClassMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\Collector' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Collector.php', + 'PHPUnit\\TestRunner\\TestResult\\ExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Facade.php', + 'PHPUnit\\TestRunner\\TestResult\\Issues\\Issue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Issue.php', + 'PHPUnit\\TestRunner\\TestResult\\PassedTests' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/PassedTests.php', + 'PHPUnit\\TestRunner\\TestResult\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/TestResult.php', + 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestRunnerTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSuiteFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSuiteSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestSuiteStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredPhpunitWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', + 'PHPUnit\\TestRunner\\TestResult\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\TextUI\\Application' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Application.php', + 'PHPUnit\\TextUI\\CannotOpenSocketException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php', + 'PHPUnit\\TextUI\\CliArguments\\Builder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php', + 'PHPUnit\\TextUI\\CliArguments\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php', + 'PHPUnit\\TextUI\\CliArguments\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php', + 'PHPUnit\\TextUI\\CliArguments\\XmlConfigurationFileFinder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php', + 'PHPUnit\\TextUI\\Command\\AtLeastVersionCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php', + 'PHPUnit\\TextUI\\Command\\Command' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Command.php', + 'PHPUnit\\TextUI\\Command\\GenerateConfigurationCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php', + 'PHPUnit\\TextUI\\Command\\ListGroupsCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php', + 'PHPUnit\\TextUI\\Command\\ListTestSuitesCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php', + 'PHPUnit\\TextUI\\Command\\ListTestsAsTextCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php', + 'PHPUnit\\TextUI\\Command\\ListTestsAsXmlCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php', + 'PHPUnit\\TextUI\\Command\\MigrateConfigurationCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php', + 'PHPUnit\\TextUI\\Command\\Result' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Result.php', + 'PHPUnit\\TextUI\\Command\\ShowHelpCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php', + 'PHPUnit\\TextUI\\Command\\ShowVersionCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php', + 'PHPUnit\\TextUI\\Command\\VersionCheckCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php', + 'PHPUnit\\TextUI\\Command\\WarmCodeCoverageCacheCommand' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php', + 'PHPUnit\\TextUI\\Configuration\\Builder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Builder.php', + 'PHPUnit\\TextUI\\Configuration\\CodeCoverageFilterRegistry' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php', + 'PHPUnit\\TextUI\\Configuration\\CodeCoverageReportNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php', + 'PHPUnit\\TextUI\\Configuration\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Configuration.php', + 'PHPUnit\\TextUI\\Configuration\\ConfigurationCannotBeBuiltException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php', + 'PHPUnit\\TextUI\\Configuration\\Constant' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php', + 'PHPUnit\\TextUI\\Configuration\\ConstantCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php', + 'PHPUnit\\TextUI\\Configuration\\ConstantCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\Directory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php', + 'PHPUnit\\TextUI\\Configuration\\DirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php', + 'PHPUnit\\TextUI\\Configuration\\DirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php', + 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrap' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php', + 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php', + 'PHPUnit\\TextUI\\Configuration\\ExtensionBootstrapCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\File' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/File.php', + 'PHPUnit\\TextUI\\Configuration\\FileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php', + 'PHPUnit\\TextUI\\Configuration\\FileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\FilterDirectory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php', + 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php', + 'PHPUnit\\TextUI\\Configuration\\FilterDirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\FilterNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php', + 'PHPUnit\\TextUI\\Configuration\\Group' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php', + 'PHPUnit\\TextUI\\Configuration\\GroupCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php', + 'PHPUnit\\TextUI\\Configuration\\GroupCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\IniSetting' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php', + 'PHPUnit\\TextUI\\Configuration\\IniSettingCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php', + 'PHPUnit\\TextUI\\Configuration\\IniSettingCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\LoggingNotConfiguredException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php', + 'PHPUnit\\TextUI\\Configuration\\Merger' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Merger.php', + 'PHPUnit\\TextUI\\Configuration\\NoBaselineException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php', + 'PHPUnit\\TextUI\\Configuration\\NoBootstrapException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCacheDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCliArgumentException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php', + 'PHPUnit\\TextUI\\Configuration\\NoConfigurationFileException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCoverageCacheDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php', + 'PHPUnit\\TextUI\\Configuration\\NoCustomCssFileException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php', + 'PHPUnit\\TextUI\\Configuration\\NoDefaultTestSuiteException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php', + 'PHPUnit\\TextUI\\Configuration\\NoPharExtensionDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php', + 'PHPUnit\\TextUI\\Configuration\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php', + 'PHPUnit\\TextUI\\Configuration\\PhpHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php', + 'PHPUnit\\TextUI\\Configuration\\Registry' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Registry.php', + 'PHPUnit\\TextUI\\Configuration\\Source' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php', + 'PHPUnit\\TextUI\\Configuration\\SourceFilter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php', + 'PHPUnit\\TextUI\\Configuration\\SourceMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php', + 'PHPUnit\\TextUI\\Configuration\\TestDirectory' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php', + 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php', + 'PHPUnit\\TextUI\\Configuration\\TestDirectoryCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\TestFile' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php', + 'PHPUnit\\TextUI\\Configuration\\TestFileCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php', + 'PHPUnit\\TextUI\\Configuration\\TestFileCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuiteBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php', + 'PHPUnit\\TextUI\\Configuration\\TestSuiteCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php', + 'PHPUnit\\TextUI\\Configuration\\Variable' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php', + 'PHPUnit\\TextUI\\Configuration\\VariableCollection' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php', + 'PHPUnit\\TextUI\\Configuration\\VariableCollectionIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php', + 'PHPUnit\\TextUI\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/Exception.php', + 'PHPUnit\\TextUI\\Help' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Help.php', + 'PHPUnit\\TextUI\\InvalidSocketException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php', + 'PHPUnit\\TextUI\\Output\\DefaultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\BeforeTestClassMethodErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\ProgressPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\Subscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestConsideredRiskySubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestErroredSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFailedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestFinishedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestMarkedIncompleteSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestPreparedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestRunnerExecutionStartedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestSkippedSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredErrorSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpNoticeSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitDeprecationSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredPhpunitWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ProgressPrinter\\TestTriggeredWarningSubscriber' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php', + 'PHPUnit\\TextUI\\Output\\Default\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php', + 'PHPUnit\\TextUI\\Output\\Default\\UnexpectedOutputPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php', + 'PHPUnit\\TextUI\\Output\\Facade' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Facade.php', + 'PHPUnit\\TextUI\\Output\\NullPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php', + 'PHPUnit\\TextUI\\Output\\Printer' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php', + 'PHPUnit\\TextUI\\Output\\SummaryPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php', + 'PHPUnit\\TextUI\\Output\\TestDox\\ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php', + 'PHPUnit\\TextUI\\RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php', + 'PHPUnit\\TextUI\\ShellExitCodeCalculator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php', + 'PHPUnit\\TextUI\\TestDirectoryNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php', + 'PHPUnit\\TextUI\\TestFileNotFoundException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php', + 'PHPUnit\\TextUI\\TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestRunner.php', + 'PHPUnit\\TextUI\\TestSuiteFilterProcessor' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CannotFindSchemaException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Php' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CodeCoverage\\Report\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ConvertLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCloverToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageCrap4jToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageHtmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoveragePhpToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageTextToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\CoverageXmlToReport' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\DefaultConfiguration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\FailedSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Generator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Groups' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCacheDirectoryAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\IntroduceCoverageElement' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\LoadedFromFileConfiguration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\LogToReportMigration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Junit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\Logging' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TeamCity' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Html' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Logging\\TestDox\\Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migration' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationBuilder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MigrationException' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Migrator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromFilterWhitelistToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveAttributesFromRootToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveCoverageDirectoriesToSource' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistExcludesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\MoveWhitelistIncludesToCoverage' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\PHPUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveBeStrictAboutTodoAnnotatedTestsAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheResultFileAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCacheTokensAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveConversionToExceptionsAttributes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementCacheDirectoryAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveCoverageElementProcessUncoveredFilesAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveEmptyFilter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveListeners' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLogTypes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveLoggingElements' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveNoInteractionAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemovePrinterAttributes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestDoxGroupsElement' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveTestSuiteLoaderAttributes' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RemoveVerboseAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBackupStaticAttributesAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RenameBeStrictAboutCoversAnnotationAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\RenameForceCoversAnnotationAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaDetector' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SchemaFinder' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SnapshotNodeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\SuccessfulSchemaDetectionResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\TestSuiteMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\UpdateSchemaLocation' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\ValidationResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php', + 'PHPUnit\\TextUI\\XmlConfiguration\\Validator' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php', + 'PHPUnit\\Util\\Cloner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Cloner.php', + 'PHPUnit\\Util\\Color' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Color.php', + 'PHPUnit\\Util\\Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/Exception.php', + 'PHPUnit\\Util\\ExcludeList' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ExcludeList.php', + 'PHPUnit\\Util\\Exporter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exporter.php', + 'PHPUnit\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filesystem.php', + 'PHPUnit\\Util\\Filter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filter.php', + 'PHPUnit\\Util\\GlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/GlobalState.php', + 'PHPUnit\\Util\\Http\\Downloader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Http/Downloader.php', + 'PHPUnit\\Util\\Http\\PhpDownloader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Http/PhpDownloader.php', + 'PHPUnit\\Util\\InvalidDirectoryException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php', + 'PHPUnit\\Util\\InvalidJsonException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php', + 'PHPUnit\\Util\\InvalidVersionOperatorException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php', + 'PHPUnit\\Util\\Json' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Json.php', + 'PHPUnit\\Util\\PHP\\AbstractPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php', + 'PHPUnit\\Util\\PHP\\DefaultPhpProcess' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php', + 'PHPUnit\\Util\\PHP\\PhpProcessException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/PhpProcessException.php', + 'PHPUnit\\Util\\Reflection' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Reflection.php', + 'PHPUnit\\Util\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Test.php', + 'PHPUnit\\Util\\ThrowableToStringMapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ThrowableToStringMapper.php', + 'PHPUnit\\Util\\VersionComparisonOperator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/VersionComparisonOperator.php', + 'PHPUnit\\Util\\Xml' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Xml.php', + 'PHPUnit\\Util\\Xml\\Loader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Xml/Loader.php', + 'PHPUnit\\Util\\Xml\\XmlException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Exception/XmlException.php', + 'PharIo\\Manifest\\Application' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Application.php', + 'PharIo\\Manifest\\ApplicationName' => __DIR__ . '/..' . '/phar-io/manifest/src/values/ApplicationName.php', + 'PharIo\\Manifest\\Author' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Author.php', + 'PharIo\\Manifest\\AuthorCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollection.php', + 'PharIo\\Manifest\\AuthorCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/AuthorCollectionIterator.php', + 'PharIo\\Manifest\\AuthorElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElement.php', + 'PharIo\\Manifest\\AuthorElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/AuthorElementCollection.php', + 'PharIo\\Manifest\\BundledComponent' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponent.php', + 'PharIo\\Manifest\\BundledComponentCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollection.php', + 'PharIo\\Manifest\\BundledComponentCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/BundledComponentCollectionIterator.php', + 'PharIo\\Manifest\\BundlesElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/BundlesElement.php', + 'PharIo\\Manifest\\ComponentElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElement.php', + 'PharIo\\Manifest\\ComponentElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ComponentElementCollection.php', + 'PharIo\\Manifest\\ContainsElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ContainsElement.php', + 'PharIo\\Manifest\\CopyrightElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/CopyrightElement.php', + 'PharIo\\Manifest\\CopyrightInformation' => __DIR__ . '/..' . '/phar-io/manifest/src/values/CopyrightInformation.php', + 'PharIo\\Manifest\\ElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ElementCollection.php', + 'PharIo\\Manifest\\ElementCollectionException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ElementCollectionException.php', + 'PharIo\\Manifest\\Email' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Email.php', + 'PharIo\\Manifest\\Exception' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/Exception.php', + 'PharIo\\Manifest\\ExtElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElement.php', + 'PharIo\\Manifest\\ExtElementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtElementCollection.php', + 'PharIo\\Manifest\\Extension' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Extension.php', + 'PharIo\\Manifest\\ExtensionElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ExtensionElement.php', + 'PharIo\\Manifest\\InvalidApplicationNameException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php', + 'PharIo\\Manifest\\InvalidEmailException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidEmailException.php', + 'PharIo\\Manifest\\InvalidUrlException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/InvalidUrlException.php', + 'PharIo\\Manifest\\Library' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Library.php', + 'PharIo\\Manifest\\License' => __DIR__ . '/..' . '/phar-io/manifest/src/values/License.php', + 'PharIo\\Manifest\\LicenseElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/LicenseElement.php', + 'PharIo\\Manifest\\Manifest' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Manifest.php', + 'PharIo\\Manifest\\ManifestDocument' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestDocument.php', + 'PharIo\\Manifest\\ManifestDocumentException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentException.php', + 'PharIo\\Manifest\\ManifestDocumentLoadingException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php', + 'PharIo\\Manifest\\ManifestDocumentMapper' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestDocumentMapper.php', + 'PharIo\\Manifest\\ManifestDocumentMapperException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php', + 'PharIo\\Manifest\\ManifestElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/ManifestElement.php', + 'PharIo\\Manifest\\ManifestElementException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestElementException.php', + 'PharIo\\Manifest\\ManifestLoader' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestLoader.php', + 'PharIo\\Manifest\\ManifestLoaderException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/ManifestLoaderException.php', + 'PharIo\\Manifest\\ManifestSerializer' => __DIR__ . '/..' . '/phar-io/manifest/src/ManifestSerializer.php', + 'PharIo\\Manifest\\NoEmailAddressException' => __DIR__ . '/..' . '/phar-io/manifest/src/exceptions/NoEmailAddressException.php', + 'PharIo\\Manifest\\PhpElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/PhpElement.php', + 'PharIo\\Manifest\\PhpExtensionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpExtensionRequirement.php', + 'PharIo\\Manifest\\PhpVersionRequirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/PhpVersionRequirement.php', + 'PharIo\\Manifest\\Requirement' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Requirement.php', + 'PharIo\\Manifest\\RequirementCollection' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollection.php', + 'PharIo\\Manifest\\RequirementCollectionIterator' => __DIR__ . '/..' . '/phar-io/manifest/src/values/RequirementCollectionIterator.php', + 'PharIo\\Manifest\\RequiresElement' => __DIR__ . '/..' . '/phar-io/manifest/src/xml/RequiresElement.php', + 'PharIo\\Manifest\\Type' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Type.php', + 'PharIo\\Manifest\\Url' => __DIR__ . '/..' . '/phar-io/manifest/src/values/Url.php', + 'PharIo\\Version\\AbstractVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AbstractVersionConstraint.php', + 'PharIo\\Version\\AndVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AndVersionConstraintGroup.php', + 'PharIo\\Version\\AnyVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/AnyVersionConstraint.php', + 'PharIo\\Version\\BuildMetaData' => __DIR__ . '/..' . '/phar-io/version/src/BuildMetaData.php', + 'PharIo\\Version\\ExactVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/ExactVersionConstraint.php', + 'PharIo\\Version\\Exception' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/Exception.php', + 'PharIo\\Version\\GreaterThanOrEqualToVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php', + 'PharIo\\Version\\InvalidPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php', + 'PharIo\\Version\\InvalidVersionException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/InvalidVersionException.php', + 'PharIo\\Version\\NoBuildMetaDataException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoBuildMetaDataException.php', + 'PharIo\\Version\\NoPreReleaseSuffixException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/NoPreReleaseSuffixException.php', + 'PharIo\\Version\\OrVersionConstraintGroup' => __DIR__ . '/..' . '/phar-io/version/src/constraints/OrVersionConstraintGroup.php', + 'PharIo\\Version\\PreReleaseSuffix' => __DIR__ . '/..' . '/phar-io/version/src/PreReleaseSuffix.php', + 'PharIo\\Version\\SpecificMajorAndMinorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php', + 'PharIo\\Version\\SpecificMajorVersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php', + 'PharIo\\Version\\UnsupportedVersionConstraintException' => __DIR__ . '/..' . '/phar-io/version/src/exceptions/UnsupportedVersionConstraintException.php', + 'PharIo\\Version\\Version' => __DIR__ . '/..' . '/phar-io/version/src/Version.php', + 'PharIo\\Version\\VersionConstraint' => __DIR__ . '/..' . '/phar-io/version/src/constraints/VersionConstraint.php', + 'PharIo\\Version\\VersionConstraintParser' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintParser.php', + 'PharIo\\Version\\VersionConstraintValue' => __DIR__ . '/..' . '/phar-io/version/src/VersionConstraintValue.php', + 'PharIo\\Version\\VersionNumber' => __DIR__ . '/..' . '/phar-io/version/src/VersionNumber.php', 'ReturnTypeWillChange' => __DIR__ . '/..' . '/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', 'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', + 'SebastianBergmann\\CliParser\\AmbiguousOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php', + 'SebastianBergmann\\CliParser\\Exception' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/Exception.php', + 'SebastianBergmann\\CliParser\\OptionDoesNotAllowArgumentException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php', + 'SebastianBergmann\\CliParser\\Parser' => __DIR__ . '/..' . '/sebastian/cli-parser/src/Parser.php', + 'SebastianBergmann\\CliParser\\RequiredOptionArgumentMissingException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php', + 'SebastianBergmann\\CliParser\\UnknownOptionException' => __DIR__ . '/..' . '/sebastian/cli-parser/src/exceptions/UnknownOptionException.php', + 'SebastianBergmann\\CodeCoverage\\BranchAndPathCoverageNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php', + 'SebastianBergmann\\CodeCoverage\\Data\\ProcessedCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\Data\\RawCodeCoverageData' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php', + 'SebastianBergmann\\CodeCoverage\\DeadCodeDetectionNotSupportedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Driver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PathExistsButIsNotDirectoryException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/PcovDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\PcovNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\Selector' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/Selector.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\WriteOperationFailedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugDriver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Driver/XdebugDriver.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Driver\\XdebugNotEnabledException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php', + 'SebastianBergmann\\CodeCoverage\\Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/Exception.php', + 'SebastianBergmann\\CodeCoverage\\FileCouldNotBeWrittenException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php', + 'SebastianBergmann\\CodeCoverage\\Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Filter.php', + 'SebastianBergmann\\CodeCoverage\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\NoCodeCoverageDriverWithPathCoverageSupportAvailableException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php', + 'SebastianBergmann\\CodeCoverage\\Node\\AbstractNode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/AbstractNode.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Builder' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Builder.php', + 'SebastianBergmann\\CodeCoverage\\Node\\CrapIndex' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/CrapIndex.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Node\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/File.php', + 'SebastianBergmann\\CodeCoverage\\Node\\Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Node/Iterator.php', + 'SebastianBergmann\\CodeCoverage\\ParserException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ParserException.php', + 'SebastianBergmann\\CodeCoverage\\ReflectionException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReflectionException.php', + 'SebastianBergmann\\CodeCoverage\\ReportAlreadyFinalizedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Clover.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Cobertura' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Cobertura.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Crap4j.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Colors' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Colors.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\CustomCssFile' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Html\\Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Html/Renderer.php', + 'SebastianBergmann\\CodeCoverage\\Report\\PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/PHP.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Text.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Thresholds' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Thresholds.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\BuildInformation' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Coverage.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Directory.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Facade' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Facade.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/File.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Method.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Node.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Project.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Report.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Source' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Source.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Tests.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Totals.php', + 'SebastianBergmann\\CodeCoverage\\Report\\Xml\\Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Report/Xml/Unit.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysisCacheNotConfiguredException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CachingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CodeUnitFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ExecutableLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\FileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\IgnoredLinesFindingVisitor' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php', + 'SebastianBergmann\\CodeCoverage\\StaticAnalysis\\ParsingFileAnalyser' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php', + 'SebastianBergmann\\CodeCoverage\\TestIdMissingException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Known' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Known.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Large' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Large.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Medium' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Medium.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Small' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Small.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\TestSize' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/TestSize.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestSize\\Unknown' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestSize/Unknown.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Failure' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Failure.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Known' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Known.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Success' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Success.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\TestStatus' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/TestStatus.php', + 'SebastianBergmann\\CodeCoverage\\Test\\TestStatus\\Unknown' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/TestStatus/Unknown.php', + 'SebastianBergmann\\CodeCoverage\\UnintentionallyCoveredCodeException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\DirectoryCouldNotBeCreatedException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Filesystem' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Filesystem.php', + 'SebastianBergmann\\CodeCoverage\\Util\\Percentage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Util/Percentage.php', + 'SebastianBergmann\\CodeCoverage\\Version' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Version.php', + 'SebastianBergmann\\CodeCoverage\\XmlException' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/Exception/XmlException.php', + 'SebastianBergmann\\CodeUnitReverseLookup\\Wizard' => __DIR__ . '/..' . '/sebastian/code-unit-reverse-lookup/src/Wizard.php', + 'SebastianBergmann\\CodeUnit\\ClassMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\ClassUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/ClassUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnit.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollection' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollection.php', + 'SebastianBergmann\\CodeUnit\\CodeUnitCollectionIterator' => __DIR__ . '/..' . '/sebastian/code-unit/src/CodeUnitCollectionIterator.php', + 'SebastianBergmann\\CodeUnit\\Exception' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/Exception.php', + 'SebastianBergmann\\CodeUnit\\FileUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/FileUnit.php', + 'SebastianBergmann\\CodeUnit\\FunctionUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/FunctionUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\InterfaceUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/InterfaceUnit.php', + 'SebastianBergmann\\CodeUnit\\InvalidCodeUnitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php', + 'SebastianBergmann\\CodeUnit\\Mapper' => __DIR__ . '/..' . '/sebastian/code-unit/src/Mapper.php', + 'SebastianBergmann\\CodeUnit\\NoTraitException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/NoTraitException.php', + 'SebastianBergmann\\CodeUnit\\ReflectionException' => __DIR__ . '/..' . '/sebastian/code-unit/src/exceptions/ReflectionException.php', + 'SebastianBergmann\\CodeUnit\\TraitMethodUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitMethodUnit.php', + 'SebastianBergmann\\CodeUnit\\TraitUnit' => __DIR__ . '/..' . '/sebastian/code-unit/src/TraitUnit.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', + 'SebastianBergmann\\Comparator\\DOMNodeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DOMNodeComparator.php', + 'SebastianBergmann\\Comparator\\DateTimeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DateTimeComparator.php', + 'SebastianBergmann\\Comparator\\Exception' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/Exception.php', + 'SebastianBergmann\\Comparator\\ExceptionComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ExceptionComparator.php', + 'SebastianBergmann\\Comparator\\Factory' => __DIR__ . '/..' . '/sebastian/comparator/src/Factory.php', + 'SebastianBergmann\\Comparator\\MockObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/MockObjectComparator.php', + 'SebastianBergmann\\Comparator\\NumericComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/NumericComparator.php', + 'SebastianBergmann\\Comparator\\ObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ObjectComparator.php', + 'SebastianBergmann\\Comparator\\ResourceComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ResourceComparator.php', + 'SebastianBergmann\\Comparator\\RuntimeException' => __DIR__ . '/..' . '/sebastian/comparator/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Comparator\\ScalarComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ScalarComparator.php', + 'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/SplObjectStorageComparator.php', + 'SebastianBergmann\\Comparator\\TypeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/TypeComparator.php', + 'SebastianBergmann\\Complexity\\Calculator' => __DIR__ . '/..' . '/sebastian/complexity/src/Calculator.php', + 'SebastianBergmann\\Complexity\\Complexity' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/Complexity.php', + 'SebastianBergmann\\Complexity\\ComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\ComplexityCollection' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollection.php', + 'SebastianBergmann\\Complexity\\ComplexityCollectionIterator' => __DIR__ . '/..' . '/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php', + 'SebastianBergmann\\Complexity\\CyclomaticComplexityCalculatingVisitor' => __DIR__ . '/..' . '/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php', + 'SebastianBergmann\\Complexity\\Exception' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/Exception.php', + 'SebastianBergmann\\Complexity\\RuntimeException' => __DIR__ . '/..' . '/sebastian/complexity/src/Exception/RuntimeException.php', + 'SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php', + 'SebastianBergmann\\Diff\\ConfigurationException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/ConfigurationException.php', + 'SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php', + 'SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php', + 'SebastianBergmann\\Diff\\Exception' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/Exception.php', + 'SebastianBergmann\\Diff\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/diff/src/Exception/InvalidArgumentException.php', + 'SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php', + 'SebastianBergmann\\Diff\\LongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/LongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\MemoryEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Diff\\Output\\AbstractChunkOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOnlyOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\DiffOutputBuilderInterface' => __DIR__ . '/..' . '/sebastian/diff/src/Output/DiffOutputBuilderInterface.php', + 'SebastianBergmann\\Diff\\Output\\StrictUnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Output\\UnifiedDiffOutputBuilder' => __DIR__ . '/..' . '/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php', + 'SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php', + 'SebastianBergmann\\Diff\\TimeEfficientLongestCommonSubsequenceCalculator' => __DIR__ . '/..' . '/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php', + 'SebastianBergmann\\Environment\\Console' => __DIR__ . '/..' . '/sebastian/environment/src/Console.php', + 'SebastianBergmann\\Environment\\Runtime' => __DIR__ . '/..' . '/sebastian/environment/src/Runtime.php', + 'SebastianBergmann\\Exporter\\Exporter' => __DIR__ . '/..' . '/sebastian/exporter/src/Exporter.php', + 'SebastianBergmann\\FileIterator\\ExcludeIterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/ExcludeIterator.php', + 'SebastianBergmann\\FileIterator\\Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php', + 'SebastianBergmann\\FileIterator\\Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php', + 'SebastianBergmann\\FileIterator\\Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php', + 'SebastianBergmann\\GlobalState\\CodeExporter' => __DIR__ . '/..' . '/sebastian/global-state/src/CodeExporter.php', + 'SebastianBergmann\\GlobalState\\Exception' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/Exception.php', + 'SebastianBergmann\\GlobalState\\ExcludeList' => __DIR__ . '/..' . '/sebastian/global-state/src/ExcludeList.php', + 'SebastianBergmann\\GlobalState\\Restorer' => __DIR__ . '/..' . '/sebastian/global-state/src/Restorer.php', + 'SebastianBergmann\\GlobalState\\RuntimeException' => __DIR__ . '/..' . '/sebastian/global-state/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\GlobalState\\Snapshot' => __DIR__ . '/..' . '/sebastian/global-state/src/Snapshot.php', + 'SebastianBergmann\\Invoker\\Exception' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/Exception.php', + 'SebastianBergmann\\Invoker\\Invoker' => __DIR__ . '/..' . '/phpunit/php-invoker/src/Invoker.php', + 'SebastianBergmann\\Invoker\\ProcessControlExtensionNotLoadedException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php', + 'SebastianBergmann\\Invoker\\TimeoutException' => __DIR__ . '/..' . '/phpunit/php-invoker/src/exceptions/TimeoutException.php', + 'SebastianBergmann\\LinesOfCode\\Counter' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Counter.php', + 'SebastianBergmann\\LinesOfCode\\Exception' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/Exception.php', + 'SebastianBergmann\\LinesOfCode\\IllogicalValuesException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php', + 'SebastianBergmann\\LinesOfCode\\LineCountingVisitor' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LineCountingVisitor.php', + 'SebastianBergmann\\LinesOfCode\\LinesOfCode' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/LinesOfCode.php', + 'SebastianBergmann\\LinesOfCode\\NegativeValueException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/NegativeValueException.php', + 'SebastianBergmann\\LinesOfCode\\RuntimeException' => __DIR__ . '/..' . '/sebastian/lines-of-code/src/Exception/RuntimeException.php', + 'SebastianBergmann\\ObjectEnumerator\\Enumerator' => __DIR__ . '/..' . '/sebastian/object-enumerator/src/Enumerator.php', + 'SebastianBergmann\\ObjectReflector\\ObjectReflector' => __DIR__ . '/..' . '/sebastian/object-reflector/src/ObjectReflector.php', + 'SebastianBergmann\\RecursionContext\\Context' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Context.php', + 'SebastianBergmann\\Template\\Exception' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/Exception.php', + 'SebastianBergmann\\Template\\InvalidArgumentException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php', + 'SebastianBergmann\\Template\\RuntimeException' => __DIR__ . '/..' . '/phpunit/php-text-template/src/exceptions/RuntimeException.php', + 'SebastianBergmann\\Template\\Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php', + 'SebastianBergmann\\Timer\\Duration' => __DIR__ . '/..' . '/phpunit/php-timer/src/Duration.php', + 'SebastianBergmann\\Timer\\Exception' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/Exception.php', + 'SebastianBergmann\\Timer\\NoActiveTimerException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/NoActiveTimerException.php', + 'SebastianBergmann\\Timer\\ResourceUsageFormatter' => __DIR__ . '/..' . '/phpunit/php-timer/src/ResourceUsageFormatter.php', + 'SebastianBergmann\\Timer\\TimeSinceStartOfRequestNotAvailableException' => __DIR__ . '/..' . '/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php', + 'SebastianBergmann\\Timer\\Timer' => __DIR__ . '/..' . '/phpunit/php-timer/src/Timer.php', + 'SebastianBergmann\\Type\\CallableType' => __DIR__ . '/..' . '/sebastian/type/src/type/CallableType.php', + 'SebastianBergmann\\Type\\Exception' => __DIR__ . '/..' . '/sebastian/type/src/exception/Exception.php', + 'SebastianBergmann\\Type\\FalseType' => __DIR__ . '/..' . '/sebastian/type/src/type/FalseType.php', + 'SebastianBergmann\\Type\\GenericObjectType' => __DIR__ . '/..' . '/sebastian/type/src/type/GenericObjectType.php', + 'SebastianBergmann\\Type\\IntersectionType' => __DIR__ . '/..' . '/sebastian/type/src/type/IntersectionType.php', + 'SebastianBergmann\\Type\\IterableType' => __DIR__ . '/..' . '/sebastian/type/src/type/IterableType.php', + 'SebastianBergmann\\Type\\MixedType' => __DIR__ . '/..' . '/sebastian/type/src/type/MixedType.php', + 'SebastianBergmann\\Type\\NeverType' => __DIR__ . '/..' . '/sebastian/type/src/type/NeverType.php', + 'SebastianBergmann\\Type\\NullType' => __DIR__ . '/..' . '/sebastian/type/src/type/NullType.php', + 'SebastianBergmann\\Type\\ObjectType' => __DIR__ . '/..' . '/sebastian/type/src/type/ObjectType.php', + 'SebastianBergmann\\Type\\Parameter' => __DIR__ . '/..' . '/sebastian/type/src/Parameter.php', + 'SebastianBergmann\\Type\\ReflectionMapper' => __DIR__ . '/..' . '/sebastian/type/src/ReflectionMapper.php', + 'SebastianBergmann\\Type\\RuntimeException' => __DIR__ . '/..' . '/sebastian/type/src/exception/RuntimeException.php', + 'SebastianBergmann\\Type\\SimpleType' => __DIR__ . '/..' . '/sebastian/type/src/type/SimpleType.php', + 'SebastianBergmann\\Type\\StaticType' => __DIR__ . '/..' . '/sebastian/type/src/type/StaticType.php', + 'SebastianBergmann\\Type\\TrueType' => __DIR__ . '/..' . '/sebastian/type/src/type/TrueType.php', + 'SebastianBergmann\\Type\\Type' => __DIR__ . '/..' . '/sebastian/type/src/type/Type.php', + 'SebastianBergmann\\Type\\TypeName' => __DIR__ . '/..' . '/sebastian/type/src/TypeName.php', + 'SebastianBergmann\\Type\\UnionType' => __DIR__ . '/..' . '/sebastian/type/src/type/UnionType.php', + 'SebastianBergmann\\Type\\UnknownType' => __DIR__ . '/..' . '/sebastian/type/src/type/UnknownType.php', + 'SebastianBergmann\\Type\\VoidType' => __DIR__ . '/..' . '/sebastian/type/src/type/VoidType.php', + 'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php', + 'TheSeer\\Tokenizer\\Exception' => __DIR__ . '/..' . '/theseer/tokenizer/src/Exception.php', + 'TheSeer\\Tokenizer\\NamespaceUri' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUri.php', + 'TheSeer\\Tokenizer\\NamespaceUriException' => __DIR__ . '/..' . '/theseer/tokenizer/src/NamespaceUriException.php', + 'TheSeer\\Tokenizer\\Token' => __DIR__ . '/..' . '/theseer/tokenizer/src/Token.php', + 'TheSeer\\Tokenizer\\TokenCollection' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollection.php', + 'TheSeer\\Tokenizer\\TokenCollectionException' => __DIR__ . '/..' . '/theseer/tokenizer/src/TokenCollectionException.php', + 'TheSeer\\Tokenizer\\Tokenizer' => __DIR__ . '/..' . '/theseer/tokenizer/src/Tokenizer.php', + 'TheSeer\\Tokenizer\\XMLSerializer' => __DIR__ . '/..' . '/theseer/tokenizer/src/XMLSerializer.php', '©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitd92254016c92c1549c1187a87107524d::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitd92254016c92c1549c1187a87107524d::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInitd92254016c92c1549c1187a87107524d::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4::$prefixesPsr0; + $loader->classMap = ComposerStaticIniteb8044a5f31df9017f83ac696a2e46a4::$classMap; }, null, ClassLoader::class); } diff --git a/.extlib/simplesamlphp/vendor/composer/installed.json b/.extlib/simplesamlphp/vendor/composer/installed.json index 459a58926..3dc55a9ec 100644 --- a/.extlib/simplesamlphp/vendor/composer/installed.json +++ b/.extlib/simplesamlphp/vendor/composer/installed.json @@ -1,18 +1,99 @@ { "packages": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "4be43904336affa5c2f70744a348312336afd0da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", + "reference": "4be43904336affa5c2f70744a348312336afd0da", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "time": "2023-01-05T11:28:13+00:00", + "type": "composer-plugin", + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "install-path": "../dealerdirect/phpcodesniffer-composer-installer" + }, { "name": "gettext/gettext", - "version": "v5.7.1", - "version_normalized": "5.7.1.0", + "version": "v5.7.3", + "version_normalized": "5.7.3.0", "source": { "type": "git", "url": "https://github.com/php-gettext/Gettext.git", - "reference": "a9f89e0cc9d9a67b422632b594b5f1afb16eccfc" + "reference": "95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/a9f89e0cc9d9a67b422632b594b5f1afb16eccfc", - "reference": "a9f89e0cc9d9a67b422632b594b5f1afb16eccfc", + "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1", + "reference": "95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1", "shasum": "" }, "require": { @@ -26,7 +107,7 @@ "phpunit/phpunit": "^8.0|^9.0", "squizlabs/php_codesniffer": "^3.0" }, - "time": "2024-07-24T22:05:18+00:00", + "time": "2024-12-01T10:18:08+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -59,7 +140,7 @@ "support": { "email": "oom@oscarotero.com", "issues": "https://github.com/php-gettext/Gettext/issues", - "source": "https://github.com/php-gettext/Gettext/tree/v5.7.1" + "source": "https://github.com/php-gettext/Gettext/tree/v5.7.3" }, "funding": [ { @@ -154,6 +235,68 @@ ], "install-path": "../gettext/languages" }, + { + "name": "gettext/php-scanner", + "version": "v1.3.1", + "version_normalized": "1.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-gettext/PHP-Scanner.git", + "reference": "989a2cffa1d0f43d13b14c83a50429119b5eb8e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-gettext/PHP-Scanner/zipball/989a2cffa1d0f43d13b14c83a50429119b5eb8e4", + "reference": "989a2cffa1d0f43d13b14c83a50429119b5eb8e4", + "shasum": "" + }, + "require": { + "gettext/gettext": "^5.5.0", + "nikic/php-parser": "^4.2", + "php": ">=7.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.15", + "oscarotero/php-cs-fixer-config": "^1.0", + "phpunit/phpunit": "^8.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "time": "2022-03-18T11:47:55+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Gettext\\Scanner\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "description": "PHP scanner for gettext", + "homepage": "https://github.com/php-gettext/PHP-Scanner", + "keywords": [ + "gettext", + "i18n", + "php", + "scanner", + "translation" + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/php-gettext/PHP-Scanner/issues", + "source": "https://github.com/php-gettext/PHP-Scanner/tree/v1.3.1" + }, + "install-path": "../gettext/php-scanner" + }, { "name": "gettext/translator", "version": "v1.2.0", @@ -319,391 +462,2372 @@ "install-path": "../league/uri-interfaces" }, { - "name": "psr/cache", - "version": "3.0.0", - "version_normalized": "3.0.0.0", + "name": "mikey179/vfsstream", + "version": "v1.6.12", + "version_normalized": "1.6.12.0", "source": { "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + "url": "https://github.com/bovigo/vfsStream.git", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", + "reference": "fe695ec993e0a55c3abdda10a9364eb31c6f1bf0", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=7.1.0" }, - "time": "2021-02-03T23:26:27+00:00", + "require-dev": { + "phpunit/phpunit": "^7.5||^8.5||^9.6", + "yoast/phpunit-polyfills": "^2.0" + }, + "time": "2024-08-29T18:43:31+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.6.x-dev" } }, "installation-source": "dist", "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" + "psr-0": { + "org\\bovigo\\vfs\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Frank Kleine", + "homepage": "http://frankkleine.de/", + "role": "Developer" } ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], + "description": "Virtual file system to mock the real file system in unit tests.", + "homepage": "http://vfs.bovigo.org/", "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" + "issues": "https://github.com/bovigo/vfsStream/issues", + "source": "https://github.com/bovigo/vfsStream/tree/master", + "wiki": "https://github.com/bovigo/vfsStream/wiki" }, - "install-path": "../psr/cache" + "install-path": "../mikey179/vfsstream" }, { - "name": "psr/container", - "version": "2.0.2", - "version_normalized": "2.0.2.0", + "name": "myclabs/deep-copy", + "version": "1.12.1", + "version_normalized": "1.12.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": "^7.1 || ^8.0" }, - "time": "2021-11-05T16:47:00+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, + "time": "2024-11-08T17:47:46+00:00", + "type": "library", "installation-source": "dist", "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "Psr\\Container\\": "src/" + "DeepCopy\\": "src/DeepCopy/" } }, "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", + "description": "Create deep copies (clones) of your objects", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "clone", + "copy", + "duplicate", + "object", + "object graph" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, - "install-path": "../psr/container" + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "install-path": "../myclabs/deep-copy" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "version_normalized": "1.0.0.0", + "name": "nikic/php-parser", + "version": "v4.19.4", + "version_normalized": "4.19.4.0", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/715f4d25e225bc47b293a8b997fe6ce99bf987d2", + "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2", "shasum": "" }, "require": { - "php": ">=7.2.0" + "ext-tokenizer": "*", + "php": ">=7.1" }, - "time": "2019-01-08T18:20:26+00:00", + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "time": "2024-09-29T15:01:53+00:00", + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "4.9-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Nikita Popov" } ], - "description": "Standard interfaces for event handling.", + "description": "A PHP parser written in PHP", "keywords": [ - "events", - "psr", - "psr-14" + "parser", + "php" ], "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.4" }, - "install-path": "../psr/event-dispatcher" + "install-path": "../nikic/php-parser" }, { - "name": "psr/http-factory", - "version": "1.1.0", - "version_normalized": "1.1.0.0", + "name": "phar-io/manifest", + "version": "2.0.4", + "version_normalized": "2.0.4.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "php": ">=7.1", - "psr/http-message": "^1.0 || ^2.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, - "time": "2024-04-15T12:06:14+00:00", + "time": "2024-03-03T12:33:53+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "installation-source": "dist", "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", - "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" - ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "source": "https://github.com/php-fig/http-factory" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "install-path": "../psr/http-factory" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "install-path": "../phar-io/manifest" }, { - "name": "psr/http-message", - "version": "2.0", - "version_normalized": "2.0.0.0", + "name": "phar-io/version", + "version": "3.2.1", + "version_normalized": "3.2.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, - "time": "2023-04-04T09:54:51+00:00", + "time": "2022-02-21T01:04:05+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "installation-source": "dist", "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "install-path": "../phar-io/version" + }, + { + "name": "phpstan/extension-installer", + "version": "1.4.3", + "version_normalized": "1.4.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/extension-installer.git", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/85e90b3942d06b2326fba0403ec24fe912372936", + "reference": "85e90b3942d06b2326fba0403ec24fe912372936", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "time": "2024-09-04T20:21:43+00:00", + "type": "composer-plugin", + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Composer plugin for automatic installation of PHPStan extensions", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "dev", + "static analysis" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" + "issues": "https://github.com/phpstan/extension-installer/issues", + "source": "https://github.com/phpstan/extension-installer/tree/1.4.3" }, - "install-path": "../psr/http-message" + "install-path": "../phpstan/extension-installer" }, { - "name": "psr/log", - "version": "3.0.2", - "version_normalized": "3.0.2.0", + "name": "phpstan/phpdoc-parser", + "version": "1.33.0", + "version_normalized": "1.33.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": "^7.2 || ^8.0" }, - "time": "2024-09-11T13:17:53+00:00", + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "time": "2024-10-13T11:25:22+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + }, + "install-path": "../phpstan/phpdoc-parser" + }, + { + "name": "phpstan/phpstan", + "version": "1.12.12", + "version_normalized": "1.12.12.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "time": "2024-11-28T22:13:23+00:00", + "bin": [ + "phpstan", + "phpstan.phar" + ], "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "install-path": "../phpstan/phpstan" + }, + { + "name": "phpstan/phpstan-mockery", + "version": "1.1.3", + "version_normalized": "1.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-mockery.git", + "reference": "98cac6e256b4ee60fdeb26a7dd81bb271b454e80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-mockery/zipball/98cac6e256b4ee60fdeb26a7dd81bb271b454e80", + "reference": "98cac6e256b4ee60fdeb26a7dd81bb271b454e80", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.12" + }, + "require-dev": { + "mockery/mockery": "^1.6.11", + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan-strict-rules": "^1.6", + "phpunit/phpunit": "^9.5" + }, + "time": "2024-09-11T15:47:29+00:00", + "type": "phpstan-extension", "extra": { - "branch-alias": { - "dev-master": "3.x-dev" + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "installation-source": "dist", "autoload": { "psr-4": { - "Psr\\Log\\": "src" + "PHPStan\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], + "description": "PHPStan Mockery extension", + "support": { + "issues": "https://github.com/phpstan/phpstan-mockery/issues", + "source": "https://github.com/phpstan/phpstan-mockery/tree/1.1.3" + }, + "install-path": "../phpstan/phpstan-mockery" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.16", + "version_normalized": "10.1.16.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "time": "2024-08-22T04:31:57+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "log", - "psr", - "psr-3" + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-code-coverage" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "version_normalized": "4.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-08-31T06:24:48+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-file-iterator" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "version_normalized": "4.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "time": "2023-02-03T06:56:09+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-invoker" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "version_normalized": "3.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-08-31T14:07:24+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.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", + "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", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-text-template" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "version_normalized": "6.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T06:57:52+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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", + "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/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../phpunit/php-timer" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.38", + "version_normalized": "10.5.38.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a86773b9e887a67bc53efa9da9ad6e3f2498c132", + "reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.3", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "time": "2024-10-28T13:06:21+00:00", + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.38" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "install-path": "../phpunit/phpunit" + }, + { + "name": "predis/predis", + "version": "v2.3.0", + "version_normalized": "2.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/bac46bfdb78cd6e9c7926c697012aae740cb9ec9", + "reference": "bac46bfdb78cd6e9c7926c697012aae740cb9ec9", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.3", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^8.0 || ^9.4" + }, + "suggest": { + "ext-relay": "Faster connection with in-memory caching (>=0.6.2)" + }, + "time": "2024-11-21T20:00:02+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "A flexible and feature-complete Redis client for PHP.", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "install-path": "../predis/predis" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "time": "2021-02-03T23:26:27+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": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "install-path": "../psr/cache" + }, + { + "name": "psr/container", + "version": "2.0.2", + "version_normalized": "2.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "time": "2021-11-05T16:47:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "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/2.0.2" + }, + "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-factory", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "time": "2024-04-15T12:06:14+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": "PSR-17: 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" + }, + "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": "3.0.2", + "version_normalized": "3.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "time": "2024-09-11T13:17:53+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "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/3.0.2" + }, + "install-path": "../psr/log" + }, + { + "name": "robrichards/xmlseclibs", + "version": "3.1.3", + "version_normalized": "3.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/robrichards/xmlseclibs.git", + "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/2bdfd742624d739dfadbd415f00181b4a77aaf07", + "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">= 5.4" + }, + "time": "2024-11-20T21:13:56+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "RobRichards\\XMLSecLibs\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "A PHP library for XML Security", + "homepage": "https://github.com/robrichards/xmlseclibs", + "keywords": [ + "security", + "signature", + "xml", + "xmldsig" + ], + "support": { + "issues": "https://github.com/robrichards/xmlseclibs/issues", + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.3" + }, + "install-path": "../robrichards/xmlseclibs" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2024-03-02T07:12:49+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/cli-parser" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T06:58:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/code-unit" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T06:59:15+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.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": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/code-unit-reverse-lookup" + }, + { + "name": "sebastian/comparator", + "version": "5.0.3", + "version_normalized": "5.0.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" + }, + "time": "2024-10-18T14:56:07+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.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" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/comparator" + }, + { + "name": "sebastian/complexity", + "version": "3.2.0", + "version_normalized": "3.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-12-21T08:37:17+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-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": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/complexity" + }, + { + "name": "sebastian/diff", + "version": "5.1.1", + "version_normalized": "5.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" + }, + "time": "2024-03-02T07:15:17+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-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" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/diff" + }, + { + "name": "sebastian/environment", + "version": "6.1.0", + "version_normalized": "6.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "time": "2024-03-23T08:47:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-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": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/environment" + }, + { + "name": "sebastian/exporter", + "version": "5.1.2", + "version_normalized": "5.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2024-03-02T07:17:12+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-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" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/exporter" + }, + { + "name": "sebastian/global-state", + "version": "6.0.2", + "version_normalized": "6.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "time": "2024-03-02T07:19:19+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/global-state" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.2", + "version_normalized": "2.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-12-21T08:38:20+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.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", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/lines-of-code" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "version_normalized": "5.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T07:08:32+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.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": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/object-enumerator" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "version_normalized": "3.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T07:06:18+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.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": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/object-reflector" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "version_normalized": "5.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T07:05:40+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.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" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/recursion-context" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "version_normalized": "4.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "time": "2023-02-03T07:10:45+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.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", + "role": "lead" + } ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, - "install-path": "../psr/log" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/type" }, { - "name": "robrichards/xmlseclibs", - "version": "3.1.1", - "version_normalized": "3.1.1.0", + "name": "sebastian/version", + "version": "4.0.1", + "version_normalized": "4.0.1.0", "source": { "type": "git", - "url": "https://github.com/robrichards/xmlseclibs.git", - "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/f8f19e58f26cdb42c54b214ff8a820760292f8df", - "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "ext-openssl": "*", - "php": ">= 5.4" + "php": ">=8.1" }, - "time": "2020-09-05T13:00:25+00:00", + "time": "2023-02-07T11:34:05+00:00", "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, "installation-source": "dist", "autoload": { - "psr-4": { - "RobRichards\\XMLSecLibs\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "description": "A PHP library for XML Security", - "homepage": "https://github.com/robrichards/xmlseclibs", - "keywords": [ - "security", - "signature", - "xml", - "xmldsig" + "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/robrichards/xmlseclibs/issues", - "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, - "install-path": "../robrichards/xmlseclibs" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "install-path": "../sebastian/version" }, { "name": "simplesamlphp/assert", - "version": "v1.4.0", - "version_normalized": "1.4.0.0", + "version": "v1.5.0", + "version_normalized": "1.5.0.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/assert.git", - "reference": "cf9465870eb9fb52103e045217f6dca19aee7c84" + "reference": "f6872f002d34b8e20c19d0823b107d2c74ddfd9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/cf9465870eb9fb52103e045217f6dca19aee7c84", - "reference": "cf9465870eb9fb52103e045217f6dca19aee7c84", + "url": "https://api.github.com/repos/simplesamlphp/assert/zipball/f6872f002d34b8e20c19d0823b107d2c74ddfd9d", + "reference": "f6872f002d34b8e20c19d0823b107d2c74ddfd9d", "shasum": "" }, "require": { @@ -719,7 +2843,7 @@ "ext-intl": "*", "simplesamlphp/simplesamlphp-test-framework": "^1.7" }, - "time": "2024-10-28T22:10:22+00:00", + "time": "2024-11-19T18:52:10+00:00", "type": "library", "extra": { "branch-alias": { @@ -749,23 +2873,23 @@ "description": "A wrapper around webmozart/assert to make it useful beyond checking method arguments", "support": { "issues": "https://github.com/simplesamlphp/assert/issues", - "source": "https://github.com/simplesamlphp/assert/tree/v1.4.0" + "source": "https://github.com/simplesamlphp/assert/tree/v1.5.0" }, "install-path": "../simplesamlphp/assert" }, { "name": "simplesamlphp/composer-module-installer", - "version": "v1.3.4", - "version_normalized": "1.3.4.0", + "version": "v1.3.5", + "version_normalized": "1.3.5.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/composer-module-installer.git", - "reference": "36508ed9580a30c4d5ab0bb3c25c00d0b5d42946" + "reference": "7bf413c2d28e48dff6755d74a7e45087cf144604" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/composer-module-installer/zipball/36508ed9580a30c4d5ab0bb3c25c00d0b5d42946", - "reference": "36508ed9580a30c4d5ab0bb3c25c00d0b5d42946", + "url": "https://api.github.com/repos/simplesamlphp/composer-module-installer/zipball/7bf413c2d28e48dff6755d74a7e45087cf144604", + "reference": "7bf413c2d28e48dff6755d74a7e45087cf144604", "shasum": "" }, "require": { @@ -777,7 +2901,7 @@ "composer/composer": "^2.4", "simplesamlphp/simplesamlphp-test-framework": "^1.2.1" }, - "time": "2023-03-08T20:58:22+00:00", + "time": "2024-11-16T09:42:27+00:00", "type": "composer-plugin", "extra": { "class": "SimpleSAML\\Composer\\ModuleInstallerPlugin" @@ -795,7 +2919,7 @@ "description": "A Composer plugin that allows installing SimpleSAMLphp modules through Composer.", "support": { "issues": "https://github.com/simplesamlphp/composer-module-installer/issues", - "source": "https://github.com/simplesamlphp/composer-module-installer/tree/v1.3.4" + "source": "https://github.com/simplesamlphp/composer-module-installer/tree/v1.3.5" }, "install-path": "../simplesamlphp/composer-module-installer" }, @@ -846,17 +2970,17 @@ }, { "name": "simplesamlphp/saml2", - "version": "v4.6.12", - "version_normalized": "4.6.12.0", + "version": "v4.16.14", + "version_normalized": "4.16.14.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/saml2.git", - "reference": "9545abd0d9d48388f2fa00469c5c1e0294f0303e" + "reference": "fe6c7bdda5e166e326d19d78f230d959ab51d01d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/9545abd0d9d48388f2fa00469c5c1e0294f0303e", - "reference": "9545abd0d9d48388f2fa00469c5c1e0294f0303e", + "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/fe6c7bdda5e166e326d19d78f230d959ab51d01d", + "reference": "fe6c7bdda5e166e326d19d78f230d959ab51d01d", "shasum": "" }, "require": { @@ -868,6 +2992,9 @@ "robrichards/xmlseclibs": "^3.1.1", "webmozart/assert": "^1.9" }, + "conflict": { + "robrichards/xmlseclibs": "3.1.2" + }, "require-dev": { "mockery/mockery": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", @@ -875,7 +3002,7 @@ "simplesamlphp/simplesamlphp-test-framework": "~0.1.0", "squizlabs/php_codesniffer": "~3.5" }, - "time": "2024-04-25T14:10:08+00:00", + "time": "2024-12-01T22:26:30+00:00", "type": "library", "extra": { "branch-alias": { @@ -901,30 +3028,93 @@ "description": "SAML2 PHP library from SimpleSAMLphp", "support": { "issues": "https://github.com/simplesamlphp/saml2/issues", - "source": "https://github.com/simplesamlphp/saml2/tree/v4.6.12" + "source": "https://github.com/simplesamlphp/saml2/tree/v4.16.14" }, "install-path": "../simplesamlphp/saml2" }, + { + "name": "simplesamlphp/saml2-legacy", + "version": "v4.16.14", + "version_normalized": "4.16.14.0", + "source": { + "type": "git", + "url": "https://github.com/simplesamlphp/saml2-legacy.git", + "reference": "a9ee3a0510780d157ee8e78e7d429e47d736a208" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/a9ee3a0510780d157ee8e78e7d429e47d736a208", + "reference": "a9ee3a0510780d157ee8e78e7d429e47d736a208", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-openssl": "*", + "ext-zlib": "*", + "php": ">=7.1 || ^8.0", + "psr/log": "~1.1 || ^2.0 || ^3.0", + "robrichards/xmlseclibs": "^3.1.1", + "webmozart/assert": "^1.9" + }, + "conflict": { + "robrichards/xmlseclibs": "3.1.2" + }, + "require-dev": { + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "sebastian/phpcpd": "~4.1 || ^5.0 || ^6.0", + "simplesamlphp/simplesamlphp-test-framework": "~0.1.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "time": "2024-12-01T22:26:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "v4.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "SAML2\\": "src/SAML2" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Andreas Ã…kre Solberg", + "email": "andreas.solberg@uninett.no" + } + ], + "description": "SAML2 PHP library from SimpleSAMLphp", + "support": { + "source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.16.14" + }, + "install-path": "../simplesamlphp/saml2-legacy" + }, { "name": "simplesamlphp/simplesamlphp-assets-base", - "version": "v2.3.1", - "version_normalized": "2.3.1.0", + "version": "v2.3.2", + "version_normalized": "2.3.2.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/simplesamlphp-assets-base.git", - "reference": "b21b0a05cdedce3eb242b06d9bea30186bfea8e1" + "reference": "3f83d1afb16a2a807ac26f6a6a8e2f03bad75abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-assets-base/zipball/b21b0a05cdedce3eb242b06d9bea30186bfea8e1", - "reference": "b21b0a05cdedce3eb242b06d9bea30186bfea8e1", + "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-assets-base/zipball/3f83d1afb16a2a807ac26f6a6a8e2f03bad75abe", + "reference": "3f83d1afb16a2a807ac26f6a6a8e2f03bad75abe", "shasum": "" }, "require": { "php": "^8.1", "simplesamlphp/composer-module-installer": "^1.3.4" }, - "time": "2024-10-13T01:14:49+00:00", + "time": "2024-12-01T01:26:55+00:00", "type": "simplesamlphp-module", "installation-source": "dist", "notification-url": "https://packagist.org/downloads/", @@ -940,23 +3130,143 @@ "description": "Assets for the SimpleSAMLphp main repository", "support": { "issues": "https://github.com/simplesamlphp/simplesamlphp-assets-base/issues", - "source": "https://github.com/simplesamlphp/simplesamlphp-assets-base/tree/v2.3.1" + "source": "https://github.com/simplesamlphp/simplesamlphp-assets-base/tree/v2.3.2" }, "install-path": "../../public/assets/base" }, + { + "name": "simplesamlphp/simplesamlphp-module-adfs", + "version": "v2.1.7", + "version_normalized": "2.1.7.0", + "source": { + "type": "git", + "url": "https://github.com/simplesamlphp/simplesamlphp-module-adfs.git", + "reference": "3aef826c02a2934b06668730260df0b0138824f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-module-adfs/zipball/3aef826c02a2934b06668730260df0b0138824f7", + "reference": "3aef826c02a2934b06668730260df0b0138824f7", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^8.1", + "robrichards/xmlseclibs": "^3.1", + "simplesamlphp/assert": "^1.0", + "simplesamlphp/composer-module-installer": "^1.3.2", + "simplesamlphp/saml2-legacy": "^4.6", + "simplesamlphp/simplesamlphp": "^2.3", + "simplesamlphp/xml-security": "^1.6", + "symfony/http-foundation": "^6.4" + }, + "require-dev": { + "simplesamlphp/simplesamlphp-test-framework": "^1.5.4" + }, + "time": "2024-09-01T09:36:25+00:00", + "type": "simplesamlphp-module", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "SimpleSAML\\Module\\adfs\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Tim van Dijen", + "email": "tvdijen@gmail.com" + } + ], + "description": "A module that implements the WS-federation IDP", + "keywords": [ + "adfs", + "simplesamlphp" + ], + "support": { + "issues": "https://github.com/simplesamlphp/simplesamlphp-module-adfs/issues", + "source": "https://github.com/simplesamlphp/simplesamlphp-module-adfs" + }, + "install-path": "../../modules/adfs" + }, + { + "name": "simplesamlphp/simplesamlphp-test-framework", + "version": "v1.7.10", + "version_normalized": "1.7.10.0", + "source": { + "type": "git", + "url": "https://github.com/simplesamlphp/simplesamlphp-test-framework.git", + "reference": "157dbad53f1fc10610b23e9457eec20d0e4ad5aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplesamlphp/simplesamlphp-test-framework/zipball/157dbad53f1fc10610b23e9457eec20d0e4ad5aa", + "reference": "157dbad53f1fc10610b23e9457eec20d0e4ad5aa", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": "^8.1", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1", + "phpunit/phpunit": "^10.0 || ^11.0", + "psr/log": "^2.0 || ^3.0", + "slevomat/coding-standard": "^8.15", + "symfony/phpunit-bridge": "^6.4 || ^7.0" + }, + "require-dev": { + "simplesamlphp/simplesamlphp": "^2" + }, + "time": "2024-08-19T08:33:29+00:00", + "type": "project", + "installation-source": "dist", + "autoload": { + "psr-4": { + "SimpleSAML\\TestUtils\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Tim van Dijen", + "email": "tvdijen@gmail.com" + } + ], + "description": "Test framework for SimpleSAMLphp and related repositories ", + "keywords": [ + "test-framework" + ], + "support": { + "issues": "https://github.com/simplesamlphp/simplesamlphp-test-framework/issues", + "source": "https://github.com/simplesamlphp/simplesamlphp-test-framework" + }, + "install-path": "../simplesamlphp/simplesamlphp-test-framework" + }, { "name": "simplesamlphp/xml-common", - "version": "v1.18.5", - "version_normalized": "1.18.5.0", + "version": "v1.20.0", + "version_normalized": "1.20.0.0", "source": { "type": "git", "url": "https://github.com/simplesamlphp/xml-common.git", - "reference": "daed5738bc22067c9b0abec2d2b877dc8a1d7647" + "reference": "9cf986ee7d97c02feb992c78f51024f45b068c19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/daed5738bc22067c9b0abec2d2b877dc8a1d7647", - "reference": "daed5738bc22067c9b0abec2d2b877dc8a1d7647", + "url": "https://api.github.com/repos/simplesamlphp/xml-common/zipball/9cf986ee7d97c02feb992c78f51024f45b068c19", + "reference": "9cf986ee7d97c02feb992c78f51024f45b068c19", "shasum": "" }, "require": { @@ -974,7 +3284,7 @@ "require-dev": { "simplesamlphp/simplesamlphp-test-framework": "^1.7" }, - "time": "2024-11-06T09:36:15+00:00", + "time": "2024-12-01T23:01:07+00:00", "type": "simplesamlphp-xmlprovider", "installation-source": "dist", "autoload": { @@ -1003,91 +3313,242 @@ "xml" ], "support": { - "issues": "https://github.com/simplesamlphp/xml-common/issues", - "source": "https://github.com/simplesamlphp/xml-common" + "issues": "https://github.com/simplesamlphp/xml-common/issues", + "source": "https://github.com/simplesamlphp/xml-common" + }, + "install-path": "../simplesamlphp/xml-common" + }, + { + "name": "simplesamlphp/xml-security", + "version": "v1.10.0", + "version_normalized": "1.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/simplesamlphp/xml-security.git", + "reference": "2f478b2308b06c10542488ce9690a98baaf2fdfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/2f478b2308b06c10542488ce9690a98baaf2fdfa", + "reference": "2f478b2308b06c10542488ce9690a98baaf2fdfa", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-pcre": "*", + "ext-spl": "*", + "php": "^8.1", + "simplesamlphp/assert": "^1.5", + "simplesamlphp/xml-common": "^1.20.0" + }, + "require-dev": { + "simplesamlphp/simplesamlphp-test-framework": "^1.7" + }, + "time": "2024-12-01T23:34:04+00:00", + "type": "simplesamlphp-xmlprovider", + "installation-source": "dist", + "autoload": { + "psr-4": { + "SimpleSAML\\XMLSecurity\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Jaime Perez Crespo", + "email": "jaime.perez@uninett.no", + "role": "Maintainer" + }, + { + "name": "Tim van Dijen", + "email": "tvdijen@gmail.com", + "role": "Maintainer" + } + ], + "description": "SimpleSAMLphp library for XML Security", + "homepage": "https://github.com/simplesamlphp/xml-security", + "keywords": [ + "security", + "signature", + "xml", + "xmldsig" + ], + "support": { + "issues": "https://github.com/simplesamlphp/xml-security/issues", + "source": "https://github.com/simplesamlphp/xml-security/tree/v1.10.0" + }, + "install-path": "../simplesamlphp/xml-security" + }, + { + "name": "slevomat/coding-standard", + "version": "8.15.0", + "version_normalized": "8.15.0.0", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "7d1d957421618a3803b593ec31ace470177d7817" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817", + "reference": "7d1d957421618a3803b593ec31ace470177d7817", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", + "php": "^7.2 || ^8.0", + "phpstan/phpdoc-parser": "^1.23.1", + "squizlabs/php_codesniffer": "^3.9.0" + }, + "require-dev": { + "phing/phing": "2.17.4", + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpstan/phpstan": "1.10.60", + "phpstan/phpstan-deprecation-rules": "1.1.4", + "phpstan/phpstan-phpunit": "1.3.16", + "phpstan/phpstan-strict-rules": "1.5.2", + "phpunit/phpunit": "8.5.21|9.6.8|10.5.11" + }, + "time": "2024-03-09T15:20:58+00:00", + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.15.0" }, - "install-path": "../simplesamlphp/xml-common" + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "install-path": "../slevomat/coding-standard" }, { - "name": "simplesamlphp/xml-security", - "version": "v1.9.5", - "version_normalized": "1.9.5.0", + "name": "squizlabs/php_codesniffer", + "version": "3.11.1", + "version_normalized": "3.11.1.0", "source": { "type": "git", - "url": "https://github.com/simplesamlphp/xml-security.git", - "reference": "91e31f5930305e84ad92d573faf817abc8ad09c9" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simplesamlphp/xml-security/zipball/91e31f5930305e84ad92d573faf817abc8ad09c9", - "reference": "91e31f5930305e84ad92d573faf817abc8ad09c9", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", + "reference": "19473c30efe4f7b3cd42522d0b2e6e7f243c6f87", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-hash": "*", - "ext-mbstring": "*", - "ext-openssl": "*", - "ext-pcre": "*", - "ext-spl": "*", - "php": "^8.1", - "simplesamlphp/assert": "^1.3", - "simplesamlphp/xml-common": "^1.18" + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" }, "require-dev": { - "simplesamlphp/simplesamlphp-test-framework": "^1.7" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, - "time": "2024-09-16T21:10:04+00:00", - "type": "simplesamlphp-xmlprovider", - "installation-source": "dist", - "autoload": { - "psr-4": { - "SimpleSAML\\XMLSecurity\\": "src/" + "time": "2024-11-16T12:02:36+00:00", + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" } }, + "installation-source": "dist", "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-2.1-or-later" + "BSD-3-Clause" ], "authors": [ { - "name": "Jaime Perez Crespo", - "email": "jaime.perez@uninett.no", - "role": "Maintainer" + "name": "Greg Sherwood", + "role": "Former lead" }, { - "name": "Tim van Dijen", - "email": "tvdijen@gmail.com", - "role": "Maintainer" + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "description": "SimpleSAMLphp library for XML Security", - "homepage": "https://github.com/simplesamlphp/xml-security", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ - "security", - "signature", - "xml", - "xmldsig" + "phpcs", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/simplesamlphp/xml-security/issues", - "source": "https://github.com/simplesamlphp/xml-security/tree/v1.9.5" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, - "install-path": "../simplesamlphp/xml-security" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "install-path": "../squizlabs/php_codesniffer" }, { "name": "symfony/cache", - "version": "v6.4.14", - "version_normalized": "6.4.14.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "36fb8aa88833708e9f29014b6f15fac051a8b613" + "reference": "70d60e9a3603108563010f8592dff15a6f15dfae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/36fb8aa88833708e9f29014b6f15fac051a8b613", - "reference": "36fb8aa88833708e9f29014b6f15fac051a8b613", + "url": "https://api.github.com/repos/symfony/cache/zipball/70d60e9a3603108563010f8592dff15a6f15dfae", + "reference": "70d60e9a3603108563010f8592dff15a6f15dfae", "shasum": "" }, "require": { @@ -1121,7 +3582,7 @@ "symfony/messenger": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2024-11-05T15:34:40+00:00", + "time": "2024-11-20T10:10:54+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1156,7 +3617,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.14" + "source": "https://github.com/symfony/cache/tree/v6.4.16" }, "funding": [ { @@ -1176,24 +3637,24 @@ }, { "name": "symfony/cache-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197" + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", "shasum": "" }, "require": { "php": ">=8.1", "psr/cache": "^3.0" }, - "time": "2024-04-18T09:32:20+00:00", + "time": "2024-09-25T14:20:29+00:00", "type": "library", "extra": { "branch-alias": { @@ -1235,7 +3696,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" }, "funding": [ { @@ -1430,17 +3891,17 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.15", - "version_normalized": "6.4.15.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "70ab1f65a4516ef741e519ea938e6aa465e6aa36" + "reference": "7a379d8871f6a36f01559c14e11141cc02eb8dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/70ab1f65a4516ef741e519ea938e6aa465e6aa36", - "reference": "70ab1f65a4516ef741e519ea938e6aa465e6aa36", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/7a379d8871f6a36f01559c14e11141cc02eb8dc8", + "reference": "7a379d8871f6a36f01559c14e11141cc02eb8dc8", "shasum": "" }, "require": { @@ -1466,7 +3927,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2024-11-09T06:56:25+00:00", + "time": "2024-11-25T14:52:46+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1494,7 +3955,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.15" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.16" }, "funding": [ { @@ -1514,23 +3975,23 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2024-04-18T09:32:20+00:00", + "time": "2024-09-25T14:20:29+00:00", "type": "library", "extra": { "branch-alias": { @@ -1564,7 +4025,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -1745,24 +4206,24 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "time": "2024-04-18T09:32:20+00:00", + "time": "2024-09-25T14:20:29+00:00", "type": "library", "extra": { "branch-alias": { @@ -1804,7 +4265,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -2112,17 +4573,17 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.15", - "version_normalized": "6.4.15.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6" + "reference": "431771b7a6f662f1575b3cfc8fd7617aa9864d57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6", - "reference": "9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/431771b7a6f662f1575b3cfc8fd7617aa9864d57", + "reference": "431771b7a6f662f1575b3cfc8fd7617aa9864d57", "shasum": "" }, "require": { @@ -2144,7 +4605,7 @@ "symfony/mime": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, - "time": "2024-11-08T16:09:24+00:00", + "time": "2024-11-13T18:58:10+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2172,7 +4633,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.15" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.16" }, "funding": [ { @@ -2192,17 +4653,17 @@ }, { "name": "symfony/http-kernel", - "version": "v6.4.15", - "version_normalized": "6.4.15.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b002a5b3947653c5aee3adac2a024ea615fd3ff5" + "reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b002a5b3947653c5aee3adac2a024ea615fd3ff5", - "reference": "b002a5b3947653c5aee3adac2a024ea615fd3ff5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", + "reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", "shasum": "" }, "require": { @@ -2261,7 +4722,7 @@ "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2024-11-13T13:57:37+00:00", + "time": "2024-11-27T12:49:36+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2289,7 +4750,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.15" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.16" }, "funding": [ { @@ -2468,6 +4929,91 @@ ], "install-path": "../symfony/password-hasher" }, + { + "name": "symfony/phpunit-bridge", + "version": "v7.2.0", + "version_normalized": "7.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "2bbde92ab25a0e2c88160857af7be9db5da0d145" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2bbde92ab25a0e2c88160857af7be9db5da0d145", + "reference": "2bbde92ab25a0e2c88160857af7be9db5da0d145", + "shasum": "" + }, + "require": { + "php": ">=7.2.5" + }, + "conflict": { + "phpunit/phpunit": "<7.5|9.1.2" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/error-handler": "^5.4|^6.4|^7.0", + "symfony/polyfill-php81": "^1.27" + }, + "time": "2024-11-13T16:15:23+00:00", + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "thanks": { + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/", + "/bin/" + ] + }, + "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 utilities for PHPUnit, especially user deprecation notices management", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.2.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/phpunit-bridge" + }, { "name": "symfony/polyfill-ctype", "version": "v1.31.0", @@ -3045,17 +5591,17 @@ }, { "name": "symfony/routing", - "version": "v6.4.13", - "version_normalized": "6.4.13.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "640a74250d13f9c30d5ca045b6aaaabcc8215278" + "reference": "91e02e606b4b705c2f4fb42f7e7708b7923a3220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/640a74250d13f9c30d5ca045b6aaaabcc8215278", - "reference": "640a74250d13f9c30d5ca045b6aaaabcc8215278", + "url": "https://api.github.com/repos/symfony/routing/zipball/91e02e606b4b705c2f4fb42f7e7708b7923a3220", + "reference": "91e02e606b4b705c2f4fb42f7e7708b7923a3220", "shasum": "" }, "require": { @@ -3077,7 +5623,7 @@ "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2024-10-01T08:30:56+00:00", + "time": "2024-11-13T15:31:34+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3111,7 +5657,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.13" + "source": "https://github.com/symfony/routing/tree/v6.4.16" }, "funding": [ { @@ -3131,17 +5677,17 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -3152,7 +5698,7 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "time": "2024-04-18T09:32:20+00:00", + "time": "2024-09-25T14:20:29+00:00", "type": "library", "extra": { "branch-alias": { @@ -3197,7 +5743,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -3304,25 +5850,123 @@ ], "install-path": "../symfony/string" }, + { + "name": "symfony/translation", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/bee9bfabfa8b4045a66bf82520e492cddbaffa66", + "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.18|^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "time": "2024-09-27T18:14:25+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "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 to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.4.13" + }, + "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/translation" + }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", - "version_normalized": "3.5.0.0", + "version": "v3.5.1", + "version_normalized": "3.5.1.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2024-04-18T09:32:20+00:00", + "time": "2024-09-25T14:20:29+00:00", "type": "library", "extra": { "branch-alias": { @@ -3367,7 +6011,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -3387,17 +6031,17 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.4.13", - "version_normalized": "6.4.13.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "ec3511eef0576f378b2758da9e1c157086babd59" + "reference": "32ec012ed4f6426441a66014471bdb26674744be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/ec3511eef0576f378b2758da9e1c157086babd59", - "reference": "ec3511eef0576f378b2758da9e1c157086babd59", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/32ec012ed4f6426441a66014471bdb26674744be", + "reference": "32ec012ed4f6426441a66014471bdb26674744be", "shasum": "" }, "require": { @@ -3451,7 +6095,7 @@ "twig/inky-extra": "^2.12|^3", "twig/markdown-extra": "^2.12|^3" }, - "time": "2024-10-25T15:07:50+00:00", + "time": "2024-11-25T11:59:11+00:00", "type": "symfony-bridge", "installation-source": "dist", "autoload": { @@ -3479,7 +6123,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.13" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.16" }, "funding": [ { @@ -3740,19 +6384,72 @@ ], "install-path": "../symfony/yaml" }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "version_normalized": "1.2.3.0", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "time": "2024-03-03T12:36:25+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "install-path": "../theseer/tokenizer" + }, { "name": "twig/intl-extra", - "version": "v3.13.0", - "version_normalized": "3.13.0.0", + "version": "v3.16.0", + "version_normalized": "3.16.0.0", "source": { "type": "git", "url": "https://github.com/twigphp/intl-extra.git", - "reference": "1b8d78c5db08bdc61015fd55009d2e84b3aa7e38" + "reference": "4eeab2a3f8d04d1838be7251ab2d183f817aea7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/1b8d78c5db08bdc61015fd55009d2e84b3aa7e38", - "reference": "1b8d78c5db08bdc61015fd55009d2e84b3aa7e38", + "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/4eeab2a3f8d04d1838be7251ab2d183f817aea7b", + "reference": "4eeab2a3f8d04d1838be7251ab2d183f817aea7b", "shasum": "" }, "require": { @@ -3763,7 +6460,7 @@ "require-dev": { "symfony/phpunit-bridge": "^6.4|^7.0" }, - "time": "2024-09-03T13:08:40+00:00", + "time": "2024-11-20T13:19:52+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3793,7 +6490,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/intl-extra/tree/v3.13.0" + "source": "https://github.com/twigphp/intl-extra/tree/v3.16.0" }, "funding": [ { @@ -3809,17 +6506,17 @@ }, { "name": "twig/twig", - "version": "v3.14.2", - "version_normalized": "3.14.2.0", + "version": "v3.16.0", + "version_normalized": "3.16.0.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a" + "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", - "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/475ad2dc97d65d8631393e721e7e44fb544f0561", + "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561", "shasum": "" }, "require": { @@ -3830,10 +6527,11 @@ "symfony/polyfill-php81": "^1.29" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, - "time": "2024-11-07T12:36:22+00:00", + "time": "2024-11-29T08:27:05+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3875,7 +6573,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.2" + "source": "https://github.com/twigphp/Twig/tree/v3.16.0" }, "funding": [ { @@ -3951,6 +6649,48 @@ "install-path": "../webmozart/assert" } ], - "dev": false, - "dev-package-names": [] + "dev": true, + "dev-package-names": [ + "dealerdirect/phpcodesniffer-composer-installer", + "gettext/php-scanner", + "mikey179/vfsstream", + "myclabs/deep-copy", + "nikic/php-parser", + "phar-io/manifest", + "phar-io/version", + "phpstan/extension-installer", + "phpstan/phpdoc-parser", + "phpstan/phpstan", + "phpstan/phpstan-mockery", + "phpunit/php-code-coverage", + "phpunit/php-file-iterator", + "phpunit/php-invoker", + "phpunit/php-text-template", + "phpunit/php-timer", + "phpunit/phpunit", + "predis/predis", + "sebastian/cli-parser", + "sebastian/code-unit", + "sebastian/code-unit-reverse-lookup", + "sebastian/comparator", + "sebastian/complexity", + "sebastian/diff", + "sebastian/environment", + "sebastian/exporter", + "sebastian/global-state", + "sebastian/lines-of-code", + "sebastian/object-enumerator", + "sebastian/object-reflector", + "sebastian/recursion-context", + "sebastian/type", + "sebastian/version", + "simplesamlphp/saml2-legacy", + "simplesamlphp/simplesamlphp-module-adfs", + "simplesamlphp/simplesamlphp-test-framework", + "slevomat/coding-standard", + "squizlabs/php_codesniffer", + "symfony/phpunit-bridge", + "symfony/translation", + "theseer/tokenizer" + ] } diff --git a/.extlib/simplesamlphp/vendor/composer/installed.php b/.extlib/simplesamlphp/vendor/composer/installed.php index fbf726ac3..4f7b8e89c 100644 --- a/.extlib/simplesamlphp/vendor/composer/installed.php +++ b/.extlib/simplesamlphp/vendor/composer/installed.php @@ -1,19 +1,28 @@ array( 'name' => 'simplesamlphp/simplesamlphp', - 'pretty_version' => 'v2.3.3', - 'version' => '2.3.3.0', + 'pretty_version' => 'v2.3.5', + 'version' => '2.3.5.0', 'reference' => null, 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), - 'dev' => false, + 'dev' => true, ), 'versions' => array( + 'dealerdirect/phpcodesniffer-composer-installer' => array( + 'pretty_version' => 'v1.0.0', + 'version' => '1.0.0.0', + 'reference' => '4be43904336affa5c2f70744a348312336afd0da', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'gettext/gettext' => array( - 'pretty_version' => 'v5.7.1', - 'version' => '5.7.1.0', - 'reference' => 'a9f89e0cc9d9a67b422632b594b5f1afb16eccfc', + 'pretty_version' => 'v5.7.3', + 'version' => '5.7.3.0', + 'reference' => '95820f020e4f2f05e0bbaa5603e4c6ec3edc50f1', 'type' => 'library', 'install_path' => __DIR__ . '/../gettext/gettext', 'aliases' => array(), @@ -28,6 +37,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'gettext/php-scanner' => array( + 'pretty_version' => 'v1.3.1', + 'version' => '1.3.1.0', + 'reference' => '989a2cffa1d0f43d13b14c83a50429119b5eb8e4', + 'type' => 'library', + 'install_path' => __DIR__ . '/../gettext/php-scanner', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'gettext/translator' => array( 'pretty_version' => 'v1.2.0', 'version' => '1.2.0.0', @@ -46,6 +64,150 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'mikey179/vfsstream' => array( + 'pretty_version' => 'v1.6.12', + 'version' => '1.6.12.0', + 'reference' => 'fe695ec993e0a55c3abdda10a9364eb31c6f1bf0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../mikey179/vfsstream', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'myclabs/deep-copy' => array( + 'pretty_version' => '1.12.1', + 'version' => '1.12.1.0', + 'reference' => '123267b2c49fbf30d78a7b2d333f6be754b94845', + 'type' => 'library', + 'install_path' => __DIR__ . '/../myclabs/deep-copy', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'nikic/php-parser' => array( + 'pretty_version' => 'v4.19.4', + 'version' => '4.19.4.0', + 'reference' => '715f4d25e225bc47b293a8b997fe6ce99bf987d2', + 'type' => 'library', + 'install_path' => __DIR__ . '/../nikic/php-parser', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phar-io/manifest' => array( + 'pretty_version' => '2.0.4', + 'version' => '2.0.4.0', + 'reference' => '54750ef60c58e43759730615a392c31c80e23176', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phar-io/manifest', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phar-io/version' => array( + 'pretty_version' => '3.2.1', + 'version' => '3.2.1.0', + 'reference' => '4f7fd7836c6f332bb2933569e566a0d6c4cbed74', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phar-io/version', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpstan/extension-installer' => array( + 'pretty_version' => '1.4.3', + 'version' => '1.4.3.0', + 'reference' => '85e90b3942d06b2326fba0403ec24fe912372936', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../phpstan/extension-installer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpstan/phpdoc-parser' => array( + 'pretty_version' => '1.33.0', + 'version' => '1.33.0.0', + 'reference' => '82a311fd3690fb2bf7b64d5c98f912b3dd746140', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpstan/phpdoc-parser', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpstan/phpstan' => array( + 'pretty_version' => '1.12.12', + 'version' => '1.12.12.0', + 'reference' => 'b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpstan/phpstan', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpstan/phpstan-mockery' => array( + 'pretty_version' => '1.1.3', + 'version' => '1.1.3.0', + 'reference' => '98cac6e256b4ee60fdeb26a7dd81bb271b454e80', + 'type' => 'phpstan-extension', + 'install_path' => __DIR__ . '/../phpstan/phpstan-mockery', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-code-coverage' => array( + 'pretty_version' => '10.1.16', + 'version' => '10.1.16.0', + 'reference' => '7e308268858ed6baedc8704a304727d20bc07c77', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-code-coverage', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-file-iterator' => array( + 'pretty_version' => '4.1.0', + 'version' => '4.1.0.0', + 'reference' => 'a95037b6d9e608ba092da1b23931e537cadc3c3c', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-file-iterator', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-invoker' => array( + 'pretty_version' => '4.0.0', + 'version' => '4.0.0.0', + 'reference' => 'f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-invoker', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-text-template' => array( + 'pretty_version' => '3.0.1', + 'version' => '3.0.1.0', + 'reference' => '0c7b06ff49e3d5072f057eb1fa59258bf287a748', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-text-template', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/php-timer' => array( + 'pretty_version' => '6.0.0', + 'version' => '6.0.0.0', + 'reference' => 'e2a2d67966e740530f4a3343fe2e030ffdc1161d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/php-timer', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpunit/phpunit' => array( + 'pretty_version' => '10.5.38', + 'version' => '10.5.38.0', + 'reference' => 'a86773b9e887a67bc53efa9da9ad6e3f2498c132', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpunit/phpunit', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'predis/predis' => array( + 'pretty_version' => 'v2.3.0', + 'version' => '2.3.0.0', + 'reference' => 'bac46bfdb78cd6e9c7926c697012aae740cb9ec9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../predis/predis', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'psr/cache' => array( 'pretty_version' => '3.0.0', 'version' => '3.0.0.0', @@ -131,27 +293,162 @@ ), ), 'robrichards/xmlseclibs' => array( - 'pretty_version' => '3.1.1', - 'version' => '3.1.1.0', - 'reference' => 'f8f19e58f26cdb42c54b214ff8a820760292f8df', + 'pretty_version' => '3.1.3', + 'version' => '3.1.3.0', + 'reference' => '2bdfd742624d739dfadbd415f00181b4a77aaf07', 'type' => 'library', 'install_path' => __DIR__ . '/../robrichards/xmlseclibs', 'aliases' => array(), 'dev_requirement' => false, ), + 'sebastian/cli-parser' => array( + 'pretty_version' => '2.0.1', + 'version' => '2.0.1.0', + 'reference' => 'c34583b87e7b7a8055bf6c450c2c77ce32a24084', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/cli-parser', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/code-unit' => array( + 'pretty_version' => '2.0.0', + 'version' => '2.0.0.0', + 'reference' => 'a81fee9eef0b7a76af11d121767abc44c104e503', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/code-unit', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/code-unit-reverse-lookup' => array( + 'pretty_version' => '3.0.0', + 'version' => '3.0.0.0', + 'reference' => '5e3a687f7d8ae33fb362c5c0743794bbb2420a1d', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/code-unit-reverse-lookup', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/comparator' => array( + 'pretty_version' => '5.0.3', + 'version' => '5.0.3.0', + 'reference' => 'a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/comparator', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/complexity' => array( + 'pretty_version' => '3.2.0', + 'version' => '3.2.0.0', + 'reference' => '68ff824baeae169ec9f2137158ee529584553799', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/complexity', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/diff' => array( + 'pretty_version' => '5.1.1', + 'version' => '5.1.1.0', + 'reference' => 'c41e007b4b62af48218231d6c2275e4c9b975b2e', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/diff', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/environment' => array( + 'pretty_version' => '6.1.0', + 'version' => '6.1.0.0', + 'reference' => '8074dbcd93529b357029f5cc5058fd3e43666984', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/environment', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/exporter' => array( + 'pretty_version' => '5.1.2', + 'version' => '5.1.2.0', + 'reference' => '955288482d97c19a372d3f31006ab3f37da47adf', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/exporter', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/global-state' => array( + 'pretty_version' => '6.0.2', + 'version' => '6.0.2.0', + 'reference' => '987bafff24ecc4c9ac418cab1145b96dd6e9cbd9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/global-state', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/lines-of-code' => array( + 'pretty_version' => '2.0.2', + 'version' => '2.0.2.0', + 'reference' => '856e7f6a75a84e339195d48c556f23be2ebf75d0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/lines-of-code', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/object-enumerator' => array( + 'pretty_version' => '5.0.0', + 'version' => '5.0.0.0', + 'reference' => '202d0e344a580d7f7d04b3fafce6933e59dae906', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/object-enumerator', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/object-reflector' => array( + 'pretty_version' => '3.0.0', + 'version' => '3.0.0.0', + 'reference' => '24ed13d98130f0e7122df55d06c5c4942a577957', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/object-reflector', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/recursion-context' => array( + 'pretty_version' => '5.0.0', + 'version' => '5.0.0.0', + 'reference' => '05909fb5bc7df4c52992396d0116aed689f93712', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/recursion-context', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/type' => array( + 'pretty_version' => '4.0.0', + 'version' => '4.0.0.0', + 'reference' => '462699a16464c3944eefc02ebdd77882bd3925bf', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/type', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'sebastian/version' => array( + 'pretty_version' => '4.0.1', + 'version' => '4.0.1.0', + 'reference' => 'c51fa83a5d8f43f1402e3f32a005e6262244ef17', + 'type' => 'library', + 'install_path' => __DIR__ . '/../sebastian/version', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'simplesamlphp/assert' => array( - 'pretty_version' => 'v1.4.0', - 'version' => '1.4.0.0', - 'reference' => 'cf9465870eb9fb52103e045217f6dca19aee7c84', + 'pretty_version' => 'v1.5.0', + 'version' => '1.5.0.0', + 'reference' => 'f6872f002d34b8e20c19d0823b107d2c74ddfd9d', 'type' => 'library', 'install_path' => __DIR__ . '/../simplesamlphp/assert', 'aliases' => array(), 'dev_requirement' => false, ), 'simplesamlphp/composer-module-installer' => array( - 'pretty_version' => 'v1.3.4', - 'version' => '1.3.4.0', - 'reference' => '36508ed9580a30c4d5ab0bb3c25c00d0b5d42946', + 'pretty_version' => 'v1.3.5', + 'version' => '1.3.5.0', + 'reference' => '7bf413c2d28e48dff6755d74a7e45087cf144604', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../simplesamlphp/composer-module-installer', 'aliases' => array(), @@ -167,17 +464,26 @@ 'dev_requirement' => false, ), 'simplesamlphp/saml2' => array( - 'pretty_version' => 'v4.6.12', - 'version' => '4.6.12.0', - 'reference' => '9545abd0d9d48388f2fa00469c5c1e0294f0303e', + 'pretty_version' => 'v4.16.14', + 'version' => '4.16.14.0', + 'reference' => 'fe6c7bdda5e166e326d19d78f230d959ab51d01d', 'type' => 'library', 'install_path' => __DIR__ . '/../simplesamlphp/saml2', 'aliases' => array(), 'dev_requirement' => false, ), + 'simplesamlphp/saml2-legacy' => array( + 'pretty_version' => 'v4.16.14', + 'version' => '4.16.14.0', + 'reference' => 'a9ee3a0510780d157ee8e78e7d429e47d736a208', + 'type' => 'library', + 'install_path' => __DIR__ . '/../simplesamlphp/saml2-legacy', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'simplesamlphp/simplesamlphp' => array( - 'pretty_version' => 'v2.3.3', - 'version' => '2.3.3.0', + 'pretty_version' => 'v2.3.5', + 'version' => '2.3.5.0', 'reference' => null, 'type' => 'project', 'install_path' => __DIR__ . '/../../', @@ -185,45 +491,81 @@ 'dev_requirement' => false, ), 'simplesamlphp/simplesamlphp-assets-base' => array( - 'pretty_version' => 'v2.3.1', - 'version' => '2.3.1.0', - 'reference' => 'b21b0a05cdedce3eb242b06d9bea30186bfea8e1', + 'pretty_version' => 'v2.3.2', + 'version' => '2.3.2.0', + 'reference' => '3f83d1afb16a2a807ac26f6a6a8e2f03bad75abe', 'type' => 'simplesamlphp-module', 'install_path' => __DIR__ . '/../../public/assets/base', 'aliases' => array(), 'dev_requirement' => false, ), + 'simplesamlphp/simplesamlphp-module-adfs' => array( + 'pretty_version' => 'v2.1.7', + 'version' => '2.1.7.0', + 'reference' => '3aef826c02a2934b06668730260df0b0138824f7', + 'type' => 'simplesamlphp-module', + 'install_path' => __DIR__ . '/../../modules/adfs', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'simplesamlphp/simplesamlphp-test-framework' => array( + 'pretty_version' => 'v1.7.10', + 'version' => '1.7.10.0', + 'reference' => '157dbad53f1fc10610b23e9457eec20d0e4ad5aa', + 'type' => 'project', + 'install_path' => __DIR__ . '/../simplesamlphp/simplesamlphp-test-framework', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'simplesamlphp/xml-common' => array( - 'pretty_version' => 'v1.18.5', - 'version' => '1.18.5.0', - 'reference' => 'daed5738bc22067c9b0abec2d2b877dc8a1d7647', + 'pretty_version' => 'v1.20.0', + 'version' => '1.20.0.0', + 'reference' => '9cf986ee7d97c02feb992c78f51024f45b068c19', 'type' => 'simplesamlphp-xmlprovider', 'install_path' => __DIR__ . '/../simplesamlphp/xml-common', 'aliases' => array(), 'dev_requirement' => false, ), 'simplesamlphp/xml-security' => array( - 'pretty_version' => 'v1.9.5', - 'version' => '1.9.5.0', - 'reference' => '91e31f5930305e84ad92d573faf817abc8ad09c9', + 'pretty_version' => 'v1.10.0', + 'version' => '1.10.0.0', + 'reference' => '2f478b2308b06c10542488ce9690a98baaf2fdfa', 'type' => 'simplesamlphp-xmlprovider', 'install_path' => __DIR__ . '/../simplesamlphp/xml-security', 'aliases' => array(), 'dev_requirement' => false, ), + 'slevomat/coding-standard' => array( + 'pretty_version' => '8.15.0', + 'version' => '8.15.0.0', + 'reference' => '7d1d957421618a3803b593ec31ace470177d7817', + 'type' => 'phpcodesniffer-standard', + 'install_path' => __DIR__ . '/../slevomat/coding-standard', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'squizlabs/php_codesniffer' => array( + 'pretty_version' => '3.11.1', + 'version' => '3.11.1.0', + 'reference' => '19473c30efe4f7b3cd42522d0b2e6e7f243c6f87', + 'type' => 'library', + 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'symfony/cache' => array( - 'pretty_version' => 'v6.4.14', - 'version' => '6.4.14.0', - 'reference' => '36fb8aa88833708e9f29014b6f15fac051a8b613', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '70d60e9a3603108563010f8592dff15a6f15dfae', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/cache-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => 'df6a1a44c890faded49a5fca33c2d5c5fd3c2197', + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => '15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache-contracts', 'aliases' => array(), @@ -254,18 +596,18 @@ 'dev_requirement' => false, ), 'symfony/dependency-injection' => array( - 'pretty_version' => 'v6.4.15', - 'version' => '6.4.15.0', - 'reference' => '70ab1f65a4516ef741e519ea938e6aa465e6aa36', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '7a379d8871f6a36f01559c14e11141cc02eb8dc8', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => '0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1', + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => '74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), @@ -290,9 +632,9 @@ 'dev_requirement' => false, ), 'symfony/event-dispatcher-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => '8f93aec25d41b72493c6ddff14e916177c9efc50', + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => '7642f5e970b672283b7823222ae8ef8bbc160b9f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', 'aliases' => array(), @@ -332,18 +674,18 @@ 'dev_requirement' => false, ), 'symfony/http-foundation' => array( - 'pretty_version' => 'v6.4.15', - 'version' => '6.4.15.0', - 'reference' => '9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '431771b7a6f662f1575b3cfc8fd7617aa9864d57', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-kernel' => array( - 'pretty_version' => 'v6.4.15', - 'version' => '6.4.15.0', - 'reference' => 'b002a5b3947653c5aee3adac2a024ea615fd3ff5', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '8838b5b21d807923b893ccbfc2cbeda0f1bc00f0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), @@ -367,6 +709,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/phpunit-bridge' => array( + 'pretty_version' => 'v7.2.0', + 'version' => '7.2.0.0', + 'reference' => '2bbde92ab25a0e2c88160857af7be9db5da0d145', + 'type' => 'symfony-bridge', + 'install_path' => __DIR__ . '/../symfony/phpunit-bridge', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'symfony/polyfill-ctype' => array( 'pretty_version' => 'v1.31.0', 'version' => '1.31.0.0', @@ -431,18 +782,18 @@ 'dev_requirement' => false, ), 'symfony/routing' => array( - 'pretty_version' => 'v6.4.13', - 'version' => '6.4.13.0', - 'reference' => '640a74250d13f9c30d5ca045b6aaaabcc8215278', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '91e02e606b4b705c2f4fb42f7e7708b7923a3220', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/routing', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/service-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => 'bd1d9e59a81d8fa4acdcea3f617c581f7475a80f', + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => 'e53260aabf78fb3d63f8d79d69ece59f80d5eda0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), @@ -463,19 +814,34 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/translation' => array( + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => 'bee9bfabfa8b4045a66bf82520e492cddbaffa66', + 'type' => 'library', + 'install_path' => __DIR__ . '/../symfony/translation', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'symfony/translation-contracts' => array( - 'pretty_version' => 'v3.5.0', - 'version' => '3.5.0.0', - 'reference' => 'b9d2189887bb6b2e0367a9fc7136c5239ab9b05a', + 'pretty_version' => 'v3.5.1', + 'version' => '3.5.1.0', + 'reference' => '4667ff3bd513750603a09c8dedbea942487fb07c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/translation-implementation' => array( + 'dev_requirement' => true, + 'provided' => array( + 0 => '2.3|3.0', + ), + ), 'symfony/twig-bridge' => array( - 'pretty_version' => 'v6.4.13', - 'version' => '6.4.13.0', - 'reference' => 'ec3511eef0576f378b2758da9e1c157086babd59', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '32ec012ed4f6426441a66014471bdb26674744be', 'type' => 'symfony-bridge', 'install_path' => __DIR__ . '/../symfony/twig-bridge', 'aliases' => array(), @@ -508,19 +874,28 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'theseer/tokenizer' => array( + 'pretty_version' => '1.2.3', + 'version' => '1.2.3.0', + 'reference' => '737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2', + 'type' => 'library', + 'install_path' => __DIR__ . '/../theseer/tokenizer', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'twig/intl-extra' => array( - 'pretty_version' => 'v3.13.0', - 'version' => '3.13.0.0', - 'reference' => '1b8d78c5db08bdc61015fd55009d2e84b3aa7e38', + 'pretty_version' => 'v3.16.0', + 'version' => '3.16.0.0', + 'reference' => '4eeab2a3f8d04d1838be7251ab2d183f817aea7b', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/intl-extra', 'aliases' => array(), 'dev_requirement' => false, ), 'twig/twig' => array( - 'pretty_version' => 'v3.14.2', - 'version' => '3.14.2.0', - 'reference' => '0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a', + 'pretty_version' => 'v3.16.0', + 'version' => '3.16.0.0', + 'reference' => '475ad2dc97d65d8631393e721e7e44fb544f0561', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/twig', 'aliases' => array(), diff --git a/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md new file mode 100644 index 000000000..9bc88065e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/LICENSE.md @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2016-2022 Dealerdirect B.V. and contributors +Copyright (c) 2022 PHPCSStandards and contributors + +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/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/README.md b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/README.md new file mode 100644 index 000000000..e8c263abc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/README.md @@ -0,0 +1,285 @@ +# PHP_CodeSniffer Standards Composer Installer Plugin + +![Project Stage][project-stage-shield] +![Last Commit][last-updated-shield] +![Awesome][awesome-shield] +[![License][license-shield]](LICENSE.md) + +[![Tests][ghactionstest-shield]][ghactions] +[![Latest Version on Packagist][packagist-version-shield]][packagist-version] +[![Packagist][packagist-shield]][packagist] + +[![Contributor Covenant][code-of-conduct-shield]][code-of-conduct] + +This composer installer plugin allows for easy installation of [PHP_CodeSniffer][codesniffer] coding standards (rulesets). + +No more symbolic linking of directories, checking out repositories on specific locations or changing +the `phpcs` configuration. + +## Usage + +Installation can be done with [Composer][composer], by requiring this package as a development dependency: + +```bash +composer require --dev dealerdirect/phpcodesniffer-composer-installer +``` + +When using Composer 2.2 or higher, Composer will [ask for your permission](https://blog.packagist.com/composer-2-2/#more-secure-plugin-execution) to allow this plugin to execute code. For this plugin to be functional, permission needs to be granted. + +When permission has been granted, the following snippet will automatically be added to your `composer.json` file by Composer: +```json +{ + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} +``` + +When using Composer < 2.2, you can add the permission flag ahead of the upgrade to Composer 2.2, by running: +```bash +composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true +``` + +That's it. + +### Compatibility + +This plugin is compatible with: + +- PHP **5.4+**, **7.x**, and **8.x** (Support for PHP v8 is available since [`v0.7.0`][v0.7]) +- [Composer][composer] **1.x** and **2.x** (Support for Composer v2 is available since [`v0.7.0`][v0.7]) +- [PHP_CodeSniffer][codesniffer] **2.x** and **3.x** (Support for PHP_CodeSniffer v3 is available since [`v0.4.0`][v0.4]) + + +> **â„¹ï¸ Please Note:** [Composer treats _minor_ releases below 1.0.0 as _major_ releases][composer-manual-caret]. So version `0.7.x` (or higher) of this plugin must be _explicitly_ set as version constraint when using Composer 2.x or PHP 8.0. In other words: using `^0.6` will **not** work with Composer 2.x or PHP 8.0. + +### How it works + +Basically, this plugin executes the following steps: + +- This plugin searches for [`phpcodesniffer-standard` packages][] in all of your currently installed Composer packages. +- Matching packages and the project itself are scanned for PHP_CodeSniffer rulesets. +- The plugin will call PHP_CodeSniffer and configure the `installed_paths` option. + +### Example project + +The following is an example Composer project and has included +multiple `phpcodesniffer-standard` packages. + +```json +{ + "name": "example/project", + "description": "Just an example project", + "type": "project", + "require": {}, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "*", + "object-calisthenics/phpcs-calisthenics-rules": "*", + "phpcompatibility/php-compatibility": "*", + "wp-coding-standards/wpcs": "*" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} +``` + +After running `composer install` PHP_CodeSniffer just works: + +```bash +$ ./vendor/bin/phpcs -i +The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, ObjectCalisthenics, +PHPCompatibility, WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra +``` + +### Calling the plugin directly + +In some circumstances, it is desirable to call this plugin's functionality +directly. For instance, during development or in [CI][definition-ci] environments. + +As the plugin requires Composer to work, direct calls need to be wired through a +project's `composer.json`. + +This is done by adding a call to the `Plugin::run` function in the `script` +section of the `composer.json`: + +```json +{ + "scripts": { + "install-codestandards": [ + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ] + } +} +``` + +The command can then be called using `composer run-script install-codestandards` or +referenced from other script configurations, as follows: + +```json +{ + "scripts": { + "install-codestandards": [ + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ], + "post-install-cmd": [ + "@install-codestandards" + ] + } +} +``` + +For more details about Composer scripts, please refer to [the section on scripts +in the Composer manual][composer-manual-scripts]. + +### Changing the Coding Standards search depth + +By default, this plugin searches up for Coding Standards up to three directories +deep. In most cases, this should be sufficient. However, this plugin allows +you to customize the search depth setting if needed. + +```json +{ + "extra": { + "phpcodesniffer-search-depth": 5 + } +} +``` + +### Caveats + +When this plugin is installed globally, composer will load the _global_ plugin rather +than the one from the local repository. Despite [this behavior being documented +in the composer manual][using-composer-plugins], it could potentially confuse +as another version of the plugin could be run and not the one specified by the project. + +## Developing Coding Standards + +Coding standard can be developed normally, as documented by [PHP_CodeSniffer][codesniffer], in the [Coding Standard Tutorial][tutorial]. + +Create a composer package of your coding standard by adding a `composer.json` file. + +```json +{ + "name" : "acme/phpcodesniffer-our-standards", + "description" : "Package contains all coding standards of the Acme company", + "require" : { + "php" : ">=5.4.0", + "squizlabs/php_codesniffer" : "^3.6" + }, + "type" : "phpcodesniffer-standard" +} +``` + +Requirements: +* The repository may contain one or more standards. +* Each standard can have a separate directory no deeper than 3 levels from the repository root. +* The package `type` must be `phpcodesniffer-standard`. Without this, the plugin will not trigger. + +### Requiring the plugin from within your coding standard + +If your coding standard itself depends on additional external PHPCS standards, this plugin can +make life easier on your end-users by taking care of the installation of all standards - yours +and your dependencies - for them. + +This can help reduce the number of support questions about setting the `installed_paths`, as well +as simplify your standard's installation instructions. + +For this to work, make sure your external standard adds this plugin to the `composer.json` config +via `require`, **not** `require-dev`. + +> :warning: Your end-user may already `require-dev` this plugin and/or other external standards used +> by your end-users may require this plugin as well. +> +> To prevent your end-users getting into "_dependency hell_", make sure to make the version requirement +> for this plugin flexible. +> +> As, for now, this plugin is still regarded as "unstable" (version < 1.0), remember that Composer +> treats unstable minors as majors and will not be able to resolve one config requiring this plugin +> at version `^0.5`, while another requires it at version `^0.6`. +> Either allow multiple minors or use `*` as the version requirement. +> +> Some examples of flexible requirements which can be used: +> ```bash +> composer require dealerdirect/phpcodesniffer-composer-installer:"*" +> composer require dealerdirect/phpcodesniffer-composer-installer:"0.*" +> composer require dealerdirect/phpcodesniffer-composer-installer:"^0.4.1 || ^0.5 || ^0.6 || ^0.7" +> ``` + +## Changelog + +This repository does not contain a `CHANGELOG.md` file, however, we do publish a changelog on each release +using the [GitHub releases][changelog] functionality. + +## Contributing + +This is an active open-source project. We are always open to people who want to +use the code or contribute to it. + +We've set up a separate document for our [contribution guidelines][contributing-guidelines]. + +Thank you for being involved! :heart_eyes: + +## Authors & contributors + +The original idea and setup of this repository is by [Franck Nijhof][frenck], employee @ Dealerdirect. + +For a full list of all author and/or contributors, check [the contributors page][contributors]. + +## License + +The MIT License (MIT) + +Copyright (c) 2016-2022 Dealerdirect B.V. and contributors +Copyright (c) 2022 PHPCSStandards and contributors + +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. + +[awesome-shield]: https://img.shields.io/badge/awesome%3F-yes-brightgreen.svg +[changelog]: https://github.com/PHPCSStandards/composer-installer/releases +[code-of-conduct-shield]: https://img.shields.io/badge/Contributor%20Covenant-v2.0-ff69b4.svg +[code-of-conduct]: CODE_OF_CONDUCT.md +[codesniffer]: https://github.com/squizlabs/PHP_CodeSniffer +[composer-manual-scripts]: https://getcomposer.org/doc/articles/scripts.md +[composer-manual-caret]: https://getcomposer.org/doc/articles/versions.md#caret-version-range- +[composer]: https://getcomposer.org/ +[contributing-guidelines]: CONTRIBUTING.md +[contributors]: https://github.com/PHPCSStandards/composer-installer/graphs/contributors +[definition-ci]: https://en.wikipedia.org/wiki/Continuous_integration +[frenck]: https://github.com/frenck +[last-updated-shield]: https://img.shields.io/github/last-commit/PHPCSStandards/composer-installer.svg +[license-shield]: https://img.shields.io/github/license/PHPCSStandards/composer-installer.svg +[packagist-shield]: https://img.shields.io/packagist/dt/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-version-shield]: https://img.shields.io/packagist/v/dealerdirect/phpcodesniffer-composer-installer.svg +[packagist-version]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer +[packagist]: https://packagist.org/packages/dealerdirect/phpcodesniffer-composer-installer +[`phpcodesniffer-standard` packages]: https://packagist.org/explore/?type=phpcodesniffer-standard +[project-stage-shield]: https://img.shields.io/badge/Project%20Stage-Development-yellowgreen.svg +[scrutinizer-shield]: https://img.shields.io/scrutinizer/g/dealerdirect/phpcodesniffer-composer-installer.svg +[scrutinizer]: https://scrutinizer-ci.com/g/dealerdirect/phpcodesniffer-composer-installer/ +[ghactionstest-shield]: https://github.com/PHPCSStandards/composer-installer/actions/workflows/integrationtest.yml/badge.svg +[ghactions]: https://github.com/PHPCSStandards/composer-installer/actions/workflows/integrationtest.yml +[tutorial]: https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial +[using-composer-plugins]: https://getcomposer.org/doc/articles/plugins.md#using-plugins +[v0.4]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v0.4.0 +[v0.7]: https://github.com/PHPCSStandards/composer-installer/releases/tag/v0.7.0 diff --git a/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json new file mode 100644 index 000000000..bf3355ac4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/composer.json @@ -0,0 +1,71 @@ +{ + "name": "dealerdirect/phpcodesniffer-composer-installer", + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "type": "composer-plugin", + "keywords": [ + "composer", "installer", "plugin", + "phpcs", "phpcbf", "codesniffer", "phpcodesniffer", "php_codesniffer", + "standard", "standards", "style guide", "stylecheck", + "qa", "quality", "code quality", "tests" + ], + "homepage": "http://www.dealerdirect.com", + "license": "MIT", + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name" : "Contributors", + "homepage" : "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "require": { + "php": ">=5.4", + "composer-plugin-api": "^1.0 || ^2.0", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "ext-json": "*", + "ext-zip": "*", + "composer/composer": "*", + "phpcompatibility/php-compatibility": "^9.0", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "yoast/phpunit-polyfills": "^1.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Tests\\": "tests/" + } + }, + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "scripts": { + "install-codestandards": [ + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run" + ], + "lint": [ + "@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php --exclude vendor --exclude .git" + ], + "test": [ + "@php ./vendor/phpunit/phpunit/phpunit --no-coverage" + ], + "coverage": [ + "@php ./vendor/phpunit/phpunit/phpunit" + ] + } +} diff --git a/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php new file mode 100644 index 000000000..a2863d6c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/dealerdirect/phpcodesniffer-composer-installer/src/Plugin.php @@ -0,0 +1,637 @@ + + */ +class Plugin implements PluginInterface, EventSubscriberInterface +{ + const KEY_MAX_DEPTH = 'phpcodesniffer-search-depth'; + + const MESSAGE_ERROR_WRONG_MAX_DEPTH = + 'The value of "%s" (in the composer.json "extra".section) must be an integer larger than %d, %s given.'; + + const MESSAGE_NOT_INSTALLED = 'PHPCodeSniffer is not installed'; + const MESSAGE_NOTHING_TO_INSTALL = 'No PHPCS standards to install or update'; + const MESSAGE_PLUGIN_UNINSTALLED = 'PHPCodeSniffer Composer Installer is uninstalled'; + const MESSAGE_RUNNING_INSTALLER = 'Running PHPCodeSniffer Composer Installer'; + + const PACKAGE_NAME = 'squizlabs/php_codesniffer'; + const PACKAGE_TYPE = 'phpcodesniffer-standard'; + + const PHPCS_CONFIG_REGEX = '`%s:[^\r\n]+`'; + const PHPCS_CONFIG_KEY = 'installed_paths'; + + const PLUGIN_NAME = 'dealerdirect/phpcodesniffer-composer-installer'; + + /** + * @var Composer + */ + private $composer; + + /** + * @var string + */ + private $cwd; + + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var array + */ + private $installedPaths; + + /** + * @var IOInterface + */ + private $io; + + /** + * @var ProcessExecutor + */ + private $processExecutor; + + /** + * Triggers the plugin's main functionality. + * + * Makes it possible to run the plugin as a custom command. + * + * @param Event $event + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public static function run(Event $event) + { + $io = $event->getIO(); + $composer = $event->getComposer(); + + $instance = new static(); + + $instance->io = $io; + $instance->composer = $composer; + $instance->init(); + $instance->onDependenciesChangedEvent(); + } + + /** + * {@inheritDoc} + * + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public function activate(Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->io = $io; + + $this->init(); + } + + /** + * {@inheritDoc} + */ + public function deactivate(Composer $composer, IOInterface $io) + { + } + + /** + * {@inheritDoc} + */ + public function uninstall(Composer $composer, IOInterface $io) + { + } + + /** + * Prepares the plugin so it's main functionality can be run. + * + * @throws \RuntimeException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + private function init() + { + $this->cwd = getcwd(); + $this->installedPaths = array(); + + $this->processExecutor = new ProcessExecutor($this->io); + $this->filesystem = new Filesystem($this->processExecutor); + } + + /** + * {@inheritDoc} + */ + public static function getSubscribedEvents() + { + return array( + ScriptEvents::POST_INSTALL_CMD => array( + array('onDependenciesChangedEvent', 0), + ), + ScriptEvents::POST_UPDATE_CMD => array( + array('onDependenciesChangedEvent', 0), + ), + ); + } + + /** + * Entry point for post install and post update events. + * + * @throws \InvalidArgumentException + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + public function onDependenciesChangedEvent() + { + $io = $this->io; + $isVerbose = $io->isVerbose(); + $exitCode = 0; + + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_RUNNING_INSTALLER)); + } + + if ($this->isPHPCodeSnifferInstalled() === true) { + $this->loadInstalledPaths(); + $installPathCleaned = $this->cleanInstalledPaths(); + $installPathUpdated = $this->updateInstalledPaths(); + + if ($installPathCleaned === true || $installPathUpdated === true) { + $exitCode = $this->saveInstalledPaths(); + } elseif ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_NOTHING_TO_INSTALL)); + } + } else { + $pluginPackage = $this + ->composer + ->getRepositoryManager() + ->getLocalRepository() + ->findPackages(self::PLUGIN_NAME) + ; + + $isPluginUninstalled = count($pluginPackage) === 0; + + if ($isPluginUninstalled) { + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_PLUGIN_UNINSTALLED)); + } + } else { + $exitCode = 1; + if ($isVerbose) { + $io->write(sprintf('%s', self::MESSAGE_NOT_INSTALLED)); + } + } + } + + return $exitCode; + } + + /** + * Load all paths from PHP_CodeSniffer into an array. + * + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + */ + private function loadInstalledPaths() + { + if ($this->isPHPCodeSnifferInstalled() === true) { + $this->processExecutor->execute( + $this->getPhpcsCommand() . ' --config-show', + $output, + $this->getPHPCodeSnifferInstallPath() + ); + + $regex = sprintf(self::PHPCS_CONFIG_REGEX, self::PHPCS_CONFIG_KEY); + if (preg_match($regex, $output, $match) === 1) { + $phpcsInstalledPaths = str_replace(self::PHPCS_CONFIG_KEY . ': ', '', $match[0]); + $phpcsInstalledPaths = trim($phpcsInstalledPaths); + + if ($phpcsInstalledPaths !== '') { + $this->installedPaths = explode(',', $phpcsInstalledPaths); + } + } + } + } + + /** + * Save all coding standard paths back into PHP_CodeSniffer + * + * @throws LogicException + * @throws ProcessFailedException + * @throws RuntimeException + * + * @return int Exit code. 0 for success, 1 or higher for failure. + */ + private function saveInstalledPaths() + { + // Check if we found installed paths to set. + if (count($this->installedPaths) !== 0) { + sort($this->installedPaths); + $paths = implode(',', $this->installedPaths); + $arguments = array('--config-set', self::PHPCS_CONFIG_KEY, $paths); + $configMessage = sprintf( + 'PHP CodeSniffer Config %s set to %s', + self::PHPCS_CONFIG_KEY, + $paths + ); + } else { + // Delete the installed paths if none were found. + $arguments = array('--config-delete', self::PHPCS_CONFIG_KEY); + $configMessage = sprintf( + 'PHP CodeSniffer Config %s delete', + self::PHPCS_CONFIG_KEY + ); + } + + // Prepare message in case of failure + $failMessage = sprintf( + 'Failed to set PHP CodeSniffer %s Config', + self::PHPCS_CONFIG_KEY + ); + + // Okay, lets rock! + $command = vsprintf( + '%s %s', + array( + 'phpcs command' => $this->getPhpcsCommand(), + 'arguments' => implode(' ', $arguments), + ) + ); + + $exitCode = $this->processExecutor->execute($command, $configResult, $this->getPHPCodeSnifferInstallPath()); + if ($exitCode === 0) { + $exitCode = $this->verifySaveSuccess(); + } + + if ($exitCode === 0) { + $this->io->write($configMessage); + } else { + $this->io->write($failMessage); + } + + if ($this->io->isVerbose() && !empty($configResult)) { + $this->io->write(sprintf('%s', $configResult)); + } + + return $exitCode; + } + + /** + * Verify that the paths which were expected to be saved, have been. + * + * @return int Exit code. 0 for success, 1 for failure. + */ + private function verifySaveSuccess() + { + $exitCode = 1; + $expectedPaths = $this->installedPaths; + + // Request the currently set installed paths after the save. + $this->loadInstalledPaths(); + + $registeredPaths = array_intersect($this->installedPaths, $expectedPaths); + $registeredCount = count($registeredPaths); + $expectedCount = count($expectedPaths); + + if ($expectedCount === $registeredCount) { + $exitCode = 0; + } + + if ($exitCode === 1 && $this->io->isVerbose()) { + $verificationMessage = sprintf( + "Paths to external standards found by the plugin: %s\n" + . 'Actual paths registered with PHPCS: %s', + implode(', ', $expectedPaths), + implode(', ', $this->installedPaths) + ); + $this->io->write($verificationMessage); + } + + return $exitCode; + } + + /** + * Get the command to call PHPCS. + */ + protected function getPhpcsCommand() + { + // Determine the path to the main PHPCS file. + $phpcsPath = $this->getPHPCodeSnifferInstallPath(); + if (file_exists($phpcsPath . '/bin/phpcs') === true) { + // PHPCS 3.x. + $phpcsExecutable = './bin/phpcs'; + } else { + // PHPCS 2.x. + $phpcsExecutable = './scripts/phpcs'; + } + + return vsprintf( + '%s %s', + array( + 'php executable' => $this->getPhpExecCommand(), + 'phpcs executable' => $phpcsExecutable, + ) + ); + } + + /** + * Get the path to the current PHP version being used. + * + * Duplicate of the same in the EventDispatcher class in Composer itself. + */ + protected function getPhpExecCommand() + { + $finder = new PhpExecutableFinder(); + + $phpPath = $finder->find(false); + + if ($phpPath === false) { + throw new \RuntimeException('Failed to locate PHP binary to execute ' . $phpPath); + } + + $phpArgs = $finder->findArguments(); + $phpArgs = $phpArgs + ? ' ' . implode(' ', $phpArgs) + : '' + ; + + $command = ProcessExecutor::escape($phpPath) . + $phpArgs . + ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen')) . + ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions')) . + ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit')) + ; + + return $command; + } + + /** + * Iterate trough all known paths and check if they are still valid. + * + * If path does not exists, is not an directory or isn't readable, the path + * is removed from the list. + * + * @return bool True if changes where made, false otherwise + */ + private function cleanInstalledPaths() + { + $changes = false; + foreach ($this->installedPaths as $key => $path) { + // This might be a relative path as well + $alternativePath = realpath($this->getPHPCodeSnifferInstallPath() . \DIRECTORY_SEPARATOR . $path); + + if ( + (is_dir($path) === false || is_readable($path) === false) && + ( + $alternativePath === false || + is_dir($alternativePath) === false || + is_readable($alternativePath) === false + ) + ) { + unset($this->installedPaths[$key]); + $changes = true; + } + } + return $changes; + } + + /** + * Check all installed packages (including the root package) against + * the installed paths from PHP_CodeSniffer and add the missing ones. + * + * @return bool True if changes where made, false otherwise + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + private function updateInstalledPaths() + { + $changes = false; + $searchPaths = array(); + + // Add root package only if it has the expected package type. + if ( + $this->composer->getPackage() instanceof RootPackageInterface + && $this->composer->getPackage()->getType() === self::PACKAGE_TYPE + ) { + $searchPaths[] = $this->cwd; + } + + $codingStandardPackages = $this->getPHPCodingStandardPackages(); + foreach ($codingStandardPackages as $package) { + $installPath = $this->composer->getInstallationManager()->getInstallPath($package); + if ($this->filesystem->isAbsolutePath($installPath) === false) { + $installPath = $this->filesystem->normalizePath( + $this->cwd . \DIRECTORY_SEPARATOR . $installPath + ); + } + $searchPaths[] = $installPath; + } + + // Nothing to do. + if ($searchPaths === array()) { + return false; + } + + $finder = new Finder(); + $finder->files() + ->depth('<= ' . $this->getMaxDepth()) + ->depth('>= ' . $this->getMinDepth()) + ->ignoreUnreadableDirs() + ->ignoreVCS(true) + ->in($searchPaths) + ->name('ruleset.xml'); + + // Process each found possible ruleset. + foreach ($finder as $ruleset) { + $standardsPath = $ruleset->getPath(); + + // Pick the directory above the directory containing the standard, unless this is the project root. + if ($standardsPath !== $this->cwd) { + $standardsPath = dirname($standardsPath); + } + + // Use relative paths for local project repositories. + if ($this->isRunningGlobally() === false) { + $standardsPath = $this->filesystem->findShortestPath( + $this->getPHPCodeSnifferInstallPath(), + $standardsPath, + true + ); + } + + // De-duplicate and add when directory is not configured. + if (in_array($standardsPath, $this->installedPaths, true) === false) { + $this->installedPaths[] = $standardsPath; + $changes = true; + } + } + + return $changes; + } + + /** + * Iterates through Composers' local repository looking for valid Coding + * Standard packages. + * + * @return array Composer packages containing coding standard(s) + */ + private function getPHPCodingStandardPackages() + { + $codingStandardPackages = array_filter( + $this->composer->getRepositoryManager()->getLocalRepository()->getPackages(), + function (PackageInterface $package) { + if ($package instanceof AliasPackage) { + return false; + } + return $package->getType() === Plugin::PACKAGE_TYPE; + } + ); + + return $codingStandardPackages; + } + + /** + * Searches for the installed PHP_CodeSniffer Composer package + * + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against + * + * @return PackageInterface|null + */ + private function getPHPCodeSnifferPackage($versionConstraint = null) + { + $packages = $this + ->composer + ->getRepositoryManager() + ->getLocalRepository() + ->findPackages(self::PACKAGE_NAME, $versionConstraint); + + return array_shift($packages); + } + + /** + * Returns the path to the PHP_CodeSniffer package installation location + * + * @return string + */ + private function getPHPCodeSnifferInstallPath() + { + return $this->composer->getInstallationManager()->getInstallPath($this->getPHPCodeSnifferPackage()); + } + + /** + * Simple check if PHP_CodeSniffer is installed. + * + * @param null|string|\Composer\Semver\Constraint\ConstraintInterface $versionConstraint to match against + * + * @return bool Whether PHP_CodeSniffer is installed + */ + private function isPHPCodeSnifferInstalled($versionConstraint = null) + { + return ($this->getPHPCodeSnifferPackage($versionConstraint) !== null); + } + + /** + * Test if composer is running "global" + * This check kinda dirty, but it is the "Composer Way" + * + * @return bool Whether Composer is running "globally" + * + * @throws \RuntimeException + */ + private function isRunningGlobally() + { + return ($this->composer->getConfig()->get('home') === $this->cwd); + } + + /** + * Determines the maximum search depth when searching for Coding Standards. + * + * @return int + * + * @throws \InvalidArgumentException + */ + private function getMaxDepth() + { + $maxDepth = 3; + + $extra = $this->composer->getPackage()->getExtra(); + + if (array_key_exists(self::KEY_MAX_DEPTH, $extra)) { + $maxDepth = $extra[self::KEY_MAX_DEPTH]; + $minDepth = $this->getMinDepth(); + + if ( + (string) (int) $maxDepth !== (string) $maxDepth /* Must be an integer or cleanly castable to one */ + || $maxDepth <= $minDepth /* Larger than the minimum */ + || is_float($maxDepth) === true /* Within the boundaries of integer */ + ) { + $message = vsprintf( + self::MESSAGE_ERROR_WRONG_MAX_DEPTH, + array( + 'key' => self::KEY_MAX_DEPTH, + 'min' => $minDepth, + 'given' => var_export($maxDepth, true), + ) + ); + + throw new \InvalidArgumentException($message); + } + } + + return (int) $maxDepth; + } + + /** + * Returns the minimal search depth for Coding Standard packages. + * + * Usually this is 0, unless PHP_CodeSniffer >= 3 is used. + * + * @return int + */ + private function getMinDepth() + { + if ($this->isPHPCodeSnifferInstalled('>= 3.0.0') !== true) { + return 1; + } + return 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/CHANGELOG.md b/.extlib/simplesamlphp/vendor/gettext/gettext/CHANGELOG.md index 662cb5206..101f27a7c 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/CHANGELOG.md +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/CHANGELOG.md @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Previous releases are documented in [github releases](https://github.com/oscarotero/Gettext/releases) +## [5.7.3] - 2024-12-01 +### Fixed +- Php 8.4 support [#302]. + +## [5.7.2] - 2024-11-24 +### Fixed +- Php 8.4 support [#300]. + ## [5.7.1] - 2024-07-24 ### Fixed - Parsing of PO files with empty comments instead of empty lines [#296] @@ -127,7 +135,11 @@ Previous releases are documented in [github releases](https://github.com/oscarot [#282]: https://github.com/php-gettext/Gettext/issues/282 [#296]: https://github.com/php-gettext/Gettext/issues/296 [#299]: https://github.com/php-gettext/Gettext/issues/299 +[#300]: https://github.com/php-gettext/Gettext/issues/300 +[#302]: https://github.com/php-gettext/Gettext/issues/302 +[5.7.3]: https://github.com/php-gettext/Gettext/compare/v5.7.2...v5.7.3 +[5.7.2]: https://github.com/php-gettext/Gettext/compare/v5.7.1...v5.7.2 [5.7.1]: https://github.com/php-gettext/Gettext/compare/v5.7.0...v5.7.1 [5.7.0]: https://github.com/php-gettext/Gettext/compare/v5.6.1...v5.7.0 [5.6.1]: https://github.com/php-gettext/Gettext/compare/v5.6.0...v5.6.1 diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/Loader.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/Loader.php index 684f7cab2..3ad072da6 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/Loader.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/Loader.php @@ -12,14 +12,14 @@ */ abstract class Loader implements LoaderInterface { - public function loadFile(string $filename, Translations $translations = null): Translations + public function loadFile(string $filename, ?Translations $translations = null): Translations { $string = static::readFile($filename); return $this->loadString($string, $translations); } - public function loadString(string $string, Translations $translations = null): Translations + public function loadString(string $string, ?Translations $translations = null): Translations { return $translations ?: $this->createTranslations(); } @@ -29,7 +29,7 @@ protected function createTranslations(): Translations return Translations::create(); } - protected function createTranslation(?string $context, string $original, string $plural = null): ?Translation + protected function createTranslation(?string $context, string $original, ?string $plural = null): ?Translation { $translation = Translation::create($context, $original); diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/LoaderInterface.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/LoaderInterface.php index 4f330d3b2..0d884e4be 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/LoaderInterface.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/LoaderInterface.php @@ -7,7 +7,7 @@ interface LoaderInterface { - public function loadFile(string $filename, Translations $translations = null): Translations; + public function loadFile(string $filename, ?Translations $translations = null): Translations; - public function loadString(string $string, Translations $translations = null): Translations; + public function loadString(string $string, ?Translations $translations = null): Translations; } diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/MoLoader.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/MoLoader.php index c50790481..57406813f 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/MoLoader.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/MoLoader.php @@ -19,7 +19,7 @@ final class MoLoader extends Loader private const MAGIC2 = -569244523; private const MAGIC3 = 2500072158; - public function loadString(string $string, Translations $translations = null): Translations + public function loadString(string $string, ?Translations $translations = null): Translations { $translations = parent::loadString($string, $translations); $this->init($string); diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/PoLoader.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/PoLoader.php index d7e4da022..e7e706c7d 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/PoLoader.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/PoLoader.php @@ -11,7 +11,7 @@ */ final class PoLoader extends Loader { - public function loadString(string $string, Translations $translations = null): Translations + public function loadString(string $string, ?Translations $translations = null): Translations { $translations = parent::loadString($string, $translations); diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/StrictPoLoader.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/StrictPoLoader.php index 08233b5f6..5a9c11522 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/StrictPoLoader.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Loader/StrictPoLoader.php @@ -41,7 +41,7 @@ final class StrictPoLoader extends Loader /** * Generates a Translations object from a .po based string */ - public function loadString(string $data, Translations $translations = null): Translations + public function loadString(string $data, ?Translations $translations = null): Translations { $this->data = $data; $this->position = 0; diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/References.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/References.php index 8a0a6351a..b6758b17d 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/References.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/References.php @@ -29,7 +29,7 @@ public function __debugInfo() return $this->toArray(); } - public function add(string $filename, int $line = null): self + public function add(string $filename, ?int $line = null): self { $fileReferences = $this->references[$filename] ?? []; diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/FunctionsHandlersTrait.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/FunctionsHandlersTrait.php index a31da4414..47301427d 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/FunctionsHandlersTrait.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/FunctionsHandlersTrait.php @@ -140,6 +140,6 @@ abstract protected function saveTranslation( ?string $domain, ?string $context, string $original, - string $plural = null + ?string $plural = null ): ?Translation; } diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/ParsedFunction.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/ParsedFunction.php index 5e7aff052..255df4d1a 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/ParsedFunction.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/ParsedFunction.php @@ -16,7 +16,7 @@ final class ParsedFunction private $comments = []; private $flags = []; - public function __construct(string $name, string $filename, int $line, int $lastLine = null) + public function __construct(string $name, string $filename, int $line, ?int $lastLine = null) { $this->name = $name; $this->filename = $filename; diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/Scanner.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/Scanner.php index 62a9f7cf0..f8267b2d1 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/Scanner.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Scanner/Scanner.php @@ -51,7 +51,7 @@ protected function saveTranslation( ?string $domain, ?string $context, string $original, - string $plural = null + ?string $plural = null ): ?Translation { if (is_null($domain)) { $domain = $this->defaultDomain; diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translation.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translation.php index 6f590c42e..f4c86adb6 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translation.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translation.php @@ -194,7 +194,7 @@ public function translatePlural(string ...$translations): self return $this; } - public function getPluralTranslations(int $size = null): array + public function getPluralTranslations(?int $size = null): array { if ($size === null) { return $this->pluralTranslations; diff --git a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translations.php b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translations.php index f0a5964fb..761851b57 100644 --- a/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translations.php +++ b/.extlib/simplesamlphp/vendor/gettext/gettext/src/Translations.php @@ -20,7 +20,7 @@ class Translations implements Countable, IteratorAggregate protected $headers; protected $flags; - public static function create(string $domain = null, string $language = null): Translations + public static function create(?string $domain = null, ?string $language = null): Translations { $translations = new static(); diff --git a/.extlib/simplesamlphp/vendor/gettext/languages/bin/export-plural-rules b/.extlib/simplesamlphp/vendor/gettext/languages/bin/export-plural-rules old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/CHANGELOG.md b/.extlib/simplesamlphp/vendor/gettext/php-scanner/CHANGELOG.md new file mode 100644 index 000000000..6fa3ed72e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/CHANGELOG.md @@ -0,0 +1,65 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [1.3.1] - 2022-03-18 +### Fixed +- Support for concatenated strings [#14]. + +## [1.3.0] - 2021-04-01 +### Added +- The translations with sprintf expressions have the `php-format` flag [#12] + +## [1.2.2] - 2021-01-12 +### Fixed +- Support for PHP 8 [#11] + +## [1.2.1] - 2020-05-28 +### Added +- Support for static calls [#9] + +## [1.2.0] - 2020-05-23 +### Added +- Function scanner extracts not only functions calls but also class methods calls. + +### Fixed +- Support for `gettext/gettext v5.5.0` +- Extract comments prepending variable assignments [#8] + +## [1.1.1] - 2019-11-25 +### Fixed +- Extract comments of functions prepended with echo, print or return [#6] +- Tested extracted comments from code + +## [1.1.0] - 2019-11-19 +### Added +- In v1.0, non-scalar arguments (others than string, int and float) were discarded. Now the arrays are included too [#5] + +## [1.0.1] - 2019-11-11 +### Fixed +- Anonimous function produce fatal errors [#1] + +## [1.0.0] - 2019-11-05 +First version + +[#1]: https://github.com/php-gettext/PHP-Scanner/issues/1 +[#5]: https://github.com/php-gettext/PHP-Scanner/issues/5 +[#6]: https://github.com/php-gettext/PHP-Scanner/issues/6 +[#8]: https://github.com/php-gettext/PHP-Scanner/issues/8 +[#9]: https://github.com/php-gettext/PHP-Scanner/issues/9 +[#11]: https://github.com/php-gettext/PHP-Scanner/issues/11 +[#12]: https://github.com/php-gettext/PHP-Scanner/issues/12 +[#14]: https://github.com/php-gettext/PHP-Scanner/issues/14 + +[1.3.1]: https://github.com/php-gettext/PHP-Scanner/compare/v1.3.0...v1.3.1 +[1.3.0]: https://github.com/php-gettext/PHP-Scanner/compare/v1.2.2...v1.3.0 +[1.2.2]: https://github.com/php-gettext/PHP-Scanner/compare/v1.2.1...v1.2.2 +[1.2.1]: https://github.com/php-gettext/PHP-Scanner/compare/v1.2.0...v1.2.1 +[1.2.0]: https://github.com/php-gettext/PHP-Scanner/compare/v1.1.1...v1.2.0 +[1.1.1]: https://github.com/php-gettext/PHP-Scanner/compare/v1.1.0...v1.1.1 +[1.1.0]: https://github.com/php-gettext/PHP-Scanner/compare/v1.0.1...v1.1.0 +[1.0.1]: https://github.com/php-gettext/PHP-Scanner/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/php-gettext/PHP-Scanner/releases/tag/v1.0.0 diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/CONTRIBUTING.md b/.extlib/simplesamlphp/vendor/gettext/php-scanner/CONTRIBUTING.md new file mode 100644 index 000000000..0c1b54334 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/CONTRIBUTING.md @@ -0,0 +1,17 @@ +Contributing to Gettext +======================= + +Looking to contribute something to this library? Here's how you can help. + +## Bugs + +A bug is a demonstrable problem that is caused by the code in the repository. Good bug reports are extremely helpful – thank you! + +Please try to be as detailed as possible in your report. Include specific information about the environment – version of PHP, version of gettext, etc, and steps required to reproduce the issue. + +## Pull Requests + +Good pull requests – patches, improvements, new features – are a fantastic help. New extractors or generator are welcome. Before create a pull request, please follow these instructions: + +* The code must be PSR-2 compliant +* Write some tests diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/LICENSE b/.extlib/simplesamlphp/vendor/gettext/php-scanner/LICENSE new file mode 100644 index 000000000..106de2aa8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Oscar Otero Marzoa + +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/.extlib/simplesamlphp/vendor/gettext/php-scanner/README.md b/.extlib/simplesamlphp/vendor/gettext/php-scanner/README.md new file mode 100644 index 000000000..b86831135 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/README.md @@ -0,0 +1,64 @@ +# PHP Scanner + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE) +[![Build Status][ico-travis]][link-travis] +[![Total Downloads][ico-downloads]][link-downloads] + +Created by Oscar Otero (MIT License) + +PHP code scanner to use with [gettext/gettext](https://github.com/php-gettext/Gettext) + +## Installation + +``` +composer require gettext/php-scanner +``` + +## Usage example + +```php +use Gettext\Scanner\PhpScanner; +use Gettext\Generator\PoGenerator; +use Gettext\Translations; + +//Create a new scanner, adding a translation for each domain we want to get: +$phpScanner = new PhpScanner( + Translations::create('domain1'), + Translations::create('domain2'), + Translations::create('domain3') +); + +//Set a default domain, so any translations with no domain specified, will be added to that domain +$phpScanner->setDefaultDomain('domain1'); + +//Extract all comments starting with 'i18n:' and 'Translators:' +$phpScanner->extractCommentsStartingWith('i18n:', 'Translators:'); + +//Scan files +foreach (glob('*.php') as $file) { + $phpScanner->scanFile($file); +} + +//Save the translations in .po files +$generator = new PoGenerator(); + +foreach ($phpScanner->getTranslations() as $domain => $translations) { + $generator->generateFile($translations, "locales/{$domain}.po"); +} +``` + +--- + +Please see [CHANGELOG](CHANGELOG.md) for more information about recent changes and [CONTRIBUTING](CONTRIBUTING.md) for contributing details. + +The MIT License (MIT). Please see [LICENSE](LICENSE) for more information. + +[ico-version]: https://img.shields.io/packagist/v/gettext/php-scanner.svg?style=flat-square +[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square +[ico-travis]: https://img.shields.io/travis/php-gettext/PHP-Scanner/master.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/gettext/php-scanner.svg?style=flat-square + +[link-packagist]: https://packagist.org/packages/gettext/php-scanner +[link-travis]: https://travis-ci.org/php-gettext/PHP-Scanner +[link-downloads]: https://packagist.org/packages/gettext/php-scanner diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/composer.json b/.extlib/simplesamlphp/vendor/gettext/php-scanner/composer.json new file mode 100644 index 000000000..8b73a0fd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/composer.json @@ -0,0 +1,48 @@ +{ + "name": "gettext/php-scanner", + "type": "library", + "description": "PHP scanner for gettext", + "keywords": ["php", "gettext", "i18n", "translation", "scanner"], + "homepage": "https://github.com/php-gettext/PHP-Scanner", + "license": "MIT", + "authors": [ + { + "name": "Oscar Otero", + "email": "oom@oscarotero.com", + "homepage": "http://oscarotero.com", + "role": "Developer" + } + ], + "support": { + "email": "oom@oscarotero.com", + "issues": "https://github.com/php-gettext/PHP-Scanner/issues" + }, + "require": { + "php": ">=7.2", + "nikic/php-parser": "^4.2", + "gettext/gettext": "^5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0", + "squizlabs/php_codesniffer": "^3.0", + "oscarotero/php-cs-fixer-config": "^1.0", + "friendsofphp/php-cs-fixer": "^2.15" + }, + "autoload": { + "psr-4": { + "Gettext\\Scanner\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Gettext\\Tests\\": "tests" + } + }, + "scripts": { + "test": [ + "phpunit", + "phpcs" + ], + "cs-fix": "php-cs-fixer fix" + } +} diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpFunctionsScanner.php b/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpFunctionsScanner.php new file mode 100644 index 000000000..108dfa735 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpFunctionsScanner.php @@ -0,0 +1,42 @@ +validFunctions = $validFunctions; + $this->parser = $parser ?: (new ParserFactory())->create(ParserFactory::PREFER_PHP7); + } + + public function scan(string $code, string $filename): array + { + $ast = $this->parser->parse($code); + + if (empty($ast)) { + return []; + } + + $traverser = new NodeTraverser(); + $visitor = $this->createNodeVisitor($filename); + $traverser->addVisitor($visitor); + $traverser->traverse($ast); + + return $visitor->getFunctions(); + } + + protected function createNodeVisitor(string $filename): NodeVisitor + { + return new PhpNodeVisitor($filename, $this->validFunctions); + } +} diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpNodeVisitor.php b/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpNodeVisitor.php new file mode 100644 index 000000000..20fe8a97e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpNodeVisitor.php @@ -0,0 +1,169 @@ +filename = $filename; + $this->validFunctions = $validFunctions; + } + + public function beforeTraverse(array $nodes) + { + return null; + } + + public function enterNode(Node $node) + { + switch ($node->getType()) { + case 'Expr_MethodCall': + case 'Expr_FuncCall': + case 'Expr_StaticCall': + $name = static::getName($node); + + if ($name && ($this->validFunctions === null || in_array($name, $this->validFunctions))) { + $this->functions[] = $this->createFunction($node); + } elseif ($node->getComments()) { + $this->bufferComments = $node; + } + return null; + case 'Stmt_Echo': + case 'Stmt_Return': + case 'Expr_Print': + case 'Expr_Assign': + $this->bufferComments = $node; + return null; + } + + return null; + } + + public function leaveNode(Node $node) + { + return null; + } + + public function afterTraverse(array $nodes) + { + return null; + } + + public function getFunctions(): array + { + return $this->functions; + } + + /** + * @param FuncCall|MethodCall $node + */ + protected function createFunction(Expr $node): ParsedFunction + { + $function = new ParsedFunction( + static::getName($node), + $this->filename, + $node->getStartLine(), + $node->getEndLine() + ); + + foreach ($node->getComments() as $comment) { + $function->addComment(static::getComment($comment)); + } + + if ($this->bufferComments && $this->bufferComments->getStartLine() === $node->getStartLine()) { + foreach ($this->bufferComments->getComments() as $comment) { + $function->addComment(static::getComment($comment)); + } + } + + $this->bufferComments = null; + + foreach ($node->args as $argument) { + $value = $argument->value; + + foreach ($argument->getComments() as $comment) { + $function->addComment(static::getComment($comment)); + } + + $function->addArgument(static::getValue($value)); + } + + return $function; + } + + protected static function getComment(Comment $comment): string + { + $text = $comment->getReformattedText(); + + $lines = array_map(function ($line) { + $line = ltrim($line, "#*/ \t"); + $line = rtrim($line, "#*/ \t"); + return trim($line); + }, explode("\n", $text)); + + return trim(implode("\n", $lines)); + } + + protected static function getName(Node $node): ?string + { + $name = $node->name; + + if ($name instanceof Name) { + return $name->getLast(); + } + + if ($name instanceof Identifier) { + return (string) $name; + } + + return null; + } + + protected static function getValue(Expr $value) + { + $type = $value->getType(); + + switch ($type) { + case 'Scalar_String': + case 'Scalar_LNumber': + case 'Scalar_DNumber': + return $value->value; + case 'Expr_BinaryOp_Concat': + $values = []; + foreach ($value->getSubNodeNames() as $name) { + $values[] = static::getValue($value->$name); + } + return implode('', $values); + case 'Expr_Array': + $arr = []; + + foreach ($value->items as $item) { + $value = static::getValue($item->value); + + if ($item->key === null) { + $arr[] = $value; + } else { + $key = static::getValue($item->key); + $arr[$key] = $value; + } + } + + return $arr; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpScanner.php b/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpScanner.php new file mode 100644 index 000000000..97fb32d89 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/gettext/php-scanner/src/PhpScanner.php @@ -0,0 +1,67 @@ + 'gettext', + '_' => 'gettext', + '__' => 'gettext', + 'ngettext' => 'ngettext', + 'n__' => 'ngettext', + 'pgettext' => 'pgettext', + 'p__' => 'pgettext', + 'dgettext' => 'dgettext', + 'd__' => 'dgettext', + 'dngettext' => 'dngettext', + 'dn__' => 'dngettext', + 'dpgettext' => 'dpgettext', + 'dp__' => 'dpgettext', + 'npgettext' => 'npgettext', + 'np__' => 'npgettext', + 'dnpgettext' => 'dnpgettext', + 'dnp__' => 'dnpgettext', + 'noop' => 'gettext', + 'noop__' => 'gettext', + ]; + + public function getFunctionsScanner(): FunctionsScannerInterface + { + return new PhpFunctionsScanner(array_keys($this->functions)); + } + + protected function saveTranslation( + ?string $domain, + ?string $context, + string $original, + string $plural = null + ): ?Translation { + $translation = parent::saveTranslation($domain, $context, $original, $plural); + + if (!$translation) { + return null; + } + + $original = $translation->getOriginal(); + + //Check if it includes a sprintf + if (strpos($original, '%') !== false) { + // %[argnum$][flags][width][.precision]specifier + if (preg_match('/%(\d+\$)?([\-\+\s0]|\'.)?(\d+)?(\.\d+)?[bcdeEfFgGhHosuxX]/', $original)) { + $translation->getFlags()->add('php-format'); + } + } + + return $translation; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/.github/workflows/runTests.yml b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/.github/workflows/runTests.yml new file mode 100644 index 000000000..3d4f48276 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/.github/workflows/runTests.yml @@ -0,0 +1,71 @@ +name: Tests + +on: + push: + branches: + - v1.6 + pull_request: + branches: + - v1.6 + +jobs: + tests: + name: PHP ${{ matrix.php-versions }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + php-versions: + - '7.1' + - '7.2' + - '7.3' + - '7.4' + - '8.0' + - '8.1' + - '8.2' + - '8.3' + - '8.4' + os: [ubuntu-latest, windows-latest, macOS-latest] + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up PHP ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring + coverage: pcov + + - name: Setup Problem Matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - name: Setup Problem Matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: | + composer install --prefer-dist --no-progress + + - name: Run test suite + if: matrix.php-versions == '7.1' + run: composer run-script test -- --no-coverage + + - name: Run test suite + if: matrix.php-versions > '7.1' + run: composer run-script test -- --coverage-text diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/CHANGELOG.md b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/CHANGELOG.md new file mode 100644 index 000000000..6ccf7c96c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/CHANGELOG.md @@ -0,0 +1,275 @@ +1.6.12 (2024-08-29) +------------------- + +* Drop php 5 and 7.0 support as new versions enforced a syntax change that is not compatible with the old versions. + +1.6.11 (2022-07-26) +------------------- + + * Add support for PHP 8.2's `$content` property in `vfsStreamWrapper` + +1.6.10 (2021-09-25) +------------------- + + * Fix more deprecation warnings for PHP 8.1 support affecting the following: + - `vfsStreamContainerIterator::current()` + - `vfsStreamContainerIterator::next()` + - `vfsStreamContainerIterator::key()` + - `vfsStreamContainerIterator::rewind()` + - `vfsStreamDirectory::getIterator()` + - `vfsStreamPrintVisitor::printContent()` + * Fix PHP 8.1 support in `vfsStreamPrintVisitor` + +1.6.9 (2021-07-16) +------------------ + + * Fix deprecation warning on `StringBasedFileContent` for PHP 8.1 (#252) + * Fix return type for `FileContent::write()` to fix static analysis tools + +1.6.8 (2019-10-30) +------------------ + + * Fix `StringBasedFileContent::doRead` to always return a string (#204) + +1.6.7 (2019-07-31) +------------------ + + * fix PHP 7.4 deprecation warnings (backported #189 from master) + +1.6.6 (2019-04-08) +------------------ + + * backported #174 from master, original PR provided by @localheinz + + +1.6.5 (2017-08-01) +------------------ + + * fixed #157 seeking before beginning of file should fail, reported and fixed by @merijnvdk + * structure array in `vfsStream::create()` and `vfsStream::setup()` now can contain instances of `org\bovigo\vfs\content\FileContent` and `org\bovigo\vfs\vfsStreamFile`, patch provivded by Joshua Smith (@jsmitty12) + + +1.6.4 (2016-07-18) +------------------ + + * fixed #134 type safe directory names, reported and fixed by Sebastian Hopfe + + +1.6.3 (2016-04-09) +------------------ + + * fixed #131 recursive mkdir() fails if the last dirname is '0' + + +1.6.2 (2016-01-13) +------------------ + + * fixed #128 duplicate "valid" files/directories and incorrect file names + + +1.6.1 (2015-12-04) +------------------ + + * `vfsStream::url()` didn't urlencode single path parts while `vfsStream::path()` did urldecode them + * fixed #120, #122: create directory with trailing slash results in "Uninitialized string offset: 0" + + +1.6.0 (2015-10-06) +------------------ + + * added `vfsStreamWrapper::unregister()`, provided by @malkusch with #114 + * fixed #115: incorrect handling of `..` in root directory on PHP 5.5, fix provided by @acoulton with #116 + + +1.5.0 (2015-03-29) +------------------ + + * implemented #91: `vfsStream::copyFromFileSystem()` should create large file instances + * implemented #92: `vfsStream::copyFromFileSystem()` should respect block devices + * fixed #107: `touch()` does not respect file permissions + * fixed #105: vfs directory structure is not reset after each test + * fixed #104: vfsStream can't handle url encoded pathes + + +1.4.0 (2014-09-14) +------------------ + + * implemented #85: Added support for emulating block devices in the virtual filesystem, feature provided by Harris Borawski + * fixed #68: Unlink a non-existing file now triggers a PHP warning + + +1.3.0 (2014-07-21) +------------------ + + * implemented #79: possibility to mock large files without large memory footprint, see https://github.com/mikey179/vfsStream/wiki/MockingLargeFiles + * implemented #67: added partial support for text-mode translation flag (i.e., no actual translation of line endings takes place) so it no longer throws an exception (provided by Anthon Pang) + * fixed issue #74: issue with trailing windows path separators (provided by Sebastian Krüger) + * fixed issue #50: difference between real file system and vfs with `RecursiveDirectoryIterator` + * fixed issue #80: touch with no arguments for modification and access time behave incorrect + * deprecated `org\bovigo\vfs\vfsStreamFile::readUntilEnd()` + * deprecated `org\bovigo\vfs\vfsStreamFile::getBytesRead()` + + +1.2.0 (2013-04-01) +------------------ + + * implemented issue #34: provide `url()` method on all `vfsStreamContent` instances + * added `org\bovigo\vfs\vfsStreamContent::url()` + * added `org\bovigo\vfs\vfsStreamContent::path()` + * fixed issue #40: flock implementation doesn't work correctly, patch provided by Kamil Dziedzic + * fixed issue #49: call to member function on a non-object when trying to delete a file one above root where a file with same name in root exists + * fixed issue #51: `unlink()` must consider permissions of directory where file is inside, not of the file to unlink itself + * fixed issue #52: `chmod()`, `chown()` and `chgrp()` must consider permissions of directory where file/directory is inside + * fixed issue #53: `chmod()`, `chown()` and `chgrp()` must consider current user and current owner of file/directoy to change + + +1.1.0 (2012-08-25) +------------------ + + * implemented issue #11: add support for `streamWrapper::stream_metadata()` vfsStream now supports `touch()`, `chown()`, `chgrp()` and `chmod()` + * implemented issue #33: add support for `stream_truncate()` (provided by https://github.com/nikcorg) + * implemented issue #35: size limit (quota) for VFS + + +1.0.0 (2012-05-15) +------------------ + + * raised requirement for PHP version to 5.3.0 + * migrated codebase to use namespaces + * changed distribution from PEAR to Composer + * implemented issue #30: support "c" mode for `fopen()` + * fixed issue #31: prohibit aquiring locks when already locked / release lock on `fclose()` + * fixed issue #32: problems when subfolder has same name as folder + * fixed issue #36: `vfsStreamWrapper::stream_open()` should return false while trying to open existing non-writable file, patch provided by Alexander Peresypkin + + +0.11.2 (2012-01-14) +------------------- + + * fixed issue #29: set permissions properly when using `vfsStream::copyFromFileSystem()`, patch provided by predakanga + * fixed failing tests under PHP > 5.3.2 + + +0.11.1 (2011-12-04) +------------------- + + * fixed issue #28: `mkdir()` overwrites existing directories/files + + +0.11.0 (2011-11-29) +------------------- + + * implemented issue #20: `vfsStream::create()` removes old structure + * implemented issue #4: possibility to copy structure from existing file system + * fixed issue #23: `unlink()` should not remove any directory + * fixed issue #25: `vfsStreamDirectory::hasChild()` gives false positives for nested paths, patch provided by Andrew Coulton + * fixed issue #26: opening a file for reading only should not update its modification time, reported and initial patch provided by Ludovic Chabant + + +0.10.1 (2011-08-22) +------------------- + + * fixed issue #16: replace `vfsStreamContent` to `vfsStreamContainer` for autocompletion + * fixed issue #17: `vfsStream::create()` has issues with numeric directories, patch provided by mathieuk + + +0.10.0 (2011-07-22) +------------------- + + * added new method `vfsStreamContainer::hasChildren()` and `vfsStreamDirectory::hasChildren()` + * implemented issue #14: less verbose way to initialize vfsStream + * implemented issue #13: remove deprecated method `vfsStreamContent::setFilemtime()` + * implemented issue #6: locking meachanism for files + * ensured that `stream_set_blocking()`, `stream_set_timeout()` and `stream_set_write_buffer()` on vfsStream urls have the same behaviour with PHP 5.2 and 5.3 + * implemented issue #10: method to print directory structure + + +0.9.0 (2011-07-13) +------------------ + + * implemented feature request issue #7: add support for `fileatime()` and `filectime()` + * fixed issue #3: add support for `streamWrapper::stream_cast()` + * fixed issue #9: resolve path not called everywhere its needed + * deprecated `vfsStreamAbstractContent::setFilemtime()`, use `vfsStreamAbstractContent::lastModified()` instead, will be removed with 0.10.0 + + +0.8.0 (2010-10-08) +------------------ + + * implemented enhancement #6: use `vfsStream::umask()` to influence initial file mode for files and directories + * implemented enhancement #19: support of .. in the url, patch provided by Guislain Duthieuw + * fixed issue #18: `getChild()` returns NULL when child's name contains parent name + * fixed bug with incomplete error message when accessing non-existing files on root level + + +0.7.0 (2010-06-08) +------------------ + + * added new `vfsStream::setup()` method to simplify vfsStream usage + * fixed issue #15: `mkdir()` creates a subfolder in a folder without permissions + + +0.6.0 (2010-02-15) +------------------ + + * added support for `$mode` param when opening files, implements enhancement #7 and fixes issue #13 + * `vfsStreamWrapper::stream_open()` now evaluates `$options` for `STREAM_REPORT_ERRORS` + + +0.5.0 (2010-01-25) +------------------ + + * added support for `rename()`, patch provided by Benoit Aubuchon + * added support for . as directory alias so that `vfs://foo/.` resolves to `vfs://foo`, can be used as workaround for bug #8 + + +0.4.0 (2009-07-13) +------------------ + + * added support for file modes, users and groups (with restrictions, see http://code.google.com/p/bovigo/wiki/vfsStreamDocsKnownIssues) + * fixed bug #5: `vfsStreamDirectory::addChild()` does not replace child with same name + * fixed bug with `is_writable()` because of missing `stat()` fields, patch provided by Sergey Galkin + + +0.3.2 (2009-02-16) +------------------ + + * support trailing slashes on directories in vfsStream urls, patch provided by Gabriel Birke + * fixed bug #4: vfsstream can only be read once, reported by Christoph Bloemer + * enabled multiple iterations at the same time over the same directory + + +0.3.1 (2008-02-18) +------------------ + + * fixed path/directory separator issues under linux systems + * fixed uid/gid issues under linux systems + + +0.3.0 (2008-01-02) +------------------ + + * added support for `rmdir()` + * added `vfsStream::newDirectory()`, dropped `vfsStreamDirectory::ceate()` + * added new interface `vfsStreamContainer` + * added `vfsStreamContent::at()` which allows code like `$file = vfsStream::newFile('file.txt.')->withContent('foo')->at($otherDir);` + * added `vfsStreamContent::lastModified()`, made `vfsStreamContent::setFilemtime()` an alias for this + * moved from Stubbles development environment to bovigo + * refactorings to reduce crap index of various methods + + +0.2.0 (2007-12-29) +------------------ + + * moved `vfsStreamWrapper::PROTOCOL` to `vfsStream::SCHEME` + * added new `vfsStream::url()` method to assist in creating correct vfsStream urls + * added `vfsStream::path()` method as opposite to `vfsStream::url()` + * a call to `vfsStreamWrapper::register()` will now reset the root to null, implemented on request from David Zuelke + * added support for `is_readable()`, `is_dir()`, `is_file()` + * added `vfsStream::newFile()` to be able to do `$file = vfsStream::newFile("foo.txt")->withContent("bar");` + + +0.1.0 (2007-12-14) +------------------ + + * Initial release. diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/LICENSE b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/LICENSE new file mode 100644 index 000000000..1d41ab934 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2007-2015, Frank Kleine +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 Stubbles nor the names of its + 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/.extlib/simplesamlphp/vendor/mikey179/vfsstream/README.md b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/README.md new file mode 100644 index 000000000..a1b47ee66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/README.md @@ -0,0 +1,8 @@ +You can find documentation in the [wiki](https://github.com/mikey179/vfsStream/wiki). + +Also you might want to check [vfsStream examples](https://github.com/mikey179/vfsStream-examples). + + +[![Build Status](https://secure.travis-ci.org/mikey179/vfsStream.png)](http://travis-ci.org/mikey179/vfsStream) [![Build Status Windows](https://ci.appveyor.com/api/projects/status/6whqgluyeggspjp1/branch/master?svg=true)](https://ci.appveyor.com/project/mikey179/vfsstream) [![Coverage Status](https://coveralls.io/repos/github/bovigo/vfsStream/badge.svg?branch=v1.x)](https://coveralls.io/github/bovigo/vfsStream?branch=v1.x) + +[![Latest Stable Version](https://poser.pugx.org/mikey179/vfsStream/version.png)](https://packagist.org/packages/mikey179/vfsStream) [![Latest Unstable Version](https://poser.pugx.org/mikey179/vfsStream/v/unstable.png)](//packagist.org/packages/mikey179/vfsStream) diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/composer.json b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/composer.json new file mode 100644 index 000000000..f729a8d35 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/composer.json @@ -0,0 +1,37 @@ +{ + "name": "mikey179/vfsstream", + "type": "library", + "homepage": "http://vfs.bovigo.org/", + "description": "Virtual file system to mock the real file system in unit tests.", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Frank Kleine", + "homepage": "http://frankkleine.de/", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/bovigo/vfsStream/issues", + "source": "https://github.com/bovigo/vfsStream/tree/master", + "wiki": "https://github.com/bovigo/vfsStream/wiki" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5||^8.5||^9.6", + "yoast/phpunit-polyfills": "^2.0" + }, + "autoload": { + "psr-0": { "org\\bovigo\\vfs\\": "src/main/php" } + }, + "scripts": { + "test": "phpunit" + }, + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/phpunit.xml.dist b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/phpunit.xml.dist new file mode 100644 index 000000000..56057d765 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/phpunit.xml.dist @@ -0,0 +1,43 @@ + + + + + ./src/test/phpt + ./src/test/php + + + + + + src/main/php + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/DotDirectory.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/DotDirectory.php new file mode 100644 index 000000000..edc975129 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/DotDirectory.php @@ -0,0 +1,36 @@ +amount = $amount; + } + + /** + * create with unlimited space + * + * @return Quota + */ + public static function unlimited() + { + return new self(self::UNLIMITED); + } + + /** + * checks if a quota is set + * + * @return bool + */ + public function isLimited() + { + return self::UNLIMITED < $this->amount; + } + + /** + * checks if given used space exceeda quota limit + * + * + * @param int $usedSpace + * @return int + */ + public function spaceLeft($usedSpace) + { + if (self::UNLIMITED === $this->amount) { + return $usedSpace; + } + + if ($usedSpace >= $this->amount) { + return 0; + } + + $spaceLeft = $this->amount - $usedSpace; + if (0 >= $spaceLeft) { + return 0; + } + + return $spaceLeft; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/FileContent.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/FileContent.php new file mode 100644 index 000000000..e62e30987 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/FileContent.php @@ -0,0 +1,71 @@ +size = $size; + } + + /** + * create large file with given size in kilobyte + * + * @param int $kilobyte + * @return LargeFileContent + */ + public static function withKilobytes($kilobyte) + { + return new self($kilobyte * 1024); + } + + /** + * create large file with given size in megabyte + * + * @param int $megabyte + * @return LargeFileContent + */ + public static function withMegabytes($megabyte) + { + return self::withKilobytes($megabyte * 1024); + } + + /** + * create large file with given size in gigabyte + * + * @param int $gigabyte + * @return LargeFileContent + */ + public static function withGigabytes($gigabyte) + { + return self::withMegabytes($gigabyte * 1024); + } + + /** + * returns actual content + * + * @return string + */ + public function content() + { + return $this->doRead(0, $this->size); + } + + /** + * returns size of content + * + * @return int + */ + public function size() + { + return $this->size; + } + + /** + * actual reading of given byte count starting at given offset + * + * @param int $offset + * @param int $count + */ + protected function doRead($offset, $count) + { + if (($offset + $count) > $this->size) { + $count = $this->size - $offset; + } + + $result = ''; + for ($i = 0; $i < $count; $i++) { + if (isset($this->content[$i + $offset])) { + $result .= $this->content[$i + $offset]; + } else { + $result .= ' '; + } + } + + return $result; + } + + /** + * actual writing of data with specified length at given offset + * + * @param string $data + * @param int $offset + * @param int $length + */ + protected function doWrite($data, $offset, $length) + { + for ($i = 0; $i < $length; $i++) { + $this->content[$i + $offset] = substr($data, $i, 1); + } + + if ($offset >= $this->size) { + $this->size += $length; + } elseif (($offset + $length) > $this->size) { + $this->size = $offset + $length; + } + } + + /** + * Truncates a file to a given length + * + * @param int $size length to truncate file to + * @return bool + */ + public function truncate($size) + { + $this->size = $size; + foreach (array_filter(array_keys($this->content), + function($pos) use ($size) + { + return $pos >= $size; + } + ) as $removePos) { + unset($this->content[$removePos]); + } + + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/SeekableFileContent.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/SeekableFileContent.php new file mode 100644 index 000000000..960284cf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/SeekableFileContent.php @@ -0,0 +1,134 @@ +doRead($this->offset, $count); + $this->offset += $count; + return $data; + } + + /** + * actual reading of given byte count starting at given offset + * + * @param int $offset + * @param int $count + */ + protected abstract function doRead($offset, $count); + + /** + * seeks to the given offset + * + * @param int $offset + * @param int $whence + * @return bool + */ + public function seek($offset, $whence) + { + $newOffset = $this->offset; + switch ($whence) { + case SEEK_CUR: + $newOffset += $offset; + break; + + case SEEK_END: + $newOffset = $this->size() + $offset; + break; + + case SEEK_SET: + $newOffset = $offset; + break; + + default: + return false; + } + + if ($newOffset<0) { + return false; + } + $this->offset = $newOffset; + return true; + } + + /** + * checks whether pointer is at end of file + * + * @return bool + */ + public function eof() + { + return $this->size() <= $this->offset; + } + + /** + * writes an amount of data + * + * @param string $data + * @return int amount of written bytes + */ + public function write($data) + { + $dataLength = strlen($data); + $this->doWrite($data, $this->offset, $dataLength); + $this->offset += $dataLength; + return $dataLength; + } + + /** + * actual writing of data with specified length at given offset + * + * @param string $data + * @param int $offset + * @param int $length + */ + protected abstract function doWrite($data, $offset, $length); + + /** + * for backwards compatibility with vfsStreamFile::bytesRead() + * + * @return int + * @deprecated + */ + public function bytesRead() + { + return $this->offset; + } + + /** + * for backwards compatibility with vfsStreamFile::readUntilEnd() + * + * @return string + * @deprecated + */ + public function readUntilEnd() + { + return substr($this->content(), $this->offset); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/StringBasedFileContent.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/StringBasedFileContent.php new file mode 100644 index 000000000..77adf8e56 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/content/StringBasedFileContent.php @@ -0,0 +1,97 @@ +content = $content; + } + + /** + * returns actual content + * + * @return string + */ + public function content() + { + return $this->content; + } + + /** + * returns size of content + * + * @return int + */ + public function size() + { + return strlen($this->content); + } + + /** + * actual reading of length starting at given offset + * + * @param int $offset + * @param int $count + */ + protected function doRead($offset, $count) + { + return (string) substr($this->content, $offset, $count); + } + + /** + * actual writing of data with specified length at given offset + * + * @param string $data + * @param int $offset + * @param int $length + */ + protected function doWrite($data, $offset, $length) + { + $this->content = substr($this->content, 0, $offset) + . $data + . substr($this->content, $offset + $length); + } + + /** + * Truncates a file to a given length + * + * @param int $size length to truncate file to + * @return bool + */ + public function truncate($size) + { + if ($size > $this->size()) { + // Pad with null-chars if we're "truncating up" + $this->content .= str_repeat("\0", $size - $this->size()); + } else { + $this->content = substr($this->content, 0, $size); + } + + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStream.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStream.php new file mode 100644 index 000000000..575b3b93d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStream.php @@ -0,0 +1,479 @@ + + * array('Core' = array('AbstractFactory' => array('test.php' => 'some text content', + * 'other.php' => 'Some more text content', + * 'Invalid.csv' => 'Something else', + * ), + * 'AnEmptyFolder' => array(), + * 'badlocation.php' => 'some bad content', + * ) + * ) + * + * the resulting directory tree will look like this: + *
    +     * root
    +     * \- Core
    +     *  |- badlocation.php
    +     *  |- AbstractFactory
    +     *  | |- test.php
    +     *  | |- other.php
    +     *  | \- Invalid.csv
    +     *  \- AnEmptyFolder
    +     * 
    + * Arrays will become directories with their key as directory name, and + * strings becomes files with their key as file name and their value as file + * content. + * + * @param string $rootDirName name of root directory + * @param int $permissions file permissions of root directory + * @param array $structure directory structure to add under root directory + * @return \org\bovigo\vfs\vfsStreamDirectory + * @since 0.7.0 + * @see https://github.com/mikey179/vfsStream/issues/14 + * @see https://github.com/mikey179/vfsStream/issues/20 + */ + public static function setup($rootDirName = 'root', $permissions = null, array $structure = array()) + { + vfsStreamWrapper::register(); + return self::create($structure, vfsStreamWrapper::setRoot(self::newDirectory($rootDirName, $permissions))); + } + + /** + * creates vfsStream directory structure from an array and adds it to given base dir + * + * Assumed $structure contains an array like this: + * + * array('Core' = array('AbstractFactory' => array('test.php' => 'some text content', + * 'other.php' => 'Some more text content', + * 'Invalid.csv' => 'Something else', + * ), + * 'AnEmptyFolder' => array(), + * 'badlocation.php' => 'some bad content', + * ) + * ) + * + * the resulting directory tree will look like this: + *
    +     * baseDir
    +     * \- Core
    +     *  |- badlocation.php
    +     *  |- AbstractFactory
    +     *  | |- test.php
    +     *  | |- other.php
    +     *  | \- Invalid.csv
    +     *  \- AnEmptyFolder
    +     * 
    + * Arrays will become directories with their key as directory name, and + * strings becomes files with their key as file name and their value as file + * content. + * + * If no baseDir is given it will try to add the structure to the existing + * root directory without replacing existing childs except those with equal + * names. + * + * @param array $structure directory structure to add under root directory + * @param vfsStreamDirectory $baseDir base directory to add structure to + * @return vfsStreamDirectory + * @throws \InvalidArgumentException + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/14 + * @see https://github.com/mikey179/vfsStream/issues/20 + */ + public static function create(array $structure, ?vfsStreamDirectory $baseDir = null) + { + if (null === $baseDir) { + $baseDir = vfsStreamWrapper::getRoot(); + } + + if (null === $baseDir) { + throw new \InvalidArgumentException('No baseDir given and no root directory set.'); + } + + return self::addStructure($structure, $baseDir); + } + + /** + * helper method to create subdirectories recursively + * + * @param array $structure subdirectory structure to add + * @param vfsStreamDirectory $baseDir directory to add the structure to + * @return vfsStreamDirectory + */ + protected static function addStructure(array $structure, vfsStreamDirectory $baseDir) + { + foreach ($structure as $name => $data) { + $name = (string) $name; + if (is_array($data) === true) { + self::addStructure($data, self::newDirectory($name)->at($baseDir)); + } elseif (is_string($data) === true) { + $matches = null; + preg_match('/^\[(.*)\]$/', $name, $matches); + if ($matches !== array()) { + self::newBlock($matches[1])->withContent($data)->at($baseDir); + } else { + self::newFile($name)->withContent($data)->at($baseDir); + } + } elseif ($data instanceof FileContent) { + self::newFile($name)->withContent($data)->at($baseDir); + } elseif ($data instanceof vfsStreamFile) { + $baseDir->addChild($data); + } + } + + return $baseDir; + } + + /** + * copies the file system structure from given path into the base dir + * + * If no baseDir is given it will try to add the structure to the existing + * root directory without replacing existing childs except those with equal + * names. + * File permissions are copied as well. + * Please note that file contents will only be copied if their file size + * does not exceed the given $maxFileSize which defaults to 1024 KB. In case + * the file is larger file content will be mocked, see + * https://github.com/mikey179/vfsStream/wiki/MockingLargeFiles. + * + * @param string $path path to copy the structure from + * @param vfsStreamDirectory $baseDir directory to add the structure to + * @param int $maxFileSize maximum file size of files to copy content from + * @return vfsStreamDirectory + * @throws \InvalidArgumentException + * @since 0.11.0 + * @see https://github.com/mikey179/vfsStream/issues/4 + */ + public static function copyFromFileSystem($path, ?vfsStreamDirectory $baseDir = null, $maxFileSize = 1048576) + { + if (null === $baseDir) { + $baseDir = vfsStreamWrapper::getRoot(); + } + + if (null === $baseDir) { + throw new \InvalidArgumentException('No baseDir given and no root directory set.'); + } + + $dir = new \DirectoryIterator($path); + foreach ($dir as $fileinfo) { + switch (filetype($fileinfo->getPathname())) { + case 'file': + if ($fileinfo->getSize() <= $maxFileSize) { + $content = file_get_contents($fileinfo->getPathname()); + } else { + $content = new LargeFileContent($fileinfo->getSize()); + } + + self::newFile( + $fileinfo->getFilename(), + octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) + ) + ->withContent($content) + ->at($baseDir); + break; + + case 'dir': + if (!$fileinfo->isDot()) { + self::copyFromFileSystem( + $fileinfo->getPathname(), + self::newDirectory( + $fileinfo->getFilename(), + octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) + )->at($baseDir), + $maxFileSize + ); + } + + break; + + case 'block': + self::newBlock( + $fileinfo->getFilename(), + octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4)) + )->at($baseDir); + break; + } + } + + return $baseDir; + } + + /** + * returns a new file with given name + * + * @param string $name name of file to create + * @param int $permissions permissions of file to create + * @return vfsStreamFile + */ + public static function newFile($name, $permissions = null) + { + return new vfsStreamFile($name, $permissions); + } + + /** + * returns a new directory with given name + * + * If the name contains slashes, a new directory structure will be created. + * The returned directory will always be the parent directory of this + * directory structure. + * + * @param string $name name of directory to create + * @param int $permissions permissions of directory to create + * @return vfsStreamDirectory + */ + public static function newDirectory($name, $permissions = null) + { + if ('/' === substr($name, 0, 1)) { + $name = substr($name, 1); + } + + $firstSlash = strpos($name, '/'); + if (false === $firstSlash) { + return new vfsStreamDirectory($name, $permissions); + } + + $ownName = substr($name, 0, $firstSlash); + $subDirs = substr($name, $firstSlash + 1); + $directory = new vfsStreamDirectory($ownName, $permissions); + if (is_string($subDirs) && strlen($subDirs) > 0) { + self::newDirectory($subDirs, $permissions)->at($directory); + } + + return $directory; + } + + /** + * returns a new block with the given name + * + * @param string $name name of the block device + * @param int $permissions permissions of block to create + * @return vfsStreamBlock + */ + public static function newBlock($name, $permissions = null) + { + return new vfsStreamBlock($name, $permissions); + } + + /** + * returns current user + * + * If the system does not support posix_getuid() the current user will be root (0). + * + * @return int + */ + public static function getCurrentUser() + { + return function_exists('posix_getuid') ? posix_getuid() : self::OWNER_ROOT; + } + + /** + * returns current group + * + * If the system does not support posix_getgid() the current group will be root (0). + * + * @return int + */ + public static function getCurrentGroup() + { + return function_exists('posix_getgid') ? posix_getgid() : self::GROUP_ROOT; + } + + /** + * use visitor to inspect a content structure + * + * If the given content is null it will fall back to use the current root + * directory of the stream wrapper. + * + * Returns given visitor for method chaining comfort. + * + * @param vfsStreamVisitor $visitor the visitor who inspects + * @param vfsStreamContent $content directory structure to inspect + * @return vfsStreamVisitor + * @throws \InvalidArgumentException + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/10 + */ + public static function inspect(vfsStreamVisitor $visitor, ?vfsStreamContent $content = null) + { + if (null !== $content) { + return $visitor->visit($content); + } + + $root = vfsStreamWrapper::getRoot(); + if (null === $root) { + throw new \InvalidArgumentException('No content given and no root directory set.'); + } + + return $visitor->visitDirectory($root); + } + + /** + * sets quota to given amount of bytes + * + * @param int $bytes + * @since 1.1.0 + */ + public static function setQuota($bytes) + { + vfsStreamWrapper::setQuota(new Quota($bytes)); + } + + /** + * checks if vfsStream lists dotfiles in directory listings + * + * @return bool + * @since 1.3.0 + */ + public static function useDotfiles() + { + return self::$dotFiles; + } + + /** + * disable dotfiles in directory listings + * + * @since 1.3.0 + */ + public static function disableDotfiles() + { + self::$dotFiles = false; + } + + /** + * enable dotfiles in directory listings + * + * @since 1.3.0 + */ + public static function enableDotfiles() + { + self::$dotFiles = true; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php new file mode 100644 index 000000000..7db2be28b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php @@ -0,0 +1,418 @@ +name = "{$name}"; + $time = time(); + if (null === $permissions) { + $permissions = $this->getDefaultPermissions() & ~vfsStream::umask(); + } + + $this->lastAccessed = $time; + $this->lastAttributeModified = $time; + $this->lastModified = $time; + $this->permissions = $permissions; + $this->user = vfsStream::getCurrentUser(); + $this->group = vfsStream::getCurrentGroup(); + } + + /** + * returns default permissions for concrete implementation + * + * @return int + * @since 0.8.0 + */ + protected abstract function getDefaultPermissions(); + + /** + * returns the file name of the content + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * renames the content + * + * @param string $newName + */ + public function rename($newName) + { + $this->name = "{$newName}"; + } + + /** + * checks whether the container can be applied to given name + * + * @param string $name + * @return bool + */ + public function appliesTo($name) + { + if ($name === $this->name) { + return true; + } + + $segment_name = $this->name.'/'; + return (strncmp($segment_name, $name, strlen($segment_name)) == 0); + } + + /** + * returns the type of the container + * + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * sets the last modification time of the stream content + * + * @param int $filemtime + * @return $this + */ + public function lastModified($filemtime) + { + $this->lastModified = $filemtime; + return $this; + } + + /** + * returns the last modification time of the stream content + * + * @return int + */ + public function filemtime() + { + return $this->lastModified; + } + + /** + * sets last access time of the stream content + * + * @param int $fileatime + * @return $this + * @since 0.9 + */ + public function lastAccessed($fileatime) + { + $this->lastAccessed = $fileatime; + return $this; + } + + /** + * returns the last access time of the stream content + * + * @return int + * @since 0.9 + */ + public function fileatime() + { + return $this->lastAccessed; + } + + /** + * sets the last attribute modification time of the stream content + * + * @param int $filectime + * @return $this + * @since 0.9 + */ + public function lastAttributeModified($filectime) + { + $this->lastAttributeModified = $filectime; + return $this; + } + + /** + * returns the last attribute modification time of the stream content + * + * @return int + * @since 0.9 + */ + public function filectime() + { + return $this->lastAttributeModified; + } + + /** + * adds content to given container + * + * @param vfsStreamContainer $container + * @return $this + */ + public function at(vfsStreamContainer $container) + { + $container->addChild($this); + return $this; + } + + /** + * change file mode to given permissions + * + * @param int $permissions + * @return $this + */ + public function chmod($permissions) + { + $this->permissions = $permissions; + $this->lastAttributeModified = time(); + clearstatcache(); + return $this; + } + + /** + * returns permissions + * + * @return int + */ + public function getPermissions() + { + return $this->permissions; + } + + /** + * checks whether content is readable + * + * @param int $user id of user to check for + * @param int $group id of group to check for + * @return bool + */ + public function isReadable($user, $group) + { + if ($this->user === $user) { + $check = 0400; + } elseif ($this->group === $group) { + $check = 0040; + } else { + $check = 0004; + } + + return (bool) ($this->permissions & $check); + } + + /** + * checks whether content is writable + * + * @param int $user id of user to check for + * @param int $group id of group to check for + * @return bool + */ + public function isWritable($user, $group) + { + if ($this->user === $user) { + $check = 0200; + } elseif ($this->group === $group) { + $check = 0020; + } else { + $check = 0002; + } + + return (bool) ($this->permissions & $check); + } + + /** + * checks whether content is executable + * + * @param int $user id of user to check for + * @param int $group id of group to check for + * @return bool + */ + public function isExecutable($user, $group) + { + if ($this->user === $user) { + $check = 0100; + } elseif ($this->group === $group) { + $check = 0010; + } else { + $check = 0001; + } + + return (bool) ($this->permissions & $check); + } + + /** + * change owner of file to given user + * + * @param int $user + * @return $this + */ + public function chown($user) + { + $this->user = $user; + $this->lastAttributeModified = time(); + return $this; + } + + /** + * checks whether file is owned by given user + * + * @param int $user + * @return bool + */ + public function isOwnedByUser($user) + { + return $this->user === $user; + } + + /** + * returns owner of file + * + * @return int + */ + public function getUser() + { + return $this->user; + } + + /** + * change owner group of file to given group + * + * @param int $group + * @return $this + */ + public function chgrp($group) + { + $this->group = $group; + $this->lastAttributeModified = time(); + return $this; + } + + /** + * checks whether file is owned by group + * + * @param int $group + * @return bool + */ + public function isOwnedByGroup($group) + { + return $this->group === $group; + } + + /** + * returns owner group of file + * + * @return int + */ + public function getGroup() + { + return $this->group; + } + + /** + * sets parent path + * + * @param string $parentPath + * @internal only to be set by parent + * @since 1.2.0 + */ + public function setParentPath($parentPath) + { + $this->parentPath = $parentPath; + } + + /** + * returns path to this content + * + * @return string + * @since 1.2.0 + */ + public function path() + { + if (null === $this->parentPath) { + return $this->name; + } + + return $this->parentPath . '/' . $this->name; + } + + /** + * returns complete vfsStream url for this content + * + * @return string + * @since 1.2.0 + */ + public function url() + { + return vfsStream::url($this->path()); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamBlock.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamBlock.php new file mode 100644 index 000000000..128a96a31 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamBlock.php @@ -0,0 +1,34 @@ +type = vfsStreamContent::TYPE_BLOCK; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainer.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainer.php new file mode 100644 index 000000000..74faa9a12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContainer.php @@ -0,0 +1,61 @@ +children = $children; + if (vfsStream::useDotfiles()) { + array_unshift($this->children, new DotDirectory('.'), new DotDirectory('..')); + } + + reset($this->children); + } + + /** + * resets children pointer + */ + #[\ReturnTypeWillChange] + public function rewind() + { + reset($this->children); + } + + /** + * returns the current child + * + * @return vfsStreamContent + */ + #[\ReturnTypeWillChange] + public function current() + { + $child = current($this->children); + if (false === $child) { + return null; + } + + return $child; + } + + /** + * returns the name of the current child + * + * @return string + */ + #[\ReturnTypeWillChange] + public function key() + { + $child = current($this->children); + if (false === $child) { + return null; + } + + return $child->getName(); + } + + /** + * iterates to next child + */ + #[\ReturnTypeWillChange] + public function next() + { + next($this->children); + } + + /** + * checks if the current value is valid + * + * @return bool + */ + #[\ReturnTypeWillChange] + public function valid() + { + return (false !== current($this->children)); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContent.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContent.php new file mode 100644 index 000000000..03b5bab70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamContent.php @@ -0,0 +1,213 @@ +type = vfsStreamContent::TYPE_DIR; + parent::__construct($name, $permissions); + } + + /** + * returns default permissions for concrete implementation + * + * @return int + * @since 0.8.0 + */ + protected function getDefaultPermissions() + { + return 0777; + } + + /** + * returns size of directory + * + * The size of a directory is always 0 bytes. To calculate the summarized + * size of all children in the directory use sizeSummarized(). + * + * @return int + */ + public function size() + { + return 0; + } + + /** + * returns summarized size of directory and its children + * + * @return int + */ + public function sizeSummarized() + { + $size = 0; + foreach ($this->children as $child) { + if ($child->getType() === vfsStreamContent::TYPE_DIR) { + $size += $child->sizeSummarized(); + } else { + $size += $child->size(); + } + } + + return $size; + } + + /** + * renames the content + * + * @param string $newName + * @throws vfsStreamException + */ + public function rename($newName) + { + if (strstr($newName, '/') !== false) { + throw new vfsStreamException('Directory name can not contain /.'); + } + + parent::rename($newName); + } + + + /** + * sets parent path + * + * @param string $parentPath + * @internal only to be set by parent + * @since 1.2.0 + */ + public function setParentPath($parentPath) + { + parent::setParentPath($parentPath); + foreach ($this->children as $child) { + $child->setParentPath($this->path()); + } + } + + /** + * adds child to the directory + * + * @param vfsStreamContent $child + */ + public function addChild(vfsStreamContent $child) + { + $child->setParentPath($this->path()); + $this->children[$child->getName()] = $child; + $this->updateModifications(); + } + + /** + * removes child from the directory + * + * @param string $name + * @return bool + */ + public function removeChild($name) + { + foreach ($this->children as $key => $child) { + if ($child->appliesTo($name)) { + $child->setParentPath(null); + unset($this->children[$key]); + $this->updateModifications(); + return true; + } + } + + return false; + } + + /** + * updates internal timestamps + */ + protected function updateModifications() + { + $time = time(); + $this->lastAttributeModified = $time; + $this->lastModified = $time; + } + + /** + * checks whether the container contains a child with the given name + * + * @param string $name + * @return bool + */ + public function hasChild($name) + { + return ($this->getChild($name) !== null); + } + + /** + * returns the child with the given name + * + * @param string $name + * @return vfsStreamContent + */ + public function getChild($name) + { + $childName = $this->getRealChildName($name); + foreach ($this->children as $child) { + if ($child->getName() === $childName) { + return $child; + } + + if ($child->appliesTo($childName) === true && $child->hasChild($childName) === true) { + return $child->getChild($childName); + } + } + + return null; + } + + /** + * helper method to detect the real child name + * + * @param string $name + * @return string + */ + protected function getRealChildName($name) + { + if ($this->appliesTo($name) === true) { + return self::getChildName($name, $this->name); + } + + return $name; + } + + /** + * helper method to calculate the child name + * + * @param string $name + * @param string $ownName + * @return string + */ + protected static function getChildName($name, $ownName) + { + if ($name === $ownName) { + return $name; + } + + return substr($name, strlen($ownName) + 1); + } + + /** + * checks whether directory contains any children + * + * @return bool + * @since 0.10.0 + */ + public function hasChildren() + { + return (count($this->children) > 0); + } + + /** + * returns a list of children for this directory + * + * @return vfsStreamContent[] + */ + public function getChildren() + { + return array_values($this->children); + } + + /** + * returns iterator for the children + * + * @return vfsStreamContainerIterator + */ + #[\ReturnTypeWillChange] + public function getIterator() + { + return new vfsStreamContainerIterator($this->children); + } + + /** + * checks whether dir is a dot dir + * + * @return bool + */ + public function isDot() + { + if ('.' === $this->name || '..' === $this->name) { + return true; + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamException.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamException.php new file mode 100644 index 000000000..b78afd182 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamException.php @@ -0,0 +1,19 @@ +content = new StringBasedFileContent(''); + $this->type = vfsStreamContent::TYPE_FILE; + parent::__construct($name, $permissions); + } + + /** + * returns default permissions for concrete implementation + * + * @return int + * @since 0.8.0 + */ + protected function getDefaultPermissions() + { + return 0666; + } + + /** + * checks whether the container can be applied to given name + * + * @param string $name + * @return bool + */ + public function appliesTo($name) + { + return ($name === $this->name); + } + + /** + * alias for withContent() + * + * @param string $content + * @return vfsStreamFile + * @see withContent() + */ + public function setContent($content) + { + return $this->withContent($content); + } + + /** + * sets the contents of the file + * + * Setting content with this method does not change the time when the file + * was last modified. + * + * @param string]FileContent $content + * @return vfsStreamFile + * @throws \InvalidArgumentException + */ + public function withContent($content) + { + if (is_string($content)) { + $this->content = new StringBasedFileContent($content); + } elseif ($content instanceof FileContent) { + $this->content = $content; + } else { + throw new \InvalidArgumentException('Given content must either be a string or an instance of org\bovigo\vfs\content\FileContent'); + } + + return $this; + } + + /** + * returns the contents of the file + * + * Getting content does not change the time when the file + * was last accessed. + * + * @return string + */ + public function getContent() + { + return $this->content->content(); + } + + /** + * simply open the file + * + * @since 0.9 + */ + public function open() + { + $this->content->seek(0, SEEK_SET); + $this->lastAccessed = time(); + } + + /** + * open file and set pointer to end of file + * + * @since 0.9 + */ + public function openForAppend() + { + $this->content->seek(0, SEEK_END); + $this->lastAccessed = time(); + } + + /** + * open file and truncate content + * + * @since 0.9 + */ + public function openWithTruncate() + { + $this->open(); + $this->content->truncate(0); + $time = time(); + $this->lastAccessed = $time; + $this->lastModified = $time; + } + + /** + * reads the given amount of bytes from content + * + * Using this method changes the time when the file was last accessed. + * + * @param int $count + * @return string + */ + public function read($count) + { + $this->lastAccessed = time(); + return $this->content->read($count); + } + + /** + * returns the content until its end from current offset + * + * Using this method changes the time when the file was last accessed. + * + * @return string + * @deprecated since 1.3.0 + */ + public function readUntilEnd() + { + $this->lastAccessed = time(); + return $this->content->readUntilEnd(); + } + + /** + * writes an amount of data + * + * Using this method changes the time when the file was last modified. + * + * @param string $data + * @return int amount of written bytes + */ + public function write($data) + { + $this->lastModified = time(); + return $this->content->write($data); + } + + /** + * Truncates a file to a given length + * + * @param int $size length to truncate file to + * @return bool + * @since 1.1.0 + */ + public function truncate($size) + { + $this->content->truncate($size); + $this->lastModified = time(); + return true; + } + + /** + * checks whether pointer is at end of file + * + * @return bool + */ + public function eof() + { + return $this->content->eof(); + } + + /** + * returns the current position within the file + * + * @return int + * @deprecated since 1.3.0 + */ + public function getBytesRead() + { + return $this->content->bytesRead(); + } + + /** + * seeks to the given offset + * + * @param int $offset + * @param int $whence + * @return bool + */ + public function seek($offset, $whence) + { + return $this->content->seek($offset, $whence); + } + + /** + * returns size of content + * + * @return int + */ + public function size() + { + return $this->content->size(); + } + + + /** + * locks file for + * + * @param resource|vfsStreamWrapper $resource + * @param int $operation + * @return bool + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/6 + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function lock($resource, $operation) + { + if ((LOCK_NB & $operation) == LOCK_NB) { + $operation = $operation - LOCK_NB; + } + + // call to lock file on the same file handler firstly releases the lock + $this->unlock($resource); + + if (LOCK_EX === $operation) { + if ($this->isLocked()) { + return false; + } + + $this->setExclusiveLock($resource); + } elseif(LOCK_SH === $operation) { + if ($this->hasExclusiveLock()) { + return false; + } + + $this->addSharedLock($resource); + } + + return true; + } + + /** + * Removes lock from file acquired by given resource + * + * @param resource|vfsStreamWrapper $resource + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function unlock($resource) { + if ($this->hasExclusiveLock($resource)) { + $this->exclusiveLock = null; + } + if ($this->hasSharedLock($resource)) { + unset($this->sharedLock[$this->getResourceId($resource)]); + } + } + + /** + * Set exlusive lock on file by given resource + * + * @param resource|vfsStreamWrapper $resource + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + protected function setExclusiveLock($resource) { + $this->exclusiveLock = $this->getResourceId($resource); + } + + /** + * Add shared lock on file by given resource + * + * @param resource|vfsStreamWrapper $resource + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + protected function addSharedLock($resource) { + $this->sharedLock[$this->getResourceId($resource)] = true; + } + + /** + * checks whether file is locked + * + * @param resource|vfsStreamWrapper $resource + * @return bool + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/6 + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function isLocked($resource = null) + { + return $this->hasSharedLock($resource) || $this->hasExclusiveLock($resource); + } + + /** + * checks whether file is locked in shared mode + * + * @param resource|vfsStreamWrapper $resource + * @return bool + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/6 + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function hasSharedLock($resource = null) + { + if (null !== $resource) { + return isset($this->sharedLock[$this->getResourceId($resource)]); + } + + return !empty($this->sharedLock); + } + + /** + * Returns unique resource id + * + * @param resource|vfsStreamWrapper $resource + * @return string + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function getResourceId($resource) { + if (is_resource($resource)) { + $data = stream_get_meta_data($resource); + $resource = $data['wrapper_data']; + } + + return spl_object_hash($resource); + } + + /** + * checks whether file is locked in exclusive mode + * + * @param resource|vfsStreamWrapper $resource + * @return bool + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/6 + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function hasExclusiveLock($resource = null) + { + if (null !== $resource) { + return $this->exclusiveLock === $this->getResourceId($resource); + } + + return null !== $this->exclusiveLock; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.php new file mode 100644 index 000000000..a31e6d22b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.php @@ -0,0 +1,1018 @@ +getName() === $path) { + return self::$root; + } + + if ($this->isInRoot($path) && self::$root->hasChild($path) === true) { + return self::$root->getChild($path); + } + + return null; + } + + /** + * helper method to detect whether given path is in root path + * + * @param string $path + * @return bool + */ + private function isInRoot($path) + { + return substr($path, 0, strlen(self::$root->getName())) === self::$root->getName(); + } + + /** + * returns content for given path but only when it is of given type + * + * @param string $path + * @param int $type + * @return vfsStreamContent + */ + protected function getContentOfType($path, $type) + { + $content = $this->getContent($path); + if (null !== $content && $content->getType() === $type) { + return $content; + } + + return null; + } + + /** + * splits path into its dirname and the basename + * + * @param string $path + * @return string[] + */ + protected function splitPath($path) + { + $lastSlashPos = strrpos($path, '/'); + if (false === $lastSlashPos) { + return array('dirname' => '', 'basename' => $path); + } + + return array('dirname' => substr($path, 0, $lastSlashPos), + 'basename' => substr($path, $lastSlashPos + 1) + ); + } + + /** + * helper method to resolve a path from /foo/bar/. to /foo/bar + * + * @param string $path + * @return string + */ + protected function resolvePath($path) + { + $newPath = array(); + foreach (explode('/', $path) as $pathPart) { + if ('.' !== $pathPart) { + if ('..' !== $pathPart) { + $newPath[] = $pathPart; + } elseif (count($newPath) > 1) { + array_pop($newPath); + } + } + } + + return implode('/', $newPath); + } + + /** + * open the stream + * + * @param string $path the path to open + * @param string $mode mode for opening + * @param string $options options for opening + * @param string $opened_path full path that was actually opened + * @return bool + */ + public function stream_open($path, $mode, $options, $opened_path) + { + $extended = ((strstr($mode, '+') !== false) ? (true) : (false)); + $mode = str_replace(array('t', 'b', '+'), '', $mode); + if (in_array($mode, array('r', 'w', 'a', 'x', 'c')) === false) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('Illegal mode ' . $mode . ', use r, w, a, x or c, flavoured with t, b and/or +', E_USER_WARNING); + } + + return false; + } + + $this->mode = $this->calculateMode($mode, $extended); + $path = $this->resolvePath(vfsStream::path($path)); + $this->content = $this->getContentOfType($path, vfsStreamContent::TYPE_FILE); + if (null !== $this->content) { + if (self::WRITE === $mode) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('File ' . $path . ' already exists, can not open with mode x', E_USER_WARNING); + } + + return false; + } + + if ( + (self::TRUNCATE === $mode || self::APPEND === $mode) && + $this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false + ) { + return false; + } + + if (self::TRUNCATE === $mode) { + $this->content->openWithTruncate(); + } elseif (self::APPEND === $mode) { + $this->content->openForAppend(); + } else { + if (!$this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('Permission denied', E_USER_WARNING); + } + return false; + } + $this->content->open(); + } + + return true; + } + + $content = $this->createFile($path, $mode, $options); + if (false === $content) { + return false; + } + + $this->content = $content; + return true; + } + + /** + * creates a file at given path + * + * @param string $path the path to open + * @param string $mode mode for opening + * @param string $options options for opening + * @return bool + */ + private function createFile($path, $mode = null, $options = null) + { + $names = $this->splitPath($path); + if (empty($names['dirname']) === true) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('File ' . $names['basename'] . ' does not exist', E_USER_WARNING); + } + + return false; + } + + $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR); + if (null === $dir) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('Directory ' . $names['dirname'] . ' does not exist', E_USER_WARNING); + } + + return false; + } elseif ($dir->hasChild($names['basename']) === true) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('Directory ' . $names['dirname'] . ' already contains a director named ' . $names['basename'], E_USER_WARNING); + } + + return false; + } + + if (self::READ === $mode) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('Can not open non-existing file ' . $path . ' for reading', E_USER_WARNING); + } + + return false; + } + + if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) { + trigger_error('Can not create new file in non-writable path ' . $names['dirname'], E_USER_WARNING); + } + + return false; + } + + return vfsStream::newFile($names['basename'])->at($dir); + } + + /** + * calculates the file mode + * + * @param string $mode opening mode: r, w, a or x + * @param bool $extended true if + was set with opening mode + * @return int + */ + protected function calculateMode($mode, $extended) + { + if (true === $extended) { + return self::ALL; + } + + if (self::READ === $mode) { + return self::READONLY; + } + + return self::WRITEONLY; + } + + /** + * closes the stream + * + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function stream_close() + { + $this->content->lock($this, LOCK_UN); + } + + /** + * read the stream up to $count bytes + * + * @param int $count amount of bytes to read + * @return string + */ + public function stream_read($count) + { + if (self::WRITEONLY === $this->mode) { + return ''; + } + + if ($this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + return ''; + } + + return $this->content->read($count); + } + + /** + * writes data into the stream + * + * @param string $data + * @return int amount of bytes written + */ + public function stream_write($data) + { + if (self::READONLY === $this->mode) { + return 0; + } + + if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + return 0; + } + + if (self::$quota->isLimited()) { + $data = substr($data, 0, self::$quota->spaceLeft(self::$root->sizeSummarized())); + } + + return $this->content->write($data); + } + + /** + * truncates a file to a given length + * + * @param int $size length to truncate file to + * @return bool + * @since 1.1.0 + */ + public function stream_truncate($size) + { + if (self::READONLY === $this->mode) { + return false; + } + + if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + return false; + } + + if ($this->content->getType() !== vfsStreamContent::TYPE_FILE) { + return false; + } + + if (self::$quota->isLimited() && $this->content->size() < $size) { + $maxSize = self::$quota->spaceLeft(self::$root->sizeSummarized()); + if (0 === $maxSize) { + return false; + } + + if ($size > $maxSize) { + $size = $maxSize; + } + } + + return $this->content->truncate($size); + } + + /** + * sets metadata like owner, user or permissions + * + * @param string $path + * @param int $option + * @param mixed $var + * @return bool + * @since 1.1.0 + */ + public function stream_metadata($path, $option, $var) + { + $path = $this->resolvePath(vfsStream::path($path)); + $content = $this->getContent($path); + switch ($option) { + case STREAM_META_TOUCH: + if (null === $content) { + $content = $this->createFile($path, null, STREAM_REPORT_ERRORS); + // file creation may not be allowed at provided path + if (false === $content) { + return false; + } + } + + $currentTime = time(); + $content->lastModified(((isset($var[0])) ? ($var[0]) : ($currentTime))) + ->lastAccessed(((isset($var[1])) ? ($var[1]) : ($currentTime))); + return true; + + case STREAM_META_OWNER_NAME: + return false; + + case STREAM_META_OWNER: + if (null === $content) { + return false; + } + + return $this->doPermChange($path, + $content, + function() use ($content, $var) + { + $content->chown($var); + } + ); + + case STREAM_META_GROUP_NAME: + return false; + + case STREAM_META_GROUP: + if (null === $content) { + return false; + } + + return $this->doPermChange($path, + $content, + function() use ($content, $var) + { + $content->chgrp($var); + } + ); + + case STREAM_META_ACCESS: + if (null === $content) { + return false; + } + + return $this->doPermChange($path, + $content, + function() use ($content, $var) + { + $content->chmod($var); + } + ); + + default: + return false; + } + } + + /** + * executes given permission change when necessary rights allow such a change + * + * @param string $path + * @param vfsStreamAbstractContent $content + * @param \Closure $change + * @return bool + */ + private function doPermChange($path, vfsStreamAbstractContent $content, \Closure $change) + { + if (!$content->isOwnedByUser(vfsStream::getCurrentUser())) { + return false; + } + + if (self::$root->getName() !== $path) { + $names = $this->splitPath($path); + $parent = $this->getContent($names['dirname']); + if (!$parent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { + return false; + } + } + + $change(); + return true; + } + + /** + * checks whether stream is at end of file + * + * @return bool + */ + public function stream_eof() + { + return $this->content->eof(); + } + + /** + * returns the current position of the stream + * + * @return int + */ + public function stream_tell() + { + return $this->content->getBytesRead(); + } + + /** + * seeks to the given offset + * + * @param int $offset + * @param int $whence + * @return bool + */ + public function stream_seek($offset, $whence) + { + return $this->content->seek($offset, $whence); + } + + /** + * flushes unstored data into storage + * + * @return bool + */ + public function stream_flush() + { + return true; + } + + /** + * returns status of stream + * + * @return array + */ + public function stream_stat() + { + $fileStat = array('dev' => 0, + 'ino' => 0, + 'mode' => $this->content->getType() | $this->content->getPermissions(), + 'nlink' => 0, + 'uid' => $this->content->getUser(), + 'gid' => $this->content->getGroup(), + 'rdev' => 0, + 'size' => $this->content->size(), + 'atime' => $this->content->fileatime(), + 'mtime' => $this->content->filemtime(), + 'ctime' => $this->content->filectime(), + 'blksize' => -1, + 'blocks' => -1 + ); + return array_merge(array_values($fileStat), $fileStat); + } + + /** + * retrieve the underlaying resource + * + * Please note that this method always returns false as there is no + * underlaying resource to return. + * + * @param int $cast_as + * @since 0.9.0 + * @see https://github.com/mikey179/vfsStream/issues/3 + * @return bool + */ + public function stream_cast($cast_as) + { + return false; + } + + /** + * set lock status for stream + * + * @param int $operation + * @return bool + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/6 + * @see https://github.com/mikey179/vfsStream/issues/31 + * @see https://github.com/mikey179/vfsStream/issues/40 + */ + public function stream_lock($operation) + { + if ((LOCK_NB & $operation) == LOCK_NB) { + $operation = $operation - LOCK_NB; + } + + return $this->content->lock($this, $operation); + } + + /** + * sets options on the stream + * + * @param int $option key of option to set + * @param int $arg1 + * @param int $arg2 + * @return bool + * @since 0.10.0 + * @see https://github.com/mikey179/vfsStream/issues/15 + * @see http://www.php.net/manual/streamwrapper.stream-set-option.php + */ + public function stream_set_option($option, $arg1, $arg2) + { + switch ($option) { + case STREAM_OPTION_BLOCKING: + // break omitted + + case STREAM_OPTION_READ_TIMEOUT: + // break omitted + + case STREAM_OPTION_WRITE_BUFFER: + // break omitted + + default: + // nothing to do here + } + + return false; + } + + /** + * remove the data under the given path + * + * @param string $path + * @return bool + */ + public function unlink($path) + { + $realPath = $this->resolvePath(vfsStream::path($path)); + $content = $this->getContent($realPath); + if (null === $content) { + trigger_error('unlink(' . $path . '): No such file or directory', E_USER_WARNING); + return false; + } + + if ($content->getType() !== vfsStreamContent::TYPE_FILE) { + trigger_error('unlink(' . $path . '): Operation not permitted', E_USER_WARNING); + return false; + } + + return $this->doUnlink($realPath); + } + + /** + * removes a path + * + * @param string $path + * @return bool + */ + protected function doUnlink($path) + { + if (self::$root->getName() === $path) { + // delete root? very brave. :) + self::$root = null; + clearstatcache(); + return true; + } + + $names = $this->splitPath($path); + $content = $this->getContent($names['dirname']); + if (!$content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { + return false; + } + + clearstatcache(); + return $content->removeChild($names['basename']); + } + + /** + * rename from one path to another + * + * @param string $path_from + * @param string $path_to + * @return bool + * @author Benoit Aubuchon + */ + public function rename($path_from, $path_to) + { + $srcRealPath = $this->resolvePath(vfsStream::path($path_from)); + $dstRealPath = $this->resolvePath(vfsStream::path($path_to)); + $srcContent = $this->getContent($srcRealPath); + if (null == $srcContent) { + trigger_error(' No such file or directory', E_USER_WARNING); + return false; + } + $dstNames = $this->splitPath($dstRealPath); + $dstParentContent = $this->getContent($dstNames['dirname']); + if (null == $dstParentContent) { + trigger_error('No such file or directory', E_USER_WARNING); + return false; + } + if (!$dstParentContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) { + trigger_error('Permission denied', E_USER_WARNING); + return false; + } + if ($dstParentContent->getType() !== vfsStreamContent::TYPE_DIR) { + trigger_error('Target is not a directory', E_USER_WARNING); + return false; + } + + // remove old source first, so we can rename later + // (renaming first would lead to not being able to remove the old path) + if (!$this->doUnlink($srcRealPath)) { + return false; + } + + $dstContent = $srcContent; + // Renaming the filename + $dstContent->rename($dstNames['basename']); + // Copying to the destination + $dstParentContent->addChild($dstContent); + return true; + } + + /** + * creates a new directory + * + * @param string $path + * @param int $mode + * @param int $options + * @return bool + */ + public function mkdir($path, $mode, $options) + { + $umask = vfsStream::umask(); + if (0 < $umask) { + $permissions = $mode & ~$umask; + } else { + $permissions = $mode; + } + + $path = $this->resolvePath(vfsStream::path($path)); + if (null !== $this->getContent($path)) { + trigger_error('mkdir(): Path vfs://' . $path . ' exists', E_USER_WARNING); + return false; + } + + if (null === self::$root) { + self::$root = vfsStream::newDirectory($path, $permissions); + return true; + } + + $maxDepth = count(explode('/', $path)); + $names = $this->splitPath($path); + $newDirs = $names['basename']; + $dir = null; + $i = 0; + while ($dir === null && $i < $maxDepth) { + $dir = $this->getContent($names['dirname']); + $names = $this->splitPath($names['dirname']); + if (null == $dir) { + $newDirs = $names['basename'] . '/' . $newDirs; + } + + $i++; + } + + if (null === $dir + || $dir->getType() !== vfsStreamContent::TYPE_DIR + || $dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + return false; + } + + $recursive = ((STREAM_MKDIR_RECURSIVE & $options) !== 0) ? (true) : (false); + if (strpos($newDirs, '/') !== false && false === $recursive) { + return false; + } + + vfsStream::newDirectory($newDirs, $permissions)->at($dir); + return true; + } + + /** + * removes a directory + * + * @param string $path + * @param int $options + * @return bool + * @todo consider $options with STREAM_MKDIR_RECURSIVE + */ + public function rmdir($path, $options) + { + $path = $this->resolvePath(vfsStream::path($path)); + $child = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR); + if (null === $child) { + return false; + } + + // can only remove empty directories + if (count($child->getChildren()) > 0) { + return false; + } + + if (self::$root->getName() === $path) { + // delete root? very brave. :) + self::$root = null; + clearstatcache(); + return true; + } + + $names = $this->splitPath($path); + $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR); + if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + return false; + } + + clearstatcache(); + return $dir->removeChild($child->getName()); + } + + /** + * opens a directory + * + * @param string $path + * @param int $options + * @return bool + */ + public function dir_opendir($path, $options) + { + $path = $this->resolvePath(vfsStream::path($path)); + $this->dir = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR); + if (null === $this->dir || $this->dir->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) { + return false; + } + + $this->dirIterator = $this->dir->getIterator(); + return true; + } + + /** + * reads directory contents + * + * @return string + */ + public function dir_readdir() + { + $dir = $this->dirIterator->current(); + if (null === $dir) { + return false; + } + + $this->dirIterator->next(); + return $dir->getName(); + } + + /** + * reset directory iteration + * + * @return bool + */ + public function dir_rewinddir() + { + return $this->dirIterator->rewind(); + } + + /** + * closes directory + * + * @return bool + */ + public function dir_closedir() + { + $this->dirIterator = null; + return true; + } + + /** + * returns status of url + * + * @param string $path path of url to return status for + * @param int $flags flags set by the stream API + * @return array + */ + public function url_stat($path, $flags) + { + $content = $this->getContent($this->resolvePath(vfsStream::path($path))); + if (null === $content) { + if (($flags & STREAM_URL_STAT_QUIET) != STREAM_URL_STAT_QUIET) { + trigger_error(' No such file or directory: ' . $path, E_USER_WARNING); + } + + return false; + + } + + $fileStat = array('dev' => 0, + 'ino' => 0, + 'mode' => $content->getType() | $content->getPermissions(), + 'nlink' => 0, + 'uid' => $content->getUser(), + 'gid' => $content->getGroup(), + 'rdev' => 0, + 'size' => $content->size(), + 'atime' => $content->fileatime(), + 'mtime' => $content->filemtime(), + 'ctime' => $content->filectime(), + 'blksize' => -1, + 'blocks' => -1 + ); + return array_merge(array_values($fileStat), $fileStat); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.php new file mode 100644 index 000000000..f9e597b91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.php @@ -0,0 +1,64 @@ +getType()) { + case vfsStreamContent::TYPE_BLOCK: + $this->visitBlockDevice($content); + break; + + case vfsStreamContent::TYPE_FILE: + $this->visitFile($content); + break; + + case vfsStreamContent::TYPE_DIR: + if (!$content->isDot()) { + $this->visitDirectory($content); + } + + break; + + default: + throw new \InvalidArgumentException('Unknown content type ' . $content->getType() . ' for ' . $content->getName()); + } + + return $this; + } + + /** + * visit a block device and process it + * + * @param vfsStreamBlock $block + * @return vfsStreamVisitor + */ + public function visitBlockDevice(vfsStreamBlock $block) + { + return $this->visitFile($block); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php new file mode 100644 index 000000000..b039a7dda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php @@ -0,0 +1,108 @@ +out = $out; + $this->depth = 0; + } + + /** + * visit a file and process it + * + * @param vfsStreamFile $file + * @return vfsStreamPrintVisitor + */ + public function visitFile(vfsStreamFile $file) + { + $this->printContent($file->getName()); + return $this; + } + + /** + * visit a block device and process it + * + * @param vfsStreamBlock $block + * @return vfsStreamPrintVisitor + */ + public function visitBlockDevice(vfsStreamBlock $block) + { + $name = '[' . $block->getName() . ']'; + $this->printContent($name); + return $this; + } + + /** + * visit a directory and process it + * + * @param vfsStreamDirectory $dir + * @return vfsStreamPrintVisitor + */ + public function visitDirectory(vfsStreamDirectory $dir) + { + $this->printContent($dir->getName()); + $this->depth++; + foreach ($dir as $child) { + $this->visit($child); + } + + $this->depth--; + return $this; + } + + /** + * helper method to print the content + * + * @param string $name + */ + protected function printContent($name) + { + fwrite($this->out, str_repeat(' ', $this->depth) . '- ' . $name . "\n"); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php new file mode 100644 index 000000000..47acc45cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php @@ -0,0 +1,111 @@ +reset(); + } + + /** + * visit a file and process it + * + * @param vfsStreamFile $file + * @return vfsStreamStructureVisitor + */ + public function visitFile(vfsStreamFile $file) + { + $this->current[$file->getName()] = $file->getContent(); + return $this; + } + + /** + * visit a block device and process it + * + * @param vfsStreamBlock $block + * @return vfsStreamStructureVisitor + */ + public function visitBlockDevice(vfsStreamBlock $block) + { + $this->current['[' . $block->getName() . ']'] = $block->getContent(); + return $this; + } + + /** + * visit a directory and process it + * + * @param vfsStreamDirectory $dir + * @return vfsStreamStructureVisitor + */ + public function visitDirectory(vfsStreamDirectory $dir) + { + $this->current[$dir->getName()] = array(); + $tmp =& $this->current; + $this->current =& $tmp[$dir->getName()]; + foreach ($dir as $child) { + $this->visit($child); + } + + $this->current =& $tmp; + return $this; + } + + /** + * returns structure of visited contents + * + * @return array + * @api + */ + public function getStructure() + { + return $this->structure; + } + + /** + * resets structure so visitor could be reused + * + * @return vfsStreamStructureVisitor + */ + public function reset() + { + $this->structure = array(); + $this->current =& $this->structure; + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.php new file mode 100644 index 000000000..217010587 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.php @@ -0,0 +1,55 @@ +expectException($exception); + } elseif (method_exists($this, 'setExpectedException')) { + $this->setExpectedException($exception); + } + } + + // A BC hack to get handle the deprecation of this method in PHPUnit + public function bc_getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = null) + { + if (method_exists($this, "getMockBuilder")) { + return $this + ->getMockBuilder($originalClassName) + ->setMethods($methods) + ->getMock() + ; + } + + return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/DirectoryIterationTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/DirectoryIterationTestCase.php new file mode 100644 index 000000000..6fcdf2ad0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/DirectoryIterationTestCase.php @@ -0,0 +1,318 @@ +assertEquals($expectedCount, + $actualCount, + 'Directory foo contains ' . $expectedCount . ' children, but got ' . $actualCount . ' children while iterating over directory contents' + ); + } + + /** + * @param \Closure $dotFilesSwitch + * @param string[] $expectedDirectories + * @test + * @dataProvider provideSwitchWithExpectations + */ + public function directoryIteration(\Closure $dotFilesSwitch, array $expectedDirectories) + { + $dotFilesSwitch(); + $dir = dir($this->fooURL); + $i = 0; + while (false !== ($entry = $dir->read())) { + $i++; + $this->assertTrue(in_array($entry, $expectedDirectories)); + } + + $this->assertDirectoryCount(count($expectedDirectories), $i); + $dir->rewind(); + $i = 0; + while (false !== ($entry = $dir->read())) { + $i++; + $this->assertTrue(in_array($entry, $expectedDirectories)); + } + + $this->assertDirectoryCount(count($expectedDirectories), $i); + $dir->close(); + } + + /** + * @param \Closure $dotFilesSwitch + * @param string[] $expectedDirectories + * @test + * @dataProvider provideSwitchWithExpectations + */ + public function directoryIterationWithDot(\Closure $dotFilesSwitch, array $expectedDirectories) + { + $dotFilesSwitch(); + $dir = dir($this->fooURL . '/.'); + $i = 0; + while (false !== ($entry = $dir->read())) { + $i++; + $this->assertTrue(in_array($entry, $expectedDirectories)); + } + + $this->assertDirectoryCount(count($expectedDirectories), $i); + $dir->rewind(); + $i = 0; + while (false !== ($entry = $dir->read())) { + $i++; + $this->assertTrue(in_array($entry, $expectedDirectories)); + } + + $this->assertDirectoryCount(count($expectedDirectories), $i); + $dir->close(); + } + + /** + * assure that a directory iteration works as expected + * + * @param \Closure $dotFilesSwitch + * @param string[] $expectedDirectories + * @test + * @dataProvider provideSwitchWithExpectations + * @group regression + * @group bug_2 + */ + public function directoryIterationWithOpenDir_Bug_2(\Closure $dotFilesSwitch, array $expectedDirectories) + { + $dotFilesSwitch(); + $handle = opendir($this->fooURL); + $i = 0; + while (false !== ($entry = readdir($handle))) { + $i++; + $this->assertTrue(in_array($entry, $expectedDirectories)); + } + + $this->assertDirectoryCount(count($expectedDirectories), $i); + + rewinddir($handle); + $i = 0; + while (false !== ($entry = readdir($handle))) { + $i++; + $this->assertTrue(in_array($entry, $expectedDirectories)); + } + + $this->assertDirectoryCount(count($expectedDirectories), $i); + closedir($handle); + } + + /** + * assure that a directory iteration works as expected + * + * @author Christoph Bloemer + * @param \Closure $dotFilesSwitch + * @param string[] $expectedDirectories + * @test + * @dataProvider provideSwitchWithExpectations + * @group regression + * @group bug_4 + */ + public function directoryIteration_Bug_4(\Closure $dotFilesSwitch, array $expectedDirectories) + { + $dotFilesSwitch(); + $dir = $this->fooURL; + $list1 = array(); + if ($handle = opendir($dir)) { + while (false !== ($listItem = readdir($handle))) { + if ('.' != $listItem && '..' != $listItem) { + if (is_file($dir . '/' . $listItem) === true) { + $list1[] = 'File:[' . $listItem . ']'; + } elseif (is_dir($dir . '/' . $listItem) === true) { + $list1[] = 'Folder:[' . $listItem . ']'; + } + } + } + + closedir($handle); + } + + $list2 = array(); + if ($handle = opendir($dir)) { + while (false !== ($listItem = readdir($handle))) { + if ('.' != $listItem && '..' != $listItem) { + if (is_file($dir . '/' . $listItem) === true) { + $list2[] = 'File:[' . $listItem . ']'; + } elseif (is_dir($dir . '/' . $listItem) === true) { + $list2[] = 'Folder:[' . $listItem . ']'; + } + } + } + + closedir($handle); + } + + $this->assertEquals($list1, $list2); + $this->assertEquals(2, count($list1)); + $this->assertEquals(2, count($list2)); + } + + /** + * assure that a directory iteration works as expected + * + * @param \Closure $dotFilesSwitch + * @param string[] $expectedDirectories + * @test + * @dataProvider provideSwitchWithExpectations + */ + public function directoryIterationShouldBeIndependent(\Closure $dotFilesSwitch, array $expectedDirectories) + { + $dotFilesSwitch(); + $list1 = array(); + $list2 = array(); + $handle1 = opendir($this->fooURL); + if (false !== ($listItem = readdir($handle1))) { + $list1[] = $listItem; + } + + $handle2 = opendir($this->fooURL); + if (false !== ($listItem = readdir($handle2))) { + $list2[] = $listItem; + } + + if (false !== ($listItem = readdir($handle1))) { + $list1[] = $listItem; + } + + if (false !== ($listItem = readdir($handle2))) { + $list2[] = $listItem; + } + + closedir($handle1); + closedir($handle2); + $this->assertEquals($list1, $list2); + $this->assertEquals(2, count($list1)); + $this->assertEquals(2, count($list2)); + } + + /** + * @test + * @group issue_50 + */ + public function recursiveDirectoryIterationWithDotsEnabled() + { + vfsStream::enableDotfiles(); + vfsStream::setup(); + $structure = array( + 'Core' => array( + 'AbstractFactory' => array( + 'test.php' => 'some text content', + 'other.php' => 'Some more text content', + 'Invalid.csv' => 'Something else', + ), + 'AnEmptyFolder' => array(), + 'badlocation.php' => 'some bad content', + ) + ); + $root = vfsStream::create($structure); + $rootPath = vfsStream::url($root->getName()); + + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($rootPath), + \RecursiveIteratorIterator::CHILD_FIRST); + $pathes = array(); + foreach ($iterator as $fullFileName => $fileSPLObject) { + $pathes[] = $fullFileName; + } + + $this->assertEquals(array('vfs://root'.DIRECTORY_SEPARATOR.'.', + 'vfs://root'.DIRECTORY_SEPARATOR.'..', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'.', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'..', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'.', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'..', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'test.php', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'other.php', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'Invalid.csv', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder'.DIRECTORY_SEPARATOR.'.', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder'.DIRECTORY_SEPARATOR.'..', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'badlocation.php', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core' + ), + $pathes + ); + } + + /** + * @test + * @group issue_50 + */ + public function recursiveDirectoryIterationWithDotsDisabled() + { + vfsStream::disableDotfiles(); + vfsStream::setup(); + $structure = array( + 'Core' => array( + 'AbstractFactory' => array( + 'test.php' => 'some text content', + 'other.php' => 'Some more text content', + 'Invalid.csv' => 'Something else', + ), + 'AnEmptyFolder' => array(), + 'badlocation.php' => 'some bad content', + ) + ); + $root = vfsStream::create($structure); + $rootPath = vfsStream::url($root->getName()); + + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($rootPath), + \RecursiveIteratorIterator::CHILD_FIRST); + $pathes = array(); + foreach ($iterator as $fullFileName => $fileSPLObject) { + $pathes[] = $fullFileName; + } + + $this->assertEquals(array('vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'test.php', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'other.php', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory'.DIRECTORY_SEPARATOR.'Invalid.csv', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AbstractFactory', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'AnEmptyFolder', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core'.DIRECTORY_SEPARATOR.'badlocation.php', + 'vfs://root'.DIRECTORY_SEPARATOR.'Core' + ), + $pathes + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/FilenameTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/FilenameTestCase.php new file mode 100644 index 000000000..678038f28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/FilenameTestCase.php @@ -0,0 +1,88 @@ +rootDir = vfsStream::url('root'); + $this->lostAndFound = $this->rootDir . '/lost+found/'; + mkdir($this->lostAndFound); + } + + /** + * @test + */ + public function worksWithCorrectName() + { + $results = array(); + $it = new \RecursiveDirectoryIterator($this->lostAndFound); + foreach ($it as $f) { + $results[] = $f->getPathname(); + } + + $this->assertEquals( + array( + 'vfs://root/lost+found' . DIRECTORY_SEPARATOR . '.', + 'vfs://root/lost+found' . DIRECTORY_SEPARATOR . '..' + ), + $results + ); + } + + /** + * @test + */ + public function doesNotWorkWithInvalidName() + { + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionMessage('ailed to open dir'); + $results = array(); + $it = new \RecursiveDirectoryIterator($this->rootDir . '/lost found/'); + foreach ($it as $f) { + $results[] = $f->getPathname(); + } + } + + /** + * @test + */ + public function returnsCorrectNames() + { + $results = array(); + $it = new \RecursiveDirectoryIterator($this->rootDir); + foreach ($it as $f) { + $results[] = $f->getPathname(); + } + + $this->assertEquals( + array( + 'vfs://root' . DIRECTORY_SEPARATOR . '.', + 'vfs://root' . DIRECTORY_SEPARATOR . '..', + 'vfs://root' . DIRECTORY_SEPARATOR . 'lost+found' + ), + $results + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/Issue104TestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/Issue104TestCase.php new file mode 100644 index 000000000..895f601df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/Issue104TestCase.php @@ -0,0 +1,52 @@ + array( + 'schema.xsd' => ' + + ', + ) + ); + vfsStream::setup('root', null, $structure); + $doc = new \DOMDocument(); + $this->assertTrue($doc->load(vfsStream::url('root/foo bar/schema.xsd'))); + } + + /** + * @test + */ + public function vfsStreamCanHandleUrlEncodedPath() + { + $content = ' + + '; + $structure = array('foo bar' => array( + 'schema.xsd' => $content, + ) + ); + vfsStream::setup('root', null, $structure); + $this->assertEquals( + $content, + file_get_contents(vfsStream::url('root/foo bar/schema.xsd')) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/PermissionsTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/PermissionsTestCase.php new file mode 100644 index 000000000..185be7ffb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/PermissionsTestCase.php @@ -0,0 +1,121 @@ + array('test.file' => '')); + $this->root = vfsStream::setup('root', null, $structure); + } + + /** + * @test + * @group issue_52 + */ + public function canNotChangePermissionWhenDirectoryNotWriteable() + { + $this->root->getChild('test_directory')->chmod(0444); + $this->assertFalse(@chmod(vfsStream::url('root/test_directory/test.file'), 0777)); + } + + /** + * @test + * @group issue_53 + */ + public function canNotChangePermissionWhenFileNotOwned() + { + $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1); + $this->assertFalse(@chmod(vfsStream::url('root/test_directory/test.file'), 0777)); + } + + /** + * @test + * @group issue_52 + */ + public function canNotChangeOwnerWhenDirectoryNotWriteable() + { + $this->root->getChild('test_directory')->chmod(0444); + $this->assertFalse(@chown(vfsStream::url('root/test_directory/test.file'), vfsStream::OWNER_USER_2)); + } + + /** + * @test + * @group issue_53 + */ + public function canNotChangeOwnerWhenFileNotOwned() + { + $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1); + $this->assertFalse(@chown(vfsStream::url('root/test_directory/test.file'), vfsStream::OWNER_USER_2)); + } + + /** + * @test + * @group issue_52 + */ + public function canNotChangeGroupWhenDirectoryNotWriteable() + { + $this->root->getChild('test_directory')->chmod(0444); + $this->assertFalse(@chgrp(vfsStream::url('root/test_directory/test.file'), vfsStream::GROUP_USER_2)); + } + + /** + * @test + * @group issue_53 + */ + public function canNotChangeGroupWhenFileNotOwned() + { + $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1); + $this->assertFalse(@chgrp(vfsStream::url('root/test_directory/test.file'), vfsStream::GROUP_USER_2)); + } + + /** + * @test + * @group issue_107 + * @requires PHP 5.4 + * @since 1.5.0 + */ + public function touchOnNonWriteableDirectoryTriggersError() + { + $this->expectException(Error\Warning::class); + $this->expectExceptionMessage('Can not create new file in non-writable path root'); + + $this->root->chmod(0555); + touch($this->root->url() . '/touch.txt'); + } + + /** + * @test + * @group issue_107 + * @requires PHP 5.4 + * @since 1.5.0 + */ + public function touchOnNonWriteableDirectoryDoesNotCreateFile() + { + $this->root->chmod(0555); + $this->assertFalse(@touch($this->root->url() . '/touch.txt')); + $this->assertFalse($this->root->hasChild('touch.txt')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/QuotaTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/QuotaTestCase.php new file mode 100644 index 000000000..b56afd9d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/QuotaTestCase.php @@ -0,0 +1,80 @@ +quota = new Quota(10); + } + + /** + * @test + */ + public function unlimitedQuotaIsNotLimited() + { + $this->assertFalse(Quota::unlimited()->isLimited()); + } + + /** + * @test + */ + public function limitedQuotaIsLimited() + { + $this->assertTrue($this->quota->isLimited()); + } + + /** + * @test + */ + public function unlimitedQuotaHasAlwaysSpaceLeft() + { + $this->assertEquals(303, Quota::unlimited()->spaceLeft(303)); + } + + /** + * @test + */ + public function hasNoSpaceLeftWhenUsedSpaceIsLargerThanQuota() + { + $this->assertEquals(0, $this->quota->spaceLeft(11)); + } + + /** + * @test + */ + public function hasNoSpaceLeftWhenUsedSpaceIsEqualToQuota() + { + $this->assertEquals(0, $this->quota->spaceLeft(10)); + } + + /** + * @test + */ + public function hasSpaceLeftWhenUsedSpaceIsLowerThanQuota() + { + $this->assertEquals(1, $this->quota->spaceLeft(9)); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/UnlinkTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/UnlinkTestCase.php new file mode 100644 index 000000000..c33a4c2ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/UnlinkTestCase.php @@ -0,0 +1,58 @@ + array('test.file' => '')); + $root = vfsStream::setup('root', null, $structure); + $root->getChild('test_directory')->chmod(0777); + $root->getChild('test_directory')->getChild('test.file')->chmod(0444); + $this->assertTrue(@unlink(vfsStream::url('root/test_directory/test.file'))); + } + + /** + * @test + * @group issue_51 + */ + public function canNotRemoveWritableFileFromNonWritableDirectory() + { + $structure = array('test_directory' => array('test.file' => '')); + $root = vfsStream::setup('root', null, $structure); + $root->getChild('test_directory')->chmod(0444); + $root->getChild('test_directory')->getChild('test.file')->chmod(0777); + $this->assertFalse(@unlink(vfsStream::url('root/test_directory/test.file'))); + } + + /** + * @test + * @since 1.4.0 + * @group issue_68 + */ + public function unlinkNonExistingFileTriggersError() + { + vfsStream::setup(); + try { + $this->assertFalse(unlink('vfs://root/foo.txt')); + } catch (\PHPUnit_Framework_Error $fe) { + $this->assertEquals('unlink(vfs://root/foo.txt): No such file or directory', $fe->getMessage()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/LargeFileContentTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/LargeFileContentTestCase.php new file mode 100644 index 000000000..203f598b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/LargeFileContentTestCase.php @@ -0,0 +1,225 @@ +largeFileContent = new LargeFileContent(100); + } + + /** + * @test + */ + public function hasSizeOriginallyGiven() + { + $this->assertEquals(100, $this->largeFileContent->size()); + } + + /** + * @test + */ + public function contentIsFilledUpWithSpacesIfNoDataWritten() + { + $this->assertEquals( + str_repeat(' ', 100), + $this->largeFileContent->content() + ); + } + + /** + * @test + */ + public function readReturnsSpacesWhenNothingWrittenAtOffset() + { + $this->assertEquals( + str_repeat(' ', 10), + $this->largeFileContent->read(10) + ); + } + + /** + * @test + */ + public function readReturnsContentFilledWithSpaces() + { + $this->largeFileContent->write('foobarbaz'); + $this->largeFileContent->seek(0, SEEK_SET); + $this->assertEquals( + 'foobarbaz ', + $this->largeFileContent->read(10) + ); + } + + /** + * @test + */ + public function writesDataAtStartWhenOffsetNotMoved() + { + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals( + 'foobarbaz' . str_repeat(' ', 91), + $this->largeFileContent->content() + ); + } + + /** + * @test + */ + public function writeDataAtStartDoesNotIncreaseSize() + { + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals(100, $this->largeFileContent->size()); + } + + /** + * @test + */ + public function writesDataAtOffsetWhenOffsetMoved() + { + $this->largeFileContent->seek(50, SEEK_SET); + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals( + str_repeat(' ', 50) . 'foobarbaz' . str_repeat(' ', 41), + $this->largeFileContent->content() + ); + } + + /** + * @test + */ + public function writeDataInBetweenDoesNotIncreaseSize() + { + $this->largeFileContent->seek(50, SEEK_SET); + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals(100, $this->largeFileContent->size()); + } + + /** + * @test + */ + public function writesDataOverEndWhenOffsetAndDataLengthLargerThanSize() + { + $this->largeFileContent->seek(95, SEEK_SET); + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals( + str_repeat(' ', 95) . 'foobarbaz', + $this->largeFileContent->content() + ); + } + + /** + * @test + */ + public function writeDataOverLastOffsetIncreasesSize() + { + $this->largeFileContent->seek(95, SEEK_SET); + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals(104, $this->largeFileContent->size()); + } + + /** + * @test + */ + public function writesDataAfterEndWhenOffsetAfterEnd() + { + $this->largeFileContent->seek(0, SEEK_END); + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals( + str_repeat(' ', 100) . 'foobarbaz', + $this->largeFileContent->content() + ); + } + + /** + * @test + */ + public function writeDataAfterLastOffsetIncreasesSize() + { + $this->largeFileContent->seek(0, SEEK_END); + $this->assertEquals(9, $this->largeFileContent->write('foobarbaz')); + $this->assertEquals(109, $this->largeFileContent->size()); + } + + /** + * @test + */ + public function truncateReducesSize() + { + $this->assertTrue($this->largeFileContent->truncate(50)); + $this->assertEquals(50, $this->largeFileContent->size()); + } + + /** + * @test + */ + public function truncateRemovesWrittenContentAfterOffset() + { + $this->largeFileContent->seek(45, SEEK_SET); + $this->largeFileContent->write('foobarbaz'); + $this->assertTrue($this->largeFileContent->truncate(50)); + $this->assertEquals( + str_repeat(' ', 45) . 'fooba', + $this->largeFileContent->content() + ); + } + + /** + * @test + */ + public function createInstanceWithKilobytes() + { + $this->assertEquals( + 100 * 1024, + LargeFileContent::withKilobytes(100) + ->size() + ); + } + + /** + * @test + */ + public function createInstanceWithMegabytes() + { + $this->assertEquals( + 100 * 1024 * 1024, + LargeFileContent::withMegabytes(100) + ->size() + ); + } + + /** + * @test + */ + public function createInstanceWithGigabytes() + { + $this->assertEquals( + 100 * 1024 * 1024 * 1024, + LargeFileContent::withGigabytes(100) + ->size() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/StringBasedFileContentTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/StringBasedFileContentTestCase.php new file mode 100644 index 000000000..75fc3f96b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/content/StringBasedFileContentTestCase.php @@ -0,0 +1,232 @@ +stringBasedFileContent = new StringBasedFileContent('foobarbaz'); + } + + /** + * @test + */ + public function hasContentOriginallySet() + { + $this->assertEquals('foobarbaz', $this->stringBasedFileContent->content()); + } + + /** + * @test + */ + public function hasNotReachedEofAfterCreation() + { + $this->assertFalse($this->stringBasedFileContent->eof()); + } + + /** + * @test + */ + public function sizeEqualsLengthOfGivenString() + { + $this->assertEquals(9, $this->stringBasedFileContent->size()); + } + + /** + * @test + */ + public function readReturnsSubstringWithRequestedLength() + { + $this->assertEquals('foo', $this->stringBasedFileContent->read(3)); + } + + /** + * @test + */ + public function readMovesOffset() + { + $this->assertEquals('foo', $this->stringBasedFileContent->read(3)); + $this->assertEquals('bar', $this->stringBasedFileContent->read(3)); + $this->assertEquals('baz', $this->stringBasedFileContent->read(3)); + } + + /** + * @test + */ + public function reaMoreThanSizeReturnsWholeContent() + { + $this->assertEquals('foobarbaz', $this->stringBasedFileContent->read(10)); + } + + /** + * @test + */ + public function readAfterEndReturnsEmptyString() + { + // Read more than the length of the string to test substr() returning + // false. + $this->stringBasedFileContent->read(10); + $this->assertSame('', $this->stringBasedFileContent->read(3)); + } + + /** + * @test + */ + public function readDoesNotChangeSize() + { + $this->stringBasedFileContent->read(3); + $this->assertEquals(9, $this->stringBasedFileContent->size()); + } + + /** + * @test + */ + public function readLessThenSizeDoesNotReachEof() + { + $this->stringBasedFileContent->read(3); + $this->assertFalse($this->stringBasedFileContent->eof()); + } + + /** + * @test + */ + public function readSizeReachesEof() + { + $this->stringBasedFileContent->read(9); + $this->assertTrue($this->stringBasedFileContent->eof()); + } + + /** + * @test + */ + public function readMoreThanSizeReachesEof() + { + $this->stringBasedFileContent->read(10); + $this->assertTrue($this->stringBasedFileContent->eof()); + } + + /** + * @test + */ + public function seekWithInvalidOptionReturnsFalse() + { + $this->assertFalse($this->stringBasedFileContent->seek(0, 55)); + } + + /** + * @test + */ + public function canSeekToGivenOffset() + { + $this->assertTrue($this->stringBasedFileContent->seek(5, SEEK_SET)); + $this->assertEquals('rbaz', $this->stringBasedFileContent->read(10)); + } + + /** + * @test + */ + public function canSeekFromCurrentOffset() + { + $this->assertTrue($this->stringBasedFileContent->seek(5, SEEK_SET)); + $this->assertTrue($this->stringBasedFileContent->seek(2, SEEK_CUR)); + $this->assertEquals('az', $this->stringBasedFileContent->read(10)); + } + + /** + * @test + */ + public function canSeekToEnd() + { + $this->assertTrue($this->stringBasedFileContent->seek(0, SEEK_END)); + $this->assertEquals('', $this->stringBasedFileContent->read(10)); + } + + /** + * @test + */ + public function writeOverwritesExistingContentWhenOffsetNotAtEof() + { + $this->assertEquals(3, $this->stringBasedFileContent->write('bar')); + $this->assertEquals('barbarbaz', $this->stringBasedFileContent->content()); + } + + /** + * @test + */ + public function writeAppendsContentWhenOffsetAtEof() + { + $this->assertTrue($this->stringBasedFileContent->seek(0, SEEK_END)); + $this->assertEquals(3, $this->stringBasedFileContent->write('bar')); + $this->assertEquals('foobarbazbar', $this->stringBasedFileContent->content()); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + */ + public function truncateRemovesSuperflouosContent() + { + $this->assertTrue($this->stringBasedFileContent->truncate(6)); + $this->assertEquals('foobar', $this->stringBasedFileContent->content()); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + */ + public function truncateDecreasesSize() + { + $this->assertTrue($this->stringBasedFileContent->truncate(6)); + $this->assertEquals(6, $this->stringBasedFileContent->size()); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + */ + public function truncateToGreaterSizeAddsZeroBytes() + { + $this->assertTrue($this->stringBasedFileContent->truncate(25)); + $this->assertEquals( + "foobarbaz\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", + $this->stringBasedFileContent->content() + ); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + */ + public function truncateToGreaterSizeIncreasesSize() + { + $this->assertTrue($this->stringBasedFileContent->truncate(25)); + $this->assertEquals(25, $this->stringBasedFileContent->size()); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/proxy/vfsStreamWrapperRecordingProxy.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/proxy/vfsStreamWrapperRecordingProxy.php new file mode 100644 index 000000000..1ed84b5ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/proxy/vfsStreamWrapperRecordingProxy.php @@ -0,0 +1,325 @@ + + */ + public static function getMethodCalls($path) + { + if (isset(self::$calledMethods[$path]) === true) { + return self::$calledMethods[$path]; + } + + return array(); + } + + /** + * helper method for setting up vfsStream with the proxy + * + * @param string $rootDirName optional name of root directory + * @param int $permissions optional file permissions of root directory + * @return vfsStreamDirectory + * @throws vfsStreamException + */ + public static function setup($rootDirName = 'root', $permissions = null) + { + self::$root = vfsStream::newDirectory($rootDirName, $permissions); + if (true === self::$registered) { + return self::$root; + } + + if (@stream_wrapper_register(vfsStream::SCHEME, __CLASS__) === false) { + throw new vfsStreamException('A handler has already been registered for the ' . vfsStream::SCHEME . ' protocol.'); + } + + self::$registered = true; + return self::$root; + } + + /** + * open the stream + * + * @param string $path the path to open + * @param string $mode mode for opening + * @param string $options options for opening + * @param string $opened_path full path that was actually opened + * @return bool + */ + public function stream_open($path, $mode, $options, $opened_path) + { + $this->path = $path; + self::recordMethodCall('stream_open', $this->path); + return parent::stream_open($path, $mode, $options, $opened_path); + } + + /** + * closes the stream + */ + public function stream_close() + { + self::recordMethodCall('stream_close', $this->path); + return parent::stream_close(); + } + + /** + * read the stream up to $count bytes + * + * @param int $count amount of bytes to read + * @return string + */ + public function stream_read($count) + { + self::recordMethodCall('stream_read', $this->path); + return parent::stream_read($count); + } + + /** + * writes data into the stream + * + * @param string $data + * @return int amount of bytes written + */ + public function stream_write($data) + { + self::recordMethodCall('stream_write', $this->path); + return parent::stream_write($data); + } + + /** + * checks whether stream is at end of file + * + * @return bool + */ + public function stream_eof() + { + self::recordMethodCall('stream_eof', $this->path); + return parent::stream_eof(); + } + + /** + * returns the current position of the stream + * + * @return int + */ + public function stream_tell() + { + self::recordMethodCall('stream_tell', $this->path); + return parent::stream_tell(); + } + + /** + * seeks to the given offset + * + * @param int $offset + * @param int $whence + * @return bool + */ + public function stream_seek($offset, $whence) + { + self::recordMethodCall('stream_seek', $this->path); + return parent::stream_seek($offset, $whence); + } + + /** + * flushes unstored data into storage + * + * @return bool + */ + public function stream_flush() + { + self::recordMethodCall('stream_flush', $this->path); + return parent::stream_flush(); + } + + /** + * returns status of stream + * + * @return array + */ + public function stream_stat() + { + self::recordMethodCall('stream_stat', $this->path); + return parent::stream_stat(); + } + + /** + * retrieve the underlaying resource + * + * @param int $cast_as + * @return bool + */ + public function stream_cast($cast_as) + { + self::recordMethodCall('stream_cast', $this->path); + return parent::stream_cast($cast_as); + } + + /** + * set lock status for stream + * + * @param int $operation + * @return bool + */ + public function stream_lock($operation) + { + self::recordMethodCall('stream_link', $this->path); + return parent::stream_lock($operation); + } + + /** + * remove the data under the given path + * + * @param string $path + * @return bool + */ + public function unlink($path) + { + self::recordMethodCall('unlink', $path); + return parent::unlink($path); + } + + /** + * rename from one path to another + * + * @param string $path_from + * @param string $path_to + * @return bool + */ + public function rename($path_from, $path_to) + { + self::recordMethodCall('rename', $path_from); + return parent::rename($path_from, $path_to); + } + + /** + * creates a new directory + * + * @param string $path + * @param int $mode + * @param int $options + * @return bool + */ + public function mkdir($path, $mode, $options) + { + self::recordMethodCall('mkdir', $path); + return parent::mkdir($path, $mode, $options); + } + + /** + * removes a directory + * + * @param string $path + * @param int $options + * @return bool + */ + public function rmdir($path, $options) + { + self::recordMethodCall('rmdir', $path); + return parent::rmdir($path, $options); + } + + /** + * opens a directory + * + * @param string $path + * @param int $options + * @return bool + */ + public function dir_opendir($path, $options) + { + $this->path = $path; + self::recordMethodCall('dir_opendir', $this->path); + return parent::dir_opendir($path, $options); + } + + /** + * reads directory contents + * + * @return string + */ + public function dir_readdir() + { + self::recordMethodCall('dir_readdir', $this->path); + return parent::dir_readdir(); + } + + /** + * reset directory iteration + * + * @return bool + */ + public function dir_rewinddir() + { + self::recordMethodCall('dir_rewinddir', $this->path); + return parent::dir_rewinddir(); + } + + /** + * closes directory + * + * @return bool + */ + public function dir_closedir() + { + self::recordMethodCall('dir_closedir', $this->path); + return parent::dir_closedir(); + } + + /** + * returns status of url + * + * @param string $path path of url to return status for + * @param int $flags flags set by the stream API + * @return array + */ + public function url_stat($path, $flags) + { + self::recordMethodCall('url_stat', $path); + return parent::url_stat($path, $flags); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamAbstractContentTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamAbstractContentTestCase.php new file mode 100644 index 000000000..faff3d6a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamAbstractContentTestCase.php @@ -0,0 +1,1053 @@ +assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function executePermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0100); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function executePermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0010); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function executePermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0001); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function writePermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0200); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function writePermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0020); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function writePermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0002); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function executeAndWritePermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0300); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function executeAndWritePermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0030); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function executeAndWritePermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0003); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readPermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0400); + $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readPermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0040); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readPermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0004); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readAndExecutePermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0500); + $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readAndExecutePermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0050); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readAndExecutePermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0005); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readAndWritePermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0600); + $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readAndWritePermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0060); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function readAndWritePermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0006); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function allPermissionsForUser() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0700); + $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function allPermissionsForGroup() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0070); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + -1 + ) + ); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function allPermissionsForOther() + { + $abstractContent = new TestvfsStreamAbstractContent('foo', 0007); + $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isReadable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isReadable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isWritable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isWritable(-1, + -1 + ) + ); + $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(), + vfsStream::getCurrentGroup() + ) + ); + $this->assertFalse($abstractContent->isExecutable(-1, + vfsStream::getCurrentGroup() + ) + ); + $this->assertTrue($abstractContent->isExecutable(-1, + -1 + ) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamBlockTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamBlockTestCase.php new file mode 100644 index 000000000..40a8b59ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamBlockTestCase.php @@ -0,0 +1,89 @@ +block = new vfsStreamBlock('foo'); + } + + /** + * test default values and methods + * + * @test + */ + public function defaultValues() + { + $this->assertEquals(vfsStreamContent::TYPE_BLOCK, $this->block->getType()); + $this->assertEquals('foo', $this->block->getName()); + $this->assertTrue($this->block->appliesTo('foo')); + $this->assertFalse($this->block->appliesTo('foo/bar')); + $this->assertFalse($this->block->appliesTo('bar')); + } + + /** + * tests how external functions see this object + * + * @test + */ + public function external() + { + $root = vfsStream::setup('root'); + $root->addChild(vfsStream::newBlock('foo')); + $this->assertEquals('block', filetype(vfsStream::url('root/foo'))); + } + + /** + * tests adding a complex structure + * + * @test + */ + public function addStructure() + { + $structure = array( + 'topLevel' => array( + 'thisIsAFile' => 'file contents', + '[blockDevice]' => 'block contents' + ) + ); + + $root = vfsStream::create($structure); + + $this->assertSame('block', filetype(vfsStream::url('root/topLevel/blockDevice'))); + } + + /** + * tests that a blank name for a block device throws an exception + * @test + */ + public function createWithEmptyName() + { + $this->expectException(vfsStreamException::class); + $structure = array( + 'topLevel' => array( + 'thisIsAFile' => 'file contents', + '[]' => 'block contents' + ) + ); + + $root = vfsStream::create($structure); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamContainerIteratorTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamContainerIteratorTestCase.php new file mode 100644 index 000000000..7698be038 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamContainerIteratorTestCase.php @@ -0,0 +1,111 @@ +dir = new vfsStreamDirectory('foo'); + $this->mockChild1 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $this->mockChild1->expects($this->any()) + ->method('getName') + ->will($this->returnValue('bar')); + $this->dir->addChild($this->mockChild1); + $this->mockChild2 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $this->mockChild2->expects($this->any()) + ->method('getName') + ->will($this->returnValue('baz')); + $this->dir->addChild($this->mockChild2); + } + + /** + * clean up test environment + */ + public function tearDown(): void + { + vfsStream::enableDotfiles(); + } + + /** + * @return array + */ + public function provideSwitchWithExpectations() + { + return array(array(function() { vfsStream::disableDotfiles(); }, + array() + ), + array(function() { vfsStream::enableDotfiles(); }, + array('.', '..') + ) + ); + } + + private function getDirName($dir) + { + if (is_string($dir)) { + return $dir; + } + + + return $dir->getName(); + } + + /** + * @param \Closure $dotFilesSwitch + * @param array $dirNames + * @test + * @dataProvider provideSwitchWithExpectations + */ + public function iteration(\Closure $dotFilesSwitch, array $dirs) + { + $dirs[] = $this->mockChild1; + $dirs[] = $this->mockChild2; + $dotFilesSwitch(); + $dirIterator = $this->dir->getIterator(); + foreach ($dirs as $dir) { + $this->assertEquals($this->getDirName($dir), $dirIterator->key()); + $this->assertTrue($dirIterator->valid()); + if (!is_string($dir)) { + $this->assertSame($dir, $dirIterator->current()); + } + + $dirIterator->next(); + } + + $this->assertFalse($dirIterator->valid()); + $this->assertNull($dirIterator->key()); + $this->assertNull($dirIterator->current()); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue134TestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue134TestCase.php new file mode 100644 index 000000000..3e8258917 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue134TestCase.php @@ -0,0 +1,64 @@ +rootDirectory = vfsStream::newDirectory('/'); + $this->rootDirectory->addChild(vfsStream::newDirectory('var/log/app')); + + } + + /** + * Test: should save directory name as string internal + * + * @small + */ + public function testShouldSaveDirectoryNameAsStringInternal() + { + $dir = $this->rootDirectory->getChild('var/log/app'); + + $dir->addChild(vfsStream::newDirectory(80)); + + static::assertNotNull($this->rootDirectory->getChild('var/log/app/80')); + } + + + + /** + * Test: should rename directory name as string internal + * + * @small + */ + public function testShouldRenameDirectoryNameAsStringInternal() + { + $dir = $this->rootDirectory->getChild('var/log/app'); + + $dir->addChild(vfsStream::newDirectory(80)); + + $child = $this->rootDirectory->getChild('var/log/app/80'); + $child->rename(90); + + static::assertNotNull($this->rootDirectory->getChild('var/log/app/90')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue18TestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue18TestCase.php new file mode 100644 index 000000000..1bf8661e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue18TestCase.php @@ -0,0 +1,80 @@ +rootDirectory = vfsStream::newDirectory('/'); + $this->rootDirectory->addChild(vfsStream::newDirectory('var/log/app')); + $dir = $this->rootDirectory->getChild('var/log/app'); + $dir->addChild(vfsStream::newDirectory('app1')); + $dir->addChild(vfsStream::newDirectory('app2')); + $dir->addChild(vfsStream::newDirectory('foo')); + } + + /** + * @test + */ + public function shouldContainThreeSubdirectories() + { + $this->assertEquals(3, + count($this->rootDirectory->getChild('var/log/app')->getChildren()) + ); + } + + /** + * @test + */ + public function shouldContainSubdirectoryFoo() + { + $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('foo')); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', + $this->rootDirectory->getChild('var/log/app')->getChild('foo') + ); + } + + /** + * @test + */ + public function shouldContainSubdirectoryApp1() + { + $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('app1')); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', + $this->rootDirectory->getChild('var/log/app')->getChild('app1') + ); + } + + /** + * @test + */ + public function shouldContainSubdirectoryApp2() + { + $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('app2')); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', + $this->rootDirectory->getChild('var/log/app')->getChild('app2') + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryTestCase.php new file mode 100644 index 000000000..68e1bee98 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryTestCase.php @@ -0,0 +1,334 @@ +dir = new vfsStreamDirectory('foo'); + } + + /** + * assure that a directory seperator inside the name throws an exception + * + * @test + */ + public function invalidCharacterInName() + { + $this->expectException(vfsStreamException::class); + $dir = new vfsStreamDirectory('foo/bar'); + } + + /** + * test default values and methods + * + * @test + */ + public function defaultValues() + { + $this->assertEquals(vfsStreamContent::TYPE_DIR, $this->dir->getType()); + $this->assertEquals('foo', $this->dir->getName()); + $this->assertTrue($this->dir->appliesTo('foo')); + $this->assertTrue($this->dir->appliesTo('foo/bar')); + $this->assertFalse($this->dir->appliesTo('bar')); + $this->assertEquals(array(), $this->dir->getChildren()); + } + + /** + * test renaming the directory + * + * @test + */ + public function rename() + { + $this->dir->rename('bar'); + $this->assertEquals('bar', $this->dir->getName()); + $this->assertFalse($this->dir->appliesTo('foo')); + $this->assertFalse($this->dir->appliesTo('foo/bar')); + $this->assertTrue($this->dir->appliesTo('bar')); + } + + /** + * renaming the directory to an invalid name throws a vfsStreamException + * + * @test + */ + public function renameToInvalidNameThrowsvfsStreamException() + { + $this->expectException(vfsStreamException::class); + $this->dir->rename('foo/baz'); + } + + /** + * @test + * @since 0.10.0 + */ + public function hasNoChildrenByDefault() + { + $this->assertFalse($this->dir->hasChildren()); + } + + /** + * @test + * @since 0.10.0 + */ + public function hasChildrenReturnsTrueIfAtLeastOneChildPresent() + { + $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild->expects($this->any()) + ->method('appliesTo') + ->will($this->returnValue(false)); + $mockChild->expects($this->any()) + ->method('getName') + ->will($this->returnValue('baz')); + $this->dir->addChild($mockChild); + $this->assertTrue($this->dir->hasChildren()); + } + + /** + * @test + */ + public function hasChildReturnsFalseForNonExistingChild() + { + $this->assertFalse($this->dir->hasChild('bar')); + } + + /** + * @test + */ + public function getChildReturnsNullForNonExistingChild() + { + $this->assertNull($this->dir->getChild('bar')); + } + + /** + * @test + */ + public function removeChildReturnsFalseForNonExistingChild() + { + $this->assertFalse($this->dir->removeChild('bar')); + } + + /** + * @test + */ + public function nonExistingChild() + { + $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild->expects($this->any()) + ->method('appliesTo') + ->will($this->returnValue(false)); + $mockChild->expects($this->any()) + ->method('getName') + ->will($this->returnValue('baz')); + $this->dir->addChild($mockChild); + $this->assertFalse($this->dir->removeChild('bar')); + } + + /** + * test that adding, handling and removing of a child works as expected + * + * @test + */ + public function childHandling() + { + $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild->expects($this->any()) + ->method('getType') + ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); + $mockChild->expects($this->any()) + ->method('getName') + ->will($this->returnValue('bar')); + $mockChild->expects($this->any()) + ->method('appliesTo') + ->with($this->equalTo('bar')) + ->will($this->returnValue(true)); + $mockChild->expects($this->once()) + ->method('size') + ->will($this->returnValue(5)); + $this->dir->addChild($mockChild); + $this->assertTrue($this->dir->hasChild('bar')); + $bar = $this->dir->getChild('bar'); + $this->assertSame($mockChild, $bar); + $this->assertEquals(array($mockChild), $this->dir->getChildren()); + $this->assertEquals(0, $this->dir->size()); + $this->assertEquals(5, $this->dir->sizeSummarized()); + $this->assertTrue($this->dir->removeChild('bar')); + $this->assertEquals(array(), $this->dir->getChildren()); + $this->assertEquals(0, $this->dir->size()); + $this->assertEquals(0, $this->dir->sizeSummarized()); + } + + /** + * test that adding, handling and removing of a child works as expected + * + * @test + */ + public function childHandlingWithSubdirectory() + { + $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild->expects($this->any()) + ->method('getType') + ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); + $mockChild->expects($this->any()) + ->method('getName') + ->will($this->returnValue('bar')); + $mockChild->expects($this->once()) + ->method('size') + ->will($this->returnValue(5)); + $subdir = new vfsStreamDirectory('subdir'); + $subdir->addChild($mockChild); + $this->dir->addChild($subdir); + $this->assertTrue($this->dir->hasChild('subdir')); + $this->assertSame($subdir, $this->dir->getChild('subdir')); + $this->assertEquals(array($subdir), $this->dir->getChildren()); + $this->assertEquals(0, $this->dir->size()); + $this->assertEquals(5, $this->dir->sizeSummarized()); + $this->assertTrue($this->dir->removeChild('subdir')); + $this->assertEquals(array(), $this->dir->getChildren()); + $this->assertEquals(0, $this->dir->size()); + $this->assertEquals(0, $this->dir->sizeSummarized()); + } + + /** + * dd + * + * @test + * @group regression + * @group bug_5 + */ + public function addChildReplacesChildWithSameName_Bug_5() + { + $mockChild1 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild1->expects($this->any()) + ->method('getType') + ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); + $mockChild1->expects($this->any()) + ->method('getName') + ->will($this->returnValue('bar')); + $mockChild2 = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild2->expects($this->any()) + ->method('getType') + ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); + $mockChild2->expects($this->any()) + ->method('getName') + ->will($this->returnValue('bar')); + $this->dir->addChild($mockChild1); + $this->assertTrue($this->dir->hasChild('bar')); + $this->assertSame($mockChild1, $this->dir->getChild('bar')); + $this->dir->addChild($mockChild2); + $this->assertTrue($this->dir->hasChild('bar')); + $this->assertSame($mockChild2, $this->dir->getChild('bar')); + } + + /** + * When testing for a nested path, verify that directory separators are respected properly + * so that subdir1/subdir2 is not considered equal to subdir1Xsubdir2. + * + * @test + * @group bug_24 + * @group regression + */ + public function explicitTestForSeparatorWithNestedPaths_Bug_24() + { + $mockChild = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockChild->expects($this->any()) + ->method('getType') + ->will($this->returnValue(vfsStreamContent::TYPE_FILE)); + $mockChild->expects($this->any()) + ->method('getName') + ->will($this->returnValue('bar')); + + $subdir1 = new vfsStreamDirectory('subdir1'); + $this->dir->addChild($subdir1); + + $subdir2 = new vfsStreamDirectory('subdir2'); + $subdir1->addChild($subdir2); + + $subdir2->addChild($mockChild); + + $this->assertTrue($this->dir->hasChild('subdir1'), "Level 1 path with separator exists"); + $this->assertTrue($this->dir->hasChild('subdir1/subdir2'), "Level 2 path with separator exists"); + $this->assertTrue($this->dir->hasChild('subdir1/subdir2/bar'), "Level 3 path with separator exists"); + $this->assertFalse($this->dir->hasChild('subdir1.subdir2'), "Path with period does not exist"); + $this->assertFalse($this->dir->hasChild('subdir1.subdir2/bar'), "Nested path with period does not exist"); + } + + + /** + * setting and retrieving permissions for a directory + * + * @test + * @group permissions + */ + public function permissions() + { + $this->assertEquals(0777, $this->dir->getPermissions()); + $this->assertSame($this->dir, $this->dir->chmod(0755)); + $this->assertEquals(0755, $this->dir->getPermissions()); + } + + /** + * setting and retrieving permissions for a directory + * + * @test + * @group permissions + */ + public function permissionsSet() + { + $this->dir = new vfsStreamDirectory('foo', 0755); + $this->assertEquals(0755, $this->dir->getPermissions()); + $this->assertSame($this->dir, $this->dir->chmod(0700)); + $this->assertEquals(0700, $this->dir->getPermissions()); + } + + /** + * setting and retrieving owner of a file + * + * @test + * @group permissions + */ + public function owner() + { + $this->assertEquals(vfsStream::getCurrentUser(), $this->dir->getUser()); + $this->assertTrue($this->dir->isOwnedByUser(vfsStream::getCurrentUser())); + $this->assertSame($this->dir, $this->dir->chown(vfsStream::OWNER_USER_1)); + $this->assertEquals(vfsStream::OWNER_USER_1, $this->dir->getUser()); + $this->assertTrue($this->dir->isOwnedByUser(vfsStream::OWNER_USER_1)); + } + + /** + * setting and retrieving owner group of a file + * + * @test + * @group permissions + */ + public function group() + { + $this->assertEquals(vfsStream::getCurrentGroup(), $this->dir->getGroup()); + $this->assertTrue($this->dir->isOwnedByGroup(vfsStream::getCurrentGroup())); + $this->assertSame($this->dir, $this->dir->chgrp(vfsStream::GROUP_USER_1)); + $this->assertEquals(vfsStream::GROUP_USER_1, $this->dir->getGroup()); + $this->assertTrue($this->dir->isOwnedByGroup(vfsStream::GROUP_USER_1)); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamExLockTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamExLockTestCase.php new file mode 100644 index 000000000..891ee1d47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamExLockTestCase.php @@ -0,0 +1,55 @@ +at($root); + + } + + /** + * This test verifies the current behaviour where vfsStream URLs do not work + * with file_put_contents() and LOCK_EX. The test is intended to break once + * PHP changes this so we get notified about the change. + * + * @test + */ + public function filePutContentsLockShouldReportError() + { + @file_put_contents(vfsStream::url('root/testfile'), "some string\n", LOCK_EX); + $php_error = error_get_last(); + $this->assertEquals("file_put_contents(): Exclusive locks may only be set for regular files", $php_error['message']); + } + + /** + * @test + */ + public function flockSouldPass() + { + $fp = fopen(vfsStream::url('root/testfile'), 'w'); + flock($fp, LOCK_EX); + fwrite($fp, "another string\n"); + flock($fp, LOCK_UN); + fclose($fp); + $this->assertEquals("another string\n", file_get_contents(vfsStream::url('root/testfile'))); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamFileTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamFileTestCase.php new file mode 100644 index 000000000..537bcbe3b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamFileTestCase.php @@ -0,0 +1,337 @@ +file = new vfsStreamFile('foo'); + } + + /** + * test default values and methods + * + * @test + */ + public function defaultValues() + { + $this->assertEquals(vfsStreamContent::TYPE_FILE, $this->file->getType()); + $this->assertEquals('foo', $this->file->getName()); + $this->assertTrue($this->file->appliesTo('foo')); + $this->assertFalse($this->file->appliesTo('foo/bar')); + $this->assertFalse($this->file->appliesTo('bar')); + } + + /** + * test setting and getting the content of a file + * + * @test + */ + public function content() + { + $this->assertEquals('', $this->file->getContent()); + $this->assertSame($this->file, $this->file->setContent('bar')); + $this->assertEquals('bar', $this->file->getContent()); + $this->assertSame($this->file, $this->file->withContent('baz')); + $this->assertEquals('baz', $this->file->getContent()); + } + + /** + * test renaming the directory + * + * @test + */ + public function rename() + { + $this->file->rename('bar'); + $this->assertEquals('bar', $this->file->getName()); + $this->assertFalse($this->file->appliesTo('foo')); + $this->assertFalse($this->file->appliesTo('foo/bar')); + $this->assertTrue($this->file->appliesTo('bar')); + } + + /** + * test reading contents from the file + * + * @test + */ + public function readEmptyFile() + { + $this->assertTrue($this->file->eof()); + $this->assertEquals(0, $this->file->size()); + $this->assertEquals('', $this->file->read(5)); + $this->assertEquals(5, $this->file->getBytesRead()); + $this->assertTrue($this->file->eof()); + } + + /** + * test reading contents from the file + * + * @test + */ + public function read() + { + $this->file->setContent('foobarbaz'); + $this->assertFalse($this->file->eof()); + $this->assertEquals(9, $this->file->size()); + $this->assertEquals('foo', $this->file->read(3)); + $this->assertEquals(3, $this->file->getBytesRead()); + $this->assertFalse($this->file->eof()); + $this->assertEquals(9, $this->file->size()); + $this->assertEquals('bar', $this->file->read(3)); + $this->assertEquals(6, $this->file->getBytesRead()); + $this->assertFalse($this->file->eof()); + $this->assertEquals(9, $this->file->size()); + $this->assertEquals('baz', $this->file->read(3)); + $this->assertEquals(9, $this->file->getBytesRead()); + $this->assertEquals(9, $this->file->size()); + $this->assertTrue($this->file->eof()); + $this->assertEquals('', $this->file->read(3)); + } + + /** + * test seeking to offset + * + * @test + */ + public function seekEmptyFile() + { + $this->assertFalse($this->file->seek(0, 55)); + $this->assertTrue($this->file->seek(0, SEEK_SET)); + $this->assertEquals(0, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(5, SEEK_SET)); + $this->assertEquals(5, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(0, SEEK_CUR)); + $this->assertEquals(5, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(2, SEEK_CUR)); + $this->assertEquals(7, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(0, SEEK_END)); + $this->assertEquals(0, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(2, SEEK_END)); + $this->assertEquals(2, $this->file->getBytesRead()); + } + + /** + * @test + * @since 1.6.5 + */ + public function seekEmptyFileBeforeBeginningDoesNotChangeOffset() + { + $this->assertFalse($this->file->seek(-5, SEEK_SET), 'Seek before beginning of file'); + $this->assertEquals(0, $this->file->getBytesRead()); + } + + /** + * test seeking to offset + * + * @test + */ + public function seekRead() + { + $this->file->setContent('foobarbaz'); + $this->assertFalse($this->file->seek(0, 55)); + $this->assertTrue($this->file->seek(0, SEEK_SET)); + $this->assertEquals('foobarbaz', $this->file->readUntilEnd()); + $this->assertEquals(0, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(5, SEEK_SET)); + $this->assertEquals('rbaz', $this->file->readUntilEnd()); + $this->assertEquals(5, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(0, SEEK_CUR)); + $this->assertEquals('rbaz', $this->file->readUntilEnd()); + $this->assertEquals(5, $this->file->getBytesRead(), 5); + $this->assertTrue($this->file->seek(2, SEEK_CUR)); + $this->assertEquals('az', $this->file->readUntilEnd()); + $this->assertEquals(7, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(0, SEEK_END)); + $this->assertEquals('', $this->file->readUntilEnd()); + $this->assertEquals(9, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(2, SEEK_END)); + $this->assertEquals('', $this->file->readUntilEnd()); + $this->assertEquals(11, $this->file->getBytesRead()); + } + + /** + * @test + * @since 1.6.5 + */ + public function seekFileBeforeBeginningDoesNotChangeOffset() + { + $this->file->setContent('foobarbaz'); + $this->assertFalse($this->file->seek(-5, SEEK_SET), 'Seek before beginning of file'); + $this->assertEquals(0, $this->file->getBytesRead()); + $this->assertTrue($this->file->seek(2, SEEK_CUR)); + $this->assertFalse($this->file->seek(-5, SEEK_SET), 'Seek before beginning of file'); + $this->assertEquals(2, $this->file->getBytesRead()); + $this->assertEquals('obarbaz', $this->file->readUntilEnd()); + $this->assertFalse($this->file->seek(-5, SEEK_CUR), 'Seek before beginning of file'); + $this->assertEquals(2, $this->file->getBytesRead()); + $this->assertEquals('obarbaz', $this->file->readUntilEnd()); + $this->assertFalse($this->file->seek(-20, SEEK_END), 'Seek before beginning of file'); + $this->assertEquals(2, $this->file->getBytesRead()); + $this->assertEquals('obarbaz', $this->file->readUntilEnd()); + } + + /** + * test writing data into the file + * + * @test + */ + public function writeEmptyFile() + { + $this->assertEquals(3, $this->file->write('foo')); + $this->assertEquals('foo', $this->file->getContent()); + $this->assertEquals(3, $this->file->size()); + $this->assertEquals(3, $this->file->write('bar')); + $this->assertEquals('foobar', $this->file->getContent()); + $this->assertEquals(6, $this->file->size()); + } + + /** + * test writing data into the file + * + * @test + */ + public function write() + { + $this->file->setContent('foobarbaz'); + $this->assertTrue($this->file->seek(3, SEEK_SET)); + $this->assertEquals(3, $this->file->write('foo')); + $this->assertEquals('foofoobaz', $this->file->getContent()); + $this->assertEquals(9, $this->file->size()); + $this->assertEquals(3, $this->file->write('bar')); + $this->assertEquals('foofoobar', $this->file->getContent()); + $this->assertEquals(9, $this->file->size()); + } + + /** + * setting and retrieving permissions for a file + * + * @test + * @group permissions + */ + public function permissions() + { + $this->assertEquals(0666, $this->file->getPermissions()); + $this->assertSame($this->file, $this->file->chmod(0644)); + $this->assertEquals(0644, $this->file->getPermissions()); + } + + /** + * setting and retrieving permissions for a file + * + * @test + * @group permissions + */ + public function permissionsSet() + { + $this->file = new vfsStreamFile('foo', 0644); + $this->assertEquals(0644, $this->file->getPermissions()); + $this->assertSame($this->file, $this->file->chmod(0600)); + $this->assertEquals(0600, $this->file->getPermissions()); + } + + /** + * setting and retrieving owner of a file + * + * @test + * @group permissions + */ + public function owner() + { + $this->assertEquals(vfsStream::getCurrentUser(), $this->file->getUser()); + $this->assertTrue($this->file->isOwnedByUser(vfsStream::getCurrentUser())); + $this->assertSame($this->file, $this->file->chown(vfsStream::OWNER_USER_1)); + $this->assertEquals(vfsStream::OWNER_USER_1, $this->file->getUser()); + $this->assertTrue($this->file->isOwnedByUser(vfsStream::OWNER_USER_1)); + } + + /** + * setting and retrieving owner group of a file + * + * @test + * @group permissions + */ + public function group() + { + $this->assertEquals(vfsStream::getCurrentGroup(), $this->file->getGroup()); + $this->assertTrue($this->file->isOwnedByGroup(vfsStream::getCurrentGroup())); + $this->assertSame($this->file, $this->file->chgrp(vfsStream::GROUP_USER_1)); + $this->assertEquals(vfsStream::GROUP_USER_1, $this->file->getGroup()); + $this->assertTrue($this->file->isOwnedByGroup(vfsStream::GROUP_USER_1)); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + */ + public function truncateRemovesSuperflouosContent() + { + $this->assertEquals(11, $this->file->write("lorem ipsum")); + $this->assertTrue($this->file->truncate(5)); + $this->assertEquals(5, $this->file->size()); + $this->assertEquals('lorem', $this->file->getContent()); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + */ + public function truncateToGreaterSizeAddsZeroBytes() + { + $this->assertEquals(11, $this->file->write("lorem ipsum")); + $this->assertTrue($this->file->truncate(25)); + $this->assertEquals(25, $this->file->size()); + $this->assertEquals("lorem ipsum\0\0\0\0\0\0\0\0\0\0\0\0\0\0", $this->file->getContent()); + } + + /** + * @test + * @group issue_79 + * @since 1.3.0 + */ + public function withContentAcceptsAnyFileContentInstance() + { + $mockFileContent = $this->bc_getMock('org\bovigo\vfs\content\FileContent'); + $mockFileContent->expects($this->once()) + ->method('content') + ->will($this->returnValue('foobarbaz')); + $this->assertEquals( + 'foobarbaz', + $this->file->withContent($mockFileContent) + ->getContent() + ); + } + + /** + * @test + * @group issue_79 + * @since 1.3.0 + */ + public function withContentThrowsInvalidArgumentExceptionWhenContentIsNoStringAndNoFileContent() + { + $this->expectException(\InvalidArgumentException::class); + $this->file->withContent(313); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamGlobTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamGlobTestCase.php new file mode 100644 index 000000000..2dec5638e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamGlobTestCase.php @@ -0,0 +1,28 @@ +assertEmpty(glob(vfsStream::url('example'), GLOB_MARK)); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamResolveIncludePathTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamResolveIncludePathTestCase.php new file mode 100644 index 000000000..7f0130c77 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamResolveIncludePathTestCase.php @@ -0,0 +1,61 @@ +backupIncludePath = get_include_path(); + vfsStream::setup(); + mkdir('vfs://root/a/path', 0777, true); + set_include_path('vfs://root/a' . PATH_SEPARATOR . $this->backupIncludePath); + } + + /** + * clean up test environment + */ + public function tearDown(): void + { + set_include_path($this->backupIncludePath); + } + + /** + * @test + */ + public function knownFileCanBeResolved() + { + file_put_contents('vfs://root/a/path/knownFile.php', ''); + $this->assertEquals('vfs://root/a/path/knownFile.php', stream_resolve_include_path('path/knownFile.php')); + } + + /** + * @test + */ + public function unknownFileCanNotBeResolvedYieldsFalse() + { + $this->assertFalse(@stream_resolve_include_path('path/unknownFile.php')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamTestCase.php new file mode 100644 index 000000000..38e1f0d11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamTestCase.php @@ -0,0 +1,780 @@ +assertEquals('vfs://foo', vfsStream::url('foo')); + $this->assertEquals('vfs://foo/bar.baz', vfsStream::url('foo/bar.baz')); + $this->assertEquals('vfs://foo/bar.baz', vfsStream::url('foo\bar.baz')); + } + + /** + * assure that url2path conversion works correct + * + * @test + */ + public function path() + { + $this->assertEquals('foo', vfsStream::path('vfs://foo')); + $this->assertEquals('foo/bar.baz', vfsStream::path('vfs://foo/bar.baz')); + $this->assertEquals('foo/bar.baz', vfsStream::path('vfs://foo\bar.baz')); + } + + /** + * windows directory separators are converted into default separator + * + * @author Gabriel Birke + * @test + */ + public function pathConvertsWindowsDirectorySeparators() + { + $this->assertEquals('foo/bar', vfsStream::path('vfs://foo\\bar')); + } + + /** + * trailing whitespace should be removed + * + * @author Gabriel Birke + * @test + */ + public function pathRemovesTrailingWhitespace() + { + $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar ')); + } + + /** + * trailing slashes are removed + * + * @author Gabriel Birke + * @test + */ + public function pathRemovesTrailingSlash() + { + $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar/')); + } + + /** + * trailing slash and whitespace should be removed + * + * @author Gabriel Birke + * @test + */ + public function pathRemovesTrailingSlashAndWhitespace() + { + $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar/ ')); + } + + /** + * double slashes should be replaced by single slash + * + * @author Gabriel Birke + * @test + */ + public function pathRemovesDoubleSlashes() + { + // Regular path + $this->assertEquals('my/path', vfsStream::path('vfs://my/path')); + // Path with double slashes + $this->assertEquals('my/path', vfsStream::path('vfs://my//path')); + } + + /** + * test to create a new file + * + * @test + */ + public function newFile() + { + $file = vfsStream::newFile('filename.txt'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file); + $this->assertEquals('filename.txt', $file->getName()); + $this->assertEquals(0666, $file->getPermissions()); + } + + /** + * test to create a new file with non-default permissions + * + * @test + * @group permissions + */ + public function newFileWithDifferentPermissions() + { + $file = vfsStream::newFile('filename.txt', 0644); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file); + $this->assertEquals('filename.txt', $file->getName()); + $this->assertEquals(0644, $file->getPermissions()); + } + + /** + * test to create a new directory structure + * + * @test + */ + public function newSingleDirectory() + { + $foo = vfsStream::newDirectory('foo'); + $this->assertEquals('foo', $foo->getName()); + $this->assertEquals(0, count($foo->getChildren())); + $this->assertEquals(0777, $foo->getPermissions()); + } + + /** + * test to create a new directory structure with non-default permissions + * + * @test + * @group permissions + */ + public function newSingleDirectoryWithDifferentPermissions() + { + $foo = vfsStream::newDirectory('foo', 0755); + $this->assertEquals('foo', $foo->getName()); + $this->assertEquals(0, count($foo->getChildren())); + $this->assertEquals(0755, $foo->getPermissions()); + } + + /** + * test to create a new directory structure + * + * @test + */ + public function newDirectoryStructure() + { + $foo = vfsStream::newDirectory('foo/bar/baz'); + $this->assertEquals('foo', $foo->getName()); + $this->assertEquals(0777, $foo->getPermissions()); + $this->assertTrue($foo->hasChild('bar')); + $this->assertTrue($foo->hasChild('bar/baz')); + $this->assertFalse($foo->hasChild('baz')); + $bar = $foo->getChild('bar'); + $this->assertEquals('bar', $bar->getName()); + $this->assertEquals(0777, $bar->getPermissions()); + $this->assertTrue($bar->hasChild('baz')); + $baz1 = $bar->getChild('baz'); + $this->assertEquals('baz', $baz1->getName()); + $this->assertEquals(0777, $baz1->getPermissions()); + $baz2 = $foo->getChild('bar/baz'); + $this->assertSame($baz1, $baz2); + } + + /** + * test that correct directory structure is created + * + * @test + */ + public function newDirectoryWithSlashAtStart() + { + $foo = vfsStream::newDirectory('/foo/bar/baz', 0755); + $this->assertEquals('foo', $foo->getName()); + $this->assertEquals(0755, $foo->getPermissions()); + $this->assertTrue($foo->hasChild('bar')); + $this->assertTrue($foo->hasChild('bar/baz')); + $this->assertFalse($foo->hasChild('baz')); + $bar = $foo->getChild('bar'); + $this->assertEquals('bar', $bar->getName()); + $this->assertEquals(0755, $bar->getPermissions()); + $this->assertTrue($bar->hasChild('baz')); + $baz1 = $bar->getChild('baz'); + $this->assertEquals('baz', $baz1->getName()); + $this->assertEquals(0755, $baz1->getPermissions()); + $baz2 = $foo->getChild('bar/baz'); + $this->assertSame($baz1, $baz2); + } + + /** + * @test + * @group setup + * @since 0.7.0 + */ + public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithDefaultNameAndPermissions() + { + $root = vfsStream::setup(); + $this->assertSame($root, vfsStreamWrapper::getRoot()); + $this->assertEquals('root', $root->getName()); + $this->assertEquals(0777, $root->getPermissions()); + } + + /** + * @test + * @group setup + * @since 0.7.0 + */ + public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithGivenNameAndDefaultPermissions() + { + $root = vfsStream::setup('foo'); + $this->assertSame($root, vfsStreamWrapper::getRoot()); + $this->assertEquals('foo', $root->getName()); + $this->assertEquals(0777, $root->getPermissions()); + } + + /** + * @test + * @group setup + * @since 0.7.0 + */ + public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithGivenNameAndPermissions() + { + $root = vfsStream::setup('foo', 0444); + $this->assertSame($root, vfsStreamWrapper::getRoot()); + $this->assertEquals('foo', $root->getName()); + $this->assertEquals(0444, $root->getPermissions()); + } + + /** + * @test + * @group issue_14 + * @group issue_20 + * @since 0.10.0 + */ + public function setupWithEmptyArrayIsEqualToSetup() + { + $root = vfsStream::setup('example', + 0755, + array() + ); + $this->assertEquals('example', $root->getName()); + $this->assertEquals(0755, $root->getPermissions()); + $this->assertFalse($root->hasChildren()); + } + + /** + * @test + * @group issue_14 + * @group issue_20 + * @since 0.10.0 + */ + public function setupArraysAreTurnedIntoSubdirectories() + { + $root = vfsStream::setup('root', + null, + array('test' => array()) + ); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('test')); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', + $root->getChild('test') + ); + $this->assertFalse($root->getChild('test')->hasChildren()); + } + + /** + * @test + * @group issue_14 + * @group issue_20 + * @since 0.10.0 + */ + public function setupStringsAreTurnedIntoFilesWithContent() + { + $root = vfsStream::setup('root', + null, + array('test.txt' => 'some content') + ); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('test.txt')); + $this->assertVfsFile($root->getChild('test.txt'), 'some content'); + } + + /** + * @test + * @group issue_14 + * @group issue_20 + * @since 0.10.0 + */ + public function setupWorksRecursively() + { + $root = vfsStream::setup('root', + null, + array('test' => array('foo' => array('test.txt' => 'hello'), + 'baz.txt' => 'world' + ) + ) + ); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('test')); + $test = $root->getChild('test'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test); + $this->assertTrue($test->hasChildren()); + $this->assertTrue($test->hasChild('baz.txt')); + $this->assertVfsFile($test->getChild('baz.txt'), 'world'); + + $this->assertTrue($test->hasChild('foo')); + $foo = $test->getChild('foo'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo); + $this->assertTrue($foo->hasChildren()); + $this->assertTrue($foo->hasChild('test.txt')); + $this->assertVfsFile($foo->getChild('test.txt'), 'hello'); + } + + /** + * @test + * @group issue_17 + * @group issue_20 + */ + public function setupCastsNumericDirectoriesToStrings() + { + $root = vfsStream::setup('root', + null, + array(2011 => array ('test.txt' => 'some content')) + ); + $this->assertTrue($root->hasChild('2011')); + + $directory = $root->getChild('2011'); + $this->assertVfsFile($directory->getChild('test.txt'), 'some content'); + + $this->assertTrue(file_exists('vfs://root/2011/test.txt')); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createArraysAreTurnedIntoSubdirectories() + { + $baseDir = vfsStream::create(array('test' => array()), new vfsStreamDirectory('baseDir')); + $this->assertTrue($baseDir->hasChildren()); + $this->assertTrue($baseDir->hasChild('test')); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', + $baseDir->getChild('test') + ); + $this->assertFalse($baseDir->getChild('test')->hasChildren()); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createArraysAreTurnedIntoSubdirectoriesOfRoot() + { + $root = vfsStream::setup(); + $this->assertSame($root, vfsStream::create(array('test' => array()))); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('test')); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', + $root->getChild('test') + ); + $this->assertFalse($root->getChild('test')->hasChildren()); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createThrowsExceptionIfNoBaseDirGivenAndNoRootSet() + { + $this->expectException(\InvalidArgumentException::class); + vfsStream::create(array('test' => array())); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createWorksRecursively() + { + $baseDir = vfsStream::create(array('test' => array('foo' => array('test.txt' => 'hello'), + 'baz.txt' => 'world' + ) + ), + new vfsStreamDirectory('baseDir') + ); + $this->assertTrue($baseDir->hasChildren()); + $this->assertTrue($baseDir->hasChild('test')); + $test = $baseDir->getChild('test'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test); + $this->assertTrue($test->hasChildren()); + $this->assertTrue($test->hasChild('baz.txt')); + $this->assertVfsFile($test->getChild('baz.txt'), 'world'); + + $this->assertTrue($test->hasChild('foo')); + $foo = $test->getChild('foo'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo); + $this->assertTrue($foo->hasChildren()); + $this->assertTrue($foo->hasChild('test.txt')); + $this->assertVfsFile($foo->getChild('test.txt'), 'hello'); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createWorksRecursivelyWithRoot() + { + $root = vfsStream::setup(); + $this->assertSame($root, + vfsStream::create(array('test' => array('foo' => array('test.txt' => 'hello'), + 'baz.txt' => 'world' + ) + ) + ) + ); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('test')); + $test = $root->getChild('test'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test); + $this->assertTrue($test->hasChildren()); + $this->assertTrue($test->hasChild('baz.txt')); + $this->assertVfsFile($test->getChild('baz.txt'), 'world'); + + $this->assertTrue($test->hasChild('foo')); + $foo = $test->getChild('foo'); + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo); + $this->assertTrue($foo->hasChildren()); + $this->assertTrue($foo->hasChild('test.txt')); + $this->assertVfsFile($foo->getChild('test.txt'), 'hello'); + } + + /** + * @test + * @group issue_20 + * @since 0.10.0 + */ + public function createStringsAreTurnedIntoFilesWithContent() + { + $baseDir = vfsStream::create(array('test.txt' => 'some content'), new vfsStreamDirectory('baseDir')); + $this->assertTrue($baseDir->hasChildren()); + $this->assertTrue($baseDir->hasChild('test.txt')); + $this->assertVfsFile($baseDir->getChild('test.txt'), 'some content'); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createStringsAreTurnedIntoFilesWithContentWithRoot() + { + $root = vfsStream::setup(); + $this->assertSame($root, + vfsStream::create(array('test.txt' => 'some content')) + ); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('test.txt')); + $this->assertVfsFile($root->getChild('test.txt'), 'some content'); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createCastsNumericDirectoriesToStrings() + { + $baseDir = vfsStream::create(array(2011 => array ('test.txt' => 'some content')), new vfsStreamDirectory('baseDir')); + $this->assertTrue($baseDir->hasChild('2011')); + + $directory = $baseDir->getChild('2011'); + $this->assertVfsFile($directory->getChild('test.txt'), 'some content'); + } + + /** + * @test + * @group issue_20 + * @since 0.11.0 + */ + public function createCastsNumericDirectoriesToStringsWithRoot() + { + $root = vfsStream::setup(); + $this->assertSame($root, + vfsStream::create(array(2011 => array ('test.txt' => 'some content'))) + ); + $this->assertTrue($root->hasChild('2011')); + + $directory = $root->getChild('2011'); + $this->assertVfsFile($directory->getChild('test.txt'), 'some content'); + } + + /** + * helper function for assertions on vfsStreamFile + * + * @param vfsStreamFile $file + * @param string $content + */ + protected function assertVfsFile(vfsStreamFile $file, $content) + { + $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', + $file + ); + $this->assertEquals($content, + $file->getContent() + ); + } + + /** + * @test + * @group issue_10 + * @since 0.10.0 + */ + public function inspectWithContentGivesContentToVisitor() + { + $mockContent = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor'); + $mockVisitor->expects($this->once()) + ->method('visit') + ->with($this->equalTo($mockContent)) + ->will($this->returnValue($mockVisitor)); + $this->assertSame($mockVisitor, vfsStream::inspect($mockVisitor, $mockContent)); + } + + /** + * @test + * @group issue_10 + * @since 0.10.0 + */ + public function inspectWithoutContentGivesRootToVisitor() + { + $root = vfsStream::setup(); + $mockVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor'); + $mockVisitor->expects($this->once()) + ->method('visitDirectory') + ->with($this->equalTo($root)) + ->will($this->returnValue($mockVisitor)); + $this->assertSame($mockVisitor, vfsStream::inspect($mockVisitor)); + } + + /** + * @test + * @group issue_10 + * @since 0.10.0 + */ + public function inspectWithoutContentAndWithoutRootThrowsInvalidArgumentException() + { + $this->expectException(\InvalidArgumentException::class); + $mockVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor'); + $mockVisitor->expects($this->never()) + ->method('visit'); + $mockVisitor->expects($this->never()) + ->method('visitDirectory'); + vfsStream::inspect($mockVisitor); + } + + /** + * returns path to file system copy resource directory + * + * @return string + */ + protected function getFileSystemCopyDir() + { + return realpath(dirname(__FILE__) . '/../../../../resources/filesystemcopy'); + } + + /** + * @test + * @group issue_4 + * @since 0.11.0 + */ + public function copyFromFileSystemThrowsExceptionIfNoBaseDirGivenAndNoRootSet() + { + $this->expectException(\InvalidArgumentException::class); + vfsStream::copyFromFileSystem($this->getFileSystemCopyDir()); + } + + /** + * @test + * @group issue_4 + * @since 0.11.0 + */ + public function copyFromEmptyFolder() + { + $baseDir = vfsStream::copyFromFileSystem($this->getFileSystemCopyDir() . '/emptyFolder', + vfsStream::newDirectory('test') + ); + $baseDir->removeChild('.gitignore'); + $this->assertFalse($baseDir->hasChildren()); + } + + /** + * @test + * @group issue_4 + * @since 0.11.0 + */ + public function copyFromEmptyFolderWithRoot() + { + $root = vfsStream::setup(); + $this->assertEquals($root, + vfsStream::copyFromFileSystem($this->getFileSystemCopyDir() . '/emptyFolder') + ); + $root->removeChild('.gitignore'); + $this->assertFalse($root->hasChildren()); + } + + /** + * @test + * @group issue_4 + * @since 0.11.0 + */ + public function copyFromWithSubFolders() + { + $baseDir = vfsStream::copyFromFileSystem($this->getFileSystemCopyDir(), + vfsStream::newDirectory('test'), + 3 + ); + $this->assertTrue($baseDir->hasChildren()); + $this->assertTrue($baseDir->hasChild('emptyFolder')); + $this->assertTrue($baseDir->hasChild('withSubfolders')); + $subfolderDir = $baseDir->getChild('withSubfolders'); + $this->assertTrue($subfolderDir->hasChild('subfolder1')); + $this->assertTrue($subfolderDir->getChild('subfolder1')->hasChild('file1.txt')); + $this->assertVfsFile($subfolderDir->getChild('subfolder1/file1.txt'), ' '); + $this->assertTrue($subfolderDir->hasChild('subfolder2')); + $this->assertTrue($subfolderDir->hasChild('aFile.txt')); + $this->assertVfsFile($subfolderDir->getChild('aFile.txt'), 'foo'); + } + + /** + * @test + * @group issue_4 + * @since 0.11.0 + */ + public function copyFromWithSubFoldersWithRoot() + { + $root = vfsStream::setup(); + $this->assertEquals($root, + vfsStream::copyFromFileSystem($this->getFileSystemCopyDir(), + null, + 3 + ) + ); + $this->assertTrue($root->hasChildren()); + $this->assertTrue($root->hasChild('emptyFolder')); + $this->assertTrue($root->hasChild('withSubfolders')); + $subfolderDir = $root->getChild('withSubfolders'); + $this->assertTrue($subfolderDir->hasChild('subfolder1')); + $this->assertTrue($subfolderDir->getChild('subfolder1')->hasChild('file1.txt')); + $this->assertVfsFile($subfolderDir->getChild('subfolder1/file1.txt'), ' '); + $this->assertTrue($subfolderDir->hasChild('subfolder2')); + $this->assertTrue($subfolderDir->hasChild('aFile.txt')); + $this->assertVfsFile($subfolderDir->getChild('aFile.txt'), 'foo'); + } + + /** + * @test + * @group issue_4 + * @group issue_29 + * @since 0.11.2 + */ + public function copyFromPreservesFilePermissions() + { + if (DIRECTORY_SEPARATOR !== '/') { + $this->markTestSkipped('Only applicable on Linux style systems.'); + } + + $copyDir = $this->getFileSystemCopyDir(); + $root = vfsStream::setup(); + $this->assertEquals($root, + vfsStream::copyFromFileSystem($copyDir, + null + ) + ); + $this->assertEquals(fileperms($copyDir . '/withSubfolders') - vfsStreamContent::TYPE_DIR, + $root->getChild('withSubfolders') + ->getPermissions() + ); + $this->assertEquals(fileperms($copyDir . '/withSubfolders/aFile.txt') - vfsStreamContent::TYPE_FILE, + $root->getChild('withSubfolders/aFile.txt') + ->getPermissions() + ); + } + + /** + * To test this the max file size is reduced to something reproduceable. + * + * @test + * @group issue_91 + * @since 1.5.0 + */ + public function copyFromFileSystemMocksLargeFiles() + { + if (DIRECTORY_SEPARATOR !== '/') { + $this->markTestSkipped('Only applicable on Linux style systems.'); + } + + $copyDir = $this->getFileSystemCopyDir(); + $root = vfsStream::setup(); + vfsStream::copyFromFileSystem($copyDir, $root, 3); + $this->assertEquals( + ' ', + $root->getChild('withSubfolders/subfolder1/file1.txt')->getContent() + ); + } + + /** + * @test + * @group issue_121 + * @since 1.6.1 + */ + public function createDirectoryWithTrailingSlashShouldNotCreateSubdirectoryWithEmptyName() + { + $directory = vfsStream::newDirectory('foo/'); + $this->assertFalse($directory->hasChildren()); + } + + /** + * @test + * @group issue_149 + */ + public function addStructureHandlesVfsStreamFileObjects() + { + $structure = array( + 'topLevel' => array( + 'thisIsAFile' => 'file contents', + vfsStream::newFile('anotherFile'), + ), + ); + + vfsStream::setup(); + $root = vfsStream::create($structure); + + $this->assertTrue($root->hasChild('topLevel/anotherFile')); + } + + /** + * @test + * @group issue_149 + */ + public function createHandlesLargeFileContentObjects() + { + $structure = array( + 'topLevel' => array( + 'thisIsAFile' => 'file contents', + 'anotherFile' => LargeFileContent::withMegabytes(2), + ), + ); + + vfsStream::setup(); + $root = vfsStream::create($structure); + + $this->assertTrue($root->hasChild('topLevel/anotherFile')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamUmaskTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamUmaskTestCase.php new file mode 100644 index 000000000..2747399b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamUmaskTestCase.php @@ -0,0 +1,194 @@ +assertEquals(vfsStream::umask(), + vfsStream::umask() + ); + $this->assertEquals(0000, + vfsStream::umask() + ); + } + + /** + * @test + */ + public function changingUmaskSettingReturnsOldUmaskSetting() + { + $this->assertEquals(0000, + vfsStream::umask(0022) + ); + $this->assertEquals(0022, + vfsStream::umask() + ); + } + + /** + * @test + */ + public function createFileWithDefaultUmaskSetting() + { + $file = new vfsStreamFile('foo'); + $this->assertEquals(0666, $file->getPermissions()); + } + + /** + * @test + */ + public function createFileWithDifferentUmaskSetting() + { + vfsStream::umask(0022); + $file = new vfsStreamFile('foo'); + $this->assertEquals(0644, $file->getPermissions()); + } + + /** + * @test + */ + public function createDirectoryWithDefaultUmaskSetting() + { + $directory = new vfsStreamDirectory('foo'); + $this->assertEquals(0777, $directory->getPermissions()); + } + + /** + * @test + */ + public function createDirectoryWithDifferentUmaskSetting() + { + vfsStream::umask(0022); + $directory = new vfsStreamDirectory('foo'); + $this->assertEquals(0755, $directory->getPermissions()); + } + + /** + * @test + */ + public function createFileUsingStreamWithDefaultUmaskSetting() + { + $root = vfsStream::setup(); + file_put_contents(vfsStream::url('root/newfile.txt'), 'file content'); + $this->assertEquals(0666, $root->getChild('newfile.txt')->getPermissions()); + } + + /** + * @test + */ + public function createFileUsingStreamWithDifferentUmaskSetting() + { + $root = vfsStream::setup(); + vfsStream::umask(0022); + file_put_contents(vfsStream::url('root/newfile.txt'), 'file content'); + $this->assertEquals(0644, $root->getChild('newfile.txt')->getPermissions()); + } + + /** + * @test + */ + public function createDirectoryUsingStreamWithDefaultUmaskSetting() + { + $root = vfsStream::setup(); + mkdir(vfsStream::url('root/newdir')); + $this->assertEquals(0777, $root->getChild('newdir')->getPermissions()); + } + + /** + * @test + */ + public function createDirectoryUsingStreamWithDifferentUmaskSetting() + { + $root = vfsStream::setup(); + vfsStream::umask(0022); + mkdir(vfsStream::url('root/newdir')); + $this->assertEquals(0755, $root->getChild('newdir')->getPermissions()); + } + + /** + * @test + */ + public function createDirectoryUsingStreamWithExplicit0() + { + $root = vfsStream::setup(); + vfsStream::umask(0022); + mkdir(vfsStream::url('root/newdir'), 0000); + $this->assertEquals(0000, $root->getChild('newdir')->getPermissions()); + } + + /** + * @test + * + */ + public function createDirectoryUsingStreamWithDifferentUmaskSettingButExplicit0777() + { + $root = vfsStream::setup(); + vfsStream::umask(0022); + mkdir(vfsStream::url('root/newdir'), 0777); + $this->assertEquals(0755, $root->getChild('newdir')->getPermissions()); + } + + /** + * @test + */ + public function createDirectoryUsingStreamWithDifferentUmaskSettingButExplicitModeRequestedByCall() + { + $root = vfsStream::setup(); + vfsStream::umask(0022); + mkdir(vfsStream::url('root/newdir'), 0700); + $this->assertEquals(0700, $root->getChild('newdir')->getPermissions()); + } + + /** + * @test + */ + public function defaultUmaskSettingDoesNotInfluenceSetup() + { + $root = vfsStream::setup(); + $this->assertEquals(0777, $root->getPermissions()); + } + + /** + * @test + */ + public function umaskSettingShouldBeRespectedBySetup() + { + vfsStream::umask(0022); + $root = vfsStream::setup(); + $this->assertEquals(0755, $root->getPermissions()); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperAlreadyRegisteredTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperAlreadyRegisteredTestCase.php new file mode 100644 index 000000000..786c3b84e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperAlreadyRegisteredTestCase.php @@ -0,0 +1,62 @@ +bc_getMock('org\\bovigo\\vfs\\vfsStreamWrapper'); + stream_wrapper_register(vfsStream::SCHEME, get_class($mock)); + } + + /** + * clean up test environment + */ + public function tearDown(): void + { + TestvfsStreamWrapper::unregister(); + } + + /** + * registering the stream wrapper when another stream wrapper is already + * registered for the vfs scheme should throw an exception + * + * @test + */ + public function registerOverAnotherStreamWrapper() + { + $this->expectException(vfsStreamException::class); + vfsStreamWrapper::register(); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperBaseTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperBaseTestCase.php new file mode 100644 index 000000000..c60806de0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperBaseTestCase.php @@ -0,0 +1,98 @@ +fooURL = vfsStream::url('foo'); + $this->barURL = vfsStream::url('foo/bar'); + $this->baz1URL = vfsStream::url('foo/bar/baz1'); + $this->baz2URL = vfsStream::url('foo/baz2'); + $this->foo = new vfsStreamDirectory('foo'); + $this->bar = new vfsStreamDirectory('bar'); + $this->baz1 = vfsStream::newFile('baz1') + ->lastModified(300) + ->lastAccessed(300) + ->lastAttributeModified(300) + ->withContent('baz 1'); + $this->baz2 = vfsStream::newFile('baz2') + ->withContent('baz2') + ->lastModified(400) + ->lastAccessed(400) + ->lastAttributeModified(400); + $this->bar->addChild($this->baz1); + $this->foo->addChild($this->bar); + $this->foo->addChild($this->baz2); + $this->foo->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + $this->bar->lastModified(200) + ->lastAccessed(100) + ->lastAttributeModified(100); + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot($this->foo); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirSeparatorTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirSeparatorTestCase.php new file mode 100644 index 000000000..f9010437a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirSeparatorTestCase.php @@ -0,0 +1,72 @@ +root = vfsStream::setup(); + } + + /** + * @test + */ + public function fileCanBeAccessedUsingWinDirSeparator() + { + vfsStream::newFile('foo/bar/baz.txt') + ->at($this->root) + ->withContent('test'); + $this->assertEquals('test', file_get_contents('vfs://root/foo\bar\baz.txt')); + } + + + /** + * @test + */ + public function directoryCanBeCreatedUsingWinDirSeparator() + { + mkdir('vfs://root/dir\bar\foo', true, 0777); + $this->assertTrue($this->root->hasChild('dir')); + $this->assertTrue($this->root->getChild('dir')->hasChild('bar')); + $this->assertTrue($this->root->getChild('dir/bar')->hasChild('foo')); + } + + /** + * @test + */ + public function directoryExitsTestUsingTrailingWinDirSeparator() + { + $structure = array( + 'dir' => array( + 'bar' => array( + ) + ) + ); + vfsStream::create($structure, $this->root); + + $this->assertTrue(file_exists(vfsStream::url('root/').'dir\\')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirTestCase.php new file mode 100644 index 000000000..bd61597a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirTestCase.php @@ -0,0 +1,503 @@ +assertFalse(mkdir(vfsStream::url('another'))); + $this->assertEquals(2, count($this->foo->getChildren())); + $this->assertSame($this->foo, vfsStreamWrapper::getRoot()); + } + + /** + * mkdir() should not overwrite existing root + * + * @test + */ + public function mkdirNoNewRootRecursively() + { + $this->assertFalse(mkdir(vfsStream::url('another/more'), 0777, true)); + $this->assertEquals(2, count($this->foo->getChildren())); + $this->assertSame($this->foo, vfsStreamWrapper::getRoot()); + } + + /** + * assert that mkdir() creates the correct directory structure + * + * @test + * @group permissions + */ + public function mkdirNonRecursively() + { + $this->assertFalse(mkdir($this->barURL . '/another/more')); + $this->assertEquals(2, count($this->foo->getChildren())); + $this->assertTrue(mkdir($this->fooURL . '/another')); + $this->assertEquals(3, count($this->foo->getChildren())); + $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions()); + } + + /** + * assert that mkdir() creates the correct directory structure + * + * @test + * @group permissions + */ + public function mkdirRecursively() + { + $this->assertTrue(mkdir($this->fooURL . '/another/more', 0777, true)); + $this->assertEquals(3, count($this->foo->getChildren())); + $another = $this->foo->getChild('another'); + $this->assertTrue($another->hasChild('more')); + $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions()); + $this->assertEquals(0777, $this->foo->getChild('another')->getChild('more')->getPermissions()); + } + + /** + * @test + * @group issue_9 + * @since 0.9.0 + */ + public function mkdirWithDots() + { + $this->assertTrue(mkdir($this->fooURL . '/another/../more/.', 0777, true)); + $this->assertEquals(3, count($this->foo->getChildren())); + $this->assertTrue($this->foo->hasChild('more')); + } + + /** + * no root > new directory becomes root + * + * @test + * @group permissions + */ + public function mkdirWithoutRootCreatesNewRoot() + { + vfsStreamWrapper::register(); + $this->assertTrue(@mkdir(vfsStream::url('foo'))); + $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType()); + $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName()); + $this->assertEquals(0777, vfsStreamWrapper::getRoot()->getPermissions()); + } + + /** + * trying to create a subdirectory of a file should not work + * + * @test + */ + public function mkdirOnFileReturnsFalse() + { + $this->assertFalse(mkdir($this->baz1URL . '/another/more', 0777, true)); + } + + /** + * assert that mkdir() creates the correct directory structure + * + * @test + * @group permissions + */ + public function mkdirNonRecursivelyDifferentPermissions() + { + $this->assertTrue(mkdir($this->fooURL . '/another', 0755)); + $this->assertEquals(0755, $this->foo->getChild('another')->getPermissions()); + } + + /** + * assert that mkdir() creates the correct directory structure + * + * @test + * @group permissions + */ + public function mkdirRecursivelyDifferentPermissions() + { + $this->assertTrue(mkdir($this->fooURL . '/another/more', 0755, true)); + $this->assertEquals(3, count($this->foo->getChildren())); + $another = $this->foo->getChild('another'); + $this->assertTrue($another->hasChild('more')); + $this->assertEquals(0755, $this->foo->getChild('another')->getPermissions()); + $this->assertEquals(0755, $this->foo->getChild('another')->getChild('more')->getPermissions()); + } + + /** + * assert that mkdir() creates the correct directory structure + * + * @test + * @group permissions + */ + public function mkdirRecursivelyUsesDefaultPermissions() + { + $this->foo->chmod(0700); + $this->assertTrue(mkdir($this->fooURL . '/another/more', 0777, true)); + $this->assertEquals(3, count($this->foo->getChildren())); + $another = $this->foo->getChild('another'); + $this->assertTrue($another->hasChild('more')); + $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions()); + $this->assertEquals(0777, $this->foo->getChild('another')->getChild('more')->getPermissions()); + } + + /** + * no root > new directory becomes root + * + * @test + * @group permissions + */ + public function mkdirWithoutRootCreatesNewRootDifferentPermissions() + { + vfsStreamWrapper::register(); + $this->assertTrue(@mkdir(vfsStream::url('foo'), 0755)); + $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType()); + $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName()); + $this->assertEquals(0755, vfsStreamWrapper::getRoot()->getPermissions()); + } + + /** + * no root > new directory becomes root + * + * @test + * @group permissions + */ + public function mkdirWithoutRootCreatesNewRootWithDefaultPermissions() + { + vfsStreamWrapper::register(); + $this->assertTrue(@mkdir(vfsStream::url('foo'))); + $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType()); + $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName()); + $this->assertEquals(0777, vfsStreamWrapper::getRoot()->getPermissions()); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function mkdirDirCanNotCreateNewDirInNonWritingDirectory() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root')); + vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory('restrictedFolder', 0000)); + $this->assertFalse(is_writable(vfsStream::url('root/restrictedFolder/'))); + $this->assertFalse(mkdir(vfsStream::url('root/restrictedFolder/newFolder'))); + $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('restrictedFolder/newFolder')); + } + + /** + * @test + * @group issue_28 + */ + public function mkDirShouldNotOverwriteExistingDirectories() + { + vfsStream::setup('root'); + $dir = vfsStream::url('root/dir'); + $this->assertTrue(mkdir($dir)); + $this->assertFalse(@mkdir($dir)); + } + + /** + * @test + * @group issue_28 + */ + public function mkDirShouldNotOverwriteExistingDirectoriesAndTriggerE_USER_WARNING() + { + $this->expectException(Error\Warning::class); + $this->expectExceptionMessage('mkdir(): Path vfs://root/dir exists'); + + vfsStream::setup('root'); + $dir = vfsStream::url('root/dir'); + $this->assertTrue(mkdir($dir)); + $this->assertFalse(mkdir($dir)); + } + + /** + * @test + * @group issue_28 + */ + public function mkDirShouldNotOverwriteExistingFiles() + { + $root = vfsStream::setup('root'); + vfsStream::newFile('test.txt')->at($root); + $this->assertFalse(@mkdir(vfsStream::url('root/test.txt'))); + } + + /** + * @test + * @group issue_28 + */ + public function mkDirShouldNotOverwriteExistingFilesAndTriggerE_USER_WARNING() + { + $this->expectException(Error\Warning::class); + $this->expectExceptionMessage('mkdir(): Path vfs://root/test.txt exists'); + $root = vfsStream::setup('root'); + vfsStream::newFile('test.txt')->at($root); + $this->assertFalse(mkdir(vfsStream::url('root/test.txt'))); + } + + /** + * @test + * @group issue_131 + * @since 1.6.3 + */ + public function allowsRecursiveMkDirWithDirectoryName0() + { + vfsStream::setup('root'); + $subdir = vfsStream::url('root/a/0'); + mkdir($subdir, 0777, true); + $this->assertFileExists($subdir); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function canNotIterateOverNonReadableDirectory() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); + $this->assertFalse(@opendir(vfsStream::url('root'))); + $this->assertFalse(@dir(vfsStream::url('root'))); + } + + /** + * assert is_dir() returns correct result + * + * @test + */ + public function is_dir() + { + $this->assertTrue(is_dir($this->fooURL)); + $this->assertTrue(is_dir($this->fooURL . '/.')); + $this->assertTrue(is_dir($this->barURL)); + $this->assertTrue(is_dir($this->barURL . '/.')); + $this->assertFalse(is_dir($this->baz1URL)); + $this->assertFalse(is_dir($this->baz2URL)); + $this->assertFalse(is_dir($this->fooURL . '/another')); + $this->assertFalse(is_dir(vfsStream::url('another'))); + } + + /** + * can not unlink without root + * + * @test + */ + public function canNotUnlinkDirectoryWithoutRoot() + { + vfsStreamWrapper::register(); + $this->assertFalse(@rmdir(vfsStream::url('foo'))); + } + + /** + * rmdir() can not remove files + * + * @test + */ + public function rmdirCanNotRemoveFiles() + { + $this->assertFalse(rmdir($this->baz1URL)); + $this->assertFalse(rmdir($this->baz2URL)); + } + + /** + * rmdir() can not remove a non-existing directory + * + * @test + */ + public function rmdirCanNotRemoveNonExistingDirectory() + { + $this->assertFalse(rmdir($this->fooURL . '/another')); + } + + /** + * rmdir() can not remove non-empty directories + * + * @test + */ + public function rmdirCanNotRemoveNonEmptyDirectory() + { + $this->assertFalse(rmdir($this->fooURL)); + $this->assertFalse(rmdir($this->barURL)); + } + + /** + * @test + */ + public function rmdirCanRemoveEmptyDirectory() + { + vfsStream::newDirectory('empty')->at($this->foo); + $this->assertTrue($this->foo->hasChild('empty')); + $this->assertTrue(rmdir($this->fooURL . '/empty')); + $this->assertFalse($this->foo->hasChild('empty')); + } + + /** + * @test + */ + public function rmdirCanRemoveEmptyDirectoryWithDot() + { + vfsStream::newDirectory('empty')->at($this->foo); + $this->assertTrue($this->foo->hasChild('empty')); + $this->assertTrue(rmdir($this->fooURL . '/empty/.')); + $this->assertFalse($this->foo->hasChild('empty')); + } + + /** + * rmdir() can remove empty directories + * + * @test + */ + public function rmdirCanRemoveEmptyRoot() + { + $this->foo->removeChild('bar'); + $this->foo->removeChild('baz2'); + $this->assertTrue(rmdir($this->fooURL)); + $this->assertFalse(file_exists($this->fooURL)); // make sure statcache was cleared + $this->assertNull(vfsStreamWrapper::getRoot()); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function rmdirDirCanNotRemoveDirFromNonWritingDirectory() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); + vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory('nonRemovableFolder')); + $this->assertFalse(is_writable(vfsStream::url('root'))); + $this->assertFalse(rmdir(vfsStream::url('root/nonRemovableFolder'))); + $this->assertTrue(vfsStreamWrapper::getRoot()->hasChild('nonRemovableFolder')); + } + + /** + * @test + * @group permissions + * @group bug_17 + */ + public function issue17() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0770)); + vfsStreamWrapper::getRoot()->chgrp(vfsStream::GROUP_USER_1) + ->chown(vfsStream::OWNER_USER_1); + $this->assertFalse(mkdir(vfsStream::url('root/doesNotWork'))); + $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('doesNotWork')); + } + + /** + * @test + * @group bug_19 + */ + public function accessWithDoubleDotReturnsCorrectContent() + { + $this->assertEquals('baz2', + file_get_contents(vfsStream::url('foo/bar/../baz2')) + ); + } + + /** + * @test + * @group bug_115 + */ + public function accessWithExcessDoubleDotsReturnsCorrectContent() + { + $this->assertEquals('baz2', + file_get_contents(vfsStream::url('foo/../../../../bar/../baz2')) + ); + } + + /** + * @test + * @group bug_115 + */ + public function alwaysResolvesRootDirectoryAsOwnParentWithDoubleDot() + { + vfsStreamWrapper::getRoot()->chown(vfsStream::OWNER_USER_1); + + $this->assertTrue(is_dir(vfsStream::url('foo/..'))); + $stat = stat(vfsStream::url('foo/..')); + $this->assertEquals( + vfsStream::OWNER_USER_1, + $stat['uid'] + ); + } + + + /** + * @test + * @since 0.11.0 + * @group issue_23 + */ + public function unlinkCanNotRemoveNonEmptyDirectory() + { + try { + $this->assertFalse(unlink($this->barURL)); + } catch (\PHPUnit_Framework_Error $fe) { + $this->assertEquals('unlink(vfs://foo/bar): Operation not permitted', $fe->getMessage()); + } + + $this->assertTrue($this->foo->hasChild('bar')); + $this->assertFileExists($this->barURL); + } + + /** + * @test + * @since 0.11.0 + * @group issue_23 + */ + public function unlinkCanNotRemoveEmptyDirectory() + { + vfsStream::newDirectory('empty')->at($this->foo); + try { + $this->assertTrue(unlink($this->fooURL . '/empty')); + } catch (\PHPUnit_Framework_Error $fe) { + $this->assertEquals('unlink(vfs://foo/empty): Operation not permitted', $fe->getMessage()); + } + + $this->assertTrue($this->foo->hasChild('empty')); + $this->assertFileExists($this->fooURL . '/empty'); + } + + /** + * @test + * @group issue_32 + */ + public function canCreateFolderOfSameNameAsParentFolder() + { + $root = vfsStream::setup('testFolder'); + mkdir(vfsStream::url('testFolder') . '/testFolder/subTestFolder', 0777, true); + $this->assertTrue(file_exists(vfsStream::url('testFolder/testFolder/subTestFolder/.'))); + } + + /** + * @test + * @group issue_32 + */ + public function canRetrieveFolderOfSameNameAsParentFolder() + { + $root = vfsStream::setup('testFolder'); + mkdir(vfsStream::url('testFolder') . '/testFolder/subTestFolder', 0777, true); + $this->assertTrue($root->hasChild('testFolder')); + $this->assertNotNull($root->getChild('testFolder')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTestCase.php new file mode 100644 index 000000000..3ac9fb8e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTestCase.php @@ -0,0 +1,457 @@ +assertEquals('baz2', file_get_contents($this->baz2URL)); + $this->assertEquals('baz 1', file_get_contents($this->baz1URL)); + $this->assertFalse(@file_get_contents($this->barURL)); + $this->assertFalse(@file_get_contents($this->fooURL)); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function file_get_contentsNonReadableFile() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root')); + vfsStream::newFile('new.txt', 0000)->at(vfsStreamWrapper::getRoot())->withContent('content'); + $this->assertEquals('', @file_get_contents(vfsStream::url('root/new.txt'))); + } + + /** + * assert that file_put_contents() delivers correct file contents + * + * @test + */ + public function file_put_contentsExistingFile() + { + $this->assertEquals(14, file_put_contents($this->baz2URL, 'baz is not bar')); + $this->assertEquals('baz is not bar', $this->baz2->getContent()); + $this->assertEquals(6, file_put_contents($this->baz1URL, 'foobar')); + $this->assertEquals('foobar', $this->baz1->getContent()); + $this->assertFalse(@file_put_contents($this->barURL, 'This does not work.')); + $this->assertFalse(@file_put_contents($this->fooURL, 'This does not work, too.')); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function file_put_contentsExistingFileNonWritableDirectory() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); + vfsStream::newFile('new.txt')->at(vfsStreamWrapper::getRoot())->withContent('content'); + $this->assertEquals(15, @file_put_contents(vfsStream::url('root/new.txt'), 'This does work.')); + $this->assertEquals('This does work.', file_get_contents(vfsStream::url('root/new.txt'))); + + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function file_put_contentsExistingNonWritableFile() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root')); + vfsStream::newFile('new.txt', 0400)->at(vfsStreamWrapper::getRoot())->withContent('content'); + $this->assertFalse(@file_put_contents(vfsStream::url('root/new.txt'), 'This does not work.')); + $this->assertEquals('content', file_get_contents(vfsStream::url('root/new.txt'))); + } + + /** + * assert that file_put_contents() delivers correct file contents + * + * @test + */ + public function file_put_contentsNonExistingFile() + { + $this->assertEquals(14, file_put_contents($this->fooURL . '/baznot.bar', 'baz is not bar')); + $this->assertEquals(3, count($this->foo->getChildren())); + $this->assertEquals(14, file_put_contents($this->barURL . '/baznot.bar', 'baz is not bar')); + $this->assertEquals(2, count($this->bar->getChildren())); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function file_put_contentsNonExistingFileNonWritableDirectory() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); + $this->assertFalse(@file_put_contents(vfsStream::url('root/new.txt'), 'This does not work.')); + $this->assertFalse(file_exists(vfsStream::url('root/new.txt'))); + + } + + /** + * using a file pointer should work without any problems + * + * @test + */ + public function usingFilePointer() + { + $fp = fopen($this->baz1URL, 'r'); + $this->assertEquals(0, ftell($fp)); + $this->assertFalse(feof($fp)); + $this->assertEquals(0, fseek($fp, 2)); + $this->assertEquals(2, ftell($fp)); + $this->assertEquals(0, fseek($fp, 1, SEEK_CUR)); + $this->assertEquals(3, ftell($fp)); + $this->assertEquals(0, fseek($fp, 1, SEEK_END)); + $this->assertEquals(6, ftell($fp)); + $this->assertTrue(feof($fp)); + $this->assertEquals(0, fseek($fp, 2)); + $this->assertFalse(feof($fp)); + $this->assertEquals(2, ftell($fp)); + $this->assertEquals('z', fread($fp, 1)); + $this->assertEquals(3, ftell($fp)); + $this->assertEquals(' 1', fread($fp, 8092)); + $this->assertEquals(5, ftell($fp)); + $this->assertTrue(fclose($fp)); + } + + /** + * assert is_file() returns correct result + * + * @test + */ + public function is_file() + { + $this->assertFalse(is_file($this->fooURL)); + $this->assertFalse(is_file($this->barURL)); + $this->assertTrue(is_file($this->baz1URL)); + $this->assertTrue(is_file($this->baz2URL)); + $this->assertFalse(is_file($this->fooURL . '/another')); + $this->assertFalse(is_file(vfsStream::url('another'))); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function issue13CanNotOverwriteFiles() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + file_put_contents($vfsFile, 'd'); + $this->assertEquals('d', file_get_contents($vfsFile)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function appendContentIfOpenedWithModeA() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $fp = fopen($vfsFile, 'ab'); + fwrite($fp, 'd'); + fclose($fp); + $this->assertEquals('testd', file_get_contents($vfsFile)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canOverwriteNonExistingFileWithModeX() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + $fp = fopen($vfsFile, 'xb'); + fwrite($fp, 'test'); + fclose($fp); + $this->assertEquals('test', file_get_contents($vfsFile)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotOverwriteExistingFileWithModeX() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $this->assertFalse(@fopen($vfsFile, 'xb')); + $this->assertEquals('test', file_get_contents($vfsFile)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotOpenNonExistingFileReadonly() + { + $this->assertFalse(@fopen(vfsStream::url('foo/doesNotExist.txt'), 'rb')); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotOpenNonExistingFileReadAndWrite() + { + $this->assertFalse(@fopen(vfsStream::url('foo/doesNotExist.txt'), 'rb+')); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotOpenWithIllegalMode() + { + $this->assertFalse(@fopen($this->baz2URL, 'invalid')); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotWriteToReadOnlyFile() + { + $fp = fopen($this->baz2URL, 'rb'); + $this->assertEquals('baz2', fread($fp, 4096)); + $this->assertEquals(0, fwrite($fp, 'foo')); + fclose($fp); + $this->assertEquals('baz2', file_get_contents($this->baz2URL)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotReadFromWriteOnlyFileWithModeW() + { + $fp = fopen($this->baz2URL, 'wb'); + $this->assertEquals('', fread($fp, 4096)); + $this->assertEquals(3, fwrite($fp, 'foo')); + fseek($fp, 0); + $this->assertEquals('', fread($fp, 4096)); + fclose($fp); + $this->assertEquals('foo', file_get_contents($this->baz2URL)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotReadFromWriteOnlyFileWithModeA() + { + $fp = fopen($this->baz2URL, 'ab'); + $this->assertEquals('', fread($fp, 4096)); + $this->assertEquals(3, fwrite($fp, 'foo')); + fseek($fp, 0); + $this->assertEquals('', fread($fp, 4096)); + fclose($fp); + $this->assertEquals('baz2foo', file_get_contents($this->baz2URL)); + } + + /** + * @test + * @group issue7 + * @group issue13 + */ + public function canNotReadFromWriteOnlyFileWithModeX() + { + $vfsFile = vfsStream::url('foo/modeXtest.txt'); + $fp = fopen($vfsFile, 'xb'); + $this->assertEquals('', fread($fp, 4096)); + $this->assertEquals(3, fwrite($fp, 'foo')); + fseek($fp, 0); + $this->assertEquals('', fread($fp, 4096)); + fclose($fp); + $this->assertEquals('foo', file_get_contents($vfsFile)); + } + + /** + * @test + * @group permissions + * @group bug_15 + */ + public function canNotRemoveFileFromDirectoryWithoutWritePermissions() + { + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000)); + vfsStream::newFile('new.txt')->at(vfsStreamWrapper::getRoot()); + $this->assertFalse(unlink(vfsStream::url('root/new.txt'))); + $this->assertTrue(file_exists(vfsStream::url('root/new.txt'))); + } + + /** + * @test + * @group issue_30 + */ + public function truncatesFileWhenOpenedWithModeW() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $fp = fopen($vfsFile, 'wb'); + $this->assertEquals('', file_get_contents($vfsFile)); + fclose($fp); + } + + /** + * @test + * @group issue_30 + */ + public function createsNonExistingFileWhenOpenedWithModeC() + { + $vfsFile = vfsStream::url('foo/tobecreated.txt'); + $fp = fopen($vfsFile, 'cb'); + fwrite($fp, 'some content'); + $this->assertTrue($this->foo->hasChild('tobecreated.txt')); + fclose($fp); + $this->assertEquals('some content', file_get_contents($vfsFile)); + } + + /** + * @test + * @group issue_30 + */ + public function createsNonExistingFileWhenOpenedWithModeCplus() + { + $vfsFile = vfsStream::url('foo/tobecreated.txt'); + $fp = fopen($vfsFile, 'cb+'); + fwrite($fp, 'some content'); + $this->assertTrue($this->foo->hasChild('tobecreated.txt')); + fclose($fp); + $this->assertEquals('some content', file_get_contents($vfsFile)); + } + + /** + * @test + * @group issue_30 + */ + public function doesNotTruncateFileWhenOpenedWithModeC() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $fp = fopen($vfsFile, 'cb'); + $this->assertEquals('test', file_get_contents($vfsFile)); + fclose($fp); + } + + /** + * @test + * @group issue_30 + */ + public function setsPointerToStartWhenOpenedWithModeC() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $fp = fopen($vfsFile, 'cb'); + $this->assertEquals(0, ftell($fp)); + fclose($fp); + } + + /** + * @test + * @group issue_30 + */ + public function doesNotTruncateFileWhenOpenedWithModeCplus() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $fp = fopen($vfsFile, 'cb+'); + $this->assertEquals('test', file_get_contents($vfsFile)); + fclose($fp); + } + + /** + * @test + * @group issue_30 + */ + public function setsPointerToStartWhenOpenedWithModeCplus() + { + $vfsFile = vfsStream::url('foo/overwrite.txt'); + file_put_contents($vfsFile, 'test'); + $fp = fopen($vfsFile, 'cb+'); + $this->assertEquals(0, ftell($fp)); + fclose($fp); + } + + /** + * @test + */ + public function cannotOpenExistingNonwritableFileWithModeA() + { + $this->baz1->chmod(0400); + $this->assertFalse(@fopen($this->baz1URL, 'a')); + } + + /** + * @test + */ + public function cannotOpenExistingNonwritableFileWithModeW() + { + $this->baz1->chmod(0400); + $this->assertFalse(@fopen($this->baz1URL, 'w')); + } + + /** + * @test + */ + public function cannotOpenNonReadableFileWithModeR() + { + $this->baz1->chmod(0); + $this->assertFalse(@fopen($this->baz1URL, 'r')); + } + + /** + * @test + */ + public function cannotRenameToNonWritableDir() + { + $this->bar->chmod(0); + $this->assertFalse(@rename($this->baz2URL, vfsStream::url('foo/bar/baz3'))); + } + + /** + * @test + * @group issue_38 + */ + public function cannotReadFileFromNonReadableDir() + { + $this->markTestSkipped("Issue #38."); + $this->bar->chmod(0); + $this->assertFalse(@file_get_contents($this->baz1URL)); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTimesTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTimesTestCase.php new file mode 100644 index 000000000..f58b6bcaf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTimesTestCase.php @@ -0,0 +1,314 @@ +lastModified(50) + ->lastAccessed(50) + ->lastAttributeModified(50); + $this->fooUrl = vfsStream::url('root/foo.txt'); + $this->barUrl = vfsStream::url('root/bar'); + $this->bazUrl = vfsStream::url('root/bar/baz.txt'); + } + + /** + * helper assertion for the tests + * + * @param string $url url to check + * @param vfsStreamContent $content content to compare + */ + protected function assertFileTimesEqualStreamTimes($url, vfsStreamContent $content) + { + $this->assertEquals(filemtime($url), $content->filemtime()); + $this->assertEquals(fileatime($url), $content->fileatime()); + $this->assertEquals(filectime($url), $content->filectime()); + } + + /** + * @test + * @group issue_7 + * @group issue_26 + */ + public function openFileChangesAttributeTimeOnly() + { + $file = vfsStream::newFile('foo.txt') + ->withContent('test') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + fclose(fopen($this->fooUrl, 'rb')); + $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl)); + $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl)); + $this->assertLessThanOrEqual(100, filemtime($this->fooUrl)); + $this->assertEquals(100, filectime($this->fooUrl)); + $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); + } + + /** + * @test + * @group issue_7 + * @group issue_26 + */ + public function fileGetContentsChangesAttributeTimeOnly() + { + $file = vfsStream::newFile('foo.txt') + ->withContent('test') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + file_get_contents($this->fooUrl); + $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl)); + $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl)); + $this->assertLessThanOrEqual(100, filemtime($this->fooUrl)); + $this->assertEquals(100, filectime($this->fooUrl)); + $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); + } + + /** + * @test + * @group issue_7 + * @group issue_26 + */ + public function openFileWithTruncateChangesAttributeAndModificationTime() + { + $file = vfsStream::newFile('foo.txt') + ->withContent('test') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + fclose(fopen($this->fooUrl, 'wb')); + $this->assertGreaterThan(time() - 2, filemtime($this->fooUrl)); + $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl)); + $this->assertLessThanOrEqual(time(), filemtime($this->fooUrl)); + $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl)); + $this->assertEquals(100, filectime($this->fooUrl)); + $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); + } + + /** + * @test + * @group issue_7 + */ + public function readFileChangesAccessTime() + { + $file = vfsStream::newFile('foo.txt') + ->withContent('test') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + $fp = fopen($this->fooUrl, 'rb'); + $openTime = time(); + sleep(2); + fread($fp, 1024); + fclose($fp); + $this->assertLessThanOrEqual($openTime, filemtime($this->fooUrl)); + $this->assertLessThanOrEqual($openTime + 3, fileatime($this->fooUrl)); + $this->assertEquals(100, filectime($this->fooUrl)); + $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); + } + + /** + * @test + * @group issue_7 + */ + public function writeFileChangesModificationTime() + { + $file = vfsStream::newFile('foo.txt') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + $fp = fopen($this->fooUrl, 'wb'); + $openTime = time(); + sleep(2); + fwrite($fp, 'test'); + fclose($fp); + $this->assertLessThanOrEqual($openTime + 3, filemtime($this->fooUrl)); + $this->assertLessThanOrEqual($openTime, fileatime($this->fooUrl)); + $this->assertEquals(100, filectime($this->fooUrl)); + $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file); + + } + + /** + * @test + * @group issue_7 + */ + public function createNewFileSetsAllTimesToCurrentTime() + { + file_put_contents($this->fooUrl, 'test'); + $this->assertLessThanOrEqual(time(), filemtime($this->fooUrl)); + $this->assertEquals(fileatime($this->fooUrl), filectime($this->fooUrl)); + $this->assertEquals(fileatime($this->fooUrl), filemtime($this->fooUrl)); + $this->assertFileTimesEqualStreamTimes($this->fooUrl, vfsStreamWrapper::getRoot()->getChild('foo.txt')); + } + + /** + * @test + * @group issue_7 + */ + public function createNewFileChangesAttributeAndModificationTimeOfContainingDirectory() + { + $dir = vfsStream::newDirectory('bar') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + file_put_contents($this->bazUrl, 'test'); + $this->assertLessThanOrEqual(time(), filemtime($this->barUrl)); + $this->assertLessThanOrEqual(time(), filectime($this->barUrl)); + $this->assertEquals(100, fileatime($this->barUrl)); + $this->assertFileTimesEqualStreamTimes($this->barUrl, $dir); + } + + /** + * @test + * @group issue_7 + */ + public function addNewFileNameWithLinkFunctionChangesAttributeTimeOfOriginalFile() + { + $this->markTestSkipped('Links are currently not supported by vfsStream.'); + } + + /** + * @test + * @group issue_7 + */ + public function addNewFileNameWithLinkFunctionChangesAttributeAndModificationTimeOfDirectoryContainingLink() + { + $this->markTestSkipped('Links are currently not supported by vfsStream.'); + } + + /** + * @test + * @group issue_7 + */ + public function removeFileChangesAttributeAndModificationTimeOfContainingDirectory() + { + $dir = vfsStream::newDirectory('bar') + ->at(vfsStreamWrapper::getRoot()); + $file = vfsStream::newFile('baz.txt') + ->at($dir) + ->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + $dir->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + unlink($this->bazUrl); + $this->assertLessThanOrEqual(time(), filemtime($this->barUrl)); + $this->assertLessThanOrEqual(time(), filectime($this->barUrl)); + $this->assertEquals(100, fileatime($this->barUrl)); + $this->assertFileTimesEqualStreamTimes($this->barUrl, $dir); + } + + /** + * @test + * @group issue_7 + */ + public function renameFileChangesAttributeAndModificationTimeOfAffectedDirectories() + { + $target = vfsStream::newDirectory('target') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(200) + ->lastAccessed(200) + ->lastAttributeModified(200); + $source = vfsStream::newDirectory('bar') + ->at(vfsStreamWrapper::getRoot()); + $file = vfsStream::newFile('baz.txt') + ->at($source) + ->lastModified(300) + ->lastAccessed(300) + ->lastAttributeModified(300); + $source->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + rename($this->bazUrl, vfsStream::url('root/target/baz.txt')); + $this->assertLessThanOrEqual(time(), filemtime($this->barUrl)); + $this->assertLessThanOrEqual(time(), filectime($this->barUrl)); + $this->assertEquals(100, fileatime($this->barUrl)); + $this->assertFileTimesEqualStreamTimes($this->barUrl, $source); + $this->assertLessThanOrEqual(time(), filemtime(vfsStream::url('root/target'))); + $this->assertLessThanOrEqual(time(), filectime(vfsStream::url('root/target'))); + $this->assertEquals(200, fileatime(vfsStream::url('root/target'))); + $this->assertFileTimesEqualStreamTimes(vfsStream::url('root/target'), $target); + } + + /** + * @test + * @group issue_7 + */ + public function renameFileDoesNotChangeFileTimesOfFileItself() + { + $target = vfsStream::newDirectory('target') + ->at(vfsStreamWrapper::getRoot()) + ->lastModified(200) + ->lastAccessed(200) + ->lastAttributeModified(200); + $source = vfsStream::newDirectory('bar') + ->at(vfsStreamWrapper::getRoot()); + $file = vfsStream::newFile('baz.txt') + ->at($source) + ->lastModified(300) + ->lastAccessed(300) + ->lastAttributeModified(300); + $source->lastModified(100) + ->lastAccessed(100) + ->lastAttributeModified(100); + rename($this->bazUrl, vfsStream::url('root/target/baz.txt')); + $this->assertEquals(300, filemtime(vfsStream::url('root/target/baz.txt'))); + $this->assertEquals(300, filectime(vfsStream::url('root/target/baz.txt'))); + $this->assertEquals(300, fileatime(vfsStream::url('root/target/baz.txt'))); + $this->assertFileTimesEqualStreamTimes(vfsStream::url('root/target/baz.txt'), $file); + } + + /** + * @test + * @group issue_7 + */ + public function changeFileAttributesChangesAttributeTimeOfFileItself() + { + $this->markTestSkipped('Changing file attributes via stream wrapper for self-defined streams is not supported by PHP.'); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFlockTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFlockTestCase.php new file mode 100644 index 000000000..114dd48c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFlockTestCase.php @@ -0,0 +1,439 @@ +root = vfsStream::setup(); + } + + /** + * @test + */ + public function fileIsNotLockedByDefault() + { + $this->assertFalse(vfsStream::newFile('foo.txt')->isLocked()); + } + + /** + * @test + */ + public function streamIsNotLockedByDefault() + { + file_put_contents(vfsStream::url('root/foo.txt'), 'content'); + $this->assertFalse($this->root->getChild('foo.txt')->isLocked()); + } + + /** + * @test + */ + public function canAquireSharedLock() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertTrue(flock($fp, LOCK_SH)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp); + + } + + /** + * @test + */ + public function canAquireSharedLockWithNonBlockingFlockCall() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertTrue(flock($fp, LOCK_SH | LOCK_NB)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp); + + } + + /** + * @test + */ + public function canAquireEclusiveLock() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertTrue(flock($fp, LOCK_EX)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @test + */ + public function canAquireEclusiveLockWithNonBlockingFlockCall() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertTrue(flock($fp, LOCK_EX | LOCK_NB)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @test + */ + public function canRemoveLock() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_EX); + $this->assertTrue(flock($fp, LOCK_UN)); + $this->assertFalse($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canRemoveLockWhenNotLocked() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertTrue(flock($fp, LOCK_UN)); + $this->assertFalse($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertFalse($file->hasSharedLock($fp)); + $this->assertFalse($file->hasExclusiveLock()); + $this->assertFalse($file->hasExclusiveLock($fp)); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canRemoveSharedLockWithoutRemovingSharedLockOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_SH); + $file->lock($fp2, LOCK_SH); + $this->assertTrue(flock($fp1, LOCK_UN)); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasSharedLock($fp1)); + $this->assertTrue($file->hasSharedLock($fp2)); + fclose($fp1); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canNotRemoveSharedLockAcquiredOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_SH); + $this->assertTrue(flock($fp2, LOCK_UN)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp1); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canNotRemoveExlusiveLockAcquiredOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_EX); + $this->assertTrue(flock($fp2, LOCK_UN)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + fclose($fp1); + fclose($fp2); + } + + /** + * @test + */ + public function canRemoveLockWithNonBlockingFlockCall() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_EX); + $this->assertTrue(flock($fp, LOCK_UN | LOCK_NB)); + $this->assertFalse($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canNotAquireExclusiveLockIfAlreadyExclusivelyLockedOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_EX); + $this->assertFalse(flock($fp2, LOCK_EX + LOCK_NB)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + $this->assertTrue($file->hasExclusiveLock($fp1)); + $this->assertFalse($file->hasExclusiveLock($fp2)); + fclose($fp1); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canAquireExclusiveLockIfAlreadySelfExclusivelyLocked() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_EX); + $this->assertTrue(flock($fp, LOCK_EX + LOCK_NB)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canNotAquireExclusiveLockIfAlreadySharedLockedOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_SH); + $this->assertFalse(flock($fp2, LOCK_EX)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp1); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canAquireExclusiveLockIfAlreadySelfSharedLocked() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_SH); + $this->assertTrue(flock($fp, LOCK_EX)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canNotAquireSharedLockIfAlreadyExclusivelyLockedOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_EX); + $this->assertFalse(flock($fp2, LOCK_SH + LOCK_NB)); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + fclose($fp1); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canAquireSharedLockIfAlreadySelfExclusivelyLocked() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_EX); + $this->assertTrue(flock($fp, LOCK_SH + LOCK_NB)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canAquireSharedLockIfAlreadySelfSharedLocked() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_SH); + $this->assertTrue(flock($fp, LOCK_SH)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function canAquireSharedLockIfAlreadySharedLockedOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp1, LOCK_SH); + $this->assertTrue(flock($fp2, LOCK_SH)); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertTrue($file->hasSharedLock($fp1)); + $this->assertTrue($file->hasSharedLock($fp2)); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp1); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/31 + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_31 + * @group issue_40 + */ + public function removesExclusiveLockOnStreamClose() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_EX); + fclose($fp); + $this->assertFalse($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/31 + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_31 + * @group issue_40 + */ + public function removesSharedLockOnStreamClose() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp, LOCK_SH); + fclose($fp); + $this->assertFalse($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertFalse($file->hasExclusiveLock()); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function notRemovesExclusiveLockOnStreamCloseIfExclusiveLockAcquiredOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp2, LOCK_EX); + fclose($fp1); + $this->assertTrue($file->isLocked()); + $this->assertFalse($file->hasSharedLock()); + $this->assertTrue($file->hasExclusiveLock()); + $this->assertTrue($file->hasExclusiveLock($fp2)); + fclose($fp2); + } + + /** + * @see https://github.com/mikey179/vfsStream/issues/40 + * @test + * @group issue_40 + */ + public function notRemovesSharedLockOnStreamCloseIfSharedLockAcquiredOnOtherFileHandler() + { + $file = vfsStream::newFile('foo.txt')->at($this->root); + $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $file->lock($fp2, LOCK_SH); + fclose($fp1); + $this->assertTrue($file->isLocked()); + $this->assertTrue($file->hasSharedLock()); + $this->assertTrue($file->hasSharedLock($fp2)); + $this->assertFalse($file->hasExclusiveLock()); + fclose($fp2); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperLargeFileTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperLargeFileTestCase.php new file mode 100644 index 000000000..d6ae211ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperLargeFileTestCase.php @@ -0,0 +1,81 @@ +largeFile = vfsStream::newFile('large.txt') + ->withContent(LargeFileContent::withGigabytes(100)) + ->at($root); + } + + /** + * @test + */ + public function hasLargeFileSize() + { + if (PHP_INT_MAX == 2147483647) { + $this->markTestSkipped('Requires 64-bit version of PHP'); + } + + $this->assertEquals( + 100 * 1024 * 1024 * 1024, + filesize($this->largeFile->url()) + ); + } + + /** + * @test + */ + public function canReadFromLargeFile() + { + $fp = fopen($this->largeFile->url(), 'rb'); + $data = fread($fp, 15); + fclose($fp); + $this->assertEquals(str_repeat(' ', 15), $data); + } + + /** + * @test + */ + public function canWriteIntoLargeFile() + { + $fp = fopen($this->largeFile->url(), 'rb+'); + fseek($fp, 100 * 1024 * 1024, SEEK_SET); + fwrite($fp, 'foobarbaz'); + fclose($fp); + $this->largeFile->seek((100 * 1024 * 1024) - 3, SEEK_SET); + $this->assertEquals( + ' foobarbaz ', + $this->largeFile->read(15) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperQuotaTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperQuotaTestCase.php new file mode 100644 index 000000000..574ab9f84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperQuotaTestCase.php @@ -0,0 +1,223 @@ +root = vfsStream::setup(); + vfsStream::setQuota(10); + } + + /** + * @test + */ + public function writeLessThanQuotaWritesEverything() + { + $this->assertEquals(9, file_put_contents(vfsStream::url('root/file.txt'), '123456789')); + $this->assertEquals('123456789', $this->root->getChild('file.txt')->getContent()); + } + + /** + * @test + */ + public function writeUpToQotaWritesEverything() + { + $this->assertEquals(10, file_put_contents(vfsStream::url('root/file.txt'), '1234567890')); + $this->assertEquals('1234567890', $this->root->getChild('file.txt')->getContent()); + } + + /** + * @test + */ + public function writeMoreThanQotaWritesOnlyUpToQuota() + { + try { + file_put_contents(vfsStream::url('root/file.txt'), '12345678901'); + } catch (\PHPUnit_Framework_Error $e) { + $this->assertEquals('file_put_contents(): Only 10 of 11 bytes written, possibly out of free disk space', + $e->getMessage() + ); + } + + $this->assertEquals('1234567890', $this->root->getChild('file.txt')->getContent()); + } + + /** + * @test + */ + public function considersAllFilesForQuota() + { + vfsStream::newFile('foo.txt') + ->withContent('foo') + ->at(vfsStream::newDirectory('bar') + ->at($this->root) + ); + try { + file_put_contents(vfsStream::url('root/file.txt'), '12345678901'); + } catch (\PHPUnit_Framework_Error $e) { + $this->assertEquals('file_put_contents(): Only 7 of 11 bytes written, possibly out of free disk space', + $e->getMessage() + ); + } + + $this->assertEquals('1234567', $this->root->getChild('file.txt')->getContent()); + } + + /** + * @test + * @group issue_33 + */ + public function truncateToLessThanQuotaWritesEverything() + { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); + $this->assertTrue(ftruncate($fp, 9)); + fclose($fp); + $this->assertEquals(9, + $this->root->getChild('file.txt')->size() + ); + $this->assertEquals("\0\0\0\0\0\0\0\0\0", + $this->root->getChild('file.txt')->getContent() + ); + } + + /** + * @test + * @group issue_33 + */ + public function truncateUpToQotaWritesEverything() + { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); + $this->assertTrue(ftruncate($fp, 10)); + fclose($fp); + $this->assertEquals(10, + $this->root->getChild('file.txt')->size() + ); + $this->assertEquals("\0\0\0\0\0\0\0\0\0\0", + $this->root->getChild('file.txt')->getContent() + ); + } + + /** + * @test + * @group issue_33 + */ + public function truncateToMoreThanQotaWritesOnlyUpToQuota() + { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); + $this->assertTrue(ftruncate($fp, 11)); + fclose($fp); + $this->assertEquals(10, + $this->root->getChild('file.txt')->size() + ); + $this->assertEquals("\0\0\0\0\0\0\0\0\0\0", + $this->root->getChild('file.txt')->getContent() + ); + } + + /** + * @test + * @group issue_33 + */ + public function truncateConsidersAllFilesForQuota() + { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + vfsStream::newFile('bar.txt') + ->withContent('bar') + ->at(vfsStream::newDirectory('bar') + ->at($this->root) + ); + $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); + $this->assertTrue(ftruncate($fp, 11)); + fclose($fp); + $this->assertEquals(7, + $this->root->getChild('file.txt')->size() + ); + $this->assertEquals("\0\0\0\0\0\0\0", + $this->root->getChild('file.txt')->getContent() + ); + } + + /** + * @test + * @group issue_33 + */ + public function canNotTruncateToGreaterLengthWhenDiscQuotaReached() + { + if (version_compare(PHP_VERSION, '5.4.0', '<')) { + $this->markTestSkipped('Requires PHP 5.4'); + } + + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + vfsStream::newFile('bar.txt') + ->withContent('1234567890') + ->at(vfsStream::newDirectory('bar') + ->at($this->root) + ); + $fp = fopen(vfsStream::url('root/file.txt'), 'w+'); + $this->assertFalse(ftruncate($fp, 11)); + fclose($fp); + $this->assertEquals(0, + $this->root->getChild('file.txt')->size() + ); + $this->assertEquals('', + $this->root->getChild('file.txt')->getContent() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperSetOptionTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperSetOptionTestCase.php new file mode 100644 index 000000000..8f232b7bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperSetOptionTestCase.php @@ -0,0 +1,75 @@ +root = vfsStream::setup(); + vfsStream::newFile('foo.txt')->at($this->root); + } + + /** + * @test + */ + public function setBlockingDoesNotWork() + { + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertFalse(stream_set_blocking($fp, 1)); + fclose($fp); + } + + /** + * @test + */ + public function removeBlockingDoesNotWork() + { + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertFalse(stream_set_blocking($fp, 0)); + fclose($fp); + } + + /** + * @test + */ + public function setTimeoutDoesNotWork() + { + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertFalse(stream_set_timeout($fp, 1)); + fclose($fp); + } + + /** + * @test + */ + public function setWriteBufferDoesNotWork() + { + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $this->assertEquals(-1, stream_set_write_buffer($fp, 512)); + fclose($fp); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperStreamSelectTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperStreamSelectTestCase.php new file mode 100644 index 000000000..fd1c26c6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperStreamSelectTestCase.php @@ -0,0 +1,42 @@ += 80000) + { + $this->bc_expectException('\ValueError'); + } + else + { + $this->bc_expectException('\PHPUnit_Framework_Error'); + } + + $root = vfsStream::setup(); + $file = vfsStream::newFile('foo.txt')->at($root)->withContent('testContent'); + + $fp = fopen(vfsStream::url('root/foo.txt'), 'rb'); + $readarray = array($fp); + $writearray = array(); + $exceptarray = array(); + stream_select($readarray, $writearray, $exceptarray, 1); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperTestCase.php new file mode 100644 index 000000000..b99196389 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperTestCase.php @@ -0,0 +1,791 @@ +assertSame($this->foo, vfsStreamWrapper::getRoot()); + vfsStreamWrapper::register(); + $this->assertNull(vfsStreamWrapper::getRoot()); + } + + /** + * @test + * @since 0.11.0 + */ + public function setRootReturnsRoot() + { + vfsStreamWrapper::register(); + $root = vfsStream::newDirectory('root'); + $this->assertSame($root, vfsStreamWrapper::setRoot($root)); + } + + /** + * assure that filesize is returned correct + * + * @test + */ + public function filesize() + { + $this->assertEquals(0, filesize($this->fooURL)); + $this->assertEquals(0, filesize($this->fooURL . '/.')); + $this->assertEquals(0, filesize($this->barURL)); + $this->assertEquals(0, filesize($this->barURL . '/.')); + $this->assertEquals(4, filesize($this->baz2URL)); + $this->assertEquals(5, filesize($this->baz1URL)); + } + + /** + * assert that file_exists() delivers correct result + * + * @test + */ + public function file_exists() + { + $this->assertTrue(file_exists($this->fooURL)); + $this->assertTrue(file_exists($this->fooURL . '/.')); + $this->assertTrue(file_exists($this->barURL)); + $this->assertTrue(file_exists($this->barURL . '/.')); + $this->assertTrue(file_exists($this->baz1URL)); + $this->assertTrue(file_exists($this->baz2URL)); + $this->assertFalse(file_exists($this->fooURL . '/another')); + $this->assertFalse(file_exists(vfsStream::url('another'))); + } + + /** + * assert that filemtime() delivers correct result + * + * @test + */ + public function filemtime() + { + $this->assertEquals(100, filemtime($this->fooURL)); + $this->assertEquals(100, filemtime($this->fooURL . '/.')); + $this->assertEquals(200, filemtime($this->barURL)); + $this->assertEquals(200, filemtime($this->barURL . '/.')); + $this->assertEquals(300, filemtime($this->baz1URL)); + $this->assertEquals(400, filemtime($this->baz2URL)); + } + + /** + * @test + * @group issue_23 + */ + public function unlinkRemovesFilesOnly() + { + $this->assertTrue(unlink($this->baz2URL)); + $this->assertFalse(file_exists($this->baz2URL)); // make sure statcache was cleared + $this->assertEquals(array($this->bar), $this->foo->getChildren()); + $this->assertFalse(@unlink($this->fooURL . '/another')); + $this->assertFalse(@unlink(vfsStream::url('another'))); + $this->assertEquals(array($this->bar), $this->foo->getChildren()); + } + + /** + * @test + * @group issue_49 + */ + public function unlinkReturnsFalseWhenFileDoesNotExist() + { + vfsStream::setup()->addChild(vfsStream::newFile('foo.blubb')); + $this->assertFalse(@unlink(vfsStream::url('foo.blubb2'))); + } + + /** + * @test + * @group issue_49 + */ + public function unlinkReturnsFalseWhenFileDoesNotExistAndFileWithSameNameExistsInRoot() + { + vfsStream::setup()->addChild(vfsStream::newFile('foo.blubb')); + $this->assertFalse(@unlink(vfsStream::url('foo.blubb'))); + } + + /** + * assert dirname() returns correct directory name + * + * @test + */ + public function dirname() + { + $this->assertEquals($this->fooURL, dirname($this->barURL)); + $this->assertEquals($this->barURL, dirname($this->baz1URL)); + # returns "vfs:" instead of "." + # however this seems not to be fixable because dirname() does not + # call the stream wrapper + #$this->assertEquals(dirname(vfsStream::url('doesNotExist')), '.'); + } + + /** + * assert basename() returns correct file name + * + * @test + */ + public function basename() + { + $this->assertEquals('bar', basename($this->barURL)); + $this->assertEquals('baz1', basename($this->baz1URL)); + $this->assertEquals('doesNotExist', basename(vfsStream::url('doesNotExist'))); + } + + /** + * assert is_readable() works correct + * + * @test + */ + public function is_readable() + { + $this->assertTrue(is_readable($this->fooURL)); + $this->assertTrue(is_readable($this->fooURL . '/.')); + $this->assertTrue(is_readable($this->barURL)); + $this->assertTrue(is_readable($this->barURL . '/.')); + $this->assertTrue(is_readable($this->baz1URL)); + $this->assertTrue(is_readable($this->baz2URL)); + $this->assertFalse(is_readable($this->fooURL . '/another')); + $this->assertFalse(is_readable(vfsStream::url('another'))); + + $this->foo->chmod(0222); + $this->assertFalse(is_readable($this->fooURL)); + + $this->baz1->chmod(0222); + $this->assertFalse(is_readable($this->baz1URL)); + } + + /** + * assert is_writable() works correct + * + * @test + */ + public function is_writable() + { + $this->assertTrue(is_writable($this->fooURL)); + $this->assertTrue(is_writable($this->fooURL . '/.')); + $this->assertTrue(is_writable($this->barURL)); + $this->assertTrue(is_writable($this->barURL . '/.')); + $this->assertTrue(is_writable($this->baz1URL)); + $this->assertTrue(is_writable($this->baz2URL)); + $this->assertFalse(is_writable($this->fooURL . '/another')); + $this->assertFalse(is_writable(vfsStream::url('another'))); + + $this->foo->chmod(0444); + $this->assertFalse(is_writable($this->fooURL)); + + $this->baz1->chmod(0444); + $this->assertFalse(is_writable($this->baz1URL)); + } + + /** + * assert is_executable() works correct + * + * @test + */ + public function is_executable() + { + $this->assertFalse(is_executable($this->baz1URL)); + $this->baz1->chmod(0766); + $this->assertTrue(is_executable($this->baz1URL)); + $this->assertFalse(is_executable($this->baz2URL)); + } + + /** + * assert is_executable() works correct + * + * @test + */ + public function directoriesAndNonExistingFilesAreSometimesExecutable() + { + // Inconsistent behavior has been fixed in 7.3 + // see https://github.com/php/php-src/commit/94b4abdbc4d + if (PHP_VERSION_ID >= 70300) { + $this->assertTrue(is_executable($this->fooURL)); + $this->assertTrue(is_executable($this->fooURL . '/.')); + $this->assertTrue(is_executable($this->barURL)); + $this->assertTrue(is_executable($this->barURL . '/.')); + } else { + $this->assertFalse(is_executable($this->fooURL)); + $this->assertFalse(is_executable($this->fooURL . '/.')); + $this->assertFalse(is_executable($this->barURL)); + $this->assertFalse(is_executable($this->barURL . '/.')); + } + + $this->assertFalse(is_executable($this->fooURL . '/another')); + $this->assertFalse(is_executable(vfsStream::url('another'))); + } + + /** + * file permissions + * + * @test + * @group permissions + */ + public function chmod() + { + $this->assertEquals(40777, decoct(fileperms($this->fooURL))); + $this->assertEquals(40777, decoct(fileperms($this->fooURL . '/.'))); + $this->assertEquals(40777, decoct(fileperms($this->barURL))); + $this->assertEquals(40777, decoct(fileperms($this->barURL . '/.'))); + $this->assertEquals(100666, decoct(fileperms($this->baz1URL))); + $this->assertEquals(100666, decoct(fileperms($this->baz2URL))); + + $this->foo->chmod(0755); + $this->bar->chmod(0700); + $this->baz1->chmod(0644); + $this->baz2->chmod(0600); + $this->assertEquals(40755, decoct(fileperms($this->fooURL))); + $this->assertEquals(40755, decoct(fileperms($this->fooURL . '/.'))); + $this->assertEquals(40700, decoct(fileperms($this->barURL))); + $this->assertEquals(40700, decoct(fileperms($this->barURL . '/.'))); + $this->assertEquals(100644, decoct(fileperms($this->baz1URL))); + $this->assertEquals(100600, decoct(fileperms($this->baz2URL))); + } + + /** + * @test + * @group issue_11 + * @group permissions + */ + public function chmodModifiesPermissions() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertFalse(@chmod($this->fooURL, 0755)); + $this->assertFalse(@chmod($this->barURL, 0711)); + $this->assertFalse(@chmod($this->baz1URL, 0644)); + $this->assertFalse(@chmod($this->baz2URL, 0664)); + $this->assertEquals(40777, decoct(fileperms($this->fooURL))); + $this->assertEquals(40777, decoct(fileperms($this->barURL))); + $this->assertEquals(100666, decoct(fileperms($this->baz1URL))); + $this->assertEquals(100666, decoct(fileperms($this->baz2URL))); + } else { + $this->assertTrue(chmod($this->fooURL, 0755)); + $this->assertTrue(chmod($this->barURL, 0711)); + $this->assertTrue(chmod($this->baz1URL, 0644)); + $this->assertTrue(chmod($this->baz2URL, 0664)); + $this->assertEquals(40755, decoct(fileperms($this->fooURL))); + $this->assertEquals(40711, decoct(fileperms($this->barURL))); + $this->assertEquals(100644, decoct(fileperms($this->baz1URL))); + $this->assertEquals(100664, decoct(fileperms($this->baz2URL))); + } + } + + /** + * @test + * @group permissions + */ + public function fileownerIsCurrentUserByDefault() + { + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL)); + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL . '/.')); + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->barURL)); + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->barURL . '/.')); + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->baz1URL)); + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->baz2URL)); + } + + /** + * @test + * @group issue_11 + * @group permissions + */ + public function chownChangesUser() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->foo->chown(vfsStream::OWNER_USER_1); + $this->bar->chown(vfsStream::OWNER_USER_1); + $this->baz1->chown(vfsStream::OWNER_USER_2); + $this->baz2->chown(vfsStream::OWNER_USER_2); + } else { + chown($this->fooURL, vfsStream::OWNER_USER_1); + chown($this->barURL, vfsStream::OWNER_USER_1); + chown($this->baz1URL, vfsStream::OWNER_USER_2); + chown($this->baz2URL, vfsStream::OWNER_USER_2); + } + + $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->fooURL)); + $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->fooURL . '/.')); + $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->barURL)); + $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->barURL . '/.')); + $this->assertEquals(vfsStream::OWNER_USER_2, fileowner($this->baz1URL)); + $this->assertEquals(vfsStream::OWNER_USER_2, fileowner($this->baz2URL)); + } + + /** + * @test + * @group issue_11 + * @group permissions + */ + public function chownDoesNotWorkOnVfsStreamUrls() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertFalse(@chown($this->fooURL, vfsStream::OWNER_USER_2)); + $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL)); + } + } + + /** + * @test + * @group issue_11 + * @group permissions + */ + public function groupIsCurrentGroupByDefault() + { + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL)); + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL . '/.')); + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->barURL)); + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->barURL . '/.')); + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->baz1URL)); + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->baz2URL)); + } + + /** + * @test + * @group issue_11 + * @group permissions + */ + public function chgrp() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->foo->chgrp(vfsStream::GROUP_USER_1); + $this->bar->chgrp(vfsStream::GROUP_USER_1); + $this->baz1->chgrp(vfsStream::GROUP_USER_2); + $this->baz2->chgrp(vfsStream::GROUP_USER_2); + } else { + chgrp($this->fooURL, vfsStream::GROUP_USER_1); + chgrp($this->barURL, vfsStream::GROUP_USER_1); + chgrp($this->baz1URL, vfsStream::GROUP_USER_2); + chgrp($this->baz2URL, vfsStream::GROUP_USER_2); + } + + $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->fooURL)); + $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->fooURL . '/.')); + $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->barURL)); + $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->barURL . '/.')); + $this->assertEquals(vfsStream::GROUP_USER_2, filegroup($this->baz1URL)); + $this->assertEquals(vfsStream::GROUP_USER_2, filegroup($this->baz2URL)); + } + + /** + * @test + * @group issue_11 + * @group permissions + */ + public function chgrpDoesNotWorkOnVfsStreamUrls() + { + if (version_compare(phpversion(), '5.4.0', '<')) { + $this->assertFalse(@chgrp($this->fooURL, vfsStream::GROUP_USER_2)); + $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL)); + } + } + + /** + * @test + * @author Benoit Aubuchon + */ + public function renameDirectory() + { + // move foo/bar to foo/baz3 + $baz3URL = vfsStream::url('foo/baz3'); + $this->assertTrue(rename($this->barURL, $baz3URL)); + $this->assertFileExists($baz3URL); + $this->assertFileDoesNotExist($this->barURL); + } + + /** + * @test + */ + public function renameDirectoryWithDots() + { + // move foo/bar to foo/baz3 + $baz3URL = vfsStream::url('foo/baz3'); + $this->assertTrue(rename($this->barURL . '/.', $baz3URL)); + $this->assertFileExists($baz3URL); + $this->assertFileDoesNotExist($this->barURL); + } + + /** + * @test + * @group issue_9 + * @since 0.9.0 + */ + public function renameDirectoryWithDotsInTarget() + { + // move foo/bar to foo/baz3 + $baz3URL = vfsStream::url('foo/../baz3/.'); + $this->assertTrue(rename($this->barURL . '/.', $baz3URL)); + $this->assertFileExists($baz3URL); + $this->assertFileDoesNotExist($this->barURL); + } + + /** + * @test + * @author Benoit Aubuchon + */ + public function renameDirectoryOverwritingExistingFile() + { + // move foo/bar to foo/baz2 + $this->assertTrue(rename($this->barURL, $this->baz2URL)); + $this->assertFileExists(vfsStream::url('foo/baz2/baz1')); + $this->assertFileDoesNotExist($this->barURL); + } + + /** + * @test + */ + public function renameFileIntoFile() + { + $this->expectException(Error\Warning::class); + // foo/baz2 is a file, so it can not be turned into a directory + $baz3URL = vfsStream::url('foo/baz2/baz3'); + $this->assertTrue(rename($this->baz1URL, $baz3URL)); + $this->assertFileExists($baz3URL); + $this->assertFileDoesNotExist($this->baz1URL); + } + + /** + * @test + * @author Benoit Aubuchon + */ + public function renameFileToDirectory() + { + // move foo/bar/baz1 to foo/baz3 + $baz3URL = vfsStream::url('foo/baz3'); + $this->assertTrue(rename($this->baz1URL, $baz3URL)); + $this->assertFileExists($this->barURL); + $this->assertFileExists($baz3URL); + $this->assertFileDoesNotExist($this->baz1URL); + } + + /** + * assert that trying to rename from a non existing file trigger a warning + * + * @test + */ + public function renameOnSourceFileNotFound() + { + $this->expectException(Error\Warning::class); + rename(vfsStream::url('notfound'), $this->baz1URL); + } + /** + * assert that trying to rename to a directory that is not found trigger a warning + + * @test + */ + public function renameOnDestinationDirectoryFileNotFound() + { + $this->expectException(Error\Warning::class); + rename($this->baz1URL, vfsStream::url('foo/notfound/file2')); + } + /** + * stat() and fstat() should return the same result + * + * @test + */ + public function statAndFstatReturnSameResult() + { + $fp = fopen($this->baz2URL, 'r'); + $this->assertEquals(stat($this->baz2URL), + fstat($fp) + ); + fclose($fp); + } + + /** + * stat() returns full data + * + * @test + */ + public function statReturnsFullDataForFiles() + { + $this->assertEquals(array(0 => 0, + 1 => 0, + 2 => 0100666, + 3 => 0, + 4 => vfsStream::getCurrentUser(), + 5 => vfsStream::getCurrentGroup(), + 6 => 0, + 7 => 4, + 8 => 400, + 9 => 400, + 10 => 400, + 11 => -1, + 12 => -1, + 'dev' => 0, + 'ino' => 0, + 'mode' => 0100666, + 'nlink' => 0, + 'uid' => vfsStream::getCurrentUser(), + 'gid' => vfsStream::getCurrentGroup(), + 'rdev' => 0, + 'size' => 4, + 'atime' => 400, + 'mtime' => 400, + 'ctime' => 400, + 'blksize' => -1, + 'blocks' => -1 + ), + stat($this->baz2URL) + ); + } + + /** + * @test + */ + public function statReturnsFullDataForDirectories() + { + $this->assertEquals(array(0 => 0, + 1 => 0, + 2 => 0040777, + 3 => 0, + 4 => vfsStream::getCurrentUser(), + 5 => vfsStream::getCurrentGroup(), + 6 => 0, + 7 => 0, + 8 => 100, + 9 => 100, + 10 => 100, + 11 => -1, + 12 => -1, + 'dev' => 0, + 'ino' => 0, + 'mode' => 0040777, + 'nlink' => 0, + 'uid' => vfsStream::getCurrentUser(), + 'gid' => vfsStream::getCurrentGroup(), + 'rdev' => 0, + 'size' => 0, + 'atime' => 100, + 'mtime' => 100, + 'ctime' => 100, + 'blksize' => -1, + 'blocks' => -1 + ), + stat($this->fooURL) + ); + } + + /** + * @test + */ + public function statReturnsFullDataForDirectoriesWithDot() + { + $this->assertEquals(array(0 => 0, + 1 => 0, + 2 => 0040777, + 3 => 0, + 4 => vfsStream::getCurrentUser(), + 5 => vfsStream::getCurrentGroup(), + 6 => 0, + 7 => 0, + 8 => 100, + 9 => 100, + 10 => 100, + 11 => -1, + 12 => -1, + 'dev' => 0, + 'ino' => 0, + 'mode' => 0040777, + 'nlink' => 0, + 'uid' => vfsStream::getCurrentUser(), + 'gid' => vfsStream::getCurrentGroup(), + 'rdev' => 0, + 'size' => 0, + 'atime' => 100, + 'mtime' => 100, + 'ctime' => 100, + 'blksize' => -1, + 'blocks' => -1 + ), + stat($this->fooURL . '/.') + ); + } + + /** + * @test + */ + public function openFileWithoutDirectory() + { + $this->expectException(Error\Warning::class); + vfsStreamWrapper::register(); + $this->assertFalse(file_get_contents(vfsStream::url('file.txt'))); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + * @requires PHP 5.4.0 + */ + public function truncateRemovesSuperflouosContent() + { + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + $handle = fopen($this->baz1URL, "r+"); + $this->assertTrue(ftruncate($handle, 0)); + $this->assertEquals(0, filesize($this->baz1URL)); + $this->assertEquals('', file_get_contents($this->baz1URL)); + fclose($handle); + } + + /** + * @test + * @group issue_33 + * @since 1.1.0 + * @requires PHP 5.4.0 + */ + public function truncateToGreaterSizeAddsZeroBytes() + { + if (strstr(PHP_VERSION, 'hiphop') !== false) { + $this->markTestSkipped('Not supported on hhvm'); + } + + $handle = fopen($this->baz1URL, "r+"); + $this->assertTrue(ftruncate($handle, 25)); + $this->assertEquals(25, filesize($this->baz1URL)); + $this->assertEquals("baz 1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", + file_get_contents($this->baz1URL)); + fclose($handle); + } + + /** + * @test + * @group issue_11 + * @requires PHP 5.4.0 + */ + public function touchCreatesNonExistingFile() + { + $this->assertTrue(touch($this->fooURL . '/new.txt')); + $this->assertTrue($this->foo->hasChild('new.txt')); + } + + /** + * @test + * @group issue_11 + * @requires PHP 5.4.0 + */ + public function touchChangesAccessAndModificationTimeForFile() + { + $this->assertTrue(touch($this->baz1URL, 303, 313)); + $this->assertEquals(303, $this->baz1->filemtime()); + $this->assertEquals(313, $this->baz1->fileatime()); + } + + /** + * @test + * @group issue_11 + * @group issue_80 + * @requires PHP 5.4.0 + */ + public function touchChangesTimesToCurrentTimestampWhenNoTimesGiven() + { + $this->assertTrue(touch($this->baz1URL)); + $this->assertEquals(time(), $this->baz1->filemtime(), '', 1); + $this->assertEquals(time(), $this->baz1->fileatime(), '', 1); + } + + /** + * @test + * @group issue_11 + * @requires PHP 5.4.0 + */ + public function touchWithModifiedTimeChangesAccessAndModifiedTime() + { + $this->assertTrue(touch($this->baz1URL, 303)); + $this->assertEquals(303, $this->baz1->filemtime()); + $this->assertEquals(303, $this->baz1->fileatime()); + } + + /** + * @test + * @group issue_11 + * @requires PHP 5.4.0 + */ + public function touchChangesAccessAndModificationTimeForDirectory() + { + $this->assertTrue(touch($this->fooURL, 303, 313)); + $this->assertEquals(303, $this->foo->filemtime()); + $this->assertEquals(313, $this->foo->fileatime()); + } + + /** + * @test + * @group issue_34 + * @since 1.2.0 + */ + public function pathesAreCorrectlySet() + { + $this->assertEquals(vfsStream::path($this->fooURL), $this->foo->path()); + $this->assertEquals(vfsStream::path($this->barURL), $this->bar->path()); + $this->assertEquals(vfsStream::path($this->baz1URL), $this->baz1->path()); + $this->assertEquals(vfsStream::path($this->baz2URL), $this->baz2->path()); + } + + /** + * @test + * @group issue_34 + * @since 1.2.0 + */ + public function urlsAreCorrectlySet() + { + $this->assertEquals($this->fooURL, $this->foo->url()); + $this->assertEquals($this->barURL, $this->bar->url()); + $this->assertEquals($this->baz1URL, $this->baz1->url()); + $this->assertEquals($this->baz2URL, $this->baz2->url()); + } + + /** + * @test + * @group issue_34 + * @since 1.2.0 + */ + public function pathIsUpdatedAfterMove() + { + // move foo/bar/baz1 to foo/baz3 + $baz3URL = vfsStream::url('foo/baz3'); + $this->assertTrue(rename($this->baz1URL, $baz3URL)); + $this->assertEquals(vfsStream::path($baz3URL), $this->baz1->path()); + } + + /** + * @test + * @group issue_34 + * @since 1.2.0 + */ + public function urlIsUpdatedAfterMove() + { + // move foo/bar/baz1 to foo/baz3 + $baz3URL = vfsStream::url('foo/baz3'); + $this->assertTrue(rename($this->baz1URL, $baz3URL)); + $this->assertEquals($baz3URL, $this->baz1->url()); + } + + /** + * @test + */ + public function fileCopy() + { + $baz3URL = vfsStream::url('foo/baz3'); + $this->assertTrue(copy($this->baz1URL, $baz3URL)); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperUnregisterTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperUnregisterTestCase.php new file mode 100644 index 000000000..01d1cfa5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperUnregisterTestCase.php @@ -0,0 +1,75 @@ +assertNotContains(vfsStream::SCHEME, stream_get_wrappers()); + } + + /** + * Unregistering a third party wrapper for vfs:// fails. + * + * @test + * @runInSeparateProcess + */ + public function unregisterThirdPartyVfsScheme() + { + $this->expectException(vfsStreamException::class); + // Unregister possible registered URL wrapper. + vfsStreamWrapper::unregister(); + + $mock = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamWrapper'); + stream_wrapper_register(vfsStream::SCHEME, get_class($mock)); + + vfsStreamWrapper::unregister(); + } + + /** + * Unregistering when not in registered state will fail. + * + * @test + * @runInSeparateProcess + */ + public function unregisterWhenNotInRegisteredState() + { + $this->expectException(vfsStreamException::class); + vfsStreamWrapper::register(); + stream_wrapper_unregister(vfsStream::SCHEME); + vfsStreamWrapper::unregister(); + } + + /** + * Unregistering while not registers won't fail. + * + * @test + */ + public function unregisterWhenNotRegistered() + { + // Unregister possible registered URL wrapper. + vfsStreamWrapper::unregister(); + + $this->assertNotContains(vfsStream::SCHEME, stream_get_wrappers()); + vfsStreamWrapper::unregister(); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperWithoutRootTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperWithoutRootTestCase.php new file mode 100644 index 000000000..03c3d5b91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamWrapperWithoutRootTestCase.php @@ -0,0 +1,63 @@ + no directory to open + * + * @test + */ + public function canNotOpenDirectory() + { + $this->assertFalse(@dir(vfsStream::url('foo'))); + } + + /** + * can not unlink without root + * + * @test + */ + public function canNotUnlink() + { + $this->assertFalse(@unlink(vfsStream::url('foo'))); + } + + /** + * can not open a file without root + * + * @test + */ + public function canNotOpen() + { + $this->assertFalse(@fopen(vfsStream::url('foo'), 'r')); + } + + /** + * can not rename a file without root + * + * @test + */ + public function canNotRename() + { + $this->assertFalse(@rename(vfsStream::url('foo'), vfsStream::url('bar'))); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamZipTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamZipTestCase.php new file mode 100644 index 000000000..166186be8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/vfsStreamZipTestCase.php @@ -0,0 +1,52 @@ +markTestSkipped('No ext/zip installed, skipping test.'); + } + + $this->markTestSkipped('Zip extension can not work with vfsStream urls.'); + + vfsStreamWrapper::register(); + vfsStreamWrapper::setRoot(vfsStream::newDirectory('root')); + + } + + /** + * @test + */ + public function createZipArchive() + { + $zip = new ZipArchive(); + $this->assertTrue($zip->open(vfsStream::url('root/test.zip'), ZipArchive::CREATE)); + $this->assertTrue($zip->addFromString("testfile1.txt", "#1 This is a test string added as testfile1.txt.\n")); + $this->assertTrue($zip->addFromString("testfile2.txt", "#2 This is a test string added as testfile2.txt.\n")); + $zip->setArchiveComment('a test'); + var_dump($zip); + $this->assertTrue($zip->close()); + var_dump($zip->getStatusString()); + var_dump($zip->close()); + var_dump($zip->getStatusString()); + var_dump($zip); + var_dump(file_exists(vfsStream::url('root/test.zip'))); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitorTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitorTestCase.php new file mode 100644 index 000000000..e1d101095 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitorTestCase.php @@ -0,0 +1,98 @@ +abstractVisitor = $this->bc_getMock('org\\bovigo\\vfs\\visitor\\vfsStreamAbstractVisitor', + array('visitFile', 'visitDirectory') + ); + } + + /** + * @test + */ + public function visitThrowsInvalidArgumentExceptionOnUnknownContentType() + { + $this->expectException(\InvalidArgumentException::class); + $mockContent = $this->bc_getMock('org\\bovigo\\vfs\\vfsStreamContent'); + $mockContent->expects($this->any()) + ->method('getType') + ->will($this->returnValue('invalid')); + $this->assertSame($this->abstractVisitor, + $this->abstractVisitor->visit($mockContent) + ); + } + + /** + * @test + */ + public function visitWithFileCallsVisitFile() + { + $file = new vfsStreamFile('foo.txt'); + $this->abstractVisitor->expects($this->once()) + ->method('visitFile') + ->with($this->equalTo($file)); + $this->assertSame($this->abstractVisitor, + $this->abstractVisitor->visit($file) + ); + } + + /** + * tests that a block device eventually calls out to visit file + * + * @test + */ + public function visitWithBlockCallsVisitFile() + { + $block = new vfsStreamBlock('foo'); + $this->abstractVisitor->expects($this->once()) + ->method('visitFile') + ->with($this->equalTo($block)); + $this->assertSame($this->abstractVisitor, + $this->abstractVisitor->visit($block) + ); + } + + /** + * @test + */ + public function visitWithDirectoryCallsVisitDirectory() + { + $dir = new vfsStreamDirectory('bar'); + $this->abstractVisitor->expects($this->once()) + ->method('visitDirectory') + ->with($this->equalTo($dir)); + $this->assertSame($this->abstractVisitor, + $this->abstractVisitor->visit($dir) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitorTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitorTestCase.php new file mode 100644 index 000000000..3f8b8c704 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitorTestCase.php @@ -0,0 +1,102 @@ +expectException(\InvalidArgumentException::class); + new vfsStreamPrintVisitor('invalid'); + } + + /** + * @test + */ + public function constructWithNonStreamResourceThrowsInvalidArgumentException() + { + $this->expectException(\InvalidArgumentException::class); + new vfsStreamPrintVisitor(xml_parser_create()); + } + + /** + * @test + */ + public function visitFileWritesFileNameToStream() + { + $output = vfsStream::newFile('foo.txt') + ->at(vfsStream::setup()); + $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); + $this->assertSame($printVisitor, + $printVisitor->visitFile(vfsStream::newFile('bar.txt')) + ); + $this->assertEquals("- bar.txt\n", $output->getContent()); + } + + /** + * @test + */ + public function visitFileWritesBlockDeviceToStream() + { + $output = vfsStream::newFile('foo.txt') + ->at(vfsStream::setup()); + $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); + $this->assertSame($printVisitor, + $printVisitor->visitBlockDevice(vfsStream::newBlock('bar')) + ); + $this->assertEquals("- [bar]\n", $output->getContent()); + } + + /** + * @test + */ + public function visitDirectoryWritesDirectoryNameToStream() + { + $output = vfsStream::newFile('foo.txt') + ->at(vfsStream::setup()); + $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); + $this->assertSame($printVisitor, + $printVisitor->visitDirectory(vfsStream::newDirectory('baz')) + ); + $this->assertEquals("- baz\n", $output->getContent()); + } + + /** + * @test + */ + public function visitRecursiveDirectoryStructure() + { + $root = vfsStream::setup('root', + null, + array('test' => array('foo' => array('test.txt' => 'hello'), + 'baz.txt' => 'world' + ), + 'foo.txt' => '' + ) + ); + $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb')); + $this->assertSame($printVisitor, + $printVisitor->visitDirectory($root) + ); + $this->assertEquals("- root\n - test\n - foo\n - test.txt\n - baz.txt\n - foo.txt\n", file_get_contents('vfs://root/foo.txt')); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitorTestCase.php b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitorTestCase.php new file mode 100644 index 000000000..c9df23406 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitorTestCase.php @@ -0,0 +1,85 @@ +assertEquals(array('foo.txt' => 'test'), + $structureVisitor->visitFile(vfsStream::newFile('foo.txt') + ->withContent('test') + ) + ->getStructure() + ); + } + + /** + * @test + */ + public function visitFileCreatesStructureForBlock() + { + $structureVisitor = new vfsStreamStructureVisitor(); + $this->assertEquals(array('[foo]' => 'test'), + $structureVisitor->visitBlockDevice(vfsStream::newBlock('foo') + ->withContent('test') + ) + ->getStructure() + ); + } + + /** + * @test + */ + public function visitDirectoryCreatesStructureForDirectory() + { + $structureVisitor = new vfsStreamStructureVisitor(); + $this->assertEquals(array('baz' => array()), + $structureVisitor->visitDirectory(vfsStream::newDirectory('baz')) + ->getStructure() + ); + } + + /** + * @test + */ + public function visitRecursiveDirectoryStructure() + { + $root = vfsStream::setup('root', + null, + array('test' => array('foo' => array('test.txt' => 'hello'), + 'baz.txt' => 'world' + ), + 'foo.txt' => '' + ) + ); + $structureVisitor = new vfsStreamStructureVisitor(); + $this->assertEquals(array('root' => array('test' => array('foo' => array('test.txt' => 'hello'), + 'baz.txt' => 'world' + ), + 'foo.txt' => '' + ), + ), + $structureVisitor->visitDirectory($root) + ->getStructure() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/phpt/bug71287.phpt b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/phpt/bug71287.phpt new file mode 100644 index 000000000..75b9b3764 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/phpt/bug71287.phpt @@ -0,0 +1,29 @@ +--TEST-- +Reproduce octal output from stream wrapper invocation + +See https://bugs.php.net/bug.php?id=71287 +See https://github.com/mikey179/vfsStream/issues/120 +--FILE-- + +--EXPECTF-- +Warning: file_put_contents(): Only 7 of 9 bytes written, possibly out of free disk space in %s on line %d \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/emptyFolder/.gitignore b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/emptyFolder/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/aFile.txt b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/aFile.txt new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/aFile.txt @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder1/file1.txt b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder1/file1.txt new file mode 100644 index 000000000..f6ea04951 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder1/file1.txt @@ -0,0 +1 @@ +foobar \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder2/.gitignore b/.extlib/simplesamlphp/vendor/mikey179/vfsstream/src/test/resources/filesystemcopy/withSubfolders/subfolder2/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/LICENSE b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/LICENSE new file mode 100644 index 000000000..c3e835001 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 My C-Sense + +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/.extlib/simplesamlphp/vendor/myclabs/deep-copy/README.md b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/README.md new file mode 100644 index 000000000..88ae14cca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/README.md @@ -0,0 +1,406 @@ +# DeepCopy + +DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph. + +[![Total Downloads](https://poser.pugx.org/myclabs/deep-copy/downloads.svg)](https://packagist.org/packages/myclabs/deep-copy) +[![Integrate](https://github.com/myclabs/DeepCopy/actions/workflows/ci.yaml/badge.svg?branch=1.x)](https://github.com/myclabs/DeepCopy/actions/workflows/ci.yaml) + +## Table of Contents + +1. [How](#how) +1. [Why](#why) + 1. [Using simply `clone`](#using-simply-clone) + 1. [Overriding `__clone()`](#overriding-__clone) + 1. [With `DeepCopy`](#with-deepcopy) +1. [How it works](#how-it-works) +1. [Going further](#going-further) + 1. [Matchers](#matchers) + 1. [Property name](#property-name) + 1. [Specific property](#specific-property) + 1. [Type](#type) + 1. [Filters](#filters) + 1. [`SetNullFilter`](#setnullfilter-filter) + 1. [`KeepFilter`](#keepfilter-filter) + 1. [`DoctrineCollectionFilter`](#doctrinecollectionfilter-filter) + 1. [`DoctrineEmptyCollectionFilter`](#doctrineemptycollectionfilter-filter) + 1. [`DoctrineProxyFilter`](#doctrineproxyfilter-filter) + 1. [`ReplaceFilter`](#replacefilter-type-filter) + 1. [`ShallowCopyFilter`](#shallowcopyfilter-type-filter) +1. [Edge cases](#edge-cases) +1. [Contributing](#contributing) + 1. [Tests](#tests) + + +## How? + +Install with Composer: + +``` +composer require myclabs/deep-copy +``` + +Use it: + +```php +use DeepCopy\DeepCopy; + +$copier = new DeepCopy(); +$myCopy = $copier->copy($myObject); +``` + + +## Why? + +- How do you create copies of your objects? + +```php +$myCopy = clone $myObject; +``` + +- How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)? + +You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior +yourself. + +- But how do you handle **cycles** in the association graph? + +Now you're in for a big mess :( + +![association graph](doc/graph.png) + + +### Using simply `clone` + +![Using clone](doc/clone.png) + + +### Overriding `__clone()` + +![Overriding __clone](doc/deep-clone.png) + + +### With `DeepCopy` + +![With DeepCopy](doc/deep-copy.png) + + +## How it works + +DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it +keeps a hash map of all instances and thus preserves the object graph. + +To use it: + +```php +use function DeepCopy\deep_copy; + +$copy = deep_copy($var); +``` + +Alternatively, you can create your own `DeepCopy` instance to configure it differently for example: + +```php +use DeepCopy\DeepCopy; + +$copier = new DeepCopy(true); + +$copy = $copier->copy($var); +``` + +You may want to roll your own deep copy function: + +```php +namespace Acme; + +use DeepCopy\DeepCopy; + +function deep_copy($var) +{ + static $copier = null; + + if (null === $copier) { + $copier = new DeepCopy(true); + } + + return $copier->copy($var); +} +``` + + +## Going further + +You can add filters to customize the copy process. + +The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`, +with `$filter` implementing `DeepCopy\Filter\Filter` +and `$matcher` implementing `DeepCopy\Matcher\Matcher`. + +We provide some generic filters and matchers. + + +### Matchers + + - `DeepCopy\Matcher` applies on a object attribute. + - `DeepCopy\TypeMatcher` applies on any element found in graph, including array elements. + + +#### Property name + +The `PropertyNameMatcher` will match a property by its name: + +```php +use DeepCopy\Matcher\PropertyNameMatcher; + +// Will apply a filter to any property of any objects named "id" +$matcher = new PropertyNameMatcher('id'); +``` + + +#### Specific property + +The `PropertyMatcher` will match a specific property of a specific class: + +```php +use DeepCopy\Matcher\PropertyMatcher; + +// Will apply a filter to the property "id" of any objects of the class "MyClass" +$matcher = new PropertyMatcher('MyClass', 'id'); +``` + + +#### Type + +The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of +[gettype()](http://php.net/manual/en/function.gettype.php) function): + +```php +use DeepCopy\TypeMatcher\TypeMatcher; + +// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection +$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection'); +``` + + +### Filters + +- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher` +- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher` + +By design, matching a filter will stop the chain of filters (i.e. the next ones will not be applied). +Using the ([`ChainableFilter`](#chainablefilter-filter)) won't stop the chain of filters. + + +#### `SetNullFilter` (filter) + +Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have +any ID: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\SetNullFilter; +use DeepCopy\Matcher\PropertyNameMatcher; + +$object = MyClass::load(123); +echo $object->id; // 123 + +$copier = new DeepCopy(); +$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id')); + +$copy = $copier->copy($object); + +echo $copy->id; // null +``` + + +#### `KeepFilter` (filter) + +If you want a property to remain untouched (for example, an association to an object): + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\KeepFilter; +use DeepCopy\Matcher\PropertyMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category')); + +$copy = $copier->copy($object); +// $copy->category has not been touched +``` + + +#### `ChainableFilter` (filter) + +If you use cloning on proxy classes, you might want to apply two filters for: +1. loading the data +2. applying a transformation + +You can use the `ChainableFilter` as a decorator of the proxy loader filter, which won't stop the chain of filters (i.e. +the next ones may be applied). + + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\ChainableFilter; +use DeepCopy\Filter\Doctrine\DoctrineProxyFilter; +use DeepCopy\Filter\SetNullFilter; +use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher; +use DeepCopy\Matcher\PropertyNameMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new ChainableFilter(new DoctrineProxyFilter()), new DoctrineProxyMatcher()); +$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id')); + +$copy = $copier->copy($object); + +echo $copy->id; // null +``` + + +#### `DoctrineCollectionFilter` (filter) + +If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter; +use DeepCopy\Matcher\PropertyTypeMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection')); + +$copy = $copier->copy($object); +``` + + +#### `DoctrineEmptyCollectionFilter` (filter) + +If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the +`DoctrineEmptyCollectionFilter` + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter; +use DeepCopy\Matcher\PropertyMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty')); + +$copy = $copier->copy($object); + +// $copy->myProperty will return an empty collection +``` + + +#### `DoctrineProxyFilter` (filter) + +If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a +Doctrine proxy class (...\\\_\_CG\_\_\Proxy). +You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class. +**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded +before other filters are applied!** +We recommend to decorate the `DoctrineProxyFilter` with the `ChainableFilter` to allow applying other filters to the +cloned lazy loaded entities. + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\Doctrine\DoctrineProxyFilter; +use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher; + +$copier = new DeepCopy(); +$copier->addFilter(new ChainableFilter(new DoctrineProxyFilter()), new DoctrineProxyMatcher()); + +$copy = $copier->copy($object); + +// $copy should now contain a clone of all entities, including those that were not yet fully loaded. +``` + + +#### `ReplaceFilter` (type filter) + +1. If you want to replace the value of a property: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\Filter\ReplaceFilter; +use DeepCopy\Matcher\PropertyMatcher; + +$copier = new DeepCopy(); +$callback = function ($currentValue) { + return $currentValue . ' (copy)' +}; +$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title')); + +$copy = $copier->copy($object); + +// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)' +``` + +2. If you want to replace whole element: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\TypeFilter\ReplaceFilter; +use DeepCopy\TypeMatcher\TypeMatcher; + +$copier = new DeepCopy(); +$callback = function (MyClass $myClass) { + return get_class($myClass); +}; +$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass')); + +$copy = $copier->copy([new MyClass, 'some string', new MyClass]); + +// $copy will contain ['MyClass', 'some string', 'MyClass'] +``` + + +The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable. + + +#### `ShallowCopyFilter` (type filter) + +Stop *DeepCopy* from recursively copying element, using standard `clone` instead: + +```php +use DeepCopy\DeepCopy; +use DeepCopy\TypeFilter\ShallowCopyFilter; +use DeepCopy\TypeMatcher\TypeMatcher; +use Mockery as m; + +$this->deepCopy = new DeepCopy(); +$this->deepCopy->addTypeFilter( + new ShallowCopyFilter, + new TypeMatcher(m\MockInterface::class) +); + +$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class)); +// All mocks will be just cloned, not deep copied +``` + + +## Edge cases + +The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are +not applied. There is two ways for you to handle them: + +- Implement your own `__clone()` method +- Use a filter with a type matcher + + +## Contributing + +DeepCopy is distributed under the MIT license. + + +### Tests + +Running the tests is simple: + +```php +vendor/bin/phpunit +``` + +### Support + +Get professional support via [the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-myclabs-deep-copy?utm_source=packagist-myclabs-deep-copy&utm_medium=referral&utm_campaign=readme). diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/composer.json b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/composer.json new file mode 100644 index 000000000..f115fff85 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/composer.json @@ -0,0 +1,43 @@ +{ + "name": "myclabs/deep-copy", + "description": "Create deep copies (clones) of your objects", + "license": "MIT", + "type": "library", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "autoload-dev": { + "psr-4": { + "DeepCopyTest\\": "tests/DeepCopyTest/", + "DeepCopy\\": "fixtures/" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php new file mode 100644 index 000000000..f739d922d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php @@ -0,0 +1,316 @@ + Filter, 'matcher' => Matcher] pairs. + */ + private $filters = []; + + /** + * Type Filters to apply. + * + * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs. + */ + private $typeFilters = []; + + /** + * @var bool + */ + private $skipUncloneable = false; + + /** + * @var bool + */ + private $useCloneMethod; + + /** + * @param bool $useCloneMethod If set to true, when an object implements the __clone() function, it will be used + * instead of the regular deep cloning. + */ + public function __construct($useCloneMethod = false) + { + $this->useCloneMethod = $useCloneMethod; + + $this->addTypeFilter(new ArrayObjectFilter($this), new TypeMatcher(ArrayObject::class)); + $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class)); + $this->addTypeFilter(new DatePeriodFilter(), new TypeMatcher(DatePeriod::class)); + $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class)); + } + + /** + * If enabled, will not throw an exception when coming across an uncloneable property. + * + * @param $skipUncloneable + * + * @return $this + */ + public function skipUncloneable($skipUncloneable = true) + { + $this->skipUncloneable = $skipUncloneable; + + return $this; + } + + /** + * Deep copies the given object. + * + * @param mixed $object + * + * @return mixed + */ + public function copy($object) + { + $this->hashMap = []; + + return $this->recursiveCopy($object); + } + + public function addFilter(Filter $filter, Matcher $matcher) + { + $this->filters[] = [ + 'matcher' => $matcher, + 'filter' => $filter, + ]; + } + + public function prependFilter(Filter $filter, Matcher $matcher) + { + array_unshift($this->filters, [ + 'matcher' => $matcher, + 'filter' => $filter, + ]); + } + + public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher) + { + $this->typeFilters[] = [ + 'matcher' => $matcher, + 'filter' => $filter, + ]; + } + + private function recursiveCopy($var) + { + // Matches Type Filter + if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) { + return $filter->apply($var); + } + + // Resource + if (is_resource($var)) { + return $var; + } + + // Array + if (is_array($var)) { + return $this->copyArray($var); + } + + // Scalar + if (! is_object($var)) { + return $var; + } + + // Enum + if (PHP_VERSION_ID >= 80100 && enum_exists(get_class($var))) { + return $var; + } + + // Object + return $this->copyObject($var); + } + + /** + * Copy an array + * @param array $array + * @return array + */ + private function copyArray(array $array) + { + foreach ($array as $key => $value) { + $array[$key] = $this->recursiveCopy($value); + } + + return $array; + } + + /** + * Copies an object. + * + * @param object $object + * + * @throws CloneException + * + * @return object + */ + private function copyObject($object) + { + $objectHash = spl_object_hash($object); + + if (isset($this->hashMap[$objectHash])) { + return $this->hashMap[$objectHash]; + } + + $reflectedObject = new ReflectionObject($object); + $isCloneable = $reflectedObject->isCloneable(); + + if (false === $isCloneable) { + if ($this->skipUncloneable) { + $this->hashMap[$objectHash] = $object; + + return $object; + } + + throw new CloneException( + sprintf( + 'The class "%s" is not cloneable.', + $reflectedObject->getName() + ) + ); + } + + $newObject = clone $object; + $this->hashMap[$objectHash] = $newObject; + + if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) { + return $newObject; + } + + if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) { + return $newObject; + } + + foreach (ReflectionHelper::getProperties($reflectedObject) as $property) { + $this->copyObjectProperty($newObject, $property); + } + + return $newObject; + } + + private function copyObjectProperty($object, ReflectionProperty $property) + { + // Ignore static properties + if ($property->isStatic()) { + return; + } + + // Ignore readonly properties + if (method_exists($property, 'isReadOnly') && $property->isReadOnly()) { + return; + } + + // Apply the filters + foreach ($this->filters as $item) { + /** @var Matcher $matcher */ + $matcher = $item['matcher']; + /** @var Filter $filter */ + $filter = $item['filter']; + + if ($matcher->matches($object, $property->getName())) { + $filter->apply( + $object, + $property->getName(), + function ($object) { + return $this->recursiveCopy($object); + } + ); + + if ($filter instanceof ChainableFilter) { + continue; + } + + // If a filter matches, we stop processing this property + return; + } + } + + $property->setAccessible(true); + + // Ignore uninitialized properties (for PHP >7.4) + if (method_exists($property, 'isInitialized') && !$property->isInitialized($object)) { + return; + } + + $propertyValue = $property->getValue($object); + + // Copy the property + $property->setValue($object, $this->recursiveCopy($propertyValue)); + } + + /** + * Returns first filter that matches variable, `null` if no such filter found. + * + * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and + * 'matcher' with value of type {@see TypeMatcher} + * @param mixed $var + * + * @return TypeFilter|null + */ + private function getFirstMatchedTypeFilter(array $filterRecords, $var) + { + $matched = $this->first( + $filterRecords, + function (array $record) use ($var) { + /* @var TypeMatcher $matcher */ + $matcher = $record['matcher']; + + return $matcher->matches($var); + } + ); + + return isset($matched) ? $matched['filter'] : null; + } + + /** + * Returns first element that matches predicate, `null` if no such element found. + * + * @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs. + * @param callable $predicate Predicate arguments are: element. + * + * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher' + * with value of type {@see TypeMatcher} or `null`. + */ + private function first(array $elements, callable $predicate) + { + foreach ($elements as $element) { + if (call_user_func($predicate, $element)) { + return $element; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php new file mode 100644 index 000000000..c046706a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php @@ -0,0 +1,9 @@ +filter = $filter; + } + + public function apply($object, $property, $objectCopier) + { + $this->filter->apply($object, $property, $objectCopier); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php new file mode 100644 index 000000000..e6d937710 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineCollectionFilter.php @@ -0,0 +1,33 @@ +setAccessible(true); + $oldCollection = $reflectionProperty->getValue($object); + + $newCollection = $oldCollection->map( + function ($item) use ($objectCopier) { + return $objectCopier($item); + } + ); + + $reflectionProperty->setValue($object, $newCollection); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php new file mode 100644 index 000000000..7b33fd547 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php @@ -0,0 +1,28 @@ +setAccessible(true); + + $reflectionProperty->setValue($object, new ArrayCollection()); + } +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php new file mode 100644 index 000000000..8bee8f769 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php @@ -0,0 +1,22 @@ +__load(); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php new file mode 100644 index 000000000..85ba18ce1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php @@ -0,0 +1,18 @@ +callback = $callable; + } + + /** + * Replaces the object property by the result of the callback called with the object property. + * + * {@inheritdoc} + */ + public function apply($object, $property, $objectCopier) + { + $reflectionProperty = ReflectionHelper::getProperty($object, $property); + $reflectionProperty->setAccessible(true); + + $value = call_user_func($this->callback, $reflectionProperty->getValue($object)); + + $reflectionProperty->setValue($object, $value); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php new file mode 100644 index 000000000..bea86b884 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php @@ -0,0 +1,24 @@ +setAccessible(true); + $reflectionProperty->setValue($object, null); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php new file mode 100644 index 000000000..c5887b19c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php @@ -0,0 +1,22 @@ +class = $class; + $this->property = $property; + } + + /** + * Matches a specific property of a specific class. + * + * {@inheritdoc} + */ + public function matches($object, $property) + { + return ($object instanceof $this->class) && $property == $this->property; + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php new file mode 100644 index 000000000..c8ec0d2bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php @@ -0,0 +1,32 @@ +property = $property; + } + + /** + * Matches a property by its name. + * + * {@inheritdoc} + */ + public function matches($object, $property) + { + return $property == $this->property; + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php new file mode 100644 index 000000000..c7f46908c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php @@ -0,0 +1,52 @@ +propertyType = $propertyType; + } + + /** + * {@inheritdoc} + */ + public function matches($object, $property) + { + try { + $reflectionProperty = ReflectionHelper::getProperty($object, $property); + } catch (ReflectionException $exception) { + return false; + } + + $reflectionProperty->setAccessible(true); + + // Uninitialized properties (for PHP >7.4) + if (method_exists($reflectionProperty, 'isInitialized') && !$reflectionProperty->isInitialized($object)) { + // null instanceof $this->propertyType + return false; + } + + return $reflectionProperty->getValue($object) instanceof $this->propertyType; + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php new file mode 100644 index 000000000..742410cb2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php @@ -0,0 +1,78 @@ +getProperties() does not return private properties from ancestor classes. + * + * @author muratyaman@gmail.com + * @see http://php.net/manual/en/reflectionclass.getproperties.php + * + * @param ReflectionClass $ref + * + * @return ReflectionProperty[] + */ + public static function getProperties(ReflectionClass $ref) + { + $props = $ref->getProperties(); + $propsArr = array(); + + foreach ($props as $prop) { + $propertyName = $prop->getName(); + $propsArr[$propertyName] = $prop; + } + + if ($parentClass = $ref->getParentClass()) { + $parentPropsArr = self::getProperties($parentClass); + foreach ($propsArr as $key => $property) { + $parentPropsArr[$key] = $property; + } + + return $parentPropsArr; + } + + return $propsArr; + } + + /** + * Retrieves property by name from object and all its ancestors. + * + * @param object|string $object + * @param string $name + * + * @throws PropertyException + * @throws ReflectionException + * + * @return ReflectionProperty + */ + public static function getProperty($object, $name) + { + $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object); + + if ($reflection->hasProperty($name)) { + return $reflection->getProperty($name); + } + + if ($parentClass = $reflection->getParentClass()) { + return self::getProperty($parentClass->getName(), $name); + } + + throw new PropertyException( + sprintf( + 'The class "%s" doesn\'t have a property with the given name: "%s".', + is_object($object) ? get_class($object) : $object, + $name + ) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php new file mode 100644 index 000000000..becd1cfff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php @@ -0,0 +1,33 @@ + $propertyValue) { + $copy->{$propertyName} = $propertyValue; + } + + return $copy; + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DatePeriodFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DatePeriodFilter.php new file mode 100644 index 000000000..6bd2f7e57 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DatePeriodFilter.php @@ -0,0 +1,42 @@ += 80200 && $element->include_end_date) { + $options |= DatePeriod::INCLUDE_END_DATE; + } + if (!$element->include_start_date) { + $options |= DatePeriod::EXCLUDE_START_DATE; + } + + if ($element->getEndDate()) { + return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $element->getEndDate(), $options); + } + + if (PHP_VERSION_ID >= 70217) { + $recurrences = $element->getRecurrences(); + } else { + $recurrences = $element->recurrences - $element->include_start_date; + } + + return new DatePeriod($element->getStartDate(), $element->getDateInterval(), $recurrences, $options); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php new file mode 100644 index 000000000..164f8b8e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php @@ -0,0 +1,30 @@ +callback = $callable; + } + + /** + * {@inheritdoc} + */ + public function apply($element) + { + return call_user_func($this->callback, $element); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php new file mode 100644 index 000000000..a5fbd7a2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php @@ -0,0 +1,17 @@ +copier = $copier; + } + + /** + * {@inheritdoc} + */ + public function apply($arrayObject) + { + $clone = clone $arrayObject; + foreach ($arrayObject->getArrayCopy() as $k => $v) { + $clone->offsetSet($k, $this->copier->copy($v)); + } + + return $clone; + } +} + diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php new file mode 100644 index 000000000..c5644cff8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Spl/SplDoublyLinkedList.php @@ -0,0 +1,10 @@ +copier = $copier; + } + + /** + * {@inheritdoc} + */ + public function apply($element) + { + $newElement = clone $element; + + $copy = $this->createCopyClosure(); + + return $copy($newElement); + } + + private function createCopyClosure() + { + $copier = $this->copier; + + $copy = function (SplDoublyLinkedList $list) use ($copier) { + // Replace each element in the list with a deep copy of itself + for ($i = 1; $i <= $list->count(); $i++) { + $copy = $copier->recursiveCopy($list->shift()); + + $list->push($copy); + } + + return $list; + }; + + return Closure::bind($copy, null, DeepCopy::class); + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php new file mode 100644 index 000000000..5785a7da9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php @@ -0,0 +1,13 @@ +type = $type; + } + + /** + * @param mixed $element + * + * @return boolean + */ + public function matches($element) + { + return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type; + } +} diff --git a/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php new file mode 100644 index 000000000..55dcc9261 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php @@ -0,0 +1,20 @@ +copy($value); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/LICENSE b/.extlib/simplesamlphp/vendor/nikic/php-parser/LICENSE new file mode 100644 index 000000000..2e5671835 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2011, Nikita Popov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/nikic/php-parser/README.md b/.extlib/simplesamlphp/vendor/nikic/php-parser/README.md new file mode 100644 index 000000000..3bca288b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/README.md @@ -0,0 +1,225 @@ +PHP Parser +========== + +[![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master) + +This is a PHP 5.2 to PHP 8.2 parser written in PHP. Its purpose is to simplify static code analysis and +manipulation. + +[**Documentation for version 4.x**][doc_4_x] (stable; for running on PHP >= 7.1; for parsing PHP 5.2 to PHP 8.2). + +[Documentation for version 3.x][doc_3_x] (unsupported; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.2). + +Features +-------- + +The main features provided by this library are: + + * Parsing PHP 5, PHP 7, and PHP 8 code into an abstract syntax tree (AST). + * Invalid code can be parsed into a partial AST. + * The AST contains accurate location information. + * Dumping the AST in human-readable form. + * Converting an AST back to PHP code. + * Experimental: Formatting can be preserved for partially changed ASTs. + * Infrastructure to traverse and modify ASTs. + * Resolution of namespaced names. + * Evaluation of constant expressions. + * Builders to simplify AST construction for code generation. + * Converting an AST into JSON and back. + +Quick Start +----------- + +Install the library using [composer](https://getcomposer.org): + + php composer.phar require nikic/php-parser + +Parse some PHP code into an AST and dump the result in human-readable form: + +```php +create(ParserFactory::PREFER_PHP7); +try { + $ast = $parser->parse($code); +} catch (Error $error) { + echo "Parse error: {$error->getMessage()}\n"; + return; +} + +$dumper = new NodeDumper; +echo $dumper->dump($ast) . "\n"; +``` + +This dumps an AST looking something like this: + +``` +array( + 0: Stmt_Function( + byRef: false + name: Identifier( + name: test + ) + params: array( + 0: Param( + type: null + byRef: false + variadic: false + var: Expr_Variable( + name: foo + ) + default: null + ) + ) + returnType: null + stmts: array( + 0: Stmt_Expression( + expr: Expr_FuncCall( + name: Name( + parts: array( + 0: var_dump + ) + ) + args: array( + 0: Arg( + value: Expr_Variable( + name: foo + ) + byRef: false + unpack: false + ) + ) + ) + ) + ) + ) +) +``` + +Let's traverse the AST and perform some kind of modification. For example, drop all function bodies: + +```php +use PhpParser\Node; +use PhpParser\Node\Stmt\Function_; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitorAbstract; + +$traverser = new NodeTraverser(); +$traverser->addVisitor(new class extends NodeVisitorAbstract { + public function enterNode(Node $node) { + if ($node instanceof Function_) { + // Clean out the function body + $node->stmts = []; + } + } +}); + +$ast = $traverser->traverse($ast); +echo $dumper->dump($ast) . "\n"; +``` + +This gives us an AST where the `Function_::$stmts` are empty: + +``` +array( + 0: Stmt_Function( + byRef: false + name: Identifier( + name: test + ) + params: array( + 0: Param( + type: null + byRef: false + variadic: false + var: Expr_Variable( + name: foo + ) + default: null + ) + ) + returnType: null + stmts: array( + ) + ) +) +``` + +Finally, we can convert the new AST back to PHP code: + +```php +use PhpParser\PrettyPrinter; + +$prettyPrinter = new PrettyPrinter\Standard; +echo $prettyPrinter->prettyPrintFile($ast); +``` + +This gives us our original code, minus the `var_dump()` call inside the function: + +```php + [ + 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' +]]); +$parser = (new PhpParser\ParserFactory)->create( + PhpParser\ParserFactory::PREFER_PHP7, + $lexer +); +$dumper = new PhpParser\NodeDumper([ + 'dumpComments' => true, + 'dumpPositions' => $attributes['with-positions'], +]); +$prettyPrinter = new PhpParser\PrettyPrinter\Standard; + +$traverser = new PhpParser\NodeTraverser(); +$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); + +foreach ($files as $file) { + if (strpos($file, ' Code $code\n"); + } else { + if (!file_exists($file)) { + fwrite(STDERR, "File $file does not exist.\n"); + exit(1); + } + + $code = file_get_contents($file); + fwrite(STDERR, "====> File $file:\n"); + } + + if ($attributes['with-recovery']) { + $errorHandler = new PhpParser\ErrorHandler\Collecting; + $stmts = $parser->parse($code, $errorHandler); + foreach ($errorHandler->getErrors() as $error) { + $message = formatErrorMessage($error, $code, $attributes['with-column-info']); + fwrite(STDERR, $message . "\n"); + } + if (null === $stmts) { + continue; + } + } else { + try { + $stmts = $parser->parse($code); + } catch (PhpParser\Error $error) { + $message = formatErrorMessage($error, $code, $attributes['with-column-info']); + fwrite(STDERR, $message . "\n"); + exit(1); + } + } + + foreach ($operations as $operation) { + if ('dump' === $operation) { + fwrite(STDERR, "==> Node dump:\n"); + echo $dumper->dump($stmts, $code), "\n"; + } elseif ('pretty-print' === $operation) { + fwrite(STDERR, "==> Pretty print:\n"); + echo $prettyPrinter->prettyPrintFile($stmts), "\n"; + } elseif ('json-dump' === $operation) { + fwrite(STDERR, "==> JSON dump:\n"); + echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; + } elseif ('var-dump' === $operation) { + fwrite(STDERR, "==> var_dump():\n"); + var_dump($stmts); + } elseif ('resolve-names' === $operation) { + fwrite(STDERR, "==> Resolved names.\n"); + $stmts = $traverser->traverse($stmts); + } + } +} + +function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) { + if ($withColumnInfo && $e->hasColumnInfo()) { + return $e->getMessageWithColumnInfo($code); + } else { + return $e->getMessage(); + } +} + +function showHelp($error = '') { + if ($error) { + fwrite(STDERR, $error . "\n\n"); + } + fwrite($error ? STDERR : STDOUT, << false, + 'with-positions' => false, + 'with-recovery' => false, + ]; + + array_shift($args); + $parseOptions = true; + foreach ($args as $arg) { + if (!$parseOptions) { + $files[] = $arg; + continue; + } + + switch ($arg) { + case '--dump': + case '-d': + $operations[] = 'dump'; + break; + case '--pretty-print': + case '-p': + $operations[] = 'pretty-print'; + break; + case '--json-dump': + case '-j': + $operations[] = 'json-dump'; + break; + case '--var-dump': + $operations[] = 'var-dump'; + break; + case '--resolve-names': + case '-N'; + $operations[] = 'resolve-names'; + break; + case '--with-column-info': + case '-c'; + $attributes['with-column-info'] = true; + break; + case '--with-positions': + case '-P': + $attributes['with-positions'] = true; + break; + case '--with-recovery': + case '-r': + $attributes['with-recovery'] = true; + break; + case '--help': + case '-h'; + showHelp(); + break; + case '--': + $parseOptions = false; + break; + default: + if ($arg[0] === '-') { + showHelp("Invalid operation $arg."); + } else { + $files[] = $arg; + } + } + } + + return [$operations, $files, $attributes]; +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/composer.json b/.extlib/simplesamlphp/vendor/nikic/php-parser/composer.json new file mode 100644 index 000000000..6eef359e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/composer.json @@ -0,0 +1,41 @@ +{ + "name": "nikic/php-parser", + "type": "library", + "description": "A PHP parser written in PHP", + "keywords": [ + "php", + "parser" + ], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov" + } + ], + "require": { + "php": ">=7.1", + "ext-tokenizer": "*" + }, + "require-dev": { + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "ircmaxell/php-yacc": "^0.0.7" + }, + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "autoload-dev": { + "psr-4": { + "PhpParser\\": "test/PhpParser/" + } + }, + "bin": [ + "bin/php-parse" + ] +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder.php new file mode 100644 index 000000000..26d8921ef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder.php @@ -0,0 +1,13 @@ +constants = [new Const_($name, BuilderHelpers::normalizeValue($value))]; + } + + /** + * Add another constant to const group + * + * @param string|Identifier $name Name + * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value + * + * @return $this The builder instance (for fluid interface) + */ + public function addConst($name, $value) { + $this->constants[] = new Const_($name, BuilderHelpers::normalizeValue($value)); + + return $this; + } + + /** + * Makes the constant public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the constant protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the constant private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the constant final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + /** + * Sets doc comment for the constant. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = [ + 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] + ]; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Sets the constant type. + * + * @param string|Node\Name|Identifier|Node\ComplexType $type + * + * @return $this + */ + public function setType($type) { + $this->type = BuilderHelpers::normalizeType($type); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\ClassConst The built constant node + */ + public function getNode(): PhpParser\Node { + return new Stmt\ClassConst( + $this->constants, + $this->flags, + $this->attributes, + $this->attributeGroups, + $this->type + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php new file mode 100644 index 000000000..35b54d041 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php @@ -0,0 +1,146 @@ +name = $name; + } + + /** + * Extends a class. + * + * @param Name|string $class Name of class to extend + * + * @return $this The builder instance (for fluid interface) + */ + public function extend($class) { + $this->extends = BuilderHelpers::normalizeName($class); + + return $this; + } + + /** + * Implements one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to implement + * + * @return $this The builder instance (for fluid interface) + */ + public function implement(...$interfaces) { + foreach ($interfaces as $interface) { + $this->implements[] = BuilderHelpers::normalizeName($interface); + } + + return $this; + } + + /** + * Makes the class abstract. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeAbstract() { + $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); + + return $this; + } + + /** + * Makes the class final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + public function makeReadonly() { + $this->flags = BuilderHelpers::addClassModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + $targets = [ + Stmt\TraitUse::class => &$this->uses, + Stmt\ClassConst::class => &$this->constants, + Stmt\Property::class => &$this->properties, + Stmt\ClassMethod::class => &$this->methods, + ]; + + $class = \get_class($stmt); + if (!isset($targets[$class])) { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + $targets[$class][] = $stmt; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Class_ The built class node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Class_($this->name, [ + 'flags' => $this->flags, + 'extends' => $this->extends, + 'implements' => $this->implements, + 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php new file mode 100644 index 000000000..830949928 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php @@ -0,0 +1,43 @@ +addStmt($stmt); + } + + return $this; + } + + /** + * Sets doc comment for the declaration. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes['comments'] = [ + BuilderHelpers::normalizeDocComment($docComment) + ]; + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php new file mode 100644 index 000000000..accc5166b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php @@ -0,0 +1,85 @@ +name = $name; + } + + /** + * Sets the value. + * + * @param Node\Expr|string|int $value + * + * @return $this + */ + public function setValue($value) { + $this->value = BuilderHelpers::normalizeValue($value); + + return $this; + } + + /** + * Sets doc comment for the constant. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = [ + 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] + ]; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built enum case node. + * + * @return Stmt\EnumCase The built constant node + */ + public function getNode(): PhpParser\Node { + return new Stmt\EnumCase( + $this->name, + $this->value, + $this->attributeGroups, + $this->attributes + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php new file mode 100644 index 000000000..be7eef95f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php @@ -0,0 +1,117 @@ +name = $name; + } + + /** + * Sets the scalar type. + * + * @param string|Identifier $type + * + * @return $this + */ + public function setScalarType($scalarType) { + $this->scalarType = BuilderHelpers::normalizeType($scalarType); + + return $this; + } + + /** + * Implements one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to implement + * + * @return $this The builder instance (for fluid interface) + */ + public function implement(...$interfaces) { + foreach ($interfaces as $interface) { + $this->implements[] = BuilderHelpers::normalizeName($interface); + } + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + $targets = [ + Stmt\TraitUse::class => &$this->uses, + Stmt\EnumCase::class => &$this->enumCases, + Stmt\ClassConst::class => &$this->constants, + Stmt\ClassMethod::class => &$this->methods, + ]; + + $class = \get_class($stmt); + if (!isset($targets[$class])) { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + $targets[$class][] = $stmt; + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Enum_ The built enum node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Enum_($this->name, [ + 'scalarType' => $this->scalarType, + 'implements' => $this->implements, + 'stmts' => array_merge($this->uses, $this->enumCases, $this->constants, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php new file mode 100644 index 000000000..98ea9d336 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php @@ -0,0 +1,73 @@ +returnByRef = true; + + return $this; + } + + /** + * Adds a parameter. + * + * @param Node\Param|Param $param The parameter to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addParam($param) { + $param = BuilderHelpers::normalizeNode($param); + + if (!$param instanceof Node\Param) { + throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); + } + + $this->params[] = $param; + + return $this; + } + + /** + * Adds multiple parameters. + * + * @param array $params The parameters to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addParams(array $params) { + foreach ($params as $param) { + $this->addParam($param); + } + + return $this; + } + + /** + * Sets the return type for PHP 7. + * + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type + * + * @return $this The builder instance (for fluid interface) + */ + public function setReturnType($type) { + $this->returnType = BuilderHelpers::normalizeType($type); + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php new file mode 100644 index 000000000..1cd73c0d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php @@ -0,0 +1,67 @@ +name = $name; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built function node. + * + * @return Stmt\Function_ The built function node + */ + public function getNode() : Node { + return new Stmt\Function_($this->name, [ + 'byRef' => $this->returnByRef, + 'params' => $this->params, + 'returnType' => $this->returnType, + 'stmts' => $this->stmts, + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php new file mode 100644 index 000000000..7806e85fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php @@ -0,0 +1,93 @@ +name = $name; + } + + /** + * Extends one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to extend + * + * @return $this The builder instance (for fluid interface) + */ + public function extend(...$interfaces) { + foreach ($interfaces as $interface) { + $this->extends[] = BuilderHelpers::normalizeName($interface); + } + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + if ($stmt instanceof Stmt\ClassConst) { + $this->constants[] = $stmt; + } elseif ($stmt instanceof Stmt\ClassMethod) { + // we erase all statements in the body of an interface method + $stmt->stmts = null; + $this->methods[] = $stmt; + } else { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built interface node. + * + * @return Stmt\Interface_ The built interface node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Interface_($this->name, [ + 'extends' => $this->extends, + 'stmts' => array_merge($this->constants, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php new file mode 100644 index 000000000..232d7cb87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php @@ -0,0 +1,146 @@ +name = $name; + } + + /** + * Makes the method public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the method protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the method private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the method static. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeStatic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); + + return $this; + } + + /** + * Makes the method abstract. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeAbstract() { + if (!empty($this->stmts)) { + throw new \LogicException('Cannot make method with statements abstract'); + } + + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT); + $this->stmts = null; // abstract methods don't have statements + + return $this; + } + + /** + * Makes the method final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + if (null === $this->stmts) { + throw new \LogicException('Cannot add statements to an abstract method'); + } + + $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built method node. + * + * @return Stmt\ClassMethod The built method node + */ + public function getNode() : Node { + return new Stmt\ClassMethod($this->name, [ + 'flags' => $this->flags, + 'byRef' => $this->returnByRef, + 'params' => $this->params, + 'returnType' => $this->returnType, + 'stmts' => $this->stmts, + 'attrGroups' => $this->attributeGroups, + ], $this->attributes); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php new file mode 100644 index 000000000..1c751e163 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php @@ -0,0 +1,45 @@ +name = null !== $name ? BuilderHelpers::normalizeName($name) : null; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $this->stmts[] = BuilderHelpers::normalizeStmt($stmt); + + return $this; + } + + /** + * Returns the built node. + * + * @return Stmt\Namespace_ The built node + */ + public function getNode() : Node { + return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php new file mode 100644 index 000000000..69f353326 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php @@ -0,0 +1,168 @@ +name = $name; + } + + /** + * Sets default value for the parameter. + * + * @param mixed $value Default value to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setDefault($value) { + $this->default = BuilderHelpers::normalizeValue($value); + + return $this; + } + + /** + * Sets type for the parameter. + * + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type + * + * @return $this The builder instance (for fluid interface) + */ + public function setType($type) { + $this->type = BuilderHelpers::normalizeType($type); + if ($this->type == 'void') { + throw new \LogicException('Parameter type cannot be void'); + } + + return $this; + } + + /** + * Sets type for the parameter. + * + * @param string|Node\Name|Node\Identifier|Node\ComplexType $type Parameter type + * + * @return $this The builder instance (for fluid interface) + * + * @deprecated Use setType() instead + */ + public function setTypeHint($type) { + return $this->setType($type); + } + + /** + * Make the parameter accept the value by reference. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeByRef() { + $this->byRef = true; + + return $this; + } + + /** + * Make the parameter variadic + * + * @return $this The builder instance (for fluid interface) + */ + public function makeVariadic() { + $this->variadic = true; + + return $this; + } + + /** + * Makes the (promoted) parameter public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the (promoted) parameter protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the (promoted) parameter private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the (promoted) parameter readonly. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeReadonly() { + $this->flags = BuilderHelpers::addModifier($this->flags, Node\Stmt\Class_::MODIFIER_READONLY); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built parameter node. + * + * @return Node\Param The built parameter node + */ + public function getNode() : Node { + return new Node\Param( + new Node\Expr\Variable($this->name), + $this->default, $this->type, $this->byRef, $this->variadic, [], $this->flags, $this->attributeGroups + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php new file mode 100644 index 000000000..68e318565 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php @@ -0,0 +1,161 @@ +name = $name; + } + + /** + * Makes the property public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the property protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the property private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the property static. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeStatic() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC); + + return $this; + } + + /** + * Makes the property readonly. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeReadonly() { + $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_READONLY); + + return $this; + } + + /** + * Sets default value for the property. + * + * @param mixed $value Default value to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setDefault($value) { + $this->default = BuilderHelpers::normalizeValue($value); + + return $this; + } + + /** + * Sets doc comment for the property. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = [ + 'comments' => [BuilderHelpers::normalizeDocComment($docComment)] + ]; + + return $this; + } + + /** + * Sets the property type for PHP 7.4+. + * + * @param string|Name|Identifier|ComplexType $type + * + * @return $this + */ + public function setType($type) { + $this->type = BuilderHelpers::normalizeType($type); + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Property The built property node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Property( + $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC, + [ + new Stmt\PropertyProperty($this->name, $this->default) + ], + $this->attributes, + $this->type, + $this->attributeGroups + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php new file mode 100644 index 000000000..311e8cd7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php @@ -0,0 +1,64 @@ +and($trait); + } + } + + /** + * Adds used trait. + * + * @param Node\Name|string $trait Trait name + * + * @return $this The builder instance (for fluid interface) + */ + public function and($trait) { + $this->traits[] = BuilderHelpers::normalizeName($trait); + return $this; + } + + /** + * Adds trait adaptation. + * + * @param Stmt\TraitUseAdaptation|Builder\TraitUseAdaptation $adaptation Trait adaptation + * + * @return $this The builder instance (for fluid interface) + */ + public function with($adaptation) { + $adaptation = BuilderHelpers::normalizeNode($adaptation); + + if (!$adaptation instanceof Stmt\TraitUseAdaptation) { + throw new \LogicException('Adaptation must have type TraitUseAdaptation'); + } + + $this->adaptations[] = $adaptation; + return $this; + } + + /** + * Returns the built node. + * + * @return Node The built node + */ + public function getNode() : Node { + return new Stmt\TraitUse($this->traits, $this->adaptations); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php new file mode 100644 index 000000000..eb6c0b622 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php @@ -0,0 +1,148 @@ +type = self::TYPE_UNDEFINED; + + $this->trait = is_null($trait)? null: BuilderHelpers::normalizeName($trait); + $this->method = BuilderHelpers::normalizeIdentifier($method); + } + + /** + * Sets alias of method. + * + * @param Node\Identifier|string $alias Alias for adaptated method + * + * @return $this The builder instance (for fluid interface) + */ + public function as($alias) { + if ($this->type === self::TYPE_UNDEFINED) { + $this->type = self::TYPE_ALIAS; + } + + if ($this->type !== self::TYPE_ALIAS) { + throw new \LogicException('Cannot set alias for not alias adaptation buider'); + } + + $this->alias = $alias; + return $this; + } + + /** + * Sets adaptated method public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); + return $this; + } + + /** + * Sets adaptated method protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); + return $this; + } + + /** + * Sets adaptated method private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); + return $this; + } + + /** + * Adds overwritten traits. + * + * @param Node\Name|string ...$traits Traits for overwrite + * + * @return $this The builder instance (for fluid interface) + */ + public function insteadof(...$traits) { + if ($this->type === self::TYPE_UNDEFINED) { + if (is_null($this->trait)) { + throw new \LogicException('Precedence adaptation must have trait'); + } + + $this->type = self::TYPE_PRECEDENCE; + } + + if ($this->type !== self::TYPE_PRECEDENCE) { + throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider'); + } + + foreach ($traits as $trait) { + $this->insteadof[] = BuilderHelpers::normalizeName($trait); + } + + return $this; + } + + protected function setModifier(int $modifier) { + if ($this->type === self::TYPE_UNDEFINED) { + $this->type = self::TYPE_ALIAS; + } + + if ($this->type !== self::TYPE_ALIAS) { + throw new \LogicException('Cannot set access modifier for not alias adaptation buider'); + } + + if (is_null($this->modifier)) { + $this->modifier = $modifier; + } else { + throw new \LogicException('Multiple access type modifiers are not allowed'); + } + } + + /** + * Returns the built node. + * + * @return Node The built node + */ + public function getNode() : Node { + switch ($this->type) { + case self::TYPE_ALIAS: + return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias); + case self::TYPE_PRECEDENCE: + return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof); + default: + throw new \LogicException('Type of adaptation is not defined'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php new file mode 100644 index 000000000..97f32f98d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php @@ -0,0 +1,78 @@ +name = $name; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = BuilderHelpers::normalizeNode($stmt); + + if ($stmt instanceof Stmt\Property) { + $this->properties[] = $stmt; + } elseif ($stmt instanceof Stmt\ClassMethod) { + $this->methods[] = $stmt; + } elseif ($stmt instanceof Stmt\TraitUse) { + $this->uses[] = $stmt; + } else { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + return $this; + } + + /** + * Adds an attribute group. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return $this The builder instance (for fluid interface) + */ + public function addAttribute($attribute) { + $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute); + + return $this; + } + + /** + * Returns the built trait node. + * + * @return Stmt\Trait_ The built interface node + */ + public function getNode() : PhpParser\Node { + return new Stmt\Trait_( + $this->name, [ + 'stmts' => array_merge($this->uses, $this->properties, $this->methods), + 'attrGroups' => $this->attributeGroups, + ], $this->attributes + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php new file mode 100644 index 000000000..4bd3d12df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php @@ -0,0 +1,49 @@ +name = BuilderHelpers::normalizeName($name); + $this->type = $type; + } + + /** + * Sets alias for used name. + * + * @param string $alias Alias to use (last component of full name by default) + * + * @return $this The builder instance (for fluid interface) + */ + public function as(string $alias) { + $this->alias = $alias; + return $this; + } + + /** + * Returns the built node. + * + * @return Stmt\Use_ The built node + */ + public function getNode() : Node { + return new Stmt\Use_([ + new Stmt\UseUse($this->name, $this->alias) + ], $this->type); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php new file mode 100644 index 000000000..0aae8738c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php @@ -0,0 +1,399 @@ +args($args) + ); + } + + /** + * Creates a namespace builder. + * + * @param null|string|Node\Name $name Name of the namespace + * + * @return Builder\Namespace_ The created namespace builder + */ + public function namespace($name) : Builder\Namespace_ { + return new Builder\Namespace_($name); + } + + /** + * Creates a class builder. + * + * @param string $name Name of the class + * + * @return Builder\Class_ The created class builder + */ + public function class(string $name) : Builder\Class_ { + return new Builder\Class_($name); + } + + /** + * Creates an interface builder. + * + * @param string $name Name of the interface + * + * @return Builder\Interface_ The created interface builder + */ + public function interface(string $name) : Builder\Interface_ { + return new Builder\Interface_($name); + } + + /** + * Creates a trait builder. + * + * @param string $name Name of the trait + * + * @return Builder\Trait_ The created trait builder + */ + public function trait(string $name) : Builder\Trait_ { + return new Builder\Trait_($name); + } + + /** + * Creates an enum builder. + * + * @param string $name Name of the enum + * + * @return Builder\Enum_ The created enum builder + */ + public function enum(string $name) : Builder\Enum_ { + return new Builder\Enum_($name); + } + + /** + * Creates a trait use builder. + * + * @param Node\Name|string ...$traits Trait names + * + * @return Builder\TraitUse The create trait use builder + */ + public function useTrait(...$traits) : Builder\TraitUse { + return new Builder\TraitUse(...$traits); + } + + /** + * Creates a trait use adaptation builder. + * + * @param Node\Name|string|null $trait Trait name + * @param Node\Identifier|string $method Method name + * + * @return Builder\TraitUseAdaptation The create trait use adaptation builder + */ + public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation { + if ($method === null) { + $method = $trait; + $trait = null; + } + + return new Builder\TraitUseAdaptation($trait, $method); + } + + /** + * Creates a method builder. + * + * @param string $name Name of the method + * + * @return Builder\Method The created method builder + */ + public function method(string $name) : Builder\Method { + return new Builder\Method($name); + } + + /** + * Creates a parameter builder. + * + * @param string $name Name of the parameter + * + * @return Builder\Param The created parameter builder + */ + public function param(string $name) : Builder\Param { + return new Builder\Param($name); + } + + /** + * Creates a property builder. + * + * @param string $name Name of the property + * + * @return Builder\Property The created property builder + */ + public function property(string $name) : Builder\Property { + return new Builder\Property($name); + } + + /** + * Creates a function builder. + * + * @param string $name Name of the function + * + * @return Builder\Function_ The created function builder + */ + public function function(string $name) : Builder\Function_ { + return new Builder\Function_($name); + } + + /** + * Creates a namespace/class use builder. + * + * @param Node\Name|string $name Name of the entity (namespace or class) to alias + * + * @return Builder\Use_ The created use builder + */ + public function use($name) : Builder\Use_ { + return new Builder\Use_($name, Use_::TYPE_NORMAL); + } + + /** + * Creates a function use builder. + * + * @param Node\Name|string $name Name of the function to alias + * + * @return Builder\Use_ The created use function builder + */ + public function useFunction($name) : Builder\Use_ { + return new Builder\Use_($name, Use_::TYPE_FUNCTION); + } + + /** + * Creates a constant use builder. + * + * @param Node\Name|string $name Name of the const to alias + * + * @return Builder\Use_ The created use const builder + */ + public function useConst($name) : Builder\Use_ { + return new Builder\Use_($name, Use_::TYPE_CONSTANT); + } + + /** + * Creates a class constant builder. + * + * @param string|Identifier $name Name + * @param Node\Expr|bool|null|int|float|string|array $value Value + * + * @return Builder\ClassConst The created use const builder + */ + public function classConst($name, $value) : Builder\ClassConst { + return new Builder\ClassConst($name, $value); + } + + /** + * Creates an enum case builder. + * + * @param string|Identifier $name Name + * + * @return Builder\EnumCase The created use const builder + */ + public function enumCase($name) : Builder\EnumCase { + return new Builder\EnumCase($name); + } + + /** + * Creates node a for a literal value. + * + * @param Expr|bool|null|int|float|string|array|\UnitEnum $value $value + * + * @return Expr + */ + public function val($value) : Expr { + return BuilderHelpers::normalizeValue($value); + } + + /** + * Creates variable node. + * + * @param string|Expr $name Name + * + * @return Expr\Variable + */ + public function var($name) : Expr\Variable { + if (!\is_string($name) && !$name instanceof Expr) { + throw new \LogicException('Variable name must be string or Expr'); + } + + return new Expr\Variable($name); + } + + /** + * Normalizes an argument list. + * + * Creates Arg nodes for all arguments and converts literal values to expressions. + * + * @param array $args List of arguments to normalize + * + * @return Arg[] + */ + public function args(array $args) : array { + $normalizedArgs = []; + foreach ($args as $key => $arg) { + if (!($arg instanceof Arg)) { + $arg = new Arg(BuilderHelpers::normalizeValue($arg)); + } + if (\is_string($key)) { + $arg->name = BuilderHelpers::normalizeIdentifier($key); + } + $normalizedArgs[] = $arg; + } + return $normalizedArgs; + } + + /** + * Creates a function call node. + * + * @param string|Name|Expr $name Function name + * @param array $args Function arguments + * + * @return Expr\FuncCall + */ + public function funcCall($name, array $args = []) : Expr\FuncCall { + return new Expr\FuncCall( + BuilderHelpers::normalizeNameOrExpr($name), + $this->args($args) + ); + } + + /** + * Creates a method call node. + * + * @param Expr $var Variable the method is called on + * @param string|Identifier|Expr $name Method name + * @param array $args Method arguments + * + * @return Expr\MethodCall + */ + public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall { + return new Expr\MethodCall( + $var, + BuilderHelpers::normalizeIdentifierOrExpr($name), + $this->args($args) + ); + } + + /** + * Creates a static method call node. + * + * @param string|Name|Expr $class Class name + * @param string|Identifier|Expr $name Method name + * @param array $args Method arguments + * + * @return Expr\StaticCall + */ + public function staticCall($class, $name, array $args = []) : Expr\StaticCall { + return new Expr\StaticCall( + BuilderHelpers::normalizeNameOrExpr($class), + BuilderHelpers::normalizeIdentifierOrExpr($name), + $this->args($args) + ); + } + + /** + * Creates an object creation node. + * + * @param string|Name|Expr $class Class name + * @param array $args Constructor arguments + * + * @return Expr\New_ + */ + public function new($class, array $args = []) : Expr\New_ { + return new Expr\New_( + BuilderHelpers::normalizeNameOrExpr($class), + $this->args($args) + ); + } + + /** + * Creates a constant fetch node. + * + * @param string|Name $name Constant name + * + * @return Expr\ConstFetch + */ + public function constFetch($name) : Expr\ConstFetch { + return new Expr\ConstFetch(BuilderHelpers::normalizeName($name)); + } + + /** + * Creates a property fetch node. + * + * @param Expr $var Variable holding object + * @param string|Identifier|Expr $name Property name + * + * @return Expr\PropertyFetch + */ + public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch { + return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name)); + } + + /** + * Creates a class constant fetch node. + * + * @param string|Name|Expr $class Class name + * @param string|Identifier|Expr $name Constant name + * + * @return Expr\ClassConstFetch + */ + public function classConstFetch($class, $name): Expr\ClassConstFetch { + return new Expr\ClassConstFetch( + BuilderHelpers::normalizeNameOrExpr($class), + BuilderHelpers::normalizeIdentifierOrExpr($name) + ); + } + + /** + * Creates nested Concat nodes from a list of expressions. + * + * @param Expr|string ...$exprs Expressions or literal strings + * + * @return Concat + */ + public function concat(...$exprs) : Concat { + $numExprs = count($exprs); + if ($numExprs < 2) { + throw new \LogicException('Expected at least two expressions'); + } + + $lastConcat = $this->normalizeStringExpr($exprs[0]); + for ($i = 1; $i < $numExprs; $i++) { + $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i])); + } + return $lastConcat; + } + + /** + * @param string|Expr $expr + * @return Expr + */ + private function normalizeStringExpr($expr) : Expr { + if ($expr instanceof Expr) { + return $expr; + } + + if (\is_string($expr)) { + return new String_($expr); + } + + throw new \LogicException('Expected string or Expr'); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php new file mode 100644 index 000000000..05e7868f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php @@ -0,0 +1,340 @@ +getNode(); + } + + if ($node instanceof Node) { + return $node; + } + + throw new \LogicException('Expected node or builder object'); + } + + /** + * Normalizes a node to a statement. + * + * Expressions are wrapped in a Stmt\Expression node. + * + * @param Node|Builder $node The node to normalize + * + * @return Stmt The normalized statement node + */ + public static function normalizeStmt($node) : Stmt { + $node = self::normalizeNode($node); + if ($node instanceof Stmt) { + return $node; + } + + if ($node instanceof Expr) { + return new Stmt\Expression($node); + } + + throw new \LogicException('Expected statement or expression node'); + } + + /** + * Normalizes strings to Identifier. + * + * @param string|Identifier $name The identifier to normalize + * + * @return Identifier The normalized identifier + */ + public static function normalizeIdentifier($name) : Identifier { + if ($name instanceof Identifier) { + return $name; + } + + if (\is_string($name)) { + return new Identifier($name); + } + + throw new \LogicException('Expected string or instance of Node\Identifier'); + } + + /** + * Normalizes strings to Identifier, also allowing expressions. + * + * @param string|Identifier|Expr $name The identifier to normalize + * + * @return Identifier|Expr The normalized identifier or expression + */ + public static function normalizeIdentifierOrExpr($name) { + if ($name instanceof Identifier || $name instanceof Expr) { + return $name; + } + + if (\is_string($name)) { + return new Identifier($name); + } + + throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr'); + } + + /** + * Normalizes a name: Converts string names to Name nodes. + * + * @param Name|string $name The name to normalize + * + * @return Name The normalized name + */ + public static function normalizeName($name) : Name { + if ($name instanceof Name) { + return $name; + } + + if (is_string($name)) { + if (!$name) { + throw new \LogicException('Name cannot be empty'); + } + + if ($name[0] === '\\') { + return new Name\FullyQualified(substr($name, 1)); + } + + if (0 === strpos($name, 'namespace\\')) { + return new Name\Relative(substr($name, strlen('namespace\\'))); + } + + return new Name($name); + } + + throw new \LogicException('Name must be a string or an instance of Node\Name'); + } + + /** + * Normalizes a name: Converts string names to Name nodes, while also allowing expressions. + * + * @param Expr|Name|string $name The name to normalize + * + * @return Name|Expr The normalized name or expression + */ + public static function normalizeNameOrExpr($name) { + if ($name instanceof Expr) { + return $name; + } + + if (!is_string($name) && !($name instanceof Name)) { + throw new \LogicException( + 'Name must be a string or an instance of Node\Name or Node\Expr' + ); + } + + return self::normalizeName($name); + } + + /** + * Normalizes a type: Converts plain-text type names into proper AST representation. + * + * In particular, builtin types become Identifiers, custom types become Names and nullables + * are wrapped in NullableType nodes. + * + * @param string|Name|Identifier|ComplexType $type The type to normalize + * + * @return Name|Identifier|ComplexType The normalized type + */ + public static function normalizeType($type) { + if (!is_string($type)) { + if ( + !$type instanceof Name && !$type instanceof Identifier && + !$type instanceof ComplexType + ) { + throw new \LogicException( + 'Type must be a string, or an instance of Name, Identifier or ComplexType' + ); + } + return $type; + } + + $nullable = false; + if (strlen($type) > 0 && $type[0] === '?') { + $nullable = true; + $type = substr($type, 1); + } + + $builtinTypes = [ + 'array', + 'callable', + 'bool', + 'int', + 'float', + 'string', + 'iterable', + 'void', + 'object', + 'null', + 'false', + 'mixed', + 'never', + 'true', + ]; + + $lowerType = strtolower($type); + if (in_array($lowerType, $builtinTypes)) { + $type = new Identifier($lowerType); + } else { + $type = self::normalizeName($type); + } + + $notNullableTypes = [ + 'void', 'mixed', 'never', + ]; + if ($nullable && in_array((string) $type, $notNullableTypes)) { + throw new \LogicException(sprintf('%s type cannot be nullable', $type)); + } + + return $nullable ? new NullableType($type) : $type; + } + + /** + * Normalizes a value: Converts nulls, booleans, integers, + * floats, strings and arrays into their respective nodes + * + * @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value The value to normalize + * + * @return Expr The normalized value + */ + public static function normalizeValue($value) : Expr { + if ($value instanceof Node\Expr) { + return $value; + } + + if (is_null($value)) { + return new Expr\ConstFetch( + new Name('null') + ); + } + + if (is_bool($value)) { + return new Expr\ConstFetch( + new Name($value ? 'true' : 'false') + ); + } + + if (is_int($value)) { + return new Scalar\LNumber($value); + } + + if (is_float($value)) { + return new Scalar\DNumber($value); + } + + if (is_string($value)) { + return new Scalar\String_($value); + } + + if (is_array($value)) { + $items = []; + $lastKey = -1; + foreach ($value as $itemKey => $itemValue) { + // for consecutive, numeric keys don't generate keys + if (null !== $lastKey && ++$lastKey === $itemKey) { + $items[] = new Expr\ArrayItem( + self::normalizeValue($itemValue) + ); + } else { + $lastKey = null; + $items[] = new Expr\ArrayItem( + self::normalizeValue($itemValue), + self::normalizeValue($itemKey) + ); + } + } + + return new Expr\Array_($items); + } + + if ($value instanceof \UnitEnum) { + return new Expr\ClassConstFetch(new FullyQualified(\get_class($value)), new Identifier($value->name)); + } + + throw new \LogicException('Invalid value'); + } + + /** + * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. + * + * @param Comment\Doc|string $docComment The doc comment to normalize + * + * @return Comment\Doc The normalized doc comment + */ + public static function normalizeDocComment($docComment) : Comment\Doc { + if ($docComment instanceof Comment\Doc) { + return $docComment; + } + + if (is_string($docComment)) { + return new Comment\Doc($docComment); + } + + throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); + } + + /** + * Normalizes a attribute: Converts attribute to the Attribute Group if needed. + * + * @param Node\Attribute|Node\AttributeGroup $attribute + * + * @return Node\AttributeGroup The Attribute Group + */ + public static function normalizeAttribute($attribute) : Node\AttributeGroup + { + if ($attribute instanceof Node\AttributeGroup) { + return $attribute; + } + + if (!($attribute instanceof Node\Attribute)) { + throw new \LogicException('Attribute must be an instance of PhpParser\Node\Attribute or PhpParser\Node\AttributeGroup'); + } + + return new Node\AttributeGroup([$attribute]); + } + + /** + * Adds a modifier and returns new modifier bitmask. + * + * @param int $modifiers Existing modifiers + * @param int $modifier Modifier to set + * + * @return int New modifiers + */ + public static function addModifier(int $modifiers, int $modifier) : int { + Stmt\Class_::verifyModifier($modifiers, $modifier); + return $modifiers | $modifier; + } + + /** + * Adds a modifier and returns new modifier bitmask. + * @return int New modifiers + */ + public static function addClassModifier(int $existingModifiers, int $modifierToSet) : int { + Stmt\Class_::verifyClassModifier($existingModifiers, $modifierToSet); + return $existingModifiers | $modifierToSet; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment.php new file mode 100644 index 000000000..61e98d3dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment.php @@ -0,0 +1,239 @@ +text = $text; + $this->startLine = $startLine; + $this->startFilePos = $startFilePos; + $this->startTokenPos = $startTokenPos; + $this->endLine = $endLine; + $this->endFilePos = $endFilePos; + $this->endTokenPos = $endTokenPos; + } + + /** + * Gets the comment text. + * + * @return string The comment text (including comment delimiters like /*) + */ + public function getText() : string { + return $this->text; + } + + /** + * Gets the line number the comment started on. + * + * @return int Line number (or -1 if not available) + */ + public function getStartLine() : int { + return $this->startLine; + } + + /** + * Gets the file offset the comment started on. + * + * @return int File offset (or -1 if not available) + */ + public function getStartFilePos() : int { + return $this->startFilePos; + } + + /** + * Gets the token offset the comment started on. + * + * @return int Token offset (or -1 if not available) + */ + public function getStartTokenPos() : int { + return $this->startTokenPos; + } + + /** + * Gets the line number the comment ends on. + * + * @return int Line number (or -1 if not available) + */ + public function getEndLine() : int { + return $this->endLine; + } + + /** + * Gets the file offset the comment ends on. + * + * @return int File offset (or -1 if not available) + */ + public function getEndFilePos() : int { + return $this->endFilePos; + } + + /** + * Gets the token offset the comment ends on. + * + * @return int Token offset (or -1 if not available) + */ + public function getEndTokenPos() : int { + return $this->endTokenPos; + } + + /** + * Gets the line number the comment started on. + * + * @deprecated Use getStartLine() instead + * + * @return int Line number + */ + public function getLine() : int { + return $this->startLine; + } + + /** + * Gets the file offset the comment started on. + * + * @deprecated Use getStartFilePos() instead + * + * @return int File offset + */ + public function getFilePos() : int { + return $this->startFilePos; + } + + /** + * Gets the token offset the comment started on. + * + * @deprecated Use getStartTokenPos() instead + * + * @return int Token offset + */ + public function getTokenPos() : int { + return $this->startTokenPos; + } + + /** + * Gets the comment text. + * + * @return string The comment text (including comment delimiters like /*) + */ + public function __toString() : string { + return $this->text; + } + + /** + * Gets the reformatted comment text. + * + * "Reformatted" here means that we try to clean up the whitespace at the + * starts of the lines. This is necessary because we receive the comments + * without trailing whitespace on the first line, but with trailing whitespace + * on all subsequent lines. + * + * @return mixed|string + */ + public function getReformattedText() { + $text = trim($this->text); + $newlinePos = strpos($text, "\n"); + if (false === $newlinePos) { + // Single line comments don't need further processing + return $text; + } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) { + // Multi line comment of the type + // + // /* + // * Some text. + // * Some more text. + // */ + // + // is handled by replacing the whitespace sequences before the * by a single space + return preg_replace('(^\s+\*)m', ' *', $this->text); + } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { + // Multi line comment of the type + // + // /* + // Some text. + // Some more text. + // */ + // + // is handled by removing the whitespace sequence on the line before the closing + // */ on all lines. So if the last line is " */", then " " is removed at the + // start of all lines. + return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); + } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { + // Multi line comment of the type + // + // /* Some text. + // Some more text. + // Indented text. + // Even more text. */ + // + // is handled by removing the difference between the shortest whitespace prefix on all + // lines and the length of the "/* " opening sequence. + $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1)); + $removeLen = $prefixLen - strlen($matches[0]); + return preg_replace('(^\s{' . $removeLen . '})m', '', $text); + } + + // No idea how to format this comment, so simply return as is + return $text; + } + + /** + * Get length of shortest whitespace prefix (at the start of a line). + * + * If there is a line with no prefix whitespace, 0 is a valid return value. + * + * @param string $str String to check + * @return int Length in characters. Tabs count as single characters. + */ + private function getShortestWhitespacePrefixLen(string $str) : int { + $lines = explode("\n", $str); + $shortestPrefixLen = \INF; + foreach ($lines as $line) { + preg_match('(^\s*)', $line, $matches); + $prefixLen = strlen($matches[0]); + if ($prefixLen < $shortestPrefixLen) { + $shortestPrefixLen = $prefixLen; + } + } + return $shortestPrefixLen; + } + + /** + * @return array + * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed} + */ + public function jsonSerialize() : array { + // Technically not a node, but we make it look like one anyway + $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment'; + return [ + 'nodeType' => $type, + 'text' => $this->text, + // TODO: Rename these to include "start". + 'line' => $this->startLine, + 'filePos' => $this->startFilePos, + 'tokenPos' => $this->startTokenPos, + 'endLine' => $this->endLine, + 'endFilePos' => $this->endFilePos, + 'endTokenPos' => $this->endTokenPos, + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php new file mode 100644 index 000000000..a9db6128f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php @@ -0,0 +1,7 @@ +fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) { + throw new ConstExprEvaluationException( + "Expression of type {$expr->getType()} cannot be evaluated" + ); + }; + } + + /** + * Silently evaluates a constant expression into a PHP value. + * + * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException. + * The original source of the exception is available through getPrevious(). + * + * If some part of the expression cannot be evaluated, the fallback evaluator passed to the + * constructor will be invoked. By default, if no fallback is provided, an exception of type + * ConstExprEvaluationException is thrown. + * + * See class doc comment for caveats and limitations. + * + * @param Expr $expr Constant expression to evaluate + * @return mixed Result of evaluation + * + * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred + */ + public function evaluateSilently(Expr $expr) { + set_error_handler(function($num, $str, $file, $line) { + throw new \ErrorException($str, 0, $num, $file, $line); + }); + + try { + return $this->evaluate($expr); + } catch (\Throwable $e) { + if (!$e instanceof ConstExprEvaluationException) { + $e = new ConstExprEvaluationException( + "An error occurred during constant expression evaluation", 0, $e); + } + throw $e; + } finally { + restore_error_handler(); + } + } + + /** + * Directly evaluates a constant expression into a PHP value. + * + * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these + * into a ConstExprEvaluationException. + * + * If some part of the expression cannot be evaluated, the fallback evaluator passed to the + * constructor will be invoked. By default, if no fallback is provided, an exception of type + * ConstExprEvaluationException is thrown. + * + * See class doc comment for caveats and limitations. + * + * @param Expr $expr Constant expression to evaluate + * @return mixed Result of evaluation + * + * @throws ConstExprEvaluationException if the expression cannot be evaluated + */ + public function evaluateDirectly(Expr $expr) { + return $this->evaluate($expr); + } + + private function evaluate(Expr $expr) { + if ($expr instanceof Scalar\LNumber + || $expr instanceof Scalar\DNumber + || $expr instanceof Scalar\String_ + ) { + return $expr->value; + } + + if ($expr instanceof Expr\Array_) { + return $this->evaluateArray($expr); + } + + // Unary operators + if ($expr instanceof Expr\UnaryPlus) { + return +$this->evaluate($expr->expr); + } + if ($expr instanceof Expr\UnaryMinus) { + return -$this->evaluate($expr->expr); + } + if ($expr instanceof Expr\BooleanNot) { + return !$this->evaluate($expr->expr); + } + if ($expr instanceof Expr\BitwiseNot) { + return ~$this->evaluate($expr->expr); + } + + if ($expr instanceof Expr\BinaryOp) { + return $this->evaluateBinaryOp($expr); + } + + if ($expr instanceof Expr\Ternary) { + return $this->evaluateTernary($expr); + } + + if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) { + return $this->evaluate($expr->var)[$this->evaluate($expr->dim)]; + } + + if ($expr instanceof Expr\ConstFetch) { + return $this->evaluateConstFetch($expr); + } + + return ($this->fallbackEvaluator)($expr); + } + + private function evaluateArray(Expr\Array_ $expr) { + $array = []; + foreach ($expr->items as $item) { + if (null !== $item->key) { + $array[$this->evaluate($item->key)] = $this->evaluate($item->value); + } elseif ($item->unpack) { + $array = array_merge($array, $this->evaluate($item->value)); + } else { + $array[] = $this->evaluate($item->value); + } + } + return $array; + } + + private function evaluateTernary(Expr\Ternary $expr) { + if (null === $expr->if) { + return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else); + } + + return $this->evaluate($expr->cond) + ? $this->evaluate($expr->if) + : $this->evaluate($expr->else); + } + + private function evaluateBinaryOp(Expr\BinaryOp $expr) { + if ($expr instanceof Expr\BinaryOp\Coalesce + && $expr->left instanceof Expr\ArrayDimFetch + ) { + // This needs to be special cased to respect BP_VAR_IS fetch semantics + return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] + ?? $this->evaluate($expr->right); + } + + // The evaluate() calls are repeated in each branch, because some of the operators are + // short-circuiting and evaluating the RHS in advance may be illegal in that case + $l = $expr->left; + $r = $expr->right; + switch ($expr->getOperatorSigil()) { + case '&': return $this->evaluate($l) & $this->evaluate($r); + case '|': return $this->evaluate($l) | $this->evaluate($r); + case '^': return $this->evaluate($l) ^ $this->evaluate($r); + case '&&': return $this->evaluate($l) && $this->evaluate($r); + case '||': return $this->evaluate($l) || $this->evaluate($r); + case '??': return $this->evaluate($l) ?? $this->evaluate($r); + case '.': return $this->evaluate($l) . $this->evaluate($r); + case '/': return $this->evaluate($l) / $this->evaluate($r); + case '==': return $this->evaluate($l) == $this->evaluate($r); + case '>': return $this->evaluate($l) > $this->evaluate($r); + case '>=': return $this->evaluate($l) >= $this->evaluate($r); + case '===': return $this->evaluate($l) === $this->evaluate($r); + case 'and': return $this->evaluate($l) and $this->evaluate($r); + case 'or': return $this->evaluate($l) or $this->evaluate($r); + case 'xor': return $this->evaluate($l) xor $this->evaluate($r); + case '-': return $this->evaluate($l) - $this->evaluate($r); + case '%': return $this->evaluate($l) % $this->evaluate($r); + case '*': return $this->evaluate($l) * $this->evaluate($r); + case '!=': return $this->evaluate($l) != $this->evaluate($r); + case '!==': return $this->evaluate($l) !== $this->evaluate($r); + case '+': return $this->evaluate($l) + $this->evaluate($r); + case '**': return $this->evaluate($l) ** $this->evaluate($r); + case '<<': return $this->evaluate($l) << $this->evaluate($r); + case '>>': return $this->evaluate($l) >> $this->evaluate($r); + case '<': return $this->evaluate($l) < $this->evaluate($r); + case '<=': return $this->evaluate($l) <= $this->evaluate($r); + case '<=>': return $this->evaluate($l) <=> $this->evaluate($r); + } + + throw new \Exception('Should not happen'); + } + + private function evaluateConstFetch(Expr\ConstFetch $expr) { + $name = $expr->name->toLowerString(); + switch ($name) { + case 'null': return null; + case 'false': return false; + case 'true': return true; + } + + return ($this->fallbackEvaluator)($expr); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Error.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Error.php new file mode 100644 index 000000000..d1fb959d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Error.php @@ -0,0 +1,180 @@ +rawMessage = $message; + if (is_array($attributes)) { + $this->attributes = $attributes; + } else { + $this->attributes = ['startLine' => $attributes]; + } + $this->updateMessage(); + } + + /** + * Gets the error message + * + * @return string Error message + */ + public function getRawMessage() : string { + return $this->rawMessage; + } + + /** + * Gets the line the error starts in. + * + * @return int Error start line + */ + public function getStartLine() : int { + return $this->attributes['startLine'] ?? -1; + } + + /** + * Gets the line the error ends in. + * + * @return int Error end line + */ + public function getEndLine() : int { + return $this->attributes['endLine'] ?? -1; + } + + /** + * Gets the attributes of the node/token the error occurred at. + * + * @return array + */ + public function getAttributes() : array { + return $this->attributes; + } + + /** + * Sets the attributes of the node/token the error occurred at. + * + * @param array $attributes + */ + public function setAttributes(array $attributes) { + $this->attributes = $attributes; + $this->updateMessage(); + } + + /** + * Sets the line of the PHP file the error occurred in. + * + * @param string $message Error message + */ + public function setRawMessage(string $message) { + $this->rawMessage = $message; + $this->updateMessage(); + } + + /** + * Sets the line the error starts in. + * + * @param int $line Error start line + */ + public function setStartLine(int $line) { + $this->attributes['startLine'] = $line; + $this->updateMessage(); + } + + /** + * Returns whether the error has start and end column information. + * + * For column information enable the startFilePos and endFilePos in the lexer options. + * + * @return bool + */ + public function hasColumnInfo() : bool { + return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']); + } + + /** + * Gets the start column (1-based) into the line where the error started. + * + * @param string $code Source code of the file + * @return int + */ + public function getStartColumn(string $code) : int { + if (!$this->hasColumnInfo()) { + throw new \RuntimeException('Error does not have column information'); + } + + return $this->toColumn($code, $this->attributes['startFilePos']); + } + + /** + * Gets the end column (1-based) into the line where the error ended. + * + * @param string $code Source code of the file + * @return int + */ + public function getEndColumn(string $code) : int { + if (!$this->hasColumnInfo()) { + throw new \RuntimeException('Error does not have column information'); + } + + return $this->toColumn($code, $this->attributes['endFilePos']); + } + + /** + * Formats message including line and column information. + * + * @param string $code Source code associated with the error, for calculation of the columns + * + * @return string Formatted message + */ + public function getMessageWithColumnInfo(string $code) : string { + return sprintf( + '%s from %d:%d to %d:%d', $this->getRawMessage(), + $this->getStartLine(), $this->getStartColumn($code), + $this->getEndLine(), $this->getEndColumn($code) + ); + } + + /** + * Converts a file offset into a column. + * + * @param string $code Source code that $pos indexes into + * @param int $pos 0-based position in $code + * + * @return int 1-based column (relative to start of line) + */ + private function toColumn(string $code, int $pos) : int { + if ($pos > strlen($code)) { + throw new \RuntimeException('Invalid position information'); + } + + $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); + if (false === $lineStartPos) { + $lineStartPos = -1; + } + + return $pos - $lineStartPos; + } + + /** + * Updates the exception message after a change to rawMessage or rawLine. + */ + protected function updateMessage() { + $this->message = $this->rawMessage; + + if (-1 === $this->getStartLine()) { + $this->message .= ' on unknown line'; + } else { + $this->message .= ' on line ' . $this->getStartLine(); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php new file mode 100644 index 000000000..d620e7453 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php @@ -0,0 +1,13 @@ +errors[] = $error; + } + + /** + * Get collected errors. + * + * @return Error[] + */ + public function getErrors() : array { + return $this->errors; + } + + /** + * Check whether there are any errors. + * + * @return bool + */ + public function hasErrors() : bool { + return !empty($this->errors); + } + + /** + * Reset/clear collected errors. + */ + public function clearErrors() { + $this->errors = []; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php new file mode 100644 index 000000000..aeee989b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php @@ -0,0 +1,18 @@ +type = $type; + $this->old = $old; + $this->new = $new; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php new file mode 100644 index 000000000..7f218c74f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php @@ -0,0 +1,164 @@ +isEqual = $isEqual; + } + + /** + * Calculate diff (edit script) from $old to $new. + * + * @param array $old Original array + * @param array $new New array + * + * @return DiffElem[] Diff (edit script) + */ + public function diff(array $old, array $new) { + list($trace, $x, $y) = $this->calculateTrace($old, $new); + return $this->extractDiff($trace, $x, $y, $old, $new); + } + + /** + * Calculate diff, including "replace" operations. + * + * If a sequence of remove operations is followed by the same number of add operations, these + * will be coalesced into replace operations. + * + * @param array $old Original array + * @param array $new New array + * + * @return DiffElem[] Diff (edit script), including replace operations + */ + public function diffWithReplacements(array $old, array $new) { + return $this->coalesceReplacements($this->diff($old, $new)); + } + + private function calculateTrace(array $a, array $b) { + $n = \count($a); + $m = \count($b); + $max = $n + $m; + $v = [1 => 0]; + $trace = []; + for ($d = 0; $d <= $max; $d++) { + $trace[] = $v; + for ($k = -$d; $k <= $d; $k += 2) { + if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { + $x = $v[$k+1]; + } else { + $x = $v[$k-1] + 1; + } + + $y = $x - $k; + while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) { + $x++; + $y++; + } + + $v[$k] = $x; + if ($x >= $n && $y >= $m) { + return [$trace, $x, $y]; + } + } + } + throw new \Exception('Should not happen'); + } + + private function extractDiff(array $trace, int $x, int $y, array $a, array $b) { + $result = []; + for ($d = \count($trace) - 1; $d >= 0; $d--) { + $v = $trace[$d]; + $k = $x - $y; + + if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) { + $prevK = $k + 1; + } else { + $prevK = $k - 1; + } + + $prevX = $v[$prevK]; + $prevY = $prevX - $prevK; + + while ($x > $prevX && $y > $prevY) { + $result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x-1], $b[$y-1]); + $x--; + $y--; + } + + if ($d === 0) { + break; + } + + while ($x > $prevX) { + $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x-1], null); + $x--; + } + + while ($y > $prevY) { + $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y-1]); + $y--; + } + } + return array_reverse($result); + } + + /** + * Coalesce equal-length sequences of remove+add into a replace operation. + * + * @param DiffElem[] $diff + * @return DiffElem[] + */ + private function coalesceReplacements(array $diff) { + $newDiff = []; + $c = \count($diff); + for ($i = 0; $i < $c; $i++) { + $diffType = $diff[$i]->type; + if ($diffType !== DiffElem::TYPE_REMOVE) { + $newDiff[] = $diff[$i]; + continue; + } + + $j = $i; + while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) { + $j++; + } + + $k = $j; + while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) { + $k++; + } + + if ($j - $i === $k - $j) { + $len = $j - $i; + for ($n = 0; $n < $len; $n++) { + $newDiff[] = new DiffElem( + DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new + ); + } + } else { + for (; $i < $k; $i++) { + $newDiff[] = $diff[$i]; + } + } + $i = $k - 1; + } + return $newDiff; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php new file mode 100644 index 000000000..fc276ecb9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php @@ -0,0 +1,64 @@ +attrGroups = $attrGroups; + $this->flags = $flags; + $this->args = $args; + $this->extends = $extends; + $this->implements = $implements; + $this->stmts = $stmts; + } + + public static function fromNewNode(Expr\New_ $newNode) { + $class = $newNode->class; + assert($class instanceof Node\Stmt\Class_); + // We don't assert that $class->name is null here, to allow consumers to assign unique names + // to anonymous classes for their own purposes. We simplify ignore the name here. + return new self( + $class->attrGroups, $class->flags, $newNode->args, $class->extends, $class->implements, + $class->stmts, $newNode->getAttributes() + ); + } + + public function getType() : string { + return 'Expr_PrintableNewAnonClass'; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'args', 'extends', 'implements', 'stmts']; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php new file mode 100644 index 000000000..7e0a5de0f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php @@ -0,0 +1,286 @@ +tokens = $tokens; + $this->indentMap = $this->calcIndentMap(); + } + + /** + * Whether the given position is immediately surrounded by parenthesis. + * + * @param int $startPos Start position + * @param int $endPos End position + * + * @return bool + */ + public function haveParens(int $startPos, int $endPos) : bool { + return $this->haveTokenImmediatelyBefore($startPos, '(') + && $this->haveTokenImmediatelyAfter($endPos, ')'); + } + + /** + * Whether the given position is immediately surrounded by braces. + * + * @param int $startPos Start position + * @param int $endPos End position + * + * @return bool + */ + public function haveBraces(int $startPos, int $endPos) : bool { + return ($this->haveTokenImmediatelyBefore($startPos, '{') + || $this->haveTokenImmediatelyBefore($startPos, T_CURLY_OPEN)) + && $this->haveTokenImmediatelyAfter($endPos, '}'); + } + + /** + * Check whether the position is directly preceded by a certain token type. + * + * During this check whitespace and comments are skipped. + * + * @param int $pos Position before which the token should occur + * @param int|string $expectedTokenType Token to check for + * + * @return bool Whether the expected token was found + */ + public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool { + $tokens = $this->tokens; + $pos--; + for (; $pos >= 0; $pos--) { + $tokenType = $tokens[$pos][0]; + if ($tokenType === $expectedTokenType) { + return true; + } + if ($tokenType !== \T_WHITESPACE + && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { + break; + } + } + return false; + } + + /** + * Check whether the position is directly followed by a certain token type. + * + * During this check whitespace and comments are skipped. + * + * @param int $pos Position after which the token should occur + * @param int|string $expectedTokenType Token to check for + * + * @return bool Whether the expected token was found + */ + public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool { + $tokens = $this->tokens; + $pos++; + for (; $pos < \count($tokens); $pos++) { + $tokenType = $tokens[$pos][0]; + if ($tokenType === $expectedTokenType) { + return true; + } + if ($tokenType !== \T_WHITESPACE + && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) { + break; + } + } + return false; + } + + public function skipLeft(int $pos, $skipTokenType) { + $tokens = $this->tokens; + + $pos = $this->skipLeftWhitespace($pos); + if ($skipTokenType === \T_WHITESPACE) { + return $pos; + } + + if ($tokens[$pos][0] !== $skipTokenType) { + // Shouldn't happen. The skip token MUST be there + throw new \Exception('Encountered unexpected token'); + } + $pos--; + + return $this->skipLeftWhitespace($pos); + } + + public function skipRight(int $pos, $skipTokenType) { + $tokens = $this->tokens; + + $pos = $this->skipRightWhitespace($pos); + if ($skipTokenType === \T_WHITESPACE) { + return $pos; + } + + if ($tokens[$pos][0] !== $skipTokenType) { + // Shouldn't happen. The skip token MUST be there + throw new \Exception('Encountered unexpected token'); + } + $pos++; + + return $this->skipRightWhitespace($pos); + } + + /** + * Return first non-whitespace token position smaller or equal to passed position. + * + * @param int $pos Token position + * @return int Non-whitespace token position + */ + public function skipLeftWhitespace(int $pos) { + $tokens = $this->tokens; + for (; $pos >= 0; $pos--) { + $type = $tokens[$pos][0]; + if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { + break; + } + } + return $pos; + } + + /** + * Return first non-whitespace position greater or equal to passed position. + * + * @param int $pos Token position + * @return int Non-whitespace token position + */ + public function skipRightWhitespace(int $pos) { + $tokens = $this->tokens; + for ($count = \count($tokens); $pos < $count; $pos++) { + $type = $tokens[$pos][0]; + if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) { + break; + } + } + return $pos; + } + + public function findRight(int $pos, $findTokenType) { + $tokens = $this->tokens; + for ($count = \count($tokens); $pos < $count; $pos++) { + $type = $tokens[$pos][0]; + if ($type === $findTokenType) { + return $pos; + } + } + return -1; + } + + /** + * Whether the given position range contains a certain token type. + * + * @param int $startPos Starting position (inclusive) + * @param int $endPos Ending position (exclusive) + * @param int|string $tokenType Token type to look for + * @return bool Whether the token occurs in the given range + */ + public function haveTokenInRange(int $startPos, int $endPos, $tokenType) { + $tokens = $this->tokens; + for ($pos = $startPos; $pos < $endPos; $pos++) { + if ($tokens[$pos][0] === $tokenType) { + return true; + } + } + return false; + } + + public function haveBracesInRange(int $startPos, int $endPos) { + return $this->haveTokenInRange($startPos, $endPos, '{') + || $this->haveTokenInRange($startPos, $endPos, T_CURLY_OPEN) + || $this->haveTokenInRange($startPos, $endPos, '}'); + } + + public function haveTagInRange(int $startPos, int $endPos): bool { + return $this->haveTokenInRange($startPos, $endPos, \T_OPEN_TAG) + || $this->haveTokenInRange($startPos, $endPos, \T_CLOSE_TAG); + } + + /** + * Get indentation before token position. + * + * @param int $pos Token position + * + * @return int Indentation depth (in spaces) + */ + public function getIndentationBefore(int $pos) : int { + return $this->indentMap[$pos]; + } + + /** + * Get the code corresponding to a token offset range, optionally adjusted for indentation. + * + * @param int $from Token start position (inclusive) + * @param int $to Token end position (exclusive) + * @param int $indent By how much the code should be indented (can be negative as well) + * + * @return string Code corresponding to token range, adjusted for indentation + */ + public function getTokenCode(int $from, int $to, int $indent) : string { + $tokens = $this->tokens; + $result = ''; + for ($pos = $from; $pos < $to; $pos++) { + $token = $tokens[$pos]; + if (\is_array($token)) { + $type = $token[0]; + $content = $token[1]; + if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) { + $result .= $content; + } else { + // TODO Handle non-space indentation + if ($indent < 0) { + $result .= str_replace("\n" . str_repeat(" ", -$indent), "\n", $content); + } elseif ($indent > 0) { + $result .= str_replace("\n", "\n" . str_repeat(" ", $indent), $content); + } else { + $result .= $content; + } + } + } else { + $result .= $token; + } + } + return $result; + } + + /** + * Precalculate the indentation at every token position. + * + * @return int[] Token position to indentation map + */ + private function calcIndentMap() { + $indentMap = []; + $indent = 0; + foreach ($this->tokens as $token) { + $indentMap[] = $indent; + + if ($token[0] === \T_WHITESPACE) { + $content = $token[1]; + $newlinePos = \strrpos($content, "\n"); + if (false !== $newlinePos) { + $indent = \strlen($content) - $newlinePos - 1; + } + } + } + + // Add a sentinel for one past end of the file + $indentMap[] = $indent; + + return $indentMap; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php new file mode 100644 index 000000000..47d2003d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php @@ -0,0 +1,103 @@ +decodeRecursive($value); + } + + private function decodeRecursive($value) { + if (\is_array($value)) { + if (isset($value['nodeType'])) { + if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') { + return $this->decodeComment($value); + } + return $this->decodeNode($value); + } + return $this->decodeArray($value); + } + return $value; + } + + private function decodeArray(array $array) : array { + $decodedArray = []; + foreach ($array as $key => $value) { + $decodedArray[$key] = $this->decodeRecursive($value); + } + return $decodedArray; + } + + private function decodeNode(array $value) : Node { + $nodeType = $value['nodeType']; + if (!\is_string($nodeType)) { + throw new \RuntimeException('Node type must be a string'); + } + + $reflectionClass = $this->reflectionClassFromNodeType($nodeType); + /** @var Node $node */ + $node = $reflectionClass->newInstanceWithoutConstructor(); + + if (isset($value['attributes'])) { + if (!\is_array($value['attributes'])) { + throw new \RuntimeException('Attributes must be an array'); + } + + $node->setAttributes($this->decodeArray($value['attributes'])); + } + + foreach ($value as $name => $subNode) { + if ($name === 'nodeType' || $name === 'attributes') { + continue; + } + + $node->$name = $this->decodeRecursive($subNode); + } + + return $node; + } + + private function decodeComment(array $value) : Comment { + $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class; + if (!isset($value['text'])) { + throw new \RuntimeException('Comment must have text'); + } + + return new $className( + $value['text'], + $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, + $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1 + ); + } + + private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass { + if (!isset($this->reflectionClassCache[$nodeType])) { + $className = $this->classNameFromNodeType($nodeType); + $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className); + } + return $this->reflectionClassCache[$nodeType]; + } + + private function classNameFromNodeType(string $nodeType) : string { + $className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\'); + if (class_exists($className)) { + return $className; + } + + $className .= '_'; + if (class_exists($className)) { + return $className; + } + + throw new \RuntimeException("Unknown node type \"$nodeType\""); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer.php new file mode 100644 index 000000000..60b809b8b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer.php @@ -0,0 +1,560 @@ +defineCompatibilityTokens(); + $this->tokenMap = $this->createTokenMap(); + $this->identifierTokens = $this->createIdentifierTokenMap(); + + // map of tokens to drop while lexing (the map is only used for isset lookup, + // that's why the value is simply set to 1; the value is never actually used.) + $this->dropTokens = array_fill_keys( + [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1 + ); + + $defaultAttributes = ['comments', 'startLine', 'endLine']; + $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true); + + // Create individual boolean properties to make these checks faster. + $this->attributeStartLineUsed = isset($usedAttributes['startLine']); + $this->attributeEndLineUsed = isset($usedAttributes['endLine']); + $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']); + $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']); + $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']); + $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']); + $this->attributeCommentsUsed = isset($usedAttributes['comments']); + } + + /** + * Initializes the lexer for lexing the provided source code. + * + * This function does not throw if lexing errors occur. Instead, errors may be retrieved using + * the getErrors() method. + * + * @param string $code The source code to lex + * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to + * ErrorHandler\Throwing + */ + public function startLexing(string $code, ?ErrorHandler $errorHandler = null) { + if (null === $errorHandler) { + $errorHandler = new ErrorHandler\Throwing(); + } + + $this->code = $code; // keep the code around for __halt_compiler() handling + $this->pos = -1; + $this->line = 1; + $this->filePos = 0; + + // If inline HTML occurs without preceding code, treat it as if it had a leading newline. + // This ensures proper composability, because having a newline is the "safe" assumption. + $this->prevCloseTagHasNewline = true; + + $scream = ini_set('xdebug.scream', '0'); + + $this->tokens = @token_get_all($code); + $this->postprocessTokens($errorHandler); + + if (false !== $scream) { + ini_set('xdebug.scream', $scream); + } + } + + private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) { + $tokens = []; + for ($i = $start; $i < $end; $i++) { + $chr = $this->code[$i]; + if ($chr === "\0") { + // PHP cuts error message after null byte, so need special case + $errorMsg = 'Unexpected null byte'; + } else { + $errorMsg = sprintf( + 'Unexpected character "%s" (ASCII %d)', $chr, ord($chr) + ); + } + + $tokens[] = [\T_BAD_CHARACTER, $chr, $line]; + $errorHandler->handleError(new Error($errorMsg, [ + 'startLine' => $line, + 'endLine' => $line, + 'startFilePos' => $i, + 'endFilePos' => $i, + ])); + } + return $tokens; + } + + /** + * Check whether comment token is unterminated. + * + * @return bool + */ + private function isUnterminatedComment($token) : bool { + return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT) + && substr($token[1], 0, 2) === '/*' + && substr($token[1], -2) !== '*/'; + } + + protected function postprocessTokens(ErrorHandler $errorHandler) { + // PHP's error handling for token_get_all() is rather bad, so if we want detailed + // error information we need to compute it ourselves. Invalid character errors are + // detected by finding "gaps" in the token array. Unterminated comments are detected + // by checking if a trailing comment has a "*/" at the end. + // + // Additionally, we perform a number of canonicalizations here: + // * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore. + // * Use PHP 8.0 T_NAME_* tokens. + // * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and + // T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types. + + $filePos = 0; + $line = 1; + $numTokens = \count($this->tokens); + for ($i = 0; $i < $numTokens; $i++) { + $token = $this->tokens[$i]; + + // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token. + // In this case we only need to emit an error. + if ($token[0] === \T_BAD_CHARACTER) { + $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler); + } + + if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*' + && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) { + $trailingNewline = $matches[0]; + $token[1] = substr($token[1], 0, -strlen($trailingNewline)); + $this->tokens[$i] = $token; + if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) { + // Move trailing newline into following T_WHITESPACE token, if it already exists. + $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1]; + $this->tokens[$i + 1][2]--; + } else { + // Otherwise, we need to create a new T_WHITESPACE token. + array_splice($this->tokens, $i + 1, 0, [ + [\T_WHITESPACE, $trailingNewline, $line], + ]); + $numTokens++; + } + } + + // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING + // into a single token. + if (\is_array($token) + && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) { + $lastWasSeparator = $token[0] === \T_NS_SEPARATOR; + $text = $token[1]; + for ($j = $i + 1; isset($this->tokens[$j]); $j++) { + if ($lastWasSeparator) { + if (!isset($this->identifierTokens[$this->tokens[$j][0]])) { + break; + } + $lastWasSeparator = false; + } else { + if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) { + break; + } + $lastWasSeparator = true; + } + $text .= $this->tokens[$j][1]; + } + if ($lastWasSeparator) { + // Trailing separator is not part of the name. + $j--; + $text = substr($text, 0, -1); + } + if ($j > $i + 1) { + if ($token[0] === \T_NS_SEPARATOR) { + $type = \T_NAME_FULLY_QUALIFIED; + } else if ($token[0] === \T_NAMESPACE) { + $type = \T_NAME_RELATIVE; + } else { + $type = \T_NAME_QUALIFIED; + } + $token = [$type, $text, $line]; + array_splice($this->tokens, $i, $j - $i, [$token]); + $numTokens -= $j - $i - 1; + } + } + + if ($token === '&') { + $next = $i + 1; + while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) { + $next++; + } + $followedByVarOrVarArg = isset($this->tokens[$next]) && + ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS); + $this->tokens[$i] = $token = [ + $followedByVarOrVarArg + ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, + '&', + $line, + ]; + } + + $tokenValue = \is_string($token) ? $token : $token[1]; + $tokenLen = \strlen($tokenValue); + + if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) { + // Something is missing, must be an invalid character + $nextFilePos = strpos($this->code, $tokenValue, $filePos); + $badCharTokens = $this->handleInvalidCharacterRange( + $filePos, $nextFilePos, $line, $errorHandler); + $filePos = (int) $nextFilePos; + + array_splice($this->tokens, $i, 0, $badCharTokens); + $numTokens += \count($badCharTokens); + $i += \count($badCharTokens); + } + + $filePos += $tokenLen; + $line += substr_count($tokenValue, "\n"); + } + + if ($filePos !== \strlen($this->code)) { + if (substr($this->code, $filePos, 2) === '/*') { + // Unlike PHP, HHVM will drop unterminated comments entirely + $comment = substr($this->code, $filePos); + $errorHandler->handleError(new Error('Unterminated comment', [ + 'startLine' => $line, + 'endLine' => $line + substr_count($comment, "\n"), + 'startFilePos' => $filePos, + 'endFilePos' => $filePos + \strlen($comment), + ])); + + // Emulate the PHP behavior + $isDocComment = isset($comment[3]) && $comment[3] === '*'; + $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line]; + } else { + // Invalid characters at the end of the input + $badCharTokens = $this->handleInvalidCharacterRange( + $filePos, \strlen($this->code), $line, $errorHandler); + $this->tokens = array_merge($this->tokens, $badCharTokens); + } + return; + } + + if (count($this->tokens) > 0) { + // Check for unterminated comment + $lastToken = $this->tokens[count($this->tokens) - 1]; + if ($this->isUnterminatedComment($lastToken)) { + $errorHandler->handleError(new Error('Unterminated comment', [ + 'startLine' => $line - substr_count($lastToken[1], "\n"), + 'endLine' => $line, + 'startFilePos' => $filePos - \strlen($lastToken[1]), + 'endFilePos' => $filePos, + ])); + } + } + } + + /** + * Fetches the next token. + * + * The available attributes are determined by the 'usedAttributes' option, which can + * be specified in the constructor. The following attributes are supported: + * + * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, + * representing all comments that occurred between the previous + * non-discarded token and the current one. + * * 'startLine' => Line in which the node starts. + * * 'endLine' => Line in which the node ends. + * * 'startTokenPos' => Offset into the token array of the first token in the node. + * * 'endTokenPos' => Offset into the token array of the last token in the node. + * * 'startFilePos' => Offset into the code string of the first character that is part of the node. + * * 'endFilePos' => Offset into the code string of the last character that is part of the node. + * + * @param mixed $value Variable to store token content in + * @param mixed $startAttributes Variable to store start attributes in + * @param mixed $endAttributes Variable to store end attributes in + * + * @return int Token id + */ + public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int { + $startAttributes = []; + $endAttributes = []; + + while (1) { + if (isset($this->tokens[++$this->pos])) { + $token = $this->tokens[$this->pos]; + } else { + // EOF token with ID 0 + $token = "\0"; + } + + if ($this->attributeStartLineUsed) { + $startAttributes['startLine'] = $this->line; + } + if ($this->attributeStartTokenPosUsed) { + $startAttributes['startTokenPos'] = $this->pos; + } + if ($this->attributeStartFilePosUsed) { + $startAttributes['startFilePos'] = $this->filePos; + } + + if (\is_string($token)) { + $value = $token; + if (isset($token[1])) { + // bug in token_get_all + $this->filePos += 2; + $id = ord('"'); + } else { + $this->filePos += 1; + $id = ord($token); + } + } elseif (!isset($this->dropTokens[$token[0]])) { + $value = $token[1]; + $id = $this->tokenMap[$token[0]]; + if (\T_CLOSE_TAG === $token[0]) { + $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n") + || false !== strpos($token[1], "\r"); + } elseif (\T_INLINE_HTML === $token[0]) { + $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline; + } + + $this->line += substr_count($value, "\n"); + $this->filePos += \strlen($value); + } else { + $origLine = $this->line; + $origFilePos = $this->filePos; + $this->line += substr_count($token[1], "\n"); + $this->filePos += \strlen($token[1]); + + if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) { + if ($this->attributeCommentsUsed) { + $comment = \T_DOC_COMMENT === $token[0] + ? new Comment\Doc($token[1], + $origLine, $origFilePos, $this->pos, + $this->line, $this->filePos - 1, $this->pos) + : new Comment($token[1], + $origLine, $origFilePos, $this->pos, + $this->line, $this->filePos - 1, $this->pos); + $startAttributes['comments'][] = $comment; + } + } + continue; + } + + if ($this->attributeEndLineUsed) { + $endAttributes['endLine'] = $this->line; + } + if ($this->attributeEndTokenPosUsed) { + $endAttributes['endTokenPos'] = $this->pos; + } + if ($this->attributeEndFilePosUsed) { + $endAttributes['endFilePos'] = $this->filePos - 1; + } + + return $id; + } + + throw new \RuntimeException('Reached end of lexer loop'); + } + + /** + * Returns the token array for current code. + * + * The token array is in the same format as provided by the + * token_get_all() function and does not discard tokens (i.e. + * whitespace and comments are included). The token position + * attributes are against this token array. + * + * @return array Array of tokens in token_get_all() format + */ + public function getTokens() : array { + return $this->tokens; + } + + /** + * Handles __halt_compiler() by returning the text after it. + * + * @return string Remaining text + */ + public function handleHaltCompiler() : string { + // text after T_HALT_COMPILER, still including (); + $textAfter = substr($this->code, $this->filePos); + + // ensure that it is followed by (); + // this simplifies the situation, by not allowing any comments + // in between of the tokens. + if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) { + throw new Error('__HALT_COMPILER must be followed by "();"'); + } + + // prevent the lexer from returning any further tokens + $this->pos = count($this->tokens); + + // return with (); removed + return substr($textAfter, strlen($matches[0])); + } + + private function defineCompatibilityTokens() { + static $compatTokensDefined = false; + if ($compatTokensDefined) { + return; + } + + $compatTokens = [ + // PHP 7.4 + 'T_BAD_CHARACTER', + 'T_FN', + 'T_COALESCE_EQUAL', + // PHP 8.0 + 'T_NAME_QUALIFIED', + 'T_NAME_FULLY_QUALIFIED', + 'T_NAME_RELATIVE', + 'T_MATCH', + 'T_NULLSAFE_OBJECT_OPERATOR', + 'T_ATTRIBUTE', + // PHP 8.1 + 'T_ENUM', + 'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', + 'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', + 'T_READONLY', + ]; + + // PHP-Parser might be used together with another library that also emulates some or all + // of these tokens. Perform a sanity-check that all already defined tokens have been + // assigned a unique ID. + $usedTokenIds = []; + foreach ($compatTokens as $token) { + if (\defined($token)) { + $tokenId = \constant($token); + $clashingToken = $usedTokenIds[$tokenId] ?? null; + if ($clashingToken !== null) { + throw new \Error(sprintf( + 'Token %s has same ID as token %s, ' . + 'you may be using a library with broken token emulation', + $token, $clashingToken + )); + } + $usedTokenIds[$tokenId] = $token; + } + } + + // Now define any tokens that have not yet been emulated. Try to assign IDs from -1 + // downwards, but skip any IDs that may already be in use. + $newTokenId = -1; + foreach ($compatTokens as $token) { + if (!\defined($token)) { + while (isset($usedTokenIds[$newTokenId])) { + $newTokenId--; + } + \define($token, $newTokenId); + $newTokenId--; + } + } + + $compatTokensDefined = true; + } + + /** + * Creates the token map. + * + * The token map maps the PHP internal token identifiers + * to the identifiers used by the Parser. Additionally it + * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. + * + * @return array The token map + */ + protected function createTokenMap() : array { + $tokenMap = []; + + // 256 is the minimum possible token number, as everything below + // it is an ASCII value + for ($i = 256; $i < 1000; ++$i) { + if (\T_DOUBLE_COLON === $i) { + // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM + $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM; + } elseif(\T_OPEN_TAG_WITH_ECHO === $i) { + // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO + $tokenMap[$i] = Tokens::T_ECHO; + } elseif(\T_CLOSE_TAG === $i) { + // T_CLOSE_TAG is equivalent to ';' + $tokenMap[$i] = ord(';'); + } elseif ('UNKNOWN' !== $name = token_name($i)) { + if ('T_HASHBANG' === $name) { + // HHVM uses a special token for #! hashbang lines + $tokenMap[$i] = Tokens::T_INLINE_HTML; + } elseif (defined($name = Tokens::class . '::' . $name)) { + // Other tokens can be mapped directly + $tokenMap[$i] = constant($name); + } + } + } + + // HHVM uses a special token for numbers that overflow to double + if (defined('T_ONUMBER')) { + $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER; + } + // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant + if (defined('T_COMPILER_HALT_OFFSET')) { + $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING; + } + + // Assign tokens for which we define compatibility constants, as token_name() does not know them. + $tokenMap[\T_FN] = Tokens::T_FN; + $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL; + $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED; + $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED; + $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE; + $tokenMap[\T_MATCH] = Tokens::T_MATCH; + $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR; + $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE; + $tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG; + $tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG; + $tokenMap[\T_ENUM] = Tokens::T_ENUM; + $tokenMap[\T_READONLY] = Tokens::T_READONLY; + + return $tokenMap; + } + + private function createIdentifierTokenMap(): array { + // Based on semi_reserved production. + return array_fill_keys([ + \T_STRING, + \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, + \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, + \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, + \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, + \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, + \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, + \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, + \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, + \T_MATCH, + ], true); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php new file mode 100644 index 000000000..a0e781d04 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php @@ -0,0 +1,251 @@ +targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_2; + unset($options['phpVersion']); + + parent::__construct($options); + + $emulators = [ + new FlexibleDocStringEmulator(), + new FnTokenEmulator(), + new MatchTokenEmulator(), + new CoaleseEqualTokenEmulator(), + new NumericLiteralSeparatorEmulator(), + new NullsafeTokenEmulator(), + new AttributeEmulator(), + new EnumTokenEmulator(), + new ReadonlyTokenEmulator(), + new ExplicitOctalEmulator(), + new ReadonlyFunctionTokenEmulator(), + ]; + + // Collect emulators that are relevant for the PHP version we're running + // and the PHP version we're targeting for emulation. + foreach ($emulators as $emulator) { + $emulatorPhpVersion = $emulator->getPhpVersion(); + if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) { + $this->emulators[] = $emulator; + } else if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) { + $this->emulators[] = new ReverseEmulator($emulator); + } + } + } + + public function startLexing(string $code, ?ErrorHandler $errorHandler = null) { + $emulators = array_filter($this->emulators, function($emulator) use($code) { + return $emulator->isEmulationNeeded($code); + }); + + if (empty($emulators)) { + // Nothing to emulate, yay + parent::startLexing($code, $errorHandler); + return; + } + + $this->patches = []; + foreach ($emulators as $emulator) { + $code = $emulator->preprocessCode($code, $this->patches); + } + + $collector = new ErrorHandler\Collecting(); + parent::startLexing($code, $collector); + $this->sortPatches(); + $this->fixupTokens(); + + $errors = $collector->getErrors(); + if (!empty($errors)) { + $this->fixupErrors($errors); + foreach ($errors as $error) { + $errorHandler->handleError($error); + } + } + + foreach ($emulators as $emulator) { + $this->tokens = $emulator->emulate($code, $this->tokens); + } + } + + private function isForwardEmulationNeeded(string $emulatorPhpVersion): bool { + return version_compare(\PHP_VERSION, $emulatorPhpVersion, '<') + && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>='); + } + + private function isReverseEmulationNeeded(string $emulatorPhpVersion): bool { + return version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=') + && version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<'); + } + + private function sortPatches() + { + // Patches may be contributed by different emulators. + // Make sure they are sorted by increasing patch position. + usort($this->patches, function($p1, $p2) { + return $p1[0] <=> $p2[0]; + }); + } + + private function fixupTokens() + { + if (\count($this->patches) === 0) { + return; + } + + // Load first patch + $patchIdx = 0; + + list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; + + // We use a manual loop over the tokens, because we modify the array on the fly + $pos = 0; + for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) { + $token = $this->tokens[$i]; + if (\is_string($token)) { + if ($patchPos === $pos) { + // Only support replacement for string tokens. + assert($patchType === 'replace'); + $this->tokens[$i] = $patchText; + + // Fetch the next patch + $patchIdx++; + if ($patchIdx >= \count($this->patches)) { + // No more patches, we're done + return; + } + list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; + } + + $pos += \strlen($token); + continue; + } + + $len = \strlen($token[1]); + $posDelta = 0; + while ($patchPos >= $pos && $patchPos < $pos + $len) { + $patchTextLen = \strlen($patchText); + if ($patchType === 'remove') { + if ($patchPos === $pos && $patchTextLen === $len) { + // Remove token entirely + array_splice($this->tokens, $i, 1, []); + $i--; + $c--; + } else { + // Remove from token string + $this->tokens[$i][1] = substr_replace( + $token[1], '', $patchPos - $pos + $posDelta, $patchTextLen + ); + $posDelta -= $patchTextLen; + } + } elseif ($patchType === 'add') { + // Insert into the token string + $this->tokens[$i][1] = substr_replace( + $token[1], $patchText, $patchPos - $pos + $posDelta, 0 + ); + $posDelta += $patchTextLen; + } else if ($patchType === 'replace') { + // Replace inside the token string + $this->tokens[$i][1] = substr_replace( + $token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen + ); + } else { + assert(false); + } + + // Fetch the next patch + $patchIdx++; + if ($patchIdx >= \count($this->patches)) { + // No more patches, we're done + return; + } + + list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx]; + + // Multiple patches may apply to the same token. Reload the current one to check + // If the new patch applies + $token = $this->tokens[$i]; + } + + $pos += $len; + } + + // A patch did not apply + assert(false); + } + + /** + * Fixup line and position information in errors. + * + * @param Error[] $errors + */ + private function fixupErrors(array $errors) { + foreach ($errors as $error) { + $attrs = $error->getAttributes(); + + $posDelta = 0; + $lineDelta = 0; + foreach ($this->patches as $patch) { + list($patchPos, $patchType, $patchText) = $patch; + if ($patchPos >= $attrs['startFilePos']) { + // No longer relevant + break; + } + + if ($patchType === 'add') { + $posDelta += strlen($patchText); + $lineDelta += substr_count($patchText, "\n"); + } else if ($patchType === 'remove') { + $posDelta -= strlen($patchText); + $lineDelta -= substr_count($patchText, "\n"); + } + } + + $attrs['startFilePos'] += $posDelta; + $attrs['endFilePos'] += $posDelta; + $attrs['startLine'] += $lineDelta; + $attrs['endLine'] += $lineDelta; + $error->setAttributes($attrs); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php new file mode 100644 index 000000000..6776a5197 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php @@ -0,0 +1,56 @@ +resolveIntegerOrFloatToken($tokens[$i + 1][1]); + array_splice($tokens, $i, 2, [ + [$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]], + ]); + $c--; + } + } + return $tokens; + } + + private function resolveIntegerOrFloatToken(string $str): int + { + $str = substr($str, 1); + $str = str_replace('_', '', $str); + $num = octdec($str); + return is_float($num) ? \T_DNUMBER : \T_LNUMBER; + } + + public function reverseEmulate(string $code, array $tokens): array { + // Explicit octals were not legal code previously, don't bother. + return $tokens; + } +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php new file mode 100644 index 000000000..c15d6271f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php @@ -0,0 +1,76 @@ +\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?(?:;?[\r\n])?)/x +REGEX; + + public function getPhpVersion(): string + { + return Emulative::PHP_7_3; + } + + public function isEmulationNeeded(string $code) : bool + { + return strpos($code, '<<<') !== false; + } + + public function emulate(string $code, array $tokens): array + { + // Handled by preprocessing + fixup. + return $tokens; + } + + public function reverseEmulate(string $code, array $tokens): array + { + // Not supported. + return $tokens; + } + + public function preprocessCode(string $code, array &$patches): string { + if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) { + // No heredoc/nowdoc found + return $code; + } + + // Keep track of how much we need to adjust string offsets due to the modifications we + // already made + $posDelta = 0; + foreach ($matches as $match) { + $indentation = $match['indentation'][0]; + $indentationStart = $match['indentation'][1]; + + $separator = $match['separator'][0]; + $separatorStart = $match['separator'][1]; + + if ($indentation === '' && $separator !== '') { + // Ordinary heredoc/nowdoc + continue; + } + + if ($indentation !== '') { + // Remove indentation + $indentationLen = strlen($indentation); + $code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen); + $patches[] = [$indentationStart + $posDelta, 'add', $indentation]; + $posDelta -= $indentationLen; + } + + if ($separator === '') { + // Insert newline as separator + $code = substr_replace($code, "\n", $separatorStart + $posDelta, 0); + $patches[] = [$separatorStart + $posDelta, 'remove', "\n"]; + $posDelta += 1; + } + } + + return $code; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php new file mode 100644 index 000000000..eb7e49634 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php @@ -0,0 +1,23 @@ +getKeywordString()) !== false; + } + + protected function isKeywordContext(array $tokens, int $pos): bool + { + $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos); + return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR; + } + + public function emulate(string $code, array $tokens): array + { + $keywordString = $this->getKeywordString(); + foreach ($tokens as $i => $token) { + if ($token[0] === T_STRING && strtolower($token[1]) === $keywordString + && $this->isKeywordContext($tokens, $i)) { + $tokens[$i][0] = $this->getKeywordToken(); + } + } + + return $tokens; + } + + /** + * @param mixed[] $tokens + * @return array|string|null + */ + private function getPreviousNonSpaceToken(array $tokens, int $start) + { + for ($i = $start - 1; $i >= 0; --$i) { + if ($tokens[$i][0] === T_WHITESPACE) { + continue; + } + + return $tokens[$i]; + } + + return null; + } + + public function reverseEmulate(string $code, array $tokens): array + { + $keywordToken = $this->getKeywordToken(); + foreach ($tokens as $i => $token) { + if ($token[0] === $keywordToken) { + $tokens[$i][0] = \T_STRING; + } + } + + return $tokens; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php new file mode 100644 index 000000000..902a46dfc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php @@ -0,0 +1,23 @@ +') !== false; + } + + public function emulate(string $code, array $tokens): array + { + // We need to manually iterate and manage a count because we'll change + // the tokens array on the way + $line = 1; + for ($i = 0, $c = count($tokens); $i < $c; ++$i) { + if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) { + array_splice($tokens, $i, 2, [ + [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line] + ]); + $c--; + continue; + } + + // Handle ?-> inside encapsed string. + if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) + && $tokens[$i - 1][0] === \T_VARIABLE + && preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches) + ) { + $replacement = [ + [\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line], + [\T_STRING, $matches[1], $line], + ]; + if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) { + $replacement[] = [ + \T_ENCAPSED_AND_WHITESPACE, + \substr($tokens[$i][1], \strlen($matches[0])), + $line + ]; + } + array_splice($tokens, $i, 1, $replacement); + $c += \count($replacement) - 1; + continue; + } + + if (\is_array($tokens[$i])) { + $line += substr_count($tokens[$i][1], "\n"); + } + } + + return $tokens; + } + + public function reverseEmulate(string $code, array $tokens): array + { + // ?-> was not valid code previously, don't bother. + return $tokens; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php new file mode 100644 index 000000000..cdf793e46 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php @@ -0,0 +1,105 @@ +resolveIntegerOrFloatToken($match); + $newTokens = [[$tokenKind, $match, $token[2]]]; + + $numTokens = 1; + $len = $tokenLen; + while ($matchLen > $len) { + $nextToken = $tokens[$i + $numTokens]; + $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken; + $nextTokenLen = \strlen($nextTokenText); + + $numTokens++; + if ($matchLen < $len + $nextTokenLen) { + // Split trailing characters into a partial token. + assert(is_array($nextToken), "Partial token should be an array token"); + $partialText = substr($nextTokenText, $matchLen - $len); + $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]]; + break; + } + + $len += $nextTokenLen; + } + + array_splice($tokens, $i, $numTokens, $newTokens); + $c -= $numTokens - \count($newTokens); + $codeOffset += $matchLen; + } + + return $tokens; + } + + private function resolveIntegerOrFloatToken(string $str): int + { + $str = str_replace('_', '', $str); + + if (stripos($str, '0b') === 0) { + $num = bindec($str); + } elseif (stripos($str, '0x') === 0) { + $num = hexdec($str); + } elseif (stripos($str, '0') === 0 && ctype_digit($str)) { + $num = octdec($str); + } else { + $num = +$str; + } + + return is_float($num) ? T_DNUMBER : T_LNUMBER; + } + + public function reverseEmulate(string $code, array $tokens): array + { + // Numeric separators were not legal code previously, don't bother. + return $tokens; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php new file mode 100644 index 000000000..e671458c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php @@ -0,0 +1,31 @@ +emulator = $emulator; + } + + public function getPhpVersion(): string { + return $this->emulator->getPhpVersion(); + } + + public function isEmulationNeeded(string $code): bool { + return $this->emulator->isEmulationNeeded($code); + } + + public function emulate(string $code, array $tokens): array { + return $this->emulator->reverseEmulate($code, $tokens); + } + + public function reverseEmulate(string $code, array $tokens): array { + return $this->emulator->emulate($code, $tokens); + } + + public function preprocessCode(string $code, array &$patches): string { + return $code; + } +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php new file mode 100644 index 000000000..a020bc0ff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php @@ -0,0 +1,25 @@ + [aliasName => originalName]] */ + protected $aliases = []; + + /** @var Name[][] Same as $aliases but preserving original case */ + protected $origAliases = []; + + /** @var ErrorHandler Error handler */ + protected $errorHandler; + + /** + * Create a name context. + * + * @param ErrorHandler $errorHandler Error handling used to report errors + */ + public function __construct(ErrorHandler $errorHandler) { + $this->errorHandler = $errorHandler; + } + + /** + * Start a new namespace. + * + * This also resets the alias table. + * + * @param Name|null $namespace Null is the global namespace + */ + public function startNamespace(?Name $namespace = null) { + $this->namespace = $namespace; + $this->origAliases = $this->aliases = [ + Stmt\Use_::TYPE_NORMAL => [], + Stmt\Use_::TYPE_FUNCTION => [], + Stmt\Use_::TYPE_CONSTANT => [], + ]; + } + + /** + * Add an alias / import. + * + * @param Name $name Original name + * @param string $aliasName Aliased name + * @param int $type One of Stmt\Use_::TYPE_* + * @param array $errorAttrs Attributes to use to report an error + */ + public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = []) { + // Constant names are case sensitive, everything else case insensitive + if ($type === Stmt\Use_::TYPE_CONSTANT) { + $aliasLookupName = $aliasName; + } else { + $aliasLookupName = strtolower($aliasName); + } + + if (isset($this->aliases[$type][$aliasLookupName])) { + $typeStringMap = [ + Stmt\Use_::TYPE_NORMAL => '', + Stmt\Use_::TYPE_FUNCTION => 'function ', + Stmt\Use_::TYPE_CONSTANT => 'const ', + ]; + + $this->errorHandler->handleError(new Error( + sprintf( + 'Cannot use %s%s as %s because the name is already in use', + $typeStringMap[$type], $name, $aliasName + ), + $errorAttrs + )); + return; + } + + $this->aliases[$type][$aliasLookupName] = $name; + $this->origAliases[$type][$aliasName] = $name; + } + + /** + * Get current namespace. + * + * @return null|Name Namespace (or null if global namespace) + */ + public function getNamespace() { + return $this->namespace; + } + + /** + * Get resolved name. + * + * @param Name $name Name to resolve + * @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT} + * + * @return null|Name Resolved name, or null if static resolution is not possible + */ + public function getResolvedName(Name $name, int $type) { + // don't resolve special class names + if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) { + if (!$name->isUnqualified()) { + $this->errorHandler->handleError(new Error( + sprintf("'\\%s' is an invalid class name", $name->toString()), + $name->getAttributes() + )); + } + return $name; + } + + // fully qualified names are already resolved + if ($name->isFullyQualified()) { + return $name; + } + + // Try to resolve aliases + if (null !== $resolvedName = $this->resolveAlias($name, $type)) { + return $resolvedName; + } + + if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { + if (null === $this->namespace) { + // outside of a namespace unaliased unqualified is same as fully qualified + return new FullyQualified($name, $name->getAttributes()); + } + + // Cannot resolve statically + return null; + } + + // if no alias exists prepend current namespace + return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); + } + + /** + * Get resolved class name. + * + * @param Name $name Class ame to resolve + * + * @return Name Resolved name + */ + public function getResolvedClassName(Name $name) : Name { + return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL); + } + + /** + * Get possible ways of writing a fully qualified name (e.g., by making use of aliases). + * + * @param string $name Fully-qualified name (without leading namespace separator) + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name[] Possible representations of the name + */ + public function getPossibleNames(string $name, int $type) : array { + $lcName = strtolower($name); + + if ($type === Stmt\Use_::TYPE_NORMAL) { + // self, parent and static must always be unqualified + if ($lcName === "self" || $lcName === "parent" || $lcName === "static") { + return [new Name($name)]; + } + } + + // Collect possible ways to write this name, starting with the fully-qualified name + $possibleNames = [new FullyQualified($name)]; + + if (null !== $nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type)) { + // Make sure there is no alias that makes the normally namespace-relative name + // into something else + if (null === $this->resolveAlias($nsRelativeName, $type)) { + $possibleNames[] = $nsRelativeName; + } + } + + // Check for relevant namespace use statements + foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) { + $lcOrig = $orig->toLowerString(); + if (0 === strpos($lcName, $lcOrig . '\\')) { + $possibleNames[] = new Name($alias . substr($name, strlen($lcOrig))); + } + } + + // Check for relevant type-specific use statements + foreach ($this->origAliases[$type] as $alias => $orig) { + if ($type === Stmt\Use_::TYPE_CONSTANT) { + // Constants are are complicated-sensitive + $normalizedOrig = $this->normalizeConstName($orig->toString()); + if ($normalizedOrig === $this->normalizeConstName($name)) { + $possibleNames[] = new Name($alias); + } + } else { + // Everything else is case-insensitive + if ($orig->toLowerString() === $lcName) { + $possibleNames[] = new Name($alias); + } + } + } + + return $possibleNames; + } + + /** + * Get shortest representation of this fully-qualified name. + * + * @param string $name Fully-qualified name (without leading namespace separator) + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name Shortest representation + */ + public function getShortName(string $name, int $type) : Name { + $possibleNames = $this->getPossibleNames($name, $type); + + // Find shortest name + $shortestName = null; + $shortestLength = \INF; + foreach ($possibleNames as $possibleName) { + $length = strlen($possibleName->toCodeString()); + if ($length < $shortestLength) { + $shortestName = $possibleName; + $shortestLength = $length; + } + } + + return $shortestName; + } + + private function resolveAlias(Name $name, $type) { + $firstPart = $name->getFirst(); + + if ($name->isQualified()) { + // resolve aliases for qualified names, always against class alias table + $checkName = strtolower($firstPart); + if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) { + $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName]; + return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); + } + } elseif ($name->isUnqualified()) { + // constant aliases are case-sensitive, function aliases case-insensitive + $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : strtolower($firstPart); + if (isset($this->aliases[$type][$checkName])) { + // resolve unqualified aliases + return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes()); + } + } + + // No applicable aliases + return null; + } + + private function getNamespaceRelativeName(string $name, string $lcName, int $type) { + if (null === $this->namespace) { + return new Name($name); + } + + if ($type === Stmt\Use_::TYPE_CONSTANT) { + // The constants true/false/null always resolve to the global symbols, even inside a + // namespace, so they may be used without qualification + if ($lcName === "true" || $lcName === "false" || $lcName === "null") { + return new Name($name); + } + } + + $namespacePrefix = strtolower($this->namespace . '\\'); + if (0 === strpos($lcName, $namespacePrefix)) { + return new Name(substr($name, strlen($namespacePrefix))); + } + + return null; + } + + private function normalizeConstName(string $name) { + $nsSep = strrpos($name, '\\'); + if (false === $nsSep) { + return $name; + } + + // Constants have case-insensitive namespace and case-sensitive short-name + $ns = substr($name, 0, $nsSep); + $shortName = substr($name, $nsSep + 1); + return strtolower($ns) . '\\' . $shortName; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node.php new file mode 100644 index 000000000..befb25650 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node.php @@ -0,0 +1,151 @@ +attributes = $attributes; + $this->name = $name; + $this->value = $value; + $this->byRef = $byRef; + $this->unpack = $unpack; + } + + public function getSubNodeNames() : array { + return ['name', 'value', 'byRef', 'unpack']; + } + + public function getType() : string { + return 'Arg'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php new file mode 100644 index 000000000..c96f66e51 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->name = $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['name', 'args']; + } + + public function getType() : string { + return 'Attribute'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php new file mode 100644 index 000000000..613bfc413 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php @@ -0,0 +1,29 @@ +attributes = $attributes; + $this->attrs = $attrs; + } + + public function getSubNodeNames() : array { + return ['attrs']; + } + + public function getType() : string { + return 'AttributeGroup'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php new file mode 100644 index 000000000..9505532ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php @@ -0,0 +1,14 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['name', 'value']; + } + + public function getType() : string { + return 'Const'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php new file mode 100644 index 000000000..6cf4df223 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php @@ -0,0 +1,9 @@ +attributes = $attributes; + $this->var = $var; + $this->dim = $dim; + } + + public function getSubNodeNames() : array { + return ['var', 'dim']; + } + + public function getType() : string { + return 'Expr_ArrayDimFetch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php new file mode 100644 index 000000000..5aaa9867e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php @@ -0,0 +1,41 @@ +attributes = $attributes; + $this->key = $key; + $this->value = $value; + $this->byRef = $byRef; + $this->unpack = $unpack; + } + + public function getSubNodeNames() : array { + return ['key', 'value', 'byRef', 'unpack']; + } + + public function getType() : string { + return 'Expr_ArrayItem'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php new file mode 100644 index 000000000..e6eaa2834 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->items = $items; + } + + public function getSubNodeNames() : array { + return ['items']; + } + + public function getType() : string { + return 'Expr_Array'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php new file mode 100644 index 000000000..c273fb7ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php @@ -0,0 +1,79 @@ + false : Whether the closure is static + * 'byRef' => false : Whether to return by reference + * 'params' => array() : Parameters + * 'returnType' => null : Return type + * 'expr' => Expr : Expression body + * 'attrGroups' => array() : PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->static = $subNodes['static'] ?? false; + $this->byRef = $subNodes['byRef'] ?? false; + $this->params = $subNodes['params'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->expr = $subNodes['expr']; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + /** + * @return Node\Stmt\Return_[] + */ + public function getStmts() : array { + return [new Node\Stmt\Return_($this->expr)]; + } + + public function getType() : string { + return 'Expr_ArrowFunction'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php new file mode 100644 index 000000000..cf9e6e82b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['var', 'expr']; + } + + public function getType() : string { + return 'Expr_Assign'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php new file mode 100644 index 000000000..bce8604f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['var', 'expr']; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php new file mode 100644 index 000000000..420284cdc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php @@ -0,0 +1,12 @@ +attributes = $attributes; + $this->var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['var', 'expr']; + } + + public function getType() : string { + return 'Expr_AssignRef'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php new file mode 100644 index 000000000..d9c582b0d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php @@ -0,0 +1,40 @@ +attributes = $attributes; + $this->left = $left; + $this->right = $right; + } + + public function getSubNodeNames() : array { + return ['left', 'right']; + } + + /** + * Get the operator sigil for this binary operation. + * + * In the case there are multiple possible sigils for an operator, this method does not + * necessarily return the one used in the parsed code. + * + * @return string + */ + abstract public function getOperatorSigil() : string; +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php new file mode 100644 index 000000000..d907393bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php @@ -0,0 +1,16 @@ +'; + } + + public function getType() : string { + return 'Expr_BinaryOp_Greater'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php new file mode 100644 index 000000000..d677502cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php @@ -0,0 +1,16 @@ +='; + } + + public function getType() : string { + return 'Expr_BinaryOp_GreaterOrEqual'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php new file mode 100644 index 000000000..3d96285c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php @@ -0,0 +1,16 @@ +>'; + } + + public function getType() : string { + return 'Expr_BinaryOp_ShiftRight'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php new file mode 100644 index 000000000..3cb8e7e0d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php @@ -0,0 +1,16 @@ +'; + } + + public function getType() : string { + return 'Expr_BinaryOp_Spaceship'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php new file mode 100644 index 000000000..ed44984be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_BitwiseNot'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php new file mode 100644 index 000000000..bf27e9f65 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_BooleanNot'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php new file mode 100644 index 000000000..78e1cf349 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php @@ -0,0 +1,39 @@ + + */ + abstract public function getRawArgs(): array; + + /** + * Returns whether this call expression is actually a first class callable. + */ + public function isFirstClassCallable(): bool { + foreach ($this->getRawArgs() as $arg) { + if ($arg instanceof VariadicPlaceholder) { + return true; + } + } + return false; + } + + /** + * Assert that this is not a first-class callable and return only ordinary Args. + * + * @return Arg[] + */ + public function getArgs(): array { + assert(!$this->isFirstClassCallable()); + return $this->getRawArgs(); + } +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php new file mode 100644 index 000000000..36769d4fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php @@ -0,0 +1,26 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php new file mode 100644 index 000000000..57cc473b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php @@ -0,0 +1,12 @@ +attributes = $attributes; + $this->class = $class; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['class', 'name']; + } + + public function getType() : string { + return 'Expr_ClassConstFetch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php new file mode 100644 index 000000000..db216b8f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Clone'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php new file mode 100644 index 000000000..56ddea6aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php @@ -0,0 +1,79 @@ + false : Whether the closure is static + * 'byRef' => false : Whether to return by reference + * 'params' => array(): Parameters + * 'uses' => array(): use()s + * 'returnType' => null : Return type + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attributes groups + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->static = $subNodes['static'] ?? false; + $this->byRef = $subNodes['byRef'] ?? false; + $this->params = $subNodes['params'] ?? []; + $this->uses = $subNodes['uses'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + /** @return Node\Stmt[] */ + public function getStmts() : array { + return $this->stmts; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + public function getType() : string { + return 'Expr_Closure'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php new file mode 100644 index 000000000..2b8a09666 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->var = $var; + $this->byRef = $byRef; + } + + public function getSubNodeNames() : array { + return ['var', 'byRef']; + } + + public function getType() : string { + return 'Expr_ClosureUse'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php new file mode 100644 index 000000000..14ebd16bd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->name = $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Expr_ConstFetch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php new file mode 100644 index 000000000..4042ec93c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Empty'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php new file mode 100644 index 000000000..1637f3aea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php @@ -0,0 +1,31 @@ +attributes = $attributes; + } + + public function getSubNodeNames() : array { + return []; + } + + public function getType() : string { + return 'Expr_Error'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php new file mode 100644 index 000000000..c44ff6f93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_ErrorSuppress'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php new file mode 100644 index 000000000..856854743 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Eval'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php new file mode 100644 index 000000000..5469b8e4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Exit'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php new file mode 100644 index 000000000..2de4d0dd5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php @@ -0,0 +1,39 @@ + Arguments */ + public $args; + + /** + * Constructs a function call node. + * + * @param Node\Name|Expr $name Function name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct($name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->name = $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['name', 'args']; + } + + public function getType() : string { + return 'Expr_FuncCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php new file mode 100644 index 000000000..07ce5968e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php @@ -0,0 +1,39 @@ +attributes = $attributes; + $this->expr = $expr; + $this->type = $type; + } + + public function getSubNodeNames() : array { + return ['expr', 'type']; + } + + public function getType() : string { + return 'Expr_Include'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php new file mode 100644 index 000000000..9000d47bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php @@ -0,0 +1,35 @@ +attributes = $attributes; + $this->expr = $expr; + $this->class = $class; + } + + public function getSubNodeNames() : array { + return ['expr', 'class']; + } + + public function getType() : string { + return 'Expr_Instanceof'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php new file mode 100644 index 000000000..76b738758 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Expr_Isset'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php new file mode 100644 index 000000000..c27a27b95 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->items = $items; + } + + public function getSubNodeNames() : array { + return ['items']; + } + + public function getType() : string { + return 'Expr_List'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php new file mode 100644 index 000000000..2455a3026 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->cond = $cond; + $this->arms = $arms; + } + + public function getSubNodeNames() : array { + return ['cond', 'arms']; + } + + public function getType() : string { + return 'Expr_Match'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php new file mode 100644 index 000000000..49ca48356 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php @@ -0,0 +1,45 @@ + Arguments */ + public $args; + + /** + * Constructs a function call node. + * + * @param Expr $var Variable holding object + * @param string|Identifier|Expr $name Method name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['var', 'name', 'args']; + } + + public function getType() : string { + return 'Expr_MethodCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php new file mode 100644 index 000000000..e2bb64928 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php @@ -0,0 +1,41 @@ + Arguments */ + public $args; + + /** + * Constructs a function call node. + * + * @param Node\Name|Expr|Node\Stmt\Class_ $class Class name (or class node for anonymous classes) + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct($class, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->class = $class; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['class', 'args']; + } + + public function getType() : string { + return 'Expr_New'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php new file mode 100644 index 000000000..07a571fd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php @@ -0,0 +1,45 @@ + Arguments */ + public $args; + + /** + * Constructs a nullsafe method call node. + * + * @param Expr $var Variable holding object + * @param string|Identifier|Expr $name Method name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct(Expr $var, $name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['var', 'name', 'args']; + } + + public function getType() : string { + return 'Expr_NullsafeMethodCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php new file mode 100644 index 000000000..9317eb3b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php @@ -0,0 +1,35 @@ +attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['var', 'name']; + } + + public function getType() : string { + return 'Expr_NullsafePropertyFetch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php new file mode 100644 index 000000000..94d6c296d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PostDec'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php new file mode 100644 index 000000000..005c443a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PostInc'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php new file mode 100644 index 000000000..a5ca685a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PreDec'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php new file mode 100644 index 000000000..0986c4474 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->var = $var; + } + + public function getSubNodeNames() : array { + return ['var']; + } + + public function getType() : string { + return 'Expr_PreInc'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php new file mode 100644 index 000000000..2d43c2ac8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Print'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php new file mode 100644 index 000000000..4281f31cc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php @@ -0,0 +1,35 @@ +attributes = $attributes; + $this->var = $var; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['var', 'name']; + } + + public function getType() : string { + return 'Expr_PropertyFetch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php new file mode 100644 index 000000000..537a7cc80 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->parts = $parts; + } + + public function getSubNodeNames() : array { + return ['parts']; + } + + public function getType() : string { + return 'Expr_ShellExec'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php new file mode 100644 index 000000000..d0d099c47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php @@ -0,0 +1,46 @@ + Arguments */ + public $args; + + /** + * Constructs a static method call node. + * + * @param Node\Name|Expr $class Class name + * @param string|Identifier|Expr $name Method name + * @param array $args Arguments + * @param array $attributes Additional attributes + */ + public function __construct($class, $name, array $args = [], array $attributes = []) { + $this->attributes = $attributes; + $this->class = $class; + $this->name = \is_string($name) ? new Identifier($name) : $name; + $this->args = $args; + } + + public function getSubNodeNames() : array { + return ['class', 'name', 'args']; + } + + public function getType() : string { + return 'Expr_StaticCall'; + } + + public function getRawArgs(): array { + return $this->args; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php new file mode 100644 index 000000000..1ee1a25e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php @@ -0,0 +1,36 @@ +attributes = $attributes; + $this->class = $class; + $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['class', 'name']; + } + + public function getType() : string { + return 'Expr_StaticPropertyFetch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php new file mode 100644 index 000000000..9316f47d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php @@ -0,0 +1,38 @@ +attributes = $attributes; + $this->cond = $cond; + $this->if = $if; + $this->else = $else; + } + + public function getSubNodeNames() : array { + return ['cond', 'if', 'else']; + } + + public function getType() : string { + return 'Expr_Ternary'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php new file mode 100644 index 000000000..5c97f0e2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_Throw'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php new file mode 100644 index 000000000..ce8808bc6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_UnaryMinus'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php new file mode 100644 index 000000000..d23047e54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_UnaryPlus'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php new file mode 100644 index 000000000..b47d38e93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->name = $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Expr_Variable'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php new file mode 100644 index 000000000..a3efce618 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Expr_YieldFrom'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php new file mode 100644 index 000000000..f15336ede --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->key = $key; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['key', 'value']; + } + + public function getType() : string { + return 'Expr_Yield'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php new file mode 100644 index 000000000..5a825e731 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php @@ -0,0 +1,43 @@ + true, + 'parent' => true, + 'static' => true, + ]; + + /** + * Constructs an identifier node. + * + * @param string $name Identifier as string + * @param array $attributes Additional attributes + */ + public function __construct(string $name, array $attributes = []) { + $this->attributes = $attributes; + $this->name = $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + /** + * Get identifier as string. + * + * @return string Identifier as string. + */ + public function toString() : string { + return $this->name; + } + + /** + * Get lowercased identifier as string. + * + * @return string Lowercased identifier as string + */ + public function toLowerString() : string { + return strtolower($this->name); + } + + /** + * Checks whether the identifier is a special class name (self, parent or static). + * + * @return bool Whether identifier is a special class name + */ + public function isSpecialClassName() : bool { + return isset(self::$specialClassNames[strtolower($this->name)]); + } + + /** + * Get identifier as string. + * + * @return string Identifier as string + */ + public function __toString() : string { + return $this->name; + } + + public function getType() : string { + return 'Identifier'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php new file mode 100644 index 000000000..9208e1392 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->types = $types; + } + + public function getSubNodeNames() : array { + return ['types']; + } + + public function getType() : string { + return 'IntersectionType'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php new file mode 100644 index 000000000..2ae1c86b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php @@ -0,0 +1,31 @@ +conds = $conds; + $this->body = $body; + $this->attributes = $attributes; + } + + public function getSubNodeNames() : array { + return ['conds', 'body']; + } + + public function getType() : string { + return 'MatchArm'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php new file mode 100644 index 000000000..0d6e4b1ff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php @@ -0,0 +1,254 @@ + true, + 'parent' => true, + 'static' => true, + ]; + + /** + * Constructs a name node. + * + * @param string|string[]|self $name Name as string, part array or Name instance (copy ctor) + * @param array $attributes Additional attributes + */ + public function __construct($name, array $attributes = []) { + $this->attributes = $attributes; + $this->parts = self::prepareName($name); + } + + public function getSubNodeNames() : array { + return ['parts']; + } + + /** + * Get parts of name (split by the namespace separator). + * + * @return string[] Parts of name + */ + public function getParts(): array { + return $this->parts; + } + + /** + * Gets the first part of the name, i.e. everything before the first namespace separator. + * + * @return string First part of the name + */ + public function getFirst() : string { + return $this->parts[0]; + } + + /** + * Gets the last part of the name, i.e. everything after the last namespace separator. + * + * @return string Last part of the name + */ + public function getLast() : string { + return $this->parts[count($this->parts) - 1]; + } + + /** + * Checks whether the name is unqualified. (E.g. Name) + * + * @return bool Whether the name is unqualified + */ + public function isUnqualified() : bool { + return 1 === count($this->parts); + } + + /** + * Checks whether the name is qualified. (E.g. Name\Name) + * + * @return bool Whether the name is qualified + */ + public function isQualified() : bool { + return 1 < count($this->parts); + } + + /** + * Checks whether the name is fully qualified. (E.g. \Name) + * + * @return bool Whether the name is fully qualified + */ + public function isFullyQualified() : bool { + return false; + } + + /** + * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) + * + * @return bool Whether the name is relative + */ + public function isRelative() : bool { + return false; + } + + /** + * Returns a string representation of the name itself, without taking the name type into + * account (e.g., not including a leading backslash for fully qualified names). + * + * @return string String representation + */ + public function toString() : string { + return implode('\\', $this->parts); + } + + /** + * Returns a string representation of the name as it would occur in code (e.g., including + * leading backslash for fully qualified names. + * + * @return string String representation + */ + public function toCodeString() : string { + return $this->toString(); + } + + /** + * Returns lowercased string representation of the name, without taking the name type into + * account (e.g., no leading backslash for fully qualified names). + * + * @return string Lowercased string representation + */ + public function toLowerString() : string { + return strtolower(implode('\\', $this->parts)); + } + + /** + * Checks whether the identifier is a special class name (self, parent or static). + * + * @return bool Whether identifier is a special class name + */ + public function isSpecialClassName() : bool { + return count($this->parts) === 1 + && isset(self::$specialClassNames[strtolower($this->parts[0])]); + } + + /** + * Returns a string representation of the name by imploding the namespace parts with the + * namespace separator. + * + * @return string String representation + */ + public function __toString() : string { + return implode('\\', $this->parts); + } + + /** + * Gets a slice of a name (similar to array_slice). + * + * This method returns a new instance of the same type as the original and with the same + * attributes. + * + * If the slice is empty, null is returned. The null value will be correctly handled in + * concatenations using concat(). + * + * Offset and length have the same meaning as in array_slice(). + * + * @param int $offset Offset to start the slice at (may be negative) + * @param int|null $length Length of the slice (may be negative) + * + * @return static|null Sliced name + */ + public function slice(int $offset, ?int $length = null) { + $numParts = count($this->parts); + + $realOffset = $offset < 0 ? $offset + $numParts : $offset; + if ($realOffset < 0 || $realOffset > $numParts) { + throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); + } + + if (null === $length) { + $realLength = $numParts - $realOffset; + } else { + $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; + if ($realLength < 0 || $realLength > $numParts - $realOffset) { + throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); + } + } + + if ($realLength === 0) { + // Empty slice is represented as null + return null; + } + + return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes); + } + + /** + * Concatenate two names, yielding a new Name instance. + * + * The type of the generated instance depends on which class this method is called on, for + * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. + * + * If one of the arguments is null, a new instance of the other name will be returned. If both + * arguments are null, null will be returned. As such, writing + * Name::concat($namespace, $shortName) + * where $namespace is a Name node or null will work as expected. + * + * @param string|string[]|self|null $name1 The first name + * @param string|string[]|self|null $name2 The second name + * @param array $attributes Attributes to assign to concatenated name + * + * @return static|null Concatenated name + */ + public static function concat($name1, $name2, array $attributes = []) { + if (null === $name1 && null === $name2) { + return null; + } elseif (null === $name1) { + return new static(self::prepareName($name2), $attributes); + } elseif (null === $name2) { + return new static(self::prepareName($name1), $attributes); + } else { + return new static( + array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes + ); + } + } + + /** + * Prepares a (string, array or Name node) name for use in name changing methods by converting + * it to an array. + * + * @param string|string[]|self $name Name to prepare + * + * @return string[] Prepared name + */ + private static function prepareName($name) : array { + if (\is_string($name)) { + if ('' === $name) { + throw new \InvalidArgumentException('Name cannot be empty'); + } + + return explode('\\', $name); + } elseif (\is_array($name)) { + if (empty($name)) { + throw new \InvalidArgumentException('Name cannot be empty'); + } + + return $name; + } elseif ($name instanceof self) { + return $name->parts; + } + + throw new \InvalidArgumentException( + 'Expected string, array of parts or Name instance' + ); + } + + public function getType() : string { + return 'Name'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php new file mode 100644 index 000000000..1df93a56b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php @@ -0,0 +1,50 @@ +toString(); + } + + public function getType() : string { + return 'Name_FullyQualified'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php new file mode 100644 index 000000000..57bf7af2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php @@ -0,0 +1,50 @@ +toString(); + } + + public function getType() : string { + return 'Name_Relative'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php new file mode 100644 index 000000000..d68e26a38 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php @@ -0,0 +1,28 @@ +attributes = $attributes; + $this->type = \is_string($type) ? new Identifier($type) : $type; + } + + public function getSubNodeNames() : array { + return ['type']; + } + + public function getType() : string { + return 'NullableType'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php new file mode 100644 index 000000000..dfb77f629 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php @@ -0,0 +1,60 @@ +attributes = $attributes; + $this->type = \is_string($type) ? new Identifier($type) : $type; + $this->byRef = $byRef; + $this->variadic = $variadic; + $this->var = $var; + $this->default = $default; + $this->flags = $flags; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default']; + } + + public function getType() : string { + return 'Param'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php new file mode 100644 index 000000000..8117909b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php @@ -0,0 +1,7 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + /** + * @param mixed[] $attributes + */ + public static function fromString(string $str, array $attributes = []): DNumber + { + $attributes['rawValue'] = $str; + $float = self::parse($str); + + return new DNumber($float, $attributes); + } + + /** + * @internal + * + * Parses a DNUMBER token like PHP would. + * + * @param string $str A string number + * + * @return float The parsed number + */ + public static function parse(string $str) : float { + $str = str_replace('_', '', $str); + + // Check whether this is one of the special integer notations. + if ('0' === $str[0]) { + // hex + if ('x' === $str[1] || 'X' === $str[1]) { + return hexdec($str); + } + + // bin + if ('b' === $str[1] || 'B' === $str[1]) { + return bindec($str); + } + + // oct, but only if the string does not contain any of '.eE'. + if (false === strpbrk($str, '.eE')) { + // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit + // (8 or 9) so that only the digits before that are used. + return octdec(substr($str, 0, strcspn($str, '89'))); + } + } + + // dec + return (float) $str; + } + + public function getType() : string { + return 'Scalar_DNumber'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php new file mode 100644 index 000000000..fa5d2e268 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->parts = $parts; + } + + public function getSubNodeNames() : array { + return ['parts']; + } + + public function getType() : string { + return 'Scalar_Encapsed'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php new file mode 100644 index 000000000..bb3194c1d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + public function getType() : string { + return 'Scalar_EncapsedStringPart'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php new file mode 100644 index 000000000..2cc2b22c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php @@ -0,0 +1,80 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + /** + * Constructs an LNumber node from a string number literal. + * + * @param string $str String number literal (decimal, octal, hex or binary) + * @param array $attributes Additional attributes + * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) + * + * @return LNumber The constructed LNumber, including kind attribute + */ + public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = false) : LNumber { + $attributes['rawValue'] = $str; + + $str = str_replace('_', '', $str); + + if ('0' !== $str[0] || '0' === $str) { + $attributes['kind'] = LNumber::KIND_DEC; + return new LNumber((int) $str, $attributes); + } + + if ('x' === $str[1] || 'X' === $str[1]) { + $attributes['kind'] = LNumber::KIND_HEX; + return new LNumber(hexdec($str), $attributes); + } + + if ('b' === $str[1] || 'B' === $str[1]) { + $attributes['kind'] = LNumber::KIND_BIN; + return new LNumber(bindec($str), $attributes); + } + + if (!$allowInvalidOctal && strpbrk($str, '89')) { + throw new Error('Invalid numeric literal', $attributes); + } + + // Strip optional explicit octal prefix. + if ('o' === $str[1] || 'O' === $str[1]) { + $str = substr($str, 2); + } + + // use intval instead of octdec to get proper cutting behavior with malformed numbers + $attributes['kind'] = LNumber::KIND_OCT; + return new LNumber(intval($str, 8), $attributes); + } + + public function getType() : string { + return 'Scalar_LNumber'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php new file mode 100644 index 000000000..941f0c762 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php @@ -0,0 +1,28 @@ +attributes = $attributes; + } + + public function getSubNodeNames() : array { + return []; + } + + /** + * Get name of magic constant. + * + * @return string Name of magic constant + */ + abstract public function getName() : string; +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php new file mode 100644 index 000000000..244328476 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php @@ -0,0 +1,16 @@ + '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ]; + + /** + * Constructs a string scalar node. + * + * @param string $value Value of the string + * @param array $attributes Additional attributes + */ + public function __construct(string $value, array $attributes = []) { + $this->attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + /** + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + */ + public static function fromString(string $str, array $attributes = [], bool $parseUnicodeEscape = true): self + { + $attributes['kind'] = ($str[0] === "'" || ($str[1] === "'" && ($str[0] === 'b' || $str[0] === 'B'))) + ? Scalar\String_::KIND_SINGLE_QUOTED + : Scalar\String_::KIND_DOUBLE_QUOTED; + + $attributes['rawValue'] = $str; + + $string = self::parse($str, $parseUnicodeEscape); + + return new self($string, $attributes); + } + + /** + * @internal + * + * Parses a string token. + * + * @param string $str String token content + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + * + * @return string The parsed string + */ + public static function parse(string $str, bool $parseUnicodeEscape = true) : string { + $bLength = 0; + if ('b' === $str[0] || 'B' === $str[0]) { + $bLength = 1; + } + + if ('\'' === $str[$bLength]) { + return str_replace( + ['\\\\', '\\\''], + ['\\', '\''], + substr($str, $bLength + 1, -1) + ); + } else { + return self::parseEscapeSequences( + substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape + ); + } + } + + /** + * @internal + * + * Parses escape sequences in strings (all string types apart from single quoted). + * + * @param string $str String without quotes + * @param null|string $quote Quote type + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + * + * @return string String with escape sequences parsed + */ + public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = true) : string { + if (null !== $quote) { + $str = str_replace('\\' . $quote, $quote, $str); + } + + $extra = ''; + if ($parseUnicodeEscape) { + $extra = '|u\{([0-9a-fA-F]+)\}'; + } + + return preg_replace_callback( + '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', + function($matches) { + $str = $matches[1]; + + if (isset(self::$replacements[$str])) { + return self::$replacements[$str]; + } elseif ('x' === $str[0] || 'X' === $str[0]) { + return chr(hexdec(substr($str, 1))); + } elseif ('u' === $str[0]) { + return self::codePointToUtf8(hexdec($matches[2])); + } else { + return chr(octdec($str)); + } + }, + $str + ); + } + + /** + * Converts a Unicode code point to its UTF-8 encoded representation. + * + * @param int $num Code point + * + * @return string UTF-8 representation of code point + */ + private static function codePointToUtf8(int $num) : string { + if ($num <= 0x7F) { + return chr($num); + } + if ($num <= 0x7FF) { + return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80); + } + if ($num <= 0xFFFF) { + return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); + } + if ($num <= 0x1FFFFF) { + return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80) + . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); + } + throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); + } + + public function getType() : string { + return 'Scalar_String'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php new file mode 100644 index 000000000..69d33e579 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php @@ -0,0 +1,9 @@ +attributes = $attributes; + $this->num = $num; + } + + public function getSubNodeNames() : array { + return ['num']; + } + + public function getType() : string { + return 'Stmt_Break'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php new file mode 100644 index 000000000..2bf044c90 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Case'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php new file mode 100644 index 000000000..5d7b5c016 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php @@ -0,0 +1,41 @@ +attributes = $attributes; + $this->types = $types; + $this->var = $var; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['types', 'var', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Catch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php new file mode 100644 index 000000000..8abaad6de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php @@ -0,0 +1,85 @@ +attributes = $attributes; + $this->flags = $flags; + $this->consts = $consts; + $this->attrGroups = $attrGroups; + $this->type = \is_string($type) ? new Node\Identifier($type) : $type; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'type', 'consts']; + } + + /** + * Whether constant is explicitly or implicitly public. + * + * @return bool + */ + public function isPublic() : bool { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + /** + * Whether constant is protected. + * + * @return bool + */ + public function isProtected() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + /** + * Whether constant is private. + * + * @return bool + */ + public function isPrivate() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + /** + * Whether constant is final. + * + * @return bool + */ + public function isFinal() : bool { + return (bool) ($this->flags & Class_::MODIFIER_FINAL); + } + + public function getType() : string { + return 'Stmt_ClassConst'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php new file mode 100644 index 000000000..2fa4e861b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php @@ -0,0 +1,109 @@ +stmts as $stmt) { + if ($stmt instanceof TraitUse) { + $traitUses[] = $stmt; + } + } + return $traitUses; + } + + /** + * @return ClassConst[] + */ + public function getConstants() : array { + $constants = []; + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassConst) { + $constants[] = $stmt; + } + } + return $constants; + } + + /** + * @return Property[] + */ + public function getProperties() : array { + $properties = []; + foreach ($this->stmts as $stmt) { + if ($stmt instanceof Property) { + $properties[] = $stmt; + } + } + return $properties; + } + + /** + * Gets property with the given name defined directly in this class/interface/trait. + * + * @param string $name Name of the property + * + * @return Property|null Property node or null if the property does not exist + */ + public function getProperty(string $name) { + foreach ($this->stmts as $stmt) { + if ($stmt instanceof Property) { + foreach ($stmt->props as $prop) { + if ($prop instanceof PropertyProperty && $name === $prop->name->toString()) { + return $stmt; + } + } + } + } + return null; + } + + /** + * Gets all methods defined directly in this class/interface/trait + * + * @return ClassMethod[] + */ + public function getMethods() : array { + $methods = []; + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassMethod) { + $methods[] = $stmt; + } + } + return $methods; + } + + /** + * Gets method with the given name defined directly in this class/interface/trait. + * + * @param string $name Name of the method (compared case-insensitively) + * + * @return ClassMethod|null Method node or null if the method does not exist + */ + public function getMethod(string $name) { + $lowerName = strtolower($name); + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) { + return $stmt; + } + } + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php new file mode 100644 index 000000000..6e85161e3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php @@ -0,0 +1,161 @@ + true, + '__destruct' => true, + '__call' => true, + '__callstatic' => true, + '__get' => true, + '__set' => true, + '__isset' => true, + '__unset' => true, + '__sleep' => true, + '__wakeup' => true, + '__tostring' => true, + '__set_state' => true, + '__clone' => true, + '__invoke' => true, + '__debuginfo' => true, + '__serialize' => true, + '__unserialize' => true, + ]; + + /** + * Constructs a class method node. + * + * @param string|Node\Identifier $name Name + * @param array $subNodes Array of the following optional subnodes: + * 'flags => MODIFIER_PUBLIC: Flags + * 'byRef' => false : Whether to return by reference + * 'params' => array() : Parameters + * 'returnType' => null : Return type + * 'stmts' => array() : Statements + * 'attrGroups' => array() : PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; + $this->byRef = $subNodes['byRef'] ?? false; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->params = $subNodes['params'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getStmts() { + return $this->stmts; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + /** + * Whether the method is explicitly or implicitly public. + * + * @return bool + */ + public function isPublic() : bool { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + /** + * Whether the method is protected. + * + * @return bool + */ + public function isProtected() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + /** + * Whether the method is private. + * + * @return bool + */ + public function isPrivate() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + /** + * Whether the method is abstract. + * + * @return bool + */ + public function isAbstract() : bool { + return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT); + } + + /** + * Whether the method is final. + * + * @return bool + */ + public function isFinal() : bool { + return (bool) ($this->flags & Class_::MODIFIER_FINAL); + } + + /** + * Whether the method is static. + * + * @return bool + */ + public function isStatic() : bool { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } + + /** + * Whether the method is magic. + * + * @return bool + */ + public function isMagic() : bool { + return isset(self::$magicNames[$this->name->toLowerString()]); + } + + public function getType() : string { + return 'Stmt_ClassMethod'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php new file mode 100644 index 000000000..52ed6c6cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php @@ -0,0 +1,137 @@ + 0 : Flags + * 'extends' => null : Name of extended class + * 'implements' => array(): Names of implemented interfaces + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->extends = $subNodes['extends'] ?? null; + $this->implements = $subNodes['implements'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts']; + } + + /** + * Whether the class is explicitly abstract. + * + * @return bool + */ + public function isAbstract() : bool { + return (bool) ($this->flags & self::MODIFIER_ABSTRACT); + } + + /** + * Whether the class is final. + * + * @return bool + */ + public function isFinal() : bool { + return (bool) ($this->flags & self::MODIFIER_FINAL); + } + + public function isReadonly() : bool { + return (bool) ($this->flags & self::MODIFIER_READONLY); + } + + /** + * Whether the class is anonymous. + * + * @return bool + */ + public function isAnonymous() : bool { + return null === $this->name; + } + + /** + * @internal + */ + public static function verifyClassModifier($a, $b) { + if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { + throw new Error('Multiple abstract modifiers are not allowed'); + } + + if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { + throw new Error('Multiple final modifiers are not allowed'); + } + + if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { + throw new Error('Multiple readonly modifiers are not allowed'); + } + + if ($a & 48 && $b & 48) { + throw new Error('Cannot use the final modifier on an abstract class'); + } + } + + /** + * @internal + */ + public static function verifyModifier($a, $b) { + if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) { + throw new Error('Multiple access type modifiers are not allowed'); + } + + if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { + throw new Error('Multiple abstract modifiers are not allowed'); + } + + if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { + throw new Error('Multiple static modifiers are not allowed'); + } + + if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { + throw new Error('Multiple final modifiers are not allowed'); + } + + if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) { + throw new Error('Multiple readonly modifiers are not allowed'); + } + + if ($a & 48 && $b & 48) { + throw new Error('Cannot use the final modifier on an abstract class member'); + } + } + + public function getType() : string { + return 'Stmt_Class'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php new file mode 100644 index 000000000..e6316345e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->consts = $consts; + } + + public function getSubNodeNames() : array { + return ['consts']; + } + + public function getType() : string { + return 'Stmt_Const'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php new file mode 100644 index 000000000..f2b30d79f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->num = $num; + } + + public function getSubNodeNames() : array { + return ['num']; + } + + public function getType() : string { + return 'Stmt_Continue'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php new file mode 100644 index 000000000..ac07f30c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php @@ -0,0 +1,34 @@ +value pair node. + * + * @param string|Node\Identifier $key Key + * @param Node\Expr $value Value + * @param array $attributes Additional attributes + */ + public function __construct($key, Node\Expr $value, array $attributes = []) { + $this->attributes = $attributes; + $this->key = \is_string($key) ? new Node\Identifier($key) : $key; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['key', 'value']; + } + + public function getType() : string { + return 'Stmt_DeclareDeclare'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php new file mode 100644 index 000000000..a3a5bfaa5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->declares = $declares; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['declares', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Declare'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php new file mode 100644 index 000000000..78e90da03 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['stmts', 'cond']; + } + + public function getType() : string { + return 'Stmt_Do'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php new file mode 100644 index 000000000..7cc50d5d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->exprs = $exprs; + } + + public function getSubNodeNames() : array { + return ['exprs']; + } + + public function getType() : string { + return 'Stmt_Echo'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php new file mode 100644 index 000000000..eef1ece32 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts']; + } + + public function getType() : string { + return 'Stmt_ElseIf'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php new file mode 100644 index 000000000..0e61778e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['stmts']; + } + + public function getType() : string { + return 'Stmt_Else'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php new file mode 100644 index 000000000..4b1079bcd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php @@ -0,0 +1,37 @@ +name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->expr = $expr; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'expr']; + } + + public function getType() : string { + return 'Stmt_EnumCase'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php new file mode 100644 index 000000000..3a50c225d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php @@ -0,0 +1,40 @@ + null : Scalar type + * 'implements' => array() : Names of implemented interfaces + * 'stmts' => array() : Statements + * 'attrGroups' => array() : PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->scalarType = $subNodes['scalarType'] ?? null; + $this->implements = $subNodes['implements'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + + parent::__construct($attributes); + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Enum'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php new file mode 100644 index 000000000..99d1687de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php @@ -0,0 +1,33 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Stmt_Expression'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php new file mode 100644 index 000000000..d55b8b687 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['stmts']; + } + + public function getType() : string { + return 'Stmt_Finally'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php new file mode 100644 index 000000000..1323d37cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php @@ -0,0 +1,43 @@ + array(): Init expressions + * 'cond' => array(): Loop conditions + * 'loop' => array(): Loop expressions + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->init = $subNodes['init'] ?? []; + $this->cond = $subNodes['cond'] ?? []; + $this->loop = $subNodes['loop'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + } + + public function getSubNodeNames() : array { + return ['init', 'cond', 'loop', 'stmts']; + } + + public function getType() : string { + return 'Stmt_For'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php new file mode 100644 index 000000000..0556a7ce5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php @@ -0,0 +1,47 @@ + null : Variable to assign key to + * 'byRef' => false : Whether to assign value by reference + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->expr = $expr; + $this->keyVar = $subNodes['keyVar'] ?? null; + $this->byRef = $subNodes['byRef'] ?? false; + $this->valueVar = $valueVar; + $this->stmts = $subNodes['stmts'] ?? []; + } + + public function getSubNodeNames() : array { + return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Foreach'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php new file mode 100644 index 000000000..c2ccae24e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php @@ -0,0 +1,77 @@ + false : Whether to return by reference + * 'params' => array(): Parameters + * 'returnType' => null : Return type + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->byRef = $subNodes['byRef'] ?? false; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->params = $subNodes['params'] ?? []; + $returnType = $subNodes['returnType'] ?? null; + $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts']; + } + + public function returnsByRef() : bool { + return $this->byRef; + } + + public function getParams() : array { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getAttrGroups() : array { + return $this->attrGroups; + } + + /** @return Node\Stmt[] */ + public function getStmts() : array { + return $this->stmts; + } + + public function getType() : string { + return 'Stmt_Function'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php new file mode 100644 index 000000000..a0022ad93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Stmt_Global'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php new file mode 100644 index 000000000..24a57f780 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Stmt_Goto'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php new file mode 100644 index 000000000..24520d223 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php @@ -0,0 +1,39 @@ +attributes = $attributes; + $this->type = $type; + $this->prefix = $prefix; + $this->uses = $uses; + } + + public function getSubNodeNames() : array { + return ['type', 'prefix', 'uses']; + } + + public function getType() : string { + return 'Stmt_GroupUse'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php new file mode 100644 index 000000000..8e624e0f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->remaining = $remaining; + } + + public function getSubNodeNames() : array { + return ['remaining']; + } + + public function getType() : string { + return 'Stmt_HaltCompiler'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php new file mode 100644 index 000000000..a1bae4bf8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php @@ -0,0 +1,43 @@ + array(): Statements + * 'elseifs' => array(): Elseif clauses + * 'else' => null : Else clause + * @param array $attributes Additional attributes + */ + public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->cond = $cond; + $this->stmts = $subNodes['stmts'] ?? []; + $this->elseifs = $subNodes['elseifs'] ?? []; + $this->else = $subNodes['else'] ?? null; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts', 'elseifs', 'else']; + } + + public function getType() : string { + return 'Stmt_If'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php new file mode 100644 index 000000000..0711d2842 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->value = $value; + } + + public function getSubNodeNames() : array { + return ['value']; + } + + public function getType() : string { + return 'Stmt_InlineHTML'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php new file mode 100644 index 000000000..4d587dd48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php @@ -0,0 +1,37 @@ + array(): Name of extended interfaces + * 'stmts' => array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->extends = $subNodes['extends'] ?? []; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'extends', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Interface'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php new file mode 100644 index 000000000..3edcb3be7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php @@ -0,0 +1,31 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Identifier($name) : $name; + } + + public function getSubNodeNames() : array { + return ['name']; + } + + public function getType() : string { + return 'Stmt_Label'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php new file mode 100644 index 000000000..fc249161a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php @@ -0,0 +1,38 @@ +attributes = $attributes; + $this->name = $name; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['name', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Namespace'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php new file mode 100644 index 000000000..f86f8df7d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php @@ -0,0 +1,17 @@ +attributes = $attributes; + $this->flags = $flags; + $this->props = $props; + $this->type = \is_string($type) ? new Identifier($type) : $type; + $this->attrGroups = $attrGroups; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'flags', 'type', 'props']; + } + + /** + * Whether the property is explicitly or implicitly public. + * + * @return bool + */ + public function isPublic() : bool { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + /** + * Whether the property is protected. + * + * @return bool + */ + public function isProtected() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + /** + * Whether the property is private. + * + * @return bool + */ + public function isPrivate() : bool { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + /** + * Whether the property is static. + * + * @return bool + */ + public function isStatic() : bool { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } + + /** + * Whether the property is readonly. + * + * @return bool + */ + public function isReadonly() : bool { + return (bool) ($this->flags & Class_::MODIFIER_READONLY); + } + + public function getType() : string { + return 'Stmt_Property'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php new file mode 100644 index 000000000..286b42961 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name; + $this->default = $default; + } + + public function getSubNodeNames() : array { + return ['name', 'default']; + } + + public function getType() : string { + return 'Stmt_PropertyProperty'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php new file mode 100644 index 000000000..53731254c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Stmt_Return'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php new file mode 100644 index 000000000..0cc47b412 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php @@ -0,0 +1,37 @@ +attributes = $attributes; + $this->var = $var; + $this->default = $default; + } + + public function getSubNodeNames() : array { + return ['var', 'default']; + } + + public function getType() : string { + return 'Stmt_StaticVar'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php new file mode 100644 index 000000000..464898ffa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Stmt_Static'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php new file mode 100644 index 000000000..2c8dae022 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->cases = $cases; + } + + public function getSubNodeNames() : array { + return ['cond', 'cases']; + } + + public function getType() : string { + return 'Stmt_Switch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php new file mode 100644 index 000000000..a34e2b362 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->expr = $expr; + } + + public function getSubNodeNames() : array { + return ['expr']; + } + + public function getType() : string { + return 'Stmt_Throw'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php new file mode 100644 index 000000000..9e97053b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->traits = $traits; + $this->adaptations = $adaptations; + } + + public function getSubNodeNames() : array { + return ['traits', 'adaptations']; + } + + public function getType() : string { + return 'Stmt_TraitUse'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php new file mode 100644 index 000000000..8bdd2c041 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php @@ -0,0 +1,13 @@ +attributes = $attributes; + $this->trait = $trait; + $this->method = \is_string($method) ? new Node\Identifier($method) : $method; + $this->newModifier = $newModifier; + $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName; + } + + public function getSubNodeNames() : array { + return ['trait', 'method', 'newModifier', 'newName']; + } + + public function getType() : string { + return 'Stmt_TraitUseAdaptation_Alias'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php new file mode 100644 index 000000000..80385f64e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->trait = $trait; + $this->method = \is_string($method) ? new Node\Identifier($method) : $method; + $this->insteadof = $insteadof; + } + + public function getSubNodeNames() : array { + return ['trait', 'method', 'insteadof']; + } + + public function getType() : string { + return 'Stmt_TraitUseAdaptation_Precedence'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php new file mode 100644 index 000000000..0cec203ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php @@ -0,0 +1,32 @@ + array(): Statements + * 'attrGroups' => array(): PHP attribute groups + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = [], array $attributes = []) { + $this->attributes = $attributes; + $this->name = \is_string($name) ? new Node\Identifier($name) : $name; + $this->stmts = $subNodes['stmts'] ?? []; + $this->attrGroups = $subNodes['attrGroups'] ?? []; + } + + public function getSubNodeNames() : array { + return ['attrGroups', 'name', 'stmts']; + } + + public function getType() : string { + return 'Stmt_Trait'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php new file mode 100644 index 000000000..74e004380 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php @@ -0,0 +1,38 @@ +attributes = $attributes; + $this->stmts = $stmts; + $this->catches = $catches; + $this->finally = $finally; + } + + public function getSubNodeNames() : array { + return ['stmts', 'catches', 'finally']; + } + + public function getType() : string { + return 'Stmt_TryCatch'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php new file mode 100644 index 000000000..310e427aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php @@ -0,0 +1,30 @@ +attributes = $attributes; + $this->vars = $vars; + } + + public function getSubNodeNames() : array { + return ['vars']; + } + + public function getType() : string { + return 'Stmt_Unset'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php new file mode 100644 index 000000000..32bd7847d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php @@ -0,0 +1,52 @@ +attributes = $attributes; + $this->type = $type; + $this->name = $name; + $this->alias = \is_string($alias) ? new Identifier($alias) : $alias; + } + + public function getSubNodeNames() : array { + return ['type', 'name', 'alias']; + } + + /** + * Get alias. If not explicitly given this is the last component of the used name. + * + * @return Identifier + */ + public function getAlias() : Identifier { + if (null !== $this->alias) { + return $this->alias; + } + + return new Identifier($this->name->getLast()); + } + + public function getType() : string { + return 'Stmt_UseUse'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php new file mode 100644 index 000000000..8753da313 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php @@ -0,0 +1,47 @@ +attributes = $attributes; + $this->type = $type; + $this->uses = $uses; + } + + public function getSubNodeNames() : array { + return ['type', 'uses']; + } + + public function getType() : string { + return 'Stmt_Use'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php new file mode 100644 index 000000000..f41034f8c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php @@ -0,0 +1,34 @@ +attributes = $attributes; + $this->cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() : array { + return ['cond', 'stmts']; + } + + public function getType() : string { + return 'Stmt_While'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php new file mode 100644 index 000000000..93cecd238 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php @@ -0,0 +1,28 @@ +attributes = $attributes; + $this->types = $types; + } + + public function getSubNodeNames() : array { + return ['types']; + } + + public function getType() : string { + return 'UnionType'; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php new file mode 100644 index 000000000..a30807a6d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php @@ -0,0 +1,17 @@ +attributes = $attributes; + } + + public function getType(): string { + return 'VariadicPlaceholder'; + } + + public function getSubNodeNames(): array { + return []; + } +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php new file mode 100644 index 000000000..04514da11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php @@ -0,0 +1,178 @@ +attributes = $attributes; + } + + /** + * Gets line the node started in (alias of getStartLine). + * + * @return int Start line (or -1 if not available) + */ + public function getLine() : int { + return $this->attributes['startLine'] ?? -1; + } + + /** + * Gets line the node started in. + * + * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default). + * + * @return int Start line (or -1 if not available) + */ + public function getStartLine() : int { + return $this->attributes['startLine'] ?? -1; + } + + /** + * Gets the line the node ended in. + * + * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default). + * + * @return int End line (or -1 if not available) + */ + public function getEndLine() : int { + return $this->attributes['endLine'] ?? -1; + } + + /** + * Gets the token offset of the first token that is part of this node. + * + * The offset is an index into the array returned by Lexer::getTokens(). + * + * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int Token start position (or -1 if not available) + */ + public function getStartTokenPos() : int { + return $this->attributes['startTokenPos'] ?? -1; + } + + /** + * Gets the token offset of the last token that is part of this node. + * + * The offset is an index into the array returned by Lexer::getTokens(). + * + * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int Token end position (or -1 if not available) + */ + public function getEndTokenPos() : int { + return $this->attributes['endTokenPos'] ?? -1; + } + + /** + * Gets the file offset of the first character that is part of this node. + * + * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int File start position (or -1 if not available) + */ + public function getStartFilePos() : int { + return $this->attributes['startFilePos'] ?? -1; + } + + /** + * Gets the file offset of the last character that is part of this node. + * + * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default). + * + * @return int File end position (or -1 if not available) + */ + public function getEndFilePos() : int { + return $this->attributes['endFilePos'] ?? -1; + } + + /** + * Gets all comments directly preceding this node. + * + * The comments are also available through the "comments" attribute. + * + * @return Comment[] + */ + public function getComments() : array { + return $this->attributes['comments'] ?? []; + } + + /** + * Gets the doc comment of the node. + * + * @return null|Comment\Doc Doc comment object or null + */ + public function getDocComment() { + $comments = $this->getComments(); + for ($i = count($comments) - 1; $i >= 0; $i--) { + $comment = $comments[$i]; + if ($comment instanceof Comment\Doc) { + return $comment; + } + } + + return null; + } + + /** + * Sets the doc comment of the node. + * + * This will either replace an existing doc comment or add it to the comments array. + * + * @param Comment\Doc $docComment Doc comment to set + */ + public function setDocComment(Comment\Doc $docComment) { + $comments = $this->getComments(); + for ($i = count($comments) - 1; $i >= 0; $i--) { + if ($comments[$i] instanceof Comment\Doc) { + // Replace existing doc comment. + $comments[$i] = $docComment; + $this->setAttribute('comments', $comments); + return; + } + } + + // Append new doc comment. + $comments[] = $docComment; + $this->setAttribute('comments', $comments); + } + + public function setAttribute(string $key, $value) { + $this->attributes[$key] = $value; + } + + public function hasAttribute(string $key) : bool { + return array_key_exists($key, $this->attributes); + } + + public function getAttribute(string $key, $default = null) { + if (array_key_exists($key, $this->attributes)) { + return $this->attributes[$key]; + } + + return $default; + } + + public function getAttributes() : array { + return $this->attributes; + } + + public function setAttributes(array $attributes) { + $this->attributes = $attributes; + } + + /** + * @return array + */ + public function jsonSerialize() : array { + return ['nodeType' => $this->getType()] + get_object_vars($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php new file mode 100644 index 000000000..e0c7f783a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php @@ -0,0 +1,206 @@ +dumpComments = !empty($options['dumpComments']); + $this->dumpPositions = !empty($options['dumpPositions']); + } + + /** + * Dumps a node or array. + * + * @param array|Node $node Node or array to dump + * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if + * the dumpPositions option is enabled and the dumping of node offsets + * is desired. + * + * @return string Dumped value + */ + public function dump($node, ?string $code = null) : string { + $this->code = $code; + return $this->dumpRecursive($node); + } + + protected function dumpRecursive($node) { + if ($node instanceof Node) { + $r = $node->getType(); + if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) { + $r .= $p; + } + $r .= '('; + + foreach ($node->getSubNodeNames() as $key) { + $r .= "\n " . $key . ': '; + + $value = $node->$key; + if (null === $value) { + $r .= 'null'; + } elseif (false === $value) { + $r .= 'false'; + } elseif (true === $value) { + $r .= 'true'; + } elseif (is_scalar($value)) { + if ('flags' === $key || 'newModifier' === $key) { + $r .= $this->dumpFlags($value); + } elseif ('type' === $key && $node instanceof Include_) { + $r .= $this->dumpIncludeType($value); + } elseif ('type' === $key + && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) { + $r .= $this->dumpUseType($value); + } else { + $r .= $value; + } + } else { + $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); + } + } + + if ($this->dumpComments && $comments = $node->getComments()) { + $r .= "\n comments: " . str_replace("\n", "\n ", $this->dumpRecursive($comments)); + } + } elseif (is_array($node)) { + $r = 'array('; + + foreach ($node as $key => $value) { + $r .= "\n " . $key . ': '; + + if (null === $value) { + $r .= 'null'; + } elseif (false === $value) { + $r .= 'false'; + } elseif (true === $value) { + $r .= 'true'; + } elseif (is_scalar($value)) { + $r .= $value; + } else { + $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); + } + } + } elseif ($node instanceof Comment) { + return $node->getReformattedText(); + } else { + throw new \InvalidArgumentException('Can only dump nodes and arrays.'); + } + + return $r . "\n)"; + } + + protected function dumpFlags($flags) { + $strs = []; + if ($flags & Class_::MODIFIER_PUBLIC) { + $strs[] = 'MODIFIER_PUBLIC'; + } + if ($flags & Class_::MODIFIER_PROTECTED) { + $strs[] = 'MODIFIER_PROTECTED'; + } + if ($flags & Class_::MODIFIER_PRIVATE) { + $strs[] = 'MODIFIER_PRIVATE'; + } + if ($flags & Class_::MODIFIER_ABSTRACT) { + $strs[] = 'MODIFIER_ABSTRACT'; + } + if ($flags & Class_::MODIFIER_STATIC) { + $strs[] = 'MODIFIER_STATIC'; + } + if ($flags & Class_::MODIFIER_FINAL) { + $strs[] = 'MODIFIER_FINAL'; + } + if ($flags & Class_::MODIFIER_READONLY) { + $strs[] = 'MODIFIER_READONLY'; + } + + if ($strs) { + return implode(' | ', $strs) . ' (' . $flags . ')'; + } else { + return $flags; + } + } + + protected function dumpIncludeType($type) { + $map = [ + Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', + Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', + Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', + Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE', + ]; + + if (!isset($map[$type])) { + return $type; + } + return $map[$type] . ' (' . $type . ')'; + } + + protected function dumpUseType($type) { + $map = [ + Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', + Use_::TYPE_NORMAL => 'TYPE_NORMAL', + Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', + Use_::TYPE_CONSTANT => 'TYPE_CONSTANT', + ]; + + if (!isset($map[$type])) { + return $type; + } + return $map[$type] . ' (' . $type . ')'; + } + + /** + * Dump node position, if possible. + * + * @param Node $node Node for which to dump position + * + * @return string|null Dump of position, or null if position information not available + */ + protected function dumpPosition(Node $node) { + if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { + return null; + } + + $start = $node->getStartLine(); + $end = $node->getEndLine(); + if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') + && null !== $this->code + ) { + $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos()); + $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos()); + } + return "[$start - $end]"; + } + + // Copied from Error class + private function toColumn($code, $pos) { + if ($pos > strlen($code)) { + throw new \RuntimeException('Invalid position information'); + } + + $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); + if (false === $lineStartPos) { + $lineStartPos = -1; + } + + return $pos - $lineStartPos; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php new file mode 100644 index 000000000..2e7cfdad4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php @@ -0,0 +1,81 @@ +addVisitor($visitor); + $traverser->traverse($nodes); + + return $visitor->getFoundNodes(); + } + + /** + * Find all nodes that are instances of a certain class. + * + * @param Node|Node[] $nodes Single node or array of nodes to search in + * @param string $class Class name + * + * @return Node[] Found nodes (all instances of $class) + */ + public function findInstanceOf($nodes, string $class) : array { + return $this->find($nodes, function ($node) use ($class) { + return $node instanceof $class; + }); + } + + /** + * Find first node satisfying a filter callback. + * + * @param Node|Node[] $nodes Single node or array of nodes to search in + * @param callable $filter Filter callback: function(Node $node) : bool + * + * @return null|Node Found node (or null if none found) + */ + public function findFirst($nodes, callable $filter) { + if (!is_array($nodes)) { + $nodes = [$nodes]; + } + + $visitor = new FirstFindingVisitor($filter); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $traverser->traverse($nodes); + + return $visitor->getFoundNode(); + } + + /** + * Find first node that is an instance of a certain class. + * + * @param Node|Node[] $nodes Single node or array of nodes to search in + * @param string $class Class name + * + * @return null|Node Found node, which is an instance of $class (or null if none found) + */ + public function findFirstInstanceOf($nodes, string $class) { + return $this->findFirst($nodes, function ($node) use ($class) { + return $node instanceof $class; + }); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php new file mode 100644 index 000000000..97d45bdaa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php @@ -0,0 +1,291 @@ +visitors[] = $visitor; + } + + /** + * Removes an added visitor. + * + * @param NodeVisitor $visitor + */ + public function removeVisitor(NodeVisitor $visitor) { + foreach ($this->visitors as $index => $storedVisitor) { + if ($storedVisitor === $visitor) { + unset($this->visitors[$index]); + break; + } + } + } + + /** + * Traverses an array of nodes using the registered visitors. + * + * @param Node[] $nodes Array of nodes + * + * @return Node[] Traversed array of nodes + */ + public function traverse(array $nodes) : array { + $this->stopTraversal = false; + + foreach ($this->visitors as $visitor) { + if (null !== $return = $visitor->beforeTraverse($nodes)) { + $nodes = $return; + } + } + + $nodes = $this->traverseArray($nodes); + + foreach ($this->visitors as $visitor) { + if (null !== $return = $visitor->afterTraverse($nodes)) { + $nodes = $return; + } + } + + return $nodes; + } + + /** + * Recursively traverse a node. + * + * @param Node $node Node to traverse. + * + * @return Node Result of traversal (may be original node or new one) + */ + protected function traverseNode(Node $node) : Node { + foreach ($node->getSubNodeNames() as $name) { + $subNode =& $node->$name; + + if (\is_array($subNode)) { + $subNode = $this->traverseArray($subNode); + if ($this->stopTraversal) { + break; + } + } elseif ($subNode instanceof Node) { + $traverseChildren = true; + $breakVisitorIndex = null; + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->enterNode($subNode); + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($subNode, $return); + $subNode = $return; + } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { + $traverseChildren = false; + } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { + $traverseChildren = false; + $breakVisitorIndex = $visitorIndex; + break; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else { + throw new \LogicException( + 'enterNode() returned invalid value of type ' . gettype($return) + ); + } + } + } + + if ($traverseChildren) { + $subNode = $this->traverseNode($subNode); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->leaveNode($subNode); + + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($subNode, $return); + $subNode = $return; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } elseif (\is_array($return)) { + throw new \LogicException( + 'leaveNode() may only return an array ' . + 'if the parent structure is an array' + ); + } else { + throw new \LogicException( + 'leaveNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($breakVisitorIndex === $visitorIndex) { + break; + } + } + } + } + + return $node; + } + + /** + * Recursively traverse array (usually of nodes). + * + * @param array $nodes Array to traverse + * + * @return array Result of traversal (may be original array or changed one) + */ + protected function traverseArray(array $nodes) : array { + $doNodes = []; + + foreach ($nodes as $i => &$node) { + if ($node instanceof Node) { + $traverseChildren = true; + $breakVisitorIndex = null; + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->enterNode($node); + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($node, $return); + $node = $return; + } elseif (self::DONT_TRAVERSE_CHILDREN === $return) { + $traverseChildren = false; + } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) { + $traverseChildren = false; + $breakVisitorIndex = $visitorIndex; + break; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else { + throw new \LogicException( + 'enterNode() returned invalid value of type ' . gettype($return) + ); + } + } + } + + if ($traverseChildren) { + $node = $this->traverseNode($node); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->leaveNode($node); + + if (null !== $return) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($node, $return); + $node = $return; + } elseif (\is_array($return)) { + $doNodes[] = [$i, $return]; + break; + } elseif (self::REMOVE_NODE === $return) { + $doNodes[] = [$i, []]; + break; + } elseif (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } elseif (false === $return) { + throw new \LogicException( + 'bool(false) return from leaveNode() no longer supported. ' . + 'Return NodeTraverser::REMOVE_NODE instead' + ); + } else { + throw new \LogicException( + 'leaveNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($breakVisitorIndex === $visitorIndex) { + break; + } + } + } elseif (\is_array($node)) { + throw new \LogicException('Invalid node structure: Contains nested arrays'); + } + } + + if (!empty($doNodes)) { + while (list($i, $replace) = array_pop($doNodes)) { + array_splice($nodes, $i, 1, $replace); + } + } + + return $nodes; + } + + private function ensureReplacementReasonable($old, $new) { + if ($old instanceof Node\Stmt && $new instanceof Node\Expr) { + throw new \LogicException( + "Trying to replace statement ({$old->getType()}) " . + "with expression ({$new->getType()}). Are you missing a " . + "Stmt_Expression wrapper?" + ); + } + + if ($old instanceof Node\Expr && $new instanceof Node\Stmt) { + throw new \LogicException( + "Trying to replace expression ({$old->getType()}) " . + "with statement ({$new->getType()})" + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php new file mode 100644 index 000000000..77ff3d27f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php @@ -0,0 +1,29 @@ + $node stays as-is + * * NodeTraverser::DONT_TRAVERSE_CHILDREN + * => Children of $node are not traversed. $node stays as-is + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return null|int|Node Replacement node (or special return value) + */ + public function enterNode(Node $node); + + /** + * Called when leaving a node. + * + * Return value semantics: + * * null + * => $node stays as-is + * * NodeTraverser::REMOVE_NODE + * => $node is removed from the parent array + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * array (of Nodes) + * => The return value is merged into the parent array (at the position of the $node) + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return null|int|Node|Node[] Replacement node (or special return value) + */ + public function leaveNode(Node $node); + + /** + * Called once after traversal. + * + * Return value semantics: + * * null: $nodes stays as-is + * * otherwise: $nodes is set to the return value + * + * @param Node[] $nodes Array of nodes + * + * @return null|Node[] Array of nodes + */ + public function afterTraverse(array $nodes); +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php new file mode 100644 index 000000000..a85fa493b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php @@ -0,0 +1,20 @@ +setAttribute('origNode', $origNode); + return $node; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php new file mode 100644 index 000000000..9531edbce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php @@ -0,0 +1,48 @@ +filterCallback = $filterCallback; + } + + /** + * Get found nodes satisfying the filter callback. + * + * Nodes are returned in pre-order. + * + * @return Node[] Found nodes + */ + public function getFoundNodes() : array { + return $this->foundNodes; + } + + public function beforeTraverse(array $nodes) { + $this->foundNodes = []; + + return null; + } + + public function enterNode(Node $node) { + $filterCallback = $this->filterCallback; + if ($filterCallback($node)) { + $this->foundNodes[] = $node; + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php new file mode 100644 index 000000000..596a7d7fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php @@ -0,0 +1,50 @@ +filterCallback = $filterCallback; + } + + /** + * Get found node satisfying the filter callback. + * + * Returns null if no node satisfies the filter callback. + * + * @return null|Node Found node (or null if not found) + */ + public function getFoundNode() { + return $this->foundNode; + } + + public function beforeTraverse(array $nodes) { + $this->foundNode = null; + + return null; + } + + public function enterNode(Node $node) { + $filterCallback = $this->filterCallback; + if ($filterCallback($node)) { + $this->foundNode = $node; + return NodeTraverser::STOP_TRAVERSAL; + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php new file mode 100644 index 000000000..dd2e9ca76 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php @@ -0,0 +1,260 @@ +nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing); + $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false; + $this->replaceNodes = $options['replaceNodes'] ?? true; + } + + /** + * Get name resolution context. + * + * @return NameContext + */ + public function getNameContext() : NameContext { + return $this->nameContext; + } + + public function beforeTraverse(array $nodes) { + $this->nameContext->startNamespace(); + return null; + } + + public function enterNode(Node $node) { + if ($node instanceof Stmt\Namespace_) { + $this->nameContext->startNamespace($node->name); + } elseif ($node instanceof Stmt\Use_) { + foreach ($node->uses as $use) { + $this->addAlias($use, $node->type, null); + } + } elseif ($node instanceof Stmt\GroupUse) { + foreach ($node->uses as $use) { + $this->addAlias($use, $node->type, $node->prefix); + } + } elseif ($node instanceof Stmt\Class_) { + if (null !== $node->extends) { + $node->extends = $this->resolveClassName($node->extends); + } + + foreach ($node->implements as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->resolveAttrGroups($node); + if (null !== $node->name) { + $this->addNamespacedName($node); + } + } elseif ($node instanceof Stmt\Interface_) { + foreach ($node->extends as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->resolveAttrGroups($node); + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\Enum_) { + foreach ($node->implements as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->resolveAttrGroups($node); + if (null !== $node->name) { + $this->addNamespacedName($node); + } + } elseif ($node instanceof Stmt\Trait_) { + $this->resolveAttrGroups($node); + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\Function_) { + $this->resolveSignature($node); + $this->resolveAttrGroups($node); + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\ClassMethod + || $node instanceof Expr\Closure + || $node instanceof Expr\ArrowFunction + ) { + $this->resolveSignature($node); + $this->resolveAttrGroups($node); + } elseif ($node instanceof Stmt\Property) { + if (null !== $node->type) { + $node->type = $this->resolveType($node->type); + } + $this->resolveAttrGroups($node); + } elseif ($node instanceof Stmt\Const_) { + foreach ($node->consts as $const) { + $this->addNamespacedName($const); + } + } else if ($node instanceof Stmt\ClassConst) { + if (null !== $node->type) { + $node->type = $this->resolveType($node->type); + } + $this->resolveAttrGroups($node); + } else if ($node instanceof Stmt\EnumCase) { + $this->resolveAttrGroups($node); + } elseif ($node instanceof Expr\StaticCall + || $node instanceof Expr\StaticPropertyFetch + || $node instanceof Expr\ClassConstFetch + || $node instanceof Expr\New_ + || $node instanceof Expr\Instanceof_ + ) { + if ($node->class instanceof Name) { + $node->class = $this->resolveClassName($node->class); + } + } elseif ($node instanceof Stmt\Catch_) { + foreach ($node->types as &$type) { + $type = $this->resolveClassName($type); + } + } elseif ($node instanceof Expr\FuncCall) { + if ($node->name instanceof Name) { + $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION); + } + } elseif ($node instanceof Expr\ConstFetch) { + $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT); + } elseif ($node instanceof Stmt\TraitUse) { + foreach ($node->traits as &$trait) { + $trait = $this->resolveClassName($trait); + } + + foreach ($node->adaptations as $adaptation) { + if (null !== $adaptation->trait) { + $adaptation->trait = $this->resolveClassName($adaptation->trait); + } + + if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { + foreach ($adaptation->insteadof as &$insteadof) { + $insteadof = $this->resolveClassName($insteadof); + } + } + } + } + + return null; + } + + private function addAlias(Stmt\UseUse $use, int $type, ?Name $prefix = null) { + // Add prefix for group uses + $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; + // Type is determined either by individual element or whole use declaration + $type |= $use->type; + + $this->nameContext->addAlias( + $name, (string) $use->getAlias(), $type, $use->getAttributes() + ); + } + + /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ + private function resolveSignature($node) { + foreach ($node->params as $param) { + $param->type = $this->resolveType($param->type); + $this->resolveAttrGroups($param); + } + $node->returnType = $this->resolveType($node->returnType); + } + + private function resolveType($node) { + if ($node instanceof Name) { + return $this->resolveClassName($node); + } + if ($node instanceof Node\NullableType) { + $node->type = $this->resolveType($node->type); + return $node; + } + if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { + foreach ($node->types as &$type) { + $type = $this->resolveType($type); + } + return $node; + } + return $node; + } + + /** + * Resolve name, according to name resolver options. + * + * @param Name $name Function or constant name to resolve + * @param int $type One of Stmt\Use_::TYPE_* + * + * @return Name Resolved name, or original name with attribute + */ + protected function resolveName(Name $name, int $type) : Name { + if (!$this->replaceNodes) { + $resolvedName = $this->nameContext->getResolvedName($name, $type); + if (null !== $resolvedName) { + $name->setAttribute('resolvedName', $resolvedName); + } else { + $name->setAttribute('namespacedName', FullyQualified::concat( + $this->nameContext->getNamespace(), $name, $name->getAttributes())); + } + return $name; + } + + if ($this->preserveOriginalNames) { + // Save the original name + $originalName = $name; + $name = clone $originalName; + $name->setAttribute('originalName', $originalName); + } + + $resolvedName = $this->nameContext->getResolvedName($name, $type); + if (null !== $resolvedName) { + return $resolvedName; + } + + // unqualified names inside a namespace cannot be resolved at compile-time + // add the namespaced version of the name as an attribute + $name->setAttribute('namespacedName', FullyQualified::concat( + $this->nameContext->getNamespace(), $name, $name->getAttributes())); + return $name; + } + + protected function resolveClassName(Name $name) { + return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL); + } + + protected function addNamespacedName(Node $node) { + $node->namespacedName = Name::concat( + $this->nameContext->getNamespace(), (string) $node->name); + } + + protected function resolveAttrGroups(Node $node) + { + foreach ($node->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + $attr->name = $this->resolveClassName($attr->name); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php new file mode 100644 index 000000000..ea372e5b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php @@ -0,0 +1,52 @@ +$node->getAttribute('parent'), the previous + * node can be accessed through $node->getAttribute('previous'), + * and the next node can be accessed through $node->getAttribute('next'). + */ +final class NodeConnectingVisitor extends NodeVisitorAbstract +{ + /** + * @var Node[] + */ + private $stack = []; + + /** + * @var ?Node + */ + private $previous; + + public function beforeTraverse(array $nodes) { + $this->stack = []; + $this->previous = null; + } + + public function enterNode(Node $node) { + if (!empty($this->stack)) { + $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + } + + if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { + $node->setAttribute('previous', $this->previous); + $this->previous->setAttribute('next', $node); + } + + $this->stack[] = $node; + } + + public function leaveNode(Node $node) { + $this->previous = $node; + + array_pop($this->stack); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php new file mode 100644 index 000000000..b98d2bfa6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php @@ -0,0 +1,41 @@ +$node->getAttribute('parent'). + */ +final class ParentConnectingVisitor extends NodeVisitorAbstract +{ + /** + * @var Node[] + */ + private $stack = []; + + public function beforeTraverse(array $nodes) + { + $this->stack = []; + } + + public function enterNode(Node $node) + { + if (!empty($this->stack)) { + $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + } + + $this->stack[] = $node; + } + + public function leaveNode(Node $node) + { + array_pop($this->stack); + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php new file mode 100644 index 000000000..d378d6709 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php @@ -0,0 +1,25 @@ +parsers = $parsers; + } + + public function parse(string $code, ?ErrorHandler $errorHandler = null) { + if (null === $errorHandler) { + $errorHandler = new ErrorHandler\Throwing; + } + + list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code); + if ($firstError === null) { + return $firstStmts; + } + + for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) { + list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code); + if ($error === null) { + return $stmts; + } + } + + throw $firstError; + } + + private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) { + $stmts = null; + $error = null; + try { + $stmts = $parser->parse($code, $errorHandler); + } catch (Error $error) {} + return [$stmts, $error]; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php new file mode 100644 index 000000000..80ebdfb37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php @@ -0,0 +1,2682 @@ +'", + "T_IS_GREATER_OR_EQUAL", + "T_SL", + "T_SR", + "'+'", + "'-'", + "'.'", + "'*'", + "'/'", + "'%'", + "'!'", + "T_INSTANCEOF", + "'~'", + "T_INC", + "T_DEC", + "T_INT_CAST", + "T_DOUBLE_CAST", + "T_STRING_CAST", + "T_ARRAY_CAST", + "T_OBJECT_CAST", + "T_BOOL_CAST", + "T_UNSET_CAST", + "'@'", + "T_POW", + "'['", + "T_NEW", + "T_CLONE", + "T_EXIT", + "T_IF", + "T_ELSEIF", + "T_ELSE", + "T_ENDIF", + "T_LNUMBER", + "T_DNUMBER", + "T_STRING", + "T_STRING_VARNAME", + "T_VARIABLE", + "T_NUM_STRING", + "T_INLINE_HTML", + "T_ENCAPSED_AND_WHITESPACE", + "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", + "T_DO", + "T_WHILE", + "T_ENDWHILE", + "T_FOR", + "T_ENDFOR", + "T_FOREACH", + "T_ENDFOREACH", + "T_DECLARE", + "T_ENDDECLARE", + "T_AS", + "T_SWITCH", + "T_MATCH", + "T_ENDSWITCH", + "T_CASE", + "T_DEFAULT", + "T_BREAK", + "T_CONTINUE", + "T_GOTO", + "T_FUNCTION", + "T_FN", + "T_CONST", + "T_RETURN", + "T_TRY", + "T_CATCH", + "T_FINALLY", + "T_USE", + "T_INSTEADOF", + "T_GLOBAL", + "T_STATIC", + "T_ABSTRACT", + "T_FINAL", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_READONLY", + "T_VAR", + "T_UNSET", + "T_ISSET", + "T_EMPTY", + "T_HALT_COMPILER", + "T_CLASS", + "T_TRAIT", + "T_INTERFACE", + "T_EXTENDS", + "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", + "T_LIST", + "T_ARRAY", + "T_CALLABLE", + "T_CLASS_C", + "T_TRAIT_C", + "T_METHOD_C", + "T_FUNC_C", + "T_LINE", + "T_FILE", + "T_START_HEREDOC", + "T_END_HEREDOC", + "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", + "T_PAAMAYIM_NEKUDOTAYIM", + "T_NAMESPACE", + "T_NS_C", + "T_DIR", + "T_NS_SEPARATOR", + "T_ELLIPSIS", + "T_NAME_FULLY_QUALIFIED", + "T_NAME_QUALIFIED", + "T_NAME_RELATIVE", + "';'", + "'{'", + "'}'", + "'('", + "')'", + "'$'", + "'`'", + "']'", + "'\"'", + "T_ENUM", + "T_NULLSAFE_OBJECT_OPERATOR", + "T_ATTRIBUTE" + ); + + protected $tokenToSymbol = array( + 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 56, 164, 168, 161, 55, 168, 168, + 159, 160, 53, 50, 8, 51, 52, 54, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 31, 156, + 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 70, 168, 163, 36, 168, 162, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 157, 35, 158, 58, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, + 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, + 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 165, 131, + 132, 133, 166, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 167 + ); + + protected $action = array( + 701, 671, 672, 673, 674, 675, 286, 676, 677, 678, + 714, 715, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 0, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244,-32766,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, 245, 246, + 242, 243, 244,-32766,-32766, 679,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32766, 1230, 245, 246, 1231, 680, + 681, 682, 683, 684, 685, 686, 900, 901, 748,-32766, + -32766,-32766,-32766,-32766,-32766, 687, 688, 689, 690, 691, + 692, 693, 694, 695, 696, 697, 717, 740, 718, 719, + 720, 721, 709, 710, 711, 739, 712, 713, 698, 699, + 700, 702, 703, 704, 742, 743, 744, 745, 746, 747, + 876, 705, 706, 707, 708, 738, 729, 727, 728, 724, + 725, 1047, 716, 722, 723, 730, 731, 733, 732, 734, + 735, 55, 56, 425, 57, 58, 726, 737, 736, 756, + 59, 60, -226, 61,-32766,-32766,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766, 337,-32767,-32767,-32767,-32767, 29, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 621,-32766,-32766,-32766,-32766, 62, 63, + 1047,-32766,-32766,-32766, 64, 419, 65, 294, 295, 66, + 67, 68, 69, 70, 71, 72, 73, 824, 25, 302, + 74, 418, 985, 987, 670, 669, 1101, 1102, 1079, 756, + 756, 768, 1221, 769, 470,-32766,-32766,-32766, 341, 750, + 825, 54,-32767,-32767,-32767,-32767, 98, 99, 100, 101, + 102, 220, 221, 222, 362, 877,-32766, 27,-32766,-32766, + -32766,-32766,-32766, 1047, 492, 126, 1081, 1080, 1082, 370, + 1069, 931, 207, 478, 479, 953, 954, 955, 952, 951, + 950, 128, 480, 481, 804, 1107, 1108, 1109, 1110, 1104, + 1105, 319, 32, 297, 10, 211, -515, 1111, 1106, 670, + 669, 1081, 1080, 1082, 220, 221, 222, 41, 364, 341, + 334, 421, 336, 426, -128, -128, -128, 313, 1047, 469, + -4, 825, 54, 813, 597, 207, 40, 21, 427, -128, + 471, -128, 472, -128, 473, -128, 1047, 428, 220, 221, + 222,-32766, 33, 34, 429, 361, 327, 52, 35, 474, + -32766,-32766,-32766, 342, 357, 358, 475, 476, 48, 207, + 249, 670, 669, 477, 443, 300, 796, 847, 430, 431, + 28,-32766, 815,-32766,-32766,-32766,-32766,-32766,-32766,-32766, + -32767,-32767,-32767,-32767,-32767, 953, 954, 955, 952, 951, + 950, 422, 756, 424, 426, 827, 635, -128,-32766,-32766, + 469, 825, 54, 288, 813, 1152, 756, 40, 21, 427, + 317, 471, 345, 472, 129, 473, 9, 1187, 428, 612, + 360, 324, 906, 33, 34, 429, 361, 1047, 415, 35, + 474, 945, 1069, 315, 125, 357, 358, 475, 476,-32766, + -32766,-32766, 927, 302, 477, 121, 1069, 760, 847, 430, + 431, 670, 669, 423, 756, 1153, 810, 1047, 480, 767, + -32766, 806,-32766,-32766,-32766,-32766, -261, 127, 347, 436, + 842, 341, 1079, 1201, 426, 446, 827, 635, -4, 808, + 469, 825, 54, 436, 813, 341, 756, 40, 21, 427, + 444, 471, 130, 472, 1069, 473, 346, 768, 428, 769, + -211, -211, -211, 33, 34, 429, 361, 308, 1077, 35, + 474,-32766,-32766,-32766, 1047, 357, 358, 475, 476,-32766, + -32766,-32766, 907, 120, 477, 538, 1069, 796, 847, 430, + 431, 436,-32766, 341,-32766,-32766,-32766, 1047, 480, 811, + -32766, 926,-32766,-32766, 755, 1081, 1080, 1082, 49,-32766, + -32766,-32766, 750, 752, 426, 1202, 827, 635, -211, 30, + 469, 670, 669, 436, 813, 341, 75, 40, 21, 427, + -32766, 471, 1065, 472, 124, 473, 670, 669, 428, 212, + -210, -210, -210, 33, 34, 429, 361, 51, 1187, 35, + 474, 756,-32766,-32766,-32766, 357, 358, 475, 476, 213, + 825, 54, 221, 222, 477, 20, 580, 796, 847, 430, + 431, 220, 221, 222, 756, 222, 247, 78, 79, 80, + 81, 341, 207, 516, 103, 104, 105, 753, 307, 131, + 638, 1069, 207, 341, 207, 122, 827, 635, -210, 36, + 106, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 1113, 307, 346, 436, 214, + 341, 825, 54, 426, 123, 250, 129, 134, 106, 469, + -32766, 571, 1113, 813, 245, 246, 40, 21, 427, 251, + 471, 252, 472, 341, 473, 453, 22, 428, 207, 900, + 901, 639, 33, 34, 429, 825, 54, -86, 35, 474, + 220, 221, 222, 314, 357, 358, 100, 101, 102, 239, + 240, 241, 646, 477, -230, 458, 588, 135, 374, 595, + 596, 207, 761, 641, 649, 643, 942, 655, 930, 663, + 823, 133, 307, 838, 426,-32766, 106, 750, 43, 44, + 469, 45, 442, 46, 813, 827, 635, 40, 21, 427, + 47, 471, 50, 472, 53, 473, 132, 608, 428, 302, + 604, -280,-32766, 33, 34, 429, 825, 54, 426, 35, + 474, 756, 958, -84, 469, 357, 358, 520, 813, 629, + 363, 40, 21, 427, 477, 471, 574, 472, -515, 473, + 848, 617, 428, -423,-32766, 11, 647, 33, 34, 429, + 825, 54, 445, 35, 474, 462, 285, 577, 1112, 357, + 358, 592, 369, 849, 593, 290, 827, 635, 477, 0, + 0, 531, 0, 0, 325, 0, 0, 0, 0, 0, + 652, 0, 0, 0, 322, 326, 0, 0, 0, 426, + 0, 0, 0, 0, 323, 469, 316, 318, -516, 813, + 863, 635, 40, 21, 427, 0, 471, 0, 472, 0, + 473, 1159, 0, 428, 0, -414, 6, 7, 33, 34, + 429, 825, 54, 426, 35, 474, 12, 14, 373, 469, + 357, 358, -424, 813, 562, 755, 40, 21, 427, 477, + 471, 248, 472, 840, 473, 38, 39, 428, 658, 659, + 814, 822, 33, 34, 429, 801, 816, 879, 35, 474, + 215, 216, 870, 871, 357, 358, 217, 771, 218, 799, + 864, 827, 635, 477, 770, 861, 859, 937, 938, 935, + 209, 821, 805, 807, 809, 812, 934, 764, 1101, 1102, + 765, 936, 24, 78, 426, 335, 1103, 359, 636, 640, + 469, 642, 644, 645, 813, 827, 635, 40, 21, 427, + 648, 471, 650, 472, 651, 473, 653, 654, 428, 637, + 26, 660, 797, 33, 34, 429, 215, 216, 1227, 35, + 474, 1229, 217, 763, 218, 357, 358, 846, 762, 845, + 1228, 844, 1061, 832, 477, 558, 209, 1107, 1108, 1109, + 1110, 1104, 1105, 398, 1101, 1102, 1049, 843, 1050, 1111, + 1106, 830, 1103, 943, 868, 869, 457, 1226, 1158, 219, + 1195, 1193, 1178, 1191, 1092, 918, 827, 635, 31, 1199, + 1189, 1056, 37, 42, 76, 77, 210, 287, 292, 293, + 308, 309, 310, 311, 339, 356, 416, 0, -227, -226, + 16, 17, 18, 393, 454, 461, 463, 467, 552, 626, + 1052, 558, 1055, 1107, 1108, 1109, 1110, 1104, 1105, 398, + 908, 1117, 1051, 1027, 563, 1111, 1106, 1026, 1094, 1058, + 0, -433, 1045, 0, 1057, 219, 1060, 1059, 1076, 0, + 1192, 1177, 1173, 1190, 1091, 1224, 1118, 1172, 600 + ); + + protected $actionCheck = array( + 2, 3, 4, 5, 6, 7, 14, 9, 10, 11, + 12, 13, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 0, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 9, 10, 11, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 69, 70, + 53, 54, 55, 9, 10, 57, 30, 116, 32, 33, + 34, 35, 36, 37, 38, 80, 69, 70, 83, 71, + 72, 73, 74, 75, 76, 77, 135, 136, 80, 33, + 34, 35, 36, 37, 38, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 31, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 13, 134, 135, 136, 137, 138, 139, 140, 141, + 142, 3, 4, 5, 6, 7, 148, 149, 150, 82, + 12, 13, 160, 15, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 8, 44, 45, 46, 47, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 80, 33, 34, 35, 36, 50, 51, + 13, 9, 10, 11, 56, 128, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, + 72, 73, 59, 60, 37, 38, 78, 79, 80, 82, + 82, 106, 85, 108, 86, 9, 10, 11, 161, 80, + 1, 2, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 9, 10, 11, 106, 156, 30, 8, 32, 33, + 34, 35, 36, 13, 116, 8, 153, 154, 155, 8, + 122, 158, 30, 125, 126, 116, 117, 118, 119, 120, + 121, 31, 134, 135, 156, 137, 138, 139, 140, 141, + 142, 143, 145, 146, 8, 8, 133, 149, 150, 37, + 38, 153, 154, 155, 9, 10, 11, 159, 8, 161, + 162, 8, 164, 74, 75, 76, 77, 8, 13, 80, + 0, 1, 2, 84, 158, 30, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 13, 98, 9, 10, + 11, 9, 103, 104, 105, 106, 8, 70, 109, 110, + 9, 10, 11, 8, 115, 116, 117, 118, 70, 30, + 31, 37, 38, 124, 31, 8, 127, 128, 129, 130, + 8, 30, 156, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 116, 117, 118, 119, 120, + 121, 8, 82, 8, 74, 156, 157, 158, 33, 34, + 80, 1, 2, 8, 84, 163, 82, 87, 88, 89, + 133, 91, 70, 93, 152, 95, 108, 82, 98, 158, + 8, 113, 160, 103, 104, 105, 106, 13, 108, 109, + 110, 123, 122, 113, 157, 115, 116, 117, 118, 9, + 10, 11, 156, 71, 124, 157, 122, 127, 128, 129, + 130, 37, 38, 8, 82, 160, 156, 13, 134, 156, + 30, 156, 32, 33, 34, 35, 158, 157, 148, 159, + 122, 161, 80, 1, 74, 133, 156, 157, 158, 156, + 80, 1, 2, 159, 84, 161, 82, 87, 88, 89, + 157, 91, 157, 93, 122, 95, 161, 106, 98, 108, + 100, 101, 102, 103, 104, 105, 106, 159, 116, 109, + 110, 9, 10, 11, 13, 115, 116, 117, 118, 9, + 10, 11, 160, 16, 124, 81, 122, 127, 128, 129, + 130, 159, 30, 161, 32, 33, 34, 13, 134, 156, + 30, 156, 32, 33, 153, 153, 154, 155, 70, 9, + 10, 11, 80, 80, 74, 160, 156, 157, 158, 14, + 80, 37, 38, 159, 84, 161, 152, 87, 88, 89, + 30, 91, 160, 93, 14, 95, 37, 38, 98, 16, + 100, 101, 102, 103, 104, 105, 106, 70, 82, 109, + 110, 82, 33, 34, 35, 115, 116, 117, 118, 16, + 1, 2, 10, 11, 124, 160, 85, 127, 128, 129, + 130, 9, 10, 11, 82, 11, 14, 157, 9, 10, + 11, 161, 30, 85, 53, 54, 55, 154, 57, 157, + 31, 122, 30, 161, 30, 157, 156, 157, 158, 30, + 69, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 144, 57, 161, 159, 16, + 161, 1, 2, 74, 157, 16, 152, 157, 69, 80, + 116, 161, 144, 84, 69, 70, 87, 88, 89, 16, + 91, 16, 93, 161, 95, 75, 76, 98, 30, 135, + 136, 31, 103, 104, 105, 1, 2, 31, 109, 110, + 9, 10, 11, 31, 115, 116, 50, 51, 52, 50, + 51, 52, 31, 124, 160, 75, 76, 101, 102, 111, + 112, 30, 156, 157, 31, 31, 156, 157, 156, 157, + 31, 31, 57, 38, 74, 33, 69, 80, 70, 70, + 80, 70, 89, 70, 84, 156, 157, 87, 88, 89, + 70, 91, 70, 93, 70, 95, 70, 96, 98, 71, + 77, 82, 85, 103, 104, 105, 1, 2, 74, 109, + 110, 82, 82, 97, 80, 115, 116, 85, 84, 92, + 106, 87, 88, 89, 124, 91, 90, 93, 133, 95, + 128, 94, 98, 147, 116, 97, 31, 103, 104, 105, + 1, 2, 97, 109, 110, 97, 97, 100, 144, 115, + 116, 100, 106, 128, 113, 161, 156, 157, 124, -1, + -1, 151, -1, -1, 114, -1, -1, -1, -1, -1, + 31, -1, -1, -1, 131, 131, -1, -1, -1, 74, + -1, -1, -1, -1, 132, 80, 133, 133, 133, 84, + 156, 157, 87, 88, 89, -1, 91, -1, 93, -1, + 95, 144, -1, 98, -1, 147, 147, 147, 103, 104, + 105, 1, 2, 74, 109, 110, 147, 147, 147, 80, + 115, 116, 147, 84, 151, 153, 87, 88, 89, 124, + 91, 31, 93, 152, 95, 156, 156, 98, 156, 156, + 156, 156, 103, 104, 105, 156, 156, 156, 109, 110, + 50, 51, 156, 156, 115, 116, 56, 156, 58, 156, + 156, 156, 157, 124, 156, 156, 156, 156, 156, 156, + 70, 156, 156, 156, 156, 156, 156, 156, 78, 79, + 156, 156, 159, 157, 74, 157, 86, 157, 157, 157, + 80, 157, 157, 157, 84, 156, 157, 87, 88, 89, + 157, 91, 157, 93, 157, 95, 157, 157, 98, 157, + 159, 158, 158, 103, 104, 105, 50, 51, 158, 109, + 110, 158, 56, 158, 58, 115, 116, 158, 158, 158, + 158, 158, 158, 158, 124, 135, 70, 137, 138, 139, + 140, 141, 142, 143, 78, 79, 158, 158, 158, 149, + 150, 158, 86, 158, 158, 158, 158, 158, 164, 159, + 158, 158, 158, 158, 158, 158, 156, 157, 159, 158, + 158, 163, 159, 159, 159, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, -1, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 135, 160, 137, 138, 139, 140, 141, 142, 143, + 160, 160, 160, 160, 160, 149, 150, 160, 160, 163, + -1, 162, 162, -1, 163, 159, 163, 163, 163, -1, + 163, 163, 163, 163, 163, 163, 163, 163, 163 + ); + + protected $actionBase = array( + 0, 229, 310, 390, 470, 103, 325, 325, 785, -2, + -2, 149, -2, -2, -2, 660, 765, 799, 765, 589, + 694, 870, 870, 870, 252, 404, 404, 404, 514, 177, + 177, 918, 434, 118, 295, 313, 240, 491, 491, 491, + 491, 138, 138, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, + 491, 491, 491, 491, 491, 491, 89, 206, 775, 550, + 535, 776, 777, 778, 912, 709, 913, 859, 862, 700, + 863, 864, 865, 866, 867, 858, 871, 935, 872, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 322, 592, 285, 319, 232, 44, 691, 691, 691, + 691, 691, 691, 691, 182, 182, 182, 182, 182, 182, + 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, + 182, 182, 582, 530, 530, 530, 594, 860, 658, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 926, 926, 926, 926, 926, 926, 926, + 926, 926, 926, 500, -21, -21, 492, 702, 420, 355, + 216, 549, 151, 26, 26, 331, 331, 331, 331, 331, + 46, 46, 5, 5, 5, 5, 153, 188, 188, 188, + 188, 121, 121, 121, 121, 314, 314, 394, 394, 362, + 300, 298, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 67, 656, 656, 659, 659, 522, 554, 554, + 554, 554, 679, -59, -59, 381, 462, 462, 462, 528, + 717, 854, 382, 382, 382, 382, 382, 382, 561, 561, + 561, -3, -3, -3, 692, 115, 137, 115, 137, 678, + 732, 450, 732, 338, 677, -15, 510, 812, 468, 707, + 856, 711, 857, 572, 735, 267, 529, 654, 674, 463, + 529, 529, 529, 529, 654, 610, 640, 608, 463, 529, + 463, 718, 323, 496, 89, 570, 507, 675, 779, 293, + 670, 781, 290, 373, 332, 566, 278, 435, 733, 784, + 914, 917, 385, 715, 675, 675, 675, 352, 511, 278, + -8, 605, 605, 605, 605, 156, 605, 605, 605, 605, + 251, 276, 375, 402, 780, 657, 657, 690, 869, 783, + 783, 657, 689, 657, 690, 874, 874, 874, 874, 657, + 657, 657, 657, 783, 783, 783, 688, 783, 239, 703, + 704, 704, 874, 742, 743, 657, 657, 712, 783, 783, + 783, 712, 695, 874, 701, 741, 277, 783, 874, 672, + 689, 672, 657, 701, 672, 689, 689, 672, 22, 666, + 668, 873, 875, 887, 791, 662, 685, 879, 880, 876, + 878, 811, 699, 744, 497, 669, 671, 673, 680, 719, + 682, 713, 674, 667, 667, 667, 655, 720, 655, 667, + 667, 667, 667, 667, 667, 667, 667, 868, 646, 731, + 714, 653, 745, 553, 573, 792, 664, 814, 900, 893, + 919, 920, 881, 898, 655, 916, 739, 247, 643, 882, + 813, 788, 655, 883, 655, 794, 655, 902, 820, 686, + 823, 825, 667, 910, 921, 923, 924, 925, 927, 928, + 929, 930, 684, 931, 749, 696, 894, 299, 877, 718, + 729, 705, 790, 750, 829, 328, 932, 830, 655, 655, + 795, 786, 655, 796, 751, 740, 890, 756, 895, 933, + 664, 708, 896, 655, 706, 831, 934, 328, 681, 683, + 888, 661, 757, 886, 911, 885, 803, 761, 649, 663, + 832, 833, 834, 693, 763, 891, 892, 889, 764, 805, + 665, 807, 768, 697, 835, 809, 884, 769, 848, 849, + 899, 676, 730, 710, 698, 687, 810, 850, 897, 770, + 771, 772, 853, 773, 855, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 138, 138, 138, 138, -2, + -2, -2, -2, 0, 0, -2, 0, 0, 0, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 0, 0, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 599, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 599, -21, -21, -21, -21, + 599, -21, -21, -21, -21, -21, -21, -21, 599, 599, + 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, + 599, 599, 599, 599, 599, 599, -21, 599, 599, 599, + -21, 382, -21, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 599, 0, 0, + 599, -21, 599, -21, 599, -21, -21, 599, 599, 599, + 599, 599, 599, 599, -21, -21, -21, -21, -21, -21, + 0, 561, 561, 561, 561, -21, -21, -21, -21, 382, + 382, 382, 382, 382, 382, 259, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 561, 561, -3, + -3, 382, 382, 382, 382, 382, 259, 382, 382, 463, + 689, 689, 689, 137, 137, 137, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 137, 463, + 0, 463, 0, 382, 463, 689, 463, 657, 137, 689, + 689, 463, 783, 616, 616, 616, 616, 328, 278, 0, + 0, 689, 689, 0, 0, 0, 0, 0, 689, 0, + 0, 0, 0, 0, 0, 783, 0, 0, 0, 0, + 0, 667, 247, 0, 705, 335, 0, 0, 0, 0, + 0, 0, 705, 335, 347, 347, 0, 684, 667, 667, + 667, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 328 + ); + + protected $actionDefault = array( + 3,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 544, 544, 499,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 299, 299, 299, + 32767,32767,32767, 532, 532, 532, 532, 532, 532, 532, + 532, 532, 532, 532,32767,32767,32767,32767,32767,32767, + 383,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 389, + 549,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 364, + 365, 367, 368, 298, 552, 533, 247, 390, 548, 297, + 249, 327, 503,32767,32767,32767, 329, 122, 258, 203, + 502, 125, 296, 234, 382, 384, 328, 303, 308, 309, + 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, + 320, 302, 458, 361, 360, 359, 460,32767, 459, 496, + 496, 499,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 325, 487, 486, 326, 456, 330, 457, + 333, 461, 464, 331, 332, 349, 350, 347, 348, 351, + 462, 463, 480, 481, 478, 479, 301, 352, 353, 354, + 355, 482, 483, 484, 485,32767,32767, 543, 543,32767, + 32767, 282,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 340, 341, 471, 472,32767, 238, 238, + 238, 238, 283, 238,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 335, 336, + 334, 466, 467, 465, 432,32767,32767,32767, 434,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 504,32767, + 32767,32767,32767,32767, 517, 421, 171,32767, 413,32767, + 171, 171, 171, 171,32767, 222, 224, 167,32767, 171, + 32767, 490,32767,32767,32767,32767, 522, 345,32767,32767, + 116,32767,32767,32767, 559,32767, 517,32767, 116,32767, + 32767,32767,32767, 358, 337, 338, 339,32767,32767, 521, + 515, 474, 475, 476, 477,32767, 468, 469, 470, 473, + 32767,32767,32767,32767,32767,32767,32767,32767, 429, 435, + 435,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 520, 519,32767, 414, 498, 188, + 186, 186,32767, 208, 208,32767,32767, 190, 491, 510, + 32767, 190, 173,32767, 400, 175, 498,32767,32767, 240, + 32767, 240,32767, 400, 240,32767,32767, 240,32767, 415, + 439,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 379, 380, 493, 506,32767, + 507,32767, 413, 343, 344, 346, 322,32767, 324, 369, + 370, 371, 372, 373, 374, 375, 377,32767, 419,32767, + 422,32767,32767,32767, 257,32767, 557,32767,32767, 306, + 557,32767,32767,32767, 551,32767,32767, 300,32767,32767, + 32767,32767, 253,32767, 169,32767, 541,32767, 558,32767, + 515,32767, 342,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 516,32767,32767,32767,32767, 229,32767, 452, + 32767, 116,32767,32767,32767, 189,32767,32767, 304, 248, + 32767,32767, 550,32767,32767,32767,32767,32767,32767,32767, + 32767, 114,32767, 170,32767,32767,32767, 191,32767,32767, + 515,32767,32767,32767,32767,32767,32767,32767,32767, 295, + 32767,32767,32767,32767,32767,32767,32767, 515,32767,32767, + 233,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767, 415,32767, 276,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 127, 127, 3, 127, 127, + 260, 3, 260, 127, 260, 260, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 216, 219, 208, 208, + 164, 127, 127, 268 + ); + + protected $goto = array( + 166, 140, 140, 140, 166, 187, 168, 144, 147, 141, + 142, 143, 149, 163, 163, 163, 163, 144, 144, 165, + 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, + 138, 159, 160, 161, 162, 184, 139, 185, 493, 494, + 377, 495, 499, 500, 501, 502, 503, 504, 505, 506, + 971, 164, 145, 146, 148, 171, 176, 186, 203, 253, + 256, 258, 260, 263, 264, 265, 266, 267, 268, 269, + 277, 278, 279, 280, 303, 304, 328, 329, 330, 394, + 395, 396, 542, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 150, 151, 152, + 167, 153, 169, 154, 204, 170, 155, 156, 157, 205, + 158, 136, 622, 560, 758, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 560, 560, 560, 560, 560, 560, 560, 1114, + 630, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, + 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, + 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, + 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, 1114, + 1114, 1114, 1114, 1114, 1114, 759, 519, 530, 508, 657, + 555, 1184, 350, 508, 591, 787, 1184, 889, 613, 614, + 885, 618, 619, 625, 627, 632, 634, 751, 856, 856, + 856, 856, 851, 857, 174, 892, 892, 1206, 1206, 177, + 178, 179, 401, 402, 403, 404, 173, 202, 206, 208, + 257, 259, 261, 262, 270, 271, 272, 273, 274, 275, + 281, 282, 283, 284, 305, 306, 331, 332, 333, 406, + 407, 408, 409, 175, 180, 254, 255, 181, 182, 183, + 497, 497, 497, 497, 497, 497, 818, 497, 497, 497, + 497, 497, 497, 497, 497, 497, 497, 509, 585, 862, + 601, 602, 509, 544, 545, 546, 547, 548, 549, 550, + 551, 553, 586, 338, 559, 321, 559, 559, 559, 559, + 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, + 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, + 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, + 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, + 400, 607, 536, 536, 568, 532, 537, 534, 534, 496, + 498, 524, 540, 569, 572, 583, 590, 298, 296, 296, + 296, 298, 289, 299, 611, 1210, 510, 615, 910, 948, + 375, 510, 437, 437, 437, 437, 437, 437, 594, 437, + 437, 437, 437, 437, 437, 437, 437, 437, 437, 1078, + 949, 388, 1176, 561, 1078, 899, 899, 899, 899, 378, + 899, 899, 1218, 1218, 1164, 754, 351, 352, 757, 1078, + 1078, 1078, 1078, 1078, 1078, 1070, 384, 384, 384, 606, + 1218, 878, 860, 858, 860, 656, 466, 511, 887, 882, + 754, 384, 754, 384, 969, 384, 391, 385, 587, 353, + 414, 384, 1232, 1203, 541, 1198, 1198, 1198, 567, 1095, + 386, 386, 386, 1020, 916, 514, 1030, 19, 15, 372, + 776, 916, 941, 448, 450, 633, 896, 1217, 1217, 1115, + 616, 939, 841, 554, 905, 386, 340, 1071, 1074, 1075, + 399, 1070, 1183, 914, 23, 1217, 774, 1183, 543, 603, + 389, 1220, 1072, 1175, 1072, 518, 1200, 1200, 1200, 575, + 605, 1073, 343, 522, 533, 518, 518, 773, 1090, 1089, + 13, 578, 582, 628, 3, 4, 783, 1067, 772, 514, + 1062, 1182, 784, 661, 919, 451, 866, 573, 957, 1161, + 464, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 513, 528, 0, 0, 0, 0, + 513, 0, 528, 0, 0, 0, 0, 610, 512, 515, + 439, 440, 1068, 620, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 781, 1225, 0, 0, 0, 0, + 0, 523, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 779, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 301, 301 + ); + + protected $gotoCheck = array( + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 57, 69, 15, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 128, + 9, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 16, 102, 32, 69, 32, + 32, 120, 72, 69, 32, 29, 120, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 6, 69, 69, + 69, 69, 69, 69, 27, 77, 77, 77, 77, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 119, 119, 119, 119, 119, 119, 50, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 67, 33, + 67, 67, 119, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 127, 57, 127, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 51, 51, 51, 51, 51, 51, 110, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 5, 5, 5, + 5, 5, 5, 5, 63, 142, 124, 63, 84, 98, + 63, 124, 57, 57, 57, 57, 57, 57, 129, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, + 98, 12, 82, 12, 57, 57, 57, 57, 57, 46, + 57, 57, 144, 144, 133, 11, 72, 72, 14, 57, + 57, 57, 57, 57, 57, 82, 13, 13, 13, 49, + 144, 14, 14, 14, 14, 14, 57, 14, 14, 14, + 11, 13, 11, 13, 102, 13, 48, 11, 70, 70, + 70, 13, 13, 140, 2, 9, 9, 9, 2, 34, + 125, 125, 125, 103, 13, 13, 34, 34, 34, 34, + 25, 13, 8, 8, 8, 8, 79, 143, 143, 8, + 8, 8, 9, 34, 81, 125, 18, 82, 82, 82, + 125, 82, 121, 85, 34, 143, 24, 121, 47, 34, + 17, 143, 82, 82, 82, 47, 121, 121, 121, 40, + 40, 82, 58, 58, 58, 47, 47, 23, 126, 126, + 58, 62, 62, 62, 30, 30, 23, 116, 23, 13, + 114, 121, 26, 74, 86, 65, 71, 66, 100, 132, + 109, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, + 9, -1, 9, -1, -1, -1, -1, 13, 9, 9, + 9, 9, 13, 13, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, + -1, 102, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 5, 5 + ); + + protected $gotoBase = array( + 0, 0, -173, 0, 0, 353, 216, 0, 477, 149, + 0, 110, 71, 117, 426, 112, 203, 170, 181, 0, + 0, 0, 0, 168, 164, 143, 121, 27, 0, 205, + -127, 0, -429, 279, 51, 0, 0, 0, 0, 0, + 481, 0, 0, -24, 0, 0, 379, 484, 163, 153, + 268, 75, 0, 0, 0, 0, 0, 107, 161, 0, + 0, 0, 222, -77, 0, 104, 96, -344, 0, -94, + 135, 123, -232, 0, 169, 0, 0, -50, 0, 173, + 0, 180, 64, 0, 360, 139, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, + 124, 0, 165, 166, 0, 0, 0, 0, 0, 87, + 340, 259, 0, 0, 120, 0, 177, 0, 0, -5, + -91, 200, 0, 0, 84, 154, 211, -21, -48, 188, + 0, 0, 93, 213, 0, 0, 0, 0, 0, 0, + 175, 0, 358, 167, 102, 0, 0 + ); + + protected $gotoDefault = array( + -32768, 468, 665, 2, 666, 836, 741, 749, 598, 482, + 631, 581, 380, 1194, 793, 794, 795, 381, 368, 766, + 379, 410, 405, 782, 775, 777, 785, 172, 411, 788, + 1, 790, 517, 826, 1021, 365, 798, 366, 589, 800, + 526, 802, 803, 137, 382, 383, 527, 483, 390, 576, + 817, 276, 387, 819, 367, 820, 829, 371, 465, 455, + 460, 529, 556, 609, 432, 447, 570, 564, 535, 1087, + 565, 865, 349, 873, 662, 881, 884, 484, 557, 895, + 452, 903, 1100, 397, 909, 915, 920, 291, 923, 417, + 412, 584, 928, 929, 5, 933, 623, 624, 8, 312, + 956, 599, 970, 420, 1040, 1042, 485, 486, 521, 459, + 507, 525, 487, 1063, 441, 413, 1066, 433, 488, 489, + 434, 435, 1084, 355, 1169, 354, 449, 320, 1156, 579, + 1119, 456, 1209, 1165, 348, 490, 491, 376, 1188, 392, + 1204, 438, 1211, 1219, 344, 539, 566 + ); + + protected $ruleToNonTerminal = array( + 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, + 12, 12, 13, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 18, 18, 19, 19, 21, 21, + 17, 17, 22, 22, 23, 23, 24, 24, 25, 25, + 20, 20, 26, 28, 28, 29, 30, 30, 32, 31, + 31, 31, 31, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 14, 14, 54, 54, 56, 55, 55, 48, + 48, 58, 58, 59, 59, 60, 60, 61, 61, 15, + 16, 16, 16, 64, 64, 64, 65, 65, 68, 68, + 66, 66, 70, 70, 41, 41, 50, 50, 53, 53, + 53, 52, 52, 71, 42, 42, 42, 42, 72, 72, + 73, 73, 74, 74, 39, 39, 35, 35, 75, 37, + 37, 76, 36, 36, 38, 38, 49, 49, 49, 62, + 62, 78, 78, 79, 79, 81, 81, 81, 80, 80, + 63, 63, 82, 82, 82, 83, 83, 84, 84, 84, + 44, 44, 85, 85, 85, 45, 45, 86, 86, 87, + 87, 67, 88, 88, 88, 88, 93, 93, 94, 94, + 95, 95, 95, 95, 95, 96, 97, 97, 92, 92, + 89, 89, 91, 91, 99, 99, 98, 98, 98, 98, + 98, 98, 90, 90, 101, 100, 100, 46, 46, 40, + 40, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 34, 34, 47, + 47, 106, 106, 107, 107, 107, 107, 113, 102, 102, + 109, 109, 115, 115, 116, 117, 118, 118, 118, 118, + 118, 118, 118, 69, 69, 57, 57, 57, 57, 103, + 103, 122, 122, 119, 119, 123, 123, 123, 123, 104, + 104, 104, 108, 108, 108, 114, 114, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 27, 27, 27, 27, 27, 27, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 112, 112, 105, 105, 105, 105, 129, 129, 132, 132, + 131, 131, 133, 133, 51, 51, 51, 51, 135, 135, + 134, 134, 134, 134, 134, 136, 136, 121, 121, 124, + 124, 120, 120, 138, 137, 137, 137, 137, 125, 125, + 125, 125, 111, 111, 126, 126, 126, 126, 77, 139, + 139, 140, 140, 140, 110, 110, 141, 141, 142, 142, + 142, 142, 142, 127, 127, 127, 127, 144, 145, 143, + 143, 143, 143, 143, 143, 143, 146, 146, 146 + ); + + protected $ruleToLength = array( + 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 5, 4, + 3, 4, 1, 3, 1, 1, 8, 7, 3, 1, + 3, 1, 3, 1, 1, 3, 1, 3, 1, 2, + 3, 1, 3, 3, 1, 3, 2, 0, 1, 1, + 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, + 2, 3, 2, 3, 2, 3, 3, 3, 3, 1, + 2, 2, 5, 7, 9, 5, 6, 3, 3, 2, + 2, 1, 1, 1, 0, 2, 8, 0, 4, 1, + 3, 0, 1, 0, 1, 0, 1, 1, 1, 10, + 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, + 0, 2, 1, 3, 1, 4, 1, 4, 1, 1, + 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, + 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, + 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, + 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, + 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, + 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, + 0, 1, 3, 3, 9, 3, 1, 3, 0, 2, + 4, 5, 4, 4, 4, 3, 1, 1, 1, 3, + 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 3, 3, 1, 0, + 1, 1, 3, 3, 4, 4, 1, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 1, 3, 5, + 4, 3, 4, 4, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 1, 3, 2, 1, 2, 10, 11, 3, 3, 2, + 4, 4, 3, 4, 4, 4, 4, 7, 3, 2, + 0, 4, 1, 3, 2, 1, 2, 2, 4, 6, + 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 4, 4, 0, + 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 1, 3, 1, 4, 3, 1, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, + 1, 3, 1, 1, 3, 3, 0, 2, 0, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 6, 4, + 3, 4, 2, 4, 4, 1, 3, 1, 2, 1, + 1, 4, 1, 1, 3, 6, 4, 4, 4, 4, + 1, 4, 0, 1, 1, 3, 1, 1, 4, 3, + 1, 1, 1, 0, 0, 2, 3, 1, 3, 1, + 4, 2, 2, 2, 2, 1, 2, 1, 1, 1, + 4, 3, 3, 3, 6, 3, 1, 1, 1 + ); + + protected function initReduceCallbacks() { + $this->reduceCallbacks = [ + 0 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 1 => function ($stackPos) { + $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); + }, + 2 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 3 => function ($stackPos) { + $this->semValue = array(); + }, + 4 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 5 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 6 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 7 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 8 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 9 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 10 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 11 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 12 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 13 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 14 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 15 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 16 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 17 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 18 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 19 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 20 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 21 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 22 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 23 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 24 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 25 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 26 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 27 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 28 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 29 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 30 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 31 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 32 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 33 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 34 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 35 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 36 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 37 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 38 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 39 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 40 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 41 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 42 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 43 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 44 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 45 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 46 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 47 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 48 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 49 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 50 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 51 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 52 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 53 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 54 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 55 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 56 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 57 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 58 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 59 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 60 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 61 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 62 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 63 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 64 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 65 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 66 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 67 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 68 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 69 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 70 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 71 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 72 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 73 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 74 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 75 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 76 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 77 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 78 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 79 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 80 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 81 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 82 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 83 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 84 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 85 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 86 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 87 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 88 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 89 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 90 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 91 => function ($stackPos) { + $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 92 => function ($stackPos) { + $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 93 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 94 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 95 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 96 => function ($stackPos) { + $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 97 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($this->semValue); + }, + 98 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 99 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 100 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 101 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 102 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 103 => function ($stackPos) { + $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 104 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_FUNCTION; + }, + 105 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_CONSTANT; + }, + 106 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-2)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 107 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-2)], $this->semStack[$stackPos-(7-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 108 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 109 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 110 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 111 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 112 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 113 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 114 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 115 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 116 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 117 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 118 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; + }, + 119 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; + }, + 120 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 121 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 122 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 123 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 124 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 125 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 126 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 127 => function ($stackPos) { + $this->semValue = array(); + }, + 128 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 129 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 130 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 131 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 132 => function ($stackPos) { + throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 133 => function ($stackPos) { + + if ($this->semStack[$stackPos-(3-2)]) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; + } else { + $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if (null === $this->semValue) { $this->semValue = array(); } + } + + }, + 134 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(5-2)], ['stmts' => is_array($this->semStack[$stackPos-(5-3)]) ? $this->semStack[$stackPos-(5-3)] : array($this->semStack[$stackPos-(5-3)]), 'elseifs' => $this->semStack[$stackPos-(5-4)], 'else' => $this->semStack[$stackPos-(5-5)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 135 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(8-2)], ['stmts' => $this->semStack[$stackPos-(8-4)], 'elseifs' => $this->semStack[$stackPos-(8-5)], 'else' => $this->semStack[$stackPos-(8-6)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 136 => function ($stackPos) { + $this->semValue = new Stmt\While_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 137 => function ($stackPos) { + $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(5-4)], is_array($this->semStack[$stackPos-(5-2)]) ? $this->semStack[$stackPos-(5-2)] : array($this->semStack[$stackPos-(5-2)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 138 => function ($stackPos) { + $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 139 => function ($stackPos) { + $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 140 => function ($stackPos) { + $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 141 => function ($stackPos) { + $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 142 => function ($stackPos) { + $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 143 => function ($stackPos) { + $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 144 => function ($stackPos) { + $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 145 => function ($stackPos) { + $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 146 => function ($stackPos) { + $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 147 => function ($stackPos) { + $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 148 => function ($stackPos) { + $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 149 => function ($stackPos) { + $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 150 => function ($stackPos) { + $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 151 => function ($stackPos) { + $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 152 => function ($stackPos) { + $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 153 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 154 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 155 => function ($stackPos) { + $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 156 => function ($stackPos) { + $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); + }, + 157 => function ($stackPos) { + $this->semValue = new Stmt\Throw_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 158 => function ($stackPos) { + $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 159 => function ($stackPos) { + $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 160 => function ($stackPos) { + $this->semValue = new Stmt\Expression($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 161 => function ($stackPos) { + $this->semValue = array(); /* means: no statement */ + }, + 162 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 163 => function ($stackPos) { + $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ + }, + 164 => function ($stackPos) { + $this->semValue = array(); + }, + 165 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 166 => function ($stackPos) { + $this->semValue = new Stmt\Catch_(array($this->semStack[$stackPos-(8-3)]), $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 167 => function ($stackPos) { + $this->semValue = null; + }, + 168 => function ($stackPos) { + $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 169 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 170 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 171 => function ($stackPos) { + $this->semValue = false; + }, + 172 => function ($stackPos) { + $this->semValue = true; + }, + 173 => function ($stackPos) { + $this->semValue = false; + }, + 174 => function ($stackPos) { + $this->semValue = true; + }, + 175 => function ($stackPos) { + $this->semValue = false; + }, + 176 => function ($stackPos) { + $this->semValue = true; + }, + 177 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 178 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 179 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(10-3)], ['byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-5)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 180 => function ($stackPos) { + $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $stackPos-(7-2)); + }, + 181 => function ($stackPos) { + $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(6-2)], ['extends' => $this->semStack[$stackPos-(6-3)], 'stmts' => $this->semStack[$stackPos-(6-5)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + $this->checkInterface($this->semValue, $stackPos-(6-2)); + }, + 182 => function ($stackPos) { + $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(5-2)], ['stmts' => $this->semStack[$stackPos-(5-4)]], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 183 => function ($stackPos) { + $this->semValue = 0; + }, + 184 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 185 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 186 => function ($stackPos) { + $this->semValue = null; + }, + 187 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 188 => function ($stackPos) { + $this->semValue = array(); + }, + 189 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 190 => function ($stackPos) { + $this->semValue = array(); + }, + 191 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 192 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 193 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 194 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 195 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 196 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 197 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 198 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 199 => function ($stackPos) { + $this->semValue = null; + }, + 200 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 201 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 202 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 203 => function ($stackPos) { + $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 204 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 205 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 206 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 207 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(5-3)]; + }, + 208 => function ($stackPos) { + $this->semValue = array(); + }, + 209 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 210 => function ($stackPos) { + $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 211 => function ($stackPos) { + $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 212 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 213 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 214 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 215 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 216 => function ($stackPos) { + $this->semValue = array(); + }, + 217 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 218 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(3-2)], is_array($this->semStack[$stackPos-(3-3)]) ? $this->semStack[$stackPos-(3-3)] : array($this->semStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 219 => function ($stackPos) { + $this->semValue = array(); + }, + 220 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 221 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 222 => function ($stackPos) { + $this->semValue = null; + }, + 223 => function ($stackPos) { + $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 224 => function ($stackPos) { + $this->semValue = null; + }, + 225 => function ($stackPos) { + $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 226 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 227 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-2)], true); + }, + 228 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 229 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 230 => function ($stackPos) { + $this->semValue = array(); + }, + 231 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 232 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 233 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(4-4)], null, $this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); + }, + 234 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-3)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); + }, + 235 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 236 => function ($stackPos) { + $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 237 => function ($stackPos) { + $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 238 => function ($stackPos) { + $this->semValue = null; + }, + 239 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 240 => function ($stackPos) { + $this->semValue = null; + }, + 241 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 242 => function ($stackPos) { + $this->semValue = array(); + }, + 243 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 244 => function ($stackPos) { + $this->semValue = array(new Node\Arg($this->semStack[$stackPos-(3-2)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes)); + }, + 245 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 246 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 247 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 248 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 249 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 250 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 251 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 252 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 253 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 254 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 255 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 256 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 257 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 258 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 259 => function ($stackPos) { + if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } else { $this->semValue = $this->semStack[$stackPos-(2-1)]; } + }, + 260 => function ($stackPos) { + $this->semValue = array(); + }, + 261 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 262 => function ($stackPos) { + $this->semValue = new Stmt\Property($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $stackPos-(3-1)); + }, + 263 => function ($stackPos) { + $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(3-2)], 0, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 264 => function ($stackPos) { + $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(9-4)], ['type' => $this->semStack[$stackPos-(9-1)], 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + $this->checkClassMethod($this->semValue, $stackPos-(9-1)); + }, + 265 => function ($stackPos) { + $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 266 => function ($stackPos) { + $this->semValue = array(); + }, + 267 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 268 => function ($stackPos) { + $this->semValue = array(); + }, + 269 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 270 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 271 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 272 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 273 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 274 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 275 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 276 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 277 => function ($stackPos) { + $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); + }, + 278 => function ($stackPos) { + $this->semValue = null; + }, + 279 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 280 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 281 => function ($stackPos) { + $this->semValue = 0; + }, + 282 => function ($stackPos) { + $this->semValue = 0; + }, + 283 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 284 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 285 => function ($stackPos) { + $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 286 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 287 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 288 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 289 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + }, + 290 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 291 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 292 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 293 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 294 => function ($stackPos) { + $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 295 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 296 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 297 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 298 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 299 => function ($stackPos) { + $this->semValue = array(); + }, + 300 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 301 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 302 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 303 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 304 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 305 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 306 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 307 => function ($stackPos) { + $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 308 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 309 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 310 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 311 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 312 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 313 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 314 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 315 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 316 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 317 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 318 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 319 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 320 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 321 => function ($stackPos) { + $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 322 => function ($stackPos) { + $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 323 => function ($stackPos) { + $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 324 => function ($stackPos) { + $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 325 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 326 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 327 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 328 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 329 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 330 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 331 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 332 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 333 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 334 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 335 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 336 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 337 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 338 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 339 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 340 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 341 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 342 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 343 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 344 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 345 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 346 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 347 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 348 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 349 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 350 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 351 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 352 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 353 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 354 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 355 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 356 => function ($stackPos) { + $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 357 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 358 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 359 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 360 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 361 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 362 => function ($stackPos) { + $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 363 => function ($stackPos) { + $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 364 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 365 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 366 => function ($stackPos) { + $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 367 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 368 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 369 => function ($stackPos) { + $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 370 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); + $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); + }, + 371 => function ($stackPos) { + $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 372 => function ($stackPos) { + $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 373 => function ($stackPos) { + $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 374 => function ($stackPos) { + $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 375 => function ($stackPos) { + $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 376 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); + }, + 377 => function ($stackPos) { + $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 378 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 379 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 380 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 381 => function ($stackPos) { + $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 382 => function ($stackPos) { + $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 383 => function ($stackPos) { + $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 384 => function ($stackPos) { + $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 385 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(10-2)], 'params' => $this->semStack[$stackPos-(10-4)], 'uses' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-7)], 'stmts' => $this->semStack[$stackPos-(10-9)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 386 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(11-3)], 'params' => $this->semStack[$stackPos-(11-5)], 'uses' => $this->semStack[$stackPos-(11-7)], 'returnType' => $this->semStack[$stackPos-(11-8)], 'stmts' => $this->semStack[$stackPos-(11-10)]], $this->startAttributeStack[$stackPos-(11-1)] + $this->endAttributes); + }, + 387 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 388 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 389 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 390 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 391 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); + }, + 392 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); + }, + 393 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 394 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch(Scalar\String_::fromString($this->semStack[$stackPos-(4-1)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes), $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 395 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 396 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 397 => function ($stackPos) { + $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes), $this->semStack[$stackPos-(7-2)]); + $this->checkClass($this->semValue[0], -1); + }, + 398 => function ($stackPos) { + $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 399 => function ($stackPos) { + list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 400 => function ($stackPos) { + $this->semValue = array(); + }, + 401 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 402 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 403 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 404 => function ($stackPos) { + $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 405 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 406 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 407 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 408 => function ($stackPos) { + $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 409 => function ($stackPos) { + $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 410 => function ($stackPos) { + $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 411 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 412 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 413 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 414 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 415 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 416 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 417 => function ($stackPos) { + $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 418 => function ($stackPos) { + $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 419 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 420 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 421 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 422 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 423 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 424 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 425 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 426 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 427 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 428 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 429 => function ($stackPos) { + $this->semValue = null; + }, + 430 => function ($stackPos) { + $this->semValue = null; + }, + 431 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 432 => function ($stackPos) { + $this->semValue = array(); + }, + 433 => function ($stackPos) { + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`', false), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); + }, + 434 => function ($stackPos) { + foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 435 => function ($stackPos) { + $this->semValue = array(); + }, + 436 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 437 => function ($stackPos) { + $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, true); + }, + 438 => function ($stackPos) { + $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 439 => function ($stackPos) { + $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes, false); + }, + 440 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 441 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 442 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 443 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 444 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 445 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 446 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 447 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 448 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], false); + }, + 449 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], false); + }, + 450 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 451 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 452 => function ($stackPos) { + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 453 => function ($stackPos) { + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 454 => function ($stackPos) { + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 455 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 456 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 457 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 458 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 459 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 460 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 461 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 462 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 463 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 464 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 465 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 466 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 467 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 468 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 469 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 470 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 471 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 472 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 473 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 474 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 475 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 476 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 477 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 478 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 479 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 480 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 481 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 482 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 483 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 484 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 485 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 486 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 487 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 488 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 489 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 490 => function ($stackPos) { + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 491 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 492 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 493 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 494 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); + }, + 495 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); + }, + 496 => function ($stackPos) { + $this->semValue = array(); + }, + 497 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 498 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 499 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 500 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 501 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 502 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 503 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 504 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 505 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 506 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 507 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 508 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 509 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 510 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 511 => function ($stackPos) { + $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 512 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 513 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 514 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 515 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 516 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 517 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 518 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 519 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 520 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 521 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 522 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 523 => function ($stackPos) { + $var = substr($this->semStack[$stackPos-(1-1)], 1); $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; + }, + 524 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 525 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 526 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 527 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 528 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 529 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 530 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 531 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 532 => function ($stackPos) { + $this->semValue = null; + }, + 533 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 534 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 535 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 536 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 537 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 538 => function ($stackPos) { + $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 539 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 540 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 541 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 542 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 543 => function ($stackPos) { + $this->semValue = null; + }, + 544 => function ($stackPos) { + $this->semValue = array(); + }, + 545 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 546 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 547 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 548 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 549 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 550 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 551 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 552 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true); + }, + 553 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 554 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 555 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 556 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); + }, + 557 => function ($stackPos) { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 558 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 559 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 560 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 561 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 562 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 563 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 564 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 565 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 566 => function ($stackPos) { + $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 567 => function ($stackPos) { + $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 568 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php new file mode 100644 index 000000000..d41bb8369 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php @@ -0,0 +1,2899 @@ +'", + "T_IS_GREATER_OR_EQUAL", + "T_SL", + "T_SR", + "'+'", + "'-'", + "'.'", + "'*'", + "'/'", + "'%'", + "'!'", + "T_INSTANCEOF", + "'~'", + "T_INC", + "T_DEC", + "T_INT_CAST", + "T_DOUBLE_CAST", + "T_STRING_CAST", + "T_ARRAY_CAST", + "T_OBJECT_CAST", + "T_BOOL_CAST", + "T_UNSET_CAST", + "'@'", + "T_POW", + "'['", + "T_NEW", + "T_CLONE", + "T_EXIT", + "T_IF", + "T_ELSEIF", + "T_ELSE", + "T_ENDIF", + "T_LNUMBER", + "T_DNUMBER", + "T_STRING", + "T_STRING_VARNAME", + "T_VARIABLE", + "T_NUM_STRING", + "T_INLINE_HTML", + "T_ENCAPSED_AND_WHITESPACE", + "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", + "T_DO", + "T_WHILE", + "T_ENDWHILE", + "T_FOR", + "T_ENDFOR", + "T_FOREACH", + "T_ENDFOREACH", + "T_DECLARE", + "T_ENDDECLARE", + "T_AS", + "T_SWITCH", + "T_MATCH", + "T_ENDSWITCH", + "T_CASE", + "T_DEFAULT", + "T_BREAK", + "T_CONTINUE", + "T_GOTO", + "T_FUNCTION", + "T_FN", + "T_CONST", + "T_RETURN", + "T_TRY", + "T_CATCH", + "T_FINALLY", + "T_USE", + "T_INSTEADOF", + "T_GLOBAL", + "T_STATIC", + "T_ABSTRACT", + "T_FINAL", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_READONLY", + "T_VAR", + "T_UNSET", + "T_ISSET", + "T_EMPTY", + "T_HALT_COMPILER", + "T_CLASS", + "T_TRAIT", + "T_INTERFACE", + "T_ENUM", + "T_EXTENDS", + "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", + "T_NULLSAFE_OBJECT_OPERATOR", + "T_LIST", + "T_ARRAY", + "T_CALLABLE", + "T_CLASS_C", + "T_TRAIT_C", + "T_METHOD_C", + "T_FUNC_C", + "T_LINE", + "T_FILE", + "T_START_HEREDOC", + "T_END_HEREDOC", + "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", + "T_PAAMAYIM_NEKUDOTAYIM", + "T_NAMESPACE", + "T_NS_C", + "T_DIR", + "T_NS_SEPARATOR", + "T_ELLIPSIS", + "T_NAME_FULLY_QUALIFIED", + "T_NAME_QUALIFIED", + "T_NAME_RELATIVE", + "T_ATTRIBUTE", + "';'", + "']'", + "'{'", + "'}'", + "'('", + "')'", + "'`'", + "'\"'", + "'$'" + ); + + protected $tokenToSymbol = array( + 0, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 56, 166, 168, 167, 55, 168, 168, + 163, 164, 53, 50, 8, 51, 52, 54, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 31, 159, + 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 70, 168, 160, 36, 168, 165, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 161, 35, 162, 58, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, + 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, + 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 69, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158 + ); + + protected $action = array( + 133, 134, 135, 580, 136, 137, 0, 749, 750, 751, + 138, 38, 327,-32766,-32766,-32766,-32766,-32766,-32766,-32767, + -32767,-32767,-32767, 102, 103, 104, 105, 106, 1110, 1111, + 1112, 1109, 1108, 1107, 1113, 743, 742,-32766, 1233,-32766, + -32766,-32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767, + -32767, 2, 107, 108, 109, 752, 274, 381, 380,-32766, + -32766,-32766,-32766, 104, 105, 106, 1025, 423, 110, 265, + 139, 402, 756, 757, 758, 759, 467, 468, 429, 939, + 291,-32766, 287,-32766,-32766, 760, 761, 762, 763, 764, + 765, 766, 767, 768, 769, 770, 790, 581, 791, 792, + 793, 794, 782, 783, 344, 345, 785, 786, 771, 772, + 773, 775, 776, 777, 355, 817, 818, 819, 820, 821, + 582, 778, 779, 583, 584, 811, 802, 800, 801, 814, + 797, 798, 688, -545, 585, 586, 796, 587, 588, 589, + 590, 591, 592, -328, -593, -367, 1235, -367, 799, 593, + 594, -593, 140,-32766,-32766,-32766, 133, 134, 135, 580, + 136, 137, 1058, 749, 750, 751, 138, 38, 689, 1021, + 1020, 1019, 1022, 390,-32766, 7,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32766,-32766, 379, 380, 1034, 690, + 691, 743, 742,-32766,-32766,-32766, 423, -545, -545, -590, + -32766,-32766,-32766, 1033,-32766, 127, -590, 1237, 1236, 1238, + 1319, 752, -545, 290,-32766, 283,-32766,-32766,-32766,-32766, + -32766, 1237, 1236, 1238, -545, 265, 139, 402, 756, 757, + 758, 759, 16, 482, 429, 459, 460, 461, 298, 723, + 35, 760, 761, 762, 763, 764, 765, 766, 767, 768, + 769, 770, 790, 581, 791, 792, 793, 794, 782, 783, + 344, 345, 785, 786, 771, 772, 773, 775, 776, 777, + 355, 817, 818, 819, 820, 821, 582, 778, 779, 583, + 584, 811, 802, 800, 801, 814, 797, 798, 129, 825, + 585, 586, 796, 587, 588, 589, 590, 591, 592, -328, + 83, 84, 85, -593, 799, 593, 594, -593, 149, 774, + 744, 745, 746, 747, 748, 825, 749, 750, 751, 787, + 788, 37, 145, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 291, 274, 836, + 254, 1110, 1111, 1112, 1109, 1108, 1107, 1113, -590, 861, + 110, 862, -590, 483, 752,-32766,-32766,-32766,-32766,-32766, + 142, 604, 1086, 743, 742, 1263, 326, 988, 753, 754, + 755, 756, 757, 758, 759, 309,-32766, 823,-32766,-32766, + -32766,-32766, 242, 554, 760, 761, 762, 763, 764, 765, + 766, 767, 768, 769, 770, 790, 813, 791, 792, 793, + 794, 782, 783, 784, 812, 785, 786, 771, 772, 773, + 775, 776, 777, 816, 817, 818, 819, 820, 821, 822, + 778, 779, 780, 781, 811, 802, 800, 801, 814, 797, + 798, 311, 941, 789, 795, 796, 803, 804, 806, 805, + 807, 808, 323, 610, 1275, 1034, 834, 799, 810, 809, + 50, 51, 52, 513, 53, 54, 861, 241, 862, 919, + 55, 56, -111, 57,-32766,-32766,-32766, -111, 827, -111, + 290, 1303, 1348, 356, 305, 1349, 339, -111, -111, -111, + -111, -111, -111, -111, -111,-32766, -194,-32766,-32766,-32766, + -193, 957, 958, 830, -86, 989, 959, 835, 58, 59, + 340, 429, 953, -544, 60, 833, 61, 247, 248, 62, + 63, 64, 65, 66, 67, 68, 69, 1242, 28, 267, + 70, 445, 514, -342,-32766, 141, 1269, 1270, 515, 919, + 834, 326, -272, 919, 1267, 42, 25, 516, 941, 517, + 14, 518, 909, 519, 829, 369, 520, 521, 373, 710, + 1034, 44, 45, 446, 376, 375, 388, 46, 522, 713, + -86, 441, 1102, 367, 338, -543, 442, -544, -544, 831, + 1228, 443, 524, 525, 526, 290, 1237, 1236, 1238, 361, + 1031, 444, -544, 1088, 527, 528, 840, 1256, 1257, 1258, + 1259, 1253, 1254, 297, -544, 151, -550, -584, 834, 1260, + 1255, -584, 1034, 1237, 1236, 1238, 298, -154, -154, -154, + 152, 71, 909, 321, 322, 326, 909, 921, 1031, 708, + 834, 154, -154, 1338, -154, 155, -154, 283, -154, -543, + -543, 82, 1233, 1087, 1323, 735, 156, 326, 374, 158, + 1034, 1322, -194, -79, -543, -88, -193, 743, 742, 957, + 958, 654, 26,-32766, 523, -51, -543, 33, -549, 895, + 953, -111, -111, -111, 32, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, -59, 75, + 28, 673, 674, 326, -58, 36, 250, 921, 124, 708, + 125, 921, 834, 708, -154, 130, 1267, 131,-32766, -547, + 144, -542, 150, 406, 1235, 377, 378, 1147, 1149, 382, + 383,-32766,-32766,-32766, -85,-32766, 1057,-32766, -542,-32766, + 645, 646,-32766, 159, 160, 161, 1233,-32766,-32766,-32766, + 162, -79, 1228,-32766,-32766, 743, 742, 163, -302,-32766, + 420, -75, -4, 919, -73, 287, 527, 528,-32766, 1256, + 1257, 1258, 1259, 1253, 1254, -72, -71, -70, -69, -68, + -67, 1260, 1255, -547, -547, -542, -542, 743, 742, -66, + -47, -18,-32766, 73, 148, 919, 322, 326, 1235, 273, + -542, 284, -542, -542, 724,-32766,-32766,-32766, 727,-32766, + -547,-32766, -542,-32766, 918, 147,-32766, -542, 288, 289, + -298,-32766,-32766,-32766,-32766, 714, 279,-32766,-32766, -542, + 1235, 280, 285,-32766, 420, 48, 286,-32766,-32766,-32766, + 332,-32766,-32766,-32766, 292,-32766, 909, 293,-32766, 935, + 274, 1031, 919,-32766,-32766,-32766, 110, 683, 132,-32766, + -32766, 834, 146,-32766, 560,-32766, 420, 660, 374, 825, + 436, 1350, 74, 1034,-32766, 296, 655, 1117, 909, 957, + 958, 306, 715, 699, 523, 556, 303, 13, 310, 853, + 953, -111, -111, -111, 701, 464, 493, 954, 283, 299, + 300,-32766, 49, 676, 919, 304, 661, 1235, 677, 937, + 1274,-32766, 10, 1264,-32766,-32766,-32766, 643,-32766, 919, + -32766, 921,-32766, 708, -4,-32766, 126, 34, 919, 566, + -32766,-32766,-32766,-32766, 0, 909,-32766,-32766, 0, 1235, + 919, 0,-32766, 420, 0, 0,-32766,-32766,-32766, 718, + -32766,-32766,-32766, 921,-32766, 708, 1034,-32766, 725, 1276, + 0, 488,-32766,-32766,-32766,-32766, 301, 302,-32766,-32766, + -507, 1235, 572, -497,-32766, 420, 608, 8,-32766,-32766, + -32766, 372,-32766,-32766,-32766, 17,-32766, 909, 371,-32766, + 833, 298, 320, 128,-32766,-32766,-32766, 40, 370, 41, + -32766,-32766, 909, -250, -250, -250,-32766, 420, 732, 374, + 974, 909, 708, 733, 900,-32766, 998, 975, 405, 982, + 957, 958, 972, 909, 983, 523, 898, 970, 1091, 1094, + 895, 953, -111, -111, -111, 28, 1095, 1092, 1093, -249, + -249, -249, 1242, 1099, 709, 374, 845, 834, 1289, 1307, + 1341, 1267, 648, 1268, 712, 716, 957, 958, 717, 1242, + 719, 523, 921, 720, 708, -250, 895, 953, -111, -111, + -111, 721, -16, 722, 726, 711, -511, 921, 409, 708, + -578, 1233, 729, 896, 1345, 1347, 921, 1228, 708, -577, + 856, 855, 947, 990, 1346, 946, 944, 945, 921, 948, + 708, -249, 528, 1219, 1256, 1257, 1258, 1259, 1253, 1254, + 928, 938, 926, 980, 981, 632, 1260, 1255, 1344, 1301, + -32766, 1290, 1308, 834, 1317, -275, 1235, -576, 73, -550, + -549, 322, 326,-32766,-32766,-32766, -548,-32766, -491,-32766, + 834,-32766, 1, 29,-32766, 30, 39, 43, 47,-32766, + -32766,-32766, 72, 76, 77,-32766,-32766, 1233, -111, -111, + 78,-32766, 420, -111, 79, 80, 81, 143, 153, -111, + -32766, 157, 246, 328, 1233, -111, -111, 356,-32766, 357, + -111, 358, 359, 360, 361, 362, -111, 363, 364, 365, + 366, 368, 437, 0, -273,-32766, -272, 19, 20, 298, + 21, 22, 24, 404, 75, 1204, 484, 485, 326, 492, + 0, 495, 496, 497, 498, 502, 298, 503, 504, 511, + 694, 75, 0, 1246, 1187, 326, 1265, 1060, 1059, 1040, + 1223, 1036, -277, -103, 18, 23, 27, 295, 403, 601, + 605, 634, 700, 1191, 1241, 1188, 1320, 0, 0, 0, + 326 + ); + + protected $actionCheck = array( + 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, + 12, 13, 70, 9, 10, 11, 9, 10, 11, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 116, 117, + 118, 119, 120, 121, 122, 37, 38, 30, 116, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 8, 53, 54, 55, 57, 57, 106, 107, 137, + 9, 10, 11, 50, 51, 52, 1, 116, 69, 71, + 72, 73, 74, 75, 76, 77, 134, 135, 80, 1, + 30, 30, 30, 32, 33, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 80, 70, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 8, 1, 106, 80, 108, 150, 151, + 152, 8, 154, 9, 10, 11, 2, 3, 4, 5, + 6, 7, 164, 9, 10, 11, 12, 13, 116, 119, + 120, 121, 122, 106, 30, 108, 32, 33, 34, 35, + 36, 37, 38, 9, 10, 11, 106, 107, 138, 137, + 138, 37, 38, 9, 10, 11, 116, 134, 135, 1, + 9, 10, 11, 137, 30, 14, 8, 155, 156, 157, + 1, 57, 149, 163, 30, 163, 32, 33, 34, 35, + 36, 155, 156, 157, 161, 71, 72, 73, 74, 75, + 76, 77, 8, 31, 80, 129, 130, 131, 158, 161, + 8, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 8, 80, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 164, + 9, 10, 11, 160, 150, 151, 152, 164, 154, 2, + 3, 4, 5, 6, 7, 80, 9, 10, 11, 12, + 13, 30, 8, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 30, 57, 1, + 8, 116, 117, 118, 119, 120, 121, 122, 160, 106, + 69, 108, 164, 161, 57, 9, 10, 11, 9, 10, + 161, 1, 1, 37, 38, 1, 167, 31, 71, 72, + 73, 74, 75, 76, 77, 8, 30, 80, 32, 33, + 34, 35, 14, 85, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 8, 122, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 8, 51, 146, 138, 82, 150, 151, 152, + 2, 3, 4, 5, 6, 7, 106, 97, 108, 1, + 12, 13, 101, 15, 9, 10, 11, 106, 80, 108, + 163, 1, 80, 163, 113, 83, 8, 116, 117, 118, + 119, 120, 121, 122, 123, 30, 8, 32, 33, 34, + 8, 117, 118, 80, 31, 159, 122, 159, 50, 51, + 8, 80, 128, 70, 56, 155, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, + 72, 73, 74, 162, 9, 161, 78, 79, 80, 1, + 82, 167, 164, 1, 86, 87, 88, 89, 122, 91, + 101, 93, 84, 95, 156, 8, 98, 99, 8, 161, + 138, 103, 104, 105, 106, 107, 8, 109, 110, 31, + 97, 8, 123, 115, 116, 70, 8, 134, 135, 156, + 122, 8, 124, 125, 126, 163, 155, 156, 157, 163, + 116, 8, 149, 162, 136, 137, 8, 139, 140, 141, + 142, 143, 144, 145, 161, 14, 163, 160, 82, 151, + 152, 164, 138, 155, 156, 157, 158, 75, 76, 77, + 14, 163, 84, 165, 166, 167, 84, 159, 116, 161, + 82, 14, 90, 85, 92, 14, 94, 163, 96, 134, + 135, 161, 116, 159, 1, 161, 14, 167, 106, 14, + 138, 8, 164, 16, 149, 31, 164, 37, 38, 117, + 118, 75, 76, 137, 122, 31, 161, 14, 163, 127, + 128, 129, 130, 131, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 16, 163, + 70, 75, 76, 167, 16, 147, 148, 159, 16, 161, + 16, 159, 82, 161, 162, 16, 86, 16, 74, 70, + 16, 70, 101, 102, 80, 106, 107, 59, 60, 106, + 107, 87, 88, 89, 31, 91, 1, 93, 70, 95, + 111, 112, 98, 16, 16, 16, 116, 103, 104, 105, + 16, 31, 122, 109, 110, 37, 38, 16, 35, 115, + 116, 31, 0, 1, 31, 30, 136, 137, 124, 139, + 140, 141, 142, 143, 144, 31, 31, 31, 31, 31, + 31, 151, 152, 134, 135, 134, 135, 37, 38, 31, + 31, 31, 74, 163, 31, 1, 166, 167, 80, 31, + 149, 31, 134, 135, 31, 87, 88, 89, 31, 91, + 161, 93, 161, 95, 31, 31, 98, 149, 37, 37, + 35, 103, 104, 105, 74, 31, 35, 109, 110, 161, + 80, 35, 35, 115, 116, 70, 35, 87, 88, 89, + 35, 91, 124, 93, 37, 95, 84, 37, 98, 38, + 57, 116, 1, 103, 104, 105, 69, 77, 31, 109, + 110, 82, 70, 85, 89, 115, 116, 96, 106, 80, + 108, 83, 154, 138, 124, 113, 90, 82, 84, 117, + 118, 114, 31, 80, 122, 85, 132, 97, 132, 127, + 128, 129, 130, 131, 92, 97, 97, 128, 163, 134, + 135, 74, 70, 94, 1, 133, 100, 80, 100, 154, + 146, 137, 150, 160, 87, 88, 89, 113, 91, 1, + 93, 159, 95, 161, 162, 98, 161, 161, 1, 153, + 103, 104, 105, 74, -1, 84, 109, 110, -1, 80, + 1, -1, 115, 116, -1, -1, 87, 88, 89, 31, + 91, 124, 93, 159, 95, 161, 138, 98, 31, 146, + -1, 102, 103, 104, 105, 74, 134, 135, 109, 110, + 149, 80, 81, 149, 115, 116, 153, 149, 87, 88, + 89, 149, 91, 124, 93, 149, 95, 84, 149, 98, + 155, 158, 161, 161, 103, 104, 105, 159, 161, 159, + 109, 110, 84, 100, 101, 102, 115, 116, 159, 106, + 159, 84, 161, 159, 159, 124, 159, 159, 162, 159, + 117, 118, 159, 84, 159, 122, 159, 159, 159, 159, + 127, 128, 129, 130, 131, 70, 159, 159, 159, 100, + 101, 102, 1, 159, 161, 106, 160, 82, 160, 160, + 160, 86, 160, 166, 161, 161, 117, 118, 161, 1, + 161, 122, 159, 161, 161, 162, 127, 128, 129, 130, + 131, 161, 31, 161, 161, 161, 165, 159, 162, 161, + 163, 116, 162, 162, 162, 162, 159, 122, 161, 163, + 162, 162, 162, 162, 162, 162, 162, 162, 159, 162, + 161, 162, 137, 162, 139, 140, 141, 142, 143, 144, + 162, 162, 162, 162, 162, 162, 151, 152, 162, 162, + 74, 162, 162, 82, 162, 164, 80, 163, 163, 163, + 163, 166, 167, 87, 88, 89, 163, 91, 163, 93, + 82, 95, 163, 163, 98, 163, 163, 163, 163, 103, + 104, 105, 163, 163, 163, 109, 110, 116, 117, 118, + 163, 115, 116, 122, 163, 163, 163, 163, 163, 128, + 124, 163, 163, 163, 116, 117, 118, 163, 137, 163, + 122, 163, 163, 163, 163, 163, 128, 163, 163, 163, + 163, 163, 163, -1, 164, 137, 164, 164, 164, 158, + 164, 164, 164, 164, 163, 165, 164, 164, 167, 164, + -1, 164, 164, 164, 164, 164, 158, 164, 164, 164, + 164, 163, -1, 164, 164, 167, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, -1, -1, -1, + 167 + ); + + protected $actionBase = array( + 0, -2, 154, 542, 752, 893, 929, 52, 374, 431, + 398, 869, 793, 235, 307, 307, 793, 307, 784, 908, + 908, 917, 908, 538, 841, 468, 468, 468, 708, 708, + 708, 708, 740, 740, 849, 849, 881, 817, 634, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, 1036, + 1036, 1036, 1036, 1036, 348, 346, 370, 653, 1063, 1069, + 1065, 1070, 1061, 1060, 1064, 1066, 1071, 946, 947, 774, + 949, 950, 943, 952, 1067, 882, 1062, 1068, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 525, 191, 359, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 174, 174, + 174, 620, 620, 51, 465, 356, 955, 955, 955, 955, + 955, 955, 955, 955, 955, 955, 658, 184, 144, 144, + 7, 7, 7, 7, 7, 1031, 371, 1048, -25, -25, + -25, -25, 50, 725, 526, 449, 39, 317, 80, 474, + 474, 13, 13, 512, 512, 422, 422, 512, 512, 512, + 808, 808, 808, 808, 443, 505, 360, 308, -78, 209, + 209, 209, 209, -78, -78, -78, -78, 803, 877, -78, + -78, -78, 63, 641, 641, 822, -1, -1, -1, 641, + 253, 790, 548, 253, 384, 548, 480, 402, 764, 759, + -49, 447, 764, 639, 755, 198, 143, 825, 609, 825, + 1059, 320, 768, 426, 749, 720, 874, 904, 1072, 796, + 941, 798, 942, 106, -58, 710, 1058, 1058, 1058, 1058, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1073, 336, 1059, + 423, 1073, 1073, 1073, 336, 336, 336, 336, 336, 336, + 336, 336, 336, 336, 619, 423, 586, 616, 423, 795, + 336, 814, 348, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 750, 202, 348, 348, 346, 78, 78, 348, + 484, 65, 78, 78, 78, 78, 348, 348, 348, 348, + 609, 783, 766, 613, 813, 492, 783, 783, 783, 473, + 135, 378, 488, 713, 775, 67, 779, 779, 785, 969, + 969, 779, 769, 779, 785, 975, 779, 779, 969, 969, + 823, 280, 563, 478, 550, 568, 969, 377, 779, 779, + 779, 779, 746, 573, 779, 342, 314, 779, 779, 746, + 744, 760, 43, 762, 969, 969, 969, 746, 547, 762, + 762, 762, 839, 844, 794, 758, 444, 433, 588, 232, + 801, 758, 758, 779, 558, 794, 758, 794, 758, 745, + 758, 758, 758, 794, 758, 769, 502, 758, 717, 583, + 224, 758, 6, 979, 980, 624, 981, 973, 987, 1019, + 991, 992, 873, 965, 999, 974, 993, 972, 970, 773, + 682, 684, 818, 811, 963, 777, 777, 777, 956, 777, + 777, 777, 777, 777, 777, 777, 777, 682, 743, 829, + 765, 1006, 689, 691, 754, 911, 901, 1030, 1004, 1049, + 994, 828, 694, 1028, 1008, 910, 821, 1009, 1010, 1029, + 1050, 1052, 912, 782, 913, 918, 876, 1012, 883, 777, + 979, 992, 693, 974, 993, 972, 970, 748, 739, 737, + 738, 736, 735, 723, 734, 753, 1053, 954, 907, 878, + 1011, 957, 682, 879, 1023, 756, 1032, 1033, 827, 788, + 778, 880, 919, 1014, 1015, 1016, 884, 1054, 887, 830, + 1024, 951, 1035, 789, 846, 1037, 1038, 1039, 1040, 889, + 920, 892, 916, 900, 845, 776, 1020, 761, 921, 591, + 787, 791, 800, 1018, 606, 1000, 902, 906, 922, 1041, + 1043, 1044, 923, 924, 995, 847, 1026, 799, 1027, 1022, + 848, 850, 617, 797, 1055, 781, 786, 772, 621, 632, + 925, 927, 931, 998, 763, 770, 853, 855, 1056, 771, + 1057, 938, 635, 857, 718, 939, 1046, 719, 724, 637, + 678, 672, 731, 792, 903, 826, 757, 780, 1017, 724, + 767, 858, 940, 859, 860, 867, 1045, 868, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 458, 458, + 458, 458, 458, 458, 307, 307, 307, 307, 307, 307, + 307, 0, 0, 307, 0, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, + 458, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, + 291, 291, 291, 291, 291, 291, 291, 291, 66, 66, + 291, 291, 291, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 0, 291, 291, 291, 291, 291, 291, + 291, 291, 66, 823, 66, -1, -1, -1, -1, 66, + 66, 66, -88, -88, 66, 384, 66, 66, -1, -1, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 0, 0, 423, 548, 66, 769, 769, 769, 769, + 66, 66, 66, 66, 548, 548, 66, 66, 66, 0, + 0, 0, 0, 0, 0, 0, 0, 423, 548, 0, + 423, 0, 0, 769, 769, 66, 384, 823, 643, 66, + 0, 0, 0, 0, 423, 769, 423, 336, 779, 548, + 779, 336, 336, 78, 348, 643, 611, 611, 611, 611, + 0, 0, 609, 823, 823, 823, 823, 823, 823, 823, + 823, 823, 823, 823, 769, 0, 823, 0, 769, 769, + 769, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 769, 0, 969, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 975, + 0, 0, 0, 0, 0, 0, 0, 0, 769, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 777, 788, + 0, 788, 0, 777, 777, 777, 0, 0, 0, 0, + 797, 771 + ); + + protected $actionDefault = array( + 3,32767, 103,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 101,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 596, 596, + 596, 596,32767,32767, 254, 103,32767,32767, 469, 387, + 387, 387,32767,32767, 540, 540, 540, 540, 540, 540, + 32767,32767,32767,32767,32767,32767, 469,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 101, + 32767,32767,32767, 37, 7, 8, 10, 11, 50, 17, + 324,32767,32767,32767,32767, 103,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 589,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 473, 452, + 453, 455, 456, 386, 541, 595, 327, 592, 385, 146, + 339, 329, 242, 330, 258, 474, 259, 475, 478, 479, + 215, 287, 382, 150, 151, 416, 470, 418, 468, 472, + 417, 392, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 409, 390, 391, 471, 449, 448, + 447,32767,32767, 414, 415, 419,32767,32767,32767,32767, + 32767,32767,32767,32767, 103,32767, 389, 422, 420, 421, + 438, 439, 436, 437, 440,32767,32767,32767, 441, 442, + 443, 444, 316,32767,32767, 366, 364, 316, 112,32767, + 32767, 429, 430,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 534, 446,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 103, + 32767, 101, 536, 411, 413, 503, 424, 425, 423, 393, + 32767, 510,32767, 103,32767, 512,32767,32767,32767,32767, + 32767,32767,32767, 535,32767, 542, 542,32767, 496, 101, + 195,32767,32767,32767, 195, 195,32767,32767,32767,32767, + 32767,32767,32767,32767, 603, 496, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111,32767, 195, 111, + 32767,32767,32767, 101, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 190,32767, 268, 270, 103, 557, + 195, 515,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 508,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 496, 434, 139,32767, 139, 542, 426, 427, 428, 498, + 542, 542, 542, 312, 289,32767,32767,32767,32767, 513, + 513, 101, 101, 101, 101, 508,32767,32767,32767,32767, + 112, 100, 100, 100, 100, 100, 104, 102,32767,32767, + 32767,32767, 223, 100,32767, 102, 102,32767,32767, 223, + 225, 212, 102, 227,32767, 561, 562, 223, 102, 227, + 227, 227, 247, 247, 485, 318, 102, 100, 102, 102, + 197, 318, 318,32767, 102, 485, 318, 485, 318, 199, + 318, 318, 318, 485, 318,32767, 102, 318, 214, 100, + 100, 318,32767,32767,32767, 498,32767,32767,32767,32767, + 32767,32767,32767, 222,32767,32767,32767,32767,32767,32767, + 32767, 529,32767, 546, 559, 432, 433, 435, 544, 457, + 458, 459, 460, 461, 462, 463, 465, 591,32767, 502, + 32767,32767,32767, 338, 601,32767, 601,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 602,32767, 542,32767,32767,32767,32767, 431, + 9, 76, 491, 43, 44, 52, 58, 519, 520, 521, + 522, 516, 517, 523, 518,32767,32767, 524, 567,32767, + 32767, 543, 594,32767,32767,32767,32767,32767,32767, 139, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767, 529,32767, 137,32767,32767,32767,32767,32767,32767, + 32767,32767, 525,32767,32767,32767, 542,32767,32767,32767, + 32767, 314, 311,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 542, + 32767,32767,32767,32767,32767, 291,32767, 308,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 286,32767,32767, 381, 498, 294, + 296, 297,32767,32767,32767,32767, 360,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 153, 153, + 3, 3, 341, 153, 153, 153, 341, 341, 153, 341, + 341, 341, 153, 153, 153, 153, 153, 153, 280, 185, + 262, 265, 247, 247, 153, 352, 153 + ); + + protected $goto = array( + 196, 196, 1032, 704, 695, 431, 659, 1063, 1335, 1335, + 425, 313, 314, 335, 574, 319, 430, 336, 432, 636, + 652, 653, 851, 670, 671, 672, 1335, 167, 167, 167, + 167, 221, 197, 193, 193, 177, 179, 216, 193, 193, + 193, 193, 193, 194, 194, 194, 194, 194, 194, 188, + 189, 190, 191, 192, 218, 216, 219, 535, 536, 421, + 537, 539, 540, 541, 542, 543, 544, 545, 546, 1133, + 168, 169, 170, 195, 171, 172, 173, 166, 174, 175, + 176, 178, 215, 217, 220, 238, 243, 244, 245, 257, + 258, 259, 260, 261, 262, 263, 264, 268, 269, 270, + 271, 281, 282, 316, 317, 318, 426, 427, 428, 579, + 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 180, 237, 181, 198, 199, + 200, 239, 188, 189, 190, 191, 192, 218, 1133, 201, + 182, 183, 184, 202, 198, 185, 240, 203, 201, 165, + 204, 205, 186, 206, 207, 208, 187, 209, 210, 211, + 212, 213, 214, 854, 619, 656, 278, 278, 278, 278, + 852, 621, 621, 350, 419, 598, 1266, 1266, 1266, 1266, + 1266, 1266, 1266, 1266, 1266, 1266, 1284, 1284, 832, 1105, + 1106, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1284, + 1284, 353, 353, 353, 353, 826, 558, 551, 908, 903, + 904, 917, 860, 905, 857, 906, 907, 858, 1035, 1035, + 911, 864, 679, 950, 458, 863, 1027, 1043, 1044, 832, + 885, 832, 1085, 1080, 1081, 1082, 341, 551, 558, 567, + 568, 343, 577, 600, 614, 615, 547, 547, 547, 547, + 973, 602, 15, 394, 397, 559, 599, 603, 1213, 942, + 1234, 571, 1234, 1214, 1217, 943, 1218, 1032, 1032, 1234, + 440, 912, 1032, 913, 1032, 1032, 1038, 1037, 1032, 1032, + 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1032, 1316, + 1316, 1316, 1316, 1234, 476, 1309, 1310, 348, 1234, 1234, + 1234, 1234, 407, 408, 1234, 1234, 1234, 668, 1324, 669, + 354, 412, 413, 414, 867, 682, 466, 466, 415, 994, + 354, 354, 346, 924, 424, 466, 609, 925, 5, 879, + 6, 940, 866, 940, 354, 354, 1282, 1282, 354, 392, + 1351, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, 1282, + 1282, 553, 538, 538, 570, 354, 658, 538, 538, 538, + 538, 538, 538, 538, 538, 538, 538, 549, 565, 549, + 1041, 1042, 731, 635, 637, 850, 549, 657, 965, 410, + 703, 681, 685, 1008, 693, 702, 1004, 252, 252, 997, + 971, 971, 969, 971, 730, 1056, 550, 1006, 1001, 1182, + 456, 847, 1295, 1334, 1334, 967, 967, 967, 967, 325, + 308, 456, 961, 968, 249, 249, 249, 249, 251, 253, + 438, 1334, 351, 352, 684, 680, 552, 562, 450, 450, + 450, 552, 1306, 562, 1306, 479, 395, 462, 1337, 1311, + 1312, 1306, 664, 481, 500, 337, 501, 844, 469, 578, + 470, 471, 507, 847, 877, 553, 872, 1342, 1343, 1011, + 1011, 575, 612, 324, 275, 324, 1318, 1318, 1318, 1318, + 607, 622, 625, 626, 627, 628, 649, 650, 651, 706, + 956, 401, 692, 875, 1229, 828, 869, 692, 629, 631, + 633, 692, 433, 1302, 1225, 734, 613, 433, 880, 868, + 1068, 1072, 1069, 1016, 477, 1039, 1039, 881, 0, 976, + 663, 1050, 1046, 1047, 1073, 1116, 978, 0, 1227, 450, + 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, + 929, 1121, 450, 966, 1071, 0, 0, 617, 1304, 1304, + 1071, 1230, 1231, 1013, 0, 0, 0, 0, 0, 842, + 0, 871, 0, 662, 992, 1114, 884, 597, 1098, 865, + 707, 0, 0, 508, 698, 0, 1096, 1232, 1292, 1293, + 0, 1224, 0, 847, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 255, 255 + ); + + protected $gotoCheck = array( + 42, 42, 72, 9, 72, 65, 65, 126, 181, 181, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 85, 85, 26, 85, 85, 85, 181, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 15, 55, 55, 23, 23, 23, 23, + 27, 107, 107, 96, 43, 129, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 168, 168, 12, 143, + 143, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 24, 24, 24, 24, 6, 75, 75, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 88, 88, + 15, 15, 88, 88, 82, 15, 88, 88, 88, 12, + 45, 12, 15, 15, 15, 15, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 106, 106, 106, 106, + 49, 106, 75, 58, 58, 58, 58, 58, 78, 78, + 72, 170, 72, 78, 78, 78, 78, 72, 72, 72, + 82, 64, 72, 64, 72, 72, 117, 117, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 9, + 9, 9, 9, 72, 174, 174, 174, 177, 72, 72, + 72, 72, 81, 81, 72, 72, 72, 81, 179, 81, + 14, 81, 81, 81, 35, 81, 148, 148, 81, 102, + 14, 14, 81, 72, 13, 148, 13, 72, 46, 35, + 46, 9, 35, 9, 14, 14, 169, 169, 14, 61, + 14, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 14, 171, 171, 103, 14, 63, 171, 171, 171, + 171, 171, 171, 171, 171, 171, 171, 19, 48, 19, + 118, 118, 48, 48, 48, 25, 19, 48, 92, 92, + 92, 48, 48, 48, 48, 48, 48, 5, 5, 25, + 25, 25, 25, 25, 25, 113, 25, 25, 25, 150, + 19, 22, 14, 180, 180, 19, 19, 19, 19, 167, + 167, 19, 19, 19, 5, 5, 5, 5, 5, 5, + 112, 180, 96, 96, 14, 115, 9, 9, 23, 23, + 23, 9, 129, 9, 129, 83, 9, 9, 180, 176, + 176, 129, 119, 83, 154, 29, 154, 18, 9, 9, + 9, 9, 154, 22, 9, 14, 39, 9, 9, 106, + 106, 2, 2, 24, 24, 24, 129, 129, 129, 129, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 91, 28, 7, 9, 20, 7, 37, 7, 84, 84, + 84, 7, 116, 129, 159, 98, 79, 116, 16, 16, + 16, 16, 128, 109, 156, 116, 116, 41, -1, 16, + 116, 116, 116, 116, 131, 146, 95, -1, 14, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 17, 17, 23, 16, 129, -1, -1, 17, 129, 129, + 129, 20, 20, 17, -1, -1, -1, -1, -1, 20, + -1, 17, -1, 17, 17, 16, 16, 8, 8, 17, + 8, -1, -1, 8, 8, -1, 8, 20, 20, 20, + -1, 17, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 5, 5 + ); + + protected $gotoBase = array( + 0, 0, -249, 0, 0, 386, 192, 475, 549, -10, + 0, 0, -108, -13, 13, -184, 46, 65, 138, 102, + 93, 0, 123, 163, 198, 371, 18, 166, 144, 149, + 0, 0, 0, 0, 0, -56, 0, 147, 0, 133, + 0, 66, -1, 162, 0, 214, -406, 0, -341, 226, + 0, 0, 0, 0, 0, 124, 0, 0, 208, 0, + 0, 297, 0, 114, 251, -236, 0, 0, 0, 0, + 0, 0, -5, 0, 0, -138, 0, 0, -149, 153, + 113, -189, -54, -34, 9, -696, 0, 0, -61, 0, + 0, 151, 74, 0, 0, 73, -310, 0, 89, 0, + 0, 0, 284, 311, 0, 0, 218, -70, 0, 134, + 0, 0, 143, 122, 0, 142, 220, -3, 85, 152, + 0, 0, 0, 0, 0, 0, 5, 0, 129, 167, + 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -86, 0, 0, 71, 0, 282, 0, + 125, 0, 0, 0, -51, 0, 64, 0, 0, 126, + 0, 0, 0, 0, 0, 0, 0, 88, -55, 95, + 232, 111, 0, 0, -6, 0, 68, 267, 0, 277, + 96, -299, 0, 0 + ); + + protected $gotoDefault = array( + -32768, 512, 738, 4, 739, 933, 815, 824, 595, 529, + 705, 347, 623, 422, 1300, 910, 1120, 576, 843, 1243, + 1251, 457, 846, 330, 728, 892, 893, 894, 398, 385, + 859, 396, 647, 624, 494, 878, 453, 870, 486, 873, + 452, 882, 164, 418, 510, 886, 3, 889, 555, 920, + 386, 897, 387, 675, 899, 561, 901, 902, 393, 399, + 400, 1125, 569, 620, 914, 256, 563, 915, 384, 916, + 923, 389, 391, 686, 465, 505, 499, 411, 1100, 564, + 606, 644, 447, 473, 618, 630, 616, 480, 434, 416, + 329, 955, 963, 487, 463, 977, 349, 985, 736, 1132, + 638, 489, 993, 639, 1000, 1003, 530, 531, 478, 1015, + 272, 1018, 490, 12, 665, 1029, 1030, 666, 640, 1052, + 641, 667, 642, 1054, 472, 596, 1062, 454, 1070, 1288, + 455, 1074, 266, 1077, 277, 417, 435, 1083, 1084, 9, + 1090, 696, 697, 11, 276, 509, 1115, 687, 451, 1131, + 439, 1201, 1203, 557, 491, 1221, 1220, 678, 506, 1226, + 448, 1291, 449, 532, 474, 315, 533, 307, 333, 312, + 548, 294, 334, 534, 475, 1297, 1305, 331, 31, 1325, + 1336, 342, 573, 611 + ); + + protected $ruleToNonTerminal = array( + 0, 1, 3, 3, 2, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, + 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, + 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, + 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, + 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, + 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, + 45, 45, 46, 46, 48, 47, 47, 47, 47, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 25, 25, 68, 68, 71, 71, 70, + 69, 69, 62, 74, 74, 75, 75, 76, 76, 77, + 77, 78, 78, 79, 79, 26, 26, 27, 27, 27, + 27, 27, 87, 87, 89, 89, 82, 82, 90, 90, + 91, 91, 91, 83, 83, 86, 86, 84, 84, 92, + 93, 93, 56, 56, 64, 64, 67, 67, 67, 66, + 94, 94, 95, 57, 57, 57, 57, 96, 96, 97, + 97, 98, 98, 99, 100, 100, 101, 101, 102, 102, + 54, 54, 50, 50, 104, 52, 52, 105, 51, 51, + 53, 53, 63, 63, 63, 63, 80, 80, 108, 108, + 110, 110, 111, 111, 111, 111, 109, 109, 109, 113, + 113, 113, 113, 88, 88, 116, 116, 116, 117, 117, + 114, 114, 118, 118, 120, 120, 121, 121, 115, 122, + 122, 119, 123, 123, 123, 123, 112, 112, 81, 81, + 81, 20, 20, 20, 125, 124, 124, 126, 126, 126, + 126, 59, 127, 127, 128, 60, 130, 130, 131, 131, + 132, 132, 85, 133, 133, 133, 133, 133, 133, 133, + 138, 138, 139, 139, 140, 140, 140, 140, 140, 141, + 142, 142, 137, 137, 134, 134, 136, 136, 144, 144, + 143, 143, 143, 143, 143, 143, 143, 135, 145, 145, + 147, 146, 146, 61, 103, 148, 148, 55, 55, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 155, 149, 149, 154, 154, 157, 158, 158, + 159, 160, 161, 161, 161, 161, 19, 19, 72, 72, + 72, 72, 150, 150, 150, 150, 163, 163, 151, 151, + 153, 153, 153, 156, 156, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 169, 169, 169, 107, 171, 171, + 171, 171, 152, 152, 152, 152, 152, 152, 152, 152, + 58, 58, 166, 166, 166, 166, 172, 172, 162, 162, + 162, 173, 173, 173, 173, 173, 173, 73, 73, 65, + 65, 65, 65, 129, 129, 129, 129, 176, 175, 165, + 165, 165, 165, 165, 165, 165, 164, 164, 164, 174, + 174, 174, 174, 106, 170, 178, 178, 177, 177, 179, + 179, 179, 179, 179, 179, 179, 179, 167, 167, 167, + 167, 181, 182, 180, 180, 180, 180, 180, 180, 180, + 180, 183, 183, 183, 183 + ); + + protected $ruleToLength = array( + 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, + 2, 0, 1, 1, 1, 1, 1, 3, 5, 4, + 3, 4, 1, 3, 1, 1, 8, 7, 2, 3, + 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, + 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, + 3, 3, 2, 0, 1, 1, 1, 1, 1, 3, + 7, 10, 5, 7, 9, 5, 3, 3, 3, 3, + 3, 3, 1, 2, 5, 7, 9, 6, 5, 6, + 3, 2, 1, 1, 1, 0, 2, 1, 3, 8, + 0, 4, 2, 1, 3, 0, 1, 0, 1, 0, + 1, 3, 1, 1, 1, 8, 9, 7, 8, 7, + 6, 8, 0, 2, 0, 2, 1, 2, 1, 2, + 1, 1, 1, 0, 2, 0, 2, 0, 2, 2, + 1, 3, 1, 4, 1, 4, 1, 1, 4, 2, + 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, + 3, 1, 1, 7, 0, 2, 1, 3, 3, 4, + 1, 4, 0, 2, 5, 0, 2, 6, 0, 2, + 0, 3, 1, 2, 1, 1, 2, 0, 1, 3, + 0, 2, 1, 1, 1, 1, 6, 8, 6, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, + 3, 1, 1, 2, 1, 1, 0, 1, 0, 2, + 2, 2, 4, 3, 1, 1, 3, 1, 2, 2, + 3, 2, 3, 1, 1, 2, 3, 1, 1, 3, + 2, 0, 1, 5, 5, 6, 10, 3, 5, 1, + 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, + 1, 1, 3, 2, 2, 3, 1, 0, 1, 1, + 3, 3, 3, 4, 1, 1, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, + 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 3, 2, 1, + 2, 4, 2, 2, 8, 9, 8, 9, 9, 10, + 9, 10, 8, 3, 2, 0, 4, 2, 1, 3, + 2, 1, 2, 2, 2, 4, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 1, 1, 0, 3, + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 5, 3, 3, 4, 1, + 1, 3, 1, 1, 1, 1, 1, 3, 2, 3, + 0, 1, 1, 3, 1, 1, 1, 1, 1, 3, + 1, 1, 4, 4, 1, 4, 4, 0, 1, 1, + 1, 3, 3, 1, 4, 2, 2, 1, 3, 1, + 4, 4, 3, 3, 3, 3, 1, 3, 1, 1, + 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, + 2, 1, 3, 4, 3, 2, 0, 2, 2, 1, + 2, 1, 1, 1, 4, 3, 3, 3, 3, 6, + 3, 1, 1, 2, 1 + ); + + protected function initReduceCallbacks() { + $this->reduceCallbacks = [ + 0 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 1 => function ($stackPos) { + $this->semValue = $this->handleNamespaces($this->semStack[$stackPos-(1-1)]); + }, + 2 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 3 => function ($stackPos) { + $this->semValue = array(); + }, + 4 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 5 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 6 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 7 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 8 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 9 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 10 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 11 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 12 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 13 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 14 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 15 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 16 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 17 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 18 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 19 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 20 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 21 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 22 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 23 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 24 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 25 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 26 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 27 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 28 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 29 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 30 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 31 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 32 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 33 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 34 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 35 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 36 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 37 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 38 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 39 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 40 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 41 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 42 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 43 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 44 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 45 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 46 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 47 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 48 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 49 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 50 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 51 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 52 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 53 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 54 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 55 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 56 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 57 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 58 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 59 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 60 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 61 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 62 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 63 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 64 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 65 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 66 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 67 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 68 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 69 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 70 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 71 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 72 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 73 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 74 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 75 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 76 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 77 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 78 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 79 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 80 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 81 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 82 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 83 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 84 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 85 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 86 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 87 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 88 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 89 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 90 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 91 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 92 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 93 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 94 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 95 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 96 => function ($stackPos) { + $this->semValue = new Name(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 97 => function ($stackPos) { + $this->semValue = new Expr\Variable(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 98 => function ($stackPos) { + /* nothing */ + }, + 99 => function ($stackPos) { + /* nothing */ + }, + 100 => function ($stackPos) { + /* nothing */ + }, + 101 => function ($stackPos) { + $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); + }, + 102 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 103 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 104 => function ($stackPos) { + $this->semValue = new Node\Attribute($this->semStack[$stackPos-(1-1)], [], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 105 => function ($stackPos) { + $this->semValue = new Node\Attribute($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 106 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 107 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 108 => function ($stackPos) { + $this->semValue = new Node\AttributeGroup($this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 109 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 110 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 111 => function ($stackPos) { + $this->semValue = []; + }, + 112 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 113 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 114 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 115 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 116 => function ($stackPos) { + $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 117 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(3-2)], null, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($this->semValue); + }, + 118 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 119 => function ($stackPos) { + $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + }, + 120 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 121 => function ($stackPos) { + $this->semValue = new Stmt\Use_($this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 122 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 123 => function ($stackPos) { + $this->semValue = new Stmt\Const_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 124 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_FUNCTION; + }, + 125 => function ($stackPos) { + $this->semValue = Stmt\Use_::TYPE_CONSTANT; + }, + 126 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-2)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 127 => function ($stackPos) { + $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos-(7-2)], $this->semStack[$stackPos-(7-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 128 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 129 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 130 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 131 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 132 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 133 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 134 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 135 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 136 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 137 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 138 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 139 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(1-1)); + }, + 140 => function ($stackPos) { + $this->semValue = new Stmt\UseUse($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $stackPos-(3-3)); + }, + 141 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; + }, + 142 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; $this->semValue->type = $this->semStack[$stackPos-(2-1)]; + }, + 143 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 144 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 145 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 146 => function ($stackPos) { + $this->semValue = new Node\Const_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 147 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 148 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 149 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 150 => function ($stackPos) { + $this->semValue = new Node\Const_(new Node\Identifier($this->semStack[$stackPos-(3-1)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributeStack[$stackPos-(3-1)]), $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 151 => function ($stackPos) { + $this->semValue = new Node\Const_(new Node\Identifier($this->semStack[$stackPos-(3-1)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributeStack[$stackPos-(3-1)]), $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 152 => function ($stackPos) { + if (is_array($this->semStack[$stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); } else { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; }; + }, + 153 => function ($stackPos) { + $this->semValue = array(); + }, + 154 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 155 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 156 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 157 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 158 => function ($stackPos) { + throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 159 => function ($stackPos) { + + if ($this->semStack[$stackPos-(3-2)]) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; $attrs = $this->startAttributeStack[$stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; + } else { + $startAttributes = $this->startAttributeStack[$stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if (null === $this->semValue) { $this->semValue = array(); } + } + + }, + 160 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(7-3)], ['stmts' => is_array($this->semStack[$stackPos-(7-5)]) ? $this->semStack[$stackPos-(7-5)] : array($this->semStack[$stackPos-(7-5)]), 'elseifs' => $this->semStack[$stackPos-(7-6)], 'else' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 161 => function ($stackPos) { + $this->semValue = new Stmt\If_($this->semStack[$stackPos-(10-3)], ['stmts' => $this->semStack[$stackPos-(10-6)], 'elseifs' => $this->semStack[$stackPos-(10-7)], 'else' => $this->semStack[$stackPos-(10-8)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 162 => function ($stackPos) { + $this->semValue = new Stmt\While_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 163 => function ($stackPos) { + $this->semValue = new Stmt\Do_($this->semStack[$stackPos-(7-5)], is_array($this->semStack[$stackPos-(7-2)]) ? $this->semStack[$stackPos-(7-2)] : array($this->semStack[$stackPos-(7-2)]), $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 164 => function ($stackPos) { + $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos-(9-3)], 'cond' => $this->semStack[$stackPos-(9-5)], 'loop' => $this->semStack[$stackPos-(9-7)], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 165 => function ($stackPos) { + $this->semValue = new Stmt\Switch_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 166 => function ($stackPos) { + $this->semValue = new Stmt\Break_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 167 => function ($stackPos) { + $this->semValue = new Stmt\Continue_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 168 => function ($stackPos) { + $this->semValue = new Stmt\Return_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 169 => function ($stackPos) { + $this->semValue = new Stmt\Global_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 170 => function ($stackPos) { + $this->semValue = new Stmt\Static_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 171 => function ($stackPos) { + $this->semValue = new Stmt\Echo_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 172 => function ($stackPos) { + $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 173 => function ($stackPos) { + + $e = $this->semStack[$stackPos-(2-1)]; + if ($e instanceof Expr\Throw_) { + // For backwards-compatibility reasons, convert throw in statement position into + // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_). + $this->semValue = new Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + } else { + $this->semValue = new Stmt\Expression($e, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + } + + }, + 174 => function ($stackPos) { + $this->semValue = new Stmt\Unset_($this->semStack[$stackPos-(5-3)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 175 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos-(7-5)][1], 'stmts' => $this->semStack[$stackPos-(7-7)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 176 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(9-3)], $this->semStack[$stackPos-(9-7)][0], ['keyVar' => $this->semStack[$stackPos-(9-5)], 'byRef' => $this->semStack[$stackPos-(9-7)][1], 'stmts' => $this->semStack[$stackPos-(9-9)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 177 => function ($stackPos) { + $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos-(6-3)], new Expr\Error($this->startAttributeStack[$stackPos-(6-4)] + $this->endAttributeStack[$stackPos-(6-4)]), ['stmts' => $this->semStack[$stackPos-(6-6)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 178 => function ($stackPos) { + $this->semValue = new Stmt\Declare_($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 179 => function ($stackPos) { + $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); + }, + 180 => function ($stackPos) { + $this->semValue = new Stmt\Goto_($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 181 => function ($stackPos) { + $this->semValue = new Stmt\Label($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 182 => function ($stackPos) { + $this->semValue = array(); /* means: no statement */ + }, + 183 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 184 => function ($stackPos) { + $startAttributes = $this->startAttributeStack[$stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes); } else { $this->semValue = null; }; + if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ + }, + 185 => function ($stackPos) { + $this->semValue = array(); + }, + 186 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 187 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 188 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 189 => function ($stackPos) { + $this->semValue = new Stmt\Catch_($this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-7)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 190 => function ($stackPos) { + $this->semValue = null; + }, + 191 => function ($stackPos) { + $this->semValue = new Stmt\Finally_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 192 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 193 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 194 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 195 => function ($stackPos) { + $this->semValue = false; + }, + 196 => function ($stackPos) { + $this->semValue = true; + }, + 197 => function ($stackPos) { + $this->semValue = false; + }, + 198 => function ($stackPos) { + $this->semValue = true; + }, + 199 => function ($stackPos) { + $this->semValue = false; + }, + 200 => function ($stackPos) { + $this->semValue = true; + }, + 201 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 202 => function ($stackPos) { + $this->semValue = []; + }, + 203 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 204 => function ($stackPos) { + $this->semValue = new Node\Identifier($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 205 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(8-3)], ['byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-5)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 206 => function ($stackPos) { + $this->semValue = new Stmt\Function_($this->semStack[$stackPos-(9-4)], ['byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-6)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 207 => function ($stackPos) { + $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(7-2)], ['type' => $this->semStack[$stackPos-(7-1)], 'extends' => $this->semStack[$stackPos-(7-3)], 'implements' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $stackPos-(7-2)); + }, + 208 => function ($stackPos) { + $this->semValue = new Stmt\Class_($this->semStack[$stackPos-(8-3)], ['type' => $this->semStack[$stackPos-(8-2)], 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $stackPos-(8-3)); + }, + 209 => function ($stackPos) { + $this->semValue = new Stmt\Interface_($this->semStack[$stackPos-(7-3)], ['extends' => $this->semStack[$stackPos-(7-4)], 'stmts' => $this->semStack[$stackPos-(7-6)], 'attrGroups' => $this->semStack[$stackPos-(7-1)]], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + $this->checkInterface($this->semValue, $stackPos-(7-3)); + }, + 210 => function ($stackPos) { + $this->semValue = new Stmt\Trait_($this->semStack[$stackPos-(6-3)], ['stmts' => $this->semStack[$stackPos-(6-5)], 'attrGroups' => $this->semStack[$stackPos-(6-1)]], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 211 => function ($stackPos) { + $this->semValue = new Stmt\Enum_($this->semStack[$stackPos-(8-3)], ['scalarType' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + $this->checkEnum($this->semValue, $stackPos-(8-3)); + }, + 212 => function ($stackPos) { + $this->semValue = null; + }, + 213 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 214 => function ($stackPos) { + $this->semValue = null; + }, + 215 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 216 => function ($stackPos) { + $this->semValue = 0; + }, + 217 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 218 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 219 => function ($stackPos) { + $this->checkClassModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 220 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 221 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 222 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 223 => function ($stackPos) { + $this->semValue = null; + }, + 224 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 225 => function ($stackPos) { + $this->semValue = array(); + }, + 226 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 227 => function ($stackPos) { + $this->semValue = array(); + }, + 228 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 229 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 230 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 231 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 232 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 233 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 234 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 235 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 236 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 237 => function ($stackPos) { + $this->semValue = null; + }, + 238 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 239 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 240 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 241 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 242 => function ($stackPos) { + $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 243 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 244 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 245 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 246 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(5-3)]; + }, + 247 => function ($stackPos) { + $this->semValue = array(); + }, + 248 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 249 => function ($stackPos) { + $this->semValue = new Stmt\Case_($this->semStack[$stackPos-(4-2)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 250 => function ($stackPos) { + $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 251 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 252 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 253 => function ($stackPos) { + $this->semValue = new Expr\Match_($this->semStack[$stackPos-(7-3)], $this->semStack[$stackPos-(7-6)], $this->startAttributeStack[$stackPos-(7-1)] + $this->endAttributes); + }, + 254 => function ($stackPos) { + $this->semValue = []; + }, + 255 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 256 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 257 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 258 => function ($stackPos) { + $this->semValue = new Node\MatchArm($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 259 => function ($stackPos) { + $this->semValue = new Node\MatchArm(null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 260 => function ($stackPos) { + $this->semValue = is_array($this->semStack[$stackPos-(1-1)]) ? $this->semStack[$stackPos-(1-1)] : array($this->semStack[$stackPos-(1-1)]); + }, + 261 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 262 => function ($stackPos) { + $this->semValue = array(); + }, + 263 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 264 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(5-3)], is_array($this->semStack[$stackPos-(5-5)]) ? $this->semStack[$stackPos-(5-5)] : array($this->semStack[$stackPos-(5-5)]), $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 265 => function ($stackPos) { + $this->semValue = array(); + }, + 266 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 267 => function ($stackPos) { + $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-6)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); $this->fixupAlternativeElse($this->semValue); + }, + 268 => function ($stackPos) { + $this->semValue = null; + }, + 269 => function ($stackPos) { + $this->semValue = new Stmt\Else_(is_array($this->semStack[$stackPos-(2-2)]) ? $this->semStack[$stackPos-(2-2)] : array($this->semStack[$stackPos-(2-2)]), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 270 => function ($stackPos) { + $this->semValue = null; + }, + 271 => function ($stackPos) { + $this->semValue = new Stmt\Else_($this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->fixupAlternativeElse($this->semValue); + }, + 272 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 273 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-2)], true); + }, + 274 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 275 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)], false); + }, + 276 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 277 => function ($stackPos) { + $this->semValue = array(); + }, + 278 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 279 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 280 => function ($stackPos) { + $this->semValue = 0; + }, + 281 => function ($stackPos) { + $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 282 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 283 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 284 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 285 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 286 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(6-6)], null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); + $this->checkParam($this->semValue); + }, + 287 => function ($stackPos) { + $this->semValue = new Node\Param($this->semStack[$stackPos-(8-6)], $this->semStack[$stackPos-(8-8)], $this->semStack[$stackPos-(8-3)], $this->semStack[$stackPos-(8-4)], $this->semStack[$stackPos-(8-5)], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes, $this->semStack[$stackPos-(8-2)], $this->semStack[$stackPos-(8-1)]); + $this->checkParam($this->semValue); + }, + 288 => function ($stackPos) { + $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes), null, $this->semStack[$stackPos-(6-3)], $this->semStack[$stackPos-(6-4)], $this->semStack[$stackPos-(6-5)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-1)]); + }, + 289 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 290 => function ($stackPos) { + $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 291 => function ($stackPos) { + $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 292 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 293 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 294 => function ($stackPos) { + $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 295 => function ($stackPos) { + $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos-(1-1)]); + }, + 296 => function ($stackPos) { + $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 297 => function ($stackPos) { + $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 298 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 299 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 300 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 301 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 302 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 303 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 304 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 305 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 306 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 307 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 308 => function ($stackPos) { + $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 309 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 310 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 311 => function ($stackPos) { + $this->semValue = new Node\IntersectionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 312 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 313 => function ($stackPos) { + $this->semValue = new Node\NullableType($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 314 => function ($stackPos) { + $this->semValue = new Node\UnionType($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 315 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 316 => function ($stackPos) { + $this->semValue = null; + }, + 317 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 318 => function ($stackPos) { + $this->semValue = null; + }, + 319 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-2)]; + }, + 320 => function ($stackPos) { + $this->semValue = null; + }, + 321 => function ($stackPos) { + $this->semValue = array(); + }, + 322 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-2)]; + }, + 323 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-2)]); + }, + 324 => function ($stackPos) { + $this->semValue = new Node\VariadicPlaceholder($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 325 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 326 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 327 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(1-1)], false, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 328 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], true, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 329 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(2-2)], false, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 330 => function ($stackPos) { + $this->semValue = new Node\Arg($this->semStack[$stackPos-(3-3)], false, false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->semStack[$stackPos-(3-1)]); + }, + 331 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 332 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 333 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 334 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 335 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 336 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 337 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 338 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 339 => function ($stackPos) { + $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 340 => function ($stackPos) { + if ($this->semStack[$stackPos-(2-2)] !== null) { $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; } else { $this->semValue = $this->semStack[$stackPos-(2-1)]; } + }, + 341 => function ($stackPos) { + $this->semValue = array(); + }, + 342 => function ($stackPos) { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 343 => function ($stackPos) { + $this->semValue = new Stmt\Property($this->semStack[$stackPos-(5-2)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-1)]); + $this->checkProperty($this->semValue, $stackPos-(5-2)); + }, + 344 => function ($stackPos) { + $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-2)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes, $this->semStack[$stackPos-(5-1)]); + $this->checkClassConst($this->semValue, $stackPos-(5-2)); + }, + 345 => function ($stackPos) { + $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos-(6-5)], $this->semStack[$stackPos-(6-2)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes, $this->semStack[$stackPos-(6-1)], $this->semStack[$stackPos-(6-4)]); + $this->checkClassConst($this->semValue, $stackPos-(6-2)); + }, + 346 => function ($stackPos) { + $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos-(10-5)], ['type' => $this->semStack[$stackPos-(10-2)], 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-7)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + $this->checkClassMethod($this->semValue, $stackPos-(10-2)); + }, + 347 => function ($stackPos) { + $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 348 => function ($stackPos) { + $this->semValue = new Stmt\EnumCase($this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->semStack[$stackPos-(5-1)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 349 => function ($stackPos) { + $this->semValue = null; /* will be skipped */ + }, + 350 => function ($stackPos) { + $this->semValue = array(); + }, + 351 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 352 => function ($stackPos) { + $this->semValue = array(); + }, + 353 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 354 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 355 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(5-1)][0], $this->semStack[$stackPos-(5-1)][1], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 356 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], $this->semStack[$stackPos-(4-3)], null, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 357 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 358 => function ($stackPos) { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos-(4-1)][0], $this->semStack[$stackPos-(4-1)][1], null, $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 359 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)]); + }, + 360 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 361 => function ($stackPos) { + $this->semValue = array(null, $this->semStack[$stackPos-(1-1)]); + }, + 362 => function ($stackPos) { + $this->semValue = null; + }, + 363 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 364 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 365 => function ($stackPos) { + $this->semValue = 0; + }, + 366 => function ($stackPos) { + $this->semValue = 0; + }, + 367 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 368 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 369 => function ($stackPos) { + $this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)]; + }, + 370 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + }, + 371 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + }, + 372 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + }, + 373 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + }, + 374 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + }, + 375 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + }, + 376 => function ($stackPos) { + $this->semValue = Stmt\Class_::MODIFIER_READONLY; + }, + 377 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 378 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 379 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 380 => function ($stackPos) { + $this->semValue = new Node\VarLikeIdentifier(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 381 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(1-1)], null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 382 => function ($stackPos) { + $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 383 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 384 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 385 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 386 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 387 => function ($stackPos) { + $this->semValue = array(); + }, + 388 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 389 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 390 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 391 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 392 => function ($stackPos) { + $this->semValue = new Expr\Assign($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 393 => function ($stackPos) { + $this->semValue = new Expr\AssignRef($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 394 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 395 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 396 => function ($stackPos) { + $this->semValue = new Expr\Clone_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 397 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 398 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 399 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 400 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 401 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 402 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 403 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 404 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 405 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 406 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 407 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 408 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 409 => function ($stackPos) { + $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 410 => function ($stackPos) { + $this->semValue = new Expr\PostInc($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 411 => function ($stackPos) { + $this->semValue = new Expr\PreInc($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 412 => function ($stackPos) { + $this->semValue = new Expr\PostDec($this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 413 => function ($stackPos) { + $this->semValue = new Expr\PreDec($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 414 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 415 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 416 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 417 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 418 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 419 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 420 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 421 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 422 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 423 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 424 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 425 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 426 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 427 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 428 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 429 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 430 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 431 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 432 => function ($stackPos) { + $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 433 => function ($stackPos) { + $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 434 => function ($stackPos) { + $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 435 => function ($stackPos) { + $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 436 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 437 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 438 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 439 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 440 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 441 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 442 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 443 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 444 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 445 => function ($stackPos) { + $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 446 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 447 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-3)], $this->semStack[$stackPos-(5-5)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 448 => function ($stackPos) { + $this->semValue = new Expr\Ternary($this->semStack[$stackPos-(4-1)], null, $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 449 => function ($stackPos) { + $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 450 => function ($stackPos) { + $this->semValue = new Expr\Isset_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 451 => function ($stackPos) { + $this->semValue = new Expr\Empty_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 452 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 453 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 454 => function ($stackPos) { + $this->semValue = new Expr\Eval_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 455 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 456 => function ($stackPos) { + $this->semValue = new Expr\Include_($this->semStack[$stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 457 => function ($stackPos) { + $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 458 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos-(2-1)]); + $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos-(2-2)], $attrs); + }, + 459 => function ($stackPos) { + $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 460 => function ($stackPos) { + $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 461 => function ($stackPos) { + $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 462 => function ($stackPos) { + $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 463 => function ($stackPos) { + $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 464 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = strtolower($this->semStack[$stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $this->semValue = new Expr\Exit_($this->semStack[$stackPos-(2-2)], $attrs); + }, + 465 => function ($stackPos) { + $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 466 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 467 => function ($stackPos) { + $this->semValue = new Expr\ShellExec($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 468 => function ($stackPos) { + $this->semValue = new Expr\Print_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 469 => function ($stackPos) { + $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 470 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(2-2)], null, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 471 => function ($stackPos) { + $this->semValue = new Expr\Yield_($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-2)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 472 => function ($stackPos) { + $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 473 => function ($stackPos) { + $this->semValue = new Expr\Throw_($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 474 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'returnType' => $this->semStack[$stackPos-(8-6)], 'expr' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 475 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 476 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(8-2)], 'params' => $this->semStack[$stackPos-(8-4)], 'uses' => $this->semStack[$stackPos-(8-6)], 'returnType' => $this->semStack[$stackPos-(8-7)], 'stmts' => $this->semStack[$stackPos-(8-8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes); + }, + 477 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 478 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'returnType' => $this->semStack[$stackPos-(9-7)], 'expr' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 479 => function ($stackPos) { + $this->semValue = new Expr\ArrowFunction(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'returnType' => $this->semStack[$stackPos-(10-8)], 'expr' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 480 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$stackPos-(9-3)], 'params' => $this->semStack[$stackPos-(9-5)], 'uses' => $this->semStack[$stackPos-(9-7)], 'returnType' => $this->semStack[$stackPos-(9-8)], 'stmts' => $this->semStack[$stackPos-(9-9)], 'attrGroups' => $this->semStack[$stackPos-(9-1)]], $this->startAttributeStack[$stackPos-(9-1)] + $this->endAttributes); + }, + 481 => function ($stackPos) { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$stackPos-(10-4)], 'params' => $this->semStack[$stackPos-(10-6)], 'uses' => $this->semStack[$stackPos-(10-8)], 'returnType' => $this->semStack[$stackPos-(10-9)], 'stmts' => $this->semStack[$stackPos-(10-10)], 'attrGroups' => $this->semStack[$stackPos-(10-1)]], $this->startAttributeStack[$stackPos-(10-1)] + $this->endAttributes); + }, + 482 => function ($stackPos) { + $this->semValue = array(new Stmt\Class_(null, ['type' => $this->semStack[$stackPos-(8-2)], 'extends' => $this->semStack[$stackPos-(8-4)], 'implements' => $this->semStack[$stackPos-(8-5)], 'stmts' => $this->semStack[$stackPos-(8-7)], 'attrGroups' => $this->semStack[$stackPos-(8-1)]], $this->startAttributeStack[$stackPos-(8-1)] + $this->endAttributes), $this->semStack[$stackPos-(8-3)]); + $this->checkClass($this->semValue[0], -1); + }, + 483 => function ($stackPos) { + $this->semValue = new Expr\New_($this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 484 => function ($stackPos) { + list($class, $ctorArgs) = $this->semStack[$stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 485 => function ($stackPos) { + $this->semValue = array(); + }, + 486 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(4-3)]; + }, + 487 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 488 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 489 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 490 => function ($stackPos) { + $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos-(2-2)], $this->semStack[$stackPos-(2-1)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 491 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 492 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 493 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 494 => function ($stackPos) { + $this->semValue = new Expr\FuncCall($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 495 => function ($stackPos) { + $this->semValue = new Expr\StaticCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 496 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 497 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 498 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 499 => function ($stackPos) { + $this->semValue = new Name($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 500 => function ($stackPos) { + $this->semValue = new Name\FullyQualified(substr($this->semStack[$stackPos-(1-1)], 1), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 501 => function ($stackPos) { + $this->semValue = new Name\Relative(substr($this->semStack[$stackPos-(1-1)], 10), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 502 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 503 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 504 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 505 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 506 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 507 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 508 => function ($stackPos) { + $this->semValue = null; + }, + 509 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 510 => function ($stackPos) { + $this->semValue = array(); + }, + 511 => function ($stackPos) { + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos-(1-1)], '`'), $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes)); + }, + 512 => function ($stackPos) { + foreach ($this->semStack[$stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 513 => function ($stackPos) { + $this->semValue = array(); + }, + 514 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 515 => function ($stackPos) { + $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 516 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 517 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 518 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 519 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 520 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 521 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 522 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 523 => function ($stackPos) { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 524 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 525 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(5-1)], $this->semStack[$stackPos-(5-4)], $this->startAttributeStack[$stackPos-(5-1)] + $this->endAttributes); + }, + 526 => function ($stackPos) { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)]), $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2; + }, + 527 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(3-2)], $attrs); + }, + 528 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; + $this->semValue = new Expr\Array_($this->semStack[$stackPos-(4-3)], $attrs); + }, + 529 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 530 => function ($stackPos) { + $this->semValue = Scalar\String_::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 531 => function ($stackPos) { + $attrs = $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + foreach ($this->semStack[$stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos-(3-2)], $attrs); + }, + 532 => function ($stackPos) { + $this->semValue = $this->parseLNumber($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 533 => function ($stackPos) { + $this->semValue = Scalar\DNumber::fromString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 534 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 535 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 536 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 537 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); + }, + 538 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(2-1)], '', $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(2-2)] + $this->endAttributeStack[$stackPos-(2-2)], true); + }, + 539 => function ($stackPos) { + $this->semValue = $this->parseDocString($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-2)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes, $this->startAttributeStack[$stackPos-(3-3)] + $this->endAttributeStack[$stackPos-(3-3)], true); + }, + 540 => function ($stackPos) { + $this->semValue = null; + }, + 541 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 542 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 543 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 544 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 545 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 546 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 547 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 548 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 549 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 550 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 551 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 552 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 553 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 554 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 555 => function ($stackPos) { + $this->semValue = new Expr\MethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 556 => function ($stackPos) { + $this->semValue = new Expr\NullsafeMethodCall($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->semStack[$stackPos-(4-4)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 557 => function ($stackPos) { + $this->semValue = null; + }, + 558 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 559 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 560 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 561 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 562 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 563 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 564 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 565 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 566 => function ($stackPos) { + $this->semValue = new Expr\Variable(new Expr\Error($this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes), $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2; + }, + 567 => function ($stackPos) { + $var = $this->semStack[$stackPos-(1-1)]->name; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes) : $var; + }, + 568 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 569 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 570 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 571 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 572 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 573 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 574 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 575 => function ($stackPos) { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 576 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 577 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 578 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 579 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 580 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 581 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 582 => function ($stackPos) { + $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + }, + 583 => function ($stackPos) { + $this->semValue = new Expr\List_($this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 584 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) array_pop($this->semValue); + }, + 585 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos]; + }, + 586 => function ($stackPos) { + /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */ + }, + 587 => function ($stackPos) { + $this->semStack[$stackPos-(3-1)][] = $this->semStack[$stackPos-(3-3)]; $this->semValue = $this->semStack[$stackPos-(3-1)]; + }, + 588 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 589 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 590 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, true, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 591 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(1-1)], null, false, $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 592 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 593 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(4-4)], $this->semStack[$stackPos-(4-1)], true, $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 594 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(3-3)], $this->semStack[$stackPos-(3-1)], false, $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 595 => function ($stackPos) { + $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos-(2-2)], null, false, $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes, true); + }, + 596 => function ($stackPos) { + $this->semValue = null; + }, + 597 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 598 => function ($stackPos) { + $this->semStack[$stackPos-(2-1)][] = $this->semStack[$stackPos-(2-2)]; $this->semValue = $this->semStack[$stackPos-(2-1)]; + }, + 599 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(1-1)]); + }, + 600 => function ($stackPos) { + $this->semValue = array($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)]); + }, + 601 => function ($stackPos) { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 602 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 603 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + 604 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(4-1)], $this->semStack[$stackPos-(4-3)], $this->startAttributeStack[$stackPos-(4-1)] + $this->endAttributes); + }, + 605 => function ($stackPos) { + $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 606 => function ($stackPos) { + $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos-(3-1)], $this->semStack[$stackPos-(3-3)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 607 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 608 => function ($stackPos) { + $this->semValue = new Expr\Variable($this->semStack[$stackPos-(3-2)], $this->startAttributeStack[$stackPos-(3-1)] + $this->endAttributes); + }, + 609 => function ($stackPos) { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos-(6-2)], $this->semStack[$stackPos-(6-4)], $this->startAttributeStack[$stackPos-(6-1)] + $this->endAttributes); + }, + 610 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(3-2)]; + }, + 611 => function ($stackPos) { + $this->semValue = new Scalar\String_($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 612 => function ($stackPos) { + $this->semValue = $this->parseNumString($this->semStack[$stackPos-(1-1)], $this->startAttributeStack[$stackPos-(1-1)] + $this->endAttributes); + }, + 613 => function ($stackPos) { + $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos-(2-2)], $this->startAttributeStack[$stackPos-(2-1)] + $this->endAttributes); + }, + 614 => function ($stackPos) { + $this->semValue = $this->semStack[$stackPos-(1-1)]; + }, + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php new file mode 100644 index 000000000..b76a5d94c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php @@ -0,0 +1,148 @@ +lexer = $lexer; + + if (isset($options['throwOnError'])) { + throw new \LogicException( + '"throwOnError" is no longer supported, use "errorHandler" instead'); + } + + $this->initReduceCallbacks(); + } + + /** + * Parses PHP code into a node tree. + * + * If a non-throwing error handler is used, the parser will continue parsing after an error + * occurred and attempt to build a partial AST. + * + * @param string $code The source code to parse + * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults + * to ErrorHandler\Throwing. + * + * @return Node\Stmt[]|null Array of statements (or null non-throwing error handler is used and + * the parser was unable to recover from an error). + */ + public function parse(string $code, ?ErrorHandler $errorHandler = null) { + $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; + + $this->lexer->startLexing($code, $this->errorHandler); + $result = $this->doParse(); + + // Clear out some of the interior state, so we don't hold onto unnecessary + // memory between uses of the parser + $this->startAttributeStack = []; + $this->endAttributeStack = []; + $this->semStack = []; + $this->semValue = null; + + return $result; + } + + protected function doParse() { + // We start off with no lookahead-token + $symbol = self::SYMBOL_NONE; + + // The attributes for a node are taken from the first and last token of the node. + // From the first token only the startAttributes are taken and from the last only + // the endAttributes. Both are merged using the array union operator (+). + $startAttributes = []; + $endAttributes = []; + $this->endAttributes = $endAttributes; + + // Keep stack of start and end attributes + $this->startAttributeStack = []; + $this->endAttributeStack = [$endAttributes]; + + // Start off in the initial state and keep a stack of previous states + $state = 0; + $stateStack = [$state]; + + // Semantic value stack (contains values of tokens and semantic action results) + $this->semStack = []; + + // Current position in the stack(s) + $stackPos = 0; + + $this->errorState = 0; + + for (;;) { + //$this->traceNewState($state, $symbol); + + if ($this->actionBase[$state] === 0) { + $rule = $this->actionDefault[$state]; + } else { + if ($symbol === self::SYMBOL_NONE) { + // Fetch the next token id from the lexer and fetch additional info by-ref. + // The end attributes are fetched into a temporary variable and only set once the token is really + // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is + // reduced after a token was read but not yet shifted. + $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); + + // map the lexer token id to the internally used symbols + $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize + ? $this->tokenToSymbol[$tokenId] + : $this->invalidSymbol; + + if ($symbol === $this->invalidSymbol) { + throw new \RangeException(sprintf( + 'The lexer returned an invalid token (id=%d, value=%s)', + $tokenId, $tokenValue + )); + } + + // Allow productions to access the start attributes of the lookahead token. + $this->lookaheadStartAttributes = $startAttributes; + + //$this->traceRead($symbol); + } + + $idx = $this->actionBase[$state] + $symbol; + if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) + || ($state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol)) + && ($action = $this->action[$idx]) !== $this->defaultAction) { + /* + * >= numNonLeafStates: shift and reduce + * > 0: shift + * = 0: accept + * < 0: reduce + * = -YYUNEXPECTED: error + */ + if ($action > 0) { + /* shift */ + //$this->traceShift($symbol); + + ++$stackPos; + $stateStack[$stackPos] = $state = $action; + $this->semStack[$stackPos] = $tokenValue; + $this->startAttributeStack[$stackPos] = $startAttributes; + $this->endAttributeStack[$stackPos] = $endAttributes; + $this->endAttributes = $endAttributes; + $symbol = self::SYMBOL_NONE; + + if ($this->errorState) { + --$this->errorState; + } + + if ($action < $this->numNonLeafStates) { + continue; + } + + /* $yyn >= numNonLeafStates means shift-and-reduce */ + $rule = $action - $this->numNonLeafStates; + } else { + $rule = -$action; + } + } else { + $rule = $this->actionDefault[$state]; + } + } + + for (;;) { + if ($rule === 0) { + /* accept */ + //$this->traceAccept(); + return $this->semValue; + } elseif ($rule !== $this->unexpectedTokenRule) { + /* reduce */ + //$this->traceReduce($rule); + + try { + $this->reduceCallbacks[$rule]($stackPos); + } catch (Error $e) { + if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { + $e->setStartLine($startAttributes['startLine']); + } + + $this->emitError($e); + // Can't recover from this type of error + return null; + } + + /* Goto - shift nonterminal */ + $lastEndAttributes = $this->endAttributeStack[$stackPos]; + $ruleLength = $this->ruleToLength[$rule]; + $stackPos -= $ruleLength; + $nonTerminal = $this->ruleToNonTerminal[$rule]; + $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos]; + if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) { + $state = $this->goto[$idx]; + } else { + $state = $this->gotoDefault[$nonTerminal]; + } + + ++$stackPos; + $stateStack[$stackPos] = $state; + $this->semStack[$stackPos] = $this->semValue; + $this->endAttributeStack[$stackPos] = $lastEndAttributes; + if ($ruleLength === 0) { + // Empty productions use the start attributes of the lookahead token. + $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; + } + } else { + /* error */ + switch ($this->errorState) { + case 0: + $msg = $this->getErrorMessage($symbol, $state); + $this->emitError(new Error($msg, $startAttributes + $endAttributes)); + // Break missing intentionally + case 1: + case 2: + $this->errorState = 3; + + // Pop until error-expecting state uncovered + while (!( + (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) + || ($state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) + ) || ($action = $this->action[$idx]) === $this->defaultAction) { // Not totally sure about this + if ($stackPos <= 0) { + // Could not recover from error + return null; + } + $state = $stateStack[--$stackPos]; + //$this->tracePop($state); + } + + //$this->traceShift($this->errorSymbol); + ++$stackPos; + $stateStack[$stackPos] = $state = $action; + + // We treat the error symbol as being empty, so we reset the end attributes + // to the end attributes of the last non-error symbol + $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes; + $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1]; + $this->endAttributes = $this->endAttributeStack[$stackPos - 1]; + break; + + case 3: + if ($symbol === 0) { + // Reached EOF without recovering from error + return null; + } + + //$this->traceDiscard($symbol); + $symbol = self::SYMBOL_NONE; + break 2; + } + } + + if ($state < $this->numNonLeafStates) { + break; + } + + /* >= numNonLeafStates means shift-and-reduce */ + $rule = $state - $this->numNonLeafStates; + } + } + + throw new \RuntimeException('Reached end of parser loop'); + } + + protected function emitError(Error $error) { + $this->errorHandler->handleError($error); + } + + /** + * Format error message including expected tokens. + * + * @param int $symbol Unexpected symbol + * @param int $state State at time of error + * + * @return string Formatted error message + */ + protected function getErrorMessage(int $symbol, int $state) : string { + $expectedString = ''; + if ($expected = $this->getExpectedTokens($state)) { + $expectedString = ', expecting ' . implode(' or ', $expected); + } + + return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; + } + + /** + * Get limited number of expected tokens in given state. + * + * @param int $state State + * + * @return string[] Expected tokens. If too many, an empty array is returned. + */ + protected function getExpectedTokens(int $state) : array { + $expected = []; + + $base = $this->actionBase[$state]; + foreach ($this->symbolToName as $symbol => $name) { + $idx = $base + $symbol; + if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol + || $state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol + ) { + if ($this->action[$idx] !== $this->unexpectedTokenRule + && $this->action[$idx] !== $this->defaultAction + && $symbol !== $this->errorSymbol + ) { + if (count($expected) === 4) { + /* Too many expected tokens */ + return []; + } + + $expected[] = $name; + } + } + } + + return $expected; + } + + /* + * Tracing functions used for debugging the parser. + */ + + /* + protected function traceNewState($state, $symbol) { + echo '% State ' . $state + . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; + } + + protected function traceRead($symbol) { + echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; + } + + protected function traceShift($symbol) { + echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; + } + + protected function traceAccept() { + echo "% Accepted.\n"; + } + + protected function traceReduce($n) { + echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; + } + + protected function tracePop($state) { + echo '% Recovering, uncovered state ' . $state . "\n"; + } + + protected function traceDiscard($symbol) { + echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; + } + */ + + /* + * Helper functions invoked by semantic actions + */ + + /** + * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. + * + * @param Node\Stmt[] $stmts + * @return Node\Stmt[] + */ + protected function handleNamespaces(array $stmts) : array { + $hasErrored = false; + $style = $this->getNamespacingStyle($stmts); + if (null === $style) { + // not namespaced, nothing to do + return $stmts; + } elseif ('brace' === $style) { + // For braced namespaces we only have to check that there are no invalid statements between the namespaces + $afterFirstNamespace = false; + foreach ($stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + $afterFirstNamespace = true; + } elseif (!$stmt instanceof Node\Stmt\HaltCompiler + && !$stmt instanceof Node\Stmt\Nop + && $afterFirstNamespace && !$hasErrored) { + $this->emitError(new Error( + 'No code may exist outside of namespace {}', $stmt->getAttributes())); + $hasErrored = true; // Avoid one error for every statement + } + } + return $stmts; + } else { + // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts + $resultStmts = []; + $targetStmts =& $resultStmts; + $lastNs = null; + foreach ($stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + if ($lastNs !== null) { + $this->fixupNamespaceAttributes($lastNs); + } + if ($stmt->stmts === null) { + $stmt->stmts = []; + $targetStmts =& $stmt->stmts; + $resultStmts[] = $stmt; + } else { + // This handles the invalid case of mixed style namespaces + $resultStmts[] = $stmt; + $targetStmts =& $resultStmts; + } + $lastNs = $stmt; + } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { + // __halt_compiler() is not moved into the namespace + $resultStmts[] = $stmt; + } else { + $targetStmts[] = $stmt; + } + } + if ($lastNs !== null) { + $this->fixupNamespaceAttributes($lastNs); + } + return $resultStmts; + } + } + + private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt) { + // We moved the statements into the namespace node, as such the end of the namespace node + // needs to be extended to the end of the statements. + if (empty($stmt->stmts)) { + return; + } + + // We only move the builtin end attributes here. This is the best we can do with the + // knowledge we have. + $endAttributes = ['endLine', 'endFilePos', 'endTokenPos']; + $lastStmt = $stmt->stmts[count($stmt->stmts) - 1]; + foreach ($endAttributes as $endAttribute) { + if ($lastStmt->hasAttribute($endAttribute)) { + $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute)); + } + } + } + + /** + * Determine namespacing style (semicolon or brace) + * + * @param Node[] $stmts Top-level statements. + * + * @return null|string One of "semicolon", "brace" or null (no namespaces) + */ + private function getNamespacingStyle(array $stmts) { + $style = null; + $hasNotAllowedStmts = false; + foreach ($stmts as $i => $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; + if (null === $style) { + $style = $currentStyle; + if ($hasNotAllowedStmts) { + $this->emitError(new Error( + 'Namespace declaration statement has to be the very first statement in the script', + $stmt->getLine() // Avoid marking the entire namespace as an error + )); + } + } elseif ($style !== $currentStyle) { + $this->emitError(new Error( + 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', + $stmt->getLine() // Avoid marking the entire namespace as an error + )); + // Treat like semicolon style for namespace normalization + return 'semicolon'; + } + continue; + } + + /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ + if ($stmt instanceof Node\Stmt\Declare_ + || $stmt instanceof Node\Stmt\HaltCompiler + || $stmt instanceof Node\Stmt\Nop) { + continue; + } + + /* There may be a hashbang line at the very start of the file */ + if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) { + continue; + } + + /* Everything else if forbidden before namespace declarations */ + $hasNotAllowedStmts = true; + } + return $style; + } + + /** + * Fix up parsing of static property calls in PHP 5. + * + * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is + * interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the + * latter as the former initially and this method fixes the AST into the correct form when we + * encounter the "()". + * + * @param Node\Expr\StaticPropertyFetch|Node\Expr\ArrayDimFetch $prop + * @param Node\Arg[] $args + * @param array $attributes + * + * @return Expr\StaticCall + */ + protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : Expr\StaticCall { + if ($prop instanceof Node\Expr\StaticPropertyFetch) { + $name = $prop->name instanceof VarLikeIdentifier + ? $prop->name->toString() : $prop->name; + $var = new Expr\Variable($name, $prop->name->getAttributes()); + return new Expr\StaticCall($prop->class, $var, $args, $attributes); + } elseif ($prop instanceof Node\Expr\ArrayDimFetch) { + $tmp = $prop; + while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { + $tmp = $tmp->var; + } + + /** @var Expr\StaticPropertyFetch $staticProp */ + $staticProp = $tmp->var; + + // Set start attributes to attributes of innermost node + $tmp = $prop; + $this->fixupStartAttributes($tmp, $staticProp->name); + while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { + $tmp = $tmp->var; + $this->fixupStartAttributes($tmp, $staticProp->name); + } + + $name = $staticProp->name instanceof VarLikeIdentifier + ? $staticProp->name->toString() : $staticProp->name; + $tmp->var = new Expr\Variable($name, $staticProp->name->getAttributes()); + return new Expr\StaticCall($staticProp->class, $prop, $args, $attributes); + } else { + throw new \Exception; + } + } + + protected function fixupStartAttributes(Node $to, Node $from) { + $startAttributes = ['startLine', 'startFilePos', 'startTokenPos']; + foreach ($startAttributes as $startAttribute) { + if ($from->hasAttribute($startAttribute)) { + $to->setAttribute($startAttribute, $from->getAttribute($startAttribute)); + } + } + } + + protected function handleBuiltinTypes(Name $name) { + $builtinTypes = [ + 'bool' => true, + 'int' => true, + 'float' => true, + 'string' => true, + 'iterable' => true, + 'void' => true, + 'object' => true, + 'null' => true, + 'false' => true, + 'mixed' => true, + 'never' => true, + 'true' => true, + ]; + + if (!$name->isUnqualified()) { + return $name; + } + + $lowerName = $name->toLowerString(); + if (!isset($builtinTypes[$lowerName])) { + return $name; + } + + return new Node\Identifier($lowerName, $name->getAttributes()); + } + + /** + * Get combined start and end attributes at a stack location + * + * @param int $pos Stack location + * + * @return array Combined start and end attributes + */ + protected function getAttributesAt(int $pos) : array { + return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; + } + + protected function getFloatCastKind(string $cast): int + { + $cast = strtolower($cast); + if (strpos($cast, 'float') !== false) { + return Double::KIND_FLOAT; + } + + if (strpos($cast, 'real') !== false) { + return Double::KIND_REAL; + } + + return Double::KIND_DOUBLE; + } + + protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { + try { + return LNumber::fromString($str, $attributes, $allowInvalidOctal); + } catch (Error $error) { + $this->emitError($error); + // Use dummy value + return new LNumber(0, $attributes); + } + } + + /** + * Parse a T_NUM_STRING token into either an integer or string node. + * + * @param string $str Number string + * @param array $attributes Attributes + * + * @return LNumber|String_ Integer or string node. + */ + protected function parseNumString(string $str, array $attributes) { + if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { + return new String_($str, $attributes); + } + + $num = +$str; + if (!is_int($num)) { + return new String_($str, $attributes); + } + + return new LNumber($num, $attributes); + } + + protected function stripIndentation( + string $string, int $indentLen, string $indentChar, + bool $newlineAtStart, bool $newlineAtEnd, array $attributes + ) { + if ($indentLen === 0) { + return $string; + } + + $start = $newlineAtStart ? '(?:(?<=\n)|\A)' : '(?<=\n)'; + $end = $newlineAtEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])'; + $regex = '/' . $start . '([ \t]*)(' . $end . ')?/'; + return preg_replace_callback( + $regex, + function ($matches) use ($indentLen, $indentChar, $attributes) { + $prefix = substr($matches[1], 0, $indentLen); + if (false !== strpos($prefix, $indentChar === " " ? "\t" : " ")) { + $this->emitError(new Error( + 'Invalid indentation - tabs and spaces cannot be mixed', $attributes + )); + } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) { + $this->emitError(new Error( + 'Invalid body indentation level ' . + '(expecting an indentation level of at least ' . $indentLen . ')', + $attributes + )); + } + return substr($matches[0], strlen($prefix)); + }, + $string + ); + } + + protected function parseDocString( + string $startToken, $contents, string $endToken, + array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape + ) { + $kind = strpos($startToken, "'") === false + ? String_::KIND_HEREDOC : String_::KIND_NOWDOC; + + $regex = '/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/'; + $result = preg_match($regex, $startToken, $matches); + assert($result === 1); + $label = $matches[1]; + + $result = preg_match('/\A[ \t]*/', $endToken, $matches); + assert($result === 1); + $indentation = $matches[0]; + + $attributes['kind'] = $kind; + $attributes['docLabel'] = $label; + $attributes['docIndentation'] = $indentation; + + $indentHasSpaces = false !== strpos($indentation, " "); + $indentHasTabs = false !== strpos($indentation, "\t"); + if ($indentHasSpaces && $indentHasTabs) { + $this->emitError(new Error( + 'Invalid indentation - tabs and spaces cannot be mixed', + $endTokenAttributes + )); + + // Proceed processing as if this doc string is not indented + $indentation = ''; + } + + $indentLen = \strlen($indentation); + $indentChar = $indentHasSpaces ? " " : "\t"; + + if (\is_string($contents)) { + if ($contents === '') { + return new String_('', $attributes); + } + + $contents = $this->stripIndentation( + $contents, $indentLen, $indentChar, true, true, $attributes + ); + $contents = preg_replace('~(\r\n|\n|\r)\z~', '', $contents); + + if ($kind === String_::KIND_HEREDOC) { + $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape); + } + + return new String_($contents, $attributes); + } else { + assert(count($contents) > 0); + if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) { + // If there is no leading encapsed string part, pretend there is an empty one + $this->stripIndentation( + '', $indentLen, $indentChar, true, false, $contents[0]->getAttributes() + ); + } + + $newContents = []; + foreach ($contents as $i => $part) { + if ($part instanceof Node\Scalar\EncapsedStringPart) { + $isLast = $i === \count($contents) - 1; + $part->value = $this->stripIndentation( + $part->value, $indentLen, $indentChar, + $i === 0, $isLast, $part->getAttributes() + ); + $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape); + if ($isLast) { + $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value); + } + if ('' === $part->value) { + continue; + } + } + $newContents[] = $part; + } + return new Encapsed($newContents, $attributes); + } + } + + /** + * Create attributes for a zero-length common-capturing nop. + * + * @param Comment[] $comments + * @return array + */ + protected function createCommentNopAttributes(array $comments) { + $comment = $comments[count($comments) - 1]; + $commentEndLine = $comment->getEndLine(); + $commentEndFilePos = $comment->getEndFilePos(); + $commentEndTokenPos = $comment->getEndTokenPos(); + + $attributes = ['comments' => $comments]; + if (-1 !== $commentEndLine) { + $attributes['startLine'] = $commentEndLine; + $attributes['endLine'] = $commentEndLine; + } + if (-1 !== $commentEndFilePos) { + $attributes['startFilePos'] = $commentEndFilePos + 1; + $attributes['endFilePos'] = $commentEndFilePos; + } + if (-1 !== $commentEndTokenPos) { + $attributes['startTokenPos'] = $commentEndTokenPos + 1; + $attributes['endTokenPos'] = $commentEndTokenPos; + } + return $attributes; + } + + /** @param ElseIf_|Else_ $node */ + protected function fixupAlternativeElse($node) { + // Make sure a trailing nop statement carrying comments is part of the node. + $numStmts = \count($node->stmts); + if ($numStmts !== 0 && $node->stmts[$numStmts - 1] instanceof Nop) { + $nopAttrs = $node->stmts[$numStmts - 1]->getAttributes(); + if (isset($nopAttrs['endLine'])) { + $node->setAttribute('endLine', $nopAttrs['endLine']); + } + if (isset($nopAttrs['endFilePos'])) { + $node->setAttribute('endFilePos', $nopAttrs['endFilePos']); + } + if (isset($nopAttrs['endTokenPos'])) { + $node->setAttribute('endTokenPos', $nopAttrs['endTokenPos']); + } + } + } + + protected function checkClassModifier($a, $b, $modifierPos) { + try { + Class_::verifyClassModifier($a, $b); + } catch (Error $error) { + $error->setAttributes($this->getAttributesAt($modifierPos)); + $this->emitError($error); + } + } + + protected function checkModifier($a, $b, $modifierPos) { + // Jumping through some hoops here because verifyModifier() is also used elsewhere + try { + Class_::verifyModifier($a, $b); + } catch (Error $error) { + $error->setAttributes($this->getAttributesAt($modifierPos)); + $this->emitError($error); + } + } + + protected function checkParam(Param $node) { + if ($node->variadic && null !== $node->default) { + $this->emitError(new Error( + 'Variadic parameter cannot have a default value', + $node->default->getAttributes() + )); + } + } + + protected function checkTryCatch(TryCatch $node) { + if (empty($node->catches) && null === $node->finally) { + $this->emitError(new Error( + 'Cannot use try without catch or finally', $node->getAttributes() + )); + } + } + + protected function checkNamespace(Namespace_ $node) { + if (null !== $node->stmts) { + foreach ($node->stmts as $stmt) { + if ($stmt instanceof Namespace_) { + $this->emitError(new Error( + 'Namespace declarations cannot be nested', $stmt->getAttributes() + )); + } + } + } + } + + private function checkClassName($name, $namePos) { + if (null !== $name && $name->isSpecialClassName()) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $name), + $this->getAttributesAt($namePos) + )); + } + } + + private function checkImplementedInterfaces(array $interfaces) { + foreach ($interfaces as $interface) { + if ($interface->isSpecialClassName()) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), + $interface->getAttributes() + )); + } + } + } + + protected function checkClass(Class_ $node, $namePos) { + $this->checkClassName($node->name, $namePos); + + if ($node->extends && $node->extends->isSpecialClassName()) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), + $node->extends->getAttributes() + )); + } + + $this->checkImplementedInterfaces($node->implements); + } + + protected function checkInterface(Interface_ $node, $namePos) { + $this->checkClassName($node->name, $namePos); + $this->checkImplementedInterfaces($node->extends); + } + + protected function checkEnum(Enum_ $node, $namePos) { + $this->checkClassName($node->name, $namePos); + $this->checkImplementedInterfaces($node->implements); + } + + protected function checkClassMethod(ClassMethod $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_STATIC) { + switch ($node->name->toLowerString()) { + case '__construct': + $this->emitError(new Error( + sprintf('Constructor %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + case '__destruct': + $this->emitError(new Error( + sprintf('Destructor %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + case '__clone': + $this->emitError(new Error( + sprintf('Clone method %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + } + } + + if ($node->flags & Class_::MODIFIER_READONLY) { + $this->emitError(new Error( + sprintf('Method %s() cannot be readonly', $node->name), + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkClassConst(ClassConst $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_STATIC) { + $this->emitError(new Error( + "Cannot use 'static' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + if ($node->flags & Class_::MODIFIER_ABSTRACT) { + $this->emitError(new Error( + "Cannot use 'abstract' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + if ($node->flags & Class_::MODIFIER_READONLY) { + $this->emitError(new Error( + "Cannot use 'readonly' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkProperty(Property $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_ABSTRACT) { + $this->emitError(new Error('Properties cannot be declared abstract', + $this->getAttributesAt($modifierPos))); + } + + if ($node->flags & Class_::MODIFIER_FINAL) { + $this->emitError(new Error('Properties cannot be declared final', + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkUseUse(UseUse $node, $namePos) { + if ($node->alias && $node->alias->isSpecialClassName()) { + $this->emitError(new Error( + sprintf( + 'Cannot use %s as %s because \'%2$s\' is a special class name', + $node->name, $node->alias + ), + $this->getAttributesAt($namePos) + )); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php new file mode 100644 index 000000000..98b0aee34 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php @@ -0,0 +1,76 @@ +getLexerOptions())); + } + + /** + * Create a parser targeting the host PHP version, that is the PHP version we're currently + * running on. This parser will not use any token emulation. + * + * All supported lexer attributes (comments, startLine, endLine, startTokenPos, endTokenPos, + * startFilePos, endFilePos) will be enabled. + */ + public function createForHostVersion(): Parser { + return new Php7(new Lexer($this->getLexerOptions())); + } + + private function getLexerOptions(): array { + return ['usedAttributes' => [ + 'comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos', 'startFilePos', 'endFilePos', + ]]; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php new file mode 100644 index 000000000..7c32e5a3c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php @@ -0,0 +1,1126 @@ +pAttrGroups($node->attrGroups, true) + . $this->pModifiers($node->flags) + . ($node->type ? $this->p($node->type) . ' ' : '') + . ($node->byRef ? '&' : '') + . ($node->variadic ? '...' : '') + . $this->p($node->var) + . ($node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pArg(Node\Arg $node) { + return ($node->name ? $node->name->toString() . ': ' : '') + . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') + . $this->p($node->value); + } + + protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node) { + return '...'; + } + + protected function pConst(Node\Const_ $node) { + return $node->name . ' = ' . $this->p($node->value); + } + + protected function pNullableType(Node\NullableType $node) { + return '?' . $this->p($node->type); + } + + protected function pUnionType(Node\UnionType $node) { + $types = []; + foreach ($node->types as $typeNode) { + if ($typeNode instanceof Node\IntersectionType) { + $types[] = '('. $this->p($typeNode) . ')'; + continue; + } + $types[] = $this->p($typeNode); + } + return implode('|', $types); + } + + protected function pIntersectionType(Node\IntersectionType $node) { + return $this->pImplode($node->types, '&'); + } + + protected function pIdentifier(Node\Identifier $node) { + return $node->name; + } + + protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node) { + return '$' . $node->name; + } + + protected function pAttribute(Node\Attribute $node) { + return $this->p($node->name) + . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : ''); + } + + protected function pAttributeGroup(Node\AttributeGroup $node) { + return '#[' . $this->pCommaSeparated($node->attrs) . ']'; + } + + // Names + + protected function pName(Name $node) { + return implode('\\', $node->parts); + } + + protected function pName_FullyQualified(Name\FullyQualified $node) { + return '\\' . implode('\\', $node->parts); + } + + protected function pName_Relative(Name\Relative $node) { + return 'namespace\\' . implode('\\', $node->parts); + } + + // Magic Constants + + protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) { + return '__CLASS__'; + } + + protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) { + return '__DIR__'; + } + + protected function pScalar_MagicConst_File(MagicConst\File $node) { + return '__FILE__'; + } + + protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) { + return '__FUNCTION__'; + } + + protected function pScalar_MagicConst_Line(MagicConst\Line $node) { + return '__LINE__'; + } + + protected function pScalar_MagicConst_Method(MagicConst\Method $node) { + return '__METHOD__'; + } + + protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { + return '__NAMESPACE__'; + } + + protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { + return '__TRAIT__'; + } + + // Scalars + + protected function pScalar_String(Scalar\String_ $node) { + $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); + switch ($kind) { + case Scalar\String_::KIND_NOWDOC: + $label = $node->getAttribute('docLabel'); + if ($label && !$this->containsEndLabel($node->value, $label)) { + if ($node->value === '') { + return "<<<'$label'\n$label" . $this->docStringEndToken; + } + + return "<<<'$label'\n$node->value\n$label" + . $this->docStringEndToken; + } + /* break missing intentionally */ + case Scalar\String_::KIND_SINGLE_QUOTED: + return $this->pSingleQuotedString($node->value); + case Scalar\String_::KIND_HEREDOC: + $label = $node->getAttribute('docLabel'); + if ($label && !$this->containsEndLabel($node->value, $label)) { + if ($node->value === '') { + return "<<<$label\n$label" . $this->docStringEndToken; + } + + $escaped = $this->escapeString($node->value, null); + return "<<<$label\n" . $escaped . "\n$label" + . $this->docStringEndToken; + } + /* break missing intentionally */ + case Scalar\String_::KIND_DOUBLE_QUOTED: + return '"' . $this->escapeString($node->value, '"') . '"'; + } + throw new \Exception('Invalid string kind'); + } + + protected function pScalar_Encapsed(Scalar\Encapsed $node) { + if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { + $label = $node->getAttribute('docLabel'); + if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { + if (count($node->parts) === 1 + && $node->parts[0] instanceof Scalar\EncapsedStringPart + && $node->parts[0]->value === '' + ) { + return "<<<$label\n$label" . $this->docStringEndToken; + } + + return "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label" + . $this->docStringEndToken; + } + } + return '"' . $this->pEncapsList($node->parts, '"') . '"'; + } + + protected function pScalar_LNumber(Scalar\LNumber $node) { + if ($node->value === -\PHP_INT_MAX-1) { + // PHP_INT_MIN cannot be represented as a literal, + // because the sign is not part of the literal + return '(-' . \PHP_INT_MAX . '-1)'; + } + + $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC); + if (Scalar\LNumber::KIND_DEC === $kind) { + return (string) $node->value; + } + + if ($node->value < 0) { + $sign = '-'; + $str = (string) -$node->value; + } else { + $sign = ''; + $str = (string) $node->value; + } + switch ($kind) { + case Scalar\LNumber::KIND_BIN: + return $sign . '0b' . base_convert($str, 10, 2); + case Scalar\LNumber::KIND_OCT: + return $sign . '0' . base_convert($str, 10, 8); + case Scalar\LNumber::KIND_HEX: + return $sign . '0x' . base_convert($str, 10, 16); + } + throw new \Exception('Invalid number kind'); + } + + protected function pScalar_DNumber(Scalar\DNumber $node) { + if (!is_finite($node->value)) { + if ($node->value === \INF) { + return '\INF'; + } elseif ($node->value === -\INF) { + return '-\INF'; + } else { + return '\NAN'; + } + } + + // Try to find a short full-precision representation + $stringValue = sprintf('%.16G', $node->value); + if ($node->value !== (double) $stringValue) { + $stringValue = sprintf('%.17G', $node->value); + } + + // %G is locale dependent and there exists no locale-independent alternative. We don't want + // mess with switching locales here, so let's assume that a comma is the only non-standard + // decimal separator we may encounter... + $stringValue = str_replace(',', '.', $stringValue); + + // ensure that number is really printed as float + return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; + } + + protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node) { + throw new \LogicException('Cannot directly print EncapsedStringPart'); + } + + // Assignments + + protected function pExpr_Assign(Expr\Assign $node) { + return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr); + } + + protected function pExpr_AssignRef(Expr\AssignRef $node) { + return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr); + } + + protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { + return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr); + } + + protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { + return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr); + } + + protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { + return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr); + } + + protected function pExpr_AssignOp_Div(AssignOp\Div $node) { + return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr); + } + + protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { + return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr); + } + + protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { + return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { + return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { + return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { + return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr); + } + + protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { + return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr); + } + + protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { + return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr); + } + + protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { + return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr); + } + + protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node) { + return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr); + } + + // Binary expressions + + protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { + return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right); + } + + protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { + return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right); + } + + protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { + return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right); + } + + protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) { + return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right); + } + + protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { + return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right); + } + + protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { + return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right); + } + + protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { + return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right); + } + + protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { + return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { + return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { + return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { + return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right); + } + + protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { + return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right); + } + + protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { + return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right); + } + + protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { + return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { + return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { + return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { + return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right); + } + + protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { + return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right); + } + + protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { + return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right); + } + + protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { + return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right); + } + + protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { + return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right); + } + + protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { + return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right); + } + + protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { + return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right); + } + + protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { + return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right); + } + + protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { + return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right); + } + + protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { + return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right); + } + + protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { + return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right); + } + + protected function pExpr_Instanceof(Expr\Instanceof_ $node) { + list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class]; + return $this->pPrec($node->expr, $precedence, $associativity, -1) + . ' instanceof ' + . $this->pNewVariable($node->class); + } + + // Unary expressions + + protected function pExpr_BooleanNot(Expr\BooleanNot $node) { + return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr); + } + + protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) { + return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr); + } + + protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) { + if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) { + // Enforce -(-$expr) instead of --$expr + return '-(' . $this->p($node->expr) . ')'; + } + return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr); + } + + protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) { + if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) { + // Enforce +(+$expr) instead of ++$expr + return '+(' . $this->p($node->expr) . ')'; + } + return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr); + } + + protected function pExpr_PreInc(Expr\PreInc $node) { + return $this->pPrefixOp(Expr\PreInc::class, '++', $node->var); + } + + protected function pExpr_PreDec(Expr\PreDec $node) { + return $this->pPrefixOp(Expr\PreDec::class, '--', $node->var); + } + + protected function pExpr_PostInc(Expr\PostInc $node) { + return $this->pPostfixOp(Expr\PostInc::class, $node->var, '++'); + } + + protected function pExpr_PostDec(Expr\PostDec $node) { + return $this->pPostfixOp(Expr\PostDec::class, $node->var, '--'); + } + + protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { + return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr); + } + + protected function pExpr_YieldFrom(Expr\YieldFrom $node) { + return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr); + } + + protected function pExpr_Print(Expr\Print_ $node) { + return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr); + } + + // Casts + + protected function pExpr_Cast_Int(Cast\Int_ $node) { + return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr); + } + + protected function pExpr_Cast_Double(Cast\Double $node) { + $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE); + if ($kind === Cast\Double::KIND_DOUBLE) { + $cast = '(double)'; + } elseif ($kind === Cast\Double::KIND_FLOAT) { + $cast = '(float)'; + } elseif ($kind === Cast\Double::KIND_REAL) { + $cast = '(real)'; + } + return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr); + } + + protected function pExpr_Cast_String(Cast\String_ $node) { + return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr); + } + + protected function pExpr_Cast_Array(Cast\Array_ $node) { + return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr); + } + + protected function pExpr_Cast_Object(Cast\Object_ $node) { + return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr); + } + + protected function pExpr_Cast_Bool(Cast\Bool_ $node) { + return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr); + } + + protected function pExpr_Cast_Unset(Cast\Unset_ $node) { + return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr); + } + + // Function calls and similar constructs + + protected function pExpr_FuncCall(Expr\FuncCall $node) { + return $this->pCallLhs($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_MethodCall(Expr\MethodCall $node) { + return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node) { + return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_StaticCall(Expr\StaticCall $node) { + return $this->pStaticDereferenceLhs($node->class) . '::' + . ($node->name instanceof Expr + ? ($node->name instanceof Expr\Variable + ? $this->p($node->name) + : '{' . $this->p($node->name) . '}') + : $node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_Empty(Expr\Empty_ $node) { + return 'empty(' . $this->p($node->expr) . ')'; + } + + protected function pExpr_Isset(Expr\Isset_ $node) { + return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; + } + + protected function pExpr_Eval(Expr\Eval_ $node) { + return 'eval(' . $this->p($node->expr) . ')'; + } + + protected function pExpr_Include(Expr\Include_ $node) { + static $map = [ + Expr\Include_::TYPE_INCLUDE => 'include', + Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', + Expr\Include_::TYPE_REQUIRE => 'require', + Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', + ]; + + return $map[$node->type] . ' ' . $this->p($node->expr); + } + + protected function pExpr_List(Expr\List_ $node) { + return 'list(' . $this->pCommaSeparated($node->items) . ')'; + } + + // Other + + protected function pExpr_Error(Expr\Error $node) { + throw new \LogicException('Cannot pretty-print AST with Error nodes'); + } + + protected function pExpr_Variable(Expr\Variable $node) { + if ($node->name instanceof Expr) { + return '${' . $this->p($node->name) . '}'; + } else { + return '$' . $node->name; + } + } + + protected function pExpr_Array(Expr\Array_ $node) { + $syntax = $node->getAttribute('kind', + $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); + if ($syntax === Expr\Array_::KIND_SHORT) { + return '[' . $this->pMaybeMultiline($node->items, true) . ']'; + } else { + return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; + } + } + + protected function pExpr_ArrayItem(Expr\ArrayItem $node) { + return (null !== $node->key ? $this->p($node->key) . ' => ' : '') + . ($node->byRef ? '&' : '') + . ($node->unpack ? '...' : '') + . $this->p($node->value); + } + + protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { + return $this->pDereferenceLhs($node->var) + . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; + } + + protected function pExpr_ConstFetch(Expr\ConstFetch $node) { + return $this->p($node->name); + } + + protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { + return $this->pStaticDereferenceLhs($node->class) . '::' . $this->pObjectProperty($node->name); + } + + protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) { + return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); + } + + protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node) { + return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name); + } + + protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { + return $this->pStaticDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); + } + + protected function pExpr_ShellExec(Expr\ShellExec $node) { + return '`' . $this->pEncapsList($node->parts, '`') . '`'; + } + + protected function pExpr_Closure(Expr\Closure $node) { + return $this->pAttrGroups($node->attrGroups, true) + . ($node->static ? 'static ' : '') + . 'function ' . ($node->byRef ? '&' : '') + . '(' . $this->pCommaSeparated($node->params) . ')' + . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '') + . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') + . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pExpr_Match(Expr\Match_ $node) { + return 'match (' . $this->p($node->cond) . ') {' + . $this->pCommaSeparatedMultiline($node->arms, true) + . $this->nl + . '}'; + } + + protected function pMatchArm(Node\MatchArm $node) { + return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default') + . ' => ' . $this->p($node->body); + } + + protected function pExpr_ArrowFunction(Expr\ArrowFunction $node) { + return $this->pAttrGroups($node->attrGroups, true) + . ($node->static ? 'static ' : '') + . 'fn' . ($node->byRef ? '&' : '') + . '(' . $this->pCommaSeparated($node->params) . ')' + . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') + . ' => ' + . $this->p($node->expr); + } + + protected function pExpr_ClosureUse(Expr\ClosureUse $node) { + return ($node->byRef ? '&' : '') . $this->p($node->var); + } + + protected function pExpr_New(Expr\New_ $node) { + if ($node->class instanceof Stmt\Class_) { + $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; + return 'new ' . $this->pClassCommon($node->class, $args); + } + return 'new ' . $this->pNewVariable($node->class) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_Clone(Expr\Clone_ $node) { + return 'clone ' . $this->p($node->expr); + } + + protected function pExpr_Ternary(Expr\Ternary $node) { + // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. + // this is okay because the part between ? and : never needs parentheses. + return $this->pInfixOp(Expr\Ternary::class, + $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else + ); + } + + protected function pExpr_Exit(Expr\Exit_ $node) { + $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); + return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') + . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); + } + + protected function pExpr_Throw(Expr\Throw_ $node) { + return 'throw ' . $this->p($node->expr); + } + + protected function pExpr_Yield(Expr\Yield_ $node) { + if ($node->value === null) { + return 'yield'; + } else { + // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary + return '(yield ' + . ($node->key !== null ? $this->p($node->key) . ' => ' : '') + . $this->p($node->value) + . ')'; + } + } + + // Declarations + + protected function pStmt_Namespace(Stmt\Namespace_ $node) { + if ($this->canUseSemicolonNamespaces) { + return 'namespace ' . $this->p($node->name) . ';' + . $this->nl . $this->pStmts($node->stmts, false); + } else { + return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') + . ' {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + } + + protected function pStmt_Use(Stmt\Use_ $node) { + return 'use ' . $this->pUseType($node->type) + . $this->pCommaSeparated($node->uses) . ';'; + } + + protected function pStmt_GroupUse(Stmt\GroupUse $node) { + return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) + . '\{' . $this->pCommaSeparated($node->uses) . '};'; + } + + protected function pStmt_UseUse(Stmt\UseUse $node) { + return $this->pUseType($node->type) . $this->p($node->name) + . (null !== $node->alias ? ' as ' . $node->alias : ''); + } + + protected function pUseType($type) { + return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' + : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); + } + + protected function pStmt_Interface(Stmt\Interface_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'interface ' . $node->name + . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Enum(Stmt\Enum_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'enum ' . $node->name + . ($node->scalarType ? " : $node->scalarType" : '') + . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Class(Stmt\Class_ $node) { + return $this->pClassCommon($node, ' ' . $node->name); + } + + protected function pStmt_Trait(Stmt\Trait_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'trait ' . $node->name + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_EnumCase(Stmt\EnumCase $node) { + return $this->pAttrGroups($node->attrGroups) + . 'case ' . $node->name + . ($node->expr ? ' = ' . $this->p($node->expr) : '') + . ';'; + } + + protected function pStmt_TraitUse(Stmt\TraitUse $node) { + return 'use ' . $this->pCommaSeparated($node->traits) + . (empty($node->adaptations) + ? ';' + : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}'); + } + + protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { + return $this->p($node->trait) . '::' . $node->method + . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; + } + + protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { + return (null !== $node->trait ? $this->p($node->trait) . '::' : '') + . $node->method . ' as' + . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') + . (null !== $node->newName ? ' ' . $node->newName : '') + . ';'; + } + + protected function pStmt_Property(Stmt\Property $node) { + return $this->pAttrGroups($node->attrGroups) + . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) + . ($node->type ? $this->p($node->type) . ' ' : '') + . $this->pCommaSeparated($node->props) . ';'; + } + + protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { + return '$' . $node->name + . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { + return $this->pAttrGroups($node->attrGroups) + . $this->pModifiers($node->flags) + . 'function ' . ($node->byRef ? '&' : '') . $node->name + . '(' . $this->pMaybeMultiline($node->params) . ')' + . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') + . (null !== $node->stmts + ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' + : ';'); + } + + protected function pStmt_ClassConst(Stmt\ClassConst $node) { + return $this->pAttrGroups($node->attrGroups) + . $this->pModifiers($node->flags) + . 'const ' + . (null !== $node->type ? $this->p($node->type) . ' ' : '') + . $this->pCommaSeparated($node->consts) . ';'; + } + + protected function pStmt_Function(Stmt\Function_ $node) { + return $this->pAttrGroups($node->attrGroups) + . 'function ' . ($node->byRef ? '&' : '') . $node->name + . '(' . $this->pCommaSeparated($node->params) . ')' + . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Const(Stmt\Const_ $node) { + return 'const ' . $this->pCommaSeparated($node->consts) . ';'; + } + + protected function pStmt_Declare(Stmt\Declare_ $node) { + return 'declare (' . $this->pCommaSeparated($node->declares) . ')' + . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';'); + } + + protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { + return $node->key . '=' . $this->p($node->value); + } + + // Control flow + + protected function pStmt_If(Stmt\If_ $node) { + return 'if (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}' + . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') + . (null !== $node->else ? ' ' . $this->p($node->else) : ''); + } + + protected function pStmt_ElseIf(Stmt\ElseIf_ $node) { + return 'elseif (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Else(Stmt\Else_ $node) { + return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_For(Stmt\For_ $node) { + return 'for (' + . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') + . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') + . $this->pCommaSeparated($node->loop) + . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Foreach(Stmt\Foreach_ $node) { + return 'foreach (' . $this->p($node->expr) . ' as ' + . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') + . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_While(Stmt\While_ $node) { + return 'while (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Do(Stmt\Do_ $node) { + return 'do {' . $this->pStmts($node->stmts) . $this->nl + . '} while (' . $this->p($node->cond) . ');'; + } + + protected function pStmt_Switch(Stmt\Switch_ $node) { + return 'switch (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->cases) . $this->nl . '}'; + } + + protected function pStmt_Case(Stmt\Case_ $node) { + return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' + . $this->pStmts($node->stmts); + } + + protected function pStmt_TryCatch(Stmt\TryCatch $node) { + return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' + . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') + . ($node->finally !== null ? ' ' . $this->p($node->finally) : ''); + } + + protected function pStmt_Catch(Stmt\Catch_ $node) { + return 'catch (' . $this->pImplode($node->types, '|') + . ($node->var !== null ? ' ' . $this->p($node->var) : '') + . ') {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Finally(Stmt\Finally_ $node) { + return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pStmt_Break(Stmt\Break_ $node) { + return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; + } + + protected function pStmt_Continue(Stmt\Continue_ $node) { + return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; + } + + protected function pStmt_Return(Stmt\Return_ $node) { + return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; + } + + protected function pStmt_Throw(Stmt\Throw_ $node) { + return 'throw ' . $this->p($node->expr) . ';'; + } + + protected function pStmt_Label(Stmt\Label $node) { + return $node->name . ':'; + } + + protected function pStmt_Goto(Stmt\Goto_ $node) { + return 'goto ' . $node->name . ';'; + } + + // Other + + protected function pStmt_Expression(Stmt\Expression $node) { + return $this->p($node->expr) . ';'; + } + + protected function pStmt_Echo(Stmt\Echo_ $node) { + return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; + } + + protected function pStmt_Static(Stmt\Static_ $node) { + return 'static ' . $this->pCommaSeparated($node->vars) . ';'; + } + + protected function pStmt_Global(Stmt\Global_ $node) { + return 'global ' . $this->pCommaSeparated($node->vars) . ';'; + } + + protected function pStmt_StaticVar(Stmt\StaticVar $node) { + return $this->p($node->var) + . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pStmt_Unset(Stmt\Unset_ $node) { + return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; + } + + protected function pStmt_InlineHTML(Stmt\InlineHTML $node) { + $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : ''; + return '?>' . $newline . $node->value . 'remaining; + } + + protected function pStmt_Nop(Stmt\Nop $node) { + return ''; + } + + // Helpers + + protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { + return $this->pAttrGroups($node->attrGroups, $node->name === null) + . $this->pModifiers($node->flags) + . 'class' . $afterClassToken + . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') + . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') + . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}'; + } + + protected function pObjectProperty($node) { + if ($node instanceof Expr) { + return '{' . $this->p($node) . '}'; + } else { + return $node; + } + } + + protected function pEncapsList(array $encapsList, $quote) { + $return = ''; + foreach ($encapsList as $element) { + if ($element instanceof Scalar\EncapsedStringPart) { + $return .= $this->escapeString($element->value, $quote); + } else { + $return .= '{' . $this->p($element) . '}'; + } + } + + return $return; + } + + protected function pSingleQuotedString(string $string) { + return '\'' . addcslashes($string, '\'\\') . '\''; + } + + protected function escapeString($string, $quote) { + if (null === $quote) { + // For doc strings, don't escape newlines + $escaped = addcslashes($string, "\t\f\v$\\"); + } else { + $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\"); + } + + // Escape control characters and non-UTF-8 characters. + // Regex based on https://stackoverflow.com/a/11709412/385378. + $regex = '/( + [\x00-\x08\x0E-\x1F] # Control characters + | [\xC0-\xC1] # Invalid UTF-8 Bytes + | [\xF5-\xFF] # Invalid UTF-8 Bytes + | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point + | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point + | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start + | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start + | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start + | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle + | (? $part) { + $atStart = $i === 0; + $atEnd = $i === count($parts) - 1; + if ($part instanceof Scalar\EncapsedStringPart + && $this->containsEndLabel($part->value, $label, $atStart, $atEnd) + ) { + return true; + } + } + return false; + } + + protected function pDereferenceLhs(Node $node) { + if (!$this->dereferenceLhsRequiresParens($node)) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + protected function pStaticDereferenceLhs(Node $node) { + if (!$this->staticDereferenceLhsRequiresParens($node)) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + protected function pCallLhs(Node $node) { + if (!$this->callLhsRequiresParens($node)) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + protected function pNewVariable(Node $node): string { + if (!$this->newOperandRequiresParens($node)) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + /** + * @param Node[] $nodes + * @return bool + */ + protected function hasNodeWithComments(array $nodes) { + foreach ($nodes as $node) { + if ($node && $node->getComments()) { + return true; + } + } + return false; + } + + protected function pMaybeMultiline(array $nodes, bool $trailingComma = false) { + if (!$this->hasNodeWithComments($nodes)) { + return $this->pCommaSeparated($nodes); + } else { + return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl; + } + } + + protected function pAttrGroups(array $nodes, bool $inline = false): string { + $result = ''; + $sep = $inline ? ' ' : $this->nl; + foreach ($nodes as $node) { + $result .= $this->p($node) . $sep; + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php new file mode 100644 index 000000000..5d87e5ce8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php @@ -0,0 +1,1576 @@ + [ 0, 1], + Expr\BitwiseNot::class => [ 10, 1], + Expr\PreInc::class => [ 10, 1], + Expr\PreDec::class => [ 10, 1], + Expr\PostInc::class => [ 10, -1], + Expr\PostDec::class => [ 10, -1], + Expr\UnaryPlus::class => [ 10, 1], + Expr\UnaryMinus::class => [ 10, 1], + Cast\Int_::class => [ 10, 1], + Cast\Double::class => [ 10, 1], + Cast\String_::class => [ 10, 1], + Cast\Array_::class => [ 10, 1], + Cast\Object_::class => [ 10, 1], + Cast\Bool_::class => [ 10, 1], + Cast\Unset_::class => [ 10, 1], + Expr\ErrorSuppress::class => [ 10, 1], + Expr\Instanceof_::class => [ 20, 0], + Expr\BooleanNot::class => [ 30, 1], + BinaryOp\Mul::class => [ 40, -1], + BinaryOp\Div::class => [ 40, -1], + BinaryOp\Mod::class => [ 40, -1], + BinaryOp\Plus::class => [ 50, -1], + BinaryOp\Minus::class => [ 50, -1], + BinaryOp\Concat::class => [ 50, -1], + BinaryOp\ShiftLeft::class => [ 60, -1], + BinaryOp\ShiftRight::class => [ 60, -1], + BinaryOp\Smaller::class => [ 70, 0], + BinaryOp\SmallerOrEqual::class => [ 70, 0], + BinaryOp\Greater::class => [ 70, 0], + BinaryOp\GreaterOrEqual::class => [ 70, 0], + BinaryOp\Equal::class => [ 80, 0], + BinaryOp\NotEqual::class => [ 80, 0], + BinaryOp\Identical::class => [ 80, 0], + BinaryOp\NotIdentical::class => [ 80, 0], + BinaryOp\Spaceship::class => [ 80, 0], + BinaryOp\BitwiseAnd::class => [ 90, -1], + BinaryOp\BitwiseXor::class => [100, -1], + BinaryOp\BitwiseOr::class => [110, -1], + BinaryOp\BooleanAnd::class => [120, -1], + BinaryOp\BooleanOr::class => [130, -1], + BinaryOp\Coalesce::class => [140, 1], + Expr\Ternary::class => [150, 0], + // parser uses %left for assignments, but they really behave as %right + Expr\Assign::class => [160, 1], + Expr\AssignRef::class => [160, 1], + AssignOp\Plus::class => [160, 1], + AssignOp\Minus::class => [160, 1], + AssignOp\Mul::class => [160, 1], + AssignOp\Div::class => [160, 1], + AssignOp\Concat::class => [160, 1], + AssignOp\Mod::class => [160, 1], + AssignOp\BitwiseAnd::class => [160, 1], + AssignOp\BitwiseOr::class => [160, 1], + AssignOp\BitwiseXor::class => [160, 1], + AssignOp\ShiftLeft::class => [160, 1], + AssignOp\ShiftRight::class => [160, 1], + AssignOp\Pow::class => [160, 1], + AssignOp\Coalesce::class => [160, 1], + Expr\YieldFrom::class => [165, 1], + Expr\Print_::class => [168, 1], + BinaryOp\LogicalAnd::class => [170, -1], + BinaryOp\LogicalXor::class => [180, -1], + BinaryOp\LogicalOr::class => [190, -1], + Expr\Include_::class => [200, -1], + ]; + + /** @var int Current indentation level. */ + protected $indentLevel; + /** @var string Newline including current indentation. */ + protected $nl; + /** @var string Token placed at end of doc string to ensure it is followed by a newline. */ + protected $docStringEndToken; + /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */ + protected $canUseSemicolonNamespaces; + /** @var array Pretty printer options */ + protected $options; + + /** @var TokenStream Original tokens for use in format-preserving pretty print */ + protected $origTokens; + /** @var Internal\Differ Differ for node lists */ + protected $nodeListDiffer; + /** @var bool[] Map determining whether a certain character is a label character */ + protected $labelCharMap; + /** + * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used + * during format-preserving prints to place additional parens/braces if necessary. + */ + protected $fixupMap; + /** + * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r], + * where $l and $r specify the token type that needs to be stripped when removing + * this node. + */ + protected $removalMap; + /** + * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight]. + * $find is an optional token after which the insertion occurs. $extraLeft/Right + * are optionally added before/after the main insertions. + */ + protected $insertionMap; + /** + * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted + * between elements of this list subnode. + */ + protected $listInsertionMap; + protected $emptyListInsertionMap; + /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers + * should be reprinted. */ + protected $modifierChangeMap; + + /** + * Creates a pretty printer instance using the given options. + * + * Supported options: + * * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array + * syntax, if the node does not specify a format. + * + * @param array $options Dictionary of formatting options + */ + public function __construct(array $options = []) { + $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand(); + + $defaultOptions = ['shortArraySyntax' => false]; + $this->options = $options + $defaultOptions; + } + + /** + * Reset pretty printing state. + */ + protected function resetState() { + $this->indentLevel = 0; + $this->nl = "\n"; + $this->origTokens = null; + } + + /** + * Set indentation level + * + * @param int $level Level in number of spaces + */ + protected function setIndentLevel(int $level) { + $this->indentLevel = $level; + $this->nl = "\n" . \str_repeat(' ', $level); + } + + /** + * Increase indentation level. + */ + protected function indent() { + $this->indentLevel += 4; + $this->nl .= ' '; + } + + /** + * Decrease indentation level. + */ + protected function outdent() { + assert($this->indentLevel >= 4); + $this->indentLevel -= 4; + $this->nl = "\n" . str_repeat(' ', $this->indentLevel); + } + + /** + * Pretty prints an array of statements. + * + * @param Node[] $stmts Array of statements + * + * @return string Pretty printed statements + */ + public function prettyPrint(array $stmts) : string { + $this->resetState(); + $this->preprocessNodes($stmts); + + return ltrim($this->handleMagicTokens($this->pStmts($stmts, false))); + } + + /** + * Pretty prints an expression. + * + * @param Expr $node Expression node + * + * @return string Pretty printed node + */ + public function prettyPrintExpr(Expr $node) : string { + $this->resetState(); + return $this->handleMagicTokens($this->p($node)); + } + + /** + * Pretty prints a file of statements (includes the opening prettyPrint($stmts); + + if ($stmts[0] instanceof Stmt\InlineHTML) { + $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p); + } + if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) { + $p = preg_replace('/<\?php$/', '', rtrim($p)); + } + + return $p; + } + + /** + * Preprocesses the top-level nodes to initialize pretty printer state. + * + * @param Node[] $nodes Array of nodes + */ + protected function preprocessNodes(array $nodes) { + /* We can use semicolon-namespaces unless there is a global namespace declaration */ + $this->canUseSemicolonNamespaces = true; + foreach ($nodes as $node) { + if ($node instanceof Stmt\Namespace_ && null === $node->name) { + $this->canUseSemicolonNamespaces = false; + break; + } + } + } + + /** + * Handles (and removes) no-indent and doc-string-end tokens. + * + * @param string $str + * @return string + */ + protected function handleMagicTokens(string $str) : string { + // Replace doc-string-end tokens with nothing or a newline + $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str); + $str = str_replace($this->docStringEndToken, "\n", $str); + + return $str; + } + + /** + * Pretty prints an array of nodes (statements) and indents them optionally. + * + * @param Node[] $nodes Array of nodes + * @param bool $indent Whether to indent the printed nodes + * + * @return string Pretty printed statements + */ + protected function pStmts(array $nodes, bool $indent = true) : string { + if ($indent) { + $this->indent(); + } + + $result = ''; + foreach ($nodes as $node) { + $comments = $node->getComments(); + if ($comments) { + $result .= $this->nl . $this->pComments($comments); + if ($node instanceof Stmt\Nop) { + continue; + } + } + + $result .= $this->nl . $this->p($node); + } + + if ($indent) { + $this->outdent(); + } + + return $result; + } + + /** + * Pretty-print an infix operation while taking precedence into account. + * + * @param string $class Node class of operator + * @param Node $leftNode Left-hand side node + * @param string $operatorString String representation of the operator + * @param Node $rightNode Right-hand side node + * + * @return string Pretty printed infix operation + */ + protected function pInfixOp(string $class, Node $leftNode, string $operatorString, Node $rightNode) : string { + list($precedence, $associativity) = $this->precedenceMap[$class]; + + return $this->pPrec($leftNode, $precedence, $associativity, -1) + . $operatorString + . $this->pPrec($rightNode, $precedence, $associativity, 1); + } + + /** + * Pretty-print a prefix operation while taking precedence into account. + * + * @param string $class Node class of operator + * @param string $operatorString String representation of the operator + * @param Node $node Node + * + * @return string Pretty printed prefix operation + */ + protected function pPrefixOp(string $class, string $operatorString, Node $node) : string { + list($precedence, $associativity) = $this->precedenceMap[$class]; + return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); + } + + /** + * Pretty-print a postfix operation while taking precedence into account. + * + * @param string $class Node class of operator + * @param string $operatorString String representation of the operator + * @param Node $node Node + * + * @return string Pretty printed postfix operation + */ + protected function pPostfixOp(string $class, Node $node, string $operatorString) : string { + list($precedence, $associativity) = $this->precedenceMap[$class]; + return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; + } + + /** + * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. + * + * @param Node $node Node to pretty print + * @param int $parentPrecedence Precedence of the parent operator + * @param int $parentAssociativity Associativity of parent operator + * (-1 is left, 0 is nonassoc, 1 is right) + * @param int $childPosition Position of the node relative to the operator + * (-1 is left, 1 is right) + * + * @return string The pretty printed node + */ + protected function pPrec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string { + $class = \get_class($node); + if (isset($this->precedenceMap[$class])) { + $childPrecedence = $this->precedenceMap[$class][0]; + if ($childPrecedence > $parentPrecedence + || ($parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition) + ) { + return '(' . $this->p($node) . ')'; + } + } + + return $this->p($node); + } + + /** + * Pretty prints an array of nodes and implodes the printed values. + * + * @param Node[] $nodes Array of Nodes to be printed + * @param string $glue Character to implode with + * + * @return string Imploded pretty printed nodes + */ + protected function pImplode(array $nodes, string $glue = '') : string { + $pNodes = []; + foreach ($nodes as $node) { + if (null === $node) { + $pNodes[] = ''; + } else { + $pNodes[] = $this->p($node); + } + } + + return implode($glue, $pNodes); + } + + /** + * Pretty prints an array of nodes and implodes the printed values with commas. + * + * @param Node[] $nodes Array of Nodes to be printed + * + * @return string Comma separated pretty printed nodes + */ + protected function pCommaSeparated(array $nodes) : string { + return $this->pImplode($nodes, ', '); + } + + /** + * Pretty prints a comma-separated list of nodes in multiline style, including comments. + * + * The result includes a leading newline and one level of indentation (same as pStmts). + * + * @param Node[] $nodes Array of Nodes to be printed + * @param bool $trailingComma Whether to use a trailing comma + * + * @return string Comma separated pretty printed nodes in multiline style + */ + protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string { + $this->indent(); + + $result = ''; + $lastIdx = count($nodes) - 1; + foreach ($nodes as $idx => $node) { + if ($node !== null) { + $comments = $node->getComments(); + if ($comments) { + $result .= $this->nl . $this->pComments($comments); + } + + $result .= $this->nl . $this->p($node); + } else { + $result .= $this->nl; + } + if ($trailingComma || $idx !== $lastIdx) { + $result .= ','; + } + } + + $this->outdent(); + return $result; + } + + /** + * Prints reformatted text of the passed comments. + * + * @param Comment[] $comments List of comments + * + * @return string Reformatted text of comments + */ + protected function pComments(array $comments) : string { + $formattedComments = []; + + foreach ($comments as $comment) { + $formattedComments[] = str_replace("\n", $this->nl, $comment->getReformattedText()); + } + + return implode($this->nl, $formattedComments); + } + + /** + * Perform a format-preserving pretty print of an AST. + * + * The format preservation is best effort. For some changes to the AST the formatting will not + * be preserved (at least not locally). + * + * In order to use this method a number of prerequisites must be satisfied: + * * The startTokenPos and endTokenPos attributes in the lexer must be enabled. + * * The CloningVisitor must be run on the AST prior to modification. + * * The original tokens must be provided, using the getTokens() method on the lexer. + * + * @param Node[] $stmts Modified AST with links to original AST + * @param Node[] $origStmts Original AST with token offset information + * @param array $origTokens Tokens of the original code + * + * @return string + */ + public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string { + $this->initializeNodeListDiffer(); + $this->initializeLabelCharMap(); + $this->initializeFixupMap(); + $this->initializeRemovalMap(); + $this->initializeInsertionMap(); + $this->initializeListInsertionMap(); + $this->initializeEmptyListInsertionMap(); + $this->initializeModifierChangeMap(); + + $this->resetState(); + $this->origTokens = new TokenStream($origTokens); + + $this->preprocessNodes($stmts); + + $pos = 0; + $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null); + if (null !== $result) { + $result .= $this->origTokens->getTokenCode($pos, count($origTokens), 0); + } else { + // Fallback + // TODO Add pStmts($stmts, false); + } + + return ltrim($this->handleMagicTokens($result)); + } + + protected function pFallback(Node $node) { + return $this->{'p' . $node->getType()}($node); + } + + /** + * Pretty prints a node. + * + * This method also handles formatting preservation for nodes. + * + * @param Node $node Node to be pretty printed + * @param bool $parentFormatPreserved Whether parent node has preserved formatting + * + * @return string Pretty printed node + */ + protected function p(Node $node, $parentFormatPreserved = false) : string { + // No orig tokens means this is a normal pretty print without preservation of formatting + if (!$this->origTokens) { + return $this->{'p' . $node->getType()}($node); + } + + /** @var Node $origNode */ + $origNode = $node->getAttribute('origNode'); + if (null === $origNode) { + return $this->pFallback($node); + } + + $class = \get_class($node); + \assert($class === \get_class($origNode)); + + $startPos = $origNode->getStartTokenPos(); + $endPos = $origNode->getEndTokenPos(); + \assert($startPos >= 0 && $endPos >= 0); + + $fallbackNode = $node; + if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) { + // Normalize node structure of anonymous classes + $node = PrintableNewAnonClassNode::fromNewNode($node); + $origNode = PrintableNewAnonClassNode::fromNewNode($origNode); + } + + // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting + // is not preserved, then we need to use the fallback code to make sure the tags are + // printed. + if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) { + return $this->pFallback($fallbackNode); + } + + $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos); + + $type = $node->getType(); + $fixupInfo = $this->fixupMap[$class] ?? null; + + $result = ''; + $pos = $startPos; + foreach ($node->getSubNodeNames() as $subNodeName) { + $subNode = $node->$subNodeName; + $origSubNode = $origNode->$subNodeName; + + if ((!$subNode instanceof Node && $subNode !== null) + || (!$origSubNode instanceof Node && $origSubNode !== null) + ) { + if ($subNode === $origSubNode) { + // Unchanged, can reuse old code + continue; + } + + if (is_array($subNode) && is_array($origSubNode)) { + // Array subnode changed, we might be able to reconstruct it + $listResult = $this->pArray( + $subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName, + $fixupInfo[$subNodeName] ?? null + ); + if (null === $listResult) { + return $this->pFallback($fallbackNode); + } + + $result .= $listResult; + continue; + } + + if (is_int($subNode) && is_int($origSubNode)) { + // Check if this is a modifier change + $key = $type . '->' . $subNodeName; + if (!isset($this->modifierChangeMap[$key])) { + return $this->pFallback($fallbackNode); + } + + $findToken = $this->modifierChangeMap[$key]; + $result .= $this->pModifiers($subNode); + $pos = $this->origTokens->findRight($pos, $findToken); + continue; + } + + // If a non-node, non-array subnode changed, we don't be able to do a partial + // reconstructions, as we don't have enough offset information. Pretty print the + // whole node instead. + return $this->pFallback($fallbackNode); + } + + $extraLeft = ''; + $extraRight = ''; + if ($origSubNode !== null) { + $subStartPos = $origSubNode->getStartTokenPos(); + $subEndPos = $origSubNode->getEndTokenPos(); + \assert($subStartPos >= 0 && $subEndPos >= 0); + } else { + if ($subNode === null) { + // Both null, nothing to do + continue; + } + + // A node has been inserted, check if we have insertion information for it + $key = $type . '->' . $subNodeName; + if (!isset($this->insertionMap[$key])) { + return $this->pFallback($fallbackNode); + } + + list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key]; + if (null !== $findToken) { + $subStartPos = $this->origTokens->findRight($pos, $findToken) + + (int) !$beforeToken; + } else { + $subStartPos = $pos; + } + + if (null === $extraLeft && null !== $extraRight) { + // If inserting on the right only, skipping whitespace looks better + $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos); + } + $subEndPos = $subStartPos - 1; + } + + if (null === $subNode) { + // A node has been removed, check if we have removal information for it + $key = $type . '->' . $subNodeName; + if (!isset($this->removalMap[$key])) { + return $this->pFallback($fallbackNode); + } + + // Adjust positions to account for additional tokens that must be skipped + $removalInfo = $this->removalMap[$key]; + if (isset($removalInfo['left'])) { + $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1; + } + if (isset($removalInfo['right'])) { + $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1; + } + } + + $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment); + + if (null !== $subNode) { + $result .= $extraLeft; + + $origIndentLevel = $this->indentLevel; + $this->setIndentLevel(max($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment, 0)); + + // If it's the same node that was previously in this position, it certainly doesn't + // need fixup. It's important to check this here, because our fixup checks are more + // conservative than strictly necessary. + if (isset($fixupInfo[$subNodeName]) + && $subNode->getAttribute('origNode') !== $origSubNode + ) { + $fixup = $fixupInfo[$subNodeName]; + $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos); + } else { + $res = $this->p($subNode, true); + } + + $this->safeAppend($result, $res); + $this->setIndentLevel($origIndentLevel); + + $result .= $extraRight; + } + + $pos = $subEndPos + 1; + } + + $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment); + return $result; + } + + /** + * Perform a format-preserving pretty print of an array. + * + * @param array $nodes New nodes + * @param array $origNodes Original nodes + * @param int $pos Current token position (updated by reference) + * @param int $indentAdjustment Adjustment for indentation + * @param string $parentNodeType Type of the containing node. + * @param string $subNodeName Name of array subnode. + * @param null|int $fixup Fixup information for array item nodes + * + * @return null|string Result of pretty print or null if cannot preserve formatting + */ + protected function pArray( + array $nodes, array $origNodes, int &$pos, int $indentAdjustment, + string $parentNodeType, string $subNodeName, $fixup + ) { + $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes); + + $mapKey = $parentNodeType . '->' . $subNodeName; + $insertStr = $this->listInsertionMap[$mapKey] ?? null; + $isStmtList = $subNodeName === 'stmts'; + + $beforeFirstKeepOrReplace = true; + $skipRemovedNode = false; + $delayedAdd = []; + $lastElemIndentLevel = $this->indentLevel; + + $insertNewline = false; + if ($insertStr === "\n") { + $insertStr = ''; + $insertNewline = true; + } + + if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) { + $startPos = $origNodes[0]->getStartTokenPos(); + $endPos = $origNodes[0]->getEndTokenPos(); + \assert($startPos >= 0 && $endPos >= 0); + if (!$this->origTokens->haveBraces($startPos, $endPos)) { + // This was a single statement without braces, but either additional statements + // have been added, or the single statement has been removed. This requires the + // addition of braces. For now fall back. + // TODO: Try to preserve formatting + return null; + } + } + + $result = ''; + foreach ($diff as $i => $diffElem) { + $diffType = $diffElem->type; + /** @var Node|null $arrItem */ + $arrItem = $diffElem->new; + /** @var Node|null $origArrItem */ + $origArrItem = $diffElem->old; + + if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { + $beforeFirstKeepOrReplace = false; + + if ($origArrItem === null || $arrItem === null) { + // We can only handle the case where both are null + if ($origArrItem === $arrItem) { + continue; + } + return null; + } + + if (!$arrItem instanceof Node || !$origArrItem instanceof Node) { + // We can only deal with nodes. This can occur for Names, which use string arrays. + return null; + } + + $itemStartPos = $origArrItem->getStartTokenPos(); + $itemEndPos = $origArrItem->getEndTokenPos(); + \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos); + + $origIndentLevel = $this->indentLevel; + $lastElemIndentLevel = max($this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment, 0); + $this->setIndentLevel($lastElemIndentLevel); + + $comments = $arrItem->getComments(); + $origComments = $origArrItem->getComments(); + $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos; + \assert($commentStartPos >= 0); + + if ($commentStartPos < $pos) { + // Comments may be assigned to multiple nodes if they start at the same position. + // Make sure we don't try to print them multiple times. + $commentStartPos = $itemStartPos; + } + + if ($skipRemovedNode) { + if ($isStmtList && ($this->origTokens->haveBracesInRange($pos, $itemStartPos) || + $this->origTokens->haveTagInRange($pos, $itemStartPos))) { + // We'd remove the brace of a code block. + // TODO: Preserve formatting. + $this->setIndentLevel($origIndentLevel); + return null; + } + } else { + $result .= $this->origTokens->getTokenCode( + $pos, $commentStartPos, $indentAdjustment); + } + + if (!empty($delayedAdd)) { + /** @var Node $delayedAddNode */ + foreach ($delayedAdd as $delayedAddNode) { + if ($insertNewline) { + $delayedAddComments = $delayedAddNode->getComments(); + if ($delayedAddComments) { + $result .= $this->pComments($delayedAddComments) . $this->nl; + } + } + + $this->safeAppend($result, $this->p($delayedAddNode, true)); + + if ($insertNewline) { + $result .= $insertStr . $this->nl; + } else { + $result .= $insertStr; + } + } + + $delayedAdd = []; + } + + if ($comments !== $origComments) { + if ($comments) { + $result .= $this->pComments($comments) . $this->nl; + } + } else { + $result .= $this->origTokens->getTokenCode( + $commentStartPos, $itemStartPos, $indentAdjustment); + } + + // If we had to remove anything, we have done so now. + $skipRemovedNode = false; + } elseif ($diffType === DiffElem::TYPE_ADD) { + if (null === $insertStr) { + // We don't have insertion information for this list type + return null; + } + + // We go multiline if the original code was multiline, + // or if it's an array item with a comment above it. + if ($insertStr === ', ' && + ($this->isMultiline($origNodes) || $arrItem->getComments()) + ) { + $insertStr = ','; + $insertNewline = true; + } + + if ($beforeFirstKeepOrReplace) { + // Will be inserted at the next "replace" or "keep" element + $delayedAdd[] = $arrItem; + continue; + } + + $itemStartPos = $pos; + $itemEndPos = $pos - 1; + + $origIndentLevel = $this->indentLevel; + $this->setIndentLevel($lastElemIndentLevel); + + if ($insertNewline) { + $result .= $insertStr . $this->nl; + $comments = $arrItem->getComments(); + if ($comments) { + $result .= $this->pComments($comments) . $this->nl; + } + } else { + $result .= $insertStr; + } + } elseif ($diffType === DiffElem::TYPE_REMOVE) { + if (!$origArrItem instanceof Node) { + // We only support removal for nodes + return null; + } + + $itemStartPos = $origArrItem->getStartTokenPos(); + $itemEndPos = $origArrItem->getEndTokenPos(); + \assert($itemStartPos >= 0 && $itemEndPos >= 0); + + // Consider comments part of the node. + $origComments = $origArrItem->getComments(); + if ($origComments) { + $itemStartPos = $origComments[0]->getStartTokenPos(); + } + + if ($i === 0) { + // If we're removing from the start, keep the tokens before the node and drop those after it, + // instead of the other way around. + $result .= $this->origTokens->getTokenCode( + $pos, $itemStartPos, $indentAdjustment); + $skipRemovedNode = true; + } else { + if ($isStmtList && ($this->origTokens->haveBracesInRange($pos, $itemStartPos) || + $this->origTokens->haveTagInRange($pos, $itemStartPos))) { + // We'd remove the brace of a code block. + // TODO: Preserve formatting. + return null; + } + } + + $pos = $itemEndPos + 1; + continue; + } else { + throw new \Exception("Shouldn't happen"); + } + + if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) { + $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos); + } else { + $res = $this->p($arrItem, true); + } + $this->safeAppend($result, $res); + + $this->setIndentLevel($origIndentLevel); + $pos = $itemEndPos + 1; + } + + if ($skipRemovedNode) { + // TODO: Support removing single node. + return null; + } + + if (!empty($delayedAdd)) { + if (!isset($this->emptyListInsertionMap[$mapKey])) { + return null; + } + + list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey]; + if (null !== $findToken) { + $insertPos = $this->origTokens->findRight($pos, $findToken) + 1; + $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment); + $pos = $insertPos; + } + + $first = true; + $result .= $extraLeft; + foreach ($delayedAdd as $delayedAddNode) { + if (!$first) { + $result .= $insertStr; + if ($insertNewline) { + $result .= $this->nl; + } + } + $result .= $this->p($delayedAddNode, true); + $first = false; + } + $result .= $extraRight === "\n" ? $this->nl : $extraRight; + } + + return $result; + } + + /** + * Print node with fixups. + * + * Fixups here refer to the addition of extra parentheses, braces or other characters, that + * are required to preserve program semantics in a certain context (e.g. to maintain precedence + * or because only certain expressions are allowed in certain places). + * + * @param int $fixup Fixup type + * @param Node $subNode Subnode to print + * @param string|null $parentClass Class of parent node + * @param int $subStartPos Original start pos of subnode + * @param int $subEndPos Original end pos of subnode + * + * @return string Result of fixed-up print of subnode + */ + protected function pFixup(int $fixup, Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string { + switch ($fixup) { + case self::FIXUP_PREC_LEFT: + case self::FIXUP_PREC_RIGHT: + if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) { + list($precedence, $associativity) = $this->precedenceMap[$parentClass]; + return $this->pPrec($subNode, $precedence, $associativity, + $fixup === self::FIXUP_PREC_LEFT ? -1 : 1); + } + break; + case self::FIXUP_CALL_LHS: + if ($this->callLhsRequiresParens($subNode) + && !$this->origTokens->haveParens($subStartPos, $subEndPos) + ) { + return '(' . $this->p($subNode) . ')'; + } + break; + case self::FIXUP_DEREF_LHS: + if ($this->dereferenceLhsRequiresParens($subNode) + && !$this->origTokens->haveParens($subStartPos, $subEndPos) + ) { + return '(' . $this->p($subNode) . ')'; + } + break; + case self::FIXUP_STATIC_DEREF_LHS: + if ($this->staticDereferenceLhsRequiresParens($subNode) + && !$this->origTokens->haveParens($subStartPos, $subEndPos) + ) { + return '(' . $this->p($subNode) . ')'; + } + break; + case self::FIXUP_NEW: + if ($this->newOperandRequiresParens($subNode) + && !$this->origTokens->haveParens($subStartPos, $subEndPos)) { + return '(' . $this->p($subNode) . ')'; + } + break; + case self::FIXUP_BRACED_NAME: + case self::FIXUP_VAR_BRACED_NAME: + if ($subNode instanceof Expr + && !$this->origTokens->haveBraces($subStartPos, $subEndPos) + ) { + return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') + . '{' . $this->p($subNode) . '}'; + } + break; + case self::FIXUP_ENCAPSED: + if (!$subNode instanceof Scalar\EncapsedStringPart + && !$this->origTokens->haveBraces($subStartPos, $subEndPos) + ) { + return '{' . $this->p($subNode) . '}'; + } + break; + default: + throw new \Exception('Cannot happen'); + } + + // Nothing special to do + return $this->p($subNode); + } + + /** + * Appends to a string, ensuring whitespace between label characters. + * + * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x". + * Without safeAppend the result would be "echox", which does not preserve semantics. + * + * @param string $str + * @param string $append + */ + protected function safeAppend(string &$str, string $append) { + if ($str === "") { + $str = $append; + return; + } + + if ($append === "") { + return; + } + + if (!$this->labelCharMap[$append[0]] + || !$this->labelCharMap[$str[\strlen($str) - 1]]) { + $str .= $append; + } else { + $str .= " " . $append; + } + } + + /** + * Determines whether the LHS of a call must be wrapped in parenthesis. + * + * @param Node $node LHS of a call + * + * @return bool Whether parentheses are required + */ + protected function callLhsRequiresParens(Node $node) : bool { + return !($node instanceof Node\Name + || $node instanceof Expr\Variable + || $node instanceof Expr\ArrayDimFetch + || $node instanceof Expr\FuncCall + || $node instanceof Expr\MethodCall + || $node instanceof Expr\NullsafeMethodCall + || $node instanceof Expr\StaticCall + || $node instanceof Expr\Array_); + } + + /** + * Determines whether the LHS of an array/object operation must be wrapped in parentheses. + * + * @param Node $node LHS of dereferencing operation + * + * @return bool Whether parentheses are required + */ + protected function dereferenceLhsRequiresParens(Node $node) : bool { + // A constant can occur on the LHS of an array/object deref, but not a static deref. + return $this->staticDereferenceLhsRequiresParens($node) + && !$node instanceof Expr\ConstFetch; + } + + /** + * Determines whether the LHS of a static operation must be wrapped in parentheses. + * + * @param Node $node LHS of dereferencing operation + * + * @return bool Whether parentheses are required + */ + protected function staticDereferenceLhsRequiresParens(Node $node): bool { + return !($node instanceof Expr\Variable + || $node instanceof Node\Name + || $node instanceof Expr\ArrayDimFetch + || $node instanceof Expr\PropertyFetch + || $node instanceof Expr\NullsafePropertyFetch + || $node instanceof Expr\StaticPropertyFetch + || $node instanceof Expr\FuncCall + || $node instanceof Expr\MethodCall + || $node instanceof Expr\NullsafeMethodCall + || $node instanceof Expr\StaticCall + || $node instanceof Expr\Array_ + || $node instanceof Scalar\String_ + || $node instanceof Expr\ClassConstFetch); + } + + /** + * Determines whether an expression used in "new" or "instanceof" requires parentheses. + * + * @param Node $node New or instanceof operand + * + * @return bool Whether parentheses are required + */ + protected function newOperandRequiresParens(Node $node): bool { + if ($node instanceof Node\Name || $node instanceof Expr\Variable) { + return false; + } + if ($node instanceof Expr\ArrayDimFetch || $node instanceof Expr\PropertyFetch || + $node instanceof Expr\NullsafePropertyFetch + ) { + return $this->newOperandRequiresParens($node->var); + } + if ($node instanceof Expr\StaticPropertyFetch) { + return $this->newOperandRequiresParens($node->class); + } + return true; + } + + /** + * Print modifiers, including trailing whitespace. + * + * @param int $modifiers Modifier mask to print + * + * @return string Printed modifiers + */ + protected function pModifiers(int $modifiers) { + return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_READONLY ? 'readonly ' : ''); + } + + /** + * Determine whether a list of nodes uses multiline formatting. + * + * @param (Node|null)[] $nodes Node list + * + * @return bool Whether multiline formatting is used + */ + protected function isMultiline(array $nodes) : bool { + if (\count($nodes) < 2) { + return false; + } + + $pos = -1; + foreach ($nodes as $node) { + if (null === $node) { + continue; + } + + $endPos = $node->getEndTokenPos() + 1; + if ($pos >= 0) { + $text = $this->origTokens->getTokenCode($pos, $endPos, 0); + if (false === strpos($text, "\n")) { + // We require that a newline is present between *every* item. If the formatting + // is inconsistent, with only some items having newlines, we don't consider it + // as multiline + return false; + } + } + $pos = $endPos; + } + + return true; + } + + /** + * Lazily initializes label char map. + * + * The label char map determines whether a certain character may occur in a label. + */ + protected function initializeLabelCharMap() { + if ($this->labelCharMap) return; + + $this->labelCharMap = []; + for ($i = 0; $i < 256; $i++) { + // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for + // older versions. + $chr = chr($i); + $this->labelCharMap[$chr] = $i >= 0x7f || ctype_alnum($chr); + } + } + + /** + * Lazily initializes node list differ. + * + * The node list differ is used to determine differences between two array subnodes. + */ + protected function initializeNodeListDiffer() { + if ($this->nodeListDiffer) return; + + $this->nodeListDiffer = new Internal\Differ(function ($a, $b) { + if ($a instanceof Node && $b instanceof Node) { + return $a === $b->getAttribute('origNode'); + } + // Can happen for array destructuring + return $a === null && $b === null; + }); + } + + /** + * Lazily initializes fixup map. + * + * The fixup map is used to determine whether a certain subnode of a certain node may require + * some kind of "fixup" operation, e.g. the addition of parenthesis or braces. + */ + protected function initializeFixupMap() { + if ($this->fixupMap) return; + + $this->fixupMap = [ + Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT], + Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT], + Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT], + Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT], + Expr\Instanceof_::class => [ + 'expr' => self::FIXUP_PREC_LEFT, + 'class' => self::FIXUP_NEW, + ], + Expr\Ternary::class => [ + 'cond' => self::FIXUP_PREC_LEFT, + 'else' => self::FIXUP_PREC_RIGHT, + ], + + Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS], + Expr\StaticCall::class => ['class' => self::FIXUP_STATIC_DEREF_LHS], + Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS], + Expr\ClassConstFetch::class => [ + 'class' => self::FIXUP_STATIC_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\New_::class => ['class' => self::FIXUP_NEW], + Expr\MethodCall::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\NullsafeMethodCall::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\StaticPropertyFetch::class => [ + 'class' => self::FIXUP_STATIC_DEREF_LHS, + 'name' => self::FIXUP_VAR_BRACED_NAME, + ], + Expr\PropertyFetch::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Expr\NullsafePropertyFetch::class => [ + 'var' => self::FIXUP_DEREF_LHS, + 'name' => self::FIXUP_BRACED_NAME, + ], + Scalar\Encapsed::class => [ + 'parts' => self::FIXUP_ENCAPSED, + ], + ]; + + $binaryOps = [ + BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class, + BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class, + BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class, + BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class, + BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class, + BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class, + BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class, + BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class, + BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class, + ]; + foreach ($binaryOps as $binaryOp) { + $this->fixupMap[$binaryOp] = [ + 'left' => self::FIXUP_PREC_LEFT, + 'right' => self::FIXUP_PREC_RIGHT + ]; + } + + $assignOps = [ + Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class, + AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class, + AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class, + AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class + ]; + foreach ($assignOps as $assignOp) { + $this->fixupMap[$assignOp] = [ + 'var' => self::FIXUP_PREC_LEFT, + 'expr' => self::FIXUP_PREC_RIGHT, + ]; + } + + $prefixOps = [ + Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, + Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, + Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, + Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class, + ]; + foreach ($prefixOps as $prefixOp) { + $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT]; + } + } + + /** + * Lazily initializes the removal map. + * + * The removal map is used to determine which additional tokens should be removed when a + * certain node is replaced by null. + */ + protected function initializeRemovalMap() { + if ($this->removalMap) return; + + $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE]; + $stripLeft = ['left' => \T_WHITESPACE]; + $stripRight = ['right' => \T_WHITESPACE]; + $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW]; + $stripColon = ['left' => ':']; + $stripEquals = ['left' => '=']; + $this->removalMap = [ + 'Expr_ArrayDimFetch->dim' => $stripBoth, + 'Expr_ArrayItem->key' => $stripDoubleArrow, + 'Expr_ArrowFunction->returnType' => $stripColon, + 'Expr_Closure->returnType' => $stripColon, + 'Expr_Exit->expr' => $stripBoth, + 'Expr_Ternary->if' => $stripBoth, + 'Expr_Yield->key' => $stripDoubleArrow, + 'Expr_Yield->value' => $stripBoth, + 'Param->type' => $stripRight, + 'Param->default' => $stripEquals, + 'Stmt_Break->num' => $stripBoth, + 'Stmt_Catch->var' => $stripLeft, + 'Stmt_ClassConst->type' => $stripRight, + 'Stmt_ClassMethod->returnType' => $stripColon, + 'Stmt_Class->extends' => ['left' => \T_EXTENDS], + 'Stmt_Enum->scalarType' => $stripColon, + 'Stmt_EnumCase->expr' => $stripEquals, + 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], + 'Stmt_Continue->num' => $stripBoth, + 'Stmt_Foreach->keyVar' => $stripDoubleArrow, + 'Stmt_Function->returnType' => $stripColon, + 'Stmt_If->else' => $stripLeft, + 'Stmt_Namespace->name' => $stripLeft, + 'Stmt_Property->type' => $stripRight, + 'Stmt_PropertyProperty->default' => $stripEquals, + 'Stmt_Return->expr' => $stripBoth, + 'Stmt_StaticVar->default' => $stripEquals, + 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, + 'Stmt_TryCatch->finally' => $stripLeft, + // 'Stmt_Case->cond': Replace with "default" + // 'Stmt_Class->name': Unclear what to do + // 'Stmt_Declare->stmts': Not a plain node + // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a plain node + ]; + } + + protected function initializeInsertionMap() { + if ($this->insertionMap) return; + + // TODO: "yield" where both key and value are inserted doesn't work + // [$find, $beforeToken, $extraLeft, $extraRight] + $this->insertionMap = [ + 'Expr_ArrayDimFetch->dim' => ['[', false, null, null], + 'Expr_ArrayItem->key' => [null, false, null, ' => '], + 'Expr_ArrowFunction->returnType' => [')', false, ' : ', null], + 'Expr_Closure->returnType' => [')', false, ' : ', null], + 'Expr_Ternary->if' => ['?', false, ' ', ' '], + 'Expr_Yield->key' => [\T_YIELD, false, null, ' => '], + 'Expr_Yield->value' => [\T_YIELD, false, ' ', null], + 'Param->type' => [null, false, null, ' '], + 'Param->default' => [null, false, ' = ', null], + 'Stmt_Break->num' => [\T_BREAK, false, ' ', null], + 'Stmt_Catch->var' => [null, false, ' ', null], + 'Stmt_ClassMethod->returnType' => [')', false, ' : ', null], + 'Stmt_ClassConst->type' => [\T_CONST, false, ' ', null], + 'Stmt_Class->extends' => [null, false, ' extends ', null], + 'Stmt_Enum->scalarType' => [null, false, ' : ', null], + 'Stmt_EnumCase->expr' => [null, false, ' = ', null], + 'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null], + 'Stmt_Continue->num' => [\T_CONTINUE, false, ' ', null], + 'Stmt_Foreach->keyVar' => [\T_AS, false, null, ' => '], + 'Stmt_Function->returnType' => [')', false, ' : ', null], + 'Stmt_If->else' => [null, false, ' ', null], + 'Stmt_Namespace->name' => [\T_NAMESPACE, false, ' ', null], + 'Stmt_Property->type' => [\T_VARIABLE, true, null, ' '], + 'Stmt_PropertyProperty->default' => [null, false, ' = ', null], + 'Stmt_Return->expr' => [\T_RETURN, false, ' ', null], + 'Stmt_StaticVar->default' => [null, false, ' = ', null], + //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO + 'Stmt_TryCatch->finally' => [null, false, ' ', null], + + // 'Expr_Exit->expr': Complicated due to optional () + // 'Stmt_Case->cond': Conversion from default to case + // 'Stmt_Class->name': Unclear + // 'Stmt_Declare->stmts': Not a proper node + // 'Stmt_TraitUseAdaptation_Alias->newModifier': Not a proper node + ]; + } + + protected function initializeListInsertionMap() { + if ($this->listInsertionMap) return; + + $this->listInsertionMap = [ + // special + //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully + //'Scalar_Encapsed->parts' => '', + 'Stmt_Catch->types' => '|', + 'UnionType->types' => '|', + 'IntersectionType->types' => '&', + 'Stmt_If->elseifs' => ' ', + 'Stmt_TryCatch->catches' => ' ', + + // comma-separated lists + 'Expr_Array->items' => ', ', + 'Expr_ArrowFunction->params' => ', ', + 'Expr_Closure->params' => ', ', + 'Expr_Closure->uses' => ', ', + 'Expr_FuncCall->args' => ', ', + 'Expr_Isset->vars' => ', ', + 'Expr_List->items' => ', ', + 'Expr_MethodCall->args' => ', ', + 'Expr_NullsafeMethodCall->args' => ', ', + 'Expr_New->args' => ', ', + 'Expr_PrintableNewAnonClass->args' => ', ', + 'Expr_StaticCall->args' => ', ', + 'Stmt_ClassConst->consts' => ', ', + 'Stmt_ClassMethod->params' => ', ', + 'Stmt_Class->implements' => ', ', + 'Stmt_Enum->implements' => ', ', + 'Expr_PrintableNewAnonClass->implements' => ', ', + 'Stmt_Const->consts' => ', ', + 'Stmt_Declare->declares' => ', ', + 'Stmt_Echo->exprs' => ', ', + 'Stmt_For->init' => ', ', + 'Stmt_For->cond' => ', ', + 'Stmt_For->loop' => ', ', + 'Stmt_Function->params' => ', ', + 'Stmt_Global->vars' => ', ', + 'Stmt_GroupUse->uses' => ', ', + 'Stmt_Interface->extends' => ', ', + 'Stmt_Match->arms' => ', ', + 'Stmt_Property->props' => ', ', + 'Stmt_StaticVar->vars' => ', ', + 'Stmt_TraitUse->traits' => ', ', + 'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ', + 'Stmt_Unset->vars' => ', ', + 'Stmt_Use->uses' => ', ', + 'MatchArm->conds' => ', ', + 'AttributeGroup->attrs' => ', ', + + // statement lists + 'Expr_Closure->stmts' => "\n", + 'Stmt_Case->stmts' => "\n", + 'Stmt_Catch->stmts' => "\n", + 'Stmt_Class->stmts' => "\n", + 'Stmt_Enum->stmts' => "\n", + 'Expr_PrintableNewAnonClass->stmts' => "\n", + 'Stmt_Interface->stmts' => "\n", + 'Stmt_Trait->stmts' => "\n", + 'Stmt_ClassMethod->stmts' => "\n", + 'Stmt_Declare->stmts' => "\n", + 'Stmt_Do->stmts' => "\n", + 'Stmt_ElseIf->stmts' => "\n", + 'Stmt_Else->stmts' => "\n", + 'Stmt_Finally->stmts' => "\n", + 'Stmt_Foreach->stmts' => "\n", + 'Stmt_For->stmts' => "\n", + 'Stmt_Function->stmts' => "\n", + 'Stmt_If->stmts' => "\n", + 'Stmt_Namespace->stmts' => "\n", + 'Stmt_Class->attrGroups' => "\n", + 'Stmt_Enum->attrGroups' => "\n", + 'Stmt_EnumCase->attrGroups' => "\n", + 'Stmt_Interface->attrGroups' => "\n", + 'Stmt_Trait->attrGroups' => "\n", + 'Stmt_Function->attrGroups' => "\n", + 'Stmt_ClassMethod->attrGroups' => "\n", + 'Stmt_ClassConst->attrGroups' => "\n", + 'Stmt_Property->attrGroups' => "\n", + 'Expr_PrintableNewAnonClass->attrGroups' => ' ', + 'Expr_Closure->attrGroups' => ' ', + 'Expr_ArrowFunction->attrGroups' => ' ', + 'Param->attrGroups' => ' ', + 'Stmt_Switch->cases' => "\n", + 'Stmt_TraitUse->adaptations' => "\n", + 'Stmt_TryCatch->stmts' => "\n", + 'Stmt_While->stmts' => "\n", + + // dummy for top-level context + 'File->stmts' => "\n", + ]; + } + + protected function initializeEmptyListInsertionMap() { + if ($this->emptyListInsertionMap) return; + + // TODO Insertion into empty statement lists. + + // [$find, $extraLeft, $extraRight] + $this->emptyListInsertionMap = [ + 'Expr_ArrowFunction->params' => ['(', '', ''], + 'Expr_Closure->uses' => [')', ' use(', ')'], + 'Expr_Closure->params' => ['(', '', ''], + 'Expr_FuncCall->args' => ['(', '', ''], + 'Expr_MethodCall->args' => ['(', '', ''], + 'Expr_NullsafeMethodCall->args' => ['(', '', ''], + 'Expr_New->args' => ['(', '', ''], + 'Expr_PrintableNewAnonClass->args' => ['(', '', ''], + 'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''], + 'Expr_StaticCall->args' => ['(', '', ''], + 'Stmt_Class->implements' => [null, ' implements ', ''], + 'Stmt_Enum->implements' => [null, ' implements ', ''], + 'Stmt_ClassMethod->params' => ['(', '', ''], + 'Stmt_Interface->extends' => [null, ' extends ', ''], + 'Stmt_Function->params' => ['(', '', ''], + 'Stmt_Interface->attrGroups' => [null, '', "\n"], + 'Stmt_Class->attrGroups' => [null, '', "\n"], + 'Stmt_ClassConst->attrGroups' => [null, '', "\n"], + 'Stmt_ClassMethod->attrGroups' => [null, '', "\n"], + 'Stmt_Function->attrGroups' => [null, '', "\n"], + 'Stmt_Property->attrGroups' => [null, '', "\n"], + 'Stmt_Trait->attrGroups' => [null, '', "\n"], + 'Expr_ArrowFunction->attrGroups' => [null, '', ' '], + 'Expr_Closure->attrGroups' => [null, '', ' '], + 'Expr_PrintableNewAnonClass->attrGroups' => [\T_NEW, ' ', ''], + + /* These cannot be empty to start with: + * Expr_Isset->vars + * Stmt_Catch->types + * Stmt_Const->consts + * Stmt_ClassConst->consts + * Stmt_Declare->declares + * Stmt_Echo->exprs + * Stmt_Global->vars + * Stmt_GroupUse->uses + * Stmt_Property->props + * Stmt_StaticVar->vars + * Stmt_TraitUse->traits + * Stmt_TraitUseAdaptation_Precedence->insteadof + * Stmt_Unset->vars + * Stmt_Use->uses + * UnionType->types + */ + + /* TODO + * Stmt_If->elseifs + * Stmt_TryCatch->catches + * Expr_Array->items + * Expr_List->items + * Stmt_For->init + * Stmt_For->cond + * Stmt_For->loop + */ + ]; + } + + protected function initializeModifierChangeMap() { + if ($this->modifierChangeMap) return; + + $this->modifierChangeMap = [ + 'Stmt_ClassConst->flags' => \T_CONST, + 'Stmt_ClassMethod->flags' => \T_FUNCTION, + 'Stmt_Class->flags' => \T_CLASS, + 'Stmt_Property->flags' => \T_VARIABLE, + 'Expr_PrintableNewAnonClass->flags' => \T_CLASS, + 'Param->flags' => \T_VARIABLE, + //'Stmt_TraitUseAdaptation_Alias->newModifier' => 0, // TODO + ]; + + // List of integer subnodes that are not modifiers: + // Expr_Include->type + // Stmt_GroupUse->type + // Stmt_Use->type + // Stmt_UseUse->type + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/.github/FUNDING.yml b/.extlib/simplesamlphp/vendor/phar-io/manifest/.github/FUNDING.yml new file mode 100644 index 000000000..70388edb2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [theseer] diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/.github/workflows/ci.yml b/.extlib/simplesamlphp/vendor/phar-io/manifest/.github/workflows/ci.yml new file mode 100644 index 000000000..c9e7feb09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/.github/workflows/ci.yml @@ -0,0 +1,86 @@ +name: "CI" + +on: + push: + branches: + - "master" + pull_request: null + +jobs: + qa: + name: "QA" + + runs-on: "ubuntu-latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v3.5.2" + + - name: "Set up PHP" + uses: "shivammathur/setup-php@2.25.1" + with: + coverage: "none" + php-version: "8.0" + tools: "phive" + + - name: "Install dependencies with composer" + run: "composer install --no-interaction --optimize-autoloader --prefer-dist" + + - name: "Install dependencies with phive" + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: "ant install-tools" + + - name: "Run php-cs-fixer" + run: "ant php-cs-fixer" + + - name: "Run psalm" + run: "ant psalm" + + tests: + name: "Tests" + + runs-on: "ubuntu-latest" + + strategy: + fail-fast: false + + matrix: + php-versions: + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + - "8.2" + + steps: + - name: "Checkout" + uses: "actions/checkout@v3.5.2" + + - name: "Set up PHP" + uses: "shivammathur/setup-php@2.25.1" + env: + COMPOSER_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + with: + coverage: "pcov" + extensions: "${{ env.extensions }}" + ini-values: "display_errors=On, error_reporting=-1, memory_limit=2G" + php-version: "${{ matrix.php-versions }}" + tools: "phive" + + - name: "Install dependencies with composer" + run: "composer install --no-interaction --optimize-autoloader --prefer-dist" + + - name: "Install dependencies with phive" + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: "ant install-tools" + + - name: "Run PHPUnit" + run: "tools/phpunit --coverage-clover build/logs/clover.xml" + + - name: "Send code coverage report to codecov.io" + uses: "codecov/codecov-action@v3.1.4" + with: + files: "build/logs/clover.xml" diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/.php-cs-fixer.dist.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/.php-cs-fixer.dist.php new file mode 100644 index 000000000..ca965141a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/.php-cs-fixer.dist.php @@ -0,0 +1,223 @@ +registerCustomFixers([ + new \PharIo\CSFixer\PhpdocSingleLineVarFixer() + ]) + ->setRiskyAllowed(true) + ->setRules( + [ + 'PharIo/phpdoc_single_line_var_fixer' => true, + + 'align_multiline_comment' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'binary_operator_spaces' => [ + 'operators' => [ + '=' => 'align', + '=>' => 'align', + ], + ], + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => false, + 'blank_line_before_statement' => [ + 'statements' => [ + 'break', + 'continue', + 'declare', + 'do', + 'for', + 'foreach', + 'if', + 'include', + 'include_once', + 'require', + 'require_once', + 'return', + 'switch', + 'throw', + 'try', + 'while', + 'yield', + ], + ], + 'braces' => [ + 'allow_single_line_closure' => false, + 'position_after_anonymous_constructs' => 'same', + 'position_after_control_structures' => 'same', + 'position_after_functions_and_oop_constructs' => 'same' + ], + 'cast_spaces' => ['space' => 'none'], + + // This fixer removes the blank line at class start, no way to disable that, so we disable the fixer :( + //'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], + + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'date_time_immutable' => true, + 'declare_equal_normalize' => ['space' => 'single'], + 'declare_strict_types' => true, + 'dir_constant' => true, + 'elseif' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => true, + 'function_declaration' => [ + 'closure_function_spacing' => 'one' + ], + 'global_namespace_import' => [ + 'import_classes' => true, + 'import_constants' => true, + 'import_functions' => true, + ], + 'header_comment' => ['header' => $header, 'separate' => 'none'], + 'indentation_type' => true, + 'is_null' => true, + 'line_ending' => true, + 'list_syntax' => ['syntax' => 'short'], + 'logical_operators' => true, + 'lowercase_cast' => true, + 'constant_case' => ['case' => 'lower'], + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'], + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => true, + 'new_with_braces' => false, + 'no_alias_functions' => true, + 'no_alternative_syntax' => true, + 'no_blank_lines_after_class_opening' => false, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => ['use' => 'print'], + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_short_bool_cast' => true, + 'echo_tag_syntax' => ['format' => 'long'], + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_elseif' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => false, + 'no_unneeded_curly_braces' => false, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'non_printable_character' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => [ + 'order' => [ + 'use_trait', + 'constant_public', + 'constant_protected', + 'constant_private', + 'property_public_static', + 'property_protected_static', + 'property_private_static', + 'property_public', + 'property_protected', + 'property_private', + 'method_public_static', + 'construct', + 'destruct', + 'magic', + 'phpunit', + 'method_public', + 'method_protected', + 'method_private', + 'method_protected_static', + 'method_private_static', + ], + ], + 'ordered_imports' => [ + 'imports_order' => [ + PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_CLASS, + PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_CONST, + PhpCsFixer\Fixer\Import\OrderedImportsFixer::IMPORT_TYPE_FUNCTION, + ] + ], + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_align' => true, + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => ['groups' => ['simple', 'meta']], + 'phpdoc_types_order' => true, + 'phpdoc_to_return_type' => true, + 'phpdoc_var_without_name' => true, + 'pow_to_exponentiation' => true, + 'protected_to_private' => true, + 'return_assignment' => true, + 'return_type_declaration' => ['space_before' => 'none'], + 'self_accessor' => false, + 'semicolon_after_instruction' => true, + 'set_type_to_cast' => true, + 'short_scalar_cast' => true, + 'simplified_null_return' => true, + 'single_blank_line_at_eof' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_quote' => true, + 'standardize_not_equals' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline' => false, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => [ + 'elements' => [ + 'const', + 'method', + 'property', + ], + ], + 'void_return' => true, + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => false + ] + ) + ->setFinder( + PhpCsFixer\Finder::create() + ->files() + ->in(__DIR__ . '/build') + ->in(__DIR__ . '/src') + ->in(__DIR__ . '/tests') + ->notName('autoload.php') + ); diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/CHANGELOG.md b/.extlib/simplesamlphp/vendor/phar-io/manifest/CHANGELOG.md new file mode 100644 index 000000000..f363b169b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/CHANGELOG.md @@ -0,0 +1,45 @@ +# Changelog + +All notable changes to phar-io/manifest are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.0.4] - 03-03-2024 + +### Changed + +- Make `EMail` an optional attribute for author +- Stick with PHP 7.2 compatibilty +- Do not use implict nullable type (thanks @sebastianbergmann), this should make things work on PHP 8.4 + +## [2.0.3] - 20.07.2021 + +- Fixed PHP 7.2 / PHP 7.3 incompatibility introduced in previous release + +## [2.0.2] - 20.07.2021 + +- Fixed PHP 8.1 deprecation notice + +## [2.0.1] - 27.06.2020 + +This release now supports the use of PHP 7.2+ and ^8.0 + +## [2.0.0] - 10.05.2020 + +This release now requires PHP 7.2+ + +### Changed + +- Upgraded to phar-io/version 3.0 + - Version strings `v1.2.3` will now be converted to valid semantic version strings `1.2.3` + - Abreviated strings like `1.0` will get expaneded to `1.0.0` + +### Unreleased + +[Unreleased]: https://github.com/phar-io/manifest/compare/2.1.0...HEAD +[2.1.0]: https://github.com/phar-io/manifest/compare/2.0.3...2.1.0 +[2.0.3]: https://github.com/phar-io/manifest/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/phar-io/manifest/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/phar-io/manifest/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/phar-io/manifest/compare/1.0.1...2.0.0 +[1.0.3]: https://github.com/phar-io/manifest/compare/1.0.2...1.0.3 +[1.0.2]: https://github.com/phar-io/manifest/compare/1.0.1...1.0.2 +[1.0.1]: https://github.com/phar-io/manifest/compare/1.0.0...1.0.1 diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/LICENSE b/.extlib/simplesamlphp/vendor/phar-io/manifest/LICENSE new file mode 100644 index 000000000..64690cf2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/LICENSE @@ -0,0 +1,31 @@ +Phar.io - Manifest + +Copyright (c) 2016-2019 Arne Blankerts , Sebastian Heuer , Sebastian Bergmann , and contributors +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 Arne Blankerts nor the names of 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 HOLDER 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/.extlib/simplesamlphp/vendor/phar-io/manifest/README.md b/.extlib/simplesamlphp/vendor/phar-io/manifest/README.md new file mode 100644 index 000000000..fae2c9a78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/README.md @@ -0,0 +1,178 @@ +# Manifest + +Component for reading [phar.io](https://phar.io/) manifest information from a [PHP Archive (PHAR)](http://php.net/phar). + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phar-io/manifest + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phar-io/manifest + +## Usage Examples + +### Read from `manifest.xml` +```php +use PharIo\Manifest\ManifestLoader; +use PharIo\Manifest\ManifestSerializer; + +$manifest = ManifestLoader::fromFile('manifest.xml'); + +var_dump($manifest); + +echo (new ManifestSerializer)->serializeToString($manifest); +``` + +
    + Output + +```shell +object(PharIo\Manifest\Manifest)#14 (6) { + ["name":"PharIo\Manifest\Manifest":private]=> + object(PharIo\Manifest\ApplicationName)#10 (1) { + ["name":"PharIo\Manifest\ApplicationName":private]=> + string(12) "some/library" + } + ["version":"PharIo\Manifest\Manifest":private]=> + object(PharIo\Version\Version)#12 (5) { + ["originalVersionString":"PharIo\Version\Version":private]=> + string(5) "1.0.0" + ["major":"PharIo\Version\Version":private]=> + object(PharIo\Version\VersionNumber)#13 (1) { + ["value":"PharIo\Version\VersionNumber":private]=> + int(1) + } + ["minor":"PharIo\Version\Version":private]=> + object(PharIo\Version\VersionNumber)#23 (1) { + ["value":"PharIo\Version\VersionNumber":private]=> + int(0) + } + ["patch":"PharIo\Version\Version":private]=> + object(PharIo\Version\VersionNumber)#22 (1) { + ["value":"PharIo\Version\VersionNumber":private]=> + int(0) + } + ["preReleaseSuffix":"PharIo\Version\Version":private]=> + NULL + } + ["type":"PharIo\Manifest\Manifest":private]=> + object(PharIo\Manifest\Library)#6 (0) { + } + ["copyrightInformation":"PharIo\Manifest\Manifest":private]=> + object(PharIo\Manifest\CopyrightInformation)#19 (2) { + ["authors":"PharIo\Manifest\CopyrightInformation":private]=> + object(PharIo\Manifest\AuthorCollection)#9 (1) { + ["authors":"PharIo\Manifest\AuthorCollection":private]=> + array(1) { + [0]=> + object(PharIo\Manifest\Author)#15 (2) { + ["name":"PharIo\Manifest\Author":private]=> + string(13) "Reiner Zufall" + ["email":"PharIo\Manifest\Author":private]=> + object(PharIo\Manifest\Email)#16 (1) { + ["email":"PharIo\Manifest\Email":private]=> + string(16) "reiner@zufall.de" + } + } + } + } + ["license":"PharIo\Manifest\CopyrightInformation":private]=> + object(PharIo\Manifest\License)#11 (2) { + ["name":"PharIo\Manifest\License":private]=> + string(12) "BSD-3-Clause" + ["url":"PharIo\Manifest\License":private]=> + object(PharIo\Manifest\Url)#18 (1) { + ["url":"PharIo\Manifest\Url":private]=> + string(26) "https://domain.tld/LICENSE" + } + } + } + ["requirements":"PharIo\Manifest\Manifest":private]=> + object(PharIo\Manifest\RequirementCollection)#17 (1) { + ["requirements":"PharIo\Manifest\RequirementCollection":private]=> + array(1) { + [0]=> + object(PharIo\Manifest\PhpVersionRequirement)#20 (1) { + ["versionConstraint":"PharIo\Manifest\PhpVersionRequirement":private]=> + object(PharIo\Version\SpecificMajorAndMinorVersionConstraint)#24 (3) { + ["originalValue":"PharIo\Version\AbstractVersionConstraint":private]=> + string(3) "7.0" + ["major":"PharIo\Version\SpecificMajorAndMinorVersionConstraint":private]=> + int(7) + ["minor":"PharIo\Version\SpecificMajorAndMinorVersionConstraint":private]=> + int(0) + } + } + } + } + ["bundledComponents":"PharIo\Manifest\Manifest":private]=> + object(PharIo\Manifest\BundledComponentCollection)#8 (1) { + ["bundledComponents":"PharIo\Manifest\BundledComponentCollection":private]=> + array(0) { + } + } +} + + + + + + + + + + + +``` +
    + +### Create via API +```php +$bundled = new \PharIo\Manifest\BundledComponentCollection(); +$bundled->add( + new \PharIo\Manifest\BundledComponent('vendor/packageA', new \PharIo\Version\Version('1.2.3-dev') + ) +); + +$manifest = new PharIo\Manifest\Manifest( + new \PharIo\Manifest\ApplicationName('vendor/package'), + new \PharIo\Version\Version('1.0.0'), + new \PharIo\Manifest\Library(), + new \PharIo\Manifest\CopyrightInformation( + new \PharIo\Manifest\AuthorCollection(), + new \PharIo\Manifest\License( + 'BSD-3-Clause', + new \PharIo\Manifest\Url('https://spdx.org/licenses/BSD-3-Clause.html') + ) + ), + new \PharIo\Manifest\RequirementCollection(), + $bundled +); + +echo (new ManifestSerializer)->serializeToString($manifest); +``` + +
    + Output + +```xml + + + + + + + + + + + + + +``` + +
    + diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/composer.json b/.extlib/simplesamlphp/vendor/phar-io/manifest/composer.json new file mode 100644 index 000000000..dc5fa4589 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/composer.json @@ -0,0 +1,43 @@ +{ + "name": "phar-io/manifest", + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/phar-io/manifest/issues" + }, + "require": { + "php": "^7.2 || ^8.0", + "ext-dom": "*", + "ext-phar": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/composer.lock b/.extlib/simplesamlphp/vendor/phar-io/manifest/composer.lock new file mode 100644 index 000000000..fe18e08b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/composer.lock @@ -0,0 +1,76 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "279b3c4fe44357abd924fdcc0cfa5664", + "packages": [ + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.2 || ^8.0", + "ext-dom": "*", + "ext-phar": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/manifest.xsd b/.extlib/simplesamlphp/vendor/phar-io/manifest/manifest.xsd new file mode 100644 index 000000000..63e3f1cbd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/manifest.xsd @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestDocumentMapper.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestDocumentMapper.php new file mode 100644 index 000000000..3da6403f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestDocumentMapper.php @@ -0,0 +1,151 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\Exception as VersionException; +use PharIo\Version\Version; +use PharIo\Version\VersionConstraintParser; +use Throwable; +use function sprintf; + +class ManifestDocumentMapper { + public function map(ManifestDocument $document): Manifest { + try { + $contains = $document->getContainsElement(); + $type = $this->mapType($contains); + $copyright = $this->mapCopyright($document->getCopyrightElement()); + $requirements = $this->mapRequirements($document->getRequiresElement()); + $bundledComponents = $this->mapBundledComponents($document); + + return new Manifest( + new ApplicationName($contains->getName()), + new Version($contains->getVersion()), + $type, + $copyright, + $requirements, + $bundledComponents + ); + } catch (Throwable $e) { + throw new ManifestDocumentMapperException($e->getMessage(), (int)$e->getCode(), $e); + } + } + + private function mapType(ContainsElement $contains): Type { + switch ($contains->getType()) { + case 'application': + return Type::application(); + case 'library': + return Type::library(); + case 'extension': + return $this->mapExtension($contains->getExtensionElement()); + } + + throw new ManifestDocumentMapperException( + sprintf('Unsupported type %s', $contains->getType()) + ); + } + + private function mapCopyright(CopyrightElement $copyright): CopyrightInformation { + $authors = new AuthorCollection(); + + foreach ($copyright->getAuthorElements() as $authorElement) { + $authors->add( + new Author( + $authorElement->getName(), + $authorElement->hasEMail() ? new Email($authorElement->getEmail()) : null + ) + ); + } + + $licenseElement = $copyright->getLicenseElement(); + $license = new License( + $licenseElement->getType(), + new Url($licenseElement->getUrl()) + ); + + return new CopyrightInformation( + $authors, + $license + ); + } + + private function mapRequirements(RequiresElement $requires): RequirementCollection { + $collection = new RequirementCollection(); + $phpElement = $requires->getPHPElement(); + $parser = new VersionConstraintParser; + + try { + $versionConstraint = $parser->parse($phpElement->getVersion()); + } catch (VersionException $e) { + throw new ManifestDocumentMapperException( + sprintf('Unsupported version constraint - %s', $e->getMessage()), + (int)$e->getCode(), + $e + ); + } + + $collection->add( + new PhpVersionRequirement( + $versionConstraint + ) + ); + + if (!$phpElement->hasExtElements()) { + return $collection; + } + + foreach ($phpElement->getExtElements() as $extElement) { + $collection->add( + new PhpExtensionRequirement($extElement->getName()) + ); + } + + return $collection; + } + + private function mapBundledComponents(ManifestDocument $document): BundledComponentCollection { + $collection = new BundledComponentCollection(); + + if (!$document->hasBundlesElement()) { + return $collection; + } + + foreach ($document->getBundlesElement()->getComponentElements() as $componentElement) { + $collection->add( + new BundledComponent( + $componentElement->getName(), + new Version( + $componentElement->getVersion() + ) + ) + ); + } + + return $collection; + } + + private function mapExtension(ExtensionElement $extension): Extension { + try { + $versionConstraint = (new VersionConstraintParser)->parse($extension->getCompatible()); + + return Type::extension( + new ApplicationName($extension->getFor()), + $versionConstraint + ); + } catch (VersionException $e) { + throw new ManifestDocumentMapperException( + sprintf('Unsupported version constraint - %s', $e->getMessage()), + (int)$e->getCode(), + $e + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestLoader.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestLoader.php new file mode 100644 index 000000000..f467d2d3b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestLoader.php @@ -0,0 +1,47 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use function sprintf; + +class ManifestLoader { + public static function fromFile(string $filename): Manifest { + try { + return (new ManifestDocumentMapper())->map( + ManifestDocument::fromFile($filename) + ); + } catch (Exception $e) { + throw new ManifestLoaderException( + sprintf('Loading %s failed.', $filename), + (int)$e->getCode(), + $e + ); + } + } + + public static function fromPhar(string $filename): Manifest { + return self::fromFile('phar://' . $filename . '/manifest.xml'); + } + + public static function fromString(string $manifest): Manifest { + try { + return (new ManifestDocumentMapper())->map( + ManifestDocument::fromString($manifest) + ); + } catch (Exception $e) { + throw new ManifestLoaderException( + 'Processing string failed', + (int)$e->getCode(), + $e + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestSerializer.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestSerializer.php new file mode 100644 index 000000000..48b8efddf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/ManifestSerializer.php @@ -0,0 +1,172 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\AnyVersionConstraint; +use PharIo\Version\Version; +use PharIo\Version\VersionConstraint; +use XMLWriter; +use function count; +use function file_put_contents; +use function str_repeat; + +/** @psalm-suppress MissingConstructor */ +class ManifestSerializer { + /** @var XMLWriter */ + private $xmlWriter; + + public function serializeToFile(Manifest $manifest, string $filename): void { + file_put_contents( + $filename, + $this->serializeToString($manifest) + ); + } + + public function serializeToString(Manifest $manifest): string { + $this->startDocument(); + + $this->addContains($manifest->getName(), $manifest->getVersion(), $manifest->getType()); + $this->addCopyright($manifest->getCopyrightInformation()); + $this->addRequirements($manifest->getRequirements()); + $this->addBundles($manifest->getBundledComponents()); + + return $this->finishDocument(); + } + + private function startDocument(): void { + $xmlWriter = new XMLWriter(); + $xmlWriter->openMemory(); + $xmlWriter->setIndent(true); + $xmlWriter->setIndentString(str_repeat(' ', 4)); + $xmlWriter->startDocument('1.0', 'UTF-8'); + $xmlWriter->startElement('phar'); + $xmlWriter->writeAttribute('xmlns', 'https://phar.io/xml/manifest/1.0'); + + $this->xmlWriter = $xmlWriter; + } + + private function finishDocument(): string { + $this->xmlWriter->endElement(); + $this->xmlWriter->endDocument(); + + return $this->xmlWriter->outputMemory(); + } + + private function addContains(ApplicationName $name, Version $version, Type $type): void { + $this->xmlWriter->startElement('contains'); + $this->xmlWriter->writeAttribute('name', $name->asString()); + $this->xmlWriter->writeAttribute('version', $version->getVersionString()); + + switch (true) { + case $type->isApplication(): { + $this->xmlWriter->writeAttribute('type', 'application'); + + break; + } + + case $type->isLibrary(): { + $this->xmlWriter->writeAttribute('type', 'library'); + + break; + } + + case $type->isExtension(): { + $this->xmlWriter->writeAttribute('type', 'extension'); + /* @var $type Extension */ + $this->addExtension( + $type->getApplicationName(), + $type->getVersionConstraint() + ); + + break; + } + + default: { + $this->xmlWriter->writeAttribute('type', 'custom'); + } + } + + $this->xmlWriter->endElement(); + } + + private function addCopyright(CopyrightInformation $copyrightInformation): void { + $this->xmlWriter->startElement('copyright'); + + foreach ($copyrightInformation->getAuthors() as $author) { + $this->xmlWriter->startElement('author'); + $this->xmlWriter->writeAttribute('name', $author->getName()); + $this->xmlWriter->writeAttribute('email', $author->getEmail()->asString()); + $this->xmlWriter->endElement(); + } + + $license = $copyrightInformation->getLicense(); + + $this->xmlWriter->startElement('license'); + $this->xmlWriter->writeAttribute('type', $license->getName()); + $this->xmlWriter->writeAttribute('url', $license->getUrl()->asString()); + $this->xmlWriter->endElement(); + + $this->xmlWriter->endElement(); + } + + private function addRequirements(RequirementCollection $requirementCollection): void { + $phpRequirement = new AnyVersionConstraint(); + $extensions = []; + + foreach ($requirementCollection as $requirement) { + if ($requirement instanceof PhpVersionRequirement) { + $phpRequirement = $requirement->getVersionConstraint(); + + continue; + } + + if ($requirement instanceof PhpExtensionRequirement) { + $extensions[] = $requirement->asString(); + } + } + + $this->xmlWriter->startElement('requires'); + $this->xmlWriter->startElement('php'); + $this->xmlWriter->writeAttribute('version', $phpRequirement->asString()); + + foreach ($extensions as $extension) { + $this->xmlWriter->startElement('ext'); + $this->xmlWriter->writeAttribute('name', $extension); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->endElement(); + $this->xmlWriter->endElement(); + } + + private function addBundles(BundledComponentCollection $bundledComponentCollection): void { + if (count($bundledComponentCollection) === 0) { + return; + } + $this->xmlWriter->startElement('bundles'); + + foreach ($bundledComponentCollection as $bundledComponent) { + $this->xmlWriter->startElement('component'); + $this->xmlWriter->writeAttribute('name', $bundledComponent->getName()); + $this->xmlWriter->writeAttribute('version', $bundledComponent->getVersion()->getVersionString()); + $this->xmlWriter->endElement(); + } + + $this->xmlWriter->endElement(); + } + + private function addExtension(ApplicationName $applicationName, VersionConstraint $versionConstraint): void { + $this->xmlWriter->startElement('extension'); + $this->xmlWriter->writeAttribute('for', $applicationName->asString()); + $this->xmlWriter->writeAttribute('compatible', $versionConstraint->asString()); + $this->xmlWriter->endElement(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php new file mode 100644 index 000000000..7528afc89 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ElementCollectionException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use InvalidArgumentException; + +class ElementCollectionException extends InvalidArgumentException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/Exception.php new file mode 100644 index 000000000..0c135d3c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/Exception.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Throwable; + +interface Exception extends Throwable { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php new file mode 100644 index 000000000..ecfe5142a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidApplicationNameException.php @@ -0,0 +1,17 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use InvalidArgumentException; + +class InvalidApplicationNameException extends InvalidArgumentException implements Exception { + public const InvalidFormat = 2; +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php new file mode 100644 index 000000000..242405518 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidEmailException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use InvalidArgumentException; + +class InvalidEmailException extends InvalidArgumentException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php new file mode 100644 index 000000000..c8b192b14 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/InvalidUrlException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use InvalidArgumentException; + +class InvalidUrlException extends InvalidArgumentException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php new file mode 100644 index 000000000..0a158e6e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use RuntimeException; + +class ManifestDocumentException extends RuntimeException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php new file mode 100644 index 000000000..816af1205 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentLoadingException.php @@ -0,0 +1,47 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use LibXMLError; +use function sprintf; + +class ManifestDocumentLoadingException extends \Exception implements Exception { + /** @var LibXMLError[] */ + private $libxmlErrors; + + /** + * ManifestDocumentLoadingException constructor. + * + * @param LibXMLError[] $libxmlErrors + */ + public function __construct(array $libxmlErrors) { + $this->libxmlErrors = $libxmlErrors; + $first = $this->libxmlErrors[0]; + + parent::__construct( + sprintf( + '%s (Line: %d / Column: %d / File: %s)', + $first->message, + $first->line, + $first->column, + $first->file + ), + $first->code + ); + } + + /** + * @return LibXMLError[] + */ + public function getLibxmlErrors(): array { + return $this->libxmlErrors; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php new file mode 100644 index 000000000..0d1a5f5a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestDocumentMapperException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use RuntimeException; + +class ManifestDocumentMapperException extends RuntimeException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php new file mode 100644 index 000000000..46f82e32e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestElementException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use RuntimeException; + +class ManifestElementException extends RuntimeException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php new file mode 100644 index 000000000..d00ed190c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/ManifestLoaderException.php @@ -0,0 +1,14 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ManifestLoaderException extends \Exception implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/NoEmailAddressException.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/NoEmailAddressException.php new file mode 100644 index 000000000..279131267 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/exceptions/NoEmailAddressException.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use InvalidArgumentException; + +class NoEmailAddressException extends InvalidArgumentException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Application.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Application.php new file mode 100644 index 000000000..11a44d9cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Application.php @@ -0,0 +1,17 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class Application extends Type { + public function isApplication(): bool { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/ApplicationName.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/ApplicationName.php new file mode 100644 index 000000000..1a0ad1e2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/ApplicationName.php @@ -0,0 +1,41 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use function preg_match; +use function sprintf; + +class ApplicationName { + /** @var string */ + private $name; + + public function __construct(string $name) { + $this->ensureValidFormat($name); + $this->name = $name; + } + + public function asString(): string { + return $this->name; + } + + public function isEqual(ApplicationName $name): bool { + return $this->name === $name->name; + } + + private function ensureValidFormat(string $name): void { + if (!preg_match('#\w/\w#', $name)) { + throw new InvalidApplicationNameException( + sprintf('Format of name "%s" is not valid - expected: vendor/packagename', $name), + InvalidApplicationNameException::InvalidFormat + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Author.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Author.php new file mode 100644 index 000000000..7b243aace --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Author.php @@ -0,0 +1,57 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use function sprintf; + +class Author { + /** @var string */ + private $name; + + /** @var null|Email */ + private $email; + + public function __construct(string $name, ?Email $email = null) { + $this->name = $name; + $this->email = $email; + } + + public function asString(): string { + if (!$this->hasEmail()) { + return $this->name; + } + + return sprintf( + '%s <%s>', + $this->name, + $this->email->asString() + ); + } + + public function getName(): string { + return $this->name; + } + + /** + * @psalm-assert-if-true Email $this->email + */ + public function hasEmail(): bool { + return $this->email !== null; + } + + public function getEmail(): Email { + if (!$this->hasEmail()) { + throw new NoEmailAddressException(); + } + + return $this->email; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollection.php new file mode 100644 index 000000000..549876da7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollection.php @@ -0,0 +1,40 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Countable; +use IteratorAggregate; +use function count; + +/** @template-implements IteratorAggregate */ +class AuthorCollection implements Countable, IteratorAggregate { + /** @var Author[] */ + private $authors = []; + + public function add(Author $author): void { + $this->authors[] = $author; + } + + /** + * @return Author[] + */ + public function getAuthors(): array { + return $this->authors; + } + + public function count(): int { + return count($this->authors); + } + + public function getIterator(): AuthorCollectionIterator { + return new AuthorCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php new file mode 100644 index 000000000..36fee9f7f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/AuthorCollectionIterator.php @@ -0,0 +1,47 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Iterator; +use function count; + +/** @template-implements Iterator */ +class AuthorCollectionIterator implements Iterator { + /** @var Author[] */ + private $authors; + + /** @var int */ + private $position = 0; + + public function __construct(AuthorCollection $authors) { + $this->authors = $authors->getAuthors(); + } + + public function rewind(): void { + $this->position = 0; + } + + public function valid(): bool { + return $this->position < count($this->authors); + } + + public function key(): int { + return $this->position; + } + + public function current(): Author { + return $this->authors[$this->position]; + } + + public function next(): void { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponent.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponent.php new file mode 100644 index 000000000..581703689 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponent.php @@ -0,0 +1,34 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\Version; + +class BundledComponent { + /** @var string */ + private $name; + + /** @var Version */ + private $version; + + public function __construct(string $name, Version $version) { + $this->name = $name; + $this->version = $version; + } + + public function getName(): string { + return $this->name; + } + + public function getVersion(): Version { + return $this->version; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollection.php new file mode 100644 index 000000000..28aaa06ca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollection.php @@ -0,0 +1,40 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Countable; +use IteratorAggregate; +use function count; + +/** @template-implements IteratorAggregate */ +class BundledComponentCollection implements Countable, IteratorAggregate { + /** @var BundledComponent[] */ + private $bundledComponents = []; + + public function add(BundledComponent $bundledComponent): void { + $this->bundledComponents[] = $bundledComponent; + } + + /** + * @return BundledComponent[] + */ + public function getBundledComponents(): array { + return $this->bundledComponents; + } + + public function count(): int { + return count($this->bundledComponents); + } + + public function getIterator(): BundledComponentCollectionIterator { + return new BundledComponentCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php new file mode 100644 index 000000000..5c72817dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/BundledComponentCollectionIterator.php @@ -0,0 +1,47 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Iterator; +use function count; + +/** @template-implements Iterator */ +class BundledComponentCollectionIterator implements Iterator { + /** @var BundledComponent[] */ + private $bundledComponents; + + /** @var int */ + private $position = 0; + + public function __construct(BundledComponentCollection $bundledComponents) { + $this->bundledComponents = $bundledComponents->getBundledComponents(); + } + + public function rewind(): void { + $this->position = 0; + } + + public function valid(): bool { + return $this->position < count($this->bundledComponents); + } + + public function key(): int { + return $this->position; + } + + public function current(): BundledComponent { + return $this->bundledComponents[$this->position]; + } + + public function next(): void { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/CopyrightInformation.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/CopyrightInformation.php new file mode 100644 index 000000000..b4468ed71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/CopyrightInformation.php @@ -0,0 +1,32 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class CopyrightInformation { + /** @var AuthorCollection */ + private $authors; + + /** @var License */ + private $license; + + public function __construct(AuthorCollection $authors, License $license) { + $this->authors = $authors; + $this->license = $license; + } + + public function getAuthors(): AuthorCollection { + return $this->authors; + } + + public function getLicense(): License { + return $this->license; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Email.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Email.php new file mode 100644 index 000000000..dbaff84a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Email.php @@ -0,0 +1,35 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use const FILTER_VALIDATE_EMAIL; +use function filter_var; + +class Email { + /** @var string */ + private $email; + + public function __construct(string $email) { + $this->ensureEmailIsValid($email); + + $this->email = $email; + } + + public function asString(): string { + return $this->email; + } + + private function ensureEmailIsValid(string $url): void { + if (filter_var($url, FILTER_VALIDATE_EMAIL) === false) { + throw new InvalidEmailException; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Extension.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Extension.php new file mode 100644 index 000000000..abcd2f891 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Extension.php @@ -0,0 +1,47 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\Version; +use PharIo\Version\VersionConstraint; + +class Extension extends Type { + /** @var ApplicationName */ + private $application; + + /** @var VersionConstraint */ + private $versionConstraint; + + public function __construct(ApplicationName $application, VersionConstraint $versionConstraint) { + $this->application = $application; + $this->versionConstraint = $versionConstraint; + } + + public function getApplicationName(): ApplicationName { + return $this->application; + } + + public function getVersionConstraint(): VersionConstraint { + return $this->versionConstraint; + } + + public function isExtension(): bool { + return true; + } + + public function isExtensionFor(ApplicationName $name): bool { + return $this->application->isEqual($name); + } + + public function isCompatibleWith(ApplicationName $name, Version $version): bool { + return $this->isExtensionFor($name) && $this->versionConstraint->complies($version); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Library.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Library.php new file mode 100644 index 000000000..97c292dc0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Library.php @@ -0,0 +1,17 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class Library extends Type { + public function isLibrary(): bool { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/License.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/License.php new file mode 100644 index 000000000..c2d94299c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/License.php @@ -0,0 +1,32 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class License { + /** @var string */ + private $name; + + /** @var Url */ + private $url; + + public function __construct(string $name, Url $url) { + $this->name = $name; + $this->url = $url; + } + + public function getName(): string { + return $this->name; + } + + public function getUrl(): Url { + return $this->url; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Manifest.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Manifest.php new file mode 100644 index 000000000..36466820d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Manifest.php @@ -0,0 +1,93 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\Version; + +class Manifest { + /** @var ApplicationName */ + private $name; + + /** @var Version */ + private $version; + + /** @var Type */ + private $type; + + /** @var CopyrightInformation */ + private $copyrightInformation; + + /** @var RequirementCollection */ + private $requirements; + + /** @var BundledComponentCollection */ + private $bundledComponents; + + public function __construct(ApplicationName $name, Version $version, Type $type, CopyrightInformation $copyrightInformation, RequirementCollection $requirements, BundledComponentCollection $bundledComponents) { + $this->name = $name; + $this->version = $version; + $this->type = $type; + $this->copyrightInformation = $copyrightInformation; + $this->requirements = $requirements; + $this->bundledComponents = $bundledComponents; + } + + public function getName(): ApplicationName { + return $this->name; + } + + public function getVersion(): Version { + return $this->version; + } + + public function getType(): Type { + return $this->type; + } + + public function getCopyrightInformation(): CopyrightInformation { + return $this->copyrightInformation; + } + + public function getRequirements(): RequirementCollection { + return $this->requirements; + } + + public function getBundledComponents(): BundledComponentCollection { + return $this->bundledComponents; + } + + public function isApplication(): bool { + return $this->type->isApplication(); + } + + public function isLibrary(): bool { + return $this->type->isLibrary(); + } + + public function isExtension(): bool { + return $this->type->isExtension(); + } + + public function isExtensionFor(ApplicationName $application, ?Version $version = null): bool { + if (!$this->isExtension()) { + return false; + } + + /** @var Extension $type */ + $type = $this->type; + + if ($version !== null) { + return $type->isCompatibleWith($application, $version); + } + + return $type->isExtensionFor($application); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php new file mode 100644 index 000000000..f81bd2597 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpExtensionRequirement.php @@ -0,0 +1,24 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class PhpExtensionRequirement implements Requirement { + /** @var string */ + private $extension; + + public function __construct(string $extension) { + $this->extension = $extension; + } + + public function asString(): string { + return $this->extension; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php new file mode 100644 index 000000000..fb30c3b8f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/PhpVersionRequirement.php @@ -0,0 +1,26 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\VersionConstraint; + +class PhpVersionRequirement implements Requirement { + /** @var VersionConstraint */ + private $versionConstraint; + + public function __construct(VersionConstraint $versionConstraint) { + $this->versionConstraint = $versionConstraint; + } + + public function getVersionConstraint(): VersionConstraint { + return $this->versionConstraint; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Requirement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Requirement.php new file mode 100644 index 000000000..d4b464015 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Requirement.php @@ -0,0 +1,14 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +interface Requirement { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollection.php new file mode 100644 index 000000000..e4fe2a112 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollection.php @@ -0,0 +1,40 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Countable; +use IteratorAggregate; +use function count; + +/** @template-implements IteratorAggregate */ +class RequirementCollection implements Countable, IteratorAggregate { + /** @var Requirement[] */ + private $requirements = []; + + public function add(Requirement $requirement): void { + $this->requirements[] = $requirement; + } + + /** + * @return Requirement[] + */ + public function getRequirements(): array { + return $this->requirements; + } + + public function count(): int { + return count($this->requirements); + } + + public function getIterator(): RequirementCollectionIterator { + return new RequirementCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php new file mode 100644 index 000000000..a587468c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/RequirementCollectionIterator.php @@ -0,0 +1,47 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use Iterator; +use function count; + +/** @template-implements Iterator */ +class RequirementCollectionIterator implements Iterator { + /** @var Requirement[] */ + private $requirements; + + /** @var int */ + private $position = 0; + + public function __construct(RequirementCollection $requirements) { + $this->requirements = $requirements->getRequirements(); + } + + public function rewind(): void { + $this->position = 0; + } + + public function valid(): bool { + return $this->position < count($this->requirements); + } + + public function key(): int { + return $this->position; + } + + public function current(): Requirement { + return $this->requirements[$this->position]; + } + + public function next(): void { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Type.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Type.php new file mode 100644 index 000000000..231e7fd9c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Type.php @@ -0,0 +1,42 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use PharIo\Version\VersionConstraint; + +abstract class Type { + public static function application(): Application { + return new Application; + } + + public static function library(): Library { + return new Library; + } + + public static function extension(ApplicationName $application, VersionConstraint $versionConstraint): Extension { + return new Extension($application, $versionConstraint); + } + + /** @psalm-assert-if-true Application $this */ + public function isApplication(): bool { + return false; + } + + /** @psalm-assert-if-true Library $this */ + public function isLibrary(): bool { + return false; + } + + /** @psalm-assert-if-true Extension $this */ + public function isExtension(): bool { + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Url.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Url.php new file mode 100644 index 000000000..980615545 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/values/Url.php @@ -0,0 +1,38 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use const FILTER_VALIDATE_URL; +use function filter_var; + +class Url { + /** @var string */ + private $url; + + public function __construct(string $url) { + $this->ensureUrlIsValid($url); + + $this->url = $url; + } + + public function asString(): string { + return $this->url; + } + + /** + * @throws InvalidUrlException + */ + private function ensureUrlIsValid(string $url): void { + if (filter_var($url, FILTER_VALIDATE_URL) === false) { + throw new InvalidUrlException; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElement.php new file mode 100644 index 000000000..b33eb3ca0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElement.php @@ -0,0 +1,25 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class AuthorElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } + + public function getEmail(): string { + return $this->getAttributeValue('email'); + } + + public function hasEMail(): bool { + return $this->hasAttribute('email'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php new file mode 100644 index 000000000..0a2a2a388 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/AuthorElementCollection.php @@ -0,0 +1,19 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class AuthorElementCollection extends ElementCollection { + public function current(): AuthorElement { + return new AuthorElement( + $this->getCurrentElement() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/BundlesElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/BundlesElement.php new file mode 100644 index 000000000..ef721a663 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/BundlesElement.php @@ -0,0 +1,19 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class BundlesElement extends ManifestElement { + public function getComponentElements(): ComponentElementCollection { + return new ComponentElementCollection( + $this->getChildrenByName('component') + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElement.php new file mode 100644 index 000000000..84373c470 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElement.php @@ -0,0 +1,21 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ComponentElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } + + public function getVersion(): string { + return $this->getAttributeValue('version'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php new file mode 100644 index 000000000..cd9ad5dd4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ComponentElementCollection.php @@ -0,0 +1,19 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ComponentElementCollection extends ElementCollection { + public function current(): ComponentElement { + return new ComponentElement( + $this->getCurrentElement() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ContainsElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ContainsElement.php new file mode 100644 index 000000000..55a9c605e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ContainsElement.php @@ -0,0 +1,31 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ContainsElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } + + public function getVersion(): string { + return $this->getAttributeValue('version'); + } + + public function getType(): string { + return $this->getAttributeValue('type'); + } + + public function getExtensionElement(): ExtensionElement { + return new ExtensionElement( + $this->getChildByName('extension') + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/CopyrightElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/CopyrightElement.php new file mode 100644 index 000000000..c11415a54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/CopyrightElement.php @@ -0,0 +1,25 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class CopyrightElement extends ManifestElement { + public function getAuthorElements(): AuthorElementCollection { + return new AuthorElementCollection( + $this->getChildrenByName('author') + ); + } + + public function getLicenseElement(): LicenseElement { + return new LicenseElement( + $this->getChildByName('license') + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ElementCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ElementCollection.php new file mode 100644 index 000000000..9e1de5699 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ElementCollection.php @@ -0,0 +1,68 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use DOMElement; +use DOMNodeList; +use Iterator; +use ReturnTypeWillChange; +use function count; +use function get_class; +use function sprintf; + +/** @template-implements Iterator */ +abstract class ElementCollection implements Iterator { + /** @var DOMElement[] */ + private $nodes = []; + + /** @var int */ + private $position; + + public function __construct(DOMNodeList $nodeList) { + $this->position = 0; + $this->importNodes($nodeList); + } + + #[ReturnTypeWillChange] + abstract public function current(); + + public function next(): void { + $this->position++; + } + + public function key(): int { + return $this->position; + } + + public function valid(): bool { + return $this->position < count($this->nodes); + } + + public function rewind(): void { + $this->position = 0; + } + + protected function getCurrentElement(): DOMElement { + return $this->nodes[$this->position]; + } + + private function importNodes(DOMNodeList $nodeList): void { + foreach ($nodeList as $node) { + if (!$node instanceof DOMElement) { + throw new ElementCollectionException( + sprintf('\DOMElement expected, got \%s', get_class($node)) + ); + } + + $this->nodes[] = $node; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElement.php new file mode 100644 index 000000000..6a88a05d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElement.php @@ -0,0 +1,17 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ExtElement extends ManifestElement { + public function getName(): string { + return $this->getAttributeValue('name'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElementCollection.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElementCollection.php new file mode 100644 index 000000000..3eec9463c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtElementCollection.php @@ -0,0 +1,19 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ExtElementCollection extends ElementCollection { + public function current(): ExtElement { + return new ExtElement( + $this->getCurrentElement() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtensionElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtensionElement.php new file mode 100644 index 000000000..22016a017 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ExtensionElement.php @@ -0,0 +1,21 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class ExtensionElement extends ManifestElement { + public function getFor(): string { + return $this->getAttributeValue('for'); + } + + public function getCompatible(): string { + return $this->getAttributeValue('compatible'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/LicenseElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/LicenseElement.php new file mode 100644 index 000000000..d9f4cb268 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/LicenseElement.php @@ -0,0 +1,21 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class LicenseElement extends ManifestElement { + public function getType(): string { + return $this->getAttributeValue('type'); + } + + public function getUrl(): string { + return $this->getAttributeValue('url'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestDocument.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestDocument.php new file mode 100644 index 000000000..874586865 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestDocument.php @@ -0,0 +1,115 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use DOMDocument; +use DOMElement; +use Throwable; +use function count; +use function file_get_contents; +use function is_file; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; + +class ManifestDocument { + public const XMLNS = 'https://phar.io/xml/manifest/1.0'; + + /** @var DOMDocument */ + private $dom; + + public static function fromFile(string $filename): ManifestDocument { + if (!is_file($filename)) { + throw new ManifestDocumentException( + sprintf('File "%s" not found', $filename) + ); + } + + return self::fromString( + file_get_contents($filename) + ); + } + + public static function fromString(string $xmlString): ManifestDocument { + $prev = libxml_use_internal_errors(true); + libxml_clear_errors(); + + try { + $dom = new DOMDocument(); + $dom->loadXML($xmlString); + $errors = libxml_get_errors(); + libxml_use_internal_errors($prev); + } catch (Throwable $t) { + throw new ManifestDocumentException($t->getMessage(), 0, $t); + } + + if (count($errors) !== 0) { + throw new ManifestDocumentLoadingException($errors); + } + + return new self($dom); + } + + private function __construct(DOMDocument $dom) { + $this->ensureCorrectDocumentType($dom); + + $this->dom = $dom; + } + + public function getContainsElement(): ContainsElement { + return new ContainsElement( + $this->fetchElementByName('contains') + ); + } + + public function getCopyrightElement(): CopyrightElement { + return new CopyrightElement( + $this->fetchElementByName('copyright') + ); + } + + public function getRequiresElement(): RequiresElement { + return new RequiresElement( + $this->fetchElementByName('requires') + ); + } + + public function hasBundlesElement(): bool { + return $this->dom->getElementsByTagNameNS(self::XMLNS, 'bundles')->length === 1; + } + + public function getBundlesElement(): BundlesElement { + return new BundlesElement( + $this->fetchElementByName('bundles') + ); + } + + private function ensureCorrectDocumentType(DOMDocument $dom): void { + $root = $dom->documentElement; + + if ($root->localName !== 'phar' || $root->namespaceURI !== self::XMLNS) { + throw new ManifestDocumentException('Not a phar.io manifest document'); + } + } + + private function fetchElementByName(string $elementName): DOMElement { + $element = $this->dom->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); + + if (!$element instanceof DOMElement) { + throw new ManifestDocumentException( + sprintf('Element %s missing', $elementName) + ); + } + + return $element; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestElement.php new file mode 100644 index 000000000..461ba0c94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/ManifestElement.php @@ -0,0 +1,72 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +use DOMElement; +use DOMNodeList; +use function sprintf; + +class ManifestElement { + public const XMLNS = 'https://phar.io/xml/manifest/1.0'; + + /** @var DOMElement */ + private $element; + + public function __construct(DOMElement $element) { + $this->element = $element; + } + + protected function getAttributeValue(string $name): string { + if (!$this->element->hasAttribute($name)) { + throw new ManifestElementException( + sprintf( + 'Attribute %s not set on element %s', + $name, + $this->element->localName + ) + ); + } + + return $this->element->getAttribute($name); + } + + protected function hasAttribute(string $name): bool { + return $this->element->hasAttribute($name); + } + + protected function getChildByName(string $elementName): DOMElement { + $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0); + + if (!$element instanceof DOMElement) { + throw new ManifestElementException( + sprintf('Element %s missing', $elementName) + ); + } + + return $element; + } + + protected function getChildrenByName(string $elementName): DOMNodeList { + $elementList = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName); + + if ($elementList->length === 0) { + throw new ManifestElementException( + sprintf('Element(s) %s missing', $elementName) + ); + } + + return $elementList; + } + + protected function hasChild(string $elementName): bool { + return $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->length !== 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/PhpElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/PhpElement.php new file mode 100644 index 000000000..9340c2e66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/PhpElement.php @@ -0,0 +1,27 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class PhpElement extends ManifestElement { + public function getVersion(): string { + return $this->getAttributeValue('version'); + } + + public function hasExtElements(): bool { + return $this->hasChild('ext'); + } + + public function getExtElements(): ExtElementCollection { + return new ExtElementCollection( + $this->getChildrenByName('ext') + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/RequiresElement.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/RequiresElement.php new file mode 100644 index 000000000..73ba54ca3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/src/xml/RequiresElement.php @@ -0,0 +1,19 @@ +, Sebastian Heuer , Sebastian Bergmann and contributors + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + */ +namespace PharIo\Manifest; + +class RequiresElement extends ManifestElement { + public function getPHPElement(): PhpElement { + return new PhpElement( + $this->getChildByName('php') + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.php b/.extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.php new file mode 100644 index 000000000..ea5414e42 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/PhpdocSingleLineVarFixer.php @@ -0,0 +1,72 @@ +isTokenKindFound(T_DOC_COMMENT); + } + + public function isRisky(): bool { + return false; + } + + public function fix(\SplFileInfo $file, Tokens $tokens): void { + foreach($tokens as $index => $token) { + if (!$token->isGivenKind(T_DOC_COMMENT)) { + continue; + } + if (\stripos($token->getContent(), '@var') === false) { + continue; + } + + if (preg_match('#^/\*\*[\s\*]+(@var[^\r\n]+)[\s\*]*\*\/$#u', $token->getContent(), $matches) !== 1) { + continue; + } + $newContent = '/** ' . \rtrim($matches[1]) . ' */'; + if ($newContent === $token->getContent()) { + continue; + } + $tokens[$index] = new Token([T_DOC_COMMENT, $newContent]); + } + } + + public function getPriority(): int { + return 0; + } + + public function getName(): string { + return 'PharIo/phpdoc_single_line_var_fixer'; + } + + public function supports(\SplFileInfo $file): bool { + return true; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/header.txt b/.extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/header.txt new file mode 100644 index 000000000..dc8c4ffc0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/manifest/tools/php-cs-fixer.d/header.txt @@ -0,0 +1,6 @@ +This file is part of PharIo\Manifest. + +Copyright (c) Arne Blankerts , Sebastian Heuer , Sebastian Bergmann and contributors + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/CHANGELOG.md b/.extlib/simplesamlphp/vendor/phar-io/version/CHANGELOG.md new file mode 100644 index 000000000..4c0edfa70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/CHANGELOG.md @@ -0,0 +1,142 @@ +# Changelog + +All notable changes to phar-io/version are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.2.1] - 2022-02-21 + +### Fixed + +- Have ExactVersionConstraint honor build metadata (added in 3.2.0) + + +## [3.2.0] - 2022-02-21 + +### Added + +- Build metadata is now supported and considered for equality checks only + + +## [3.1.1] - 2022-02-07 + +### Fixed + +- [#28](https://github.com/phar-io/version/issues/28): `VersionConstraintParser` does not support logical OR represented by single pipe (|) (Thanks @llaville) + + +## [3.1.0] - 2021-02-23 + +### Changed + +- Internal Refactoring +- More scalar types + +### Added + +- [#24](https://github.com/phar-io/version/issues/24): `Version::getOriginalString()` added (Thanks @addshore) +- Version constraints using the caret operator (`^`) now honor pre-1.0 releases, e.g. `^0.3` translates to `0.3.*`) +- Various integration tests for version constraint processing + +### Fixed + +- [#23](https://github.com/phar-io/version/pull/23): Tilde operator without patch level + + + +## [3.0.4] - 14.12.2020 + +### Fixed + +- [#22](https://github.com/phar-io/version/pull/22): make dev suffix rank works for uppercase too + +## [3.0.3] - 30.11.2020 + +### Added + +- Comparator method `Version::equals()` added + + +## [3.0.2] - 27.06.2020 + +This release now supports PHP 7.2+ and PHP ^8.0. No other changes included. + + +## [3.0.1] - 09.05.2020 + +__Potential BC Break Notice:__ +`Version::getVersionString()` no longer returns `v` prefixes in case the "input" +string contained one. These are not part of the semver specs +(see https://semver.org/#is-v123-a-semantic-version) and get stripped out. +As of Version 3.1.0 `Version::getOriginalString()` can be used to still +retrieve it as given. + +### Changed + +- Internal Refactoring +- More scalar types + +### Fixed + +- Fixed Constraint processing Regression for ^1.2 and ~1.2 + + +## [3.0.0] - 05.05.2020 + +### Changed + +- Require PHP 7.2+ +- All code now uses strict mode +- Scalar types have been added as needed + +### Added + +- The technically invalid format using 'v' prefix ("v1.2.3") is now properly supported + + +## [2.0.1] - 08.07.2018 + +### Fixed + +- Versions without a pre-release suffix are now always considered greater +than versions with a pre-release suffix. Example: `3.0.0 > 3.0.0-alpha.1` + + +## [2.0.0] - 23.06.2018 + +Changes to public API: + +- `PreReleaseSuffix::construct()`: optional parameter `$number` removed +- `PreReleaseSuffix::isGreaterThan()`: introduced +- `Version::hasPreReleaseSuffix()`: introduced + +### Added + +- [#11](https://github.com/phar-io/version/issues/11): Added support for pre-release version suffixes. Supported values are: + - `dev` + - `beta` (also abbreviated form `b`) + - `rc` + - `alpha` (also abbreviated form `a`) + - `patch` (also abbreviated form `p`) + + All values can be followed by a number, e.g. `beta3`. + + When comparing versions, the pre-release suffix is taken into account. Example: +`1.5.0 > 1.5.0-beta1 > 1.5.0-alpha3 > 1.5.0-alpha2 > 1.5.0-dev11` + +### Changed + +- reorganized the source directories + +### Fixed + +- [#10](https://github.com/phar-io/version/issues/10): Version numbers containing +a numeric suffix as seen in Debian packages are now supported. + + +[3.1.0]: https://github.com/phar-io/version/compare/3.0.4...3.1.0 +[3.0.4]: https://github.com/phar-io/version/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/phar-io/version/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/phar-io/version/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/phar-io/version/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/phar-io/version/compare/2.0.1...3.0.0 +[2.0.1]: https://github.com/phar-io/version/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/phar-io/version/compare/1.0.1...2.0.0 diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/LICENSE b/.extlib/simplesamlphp/vendor/phar-io/version/LICENSE new file mode 100644 index 000000000..ce32758a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2016-2017 Arne Blankerts , Sebastian Heuer and contributors +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 the copyright holder nor the names of 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 HOLDER 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/.extlib/simplesamlphp/vendor/phar-io/version/README.md b/.extlib/simplesamlphp/vendor/phar-io/version/README.md new file mode 100644 index 000000000..76e6e9857 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/README.md @@ -0,0 +1,61 @@ +# Version + +Library for handling version information and constraints + +[![Build Status](https://travis-ci.org/phar-io/version.svg?branch=master)](https://travis-ci.org/phar-io/version) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phar-io/version + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phar-io/version + +## Version constraints + +A Version constraint describes a range of versions or a discrete version number. The format of version numbers follows the schema of [semantic versioning](http://semver.org): `..`. A constraint might contain an operator that describes the range. + +Beside the typical mathematical operators like `<=`, `>=`, there are two special operators: + +*Caret operator*: `^1.0` +can be written as `>=1.0.0 <2.0.0` and read as »every Version within major version `1`«. + +*Tilde operator*: `~1.0.0` +can be written as `>=1.0.0 <1.1.0` and read as »every version within minor version `1.1`. The behavior of tilde operator depends on whether a patch level version is provided or not. If no patch level is provided, tilde operator behaves like the caret operator: `~1.0` is identical to `^1.0`. + +## Usage examples + +Parsing version constraints and check discrete versions for compliance: + +```php + +use PharIo\Version\Version; +use PharIo\Version\VersionConstraintParser; + +$parser = new VersionConstraintParser(); +$caret_constraint = $parser->parse( '^7.0' ); + +$caret_constraint->complies( new Version( '7.0.17' ) ); // true +$caret_constraint->complies( new Version( '7.1.0' ) ); // true +$caret_constraint->complies( new Version( '6.4.34' ) ); // false + +$tilde_constraint = $parser->parse( '~1.1.0' ); + +$tilde_constraint->complies( new Version( '1.1.4' ) ); // true +$tilde_constraint->complies( new Version( '1.2.0' ) ); // false +``` + +As of version 2.0.0, pre-release labels are supported and taken into account when comparing versions: + +```php + +$leftVersion = new PharIo\Version\Version('3.0.0-alpha.1'); +$rightVersion = new PharIo\Version\Version('3.0.0-alpha.2'); + +$leftVersion->isGreaterThan($rightVersion); // false +$rightVersion->isGreaterThan($leftVersion); // true + +``` diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/composer.json b/.extlib/simplesamlphp/vendor/phar-io/version/composer.json new file mode 100644 index 000000000..22687dcd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/composer.json @@ -0,0 +1,34 @@ +{ + "name": "phar-io/version", + "description": "Library for handling version information and constraints", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/phar-io/version/issues" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + } +} + diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/BuildMetaData.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/BuildMetaData.php new file mode 100644 index 000000000..d42f0363f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/BuildMetaData.php @@ -0,0 +1,28 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class BuildMetaData { + + /** @var string */ + private $value; + + public function __construct(string $value) { + $this->value = $value; + } + + public function asString(): string { + return $this->value; + } + + public function equals(BuildMetaData $other): bool { + return $this->asString() === $other->asString(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/PreReleaseSuffix.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/PreReleaseSuffix.php new file mode 100644 index 000000000..00563008e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/PreReleaseSuffix.php @@ -0,0 +1,82 @@ + 0, + 'a' => 1, + 'alpha' => 1, + 'b' => 2, + 'beta' => 2, + 'rc' => 3, + 'p' => 4, + 'pl' => 4, + 'patch' => 4, + ]; + + /** @var string */ + private $value; + + /** @var int */ + private $valueScore; + + /** @var int */ + private $number = 0; + + /** @var string */ + private $full; + + /** + * @throws InvalidPreReleaseSuffixException + */ + public function __construct(string $value) { + $this->parseValue($value); + } + + public function asString(): string { + return $this->full; + } + + public function getValue(): string { + return $this->value; + } + + public function getNumber(): ?int { + return $this->number; + } + + public function isGreaterThan(PreReleaseSuffix $suffix): bool { + if ($this->valueScore > $suffix->valueScore) { + return true; + } + + if ($this->valueScore < $suffix->valueScore) { + return false; + } + + return $this->getNumber() > $suffix->getNumber(); + } + + private function mapValueToScore(string $value): int { + $value = \strtolower($value); + + return self::valueScoreMap[$value]; + } + + private function parseValue(string $value): void { + $regex = '/-?((dev|beta|b|rc|alpha|a|patch|p|pl)\.?(\d*)).*$/i'; + + if (\preg_match($regex, $value, $matches) !== 1) { + throw new InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value)); + } + + $this->full = $matches[1]; + $this->value = $matches[2]; + + if ($matches[3] !== '') { + $this->number = (int)$matches[3]; + } + + $this->valueScore = $this->mapValueToScore($matches[2]); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/Version.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/Version.php new file mode 100644 index 000000000..644af5ca8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/Version.php @@ -0,0 +1,208 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class Version { + /** @var string */ + private $originalVersionString; + + /** @var VersionNumber */ + private $major; + + /** @var VersionNumber */ + private $minor; + + /** @var VersionNumber */ + private $patch; + + /** @var null|PreReleaseSuffix */ + private $preReleaseSuffix; + + /** @var null|BuildMetaData */ + private $buildMetadata; + + public function __construct(string $versionString) { + $this->ensureVersionStringIsValid($versionString); + $this->originalVersionString = $versionString; + } + + /** + * @throws NoPreReleaseSuffixException + */ + public function getPreReleaseSuffix(): PreReleaseSuffix { + if ($this->preReleaseSuffix === null) { + throw new NoPreReleaseSuffixException('No pre-release suffix set'); + } + + return $this->preReleaseSuffix; + } + + public function getOriginalString(): string { + return $this->originalVersionString; + } + + public function getVersionString(): string { + $str = \sprintf( + '%d.%d.%d', + $this->getMajor()->getValue() ?? 0, + $this->getMinor()->getValue() ?? 0, + $this->getPatch()->getValue() ?? 0 + ); + + if (!$this->hasPreReleaseSuffix()) { + return $str; + } + + return $str . '-' . $this->getPreReleaseSuffix()->asString(); + } + + public function hasPreReleaseSuffix(): bool { + return $this->preReleaseSuffix !== null; + } + + public function equals(Version $other): bool { + if ($this->getVersionString() !== $other->getVersionString()) { + return false; + } + + if ($this->hasBuildMetaData() !== $other->hasBuildMetaData()) { + return false; + } + + if ($this->hasBuildMetaData() && $other->hasBuildMetaData() && + !$this->getBuildMetaData()->equals($other->getBuildMetaData())) { + return false; + } + + return true; + } + + public function isGreaterThan(Version $version): bool { + if ($version->getMajor()->getValue() > $this->getMajor()->getValue()) { + return false; + } + + if ($version->getMajor()->getValue() < $this->getMajor()->getValue()) { + return true; + } + + if ($version->getMinor()->getValue() > $this->getMinor()->getValue()) { + return false; + } + + if ($version->getMinor()->getValue() < $this->getMinor()->getValue()) { + return true; + } + + if ($version->getPatch()->getValue() > $this->getPatch()->getValue()) { + return false; + } + + if ($version->getPatch()->getValue() < $this->getPatch()->getValue()) { + return true; + } + + if (!$version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { + return false; + } + + if ($version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { + return true; + } + + if (!$version->hasPreReleaseSuffix() && $this->hasPreReleaseSuffix()) { + return false; + } + + return $this->getPreReleaseSuffix()->isGreaterThan($version->getPreReleaseSuffix()); + } + + public function getMajor(): VersionNumber { + return $this->major; + } + + public function getMinor(): VersionNumber { + return $this->minor; + } + + public function getPatch(): VersionNumber { + return $this->patch; + } + + /** + * @psalm-assert-if-true BuildMetaData $this->buildMetadata + * @psalm-assert-if-true BuildMetaData $this->getBuildMetaData() + */ + public function hasBuildMetaData(): bool { + return $this->buildMetadata !== null; + } + + /** + * @throws NoBuildMetaDataException + */ + public function getBuildMetaData(): BuildMetaData { + if (!$this->hasBuildMetaData()) { + throw new NoBuildMetaDataException('No build metadata set'); + } + + return $this->buildMetadata; + } + + /** + * @param string[] $matches + * + * @throws InvalidPreReleaseSuffixException + */ + private function parseVersion(array $matches): void { + $this->major = new VersionNumber((int)$matches['Major']); + $this->minor = new VersionNumber((int)$matches['Minor']); + $this->patch = isset($matches['Patch']) ? new VersionNumber((int)$matches['Patch']) : new VersionNumber(0); + + if (isset($matches['PreReleaseSuffix']) && $matches['PreReleaseSuffix'] !== '') { + $this->preReleaseSuffix = new PreReleaseSuffix($matches['PreReleaseSuffix']); + } + + if (isset($matches['BuildMetadata'])) { + $this->buildMetadata = new BuildMetaData($matches['BuildMetadata']); + } + } + + /** + * @param string $version + * + * @throws InvalidVersionException + */ + private function ensureVersionStringIsValid($version): void { + $regex = '/^v? + (?P0|[1-9]\d*) + \\. + (?P0|[1-9]\d*) + (\\. + (?P0|[1-9]\d*) + )? + (?: + - + (?(?:(dev|beta|b|rc|alpha|a|patch|p|pl)\.?\d*)) + )? + (?: + \\+ + (?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-@]+)*) + )? + $/xi'; + + if (\preg_match($regex, $version, $matches) !== 1) { + throw new InvalidVersionException( + \sprintf("Version string '%s' does not follow SemVer semantics", $version) + ); + } + + $this->parseVersion($matches); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintParser.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintParser.php new file mode 100644 index 000000000..03d6a0959 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintParser.php @@ -0,0 +1,115 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class VersionConstraintParser { + /** + * @throws UnsupportedVersionConstraintException + */ + public function parse(string $value): VersionConstraint { + if (\strpos($value, '|') !== false) { + return $this->handleOrGroup($value); + } + + if (!\preg_match('/^[\^~*]?v?[\d.*]+(?:-.*)?$/i', $value)) { + throw new UnsupportedVersionConstraintException( + \sprintf('Version constraint %s is not supported.', $value) + ); + } + + switch ($value[0]) { + case '~': + return $this->handleTildeOperator($value); + case '^': + return $this->handleCaretOperator($value); + } + + $constraint = new VersionConstraintValue($value); + + if ($constraint->getMajor()->isAny()) { + return new AnyVersionConstraint(); + } + + if ($constraint->getMinor()->isAny()) { + return new SpecificMajorVersionConstraint( + $constraint->getVersionString(), + $constraint->getMajor()->getValue() ?? 0 + ); + } + + if ($constraint->getPatch()->isAny()) { + return new SpecificMajorAndMinorVersionConstraint( + $constraint->getVersionString(), + $constraint->getMajor()->getValue() ?? 0, + $constraint->getMinor()->getValue() ?? 0 + ); + } + + return new ExactVersionConstraint($constraint->getVersionString()); + } + + private function handleOrGroup(string $value): OrVersionConstraintGroup { + $constraints = []; + + foreach (\preg_split('{\s*\|\|?\s*}', \trim($value)) as $groupSegment) { + $constraints[] = $this->parse(\trim($groupSegment)); + } + + return new OrVersionConstraintGroup($value, $constraints); + } + + private function handleTildeOperator(string $value): AndVersionConstraintGroup { + $constraintValue = new VersionConstraintValue(\substr($value, 1)); + + if ($constraintValue->getPatch()->isAny()) { + return $this->handleCaretOperator($value); + } + + $constraints = [ + new GreaterThanOrEqualToVersionConstraint( + $value, + new Version(\substr($value, 1)) + ), + new SpecificMajorAndMinorVersionConstraint( + $value, + $constraintValue->getMajor()->getValue() ?? 0, + $constraintValue->getMinor()->getValue() ?? 0 + ) + ]; + + return new AndVersionConstraintGroup($value, $constraints); + } + + private function handleCaretOperator(string $value): AndVersionConstraintGroup { + $constraintValue = new VersionConstraintValue(\substr($value, 1)); + + $constraints = [ + new GreaterThanOrEqualToVersionConstraint($value, new Version(\substr($value, 1))) + ]; + + if ($constraintValue->getMajor()->getValue() === 0) { + $constraints[] = new SpecificMajorAndMinorVersionConstraint( + $value, + $constraintValue->getMajor()->getValue() ?? 0, + $constraintValue->getMinor()->getValue() ?? 0 + ); + } else { + $constraints[] = new SpecificMajorVersionConstraint( + $value, + $constraintValue->getMajor()->getValue() ?? 0 + ); + } + + return new AndVersionConstraintGroup( + $value, + $constraints + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintValue.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintValue.php new file mode 100644 index 000000000..0762e7c0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionConstraintValue.php @@ -0,0 +1,88 @@ +versionString = $versionString; + + $this->parseVersion($versionString); + } + + public function getLabel(): string { + return $this->label; + } + + public function getBuildMetaData(): string { + return $this->buildMetaData; + } + + public function getVersionString(): string { + return $this->versionString; + } + + public function getMajor(): VersionNumber { + return $this->major; + } + + public function getMinor(): VersionNumber { + return $this->minor; + } + + public function getPatch(): VersionNumber { + return $this->patch; + } + + private function parseVersion(string $versionString): void { + $this->extractBuildMetaData($versionString); + $this->extractLabel($versionString); + $this->stripPotentialVPrefix($versionString); + + $versionSegments = \explode('.', $versionString); + $this->major = new VersionNumber(\is_numeric($versionSegments[0]) ? (int)$versionSegments[0] : null); + + $minorValue = isset($versionSegments[1]) && \is_numeric($versionSegments[1]) ? (int)$versionSegments[1] : null; + $patchValue = isset($versionSegments[2]) && \is_numeric($versionSegments[2]) ? (int)$versionSegments[2] : null; + + $this->minor = new VersionNumber($minorValue); + $this->patch = new VersionNumber($patchValue); + } + + private function extractBuildMetaData(string &$versionString): void { + if (\preg_match('/\+(.*)/', $versionString, $matches) === 1) { + $this->buildMetaData = $matches[1]; + $versionString = \str_replace($matches[0], '', $versionString); + } + } + + private function extractLabel(string &$versionString): void { + if (\preg_match('/-(.*)/', $versionString, $matches) === 1) { + $this->label = $matches[1]; + $versionString = \str_replace($matches[0], '', $versionString); + } + } + + private function stripPotentialVPrefix(string &$versionString): void { + if ($versionString[0] !== 'v') { + return; + } + $versionString = \substr($versionString, 1); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionNumber.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionNumber.php new file mode 100644 index 000000000..4833a9b0f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/VersionNumber.php @@ -0,0 +1,28 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class VersionNumber { + + /** @var ?int */ + private $value; + + public function __construct(?int $value) { + $this->value = $value; + } + + public function isAny(): bool { + return $this->value === null; + } + + public function getValue(): ?int { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php new file mode 100644 index 000000000..66201a140 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AbstractVersionConstraint.php @@ -0,0 +1,23 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +abstract class AbstractVersionConstraint implements VersionConstraint { + /** @var string */ + private $originalValue; + + public function __construct(string $originalValue) { + $this->originalValue = $originalValue; + } + + public function asString(): string { + return $this->originalValue; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php new file mode 100644 index 000000000..5096f2fbb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AndVersionConstraintGroup.php @@ -0,0 +1,34 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class AndVersionConstraintGroup extends AbstractVersionConstraint { + /** @var VersionConstraint[] */ + private $constraints = []; + + /** + * @param VersionConstraint[] $constraints + */ + public function __construct(string $originalValue, array $constraints) { + parent::__construct($originalValue); + + $this->constraints = $constraints; + } + + public function complies(Version $version): bool { + foreach ($this->constraints as $constraint) { + if (!$constraint->complies($version)) { + return false; + } + } + + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php new file mode 100644 index 000000000..1499f071f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/AnyVersionConstraint.php @@ -0,0 +1,20 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class AnyVersionConstraint implements VersionConstraint { + public function complies(Version $version): bool { + return true; + } + + public function asString(): string { + return '*'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php new file mode 100644 index 000000000..1d675c9c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/ExactVersionConstraint.php @@ -0,0 +1,22 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class ExactVersionConstraint extends AbstractVersionConstraint { + public function complies(Version $version): bool { + $other = $version->getVersionString(); + + if ($version->hasBuildMetaData()) { + $other .= '+' . $version->getBuildMetaData()->asString(); + } + + return $this->asString() === $other; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php new file mode 100644 index 000000000..ec3717231 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/GreaterThanOrEqualToVersionConstraint.php @@ -0,0 +1,26 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class GreaterThanOrEqualToVersionConstraint extends AbstractVersionConstraint { + /** @var Version */ + private $minimalVersion; + + public function __construct(string $originalValue, Version $minimalVersion) { + parent::__construct($originalValue); + + $this->minimalVersion = $minimalVersion; + } + + public function complies(Version $version): bool { + return $version->getVersionString() === $this->minimalVersion->getVersionString() + || $version->isGreaterThan($this->minimalVersion); + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php new file mode 100644 index 000000000..59fd382f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/OrVersionConstraintGroup.php @@ -0,0 +1,35 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class OrVersionConstraintGroup extends AbstractVersionConstraint { + /** @var VersionConstraint[] */ + private $constraints = []; + + /** + * @param string $originalValue + * @param VersionConstraint[] $constraints + */ + public function __construct($originalValue, array $constraints) { + parent::__construct($originalValue); + + $this->constraints = $constraints; + } + + public function complies(Version $version): bool { + foreach ($this->constraints as $constraint) { + if ($constraint->complies($version)) { + return true; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php new file mode 100644 index 000000000..302aa311c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorAndMinorVersionConstraint.php @@ -0,0 +1,33 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class SpecificMajorAndMinorVersionConstraint extends AbstractVersionConstraint { + /** @var int */ + private $major; + + /** @var int */ + private $minor; + + public function __construct(string $originalValue, int $major, int $minor) { + parent::__construct($originalValue); + + $this->major = $major; + $this->minor = $minor; + } + + public function complies(Version $version): bool { + if ($version->getMajor()->getValue() !== $this->major) { + return false; + } + + return $version->getMinor()->getValue() === $this->minor; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php new file mode 100644 index 000000000..968b809c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/SpecificMajorVersionConstraint.php @@ -0,0 +1,25 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +class SpecificMajorVersionConstraint extends AbstractVersionConstraint { + /** @var int */ + private $major; + + public function __construct(string $originalValue, int $major) { + parent::__construct($originalValue); + + $this->major = $major; + } + + public function complies(Version $version): bool { + return $version->getMajor()->getValue() === $this->major; + } +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/VersionConstraint.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/VersionConstraint.php new file mode 100644 index 000000000..e94f9e00e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/constraints/VersionConstraint.php @@ -0,0 +1,16 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +interface VersionConstraint { + public function complies(Version $version): bool; + + public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/Exception.php new file mode 100644 index 000000000..3ea458f3d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/Exception.php @@ -0,0 +1,15 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +use Throwable; + +interface Exception extends Throwable { +} diff --git a/.extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php b/.extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php new file mode 100644 index 000000000..bc0b0c3e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phar-io/version/src/exceptions/InvalidPreReleaseSuffixException.php @@ -0,0 +1,5 @@ +, Sebastian Heuer , Sebastian Bergmann + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PharIo\Version; + +final class UnsupportedVersionConstraintException extends \RuntimeException implements Exception { +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/extension-installer/LICENSE b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/LICENSE new file mode 100644 index 000000000..afe8bee4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Ondřej Mirtes + +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/.extlib/simplesamlphp/vendor/phpstan/extension-installer/README.md b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/README.md new file mode 100644 index 000000000..0616f9996 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/README.md @@ -0,0 +1,93 @@ +# PHPStan Extension Installer + +[![Build](https://github.com/phpstan/extension-installer/workflows/Build/badge.svg)](https://github.com/phpstan/extension-installer/actions) +[![Latest Stable Version](https://poser.pugx.org/phpstan/extension-installer/v/stable)](https://packagist.org/packages/phpstan/extension-installer) +[![License](https://poser.pugx.org/phpstan/extension-installer/license)](https://packagist.org/packages/phpstan/extension-installer) + +Composer plugin for automatic installation of [PHPStan](https://phpstan.org/) extensions. + +# Motivation + +```diff +diff --git a/phpstan.neon b/phpstan.neon +index db4e3df32e..2ca30fa20a 100644 +--- a/phpstan.neon ++++ b/phpstan.neon +@@ -1,12 +1,3 @@ +-includes: +- - vendor/phpstan/phpstan-doctrine/extension.neon +- - vendor/phpstan/phpstan-doctrine/rules.neon +- - vendor/phpstan/phpstan-nette/extension.neon +- - vendor/phpstan/phpstan-nette/rules.neon +- - vendor/phpstan/phpstan-phpunit/extension.neon +- - vendor/phpstan/phpstan-phpunit/rules.neon +- - vendor/phpstan/phpstan-strict-rules/rules.neon +- + parameters: + autoload_directories: + - %rootDir%/../../../build/SlevomatSniffs +diff --git a/composer.json b/composer.json +index 1b578dd624..f6ebf6e477 100644 +--- a/composer.json ++++ b/composer.json +@@ -142,6 +142,7 @@ + "jakub-onderka/php-parallel-lint": "1.0.0", + "justinrainbow/json-schema": "5.2.8", + "ondrejmirtes/mocktainer": "0.8", ++ "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.11.7", + "phpstan/phpstan-doctrine": "^0.11.3", + "phpstan/phpstan-nette": "^0.11.1", +``` + +## Usage + +```bash +composer require --dev phpstan/extension-installer +``` + +Starting from Composer 2.2.0 you'll get the following question: +``` +phpstan/extension-installer contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins +Do you trust "phpstan/extension-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] +``` + +Answer with `y` to allow the plugin. + +## Instructions for extension developers + +It's best (but optional) to set the extension's composer package [type](https://getcomposer.org/doc/04-schema.md#type) to `phpstan-extension` for this plugin to be able to recognize it and to be [discoverable on Packagist](https://packagist.org/explore/?type=phpstan-extension). + +Add `phpstan` key in the extension `composer.json`'s `extra` section: + +```json +{ + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + } +} +``` + +## Ignoring a particular extension + +You may want to disable auto-installation of a particular extension to handle installation manually. Ignore an extension by adding an `extra.phpstan/extension-installer.ignore` array in `composer.json` that specifies a list of packages to ignore: + +```json +{ + "extra": { + "phpstan/extension-installer": { + "ignore": [ + "phpstan/phpstan-phpunit" + ] + } + } +} +``` + +## Limitations + +The extension installer depends on Composer script events, therefore you cannot use `--no-scripts` flag. diff --git a/.extlib/simplesamlphp/vendor/phpstan/extension-installer/composer.json b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/composer.json new file mode 100644 index 000000000..b2cc1a051 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/composer.json @@ -0,0 +1,33 @@ +{ + "name": "phpstan/extension-installer", + "type": "composer-plugin", + "description": "Composer plugin for automatic installation of PHPStan extensions", + "license": [ + "MIT" + ], + "keywords": ["dev", "static analysis"], + "require": { + "php": "^7.2 || ^8.0", + "composer-plugin-api": "^2.0", + "phpstan/phpstan": "^1.9.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "^2.0", + "php-parallel-lint/php-parallel-lint": "^1.2.0", + "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0" + }, + "config": { + "sort-packages": true, + "allow-plugins": { + "ocramius/package-versions": true + } + }, + "extra": { + "class": "PHPStan\\ExtensionInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPStan\\ExtensionInstaller\\": "src/" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/extension-installer/src/GeneratedConfig.php b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/src/GeneratedConfig.php new file mode 100644 index 000000000..37922b4ef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/src/GeneratedConfig.php @@ -0,0 +1,39 @@ + + array ( + 'install_path' => '/home/guillaumebarat/docker-dev/sites/simplesamlphp/vendor/phpstan/phpstan-mockery', + 'relative_install_path' => '../../phpstan-mockery', + 'extra' => + array ( + 'includes' => + array ( + 0 => 'extension.neon', + ), + ), + 'version' => '1.1.3', + 'phpstanVersionConstraint' => '>=1.12.0.0-dev, <2.0.0.0-dev', + ), +); + + public const NOT_INSTALLED = array ( +); + + /** @var string|null */ + public const PHPSTAN_VERSION_CONSTRAINT = '>=1.12.0.0-dev, <2.0.0.0-dev'; + + private function __construct() + { + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/extension-installer/src/Plugin.php b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/src/Plugin.php new file mode 100644 index 000000000..ec757351f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/extension-installer/src/Plugin.php @@ -0,0 +1,228 @@ + + */ + public static function getSubscribedEvents(): array + { + return [ + ScriptEvents::POST_INSTALL_CMD => 'process', + ScriptEvents::POST_UPDATE_CMD => 'process', + ]; + } + + public function process(Event $event): void + { + $io = $event->getIO(); + + if (!file_exists(__DIR__)) { + $io->write('phpstan/extension-installer: Package not found (probably scheduled for removal); extensions installation skipped.'); + return; + } + + $composer = $event->getComposer(); + $installationManager = $composer->getInstallationManager(); + + $generatedConfigFilePath = __DIR__ . '/GeneratedConfig.php'; + $oldGeneratedConfigFileHash = null; + if (is_file($generatedConfigFilePath)) { + $oldGeneratedConfigFileHash = md5_file($generatedConfigFilePath); + } + $notInstalledPackages = []; + $installedPackages = []; + $ignoredPackages = []; + + $data = []; + $fs = new Filesystem(); + $ignore = []; + + $packageExtra = $composer->getPackage()->getExtra(); + + if (isset($packageExtra['phpstan/extension-installer']['ignore'])) { + $ignore = $packageExtra['phpstan/extension-installer']['ignore']; + } + + $phpstanVersionConstraints = []; + + foreach ($composer->getRepositoryManager()->getLocalRepository()->getPackages() as $package) { + if ( + $package->getType() !== 'phpstan-extension' + && !isset($package->getExtra()['phpstan']) + ) { + if ( + strpos($package->getName(), 'phpstan') !== false + && !in_array($package->getName(), [ + 'phpstan/phpstan', + 'phpstan/phpstan-shim', + 'phpstan/phpdoc-parser', + 'phpstan/extension-installer', + ], true) + ) { + $notInstalledPackages[$package->getName()] = $package->getFullPrettyVersion(); + } + continue; + } + + if (in_array($package->getName(), $ignore, true)) { + $ignoredPackages[] = $package->getName(); + continue; + } + + $installPath = $installationManager->getInstallPath($package); + if ($installPath === null) { + continue; + } + + $absoluteInstallPath = $fs->isAbsolutePath($installPath) + ? $installPath + : getcwd() . DIRECTORY_SEPARATOR . $installPath; + + $packageRequires = $package->getRequires(); + $phpstanConstraint = null; + if (array_key_exists('phpstan/phpstan', $packageRequires)) { + $phpstanConstraint = $packageRequires['phpstan/phpstan']->getConstraint(); + if ($phpstanConstraint->getLowerBound()->isZero()) { + continue; + } + if ($phpstanConstraint->getUpperBound()->isPositiveInfinity()) { + continue; + } + $phpstanVersionConstraints[] = $phpstanConstraint; + } + + $data[$package->getName()] = [ + 'install_path' => $absoluteInstallPath, + 'relative_install_path' => $fs->findShortestPath(dirname($generatedConfigFilePath), $absoluteInstallPath, true), + 'extra' => $package->getExtra()['phpstan'] ?? null, + 'version' => $package->getFullPrettyVersion(), + 'phpstanVersionConstraint' => $phpstanConstraint !== null ? $this->constraintIntoString($phpstanConstraint) : null, + ]; + + $installedPackages[$package->getName()] = true; + } + + $phpstanVersionConstraint = null; + if (count($phpstanVersionConstraints) > 0 && class_exists(Intervals::class)) { + if (count($phpstanVersionConstraints) === 1) { + $multiConstraint = $phpstanVersionConstraints[0]; + } else { + $multiConstraint = new MultiConstraint($phpstanVersionConstraints); + } + $phpstanVersionConstraint = $this->constraintIntoString(Intervals::compactConstraint($multiConstraint)); + } + + ksort($data); + ksort($installedPackages); + ksort($notInstalledPackages); + sort($ignoredPackages); + + $generatedConfigFileContents = sprintf(self::$generatedFileTemplate, var_export($data, true), var_export($notInstalledPackages, true), var_export($phpstanVersionConstraint, true)); + file_put_contents($generatedConfigFilePath, $generatedConfigFileContents); + $io->write('phpstan/extension-installer: Extensions installed'); + + if ($oldGeneratedConfigFileHash === md5($generatedConfigFileContents)) { + return; + } + + foreach (array_keys($installedPackages) as $name) { + $io->write(sprintf('> %s: installed', $name)); + } + + foreach (array_keys($notInstalledPackages) as $name) { + $io->write(sprintf('> %s: not supported', $name)); + } + + foreach ($ignoredPackages as $name) { + $io->write(sprintf('> %s: ignored', $name)); + } + } + + private function constraintIntoString(ConstraintInterface $constraint): string + { + return sprintf( + '%s%s, %s%s', + $constraint->getLowerBound()->isInclusive() ? '>=' : '>', + $constraint->getLowerBound()->getVersion(), + $constraint->getUpperBound()->isInclusive() ? '<=' : '<', + $constraint->getUpperBound()->getVersion() + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/LICENSE b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/LICENSE new file mode 100644 index 000000000..98a854e4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Ondřej Mirtes + +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/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/README.md b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/README.md new file mode 100644 index 000000000..706b2a3c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/README.md @@ -0,0 +1,121 @@ +

    PHPDoc Parser for PHPStan

    + +
    + +This library `phpstan/phpdoc-parser` represents PHPDocs with an AST (Abstract Syntax Tree). It supports parsing and modifying PHPDocs. + +For the complete list of supported PHPDoc features check out PHPStan documentation. PHPStan is the main (but not the only) user of this library. + +* [PHPDoc Basics](https://phpstan.org/writing-php-code/phpdocs-basics) (list of PHPDoc tags) +* [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) (list of PHPDoc types) +* [phpdoc-parser API Reference](https://phpstan.github.io/phpdoc-parser/1.23.x/namespace-PHPStan.PhpDocParser.html) with all the AST node types etc. + +This parser also supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/1.23.x/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html). The support needs to be turned on by setting `bool $parseDoctrineAnnotations` to `true` in `Lexer` and `PhpDocParser` class constructors. + +## Installation + +``` +composer require phpstan/phpdoc-parser +``` + +## Basic usage + +```php +tokenize('/** @param Lorem $a */')); +$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode +$paramTags = $phpDocNode->getParamTagValues(); // ParamTagValueNode[] +echo $paramTags[0]->parameterName; // '$a' +echo $paramTags[0]->type; // IdentifierTypeNode - 'Lorem' +``` + +### Format-preserving printer + +This component can be used to modify the AST +and print it again as close as possible to the original. + +It's heavily inspired by format-preserving printer component in [nikic/PHP-Parser](https://github.com/nikic/PHP-Parser). + +```php + true, 'indexes' => true]; + +$lexer = new Lexer(); +$constExprParser = new ConstExprParser(true, true, $usedAttributes); +$typeParser = new TypeParser($constExprParser, true, $usedAttributes); +$phpDocParser = new PhpDocParser($typeParser, $constExprParser, true, true, $usedAttributes); + +$tokens = new TokenIterator($lexer->tokenize('/** @param Lorem $a */')); +$phpDocNode = $phpDocParser->parse($tokens); // PhpDocNode + +$cloningTraverser = new NodeTraverser([new CloningVisitor()]); + +/** @var PhpDocNode $newPhpDocNode */ +[$newPhpDocNode] = $cloningTraverser->traverse([$phpDocNode]); + +// change something in $newPhpDocNode +$newPhpDocNode->getParamTagValues()[0]->type = new IdentifierTypeNode('Ipsum'); + +// print changed PHPDoc +$printer = new Printer(); +$newPhpDoc = $printer->printFormatPreserving($newPhpDocNode, $phpDocNode, $tokens); +echo $newPhpDoc; // '/** @param Ipsum $a */' +``` + +## Code of Conduct + +This project adheres to a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code. + +## Building + +Initially you need to run `composer install`, or `composer update` in case you aren't working in a folder which was built before. + +Afterwards you can either run the whole build including linting and coding standards using + + make + +or run only tests using + + make tests diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/composer.json b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/composer.json new file mode 100644 index 000000000..f1c648e51 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/composer.json @@ -0,0 +1,44 @@ +{ + "name": "phpstan/phpdoc-parser", + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "license": "MIT", + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "config": { + "platform": { + "php": "7.4.6" + }, + "sort-packages": true, + "allow-plugins": { + "phpstan/extension-installer": true + } + }, + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "autoload-dev": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "tests/PHPStan" + ] + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php new file mode 100644 index 000000000..2b9c10ec2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php @@ -0,0 +1,34 @@ +key = $key; + $this->value = $value; + } + + + public function __toString(): string + { + if ($this->key !== null) { + return sprintf('%s => %s', $this->key, $this->value); + + } + + return (string) $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php new file mode 100644 index 000000000..1f9def371 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php @@ -0,0 +1,30 @@ +items = $items; + } + + + public function __toString(): string + { + return '[' . implode(', ', $this->items) . ']'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php new file mode 100644 index 000000000..e6811277e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php @@ -0,0 +1,17 @@ +value = $value; + } + + + public function __toString(): string + { + return $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php new file mode 100644 index 000000000..5339bb5ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php @@ -0,0 +1,26 @@ +value = $value; + } + + + public function __toString(): string + { + return $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php new file mode 100644 index 000000000..1859f03e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php @@ -0,0 +1,10 @@ +value = $value; + } + + + public function __toString(): string + { + return $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php new file mode 100644 index 000000000..ec9803202 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php @@ -0,0 +1,17 @@ +className = $className; + $this->name = $name; + } + + + public function __toString(): string + { + if ($this->className === '') { + return $this->name; + + } + + return "{$this->className}::{$this->name}"; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php new file mode 100644 index 000000000..a503937b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php @@ -0,0 +1,42 @@ +value = $value; + } + + public function __toString(): string + { + return self::escape($this->value); + } + + public static function unescape(string $value): string + { + // from https://github.com/doctrine/annotations/blob/a9ec7af212302a75d1f92fa65d3abfbd16245a2a/lib/Doctrine/Common/Annotations/DocLexer.php#L103-L107 + return str_replace('""', '"', substr($value, 1, strlen($value) - 2)); + } + + private static function escape(string $value): string + { + // from https://github.com/phpstan/phpdoc-parser/issues/205#issuecomment-1662323656 + return sprintf('"%s"', str_replace('"', '""', $value)); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php new file mode 100644 index 000000000..f2792b1bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php @@ -0,0 +1,78 @@ +quoteType = $quoteType; + } + + + public function __toString(): string + { + if ($this->quoteType === self::SINGLE_QUOTED) { + // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1007 + return sprintf("'%s'", addcslashes($this->value, '\'\\')); + } + + // from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1010-L1040 + return sprintf('"%s"', $this->escapeDoubleQuotedString()); + } + + private function escapeDoubleQuotedString(): string + { + $quote = '"'; + $escaped = addcslashes($this->value, "\n\r\t\f\v$" . $quote . '\\'); + + // Escape control characters and non-UTF-8 characters. + // Regex based on https://stackoverflow.com/a/11709412/385378. + $regex = '/( + [\x00-\x08\x0E-\x1F] # Control characters + | [\xC0-\xC1] # Invalid UTF-8 Bytes + | [\xF5-\xFF] # Invalid UTF-8 Bytes + | \xE0(?=[\x80-\x9F]) # Overlong encoding of prior code point + | \xF0(?=[\x80-\x8F]) # Overlong encoding of prior code point + | [\xC2-\xDF](?![\x80-\xBF]) # Invalid UTF-8 Sequence Start + | [\xE0-\xEF](?![\x80-\xBF]{2}) # Invalid UTF-8 Sequence Start + | [\xF0-\xF4](?![\x80-\xBF]{3}) # Invalid UTF-8 Sequence Start + | (?<=[\x00-\x7F\xF5-\xFF])[\x80-\xBF] # Invalid UTF-8 Sequence Middle + | (? */ + private $attributes = []; + + /** + * @param mixed $value + */ + public function setAttribute(string $key, $value): void + { + $this->attributes[$key] = $value; + } + + public function hasAttribute(string $key): bool + { + return array_key_exists($key, $this->attributes); + } + + /** + * @return mixed + */ + public function getAttribute(string $key) + { + if ($this->hasAttribute($key)) { + return $this->attributes[$key]; + } + + return null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php new file mode 100644 index 000000000..63b25c375 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php @@ -0,0 +1,312 @@ + Visitors */ + private $visitors = []; + + /** @var bool Whether traversal should be stopped */ + private $stopTraversal; + + /** + * @param list $visitors + */ + public function __construct(array $visitors) + { + $this->visitors = $visitors; + } + + /** + * Traverses an array of nodes using the registered visitors. + * + * @param Node[] $nodes Array of nodes + * + * @return Node[] Traversed array of nodes + */ + public function traverse(array $nodes): array + { + $this->stopTraversal = false; + + foreach ($this->visitors as $visitor) { + $return = $visitor->beforeTraverse($nodes); + if ($return === null) { + continue; + } + + $nodes = $return; + } + + $nodes = $this->traverseArray($nodes); + + foreach ($this->visitors as $visitor) { + $return = $visitor->afterTraverse($nodes); + if ($return === null) { + continue; + } + + $nodes = $return; + } + + return $nodes; + } + + /** + * Recursively traverse a node. + * + * @param Node $node Node to traverse. + * + * @return Node Result of traversal (may be original node or new one) + */ + private function traverseNode(Node $node): Node + { + $subNodeNames = array_keys(get_object_vars($node)); + foreach ($subNodeNames as $name) { + $subNode =& $node->$name; + + if (is_array($subNode)) { + $subNode = $this->traverseArray($subNode); + if ($this->stopTraversal) { + break; + } + } elseif ($subNode instanceof Node) { + $traverseChildren = true; + $breakVisitorIndex = null; + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->enterNode($subNode); + if ($return === null) { + continue; + } + + if ($return instanceof Node) { + $this->ensureReplacementReasonable($subNode, $return); + $subNode = $return; + } elseif ($return === self::DONT_TRAVERSE_CHILDREN) { + $traverseChildren = false; + } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { + $traverseChildren = false; + $breakVisitorIndex = $visitorIndex; + break; + } elseif ($return === self::STOP_TRAVERSAL) { + $this->stopTraversal = true; + break 2; + } else { + throw new LogicException( + 'enterNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($traverseChildren) { + $subNode = $this->traverseNode($subNode); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->leaveNode($subNode); + + if ($return !== null) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($subNode, $return); + $subNode = $return; + } elseif ($return === self::STOP_TRAVERSAL) { + $this->stopTraversal = true; + break 2; + } elseif (is_array($return)) { + throw new LogicException( + 'leaveNode() may only return an array ' . + 'if the parent structure is an array' + ); + } else { + throw new LogicException( + 'leaveNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($breakVisitorIndex === $visitorIndex) { + break; + } + } + } + } + + return $node; + } + + /** + * Recursively traverse array (usually of nodes). + * + * @param mixed[] $nodes Array to traverse + * + * @return mixed[] Result of traversal (may be original array or changed one) + */ + private function traverseArray(array $nodes): array + { + $doNodes = []; + + foreach ($nodes as $i => &$node) { + if ($node instanceof Node) { + $traverseChildren = true; + $breakVisitorIndex = null; + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->enterNode($node); + if ($return === null) { + continue; + } + + if ($return instanceof Node) { + $this->ensureReplacementReasonable($node, $return); + $node = $return; + } elseif (is_array($return)) { + $doNodes[] = [$i, $return]; + continue 2; + } elseif ($return === self::REMOVE_NODE) { + $doNodes[] = [$i, []]; + continue 2; + } elseif ($return === self::DONT_TRAVERSE_CHILDREN) { + $traverseChildren = false; + } elseif ($return === self::DONT_TRAVERSE_CURRENT_AND_CHILDREN) { + $traverseChildren = false; + $breakVisitorIndex = $visitorIndex; + break; + } elseif ($return === self::STOP_TRAVERSAL) { + $this->stopTraversal = true; + break 2; + } else { + throw new LogicException( + 'enterNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($traverseChildren) { + $node = $this->traverseNode($node); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitorIndex => $visitor) { + $return = $visitor->leaveNode($node); + + if ($return !== null) { + if ($return instanceof Node) { + $this->ensureReplacementReasonable($node, $return); + $node = $return; + } elseif (is_array($return)) { + $doNodes[] = [$i, $return]; + break; + } elseif ($return === self::REMOVE_NODE) { + $doNodes[] = [$i, []]; + break; + } elseif ($return === self::STOP_TRAVERSAL) { + $this->stopTraversal = true; + break 2; + } else { + throw new LogicException( + 'leaveNode() returned invalid value of type ' . gettype($return) + ); + } + } + + if ($breakVisitorIndex === $visitorIndex) { + break; + } + } + } elseif (is_array($node)) { + throw new LogicException('Invalid node structure: Contains nested arrays'); + } + } + + if (count($doNodes) > 0) { + while ([$i, $replace] = array_pop($doNodes)) { + array_splice($nodes, $i, 1, $replace); + } + } + + return $nodes; + } + + private function ensureReplacementReasonable(Node $old, Node $new): void + { + if ($old instanceof TypeNode && !$new instanceof TypeNode) { + throw new LogicException(sprintf('Trying to replace TypeNode with %s', get_class($new))); + } + + if ($old instanceof ConstExprNode && !$new instanceof ConstExprNode) { + throw new LogicException(sprintf('Trying to replace ConstExprNode with %s', get_class($new))); + } + + if ($old instanceof PhpDocChildNode && !$new instanceof PhpDocChildNode) { + throw new LogicException(sprintf('Trying to replace PhpDocChildNode with %s', get_class($new))); + } + + if ($old instanceof PhpDocTagValueNode && !$new instanceof PhpDocTagValueNode) { + throw new LogicException(sprintf('Trying to replace PhpDocTagValueNode with %s', get_class($new))); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php new file mode 100644 index 000000000..bf7d784e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php @@ -0,0 +1,87 @@ + $node stays as-is + * * array (of Nodes) + * => The return value is merged into the parent array (at the position of the $node) + * * NodeTraverser::REMOVE_NODE + * => $node is removed from the parent array + * * NodeTraverser::DONT_TRAVERSE_CHILDREN + * => Children of $node are not traversed. $node stays as-is + * * NodeTraverser::DONT_TRAVERSE_CURRENT_AND_CHILDREN + * => Further visitors for the current node are skipped, and its children are not + * traversed. $node stays as-is. + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return Node|Node[]|NodeTraverser::*|null Replacement node (or special return value) + */ + public function enterNode(Node $node); + + /** + * Called when leaving a node. + * + * Return value semantics: + * * null + * => $node stays as-is + * * NodeTraverser::REMOVE_NODE + * => $node is removed from the parent array + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * array (of Nodes) + * => The return value is merged into the parent array (at the position of the $node) + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return Node|Node[]|NodeTraverser::REMOVE_NODE|NodeTraverser::STOP_TRAVERSAL|null Replacement node (or special return value) + */ + public function leaveNode(Node $node); + + /** + * Called once after traversal. + * + * Return value semantics: + * * null: $nodes stays as-is + * * otherwise: $nodes is set to the return value + * + * @param Node[] $nodes Array of nodes + * + * @return Node[]|null Array of nodes + */ + public function afterTraverse(array $nodes): ?array; + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php new file mode 100644 index 000000000..7200f3af4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php @@ -0,0 +1,20 @@ +setAttribute(Attribute::ORIGINAL_NODE, $originalNode); + + return $node; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php new file mode 100644 index 000000000..cf4f55631 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php @@ -0,0 +1,50 @@ +type = $type; + $this->parameter = $parameter; + $this->method = $method; + $this->isNegated = $isNegated; + $this->isEquality = $isEquality; + $this->description = $description; + } + + + public function __toString(): string + { + $isNegated = $this->isNegated ? '!' : ''; + $isEquality = $this->isEquality ? '=' : ''; + return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->method}() {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php new file mode 100644 index 000000000..4fb31807f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php @@ -0,0 +1,50 @@ +type = $type; + $this->parameter = $parameter; + $this->property = $property; + $this->isNegated = $isNegated; + $this->isEquality = $isEquality; + $this->description = $description; + } + + + public function __toString(): string + { + $isNegated = $this->isNegated ? '!' : ''; + $isEquality = $this->isEquality ? '=' : ''; + return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter}->{$this->property} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php new file mode 100644 index 000000000..d6423f50d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php @@ -0,0 +1,46 @@ +type = $type; + $this->parameter = $parameter; + $this->isNegated = $isNegated; + $this->isEquality = $isEquality; + $this->description = $description; + } + + + public function __toString(): string + { + $isNegated = $this->isNegated ? '!' : ''; + $isEquality = $this->isEquality ? '=' : ''; + return trim("{$isNegated}{$isEquality}{$this->type} {$this->parameter} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php new file mode 100644 index 000000000..abf2f1a64 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php @@ -0,0 +1,27 @@ +description = $description; + } + + + public function __toString(): string + { + return trim($this->description); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php new file mode 100644 index 000000000..3a93f5aab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php @@ -0,0 +1,35 @@ + */ + public $arguments; + + /** + * @param list $arguments + */ + public function __construct(string $name, array $arguments) + { + $this->name = $name; + $this->arguments = $arguments; + } + + public function __toString(): string + { + $arguments = implode(', ', $this->arguments); + return $this->name . '(' . $arguments . ')'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php new file mode 100644 index 000000000..f30812cff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php @@ -0,0 +1,43 @@ +key = $key; + $this->value = $value; + } + + + public function __toString(): string + { + if ($this->key === null) { + return (string) $this->value; + } + + return $this->key . '=' . $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php new file mode 100644 index 000000000..e740567d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php @@ -0,0 +1,32 @@ + */ + public $items; + + /** + * @param list $items + */ + public function __construct(array $items) + { + $this->items = $items; + } + + public function __toString(): string + { + $items = implode(', ', $this->items); + + return '{' . $items . '}'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php new file mode 100644 index 000000000..d2dbf2b67 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php @@ -0,0 +1,47 @@ +key = $key; + $this->value = $value; + } + + + public function __toString(): string + { + if ($this->key === null) { + return (string) $this->value; + } + + return $this->key . '=' . $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php new file mode 100644 index 000000000..84f7b18b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php @@ -0,0 +1,36 @@ +annotation = $annotation; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->annotation} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php new file mode 100644 index 000000000..3bf53e13c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php new file mode 100644 index 000000000..026aa1537 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php @@ -0,0 +1,26 @@ +value = $value; + } + + + public function __toString(): string + { + return $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php new file mode 100644 index 000000000..99043d912 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php new file mode 100644 index 000000000..ca7b4f20a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php @@ -0,0 +1,53 @@ +value = $value; + $this->exceptionArgs = [ + $exception->getCurrentTokenValue(), + $exception->getCurrentTokenType(), + $exception->getCurrentOffset(), + $exception->getExpectedTokenType(), + $exception->getExpectedTokenValue(), + $exception->getCurrentTokenLine(), + ]; + } + + public function __get(string $name): ?ParserException + { + if ($name !== 'exception') { + trigger_error(sprintf('Undefined property: %s::$%s', self::class, $name), E_USER_WARNING); + return null; + } + + return new ParserException(...$this->exceptionArgs); + } + + public function __toString(): string + { + return $this->value; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php new file mode 100644 index 000000000..211510bee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php @@ -0,0 +1,58 @@ +isStatic = $isStatic; + $this->returnType = $returnType; + $this->methodName = $methodName; + $this->parameters = $parameters; + $this->description = $description; + $this->templateTypes = $templateTypes; + } + + + public function __toString(): string + { + $static = $this->isStatic ? 'static ' : ''; + $returnType = $this->returnType !== null ? "{$this->returnType} " : ''; + $parameters = implode(', ', $this->parameters); + $description = $this->description !== '' ? " {$this->description}" : ''; + $templateTypes = count($this->templateTypes) > 0 ? '<' . implode(', ', $this->templateTypes) . '>' : ''; + return "{$static}{$returnType}{$this->methodName}{$templateTypes}({$parameters}){$description}"; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php new file mode 100644 index 000000000..7c17e44c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php @@ -0,0 +1,49 @@ +type = $type; + $this->isReference = $isReference; + $this->isVariadic = $isVariadic; + $this->parameterName = $parameterName; + $this->defaultValue = $defaultValue; + } + + + public function __toString(): string + { + $type = $this->type !== null ? "{$this->type} " : ''; + $isReference = $this->isReference ? '&' : ''; + $isVariadic = $this->isVariadic ? '...' : ''; + $default = $this->defaultValue !== null ? " = {$this->defaultValue}" : ''; + return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}"; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php new file mode 100644 index 000000000..d9b7d78a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php new file mode 100644 index 000000000..0ac2131a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php @@ -0,0 +1,35 @@ +type = $type; + $this->parameterName = $parameterName; + $this->description = $description; + } + + public function __toString(): string + { + return trim("{$this->type} {$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php new file mode 100644 index 000000000..0f480f7a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php @@ -0,0 +1,30 @@ +parameterName = $parameterName; + $this->description = $description; + } + + public function __toString(): string + { + return trim("{$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php new file mode 100644 index 000000000..eab353f99 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php @@ -0,0 +1,30 @@ +parameterName = $parameterName; + $this->description = $description; + } + + public function __toString(): string + { + return trim("{$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php new file mode 100644 index 000000000..9f374bf18 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php @@ -0,0 +1,35 @@ +type = $type; + $this->parameterName = $parameterName; + $this->description = $description; + } + + public function __toString(): string + { + return trim("{$this->type} {$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php new file mode 100644 index 000000000..f93af0ea1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php @@ -0,0 +1,46 @@ +type = $type; + $this->isReference = $isReference; + $this->isVariadic = $isVariadic; + $this->parameterName = $parameterName; + $this->description = $description; + } + + + public function __toString(): string + { + $reference = $this->isReference ? '&' : ''; + $variadic = $this->isVariadic ? '...' : ''; + return trim("{$this->type} {$reference}{$variadic}{$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php new file mode 100644 index 000000000..6162f92df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php @@ -0,0 +1,10 @@ +children = $children; + } + + + /** + * @return PhpDocTagNode[] + */ + public function getTags(): array + { + return array_filter($this->children, static function (PhpDocChildNode $child): bool { + return $child instanceof PhpDocTagNode; + }); + } + + + /** + * @return PhpDocTagNode[] + */ + public function getTagsByName(string $tagName): array + { + return array_filter($this->getTags(), static function (PhpDocTagNode $tag) use ($tagName): bool { + return $tag->name === $tagName; + }); + } + + + /** + * @return VarTagValueNode[] + */ + public function getVarTagValues(string $tagName = '@var'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof VarTagValueNode; + } + ); + } + + + /** + * @return ParamTagValueNode[] + */ + public function getParamTagValues(string $tagName = '@param'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ParamTagValueNode; + } + ); + } + + + /** + * @return TypelessParamTagValueNode[] + */ + public function getTypelessParamTagValues(string $tagName = '@param'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof TypelessParamTagValueNode; + } + ); + } + + + /** + * @return ParamImmediatelyInvokedCallableTagValueNode[] + */ + public function getParamImmediatelyInvokedCallableTagValues(string $tagName = '@param-immediately-invoked-callable'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ParamImmediatelyInvokedCallableTagValueNode; + } + ); + } + + + /** + * @return ParamLaterInvokedCallableTagValueNode[] + */ + public function getParamLaterInvokedCallableTagValues(string $tagName = '@param-later-invoked-callable'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ParamLaterInvokedCallableTagValueNode; + } + ); + } + + + /** + * @return ParamClosureThisTagValueNode[] + */ + public function getParamClosureThisTagValues(string $tagName = '@param-closure-this'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ParamClosureThisTagValueNode; + } + ); + } + + /** + * @return PureUnlessCallableIsImpureTagValueNode[] + */ + public function getPureUnlessCallableIsImpureTagValues(string $tagName = '@pure-unless-callable-is-impure'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof PureUnlessCallableIsImpureTagValueNode; + } + ); + } + + /** + * @return TemplateTagValueNode[] + */ + public function getTemplateTagValues(string $tagName = '@template'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof TemplateTagValueNode; + } + ); + } + + + /** + * @return ExtendsTagValueNode[] + */ + public function getExtendsTagValues(string $tagName = '@extends'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ExtendsTagValueNode; + } + ); + } + + + /** + * @return ImplementsTagValueNode[] + */ + public function getImplementsTagValues(string $tagName = '@implements'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ImplementsTagValueNode; + } + ); + } + + + /** + * @return UsesTagValueNode[] + */ + public function getUsesTagValues(string $tagName = '@use'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof UsesTagValueNode; + } + ); + } + + + /** + * @return ReturnTagValueNode[] + */ + public function getReturnTagValues(string $tagName = '@return'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ReturnTagValueNode; + } + ); + } + + + /** + * @return ThrowsTagValueNode[] + */ + public function getThrowsTagValues(string $tagName = '@throws'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ThrowsTagValueNode; + } + ); + } + + + /** + * @return MixinTagValueNode[] + */ + public function getMixinTagValues(string $tagName = '@mixin'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof MixinTagValueNode; + } + ); + } + + /** + * @return RequireExtendsTagValueNode[] + */ + public function getRequireExtendsTagValues(string $tagName = '@phpstan-require-extends'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof RequireExtendsTagValueNode; + } + ); + } + + /** + * @return RequireImplementsTagValueNode[] + */ + public function getRequireImplementsTagValues(string $tagName = '@phpstan-require-implements'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof RequireImplementsTagValueNode; + } + ); + } + + /** + * @return DeprecatedTagValueNode[] + */ + public function getDeprecatedTagValues(): array + { + return array_filter( + array_column($this->getTagsByName('@deprecated'), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof DeprecatedTagValueNode; + } + ); + } + + + /** + * @return PropertyTagValueNode[] + */ + public function getPropertyTagValues(string $tagName = '@property'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof PropertyTagValueNode; + } + ); + } + + + /** + * @return PropertyTagValueNode[] + */ + public function getPropertyReadTagValues(string $tagName = '@property-read'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof PropertyTagValueNode; + } + ); + } + + + /** + * @return PropertyTagValueNode[] + */ + public function getPropertyWriteTagValues(string $tagName = '@property-write'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof PropertyTagValueNode; + } + ); + } + + + /** + * @return MethodTagValueNode[] + */ + public function getMethodTagValues(string $tagName = '@method'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof MethodTagValueNode; + } + ); + } + + + /** + * @return TypeAliasTagValueNode[] + */ + public function getTypeAliasTagValues(string $tagName = '@phpstan-type'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof TypeAliasTagValueNode; + } + ); + } + + + /** + * @return TypeAliasImportTagValueNode[] + */ + public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof TypeAliasImportTagValueNode; + } + ); + } + + + /** + * @return AssertTagValueNode[] + */ + public function getAssertTagValues(string $tagName = '@phpstan-assert'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof AssertTagValueNode; + } + ); + } + + + /** + * @return AssertTagPropertyValueNode[] + */ + public function getAssertPropertyTagValues(string $tagName = '@phpstan-assert'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof AssertTagPropertyValueNode; + } + ); + } + + + /** + * @return AssertTagMethodValueNode[] + */ + public function getAssertMethodTagValues(string $tagName = '@phpstan-assert'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof AssertTagMethodValueNode; + } + ); + } + + + /** + * @return SelfOutTagValueNode[] + */ + public function getSelfOutTypeTagValues(string $tagName = '@phpstan-this-out'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof SelfOutTagValueNode; + } + ); + } + + + /** + * @return ParamOutTagValueNode[] + */ + public function getParamOutTypeTagValues(string $tagName = '@param-out'): array + { + return array_filter( + array_column($this->getTagsByName($tagName), 'value'), + static function (PhpDocTagValueNode $value): bool { + return $value instanceof ParamOutTagValueNode; + } + ); + } + + + public function __toString(): string + { + $children = array_map( + static function (PhpDocChildNode $child): string { + $s = (string) $child; + return $s === '' ? '' : ' ' . $s; + }, + $this->children + ); + return "/**\n *" . implode("\n *", $children) . "\n */"; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php new file mode 100644 index 000000000..d20746fcf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php @@ -0,0 +1,36 @@ +name = $name; + $this->value = $value; + } + + + public function __toString(): string + { + if ($this->value instanceof DoctrineTagValueNode) { + return (string) $this->value; + } + + return trim("{$this->name} {$this->value}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php new file mode 100644 index 000000000..7723fa0c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php @@ -0,0 +1,10 @@ +text = $text; + } + + + public function __toString(): string + { + return $this->text; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php new file mode 100644 index 000000000..046003d18 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php @@ -0,0 +1,36 @@ +type = $type; + $this->propertyName = $propertyName; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->propertyName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php new file mode 100644 index 000000000..4cf0937d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php @@ -0,0 +1,30 @@ +parameterName = $parameterName; + $this->description = $description; + } + + public function __toString(): string + { + return trim("{$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php new file mode 100644 index 000000000..91c268928 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php new file mode 100644 index 000000000..65c9213f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php new file mode 100644 index 000000000..d53c8c755 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php new file mode 100644 index 000000000..83169aff7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim($this->type . ' ' . $this->description); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php new file mode 100644 index 000000000..8bc01f6e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php @@ -0,0 +1,50 @@ +name = $name; + $this->bound = $bound; + $this->lowerBound = $lowerBound; + $this->default = $default; + $this->description = $description; + } + + + public function __toString(): string + { + $upperBound = $this->bound !== null ? " of {$this->bound}" : ''; + $lowerBound = $this->lowerBound !== null ? " super {$this->lowerBound}" : ''; + $default = $this->default !== null ? " = {$this->default}" : ''; + return trim("{$this->name}{$upperBound}{$lowerBound}{$default} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php new file mode 100644 index 000000000..62d2aed3b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php new file mode 100644 index 000000000..ad6b85a57 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php @@ -0,0 +1,38 @@ +importedAlias = $importedAlias; + $this->importedFrom = $importedFrom; + $this->importedAs = $importedAs; + } + + public function __toString(): string + { + return trim( + "{$this->importedAlias} from {$this->importedFrom}" + . ($this->importedAs !== null ? " as {$this->importedAs}" : '') + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php new file mode 100644 index 000000000..4ccaaac4b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php @@ -0,0 +1,32 @@ +alias = $alias; + $this->type = $type; + } + + + public function __toString(): string + { + return trim("{$this->alias} {$this->type}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php new file mode 100644 index 000000000..8b9829549 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php @@ -0,0 +1,41 @@ +isReference = $isReference; + $this->isVariadic = $isVariadic; + $this->parameterName = $parameterName; + $this->description = $description; + } + + + public function __toString(): string + { + $reference = $this->isReference ? '&' : ''; + $variadic = $this->isVariadic ? '...' : ''; + return trim("{$reference}{$variadic}{$this->parameterName} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php new file mode 100644 index 000000000..cd573d975 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php @@ -0,0 +1,32 @@ +type = $type; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("{$this->type} {$this->description}"); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php new file mode 100644 index 000000000..afb941a83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php @@ -0,0 +1,36 @@ +type = $type; + $this->variableName = $variableName; + $this->description = $description; + } + + + public function __toString(): string + { + return trim("$this->type " . trim("{$this->variableName} {$this->description}")); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php new file mode 100644 index 000000000..660c6c9d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php @@ -0,0 +1,49 @@ +keyName = $keyName; + $this->optional = $optional; + $this->valueType = $valueType; + } + + + public function __toString(): string + { + if ($this->keyName !== null) { + return sprintf( + '%s%s: %s', + (string) $this->keyName, + $this->optional ? '?' : '', + (string) $this->valueType + ); + } + + return (string) $this->valueType; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php new file mode 100644 index 000000000..73d162ded --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php @@ -0,0 +1,59 @@ +items = $items; + $this->sealed = $sealed; + $this->kind = $kind; + $this->unsealedType = $unsealedType; + } + + + public function __toString(): string + { + $items = $this->items; + + if (! $this->sealed) { + $items[] = '...' . $this->unsealedType; + } + + return $this->kind . '{' . implode(', ', $items) . '}'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php new file mode 100644 index 000000000..7ffdf1d2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php @@ -0,0 +1,34 @@ +valueType = $valueType; + $this->keyType = $keyType; + } + + public function __toString(): string + { + if ($this->keyType !== null) { + return sprintf('<%s, %s>', $this->keyType, $this->valueType); + } + return sprintf('<%s>', $this->valueType); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php new file mode 100644 index 000000000..d2031032f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php @@ -0,0 +1,34 @@ +type = $type; + } + + + public function __toString(): string + { + if ( + $this->type instanceof CallableTypeNode + || $this->type instanceof ConstTypeNode + || $this->type instanceof NullableTypeNode + ) { + return '(' . $this->type . ')[]'; + } + + return $this->type . '[]'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php new file mode 100644 index 000000000..4c9131985 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php @@ -0,0 +1,52 @@ +identifier = $identifier; + $this->parameters = $parameters; + $this->returnType = $returnType; + $this->templateTypes = $templateTypes; + } + + + public function __toString(): string + { + $returnType = $this->returnType; + if ($returnType instanceof self) { + $returnType = "({$returnType})"; + } + $template = $this->templateTypes !== [] + ? '<' . implode(', ', $this->templateTypes) . '>' + : ''; + $parameters = implode(', ', $this->parameters); + return "{$this->identifier}{$template}({$parameters}): {$returnType}"; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php new file mode 100644 index 000000000..c78d4c7b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php @@ -0,0 +1,48 @@ +type = $type; + $this->isReference = $isReference; + $this->isVariadic = $isVariadic; + $this->parameterName = $parameterName; + $this->isOptional = $isOptional; + } + + + public function __toString(): string + { + $type = "{$this->type} "; + $isReference = $this->isReference ? '&' : ''; + $isVariadic = $this->isVariadic ? '...' : ''; + $isOptional = $this->isOptional ? '=' : ''; + return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $isOptional; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php new file mode 100644 index 000000000..fbfcae95d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php @@ -0,0 +1,49 @@ +parameterName = $parameterName; + $this->targetType = $targetType; + $this->if = $if; + $this->else = $else; + $this->negated = $negated; + } + + public function __toString(): string + { + return sprintf( + '(%s %s %s ? %s : %s)', + $this->parameterName, + $this->negated ? 'is not' : 'is', + $this->targetType, + $this->if, + $this->else + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php new file mode 100644 index 000000000..bfdb0db1a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php @@ -0,0 +1,49 @@ +subjectType = $subjectType; + $this->targetType = $targetType; + $this->if = $if; + $this->else = $else; + $this->negated = $negated; + } + + public function __toString(): string + { + return sprintf( + '(%s %s %s ? %s : %s)', + $this->subjectType, + $this->negated ? 'is not' : 'is', + $this->targetType, + $this->if, + $this->else + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php new file mode 100644 index 000000000..0096055b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php @@ -0,0 +1,26 @@ +constExpr = $constExpr; + } + + public function __toString(): string + { + return $this->constExpr->__toString(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php new file mode 100644 index 000000000..44e1d16df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php @@ -0,0 +1,58 @@ +type = $type; + $this->genericTypes = $genericTypes; + $this->variances = $variances; + } + + + public function __toString(): string + { + $genericTypes = []; + + foreach ($this->genericTypes as $index => $type) { + $variance = $this->variances[$index] ?? self::VARIANCE_INVARIANT; + if ($variance === self::VARIANCE_INVARIANT) { + $genericTypes[] = (string) $type; + } elseif ($variance === self::VARIANCE_BIVARIANT) { + $genericTypes[] = '*'; + } else { + $genericTypes[] = sprintf('%s %s', $variance, $type); + } + } + + return $this->type . '<' . implode(', ', $genericTypes) . '>'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php new file mode 100644 index 000000000..29bac308e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php @@ -0,0 +1,26 @@ +name = $name; + } + + + public function __toString(): string + { + return $this->name; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php new file mode 100644 index 000000000..fd761cf78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php @@ -0,0 +1,37 @@ +types = $types; + } + + + public function __toString(): string + { + return '(' . implode(' & ', array_map(static function (TypeNode $type): string { + if ($type instanceof NullableTypeNode) { + return '(' . $type . ')'; + } + + return (string) $type; + }, $this->types)) . ')'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php new file mode 100644 index 000000000..1ec47cf6c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php @@ -0,0 +1,38 @@ +exceptionArgs = [ + $exception->getCurrentTokenValue(), + $exception->getCurrentTokenType(), + $exception->getCurrentOffset(), + $exception->getExpectedTokenType(), + $exception->getExpectedTokenValue(), + $exception->getCurrentTokenLine(), + ]; + } + + public function getException(): ParserException + { + return new ParserException(...$this->exceptionArgs); + } + + public function __toString(): string + { + return '*Invalid type*'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php new file mode 100644 index 000000000..73f438cd2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php @@ -0,0 +1,26 @@ +type = $type; + } + + + public function __toString(): string + { + return '?' . $this->type; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php new file mode 100644 index 000000000..2f0124066 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php @@ -0,0 +1,48 @@ +keyName = $keyName; + $this->optional = $optional; + $this->valueType = $valueType; + } + + + public function __toString(): string + { + if ($this->keyName !== null) { + return sprintf( + '%s%s: %s', + (string) $this->keyName, + $this->optional ? '?' : '', + (string) $this->valueType + ); + } + + return (string) $this->valueType; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php new file mode 100644 index 000000000..f418bc30b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php @@ -0,0 +1,31 @@ +items = $items; + } + + public function __toString(): string + { + $items = $this->items; + + return 'object{' . implode(', ', $items) . '}'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php new file mode 100644 index 000000000..c27ec0a3e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php @@ -0,0 +1,36 @@ +type = $type; + $this->offset = $offset; + } + + public function __toString(): string + { + if ( + $this->type instanceof CallableTypeNode + || $this->type instanceof NullableTypeNode + ) { + return '(' . $this->type . ')[' . $this->offset . ']'; + } + + return $this->type . '[' . $this->offset . ']'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php new file mode 100644 index 000000000..d94e6f838 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php @@ -0,0 +1,17 @@ +types = $types; + } + + + public function __toString(): string + { + return '(' . implode(' | ', array_map(static function (TypeNode $type): string { + if ($type instanceof NullableTypeNode) { + return '(' . $type . ')'; + } + + return (string) $type; + }, $this->types)) . ')'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php new file mode 100644 index 000000000..32539faf6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php @@ -0,0 +1,198 @@ + '\'&\'', + self::TOKEN_UNION => '\'|\'', + self::TOKEN_INTERSECTION => '\'&\'', + self::TOKEN_NULLABLE => '\'?\'', + self::TOKEN_NEGATED => '\'!\'', + self::TOKEN_OPEN_PARENTHESES => '\'(\'', + self::TOKEN_CLOSE_PARENTHESES => '\')\'', + self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'', + self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'', + self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'', + self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'', + self::TOKEN_OPEN_CURLY_BRACKET => '\'{\'', + self::TOKEN_CLOSE_CURLY_BRACKET => '\'}\'', + self::TOKEN_COMMA => '\',\'', + self::TOKEN_COLON => '\':\'', + self::TOKEN_VARIADIC => '\'...\'', + self::TOKEN_DOUBLE_COLON => '\'::\'', + self::TOKEN_DOUBLE_ARROW => '\'=>\'', + self::TOKEN_ARROW => '\'->\'', + self::TOKEN_EQUAL => '\'=\'', + self::TOKEN_OPEN_PHPDOC => '\'/**\'', + self::TOKEN_CLOSE_PHPDOC => '\'*/\'', + self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', + self::TOKEN_DOCTRINE_TAG => 'TOKEN_DOCTRINE_TAG', + self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', + self::TOKEN_FLOAT => 'TOKEN_FLOAT', + self::TOKEN_INTEGER => 'TOKEN_INTEGER', + self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING', + self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING', + self::TOKEN_DOCTRINE_ANNOTATION_STRING => 'TOKEN_DOCTRINE_ANNOTATION_STRING', + self::TOKEN_IDENTIFIER => 'type', + self::TOKEN_THIS_VARIABLE => '\'$this\'', + self::TOKEN_VARIABLE => 'variable', + self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS', + self::TOKEN_OTHER => 'TOKEN_OTHER', + self::TOKEN_END => 'TOKEN_END', + self::TOKEN_WILDCARD => '*', + ]; + + public const VALUE_OFFSET = 0; + public const TYPE_OFFSET = 1; + public const LINE_OFFSET = 2; + + /** @var bool */ + private $parseDoctrineAnnotations; + + /** @var string|null */ + private $regexp; + + public function __construct(bool $parseDoctrineAnnotations = false) + { + $this->parseDoctrineAnnotations = $parseDoctrineAnnotations; + } + + /** + * @return list + */ + public function tokenize(string $s): array + { + if ($this->regexp === null) { + $this->regexp = $this->generateRegexp(); + } + + preg_match_all($this->regexp, $s, $matches, PREG_SET_ORDER); + + $tokens = []; + $line = 1; + foreach ($matches as $match) { + $type = (int) $match['MARK']; + $tokens[] = [$match[0], $type, $line]; + if ($type !== self::TOKEN_PHPDOC_EOL) { + continue; + } + + $line++; + } + + $tokens[] = ['', self::TOKEN_END, $line]; + + return $tokens; + } + + + private function generateRegexp(): string + { + $patterns = [ + self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++', + + self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF-]*+)++', + self::TOKEN_THIS_VARIABLE => '\\$this(?![0-9a-z_\\x80-\\xFF])', + self::TOKEN_VARIABLE => '\\$[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF]*+', + + // '&' followed by TOKEN_VARIADIC, TOKEN_VARIABLE, TOKEN_EQUAL, TOKEN_EQUAL or TOKEN_CLOSE_PARENTHESES + self::TOKEN_REFERENCE => '&(?=\\s*+(?:[.,=)]|(?:\\$(?!this(?![0-9a-z_\\x80-\\xFF])))))', + self::TOKEN_UNION => '\\|', + self::TOKEN_INTERSECTION => '&', + self::TOKEN_NULLABLE => '\\?', + self::TOKEN_NEGATED => '!', + + self::TOKEN_OPEN_PARENTHESES => '\\(', + self::TOKEN_CLOSE_PARENTHESES => '\\)', + self::TOKEN_OPEN_ANGLE_BRACKET => '<', + self::TOKEN_CLOSE_ANGLE_BRACKET => '>', + self::TOKEN_OPEN_SQUARE_BRACKET => '\\[', + self::TOKEN_CLOSE_SQUARE_BRACKET => '\\]', + self::TOKEN_OPEN_CURLY_BRACKET => '\\{', + self::TOKEN_CLOSE_CURLY_BRACKET => '\\}', + + self::TOKEN_COMMA => ',', + self::TOKEN_VARIADIC => '\\.\\.\\.', + self::TOKEN_DOUBLE_COLON => '::', + self::TOKEN_DOUBLE_ARROW => '=>', + self::TOKEN_ARROW => '->', + self::TOKEN_EQUAL => '=', + self::TOKEN_COLON => ':', + + self::TOKEN_OPEN_PHPDOC => '/\\*\\*(?=\\s)\\x20?+', + self::TOKEN_CLOSE_PHPDOC => '\\*/', + self::TOKEN_PHPDOC_TAG => '@(?:[a-z][a-z0-9-\\\\]+:)?[a-z][a-z0-9-\\\\]*+', + self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?', + + self::TOKEN_FLOAT => '[+\-]?(?:(?:[0-9]++(_[0-9]++)*\\.[0-9]*+(_[0-9]++)*(?:e[+\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e[+\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]++(_[0-9]++)*e[+\-]?[0-9]++(_[0-9]++)*))', + self::TOKEN_INTEGER => '[+\-]?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))', + self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'', + self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"', + + self::TOKEN_WILDCARD => '\\*', + ]; + + if ($this->parseDoctrineAnnotations) { + $patterns[self::TOKEN_DOCTRINE_TAG] = '@[a-z_\\\\][a-z0-9_\:\\\\]*[a-z_][a-z0-9_]*'; + $patterns[self::TOKEN_DOCTRINE_ANNOTATION_STRING] = '"(?:""|[^"])*+"'; + } + + // anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL + $patterns[self::TOKEN_OTHER] = '(?:(?!\\*/)[^\\s])++'; + + foreach ($patterns as $type => &$pattern) { + $pattern = '(?:' . $pattern . ')(*MARK:' . $type . ')'; + } + + return '~' . implode('|', $patterns) . '~Asi'; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php new file mode 100644 index 000000000..f6a7306e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php @@ -0,0 +1,333 @@ +unescapeStrings = $unescapeStrings; + $this->quoteAwareConstExprString = $quoteAwareConstExprString; + $this->useLinesAttributes = $usedAttributes['lines'] ?? false; + $this->useIndexAttributes = $usedAttributes['indexes'] ?? false; + $this->parseDoctrineStrings = false; + } + + /** + * @internal + */ + public function toDoctrine(): self + { + $self = new self( + $this->unescapeStrings, + $this->quoteAwareConstExprString, + [ + 'lines' => $this->useLinesAttributes, + 'indexes' => $this->useIndexAttributes, + ] + ); + $self->parseDoctrineStrings = true; + return $self; + } + + public function parse(TokenIterator $tokens, bool $trimStrings = false): Ast\ConstExpr\ConstExprNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) { + $value = $tokens->currentTokenValue(); + $tokens->next(); + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprFloatNode(str_replace('_', '', $value)), + $startLine, + $startIndex + ); + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { + $value = $tokens->currentTokenValue(); + $tokens->next(); + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $value)), + $startLine, + $startIndex + ); + } + + if ($this->parseDoctrineStrings && $tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) { + $value = $tokens->currentTokenValue(); + $tokens->next(); + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($value)), + $startLine, + $startIndex + ); + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING, Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { + if ($this->parseDoctrineStrings) { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_DOUBLE_QUOTED_STRING, + null, + $tokens->currentTokenLine() + ); + } + + $value = $tokens->currentTokenValue(); + $tokens->next(); + + return $this->enrichWithAttributes( + $tokens, + $this->parseDoctrineString($value, $tokens), + $startLine, + $startIndex + ); + } + $value = $tokens->currentTokenValue(); + $type = $tokens->currentTokenType(); + if ($trimStrings) { + if ($this->unescapeStrings) { + $value = StringUnescaper::unescapeString($value); + } else { + $value = substr($value, 1, -1); + } + } + $tokens->next(); + + if ($this->quoteAwareConstExprString) { + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\QuoteAwareConstExprStringNode( + $value, + $type === Lexer::TOKEN_SINGLE_QUOTED_STRING + ? Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED + : Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED + ), + $startLine, + $startIndex + ); + } + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprStringNode($value), + $startLine, + $startIndex + ); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { + $identifier = $tokens->currentTokenValue(); + $tokens->next(); + + switch (strtolower($identifier)) { + case 'true': + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprTrueNode(), + $startLine, + $startIndex + ); + case 'false': + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprFalseNode(), + $startLine, + $startIndex + ); + case 'null': + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprNullNode(), + $startLine, + $startIndex + ); + case 'array': + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); + return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES, $startIndex); + } + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + $classConstantName = ''; + $lastType = null; + while (true) { + if ($lastType !== Lexer::TOKEN_IDENTIFIER && $tokens->currentTokenType() === Lexer::TOKEN_IDENTIFIER) { + $classConstantName .= $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + $lastType = Lexer::TOKEN_IDENTIFIER; + + continue; + } + + if ($lastType !== Lexer::TOKEN_WILDCARD && $tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) { + $classConstantName .= '*'; + $lastType = Lexer::TOKEN_WILDCARD; + + if ($tokens->getSkippedHorizontalWhiteSpaceIfAny() !== '') { + break; + } + + continue; + } + + if ($lastType === null) { + // trigger parse error if nothing valid was consumed + $tokens->consumeTokenType(Lexer::TOKEN_WILDCARD); + } + + break; + } + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName), + $startLine, + $startIndex + ); + + } + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstFetchNode('', $identifier), + $startLine, + $startIndex + ); + + } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET, $startIndex); + } + + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_IDENTIFIER, + null, + $tokens->currentTokenLine() + ); + } + + + private function parseArray(TokenIterator $tokens, int $endToken, int $startIndex): Ast\ConstExpr\ConstExprArrayNode + { + $items = []; + + $startLine = $tokens->currentTokenLine(); + + if (!$tokens->tryConsumeTokenType($endToken)) { + do { + $items[] = $this->parseArrayItem($tokens); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA) && !$tokens->isCurrentTokenType($endToken)); + $tokens->consumeTokenType($endToken); + } + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprArrayNode($items), + $startLine, + $startIndex + ); + } + + + /** + * This method is supposed to be called with TokenIterator after reading TOKEN_DOUBLE_QUOTED_STRING and shifting + * to the next token. + */ + public function parseDoctrineString(string $text, TokenIterator $tokens): Ast\ConstExpr\DoctrineConstExprStringNode + { + // Because of how Lexer works, a valid Doctrine string + // can consist of a sequence of TOKEN_DOUBLE_QUOTED_STRING and TOKEN_DOCTRINE_ANNOTATION_STRING + while ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING, Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) { + $text .= $tokens->currentTokenValue(); + $tokens->next(); + } + + return new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($text)); + } + + + private function parseArrayItem(TokenIterator $tokens): Ast\ConstExpr\ConstExprArrayItemNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + $expr = $this->parse($tokens); + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) { + $key = $expr; + $value = $this->parse($tokens); + + } else { + $key = null; + $value = $expr; + } + + return $this->enrichWithAttributes( + $tokens, + new Ast\ConstExpr\ConstExprArrayItemNode($key, $value), + $startLine, + $startIndex + ); + } + + /** + * @template T of Ast\ConstExpr\ConstExprNode + * @param T $node + * @return T + */ + private function enrichWithAttributes(TokenIterator $tokens, Ast\ConstExpr\ConstExprNode $node, int $startLine, int $startIndex): Ast\ConstExpr\ConstExprNode + { + if ($this->useLinesAttributes) { + $node->setAttribute(Ast\Attribute::START_LINE, $startLine); + $node->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); + } + + if ($this->useIndexAttributes) { + $node->setAttribute(Ast\Attribute::START_INDEX, $startIndex); + $node->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); + } + + return $node; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php new file mode 100644 index 000000000..6ab5cc076 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php @@ -0,0 +1,106 @@ +currentTokenValue = $currentTokenValue; + $this->currentTokenType = $currentTokenType; + $this->currentOffset = $currentOffset; + $this->expectedTokenType = $expectedTokenType; + $this->expectedTokenValue = $expectedTokenValue; + $this->currentTokenLine = $currentTokenLine; + + parent::__construct(sprintf( + 'Unexpected token %s, expected %s%s at offset %d%s', + $this->formatValue($currentTokenValue), + Lexer::TOKEN_LABELS[$expectedTokenType], + $expectedTokenValue !== null ? sprintf(' (%s)', $this->formatValue($expectedTokenValue)) : '', + $currentOffset, + $currentTokenLine === null ? '' : sprintf(' on line %d', $currentTokenLine) + )); + } + + + public function getCurrentTokenValue(): string + { + return $this->currentTokenValue; + } + + + public function getCurrentTokenType(): int + { + return $this->currentTokenType; + } + + + public function getCurrentOffset(): int + { + return $this->currentOffset; + } + + + public function getExpectedTokenType(): int + { + return $this->expectedTokenType; + } + + + public function getExpectedTokenValue(): ?string + { + return $this->expectedTokenValue; + } + + + public function getCurrentTokenLine(): ?int + { + return $this->currentTokenLine; + } + + + private function formatValue(string $value): string + { + $json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE); + assert($json !== false); + + return $json; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php new file mode 100644 index 000000000..b6cd85eab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php @@ -0,0 +1,1301 @@ +typeParser = $typeParser; + $this->constantExprParser = $constantExprParser; + $this->doctrineConstantExprParser = $constantExprParser->toDoctrine(); + $this->requireWhitespaceBeforeDescription = $requireWhitespaceBeforeDescription; + $this->preserveTypeAliasesWithInvalidTypes = $preserveTypeAliasesWithInvalidTypes; + $this->parseDoctrineAnnotations = $parseDoctrineAnnotations; + $this->useLinesAttributes = $usedAttributes['lines'] ?? false; + $this->useIndexAttributes = $usedAttributes['indexes'] ?? false; + $this->textBetweenTagsBelongsToDescription = $textBetweenTagsBelongsToDescription; + } + + + public function parse(TokenIterator $tokens): Ast\PhpDoc\PhpDocNode + { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $children = []; + + if ($this->parseDoctrineAnnotations) { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + $lastChild = $this->parseChild($tokens); + $children[] = $lastChild; + while (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + if ( + $lastChild instanceof Ast\PhpDoc\PhpDocTagNode + && ( + $lastChild->value instanceof Doctrine\DoctrineTagValueNode + || $lastChild->value instanceof Ast\PhpDoc\GenericTagValueNode + ) + ) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + break; + } + $lastChild = $this->parseChild($tokens); + $children[] = $lastChild; + continue; + } + + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + break; + } + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + break; + } + + $lastChild = $this->parseChild($tokens); + $children[] = $lastChild; + } + } + } else { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + $children[] = $this->parseChild($tokens); + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL) && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + $children[] = $this->parseChild($tokens); + } + } + } + + try { + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC); + } catch (ParserException $e) { + $name = ''; + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + if (count($children) > 0) { + $lastChild = $children[count($children) - 1]; + if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode) { + $name = $lastChild->name; + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + } + } + + $tag = new Ast\PhpDoc\PhpDocTagNode( + $name, + $this->enrichWithAttributes( + $tokens, + new Ast\PhpDoc\InvalidTagValueNode($e->getMessage(), $e), + $startLine, + $startIndex + ) + ); + + $tokens->forwardToTheEnd(); + + return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode([$this->enrichWithAttributes($tokens, $tag, $startLine, $startIndex)]), 1, 0); + } + + return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode(array_values($children)), 1, 0); + } + + + /** @phpstan-impure */ + private function parseChild(TokenIterator $tokens): Ast\PhpDoc\PhpDocChildNode + { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + return $this->enrichWithAttributes($tokens, $this->parseTag($tokens), $startLine, $startIndex); + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_TAG)) { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $tag = $tokens->currentTokenValue(); + $tokens->next(); + + $tagStartLine = $tokens->currentTokenLine(); + $tagStartIndex = $tokens->currentTokenIndex(); + + return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocTagNode( + $tag, + $this->enrichWithAttributes( + $tokens, + $this->parseDoctrineTagValue($tokens, $tag), + $tagStartLine, + $tagStartIndex + ) + ), $startLine, $startIndex); + } + + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $text = $this->parseText($tokens); + + return $this->enrichWithAttributes($tokens, $text, $startLine, $startIndex); + } + + /** + * @template T of Ast\Node + * @param T $tag + * @return T + */ + private function enrichWithAttributes(TokenIterator $tokens, Ast\Node $tag, int $startLine, int $startIndex): Ast\Node + { + if ($this->useLinesAttributes) { + $tag->setAttribute(Ast\Attribute::START_LINE, $startLine); + $tag->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); + } + + if ($this->useIndexAttributes) { + $tag->setAttribute(Ast\Attribute::START_INDEX, $startIndex); + $tag->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); + } + + return $tag; + } + + + private function parseText(TokenIterator $tokens): Ast\PhpDoc\PhpDocTextNode + { + $text = ''; + + $endTokens = [Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + if ($this->textBetweenTagsBelongsToDescription) { + $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + } + + $savepoint = false; + + // if the next token is EOL, everything below is skipped and empty string is returned + while ($this->textBetweenTagsBelongsToDescription || !$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, ...$endTokens); + $text .= $tmpText; + + // stop if we're not at EOL - meaning it's the end of PHPDoc + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC)) { + break; + } + + if ($this->textBetweenTagsBelongsToDescription) { + if (!$savepoint) { + $tokens->pushSavePoint(); + $savepoint = true; + } elseif ($tmpText !== '') { + $tokens->dropSavePoint(); + $tokens->pushSavePoint(); + } + } + + $tokens->pushSavePoint(); + $tokens->next(); + + // if we're at EOL, check what's next + // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) { + $tokens->rollback(); + break; + } + + // otherwise if the next is text, continue building the description string + + $tokens->dropSavePoint(); + $text .= $tokens->getDetectedNewline() ?? "\n"; + } + + if ($savepoint) { + $tokens->rollback(); + $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n"); + } + + return new Ast\PhpDoc\PhpDocTextNode(trim($text, " \t")); + } + + + private function parseOptionalDescriptionAfterDoctrineTag(TokenIterator $tokens): string + { + $text = ''; + + $endTokens = [Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + if ($this->textBetweenTagsBelongsToDescription) { + $endTokens = [Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END]; + } + + $savepoint = false; + + // if the next token is EOL, everything below is skipped and empty string is returned + while ($this->textBetweenTagsBelongsToDescription || !$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + $tmpText = $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, ...$endTokens); + $text .= $tmpText; + + // stop if we're not at EOL - meaning it's the end of PHPDoc + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC)) { + if (!$tokens->isPrecededByHorizontalWhitespace()) { + return trim($text . $this->parseText($tokens)->text, " \t"); + } + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) { + $tokens->pushSavePoint(); + $child = $this->parseChild($tokens); + if ($child instanceof Ast\PhpDoc\PhpDocTagNode) { + if ( + $child->value instanceof Ast\PhpDoc\GenericTagValueNode + || $child->value instanceof Doctrine\DoctrineTagValueNode + ) { + $tokens->rollback(); + break; + } + if ($child->value instanceof Ast\PhpDoc\InvalidTagValueNode) { + $tokens->rollback(); + $tokens->pushSavePoint(); + $tokens->next(); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $tokens->rollback(); + break; + } + $tokens->rollback(); + return trim($text . $this->parseText($tokens)->text, " \t"); + } + } + + $tokens->rollback(); + return trim($text . $this->parseText($tokens)->text, " \t"); + } + break; + } + + if ($this->textBetweenTagsBelongsToDescription) { + if (!$savepoint) { + $tokens->pushSavePoint(); + $savepoint = true; + } elseif ($tmpText !== '') { + $tokens->dropSavePoint(); + $tokens->pushSavePoint(); + } + } + + $tokens->pushSavePoint(); + $tokens->next(); + + // if we're at EOL, check what's next + // if next is a PHPDoc tag, EOL, or end of PHPDoc, stop + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, ...$endTokens)) { + $tokens->rollback(); + break; + } + + // otherwise if the next is text, continue building the description string + + $tokens->dropSavePoint(); + $text .= $tokens->getDetectedNewline() ?? "\n"; + } + + if ($savepoint) { + $tokens->rollback(); + $text = rtrim($text, $tokens->getDetectedNewline() ?? "\n"); + } + + return trim($text, " \t"); + } + + + public function parseTag(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagNode + { + $tag = $tokens->currentTokenValue(); + $tokens->next(); + $value = $this->parseTagValue($tokens, $tag); + + return new Ast\PhpDoc\PhpDocTagNode($tag, $value); + } + + + public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + try { + $tokens->pushSavePoint(); + + switch ($tag) { + case '@param': + case '@phpstan-param': + case '@psalm-param': + case '@phan-param': + $tagValue = $this->parseParamTagValue($tokens); + break; + + case '@param-immediately-invoked-callable': + case '@phpstan-param-immediately-invoked-callable': + $tagValue = $this->parseParamImmediatelyInvokedCallableTagValue($tokens); + break; + + case '@param-later-invoked-callable': + case '@phpstan-param-later-invoked-callable': + $tagValue = $this->parseParamLaterInvokedCallableTagValue($tokens); + break; + + case '@param-closure-this': + case '@phpstan-param-closure-this': + $tagValue = $this->parseParamClosureThisTagValue($tokens); + break; + + case '@pure-unless-callable-is-impure': + case '@phpstan-pure-unless-callable-is-impure': + $tagValue = $this->parsePureUnlessCallableIsImpureTagValue($tokens); + break; + + case '@var': + case '@phpstan-var': + case '@psalm-var': + case '@phan-var': + $tagValue = $this->parseVarTagValue($tokens); + break; + + case '@return': + case '@phpstan-return': + case '@psalm-return': + case '@phan-return': + case '@phan-real-return': + $tagValue = $this->parseReturnTagValue($tokens); + break; + + case '@throws': + case '@phpstan-throws': + $tagValue = $this->parseThrowsTagValue($tokens); + break; + + case '@mixin': + case '@phan-mixin': + $tagValue = $this->parseMixinTagValue($tokens); + break; + + case '@psalm-require-extends': + case '@phpstan-require-extends': + $tagValue = $this->parseRequireExtendsTagValue($tokens); + break; + + case '@psalm-require-implements': + case '@phpstan-require-implements': + $tagValue = $this->parseRequireImplementsTagValue($tokens); + break; + + case '@deprecated': + $tagValue = $this->parseDeprecatedTagValue($tokens); + break; + + case '@property': + case '@property-read': + case '@property-write': + case '@phpstan-property': + case '@phpstan-property-read': + case '@phpstan-property-write': + case '@psalm-property': + case '@psalm-property-read': + case '@psalm-property-write': + case '@phan-property': + case '@phan-property-read': + case '@phan-property-write': + $tagValue = $this->parsePropertyTagValue($tokens); + break; + + case '@method': + case '@phpstan-method': + case '@psalm-method': + case '@phan-method': + $tagValue = $this->parseMethodTagValue($tokens); + break; + + case '@template': + case '@phpstan-template': + case '@psalm-template': + case '@phan-template': + case '@template-covariant': + case '@phpstan-template-covariant': + case '@psalm-template-covariant': + case '@template-contravariant': + case '@phpstan-template-contravariant': + case '@psalm-template-contravariant': + $tagValue = $this->typeParser->parseTemplateTagValue( + $tokens, + function ($tokens) { + return $this->parseOptionalDescription($tokens); + } + ); + break; + + case '@extends': + case '@phpstan-extends': + case '@phan-extends': + case '@phan-inherits': + case '@template-extends': + $tagValue = $this->parseExtendsTagValue('@extends', $tokens); + break; + + case '@implements': + case '@phpstan-implements': + case '@template-implements': + $tagValue = $this->parseExtendsTagValue('@implements', $tokens); + break; + + case '@use': + case '@phpstan-use': + case '@template-use': + $tagValue = $this->parseExtendsTagValue('@use', $tokens); + break; + + case '@phpstan-type': + case '@psalm-type': + case '@phan-type': + $tagValue = $this->parseTypeAliasTagValue($tokens); + break; + + case '@phpstan-import-type': + case '@psalm-import-type': + $tagValue = $this->parseTypeAliasImportTagValue($tokens); + break; + + case '@phpstan-assert': + case '@phpstan-assert-if-true': + case '@phpstan-assert-if-false': + case '@psalm-assert': + case '@psalm-assert-if-true': + case '@psalm-assert-if-false': + case '@phan-assert': + case '@phan-assert-if-true': + case '@phan-assert-if-false': + $tagValue = $this->parseAssertTagValue($tokens); + break; + + case '@phpstan-this-out': + case '@phpstan-self-out': + case '@psalm-this-out': + case '@psalm-self-out': + $tagValue = $this->parseSelfOutTagValue($tokens); + break; + + case '@param-out': + case '@phpstan-param-out': + case '@psalm-param-out': + $tagValue = $this->parseParamOutTagValue($tokens); + break; + + default: + if ($this->parseDoctrineAnnotations) { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $tagValue = $this->parseDoctrineTagValue($tokens, $tag); + } else { + $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescriptionAfterDoctrineTag($tokens)); + } + break; + } + + $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens)); + + break; + } + + $tokens->dropSavePoint(); + + } catch (ParserException $e) { + $tokens->rollback(); + $tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens), $e); + } + + return $this->enrichWithAttributes($tokens, $tagValue, $startLine, $startIndex); + } + + + private function parseDoctrineTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + return new Doctrine\DoctrineTagValueNode( + $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineAnnotation($tag, $this->parseDoctrineArguments($tokens, false)), + $startLine, + $startIndex + ), + $this->parseOptionalDescriptionAfterDoctrineTag($tokens) + ); + } + + + /** + * @return list + */ + private function parseDoctrineArguments(TokenIterator $tokens, bool $deep): array + { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + return []; + } + + if (!$deep) { + $tokens->addEndOfLineToSkippedTokens(); + } + + $arguments = []; + + try { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); + + do { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { + break; + } + $arguments[] = $this->parseDoctrineArgument($tokens); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + } finally { + if (!$deep) { + $tokens->removeEndOfLineFromSkippedTokens(); + } + } + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + + return $arguments; + } + + + private function parseDoctrineArgument(TokenIterator $tokens): Doctrine\DoctrineArgument + { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), + $startLine, + $startIndex + ); + } + + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + try { + $tokens->pushSavePoint(); + $currentValue = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + $key = $this->enrichWithAttributes( + $tokens, + new IdentifierTypeNode($currentValue), + $startLine, + $startIndex + ); + $tokens->consumeTokenType(Lexer::TOKEN_EQUAL); + + $value = $this->parseDoctrineArgumentValue($tokens); + + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArgument($key, $value), + $startLine, + $startIndex + ); + } catch (ParserException $e) { + $tokens->rollback(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), + $startLine, + $startIndex + ); + } + } + + + /** + * @return DoctrineValueType + */ + private function parseDoctrineArgumentValue(TokenIterator $tokens) + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG)) { + $name = $tokens->currentTokenValue(); + $tokens->next(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineAnnotation($name, $this->parseDoctrineArguments($tokens, true)), + $startLine, + $startIndex + ); + } + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { + $items = []; + do { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + break; + } + $items[] = $this->parseDoctrineArrayItem($tokens); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArray($items), + $startLine, + $startIndex + ); + } + + $currentTokenValue = $tokens->currentTokenValue(); + $tokens->pushSavePoint(); // because of ConstFetchNode + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { + $identifier = $this->enrichWithAttributes( + $tokens, + new Ast\Type\IdentifierTypeNode($currentTokenValue), + $startLine, + $startIndex + ); + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + $tokens->dropSavePoint(); + return $identifier; + } + + $tokens->rollback(); // because of ConstFetchNode + } else { + $tokens->dropSavePoint(); // because of ConstFetchNode + } + + $currentTokenValue = $tokens->currentTokenValue(); + $currentTokenType = $tokens->currentTokenType(); + $currentTokenOffset = $tokens->currentTokenOffset(); + $currentTokenLine = $tokens->currentTokenLine(); + + try { + $constExpr = $this->doctrineConstantExprParser->parse($tokens, true); + if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + + return $constExpr; + } catch (LogicException $e) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + } + + + private function parseDoctrineArrayItem(TokenIterator $tokens): Doctrine\DoctrineArrayItem + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + try { + $tokens->pushSavePoint(); + + $key = $this->parseDoctrineArrayKey($tokens); + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) { + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COLON)) { + $tokens->consumeTokenType(Lexer::TOKEN_EQUAL); // will throw exception + } + } + + $value = $this->parseDoctrineArgumentValue($tokens); + + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArrayItem($key, $value), + $startLine, + $startIndex + ); + } catch (ParserException $e) { + $tokens->rollback(); + + return $this->enrichWithAttributes( + $tokens, + new Doctrine\DoctrineArrayItem(null, $this->parseDoctrineArgumentValue($tokens)), + $startLine, + $startIndex + ); + } + } + + + /** + * @return ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode + */ + private function parseDoctrineArrayKey(TokenIterator $tokens) + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { + $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue())); + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_ANNOTATION_STRING)) { + $key = new Ast\ConstExpr\DoctrineConstExprStringNode(Ast\ConstExpr\DoctrineConstExprStringNode::unescape($tokens->currentTokenValue())); + + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { + $value = $tokens->currentTokenValue(); + $tokens->next(); + $key = $this->doctrineConstantExprParser->parseDoctrineString($value, $tokens); + + } else { + $currentTokenValue = $tokens->currentTokenValue(); + $tokens->pushSavePoint(); // because of ConstFetchNode + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { + $tokens->dropSavePoint(); + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_IDENTIFIER, + null, + $tokens->currentTokenLine() + ); + } + + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new IdentifierTypeNode($currentTokenValue), + $startLine, + $startIndex + ); + } + + $tokens->rollback(); + $constExpr = $this->doctrineConstantExprParser->parse($tokens, true); + if (!$constExpr instanceof Ast\ConstExpr\ConstFetchNode) { + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_IDENTIFIER, + null, + $tokens->currentTokenLine() + ); + } + + return $constExpr; + } + + return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex); + } + + + /** + * @return Ast\PhpDoc\ParamTagValueNode|Ast\PhpDoc\TypelessParamTagValueNode + */ + private function parseParamTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode + { + if ( + $tokens->isCurrentTokenType(Lexer::TOKEN_REFERENCE, Lexer::TOKEN_VARIADIC, Lexer::TOKEN_VARIABLE) + ) { + $type = null; + } else { + $type = $this->typeParser->parse($tokens); + } + + $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE); + $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + + if ($type !== null) { + return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description, $isReference); + } + + return new Ast\PhpDoc\TypelessParamTagValueNode($isVariadic, $parameterName, $description, $isReference); + } + + + private function parseParamImmediatelyInvokedCallableTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode + { + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + + return new Ast\PhpDoc\ParamImmediatelyInvokedCallableTagValueNode($parameterName, $description); + } + + + private function parseParamLaterInvokedCallableTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode + { + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + + return new Ast\PhpDoc\ParamLaterInvokedCallableTagValueNode($parameterName, $description); + } + + + private function parseParamClosureThisTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamClosureThisTagValueNode + { + $type = $this->typeParser->parse($tokens); + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + + return new Ast\PhpDoc\ParamClosureThisTagValueNode($type, $parameterName, $description); + } + + private function parsePureUnlessCallableIsImpureTagValue(TokenIterator $tokens): Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode + { + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + + return new Ast\PhpDoc\PureUnlessCallableIsImpureTagValueNode($parameterName, $description); + } + + private function parseVarTagValue(TokenIterator $tokens): Ast\PhpDoc\VarTagValueNode + { + $type = $this->typeParser->parse($tokens); + $variableName = $this->parseOptionalVariableName($tokens); + $description = $this->parseOptionalDescription($tokens, $variableName === ''); + return new Ast\PhpDoc\VarTagValueNode($type, $variableName, $description); + } + + + private function parseReturnTagValue(TokenIterator $tokens): Ast\PhpDoc\ReturnTagValueNode + { + $type = $this->typeParser->parse($tokens); + $description = $this->parseOptionalDescription($tokens, true); + return new Ast\PhpDoc\ReturnTagValueNode($type, $description); + } + + + private function parseThrowsTagValue(TokenIterator $tokens): Ast\PhpDoc\ThrowsTagValueNode + { + $type = $this->typeParser->parse($tokens); + $description = $this->parseOptionalDescription($tokens, true); + return new Ast\PhpDoc\ThrowsTagValueNode($type, $description); + } + + private function parseMixinTagValue(TokenIterator $tokens): Ast\PhpDoc\MixinTagValueNode + { + $type = $this->typeParser->parse($tokens); + $description = $this->parseOptionalDescription($tokens, true); + return new Ast\PhpDoc\MixinTagValueNode($type, $description); + } + + private function parseRequireExtendsTagValue(TokenIterator $tokens): Ast\PhpDoc\RequireExtendsTagValueNode + { + $type = $this->typeParser->parse($tokens); + $description = $this->parseOptionalDescription($tokens, true); + return new Ast\PhpDoc\RequireExtendsTagValueNode($type, $description); + } + + private function parseRequireImplementsTagValue(TokenIterator $tokens): Ast\PhpDoc\RequireImplementsTagValueNode + { + $type = $this->typeParser->parse($tokens); + $description = $this->parseOptionalDescription($tokens, true); + return new Ast\PhpDoc\RequireImplementsTagValueNode($type, $description); + } + + private function parseDeprecatedTagValue(TokenIterator $tokens): Ast\PhpDoc\DeprecatedTagValueNode + { + $description = $this->parseOptionalDescription($tokens); + return new Ast\PhpDoc\DeprecatedTagValueNode($description); + } + + + private function parsePropertyTagValue(TokenIterator $tokens): Ast\PhpDoc\PropertyTagValueNode + { + $type = $this->typeParser->parse($tokens); + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + return new Ast\PhpDoc\PropertyTagValueNode($type, $parameterName, $description); + } + + + private function parseMethodTagValue(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueNode + { + $staticKeywordOrReturnTypeOrMethodName = $this->typeParser->parse($tokens); + + if ($staticKeywordOrReturnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode && $staticKeywordOrReturnTypeOrMethodName->name === 'static') { + $isStatic = true; + $returnTypeOrMethodName = $this->typeParser->parse($tokens); + + } else { + $isStatic = false; + $returnTypeOrMethodName = $staticKeywordOrReturnTypeOrMethodName; + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { + $returnType = $returnTypeOrMethodName; + $methodName = $tokens->currentTokenValue(); + $tokens->next(); + + } elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) { + $returnType = $isStatic ? $staticKeywordOrReturnTypeOrMethodName : null; + $methodName = $returnTypeOrMethodName->name; + $isStatic = false; + + } else { + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); // will throw exception + exit; + } + + $templateTypes = []; + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { + do { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $templateTypes[] = $this->enrichWithAttributes( + $tokens, + $this->typeParser->parseTemplateTagValue($tokens), + $startLine, + $startIndex + ); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); + } + + $parameters = []; + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { + $parameters[] = $this->parseMethodTagValueParameter($tokens); + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { + $parameters[] = $this->parseMethodTagValueParameter($tokens); + } + } + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + + $description = $this->parseOptionalDescription($tokens); + return new Ast\PhpDoc\MethodTagValueNode($isStatic, $returnType, $methodName, $parameters, $description, $templateTypes); + } + + private function parseMethodTagValueParameter(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueParameterNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + switch ($tokens->currentTokenType()) { + case Lexer::TOKEN_IDENTIFIER: + case Lexer::TOKEN_OPEN_PARENTHESES: + case Lexer::TOKEN_NULLABLE: + $parameterType = $this->typeParser->parse($tokens); + break; + + default: + $parameterType = null; + } + + $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE); + $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); + + $parameterName = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) { + $defaultValue = $this->constantExprParser->parse($tokens); + + } else { + $defaultValue = null; + } + + return $this->enrichWithAttributes( + $tokens, + new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue), + $startLine, + $startIndex + ); + } + + private function parseExtendsTagValue(string $tagName, TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $baseType = new IdentifierTypeNode($tokens->currentTokenValue()); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + $type = $this->typeParser->parseGeneric( + $tokens, + $this->typeParser->enrichWithAttributes($tokens, $baseType, $startLine, $startIndex) + ); + + $description = $this->parseOptionalDescription($tokens); + + switch ($tagName) { + case '@extends': + return new Ast\PhpDoc\ExtendsTagValueNode($type, $description); + case '@implements': + return new Ast\PhpDoc\ImplementsTagValueNode($type, $description); + case '@use': + return new Ast\PhpDoc\UsesTagValueNode($type, $description); + } + + throw new ShouldNotHappenException(); + } + + private function parseTypeAliasTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeAliasTagValueNode + { + $alias = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + // support phan-type/psalm-type syntax + $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); + + if ($this->preserveTypeAliasesWithInvalidTypes) { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + try { + $type = $this->typeParser->parse($tokens); + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + throw new ParserException( + $tokens->currentTokenValue(), + $tokens->currentTokenType(), + $tokens->currentTokenOffset(), + Lexer::TOKEN_PHPDOC_EOL, + null, + $tokens->currentTokenLine() + ); + } + } + + return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type); + } catch (ParserException $e) { + $this->parseOptionalDescription($tokens); + return new Ast\PhpDoc\TypeAliasTagValueNode( + $alias, + $this->enrichWithAttributes($tokens, new Ast\Type\InvalidTypeNode($e), $startLine, $startIndex) + ); + } + } + + $type = $this->typeParser->parse($tokens); + + return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type); + } + + private function parseTypeAliasImportTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeAliasImportTagValueNode + { + $importedAlias = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + $tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'from'); + + $identifierStartLine = $tokens->currentTokenLine(); + $identifierStartIndex = $tokens->currentTokenIndex(); + $importedFrom = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + $importedFromType = $this->enrichWithAttributes( + $tokens, + new IdentifierTypeNode($importedFrom), + $identifierStartLine, + $identifierStartIndex + ); + + $importedAs = null; + if ($tokens->tryConsumeTokenValue('as')) { + $importedAs = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + } + + return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, $importedFromType, $importedAs); + } + + /** + * @return Ast\PhpDoc\AssertTagValueNode|Ast\PhpDoc\AssertTagPropertyValueNode|Ast\PhpDoc\AssertTagMethodValueNode + */ + private function parseAssertTagValue(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagValueNode + { + $isNegated = $tokens->tryConsumeTokenType(Lexer::TOKEN_NEGATED); + $isEquality = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); + $type = $this->typeParser->parse($tokens); + $parameter = $this->parseAssertParameter($tokens); + $description = $this->parseOptionalDescription($tokens); + + if (array_key_exists('method', $parameter)) { + return new Ast\PhpDoc\AssertTagMethodValueNode($type, $parameter['parameter'], $parameter['method'], $isNegated, $description, $isEquality); + } elseif (array_key_exists('property', $parameter)) { + return new Ast\PhpDoc\AssertTagPropertyValueNode($type, $parameter['parameter'], $parameter['property'], $isNegated, $description, $isEquality); + } + + return new Ast\PhpDoc\AssertTagValueNode($type, $parameter['parameter'], $isNegated, $description, $isEquality); + } + + /** + * @return array{parameter: string}|array{parameter: string, property: string}|array{parameter: string, method: string} + */ + private function parseAssertParameter(TokenIterator $tokens): array + { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) { + $parameter = '$this'; + $tokens->next(); + } else { + $parameter = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_ARROW)) { + $tokens->consumeTokenType(Lexer::TOKEN_ARROW); + + $propertyOrMethod = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + + return ['parameter' => $parameter, 'method' => $propertyOrMethod]; + } + + return ['parameter' => $parameter, 'property' => $propertyOrMethod]; + } + + return ['parameter' => $parameter]; + } + + private function parseSelfOutTagValue(TokenIterator $tokens): Ast\PhpDoc\SelfOutTagValueNode + { + $type = $this->typeParser->parse($tokens); + $description = $this->parseOptionalDescription($tokens); + + return new Ast\PhpDoc\SelfOutTagValueNode($type, $description); + } + + private function parseParamOutTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamOutTagValueNode + { + $type = $this->typeParser->parse($tokens); + $parameterName = $this->parseRequiredVariableName($tokens); + $description = $this->parseOptionalDescription($tokens); + + return new Ast\PhpDoc\ParamOutTagValueNode($type, $parameterName, $description); + } + + private function parseOptionalVariableName(TokenIterator $tokens): string + { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) { + $parameterName = $tokens->currentTokenValue(); + $tokens->next(); + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) { + $parameterName = '$this'; + $tokens->next(); + + } else { + $parameterName = ''; + } + + return $parameterName; + } + + + private function parseRequiredVariableName(TokenIterator $tokens): string + { + $parameterName = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); + + return $parameterName; + } + + private function parseOptionalDescription(TokenIterator $tokens, bool $limitStartToken = false): string + { + if ($limitStartToken) { + foreach (self::DISALLOWED_DESCRIPTION_START_TOKENS as $disallowedStartToken) { + if (!$tokens->isCurrentTokenType($disallowedStartToken)) { + continue; + } + + $tokens->consumeTokenType(Lexer::TOKEN_OTHER); // will throw exception + } + + if ( + $this->requireWhitespaceBeforeDescription + && !$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END) + && !$tokens->isPrecededByHorizontalWhitespace() + ) { + $tokens->consumeTokenType(Lexer::TOKEN_HORIZONTAL_WS); // will throw exception + } + } + + return $this->parseText($tokens)->text; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php new file mode 100644 index 000000000..a3bbeeddb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php @@ -0,0 +1,100 @@ + '\\', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ]; + + public static function unescapeString(string $string): string + { + $quote = $string[0]; + + if ($quote === '\'') { + return str_replace( + ['\\\\', '\\\''], + ['\\', '\''], + substr($string, 1, -1) + ); + } + + return self::parseEscapeSequences(substr($string, 1, -1), '"'); + } + + /** + * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130 + */ + private static function parseEscapeSequences(string $str, string $quote): string + { + $str = str_replace('\\' . $quote, $quote, $str); + + return preg_replace_callback( + '~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\{([0-9a-fA-F]+)\})~', + static function ($matches) { + $str = $matches[1]; + + if (isset(self::REPLACEMENTS[$str])) { + return self::REPLACEMENTS[$str]; + } + if ($str[0] === 'x' || $str[0] === 'X') { + return chr((int) hexdec(substr($str, 1))); + } + if ($str[0] === 'u') { + if (!isset($matches[2])) { + throw new ShouldNotHappenException(); + } + return self::codePointToUtf8((int) hexdec($matches[2])); + } + + return chr((int) octdec($str)); + }, + $str + ); + } + + /** + * Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154 + */ + private static function codePointToUtf8(int $num): string + { + if ($num <= 0x7F) { + return chr($num); + } + if ($num <= 0x7FF) { + return chr(($num >> 6) + 0xC0) + . chr(($num & 0x3F) + 0x80); + } + if ($num <= 0xFFFF) { + return chr(($num >> 12) + 0xE0) + . chr((($num >> 6) & 0x3F) + 0x80) + . chr(($num & 0x3F) + 0x80); + } + if ($num <= 0x1FFFFF) { + return chr(($num >> 18) + 0xF0) + . chr((($num >> 12) & 0x3F) + 0x80) + . chr((($num >> 6) & 0x3F) + 0x80) + . chr(($num & 0x3F) + 0x80); + } + + // Invalid UTF-8 codepoint escape sequence: Codepoint too large + return "\xef\xbf\xbd"; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php new file mode 100644 index 000000000..9be7593d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php @@ -0,0 +1,383 @@ + */ + private $tokens; + + /** @var int */ + private $index; + + /** @var int[] */ + private $savePoints = []; + + /** @var list */ + private $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; + + /** @var string|null */ + private $newline = null; + + /** + * @param list $tokens + */ + public function __construct(array $tokens, int $index = 0) + { + $this->tokens = $tokens; + $this->index = $index; + + $this->skipIrrelevantTokens(); + } + + + /** + * @return list + */ + public function getTokens(): array + { + return $this->tokens; + } + + + public function getContentBetween(int $startPos, int $endPos): string + { + if ($startPos < 0 || $endPos > count($this->tokens)) { + throw new LogicException(); + } + + $content = ''; + for ($i = $startPos; $i < $endPos; $i++) { + $content .= $this->tokens[$i][Lexer::VALUE_OFFSET]; + } + + return $content; + } + + + public function getTokenCount(): int + { + return count($this->tokens); + } + + + public function currentTokenValue(): string + { + return $this->tokens[$this->index][Lexer::VALUE_OFFSET]; + } + + + public function currentTokenType(): int + { + return $this->tokens[$this->index][Lexer::TYPE_OFFSET]; + } + + + public function currentTokenOffset(): int + { + $offset = 0; + for ($i = 0; $i < $this->index; $i++) { + $offset += strlen($this->tokens[$i][Lexer::VALUE_OFFSET]); + } + + return $offset; + } + + + public function currentTokenLine(): int + { + return $this->tokens[$this->index][Lexer::LINE_OFFSET]; + } + + + public function currentTokenIndex(): int + { + return $this->index; + } + + + public function endIndexOfLastRelevantToken(): int + { + $endIndex = $this->currentTokenIndex(); + $endIndex--; + while (in_array($this->tokens[$endIndex][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, true)) { + if (!isset($this->tokens[$endIndex - 1])) { + break; + } + $endIndex--; + } + + return $endIndex; + } + + + public function isCurrentTokenValue(string $tokenValue): bool + { + return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue; + } + + + public function isCurrentTokenType(int ...$tokenType): bool + { + return in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, true); + } + + + public function isPrecededByHorizontalWhitespace(): bool + { + return ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS; + } + + + /** + * @throws ParserException + */ + public function consumeTokenType(int $tokenType): void + { + if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) { + $this->throwError($tokenType); + } + + if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) { + if ($this->newline === null) { + $this->detectNewline(); + } + } + + $this->index++; + $this->skipIrrelevantTokens(); + } + + + /** + * @throws ParserException + */ + public function consumeTokenValue(int $tokenType, string $tokenValue): void + { + if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType || $this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) { + $this->throwError($tokenType, $tokenValue); + } + + $this->index++; + $this->skipIrrelevantTokens(); + } + + + /** @phpstan-impure */ + public function tryConsumeTokenValue(string $tokenValue): bool + { + if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) { + return false; + } + + $this->index++; + $this->skipIrrelevantTokens(); + + return true; + } + + + /** @phpstan-impure */ + public function tryConsumeTokenType(int $tokenType): bool + { + if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) { + return false; + } + + if ($tokenType === Lexer::TOKEN_PHPDOC_EOL) { + if ($this->newline === null) { + $this->detectNewline(); + } + } + + $this->index++; + $this->skipIrrelevantTokens(); + + return true; + } + + + private function detectNewline(): void + { + $value = $this->currentTokenValue(); + if (substr($value, 0, 2) === "\r\n") { + $this->newline = "\r\n"; + } elseif (substr($value, 0, 1) === "\n") { + $this->newline = "\n"; + } + } + + + public function getSkippedHorizontalWhiteSpaceIfAny(): string + { + if ($this->index > 0 && $this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) { + return $this->tokens[$this->index - 1][Lexer::VALUE_OFFSET]; + } + + return ''; + } + + + /** @phpstan-impure */ + public function joinUntil(int ...$tokenType): string + { + $s = ''; + while (!in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, true)) { + $s .= $this->tokens[$this->index++][Lexer::VALUE_OFFSET]; + } + return $s; + } + + + public function next(): void + { + $this->index++; + $this->skipIrrelevantTokens(); + } + + + private function skipIrrelevantTokens(): void + { + if (!isset($this->tokens[$this->index])) { + return; + } + + while (in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, true)) { + if (!isset($this->tokens[$this->index + 1])) { + break; + } + $this->index++; + } + } + + + public function addEndOfLineToSkippedTokens(): void + { + $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL]; + } + + + public function removeEndOfLineFromSkippedTokens(): void + { + $this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS]; + } + + /** @phpstan-impure */ + public function forwardToTheEnd(): void + { + $lastToken = count($this->tokens) - 1; + $this->index = $lastToken; + } + + + public function pushSavePoint(): void + { + $this->savePoints[] = $this->index; + } + + + public function dropSavePoint(): void + { + array_pop($this->savePoints); + } + + + public function rollback(): void + { + $index = array_pop($this->savePoints); + assert($index !== null); + $this->index = $index; + } + + + /** + * @throws ParserException + */ + private function throwError(int $expectedTokenType, ?string $expectedTokenValue = null): void + { + throw new ParserException( + $this->currentTokenValue(), + $this->currentTokenType(), + $this->currentTokenOffset(), + $expectedTokenType, + $expectedTokenValue, + $this->currentTokenLine() + ); + } + + /** + * Check whether the position is directly preceded by a certain token type. + * + * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped + */ + public function hasTokenImmediatelyBefore(int $pos, int $expectedTokenType): bool + { + $tokens = $this->tokens; + $pos--; + for (; $pos >= 0; $pos--) { + $token = $tokens[$pos]; + $type = $token[Lexer::TYPE_OFFSET]; + if ($type === $expectedTokenType) { + return true; + } + if (!in_array($type, [ + Lexer::TOKEN_HORIZONTAL_WS, + Lexer::TOKEN_PHPDOC_EOL, + ], true)) { + break; + } + } + return false; + } + + /** + * Check whether the position is directly followed by a certain token type. + * + * During this check TOKEN_HORIZONTAL_WS and TOKEN_PHPDOC_EOL are skipped + */ + public function hasTokenImmediatelyAfter(int $pos, int $expectedTokenType): bool + { + $tokens = $this->tokens; + $pos++; + for ($c = count($tokens); $pos < $c; $pos++) { + $token = $tokens[$pos]; + $type = $token[Lexer::TYPE_OFFSET]; + if ($type === $expectedTokenType) { + return true; + } + if (!in_array($type, [ + Lexer::TOKEN_HORIZONTAL_WS, + Lexer::TOKEN_PHPDOC_EOL, + ], true)) { + break; + } + } + + return false; + } + + public function getDetectedNewline(): ?string + { + return $this->newline; + } + + /** + * Whether the given position is immediately surrounded by parenthesis. + */ + public function hasParentheses(int $startPos, int $endPos): bool + { + return $this->hasTokenImmediatelyBefore($startPos, Lexer::TOKEN_OPEN_PARENTHESES) + && $this->hasTokenImmediatelyAfter($endPos, Lexer::TOKEN_CLOSE_PARENTHESES); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php new file mode 100644 index 000000000..982eba7d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php @@ -0,0 +1,1110 @@ +constExprParser = $constExprParser; + $this->quoteAwareConstExprString = $quoteAwareConstExprString; + $this->useLinesAttributes = $usedAttributes['lines'] ?? false; + $this->useIndexAttributes = $usedAttributes['indexes'] ?? false; + } + + /** @phpstan-impure */ + public function parse(TokenIterator $tokens): Ast\Type\TypeNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) { + $type = $this->parseNullable($tokens); + + } else { + $type = $this->parseAtomic($tokens); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) { + $type = $this->parseUnion($tokens, $type); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) { + $type = $this->parseIntersection($tokens, $type); + } + } + + return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); + } + + /** + * @internal + * @template T of Ast\Node + * @param T $type + * @return T + */ + public function enrichWithAttributes(TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex): Ast\Node + { + if ($this->useLinesAttributes) { + $type->setAttribute(Ast\Attribute::START_LINE, $startLine); + $type->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine()); + } + + if ($this->useIndexAttributes) { + $type->setAttribute(Ast\Attribute::START_INDEX, $startIndex); + $type->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken()); + } + + return $type; + } + + /** @phpstan-impure */ + private function subParse(TokenIterator $tokens): Ast\Type\TypeNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) { + $type = $this->parseNullable($tokens); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) { + $type = $this->parseConditionalForParameter($tokens, $tokens->currentTokenValue()); + + } else { + $type = $this->parseAtomic($tokens); + + if ($tokens->isCurrentTokenValue('is')) { + $type = $this->parseConditional($tokens, $type); + } else { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) { + $type = $this->subParseUnion($tokens, $type); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) { + $type = $this->subParseIntersection($tokens, $type); + } + } + } + + return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); + } + + + /** @phpstan-impure */ + private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $type = $this->subParse($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + } + + return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); + } + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) { + $type = $this->enrichWithAttributes($tokens, new Ast\Type\ThisTypeNode(), $startLine, $startIndex); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + } + + return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); + } + + $currentTokenValue = $tokens->currentTokenValue(); + $tokens->pushSavePoint(); // because of ConstFetchNode + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { + $type = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex); + + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + $tokens->dropSavePoint(); // because of ConstFetchNode + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { + $tokens->pushSavePoint(); + + $isHtml = $this->isHtml($tokens); + $tokens->rollback(); + if ($isHtml) { + return $type; + } + + $origType = $type; + $type = $this->tryParseCallable($tokens, $type, true); + if ($type === $origType) { + $type = $this->parseGeneric($tokens, $type); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + } + } + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $type = $this->tryParseCallable($tokens, $type, false); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + + } elseif (in_array($type->name, [ + Ast\Type\ArrayShapeNode::KIND_ARRAY, + Ast\Type\ArrayShapeNode::KIND_LIST, + Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_ARRAY, + Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_LIST, + 'object', + ], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) { + if ($type->name === 'object') { + $type = $this->parseObjectShape($tokens); + } else { + $type = $this->parseArrayShape($tokens, $type, $type->name); + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess( + $tokens, + $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex) + ); + } + } + + return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); + } else { + $tokens->rollback(); // because of ConstFetchNode + } + } else { + $tokens->dropSavePoint(); // because of ConstFetchNode + } + + $currentTokenValue = $tokens->currentTokenValue(); + $currentTokenType = $tokens->currentTokenType(); + $currentTokenOffset = $tokens->currentTokenOffset(); + $currentTokenLine = $tokens->currentTokenLine(); + + if ($this->constExprParser === null) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + + try { + $constExpr = $this->constExprParser->parse($tokens, true); + if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + + $type = $this->enrichWithAttributes( + $tokens, + new Ast\Type\ConstTypeNode($constExpr), + $startLine, + $startIndex + ); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + } + + return $type; + } catch (LogicException $e) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + } + + + /** @phpstan-impure */ + private function parseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode + { + $types = [$type]; + + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) { + $types[] = $this->parseAtomic($tokens); + } + + return new Ast\Type\UnionTypeNode($types); + } + + + /** @phpstan-impure */ + private function subParseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode + { + $types = [$type]; + + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $types[] = $this->parseAtomic($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + + return new Ast\Type\UnionTypeNode($types); + } + + + /** @phpstan-impure */ + private function parseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode + { + $types = [$type]; + + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) { + $types[] = $this->parseAtomic($tokens); + } + + return new Ast\Type\IntersectionTypeNode($types); + } + + + /** @phpstan-impure */ + private function subParseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode + { + $types = [$type]; + + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $types[] = $this->parseAtomic($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + + return new Ast\Type\IntersectionTypeNode($types); + } + + + /** @phpstan-impure */ + private function parseConditional(TokenIterator $tokens, Ast\Type\TypeNode $subjectType): Ast\Type\TypeNode + { + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + $negated = false; + if ($tokens->isCurrentTokenValue('not')) { + $negated = true; + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + } + + $targetType = $this->parse($tokens); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $ifType = $this->parse($tokens); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokens->consumeTokenType(Lexer::TOKEN_COLON); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $elseType = $this->subParse($tokens); + + return new Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated); + } + + /** @phpstan-impure */ + private function parseConditionalForParameter(TokenIterator $tokens, string $parameterName): Ast\Type\TypeNode + { + $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); + $tokens->consumeTokenValue(Lexer::TOKEN_IDENTIFIER, 'is'); + + $negated = false; + if ($tokens->isCurrentTokenValue('not')) { + $negated = true; + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + } + + $targetType = $this->parse($tokens); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $ifType = $this->parse($tokens); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokens->consumeTokenType(Lexer::TOKEN_COLON); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $elseType = $this->subParse($tokens); + + return new Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated); + } + + + /** @phpstan-impure */ + private function parseNullable(TokenIterator $tokens): Ast\Type\TypeNode + { + $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE); + + $type = $this->parseAtomic($tokens); + + return new Ast\Type\NullableTypeNode($type); + } + + /** @phpstan-impure */ + public function isHtml(TokenIterator $tokens): bool + { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); + + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) { + return false; + } + + $htmlTagName = $tokens->currentTokenValue(); + + $tokens->next(); + + if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) { + return false; + } + + $endTag = ''; + $endTagSearchOffset = - strlen($endTag); + + while (!$tokens->isCurrentTokenType(Lexer::TOKEN_END)) { + if ( + ( + $tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET) + && strpos($tokens->currentTokenValue(), '/' . $htmlTagName . '>') !== false + ) + || substr_compare($tokens->currentTokenValue(), $endTag, $endTagSearchOffset) === 0 + ) { + return true; + } + + $tokens->next(); + } + + return false; + } + + /** @phpstan-impure */ + public function parseGeneric(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $baseType): Ast\Type\GenericTypeNode + { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); + + $startLine = $baseType->getAttribute(Ast\Attribute::START_LINE); + $startIndex = $baseType->getAttribute(Ast\Attribute::START_INDEX); + $genericTypes = []; + $variances = []; + + $isFirst = true; + while ($isFirst || $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + // trailing comma case + if (!$isFirst && $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) { + break; + } + $isFirst = false; + + [$genericTypes[], $variances[]] = $this->parseGenericTypeArgument($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + + $type = new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances); + if ($startLine !== null && $startIndex !== null) { + $type = $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex); + } + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); + + return $type; + } + + + /** + * @phpstan-impure + * @return array{Ast\Type\TypeNode, Ast\Type\GenericTypeNode::VARIANCE_*} + */ + public function parseGenericTypeArgument(TokenIterator $tokens): array + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) { + return [ + $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode('mixed'), $startLine, $startIndex), + Ast\Type\GenericTypeNode::VARIANCE_BIVARIANT, + ]; + } + + if ($tokens->tryConsumeTokenValue('contravariant')) { + $variance = Ast\Type\GenericTypeNode::VARIANCE_CONTRAVARIANT; + } elseif ($tokens->tryConsumeTokenValue('covariant')) { + $variance = Ast\Type\GenericTypeNode::VARIANCE_COVARIANT; + } else { + $variance = Ast\Type\GenericTypeNode::VARIANCE_INVARIANT; + } + + $type = $this->parse($tokens); + return [$type, $variance]; + } + + /** + * @throws ParserException + * @param ?callable(TokenIterator): string $parseDescription + */ + public function parseTemplateTagValue( + TokenIterator $tokens, + ?callable $parseDescription = null + ): TemplateTagValueNode + { + $name = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + + $upperBound = $lowerBound = null; + + if ($tokens->tryConsumeTokenValue('of') || $tokens->tryConsumeTokenValue('as')) { + $upperBound = $this->parse($tokens); + } + + if ($tokens->tryConsumeTokenValue('super')) { + $lowerBound = $this->parse($tokens); + } + + if ($tokens->tryConsumeTokenValue('=')) { + $default = $this->parse($tokens); + } else { + $default = null; + } + + if ($parseDescription !== null) { + $description = $parseDescription($tokens); + } else { + $description = ''; + } + + if ($name === '') { + throw new LogicException('Template tag name cannot be empty.'); + } + + return new Ast\PhpDoc\TemplateTagValueNode($name, $upperBound, $description, $default, $lowerBound); + } + + + /** @phpstan-impure */ + private function parseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier, bool $hasTemplate): Ast\Type\TypeNode + { + $templates = $hasTemplate + ? $this->parseCallableTemplates($tokens) + : []; + + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $parameters = []; + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { + $parameters[] = $this->parseCallableParameter($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { + break; + } + $parameters[] = $this->parseCallableParameter($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + } + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + $tokens->consumeTokenType(Lexer::TOKEN_COLON); + + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $returnType = $this->enrichWithAttributes($tokens, $this->parseCallableReturnType($tokens), $startLine, $startIndex); + + return new Ast\Type\CallableTypeNode($identifier, $parameters, $returnType, $templates); + } + + + /** + * @return Ast\PhpDoc\TemplateTagValueNode[] + * + * @phpstan-impure + */ + private function parseCallableTemplates(TokenIterator $tokens): array + { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); + + $templates = []; + + $isFirst = true; + while ($isFirst || $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + // trailing comma case + if (!$isFirst && $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) { + break; + } + $isFirst = false; + + $templates[] = $this->parseCallableTemplateArgument($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); + + return $templates; + } + + + private function parseCallableTemplateArgument(TokenIterator $tokens): Ast\PhpDoc\TemplateTagValueNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + return $this->enrichWithAttributes( + $tokens, + $this->parseTemplateTagValue($tokens), + $startLine, + $startIndex + ); + } + + + /** @phpstan-impure */ + private function parseCallableParameter(TokenIterator $tokens): Ast\Type\CallableTypeParameterNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + $type = $this->parse($tokens); + $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE); + $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) { + $parameterName = $tokens->currentTokenValue(); + $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE); + + } else { + $parameterName = ''; + } + + $isOptional = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL); + return $this->enrichWithAttributes( + $tokens, + new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional), + $startLine, + $startIndex + ); + } + + + /** @phpstan-impure */ + private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) { + return $this->parseNullable($tokens); + + } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { + $type = $this->subParse($tokens); + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + } + + return $type; + } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) { + $type = new Ast\Type\ThisTypeNode(); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + )); + } + + return $type; + } else { + $currentTokenValue = $tokens->currentTokenValue(); + $tokens->pushSavePoint(); // because of ConstFetchNode + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) { + $type = new Ast\Type\IdentifierTypeNode($currentTokenValue); + + if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) { + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { + $type = $this->parseGeneric( + $tokens, + $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + ) + ); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + )); + } + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + )); + + } elseif (in_array($type->name, [ + Ast\Type\ArrayShapeNode::KIND_ARRAY, + Ast\Type\ArrayShapeNode::KIND_LIST, + Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_ARRAY, + Ast\Type\ArrayShapeNode::KIND_NON_EMPTY_LIST, + 'object', + ], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) { + if ($type->name === 'object') { + $type = $this->parseObjectShape($tokens); + } else { + $type = $this->parseArrayShape($tokens, $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + ), $type->name); + } + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + )); + } + } + + return $type; + } else { + $tokens->rollback(); // because of ConstFetchNode + } + } else { + $tokens->dropSavePoint(); // because of ConstFetchNode + } + } + + $currentTokenValue = $tokens->currentTokenValue(); + $currentTokenType = $tokens->currentTokenType(); + $currentTokenOffset = $tokens->currentTokenOffset(); + $currentTokenLine = $tokens->currentTokenLine(); + + if ($this->constExprParser === null) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + + try { + $constExpr = $this->constExprParser->parse($tokens, true); + if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + + $type = $this->enrichWithAttributes( + $tokens, + new Ast\Type\ConstTypeNode($constExpr), + $startLine, + $startIndex + ); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $type = $this->tryParseArrayOrOffsetAccess($tokens, $type); + } + + return $type; + } catch (LogicException $e) { + throw new ParserException( + $currentTokenValue, + $currentTokenType, + $currentTokenOffset, + Lexer::TOKEN_IDENTIFIER, + null, + $currentTokenLine + ); + } + } + + + /** @phpstan-impure */ + private function tryParseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier, bool $hasTemplate): Ast\Type\TypeNode + { + try { + $tokens->pushSavePoint(); + $type = $this->parseCallable($tokens, $identifier, $hasTemplate); + $tokens->dropSavePoint(); + + } catch (ParserException $e) { + $tokens->rollback(); + $type = $identifier; + } + + return $type; + } + + + /** @phpstan-impure */ + private function tryParseArrayOrOffsetAccess(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode + { + $startLine = $type->getAttribute(Ast\Attribute::START_LINE); + $startIndex = $type->getAttribute(Ast\Attribute::START_INDEX); + try { + while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { + $tokens->pushSavePoint(); + + $canBeOffsetAccessType = !$tokens->isPrecededByHorizontalWhitespace(); + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET); + + if ($canBeOffsetAccessType && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET)) { + $offset = $this->parse($tokens); + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET); + $tokens->dropSavePoint(); + $type = new Ast\Type\OffsetAccessTypeNode($type, $offset); + + if ($startLine !== null && $startIndex !== null) { + $type = $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + ); + } + } else { + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET); + $tokens->dropSavePoint(); + $type = new Ast\Type\ArrayTypeNode($type); + + if ($startLine !== null && $startIndex !== null) { + $type = $this->enrichWithAttributes( + $tokens, + $type, + $startLine, + $startIndex + ); + } + } + } + + } catch (ParserException $e) { + $tokens->rollback(); + } + + return $type; + } + + + /** + * @phpstan-impure + * @param Ast\Type\ArrayShapeNode::KIND_* $kind + */ + private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type, string $kind): Ast\Type\ArrayShapeNode + { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET); + + $items = []; + $sealed = true; + $unsealedType = null; + + do { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + return new Ast\Type\ArrayShapeNode($items, true, $kind); + } + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC)) { + $sealed = false; + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) { + if ($kind === Ast\Type\ArrayShapeNode::KIND_ARRAY) { + $unsealedType = $this->parseArrayShapeUnsealedType($tokens); + } else { + $unsealedType = $this->parseListShapeUnsealedType($tokens); + } + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + + $tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA); + break; + } + + $items[] = $this->parseArrayShapeItem($tokens); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); + + return new Ast\Type\ArrayShapeNode($items, $sealed, $kind, $unsealedType); + } + + + /** @phpstan-impure */ + private function parseArrayShapeItem(TokenIterator $tokens): Ast\Type\ArrayShapeItemNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + try { + $tokens->pushSavePoint(); + $key = $this->parseArrayShapeKey($tokens); + $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE); + $tokens->consumeTokenType(Lexer::TOKEN_COLON); + $value = $this->parse($tokens); + $tokens->dropSavePoint(); + + return $this->enrichWithAttributes( + $tokens, + new Ast\Type\ArrayShapeItemNode($key, $optional, $value), + $startLine, + $startIndex + ); + } catch (ParserException $e) { + $tokens->rollback(); + $value = $this->parse($tokens); + + return $this->enrichWithAttributes( + $tokens, + new Ast\Type\ArrayShapeItemNode(null, false, $value), + $startLine, + $startIndex + ); + } + } + + /** + * @phpstan-impure + * @return Ast\ConstExpr\ConstExprIntegerNode|Ast\ConstExpr\ConstExprStringNode|Ast\Type\IdentifierTypeNode + */ + private function parseArrayShapeKey(TokenIterator $tokens) + { + $startIndex = $tokens->currentTokenIndex(); + $startLine = $tokens->currentTokenLine(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) { + $key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue())); + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { + if ($this->quoteAwareConstExprString) { + $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED); + } else { + $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'")); + } + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { + if ($this->quoteAwareConstExprString) { + $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED); + } else { + $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"')); + } + + $tokens->next(); + + } else { + $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue()); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + } + + return $this->enrichWithAttributes( + $tokens, + $key, + $startLine, + $startIndex + ); + } + + /** + * @phpstan-impure + */ + private function parseArrayShapeUnsealedType(TokenIterator $tokens): Ast\Type\ArrayShapeUnsealedTypeNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $valueType = $this->parse($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $keyType = null; + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $keyType = $valueType; + $valueType = $this->parse($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); + + return $this->enrichWithAttributes( + $tokens, + new Ast\Type\ArrayShapeUnsealedTypeNode($valueType, $keyType), + $startLine, + $startIndex + ); + } + + /** + * @phpstan-impure + */ + private function parseListShapeUnsealedType(TokenIterator $tokens): Ast\Type\ArrayShapeUnsealedTypeNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $valueType = $this->parse($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET); + + return $this->enrichWithAttributes( + $tokens, + new Ast\Type\ArrayShapeUnsealedTypeNode($valueType, null), + $startLine, + $startIndex + ); + } + + /** + * @phpstan-impure + */ + private function parseObjectShape(TokenIterator $tokens): Ast\Type\ObjectShapeNode + { + $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET); + + $items = []; + + do { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + return new Ast\Type\ObjectShapeNode($items); + } + + $items[] = $this->parseObjectShapeItem($tokens); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)); + + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); + + return new Ast\Type\ObjectShapeNode($items); + } + + /** @phpstan-impure */ + private function parseObjectShapeItem(TokenIterator $tokens): Ast\Type\ObjectShapeItemNode + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + $key = $this->parseObjectShapeKey($tokens); + $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE); + $tokens->consumeTokenType(Lexer::TOKEN_COLON); + $value = $this->parse($tokens); + + return $this->enrichWithAttributes($tokens, new Ast\Type\ObjectShapeItemNode($key, $optional, $value), $startLine, $startIndex); + } + + /** + * @phpstan-impure + * @return Ast\ConstExpr\ConstExprStringNode|Ast\Type\IdentifierTypeNode + */ + private function parseObjectShapeKey(TokenIterator $tokens) + { + $startLine = $tokens->currentTokenLine(); + $startIndex = $tokens->currentTokenIndex(); + + if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) { + if ($this->quoteAwareConstExprString) { + $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED); + } else { + $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'")); + } + $tokens->next(); + + } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) { + if ($this->quoteAwareConstExprString) { + $key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED); + } else { + $key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"')); + } + $tokens->next(); + + } else { + $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue()); + $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); + } + + return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php new file mode 100644 index 000000000..2684dfc7e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php @@ -0,0 +1,44 @@ +type = $type; + $this->old = $old; + $this->new = $new; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php new file mode 100644 index 000000000..ab10be59b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php @@ -0,0 +1,196 @@ +isEqual = $isEqual; + } + + /** + * Calculate diff (edit script) from $old to $new. + * + * @param T[] $old Original array + * @param T[] $new New array + * + * @return DiffElem[] Diff (edit script) + */ + public function diff(array $old, array $new): array + { + [$trace, $x, $y] = $this->calculateTrace($old, $new); + return $this->extractDiff($trace, $x, $y, $old, $new); + } + + /** + * Calculate diff, including "replace" operations. + * + * If a sequence of remove operations is followed by the same number of add operations, these + * will be coalesced into replace operations. + * + * @param T[] $old Original array + * @param T[] $new New array + * + * @return DiffElem[] Diff (edit script), including replace operations + */ + public function diffWithReplacements(array $old, array $new): array + { + return $this->coalesceReplacements($this->diff($old, $new)); + } + + /** + * @param T[] $old + * @param T[] $new + * @return array{array>, int, int} + */ + private function calculateTrace(array $old, array $new): array + { + $n = count($old); + $m = count($new); + $max = $n + $m; + $v = [1 => 0]; + $trace = []; + for ($d = 0; $d <= $max; $d++) { + $trace[] = $v; + for ($k = -$d; $k <= $d; $k += 2) { + if ($k === -$d || ($k !== $d && $v[$k - 1] < $v[$k + 1])) { + $x = $v[$k + 1]; + } else { + $x = $v[$k - 1] + 1; + } + + $y = $x - $k; + while ($x < $n && $y < $m && ($this->isEqual)($old[$x], $new[$y])) { + $x++; + $y++; + } + + $v[$k] = $x; + if ($x >= $n && $y >= $m) { + return [$trace, $x, $y]; + } + } + } + throw new Exception('Should not happen'); + } + + /** + * @param array> $trace + * @param T[] $old + * @param T[] $new + * @return DiffElem[] + */ + private function extractDiff(array $trace, int $x, int $y, array $old, array $new): array + { + $result = []; + for ($d = count($trace) - 1; $d >= 0; $d--) { + $v = $trace[$d]; + $k = $x - $y; + + if ($k === -$d || ($k !== $d && $v[$k - 1] < $v[$k + 1])) { + $prevK = $k + 1; + } else { + $prevK = $k - 1; + } + + $prevX = $v[$prevK]; + $prevY = $prevX - $prevK; + + while ($x > $prevX && $y > $prevY) { + $result[] = new DiffElem(DiffElem::TYPE_KEEP, $old[$x - 1], $new[$y - 1]); + $x--; + $y--; + } + + if ($d === 0) { + break; + } + + while ($x > $prevX) { + $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $old[$x - 1], null); + $x--; + } + + while ($y > $prevY) { + $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $new[$y - 1]); + $y--; + } + } + return array_reverse($result); + } + + /** + * Coalesce equal-length sequences of remove+add into a replace operation. + * + * @param DiffElem[] $diff + * @return DiffElem[] + */ + private function coalesceReplacements(array $diff): array + { + $newDiff = []; + $c = count($diff); + for ($i = 0; $i < $c; $i++) { + $diffType = $diff[$i]->type; + if ($diffType !== DiffElem::TYPE_REMOVE) { + $newDiff[] = $diff[$i]; + continue; + } + + $j = $i; + while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) { + $j++; + } + + $k = $j; + while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) { + $k++; + } + + if ($j - $i === $k - $j) { + $len = $j - $i; + for ($n = 0; $n < $len; $n++) { + $newDiff[] = new DiffElem( + DiffElem::TYPE_REPLACE, + $diff[$i + $n]->old, + $diff[$j + $n]->new + ); + } + } else { + for (; $i < $k; $i++) { + $newDiff[] = $diff[$i]; + } + } + $i = $k - 1; + } + return $newDiff; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php new file mode 100644 index 000000000..f6665987d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php @@ -0,0 +1,870 @@ + */ + private $differ; + + /** + * Map From "{$class}->{$subNode}" to string that should be inserted + * between elements of this list subnode + * + * @var array + */ + private $listInsertionMap = [ + PhpDocNode::class . '->children' => "\n * ", + UnionTypeNode::class . '->types' => '|', + IntersectionTypeNode::class . '->types' => '&', + ArrayShapeNode::class . '->items' => ', ', + ObjectShapeNode::class . '->items' => ', ', + CallableTypeNode::class . '->parameters' => ', ', + CallableTypeNode::class . '->templateTypes' => ', ', + GenericTypeNode::class . '->genericTypes' => ', ', + ConstExprArrayNode::class . '->items' => ', ', + MethodTagValueNode::class . '->parameters' => ', ', + DoctrineArray::class . '->items' => ', ', + DoctrineAnnotation::class . '->arguments' => ', ', + ]; + + /** + * [$find, $extraLeft, $extraRight] + * + * @var array + */ + private $emptyListInsertionMap = [ + CallableTypeNode::class . '->parameters' => ['(', '', ''], + ArrayShapeNode::class . '->items' => ['{', '', ''], + ObjectShapeNode::class . '->items' => ['{', '', ''], + DoctrineArray::class . '->items' => ['{', '', ''], + DoctrineAnnotation::class . '->arguments' => ['(', '', ''], + ]; + + /** @var array>> */ + private $parenthesesMap = [ + CallableTypeNode::class . '->returnType' => [ + CallableTypeNode::class, + UnionTypeNode::class, + IntersectionTypeNode::class, + ], + ArrayTypeNode::class . '->type' => [ + CallableTypeNode::class, + UnionTypeNode::class, + IntersectionTypeNode::class, + ConstTypeNode::class, + NullableTypeNode::class, + ], + OffsetAccessTypeNode::class . '->type' => [ + CallableTypeNode::class, + UnionTypeNode::class, + IntersectionTypeNode::class, + NullableTypeNode::class, + ], + ]; + + /** @var array>> */ + private $parenthesesListMap = [ + IntersectionTypeNode::class . '->types' => [ + IntersectionTypeNode::class, + UnionTypeNode::class, + NullableTypeNode::class, + ], + UnionTypeNode::class . '->types' => [ + IntersectionTypeNode::class, + UnionTypeNode::class, + NullableTypeNode::class, + ], + ]; + + public function printFormatPreserving(PhpDocNode $node, PhpDocNode $originalNode, TokenIterator $originalTokens): string + { + $this->differ = new Differ(static function ($a, $b) { + if ($a instanceof Node && $b instanceof Node) { + return $a === $b->getAttribute(Attribute::ORIGINAL_NODE); + } + + return false; + }); + + $tokenIndex = 0; + $result = $this->printArrayFormatPreserving( + $node->children, + $originalNode->children, + $originalTokens, + $tokenIndex, + PhpDocNode::class, + 'children' + ); + if ($result !== null) { + return $result . $originalTokens->getContentBetween($tokenIndex, $originalTokens->getTokenCount()); + } + + return $this->print($node); + } + + public function print(Node $node): string + { + if ($node instanceof PhpDocNode) { + return "/**\n *" . implode("\n *", array_map( + function (PhpDocChildNode $child): string { + $s = $this->print($child); + return $s === '' ? '' : ' ' . $s; + }, + $node->children + )) . "\n */"; + } + if ($node instanceof PhpDocTextNode) { + return $node->text; + } + if ($node instanceof PhpDocTagNode) { + if ($node->value instanceof DoctrineTagValueNode) { + return $this->print($node->value); + } + + return trim(sprintf('%s %s', $node->name, $this->print($node->value))); + } + if ($node instanceof PhpDocTagValueNode) { + return $this->printTagValue($node); + } + if ($node instanceof TypeNode) { + return $this->printType($node); + } + if ($node instanceof ConstExprNode) { + return $this->printConstExpr($node); + } + if ($node instanceof MethodTagValueParameterNode) { + $type = $node->type !== null ? $this->print($node->type) . ' ' : ''; + $isReference = $node->isReference ? '&' : ''; + $isVariadic = $node->isVariadic ? '...' : ''; + $default = $node->defaultValue !== null ? ' = ' . $this->print($node->defaultValue) : ''; + return "{$type}{$isReference}{$isVariadic}{$node->parameterName}{$default}"; + } + if ($node instanceof CallableTypeParameterNode) { + $type = $this->print($node->type) . ' '; + $isReference = $node->isReference ? '&' : ''; + $isVariadic = $node->isVariadic ? '...' : ''; + $isOptional = $node->isOptional ? '=' : ''; + return trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional; + } + if ($node instanceof ArrayShapeUnsealedTypeNode) { + if ($node->keyType !== null) { + return sprintf('<%s, %s>', $this->printType($node->keyType), $this->printType($node->valueType)); + } + return sprintf('<%s>', $this->printType($node->valueType)); + } + if ($node instanceof DoctrineAnnotation) { + return (string) $node; + } + if ($node instanceof DoctrineArgument) { + return (string) $node; + } + if ($node instanceof DoctrineArray) { + return (string) $node; + } + if ($node instanceof DoctrineArrayItem) { + return (string) $node; + } + + throw new LogicException(sprintf('Unknown node type %s', get_class($node))); + } + + private function printTagValue(PhpDocTagValueNode $node): string + { + // only nodes that contain another node are handled here + // the rest falls back on (string) $node + + if ($node instanceof AssertTagMethodValueNode) { + $isNegated = $node->isNegated ? '!' : ''; + $isEquality = $node->isEquality ? '=' : ''; + $type = $this->printType($node->type); + return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->method}() {$node->description}"); + } + if ($node instanceof AssertTagPropertyValueNode) { + $isNegated = $node->isNegated ? '!' : ''; + $isEquality = $node->isEquality ? '=' : ''; + $type = $this->printType($node->type); + return trim("{$isNegated}{$isEquality}{$type} {$node->parameter}->{$node->property} {$node->description}"); + } + if ($node instanceof AssertTagValueNode) { + $isNegated = $node->isNegated ? '!' : ''; + $isEquality = $node->isEquality ? '=' : ''; + $type = $this->printType($node->type); + return trim("{$isNegated}{$isEquality}{$type} {$node->parameter} {$node->description}"); + } + if ($node instanceof ExtendsTagValueNode || $node instanceof ImplementsTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof MethodTagValueNode) { + $static = $node->isStatic ? 'static ' : ''; + $returnType = $node->returnType !== null ? $this->printType($node->returnType) . ' ' : ''; + $parameters = implode(', ', array_map(function (MethodTagValueParameterNode $parameter): string { + return $this->print($parameter); + }, $node->parameters)); + $description = $node->description !== '' ? " {$node->description}" : ''; + $templateTypes = count($node->templateTypes) > 0 ? '<' . implode(', ', array_map(function (TemplateTagValueNode $templateTag): string { + return $this->print($templateTag); + }, $node->templateTypes)) . '>' : ''; + return "{$static}{$returnType}{$node->methodName}{$templateTypes}({$parameters}){$description}"; + } + if ($node instanceof MixinTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof RequireExtendsTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof RequireImplementsTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof ParamOutTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->parameterName} {$node->description}"); + } + if ($node instanceof ParamTagValueNode) { + $reference = $node->isReference ? '&' : ''; + $variadic = $node->isVariadic ? '...' : ''; + $type = $this->printType($node->type); + return trim("{$type} {$reference}{$variadic}{$node->parameterName} {$node->description}"); + } + if ($node instanceof ParamImmediatelyInvokedCallableTagValueNode) { + return trim("{$node->parameterName} {$node->description}"); + } + if ($node instanceof ParamLaterInvokedCallableTagValueNode) { + return trim("{$node->parameterName} {$node->description}"); + } + if ($node instanceof ParamClosureThisTagValueNode) { + return trim("{$node->type} {$node->parameterName} {$node->description}"); + } + if ($node instanceof PureUnlessCallableIsImpureTagValueNode) { + return trim("{$node->parameterName} {$node->description}"); + } + if ($node instanceof PropertyTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->propertyName} {$node->description}"); + } + if ($node instanceof ReturnTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof SelfOutTagValueNode) { + $type = $this->printType($node->type); + return trim($type . ' ' . $node->description); + } + if ($node instanceof TemplateTagValueNode) { + $upperBound = $node->bound !== null ? ' of ' . $this->printType($node->bound) : ''; + $lowerBound = $node->lowerBound !== null ? ' super ' . $this->printType($node->lowerBound) : ''; + $default = $node->default !== null ? ' = ' . $this->printType($node->default) : ''; + return trim("{$node->name}{$upperBound}{$lowerBound}{$default} {$node->description}"); + } + if ($node instanceof ThrowsTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof TypeAliasImportTagValueNode) { + return trim( + "{$node->importedAlias} from " . $this->printType($node->importedFrom) + . ($node->importedAs !== null ? " as {$node->importedAs}" : '') + ); + } + if ($node instanceof TypeAliasTagValueNode) { + $type = $this->printType($node->type); + return trim("{$node->alias} {$type}"); + } + if ($node instanceof UsesTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} {$node->description}"); + } + if ($node instanceof VarTagValueNode) { + $type = $this->printType($node->type); + return trim("{$type} " . trim("{$node->variableName} {$node->description}")); + } + + return (string) $node; + } + + private function printType(TypeNode $node): string + { + if ($node instanceof ArrayShapeNode) { + $items = array_map(function (ArrayShapeItemNode $item): string { + return $this->printType($item); + }, $node->items); + + if (! $node->sealed) { + $items[] = '...' . ($node->unsealedType === null ? '' : $this->print($node->unsealedType)); + } + + return $node->kind . '{' . implode(', ', $items) . '}'; + } + if ($node instanceof ArrayShapeItemNode) { + if ($node->keyName !== null) { + return sprintf( + '%s%s: %s', + $this->print($node->keyName), + $node->optional ? '?' : '', + $this->printType($node->valueType) + ); + } + + return $this->printType($node->valueType); + } + if ($node instanceof ArrayTypeNode) { + return $this->printOffsetAccessType($node->type) . '[]'; + } + if ($node instanceof CallableTypeNode) { + if ($node->returnType instanceof CallableTypeNode || $node->returnType instanceof UnionTypeNode || $node->returnType instanceof IntersectionTypeNode) { + $returnType = $this->wrapInParentheses($node->returnType); + } else { + $returnType = $this->printType($node->returnType); + } + $template = $node->templateTypes !== [] + ? '<' . implode(', ', array_map(function (TemplateTagValueNode $templateNode): string { + return $this->print($templateNode); + }, $node->templateTypes)) . '>' + : ''; + $parameters = implode(', ', array_map(function (CallableTypeParameterNode $parameterNode): string { + return $this->print($parameterNode); + }, $node->parameters)); + return "{$node->identifier}{$template}({$parameters}): {$returnType}"; + } + if ($node instanceof ConditionalTypeForParameterNode) { + return sprintf( + '(%s %s %s ? %s : %s)', + $node->parameterName, + $node->negated ? 'is not' : 'is', + $this->printType($node->targetType), + $this->printType($node->if), + $this->printType($node->else) + ); + } + if ($node instanceof ConditionalTypeNode) { + return sprintf( + '(%s %s %s ? %s : %s)', + $this->printType($node->subjectType), + $node->negated ? 'is not' : 'is', + $this->printType($node->targetType), + $this->printType($node->if), + $this->printType($node->else) + ); + } + if ($node instanceof ConstTypeNode) { + return $this->printConstExpr($node->constExpr); + } + if ($node instanceof GenericTypeNode) { + $genericTypes = []; + + foreach ($node->genericTypes as $index => $type) { + $variance = $node->variances[$index] ?? GenericTypeNode::VARIANCE_INVARIANT; + if ($variance === GenericTypeNode::VARIANCE_INVARIANT) { + $genericTypes[] = $this->printType($type); + } elseif ($variance === GenericTypeNode::VARIANCE_BIVARIANT) { + $genericTypes[] = '*'; + } else { + $genericTypes[] = sprintf('%s %s', $variance, $this->print($type)); + } + } + + return $node->type . '<' . implode(', ', $genericTypes) . '>'; + } + if ($node instanceof IdentifierTypeNode) { + return $node->name; + } + if ($node instanceof IntersectionTypeNode || $node instanceof UnionTypeNode) { + $items = []; + foreach ($node->types as $type) { + if ( + $type instanceof IntersectionTypeNode + || $type instanceof UnionTypeNode + || $type instanceof NullableTypeNode + ) { + $items[] = $this->wrapInParentheses($type); + continue; + } + + $items[] = $this->printType($type); + } + + return implode($node instanceof IntersectionTypeNode ? '&' : '|', $items); + } + if ($node instanceof InvalidTypeNode) { + return (string) $node; + } + if ($node instanceof NullableTypeNode) { + if ($node->type instanceof IntersectionTypeNode || $node->type instanceof UnionTypeNode) { + return '?(' . $this->printType($node->type) . ')'; + } + + return '?' . $this->printType($node->type); + } + if ($node instanceof ObjectShapeNode) { + $items = array_map(function (ObjectShapeItemNode $item): string { + return $this->printType($item); + }, $node->items); + + return 'object{' . implode(', ', $items) . '}'; + } + if ($node instanceof ObjectShapeItemNode) { + if ($node->keyName !== null) { + return sprintf( + '%s%s: %s', + $this->print($node->keyName), + $node->optional ? '?' : '', + $this->printType($node->valueType) + ); + } + + return $this->printType($node->valueType); + } + if ($node instanceof OffsetAccessTypeNode) { + return $this->printOffsetAccessType($node->type) . '[' . $this->printType($node->offset) . ']'; + } + if ($node instanceof ThisTypeNode) { + return (string) $node; + } + + throw new LogicException(sprintf('Unknown node type %s', get_class($node))); + } + + private function wrapInParentheses(TypeNode $node): string + { + return '(' . $this->printType($node) . ')'; + } + + private function printOffsetAccessType(TypeNode $type): string + { + if ( + $type instanceof CallableTypeNode + || $type instanceof UnionTypeNode + || $type instanceof IntersectionTypeNode + || $type instanceof NullableTypeNode + ) { + return $this->wrapInParentheses($type); + } + + return $this->printType($type); + } + + private function printConstExpr(ConstExprNode $node): string + { + // this is fine - ConstExprNode classes do not contain nodes that need smart printer logic + return (string) $node; + } + + /** + * @param Node[] $nodes + * @param Node[] $originalNodes + */ + private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $subNodeName): ?string + { + $diff = $this->differ->diffWithReplacements($originalNodes, $nodes); + $mapKey = $parentNodeClass . '->' . $subNodeName; + $insertStr = $this->listInsertionMap[$mapKey] ?? null; + $result = ''; + $beforeFirstKeepOrReplace = true; + $delayedAdd = []; + + $insertNewline = false; + [$isMultiline, $beforeAsteriskIndent, $afterAsteriskIndent] = $this->isMultiline($tokenIndex, $originalNodes, $originalTokens); + + if ($insertStr === "\n * ") { + $insertStr = sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); + } + + foreach ($diff as $i => $diffElem) { + $diffType = $diffElem->type; + $newNode = $diffElem->new; + $originalNode = $diffElem->old; + if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) { + $beforeFirstKeepOrReplace = false; + if (!$newNode instanceof Node || !$originalNode instanceof Node) { + return null; + } + $itemStartPos = $originalNode->getAttribute(Attribute::START_INDEX); + $itemEndPos = $originalNode->getAttribute(Attribute::END_INDEX); + if ($itemStartPos < 0 || $itemEndPos < 0 || $itemStartPos < $tokenIndex) { + throw new LogicException(); + } + + $result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos); + + if (count($delayedAdd) > 0) { + foreach ($delayedAdd as $delayedAddNode) { + $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) + && in_array(get_class($delayedAddNode), $this->parenthesesListMap[$mapKey], true); + if ($parenthesesNeeded) { + $result .= '('; + } + $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens); + if ($parenthesesNeeded) { + $result .= ')'; + } + + if ($insertNewline) { + $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); + } else { + $result .= $insertStr; + } + } + + $delayedAdd = []; + } + + $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) + && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true) + && !in_array(get_class($originalNode), $this->parenthesesListMap[$mapKey], true); + $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($itemStartPos, $itemEndPos); + if ($addParentheses) { + $result .= '('; + } + + $result .= $this->printNodeFormatPreserving($newNode, $originalTokens); + if ($addParentheses) { + $result .= ')'; + } + $tokenIndex = $itemEndPos + 1; + + } elseif ($diffType === DiffElem::TYPE_ADD) { + if ($insertStr === null) { + return null; + } + if (!$newNode instanceof Node) { + return null; + } + + if ($insertStr === ', ' && $isMultiline) { + $insertStr = ','; + $insertNewline = true; + } + + if ($beforeFirstKeepOrReplace) { + // Will be inserted at the next "replace" or "keep" element + $delayedAdd[] = $newNode; + continue; + } + + $itemEndPos = $tokenIndex - 1; + if ($insertNewline) { + $result .= $insertStr . sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); + } else { + $result .= $insertStr; + } + + $parenthesesNeeded = isset($this->parenthesesListMap[$mapKey]) + && in_array(get_class($newNode), $this->parenthesesListMap[$mapKey], true); + if ($parenthesesNeeded) { + $result .= '('; + } + + $result .= $this->printNodeFormatPreserving($newNode, $originalTokens); + if ($parenthesesNeeded) { + $result .= ')'; + } + + $tokenIndex = $itemEndPos + 1; + + } elseif ($diffType === DiffElem::TYPE_REMOVE) { + if (!$originalNode instanceof Node) { + return null; + } + + $itemStartPos = $originalNode->getAttribute(Attribute::START_INDEX); + $itemEndPos = $originalNode->getAttribute(Attribute::END_INDEX); + if ($itemStartPos < 0 || $itemEndPos < 0) { + throw new LogicException(); + } + + if ($i === 0) { + // If we're removing from the start, keep the tokens before the node and drop those after it, + // instead of the other way around. + $originalTokensArray = $originalTokens->getTokens(); + for ($j = $tokenIndex; $j < $itemStartPos; $j++) { + if ($originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) { + break; + } + $result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET]; + } + } + + $tokenIndex = $itemEndPos + 1; + } + } + + if (count($delayedAdd) > 0) { + if (!isset($this->emptyListInsertionMap[$mapKey])) { + return null; + } + + [$findToken, $extraLeft, $extraRight] = $this->emptyListInsertionMap[$mapKey]; + if ($findToken !== null) { + $originalTokensArray = $originalTokens->getTokens(); + for (; $tokenIndex < count($originalTokensArray); $tokenIndex++) { + $result .= $originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET]; + if ($originalTokensArray[$tokenIndex][Lexer::VALUE_OFFSET] !== $findToken) { + continue; + } + + $tokenIndex++; + break; + } + } + $first = true; + $result .= $extraLeft; + foreach ($delayedAdd as $delayedAddNode) { + if (!$first) { + $result .= $insertStr; + if ($insertNewline) { + $result .= sprintf('%s%s*%s', $originalTokens->getDetectedNewline() ?? "\n", $beforeAsteriskIndent, $afterAsteriskIndent); + } + } + + $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens); + $first = false; + } + $result .= $extraRight; + } + + return $result; + } + + /** + * @param Node[] $nodes + * @return array{bool, string, string} + */ + private function isMultiline(int $initialIndex, array $nodes, TokenIterator $originalTokens): array + { + $isMultiline = count($nodes) > 1; + $pos = $initialIndex; + $allText = ''; + /** @var Node|null $node */ + foreach ($nodes as $node) { + if (!$node instanceof Node) { + continue; + } + + $endPos = $node->getAttribute(Attribute::END_INDEX) + 1; + $text = $originalTokens->getContentBetween($pos, $endPos); + $allText .= $text; + if (strpos($text, "\n") === false) { + // We require that a newline is present between *every* item. If the formatting + // is inconsistent, with only some items having newlines, we don't consider it + // as multiline + $isMultiline = false; + } + $pos = $endPos; + } + + $c = preg_match_all('~\n(?[\\x09\\x20]*)\*(?\\x20*)~', $allText, $matches, PREG_SET_ORDER); + if ($c === 0) { + return [$isMultiline, '', '']; + } + + $before = ''; + $after = ''; + foreach ($matches as $match) { + if (strlen($match['before']) > strlen($before)) { + $before = $match['before']; + } + if (strlen($match['after']) <= strlen($after)) { + continue; + } + + $after = $match['after']; + } + + return [$isMultiline, $before, $after]; + } + + private function printNodeFormatPreserving(Node $node, TokenIterator $originalTokens): string + { + /** @var Node|null $originalNode */ + $originalNode = $node->getAttribute(Attribute::ORIGINAL_NODE); + if ($originalNode === null) { + return $this->print($node); + } + + $class = get_class($node); + if ($class !== get_class($originalNode)) { + throw new LogicException(); + } + + $startPos = $originalNode->getAttribute(Attribute::START_INDEX); + $endPos = $originalNode->getAttribute(Attribute::END_INDEX); + if ($startPos < 0 || $endPos < 0) { + throw new LogicException(); + } + + $result = ''; + $pos = $startPos; + $subNodeNames = array_keys(get_object_vars($node)); + foreach ($subNodeNames as $subNodeName) { + $subNode = $node->$subNodeName; + $origSubNode = $originalNode->$subNodeName; + + if ( + (!$subNode instanceof Node && $subNode !== null) + || (!$origSubNode instanceof Node && $origSubNode !== null) + ) { + if ($subNode === $origSubNode) { + // Unchanged, can reuse old code + continue; + } + + if (is_array($subNode) && is_array($origSubNode)) { + // Array subnode changed, we might be able to reconstruct it + $listResult = $this->printArrayFormatPreserving( + $subNode, + $origSubNode, + $originalTokens, + $pos, + $class, + $subNodeName + ); + + if ($listResult === null) { + return $this->print($node); + } + + $result .= $listResult; + continue; + } + + return $this->print($node); + } + + if ($origSubNode === null) { + if ($subNode === null) { + // Both null, nothing to do + continue; + } + + return $this->print($node); + } + + $subStartPos = $origSubNode->getAttribute(Attribute::START_INDEX); + $subEndPos = $origSubNode->getAttribute(Attribute::END_INDEX); + if ($subStartPos < 0 || $subEndPos < 0) { + throw new LogicException(); + } + + if ($subEndPos < $subStartPos) { + return $this->print($node); + } + + if ($subNode === null) { + return $this->print($node); + } + + $result .= $originalTokens->getContentBetween($pos, $subStartPos); + $mapKey = get_class($node) . '->' . $subNodeName; + $parenthesesNeeded = isset($this->parenthesesMap[$mapKey]) + && in_array(get_class($subNode), $this->parenthesesMap[$mapKey], true); + + if ($subNode->getAttribute(Attribute::ORIGINAL_NODE) !== null) { + $parenthesesNeeded = $parenthesesNeeded + && !in_array(get_class($subNode->getAttribute(Attribute::ORIGINAL_NODE)), $this->parenthesesMap[$mapKey], true); + } + + $addParentheses = $parenthesesNeeded && !$originalTokens->hasParentheses($subStartPos, $subEndPos); + if ($addParentheses) { + $result .= '('; + } + + $result .= $this->printNodeFormatPreserving($subNode, $originalTokens); + if ($addParentheses) { + $result .= ')'; + } + + $pos = $subEndPos + 1; + } + + return $result . $originalTokens->getContentBetween($pos, $endPos + 1); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/.editorconfig b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/.editorconfig new file mode 100644 index 000000000..5d66bc427 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/.editorconfig @@ -0,0 +1,27 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +[*.{php,phpt}] +indent_style = tab +indent_size = 4 + +[*.xml] +indent_style = tab +indent_size = 4 + +[*.neon] +indent_style = tab +indent_size = 4 + +[*.{yaml,yml}] +indent_style = space +indent_size = 2 + +[composer.json] +indent_style = tab +indent_size = 4 diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/LICENSE b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/LICENSE new file mode 100644 index 000000000..7c0f2b7b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Ondřej Mirtes + +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/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/README.md b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/README.md new file mode 100644 index 000000000..6957807eb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/README.md @@ -0,0 +1,36 @@ +# PHPStan Mockery extension + +[![Build](https://github.com/phpstan/phpstan-mockery/workflows/Build/badge.svg)](https://github.com/phpstan/phpstan-mockery/actions) +[![Latest Stable Version](https://poser.pugx.org/phpstan/phpstan-mockery/v/stable)](https://packagist.org/packages/phpstan/phpstan-mockery) +[![License](https://poser.pugx.org/phpstan/phpstan-mockery/license)](https://packagist.org/packages/phpstan/phpstan-mockery) + +* [PHPStan](https://phpstan.org/) +* [Mockery](https://github.com/mockery/mockery) + +This extension provides the following features: + +* Interprets `Foo|\Mockery\MockInterface` in phpDoc so that it results in an intersection type instead of a union type. +* `Mockery::mock()` and `Mockery::spy()` return an intersection type (see the [detailed explanation of intersection types](https://phpstan.org/blog/union-types-vs-intersection-types)) so that the returned object can be used as both the mock object and the mocked class object. +* `shouldReceive()`, `allows()` and `expects()` methods can be called on the mock object and they work as expected. + + +## Installation + +To use this extension, require it in [Composer](https://getcomposer.org/): + +``` +composer require --dev phpstan/phpstan-mockery +``` + +If you also install [phpstan/extension-installer](https://github.com/phpstan/extension-installer) then you're all set! + +
    + Manual installation + +If you don't want to use `phpstan/extension-installer`, include extension.neon in your project's PHPStan config: + +``` +includes: + - vendor/phpstan/phpstan-mockery/extension.neon +``` +
    diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/composer.json b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/composer.json new file mode 100644 index 000000000..23f95f507 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/composer.json @@ -0,0 +1,45 @@ +{ + "name": "phpstan/phpstan-mockery", + "type": "phpstan-extension", + "description": "PHPStan Mockery extension", + "license": [ + "MIT" + ], + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.12" + }, + "require-dev": { + "mockery/mockery": "^1.6.11", + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan-strict-rules": "^1.6", + "phpunit/phpunit": "^9.5" + }, + "config": { + "platform": { + "php": "7.4.6" + }, + "sort-packages": true + }, + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "autoload-dev": { + "classmap": [ + "tests/" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/extension.neon b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/extension.neon new file mode 100644 index 000000000..53777a40e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/extension.neon @@ -0,0 +1,58 @@ +parameters: + mockery: + convertUnionToIntersectionType: true + stubFiles: + - stubs/MockInterface.stub + +parametersSchema: + mockery: structure([ + convertUnionToIntersectionType: bool() + ]) + +services: + - + class: PHPStan\Mockery\Reflection\StubMethodsClassReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + arguments: + stubInterfaceName: PHPStan\Mockery\Type\Allows + + - + class: PHPStan\Mockery\Reflection\StubMethodsClassReflectionExtension + tags: + - phpstan.broker.methodsClassReflectionExtension + arguments: + stubInterfaceName: PHPStan\Mockery\Type\Expects + + - + class: PHPStan\Mockery\Type\StubDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + stubInterfaceName: PHPStan\Mockery\Type\Allows + stubMethodName: allows + + - + class: PHPStan\Mockery\Type\StubDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + arguments: + stubInterfaceName: PHPStan\Mockery\Type\Expects + stubMethodName: expects + + - + class: PHPStan\Mockery\Type\MockDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Mockery\Type\MockDynamicNamedMockReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: PHPStan\Mockery\PhpDoc\TypeNodeResolverExtension + +conditionalTags: + PHPStan\Mockery\PhpDoc\TypeNodeResolverExtension: + phpstan.phpDoc.typeNodeResolverExtension: %mockery.convertUnionToIntersectionType% diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/phpstan-baseline.neon b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/phpstan-baseline.neon new file mode 100644 index 000000000..2bbf36661 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/phpstan-baseline.neon @@ -0,0 +1,13 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\#1 \\.\\.\\.\\$args of static method Mockery\\:\\:namedMock\\(\\) expects array\\|class\\-string\\\\|FooBar\\|PHPStan\\\\Mockery\\\\Foo, string given\\.$#" + count: 1 + reportUnmatched: false + path: tests/Mockery/MockeryTest.php + + - + message: "#^Parameter \\#2 \\.\\.\\.\\$args of static method Mockery\\:\\:mock\\(\\) expects array\\|class\\-string\\\\|PHPStan\\\\Mockery\\\\Baz, PHPStan\\\\Mockery\\\\Buzz\\|PHPStan\\\\Mockery\\\\Foo, string given\\.$#" + count: 1 + reportUnmatched: false + path: tests/Mockery/MockeryTest.php diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/PhpDoc/TypeNodeResolverExtension.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/PhpDoc/TypeNodeResolverExtension.php new file mode 100644 index 000000000..ca936aa83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/PhpDoc/TypeNodeResolverExtension.php @@ -0,0 +1,54 @@ +typeNodeResolver = $typeNodeResolver; + } + + public function getCacheKey(): string + { + return 'mockery-v1'; + } + + public function resolve(TypeNode $typeNode, NameScope $nameScope): ?Type + { + if (!$typeNode instanceof UnionTypeNode) { + return null; + } + + $types = $this->typeNodeResolver->resolveMultiple($typeNode->types, $nameScope); + foreach ($types as $type) { + $classNames = $type->getObjectClassNames(); + if (count($classNames) !== 1) { + continue; + } + + if ( + count($types) === 2 + && $classNames[0] === 'Mockery\\MockInterface' + ) { + return TypeCombinator::intersect(...$types); + } + } + + return null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodReflection.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodReflection.php new file mode 100644 index 000000000..84dc543e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodReflection.php @@ -0,0 +1,111 @@ +declaringClass = $declaringClass; + $this->name = $name; + } + + public function getDeclaringClass(): ClassReflection + { + return $this->declaringClass; + } + + public function isStatic(): bool + { + return false; + } + + public function isPrivate(): bool + { + return false; + } + + public function isPublic(): bool + { + return true; + } + + public function getName(): string + { + return $this->name; + } + + public function getPrototype(): ClassMemberReflection + { + return $this; + } + + /** + * @return ParametersAcceptor[] + */ + public function getVariants(): array + { + return [ + new FunctionVariant( + TemplateTypeMap::createEmpty(), + TemplateTypeMap::createEmpty(), + [], + true, + new ObjectType('Mockery\\Expectation') + ), + ]; + } + + public function getDocComment(): ?string + { + return null; + } + + public function isDeprecated(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function getDeprecatedDescription(): ?string + { + return null; + } + + public function isFinal(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function isInternal(): TrinaryLogic + { + return TrinaryLogic::createNo(); + } + + public function getThrowType(): ?Type + { + return null; + } + + public function hasSideEffects(): TrinaryLogic + { + return TrinaryLogic::createMaybe(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodsClassReflectionExtension.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodsClassReflectionExtension.php new file mode 100644 index 000000000..d5aea6609 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Reflection/StubMethodsClassReflectionExtension.php @@ -0,0 +1,39 @@ +reflectionProvider = $reflectionProvider; + $this->stubInterfaceName = $stubInterfaceName; + } + + public function hasMethod(ClassReflection $classReflection, string $methodName): bool + { + return $classReflection->getName() === $this->stubInterfaceName; + } + + public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection + { + if ($this->reflectionProvider->hasClass(Expectation::class)) { + $classReflection = $this->reflectionProvider->getClass(Expectation::class); + } + return new StubMethodReflection($classReflection, $methodName); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/Allows.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/Allows.php new file mode 100644 index 000000000..bcf53ccce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/Allows.php @@ -0,0 +1,8 @@ +getName() === 'namedMock'; + } + + public function getTypeFromStaticMethodCall( + MethodReflection $methodReflection, + StaticCall $methodCall, + Scope $scope + ): Type + { + $defaultReturnType = new ObjectType('Mockery\\MockInterface'); + + $args = $methodCall->getArgs(); + if (count($args) > 1) { + array_shift($args); + } + + $types = [$defaultReturnType]; + foreach ($args as $arg) { + $classType = $scope->getType($arg->value); + $constantStrings = $classType->getConstantStrings(); + if (count($constantStrings) !== 1) { + continue; + } + + $value = $constantStrings[0]->getValue(); + if (substr($value, 0, 6) === 'alias:') { + $value = substr($value, 6); + } + if (substr($value, 0, 9) === 'overload:') { + $value = substr($value, 9); + } + if (substr($value, -1) === ']' && strpos($value, '[') !== false) { + $value = substr($value, 0, strpos($value, '[')); + } + + if (strpos($value, ',') !== false) { + $interfaceNames = explode(',', str_replace(' ', '', $value)); + } else { + $interfaceNames = [$value]; + } + + foreach ($interfaceNames as $name) { + $types[] = new ObjectType($name); + } + } + + return TypeCombinator::intersect(...$types); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/MockDynamicReturnTypeExtension.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/MockDynamicReturnTypeExtension.php new file mode 100644 index 000000000..e2913e3c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/MockDynamicReturnTypeExtension.php @@ -0,0 +1,79 @@ +getName(), [ + 'mock', + 'spy', + ], true); + } + + public function getTypeFromStaticMethodCall( + MethodReflection $methodReflection, + StaticCall $methodCall, + Scope $scope + ): Type + { + $defaultReturnType = new ObjectType('Mockery\\MockInterface'); + if (count($methodCall->getArgs()) === 0) { + return $defaultReturnType; + } + + $types = [$defaultReturnType]; + foreach ($methodCall->getArgs() as $arg) { + $classType = $scope->getType($arg->value); + $constantStrings = $classType->getConstantStrings(); + if (count($constantStrings) !== 1) { + continue; + } + + $value = $constantStrings[0]->getValue(); + if (substr($value, 0, 6) === 'alias:') { + $value = substr($value, 6); + } + if (substr($value, 0, 9) === 'overload:') { + $value = substr($value, 9); + } + if (substr($value, -1) === ']' && strpos($value, '[') !== false) { + $value = substr($value, 0, strpos($value, '[')); + } + + if (strpos($value, ',') !== false) { + $interfaceNames = explode(',', str_replace(' ', '', $value)); + } else { + $interfaceNames = [$value]; + } + + foreach ($interfaceNames as $name) { + $types[] = new ObjectType($name); + } + } + + return TypeCombinator::intersect(...$types); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/StubDynamicReturnTypeExtension.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/StubDynamicReturnTypeExtension.php new file mode 100644 index 000000000..250b79709 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/src/Mockery/Type/StubDynamicReturnTypeExtension.php @@ -0,0 +1,53 @@ +stubInterfaceName = $stubInterfaceName; + $this->stubMethodName = $stubMethodName; + } + + public function getClass(): string + { + return 'Mockery\\MockInterface'; + } + + public function isMethodSupported(MethodReflection $methodReflection): bool + { + return $methodReflection->getName() === $this->stubMethodName; + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type + { + $calledOnType = $scope->getType($methodCall->var)->getObjectClassNames(); + $names = array_values(array_filter($calledOnType, static function (string $name) { + return $name !== 'Mockery\\MockInterface'; + })); + if (count($names) !== 1) { + return null; + } + + return new ObjectType($this->stubInterfaceName); + } + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/stubs/MockInterface.stub b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/stubs/MockInterface.stub new file mode 100644 index 000000000..7fcff49c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan-mockery/stubs/MockInterface.stub @@ -0,0 +1,71 @@ + ...$methodNames + * @return Expectation + */ + public function shouldReceive(...$methodNames); + + /** + * @param string|array ...$methodNames + * @return Expectation + */ + public function shouldNotReceive(...$methodNames); + + /** + * @return static + */ + public function makePartial(); + +} + +interface LegacyMockInterface +{ + + /** + * @param string|array ...$methodNames + * @return Expectation + */ + public function shouldReceive(...$methodNames); + + /** + * @param string|array ...$methodNames + * @return Expectation + */ + public function shouldNotReceive(...$methodNames); + + /** + * @param null|string $method + * @param null|array|\Closure $args + * @return Expectation + */ + public function shouldHaveReceived($method, $args = null); + + /** + * @param null|string $method + * @param null|array|\Closure $args + * @return Expectation + */ + public function shouldNotHaveReceived($method, $args = null); + + /** + * @return static + */ + public function makePartial(); + + /** + * @return static + */ + public function shouldAllowMockingProtectedMethods(); + +} + +class Expectation +{ + +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan/LICENSE b/.extlib/simplesamlphp/vendor/phpstan/phpstan/LICENSE new file mode 100644 index 000000000..7c0f2b7b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Ondřej Mirtes + +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/.extlib/simplesamlphp/vendor/phpstan/phpstan/README.md b/.extlib/simplesamlphp/vendor/phpstan/phpstan/README.md new file mode 100644 index 000000000..e3bb94063 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/README.md @@ -0,0 +1,108 @@ +

    PHPStan - PHP Static Analysis Tool

    + +

    + PHPStan +

    + +

    + Build Status + Latest Stable Version + Total Downloads + License + PHPStan Enabled +

    + +------ + +PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs +even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code +can be checked before you run the actual line. + +**[Read more about PHPStan »](https://phpstan.org/)** + +**[Try out PHPStan on the on-line playground! »](https://phpstan.org/try)** + +## Sponsors + +TheCodingMachine +    +Private Packagist +
    +CDN77 +    +Blackfire.io +
    +iO +    +Fame Helsinki +
    +ShipMonk +    +Togetter +
    +RightCapital +    +ContentKing +
    +ZOL +    +EdgeNext +
    +Shopware +    +Craft CMS +
    +Worksome +    +campoint AG +
    +Crisp.nl +    +Inviqa +
    +GetResponse +    +Shoptet +
    +Route4Me: Route Optimizer and Route Planner Software +    +TicketSwap + + +[**You can now sponsor my open-source work on PHPStan through GitHub Sponsors.**](https://github.com/sponsors/ondrejmirtes) + +Does GitHub already have your 💳? Do you use PHPStan to find 🛠before they reach production? [Send a couple of 💸 a month my way too.](https://github.com/sponsors/ondrejmirtes) Thank you! + +One-time donations [through Revolut.me](https://revolut.me/ondrejmirtes) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail. + +## Documentation + +All the documentation lives on the [phpstan.org website](https://phpstan.org/): + +* [Getting Started & User Guide](https://phpstan.org/user-guide/getting-started) +* [Config Reference](https://phpstan.org/config-reference) +* [PHPDocs Basics](https://phpstan.org/writing-php-code/phpdocs-basics) & [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) +* [Extension Library](https://phpstan.org/user-guide/extension-library) +* [Developing Extensions](https://phpstan.org/developing-extensions/extension-types) +* [API Reference](https://apiref.phpstan.org/) + +## PHPStan Pro + +PHPStan Pro is a paid add-on on top of open-source PHPStan Static Analysis Tool with these premium features: + +* Web UI for browsing found errors, you can click and open your editor of choice on the offending line. +* Continuous analysis (watch mode): scans changed files in the background, refreshes the UI automatically. + +Try it on PHPStan 0.12.45 or later by running it with the `--pro` option. You can create an account either by following the on-screen instructions, or by visiting [account.phpstan.com](https://account.phpstan.com/). + +After 30-day free trial period it costs 7 EUR for individuals monthly, 70 EUR for teams (up to 25 members). By paying for PHPStan Pro, you're supporting the development of open-source PHPStan. + +You can read more about it on [PHPStan's website](https://phpstan.org/blog/introducing-phpstan-pro). + +## Code of Conduct + +This project adheres to a [Contributor Code of Conduct](https://github.com/phpstan/phpstan/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code. + +## Contributing + +Any contributions are welcome. PHPStan's source code open to pull requests lives at [`phpstan/phpstan-src`](https://github.com/phpstan/phpstan-src). diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan/bootstrap.php b/.extlib/simplesamlphp/vendor/phpstan/phpstan/bootstrap.php new file mode 100644 index 000000000..2d950b095 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/bootstrap.php @@ -0,0 +1,135 @@ +loadClass($class); + + return; + } + if (strpos($class, 'PHPStan\\') !== 0 || strpos($class, 'PHPStan\\PhpDocParser\\') === 0) { + return; + } + + if (!in_array('phar', stream_get_wrappers(), true)) { + throw new \Exception('Phar wrapper is not registered. Please review your php.ini settings.'); + } + + if (!self::$polyfillsLoaded) { + self::$polyfillsLoaded = true; + + if ( + PHP_VERSION_ID < 80000 + && empty($GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e']) + && !class_exists(\Symfony\Polyfill\Php80\Php80::class, false) + ) { + $GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/Php80.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/bootstrap.php'; + } + + if ( + empty($GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a']) + && !class_exists(\Symfony\Polyfill\Mbstring\Mbstring::class, false) + ) { + $GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/Mbstring.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/bootstrap.php'; + } + + if ( + empty($GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38']) + && !class_exists(\Symfony\Polyfill\Intl\Normalizer\Normalizer::class, false) + ) { + $GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/Normalizer.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/bootstrap.php'; + } + + if ( + PHP_VERSION_ID < 70300 + && empty($GLOBALS['__composer_autoload_files']['0d59ee240a4cd96ddbb4ff164fccea4d']) + && !class_exists(\Symfony\Polyfill\Php73\Php73::class, false) + ) { + $GLOBALS['__composer_autoload_files']['0d59ee240a4cd96ddbb4ff164fccea4d'] = true; + // already loaded by bootstrap inside the hrtime condition + // require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php73/Php73.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php73/bootstrap.php'; + } + + if ( + PHP_VERSION_ID < 70400 + && empty($GLOBALS['__composer_autoload_files']['b686b8e46447868025a15ce5d0cb2634']) + && !class_exists(\Symfony\Polyfill\Php74\Php74::class, false) + ) { + $GLOBALS['__composer_autoload_files']['b686b8e46447868025a15ce5d0cb2634'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php74/Php74.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php74/bootstrap.php'; + } + + if ( + !extension_loaded('intl') + && empty($GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8']) + && !class_exists(\Symfony\Polyfill\Intl\Grapheme\Grapheme::class, false) + ) { + $GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/Grapheme.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/bootstrap.php'; + } + + if ( + PHP_VERSION_ID < 80100 + && empty ($GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f']) + && !class_exists(\Symfony\Polyfill\Php81\Php81::class, false) + ) { + $GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/Php81.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/bootstrap.php'; + } + } + + $filename = str_replace('\\', DIRECTORY_SEPARATOR, $class); + if (strpos($class, 'PHPStan\\BetterReflection\\') === 0) { + $filename = substr($filename, strlen('PHPStan\\BetterReflection\\')); + $filepath = 'phar://' . __DIR__ . '/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/' . $filename . '.php'; + } else { + $filename = substr($filename, strlen('PHPStan\\')); + $filepath = 'phar://' . __DIR__ . '/phpstan.phar/src/' . $filename . '.php'; + } + + if (!file_exists($filepath)) { + return; + } + + require $filepath; + } +} + +spl_autoload_register([PharAutoloader::class, 'loadClass']); diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan/composer.json b/.extlib/simplesamlphp/vendor/phpstan/phpstan/composer.json new file mode 100644 index 000000000..07faa85b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/composer.json @@ -0,0 +1,26 @@ +{ + "name": "phpstan/phpstan", + "description": "PHPStan - PHP Static Analysis Tool", + "license": ["MIT"], + "keywords": ["dev", "static analysis"], + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "autoload": { + "files": ["bootstrap.php"] + }, + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "forum": "https://github.com/phpstan/phpstan/discussions", + "source": "https://github.com/phpstan/phpstan-src", + "docs": "https://phpstan.org/user-guide/getting-started", + "security": "https://github.com/phpstan/phpstan/security/policy" + } +} diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan/conf/bleedingEdge.neon b/.extlib/simplesamlphp/vendor/phpstan/phpstan/conf/bleedingEdge.neon new file mode 100644 index 000000000..01fee972d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/conf/bleedingEdge.neon @@ -0,0 +1,2 @@ +includes: + - phar://phpstan.phar/conf/bleedingEdge.neon diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan b/.extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan new file mode 100644 index 000000000..7a08ef485 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan @@ -0,0 +1,8 @@ +#!/usr/bin/env php +M6duh1bab2Koqfy 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�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

    $); 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%0DZ$s-)ypl2 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�fFlW&4sr z$c$jlruW)f_crj(Z$B|_QMrvay9p*O#KZze0#%YrwbPez2Baw+?TcYaVOq&l1ZlA zcIsi55E-PLGERC^OZg!5f`bDmPrTNc!!62-gGcC#D0+&0fq8)!4u0-sv4h*du?p+< zYRb-=p1Jq%l|t^Hh3h+q)=d#*96MG1qhA+uUd(NPO3bxRb440xs{>1J-#;e}@JuWb z6e+jKALw7g)(77ApYv0~?{+e&AaSibBiY&UFQaDsON6+MByk=4=7Tc6o!uOIa@rj6 za7$hb+EBPJW1o6!)@28C)Y#4SIs8^7lVfvwA8{rdADABZ-JW6>_XQTOn(62n5{_E8 z`0NC;|FQFDix@Za*V=ehg-m6Bgj@s$;O6}|-YxWQW6UnIU^iE-6zMcDjx*~36k|ES zsaLh=EppKP!LtMLA~h2Jw-Yg6vpC@Iy{^AT#JTMf)oNCLacZaM_5$Xx-VGiRQEvW) zmKi@#J!3Dr8ok=d9J@Ki%VH|!k*_RaagI(0ZgbW@|A@+Nafv5Ky*F1dJ61A3aL-Hj z-YEQTMFAdi&>V-J_zsFrPM|4T0Bm|&gDR2W)`B{#3sZD}`-2~N&R;i~py4(w3P&AY z7gbk*JFBa}s*@|X({g~bn?GyrC%UC@GWB3s*oD23+zMdz{>MxZE4j_ib_y5Dzc5$M ztZYC-mVkHC9;p&VzpQ%iA!}i)lz%SqbX{j{AvD{4K3kL%5;RQvTX7zzf zAMa)knz$b$1}&WQ|9Ida!~%f_bSu3@+EI+X>N~DyZ@KJ#(=nq(j$5Zoq*aM^e(M4w zSRzNJTOZTuZnKg2E377akE&DbWMJ}}vn~_e-RP}!vM?2}Z^ZAm@0Ycc_DX3x zK`QO~&@RI2Zg80Z!qs6pxpEd89QfO!(dKBUe~sgRKZ|2mz8_ol;52EBTj(wv)gkqa zR-8Y#U{`I9JFNZJBH>hOVem}AcA;A3P|Wf0QDCckkNaH&xJ{gP)Jxa5aP7M6Dtwd!{hEd1)=xWeBv~TALhr`Uf2k z7IL@PCNT%oSp6%tPq-1l3$oKqCEd+CZQqeHkc>BbwJ>MwGrvenJe`M*iKXebhl&$- zvGTxOum8pzI(N%S>-GR|nAka~y`ufS;aYQ5%*~C=qRLv*+JkF{gYqxYctvQ$|H24e z!8QV3Gx;2I*QNvg4jvphGqu#Vc{i+j%Dm?8b_~RJ9GSQ5r)c7=J#g?b%{?E^u(Hy6 zjv3lAn!LN`x#FO1#R?f}G`-VkQ|^gtgb16!_`R>4EX1Ys+u8K!S)IQtZo~merL0`MANmP|+ z2&w9s9<+Kfb3F3{n_Y3I*?$jQNhsvUb7a)N^yUpErfP1~V(g(?eM_#LG$Zg@qfiXG z*kUi?MgTu<`jfc?fayMv`_#i;BaNue#G%W_k`RfySZw)^fVU{4Io!TZeLKeGJL2U0jj*`bXzB7+y<)5*bQq31!>{V3SV< zo4o^!&pqIyEKrnx*~_1U9%*E5GzK0h^)*HJ zJ}$P3#q5oq==poQzaLSb7~P@>B`IOm7MLI10zBj6i(87>0w?A52~nL7FH|e1fY_rvgnMY8a;N&>$w65b-8g(MMY5Ej@l8_o^lSWoco)!r>IdXQO6F|ICX>Y1{~Jw zxNk*JQK4G3KB8tlY zbfoGuoZyc5ErTa%xh{R9v()OEbGgVQvxd z(jzOgA_}Wc?_TG`LiJ233jhxKbmdthpr|+r0d_0wOl4tTzaGUA@yrJdY~{y}N!}^~;IFRALlz$atH|*S46TR<#sPjeva>lw7&vBI4ZvSB z;c_~Inx?mD=?kni`VC*Cv5*0L>XR{BOB(`LyK2c$+f(#Cw(&80lgCb?e>u9TS+JFo zR98#MxQdM%UuRs+`uR_@2UAQpqZOu`F@3>Az%{2m*i}sABcRLaef#0L(oD8TtcpG* zs9La~fffMVulF>?+Ew`&KGG^O@J<^=Yh z^@a({r5>Epspat+#ccwMnJX=F{g&zVpH$LT@EupuZqPO+Fy4i5E%Eg+|!#`+W1+NInYmjy^y5BeDCd&Ja zAow~qwUmF;-iLA*`_y~IJsZv8%wo(QuC6<8Po6N&Y;O1}&u0!osT}t!LM{3gIQzlI ze@nl@YOc1Ial~75cINcih5<8#x){4e<8|Ziv%9V^wWPp>ky=qJMs1~~e!P0D>e9(< z6=3J%-`OInXL8zIY;V7=Q^g5lmSR$xxY)%`@At3#;0GZu#^yELpSI%f&u%_nxC3Xx zmd(Xga6kiJO~I)iTCA{BV(x)c0w3Fc%`+k?@Ci~&l1_+KuVS4GTHxP*j6OzaOX;_- zuSdcu|+o69sKRD`t?Hk@6oToR%N9r;q{q6#P(@=IYx(I+uBd=cHEYU1$=}j z&YA=Nv%~s3Mf2A5JCH|~O=?+EHYrk-2*nfh zn5bE2l`=8#p7FzsNdr$gdE#ui!aTWVduOjNk1m(?d+3|3q_@?p>58Z_#7C?zaKo_& z99;x4hLZZ2g(7~HiGlN{{(Phm2Turd>8cVsjz=#C(|fb@0X-9(P|8G{26lX-`bwd0 zPrn0o9#}PXK0x6=1}Sj+O-&yZ(!gWEBF#j?DSi9xJZ1&n{powZ3af{zG!{78Bg2EL zz}(z5eS|dd0JBuBiA7X**{RZuv%_Xx7T9m|oHQEDlHES@f5H`y{voP*cmb_Wv+@7p z1zl$!Zaf!Ts*YZusm&+e?cC-5yIL<7rQJHM3prU2T7U7&<6XJafLq;ipt+oY-(KpH znbi?Iu5hBB2B!c{`(jsf$TN6SWCjIJ_?d%|`0v3BeD0yE%*7uMGwX3&ubGE`*5f5H zvl}za+!wB4*}56)3>>|*-0ZG-cwHo!nn+({GTn$hEtms%(IKy{5v4t->FdM=p9P)D z)W83ZLZuZ4|71G=>nFJ>@GjOM#vwMjx;4NNSr|Ad|Z6a9l!*-6# ze%;e7tV-QQXqOAA%@8#f?XByYjTI&@aGST3VNzkbOrS`|lVS*Xz@K-BpCmR3z9_C0 zl?rATuz(%7Zu5o)!rqpC2e){aLH+x5qiCuWK5!dN39NpjZD*k@b)vM~c}1Blf26(noGIwg}vPHgPnT z4M+4rKqv-t08i}qyt(P)iBIV~D`cEJhwc zZl`jWXy5!9RD1mO+z>Jqz!pKfFcnRf^y_-MQnhTjb~NCzO^-Ll)WG#1ChO0~EShp( z0pGs+P&3jnt^@fO^A$dYNXn_<0DNryL#@OETv-QXX?w%mA?dx7W(8ieZOvQ48aR+a zSNbOuP16a7v@Y6}vZ}xry6pR~kOoewvhnEukoVqkQWr`8xL`U^F`b?{qaY$tK}@?O zSxGBP5CzxSnc3ZeNlXBiaEb{rU_?Cu6%%HRm~%L@o;jVKo@YFB&fj`>SM{eS?SA^R z`aI9?_4`AM-JN-Nb#--hb#--hOE3IS85-J|HpcWx08BS*0_g28Y-Ca!d~0hVa&s=B zBUjh~02j3BKj)UULKFP-YaPE=E32qg&<4YAhepMZ3JMnh~^9fIOZe3{ zKYc)O`;lDS6i$hC^7>k=pfk?6;1q$Ya)whEmXmnHClu3ugFR&7)2Etkb3py2AObEF zDz>K)d(Z~Z+j?IAXJI>_p3xz2F0W17-i!=7;OBmQ1ljiD9c2!5sEa;p6 zxbaPa^d0pukX9j|hCCk1RrvM^=dQ2zI7;vX$XSmbmDS+w(SqhW*aFm?&{Rky5IOZfJ^mKKOy!dGLc*U&o9 zGpCI2*$z}#O%XguCallo+I7Kz1pbvFzt&!TUfZ`lDEuwVdwaHb5WPV)%Q~M*HMs)zI0agC1+p6RzrJ zG9UfVfdWn9v8F2pdNIA8`3GHI-8a-;{!yctirZwflDT;mHvpPC>X@gc0XTF427zXR z($8iV3+S=iUVNaywo`rR7JpgwxqRAw_0mN9ByTk59u^GfdLP&AA@IK4n8Fzb6HzdO z=dpx9PdF`YF4hbWCU_hTQI4NIwD$bkcFW7UNe^6&Ty34Qbwg?HlGcRyc5VyH2lUSE z>&#)F?{%Ez!{|di^OfCs&P(3hu)V0=6B2A-ZopPu4tM%OSZ=)t#DKPjlbk46n@KX9!Cu^!JP(4J@Q zI7%?Fk@Pi_45lDn$y|coK4~MfZ*=cFAtt5z(#ebp`rQ*pnN0Bg=x6_Y){PlmTNu8y z_X8j8KWjVbzweE+=|4tFiF7fu3Oeq&b?OAt_ljU3QNB(;*OH0SE+a}Wx2P8W#w~!J zeElOv#O{Me4JgD_j0oE0n8hZ!*0(_|Q)NfY?d#%8A|H@~$~@y~Csh_xab?%)dp_CJN!b_^(qJDQ1wEs=l0%!3|3?OEe=`t}{nfcB-;mkRosIkbe4 zLFcbt=$-{)A&ZXRz?h&r-FSiV!2{TQ%*$e%Z?nA4jdM2bVWN#r%1@2&3+Eqn|0-*^gNS zy=C?mR|%&3+)(q)%ndtnXXv)`%%P<_E@T>^+UVM;zzPTZ2AbUD`U%3X?>(4NT1*Br z7tUl@&_6fd^N7H@D^@>Gu{L4Zf*!luJY$P}yPdp4>BW>J(G*QaGq|I~?uwlkJ38EK zia}ISKm2K!-rt%gqDk|Ffo+P{OTA`J9ewXDirLR6#Z2tZ;s)KJw(Hs=?!atYVR{?; zkm#?c3wB_shv^`mUfql(ObL#$%s%KvXHI-ynixqx2a-A#!!W%J6N}Pouo{$i#Eg=rgU52-}-Y)9P)=+a%+?JgtX-^>*Cp-G=2?ZM20ZnJRFMS^=M{p>Wt z%>0BjZWfN0TZLu&(u2(f=;E&ioAucLI#kpbbL*ptdjq=pkbO=1R^XW&YLIud?b$YU z`Ra#6P`VINnbHGi>_Qu%uve|Au|XF<)M0zU#-Id}PJ|+3nUu~A zuDYr4W3c?jRU@V=r8p^H(1t4FuMIa(t*tNR-0y&G}p;HA`Q zJM1jBhqb3BQn$!d}-adIU@D%Z|3MONhlNPMXp15mcDx0 zm*oMva^S$f3%~y5A)pjTO;VaXg|I2>$Rt4YWPH%%C9iZAeE;$gd|h}a6OH6~9S<=y z=mzg!RV~o|*FJ%!<8yjhLA{i&%m9K}P!iAuTU=`*`~J; z2Yv0?^9~ZW-NCg)=>61s6f9Sq4`y)C1=#`SrkDTio^YOw_ifO|97_YF0lM#`oO@C` zse{%#h=OX9(Mz?lGXCTvFC9EqgyG+;2(}i6$_LRgBJB^yn0e65<%dP30sm1?X@Hmy zXVcn>OlMTk58nN&`^&&aB%19=tg*2^l+AKJ(kO-p{cP~v7YNhtGd-V-&0q&(9)p7J zKVYld1l0d7SR|2ZsQ2!|cV$@6GvC=|n85mXCYx1^+T zti^WlcUspk4hW9fXs%XHWj;ZFoIcic-<{9K9Hrc-p|f4=@elPsLHLA^<~DR>H0i+( z%;{8|@ z!_R*xu~=obI!Z)EE}MQGem_u2EzyE8QC zFTXr)?rOOYo0ny8pB)|a!h_q2D!3a8(y>H~6zav-F>auz_djSofpy=?=W~q%Ne(7l zi_QWWw0^61%*Mf8&*-9XQc`PIGb-q}s|UR+{JOg>&C%HuTvo~pmcS}#_4su<3aI;d zHMgYs-jMBtcRZn+IgfK^w9zZwHG>%iy?*hZzY#{=*UCglSF44#qwAo*p785Wg6O`m z@%ByuX2U*4L0ZOQhpbI>H}9kv^>?M{pycqYfHq93Xckp>PYm3#E^Wlz1Ls zXwX0J^2)Koe--`g#(x9d5Z$}KeS9{Nu|fCRJZ{4L@aNsI)6HqxPsa2EowV-BB{O@< z-_U#g?S*@H!Hh%wOu9ofT5bz`%*=y6xoOU%kGkt46(hiXIis<@7<8y=nh^`la^?HWnKvT$xPpju(Ep5XJ1=c}dxHZ#PSa)B!C__9; zv%8tYk{EjcgVs)deyISvt1%5=ENw$$@dq^MUv9rQA<%>AXE$+k?mQMSs+gfuMCuqF zbkoHXO|1p@C6{iaB>O6Dw%wRH)z@zvoMWvZWGv$Kba0|gsXbR#oSpbt(5sx~L84BE za`ZSyRBFz{=0nz?)%8d1CfM$A5!y7+waJLuq*Asg4y>$jrEOR5o3ZZ-X~$g;NzFN< zREgfs=sJBt<}v|xw|Nv857#GSe0pbZhJQKx__YPs{TPh2uQ`>?>0p!&U`}SKgRXx4 z)42lfuHjl=aK`5CGGRI}rl2D-kKZcj@Ymet58GA_{~_ST=KC6M0(8~B=UyvKxUUG= z8SJ(qXauf7mt1s)iT=3{q?SpVYx~&;_m9l|YbRk9dpS30Af|1W@za@I(C6OW@M3`t z5a7`<=!U$C^T-Xl4jeE6-TUJc%o&?I+bZu!c82xLHt5ingBJ?h?z*8SI8{QUa6vv9 zwx;?a+yrQk&F`2cO}HD_aI>&&&+@q)#~HWGeYL^GdG&B!j2E)0ENIYir^o&(?81w1 z(~oQ@9iyXTI=`ERNFb#*<*1IHop)qA#pgUW&lCZ0-Pg4>+Uiekx8;LfCsJyCLhbD1Dphw*`)VTHTA)+`Q z%E&h7=y4x~ypoYYH@^Hv^FEjRd}>4hSz$IXCTR13ug();!{u@lOQV<8X!{cBd5^6j zpzgMX*Bv&A*1GdG^9{P?^xMt0!CgtREs3~1MN-A6pzD6zYnm|bo+B_LpUOoe`l?H) zf%3{miNY1tkNFe zXSaNQ3&D0@p{a7BB^bozu=0b>*!qW=f*V+GviWqHqG4IutA+L5I(v4`?sUyV(uBLd z)3Lq;+HPRJLC?HqFasam@*J{{ZolO=K!2EVoY`Nw zk0ZIZ87~PY$+)1G-T&@>!n?c60x!!v8(=Rw8*aS0xoYY@JF)iD-SBWM6c1DR;H*76 zZOd}sWj%~V3^14^6+M_y76|Bt&m3(w-|nk1RS#6BUR3HXZ7Lwx^XAjD51AqIb{|LW zF(*R0K=EPBHt5Lk&u<8>`(z0>n+jn$1_gcQ!_(gvP;7493{!!d6;7LLU$(Tz%v^A| zwBW8M#VsJRLgzNh!1m{UfKEL3*^{Le_c4tmDXp_PN*BP%g46AF1;2pdK~MfuhqDCU zeg5k)rGo}Km!`Z|D}B#)&>y&Ip_x$b<4eg- zpY&cLsMXYpo8s%*P6%e1d|Eq7F`>^^hUEY{uiaa0TXX`ORdOxDf&uOD#GlPwn*g@a ztjH@E6SRBJT}>rIcTBoqkm#fIqbFm6el)mov54B;2hUPcM13}u&u}y-!^ogBSDw1J zAiGZ)8a^qoW~=kj=WqCffV%4&1@(+qGM`xm-F@ekW*_AqnhDWceM+u&Xr{+cTkjK` zQT=kMK0SMs83jFer<2DBs=G|dKFfh>F9rqu{H7z!+3zU&*=@ENGo<%>n0D4ZMq42+ z&D~&5gx$vuXG8?91dVUQ69(P*jJ1rdfJF+#J*G2u@|2>g8n~1j0KF~ts@a1Cl6jI3 zZS85d-OgK^<01EGCd*uzI5{Ah$1HP@~roJ)l>@8+iLI3&H zA;#}@cOqly992PT;7C-0aY29SwRm^oHh>6P=$e$?-KH26bii{ zSiQ_70b<+XCRQ3N%;a!Zzn^+8GYh)apaCZE?5?=ll?ylL`RPaGMN*Jx79btbb4`u2=9jK;dNO6vyl z=+x}81BFNb_QQ6 z)hT`_F)rw%FTDDI@aw*TM*_Wh=xjQ}f?mA$;U@UvuC5_UHCCM39!Zzn%XbT>?uw;v zz$wrP%qQqQ!*(`>C)_OoUH+gKvJrz)z;HgWtb?90ead{{)?K$$Kwe??WK7W4`i0FV z&V3e;*`kZ6dX0%OD(KiN=a_Rn_Z=3+$*DYXu0Ef)B8X!c9`xu_o-k)E_}SUk;^GE} zK%+?&Yz=2x(mDO6>a*Mu=)7m98K1;m=SVtw@v&#eIkzu2i39E%IXEJbXhXh9y>YIF z6N(EJ0sX4at|pdPML)YqhQPh!W`zy20Bq1(5A0wZZFm1Hf^9S1?V*z)vuhs8=%9Nn z8-KqjcY9RE3JwDX%!BUzV8a4|cc1C0aE@?GB=V;hHa8m@ckO7DOFfu(;1l%wsYiby ze7cLFI7+EFUf4mygWk5*q?ZIfsL9XfwNj(UU>kJtlh@rYxbCLOy9jP$-hAeP^@8bc zM=6KSewhxjBrps5va!l6ZEERmczAE86I@u5q(YGg!?=}HYW;FqC$JD zQD>#uaiGipd()qVc|>vDW_X$(X2JOg!~r^GMgM06F+fPw3;r}9LL-IABisV$!pA?! zOA8nPN1jC@$!L@=SZAUpA8Q)70Xm?={pN~wpoJ{mkkJP|_Db{LCrAEMICr1n(^4D- zX=Fx0Px~O$T_D}UFD_r}G;IvC7ZXmb;n5Ny0 z(rNFu#W5@q&^Kny-&(-k6|hY5m}0+tCh-E%?LK1UJ-IGp4_VN;OZE^f<*Q;I^Sa-`x4qq-6PtD>` zh;6d(IsZJfQFG@P$HwN?rERdMhBkg#_;t5=p$0u>RV-N0q4kaCYOA{h^b&xpvr5yT zvlubZi-)XQF08s6e_pW)ifSCi=%9z~)nrab0vS1qL+btI97Y9={`;LBg=cqRkkg1w zyWDp{ry&f`ZQ`4R1lZjx$fff9{++$G*zk^O;~=@uHrlo;8w8(Ujh&r-d*6?rnp-qM zBQ4qHSfk##+2(U~?>du(*Y0pKmH=&wR1c2tpal;4>&RzJ85(!}zzH$UKZQD)hY|FE zxhL-;!{~0Gd7lNY3mk+KxCPM8uUDB3o%^7Y2F4OpP9qzeqX+dwh6a7?okgDt^X|&6 zXS%72`5y)bz5B2;t`cDPnNCI&n^4k6a+>%u=43_(t=Xj8KLp)k6lFBaHu$OyPBvKt?t-9m zxMU=%Z{pdz%^tmuHv43EmbF$i()l$q?bUpl%JKl6ef7?#2A6UpCG$K)f5rF%2*3zXL%6U$+9na99 ztB(5dPJwo}(KOvqufv?p+8G(2uR3c&yO1epiRZty3F^x{gFZX`+ms-?dqr@ZQ87Y| z-5iDm4Zk|9L15kU-EhYY;k$JGtY%``3(DA0le;hPYHk&|Zzqt76-&wuGxQu512n$( zPNRkO04s{Nod|_-DGlx5*)HSvcYI-dn&3yEx_*Lrr|(qm0_dSzwses$xLXj*=!Fy7 zBZGV)AJAbv>yH<3_qmP`7*}cP$)KS3FW%M!9^I#oo|W0STyn`VGU)c(eAJFLR+)YZ zrf`7G*1r{}P5PV2!Cn6%sXV!PQtH4CqBO1Owlp{{xiZ$3(tBADpkw}e!y>_TH+(c5 z$vaKvLNVTD+Gk*~LH(W(Xm?*4_s#SjHd`ZpUN+X8)?xCvE!^zFz_C;3i}l9;vi(pMJpJj#13A+#4WyEin397rFu4U}yV&_HDcG&;Zc|R_bCfxl+y3x>-(fbQH zh9c-loKu9_SQ}-y8YH&ng!Th*d&&W_`QcQ zyP%sMG~Wbw-R(&6#S|pjC@q=EO@O{%GxgHojFSO0cie5)^oN5tG(MU8I?zah)~Oe@ z%qi%TH%&JpcHe0cq)KgWjD$+Vckj*E_dpSX`x2urKT~>h%FDO1y@P+B*1MyC2N*;z z@_}R8dU{1gpVh+fVXi2;=K;n525y3*_ThL;BEEfiIx3o7GFy7FA2sbZ@1Z2LC*Ws& z?6}bV!?!mjncOE1HZijCvcr+PzL_!B)!lelML)4?gOown{j%F8A_DhasBwQu6X^m% zqs}}FGd}40w_NuZ!FTuhu#v%g#Bx9BRYnHg=#D$vQ6U3^7lM*2<6);KzBKR0wS{AM zrO@TZh;M~!+r38@*47AayB8VA+g@a5vtU5~b?0#_q#<{kA}f4sMqbOtHdpid9el4q z?@dj)O&D?cpa;-D(789fagiXpOPfqJ6@8=w7bR^wSlxHQYYD-1pMo(e<|YAOJL6!+ zffN5DsP5XVDqmWOeON>w2hhvrp1Fr0yUT$RJLpEQoEzGU);nLHYIdMOl_8rp;Zpn3 z&x6bF-%D6V7u=M=bJp!m#?MQ3H_m~(g2`>I9xPbUJ6}5KI^oh?0Hk2*E}%JRx3%Gt z3)i_;pxw2BZ#~sZ>Uo}-23_)mcahQEDpRZj3LFc^sA^?A&sD$R13=qAKRfo5JA`v= zb=`(eol>jBT|Br>PBj(lkS$DH3CzEFPf;L!@f2w*=Qc=0vk!pAFc1m{s5O*i#_gou=k!Lnf;C7xprE@ctdmQXT*_WBiT~3l;RC zr~7siPTftPT#@U|h@j7H+&?LZ?rUJaLe=i&KW$(#8QkNr*j!PCM!mD|!_0!7chckL zEX!S{I=4}I0katt^r?$Snj_GJ9=Se9b!)N^&cp8y|D$DrqIalBHKeW6%aNGU!JQH<~+0?#NVHGi(>Yv>o!$ zvzwaJ1$WJ8L{)H|;E2;Jh#NF_#o_CTAlyOo-mciTUzcsV&7TCciW+fSk>Jy-?QkyC zq%#3*RbKqXIJ025%a>0!$tln?uaQLo`e4s#KM2?ElcbUA-z3BI462%ZlNcBD`BR?1 zL~z|bFRjtpXoymC6m*QCK|_zM5ff;4{|I|ORZFJe6!HPa2YvA$=M4~i_sLl3A0<#m z&Xn@8{l_!=%zau~fxqFVE+tdmoAC+m3h3zWv(A-9+|4yzWzCwqtZy+a=x$dme@9^5 zgO0Qlw6C4aWMI&$?w9Q=!0!BFXwCV(?QdQ7@E2bQtUJG2*2J}*mkXI+(9WA&(;&dG zgKmRJUQkrW{_UCbKx&0?THGajgI*Rv zcZv-#*RtFl8(CMxLHFjFqWa-=SY8 zbI2FeR?|YDZ}g92&OyIjYn4epb6;CX;z~4XAnmQox6_kes|Xvu6b_8^LUmDX!Qx77-y=Aess{WFLT*5|E^6ZUm>9GqR{HCGUwDtHn1o_mwx-G36{89R>^HMZ@Jh?^2nSAUKFO? zmqxk+rMn@xhE>&iH{QpecntvU^zL2n39kDZ&?t9v;itpYfv$gB7n4cv z9*LM~on2KiD(Kfow5RX~9h&As*_Na}l%2}BptpTdb(;vFntpbi5V}w$o}mcM)E7aT z7#wu&E0K1Hg0fW2R>Jn~I$rwpmcp|8JfkxSdW}OVSWjjZ^oAWr-XoxaXM-1jwr9ia zi?%U&lkN&Z8IvYO5P@Z=8R(AFetlLLb`Lls1Gwb*Q`mFBgKl!w!W#wNeZpzG6H4ln zdfVOK{=wJHEgpA!hOj}nv5B74)~8_bg}^ar^_~CtuW&q=esjUxoseJ;c4!KtWr z>LZK``p`2kJtesA>=G{B&gZ0rg$xV2{Idn-W~uwQp^$9JxQ+aB%l(B@ST{G@z%PDN z+?Kpn^WL{=#NG{0J^Q2n(uliqu&ZXG+6vxYOgEkQu<^XzEoU-LDwk|Bc`G*K@14D$ zIXiJ*P^nn8WbiEKQ3U z!Kb^n;gXITDLV>q$EMGldEqWk+Ik6}{g_YCFRnW28|k~dA&;f|q70;B)kgi-xj&md zi#uvAkv5AC3=5WG(3JMVZ(nT!Si_z9E{fWi zNOCV8NYFW5Zix%qRn9Gtw?;yzciBy8yy=V$I{d>)CV1#>F5wB5IIw#$JZST~FPX@V z`>}?$#+;5<6rO}7f~JH1c)(=Si2&n@%U0SIs%22nlMWhnqDb9+wbHDcb)-ID{;Xuf z{RhpHM%?97^74swcx*f6z0cjoqj&9;;mTkDs{A!0&1sF$SZon!v$nzOV7def`z8_?-=G9$xHg?i| zK?_Iu@u%J_8qjgu|LXwhf%_;Om`JQ zSyr=`AIq?yAI`tv-QcjYZmLnlY=Cxv_S$Vtvu|x>e|NJa-;^vTqJiIl78XSazc3oy!S>8Qqd#s+=h zuI{}B+g&7#EoG}mGcf47&ka6AfZdH}qj+hU#27x%{eMoFqy%^4Ny8^udA8qv{aK%{ z7CzlUX{C}93$}TCXYyA!3urZQ?lxj7$WEtpi5Tgz9f%{)`dpqu)k<3Lrb{zNCvlpx@J#d#fT~L?oWIN6p*`?lGba6ME`9vtI&1PQ~ zHR!G{Y&%*QbstAOR0K&|&lGLSI~mZ>;UAh9mAjQAH!0OHjUFgc=E7$B`>%GNCQJv~ z4v_xkQuOR@o*pI8(cv)51oVSV|77B~?rbMwVM3Q+Rf=&zH%>jYMA#0nL^WE+Ju!v_ zUA$%WV*(3b(rqe|0^^t!qliL(?;tA#j-IfFq# zSDd-^S_0~>Z-@b@N;ryH+g^Nq_GSMT+@LF8S_~0(Bai~<5!bD0a?z^jXE%*wXMjrM zQGI2_w7mqrwb4N13P9p+*i>3yA@-nef?Lr0zrFu;5reyUQAjIqhRxmtUbJ-SO@ixg zjy)5<6Y~nX;pfK=6HNDcrg)_=3XXSZbybr1h3zqD!-rMV1>K!vN*Rmk>XC;s$Dp}B z*Y72m?i+04*o2wSXH?K%-#YVNL3N*JbZ$#Kch!CS$mEmZ?R9?ccg)$lcdHVh!&}wCRq2PnIUIZUq`* zt~y6vO%qutZsi#62$t*bB=~=bd4qr|wH2JpY)4zYb?kLH~Q~ z1J8*(s_17od6;X=rX+haV}oA&RDUCDcfUig0*Pp*DGK+|O6eTJZGd(>_rGQ;x!Z19 z8c8yekZXI8v;XwfaUz!hxO9RZG8Xm=<`=YS{>di!axePXP2Le5?t#s~;sx4s!e37i zMj;S4K+3$rA}cS=YroEp7YrT0zB%%DcM(XqG$|J#bI=c=jma8=GY}zKd)v zoKyQnbvrO|%FEZhA`Q8(KTr>uH;1vn8^QSS+kF|vu7_>{*4^C@`NUQ>B^BEQN@w37vWaYl9WxeZ0Sq25&VCquC zs(Y$TCN!(?y>NTx?7iZ|%|r_B7FAuwlbyY7Io|)NugTB~unuQ)JXva43ZSR2`u;Lu z)qNJy>_DVLo))uDm(Tj@TvG?%ea!Mnv#qlCo5$X}?W4ji&TrhNcC0Cx%0%n)a8pAK z;^|bgG(eaCbh}9~uX4u6LqvFo$g6mJBw=9Af!;X%_I4z)>KDOuiFsx5k_-*{^d?)6 z5V5%H8x3NjrK!vrMTf0FG5&SX8Dbr{*)!zH`@UaCICfV%iTxzBqkR&K0<`OQT|N_F ztTt{Mf>(~}$$z92c>5Xl?KG(#C9%u1T*u&`habLj6JZ^jbw_X=t6Mw0kDMT2mTvR~o&v&@gej zrMS4l53G5hxzlD%72GPYPDf~|OfOpTNu!dWJqPy8=JE~MUi$wOMWTPv`9UZXp?{FO zQE;Kxb_iCDsXtV(-9?*8NGgzRtkYw6ep@izt&+;Fk&G=nLSOUlMn?;*JF9p;y0l#J zBj4ThreH!WZlYCn#Q1&H2kG0G%%FF7yJ$B-b$3MJc`AFPVxw`YjFd{!0hv56aw2O6 z=s7RPHj;+it*Lq@f(mNWI&;lgg1a@v;dFhT%JzgJ?1`$C%MQ6s=&;Zv zzq(rsJnMtoVzeFC+W`CUZSsyeQ&7cS{osC>@Q}S*zU};fnluS_7ew1P9gg-AUhJ*y zxhGzIl8j{lziE2e2+q)lj=M`h-4%o^3tc9P#5g$rH&zhP4LfaX_J~#Vv)ja>tIVY3 z_8ULl85?x_|Ad-^Y4=GPP9>-`qgIOx85MNS9sf3)Hh1fc?G)XA;=l~l3R4BNzaL=97+UDh0NwqIK%V52aKU^q$2Qa6U(Ozm!yL{GfiD0^q zoZ7zf<;?q8!l0LLvbi|`agRqd$C{es^dH@x_u?{dGCb%p(;JK@;LbGZvAG3=fr46q zK2d+erXq>}?jo%LP&xYsq8$x<^0TpKPvP#pm<^$=4}08ut_i!Y&=4Og@nx1j%>5ghl?Urj{>T(sYo?T5+z%-t|#ytoY^>?WmM(%wPOKHF=FZ8qKHV7ps+9O3B0P5Vsi z^&|KBOvK>Mtrmj{!Yf;W(ZQ&Jp0VX!5kYph6?AD(yR-^-G2?=syF-mB4C3z2W};N| zjw0GRL9!tg(HD5G0JoE4#!Z^h5Hh`3pq*%tZf+#@0ef;|u1hLu~Q6=QUUZ|1> z3fwkG&;NaMlcDS`XYyIBXQ_HK)1cR%TAdN5-OVSGDr7%tr)pgI$UXxE)ty_cAc?Xo z$W?X6+#|T|+%_f?B;L|`NVl!=ywSB_+&0n69(vZ<>)i?c*SuJ`byo;lKO_N3(n0EZ z;6P{m`GWHVyo!Ey(_g-9Z>>*1O z6s(8a_+?{>7!~fV&q?~xEan#U@^zP*<4|{Qv(2GC%KX?n^t*mt{{azz`^2Ms8&eSY zRAvxX#=|bGL~3FkbZ3ix-9q{DS^6??hA7&^>U1m66})RY#{vD_~dw4|?6W&)cyB zr#o(xGp9f?5daE0{m?bdy~ry1+0Ewa&4oS3?GVSj3kHN`{M_U61-WN4bA5XEuFuj- zbaI@09Crfr){_?+{~8Rqb%J6ONRMt%W#Q@*q3O}0!sokn(DDMUz3w|R#_oYaZb}U` zJrik)uN}{w0sW@;E?Fl${apRXcQSeeFSYGvf8b_@Y76x>~=7}w*?+a z^{PcP%BCOwCk+fbfBSyBICHJU8tGs}_)C$ddc@kZX^IfVHJow9Q6 z7X{w`Vo(TA&sETphQktCgj5HP-{Mi6+iUVWzuaZU6zfh9(UV!hAQ-cj>2}(0nJ8nNTV1(mZ3qnIBcv*t_TWE5~uN0 z&LxdG{!s=KBMebwTi?QQH3wBsyu0QzqFbW65+lyoA!7zi~ zz2@cD3gS$H);jVGw*dM}hXLj)t+OGnrr8zEW^3gAyqy^sbi3;6ZA3QC zz`S_FGAOe!pMgQQzWo3boymI32u+L4ZvYEB4{7+7fAV3w6+!YmokF?$}~Us$gSC>a3D z>R8X%pfAlxcNT1ziXc)CBaH;L4lr?emqO{zqYMuE zRR0~H5b&VmOKXexgBLM0=tGOvGO81FMrng-Z+z^9ciE-QCJ8O*!mG<!3V#2gA(!P{4l1lU%I(GEXR5+iYsNndPv_2KEkMUBI zHr!uWb_E_or_hlx^wQtxkUq`4x}%l_=*bIz*<64JI&wUWPW$B|@Z()HCg?p&v$qST zZ~3wmz-%2h++bMA*RD8H`@#ql7W948P$XXkdiZIzD-Aw7=~v;O=k24FgWNA zx1DFA+`jL)%IL|U-MzjR1n7)+e%MXqi?a+D`5szJkBO-MZ@rdA1U+ukV`~J_RShs! zqogv$5FRhkj}AKI9Rc-y_|E+v=Dp~#2lWt!2K45ci+&c!D#xB{$Z=766oc+}>8X%n zY|z~=_~<`^?fV!@*qx2ar1EwtItz|LJI)%hLQq}J!H`tKC{&&?LDT#9IbASa6>7Ys zN&Lzq1v>D9Gt9M>_ZkWXw$K;j1uuyxkzIup^g|odeo3qTqXYU zp|NcXnjh(542_!&BkWRP^jKSK8t95&mKjZR6El{};)l#JAl0q{DL3ux zh4{PVKNkcBADWAlEXEVo)G`5G9eHC10e2QRkX5MKY^ZJPcH)%XXA893B1hsLpPC*` z8l!nPa}4^_Ess4au+F16WN7vH>N@0{v+CLL^)+5-d_<7lRt;jfI>#x+`!lbg>)wBK zR1ke%jgk(byEgWk2#j1z?UDr(6| zb<1pwo@U(uz4E>j&lPNEu1l8YuFN&)kPW(-EBDT`!%X4bc$W-1V%*G^g;zJt7(2Sa z8QhbH4fND?w>D{4zJoJLGscdtt*97_xCPJ`2ft%hd{=MYEX!{*An18#Uvj6&!OcpH z9bIT3YgiLNn>UFXuh?xu6Dpoav;C4dvkThgrn`)f<~ue{`;1=nUp*6kiP$ zFyd0bNg0o2+zHSZ7xpxDFlwl6UsFZeLJU=M3hCZ!wB9O*3NSbWpl|QDs*}jy_c4?- zqB^8Q6$QQ6fdUC=0Q9XF_6>(;+^Cuz<1W~N}+GxgTVY?2s;MuAShzjiBu_U*|F zv>FGm@bE2+3p#D-Etd(dZ=)f&Jj^Igr1TZ*4;Ti0?$CWqdPXq)!Nr*r0_L<{EBGjj z8uYw_9^Xv(4hEl5*8!|_p0}BM(0lg3DJSrOECd&KE0|t$nSam@pS|;)G~lfNww=>O zZEQer4H}ZV}&T_>A8&{f}UVzP*Qdm*Am`eis8XsK(6 zxdS}{owfGJ_oN3-rj%S%+QCv$E~Ps=G9>7I`*x}p$UsIRpH!M3v1&RMu4uMVm^W|f zThf~Et(=I4XBej>BulSn-*Li4=D^)|I*y>LrEE6E?vnKIBki71pDGh=EEwerd6Yq4 zcoxkIo_Z(Nt(tu2vY4#sqnt^mlM5G8)%^BAC>L(mtHo20ioW*Ny%G=+sGM}f zlzuFL-jNO@p(CKN*M|)e)}7=+Ix-Y5b+nA4x^~fsIWNnwZiC*t#YT4sxbH9`gihdx z11BSL37Vfyhjk7RC-tC zTytgMzTcf!#-f0kH?D^M+(&@Oaq!eSJfG&FQ{_h3X zNvjWvry2@WF3hR{y1|OuFA-FyF~nTaFM`pYn=2loyBI^z*?+y=TsCm>#p~!nNmMQ< zV0i^2gZ}0Ezq}+Y`wnnn5W%wXIK09XY8npb20)LywaOXv*O9M{kiMh5s^d*~V4Fo;+hc)I1>|heR?^Q;*OoLPTWF%W? zO6-i6UABGLIHykjKQTQzmNXlcTUjwcPn^1qxy0;bIw)*H3vGc~4B$x)dg+4+lb_-w zV3I^MQviDnvkSWacKdHB0(P<;Lqg$ZoM_vjj%Ros1byLY2v$s?uF8y`)iFB2or7{$u_x40TaLg2R_Pzf&LXe%99!t@wQhC@L+nofK!9=<`pVBx_s;h&K#573VXG(9EqK#qwo zi$v#DsEXJNw=7kCM9NE|O&!JlBT+h>Q})A7X&&~~n`S@Yd;21dMED;iuKM;L?|Z7S z?%UxNR2vk5W^7$R$L;g7xfkYp_yjaUkv1h6#p?ow1zk1vluw1%e)O}GnClfBv=v-} zHh*^0(E?ZH3Wrg{@aaKQ*l#g5=-(f0K1;COB@nhHFp*(FGd-^vFR;!!P$1W4Mg_g# zy;qH)@a;95;R+Yvp2@hNOHMh~2*DY*NVxAYF6e^4FENKQz89rfB9!ih|JBFoO(Qj6 z-!LZV729+&0l)y50~=y`#-g9HgMa24#sm#7PMhn-zBRz>d#>3O zg83(-g3i2aq2V+DD(#&p!%xZ7K5$*I-JvGV;Cm8SywZVUDzC+AZycXFJNc|k0^hqP z54JH%wUwb=ir=2R>VRGq&6tdS-}>qS$LX3K-UU>++cPfcjy3;!y&Vig4`@|LYnSpb z3=I0xFS&08*!K!=F--65>68h@vK?W0d#jJl2C^CoLP72}ABOUfbNrKEOMokniaU^{~u2m0h0M>Gm@0JihF#)0+Zz$fS*1C&grFgWPL zPj)ef;{hf~gzDVn^dzy1yZz7#SOB%HKrbnj>bO1|l$}Aqsn4s&vKJ*vC3?Kt4gON3M=x+E!0*aAju3qO%nG+RQTOl68746!ZXMFz+9H#R>-c{au?IFD-zA zWuiv78!)G!0|up*wS!X_3f22+<`nePW7acyqe0iDguF*%uODyhblSDTY=A*iwILeg zp{DxAd|Z1JSFtESANel)nxF?*r76w6UP`XmH)V}jOH{b2UXK{dln4qG!m zxpNn@Pp+bd94$P17Ia0N%cSCR0R#d1;jg_-Y!mA3h)w$gyd4_O#2TWy*w4DGbfDY) z_Sre@7(3b@hr(KwZPdSSypM?-2ha#&Sx{|v<=%Bx8si>d^o$ggsy)FH2JN||@iY-a zfO)O_%|a3H!y*Q~`@nq$33`C#4lWSo1)E%2^c<=II%d%h8w+#*lR?RddD=88d92AC zgKqrv3UePJ2*=4nQ9r{RgYI_9+=GSV0Aom+Q9mP3w@wt#_Qk8U#yz>80Jqo2(&kQw z+tSQD=noq`cvJh^P$hioQQV7e0;zt?;5I-Pb$QifI0TVBw1qBrN#^wsh6ero)rP%< z{Q%lRwfM~vZkzwpuGrd~P6n9l6u=4bi@3J=zc;(NS+=T)c}J_Kb`ID=7!SdYI9uKe(NVv;>fab??YFr#D6S{!j)k0BR^sZ>VZb>&3i+Zgk~I zD+F}_{p={=JjZoyLwd|+yWcI40oH7@v9SX}?hn#R>T5tn!tSwqhk|KsMGU)t?-x{CD z_Zf}nA2#Xt9kyUZ&>dgC{sZAPz;degHd?%Se(uiRG2HUpksk|s00~nrgtz~n&0K?C ze$oNE2yOrg!~M=gQT{@i^ecIyfe!m^?*W1wVEWET)154hY8%Mg*IH(_rPc1!SBDDi zee{2rWzdU$8Ccs6mMQOx;#5iy6IjHGe%8&Lk5;*}Op8DB%W1{-miP0IwtQYV4uDN2 zy>Mp+EVx;qGrns!chv$YG&4<`Gcy72rrrY`wC}+8-Vx3N#23_~6H3&#GAQUBn;vKq zp#$ig_0HQGEC|qUUHh6iXMlB6ZF9`)RdxV%-4naNATkKx^}xv6syvl>20if7fBaXV zgRCD?VRt@bf?nJ6K;u7Dle8U|PHll~hV5<6WxGGNQWy>}bn5C|>1w|`vvRqh25|mt zm-r^uGtkib|K3Po14zR7^O;mio4B_b9Q3${?=e20@1-fy5b8z$)n{9hdTII_BZA&| z_={$)`Idqp;vo|{*X9EzWKLrWgC1Rb*?&X|zFjGS^@5~J84~o>JHIorCf`~hko53M zgq%LD1&1;!=$QZZXb8+`+PME0bkuzZJ*n$@=1PR`^%#r}rT>bK5N0x~pv@=uFdHG? z^Hv04t??r}XkI}R)1KHPaQBs8q73cl+SaWvbdp(ej z(*?tvJO#gsr3w1P_!pj(o;yo3IvXcys_V8i-~BbdtzbH*UUOO8wv?1GOu23A*`qTblL6e-gOVsq9s!{zVu0?W#~uucs#!=$8+#V@|iQ$@aAv(tD)3 z4yK1+kUs_QLZV!q*X($Kh{ShRkJo_tSG~HRXO%d3iW>pFGJBLU4Zh zd=xddJG1!#U6%jqCFzL&i#JA6UK^?-jg+~on)rgd0lH|jEzGU}89=@UqbZT@MgP^O zQ~D^$UfQ-g>DYUPXJ^20LRWqs%N&BP{p_)q1_q?4nd-6~f7))Xk4@yy_u?yEhUeH@ zLE>x#8V5RJyDcUL<}n`DBX9G#?6AAcNxN@LAv{K6GwWyQYxJixlb{=()_Hef(zp2) zOp3at60wjD-P=LJ-{kz zHA_xoZE-&T&SjGWcYZe4rLZUIx{sZn5J2bg$;O&=!V$!V@c}*c_4(HcqO&+D=tFlv z)DS@jfeE_VF^8F)YG+I;(3)z9Da>(<33}%j7Z}Y9H0ft3NPE(Ed}x-5ggdKdm={l5 zmUWN3aI?tL8Bj6}?csi*I%XVAXF=+hBvh{#upmKmOSk+jFq33B6yT{02>R^-+s+q2 zXC}#Wkm!XyG>2b4+1!+L*Yg?dwAyy4??ofbZ4GBGDfA|0!ycZ_J#I6*3ui8o>aS#J zFKxR$aIZOg^c`d}hKO!xP~{f*NSxs{n1>1U>zWx)%P=`BXH&S;5Z}M|=Em*v9jFjq zu?h5SrX4i?%gXof6F%JsDwh$1G@APkdcxSAW*#~BJ=CC=buc4V^Nl5Gv#dL>zHzF^ zlBAFBWC&GlEBq3>WDBkG)~CDf-aQ zzGZOG=vvijyY7CM$DZgW0(BmtWK=&xYTM8YuKRMa06I(21mo@1bND&8{Va&iIuArK zbw{ueL9;JLj}%bnekbzUJGQ-svxk2+TmXHo@$?F6tXH}@9cgG{f+D?CqehL9Ez-SS zth+&=eZ{%TKsV5>kLmRZReMP_U@xQxfBlVd9(`?R%QO(39o45E_Nu?ervHcv=e{gU z8DJ`L%7zdzL`(wEXHNW=Spa-Rw8|jk3v?SqHcrMS2C@yW<26IO(y7=(NBXDIV3p3<}2c00F7ojXGYHmLYn zHhkk-b--?7?k~G8l_q>ekIRT(*KhW^(2L~{+Wozgj9V61H|gPG9d_!@$e`0^-E3TF zUvUS;dAKRoi!_qzqS;5D_K=?Xb+_|HB2ZL+LkipwJuufCr8JRjIz`ccPOC1BYn^k& zseh6d{9BrW7G~th%P437eh-u$bZGO4LG5aQs$Rr#SvHfP>^;6r10NF&fZl%6dZx^S zf3>HhRT2#aT_LKhB}Bwo&v^k7`jlNYTV zEE00CB!t`A7}#SS(303KluEynCGo#JgsB1gPrXgRPa@P);cH&~;kQ9qLHC<}kBP~; z<6}@u@ofRk`)Ph!hM)cW;K!RUS zB@jp-^qePN-$10}-h)QE)=G;~eHnW+fg1rGm$~00dibBfT0DI@(?uo(#S)`Q9YwWG z(RL$m`=|6Ha1;IqJ8%;`=G2n(Vk!#?^zR*~_LE-tH>l+WrC*?~&u8>uKr=T3y4mzO zJ*64{-beXn=z$RJ(cAqP@b70M(!e3qpg)x@-++@Z1uw3BjrpI8{#VxW9fRqjSQhHc zsr3jEJ4{Q^1KxPt+SJa(O<-vK{}qhb}P*yI2fc8JODU^uW3t z-LS$-(zI9q^{S3a7NEQL-|jV0ru7IWorxkl0w0Tf(m{O;G*E%Z^RPTL$gW7>Z}3{M#X@Z#{%=C)T0fUoJM23O^0nfu2H<4;&OtMl-Rn z`dm$NOe)F0&=tk-R6)VVN5}N@XQ&rMJ6%-*zS4*Ad#Ws#%a%hxSuP;d(V1f?M@jOA z@A`UGHjZ3!`Bi7sK9A9(L)6!vojY|>HH8N4P&=ZQ3M?h3kZ9?}v?-8oT`HdmM@OZ? zDB3@qj+;}N7WzVnOV9zJQzsJZK>f7ApdG5z56x-)bLY;Tl632+jtV41$3?TLIBBnv z480|ccV1H&0N@y#aOulgYSR3PzKov-qu@-2e@mKQn@P=#(T#e1vxsr;LsN>sRq_jg zDd|nduvW|ubv2))gZxZ3#0BDp&|?PCtm+X7bBC_2{kbdkrxOZv&WdHC5i=C3kEYLM zI#tpW^WiB&qm3adnrVJf(wD3~d@SFBA#H`Hg3tNktKbV$psZ60ens4QBkfby1`X2J zpSpD~FFYQsBDL_EX-$C&5b1|bJVj!Z=&MAB)XU?ydeg;ecC zQUzq)jcx3v6U(}FC-$SW!|^;-kE##Rqb@C3nv4}cgNMcmBdfr>g_12AiJn`cdEISp zMS%I;_t?Q)k};pFPDbkJq^7jJ@*gk#+#Wk{i>)A0%SpPx4hy7u8;{P6#*4Z@rmLIg zknUmAr;5Ik*1aw(75zjwWTIZ3Qer?3Tr3>Rjc?ARX3?K$2;#t}d`~*zo{&^lJQ^|e z1cy=~jv*ncFXMfb0$j~F81p`)N=jlb7qhX)4y7M96TkGs4!Ff1Z40$P2noG@3@PeH zO|n=jxm0QrnN9U;y})RB&F?;+l(R9a){OC~rY73#7PLSk8ja9^4Wlw;p5*A{6JtG2 zKP^%^NxV;Hr^nKYJ$q#=FJVfcP$N1T&l}VvCnTpQQ?q0N9TT19ffjsncq)S`(4qLm zP$mYhEM+M8;KW#{CabD`dq}Dtq^@{Z^venKm{fQ=^}Oi!YK^v&d2xF>(u1 z8G786^f}fLqo4wB4Bkg#^a6TQC{Bo4*HanqSqAS@EPo}~%07fN3o{g^ zDM6>ebibIc){ddMnhiBZ$)?fKTdrj|>MnWcv=hiupQsC&ST;qbLx94>6kK4D*HQ!v?-M=R25iU8VA(NqB$@z6^o3E(h`v*ot0{>7TbA}MmUs?)~Wa0tUrX} zvqCLdrAp(qmC!I?csRv!mK3o+ctDOUdbRBkEsP&k?m4cwp*UZlhXa45al{+K7f@*(e)qjo^J*wrRCg z8Tt?^Xkjs#Ox3WrGl>pa!l8^c7pPPMIY9W*Xm~fa=y}l>D_w6*)i=^%V0so zkKJv>Pvh-yJryf{1cMo-HLG|K5Z z&G{q4Y-gv4aT#po2o?QJL?UJ2Atp0Oj4hwRGvWwV6hYXYSWSf(MFFohw8r2qO68iC zL_Z2X+LklI9P-D?L@mmpk)2~Jj`&AWZ$uE;S_;iXBZFJW8;#OccF*=oo1vD5DC&%p zLBVT#Mb09B3a(Ls6Uo2#;z0!*PDs+|mm7n@WQk{{;xv~kexyJJ${Gc3TN`8_pHN98 zCInQh7Q<$f%VES-Bt}L@S2)O2(9aUjAX|e_3|0hsiYytarProp@hWbY1VFjB%8Q9c z*cio1ly+zf6)IIr7hKYUzel35oW=v9rfJ5LpKPpP=T3BuKANe`#Aec>Y1_Nul(?f7 z3A|S9`6Zn@(OVz>A%&F?^5aNTXK8v7W=J2htjpLi6Lqo=`7vnG* z`epT9n+*M1S}iM%P2uN+d5aTaKpLvE9EEa&tpO)d)@PH4Qj^rPs2Hp|*@7|0<`9l! zrH|F7C{Rfcicv&UUHv4zR%Rp=SF7FF#>N7Ju30GaC0Ve`eoL*ztca+8pCP8S+^TbA z!5iqo4v&2-?xX{VGI)bHE!9v**D?p~z`=&Jeq4RLE>}xYHwpx+C`2MOJC?{N#^e(X z(ahLJk~+3V7(V_cWii+vI5^dit%ZiE&zVm(Q5ph0UZ5< zhu&>K?>@bIQ^0~)={B%;|9$r9UK$fg#pBdz6+p#qg_fsujh;)@G#*V!RRi9VNzv!^ zdZlhrl8;QA1h~uA$Jvk6ADcw47|;SvmX@SY9MYhk6?}Lc+`tN-q#Jo^Q7qWSmc?vy z&UNlY?iRd6(Hl%lY>mn1(;k}F8%idOVl+kTXcZ+-Pu9Z1ZM#e*wZ$sh-xU0f2E4=^ zk=)H5(n!jL>1Yyhm`g0nfeGz}ml44pI~<6Kmy0#Vphl$0{PhD74lDSDo>CL2s0F+{ zWBQ7sc+ytESO54XR6eYk6(zh^U?6yx(1MdV-I^*3{rk0vcrY0Pq(*spp8n9H zN9#j%JVuTr$%S?s^lWTFXuGvz4>LbRwTTx*<$04>YGx>HFWxeqv&d*N=*bC3(Q3T- zYXn;SJ(>6X&Eju#?nK6dPMws@!AwDiY4=U%Rdlw3*G!cCvHwi*Egydxf{kUC><4zg zWEC;WQpM z1=$fqRL5ZAWF}&>)uV|xBdHhxC)J^ojEbs*KMEI0vZaIGNTKD-_>!Jbgqxhh2^sIm zLe#ZLF6M*dk(y*=Sn1OUGt#O{CcCYV((0<@CUZTK%pzif18Etk;@*(w5KDIJ1E-;Q zY%t>~U8Hoj;w%TVm)#KI8wQD=gXhXiK z@K@BO2z7_{M}@zq2bYVRu+OMPBMQ8T##j>%dl~zqf?nkJ4<-v0r@b9dXPUX>eMuLK z29l4oA~d(kEhL>gk-?!!<+WQZeKOD#PM|n>rkdY*R^A~ddu2=x8>VF1xG^7n>>Sf^aCOYTLs)fYPjxW2*Ph8}D%sgO$fP4o5?6S-pU?n# z+mh|TzPdP=%E!WPqFjbT@g}|$#@c(TKX%Tjz&j-=cqg;?%@nbA*(uC`4ot9LC@?T~ zrQelx!F*SK;RU_1|1JMz_7tUA{iB~RdTykAmw%%+U#7v%G)m$-EAP5`>uDPTA9>FVMCLsF=WmQrIoXdmc_cI#a#`7|!=(k`_CtUWC|%!js{H6F|qqfDf) zx{pzHD&o@3Vtp?ZZuz!`sY_9`qz+5Ax4jHZ15K}D<7%r79kp_7g;pT+t>VXJ38+bO zl%ds6>u^zZ7%>+wkm2~1v1#95Pz#gKhP1+a{ZaBL-;&8K$xczHC=}4mh!rlClxH{z zGBrzn^p=nEjmYO{+0zG?{=d-HCv^mmJm2h;$+2kMXjCchvhK8nXqf~)Uo}1f4>Zk_ zl=rFfUH1M?`B&N&6d9DVs@V3|v>ht#p7l+Pp98DjG&QL;<@@A)Q2s^3iHNKEco|nr zhihsF{r;X^Z8v_9)VfyA=A+CR2$QLe-d%`~+y zrG-9JkXLFqP2Ph2QNgmSK7E4zrjE5-oq^J=|GFH|qR04eX)+?XhhF6vtoZEk3* z)3GUI%4JZR6F-&G<#$h8F~JfxsnEf;29%=+ZRiM%t6w(S-bz@lS85h|_lGoC?mWJw z)z*~RFZVSHvzAI$oJE9bO0q>;ZKo(gK|9=1fYSD$L-d~)1Tx-@Z}F8)`K;KImvQ9M zn~XyvC5hGI3H*;WsQXA+8z%3REMsXHrZkM>x0|9RJo!qKUHJnpJ!Z$G6bm4w!wCh& zNiv19>|{dvHF9d58n(Yr=6q};gOoNZBbl8-$1t?AWaSrnZ>9E2E=^OU7%0}aTWgb2 zWRkh!3`Ljb%BDD$wx}*rq-p!sl#hop*ccO!6t_TPBX4^APR^OgNmXe*oEKTz8trXn zr81E$wO5p*=+d>41jo{b_-JYhuEfRRj;Z`@8c04Lb!o0l{53;rS~e!5EnLZ*EZxc4 zwon~9M%4P*`UjD3NXZj45x{@N&(`3`nl4vS`X`-cwgIeXFHT=u#jI0@o^5_i#9SGR z&#okCy7C8UUrmiB)k!Jc@Ssf2ei=FjqFWHPbl-!Lr7L_DJLl|_p_2MeDo1%}qhcfy z&Vi~VJpILCR6nXkxv$=aw?gR6j*el=lgiUsY=Yuy@DwCsP!hL8>hhEcR6~Xit+N%* zFGPK-<8i848L7)RsBlO59?ORnEp*39RixmZ(`_WWu7pX0l(q_ONI1(1v1?DF{O84)Qs-V?ki9L&Dtt{l zRdQQSrIxqVEC=cRH%M`E%2_b6fC`fH7%Z_gw5WI;g*{jK+imhm^LTtpVB66=ci4Bs zCH(vTrZDSYwl#F+(Oh+EOClU69~GUAOKc`ggM~m{7^`Sfg)ffi_-9W$%Hj+M`cb#YQJ+)vsbXk9|b+7p>IeAg%AHnVMLh4)bj%eS;O!q!*BQ4{{k_e=R`D%Gr!E;eCf zpnfBsR0YH1eJiU1OYDtT`ZO$<=!P<9sCqzAlJYE>B}s4d%74haEk6Z0g5Hnn==UTujgozr&;NMgukUX3%D4q8+7;rB%nK0biAdn?o-NgaSB^Z#qZ=6c2{DpQ!97H zx>o!f0zI7qr<L@=eW@`_CuxO1ik1 z%1Yjr!u{c0^&D5&`|&AqkC?}t{HYzR3IrBNY!hkvsu3yvee0uP_NIIx5ZgumU0GY9 zny8dJqZugw*Y?=}@gO`d^>2P}9?8NrRjTn&Y#l3nP?<^EbJ|4}ioaU$XY~aoS6<;O z-p$nVZT(ZfkDQ?cWzQB{o0`m+q+n}Ly7CA~#*Mm$Z=4(Kr$m)2f5MX)Yn#rp(M`(N z%lxT*(lJ48&y=fQQQ8LG*+`omY@24hoarf^x6+H^-?uuSD|7gNfVmQXohk{@mQ(-Q zxMi-wqhP63L92MC*?;wv#;Z1T^fwcJ_iNL84i_xU9MCOJ6Po_*|bl19-sO| z!c@p9KZ8vF z7u<1`057GUb}j!03~;$Nku_3sHL#?3Aa7CHG7Yl3s+<(n8W*yjw3XfD4?`c2sH_R^ zfT67pR2o|=^{BPh&0#~?T%wX8tau5&YlXkiAXdDX+rMH`uE zow6Hl<8rCA!FL8Jd`QVHkhb4Utq@XO^w*%Oh55Ec=qk@mnLsCW{k7K6;q%a5LLK|L zFdw$Q*BZW2M5Ngu6GCbQIyL66>R@Yp;1q-sr~j|8Q%6OY|A%?WRLGVaio%&x@u^G* z)X%jkPf^Fwd+4bI9Y&arm0z=4asM!a!Tn;76=egx8Chb6TB)Sewc_8@8eH+O<6~4B zv@0r}?OE|N=w8JYsfc@T#{Yke`(lgYug^R`MF_ACCH>|)wq;H>bQn_()r(DyfVOkn zWnjFkD8(%)wtbDUAA96aa&4ND&XrftJ{4Ec@|$se!KG-=ZNK}^|8DzJWPT{4d>9g@=)k#76$xwQTgq#y@ONBoB4<(JL#ke)czn27 zNCy@=%u?a|ri3b;eN(RN*hXAaRE1}~9PdhBm1KKm2=qoCw}JJ*6vXt4Mdm3gMdZK& zl~#{etl&)QT2wGZU1N)dafO=tUrk3aR1GOp;Z(Np!*(U+@*OjuM;4r4Y<$)MS_BZ_ zE9UO7+TfYfr-~vnXYYQyV!q(OoZgGLe}QUwQ}v+Mlf2D%=tf-oua58?S|MLk*MYB~ zPQ2}!f>op-t;WZ6lkW!8`jT+AR{*&vq+P5G+UR*}YK6;*#94jlw-PNaN4(WGiCq<@ zQqji?G7~BcLu6@{E;ie*-i2F#CZu#mmFJ0*$N$H;<4k>6} zO)@rptwlb}msEB;uk=n|Fw@!nTMqn*$~kaoeZ`5#;_vz3lILKd&o%^c_L8uh3il|f zQ~c$3Ng6F|-1B2SpV8}n@gZPfZh|Ye%<2HkXKNZ(9=44Y&>tY|w`@oLhlB9O`K~NKPsKNt9Q9>>a|&x;@`_8NWKOuH+C%+vGd-Lrrn#(* z2{w+u!$4@URP>8{Xsmk7M!72#_eHLnyi>zVd|_IJ(pn64brZeclg)Y8nrTRiY7EUR zaJGW$oUszJbSZ94xV30r(T&G~61Sy%6@LQyQt_m%th?sx3!XF9+Q&;GiGwM9JkwGX zMJ(zgjg;@a*Y+q`33C(vr+JH2Dzx5@Popw$C&@c64pOO8T`DR<+R$p*T=jM_9rn}3 zFVYMB;w7xUD%zr_KryuSmHhu>@9n$WHj;edznxFPd!Cc^%$~%KolKJPot+t3k{!1-f+15tF2ug(FJV)P0bu7pbs=z_rtaXO` zsr}g48tR39yF0=W<=#3#(Nt41)t)2VL9l*lN%Oyb6y>!L@>-b+zGj~69ZuK`88l6v zS;h3yRt641UDgwBqHbG8Ms%$&5E7P~VZy%o5_xa-b3_aL|95P97)LYIFe zrZkUtJT4>sABuziJ@W(buiRztn1c%OhvHwCK!>=H!E06YR0ony5$!}P-|stcOGD?#{Xj_xj03>;8#_o^<0=8! z`Wr*4kW&|Ntsb?0oz>c+yMJlyXaDoEV|2VsQ71VY|GDgru7d}B-vWTl)mu3)qbnx z^Fi&k!$lqsDZxG2xwO@(AYbqFw^EFGZT*d>_FsOBb1dBZ=T<8(Kd5AsN2Yx`f{~eJ z_6kyFUJ21x%%mkQP+8Us2w{;l>o&LlXGxqryjq5q+t9z~0m^6VyT<;erMvQ*^Wbji z|6UazR6lLG-nc_g!*68wYK<7M=aiR~TbM56&yi~HgTLDOt){T))#4P!0v_*WNuJsi zYNdCj-h#Ecej)4Jdqa)aPK3=iFEcpcu2qH=6^eAv^U=Mx+>v|XWV4*a@ZT5~+Q5hV zHpPA$#zkE|PUi;+f&wzstzmzTWLK->Xc`vv7XP*>jJTAibre;Z5LQRlj& zgKZsuh)W|(ux61e8}KA`P&BoJiPz|V`fI!JR^#x5&v}Ej;Z!XUtQOC3Eqb<@pay~F z14!o0Rd-Y3Q&~&>K)jzS$LcC^^Ipe)*J~qE{?1Z4kyOR7j zbS9eOUBAW7r$8#c1yQg_^Cw%I?>7H!3&gkzec^IljBLZFg!Qhl84+ckQy55l5~9yq zlMuD$y5#T_mHQXz2C~Rz^D{aA)SPggTB`^Ykn>BqvbN?Z(usi7MUJBpExX!sFle_w zmqy_W041XJ_;WLvNCe4uMLGf*YpMmYdEJ53)*tVW`!iF}m5P1dZQ^!bVi84e_wx^&*`(70vwZzD=TG&JPmo?@^i0vHI=J3YAme zBEN3+GruFljh!Bjw-`GgeUQE>S)d~4i-AtH^~l?nWWZw6_B``Pzob7K7^$9eJXP^-G`9Jo8c}Y)Pa*7$Dg))Oq)o|2&(p;_qQkBo_D9%u^`|`c z2gIP`%@&{#mZsmWmi2mG#`82oj;nl{C2K0e?FB>ngT-bRAEAU`$#_*SN0o9rM0LO{ zr@bXvsdsT@JAbKe+fO}m-2Q;fri)QroUWDQ#eQFaSCwf%iDT$8lxm|$e5JN*R1`lMJN<0f2 z9dBEf(J1y4y=Tl4iU1^8PjgN-V}Dh&T;Qf_k8j4$<25p8#z+CEiQVGOwC&Id?#ChL+Y*{4QRo%*6I5dM>Ae7b}?8I{KYeD@JD9!zQmj{ItKQCFovuxX)%A zh}N~71QyR#Te%a>FV#<3=J7Z}+DiSK?`f(1afWcwDc*-5&H$=oxH?9*kc2HU+vJxx zOR0)hDFPt#CqRwj>|FxY0-Fz&+3>{amfl!J#dX*&KOH=I@|3>h zPu-39DXoep^u5El`^vY$Gxuqap>4p(K-JjbDdY&{5n3-JADT&;7NjxPK1#K=etK?G zjB~9x5{W0+NvgwYHntV=+8Ya+l$~?hzZ`1;Ta%^XBiJ6iA?4#ptqNtk=&yQ(kW&BX z(Sp>^i-GzBDIIC;keyQ=M95G|wA85NX3j*D+Uz{hXdQq@6}3|jCkUrmVymk8yEeP@ z@7>V#Up=riibs04+pm#=`haxa11-i7dZbqae^<+0{q)hJZC0c~p?8o*Jvp2X-r*%> zW|`PxZ!*E34k(TCS)3*5j0W)Ofc!5Ln0+b>G232vOQ(MGeLIg~C*-In-37R}UdO9h z71>F89^WMOuSdx;DXI;JE9ldth^t@s@jw>lLG>fgdHvIzo&!RBDH$gYm{q&kYhW7| z8@0ryxX;4&HgrvF)1YEwS3WvMcICUVvdu@Y>0C3j^;+;YRaUma)|Gatlv0^7Zg8qC zdb>4l+BeK`^Fxb0Zhzipkeh~0i`@JYYLfflsy4Z4vDGLy4cn}8^Lx`QH@`IOa`QuJ zn42$N%iR39#WXj~WVX3!-7wD04|40=K-A51^WC-2%{SLTH{V(;bn|n&iEdhKwb4yO z*GM}Y|)DWub6Z#ooZ!Du` z*i>&^wHS-G>mTBV;*0T3U~tOGT(WDps=YUKx#~}?=C(L=U76ObU=EsNBAZs#pUf%N zILB#Sm8LU8nUlNA(@fsw+Ckt<*}WwKC6`u!>_UTMp6V z)f_GO6616}#|6=L80H&-+I&DP@mgG3YaVO1E-6Rop>lpyoB;4huarB7{SEZzL6Sk; zq!~X_A}0hH3dl{fpsnktbTUeQfn)FaXZQ=&3*BH)Iiqxg;e7eoXHV$+GJ2mZH%k=~ zdOFAaP&3kopFgLcaV~a#{#!c9ag^7sfErCE8w#F$F?ja*7tf!4_0{vQv0Y-*{5Hm! zoh}=+Uk2%MHbp#|LfYsO0ei@Lh%=VVG=WgEA> z0#l9`jGP7BY(?fd81ZYKypOYs;0og)bezGaUCB-xEfQ?W*s7- zj=lG_M34`RFHkVE#4Hvl{VV1M{8raLYWPrgyql?S`{`y?uv6v5;13X~DW--~Fp-lW zr_5aoTwtKhar7Qi^4aq*Fb4gb;zs%F^FMqE=~1M<D4i{hfb8jevChV7x;vZLb3=D4y^=hQ5`BZ} z`AI26HjF&Keiuh?!6S;ko@$qQg*);4;?r5~0UYwV>FpU-@WS)+*}*C8B%IjJ^E2Ho zcs?hS<#;xE?)hbToBzB>JU{%BtUX^*?#=TxU;9WMt+gDEpvqAT$peV}Am+PU&u=&z zp;#ik&*XvhacYX?>w%+Hu}_XJER-5JeCJWNxV?xo=zm^GN`}bZ)Jv$|z+iBiK(nRU zEo%nS0Z_17xjucOei|>x6^r$WQatBzj%zb=xw7VT8sl2r{F0Myuz!(;^|wf~tn^84eX@wbQPqv7d^`|05H;^Oe2^2>3&WF0zt@#34kZx6?ZC;O)d!;{wx zR{wGM`sMIs@B9bvkAEBK&gxLdqt|D9`+xTWjrK;0=sM8oaAc`RNzMw*^!M@J-%ih) zUxz22ujhwHhkK*LMr+NX@$i6YBeaL#U!3nX8h$rCIXL}pWWKA;EllHABBJ%zmv4qg zWq<#;7}=HwhcDkKzN-O#f3|n=&C#KnLHcxBwmltK}(E2V)kNaVbpv@#35F z!#&{Hd!=Uca10KULurG`aZ9=~!RZ3m`?$qchB8v!VjFmq*&9v!;UXzWi|S?+jsrs& zHj??2-{!C5f`TL1oPF^EAI4X4F(&;wo+a7ueh+IV-DFeb7??)r_Oo7QMJ9vgq4 zwnRU|mL4MXMmcl{Q#sLery#O6&k>!d|~Z`dh8a9bo8Y zQ#yfEDu6Jaf+T-~}mh|KtEc4`+@Fzh+Jp#tJTsn3D5(`{jr!RSJi2wO`` z9>kN)6&Q#Avaw9OZl)L3tv1VbdFI~MlFs&BZD{j#imq)<{c24hDx-lD;|ldrszJ!Z zl`%rpT{!hllB*?>)0!eCnZ8z{lwopA-#%HkAyvpIQrXNXAx3nmvB^3JQfAYKCP%xT zD%>#BA!kTEexQ>Bx=Uxgchuqa8Y>UcPnRdqP~Rp9f=kuEv9J-8NvAyh)g2kuHejCM zrSP=^cc3x(HP1I4MjPlV7vJvKH9h+_b`d_*ok^(OxO(~{ej@yl)N!1ZcLF>2T)hB9 z$3V{^Y2c^(?$A!e%MIeL5RQg$Oqlmr7H%u8i8YUoVz^iQ4J|rnW-iHq#z6p4uyKZk z8)a7;+Kb@M!oG>U=`>5OC^NV+y_Kt@i=w?%y1HGa8+F>(%%k0mG6YdC zeBnbI*pn_9>Krv6c%j~KP$)&?e)?F=?zacTK;CZ$-$jeJ_tt}cDsbQUQNsY$hv8ek zA92#7pkD58BpzkfDdXMRs1p>+BfT+u)4h#|y_rzzw3JotK3zHQekKX8CX^eS3Q=n( z>h1k>1>Fi)`KVZ`p!xghP+(g|K3OtpDUE4wm{Q z{{LHb4TB!$YQugp_^YvFt4;Ji{o=(Gw<|>~!D_a4G4lR>lwDOhMfMO5i9?*9KZc>N zhl~50M>r?as|jqvn<8DL5o{Li0My5+kGmU?4dyd#oVPZYY~ZN>3R-Kch}M+)XJg)f z-r%wB-VIhbt1gm2b753BT5Dl&5^8n-7PTc}?h_5XC{md^cpb1oU7J4m6SlKRcM4gv zPm~(N)}cS0ZLLIu!{RPzdV4pvo)mBGgg zL;XFYn|G!98#nI=8rzaTyX(0`!+24U&t2Q#wWeY>0{PX;8&3dd<<1N*40lzB`Vj#cWK z+3vmN9Cvha#=8qeFW{)7H+?Udl1%<@!^S~C1%=N+{Fo#iP3Pa9ZDF?@LsUmP;A<{P zPrKS;6yw)$ZS9xKXf-o-BwjNk#Q|J^=}Oc-!yD~Yn}M~TD%`Iq*xAKgU&fX72GOeg zt>ki(k@NYxG^40NBejSz{umdSzF!z>ou&R5>q?A?ioY&{PE?1x`tYE75VQz|I!~@h zNNGh@Kd64H3!Mg3{lcxPD;Xw5q0T92KCcjXi zhyz(Ym*eRKUmx2RP##?;ATKoJv*q|MMj>Y50epDx_+r6QZ?sZf z7qqNrS{NNGog&R#t)TyA@vl6na988Z1ZaUM^IbuF5PP7a<@5_Ekb#l5{L;0Up>Fu; zGA>YF;=KVmjI}A@`^=bXiiS8`S3TkhEP*-)fB!{xtlDZvZ7=?6$1E&qF3F^YAYfEQe zk+AfJ;t!+#6fcq}T9vvRt#MeJ-$JS19rdC3!>HF{$A?H7fu*~*bZo~MMxm899cgkm zRLZb=DJ6}0N&jha|J?+bpWPkkXxY|-EuK5#EpmZLQ^~0I)Q$ul9oN!Ru`1Ue&Hb|b zr?K-qhi^Mv-Ai^J-L!4Xz61(&$3(LYbv_3_O$TNeIPy#>e{1OoXwc$46*XFEa!u@j z#!t;mmlS*MSUURsW0frO70?yNz0gF+r35M0g@8+{A&smOzA<+OuDv0K4;m>z>e(g` zmdaozIG!f0jbo*6rHfzT)De?*Ak7mlK`iIBe4OI7ujf9J2CWFK_>Byoyz3Xb1-BMB z89`FA7;k4eHKsXHcyIRB4C0Rn_FM3}li_lSV;tE@W5XLjpYVz*8 zc%_095gaIbW%`9%P1EK6db5w0n|#M^T|1ub!!gWFU*)H^eFRgF6@(QRa35G=z0@!F z>57wVKe8B%RoPI6aCOjzh{GMnVtU@flQ*QZNsFX81nsSm&5ZqJIecjL-|A9E1$&pR ztqJCzxU!*(%KbM?H~mU}pSI5uK#p0JODiESNAANc)TrRxgGR@A1;qj0f{m0g`GWGh zbOy=0hXaxW@hG$aRVeuJ0yNx={;mxBI6{=<)=AkiSY(sNv*KUknRP@|`e<7bE&CAf zh&!@>3q|M1+|2J<%wvk~MJ^rwS?)wW>IZ*j@M=JJ)6WQpG1|hBhR7A+YFD*ALM}U& zcP-sCnAhHujuNzM6rTT|Hwc^I53_t%UEyM*qjnAb9q0^XvPxEX{f7T;Bergldb7%W z?D@J~)jCuN#&nN_ATp8S3|m!jz3VM|9xQTkUL+V=q6|ugo82o-4@AvrxiriQ3LM8a zWktP>(n$Shf04i(*)B~UGibsw?MUTNT&J`CTP%@7VPJcUMS2s@Mw0t- zvbMWLI|nsWsV|Jo7MqNHizP=Ib|4Rl-aM4vhLWDTyBg4slw>IgJY%m9VXK{BE^_LC zByGQ`vC|TuSCx3oYWQg~N_+UAPQ7%kMYiWwE|ffmw&s{+Y)l5d`DFeV-ObHg0K>kr zwFi*z0?HN!kNMxN)Y%Mgcxi~|pY-OXd5E#t>Y6ZfV#+35f4C$?|En!fv21u*p~3wF zC)w8E$ToOGeFaY$EMD~!A(9-mj8$m|y6fkX6LoiUDWG2w}TRGA?4-8cOyNpyihx#Y0Kbdu=fx?;^sJFPM z(P2*`qy6@`Jr!`Qp+p$mXtt(0)Qt+KadwdUw$MKoyjD_ zzUC1g8rd(zrgjf}d*vec)j+d=5duSy!6j#IHGgGY!)Mgk685CES-DP~y0N+g%$9?K zwMVm&7lD_CIs)B@c(Qef zoE23NSc@snGP$Rt1c)%Qfcc}rQu(nIcJtYnpzuqZ(3&;8|g-muK7x$w#APilWOIc3E!D=K^?r;(Yso(}L@N>>(cjJ-g@< zdfk*6K5VI#p}4%gCG)?n+FWBAS{mNRB-R;I76Oq^iM9PN5Jin7FEObJId~K5juu6S zAlhM@GEs_LZ^taO2$3~So682aEI;ovE!1qYkBlNGlBxNj396iAs+H!W!$bquxemDy zcnAHp>OWfd&fZZ@j2Qznz5T69HHPig?dsY_2G==u#WHjJr2VXe5k?2|DIe|!qf+bN znH|Q-JEjy@3|GrJu z%zJkbbaL$2JWgT3`p zTwqYLAM19B7Ns5MxL`U+(HM|E5dJ0yq^>pG*)-yA4-tA6?e|iue1@(OdEajgSvO#t z6JBr8In#QGuFX%BZnrlzpb;u9!w!?S^A&qPe0bEI1Lox|wb{GE6T`ev{n7`FTxr{u zl2dA#u#IBsOz}Ffa4kisy7^`Evg55Gq7WR)y9R9I4D_vRH2V%YyJGFi#4GYJ$u7|u zXXrtkPqSoAVcar03}AU())o0m!^|(wPyp%D*b?}|-fDDoNs#=ezhw*JwL|)bRG?in z_CvW^%t6nr5c7B00&yYg8I?s-ekofaDwb>1BUp-kqf9{MW7!rS&t}`oM{et@;#%Ku znr+H%{FU|8CgA(6Q$pXY=moQ#rJD1jW2TIg1xt&I=3VL!)|}9f=y(zNrHqy(KPjMp z;L03+`i75cZ8Cv|g*Y>6`VZelIS$oER0OxgCN$qHeC?ykdyuV{S6+tsiLtwzCsczW zXiIC5WTD!7dYKeA$d>YI5nXjDX6^&}@p5mHoB7`@hR9$kH%_akIs|}8&|IdcwpJK@ zXu86)bR^R*RN&^Dy(l?S&HX*L#h4z3lKtz=>TTC(?w=XRnz32hY77s=hIBch*Vno* z)&mit-pW7R`k>Na$zt)aTp$XtEUdbCn7IHIPN-E$gG||Rk+l{KrMkNRrS)o&tRH$d zR}ZXf$%cGzH46eBbXlYSLn>EmR~2o{p6Br}jXa^rg>9UmPRd*>$u<=2MuXagp=D@3 zk}NMCnkST2{-J5GQ}UpMz%qVVMR6QwS9bq>P*$A8?;lnu&e8{-i*qCwdst~W$6Mg3 z6^C;B{g9jId5n9thbMyGl{_#fM%T%_cvyiL!RhhPTp-8GL(_n)iqmT|6%VQ=M-@`q zjDZhhPw@53Z(}1JZI%x{J$yM}Ba^o1%$a(dWr+5GbsKaqBV^8>(K9JZho&w?b`wnZ zs?w+Wx6zZwUw(miPk6$v=`dsSA@d5Tej!+6jSqYaEz@HpGZ?|)zq&fj$b;;|ajzse z1;HM2Rva=e(%lGABIaXc_he`iIBB208`_PK-Q<+=9N^OZUS+fP!iVn__(jbdq+Ui$ zTs-4o7x$W@<>wavKB;|r;bkMr?{zqyj6n?oL=GBGlk$M1ZjjVv%PHEc6pA}Mi0`9{ zA95(;ZF*{G*=;!(Ea5Bj0O4y*XwghEC>OSFBG|I=-IbCrNodzh-r1}Y&<@eaX=i=h6=rUj0i6WX3F+(6{!bw`}hqBy9uyMMn56GNbnMm3*zlYNtY~d z=LS*n(EX!CJTh{DDLv&`rrwFwE4&p*Ce6t6(Td?7yZr|qE~sOCfQPH~#<0^zz`e3jk$~gH!!i&A zs9Xce()i$PfQ3!Lv^xCsp?E=5&<6Q{{U5}W4F^_sEs1-TNH76$V@P1-vf?4Bq0`)h z_K!V1ozIYnqv`_u;EUv&D7QXschM6Vr0_`dz zJ|3{{?FBhmu^v7+uPKSAhgR?W&Z<)B0qY(j7CW+?6j?o3bj#6rt~dU6ur1wY@fEzj z(`#}~JxGYfnW3P42wsNY#mM!gDeZX^TnuQRE3qP!?OxDs)^maY-tI@&5k>oA7TQw8 z5=lr=hLi>Bzpt}&vu2TL30JQJP%2|pCPUk$SP0 zC&<`XxuAF`1Cx^G{}yh0$UJHDZpbuC%`)`OYWK7d2_uB_JeYT+REDe@hdDf)Q#zra z&UaX`OU|y`hM=1zwP?2oa}}`pc9teo1l=s#2P5VPCqf&};}bKl9bMJpW)ME`?kPE* z7}yVgC_bLR96{(|akxSt4Qvuaif9pr3D-}4>lj)WDnXsJ#}^5^B-IskvaBoxh`&%v&hWChhLy0RsPx#(5CdgOS7<^ ziQV6G(7^={Dh(YEz=(%kkQo1PHO=_AgrGz955tWQE}fv}EPA-ueRK~yB93fy(}!mO z?G+EUJ+P0GF7$hjyYGpQ{Z?->`*QQ4w#N%p$i70AuPjR+ZVnui?VHYt-0eKv3`DE)VO>wX)J1&v8Ac^4GVl*( zrSK{HH}V2jo%mtKvdv&$t$gsQ;jE}CzA0K24>mQ5j2ZjgACe9uqrVX;(KRv*RSz~j z!<;=bAB2utY-e0ci&V>-Tlx9hB+`^_d#NzYO?JBvGN!IK3&Y&x7yJ#7QhFdCo)~y| zA_^l-@NN+?w4k=4yhj z{z-egs!Sk>T-VPktJ}SnlJKSexGP_F{VsPe$1QXFao6j%s?yR9+-;H8Dfxbld$D$8 z_en{S@gXADo{A#F8>&~)GFd!aN;n9_ zcWDM&+6b34#5V2{wvb1>#E%=>GT-z zEY6Zt`5@E_)}9KdzwU6tT}?64dfw?ZSC~bP+NnwuiFfzf(Tsm>4P7;>@bZ*03MIe9 zGd^5VDPbsCaM*KFRXLW;B0#of-mvY-!&}4Y1+*0FuzEF6r`DDIC!I!oiF3=+shs86 zw%=N5i_SYL=o(j>9#ZyJ(c%`l(=W?&5E_DHo3rItd)PD3R zi&3-%1&k>wOEJ_#EyAQINV(q9CD)WBS+fn8n{xna^QSxDjk5cjsKLyg znL{{iE#m>Wkkgaitpjcw71r_=PSt6yb=5VIep=Pp%0tl0EPadRqW;GfyuT`t`T}t| zf#y!pyeg)T9#!Gdwx%^I?aPHTjS$p7g1AOkv4`G$`k51c^S^XM8gwPe_RNv_V!4J? ze*Ba%Kh+Bg^XHq>hUz^}rq`G+s1y$|>W9m+O@j_h9D#P~bZ~Kj%8K4rNAv@*K8m@r z=J0BjW-+aKT0CJ;>7@*eGHWutJ;)p`qRl5coZZgWu4$acW z4b_WM9vVjweJ*7CM7d*W(70|T&fR`}JVUM>s=ukWgaozuy2XVBSM#DlMT#r-1d78GNxzHRCXHW^2duNZd5^mKO8-*8rz20bc@XdWI|0KX#ZUTYtYk$YH&Gf zw56UZs&#GFN!z4m@q7V;0|64IKQjZKk=eGegX&~Xb=_Z@TR3#k(@0rGz zwZUFi0N5(7e%dzP2EzJ>N(Ws7w|0|Jadk|Z%d&CV#-{qQ{XpEV2y9;ASyLb?Bk=It zV)pP`{{~sVtPjUbXqusr`!Y>_fd;pz8boGF5HR?`U$-)-MRQJSlh0ly+ogy44w9>| z4RS+y>MQ^&2X%7IIkYFm4e$>_v^jS7B)S29FGQ0mFq)!hup)ETNEfM(x-QyaA9elQW+3^zC#CML522w9Dmq4M$;SBX z&bl@hj%#5(!q=~r)j_9i`olB>rbl$kK~4fX3fO=1sh$2(_AwNT{oVN@JpE4*?wH~< zvj<67q~yBCO#OtN-Z%`p8#H_2RGsN+o?Lsg z`IRP+CW}1{OPsSEKUKhl86j+&t1cN5h*+RFDe)oW49^WIAt#-Cm-KgD`KgUsNK1?4 zC}x!^!1$ZG7Hp-&Wy^6~<`iH|hPJle>PL0YMrcM=Zwd}nt=2A2l*gS^ z@j*Rm0K0?qd86FlX<<5y(|Zkbv2Eb$efvQY!9SIksX#pAH*GHU!Z&}rFN150xQlHE zHLQ7~F*_t2+0KW6O&>A;OT>I%vJXx@{Ko0>az8nU3v7kRlunN$><=`p)^H-mmKrY< z(?^fu3hF0WbmL)g3)=JOrbbxZ{|PQqO_eVZ4zXpQcTCi>1W{36@O}&>=P7 z(&LUCPz2M+0?3l{0XdE1rbr;967^x_9lqxF_sa;-biE0q3GMHfrXr4(Q&i=ZbLv7v z+$~*y`U|$Kk3L#O%Q#2g{dh3e8_f92=hH8v&!Vp<|NEnlo<60ZAY7Lue33%C!ADpQ zn`|}s@iFS1??=eU;QuaDuYg-6HvJf^GT|587G z_Up4>KmYX$`V~HUIPc+}Ojr8H5;A^|u#@pM$3f-QU;hcvIoB8*CzR+@ld_~5!i1JO zQ+*9j&fZ*%Umsrls{VC$Ix_#A+%`BildVx!q? z9MfxVJqDgfqVyUW3CGuOXLC*9DqVd_+C|_fUDwKclFt? zI4gs&ck!p1bCjEjI)j}}Gsqa|-W0e#OM0(m520@uhka)V&MI+fI8{Tu3nUSV1tG2TIay-4C?~ic$ap-7SMj?PD2qS6o(-wNuPhmVCaJhdX2rE4 z0&M%!vrh)g=so{(9a9d+=1;^gryJ7dQ@AIx`|NKy8PC|<8-u~I>58Q5*9ER;{!|wj z9zd)!ZH%djW)wA4)9Q!&wT?+GpMTPz(}kMbAOHE!|NT*a_4o8Y|MR24e-8H3brR18 zDT0Rva}@d+To=VUfARFG+H{^w)8*6kb+l6dnJm)D)33k&^2^zmlRthviU0V;v%vbG+XjQ7_8!W27VMNH33r!ZZX%%BL}&m zHy;3oHkHBGPd=mO^v|!Jd@=YPP6>l|s34orz`^e@>;cv}@wkZdPX@_+fD3rkHzQsDdkiHi2D5aq zN{c~Ebwe?9BAn>PXs)Ao@c{Y#=P|{pxMNk#XsAr`U@)8$Uv39CXgc_515BGW8a!hi@C$@%8WVRc}xhbaR}GcVpN)1!>oKj z4e`K?Pi!=6pb4oRApKYZtHmu5wv2uPFJQaI$bXR!(m8R65Yc4)HIL(gLFWpu7FcdW z>*Z5yqVcEsW=%uR2eb^%78_jgAJayTLa8Sy{xkR;E(&LZ$t^b+++4@20XszL(g-Yq zq!JzyqNhHC#S}bv@nXq^8MN|Kx1yw1ozKQ_Asu4iY^8!w1lTUIP<2`i-D|1T%FR^& zi_ELXjo*n9LX?<98xErSuDlh|)pSh5-l(nY$H#08{GV*IqVSX#q@zDsBgGESy!vwv zi$whktza6iicheE&=qz(G?*zzF_O~69|(9!8&+LN=0{)B?cEr zN+Lq^7xQI;b@b&If8mz@mxOY@=3zVrclnC;@xS-AfA4G1bYy<`bnCzOHMJrC&)L`1 z!33IfN>7%w((@dx`23=6{>KaimBh-^Vkpw)k(88>X`ob*g~czMJRakiXU@9z@Cao& z&MCX3riV>;r9s)y$3GP^^^H2==HtpSs&dAG>ZY(?@)}=MIr(-#b?8dbsEQu|0FMs%pWwnLNxq>NiR+UQ80L34VO6zmW_XhlBgA&@QsSq!Wq+VO>Xo zM%urjzW&NLDq7?GdI^?Nu;%4s?aTn`O3xPxXQglBn|^dC3ln{>07@sU8!30%{xnaTB*Oy9nE5zQhvb>GD=7n_XzaWxvUXqK4Oz$Y4> z<>YFqP9cx&w z+fkgH4o8O=112SKoVfpe9pMhq*IhWOqxfCC*d5j6!%p^u_q7#VAh>qNokw2yhETRr z%r7NN1JyqV2^_T0a_#FjY!YD4KtC$sF-``;inZhjhjTq+)>+FsAo~dJC?;%Q4alHX z$9s+Z6XpgVoD=ezD_+n)1A2z^!iNC+&qLqw;l=rIzrIXe@{Xcg_%gZUA0KP7Xw1qj zsR+`aU%WWl`{D2$IKMeP=)!5xwT)Hx-x#eLMy=2GA<$)vcfk{W{&B3gF!oWoY&8vP zeeItfv!gMekU7Vg@3{Ov#3br9a zH7X`>tIhSvOmT}2Ayy`17kUz3gWgAqmmtG!|$8>GDInz!7jlQG*IN@ z6kO4I_U&!-950h=l2~AlVlAGwUDwzWzGqQbjG%|HcdoBzyhQ8Y6n;C&uil*OZx^dT zGTyrc=&opDF#U83V9mL5e!@DqYBMMJhuS=ZqTYbOX!U`OK}ZVoY+r4F2k}~816!wo z9!72YTK3dBI;Cw4-+wGkRy-*npW3u_H*M`tZF|^BYc2d+P%A-316T##PEq%c2YLc$ zy2^3{VB!X>da-{BquqSNfOHuExBM8;sdovT4=F0%v} z=JFrz0K@t^kP5uA9&gC=7c9`{=GsODO=(-lV_2Raj!xg4?;l?La7M;bWk<%07(7SG z()v{UAw#sOcY8IvN!RXkKRYX!x-K_*bs1S@z@qIu$2OkN#Pcb6Hv4>y!*l{%!&k~U zYBTlm)&`fKUK_2$;9pXhg~qHGoU<*?5J05l8+wIKGyDOpE8rc$y=O|AuMuvASjgpM z6(x(-7IaTpTQ|q2Cl`CK506g|wAnt->Va<+@m!|a8aKb`mFm8HQPm7`JHDP7e@9xGdhn68{Mw;Vxt7Wt{ zGGV-I+WcXxSQ8Uok?l_d^s!bp@CnmhhTuIG+5SCfJ>|Lc5xT>)h0#Ht(P+_TD(}9A z=teGGqUwkWKkJMFllB^6ayzYDG6TJSvMk0!%qgd}R~;luU6bj6*BGe9t3DH* z>{&h-UVPK$140ZAn^o=nQ;LUmP~U@69$(QDP#@!1LOE2tM)W?^_W9^+Z{K)(aTSCW zIJRr8#@u{~0HEvEpAr2x!J8;;pt8oR>@Yb3%n${52k!Sa0>flFkKv6pntNXz$9Tl$ z-lq}P`Q~@?=W(%5@wg?c9Yob1O25WbTo;wr{ph z1g%SZl4hI3OSA6b7#B;L1+=0=XIT-uNY)M>ODH~Li_-WxUYnfOeriZ4pn+IwYEy!H z$+&97I~z@+)DGL*9jNb45Y>p;J=`!uoUf(qxGv+Cu~!9nchP1VaU6t?yG|o~u=Z<7 zBRs8eYd6kmMjG#MsSGIyoHmpZ-rwohC*^=)ji_J8dHHim=J4d=@cc+AX)h}o`#Qz* z<=C;%OZ?s=3}ZbzJyKp@FWyt+P{3iv-pQ62DZ7IEOG)hM`S1|u4((_3qCJlx+Vr4^ z=+<855;a^@>Q}_b+Mi4O=Z7Z;hv&nS*F^uxMVoHAFi(a`#I$C-*PX-T*S_OA#NaNl zeDEt@1d1aC&n%)>zpdAgxgtxcQ=_^fQt0ZFJqaQCNd1%6mO?)io_{6_JiRJzd3|av zNB`D$c{DHdPqu!X@Bcv;9LEu^h15^>`sF`Llr>_@A6jh`I$sMNnb4ldZpXUWCEajK z{p|M-z@|DM9rD(0uLZHsv|Z%{a+H=N9@6J5hCwT7)90`^HOAN z`r2d#c7X#zPH$GYi@P+l5C~6;fwpoV`Qng}XlVmC%M*&_%npM;px5s&%H6+IY1%%p zi&gs??B9IQ^=kjKJ?PJ>@-*G(J7Old>`L7oYd;C`iBCQ5E)UV#Mvo(UmPYqd&wjKw z)$Fci&5&p{;cO|2Vz^ab;TTW305#2)yjR1cqw_aMwH>|$gM!pI&vnSr#rfgI{x?1j zQGX1GH}p-gA6k2>niG~ruaRv@1bIkWdxRj2eeLzI(Fh1T7@i#N@13;}S%Urzm*;g# z3HEQNL%L)3ar6Sub@vu{`9){SI_%!j@O2lUPUTeILD|6`KqsDii~}`ZyhkexOO2M@ zCQ>~_oQ`QQ(j9>@osrvToEbqXjgBrk0=Am??TW1-l@=j>fqQ@=C3s3o0z1T&=&OmV z!N+MJ8kkxn7aBy_^jk~$a)2zBkL~0pUe^{dDgW8 zfYP@D3`V$Qot06dY+V=z->QHUEs4y{pT$@C-U#NfY$KW)i_0Lv+cZjNYgS!JRokLd zu6P7v;t>kv&d1aJ>PpwXdMI`k24l_P68GN^&sDsmZG@?%Tmh~x%TX|7%8O@V_S8?pwa9`azS?!m|6OManGfWSUV%ZTmDR4l7oJ z66JTLQ4N*a_n<|*roT85wI;HXgTv@}Cke-Ue%x$nb+d5Xw)|Ai8h6y0h2!peL?n_P z67loNlPB;cJX3U+kIa>ega~}Nv>m*WAkHU*TG-uY`MEC)OEp0aylH!26_`hh5C-*N z1lIcD_znEJ!;}4^H;8^X+q?MYSN@7~%jx;y_~h`rF`0iO^>y_3;o11`_zYJa&exOE z@xkG%y*Eb}<9&ou9DaYnMgS#cfElJG&`dCo8pqehtCq&YZ%ocTzI2%v>oL`zu#cLI zb%-C7v{;Hk2<3r52(@Lu^8$=4r-kQelR9YIMgfm3$Ky}<{7X$y5>}>|+D2Fh5k8s)gdwmxEBtiH`PDu- z9Rv%AgKU6n2&wn6Z8dSH6swIC(Qji$iL`Q3w~*GsqPw3{P*zSW2rE@u8|NNsZY%uT zPG$!e+eaV}!H)G&Qnc)Fl#Jgub7#!$|^nq$1D z$4@$#5AbxlM<;l1iRY!$ax>7&PJLJH^q@*0O5cLyE&984_s)IWIQg{pj>r2)bfHLF zFr1wizgEBQjea=UZ~5))@O*@84*+l5x2sH1<)_Be>~^i6{Qmg(vtPG~oPttYtZA!I z=o=z4!Fp8ZKb&2hj`iixXms@MxgMz zqR95rQfSsX+eENtv(jx)eE~rj)Tx3UV)hQ!U9qr?&&Q|8xB1;Uo(TTRf09Y9{)Jei zSHtheqrGGOlm4)GbW~|DJi!~Z;eq-#d^JA&9*cKWZBqRT#3P~)5mNKyeMQ%l&+X4+ zBnZzDb2dbb1yvF<|NG*_7^zn9(2Y`4X%%RXw7RWY&J7g58XS99a0ycEFOlJFZVdAakn(w0;{PmkzC)7%YmiT~WL?;dSjaAS1=n=> zH>YD=p#j7HiU0d4a?pIDI{Wh{$efqF18+N8Kys$cYkYa$`0{z<3sQP1 z@;(`8%ztQn`LglltHzhF8(;p|`0~s{bd&05O|qXg>3-%AZush;*PM2+>n{#+{l&qp zzc{G%7l$YMi^CKB#o>wm;_yU&ad@J?xI8hRnpC?yF|C?(yFAf?{jP$d{d}uSE4}OQlrqg^t*)In;h)}B2C7fW{?eCE>y?1)x zS@gvpr?cl@e-(c|`TW@*=6{&YXOl0!`0NkQpUWi-O@4jt23acr^&-q|Ol1UYAjOXgBmWI`#=)EDM%&xmoB3^)EOR13 znak+q6Z}72+gm!ONHwGlkdn?VST&gyG$=GsqM^YnCy%9zJ}r{Te-Sl*QKY)?l-O6p zoAZ?JrKHNCn#$`{yR(-)WsgpKsOxDx%OdbUt4z0a$4{rp6sM)gbloLIDUu4zc;<|g z3R%~Xihv^R%g+ukIPF|@e)yBBqG1Q`vX7{3Sq_$azw*CWw%yLk*r6XCN2!lL)Cm(@ zn>!l3?Y!(n2|{%OosOAhba@|AHmnuhjp)@Ta^iwzT#S?tdgNR z$K3$l3ef{(B(>(;cw?AACOnLnI$_06gg|F)QlPluMdz*AS)IeW(nRHosAgydUSc77 zF;yFwt-87D%M{ocQ=t$;o$Ke;oU!ewq(DB-Vk$nOg~!Mne?q4vJzRanezB=bZTS`a zq&T68fhPf|`F-XXK8wW!38Hi-3aPRgEh4nXORBO1%T^1F-{{|DZ~o5eSFJ-n87QQG z{=Gi>6RY3=;T(`2qzg*zU?mf6;Sgt|*ZrnFH2^Qg7jCTPxGIT!y`x)G&}_D%@hQ?( zt53{;*!g`Q^ybkz8QDLM!)Z$3I+@Z;5|=?9go+6PuJ|nwg|8aEKAlz$&w)b@T@23=O?X z3iP@h{r6E)#Gj9fWx*`O-<1VJJt1Kerq10QR8NFxJ+|&XS1;qIa#=C`2)MkVRmAO? zNs11&BL9S8*yW^2`!0^&S{|5+qnfzNZ-hTnoaK$Uq6{l7d59WCb&gOCVM>{uO>m0Q z)1|V6ABSolmcvq2Zqz7vDWRGHdp7BrZ_L}jnl+GzmA+2aF`H=y^^gA~!lyS%x{bL+ z{9e6NQe?sLv>I=({c4ZqqCD-A$w%b|art)n_<3V0QQl^%sIa)NC_oj0qz1yg2TD^- zXMosYywQq(M?X&s&Iy_i{%i2;_f$ws9gANdo*W`{|L|Zyku-x(2M4EvlhcdAAzr@! zFB~%IoXKZGGT#QM;&FxINA$WHHBra8xE0iKzP>~YU7vX{<$oTLUet`ih z!u%8$lMHDfauoSlQ^vR@a`vLcFc25l=`5$w5R}225BS_o6-&<6owc_62hDyq_^B1m3O&9bUSLNs6J;YI-_zo(Si&Wz@^#S z0m|@Tg>#_~KFvM4{M18=kF^78Qg6z}#SL6?_%N?;GEOjB;Z`!4FbDf1)WVDaFcg%a1h#*Vdw+U^_m z{^G8YA0+Rv4qo2=BhJ!0#|_P#tnM1?;d@-W(xl!s;^7KuO_SMPc7;H-RdG+~|9cZ> zxA%m5bc=`c@9!LW{*r1l;Ua&%#$IsO=#Nso_q=PQr`Yny`vVnebif_0b=dtyiWu~} z#>)u}?;I&M=?fJXb?2y2Nd}nj8to{~Fm-p0^`3Zef&H5vf!#H^Z&omCuVH5Xa`*BJ z-0zU>k4{o|Pd5Avl!X1x7u~m{nAsM*Yns19_K0|Q@xYTd819vlAKi9@3t%gCbc4XW zry!$nJ!SzZk^s{qGWskKPX2r5I1&uW)v5PQ0?BRmqT44!9wWf4Oin0d4+ySA7|Fp# zh?+$i$>33r5dTI+izR^Yq_e#7eNa09orKtEFWajEz+|<*qL-`YKBjYcK4@E|vc31x zhA$CNCDSknRR%T;h9(bpO+5R?8!Q|lKu_oM@(M%_M(ZEJ;r8k$4DuJ$UJ4r|A8tFu z%rp5I7EMKaKYp0u=(GtAlV`FT?XAdfS#?dhcOZ9Je_k}l zn}W9Cc1CxS6S^K962cdz1KfLsR&j(c)hfI|+&bBZVQd$?P7K>taVPNB^}G#w>&o7S zfJWa_^g#Ts?AIu|*M0X8x->uu$va7~&BRdsZOy}Xa3F+tN>DFR=TCXsVy@&a+61{j z3kgRx{LGTMt-{fqp3V=V+x-Z+0)r8xaGBW5^B%42%!xD56bV~&&6q9bp(2*cM)zbb z!|pOSE&?c!gH_Ig0{ah+5jn$aXbxAj4FvGJ20vVt&({QeuR)(~iV$$+jqEo8;Fl88 z=JSZ{bbnJ6NM?%4cu4b$G7_FA7BU>?F>;mXJy$0YVG%$A_Vt~fx-$+WfZ@%6#L`nI z;T!nJdjqrRykv>k4aYa|G?hio!Wp5Ya7RiMl3htTkCD)IMcEm3-2;hUs?W-sEDfYW>XLDmY6ppp*4^VV1BN}A|iZafHLj|}3szW==PQ%^~D7xftjJeDa zAKEV>u~f=&C*yc94t^yIJ5O}{X%O#b`wSB?hU~8d5d}s<+G{=H-eea^vB}Me|2FeN z*yt&;Y{8f7y+)8v5tr2u63-m?xZ4Z5C^NE$jdz1s%zhG9s}vS0-(|Mq07xA^Bn`iD zSH;g8M2>Biy;OdN(kgID%sSoA<>B7#Hiu6gIajad$N_+$#?Z;-w+VuymD?q5k8Nd8 z8E;hzRM=ivxr@-HUjarPtZ7*QMIwqNI0EJZ*i(TEWK$KkC{s-b6MPe+NK!Ad5lw>J z)4iFkz;|G`LJ+zNE$1jpTP-JUpsW!F^C%)<-nrZ{y9YygSA%rl%1Y+F22KT_MVg+@ z#ro*RWWP*jB5Sn{rw;WJPWd54x~BmO;=h&alREftHBb9ce1<#vRS|IDt#_ncPxs^Ez5$I}PlcwNu{ zk0i0G0!oKCnMb7#8n*o1PER>#y4O%uw069h?Et;#$K|sPg-D1z3w2fj^p)_~RtM$P z*tg&F=!O`!1Gt{Hz|F#)Y|vml-n(E?w<G8T!ouDjv#%1Kb|z-=YIr18A>VdR0s?_qvDFv*hrRSW3;_Lqd%k z(DcGh-DB|*>P5lJMQUnogpC^otm8BJ1z3}Kz5we__`a$#d|*q}2Ivi*ID>#qP71Q< z#lHp?ks57qL!&vAUl+BZ`1>X+kRD?vGLGYDCvNcTo?X~UyD8=+nf4q;wV-gAV6#Zp zN(uMC(3A4sd!dr)O7g@|s(Wvyw(m@($nCkKGMWSF4R2!s^j8JdQpaIz11yfLz4gZ~ zE1nK<((921x8$!X8lbNuq;}}FykEyD(gMg1_|0ye((0kg{x#i9@3LKeBX<5b=>CQz zM0zvbfF9cF<)LGSv&&N|J50J6ho>NRAeNx}?FI{u#LtZypvRQcrSnp{Fn*u)wTAiLqyM1sT38wn&=|9Z?YC_Ln9>>v9hSbnIV(~xK{=0SyC{}(&gR{- zXJ7gEFj0XMCm;r*!MTw%2BHZW5(D9ZM!rFTZ@K|^fojY7S)7e<9cxQFg|X}+EuzJ6 z_4XiMAq}1A5~N9nFovT6_(mGT(SZCm$qINnc!|rMMy8PeqRJMn&(%w#V| z8y)Apj;cHEfxK~{)Ipz3_++!3#2Jl4=HYiotb9tL65dDevpkrp3c(#F@8gBiV7*b0 zD2*sBXW()k>1dl*@@N~E!@ar$nevx>x;Gm}@v@i4!-7+#?XxIo@l;@)D%}!&SAh-H zIuxgeL7ik6!xxNnb#1qxAx@3kMB}+`fWy!iMLoY+= zu0e*pNz+qU!@#9e0wl2p4lg)Gq4!6CJW#T*Q$P6(z6%lGjE;H{A9`A1zM1m_hbHWA zG71Vc-_FyUP(lnSqceZ(isythggz4PipxCI48=z|6T*|BLa(`C0r^k?xp;~6w{H!h zNG+{qM>Hi(XgodOGy>AdB@Y1xML^t+AB!1N|DnipZ}}-e^mCE#P6q8=JqM8>;U%8J z3Lmo4DE3j_kN}WgXpYq&?Y9J*#CV=4JMdS!L)2Zgka>tJaPtHqng__}rLxI~6AXdt z1++IMm)mjlK3NJkf(qT}R%1YjRbLFqaB@2TE{@+yLxHPPY}Q)HaxG`tKnJeW3W8Tj zMnR)`6ussF*ME4=l^4f5@bL)G!irs{GE7xeSg=dCJmzQt2BH`P^OA(27aMnB-+8>I zIhcKi)b*Tthoi20kuiFktk-vfNtzX^u_OraAHqy{O<<|>zpe~u;-Gnva)E9hq#;Wc zEXfLjfRo}i=d=oEf07^myg@Zt>;Q!Remk5g1Kg7DK>Na03W~O4;Gc^@e zAf<(FAt;O3tODIj1GJ&SLRLzS8i=jy4s7(3{5=Gz1Q9a0qju#Qh8i?TvlMv#4n`NF z=pDRqVjfk&6O@aKZcidvB1&RQ1wL5CHK7BwTLr=JK+60I7~We2+zwR6OiBaH>N#QM zmM^u_{+6e!;R<69|l3a`F>7!Fr6X`W6mIAyny=3(kY z5H8xKOdx0}-US{OXPn_FBO~c87#2%!4D#SqA1f7f|IWD*qcFFxum4?UfM7YV<}OHJ zw_+u*SoB?)yD!NQf0>Vq&bJ*kT@zDp*%+ZnRk6#|;82_uyC@od7dhR1dMbEs#c>7> zFYR6iXLLfbNAOYfW-Q}i;qNQ4jG6ARMLpCF1d7oRsQQ%ux*u{%N?>fDvo(hbUzqCIC0KE(K1YYbid*?_c zf4Y(d{d(9p+DxXj7EeXhsyqmI<@DtJ8#qW{#UWfyRL-H+yRkucH;F5l5QT^e+;G$N z-2$uFcCjrhn2vX_EGme4?m!hBeN}#mB+2pW?Hy#lhwN0bqyf zlW4afxrmo*#D2?O_Ln%!L}*#%vZ7&2ro@osNW~y7E!3pJSb;ljM~0jVG8lMNFBMml zsC(37SL#AKLJ5udj&WWfmwvxl@C_SA!t7gY$TT%~fwr%=$IHcDjvqfJqhaoVb9RY` zYX>iF{X9cnRCh!XZ%KG!(ZgZoCyU?Op3dR?fDZ*m`CUkw@`RtxDX|?Mrp)dX`JEy= zkBd#Vl7@Y3(S1GL9Nu~9>G5d8g^W;lsY)*BqPIxi#dpU)Tw31)R(2B59*onQ-hY})>Le1>nk5EE{?RB3=WB-9zklAEi`PSU_U7Wzlv7NjmN z7+M>QVT^F#cX5F@XnJ}q91QSO7il4k>@2q>gQ2f$wuEO-L!WEP62$@D4eW-Yhl954 zzL%H91@GlvaS-(ItCY}vl(B(E(d519lrjnidzZ<)oY}<~ZnHY@cpkM$7ErrktI?Ww zyr69mM4(QnV(D?rt0LG%FSKClr?l(HI1r$Rv#TACaWRI^eHG`f@JM(seyLF^z$y(S z$i1ZxI#gP!!`nYhPxvjuuSlFBkkMJr@ZP&9xl4Rzrgz|w%C;1Ghg2Ei8SY>Zq z${!iFFdVz)5?VXZK(CO~&)zh*_PgmUm5c9|k?f>#s)$Mn3Y_T*nx5A=70&duiz+yJ z=oNPyJye1V-bdA1c)OhY&I4WALMbBa{x88o?oiRoGAbv5F0gv7vkD2ltg8wUJ?twN zzK?}f!tY>XSxv_aUG~(cRCvlb>uFr!nk{8-7k5pl0`01Q;2Oy~S(Uci6o~E#ljtUv z{g8UrB{Q0c!qr0)$D4Ce`i?F#f^L`cbdycvm&hfsz#%v==$vwwx!~f8eRV)_WN)=U z^Fl!S%-z#12bl-NhzXVzdt@YT=0vR;3;b&m|iD~8KMs* z%g6(bG!&v3EDxwWBS{k&Q@_6x;Xr^(DO$1|yeZN}UNWSsz7=?v{^7aajScC1j_u^| zJuZ`bvOr;YEsM=>GT|L83X#!lLCtzYPMcuib6|T&UkTk;{7MXcXRgE`=Uf`CUs2S4 zxVBg?$ZxHliobXr6k=3Wgt6bZ^yzGdEcxgiF);^g2d< zt?(oZ$N`DF88^$;9OsL6YRekpO~`=!T%%$$xqyp0zq};dWkeOOFE3xxJw|@Iis@43 z6|yvAJhV+wu%_4_<)DUh0kNLw|kbV4Z*xP@Bfs7a?TSFt&9`l8{As=ar}e>(z9eb5ugIspbgz`CuYD4a2g#_$G? zJq#F32%dHqbgHmO#L)%g#exb{E5rw+tB|y!?O3Evn;M3one)L0%vue6#AmV{Mz0X` z95`GXlx9v=T(?d+Ry)jksIAbM$67-o0BJ%!iuk3lT`W@R3z+YaOz}8c2iTkz0#a#= zHp#FoT&QVY1AHyB$O+2v3Ms86rPBe#C?!zeFHw3RLW0{DFII6^`a^3{I1oac=N~EZ zbR+6mZJ&En(L0+eP{^UG2DzX_Su)RB74kfuzN0i8=|;rKDlmBzMH+f6nWbnVT7l6t z6}Rg+Hk4anG@DIxyo|Y)`3BKEq%}epuj4TUb-YYx(zH2I2}L`(Fn?PK6|XuDFwV$T zH<_wYJ-+5OB4aMy6pp8yENT2U#y_FcM3bxmH!D$M!ALbn;i09-%rfnl6IinW^w61p zjI-@VC<9E^40%H3eNgK$&TMJNq12fg+XJyTu$N7rZZ<*v%u)A3P8GGLaRkWL97Rmz z9l&rVi&yqCQwfO$37wP@Fo56dMUS~GBFk%;hfHC|@v6g# zQ>QzNk&8?g>8Q~wfIbY(V)40E^_3&d-c+{9vp&tQlX-{O)usUl>yUxxvPXQ1@=e(0 z!OcSzl>!RYHXEyMYpU z6b8Nw<8mXiohH+@tegcm6!)J0oOS5HQvXk;`DP*-P_lY{9g9l0z$}MoiIAr00xM9| z^cR}U4Dr9R)+F2^?c*$4r83lLDvJ%7{DP(k7nh;M%T19!n8t~SV|;Tl6CU1G<5ixC zh@D62f+q7NPynL~=EflTcJWXfqirof-EJZrWKnk<)_Li*au3)rjonR=iF<8vARf^>vrkxH34 zmO8zd+(5RF=}2B>Wj~5GYVL*|P&jGo8B|Q+U*vX56;UAJ>dHNck1*n8*KJG~x9&CB z`DQhisy@ZC%_>U*NJ9sR1QyE=2^~z%ECQD_L4?hG2{BG5KM60dh|L5@ z;!ejEihGgruMXFhtO`r4tDN96=cA<&IOhq>s+Wc4zR-VN-h}5S|8pR84cyB zfg8)>*$t@)t_J1R)n?Nb#I5KIohgqsII6+TCmKi$-;&60NXI{!$&CF;nq?GC;TDOZ z;bbR?S$y?8lbKkv1es=KKI>VMzlCy+V|bf{7i|oJbQ##Rf?%i@IY7{yr+Azg3;nff zHJklfA}9)Ck#;x@>>*v5j)>-g&nxQyCb6!{{4yD^6}bX*IR1X4TE(*?rVVFXq%c3m8l z4TZUs_=G8sqTuGV7WBbSL^B;?@rWZ71`*0KokT<-@2R};RhDi)^g za0MW9eGq1NNtPYlE|)Pi&hY|WvOKA+bpJ6)T4}g*e8fl`!#*5Y=1o8Wl$%cw}%SONepiDNy(7T0jr<=p}?1*zLb;}}^xxD6` zmu8O0u24fw78x_|zFaJ640v!h7r!v0mK}?*?7iE$RkoA9HNy+kuG-cPLR^Q4#HfJ9 zA#0d+$b>V8ph5bMZH|_FBovxFZu<`QJH${2aQ|Z+%BosY5A+}=AfRwAeSLQ|9U~+J z2B*mSLF;W-TID#eW@3lORh%Yk-hy%9K=?4-SdJ&RW2xb9;Bg6*A%GgtpYI0VADT!G zhsI$tqUfAJj?E_Hh%!4#){5d0AV@ohF&02%Rv{%-AbrU!oE50p8V;0ZSK&a2Q%$oT z6r$`gt;S&a)Nn>Zq}TFl;>dOzvzHkC@+~GL9d}2#svv4)5>SjMS$cyR`e1f8s=3q)Xy;S&|zp*t`$*4*M@DW3*x2F(;PAXZm| zLCI_rqEC6;gBF+y)e6%q^tOsJ!iTW|v5fqlR_N8G@fZ*($Dkv_WN3OLv$o=boXkSq zD14}f0bZwhF}X!}uXGzw0CJl__dozb(}W=cI-uK0;rR^%Ufy2G&iUL{>{H>^>j2Cf zaa+VC7U|?RfFlNiYcdE$hMuo1Bhjq^#+q%Up@3+Njq_a){R#l}Y(ytS^dP-Mp{B5% z()ldv2u!Q&cj8Tak&2?aua@F%5)?J zSWLx>U=d#-gh3XPPUDpBpVUL;p;5Mi?$&HEV2NNB7FQsbQB26n#f`(sQG*0lAw@nBpl`U0&7{)4-WG- zFo@q1O{dcjoQ$C$Jt)hPK0rNSf;m9BkYr2?dUJR63kC4V9`sOKj>{2E#4qwk9#_90 zl#v2{WQgI733w%lOI(p_gxbL;eI*lTZr%Mjr91<0W4Iflg~$iM&83%~-1z$KOceE@ z8ZV=cfQ}l~*JvEb6$S|+Uut|Y`RfS=`&=R^+KVDiwQ(I!kmo>#`8}46sAVQSf3YJF zw^d1T8}P`RpcqJ4!d`td zLOsb4Q_cYe52eV;bU-+s9VTxwPh@wU3icXrSK)G$>s$tt9`{vaxsK-caA?3q2}UD8 zf0E8bP7N<0Sp#t-GU^)e0S-@w4cITZJ;z*(gXUR*1W&O7GYnPZ5-AE2di5S4aHS}q zP!1}nfWU3$qk_VJBUykJ0~uzJbRj%IYHn0u)g4_x$bt`A>i=Ze9Iy3+4utF5we0MZ z&=XjRG;l+{C1-vKALS~jC0*^xHB192B-@+=ET32f1Z^R->1}(Voo(A^VE|$iJCQ2n zWQo`Ae2I&k%H`deNCGOLJf~7WGWUx2>?r0gI+2&{IT~5!Vru|J3*n>U2ITdP$n9Oi zi9MY)kRBw`<=sM-daUeB1NG=G$2%oT#3H&xDLc&h$$?m`vew zuj+>a_E;Ll^v&_o_Bu|kuI1uOAUDZOb_>p9hh3sIpqwELCy$Rby-5$#Xh%KB2vX^75SburULeqm$;WkY zvXo`t!|D>=yP>7dMIesoWDxOafu2r9>TQ$MTs2*2umH=NA@S~Sj?hbCeRu*P9!GOL z3=qx<159G?@F7eI z5DX*OxDbUqZyYAyJOd1Q+*W=%|MS(duoZH?h(2$PUqtr#Mz4@3=Nn2 zEeyjpwWI>qh5_bewl493b3DFcLk511Wk1FvqwWob_~Nbx?h<-au4f>WkOk@!fQlgH zXs2KPYTBK%o}DqLAm|VoWKmnGgu*O2p=0jJ^OevDa>N^nabu`~+4zP+%sJ9IU5jlt z2T}euLB^il@km|3?tC%X6rdf-XYnb~87OH2T=uItRB>$~ORid0eO47D3X-)TQ$JX1 zW5=WrPAo=x<57sR02z|QUfDZP!kicmgywC?G{RR9ypKV*U6G>fxm_D@Qt$L{97Cg( zE+Zf%-QZy6M(gn{azIOAi(k|$1b0dkSxi3hn!s5K;rQYr(;@vTz!-0+s92NqY**O`of>Ll+>P1@+qn zdn!F)s8O)W{hl#606{ zE5gR{dsMa%KlcG0(x3`%iqttW+Yxx_;k=M&xS7bqBt?zoAx2yv;#A6LF06=m#zN$a zL{`-ZoD<7@jxA57jL>o;be&OCm?4QMxCGS7)03ew44qkk*rU00MVU8F!s$SaCY~xv z8_O>ppu9H|mAzY*1_w;pz^hE@dO}tgJ%(kj>^i-1XtxWUL$`ZIaetzLPQO_CCfvFFhh^-k%Bur zlVX)2iW&m@BIU>7&>NXIR0GoNkdFw@f^poHJz#b~1J0T*ls+&mqSe(#m<`_pE`zJ;1ojgt-?W2E=4M+~Gr_W^^F5_PffKkdi&>l%6j{NNdoO(Y?47%pK$xdMiuN zrRPFyXRG$oh$C(-byRld`*WA))icq%4d8nw)GVv3=d$vH3%WWL2^#DRQPd(_=n{O( z3H)Ywm8C-6gz*v#B(jL8rK*Q5F74@ngoKkhU~i+9=*$KX6?q0{@G_Q1KbCOX{8fR_ zLUzyMf?j6@j!gxug%hgb`VeX;#HN!VJ&#DCfi<`by;8fIkRc2ZP#@6rA+Oq3g&;FW z7;D!A#NdJ$p@_s=ygpDpJA;2LtiJ?@Epd59@Pzg&sbz-d9HGkj0EH4kSpe+34i0aW8Z;O_c3D{gG-@lY6h&=|3^CZ!K~w8M?C|#p zIZB~+OL0V-qFwrUO}9oDa$Hyt2`-2Gm>mOXn&1$C(t5(mU8UI)ryvwtBSQjBX3%zCyIB)@i<{7>ts$wTP0s=(6r3>k1T3{VZR+8{^ ziP9?~8(|$G1@=bv0EpU7uPJT1gixLooX!)m)mcK&F-{gkptxqPj#KTvHCUM3>2tFDea2 z37%H^zFyoPZWz+>l`v!G8a?IFIuXY-G5}WkdVF&Y2@qFuBDjt8;Dp8jadT@?61lao z#Dvf-LdM(s@svbI7QUzeu%=g{J89Lthst5P04Ge9Yx_ZvqimI#4q~Z@8Gz6ZuCj0l zNSJ6{TAHY4kZfrg5UelRvD>nC9XgJ6XM{$1>sa;>ICpDd^4+q7n^4ZKZ$jlGTO> zF1@*Npp8ZNOAu+?7Wee?CY6PEa%=Gg2r^2-n~mgF@(OHB$&BJSRvc~@kkzCCs%~v1 zYLG!GYrUi~s!l#f^+{RNt~|)rr9++{#9B>mVMny1tvBzCvvnI^i9%-Kj=@Ppoh(Ernp(B8mdx8gw>p=XSFP4JGxJqp*2r(NSl#s=mNv zvznolpxB9T0&oo+MkiauH9#>NDrAyH7Ul?Qb{qa~zJ^0Ng*w)ZJByTFqkX>1=|IZq z4)15#F2#Jc<8ykJ1{>wqktmBTwG$tqa+!^WW}=HGl73m7HKawF)dm}iD&*0n{z`^Y zb6qh+dOw!)h9XLsDb4vSjWvU1!ydQ@=@ca5LhYf2kxCdoJ1GEO^5)~4MCJ;k9_V1y zRl3#THd>?ROc*`Fhzg=aJ>8ZL6nBEpK9@EY8!AKx<})k8n8=v{#QGYYOc4PltY1K_ zWl;~*QdSdzTBfpBDbzGyi*8lX6geQ-)2yPhrDATNxD*m4-U|i1L9%EVm?2=eG~!J| zC_+S{{3ruXz#k+ne8jD%IZXCzq243(vJg1N9f%q*Laqn{gMe^_!lywpPXJ>UQaU74FrZLpAjUakX0%G)_}z?Okhk%1H>m_Tyi}D8iXPi5IO~<$b~0oZ9tF} zp_WoCd}6Btt3+HdAy`Y?6N!#+p+Q@^eL&bMu132LX4X8;kvs-Q20gTk-iZ#&$TcNl z3z~^6)goT5JAHMQRFWO8iy2KQ8+gJAA+S#fE6-T)WJV$E$Y+)H0H$4uOY{nlW42d1 zWvaJYM81fFX1oj<+Mh}tAU!-=GP`dbN^{c!uvNfuAuLEi1Jjo#Vj`Dop=Y8sYa0Z`ly6S|N5(|$}zTgMZ1@cqKBgs_N$r_-N9&!2uKaONYOc$xC8UhGl zpeLafK|p9p4F?Cy3$xGEK;1uu(Q9GlLxZ6qj2SU6j8)7R^7q4OjPtoL ze{dZd$HC2VMF|KH;U*=S7Od$WG7|Ry5Az%n)f_7mqUstzW10WOfun)S)5!h*?7eGu zTsLwy`aQpbpCbER@^vPYq>p1AnUXw8bc;yOiWKmuj+3~#?5eS#*_?a^kx+#cZ`(9!Dr zNRsD2{fB?};(z_Ge>nPIN5`u*p2;{ue)Q&uZjv9-{iW^bi!Uw^rP`l;j=aw=P(6Gp z{|{;CXJ5?D&i=WX{Oj55%isTNb2j_xt3OP?Jp1xr&c6Kp@BaB;e?R@hzy9;@|K$(= z^5s`wY&X*{-ca8c?mqPw&ynGV&F12ZXLu=y+^7@EvDu-t>dVRcb6`s-QGD!ZySi$Q z@D2(RVz)<&`Mc%_k*yV+cOrtHNjaZSkGKlW5i-`dN1*-)wJR1>%;5;vzv(m-18g0U zw;QTtcl62h)1$Ay{OX^M-cGhx`|Z(-W;0uD&MS=`(<^(|M=w{{lA%HaT7BUe_l&Y+ zclbnoAAFM<}^{M758ObdCpkWErS)#Wl)K9#NhiwCC&=(s6ZRKPP~n%s+2FKYEMzPH_7ZQg}npQs64+=Cg0- z+c(_lyIcG$rDQ+(^i%3|dI`YS6F?>Jezo5&ZjV+={6AD-nh|ysMnH>8^kQ6;8%I*K z6)nZXn$fQWk?*vVKAGLJd5=>ipAkbwymTr7?*ClCa1IiKHP zSb#7L*{$$lhO%rsK?U4U_Am(I5uwe)9Lpo~i`$3XhH3I}S=))fn8U!JIeM_U9zQtx z1i`x5XI!4-Q`YSV{8c_M)KfgxZ19_*^7W1dh32=EgLuKZgX(dgc@npR4{CJ-J8A*0 z0EpMN?a}sfwO`C+vJq*~7;GS%^9Hj5LkdxV+bgCE^lljbSD!@mAxqh}FC zWP(Y&$N^>~e)l!LgiahMlY)vX<#obhdhnDDfws>Qrr}mt4UR z6O_<&Cgkjv^ztD=QRU#Dy|RjmJb+GmV<>%C55oLl5Fq*gu+m9kGMHES$NwStTT)PH zohS)U6tNUX^Bo4~VU2A-7wYv#TndCtguscny|NlX67J%6pcAzHZZlK*pl-4}(So%< z`^+V|AGum6N1xD&C2q@P@hKC5Sqn9VggtXCgLary!LvEQ&;0K?7 z{`mt!ITEImHP1sB09I^jiSJurq-|kdAqY^o!qTseSOTb0o;G-E`CBA8ZFneNR^V%@k`e&7|G_3~F<}8adU*V)NGf8Ppi)&Q{Yc zd6S>x5*F;o$)8?fv0AUl)?YVgxWxp!Ptw9`HF&uKfIm5D$VqU{ss6*;9R|ie3XJlf zP>~4Ei9*`aXuRgr#3DhwpU+T$9>8JAX_LV&=ZlEwTTMI&9@FWe^;c;q@TUsDPuXY z4YC1vQdG%n2!CH-i#}PjuzdqB;0!mn`Z69HH$O`wqu~pasNdf5<>bcA z1+|HlsbFv>&BjiO;-2w}P{HO+cww;@@VD5np5nv`aV7^pSjBkOjYhy_K+_+vk3NLl zKVkE#xU}>0&)9Y~eKG2qxrXP6bx@pfOV>IbQ{q`}+OB(Q)Vja&VUN-iXzzxY&qkkh z9y6okwJ8-jI$HhKo^m;*vumQc+M7ZHtkB&6f;Rik^vT)H(i{NBxlU_mI{qY0Z|@(g z)Udu*d$s5LevB@tvqGrg{S>Ey3q-|uYCc}C{Sqtl<^vZ=RwhM_zYFgYCvz-nb}VhL!m*EvVT3(A3Yui)*GBujE(D3wT z%3O5V2%0R?7VG$oUkB1SI`+Ibl!y8yWN=LkliU z)a_-nrLsN!IsGQSSxid{9IMDjiUxR#T5Y$ddIhnQ4R0|ip8cK$F;oWjro!^k{^!9RH$QG>Bx{z_)%KljZZE=x-=qunmL{-KJA(yR8EmUw4f zQgag%?;!oUbRz(d*ju9AaQL^d%Nw9>t)-d^hp20n_QmlzMFzMdxqKh=K>ZW4SGq1g zJfgoC(x)StftfWH_JC<+e2Uz2YXt)?7%_)>v`CPV>m?Z&M+eeU;;}4PorGg%1#p0j zarnSf`~!hz+rj^O(o9k0e8K+?o`x|qi25**ZLE9(@vwztfUYDAG?=JHsKHWH z!g`ac$>4Rxi5LBhcy+ub?PdHzkdF1MEC3T^Gvada^m2}8iE(g)+LGa3t&g&}R+uDX zWDJ;>!@^uLO|S(tSz%6>IqjE83@w}Gd$j_xoJu21Zp}C_+`(5ocZ&CXSNOj*8`l&+ zd1_$1-)LzVxi|U2gQdLZ0@EEv%TN{|LK-8}Pja#!#HFA4EG}Io97qn|qcF92UaD_m z=Q57)5evT(8lrzGiD8h$G8MhqJsl&9!O2eHB7ZFI43g5NNn?fpJfWXKB}#BO8O=ucTT z^eT$|OooDRQaC0{UROv06r-hZqOS!#!gM>3KmK z%TSl?-;@aIZirApm9Z-#lVPnql9~dhLYo(q{IWx=$<7G?;yN!*ghs8W^vXj*WTr~1 z#f*q{VpulU`j^KCFHR$0mW){ftBjBDheRd_)m||7`da1_o~}Z*UZyRg0)Cep*GgG~-1Qdi{w*T@2v0*Oy@0$sw{gbIqV zKZu_F<*y$ezd3%61%h7g@;WMBWRZEmkY|c;Q`sGrMll0&Q>W5#+k$ma(2ANzhYuW` z5WEx}tNh<>Tt{NtJ<5=#-v9|BEwfEl+p7sO-~H28UdGjFg^GCoBAsD%Y&@Keu9;MZ zQ4j&I7KtTnH_%3XTKAefgCqMURn}Q~*_d<2F#qZ1(ex4zr*c(q`;|`m{okZh5e6=! zKT?*g5&WIg)o!w|2eve3wc#I8iqR-gwVgS{Ey5$6jq*)0NK336t_gdSSp#HTCsE3* z34}P0mKSP)wPQbEajz&2gGls7qfMarTk4kRkp9dQl^b*~`FmHTCY={KtlBIg2r9Db zB!N7#pAV^hX2CNN0;0CB}1Locw0tvI2{N=B@IPAx5tAkMZ!4nGPTh@s^ zl?XBO9IZ3j`z-b~c@8!8dn8}=v-RGJ7WL>}t-V*bHgj)mdm@4mRJwz`H#oEyeABAK z;ul($O@5(a+2)&uq(UX5Z<)pu_8Ek*By4(%6~}YpCdgo4V{najjwp zs1H_~)#UEu(q?k3Ir*q`5}srBYwlz{<2~n?Dziw63Tphgd{c*S%n}BQwD&zux;mO7 z<6n<#m1aZ+@D7#XopPFDGnD^_7doV(yRK^S=!gi6*Qiu@KE_4fsqU2=zabpP4kf`5 z`NOj^Rv7s4d^5SAn?3fkj!%GbugC;`G|JVYJf>5GPfOQU91F+@-0>C2zYL8?Ruv-!7Z3TaVkn6i#9NU zQ?Y_ctFj#=J|G@SS0=~6hx|jGCNh5)bWqkI28}l;gMi8G`Gg34@uu0`$qfcVE(5eE41b@ajC zlks@Q5XVS=Td6yDpKyuKhEQ^R?*ZHWf#_1;5YY&?q7jGGBmaa&E(uDXj$#ESmXBq~ zg0tOC4qE&!k_OILe(yholhF(XFbjf%=F4isa`DZLS_y&&u^OEYWeB?d9kHWLfCysh z;WqP-v=IKFu(PLjS?Lli(CYK?#r&pl+dv4>5{QkFBuGSfXB`L~*dgfAdefS&Wi=!mbYM7_Q>DumOMl z;8evn2`8^nlMET|8yFwz`f@koZ@gO27c`O=MIj0|G<{-6m&B8wE1XX#E z7)n7ov00ym3x=ed{zhbij6rrmFGlmw;hxp&O zl9j`M%I}p~0A~X_^E0uB@C%63Ai-{haSE(Aof;pm{(YzU%m>b95jbDjPkMnQLj@KG4h%f5v!spF^$2ON+Hbg{c+G9Qr+ z;*-)|-DgvU?R+poFK1-ifNne|b01Ml6%84vW<~0r_4~v2$A@hUd9W~5J?rt0j%k1v zA7M)vPh{e7&=JP{)*V>*8-*SarT8Z@7Od9Z#m{vN z#9_^>L@Dy-MkS%4hwdmnvxjb;_I}X+DN5-PK6Lip1FvN0|9Kp{^IYzyUS@vx>rk2m zzg39wl+@O6k+AI0N&2g_ba$!`yG zqde?nkCr<@A0+vj&@4IL^qrD$X@Z)Ka6Cxn4(pciK8Jfu#}kh^4|6mUx9ursmn0+x zk1jZBg}&eWV@B`5_Uw7$d+PaT+L49pZq>CS@dHxC)sLAfD|=d|$?{}aOB^&lLVH0Z>!U&}tNO6i0#5iK)=4-m;+azO#2l4h#8 zpH_lZm?;NB%4beHASg6)$g@L^L=Zx8X)3itFX&0-Ksx5iwrSL?>YNpWFIA*;VMwrq z4Mn6P)JqZ>@a`vT87Zrd!4o)0uhbK+L{M9fCT4pbvRIERXW~jIP49*+&il^stYhR1+rT5jgIH+x^?^XDMbn z>L3H^JEaoyTB$Ai7*B1h*Podi&X%!AXc@QHe6mrxt*MUDW=l;QHLDJbNDG4Q7CIag zlU=VGt252a=;^Y&IxyOGN}!KPO_nJIFJ0R#Xlut7gDL&mEM$yBt9`5>;b&xrIN-$C zyK9-F=!kkIrxdhx={8Zd>1(=k6H0A0OnP ziA;^h%v`og%3V|^)S`ku2{@xt~ujH>+z(?F`lf{XXAHp z6y(~d_^8h8pcnn3K*+{u4|wbq)U|9PuA2xq!TXz?D1~dbGn2uT=5_ z8;I-9{NCIROa1t>cV}71l-(QLFe1WTC1%J@t}$?Gp<*<^wWF~-0H=4RonA4d@I+Yq zY(l%Q-9Ww}M;H8GH#C_1rI33~)bA#ns_G0C;0@=0_{~QOj`d!c*i@F< zaa@gLYx`$G75WbGBII258p4$jb6E8q<&ER2>vm6k1&2^^)Sr}v#EAdaWcraH_>ku2 zBT6}ZNYmnxerA98(a5^R59vnnqtTBKM)=={A0K@7?T-(zE4bJ`8nNB|%U>U^*h_yj zlK=iqtYoWP7|X}ole!MT>7R&J?|Xzf_5($yir&l%HTw->hRP_9WYS2L%HYh zL7{T3kkoa<3lyAz7T|67=Xl-5E?^AcjQj|?OFPE>O!L0E`ch}ofC?|*xpcXNqIZXg zQar6(s5wGk<@G|W>Ff~+)52)mE7($vIQAXPbpp&lmnNm0u{Ytq8`7ee7%k?GGJZU2 zvfwwOnL8P}@X2?Z)gWBW`0T{RD<0U^$<~!TuV%E`z{Kv6_C@XmHV3>f6W!3JKltex zlZ+y}SkbP&14KJt(28n2v2S}e4TV{t`iO{4HLir_i{_l(c*Bh%*?kyM)4N{fpQu7t zItV31INp$Va-X2_@`HmMuQ~WJP4~(;sbsRji|<*{n8Kcem65~< zTOoarhO17ks$*wAw~aE9HSNm2o0(!z5gX#Q#>8Vmj}av^jxfMoESFXmPbJ@vpYf4! zYQOG;4B?#Ag2HEhZe%96tcp0gv0S;8{=>Nr$%wHO1UAGlK3}2Wl-`q2mR5KHta+o0 zvjSbvN?@sXZ*)5aFQ^Vdvxt-1T=vJyb?CuH-D)6?f#u%TsOjcsPx7UzS8wEnXYf)o zPa)A{R2QHy&5V&YKFA#qU$3qmp1B25&nK(~cz_6-dl>e}9VjgXfZJ(C`@-kaa(JJn zb5KUak>i%15^md{y+4=}U0el=Q1)k4&fV8iG+%yw+1$8cf*3du7`VYRh$4zqG;FrI zg44(mEVwLD*WhkTqnM%Olv0lzt}kH4ks^w+(fWkTpOek4zIvPY3dpn~QSfAO%{;>b zFR!9X)_AhttuQH25x@ae)d%@t6tE!dgdwiWbb&_})7DXp^=z(92SS!&pANPvT;bk0 z<+B)yz&v_d!F-7jhMm`2rw(RB94|)A6c+<5%m{+5XwuD~^LewF8EX>sEFBl`Bo|pM z5NuX5DM-{i#&6T$Wy>wDb)<5sN)hK;hX_9!B|{2GI+9|Q(KmcLv7@)SQS)ZHxm_zM zfqUx(CL+xOBWMyHJ<`xf{k<@2uG=pmf4pEJh{TWxO7A%-+JR&Wnk0}c8@C#g!tz970L!~bN4s5d? zKjAIl5*q(Lc|Vbpnl{RQ@~sREqK}@XO&3_kUCz;-KWT$HmxBr;kF0A;$e3jEwz+6- z+J{i0+xmM+$;-aPa$^3EoEC=z(5napJNk=qLEKD!dbc73h^1}@iVXyR z;)q`x>xeyM|6tIvX{>KA61T$%=-Dr&_4w=;Y8CI|ej(=@ZHo1R8c@mm>ojt>#k?mU0jzljb9Y@<6jvLzy8R~|6yNGd zjF-*DglfJSl71^}R8bJSENO~koNu+QX^J$QhDt5O;%;tG2Sl*xjmTL0`u8R;gm(3Y znLWp)a(OJ)G37c$%HMN%#4b|Z>@hZOD4>@w;n0&)(#y|-W11h>6rfc* zDf|;<-1pecIk3xV2F(W61^qirKNOolnZunrVmt@q33VI)c@xjA+xX9$-$gU;HvY3) z3^QaVO$nbd2Y{^U137K;aVYFDUM+>9`OF&cTHb9Cc!U~o=%)kJ;qb}Ey$_mfWLoYp zF7>A6X$-$gsyl}D1d<}?^t0DI{~@RzW56)nT6GwN6~}+Ja*9XCJkvjC9;7@@A;K-y||DWORQM?~n432E*#a|q7~(9IHGADfn4g5|K&`Pma1 zJa)Vu(@^q=8t8ifxZU0QW39V^Ltt!;2R|25PsZ8s!$HDlR!8G-Ahte_`g3jUKSa`S z8^@`ndyW;lK^KV1iZam<1@ZSBCF@oR}<9a z#e_o^()nsLzMjwgqVIGPpV5e{hWj9GGMva@25Cn&uX_!n&aOJ`*jAVJt5-h|voNC$ z=!ugu)E|u**>7B4t|;T`pw7DHxX%67SK=72G!V{at_Ony`>LT3Y4z`Xfu}{+$k{?^ zFy&YO&XmxLlDSE8P(Ma<-=9!^{18TSXRF}@c2dOd13Aq#%i;BhlgfeP@;NjjmWR;H z$JNLZfQ}7TFBkC~svHNZ#cqWxBjdOZVbbDueVOi!F6bji$_JPNEXhSXq@mPqErlh8 zPqe!|L|gERB`Qk0%}l}ZdrrTf$gY^?Tf1pSgUg0;_SANVrMEN?+kcL&ion^`Oh?RP zuLE%aQnK7|U^R9K%2-im&e}g@U&IRLH;qY)PaH#}Icx}Y@ifB7u@q|>_v3E*vBotq zz`Qm_i=Flx49p4Zet-#+V~cSxX4YmpC!jB^B_$~7&QWI(Z$$(9ZR#+j(PNG+$!A%; z)8+QQ;PL_y#|&uh+yT?8$yV>{(}YF%kPlW>H}vmbR1+*U4#t+JlF+{aGs-u|-|1rw zj?+99S@D(iLFZ-7bGB$~v#R6@4NraB++*v0JM zwX@&cfY8l|^J`Qo-JcmXS5$j-z0kZ4w!|;R`GgWkFOI3PDmf_r7mladUo!X+n@O)6 zhy*YE(9LNNTE@6`55+yOZ{A&wCyVu^-pVGWlfQvwSU~!~ z1EhlwDcpj>H;RzYh8;Z~>{^dE7n-1|V%C*Md3Zr{3ZAQe2l{eAO5*c|b<=RRr2qQ@ z*?XKr(kyrMMbx}30@f)|61Csu#%+$Yw{ZR59NOCk# z5~U37=F5oZxAC7h@v((H#i$O)_EMcNw%Z2z_Te_YM+YCItZN55gD$3+++DjIdohG+ z)m_KvqbIZzFq5qiMRMXNx$+X2&bC}~2~0zg-_3Rb1?pMeEssuSk=#&@;IpaGD>cr! zH;|p_DkBKjK3qY``|@CJE-1({Aej#m`P0aMl}>4_EHnXSOO{(B%?x|#T@}SerJ;Y9 zag)h2p3XOT!Lt)NY2ATbA8Bq^s5I4%nVK0x_R+V!Kg6wZ_|5r zuA93;DG=#QcCTtT4R$i;*AqsgxAT)c;(wWa~o20h)C#W#aY&#vFH5a(e zL%AGyk#M)y_<2=kTNPPEv->y>5bp^X-Nm6C?hZ}zSb@LVrDy~K@w65;Yn7u0dz3n_ zqaJdRUL@|&xiSv*SMHV40f=@h0!^fVW4BDKb}>aor29@!Px{c=iDcnJrl;>F8z0`) zc+u0=N52Hg>PNW)!xKq2LxFUkBxS5cd$7r~zThfNY-;y^J{+7g{@V8_Rg})V%cEs*KFu6e%!_~cS)+svVP)yFtGjWQb72C@$3PMmb#|`%Zuz_YB4a`nAi2x+`?${QZMxqT}<*d*XM# zoj8cWe7t**Zh`6PIdECsN~wB>;7VEHweVd#JfNy6<<4jsOi>*Ou1l)EJn1L67?zx% z;hZ3Tfg7-|`6!srNiv(*b^t^MJx%MOas9W$K$=V)f<}L0bB)RDxBU`+JPbNENDHoj zWc&yaf*0bGH|2X6V9;OWJEnHk*bV?284Y5E`=EBs{fQq20F7-0s|nE6uL_#T(r?4y zn=K;&*H@`C#qtY_;%-%Xhn$!w6No__E+vL$a)a&zoIUv_cm;P;NmH)s-!ZB8E#^F_ zh|rTHBVaOA5=n~D9a$%aj;D>Cfb6W0(s{Ko7O}SiX5j!AHV!2FQ;G0Nk0rvF0f#d{ zP2)8xWc@o9vY@8H0ZV$4V4{0hK)#1FdNR>z_7q7ld>g6}mn%AS8+d7COTBmr6BmV1 zz;Z~^4t&??p`6se4JQlnGi}w?t0kC|UmTNY4p0l3B!qLHv8YRJneW~Ip!*FPzd;Ry z=weST-wW=nUs_06~v6$t}2^z{o(7{qPE9(kAfRAqq#EGtrRUoTs5R=cA)?QVRxGehaQMM`wceW2C?@S z9Km;&dNuYdlPYeeh9tiyb@Kk=Bv`V$9hz)`kd8!CegI+=-O|W&d`Y>=rS})geK1P< zU>d}SS%j1Ov1Q$>c5mCNCOc7J(Y>lMJUB*rr-_|NIamSe-5vl2NrnxA_8C#esk*~P zDNUwhS0xG6NgiDh^JE=7x5@hkfa(T?!so^RgA zv`|dbtbYAbq>gu3(~dSacg6yq*W>by^Zx7rjAJRT^al3`Rqg#kJP6Q}f%i>g zi2@S>a6IhRX$IpNMDupg-P0Tdgu_Q*vS@cjL5lrf4!MU~gz(y(lpTn~_jD=sbjY35 z42u^CNFNWmnOcPK?}P5A7D4>k+{5-ZYLIH)O&l+&DB6pmS5`ApUeh}QgKn;7AWp&& z_kntGBAd$td*4l=P7k@%n(%;5KNBY-J<}Yt=;MxS!2oJnRevSZD^z#TwE2>Zms`~o zgTwbIG2`aT6C2vSZ}4>76gxa|pxf>O2g&Dt?hMAfAeg$33KPNXw5F6`p??G2I~_|T zV+MC#WOo0aP-g%Ek&MUg3I(e`m4P6t+c2nh}(_y%wxrwoqk+cWP zozAA;Fhemzj~u9vGS@-+%a3J8D4MW4?w_=nQavPjG3lEoF{YV_gBFef$%-)=d<<`9 zeY;xsH?mt!TY8pnF3vw%(o#ZLzF(widr2!i^$~r8ODF<4R z2tFN@&Qt`RxrA4;In=PM`*WCfqjoKj%r}V?S4mT5GSb|f=l6YHr zKQbhkW}|t3K<(C(pcYoKAr@fwk#r&3p%ShG^Pe(7CHvL;VQO&)YciiyXU(UfDx0}n z>%$6-WDF6&Z@>S}Ooqeqt!g?0QftWOJ{U}&$LR5$QM$hrunOOPs~s2Elm;G1l@G`V zO9(@v!NDgMlpc24ARR31Ka=C$VOn2ES*Yn)L6K}^fOs>s>zy}S*b^X!>`ozdVqXQ1 zyKt8JCL3e7fq|t8TbUZiNYMbn1VeK6-`jD1te>T0{rmD|>45!o^@Qs}&#VuPN*5@|3oAR7(J0QP>xYtWTr6>{HH;mD z%ER2@6p85d7y!;6!3{jAofIst4ol5Xl5)h=#)waGwc*#BnLoYEnD3EEiV2sY7K;V< z;u)5d^yH1q=HWZ3h?9Vxb5gUT(&E0YvUQLwlOs63dT$q$689AnN(x9@|;G+`a*9BjGB~`Z4_`H(a zLM-)hq2y6(VyU%df5VB@-U&WPbNF%h$8rr%7^k&6jSN2 zK=IHwgKLKtz(LZ6oK&3g&}a+lF?pSv(84P;{iBp<6{onp=?R;HUQknG;dP0^29u5I zUz;|x*M;gRL&Ypi#{#vSa*=2Aa&rk3w4#*Mg}nDVkr5tLs`9z3=Ifa5iY|I?D$3OK zt&Qb|>Wo|vD6JBijl(g5co59Dj>4K5l+#0NL?)1s$*IcAGdH96Bb0)SP{>L_3MayP zbjQp6(O?{RalEHhwT0{WwR7QCo$z~{nkO$6Ap=cP5;CKZvk|Ti4paxQheReqfu}YD zh%CH=3O|Vmd<`jhl?bGT5VtPRg-~x;@>9ipqlJz>9>QS+R4e+9${$hm=_Do zNjvmyd|a$vR4z~?+ziM;Q=i7=iAoru)r;nRv#6|o26wJDRDA$1t3{NeqxVftS3I7Z zJ}P71y+xkTjzG}Bj(1h7w^UVmad!vhPK7I(r70#5;Blb{pqDkT;WOITw$2FrE+t5? zFX3^h2Pa>`3J3GUKRNS6%Z^lONxrVaJ4+sviwN*#D*kBk;vGWr`dyI#BDPq4rPkV0 z5yHEj*4ko*0SQEAkPiW(EI1q$#w@}mc7zhlYfDYkjPm$++m`Sj(hd21>8!L64vHgK z0QVa(KA{Sge$}h2>mY7uSyy!7jXRhAkmT2(bkUg5nQYq~n#$F`>Rikl%58|=x87xP z=_s<{Jc%w-tLcoNRx??4tlW~4L|Z>lK4=Mc=S!neeu+A#F1sn6H=#+7IT+HWqW!2J z4b3DD{`&kJONCotB6kdpizz_Zf?qj9yUkkn69x7 zW3wm<5*`#(EDEWWG~YHxUQS&4xQZko>*%r`B`ZmS2>D(T#xt#97g%njk$zaz z3`+^$LM$}glCGLc44;U^S}K1(A?y`WtL-mhk49j}pPJ2fj!j_2aG1uym34iR$?C40 zc9G?pRb6TWMwyFS2Y4&!b~{GN)hn1Uz0^#u$-Z41{mr-NvrVpEme4Tf0A+# z#B+Mg=qC;G`ZzJZgnlV#?K@wd>-9R{QQPuTX;H^LV?RuPltHjTq(H!QzZhR$P4s1J z=d2Jvzz%!li%;A6rrAwbvt+}%##veNY15oHn}(jO1s4KLesdfzX~kc6lN&r|z2a8~ zLR-3qw@vz^2-?M-?pFq=j+Y>#FBM6|+5uSbGrr^V{Zd&Wui1la`lk3nJp3>^Y0T%J zf4-hpylg$ z3FHi~fHR_)^dST@{a}Uwp$*rr>QuP_igXPeJk*FwsXTVeqL{zuU^Cr3YO`r{$BAzz zfktglqGGY)n-?F+s0MyAoi=OrfqW(3T5D98g{EuspaHe^u$Ir4%Vy)z6Rq%nwqf?J z(UL9Q<1DefSlikLchg+sV5@Iyp2e=QXV0{m>#d(L>RKNowZ4Ijr+`rD)SuUZs4cGCD;z)6Qu1vXxq5js$L!{00)|CBt*d- zgt^{0*1jmBgKOujO+H#PeFqSlaH{Ro1*O9}UlNq%c9RZ!x!NX{d3U>RcmhWxUu?9Z zxFSGne!@u*E7jaR!#?&48}8s>(zF?o4;>9qjA9mI31{AnGwI3Y`1uRD7?e17_rr#^3S;>xkJJ1PxiXyBanFaDeHP}&zHi`72NAredO=$$Vn&L!}3hBU~aLGc#5G62ks#Sw#^ z2^R6kZK2^-8Wv}V85Z%V1_6`Q+*XwM`5$P^>OrC>2{LW;F$RZ>q!*L3Mx6p@?chA)6MFGK@?Hp^Ve5um z=MyP2B@{c85Dy^Xxfjg^Ea-FebKK#VULB4;w&O+*+u2Bg(RwtR;bzkgb-ixWC%=8l zPod9da-Aa}cD;RUOpG~KO0($Bw!8l#-Z*UW=l`RB#-yL)kv2!J4?U)_C80q=YH2UvRa*^V)vj%f}M{-UNT0-7EN%^9&B2S`IY9v~0|mvr8U+O9WLI2eyz zCvpTyAb1Slf6ty?GTS-Er8*ZwY`iX#G8d;ZdiTN|NO%NlfH+fKor)EB91^11xlxr>18w#fgs{0lMU)a;=lvjmN7R8ZWkKpik>fO zb1skw2~06}$9Qtwo1%!=IXxCME;ZAY0bBP3<>LkFTFt)4zKr+BPj6_83-iEcf3fmQ zr#B~U9d=dgT`gt?jYx*Y<|~)-IHvHe`sGV05V0)przJ@pwO9?bRtf zz1*y>CufW1Lk+hN%ROphbP|kYFGS3QLkl?N->?_>-x`17#Np+|!v%mAI5%ZY^IK(&R%0VIzML#)3)!b)butA)smo$@;YepKR%Y!tP1Q9? z+RT^la3I%xC&Rv5(bRe*{GtzAIK4uY zd~+L^Smu6If0e#{T-e%V7<}nJ62-Y3eF5iyavr&i*+W5XieHgZJ1~X=1e|{XAN;>b z7SqLki(TGpa;JJYa-lJd113AV)|D!1%mpR-w1uG*z>W%M)?1dOFb?|K!WCUzk!+6q zyY}$pVg-KLh%9Tc?>O0p4WOFxf81PC^q7>v?+K~dm^Nd)gb-pe9OO9B_BhZS_S%@J zNpT5$`8r)JJVxSUJ3x<=MD}mmNr6Nk@8H6p?R^l;F%UNvn3^1I^m)43tTv@}!egY3 z>XzF!eIZziNd=|!S_sWym_?$wh{FlE`yW2g8am-$RXzc$6BIvQUPPx#u~eW>DN9ty zmM1_DK28}sfJlZ>2tZCoFH$vBuO#lDbBEwiB^JjbT>uq{Ojp?`IC+dq+C9aOL@NE4 z;SRWjcNf`>3>!5d4@o7M$FEsmhOew7IBCr8_qQ#8qCplcxaPM#2BJZh2UxeiHzA1 zcQCOsS*ccMJps*%34bON)}upU{mc|}+MxQTW)cTjm;%lax4}4I_OJ-}xqB5xIMATT}sG7G=Wz(4DZ_SR-w6R zaQyluJBhK^qdQo#_~ZwY(#T5bnwPTH(H4gpsJ&U(0CR=n4gbI^uRm_3DM^p3`1Kf2 zXpLFS&(d9k7-< z?9yh)U`GDxcD{V)00i~AaxNnn7o10GS^JJ9L!$hKKROQELmZ^zJxiI-RAY&((q@(*@p^xyhhECU-TbOq?RQu4f{Nt|+jsDaaWPpS+6@haD`VJu#WxbdY`$H` z%nmHO2FWBOM$}BYD?}v_oIp~AFkacR#u=RZ#4hGH0_x!r>o;$Muwei%nK?p=(hnKu}rU21p-lJAm1Zwu-{Z70ojmf{c>`1!p~5ctab0mWF4O4 zme(t6wSoaEqwxZYLop(Qh|21`c%;flC8UD&u@$DEt1hFYtHvnP1M^mNr5 z7X$|zJ#_c#kjqP;M%WPYIYQ)ZA!4*?e#F#J%{e8P8f{@{*|(y92P@%KE%Y0o-9jJL zX!Yv8JfCkcb7rgY{0!y|Xn^->+uRUHt>9#x@#G8(rvLTJ4_~DX(oDzC=n(pwj{gCNP%6I=EQ6106vFgq|Sbnn-8=d+dG@nFw&tW z&I*2`(N9~P-!*Vy7U5!FNjMI`!HkSL3QNSuWW<@4ec5Na+>N3ugyw2YH-ivfa94iD zbe%WitT4|wxiAo9dc2uzb}sJi^}WPWLg1Cp5DK93wjU1%l-%0ab0%n-qd)!s&xi5+sMCQ__~h<%5HRxnz4f1sy;< z?H}GY$QYbz4V42J(04rAuljh=0plD#2k7APX(^>J-PtEYlx+z?``$-F{De$lW!W8p zWVJ2?=?%(>JK>XkOri9~=&jB1DnaUr&xxn36Noi^!iGA-PA=!?x>S|`_og%1L#HgO zV6a-f+pnK%K30-`l!`}ur3}*8I`Na`ms-p%*Mm`aiVx% z9s_I-os3~u5$x2Zo^TG5)zuywfu?6W|XiXKd4qjpt<;UQCZ7R8xn%x?Lmhu(8eNgmx&-fwy@an6d7rfCi-;B>@zan`E ze*d55&2`$reMVwefAALOCT@)TxR3$H}Zk^OLE^2x7>a0^nU%@_`c2;=@}!8{1@a) zah3rs5YIX3TGls`cd~cJ7Y-+dtt&OUzC=9!crn3U6SzW!tjfIbn%M9tt{g|eFKm@1AidK?!m_rFZ zXi!_;Lr#K{P=}WY_O?%&Ehtoj?k1TJ1tdDuN~<}Ktj9Y1(6Z4ij$T&YnG3^^@7M!A zZQEk#8tCuY*=t99iL0HV;ugf?nvLTSc8WFX3yLOW2ZJ!nakFFkc#kU2csX?{Nrz{= z^44(#;5GVPuQv98JywJ=WS7-xK+_e(ga!S;!!C543@>pImZtXvcj;I%Oi}MRP_M_? zoMR0<%ug$Z6uL(|OEjPe`mrjT0>3NiSC!qY8{JJSnmIaBVnS7j_H!yl$7ZA@FJ+Z+ zvI~rGpD_%{(ZVu3H_ha61j`|PKP)D@4fyz*`X$7&f z)zxG!H*@odatgV_G^WkTb_so|MkSk7>P7g+eTJec7OacA?Gh3ghL>ge3}T^}!%moR ze(6Olc5;H+QnwTRrIRD8z*Kr^cKZgP|1@HbE)=W-&3PRvHq7)>3a&B^yaWlPi-rAE$dpTZKtM{I^oJIcuA)zH~~TsW?>kbSid(a^r4)RZ})?()>PYbR4FtpIEg`0)ey;xc3 z*PoBc8Ff$pE$h|XG}CbNF|sP0gX9lf;zhFn2SU{;8o(s&h%HoXz|2~F>Do3YKzQGr zx!Xyj`x^x{|j2 z2unH*r0mV*2IBzK_KHrNaoI0;Th=V8ZfsT8E zA@06^TutxAPAbZa_ycb^-0UZ9N^A8R6P_AlIRHA$a%5(rYgW`!T1>P;(he0#M>ydp!Se+&dpQ9Vow;*|byu`^oHbrB6NtW%dn-+tLJlF1UZbA(uR(`UhZtK6`yLf;WYJ zX+uEGndVy?pj>zs@nQ^q9sQvEU*nbfpTg36(T41$^>M#&Q{As$E5JB zfMxqU+fFCTPP(;GnP&Jzc(mrgj0M=%a_?%=g6ko>d`^xaEy`2q+%cLjO#uC+>0AmE zRgvg>@RtJ^WI!_>xZV=mO4skoV8jLK(3?s(OgS3XGE93ArqZ#0u%rrrL^yyOk;K8B z!dX7QrII+a_2CQ0xRu5vj8p*&!xvHsC?|1ux!K3L1i^#3b25Pr(3MS4bXnfGwAU#4 z6Q)_SVN>Z8+l$rj$e%6tM2Tr6*YI5LJ(BN%X;G%>z-W0Ej;;krvxc2hHS19ek!B4E zbo=zoy7Zrz2yP%|8O2w7d5DF6Wz&{5?B-OCQrVmpL3eN}huwEUV9R>KRceN_tJb;9 zvvTWB#+AGE*M+xuE8=E7oVY^2GF@52PLi@7wONxj?4C7Qm;RjU!y{gu@ID0ZdV`_D z=b!1KEL=!V!3=(>0m?tdyAks%BDJ%bxJjwWG_8mMxeG;43>C)}cr9Z>q*RkATdlv7 z?{?&FD9?tL2=b>7ghsNuo1u9_$k}oE7NwlTOKiG(npuj1>|e`!Qqz_OAGj+uy(L4n zo(F9FcQy@eY(rL)WGI*QDoN&)MnFEbw)nKbgV35>+&ZGmtjh(343$EH<3|wGjB>;> zg+^2^O0IJQqcMky`=+)27mV3*=mQYk#FZ0mzB=8K?b13?tmIi zd@7NmzZnh?9eDYpKmbZ{=a|o2dYOqgwxDwf3Kv9WhD?HiJh&7sA9s*xUth-{F&fE) z?pSI1&ibojq$fRvC*DiTKzR!{xoPoyE>Cr8Gf51G@^mt(FoH=2PbVaC%geAbmz_w4 zWN`t|Rm1H{osDF)H1URPz}kkkg`*Z;c}2*9-p8V_X8$~+py=tlw!JijT`qCnGvH;n zndD)6^%`cw9&|QB=4lde*R~g2?2vKi>100R`zWZGoDE^Lfq>^7FisvwH@!w9JXDwm zOHB)gOKp093dPuq{w;xmvQs_vWMK-;>BqEwhQVeuqN$Sc;S?WDD;kK~^xc8yX|(+Tb@r{?+3?uUdIzI~M+NnxFy2TUhfx3jZV9@$Hqk$AWv z&?y}ir0valPvHE$o34lnKNz-eT(llZk73FkVI{6=B{Mh~h7gO|7jd&! z{fX+ug5!)S(YBdT>>2{7)8BYj+YT*>>nEg4^v#G;+ps7Z-#YOmf@kYnFub15h3`an#5=qS)7B(WRS=j(m67sj z^?TGWRoxTA9YVkIGyU|EoyjC8mV93++Sk(I@YLJY7mv zaniG5xlucQGu!)TZ7Yhqkv5&0TXdQISj3aMuk4#~7J)ob)@f-9+svM}x7f4nY!sRj zDXk7ip-;`}C^RMT?cQ&pQ-A;97d(7+*!^0^e)r+`8ZMQA zXeS?TxF(2^HJjqG=XV&c@g*_YXancjoL?|PVMQ8}sPMTe0R;m>9$fZsc;#T2%=oz+ z9vo!@QA=)DdJvL{5frJ67@_2t;^AbN8kYq&Q%5x?+-{e+Y$w`;|9xmteKT&;Jv?mcYcWjri>m@Fhn=fE;1^g7OXvOt*FVWC`| z63$^UnYxDSOD*c(+HktuZFJFXZ8)3bT&B;^7n{jiGfP_`E>_n*h|$`RU#9Cb^qQ(` z^=Y`p3v=oYw+_9>tvRjR*4pr<4}bP&oB3=!IX}mXV9jidN7{8_I}O}4KaUY|MiE8W zLaBi&dM`cABjJin+=EoXP6z6Mw+fLzOux86_@h7F_a-HL<_G>#pMNSSOc!%{oROEQ zP)gnE|8m(z0zbx{iU^OCb@svggm}@?zaia&ex5dpHQsZ_<8C-!@Zp|;5LSyZtdqlB zTrNyi>`g4{DgRgLZ3ud%wfL%tC#LkYsFP*qYC#al(x?J^ zj`W3aML7%N1F9t2=!{0^H|<M*_o(rj>r~uyQqWLg6z2wXFdRe%@IZQQ{C$+ejNK#OPJ8Z)Q2i359kS| z#Ix8i1kYbDR}NNruCf)iCY)c)c3pxf9YMHHR_>5Iv7G_r-^b^Z>3lKY>GqQ_ijl?J ztyf!p{=zyJVtwMPrm83fv9QR2WHlplSWW@0JMm!|98L!UIQ9ZPd`-1Bi6fCK- z!HQAHbpy7KKBcin$2U=x22xD<`17fC`gyOSoWPw&F0(&69xCMND>$r-_7kffA$w>_7*oh2g-xNYvbp-&<*COR35-8(8WyF z3$HzfdGjqjch0rs9E|d6OD4hhZ<7Yq!3LW%lUtCk)qj4io#OlBi-oeIjtLpP*mb}M zdSAF@1F%?~eLX&Gn-{rU7%A-Mh%J7?hR=K(E&x$n);3M*1OEb%-P z9PnLj5XOm%%RA595AcWIJB0i3HVhFAL)R$T4!4DhRI6xv>`@Fu4uG(0eC;7Oc?WjB z+wj+$Iqt;A%Wn$;G?Vw|B*LPKVXZ=FqZOR7W%TfAsQ=m1_xe+~smPtA>|`wcQb z9s9!8t!C!QitvV}msx>XHH&3nU;$%VFOBCFG#=kOmd#~zv#U9_>alyXZWxMC2e!@& z^#i(zPx|tvCF`vtTGxR_>WcS9v&@XNCT4|rhbIJl`IRDGiovfD@-i=UR^|(@!j`#l zXxQ?npl0@G*Kv#^rzCKgL^G^3d@gtey-18STS`G-rXfrR4#)GiY+uA~yqldCcljR8 zl7!lfPcTJ`af3n>I7)J3r~BkR$~@BVGi@+%0JFCY)B$Z5(4jd_u?0YNlZ~fPj_GQ# zIKy$|0Hbb1w4K1L?N-L{xWN(z5gLbh>02CTE>zFXl_qZ$|z_Z2CgVTODePz_m zBHCcQC!Gg|C>;glymbq0SL@sHKfL7tas?A{NrG`C;T09zRNB3TTWZqMdfg*8>O% z@jerx^TD1(PJmSOYXD%r^vAK|@maHM-Xmdnx%(!T-?xN0jx~!oTw#r$li`Xrz%9L3 zv2*|@LC$kp;Mjews$Bvj=}}Oijt)VjRV4rM8jjF>u^4am%Oxc|M3WMX6KuhMtQM%W zr)!AJq7V8?V>_)RI=fF~mm=tBLIqd{tZwZkTji*;ZmdG#9t}33%1c;RXsMZNq;xqCM3Yq>XyVrb>p};pyG_Mx(0#E~s%v_; z*rDJkNkoVN&*rT$3V52GbY{)oU`6Z$5z3Q5R7EC=4G-cG(5*0nc1_l8>I(Zsi8@Z=egS5gVK(x* zAp&$q_uT1rv)|I8r@ou4CPxRN9SBS+IcIj#k-VBI%2{lqJW+h6cADXON@Ha|5%%ol5YybUWeBnK-7gYV=-yUhd|4ns3NR$Tjn2%e}g(}&eYx97q`#G@N z5uLN4=b-beD-<_B^Sc-w^0|HwV<#jMs|HZ#2Wp|SFzEde%&dmBbBd&d2Kr(xxW#L_ z#8o2m3Jxzj1N6siB6kD4_}p`woPR)EH%C5Znd9NJrU4(FAj;C@P$GjgKR-8=JXf6s zf}rCo!dxlj-;goKn=$X1_#F z71-GP_w{5$yAK>z;0nj+D89Y%@W}nV9Uak{@Qq;d?ZYF6RO=+e#9jX81n-g3X+M^k zE@~=D!-W|O+zz@!QX@vBV)8)i{G*M8la`fYoqO}`O3>=1%c=#Wx~kK_ivGN&Tv-h5 z{)A$y+58YT7CaQ9UGsCzwp56L`Y?0!H<>luslXLERWtL%VNlg3FC@gm{BA|`g=iWb z0f3igXQCMJNwNw=1 zFMmxmlv}AQC zq{%IEMaL{E{30l`MJW98x4((mmHPVW3}cNbtSJdiDy{!tJ4mPgKc^j;wd94mtTEgD znX%=km}*^?44UjcLb7nr^>1&NwtHNT37LaYU{N#?EjIJ5Gcv63_=4r%OzIu33vcK4 z%XI#Jz8LSWk?f9oeu!3H%wc|j4!>ygF!>qhWah^uHZ^nDl6v>NMGOHe^k%hOUA03g zw~8RSwU%S5x>AA&n%2d7hlSFJmea&XCqcjcOu&jh=yGNU;%^d-qv5p(WBmD-20`M> z_}j%5E~kY2_7KqH6;g!x_l6a51&OVFeO@x~g+t{poZh9SlAJ0 zc+b9bC|R`A#P|!s?yF<`N%Db&ghY|KqEYIbBsnUeItIbNTvG+rI{H* z1D~QJ|KWrC6GXOV6A7^Z`Uh%t>^}NEFS6o*sN`NI%QeyGY_-kD2t=U)p-ylkvPtWF z*jo{ehi5zc0a!)cl+nh{MJ*2+{8#rc3}!5dH!{L;!?I{3+SS0`GJ~8UAQt&xXq7b8 zEMkrY5+fb4nt^(T_l7)!Cb1?69}YuLw^}$%@L)(hy|EAg#jEc_z&QOci?oUiM!3G5 zPsO;W%0k?C+Usa@Q)9Rg{iO3eIzSV=y$~Rz0)9>kN~!K>5BU0bp@23bSOY_xmpqo< zLiT$Yhl0$^ZXQB5JIZfFLKD07cBbLCf81Ql_c2b1`L|Slc6-Rmje87zX5gI%#!`^Z z{Z5XlCX&5N2_bl~05nkErr6p80C{w)90V~|?LG)<4?rwfa)PM}=R~bQX>B3G;y?nB zCwIhm3R{92#>W-oH@F49nzeF^ibWBrG!PjaX0e74p{wQH z5SX-Sa6CjkNulw#oaV-pm4Fs-`0>G4PKQ+0A&mpkz#3dde-KJqH$_oG?2Q0B4eUi= zT`80aSaqyK9T%ccsqE0@>2gL*Tx)-{5JXkzb3z<7z388@e6Pc%jO zv&V=0M|P8REP|TOHJW$xY0E5Abn48M79p81fUN3kOlz2!&+HkDz%grgI<24tM0u zh*5&JzCf7Z>1MO?1)kW7{wC4>Kn?JEEf+kzla{C|T99Hv4p&-Afh=1_9yQ|SNdV~( z1?7)I=~0}>Y8r=1T+;#MVgFhdKOfafILysX)1Lz}!VhqItpOI6KW7Rs`Yi^uV$g02kFb3_ zXYP3zz(jK+gw(y~G-i1x)%T9I|d zIX|a6ipMDKFekmBlnK?=3@7(`M&=R^9v=BqEB}Q`$skyVv>4f%+Uyof13kUAdxcC# zZ&lcZx2}lCFf*^9e^yxMyuhLb&x1LYQ%xjJXrd2i?g+tz@tiUyXmTm?50B)W&HXgr zBC$b}1SqLN+x^WSDDuRY<53?M1hxcJenLRN|Bw?)2t5Yi=KY*yqKGn%F2@L5r-UOx z+aMI7swM()Ek%+ye1H2^UK@%(lo8kjmL4MKhFB z$%+a+`R?oS;~!36AHRP2^7-lb^|NOm(oe7WC|Lm4QgHd;g$GP~mjJRF5IS6d1tD3~ zAfH}Bwn?kpj*8_aRrx?M3JK52>q=8Y@l)tU#~NP5_yw9e33Xo_?{EuxI;R_8 zwk0l2Ekal2r7Qnw4)wRY*)i1_3$cJox^DoH7p&;&BK0Ow2Nnnac<@V=LOInrHYopj zKUsvTsv%S**K)1ipfS6%%-G}y6bsPWnf4b?8~^-wj9#U*Rw2hckc0}Sd^QyuM{p@f zjd`Kc@S0A)OV_OGV9(y+I*|eoq9#>7n;_>QtX+UgsqRUxG`?!edfe8=JlTQ;%(*0n zTsaLv5CF>NsIsa3R=ud(7{wWzjigXJ1@zs+RkWPaz-Pi=e<$NaE>wE08K3Kfl}kKk zR58n7q4@DF7H-U+yyjvkY|WOM4>-OJ!YYjrYK`&;WQ>#@4!$YL7~n_C&%KO;7f!Wc zH3PpR+R34MY90?_MX1Nvwpz4tlxq>9b}C-Qy-jKix6>;ok2KGmT45cNf{i@aWQvGN z-wBv6ZVqL*3n0IuIh%DyaJ&}Y4=9soaCd%P&u3n94<~W8Y33Kpv3YPrO-v9$-30k{ zHMXs;L`Gzr!>Vf9`YB(nO_@!Ys0;tv;Yeu*c==>nK0Ej;J%QX81z9Q=QWWOkw9;iwN$PsDsB|tIOquh z_DFr9!Tr~z>t9MiBp)SMixfH8YTJP8$MhJ=C5Xb<^$9e14Tl?ig{L@v>j~@7FlNK6 z-g>i|;{6=DL40?I*w_m4c%<}Bn2F@7=x}jUzY8*-y{>4N7{QzZ)!$s3>JlAb5=*En zju?`vCW&p6wU-#+N>wRBvPY#|36U8u(Rk0TRz<1B<1dwbO`Vtu@rpVHj3Ps;UW>;X zxcYyCD(A5h3F2wun&o(PthGkXmseBiT&xG!4-Zp)8oi zhy}dqj2{&yrXN|+YA7QNjJv9YGmFRz5L#B*^^pRW_j~k9eZN=lC%FCAyL%;_vB{9} z0^^_WBrIm0+yAlBP%*LOV-Q#I2OrjPUJSiY z0npq)ca<530N{;Y#Tm;Gu`j8CaV>Z;*pNDvdQ}3E6Jo)5#nDMh`8A_J8^ZTEOyL+R83>gkL3N$*HPROJ zDS7d&(46F`EA~a+I_YR(B`?=8ahsL`CSvUFLSGVt517)v@)DK4<3jn~k?BbbKGqQloueV_?G=?HAqFv?uB4EeI-F!@9Rl*|MIfeF>f#X*iyROG}RS zq`=MJSb&F4pLUV17gRLH*N1ehl8eiEp_tu%jWQO=d=L<*s4a_{PA;0tY2^}pk_~}1 zulP7SBcp9U%6wqZ)63ahD@q5Oj#|+8Tu$r)(uBYq%Jks&3d;0|z9bAeM+^Gd{MrXO$LeILO*&8wl<5b{c`xGwj@u6fI%~t@ zyR?<+&IwD*0cjhX0VG@EF&SO4{a%P-w&P!*@%#2jDfE&^^Fn{!SBM?hHSf4z$25-Yaxb4TEc% z!eA*!stOJ$aJB8us(_iMKs5JAVNfS^F<D$YqGMd}eBx3o=!s3Um^gBL$4NRk(} z?Zk48VrA8b$AsbGxOid%#q;r5aLDAGfee|6fk+DpLv8wBmU24t|_hjk48T} z7~y{(ethuRw?963NCDVKBUToabrW14jpV<7Pec)%Zf)y=42-5d87>cDqohrM2gP$l zo1RZmd&Q}t7irR#jNBD>CpE)g{;bB#I1F3ZRRxZfgShhSv{PU}&ZPmkS#}lSkmHCX zDm6_qW6;&Sx9M=t`_U#OU~r8}-md(%pHu`0r~HmhY<+!hSOQP^x|?EqL60iAPCB)c z<{-rB4WVFMYYe%=MvNAhZV1t1eu{y8Ww1(nJ}YuADhW^Ki11@8e;b5~V6c3OXO^3S zER9IxJctq2qi~5pbrj&-GZw8~Gku5<>IdOE#CZpe{+#l^!GyLuS;<)_3B(g_`|nmK zwoHmM*OlgRdHM_+59{7^!3Nh7tfG_r1OC z{mFnv9wGyjr@2xGq+JGYacnY#u9J|b&<^;NDjD`+)_e=Sb1i*HxuA+@x6<{gz1>sX zQ;9D7w>PKB(QACt!d?x*)S0O@&_4X1@ziq9#uR$!!%}k+;@!^zN6DEn#5+6j`s^pV z(PTZ9U?s8Dh1WP;>}PZi?T%KNKC&$0mbNTxVQJVj>GD*WOUAv?RSez?+;BNXZc##b zCq&&bUHo%wQwW1>AmGqUzB3%`EBq$RtHf+BH^CyYf|tbH*yC6<@0*4A-ok+Q&1XtI zuFSkcA?*gc5M&3aHnZOy9ESuX@tgbYRy%CRhIgd#2KVBdJs6fWeiniyLcaL4>Z_|- zA$BC|ACmpyy3x@B97(eR%sxs0gfHvTNS?{d?HC(Wel5F@ew0V?iV2Vaf@N%crTbi^ zlDa3fK@I2)wHx{=K7hyPYutyq#uN~0;%$Xyq>gmg1vE;*5T)bVm4D=Gl9(fiXIBW zrMWAl(gdbFdHwRKJSrOu0lQsb&k48vua_@e3z>d^bwj3N+)yASY|cm_nwxcU+H67* z80r-{bZCdTAO)Y1n}TdS=3Ar{0^bI3UEdd!(RttFC^BPT#X#pA4rt)>8%@E``_0^Z zP*DrU9@6@9?QNH?E#m8QF!$-rwBb+*Z=q1~K{Y+B#)WpAY_s>FEnTaS2DhDDr0JxT z4aC#UX$9pW%vXDvsh>PLy+l-+Hk(!Cbse0HE=!CU2f{qmT?M<;R-sf{%PAwdP*@r)xfVw%kp zfEkS@Yq;E0`%~X#*GW#Jq=aO>B{{gzTMC&_e`gIc-v#zHK}E9o`vB{On@cV211~}j z7Pl9Cl;;z{m=T<$0HPlQq|i>M6tfu6>z7ZQ8`IiX9;mjxX(e+}bo<%OkpNWEvb@?l zJ%`Nb6Rn5I#Ong^>ZA;Uz4ds318}`lHtRRa@sr1=kKK$2!$e;Jv@Fz=b-%&s0e8-oX!PC(Y^+oJ<*Ek?n5((U4!Wc3%?mz5q z-!}9FJL3F-xlfZHasn$XdP5gcw_6+rJ*R|V_$ajd_6#fk4Cpveq>x>(iugu~(PJ{4 zV%Nvsq#uR8&|IjP{UC7m5gfC>yY(v&RKk7q2OEue#@Lky6f+ip0@rW*-RPi_;Q5Ln<=7laep zYs(~6EHf!)P$)6d4G#4PJJSLNeYATnwYbV{{rXsCHS{1^c<=?HkGFvM1|PGq#=B*d z*XQv>H-RzM`4CRN<<4VX#GH>{c7AoIIfB!O1F#*R-HvyY3nLpJ)=UU4V3Ydoj{m(V z@qNkSJ5FG_w)_2-gb09jCM<}-jzoC`-BrW{-U+xH=rGU9VwnN5yddUUC+%>QFDJOw zm}surl@3ioS1&9l=>vLtvTWbO>5-iILrId}2U3-EHWNTeL&iBzZ}CxCq0{M?0#OxJ z5G0esxkHhsRN6MaRIoB?5RHSD;v7Lu3>b3(Flbckn-^fDY_FS*emHq}MiK_5!H8N) z4B0Fhpelmk74=XUDoPEJ)kRqgVDzK=`OM?(rllRx$PwUBfR^`)tX>6~7+8jj3NK~h zK!E)jQraSR4Hhqd)`x(Q>UA060Nu#q!T*O!wu!dI(3V(LOsTn|qf61PWCgFhg(LvOJ9 zZI+XZnM1`PEeLNmQXqq^c#P(}jGo-I155nQV|7KWK&T#NMwYsIB>c@nsM$dx)9FER z)E~J6$QlgV%Lalt)Lbvg`IA+Szbcmm5$???hr>G`fA#xUu2)d8<^~Bol&{E>L6^#F zJey3nSZJEcF{1v$ho9Uwc*WbX(A?PEfCz6II^Isxa+&N5@a5OR2D!M)hMDUps|uhP z^r9dAVdE=%`7a`pR2MDZP_~W$eiWNdfn$BYt!rr45Z{W$On=o|$-&Kc4PJiGc@N7) zeb^nzwFx}NIrkC`Sccj-q65iw&G`gZ`f1kiRI^x;mg@Id_Y)u|XvLTaFI0hO?5cjx zw8N(nHqFlY(uRRq%ynUX?1#rV`EecCO;6Rvi1B8$;clz+b$NXGx z8|x$Pj7H+NR_1i<_A)yoHoK#?O7DU>0mZia@&kEk+uNMJepx&nsJZ}7)y$HC zFC1bppO_u1s|sX}??iHIZ|_bi@*b~W(wRdWs#)yA2}=6Sw{BN@Oo@@p-JdVPwrp}G zT|%Sh%ecFpkx?fuoW{o^LIY+v{S^YB@$o42ovp5rBQ%DxP>Pm=Y$8i!O3Ds{>q)tz zHqR;PTMpz#S6?s!iqx#6)J_O*S@>7prAWYIJ{olZqydnXtW4f+Wbg%7$-QX}(Kg~q zJh0*9&2~Xgv)wM5?PcS`fI$1d@WV;?4j5=UKHHxg0_t#L>6BrS0L6Jw_me#}B_~EK zky#lcNv{RHn1kMPdj0ahXdP^uFBMdwu&!&8bLOvWQQ{e$KuXeYFvl+aj20MP+^pBA zhbi=H4TsLAR3oT5Zk2ka;=vON{!=Wf)oeBiEuRo3^1^ni6{mflQR)0eGqTnWy zaHevnHQaH_6m~RP%i(X?MvxIH2vxM4UaiLa4Aw)$4|tzkvg!E8$OXkvq2o_9Kk1>Kt>KcN9y*_>Q^t5e8AUD0aI$PWpu0HZ< zUg+rurLUY8fc0-W$<@B-R)$0 zf?%@wz{dQ8-ik9BbK4(}QS4chsiuntmzu>42Nx-6vs&wwhbQ(I*^AmQqY;+dtMyKs zhp8U7+N~aMHh4!>#trKZz&~kV4BCXn%e|mjU9ek>1E=*Z#Lxa)`{!-=v3Y8KQ}=bPp@oM>d}g> z5~0HIpxYw|o(9Z7oSms*ai2+NiDtS}&pKIQ04`JOX4Pnou{bw$5FA0lu>6s(;+KaG=g`WnNRXO03x8xLGmsSf|Xu-?*%UCqH-+Kgtc1DXyYeN@*Utd)zkjsiTh-*ztRI zkKgaXis>E&_jaj!i9od_!y`q%MJ4|@*!MtS0vXFCD?=6do#hMRtq>RFWwZnN>cvsnS|h2_j5r*3;x63 z|J3z50%3pvB8=F9V*3BU{`d*$z+IOeo+tG<3Q$j+sRTY(0h4;b?V%djQn-Ecc0 zP*XF3uk2fJ`LC*t;l5^R1V))CuK-EhuD~Nz5K^mjVPu%evgojpIhxIV?y-gnMT~)W zO8LB&JL|pboEo7>BOtsMiKFx5h5GW^zYU{%T2Yz0@_L$L-##VkORO7$S75Wi64x#J z_^}2rN)|L&R=i)#reZWo);b$M5c#KiYddI(`gm6gr?qNfn z3VFVs(7r0w+?$p0{2d#wz|G7olT_L^Wl$MoF;(NuCns=$6K`Kw;?eJ&CQHDyuRZd2#FSTjI%A%V#i=sK5 zc-=Hwsv%lQ6R?$CN7^dieI!%zv|bsVNUu2WrSv_VBz z^yf%N_@nBEZ_(wZxrTLJa1A(nAuwS7n^7!(~c{RX<- zp=VvVrp@3uQ0SZb%KA%Z2uB-^M*X8WwomZ1qsbkb6rAm7iFVdEbhv9gCqNn!u?fA5 z$H|UZh9E7C`GN|o(B^ms_=)$aKaiv<4xcu`0YG`emfRlDTt zKBR@4I+FUE8aw?P2NFZ#HKE&~AsYk1L?kNHB5_`|?*I>0yTB0+wQ+Up&=G%$``QSO z{=$Z%eSfA+fk54>4UGl|YOwumb2eqNgjcB9}k0idIhsc${jOpMUMW zFo3W^K!mVtMZ50A@bJSH2jI}@^DtPmdL%O+Ad;1%CmXW`gZow23XF4a)|_D(L*92X zwOMk8nH%v~lQZ+kG)Kz^gkRa)vmg#Jia;&h+dDPuw5Qay%?jf8R@W52CwqH0^0qoJ zqiuU@>m3g84lSORI#J+-A>Z9C&o zu6bv!^Dx&;I<@G`pAa8zuMAsTA+_f)x%yrMH$mF3t`NROMI-$0gV)T^)1H*eSJkG_ zrc0f)Wx60bcrZx117NQtjXj6%eUHmSkIFVn8}wXDwfSAQSRPI_%|lxZS!I2nu2XYu zSX*oL_h`A5kL=bu$A#RTnv9Y)H*~HnyEVKq;0854B8Tnkke{DPF8^ovR4t31ubexLA;o%J4h}oWY z8x~OL@H{+#y7Qq;daNbG_Gryys)yl{yakT^;|8zy;E_$pA|!M*c!v*a}{W> zgx0r6J7Zg^dne!0pF@^fqUTk!yIjeIE#DVa?9cXFO^MQ^HyQ`!x{zlEoE$Vni2bnm zxooznpH|2TdevZ*=>$h8>1o}j`I$!W!&2Oc8($(L+Uc+V5wMdQu=qlm)Axwv#qy)Oei{^eNFK0i$Y{Dp>!+m!)WZ$CsmS;ohPoGWkG^hqGa)X1h7U- z-2JKH`Lv?{?Rec$AuwuL`;$>Wrs|)Q{+K7#TZD2~YR!8g?V}jE4%GT{8sq)BWauU+#zswhbsP zOojznYt2LrXuQ}_Bl5H>kJZ(dy^D=nDodjZs%mOoD!(qCfMT95SND%#+ocv}s|Ahn za-G7kBk~htiOZR`CsRo;k?D-m{^lVkMpwV%y)-=rw+zX>0J;d4f4!rm7ZnRp97st5 ziJkI_b>-?Eis%>C#(bD$8M-5RSMPAM=#X(|crqHAbU$w4(l5@Dgzx5SE~!i{z5Nv* zGSI5O#GIX}yGtafuHlED)lf&@cbC+q^i$zAEpnW5!A0fQ(IOY5Vdy~hS>sAdflk7? zAlzgr&m5P`wSkfyjvFB{x$K2WHgJa89o3z1`G2{4(&%f2?grn7r#XV(4*mFB3m0{A;biE9!{eJZ96kEQCm(6fU@9Te0aWH9 zLHs|+L{7BDG=gZaGD=AK2+up|2*M&DQ&UTRucKJo3_(Qb^lcq#+dXG`nJJxU`u zW3S90emP`w{Lr-*@jY-Ec?p`16<(=H;!r%g3x@$us1J?zFU91{-~05E$=_i?>0bf$ z#AG@L&qDg84u)1z@p_tu;tx6^d>I*4vGgs?^l{7Rf3jwD0YYMrW|P|MZW)yN>uOme z>|cbMu`#i?p5D^4$dldX4Q0>q=sVu(Fp~}$clnv*86?hAQq~&<21fIDs4ipCzujA^ z^v8&x2AvzC3P5^tOvTdysnKyX136i5{?x+-e05%{>T&3|61Hv5HsPM4<8AgB?(s4Kb?@M@bs)uXutD`Q%+rQG6O6AiBYH zzIJqykmNb7Xg&Cbo`uBl&19rdBlA_jUZ4r|0;5s8cvx~5AClf@H0AN}z}oY8@z=)P z_RAl|V-)ffUclCV08g91#w)Mc#UG!?{DO`WjZOUh+w$eQ_+#_Ey4VCo3Hg;j9q9N< z9XE-Uc4CiznHT9YlG^Xk%}Fyxe2$&BfRtCB97NOUck;IGDAr#jaG_X>&TW6J`e9*- zi$*@i8j0KdL#>>kEjMQB=5G~1YU}!OL}>iF4U@)UvF6&w{5e`S%JA*RBg)`n?)1M! zPGILa!4v0ibvCs87g6xTzX4rPsQyPLS>$Q6i_B?H6-{unHP8ZAXYr8d4WCKK>y2-S zVrI<;DpNw8Q6|LqSf^{-VWw%T4tq@-whT9I)osCP+ip`1Z8Mt=-?=vJl@5sW`!)4| zIR3TVK*|Nv*5MCORcuRD6;THZQ?*}z(PoiO-_G4)Ibt2AE1USEN#bnVYK+6MaZY8K zy?ykEE|y^5E0-pIK`pdU;Fs*vdZ2XMe8x|`Kasw+qVkQd=kwXs0*{O2f%6_8ae@wn z)SEw}U2^aKz;3+{>WU)G5O3*wc2j66v^bh8@4d zyv6A6LeMe5PQ0ur0`2gLi&4w&Hd~Wsm_xzbBGo~LH6(X zz_U$iasAJufScjTDG}o+*}8E!qn=pHp@SOSA&+WdD9vF7#+O!>L*fR*Y(CJ`B_*?v z9Pn0YJwe52;tmmj%BW1^CO-a7va_@)*&CrYld%9q z0FdlPxyqqO{563^gAsr7=a1F0lJFtyl`xP+UL4RBzoLI(CSY*Ogy z+%FF-@YJ?j7)?o$6+8j$TD#Hfh3X75PImL*0JE;84YPdnVTeLcesRE#*La?oWlpC9 zypx0ECKmynE%qE?r54`-vnD5@52=0>Z5&Qr8`Aa6@oBSiohF&pYDytQRSc;DsE~C< z-ymwle{=>nGi5q)CH^5KOnH|z`^Nc+>|5!KRT+f%pwmM~-8xisSs)UvIzlnVtq26n zQZPK)<1yYQFi?e)yIOrYRiLU)emFs?Hyx}sLS|sw zqX^5C)rm2gCy0k&*r3bWo75tt(mYC{03eHii%|)>48*~dTPDh}gFE@&NqT#>7ci#{ zg7k^9CDfsUyd-Kl6p?oIxU(vtJ~9W&*~@XjisA_Zp03r*^ja1o&xom~oAveLMsrH| zTRLMF!?sYk>zGFA(xeiNcy_a8i}cC0oivWAke?C!>yvU8^jjpCHj;%w;dTe`Maf76 zia%U`HNJm}yPP4DQ6=|gb9k1;Tsg%XJg*Y+Laee`i~Rl?nay&nJ9HKH%qU-!Q5TLd z%6cLTuAFdo^Sob14z^1zY7-ZaZ;g*2z z+s*V%+;GWEOQnlvUnonQ#sFQQ$+8exq#edMSiD082@*zqwDDwwtw-vFVB^H4Dj5g_ zoC&KCjP^QvxVOjU@@RS*r`^mbu0BMo7s@)T^->KA;;8Yb+`zK+oXvU z&o_9Qo!(z+cHQGXc<{4flC)$}goIPVJ4pzs&LaDfL?4MT1nRSmC2#`Z5{yyU0Ss@; z~U7Y|F8k32X{ux6X}I@VSbd`QQ3=)*ol2MX~Cq{utcS8}u`vAQ}<==6+J1vX(+ z%rC-!v5sZi`Kx;AChQ-Mhf{ixvX{OhTlPA{N*Q%KbG}dr2&SLv;@QGSOLd3=lIm6L zFaJCj^UFWmxf_TA*1gtPB`$1e__@znT zPqy0DK{6RJ+d=yQc-Wen2~T<0FIj<8C1}vIU*Z%5mjBu~hep1nYUf964)2!t6i0#O zTDR$epT^;zuJ%i;a}GEULjdW*O_-4J_b{Ka-!H$0hAp<(Lwm8lwnurp)xq`oKHj$* z+~>b=ZYS=m59o$RNe`Q8nD+a6yqd4)SmZ279^zQi}SJZ1Sd0<(C zfTnC(22Gm+`f3LB4mTzgGbvUhmvIPox z+bOwD7NICVaO9c+6X)o<0$}ZG0NYbw4bVhf-{Wb>oWC`H%N6IF!(n@}*1(T&_?&zB zFfsylJe}eURmNHFmhwKNE~ICVmy2=E0xmD%TSa9A-vm|EG8>~{8}|)d9|+P1#2I>d zq2_D~FaVEH-uZ5>ZpRofr5C>wtU5!E-WEz_Y?OEGWCuo76+E@#B#{gt>s#*)1Sf-o zdwa5(-Ct3J>ErN3sqt=OKhM4MR??N*=y9)!sv0jo-k<@l`Apv-vm7h-5}g8I7j3 z0<-?Q8~!{>`HS3-QYVj!)SVX6EtRw_IUuF^uyKN}DIb7G&TqVYtS%tc(o#shfL@kG z7YB(HgtV=NW_wGp4G>tT^_&Rn)f{VG92iIiv(vA&i6R@lx;g5~h;*g!0ID-x)<{E5 zp%3*RI_v=~Mpc|krn~yYSag^9T$(9yq6-0fS&gyLj>-$Glk?JTwI&+~o~pkCy`PeB zX|`W*X?9sttiV+>MdFN{PoBHwrV=S$DrQpRepcT1sUE;~x>lD4++ZP#;BwqA&E76$ z*2y*yaZV;#g*b-Vyl}U4c(YS-IroywIUSSqOHuJ)H@Qc2y2X7D=o2b@im=;82od}U zS1rvtg(YFp11jAfd32wyFcs$0CFVL{l*qf_`Y8vSodgoRSGbLs9MwjDdeXcAM;{a# znoN$@F__gcs>?SZd3t*cHP(!BfFZd38Wf;BOQY2uoL96H;hn<(?gGefar+xdht4{KDEk{YhGD$~G~MnL5PsnlGe9MDSA zDlS1}kxowx#o8k5SI|>bV^f&(b~IW;&n8DI0gSDr6Jl-{G40kh&lV{VP^c+68mS!U zkB7yw2`-31T0yqoqK>1;7xb?!Yp41kOTd~K>;1Dj37kyKw}46#1pRYc5hl1Rx)@M5 z)k4UQT_LbDG)3@WUlW&B^DidIug$ppXS0^Xx%51o|3(&)&Y+kmda@1i(D9sjd^PjLo;GS=}kR{LJd zLBEFc3@FLb<%4>br;#CbWdUJ;R3i{H`oX#c_WCXAJ-vj!R?kH#0XBF4ZuT#Dmrx*< zrHi4w(Car`rEkYAS80HvHj54Fh=fslX&*>euCK}cV1@|RZ&sgte4tUFLtEpWE!LjB z#T{|}`{BkJ3GnKTU6IAGTf5RWyU(PT(LiZ=d+E}NRuRThkk8&?1;opVG8z6M$HyJr zw548o0a>YST`-oPDKQpz+$njsBWoUC(?+~kH#+<$w;F>6K9I7tt}~ndcTJx?b`kw0 z^o@@A9+&e`x#YQ+kx1(JCY}Rzv8-!gL4=4=+(-Pm9_85YJZ%hg1-}=^WmwcRC<)`@ zSh|MT4^AA$ zs{UFVsb_D0=ZQ>dDaWHsW@JL6 z)0A}adsqZUdwNG_LTpFAS_dv^aZ&LqGU&zTC`Gvb$6rF}wEyk>|M*L&N2H~vJl2k? zQ?VHa((SUioLkbQQEe(|kz8tGb`@x`%fHi&Sf9iOr5ecY`_(OPUEaNq8Fv{;QHBdX~uMuHzBCjOBQ zd%3(N83OmDbHj4UNqREQ*ta|*7B4_j6d{LK_M&>#JFsKoX`u1<9pF>vv@{% zxIL~W>+xclnm*Hna9T_ zpka`4Xe`JrjTDwbD4#X)3npy_QK9Vg7XPtxmWoh5(%>LW-yC-+Uj#CyxH7@#u!0t> zXkKuN;o#!2Rorb8c^Qy6h^4A&*Ja#u z`b;V6kqkEe=rl7bVc^u2%~hr>IGe3M+irsDm#{#YLR&_B5#F{TN(X(YLims|`-9h7BQO0}b*4 zraso#k3BKQ@bWu65PS~C+A5q8j(9J{Br|0ojmkUY6CPX1#7ZBzt{g~Gepll?A9itq zceJCVH0rW}W82v_{TqxjXM$Z-s>=;n6{9v_RF7U>bW=%0708CddUTr5c)KM*v5IGM zNbh~C%yL;95(o#Wt}yPx-iBkO~ZLoeAO?b$^3wtTWc!ki(_lP1qzo!rDpod9)QLq!8K496gqwB zps=DVACg8oVKsszQFHW$pO{(MIkpy!q9VlKCOpyZMVw1Lw#S5epi)Mg6~A{ac!R|NOc8 z{Kr535yvegBp?7eABJ8+hYB-Q8X{3*=mk_h8=pb*Q=}cl#cMHg3&_t}ADm~VuFCNR zH1^8mfc^F{YT}p9wkqQX9%sc~<+`bBeLS(>YA|F@%Bk&wZ#|}}ED^YAY_3S+7}?mu z60|PAv(UlDj=0A%x<0P?TsV=DEN|Hb!bRfa9DBj>3TDf%03tUVz2#||0A?m)(3J6X zQp(*9z)8D)cz!H8s1u2rw1UeEf(Lnr-NwR;7NETOsD`~4)p5IAOv#(NmgVTSX~imR zgot$UmJ8p;Q4|=ecomVdTARv|pXGVeJ_Oz}@HjI!->&KUh`oN=zTw+PAGQ>_f z+=Q^n0(B*@qEliT%vQUM{5!KvE|RVqr_`iv;uuDD7a+{VM@&(jqt{1O7^HBL{cO4% zsIw`<8S&Wy3XHukys30UaRVvr#+Hw#Nk2k6e*_~8?r7(dld*Hiz*Nk&ZdcQ|2G( zYx$?)h9`kP+#_D#35&2(yVIGhvwM^G94~L^&4pWYpM8FY$|Q_L+9ssdLJ7{_EpDpw z1}e&-WLLQcQYzZZADkFNMCrhb;KIxV+|-$~MEOU~5rvOo+6x}H1lvnabfRZ;#;IC7 zIm(Kl9?1@U#JMxipy8!ql#RfZ^WkGbRWoGZXbunNMImVZImiUg24!_QL)(@0tE4;~ z2yCqrcOjlAxhn?)U-FP*c(*u3XR299F}%~#Tq!}3Lh42u1vT9>FBf5X%pR4|H@6HQ4d zVkjzN)eyazY7)}5l_OF7gaLLxJOJ$sEgQcI=?$crAY7{tL~~~b$s|;vzm|4_^wdcX zOfZpoR{)J}7qeN|VLp$DD98p5Au*NeWqkIc9IDn8k&vm7Y+E=&uBKn}9Q4>LSRyR; zyuk~w&KbSXx#kkm0SrxLmGjX2_6j&%Ck<21Ky!mV%Vj2s$qvw2`!IM3@!5Vs2e{A@ zfau@ha2sd;$w)0#<#flQ)d2xuXK&!lr_?&aAjFW_>|_bPe>V5t#r4;8W;g1X&Z=jV z24HW4XbqWA9sBt_=Sc{q<4`oMB-cqOOCUgBI4x6#dfs#Z!n|W25_sJ-wK@=o>(_~* zntUCCBkS0Q#L?3`YXu>vdEG7)w0enpmt=4UFjMW_g-+(e#;(8sgpK|{DT|uS6^dPH zr&3V|3$zKLi&xD{6zSgqY?fW?97+ZuzTw-kPNErpbJIMQLGE65a4C8oe4YeQU9buw z!*Wj700OhN63}1j>j6*`(zIEUw?lkom%7+OJC^|-0yaIhk?5Lf$b$+`f!3sFKQ+Y{ zQ>{Kt+reetp)R`EDr9g6!9?piK+DV4lA9fn>)pChq^aKlz^%goupuiv6s%txCz@oO z5ptI>9tf9vbkSQ+BlkkjyVX%xN*6&_EzjJ6rP*^ZqDC(IG@J#HZuDj9dH_1#sT;gb z17&7=0G3MM2C@frStt2>og>Vbd6UR~YPva@ePkZAwMqZtFl!IN6alLMuI1RfgrB73 zn_z3n_YSB`O4_FeT1LE|dCumhXMboK-{|p5%Q@hiLaghJDwwR|`Xec~zXEvq+V2+S z^N`qdu|x{d{ea#f$cT;;&x9amaLuHDXbEm==~Nu%cl^qhgnbCW4>%jvFILuk>MOhv zLOo+F`W=5t0Qsst(rkvx!Nsi|@-~GKD3lsw~zgTJedNZ`;PkazY zRfyLpq`Wyu7;w_iJYwAo?GMwN1;%Z?*x%xOe^INK&116vbvYX2!PV&jXZ?4ZJ4;)s z0%4)^X0$-k`LMXg`5eA^@t5E;9Ec;mY_P)pqs$Lv0LaEecX)u!8l?#sDl-!SPL`XA zRJ@I1MtlB@6LVDJ2B6|enhZ~qP|aD<>E4V|{*=Jnj`w>UPvI9mA|~=PR0PrALIGui z38*uMw}K|P<#YjK?xK<@#$cKTj9goyVu&hDKe+bJP$nr7bbgHo0yJs+)=?kyRs@Z| zVu~ZeN@4Clejd!dT)3bSC_wYDTnu_`Q|XKUzUxfAwDpsX4Had@<&%O8G*wasw?|1#B`E}%6>yP%>4&K;RK$ygCMz9be%y8>1$CN) zNSthXa0)4kUW}oWmYfOL@M)|Q(<3R%o7>)btTRA*2Q!(nFM!3jVo#xsZ>85pg-ILi z4*SNKp&<%D5ONB2ZKV-_v2sB4g6ByO?~NklV^1#xcDVnjM|`gZfgGIJj*{Ks8Lgne zLp`C*{DpWj0J&4Ae(WZB3{?t|zy(T{6J>T+?nIA8x9dl_GNZH0xemdO@mZ5w6am399gmCIBHMN|GcdVV#hN$vL}aVn=pOh4Rd0h_qoEQ?T9d9~brR#K zK0KkZVn{)mF=oQ)p?v6?oDSFr3^8_3NkA@Zy{D5p;g;P%`OyQ%$S#vuO>}tNjc>@= zH;0KQ&u%R^#Z5!gg9df3_&5{)aCjp}Zt5Bq?G&|v#4OE!o*EQbKW{scx;we)WV52_ zXf3e>7Z%=QwszP2EMf5e40m=-k7JEyo9XD6@mo~l*e#0p>8{ZT4Nyh|rw^eR0RqNL zI#ecm{lQ)v@$rq~q^&P#mc^BU$_{KeG`vOKDbqyuj0nQD>VJ$R1L$ZUXp5Q>?tK7b z-%HAjq{(sU#Ceo_KDA%xH1l)etbC}NfQgmb1$=xboglNw{XgWCFKGh-beW{kJ=y4@ z5lMX@0C6~Mb)|-k1P4Q@ZQ~wR&&U{gjO}n3Pj6YJ#L`0G-6LrMQWck>?5z0Ix;z7ds2}oexF2LX9Jn!7;UJtj8bW!cYP5huR7M9IcWGq| zMFRsvP`UfkEgf;!HR15pmxRd^l#N2T@yQOXGH>;JF-V*yp;{6dLq&vS{$_~CLzg&X z1rYWWEJ`}EilBtg@i-a$5{yTV6I+*J=ocw^kbN3}!5 zdI1fvl$#r=h^T&71Dm>ZvFE#3QBg2Q%L(REzy`yUIo`mS^M1aNR1EKn;PMM`Ps{0@VW9M&G<(H@+Eq6N7FyXpF z8CE>c$rGwFaIHuBdxUdO_>E9qOFu>>1K>V%@pdzlx~&8xOwv4p34kefxg2`>6WCd@ z$`F4-!s4)51&*NQ{CPRQjrW)V2_1H_r6?A7gA4bRlbsz_DH;^%UV3#r$$)c~y z)l<~JWa}Bw_A9MvsZE<=eGcbVE*`4ry)R1q4pf63Q02HnKH?1HX;wR|jjhWOMAcxR z-^*Evs@Y~uhm11A?C=B;_sd1qtpq+0yecoBQ@XKTOvvAZ%+LD{nJMuQ621m2$c6+6Pxru4L0xvW`$BA?C;b1 z+o8{F&NmBOZ2nN%HW}=qO4N#AJp?dd!sXn} z9qq@DP`gfw+Ilsks{3NAiIA_yOXP#my^>|1ulYNK*fBi7u2@p(bVorOistWwa6(*Y z9xsbDsRQ_@sye8w9=a7WExUs-BtNk`KV2Sik(XvrCde>)BI6D=dS#~%@C7$Up*R(- zk?|oKQP?!6F;lQah!mAX9ijv+eF-sqr$i&MtZBfGU@OF~yaSfo|LmE+~2KAHxIZn<4Fydj4-2xBts0<=PYzAjZts&4hcP+uV zSiZ}UDq2Uu)BYY8$5t<}2~5vHbS=5cC1h%RG*C5&)8h_XLN@=aKf2m3sqG6o5!C7k zZ}vP(?YEk~nOjjjm2;~h<(zdyLN2;S^lpBKJ;xy}kz4arhP|!C)e||_;J47gAsz^0 zL$6g}tIN#RJTrrXEm3$3B|?J*Pg#|*26lqu4>~2d@nc6XSB^Tk-hs$jxd}JV3QDQp zcILq3J^i3kVmb+9d6-j34k1WJ0-gY-dTCfs8?N_ZyNkA8u@ic@k5ijNN0Yb?_Ik7a zgd2XsGdulB-uwO&(X1~$m2pIZRBQ~=S&D^kMA1-r0Z3m*4Pf-LZZlzEFk?Ot)L=F9d+bNBZy=7Wz1eI6Vmzf6wp5HE&dm{}?jZ7>w}bV+z+yR&sBk+eh;E<_x8VU2 zPMX%Av_eKPm{VXE8hG9Lj=CRtwFcxo7E|7QU=?vLOri0Ayfex)XegWsuKb0$Up;XM zO%!dMn(Ih>G?;~~%sCuQI_D*BrYNL#9+K8ZiVBxhH98cKHR|MC#EU+GA5irm;u!g3 z59YN?bYlBNXQ%YgfH?D1Qu{o4evU|a?^89*;KzZh=q#T4s46S(%yD4g9RWxxxsG%u zq0{Caq@OeO@DBAu+tF&B$lZ1lpV(Wxy}6p%tshHZ|^ z84f&7-vn2!Fhjy@gqx4+`P&UvIfp+pZ6c*F$*IQ#l29$3V`@J{9M?Dkm-FXp^a0d8 zQRbkm`H`@UF+^l=NX&$4D|(VfWHUK^EyIyhcgX>TPwvqm$R0Vq3|=?}r3%k*Vebkj zt!8||1?~^yYGWSeuGU!{JT*h_m#yYtU)JW)-&epUlW8yT2${x!=hr{OnS9J0b^521 zfv8(x1(lm|cdB`;58D+l)06E$M)LRVX0v?sk;wMrkFaW);suCLR^v5N;=4y5{rvB< zdkpMi`t!fP{~6aDXLI~C<39)(eg7D}anSw~S`|L}2t@z+(~m#Gn*2-qVUI9yd+m*UoaC7k{{&CL8^7WuMtZvE@p^W}E{s-7wDfo{uAF?+`xwe$ z2@;d318tn>pwn|);~=PtriVZNXfOplp`4durBYwA+L94hIUYk!a5yUfz>{w9_o4_q zJ*H3u37zZLNlI~(JW?-+F9L-iCoem)f21eLZV#JZ42}*tUP4T^t7j;KkN*1WJtgDy zPl2+SEM^NFH^2G(?IKMHs{*BbNoq zs)MqSQU|FLy$13sXYDI6L-T48fv8`k;;CqJ_4X=Dt3w;?~BR?{XgyFiC=n$|&k#QRVF1k>x>+*TJ%1|(fh8|}oi>5ht4rOb|hjQLB zm8Naw6bS#L1`Sv;yNf?zSy7jRw)ImK1`*R!QN*s^pJJ_w^Rh|@(M6bwt!4*1i>#(q z2i#$Bt2fafpfkePXgzgcU4CJ;+?(IaJv}6GI=uCSw-FcXqnToxPZJ9IIJ;@Lhc=e_ zd7|3Xw1)6U%jv}5#8wiPt8LS8fIiv|u=fq;hcqD2l1QSDmZm&fL=Kk<1##+1GtE3* zE0Gwm(-+;Iog2bz<7xv|5GB&x`NIigduK*Ez~arUcH^Q>L|t<2=?owqVi^ zYLR_yp$ialn{Q`Vg+c&;%sB1uld|;mv~{UlMM{uK&;bH@%W$!+0g57!#yKIq=a}yf zung|-29=F%3OUNJB9POv0XInM;@&)6VV~YlanwLnfRu@-!0)rg-qkz_`EmS$9Cj>* zQvP6Gibqd@A(wd%ztG zGM{drF~b3YhxHb{_#VtL48rugv*$GUL^Z)!Je05K70m~53%xkkv`b|>-NThymSfc3 z&yMkH#H-&b)(+7Q@IRG~^XYA`8G5p65rHqFQD?h`*j3mV+=+B=0G|-0)6zynG$c@~ z&`k?;yf8VWH^}G?^Kg*(xWlva@pSlLNg%|<^@aT#AI;gp!P*$nIuvVk+$5vDhwj+~ zbkmUyu8P$Vo`B;U4t;aKo+@hvbqtB;57d`@5V}YV4+Ludj?O*OLhNBkyB;sF!}B0q zK8OO6@Wq}Uh$`J!>C*{o)}dWms_B8~G8gs$;EeVYC%?OKD0kj(BZzza*ymzJXK9Yje_`iV0ulLFbXFaXi;@G9$X3!)8{@Ekk_{c9JD~x23 zXw8Ggul}-F*dUczbQm2^^0e$fouY5zj?TXXE&qBF`ZjF!{L=*lQvUVibLCfInTT98 z4sTI6B>h@3Ufu?Js#&?j{;Q2+w4+pr&*SxY^5xMZ%g@P-(WbyH#yT2VC=>ZB=J)th z-LnjGBC|~~`VsDjLg^gD?}O~0z~f&xlW*i@xn70XM0fDv#Zj~O50CYGzoqlx(Ix&P zoIEa*dLdnMx}hBz@)tDv#aNh8%ti*3wz zoW`dt56+F)WI;g1!c`dz9_wPDegklmI68#+%=UIJ2lX6@ zR{c4!7UuimB!yGtd zb;!+ZQ#F%W+yg01fcv>{s$coJN8Hg!Z6h$TOEuoXVxO7?_*Kl2Hm=yAS5)} z^m$MwiPE;_&`uQ|^*zaZ1dPGzGn7MwNLb0#eb-!&)Fzo1ZE#~+UCjtnWwtYvDQTct zP0OQ2XSW;F7zSA7D?VY6^}Nv&W}5lR55H@)A?W>r=0aAI6nleYV=C2f``Xs;5dU=Q zrM0?>HIg%#(}X_6^rc;rAXc$)Ld9u?v~<>9avq!X5oTtp1KI**%{r}FurBt0bDL4Q zZ?HD6lFg@jt6zE-4g!s~ik$6AluO3o_J*pX(&tqKeC8Smk^-l_k(R`$mrXn>+<`q0 z(3r1^EyOAV)b#tXJ1m-7ZP;Te!sziBN>r6x5icm=@Mwe``!#+(PVF94IB>7}YAuoC ze6IHjGIwFx6cY4`4q~;RNVHQ6xA4819Ml<^vx6Dij)<-(h|siqUYcfgM0BQE>w09p z{Z3O$)+aCE40!hf&RTUZ;6f{G2f@edVEfFFwMbWJ4Z&yo1~x~SW>l1BfFATO;5t;H z&rcY8m>ypwmrbC!FsZ7SaDC2HP+)s~VsvdtJ40D(RP5mNjf9({N*IsBu1)Ujt*r~4 zn@!@LjBA4GM!TO;njHUW`X}<(dnxsp__m}koXi?GkTP$De#H=G-Hz)+c;h`xKU{+q zpA#38bWAST(xg(}+EyT$i%Xy^_TMi;9kYO)Kz-`yR_NIqGy}lz7pn!TsL{-CiHQVB zilYHAR*bzHznOrYy}MAi_1Y=27x#|4*~^^lQEY#4|n%scw)aM z_9!x(O-6XFGhNG(*HL)h4TKKiHf%mxoxPy`vIL{=Rw%u4((ZtV%@MoO~JHp@NJz`Q;dQ$+!u5;4RuHL zqr}vUvMr_lRS|QqG_DY(LQrr-U7aJI<6Ys#ELg-LQLA@t3F53eck}}k7mR+xRv&R@ zL}2d*=X;4?^>;#Ny!>koGoqj}j@o<+pOkn)Z(WD;Ji#aGXZB;h8w2F~4LnHvlkhV*GC{VyCBy(eC=jmCgM;G{SHanzfN|oVC*nnlL3!|A~{hf(kkC%_KLf^JBHPSxj@`fTD zU9{Ry{~*_iS)QNE&@1e-HXZp;=Iq$Oqcr_|O|Psn6g0g(6Bek`Tbzfnz5Okx8@#?)<8RQVtS#IHo3H3~Xu9}>ZF1>cYC zCw3tOw4!gY^@_C!&xTdp&K`ludKOE{{^|cjQC?j5I6_%M`BVOQ zyFvY$@agj}s2!?Z$`_QV{o*rxxeH%V;rBnN$wo`;qQz&Q;{%n%*$nm<0?Ai}{vu5g)d zzM9N;`1cP8b>v^)<36Q+{Axaxe}4QCp0k3RVt-7AgsEe-ZSueAfA~3B1($D|?S=DSZr$T||bj(&>eh{<(Qt$Ti>v=rFt{w5?NO1$^= zN2*lVt9z8fZqj@ow;~F_2*$NvGPUzi+SH^bCZ+%FBhQ&%rr%icB~<)UOO(r}>91scH=Zp}TMQior2PVPC0}%Q zW62ggPLQ*jx4^>;FBb9VktZp{&)_4QQ zLkJ1b54V_6)<{pEg(ekg@?@){d$C%|JL8|dby|$V*(8hZ9pS>iKoHkna&H6UC`ricx~w|oE>ag zZ4FNdS%X(-~-16Tn@M4<@ZQ8E-`f28N-&WscIc4SCj5yHZ1^B z0fIMx>4XcLlZvejchG3No4;Lbj!EEAHe7&o91QW$WHsCu)!@3!JPA2NH~xht*qXSO zG?Q1cP2d*Zh%%sWSVLvgHOO*W;~RD^tq=;V7uWYC;zW(wA?=OE!a!*M1SPY@;TGGh z_*e>dHJ>f;LKMHR>(SayeP_ss9f6EmbuOtkBR6=&j$1N%))3@PcDST|Kn_1!m6Dx@ zcQ1pWZ>5-WWrD%mE!d8{bm^Ndv=hOv@y>QVTI*dT#pueZ9GG`om^D4@HzBFe*@&Tm zpi|#Ai{%!_bP_9dBhxwf!wgp^riR$E=?Uc8LUcB^GWD2m+B<=PatT%yT3;A4d*&`i>Z+$4jL@g zmXG+{l}zHt771hlOtXy51f2Fn3E9*8lJ1R{9oC!~Dvh-4$<(t}INH(7=k;1|HGu+* z47Bc8ai7$77o0wXxEtD3({Jk4u$94G@g}exfp?f0Dj$!afsE+Eg+XqPW1xy!>SXRf zmv1i&fH*rM-s{M*cKRMUOkWdJ;;&sZ^DCzW$cSDkWNOV@?_6{Xd4?J4zVRJG!8(CN zubzpNoBpiKWdPCka=q%>gNcV+D)p2eZHGrNYJx?lsuiRH?@E5liU$0K5NtN5#h{z^ z6JYdsc1!jHM9^YzKc_d7H5yTuQR=k)pre%%CfC+6Ms)t^KPiQEu#}!N3(O7tLj#1_ zNQpcAf}S-efg_eYLNTVOEEdDmM;dk`aiJvRb6x~ik;QSGG&d&dpjtVe6G_q`@GBrk zQ#L?Q&tyKYQszPd@dF-S5hgT1_{>kzUsLsF;MMLvBjh^E=Z2#2_%x)@&vTkN@;D`> z#H-{k%t0Fqk%eD+^fbvJISQCD{jmpx&n-C!*{Z85@=CtRK{!pdee%cwkc;6ei&pyB*e7pHC-E>!oV zxx1=XK3(M~l+RscxwMq)w^-fuTB1)@xvq}SF1#)uQHmpmA#kL;(^&~hFyQqZk|V~F zOQ58Z6e0+SYsx7Pp82?1b0na_5uMDh+X4i)?(XuVyO(elUB}!b%Vo$k72z`Zmr4_(8}>fRhL#n5Vd(DXBtw)YO^n0 zh6+Gh%gRbLx6K`CKOK?K1g$i0QBIBR&V-WQk}&osve|(oPquir*%U(eJ2{y?rwZ$| zxdLQ)e-kdGWniLt@f6mutnFrb-{v>M=rvKgV<*|Ls>6B5SFVGV-KT%P`#jnl#C-4m zESSc5Qn-v%`)qu=<{z;he%7fHnoM+1bu+i|(y%cz_mqC%A0HNwCl!L?@W&rfJ z4hZ7KDzii}CO3_wh-fQ_5l|-is%=S=VWT5$y?@P_Tg-66rBl9Dzng(^ez`+V6{noR z2`(E@Ks$Dh{RGCdPS=@X9)dfHdFusTfY8JTom(v;$D~k6G!0vpLEG9{LQ2G-OHv1 zx!(_)D^WigA1_Y=fJ6S+DT>R={CB*ZoVBpc?eM)g#J|Fgr-|)%ef`}_5BsH`I6*HhbEQ0b@eu-GUM7d2}G`fic0AmldR8QyZuaPnUBMnG83;y&;l3FVp1? zx0w`ziK@mtIv1HQ62^43jjGg=Tn{5S#2k5O!5|$WgtLWRnmb)`po0UGL@^cU=+}N4 z8hmtvwfj&K8KP}Nyft;{glvExRu1!bI5Kp$C~TDG?~02!G_a60cFA#XvSJ$e`3@^p zegG>B5I*YdsPM^9Q1+=pr`PVA>E)IR7+BIMqI1U3=)E1Uke@e5>f%q(1%rd*QS?x{ zhA85J$_soai4sS9GJtWEK&U!F8bB&mQ;YS$wpK8*F; zo`CCsVF>9!6rENz_6Kwc&q{T)?UDHw^+d499&I;wK?^J{ttpgIYyI}v3l1YTsN-gv z2d^Np6ICefrEHQ}R@4Y!;E3}%AB<(1+1njxd?W<8q)_ef1{+V4ksrElcek5wC2>p5 zOrCVfG!G1r5T|Xi!UIX$5naqyQ!&BNmn`Pd#`sUXGbe5o0dIvV;ue=(+uSO^J&u_v zc8jF=Q%A?m#<{;%DQZ=H$0x65G{r$}A2 zfPt=A5RnC>R8-^scNcqFNa5P8M0KGRRxl?lY1hZ?4Yqe? zGh{<{_uE4(#%P?OgwxG@2Zxko#=zSaCAzk^J9VErFg(ryC{iP*08KlS8lFWCySS1b z*7nGzdAq3kLN+&xgm*Sm5?gH)nc7l5N|ae5&sb85V=kymQu0n;Vh0QX_U<-!cv%_M z$Qe}5ixPlP5$DgnyNlssMg@TW0k=Id*iGtGHVv+Zb#^W$7fT<2a&;7$sq3m!D`e8< zbSY;}g+;tTWa<n&aU{9L2%UD|OV2>2%Rthdzc9GJ(>5~KocqfoVejMH4Jrzv4xxSc zhnEPD<^qcpl{FL`MZ`M|HeW_EI}swt?-Sr6sU$+c1U25R!YG(Kl5gN76E>Rjpdq-j znAakS_`TYV$aB36QTSZx6eq|;IcQwFZKul;2_Xt-WrhcsL4MKrqx7S-R^1+D+@jA@ zEi@Jvc!lDyxTfuIFzGd>Zb-ymr_(2F(RE&kEoc!zB^i+WlcoEEFi@9Q*DL}48zPIe zc1<6H`zyC*FFou=0AM@R9iCM!SK+w(=JewvOeLpF_11mXT|(Dg6y0M zN8OWF8&5ag3YCUSH8b}IXG89q=Gs8(b{ogDJ^!`GGwt1)7zg&R%$NgvHmB0IG&*Lc zQP&*Xh6uH5&AvEl88U(1mHHg)IkWGG=Ey8siSEBmY8Uf8vvM0K(NdkS5rkH!>o%zR zL{4zxd@bJI=J7VH*dw2;2_BheWrA;m3mr;m4{zzEZyhqaMB;-63!5$OzK(F^16QOM zmcb14euf4fCMaWL!JEuJS2NbxY zv}X8}&_GyG`a#_=Ku0Owj_&~rwWgB^V~vzkUU6`9eGPqSBOq4%=IS{(AmZ%G4GJ=d z907hgx0xg@_7yRu;>>06p+)fFg}nRFEPUueJWkpe(!nz&C&g4_!1&)BZZi$!qSz>N zu=&N3q}m$i2x4{<(5RMPghl5F>`&2?#q5X4FLV;X)}smsvoccf2YrzuGm|^i6~?V6 zf+Po9cH8OCPmy|Po=E^D?%L7U++OaSlD$hMbpi)z&}kWb!yy7HfPob#4ugHlQ6`aAYr1AQ^gwvYNt8H2!LMVqHmVD~Wt|v8%!7B>!rIJ~E!8=IYDk5lNIjIxre^^^Pz-U2f=xxRbQ#LzfC6p1^2j zda}FmRXroE1`cm5pYfkQd5%5CK9zXyT~aTtT-Yu*WA?G=}xoF5cMfK zn<9TTzaAf#=7K~Ci^hcn9i;~71x_sC6(Y;`tdDrQYJfbh_U0X0xM4-x`D(PoKGA3j z$0#}{?&>|G(H2OHzr|otjLxc3X+r%+aEE#z%(v*I6<$aM^$KL{UxxiE8YiQUH|W%j z2546({@VS*78Eu=aZOIzIwIfl&Ec^9{AD~WVG4?$d^A_!#P3%;CIbPeze-)I(BTF= zj;fJJ_2#h=L(`CXdVoS@eT0ZyGt|r(UvxrHgDOa74{boQUmXpmbWwYvC%54cWl3EY z{pQr9{4pws`z_F+cHZSE@jk%R+(p?BBjO#k`3*>GW94qx4D5#z0u{=P+wv+{*&`*b zv5tT!=P~@p5*pUB&yTJ&RS$ABe+j2pW1)nN_e_U1)VI>KaZqlOVnR=qCsMRqEb(tQ zOWDZpW_Z7x&$mA!(HbHEu~Z&xHGpsqRAkVCb$qTo;u&%FjF!3PVpYsCl1LF(WBf3P8C5h^erk1lES%z zz*nd@7RDyk+X|G8>Hir(Ogxli%3R5`Bn9%MtPR#OI%MYvIC4-|#Fnz;v2>Kn40YwE zxZgNsL+oIQqakUXxP}^E3az{=Z}161uSO|pl>H=!r6LYVsTM&6Zw3J4BxUhS18%_r zb9Udna0#vt`%`{Z&^?u88s*w0f{S#z77Pis3Q^JR?R-Su%9VwT?#lHT0P`eW2{;q~ zh>Fa?TT_BC{#a*&oZG1afv{s2AYcJDz*o%wG?}0hYHs@d091j@TB1@$U1mE<#sqAY zhG1Gnb6sRHgD>wHXRbwTE5XnMV8r?HelQ@ETOvxpCOQT{Ct~^NG{DbuP28nZtWe%7 z8#D;%r+mgSXyf_PbTdXyr|JuY9Ilv*28$O^ zyY-#XYD%#+rYx@xJFChwDp>TC-K3P#O%Rtld;#7}k0FI_C!mzfW_8W3QW9`P0eB?9 zX*x%W5VW&T<%AULT8Ve6#9S8cnBEC)TCixaJPBuo&B#mat#Or7cNYk>1(=?hR(0)n zA{d66s^TGFs=2muxf!&?x~TZvrs5! z{zmBqe6mElC~n;E%J$nqG8Y|Y4{7t0e`u1vv3P#NX_$BzYzWwL>jg0If=_m9^dV@& z$&u4&L!IRs%Ol#@4nGLr^UZZO*H`6EX8^Tb{c$8}P;I(f7GJ7ocY88Oj3yf z_dSxQqj|_n9d%4GBoRd>O5tpK45II9Oin^J>Jn;dJC(mtT_?rgGx}jPZ777M9ZE-s z`@NlR1NTGh^=Q&Qz{{A#7unA@4ES(&3&YFp<$&5fgN1g4;hyZTDjMMnJ3Wl_zZvh2 zkL6u0q||tq_X(GnymIArOr)VOXsCBG8}DyNsMLZ%R(Z;o>udW&BUC~14a$-)sWka_ z(W4m}Q(}VH=>7sJ3zfe0TF@t@qtWXJ7*r7kkd@&hdNL&I`V}?`sECtE<#{-#)z|Ea zC#(b9lW%-O=ozgoK}IY-Kys_l@#MdHaAX^HrOP28B4S2#!jupxAaazM%?vchh5t( z^^eArlyCuo(g=5hT^ocw*Nb=gl*6h*gim?f|A!+k5QJ(^anI?nIONBdXqN^VQUr|D zgW<;Z5^>1=zZ!#>MxV-qVb3@=u`?3gZF{5!pjBuP2-8EyKOi$V;Rf!}^*L4Jkz8Hm zgNpZ*QHeoo3KQU7AdmR?kR9QoiNmjul0io&V({DXeY!bOYvjD2_jX^=NCM6kZXAwR zSF!v?(P%;SHyB^Rv*}iCEa;{4zrK9-bIWGi5JnnkE{~_Cev>#P zV6RYttQf6o3>ju0ooV#-qG&x_FlLmzMo`fH`t?&qr|Lsi2Ib(mHYydqCb#hLH$61n z#mMW|&j&*8g@otG?Sf~da(uliiQLM^rUF9)5wIy;JJwx;jV1};vdw<{)>aezBMk;EFycTYSgHAIs#gP}Xz~QCbm)l|hnTyaffSB86$a5_&)x5Ri^LB{9m( zJf_;)Hjz|YJRNVpsl6viu~`6v)l4588-njqU06k@lb|skpwT}DG<%J+D?f4hKQYFz z$B~Ui0bix+`}T=8(DuK2grUzL5p8`65(1yF?7jx$T(^mQSNKZf9mAjSSt=9R8%^ow zJKQ4R2`I7T7gTXtbQtA4;4)}JMVX$e0>s8o>6M2oMkIpH#x1sN$|g2(L2o?iOu7`C z6{F<0iTA7m-U$r!i%&p>p~eICXsX%CvgP}(8X*EWeY3%8Q^yQm)XIutjT7L^Aj05KDih;Z{^DpS{M95g!^x}mad!L;>L>+$2J|m-=-r$-Vu7qp`waEKYwjxdR77zqj^wX$!isBkv5Zt?X&L-5S_w=( zP!Y{4_c`~;hYb80dAjtdXVIYB17ULvb)vn@GXR_C_#F#V6p{C>ASZS>2-@|2R>i$_ zgQj241dJH;DMA82BiE!)&A$8ZzYzyYdphBYMQN*qlvX=gL{liF0IQZy5MxU>-?xaA z#xKKt&2IEGqP=au!u~}!(@k2~qwxAZzqpWvwBcVldf+AHY|^wjQ^JqO;WF5DOo zaCS?FT9v|vhdST~af0fSQ*GM5w-aqWRbHR%7eU`jh!;d$|8Z1}C0M94~MD zh9>}(hkcR8paU(~`c6YGLNFo#wo??*@M%{1lM3P*)-U<|8TXoQwpK{+8$iJ(A9Dos zICo~u`Cn*+xhF22$BH1Pvu|+gc#ZprT+1Y?Ai(iXUhzYKb{!AkM&kQrMBT~*Fr9Kj zSvXuflxQ(WMP9eTH-6~^d;4Z)CyjHcU4x9>a%ZYQk{u<*7rKwbM4A!`v*h;s5zUC&JWP&$O4i9yTjMH|wKj@SdXKc%!-x3r6$`WU zIQ{K>f+1C8ah&n5RC?HJrK&i)J)fazfHA**37mJIomZNiH>1R+Mt7 z@au7dGGcsbAjl6*dCwhc!rv4E`vzcPBnzDC^?pGV@gn#@JKG!)4^Yu;yImL*l=!1N z?sz%1{S6MWj3_C7b8Hw*Iy;ZAivAw#Z|qvD|q zjc}|UK}i0Ms-g2Y61zI&I;p_^98-!ZLEM9?68e0zv(wgrg5QhG|2)p|vc2f)?}S{! zu%Y7_TQAmc%iaGhR={ZDoi3#FwIHQAJSTSpxY$1(PjBb5C-=`@k8L}a+5?70g!v$3 zgIz)*7mCe9dc48T7M}%?uC42!u!(~txEU-nSpCAvp+OHKY-a5#@+PQEq<{($5TjEP z0hb@6hA~{}fK17l_2DZdayNUNYz@~0tMDn`tIcpkBfUi5i^C48b}}I3h*Q+k%g z(MS(>=C?{YFX3* z2bqZy0)g`Jj*f1Lix1nRgxrlXaGx>f<(QseUQ|Tpwmt}+=eXBqYvB;&eh^GwFE^9% z5*2L^RKD7qjpIEUoBPNy{EM(;SN;4TM83cZZ+r-EGTEPxZ*Gv%ASr`#rMMko zI{DygAttB7Q^QjIe^^{_GOZy3KAC@9P*)d=R3~`$Zhj^v*r72WEfsLB4WXQNVHMS&P_0*$#DVRr+!TqU4ecE zZRt`;d;RJbDX|lOwfLX=y^lw5%1iv<7xlDIB#X2V-jc^4Lc^*$ed{En94!kECUga= zNyB69fWJi8O}rV7BL*r@8{nIx^nIAX!9`jCJ^T_!)g~RMUzvO*{>LLh782ULO`jaz zpkPRj(~2RD>4awMN*PVemw2*vv%@1aTbvz9-$EwqL6#Ze8{W!kWMd@B;V-rZSz*X+ zCXONwNSSD2JhrbCiz0h4)rmk-$prv0Y>Q24s4(#HgWr)0LlHJiGqD4rMed`?W@gcu zLi31|X0)9h_nL}jpcW~GRwCe*C9KV08Gib)rfC(vHSkGr7GT1HYcbPMjS6RFu-g;9YkFa^SU*6Cg+1);t1K17M7QSgx}&lIJa1i zUOUbMQ530Bk{74aVDKE+yTmicHE9TrngyVHF@Qmrq#K+Uub_p|NSl3+R-bi5cPbK? z_v6p0zN9QgF!S9WQ75u1BiSb2^IPEQHW_&?ej|+;S21;hpe>-3s;=e?yBOsTjP(2u z8+oo7g^SEw0T?;SX(Ewyz#iUwIWr+gC28UcwnJNdURh4Yj(U&351T+l#1>;v@W`#A zI-bK3Bp4@@4smKbAS3-dY1mMmhEI&B^uZdn9Bkae|_5XwY>Qx&Dv{kYBm*vQqXmK>^7w-$PVFzlpb&TAdppfHjPyjrf- zWt%f?BU34JFN<|J;gCiZ2~;NX*<$3>Eo zp5I{Pzmll_iXB*2I=7r`E8VYA#$yvU!iok&Rtg6nrjS3*VN?$I6#XAP!dcHnID4zw z0vMzZ-t&+YYrU7p^E)SJ>r&J%EHTU|ibQezxpK|AmvT)SoFUhw|H*RAd!HoNtn+Dd z)s2}hP1OjqrVp-nmio~Fwc!g5Q9JP)IXUJ`%R=HX=RgI=TNHoF>#o7T0;H)6Ak*hh z*{6`Y#b#S(v<}3USz$N8Hl|`VK(fvDY2dq zz);9x|4%2uZlg~?!-V2dq73@Qv?GJ?q?$Nzhy@gIih&vSCGb6SEv}{Qi>5WvV1AV^e54`n-}|(C_Al+pq=DL4r2_F;BPEK}-Dc zG_C&B)%1!3)KuiP_OH|0Rb>+-a;VrDtq5J)IEW~3v(O{!u;~0dk|ODZn+#h#_Dj)L zOIUP3SQ&|@)x5zY;Ysd8+mKnR;n37_iKr z{QK(Y}uGwT=6GOAk zF^KJ;+nEy$DaG+5+bY7tMu(Omx}Pc{9AlQDeL;A4a_*Ox;)NMvXH%Ahk2Z| zdzAwd1EU$JI=iL?N#k^ir@;_>G#vDoWCiT6 zIQ{aMDn!f&&K<$eF{!EyfJlQa)Z-6#>VdG~{D?o~SLY819=kIY)X&zI0)q|@8pQ&! zliDZo*u=%K{LzSufxQTc!;3*Bc5^W_QCc_3=gU9tm6Fjo)g&UF@>Nw$_T&ej7056= zdUVoJfkyAEpzgMvJ?x}F1KiMq0!89K+122aNGF6RWAN<~2Ue+7auC3W_V+;W_UH){mOGcWsQ6ufDG?LZ5kJLTC zsphp&i$Obw(ATtfn+J7AW^+uc~DW)e?!ifW_)zOB24 z_p!W;-%{@zXT#!Dw~Lc<8QIbe1Dsl(3_Q7l%Yb=J6#j$>- zt`3B9oUQg-8xh_*3~xGsLkA>TZg&hxF#)s%@nb6m7pSJ`-3jO{KPb*R3DYwlUdUOx zd>>1s#||T`rmNA7^m(P%$Q{x0L%3jEdN*nCW4>=1an=#ijO_G{nmhT-D3TyT@p<^1 zK`@g@>0zKIfz3mKbUri#X<^ujydTr|R5GAYc{(g{vPgIImP_h%EP&MW4S3;gDQOD+ zq0mN`&FnN*;Bj8lknA+ppIC6->0y}GJm+knd@xIbXnBDq!&5#0+_}0y-!yx0ZlA$yuGr$o%cH(u&rC~DK=TIi=@n>(bOKD3(lD~ZB*|I7)`TgZ$ zJI5icxKTc&D^^f=Zi_A=%#;;FT=k8@CptanLpY~&>f9ww#Ms&?O&WEnvryUI+Drhs zfPjarD&hTR`UZz!%6Fx zw9*AYQqeP9ZDBsh*U+aU0(P88p{;YAhU{UHa8+w!7+MOV%e{iy@#9?Tl?1H;C0^*R zh#g*N+7Sl9c^vBwz9cqflOcy)EleG^9DhTK)>Fekps zu$5BA7#`z(e^DN=%6-M58G>-pkcg|#Ob}nTM)jpk}IMS1SP#O zFcgqZ!il{Rv|G-{#I$Do#5QLmMwcMzo(5G5LVe6qrNZUKr&M_|9A_XD$%RGw@CVHN zxC7Y}{yy@yMyb}O5FZG6{Ft}G5xllKe^}emb+%L`RQ@@oQ zknZXC(qCPqZh$sk`A+y2%`jDM9V2HydfOum((T=7yj>vrznxFtgtDLJq8JxWU2!SW z7^Nkhu=-H=gL|Rez;14LCqwYlhfH)waeedC=<&-JBc0xZTsmltHOz&4F0F-0dO+XV zgdDhH*52{1IjkfOxL|RJ{~1v(5ClA}bIX zoC*Z_q5OT>9&=bC^P$KF4v{O}Jg|q_=6Nhh=gIv=V+0{UsHYljQl@$!uNpOPsmF6@=Crr3NLV7$oEjmIJ{uJ-{W-|mGB@p z61ze%Q54|71@uLVrvc~?3C6K=ZU{sq6Re>RYEQ$Fn*uKc^`l9l>P)j7L?QS`k5Gp? zoF$EFFpThuiGb-gPEm(|$uW#nkBvT%q=G6=Yj2yJllw25_?36G@)OGjHg1MHdj7xaaJI84^#=r`~w6-lSIXx+jA|Pt4xPB z5+K*XWMpYg;$?0lWV-}PPweby&@o=j@?i!{_XN5gm2zT6-W=iBmdI&4rVjCvXk zO6*sg>681%ym(2aSOq50Rx$JrNF4oWmM4PZNOu$_Uz?*MJSc1kh*Pf*LZmnCj=T;v z**d#I;I8OgI_?49(_~rO2`>s(NVy7Ugfp$KumM^iEJ{i{1ug*6rtwXI%#N#- zt+gW6UTJ|cjwk+D?Qi1WiuxJmn%D6nt2z7XxK_9_C^Q|XgqIL}+wb;PR4bUExb^=7{Z=E@Kll zB6Hij4Qe2UC=61S9sT4JhZ3Ppbb7Dw)K*yT>MU{!yG$j4n5L0qkM&?jc#0>?oytX$ zu6Bq-zQWPI3k3)RadXuvyg`I660p?@ShavrO*xK8DKh2f#SC+JOmoH_*%$`Mh+|?S zi$qH~y;zgIOGs{kQMYFiHA5U(2{fkxR{eK*z6&Y%h%$}0+zpCIeOoAN6ypdp(upIZ zdRWiL2Q4wH*BU>EQx zFQ=P80HnC-p<7U@3d+C=J6D#)=>m;K8FHH`-HI*_nZo3q*?aj_N8QGt)IN}>aIgrH z<+B?jO+fhZz)jg?e2O|S5a-IO9(A!4$gkL*IO~+%&V}FiC_-IV14UC)V(6o+LhP_g zG}G{tf2v&N3y6UBxoD^?HG;NwV8f0&w%*xj67$3h&~ybiquxfWt(@DZztj4j4$)@R z^^a@RN@y5tc+@uHSD31ucTy=MtxwYd&ExJz0LvzcbfUM;aj!Fusqd)meykzOlSx%mmxK6lRBo5Y=(g+eu<#o z-c0wFtPvV%nxOnqmJP&L$|134lVU`6)fysQ&}ITH-*wiBuF;vr{Wc7{97qBZyh-^P z(eFQe9zPJ;#e`0Sz(tKHcF3F``Ow95uGNpJV>sst=+q$`Hi=48i8j#qda=U^zDk;G zwV2@n-r6sGI41AmXvV4JDR!_%yUm@=oN8sHw{V3VGcD%wvOu6bLYR!FZ;m!#QX3DH zb~CMhb~Z`%f?Tas366>ZSpK$)(uPTCf|MkWJ-aMN4+{IxQ0ORF`H%^HuD?^9x#0{H zodcNLirw5}3tHaSIPan-tCF z-w4#t|NdE~-M!rqs%w{i2@rGXu93sPzzMl%#ux$Q)bLjS!`*SeKv2Kedb3;=gESD42AbPW2tV!h6i}yM!CCsD4fSm zkVk>dCVsyn($?)Vb6<(lzFIm@5#mrPN0osHhmkiK9(-=fr1kKV(`>idj=;DCyC>=f zHk!HOUQEhIf#5f!)D^Cdfcy2`d>YRk1eM1)hXj`Yh$p{k9WM{dgbDDEfBYl9iI&8Q zvEqTQadhMs&t2mxlhP2J1_0|pP>(`7q@^4pz4EIDH^Od=bj}Beh~Pn}qXI=<;{&fO zO&EWbW9}87J|`u29Mir6Dr<%}CGwbye@jBGth0<{s#xXdW}TGOv{!}x*zIP%rqyKB zK`0Tv>C1LWl!KaySoVUYV8CcQ(2uTgR{MbemB#YnoC+4;$fZ5FQ%NJjhxaKI3Y*UL z4kSh(TXe*sg>I(rcBmh2YIWL`lQUVw-KBtpu8h$|`COFF(OksDSlY&ySO}QqDpI4C z)opc&sp<^ea$5}@|AnVpBmgM;Rv|hwE*2el38N6FW<1HW-nXSJJw%(lR5Ao?*#37x zkWHh>bfP-tCllue0Sh(7jI}WJblbeHy|N2TG={YL%EOG))?NsDmb4yJVV^i-TkrGZ zLE@a!l`*)FW7sW~G@ObCWW8`sCl)R6V^|(+nN7y*6*JF462>nUYC1nxVyoU>H&QB# zSP$V)oftjInOd6OPf;0)2M^N{{hJT6foh&hGbL>(B$8(-_WDYs6O$7RkSijlF>*;) znXXs)qCqm9X@6{!99L^P`4y&B2ZqeL;uyr-L-?jfn2C+y(Nd!!i@Whcg`pUtDrS&u z08S8e1RfitUaI@2`q2EMMjf-0gO&%4Oc}~ds;AJ)Qd`vOMpHdl@OljL&TwzFBRuX z0z>&O2PBgpD78Ju?%7myTjJ`-92?^rYoI87bI93&;3y`C*#SE2C@UlLTl!W;q(0Sw z2+=!^1SGCIDoEH@gmXK_E9EqWB&@FIbL2PEZ&DCAnDqdZyNhvlYSaFR%TBfu5si#| z74nJojLpBy*EfgTA^gm~VAHy$?Y+@*v%Zl8vJ8+QCdb6Tml?gJ_Z}CdB%_>YWq)_9 zVs`V|+6M7R96BCxMJPRrivVR4o;Y)60zLpIf%$InQfXLQQg~BNzk z3`#K8NA@U35w{uFX{gCchr*zCU_UTfXD23&6T_;_j^RphCXqE=lH`;6g;wy_{3(OQ zY(2t0?sz|4ERr5k|7ROoq&n4rg4Tk|F&?u{*T8?cgPN_!9Mv(M&d~|pr5ayVog7_1O@vEHB~rG*ioQhJ&u5T)Cchd+50rylnQTy}Un-jVki(Ehw+ zE)boyzFSD0?dWza!sW5j&&K=|S4mj{%7(hWiO4G0HPOPmAChzP9^cms2Z?G*C9Tht={hS*BSkRo6Nn7$)k3i3ByoN8YVw_P0JR zmpT#11Z%?dW@I+g%5c?b@Vz<`RaKvOUS{be&(lr=Rq{QV-6k|c)~G_a$9vm&WhGc9 zzOrMV@fcUEtd%1=8+%wlsb+Mer-O5+%pvj&pf?KB6lW47it5dX1>A~4aHeu1gd;r^ zjZOa1eu$f(*5cz`^U55dYKrFUS6t%?d9g8Vt9n9A=yBqLFe*j_JfLdkyH-60dasMp zQ4k~g@8|P3zJD)jz)BYvk&OdRF?Yj?ZSQsqyyfl$R7KoSfE&a(V?5A+q!so?3pW|=V$b@pQ^o4gmXaE7ITZy0lu;`+rsPHbL6#_@c}62p8#`NK}uCb|0MF0-Z5RVpw`(^(_S^4 zZDfx=P9+Iw&R=s^51MA70%)KM*#zjGj)?IXsX?I+(mMNrU}+D04XcXjav@KV%9ji{ zCTiHXq6mHDXlwkF54KkO;}H37@vemO_fH@3$=HuS)Bk?1|NTP$`@idd|0MtYM`Y_% zX6^zoaIlp|8p&DkMMPM4TV&F-H+}<83PEl5oFVE?JhaY(Kk=oJc zfBMsxAAiJ-H2X%*H2cKj3*SEb{C|G=kGkj_JLxzeem>ywebSpk!Fe#7ma4=wr{`Rvv_42>d-}&!8*rDG;z~cnFysxr{)-DVZn4JkPCVYYs! z?i#B{BMlI4OvdK}_*~h$00MlldEh}%M3*vW<$cxNVkUVevT?M&ol`!zLy|X(>kHZV zWjnV!FN1if48|7eFR|WpA?QH2fbep=TOnL-=v*T1<`YXVoeSdKWObn=-fb^|fXCKQ zwgthCQt@!6yJ?H2oCr~ofR#2&8BKAVV0=8-8H!TKB_!HB3jquaBF*B3*n@cv?ShKV z#(TV*g?-z6Rxc5~<5*qI?%x0Ljzf0)#s5)@?C8AwZj;Z%|1Wp%+8oDmq>cWS{p8CD zdc)H0`t?CL%pd_$f(4RT0F}{s2@;d9@^zAtL8eQ*H%+6ze=&zJ0gpSGM7A=K4dXi#Z}kwZTW8q3l@pzZehdihb2 zV$JdK4RgDkT@>vAr`;DCzfetqGC_g`77W9OHF7g=BzBuv@*C7QM+d<+K_X|+0JH|! z9N_dg$ls3V^D&B>@hTN7SdM$UKs_ApLF{pC#I1+?yOXE$PV18cO3SIptaIZ2d~ypS zCqe|!%vF5|IGSg7I~4CAX*f;CSDHBPZ$Bt*BYWj{7Aj$oZ|?lihv4YJt;g3mm!*id z2*|PKW<0}s88!TXsE)gpoHPV|@^eu2!R+d+#fAoVw3~5GKH8u>{Wv`jO~?my*RTKs zVvXIg3U3@WfiGTZiV^!Y2aSG0eg`r_a-{H-A8vt9C&8jeoe)+8nF*Q2#aCxIezN7i*V@M@^D6FSzoZ+~G zdlQ^rqRKm#Wa5Fb*SAybg1m_(b>QUHU`=w^IGv=GB|OHn36;AkrTmc%Zd}{Km}8#9 zK;^tq8la?avdwYW0d>?Dy;~L%t#JBxz20r^GS8#1GD$-yuA%1FLVyW;(>l?6?|MCB z8)Q(z{9`5M?8gjYno$lhN3qSb5YDRom=%i4d0U%-rL8f@m!L=A-i2EQ6>USbws-C1 z9j^y{P<%_ZA`uv}_9=vdH1P;)?0a}1NFW=sj1Nok!Ky<-(8ULWDKe0Ue7rQDVT0P9 z9g6jrFC@E1tbU|Ro-YvC~tZU>Ts`6kxkAym%!p0x(Hdxp262rS!w)v&a@eH(YLL2TU~JvoD&# zRX6g#9R9(ngt0fr+Pn_7prW}+D1b4t#oQTMKZ-xNc;G12ZKFTfc;E=$DT(NyEe#CP z(b0(Rn}P{DmpNox3SyIZ63pMA$98!c8WCY(+-N)<<2k7J&GXrAO+8biwH{B~9h*w0 zJ9zVJ&gpCJ3z7p-SujqhaA?>F7kmU<8UqsxRYyVxoNvUbRfUYNadvRiCTYak0GCKn z#3rva!sAha_qioox-?Ac1jMJ5AjGGF*lY->n3h0l{xb%gk#}Yo0@ROS zA?)(5z1f!NxIxWRk%@mkE-Cl@dns3$N^+Am~!}Opej!Yb@k39>Wz|BeGT; z$hC@=eb{vF5`XM6r<902S&oZ((r@M>%u%6uRl>EKc$;ZzP}~7l40?v-r4sDUNidl; zamj`RW}Aa7w>YO;N#cFmDoGcW@)9R_3IjE}iTfpMM4KrBRU)JhUTz$arR>hz2_j5Q zY&a*_hL?t#;r;mCO0KIDs;zd0Bp?KK7YfsflmyQ`4w&_<{x31g6s|;3vFJOE>_P)K zyPtoKbhb8;if&~rG}_+7K`v3wn5pyZ#)ca|p-Y_(pB&sPzI{`Li0hklJBJ|n^E+zI z)*sg{a2>bIH?UkaI6PKO5a1h{<-yZyv1w0AUge(0Vgt-tGn)UaC_Z6nYgVo9DO;}- z1q6XMLJ#Y9(uK7f`;3l4Y-Ami7Cwny5Z5yAg|4a?>ejP{v$kb89&5p`3Y-dZR8$0o z&gn;cuYl0=U}-S^*&u_CqE33rmi=!Bh#1m*wI09s7mLl~vT=bzz_#Nzug>3Go?g8e z9lv>fdG+k|Re;M^7tg*uz4|`;DN&62!m<&smp~RwjxI0Q22c@YMm_WrKr}D;l3YPB z#E{_o2Rz({>z$U0;l6hpaMZD*O#RY8@9<(N0zMeSov8G{+BugdE~Cb}80J64%tA6% zY5d1n)d2eHZa2SPjN77}>>Xp)+>R#_EiFiEhog5#vuRLF+&$LFW3rey2P;uIZ8s}E zo&}$?SvqYd?Fx~NQb(#ow7P@)Qe6$v+jgJ~z~*@oQF*DA+dV^}9P<1U#Y2jyd5@%pytEtePC^qgpv6O!zgb{GR%a?iKOTa^LjNL~n$ie(RrwF}4p-O~*fklzb_5e$_ z0RVEn_K)gj`1y_=RFc_T7?{2U6?zw`B>LWQic5S194>91M@M792mHn@Rq+Sld;ImY z*RNlkm3;(6jB)BO5h&xELWn7&^tp_#7(H^wU&8G^r(*S4TVT@flcRhA-2n%`o$p-a z3xKr?gb28)nVC*KgW2rEf4TlJUQb`5`~Y42&y&gEb%?4E_KVO6xO3E&cq-MyrU8z4hI(~EZ=Hl}F+3}0f z{}WFl?j|?ni8EQhSLYWmE-z2tyzcJ!pOO)#{WG75M?nF~+ugc(gHSnKAZ=Q5TDbM< zo`XHz&0gZUDuC<(1`8mCS%tdFkT2;Bu%`t*YuMc;-qSb%*bXJ<{?{iLr!N*%>A@}? zmALoya^AeXIO`re)KeWf6E?SbMtA3rWerr2xygVOq_Me}5pOVY`g~6ZV2e%jwSV14 z`40&18eaD*0^!l0yNnXnZpBuq^1@j=EtAS~lDtwSdUI77(cn z!l~-}A*O6UX;v<}MgsSS$jo14H;tFp8-4^F3_oMt&eGNAW-#9RsdX~o7_K8$P#w)C zTJLZ%a8F!$$xp_6f#mQ8r(>dUB9M7Y2O>xD9`*@}Sma+hrjyXy#msMZ>n)-iMw^WH zPCu$1&_0Nw)20r4QuL}Bn{8Ec@WDXimIdy(Oi!BkEvJLzW0=&ssJOuCj5!4n%UD*% zDgI+$23;Zv2@2QZ{o+U@o(7dpKGYMc2Uei&$&~c}2%7(o^3*zpbN6bzv1dJW!dKer zR=zqBAuX3xShB7JT>=6|VNWYge-vIQW<6`HjzD2F6H?I8LRav^0-yhRYs%+tf-qO*n$@*J~_QaFt6l`$oRvon;18wl1w$OiqLH5OsUwF zf>B96RdjTiU%@23Z|G=FJ&`l>j_I|xo5ECl zMRz6+UoO9v`^KWeRmJ+6q>p+7c2kx2%rrdwcwX@TTDAhGTq>pq_^I8zxSZVKeSP)f;;if@GY7ao=j}DGI1RA~;rz`Rg$OFs`4n3uHuSy5<_z@#otF?VePtfJ zVlJJb^c|jaAE0eG;&JJvbq|nRRgG&=KVRWNl`G^eDGrO};t$PywY~pCm+s2}e3%mH z1oH+?^6RT-SLKZei{{*Kie>#PO@}8Rd4Ak?ObyntDz#WjirfDp7Z7qqfWercqys`% z)Y5z*?Q1&1B$1uNkty^?imH2v%f;-T3%*JYQ(cxC1uhg_e;mNJZg|v&5PQ)~4>v0p z&8>HYRbz-#j}YH7VO$`S1yzL?w>1CVHqmM4#f#S`FD_1Be?|7=^;K=+BY7)M5*Ixk zw%6DU+|gWO?wiI9F&UT01m{ik0CRCkr^sSqhk(9<#onAZ>q|QGu-)yTj#Rqnbn)(l z>iN3L!yU_EU}~IDPG5a>_5FF(3cp3T%qCZLE&5h!8M8@oam~ayU99MzBg4^{6oiB{QJPMNIKA*d;#iK zzY9E6jq}-5fUH5UX+hxIsX=dFbe$#6gmy1HFb$ttWhFFDcArXIV& zEdJd84HQH~sY;egkTQakZ@J6}*qfUhUrVoK>%K*9i(hnQP#k{HH!&N@Fi-SHlO_B? zx@&FzV1mWncs4z*5rm)tu-qw_W5FUwtiNE%H^LexSz5Q+Y#;?3QOcRSy`iVP!fqwQ``Pu_6_jwLk6JDJ(i& zYb^1j4#eo*j2&QKwS@ zcmR-u8lXA_JXnQp@-&=?LzP@AodT^_NVynBdXrCe*tTu+vMY;LZlpRqf&3$;(axJG z4rvkBgNs}ea>}}x0aW0Vd)0D3xje=Q1|9cTiT=!hQ5?OO&&%l!DH25`ye=omZ)k%j zag~s9cT&T^^l!B&r5q*5fo@^q)ff#-VjxjZc6Th_ukw3X+ZJ4*oI?n1>EUpnS{P~Jd(Z>JNp1=1_a>V>E*n<`^j513+t8@v=J7_c_I zq~?x$N&GJ3M!X(2`KnYAk8n@?eADcvOJ=7oXAa5E4Hr;A?Fe*LxL$3O5nMqkPMpks z%tnq|kk>{}Qf19BekT`~Z9RFZ(;6YcAMdhT$?kDV-;6zVc%#G;CCgz5p zPtp+ugdDJ=EHla_o$||3UQ&HLTv7H{=c3Y2`d(Kv1|jr@1yoXqgJjdGMa%)tAEOHf z4FX{4tSg%WiBELl+@TT1fZ`~mn zL#Jv?=yYejY>O93SCT_b(Q_b0*kMWJL&7HReXB{?ws07` z^tYmG!N2wHZ$Th2s3gZkh9FoQ({T0_QbaTdc`9>R7HZzIhLp<(K3*pVYp?{zj+`%G zgkkK2MffsD7zepv@+vMm=Qbw7C*|F*gHW?ZC}FXM$AK`Kp(NXHOz1TtK+T$?!kR4N zKFV3De#Il$d_bXpB5gnVn{MfbK`NtDLyKNVLS0M7&_wpBS{5vO7a;unRi^r{7+S^qk1pJ~YG16Gb z(K1=mIoG;yxRt0XOM+r6hk~Hhcs#2)YKd_GO`QfC#WBnG(R;U{*=qpVrnTHGqko1w>w6DvtdDbY<;?!gQDV=%D~y=`IGcZm6uO`f>Sw zXT2<6a4wpjSWwlv6mjJ^xAB{z##|%bR*Cxr4!h&J*_BRS1|YrLQqgjEyu>9-cX!vM z2}RPiFfx2lqta(g_2s)pDw?r9a;DQR7sg*n*0_ejWrIOc@MFS2k6%UG18gYt65~f- zGSui}gcY|cAQUTTea>|&Xhcvoo(dSDW0=MX(qc9sq4Qekrnx1nR^l1k-?XA7j+tmD zI&yo?Na&mSa=E>${D`A2+_tN^DjS?P;tI?Iiv^X@>QwDbgT0>xc8>Gpe{fLyo9T-M z)vVg_6^bvESXe+O>AZc0bF*i`Ym{nRad54VRAQ3mt_h4}`38W^%97nkhd!o*vG87u zbYvEnsjjTQh3)T=QD=2xfC>P$)fENUB6EXFFAhB1=q}J-S08pX7q-pA*Fw50DN!iBT z_=-!y?j)R1?^m83VUW7qH@+!jR2J^ZV6M4m=qn-=Dw3-+1~N`*7z*v-Gl`LUo2=Y|y2D)|bVg$BT$vquo1v?#Xajl)CIV`dpI|fGrd_;seA4LhP zVuZOf)<3bGkVzD>=mHnqbD)(sfmH4pUypD|;4^}wxHdsks%w6*O~fvM|C`K{=&l4I zMD{a)$Vb+RFQ8s9gFDRBvTl*d^cMykS^BlhP6Wm_A!mT4c4NcorW}@o%ryfE?@k!{ zIQf-xlWgl`YFSdKe)WlOSGdvi&P5lqUQp$0OG&bh5Oc@2qNs+4uTadaD2v9>kh30A zw=RPa-jlGNNeV#``euQ zusT++{Az*`jMyfok~>_lPVqu~;ILR;kuh;l#c=Bk*>}w@fWy9fvw5{d>X465KuDqU zSzZFrcZD(tsjr*kGROnUZUz`_`^~v>0>8nM@DifjBZ!X-W7q7t@ZqFbllF`>73COa z?;Ca$%;z{#Rkw5)u#1&ABn1}iF)|Jx}JDFKc zus09`Y*ChSZ+(ZW$m7^n-EZw}-_NMr<$%pvlwNN{?!6WGY=($$Jy1Sr;(u|roqM#k zY-Gy@$7n=C+l)5)q)PN}s+N!$pCnPv`tHr2&o#dZE*(OL+2DpGCFIm<1R%-}x1qbifUJ(f%|Pq`({nd2C;O&(O5>l~`A(j` zbvs3b;oiGdyQGu=zAR=iWgY`aLw0jg&YO)7S#12uyVBfxf6h|dsAyQOAlNOX*tFjv zmzEv%WJZ^QZXgqNsi_AkvSTw|YmUFgBYk8$qx)f9@)0oY?W;>fQlA9APiie+J?HA=K6t3of9-PCW9 z*13o>Bm=R3z`+1Qxa)T#uBSjtkDm-(Du8ZH1T@y03|vC}y03)WW+xBQ$*dEHJHXri znatAd>hMO`W5M!tN zF|sh765m?VbqQYgG60mb6JmVB=1<`($MsssBnk8!Gc=YzN55z{*pq# zTYC4K!0CP#XcltNBejbm9v^r*#84!ia-S^QeCf*WFC=NUIqno9%{ZGkqdRxK?b_lC z6){c`Xl&|`ZpFh3>q5()wB)6m!rK|P5L0Rx@u{$o&2gU1>f&6A1EvB(4Xx!fuAn!~?|1q>RNOMY^J(=P9jQ3~qXHn%?t+KPI9zo-r4n(fFtt9w z11eH&Q64sur9hGINg?1+1Hc99T}i&>!$XEz%oz1x%{4JgV;IFVeLVdU7o_Q1F4X|m zBjR|1%Zk-^gaWOSc4K}ECSi|$1k%|KO?%1vEr_lrJ*xo?Fg;0{%u&Gusd2n&6NB3X zXJ>#XuhTkBluCW>&kf&Sa(~KOUYU*xIoHk4s9u^3K3U=uf_ve)3Hl*)VYMNjk;M#-F$oX>)|`=F4Q?4sdFddA zisLNH&&y|~>xd-+b35T2orKZp8rVl`Fwp2i(fONB%u-e=;=X{yP^sUTF&kOQ9ksp% z@n(htOjo(c=6<)p*D(z!01#>i_A^qF*AanKLf<0864&;hXJ^E;Fkm;xMIds~qYG85 zJNM6})a0TqFLq9+lTC_nL7RmU)mpo_LJGa?Ubw>Rpu!H~W+)xzMvioyF6s~;n^fjF zP^Pv4Wy-UoqnD>=XBThJl0qyVCrURFbUN5Zc`7f**tFZRLQmT)h*vQ%gf~D3L9q@3 zsiE8~j`??Vba{30;_CS8xbROz;^p?<3Ei>g^6L9ezI@kFFwH@aPc$9uV#Qh4X{b;^ zFVYw(cMBdAay$Z4RGK={d@mJ~E+^y7-Lo}aFO(7L;_~g^gheXqVv`PMxIA!-y6KVP zA03^YzJ781?7Sj4-}P_gW)%AV?agUY8QHN|I=_NxT!$gw+Dw+_`^n|Ipk7d&0aw_X zKAXYEDCvHzk&8YDU zdPE#Yb}E$(7o;f~XKH=QCp^%BOF9I0y}FskojzbS*ryZS2Oc`WTgqzRYqop~1})c^ z@+-WsYtyktJ6)Jj_SjN-u+Nu?K~CI7%mzJPiQ|QMh{JyKHnOp7F@0+XT zvujT6PpOornMJs8a_+zI3qJWgUq*l4$A4C7=)wc}LQ_)w$#eE~4?`=)%Kx>;z$j(} zEZ*yFeY9edJ}o+On>JAc1SS#7O6}v zatZh$R{rI9$0bvXSvqEIVgW!8rsqkBWgelVs+9Al{cA$AQ%%RJ6VT6vm zreZ?ZbnCO|il>()wLM>Z38!r1@JT}1?x?}aq*ufX{64a|Q&3l)^X{_Tw zV`BFT!uVP>eg&5IX?T}Fd%20d3M$E97T*6IS$iV zU(}MM^2Q^bksWgrASk?6y3`aLo>q3V+Bw{38U{?dT<5^(L&ZR-#DR(s-e82(j`(Md zLMWr%nu`(Dtd$aVs5mS4-nfK%j}~R2NQXA!gQFV>QufFaEwc!vf!S+vCBaLB!6}y; zO2q^s9cqz9G!4KFegW$#2dQgT@bE!o)4Ff?8^$h1yGV9`A4NB#bcu8>F+D#H{z>iQf*bONq16yIhH_9fX>8FU9I$XCX+si{5$FHo>H1 zEELS%=0cE5BfKWFDI&iT?S;52VP7bW2NH#SLnxZ_)2;FXhum@>4K^U;F-{O8?$A5m zJ%|X0{p~!uruYINiwYYE6pF?@o=W;}BBNN94Z=o*y@%RV?XZICx5PqJ7>!P_NgTb> z0!vZaG)iqyaQ2|l>kiQ{fXWOQruqaS3t<}$^l-DrwtJ8`DTT4g;d9@603@Mp!=SN< zH@ZVK6lAV3vJ&n#gGCoKsXGAG7Y7$M&m-V_!-<39*8QD^%6rks;^f8>_{X@{vbP^u zblnZ+$9bRQ@h$4FUE@%?v;(1e4_QmtQ2&sCv;D#mHu@tM9v+$ddjhq8mq1U`eZO}v z&R(N3vPsV&-iMStJvtgsr}9sQVRBVJQh$SV;|~Gd0VHy+?{jd4#y9Kb{P_+=deS2~ z?G5(7gJv}|zEObTmGkluwn|k$pF;xR=!ix@!YLJB5*fz?U;vzcM5USVNs62W8K(u* zaoiliDQ?Va90r=B5vjSXiOam$Na???llYG%W_A^kwTVrvy~< zoG=j2xk`GNcJ9iqaZONAB-EaOXWFDYZA2SU#zc_Uz~ubz`siOk{U^3?PyXdL`s+IS zYaIN=<>?$7r%d7>KYj7(%W%FX!#>-nR*AOcij}lK=A1@poCqjs8COimQuvbA-{MVl zW2YE)lT^W{DfJyZ+}D@(7Hv&+Ad>JRT$#*v!&qEOR<wT ze-0>>D(NVS&@L#Ot{kTKScmFvnAYy~bFWkQ`ePjDciGvFw7LXFuetTZO?Id==F+ap zO!KV=SYY3nEU`ehZx<*XDWVv?hSx34+en`KhkEos5)sB(x7ZV#gRD^mD82$YI1s2QI z=+D>gX)IZ({4+{h5>dQ@aTh$mvUXK^d7f(@8edwhR+Qx{R>#aez&GQ$o=-ujz9RT? zM#V+_NZvJ*#s2i~iq23fuaO*| zJZ9FMmNZY9;ySI26viJ^*Yu9%PkRJl35N_AmR-!3S@cf zRc6$oKt;1Hc@@lj+|DQtQDPwjvIYYuf;BI|LkX*955$~G4d9%Bwy__MDi?saQ}?2I zXg;oX3wKSk+deqGx}md>5i&8>RDNIeDg+Phs7k7=UR5>Vu^weE=d-L!iFsUH*Y~xS zMSh3O?{4DgSvxnwDIjym5C;$kdSJeAQP&MV%)EeW!|f!qkykIXVTV#!W#VminX9_G z!4$eex=x$nYL9-}AuVA~MgD1x!nY-Z;{b94p?m1;m{*J#V2&qd!UqGZ8%4lVGvl6I z8VYsY+yqoZ8#LV|_!#mQx7Ih4b&F>p_vG(B<0KRHa7CtY=SZ%avj0L08(Fj6^^aJj z3%^X8n=xKw7~SDjlcL8XsI`lma4)j5EdxDBTf?qrM2?N5 zhDJLYRLr{hKcnq(g#Z3o;ilRkckfk^9VU26iGU8rCF+R`Pam5cK#1!Mtu!NL+k4N1 zqCj_>bl<K%izhtGaCHbWYf!+&o=3lRtm? zkV3}Peu*dvVHZvJT9D_W7bC^8 zGHC-=SrHBz7QP%|9ehH~&<#DV5`K2nY*5G~*rN6d2&tw)bmf!HP@*{7S?R_uBoxi6 zHviY~PH0SHWS}G7;8ZnrfQt`eI~=180$fPT+;3FuMi8cKxkjGa>jFz@U}WPVv>fu@ z%RJdN_6j}SE&{$X&D8^q)*KA%cYM9jjsMY1i7q){Jbn?GH^54ENX;)FC*0tn`3Hzj z7aAPA>&d6-j0M#xEL@_g5J^RhKAG%WI&>bu) zbTr;~ubr~YLxUr>+?kl8R!% zkvB_TExWf$b&6-ftzFH$Kkl)+rF@&n{H$8IuSxmccFw(j`0W?bc!Y9i^Dldw144p= zFm(kh0|yn}J>nGaQKXY9CfkHIyGnW-8b(3~i&OhCv=j_)ft$9zHiz|J;8j*x)7=!g z8{>dT3y3~2Kw6UA0YMSZ<6;h@WTBICw-W<+he5Rc)?Fy66w%tuWcM1T>LvUg; zet_)=3DcY?2>`LuFgRfhUOFLESf|nt(k;TJOGu|dO4x^%FbPjR?AR;nW2OHAH`)T6>WnUh?d%v z)uuii2+MN%pf*5kbi;6h*o#-90^a?Aa9Y6+9SBO@D%6b=mi0+X?^-Ei9zY)EimPMx z05I%Bhbuej{GMFG!>~{iwmQ8m3bcgQ0y=%4gZI~pg2d^0TJ5dcjyt0cp}IDFMni= z$l`Y55`qcBD-;(03(M($KTMB2g#fyF$A1g_C#bgau5H3EMAnfA@gGAu5@9iqxNFm_ zlL}DD62XxgrDR}p$Qw65^|#aZy%!g81-9Pr@Teiap;1e2Z)7#F5yX2th&iB6mCHyq ztR|EhnG2HkFSF%XE*1rPcVORvkhOlL3Fg^MED(V{XRPkgO66yPi%18{aT&}xN_K5*x+*kk8Gi@mxE|uS zi&=}KqiE4q_BbOE-wZwV`06y>NkHv~6mF z8naR7&<>aTzHgWA5QVx{bPpa#z%3)c6ut(hVf2E)p*6-=LWj^ehE*hXl6LTZ#qh-6 zWA~PZp@aVl$Q#&SWn>S~<@QdJCZf@ZHUoCu;0a&zz#a@OyVeFmy6BCBYADG{gV#OP z2+EVf;S$bq;5RPU$|2J#JtXn_p6nq`;V4n< z_jMH6UoK|%Z{hRNFFd1CYH-7cNO>%sQ9PoRxIWvY^;Pg-XNumVA;!Yui)Hs4*e+EB z(yskA;L!xXaN$*dfjiVz1dvGAXdjHSdSqut67tv|=gqqo7x^9oQef_!l`L7)RFsVV z&%Q>*Db`D}jkHR5%^n1a6lREur6`cNv7(Q-U<>E|_A?UN8(EdW1v61WozMhzmF|$x z;1`3g6)eOITScsVEoMJ9DmYG8oVvOLsea!9Z~>8CR388_LCA-4deEq@NElt&Jz#WZ zvflX2rvk+ihXIMO0Z{SM-mKrQ-mFiSA9!gOXC$QeFk%7T#qOX9E<^wgMg(>1GZcC_ zc(2dA5)8nE$(C2j^lw%^ydAG;=KA#xAui{gQLlD^6SD9N^8S_!iHsDmt1g5+$VOA4 z1b4W`0qb^irV3hGp1?$$NpxGl9(2iWl8t%8w~b3q0S(e)8y{tifp!5*A)k>j&F2B( zN^nMj741Qenv;PgfVtu$btm;;otJt8SG=it$~1dUgB?c>mm^U)tysoLPjXJfH-E-EpjRblc5vsCQ$L`y z?QPC@hnsJ0GTKgTtHSPYw7Dr7*$hBepv;tuxyTJWV`NctuAJep3q(+4`B%CddUY7z zzLBlZx4iRtxm*kTOn-FWL%Q>@9Z$x*GurkXs3;MRe!ErP%w!`UI4JXXJcC>|rwbMl zZ*#rg6s2>ZR9+YMB^e$DnC9IMdn_8bLkR{cw9G%x0OVf!FXxVD$P_KF z=WZdim4PsSI*>WI>U9AtZ&gLX&rU02n9Rx4iz%u*X#mz~APiXDL(gdIG93qiOXs0F zC`3|CfkBkBC^3h(W_uz(J0@YfG^a<^*8S;B0FG~ujwnm^nJcLx(NQ2rpOxR4)8zV{ zw72b+S5qCM72k{tz0NFW5I!;Q z8f05g3IH*|Tu@8f!D)>=-s|}3N~60k6D;MNv;`%he{;&Da_YECXf`l$D;;=p&5MGA z7o&{R;^{H655L6!=UxtLimo(b4TJa4D%`4}a} zkt=~47;c^MjOr670f9sKE;-09(-dPI~^!nvD$0K_G z(Py9p+L&urhQsM%d%ni4;q~?&E^EQ0AhDQ#t#UDh&@LVd;h`uL#xI+NUbe)t z0m_0gP`bv}7nrTFY*E<{?*c2-@)4CR|T#7i*={0ds7K6$3YJvl{Xk9FZLzyQ{qo=|Sj{=7LoxlG^pBU8~Y!qdw)$B6u6-?aare;dCa zABwQ_JrHT?OpiQsGUEPtBX=xMpXq0nxQvG=U|1Gp4^2YZLw9Lxk8bo_$N`giOZkQS zGxIIKa(3O|+06qwpOGjg2N|Co4x7yj-h(@D-%`KBhJ5?o9d47d=Iu`__dQTH9}hBN zR2WCBtS)=B5^?S>EsWx6#!eaKI{UdX+!x&moO{wD7?ae-djy0d8+)REqUo19iH)ygbE7jX5$k%47RoZ zWczXsCX%JrJV4(ILvWYlAVW~A7;>Y;e@lpyGa+RHjU4?hrS&lEuTAO0h{Qe&!c-!K zA3n-Mh^2k>YNcYYIIhD<@|-aI{6<$PKTv0e^f>mzra|0L`Lp8bbFd7ra9QMwna^XLWMNN9CZ zXy(O%mfmq}vIeurJ`L`BY8H41nm&da_{J5ISm(ANO0naOiK2yxP5H=FHUro5r0$H2 zPjQOhe9)R%xLU_L3r(m^66qeODz3tq+C1JUhZICx7mU@Si=#$l2O5BMt zu{#flR7Y1w#N^s|z7-wa3VzC|yh(7Yz`q~?BkF;yo8mJNQ5%F2T$!LqsiG?xDcXzW z;t$PywY~pCf?m=KMl^D3lqQmO{N2baUtp@H%0O;wT+s^SKlp?T#E1s2Q1DH1xe^>} zV?6viSYc-M3})V4DcQw-+mBO1#ew(3_9ox~_r&%d>(KjRdk=Kry|I19iHtzFUe)x4 zlkj!=3~Im6jk4OHG<`V`NDb_aV&H5t|A{s*d*E%|I&*J2@GbaX z#je&oSQSYK5R6>p%N)ZRfW0o=bpWZ|zN>X1pUYobG;gAC4eu0-r}~<4`hkjD3#VK50i$vkI{2WA>b|fG;b#5^@t(0;-@jR3 zj6cY`*}+EB*8CK#{ar!@Fb7j)a86J95hb9!n*yVhbMm5ExCzGK>xd3&nNtyFb^aIm z%HqfoZww{kji-aWZ}&?M4~F7+43DdwjAy4O3QeUM!SUa)CBj>gsD; zWEr7M_&v^OLnSS?3^jTX#aRKO zkljpY*WN#3NdLA!YW~%$tCEC^WToP(G(u4CI}n7zJ!uCpe~Udb=}s`G@io`hB5aw2 zimwVU-mw4{OOwEx6@ofB#i#Gu5uc}9 zYVnWSRP_=$CS?Cj{f)nzpJ+-&4DLb3XGI0}rN@e( z0-w!g8cBKV%mPF@+y0CSA6QPpt5xmPkVOk0j`7AT;IP5q#Q|lB_Fo-{cE2T#;gQ~l zw>VC#_B2N+zIZ$gO2$t`2bwTK@ollk^l(AAPw(ImCf0AfQFhad6eWN>6>FSVVeya= zyUlb2z`d<@u_;PEAgltg8jq;rxA*i!d-jn;$2zHq!a_p#Fw55^8(G%+e$%PI!+Tqy0SKpgMh-6o z3IGPQ^UA6!g6jffDuz(sPEf|5hGt7yO}RWyyJ?o9UKmeNczomaCkcgHc`bL=<;tuA zL0z#pn)hsd3(JdL!N*C%clbDbHuIin5H9TKfR{$Yw>B*Ztura~^?)!XX7DG%1%G1~ z#Ty|0_PeK7cc?;02_(P&^t-30i}I+y? zAO^ch@wPyOy(o2rH#!hISFY+vj;lCVE%yqK(8?{CU|iF12^K+lwHr#;z?9dLX-`m2 zuz5=L)Sl2|8c*#r7aDtd#Q)KF@Dn;jetPu7Z;$Z5Pe1(j4}bmPw@>H*^XU;U@BjTj zPcU7OIQ{fU{`-%=_Vbvre732nK)d=9Iv!L|^0T?EmEA@;wn;Ph&*Z69Grx>}CfgS* zm(cAWR}CI_1qad>YVg};wOr2JMBwQS7%M)s5{=@?{1+Jr97QcV`S)MLf^_+~3<}k! zRrH3TaBqYqQlJo~@-0jWrb=)HWRb1B{Gc5fXYUPSq(a4YHA{hqwi$6BAVwzkV1 z3|GQ;1EDW`}n)@Hp|5t$%_e4%hE;<3aCX?Il%yKx=pp z3$~^Qv|a+fg+Eg+{Tc+$y?>~eiI0vdN6GGYb}mAWu<_KNN8{CMX6M;|{3I2S-#33y zUy-eXmPN%HPx}mJ0L;F5AjDX+|Lk5S58a8z+i<)RC^Ex`i!jD+AzT3E-$1AXSK1$d z#Ys(IWB;?;TZHHk=w*k?zABO-)r5xqZ2#>#|8A9PVo^VwYW9Ib@gu^iJ;fsrYx^=7 z)h;zNU`Iz?>gHQ@tDSFGRKFjQR6U~OBP`Fl6B>o(C|GGqjX=6mt0s+P!VTAWdo+IM ziL{X(EBtZH&zh1H!aswa2#&a_gifEREgL;EAMpp*9UFIfS;*H2buhvgOx(Yto-O6? zH}Ig`oe0~_$uESp{>$~llU8sJ9p@|xXdU@y>L>r8Zj{6x>^Z^3<1r>hft6F-|6blu zsU!VS3=&xR;||w(P(Sis<}l$U8_Mi)nIETI^@n{nSzFXr_d#J|b;tbUbi2I4dy=kT zb{`C84?59g=A0xYU}(P|k&?5qI~aYPK*?QmjX4mx!Z-2$f=Cdq?THFrU;U_Ez+=Bz z`VriZc*H1U5L+dkM6#kw)(wcK=~O>1ueB67uCXp)Dub75MU$DeOFVs*N;7$33cyRR zR{e;s{${#oZLuwOa9@77p4;P2w(ir;F4+WNG-{ZCMLBOgK;BRRvw&>=`k|dh<)|=4 zn#~<9ZCXPn6;E5n&+Ph1fS;(TCj$Gor97-msJaLc?k8)Bt8`5*-S_;FMq~qFb23fi z@=9R4UWZc(5PYeO?uZl98{A6%+vS_rqZbz!Z!Si!-@JbDDfs*3#rf6O;fKqsXIC#q zuTC#tJ-a%NemTCnI2#>*{p=!Y{{8E#XMYdByuEt)=kV`~7sqceE>GXQ4nLm0emNp+ zo<(2ZzP@~We*Wg->cz?E>ihEu(bL!8K07--8J%CeIe&3+^*#E&iW*?tFa9J;3-Q}C zA$XEl1xuXz8ycN15GkaH-Ixj?h9g%zwM^?T}=KF zzq@21vUki}?L>2Yy>l0tg5R$1kLmo(TU8@~@oc=nb z`np`YF1B2yJ)mrbExTxjw0(<}*F;f+;$=!fe3hHSk_A^{9X0M^UCQcB`?G11+i&`5 zCq95`y!Z#;CH>BN#SKdbQu-@7kq`A)-i@d8{}@f~=#9D&U3i?dt1RMz3~+se(gj-} z1>YJ-`&HatyCe1mYOe#yVUh0|2TTqcD2$QwHZ@fMNouobn5=1V|w3xaT z2=QI`AxTxaK^X4quAZe7KWHyH`-k#`S=_=C$dC_^JSA@YV z0>~K6)C=7o#eic3%n&PcPo+J=&9=+R$#%?cuO63v{VcS^fb%rxb1?T6swSRT~;;YfK-Lze5?GV^y*5>E!7Ma4f;-?r_ zyP+Tnf{^Zki^2WQ#`o?pYIvt+af^++_dP;RR8d4y-wLlp9Y)``QBut?Oxw-za&^C^ z$U}T`(T{Gsd4qnq(h;2;4e1AQZl%!Kiv{hlEEvSAbOwO-bu9Ko6_mG;w(uUX4uP!X z7f`^YD}Nr*cT6%#wDD20ZfIYYp?x_7n$3h~vujs~s9+;pv-Q@`mX3C~u15QRrLm*o zSIxo&kvp34RjGbxI4_u32sYI{BO$mdS!{yBo52RssRIuC8$9iUmF>;-kGPzUed96x zrAWo?xXB1veub1Hk|hJ6XM0sOm%gcZw3n2su7eW(&=$9aF?xI-LQ@;NO^N>% z77*8=f(MyY0)WYlP=AbngkAN!ov8bZkJu({D2?v2V(z2nA@ZEa2_E!N037KWNk91c z@_obbxyHY@dEE?hz1~{vw4bSnZDFjKbJ}YN+x(7IJ6UzDLPiUnp13VAdjX!GfU^e< zV1ok`Otc7`mu9SBjgxZXl0?0O+dfKI;j)kKv0EV~3-@q2k7TP|Hw${Igd@=bwr68h z&UtrqgeY|*#pJS$3FkJ+I!EvsMb4QxAw&1zln$o1jaA0b9_*BbMq zIhS~?3KQV@{YzAB!THH1ygcOk$2eUR6Z64ic$eRvs0{Xlvf4De=@RL4Sch%qmmq|c zY;Xp*L$<`XT!6b{*r?NT_P(Jk!SNb*TlOa#H*}gcn?Str`VueP_!@<#0(W>to)wP% zL6$;Hr|UYX44&Np+RJO!Q*pT z_!twijxLEWu)#L)1mzh`P^F*y*9U_%MNV{#J1X=dhzQjAA2|o9$A1RzA}b5~x|J6d zLjyCD?$9+}GQkA)QiokXMr73HFP|CfYQXCS7{Pi`ixKhzIlq ziB1e$F4!mf1dLwL^T_74P#xTyXJ`cn57`Bm)dkOU0;LsNyx57>c!`BFPmh;~R={1w z+hNf>i!~c#AQfQV)8rMNY(}!TWl*Z{l7qbr@ax_Dg5P*I=+rN3m1(ZGSCJghjjHxukV(w0uJ>pC2_8JcznK~#Berhpg0{#NcpOn>}>4ZDo-&ffb2T(0Y zz;7Ih`Gir-xawKVWLIvR|DntZF#tmHL_MM8GhdC3M@I_#0<$azO|yVHm1l!?3wf@5 z;)%h0Dle&|1Teuk*q9d%=BxOAFin(w5h#_4I>V>L(f!dP-rmBoj z{TiosRwbTm+}&~`dvb3IRydtvQK~Vc2SJ*&k$jXR#i$Mzuo~~ScUeZ|OgO`H1KnQ@)71w48 z&*~P;fMiz(=9kPxe!k38u=%*Or5mcktJ^1=GK3aUZa)y1b@S5_*VFOUqmOTt!kG+M zH1%$!fWEJrZK0d|fH6XFo_|1BtxP1TPMpbQ2%&)t0e#E9OM#cG5UE0eULjeWk5W+vI8AgY_j3~a8%q~+tPrgbP;y)g0Stcb2W#tWS9tOB&R$wJND)M@PVkMU(ym)9Y)m< z&Pj@p>ThV?YJ4XX5j{za4`P{MZ)rvcXKv)l5YyNaN1}ODz5xS26TSU)3hhy#SH+dq zgE-nLzCJYQmbngIo=l-Vlxh>Su26jmQaeu=K4KGz@NE2zco6O#6dz<@>n(1wVE9O0 zAwQtSmR~G>xL-e#KQ1 zKj(7D1InCunCH`Jz8!mcxJPh*)PEZ2-|@E>BB|*hIPDBRbutc9F zVuCHIb}%LBUmgX~$6OVD5wths&1^)m+x=KfJu)RPM4#Cmq#@{K+eG(yXui}?`hh~1 z6WE2?Z$Ib1;jCvRvqx^?RI{u<#u!_Ty zMhjin-D1!A$32^|W%SYZv@?oi2wcuf? zakb82(pU@=DP{5l-#wu0b|d0ft!h|Bu3pS=*1SiR3|#PV^)M`kvR!`>yC#s&m%$gA zqOP|ui7^xaly`z7N8DL=M#DZ~i)(hoK2gXaG%f8l(n+Pv4tciAwME~2vZgdap<^;X z(>c*KRZ?5M{qthV8$-rFDPPqDRV0QQjo0xF-Jwby@tb@qZrm$H&bRUxdX3*9c4 zerj%l#u^)B4oVMN#<1yZ*0?d#i7Ca^kl?!>6)RRH5FxP!c_(z=fm6Q4{a^-xt?94e zu0`$SltWOXa#J8yQ42Y3+@lu4p_qYZ?YyOgNo1WaJ4;O~A^;x7UMg>3k0j|h&pzI5|K+|qO>|64w7h4;QQSzgufJtPAD|9D* zfG6ddSTsM{iM$hV1`>9@^hwsMLXf^PAfq!ysSQZE1bqqaA})Gm?(Z!9jBvYF*&^uyJR| z$#O~f>7c6ixTNamenr>Ilb3`nFJ5&|0uB&M6BX|svl{MWJgaTBn5Bxr=9@o`#2Di) z{&GILJJ=k{2>zjxL#?sF5n~)_c#j#@o??YH0B+j+*k)MAg1U_mJCfMOUUoPDplYF{ zX0|Ah6b+}A0{e=`H^d=Q`Li$?W)=PKv}J`MP}$P^(w}P(N(g-nTU@}OqgZfz#Up%x zoeyAR@35ya4mzWv4jJP<73sE$0lY{+sbTCeETpalz7HC=&lsy4B~DmH5f3xON;uo$ z;TBkX(f&Q2&jTzlMK!~bWY&~2y;P6R&&fev-IMZxlXm+G?E+VI)nV$fPcliz{wr1hD{Lv zg5$Dzm+g>tW3C<`obBB6(he$#J`ksaM++yOL|q@-`C@`i&ZKHI7o0jqB?1&-AVp{w@0agvWw1D| z*0OV0{p-K}t5X8`NQljTzTw+Qtl6o{Lb><}A=G}_(EX)-deFh`99saqT;c9ISQv7S z8kf!F9f@LR{<+2v>1q;<@8ZwUn>e>O00NY738|s;c~tiJnM+&@fG6_-gM^^?=BX-6 z4Hx1baCf&;UUk4FIobYk7obBdGMhnXLlMFq3b(HISI1c^%>K{r4R2&C&tq_2m z(P4lq8MZH7!a88BamRF)43n7S&WOm47((?o0~tDPmx1}6q)=c=FS(d}>Ht_ul6Kf& zdgf%;^ti}ifixd~B)rJQq*!#1iUAPHW<=}be1u05T6$YW`qpre;lLPCAe$4l<{c;l z1{C1|0NBxgECxc9d}9#%H$%y-zr)lTGRk;CKRJ3b zAGbD}4bLs#;PuLhqdY#C^%D=UG>a-W7uW~#aX(Tr^msGapXp<{b~+KXW!nu0Rj(?A zOE$3MWe1)$en*|{W^_#ltsjwrjkFJ>b9=k$F}~qsnAlrzkdV@?@Bb=mI@%%YfHs>{ zj>Oc+HW70y{meYD#X%s(Y;LcYD25+#i*|05H%Yq|W{KN?vYtk`g=2=#*?ID6Lx)zx zZEg-38kcF2|3gF{j(|sZ9}I$AL{rBiwK?11g@$4>k@%yKA{-JJg$Z@SdZE<^ki1JV z4$fsM0x!b=WAH?YFA}&f44w~(X($d4+6voL(pi~OG!f)qyy^)>#y7GTp+2cNW0KZ4 zlRtm?r2^3)kgI0p=<+|**bCrDyOQ~AE0&30uGuFunn;5g$iF(1P#bE8s03XCq0=a3 zqC+$RC$v&wFb*kI0zW7n#*?Iy4NE`U3vv+;1uouSq%_>!cD37TVYO)4!REsM0-EG+ zgbHwNg>qp+9QiFrtUfpGt)zp8?oigyS2fgi74;$GdXuFtzM7ox6<3uEdjT1&i5)e8 zrS96%QCRVjNYd+tQeGwJcf|ZI0sp!&CN^j|1+!~SwrH&uE4(uq?voGsVa_orMyQS=|%-6d63WnLhlC%<6^kkpfLj#=m5 z$Q5+yu2T(+j6Kt&C+n0d1{d_@y4bIXy>9Tds$;+jrp|Sj+GdP!U!Ujq#FIi#E|-^@ zk_>5#v^l|)fba8Wjf67=R1^Z^xMB7^zh}8ct-&F#GgjJtIK9{oD*Be7`Fc0Myq{mA znwJh(kX*s=r529nLI*p~T?(L%QZTYmMZqLuyBRRXv4`c-9qI@_;rack?MODI92`T~qT(Z{QRYr%saV`LNt2yOb z#=6Rv)){RVu1A@z#=#pEWR{iVszHDsd)IgdfFl@At0?BCK_T!cg8=}htrEOIahxO5 zN(KGMP@&4}d(W|W!@ zJc*f9=#BgBy;8_9lX`&w&rcNTYE(sf6x>H;dTd zgU!j6it)#!#rR{;B0={h7WT`OW2B7i=7G*KhX+lTeiF}9AIQuOzSHJBuA~ci*TD5H zPMPddvyR` z_pS}R2Ty387EJu&zwlk&&LF*3J}uANkIf9XpdwwzXbbiNzDu5?maku@PggI$YVb(> z4J1Wi!ZO)5&j=}69Yh?_Dkmr;eLoKdydjOP#)7|{WX9`rG6uvgUyVO@FwI_9rzKvJ zKltWm=p=pg*E6XV@2+7Us8BQ(`9`?LIFIVBVoWa1kXBQe zUYA-XRcDdn_%5zGD>I8x8{gbOQ|QuCb{cHgqC!fLHL|2U7~~14Xe~15S_4;eW&&T3 z2Sc{j;5XKy8q_V_(ae5G(Eh%Bm&rI}%{Te4?Lg8>fZfFHF|#WYCB zh;AMP0Fl3*0YoM4*%Y$N9=dKUpK^MQht204gLGxonq+*NrTsFl5$+ypQyuFcv-uugJ>q@fi^w5J4qr zEZ?j{o}}Id>-o!?U&a*=$f7(k7>#$1E#bT{*+96o#BU_;Tn`yq$jeOD1%8H{TWUcU zky+L|Y`U7sj2ZE^A#yUDrUdPgL5p=}G`;SSh^%I1(&*&>AyZTeKn*u%+CEldonb}# zewuNTtdds{U&st(s9;s&jhGmzsXOgZJhlTa6ZYgc!&waS%+&>e;?3;-DC zR{W(T004ZE5y&|*<69#zV8!;17Dm4sbg&pRGp++1o=%of`7mBDFr$X8d7}ZIkQ>ku zFd~Pj+ZOKl_W{$6z2k9VmE2g0a>q@Yamv_&h%Hba3QJXdS~X}LKE_>VC?Ba;{kr9 z?*{vgU_e#8PCA|i)7^X}NQP!KT_g$}`FwJUJw{yt@{Noi7rAg$fQIZu$$=h%fI`@x z=2Rg9qgNu7%DYr;YN5jo63Or6=9zXQ?*|RFc&Go1R@vOy87Tm|#-;#d+Zsdhyp;C5 z6(|o_YznQRI77JyhGKXNc1mKE4u&&F+>?}85owFeN0j)o#sy-kT-0SrJQ2S}d1mUj zltRjfmrixmhHss4AVu4(UL#Ov8Ta4%>jkf4zY#(A6#`e@Mp9217mjFk%qY|kSdAQNHwM*mLbj!(k%@qjBd{-FTu>}|u z{lX0F4t_bLFp=s(Fo1bT49uJ+e}yKtt~prXV}@fCi8e+>tAS$ z-2)ym*p34ga%LzTI_=6v_Yma+P#&ukydy-9j_CizsMp}93Oxj--=l?!5tG#w>^3Gk z?j&6gwPB%s2y1MR;PG3qx|9ZdTnki;Y#ZT$`@s@=Ec;Up5AS7uvKV!syfu+^8=-2i zeQc3LB14S}@JcyK_fD`63U>6->`&xB@aTz`7AhK1I9xZ;)=2F&Ue%5duwlf3p(aeZ zb$|uyHZaB*;{U$JW>od_3~G&QoBA1{b&XV}Y|?np8Sh^`Ku=ZnJ(n8Ra+8okgnzc zySDTL*KM_*m~+0^(;SRbvfqst;|L?_ixK_6^g*J4A^-6)0xn33o_gqzEI;mIVFe|{ z6-OI}J>kO6`zIX*ga1bS`d}ZSH}3t(h~HF*m#%{gr0}rhnk!l1mMmQ?t`zstkv)rf z`naAj%P5CHncjFrqQp4w=-dWmZwdxVso_&ewt036Y~ zBY_g&C+a(qZ#)mEEzJJT@~Afw#J+8Ap(%*V=+s2f+) z2n!)3zr$AIx@wcAkkWmYg}|b@8e{diVoMNeH>eBokw1nUHW}hhb_<(hQ=`maZw#zk zz$&8!_2g9LK%wt}bQv6rgm>Ol?5Qg9BY#qoE(>^E!yjvIrEIbeVrF|V{M>p3m{Yts zcq}zkX;%@pIFk0WZLM@v>y^#6K`3Aii1NdRLDn5d_z>g%?H4&(DyK)uwoupV+Ov+GcjOCXp(?I8;HS=98CF&#`MqNwqu^rr1^|f zj1IJe<7Iai><&{@J5-gZ);!vy5QH*gPzSk4tvz(&8pF+WhN`B6f&ccXQlYxervVU> zg6ql9_G@8iGWc#mx2fgpoR`-Fo1Ao6KzxA6)pbKzK zwpcR*-%89Xmxha#7JDixAB$n*s3o%;8Bq!}n)s}&v^QqVcm^9;H~^-{X3>#cvHVtp zU))Tl0l6wtOrz$bW9;4A=?^?6E@jAxHn)zGIj^idLbX9>W*J#i;uKv^gpi2J81 zP*u>J&1&ZIK3GGA%wW?}G$hK5hznedlZOb5AQ~b*90^UA^q7SRDfwD`P+2*1V`xta z96p(bl&GNM%W^p{bfgE3l-}thP$;Yau8|0zQrbVhUl;!PNmhjS%^#x4d^f%anUnD8 zCV*YQ#f{1e){xt{x73RnmWq>}o1)2X%VJY2h7tK@m9ND695$>_;#N&TI3}9$9 z<9WO{cDw5hf+aW%^vU~*r*rsFi*bVlVm&;G;#d5W5$26Pk&IPfm)G6-CmdBj|Hdk11$f6w;)LEWIJ2lXTEJ($W3%p7irV-I1&n+q>n zjb4Hgw-Zh|j;o^CZm^qQd3WR$yT>8+gt2!|ddXvig19z0bS`zG{433+TdKg<<|Z$} z74k~#TVM$k1_Jnns8a%{(9P$H^~=SE3I-}O7YJt-8rIIcwhjsM-FNiXrVkODdpdQLQ~N^V7>S#P**wO3+LZiSS=+cXO`tvd z32DU?in>N=Co|Mlp*ms$eSpGrQ<4HNGxwpO2N=$W43XQ##H>Cp@RHFbWjKKE4s-4w z2f7XfiRx0e9kvzQ@4-v6M80XNcl_!B)F;P+z7$&r6CQ0~Oc3Lbmkcw72gzgkOFER( z|4&zXzzrYq9X}~vISwfnLX40;JS+n{CB<3fA3{isL2NT)JGCemflJ@d@V!; zSFYrWoZYE~g-wXrN`xbMngVW*MK?2?j}26tk1Je;bYF-c5&TQeqE4nR-EWR37P(*! z2*6?&x}is}^eEQQ`@q$o!iM_xMED6$li=A(EFl-Yz1`kosJ@(ZUqdnC0#!KS!6mZPb1Sq;$nlX-C5kkSSwzy(~y?wyOz8-jYfr zlR@al<7T#V4|XtZF`8K36u#4+Y=GbJT^}c<41iDJW*GndKYsE6R&eO>-~U76ioxMq z29RsI;rjI@lp$N{(?cdeMD@(;R?-BN&3P!=t2{^+l_&7&!(=^T&rtnrD1NK;ZKH5@ zJUkw$d$5YF;v4RdrTuXVfI-bP>p`X~Pepum_{aJh-W6(oZ1AW=YKtimPrmyg2TC!H zP^c3L3u2FaWkIikKwVVuT&f$!9!QT4LgCXXk57+iQc26^x&lQt9!!qQ#Rvx!v^-=M zWjb)lg3*f>EncL!CS%dg2-xTM-{76Am|1euhav;Ri>Pw8#Lw~t0N(x_9s~d z!+9&D2v{?2##kYSEv7$3HMOCR{M5fglY2<+!R=Lp(#?q~Mf;x$`vi$?Gm7%osoe+i#Mm6IEXm?MB;> zvCc3I)@hzi2jO@^>~Ys}P5mK zYz}z4k&)Ub)odQPNi~?5z9HU(&!jkQkPIGMfO8@*`07sKvG!nHgr-Te>htPx<4fK* zhmz~2HpfaJoM9K;HFJSi_b%gUc@;*#coR{y3x!QYqyV33(Q?Cv{QH#`t#)(nVjAJn zl?V>a))1M0XPGB#(ufM5P%%H9Q(6|GLJ4^^z&h+T#7{ey{#Bx5@J4Qbhh9NH z4sp&B^gH#~vf1`4n0h7R2kkKTCmdjZaiTG1Xy{Fg@Obt-UQGJ=XQ1|>;lObsV{bUe zwjOSbn?#}n$xH;g0w&#)2%LcWyyN9~Gkb<-=TA_TMlFKXIm8t^E_xnMHm-Rd*ZoeQ zB7tXO59k_2nOX2cAn>%OEJ4{v0DBH`zFf`*?&J>+KFb)L!C7hIHaIE*-D77Yu^tp1 zb%Qf>Q-Wx62b|83stkp-SCMswDML4ogGLf|Kpr!+>VSUE@Twa`e47V`SUt4Q5D9j` zV=t+&5=%?xvOG`?2QR4)oLMk@ifPr(JRtrmJi!>BCr0YPiyr+m$4PN^%jsOJX8aB> zMd0~QWqX(eP6r=cevTXXts>d=d4n>A0^^YGx?PdyS8<}&^?Ju_iM?oYVxH&s%VM)3 zQUa(rZ19h?rGpZE4*@Pu!YbqVBAVs105D!J$(HF9I{^@H-BLKi5F9ulO#BO~o?F~h zrr25I7{AEW6uO*=v03c6(OmMRj7uU1KU7gu(39f@W}SI>&-> ziHR~hR@PXmm9x5AE^PWKY>1N|t@NYe3%85Ui_!gVIUO}0vA4@yMfZZd+%gYzQ@RCS zAkXN#u{(4XH2j{LfAS{hrNIz>s#<`c>Q5-=u*DC$B7+995T{X-tA;}jXVGD6jJ8CZBhJpRW}yA_T;zsl$+K; zzM-){v$TOWA8zny03+vLQ?q`v=6%D3Eu2=;AlM;+{Tn>$<>r%hz)!Jsr8x#cJwJZd zHKxSAhIG6`o}l6%*o8aRX6=3yEs|;;&{{u7 zL_2HlMfnQ#=$2j10d}-tG-K(3>n@qUI!ixYgMDkePZ|8io`a2pxv2u;p--OEgeX>v zbf|5YmvWIlU&RD!dAq2;<%v82KAPz87LTNcY7?}W;)zHgDMNc&uSr#9dnV(6-;;*d z{t6%vek{0PuGnN2fWdHR^)<4rx_&1wIC+FH25^BV2G044Ev^KZaV(8=IrEQ=s&HdS z+~CbSS1_07Mcm{&Tvlj67+!WULzoRkHNTHBz1*t;By&+L+)l=#7-^}zg~if8U2OmK z@1IQHRUu}m10FJ(hm#@_0cw;MeDb`?$JMxnlNLVYk zL?F8<#t_9SBvw1>vrT4!S?us~QQV<8E36w<_;AX2L_yGYtVuf=U$NE}X9zki-?98t zrP|2J|g2|)Fj&|`i{p=->?Tn7ATdoBjP<3M_{g#nV8 zI3w&NWS+ZI7#m327A?B9=~^Iy*fXsX)@8_25VY-B5Q0`k{Z3RiXx?wPt#M|(ZPN5u zaOmPEZ^ga2F}R%;+8TW>yA#9T$NKo5I2n$thWH4^9Wp8O)B!48@G?BerUbwX0y5Aa z$ilka&IfWuv*2{7Z~az>;uT%fA5~M50MTZG%MCn(QXNxJeN)se3ti*lp*@f~U`_CA z5P?hVivN)ukJ_^0TM>vo&>!F4qMV2ig9$@u5s2%)Emr}*@N-x`He;eKnmBMV@O~5N zMp(70hAN^Fm)ytPJNJey;JSkwxn{bequ9k_sz0#NxQI5_YWVTt0eS8qG zWc46VN&-$D@|T4F5Taw5ffVOmN+Sk_HV}3IB)KS8qyo>fA(z3ul@$(1I^cJLDZk6m zu!oBHSZviSHn`Cd()m!%-JmLwnVmp&ibxVjJTU)iIc;w&>)3I} z75jEyb}Kk*p_wcVG+Y&E^fxY+=|(x28raFAl4I5KQ@zLs^khk$`iGSTom%VH*=6=x z%i^lq4ZP@u*Wecx)-LF46xWE97vi#c=Pa3K>3XK25$ap*u>Gc`nigYTLWhgG4J{^3 z1fAW05SXCh@DQU%#lmLh%^Y5_w;g+K^yO9#m7%7%*m4~OUbVSjqHyD6`Q9Q8F|rei z51>43FtLUsjVlud)v@{@>akNRs+C!o!<@CizV5pf^kP5({bpOxNkeV0vln2qUGn5C zh0VbHSbK}pMC_KTy0awb?IX^ztp-9Zy7UJoaUR*jqkt2)u8Fp%Wh?LSKA^m+R&HWH~`; zVWjlP9-<7llcqe5HZ_>QA~SF?9`Y_%B#0Udrr6emdQoeK1)@0Px-kg~NOm`b4l5R2 z45l~tv>Bf=)R0{_AF#3xqQ7QI$|5_^u0+z&?VVy*9!K)^x>&)pO<^Q+iVgguO{V>v z5gi*hn%{&u+(M;u*GSsXVn1WuNro&7Uaki3!?@j294+FSgGaxXtc&*c6F8iXt~XXi z!Y1ancJ1Ds+@QkLbh((xS#DVjSa0c(yoxgFF!fnz4VM48Yt}YL66M!6NGP0*-SK5Q z-?UNm`eY)OqLZloF#lis*;fHR)JP~y*th^@nSFO8mZI38L^x}9#j-0Xq0A%hw4)?{ z5ylKhTsY~$(WV@Um2v2>VoHfOU#ioY2J^19j6|3I;Wf=Ggo9pPmb;ehgrXGK$_i`X zLef>VGUO#ri8`hfpD<|8vNlFGxZDJ`_a*8Wlo6miA~r3t2%~KWI^9;BIYKM>Vdh&I zN@0dFs$Bxy(3xCt02+J_BuGx@aW8UM#_+8`nr9A|~%2Iq+ zg;iL#0$kAcW$Of6HcoMKI-O9^LzA*9#3^M%pySw^WuXW;Og}k6bjSg;U#-XP z#GKA2{=%m4e{Xh(g&|g_75$%3$o1(F@P9&yLQn1U1V_`Gr$_uBt>*cJj^>^o{qWl( z{O{8bzx~5sfB5YaN?m+<#IDPK|IZW29(#Hu|NX~b2VnSYbJ>*ozW_78vKCd9ad} zW@gZ`cg+jh4p_2W>j$n~4$je0)mXbWG*;DWyH-a>b@L5By{@Bxo@7Z;3YoLNPK6Cf z&$*2>+b-$9 zq+|~}*7!vE98TEy8~&~PGe#D^+O{c1vnQU>UN(TmkwkB8341!sSBw)U*nZ6@3;2S| z_81_B*hJ3{294!Fl|)a=0TWdivL~&Ku!357q_TKC;CIC1vi=mNkCUbb0Vwjle2Sn$ zezk6=FQZ+Ge!+NjYTk;ROEU=spRbo#d67_h##yGKp)LHeNGAp^4T@3sA%Zq41ZoRX zE2gN$xRH0^#TK(XB7)q@j?^r|3zvtGtQP65aFH`KsKn(0b#lp7iR%$u&ta$w9k01zc1Pni{1%FYQy% z6+>lcQ2*rl56>^(y#9fn`THCGp)%H4f$@LbEW@Y20+IQS=U<;^{agS|?=ECYEZw)u z<1y+YVo{md1;HX3*F9)#mj`z9xJQVB@?=PSAy*r3?Xf9+S|#WL1w1}B(?iKQ;VkDL zpmZ&s|AYnl0kO+V6p+X1$hE7%Z#zh;U#~xyw*ZmmFaiLf2=j(=(iSuq)AvZ@v92L) zaJ;_n@_wciSdEs_asr}huR(-8hNERM+1#{?&IPTnAW>D_#JI;zd((ANOkfxh$)ZB^ z!oNOTc61sW^)QYnya=Tiag!$MWdbAF1jR@OuJb;8i@ObDV9;kUCr_TAFCi1TS=j5I zinxM4DLZQd2)Z0Dg8;}LVmN6g?R-4@;>$mG%>`#js}w|FhH@(CG?-OEp9ki~h%742$X%HYwrOV5vpT3wZ2^{mRCw}Tvx4kEV8 z-u1nsx0JejQM~PWa|6eeR=tYV_B05TuX1V14|~A4bTDkWNkM?YPR|A+_7-cIDOwF| z2akrY5N=WrwqUNu;r0vW=THB>hry0-7ugc*pbWIv+I}dZ+Wf&(?qQ(K0`vr89Rt*u z93A=Kr>t-lhPn3D=w}YPBm9{+hMMDMn7C_fpfVl(+xY#MyzSMtOa5J{?4j*SZj>29 z;UF;B!NE$+0Z4jWQsTVQ@l*y3BLlM3g?$E3xUkbuO$_@Su8tv;J#^A{!-TN2ihY?H zcioe_LFd72el`C1O@sZ>P!?PJ!`W*P_F(O+cCjCl+WrAZDug|de8UwKPEq`GM3?e0 zf$}q0E#V%OGo*A{n~xp_6o(@ExLZEA7;YO!1Z8gd9)m^hy9^b&?{PRsJ&Xf*8ff;u zj0w69=FmApiOuxcdOgO>ASd2Cgpq?Bw4>0s^Ia<8nxHucy47wv{}@?&xMu;UtSITU zx2=H+B|^;omMtq0l-x<)1BHjW$q^QwhX^c~Gja_Y>p}{Etg-K$}zBYa${;81k%1wTq3Bl2aX0DluIL?chv7N@`mbAG}Pf*6oJ`8 zkAi-VyGW)Ql6I7_DgZE?XYh-0S+wD;)xa3mTi<6emwlH9@Yn;{hr{kf&aY8#-8T!c zSbWn?>GExc9M6KM(u%sHs=HV7tF6z9oX%N=dqoEYZF$v|j?wm3`P zE&FSr(p;|1$b=q*Q*^P^`TA2kTS*5B7l9n*=$>Fd%D60uO>K!70W^#lDU$I5D;8b{ zr>xwL@PUeqhOEjyhleA5L{Fa0w!y7si`8LSMo9FOZwp3Vj+|T5t`@&rU$<_TWSf<=V~k(grUrw|@#MhreLEHH@NWAsEzQTKirW6Ub*C9_i(VqOpdBT^RASo`B#Nwz zsxxvBY?M|BkS?JJc{marQHSzKhkNl6Sy`K)CZQ(@m#T`h_0SRFeR$3d)xklm6Ufh< zs!C`*9^ybX7SOi8GpVTg(5fPXaFlcxFu)KgAz4?U2hByCPOQhPSL4NfJRiNR>$Z8I zwB_D$m;I{RWss)%xo_AA_N@TI_4M>dXpuD~clIKIar_Oe76}w(ieF1o<(mN9{W5%2 zHUXi(bpU8LC$-DR2y`UKzH|2TX=UX#j&vPZB|y6mtdhn!Wu^2RoP8%tIweaXPpx}R zQl@Q}98*;Y^(9Q3cOH^O_({~g-!;rS4e$-KJ_k96F_h?l=x{X*oM{-Thv;JfX%EE= zdOd=E1keU5in|f@13h7)_XXfXx$k6*25W`u^@H=D-KPTq9g9s2z(7tH{8E=iIdw9q z9WEFQ*ZGGW+CkJEyPAOx^ugqD%~5ci0u-p)_E3P{4Sq1B@c!fhD)54DIy@d_rwg`b z&(^nG8snkloh@(M$wPr$>~OyAIM5us}ET6oCBDxesvQe#qe; zq_3BkXOE|{Vk8}o2P*zsEVC=rj%}vjj`2FyL&5Q0JpckD!JouZs2maxBW%!VHB#Vv z$N=slZVY!mx3OEdlA`XnZ1`00;-Ep(|Bt+PZ<6!2@rA#N>->@IR@o`r$)4R;m5NJ| z?Ty~DW3A+5&&8*@`ZhBi_04_JNQv^@&kq1W0=zv>_lz9Zo<9<6o+d#MH-aDta<+Np zw+jAo=${}VU1u3?d+`OhWQpqJ&o_p&0Sta}*A^l*c)MRseGA4BslvOoE2an4iAkS|S-G62=Wmb3K>}+5+e?F-F+|Yte z4>o1F_S>c+&i=uPRvUMdRvxQM&l5*)Ghf?^(=)skhi!Z*W=-aL^ScEFy`2JSLo z`eSC6I_jP7fdyOhHL9QBdf6N7t-{@0)^ig{uH-u?jRv88c}9*ueC%)O?HiSsRsCoI zbJII&4czR#(&$W8WpxnLcX-%HlZkMT+^g4q%*3d016)MH3g27p~G zef-jDSTx7!S-OCmkT}oh%jIIJ5%Me0PzbDRS0f?|(AC5+>(^Km!o&*`ajhOYI`AU; zux0O63GjicT>`vz#j4=;AUjcF_Gp%(4*Jn-MIHRL)&k)^tEB6lmJL+BbafQ$GIIJIbtu4PsU=^8qn zcKaRl_1)Ea^SuY~ARMmLoruEK+M`ssT7MLUOEk#ZD<&JSzAsXx(BW-EX|xzdr%Yrz zyf>~{1I!u|_HIN8~*pm{Rt|ym3{&osP<9u;a1_Uh=6aAA|MA;@z`LW2msw!NR$jE!J7P z&>z+n*Nt-PZl>q8R;+0)My^xu=4>sf1qtg3(p>2Np4W((CD>(>W_vzF*u*7x^5n78Y52Ig5^w(i zIW^f7eyS`F-H;hOm6$S+Qj?)9*)P>~^5>ILli^I_|5K5=ed1n0>SvO;l415U!;0*B z`>Bp(9(5LIUlbFsECQzaHz>fqo$IlE>)M6sFue6Jjpd)#d8}$r*{qK=OusHsO}lTf z=oD0S(WfU*uyZ-gu#47uj4j7Sfv=8#SS=PyjcE-xe}OU}c#bM8S|i#YP|h?y2{znb z*6*=Bp6*vYzXcCw@pZX$k^%>XGDPO`Ow$*P4;{lS_lG6kFhF#VLoUIo>7&boU%DC# z;koN^w998YJ$wx|!pvLLKP=a4)UQ15;ovJ@2ZXW!FtnSuM}BZpwrvYmDmlDqI!#tZ>%JoU3ZPWf4%FjqbqtXd1s z7(>6sn<;ii&(`N7^x7b+XNq(43nbkpDc1H62_XTD&7$N`RY33DZvd{&2uFvh!;uP~ zJ=c3u-SH@IVs#A#mfMA<$cgnGq#2fxl3txnMWhKj@|BJ0I(&+o{dUTc?OY?KPpyhX z>(UB%h_nYOi7=eK9|B>dE$qV;Tt~r!*Z~969s8^JX6^`C$NqVBIO(F?Hltyz)$#e( z3>J_a>;~CuYSieRsK!ikSLJ!>`bwjVM^AHpjPTu2lit-3mcD{f9R#o&1iLpE32 zyet15E{w3WsE}mHlVhF*oB(z>pTX7|vSXqTCEm00OFCC?#^8i>X0yQIaxq-Ez%D(s~hQsw5 ziX|5OVgM_w%Qpc;T8z1aAd-l|;`@8jo!<7;PmWof9_J!-?y(v#C*isx&n?3&UZ3D$ zny=6LW{rcKkalQE$P9ScyR&ZSf&1OAZRf37(+*5+nQPzb>-PJyzG3UBSl_B|i+x)} zYezp1>wCf{{uwj_KEEI*NfpVBUls zLo_@^>=kYT$7548t2YEcw=2#;uxins@d5`VMl{gK`mK4tREJUM@b$-ghZH{IaMrNO*}RAcF8FakRHPbgkqOz zSGfMhsg}+5X z8vMKX^1GQ7uR4wiQN_$)4V#u(G$E5h>`EhgR#m9(-YA#Ri&<>8Tn#Nn%g!wu1CIh3 z>9EqdUxf+*X!X6zvf*JDAEA#dRyB|GUEvxk-p+GeKP(q#smT!52%PzYJCrei#=C7# zz+44O9yaP+vP|#8W)48D+%(9zKdTN$tdUK#%oZ!aTE0CUrak23E_LRc;!zp|j90ef zIJ}P2c);^G6GhRfswAitfze+~XysoXaF%CMO^7=uIxCCIXdw-NT@@ReYI-L1Jzn`( zmR9$Om&=yFe|L%|H!@L{r5HJI<%u3GD@WYBccs zo9P;-S{a72*7W?+TRaqf!(wNwd9W2*6cnOs01%GD@`&goB$lSa&9jBq%}h*w`qaP* zm2|%2>WV?1#a3~xJsPK2;Xw_^Hn0(%x1dsXHQiONL#1C6)oR+JL}Rz{ReHrVLofXd zj9jQsL`%W+J;v!;!ob5koSzRc8fr)lw^-*I#8|-KSZmp8w)>CsG9F(0Qzt(gl$l!7 zMLu!UtM*g z5%$gWEuH&)`>GCL!=|ItzgaER3&$SkVdV2vDY$z*eK(GDuxc?@))V?pVN#D5z|q4Y zb-d`o7bPFe8`_S;5)G?Do!O)7eGBFM@%2iJsb;W;8Gl^Em--Hrug`rvPmbH^{&=^m zNnk@OkLmtghW5yH=!BXwbQV}goqiq1D1TO#;W8-tyw(R4N+Wc0B)fOjN=|N2b1fFA zu$$I7tQ&~fl>WiqR?nQo)(Fgt>maS8Cy{Y8wl^zo#ZX8yju!`7Q6s3+O+boSl}}*Q zBY4tDo_<0$M8r=zLklN3hmVnaW-ppy=sn^JHP3xi5nyTr@>B9)ho+$wUOO?fb{GQ2 zi|1c`gGdeGt!RI6lR#u^~gIsvPJ?w^CzdR%fER_p)sIumPRIB+r+SDl^($Fo_y zY?D#Jl7pCk{4-ic2WUV}CC~OJSex8H2xnw#C&H4vVai0;^$PcdLQiQ48n_ejiucBe z3lEzIi2k>lL>Wx&IV^lw7e50Lb@ljJGsH??@wvn1! z0S|m)LW(*pe@b+f-fxzZGaq{_7ZV=P@6r%^yz@BVz=0x?_A5jB5gb8s+r(@`;=ni` zETa9m%&=Du9CRy>6$0TVJfKWt#;+d!@-~Kvy93OqVK@sRaB&H|c4RCC@qSNt;2=~OfhpPl(Y>-pUjSF}zgIrN93!v;DxT=v;DKD z4|%&Iw-Z4KqnKqc47l1MZwZI0YqW;9ci3%$~p+f9pjmcW!iNg{` zdy690J6zPq>u*!M9eY_H-iO!7`I69Jj(mfh$O<0c?_Q%0>|f1uh;f0zTZrs2PBO1R zW&oo=ZYV9%$o2@3HH>;k*PWf}?dhy7eaT>?Yd499IsoJ>o}DQCqx@(9l1ZYS2H|Q? za_~K-yEsV;;9*Tphn*fiD*WDz$zyPnW_#-m<8^Z}ID!sn&Cd6Y2uo#iJAw zxPjsK>vP(Y^kyzh^-_t9gXzXfq{AJT-4}pZkcfK`ph6$gTBO2Sa;}_@U?xdWVFnHl zKy_lFK13Dv2^&h}0|L7WHwY4GTxJoffVvvs55)tUs$dd{3u>LWEA>|s;~a58nX3%P zdAlxzsES?4MoXyOl5$UwaSe8e5~|-4a`AwY>4d)!>Db8S4hw}LOqOq<9J*SlNSN-z z=GzIXcPz8AB!DbffRl;>=>lxx3W>n*wKTpPsQ-)mN%;|(JNDEJ{izwuD<0e<8Hst8 z=E^MVgCa}mEopYrpS=c(9=Lcu2FE-$JH#|B`4mt&8J+wQ1rjoWEE{9w%Iqo=p+E=@ zy#Ff5>F6_(2UMhUa|0>bQz2CuHxFV8=~Sk2x13nuV6a9eIVxuvNOH3|P27dT5D!HL z*#;Xal*hrCm=TJ`(Wq8==vP~i-$1#gt2bs?x8=-42AJ_M13a3AAtfk@q?tYGlb^lnW(RNWkVE`&J((iFLNB9E z4!e7`u)z|-TvF{zbc%*k5J5K^MpOh4)qOo#p^VgtZhT9E<`s*-p)wt#FYzhMpo5_pamNUXWPP_7Sp>~;wH26pu{yIqLiW%zw!ZUw!}qf zoP-$0LpX$XS+S#&JbdN0like?bf5(tx?z) zk|R??lp_FZYhXr)1|;4WSmQX3ststPb;EL~0gLO(Jkl)7h`^Q9KP;E@Gu0XSq(_tWH9}*Z69WR$%qVM{D>n#!zLnwkR(Ow#=barvr(DY0L197BP|Pky)6zxGEUvd&V+SCRhey>IsHAtI!Z|O(JefI zp5dBmV3DqL$CJ3NmWaH8tSqV&g}?;jjwjnbt&S6f4G{t7S?K`yx;>lAJYC>)KB<5;`&XP1#rjXPNQGh%840QR5x|y^s14@BK2Y$ z6MA(QcvY{u$B+PC>N2FBm-r0ai=BpWmLcY%yUdj z$czAW<9i63l%%6Js8E@t8ML=WVEvTs-&_!p;NPBC3&7`^{JFV@S*3cl&Y8zmorCW0 zYZilUrw37v#tdS6+*j;wZ5fW8(o{C9ZP?{==FcjYUrf;6vjlso^19776Ie;GZ9V>O|I1E3*;$Yp5XvIhR9FfhC4arHRU}RdCQF^H_)Cu;eyOMSaaWI9O$Judf~EKc!FuBohv&w(kir$t51u3RH^t5WUV68W z4ATV4-UwDs=XVM%%uKPN@(wfz%_ug(lqs!G`~YLeO4xKFi#yB5*j1!Qt!5Q^9ZNp` zS1@)L&}iV$uZ@E}rI{i8vh|Jd%hc}{8ZMU0C@s z0A6fVSRw|neE1$zB!&rTqs(bls9U@-$X&3f9RPRn#+GMA8`Q8MncEtLNuXvF{Ipj( zq)}q~NCQQnaCQH*v#?+wuL2}%w1spfR>kBmMn?*`(QY)_{EJ~UBLCOHVR=#8rVCU8 zrR!)VBEUjk`96}vJPWXRjj#NQu$`vt49Z!@e}jEd*6G*e$&DukMKlArU^nS7h0ah$DktmZ#jEy8iJA22bO#|= zJj{BYw~|s0@Akt8YWFcPS{^f(uD4mt&wmy(B4Y-C^1k^~*g)V!P*Ee@B|52VVl5P`JxK8l@fm9u;Dd<7k0F5VyCuF9`#di70<^@~MYl zgjJXcpzD%kzGefUU^#+P2qK@#4QMj#m|1bu=K$4+bkSTF%h_4$jVZA-do4}Lj)}x~ zsyTy5_H=Qa&`pWS1_uM4R<6T&gG3w}$GSHK3)z8lh9PW9EUa-}9>~TGB`!ku6UaWO z2Vr+dIqduCVT(mYoARz@H3?sXakYKS@r1N>ynDTZ4f4Ul;7!Q6A1Q-{hPr;5WuX`p zWZFe>^NX`^h#%5Y||r zocG2j`LPImD@yDt_yi4QWHi8EB#YuKu=&pRM@+E!YHYCi8jbK5r4=^Ky#26DWSraX z4K26wEAVcZJ_eD~lRD-U%*NeMrpI^Nxf6WHg^F^bPBNHqmuaBNc@P^v&KkGU5pzN< z!aXj8sY{`ZVgCUADofS@@@=lfYY$ILOtZJ{9QJFOpA=MyyRRYgT!C)WzvIQb!8=Ny zcMQ;3_IP)Rzh`+t{Wu+%77bKLzzSj?n&+dPZu@ZSF5^BK8?Il*-iRw+rkZ&?QgTtw z`*4>cY2+MlMHxbYw{yMRgckJ8f;nmWiCGs+vf(*Sh8)Kd(gi9_8=ZzHS;Bo3-;%dhJ=YSX$c8q&DSXX- z>zebK0SADK=;cnbgyCY?<;g*Si;H6t5Vtm_&t_>%AI-{`KE{QyTo*$lOC-UOQb^pf zNWBRTo!$PNx22}(@KKi2T3QMuC5SYF(6z8G^yMd`T=}jHL+Z(6zp89$x8g*2g)%x=Z050Zlt{(kSs8~QnQHDDq)ihpck9-Yob*NBU zt{dS9FYZWU#}qUxv`&7aQ;y0?shOUKLo8s;FxhIQJ;p=9=ZU1h73=h|{D+>5eSd?e zElxZvEv0LH*8zlV4Q_;9=z`bw&KtdE!7viwFp{_>2`DLFSfAAyz>fh?X{gFW(0@V& zglBYd{};09{~P(qPd*Cs`)GH#^&dD~=YG$=z*|f|FJ|fAc)Wg!8n#b9`fq6R-#-2b zPDdz<^W-DU^W%@?C^h^MVv^fK0>JB8_?g5Z{ByCKuQqr?ga7>dKMym#pt~H4EpX>H z7E<_skSvfJCdAfX9;4XtDyW$|4}?gdupc5u}x$^C@tf42bfI=qgf10kelXZv{;Tf)e z5YG4D2vQZ9-~bQ}^Jxr6at9|>KlSfR3(bhwahwzr%2BLk0t^Fh9s7^&S(0v$5MyH8 zT_7gKz=RFG*jn-w(TY+SYB>k8`1dJMiLhsQU?!cIJ9C$+7h$k-Ty~3thj7AC4Stp5 zwZmbPR)oJx?{>)lqOlui0NtT$i3KG`DmJQ2EBNiF;{rStU>dUZd%SY;;}0t)`B_Dm z3a!Hn3MRS@r6fGsE#|dn7WB&B(2+$+fR5zJPeMVr!o_^lVQ?UltZa=_4X_UR5A{P0 zf^OFhz>1+9V?|sn$9y-z9P`ygbIjKm&bjWKLuS!G<|t{^Kll)smIoR;FClf92>Oma z2MHR2y!X5B(d+(^Egw;Ge0d0t5SpACJ%<>KDR9TbZl?2UEbW$#os<4@5*>%2b@X2X zX)nJK1~x-8b`9-PY_M)64U~h4Uq-8U*u*&~jVyu^OmE`NG}01GnON%38O}54`cg%r zLOt=IL@TBu5S=QS2oru2^Wl3=L{2Gsq0%{KTU}3qD5vn@lOiUBdXPuKJVn+sd@NIu zBypLG$fCyklZwPLG^#6a>hbas2pzf5c9?#v_^OnYfoxXlSSFO%J^-N!3R(0^Ku|#% zvQ5*CRZa9FUylzk6IW4v<}<=2UZMZhuYN@p4`uVUdJDT&P>SKpQjiURTs#Fx6a58% z@fQJCLMl=Sim`GRTEm`A7g|W*tGr}sD3B7OG&|X50us6|Fc@B61RO>G98vtfInT`r zNKmgaA+`doR&1zf*a+m5?TXq_jTlVP(+3}PJ?oicray?~^QH>GLQWJBIZa6p0C^YP@U0pBj?=jeF! zSeT<)x8x%!B->_tEcogB{qDFrA>-(iuwsuvzp+k?#A4LyaRIC`YsyG)#eobjUC99T z9V=v?;@ApFsJcNS$6yRSTMOLC?u}({Y;V69UMCT<%sgDO>g#KbhM3*JvP&+CUv)=P zWc*q@5@2_QZcOgtg?pmbDfkZC-S(5^W`BBTGKOnor(z*nch2G?WT9r@57?H6=AQKDb3WfWrxqf9a)z1NJ?elhKm(fN=Y-35(-~6b0bq@kvB~XvH=F8xvo08*$LVtMW_)&+ zOOW%>kH{oZgMSThjL9G-A!bk=k~qv&25(PsbxAwh#DuiJjS?t0M*xuhh2^Roe0CA9 zfa+v@$ar`p0R_MBS8FAWIys)cX%5tMPL!Zqw#rIEg${FZ(msD3WZaqs z0J=GE=ck}@dDKPb^L8p1G&~U+^SMQ(AWK(_5FU?V9i-W1ECzUY%{UNXB>WQCt(JKm z0Vp#UtJ^KDDwK_SK-oULu*waXh2=omZL<->HRSEbx!zH!M=kX$q}36R`r!chFk#DV z`D&3xD^kemo9SxJdFTP03aF@KrH9yilV{X!NmT2rX~06KVl6>sXs`ikyeJ+SuDa2s za#E6=Uvw%xMR7+pC*_biLe>`8n8f5aqqFioKCYga96Ep}F~%3c1bwX=NKk@C&TUJA z64tD?uuymMobag6#1m8z*ROT^7BFDLkO_kVAc?t~;@W0{K(>M+pusfaxjFI&d;@6B z`LLa!8c*d%JTV_S>+h4*&1Abn**&267R&oXWyL<^Cib(4|rgSYieW$i^EP%T>+9sE~QZ- zC+=n;#r|&mmFdM+i?LeOFd%{~=^{>m?lZawfxLws z|CRP;&=s`0j%u~N+|c_I7AkARAaIEgL;{`>B+z_C8xmtLg`>+sp!X5CTCpYpx{AIe zIni|l`br8^r zWBB5e*f0g-W>v)sM(b&K?&xLl+R@;M&4~c)S9HbekMb&zXnk7Ht|X5_y_P^dbibwy zhiBzJ^+7cF10?u4Y7W!eYDrEWLvcZhZ%~BgIY;K6>t^IJC`@3#mAA%%&gy~PgGlj$ z3g;mQ?1Pcx6<;U)z~E^?!u_MwTs_)H;-w(}=i*ufncB1lUufJRBd=Pi01tzjQ=zrZ zzQFVW+3&fM)}spZe@c0uN7ZW+Odq{uHZ2d`XLy!4?A@b5CP6&*vIXw?4s`6p_D!XB zJijmkM>hOA32*###=$JdK}M`Hguu6W7kj6MYP3ng_<0BfpBm#6IYKhT(7H!Q6EC^! zuhQhLmzw85jhl@eI|GJhs=P?CT;9e~qQ zl1BfV?5E?PXV+{fx)85oB`_Z?wb;{P@BJkr^IuXujnad7xBy|}_Ow;va10mngpI27 zV323-_UCB4L9KeqWOE#T0^z&8acVCaO!R?7DmbjM#$0z9!vsYI-N2VDC4S(x*xj8^ zi{1U!DZGyJ?f-oBAK(1(%gLYqFnRgatBL;k$EV+ZWt0RYjbZkowdlCo;9-9Eid{IF=XsD7ecT4g5cwqjaW&P8W8VpAr4Uqg#u`TQnz-H_ zbn6l(cf(W;f6U?^4qK$ABT3N{h4M^SGvw_tbqY#S7h9?Uf-u|zYxO0A%%ERkDca@GB<{d&d!iE*H#b2! z`96{FpncQ<;)AllAh9YHHQ_VgEf!Ao7HhOTdlJPB$aBYIz?w+w7D1{2AN25B5Hhtu!5t@V~u_{UEi?idYL6#Qgt4XjUbj#7ubSw)MBN{KlNXm zwv77H_Q45PM^*1ui>1@mXrxGeTk?O0TvR1@=)eMu#Zl!K%&Iy-t8J8uiaeU|cOi}R zn_EM4WHPg6So`lm8_hu3B0Gv%8;zNaaDI@+9w(-V^>iBTAvMt~X%{{t4C{?mMahzP z&9k2`@%I2NcV6X<5F%rZEfjsrtfUc(Jp zQwM+*qHpQwt{2~0mO(0$q-$hjP?-GN44co|G}sDJir0;^{+N5!hT;2Zcf`Y%lA%#h zg~5TG2qDHy+(6x-6_LB*A&rbF+vPof3<3rOc5A%oi)P`AW$I@4Ce!iiEb=bntOA1T(f|?L?G_-q(V%7pFDn@6nid1w5A{T%`wuYK zo5eq~{%NTi*&pDlba8N-PSgIR&Dhw3(p1tz50PvL1}8a+`h@^ zNX6QShV|xe5uc-XVu(YELQt}1$2Tj)eDkuVXl*4N1kwga?l za4NTT_ZxMoxu=;IX0+nT11C|7ij5Z_nPI&KMzSV>XO{w*RSw?jFn*@TarbulXcNJz z>OGsY@`R~AZ)t4z2@aM$co;c+#jsR{cB52w?UgR91~@($5q-XIhv@2ntGhxB*bUra zlst5H0dz-!a)};E?Q+ou))g$=XuK-=MRRN~zm|^ZRWXkh^Z;nkXu^kwY{3)8l6!;g zf!cFE_A##mAh3W!(pGdA;R0{4nxYII&IdKhrQQjaJZ~0b7NK~H6;OOvH;1FQ z(qnOi;M*|S6$m}`Nw0??1^F*KO{7(SfR-bFdppi!KHcM*Ds6`_37xg}lW=>hr_3HR zN6824go57kF-I6bL=y0`P@WF@bQ?XQcsRSlf^Mo1uF3AE^0szb|CK7#6f|wT!7V9y zjp>m%%qU!hiUIJl@CNhbX17aRP7Wrv@9Q&;z)sUp(=fRUibn+)c~enjE&>)Z38(wT z(w%-fB85if8LU!|YSDRqswfrk;X5&%gYm(R}ZK(#v%m9~HxbQ=fIa!-W* zu7kJusaChZ=QJoGB5fE4jw@vt?8H(5o>I1ko=2umTNWvtE*>fdvkAKc z3Sdw|!^%J@qYuJW-c6F*PU*V!D0)D>@PbikBw;avX2V8863ElIe1HZ~7~ddM*Gn)^ zH+X~ZqePmt-SakA$g5dFpqbYfsEe0JOd`{t1_k3#POL7U2?iWzZ@8?AtP^5p^RZY= zh#!`rZedAN;etxo#$ahg4F=tpFhtYH?Hbbe-3B*$bRE1@h?>*|)ZG@$lMR@b2g;_Z zjq+)d7Zo=p(ad?)x(Ucor|D~?_TTKV-^(SYHInTDTH74~#2RVJsMvE$)xiXF%L_zJ ztkI<{2+hMASmgO4-#7)+GM0j?HR*K*f|YJ(gSF1YO<66&^k@ zik8h3(aK>SFb4w@$te_{p z>ET^*Q-Mrzq)u&#uR(Jr&`$+NDJT_+GrVDnfLlvE^Ab38wfEU%$CS~)L(D&j0KsC?7Juf;qR3J4&i>vr5$xO7dj-!`iS?h)q{ zG5h-1I1-(Qq7v>I!E1BqgQ4iu zXRflE`JU6m?hqp!PY@IW{3(ay_=2M4t#m%0eRPGR5eb3iBiU zjhvQ9I71;mcd?H?`S1aK$*=p-x8joD6n7}xm4}uxlPXF9fS*P|-uxqk@Xb#vg!czT zE%O+ky5co0K2cnc1R?|^ybOA9@EJ$QVh#}knF*H>tT>!W4{|17(r&~wM?LR?#E)uL z^Eojvb^&Ue2TJ+LRig{iCF{vPX3OQL2L?F9@79g-+#OdZG(+e)C?63=XrHdIPfCMIR ztcwsYf7y&;5N#9$xe9g3lrj-3IED}XSyKQM*I!xvQA#`(<@&r6fe>v14*$lr)?St%?ihYuY~$O2BP zY1kBFY>d4HUd)XQeztBEoysXiFguuF@1O)Xt4kn9Za^~5h0NsmHU1J2V;GNe+6hcM5+y_M zG%83eIY`(iAu^C~<--OM(^63ich1e5_44h6>SU3u2XWwUXIuXQLF)5#4cYN$tKqYk zh(tnn>B2J>bH(0l5^iOBdxeu-1XGzLejkcXD4${#AdQ8Z?q=&7NeSW?JO0?|h!CHG zvpp_Shnq7BKE!heXYCn&MQ3GPtLZ>=j`D1TeT-BW9#D@9DscvZoxuGa zj>i=gY0B;-dnJz^RDeZ`BApZ*vXmvlnU_8?H-)t4cs{aAH=_55P-=i?QHV4kDZau* z&85|gDNV2*n+e0Q0l`AX#!G{iK|>TH%flR9JPAUIS&b2NB}|o;FIof5d>-Rec3^VE z!9WnNeYL3p2~WIYt^|(p9tBKinD1&RhP{HYkX;CpE%2;xcWLL*1m5y8h+HuMl5AC! ziFYV$Uj7p2c0WZ77SM6XI% zLco7084Brw`OS~Vz=NbaJKP}tBE4%nJ?OE_er7>toVRlbm;5F^WN`fe?g!@ zva7HcFlIC9`Q~`LT4YMW-?H?~=(e#@T7N#%(~|@W|ME5j-ss!A(`KD{SZh4uw!K~9 zrGp@E0wO&yYDJoc`{VBAl6?2);MNrB$jyq0kXiKQHiU_`X9|=+{3bh@w6Z0L_k4>Q zY!RR=7V*zIlIg^-2irV|7(Le#g98)5>SujS_=ho%A^Nm`B>PT}R)KPu%FF5fmq;!^ z?gl-28y8(E<+rOJE^tysF^9BdJ97UkQ-Z5V%LBvrYEx@&3 z4QNTSDS(geNf-voDPpa@K{|3&6Ecefq6Jr=!l{!6k+52H@F+98>14^S%?T^Hf`Cge z(JTh@jrlwZd&ybAtD;CE73&r0$OR$-LlZum>EShY7V(y8Y~Elt(BusCa?V6DdJfv# z5|KF`<-Gmi<7}rm%3>kRXWyPqHj_k}BWhR1+niAcJ92=P;2zf%*dHwj?Pfm)T8+#J zIoJX7%9Pyf0dHE^amV9yzXGpO1Ro+If~Znre5TM!iggb(d$T%FASWaC`LN2R;B>c{ z>V>6bRB*x~A&T^gCXjb#L&o8lc+6IN@HrX0NDkU=V|`d*U7YYKbV{8dVlC+@M7q)e zZ^NkTdtDsyILY~l3+Ghdv(=0!`$xv`Yu;bMG3hxj>mBx^_E?eh{`5{h1yfUbOSn3U zlk^M+S_K|+tgv|$n_%;qy@|vzLhOWjz0i-ekz!t_=ZkZSweruV(p$`aTGB~ zvuy#ZF}(pZ&di7)wEt$K8P-8UGsS$MH3}niZ4gi(x}hn&UTF!9p@A7^mZ)e>3M=JC zNRnc8HHq@TP=rPtsUmd5hA zj)M_a9@}}$oLX!lGO2D{1T&jj(1?pbV9p&nxr-cmYkL%x{e#*UYv$OYkO}^4L~Pb!|+>L3P)2SaCgtPD$m|BF!G;jlbXy3m)F~qIbk)csvzEui5h(f5yEg zGlF^pcbw4bR{Dqxr_s{|Wl>dLM#GPxVgWzP6@F$ykgEG8FPDoIa(Yj?$7wWs_3E2v zbe*r&ObRme#*-F9!%3^5(QZr`rx^Ifb?p--f};~XxSE^~oRJsA1r&uLI!set4B6@moueSg@%!Ct z6j>G_V7!u1#l3bkKq@X;l+bVgx>1-`8P{sM=ZYDF7`VzV`AlW)>cMHr9?F= z^IRPR*%-41G(6C}o~-b6*fIu#nL`A*h2ddIwb33+{7?@VPs3sUs6M0@oD=<6*<#fq zZ$jun3yn#4NeX+-N|GrEQ<4*Kl74_k@)>~whS?-9fLi(*$3X2Att$rO3X7sOZ7I<; z0@>2AQLuJMT0+$U^|PV~;5+h`*I0e<4j3-psfkFO%7XP6Eq|02Fo)jMqwBPgP#n~%o^y2EWf}OmG2xGbF;nG1O@GK${_M& z)s=vLvzs*}VGWV9Tt&;s2kympkgfPA3HaCLP9Fz#6qVo1OLl}lXo3nUSSX{s;)|HS z_{9T%OTK^|n?$fIppUPtq!G#hTx)AooC;eL$<~q@o+EhwdoIRvNfqJeNSUgHxE!;Rq4eN^og{#j%SFawhb{pi{$)TcOZ^0n z%cWiwP(}%SMIR{O1_Jikk@tSU27AyA!5^yE;~ZPn6v$|mVMEK{RO9}DG{->3pj#y?1_6A(B%w>$uR3xC6s=5}xl~Mmu{rIASPSyWVhW;@ zH3+T`{Y6~c%~z8dR)_EkG%hQ0{*7OGk9gOdn5NNAf|I4`;0v8*ypbn;WzURnFt?}) zi){t2?X$}TD1mhJ6X=Qi7yL_rAQRvYroR`d#Q^Fs7+HExI%_@iemG zD_#aoqm7J0gRu^vq-}DIw~JV9u|fp5np-EH$eWP%OM1KA@VYM4*q|hAHuXWqF<(O` z)uS}cvQF$C6gI?zY%FH1BY~PEEO;1GSN8N(qwIx~O1SeY#7nx9e7%}SEst7M)mK{( zSv+)h_sMqX{CPh5M>I#vwy^~tO16z^)>)fY*>`{+VSEZU1`IM%)o^G}o78frd3{5WJPktHt5_=e zqeBVbm&&+E$I)Z1mU!@x61^$!eR#DAWnE6?pnm9IU2Mq__!} z{u>eu*9B+P^TTS7)KS~bHKAw-FJHC=2v<--dtqIgV2{Ajl186swrpEE7e;*n80XMS zjhtnm;$j^u9T?Q5D^hD1?Acj2IU0W6ZF47@v|$Zzu^M;4544bky;a1Q+7~W}j?X{h zVnQ})`h411XrLZ_%y+Z&+51%%a%BUnGsqr9N%ShVAl{*L;4j?5(tJR0?;Xq@A$e239D7I*jeTU~R~3CzuEr+_2>IMn!0XK{8Q&Lm2i_$+KhaBSRkK zRp&^L#1=M{q~lpMv1h^dtT}Tw0#JT`o#n+nBSRO|g0e z?HWb6e2-3Qfqrek^u1(Lzgd3LUppgOfWVcH#XY*XKMv7i^7m+(Kn~I>nZ#Ie zqFo8yslmN?TqaeQLfvdnXR@cXuPGx1^w_mRB4JJRgI=DUIdUTQzi%&}hsp!9aw-7F!z_8zRkJ*;dJAay!5A=IW~va%H_niMIT zI#RS%n&_(D)#?_2@HAj|HDj-8f=M^)8~oaq+nz9BX|~!Q2DKsWtOZ7*hyYnXrmFNf z;R;-U!wABilOvot3jCNG#KB;4r^O5}vEjKeTrE#wskq5Yd=Ga)qrL+J-bkXh?XE)iENwjEB)FT2#cz}T7Oz^bah==2sAP!giPszaMgqL3~Mur@HHe}YhB8J=}wKw}F;d4^y><1Z} zmEHbgC}spgRkuwe)35K?Esng_Br4VyU2+pLGD791yhk?FB7 z9iB|WYgJ-hvPe{W-XOa~;W$Q;%QAdoffvUlS&C8mic%p>4wX#+ClRO;`y)NE5z^Gy z0cXa>q2qM9CoYu-+%D{l_-Zz(L}xcT%_0ttd0#NKY77^!;Mr7Y#`#|Kd}KZGa!1q} z43!G>9A|jYaK&*4jY;VQP9Wlw@)-Y2lxQN06(an`GDZW+KR}_u(Yj&QGy}qO47e0| zRRwRNjizA*sZfH$vDp0wxfn-?5PxOr5)}yPD58VG*(Rc6z{aOBFTxZyl<*AdlA+p- z{yqfRW+?a}KuthbrZYlt`-I&c@RHsZH4`pg&GxS+aX~Zmh5X_dUeb!Ml|}ZZ2?f7Y zpx|o`C2^Eu$U@#A(S7xZ9pTdvWlcE{K#7kac8w!1LDacauQd{mDe9IKtd9;TSBb=t z5u~z3S52%4N2rCVn&e0i>ITE1A~CMhKF}#!WXPa>DBl6fi#0?&R^?gJi7w~zWi8Gg z-XF+c+ZfWFe#fxD3M)NUY5K@}Zp>fLF2FLY7Sex?|V=%IkV;84{Eur|oqwEq$dw;h= z(VMWk;_uKqeTeY@xBQ}Z>wGoEr4kAajba(-5DlGmg)fq*T$s`MhyqtJWR1V+#FsB} zgefG_;B<~EE6y)Qcf7=Bk_L3n+ZFWR5EvI3&xfg$HgP27xm~{jy&B0#AV%PN;#f(> z#Mu;O-zvLI9+bm2lFndNVLzYZhyZ5~n>{w=2zOVr42^~1sf1p1UJAQ$v$_SjO`OYa z-17DmNAjun$;1;pIRO?#d5N_ER$Hjb3d^)E6S@dXFM}qigNhX)zp;da@t4%CD&s4hARGABG$UQCwCQ}0DP!(ouDH-^FoZ=FwgptoqZYZk!TA= zTv$(g_K6ib(z^tiFPPLew4w7iYm5xZ>3#@Zd8bQ20ZjA-I)W3sWf}(o$$Q}w8l5Op z9BenCgl_bvAyo|xfqR@40_=u-c0AK^{TY6xPv~Kul9IQV6u9nN!kJ)_$M`$ zYrSR=MTY?#50hmr>1KX3MaJI8sbGq7%wpi-8`Y+KD;HImQ}rQ`fK>A|+Cw2<(_VH+ zL>d~8Jc|8!hU_m>B3>tvNYfq}8aO%PiMbQ`RfSiw+$!y8pyOG}Mhoq&6GQ^hq~q8j zaIoGKzy-(iV+<3lAupHeC|kW1xrDnGYt+XcT#q=}HW9_e6mhMjqtGzS1eYGdl+~M6`mmm?N zBn72YRj3Ro7>Jr=P!v_D7VO9Bja>-Q2^Vj(FVm^KhaBKoLND-wCH!$DP#dAmk%d%y zijixEo;lAQ;1xX=5QHcPIBxb-9$K=ec|L`b<4(~(hQbi}K_Uwy^4ltwLQ>}~@I>_3 z(aE-@3vPx%dQ1uiAaoGZ9IXD?-efSS|HD4$TW{kuH&}ap0pjFc#ze?DgX2^M;OB^0ENzIF)zQ!u;_C z$f_fe3@&bZ$u8eo;RTx%9QohwaJBA^Z_rlgxPLuAe)f6Y!)PoHH20c|QCTZWqR~Xt zg2STd*9k{5i(JDu=^$D6OgQ|6#RWo7+{|+HD3LItryPS&zskV`U*#GNH zv9P~*hQKJAbfFUJ|*%u2mA3HCdP5AEXNN?F2K)qPpun1xfdmbJw)`rYC~ zXD)OxR~f%y7&AQH2U8*X_~tuEsiVrFU#825|DiF7GuL*C8;m2g&T^;#I$v<=8+ zlnF5SK@f&h}*M==(5bvmFcKz6pQsta<_08-=^ zF16}{{%&pAasPVdSB9WjbU2#`h-P>tBq7lNL6<>rqchzHxeiz|HP!yc(@^~<$xCA= zJn=d1DU=M(wDJ54PlCYprtCU=^4a@O-+z{9RdOj^Ubwx1| z1vM@m->qv@Ew9r+`||;}nC!WNx?j|$GnRG)lY%E!^SAIq?%_;tQj#0RoD)%S%wue- zZVmmCh#fsq;;Xnf{%tjU?uCHOI1TruGhWkk85|MsUEMAZkalEKR)R=Cx-;zE6c1{9 z*$)&%zoGCOPq^Y0>3C7?3fZt%%`%6GI(Ot^C_K(MneC9`kQ7e`@Culi&&VPbU1$la z{`S+4Kl=P%{^fVUdLY*Wv56!$ENkB(ej48$*|<>=O3&}fT2|THrhA*jV!n~D?E|J-~Q=~@9&VhN2xad z{QjT5sEzo~I@c=Vr`;<=^ka!Fqlqt4+|~ww?iM z_IME}7o;Ro?tQI?>@&I;d=IHorgJ!zwc>ADz3_?5_~SJu^~Dp+=VLN>U+Cxg8XK=K zp74J(gi9$|Up)EYmrwA&_dopdli&UD%a3XA^~DoDum0cv=VM7N|Kf@K_wN$yt>MqC zVho=iyDWZ5cRWW5bEWNvm1RGm5oP}aso;Pl=N+&`YYB3tX-AGLty^MTY1)_KN{7A> z`wp25`yZ2l1bz6&i*O6Uwgm6EOwR-xLxj`#!ai3glVw1?qcWZr(F2yJJd*emEmg+H zvOjSJe?Q`W8gH!!HKY!lkL`ijhvZY<)(cz(*q-#A=-z8Oax8_CK^Xrf%8ua?&o@i$ z$WBHMi{3ejNdQst^H!u5cdPXRcm!hk7FE!2-m^|k__gP&{RmH|9nze8cQMT*Gj+v)tEw+7WmFV_-WTVHbd zLbH}QVEeNEcHYMks=$Vqq>LQcpc56ld}Uf$#)7vEJV7^0n!Isq#fYv?I&hdW~Lh1)ua zu;$V^qHB_ZpbZsKLR|+UV-xY3B=FGBIh0fD$gIh*48I&>E45KawY15@t!0FCnYq+%ZDrIJ zqYS1tt{6G42V%q-M6TF91cYBv#Xi$8$(4mJt(=VHBa|I$3R5+mFV!}57sJ@9$6bqena7xlPq^V!elEzk#WlEvQ^Vd(F>|@4$=CA4RiP^f8z>$|X&q>kuMYkOS;P#ss{~ z`-2C9sPLjX5)MHi;V8ku0phe$3;y&tq(vMqgC=CiLoHmZ7YG-xNa6!09V5`aO%F{3 zlY3mUlhzD{vw=!YK3E7OjU%y-^mjk#VcXTC9a)Qdm?LXciEm^rnt_e1T{EJQ+NDrN z`u6jRVbt(y2QT)d->>n2QRU{TNHwIiuHd{3idx5(c@BOwA$EvTv&j|R-=Ww6DrGr^ zzIY6ZlF(fQN2~kWLtQ2SnKih?-udT^*J3F$uvVf zM@Tk5x0w%52Z{!q>%+f^#h6THxT5!F2b+50^mEiSJ!$&6oYk=q@}V0cUsi{rQ_D1x z9xGekSc4VN-b`QPiVdY83mzJhst?hd%yzk49AO^Kq!d`z4NOs7!**=|NrcZJeq{rmf9ZQK?MK|*N$COo#rFi zjWHIspHmMg*;bXs!=m>C3UP4H01^j%MmN47`N!IYG!Mib^*tOv5a|qJrYBd(t7w9g ze9CTD{^R#_cD*-Qz(7Ggfph~Tp6(`ez=RB>%4z%zW)K<#@tOgc3mFB8HO%DzSYAsb zwrjLbH5LLzkGD;Z@2K$6+PF|=4m`vJZ-+yCQQpERZ_$XT?B8Z15(aaODLTwtZzAVr zdQ|2qneOmfL84Garcs_2UvnRcr4ED9gORw39$x@)46Q&z7t#;|j*v!C7brqxFFtLj zTV&Sw&u%)UP9{MbHLih%E3Ond3xrR^6s-!>N$ve~Nw7%ur5HmZWo~$+84`M?x3cOO z1J2YWu#nJzMG{%Vp2rzy`F3>*=!&R$rn!ljS+8!u4%oqSS>&PJg~qz1J;^VnBw8gP z32Bc&H=6h3J5X~BlBjINrZot%UpAxry!i5KuJ%hg&HSWOHkJM2W+8=!;$njdrtm*e zoMGUoc0GkJbcei%Tx;t<)@zQhdx)N)T!Ff?aW*(u&JsLxqi22<&=x^LP@{x2s;2n(K*92XAxa<(2$mksA7o zBdkkA__&z4mUwrK*6d8UU3<*9y0FVb0{g{ksCU?vSkA}3c!p+pc^Ume!@X!t z3m>ks;hNj){;bQMmvq|ELsvs|dGs|P;vBZqc=M{XEje#94>ZESZ4m4;f4z9KiZzY8 zszc8cluJh29!X_D|9(w(fYJpR2EN5TAY1jauagg2(4Zz)Uqxi9I!}|mvZbFmC ztbT#IQmZ%9km{2E(7Bhazk(W!?(JcBE^J*D=W@(JiMXYJk7|CG+Jm6>Z*Fo8uVPtu z0L%QR!2vJb`;C?rsw)&fiY^BhY#99A#-9A52|ZGpffo#P+3Gk z(d29f+(AP^22OkN-t{QK)?QxDj_Vy;sX(&ER^t4IdQqE%0}3|zZCigbZPF~ai^;hC znH_xO_Q-ZI+m=4AWfYchw6fmmZ$}(-m-5EO^X&}L^=b)Kzi)_;h>3+`N$oSIez3!6 zPmcVzTso^*u%pM0>kQ@FMlG<`&jdxdUukBXGu$N{qk!G!BO_oVwn59T*!JbBwvOe>K*p!5tk)dAqSDmRx$AA!{dkewYrVbm{s{z z3i@>{qXYTre#HVlf-Y+JsavT2Ui5MbWIN!5toF=VMK-ctc(^7QV^z|UCbr9F`j;J? zP2B%N;8*aoJ^&%VS#5`!ATbSRZ&Xg8KSczWen0#S|Xx20^=Z%FaMMv64d1^Ddddw@wYg3RCFs$R1CQ(WSX2K>uc!4spGF`20 zICwC;xG=w)?cNqts}6{U<$6IP+(SaegU7QrbYOP5356tP)ANwksEJ4q0oT^!F-H$$ z!$!a-sw7ifq7Rn!xU)Ll9;SOdtCJ_1d5Kmc5N;#(poCP!-9$|z7(8HspcU_~lYIfI z6W@ z9;bx9>0~H;n5~d5Mr)(ZKY2}9YlAheZLE(RccD)@f5y(pM)Xf|8deZj7Bbdb`ii%#bPNi3}ZW(3yIa0Slfm}FrY z9nzr(5Oq?OqvbQPd!ZKW(#gTPjpt?+XAIvS2$u(rToE+%$(PuCBKcr0t68y+K*9Xw zRNdet35Di(s3o?T0!KlTJk^FODn(JZ>m~qmf)tv&iFWPz67uRg9ia zS}Z(4u~MDzqHJ&q>VqY$sHlTgw%EQ(`Of_4P^~{GN#)&&ChZYEPGd#pIJzT^Vr!rC zt+&JwM^D8X$0?#c!yD!Tf-21{Up&>ktr&2bkv6gzU+ zh9*2MK#q{3S}{t{Qqc#!-O}gd658nw!5B)UX^u}j{`s^x>CchZW`Q1t#q`Txb}J1eMw;dj zqJgo_Efk;n%Tha_qS<%2-lhFJGZJW#JMH*HH7%%DT2OD0W{1b;%}0mq+d<=AqB`tRypAb-ZJRan z7K6;hno+SVm~62vEm6&m06Ht(@In*mcE+phoU$--i`kY~6u8T0NTG{0?c>vU# zSUivU*?*@B=lI9J1tCsiP!CUYpU@~tjZPH5{`&I(@w5Lv9^|h-FF=A@yhkE)RvqZy zt{CUvE*j>$UIEF)F}o+C*`|E8_X|Tuy6-P|$2j zqkKYWZgY=Nb<9dk<#GrB-v>dR=j{1t(||_2 z`!8SlVR&LpuvdJx#C1S2~Xn=cQct z%;Di&^C`bpiYo76UUUL0FPPG|FrkP5b$ElzW>if5OM1KMpu49GmDP5L-c&H)IoFVk z)tCgmg!ggzBONGM3Pw!!x5ppX&vyHFUmtdxr-#zVP8=}$g2~}_A3Oh%fk@LM=WKbf z? zg?~97a>R{xM5Uk~cI)-;Q(bDmiekT;uP7>Z#i{~=#EpMAhQneF0e~?UHFl|tKew~gy_)BLq03kepUlfgr}f0g3h`HwhuN^fA3vPY6xbe>`6wYw@6Mx$E7 zEQF3D5>=RAqs&9@lMuGyb7h7EuYip%#T*FCdKw<~)=BO0^w^@ka+`wvSnG`|q7?BB zj6JV6_y!T2Aky^)zPekzO;*{h-U$9iEOq-2eWn4n$rFh&%Zj+^9HLnz-+IW+b&Z?; zu4y$}Z5I$)vVML~o=l>YQiG_Vz)Up{Esmk1O~4nCB}ydVuc1IQ5JAvsYH>KcayE^nrIe;!^YX=?mV!xW3Mq%4#;;T`F;r|9AJXQ~D_3a@Cc zIv52lH(cPWl+RF7Kc>)Fn`s*|tDfQMBn=gQ`X1*Ks6h5+`H3p9r|V)lJKuhZy6#L| zb;j-X$H4DzFY<=1eTHp^3S(*OpoV@%Z$F`k9v&GJk*aO$3>03a1N|dm5eKp?MddK~ z9&CKw=bIa>IPptKdxrfq#srCb^$La^f^aowi{SDq1c+Dk> zgoe7;u?l+3a|%I_{qB%-9)DxGfN9%GX*nW%{04R7xg=-T?%z`QZ+|c>P*(6?tk?|6msW;7O4li(*;*5xy+P2I#F1W-@#1wPjzzoqXi3K|# zK73`p9Kt{HWRJ6B#Ky*9sKZtE8xIMXS!81FcsB6{pF0>`5Sa=HEKnjVK9`fonTD=v z8OBMMlH*c1ic$F^$qg>iDaaf_%qEknc%d}Ybid>mq;;XK&B>`8$eCsP2GUqyX-P`( zy1i0?)-VI;e*Ai&guJ9@aA2b%EO$R|>3T*xJ|@-bVj-zApUXX8c= zc0nc)B8Vcu@<$CAd0Y+%{auNnS70Zx31h{s#LF7s{yv8z3bNy5O6Ym&eRh4VS$Z;K4yRd)`U*P;>;f+LhJM(Pn>yjG97Y?1+v$}V>AH; z-9T0-7WyF4GC|p_?A$Wp-54>a1|OVgKGe){_NcjMV51Zrb$%$ z$n%q-SEThQ-+cTgigFa(qXtRbTIiAVqMo&nR0c{hIAUBpsHnknQo`UUh`>Z3y|l2B z+zOyX@wV`+cN6;thDsaWsJLBD!V+w?RL4U%dvxtAT89`GF6kN1BTixm=aHg0ndm2Y z1u^6ZJQ%1-=0rkQASaWlGbN&7f&m0w=*rIT5{MP9Hb&$cGtM!r03;^Lpl0F%JE7Oc zr`o+6HXBPn4ORv*OcMvE)gtDSWf_{!-JT73V0Z+@xEQpqHsPd>$K^85U1;_qBJp8> z;qCn$;%oi{8{Rn-;8c_fZ^BL3oDMjXEzhExJ%N$l2_W7kK<8Rg#weC082pZV&>AP0 zJ#@0IJTbu><^|v=+cBMROR>n=)@781MHrv11BtTR^_$M9C4(yA-f*%4I@AN+v~JFV zmbA@V2($$7HTzm!PU1Nvf}bWJmb&CM=+yI{ZODglBc@qI8p#S#1BVnSlu2p1dB%qM&W@Yas|AkA;Q!YSAH&kx#yTEW77>pM(4@oxZofCH=>(@^Gs<_- z^AL1R+S*1ebqjudM z;wyS>^vji&-6OYbvC50SyB;=!lg6WK3rWB61*KW1YeI~r(eOVGN;fcGNy>m2K;GVI zHxCWu$=|Xv=WvH@JBY(Z0p$+Rwb@?9Dff^A#Ufa%QOrtCI2YMkgSHg5EKfc^2jm zBfO$lGWkBTv|;@JM$aWbk>($NM1Qci9lreCSQvs(h>An-72aLM-hPS1@u+A4A2G7^ z))6lyPo?pIaR=TR{W9vn0xS>n<^Dv%MHeS@EHlB?@%LwB@^J!NRa#a@omjkM?z%H< zwmO+OiGiS%z#Hw=5eek01=$hmYmOvUwn^y9rCqi?WQl6RwmQ;EVC+;z3#xO;rpru{ z>}7SRj?=K2?kix54ggIGD0|Upcatb=Owu}MpOgN9BBX2!r_ZHpS@zObm0tL)aj7O^N{Dnk*#?v)8aCje!p3ilW_k(cody z;JTLB&kkIs(#%XX=U}GMJ&YZ#$kX*LJr;hahw;=6@9^@;Z_q$|!9(Bl)-DQGHHSCW zPN#7s0|+2#5_uS$WC1tP==tv4npk{MV50Lg>{I4BS%Z>jB*y_y5A!=*^RP`Y!D;xK zuuc6ydBQXFAOh92w#KuY-+cNTOE7fR7aVQk3_c&0yc*iCiU4_NkG`3~keMImhby-@ z%GCBYM-W9%vd)HDWGXW;&^?PKPJuwN-BA?cPRT>|3ZG_pY_;szRCtwsOycgRxw^qUwWU-|g-sYt6B@&@A&wean~6ey!1_zXRX9et_=etpiXLn^kNw@^=Gaq1yoQ^+R+ur)q)J~%@FNU7HjeC? zcml~jcK9*G)2+stu9dqpa#BMD3^VVJ20;x7N~X(ywGcVUjUvb{zN`XP*|i2ltE*n8 z`Rdr8+OoEvZNsDa;?8xf?kk&QqPyRLo2k-%x|ryQenoN^tz6kK_<~KrT?G)c9S$ND4eEr0INZ>bUTSEo zjn})|-Q@NhQ=ZL2u)o_+j(E~a@|a|3R|u$%$M1r|qBD+x_7kp=EhUHrMi>HwWHHUi zqO&-g&{^uyB0bfYBN8E+^yG>B*DNm>3T0=(Lp{1>@9JFK5BkO7p02Obg-)9lN*S`@ z3T(98L>xEhZu`t!!;Li;YVB<1tObY|{$f=`t?1B?Wkc6qfLzROCo_O~ZN-8nMHKax zmeZ9m^?GlFCHPXZaE2l1rzG-$C23Hs7&x*D1g1`W3CE8c+H|1M{eFdEhQN#LDUM;k zn^$LOOk}BOwJDk#VZkk`BT{C`ZVzD(14hGUuVSW9VjwY|AHWf+;)oH#hw2a_i$^xCKc z{|6kLd`}_wCr?H+$?nT2=?#$fNdIwOo-qpUXG4xf6O$jdzdQX98nn;|KkrfDw$po` zZlgGUlfYDmYfLGO)}GEwM5cvqh*4XXC{g~*&QwnjY3L}2%1QpHN|L z+Dd?Sl1n2+rzkZt6h`lZX>mn|X|W~#KAJDu1FKlt;OSiX6Ie+z9YL|<-RefkRi~*L zqei_p{}s*i)()b0X5`If;>_7Q*D+-kgw0g)*xr7AKijBYsP)}%act@?>w#j_uKY^- zgh{Fl9jMD+V+HB(@pK2q+`(-njfx~g!TZy9v%fT@oe2;dE#QSy6_M|ErdC?2(9Ewk z>_cl}^PV4Wh+kU3UQicD9qPN2&%kyNz^gmd7{~#jn0R<^g8qR?%7T|BbC_!R??57) zFS5Cr?x{6!kSDc)0skX>Ty40jF+X4wKFKX#KE6=uqIXuH+Rq;4Ik8#bDH0H|jE#w6 zT{kt90vzS!;7O(_HxnE|P|bd+MnMmRZ20u+vyNf{1^hL1?00#eU#PP(U?}?WL7py3eq5R1}s7D_0 zusi1qkYmFwHPFpGqYdn|nuBYJeNKF4rNMCUW1naTKxyi9@3%Jf{p~>)(t<4RuCNh4 z8m9N#eMZfM1mR;)yT>~IzhDMwQbkDVxAGenofV$4 zk@#pB>BSW92O}nf`%1`ES8y^bMo#+*2(E3Utws*2J%y+0kh7Plsz8OnO+f_7i+LcEl^aSU{uJ0t^a0&MDC_ zev7!>Vg$QJCp(+rMA%5>J`Bk8rZ4`QMTFY+f`}gcw0#)#)AygHAz|Yv$1%;8hA8Gq zA2A_(5AAJUvIv_;3+*K?QBI#xF?Z~J-C)5iURQh&dJU3waQpGxC_3-ygMiLzg9DY2 z$S4vdwugwV66Dlhlv$IvGfw}6(if0JInYp={TeJ|X9yJ7XBo=|3H6h5y!E^cD zKZoS*s%WLDU!X$yB(OJ0uc}yut_hOh8E{nW<&lU-(eL9PCHR7_S^xbSrAsu?N^4%v zg8IJ+!^IsNofYvs-LCEZPVATT0;eW^(R+`u`;xeXismHo5ggKX&j-1l!;5zWa1#b5 z9}N9c-g(doeEZd}e#KEWF&U^F&)2V>ZWpikA0#?t>BY1&zuucMc5_z(CX9pd25&ln zV{{?}C$xuG?{6D2A^sNjzv?q%`xRa8kgfdWBN`ZDOZOJmOE~1=ZzRv|)1Nr)#*?QD zY~+B=#~;xK7CpjWctLrue;K#Di|{rT+2NUkXvh|(oML{!mF65Lclj0{(ZD%QIuRYg zOJ@Aky(kMtfl1%5_Hbql9mSes$IO=di^Rv}_Kkds-FK%uoNE>iMM9SM_DEyU*j$=j z$v&VXbk9}{4t+^{s}~hlw!lD*hYQTANQghD8rRY?4Ypbe4%@(ZfO+ZBrW8N~2ug_iyc zn-OSzlzhP)4+s8K)T}TTn2x3~ZWR1fn4S;$Gf#U^>!63jUGewA?M459S4mOM8(fIe zj;ls@+55goe@jhN+YfV%Hva=g=O+r0=2Sk2SrhVj4izVv&a328n3RI8y%u{NV93*3 zdSfZk4`1FDU-naIfxWHc5W-7h*bhd9?pf8*Q=P94$Ri1^)1z@PppA+dy1i_Jj%~}@ z{QH8~w(*3|y#nfbYFc(7qqBj8q{y2ELV>lx+2o`q0lKues@I;X z>5?hOU>_KLEv+}I?S(wYyJ-u41X#SZo~}}}%&&k9R0_Y)R~*LV_2G`Z%?SCIb_>nU zT8k~THR0kv2+;biSG^ksFOft5dWBjb5;S%ul)y^{gJ2Y;t*W4xK)!poM}fj*2IC%} z3c0RI$fsJL7kJc;vH%6awh&T`4AH7PYzXGHUUg16Nci79VWAL{p zG9|s>Qq$#MUmgR_!3KBpN7{^p6=rPwgMcG)1Olm|`yPHF5AGsT68h}VdwMb)Yt(xr z&{Z;k0Lr0Ubz&2~E$DWg`y%<(^esS-OJ(>w`2^tucIy)0Wd|vIob7r48vbHM;-6bH zvh>kTg=zxfa$0roRL0?PEhPZ~(9>rc%5n*(xv2i)R?Z$axBdk0IN^A->)zFyY~clV zJueiw*s@)4mV|B;jM32^9Qlnq*KwFw8T46P+G#h}Nb(RWJ?d)(Lt1jbj63cR+KytL4mBx>|%AE*D={YC(MIo7c z7j|xZR`6;5o0|NL6-kL##G!DORD*_C_$VtCS(y{bIE!7nQ@ga4!R$00EeCj;jv=}L zxm`td$-6<7x-nX-d^4*J*iHccf)u@nK@b%kVfdQ5%&*k*>BSgKnhc^MM~H=QPn>lz z0-+*1<2V6T@Y>tEv7!gpwv@Fy#A;&M;ojn{TuJun?WYMGB#Rgpy&$s*TU-DAf&_X0cHn$={n-Ygc$B5~v%>5BozSVC7E z#_0D~D|Y}lIQoz27a@pu3bEo|;oeqRM{yu!&WVRD4UA7-oc~VUIFF`XU_kHTM;ejQ z+J0PIuKLp_pbL>^uE*S0-<6DtWD=!70AR*C5sL#loKsDpRe5j~S(Soq8g-BQu5oIT zH_LXb3HH;rD{S-@noNy^f4~ZdubG{R7uA5aIDUog!NcM3)!ZYx)15?2bNyI2!7=XG z61th;Jyd<&6V5FjQkYMd@As7Cj}r)qh&p2~&~68x{~L$H)B2tGDA_dKw#0z41zZI+ zbtr_N5<9?>yi&93;Gc*e_vVBruzxhTyb`8LU%p}A{BEg1yy>v7J}{VOV(!3eEd ztf3<_ZMJZWCI}p7TOr4YUH=|Psv!Wf!Ir|Jl{lZ3Y6Ig1y8$Jp#(oC1g*KC^pcA-zw1&DCndd8o(%J;wh1d)k3_kU1Z%m=~ZC*D-+Q!|@L2QVveZ zoPxCic8&OexOVrrr=qUUOXKx@ezbz|Lt}QTlbd24S9AbslIGS)4leag2X}}eF4yis z!&`P=dDI-~Y9hD5hozP0L~%q*0P6>Ydnt6gQ4ld?B%yJ=6R4!O3bhg3^Zp6bsYS@! zAQlX7G!dKj4HToj;$`o`EP`S`1JC5|0i1Of{wE!_rK z1EEt%F>Ec^K`5nnOg&xh+HopauQ{c<1B&GO6D5tVIViOU4>e#(O6sf%I<|LQ9@@ce ziyUTneoT7*CJ}8@v3<*6r{D=bAvu`N754y%bw$Tho-&%Yl$F&~)CLY~ayegJ>aC6@ zzQ)dmr<*|Kw$TKYX%H|B&L(x91exmta}VdX!r6i0y6M2+?LRnf9KehTnI@K@Z8nYE zQ(`FDE^UHo5UW;?_Y=MyvYRf}hk5B>vo$~MuAq-l(9}X9B&Ad&`5&%V3*+e_-ofJE za6LwLTmI`Qo-Ve&`2HI3Pc$qM{RLoJs8m){xT{_}M z>!j)%9dx+K({Rxm;{i&o#_7}T(DVUSJiw#^SZ=m(1bD}lXnJT&2t1I&2bgfWN4R;- z^~2PE8(hA34@$-(6?Kg3-!cQzP{t8+{;=^;2DECJ9wAL~5n*JoT88PtC9_M`y=9vN zy4THfSm)NXlVK_*V$D8D(+9H91ZJOwCXFA+LKB!rSf~ldee{lI+iwRo3-w*cXl%~_lh@OOds6x40i)n9%vaZ)WYEJR7)w>u z!6A&|8rxl)p|V3e+&!!nJR-A|mbe?o=XCR33;+8qswlW4kRe+IiQJ;tLb>Lb%Fy1^ zZabuU^*Rw9DFNWCaQRk?DbfPS{e+{e8oB-Mb{H8}2D(mx8UpiO+?UD8UhAm)UBQ0MNg+3 zuQ$W+;s^Q=0`Od&JGNmUY9*rjdZXT=8_*++;$F%M5E#f`&L1zYV-4-7AaIb2$>qmg zs5+IGwx^gmUa`U6(`<+L*}lji(4V7_2^V~WN1o$gCVVC!`EngmwzsqQ{CcAG8(q1T zytOakMD)JJ6x%(!r&ls@e2R01a};&*NQONCqZz8;TNT2Mw+g@+3Up<3;uIbx{xDnZ z-3Hxn9-|27>W*UK&p-Xj-;gEeqGsNSQzy10I|NHc}Uw`q(zy10V4w-EqpKx^Z*S|k< zH8LKbxc~msRW3_$J~;tv8Mo7IO=KIKokI}`I_FFGiJl1{t&99 z`;lRA2VxNc_26c*b=`(0z3edG8b9 zIUq<2Z!xKpRa)XkV-hH>Kb^lSxT1yB>bCKj(7vps2B$_JWlFNpE2CO@kx zX#C*@PRT8lRJ06Vc-1RxwlON=$Pa>R4gfq(yOKMJN=zD0RTDDZuBbdew?WVHP)x;L zf@6yKL5EIbL>;FlXZ`Fs&q9%tRG~fYfbbl6y+gvo<6mp`4U#FZMg7d7Ug}3%%oeZc zypl2DDtzDI9;5lbTtYR9TOvLR=e5nj-r}vB%{$CDxlgqj>6+7;CInc{SoEZ+5WPS= z845K^)+w5oC01`bk@ep$*MrFYE_t}6q;|G_YCRy9jyKyrbAf%h2xBl}wq-ux>hQaj z1v6zvjQiM|g=D10Flj@&W-CC_%nXn=D$K-ijqoUInFU7y%%>10`4}aX4C1Xozulp)0@u}fMrVDU&UgC1?@;8-&^jJl|<+M-)iFhS_VBkpdI!(L8j^VAR1 zZ{+2jzsMJK(G{T0#3iV?f53^%lVA|u9*9*)m2fXfqpx@#3`b{OMUF7D2`X908pzW5J*5mK z`OF}LdZq9hxdc8+E6h-(bt;NdLg(ifGekw5#GWePr7WT&KkBb^EA?=$>S5JA0XK?4 zp(lv@`V~kFRuZ1-CUmUF%Ric(xf3Y)wm2d<3z`b_ske3d*aQ&DSqHBIsMsw-ZkYgw zuZ}tf?bRrW{Lsk+Z{pYcz!A=CyEfPVf+vB(;5VUYaM=C~SA$7bpgCR)R>E_ryIQ4h z9VK4E9<*EJ3XSk%$3G?%kdC<$k0QWhNsLOT;!?c$fPHx+SA*d-izF~4TtK=sz0ipd zsz?%mB88f@nBwL$R4Hy4gDHEwUHG9pr6SSixbsdqZcaB=@`!9cY~K7YDVvPp%IeEC z=#&}=*o_N?gR2%y~-UNwhij!X7 z4hH0sPPc=Vl4Ezg*k8Vh#d9ss(Co)SSrSPnUeD-T(I5~FwZWbl)@a|WtVbWXILQvg zT|L7+NNhcxI#r;Sl-o+4(3t}*1srrgZJJ6v{moL`GKPuz+89(CrNhbBaRbF(^@qA= z%KZh(rQ;|0$Lag`cm;&$J7lK%4FlM}8So`rj*vPgURukYvnjN1VP!Zz0; z6moK3*JE61I0OuCd}L(QB`$EWTi6%HOH=tTcAb{j*+4`1gI{H zNjv^}+r97ZW8(we4>=otd`oBV2-)nAP`c1Z1DqPdvvL%`+2myCHQaI1GIa~dPs1GZ zJKUN+nk%+bPN@YCu4cQ81v%#uLrPH_=B153j=I4E;@yuDT#4B6TPTGEm zOD=lktSK!#?EY?tqDX7{7IY`QT$q95!>sObb#VyS7L15A7LIKQ+p z*4!y;#P7jV5cOF9^pitCxcQrDn(ZTxL!SVJW)kOs27|45QtW!PLSB8R{V^}X|3SB4 z!ZAI%{NhgUVSf;HYIk(<1IhcxC!B13L}!Q}pU@W1KOE(};qRu{NAAl%KdGPp`DnYH zKR)4+P6(lG4+-8z$r+y!p5my}0Gw44TTZ=s3u@VN{PHBTTPkQ#6o)o$srK&aZ$pJorZk zHT4ARrUhn6k{6#$F1uxi6MD!(|A7vVY~53Ulz``IxE`g!^dxD-h-FqwoX1%F-Ls;&^~Z7e6TIUdGnh>T4WCvEAaS%qK$5-6o|@Xz=b7?!UXv!P=7 zJb!ZlA{dljI!woo<_EMqs=ig^jK6Z=r$cBH=J(B%9yn!fDjXu?7w=Q>G(!_wcT%i;rt-{epY@!QRnM@c!c6%3`uD+yC+<2mn{fqAU}dkEJ^F$R7`~T z`AUyEOc{r(A>$J&@*7O}x$*g>I1oO;^kTZ*J=<*3H&K*TaU-0jTyAeV>{eetQTL$K za)(8ar|)5t9O@JCs18d7gSjRb5L6U4|moUm~arBpr@JZ;&^W=GH+7QpK^>Me;rVG8{|*n zvPM=;m_m@Ff% z;+Y1+L__r0Khc+~s6V)=+W(dm#mFWZn)C1B?IF& zWZgrmVWC3Bgn9Wf2r$9wYV$grs5NMqJ$-o4YvpdN!juqMq=2;}>+aXMXj7+5;A;bh zzsB7LB9SNiQI0+;38QBGjYocPGp0ULOP?V5xhviuLIipt4ncVM8*g#?ic-;|0v~7a zxFn0q5_sGluP5s;&gqE~IFQ7GpkZM=o|>hgP^n2b@o+zC4b&3F;5e1jNOijP0T|_z z?tlF05NT%XA|Cv&fBatV`+w>G@z0|%Q%p_8;|g=s)hOb|!u_KWEf3HpKZ;hc{n8~N zqk3sga>Kgc+!4xT3WI1J$jgsjL8|lMzX<`+D;n7W z>@RNH_l^JWv%j3alP}?4&)!~~U*IzVPBJUN=joGIc>l%uGSHOHW;hTg0hz&qHo7U> zsmy>M#oJQ)`=2Q2cUVNjaxK~a<76-LQ#uw*`{%hzBlrffFO7mfLEJC*^Bn~l8V#Q! zQ0tL2M*x_wxkQrUAmk)BtV)Ky37NR_r@oJk>YI4SsD#3$bbR-^U@A#;qKWt4NR0?K z{>HAP{FUnlacY zPQ3`1^bANX_0&9g31h8WsYOf}3PFbEfr{3I zMme(>6t8C=R-B>?3(KJJg(IZ1v+p)DSxK2#=j^~zel5c(+ngWl=roX*v6hX&2hCxg z5sN%PktrB_N={?ZKF^}ekQw^N{Ae6oafqr%AA@V3f+Jgy#5fQC*T37rL3N@9{D!@= zD)S(ub>0iY9Q?q{4JloY{25`W5a+ar2(L z+|i};M;wUIaKvJIj(vLNDs0I&b#|TG7BHUBs^%G7b&b!Fp#FpzHS&j17bJY~87vjMb@9kN^LBJC`b0W6lff z&noAjfrZ6-yN)(gkJ8q-jz>ovFGZEa4ft$B8UtalD~?I%^b$RQk?8tv*VvRBYK8kt zELj`-=qa2l6uMnvFEFu4uaoMdRxi-Im$OZ5uaxs3LpJARoZt$E?Pv0Y=KV5fpdl$Y zOt2YYEzj1@pwittEH?0d%b$?*s0J2kP@(8UJxU?Ob#?(?jXo@?!XdRHG(`QqSV7&O zD^RqWUstL(%8sM=ml{z99*GpibM8qA52(Y3rAl7F8IT^84_oPcGiQd*KpnkKR6e^WyaEng8qj>5FIY z&R^nB7{H_FZ=d}a|0`LqZ*b4n6H;nN^X{6|$6kKvR=` z+T_IMr%Fz2PmehLm`x4PqOd{CKh=&D(x9hQb#6Bb05K=mS@EHK5t_n=ta5vy}zS|1s; zbdaAsL>-a(Nu!30T`AhH_3o^63WK#&b&pBPZth?t2br4`xw`pG+E4W##Oy;wNFIj=Mi6t;8 zqa0Aembd^1!v;CL*|zU2cHQzCT04&urf7hj2NVs~@}$nCj~Um$zo-c~L?Dwn6yK8D zzzJ5XyZK7;4a!%VH=9xO<$X~bj;~p7Q}s5iage@h%wEns(7Fvk&l(3XK(=*gB`A>l zu{vqCH%f#4^ly+h6e^zOWQQOt;Y9l>K+$uTUszncev4yB&R0D;eevd-Q@^ZuasKig zzc4_YSqG2&sm4c7{-4m{>t~^JvfiM|&++{KF9oUQLdS;!4%c{Cq~Kw7X|u&Va_#iD zu4>1R@~|6=L5o?tD%-Jm+)M2)kynN;6^wCqkexFL@O!L8EeZ^ycU)`R=wS;6B1U_Q zJPRcL*(a!q$*P`41J3YsbxlYgYZ$cTsHFG~zzvYXlkui7hwaJkmsA8g&PJAMq$#oO zx64@0(U9~Y_YUm~dIdGCx?Ub@RJ`y&3zk9IL_?`fNow`Ho363Qsb&-N*~H7kQ~)T3V>@eBUWds;&CZ}W_;5L2 zU40)u5XAN#jp=zdpgCfQzLTaY}Gcdua%aYZc2JtBBrP$O>YYEEEzR9SoxO6>@nK<0zd zHwMq^v2bpTr?qT}#?73&O53?_(V)2DE7tO~q5I|=D&_z2tXV;7plkc_?Dz_~sg9(2 zs}aT>O&r$nzQND(h4XPs*%V}0kF?jhKe_=p}B=>09LP%MKu_Et^O#F}M?M$`d5sKybT{nAw>ra)(DnUBX z@n1EW11=Ff@Wp{2Sy+8jP$LNyG{YI4B>WP^mXDhHIMoyd2^>yOKE7ye1Q{|&?Et_l98EPP9rObaS{GoixrFgb z@<1$4xGpT9$i-dl`^VjEhfBfm@>_S^&amXpA$GJe=eAo|_b6iySm`;+FsELwVI`g_ zWr-K>3Om+CpO>i&F-hiM1C1V4X<2nUo83#_gQT*5?BR0nP3-ek(BwF*d^PL+luRODr0eA!b?Weg|gqMYypwW_v*CZ*uJx!UJ9CIl!}U%L0(H;V&A2ba73ZEd3^Z~R=7If^y4Nb-eA9f!o>f~kpV;X9}tIxKMg9?U1X=WfC$8*t5SwW zu9Tn}VAMkvM}f(X`FhR(C!BNmQ_f`UPZi&4n-oEl20S64+N#$9h!Li?5_bE`Gxw+w zwW1UC#4CeQ`mF%-XLgg`j|4-l4J#-8lZ6sSM_M0uqzQ$ZN0FX7rCy2^4)A6sr*nc_ zYuHrG1KLEGL{awpi=@WA*JE?k66NbyrQUZ;$G3ZgQYK~}h&14A>wnzzhyd9B@uyrH z0TiI(l4HeZ=Lpni1J9(gx}iMRv5N*c-7i?dgt- zo7)X?2-<~F-W<1;);szkQ7W=Ih8)#YfhVby9PMJ+aPIXfeH|pYfuu~hOg_Dg)wR3r zPS6PJz@{3P%72Helyx9D916c5uT7Sua!u!09!)?EG%8mS`iXZ-BRiu)ZOo37+*8is z!+f=TKiloEdDAhZ{7{Fv{1_J(RV~DLPh+KJb3g|ro1optY>uYlsH|44;j#eQ(?=t# zf#RRe1q5qzZCozA=B_~#)qru{T9FiiGBNSb!^U_!y`JrjVWK-3Au3mvn5;C2)P2I* zE_*Dd*o7z+7#wieJ^A?37340M5wUbEO&!ETqazm!$Qn`?ug10LQ1x5MEm;QP(jx@N zc3fC^<%LBX`dKY68XOJaz1HX9JzlcjtsHRUIs6bVg*=vl{|c+LUHb)^59<#^dVaDX2WTI5sp=u1RKM=#Qln7 z>2KMz7n538S&*XY_i0WW&_%5NSfLy^Ciy~7tS;&pm9DZIAC*4hZ88mmm1>HQK}+gJ z49MYfZy!%8Dp&{pU97QKVN)q2QavwilUBROu`3K3b?BQ`gN#ERRf=+U6LCA>fq522 z)u>Gvbi^o82n`q*fgV;5Fphn$YWYQS3r~|=$|?mpPwM!Y(g#VpRJ~Z0lmiyX%;Ut0r?!sAA4rVxxNV998uY`fwzu6D%K0sM+G1A zxUV`CF$}@pk#MCx2BOh9RvlQPc*5{D`KqkraO%z4j=@Y+t+W8r{R70gf0X2@f?q=3 zpgy6Vm*;eUCsnPBA1>hK4)VwBuWa5Y1-hb5xPNIs2cE-F^p}!Szj2T)gZu1j{p|Qm zfQRuQsetuOT#k#tQX0UEMpdJrE$f>D((3D*m#T1)jE@Jw%T(@mwclKIe@c?khEU?^ z)hOSAvr1B8M{p^4p>i~XEVHPo6PEf?`GpMIsXGAD7TYBqZO2DXfk9=wIAJ;_qeoIn z$9M8q2-HwOpiwU;%DO0XRj1=J`PJl>iy2s4+%Zu#F5)G!WKk(m* zZ-&?1WJPpFD+em+oY}AU*2tEmdP26)+)T$Om3BlC2W@$jf_JcrnE7C6m@>l2Ktb(j z8&QR2f+3h}HRwAe$jR%+L~S^fFRECKX_3%a4u&2oYD&t-G)GisS8{I~oqrR^L!nLM zoer%N;~EC%XkcI7fFGze>S#?+xQAQ+ZqX5@3*(&B^gN>~!j9Ud7u&WC%%K!@~odVWm);21D zj$W2UHw%d?ztm)59m#Wb(%aDHbbv7$#ej$F?hyl}MJ0sI1$PEWY`(gC5lUyYqA}BV zNLWIo1n(1ACciq9uL|4k#7H)%EfK@gREY~=#Gu(2+EeWC7~r$&7T)EhvQr5!H!T=& z4v9C)q7KgIGz_9I$4b={T6xF7mCUIJp*o)RdGQCy9Lov4UYc~VgY>d>DK0}a*)kz0 zvR*5M>3+~cD=9P(x*j)Q74-yus+p1IIIkiBbu*$USvh)rsqWvKvt&6$a@pSO0~HS1 z3YPb%>ab;E04O@ai%(<0m|mYZ8t7Z@a;&#-++nzW{MCJSQg*n8Ndb;N8W%euUEI=c zZUNm-!_D?4^jWq{C(yj%rl146*+kuACxGzS6L)EHw!mWuHLfN%*PDnKWD@mqB{=ol zKu29vC%6Sm{5N=br$^2rO0~R?hqtQu6~GNJ`nIkBsvL>)qSk2;U`t;y@w!{#0s$Xf zj$M8Dk1Dg(rjE3~a_15OoDyYz80eWXI8&g%8&t+i=LE~^t6?nn>BVw2a4JY5x+3{_ zlvR4mSyuXc2F;M$)bhLNN)HW44TaL_($%!Quy-J>{H2~^e1lPR2HpE&YEBviT2bI3 zx2u$l*(BZxx7bQxElsQNP&kq@{o#;Fu7V4f9-Noz%6D}PaZp4lH5%xj)XnYMl*E^& zIH(Fo6gWK3;w*0FY&C6{?~!psw?~#X?AbTd*P=~aOD#<9K%0HQsi5W2M|eH=9}KwX z`u)E^MIrdGj0sH!1n%xaudy0?z2B|(+0n88jm@<`C0hib=+EYL-s$`Io9;d4s^|Xl zOxsQTh#ReE>I!*{ef|=e|JmO$qrVKc>9w(&kAQ8#wIC1=(@Vqu74Pve{=9Ok4W)1L z)yJz+0OSVW)C*e$av@mXBdd?yrqwOa+VeM!C)e>jiwceo(Yl{ydG#YkVI??HGM2yt z+GY}Nm&Ob1^${Q1Qo`Vxul3;r zXHCa2%vgBHhp?9iNfg8>Cx$^poS_z)MPWKQ$kJ=;@t=NvxuJ^WC}enYf;U=Xe#&tn z+-u~LT$_#?uQn9S;ELIPv&azT^uh!X$Ev1jD3064?h ztS#To#QAQ?AgId_WjoXk+imuty1FcfC2vSUm^*qQ=I;br0NSlC+``12=Jx7fHg0iD zkL#J~Pk!_=&(jVLo)J+~D4)I*h5nKQZy~3;C(QqY>-2~-Q&I^roQ`?3p#|p-CCYRbNO1V92Z^VvE86hJ)iK}ObJD$cYsv(u zKU-eEm<6SQZn=^c-hxY1pWW}e8QeRn%t1 ziEdQn+it&bEUF7O^tUAviDxye!*NPb(GBtt1C`Xl5oDN({G+dJlv+XHW&7Ou}Nv+tk=@CtrtL4YVDqO;AwLPO?jbGtY462~; ze72m*>wGPkIN**DD5VP8?t`fi)m6B%b=`NffmoTssZhXe2ND6%4#j|)?uK#^#}aw! zdMz&}iB9s@m}4ENL|Zn`0SfdjN_Zf|LzpEg<+==)-CZWc7zraxcDa<`*sxudeKgsx zfSyuu1E+8XV7KDvgYjpSqFU`;z@0?B9-`SFM@#CSS{5LgTY~C_6lB#)i-&6!rwIZM zoXbWsP}Xn)ASC*~~t~r`~H;7ssF;s~r~ky_TBvp|jdobw?1EJOkF~ zY1_&=y{WtjgdvKnIv7eD(i+*Iy?Uy^LcLfu?FcH<)I63k;E?8s7vpdW`d?kmW&M4Y zK)NSU6?=#F_)k098SR!=l~uYO4yHKB28M}4MSW(N;{F{y zT)vXZ<)+=L4r)W&$Vcgh+c)k-^q9Wr>+r5a1=r1VBTrZw)-4=tO%179e?nBY-Q&P~ z>R2?OAtn{uKcq!PsBBOUQ8$fJ}bGOTJLI7{8OL-H%>VEe^ow|RZTHQP}0IuyOb zf~q;1@AtO*VUMCV*JJw^?X!eL_&s-a3HEO}kNys?yn0{vIC@L|TC-a4YfvsD84cm; zpmavw2^o#=5RTCjM$E*Dt7Er8%Te9@!|HqCKnQ62mI8TywGap}Xe~j@pdNI$;%%x6 zS2frcGv=ndLKN0m{3PvXTVmb7)?ar^S^|c|d($D!u)>ATH+ll)wqI zkNE4cvr_`?z*#DRF>1C-dybs7^3Ee?uh<>w;)3#qH;x@gO@FG}@M%bQ8Z#Z~ej_Ft z-EH`UqkD~-cy!0%6Hx3md?E@wXf3GThZ(t+Z&qM18$3f9$Ndi3EAnLCshaD`O1JRY z_l}KL}5oP>N}<-5NU&!WH&P9Gm^)#-D+dCw%cB zXZM(2>&4bD{^c0>i1Q+kPjq_Z5#9WFeDb$npWuI={`TuH{`j|FKcc|z@d?L)fBpL- zHyb}basT}%Z}D$h5U{htpr_Z8Z1K%iLln%4Q` zX@;1w>VRq^tGn$hdU~L`YE{i)k@S~uYx*YDdbWMC$B7#}f>ee5`trZAt(4uGfErs!MGXq&@YU8bFf z%mX8!NOV)6BR^Eao*XGYmM4T^CrC9pfp20lY$0!s9Go@1XNUF`G1XmRGVE(E zT--X`k~A0d1&{l(W=X&Pb&(ub8sY@qIo;-CLm@ge;=)W_6|_MPFtl%ZrZ9d;?k>|n zyMI~;of<0fJD*XDd22M*TLQ2H?3 zfKv$?GXC9nAR%eq6R+vEeGyx1dw9&2z|d@#kk7Lgp#oK%_~ict`#2RNFteI??`Y&&IG0cD7n$vU-MO*VM1W640n zJDlR}uCRk+2HRzyv(@_JhMs-(HaD=Fau5T1eEasrxFPzENUZoBwO%1mvxMzwwDZ2Z zKj+hr4%}5mGiJUGh2GMhrX*aYMKvpYjPdD0*J4GJoB7nAH>BVPAFz-2ev*E5nwH=) z#o}%)Qc*!l(g;F-PT)OfV|10bg8!FQSiR93AT|u#TPEAZX^H%kap71rI3@!0;~1qQ zpZHe623-}(x+k%>-7zOa_hz>1?jRY@q;#7}_W@^SCby`UImZf1EkJ>B^4o+~D+I#$ zinboYBmfq>wtooFcL;J(U1ZA@P#x&_iS#1?+}`eY*Q>iFBcft!nF{o3D!g2XagYjH z%Mvm>u^(V#+v58iuJF%-`O5COdHGPTH*fbP4Nt{&C;ROpvyr>g*O+H>zSPh*3 zT?rOXs`v5!@~RujHS;>FKTUpmp@_wJR8yH)SdJA{Il!bN{(~#Ylmocda0WYpqX&Vb zS)~kz19B>zh&A2?GmXzT`1C&qVkGp)u*oZYqy62CrST2Y=8ExDjF!bD-5^ww+*=gYsYLj8EHt8FyGx=z(*e zlFbqxN3Ck~`%pXbyV+c)jzFk3fPoIRh3GsLBL*03cAgI9?+E-&x4ROx3+`1`dAFqG3XW%!VhG54SX%B0zYcJUth;5a>xkY z3uL-;znG(TT)`O-J%vEpkF5%s0Tnrz|+mu?d*d%8Hr!<`~p{_ zrfhW_hO{Z`{&c#VUbr~ad5v)p@;99Q2w#(hv_i;?{O@igj0N>&bggD9sedeU zrVwTd6(v#NiiTKN$U0lJaZ=VJ$DFC4Z4XXC z4c&*qQ0h?1h_P_pB)OpjOzn~25)l+-M(oIz!0}YHeOIL$ess zR5NINo%y(tU%D(i4&zK!GKqQh!x^>0yZD@#cUOu6YV5*}4EIWW>ogpv3{Y&xuq?~r zKoed2jBI>|*02{>ZZyS|v^Ywyr znQuHJ#FTQEOtVob6xXTz{?iIeaQwwd%ybK5v`AT7kOy-&wYV`LVHQm{;*P-3!gb$G z_Be>6B~SRgb#{D#Z1&~qz72TYtnTPM$>*Pb^BBY?qkS$cNWK!Xjcu+B24_I6JgL?0 zIW0(?o~pScM~gvP2fQti^}MUq8hbU&9gjrd&Zis)b^gbKgBl|L`t#kkrXd<*>`u2A zl_Gx^r!UXk!Wc`>lM@O*@ix429|X8)q*u}se6Hy{@zrXcPAvH93*xa7#+6?Nvsj=r zSYvQxnwBe%pd@)RSe0Z{)@nwDl_(=ny0EO}y6dD|Cw>tngMGPp_b`G9=xI308di$O zfJCaZi>ZZ&Lp7PE9uVxxKfBo0wk=Lvq<*5p`NftO-Pp8R*t@aIoNDDZj;@bJBc zo}65+u4Un-Tx^u!$;mB>*@rD>bwp}AUC$rMe2U&x&7H#5Z{{k!_iLZ?x{t&48+VHPGM!pZU{myjziYiZ3vONjVp<~}MfeRewG z9ZDPmyT@tCpM#Rg#cI0#xyHk*g!Arlx`AM5_FE$9yn9zIiJP>(*>n=XgluxsAZi^= zRA8~63_s>40Pqu?3kcaNr;HjifI445ThCVWaLUR9#p;H%!T8^eCwXxGsw zB^gcVyr2wTW3bSl4ihTB1v0N;`rf+|U#?dZ^`#B+_52!f$_`sw!B3ZdgP=_gAK*J$ z%oU`1ybppq+opVv{?H4GSo|DG?G;HCIbzs5#fcx^trYjzW_X!4>GO;(n;n~_`qwbL zKEUDk6r#O$6|K#w%V-KPN4R-NW5k%yMTLV`MgzM9VqKyhE8Y2=USnM1ZU}<$suilSF__6_wZb+#EGnC>$cW&t$uKBkjx%rm zI>9!;(;4VnqK*=?Ei6&mF-amgdADCIC)+g+RZyw>0UY*NABgSthk1&qpNW9tKwK_5?9wjZ`#i#ScaG9;_sTnK zZtJ$kJOEnCpf3%o{pU4b+vq|TQ z5gUP**`(r^uY;94UexDtMs>cLUaKq@=>WcK{EXuo1!oCL5}t`J<-`&&Zypq6xP(su zjyCHRQY>-sfM++*10cc?{>eN~g7t&!QBtgEj*+13kskJW}6Ud>cf>{d2STnL2QNC z=m#ps?v9XH{-OYeV;QOxq!+lHyD@MA{1CJyK12>{91__CIfZEvE3tVul{H3KT(RQo zMnjj?Gg4Qcut?3LzA9K0ytl(_3r+O8Ksh~C`-^Z4pDJC*V>gs8#Y!5pOR6fI+Fc+@ zrr4Mf?GPkr`Er8#BB*37bBahUEIfm|CtJK{C#MaZu0_lzGBdg$(J>8bO^B))#kJ*+ zf`QT9Us=s@HComgW;7m;3ul8RnDpo*CX|md+rFGGCA(&{j8}-`q}Ue`r!l3qMs!%% zu#=lcL6RH9tz^mY?F$wk0%iXOQk>4n@~yk=q|L1%qt#F#DT+~OLHHrn1e*-Nl=A7m zUsk6#*l!PJLzRHqu`WNsf@E~3KD`XksbSlQ9X+ALAnNnhqLEQ@f%%Ye#S!X(<6{Ym z6^4GhfpKjX?rK;|k*c;X;6z$DRPkld*Ek0~Y*6vVTy#W_EUG9CSOWsDVp!>T6Mg`~ zTkr8F>?Fy!w2zGN2D(}Sm%3bxv-T;GC^Qw4m*}e#M&j3Zs{}>Byg{xn`NnXt6-AkA zxmk39?F`EJi>SVdbq>Tgbfrw_>#7yvhi5N1@;WO4b@-7y^@m? zdbII;Nw2(m8_++~JTc=R`#@m(2L~+Zt>p?BBq97u%n+&U8+lIU_%Ngzpr{xEg-PXo z=q8mz@oNJ4b|ck@5l>pWv;#cQ|BnE|2fH$uvU@c9APgL(%=LZTM7P0G8W(x6a^e*%z!tzTSFQ>Q>3LU1jh@nAQ|Qj-lw9k zlj&u4Qq$SB`|)aeb&DHf_iGgK_BKHl6z*ctPLggD{9y@XKEq*;u&v-#!~o>mF(k!y zLDxPs5`N`X8fF8JY(5MUk~cHA)-YgWRg0+AcNJetAp^19Y>$sCiGtMZ;+V$^ZUL8I zqPg>4UIK}XO@7A3udCJS`x)&ZD<8*}{*U<#H=bZ(C+Wr5M|2tCgesa4gQYzDqwCcI z8Eh%`xJ4b!O^1E^)%?-zZU;Xx|LFe0sfG^Kj5^=)pNYOyc?(^bUDw2hy>q#HogRUK zoi8biX>)k7y57$_mq~NJJ>esDcE^xw<1%d5GiOJl#ni3_WBr~o!*HO<%`?#tcL{Wk zo9ygH$vT0S`wBMFz0NjZxUd9pNPyGq=x=9gK!u(;{0I!vakXR#w@^#gVfFaLqx8t(^EmZ4{!ei@(mC}wgcvhA zy`wBl!d@;PLZFkl6v+O@3E`3Z&*wZKnWVdK3)Dly_#37T4sF9v(%Jo&y5DW!5sC7w zO)(Cx*YT`SHjU%K>9>A%>CVa4`_nMu=iVa|KCs0Z1zcq-!Ce^SPF_rCo`88S+>OBi zGijacgJyfF4&IhTETHJZ1r^`8>LTYM@B_YLwi7Y9iWcG!kt_#<0DCW5EIDyGZ@zgm zxp;PQasK+%rQ#$o0_B?qhxfvy2$jKja--m{qP80;np6Lkb@ItbPib&qWf# zViUH-E$3HKcI625A`&cZkOHaJwtfsmUcos+VHA|%n$xQ>3aY6(<4LpxWkMOGLFd;B z!|3n5hL(o#E#E*6n(RI7$w^zohbvMIexcy(YCvKFS}C>-ND`?WN*@nEcoJE z0klTiDD~o`l&q|fxmFcnQb`iqanf{lHThwWvXxjPx;rnKpQbDWn$po4;(eGFsXIkA z6V4fAoe*!Xme)zf1nph4oi)vz2?&Pj?2~01zPT(&lpQ{`gYl@tBVuunVHs=7U7Z!AI$z#W4MEzkY?+sQE#N7t?$G?*-0)T~Jtd(wU;o!;cq(`P1Br)Xgmch>Qfv5P7{tpW_DbrNeX- z5>=g^EPIa=rfM|bKIpu=+XXcA($s5-w@TL~O5goDaFoY-!M($l&ed+V3m4ynC+=H7 zN_@~}diTpWj(}w3kT~`KqwM1?RVsaO1KHhDD5P~lm{-vWnyfNkNp(lCw?kSUGA-OJ zQ>feNm%eA7cl#AyR_HcY*d>!^D`64Pa{}p&fh=`;=da^t>qG$77yWx)RwN8TETsw5vfQ~(t`6%^k1TdX9zD{ zx^9O$b@4Uhz=E`uKeR5JV`AHDF(zl|@a)KJ^3@U(_t z*0074{CY;=syYG}fI~|B?*?YL_WR$Z&Gq(zdq`POsMvh^5ivB3kN-ikBGq4TusWlg zRP-qo40gcd{r!Q&SM8Ts11mg*d-tfinuO_?XmN&GLEFOGsvAwa z<@-?Uu`(`0`gV%|{w0n_P=TNf0WgfOI9B?9$Hm=s;6*Gp`A)WaojLiG4`4TTMB&=# z^s0v`x;#LQLU++!v8p~zVuN<$iA|H9km8UAq)5UyiEh)Kxj%m|K3TpJ1McvZe11HB zEx(?epwQH2K3xlv19c2RBj1&EX!=fgs0gF@pTIP);W&0teov{uipz7@gOYPb#^HEc z}Wq-@3tABao46)Ih$vKV_)OTo4uQ8x4l$AYWZxGMSn zBW}y!q|66s`Na{~>{fehx@$@YDCKUYG{jPe{qitvr%lN4P?c69YYynPTBG(V1$&(;7V6R>1J9n;UZ3$@nWI z-*gdBG69-ogA1n*?m#zn^lU(0F=QS@DwUd*%(vP5Wrss->*>th6ZG@4b7jOBtlacu zhff*$4$J~CQEeu4&pYGSZu2Ff7bS^*IUg3r_|@G6hdQq?5U)AaR6*{%qdQNou-ycC zGY_6UeTTa;{+dq6@hrWfJbnH075$TGpt6}1n=pJmZHEEq29{pm7VyK7DSJ`E<+qA4 zFu2YPdZk#pWM*UuPU)xFhn-16~Ti?0$RgDKRAs%1kN zW99)k4rP{w5T+KdF0@&VGA#tJJoRLCtrx^9TVn}%x`Q@f?!)0s@u1mg7~e{9r!Jfu3{(UI4Hk7zs7pi0S+_7N2#s6BxhH`W??HeTRU|M7NE)O(lCSPw zT&iV*yCPU+Q;rH6Tz&!LSs8F+vGcfz0O0x|PjfRq2t%h({A#D+`L_)!% z>>7>cilSnjuvBW zMJ^ZXuhbnBXJ)a>?W(NcyjWlnx8n__IAyQ6$P=BWj0y(iXj>HP^MD^dAw=8Yc3b$w zoDnpXxc;T6Aab5h?xu68fydnb7qKNKFT_P0Efv~NN#qm~9#NvBME8qe)qjjqWLQI3 zIz+1JYdAz5KjTu>En-ru+N1jk5%v0ZgUzIruj|e1L#3blsnYLwb7E$UGN=FJ88X_a z|BvU$5ZCf=$%F@XaQ`uCF8H_P*szKE;?>JHt);EHs`jz$bzhF-g+t%fMFh^rOYB6|8E4?k!i8I{7-jZ(ch{6;c|3LnFO>aJK zVr+{pbZeV_z|j`$e8it5?4_6m#}4ToQ1BtFm4nJ{5gKzFmXr&g@y{6FyF@3oqIBSOjHW9@^r-A_L@)chkUWxbN5{@h*)^u}=IG~ho@B(Li z5nEEDHD;jUbI;GDsmf|6%tQMZc$KkEF9#ouF0TH7jHNl%=;5~xSV3EBM}o;4PpLO8O^>!l73aYI#U8K8qI@4-%*B;o{!NUd zkXDXRRMmoqKQl&LoTtSh**Fd=mhnbN^MHsl{%1khP(ZG}PYWfnMs>!jbPPD1|Ns%Xf}98VLzTyNH|v zwYj-K*4+cluqEQK+T-d~tx;$uqetno?(u9!YH9j9kj;Ale63&eP<$s)p8Ywo==FvI z9Xu0Eryt!^C|&hIro1D`*-6cJDrbQ~diUM5`DAWk4O}tD-}3Wu8Rbv%<1ArgHT=l# zOGzZOpi?;2?%_wfyKsf6AeP`C1wZ}`XxOf_j=2dZ>|+-ll;auA)T+U zktDfUP3S!r&je}5%#M3>a5CJq7Zg%O>XGbYq2Ze29Mz3HZZ5ikn;4AE9I^dgwr>R) z*~;fo)F0@I&Sp!8eXpFq2~z`3%kG?4iV>D)qT-#*k_Oj3(y5D}cY#>HWo_a?a_!=z ze300;YruVk8ZA(r#7(=@DBi*32sWt!NUPZaU#Nlu}ESZ zg!DJO<1Zxpf_GjkU<=Tf2{e^nj&goqT1Ms=x<@Y0!@x{AaS??F5H#HA2b6L(KwpWH zGR^`re*6ib;+eY*kC`SkZG6E(@(rn((FxFsr2%UK^pnB&CrkTeRz3!%WQLd{ttIBw z+;O1l3lbd{t+ct;P;ls)%nZ&&HZ_ekhA$39>mlQ`Oa~{<p;zZI=JHm+`8+0l?3?(e*sO((Ig7mFtr8HaAUBl~m z#sENzgbG)~%L4Hrm=qcR5%8UQV6;!Q$It*>EB#x|xnZR+xkN@xj$JjJKq7$M1p9A? zbxh`##(4cx3t9je?aet?;!E@T1enJ6cE7_TlQNsP2fbb0iRS6JiTrc9%?uRq6>r6s zaZh#`;}8+!dZmTR9iEW%C!EtAi1;snD;_nty{Z6o@fPJtpSMsV^ zRLFr^%m4Eb+bD>@K@IetAR9ed?=SJPAJO7sn}};@ryKzI z5IgiCsO}I(s1M13h)RyT@TL#N03l<|AZC>6L}Jx!7OA$_p!2Nz$mCQ+&3tILIB5L>dOClsN#}-MQpk#vBi^_2$7q7{=RfYQS{MB zD&~#PS9~%;d5feI<@mad`D>}r>pN52*nP#pJ-q^5V{_n6(?uFJo$DY5Usmg_t8531 zd>FFm7Rjd?4wEg<_kg*@RQkVA4go<(AW$G?MadanP@_RPo4Ka z2Q?3hIK9+8-7K&lUx=Z*y1qSC76`qhPfygRk`WQ!gr2r7fNsBUcjtNBiZVFI&$qi1 z+4M%t28uF9YK^`HOw<^Mfde?P&B2<3*r#bUs)Q6tpip6yZ<_^G zKV`hhj42|dxay|g5vZ7g8Wx8+)>ortVNah@#z`{cPAO}N)BB|zbvTg@ywG5@j*H`% zIc^=5TZu$3)C8~dAY~9)1O$uqz(8r}U7I`{q!D~5aEQ-i(3AW8mIRP}0LO|v%U8&& z6w;>rOJt0)D^vzX2^p&Ek<0d1IdQ7je0I4(?uMpqe!yrk{qI1JB(Qv-Tr{06YfTYY zT`gq$_mG?q0Q}f(B$>;ZDwkZdX-7dS?E77Qq^if1*3CKK;&c(WB42lO|Nc?}JD@Gk zl2tn3>JOdy_oI0-_Xx5#Twd$dYI#o8n(21GF|=^pD`kQ*4Y=ie9c`->gS+P@mFR-RJi zrt*|Au?zaK7Eg7)!i6HU_)8R3f#fesVg-7$Zg*p5iT~9)Z)5uJz|CV+dPLuQn?t`u zqo|y{GP_j1mmaT`lVbMiMh;oF6Ua^##nWL)Uvp%n-*c7RG|1qd0t z(n%JKi0i{Xq>kUcDA6RCqZy1NJ+n34#v9DfNaUgX9J>ZiNmV-yUI0*%FS^BgCvS_I z``8dR?-Z!B;%fWhu`JfAV(mPwQL z!o!sVe1A}xBgQfMG#v?Nf;z-@mL$U{!90G zQvLk?9wlnodgbvi&>%NG_{7&ApxFK$D6WF&o1Wf@45};uy0#ZJ~T;Fy$ms*_=if%92x z-w4i++JUt2gAi~XWMZrlam)joH=!(qpNFB({w8Of#qn(z!}|scr((h(=_BEydknBV z1*Jth&R3CBOkliX0x5)BkvZ8Zy7ENkC?Tx(fhBPWW7J|-DIFIA+D%)NN)HD%9m&Bh zGs3;F>|l<;)?>H0Ggb+>q4tDKzsI=(S6FSIRVy6d1-^gWHjFA(X#cvg6 zkJ#fcK-TO&3UHu!9&+zL^Qmt3hq?@zChG?UOzj3k+BX&y&xaio07skKw~ey{Zu^$j zA-#@KxW}zIdig8D(md-CFSGxOMJaf zjw$17x=>U+(FY5Lok;Lx>yGUc2}XwlPb7FqOk%Ox7)5sfp#~J5pWNW-XevbA$wgFI zE8!LtPEGpy>;Cf8eB%m7`XXaV&XyQ{v6^qrVm-D>c_f#(c)jNGl_Yf+DVG4QJ1E&c zT;XIS^bk-2yzIb5+&ru3SNBf)TU7qR`20N0^~y!G_>m8&<8RjqT7wc+tGny{+Eq3X z;;EYKZ0DW`OKzxDhL<#1b$nH1?zll6W=(QYAavWkr{hPCD1RE}ZaUlD;0TPnawnA1 zS0wv4c$sa(l=2U`EZkdEPd=W@0T`Q5fnZAK(c*wJp(p^**tW~5A_Ez+O;y<5t;nk*`Hmm(N7^PRuR1)^hGw2WzrY1)05eIc*QsT$Vjdys%=ma#WiRRyiER*&vw3A4;q-dG7ZXI z_K%o5FhOF-kk9a%)$;oJYz~){kL>;?L-;|FSmT<5bb*^MInN>-c1TeX02&)A?j`Na zz!lXeCy>c=RH52E#pT8-aMWeweA zR~;D?{~MILm{YlnD$9ln@8$eKU@)%+BO|_u6g@t#O3Ig8xUQc{zw_T)aMMy@MxaVj&ev19 znf4GEd^6o#KP*i;Zh8m|;W_Xsdb0LBnCEQ4Bl!ISIUO0Bl<(kyUv|6Ol_Ua>s%rrdk(a;p47%`vKhGU z9vOM))m%%+oG%(;VlJ^np{nR;n`y4Sj?LTcwY@Z50ykt;8OC33&lOg#yBDiFUv*^& z$-3vaphUw*Po-Owa-ua*;L&s0f<|%_@;G2+zfYOlW9V{!o#!7~m^N!-N;FImd1pdNpG)ARA zn1pPXF&zaru2y?@T=ghEy-ciXvHyCIhTD-OWrN!abM> zwHQrCxS_NM|9AuyynkeQzu<$LQvr83wigpbQB#(89zB|7hy*vsu&Um81U}F8=3;_L z0Mau4~woEEhA zCsV+r4t{guf!J2rB}|4LWL}Xq=B8!>Fk#S90%`4ZCPOar-OwIa9>_7aLKDD&IXwBF7x~uoAh3$In6L_74KP)M9)PcLWc3?7Hd={OhNvm$mz0tpmo-#b z?1#t~I&j$pklFIUOrc}2!SJD(BL;vlRPidqWJoHEp*$d2wWQjHPSW>i&jp@3=3DXV z26AFGgFJ3EwX@}%Pah6+<3zF4iHYKzAdZ?N>4!*|>-7SS3&&WFiV1gGZxh*MflW+;8R+yic*Zc5fh2 zy2ux_G<9~5IzZ_rqZHW)-*wqz8^*R%EJhH4uF5g1-|QX7{kD6i8Vv*B>lE=#|M_Yu zr`wat8&UzOS`HwPqoCC)D`{Zy4jyT&{Nkn)S*O>g4>c5$;$hd8^Liut4(llZL!6)6 zxWa~1K_Z-S*wE#C&cL~;wAFbyLRWK?Uh-&%Wc? z{cIZomlm;Qe<;q`?Q9-ubBQ0w&L#$_6z%m?m#o=z7foNu6%j$Nf?{xnGsS~K{|q(JsP+Sw z9pd}cm4TPty% zT|B?Bz4~E>TR+_FH;)74&p-X<@w;2Bb*Go}?(+~?gx`r|J4zA`B~9-T*zV;rPNGbz z8M$LbR-WD3|E7&lOh+1Jt|x7G-d6@JZT?~w;+*=}Fa3*IrsqrHVZp{#1Z{y4tyV<0M$n~V8~CTW-Sc5S8xTB z7O!7kMmHf5;+hvmlZ7nJn!?=fudZOo9@k_7JfF|I_tW|5<~>Ix!D?BLYYw^D>F4y% zEkxSxy4ADpz3aW|&b-;D?%SK)&ih<_vvjpqNQbO65Aws2ZCD*@3Mx-dnNe@KU>Q}_lhz-v>`%)L((`ClL+6JZp(E`jhWPR9ffIV7PH8l$BZt+WxGM)pJJm92Wj`&!(Yc)pxRO|rbEXy*y8sUut&vpJlY$wZ zgVK9hpFs({8F_<&S-cE>H4T-uL)@>~3&WYytpXVoe|tkJ&#aY@n9CM8R{Km?BEvC5 zJWQ@DL%fyn!g6SKGowrmR!1l|-@E3vI@G*!*%pr3dq1)rHzbLpWL+(hX~JYc4-Ob+ zkc{le8eM+N`kL*?p|LaB1Aw&{%sQwF0Fnh_4N67zLo*$fzLz`GlWp zejr88+Rg|dGUpqz*WNf`Q5QyT??|9Rx3A>hXNncxAX^MQUvKQ+^@#p+!eYFzU%DNqP` zSdzTx*36JMS~u6`MZdn>c%wrzPi^;WWyM=PMh?}J4=+cOSHsM7ecJrMEO-W_o&x8S zqE%&tU7C-4gkCkR^bL-8!4c5m)pBwebQ~~W6>^(!ds&^m1PgfQ+H$QCaJbT5g-b7L z@S;P(78h;6sb0~~{Uq>Xu;FUT07R=u4n)u~%V{qKeUW)|z4nJn5dlS|I^vY}&u$+Y z3_73~P8`@>m#vMSv$h=F^*`XDj0^?-Q_W=V@5U^c^*>yL^;TH~8g3CCp&7VBa$Ijl zXD|pbi`VI879f)K5CKDk_RvhH{pj(}L@0c?e@&TtOj%w|u#`}K3l(8};`JN+mx>L^DJo0dR15}2O+9v=xyU#vL-)Nr=yD)&x1s=LDF8lq9wel|YWM>Ig1Y z`gkySs?Ns&E+C*5{*hPn=#wQb`K59y3WksLff19uOoii_?I~g}v*ZR-aVR3K!Wuo; z7!@dbN9h| z0|3m&DjGk~uEh;A3+YbVavV>NSK{d1EqZdzGsPO+z6GL(j-G9MZ@AccRIvTL3^Qo# z-REgrfHu z6YMHAwW9-MC{^zn++StNaJ_ZXI~hH6w_^*KA_J(JV(4#A8{Aptybl>W&4t?#TEy2i zdI<7adVAFHAad#FBZg9G z@?@Z9IqZS(15J7EJQ-=ItlJ6o6eJ0K?w;^H%&kS#?PPm0T#u5Q&fOoztV2#wSX+6*m4=-muaDc`xLPAuc-KCOY#c#Usw&>97 ziP~=%IiTKzNV;C>w_i+LD_af;lwb~a2mst2lw>1fJcMFx)B`P*X_2Y>6VResH|Jo{gYgIf>`h}8#iR^p)0Vmxp1`X*~O&fBiEz5|N#=v9O zc1uPR;QtUm>U1ZApgbI>wjqdREQTC`@JyoL1Fw4zOegqmc+03S-2g zxx$ltPbXo?5Iw6ctZ7Xx*-qQ}GZ)$_v8Niv17uQc4kctzG2y9yi`kCw#@wySD(ZU8 zIPiiM_m)yq)k`gj>~!nqWtP|wo7BVZSY_y-U-Obxt9kR5RoSucnpLYu^YT-rW9y<- zv&-1Qdaha-W2JYkNR!<~)O4#NN*4(MOu^d@w~3`LpCpUdjk06e$c>_7aj3zHlyqt8 zP^D#4eUd(Xnp0`qlw;Yar7yMCBZlbFl5~V#1&PfM)C~ooei84Y+n^xsuu@o7TdOJ$ zqQ8Z!VX2p1_Op%aYM*P#xFOZc(nXd2J%kTMl->M#rWbZnkf#gweCl zB{#b?y=JXv%RRUIj2^DXRa>L=I_$jDfo{71Q+M9q?q+jT;<@Jfw0~L5MR(P5(?=a} zzW0myMrcU#ejH!eRZaZ>-S%p_?l{&s;}ok)fwWv;3+b?gvU8xM!BqcIFto@8=Mbi0N0Gy9uA+#Q*1q+TDRp>W&4?gjPhZ8nvux zP%(aa-IdpS42ssbv*rESe1>NW+M#~Z5I549eV!f~7uYbNie>nO#8h`*Oq+`ZhSOh} zxycBZd(^6`Dd5S=GT6Ru`Nk^uXlYUeMtyTcVqpAb3<)DA+KDxe62w~6~b?LCT zGoTB7j2nE(2q;j#O#EuXntc{+K#w~d}_leZJueIDS zNtw+nV+lwMeM%+t;g|LyEiOjNdNRSN^iy2{0OM@6T%vOLJ7fS>d&#Z~7|ILKS3po# zDRMM8k@n|q_Wm{)hXA%vgVJ5@cl?r**E9%*^X00{BR+NaSM$Ak z(Z^7&Fv#=yYKltP%i>*&%5aO>GE$GRkSS089y9j%VZAH!gZjUQ4f%DqI$h$Vomib_ z>wKE+P7(2_jm_>nvKq~1J1{mOn3`o@ORERFQ)Snq8$zYh_%w>A@cm}BU(;-&jj}!p zUPs#DTu`pOmPAb;=T9xkc*&O{uwl^Da*Pdd-d4Pbu&X#Ulq7MTI!+eT-PLUu=UjZg z+V9Ynxkvb$81qB0Mn+^oNfIxMO2>QhP#?)!{9u~vt&Y)EKe@Igx$V93xe9XWNh^g9bRPrm0h-l_O)QD$#J9DJn& z1gWR~JQp)?Tzr@^zgZ$g>vlb#Orhm)=Tgj4>X7lv8F@K9z_`IH8xy=e)GaAUcJ`tO z)(|IG$cB3fG{NSmDEPj6bf;s+m$yQMhd0ytw)@17i4ba3D)cuF^5-XnpnLBlAz{CN*0l} z;@2f6D1>`kFc-fOFxP|~p6U^v0P?C>HojQTpRV?o^N&aaecxTb0Oz>gbfyDAhr6h_uh48dDsg zQU0L`f3|(LSnniw4R&baAD2? z3|W7e$Y7;#I9YWwGoV$f)+>3HsfX1t+Yefs>k#+Byo5q_$OCk|^5mE$P|RmDyv_Ba zL=egmo6SeD;Iwg#811;zVmV9+<}D;!P;@VBVXwi%LN7um{(*d zaCtMu3N)Q7AYaPo)6?25ltvieL52{YG)XA8llX6hb1ya(SCqhL+aGigw(aC3D|c%V6Z=L zX8kx(+EZcWRp+&Pcnuza7I)hA@d<0r3GyS9Bb%(DE72X3$5>&v^xnB>&PE2D%)Yz~S)^g5ap@n=G=q;z(X-9>no`XB%mnhT~pkd4ANVqufj* zeY(|6MUkY%&CNVUXSvRXM(~_h9+0*bqUd+O`|RoJv*l{{*=2`qmJi)$w|GTyd-A*A z-QC^&c7414?XuhbZZTc%r}N)+%inF+^Bb7Jiq-44Hw1b6;s3&Qvn{e4Uw&c!{Kcl* z?KevfDz+SqlO845Z6y@t6|F<^kDr)5|M>mMXXFF_>G;I{klZ11E_83P+hod(*W9s- zvESrM?=~)UW95}KGNR883rp-oc2N6-qri)g&5?0WcCzu+fHYrSCC&l>=nVmWGED+l zeEZeiKxb# z-_Z)^j0xb2fNiCzyq*-v;*^?2SIk~iU{$gf+RIf}!n%=CJef@Apk<=e&)_5`(t_>M z{U@N#WXm4y(QSaEGs@}25kaS#S`2I9pv*Sfr6^br}Od0iqi>oBxvI-6}{l>^gD> z2BXB#blpYPISs*9ro(U% zF1!QENjHfFl8=D3+fA<|!6Qy*m25WwF%Akk7ARe)r{Aqtm5f_9^A*w=~&q9=byZZj*WPCqoeborT88T^?vTK=xz3Jk9 zfj#>U>x@M1?Ehu%-J9GxZoJ{Il0TkGo~?4WVte1Gwp6LO6v>X2m1IRD=dy8%#UVK} zjCczVsnK|y@BaP(G|=eVIfpYGW&cR5Iqb%*0W`WBjlR;H46hdN7VDi~j5n^^zzS$7 zzFw@i`#hm-MdvSli|p~I$ARhX_6muLGvwek!OD>MhFH#Ei|Ojv@Hf{qY;gmYxAT9p{fq7&DjxD&H%n_>JOCSN)NVUPx_i%OTh>1>F)1#2S{fEzs-vy!6+vV39`#$$JwrB zg8UliAhuVW^g+2KB$?~LsbDXZ{`%Dm`xTqzhsD$DYY3;@2rdu0kmtAKoW)DHG8#zD z=c5ggt0gKpHGjoH`;jid;65Iv`ecz9iDh#5sW1{)7%E-Al;jZhf|67^4ACAVlL_EN zfMBgbd@A@nem!Eiu~{4_x- z+hvx#FG{V*q@7C|31d07{}s-*Z=TZ0LLfmzXmYZ|ip*LRKfBqO>5_X4Z3aG`u?DK& zX@J|)-7;@_PHLoCP3b~p^UJL*6EVfoj7cg;r<4ow^>t4pP%p8c{${$LYO1ojMd&w1 z2m6hjSwGq0zcwO4#e%@;f~d77R1(;O0J_dmn_(j6KTcP+9ylHIeX!0}i)ooIB&sEJ z^-a~%0tYilCsNgwT>Zq1B>?t7nbc=oK~Bs*Qv(4^XXf8+R;rP?PHCfxrpT~|i@M&u zh_SMgAVNXOHyWXugF+MNAbijy88+&Pt#G6gK~pdRq|;+SO99h_?gGV#iBQZhQG8M=G5P`z5N`z0ASkuWb1u+dX zKjYYDGR>m5ngH|;M&-5&hjjEiAuhr>_!+*yk^cyrq-)s{wB+Ixx)f*dEhmyy4ecPg zUc||skSSm)?0f4PukgaEqnJG8M^aakR3;D!;aXkcHP_V1g>XS_$lSeW&b1PM=d(3F z2`TID+J_ZRfu)|Qn!30TRMwwf(&7mH>)}%}D@812g&2>CX1WPt^uWZqM}%imaXpWU zAsOGVVL^x@I;*>B+IH*_+GHFoH!VZ~rmX6fmUxlZoPVNRu*@O{*7s>uk(6Z1v8RERX>DYZ7V&<2f_qqVl2_ z2cP+lW{nPwPb-u68Dru)ecyyPtAkFSNZv`YaZbRQgUTE{M-sB}KwBg_Uzj33G+xT_ z*`{R>WoweH^|K91v$L_iORw;#o<1j@(SKd84k}iyM^lr^f*=PgPW}&d|3Q-i>1hSW z{d|0m{b+vGQy{G#-RBA#8AQrx;H_Knp~STKMis%S>-7xy&u0r&)cB|M%rU|p_jHF6Dg-X?h!Dj07eIK(ZfBG z`$-TyrVH|j9?=aIXdcZK6`1~2?x-N-JT55#dk(kc0gm+?NuLwEhwnGS*s$}{?LVL> z!}W4AL8{-TL$+U;YJighKDmW2PPUk+FK!6VEXzd~W*tt-C_Jck;5wt&=epYZ898o= z^kQ?z4T`L{J?cqX2LHGYo2%tD?zINmv=7dDQ0y+N)CURU*bIEe9J(M;qA3<4Q!zvy zCC`i}ytvnma3l1?5Kx*n#~Tt!gbg*4IPZYyRKma7ZC&~4yM3tTS)503_vF;f`0E)l z@3yGDp(}=&V#83kD$H?`D$R`07sm!eEw`()WAYjb?n%oj1A98&5H?9nD}Ri@%$v*E<;7wv2^rB(`uA#Z@3a2xDL$qHkaH0aMldfZi75TkX4IJto zI@y77sqAjts2hi2MX#Jbj0!h=!F7nC=Rqd`;c1tQp94=@))1TO_ZUXVscO;H$bMT( z9k$x8?>LEx-VX?^5 zi}kxtGcG{FZ|H5YXeWoQlr1zV$OP0mQm7yN8LmawvY_aPd`DDJ-+V!ZFmaxHO_@EZ zig!2%rYH(%)!0bhCEIBy}>jv*v(z)}T3A#5>pdv^aDtz4?FR{=io}yk5VMsgv zQ2zmCE_OG2kd#e$oJl=VhWwAIbT-?KkEDK*q513I21?npTgK24kyXR-Of8fSZKI8+Yhl>(DDT>qRKg)iJ>BHzY(LN)hPP)J5r6Fli3Zx=5!OtObvO{fgDj4@KmGC`OXy9`u#jDZwFy9+Zl~$RVUFqBPhcWncN>_R%Lxiu_1Py zqb7~kM=D%Kg?erdVuCdm@K(&8n8p}*6=CNvnb9orsZd6hSDaiSxWm@{ok3mSSI#M% zGY)-sw{~M;)?48eukB)O>v#jNz2kD+jD*}f8aJ`R)j0E`AwWsWI1fe_{z!A{;mEV5 zD9dOf>(LC!*Ni=@02VF0B{6is67#adnI^pK952L46*wWyR&lNr5GxjUn<0tj5_>ek zS6O2$$9c`-Kk#D3fB2HX8d>M%WOlRc z{&9>qbWT9iBcH{`9aa^%D{~(a^}yA8mnTpOag83<>nVcU#~stvbhnz$biwsVe5|(g zz`;^eu^$Nw;#=4y3UJ}N!zZu?tW#%DsXg7;yuZ?(q7Dw@ITR15|6{C!ai}%meymZX zT9J?J$adRh*V*mZ6By}n1@{n3547WENn2u%Yx{We>yj!)X7kt?9r_maJ(qOam*a4A zB_a!66S@s(o;l}>&7>iQ^kFZCWrN7D{wg_~7D}jIHVfmIA~jWfTwhaZW#d zjR`9SiZYBT$X?;Mrl*I%9Gr|&;Joo`y0TkF>NAOMs_robb{hA)H6ql;jG4k6O(cQ5 z!C@+S+#vmF)O4!`|SCw zzOUixQ))&yQdAUJZ#T;s3eilpx`e5%bLw%J-XHe|Jd31)2jEjo`v6>U#0dkzv5l$CTe8USLb{br-|MG#&Lt!JL88aXrrX+ zbW`C~XAuLi%-liP4`+75zjwUT*5t(?m~jRNPy^M=40VwBg#K0GcA1)JK(IdcLrrBJ zIt59Gzf{f*yb=-jM*m*dFmNBKOD|b2${wY_rvg1qM^A;W17#+D5B_Vhzc)P4)b*QD zFBOIU942(8uFfeBLD?eYFmr-);j$^nk)LT;{WdB`u-qO0mx?{30f{s5ey<+%3%+H`--GIUGG-;W;1g|+oTpS;8=cuu*ptF(Mio}Hg4Xgc5Ojm5j0qQ1=hp{yemq`eY4pUM`S zV||1WgF0>d4%aI)AQ%TyInfWYNorT~wBweeHQh($(lyFW-c&=xG5@j-m1Nk{+BDDQP>Gt2>cX=SXLX8B`Kr zrX_(~yo!QrQ6y?Q(jE_n(}y30KuQR(L*euC&Z)A2=qS6I{Bfl77K2I8o5i{+rk;%+ z7m^$CLeDk(Q6LHF8>;h@39$y7js|^OBcxdfp*r-HqheA?)Rti{9%n#k!o8FNQ(-AJ zN&7)INh~}=@RzgwHq@hG9Sze>o$%vjH^U3{xvZMhkJn>V7=8rc9XT7EIGx>y1K
    Orc8@(Ym|)iLjvaU+>pYritQnOC;)ymPw|*u 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

    qhpk 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�`Y<@moYEXzX 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

    d>TaTds`5BbG+3`@iV`AeQ2GO|!|MLH{_pZxr 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

    {7ew=T+Uh-or?~71qF&68VE@Z}M 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

    BZew*U$hFrNhC9l(PS!LI?7 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%0DVZJ%HhRKZSxS_PH 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

    RPTg;Dg%8pAX`65$^jIuIo5k|}NJoL?M<{L- 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 ?{(sg58G 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

    KN0Q3Co1&|771(ZmibiL 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

    6%W2_$aTI+8%J6l%*DIYc}pKQSE4KJoxJD7 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�+ZtBHO!pI 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%0D0oTZtPEX;-&)a{7 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

  • L6cn|yz6WdYi_26 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 z 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

    ZR2riVc@^ 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�%IVxp4_y%izry za1P>n1kt>gu1pqNQrEAqDaQpuP4{HK?I3$KCVy3zu^`k&3T-p&F9H1{O zl`^9<6pfYsmmuq-A>!v~@Kd`VNCv@zdLxPaNvfYdhP;yQ745QsRL+eNMmWc%16vBb zL(pJ>2q8aHXNdY$$RNCP-6#iu%M0iD70%2!oo@-W;TUcv50k=(urQxqR`QMMoPvw+ z{k+8Dv$v8-VzqPK5-WL--W+qvY0*boNzjIJq5-2M{g7)7-3e|^RGbc<)Or2a5JZhg zY_TT9Md#xQHmSLUR!#tn?;fDNZ~er~F)3_SZ+gQsRQ8SSx+E?t+i!%506z1JnUmLOHFjH~=%<|&R zNf+l?mn!av_vH3+cNlORYyArn4b>MuM}R%!7sHk?=v@(;>WCQ+8De5<&~Qt$u9C~* z86t+FI$P8sVJ^jrJ+}x(*86=$3X&*nnB}hq+M15t%s?Igv`#c^@LV=2T}&w|fBEYX zQ>bC9zNG3lWI4$%;&Qb|^E$4~qU%{kMUIRI+gk|L*Wjnmw*_~6!>-Ju>1%T$d0=#*?5@WNyogY^4mQK)@9PN-Q^v3CB!Xp;M{>&*GR3PteSfe4Rgh zxu!E#a8q)md=R-lgu_IHyP|7&Qd_jEw}2LD&u4vPVItlm?0S)s4c_N;y0V48sH zv5Exd+~W>F-7u!OV@>P-=)5b8k}BuDthwa7Li*OGS|<9Mie!q!CaNWlE#=c|1?%Uw z|K8r-{Eru#JG+|?+dpjWev6BLh{U)5t@Ea%mZzfM+aEC_D)gEZg&Z*JILsA7zQ0xv zkVV)$4pE|&&buorYALzfe)PugyNKPKTp|PO1rDd0IviD%#MNx^7eCf?#*T*le(2m+ zy`hkFhLpC-(55j7hj7z)cw}-s8opJZQBY>uyXU9f&CzJ+4Fc!j4rafxJ z6#qow^uH7`{1p;a6E+eW$+4No)&LjGpaaDp?wpdpY&;n<;ZJ&goQ*VJ@US!K&??nI zXxB-v--AN7^>nMyIxV8nvw%9!$%z}U602v-t{Z@#!=7ke;hvXQ!vb5tk@^BDoz>5`&=1 z#8P;Je;u+J->AU)dqZSr9^=Ua7D8;@SiONJTsj}9WWgS`P`@7GDH=KOOTs?MM7UXj|LJp~YmHG) z_GKHJ5$s47rhD2#iq4} z7-81g$7&`(GkR>uRC678lmQ4P)^Mt8R@aIlR9+%3Xtc|fWNM_%Q5QF|7bp(%&5?<~ z*Er+U#!?xMzqWRTJ*KkrU0p}0>~y$|m)RUD5NYEULU;=g&CS~IQiJ)uah{~zQJAm9 zvvN!}p`_w#sI3Ujf^>7p>fG&c_jjED^E@V*Snr30$S!pDnIHJsH$)iJ0K3@X)3^V{ z&6;NH_fFGYufXS#nGI`8NMYJOW5U*o4xU_T&Ss*{IHwjL?La23HkyG<_R3g+DpJ`c zn@sANQD>=N;0oKd(CSU=s@(~$h1R(_`?b)@Kyu?tc}8v7`*_ZrFzS?R|1bPZcJN_6P1ZgC{Qq21E=TEja)_1p_JxxRQ znP!Hq0U=14arYjo!a;j)v0@8ne5&=JqrXgM)I2jd3nT|0;}oB)-e0}{X)Gv!V0=cU zk3gWY5b%vJzWNebN29ME+<*~^r8F^|rCqg9sIoJHuL0>7*@ypG-tqK#MeV?bhe9QqjfWX#g&D^oIwLox|*7&o!{uH z;wdmTW&7aUF{he-ju_1JDCr!zP^NS_X@VX7l2XxyzDRFEvnml5NRObuR=!OVA|$IJ zM1Wh)93Ett1F{GY1C^NfK6Paj`bXB#QRj=ZQ<`+WW%ozwD;IR82IR$vWZ9`(VVARK z=gF{h_^1O%+@ahPRmw1xR`+E#il%3M

    q*Z5wei^;}2G1QdpckT*$o1nce$kT`nD zfclh(m!9jm40O+QWz0yEY(Vtcpx;9hOQ3y~gVxrJuu+^iP0KJA!gPis%i#qV(Yq(z zfQ!TxrI^?8G59PFVpU-R@1X2$zIablm*g`*ha?T&V7!*)*vo~I+|hY<@kiq;b$$^x z)6PK!b@p|hN$dKyyGPD3Y?`dcRHAE{I|Hr_(>reI9)oMb{EM*?8Ffzd*5;OreN|KZ z!JQ!}Oi-amFmBL7OsTy!b`%HD7eJkiuV|abV4-ZtR{J&nFUuJD`Q%1^BQ7lE)qW6CnYfh-v*K6}j$pHNB3WLKF zwkC1WF;A*qYl7}b&1(VBle5vFkcc~2XJESN_0L9ryXH|y@T3ey8&HUs6ZK%Gsf4N0 zqasUy)#jf~?{o}#*q1ftjowu3QfgozC2uotb)*I-3t;tde}2(9Z zS87c#*2Bq=ODP8^v6f8(;BcWXsmdofNE(`0{Po_y(O@uOKTORDfLe9}&EB(K)4}V3 zon}}&8w|RX+!*SPu~}S40&6=A1`P{MmILEQAEt=Pd!0kX<-$@ou!FAXxe0ZV*r0le zTzCX&3ikyyBf^p_qYvHy*@21vk~|+K9MxVWLy6Cq`)n``ywqi5p@>ZZ^$sA##_91W z#caxw3=vgBpME#Z(pRR@n3Phb)I19VUaNG(c z$>aeCiX@zaEqBksFu0 za_7IvN;`xLUS?{>lh`bam49`vInh^Qm1V?99Fy=tQDB6mM0Y@*OQ<0Lrh?-QyP>2a zSaLrXX4hTH%1|``@(+utc`G8M{)3rJy7;(pZWa%Lqs-OPmGHnLy^=4EbZFK1kg~ zTmoVm3f>dgZ)F?B@B+~SL@kZ0kc>7)0nLMB=8(9*LO2R&{)jhwAw-`Fkb#R{m`CZR z2cVjnlna%L=(KHjRqTvAIqfOMdiq3IMApi>NFJB80hcKteOAE2CkY5yjT;2u&TToI zfgPkC5R^GOePE!66)d<7vdhg|@SD6(g@E4AeX6wjJH1cmv`fT5P9cUn@PT(nV1Kjt zvORVcoS8-JTH1FdUtkVk<$-<7bZruuZ zerJDacJW1 zZ+G7!i@00a{L2f(NE+g}GdQo!UaqIWbAnW1Z?361>DwYfPqQt|7IWKj=IV@C0+6Q1 z5SiI(p?6V?t#_2`Npw*`$8j1?X|uEw1WsBwVCDt)r&ZegXHb0HW2u^GsFjEEbv@~I z>IEObQE-F_!j{R!P30DR}YGzzEF7i>_^ z)*dKe5DaW#84^r=)H_f|uSDp{g$vxuf+gYK$R@ouOUSWGcuFA-s)ds17TOb5($5|V zPcG}ClMR6&Ad6oS_`_ccoSB{>_!}rwZPANTw#?j2)j|*p*u)H9OS_u_)AZ}Y>b2e} z)|YMw^F!}bHDkwi@3&wH6NIOsNKJ;{kWQLdeDm8RBpR)-&9=7f?yK&*G`RKz9lwgB zKAJ5cqQPtros%Iee1aE®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

    @TP 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

    mFR3t$HE0~ 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
    do{ZA-TPbLfd$y58A!=pd(tJN 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≻5_p2~ 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

    H(JB(?y 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

    ju3DJBkuN16GC$? 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�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%0D&4DmyjmjxzIIFwunZ< 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 z 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%0D(Ln>jKRJUTFe4_2wzGXeDv3B# zQcx%w5$&d;dJ}UXQI2dMk%Us>L+D>c?OHmBm1e|{ z^)Z}O&Iim-6_nRSZHn|v+cj!S3q--_Nfbu07pf|6zQD8~FK4MTt^XuStyk7q)_?h1 zuQ#oNd{WVA)%$gor&aHMC_f!#|8;Wl1=Dt)FBh(ZcVh|eo~G5SOBegesaqH3%{AM! z64Z(Qr~(-Em0-+61k-pKO-I=bRXoCHt*!RPTnz@2;?zGuwc3t!1e{i;Hn1v}?A@Co zE`E->PP59qdpbs?+Evz-?ys zO`F=hw#~VD)<(`Y?7V4B13G*j>8NT={44f$H&{I@HUp^s>WoQ-StJsY4BkLS;x69w zBc0o z<5_Q?s6%YUIH9d6zky6KL{+$X4=%f}c&cBK9{Em|Gq(XNM*&fn3&kVZ5C+_h$_`fp zmQ)DADbY47)&=crvi`h=M9y^{dUw6Jmn5TR!M$WQ4&}o zL3(nFc+FW=s7zTfsz3!F$wh3uE)6Wj2`iuD!gWVcr0;`O!S582@%myt7QGStT<6>v z2bJrLWVG~Wg7uZJ7JtGpVx=!)tB{jCu2Z`Xu9FW#sFkRib_$xZIwnzp*G zJ%tNdmKh)bCYjzqp>i@Y3b}M*kNP8ws9kZZr~W1?sh@akfmbl&0Lk&?;86Qg$^FrP zKRb0gFD^vvNu8CW_Bt2NZBTYdPyEwM+|SW7xuYAMg4f#ll~IW45Q(@0pfk=HwdwU$|>j+L_MT%iazcU zr0Ef(eiS;gCv;q1OV>L+24$KYO;zI}Ot0()V@!;+DyWm&8^c;=u+eH!qz!MK{aE=V zEdl!j*tjTEpdkxv01;epm{AJK6j{#avnZ3|dLb2jMoyS)H>3Vfv^YvC01LDA$x2Ni)#({s`W znhr_zp5iI5CttH9cjc2$xT|0EPC@&udwDTD9G;z@Vq#$$yn^ODuxSIsPzZ<|z`Ji? ziR|{lc)g{+UY_G8DPlk(5 z&i`$nFg?#%m+)WI3*fVrj~vp;@%&G+wICDM2+>8ECJkibJ6wOjlBOTHZMyJ^p=)s3 z5Y`<9hHm)0-NvCz*icI9N0W$LSVuKQXONN;qViKjOTgirlCikP50dc@y5$0+1OXU( zNC$`tWvcxdV`BOz@VzOm#P|p@M?bQN((EEN3|?V+1W3bn3cuuANpG&j=8$`DPy5oS zIy+n%!)svEGBz+qsv06ft%xw8?2{9CrnoT^78S%7EfH8)7rjINV9k#?Vt(~(a!>9) zOn7C}{Sk%lS|LSaKKn9Bw#G7T3S1eHN(0D~nv>eXz{_NGjhNK=MD|Mz{_=0!|sOME2tH{2bM0*sipT)my+P_?zZ8e@2;vS5Y+7`ZiG* zIOk0oWfT~>msGo`AiC(Pg{9`=>o>Ru>(~8ZPyRt|0%PCS=tSy%1D`hElKlZPlzl|A zZ76PF_U^z|l$47mu;$x|KIRM?v9yxk?>;QA`olK-{cpq7JZRzZB)Y3jLg2Zl?tVJ- zQlU4YTZ@u!T>|4QB~f{V3N6Z|0pU2s@kw0R89H7=pU!Z5oa}FnJ3~!65E7-}&5a!c zLZeX{c&@7A0a6s)%_Lf1_k1pYl{1qn?MqMPt{<-_+yp3?q*+18N$Y>wZ za{r?46_0!UbE`Wzx$K_wwirL#zdG-=-gQT?wQGhB-}z+ii_3%Y#%b>ip^Da91WLMy zgx7w)ivvusu`Ot`xcg!^dtg<-53r(pce34$wJlwu76&6VnsdW*^GFcNP%KEBghf=Y zjj@DG)6O{9KRwFpXkX?y=3aTq*y8^S-P4nyW&u9QSRO~@BaEyb5Wkb43SL6r=Qn5B zVt=`}oZUJ*dT{Gbc5D2md+)(R{`IB{slWR0?wwEZFLVxAUKR+A1B#O(c-Hkvw{2aT zjN^r`41GR|?~kmHt;zGMU%yFb9KB*Wnv9#R71g25aKSwycm=S1Z_Zd4>6* zjdcl%<&}^A@|yhmeZEIYg2k9U?)V}Xh`2j!l#x^7OEkkc9ph*U#<8tgxmy-*f401O z`{VDeFnK|{X^+vm@b&i}KlT|A@$`MO-#-)9ySV5c{(zg7j^WFr)DH+|>=TtNgrGKP}O3K_v3XCJ0{}e+iBO!k*RDM=TvuL)pcqGodZQAKHo6bl=P?3HgIr~CVqsfOMg+L*XX5HgFLXGd@I z?fGK6wPv-0&3ELRv+m(9z9X}C5B2m1UvW7dQf4fMfP}rXQxx@!F%$w!d_%0D@p5pB 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

    {jGzv$w)hEmJq7I3Xd=I$(AEk%FQ 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

    )wi4on(`fpjr>< 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 z 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%0ASSn&da@p@*NTGi_ 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

      k2`SMkv!+Kx${ZGgzk>n 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

      K6!g-ARB^o<440#d|!h7f?V;A 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°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%0A)>Or90|Q)+x$q<$TvhNz z@S{CA_Pp6C1)gvxNE31DF?qA=cM2;?L@R_ejAizvS@YUY@ZSUm7nQqu? z6F+t)mvW@Uy}xI*_!oBBxX}>cZKP`5pVcM1@^b-$Baw~D#}hd^fb@tc13j7`iJiTH zI$LlGvPt_i(8`%J>{6Jn5?k`JTV-7pFQa^LUtS)k_%)=V3LIkS8nc^zMg~Ox2`^nZ zg(69${xppdEq1rQ1h-9+dSrCbmeL1!#^5kbm~gP zrbpGbj~Xa`T4~r>j$*$Y=ED)#Kunxy1M0x@Q5yUHV-(Ql3uyx?^@mxBj~=n}{M6RW zH(+|kld;~B2@x$VWD@kDGn1341hnWxtQg!VCW0oj3i&IL=T$Ln75bANGGf-2V$sC^?35?+cH4=}l3@?q4RrB7aG4nl++m^4_D64SF{J zax=$oAAkyTiCBiP_ED&fK znJh9@MPRSQ&P?z`BSwyy+stoCtmsgCGlZy}>MW_%(HJ*FAx-M~J6@2UlounTKuR2d z<#Noy>)`Nsr0wYncXlVzFB9X15aU0oHovwH4@wP|r(Hk%fDw6!b=yoOFSU zR{R^4(e?*E)|5-AjfZv{WFw+HA|v4;eT_=AI7~)UL{%s;wX3yAg4MU?boD4?o0=N& z@+)WILMKy|e7%c7&+pA?C;W;o*6>2cx?@_il39b7W6X6%K;w$mCC6(PJCM@Wf&6}} zOKBL95G#^Pyvj2peJ1@Ez4nbx_RfDcR|;@aNQCaNF~i#YP1HC7+F#AWsru0B+y~!T zQv{qr?p$i4`qt@hd#fVGjU?dMv^-ljdZqSg9P&7b6RB{g7g>zBTd#hI;==b4*}ld) zuUmfqdpd)Y@=@&GwAr*$YD=&a9|R2?xiIR1s&1i|#)%rI;(ZLVSaUujuX)Py2g+fj zhh`*mTHSP1Lpk<5d(est8?=b?%MTFN; z9zjw!wBR4Dq~b*?rvpyZi{Z8JPV3AMl6m3hn$IXH{~b z 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≥X_m;f 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%0Dez1FtA=(-48+l>bO|_c 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 !W>u1^I;(9-s)49+BTJg!otxXO6Be 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 z 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μ|CCrhz5 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 GyV!7Uyn_ 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 I9iJcnFIffLGXMYp literal 0 HcmV?d00001 diff --git a/.extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan.phar.asc b/.extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan.phar.asc new file mode 100644 index 000000000..188c2f3a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpstan/phpstan/phpstan.phar.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmdI6tsACgkQUcZzBf/C +5cB4lA/+ITHN8aCrWNOMhd9PzBuls+WrAbOFpRgKdsW3mMcUyFSDfG6DjsfTtGDw +LKW01xUKq46fmoHGXjdmz0OWoB6cbfVyuo/LHUqUQvWYFieTUH56zZnQZ8H7nRDv +G3wtS/XrH5NNMJwe7JL08+kQEwqKbadNdWkd1iE2dJS5SM6gOJFfXt52PCmSsBG9 +UCCYrJpomfyK2BVPp5bkHW+MGhxjAy+0tdpZlIpZ5ivlau3opL+ZDf3jl41cgYOm +DVqs/L2aw7yBKvva7pJClFBDI3lO+APJlTsSihKUsNu58nSdT2hQFZWwzBdp1Wc/ +vs7voBii2eNpbARZ18Sv6rs8CW4tezKqgK3PcX0lK2p9r1QrrN7hZYl5jYxXovcn +n5L5MXvcVK9J4tJx/Hy1/qN7K5HLlWTX9nUeEKveIQMAtRGVHc0nEl7jfNHt5Vpb +gr8B3gRoIUqAxZcP/sly0HmR8TgBlkEzy7NdEjMkCrj4E/UMDI57crOTaDL/lE4e +E03bBXsJT4heawCdbRisl7wNb+8JDNAnFNIPobce9TocZU8TGhlrY0XNpb3NqDl2 +bSeUXQ31L6L7QV/5a0oD4VRz1army3rUYVK47BkbRaujmvvgcCb4S61MDSmTxEXu +Lgf3xfaOcta/FnvtFoMCVfScwh5a3C/Qw4Je+5JKq9lNNSgTSSM= +=NUhN +-----END PGP SIGNATURE----- diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/ChangeLog-10.1.md b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/ChangeLog-10.1.md new file mode 100644 index 000000000..27cb92fbf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/ChangeLog-10.1.md @@ -0,0 +1,132 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [10.1.16] - 2024-08-22 + +### Changed + +* Updated dependencies (so that users that install using Composer's `--prefer-lowest` CLI option also get recent versions) + +## [10.1.15] - 2024-06-29 + +### Fixed + +* [#967](https://github.com/sebastianbergmann/php-code-coverage/issues/967): Identification of executable lines for `match` expressions does not work correctly + +## [10.1.14] - 2024-03-12 + +### Fixed + +* [#1033](https://github.com/sebastianbergmann/php-code-coverage/issues/1033): `@codeCoverageIgnore` annotation does not work on `enum` + +## [10.1.13] - 2024-03-09 + +### Changed + +* [#1032](https://github.com/sebastianbergmann/php-code-coverage/pull/1032): Pad lines in code coverage report only when colors are shown + +## [10.1.12] - 2024-03-02 + +### Changed + +* Do not use implicitly nullable parameters + +## [10.1.11] - 2023-12-21 + +### Changed + +* This component is now compatible with `nikic/php-parser` 5.0 + +## [10.1.10] - 2023-12-11 + +### Fixed + +* [#1023](https://github.com/sebastianbergmann/php-code-coverage/issues/1023): Branch Coverage and Path Coverage are not correctly reported for traits + +## [10.1.9] - 2023-11-23 + +### Fixed + +* [#1020](https://github.com/sebastianbergmann/php-code-coverage/issues/1020): Single line method is ignored + +## [10.1.8] - 2023-11-15 + +### Fixed + +* [#1018](https://github.com/sebastianbergmann/php-code-coverage/issues/1018): Interface methods are not ignored when their signature is split over multiple lines + +## [10.1.7] - 2023-10-04 + +### Fixed + +* [#1014](https://github.com/sebastianbergmann/php-code-coverage/issues/1014): Incorrect statement count in coverage report for constructor property promotion + +## [10.1.6] - 2023-09-19 + +### Fixed + +* [#1012](https://github.com/sebastianbergmann/php-code-coverage/issues/1012): Cobertura report pulls functions from report scope, not the individual element + +## [10.1.5] - 2023-09-12 + +### Changed + +* [#1011](https://github.com/sebastianbergmann/php-code-coverage/pull/1011): Avoid serialization of cache data in PHP report + +## [10.1.4] - 2023-08-31 + +### Fixed + +* Exceptions of type `SebastianBergmann\Template\Exception` are now properly handled + +## [10.1.3] - 2023-07-26 + +### Changed + +* The result of `CodeCoverage::getReport()` is now cached + +### Fixed + +* Static analysis cache keys do not include configuration settings that affect source code parsing +* The Clover, Cobertura, Crap4j, and PHP report writers no longer create a `php:` directory when they should write to `php://stdout`, for instance + +## [10.1.2] - 2023-05-22 + +### Fixed + +* [#998](https://github.com/sebastianbergmann/php-code-coverage/pull/998): Group Use Declarations are not handled properly + +## [10.1.1] - 2023-04-17 + +### Fixed + +* [#994](https://github.com/sebastianbergmann/php-code-coverage/issues/994): Argument `$linesToBeIgnored` of `CodeCoverage::stop()` has no effect for files that are not executed at all + +## [10.1.0] - 2023-04-13 + +### Added + +* [#982](https://github.com/sebastianbergmann/php-code-coverage/issues/982): Add option to ignore lines from code coverage + +### Deprecated + +* The `SebastianBergmann\CodeCoverage\Filter::includeDirectory()`, `SebastianBergmann\CodeCoverage\Filter::excludeDirectory()`, and `SebastianBergmann\CodeCoverage\Filter::excludeFile()` methods are now deprecated + +[10.1.16]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.15...10.1.16 +[10.1.15]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.14...10.1.15 +[10.1.14]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.13...10.1.14 +[10.1.13]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.12...10.1.13 +[10.1.12]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.11...10.1.12 +[10.1.11]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.10...10.1.11 +[10.1.10]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.9...10.1.10 +[10.1.9]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.8...10.1.9 +[10.1.8]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.7...10.1.8 +[10.1.7]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.6...10.1.7 +[10.1.6]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.5...10.1.6 +[10.1.5]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.4...10.1.5 +[10.1.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.3...10.1.4 +[10.1.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.2...10.1.3 +[10.1.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.1...10.1.2 +[10.1.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.1.0...10.1.1 +[10.1.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/10.0.2...10.1.0 diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/LICENSE b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/LICENSE new file mode 100644 index 000000000..89f053091 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2009-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/README.md b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/README.md new file mode 100644 index 000000000..26807a8d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/README.md @@ -0,0 +1,55 @@ +# phpunit/php-code-coverage + +[![Latest Stable Version](https://poser.pugx.org/phpunit/php-code-coverage/v/stable.png)](https://packagist.org/packages/phpunit/php-code-coverage) +[![CI Status](https://github.com/sebastianbergmann/php-code-coverage/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-code-coverage/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-code-coverage/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-code-coverage) +[![codecov](https://codecov.io/gh/sebastianbergmann/php-code-coverage/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/php-code-coverage) + +Provides collection, processing, and rendering functionality for PHP code coverage information. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require phpunit/php-code-coverage +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev phpunit/php-code-coverage +``` + +## Usage + +```php +includeFiles( + [ + '/path/to/file.php', + '/path/to/another_file.php', + ] +); + +$coverage = new CodeCoverage( + (new Selector)->forLineCoverage($filter), + $filter +); + +$coverage->start(''); + +// ... + +$coverage->stop(); + + +(new HtmlReport)->process($coverage, '/tmp/code-coverage-report'); +``` diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/SECURITY.md b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/composer.json b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/composer.json new file mode 100644 index 000000000..855b369e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/composer.json @@ -0,0 +1,69 @@ +{ + "name": "phpunit/php-code-coverage", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "type": "library", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=8.1", + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "files": [ + "tests/TestCase.php", + "tests/_files/BankAccountTest.php" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "10.1.x-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/CodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/CodeCoverage.php new file mode 100644 index 000000000..805fd8223 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/CodeCoverage.php @@ -0,0 +1,631 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function array_diff; +use function array_diff_key; +use function array_flip; +use function array_keys; +use function array_merge; +use function array_merge_recursive; +use function array_unique; +use function count; +use function explode; +use function is_array; +use function is_file; +use function sort; +use ReflectionClass; +use SebastianBergmann\CodeCoverage\Data\ProcessedCodeCoverageData; +use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; +use SebastianBergmann\CodeCoverage\Driver\Driver; +use SebastianBergmann\CodeCoverage\Node\Builder; +use SebastianBergmann\CodeCoverage\Node\Directory; +use SebastianBergmann\CodeCoverage\StaticAnalysis\CachingFileAnalyser; +use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; +use SebastianBergmann\CodeCoverage\StaticAnalysis\ParsingFileAnalyser; +use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize; +use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus; +use SebastianBergmann\CodeUnitReverseLookup\Wizard; + +/** + * Provides collection functionality for PHP code coverage information. + * + * @psalm-type TestType = array{ + * size: string, + * status: string, + * } + */ +final class CodeCoverage +{ + private const UNCOVERED_FILES = 'UNCOVERED_FILES'; + private readonly Driver $driver; + private readonly Filter $filter; + private readonly Wizard $wizard; + private bool $checkForUnintentionallyCoveredCode = false; + private bool $includeUncoveredFiles = true; + private bool $ignoreDeprecatedCode = false; + private ?string $currentId = null; + private ?TestSize $currentSize = null; + private ProcessedCodeCoverageData $data; + private bool $useAnnotationsForIgnoringCode = true; + + /** + * @psalm-var array> + */ + private array $linesToBeIgnored = []; + + /** + * @psalm-var array + */ + private array $tests = []; + + /** + * @psalm-var list + */ + private array $parentClassesExcludedFromUnintentionallyCoveredCodeCheck = []; + private ?FileAnalyser $analyser = null; + private ?string $cacheDirectory = null; + private ?Directory $cachedReport = null; + + public function __construct(Driver $driver, Filter $filter) + { + $this->driver = $driver; + $this->filter = $filter; + $this->data = new ProcessedCodeCoverageData; + $this->wizard = new Wizard; + } + + /** + * Returns the code coverage information as a graph of node objects. + */ + public function getReport(): Directory + { + if ($this->cachedReport === null) { + $this->cachedReport = (new Builder($this->analyser()))->build($this); + } + + return $this->cachedReport; + } + + /** + * Clears collected code coverage data. + */ + public function clear(): void + { + $this->currentId = null; + $this->currentSize = null; + $this->data = new ProcessedCodeCoverageData; + $this->tests = []; + $this->cachedReport = null; + } + + /** + * @internal + */ + public function clearCache(): void + { + $this->cachedReport = null; + } + + /** + * Returns the filter object used. + */ + public function filter(): Filter + { + return $this->filter; + } + + /** + * Returns the collected code coverage data. + */ + public function getData(bool $raw = false): ProcessedCodeCoverageData + { + if (!$raw) { + if ($this->includeUncoveredFiles) { + $this->addUncoveredFilesFromFilter(); + } + } + + return $this->data; + } + + /** + * Sets the coverage data. + */ + public function setData(ProcessedCodeCoverageData $data): void + { + $this->data = $data; + } + + /** + * @psalm-return array + */ + public function getTests(): array + { + return $this->tests; + } + + /** + * @psalm-param array $tests + */ + public function setTests(array $tests): void + { + $this->tests = $tests; + } + + public function start(string $id, ?TestSize $size = null, bool $clear = false): void + { + if ($clear) { + $this->clear(); + } + + $this->currentId = $id; + $this->currentSize = $size; + + $this->driver->start(); + + $this->cachedReport = null; + } + + /** + * @psalm-param array> $linesToBeIgnored + */ + public function stop(bool $append = true, ?TestStatus $status = null, array|false $linesToBeCovered = [], array $linesToBeUsed = [], array $linesToBeIgnored = []): RawCodeCoverageData + { + $data = $this->driver->stop(); + + $this->linesToBeIgnored = array_merge_recursive( + $this->linesToBeIgnored, + $linesToBeIgnored, + ); + + $this->append($data, null, $append, $status, $linesToBeCovered, $linesToBeUsed, $linesToBeIgnored); + + $this->currentId = null; + $this->currentSize = null; + $this->cachedReport = null; + + return $data; + } + + /** + * @psalm-param array> $linesToBeIgnored + * + * @throws ReflectionException + * @throws TestIdMissingException + * @throws UnintentionallyCoveredCodeException + */ + public function append(RawCodeCoverageData $rawData, ?string $id = null, bool $append = true, ?TestStatus $status = null, array|false $linesToBeCovered = [], array $linesToBeUsed = [], array $linesToBeIgnored = []): void + { + if ($id === null) { + $id = $this->currentId; + } + + if ($id === null) { + throw new TestIdMissingException; + } + + $this->cachedReport = null; + + if ($status === null) { + $status = TestStatus::unknown(); + } + + $size = $this->currentSize; + + if ($size === null) { + $size = TestSize::unknown(); + } + + $this->applyFilter($rawData); + + $this->applyExecutableLinesFilter($rawData); + + if ($this->useAnnotationsForIgnoringCode) { + $this->applyIgnoredLinesFilter($rawData, $linesToBeIgnored); + } + + $this->data->initializeUnseenData($rawData); + + if (!$append) { + return; + } + + if ($id === self::UNCOVERED_FILES) { + return; + } + + $this->applyCoversAndUsesFilter( + $rawData, + $linesToBeCovered, + $linesToBeUsed, + $size, + ); + + if (empty($rawData->lineCoverage())) { + return; + } + + $this->tests[$id] = [ + 'size' => $size->asString(), + 'status' => $status->asString(), + ]; + + $this->data->markCodeAsExecutedByTestCase($id, $rawData); + } + + /** + * Merges the data from another instance. + */ + public function merge(self $that): void + { + $this->filter->includeFiles( + $that->filter()->files(), + ); + + $this->data->merge($that->data); + + $this->tests = array_merge($this->tests, $that->getTests()); + + $this->cachedReport = null; + } + + public function enableCheckForUnintentionallyCoveredCode(): void + { + $this->checkForUnintentionallyCoveredCode = true; + } + + public function disableCheckForUnintentionallyCoveredCode(): void + { + $this->checkForUnintentionallyCoveredCode = false; + } + + public function includeUncoveredFiles(): void + { + $this->includeUncoveredFiles = true; + } + + public function excludeUncoveredFiles(): void + { + $this->includeUncoveredFiles = false; + } + + public function enableAnnotationsForIgnoringCode(): void + { + $this->useAnnotationsForIgnoringCode = true; + } + + public function disableAnnotationsForIgnoringCode(): void + { + $this->useAnnotationsForIgnoringCode = false; + } + + public function ignoreDeprecatedCode(): void + { + $this->ignoreDeprecatedCode = true; + } + + public function doNotIgnoreDeprecatedCode(): void + { + $this->ignoreDeprecatedCode = false; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + */ + public function cachesStaticAnalysis(): bool + { + return $this->cacheDirectory !== null; + } + + public function cacheStaticAnalysis(string $directory): void + { + $this->cacheDirectory = $directory; + } + + public function doNotCacheStaticAnalysis(): void + { + $this->cacheDirectory = null; + } + + /** + * @throws StaticAnalysisCacheNotConfiguredException + */ + public function cacheDirectory(): string + { + if (!$this->cachesStaticAnalysis()) { + throw new StaticAnalysisCacheNotConfiguredException( + 'The static analysis cache is not configured', + ); + } + + return $this->cacheDirectory; + } + + /** + * @psalm-param class-string $className + */ + public function excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(string $className): void + { + $this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck[] = $className; + } + + public function enableBranchAndPathCoverage(): void + { + $this->driver->enableBranchAndPathCoverage(); + } + + public function disableBranchAndPathCoverage(): void + { + $this->driver->disableBranchAndPathCoverage(); + } + + public function collectsBranchAndPathCoverage(): bool + { + return $this->driver->collectsBranchAndPathCoverage(); + } + + public function detectsDeadCode(): bool + { + return $this->driver->detectsDeadCode(); + } + + /** + * @throws ReflectionException + * @throws UnintentionallyCoveredCodeException + */ + private function applyCoversAndUsesFilter(RawCodeCoverageData $rawData, array|false $linesToBeCovered, array $linesToBeUsed, TestSize $size): void + { + if ($linesToBeCovered === false) { + $rawData->clear(); + + return; + } + + if (empty($linesToBeCovered)) { + return; + } + + if ($this->checkForUnintentionallyCoveredCode && !$size->isMedium() && !$size->isLarge()) { + $this->performUnintentionallyCoveredCodeCheck($rawData, $linesToBeCovered, $linesToBeUsed); + } + + $rawLineData = $rawData->lineCoverage(); + $filesWithNoCoverage = array_diff_key($rawLineData, $linesToBeCovered); + + foreach (array_keys($filesWithNoCoverage) as $fileWithNoCoverage) { + $rawData->removeCoverageDataForFile($fileWithNoCoverage); + } + + if (is_array($linesToBeCovered)) { + foreach ($linesToBeCovered as $fileToBeCovered => $includedLines) { + $rawData->keepLineCoverageDataOnlyForLines($fileToBeCovered, $includedLines); + $rawData->keepFunctionCoverageDataOnlyForLines($fileToBeCovered, $includedLines); + } + } + } + + private function applyFilter(RawCodeCoverageData $data): void + { + if ($this->filter->isEmpty()) { + return; + } + + foreach (array_keys($data->lineCoverage()) as $filename) { + if ($this->filter->isExcluded($filename)) { + $data->removeCoverageDataForFile($filename); + } + } + } + + private function applyExecutableLinesFilter(RawCodeCoverageData $data): void + { + foreach (array_keys($data->lineCoverage()) as $filename) { + if (!$this->filter->isFile($filename)) { + continue; + } + + $linesToBranchMap = $this->analyser()->executableLinesIn($filename); + + $data->keepLineCoverageDataOnlyForLines( + $filename, + array_keys($linesToBranchMap), + ); + + $data->markExecutableLineByBranch( + $filename, + $linesToBranchMap, + ); + } + } + + /** + * @psalm-param array> $linesToBeIgnored + */ + private function applyIgnoredLinesFilter(RawCodeCoverageData $data, array $linesToBeIgnored): void + { + foreach (array_keys($data->lineCoverage()) as $filename) { + if (!$this->filter->isFile($filename)) { + continue; + } + + if (isset($linesToBeIgnored[$filename])) { + $data->removeCoverageDataForLines( + $filename, + $linesToBeIgnored[$filename], + ); + } + + $data->removeCoverageDataForLines( + $filename, + $this->analyser()->ignoredLinesFor($filename), + ); + } + } + + /** + * @throws UnintentionallyCoveredCodeException + */ + private function addUncoveredFilesFromFilter(): void + { + $uncoveredFiles = array_diff( + $this->filter->files(), + $this->data->coveredFiles(), + ); + + foreach ($uncoveredFiles as $uncoveredFile) { + if (is_file($uncoveredFile)) { + $this->append( + RawCodeCoverageData::fromUncoveredFile( + $uncoveredFile, + $this->analyser(), + ), + self::UNCOVERED_FILES, + linesToBeIgnored: $this->linesToBeIgnored, + ); + } + } + } + + /** + * @throws ReflectionException + * @throws UnintentionallyCoveredCodeException + */ + private function performUnintentionallyCoveredCodeCheck(RawCodeCoverageData $data, array $linesToBeCovered, array $linesToBeUsed): void + { + $allowedLines = $this->getAllowedLines( + $linesToBeCovered, + $linesToBeUsed, + ); + + $unintentionallyCoveredUnits = []; + + foreach ($data->lineCoverage() as $file => $_data) { + foreach ($_data as $line => $flag) { + if ($flag === 1 && !isset($allowedLines[$file][$line])) { + $unintentionallyCoveredUnits[] = $this->wizard->lookup($file, $line); + } + } + } + + $unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits); + + if (!empty($unintentionallyCoveredUnits)) { + throw new UnintentionallyCoveredCodeException( + $unintentionallyCoveredUnits, + ); + } + } + + private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed): array + { + $allowedLines = []; + + foreach (array_keys($linesToBeCovered) as $file) { + if (!isset($allowedLines[$file])) { + $allowedLines[$file] = []; + } + + $allowedLines[$file] = array_merge( + $allowedLines[$file], + $linesToBeCovered[$file], + ); + } + + foreach (array_keys($linesToBeUsed) as $file) { + if (!isset($allowedLines[$file])) { + $allowedLines[$file] = []; + } + + $allowedLines[$file] = array_merge( + $allowedLines[$file], + $linesToBeUsed[$file], + ); + } + + foreach (array_keys($allowedLines) as $file) { + $allowedLines[$file] = array_flip( + array_unique($allowedLines[$file]), + ); + } + + return $allowedLines; + } + + /** + * @param list $unintentionallyCoveredUnits + * + * @throws ReflectionException + * + * @return list + */ + private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits): array + { + $unintentionallyCoveredUnits = array_unique($unintentionallyCoveredUnits); + $processed = []; + + foreach ($unintentionallyCoveredUnits as $unintentionallyCoveredUnit) { + $tmp = explode('::', $unintentionallyCoveredUnit); + + if (count($tmp) !== 2) { + $processed[] = $unintentionallyCoveredUnit; + + continue; + } + + try { + $class = new ReflectionClass($tmp[0]); + + foreach ($this->parentClassesExcludedFromUnintentionallyCoveredCodeCheck as $parentClass) { + if ($class->isSubclassOf($parentClass)) { + continue 2; + } + } + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + $processed[] = $tmp[0]; + } + + $processed = array_unique($processed); + + sort($processed); + + return $processed; + } + + private function analyser(): FileAnalyser + { + if ($this->analyser !== null) { + return $this->analyser; + } + + $this->analyser = new ParsingFileAnalyser( + $this->useAnnotationsForIgnoringCode, + $this->ignoreDeprecatedCode, + ); + + if ($this->cachesStaticAnalysis()) { + $this->analyser = new CachingFileAnalyser( + $this->cacheDirectory, + $this->analyser, + $this->useAnnotationsForIgnoringCode, + $this->ignoreDeprecatedCode, + ); + } + + return $this->analyser; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php new file mode 100644 index 000000000..28834c244 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/ProcessedCodeCoverageData.php @@ -0,0 +1,278 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Data; + +use function array_key_exists; +use function array_keys; +use function array_merge; +use function array_unique; +use function count; +use function is_array; +use function ksort; +use SebastianBergmann\CodeCoverage\Driver\Driver; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type XdebugFunctionCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver + * + * @psalm-type TestIdType = string + */ +final class ProcessedCodeCoverageData +{ + /** + * Line coverage data. + * An array of filenames, each having an array of linenumbers, each executable line having an array of testcase ids. + * + * @psalm-var array>> + */ + private array $lineCoverage = []; + + /** + * Function coverage data. + * Maintains base format of raw data (@see https://xdebug.org/docs/code_coverage), but each 'hit' entry is an array + * of testcase ids. + * + * @psalm-var array, + * out: array, + * out_hit: array, + * }>, + * paths: array, + * hit: list, + * }>, + * hit: list + * }>> + */ + private array $functionCoverage = []; + + public function initializeUnseenData(RawCodeCoverageData $rawData): void + { + foreach ($rawData->lineCoverage() as $file => $lines) { + if (!isset($this->lineCoverage[$file])) { + $this->lineCoverage[$file] = []; + + foreach ($lines as $k => $v) { + $this->lineCoverage[$file][$k] = $v === Driver::LINE_NOT_EXECUTABLE ? null : []; + } + } + } + + foreach ($rawData->functionCoverage() as $file => $functions) { + foreach ($functions as $functionName => $functionData) { + if (isset($this->functionCoverage[$file][$functionName])) { + $this->initPreviouslySeenFunction($file, $functionName, $functionData); + } else { + $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); + } + } + } + } + + public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverageData $executedCode): void + { + foreach ($executedCode->lineCoverage() as $file => $lines) { + foreach ($lines as $k => $v) { + if ($v === Driver::LINE_EXECUTED) { + $this->lineCoverage[$file][$k][] = $testCaseId; + } + } + } + + foreach ($executedCode->functionCoverage() as $file => $functions) { + foreach ($functions as $functionName => $functionData) { + foreach ($functionData['branches'] as $branchId => $branchData) { + if ($branchData['hit'] === Driver::BRANCH_HIT) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId; + } + } + + foreach ($functionData['paths'] as $pathId => $pathData) { + if ($pathData['hit'] === Driver::BRANCH_HIT) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId; + } + } + } + } + } + + public function setLineCoverage(array $lineCoverage): void + { + $this->lineCoverage = $lineCoverage; + } + + public function lineCoverage(): array + { + ksort($this->lineCoverage); + + return $this->lineCoverage; + } + + public function setFunctionCoverage(array $functionCoverage): void + { + $this->functionCoverage = $functionCoverage; + } + + public function functionCoverage(): array + { + ksort($this->functionCoverage); + + return $this->functionCoverage; + } + + public function coveredFiles(): array + { + ksort($this->lineCoverage); + + return array_keys($this->lineCoverage); + } + + public function renameFile(string $oldFile, string $newFile): void + { + $this->lineCoverage[$newFile] = $this->lineCoverage[$oldFile]; + + if (isset($this->functionCoverage[$oldFile])) { + $this->functionCoverage[$newFile] = $this->functionCoverage[$oldFile]; + } + + unset($this->lineCoverage[$oldFile], $this->functionCoverage[$oldFile]); + } + + public function merge(self $newData): void + { + foreach ($newData->lineCoverage as $file => $lines) { + if (!isset($this->lineCoverage[$file])) { + $this->lineCoverage[$file] = $lines; + + continue; + } + + // we should compare the lines if any of two contains data + $compareLineNumbers = array_unique( + array_merge( + array_keys($this->lineCoverage[$file]), + array_keys($newData->lineCoverage[$file]), + ), + ); + + foreach ($compareLineNumbers as $line) { + $thatPriority = $this->priorityForLine($newData->lineCoverage[$file], $line); + $thisPriority = $this->priorityForLine($this->lineCoverage[$file], $line); + + if ($thatPriority > $thisPriority) { + $this->lineCoverage[$file][$line] = $newData->lineCoverage[$file][$line]; + } elseif ($thatPriority === $thisPriority && is_array($this->lineCoverage[$file][$line])) { + $this->lineCoverage[$file][$line] = array_unique( + array_merge($this->lineCoverage[$file][$line], $newData->lineCoverage[$file][$line]), + ); + } + } + } + + foreach ($newData->functionCoverage as $file => $functions) { + if (!isset($this->functionCoverage[$file])) { + $this->functionCoverage[$file] = $functions; + + continue; + } + + foreach ($functions as $functionName => $functionData) { + if (isset($this->functionCoverage[$file][$functionName])) { + $this->initPreviouslySeenFunction($file, $functionName, $functionData); + } else { + $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); + } + + foreach ($functionData['branches'] as $branchId => $branchData) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit'])); + } + + foreach ($functionData['paths'] as $pathId => $pathData) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit'])); + } + } + } + } + + /** + * Determine the priority for a line. + * + * 1 = the line is not set + * 2 = the line has not been tested + * 3 = the line is dead code + * 4 = the line has been tested + * + * During a merge, a higher number is better. + */ + private function priorityForLine(array $data, int $line): int + { + if (!array_key_exists($line, $data)) { + return 1; + } + + if (is_array($data[$line]) && count($data[$line]) === 0) { + return 2; + } + + if ($data[$line] === null) { + return 3; + } + + return 4; + } + + /** + * For a function we have never seen before, copy all data over and simply init the 'hit' array. + * + * @psalm-param XdebugFunctionCoverageType $functionData + */ + private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void + { + $this->functionCoverage[$file][$functionName] = $functionData; + + foreach (array_keys($functionData['branches']) as $branchId) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; + } + + foreach (array_keys($functionData['paths']) as $pathId) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; + } + } + + /** + * For a function we have seen before, only copy over and init the 'hit' array for any unseen branches and paths. + * Techniques such as mocking and where the contents of a file are different vary during tests (e.g. compiling + * containers) mean that the functions inside a file cannot be relied upon to be static. + * + * @psalm-param XdebugFunctionCoverageType $functionData + */ + private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void + { + foreach ($functionData['branches'] as $branchId => $branchData) { + if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) { + $this->functionCoverage[$file][$functionName]['branches'][$branchId] = $branchData; + $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; + } + } + + foreach ($functionData['paths'] as $pathId => $pathData) { + if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) { + $this->functionCoverage[$file][$functionName]['paths'][$pathId] = $pathData; + $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php new file mode 100644 index 000000000..49cefbbe1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Data/RawCodeCoverageData.php @@ -0,0 +1,281 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Data; + +use function array_diff; +use function array_diff_key; +use function array_flip; +use function array_intersect; +use function array_intersect_key; +use function count; +use function explode; +use function file_get_contents; +use function in_array; +use function is_file; +use function preg_replace; +use function range; +use function str_ends_with; +use function str_starts_with; +use function trim; +use SebastianBergmann\CodeCoverage\Driver\Driver; +use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type XdebugFunctionsCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver + * @psalm-import-type XdebugCodeCoverageWithoutPathCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver + * @psalm-import-type XdebugCodeCoverageWithPathCoverageType from \SebastianBergmann\CodeCoverage\Driver\XdebugDriver + */ +final class RawCodeCoverageData +{ + /** + * @var array> + */ + private static array $emptyLineCache = []; + + /** + * @psalm-var XdebugCodeCoverageWithoutPathCoverageType + */ + private array $lineCoverage; + + /** + * @psalm-var array + */ + private array $functionCoverage; + + /** + * @psalm-param XdebugCodeCoverageWithoutPathCoverageType $rawCoverage + */ + public static function fromXdebugWithoutPathCoverage(array $rawCoverage): self + { + return new self($rawCoverage, []); + } + + /** + * @psalm-param XdebugCodeCoverageWithPathCoverageType $rawCoverage + */ + public static function fromXdebugWithPathCoverage(array $rawCoverage): self + { + $lineCoverage = []; + $functionCoverage = []; + + foreach ($rawCoverage as $file => $fileCoverageData) { + // Xdebug annotates the function name of traits, strip that off + foreach ($fileCoverageData['functions'] as $existingKey => $data) { + if (str_ends_with($existingKey, '}') && !str_starts_with($existingKey, '{')) { // don't want to catch {main} + $newKey = preg_replace('/\{.*}$/', '', $existingKey); + $fileCoverageData['functions'][$newKey] = $data; + unset($fileCoverageData['functions'][$existingKey]); + } + } + + $lineCoverage[$file] = $fileCoverageData['lines']; + $functionCoverage[$file] = $fileCoverageData['functions']; + } + + return new self($lineCoverage, $functionCoverage); + } + + public static function fromUncoveredFile(string $filename, FileAnalyser $analyser): self + { + $lineCoverage = []; + + foreach ($analyser->executableLinesIn($filename) as $line => $branch) { + $lineCoverage[$line] = Driver::LINE_NOT_EXECUTED; + } + + return new self([$filename => $lineCoverage], []); + } + + /** + * @psalm-param XdebugCodeCoverageWithoutPathCoverageType $lineCoverage + * @psalm-param array $functionCoverage + */ + private function __construct(array $lineCoverage, array $functionCoverage) + { + $this->lineCoverage = $lineCoverage; + $this->functionCoverage = $functionCoverage; + + $this->skipEmptyLines(); + } + + public function clear(): void + { + $this->lineCoverage = $this->functionCoverage = []; + } + + /** + * @psalm-return XdebugCodeCoverageWithoutPathCoverageType + */ + public function lineCoverage(): array + { + return $this->lineCoverage; + } + + /** + * @psalm-return array + */ + public function functionCoverage(): array + { + return $this->functionCoverage; + } + + public function removeCoverageDataForFile(string $filename): void + { + unset($this->lineCoverage[$filename], $this->functionCoverage[$filename]); + } + + /** + * @param int[] $lines + */ + public function keepLineCoverageDataOnlyForLines(string $filename, array $lines): void + { + if (!isset($this->lineCoverage[$filename])) { + return; + } + + $this->lineCoverage[$filename] = array_intersect_key( + $this->lineCoverage[$filename], + array_flip($lines), + ); + } + + /** + * @param int[] $linesToBranchMap + */ + public function markExecutableLineByBranch(string $filename, array $linesToBranchMap): void + { + if (!isset($this->lineCoverage[$filename])) { + return; + } + + $linesByBranch = []; + + foreach ($linesToBranchMap as $line => $branch) { + $linesByBranch[$branch][] = $line; + } + + foreach ($this->lineCoverage[$filename] as $line => $lineStatus) { + if (!isset($linesToBranchMap[$line])) { + continue; + } + + $branch = $linesToBranchMap[$line]; + + if (!isset($linesByBranch[$branch])) { + continue; + } + + foreach ($linesByBranch[$branch] as $lineInBranch) { + $this->lineCoverage[$filename][$lineInBranch] = $lineStatus; + } + + if (Driver::LINE_EXECUTED === $lineStatus) { + unset($linesByBranch[$branch]); + } + } + } + + /** + * @param int[] $lines + */ + public function keepFunctionCoverageDataOnlyForLines(string $filename, array $lines): void + { + if (!isset($this->functionCoverage[$filename])) { + return; + } + + foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { + foreach ($functionData['branches'] as $branchId => $branch) { + if (count(array_diff(range($branch['line_start'], $branch['line_end']), $lines)) > 0) { + unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); + + foreach ($functionData['paths'] as $pathId => $path) { + if (in_array($branchId, $path['path'], true)) { + unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); + } + } + } + } + } + } + + /** + * @param int[] $lines + */ + public function removeCoverageDataForLines(string $filename, array $lines): void + { + if (empty($lines)) { + return; + } + + if (!isset($this->lineCoverage[$filename])) { + return; + } + + $this->lineCoverage[$filename] = array_diff_key( + $this->lineCoverage[$filename], + array_flip($lines), + ); + + if (isset($this->functionCoverage[$filename])) { + foreach ($this->functionCoverage[$filename] as $functionName => $functionData) { + foreach ($functionData['branches'] as $branchId => $branch) { + if (count(array_intersect($lines, range($branch['line_start'], $branch['line_end']))) > 0) { + unset($this->functionCoverage[$filename][$functionName]['branches'][$branchId]); + + foreach ($functionData['paths'] as $pathId => $path) { + if (in_array($branchId, $path['path'], true)) { + unset($this->functionCoverage[$filename][$functionName]['paths'][$pathId]); + } + } + } + } + } + } + } + + /** + * At the end of a file, the PHP interpreter always sees an implicit return. Where this occurs in a file that has + * e.g. a class definition, that line cannot be invoked from a test and results in confusing coverage. This engine + * implementation detail therefore needs to be masked which is done here by simply ensuring that all empty lines + * are skipped over for coverage purposes. + * + * @see https://github.com/sebastianbergmann/php-code-coverage/issues/799 + */ + private function skipEmptyLines(): void + { + foreach ($this->lineCoverage as $filename => $coverage) { + foreach ($this->getEmptyLinesForFile($filename) as $emptyLine) { + unset($this->lineCoverage[$filename][$emptyLine]); + } + } + } + + private function getEmptyLinesForFile(string $filename): array + { + if (!isset(self::$emptyLineCache[$filename])) { + self::$emptyLineCache[$filename] = []; + + if (is_file($filename)) { + $sourceLines = explode("\n", file_get_contents($filename)); + + foreach ($sourceLines as $line => $source) { + if (trim($source) === '') { + self::$emptyLineCache[$filename][] = ($line + 1); + } + } + } + } + + return self::$emptyLineCache[$filename]; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Driver.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Driver.php new file mode 100644 index 000000000..cfbed9cfc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Driver.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function sprintf; +use SebastianBergmann\CodeCoverage\BranchAndPathCoverageNotSupportedException; +use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; +use SebastianBergmann\CodeCoverage\DeadCodeDetectionNotSupportedException; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class Driver +{ + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const LINE_NOT_EXECUTABLE = -2; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const LINE_NOT_EXECUTED = -1; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const LINE_EXECUTED = 1; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const BRANCH_NOT_HIT = 0; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + public const BRANCH_HIT = 1; + private bool $collectBranchAndPathCoverage = false; + private bool $detectDeadCode = false; + + public function canCollectBranchAndPathCoverage(): bool + { + return false; + } + + public function collectsBranchAndPathCoverage(): bool + { + return $this->collectBranchAndPathCoverage; + } + + /** + * @throws BranchAndPathCoverageNotSupportedException + */ + public function enableBranchAndPathCoverage(): void + { + if (!$this->canCollectBranchAndPathCoverage()) { + throw new BranchAndPathCoverageNotSupportedException( + sprintf( + '%s does not support branch and path coverage', + $this->nameAndVersion(), + ), + ); + } + + $this->collectBranchAndPathCoverage = true; + } + + public function disableBranchAndPathCoverage(): void + { + $this->collectBranchAndPathCoverage = false; + } + + public function canDetectDeadCode(): bool + { + return false; + } + + public function detectsDeadCode(): bool + { + return $this->detectDeadCode; + } + + /** + * @throws DeadCodeDetectionNotSupportedException + */ + public function enableDeadCodeDetection(): void + { + if (!$this->canDetectDeadCode()) { + throw new DeadCodeDetectionNotSupportedException( + sprintf( + '%s does not support dead code detection', + $this->nameAndVersion(), + ), + ); + } + + $this->detectDeadCode = true; + } + + public function disableDeadCodeDetection(): void + { + $this->detectDeadCode = false; + } + + abstract public function nameAndVersion(): string; + + abstract public function start(): void; + + abstract public function stop(): RawCodeCoverageData; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php new file mode 100644 index 000000000..cdb01e65a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/PcovDriver.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use const pcov\inclusive; +use function array_intersect; +use function extension_loaded; +use function pcov\clear; +use function pcov\collect; +use function pcov\start; +use function pcov\stop; +use function pcov\waiting; +use function phpversion; +use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; +use SebastianBergmann\CodeCoverage\Filter; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class PcovDriver extends Driver +{ + private readonly Filter $filter; + + /** + * @throws PcovNotAvailableException + */ + public function __construct(Filter $filter) + { + $this->ensurePcovIsAvailable(); + + $this->filter = $filter; + } + + public function start(): void + { + start(); + } + + public function stop(): RawCodeCoverageData + { + stop(); + + $filesToCollectCoverageFor = waiting(); + $collected = []; + + if ($filesToCollectCoverageFor) { + if (!$this->filter->isEmpty()) { + $filesToCollectCoverageFor = array_intersect($filesToCollectCoverageFor, $this->filter->files()); + } + + $collected = collect(inclusive, $filesToCollectCoverageFor); + + clear(); + } + + return RawCodeCoverageData::fromXdebugWithoutPathCoverage($collected); + } + + public function nameAndVersion(): string + { + return 'PCOV ' . phpversion('pcov'); + } + + /** + * @throws PcovNotAvailableException + */ + private function ensurePcovIsAvailable(): void + { + if (!extension_loaded('pcov')) { + throw new PcovNotAvailableException; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Selector.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Selector.php new file mode 100644 index 000000000..f1ff32b58 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/Selector.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException; +use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException; +use SebastianBergmann\Environment\Runtime; + +final class Selector +{ + /** + * @throws NoCodeCoverageDriverAvailableException + * @throws PcovNotAvailableException + * @throws XdebugNotAvailableException + * @throws XdebugNotEnabledException + */ + public function forLineCoverage(Filter $filter): Driver + { + $runtime = new Runtime; + + if ($runtime->hasPCOV()) { + return new PcovDriver($filter); + } + + if ($runtime->hasXdebug()) { + $driver = new XdebugDriver($filter); + + $driver->enableDeadCodeDetection(); + + return $driver; + } + + throw new NoCodeCoverageDriverAvailableException; + } + + /** + * @throws NoCodeCoverageDriverWithPathCoverageSupportAvailableException + * @throws XdebugNotAvailableException + * @throws XdebugNotEnabledException + */ + public function forLineAndPathCoverage(Filter $filter): Driver + { + if ((new Runtime)->hasXdebug()) { + $driver = new XdebugDriver($filter); + + $driver->enableDeadCodeDetection(); + $driver->enableBranchAndPathCoverage(); + + return $driver; + } + + throw new NoCodeCoverageDriverWithPathCoverageSupportAvailableException; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php new file mode 100644 index 000000000..37f4572d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Driver/XdebugDriver.php @@ -0,0 +1,162 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use const XDEBUG_CC_BRANCH_CHECK; +use const XDEBUG_CC_DEAD_CODE; +use const XDEBUG_CC_UNUSED; +use const XDEBUG_FILTER_CODE_COVERAGE; +use const XDEBUG_PATH_INCLUDE; +use function explode; +use function extension_loaded; +use function getenv; +use function in_array; +use function ini_get; +use function phpversion; +use function version_compare; +use function xdebug_get_code_coverage; +use function xdebug_info; +use function xdebug_set_filter; +use function xdebug_start_code_coverage; +use function xdebug_stop_code_coverage; +use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; +use SebastianBergmann\CodeCoverage\Filter; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @see https://xdebug.org/docs/code_coverage#xdebug_get_code_coverage + * + * @psalm-type XdebugLinesCoverageType = array + * @psalm-type XdebugBranchCoverageType = array{ + * op_start: int, + * op_end: int, + * line_start: int, + * line_end: int, + * hit: int, + * out: array, + * out_hit: array, + * } + * @psalm-type XdebugPathCoverageType = array{ + * path: array, + * hit: int, + * } + * @psalm-type XdebugFunctionCoverageType = array{ + * branches: array, + * paths: array, + * } + * @psalm-type XdebugFunctionsCoverageType = array + * @psalm-type XdebugPathAndBranchesCoverageType = array{ + * lines: XdebugLinesCoverageType, + * functions: XdebugFunctionsCoverageType, + * } + * @psalm-type XdebugCodeCoverageWithoutPathCoverageType = array + * @psalm-type XdebugCodeCoverageWithPathCoverageType = array + */ +final class XdebugDriver extends Driver +{ + /** + * @throws XdebugNotAvailableException + * @throws XdebugNotEnabledException + */ + public function __construct(Filter $filter) + { + $this->ensureXdebugIsAvailable(); + $this->ensureXdebugCodeCoverageFeatureIsEnabled(); + + if (!$filter->isEmpty()) { + xdebug_set_filter( + XDEBUG_FILTER_CODE_COVERAGE, + XDEBUG_PATH_INCLUDE, + $filter->files(), + ); + } + } + + public function canCollectBranchAndPathCoverage(): bool + { + return true; + } + + public function canDetectDeadCode(): bool + { + return true; + } + + public function start(): void + { + $flags = XDEBUG_CC_UNUSED; + + if ($this->detectsDeadCode() || $this->collectsBranchAndPathCoverage()) { + $flags |= XDEBUG_CC_DEAD_CODE; + } + + if ($this->collectsBranchAndPathCoverage()) { + $flags |= XDEBUG_CC_BRANCH_CHECK; + } + + xdebug_start_code_coverage($flags); + } + + public function stop(): RawCodeCoverageData + { + $data = xdebug_get_code_coverage(); + + xdebug_stop_code_coverage(); + + if ($this->collectsBranchAndPathCoverage()) { + /* @var XdebugCodeCoverageWithPathCoverageType $data */ + return RawCodeCoverageData::fromXdebugWithPathCoverage($data); + } + + /* @var XdebugCodeCoverageWithoutPathCoverageType $data */ + return RawCodeCoverageData::fromXdebugWithoutPathCoverage($data); + } + + public function nameAndVersion(): string + { + return 'Xdebug ' . phpversion('xdebug'); + } + + /** + * @throws XdebugNotAvailableException + */ + private function ensureXdebugIsAvailable(): void + { + if (!extension_loaded('xdebug')) { + throw new XdebugNotAvailableException; + } + } + + /** + * @throws XdebugNotEnabledException + */ + private function ensureXdebugCodeCoverageFeatureIsEnabled(): void + { + if (version_compare(phpversion('xdebug'), '3.1', '>=')) { + if (!in_array('coverage', xdebug_info('mode'), true)) { + throw new XdebugNotEnabledException; + } + + return; + } + + $mode = getenv('XDEBUG_MODE'); + + if ($mode === false || $mode === '') { + $mode = ini_get('xdebug.mode'); + } + + if ($mode === false || + !in_array('coverage', explode(',', $mode), true)) { + throw new XdebugNotEnabledException; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php new file mode 100644 index 000000000..ab2089197 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/BranchAndPathCoverageNotSupportedException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class BranchAndPathCoverageNotSupportedException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php new file mode 100644 index 000000000..d36006489 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DeadCodeDetectionNotSupportedException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class DeadCodeDetectionNotSupportedException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php new file mode 100644 index 000000000..fdd9bfdf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/DirectoryCouldNotBeCreatedException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Util; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class DirectoryCouldNotBeCreatedException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/Exception.php new file mode 100644 index 000000000..28dc48b8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php new file mode 100644 index 000000000..db9cdac34 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/FileCouldNotBeWrittenException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class FileCouldNotBeWrittenException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..17e4b7076 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +final class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php new file mode 100644 index 000000000..b1494e267 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverAvailableException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class NoCodeCoverageDriverAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('No code coverage driver available'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php new file mode 100644 index 000000000..0065b740d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/NoCodeCoverageDriverWithPathCoverageSupportAvailableException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class NoCodeCoverageDriverWithPathCoverageSupportAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('No code coverage driver with path coverage support available'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php new file mode 100644 index 000000000..a907e34e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ParserException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class ParserException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php new file mode 100644 index 000000000..54bd73f58 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PathExistsButIsNotDirectoryException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function sprintf; +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class PathExistsButIsNotDirectoryException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct(sprintf('"%s" exists but is not a directory', $path)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php new file mode 100644 index 000000000..2f0a66e5a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/PcovNotAvailableException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class PcovNotAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The PCOV extension is not available'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php new file mode 100644 index 000000000..78db430be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReflectionException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php new file mode 100644 index 000000000..0481f1610 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/ReportAlreadyFinalizedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class ReportAlreadyFinalizedException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The code coverage report has already been finalized'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php new file mode 100644 index 000000000..fd58fd6b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/StaticAnalysisCacheNotConfiguredException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class StaticAnalysisCacheNotConfiguredException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php new file mode 100644 index 000000000..4cc3e0c2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/TestIdMissingException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class TestIdMissingException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('Test ID is missing'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php new file mode 100644 index 000000000..bb7d88c97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/UnintentionallyCoveredCodeException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class UnintentionallyCoveredCodeException extends RuntimeException implements Exception +{ + /** + * @var list + */ + private readonly array $unintentionallyCoveredUnits; + + /** + * @param list $unintentionallyCoveredUnits + */ + public function __construct(array $unintentionallyCoveredUnits) + { + $this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits; + + parent::__construct($this->toString()); + } + + /** + * @return list + */ + public function getUnintentionallyCoveredUnits(): array + { + return $this->unintentionallyCoveredUnits; + } + + private function toString(): string + { + $message = ''; + + foreach ($this->unintentionallyCoveredUnits as $unit) { + $message .= '- ' . $unit . "\n"; + } + + return $message; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php new file mode 100644 index 000000000..be549e17b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/WriteOperationFailedException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use function sprintf; +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class WriteOperationFailedException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct(sprintf('Cannot write to "%s"', $path)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php new file mode 100644 index 000000000..1622c5a63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotAvailableException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class XdebugNotAvailableException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('The Xdebug extension is not available'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php new file mode 100644 index 000000000..a8df4645b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XdebugNotEnabledException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use RuntimeException; +use SebastianBergmann\CodeCoverage\Exception; + +final class XdebugNotEnabledException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('XDEBUG_MODE=coverage (environment variable) or xdebug.mode=coverage (PHP configuration setting) has to be set'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php new file mode 100644 index 000000000..31e4623df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Exception/XmlException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use RuntimeException; + +final class XmlException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Filter.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Filter.php new file mode 100644 index 000000000..f51eb3e1f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Filter.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function array_keys; +use function is_file; +use function realpath; +use function str_contains; +use function str_starts_with; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +final class Filter +{ + /** + * @psalm-var array + */ + private array $files = []; + + /** + * @psalm-var array + */ + private array $isFileCache = []; + + /** + * @deprecated + */ + public function includeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void + { + foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) { + $this->includeFile($file); + } + } + + /** + * @psalm-param list $files + */ + public function includeFiles(array $filenames): void + { + foreach ($filenames as $filename) { + $this->includeFile($filename); + } + } + + public function includeFile(string $filename): void + { + $filename = realpath($filename); + + if (!$filename) { + return; + } + + $this->files[$filename] = true; + } + + /** + * @deprecated + */ + public function excludeDirectory(string $directory, string $suffix = '.php', string $prefix = ''): void + { + foreach ((new FileIteratorFacade)->getFilesAsArray($directory, $suffix, $prefix) as $file) { + $this->excludeFile($file); + } + } + + /** + * @deprecated + */ + public function excludeFile(string $filename): void + { + $filename = realpath($filename); + + if (!$filename || !isset($this->files[$filename])) { + return; + } + + unset($this->files[$filename]); + } + + public function isFile(string $filename): bool + { + if (isset($this->isFileCache[$filename])) { + return $this->isFileCache[$filename]; + } + + if ($filename === '-' || + str_starts_with($filename, 'vfs://') || + str_contains($filename, 'xdebug://debug-eval') || + str_contains($filename, 'eval()\'d code') || + str_contains($filename, 'runtime-created function') || + str_contains($filename, 'runkit created function') || + str_contains($filename, 'assert code') || + str_contains($filename, 'regexp code') || + str_contains($filename, 'Standard input code')) { + $isFile = false; + } else { + $isFile = is_file($filename); + } + + $this->isFileCache[$filename] = $isFile; + + return $isFile; + } + + public function isExcluded(string $filename): bool + { + return !isset($this->files[$filename]) || !$this->isFile($filename); + } + + /** + * @psalm-return list + */ + public function files(): array + { + return array_keys($this->files); + } + + public function isEmpty(): bool + { + return empty($this->files); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php new file mode 100644 index 000000000..3f21a50e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/AbstractNode.php @@ -0,0 +1,250 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use const DIRECTORY_SEPARATOR; +use function array_merge; +use function str_ends_with; +use function str_replace; +use function substr; +use Countable; +use SebastianBergmann\CodeCoverage\Util\Percentage; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + * @psalm-import-type ProcessedFunctionType from \SebastianBergmann\CodeCoverage\Node\File + * @psalm-import-type ProcessedClassType from \SebastianBergmann\CodeCoverage\Node\File + * @psalm-import-type ProcessedTraitType from \SebastianBergmann\CodeCoverage\Node\File + */ +abstract class AbstractNode implements Countable +{ + private readonly string $name; + private string $pathAsString; + private array $pathAsArray; + private readonly ?AbstractNode $parent; + private string $id; + + public function __construct(string $name, ?self $parent = null) + { + if (str_ends_with($name, DIRECTORY_SEPARATOR)) { + $name = substr($name, 0, -1); + } + + $this->name = $name; + $this->parent = $parent; + + $this->processId(); + $this->processPath(); + } + + public function name(): string + { + return $this->name; + } + + public function id(): string + { + return $this->id; + } + + public function pathAsString(): string + { + return $this->pathAsString; + } + + public function pathAsArray(): array + { + return $this->pathAsArray; + } + + public function parent(): ?self + { + return $this->parent; + } + + public function percentageOfTestedClasses(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedClasses(), + $this->numberOfClasses(), + ); + } + + public function percentageOfTestedTraits(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedTraits(), + $this->numberOfTraits(), + ); + } + + public function percentageOfTestedClassesAndTraits(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedClassesAndTraits(), + $this->numberOfClassesAndTraits(), + ); + } + + public function percentageOfTestedFunctions(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedFunctions(), + $this->numberOfFunctions(), + ); + } + + public function percentageOfTestedMethods(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedMethods(), + $this->numberOfMethods(), + ); + } + + public function percentageOfTestedFunctionsAndMethods(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfTestedFunctionsAndMethods(), + $this->numberOfFunctionsAndMethods(), + ); + } + + public function percentageOfExecutedLines(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfExecutedLines(), + $this->numberOfExecutableLines(), + ); + } + + public function percentageOfExecutedBranches(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfExecutedBranches(), + $this->numberOfExecutableBranches(), + ); + } + + public function percentageOfExecutedPaths(): Percentage + { + return Percentage::fromFractionAndTotal( + $this->numberOfExecutedPaths(), + $this->numberOfExecutablePaths(), + ); + } + + public function numberOfClassesAndTraits(): int + { + return $this->numberOfClasses() + $this->numberOfTraits(); + } + + public function numberOfTestedClassesAndTraits(): int + { + return $this->numberOfTestedClasses() + $this->numberOfTestedTraits(); + } + + public function classesAndTraits(): array + { + return array_merge($this->classes(), $this->traits()); + } + + public function numberOfFunctionsAndMethods(): int + { + return $this->numberOfFunctions() + $this->numberOfMethods(); + } + + public function numberOfTestedFunctionsAndMethods(): int + { + return $this->numberOfTestedFunctions() + $this->numberOfTestedMethods(); + } + + /** + * @psalm-return array + */ + abstract public function classes(): array; + + /** + * @psalm-return array + */ + abstract public function traits(): array; + + /** + * @psalm-return array + */ + abstract public function functions(): array; + + /** + * @psalm-return LinesOfCodeType + */ + abstract public function linesOfCode(): array; + + abstract public function numberOfExecutableLines(): int; + + abstract public function numberOfExecutedLines(): int; + + abstract public function numberOfExecutableBranches(): int; + + abstract public function numberOfExecutedBranches(): int; + + abstract public function numberOfExecutablePaths(): int; + + abstract public function numberOfExecutedPaths(): int; + + abstract public function numberOfClasses(): int; + + abstract public function numberOfTestedClasses(): int; + + abstract public function numberOfTraits(): int; + + abstract public function numberOfTestedTraits(): int; + + abstract public function numberOfMethods(): int; + + abstract public function numberOfTestedMethods(): int; + + abstract public function numberOfFunctions(): int; + + abstract public function numberOfTestedFunctions(): int; + + private function processId(): void + { + if ($this->parent === null) { + $this->id = 'index'; + + return; + } + + $parentId = $this->parent->id(); + + if ($parentId === 'index') { + $this->id = str_replace(':', '_', $this->name); + } else { + $this->id = $parentId . '/' . $this->name; + } + } + + private function processPath(): void + { + if ($this->parent === null) { + $this->pathAsArray = [$this]; + $this->pathAsString = $this->name; + + return; + } + + $this->pathAsArray = $this->parent->pathAsArray(); + $this->pathAsString = $this->parent->pathAsString() . DIRECTORY_SEPARATOR . $this->name; + + $this->pathAsArray[] = $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Builder.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Builder.php new file mode 100644 index 000000000..5ed6f866a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Builder.php @@ -0,0 +1,269 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use const DIRECTORY_SEPARATOR; +use function array_shift; +use function basename; +use function count; +use function dirname; +use function explode; +use function implode; +use function is_file; +use function str_ends_with; +use function str_replace; +use function str_starts_with; +use function substr; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Data\ProcessedCodeCoverageData; +use SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type TestType from \SebastianBergmann\CodeCoverage\CodeCoverage + */ +final class Builder +{ + private readonly FileAnalyser $analyser; + + public function __construct(FileAnalyser $analyser) + { + $this->analyser = $analyser; + } + + public function build(CodeCoverage $coverage): Directory + { + $data = clone $coverage->getData(); // clone because path munging is destructive to the original data + $commonPath = $this->reducePaths($data); + $root = new Directory( + $commonPath, + null, + ); + + $this->addItems( + $root, + $this->buildDirectoryStructure($data), + $coverage->getTests(), + ); + + return $root; + } + + /** + * @psalm-param array $tests + */ + private function addItems(Directory $root, array $items, array $tests): void + { + foreach ($items as $key => $value) { + $key = (string) $key; + + if (str_ends_with($key, '/f')) { + $key = substr($key, 0, -2); + $filename = $root->pathAsString() . DIRECTORY_SEPARATOR . $key; + + if (is_file($filename)) { + $root->addFile( + new File( + $key, + $root, + $value['lineCoverage'], + $value['functionCoverage'], + $tests, + $this->analyser->classesIn($filename), + $this->analyser->traitsIn($filename), + $this->analyser->functionsIn($filename), + $this->analyser->linesOfCodeFor($filename), + ), + ); + } + } else { + $child = $root->addDirectory($key); + + $this->addItems($child, $value, $tests); + } + } + } + + /** + * Builds an array representation of the directory structure. + * + * For instance, + * + * + * Array + * ( + * [Money.php] => Array + * ( + * ... + * ) + * + * [MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * + * + * is transformed into + * + * + * Array + * ( + * [.] => Array + * ( + * [Money.php] => Array + * ( + * ... + * ) + * + * [MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * ) + * + * + * @psalm-return array, functionCoverage: array>}>> + */ + private function buildDirectoryStructure(ProcessedCodeCoverageData $data): array + { + $result = []; + + foreach ($data->coveredFiles() as $originalPath) { + $path = explode(DIRECTORY_SEPARATOR, $originalPath); + $pointer = &$result; + $max = count($path); + + for ($i = 0; $i < $max; $i++) { + $type = ''; + + if ($i === ($max - 1)) { + $type = '/f'; + } + + $pointer = &$pointer[$path[$i] . $type]; + } + + $pointer = [ + 'lineCoverage' => $data->lineCoverage()[$originalPath] ?? [], + 'functionCoverage' => $data->functionCoverage()[$originalPath] ?? [], + ]; + } + + return $result; + } + + /** + * Reduces the paths by cutting the longest common start path. + * + * For instance, + * + * + * Array + * ( + * [/home/sb/Money/Money.php] => Array + * ( + * ... + * ) + * + * [/home/sb/Money/MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * + * + * is reduced to + * + * + * Array + * ( + * [Money.php] => Array + * ( + * ... + * ) + * + * [MoneyBag.php] => Array + * ( + * ... + * ) + * ) + * + */ + private function reducePaths(ProcessedCodeCoverageData $coverage): string + { + if (empty($coverage->coveredFiles())) { + return '.'; + } + + $commonPath = ''; + $paths = $coverage->coveredFiles(); + + if (count($paths) === 1) { + $commonPath = dirname($paths[0]) . DIRECTORY_SEPARATOR; + $coverage->renameFile($paths[0], basename($paths[0])); + + return $commonPath; + } + + $max = count($paths); + + for ($i = 0; $i < $max; $i++) { + // strip phar:// prefixes + if (str_starts_with($paths[$i], 'phar://')) { + $paths[$i] = substr($paths[$i], 7); + $paths[$i] = str_replace('/', DIRECTORY_SEPARATOR, $paths[$i]); + } + $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]); + + if (empty($paths[$i][0])) { + $paths[$i][0] = DIRECTORY_SEPARATOR; + } + } + + $done = false; + $max = count($paths); + + while (!$done) { + for ($i = 0; $i < $max - 1; $i++) { + if (!isset($paths[$i][0]) || + !isset($paths[$i + 1][0]) || + $paths[$i][0] !== $paths[$i + 1][0]) { + $done = true; + + break; + } + } + + if (!$done) { + $commonPath .= $paths[0][0]; + + if ($paths[0][0] !== DIRECTORY_SEPARATOR) { + $commonPath .= DIRECTORY_SEPARATOR; + } + + for ($i = 0; $i < $max; $i++) { + array_shift($paths[$i]); + } + } + } + + $original = $coverage->coveredFiles(); + $max = count($original); + + for ($i = 0; $i < $max; $i++) { + $coverage->renameFile($original[$i], implode(DIRECTORY_SEPARATOR, $paths[$i])); + } + + return substr($commonPath, 0, -1); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php new file mode 100644 index 000000000..7173276c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/CrapIndex.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class CrapIndex +{ + private readonly int $cyclomaticComplexity; + private readonly float $codeCoverage; + + public function __construct(int $cyclomaticComplexity, float $codeCoverage) + { + $this->cyclomaticComplexity = $cyclomaticComplexity; + $this->codeCoverage = $codeCoverage; + } + + public function asString(): string + { + if ($this->codeCoverage === 0.0) { + return (string) ($this->cyclomaticComplexity ** 2 + $this->cyclomaticComplexity); + } + + if ($this->codeCoverage >= 95) { + return (string) $this->cyclomaticComplexity; + } + + return sprintf( + '%01.2F', + $this->cyclomaticComplexity ** 2 * (1 - $this->codeCoverage / 100) ** 3 + $this->cyclomaticComplexity, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Directory.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Directory.php new file mode 100644 index 000000000..176318bde --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Directory.php @@ -0,0 +1,370 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function array_merge; +use function count; +use IteratorAggregate; +use RecursiveIteratorIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + */ +final class Directory extends AbstractNode implements IteratorAggregate +{ + /** + * @var list + */ + private array $children = []; + + /** + * @var list + */ + private array $directories = []; + + /** + * @var list + */ + private array $files = []; + private ?array $classes = null; + private ?array $traits = null; + private ?array $functions = null; + + /** + * @psalm-var null|LinesOfCodeType + */ + private ?array $linesOfCode = null; + private int $numFiles = -1; + private int $numExecutableLines = -1; + private int $numExecutedLines = -1; + private int $numExecutableBranches = -1; + private int $numExecutedBranches = -1; + private int $numExecutablePaths = -1; + private int $numExecutedPaths = -1; + private int $numClasses = -1; + private int $numTestedClasses = -1; + private int $numTraits = -1; + private int $numTestedTraits = -1; + private int $numMethods = -1; + private int $numTestedMethods = -1; + private int $numFunctions = -1; + private int $numTestedFunctions = -1; + + public function count(): int + { + if ($this->numFiles === -1) { + $this->numFiles = 0; + + foreach ($this->children as $child) { + $this->numFiles += count($child); + } + } + + return $this->numFiles; + } + + public function getIterator(): RecursiveIteratorIterator + { + return new RecursiveIteratorIterator( + new Iterator($this), + RecursiveIteratorIterator::SELF_FIRST, + ); + } + + public function addDirectory(string $name): self + { + $directory = new self($name, $this); + + $this->children[] = $directory; + $this->directories[] = &$this->children[count($this->children) - 1]; + + return $directory; + } + + public function addFile(File $file): void + { + $this->children[] = $file; + $this->files[] = &$this->children[count($this->children) - 1]; + + $this->numExecutableLines = -1; + $this->numExecutedLines = -1; + } + + public function directories(): array + { + return $this->directories; + } + + public function files(): array + { + return $this->files; + } + + public function children(): array + { + return $this->children; + } + + public function classes(): array + { + if ($this->classes === null) { + $this->classes = []; + + foreach ($this->children as $child) { + $this->classes = array_merge( + $this->classes, + $child->classes(), + ); + } + } + + return $this->classes; + } + + public function traits(): array + { + if ($this->traits === null) { + $this->traits = []; + + foreach ($this->children as $child) { + $this->traits = array_merge( + $this->traits, + $child->traits(), + ); + } + } + + return $this->traits; + } + + public function functions(): array + { + if ($this->functions === null) { + $this->functions = []; + + foreach ($this->children as $child) { + $this->functions = array_merge( + $this->functions, + $child->functions(), + ); + } + } + + return $this->functions; + } + + /** + * @psalm-return LinesOfCodeType + */ + public function linesOfCode(): array + { + if ($this->linesOfCode === null) { + $this->linesOfCode = [ + 'linesOfCode' => 0, + 'commentLinesOfCode' => 0, + 'nonCommentLinesOfCode' => 0, + ]; + + foreach ($this->children as $child) { + $childLinesOfCode = $child->linesOfCode(); + + $this->linesOfCode['linesOfCode'] += $childLinesOfCode['linesOfCode']; + $this->linesOfCode['commentLinesOfCode'] += $childLinesOfCode['commentLinesOfCode']; + $this->linesOfCode['nonCommentLinesOfCode'] += $childLinesOfCode['nonCommentLinesOfCode']; + } + } + + return $this->linesOfCode; + } + + public function numberOfExecutableLines(): int + { + if ($this->numExecutableLines === -1) { + $this->numExecutableLines = 0; + + foreach ($this->children as $child) { + $this->numExecutableLines += $child->numberOfExecutableLines(); + } + } + + return $this->numExecutableLines; + } + + public function numberOfExecutedLines(): int + { + if ($this->numExecutedLines === -1) { + $this->numExecutedLines = 0; + + foreach ($this->children as $child) { + $this->numExecutedLines += $child->numberOfExecutedLines(); + } + } + + return $this->numExecutedLines; + } + + public function numberOfExecutableBranches(): int + { + if ($this->numExecutableBranches === -1) { + $this->numExecutableBranches = 0; + + foreach ($this->children as $child) { + $this->numExecutableBranches += $child->numberOfExecutableBranches(); + } + } + + return $this->numExecutableBranches; + } + + public function numberOfExecutedBranches(): int + { + if ($this->numExecutedBranches === -1) { + $this->numExecutedBranches = 0; + + foreach ($this->children as $child) { + $this->numExecutedBranches += $child->numberOfExecutedBranches(); + } + } + + return $this->numExecutedBranches; + } + + public function numberOfExecutablePaths(): int + { + if ($this->numExecutablePaths === -1) { + $this->numExecutablePaths = 0; + + foreach ($this->children as $child) { + $this->numExecutablePaths += $child->numberOfExecutablePaths(); + } + } + + return $this->numExecutablePaths; + } + + public function numberOfExecutedPaths(): int + { + if ($this->numExecutedPaths === -1) { + $this->numExecutedPaths = 0; + + foreach ($this->children as $child) { + $this->numExecutedPaths += $child->numberOfExecutedPaths(); + } + } + + return $this->numExecutedPaths; + } + + public function numberOfClasses(): int + { + if ($this->numClasses === -1) { + $this->numClasses = 0; + + foreach ($this->children as $child) { + $this->numClasses += $child->numberOfClasses(); + } + } + + return $this->numClasses; + } + + public function numberOfTestedClasses(): int + { + if ($this->numTestedClasses === -1) { + $this->numTestedClasses = 0; + + foreach ($this->children as $child) { + $this->numTestedClasses += $child->numberOfTestedClasses(); + } + } + + return $this->numTestedClasses; + } + + public function numberOfTraits(): int + { + if ($this->numTraits === -1) { + $this->numTraits = 0; + + foreach ($this->children as $child) { + $this->numTraits += $child->numberOfTraits(); + } + } + + return $this->numTraits; + } + + public function numberOfTestedTraits(): int + { + if ($this->numTestedTraits === -1) { + $this->numTestedTraits = 0; + + foreach ($this->children as $child) { + $this->numTestedTraits += $child->numberOfTestedTraits(); + } + } + + return $this->numTestedTraits; + } + + public function numberOfMethods(): int + { + if ($this->numMethods === -1) { + $this->numMethods = 0; + + foreach ($this->children as $child) { + $this->numMethods += $child->numberOfMethods(); + } + } + + return $this->numMethods; + } + + public function numberOfTestedMethods(): int + { + if ($this->numTestedMethods === -1) { + $this->numTestedMethods = 0; + + foreach ($this->children as $child) { + $this->numTestedMethods += $child->numberOfTestedMethods(); + } + } + + return $this->numTestedMethods; + } + + public function numberOfFunctions(): int + { + if ($this->numFunctions === -1) { + $this->numFunctions = 0; + + foreach ($this->children as $child) { + $this->numFunctions += $child->numberOfFunctions(); + } + } + + return $this->numFunctions; + } + + public function numberOfTestedFunctions(): int + { + if ($this->numTestedFunctions === -1) { + $this->numTestedFunctions = 0; + + foreach ($this->children as $child) { + $this->numTestedFunctions += $child->numberOfTestedFunctions(); + } + } + + return $this->numTestedFunctions; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/File.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/File.php new file mode 100644 index 000000000..7029e8a5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/File.php @@ -0,0 +1,688 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function array_filter; +use function count; +use function range; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type CodeUnitFunctionType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitMethodType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitClassType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitTraitType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + * @psalm-import-type LinesType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + * + * @psalm-type ProcessedFunctionType = array{ + * functionName: string, + * namespace: string, + * signature: string, + * startLine: int, + * endLine: int, + * executableLines: int, + * executedLines: int, + * executableBranches: int, + * executedBranches: int, + * executablePaths: int, + * executedPaths: int, + * ccn: int, + * coverage: int|float, + * crap: int|string, + * link: string + * } + * @psalm-type ProcessedMethodType = array{ + * methodName: string, + * visibility: string, + * signature: string, + * startLine: int, + * endLine: int, + * executableLines: int, + * executedLines: int, + * executableBranches: int, + * executedBranches: int, + * executablePaths: int, + * executedPaths: int, + * ccn: int, + * coverage: float|int, + * crap: int|string, + * link: string + * } + * @psalm-type ProcessedClassType = array{ + * className: string, + * namespace: string, + * methods: array, + * startLine: int, + * executableLines: int, + * executedLines: int, + * executableBranches: int, + * executedBranches: int, + * executablePaths: int, + * executedPaths: int, + * ccn: int, + * coverage: int|float, + * crap: int|string, + * link: string + * } + * @psalm-type ProcessedTraitType = array{ + * traitName: string, + * namespace: string, + * methods: array, + * startLine: int, + * executableLines: int, + * executedLines: int, + * executableBranches: int, + * executedBranches: int, + * executablePaths: int, + * executedPaths: int, + * ccn: int, + * coverage: float|int, + * crap: int|string, + * link: string + * } + */ +final class File extends AbstractNode +{ + /** + * @psalm-var array> + */ + private array $lineCoverageData; + private array $functionCoverageData; + private readonly array $testData; + private int $numExecutableLines = 0; + private int $numExecutedLines = 0; + private int $numExecutableBranches = 0; + private int $numExecutedBranches = 0; + private int $numExecutablePaths = 0; + private int $numExecutedPaths = 0; + + /** + * @psalm-var array + */ + private array $classes = []; + + /** + * @psalm-var array + */ + private array $traits = []; + + /** + * @psalm-var array + */ + private array $functions = []; + + /** + * @psalm-var LinesOfCodeType + */ + private readonly array $linesOfCode; + private ?int $numClasses = null; + private int $numTestedClasses = 0; + private ?int $numTraits = null; + private int $numTestedTraits = 0; + private ?int $numMethods = null; + private ?int $numTestedMethods = null; + private ?int $numTestedFunctions = null; + + /** + * @var array + */ + private array $codeUnitsByLine = []; + + /** + * @psalm-param array> $lineCoverageData + * @psalm-param LinesOfCodeType $linesOfCode + * @psalm-param array $classes + * @psalm-param array $traits + * @psalm-param array $functions + */ + public function __construct(string $name, AbstractNode $parent, array $lineCoverageData, array $functionCoverageData, array $testData, array $classes, array $traits, array $functions, array $linesOfCode) + { + parent::__construct($name, $parent); + + $this->lineCoverageData = $lineCoverageData; + $this->functionCoverageData = $functionCoverageData; + $this->testData = $testData; + $this->linesOfCode = $linesOfCode; + + $this->calculateStatistics($classes, $traits, $functions); + } + + public function count(): int + { + return 1; + } + + /** + * @psalm-return array> + */ + public function lineCoverageData(): array + { + return $this->lineCoverageData; + } + + public function functionCoverageData(): array + { + return $this->functionCoverageData; + } + + public function testData(): array + { + return $this->testData; + } + + public function classes(): array + { + return $this->classes; + } + + public function traits(): array + { + return $this->traits; + } + + public function functions(): array + { + return $this->functions; + } + + public function linesOfCode(): array + { + return $this->linesOfCode; + } + + public function numberOfExecutableLines(): int + { + return $this->numExecutableLines; + } + + public function numberOfExecutedLines(): int + { + return $this->numExecutedLines; + } + + public function numberOfExecutableBranches(): int + { + return $this->numExecutableBranches; + } + + public function numberOfExecutedBranches(): int + { + return $this->numExecutedBranches; + } + + public function numberOfExecutablePaths(): int + { + return $this->numExecutablePaths; + } + + public function numberOfExecutedPaths(): int + { + return $this->numExecutedPaths; + } + + public function numberOfClasses(): int + { + if ($this->numClasses === null) { + $this->numClasses = 0; + + foreach ($this->classes as $class) { + foreach ($class['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numClasses++; + + continue 2; + } + } + } + } + + return $this->numClasses; + } + + public function numberOfTestedClasses(): int + { + return $this->numTestedClasses; + } + + public function numberOfTraits(): int + { + if ($this->numTraits === null) { + $this->numTraits = 0; + + foreach ($this->traits as $trait) { + foreach ($trait['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numTraits++; + + continue 2; + } + } + } + } + + return $this->numTraits; + } + + public function numberOfTestedTraits(): int + { + return $this->numTestedTraits; + } + + public function numberOfMethods(): int + { + if ($this->numMethods === null) { + $this->numMethods = 0; + + foreach ($this->classes as $class) { + foreach ($class['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numMethods++; + } + } + } + + foreach ($this->traits as $trait) { + foreach ($trait['methods'] as $method) { + if ($method['executableLines'] > 0) { + $this->numMethods++; + } + } + } + } + + return $this->numMethods; + } + + public function numberOfTestedMethods(): int + { + if ($this->numTestedMethods === null) { + $this->numTestedMethods = 0; + + foreach ($this->classes as $class) { + foreach ($class['methods'] as $method) { + if ($method['executableLines'] > 0 && + $method['coverage'] === 100) { + $this->numTestedMethods++; + } + } + } + + foreach ($this->traits as $trait) { + foreach ($trait['methods'] as $method) { + if ($method['executableLines'] > 0 && + $method['coverage'] === 100) { + $this->numTestedMethods++; + } + } + } + } + + return $this->numTestedMethods; + } + + public function numberOfFunctions(): int + { + return count($this->functions); + } + + public function numberOfTestedFunctions(): int + { + if ($this->numTestedFunctions === null) { + $this->numTestedFunctions = 0; + + foreach ($this->functions as $function) { + if ($function['executableLines'] > 0 && + $function['coverage'] === 100) { + $this->numTestedFunctions++; + } + } + } + + return $this->numTestedFunctions; + } + + /** + * @psalm-param array $classes + * @psalm-param array $traits + * @psalm-param array $functions + */ + private function calculateStatistics(array $classes, array $traits, array $functions): void + { + foreach (range(1, $this->linesOfCode['linesOfCode']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = []; + } + + $this->processClasses($classes); + $this->processTraits($traits); + $this->processFunctions($functions); + + foreach (range(1, $this->linesOfCode['linesOfCode']) as $lineNumber) { + if (isset($this->lineCoverageData[$lineNumber])) { + foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) { + $codeUnit['executableLines']++; + } + + unset($codeUnit); + + $this->numExecutableLines++; + + if (count($this->lineCoverageData[$lineNumber]) > 0) { + foreach ($this->codeUnitsByLine[$lineNumber] as &$codeUnit) { + $codeUnit['executedLines']++; + } + + unset($codeUnit); + + $this->numExecutedLines++; + } + } + } + + foreach ($this->traits as &$trait) { + foreach ($trait['methods'] as &$method) { + $methodLineCoverage = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100; + $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0; + $methodPathCoverage = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0; + + $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage; + $method['crap'] = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString(); + + $trait['ccn'] += $method['ccn']; + } + + unset($method); + + $traitLineCoverage = $trait['executableLines'] ? ($trait['executedLines'] / $trait['executableLines']) * 100 : 100; + $traitBranchCoverage = $trait['executableBranches'] ? ($trait['executedBranches'] / $trait['executableBranches']) * 100 : 0; + $traitPathCoverage = $trait['executablePaths'] ? ($trait['executedPaths'] / $trait['executablePaths']) * 100 : 0; + + $trait['coverage'] = $traitBranchCoverage ?: $traitLineCoverage; + $trait['crap'] = (new CrapIndex($trait['ccn'], $traitPathCoverage ?: $traitLineCoverage))->asString(); + + if ($trait['executableLines'] > 0 && $trait['coverage'] === 100) { + $this->numTestedClasses++; + } + } + + unset($trait); + + foreach ($this->classes as &$class) { + foreach ($class['methods'] as &$method) { + $methodLineCoverage = $method['executableLines'] ? ($method['executedLines'] / $method['executableLines']) * 100 : 100; + $methodBranchCoverage = $method['executableBranches'] ? ($method['executedBranches'] / $method['executableBranches']) * 100 : 0; + $methodPathCoverage = $method['executablePaths'] ? ($method['executedPaths'] / $method['executablePaths']) * 100 : 0; + + $method['coverage'] = $methodBranchCoverage ?: $methodLineCoverage; + $method['crap'] = (new CrapIndex($method['ccn'], $methodPathCoverage ?: $methodLineCoverage))->asString(); + + $class['ccn'] += $method['ccn']; + } + + unset($method); + + $classLineCoverage = $class['executableLines'] ? ($class['executedLines'] / $class['executableLines']) * 100 : 100; + $classBranchCoverage = $class['executableBranches'] ? ($class['executedBranches'] / $class['executableBranches']) * 100 : 0; + $classPathCoverage = $class['executablePaths'] ? ($class['executedPaths'] / $class['executablePaths']) * 100 : 0; + + $class['coverage'] = $classBranchCoverage ?: $classLineCoverage; + $class['crap'] = (new CrapIndex($class['ccn'], $classPathCoverage ?: $classLineCoverage))->asString(); + + if ($class['executableLines'] > 0 && $class['coverage'] === 100) { + $this->numTestedClasses++; + } + } + + unset($class); + + foreach ($this->functions as &$function) { + $functionLineCoverage = $function['executableLines'] ? ($function['executedLines'] / $function['executableLines']) * 100 : 100; + $functionBranchCoverage = $function['executableBranches'] ? ($function['executedBranches'] / $function['executableBranches']) * 100 : 0; + $functionPathCoverage = $function['executablePaths'] ? ($function['executedPaths'] / $function['executablePaths']) * 100 : 0; + + $function['coverage'] = $functionBranchCoverage ?: $functionLineCoverage; + $function['crap'] = (new CrapIndex($function['ccn'], $functionPathCoverage ?: $functionLineCoverage))->asString(); + + if ($function['coverage'] === 100) { + $this->numTestedFunctions++; + } + } + } + + /** + * @psalm-param array $classes + */ + private function processClasses(array $classes): void + { + $link = $this->id() . '.html#'; + + foreach ($classes as $className => $class) { + $this->classes[$className] = [ + 'className' => $className, + 'namespace' => $class['namespace'], + 'methods' => [], + 'startLine' => $class['startLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => 0, + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $class['startLine'], + ]; + + foreach ($class['methods'] as $methodName => $method) { + $methodData = $this->newMethod($className, $methodName, $method, $link); + $this->classes[$className]['methods'][$methodName] = $methodData; + + $this->classes[$className]['executableBranches'] += $methodData['executableBranches']; + $this->classes[$className]['executedBranches'] += $methodData['executedBranches']; + $this->classes[$className]['executablePaths'] += $methodData['executablePaths']; + $this->classes[$className]['executedPaths'] += $methodData['executedPaths']; + + $this->numExecutableBranches += $methodData['executableBranches']; + $this->numExecutedBranches += $methodData['executedBranches']; + $this->numExecutablePaths += $methodData['executablePaths']; + $this->numExecutedPaths += $methodData['executedPaths']; + + foreach (range($method['startLine'], $method['endLine']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = [ + &$this->classes[$className], + &$this->classes[$className]['methods'][$methodName], + ]; + } + } + } + } + + /** + * @psalm-param array $traits + */ + private function processTraits(array $traits): void + { + $link = $this->id() . '.html#'; + + foreach ($traits as $traitName => $trait) { + $this->traits[$traitName] = [ + 'traitName' => $traitName, + 'namespace' => $trait['namespace'], + 'methods' => [], + 'startLine' => $trait['startLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => 0, + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $trait['startLine'], + ]; + + foreach ($trait['methods'] as $methodName => $method) { + $methodData = $this->newMethod($traitName, $methodName, $method, $link); + $this->traits[$traitName]['methods'][$methodName] = $methodData; + + $this->traits[$traitName]['executableBranches'] += $methodData['executableBranches']; + $this->traits[$traitName]['executedBranches'] += $methodData['executedBranches']; + $this->traits[$traitName]['executablePaths'] += $methodData['executablePaths']; + $this->traits[$traitName]['executedPaths'] += $methodData['executedPaths']; + + $this->numExecutableBranches += $methodData['executableBranches']; + $this->numExecutedBranches += $methodData['executedBranches']; + $this->numExecutablePaths += $methodData['executablePaths']; + $this->numExecutedPaths += $methodData['executedPaths']; + + foreach (range($method['startLine'], $method['endLine']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = [ + &$this->traits[$traitName], + &$this->traits[$traitName]['methods'][$methodName], + ]; + } + } + } + } + + /** + * @psalm-param array $functions + */ + private function processFunctions(array $functions): void + { + $link = $this->id() . '.html#'; + + foreach ($functions as $functionName => $function) { + $this->functions[$functionName] = [ + 'functionName' => $functionName, + 'namespace' => $function['namespace'], + 'signature' => $function['signature'], + 'startLine' => $function['startLine'], + 'endLine' => $function['endLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => $function['ccn'], + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $function['startLine'], + ]; + + foreach (range($function['startLine'], $function['endLine']) as $lineNumber) { + $this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]]; + } + + if (isset($this->functionCoverageData[$functionName]['branches'])) { + $this->functions[$functionName]['executableBranches'] = count( + $this->functionCoverageData[$functionName]['branches'], + ); + + $this->functions[$functionName]['executedBranches'] = count( + array_filter( + $this->functionCoverageData[$functionName]['branches'], + static function (array $branch) + { + return (bool) $branch['hit']; + }, + ), + ); + } + + if (isset($this->functionCoverageData[$functionName]['paths'])) { + $this->functions[$functionName]['executablePaths'] = count( + $this->functionCoverageData[$functionName]['paths'], + ); + + $this->functions[$functionName]['executedPaths'] = count( + array_filter( + $this->functionCoverageData[$functionName]['paths'], + static function (array $path) + { + return (bool) $path['hit']; + }, + ), + ); + } + + $this->numExecutableBranches += $this->functions[$functionName]['executableBranches']; + $this->numExecutedBranches += $this->functions[$functionName]['executedBranches']; + $this->numExecutablePaths += $this->functions[$functionName]['executablePaths']; + $this->numExecutedPaths += $this->functions[$functionName]['executedPaths']; + } + } + + /** + * @psalm-param CodeUnitMethodType $method + * + * @psalm-return ProcessedMethodType + */ + private function newMethod(string $className, string $methodName, array $method, string $link): array + { + $methodData = [ + 'methodName' => $methodName, + 'visibility' => $method['visibility'], + 'signature' => $method['signature'], + 'startLine' => $method['startLine'], + 'endLine' => $method['endLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'executableBranches' => 0, + 'executedBranches' => 0, + 'executablePaths' => 0, + 'executedPaths' => 0, + 'ccn' => $method['ccn'], + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $method['startLine'], + ]; + + $key = $className . '->' . $methodName; + + if (isset($this->functionCoverageData[$key]['branches'])) { + $methodData['executableBranches'] = count( + $this->functionCoverageData[$key]['branches'], + ); + + $methodData['executedBranches'] = count( + array_filter( + $this->functionCoverageData[$key]['branches'], + static function (array $branch) + { + return (bool) $branch['hit']; + }, + ), + ); + } + + if (isset($this->functionCoverageData[$key]['paths'])) { + $methodData['executablePaths'] = count( + $this->functionCoverageData[$key]['paths'], + ); + + $methodData['executedPaths'] = count( + array_filter( + $this->functionCoverageData[$key]['paths'], + static function (array $path) + { + return (bool) $path['hit']; + }, + ), + ); + } + + return $methodData; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Iterator.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Iterator.php new file mode 100644 index 000000000..b110d4679 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Node/Iterator.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Node; + +use function count; +use RecursiveIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Iterator implements RecursiveIterator +{ + private int $position; + + /** + * @var list + */ + private readonly array $nodes; + + public function __construct(Directory $node) + { + $this->nodes = $node->children(); + } + + /** + * Rewinds the Iterator to the first element. + */ + public function rewind(): void + { + $this->position = 0; + } + + /** + * Checks if there is a current element after calls to rewind() or next(). + */ + public function valid(): bool + { + return $this->position < count($this->nodes); + } + + /** + * Returns the key of the current element. + */ + public function key(): int + { + return $this->position; + } + + /** + * Returns the current element. + */ + public function current(): ?AbstractNode + { + return $this->valid() ? $this->nodes[$this->position] : null; + } + + /** + * Moves forward to next element. + */ + public function next(): void + { + $this->position++; + } + + /** + * Returns the sub iterator for the current element. + */ + public function getChildren(): self + { + return new self($this->nodes[$this->position]); + } + + /** + * Checks whether the current element has children. + */ + public function hasChildren(): bool + { + return $this->nodes[$this->position] instanceof Directory; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Clover.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Clover.php new file mode 100644 index 000000000..8a24236f9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Clover.php @@ -0,0 +1,258 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function count; +use function dirname; +use function file_put_contents; +use function is_string; +use function ksort; +use function max; +use function range; +use function str_contains; +use function time; +use DOMDocument; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Clover +{ + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string + { + $time = (string) time(); + + $xmlDocument = new DOMDocument('1.0', 'UTF-8'); + $xmlDocument->formatOutput = true; + + $xmlCoverage = $xmlDocument->createElement('coverage'); + $xmlCoverage->setAttribute('generated', $time); + $xmlDocument->appendChild($xmlCoverage); + + $xmlProject = $xmlDocument->createElement('project'); + $xmlProject->setAttribute('timestamp', $time); + + if (is_string($name)) { + $xmlProject->setAttribute('name', $name); + } + + $xmlCoverage->appendChild($xmlProject); + + $packages = []; + $report = $coverage->getReport(); + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + /* @var File $item */ + + $xmlFile = $xmlDocument->createElement('file'); + $xmlFile->setAttribute('name', $item->pathAsString()); + + $classes = $item->classesAndTraits(); + $coverageData = $item->lineCoverageData(); + $lines = []; + $namespace = 'global'; + + foreach ($classes as $className => $class) { + $classStatements = 0; + $coveredClassStatements = 0; + $coveredMethods = 0; + $classMethods = 0; + + foreach ($class['methods'] as $methodName => $method) { + if ($method['executableLines'] == 0) { + continue; + } + + $classMethods++; + $classStatements += $method['executableLines']; + $coveredClassStatements += $method['executedLines']; + + if ($method['coverage'] == 100) { + $coveredMethods++; + } + + $methodCount = 0; + + foreach (range($method['startLine'], $method['endLine']) as $line) { + if (isset($coverageData[$line])) { + $methodCount = max($methodCount, count($coverageData[$line])); + } + } + + $lines[$method['startLine']] = [ + 'ccn' => $method['ccn'], + 'count' => $methodCount, + 'crap' => $method['crap'], + 'type' => 'method', + 'visibility' => $method['visibility'], + 'name' => $methodName, + ]; + } + + if (!empty($class['package']['namespace'])) { + $namespace = $class['package']['namespace']; + } + + $xmlClass = $xmlDocument->createElement('class'); + $xmlClass->setAttribute('name', $className); + $xmlClass->setAttribute('namespace', $namespace); + + if (!empty($class['package']['fullPackage'])) { + $xmlClass->setAttribute( + 'fullPackage', + $class['package']['fullPackage'], + ); + } + + if (!empty($class['package']['category'])) { + $xmlClass->setAttribute( + 'category', + $class['package']['category'], + ); + } + + if (!empty($class['package']['package'])) { + $xmlClass->setAttribute( + 'package', + $class['package']['package'], + ); + } + + if (!empty($class['package']['subpackage'])) { + $xmlClass->setAttribute( + 'subpackage', + $class['package']['subpackage'], + ); + } + + $xmlFile->appendChild($xmlClass); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); + $xmlMetrics->setAttribute('methods', (string) $classMethods); + $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); + $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); + $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); + $xmlMetrics->setAttribute('statements', (string) $classStatements); + $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); + $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); + $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); + $xmlClass->appendChild($xmlMetrics); + } + + foreach ($coverageData as $line => $data) { + if ($data === null || isset($lines[$line])) { + continue; + } + + $lines[$line] = [ + 'count' => count($data), 'type' => 'stmt', + ]; + } + + ksort($lines); + + foreach ($lines as $line => $data) { + $xmlLine = $xmlDocument->createElement('line'); + $xmlLine->setAttribute('num', (string) $line); + $xmlLine->setAttribute('type', $data['type']); + + if (isset($data['name'])) { + $xmlLine->setAttribute('name', $data['name']); + } + + if (isset($data['visibility'])) { + $xmlLine->setAttribute('visibility', $data['visibility']); + } + + if (isset($data['ccn'])) { + $xmlLine->setAttribute('complexity', (string) $data['ccn']); + } + + if (isset($data['crap'])) { + $xmlLine->setAttribute('crap', (string) $data['crap']); + } + + $xmlLine->setAttribute('count', (string) $data['count']); + $xmlFile->appendChild($xmlLine); + } + + $linesOfCode = $item->linesOfCode(); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); + $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); + $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); + $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); + $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); + $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); + $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); + $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); + $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); + $xmlFile->appendChild($xmlMetrics); + + if ($namespace === 'global') { + $xmlProject->appendChild($xmlFile); + } else { + if (!isset($packages[$namespace])) { + $packages[$namespace] = $xmlDocument->createElement( + 'package', + ); + + $packages[$namespace]->setAttribute('name', $namespace); + $xmlProject->appendChild($packages[$namespace]); + } + + $packages[$namespace]->appendChild($xmlFile); + } + } + + $linesOfCode = $report->linesOfCode(); + + $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('files', (string) count($report)); + $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); + $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); + $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); + $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); + $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); + $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); + $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); + $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); + $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); + $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); + $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); + $xmlProject->appendChild($xmlMetrics); + + $buffer = $xmlDocument->saveXML(); + + if ($target !== null) { + if (!str_contains($target, '://')) { + Filesystem::createDirectory(dirname($target)); + } + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php new file mode 100644 index 000000000..7ff5582df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Cobertura.php @@ -0,0 +1,309 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function basename; +use function count; +use function dirname; +use function file_put_contents; +use function preg_match; +use function range; +use function str_contains; +use function str_replace; +use function time; +use DOMImplementation; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Cobertura +{ + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null): string + { + $time = (string) time(); + + $report = $coverage->getReport(); + + $implementation = new DOMImplementation; + + $documentType = $implementation->createDocumentType( + 'coverage', + '', + 'http://cobertura.sourceforge.net/xml/coverage-04.dtd', + ); + + $document = $implementation->createDocument('', '', $documentType); + $document->xmlVersion = '1.0'; + $document->encoding = 'UTF-8'; + $document->formatOutput = true; + + $coverageElement = $document->createElement('coverage'); + + $linesValid = $report->numberOfExecutableLines(); + $linesCovered = $report->numberOfExecutedLines(); + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + $coverageElement->setAttribute('line-rate', (string) $lineRate); + + $branchesValid = $report->numberOfExecutableBranches(); + $branchesCovered = $report->numberOfExecutedBranches(); + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + $coverageElement->setAttribute('branch-rate', (string) $branchRate); + + $coverageElement->setAttribute('lines-covered', (string) $report->numberOfExecutedLines()); + $coverageElement->setAttribute('lines-valid', (string) $report->numberOfExecutableLines()); + $coverageElement->setAttribute('branches-covered', (string) $report->numberOfExecutedBranches()); + $coverageElement->setAttribute('branches-valid', (string) $report->numberOfExecutableBranches()); + $coverageElement->setAttribute('complexity', ''); + $coverageElement->setAttribute('version', '0.4'); + $coverageElement->setAttribute('timestamp', $time); + + $document->appendChild($coverageElement); + + $sourcesElement = $document->createElement('sources'); + $coverageElement->appendChild($sourcesElement); + + $sourceElement = $document->createElement('source', $report->pathAsString()); + $sourcesElement->appendChild($sourceElement); + + $packagesElement = $document->createElement('packages'); + $coverageElement->appendChild($packagesElement); + + $complexity = 0; + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + $packageElement = $document->createElement('package'); + $packageComplexity = 0; + + $packageElement->setAttribute('name', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); + + $linesValid = $item->numberOfExecutableLines(); + $linesCovered = $item->numberOfExecutedLines(); + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $packageElement->setAttribute('line-rate', (string) $lineRate); + + $branchesValid = $item->numberOfExecutableBranches(); + $branchesCovered = $item->numberOfExecutedBranches(); + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $packageElement->setAttribute('branch-rate', (string) $branchRate); + + $packageElement->setAttribute('complexity', ''); + $packagesElement->appendChild($packageElement); + + $classesElement = $document->createElement('classes'); + + $packageElement->appendChild($classesElement); + + $classes = $item->classesAndTraits(); + $coverageData = $item->lineCoverageData(); + + foreach ($classes as $className => $class) { + $complexity += $class['ccn']; + $packageComplexity += $class['ccn']; + + if (!empty($class['package']['namespace'])) { + $className = $class['package']['namespace'] . '\\' . $className; + } + + $linesValid = $class['executableLines']; + $linesCovered = $class['executedLines']; + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $branchesValid = $class['executableBranches']; + $branchesCovered = $class['executedBranches']; + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $classElement = $document->createElement('class'); + + $classElement->setAttribute('name', $className); + $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); + $classElement->setAttribute('line-rate', (string) $lineRate); + $classElement->setAttribute('branch-rate', (string) $branchRate); + $classElement->setAttribute('complexity', (string) $class['ccn']); + + $classesElement->appendChild($classElement); + + $methodsElement = $document->createElement('methods'); + + $classElement->appendChild($methodsElement); + + $classLinesElement = $document->createElement('lines'); + + $classElement->appendChild($classLinesElement); + + foreach ($class['methods'] as $methodName => $method) { + if ($method['executableLines'] === 0) { + continue; + } + + preg_match("/\((.*?)\)/", $method['signature'], $signature); + + $linesValid = $method['executableLines']; + $linesCovered = $method['executedLines']; + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $branchesValid = $method['executableBranches']; + $branchesCovered = $method['executedBranches']; + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $methodElement = $document->createElement('method'); + + $methodElement->setAttribute('name', $methodName); + $methodElement->setAttribute('signature', $signature[1]); + $methodElement->setAttribute('line-rate', (string) $lineRate); + $methodElement->setAttribute('branch-rate', (string) $branchRate); + $methodElement->setAttribute('complexity', (string) $method['ccn']); + + $methodLinesElement = $document->createElement('lines'); + + $methodElement->appendChild($methodLinesElement); + + foreach (range($method['startLine'], $method['endLine']) as $line) { + if (!isset($coverageData[$line])) { + continue; + } + $methodLineElement = $document->createElement('line'); + + $methodLineElement->setAttribute('number', (string) $line); + $methodLineElement->setAttribute('hits', (string) count($coverageData[$line])); + + $methodLinesElement->appendChild($methodLineElement); + + $classLineElement = $methodLineElement->cloneNode(); + + $classLinesElement->appendChild($classLineElement); + } + + $methodsElement->appendChild($methodElement); + } + } + + if ($item->numberOfFunctions() === 0) { + $packageElement->setAttribute('complexity', (string) $packageComplexity); + + continue; + } + + $functionsComplexity = 0; + $functionsLinesValid = 0; + $functionsLinesCovered = 0; + $functionsBranchesValid = 0; + $functionsBranchesCovered = 0; + + $classElement = $document->createElement('class'); + $classElement->setAttribute('name', basename($item->pathAsString())); + $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); + + $methodsElement = $document->createElement('methods'); + + $classElement->appendChild($methodsElement); + + $classLinesElement = $document->createElement('lines'); + + $classElement->appendChild($classLinesElement); + + $functions = $item->functions(); + + foreach ($functions as $functionName => $function) { + if ($function['executableLines'] === 0) { + continue; + } + + $complexity += $function['ccn']; + $packageComplexity += $function['ccn']; + $functionsComplexity += $function['ccn']; + + $linesValid = $function['executableLines']; + $linesCovered = $function['executedLines']; + $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); + + $functionsLinesValid += $linesValid; + $functionsLinesCovered += $linesCovered; + + $branchesValid = $function['executableBranches']; + $branchesCovered = $function['executedBranches']; + $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); + + $functionsBranchesValid += $branchesValid; + $functionsBranchesCovered += $branchesValid; + + $methodElement = $document->createElement('method'); + + $methodElement->setAttribute('name', $functionName); + $methodElement->setAttribute('signature', $function['signature']); + $methodElement->setAttribute('line-rate', (string) $lineRate); + $methodElement->setAttribute('branch-rate', (string) $branchRate); + $methodElement->setAttribute('complexity', (string) $function['ccn']); + + $methodLinesElement = $document->createElement('lines'); + + $methodElement->appendChild($methodLinesElement); + + foreach (range($function['startLine'], $function['endLine']) as $line) { + if (!isset($coverageData[$line])) { + continue; + } + $methodLineElement = $document->createElement('line'); + + $methodLineElement->setAttribute('number', (string) $line); + $methodLineElement->setAttribute('hits', (string) count($coverageData[$line])); + + $methodLinesElement->appendChild($methodLineElement); + + $classLineElement = $methodLineElement->cloneNode(); + + $classLinesElement->appendChild($classLineElement); + } + + $methodsElement->appendChild($methodElement); + } + + $packageElement->setAttribute('complexity', (string) $packageComplexity); + + if ($functionsLinesValid === 0) { + continue; + } + + $lineRate = $functionsLinesCovered / $functionsLinesValid; + $branchRate = $functionsBranchesValid === 0 ? 0 : ($functionsBranchesCovered / $functionsBranchesValid); + + $classElement->setAttribute('line-rate', (string) $lineRate); + $classElement->setAttribute('branch-rate', (string) $branchRate); + $classElement->setAttribute('complexity', (string) $functionsComplexity); + + $classesElement->appendChild($classElement); + } + + $coverageElement->setAttribute('complexity', (string) $complexity); + + $buffer = $document->saveXML(); + + if ($target !== null) { + if (!str_contains($target, '://')) { + Filesystem::createDirectory(dirname($target)); + } + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php new file mode 100644 index 000000000..cb1bde605 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Crap4j.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use function date; +use function dirname; +use function file_put_contents; +use function htmlspecialchars; +use function is_string; +use function round; +use function str_contains; +use DOMDocument; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class Crap4j +{ + private readonly int $threshold; + + public function __construct(int $threshold = 30) + { + $this->threshold = $threshold; + } + + /** + * @throws WriteOperationFailedException + */ + public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string + { + $document = new DOMDocument('1.0', 'UTF-8'); + $document->formatOutput = true; + + $root = $document->createElement('crap_result'); + $document->appendChild($root); + + $project = $document->createElement('project', is_string($name) ? $name : ''); + $root->appendChild($project); + $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s'))); + + $stats = $document->createElement('stats'); + $methodsNode = $document->createElement('methods'); + + $report = $coverage->getReport(); + unset($coverage); + + $fullMethodCount = 0; + $fullCrapMethodCount = 0; + $fullCrapLoad = 0; + $fullCrap = 0; + + foreach ($report as $item) { + $namespace = 'global'; + + if (!$item instanceof File) { + continue; + } + + $file = $document->createElement('file'); + $file->setAttribute('name', $item->pathAsString()); + + $classes = $item->classesAndTraits(); + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + $crapLoad = $this->crapLoad((float) $method['crap'], $method['ccn'], $method['coverage']); + + $fullCrap += $method['crap']; + $fullCrapLoad += $crapLoad; + $fullMethodCount++; + + if ($method['crap'] >= $this->threshold) { + $fullCrapMethodCount++; + } + + $methodNode = $document->createElement('method'); + + if (!empty($class['namespace'])) { + $namespace = $class['namespace']; + } + + $methodNode->appendChild($document->createElement('package', $namespace)); + $methodNode->appendChild($document->createElement('className', $className)); + $methodNode->appendChild($document->createElement('methodName', $methodName)); + $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature']))); + $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature']))); + $methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method['crap']))); + $methodNode->appendChild($document->createElement('complexity', (string) $method['ccn'])); + $methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method['coverage']))); + $methodNode->appendChild($document->createElement('crapLoad', (string) round($crapLoad))); + + $methodsNode->appendChild($methodNode); + } + } + } + + $stats->appendChild($document->createElement('name', 'Method Crap Stats')); + $stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount)); + $stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount)); + $stats->appendChild($document->createElement('crapLoad', (string) round($fullCrapLoad))); + $stats->appendChild($document->createElement('totalCrap', (string) $fullCrap)); + + $crapMethodPercent = 0; + + if ($fullMethodCount > 0) { + $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount); + } + + $stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent)); + + $root->appendChild($stats); + $root->appendChild($methodsNode); + + $buffer = $document->saveXML(); + + if ($target !== null) { + if (!str_contains($target, '://')) { + Filesystem::createDirectory(dirname($target)); + } + + if (@file_put_contents($target, $buffer) === false) { + throw new WriteOperationFailedException($target); + } + } + + return $buffer; + } + + private function crapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent): float + { + $crapLoad = 0; + + if ($crapValue >= $this->threshold) { + $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100); + $crapLoad += $cyclomaticComplexity / $this->threshold; + } + + return $crapLoad; + } + + private function roundValue(float $value): float + { + return round($value, 2); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Colors.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Colors.php new file mode 100644 index 000000000..25ca9034b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Colors.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +/** + * @psalm-immutable + */ +final class Colors +{ + private readonly string $successLow; + private readonly string $successMedium; + private readonly string $successHigh; + private readonly string $warning; + private readonly string $danger; + + public static function default(): self + { + return new self('#dff0d8', '#c3e3b5', '#99cb84', '#fcf8e3', '#f2dede'); + } + + public static function from(string $successLow, string $successMedium, string $successHigh, string $warning, string $danger): self + { + return new self($successLow, $successMedium, $successHigh, $warning, $danger); + } + + private function __construct(string $successLow, string $successMedium, string $successHigh, string $warning, string $danger) + { + $this->successLow = $successLow; + $this->successMedium = $successMedium; + $this->successHigh = $successHigh; + $this->warning = $warning; + $this->danger = $danger; + } + + public function successLow(): string + { + return $this->successLow; + } + + public function successMedium(): string + { + return $this->successMedium; + } + + public function successHigh(): string + { + return $this->successHigh; + } + + public function warning(): string + { + return $this->warning; + } + + public function danger(): string + { + return $this->danger; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php new file mode 100644 index 000000000..70a7230c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/CustomCssFile.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function is_file; +use SebastianBergmann\CodeCoverage\InvalidArgumentException; + +/** + * @psalm-immutable + */ +final class CustomCssFile +{ + private readonly string $path; + + public static function default(): self + { + return new self(__DIR__ . '/Renderer/Template/css/custom.css'); + } + + /** + * @throws InvalidArgumentException + */ + public static function from(string $path): self + { + if (!is_file($path)) { + throw new InvalidArgumentException( + '$path does not exist', + ); + } + + return new self($path); + } + + private function __construct(string $path) + { + $this->path = $path; + } + + public function path(): string + { + return $this->path; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php new file mode 100644 index 000000000..b376eb5d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use const DIRECTORY_SEPARATOR; +use function copy; +use function date; +use function dirname; +use function str_ends_with; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Report\Thresholds; +use SebastianBergmann\CodeCoverage\Util\Filesystem; +use SebastianBergmann\Template\Exception; +use SebastianBergmann\Template\Template; + +final class Facade +{ + private readonly string $templatePath; + private readonly string $generator; + private readonly Colors $colors; + private readonly Thresholds $thresholds; + private readonly CustomCssFile $customCssFile; + + public function __construct(string $generator = '', ?Colors $colors = null, ?Thresholds $thresholds = null, ?CustomCssFile $customCssFile = null) + { + $this->generator = $generator; + $this->colors = $colors ?? Colors::default(); + $this->thresholds = $thresholds ?? Thresholds::default(); + $this->customCssFile = $customCssFile ?? CustomCssFile::default(); + $this->templatePath = __DIR__ . '/Renderer/Template/'; + } + + public function process(CodeCoverage $coverage, string $target): void + { + $target = $this->directory($target); + $report = $coverage->getReport(); + $date = date('D M j G:i:s T Y'); + + $dashboard = new Dashboard( + $this->templatePath, + $this->generator, + $date, + $this->thresholds, + $coverage->collectsBranchAndPathCoverage(), + ); + + $directory = new Directory( + $this->templatePath, + $this->generator, + $date, + $this->thresholds, + $coverage->collectsBranchAndPathCoverage(), + ); + + $file = new File( + $this->templatePath, + $this->generator, + $date, + $this->thresholds, + $coverage->collectsBranchAndPathCoverage(), + ); + + $directory->render($report, $target . 'index.html'); + $dashboard->render($report, $target . 'dashboard.html'); + + foreach ($report as $node) { + $id = $node->id(); + + if ($node instanceof DirectoryNode) { + Filesystem::createDirectory($target . $id); + + $directory->render($node, $target . $id . '/index.html'); + $dashboard->render($node, $target . $id . '/dashboard.html'); + } else { + $dir = dirname($target . $id); + + Filesystem::createDirectory($dir); + + $file->render($node, $target . $id); + } + } + + $this->copyFiles($target); + $this->renderCss($target); + } + + private function copyFiles(string $target): void + { + $dir = $this->directory($target . '_css'); + + copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css'); + copy($this->templatePath . 'css/nv.d3.min.css', $dir . 'nv.d3.min.css'); + copy($this->customCssFile->path(), $dir . 'custom.css'); + copy($this->templatePath . 'css/octicons.css', $dir . 'octicons.css'); + + $dir = $this->directory($target . '_icons'); + copy($this->templatePath . 'icons/file-code.svg', $dir . 'file-code.svg'); + copy($this->templatePath . 'icons/file-directory.svg', $dir . 'file-directory.svg'); + + $dir = $this->directory($target . '_js'); + copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js'); + copy($this->templatePath . 'js/popper.min.js', $dir . 'popper.min.js'); + copy($this->templatePath . 'js/d3.min.js', $dir . 'd3.min.js'); + copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js'); + copy($this->templatePath . 'js/nv.d3.min.js', $dir . 'nv.d3.min.js'); + copy($this->templatePath . 'js/file.js', $dir . 'file.js'); + } + + private function renderCss(string $target): void + { + $template = new Template($this->templatePath . 'css/style.css', '{{', '}}'); + + $template->setVar( + [ + 'success-low' => $this->colors->successLow(), + 'success-medium' => $this->colors->successMedium(), + 'success-high' => $this->colors->successHigh(), + 'warning' => $this->colors->warning(), + 'danger' => $this->colors->danger(), + ], + ); + + try { + $template->renderTo($this->directory($target . '_css') . 'style.css'); + } catch (Exception $e) { + throw new FileCouldNotBeWrittenException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } + + private function directory(string $directory): string + { + if (!str_ends_with($directory, DIRECTORY_SEPARATOR)) { + $directory .= DIRECTORY_SEPARATOR; + } + + Filesystem::createDirectory($directory); + + return $directory; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php new file mode 100644 index 000000000..6ce7b8fe4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer.php @@ -0,0 +1,286 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function array_pop; +use function count; +use function sprintf; +use function str_repeat; +use function substr_count; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Report\Thresholds; +use SebastianBergmann\CodeCoverage\Version; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class Renderer +{ + protected string $templatePath; + protected string $generator; + protected string $date; + protected Thresholds $thresholds; + protected bool $hasBranchCoverage; + protected string $version; + + public function __construct(string $templatePath, string $generator, string $date, Thresholds $thresholds, bool $hasBranchCoverage) + { + $this->templatePath = $templatePath; + $this->generator = $generator; + $this->date = $date; + $this->thresholds = $thresholds; + $this->version = Version::id(); + $this->hasBranchCoverage = $hasBranchCoverage; + } + + protected function renderItemTemplate(Template $template, array $data): string + { + $numSeparator = ' / '; + + if (isset($data['numClasses']) && $data['numClasses'] > 0) { + $classesLevel = $this->colorLevel($data['testedClassesPercent']); + + $classesNumber = $data['numTestedClasses'] . $numSeparator . + $data['numClasses']; + + $classesBar = $this->coverageBar( + $data['testedClassesPercent'], + ); + } else { + $classesLevel = ''; + $classesNumber = '0' . $numSeparator . '0'; + $classesBar = ''; + $data['testedClassesPercentAsString'] = 'n/a'; + } + + if ($data['numMethods'] > 0) { + $methodsLevel = $this->colorLevel($data['testedMethodsPercent']); + + $methodsNumber = $data['numTestedMethods'] . $numSeparator . + $data['numMethods']; + + $methodsBar = $this->coverageBar( + $data['testedMethodsPercent'], + ); + } else { + $methodsLevel = ''; + $methodsNumber = '0' . $numSeparator . '0'; + $methodsBar = ''; + $data['testedMethodsPercentAsString'] = 'n/a'; + } + + if ($data['numExecutableLines'] > 0) { + $linesLevel = $this->colorLevel($data['linesExecutedPercent']); + + $linesNumber = $data['numExecutedLines'] . $numSeparator . + $data['numExecutableLines']; + + $linesBar = $this->coverageBar( + $data['linesExecutedPercent'], + ); + } else { + $linesLevel = ''; + $linesNumber = '0' . $numSeparator . '0'; + $linesBar = ''; + $data['linesExecutedPercentAsString'] = 'n/a'; + } + + if ($data['numExecutablePaths'] > 0) { + $pathsLevel = $this->colorLevel($data['pathsExecutedPercent']); + + $pathsNumber = $data['numExecutedPaths'] . $numSeparator . + $data['numExecutablePaths']; + + $pathsBar = $this->coverageBar( + $data['pathsExecutedPercent'], + ); + } else { + $pathsLevel = ''; + $pathsNumber = '0' . $numSeparator . '0'; + $pathsBar = ''; + $data['pathsExecutedPercentAsString'] = 'n/a'; + } + + if ($data['numExecutableBranches'] > 0) { + $branchesLevel = $this->colorLevel($data['branchesExecutedPercent']); + + $branchesNumber = $data['numExecutedBranches'] . $numSeparator . + $data['numExecutableBranches']; + + $branchesBar = $this->coverageBar( + $data['branchesExecutedPercent'], + ); + } else { + $branchesLevel = ''; + $branchesNumber = '0' . $numSeparator . '0'; + $branchesBar = ''; + $data['branchesExecutedPercentAsString'] = 'n/a'; + } + + $template->setVar( + [ + 'icon' => $data['icon'] ?? '', + 'crap' => $data['crap'] ?? '', + 'name' => $data['name'], + 'lines_bar' => $linesBar, + 'lines_executed_percent' => $data['linesExecutedPercentAsString'], + 'lines_level' => $linesLevel, + 'lines_number' => $linesNumber, + 'paths_bar' => $pathsBar, + 'paths_executed_percent' => $data['pathsExecutedPercentAsString'], + 'paths_level' => $pathsLevel, + 'paths_number' => $pathsNumber, + 'branches_bar' => $branchesBar, + 'branches_executed_percent' => $data['branchesExecutedPercentAsString'], + 'branches_level' => $branchesLevel, + 'branches_number' => $branchesNumber, + 'methods_bar' => $methodsBar, + 'methods_tested_percent' => $data['testedMethodsPercentAsString'], + 'methods_level' => $methodsLevel, + 'methods_number' => $methodsNumber, + 'classes_bar' => $classesBar, + 'classes_tested_percent' => $data['testedClassesPercentAsString'] ?? '', + 'classes_level' => $classesLevel, + 'classes_number' => $classesNumber, + ], + ); + + return $template->render(); + } + + protected function setCommonTemplateVariables(Template $template, AbstractNode $node): void + { + $template->setVar( + [ + 'id' => $node->id(), + 'full_path' => $node->pathAsString(), + 'path_to_root' => $this->pathToRoot($node), + 'breadcrumbs' => $this->breadcrumbs($node), + 'date' => $this->date, + 'version' => $this->version, + 'runtime' => $this->runtimeString(), + 'generator' => $this->generator, + 'low_upper_bound' => $this->thresholds->lowUpperBound(), + 'high_lower_bound' => $this->thresholds->highLowerBound(), + ], + ); + } + + protected function breadcrumbs(AbstractNode $node): string + { + $breadcrumbs = ''; + $path = $node->pathAsArray(); + $pathToRoot = []; + $max = count($path); + + if ($node instanceof FileNode) { + $max--; + } + + for ($i = 0; $i < $max; $i++) { + $pathToRoot[] = str_repeat('../', $i); + } + + foreach ($path as $step) { + if ($step !== $node) { + $breadcrumbs .= $this->inactiveBreadcrumb( + $step, + array_pop($pathToRoot), + ); + } else { + $breadcrumbs .= $this->activeBreadcrumb($step); + } + } + + return $breadcrumbs; + } + + protected function activeBreadcrumb(AbstractNode $node): string + { + $buffer = sprintf( + '

      ' . "\n", + $node->name(), + ); + + if ($node instanceof DirectoryNode) { + $buffer .= ' ' . "\n"; + } + + return $buffer; + } + + protected function inactiveBreadcrumb(AbstractNode $node, string $pathToRoot): string + { + return sprintf( + ' ' . "\n", + $pathToRoot, + $node->name(), + ); + } + + protected function pathToRoot(AbstractNode $node): string + { + $id = $node->id(); + $depth = substr_count($id, '/'); + + if ($id !== 'index' && + $node instanceof DirectoryNode) { + $depth++; + } + + return str_repeat('../', $depth); + } + + protected function coverageBar(float $percent): string + { + $level = $this->colorLevel($percent); + + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'coverage_bar_branch.html' : 'coverage_bar.html'); + $template = new Template( + $templateName, + '{{', + '}}', + ); + + $template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]); + + return $template->render(); + } + + protected function colorLevel(float $percent): string + { + if ($percent <= $this->thresholds->lowUpperBound()) { + return 'danger'; + } + + if ($percent > $this->thresholds->lowUpperBound() && + $percent < $this->thresholds->highLowerBound()) { + return 'warning'; + } + + return 'success'; + } + + private function runtimeString(): string + { + $runtime = new Runtime; + + return sprintf( + '%s %s', + $runtime->getVendorUrl(), + $runtime->getName(), + $runtime->getVersion(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php new file mode 100644 index 000000000..cf21cf9dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Dashboard.php @@ -0,0 +1,298 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function array_values; +use function arsort; +use function asort; +use function count; +use function explode; +use function floor; +use function json_encode; +use function sprintf; +use function str_replace; +use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\Template\Exception; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Dashboard extends Renderer +{ + public function render(DirectoryNode $node, string $file): void + { + $classes = $node->classesAndTraits(); + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'dashboard_branch.html' : 'dashboard.html'); + $template = new Template( + $templateName, + '{{', + '}}', + ); + + $this->setCommonTemplateVariables($template, $node); + + $baseLink = $node->id() . '/'; + $complexity = $this->complexity($classes, $baseLink); + $coverageDistribution = $this->coverageDistribution($classes); + $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink); + $projectRisks = $this->projectRisks($classes, $baseLink); + + $template->setVar( + [ + 'insufficient_coverage_classes' => $insufficientCoverage['class'], + 'insufficient_coverage_methods' => $insufficientCoverage['method'], + 'project_risks_classes' => $projectRisks['class'], + 'project_risks_methods' => $projectRisks['method'], + 'complexity_class' => $complexity['class'], + 'complexity_method' => $complexity['method'], + 'class_coverage_distribution' => $coverageDistribution['class'], + 'method_coverage_distribution' => $coverageDistribution['method'], + ], + ); + + try { + $template->renderTo($file); + } catch (Exception $e) { + throw new FileCouldNotBeWrittenException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } + + protected function activeBreadcrumb(AbstractNode $node): string + { + return sprintf( + ' ' . "\n" . + ' ' . "\n", + $node->name(), + ); + } + + /** + * Returns the data for the Class/Method Complexity charts. + */ + private function complexity(array $classes, string $baseLink): array + { + $result = ['class' => [], 'method' => []]; + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($className !== '*') { + $methodName = $className . '::' . $methodName; + } + + $result['method'][] = [ + $method['coverage'], + $method['ccn'], + sprintf( + '%s', + str_replace($baseLink, '', $method['link']), + $methodName, + ), + ]; + } + + $result['class'][] = [ + $class['coverage'], + $class['ccn'], + sprintf( + '%s', + str_replace($baseLink, '', $class['link']), + $className, + ), + ]; + } + + return [ + 'class' => json_encode($result['class']), + 'method' => json_encode($result['method']), + ]; + } + + /** + * Returns the data for the Class / Method Coverage Distribution chart. + */ + private function coverageDistribution(array $classes): array + { + $result = [ + 'class' => [ + '0%' => 0, + '0-10%' => 0, + '10-20%' => 0, + '20-30%' => 0, + '30-40%' => 0, + '40-50%' => 0, + '50-60%' => 0, + '60-70%' => 0, + '70-80%' => 0, + '80-90%' => 0, + '90-100%' => 0, + '100%' => 0, + ], + 'method' => [ + '0%' => 0, + '0-10%' => 0, + '10-20%' => 0, + '20-30%' => 0, + '30-40%' => 0, + '40-50%' => 0, + '50-60%' => 0, + '60-70%' => 0, + '70-80%' => 0, + '80-90%' => 0, + '90-100%' => 0, + '100%' => 0, + ], + ]; + + foreach ($classes as $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] === 0) { + $result['method']['0%']++; + } elseif ($method['coverage'] === 100) { + $result['method']['100%']++; + } else { + $key = floor($method['coverage'] / 10) * 10; + $key = $key . '-' . ($key + 10) . '%'; + $result['method'][$key]++; + } + } + + if ($class['coverage'] === 0) { + $result['class']['0%']++; + } elseif ($class['coverage'] === 100) { + $result['class']['100%']++; + } else { + $key = floor($class['coverage'] / 10) * 10; + $key = $key . '-' . ($key + 10) . '%'; + $result['class'][$key]++; + } + } + + return [ + 'class' => json_encode(array_values($result['class'])), + 'method' => json_encode(array_values($result['method'])), + ]; + } + + /** + * Returns the classes / methods with insufficient coverage. + */ + private function insufficientCoverage(array $classes, string $baseLink): array + { + $leastTestedClasses = []; + $leastTestedMethods = []; + $result = ['class' => '', 'method' => '']; + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] < $this->thresholds->highLowerBound()) { + $key = $methodName; + + if ($className !== '*') { + $key = $className . '::' . $methodName; + } + + $leastTestedMethods[$key] = $method['coverage']; + } + } + + if ($class['coverage'] < $this->thresholds->highLowerBound()) { + $leastTestedClasses[$className] = $class['coverage']; + } + } + + asort($leastTestedClasses); + asort($leastTestedMethods); + + foreach ($leastTestedClasses as $className => $coverage) { + $result['class'] .= sprintf( + ' %s%d%%' . "\n", + str_replace($baseLink, '', $classes[$className]['link']), + $className, + $coverage, + ); + } + + foreach ($leastTestedMethods as $methodName => $coverage) { + [$class, $method] = explode('::', $methodName); + + $result['method'] .= sprintf( + ' %s%d%%' . "\n", + str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), + $methodName, + $method, + $coverage, + ); + } + + return $result; + } + + /** + * Returns the project risks according to the CRAP index. + */ + private function projectRisks(array $classes, string $baseLink): array + { + $classRisks = []; + $methodRisks = []; + $result = ['class' => '', 'method' => '']; + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] < $this->thresholds->highLowerBound() && $method['ccn'] > 1) { + $key = $methodName; + + if ($className !== '*') { + $key = $className . '::' . $methodName; + } + + $methodRisks[$key] = $method['crap']; + } + } + + if ($class['coverage'] < $this->thresholds->highLowerBound() && + $class['ccn'] > count($class['methods'])) { + $classRisks[$className] = $class['crap']; + } + } + + arsort($classRisks); + arsort($methodRisks); + + foreach ($classRisks as $className => $crap) { + $result['class'] .= sprintf( + ' %s%d' . "\n", + str_replace($baseLink, '', $classes[$className]['link']), + $className, + $crap, + ); + } + + foreach ($methodRisks as $methodName => $crap) { + [$class, $method] = explode('::', $methodName); + + $result['method'] .= sprintf( + ' %s%d' . "\n", + str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), + $methodName, + $method, + $crap, + ); + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php new file mode 100644 index 000000000..1d7334b3a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Directory.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use function count; +use function sprintf; +use function str_repeat; +use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; +use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\Template\Exception; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Directory extends Renderer +{ + public function render(DirectoryNode $node, string $file): void + { + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_branch.html' : 'directory.html'); + $template = new Template($templateName, '{{', '}}'); + + $this->setCommonTemplateVariables($template, $node); + + $items = $this->renderItem($node, true); + + foreach ($node->directories() as $item) { + $items .= $this->renderItem($item); + } + + foreach ($node->files() as $item) { + $items .= $this->renderItem($item); + } + + $template->setVar( + [ + 'id' => $node->id(), + 'items' => $items, + ], + ); + + try { + $template->renderTo($file); + } catch (Exception $e) { + throw new FileCouldNotBeWrittenException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } + + private function renderItem(Node $node, bool $total = false): string + { + $data = [ + 'numClasses' => $node->numberOfClassesAndTraits(), + 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), + 'numMethods' => $node->numberOfFunctionsAndMethods(), + 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), + 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), + 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), + 'numExecutedLines' => $node->numberOfExecutedLines(), + 'numExecutableLines' => $node->numberOfExecutableLines(), + 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), + 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), + 'numExecutedBranches' => $node->numberOfExecutedBranches(), + 'numExecutableBranches' => $node->numberOfExecutableBranches(), + 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), + 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), + 'numExecutedPaths' => $node->numberOfExecutedPaths(), + 'numExecutablePaths' => $node->numberOfExecutablePaths(), + 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), + 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), + 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), + 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), + ]; + + if ($total) { + $data['name'] = 'Total'; + } else { + $up = str_repeat('../', count($node->pathAsArray()) - 2); + $data['icon'] = sprintf('', $up); + + if ($node instanceof DirectoryNode) { + $data['name'] = sprintf( + '%s', + $node->name(), + $node->name(), + ); + $data['icon'] = sprintf('', $up); + } elseif ($this->hasBranchCoverage) { + $data['name'] = sprintf( + '%s [line] [branch] [path]', + $node->name(), + $node->name(), + $node->name(), + $node->name(), + ); + } else { + $data['name'] = sprintf( + '%s', + $node->name(), + $node->name(), + ); + } + } + + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'directory_item_branch.html' : 'directory_item.html'); + + return $this->renderItemTemplate( + new Template($templateName, '{{', '}}'), + $data, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php new file mode 100644 index 000000000..005c1db3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/File.php @@ -0,0 +1,1130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use const ENT_COMPAT; +use const ENT_HTML401; +use const ENT_SUBSTITUTE; +use const T_ABSTRACT; +use const T_ARRAY; +use const T_AS; +use const T_BREAK; +use const T_CALLABLE; +use const T_CASE; +use const T_CATCH; +use const T_CLASS; +use const T_CLONE; +use const T_COMMENT; +use const T_CONST; +use const T_CONTINUE; +use const T_DECLARE; +use const T_DEFAULT; +use const T_DO; +use const T_DOC_COMMENT; +use const T_ECHO; +use const T_ELSE; +use const T_ELSEIF; +use const T_EMPTY; +use const T_ENDDECLARE; +use const T_ENDFOR; +use const T_ENDFOREACH; +use const T_ENDIF; +use const T_ENDSWITCH; +use const T_ENDWHILE; +use const T_EVAL; +use const T_EXIT; +use const T_EXTENDS; +use const T_FINAL; +use const T_FINALLY; +use const T_FOR; +use const T_FOREACH; +use const T_FUNCTION; +use const T_GLOBAL; +use const T_GOTO; +use const T_HALT_COMPILER; +use const T_IF; +use const T_IMPLEMENTS; +use const T_INCLUDE; +use const T_INCLUDE_ONCE; +use const T_INLINE_HTML; +use const T_INSTANCEOF; +use const T_INSTEADOF; +use const T_INTERFACE; +use const T_ISSET; +use const T_LIST; +use const T_NAMESPACE; +use const T_NEW; +use const T_PRINT; +use const T_PRIVATE; +use const T_PROTECTED; +use const T_PUBLIC; +use const T_REQUIRE; +use const T_REQUIRE_ONCE; +use const T_RETURN; +use const T_STATIC; +use const T_SWITCH; +use const T_THROW; +use const T_TRAIT; +use const T_TRY; +use const T_UNSET; +use const T_USE; +use const T_VAR; +use const T_WHILE; +use const T_YIELD; +use const T_YIELD_FROM; +use function array_key_exists; +use function array_keys; +use function array_merge; +use function array_pop; +use function array_unique; +use function count; +use function explode; +use function file_get_contents; +use function htmlspecialchars; +use function is_string; +use function ksort; +use function range; +use function sort; +use function sprintf; +use function str_ends_with; +use function str_replace; +use function token_get_all; +use function trim; +use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Util\Percentage; +use SebastianBergmann\Template\Exception; +use SebastianBergmann\Template\Template; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class File extends Renderer +{ + /** + * @psalm-var array + */ + private const KEYWORD_TOKENS = [ + T_ABSTRACT => true, + T_ARRAY => true, + T_AS => true, + T_BREAK => true, + T_CALLABLE => true, + T_CASE => true, + T_CATCH => true, + T_CLASS => true, + T_CLONE => true, + T_CONST => true, + T_CONTINUE => true, + T_DECLARE => true, + T_DEFAULT => true, + T_DO => true, + T_ECHO => true, + T_ELSE => true, + T_ELSEIF => true, + T_EMPTY => true, + T_ENDDECLARE => true, + T_ENDFOR => true, + T_ENDFOREACH => true, + T_ENDIF => true, + T_ENDSWITCH => true, + T_ENDWHILE => true, + T_ENUM => true, + T_EVAL => true, + T_EXIT => true, + T_EXTENDS => true, + T_FINAL => true, + T_FINALLY => true, + T_FN => true, + T_FOR => true, + T_FOREACH => true, + T_FUNCTION => true, + T_GLOBAL => true, + T_GOTO => true, + T_HALT_COMPILER => true, + T_IF => true, + T_IMPLEMENTS => true, + T_INCLUDE => true, + T_INCLUDE_ONCE => true, + T_INSTANCEOF => true, + T_INSTEADOF => true, + T_INTERFACE => true, + T_ISSET => true, + T_LIST => true, + T_MATCH => true, + T_NAMESPACE => true, + T_NEW => true, + T_PRINT => true, + T_PRIVATE => true, + T_PROTECTED => true, + T_PUBLIC => true, + T_READONLY => true, + T_REQUIRE => true, + T_REQUIRE_ONCE => true, + T_RETURN => true, + T_STATIC => true, + T_SWITCH => true, + T_THROW => true, + T_TRAIT => true, + T_TRY => true, + T_UNSET => true, + T_USE => true, + T_VAR => true, + T_WHILE => true, + T_YIELD => true, + T_YIELD_FROM => true, + ]; + private static array $formattedSourceCache = []; + private int $htmlSpecialCharsFlags = ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE; + + public function render(FileNode $node, string $file): void + { + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_branch.html' : 'file.html'); + $template = new Template($templateName, '{{', '}}'); + $this->setCommonTemplateVariables($template, $node); + + $template->setVar( + [ + 'items' => $this->renderItems($node), + 'lines' => $this->renderSourceWithLineCoverage($node), + 'legend' => '

      Covered by small (and larger) testsCovered by medium (and large) testsCovered by large tests (and tests of unknown size)Not coveredNot coverable

      ', + 'structure' => '', + ], + ); + + try { + $template->renderTo($file . '.html'); + } catch (Exception $e) { + throw new FileCouldNotBeWrittenException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + if ($this->hasBranchCoverage) { + $template->setVar( + [ + 'items' => $this->renderItems($node), + 'lines' => $this->renderSourceWithBranchCoverage($node), + 'legend' => '

      Fully coveredPartially coveredNot covered

      ', + 'structure' => $this->renderBranchStructure($node), + ], + ); + + try { + $template->renderTo($file . '_branch.html'); + } catch (Exception $e) { + throw new FileCouldNotBeWrittenException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + $template->setVar( + [ + 'items' => $this->renderItems($node), + 'lines' => $this->renderSourceWithPathCoverage($node), + 'legend' => '

      Fully coveredPartially coveredNot covered

      ', + 'structure' => $this->renderPathStructure($node), + ], + ); + + try { + $template->renderTo($file . '_path.html'); + } catch (Exception $e) { + throw new FileCouldNotBeWrittenException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } + } + + private function renderItems(FileNode $node): string + { + $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_item_branch.html' : 'file_item.html'); + $template = new Template($templateName, '{{', '}}'); + + $methodTemplateName = $this->templatePath . ($this->hasBranchCoverage ? 'method_item_branch.html' : 'method_item.html'); + $methodItemTemplate = new Template( + $methodTemplateName, + '{{', + '}}', + ); + + $items = $this->renderItemTemplate( + $template, + [ + 'name' => 'Total', + 'numClasses' => $node->numberOfClassesAndTraits(), + 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), + 'numMethods' => $node->numberOfFunctionsAndMethods(), + 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), + 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), + 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), + 'numExecutedLines' => $node->numberOfExecutedLines(), + 'numExecutableLines' => $node->numberOfExecutableLines(), + 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), + 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), + 'numExecutedBranches' => $node->numberOfExecutedBranches(), + 'numExecutableBranches' => $node->numberOfExecutableBranches(), + 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), + 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), + 'numExecutedPaths' => $node->numberOfExecutedPaths(), + 'numExecutablePaths' => $node->numberOfExecutablePaths(), + 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), + 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), + 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), + 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), + 'crap' => 'CRAP', + ], + ); + + $items .= $this->renderFunctionItems( + $node->functions(), + $methodItemTemplate, + ); + + $items .= $this->renderTraitOrClassItems( + $node->traits(), + $template, + $methodItemTemplate, + ); + + $items .= $this->renderTraitOrClassItems( + $node->classes(), + $template, + $methodItemTemplate, + ); + + return $items; + } + + private function renderTraitOrClassItems(array $items, Template $template, Template $methodItemTemplate): string + { + $buffer = ''; + + if (empty($items)) { + return $buffer; + } + + foreach ($items as $name => $item) { + $numMethods = 0; + $numTestedMethods = 0; + + foreach ($item['methods'] as $method) { + if ($method['executableLines'] > 0) { + $numMethods++; + + if ($method['executedLines'] === $method['executableLines']) { + $numTestedMethods++; + } + } + } + + if ($item['executableLines'] > 0) { + $numClasses = 1; + $numTestedClasses = $numTestedMethods === $numMethods ? 1 : 0; + $linesExecutedPercentAsString = Percentage::fromFractionAndTotal( + $item['executedLines'], + $item['executableLines'], + )->asString(); + $branchesExecutedPercentAsString = Percentage::fromFractionAndTotal( + $item['executedBranches'], + $item['executableBranches'], + )->asString(); + $pathsExecutedPercentAsString = Percentage::fromFractionAndTotal( + $item['executedPaths'], + $item['executablePaths'], + )->asString(); + } else { + $numClasses = 0; + $numTestedClasses = 0; + $linesExecutedPercentAsString = 'n/a'; + $branchesExecutedPercentAsString = 'n/a'; + $pathsExecutedPercentAsString = 'n/a'; + } + + $testedMethodsPercentage = Percentage::fromFractionAndTotal( + $numTestedMethods, + $numMethods, + ); + + $testedClassesPercentage = Percentage::fromFractionAndTotal( + $numTestedMethods === $numMethods ? 1 : 0, + 1, + ); + + $buffer .= $this->renderItemTemplate( + $template, + [ + 'name' => $this->abbreviateClassName($name), + 'numClasses' => $numClasses, + 'numTestedClasses' => $numTestedClasses, + 'numMethods' => $numMethods, + 'numTestedMethods' => $numTestedMethods, + 'linesExecutedPercent' => Percentage::fromFractionAndTotal( + $item['executedLines'], + $item['executableLines'], + )->asFloat(), + 'linesExecutedPercentAsString' => $linesExecutedPercentAsString, + 'numExecutedLines' => $item['executedLines'], + 'numExecutableLines' => $item['executableLines'], + 'branchesExecutedPercent' => Percentage::fromFractionAndTotal( + $item['executedBranches'], + $item['executableBranches'], + )->asFloat(), + 'branchesExecutedPercentAsString' => $branchesExecutedPercentAsString, + 'numExecutedBranches' => $item['executedBranches'], + 'numExecutableBranches' => $item['executableBranches'], + 'pathsExecutedPercent' => Percentage::fromFractionAndTotal( + $item['executedPaths'], + $item['executablePaths'], + )->asFloat(), + 'pathsExecutedPercentAsString' => $pathsExecutedPercentAsString, + 'numExecutedPaths' => $item['executedPaths'], + 'numExecutablePaths' => $item['executablePaths'], + 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), + 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), + 'testedClassesPercent' => $testedClassesPercentage->asFloat(), + 'testedClassesPercentAsString' => $testedClassesPercentage->asString(), + 'crap' => $item['crap'], + ], + ); + + foreach ($item['methods'] as $method) { + $buffer .= $this->renderFunctionOrMethodItem( + $methodItemTemplate, + $method, + ' ', + ); + } + } + + return $buffer; + } + + private function renderFunctionItems(array $functions, Template $template): string + { + if (empty($functions)) { + return ''; + } + + $buffer = ''; + + foreach ($functions as $function) { + $buffer .= $this->renderFunctionOrMethodItem( + $template, + $function, + ); + } + + return $buffer; + } + + private function renderFunctionOrMethodItem(Template $template, array $item, string $indent = ''): string + { + $numMethods = 0; + $numTestedMethods = 0; + + if ($item['executableLines'] > 0) { + $numMethods = 1; + + if ($item['executedLines'] === $item['executableLines']) { + $numTestedMethods = 1; + } + } + + $executedLinesPercentage = Percentage::fromFractionAndTotal( + $item['executedLines'], + $item['executableLines'], + ); + + $executedBranchesPercentage = Percentage::fromFractionAndTotal( + $item['executedBranches'], + $item['executableBranches'], + ); + + $executedPathsPercentage = Percentage::fromFractionAndTotal( + $item['executedPaths'], + $item['executablePaths'], + ); + + $testedMethodsPercentage = Percentage::fromFractionAndTotal( + $numTestedMethods, + 1, + ); + + return $this->renderItemTemplate( + $template, + [ + 'name' => sprintf( + '%s%s', + $indent, + $item['startLine'], + htmlspecialchars($item['signature'], $this->htmlSpecialCharsFlags), + $item['functionName'] ?? $item['methodName'], + ), + 'numMethods' => $numMethods, + 'numTestedMethods' => $numTestedMethods, + 'linesExecutedPercent' => $executedLinesPercentage->asFloat(), + 'linesExecutedPercentAsString' => $executedLinesPercentage->asString(), + 'numExecutedLines' => $item['executedLines'], + 'numExecutableLines' => $item['executableLines'], + 'branchesExecutedPercent' => $executedBranchesPercentage->asFloat(), + 'branchesExecutedPercentAsString' => $executedBranchesPercentage->asString(), + 'numExecutedBranches' => $item['executedBranches'], + 'numExecutableBranches' => $item['executableBranches'], + 'pathsExecutedPercent' => $executedPathsPercentage->asFloat(), + 'pathsExecutedPercentAsString' => $executedPathsPercentage->asString(), + 'numExecutedPaths' => $item['executedPaths'], + 'numExecutablePaths' => $item['executablePaths'], + 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), + 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), + 'crap' => $item['crap'], + ], + ); + } + + private function renderSourceWithLineCoverage(FileNode $node): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $coverageData = $node->lineCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + $lines = ''; + $i = 1; + + foreach ($codeLines as $line) { + $trClass = ''; + $popoverContent = ''; + $popoverTitle = ''; + + if (array_key_exists($i, $coverageData)) { + $numTests = ($coverageData[$i] ? count($coverageData[$i]) : 0); + + if ($coverageData[$i] === null) { + $trClass = 'warning'; + } elseif ($numTests === 0) { + $trClass = 'danger'; + } else { + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover line ' . $i; + } else { + $popoverTitle = '1 test covers line ' . $i; + } + + $lineCss = 'covered-by-large-tests'; + $popoverContent = '
        '; + + foreach ($coverageData[$i] as $test) { + if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { + $lineCss = 'covered-by-medium-tests'; + } elseif ($testData[$test]['size'] === 'small') { + $lineCss = 'covered-by-small-tests'; + } + + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $popoverContent .= '
      '; + $trClass = $lineCss . ' popin'; + } + } + + $popover = ''; + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); + + $i++; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderSourceWithBranchCoverage(FileNode $node): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $functionCoverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + + $lineData = []; + + /** @var int $line */ + foreach (array_keys($codeLines) as $line) { + $lineData[$line + 1] = [ + 'includedInBranches' => 0, + 'includedInHitBranches' => 0, + 'tests' => [], + ]; + } + + foreach ($functionCoverageData as $method) { + foreach ($method['branches'] as $branch) { + foreach (range($branch['line_start'], $branch['line_end']) as $line) { + if (!isset($lineData[$line])) { // blank line at end of file is sometimes included here + continue; + } + + $lineData[$line]['includedInBranches']++; + + if ($branch['hit']) { + $lineData[$line]['includedInHitBranches']++; + $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch['hit'])); + } + } + } + } + + $lines = ''; + $i = 1; + + /** @var string $line */ + foreach ($codeLines as $line) { + $trClass = ''; + $popover = ''; + + if ($lineData[$i]['includedInBranches'] > 0) { + $lineCss = 'success'; + + if ($lineData[$i]['includedInHitBranches'] === 0) { + $lineCss = 'danger'; + } elseif ($lineData[$i]['includedInHitBranches'] !== $lineData[$i]['includedInBranches']) { + $lineCss = 'warning'; + } + + $popoverContent = '
        '; + + if (count($lineData[$i]['tests']) === 1) { + $popoverTitle = '1 test covers line ' . $i; + } else { + $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; + } + $popoverTitle .= '. These are covering ' . $lineData[$i]['includedInHitBranches'] . ' out of the ' . $lineData[$i]['includedInBranches'] . ' code branches.'; + + foreach ($lineData[$i]['tests'] as $test) { + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $popoverContent .= '
      '; + $trClass = $lineCss . ' popin'; + + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); + + $i++; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderSourceWithPathCoverage(FileNode $node): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $functionCoverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + + $lineData = []; + + /** @var int $line */ + foreach (array_keys($codeLines) as $line) { + $lineData[$line + 1] = [ + 'includedInPaths' => [], + 'includedInHitPaths' => [], + 'tests' => [], + ]; + } + + foreach ($functionCoverageData as $method) { + foreach ($method['paths'] as $pathId => $path) { + foreach ($path['path'] as $branchTaken) { + foreach (range($method['branches'][$branchTaken]['line_start'], $method['branches'][$branchTaken]['line_end']) as $line) { + if (!isset($lineData[$line])) { + continue; + } + $lineData[$line]['includedInPaths'][] = $pathId; + + if ($path['hit']) { + $lineData[$line]['includedInHitPaths'][] = $pathId; + $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $path['hit'])); + } + } + } + } + } + + $lines = ''; + $i = 1; + + /** @var string $line */ + foreach ($codeLines as $line) { + $trClass = ''; + $popover = ''; + $includedInPathsCount = count(array_unique($lineData[$i]['includedInPaths'])); + $includedInHitPathsCount = count(array_unique($lineData[$i]['includedInHitPaths'])); + + if ($includedInPathsCount > 0) { + $lineCss = 'success'; + + if ($includedInHitPathsCount === 0) { + $lineCss = 'danger'; + } elseif ($includedInHitPathsCount !== $includedInPathsCount) { + $lineCss = 'warning'; + } + + $popoverContent = '
        '; + + if (count($lineData[$i]['tests']) === 1) { + $popoverTitle = '1 test covers line ' . $i; + } else { + $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; + } + $popoverTitle .= '. These are covering ' . $includedInHitPathsCount . ' out of the ' . $includedInPathsCount . ' code paths.'; + + foreach ($lineData[$i]['tests'] as $test) { + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $popoverContent .= '
      '; + $trClass = $lineCss . ' popin'; + + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); + + $i++; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderBranchStructure(FileNode $node): string + { + $branchesTemplate = new Template($this->templatePath . 'branches.html.dist', '{{', '}}'); + + $coverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + $branches = ''; + + ksort($coverageData); + + foreach ($coverageData as $methodName => $methodData) { + if (!$methodData['branches']) { + continue; + } + + $branchStructure = ''; + + foreach ($methodData['branches'] as $branch) { + $branchStructure .= $this->renderBranchLines($branch, $codeLines, $testData); + } + + if ($branchStructure !== '') { // don't show empty branches + $branches .= '
      ' . $this->abbreviateMethodName($methodName) . '
      ' . "\n"; + $branches .= $branchStructure; + } + } + + $branchesTemplate->setVar(['branches' => $branches]); + + return $branchesTemplate->render(); + } + + private function renderBranchLines(array $branch, array $codeLines, array $testData): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $lines = ''; + + $branchLines = range($branch['line_start'], $branch['line_end']); + sort($branchLines); // sometimes end_line < start_line + + /** @var int $line */ + foreach ($branchLines as $line) { + if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here + continue; + } + + $popoverContent = ''; + $popoverTitle = ''; + + $numTests = count($branch['hit']); + + if ($numTests === 0) { + $trClass = 'danger'; + } else { + $lineCss = 'covered-by-large-tests'; + $popoverContent = '
        '; + + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover this branch'; + } else { + $popoverTitle = '1 test covers this branch'; + } + + foreach ($branch['hit'] as $test) { + if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { + $lineCss = 'covered-by-medium-tests'; + } elseif ($testData[$test]['size'] === 'small') { + $lineCss = 'covered-by-small-tests'; + } + + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + $trClass = $lineCss . ' popin'; + } + + $popover = ''; + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); + } + + if ($lines === '') { + return ''; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderPathStructure(FileNode $node): string + { + $pathsTemplate = new Template($this->templatePath . 'paths.html.dist', '{{', '}}'); + + $coverageData = $node->functionCoverageData(); + $testData = $node->testData(); + $codeLines = $this->loadFile($node->pathAsString()); + $paths = ''; + + ksort($coverageData); + + foreach ($coverageData as $methodName => $methodData) { + if (!$methodData['paths']) { + continue; + } + + $pathStructure = ''; + + if (count($methodData['paths']) > 100) { + $pathStructure .= '

        ' . count($methodData['paths']) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.

        '; + + continue; + } + + foreach ($methodData['paths'] as $path) { + $pathStructure .= $this->renderPathLines($path, $methodData['branches'], $codeLines, $testData); + } + + if ($pathStructure !== '') { + $paths .= '
        ' . $this->abbreviateMethodName($methodName) . '
        ' . "\n"; + $paths .= $pathStructure; + } + } + + $pathsTemplate->setVar(['paths' => $paths]); + + return $pathsTemplate->render(); + } + + private function renderPathLines(array $path, array $branches, array $codeLines, array $testData): string + { + $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); + $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); + + $lines = ''; + $first = true; + + foreach ($path['path'] as $branchId) { + if ($first) { + $first = false; + } else { + $lines .= '  ' . "\n"; + } + + $branchLines = range($branches[$branchId]['line_start'], $branches[$branchId]['line_end']); + sort($branchLines); // sometimes end_line < start_line + + /** @var int $line */ + foreach ($branchLines as $line) { + if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here + continue; + } + + $popoverContent = ''; + $popoverTitle = ''; + + $numTests = count($path['hit']); + + if ($numTests === 0) { + $trClass = 'danger'; + } else { + $lineCss = 'covered-by-large-tests'; + $popoverContent = '
          '; + + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover this path'; + } else { + $popoverTitle = '1 test covers this path'; + } + + foreach ($path['hit'] as $test) { + if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { + $lineCss = 'covered-by-medium-tests'; + } elseif ($testData[$test]['size'] === 'small') { + $lineCss = 'covered-by-small-tests'; + } + + $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); + } + + $trClass = $lineCss . ' popin'; + } + + $popover = ''; + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), + ); + } + + $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); + } + } + + if ($lines === '') { + return ''; + } + + $linesTemplate->setVar(['lines' => $lines]); + + return $linesTemplate->render(); + } + + private function renderLine(Template $template, int $lineNumber, string $lineContent, string $class, string $popover): string + { + $template->setVar( + [ + 'lineNumber' => $lineNumber, + 'lineContent' => $lineContent, + 'class' => $class, + 'popover' => $popover, + ], + ); + + return $template->render(); + } + + private function loadFile(string $file): array + { + if (isset(self::$formattedSourceCache[$file])) { + return self::$formattedSourceCache[$file]; + } + + $buffer = file_get_contents($file); + $tokens = token_get_all($buffer); + $result = ['']; + $i = 0; + $stringFlag = false; + $fileEndsWithNewLine = str_ends_with($buffer, "\n"); + + unset($buffer); + + foreach ($tokens as $j => $token) { + if (is_string($token)) { + if ($token === '"' && $tokens[$j - 1] !== '\\') { + $result[$i] .= sprintf( + '%s', + htmlspecialchars($token, $this->htmlSpecialCharsFlags), + ); + + $stringFlag = !$stringFlag; + } else { + $result[$i] .= sprintf( + '%s', + htmlspecialchars($token, $this->htmlSpecialCharsFlags), + ); + } + + continue; + } + + [$token, $value] = $token; + + $value = str_replace( + ["\t", ' '], + ['    ', ' '], + htmlspecialchars($value, $this->htmlSpecialCharsFlags), + ); + + if ($value === "\n") { + $result[++$i] = ''; + } else { + $lines = explode("\n", $value); + + foreach ($lines as $jj => $line) { + $line = trim($line); + + if ($line !== '') { + if ($stringFlag) { + $colour = 'string'; + } else { + $colour = 'default'; + + if ($this->isInlineHtml($token)) { + $colour = 'html'; + } elseif ($this->isComment($token)) { + $colour = 'comment'; + } elseif ($this->isKeyword($token)) { + $colour = 'keyword'; + } + } + + $result[$i] .= sprintf( + '%s', + $colour, + $line, + ); + } + + if (isset($lines[$jj + 1])) { + $result[++$i] = ''; + } + } + } + } + + if ($fileEndsWithNewLine) { + unset($result[count($result) - 1]); + } + + self::$formattedSourceCache[$file] = $result; + + return $result; + } + + private function abbreviateClassName(string $className): string + { + $tmp = explode('\\', $className); + + if (count($tmp) > 1) { + $className = sprintf( + '%s', + $className, + array_pop($tmp), + ); + } + + return $className; + } + + private function abbreviateMethodName(string $methodName): string + { + $parts = explode('->', $methodName); + + if (count($parts) === 2) { + return $this->abbreviateClassName($parts[0]) . '->' . $parts[1]; + } + + return $methodName; + } + + private function createPopoverContentForTest(string $test, array $testData): string + { + $testCSS = ''; + + switch ($testData['status']) { + case 'success': + $testCSS = match ($testData['size']) { + 'small' => ' class="covered-by-small-tests"', + 'medium' => ' class="covered-by-medium-tests"', + // no break + default => ' class="covered-by-large-tests"', + }; + + break; + + case 'failure': + $testCSS = ' class="danger"'; + + break; + } + + return sprintf( + '%s', + $testCSS, + htmlspecialchars($test, $this->htmlSpecialCharsFlags), + ); + } + + private function isComment(int $token): bool + { + return $token === T_COMMENT || $token === T_DOC_COMMENT; + } + + private function isInlineHtml(int $token): bool + { + return $token === T_INLINE_HTML; + } + + private function isKeyword(int $token): bool + { + return isset(self::KEYWORD_TOKENS[$token]); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist new file mode 100644 index 000000000..547702623 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/branches.html.dist @@ -0,0 +1,9 @@ +
          +

          Branches

          +

          + Below are the source code lines that represent each code branch as identified by Xdebug. Please note a branch is not + necessarily coterminous with a line, a line may contain multiple branches and therefore show up more than once. + Please also be aware that some branches may be implicit rather than explicit, e.g. an if statement + always has an else as part of its logical flow even if you didn't write one. +

          +{{branches}} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist new file mode 100644 index 000000000..7fcf6f490 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar.html.dist @@ -0,0 +1,5 @@ +
          +
          + {{percent}}% covered ({{level}}) +
          +
          diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist new file mode 100644 index 000000000..7fcf6f490 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/coverage_bar_branch.html.dist @@ -0,0 +1,5 @@ +
          +
          + {{percent}}% covered ({{level}}) +
          +
          diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css new file mode 100644 index 000000000..83a71b1f5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors + * Copyright 2011-2022 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:.875em;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-primary tbody+tbody,.table-primary td,.table-primary th,.table-primary thead th{border-color:#7abaff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-secondary tbody+tbody,.table-secondary td,.table-secondary th,.table-secondary thead th{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-success tbody+tbody,.table-success td,.table-success th,.table-success thead th{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-info tbody+tbody,.table-info td,.table-info th,.table-info thead th{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-warning tbody+tbody,.table-warning td,.table-warning th,.table-warning thead th{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-danger tbody+tbody,.table-danger td,.table-danger th,.table-danger thead th{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-light tbody+tbody,.table-light td,.table-light th,.table-light thead th{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark td,.table-dark th,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*=col-]>.valid-tooltip{left:5px}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:#28a745;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated select.form-control:valid,select.form-control.is-valid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-valid,.was-validated .custom-select:valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-valid:focus,.was-validated .custom-select:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{border-color:#28a745}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*=col-]>.invalid-tooltip{left:5px}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem)!important;background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated select.form-control:invalid,select.form-control.is-invalid{padding-right:3rem!important;background-position:right 1.5rem center}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.custom-select.is-invalid,.was-validated .custom-select:invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem)!important;background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.custom-select.is-invalid:focus,.was-validated .custom-select:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{border-color:#dc3545}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;-ms-flex-negative:0;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#0069d9;border-color:#0062cc;box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,143,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{color:#212529;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,170,12,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,.5)}.btn-outline-primary{color:#007bff;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;text-decoration:none}.btn-link:hover{color:#0056b3;text-decoration:underline}.btn-link.focus,.btn-link:focus{text-decoration:underline}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.width{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.width{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:1 1 auto;flex:1 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn-group:not(:first-child),.btn-group>.btn:not(:first-child){margin-left:-1px}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control,.input-group>.form-control-plaintext{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control,.input-group>.form-control-plaintext+.custom-file,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label,.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after,.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label,.input-group.has-validation>.custom-file:nth-last-child(n+3) .custom-file-label::after,.input-group.has-validation>.custom-select:nth-last-child(n+3),.input-group.has-validation>.form-control:nth-last-child(n+3){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn:focus,.input-group-prepend .btn:focus{z-index:3}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.custom-select,.input-group-lg>.form-control:not(textarea){height:calc(1.5em + 1rem + 2px)}.input-group-lg>.custom-select,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.custom-select,.input-group-sm>.form-control:not(textarea){height:calc(1.5em + .5rem + 2px)}.input-group-sm>.custom-select,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n+3)>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#007bff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#80bdff}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#fff;background-color:#b3d7ff;border-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label,.custom-control-input[disabled]~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before,.custom-control-input[disabled]~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:1px solid #adb5bd}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50%/50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#007bff;background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:transform .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-transform .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;-webkit-transform:translateX(.75rem);transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:disabled~.custom-file-label,.custom-file-input[disabled]~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{-moz-transition:none;transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;-ms-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{-ms-transition:none;transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link{margin-bottom:-1px;background-color:transparent;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{background:0 0;border:0;border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item,.nav-fill>.nav-link{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-lg,.navbar .container-md,.navbar .container-sm,.navbar .container-xl{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50%/100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-md,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-lg,.navbar-expand>.container-md,.navbar-expand>.container-sm,.navbar-expand>.container-xl{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom,.card-img-top{-ms-flex-negative:0;flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{-ms-flex:1 0 0%;flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom{border-bottom-left-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card{overflow:hidden}.accordion>.card:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.badge{transition:none}}a.badge:focus,a.badge:hover{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}a.badge-primary:focus,a.badge-primary:hover{color:#fff;background-color:#0062cc}a.badge-primary.focus,a.badge-primary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:focus,a.badge-secondary:hover{color:#fff;background-color:#545b62}a.badge-secondary.focus,a.badge-secondary:focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:focus,a.badge-success:hover{color:#fff;background-color:#1e7e34}a.badge-success.focus,a.badge-success:focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:focus,a.badge-info:hover{color:#fff;background-color:#117a8b}a.badge-info.focus,a.badge-info:focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.badge-warning{color:#212529;background-color:#ffc107}a.badge-warning:focus,a.badge-warning:hover{color:#212529;background-color:#d39e00}a.badge-warning.focus,a.badge-warning:focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:focus,a.badge-danger:hover{color:#fff;background-color:#bd2130}a.badge-danger.focus,a.badge-danger:focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.badge-light{color:#212529;background-color:#f8f9fa}a.badge-light:focus,a.badge-light:hover{color:#212529;background-color:#dae0e5}a.badge-light.focus,a.badge-light:focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:focus,a.badge-dark:hover{color:#fff;background-color:#1d2124}a.badge-dark.focus,a.badge-dark:focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:1s linear infinite progress-bar-stripes;animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{-webkit-animation:none;animation:none}}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width:576px){.list-group-horizontal-sm{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:768px){.list-group-horizontal-md{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:992px){.list-group-horizontal-lg{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width:1200px){.list-group-horizontal-xl{-ms-flex-direction:row;flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{-ms-flex-preferred-size:350px;flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,.85);background-clip:padding-box;border:1px solid rgba(0,0,0,.1);box-shadow:0 .25rem .75rem rgba(0,0,0,.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-50px);transform:translate(0,-50px)}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:none;transform:none}.modal.modal-static .modal-dialog{-webkit-transform:scale(1.02);transform:scale(1.02)}.modal-dialog-scrollable{display:-ms-flexbox;display:flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-footer,.modal-dialog-scrollable .modal-header{-ms-flex-negative:0;flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:-webkit-min-content;height:-moz-min-content;height:min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:-webkit-min-content;height:-moz-min-content;height:min-content}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width:1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top]>.arrow,.bs-popover-top>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=top]>.arrow::before,.bs-popover-top>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top]>.arrow::after,.bs-popover-top>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right]>.arrow,.bs-popover-right>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right]>.arrow::before,.bs-popover-right>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right]>.arrow::after,.bs-popover-right>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom]>.arrow,.bs-popover-bottom>.arrow{top:calc(-.5rem - 1px)}.bs-popover-auto[x-placement^=bottom]>.arrow::before,.bs-popover-bottom>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom]>.arrow::after,.bs-popover-bottom>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left]>.arrow,.bs-popover-left>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left]>.arrow::before,.bs-popover-left>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left]>.arrow::after,.bs-popover-left>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{-ms-touch-action:pan-y;touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-right,.carousel-item-next:not(.carousel-item-left){-webkit-transform:translateX(100%);transform:translateX(100%)}.active.carousel-item-left,.carousel-item-prev:not(.carousel-item-right){-webkit-transform:translateX(-100%);transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;-webkit-transform:none;transform:none}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:50%/100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@-webkit-keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spinner-border{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;border:.25em solid currentcolor;border-right-color:transparent;border-radius:50%;-webkit-animation:.75s linear infinite spinner-border;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@-webkit-keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}@keyframes spinner-grow{0%{-webkit-transform:scale(0);transform:scale(0)}50%{opacity:1;-webkit-transform:none;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:-.125em;background-color:currentcolor;border-radius:50%;opacity:0;-webkit-animation:.75s linear infinite spinner-grow;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{-webkit-animation-duration:1.5s;animation-duration:1.5s}}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded-sm{border-radius:.2rem!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-lg{border-radius:.3rem!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:50rem!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;-ms-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.min-vw-100{min-width:100vw!important}.min-vh-100{min-height:100vh!important}.vw-100{width:100vw!important}.vh-100{height:100vh!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace!important}.text-justify{text-align:justify!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-lighter{font-weight:lighter!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-weight-bolder{font-weight:bolder!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0056b3!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#494f54!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#19692c!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#0f6674!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#ba8b00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#a71d2a!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#cbd3da!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#121416!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none!important}.text-break{word-break:break-word!important;word-wrap:break-word!important}.text-reset{color:inherit!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/custom.css new file mode 100644 index 000000000..e69de29bb diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css new file mode 100644 index 000000000..7a6f7fe90 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/nv.d3.min.css @@ -0,0 +1 @@ +.nvd3 .nv-axis{pointer-events:none;opacity:1}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-axis.nv-disabled{opacity:0}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover{fill-opacity:1}.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-legend .nv-disabled rect{}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nv-noninteractive{pointer-events:none}.nv-distx,.nv-disty{pointer-events:none}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);color:rgba(0,0,0,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;display:block;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip{background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip table td.legend-color-guide div{width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css new file mode 100644 index 000000000..31d97867a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/octicons.css @@ -0,0 +1,5 @@ +.octicon { + display: inline-block; + vertical-align: text-top; + fill: currentColor; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css new file mode 100644 index 000000000..04ebcd892 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/css/style.css @@ -0,0 +1,158 @@ +body { + font-family: sans-serif; + font-size: 1em; + font-kerning: normal; + font-variant-ligatures: common-ligatures; + text-rendering: optimizeLegibility; + padding-top: 10px; +} + +.popover { + max-width: none; +} + +.octicon { + margin-right:.25em; + vertical-align: baseline; + width: 0.75em; +} + +.table-bordered>thead>tr>td { + border-bottom-width: 1px; +} + +.table tbody>tr>td, .table thead>tr>td { + padding-top: 3px; + padding-bottom: 3px; +} + +.table-condensed tbody>tr>td { + padding-top: 0; + padding-bottom: 0; +} + +.table .progress { + margin-bottom: inherit; +} + +.table-borderless th, .table-borderless td { + border: 0 !important; +} + +.table tbody tr.covered-by-large-tests, li.covered-by-large-tests, tr.success, td.success, li.success, span.success { + background-color: {{success-low}}; +} + +.table tbody tr.covered-by-medium-tests, li.covered-by-medium-tests { + background-color: {{success-medium}}; +} + +.table tbody tr.covered-by-small-tests, li.covered-by-small-tests { + background-color: {{success-high}}; +} + +.table tbody tr.warning, .table tbody td.warning, li.warning, span.warning { + background-color: {{warning}}; +} + +.table tbody tr.danger, .table tbody td.danger, li.danger, span.danger { + background-color: {{danger}}; +} + +.table tbody td.info { + background-color: #d9edf7; +} + +td.big { + vertical-align: middle; + width: 117px; +} + +td.small { +} + +td.codeLine { + font-family: "Source Code Pro", "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + white-space: pre-wrap; +} + +td span.comment { + color: #888a85; +} + +td span.default { + color: #2e3436; +} + +td span.html { + color: #888a85; +} + +td span.keyword { + color: #2e3436; + font-weight: bold; +} + +pre span.string { + color: #2e3436; +} + +span.success, span.warning, span.danger { + margin-right: 2px; + padding-left: 10px; + padding-right: 10px; + text-align: center; +} + +#toplink { + position: fixed; + left: 5px; + bottom: 5px; + outline: 0; +} + +svg text { + font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + color: #666; + fill: #666; +} + +.scrollbox { + height:245px; + overflow-x:scroll; + overflow-y:scroll; +} + +table + .structure-heading { + border-top: 1px solid lightgrey; + padding-top: 0.5em; +} + +.legend { + font-weight: bold; + margin-right: 2px; + padding-left: 10px; + padding-right: 10px; + text-align: center; +} + +.covered-by-small-tests { + background-color: {{success-high}}; +} + +.covered-by-medium-tests { + background-color: {{success-medium}}; +} + +.covered-by-large-tests { + background-color: {{success-low}}; +} + +.not-covered { + background-color: {{danger}}; +} + +.not-coverable { + background-color: {{warning}}; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist new file mode 100644 index 000000000..60e66d5be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard.html.dist @@ -0,0 +1,281 @@ + + + + + Dashboard for {{full_path}} + + + + + + + +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          +
          +

          Classes

          +
          +
          +
          +
          +

          Coverage Distribution

          +
          + +
          +
          +
          +

          Complexity

          +
          + +
          +
          +
          +
          +
          +

          Insufficient Coverage

          +
          + + + + + + + + +{{insufficient_coverage_classes}} + +
          ClassCoverage
          +
          +
          +
          +

          Project Risks

          +
          + + + + + + + + +{{project_risks_classes}} + +
          ClassCRAP
          +
          +
          +
          +
          +
          +

          Methods

          +
          +
          +
          +
          +

          Coverage Distribution

          +
          + +
          +
          +
          +

          Complexity

          +
          + +
          +
          +
          +
          +
          +

          Insufficient Coverage

          +
          + + + + + + + + +{{insufficient_coverage_methods}} + +
          MethodCoverage
          +
          +
          +
          +

          Project Risks

          +
          + + + + + + + + +{{project_risks_methods}} + +
          MethodCRAP
          +
          +
          +
          + +
          + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist new file mode 100644 index 000000000..60e66d5be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/dashboard_branch.html.dist @@ -0,0 +1,281 @@ + + + + + Dashboard for {{full_path}} + + + + + + + +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          +
          +

          Classes

          +
          +
          +
          +
          +

          Coverage Distribution

          +
          + +
          +
          +
          +

          Complexity

          +
          + +
          +
          +
          +
          +
          +

          Insufficient Coverage

          +
          + + + + + + + + +{{insufficient_coverage_classes}} + +
          ClassCoverage
          +
          +
          +
          +

          Project Risks

          +
          + + + + + + + + +{{project_risks_classes}} + +
          ClassCRAP
          +
          +
          +
          +
          +
          +

          Methods

          +
          +
          +
          +
          +

          Coverage Distribution

          +
          + +
          +
          +
          +

          Complexity

          +
          + +
          +
          +
          +
          +
          +

          Insufficient Coverage

          +
          + + + + + + + + +{{insufficient_coverage_methods}} + +
          MethodCoverage
          +
          +
          +
          +

          Project Risks

          +
          + + + + + + + + +{{project_risks_methods}} + +
          MethodCRAP
          +
          +
          +
          + +
          + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist new file mode 100644 index 000000000..f769d2cae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory.html.dist @@ -0,0 +1,60 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + + + + + + + + + + + + + + +{{items}} + +
           
          Code Coverage
           
          Lines
          Functions and Methods
          Classes and Traits
          +
          +
          +
          +

          Legend

          +

          + Low: 0% to {{low_upper_bound}}% + Medium: {{low_upper_bound}}% to {{high_lower_bound}}% + High: {{high_lower_bound}}% to 100% +

          +

          + Generated by php-code-coverage {{version}} using {{runtime}}{{generator}} at {{date}}. +

          +
          +
          + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist new file mode 100644 index 000000000..a40c2e128 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_branch.html.dist @@ -0,0 +1,62 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + + + + + + + + + + + + + + + + +{{items}} + +
           
          Code Coverage
           
          Lines
          Branches
          Paths
          Functions and Methods
          Classes and Traits
          +
          +
          +
          +

          Legend

          +

          + Low: 0% to {{low_upper_bound}}% + Medium: {{low_upper_bound}}% to {{high_lower_bound}}% + High: {{high_lower_bound}}% to 100% +

          +

          + Generated by php-code-coverage {{version}} using {{runtime}}{{generator}} at {{date}}. +

          +
          +
          + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist new file mode 100644 index 000000000..f6941a437 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item.html.dist @@ -0,0 +1,13 @@ + + {{icon}}{{name}} + {{lines_bar}} +
          {{lines_executed_percent}}
          +
          {{lines_number}}
          + {{methods_bar}} +
          {{methods_tested_percent}}
          +
          {{methods_number}}
          + {{classes_bar}} +
          {{classes_tested_percent}}
          +
          {{classes_number}}
          + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist new file mode 100644 index 000000000..532a436c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist @@ -0,0 +1,19 @@ + + {{icon}}{{name}} + {{lines_bar}} +
          {{lines_executed_percent}}
          +
          {{lines_number}}
          + {{branches_bar}} +
          {{branches_executed_percent}}
          +
          {{branches_number}}
          + {{paths_bar}} +
          {{paths_executed_percent}}
          +
          {{paths_number}}
          + {{methods_bar}} +
          {{methods_tested_percent}}
          +
          {{methods_number}}
          + {{classes_bar}} +
          {{classes_tested_percent}}
          +
          {{classes_number}}
          + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist new file mode 100644 index 000000000..a022f5c2c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist @@ -0,0 +1,65 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + + + + + + + + + + + + + + +{{items}} + +
           
          Code Coverage
           
          Lines
          Functions and Methods
          Classes and Traits
          +
          +{{lines}} +{{structure}} + +
          + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist new file mode 100644 index 000000000..f48ebf128 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_branch.html.dist @@ -0,0 +1,67 @@ + + + + + Code Coverage for {{full_path}} + + + + + + + +
          +
          +
          +
          + +
          +
          +
          +
          +
          +
          + + + + + + + + + + + + + + + + +{{items}} + +
           
          Code Coverage
           
          Lines
          Branches
          Paths
          Functions and Methods
          Classes and Traits
          +
          +{{lines}} +{{structure}} + +
          + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist new file mode 100644 index 000000000..b1c0fca48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item.html.dist @@ -0,0 +1,14 @@ + + {{name}} + {{lines_bar}} +
          {{lines_executed_percent}}
          +
          {{lines_number}}
          + {{methods_bar}} +
          {{methods_tested_percent}}
          +
          {{methods_number}}
          + {{crap}} + {{classes_bar}} +
          {{classes_tested_percent}}
          +
          {{classes_number}}
          + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist new file mode 100644 index 000000000..505025179 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/file_item_branch.html.dist @@ -0,0 +1,20 @@ + + {{name}} + {{lines_bar}} +
          {{lines_executed_percent}}
          +
          {{lines_number}}
          + {{branches_bar}} +
          {{branches_executed_percent}}
          +
          {{branches_number}}
          + {{paths_bar}} +
          {{paths_executed_percent}}
          +
          {{paths_number}}
          + {{methods_bar}} +
          {{methods_tested_percent}}
          +
          {{methods_number}}
          + {{crap}} + {{classes_bar}} +
          {{classes_tested_percent}}
          +
          {{classes_number}}
          + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg new file mode 100644 index 000000000..5b4b19953 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg new file mode 100644 index 000000000..4bf1f1caa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/icons/file-directory.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js new file mode 100644 index 000000000..97206dcda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.6.2 (https://getbootstrap.com/) + * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap={},t.jQuery,t.Popper)}(this,(function(t,e,n){"use strict";function i(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=i(e),a=i(n);function s(t,e){for(var n=0;n=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};d.jQueryDetection(),o.default.fn.emulateTransitionEnd=function(t){var e=this,n=!1;return o.default(this).one(d.TRANSITION_END,(function(){n=!0})),setTimeout((function(){n||d.triggerTransitionEnd(e)}),t),this},o.default.event.special[d.TRANSITION_END]={bindType:f,delegateType:f,handle:function(t){if(o.default(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}};var c="bs.alert",h=o.default.fn.alert,g=function(){function t(t){this._element=t}var e=t.prototype;return e.close=function(t){var e=this._element;t&&(e=this._getRootElement(t)),this._triggerCloseEvent(e).isDefaultPrevented()||this._removeElement(e)},e.dispose=function(){o.default.removeData(this._element,c),this._element=null},e._getRootElement=function(t){var e=d.getSelectorFromElement(t),n=!1;return e&&(n=document.querySelector(e)),n||(n=o.default(t).closest(".alert")[0]),n},e._triggerCloseEvent=function(t){var e=o.default.Event("close.bs.alert");return o.default(t).trigger(e),e},e._removeElement=function(t){var e=this;if(o.default(t).removeClass("show"),o.default(t).hasClass("fade")){var n=d.getTransitionDurationFromElement(t);o.default(t).one(d.TRANSITION_END,(function(n){return e._destroyElement(t,n)})).emulateTransitionEnd(n)}else this._destroyElement(t)},e._destroyElement=function(t){o.default(t).detach().trigger("closed.bs.alert").remove()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(c);i||(i=new t(this),n.data(c,i)),"close"===e&&i[e](this)}))},t._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.alert.data-api",'[data-dismiss="alert"]',g._handleDismiss(new g)),o.default.fn.alert=g._jQueryInterface,o.default.fn.alert.Constructor=g,o.default.fn.alert.noConflict=function(){return o.default.fn.alert=h,g._jQueryInterface};var m="bs.button",p=o.default.fn.button,_="active",v='[data-toggle^="button"]',y='input:not([type="hidden"])',b=".btn",E=function(){function t(t){this._element=t,this.shouldAvoidTriggerChange=!1}var e=t.prototype;return e.toggle=function(){var t=!0,e=!0,n=o.default(this._element).closest('[data-toggle="buttons"]')[0];if(n){var i=this._element.querySelector(y);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(_))t=!1;else{var a=n.querySelector(".active");a&&o.default(a).removeClass(_)}t&&("checkbox"!==i.type&&"radio"!==i.type||(i.checked=!this._element.classList.contains(_)),this.shouldAvoidTriggerChange||o.default(i).trigger("change")),i.focus(),e=!1}}this._element.hasAttribute("disabled")||this._element.classList.contains("disabled")||(e&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(_)),t&&o.default(this._element).toggleClass(_))},e.dispose=function(){o.default.removeData(this._element,m),this._element=null},t._jQueryInterface=function(e,n){return this.each((function(){var i=o.default(this),a=i.data(m);a||(a=new t(this),i.data(m,a)),a.shouldAvoidTriggerChange=n,"toggle"===e&&a[e]()}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.button.data-api",v,(function(t){var e=t.target,n=e;if(o.default(e).hasClass("btn")||(e=o.default(e).closest(b)[0]),!e||e.hasAttribute("disabled")||e.classList.contains("disabled"))t.preventDefault();else{var i=e.querySelector(y);if(i&&(i.hasAttribute("disabled")||i.classList.contains("disabled")))return void t.preventDefault();"INPUT"!==n.tagName&&"LABEL"===e.tagName||E._jQueryInterface.call(o.default(e),"toggle","INPUT"===n.tagName)}})).on("focus.bs.button.data-api blur.bs.button.data-api",v,(function(t){var e=o.default(t.target).closest(b)[0];o.default(e).toggleClass("focus",/^focus(in)?$/.test(t.type))})),o.default(window).on("load.bs.button.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-toggle="buttons"] .btn')),e=0,n=t.length;e0,this._pointerEvent=Boolean(window.PointerEvent||window.MSPointerEvent),this._addEventListeners()}var e=t.prototype;return e.next=function(){this._isSliding||this._slide(N)},e.nextWhenVisible=function(){var t=o.default(this._element);!document.hidden&&t.is(":visible")&&"hidden"!==t.css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(D)},e.pause=function(t){t||(this._isPaused=!0),this._element.querySelector(".carousel-item-next, .carousel-item-prev")&&(d.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(t){var e=this;this._activeElement=this._element.querySelector(I);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)o.default(this._element).one(A,(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?N:D;this._slide(i,this._items[t])}},e.dispose=function(){o.default(this._element).off(".bs.carousel"),o.default.removeData(this._element,w),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(t){return t=r({},k,t),d.typeCheckConfig(T,t,O),t},e._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&this.prev(),e<0&&this.next()}},e._addEventListeners=function(){var t=this;this._config.keyboard&&o.default(this._element).on("keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&o.default(this._element).on("mouseenter.bs.carousel",(function(e){return t.pause(e)})).on("mouseleave.bs.carousel",(function(e){return t.cycle(e)})),this._config.touch&&this._addTouchEventListeners()},e._addTouchEventListeners=function(){var t=this;if(this._touchSupported){var e=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]?t.touchStartX=e.originalEvent.clientX:t._pointerEvent||(t.touchStartX=e.originalEvent.touches[0].clientX)},n=function(e){t._pointerEvent&&j[e.originalEvent.pointerType.toUpperCase()]&&(t.touchDeltaX=e.originalEvent.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};o.default(this._element.querySelectorAll(".carousel-item img")).on("dragstart.bs.carousel",(function(t){return t.preventDefault()})),this._pointerEvent?(o.default(this._element).on("pointerdown.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(o.default(this._element).on("touchstart.bs.carousel",(function(t){return e(t)})),o.default(this._element).on("touchmove.bs.carousel",(function(e){return function(e){t.touchDeltaX=e.originalEvent.touches&&e.originalEvent.touches.length>1?0:e.originalEvent.touches[0].clientX-t.touchStartX}(e)})),o.default(this._element).on("touchend.bs.carousel",(function(t){return n(t)})))}},e._keydown=function(t){if(!/input|textarea/i.test(t.target.tagName))switch(t.which){case 37:t.preventDefault(),this.prev();break;case 39:t.preventDefault(),this.next()}},e._getItemIndex=function(t){return this._items=t&&t.parentNode?[].slice.call(t.parentNode.querySelectorAll(".carousel-item")):[],this._items.indexOf(t)},e._getItemByDirection=function(t,e){var n=t===N,i=t===D,o=this._getItemIndex(e),a=this._items.length-1;if((i&&0===o||n&&o===a)&&!this._config.wrap)return e;var s=(o+(t===D?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},e._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(this._element.querySelector(I)),a=o.default.Event("slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n});return o.default(this._element).trigger(a),a},e._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=[].slice.call(this._indicatorsElement.querySelectorAll(".active"));o.default(e).removeClass(S);var n=this._indicatorsElement.children[this._getItemIndex(t)];n&&o.default(n).addClass(S)}},e._updateInterval=function(){var t=this._activeElement||this._element.querySelector(I);if(t){var e=parseInt(t.getAttribute("data-interval"),10);e?(this._config.defaultInterval=this._config.defaultInterval||this._config.interval,this._config.interval=e):this._config.interval=this._config.defaultInterval||this._config.interval}},e._slide=function(t,e){var n,i,a,s=this,l=this._element.querySelector(I),r=this._getItemIndex(l),u=e||l&&this._getItemByDirection(t,l),f=this._getItemIndex(u),c=Boolean(this._interval);if(t===N?(n="carousel-item-left",i="carousel-item-next",a="left"):(n="carousel-item-right",i="carousel-item-prev",a="right"),u&&o.default(u).hasClass(S))this._isSliding=!1;else if(!this._triggerSlideEvent(u,a).isDefaultPrevented()&&l&&u){this._isSliding=!0,c&&this.pause(),this._setActiveIndicatorElement(u),this._activeElement=u;var h=o.default.Event(A,{relatedTarget:u,direction:a,from:r,to:f});if(o.default(this._element).hasClass("slide")){o.default(u).addClass(i),d.reflow(u),o.default(l).addClass(n),o.default(u).addClass(n);var g=d.getTransitionDurationFromElement(l);o.default(l).one(d.TRANSITION_END,(function(){o.default(u).removeClass(n+" "+i).addClass(S),o.default(l).removeClass("active "+i+" "+n),s._isSliding=!1,setTimeout((function(){return o.default(s._element).trigger(h)}),0)})).emulateTransitionEnd(g)}else o.default(l).removeClass(S),o.default(u).addClass(S),this._isSliding=!1,o.default(this._element).trigger(h);c&&this.cycle()}},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(w),i=r({},k,o.default(this).data());"object"==typeof e&&(i=r({},i,e));var a="string"==typeof e?e:i.slide;if(n||(n=new t(this,i),o.default(this).data(w,n)),"number"==typeof e)n.to(e);else if("string"==typeof a){if("undefined"==typeof n[a])throw new TypeError('No method named "'+a+'"');n[a]()}else i.interval&&i.ride&&(n.pause(),n.cycle())}))},t._dataApiClickHandler=function(e){var n=d.getSelectorFromElement(this);if(n){var i=o.default(n)[0];if(i&&o.default(i).hasClass("carousel")){var a=r({},o.default(i).data(),o.default(this).data()),s=this.getAttribute("data-slide-to");s&&(a.interval=!1),t._jQueryInterface.call(o.default(i),a),s&&o.default(i).data(w).to(s),e.preventDefault()}}},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return k}}]),t}();o.default(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",P._dataApiClickHandler),o.default(window).on("load.bs.carousel.data-api",(function(){for(var t=[].slice.call(document.querySelectorAll('[data-ride="carousel"]')),e=0,n=t.length;e0&&(this._selector=s,this._triggerArray.push(a))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=t.prototype;return e.toggle=function(){o.default(this._element).hasClass(q)?this.hide():this.show()},e.show=function(){var e,n,i=this;if(!(this._isTransitioning||o.default(this._element).hasClass(q)||(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof i._config.parent?t.getAttribute("data-parent")===i._config.parent:t.classList.contains(F)}))).length&&(e=null),e&&(n=o.default(e).not(this._selector).data(R))&&n._isTransitioning))){var a=o.default.Event("show.bs.collapse");if(o.default(this._element).trigger(a),!a.isDefaultPrevented()){e&&(t._jQueryInterface.call(o.default(e).not(this._selector),"hide"),n||o.default(e).data(R,null));var s=this._getDimension();o.default(this._element).removeClass(F).addClass(Q),this._element.style[s]=0,this._triggerArray.length&&o.default(this._triggerArray).removeClass(B).attr("aria-expanded",!0),this.setTransitioning(!0);var l="scroll"+(s[0].toUpperCase()+s.slice(1)),r=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,(function(){o.default(i._element).removeClass(Q).addClass("collapse show"),i._element.style[s]="",i.setTransitioning(!1),o.default(i._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(r),this._element.style[s]=this._element[l]+"px"}}},e.hide=function(){var t=this;if(!this._isTransitioning&&o.default(this._element).hasClass(q)){var e=o.default.Event("hide.bs.collapse");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",d.reflow(this._element),o.default(this._element).addClass(Q).removeClass("collapse show");var i=this._triggerArray.length;if(i>0)for(var a=0;a0},e._getOffset=function(){var t=this,e={};return"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t._config.offset(e.offsets,t._element)),e}:e.offset=this._config.offset,e},e._getPopperConfig=function(){var t={placement:this._getPlacement(),modifiers:{offset:this._getOffset(),flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(t.modifiers.applyStyle={enabled:!1}),r({},t,this._config.popperConfig)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this).data(K);if(n||(n=new t(this,"object"==typeof e?e:null),o.default(this).data(K,n)),"string"==typeof e){if("undefined"==typeof n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},t._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var n=[].slice.call(document.querySelectorAll(it)),i=0,a=n.length;i0&&s--,40===e.which&&sdocument.documentElement.clientHeight;n||(this._element.style.overflowY="hidden"),this._element.classList.add(ht);var i=d.getTransitionDurationFromElement(this._dialog);o.default(this._element).off(d.TRANSITION_END),o.default(this._element).one(d.TRANSITION_END,(function(){t._element.classList.remove(ht),n||o.default(t._element).one(d.TRANSITION_END,(function(){t._element.style.overflowY=""})).emulateTransitionEnd(t._element,i)})).emulateTransitionEnd(i),this._element.focus()}},e._showElement=function(t){var e=this,n=o.default(this._element).hasClass(dt),i=this._dialog?this._dialog.querySelector(".modal-body"):null;this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),o.default(this._dialog).hasClass("modal-dialog-scrollable")&&i?i.scrollTop=0:this._element.scrollTop=0,n&&d.reflow(this._element),o.default(this._element).addClass(ct),this._config.focus&&this._enforceFocus();var a=o.default.Event("shown.bs.modal",{relatedTarget:t}),s=function(){e._config.focus&&e._element.focus(),e._isTransitioning=!1,o.default(e._element).trigger(a)};if(n){var l=d.getTransitionDurationFromElement(this._dialog);o.default(this._dialog).one(d.TRANSITION_END,s).emulateTransitionEnd(l)}else s()},e._enforceFocus=function(){var t=this;o.default(document).off(pt).on(pt,(function(e){document!==e.target&&t._element!==e.target&&0===o.default(t._element).has(e.target).length&&t._element.focus()}))},e._setEscapeEvent=function(){var t=this;this._isShown?o.default(this._element).on(yt,(function(e){t._config.keyboard&&27===e.which?(e.preventDefault(),t.hide()):t._config.keyboard||27!==e.which||t._triggerBackdropTransition()})):this._isShown||o.default(this._element).off(yt)},e._setResizeEvent=function(){var t=this;this._isShown?o.default(window).on(_t,(function(e){return t.handleUpdate(e)})):o.default(window).off(_t)},e._hideModal=function(){var t=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._showBackdrop((function(){o.default(document.body).removeClass(ft),t._resetAdjustments(),t._resetScrollbar(),o.default(t._element).trigger(gt)}))},e._removeBackdrop=function(){this._backdrop&&(o.default(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(t){var e=this,n=o.default(this._element).hasClass(dt)?dt:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className="modal-backdrop",n&&this._backdrop.classList.add(n),o.default(this._backdrop).appendTo(document.body),o.default(this._element).on(vt,(function(t){e._ignoreBackdropClick?e._ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"===e._config.backdrop?e._triggerBackdropTransition():e.hide())})),n&&d.reflow(this._backdrop),o.default(this._backdrop).addClass(ct),!t)return;if(!n)return void t();var i=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,t).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){o.default(this._backdrop).removeClass(ct);var a=function(){e._removeBackdrop(),t&&t()};if(o.default(this._element).hasClass(dt)){var s=d.getTransitionDurationFromElement(this._backdrop);o.default(this._backdrop).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a()}else t&&t()},e._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)

      3`|gLU*30^d zU9(6YVwdP^i0tD7)P&(MGNl5)23LJQXVI+bc?pcx#W6gw(-0V>iIn+hIZP7iCA_OO zKa{8xJtLCTR82^uf*52NwYp8}cdlNHq!gY;#%%Zt^+-jO(Jn2hUAGG9OGLX5kiV{{ zL>?>EHJJuOYUm|yJw820xcTh#>MgMMn0nks6aHD*}S1UgXc1144pMyP&Z*G0jq=46(VO&%DN}$}?wp>9p z>;@47^A=MmwJ$;5kDw%G*K;qt!m~C(ERs}zgf85^N_{eUh+ne`OG|A$S*FSO$Cocz zR(YW%rBTcfu88oCm35n^Y`&%CF}K@grkVa@HKvI8NDXS-Y*2Vem16&F&IkYpA9|{0 zV?I`6ohf}~12*E}TVI@>Jet3TM!5ijB{&%{&TI(#(lW39gxoEOdW*T(vM^xfK)1d) z+e5oQ7)1i|9i*V~m*=2IKZ_+t@`q|%U$J-yj5Ic#X-|#RkmvbC z5On1p)&7osHIzv9MMx5$7h0J`KPUT|yHbd)>_&wlm6h#k76842>($XL^o4T(^ z*eoKm09Z)JH%|dgp?3t@p`$YT;%e;*n%Ha;b(62)-o0Q z*LFR)2TXCK!t27NA`{p7G?Zg9(jFqK*{?egJl_vk-GQ{s|mgO1{h}Cj`Uo18O7_o zq;JBTaOTIT5b%C7f%`3|h}HRx$*PxTPEw>57b#XPO9+3AEIlv6#DwhxYZ}@hyxYp;aXs(wbdh;Jqjt7{Ss1NMI0JJhPah2>^;a*8GJPdnBv zYOGp&SCt828N>X;L^h7*{dgEXR0f(T;yE#j2ZM>CCGa?_(bwDIxDI>=rwNxT49CWI zT`0@IL;?mmn*TUQhvEQs(HZRZAz8h*Xl=lgupGeBW7|7HkLiHTQc?Yjaq#|DQF(L1 z8(qGb?2ldS1UhL47b_L8s;G;-kyXdAI{Z&wlmEqF6eOs>Iz2G!x|PzoZq@7|$Pe83 zB={LQT$LxBR_%tU>P&;`DBY&iJKZs;FpY(MUK|~sc?bxZASk7t?SOH1MQZNa<7!4A zGF?2(4V+60N5X8FC}YL`+94VD)-0G zI`FOTG1G%qflG2r^au^=$qaF0f^`>Us+xrOL;X;zv9%1^)v_jDH?I`6Kv;tR?bE(n z2A|V-G0xLzFWj8ioId411o0_I4I?$vIvyKBUvG&L6}~3-R5=YHvF)7!!(4SAZ5g_Y zo?Yr8Q&{rl~)j(_P9kFdhTDC?>RARY=J8}+2 z_HaOR@}?syzde|#P+nF-3dum4KA9h*QBN&UrGptI>_DXUh2Xi2VLMyNLGn{C`{at! zk42i1qS)eKOi%pL(<}`^E|SrVh|?D>A(C=28HrRZ75{~s2Fq3jAaB2|MCFH-C>X4! zm6ij^U+aniPm<2^zRMAj?@d?TB<>KI7tkh>ZNV%8r7}ndPh%>X{PAd7z1k z1iLCFj$umRTSbZGbiHDiEIJ3IUr(4HEsGc#*QL5)q^EwlVV@5=^eev9p@Y`caqM9B zNnEOuk7X(b<)AS32&*uv(BWEENU`rm1Xr@rjs05--3ywsC8Z2IP!so08yz8*;T;tf z?(jFxCd#Z_?zEiMDcsldQEEfcbhVV@O*f52Y@1zChwtJzHESV#^-?Q}##s1att3_M z9V|xyZWNJ*ItK%O>|j9bL|cBsoveF6>%Z#ui{PhZDq{Y<_G4YtDw4F8$=~tVuW9dJ zL|xaqDidX-7_ccaR;`!TcNM@@3H541c7qMXzTZO=pI`;2YL`u9hPrKpn6l+XR95y1 zSbu$zvArsww?P@fT_+ynutS1!1BxJR%wU)B{(N{2$=#$p_3zojK}MuVHP(7-czjpB zOzI&SL&A@_qq!|_2`}nt*0(3_vLGSivK(k7iJb1H76B2#4DYFoz@CPYb;&pkg0b*% z+;OCoDUP|Xbp#hv_kw_dYf4I!f`aSUhQdE9C|mM~d8P+V&)eckph% zgL~dZoisTs!iNh^Tu7fU6my+_?cl=n1uAaTs?T9&etQ*h;@Lz_C{p!C%!3s9&pR~B zLW1F@dH#`$2`*rSTQD%vhz(ddKYiW9--q1`m_{zCA{2vNxau;WT6__tE{l^q$#P+p zMMTB3Ce7=)%=f52s_7o#R%mR?<&SE(XjQsGn3z}T8s|+GtGw_ah9D7=8w5X*%5+JK6`oL)D0mhNNk9wCz0B z5c}?ML2)NDLpPrL*GWfKg7FvQh_|VV<;#wLw|;Yk1=hqNiX?I2&)cxs_)Zl@t|u7) z81#8#_%kv2$oz};+k+b~Z&*Ae<=$+Gk>5DDXxNGY%2yQd*YP%^zBn zHN>f8Aza1RJ>Q3bWftVH3_-?9coTPN;~ZDh9xim^i$iweMbD{b9|}d9(i8OLguP6T zVks3BuJHjKnz#H|B5netg!q^w3huh(=`Iau0tYL2t9&{H&IyapV&RTLpg#!P)uV3- zzDN@RB>J!w&Bw8vIiodQUI`z?b3CI7iK#A`BnF>ZHiSMR`x~8zh2V=HK~!*uEt(sx z_;hv(HZW?NY=N)XVd@B107*g)3Z#*#M@oKuh(ZVX&o#|!yN2?JK8g3$8hKeOSr;>P zyy6^7(?3JtJI}2N`L@kVfcBaD_)2IS+4j#GURR2MGPHm9jc!yHKV%8S=twh`<$_!y( zc9a^<$)wpkn?a-FDY&4;bDm1eXnD6bScispMP!yPrG8Y&N5a5LACKVUhm@xALW0-z zHAF!%YavL)`KCx&sFzxVNu};xRz*tiEIbaemHa4v50c~LmY9AvKQ8k6eFzGrl!Vf$ zY8n&d+MmC@h;6#NOM@XUtd{ll(Bt$8e+-@1B%&g%yc*8`57ilUCslQ<%pzWvV~jo| zJLU@gerYl?9~@J>E8fht5R5P2?-g(86$3>Gt@Zdb_}Y;&UGT#YA~*=Q2%WPQRV;lN zO)$5_-ZKUGr6zNw*F5{bd}N8!F7ZTrPm~kYRD-o(l-)KiRbQh%@>-GhT;?5QwIZJ% zx!&ag<+L`rGN-q;?tpn9?LcO>**=#E28un@naQSlWx}7A)bK5@mNzY+m5fZK zCgcnw%Gy7%`OshDH44XKCeU_%Dp`k+d--FL(d_4~N1GL?;yDi$n}Hj1U!Qz2yxVha z4Y3;4Fg8VTyxK#XOy0VMt0&Oc3>w6!Ntb0eam=o3MAKF8x|=a{6eHx*X7^EY3^EA~ zx!Cq=W>V2&pfq_~=-?fqo8qO-a3)eV_8o$kbPlY+7;Fpv@tB)+6-QiIl3d$yRM8FSa1+y`ofwMv;s>! zv*DCdE?}Uolu!yr5_aWR_IiVsfLU>R(n_mw5t?2qB#{xNpN1n5!gL^aL-IFC64;yp z)ZC*2`O+ta>k%+8I|Bjyop(1k38I5ZUb zQ;sO~Z8@935jTz{erz=XpWna@Cm3c2=cq^Qgf-`~MwBNTaj#=C6sQRf8!tuJiUFVv3~+n2L6ygeo>zp;yYW!+LmA<6D( zTVT&j7Oze(fj_x7g!z~UwZbjL&3x9 zGQq5!u+3jzUtb>CEM-mHdEME9vZZX2)<0r!fH59>X#tD(`)2@ol66Z}z%y*}A+jc< zI+&0j;!-&K`kYfXj)zcJsDCax(48e0AJb@9Jlhg^(ZMDuh9R&ihfIA_w=M?pJGBmy_PE)xDiUA$ISb(#)vYvfLMw|<nPBVr=A47ackBi)k!IGwGx0O4uTf336^7&~kJPKse z{#%GAu-Do&g8%hxm$X(+{2mwzZ(r7ZK{Dj2xxj%gq%1W?$g_)&79nfUc}UKwd2ZAe zly7z#u2vbSpT(h|BZQRsEy0qoCVzq8>w{BhM>jzK+xk~tc3SR;e6qGUhUlo zZ!mpAKLQkJ7{=0Aq4XNu?n-+Qr`G_azqUPC8kdJ|=9rNEx`_p>Qj7d?t&n&jCZyF= z<@5Q6Mpi&vh<3{d`GZ~!v$^>Uu2y_{{bm=CP=WEF6n`rKVnsB(<@gh1N`@OwQHEpt z`M3jK_NDw51gWQ{)FxsR9ZHWyJz1NPLsu6@h8`2qoXGl@)2cj_65h;3 z*F+Xc*6tc4C?G1aOhUsc{sl1Ok)S)%n6fiYerzu%mw(wQSX)@P#RE2*&l1-`34U^f zt!@MEa$3(ZNC zNOnPKBZuqoyB<7umR%@>F!N_E{z$3>ZH1gGm8ed61*#{r$FTa}(#QTPx zARWGV^Vqu~gwXWv^D;7;5BPCYN3Ri+=4ds3qv!wNu&fO1$8s`qZ$TW7KQ^YJQ63+1 z0v~+mYphPy`3-+khdceCk~04t87bJiDnBJQxy@?PKRV1~2 zd$_;|Z2coP)jjWgGfYttDpgq`uS!_Sv?+$5s453;btj)Z!%V?ySJo?e@6T9tHijL; zk77#yJM_C6+g=aXeq&iO-S|sU{>)&Y@%)=%43TJMxKK%W#s{DU5i*qj@y5U*5CD;g~;^INt*V ze>gqBXf}HcN-l{%es7OH_F&&|c3D$Fh+4O_S~bR*7o*H4rmqyQ4S*b;pXJxb6|{EE zw3Ql<>ogET(S$OO^*z>J7ev9UrD^Ns_>Rgl!GAY$Gbr77QVI3IyP0hj)MkORJLMIFf-MERtY*M>1WBdrWg z`g2@RhX7?^1Gt58U}eL}whS<mm|LTz6c!yzO^2)LDePJ`J&-IIlC_VYZ?uX+J~17HW!<-a<7kbiM^k|V-KC+~gE1h_XXsqseY!5e$UY)SOH!4mq=(Bp+Vk?uIBhpEI|wUvikrerFF^Urfk`;4NdYj z(TmZR!8nv_%{X<+o=-T|jgvI}lR}E506(4fw>(3c$qtE*Vu{RQXVt^VB2O<^I9D!h zSH)i{nKZ>EK9#jH*#_wVU>8;_?wz3baCe_3DU*P%Ke7o3jXsR+Ik#c!T=hDa2kJqj zjjrEX;mCV$^=+8`;g$pn!~KL4B^FTfqI5k?{IfK@wuYo*LYo+~*fHHQa`n}5w)L`l%1pt2 zAs}Ja@;+B7#X;znrJnI!wS4<@ne0Qn0yv1|W=snr;fOBkmte$-Kf#WCq43BUUh@7Z z@UCdO+e0tA2Cao9Pju@GqO8=TE-Cr;9vn&O72U@WFnV{qH$p*F_oAX(#~MRr5`ZqV zlCUc>Q6!!~^`0WnsJM&>HJ$>6HZ)VJ*{Fb54x+gyvA~=|We*&g$tUm}X2hHSeYIUr z7*A%#*zOlRF5mcA*VTl9)rC?0K9K8y=LfPhU#ZzTE9O@InVv{fexz=SM+2|L5ST$~ zBf*Ebc2A!dp+Mva*}YZbD=OYGu3FIeqMdT7UmKy7W&)#(AU~>BaW$weK(`$(YKwpI zH#*n9fZg?GA6ZK6*Qqwx)*nW7oSt3L>sFkOj&>EFd&N*!_qan@u5i7piM5g^&;f#c zWH!v~j@#C-{@kt^@!lJ=iT0wsp_7FoX}5?wn7rl1#pR0^6X}PFa|g6J80Kj$+hvjR zX}E9UBT>_;W^W{Z;z2QHW=k!`THgDhYST1ptZsQA2obXlvvru1t{_lBuVW#{h^wZa zwxNe0lHyRJme-;o<+K0T@rW0DM~k8P)(}n?Q^R66n85e;c`Nnlc|qTjjRvmunvo^8 z=6l9;exYzpNAUJYI;qI9a8ET+M{{!9d^si8Hs#Tzrdl61|B89m1nD{Vm z?hhqOzEUygALnc}&-(4Qj5E?F`+=Hs&j(e3md$nAeuw*GBnC-bILf0a5wdCxD4M+= z{KkH4RvfAb<8qYje$es;{| zYwaG*%pw6h)qQg}fYssgiCa7iF7;)-?m42NT#SaOJxJ!u3c-GXZ z3QPO64!$INH-=(Wi6!FqL}mFlpI*h=ZAifUw-^$tpp2l4WE6B++%Lbov$*6LNP_X^ zdgG!8=rv>H%s=u<|+u@3v4+kskkc+uq-O?Q0q#Ao&zIl)5V`M z*4yrg%q};~FB|-d?rEA(U9J|`t2n4>Fm9XZ&UT9jBoL~Xn_q$k;(-+s;CPnQLr)*M z9i4=i7^+Tn`Q!W|?U#&nf#ER@cXgPHqEcG&Q6h>gd$v}=oQ^MX378tOv$GiLy{gAd z2BvkCz;%maE_rF~&(H0IX}D>USyd2Rq+>L1jZ%7KZ$rq5B1zi+-*%>*f@ zP;G=+PP^l?!-OiMnnNYBTU!uouOoUlaik!%dEdf!B^zxs&% zbSm3LNrB8={=yeb?%ha>A71Zz7q{9;erlCRptM$h|C9lHcEy`)pgRpJI&igHem}lP zLfm^y%zmQjY#y!Hn5 zzQ}?CXyXm7 z?ow(nAVib;3*!*2h*CyGCh^zdCh6F>iGt_r9?)x2n);yZFbas`mxI_ ztrtZw*NzrVoeCmVRgG=Qj4eWYfiziH)7#Ihq%Tfa{EzaR?T;=BbRxg3wHc)^Q<-uJ z=O~KT%T7r^D5OcNy`LO~-GcrEK|kw@Q6#V^tu0J;QD_029-P=wmo0}1LA zzOMj%|F{B)C5HkaiXT{mhn9?+$HbBuL`6AXq4hD-br#J^m~?qTf1eeX`96s_));Hm z!d?8o*Qc=VxrxakBqrq;&$p$i8IRRFrP>B=Oe4;etuQ zsoA?Uxj~29y~TW?td5C^#IjZCtWqM3l5U)`q7tQNehp)|-H5XAGV+cbJ*VX>?E2r< z%J~_=Iu{%uv4(!rD#|7ZB23n#l7LtmvEb$O9ZpE!if9{P;#^C0%QpAISUP{gO-(({ zqT6-MH;(DsH2Og|mbS0-HUq$QNTXn+&{U1UnrVH9LbEzK8IsasijkljB8bv*+Ahwx zB~_*z&5+7$lp0$WF`j*Y{sXVXZXZA~v8%Uz8uB#ZinEmssOC-*vx9sY6W#XY_Uv{u z`%L!d3y2zjt;v$8*gcSvS_6=sUziiMcQHzAsC>Wn`<;_(W#OhJJbXQD{4^SdlQMdO z&}@rpf-*zdCI@(momGv3OaK<+bCmMJC?6<63`B>Z;Wm)A3=gvJY(3Ddzl9FtctNQ{ z`TNwMa)1qi-7wH6pRw#lkH*CJ1p@2zPgyq_ODNV_vxqqd2)a6M_jq}$MegBqw>}PKYYp0 zZiCtR>Tf@AlSJ~y_b+y73@kqX3@|cpba966*puDIfA<(%(ycX39?{D7@3!0!X{(Kz*j^}iX%|P_3B{G8K zWcliXN`?=KZaEaP-E`>R4+>7D=F0ME2*`>A_Pj_jgIfCj%PmQzU>FsZnnL&#SGk=q zI%uNs-ePh1@#!Hl;JZ+q;ypfOSnm~5i;5RBkM_^n@(MJK+HW;SI}(P7xebX>`3We*`RWzm8uW-@AXV&7&%}vd0p;59e z!Tmp6uf>d5}H`P4Us`Px3*>*>k;rUI)|X&Y`M2+?_zQ^-?O`mbQSNHv0g$+ zjtic=>hJAh#Kh6B+Do54ob4d+`EplUch06C{lg5x=_iT0%&%{JMD^t_GQ^;*4gC{5 z+RObHPvbKwfEXWp``)ep@%(3u|LH&h|03J=btyBDzCmmuti4U=sOjK^j`8HP_>@h798 z(beF|cxv6YBv_t?R4rFYfx6N*qNfK8i&W?>e~)aSS|K!rvpvEc%ob`!LK`>4Ds4vM zd7ZlMJd>`k9n+3bg=az>J$e7eetw8{#V&zFgGgBoAsVhccCeCq8>Q@hNjW8Ot7+dJ{dJ{r$5k73;aH#EO0foKLm3DCHDpkJONXRj(=iu_}=nw*# zjVkwEO1mVzLQJEm?2@qH)@3;U6{Rg|>K7H_H_t7`c9&SBIOi7UVQA{$Sf$ED~iEmnc)v&5h81Q*FL zxB~vKB`uPMAR(tmFo@Cqy3kP2%7{~<6hz60b30ykB4eq^NlidS$nL>!D}!!{fj+x^ zJJ1A1f`aXAhoBLa4^9mYM z#geSDlG(NhGlE27|35tV!%gkJiFe|ppCA2x3JpAMJz7bT{Td?!A$Is(;w8uJYa!H;1nFS{x~@c&#eOwU7oCFg~}xRt%tVj(a@B zgHyJ2W%}qA4vfFw+y7y$hq3x2^fX2V<64i~S=Cz4LT?=&FxqWkm#M_6iQ{e)NegH` z^-1J#TLP=-5-g|HqGNHsWZ$baBq~&-j5lWvNn>rFBd+aX@bC3jL1oHtklSVTIQ3$4p9&liV38epw!oX@`p$lWk(jyU`FEj43>cIuVTl{Pyb zq8~L_j2nexUP{N8g;CN%D%wP;h?Ca}vx2QZk5OtNlUeyyE@fvdqI1u3^5z52ahVAY zhY#S~waQ-XqIBEWnx>?$Da=UqB9z>?X#T*0+>v|VKnc4Sr`{XX?H1dM?0WF6V&NGB zY_YH-7eUX$Z=Y_B(H|&0=uN-GvcxsRbfcLIS5Pi;TeY&a+qN zr?16%+87k1==8=#9&ajk_6B=Hle!8D-c6(}}g?BeWA4J?dHn%<3*GUG9@ErKLuLH^NeB{?WiP%D$%1xbHYS= zD$N}Omx4h;H&Qc*ud>AAK&XA;c}ZN8xSj0#( zt5zWh9^|?l* zFE&*AR?Rl#Zc;I1Kv;45Ttz7FonV>rNGA7|*F}U~z_^zUKr75Jtniu8-cyj>(OgY3 zL`J5kaLtS*1cyB?l*fxu(lGK7^&_mO9vsm&cJz!wxT6S0^&uyw&6~$82B;36`~hPkQ_W(T zGKXbq2*ZvZAcObK=_L|x@yaxE)TeTd?KRZ|oqJJi;)FV`rlvdJ0e!ZRMR{sK4*FH= z7rV)w?6vaiGMCUczcykaf0ERIT^Eslb52cxd6QvKz6%WMZM;CsgdzFZ`0hL;F)C5K zAR`LNC4_Zf>c=01QU*yqIw)7xz!)&g2k%2!$-%3rT%+66K&$^@6u@e?Ez9=W@vnsM?XkQ>UYWmF8@(-;!l? z0T>iH4|pAvivJRKc7P{&1q;6}9A%l9+)tQ-Cz&%*+7RdvHxqyxQ1d+r>)_yPyZ%Z} z_3Di+cqiAqtEj(xw|IScvHuEwmQ-gqCf+_8Gsqn<8lnt)jAn{OcDtnts6yBbqT%fP zfoeeoD6R$pCK#q|e!fRc2qEbFsZ8(sQ@jkw|LJgK>ZhIk)5{b16pv13POWO*)C)UhnSv< zgd;kemUcGmRx!A+%O=z)POh@w9jk80BDCumbj7VaOqUt3#1&0EZs}Dx=&D8+$1irP zWUUO8yW*Jn3%Jq3?&XA=`b+S;nuuU&1YG@gqQux;CXT=%96dIWT?I5$2TmElFqb@5 zA>f{r%PxyIO=5K*IG;bQ4&=*38_a!f_c$UjfW!?n9_10x{6Mlc&h$VG zD*9gxP&~ z|G}eY%pAJ@2_D+s*?E5b&c;Xgp{Wf8NXGd^1kp9z2PZ5SHlbIO(&LRzz|2R2{y+|^ z*&w{-QxPYSbU1WC0!!^cvIT##=};oSLzL>%V)BKx%~0Q9R)0|TKvNbrHxCzI9Wos- zh)oCI35$sO-DMQv!(3$* z*OEy(VJ*oCW~-Q$$;#aT<3~929JNb8_o0TwE0S=Z7i26o5j^ zpy3$H=jRAYgl5*;A>f#O%IEXXl_-tZV2vH{3305lO!Cb9eVpq2$;4aBG|llK&}DW8u`n&6``Y3oRd%ux7HJ0!Fps6R;GOZh(>WgE?PzBA}f2nK< zMX-D(*1_Ab5iHLAdhh6m-N;Q$o0Q|&zhTog4#X74CO{+N5nt!Tosi+})+zo)1<>Te zYl3`L3ZCl8hx|uISLAD+3aK3tjM7!eK9-`>QO)apDRb8hpTht3(~o2eRtGKR)S!;j z%L?>lpIWLqg!8faZxnIqvWuw#|39{?hcF+c3{W9NS6-m2PA9CQ(ZH?6&$-?n~PI zQ}#x?m>13pC_B)o3DvNMPuU+hm_)iIg5$5|ThuE{CS1dd=~S9b(|j9-TW_0cxZA_N z#va4Ktp!>@e3ww>hhI);ODfOP-5~+!#804*al}yg&C-Sni8c1o@tik@B9gz2wi!pK z-|rpK`{my;4kI!CP;5nf*rv&QSfKO^Gno~yri0o+I=u61dS*oKk%xvsuXb~!o^bN{ zZ<2wWRq7lUaW|yczL6de-Vy#~`gj)Qg?t7;sBFL?nTkn2EB#^q24NE=<`6P)0n12| zy&w>I5rJT)9|v3(WODk=}_%n__LUEaKq=u4AAKTg(!)iArF3cRpF7t2AF z10>6SM06r}FkYC+{0V<$CTBFIKHYKs7PTX~>o+Ek*!}wG@So-^$MIqj#Luj?E_`)v z^FjJ@hR@Jy=tsPP`wT=MbHnhv)ySdA?Bb9Y1sq(Gf$=IcoAH}=s6mIx{T~(@?81En z^L(>}LDg@?*jap_K@uma-Qp7&s+c=2yeZ(ZP+`CC+Cp2|8~GM_lS?zv@lax+a20fD z?-$!{CWrTi|G^pXDhp?@;k>l@?)sHiBKJT9qoIDKhZiD5zl4~stcFBgh=_kVA@vj# z;~@^Tm||TumTjc=e%S!jdfQ_YiN*p@0cPlW)SyAicshqKEDaM4eNHbdWOrW(^oi5w zvOHg#sIg5tvk2WO$gQ#721{nK^dR3t3Jv}GLV+2c?J0E@qpvneiNa+9SaMl23z+;E zNQWngs-2(Ue5#QFASov$TNJWM-{=)Gln*970IW6aX64Tjdf^@2vV%T~1GLNI4;r@$ zWiQZoTZn&9UNm|AYJP%dXGa%@u*qOaU!GVTwY)o0ajvg2?=ZjB7chleF-jP?3#B?-FFdX}pxEUvUj|n@!)N5NDn| zZy6$suNvI6s4n|w!4QJ4G6~RQ039YdmZEB9{1q71Ed)2!4Lqp z$6lnC(a;OxlX&|4V)6I5DPR!1!9joxF+pIz)xW;xZa5~`;=rtfMdUJ)Dj2gs!P z0TBiyV?z7k&OW(l_u%j)Dl_`jjqU&vbb?J%zH%}Runzc!h1G!i5tQuqyl zCkXi|0vQRf-G<}w48ODbMpWi`GNxjY@c^$x5mem4Axc@~keWQva426e$anb{q6>&Y>c$;c6Ohs`a0pK0~)#PThQ z@oj7dO#;UQhDz2BP0gN81%piQCc3GWQ?@-pEBc@e3=K4J0p69(AU_Y!WCv92uqs-F zA2)N={Pj$7#Z$1ylkf}WJ>Xe;R$Z5j+XzG#s0+icjw8qlu>o=|h)#m60MIedcbB`~ zel*7xJh&nRl{f_i?qE^I{7XcmO)zq%*e;r{`6PNk-_Vt>ormPj+=1mzuYJh{X#@o4 zs<#nnXvXZ(XQ^G!4cQYk1q(L3<*Z-#rRgN2s<+LO|JMlaXBJ?PkD{Hz@o0V`k<06o zFOW)2-o&?&Apkb>k3b>}2!r#wdwjNc$h7{ZxqY0mV^B8LygA8T?zv(7AzgiF1(Y0T zS(*+q67DWkAXa;+BZ1g36X0k(JQ;OBVSFbsTAh3*9f-I0Zv7KF5r2B?Z+4&Gu;em> z5IW*`AVnOC1m))D);EuyKD+nm*)n(|_3jVa*<^FmGW6ZEXuZy7unIi6Rb|O+!&j;1 z#HPqn$7jt4W#t_n;+NF|JOyOg0_r$&bMak3CPE3qRX_ObdCT(xS2a!AA2?d7W{hBk zf-jkKY_WG#r+WUz-9DLOS@XsI9uA)-7gTC@?^cs>dLy8ga%=n*iEx#exXy(e<_``c zmJ{)Fl+!WHRvhbrpE6_e9vew4E1B7x%(N=?C;eypx%9#TrFz1xL$S(Tx92K9Mm?Nj z2@Lanm-tTJD|~qK3i4=eX$~aqlHPge#_1UnwozjO9{;rL$p+4fY3Wk}$u*+stCLG6 zg5UZqeFSF0NBz#jnu#Um#$zum@$QQ<6pqovacsq)erizYAKG=XOicO`B`O2ZCi-sg z{BZ9;D!V(JD9`%RK<@XXofLehQ#dto+K9uGVw#bBA({}rZ{g$Q{4pIyg@BS1xrIFG zI(-Imaa6VyZ+^_A&3$B~)S0EC6PPE5Y&Qe>>_k7=d%!tu5dse95D6n<$6x5=wkEwLo3{&&3F0})g`-Q#lNW;;Y8{L3JCx~&*NGG!ATW9-II=E{cK#pm+u=!}WM zI%tNTmA7R!2IJ-@(gEr8$NBl|bBF=mWjH2D19~B_;v@ z6X|_^4kq^cou7f2*EKB`Saw)<@ZEzaPal5s2=xb(FFv3Aw@>lYo2!=d-<+xF8!wHD z{elW(6=)3u_hThL=ym{Ek*uss3-ri9XB89+t$L6zQZJ2Zz#7{)_J&x4eM! z37p%_Y%vN$#ZrsJr-$&Ti}St045du-^()@%i^Jb!l6_d_pg%H@^`Cq~8JUIVz|g2E zIf-TBs1^f5k<4e304@s=`4fY+66#7O$-3#R;}SrP>dI0pQZ+Ex0$J<$1+ETovjd*q zt@2vIQCYqRfh_*7L}zCZdBaMW-2t`X$C2^Q%S% zT!WW!^3j}DyqnDIswz42e=GZn^QihPf$;LD@D=}(Jpp5dttE-Pv3qF!k!}O%p{m&{Vm2Ux^y1R@9-eW2uScd$Uze?wd3Jj1@2tcKMwB}^R>iii+$4LLS8pEg+jvx z?B2UY^XHZV9`c~e~<7uO|reAzkjj z-Tv(Mr@#~=H*j(A8wCRB<$FyCP=1g=Y?^B@+RaJ&c66#wWvav5^V^e10NBjOTgaGw zv-roOLtLCI|K6P3zHRYG0|bjsGY#MX{J1t+LRrOL;;VQM&cZ2@F?c8T0z!j%88H;8 zZvgh*IXsL59yCE41*LH`qmo*7Dm^q@bQKPoKF%>0ZOec<$5Sx&!Wx3AAt>4RqZRh!`DJz+) ziBGnccxful`OvC>#=Ht=aQisym<9;H)1F<`3u`M*3stV?Ma0^cEvn`%IC_Qn)81e( zfA&TH{)axQ1H9q({_+3=b?XZi32axzN)Bm+ zm)pg>XeaLr>MRv2)1$5FDU0f|+#5EHIIAq+fW~M`p{x;jVvD4}2qmxM;a;xcyoqLM z1uIB zpKR|P{Pp^?&y-1bCjW|x5TCvOB_U|(wI1R-AyrchFu&tLs*#)MdhiY_F+R%D)Ne`F zHE7(afj=IB=um^Kmr6s<{9*_sm!A#?Wp{s{=(a;$h?qhlgAJ4b^HX4jnvpv!isny# zt%k@&oas^xhGS&5|BmoKMiut~(%G_3ua{?T)?R_%ak14DVP8hQeb+7Be6d3JtkBol zKd#kS)V*#Q1AOGi3GQHmjNTrdTpR=R7w6N{u;to<-5ZLe#fKUEGAlgh3YDAr>EevV zxt>(0mRGBeW_QTKRzP;nJY~DJUo4lBK$-LY0Zw@&HY>fi^tmTg-&ZT^ih0;SCG)$n zy_~i&Gd=0@sY&A1A$3N+)w{q@5nC!0g-&NrWIZ)6GdLDvzHyN)KP^&jcKzx7j!w_! z@AP}@v~ZaA4xmOZi2TxlAiwf0vP-GwlOM}|wEB0YAg{cv^~Bz?wc8Pk$Xl{0N7eI1 zn?Gs?lZ1&s&A0)dTmsURP3n+d(F0e^ z7n&hcl*vd!9-w@yds(R0+tk=)B z1*#!qB_qNCl_mn9jrH11e3;7n>`3Mm_FxpVASdZYvxtP8Zi~xPr>!K93u^eALD6)Yd&aY?8_N9?AJs$M|5Ti1JA^c0kMZ%4~RfrXTJAx-jJ2y#A znw)Y~JN&fqL=qcj0s|YNT-f*pi&>EjvRpRec#yvc*Pl_r#@=aRW53k|b6rdZy%^z&eDkb0+L7- zA3R97#XM&$(0}32vqz9$DJ4i11GWw#l|$u~iX2=TX)r4U&5t1e5S*!}nAuWeJSpcK zh%pgpBw+(Yhb;#@9|^a}Se1or4*@LO!#D|<&io@ zju9BOf}+Q*T~jvBjF8&NEPs?Kre~Z%Iaz+rAC8wtVN21Qr3tUaGEFgc^~L^jUr*P5 z)QWWIGm8|q@t+*XmJD~EB1BtISp#w?FR2Q?Xw*yT&YcNElE}H?>29_0U|AtbYr`@* zCrd>tHP=h&z;OYf9gOOjWs7W@1k(H~E$Nj-#4{lQ6)iQKam7E+DCRam~0A7K&Uvy;SZvO$AMUWN9& zBlC%poXUu!4cb6)lx?|LZLxf+{%>1irtcxMEdAnC6BJwWJ2!3G8+CB%)a-!p--@Kp zLo}sy{LFuE623q6f3v`keKts=o+joU@ZU;eVtiePp#8M!w0K7mq;48$W3xR>a)T26 z<49Os9B~_hLM}WALS$?5Ui$i&PzQSqDvgF=6Oasq{`LzBdB>;9ps!iRUniwd zq?XmofNg`$gI2{S>NM1EEv8LSG_Q`pO;Jg*?HHr_k+`l>Ii~Yw;_7#}#o+ky1hz+UoJCZeDb-vh`;vIg1PrWFI*c00hu1NR%6Y1zj83hrz z2vs?~e0?Cs;qV2XV?Q{FEMUg|E;UPviN0+dLmJ~RI$GVcV+-IR#Uy}Z-akH)e%v5d zRqhlXT!sjG0kV=21d+92haUo?+538A1q2}g=wc0LkL9MnMD1N+%zBijAw!IRdfLwBx|6kw|Uoq~Z(>L*IUdoH_lm4Na$)2_Du2$jcUvo32H&}ab zYf5ADBTJbLk8e$>D$O852^yptBL|AlW*28?i0Z>Wn&LqPF4tpwR>f;5ctGJ2#G=zT2+|BS0}nwR-*Kp`wqxLiRu`^I<79EC&dJ5;1f${@ zQ%5n7sAX}nJUYO+RqKOsdtM8y-I!`NGpnpZ@GBC)gy``7St)%@~cYj!dl;acpD3RXK(YHc7Kb3uLlM2Sg?>h@4H0 zdJ1-!T!;1LAxl9=iDOEqJQOhsT){@r8cdd4vwTQvXsfA1bxuall&^{&HJZHVVmh5; zfUKt%=RE3B!&!$s-n0VcNk#P6w{)MHXhq(r_K7`B<*SUmB5%|dd4RF8FHhNQ@Ruh5 zTq3h4moO=RfrA=x7{9O0I=Rd2x;5E0lJ!qUL?VrTA8Fno(_3FJo>S( zJs~`U%(=nY`>l_XU5TC`Lgd-oyLWF525-N7i2wZVA%A^{Uy*^yJjsM7q&Hq?5)mq9 za?g}?N!~Zquk)O}eu{L+yU(6+zYv?jR=tFew9w6$tRaM%r{ zY3fjqrxLx7bI;N%xE|Z!9~*>MpgT=cWS0P*>QWJBwxsyV)`k1>xbuXwl%gf6^{)o& zANWQ8{-2%>fC=FH!`gMZ6ifbE<19&va%T$H>Y7Xp`;bR7Y!tp4@vbDTkOAngv4Rkw zzh?5XDb|f{(_;GUo#K(3R=aj`#w{d{}d)cMD_wG{R-p1(vLk}p7_q3?3M zuWY>0SCs+lT#zCE^7pm=i%~g3IqE<9ERTL)j4P|uT;Q~_Sv9H3uIlfox*KY{Q}A)I zEn-{~^|sdQxQnN{)M_N49EV!;$xPGTZQnse&mj4veCm5?t810r(M(RS>)`V#bNNSS zEMAeWU%(TqHu1LwvH2(Qf?x>(ZW$)<$J+E_zB4%)Px$qE zzzbjeGb~Sf5Huhs?{$!mW=K*^ITkb+4#Z@%!hAzf6}g!?P(RXRjz@n%C2)dj^+Eur zCKCxMu&e<@hAf|mVF`S&0ZV?L4=1b?fe-Kwv(aD3bao{#zXR7XiJJiOCvR%uW!}vN z$(6c+MNXbD2OU9+1SrSH_Af?HQ-V&Q7!PLF542u?6wxMnGLKFO(uaA{Y>Z-pATfLg z_`k$t3}d8j|GnrZuN8``fqC=Nv5?j}m6hlhNLs?;^I6nOIf>ViwzC;d6uWv%!^S)( znP(swDVbQ(Ux10fDt%HG2>u#FE1@c8(#W6Jq(mpp(hS!8I9tkI3CN4z72NPV*I}4Pvl|lAfUQ z1&>&alhB~Uvb55I;kHhuvy1cAT-U}EL=mu#8racIt}QcgH#RONTzVZkFFh%hYODTD z3bbqAEr*X^8;Wa16~4TCR}EN$SmVV6NveJo3xOj(2sr6<$LyVL0fQVmPW zxf<9*?@+T~n&9UGQsar+5;757KQeg04T|w8BKr0yJ=r-uy_j>k>=o2r-Q+MjFfjwI zcM2Qe8q4Sn2JiLM@W=lBn^MVekh=eu=>)qg*LhA`xxhYL|Ld*OTgSaWZ;Ur)w=dRt z&`g+w`xt;zKEoZ|_>+65Kw!pwCIA#hB0nU;K@Yjv)om8B>HixWYY^MO3VrZ^4O3AS zQ;O3a==r~t*$+%Y$sZohPGBsyFEne|Jh$#yJ4CUW&C{}b$froUn4Te1{I%pY=pWYx zaJp~sKkwIGf4o+{aiVH85ZcVsV%M1-@^2YHk_e%a6uXL1#@VM@o`g}(A9`_51^UN& zE*147%g`F7C5t0i#1Q^cu+GiC!XybMofuTb>&sg#Va2;pv&3#`%qb(CsoQKEQ4ZU)C|!4maBV*QafBN@ zKqeCKnVp@W9{u{SaPj$V|KI(M`yX&V8Mmc>xOI>J-PquN5d*>x|GhsL+~7a``=8@D z^!4kE#6>7>!K)cO+1vj1aR14porA*%+mCj>JKWlQa`64$c0jt7NQvHOmJbG~+&U*& zxbmRX*P;?o+p+hRxN5C{3Rg&m5x<0U&#c3D!P=Alr58lF?$?VGBm67%t?vhix!Da8 zLIwZtlSR+>{8`wj;$iaDoY8 z5{%Hf5H|d}M8^YV{=oPOKcvt0v0yslwHwo^?y?|Ewia*UlpTx#^w%Vt+)4gT1PfY% z^qZ($on|`NI4Xk%_2j`_se{oJQhim`w43QhU7^RGg;c|Cr=NCZ9>H;^i=TrERKPG2 zauBdCpkazGG~j62AtORYC7*lTPeWiDN&AuO+PJYpm<6L-Y?5L-|HWurGu+i&$k3D@ zviFjhV7kHB9r7~BpBCkkFkHe>0hom0WV0_GNc!rGVDL zkX0pIC1pJVJ-|lfE@BKrMIsG`(bpit(YX|O;IcNeA<9jkhSlk&jXA|i+3Kp0fTxl~ zCqgVUr<-t%kkexc0L`?xdki&6&(Lx(Ra7jvyoim&9bzMQbN?r+yHOGanc;At5WxF` z)Imvq4t9}TQ+xK1T+nK*eLNfk;6hAxS|;iF^ccxx^v^Ka zlM@u=IrR>IFsG(Y0g!8UG5L^9axQU57x^Bt#?2{TFTc)E@SKc7EDjln0= z8Qi#a+-?{C!udWiQP&$6Y;fxUOb;+6)T;Dl?2Cxtt$QlV`;8YH8;^G%{gp>Ueup^- z%yG$Q^HZ=ol(zPL>z@4Udzs~wAsJ8rTw!QVo012IJM?XnsQf7^`yC(idWL*;Q&R>rnqoUOq>XMCg zeI%-eAeWMUV6H5bh_i%_Tlf4|#6F18Cesu$O6n6I&9zqAHzEVljUXbC2nhA9=-)!! zu1$bxmFEC~i$K)tg9hHUCnf9f(XD&PvjnZ3;{>(Qex6j!>|wV!afSa{hED+PeZ!G) zvzcvGmT3wbdw`%hoe#EnhW*j_N3He9cDnr|+vvxfE->h~LTD$uCB>3TjTI^hZ(#X)#Of#OuBBr5j)b zkw4<%%C2)oJ zvb3FnX6nKuEz=^}=16t2cC>30v};Wxc8q>#Eo+y$hJs!Q^WkYv=v)d~WKMUYY$^1P zAkdotPO1JocE%APfI z>mUyD^dS7B>=T7r;e*)QBI*8{M(4n*09gtp5nUwlmYAoY9z29%efR%e;7kvT=ae6F zVN(aPm6@!f{yM75B^?YKFod``DLF7&>raRUFriPnwZQh{cXQJJ0E}!XY+@n z`Oz!v4Zu+59E58(Hu$T&X2~R6$#sR^DHpi)U+vq42KsIfyh|Z|5{wVd(tjH3B)gZW zdgD_U8ZtW)yN|bQ8L^zH$#ya{8x0aW%!e;Id7trox`od7HD`poI@1@|Lqf7cmGuUn zgt$1zZLQ`$(vXMe(7fD8Ih0`ZqITO8-1r6~THC`uoYzPJaaOsS{FWrw!H!4YuxwH7 z5Wk#^__SfQ5Kxcmx)|a1Isi@rO3+qW2z6vElgR>|jLyU?rW%Yg=D%G`aq`$Gb{TGv zVulP~gz73mSm`awgil8fYYHTicp90-N=0(mjcyTks&C&$j`#~q9I-X|=2H=eFM17) zSn5A-?`=PLyv6msrfYqzwYr_c=0`|;2nB{Ux!i*$J#K9LWoP%np^Z=*|0g3Ja%oQC zF7m2_X_;2Z6z-V+&w>4?A_xZXBAsz%2+bI&vb-fh>WYHytBtzGFW5a{J{st5$wUH; z21;A0REyP$lY!tie45|+E1Aj0y}`81k)9d-MD^W;R%WI|a{y$Em_#I-YhY!0b4YIvg)*R5z1W!c(m z4G7q$;+*jUAK(Q0`n3STCNB&{fHEN{!@=x+FH3mq_A@Wl9-UJL^!Xoi zcT>;&qS-s27~b4__JOV|=LJ-=aYpyY42e$~5gUUN(@!u(P~>dQZ`5bKi9M!-Ml7-+ zy`+^S_1db1uDI5CAK5=VJ!`fBl6|chx@`B5^SnrRD=5dA`S^16`M$J1!1>o%Uk)!L zZBa#wC=08+P~s+~=t)#*@Wn#w1#5V(K1l)ruMF*0@RagKu zgz_phu|uwv8)Ry;tBjvM_;fG;RpWVe1uEl9<4-p>bFWt&nr%Pb$nLk)M^EeR%|6}0 zfp@9qG6>Q4I?fdS=)TtamDFfJgoc0pKM@~ z=oYS)Sv;(_T4~sZ3h&m4PNxh_*GB&oLNW`;U;zk7O17}sG;y&N0uJ(1_k%VkVIwID z(z2&!+$ckkcPz}_>Ja}8(`{beYjGPU$nV^H+z%;X3m>=zY8pY6i$dG-4%!Nq7Mn)z zshd@s+-!tX@GNOr=>5u$B*GcMgho(MBJ{6Mwhwn7?|rxVh>j(YlN7dwgfuc^n#cmH5>_n`ibGuSha?69s#@Gr7Yp=$nuw=ywd6Tg&HoG~B< z2rz}C-?Pe20sxff2;QM9m{0ky!hF*0GX{dPHK2>uy>!t409t7XBm=Uw4`XXd?@qtN z^h=N9h&xKO`HXgCcGB7%;I#Cu{iOhR5)HTRnbXlipo}C&E)pB)miPenLBvkzIWt|k zT)8;1EE;d_=^7M7zk|BxlGm&^4lNx`tq*}0TOz{~hju*EKcl%B+PYVjo2Ms@FOsVD zLVQh;B*TGu9ne*dIO}r$opIKo14M@zjp!oxfQ0+|vx@&s- zg>5*OD!@O#6vBmqGsyLe;E%kcQ`6JX$Vbh4shKvDT!b% zl~cPlhP)>>ge^oJ$~bL7;|Cf`?M?r^9Cdg+JkzRHYGG7mn+z=@N{S6idQB&O5=e<_ zKE;wNB-le*{{v3Y)ka^&@iNe=%TfAei&n(jUTQ_oco?pGLHN449zKdM2{lcJKId9U z-mOK~r0}Rkb9#a%wMp zMN>^mcI8!NUt(R6WKeTVFIg=Oo#u!?u)?tHWcxWb8?YlO;i>4_)H!m?kuhA%C);7o zu~^oR1#nwOJvl4T=y=8!tnr8FXO5EQ$Bi?%()SWUN`hz-FTYawx}{3f$zMdo@=lvC zq~mb?XOyle~ z#yzpDbRE}Um_z!NRgFt>iDfE!Q9>%uX(#5D*9GUc9U$p*3EK+bO*-Ib%lNhoS1qCl zZ)^0>@^uj#D^>(gx_H$m8?$#~85ft$}9*`XK&G?)@xzE%E`el2%!uX}uAwR@nFerQUN(>~~ zu|#&EKciuuBP(SLyXB8ikTj(p>jHo+2_Q0TQ`=~bNouVC*_4p{jz79jSJ@xd*WUTk zZW^I#>A3YIQyDmP)0YY-H2v3hVlcRsb1O(txi$}?f5)R^NE>0s=(i`+=fe~Cg+7>7 zk<)S&L_b+pmWl0jq;?sy^Oz#74F)T^10yV5pw!iT~yggLrb%7-r-Hd zB&&TLOaimH*-Mx0x4?4Q&hR>b`D-A1D(Rl$Bmj% z&1N;xn*_L)ZBTq{yX~%<<%8aD%GCD5jg9XfKiGM=v%Pn?x4ntY-A8{dXoDv}u=D^Y z00)!b-C%L>;KH0Dd+k_e$a~{`TpaDR{pOaA&)p#%38dk6H9k!?Ht|}FL}=J||L z0?Gq*o__er?$KAv+@mG7kf0i(g$N0g%3@`iA>rt18WY5PQ|umT4@`TmM&5ewr$5~P$JZ6@R0Ph4gX+G8KFCD z=yr^+iF#S|TQ`ykDn|gQN{Z}%LqIw|sjSKqdSE6?{L2ZTvn8pY#siC|mEe(SB~=Y< z)$y4uU)h=C9K-@Qt5*0K3dOABuKZUhg7l>Tkn-7m-9LUNM@2vTObnMBy#u5fNtPzh z+CoIl{T^RAb=-SMMe=5P{$sEIYCb=kZQQvt!8(s_Php+%DD&3z>>Z9Dyqfp=D0%$V z-Mhc-Js7?oANRgJzc@b0Umf$|OFp}eIq=gvpB;}7L&0Sba_GtP<^IHk%e0TweJ>X% z)ruHRahzGsa(CU~m5*m*Hvw08&v;1y#(%**KDz|c-N;XL6_+hrxJwIL!hVBSvO>e_ zbfQan?gQwgej`?}s^uFaZ4fc;S4t<7icD0|uZ$0pF@>`(dEu0eB24e3M9ov)wghJU zK{Rc7W;}LK+$HsQO_GT$S`;Ze5ZLMX*(frRoSwca91`SI&rm3q`w`K9Ef>62GeA7Y zLdsFSf3B4bBIgcL++aN0g{YBi)mVXtefg$KsSP`hw{NztL%1e1*+X48cK30evW^Gb z!3>a8vNNJrv$t=ZA(5M^L?9xH#wvtP4sM)NnL(Zn|4c!?9P zr%~dlf?EGvBO(0utKwT@5}#@QTq%>j>DKfFwN!8bB9&fBBj1Na*#%RI@JQ&&osePW zT`}tY2Ph&)azY^58>o$W!!XTFbT?B`Ez;8q z_PhVuV|}B3a7RT-F`ASER17Jt|3(k*$@w_{Sd3yWwj)M{$Yhcs6x{4d;7em0-bHX> z<=8SlNm^*ee39{scL&3lFGrI6hLkn`P{tO=nTI(G)P!D5oTg3@4;X$br@e`9V^N znJj#b=hS-r_gok(;K%Dy=NQ|siNjiwEOc|NcO`C2g((;C;^z7J^vy%d75gv7kxRJ` z$SiqJB8+%muw2=U%(Sv+u`Wo;=MRtc-nHitis?qe84ktXI(Hs#l+xl@nT7LjtLddk zkv|_xkPz2jOjK#dAwK~VL_X2(R8{)ZkXF8DlhQ3k_BW ztT*qWe1(>yp%%nrTk zs4=us?TYB9IQmEe<&7i0+R<1bv2v2`1JQPc(*g3=P!Iy@BTb)9b%->Hov z83@4Un15&63sH9HMRFi`SuORP8A@q?B_jz6Gsy%Dj<7#O0|Z^!r7av*Q_PzS^ZX$fJ+;qXG*MHWWY>8?&`sn-Uhc9L3ZUeekc z5tCTYNF}v43Jc}{nlGUo=BJO&=NcJZCINF8)nuQ2jeyDfCW8D$UDm6xQ+kyH4}bu5 zNSxe)l#rHA4Y|{DLGObcHEd~?Wp0`ePSCiN8)L>t+2Vt`Rt#W#%}kQ>0m?dag2=CM zNspci5V{v3EA(QqqqvaDF#HnYF!sF*dqHl5Q>mdQfX7J^42kjzinE@uPAgMg9vq#n zM0kxaI%qE#rdg^X6!Upw-aEKAP_8Z2#k$TQmndqv zNlDegzfQ+t_d*rJqSq7#3*KikLL}IMpD}*sYeq?cOH*OY`W3f~q7gE28E8fOu8QH0 zHOo{XkTKG9F4G0W(uU~ko_s^rH`5K#C2m%2Y)qs`;`rZ3{ciin&%#Bbrzt|KIm^yU zV9m{plJJ3aZh}!htl-n8wu@Dk_L#UGDECqDOk_xwGT}|qN~j-ZD!-}B60qn-4;_=f z!F7IEnWjcsBaN&YL7wvBOg9-p9kSsH-_B+fJ9H72#947r_HFTf zd})imRKRDCu{pfY+|`VGsw=|apXbfIrI2_GHU;Ws=fp%{qUj_9jOqmi0mqt}>jZb} z-mBs48&u%?5!u546SXK*|KySmd>SEM1b~kylgT#6w z51cmA$0cGj@3pCP*Via=XgRyZ%JiC~RuVw+qy6npXbIwXVxi>jbnc zLx7~H*^flusj|3csgEPgS53t9TK>syurqS@De?|d&U63o@6E+D0;`Ld`YG<^}O2MGbKF8u3` zU?NYUUX}VN2&9L;q=FF3qIyy977brO3OAh>*d#3Kx&I0USV_jX=F2LA+jS6Lm*^V4 z1v4u`KjK9HwGu+Je&A;cKf_vN-~`*w#I5|63W6Vj4AOX(PSB{=E!}9`9F>>)NDe`SD1$>$ zwnqP&-Pn-HW-gk+-I0?^sc9@X`lLM81Tm)_Lb@|RR(2*h777+8SbM&ob8vvDX1Yuc z)jA-u0!ct-3saBvm3CL~M8ZtNQ}|7ixFs^L0aX4&hHUPeRiY&_nahVjT(U0>gy^v* z7fEYxWsL5_UL)Scr2daeBK5ujhB5B28 zGkrC`wv{U=B=b;WC+;8l;!Dl@A&=kY?^L)5P1_!7mP4BMA|SXd3VPfVUhKW3yugpg z28eMouYrU&A=y#vn_GN{sGeM$PHIUs^b)W2Rn40f+;WhZDg$L}Ln?xOI4sJ|yd+Td zk`HnX`5_z}*&#Y@Vn_YQ)DGwM=tDC74sr>*E%LOn)uf3G7 zmtC9AwM{0zW`;#4?LaW@eT%RQT{Ezh-!Z_;EWsdzNcGm84#NI4WtTWSJrjp1Vg>5@ zHHvo@`a1|^iJRagHW}TicRX?Kela}Z&P<2@Kq|zo*8H?wf5SoCcFBZgQ_wtIi19|s zbc35^KQGIlC9bqUq6QvdDnXLd=G3jq4?eo;!9Ha)uARmTuoqbwKj8plKk$c0KOS61 zSINOh92FB<*$Dj=>{oVG_vV#Q5-6%7pg(Ov==lf?l!7oBF;dEC%jn7&x8*=~x~wdu z->;rlVrzHL_yqlySV9k6H9%f1^ zc;?Od@GKpUuy^@c_$=6n&Tj#1)9-;J1i6d3YB5XsiWkdW2*F~X!ek(DeAd10-m{{R zY~(u&Px7uL_98q!yV8zA{*%+H%n;6c;H17t$hK&uW1w%B?xMxiL;yHmqrLJRi>EImsWE1v{6jEv*&rYu{ zadytgyW|bJ8wD4A3MOK=>7pf)N69;4lO_$a;J9ncWm!2JeepS0+H8W}E1h)}>oQX< zxqlgd=Lo_|%$*meE-ujBrXB5Nl)HY#Z<|eZtv`PDOI0*0v6o-s%jynfHSQdc%kaNm zIJb=8ipGjJj;B8KW2aLxTB)^JT#!4iX*eRA!^u;+ zD#cEB!3M{Al<{nc+FwZo*|x#1ubXas@hu^66Xx1_L+rccOT?%C3LkWEL%+CD~*%^BhNsc7OE^IeYXF;>V?PQ18RlyMw zn9O~LOLF5!tnc^grsi7g)!m zA#MCxtJ!d)39apg%Vqs(Z-Hk5R_`cduGz9dR@^7 zON-UOT^u`Uv4sOmE6G5rn|_+?Cj9DJe-$F*et+iXHmUV)ga0SoEE^1TVIHx52vSzj18ma8f#_m>o#MEVOsx<6eV@BT$6c`uGNL!Et(iquhFAQt0) zYU+lbG`UPBO=n=bp*@kvCDtAR5FS8$PDaGPjXSEG#weho1O$P3I>+WQZk_GOJL=7+ zz3IjL>|ze5gFndrur3uj_VkYYTUx(}#_wkX-D2@l3}%HuJQ0~q`?cvLFKpMO%JEwX zRvSHf5d!Obg&b3gy+JMIVGDfqzCIoyih6|ofa9K={crW}9!*>LMm$ifTosOTimQa; z=I8GUBf+LDp3M{Hfgur}3Q1CN=<%sy4`K9=D8DzS#vdHKLUjSzzg>fV%xENa&{iA3 zO+DlVs<-e2E- zdo(&@bu;9$NW#M5;dk2ye}4Sn@Q`~){p%aZc+v#J??$uP@FncKk8JBtWq#K`ZusAi z5O_xugt!OWhu`m`Sn&4V-s8P6d4gdmYi~dPod+ns_K0mOcwiPyJ9r=`&_&BChZ#+4 z>fYWcSCNB?T7Npc_3xXv{^f8mc>B8-xA5N=FP_=6ySM(I#^W2dyWi;VFQa!Tg9!-- zb(dHkm!3br!1*zuJwk3p$K%#W$Stfj zJ$f~5H9c-Wdh-feqSX+6)?dJ3tTnDZHs7+NIo;0ID>GhN&jC)?tKqEG8fvojOq5>h zsg&rz9Z4k{i8^aNMQpV7j8wrhmF*>bDVGqmKEU>3>)FKw23G5-_{goNqtml_8(@gs z`FL{ChVSKc-d=OJms_2S}8N(83J;q{pykUY_ zt2qwU4lhpHy+21}P9o>W-+6+z`PXA6>t{Nez(fMn* z4yrzdJhJYbpEtSC(%2;q5Z#WZhoL4D4ep%>+q_v>5}P(Qq7iko_m}Oz{`2F#2m9%@ z+eB)9wZ`CPj<^PuvcJ0N4p)I2<%lCS;VE}pq!E*h>GG&$B~#9xK=eekZ*fHOhYF** z1XqI;3I#;86jp1dP+Hy>!=pE)w7qN$Uvd)Gqo$A*UHy%xg;;OigW@WQ&}wdb|4g$p zYrG^4MNX)#>4>LJ0@^z%MziH$rK4D-w^eM?gx9y|E9W}hxWkmD8$JHhNS~9P1vm!C z2I0ZDOqA@X=I`~?z6!OD41k+aAD_7RMek{mhQqLY1|_jSTuKuyNN ze-Vm-%gPRMh!8!>>27&m^eh~w4Aij}*f8GZK8P;?Wz%J1R^l?%8CxUv^b9sOTw+>e2=vM~xwnrPMK-}#z;We{ zxQt@G{%wgAY2dPtJjB6Z1{~h#-Pg=R<{b)e$NvI8?Hqi3=LU`j)V8ln0ds*|h+_zn zMAb<1gcpxuyKrlH&P$3mDEM{SwU)@htRzp)KlI-J_T%;UU*43{2HGjIoIj>{XvVLX z-CD?i<5>=R$W;#)vh~y*B#hgUlAI>zc@$2un21^erkoe;0X$q^`_%&qL;Z4vb?-=e zva~pY$?!86`VpKOgirRdUGfSj_T=(vyc4w+(8Sss!X^itJCMp$YN(Mnw-}O0q^(Dt@3czwsC6h?>bd-i+l9QbJTJv?NsC~ zd(+;KIK}l@%D{?fI>46AxC{F$-1ZdS^O2VqH0ID}(7W{k`rbk~6wa8rX$B2M~qn(7{7X54ocy*m(aP_!PU?$YYot zosVUI*wduHrtV~gMPn=$k!0xi2cGJYT}zF~J@HOHk$_mp<5kX0wdQNwn-3V(@0X*l z2+Ypr)j?eQca2f~s3;%M^=(~pMSKScR~1LOB*LZnI3o1wyqp1`)F2Rrxzyz6G^q3R zrKJ{Wz2C6i7KFVcde*T}xce_de6tQL!$+3H^I-eQ z-u4#m;(ZWk-AJS@&Q_HUm$E)~joB`Ngn~`MEvrIiVbMe~vDVBgV$1bHK`lkTUouMz zi>D+T#+DWft*8|^O?;q3Q(ShgQ{gm4ijRPo$N(=?sQSH9F~*DiU~elJ2#b0x$OtsL zf_f-ETGYSGap{;jJ_4^o{r74rf&qDiO`SchncFt>f{N-%wZm3&ni`Imvh>{Od^G;i z46WeM{b%@zahC4Qxf96ScED908x*nCX%d=8SaBIUKXDJK^F}Rb+qiNtpojZh&F?#h(pV9=Zy%S{RVbi{^``>zD=$38!Y;4S@ zp^24kuI@-AxPFEtU4`|3(sVD8rb{Bbl=_y-Zju>pdx(`<3y}KUmI6#A?(bR6fF$U# zze^!+U+Upo|FYM({_*U)inZ3P;=yKg5CPAloWcb z79ZgD;8tVHkkBb{`Q(rV;X1^T;X}#-*oVmHE>ljtsAS7DkLGRgjVfCU5}!=LH9Mv% z=?L<$Ky&YFNr0X8RB!G~#C|0=j`E=mH&hD$VUelplQxO!i_8O|9s*EvgvBP+|9+kB z$rA}H)*^!u8yh)nkAp8PWVh;0QF9*sYpQ{f%wvHSkkUsigkK~%>Loal7LK|N%mGBn z1;Tj$B_94pD>*`8(T7T2|lxT9IB_Hy!IQ~k5zhV^yQo8=3nZ<#sbq?%;l_lJ#KEl~o z_j86`8;6MZ^Q`ivSw*Vg)7lkc2U0!tUP$w%q4yLSYKzRg3S(6-n^RN= z{M@F?e2uG^Mh_%VEG4Yl)T;aZa~upOXcJtn%6^eM=&LdAA1=YxNue%e>#S?5d>!K# zRypSb_Ug1MC4SQqi%IJ0pKDpQ>zY-#rO`11i(Z(g-F;%ThPYU03BsPr6U%!87^Z`Z zH2Gybfvt8vd?)#RH+xSL3L7?w5cSPm9;orsant!;P;^ra&u5ZIi9Eu{rPOSC=9Z>r z!%RblxKsm4mRi4EAVj08Z6tP738~m(MVL2oqjMl(tb}g^%8BMxHb6>BQ3E%MmBq>d z3;jgaL*lR9E`A;dl7GRnE*E*_yvMTuz|xJ!2nPZU3n0;aF0t;5kLa_+mAD+XoIrm% z!n~&|;mki4Fg^|1yvv_}8)42*fEnrMYIw;Yd?Ks_Sbm}2O4gmCXkc%7Ua0ITsQnsq zy-MpfDx*@DSzfy?=A~H8MqEYxm>9OPAflREZI_V2KIp0fxG}xUN?(}fKAt&l%l8z0 zj;#EnZn-~^8=T&=2f2Q0IST&A5X7-U#5^X4|Mb<-KMn5=fB$^Yc^>dGrejL8TJn)@ zyD(_8(8hddsbJidtFvD6{oH4?kbG-zEI}5W4F4tv!Ad`~bHfWS#yAau0#fZ%%p8uW zCvz!N>f~t6WFfLLlP$=-sqs%}=)DpN0Xqit!5 z-IBlY-iXej2+|rBOsrgeYXoBLlOYOX&Ms|88%vi)Rr9tu(psEpVeTYvN!X#+iyR|r zB{gUe%`$f?b(4Y;-Of}9NuA4M^D4u6TFBD?HgIM7(V=WirejjWHx* z0y}S3<`5rBWy9B{H`VIm>DueEu;lA(tkq-e1(s9FO`2d3NbRUcYPD+ABhR-OIIW(v z@H(HD-zV`z+9IOXxj*9VW&FH^x`6?aB>N)X=)cc?$mP(PR$T?HeOyniJRhA-Uystl zH}KpMgpgt(zFm?jK!&|2E!go;k_8KP@!J2QmV)mOfuSX-yBhBsrXmZAaRGW5?gdg53SAaMvVb(&YJgLR;cz^QdWIB0wI=z51x=g6-PUrg< zXJ@$ld~_VP9S?w?*n4tTLT(kXjhrf^Qw@E%R9N|aBQ1B55?E6| z>B(wcMf}si3#d#Cxi;nkF??mCfJzhUgbe#(S#wy+K4aZ|`L*QO+^+@FaQzhIMc@7&sla8?pX*`mLs`9s*a@(NTq(1eKr`_n(HWT|;213tdxExf>MxO%Cy>yrt5be? z>)wPGQge+1lmTN#fr@t2mM%+-A>!mRDQTr0aFQ!%u3_ewJdJck zE2Iq>2$@S~E&kE+!>EWQm?D3+6)r;d{8pmI4@Q_73y@2D^t=Ik)$Nvz4bIDo85Avb z_$D4@#kA}3%#J^zORAS9T)GO9DQ)tDtHOq@YW{!h{r)a~m_YKmfsG^;ARTF2&ku1`Jl|&Q5?bE(XYL@lZ<;h zLb|`ygGYU@+4SUsN4>fu|7pQ3zt>hp&3ukvU{Dv|J1};ZML!;=+uq6>z29pd;-1i4C0!6L1?)%=M?` zAUc1m;_Dswzp10tCGPynQW!Gxe0Vg+Wfx_ySXpxu6isT>x0+R@st-=A**#i1p9s5w zU0pWsU=4OYm<(ehm$AExCcXK`nP2Nqn(x<6f$ z?@&cht_jKb{UIF=NyG&PYT8zWPH)sHhZfP;7*L+1VIuvbThB7^=?c-NY4OC0+}l$l zUd%YjC*_rh0vQ#x9HD%q0%htGHzG-w%>~Ga&A$basq_R^R`8?5B*dS$rB4ZQMMsJ; zzDv)@q$cQkjLN?6ld0oaaY(Q`t`_{7G=(?`I4G2WEKzukg^D_xuk%#%Z#ZU&3SnX^ zvoQP$l0OS0FCpghk*>=5$O=P^&t~+8RRfCBRaJuX|63SWiWkr3E+?xvA$X;R!rXGGe@ z!b8!5Z>4x0r3@ev`AXyg-rx)CJGG%{cIn>&dL~y_x9Ul26ZbvIj{&eGj%bhg-u0|+ zR_y8Utp8Lb5=z>N;p0s*bn8gr&hA|3qiNEgiajGD8R=T{@sR^Gp4s2g&|O3D*X>|R zwq)Lv<^pLqwT#|loLH2kp*f=|@KkA)sA&h09Gh~`22f!Rb*H-nvB{OTc_946BB@ZG zYUh3)r`yqo>M_Mb4cz5g8gN_6jqyQ-HA(JsN(y_ z`31VoviDr}ncZHBGBai%H*cN%uyrz>U7%od$95&B>Y12Xg2k}3zg3ar;b*hnxea2q zqDzUJPM{@W#h{x210MIVt^W-(4k6Aa?7sG;fcBn6bO!PI=|yy7Bwe2@999wQLOx}Wldwgfm;llEfIkSb!k)S=$9jJDw7kL zd=-f!io#jFq`#m=7Emee&~j6Hh5e&J|SCe+tU`SLO zymj(gcF`YNW_mO*L+gnIZem?P=6VFH7u zN2MA%qkT>-Rok>Ql|0-_>?59Bd4@^nld_5d1Q??>*o!_{>+!aNV+2@g zV?C04P*3^;-o6*6r~pQ?XHVIb=RTv}z~CHKpaUo^wbLS4f`roAwhOw=Y@A`L#e6cI zHKtu(zJ|*p{iaY$0e5CQ8=z4gl(Ng7w=g2H)d~Eguxwd7`ez7oT-u~_eIX++6Xi~+ zbxAI9eQ%Pbxj!j|`4J;m;1Nn)Z{urMdI{22gr0D$Hv^vZ??`SQZ38x9xFeYg@u4Ws zfYb1;hCr&ChUpS4>KV2gm5|E?&vol{y7UIa6s-QQ*o^Cu<7kF|oXMA?JpL6kOZ zZd+Jdit$@V+_H^KafY2-V^kliYvI^5@~MOHH1DpfntN7Ty7cubG1SyJGW1GZF8Z`> zLjLaVZ|~kMRZp-0AZ-?!FPvC4u%>FjF(Z9sRia&Xn{CaHvkFNI>K$}gZlaOWor&eR z9X`U(VZAjcB2celzzO_?Ms-x~Aiqu1CXbyUv9Y5F=|P`b5D7P#r%iID8Z4!fA#5@y z(Wpb3u0ao%*ww?Og4fbODcW(49 zCO=N5Z*V>5o$J1Dp!QPDLp4PPGu`v&cyO8^$s5vB0hDfuX|A7&9J1pU&0y#sd@KAc zUpHkb#ffF+U6pUy8-88($fh!#;5@NetsUF44`}R)Z^WkXhyqsf5 zsZb+NTC#j7_7c*c#F)`PV51+2p0Bmgd{0`zEm5KN6u8!!zmr-zHmNqF0bwaHNH{cT{@lSmbKeO|qv z;cA79J=#}6Wqrf}r1{Y+L_`l>oloCzGX=+EN_kY%{jk=nE*@2$%C9v${m3W$X{yEI z^zM2(Ed?h^k{cVBC0*-Z-++J{iIV(oG@A`yB3I%g+xk zdwY*Bak;`TRn(aHp@xvtCvmx&6AdiD0@ z_$q9qbu}#zoyYbA{~k}~_~YTp6ve^u=L`OV2jB31ZT!t@3;1)BRYdu>ScQ0?J`JC! zTZ2cw*~f>z--pLLIJ_fdi^mc~2MOcx54c*0EqTQd{@ld{>CCu=vx8so;Jfi#9Jj** zx!(^D9u7|+Z}C8`809BS_u?1$7k}>KIt>0vDS2~)&*KT^@%i_U@-&EiV08P@!_*-c0C?Zr+YVUKWkAb=&4Zn-+*TGq zg=~jTtw85*uI=x;7HD2&Sk zU|I@Sp_DK1Rj+$nI%pE1Znq}V>tk>0r$gq_< z5q9nBMiIVJKl>scx;ml^U8x%iimpyX@UGO0$d8GPA2eCyr&wKFohH||GT{Cw=?0$mLY=d{n-IAgY@)7QcfG|6Sj?x#eSsIFV-VjIH zp`_6py@J#VRrvWmD@oum`YGzgX%q}MRl*23mudoRbLX=cash~12C;U_a@VF|JaBru z)ALi*qocZoG~p9BS^10#m(R8=J)h5xOuaU{+Wc<&aQE@vcbh?#r0&rP-#`3*ck5v1 z@h*B%UXR0Bo2|#YP$@yt#Nm~sC9@RBY~8`3QISyoBef)_rgT#;!}%P!-9N(II^KVW zxZ_(urLpSjC{Lf^$bwrC-h&*C(NiCJLXOdUI6-o=GSS|j$~PIid}D!*1bd3*Q~(eX zXdF99pEaG{%D3+J#6v5#rv3^Zk(fy+EA*RJQpMiQCKiweaUz=b~cpkAa8f$ndbo>Gqf%xr02S8ixo`A8!r%A_`8GGad008gVNzpx^Ak zLk59iTYO56){~y8)n7*M-b~MrXHN%!a6ZM^2Uc_7RIWd3*^8fuuSMY9artydq|?wV zEnREGS4MCvB~mO>n(#L;5@#qat`h|-O;MX;j-NnyNnan=c_B5oz=XPb@~|U(tYQ|r z%G?|!optOZhS}?(O;HTCd3^M0IC(ibBM6a=^65va;XgdbEnvT+8?vxG*_B3I4>9$_O zK<3NiX<xGc?H`tovKdj zBfaC^D5e8|-MEHFr)Su}IvL|vETA@k7b*-WdRQte*zs&Gs5kOW1p-pv$zORcTq_%) zfaH>(mMcuyvdpN8-Tt*rPQJJPUaTmjAF|)vCUUYk5OwiBNUbuWsyd@^mhkOHtZ;9dP-OHPfFNv9_v_ zC=z1LR3oKWkwc{urDaC&%ck8{ol*xet|vlhex@!w-V6qBfA``R z{`=y^06)*Z_z$4fJusG%vI>1uoV2TRfr>*1eixI(SHLY+2OkBJ#ski#A(cwjZ*=3c zCgT2!^L}PmS^6ao++}$35|-2SeEgEJ<8r0QK`jf)8ygc{m+~%ED~g}H$P;eLYsy#r z$(-8$%RjBqNhu0QJfBi(%wDl#tRCQLxP;*J6GYr!)5}z$h&Vk&!at+@t&8Kx$}YW7 z!?Y>0DOFBJlgRhidtdN|^|DOVCs;=zn*=$0#Wv{atwM~&l@){N5aaOSt$$Xg)Xp)R$V~JZV+((|h7r%Tme1R&+yAZP_-SPNgBYIHrr`1B`3SkIIEC#((kyY&;f}Yr6V?T)oQwWy z2-Y8J1@{+bZYqeg|A?U-XTM%}+g z(aDelAuK~Bh@vQ)K?WhOivWLY1Vh5KRZ3g*FTv*Plo!WIjP3QQc2X*I_^yKc_1||MxvlL}%B^oJ9h*W+rRUrF#+EStt z^_BLDP#QN`$ou->(}?dl!RF#DoTV?wPnu_19GU5hNqw3xCc#jUIlh=&VuF5w26J+7 z*{YAp938j)UF;3BzxkZY*S+~oVw&U)8(4YI5s$+|vF)D2&Xn+UM0BYme}>F-ngixZ zQDFs}<$qGswWwXJwyUi1%T1vZNzg+snH^5;Axg(94SIf>_5EkR)U15&0v;kKANF$V ze(ID7_ylKHSd~8H=;H*0q#rOjYI?58`i;aq`vjTNU^Q+#J5JM+kgsRwjq;(va5#t% z+WYpwB9Y0=hO6edaVL~#zUh8Qe!WVWD9BCLbwu`&c(mu|#$^P{xki8Ub4??zsMQqz zO`~5m)rhz2*|GJ-QnnZ}N>iDwcu6y>MONLF?b_UsoDAgqh?cJGT#ApUMt?##LNA{i zM4oruiYKh-w}JG|M(6W)y}{c1+$F^~58dEmfZ_42DVNyJlCY{gPDUV)6whXUClW89 zVr&%@Z2eXIyI-z+TZzfHc#!-~a{TTH&)uQ3gB0A^(fRm{*E@LL@7IpVo|c`131p>b zC6PD3_61~vyhg1=UKw57-S^@q5aft9Kyb&74)({V9DmHXi|HwJhN*-Ja-9E!wK7gC4@mb3dre_x?xGM3a4` zf&5w>Z)bn!o1I5H2Y)?$^8GiD!a0>Nm_UNzL)*Q_2RN`3j?aYV4o>mK&JUXh`D9IO zFVF?COIaP0wm&d#m1K{n7BdJU=2`KjnxEa@RGarSk^Dni#t*V=twAXuuznhX%Cu4R zSyeQu`6^nbQ#B2(x;6%EsivIW{Xr)j{0qmBYt!r=B~{q@4L7qTBR?iRr_Y4nzn_gN zg9*N>A9<1jKH{1&LB$`n@GDGL?Ip+v@5LXrddV^bsPkG6X%a~oc|ZD~)eB4#ySk>; zg_pGoQ}RcxZs^y<8JXu&I#427`sqSz!bWvoF&)hHWI&H^yS@H$h(z40`29ADoQV#@ zpx_A%9tvUG#Au4bT3oCILn!5wgU}h4D~G4({p6#!VsW50(NWA_$A&kmnOc_e2R${) z1V<`UYt+brE+LjP?%Lc>0osXixgW=bgTHEDT(sB{jSKxyF2Z?-+8u~F!8#X>n@_q6 zF@y?b^4dbo;mkXrf(ze*qd^;=5C5`awZAa1;QYPxmF^NSp`NOGOZPe*Ui5(1|pQVldo@5Sm4F%CE^2h(Lx4cLMBx zqBvYG{V^=oqBv|I3NvQA4JSPlUPuq_Js+{e!Rf`xd<>HzAL^SW4cN{#B<%=E$YM80 zuvl}0tz5oH^8%l>GoI^q(S>RooX{a4@{Xxj&RKXcf`qmDxd>_fX^us(tMXKYXcXO% zZJhK_C4(gm=meh&hbl(7-Vx;y&t<3;?z&);2&^BFjy>tcN3p+>uDTaZ^-IS>*<2P{ zONx?Of*sJby~N(U@G0hM)^BG8?*n|j&#CO`D@OBrqv5{~Q+(Jz>HG5!_iE^dX& z|Ms?IW8~<0iN$x7Ip^W7G~Y08U8kjM$QJE+G^W)gBpQ<~hFMk6scCKp;>a8wZf1p9%Q3tVsWKEsCJi(;!B;B!EZgf-J5s_D3JuOCk=`ga#7Ooyc)`3YYOL;;D zyYdXvm0_2jWC({`eV%Ffm8R-L7PB>{t@P|tP{qvY)U3g~_O#*gC36_|^|oJ?O%0FI zq170GaqsL<$5eY9jTu#EEfHgC?cx)1pbp3C3qIM!oaZ|OG#F<6zJP_RvlXt)ipHlo zV5Kc`gUDjVV)XKU>J`h!@78rz1Yz)c$u&J~lj9y$fMbTm`m^qxAzxY4(c zhKYKhnSM)1V-jE_t4CUv@?4aGf((}&t}t%L#3>hn0~0EnvvX^$X`$W_8O?HIa26nJ zsx~fv<4*%(+^NbB%7h|$m^;ZGELfI+WvdDI3Lz2Iu)vDOQO_0P{qi;HO9c z35PxwFushrmv4v`Z)G|A>xfH8P`ddb_E6&n=0vJCBMovSLS0CQ)ofTvpHG)u3%!*p zuz@LKEUFEe2!7$NgWv*$)rta2>;xHc(~}GC17p_%j*VqOyjO6QigK)h^iv}hTfL$P zH;*jaVJZQrByFch%s#JGUynnFQJQ!NA;HxMbh*S646P!r8#%W!C1fJfI*NLK0aS@Z zOiAlj)(77i``{aGAAEZ%Q4d)8baeWBbe_6sP}wr#`cA&(1?KFdL%az+Xp1PA6v%Sz zq_GM2S%`*|?L-P`r?M9%7yik~hP=XTlf{mFp*`E4UNf!PJ4=Br9BBl}>*L&ME{$!k z;+!1gCA7v*c}Mc8eOwC7OO58s+A*5$qJEN*oNl^C($X3&3|=0AE>t=Oa^ASiNX4eX zPY67$&Q=}n&?Q*d*Y@eN4^jYDEN)%VE3hgYO7Ae4B-&XA&l47 z?MJCNArH#6Q^Q1FMPAvmT6tx2;Ztq>r=DzqdCUIVkKB^PWPadnP`rBsc8)&LL>a$L zf_?C(%Kh>cQ@#0h$$;`O&oy_jVC|CCvSm|R=sb9%rKU?`4HP5=rwqkI&v~Z}Z36`d zXHt_7y@3$VdnF+tD9-BEy(7Z!st2oHV4oVPxd7U|EJn$YIeqa+G7;a-}sKb3qNH+in`Qdb!ABoG*apHhB&{h#C-mbu6WW!tcS{Q^( z8gT325V{K?|Ce0#d%Z7l8ePPVciJs(uzqyti-woNMTv@J5^1zzA%ax*r_pV5LHyqi zwr|L;7Cr()N6f|fl%$OUs-5F^?}RNO>^NYBnADpPd1?NrVd*lsgIS^dBynkdbzm+C zO#M#8W%}m5fnfPIJf=ul(?GvhzF1 zeEHjhjhK%^o0m$#zErQmnv$SQ#BMdQe#?ldn%oE#-Hjn zL&HZ+pQ)RoZ{5?6st578p87iC>9VfZcQTb04ONm;8^U)1TtP@&LJW7nv7!)O4o+}P zg>--JlWr*s2z&Cr0pa-sQXNmtB2C>uVP&H`-viH2vYNZ<0Xg~|WIr8|e2&aPEAfi7 zngkWL^%Wfa;&5nAAs$G*mkdkua9pa}=V$sjh$K$hplOUeFB$5JQ(E7gOegPfO9UJ{ zrqM5&O*15yAT0sIGT9>qtWZ@Q;%>iD=e&PSQWjUiHLtT$WaIj&Ic|EL5o7c5>8OcW zk>aKR>|jsI7J<(=KE}DrU3{9%0AgO!Mk)s}v)3=J#Es!^rF;{SpDK$jxSgOY$%_)L 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%0A4NN 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 z zxY5O)Mfq_H3HDns@PJr&{g37x#x&@XBRM7flzdaeda{KD@oh*;?Oxr#YMUh4It6c8zwJ!L2TzbhauiQv z65rgKSYA3EP3F{bwgNe5pphnY#sr)b{ca6kodFaa4g{yV1jA%5P1g1TCj*Laj~S)O ztJrlim<=j`l}yA+GR$0)K)H9hNn{B5)tz2qu3nE*MwxOgqX7-)TR<#iyey)#vZ~4I z_1^D7k-Nq%b@}zodwp6cXS}Rw)C}?+=S7L5L0yPNetImLC#;2{&OMT$K^&A4vp3>` z5hc78wrPZg`o^M4LAFNAzerg2kV5Dio_nN`rf$NkfR#p~?urcOX8#N#fngH)b6{F< zO;WqoyZ{g>|MZ!cDxYd>v9 zXo&PJ(?%*W?WWL!;w-x>vbk`*1z!^+&^tXs)(rUZLx~>_v60yBjV3|r_8z6%3`%z8 zslq-ZY&`%A_6F$~Se2iY#+;Rkaad>+>|a%rwSDI(r@NBMj#!)@C!CUeW%@Gw8;CJH zb4HWNPh1BfPoFCv?}I}7(R};8g?Ndi1Fs}NH_z^GJl`f-L_Lg%j3D{;XhTA*kJ{%P z*E(3DN&#kH)luL@3C~OFiFD>%#Ykm2H?ehSGyd#8#g~jxszBx7Uv)^UI__ujFhc%H zY11sSfiw&2N4}QQFSa;m((*a!*y)tn?Vzr(Yxl_ygHMZ3CXi`PF?8h;eu-(>ig=<( z#C591;CE#4N#Ev`oS+X-Oz$8C01t_5`>5v~)P0@6&#>X-nFQ38U=Gtgwclhjm5$lS zeYG-E0^7ZaDZwPzA7O-ZS~a+E8q1SN8Z1rVnWL0hOin1tp5H3vTdiCtj7TnjA@fq6 z@MCHWr0(dF+Dk%{Q_vNUhn^l4*%F{O z4c%zDF$8Q)fs<9{J7p*qTcWCP00*=v*{(HFeL&(zAQ?R6)ThoPp&9HUs5efsx4LBq zB(25I1$wJrA|_x>=BZ|39!>E>Y(5l7*>EAPqx=3U+hQgB!6j=audcwv(ZgP^zmPq8 z$g|N4%%>c!I&IVSgPVc`HGIj%lv!oV5k&6o5VcGh3g_|tG4>x!;9A%#V5=`F2i&lD z#Ev`!$bXFlNp6kcUs-lyhD1uU`s0QA*24#nF28#C_~U~|vz^WuDeCHYj6`SHi_bGt zPm%z__33NFoP zKewymfCBIH*A~><2p~3rCo-QTF9R?T80(m&N=nJ$EADkbZlzl=JiO6wh?JXWHfp`W z@)kpU?a96`;2tJnyfZQiH=YM79pTDNo zto&?#Sq2vzd>(_d39&Dha<(VLDS1gI8D*EzDzkXQZ-&P@@))P?m$7y9i}N3c zbTR&WL6}npl;);jz@_0K{r8}4za83*FOJphrQjTiis_4Z(L zZ;~;)tX^78VSkuD&JP)je>oJF6WF!2%V}%+_`zhnUM_Zm>?FO@gOlQHOuepOd3p5a zX!!Ohb2EK;$oG8B=&5sq1C&o!VWli$juRW&*3INnS1TNjR*_X#LT&+a_7)fdjMXNsco-AYOLKyv)h?Y?NVpRX@>yS#=Cn(g_H z910_JIch+>`AyKLOP?;K-lMmE$e4jPc%3#G`XltXJvbO3``0sieO$VI2SV4;`Ye(&HCRDQm5 zuOw0O5GjQr#>I33b^1E?1+NR>AlY{Lo%c`qCUPf9Y%(e4c#jbK&|vP)=!{&+Il0G|{h@IVjm*HA1; zjLO^B$g!Ur3y^ea4+lbn@oQ>-7%>i3V7*44{|VP1K4E#BvqPEY=wKn+9dHLRUbu9r zjaR*GWEz#xsM|1tXa>l@L#IKR1A#(k)?STY^OOfkA{A%o7Z|?8XKp|kAn%*R><^I7 zg+9{kFdgVT0C?WWHrH3$zbv*IS#vYnXs!R;Ty899R~9$%8+mMgX@dA)wlkDyEv~hH z%hp%2#kJqEpPFmS*R#g2$ZoT_nXR`jHD7G3HXC@>Tw7Xwx!hcPmOVwiwe@zk+I-PO z0-UV9p0Pt~s@XujmFz{Mwe%b++q zWou)7vw`lH(d=4tZKZ`?8ZR1a?RoTyXIbNC{Kz(+FRre#t4oV70ey?`WlQTDzqOjr zp0~5->#NHRJbc;!WQ$K%8`>2HwY0j}d~rQnUVO3mjL@~Rb+ppD#9|6v_RDifgGP(} zE#kkWc5{7=!&q8hYq#(dXrf=RkvQP5I$LZ;Q=Q(ojcV56NqPO3N!?&)e+{*@2$2z^6hG=Q1dDTNKS37Z@%*5FvPWcfT2f89;+`_vdd-UGMwbcYM9u^VkZ(2X>nN?%ulZ>-{)?Z|ZvY z?uGuQu7&$Ee)PTFx;cMm+V1ZB7=d|fYOLJ7f9JOE@80y-OzPd97R(>+-Vd`k^&I4C zO^uRVt-BY3@P}z@-Mjt$Esw|Z)C#mUH8$?uyL|y1-n)C}ribvy`CIc-&)NOkKi=~- zr>}MAUg%Hg|0N{^bZN=$5u!CT-vvw|#}F0$72Jt{5Ry1A`X=~B?d+H5bjUv75SfARqyz8&b^S7}*`qdRUu-GGWD zw-c1Xfy(&65XqPhn(82xutwf`_fB4j^vkSI%Jk;i%LZV9HBC21xdNLI*>GN4d)CFm z*C?IXfWB6=^KCR)6cFy|y;cPxGE*5J&I zWo^An^l>?6kvk=jL33!dbEWQEbeK|KFF5P4;uA6v;2wjBfu!;J$OS48I$Tzfpsf#sD@4c&8NAp!uiG<>dxx z{!RtWx4Uk-?v#?eZ6%=;ccG%L|6<*hAzaD`Z;Fb_KFiQ9vnKqBK{SzQ5=@yNOW6z< z=DO|Xiw4zEwqC{tVBwY3rcC9Xn?IKD$+Pt}ipM**%0$mZT{jjtuw7zvWs~uu zxv7i=$q|wM?J|_UT(k9t#M32dVC#m4ZjxO4%bKfr9tW?J|OOl>Z#- z0MfHUDy}YX=BerXa)d7a49XOALK1XW8_%#PVKv!YUz6VMS}m^D{Shw@G4XY`OnhOD zZ?x9Xf=Ja?x6x{0v-dE&TPny%aNJ+ZURP%7ZmBGzP<)2f{+C70(cMxp#tyMGbs-$x zfTV2M%v)QLn7CUi)_%rznsP@N!|{`}T1EpuV>^ruKP2GhdUvhyY`xtC%tYedQW4h# zkFKmVmzosQo7i4sb1sF;7-@BVeFLQ02ICo`%IJlFHhzV6LR$y=EfrsDjrK3=t)C_c z*Si#FKJxynZM;W)+>nOcNfrf+0}s*2&rr{$PKkEj($>^SI#EG~9f0A*UQdToO;x|{ z^muC0GpC~gFo?)1MBA%+FOL;gyiqOQ7QSbVcD@+SeR!AP)+<+84p_9Ev()>FfqaM* zdFz(UP9XW$j;B@F1hDuT(3QP~(TPI2#=oWSWdW^iyexmah%JIt=a;hj%Z*jgD~ss2 zvNEuJ3DKh$d?_ojzQN^_TvW5KWu<7NlCI=SSqVs88l>2ceMPBHmteumR$-XLj_*>L znR@+b_y7BU`~R7}7$8IB_{$ok|HAg@FK3SaGS=w7hA|qpXg{2P+oJy^Y|&zFcZTbE z%c(L=(ippcr?c_;czL+9(Zkijqt4>^1eR&!FMw%A%}t9ZcAjIoG%Poe*BM*wF3jR0 z+OTYmPF8tgfNofFMX}`jf`~4uDh4|OTErPg<5x;TX|jo=C-17-^hFu6QdMvr2M|qa zeQWE>0_qTFJ{;s4EM6jJzYOBcq~AOmAH!a;%dmB4q>q#R4BiZOZUFytiuD^OI3~RD z{SUn#c6WAf-s#`lzIprp-TwW(oA-aXzjx=(_U@e@Z{NFr^Y-4o-8~wtxn?gV`EG8( zA#Du}V_DxA9uI$KnME8;+3_9D{HPrB{t%pR2U8sp@bh3ifPN8@Mae?WJ|IspiXoED z;@FGM@6J`a=e<8&*_Om-scQ&yk3*h;?cl79N(uFotK!MHAU|<43A*KNNWJ%ThMyaZ zqjEzW+>PE2#_+7Pay${mz1DW7X9w%ZB*#3!(!8r}-dY?K++D5q;%L-+&oembG_7H+ zX_b%kw$#i>X@#7Zi`UE)E0z+guNUxHzw~T*EJyCj4UspS;T1Qe9c8e$;8t@v115aV zsm6_HI<&gdie0(-k&RU#Si@`Uzz9ceH$HKW^aJNco{z?8=GnHK^zz8lrh)E2uoYQj zb|d@o5Tryaot^E<6u^MY4?4IiJvwxa78Y6!8svm6eIXBpRA$$sK5u8U`%HMO8~5$& z6&hcL9kdI5i@PLR1`+JsYOMM4zMmzARAVp%TKnYD`w@~VT3`U!#$J?DEYTPZD(UxS z3%z331p!zM!^-K1WRKgxgctP?kVA#bwcuIilW>jS3=p4(th_v_rdzf|gcE#&IvF5_ zIcXS<;7TS3TfPm4zs1$0SyG8*J4WOqxOf|<-De@nvv#pDKiTKzbekGZf;H<}e-bhG zN50>BC4Zv1x~eSS>dUQ|k{VesU8l1Gqc^b-#+=}2xm+9wGqa<5r)qia@U?<$K1~&Z z;h>L9Wq+t#AY>70zAA5idD{9jrP^PQuA|9INj{JIFG~NU+5YF#zbG8NJuHk)bp2c3 z(8Di5isR8rb;Dc6K4%{wg344wOK(^y(-z_MgnPkGIQ6~?Qyx~=aN7z^eOOtJE&eUH zAz3;Y(r3=PQCH91aaICCe#hcGjrFDyxG}~m_oi*_`v|K5KLhB*& zzR`djqChHhqgdh&ZSl7Onk`<2F3~Jf&B=%|5=0uU(k?5aEsU^JoVp9!HP=S~#Pn9B z{unXV&Q#gV%i&9?N#c{W``nO9uZ4F4GzC}j76h%rO|+FT^cNx4P8+H8&RR2dWeb)V z){zBC-088R@dpU_kA`UCvYlryUAsL`!cchlH-9UWhD38zuyP?-0@|DmFG}8PBji-D z*R*jy2YD&$di3POGbC%F&aE#hp@~Vc!MNq_?VPIg&%M#0hXC26FrC}6C#xUAq69~9 zxhHGZOAw71K@7edFNU2oP!8L=#J0LyJ<|mxPMBW3q!2+uc!Fii3Mt*qM1#Msftz^b zMi}COfgejzBMiQv4M^on|BndqnDC0Eozq$S<2LctuEESq~!C_Wgw z0cgAKmliBv!n@s*;igPA;!Y5pE?*PbBm+j1SCBaqF&lG_h=@^r$h*sR-vjxaTGC5H~)Ka2#8CAHkZ;#&S0YCTNrnD`^x);S8o{~?|u`Qb$lLL(0lqQTaGw>xm!x++Ua5bG z9(B!}tY`T_MR@q=ABORLEJ`Ci7fG}; z7+}_>+tUqmJ37BLty+r2qBBvXm(1w7MnaPbVV_!ly9#b2=tgu7IqXMOA!`jJN`V|^ zBjM?KWf}K9h$@q?z8{wIKR#DrM#d)xDCLqSyNJV%m*#SZ6aw zic8JUhJ^@E7Xu2u1o4A(;mL*AN|a&h~zo) zwF+g3s_G)^dwVe2m%PW~iYUbXuJlvUMy|{>u+SBvu?J-f$Qai&TO@5k^5I znLuDN@1&sQAl3b*M-EY%GwBy+ZuhC$N-X-Gd%;0S!h4mbCQ;aFvHy z)S*P@5U!zCr((P~IZ{B_D&G#mxlIeKU@HHf%clR~Rtv6c#m=Ut1Y4SYvvZGPqpIuV z&s&mmr-_MF(vDLHuoI-V(K3O99Po%%NQ9V1K{9Dp z_i8Fu-{6|gquC zr`l8uc4)D%!?)6c0UQ&3D6x%77h(I!@c+Jw zHGY)=C&s6oodgfYc!nl558Ls+v+voLv~S`2RaGCVd-XaA zfyo5T#7JxPp}M+GU0q#0LMVHast-3+wZlPJrPhKj?p&2qcwuQ@G`9J!Ntuk;<~B*A z9hN@7QLHY&_nL(;>AoVPIoTJsc4+RVC`xyiVFi)D<737&%z~Y3A*P{8 z3--x$PwHZC-zGkH^yC=T141a{Z8%$>ueXtvOR-)I2P0g=&Zf88CUb(AO43JNpj*|W zSF!F~G@_dbgs1 z$vG0;Kok!ZxW+Lc+EZ=Cbw8!aC7V?VU8d-}MiE*CoJ^OI00{d9{LE7D5kl{1oM9+hu{S@ZlRQT4QGVzG)Ao$_))phad{x`n{G z+0J)aLJtfC5rl$feu}7ZMvH8V}`h1 zUNjV4Vh*+NMM?i96gMMP1A?Q!1wAJ<>9roi`~<1A9QWJ&)PjyPXKC^K@7CmQ*;4F^ ziA`I}6?~v0G9_>9DK~^c4lK+U#sf{3Z9%U_O;oq=>9s5Gee8l5&RHhAE+W-Rv$=P*zb5R;Gh2XQ+UW>z%YAe`qrP_i%c*zw_1$YE8OjRq)#ulSOLJPyuBces6 za|$?9BOvLcetIskBFaSsvYc|i3I$<~(o)OB1CsS-TDa7~W@_lp!*dBk&Db1~aNcXA zWRv0kNW;tNw|-EWT3tmJ80V5C#C6dmcZv3AsBmc-8m%Roi#6A47_nXBiYoGdOo z_1wvjiWoH4d^jTZHCGAZ(s~S1$tnoGViJP*QxK0_jb5rD&2Q?dwLkUQ)VqyfTV!CB z9U-wmQQOHq8JUN?u=-Y;V0l3fc#*~L7RGtu#()BIQS0uxIUvvp(e{9Aly$;+Ge%J#1gfaG z0#^=t)Qwi)A?#M4p^?kJV_?_g?4@+;ah;8T$IV;ji}v0)q@7WYKJMb&#Cg+8k;9u? zWk&?yWs#%-3p%qbd^(#POeAl3l=KF&Y?zPYhjcSI4)KYM#+4fs7@fP>-Enc!E~Rbx zGS=1drjV~+V>mmO1~in*E^;(0Iar*`p0m?TWwC)`8w%%skbCF;eSJc~l=L=;t{3fo`*r{B(f9X`y5D@=|FU~{blAW9&AqR_?%wO( z9u5v~TUxoj&XJ93nQ_ly1aD#Izl3r z=pQVZ@n%`3=4OT)MDP=oYo6T5RU-!aY>g)xkR5_a9jUm$M~8o1yXQNPw)__zK`>F(Zlfs2b_XpCzJf8C53|?vT+@Dd#|E0 z<>Kz78@DF}BMq>0z#Y!p2hVUH;**WXyH?u$^K?AR*WN-bILWoMFnPBK+t!EzGXmTd zjmta#`TVI|WoRy#49Yxu`kXHKbY;x-o`h@CvD!I8l<9>oGAP}@Pq$IK+P{mm3R{e% z^1lgzfv+|)t)z|mb~~;m(?ETE2Bw(wgq0FV=9BqW&La99C}h&RAEF@^vY>Wts<6=j zMe!zgg)AS%mo~8+zjJg1HqF1j*Z=PBH%H&z>)*+bdSCUw#|=*Ty>GwifBEH|@AIQO zcUg`jYu+;vXwM**XYZd;VkC&S9Z0->cha{qT*+^u9V^3)NV|^gGE3JHjO^t@pyD9g z_m}qfm#pBXCj9#Ua*Xiq9a2+Y-Ki7X*6+-U{LvT(Li2wTC-g;nEZZ>}YB9>mZM=w9 zO4Tb<=0b*`N9adosz^h0YO);b*Y`*Jll|HL(f*tL&UHGL!Q@Bz9BDRuYnXx!9#95x zGn|f?%bwJeds9d^WDcQ->DbonjXw0s&6Bw*SqYnJLSu{oaF({*?WbH zk|syP@!MNalDE6J@813P&i7y4y?6V|@4o)>+wXic$kIlQV5GNkuW0bu+uwh8=gtcK z`yKtWL0|7aev$nbZXJsu4(k4%QQdW}yMC7{*mNK=o`>)0j!NB`)Oh?gb@7VQT>53@GqQXs9*g}d7c8+mbR`w&S26`V;$XP z>z5qZyizfx_U=Fe{Dkyuca@~2&O5M*A?3t8#;sm`*DzIy3L8ivu-{Qc8~Qka$-7K# z+|2Glv);j?K^wTLKE)y!Jz<`HazCPS2S3h%%=7mCcq>;-M(Lk}xpAb(Tc{){ZN_&3{NsWXn!=Khz0I?_ zHHYIa-#fL4WnlgC?c983W}42$9j4nB8n{fNi6RD6e%7mbgyG7zzz1g$gsiMwvW~W4li{Fe2I-dfz47TNc7r14-2tnxs9$<62YL>0 zfHv+NZzZra@Rbgx2i$wqlyi?V$$yST*d@R1TVLl+({AsNOx*arDR)AfyYuef_jlRd zFlPKTi>@~|*DBwXdx&Ac;Yw*M3Cu0f!5zkL2e@LJE?36=Nt7W0UJtt38Ma?{^xoZn zY_BD@Ej`A2+OFWW(##c;>$7Q4NQ=rXPiNFV+9v0=_(#+=%Csba=Vn4czZNJ0ABVBpNJK3^?o_12vxTih(8uld1b^g%%jm+3Xk>i;sIC zAUECtF1n_>u5l#cChor$fH7f(OTxK`h1`z3jE*!+Ast18U>maC5hdA967-=RE7s>j8Hg`mCqONIoUd z1uFf@&4gUGLP-mMR4lie8Qz<^4RV|7+JQ;gKcZ$hZ2h-mu#&#JIGY}iPltUHE7RGS zZf`F%O3#g4w%5QZ4l)*15y*}O#*k$|flg8CeR$>yY~~nTm#l2DG?i^haOy1-Jx9NRgmuECpp_}(gJXx_kxaKtRDCZc7T z2(|#S+1OPqFpMI9>Kf$D<$6IhPQCffIIbIzsM+Uo4miE_r$_g4G79)RE%mZ{Zh9Ujw zuY%r{)el_oqo;C9Mb_|Nwv})#+Xp8Es1$wdOJdn1FPI)9hNY@ZstH+=>W0c6LY^Q> zgTCsI=Sq62k{8*rHabX7SV?u{H#xnI^+FXeccoO;0EJwnQIN zEYx=1osLIz>6;^3>_>=zC>cLBX;DNp9Ls#$CH+;jWrPmt8XLH>wR=Fx?>4q~HV)R! zdN4&%w#6i6MLN`$ZP|Om+FK+f1Wl6Ity*W&EmFN5O$j5{4KiG0RS$^Ia}+F;G~Whb z*_E4pX#dLGCj_7^Fgu=%-?B~#Jz2|3o)@kA0QMg&`0j83JCN>aVTA>MQAYc1#tlPz zg0s`fNK1R$7yT`=TJecUSYw-50ak`M%>|((C)wy2s)Uc)3UeAl6&=)wd8&TyLewwS zEN-d>Z$v`b*(HM5eikkeso@0+MQ+ln&>F!=Wvhf^bI#>n6E;D))}8%^fW)-|mRm=I?lL`Dsv`!nr&NbBFR)fUZOPF_B2ExXLOrQ8iWY?{9&wf8gnDloC%~x{md!VEg6F) z=`Ov2gGbS{pw<6t5nQHZJSfI|Q$g3t3!Wlm+es0uy%*;MQRF1PTD0Kkh@FP`ZioK}x#?5pR!z$?3tpwkQ)@7k8w-DwMT?aWsTE6|U`^PWRg76h0R^)0)`gv^ zb5|+e4i$Zyre#g0mwK(zR7DVedBAn<8!G7KbL#~_Q7#)1Um={S%L=jyA(~rbP%}m7 zDzyexIRjwLr5eMQV6=rU=oYec`|~b|oci)S!J;!I49hjfrtxU8M0RW2`+Qoa3%4(P zW7zvN+mh3Go$KYL|3;#U!<&{Zb>GNVvpX?ZZ;uDVJX^LF+{qB}dt}n_(&YfbRK9v# zm8esSNo{{ex7y z!+uqkpDkKW;hM|0vlQ$VlV!0A%RgA$7XKWGpEH)kG$ zgd@5*#4LsXsLUe95jDBEk?7#aioxh&iyMz_wat(g6gzB!O5295iw5u}K~e{Ii| zukl$RAmA4cUi+1H6qqdG>I=Vfyq%p_KxKU zixH_=Q(7XRqN1rpnS<$;zI@p=n=ZTYZ#eM=Gn44d6*dst7y>@2bHl|gnUTU3)|(7Y zW=Q-iaK+KtI`qh)i_`D=6E+SD{*esTUNq>&;|r*ceJMKg;R6&h$_E({x8Zot~eo9fJa%Ezi#%*$` zvxkn6!W)PVU|j6H^cTLNSs#e@aOx@+cB=DJT*p`m#JMHX9|EzL!(YyXyy70NeNzWBGXQP03&|*9;+ORh<8^`bYEVyzO7NB z6h$Vo@Enzxfx&AA>NTmCN~qJxGO9=<7(BQ@v9IaX9sdk~@d8*8?IjYeX|lz(^7GL! zpH3~MZcaB}pWx{ykf2u-yGTRjk594HE1tiHH{nL-&a`ZPKFz0}fSe-$mY1aPJGud1J;dEmq?!E)K9Y&Fg98XsB(vF=iQ;HMy03)?55Q`h+wf&Orf zBJ!svbh^Bhnq;-|N!&=kb|;@em^uQ9oI*2j)I4S^Ukr=@@Cz}69qy?=B_BBzm{cb6O^ahq64mPuB6yPA22qk+jDgnaY zEDBEHT24m+nkmQgLW-Z~{ zyd(@%d)KhZu?}b}aLiq{qGE+3;^-FB!M2J9v3^2=D(NXK zsGpu>)vIYT3IzzoeF6J)r=U?ZNqn`OE}o`lyF>L8*s!sRDP0-(jj9!sBW8v2(9n_S zE4FOBlh;;`KEc)?vNx9Q3^ttms%ENYeMsG3&3DA#%uZD(orl*;R`(4jI8nQ5UVGw7 zSRr4^759RB6ZmU8iH-I}8%$?yJ0%l~dMl^AG3x~L%3un?O?$I{`bn5;ebQoVwVa}jce8xd4}7Kd>=#u^PmsAC`p-T;5w2QJ4}wO9Ipx-A zIYY&I=}Cg%GwuJ`=c$OXmQxjnL)5d8u92P|c!>V&^P-W|az?f}gHJo<6V^%3ia6!| z>=P4Ws^!!a!!hdFC9IR48a^2Hr?=KaOtqYvUk2|6qjpRaR7p<^(x?nZe|DA$@YHfz zw)20V4kmfRoT%rVblvnsoyhH{D--E&<;slXTMN=CoNo@(rbgpwELLwelUKH$^*x)( zEF!Yyd_Kx?pI8qI+{_N9KK-s)A1>+F+ zmY(>kUS5sDT>xl`ua#LoJ=dj+wCUlL6LUc_u<*`tYUQJtzX^Sx4V$u@nJL>1l zR)SU0jLZ1Y(fD-sXBUkYaVi42#awaVRFrF_ezIJx`q`qC8Y@@RwC_;XV4jMns1lbD zbL9R97r*aLg&(S0FcScg6t3fo{-R^BzL7J8hr*ghaT|J{3+Z9Q{4`Laz8yY8s72% zqelgPp05g~G0H?p{UTpJqI@ZXfZ1!9E;zgXA{CMrh z2k`G)yVlQ?iOlZS0<_4A`HuF;G-GDB#Y+)f`tWtPD8n-Nm@0!lGj z!n3w6vz5-DX~5u0H?s#8U$~HthUo>a5;j3GGdRcq!f^1)W6QiPIe06_AmxTlK@w>( zBZU|Yk}ztr)a#&+j{j9?$HNJ^spdnqrG`iys-M!@8N}-;?q?Rlp_WCy%E;`U0T7ti z>E1efV4dH7yp9u&OFBoUAE9qZJquc!o}yFNpf6QyRUt=Uvk!vyesXP@*M)|X;+>`! zV%(zuKNK(@?0j4{p}uhYvJfqFL1NSKbSMtk##)F_DlVpQuMY$Zu47wvokuxc6nB+~ zg&7ng6FL4S*xBU>UNEmFX_#R7kEc)TMZDZgptR~gF+1B^MH65?MLQ2oYao)Ea~?|9 zjS{Kr-?=@Sn|8bY-3%BOnzM0!GyC5myEUJi^$wo=@a8%H7eN;Lv zQ2wa5K3HjE;7{sf?<2H#1wg~j?;>=FWj$>@lnH5LV4`B~%7R2O1r*BJUxk9ol%^Kd zPbqqab*qDp8n$jh3q4$Xm*^4)wK#Q4gG-WDoUdfc#4)%Ff8d;Z3(lw5H2GTERGt9> zA&e?zZR&QYbeY+TS4te?Z9=p`M#}{!K^7gy9sx2?i1wI-?(g{K1^y?~y#c)qi-eem1b_SWXs z-+#EqE^*2iXl{p|tGATO)e9>{wQj+OBbRw!WzaMi zA^PF1O>3=ndbVmyazf(8t@=iysfMSj5b(+T#fXS=xeW%Mh_ zk!2ibswhL|Zh4WXM@Q3qmUzGM?j-NgK`!d2q>Z3V6Ih-=&M)6E7u1$X6O7UDxripp zsrVqG$w;8Fcwuoy4)-O8LIhrYkewVtFh0;Uo+*~y<&e)u@W=zUerB2AJ}!j3f4}qD zbP0wp?s~d^pUEDWrfz`okc(6l2z6t`5AEnwNGH16G8)%1_I!;FcY`202-1KSiL*ZT zCbSQj1O>87Y#14Mv(go1weTveK#DVdwLx(HTmL^?i=z^> zy2@a+Q>LK*n81YXLUxcV_F;3YM2{19^YYDcIf;HFy%h^n8THeOT`FAU>&B9t{O)vR zqZq;ji#KgmZ=e_T~kx9|uYJ&zv=5^l7QZGEA^32gt6yZzYHeJIJ z%TxJeSQ!bkh(*$_^-r|37feuc1SYqNMj0oC+GFp?jyg8=rq zu>d;KJRGdWpv=SEYTJ)kTm39B_WA7s`XPui^}hv(vZZ9bHsz=qYSin|Ob2a+3bqhV zrqJOV(GQb>zagTeXZ0){`fF#>_oJsa02)Os+`3FzxEWaypgV+>DaiSkr8fK!C<9`{ zQ`7v%Kgc15=$gW!$IM+~zfnvBdO@Z}1Y;a?n-GqRw;y5{u42#5IjY?Ga&8-Fp97HO6@lJQgA zj;_>PX|+-=joPeOE2m;5H8mAOK%4H!*p}BuqcLUV86$&Da5HqL>)yx|M(f#ZfiW$$ z*CktM-OMPk6`*aLLwMy;Ju7NEN78m%`yP^uRBH~gO-O!@9Y`lFvB;(jNk5pd zQaiD0lS%izrfg!ZrnEd9OlLm^Ep6gGTks=L*IibyXrN`5jS`f@gm5D6OD5gV<#RFyjB#>B4Y$k~Yqgr4LK+dzh-XvZaqE zWx`^E0~^zn+rs?xd*MZInhKaUH-nHfBKws>amix<)H~9167%1B>*5vc8J!<7Tn@|b!3Ka`%BpE=y3lSo= zd1C8GJ^$*&ZA_Qm|ubVme6d{NOfJQ zQ#D4P8vV#%LqRUHf^_9cXWlp$)3wPesGTCQ9>Dtj@lAInZE*a6P$xIx)@RI~-z^Y< z884woWkrl(=x~AFfEb3W?YPUh9oIv?L!65bPNqg;It(Nx9iYW@tvf_Cf{p@01m z`9h=QpdL|ZFKL?i63RBwX!C$5Trwn_R{pw+98#|faoHhi(Im@O8~t1=*Q&`ipoCTpuljIM8*=wBHb2? zx5%vIk93%h$fY8MYs)T3hox0amjc=ZzYxo!8|**|`o!t2CVPC`^3BXO##UE}nB%fU z`U)H+;AZHU8N&fEzo0Or%G-Z_k3_=yETK|=3*GL222T}owk+}Dk{aPoN^Kbes z!e$*88!(IMxvRt5c9y#2shhLDUO6^vB5?qwS;bAaE^Xhb5ZGDkJ=4~3GoTBprJGgb zp4Nxs>FFfjJst$NS+;0l^Y!bzKY+bEe2=s`NVw8p?+%CE!=bxpsyVwcNOgxsTEG^a zw{B6h{WJ>4yTn`#`#Prk=vyF&%LBMMsie}eZw5_qVdpsGxorC$wwpt_8 z1$c_?R&6#`*FgIjem>3TfEWitTXaR>?XwlLbKE`2Nq;q9gs4{g8qY`5ygNkdDs4Q@+@PLZT>TkG{8{o5ddjg}T8YSZ@fQL|Zj zlE2F*`}}XkoP*e>D8}jNAV?>HvGiSP%zpXnBFl2BYUGmo>7_9dP7L zRF!02^B5DuWh=zzP9ni@=#k54A~%Y)Zl1UDSO`ittMb3DQ)Fw94B z(b?o=90Mp`48lr}t`^CjZEyVjU}t0Z;OX|Gjcpgxv^kod3?|5fclbU#p3P3C_ix{R zIhY-v9^UGWU*8@LUJZJ;5&pU&({Xz?$@AM^e$)M?-|OG`D*yKI&b{xx&c8dl^W8V! z9ewrHVgIY|?|u8-oqI>$_K)r&0)gTk*2gFBk%sShmM!;gWcTjey?Zm;Lc_Ce_H2AI zenVx}aM=`>nIe}S=KW3Hzr_Iz$kNvxW)d1@R^=ut(78Vz4UTY~-;cyPem~acdhGK{ z=Ps6#4~& z5#(?{iw#52noNbX7rL_AqifWVE^;aRX;to<%&y z%KsJR*C>>YtNRiqKdU=_T z^2wk_@-OIzm6wMwn40hk9aw0PB8|%BnP(tzcY!+Qi?>D0iZR15;RrnOpvTv`Tw* zwI~mPKZvPg$k?foB$ep)y8=u^dnJX_BBoNF*x9nc21q2awCE0RLJ@&^qyC_ZB16vr z0{Bu!)&+oB2GBW?0kNPVg%;v}ucB-jHIxl3U0xI#QGy8IMfPY=8E=c6klP;%Ef{6b z#0){e>ath0h?|1KMG9!=g33B$m@Q4q&4Xy;=q~L}7xMcs4o>D6<}TSTHU~RFoBj2#C>uYG>(aK4 z*@NkH`M&JVA?Kxb8y(B;+x`1bw>SU3xwZD>VC(6l4Yg%Tt;ik_eWQ{Famn?j3r;lY@wv@U(dM_ z0Z<{%+EPF>t_^%Pi$si5i%(MwCowEc(zWFM9>W+L%^r$@iOpb#3^fK-p1-bBP|mVV zO2G(qRAzgXeRD?HGGoU;pWdUBa!fB$xQvJ;CpXcRqBGAaB{-tDiU|+avu3Ru?fQ%BQ~wrS1&T6lMi@>C0N&VjiP=A! zA`d&PGc#O@`y@W}OfD2_+fNg^8=4-IP-4}H5~H!j13qbhd23|ENK17A1=qHDHe_fO zLTuTf4_CfzN8$SAnO%9My5(>IlE}glq_=fIPHGOR3^B|S{uf5(5Q=qjLf@{+SV&PY zg-g~=O`FJ2S9H(P`4+jR$#3YZ>3oWMJg`myH6(X}Hgz46O!`7%>cvn2MKb^ch^qd1XwU>k)X|sbQVRTn(mAIbApW zLyqj!Gt4s1Qb-$IlSc_}O%ogsGZJYRAe@(=1&lQc{8sj!+dXXsI_p%96gT`c1a#TXX~0;@heu zAJh>e!63k&z$4aaJTI<&6Z3Iit;1b#j!k3b@p|s&XSA!yYmYGCNne}tYBYX3$_TR= z2?J5q&V_E&izODBQkYzC5bEHsFJc?aY1X1%78T-6x@fU<`*t=S4c{{mQ}|lpo`s8h z)*XzpE>amB;|h0%4~~xPxI5}&V=%)*WOA^Q_!S0_6Xe4iD&F1qDUht;zZ zXd+lH`~7zjTv}_T<6#QuW>M-Q+C@Hs+pM0hXWEcA=cJ3!*xyPlEljkyHn(=f0|j|x zd{HTrO9hwvx*~UWNsCxN39Q62OT?G1STQ)EL@7qi7OlyLk@6*k0}iZWb%??%qJ(e3 z2u}_5vX6{c5|4zs_ZN6Tt*)f^^wELz9#?8c!?OhmL69(c!{B{1Yt9!)?O=PX>U=>8 zhr4!fO$AY568+Qm=+l+G{YJ>~2y|sYK2!F(6c0I24KqKb2OR_hqPWc3DrmaVK?eq{ z+FB^Yn_f~GP#y<(xdHw|30jskQJn30qt{6srt-7uKOTWK;gg!eU3~9_SR;1;Vr>T9 zz8nk_=B&LagV^uvcCS^T4se*f78raLSk3{9&0@i0@-TAE8tvx>U0q=Lr-G{_2EP$F zcBan-X^mpC8-clCT1$kP$6zdui41B@p9>K=+lBD(^9ElTUG8vM167}hM_(|cGEd?+ zhZjAlYH_J8;gA}%MbadvfGy^@GW+TlW}hsF&`!`S}vYT zSTN<;EsHY)3c@Hk2oXb^#3M++k&`l0{9j0f@mZy+UT0dH%w9k__J_uj= zBGHWx4MYKfz{9LGm1ZbKoHe)0P5|YjxSTQ+?X?kD@yU>Q1{SRrl%#3{CN{;+7mYLz zlqBF5-5Sn!tqNk<3dGsGDm9iAxrTH@ud=LYD_!G&W0^>2i`?ui-u)sva)u}OO8g!Z zwNRK&j!*=_rIz!)Ds3eQ094)s(98)!;4gE2QH2@i7`M02U_@_eIDat;P0sYh&{G?d zw-jklumy|z(@E=ChCWqCfjC%cgy=rnd?dG&=CD+S*caoKC-rJ((?ItMVYBF05~)H) z&}jghdR0b7Z*5*xs_$E?nKX;}c<8PgZwL}KI;9mCRq(nE!Oy0+;od}7C{be(fz3c_ zk~RZ{?8kO<71(j=i+e9j zLa_#OrZ?47tfpp6Kp{Z2e>iTyIgwXZ(-ne9{@T*17|j?*G|b39E9iPV>7Hzku+q2j z!WLB?vWR;>;uHi9oP2PuFlw7V$@U9w?(%kn2Ay-!Tcd%?j+p|&0c4xVk&+U6DJvMl z!q~<#u{LruF*<=ek}g4QPtAml_FhcyQEukg)?~%5nj8_SG!Es~o^M!wQA(PnY+SAs zT(e;rgDcpPBQ&tGI&c@q!3?%Ii=D3bVQzZj_;}qnStA?}_f&O+GG+w>oRgT#9E}E% z30lHGBs_2U*fcjt5}QtHj`Ek-?Culw;Sdn^qgiqeIHpaBAuaW0IH-|xTzW+$#^9*p zC9$2xbUU;NC42~&tSKr=hJ`B z+33ZS>7LYwJbjQwklw%l>)Q6_+SdBU!RD5H-Sxal4bz8}plyzAvIfn>NRXxgsU96$ zfOd&AjA{!$BMs3tUJ02rG_t7>e%QD@|6!=`w=JH}xM#|SdiPgz~#iBpQs7Sd1z z)=~_BtRfmP6yaz}mq3>C52JulsY2gV#uq~w7Yv|GmWU6|#6z+3t`tDs;GT@bTrLptPfjw3U(=37zA$x zi1ni9q5^b_O2dL)v)@%IfY7Sp`#bX zGzCd58;I6qiBee|_gAM645At!V7)7Ra}EMuUti#MdSn$A)+150s%j7McH z_#3aiGXflI00!M=jmGUNbV|v+vj;1wtSu9!*KlVG87_8!7Y>oKGBO>xq|iarHAjDM zf*NPpUxP!Oauk?dGH|gGfa}BVRAr(z=}6cu3-5!u#yy&v4xJh%SD0veIYYd%N`HSt zBA4wPsV{nxn`GG?Gi7WTpT$(!P#qk${8?^R0va_`q|#Q9M;Lo-3M_B3W0gn=N_J)w z4@;c4WY09uYe{mROyzvXP^^3i&L#6dG~U6dxtcaM;MpH!{ltWUJ-kXVcH+^kmovA18hU zA7BrjDT40?2U_K_Z@#fTNSUM6`D1k)n>9N6DLKR1vVrvN{_AbC#svxUUg^(4Uq z#YuR=TUZVcqhfZv#j@jJKP<~w_Wc9N^(XCV4EOKv{?D_GgP%7xp0RG2zlrUQXHVAF zH)5plc&i9LB3mj?9~uz$%nYK`0+f+~mBe2Hw%2NrN~FM`W{o@!*_2+;$Ird|CX$5r z7Qx_?*|RY@se?Yt^9Aheu5Itad-Q1IzZGc(jc$zkt(x4}dQ{q=u$YGQM`Tl{)fRzo zdeV>Fh<*g4y94-TI4d>K5@SoC(53@W*i+~Gp|8vH0ch+eI-_x$m~Ss9In=vsD2k`O zU?tA>^{c3dW{`F*?B3B9)ISUWMCDImJ=@Ios({Ht;#9;9%1&YPsV%D$W>No;US^5w zJB!=8Das;&7fWbN7YZ5yw+uJ77B(d~4aF_&LoX}en0;^m7N^?2Q7zbEPzn;lY{3SJ zFpq&-saMb>wt4&a?8CDbyKPbbEgzn+8yf~j?X*CtQgXMlPo?DaIO%((E7um*v+DGD zsD*4%ZqwPo^-mQMfSI(JW9t@Y<9ztgC>*sbRnLIL(|<`ZwWVYhDQ9EpPPgBG=0PD< zRA6j|BVwPG)#L6|Rg~xzEB^tL*ANLo!jvBNTt@1OI+9W&F@avr)Jq97FHOY5oIs~! zK>}#6E@=)t_OdUsyCE~EotgQqs!r3=3LNTZjy{wu z{0So z!DSf=lo(J`^yxKSrG`raT|{z`N)j@70k)u-vcl+$rk;@_q9tdz&vI2gf9TJ${2c ziWy&sO(K3uZi1T`iFFqFEL4$&gPnb%1jy%u+#OjTM~LubjIcuXzh#5j&7=lEkL3Eu zyM4*PoM(~>p)KyJ^SK|GR#p^jNuRfhHJ0$uNQlqH{Cd+o<4qzl-}?{!X~iKpZ>hDb%2cB zkDjg{Y&?BZ)erS`h~S}DMVUyi=u?#B@*JysWt7&y`s>=0=NktG*mPgTeu_^NUTZB% zH`l%y!fG=g2$lRx;HW?-Xfao@_f@2jTx#WchzOOEfSE}PCVNR1W+p1mfmaPkh+8Hj zO7G0ASH_A*X2hl@ z-!e(LrAZ}1O0abl{=WDkoKah(glWU}!e4+Fn?kno`3&wr<|gUB3{@I{ z8ixr_o0O?BunAeJ;mhDb3a5ksEIv^n*Dv-%XK0f(zo&!5c0ve^hJ?w2Q^I??@THBc zGZmzSyluK^Yg*ua)(>>AugxBB|C-J|FWI|Q3*lwjX~mKXcjt76w0rl??bwcBR$zaX z*>W1%k&KuFM=#u2+=MTb=GU3vz+U zUDOg3XGToK;+c>K!Xb(DEoLj>IC|5>Ois%vKe^O%CwH4L)NJ{Fj^BJKx_J=a&%=(C z4L25VZUBX(4!PIJ;Bp9r+nt;AxFt|&@Yq>L1K4Fihc|hX^9I{Uvhy3Gi)xWWf=tza zpW-$Y7@TlMbSV`cZy6)%0e7`bv6lfGRj&K^Jb#l<-hU2rG=F`IY+bTzF+a#0jtI(^ zj%uiF`jB~w@QD$SJw?8C-cf#w?RiOMHyz_F7d16S#yYl@P1iue+Z<69qa_ZinBus^ z1O-#gV{hiQ-NY`ukBB$k0VfEf2{$w>GvG1oOLcmn;P48Y<)#0~dJ&Xv6 zcJs~E5Xljk1xLt;vd`IS6F=AsY9 z$#QVT4fs(MXDrb#&D^ibk)8i;e?-14Nyc1qw{E0tSUg4anbeu2@CDurNK5`3oKpbsKs z+F_5$z$#P~y(>|QiWfYls1xh@D%8xiKjrp!3+CmXW#!< z>PCatMD2J=ONM5}yBJTaFD5 z-lZ_Tx)mq|Tu4xg?T}nIU7R*T4iRQCx|xC?usetDJTb!V>_r5J#>_||9xeZRD@yrMd zoM+nspt2eV5{aiX2Q&trbHOp^7OZfVASP{6GLzH%Ekkb zhO*71H-#>Qit(Uu%jQi=D-h@fYA-8Dg+V+I;Ra_kywJ3?UP(!D%LjGEhUOB02|^2YoMC7f@ISO=Ze7`}^y(jcrgQ5;k*G3&Z*jhd9$ zIso6lR4nTNj>WRlas&j-N)vyqEEE!Zd~Bd9{+MeQHp8IF z0za-QfGe-O1DDiPDlWw!F1f*|8%Rf(S&|~$mlI@YEjlHcB7x*CYT{v8n2i}uQ&{F4 zc1Y)oi^ox9Bl<-+KO!MUdVM60BHY3@ZZrV3(V^^dn$*Iw#A-dj7jnbdfsFTTBOtBe z>EvM$W#bE5Hn)R{0j*$LV>+W@Gn$XrK3@Cr!O8K-wQKzxdLNz>KEBbL9ngW8=}%OU zPWDbua0DU4rWDwIWUgO-CinY3qj<-B^24=j>?-^mSCC%n8)@mX+D)YUF}J;v+vk_} zxHC1Q$fc}1e2ICV9lxf_YpLkpcyzFm_%d6zjj~53D&E{jX5yHi~*h@*>UP80G|Pl z3P^VyGV{x!PS-)VL7f7erke3k3)0--qJslxnTvy(IE2K+kZxZ^+c&uS2Wf;*bsxD!PtZR<;vzkkTm|D(bMn zUh_Z7<Gj=Ijp4 zF1M~zpKDf#40_${?ybAo^4;&h`{u^|?B3URSMGiDjgu{K81ucx*)CNp6E*oHzA(E7 zmn*Fpmv`YjL%X!!;yBe_I&Cf>DRA040tRrKi;O56W0u+X{c`YzZo&TdDGu4s-ou(4 zvIHv82tuh|GZl28vNt^K(}Gq-i#nwdPsJvbGt|SsPnikf zXDWzqKHNGUQesxz^!}cydJ5wOy6yELs2p`d<#v;bOzq|F*;^CP+8cL=`Lu^dp!>-s z!v`>xK8ry!y6YmTL}RZAU@Z+54wkl~sgNoxzRc0i*Vr4Qtve2PVS-hZR+89@%&IGJHz zEfqSi{Tt#@&sbO})1A1e`UMuv>iHWy-MdStFYl;4QNnHXNXdG!lf~(*7{%9VgomXgQrPD|4SKN|(`vO*IY9-67G*p4h50&@?-Ybc#>9foD z%^sRTg!K!Gp5q@_c3>y#gUlgyt3DmZg)0_E5gka^DbLu+9Egnd;VTH!fUZ$SSeN$#fC#T{4f8_`_Y_fxxBP#PBr5gP;!nn>qmDb7%1=>EZuS0VxTN=3?Q9Jx3#x zo)k3vAwT~o#w_HGL; zh)AAu=nDw#!tN>6PlP3g4HQxMscH^!L+QXQ>6eWJDwD(O#{QMX;0mH$USbQ%n%+~gqs8|Ag3M_M!7(iJf)QF`Bzx&A zi6iEf&Pk)w2wyTf%a%j5$|D#cEVL=b!B9r>a&=EcVjT@ofdue?Y=9npNtjqvb5~`> zKq%9TR8|b(LtB{k##_mY@^dzJbYkWaI0S+p3o$u;())y-Y^aPJg&2gDtpMOd5k0nw zq?do0fwFK})M#+bBJ4hbkd@oN!Xg$z7_pcr1>vi?AuKtW+IdwC9?$Z>$h-vcV2;@! z?))n$F~MY{zNBn-m*Rgx{7#lHx!}d6ThpnCH;kY*|K7>W|5-Nh79S7ux zqf3>eiik|HMdCN7hj{tJHQ6EA;efs8Be+qz@aWi$60_=-of1Pjzie#n?f}z!OZ)q{ zw`Vn@zc?N};vbUVXlY`8Opxqo2^qOj?E3zUejJ$}NA%;3`SFH+|@sP zubVd}T_jfH35P7Se^ExsJ2T-)KI6#i{rzP`Tq6Q|GCO*czxaLc-G9H>yR-6rcjahp zVN_&XkaOJBeI`1|Sp{)c5%;0uIkf8?0#c~Yf zl0?T6fFYEmnRbsVr~Mq3ws|wMSSQp0o@hz(GUuRSuoG*|rFTp0UDA*KyTD9T({$Q9 zo-ET2-3?qCPqI%FI#}k0<`=3~)BS0(FM`sZFtoV4m&OJ4;XNZ|f;@F9HH3`X3Ghl` zj?cyz>F)UX?C862&~8Qvsw#XJuqMiZg^aFAmtJ5FOj`n)a^PM%(Qx<6dyoxZf7M7f z#HeJ?4z>+Sg#c423XrGt&bx21-1ra}4+^UtYRAujpVYXGszwk~jLue9vu|#|n7Z?> zhxPj{gpz{P`ORPP>`OF2@4ma!pt~b{Du8zV-G%p;8qK2)36w1A^=uH`C6JoI^qs(T zRD|j7y-J`K0X1SWHzgH$_I&s8%6A-Yd_sJfiMivJ%J-3EwV%tY*?62meZ4f!OV7*K z|L_0#|E>#pEZlm0LJ3+UThUsS(5{chJyEdxeD+-ajqEyJQXia*PvYlD12>sP4^4DH zV1U}Fyr?Kd39Vp4V^vHNYeWX8{NgQeiu(PLf%|}_u!*R)dR7a2;WNtoHx(?q$Q7Eg zXg>(24sqPDSPtvyxa73^Mx-wt2C%LK*EWNP4vL^mUk%^|mm}TeE8yzE+5dkapz!~F zy0yFZ==*oMf~iF+3Y&cIbH_{bmZ-2K02O*M!2&2_h8oH(kLJVC#JW7ZvR!GRXn!(@=GaA37@_DzFE3D>JuLADA!0+I&P z#Q3e+{YVpp#5gK!NqMs*loS@3gmbU2I^;E?GnCGNERbx+6lkS})O7++p^vp4gLAH|)xRTUaah{iO8U1?Dub|bcibdm;3|OOaTS)@OsyIz1~xyruDsrmGOk%`5yW$6 zyKo$!=@6?AL2E&O+R**jn$=6Ra7JuLvbh%5BigLp2uqHyD3)wbRg*E8t{23Ihz_G4 zS)!1m(&d*Vv z;)n15fiUj>1%1^W{&tLm`5eH`v|WzGm>v~)Oet0=X|kjo>~O&`KFf_b4YXP_|BdzU zG!rA-+3A(W2>DJ=U+1jJ++2hc@n$@bScnhO66l$injsUY(It^D!8}YNGQ++#;t;Dw zjwj={8**bxbUg+UT?JQR*>~MUH+Ds#M+<< z!SVoVC9F4gl-y}~gCon7}?$6k~vEPBJ9ki8iES zihdR`Jy-%ApTI~RtqfkDoZ_^LT|q?)oY~|(>~qIwG8>I$vZ7ZW6K-HkF_z}C5Eu=`#U+LXsmO z-QhrlQh{1-Ul7*H4U2fhwJVUIqd)>FY&)~TG-uOXwH68gf>-o8ZloOYiK&9cm_%NO z9AdUdnkKVq@M-4_xm3wkEi0^Q(N<)PH*{KbLnxvB#TU*-YKpXuaW|&vi;`qB0j1b2 z=-AJT8F#(+tH9;yDrsgX;Fu&IG? z^q3Ba-s;zWsu^u4%8=9ZjYzqTQ6KAVcn@~RMzrj*SFVN(3d06_xRnU!iVgh5H$!RR zt!m>)PJ<`$d=A3Llkw|wgfRf6g@pl+(cA6>uJhgF9I%!m4q1}KV+&N-XlmtPl%Q%S zAT zd`~IpqPT3DBkcc_c0fFXv{cv)!i^j3`FF{Fyf}!F%mwx6+b)aa13bLol7%QQoAP%j zd|Mjxn23IJ{T?OhRqxn{*q~oo z=PK$2u*)pW!8ELR~%VzM?#9_aWPHA%v0T5`U$6f3eg%+QrmFHey;WQ&Mjf)Xh z=@P-UFFebeuV3SICysg!-#_F`IULME z4K5L@7ipN=Wzmn*4C84Oal;42T@feg>FT<`B~NTeA2Bw8dGYBL=p%-K>KMB&kx5vj z9hISv*aD*imNKAc_QN@lit|{me60H}1x=;G^#EC*)uK*bwkP5vbxQQ|67d@4S3Fl5 z*4B$`$52jCt1_8HDakjHwTXJi*J8x+6qb8LR5k=P5bZv$zho{(&YFKNN4C+KJV-VSx9tngRQWpi^pwj4d$Pjen$W4e^=o2~4Mtp4|qf=N!IdN{g=XO(KO{t$l0FDM5r$c`6S>nEq~6M^ zUe3@vy(1?z7y)Hf_@%BRW-ps4E34raIsvyFNbRlXPoAtje6msS_jqHQ{R51aEyT`o zavcM^@@*&2CZ*a~n~h%&da#&{4dswSB-je{=Ubakw+e7mGpT-`kFZ{|-O?fus8H}z zH5o%I7&f0vPoItrdTxAL*%eiF!l|50UHcxyjdflXC0#BJrb~^rk{X*HPnm9tfG0+CgO4IJ zimKlG4;2$xUTrmf<(gL@0{9-Kma!TrV5)r{O1J{5=DL`HbNV>^$o7cF)-rGTrWhV^l8Q1jL4mTK8I82;NkY#`p+A?O~e_n%KCF{GU>j5I+1;uwO%iu zQpP(*JxS_>WD9s|;rv76_v{&9qLvVL|FOAq&{S7d^E&*DYIz9ZK=PT4&t=-zQg*6Z z@kR6$z+Shm`;VT*PC?O^Esl*9puH1D3Pjt~z61_29_GC+On+MIKtWGukMmjY*sT-_ z992t4n~&gM-F&>cv0dP#NTjqNqRl>B%!8vrK5?W}#7isU`im1cb=39f>2vrD4%VMO zDP4gZG)G(Y9?gVB`ZPkf6rD$qt!@1sfL6&dYTFIGlqxI)TzWA5$L#gcn>g~@in)kw zZB5sQ4=^ZVg96+x*I*Ot+hu zX+T7BahDXFO4kPv09B)lx@Vi_??^rkZ->QmTAk>jo{PlP9Yj!CB(>Ioy3O>g6`#&w zDA(FZ7LJl}l}|qJJSPZ$ULYIT9|UU&oO9vdgKBqiKxm-Sl~uat0r_T}cbA*rLCQ{6 z;P>zU3=hV^+V=L^|A-rkXnQ|d=*i{|@{(6KwDolBVB?o(yZ_UyNnczVUy|$AC_@eh zF_;}aBaZ6?J5$K|^X(`9<76g<=W5MRcaW%ztDO)KgmO%V1-7hCVvbo7JU#pu+^0MR zRvILTk7~=TCf3dLl0Fd$$>ND@*r0VIYs?=RL0ON1Ju98eqq!QgKw=CH#n9PTsEsjD zlwMAIogIo$=af!(BmLXh8u24acIY~*w0|1)=6fodcg@XSZ81CLZ-hepPH!d!eafP) ztWz6`=jS7++-BQLWCfE3t$fvfG>eVY`L=l@5%u7CwE!O1&j?x3BN=EE{@`tVm!(uU z6S@5Tq=H!^>Ew54y@eTJVP%!&l$Cu})O*a6RA3~!irDnVDpT&EBn89^8wv*S-&keQ zGAAXD|5*5?@p~N8uSm|fSZFb(hzxkS?q{df+R6!pMjE(*?2pFNQ08M4kMsgA}Mi>PeZ-jk0Zoxst>II^P@b9!p%uRYeS zyY)X6@kSfhPF%Hny2adySUgj=7dZV)hrxEuAD8zk!$ua%f*NCs=0x509Q)>%MH1G` z#+ewznI4ykFZH}FiYAynp>gb1{i5grQlHlP1ZFb@X%{t>%FkQt${a$%>X$epL$?OS z!H5-}M6>IUTU?6U{<=k6_ zA$CE9-h^~D=j?dkZV!+%f}eJPvhlIF(dENw9!{V&b`o=#GPD%qd4^W3Lyjv)Cio%f z#24E$z8dPE+dhjWKoG1mkFK_9MbNN>{A}UR0)>Fv*-cEOW=Y}jV8`9d4`c6Qi$rVwsN=4JMb>>MHZ`W14No5^fL&xfVN;j)H&%6mrPKD*~wGMx18(Yi|L zS7doFRttd=27R$%rtF|&?8)N<7b%G{7j=0!h-4ipgS*yfkqE3139)aiegueo#sC2P z(vP>7kTSfZhjc4jT3zx0(jhz)-pRX@-m!DcuRv$wK-sc+tJIRs72_tg&Jl@l^TH$q zW^gT15`;mUi2xC&D6L@=o_{eD1f^PnfE%1jO{jn}vBAbcd-hmdO``@YWcC!0Cs~-1 zcfZ+*D_ZcL`T~1CCMI9ZHkCT5-RgvrjfH5>>}u6r3?a%obaM$YW*|9DZ&pmP68Yd% zi6g0MeV!l(Mb0h+j(FDsv9gMljXSDPey~E(xr(1_+Y%o{&`r^8=Lk5VVYAOwxm%I= zYcinil){U_^zmRarBu*S5&`R>wFN-E4s*4ufSX$?A~M{9O&3F2GptUAG!cu`LuH-=DuAoZ9aa_Z&@1}vb@Wv2(Ot7{ ze)e9di@kY`qNsUo@)90$B)v96QnOF(x`EctPZGbL@7bpZk_f!x3Jx)^EZGBmJsv$8 z1t1G!&o(x-45w4$#~en^@-nqyYC&4uK{CRa9&#g3Oo~LjSTOREVU?%Sfl6!TrKCcV6);A75H=`-Zg;`2W?S(Q)TZS|it$uzl>cnU* zssFb5%qIczf`fw+Gq+NZpv)#D%tI6w91|_em&?k z$VZVTDG#5OGhl8{{y*9=IW%zf-xnZ$9>EDn+qDB@^@b_3kpDmLqsNhETZ ze-e_{(-9P}5`Jb1ixPl$oy(F%+e82l=;A&;y}V0;Y15qFzHy%nQqq1MhUXD(s+kN< z=)9Q`CFz5!TsTe~F_+WZ0ak>7GzQLGlXQr?B8?FX3kp<36-Prl0Hu8CQ*E`WC7Gw! z&M7WxnLMO~C)D3?{MP>>fPKjZ95z0}Jz^EckRknU;#ge-N40CX728iwF~EdFKNzY} zon>^~s>7cWo%Qph?&*+B$-17BM;m?ha84q)VzMu{82X+!2&TAVf|b+3abY_;qiF=1 z5Hw=Oi+4o&NRu!qWqHYRN;bniApKh&uB7tbBOd6F^4n{?Sa;KW5=w>K}8sw}En7}tG!l;oylc^cLEEb?^zQIxxc6Dk8R@+i~MYul$<(+S^`;&=x#*^R({*GH}i8TDE4iWRtO@gs}h`w zT+pZo9zUFPj1_>fFx_I6RuC0>XYYln;Od0|i{`O0Sd&qUZVXmn&tbBbE>!IW_JT!!t;pKmc)WpxpX(dSmyE`Kr45b#fYRJH7k}*Rd9=B%nrdaXas6caIZ&3^ z-&<{*8l<`%^wny}b?ptC^lCMRB)wh*2A{Ims4EA<4Ug8&#s)HNJW=Rt!-RIJT1~{T zd&G~X2nI%ppK<&M#>g-2V9uL~x4nIKMlL2Sd@`nOMfEO}Bwh=KlaEQ6=38|+7lWQ_ z$*r(rjzNf|PemMJ3tp>QgitfV80waKJcLVkLW%+@gJIN8MYHTO0gvxO=~^<^n){OB z@a$)Ll|ZDi`Bg9da$Ew2uM^${7r0h$g_ki-ohqr!3)1KqF9F_;K9uJ@W>RX*GHO5| zMep8naGI6vvk18svgTo0wdr4MlMa84c)B`#irTavJ9fR`H=AyDl~2p=h0~$!pZ*4u z*=T$XWR~tA8YJY&Gg1hAO1C`0*13*3=WALOg###J9{B zLUki@VMD5U&Jb!LxfGxm`jhI0*|U&4RSl5D@e^7qK6Wr=e|%QAC={ix&blErGAHkG#RDSKaVAo*VRYjXb#O3rvsbX}bRq1-PkTzQ+mON7H#L8jr>aa*yo9w|>lwyUD7@~F)i=H;T?*=8$exPI4 zu$A~QN0B7$zOkjuMXgyKF;tQ|$-52$(;nuca3obWVH3uYcE!}?Tl929P145!P`v?? z@}m|TWA%}SGfE7(uC^m-9MMKQUk}&N1=1NG9pOq9HWPX2#FD_eb|N;HK{p<@_@W~~ zisKFtSt>wm-%?s8FHqm{c3Lq)b;peFqL%DZ8~%;%L6k1ENBkBn6!;I zZ&+d)L#n1$5|PhgH^Lo-P(ME%I5hRTWEz@-m!#c~a|fXNah?$bSH0S7PDvvVLkk&X zmc+AROrQjTV<{j#q_UD5ofRF*eWRq&Yhvn?V#vABYBGgi6M>b%O| zM=J@BpP%#hWduE*C!EWL_IQ#Y)^m{7&{h;_&sE=aho|B(uU!hcZYmcn&hTomD^;RQ zEg>uua%m-FaD}f7ZX@sHh1i>IQMgFtkRb(IgSCA-%&=;4%rAI^2z z7W((pO->?aEW=b!#4;tVndB$KZZBV6I#@!&8~o?kSBp;Gw!lS}(OT4%EhL-ajmlO- z+S%k=lK%Pp>F&m(gPq-N{4V4gkrr8GlwJ{@GWd-6E#l>$r{h_kx=Wnsu$p#+UZ3Mm z_a1IxLAJS5^HpA0iJr_Y1kn_7K_wixzE>kBnuJoDvvkmoEIi9CgZZ3Ql?3@_c75r3 zOaPJTX1$mTAO{oPbwv(VmioE6e?LIZry_@?>o_eQS{SX!AzsmkqN_ywS94VejgwB* z_Kpg1^!5En+UR0qh&W3W($wn?gR6!LwV8qoR*G|II&%RzBiq}fy46o+X*Zm`nuB~z zPe3HsgJMP+hm`gWSSnQH@4%hUZ9BBJiB-Uw;8s$yww)9 zqe@PW=TL|GYCe}WbLeIABWT0s){LlOn`MtF2m&*~wTqGk$cMBe=}J7vJ;Hv@9pTJJ zfqr_UmHj!02g@s$nZ!wOT?BdSAlfq$wQ4G*=$c`jRZzGyplFPp{U8vXzT=O*oe?3; z>}M!lNYdSlXO{Jhg@RL8wM5RG1m7$|QTzvcbrk}6!79%4*wT!*Ff*G=Fqxe}waJsR zI2NPkQf%hzWtO9MS6)SOEW&e33OJI}YNS6WU9irjr~#{0776#O(=;{mJ952>hKZm~ zaLL@pi^71NoVmTJ4Gotd&&ax6-Fi=cf%E2mk~uN&EI4K>w;JIy{``|$w+v94X~=e=Qf zl4rDgG3d<>X4og1{&W|^pnQna6KrN=a2V|1o>`N|N5PH-<< z-rpsoG0_Ln$mr$ov@$J#7t}2oQ@UoX@&(Y7=q8i{TnK@wo}Bh(OskaLSJ&h&Z{kYi zS@@iW5k3}lm}ddlQucui6K4W6I=FpUDzX9mpwN#oWO&scTRL)Ty#OuQJ%xuddReIP z&YUhm0LHcaJQXX+P*n|03aWT8Qrk)4VF9$DghfySZH0<@Ox6O7pZQ9Ne?cnR3rF9 zLS1Id2dIErzQ^$>8 z9T8fWsUNUe<4!yy)b$~FY}0|}o6^=dw7h6Mgkatqj3Ma7&xny)mDmcpYC9)HXN)qE zeU;tlnWtL8#K%q&&4gC)zM=4_QZnn1X#km~ECjPRa8nEcui%aP&VG+y7|m~Al$Z|6 zm=haiS^6f{mJlFS!csqhWk(zBgu=jN-j037%XG@__{N^uc{j&`tJ8KY!w&v@WdX0F)Tcv3Co(2aYP!uv{Te1MVH<3cZl>3>&L@!cgDLfP(xNhsd!4U4Qe+= z2_j)H`qm0vrO}|=HHibaky*5jFCJl=J{Gtn1oaFkW2up3(KdI+J$kxM0jL`XYg=1S zch`0|;jJlgr(Q0qv~t$bsmKN<&rl>(l=Pvj#!S6&p46M#!-!V0f$O$xB7|j1=RXw| z+=|Oma28|~@h*M*%`lbwPS3~!^I0A2)?U(4OS&&1_hi{t^3tvw8{pIB>`8S(CMm+d zLs>!N^b(7H(Ps{R;A*zpl%%EtZKSm^5)xv-t-A~^8xb~j9}aYmLAvZ4cA$FEDU%qY zSBTTA_i_SGSxTwWG!6%OC0&Ztcy286L~OfA=n!B=Q)PxStB>TuTsIeYZ)Pjxz^4ZE zC&YR9%ke^rUX&;(H55|_YC~g1i{PJ?X9)!H#HZ{M#e$qyy7rR#lyt$xMWM{D>>=9l zEZBfGl>-?&CtI8ie<__MSZf51oP%g3($y|jOb#l)&*BWI>D$4qcg$N?#$TbYZ%HZ> zx(GL0qP4}+{Q`p!vn&YbyXb+fghsfwTq@A<*|PHm?{OEYt>=Z0{LJSI-WGb87drM? zlz``?Tn}4GvFGoD_A6Nw~zJFgi89 zb^Fx*4avtot(gdW32-nCwbW*7CB?1nIXwkSpD&dUP}5#8>9)i2ssX!T3v1`q0C$`A z|1q8n{uj{J9sYJanB_YZ+pu}GHhK>)8c}8OLP`t1{hP?PU|-SSG}h_O*=Oq~07xuY zMd*A#)!-!#24^gdvV1ZbPl*3;Rpv3>hYO2w(9hm>rvwp6K$A;{V2nNuDc#OS37w}= zQi8`~;RR^p$2n{SRwl{@f#@yBz{Z+71aqMv@`+)ePp}b42}7-xX;XRPV#*2!)=<5L zIoQfHoX6nhUf6pv-h4SPV@qE+CgwrqQgN4j5(plibZ1~)!-O_gWh9X~=BF|q3ab-V z?${}waF;~>@eTnbU?QE=tUH;JccRQl7te(ky(DUVX2TTSbr2xMgDNP9!m$mKKvnr_ zD5lyPSCPD#JJ$>;J3oL#fUtt!51S!%mP%|)`YOJLC;5=CnxzeP)9L->Zes0$5zA~e zMfN*yzZg^r1ZuNs7mkh$_u(Fo`x(CBdhC-ib{r8#L)R+zaJ4#qV2O2{g+$ps0(oMg zgqy{nQg)yIys>oajp>rq{EHX*-$rFp#)=t&naku>S^{KzbP@4&Now5jry+`8cZa(I&fDXJkzPdTLbA zZYX-=$gJd;+f#a+nrMU46@jtPd%a~bNMQUOf zYO_q3b-&;U-d)??J$Ql*Og&|h1=66Mjjczv6=yrB9b~bsRI{EK!x2S66?2b>^J&{5 zX;Xptjy?^?WZSWWg2l(JJw18?|Iv0n%-_Jz#JV`x_44DhHW5*&u>Z$v3yz(8GJZMe zH94n%$*+i~D`7gd3E#f5*H`W8x}|MRHFGJk)sr=)Y4a?RDXgLvi+O#r!j|EJDy6*;mnPmYMOZ-uQGB9~_xb3{TVqOhy|@ z61|baY!!#e*v6CD3hyobO2Mdvl4smsDiv!QiyqoU4JpiJ9b%sv1hhhfZKW4<{Vd=9u0^JSzgf<_`nf;B9 z_N1H9F`#QB_}#j*0cN)e2*t3vhP5Jn(4-cbxDWH$+Z^Y7x-X{>^Wk{(a=JTCVa-?x z7ZJKzZCyA5m0e$6g(*Z0}Q*N*88eF_>*=8BW|36CG_!t`l@bWg-F?6n>Uic~d3&xFJbm8rO_x3MuE@ zQws!|T4vO_UU8fPzLHTdH!J0U7@+fr9?1E-%o~k7wv|;jGIdRB&^c=lHQBi1>c9V< zRo14(g6Y>>Wvr_goFEoG^!JS9rJJJfLRKc;G2!KIM_IevWLPT)Oo>M6oubt`%OX4Nrr`U!7U^B^tC_L@AZO%;SX9Q`jNt z<2Je%d;T~+r*yb=1}GC?xg+-<{*q6p-IoaJN6UFd*oHD734EvJ;jwtzonWJU_c-4e z^<#pv{?R#r_SWz6UZX)160K9XxHa(tgF}G%9W@X?BZ~o3+<|P0O%(%$9ZRR|*E%^q zAxm#%@cQHwnQWq5E6$CmY}jfyLn;CzxujSp-cGD5TIp)DI@nz+rsuy{q19&c^s)dZ zty>h7(~TD+o?Ket$?ZRXdQ2HHkVc%)YK&{9JoJnn&@ow}aK0-!$Ka zo7FLgXMr~8H(@S*43@_P71F4ahR#=8+$wg0D%ckWo?RUS)pZUMVt ze3)~;7b9N8c5iJn7q#143y5rA+f7+P$z) zUo!(ONL^D~3F@(YtCtKef{!oU43=Krn-^`n>6K0N3W!s-yQn=D5)J&QvAtdaT4M;j z3hqq1Z}O8d@t)n=@L~$lYJfEi*P}>5cruY<>rFm+54n#>yhH3Bz2y)>3AE?HKZL5x z-kbP0dMCm~1)RIpa#KuXaJP9+Oq~h+4zL;|2AKORg0ZO%3}u9XDbNW?2ZWW zgW1xQ=LcL!5kb`XxaZ^|HAKWV57HtE)}&RyC-sx?BzY>cfEW{C4yv~;{KXS&%otRJ zKF-*xyg^XPqIAFjVbT#>Mn~8i%Bemt;y|dpv(Gl~O4kA$Vl@2KtQA)(Wr+&E3%v=g z-OPH&dG8hCNxMX9R4Je?sX>p4#k+<8Gl=$^A|(*R9?&M;pgcYa+7NNr&^2w?3u}Og zK=tw<=DZZ8I7Cdw!{K4K_bRs8X?ALf8so>wntbwhfPfV(D}fE7a^TOnoU_AIEEb7r zNuKt7aDow$0ZJTjmGmQuONZG)h&{?@oWgS}e>>zX1C;CN`u^y;moJ`f81;?;Vl+7@ z%1~rACr8}C%;f>QT2;U(Vd$YT=4X1nfwoC^+l$q>tLxeR%-x|T?WC=Ur{*e472U8# zLF{T7GUqm<#G>=$eQ;A~@p5HRNVJ3}J&_kz7KJ}}*w~_|6M3aZ>YvF9iLISylf0Mr z^Zvv4(cw=H6hkm-w25I=vJpiT94K-vqj@S>*CT92i6c+!wlOc^?2|cFUMaXv=GIye z1cB^HM4k%vWhPt|7G(O%VDk=z-Xd2H^1wG#hTE{E#GboqFtKY+s{k26qN)|>$?f_o zfCwmu#WHh;)H9GG5o+OT zwJ0P~Bojvnm0a&irMUcRwdj${-)f2aYPCo%x5cg&y@`e!wRt@#2AGJGWO~?LY*;SJ zr7YWEh4mkYAvo@-+#htMVjlBH6t&@*-Z1kSMX_mj_BK%ts96IIB+_eJDGdP zjceBq_6fmpe#7hy$5RB_tdLl$pxIzPYwFYvXaN1H2ysfi(K zFsiooD@TaNo--_#C^x5@9L%(kvEr~={eY?qvHYnnLeeK)qH5^Bb|(uNqo}?5Vb+%8 zk=B-?!8R<^9hR4@!pwF)JDt$sJW;;JOi+$`Z-SL^`Q6q3Hqr5=aH+p5I9aI;}hIv_&x!JwR21f zNQG_+*tpo+$zayRY^v|rD&&R$#Kr3X5gWB0jG$Z{7Q(`HAg~2o4}mUL2S8A^tp6$k zduHHS2zg1it_tEZlU7@f@mgDo247mJYS6!MRs^vOWn`ZTfT zrf%pXmKiJ-zhRe%0B|jN=ZRF8e?QJ;YBe?q8WaQ#HY+t4Ap~VmrM(?pls8DDF0=7A zBGY5(Z?+u@&F0XZxv*7fL|8>=L|T)wZkUyY+l^E;b+*CcynelSs4V1$moC+AT-3(d z24v6O5F1yFOhiR>8J4%{B2}ZJv@D#gB^DTSQKKCXX51$KsT)>x(MF(ea&HSAfZSDC z0lQ%-DYr5>S}C~@A!0#azU+zuTY=}i77SIY0T5B?IuMAYY9a828UPR$F6+N)(%1N+ z^M%ee>$vf01IvT2+p8`qtV&w5LAi?ds&KG_8~mQ0&K83N_BU6joMc+%Da`Y+;cAzKpS?pk(eOm&20=y6` zw=-E9g}ks+`}QlMzvxg8L4L{up05nW_%tkG@{O?23WQ!8*#i`C=W^GSf5v&EG2<; zCg~ybuM)7^JiJ3Bz5KC&5DVn02$;%a?Y6S5Go2&A;s0mv-PhYVu6)t|`4l}Gei4;O z@+C8wiJU~HNJ!!~MKT0v$F_8^L7+(@1_1^QN>-xm_c#x9-s}9r*YtW)^9JDgT z^5oU-Y42$8ve)nRYpZ}G3Z1NqSv`HCe+CQU<|K=)eMV9OVrfYlVeRJ@ta1KXTukTK zg!eC!si!-`u9$CGUN7F#T^WM>&v7?vEdwyfnuQEPG$S?BI3$4~va%GKvBXbej`(Sm z0LSfhJ;|pUMr%+d{2R%vdGaLSGh^Ly3v!rX=D=}XH#U;Cz*0YjSizj@SOO{PJ9PWI ztGpHJ6vo^w)`sg_4Bagz(nh~-eLrQL(zYy^GKD{^9-~jNI)dv|NRL-`d_9C68%hG1F~KML#7$_W#EvW9Z^6nJ~RyG|iw zE2kvu7;b1l)D>e&NbF)xfi25Fa75WJj_pQ@^!?o4tzc2Hw}S=Bmo~);MkyFO;UGA9 zH6Z(yduOMI-wvOh?(Tin8-(aYVLS`MK-Qc^r_T8Z<@P%NSkrJzy~Zu+TRHBzHL zKocu&GOs_n+-7J`tu+zrGGSq)0x$+QcM^*Y%{|>?p#S^Z4Qd zPyEz%6~ESYZgU7Bl1U&3nqS8-{5`3C@UP{H*+A~&|PBiK{cv#R^B`mQR$>TNG zA|xF*5mx%#MIf{ssQ&$SUXNNeF@62p1+gHPy3;?X@ORVMOp1T`T2rwEy~)v?|}`=GxxZ=8Jy6Fs7t z=VNBZ+ERAcP;Nho{$k6mWH;qr(o0@1dZ%IJCzP4m@YYB+_THkwj`jH2&ix^ZzW9}K z1%qvAWvrmyJ|+32e_BTUDBQjnO{Nu7OVamr?H(N+4|e4XXQu~8k?W7^R;l!hUbkT` ze!5YAuT$gt8`JX1liN9N;Tpkb)a(1`xHx-u*c<-&?0A4T-}-|%7T)TVWb4eWPcJ5> zV+fOesKT{C+>X%qluc(~EK?beB?64rdEk=uYK%jpY0nBpXz48tuyIQR0c1of32Ka! zsO7q@rJ5i>B40Bf`&EQMnmlfnUj;d7?>jcM*u=01PAhYr0T;h%O~Bk=@8)Q+Od`0g zdk|WnO;QFf5;W9xk-2y|jl#1|!@+;E#%+!VwVjPQssB@WRk6%i#pXuy7<#HkIc}%) zEA?g|gwX7KO0f|mN46WRJD*PM)A+Ot_QCp*M+hdsQo>|A8`_3r7x?*74E>}%N0Kr!<>hL9`w#qYRnTB%$TZ&1=Fpa_qEdKnl? zr&jMTz&@#!fye86N6|TEk*6oP(Z@CeyKP9+P7!YjTMczNV3ar5spwC5X@Z01l%-k_>|I z!C4|cTi|k2O&DuUhH~+#YXuAGc}<)(<`(nDGc+ua85dKm5!!fHtq@+*6UFXead2(y z6~3;@kHt=Lie+L?)Dbw#a9Kt&Ns>^FmuhrFqNXW+fy7BIXQxS$bIB6B7^E9&L`IGg zp}iGxm;Lh-s+xssWxSyxfX6KUPC0 z>mGLHe}?;}AbdvDFgsC38sC7?2dcuiEg_v>toNoTlU0wM!|*TiGZ zML!!OG(PSx0kidxZ-!zVy7q4$>I%!@(7zx=$AMoH*O9B0Hb!zdW(>QQCCIlxNsAtz zd&kZ{WZ0eHKA??p;*S`^$Qu6E&)6OIu2iB0YaVsLZtY-s7Z+_z8+W`IWsoFZO~)ud zdAC?jj+fHELE7thDLT7}JR;;tB2CHpx4dz^oq_>Ij}%nW8AT5t2a~FOci_K z+{_<7h!|%py<6H?iDePjrBhBBR{7&}WqKL*!b?-|WN_^vq1r#w>hNB2Gl35r>>j;9 zK|4lQ@#49t9Ga>wSDoWJFSoC0Z!78GzOQ6-vV**O}t@A6S+QXO1_@*sqtK1kE_x7N$ zr7zQ|_D5%jhr8HqciXwrK~Ng@3-oJ*@2Efhi<}>;y#>i|mz>Wv{FY$-a`xvVBoB(= zGW7%(1W;LoVaIk(K)iSzV$8QvF<6GkTsnhGPpOm%GSpl-QIs=0k@^p(xZEGNj+jzI zN!#6Q;2YJLBk9(52{9A&lf^UqiMJC_lz|U7%Hohajn6hll4r{VTgHn3{HrxltV@r? z(%m&;s*RPMD6UXDJ3pC@+ddyv?52W&h)A&-Jncza>QBmo#nPF=VDzEWw^>igOT(19 z0;NUmm#xs68BnhieQP{N8y?F-8p#5;Ri)b0+Ba_nE3m8qjOh>z<2zOIMn-jCYpBBG z=HFvWVgCsU%=^`NIpwn=79ga`D5Mab7lrm#C zOsmH5ASz^tXsg>Bx3>*Wa! zU_=9*_Cv}`AbQ7#wFA&}S2%Ffk6?<;Y?Z@W-^TVaeYoU5C%TZGv&5@`(wH+!OW zUba0R36!~ULgO<0*3WrrJnWKB;YMyvF{ePy{ZVy4FdFWVhEJN@6rsjc2yJl`A!?_F zp)6HlltV(&4;&d4>PR7yg@;fkg^5^$=C{7ut>mO)!sa6&?ls{wmwg6A|El(V8Kt$Y zL=sK6$v7yYClIu1G&BQ3JudB8j#i7MaxJ}5z;pmQt&Yk|dc4UNsH8V|)O)dugOe6D z5yAKVb_?sd5;xCDzDSPb`;}`L3X>r);>ls0z$Uz#+KjcGCG|SzS!I$pzO8kLvzNpuFb%>wOVeIS0`pp4)1bA$ZmsfRME^t6@`-%6_n#kX zet1|YEMznljHnxCYoHUwwrhGs3_H(e(vFU4N}W(0ygcX+bxt)1A2qrlwD;MUzHj1Z z$1wTlu;cs4_IRCJKfMeCqOpCgu(Er4di+fwat7c=BP==_7#K~8m(=`%>d`RtPpS!9&lZ3Dlcmz(97{znzL)w@q4JH3 zEJO0#!4+-pr-nB}Ct;RAi5~H^xc^GX#!iSgU@R6Q<7VtHeS!vR+|{tHndu2R&duJ& ztw01;Z3Zm+>3EcJG-3gxYx_}>jq&J@*byRuGvT7>awW5kEsKEf{Mc%o7_kLwYB*rK z-c1H|ly}GbOzJ%DdK41dMw=KrZ6NCHoTiP6x3VL%xB+xjZ&$`x0@5W59`B9GPO- z@?j4Y3D(Pq*UOiHiv`~59bXkY72d9T@?`&@zk7Ii{0;8x+3)rDP7hAxEk?VigW=%# ztKLz+z)s8dWQqr+W{Y>_!~o*3@R)nUy=aeqGlM0b%-M$phT7PqeYk{kq(YSn85~3|Wpt9pe#5nmKJCpDHApI=f z`ta_N=pF4p@Mk%}L(=7>oIHE~aScuE2rF#1J za#`#gp@`sFf4?}Kj>~yfeoTCzTfTnuDr4;$Zg$wX3I%zLQV3tf$KJ!{gln4OUMFd1oOSeO^zAKJNSTZ@!}* zNvb$^g>^tdc9$A(;)S$rj@zkJ?KzR5xF5i zqt??xN$YRx34vnQ-eDiZd@mfnz#{yqxc~b8uU^wVnsy6m4fxj&!LP0*s2Rdo0dDX# z7)7sQr{v&7_Wif91&#haD&H>9|uibvm?d{ z2XajgxB6p$v$?oUw;y`vMmsX5`tvD^yJ62 zL%O~Fwb#SegSx%>(rYcPmu|?Py*Ao>=~nU^uU*`N=}xhqy%8iSJ&UGCi2WRlP;cR^ zaq1d*quF*3y(t**T6h)@jb4j1OF(yH@X$!zc;b!bnL7=z^S#$c+B4mjKYMN1py?L) zX$p^8vaJFYSg^2GYyV1NlH>C#U)Duq-u1Rcg>;SJ1 zBoN=9#`39MmqUaYAz+~0MHu| znZ^6Rx)1Ia3Dn~JeIc9&d~9Ndr_S)?ti) zNg4#|`3?OKG&Phq)c9|nJa`&@8|XwE4r5d$C6`Zs^ZNDNwkWKwcy0goiCWo%CVgPS zqwg`+qc=|hEWrynVV-t|@{b2V*kk@1Gng;YvXuS89uJ;AAe9;RQbRf8XAkA{YM8xA z?brdIv+hsN0q$pN<@CpcU-K$HUEqiRQa{ii>W3d`fulzk>Nokf{FztpfZS*vVj-j; z_I)6T80Y){=k@C)sQ%^y{(@4WznP&P{Q5T(lGU2GSZv8d-;0cV&mH()!?;dp1=h2g zTJEB?2Ur&?_@1Knu$+vXofvon-|POD(%FDaNdbdz#Hf1nYyL@p{pQ!!UOsthi5Y?% zGS5fox_1xQzxM_xzh@0;JXClxqxpNd35ZP2Z&$7>BJ_xMP+S*Le~lAXnv`)kISyu! z01?~~(n=4AJ*qe4`5DjIgbUhdrLAi6>xlt=rG~E~0AU$Z+%Fz$jN#Aw4|aY{afJAu z2cs{oc?~|K|9$`e&=_*haOXb!A3Y$#H}w8LyVX<<@XxJ(ZoN7fsGYv8t-Zy~`{nfV zYE|rvA7G#1v)>iR^U44B|CWC(UQKbFrP|s$DVNvNs-i8#X;oa|rhd4PmrER1FDDO+ zi)C3Bi;H4>HCkRGqFF77NX1RLtk7X`z8X#EM6eO!lbiQjXi0uvQ7tZ3?`X$#G@l^O zsutrZSFPg}9o(RTjbaY7FQ#~+q1ahnmBqcj>~RkVEilQX9L=_-bBtCN>L)zHhI^X8 z892en`>=qS!rt-hc0w?ypSegu%s}0F{nZu*#V+hahVx-@y_ifd@F4hg$;;xTMs@YD zKq&%-2K%99#o;q;nLea-d;&IuWtnYZrBlGoYc2W z>*97fpH^4cv!&%OfHI!(ujP0}-%xYm)YH-s{7t5Wv+Bv#)&M_^&KGY>UW*{_e1R*+ z1iG0341}Pn{HeOawlbcpl?cPUKrg=1%faey&ns+Uuco6}L8qN)K7W~yG5^b6(La7Z z_y(SCanMI>e*858ul?fQZXciTJuJRC7`!|_8x&}9x_dPEwm5!X>>hnve04y9X74YE z=KKBP_;l;w)yd&O58oXe?H!)&W3#JxhJJYPsyI9VCu7jTaX}Nxp$>ZJ_q=%3JKcMU zk$0aR93Bk5eYo}fU~oiZK0iJ!c8e1fm>le#9qyhMCugT8$Ne6r-^Z{=2S?B8@u=Rb z-qGMOX2o|!?`wQ0`Y%zdLQ`$+o&ow(g0I*+KKb_a;Kj>9@$&c(oA3SNSr3rW9Uo#U zENbs?_u$pTVt@D5?hAtMv|uH(Ma=|s#Wyc|R2V|@?c)E$9ygY;hY|<8Sv{aI>~x^J zesj?8JuL8`2U)h_`RVbihg*bB^uXvC1pSWWPC22P5u_=CCWNpvELy=*?Duw&WqSeg z9PtuWj_|wlkwe;EVfB*a95oxF27pmWj z<>L0{aj^@Q74l0$Psf%g9f7=cT54G*xJXe^l?H^OTHG$BES*p1BOFJDF}Ow&iWCe5 z$x_j5u@ae%S=B%hRZ{fncn+$8-{QC!g!^g)d9D%WEmD!FN`_Du#b=KT7bccH3CtJ; zBgOS?MaqwKE)VG`0YL^K?ogtnhbdRc>Ram%UZ@KX@PJB>DO4eZyC^;n;lO+rCKMc4 zHO6Q#^91f;Y-vZJw}lZui!r(7blGSRRu#?3&!>6 zeIZvhhN1_oyj&dLRvIx5R-MQ6 zP|_IIeFo|nWy6ufBf-u}Z&ip9N!TDy*OJG17?4c@`dCvH^0t6axL5!aa*XO0tGD46ka*(~!N`Fm zR|92@a0S)i%F&Q8i{56%U<3kA6Yp_xv_Q2R1eDbPxJ&3n-Jk&4#30m9cu4?NIDR}9 zFSG#XV@i52fmUKKpctc?70TRQ2n795@Bqu=??P=UmqGhPP?q!{!MRO*LH zzjyE6J(e2e6V>sPKi$I$D5D+s=AM1aegw_64;Sh1_=KFMV$j=tRs8S&&92`4`{Y+` zk!vTNIyh|Pq6oLna@s5p?_tEnd&o{@*e&Agu_x!ads{Jg@3dE-{Fr^S-u~kv?&=XD zw}Qpd0tS8IoE^X&C0{Uf`}Pk`;etKff=es@!W4VF|FC=bu;`!k_73Qe-d}n^#_s92 z4+$}F-1^AU0gw1mxr|#o+WU>-h8%1pIoW3=g!Ipz^#=!ovq7(TaeTbbjw`t`wH zum44HcucPKbMpVlDIM(c#25lN!_NTX*%|ywa+Wz?etO1L*$=i}qEP#5IH`NP=(^8n zMxh4L7VhNnDLe6TpH{oETl6&R9{KLt^~HSb+nO~NsLVM$ctLO2X$O@&-UnOC<7GGb zTW}BN6mG9}XrBWZi(!FZIPb*)!i)W{F~=w2gjw9J{4ktO3x*oxagCe_z21IZ>nZiZHA#C)4e^nwryHH9{ zYcY~gTkXNxQCl7u&H+rs+v%w2T|@K>C~DUVZ*9TPfX0K9Ih~U_5hsLi``mB7Xv4)Lg418u2?gO+{~h$v41K=D^WPqt%u@(BILRN{=xTS6LTZ zRM=d6srC{dsolj#P=`wjxKRXv4cT&effD#)upE(9B7KM2AAEQ%pXLYJvO~_xWLl>jl z)nc}Q+w#X^wY)7KJmKmFXD|dDvqFIJO*#7E)#!$EKP4H3s(8J-#53Nz<1wDL#6vK9 z3*s}N0Dr5y1$Hklv1JdtB}=yL3IezbqibYsILWXr{woZHDzNY>1{N0=Rk?amqC#G@ z2FTabAEizF2lo{jE2dp+d|h}E9lCFZMlyy*rbmQkjGMQMsj$5r%+nKR{mm+H)z% zD3%qJ9xj$c!H3`tEmqb9!GE~rv`N#l-Jk6?R{w_HKj zGp+vp``5cGVLrrD;IwJML7-}MDNmEtwyJ0*vCZHM zxm|VUj|z)H)mIPAbUcv!8pn0;PiZo(2<(M@Mhi3M^BFj>ob(WR8q0PzpRVW|ccDZ+ z9Qn~aLBRzTMrn1S)U{~nEY0tWTLYfgb;pWnqA!ds7s9@a^vM;}&UBnB@*}>#F%94lce#_T>?>mPk)c|IVHY8N+}oHoHBaA`{>eKx5wKkC;BO zd4T@*`3neMu6BfxMPcy413HRYfkJ}12kCKJS?{j)Pr){kkJqEPvGpBSxb|-M?DL+$4JsPRt%Mp6+ zi6iCI^{HT*8uI&nD}jz|N@{Ill!taZC8M$s(DYE{$aIn%zbzjLtNDmFIaxhfC9Gu4 zsC}JpD19SK7yLUYIK41_$mMu=U0x5zNV%14TWH9bfz(j@7E=Gv!Z}w~x}=Z*;RSD! zflZ!bFkBtU-_DTinHkaW;8OZxS=PHH+5sAp=vUeq(BFgR?5KR;w|VSkr*%t>5+!2z zqGRiu8VjSAv!?p{+_$!UYItfRSh7PPQaFU2(ZG|u25LPQhGM|#=*0hvZK(L5Pbe9I!vV0N8Ud?1j4qR-H zXNwBY;=*+hK5Ma!pKxE`=p3rLMurozHmU`xn5qD%OR@;Y532uxjr*~rqUdNM}oMl>P9~NwA1ml5KvC2c(Ik@y!N*2+5kS zhLo{cEs=Pp(6`uLaC(QP`cy)|MQ8L`a$r;=($GUvixhepH=?EH!;>n=up==;$~30h z#A3-#m6I3ZAl723FN`+ryzjI>n78Xg}13F0-%i zMTTlfZ)|m{k8G7j3aw7?Ksu!l$>$2Kg{|9#k+@k)dfpAUOp6_s`bGSReemp7|dPA8rXKzO~6-TNAQqeFr?SD%# zI(^B3XkiZob9Z+1)zR@cN1;Ay1(wR!cLA9it25xlK0_Cv$sLQXu!fqBliumz+b%#; zV|9i#YnP=9_^jcuY10{$s2th_ReGmgz^Di73_N(TT>wUf?He;4Zuma!o%B#pgyQ#& zpmIj?0c(n;pyrD0i`nRs9B-`?^@bq({G_RblCIP-v5=Dr}t@1I;(dwFt3dKPIS%VH4$O1VX44VS71i*O{CS!XsA61n(^Le#p zp}U&3+|1cUIhZrQ9Wk(qX`TF=RzuXxb1XMpTPrt* ze8-Ut>Ogdsioy#kcCl?FC%WxWMeJx(MET8hHrqq$?lNcl&fVM6O2kO-7*{gk3=1yb z9lsyr*eE5wJh*gYtd!D_ImwD}6c(a}{DjB~*5(8Ed(X~Z44>`peMKkxdP7(^IvhDX ze)hkpT%2I0YkKH}s7MwDnG0KSigF}H7-vUG=V8{`DY9wU^(4LuRv0A)Y+dE0?Pe-R zA8s8>Mcm|3*07yOnTRY2oxE1nx4L%4==kDG-GHmBABpWZomzeJ1p5IqI;dg{tIn(F zZ6YB-u}vK6O1!RhPvG3PpIe$;~vfuv%v5~R zO5#H@kmMDwoZ7S_ZV{+##D`n}=}?N9D0P$p%O1|5%Jw3ER0|EY++fkqk+xMht(}7! zH7_@7QS|U-axQA5j1J+;`Q>=1TWUX)OLxdt1pv9@4z1 z@WrV%(CST^7~31r>UvFcVH9}RJ98Kx;2%RI;s)oPJ*DZQ5h~jzykRCyzM?<2} zG^EP`fDyIbr%Fq7M-=CZb4R*n$6hWx4ta)8sA?{Z7uGa~+}7S(D+(|kc9{^Ttx^Y3@O#UV0rQlQirpNv)`FLl7@Wtx~; zoTdU7A*DgP*@~(8ERXp%hqGz9tphfZK=z_F&Tb2BAdKHJP8BV2L5j3;J~A?DsQw+d zqwyvuN8I!_k>c0y2K@)7YKqsrx}x(swB-)IC70KdW5c%Coo`pCC=EFkDd~XE>`v>i zG8QQ~i_Xn8#6AEV*CNwp0^;4~-mr%!Mo+CnL3EIfFE-J~g}4vy#~@WEPY`JrBO`*U z)!=;zhC(RGf^vzq55>H{PO59PQG!dUY+peI{*NYoN$D<6@zQr|=v}JuV7~C`T!DYN zSq>HywkNn_1ppZ5wvF2p=3*);5d#cD2oU)G&Z^&Gb6;QFL&~ zsgMeV#ujMKVhV*!FGiw9=>+wW<+H`)y;j6=-K<$M%@?)_)0LG@{HBV8YJ^f1*wrNT zeEx6>pB*`hiJdMkR|Q8YIbFLTbgZqmOdVk3<)r)tVof3pp zohA;}1)LMZ=Wy8K%umuWlaC0(3sDYm+#9uwrrbjk6>(j=-c_y!n!4PX^91LW%Q^l%Nm{TM1dl*k2G7UnO3+1Ty**aK`N9hYZ&?W zpQPl8yAzx%18fhr88C4>fszhrNZu?DpjB=HOH^|v!qv+^pwOqrE2*ZJI93}`$UKQC zmC#DZQXLV~29+}BqxZm+V@X1V2N9J-4S8J>i^Wu-MCx?97<0(9lwaV^`-%7>vI1{t z@WJ@q8YZ$En?_3MER+jUN*Tg!v+1j^o*z6v_Wg?MA10ZTwpxiF#d-2# z8_B=rdx>hcu$pN_0e5n#Jb>U5EZ2|^i4^_`Pkm6iH@(Ax`!uQiOfdU>#y6ZvYE2iy;)n z6`S!-(%rZm($%zd4j25#KTOJ-Wl5X|HT+7J5*oGqu^hXSqU4na=te@~K-J?fAE+F@&*mqFW<$_`2zljM3rd2gn7M2!8n)4Pz-G|EKI<`Z`Ckp&uo7hxk|eckU(A3t0&e$> z(j?m=*>WybN8A)8><;1?X~=DY@XbGDi(4_CHC9T*oW*B)No$ClMIh-H>Jx~qS7(cr z(u$|PEAG!?F^>E zMBex+t#fOzAf#;}?|x4B;vaXyJ?$CT^F~72 zfG?9uQHCa#9neWqrF+9b1*%eS#(UYOOBw9s@=SD+4aclIh3CfA98S4%gP@CxC9(V7 zT4ras7ics=PZj4$M=A`A(zDb{rkO=5Vk<68dv1|vD9Iq$a~<83@(8W1ij)_Ox=eB2 z#pD9)bevwl!2VsNiZ%sNX)Bcpv~sC|^N!bGajX{^lB&WRZb>g&qGp>Cx)14cq42Ec z8=1SLoQfE>}NR&Wge+;|V7i_D3ar zys89YmZLyO7+kJy)FCcVj?baoz0N?CIuq;l;SAK!-GHUoFQU(FXE8}hl=;sqyo`iA za3s5H!lO{1+o_kxC@G&XR6G_#f^*^+>AXM z(gC70LCF2Y9piLjh@LF=&b%2;iQ`-lP40=Ti**C-8hFozzX7%FV}=`gAH>o^K%1qjC%j7B*PU%s{_^Gr+t1Of^hg`l0@Qv5U z%jTxRjExI5v`#M8G##GbRt}$F&O9FX$7m#`HEQD;S`n+lAztMhd4vKEnL>@mR*-{7 z$svUtvjP70ipI;M*#c{Hj!?qs_4tG3Dj+kywYHRl8;yfp*H_^8X1T(-MgFBthLAgp zzJ|tY#cb9}#7af9Ct^oyJ2V5_de7Mgw}zQo1AiCPkYVt8Q-r0sVl zBO?_hVd_d&;>ohsnW&DTvNWnfpUU2}=Unx6s^w%Go6QleauQkPIkBuDn(avQ{O!GI z1w<~hYq%Ov(JI=QlrvOY+7cX(pLt>)dBPXxFmq824`N%!2^Kk@fk8Xa1@pImpl-4inJHhz+jBA1G1a|Eey zeYd=!!k|?~Z};9I0Th)JP2ON(jXJB%yt$$g1trLkcRsU}10HuM@fADf2L88PC#|*= z?oBvmYa87xvpN>Fl5p&6#F+}J`L;|i*Vkbgps6LoD%h5~hRjY@cLJ++bWXWm!sNrc z5aM^Z%SBYh8i}B+9ct59_aQFAGdjj-;7bEQ^CkvFU5xI@`5F_cmD;$yoy#r9^Y^QA zqy=0sn^w+b-&Ai_&mt()OxIeSOwOsc!8RraIbv>QQd{L+G#GOK{*vdZpbn=4UUKsTLG8le+&_8%~aCm?hY;4OOm{S~# zk|n4xU@L4>4C$S&^XUw?V5w5JI^T_TsA+BlNx>G;NsbqisvIyjb%X8Za1cqZ__Cs_ zhzhP5n1A+nF$H&iV6P^rr0B*FHx4(3#NOVMY|U4WBs}=FG_{1I5knh8=G%N5Q?5me z;vMEq9WK!tO)KXbm8Ofyg6$CQnPnXUHJX~VUXSWYYcz+_Y}_u&k$(8Ru3Q0`xKGRq z4KQ2O5f2b&*q^F|F-RlRSi?4GhYiZdps>p2$T~@D$WSc^& z@Mr7wpo&Z%)Zks}M$#BGjjw5wO?pFWny3;NGMH3rqS>%2%O8v(XS0Fqzr_-cjS4u; z9;HTLB4b+cTXe-(4aGu2qG=OyJw2kYRr5}9V5x%Nlv3v5J?+&nZ9 zVaHb`?K5%m#a>&DbP_kHaXStijOI!*aE0vJ*wK$hS|WBCBj;q-WXhpoYrR%GIay3_ zy)F%LdL#~vv4q+Aoj`rab!Y00UoIx@a^W0nG-g@b^Ff2ywhV}wW}Z@JHKA^nLlwqw zF~=)cresO-7}(B=oNO}`sBWoHsX$Hn2dB=#7=<4y@Mt-67q}Q*TtL2Y5gzPO>(lpc z=cxXTn$v7^%qWs>_uL_e$#Quarw6z$c zO`y8?Ac0*Bl7_gR0utgVFXmPCN8z_Hx))pctaHQFLa=V70Urkvb_7 zDpj?)DtRkXTZCT{KU~$02KU_G$fgD z%D_uq^WT_{Y6ROFCTsm?l{5RN=J)|8_}g!nTm2=6VXUUs~0<=wt4KR+||xxkt(8w zBAVN3B`_~MPvyea{H*+Jf7e{q$yuoY$S5AqMVWeQ9XDHuj;@eJyz6dUy3UcK^=}FV z^?cAZ3M}^UCD}HfNkw=uyREKlx(GvHqR~dt6}=^6$0JW~ysqGe=ZTVU$7?leyCFK~ z`~kmR0SAT3OF3MRsBrfUN4sKhxNxEqb`x9MwLrg zr*7(0Y9cqm2}fHZ4NLgBNVcta?|-y_$S*0nQJ7X(`-Cy-t}^I`d@pEk&VdKE;PpQ?rOBqZDcyNziR2;ntZj* zz1(_@Wz@UD9W2A*U28Q;_#`p9%(|0j6W?WUgCnt{(3-Nd#V>IyqQ%ndxuJ`tH?u?h zSO?wTxCWi58=pgzCP5!t`tQ$v|2ed)bRo3QqjQ~Fgb+VA%-w`2o?EJSl^x3jBZVR3 z+gtJ^*TUhF$PpwQGc2uxtqqN`cs4CiPNG=|tR0PDRq2hh4q#8=S$M0AW6cmEJw(1m zYkm}2rj1&85+9oHir>!$_uHPjj zFG1x1SxJgtEh;CqQ@40q%#%{igKo4iCZ_M~TVfq*BT-M4P@N)f6yunn_Abl2OadEA ziYUiM-`oMWMh|okyksI(pw_U0!0o?NfGs_-dA!bHVDwQYA!zZpnV=J(5ZlD+&ODNY zdnUyf4K28jKG4am?q>-sTtq~rE>3c!MkXQL>;Ml|=Y%JOE1CkqMb_>Sekb=~ZCyKB zRsfnCH)SuY#m;stos+$moZMWkae-J*et36P+T^OW}MLYS#jrbs!NdCE6E!}n?|E9-c7q=@c z{n2MaOcS=!_HdJClC3>maf!P}9GPYR$f=S%IvyPC^@fML{Q=+*n;z0_j^<8+Jd-_F zLSw8oyG5dq2~CKS#0lpj*S`{@y)IRAC6J;NxUYHC_pDyM*)5zz^r_7%*3XivOoY_# zZbEm$X$$F5lbV7%r#ql2uU4Y*u9%)gjmY%#o@<7B}P{B@h6u-QU% zY?3@ILu+mo$2Vr>$oTGi{Shb1SVxyfBkt5#9lC($1qv7+$#BKZ&#AhU#Iw+7c{_ zl|moCg{bh;Di_NIuDLV4l)LUer6Q9~Z~<_IloF+O55{N@u(3?jz?3O#kpjvtptNut zVaTlfAcwUZ)-jfOiAlGMwP+m5QD!o6osITZo)UD{$J;6KYb<(x?}BUW={~*==3Gxm=F$+=_CHb3&bG$AgzYX{g5PdXr!+ zz5)xezQFiZOc{Qfxt`l2GP6Vu=2{t@<5M$iZJf`oq z)HAOKl|ofu?8MEZr{x9R5`|Y0dpPa(Y=oTtWN%cJg?RO=Dqg!S&gRn<{SIHLz`vW@ z^VxJ<=&FGsGIev9W!zf2Bkw6yMw;g{Hk;dx=Bo!hju`Eq(J}Gp6TyXNwZ0zBZp$4o zG_WZxpVM1kW8kk%Ld&5ufsM+0ylIC0tm)hGkx&Yc#1&@pSE(oj?BBoPS%_xzvs^PJ zrR}8y%vX5O8ZPDXh#q#{VUivk-eoz*4U4Ptk>b=xApde& zRs@QV{oaq`@`jdSgg}2~#|WcyU<6N!2IPB=!W-(ps~TwR7IQAlXIC7s zlS0%G40RJhR3m2BCt{#j2#R&)mqL~)n(W2XRGOJQRWzNm7}ERdJ1%Qbr`D<3{-u#QlwBd1KYa3wHQdNUVIRhb&|;(!>Ckj0gEU_VsJIB z;;U@Or8}NQX$eLjL4C=l=w|@T9&T)cuSJG20!q6rzViog_7~&5#q~9eYh+FBnT=ei+^Ku>$syfH)`2p#*sMp7-&W)cWOBUj z&3naXGXjD+v55Nx00RQ307>bL+?>Q>dxQ)&3N z=TLcWDN1k=g#&|5tb{?mGUPhe{#P(wmuB(82s^816DAZJ-z6LlSBpMqKfi2FAW6Mc z6Z7a_C1d63?aoxTTymxZ_%#eP{KYPGiV+}{QA%4#)v^-=uT$MA}jJsxDEqJXk(k*{9@6? zL`mB}txiZrD;R`M!qkij2PNGCHd?;-7FcVpUX`n>#l$3_Lsg)X%kCC|c9w0O?d`;f zkHcDA@pdrmZ0ZMCUW*4ZMMaVpO5%R^C@=yNYg#1eYKA?7aKtFP~%6MaleEp@yn21 zOemAI(#uNaa(A8z{ej~B^S^?FYSqPEq$Jc1YbO@zdirCDJ1yv+yS1y8=yd*e@k8ma zSl($@JbwImn;z!uzz@g;Wf#+h;IKU}x`M@+8g_IV5kx895}_7(_}sb+el!3G+mV9c zWVu)^X!|}gxoxvPzyCn&2=tg#Zop7tLJt zcC_Rxw*~hWUyk`fg5ta0(f)9EZ*NFN@&|hk=Ax*;m-sD=5B9E%@Z@*akBzwWNGvqJ$^mx$Q z8}#-&BJznEFK^kpb?cSup1P7s^HYn(AAG$#=ykSq9xZd>qHX(S*Ugc==-p@i!RhYa zprci*;j)&k8@FAz?zjQ9pC26U9(J^99xH3fqGj9l2IK1xueMx>^Tl>nvdsMYWxq4Yf59XP?UjeZS=KPx+Eh0SOZB3+ASdjp$Rlm$p&&!TNzn!ognv<5FT z^q#_ze)*~CB!f@?@2}e0oiFC^uNSwSgoIfLG8crD`n-BAQN7oH(S6V>kSAxYCk z!a{puKOJe*j%(Kl$=VlGliw8rjKs1dr>0Aj#_Fhdr0<4C>1-`Di2}T9B3Z?$4uY}^ zWkWo54Wcyz1wLugaXfT^vdT`JIAL;I%-Y$;dQz`Sf1H*Yi8x#Pj;#?rSdOOM6l&xm znP=<_!L4T9olS94u@jccAS^F5LezL1>{VDzD>{DJ-7$>}cz-4vvNn2ZH)y6P)*MZa z=QGq#bhSML$13G`bh_J^L6QS5q=IU2cUU`cgT;W2>z$YH^!#k#y4>GvH~%+N)S=u8 z3) z4LoF;$Be%W$A7B0X7h;G_nNc4Wt=!cnIL=G5#!$4W7CvTTjYKYVp{cY&&T98A7A)D z>(l)Fd#H?BLnAK?$gFG@heNCgxC02XLMdnB_u>`^nOEaHkt)d9o|G3OJQr@Z_d0-3 z>!do0LGxt;$Wji-F{WH6l>$;3T`)%z zfGHIB{?deEQ6{`TE`!k{poZmzK`((sWtwep8W9zY6PaD}QVLPO=<=ktf_K{6-9J7$ z{MO;#O_@Or8lghS1FG?wq*vXOa~!GwD$OD zi2v*NPWg*oI|fXS7S_tSXb3>t@1ZpCY;SOUx&|axXKUixG9nS%#*QX&l$3oQNhJqd zGhaKcwna4)NW0o_&eRXJ&|`r5{St@3_)0kzcspYDJ5U<(rW98$)ubW)E*Kq|q+7ZX zrKVhq%c8t=u$_y`O9bg^Egyhn)f&&=x-2Wwq2?mCOa*h=dwvK>Bf;7o3{DT8oeg?J zGHFMsK0n&)9Y62Ni0c8HG(Z}hc7o=t#Gbg8-@n7@OYILgR_(#-_}2|`>d=Bty4sb3 zcCx@#H!L|-55_oVlX8BD%Xfu#u<(936e+8H-u zVv-ZKw~0Y?_^xC62=wwIVGA=d?Nh|E8AEI^>HMAec)Vn&(u{%vJGw?$CCEg% zW4=!r>uc6R7}FOur`7}pq|sVW8GtW5bX@!#6d|D&Y4U1hzTWk)Rk%Z^o zP0T!Y1H7tz7fyrP&&=Fi>*|hF&Dp87YL3u7BCEDV+0UqHSDQ~L;0DsDLeN6XjEzWz z_;tK`bR(*NQAx{hBlxB~c!q&zj|;vkwQP)%q$mn$DOllt!6@=&)K>C#>$FnW{(J3R z>Hb`@hjpc7o32(uzfCuNjlS7@wY9eo;KN7wX5LyhB;NqP-e zw}*JOrL0>stnS+PNM&tZSoLI_dd`h#(^qoU3LfYP{l;%<<|ga9*Lg_NiOGYMgfC`j zDK(97s_MkEHH^j?tD`=1JQsS(sRLj!=}%tUm8B+u#g~i451fkBy4^OB_DVSa^al~3 zKeTp8#L4MDDRgB`3>@l-ODJ#6vuCCGpesqB#{$I(phRjmF%bG=xf8{q)8J5H= zk3Xwuvw?4@PKGOKHVVzM_D5~k(0@Ba@1yH{Lrw6NH3%ZbbuuRZa`DC1n!Z6@`&b=C zb9%f?PgmaVt!#o#`$jjkX&$+hjN8+ZgeImTVP_}Pp8MW5r+^%ORvu+tSnA#g{kq zkaZz;Zay%Je^5n8N}nmO$Jae}>S9|p=G&~aO61W)-VI0kA94Nr2`&;UC(qu)qL#SG zsGDmilgfHLnm;Sm)D7E`+6-se2;&t5mNONwsyC`s$4EVht=zJ}v3A8dBbj@{${o}v z7|gVSgd2B(iX=nm$hOg!Ym0W?TivV}p*7W$OND#1T#o#QKK&iFtfgkmWsY%ej@jgN zjnAdD#$-mC?PO7*xUrkZl#{EQR>yq(;zxTo(ykcUeLI@+wUAwiW7@k#Kx5C|#iSYd zwWm}uSr=2AZ31&Yew_#5tz3c8)y_c%7QV)7iK7XX6b2&eJ1Ke9dp~KqRlCJ@?8phK z5}|t$l)~tPD#9%spLhzwbb@QQ znBWL8Fm~^ryxtXuI_V|);q_udM+T1f4u<=^=euWzg9kv0UZTJ#emz{AOJv!)+^lc5 zI3HG{w^%m)15&y%Vl<>i$7Hk`soQBUE|a~vhn z>?endP{-#v6*sK|*=#XVui$3lOCchw9+rlWsJeOzE^*a&I~HpN4-GHQuY-t}tE)Cd zEEgB;AWND9jMxe}t8zAL2SWbKM>KXTV3y^(>AWSak{A(#wt}N7%OBbyB?$!$DQ`Jo zH6(S?yDN&Jr84dJdS6jNO&boXaNBn~Q1j_WW4FTFyXACsXVCEAN;0>FUKh`?2)P3i zjko6Ih%|;=<1@OsfrZyUc4L0TpgY3;;i8Y_;<^n%@eccZj4Q!9hDr@ zkJ83i=QA4*F5f^}C`(NQh1)^}aocNC`C@ikU1_kF6^T=Oh$vRdWW!KbOT!^L__ig%OCH+ z)nc_VSVX-V#ai9++np>!464%~I^tJBN*&TH7uJ^gL5y;?jh{O{PbN}X(toVO;iX(Ts9 zfooiBpIX*Mxf)*qjSFjK4~t)Ii{8?svx4KJvsYc=-4Hqjq@ed^EYXSu2`NOi#n?g% z)-5*TL|&scbv#+r5`fja$&Vq+>iBk9;Tph3hO1)>lM7+gO8-DfpH9qp(}I1VP_|8H zC3O(jzs;O{Nan<5$;jZKhGdBUr*un-;G(r`Y(oSZ$UV_aBIqqov#KacgcIZwLZz98 zk8i`r$>uA9q^l8V}A2yt)lE^i1dEQY>=%wU})XxuWpS%RPp zALBeJ2&(nw1S)52Z-;PY150G+B)JSJi}FWH*pQ%FeW1u?b8`zfe|WRRRy%ZTa{1*- zHMO`?!nj<#s{kTPt}g>ob_(?D%`cywq!GpKl!#&z9t?X;6*YB`DJ4D6vudMWn8ZW2 zna+efljT!9J0845VE}X;j&lyqPLGC1XNQM<&^BRjjZ_&19;yUL5*ag@)u>lmMt5`F zbDY^2?ZWfgQ5IH}IXJp!v4r}OUN3ht;FrrKx#Z0tb0gar4($$I-I7Fv=rX1SgpU}!+**^ZBziGkLp zu}u`IoUEX5fAH-|Z%9EQZl0AE-QHVrR!`<%WCdN@FYs72{z24W!c@D zZTfo&K8OA-7`Rscmx#>IM`LV~G)ul}XA6CN{t&5V^1v4%w}|eT9B_4LQhgZxY zeu+=UU>j{ldPHnmHm`=-pskP1I`1FeZn!Ef_Q9fv3E7T>Y-nr1=%@|2a#eK6yP4j@ET`R4OhWYw7Z)~UpxRU4?y0#A*(^WC^4C+dQ7?!G^+=n`J9O<0xl<6M zC4f$Hg@<}#YL$s@W@|Q~XueudR@vchqo>wLIOp3IkAI>836|%jV2HDoVKgH+*@CFB z)Qe!r7w5ai$#=l_j$ggPGja4-)7jo$uTQRb9k1rvP~kq38L@&LhQYuZXoUEg!;@NKA?}A#`5I5Bc;hoheXuj3D!y~-NOP*ImI{>o?##ZDEC^F*%W&&8M=p_ zk;d*!3*%`J)sPkl<+EN#i$sYy-xH$5%9P;s&f~p!s^oRGn($eL48^E(wTCjd3?$b@ z28_XWN=9acZJ+Dh9D!tUzueL>d8GRY0FTa>gucuUctAlr{si|Zo z!1LZwesU18`3Ul zZRlq^F9zXcb~*0>j#jKujjzhnzMw{VwdF#PWWg)(3AxD1Io^%RpH$S%{ zQZ;;Fg5T7Nh!3c>;|fOTpeFJiKSOq&$?)TNaScx`HN9wMb3}aZklz|K4;PZbg>lVp z{kC>ExLH-8V_fIYhP-osF2Jacw<(rPqjomaF{kky*(H*3dxPk-!U+kuNMFS9u|aCX zk$+)RHYuiXhT}k}8kT>fcPng_f{j7@ z>qUi`GM%MBsfsZLDRf7RQpb=38$_PVmyyOAPpQ(;5_~0;UUs9=Vz@f4Wig}e7OJv1 zS;?5jk2qg@r*)5YMAyjmm{G)6DbUxB!U8!G$7LddpNmPjLE}CV4@9B4TRE~a#UA?6Pwrd#Wnpu9}b4Q&-dcU@>mzV zsCE{p8ZCo$XPZ>5>3ar@mxTNvolazBDUT@{*ER^X+8ktLv8E1075a~VwFZsuo$8@x zaZoHwsS-?T487FNaVMG8S3#QCdSS4W=N9d=IBI_g^%CvQK&hH@9O$QNXj$Tk|FH59 z$FS-UiOG6YoWXfOQGn4Na^Y9N96qVw3ekGX^n~$^Uc)A)2#~IG3<#74w;8sp1tcR(1w+9WYiyUXok_1^VWXTCJXlaHNwahZmi?6MPLZo5>jqgS|o?T0Ai5qDe4n>IQULNPV)!S zLtuetM_(Nse{*C8GvBot_8OKND_whJ+TE&dM!2Erlo9sD7S(k!JqbxvKUAL7DAnRtU2E zWl>#Cmy6H;^LPE#Xi5L?Ub)UxGx#Hy-Vgij3&bt^NaZtdgRx1cN`YcAZ1E*Ilzh~f zD@-2=-Qm#f^{drqzyJMj|BK$5m{TQcSsyry->vFbg4mAuedzysdwo-Tw|cDc;bMMS z+krJun-vX*s1cuH(SNU9l+}dhJaBFWs~^&b^N!UgcM)S7pq4K7gT!`*JHNW^yxfe850#>7eQYT3$|vA4Ox9d zoJ7>Py?iN)E^sPA&vM% z8gXjYB>!2`6|SSDT!aJMEl(%tcQU>_o|jemx6eNR@4r;D)8+5}VK@@KyP~ zQZ6b_FPBBz1-Ss-y)&TwGIj_>u!9gCG+H9mLdqZ-LhH1cX{Q9v3J`5>;KOwI;tZ7l zvz`0@{g{PMkAo>InouyR4AQ)eL)-_Gjz6Y#RA9~U;@(;-2yAxn%;0}`dUJJCaIQhs zB`KJr7^+|D=IeAx#pC%fxXTw)ZoKw@o;LZ~af0qS8($82o5QGDi-UBtG3V)T#INkfqQoS)a_7WYXn+jY5Ij&82nb-97sTD9vkn%!KD+I6|XHPkIE*QLG;4Gj<6QPEv3_QB<)B25bbHhu&7fU3AJoc6_1{--U*VCB(PjDP+wzv48qq3K zPkvoplExhVjamp5_Cxtzsuu9y^^{-fpu=^a{_c0b1J}Ox#|^h{oY8q?TpoerN-{Z& z37WW{K%zoK2~#j%vCTs&OB7BI+;dV@}jM}yDDplW3z zG8fKDDqQcrQwNUH#$s5$V(_7!CyonDm)Z|#*Y7l|e$<=77 zGx{dH(qGx~YDm|-838sp~a_Xlv3O~DLZ+5BVmZ`vVT*K$Mb*_4ks}Zi1 zxAWvl|Eq(O;r{WUkDBq=?`KB`e;JECc~&30X~O7iuF zaNS1kXfo+t->lxlwbL2MiE{Hk5&(orJ-MNVzPto6&1iOnnisGbU&_M*V{ahd30@+( zSq+J)gMyn$l&CtumCTf89Y;97oz5l%q4vo&1~vH%kT;_hJoY*8ckkX$1*npuoxu{t zXUj@lD1vi797$O6a*pS`^r}80$x+;k18Y^qf-N!_>MOcRZF8pM_|4Y!zIK|FYC-`+ z2XpRF@Fx$th~erqftos4xkVa&dzQ|`c1M0t3mZXsy!U^vcQ zrygg{a;MvPXqdW>OG!s~*E4kjH*4-ZLibm<=UoswZ?><+TVP#Gm?Y)ZsM3t}F<56> zf#7fPwX+8Sv~@2n1A1Og{?Y-2Nv;8IwECCTFW1uV{7BPlYrZ?XTtI1E$;%){_-I9P zsDpWn<1i?F%fe2B@Kvzo?PM>9!>JVR5mgl7kbx!bTieyPHh=v;|RE4NSXB@!vaRpM<>a*w)J0XP%@wJFJ(tpz#dJDC_<~c`qIY15XF~EIu1#u_&I9L zcp%MN*@T%^Uqg3Klu@S|aupzMQ$$K%s3H|{tpuk-MUBc@#H6dSXu8NWT5YpAQCevo zj=3J)@Ep+*WpR!$?`yO4@^(I_a%fUz1>Uem_%x?EF(B3N05?`>l1-0ms!h?Txxsi8 z5t{@#^-D43zGC<3Q>DRDZxbjQNu(H^+u6-n#+qCrfDoE zicFNM9SbvO0|sXCj;@QJb-fAmxtO=O0Qs+pQuQdKhblVudeG|bslanU?y zqUOb)lS))%923^KL}sG)P}a3Yo00LGN?77EphwF&TH-4#NYO>}rpQ)hd`z)z|7NDX z%s3&a5(Ubq3}ZKcx9TI;myEBlCnf?OIt0)~nM5+kRU55AoE2inHu_m%W^!_Cm-^#O zH`8g64(3bkbt2eO5nDOwqx8Ou)PK&Tr+dHsyo z{UTM1jpQ+U0g%A7RRb#BG<_XklBuk|ngqH4F^Ud7MYFwahL^~x2a;C@=DsHtQDPhzK;@;!#c3iQeUwbr3~>(yw`O;)Rm+SG-E1Y)v9pg zBbBROThwNX%H#mK*0y7pm9SZO-)u<+|94Z&+pvU4*=}?#?aF3nHw;uDk_f z{@jX&8`pjF-d}D~Puy8?aU-DEtnwjE1#Wj&h1>wCC_MH-O(OL!>XnKQ)AObQ+T-)R?Qi1-_>ZY4vqzzyn#Jrpl^}H(<0rC_V`oR5M z@=MKVRYll7^hs4gEAOI!yBR!PH{!$BCV&B`dYn6C1ghWi!OY`OuKc>Am>i3j1ybw5 zrmL&Cd*=bSm1XqdOR}KV_pZol)ta{k&+2=3;O*&(bRRyBNwNa`&g$A5WZ5od_aRLZ z+U_hutr-wUEcg?Kr@t9 zRd8#J0#>WL$?w$E_H}repm|MoE_9OPu^`n~U95QB!P$dmXtgh?j~n=e$bmZ?MOd~j z4lUragvBkYrS+TEbf~}w(&FsKjWFQY@@#dTkiIKdSFZX6EwUrMg0$w524N(dSCgQX zS-6J0KgA99bj$B%kU!zFXU1yhUNKHNSf?<2%B9)M>7MXJ);73Me0R$^7^Jv#Nr*%{$Yf`IyutR`-%-W+RskLKVK3$Rv1UII2YngAg zYX3A!-n4$N*5+nyGEuxAImVI&c1_>2w)mXcMks5}aQ$8u6l!8c}3(A6M?K4Cv zAov(j76@G&I7&jJ&m84}q?^mECXQSujwq!da1JCXAU@W)rgeb}9kWK0?yND8JE*AW zVW<>v@;sEnStA5L@3T|7TF|CDKXsu`&tAW;{x+Kq$Mkf|&TH`rSDMqe%3JW?u4pp= z6TrHYJ_$&*!n+j?G(-A|-d@3h*lS$p*9xqx;d~%{fg3_S)U9~bvVi*yF-^JVzUQa$?0Z}<6Q z^4qmT@xV=`MwOG$!Osep5nyz&jmft(+4q$DqcQr#bGVYheAHpAr|g(EpbO6AjP7Ay zzE=QgqzPZ1pA1+wzd9h89S#{iBl)&m4yU-%!y6C4$l#y>n$;EHnc%J73vS7Uf= zY|0kJ$sb(9S*<2}vr$#u(=P?^nNhm;b+H_dmY4F5tS5ySnQt>ouZD>|o#XA2K+W1> zksfGtae?*VT?Tp$Jsd0#HI@uO4(Q&<=txc2r6I<%DOB=M4FLjUdb^Xrs<12go-RS~ zvqW~O_){gzSBq*zC-G&muT@Q_UR@7=xdGAMEtcv5U8@f%Z@RnG^Z}T~Hr;bzzEV?H zc&DRO-*2)fE4+PaVMn*C1xgODr$PCU4#}0r;Uma&l}GP!M*&W+cLv&diC3V9^rBXU z>-)e8ekvykVK9Q+qoboLKro*2(1f*!+SvleSEKo5IV8?#4Z77=dytC7jB-${Wi3SU zRF|uu>l0y>kT)F?p8Ul~yF@}%$17NlH^@fGKZk|cE%RYY@`iBcy2H|XG9*OrBeUgV zK8L2(7@IF1K~YXGf>K8z);VQXutYSZ$)x>XrzaSop(LPV ze8_f$Ka*8lZ4Hw^v7Mg zNdKge23Yv0{4y9X+{;>OWHj%FIIFQdAPOY(5R%dv>e?G2g35oNUKEoONeCQ8l&HZ^yERE|O$zk$$$d7e%ah;(iq^bcEU`lqff+oUo-M}1T zbfzvSOX1TYse?JSAv|o8%HUBt5V~t5AEqJ`&>AqSud6*e!`HQmzym%>;?3@y;E5Je zWo3w3Bh2dC9Y8k_qSla5rw9mb)ng01-7G@ZX9u!LzNP8csSFxqM_Q&|A$2yIXhS7m zH&j^$`jrwDGJ8_t!HM~#Qn{4rc!>-xe?rip5fJTZ$Xi;zRshHX|NH;K)J zx8==(@~5Q4$!*V#7?*ft#2G;|Gi8yw0~EIGd^G-{J$$m`$4$Sik5Aq6Ztz%vT;tVn z(o~QcS6jNL2CVZeB;_6{i5STbBt^yQs{xc_H8Y_o^HhC4&?Z958}6M5SLRGw^Qr77 z*i?LIQ$7Ea!%z4J*zMtO;T2cajPld1aVz^7M}?oD*V_VP?DXL+m@zi_tsMJ!G_3sr z*NotnU^Bq<<_f8EDxTixCOe0b$eZ_9YN(tM<iDh0v|8~gJ!huAVhTlh!`Bi zPNGZpvs?hzB-ph|x(w_yx_ev4(vr!=uKsv2yS>(%*1@hm2Xdkf$IDMR8~g!Zf4D%U zrm7wYciSPFUcNN+aw(+rp>o|=cZ=WbBg)_+r^G}i2Z!SJ2zS76pWO#X?svJ}{FuyA zpZ2z_tP;2CS;EnI8)}H!mHC2dfyrxaXdf0&Nkt%wi6mg+_!@>|ZfY2hwHG@LE_x6U z`n6&nWHL?SFNjmz!s`j^AfAeSk){QrT#i(Iq=ZfeqxNE^xXr$>3nNq_SQSW!XG+Wy z7j}h&D>W1-`00Ae*%3{&NUEf(7BPSIj81^TUr*v+6#X`)`dC|v$oI+y^HtyW|N_~_D!KBu6_AT zA^1>MNwK|Zlp)CO@EpD5aC&r4s2>*Mk)dBbe*Bo~r0Erhl)_+=D(3X@qkYJq%VxT- zr!y8P$g(O;O{qr|jNz$5pY1ur?&2n6Vxfvf>bRa_il;e`5*gLehSE0ZbA7nhR9(%t zdwIDmFQI6as=Pg)*^dF)no_t6x=NI#Kn(pcQoHby>RdT}aHcLb-EqmxCZJH??wm*M z2l(EtwpDc~(LH5wdvSpvG_-|l23D48^C2@u5g87*HBJI)GPT#RO>d2*b`s-BA-iE> z))sNTHLBG1U13HU4;DyaBzS1$rjSq5HrbwwPSohgWi;Uut(<^U)?FN(y$U(5X5Y;Q z$Sx43#RU}^0@pS#G(xvrj^4-M;}Yutm9|K%16753*c_ZuyRO+!I^GIt5_}_)R1%T5 zCn-=Y##0%bZDDm?^7=J_fJ@M&m_~R;%R@`1V&# z4l*%xofD$^2^pbJ)AQR^cN=U5xOFn@3>`Xp(8*vT;|<>y^2(5Mtj1XwACXCS&UDqv zcttP7g|S_ygtwy0^*|Q!gS=_R1fZP)`LigqX98=d+ecP1g3&z%Gs?tXr)Y9DR|{*W zv{bxaxKkL}u=>c$ulDEe5pBAO!nf;A1IYe=_TII-k>f}c{;pqvSBFP#?NQ6>mL<#b z+A>6o zu>q(`LZrHcTkh}p%A*e*tC-*9rCkxAl^Jj~MF7Y{NVi2LRkm0yZ!*$*K75s%>JAqg zQygvpUXyF4xr_1VA#hs`st zs}C~54GUz<6gyq9<+T)VmU{cB(mUQ`*7HrMnvK46`*f&p#E9yHH~V@<89~cV5d2NH zY9HLG5L?%UD{!f{FlX^>v`UP8h?%$+H!CO`(6xBNjMLpLe>=_jHlcaabcp9H@H%%- zeIqjpNm(O+I{Now#K+zssw4n~&niyW5(p#J`NvJZ%r`i?d8`nBjMf30Ii3Zla*86z zGaQ5CLbt_^JdIbNg)>9x(9<-9G=*AA9Z)Ohznr+NJ+UbD!|)PpyhHA4@lutF)o>JB za%WKip}M}XmFJ4!XyX>*9(spZ3f8$SPYz^eG~c+H6*vvg13mxz;o`rGp)T zRKcGsDc0%peHH*3MM^B8H|h5XXj1nfop~zZTbblBDXGfSUSbtG?{3@z$G>Rp?lXAC z=V71m$P9DxRyQ#T8e&@k_)`!P`VwUU07WbLi)#BL^56`UmIYzERBIccRaVZBD57Ew zO6e=`3M;V4+J{D#*!dI?7ZY66jrYOdO5RXr+v&>V+-fQqMt=wES~OH$IQLo<%BGKx zO9OE^JAy6iszO^JC_CTtKqfcAfwLN`_!K16J4dq7N|BfAQi1_@f_H^^5q6*IwHOO6 zaBvK#Ca=X>wnh&YUNRCDCe4z2NAotGFx^J_qCv_*_9tSm`5SkS)yabPTr9p*Bp3G* zgl9vwqaD;6E%vw~>3atH#zCMm6wxeK<-5yEsq}6c6gkbuie{5{D%3XX5*JlvqwZW3 zXH$q(^!O_FBr_tL=1^D(e#ML)ryDI*lKC$}U!Vn5j0M|aHC74CZlKfOJl_@dwg-7bXvK(i%;D;=!(NMktwTZ?Z|9$pF^&&dKiNveV z@(#h0NBhJoDF#-F!ZJ=!$qt*238Fx1QIzJ}1Kr#VxY^cTK1pP)EKP&J5DfH!$O|4I32hs;AhwMj_<2U1_!~3D?^Y$r7>{Z#?YGcYRO_k;?S_jkHLM!gKvK~*v7ZMo z?dbx)_-g9Xh!Ql%{I)W)Z<^U}kLRY9=YBPv%x2oTf_i*nd6)aUr;uQ573}PEvQWKd zp>vCtQ(N1sDVVK|85s)`)yZ7A)=jSCay7*rNSJlyZ~~JmFma!7ZT~(EbB}Rr0y)j+ z3wzBVj7GWb_M4@o^*?_JwK)fqmJ(z(f8A&&%GKf3bi2Q@!A~Pulv&nD8(N!YxG#UZ zUM+E)(u4yssfT)KUbQTKx?k*3s8^rWxBrHdt>yvGHJXD&>rrrRkJ&64!{*xSHrpg$k#CI;W1?bTRpp&d)>o9oiV3QD*iC^d;3{fB5y+FD8rY?wiTGXPedC zPx)pQlmv=zx9iC??|eHwLvw_`ejtvph~m@TV;Gneohfil6!g(ss?T zm|3LcNPF?z>e!K>@&}XR7T8FCRgW#mmkhf zhcGu>;z3koPmcb9JbJt~RNe#Q7=Z?qDTu@G(W)C~k}N4L+7Zlk)y)t?&I9|f9SFx@ zC6b#Zw=HW^Ug1@j9)qnK$=wZ%pQ(M9q9v~lTqRpzhc2kW+2%sHMDjAFbdcUX1PJmO zM6Y6zSh+U3ilQldfvE4*emzi*q8fSxU3)!$`w)oVtzPHj)x8Nw<=%Viw=Ed8*Z*Az zgdj?9!SAcJ!IOz(csAc`EoJ#|{5L?09K(YTu`UHx4?q*qm;L&58Ss&TH_ z{-!OmXHe-##qP3!Kys;d$9^+M2&Mdnd^ufFFe?|8A+J6)4Uqbeo$>j}d1sij&rh`g zoh?79vHZi1p3|7+SZ#*fMh6k|?l$ir1F-09rvQR6DnzoRMRfq`0)CD7`EoOF2s^oN zG+&sI;^-eKRDO7!4%@KjcZ!mAp&apOdO4kDNhh%N%h_tWrw0>(uwsE228>m*?~g#??E+0okJG z9_jyD^Qf_W%ys&Ni#}zQ)C0jY%omflgXiy=Dh?DQRsm**gh~j~qnQGRqSiW0Om4~j z?_UK=c@Y8)P08e{fkAs}?9s{j*?=;xNtZ{FgP9f7 zx!ZQGSDOy~dQ3L%G3?lKx!TFceLB>zkqjK&g755Buz^TNbl%K&x1HJQt~0@h=x>YH zrSSjpTIV(Xy~HcAXzE2@;AulKQYK(+#e)`U-1l~SD*5s5`8GGEow%#yAI6*dviJXZgBo`pt8R2pA1dV z4r55^sW6sC-6j&fciKDa4aRNIT~1Xby#cC(1XVzkQz2o^L_&1O<6-~X%W*3#s3&Vc z3_Z4VPs+)m$Hvx8B*?h;Ln~}S^Tfa@;fd(-*fW>niK#VvnQHoS9 zU6(A+hTZ2avPh=pJA^!Hj?(RllSmDZfsjb1!TGq`mSRb47d_A%zS?#apcq!ij3%q6F40c?u_6TvJeYAIAEH5TDIx%^4*S@-f3p1^oGYJ*hv zd_{U0$clupN0vfTP7Ql_Y~gB>eBV9oBU95#c0$b+gQ!RfHL3v_)X><1)g%~Qemfdx zoC@goTHyW2s zz*QZ#2^xPx2hE)$?iMmfO~Y$dB~nD&Ck)6SfU`DQ6m$~qx|5jcF{VGVS;K|Va8Y)* z#WU}^P}W*QkJznV<;#pJTVzq=Eckl?)5Yz2OutXK!ys!cMU6+H>fEn^VJN6RR}q$| z9H3RWc2~4J^S9K#;lMmU$7}Iw{v8T?#_6}tSh^=iw1mYgt)$`t%kU44+X z!LLvbsyqfCl==425q%HR>Y9XD#r%BRzgey}#PYO#Nn=ol$$LZfi1rn8I#P_SRasK4 zbyW?$Ah?QdV$zLBMfB*VhM1FzUTAx=H=Fq`&u-^*-SnL)1yIEr*e`m#LXpavss_wz zF*7}CSnt+5Gr7Q{sIb^U)cr~<)}W2!)>C$?8z~vgHvEL5oL2uBx9zMK5fxaOXuG3m z31iAqE1^>_>l$DSY6TZvXZdyKMfdw&_M%U{s(#E)@n5>v6uRK2RfL9M0s8Ar0I`KM zTGTEMq4F|%Co^ufL%iwVn=g*T4I{mhLRoA_V3X+zFQYX)&CUnep!X7p;rzWg zEo|&Ee?wjUSVnv}{QLVFbB4YF``M5kcTZ2h?H+%}bpqM(i|#N0pr+R?Y9khSf*1X{ zcD4)&B7DMid!!#aM`}obFhv4P@wWL!Q#Ngg+Cl}=CZ`ftt(c`ai2cLJ?4$oYCD<8<{xgVD@1%E9Iy3#6ur7|;eW5bF>{+#NFO-{VrGsvnt^ zl#>Ui^>3XgpFRCkWJ83&|1@8BH`7~q@kY|?g&W#mQ`~6Rd2#4w)p;pB*MZ4%M9i1JF1W@Pw^Rb50YUNkRBL;Tdg$c|CMS2qFU@261iVkT_MrCYgYGEosQ zdOsYWI?<|anu7VmFc36PLlBN%^p3wfJ|EOf!i3?_lQjfJvuYbe(UbYWNdK7lV0dyq zIQ@}VV+}~+3JV=yyjSW>G_(2H0&wFTG}@=VRN8R zz&HHyV%!>?^nA@h(ki7TGU@r6gLDefZ^ec{+IX(!pd2HgKWq&cIa?8&&Pjef*)Mh- zofP7{G~J#PjU>f88pSP`?5uVFxz3^pjNVf zT(i8oRFx8bV#33KLPVT>)gqO6zQaH|zWCGUe{K;Zp06QD$7eY2=OfrQ05Y>R2Zx*I zw*(B&bpR+YhW){JZNb8mH3w$cJGngWWlvfHM@@GyKu_BR=;^@#ecmoWpC1g+pV|fJ zPt5`9pIw}upR^JQK-A@I&B1}@Ic+P>W<5r;9SqKwZS9vt@5=)=?BctZ-68U-t?rvU zX>)pgix9aj>F2qcgL3-QSLG{2N>e3+`omAGDboR!0}coCho2%qro%Jtq4cjMZO?Q0P^E)%`qQ6V z@iCd-{`}|WfV}K}kGl4@yeK(ab8s#$&RWU#fG#vu5s*%gn)~DCIqts~?~M;|SG~iP zU6M_r*+i6)p0`3do~Q_`4mJm!Glb0Z$2g>Y)xqfyj`aEDW80z2^xOTKo^qhGuIdaZ zmO4X4XaA%>Y72BdUj%~@dfnhigu?t?eg|+Tn|GW7=v+^5fRYM2?uB;GS`lH;K};3} z`gpP063iCO>j8Xxdftx80lYj{6x>mszpBN)qh7BqE}*HRzzuQYR|`05)X;{u=B@4q zbb*$yQRgL9F4cmL59L|{kLQXIZ_qg&9@l~nzi$aPTDkmu43Mpsy9r+J@TBAons@MV za;j*X~QRt!WxBKZWtD;2pIXFkAv?b#5Tu}h&*tIiR&~f=Y)VH9tYnupX z?*~+kwUQEr0Ex*Wkd8XX6KY;Yr3`hbd4AEWd3ie=8URL`DhlBmbG=Z8^nk5OQUu6o=s|1RI%u4auqJvtY} zHQ3SR#YIb`wq}eXaDnQ>37Q+`o!F&Ywl0>o55l2HfZy?iQE` zV1I!7Gc6I4=ZXS3fNMXoJ(;VDS$-wZLjbN zgbvp}S;?;h*)Sh$Qj;~W^& zF{pZ)!{Mi?BH;h=e`)6XvW)puIa==|(>?7h{3vH2+}nKCp|?7)S?rG`>ax)EhvV(d z8X=*S`f=n`o>+Lr>TBh|bCq`J z`~!EmIAtx()u&u{O`TysU9Gq8R4(HnhhH!1BUcOP?pgo2I;4C+uzA^o0H<8U_h;{c z;&S1GfWI8{f6!w8V7x-B9t8IHXW8-lAh}rgAkfidbl6Aj-osN}t$Yyp=c7y&H9Vk{ z(y9l6ebzlj(0e|5@$h8VOCN;5PZ>isX0Yf%KzEPNhl6a`AF0E?2ZY_MeGm%YKkL2+ z(?qKt1a|k7Q;_3c_FlN%S^gkIzU{pa=bctP2<&lpaPmHklUVm4(BWJB>9fxs-mZ#u z4+Z@_c<%uGFz?;HQt^N~QZDS%+)8yNhOE7_22Yoi9Gr`(e3;S!!L6~AOcX6kCO#;d z2Wr-gK3FpM!fj+IXO1g|s{4C7#NFN~d-AlEYe#@q&gMf}6P&-OsOC`OF*tu|8m< zo__IVOM6M+U^bsRjaXh@(r*beIhzlezi*zuO3JIPSNjvM2k3l@1AGvH z=Zn>qW`8srqLLer>}Vq-J6x)^*njK%^OqKMW=&8p1aw7cm3UCEBv`f&KSgJx`+>O9 z%HS12=#M@g*nMj~5pSApQSU+eMGMqRgk^x$G|60b@{qv5{K}qMIH9FybTv%q_(y-Y zKoK=%67R!wc>r<0sfbUKq#F&M&lZy#!2>j>lqr5IQuRLbZCug<2JYYj2L7+fIeP%Z z1&rmEma~0(dtAx&2Al}zm%?KQfur6yI~(`qrJ(j55I}min}@Uob0U3()^2xb+gHVz z_Xk^mhIN4}iN}(hxVjQu%80E~upwk+^fY4o01_)IDSc^eK>=3^r&zf_gcg>r<4ZuQ zb_E#jLCWgFHUyv7kKa?7RT!Vo5>Un^_8MOqUd6`l97dK{ZCEjJ4ck)q9+5m1^wX) zTrHU@5R^A45J@TzG=l|Teka&g0?nFYOHlf3)BwoNKVyf?nO8LPy$1j3;X#d zPFvxcUKu=bYuqXXW&3sz2&MQc&N^BKV^FL7G+w8fr3x+}T4*sN~oR`RiYYUI)NVl~-yj&Pj_r!j#CKnh+~2_oXU!$YBgMg_Qxp^-QM z?z7(b#ra7__p8r`>LMfPubmI#7v=Owdrxug9M|O$nD8a6`PR}MXMERtq#F8&%%qY^ zp6m$ia^WlPHv7CRLs=UD!?A6xua%cPE~m5dimv_sK^9*W;iOu1lYVQJXjA_3HL7~> zTPx@``4Y)u!AAKqdMviE^vMBhE!|?e!CHE(zn0}dTGv8twP8VE{X#KvECX(KEqqDT zQUE0ja^Lu9L;P~`>ajk`v9)6T?kkqU(Daqe1+xa53Czs+^fh&N`DRP%;l&j@=7}8$ zX$K8Te#Hg*C!anEUr7c0rmH*yQ@$nM56N*hi&Y~6_Pku;4(OvleD!JhgRl-j?-xC- zKu+|lMUVJ`@7EompjprsyM}lrNuPA)BAxp+NYbPkp$Ap<@FG!lzb*Ah7MTSM(VD7y zb3-fY;pr>J`|d~at8BAxDNo>5)mA^cR?A)VUC6Le6s(mT8 z`t3U<*0`9OJ?o$LP^(=25<(O_x?-xQNMtm${&WkxwSLv_{FJY02B)tUZ;2mWtFi;W zwb=k|6z_N+U#hafy}Op`K;J+o15!0Qor-cqc^PyRJ2krYdY>PJU$pytke+`!XuW8! za(BI|rsPp_CiISXSCh@un;|C$r|+E{5NQP;#ZC`TU(s#K-V9B5j`X$TjohP{R`zXo zcQM+hJ-SfSw(Q0A8!7+-pm6EI@^`JE7wSp3P%nu>?4Q&Nd*w)fcS|7&G*x$L5^16y z-I3&;>F#pe*Sr~j^H3l0aso$Nphr=ok?HGHbvTbMmC(@KrC+pxd333k`juPYP$W3zLDKEQ8*mvQ)59YGCU+ZmA*<*v9wk^i&BR@J;?2XO;56zL?yer~ z4IW**Nh@%7?P%-o=-M6xv7mqdWjxOC^pKcc*1alRAxuam| z;gL<@R~L$HxLr8nZMUN^9M)yq1*4*?b`*{SnrOQ~MB7hCL7UaF1dPfKy)G>9(}t189nAoA*R^ z5pgG~mmjj>@R0~7i7>+SCwAB&-tyRm*-TLz-h1k3?7|oAU>ud<-$TP<7Z+2hVfr7} zrn)ytGOxI;gB^Z}^&|E$Q2m0N395!60=3mhx};_Vj8E;OGtq5;A#u>TT;^}r`4rC$ zbZ~*<2G`10*W6E90_~hf1}3Y$B^ERh#H>s+7KM4rx~He-F9Qvt>46Wto%03=poC_( z+TddP4rMeY@cUEMhTobX8UFDQML>AB_as9k@9)9I3QyErE#6T%;*xHn%{u(H;%2j7 z(;rk4BpW}M;8dJGgjIRD3n=VNk%m{7s(((-2dCl%B8#hV-vl@;fzsp0sAyf%N%vKb zm(0-n#OmH{NsBjE2>f#OWd^4M-XEdy#t`|&abQQLduAd<_0D{2@zuHPa#rkAOnmdg+@moulXz9l8 z8sVlL!pkL4ui?XPZHis4CVt;ev-m2gDtp5hXeC>+-#fkJI<;ulN~`xOl2vtfFHo$d zPVQB3RX1)gK&INI-}`2&g=+04bws~+$Y_yTQ0ZRh_YRs~sTO>ym-)SerxvOOT^mi( zs|2B@MW@PBnY6T9j*}>2nq3Dmt1MDAz^@^D3As8kQGeGEKtoeJ{;YwRW!z;==_wGDCTa_@g(@wSlFFWIlYwD9BwDNFKV!HzzaU{FGp z7ymeMty<_&8x876fZIvpmb{CnV9Fq>oqycqOL_=3f2_#%m7d+ zqW-~X1eQ`PLQFQ@J;sZ{cvyD_{^8BT!NKEgzL`%J^Is=d3%o=NuClN2KKaAPzkF~# zr%QFy1)d%5JfA&Vp%<)$jD3@t^@)q!&FpEBKDwz0Nj_8ybvsi%XKwe)R~c=kQ91If zyVcD4&_dP$xosHWEV%3U&z@(`PoB~xQ40p86J6|q-(t7A!eh<(rbq^{yJ{=tf5ne8 z-cb2b+2*=y@vrEpj?TDB7Q^w7oD)4#a@C&uYQcRvjM}ibSC}Av%jEe<_U+k)(cnUW zpgeauU9`NqTkEc1w6WY7?CXw_s-lMT;MWrok|NfRk97lz0*%cRaPA5-5ex)~~1 zev@BM=~;u$6J~Z7gvm8{J;!OyX8slptVCy%-Mcj!$EZoL<=haw3Y(i*aSK9hA7CNr z!2j`&o$>j}`Pa}!H_O!~&(KD2xdn=_0CZ#~KAnB@%{RpVx|=|N|2NQXA(oJxaVE=~ zg?gyqYBGIwvjKr-iUUPMmjDQV>s(J3TWau9+~E%t4x-JBBDt?#+J!X;NmwqY(1Vlx zZdKePmPx5;NYamo=NIa#?kBie%)Nwmx3K58tHlgD>a$P3u*DRgJbqFGlI>d`1`Gxe zj*88fv-vfdd*9b8Hjg9{yG;FtMvEW&p%3r7W%Bt}tD# z-+>@#FpbBft)*t$UB)`%6U`!>qwQv@KIBE|M{gws>EG|ROf_`lOfc_RgNI(S6fKs88#rk$)VIwhNpv(2Bgo+1?oh)h!rLM|!(akKI zFRxehf(h#yn-^TlUoYl?y=4%Ihtm+w-=aNfZA1lf<)FbknwCQs^=YcXHl|{J-ON;! z(Vlnt8jn}J4Uj~NKY1rw7uecU@vGuhX~eZHgX_e>4p~O?k^`-!eMaYDj8a=u#X*b( zELdm)mLx4jN}Ci}+htG2pV_M|VJhc0UW;PT#q0b5Rx=zpdkULu9-&YU zi&O+YOB_Vc4GPJa-%6x4Dpe97rc*$|q{X(AYVh}7_P#B5_}=7KH9bDtQ4z6)?l4Dz zmk^YFnM%8c{1nNmq)Ys_1WPAGsI@Y9okE`9q=jq@LD&(wr?AfzLly^wckm*XH$~P_ zE&C_}3^9h~Tyh^|cXH+@DEs2POfmjiZc3WfB%cake4~60XX_pi0QPQwqtMh=I!T(B z)zF@Tjv`frt7U$Xy_Ig(C!NAq?~Df~f(}I!#Y|zLy%;?Ad_bYmDM(v`1C+!lRRwCN zYV`GFk;6EW$7i7ipUiXdFr}aHsgQjVZdQ)+r5pT-Nx(xyeTN4E;%f#M#MMlqi01Jx zYjSE;$*kIf)w`M8-A$%cC>wICqz^G)uJ^l)f2v)H)qbZx1lay&yKqxjx+ND;l1O1E zS;GCX+5fj!cZcjhSOz}+dbN0W6Jl=pR@Qn2pte%#m;1X+e2}d+DykH$&J;I19!FR# zeV-=Kr5WW$-wUEprtA6JypWG9nm(gp1MH$S6_R@sWDCf?Uhl51R&N7|kKOK?zEQn$ zLk_N18W7BY6RWJR@;lLA-Tx+I!sw)poR8^0q9@>r#f zK_O6po|oVhMO@q%E6(6=ceih@ifi&Jacu8bj)+j z5Di3gqWr5$?t)NWZT8#SA{`8f{DaDwindebL(EK+v#@!$Zjz){4#eZl?)Uv?>C6eM zt~=HR4D;kQ0(66y#K}!Qm9gt~o#T2&8nYswS6oKwB5g9TH42pK$aVehF5lePiFDco ziGZ5s@N`!BPD%ZVY9q_mt+AES_0?vERm=E!w=|~Q-AoRNDRk_$ z!=Vg^mqp?dkvd0c@p_vpL7=!ocng*^Xe8WYOJmcF^Wh&x1+13|o7j#C@`9pXOQ551Fe_PBU)k)fRa^QRtb-)tsV zZ{UEg-iUO-?PNKlBT@l4i~(YY31PVN-) zybY%i|NT$fWX8V8YzMNjhz9co4ENS{;%u*4hJZ@?QX|5$fT6-};OKZp<{_jifvgew zDnk&PNErj>%5n}uG_$*%PhTxjmR3S~{e3`uJa)9sLPE$X_BI%XC4<noV{S>{2ap97s%p4B~%*AV%sBuD^405+@AtFq4En3sppeW z>e9vA>=oxG57;Zb3)wiAkyAP zKU|!Z66fvupab0pjgVX-ZEYu?<1$dfQ#|en3hIjXjkTx>;?#LwS&*hDT&<^*>1~b_ z(%l;3&qtb}=%uhV)`17Nd@9WNulX*!f(d!G0OLLS`FOF~?l-tpLV*JQ0VMs>2zDOg z?xL!bQeeZ$K+R2nbqe6jw;33CzTRbw@GJ$%;v~!0ND3j)$P2?&S_Hn*l+2<^i1>u7 zQZNcLc-z>N<@Nk#kBk{*e1K(%5~(vMy=l7NJ|eIndCTcyKg%U$=txw?DCG-PT*eaj zV}2N&j`0HR6mj)x0|%>v|6?HOANsua(aHJQ$!fa4qf-9gIwz~UpRGSfb1J0%;q0`x z$mtij!NAALxF(dFK2q(xS&XGto85@6G4b?|R#*Rmt75PCF(V;R`LDJRnn~>CMasli z$340UPLorJd&T~H_3RjfGw;SLP*`K9md6Q?vMb^e-7(*CN_mP|-ZiPalWOI9h?7<% z4x*ej{U?Ivpb6Hxu(Zc#urj$J!K1I>Fe*`S6S zp@LS26gJ{^&J<~4p+gkOWjv|=gdW}N=z%x0Otg}KRqIO<#%TxD8U?oh!v>m0GRlQ~4O5_lI~Ch-iH zxm73hC9iDi2B`*|C$ZC1{z?K+9xoslFb5~}R~3%nWH!sVUuDn*ER=uy01#Eg^8CLY z(!D@1Hx9kr9;_OPPvw3yQ zc$#4qbZ@`->@OJt-|4IM9*635I9i-f+8xBKhN2Q;IZ7vbrjv{=D?)t!`HSUFW`l&!3nP$YC1U<0gnyDX*X;DLRtgMbiu+}uS)FWb4G(1)NA45PS76zX&4 z^IkcLaMgyHPWe9Rd~_rhH>Mf3XY-CaSrbS4Or{{7&ey1%$tH`Nm9=0tOqN(84lrEDqbXUi2K00FD4RN%CutwL4_3dV|RX(>V>NB>6qmH6o z16ry=J4AsxT8BK~f+)U*j<|m3ZLq?83z0^`VuN_XQ6l1daUG4e6aL8U9k!9W-9j&- zkNfj;yusY1OXzV+pd@L!-DH$>F{&!05?mEy6vP$@?TB0{<>K&8QN6hwq-bDRo0$Lp zF*_-=}Y$o==&!L-tPb>~3-s+=Vb$YLug& z)rV$7B!EU^eP;AOEAbCMB-21^t8O}Kk_p}l_*;j*XKxfgF%HL*FR{hqhe454+E2$G$@&^aNBE}?`Ny*>fH`E)Oc0l;t+^f&6-3e+7uAwHbr4G%WVlf zTq9@}aL+B3YLqHbu3FFsE;OE^X2ct*0}HMD!rLf-62#>X(lIwP9wtrkW00s9?6HsH zUKyF$erS+;*RQ7AKZCu|3r>?=`ds$dunOlr6ZP+!dC0lH#?c{vH_MSK;O9re6sI4O zZqv5cv6vllaIms}a#Tq86r2oFB5%-uD)YPz;R@1tL@o0jf|U!E)BHv11UMdYu+cWi z6WoR=pvc|ORWkfjx;amtX2RXeb}MmSr_9r_2~&(`Vm>qA%PY1BIr+f9%w4uMuVf#i zd;j@MfB*%$&u;l>aW5i8%~8h5!a;C|R8EwLg#;@G)id*z8<}iz+YOO`=PpSUjQav+ z678_u(eu|~-lSPI1}YA*mLkROPOig48($?=j^I8x2eWTrm>`yf|sSks5O8kzu4WN$l3)g zz3(rwi|=|rX1(Lef-$u?g)7Llzs^OTCQ<@WAnSJhYVI35`b;vS?IaY&@|Lg%pfQNSAz1In3+TH*Dv+H<@Ng5M`h{$N4E2s#%y>+yv?iUj#UoajdJL6nVtn9;k>Cb&!s&()})zZFduj z3VgG>IvOy(Q!t2v*U&-3d-UL)J>rhTI;lN;em;2mv2$U-FTRwAZz|lSKvj!+&0tsZ zya%notHhX9m;*;qlc<*$_bY8hX3tL=Hna=Mb-hJy1M!07TaG5coya9}bb-ZIUhcX# zI6kMebv8QdpY`PLEcXwi)fOH1FJ9nKe|Y>f`xBkrljbK{**DD^5J{J_xYx7)dlN~% zBa$6|du&lk-HHq=1AQKJ|N4NI(xRioefvDhBx{s1PdkuOOkttwrH#t`sRjZhT&o8a zq2H5e{NB)yGkvu_^nGO4eX}U9SW=`f#o@11T}Gpa4p5Zg62~ZXWTHM%hbRFP?%1TT zlDdD$wbK_n0SW-G~xxW~q5EuGFa$ohx#pb_ZK7&vQ^_y4!~$ z&2cU{8hJoc1gs@<)ubiua z&Q89F=zdFGH`I&98}v0!I7Xv<6Z@D7UyJEHZJ-PYhM4m*>*tb3C10TyaaxuSQ)HUF zqZ5=81;%lZcoB&LBTy{>qDk$isHh5waCWz#z1}nZN>rdNQccKepJ4IpQ+S_4b-}J8 zx$;;J=h}Eeo!t_7CKuuX&6qB~=}CbHm?@-gQ?&QpENhZkPqGfG+;6+*tA1MPSW*=e zLg8@Ltf7s$EWg!}ka8E2OPVvwO$i|uGHGtw9Q)>*-GaW(Hyd=a792p9Rs74Sh4y&V z)vN_TM2N?#RPkf7m8`+k1`4A&!>J^yb^J3fc8t4trt-v+^GG?kb;=wdz9r`h#Yiw= zPBKEfA7g8i%zVg*!cdk)w=AR(KV$1q-~o;)#1BMJVdk{xZ*s9kU)=FF-UAm?qVspe z!!^>OI_z%D-i7TXVkDP>kdI<*vgP}zkV|LY>tEBbd)G})^x$PQVEOx zA}!AxPy?Dy+uOUtJ!?>h<#Ea?F)Vm7Rx7hY^_04{V->drq_7w#oJoC5s!*dQ};&&^O#Kvo@~Phc0`ZcL3jA0 z{9NccG6!IB<-gh|Zw6{HpA@8$(>3CJ1};o5Aw!*`Hi5N>t%3yuGvKL~{N)whV)E!o z8L)*#&Qj1>$t95&za*7c!EO?oI05emI-?B^C#tlJuKrQnY4ciKdnf}N)uVxF4@W@Q z8-hO_T4|#Kz*=)C(CkV_l1tpd6N2Zz%Fc=HYBr`D#3->PQ==1#x2x@r+%e@N;Kn0l z{i%A_WjDXe5ftI0zkJ4zw|@`ylpHf!-+Pa4xoNrDJr;*K^Ixf1krG$W>$UC_ni#JT)%p?x zB~We5DLE%tVQgG`XGOsPY*SMJVzL5wJ}A*dN}Clg9QQg zfTveyjq2U4z@2($l}MtWpU2KLEqf9Vpha7 z@h!L?v$B38@?PKzf~rP87`Rj9%2hs*Rk4$B zR?5L;$YjEc$wRoP$konnS1oq<-oU{~NUym0QeR|0B3F(Sp9FpYqA$;a$cCO*jT2fsv!=c1}vqj?tByQBT zWG`>79o+H=U(`!B3GqdH@~B~I0<*(g0bjG)YrdQ9?tCZ0ywH$lb$O1skhw~(9fyB9 z!!s#0vyC()1gYgH9Zu898b^;x@hfd|pqjA&tgy&(^$?cEHEa(Wi(J9TMx}EEcN%JJ z*Qk}%VPfRuhM$y{EXrnroIEO%Mn;q8fJl3{Z|x|?U$Hu`Ar=hNFA)HXC=DZ%WlXDq z86He|2|&WsP_)&ms|eWPlrRCWTFy7j>hl6q^KR9Pf8$Y7d3>v2xJTG5QYJ_maF;KB zabIASkBJBxnl6_nP*AwX)7WarGTPo^)iP$S6=p5oI+45ytX+>3=I8^vl%9GujMrxJ z0*I;egraH?@Kuu!jx8sG!nC^wa4mutp-ytt9wazOOm+|~VbUovE~paqg)iUCr?pg! zBBibdn!~w%ouNb+Yv^N0v7Smb^6OQo4CB>w4`X=|NP%YEDVFw7d}G3;lBMr(rb*YI zQ5mJzzn%CAxh9N#ieThXk7e3e)k2~4vPT8=4X%!guXD4?`8 zsAiaYF6*^!aT{TWmx9cU%RJ|&hII*@TGV(HAb62{D!E%$T`o2h>O*6pfuQsSX8#aA z#)sNimLbFnHX1SdJha<@IrL&;UaO!m5x?TBX>?@nH03e%7fvHAvny^afn9N#fp6Js zl-*KkDVKKLW|0J*Cl!+sv8Y~5(bv`i@wLi!+NXFK>lofucvuEmL9VD+hzF^6c$FVO zzmbK5M`#Xloti?n#{JCWkaqQkTkz2?qSLgsdW5J;MsXL zI3J*If|h2y^NJR>RH1rhT2hOe4VEk;z7+mm9 z6dtyWc;dVv1pXt3*V;$TVcDoA7Eh8fwc*~;3pC7QvhYB25N#HHDegCSwA^QOtPAb1 zM}?pqUyqc?sTZKo?Ll!8jYb>x_!BNRO0)-zkI0Gf&MWnp^hy$M zqR@(@FjS||7zq@(%1B3Fqqzs1ul9Ihc5@KcVhTkla@X1YX$@<8izw1!X3`MHw^zz9 zd(y-YWgM&LwfMFCg`9A}N@5ZCrl1>QEqsK6lN9w;TocL`9Za1Wb~SVX%-SkULS3T7 z+5z5DVIflcvd88`t0i`|SUoIvnLK(k*yJGb8q>DP%t}0}8IjnQEm`y55U+5Rvc7jS)^j$^Lnf|t% zpxILDN$WFJwORb;E}z~OKSj=DLC;=z@#bW|yPalpYIz^{=GWjiR5hgTOF0{9J$h|O zQtkqHSpQ68oLeLREy)mUF{*t=qbEG<(A?WIUXAV zG2rY}1?AmY%BU|sABr~&3Tq@I8w?dva7Fls&K3*w+eBHYUj1VyR3UT zeo-vDSGZMj?e774wXMhcj$3hSW%<6nf2zBuom^|O(Ez@`29RAZ69rCXi1tI6G5 zhy~={H|4sD-`C3;f(lyOi-biYuxheO5DqT0nSwKHa%9HW=$xC!7E=? zFM|tVz#HR;K!c{oTEIfekK~i>J3m+t$niIH zY`mD?%}EhGwy*OPK1AQn{2ISvkvr)Pd(W~#@B7}c!bmV92?x&O37c{WjP?HzVU)6y zHq7P__gSt0zge8-yTxp?Q)Hf!@P<(oui*g=*nBWP!^0L{WvL`j^A~iNS8^ZokZOR$ zU;dpTHaSEEO-y5W(1cY7dM`2i2$J;((oPXzrB%u-1( z!P@N>ASKbt^pmRwE5&}OmCFc~0*WG(+F+lRNJq-83}mF$uIivN;8Kgy=`t@>imFIW+}zAoIC$e<9^#T(K&4R62C5|}J<->^p*BQ1H>2?|8xOk!JTp7) zpAXE-jcmMjUp}D+h`##ji@)e}nJPpOFdL>*6IbrE&jL!Dl$=VW@W2u=21iwBHA#S@ zWhCT((ycl~DMq1&Rn)<1n$fo^S9%3`AHw*{$g!=9W%;Y0;^0UA!q$sAIV` zX_RT~l%X}%awX6b`Y&a##h@@EW|m}D_FXVlp&CoEF=;7e<@dNBA~seFh0!)DF+D1; zQZ9{kKqcV>TWg;}v$YWSP$ZSY<7U1x8WosXX_(@Yaqh95(V&FePFjK+FA5cf(i20K zG5PaMv5zO2yra{XiOlhXEoriO z54x_-A9MzWH}_E!{Wd0*j8BrmJ431Acmu58S&oo+6i{|O?_qEy5$ z7W>=ym5I+oBCI6i{yZhhc5tk=rH2h%N6Gkn+VcTZdbUM#TS8K%QL{Cc4iC(-y%C>V z@+SSSBuo^s%cW~L>Setj#=XHw?<7O!=JIr`(f8w30-HTI{|gaXSzjrJ!WVp1#(%7~ z@cn9@luF0KTa*mrAVF`dSlhmr!;3*~#o@5IuajXB`LSh9OHUjwy4AEP;6YV?F*;ay z#)Q_wGlefy?Ae?Oicu=1@}R(Pldl((DQ(~b9E{qFl@U?x-+K%Iwd_i7mElW`Y_R5f08rE_O;YxY4P8=z9BAGhHvBA&h*E%iOgwwT;0w_EG2t$(Kz)L{FG%;qZjtnZu zlF8^>EY6y+qPEa-EpiHt%?NFecxHpueY+XXz8G-G^HB)I42>C4a-dv(DwKp{c!Lx( zHgOL$HlP3D<6o!{Pal!Eg>vj;vGcoqx15$@XF&P)o?aG*fwn5vHo5qe%)0g{0>>kR z%hS{P#@E)3rbm>k5)6FxJtt6IT9O92~$kh3J=jmskefDwZx8J-sP(_i{$9CET!m-+Krnv}m z6B44bl~SPMOfgZ5XMuJKtQo2m##CaHVm0m+J++~(Sh}0ThQv29+Oa#}cuyq#*`#O# zBj&AfjwObd5z-bl%R#e0?opbjc)BN@HFgesM;LN+7_+dm z)mU+m^M!MAwF`>nnm8@R>Tx%1rj`ohWz24qwG}tJD?%$i1xDgV1)mg#b(&07>5P?D zVp`EX>vhMM!(R47Mz536#~*h-`bhtdAAJ72JH%tdz45Sz{^lna!}H_A^d9A=H#ue6 z@ifp1ef5a>V8qcCd_gTCkuSr)u5bm{;t9=S_kc`=X7k}K+vhj}Y9}l8Qsao7DQbo4 zb&e}4O4ceUq*pE_jgdd&mZ{IIB&@t2;H6DX5=hKHNwR#z$or9H9aC~0$s?$7W^LD+UE7UXl zWI&d5y_uu@T7*oHRe@Pq0T1gEnJTAD9V*XIGC4Tz)z4qDg|v*g$wM!~?QeL<{9E)i z-ja5TDzjbUs)wfMp?5~CiBgDQc|s5Y`-sbUJplyUu5rK(D19nr%X#PMzhjMqA)R7r z5?|~3luf<_?*4y@DYH!OYV~4`HH*>VjU67Y zht!Hf`H^)CD$N9C6e-iTpn2h|23|>H{AC@m7GrV} zLs5#lP%o%<-3CV*UTMjzc{nA&qoqPlKWe!)38bP6i-#JE6I##1DMZU`5scg7r2egsModaW_V|j67{ypAJfuKKAyHc} zDbh(-$BTTn(+RqWtFd*Pja<$2$0j} zXcaS~#;J-Y6ySH09Uf*zdW=q-{4d2wyy&r=+}MMqs$gR&Lo78^ex*vMFllA5pyC|5 zjjmWuUi_xe%YaXR8F+Q>K>b9*X??B%v_4ai1>$nK?{zlicSB%(Tog!DI0P;eC|kj* z0O~=>?@3=_7j&T$l9NNe_9N;EEWUO92I~vO?f5~RlBQzvpS5fPPuo>aX7T$trPNp8 z!^d$#*Xlg!40lvb?j?bw2KZW(W1)9>GU2qh(y3BMy6qnHR*=whT$Q2KNoYR{^iWhS zIT*fYB9@&AHzT4F`owIl5pWeTR$3R13$?eR?F*0BrrCIuRqnqxU5YmCxwmnJM41&8 z38cb{oW?k?aRr6zqQJD#tCX2&o$*Mg{Ox`lN}k1UKIu?0KVRZaK0I@9G1=gCAY7OK zMS3iqBbAPqPEEAKhLV%xNRJ9D^=I6-)E!gdW=3X4EY# zC3WG@Hef?}R<(H9uD1q_;)z4Z^+56PeaFHsi_@K6y4#B@zOE}C5M_&qmMh@0UGR%! z-9l$DI0=zqlD=>6OL!G;$!W^C%J$3>b%|&!Ia*ED&nEDyJID&b1=x0e?!BGn`~)5R z0_xKjYbnXDylP)SYM<^d%+O&&vAOs!q)UA;p-0@cuYEUvo6kB&vwSz1>()rtujxjQ z|6|dLR{$+vXehL5EW*57jkp`)Bh3ZQAbp|7kcCxU0u2-nC?PX=6W}FX3(X3neDfL| zAFIi%srP0(Tj)k5;$Ts>$ab)yZDVsu|EO%dDKkafRFwvh?@IsiiFi$XqD3ma&;B;k z1sX*lZ|g=#cF)+$HFQz{oy&@*s@Y~_0*nr=G$xw3^So!rLL5sV2Usmn8tW~KS{A1O82sH z63;xS4)2zkr4FnE+tljaSKo*Sd)1vQ{q+)RD?CtrV-IxMSCgJS*k}`MO)T8l6x0$K zKf$Y;M-*>UMFUrZ{jEcNQNdp-3NO-5sQ(1RYuhNs#I^8BZyw2_XC2@QfbRC&-Q^Np zzi@G6NmtXj)J09f*R+MtWIIJAL^2zHyqLrLOaNZ*(tUaj%wSPnix%W4&(j8n1Wmgz z)y77uU&~VeChCSvoALP)@2-d~#f@P4Kb@tPspi#w7x+n%zD&W7h1@)&1zm0l8H9)^?Dz9i!C+tCiVE*4fGkRawa-TGm~B47JqG!cvZZ6A!vou&Xvz zoQth+57H2Cw!TQGzDEF<08+BvBN&1X?+uRGYACJ=X&okgBBjZ3gJUI+XGkOllrPH)s;?NmXYJXTD_W^<4K{2wUOY{%JvjZwGYnv zMZi=gnMGNoP`Y$IEGxs zz{6*J28Iy<2hpB@G`2mw{FN^u(^vU5PWLnM^cUzRUA;<@7L)uo6v7M0l%Ffjh~6+J zC!EXOo{Emew{}otPlaxIH*rU?AVww-dmsY^wdNF!!fegQ2 zQ3l5CZnw?^T84qk_)TA$R4%-Y5P;gP_IMJv__$pq)otil+rnc+B>>kXcb*{Q>v9v( z4jPo&3TO0WnVw&gPs&M*K&%hrn{BTGIj4mzc?s}qO~~Qb01xQe(#m_AylYVzfw~WV ztb?qD<{GtM-p1QhwWq?N6D;5kaRB;SD@Id1#VAtx%c7o|KUM#rJZ1XIJc=i1Ef$cE zso2&nx)7TLD=%QweaXvIEhX6J?Zz`oxe}pcd6~mQpY?rK_C^c78y!&Btgl9ZT7f8#W;B zQ|zm_T&b;6PN0WQ=ezwb&oqO{Nvu>0KZol5s<0st;^?LTv~0Ux%u95E7Jqbu*G#X_ zFpIH(+1S|iOlRK?d(V46I8F_;cmCF>xyaNBj72}Wdo!QyZZ)OFC>gUzg~s}fe`eeP z8kyZqHm`L1v`SEHG;JwSs_fNdIVr#);OQKZbpY8u{O)_4CN*9Pv+Y)k)tf{81snX> z6Dt=)AN#v}GoQkDpYPsjPEZ@q`UcYEyyNAm zCDk(iHh&9=6ZwfyWRc*du&2-2O=Gy|IKfkZs(PT{VHB84`ZMhnBTt{9Nbc4sgQJUQ^$)Zc|r`$_Jvqym&JVw`{ONB^L@FQ|Q zUs&JjAcEapqLZa;5+UaFe`=yd=g#;?Oy18hFU zO!$8qxc8$NsVTKa(nOdxZA&x;HdSAse@Y#nY}~+wT%D(}llmk0%sDx2T8Zd8;_|?q zb>IJ{pD4yK{}#7W|E?5~o=4;{=rGB1TWv;c3Fc_dM0gpvp0QsVkF$KEwE`@%JaDu3 z#HO`;`227aQYl$-rBcbNoB&uLXEnhCd@^P*21b2ijEvats5`Hm(ASgAoQ{x9>`@vz zqw>R!n$cY&$bmwF^STKMN8N}+w60GP;-YwO&cx!MZvQY`w?YD z@Q0?E*tjTngZqnHWV473_Iw!##Wl3)X!tCdKs`4NP|6G}*XBVusJH}@*`XH~QBaQ~ zO+>v`u@907)eDp^Y@HM$-n+OJLU}Nv{<$gT*r9A*42NpjbM>D2Kwh=;AKOD=8!i&8 zNPC;3G2H*#fvJX4T|D%tkuS4%xU3AgAyZ`*f*dmkCcfO^w?Yk@*`p?t(F8>^*cR2RK z*L2>w-ppT5c6mor5LG(33xUch6lAt=A`O0zR$0K!I9@IGcgw1y-=uR~MeE<}6ZNt) z-6^k2Rcp%H5*#hy%+u8Xfy!Ij27$E-N~46ai*CVnj!QCKbS!!&fRI_X(SM%y$Gy+9 zZ_nvPT;dhMG5^K?W{pT6!d5124T~%dDBBL4-{!5bT;)o5sU5lHUvrPY^#QqQU&Fa- z63glCF}*B~!z(o9=3~Kv=sPl|?@olTQ|P7G*NB!pI@3y_68{ zNt<_kb>zF8%3BUA>EEqpD_YM&YKjHy%&0UgfYppu$wLxxR{9Sq?)~Qaa=4 zcT55qyjF6yc!9VDX=U{h(i(!$#$3pXCQp<|%xi0iDpP?A3cLOiPqplZt2h0Vhg!0? z*{n9lIC*%m1^EJ2K5KPhA?KkT)s~;=%WIx(Zyo|yWXqN}?bLNv3dYrb`)-U39tuvR zk()1&tIFZ)%mTMuZ~%wI+qKkk+4)(2oSmM-`QrQ9)ZzJ_jNoE5ne}M@sZ3C7CQ{5r zp_XQfWDW2tSY-$5Y;bw@ZEx85``gE+_(&Y&n4Z%p&H-mhntzs;wb0Bx_z@8m$S{zgU7?A2m>XoNVrq20y&^Gc;++TS@j$nO|6yw{ggeN544NclPrrZ@l-a!?1hgy&b z`XN-@?Ke6iwykxXP$#{?k7=aBLG8OXh(#+F$yEb0f3JB$d6hqnv|$kbm!?CUWc}xZ z^I=c_ILcq57hW4=6RQ>pS73el!&(F>o4kBi#I+x;%pw^{XE>2d$?#wTivDOQ32&5! z!k|8;Qh~Q^P|}8=NY6Sb`<&>^Tx$cIkwsmi2^Hr|Im@{F?P(%^O4_oeZIQMNL6Nov zUbO+PryZS<2NSG!cF}+%clq7Ab+#O9SZdJEjA_Dk(IsoL9zoK8|A>;UGogm1CM5;; zHl}15^EaU+4#S@JhI(X*o@A~>P=9lSmODbh9^~98Nn>gXc1wlH z%UoBo|0NV_%xfjfB+}}nciI~#x-X&~e;aZsR!xvb`NLW=SUPzsNrvaO{F51ua@%uE zPW0+2u{Xzn)^I+UOs#nxX7yAuHSjZ{i`3yJ%kE~$XD$Ch=%k#(80B!sN+f)4s6l6Ex=Nb zicNfqlqG9(V!CHx$k>*1VGt@Y{N-#|-^Hk0tQP6&^Iv<8tiYtyvkVihIm4AMREJquy|=e;hTZbFTA|zda~C7po?yE&0P*I=^&sjb+?aUJSd> z&${}@QIf1TlbgFq8zd2{CXht_uog*5C)ZfUNkT=2`lnHX(5rxLkb_oCAO`=e7AZ<5 z*4V`fF+!YooG32ae1WSsZ4g7Onm`Wu!&(F>ojj2w<6(C&>K>0({Z-}B2;aLDM=@;> z$67yuLiVp~k;xv|IM}5R300)^~f*CLZWu(6UE_G+9{Z}QfTsO7o|^ijX8MH@A!F; ziDhFsSp+)l9bXPd{qKdHN-t4!$5jSln|!)Q+w0e@SUA15PqPZt{B)t2rxsDoFpI_X zZBFN|CSB}Exn!+x&d3^EQ?%XIRg3C7JaEh|=y@Ai$4+e$={-MuqI;N#h9>-lx{xj} z2#;|o>LE(SuK?xulf_>jPP2la?dQhbWCIo*w#?F7gh-HHB&$NMf^qB5}y89lmVUV@&veok!BIfA;IY-mMs1*W(pwKlU`l2L)MUEkm4^7^43(>CUx zzi6`7Cd2v)+x)bI5au0Odn4u6wGI8U`9d|&^l8a^9PNb?r*?@t5n4RT?1spCd3NO=<6iFu4PS`AYb)E@;FN8E zAeb!;HXYn{ahC9vNuA<$qKmZ)j_EjbQo18)1MDgXzQJ1tUgbs=`0tL97ELjWn!{b1 ze39tJDC$&e$a4HBH4sKGAlxPBP{&ioi>`AU=L8c72!r~WeX#}}TDfy3dra_-bwqgU zDkr)?QL~4b?^Dy8ROq)UIx@+Acvq5u|9f1=fs1L?F=7mO10~#Fi<{ zHT;I1Dwv4&UqD)O^O;Ew@&DR?taCN6Tz8y0#3>(;O_q2+637Zx{El5^_RbGDiXZSuQs{v$s(cB zzIRXrG=mdM2*u{l9vmlZ;|a=WsLfPIH|N`SepVm$say5+WJ;b9o6Y^zVm>vk)Ix3f z;H2e57|`THxYS5)e50oO39m0dHLajX@sV%t64vY}{AjV%Rwg1u;TnFWo^ zRMRfAAkb3CWh6C{)Ye^Hh%O@YX7VaWPpTI3fr{8nR&PPSUlhNsiSUM++DM0l|MS3L zhy(Ly=t|zdyW8`z`6Gpf{-kpxUluR$i=?KHoHeUrV>7GzM9=zlN3B?xKYhPNN6Q(= znTgef)kR|uJOCm$M7Pk=JIlkW(3HkgE9wLXG!oLmyOmbEd1n3xk4-iIoDHA6ealOiTzuoWS@HrqM9pX_(Xi*FiXBH!VoTo4p}Qf^8(|VJQUh&#$kGM@%HS zF%_ug2NRslr<;}N+Nqu-qTyxwEvR-ieJ!krL+E8}{ar2o6|@&_A{rCp-4DI*)kn^rUb&~=ufjZx=4u!TqIu8O&nE(kp zqLK6Km-rh*e$o=;#4T)P51}-PtG3^^mi0O$ynSiQ*;1Lw1VNcL26G}_IXCV^PldCPB4Zwp5>Ri^@u3~zS zSsWB$i<(JKghN6FnsSgrS$m}wFtR~$<6x-+Ox@m z=%3Hj{*3s%N_VI<4gKlY`ePeGjS172|A)+;CWc4fh^DQeU~S|CFLRS`4-aZ`ZsVZn z=e>BQQKP+C&`!xL6aAAl0tACfBvcA!vfZwxb3`JqjmW43gLRIo=VfZiaBr^TSK;KN zxim;lD`63p4$)L~-5m)Agh>BD2fxL9cont`70$l5xgCRg5rq+81twN6&(!gp z4PWp_iUBQ;+`=ZbS+)5=Gy9=Tu4T4_(KU|lF4@~-BjmCJ>t{U!lSL?K>S(LfbLjgd z1uki-s2v1Dqvt#rp+2>-ApDB_rSZAByL&~$Y-drVKZUobrAK_Iy+$EY@|Wa}c|U}k z<9$L}#R$PXdJ4o40So-fMn7FDv?L^P{>>d2^_mw|f-OuQvMT_=a)t~7;)fB+vN+lH zbqq4|rV3sW2E)i`ijn0x@eaTQ?cjpFKNb*Fw7uG&&4s;wdqB^rP{eyiEZU@ZT zIhgs}pY)b9 z`v=`0;^eMO-)SUlPpWF4Phr{VVYZ6BwilOEs;r@2c5;RDm)B(d(Uv)*w_!tzgF1M- z$DD)E@4EKL79g3^GrIF@q}%Gj(KqAFc9Ir&zFF<*q)KrhN%z-ZcTZ2Pf>AC>*}S7J z;!2Sfn9>gJB8Mvfb3F5y%K0^;dHEUEtt8rBmeXggW=Aw7SExyl>5hFi?w|F3Iv@11 z=fm^Mi>&)>*gx(%oF3d|d|1&pUCadDDeavehe1)pUfw@pK;h(e$0@1O)il-X65_1a z8YRS3jYuJfqK1zcB#{=S>oq3EVB8(zYGO;Ap=WDE5;M9URm`{|Pc|kDQ$>z0?vYlC z3F5*tH6n-@S&tZHt2HLXsNas(z&wqJK;!C>AiPpz0*p_)14u|KyddXlLFY z7DeL{kG^(KTVe|}StF9@!S!gOhqXtP-X&V0iYu!jZmpps@dAxGAtMd@ly#RaW5 z`d#r5-GPJe1#6|bG|EwLgA*X6W3N^GAE!3d)#N%?@ivGkjO^86l zY7rp3PE$@m{MCx_I6ZBGJXWuVJPl}X=P_IMl8VF0%?$xkLpAbT{V~;=2O!j!=}W^8 z2}%fxNB}~kN*Arq6BnqLK0d!3jEAbH!$Iz)HC;WL*aK?`hdt2ZlafNwB1Q8yCrAQ3+Rt6cs%M=)@m!F3~N7vd9(6 zj}v*DoiSeE2Fq$TI`D*19GB^ww90^jJoOLBij-5Q0JX8~FG0om>>RJAa|TeKm3l{y zZ>KrG72XPIhxDd!$^oZ!Btrz#)Jr^xuz_{+{Q8*je~Q4d{kV-JYoS49x^JkQlv4;(9w&BXqk$P?7BzsBBJ6@<hghXRm5281i6_~z|cZfDP z1SGq%2-@NS%g~!bP5daJj#NTMO>|t%H-+mVtIM0hNK7b{J@2))9YyX-(&1ohTZc>j z(H9lc9H#bm!#}1`iwfz z>{f)ECY!|pfE2y!P?$Sbs>y6VzKc+cxt*qEg~nx;nkpW@>tBI1`ZuK_q`_>E+tEnR zndKDASI!hf^^bq-48Hxk)1A%c%Nul2;~GQ?nzo(Ys&kj`ZdbEyXTI%BI>@`Dc5d?O z|N8)gkYVlM_J3!ER*;?jmInVrj-D)+E2^JE6;J0j-{hZufR#m?0bQHcSD%1FjeJ;v zwG$Hf`4&MCkJ2Ciwb^=F6SIuezm(Zgf}gUafpVhJ1%X#f)n zpvLEC(6(HZ*u}q#;D!(1IGhbbYakwZHNh;OqFqqo|9|!6XHOKY z^3R&U#wNKJaI@YI7u~^0kDfGRMvxHb&zm8jhsURF7p38|CgJWmQK<>xKEybZi9dg z&-&n&PSQHKPhA{;Usf=_L08E|llEXX|8e1wo)cZ-#&# z?vX=(E~af6rO`+)HyYIiJTSOj@LqmS1xsxB@Xwmy`GbpT9SS^6{s6wVNy*spJSWOF zh|@}AQoc?o0$pbo9jmE`Hxm5+9AfBmIiJA`HiF#GJfx=Bpnm$Ns@D#W3B*(T^ zWsX-l!hhO(*mz=D3`0o~LbXmUj43Zsp_q*0ixCT7=GpA0=7Q>MFN$x9iBU#{(gDc( zB&BTAqrvjL?FsUBBQAH+sRH5{601WXw9c9lVcWenWI(U;B_h;`hWX)C1`qi^{J;Oj z|7%C%Iz}sQN%7`hQ7J`+CkBxcp~Ri65il3fuFW>I<(hGc-@K9?pIOohXS8ZI(jkiJ zoT{rncww?zZMrwqt`&et$+7qD^FMt23u7tw&WFc3DG&jn$G_WkKE=&aacNejiOnk+ zpRs7>B*puh8_W;gY4O9(5n2>` zKje=k?DDJdMQ8iMx_}L@IjGfPf8~8ee27JyzYS&NZw?WA|I|$9IRk8_6S*)NBcdh| zyP`xQT`fA~MW&4FQllgU7`X1;77$fJW@B&vwiN;p+a#hqq_^OxU3ea93u%jGL?`}_ zN(Ji*Z5LuOUxB45R1z8AdVxok1|>gB{hJrHO`&ZQs_qD*roDfDf)M5S^zx*KGV$(k z%-5(LRDzs<4=XNA7iTrfN0?oJTD-kb3X?KbHaOuFD#<|7>Jm+n^~EUt_Y^tyea`J6 zIDC;n^#_7bh#y-clRsx2A{E94Qr6`pDvZ{);;(_%jb`BUOqms@2{3;njAPM}lxKo{ z=?PYa74poR4}*igpJ^IH%aX5J>!iDCecZ6v%(t=xhGvHV->s!5Axs<&0MYXp+w^K~d#hY?=ZnshlD=+UOOX>kTdnZov*{kk-@XZb3B*)AfFGjrVfqyLYlcWxZL! z-N8#4@o#J$RAdoWfAn^@T5sn! zO@<ux#BiR@{-i_}f(B?$#%u>+WVK1sgd!|-49PoAA*xWPWC1P|P_RByusn1}&H z^A^;PfP;=tsRPZR_j1sq*I_Dn$z^%sc+6(&n*ija;}^Y?Y}6ZfpFQgj`r{uf5x^=5 z;-GX-k%eu#jrz|ohUdp;-O+b}9bYYGc>3sOi8tuTXY+U;-w^%oCR_PH5Q?i|!zH)K zai4TPIm)Jx;J35m~8H(z~;#9&9=oM z>V>ZTa!OS|9ifQc%&!GnxnysxD|~E}hgv+8*Pvf~`#S zOi_r|xkSL&CueX161~nvAYgq1B>=x}W_^Aldj46TT<+!zsC4U-Zzt1NH|PSk#6X>m z;_yNc4gFCUldDB8QZu)Br+ATX0yGo*BzKuv7-wtcsyX~|;H6MNtW ze>(%r35mTx%rzv5^%x8q29LMl$t@Tw-g@;H99;Q#!FKWIBtQUy=FLbfd!tbR7^a5E z%?h@3)lPsI`DU}^r`NEGqmKUh^JtE&!J|KX^(k+55s`ndwizb_AN|ZM^0Q)v&XN9# zKqmIl-+leH+-gA2Sy8JeZGe;);}^qTmz7}lpXa0O__RA3K_#9(%LW%kj`V;8_8JmW zxgMMjzVmBX(T*^n$LHvZGq~)X_}d35r*}`$XFf&DRo>7uk{*y?M{=)bB+BaQrllc$ z8z?%I5<{xS_RGmqw&>?ifhYDduG=pMqZi#_&qoir@7u{n21ZI_`V8-ZPl^wY&bpEy z-Z+6`Hk(7q?54N0J^o4oei)MCclOI!=I-U zglD=JiR*1Wy=1SG2-tnRe<(!+{ojRiu0P3_uQO!0#HRrsY2BJWI@ods*j9LQ;H%?{ zONV3LNBE|zO`aiT1lif`R!_h9B16;J+3Jq=NaVyE!4sxLj)lI) zC>o0At=~>>C-{F)KU=RB@1A`A*%w*&+aJfhk&#k&;flfH5!5ggno{nJuij=N>5Q>j z2J!D~J(<&!qXBdp6Ny}>$tHzX5=Oek@a3Pf@4G|v*&1i?pukPt(*kv_=F6wzw;BZj zw^a0VY7Sk*#3u>-n@xU)KDBBV5`8Kn!RUf-awrw<_6xPl(OZ+?taxeF-8{h#SF5*K zot@t=*OQrE+aZ*B!ZwLulBFm4WENoMdA_^OaMDCFqnASvL9vTL7}s05TQfgrx|^6U zmMgfM=1*W4gvm}Z#AH@5AE>@_C71X{L$?er;q!?^o9OPeqo2;#xB;@u-|h_9MJ!y& zDk`Cp)z)wLHEL{^hSt1l%pL}^ON;s49E%HwBfsN6gD6RxRI(OtXhAj2pt(yw8s9 zDcUU>E-X%}92MuF3+h6PbdGRpqW<~sAV4J?M}BOU&tOWQ{3YAIqL*%QPW?LP5A^Ip z-^q;>>)1Q#&rN3GHh*h|D`lQAlr7Iw%;1gI7R4Y6(BTj8mIYB}cRulApW|k*7*6u- z(=WcfncijdZ8mv5nR8Af6dw8LTWSg{MfP0us1Z~oF@e((u>OY121nr|lv2Jq^GKh- z=AlY!XdG%K6Q})ehuz_i+4sHSsDD1l&bt3`KJ5Ix^Ow$VzjYo-!3qBe8SKAMYP{@6 z{Q=GNx6YRz7u*g>V56C{WuDKr*(P@cJXuZqZgt6qvaHPV9Xv;P_e$IfYQ$_~kSj|j zC!> zU_k>p-idEToBJkQkmQ(hI{p(XCFXZZrX$F;AQfP4W}d_Qbnik{vT@4uVT89h`b8$| zD;ycXVa-6MOzf$q0g=+EWaSotq=hXLGHjh*x#Ad8UCx=7JIqP}I8pxrTVcHO_q7Mi z5ydDsRO{=oQfWO2k7aZnVQzgDs*;? zvhglCx$#FTZ3k~nXCT*Q8A!*|6wt-6Q*+19{5Cll*M=M$n1HgJoNNKcb1YbgOSL6Y zD<38BYH$HJ)+#E?`blQXQ?rj*HKa?!BBF_O=~Zv(0k(YNg?vyGk}Jh~h-+*mcWRm} zymYPP>Yy~eP7k)5GyrUz-9asi0<$SY`XUbHFuhyrX~pzGHG?FUEzh=tknVD*P=H3) zNu*UBo>j~Tjtq*YPYtD%Na5+d)WpFoQG=wb0BdreIQw7nC1AZ+*kP(qbLdu4TddLrYTvv zBo^-X##A19`EArIE*bp$Ncxh0>ZeogCR1Yu3#w9R13$A;wu%3jx;Jf(BT3GLzt6A0 ztD#9P*&Mu&)@o-GRSBTTx~2}Y(QnJria>!ZH3(2Ry49`Ge_xL?>C%$7 zq)ucvJDtha{Jr?0KS`3?aW(!?8*E zFqK!*l)#XRE zI67_LDzX>Q`8GH|OBFnT)tkI>fF# zsMaa|7xS$U33t)sy0+`B>(BRXL-OWFo>R^jg1I1nxB1|8XUlp3F9E_)?7EsX-@#ci z_`i=I&S&FOe%5$Z9XAuWI8+_i!EP?%k!nVoBhSphXl!+#p%qQJ(hpm-Y}K~M4lOHQ zVxNG8WyjZ>*^2z$p_96t&3m(P;J!flw-8u|m>+CE@r&EM=YSG&Wc;-GuV!=hpZ7a{ zs7)o_herfI?f9uneyiyD^XKYr985^A;mp(JmRPCRJuj(SE?y1$e)6+py)*A4cLo2BKp>c;NN$umTJRsd=?tTtWxa$lHS7 z!x6YNMU&3&x$^@E+}bdf4$tj=kK|}MI@-_hF!33w*`D-b-@q6!X;ejz`^47Sg=6` zi)?+IRwM>v3x_^pUiI1aVb-4*Qq{dbMI_56#)dL}!B^bQy!aWefI2sNKm5vn{6ze0PY<%xsV@T+LaH#!eR{Tr$UZgZhzWdLZ7Xla)I?a-oD{C-Z9nF0i1B39yg2X zT}Rz(ZK_Y?#}s(QDnxx-uuXQy^LscwXNM;Wn_a9F7w4nhE|?0+%~r21gr?Kc8{r9o zZ_#nJYA0zOhO;W@9ZK2(S)I^t!$}Yv#X}JRa&Yo3#dj94B=e&irtG&iOu0qkX&>2h z{QMDOfXzadb^V5=%IK&avyNHYW8USGI=z)#8zurNCP;C%y+>R^*<+$BtjEZ0sc;iA6CZ}$)X zAbQL;UK#Rm3v+5nu*>e7uq+_o9zYrpzVaFWK6TapFatY&Sa3UdK3!ou%7*{*m(L$R zANvCQxm_`P}ZkQE93FRMk>OIfHvJ~p`V{sN5wo;PI{2$tU|{jxutY1E?&SPhbtS4N z`Oo|9%`c)RV2JlXWy{fLLjt`fV8+O@mF$g*n>0XuxpGfc4 zP5_L)TSp+*m>4yE6C(L;EE5tvgaI0@HOEt9=}tMS1_ADGa9V&EtYBT34ZQ8N|JK-p zgymS{ex$S6DyBHFPs%eI!q@cQ#?4^8Xx7WR87@X}%^DfL0Rwc*G7I!vgRvUeZPCKY zKwSXp1im2obgt7*6~pZ;#Get!z1-Nx3yUw_`vxll)1mSwDmIs@Im-@)yTBH=v&Reh z#d3QF%kT2vEQr`FP*#lGV(ac+9J6Bax*t1L#fUEgzfyutU4ObD!v6x+Dn2%RyV;oV zOS*30HDCFPv~#o!_mQDHnn14|Q!KtZ-+ulGd6{IJ7k`%j!CwV2zRy!%`YpWM1^nH1kC`iVpp~n3A&*k>8?-Pv zgZE0R zJ&LNe#IAbFFpiC`=ExSeFwvo#I^F7o2O`@V3@~IHp=z#oOB3TTJ75TPq9xYgg_6iFW8jqzg=LnJmF~O2Kea$Ekqf~5` zukjN0>6neq{NnZnW`Ncl3`r%6J8mWUgM_EtmGP@)g~l3>tja{=;2^P9VWXyIDzQrG z?|5^vqIFTuBj$Qi5~ZHQ$Ofx&DPjPvWk-Zkp|nmth0xGL%kBn2T9%? zvcJH$lQ_JU8VyaP7%u^6gzNpLv==v9Na4#jql~U3W0*Gq%xW^WwgAn&{=B~`6Ke~` z(zI;dnL*cnjtD?h@O!#rHQm=3R9Nua@bHoHN44PiN7y30*=_BIN%(w+pKRlsqEJ`v z6?3Soelg~Smm*iZNTJ4R(Npp@&cCxc1Lk8~LPr7*uV?>V32Yqm1N9w)P4~xv0*J*_ znSsV0{f#{nG2McrL8$o&Uv^=8er4g;gK|UK#QHvGN*mqBXIyWqvJNw zy2;YeU#=I2a~NB=;uxH*KvD{C;sC$78;UG<1zQMKoxs6^i$Fp6%`FH&nH#P~Fob5h zhM}>RseAh`W;tqnaF-2q(?={RK|)}5q}>lg_G?BEDxB^Bl%Rp|^BWXvq6i1%S#Bn6 z40)+poG2BpX9K2Kix-_5n`rt>t1e7*H0`W7<%5CQ&3a5hVei;QiPGM2%zoar?|jW5 zM&Ow*HDzUdyDw`V{PpVk?vJpKw}a8^SJvyOQPTcO7S~)Be7bE84SQ79?)RArd(Y`a z6a_~j6*tz{ii=8yhpRRVTt%e$osJr~Z$Dn&!~Rfc{C0Ps{bNX&!$!`@C0?X?ve(l_ z{I$DtNEGVqvg%PN`;3G})SJ#N7C$N?f0y4#-g&KFM45FO7=N{G%G+?~?C&i5zKD5% z|GQS<|4ArS?x#jwLI{Odv2#Z1E4cHV_`uJvuvBX{l}6gLF-cI(SM{*&#Dopf{g(N3 z6-L*-{JO=418QZ!Fkt@y3e=jUw^IXyXn*3A6I5))^Bz8V%&!o+hRrL_dzLH}FbdGL z+gL%;7n#E7oqk~_gvJ>xBQ{fp%cEQ2N;PnliF$M3fZ5gD!)uL zPx=p8g5T@+|G^IJnOzKD=n&gle|*Gxx!b$*0efV(?c&rfY(MLCLk!F~qSgiKJYb+z z{hdp+M&Qf76|Sbhg#~;47FN7IH2e?xd?VZ{hnFghGmelAg>lI?2o;373c)GmkAXrP zR4=EBtAy+aAUQbGHf-Yv{Jjg-7S&qw0k;d*JTKv?WLU2e*9GJ$G(A*UcK%)dtgYq9 z{Ov9QZ^Tdq|f%hbruClsHQh}lZZ z0{`-}b-}%Bs1R8{%1x)1)X$PKcAZJBT&X`{iP7eYf(asENwG}{sg06#!T(3C*FsrFY0XA+w!vofcVD+k>|DaQ-+D9sKt{Y}kX_|M2a>lm7|S zljJ5wiD~r#yq(Tl`j-pamWhTr6-qU@PC$V+p3%^p(vp%y?xz=6FN*z`NPE5ON`kArTJ0yWvp86FGpq zjoMBlRe*ZD$XdVI!YLu>imi&bX?9Ihs#@xNb$nXYIVlXpj8JRVCWpa?Z-iS6oxFyi zvtm7v%!Q}XT1Ue%66t_aa|ove%&QFU zI-E;2{?9*O;yM78cL{X)Ob2^`$h3exeR_VrMb8aDes@J}nC@Wh(ZN~f8BOFk6RyuT zIwLJU46J#o44<9Yg`0@S&__djwvTKgjY9;PD9P0xgvg+yx01Grgod&j;* z4r22EcCenlnaHE9{uiQDczebf|JRH)$q)aiXf@#cVzACe_j< z#VU=-t_rIS#eE#qmdjnkMQE@u2e@^vY%X$HT4ZIyO9t{vt z;EB6-iaRKYmOg>R^P^_Df}DSodb&!q8c*8QDQ-VGt|vW*3J2FmN2icRkCT84)<7B8 zo|c1fwf)<{%ZCpiKk8F&=1AFyUTc;b#3NfPq%3Koh6Y!R5P&9RkA zR@q|4@jvaM*!|6Sjv#OI``yhsX3BGPDCRqGf3R+jW{XLc=#ET5hZuK&QP``|1cz-3 zW?(}znaokfGX<7(TFYutO_$YRHJVME5uE3#_`k;W+j<=Bs=CUgHS*a4o2-pit2#bi zbHp&X^BQi69**mVm5o}zsBO74GIS54YCQU$VMk#tp)}^Z#Yos{kQv1e3OhPvTV;nm zc4r4>ldV4Q-ohF(JFef=V0n0pot4qm-Q@tTUtXPWZvH-mnr!D-ry}5u*Ke_oN zR}P>9`1{4>^#+oaz~!m!9Y``iv;pkLi%)lrNWjO^kKSD}$RnPR4C9&Urg?|OU16?frwc7AJj+~z$ z5GR_YgO6GUj_|DFpI{O66J*BVSgIcR1{beUwNcfT!vYTH>6^-SZX-qkQ^Z!XxFYyB zaKYCjE_OGtX7@8oVcV^n6)?E5&SmURoqNn&SA~jEzQV+Un4Qb+j8xH({1u)cB#VZE zkc@e#0bZBgR{r6@ss?r|OP)kg<&8@4R>oCLha%LEsw5+Dq!Kb`U*ABSix)_K7|37X zyplY|pxUnZ-`JxhKJCzV@qH9b_to|>MiIWI%lVPr8oQ^adM0}dRRxRawHkGrh5gJb z8u~Et7k!vPpQ#m{kNh3@lB&G5R~WuZ@_@A0HxO4=E{Tu_0^Ahj5oa!#YP@WqSJYY=;JopPscgnRLa!Jb~_+nW% zqrsZZvX^XrF{xh97R_`$IrzW-cJS2ctbbyp zLGIta9ideh40m(EPJCGH%IsR5KV08^+_Fn!?rNZhg)MG2I0~Y{AvU1&==QM zkioBP*XaK4;-wyp&#ymic5rYBOoH|y&zp>f(@HIA$v^!B2Nz(k93pHqUBQ|mlXzRf z^lQ3m)~n@Hc$4KH4Yhio7Znz8Am#(BLPj?G_chZ6yUj3Bklp>U`ql5>{%{~?IV>Du zmi6g#7xk)>X!}n2hER8htpnU_NIF(neX7ug5wy9!;A5?LKEw$;kTVB+5T9MVgMk?| z08FR{J@{|~PuW1aWvepPj}0))E^(;v6aQdMNZB#SKZqqA^}QV?>Kl`(gTEhGt^Mz^ z6NTRyU;o@Te@)mO98!bth@ZB96bU%~$fhs)ui_%F3UM)r=s(Jg9ozz|R+Tz5&+ey8 zY_!T{nsL(+2POD7>EC;x>NBkc0u`KRwp$hV?YBqk@mO}yDulZP_Z-|*a>+rhyM!py zq)_dmaL0NN8rO`Ty@huUhivR)orKkQsP2I|_;>lmZS@FlCkrSn8dqH80jbo=OQ+iX+>hkMN(!>8r&JRutg4FnjiFHD_7C|&CED>ATG%1I?QnyC}l5; z^0uZ^I`cjNs-ACze_~!PMRQX-3IqNY^eAXDHL;>U6?7Sjg39Ls;#}W2kF5U(vAT z1WT2f3WVQ~XH{-4!MSlNPNy;)Hnhf$p=xDn@H6#yuU=$kV;__s+Se5XQ10@|4Qd$1RfKl#EXVbcb zcMK=#92d&+Edq;jjkQ@g_QQ@Zy)ELS!s4A((pgJ=UT>39gmRy?>;1SN=`rjM-BM3< zKcWcbzG(IPAt2hL*c3P>5J`wCL(#xHhyAb+>vwDtYy*fK;8ei@>{Y#(=IKy{{5eCC zUv`7#cu^nE*j}`h_UF?XlNSxv*|}J1^PKHcfN~d3CJsmJIA~R5wr0R3T{dO2#t^fh zQOkC!UcD#H_n*z=+2$;Y@21&1)N;+~czdIh8{YF& zC~yF0BzNmP)7TW+{Qh!{gfERlILDxt(c~xjgWDe=m&D!ml|G3O_?**h>hCOg--exH zVc$NtzkGUs4ao|o_n+QxZ;sT_PIW2@mSW^iq7ZcT7-^L?I!wy>xd;0oOM8Yz?*6yS zH^vDjv7l!VW}TA=9gB}Z#U}Y9oF!YzQ_z_C|g@28k1+gbP&$`}x01_FGHT2jF%FZ%Fx&1V z!1PtuiJT_!hS{is-BTr{M*J_&lqVJXn*!g8eTI&yf|^M&);4E%_iz}tz-1BabYRLR zgY2%2nmBVt*+dl8a z!W`-05$uy{JG^5mv98kfWOu8rY!A?@*vWN4*O&}PnPk?&Ko~m1MP3hYinuAEkgh7} zEO%8QKWs8wo*tF)m*F6t<)T@hM!+-N11^!X05 zQNtZM2o`psP*4BVx}v^ZB?ZN|GE^|1WFqdFniu0>f~^&Ngsbg$o3kI=rOT`B7VhDy zOSJE|@Hw%a^4~z6I01*yr&oDzuW#Uv{qF7~ykidk;xFlWi@j>~>mS9#(XfikzaY9+ z*V$zJ3f@uxS$2}OZZ=oq10jC-mVe+RuR2;@@L;hP5EudCi^*ibDkSe@+r_MVv(`esK;(Pn=5)KcG1g3^m93=ke0DRrzPkHp2!aIL z=<(KD;K45wkBhU#acIZ+NVxJ50A)fn&N1 zlE{*&0yUSLq8EcLl0w;`q^{Jr*SuP+mdyxGzA~0nN}y$29~C)a%4}m;nN;v1SrhLLMFjU3qvMle{&TQQ z0z{c?20T@||KPEwPZX(c-aJ&)4suqjKG=QwdqQ;jHg|LbFzr@qFjbxWz}RVF!LTe7oZCe&H7_&h8`Lq)bM)%v|GZ8wg>V$wukoZ zxAttWfW=B@$M|d7yMp(eOGHTQsDReByFFy70pSz$3%3RKvRercQ=JNXr1~52XlKT) zSycF^RKw$#XWR2H-_3yDpLW-UzOq>ab2Tzi;DTmJtQAOFQ^$#NGAb;!X2zwiq_0uJUQH zE_ZFUd7gGD$aA+Dk052Z)$5yNXDlXYn*=1@bt#|q^_W(cLBo1-STD*^z~PYY3t58e zF(tWfm#%+qS5^d=C8$J172@d_*X-(Bu_zF5xG0da`OZg`j zpb`;Ph^OOCHLZ%p00YBC0GG^nJE9=Z-NJRxY>HMypymyE8Uaydcp65-dRDB~85pkC zxn#c65e0ef7Or(>Q?w!iwQk7M2#6{}(J&rO;pwkgnN0%?maO$wGRx_&Mt)EnjBFBw60SpZ1I+x6MI-&p{7Z_4dRHXTjs=*cz?RO60J|u$?OPz_A|U{qM+GG!a7y!{Vp-2+fnJBywP}EdCxQvn zLL#gt+x0yJ1Xw2P){j_wCSY>bD;$C<^Rmt}OuZfQ1#;RYsdvu4?11=O*ISjw`Fh|90QQFIA5$uQ%i$y4k(wr`Y+HyUr|}+~$SSl`1SY zdNmerjjDC>{3zWO*S$4r^@?oJ)OvK)s?L$M4d_Jh*^mJ)=0q`*8O?0xGHy49Yqk*@ zGqr6f<;m{0ygh?}J2KtnMNz^<_AfU;Fhnm!f-&CB3Y2})8@4l-R^R5LWJVI$VAxbi zYgGRxp^BNu`h$phxg;u6i`phWAlx|2HO)Qm#OAPjc<@0^Ul^z2?%5ffDsydzh9Q57 zCI%{VBF*dfg-!d)!^4I@_&QvhbE+kq>L2ir2)N{Vt5zt?31j3_W)07fHZmV5yg@k_ zLFNvNHsaX=2h#nR!8_0{Km;sRj+#csPn#rdg2!{^T>X$l(KF&AR*G0sHdPf`kf2!&BK@&EB!Y zN|5NY`}|~IN2+(#X>+ugO=7At>hGi)AJuQ`f?=x=k)f-_2{o$AI-ONwTz>wF69ipa zsPAN;&1{&NNK^zSE6a*H_T+V*45VyNq7YrXx<=yGA!>7oY0YP&WGBO{LiYqxm>8NN zHTFW~d~-gR`HfZgjb&$E4V%Lnj$YKwd{G~bzLSl<*C8+u)QuQ-P7-#&ZdN{M7N34` zV(Vf+)e#(`EKHb*>GS3EF|HA++Hs?{SGorkGI*Bjqw>KcKv85^X5_PB7w{=Gb4P1My+g zv;@jz1?r2DpXmiu;PB=%NgQxtk@^}G7O!j zDN-(vrU(d;CN@*^{VCDB!pKRIBE_;eieOMFg71|*Q4~Z@Qxqu?>bY+(P+E6o)Q2K^b(IfYZ;S5f*pNO?IP;w~RtGeTPBA`f zCw+@>tE?KP;G(^93%h~g$kS+uDwB;Qp7@cSB$(F6Z~|1bS)yS%kbw%aqrsKWqQNcf zH7{H=Xqa-*;6UPOkQGX!paI58^pNy$N>?_&!v zNrNq&MS)$E=)O7`$&O4f>mtYg9mpgFu6z~=Zebz~bGTSP8Z?rHB3mvFWReC~K8pso zut$SEgo|sXxl<3d%>}t=pzC1o^(;>(hqEHr-(uK4Z3$28aVH9!#cmYEqZv06wO`zO zU@{8sQyJS8b}Lu~3T`ta#{ks)MO}z+%_=dGiD4(niWba@tSAaGvg9qff(_F~Ow%H6 z+(`rS0w<{o6)o&=tyrol$btu&B*HI|6&QYTVnpyotAb3Jcu5j0;Vl2Hl0?^G{bmh^ zOJJp|p#L6dk_5j*788DPA|3N_c{W_kBpF_TEH1p#L@M;ux!eTCflLzN%4hN57ADdF z2QkJvA6vmT62eUq5-gO(N)Ula%>-WZSh3xaeM~x{;7O9=C9{}{!w~7JzncSL{MF8a zapa>W2?`X+VkS_YND0hlCZqAVARRVhk_tyWiw37Gl>#_VUoQt0WPL2x(Zb4)4Vosx zE0M>ASDZ-4XnHi7j#kj86#Hy;Ad^(M@>xW zic$*#rhb?mK6zZsd5(s4T?l7I19v>8B-8EZPfNP}{Aq^UAWU*Qs3gbjAy1WC%x?jQ zbzDm4dmdF2b^UzHUXFxEf6ukZ8P64ZV8*`sUX1dg(`&;L@A~R)clpgfz5G-7G8T_a z1sGt2V#iQ>@y+cH($#-^0P0Pfmh9KKO)RHp)UI%rd`Md_(q=a-Rekg8_0_i7oi|%Z zmAJiu^xD@~BKIvz$ZVvB7isRnZI&4xe&^XlZ#F;AE-oM)to$8vy8keOO#JGF%8u0T zP@X63=jm_H?(R32&8N+O?LOUqO5~2e$W73{{m*-N9r_X;>;^wop2`Ppo_?8WTRw37 z?SV+_nJ~R&@qBx+xxa*GTBYwRVD)<-)y$L+XIu{cihS~3aTk2;K9G67JJqnvBm8Oi zU%H`$lU$1A(nVgIO)L9x`%8&uZGXDnsn#EMioa{yC;O?SFRAEe3om7#m+&c>f)+v< z!q|4oZ|Qe8o2%Q)9lQy#xx2nmE&k%>`crdrf4RNY?STK6Yy#&y=u%k^0L^)20et%{ z^r|d{2SoW_ez5;$2D*L{LS%_;SnF0VH#iSvsD~)1Z#QUFtS9*Z;AhZ6~t@BEoEz zmP+|7!0jgJrW5P#mOb`9-|RlY`{K}x&Si9JMV3Vet;E-)&b91x#Mf41RXVWTej~5;=VE%l4bABr& ztkEt|?{B1dmQk4ztGe}6#mCd=2MizXZa-gcehCJEF&Pa$^TW9*&}aB#maZ3BZ;IBg z*InYy1>@znaE?8tRMxdAAS!ZXC-Yl4mhMC;K^f^qe+vg8={U@9I(l1*e{TioZ&ZJ0 z*Pmc|RU{rI)c6`^gxha;Ckt;}-M_!ve7G$(Xop`!63Q|LX$~VT%^5*5JL}EmWg~+| zjUoD79LZ3I(a=LymzOeL+9`42S;fWf5fz}4OoEoh* zAKIC`aO4mCsXg{&;MMij4q|Ed>lQwYjHXp!u(`ax{_*~Eycg#0@X0@Sj`{*fMZ4+& zGu<-#GBFhwp{bU4xFH3+HYqLOy9w9UEN}kB+WY40Z2S4H;a|`n@9sLP%m@&*1|0d~ z5tv8tQGNo5+VYRv&H47G+j3~k?6XpnC)YmxH&m?HG0(9+{-=NbcmBup$|u~GSXbi) z-e;-&oW*=?E2>^GU}_F8ud>hPlp^hJm-}z4@d(~U=Ej!r-o%53u%5n|Le{2#<tCNxXAk|1E4Yrns*2=_ zR#;uNW9kes7!FD~BzGvVLNe}d{oP7|l!!?KF6Fc-iVjHWw^`N?Nu=w`!D2LrH&Dye zb&HmA+>p%m+bBwQdr=>=1Wkq9ZqZV18EK%~?b~{68`LRl&M*1awq`}y2utjVP2XR(n;Xdy7;*Pe z@wNG7b}?Z;v{f(v^zr)s#{2Qp?g}1;^?ttH!h?9{?a$x?-yHw~erL{!{?}N4cXLnL ze^y&gayJP7ka+jU3TClF?}CZL33_g!mRyx-IiLK&=fO*w3TsxI8-L9T;+j3$yScpG z3TIb`_(APjctYLhRO=brGBpb~#(D8kk6|$JL^++0D@`7jShMxP$V1u%S+=&zU1QV15VujXE;iOVaGxbF-LWxpp*?S} zKHPnD&1FNTcu~|^yi zZ8F@r3P7@xSFW+(gyP+`9$Qr$%*ODrZl5RM_=C#_YT*o)`qtjtZ`M+xp;65p%!z1t zv5Ey+N`Pu66@eU`d}{ z?X+BV7&>w7e0w{2k~s#n|9C`nIS$t*|PVnjb@ zM@PLpgz`z>m`s*eVNg_zlHXw#Eps+adz1OjV-OPM%kpFdk7ZFGSr!gSjHFjeE~}nY zA!6)JVc!Chhs+k$;kfPKAW;x9-9S; z{;ub6-MxUn22RpnQ#Q+Av!Lhi!5UVe^qRu~Z(?vj?pAeg?!GikB6UkwXBXIP^av&q zgOdjSIqvgzylCPsn9mKuY`tl|4%w&tGiT@VkAt*9=`?Q4ifYWK8?c9S0y|zkUVIij z`EWi{M#i?V1$j)MRO$%n`j!|}@IqVvE~AA>`fiA3H6Wv$*M4yI&Jo7&CT_pUR||vl zm21qa-%b^%dWF$%0tbn{=iNY`H$+5?`*2C$14XjxJ5Zij@9O)c*Py6Cl74H!EN^uw zqK_w|MRi0j$H&?E=Zf?1qIQHUHtPVIUD*<#BKj~-f*6~9Cl9e#0-hXc0! zcp!GQBsOB|AoyTuVU5kNevQQd@@WZMsb>m7bMpF6(-B{PaZ@d+;I>P?+*ewf~WdcVCny1s#9{&3p=;K7CZr`&~OX$Y9(?EI#6JQxmX zh&BC=tF?y0&m8}%OJfHjUz|r?;2(V4++<&;RmU9Iu3OF#hmV`v!`&6!9G%}>f8O5Q z{la#*{x0`Q9-Li6nv84sMUweh3UzOTbRXAHmS$gdf!o+O6>Jy<4J=_10OwH0>>2Jp z?C#!fF7LlKv*bnmuZk>oQNg<5$1V`s&2$7k1B?G}zg|ue1y|&Oyt4Uq1hV@P$ z`f?1b>dEfr=K5xTgwm|ydvn_Cfr`W5rc*vOSV^VN)>LwU2fiAZrQE4%ggsX{{`db zfgGmy+x}x|SlqkT$}bk8x8L|Sm*84NM1G^cxV}6eK&4xByW_Mtp34r_wS*qc#>0lM zYsgK<0$zX<*6cKLPYvc|e4u1DA3WeeoetmM?=BA3&1kT0-qwpHy9zO>Uc)yM%rFoB z@4p>96DjG;uPfZVgGxNiIuCc}yZHu^+?*fYK)^E0zfQxB3VA1FbvapD$`DF87da8Nwpx|7bX3g$uKi2SGBJVc2L6Ww~ZOhpRC)P-C2jBeh0G008`Ob!(gsYyYU1v1SUbDJ_2d znhZL-y1Tjjnhb(Gce|_Y`B!C9{QLK}X=Xf|=CA7z zYZ70TNz2&)?w;OUe^uSU>&;J_(eP`lK4H~YSB1>1<>$@WmMw#QO|f-({qy##GDs|+ ze_g{1Bu%~gs(OUa_g80Ml|i>Gw!fyhzT4e>T_fGPx`dhc`|aKC>}%p_J!T!i*;h6R zzlSsuUsbQPUNeinHk#J&K0@YoKCXOCF~zO=>UxC#>ewVJ@sYq5axzvUA4uT}Dt6jiFd4v(T@`^ONeZhC8SwVqb50w6L8#@D^amqFG=~0H@4~2PmfhTVIr7 zG#rlDedA^cZw0T45@7wuH8deKNh#1`uDFQo#7FnPtF;TVB%fw)=35GNXZ}vkB zL(ZUui}xfYq7p~Re!hY3uR)jYhr z!anpy({i>JH^!j*z{fu1i5vp`r|+>u+q2jrL-QqDg;D%iw<7f?jsM^+zz$~8cZLuG8x zXucV^{_r*IZ}G9Q^dhJU>_)PEZOw@ms~|0yEeI+zIl%0Mm|hDVom_ z1-Nbm(p<8x9ulEITiMg9aYRR&lvqI;PcbxVr2K6?TghZ@)uQZ|x(%Hs%8{q>o&=bo zA}CP?5WfJrRN)5ecPArAk-MB%gR&De12;{BDNKtA6M-5H-x*74McaxAoF>DPrmL4>sEc*F&IUj$mD4m6vDqQ2>nQWHzlx?-}V|oO0jwz(bC>kId zHBCw@O5>s}Pp9C`emGFD7!tHBl?4qzr(v*{NRX%)5|k*F167_*0VI0bM{7{97!tHB zl?4qzrD0hgPvA);G4dBa`{ZD!32_V1SaDIP)XXdRwqHz}<>_=)eOI*4w4u|)IPx@J z9FV@W7!&)waAV-(2{H@yW64A!Qw2xqzJn_taQUSyMJ+CZ8bg>!iGk3MioKJP*_ju{f+@!A6kx89VumE)i zS~2P-73@RpvB5H%g$@FBvS1C@*;+Ax$GF&5LSysyLJZjW539TqC z7~1mWNPwrr%AWr^WQb|kg&584mZ%cm+r?$L?Lb@gNw;K9Hcf>gOC!PnphksC##THkOyD#XmNbnF z3xZ0=5;C96%YNku$TS5~j^=z+39d1)59ak4wztRQ>Tp~)#iJplAWccI6pf%D6g5iN z;iJE;M}s%;C}~~z6TrbvljIhl@#CV5!JB$jeoh}#;u4AW%^60b_%!mPaBfwEpJ?vno9!i(-yhSc9;23t4sC5I8c%I` zhZyte*-kdxRXj-KvMjsG64c7o*V>#-dWj7}~>jS__*d$B?BlVgU4_p?pK) zmT_1l4MMgD4KZc7xxQM;D)vHxPRnN@r^&FzX?)li)W{gl)@)&_{Eo8;oF>GQrtx7x z^rWMFQ<2ui;@25#Ea_f!#1!HhOm$p#6BY2%vA~3AK8N9Pt}a>9x8prD1QR&zyd_Oz z!GfSR1U{=1?*{PwzA+>%l|+^~FC9{lrYBg6MpF=qN*6oi*RVsFKvq$jOyD#rMH|V|$4`?HDn#QZghY)DiRFdbKKSyKph@#f_F~S5 z>q(!!aIlvyNY;_31Wlh`vKM_mTu=J+RhNCz=P5zc=a=k7pASc+&#Q={t=2DS~WnJV)rGruZ0WL#N4cl>zTHZrQdmpro6cP=OvCh2Th0qvvVk znq?>}F=?`yYG;%}LpM#HbPtX^EDAyG8pXZ{ay4`ljEUY&izV5E6AOnz2pl8kdD_`t zPPUFAPv73?vGKdfab$Z?;~-IpY46jsJpcP6D6FTO zs7RR}ghdc3#KE2O(FATn^K^L)oHjb#$2=&crJJ;1i5`>%@hF6e?s{)bS@7Ky*`htT zv4JS0h@O96(PN@_Q({T>V8p_q5W-&@X_oaI9tkUyMc*FC90lF9xWYY{aiJ*W@Qc@b zxHQhvoi}au?3`ikOe18;v z1k~=BJQdw!`Qkl@^1&!1u@{^n>CWVEHZDJg8Q|T-n1VehF<~fV3}85ib+psH5#lK5 zCdC!*L5vGUAxAIP?=4!?HiuBqO^#zt-YqD*5xYsN_@v0aGH%!qvUv>n%cd57H$%2)J~w!! z>61O24#o>Js@Qy|wa~)vro|TRLyL_>iI#f3n9XZQb6j}yp(V!A&`pgi+=m<&s{lQF zSXYh`)#}Qk%qUinJOi}^jqGt~82C!=?8JF&mE{p>lq<=k0ZXA0wm1$)gZ(vE3%{E% zTeJ^HHWGyv*wUZC=@-$9wb8nVjy|HPo2po$KBUDkDfIDo8TLw>qoJEFSGW&NE*6Cz z{gQ9-4e7Sq@^o}ldOzSnIb}YBD)DjiY(oI#UKp(O~coe$Cm-haM zvhcepvPJulVe^;%A%J$h7>(AK!; z>GwcfNKH3w!4iE)3j$IoJA~!kVYN8jn-G?R*%%P}U!iDB&w1B78;0FB+ zZec*`uyM&FR8ZY=l{%!xB^2#dd;dFVey^z?#!yU70lu!S*Zud%tUce7HRw`nWfusW z){8Z)5wcf1_-ia>wAdz5`vQBU&7QuXXbTtV)6T<)PGd(!n>!lquO&w`bw^yRP#^MQ zm=1lJSyK4v+IAu%HXipd7&{+t!Tn9!bfeb`7Vg7k5YQnK6Nh4PZ#rxEKT6Oh5P7~S z1=|^Fwgq{e8ctWT4-+tl@LcJjf#GyCEzE;~jG)4l&I%EO4HJVL6`YFZQL}`*{9||t zrp%!M!%ANPf}TJjDoX*Vo@DW4L_>JCqbeLi!qgTXO_WijA58{ODUuHNOVVLJNr&YA z$El!@Ze%|+npZ~dr@|E3;0S`80@N6CV8{`~uK)4d)#|{bxI0=T$&Ar6#nd1Oix#C) z7X>7f2pgaB@%Q1Vf@EVW{vWiBndex z9WgD)zG`r~7>&oHLE&CX!6Mw(qErSn0J-+71%2MMpCKV6k4LBOI&kfL-FqPmd% z!fY`*E!`(_OoaPFj_P|%3)1mbH5nB-v1jy!924QVkfS;t(}H!p9 z01t&}kf;a}lq8h`Rh~=$%qU9_eGC%eIv1n*9npbo|Kn;_xW)ky;WCq=dK}h(ba*v7 ztXIX?J0vQ?aV1H0UX>?@`Q)^k!g6WhT9>E@0+b|`09Bq$z;QiW9G746Qm_aLv?!GW z4L~O0q?#VD$Ia_%Qo8*c$OtM-X(}5g2APn0buyaGi?0SNSOgVXl*)q!Ad@hFCs$@~ z>LO{)jL!fCiy%RZQc2JNWD?+oF37q*gmeHfGlqVmsSe@O>X_$hSe}l@>n$We)jX+h3O7C>z2MQDzRa9qey9gk^2I{xNlQYK@z z(b;fJgyTYv>Uc~G(s8)1d^{VMpM+>!1Ocrqm4p_7+~%F5Cl%cGV~Iw}+#NNdBB}>L zRJ<&exHux2NWK{^&fdTouEMi>8yrEIQ-I2o14AdLp4M<5xpWpqBfiwLN=Dj23{AdW zN(G6|-<76AfFg*Hf>a8kdXS?a%PU*M|HqG*LZ&qS z97$<1!b%Y2L<&;LiolU0XEIt2YFI6q*0c4pS=ECR_{c3jua9WK&=-NLO;d}Tc%?^B(WxnL3@w&5+&pm83Ek z!y^+2hY^pz8)*&;5B&~0f-tuPl_(d7Oc3NEobfjrVXPb0VnG?^={yYvpS_oEm}!Lw z8WA8=W)aY2vRQb`ags0L8(R~FBeO#jg5IvuR9?F<$%LMa;DyohH>MOUf+{Ua`kyCgE^4pG{^*rH{@jSOf`LluCjIAd?`E-NB`Fm{pAq zN8{1zbdLuLeLV=8qBfF0`r?RWBB41Qu1hag2~Y$@Qji))Q9a0yUloV@I=bNDBPj99 zP}%X3$Wfx#sMy#h_PxZ`Je&_osLQDQ0`OLL`+55Nb%0>_hgCVeCDGrq2zT)Lub~vI9xp=?K1n z*op0N@$EAc8bOpLPK`4Qgxq`qMXmA_4kH5@M~Sk795CG)kx?S2bo+`F7al>4SA-fd z9uPTdPT)mBSQM1+-j|+kIOrIPYeh&CQr<^E)6U-uGt{LDL0M;UYGieSlB0|tkbz6(u%|JHV_J}E7?#6e zQ)3?oNjr5RXzeaf<+U4?PONzC(kHd}2c}3P7pT6b!jKxblib|%EW$Q_ea0LzeH=CW zO`6)OKu`$lA~LJ1QH&anK`?R@`klr;8g@hrhB|lIN_0Hr$irKLjJhQxrx7nSHE$u^ zUNtR#7A2qoL0qU5HRM8A?%zqvI~<;=yF~UMsTR5@DxYEBB;`$ zR9-XynFQ9cz8ei!C;TwL(Rw@<|Fw_atWy_)uI} z3}Gri1_YUmV|W6#I1vIAL4p*d5)jpc9O>XlQ@yBHg}WJvif~^^QvFxu$+drY`aKNq zqiNkt*6<(=+_>J)LEWex1WEC-RNCT*WFq%VpM#Dd%`HKt%Eh4*WM0kV-=Fe|%AO+5 zx*ZqNhaoX#GkMNVu@2d%vCjd2OU~HrEj=eqD@0I@0HKC30-7Av4BI*)V64yW_e3^A zE0T5$QXlRy_~Z&$RmY{j5*Q?cIxa@#C87h{#N|UMdyFt&1A-Fux`|;IxrYp4k)tF4 z2CoAbp7w>6&}akeN;1db$mBt+R^wUedyx_~V3xa)rzCr{HD-T66SBF%p8R?`D}8oY zq6W-z2~d($0#tc&1RSnUMx`@UaZH5sLXPTsObfE+A@mNb>ATXKwF(yDz80l2paICW zZ(nb;X0H0SO5v^)qY^G-M|!KJ>!-#r2p;kp#0`X1GTbe<Ql_VUY>5r`LKt0TNh?kKV!!ETs-XWfFqQYZ91D z^6BU`hCH@<}%q+!;NS`P#P;qWip0GCU6WVB&tPo2+Xm|iRJeWd<6*F0)?oI z1)%zqC9f(JPtL53)e3URY76xytA!$yRn^BeyjUc1KbQV$vcVA~IR&T$IWS~$*6g)! zxTaBf5KyoPLbNEA3JpLe0a8r9E&uL}L`6`bB&iIj@?-*La8`R-{)uOSiXcGhCx79p z@?-)Ar*M~Sw%Xg^^0e_bRMIO^m{v3$vk^UU~^{36v!S3o#|M%HXo6Gy{!CF3F zAm6>-SN=uyD7D5%P~w-NhK`R!juH*ExAqv&kV95$7de=47U)Rojx2clVR6jf&u$GX z+{OYL5QK$FQR6FwMUJrJam5}5F5efmz!-Y87347L)Q60oH}Ig-YfQx5hR(? zRBB8NG9m1aH+$N*{1UK%j3C66rV?UekO>KFKkskA>Q;uJEdfAfG672_w;lQS`uKKC z4T8{UQ7V;DKst%1I!G0V0A1CPnovgcws1&j zTm%)ZEHx-v1aeep2zAhG-|x#Q;$!-9h>K$MCNzpnCwjJK>9mfU#casX>qYr2hJ%m} z457htWD9E?vWJu#82x?`iq_hZRBF6Q6a8h~<6QBqRq#)J*s2*g8JsZQz zqN6vZznT>+f&eW_r9cCaBS7bo;WtxH37TGqk9O8OxWA1bie>2 zf)FM}4U@12WHa&ED}9+UpaDThs1%i;5EeN?meqPu!QRxObW3W15%d_sR8|ZKG8u2G z)9R!dmu@o(7D0p-rP81Q$RsT4*YNgt;eJ(sA_$OzRQIELu>HqLRs53(AQ6tk)Mi5N zGkIZhjjI!=`#Bcwpd+YoOHhNs#UT>}iw~paYPM{Kqh;x3I13v=jxA56#zr9%Gd|tJ zdWrx=P$31W97OeC`wIR7MB$Edz(EntOF^phQ9VfK$ER@6vh+jG0u!BWO*RQ@qe3mZX&El*{{Mj`hH!`Wmso$ZAe6Btixz=Qgvz}=sHPR`J(}upwiv-30@(Hy*T+W#`Svn=+ZXOw^OPef%><1SAA%bwGY+-ir>w3;Sq#+MW|GHKxC5G^_S&r%^vh*=?RK2m3a6Fn*1_U zo_r)SQPtaeS$-u+q9RC9l2j^Gc`^Z`=@N1Zz%}z3TQ!?cx462SpGgw3C<4WO1_d_3g2kv269l7^HXV#-OLoR_47>Hby}=4xdndDSzg;KPVaQBDkcmwJ_a|8< ztewM)-(P^^u(lkEBM7}2j^L6BW+|oA7M8}An|$nPnc~;l(h3nYBS5H3BcRD-LpIo9 z`A7QQ98zhTaW#}LA{R}G8EL4weYB&BJe3+7g-lHRxsv$^o`8dgM#_Kx zpmZXL#Nkj0#-WpmuP2ZKW>EgULXC?cu$85f)FP0Hfa^Td<$ShS@!QOkYQCp+ny4NG zQSq`=;^K&8BCGM>q@M7^G<&)o;VD2+=UYV{F9T3yvXY-RrO$Mx6(Yz)fKUSx0Zk^G zZ)|7)^vh70^O5=zWj*N2m(&jVBe#2M)*{P#LMfio6i`o|Q}AT+;bPjG zN$IPl0u(`>6r_?9)r0(kFi&6X?@)0>3xb|lNh)74JaY6vl8_n8A>0hskmmDk>Aa^d zJc=^gBJ#M4(2b5VY0~~SSG2K)iX5`cV)Wqh-3-`(C2drdPN_Em$bdoaOU7J`OhQ-( z(rI{aY*7tM_r?+x;kuHfdaufp`;+Bt0ZTeFIFVKSg1ZTgp~A3)+=nD|VxvOk7uw%q zmrnj;sKAgEu#8St2#g#_u+30BgDuBI&?4lhjVP$)_q&UObu${Q8%SBox8)|)>)C>x z@;Lav|90@~DUYQ;|I5E1W9qP4F01BkRXV4w#&u~zJK%Q5Eh3fB7J(d1gK9mfSRQlO z>p!ffz%p`wg|q?L zAmKh!^nE0?WhkNk%>VcI|Njrm-PPIln}2%wr^o;F&;PD|TwmSoF4>Py)sLU=-(T*| z4$iKxZto7nLp+1oux>CaQKY6V??EyGoE)jc^?W>oD=3ADRj>&1v?#UVY5+0`HS}o9 z;v7g+1O-Zx%77|QCIH^mnbfNVJ6Cj4&Fj5gaF6OikQ6UVr7ey~ClWR_;D&nP)&#q8 z3>8C?lq6FU)g)a?y>IsBWcIpv21o&la9;{iy^rcaJHH-Q?;vkP;rf4bB5_d^C|NoS z3W3}VoV4Jj7sXt71T9_>Dmxw!og{cZ04{!(?kw1=1Pm5KiV`K0p#aDvKvJIya`}~R zF$xwzf)=HcpaFW207>6Zs=D|T1P&`oU=$Hrm`;U;pp#KgVP^hj^rm{VE*=&pHii;Q zp3I7cLMH}Zr7JwJu;ek(q(%x;gQim-vagvfrq!gLuHcsP5KhTLTPnRu8PI^C$G3|fI{_?m z^vq$l`tGDTfoxNyvrn7Q2#PFmY7AK*JxCc(P8apG^jF@zlDH^3lq{VKh0ueDbu)nH z&`zq-x##AUMn;j*O4I3RG3bOWtMLk+QHD6%!!7=~jgBG4DM2R3!66g0JYi!t+=%1p z>Z%oNNK99Y*|>B!9Myv$Enb#NUmTH6x<&vW$sdT9FbN1u*ZuQIO?ZF=pKHlAZ{`Sv* z-ksh5@$=2~e{9e0{&aow;m@1TAbP=metP!j`?HUmo95-mKYhIWbou+u#j9seA3u7v z**rSGc>3(|^Jg!%XHT9zd;Iv(+4C02rpNcnxk{co zr<9i*EbXQc%WL|;VGJGVD0^(Qn4=5~;V2i&cQk}RA89?? zt7m6tkIy!bFJ7HpoIgK*c=r6scDsFi_WaqaXOEsdd7?rQGs-k|)lBO(+$>BHyW;roRkKGG+xr_Rx-Dq+mb}5kJjUHNvAbl(&<(**Xgz-(djAw@GaGgaImDi zLT7eV%VI=Fp=OKB#UYv*RMJT)jdg`{D8X&65|~^Ru(f^T*qZi>EIiKYqS_`S8{Ahfkhu&d)DY(4j_I$Pg#ajKdAJ zhV7e`XeJ)0PxBY2!Wd|M^Ri;tFHUK$3gyv5cwT%D+?%*Q{pN>4$PyJpxZya6Kp{n4 zh$u^mkJ?R0Kt3x#0_7=W=&*phNu#RB+{}UOrok1?;=nE3kAT6+Y&2jOTMB)0wbq%) zSURjSL{=;ekDP<`{O0=e_U7)FzJtZHhtHlref9M0#rd<%cH{HI#>_4XV;%TU*GQTcGp+*Ndi8y$nPE30Nz zA+H({9RQStcU)&MaWAtpX5#tmnvLF)%=K5>9MF;e_+zReeMD7c#Z`j^OtEWL=u{z( zn+zRp?oPPC0yE3C7A83DoE^oM^iWyQ7mvJTGCx5m+P%6M|E~N zgUf+s9tDSHI+Ac{ca>nazp5b7;R(D%U955iSkhT3mg{O19o25jEsI0FMi;K_@szSG z-i3~HbauF?%e+p&Y!PV5I#qJHm8!}S!*@BU#-+woj+Jy&Naea2!$#HU@^9;EQEG-H zz|wAVo!KL66dmX2y2wR22;1el`$k+NWwPrrh>LU%){&%Sufv7hbihj2;hIV1yBNks zISFaKAdhCT0Y$+jUDblQ-s*zH4ye>7Bvfi-tI!@&@;4#l$fz1Ewh9e)i0wt6Y1>7@ zCS)A@VEy`fceT6vKwlzya<+YRwtf6?`{Lrs``k8Q6O5=u z<=1?PsChkuiE5eqXEvhWQobw$MpZh7WwlJFtRFJz*aZm2GOQl0;i5s2t9}lo&$YRH zZ0BL;9SmFsE* zTMu8yH`n){X(x4GynOlM<<>O};XPfQwyiK0h$M8|C zI@RWQFkE@%cILjjM2l{rQZ4G`YO!MF!P`ThlwQ4S8vEMS0tfRwB~CX?%37#HhY1v!Qmqh+ZO z1!EK<##t>(a9WooO@@w}BCDuSuZh#*Tq4)K5GJZdkBW6RfRwC3CX?%07#HUp+cj^N z_2doIy)4mpqQ!T(6=vFD(}H~0tJ+4X(mw=RXn91bUa2OX=!^ahD;uNY`j)ia# zG!k57rHD0nQs#{c=vV+LV1zy2VKTWj7{*1_;Ho}pCe`8)Qb;t%vtpI$!Y1AJ3gmL& z0g!8Z@_p6JAdM6-Q;-ozk7MH|De+6>a^fRUNhvk>o`gn9rvcRY@gG7(g+Eksq3#Qi z(ltsLf5W&~=ZZ$KY!DbXxn4p&iY6D(fONRnJmUoOb;E_S8)X<7<=~rQlLcA4}|jl3nJqjoX%EoK#h$oQoiqO_)UwLcGr;2_Sz^*974v` zq>$5qlysKK4@5EbRv--^v@04W)iOeWX2FfP)$VzZjRVP-X4DBnN&tY%ScHUmh> z+G8@g-i2{dwYR9@l;INQY{eR%frxNcYbQ9}mL(4M%W5b|>N`&bq@=S&~RE~vl5SBj(E(RA(a8A}`68XV^zXYhXi%cln!!R<^!IGN`a;pO2Cf7>vRFtE( z$CF~GCzb$}c9RKZ*Jc`T z+Vh<@%2LA?)^Ce>9X#k_e~PWxdU1B-_E=;t*AoF!vNoAau6JQvROp@-`&t2{q;pIr z*SRn**16^o(mvLuCbnRU1jM+iL*C^wlL#nUi8%GvMB9hGKKNjJGr zu8$F9l!Hg5D)J~@hai&cS`ZcG*qf7b$G|yOvhIXbu7@#fl#}1XGe@P?+BsIzNg0K<31!K?-A@oZNkX_(E-7IY;@EpsEtZ_0Ld0miBpIz_E&**x zqSMpUA}=nnjkMG5r{Wtalj~v_7Zvu48LZ(PpH?jB3stHKnXFe!IM;8huv5FgPdrrf zlzWT241Ns9Ce>@}aPy}ww#(zfx^$tPuxD!?Y%Z}LfI}{Yw$ox`h-n?5x}95VQ=o*raGZUyC%0ryh&LWjW3Aw-twK}l3+HYsqPw=VXL zX9Nj*yAy!3Xpu$w@DkOUOU%*eZK;n5gB6CFLkXAf!AC@2E*Zz8NnL6U#9)KN=FlMu z^xz|=F_#c_N>`TYJ83ugKphZv<$JIZ(U(oedOBQ`NseBf-uyac;NCq0wSU>myAVSEJuM+PYgAO3@+b;jEKHmGD@B`G}yo$ zJM;?l;3K9npO8uYW)IV?CCppiWJQQ9(TkIa&RkN;9T_sJ9CLce5%0l8SX(v`#SX2S zo*|B}I^unZ2x`kGVjo|w{6LYvcpDvBNe7TDDubt-vdP%j>eni|4i%@Q|LRvU?*> zIl%5lmP@gE98R%n+hq3@B5!Ig1JP`&$2XhLAGh#k^X2{R-S+12X1n>3mUZ?0`&aKb z+ZX4LH;>L!)CTRDf5DY2J@rrVEvmAU{q;q zTvna7#hiFX1u-iiD#LmY_AC&Gen@Jos@FfRT;&{Ia@4fL;2mDddy55$Jh&@A{{G|_mA6-M)JG;>q)u+vm@pT)aF#fBOE_ z!?PEUUOnGFdUmG9PSn@LyMo_p3d;|zFYme0d26$>qF0xq#48kL2U=HUzJXgbpII|v z4Y^!brL_V4^mqkok7kQWnHSJCSils!PK8bt?6?=uyUq*LZY6VlZcEagp011J1%x^VYXA)6E)yg88b(KjGZd{Cqd|!o zCU`2*lCCPbTwhf=Vy%jW3jl$DF66NZnRMF{&h_0YOeA1XWI72I4eMjR33l(CyMz`) zMTM~-r)Zrf9TYmV+p8?*(}!|&Tx5+2xDGA_*)<3vxj`C4ML8xq$#M--<0b2{mCW_F zElI4+Y5i_Inijdq!g^nUmULLj<+`iN5uNqF1PirSA2>-tphzwo0SJef)V*jCk*{W3AG9g`}z$}{rOE{MS zt1yv(;cR_am;e(pNq{AsOMq3_A;8{SM-42+R*l#MWyV&6I&HEeK@`YkAgJcg|8lTi zZm;gPS7+NE8~ra|ZC}C0{*$vOu;2ga{PFqI=kFh#zkmPy;?=|R?ZXQ-8c-m8?x6l^e1#Y?PC7 z`9aF|+KvM^sIJsn4>6+tG*>xAeMmf2j&x`e}94qOhkjiy3hK+Kv z%)%rzztqB{5Xto|h>CKo+`=SS9$h-L2Mo%>WEVQh(J~8@U`B8W(RMI*VKRn_a%{;? zu8yYbQgc;}mu!cvWNy5+C5hu+$ZY&sXxZ^GBQa=NAv3 zz2825eD?m;vsbS!UOs%fdHL+&^T#h<A2#bLJlyxLND_q>%@3e2>9^4&4U@7W z)hI`aQz%|d4oAo9*?K9Pa<4hLiRW``#;YZn>$0{vpd;NQG1cSwNd;-w%52+OfB}>2 zdTw>+&0tenP>#a_c=e_^gsUZms=EbDI&O&OR=81=80G?@I)Zs*QO`Ld(sdzA^F5{~ zr`Bs&*C;XuLnz7`;gCr84}~zze_5DV`*1^a$c}=Z3cCwMfPw9bSQ4K0E*_A#5GBnXjjV)w){2>ES~0!BtvKb0WYpgcAU9me zMq(f)Nibz|2{6kNoj)Fz`Gkdrz@U=ua-m#5Bgm*We{woMDU(MATohnQC#6`fn^AO> zqoZLxJ6=Hc%3>b?24d1>Q#RLcvn(-;M^jh{uND=YZzwd-8Hj1;TkY8$dbb{2%`^3N zapwgh&Uq=DUGuHw0X<0Pk4E3AU9)0!Z(s%tvp;@EQ&T#h0<$zR{Mm8A=BO@{&lmbR zjhA%3mCSX#ElG5GI-4$6)uP7Zzxm z3R^sz3A;Fv2zIKqE-FmF z*(vm9d=g%$Eo;1_!>wel%WX-b)9+@BVe@(hpE9Mkvkb(ft#_q^ls3>tPU8cUE1U z*U6JYF?{kQ?bwri$3mzm$6go7SOzurI+RgA}^B*DW?wm`o`Zru6^#M*|B zg5ikmd_vx&*VVk5*03R3cEPAiMVhJ(`?6bmrX{GTvMyc95`9lnS(r(RZ0X!cvP%=A z$iL59hzTD!Nk^baE++v9A~D6zf!C=hQs^X~^YzDyUob^&XZYb|JF4VzYgCo<@lnne>t4atNEhgYu8_)gGlG4vKG|G- zxW8Qfa(TIVf4QaivM)DeRoAVb>p1pW{pRzV5Mo4fz{aeq4wR=vHiH@0)sUURdtFUtB^tAf>633px+k4Y zgK2+2SGsvK6W+qjX!c!Fj)E33V3ZRHhHSR`Mp3CeSBQhYp?zV3ekkP;9Jc9ZO_DcDq2rXy1W; zu)Mq3U458+zT3e%H1c!mmY2B}Wtx{C|Mc0h9tNEXj^%-XATGqNkq6A7hSx{cYl9X)%WSSawu<}oIPuC zFjHMsUAL~TuAc01=TztDM*s5*VU@i2MMn?B``Zz0(bx$D;sP&hh+{f=$3Qsla_Zyh zWS?rbeH5414N0mXr7M8 zou=1^)odZtm~OZ0Z8BZY(&N`d_49N7xpO413DhV&B@UD6G~Mizo9%j;-0k-pBMNuv zWR`9LK(RN2S>D{J_n8`!Vl^?-^>1l>?GltRYR?S!=E_$czFnHHXv zK16P^UvIPA%fqpu{E*0#fF-1)`Lk-o3fv>Ljq-oG#@ZN2vqH*b9KSwM4?9Qe>%XVd zy^@eUvXlig;qDASrJdo7;1lB8bVJfVOWsWu3n4?iZ$2TILtw%#+9Bn4Zo=mQ$J=iY zo+>z#DaLTV8-2hPcgy}PCQ77+)5&VRnv?3!XGXHMiRjPBb~-?eRON}h;j3c;_v!n6 z0;{*3Umx}mic(W(-YvI=X1wL@mQ1c#)#KOa>23$J9k;iW?RN5^bHo;QS0FVGJ7u2P zC3&1wWWoUNN+=VKb&lk}j@ZJ21{`_zZ2amHF&np|q!|!jXicrP9C4d-o32RT(?^;; zkI(^eJIBQtu=&%)WVh?|9k&YY>)?Ozd2jJiM}O2wU^(FkwukBd`1kyZy!a3PH@KtX zoX%g+UU3gw^frC8P4|cG>JjOq`E|0GPj=e3v#m&`K;`(uZR zlYt3w#!;#{;GOm;>M)ox(4K+WKix%SxjhoZNzT%n$zg%ehW>}}Mj`KUR(>nSouQoy zuo6Ctqd#_s0H2g-edIs_Y~#r2qxfa`(u`X%7}uFLq1kae28y0E!b&@udb7u{d(fo{ z9*u`>Lk@)?j_}COI;jQP^rY(b{AZY&R4-cK@)kbg^j>tqnc0!Lf!Gh929%&^l;L zL3P^+m?t_2=$}U9H68=BHG4$TY`)tpCLfa3WNE!d4U&u>0I*YmbpcSv!g8$rAacwQ zz1G@)SfqI7+Ruep{O`VDwz#pT7fq5H%_pk~T%Y2f=!?4m z3rm5+;1MwT01>r);p%|mxfX&CMq6WSn5s3Ss#F5wVsRA5!@6a>uMsonN0S{hKh{(; z(OmPjGTpqgk3_(()D9%g*EE~QL$)*_V3Eo?hJ;kG#wKS|G9@(`E0I))PZdFlNcoV% zGX1g1!SrXvQdARVrp2J*soYs7^FbPJ)(tZQTUv&4&hDjSU_y_mF~uQL8hCII97*EfpGWHMY2z zG~C?Kx2dR z!Nu9D8F)H(%Ixtm6f!rX~GZa=)_~>9bF005^7@2IJQ(mVxd~(X`oRztH z^NgzcXv;gJFTAD+%>rw7ZmFPxt_PMJ1JC6{<8woAvr;dY4Y$q+4C3Ar%mY ztJRA%oP;me#nFC-F)hXG?y3o0lnNbooB4FUKG+HjnJd~wG{fqNP% zuWk-II)h~rqk`~bTYV%Cp42Cy5?9}@gUt)ovcya=YSX%l#rj=36E(1`6_wiEC;g+Q zwh9s_B#1jM&N*VCj0{|6@czhCUOnSe13eUYqR5F0iO@|FPEw zSF%t;76HSM_{c}KI1%|ikfQ2rIUk&&$^W?5K5OETE3hZ$!&)rLfzg~zxL*iuXC8n{ zF~C)r6#cFqkD?$Nv*_xgW!>@sR$z($el1q`pEhQJ=fm4JHMzhmuqOZ8T5QS()0kzl zIzU&Q=e=Qme?vZuMymuYdP{nxdH^f1#(%#SJN!=r7Pu?*`3*Wg_fM{pA3-Eq7bfT3 z{~QddS5fCb{@nRCTSZmu(_i*aPjP#~0MJnQo$JPGFwKV;a;*s|S)b?PTyM2q89U$C z_Qpy7hYQ>zi4*SB0=(ATdS3=pn;C|C70``87bCQ${ITXxnXk)+>z=Ci2cgnlcd zdZcAP4+boW>b`r*BA4O9s84PCrEx=JX5;~JP>k%Bm~Dh)zDvxGggqImbGcMM#7Ed6 z;?cbauDxjy`Z+;e1($;>J-p7tx0_PstL)7cmWM^?o+!pr}VK|C{)BYhnrDc8cnNN0`b&`Y{wC^x^&X&T9vT+ZD)>u24WsV<|@)h4mPMuL!DR1dh(H>qm zXjKq0vm7(}>R~7RI>lCNW|~Velg}O&wJCaO)aMz0b^N^*E|^zq8ro1_|6pb~sXk9? zm?ig2ra6zPdYp8Q$iL7zP-hQW+)V4_!GmRJB5qbHipIx|E@k(p;JXa)Iwq6c>SVfy z-PFBR3>fVW>fqRAQ0J;ki4$gg?JSXYF??1@97=}I{iY2tAZ~w^QGTRbt#()kiKQ@Q1_}vVk|HSR zrf2Kb;={>$xm>T>RZ*`=SBBm?j^vEmeLb`v$(a{fv{v@ZiuLU5$egyzQq}S7Ud()G zKC*hk48o}3MBxgH9WpWGU+#xCY3gJF>$2;w*wB!lY0<_|6R+yHm&Wb@$Hpa#GRp>W zr)Ak_!7M(sImA)fPzZR%sveewLKo|IElxQ3>D;buA)1)97?Nfo4q!vo0q!R>fTOc@ zQpnXZ!n-%~%_h=it^vLy0rjBh(qbw^O(iL+u5^f%Ei;j@;wFO`)cVf3?aDTvFr*Hn zZDR@d5h5twNImt`#g#;kzT34fWWUijG}&(_D=8@tQR8sG>ZFqG2Dq_-_F#(zcp%u? zdz|x~ui$g|`<5jUNph!M&VC&-wA97SceXXocHAYN(^q! z=>csOUHtW8@Y99*=?<-dGY=6fq9bYM@eapsRx|rJGAUnm#)H#AXE}M3b`)!AsbFip z-J)`{e;g_7r+uM{H070&*BOfKA4jjHEOZ#BSf}~!VTQZ}`3%OK#e^(KWMUhpT`^K)y7o5P{K1yvk${l^l1QZdAo2 z*0CXOFPm@%%)U{z6@qPHQxX8>)f>?nZIp*9G$iVG?RJgkFfaN&-0A^f) zYQTC0Ek&RW2a8C2)$0!1qmiJM63H*ssz?$lbAVSO6I~m|FWaM&!Ics!Z#AGa4}2w3 zf9m!An&1>#yEE%TEhXH0xdHv&_a-hhI#Y`cEzi70EpLi!@gM24|MopNkvCi=R-B^9 zy*=3{Xr&UsFEyYy2Y5v?U$rmyr)V#%l&J#I_T5Ib+s_*cy~38nuFVN&ya;Gj7Vx{x zS&%bS9Vs9XNgw6L?HYcE!3KIArr3|}#~ll&p`>)rlgsn=WQ4($GD6;JKzSbcN)qvM zaMfanL(obI<(C@JnFG8snPjRUqV3HqA*6s-B3i%OkaqofL!mzJUtG26>I7aX;p(*p zH0KUbX~suA^cFa6Z?XkmDY@#k2IS@rP>J00{@Gc-ZJHgRrG&fhHlW`9yrF<|)3Cvd z7o*;|y=ixVma@Qow*d>>&l|Gf6gPsl%>fIulmX7G4d{2iZb&|@>XM%ZEt+@@v6OW4 zVgtg>w++cY9sDGxN7@s61G1EG`(^{m?Z*vC@BKXPU7Vsr3h}T#@;$JnEb!lMzy=>c zLstCf)mguL(QbreVU{w%d9?utoUa>_?>LYVEdW}L^di7Z84~-Z0cT=h8nUQAN^qI| zW!uX>4{Rx0{I?r0#0Suj6_PYFQ6a!i*sp_@bq~?OJMC$me zH)@eq1+J7>{a$Tq^@k0G_^00KMXLlGfTbkcH)|7ZKW#|%_~q5G)oE7nN{QA3*E3qA zHRj8PB)=H;Ta;^oR!XjVt@Z@xg0G~*qwe@>*dnnSUMace#o7d$FB{G-CFWbCn44TH zn59(f_i7VeGD@Ynropk0Q}5oZpn$cEE}T{{D-n*d8|ZTJD0K)=2IvyfO4=$UU*&_U zazPNeA20HUti_U(UU$^W)@+6)47oB#{&3Wako@F9 zEa!y(dM#Fz4pol@XWf=LKme;VfZuLLf6hSl$iG0UDEYB_)^EjBnz^xHtFyxSrWr#V z0FJvfU3{jC$!^DY8sli}?RtxQQBTk`e>IzIJL!8=&dqk6*Zpj-8@CQEEL9EV?Y!ho{c132itV8KlzE?dkK87^|xpRWpi@!0#hfN8A2B zgY7G~SBJon6G6_~a*lPdah)Ul!Zz>=-}rUZ@v3Kh00?cr4BW5&wPQM;Z7Hxb1KG#6H<~%3U%54! zQg^WL~m3g50~oleJ$>Bv-!+kL!dvzUB1scWOg#p4H2TJ+~Q(4-Oe|A zLxKDP0P%}sI)ACqOYI8xY2fBxYT_h@K0Nc{niDk+n)cx8hWTnj*W4uNrnR2USGO=3 zWILTcK0BDVX&S!ZOGnrNzqnvrNu}mMrK68H8$<-^Z|FK6-G*U{yC!gP4lrl-7h~p_ zb8a5`=l!b28-*-^o=MPI%(|IxWj_`-*k?I&+5<* zCL_IEV-R!uNt7&e-LP{DkoZ0o>*Vy9gH7u$=93-nwH3YS9ML^J6~+kY3nLW*tlRFC z6z$h!IL~b*Rs)AqE7?6I*sWkAv)&Yyd!H^=iUTYPV+Syxo%TE#MJ<;Yh%a8pE|@Da&V*ZbXW1YC)qB3Os+1vqY-*nw{tP?5SdwYE4M)HdRU)Bs*Ju< z5#ZseDRgrx-~7w(|C=XSMPGB^5bsi8O*!N*cdZi?kfDl}I~pi8O*!N*cdZi?kfDl}J15 zj#1%^yRPYfkx^^Nqykk+pnfkhT7FcfKWgZiuf{Lre%*W0NN`FCD!gUTkm~+LDd{ITvb0W_X`8;D`5pLzeWOpPcqjlF=AFCSF{f zwZV@7WGOSk_iJ$?{J0?-`lCVe!Sc_uwRYOwGC`f3@&kLwhLe-G< zyn+7cUSzg1p@PYiiex@%LS_tjC1)qN$t7vAf$KzVJeyA|lKC_?TE1^rct(KNAoH6x z)Kf6|CW48-VASu`QcnHRy@d7;?UDJ1ie&zw$!x}e*O<+3+avSaie!Gg1616d)(%F-@YLS-*xDt8&bLy+p?Vmj#{M?3&y6{Sg z^8R0Wvd4jlRoO-Nx_VE&j)NFn+vyxlG0>;DK4!9C zZ$&EyCY#4{6kr5Y{*(N7J;Oyu*z_q@aSgwnO$5E+z@@ zN8uR5iW5t7{{7}|)A^k>lNu@^gtM)1n)Z6=e6hn<(7AcKC_nCKCX_~yJH5FcJ>xS)D6*R3 zDF&UxWGo#wC?>>87oWlW-gALbhI*Khv?aLZIp)jt0P^1g3u91qjFwAsvE2ewqj=I3 zDb<=`a(0uqIGwp`pj)@w$>t6h!X+RC2T#}b$lo2V(%s`YqV0$%X2a1I=^RAIGqoOU+fZ5Ft$EPAZgImfErJ6lf?J7Fy4-er0V z1TZtJ>T>$y*ToYnfTMG(u%Av=>(w0S%zw2fHRLz&;2y_;`;eX9`)RtNqrJ8Zg?SW3 z3gcpt3?h#iatq7%LqkuFle%$zfs7jvE!zhmkJ=Z{>pYBOBLhOsKgf)^9X5p3wxdU8Ij(#tb>jf9w4iAX;PVhz z+~x(0%IENcB++(QY>RIBVx6{HAlV1%1B~miG0H(Ak4T%$X8FQ{msHqi)}o68S)Pz8 zqk9CF*mX0RFAj*W83Nni6C6s6e3@?@HHOm#H7Ch!G9s6wa%^f{yT;E`@A$H)3HV&K zSDutik6FCt`%pV?6*5qo9i%-s^DP2H=cd*?_JHB|E^A7V!e9%OC_((OX+R?CuB3`yqBBG4PqLTtr*U>_W`kv!)4>U%ELpKk6BET+D;u&>ICVWN zX$X91+dMH&^&UI{-ZUW|y3d}Wy7nyKR?&-}l8@TZxr*&ORd5m_ZRO6H-6 z1le|eeZVc(8T6FIm^bpQg8{4@_F}z$bJ*xOV1edchskX^p4?gkruCT&FJ-3f@&#@kP$6!KSQ)}Y+EJ5lfc{g9p*6()7d}h`WI?(FRoWbD2X(?2F)wfOM zbpQ2Xg%z>1fjWLYR8ODt)6S9nDjbYDSU*v!vlw&gWkjh)KfQ{uemhz1Ou7|tzYkt< z2XS>P?$ube-pn_fbe6nB?;%N_$f5o`X;b2%?vu7o-cz@S8!lG^eb(@rGFZ`-GP9Ca z8u=0ikfuvImmx%MW|9O2Z563eC;}C7dre3#7MJd+M{PQUcvu3ff^a z5i6Xm53Bv;dO;a%I*1r{=8CpP)0WJHDx&GSb{YO2bx5m@4t*)^I5I$X~k+XnFaohHbzdGE`#w$;i}Y6Ta?kx9cq}MN7DKFWgjo z7^0`_y>Q)QsIkWy!}D~vLx>eYGPGg%LYqF?PSXGO7++j0;q5tk>kMa`RqLR786&-2 z&u6Yb$f%Yj%GriUkg=cJe4MaE1s;Hng#ZjI?Gw9l>J(&D^%Q{VPqPZ-?=i7P{$xh`YGqJ7Nu^di5WfZX z|-#@ub&1q^i9(FHAXMObd>5d1(L>VWg zN!d89#;H>U3NA!-G1txBYzv$C;8o&7+siF~7-J5qkv{C9&rw_Lt{7Ae($(PgNY@`Z z95&Gf`({(L_fb+oycVS~jJeYZuq|pR^H#@7mpQACJx>OLpg^bfb&fFulXMcz?dMCZ zz>ywDc4(!N<+M?jHyR)Vse%Msu1?8PckJbEBDtJm=$awC%T!qZRm6fBVj8`Rue0Go za9&JTO186`VRDAYuk#o7YSzrV{I?Xu)tke-iE_mv5BvW!zv)~h{gbPN6rztVkmue1 zgqgXxI`90)pF7`u@m%R&H_!SkTaHB#K7Wk3Is+^DaqqD-B6iT^*o$V=El}+ zR0}o@1NqcW-_(~CVCssEU0GET92Y^Oi0;Phw$+WqKj0Y#H$TB4K-08K@tE;2 zL**v8T^-bW7-V~R&%3~SE5>E^njAS}0b8L7w&#M4mg0x)WNO#rwrGz(+@U;8@oY~$ z9sk_ydoji|h^c@qd~bHlTyVxRIEilK;_A3VvFmvS;=r1+{$@ws46F76f_1+jZ8zX- z1;O{3>cl8DuF&atA(7K8rGn=bV~BIfsII}^VcQ<^mNeyEp0t~RAhNu(iZ}|}Uln5r zt^b*jQn8&xQFvXy>Jw8cpL${_k9hg0%hMnkSur+rDF&*|py^?Y4e==omx}^1RT4f~ zQaag6iT>COSP&U3=GX6+i-hZAL>rMB$mabFn(F<-E=AN$$FC5Bvl8!)xlpllL_f(B zSQ6zcbNR2p8B@T6v%_%3*>z#OPz=%G?{OKMpo0?_`wy7U$t>LxG2cV-7ix#dU&mC~ zjXIlO|9pPdql~hP5?kL{x zwI;|MbVF{)up zK%(5J_BrS15+WAPfL1FJL@arHKT%d%bD20@FLQ{qFl)_?pgV=foJ0_l5Ilt&DNR%0NegS;k7_*?VhjJ5bwM_KG@$5#uvTEYX zZfR=A4swIidhoAEL#oY%6~Elsu#zI^ifx|nE+^Z`vf3zQH6!zEAvcgg!{KCw13?ic zn_YdlpPM5Btr5>Ye!en0$*K-YgC~ z+9*~LQbFwOSP%LpDlq~xU2gVtZK?;8DvaIOE}|MNI`?u7G7nLAY9&O1i)xcV5g{dk zR$N|-t+6QCT2bUpz6-J%c%s;tf(YnpP()qwoT??fmTFiXtZdme8`L;Dd8JG}1R|_n zl?seLooJ^ujAK-HI8>P~W52A{duA|_ITQ6=H7*gai-W>yaE!}~%$Mc$F9+=3V$)@I z!SSVaCWq_Ad>SJxAh`}Q%JBRqo(wE4WP~{V`t&=(pya96Y|AVa>6V=E^qA2<~KKpUOQA- z(%Ijo9j+_DVpY-=Sfzf@L6o;8v%(*@Un>5OcGiPYnVc+z}Um zqa+T!lL3o`tHHNQVOhW|afb%Nr{mYT^5YqT>hVc~DdLar_G0r6u**m+Q1*o6t=@dQRGXvzv|k`2uW_%OCuotNU>ceb zwuqN`#02J4n zNNbyn7WHd7`~0<@e^)&7*FLSAj(bdmi++=d_#{+{xNYXORe(Rdw3}TjYt-TdkY{gz z7(N49?Mrb3R9FHsJhJXUC!AVjn#?EXx|&Vt2`3oaWFO6AGlcME`{;;GYK9PhD=2Au z^Z;{6+c~u-kN1Ec5Gi3BwnA!S#$OJxhw^~fiP-DS=GrLo=cjtB(?qQ8Y-=($?Jag1 z6A5iHB(|yFN}*&`T$}ZxQff*4@Dj4u=Y!3`vC@2=2nW)*8oT@FuG4m?wOMkx(yH<7_oPtEM_e-Yx(tY6w-`g1^03-SD@!0KKa3>EhI(zxv>-&;shO+H zz^B`LZ*k_lnw5|}LZEt@voXmvFKUlWX%SV18=|Pa`$swhDWan{-NIfI{Jq|_ za?52r98Ddy*?YD7nc`Pe`X;&?twkb;HI#%j*iFB0S(o)ERnYchg-S)MDhh~jBeEMG z;VFHek6JYt-n_I{k&&M(D`1T3L6t1mvtvH0M(68pP*$z}*v@b7sHXb0dNEp_rGZSY zcN&N;Fs$?)RH4y#Qk;V8D_`B=9HFX;_-6f1BhZ|B+6Sg{TV)u9tz3+dL3ecH zy4wQ|qyc-;&ulf{|A83JZ@g1<()E&iu1FCHf!j@P(9U&>uI-!c`u&IK?9qF4H~=Tp z=5JGdC`nree0Ph}aS$%d5}i-LSqt>av8F-uKMGq*M*7R!`!kr3j58RV3Q7knoL+EP zbuu`=r1I_E{$;w@q;$Z9${<3E?6$7?UXf@tQuj+ln{%OH8=9v@QCyQ7d`io*nujK+B1D%2r5j*c_u{7o1rCT}xMZX)QLKAXwnRHJs?Fxlx$7v_L z|Ji4LT%F~ZHZ7>T*QTYG(?OAFqwki7h5oL&ub3`3`9PEdQzsYaRQh^0IO(4ClF_Tt zxOX1hSmkPDUbV3}94)i%$AU%;HGM>>T zbH@A?p|jrBX12jb&)95!56?*?rEjs8WCLI5KB4DQc_`MtQHS^2(|`M@btx?PUs0*e)hi4K4aSHTtvmRu#EHYqQ= zKlYOI(aB)g>m@ILCz>={?^n2LuRPw+W_PmN!L=_wD8s8C(~c$Sk$TLc>%?keXseo3 zoTR<~oB^X$devE08I5Ajflr!uF0V2ov`TL^I<+i38rJIXDqCuq6(unhrbQW3#tUXa zjwlG3m<>Gnah&wdFUPNxQExmaTO2Jn#*K$l5NGL>8Zc1<;_qYZtPlwwR?^B)D+*RJ zS*bQlLOloJI)>{P(KaWH$*zCpYf4P}V6JC{w~0dV~*4n42d3M8h-uBhD0d~6(P0Gj@_B>-IkZo~+cEpl6TUH>X6 zpxTTu8g%_Ds=8-HwvH)G)6cJ;d;{)^`LNv3r{0@$84wklL)iD=bOOO%+qC0iG5SCCcK9pRP!Owxt zw)GmZ@f*Z6zmkRhM#=WO_4W;J!kOaUU_7M&&5jgswDXt3#s>cUD=5}D(27{i@&2$~ znV#ZGjY#qwKG9K_W8CIQ*Zpa}W9@`q=CRN*eLufRV9$~3fd4QdvR;IPs3_l9Ukhn6 z81V?WT8b8C65?_PE6XmU2YS+dc4$7BWvO9@s0&ZfyZLN?=g2KTyh|yW7(QiUc}?I8 ztl)WvEAdvi-AHrr^CJe02^LrT`H?_%9$0|tVP(>eHErk+EK~J+x{%4tcKj-2MwIL< zdLW`@ftqTwM&HtP&0932!{UKXa?t8Qa2G|H>=L#=^qg6**Fg+&uNk0!1u=oS($i#S z7;R@3$?k5l#dR9wUU4-Eo{Z?hOY|GSrHn`N>mC0Eh@mU@L5c5VAo_drB_`IDV~TUn z`p-|UhG(WBplSv9_4}{C`}*eVZ_o&~^WB$^|M2BEo}w_)>25lq1S;X{4`p>nO^ng* zjJWFcs*Y+HGG>;7nk?W5^-%!n`*fP~y)qD-M2hJ&BLIb#tWFjMZGq(~5G%ACTe{r! zrv-_K{oI}5b9$iJCcm0_DxP6^8J#@$lx|}#Ilx>LDi|6!uWIJeg%KkI>`|LeIZRgi zln)29Af0X4*6=^kWPoo$EB}_2#iQR*7jMjfx*Rt7Bu>|x4~a}g4t0)TW`i*w7}=w+ zrr=L>#@rZ-ghr9nAX9&21@1NJ?F+JZju`vapPBp1Aw2+qN|xY!OhL0u z7Je;XH*56gL_iu!Sm#LI5FSxSyI=^5V>RQK?x9REUaMF^R4uclDOO>@5h*lpE*%L7 z$#7=1b7WL8FqxXac~=xN1636!X=gPCut3A)88$fb?3@3Z90}y#0qY8lFS4vyM*LtC z>~uOT$_jpoH+kCo`fKtgU47Gc2U#qnz`y(Q+b3Ustrh@g0q6HCW3C=HZ_*SAoUBO( zpR35i4m-i<=U67r&W+(nC4zV~2*LO?9l#n31sXct+5^GnyrE%;yer}^oJ4Yl;9^e2PzNQITB^11V=b0B?9vJi3kY7 zjX#P&_!w*^Sf#{=<{9A3dNpp<^FHNXRPs=cJ*Mrla6il4kCY%p!d2OmF$!1T6=e1> z*+>xzu=K@;jn(2<&|x?vx-snG^2yimI>gUR(%TO-;yK*nm{wMwY{W}=+cxRsNRBv^ z$5-f;p;AkQ5rG!Su7ZF^v_>L`JA72K8+=aW;5xDbBg9JE$hAx47&l@{l%0^sw<2OL zokdbEhFMdRNefxMA8{`L6^+q!SJ8gSz_<(-TcDqi9Kip4Hre1}Af)-R9{p-P-KYCU zcmoX}N_SnwZ?0NdsQGM^C8@(kC$#V*mMj~6NY0}7rCRTr;H!8YBsdT&sLiNzopP0x z#O_Y&Xplueem(lId&>mOq}GrqSgKG9w{e4n{M8)+nx*^66b-bZaPW2L2@MD6<2&RO zDq>LxM}+`wfI?+6(Zd=F`t_1mrSP0>6I9uwhB9{&q=wLclXr8nRdhJa!6t~E>8#ejEqHQFC=C`U{+BvuI{hpslhbKp8;nw z0YN2Wv|Bj~QiNLQ3hWevnD}IaJxwHUofcob#xa4PUM*yhaII%q10iG=RurpiOE@b= zjzH@IgiGo|nPThvzdN;YrZm+(yA)OJbaRcXcUOEl3RUv0S8aqiY#vB-@`4Ry>6er> z%FIpe_)X7D!DX99$Jsoe-1lBVcOQrG&m)qD>r+iu8+4MQRl5F(*LGT7NsRdR)izL| zX$1~~i5lUfWEP4p$20s#=$>adT0oDrKQN+HhK;Nk~dmvS*0lOQL;pNp%rGhvXn^De$M?!B|%FaclxiIL$5t#tI*z+vEm zKxMaQ)0{I-BjTSA25k~g;6VHzDiY75Hz7VVP9x&`7vmNu9?(Gg9ZoN$1g<(4HBm5%K+t%d2rRxEkX>El$4+7R<=K>@@0i+>aZHg$p1udLu?b$C8Wg zxJ{3sK}Jw4cFX$1M$FM4M@DVTn3I=X6-dP-xrxg(&F*GVz(Y#R`F{Xz) z=I$Aep|q%124-#6m@gX%jrlqJ6Dqg@ZUot?tRk$M3RKbfjhXeLH$Hj! z0Agj}He#0fx-qj1gvj{!Wmfy5rLb)(TlVw&@+*!(V}@M}hUeY0{@>a*S_W=pcFR@K zeBGE^20~=~n#_{9yBhWMY1CGnpFlnBz35(@)v;GuZ0cF7vT++R=dAm;S1oddz(wXQ zPi}-H#-Rx>az<;!i0)|AQs5{=F}&KW5GL zHDbc^!T4p1Tp)0@*}yn7;X}@7jTkX_{+})K0nlo*fiP&oh4@&FnD87Io1eDG28LIg z5rRb%R^*M>h#4n?v#axq7P%n+YqLY)(S#qlBQ|5m8SHPH{2+Ms*}+&e;zrJRjhKOL zfkBJBAaJ!=!8kPGM9yf981drjqMcln_(TF%n-Ppd6Gr5W)`$^53PS>^Go%Ql6@z>FYSyi7A+HsX!>Ix=n}=8Ss7etY>35gP+Df@Cps%$JRr zW4?}z+lV=r!@=b!IqQzw6demRf@U#$?5B%; z&Ks{LGrD8!vUab=19X=>@3)iH4`9|{O7LY(Q3<||jN61c*cD>i&`R{eC~Ali1oNcD z`>qLF3dU^0lyU#OhZ2VNc%lH-Wr@b4o(3^D^G9sLklt{3J~(a1*fM$wU|oi2JQ^@0 zf5avXfk*qXH`M(#+7lEXZe8~HUpG-CA3|jOCd@iH>-R3k?K8`V8$q_v-uPcPVU`ae zGJX?gsTt^Byl5xM!0P4zji6b`Cg;;8JaRsdjNF7ls42eaos9c~3zS=T$5-v-rI<|_ z&=HginUw+1gk>2Z5iA-pt~+Ycf}a3d1hHcF5C#owcg|Rim~b^54XE<&yiHzMptV_I zKW)Sr`*~#K<_v1jqoIES7#=~cSW@__<{XKP*Mu2^VfO?*pXt~_i)O}!8bP#>G48ib z*yDa58M_ISE_=gKA5F1as__j-Xt~vLAwI;JP^&<=Yfe}(u9Gh!#=I)+6@gHpb<0+8RmT2gi+4tk&&A)2$lZ*iy!(g zUL`EUZK`GlbOhx>W@P|0VOa)91dAq&JMaFCqmWcnkev0}sViVF>BEg6TgWp1>n8m2 zAw@iRq zFvxt{P<+hyk+EwsiLzaYLdRFbZab$#U4Rkv@?^*TtR`37Pa`8XVaVCwr(QcHG>jaB zi=bA>48ftE4i%2pgb`PlNK&+-H;fvCtIG(%p#dZEMytsPO31aUA}+uh%y2)esUq&D zkrA6PgfBUw9yD$F9mdgx8bLHqVKUz~;ZMofO_($uw9X*|vMzhfhfR26K8}p)F-Ce9 znMbNa4mIV0e@`w37d`cx^ayU)kw?RdU}HqY9kaUeP`#H51~9Z$>qR6PxWTZWT=af! zCwBEg7V#kHP~m@AQx5!(BcnEE%;m5@XvfJ|92sT=Nh2P)tPyOgOAIyDD<8Kpb6)g^ zEu9dzNHWYu%n@vwGAD1`#>_!YZ`&$GARDoUacRn#oKYJyru)2|tqdzOfY^vFgh^Ab z#K&yRlwq%(C5~kZAU0wOVbYW-@iA*MMK;Ql7eAd2F3#FHwCsbd!506+ntbs;j*Qxj zF{6{=pr!7C3PXVyK`_rFdEYhTN_I@!b>F$y1(DKl{jOpE>0b6)=;2{SSHPNI8bY@H zNX?~(yUy!A`Z7;&>{*UL2My)sgcfx6GdMBi%Ce z^CN_Ts?U40MW_00IeCAk@8bMge|$9KCbol(drzFKw*QCa_8y5)p4HWeYKcHXm_p0YIi#gq*V5j9?W<+kR zkXE~KvEpXQa>)Z-af+egOP)QG07-2}DNVygB9QgLc8=TW`5qGgWxYW5-@duQl?8b5 z>lRcbx68O`w9V9X7mHGY@(8rSc6$ zc&iG8MaQ>v^`rhbdsuDCO$g6q6x_tQnXMBEFyVI9J(6xH9$tI9pU*xdzyNn2t#0PG z$FJ!@=ZOA)>~mu_&3AYE zj=RYDmTGUhLmI`Q&?{6KwU_44+c4}ZjtbE!Uxxyl6A8guvf#uVQn3TBZm0io(6~QrSI%8J z@dZA+&_IaxE%k`8=nqN zc$B8jIe~XhX6tE)Y89hqA|@~q&iQmb)nDcMXBCpu95upN$B!YprRq4}{mgM^O9DrD zEEi3%zzU)z97yOXL=CYxrof9AvIIFIF3*&<%!Bb|#h4_V9{po8?&2q5H8d9vc3l5)C z(%-?)ysiBZ=DQPIFNy?l%&e>5g~nlpcmk6DZm^(B&FeNSCi|*%?&)f zpM8=Tu1r(ZI)nmq<7z*_@=xb=%Fvrkr|E8ou#k4)eELFFKCJjkUy~$A$VyYpRP#I7 zA@_@X8w3PCh6c|F3|mU^=`J*_7p@KR5SQfJr=N~WskwKP?F!bZ{&aY&T_a~LEXJ$K zk?2WnF_P3~6?)5)tY3ZA8Q-P56xY3`9jHBBoxNUlaBKG6dbaD_thcli_$6MN?>hLu z)q3BVbhhba(c#42m%o$z9u?`1{_AYMPm|tz@@8bvs)xQ+vnRV>78v3L36?lbg`Bt z)tl}gZMN$TE=iuJSmoj=MD7tTO`c=%`72E<9)9(^jDHj{9ILPkc9)&Ucl#Ob;hAC%>0jJ}TQi45p zSSB6pw3EpJsV0`GLsbonm4kAeTbk9z5Nhm_a$l5C$qDR5#2Mw_028*N)R?0^1N5g& z&Ia96Townh8{u#)d)^S;#d

    &61P&kbcsks&7Y9^mUnfoQ~PY~Ps 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∓zk|!-QM;dcpRoFvT}QOg(;Ys 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

  • Jw#7G?{D|BK<3+{KRdH^G;m$RE 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%0Aj3WgGVBA9VSf`D_O~FS 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

    + Build Status + Latest Stable Version + License + PHPStan Enabled +

    J5RPh~>9IQEDv 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 literal 157192 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

  • ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",customClass:"",sanitize:!0,sanitizeFn:null,whiteList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Ut={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},Mt={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Wt=function(){function t(t,e){if("undefined"==typeof a.default)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var e=t.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=o.default(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(o.default(this.getTipElement()).hasClass(Rt))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),o.default.removeData(this.element,this.constructor.DATA_KEY),o.default(this.element).off(this.constructor.EVENT_KEY),o.default(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&o.default(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===o.default(this.element).css("display"))throw new Error("Please use show on visible elements");var e=o.default.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){o.default(this.element).trigger(e);var n=d.findShadowRoot(this.element),i=o.default.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var s=this.getTipElement(),l=d.getUID(this.constructor.NAME);s.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&o.default(s).addClass(Lt);var r="function"==typeof this.config.placement?this.config.placement.call(this,s,this.element):this.config.placement,u=this._getAttachment(r);this.addAttachmentClass(u);var f=this._getContainer();o.default(s).data(this.constructor.DATA_KEY,this),o.default.contains(this.element.ownerDocument.documentElement,this.tip)||o.default(s).appendTo(f),o.default(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new a.default(this.element,s,this._getPopperConfig(u)),o.default(s).addClass(Rt),o.default(s).addClass(this.config.customClass),"ontouchstart"in document.documentElement&&o.default(document.body).children().on("mouseover",null,o.default.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,o.default(t.element).trigger(t.constructor.Event.SHOWN),e===qt&&t._leave(null,t)};if(o.default(this.tip).hasClass(Lt)){var h=d.getTransitionDurationFromElement(this.tip);o.default(this.tip).one(d.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(t){var e=this,n=this.getTipElement(),i=o.default.Event(this.constructor.Event.HIDE),a=function(){e._hoverState!==xt&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),o.default(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(o.default(this.element).trigger(i),!i.isDefaultPrevented()){if(o.default(n).removeClass(Rt),"ontouchstart"in document.documentElement&&o.default(document.body).children().off("mouseover",null,o.default.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,o.default(this.tip).hasClass(Lt)){var s=d.getTransitionDurationFromElement(n);o.default(n).one(d.TRANSITION_END,a).emulateTransitionEnd(s)}else a();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-tooltip-"+t)},e.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},e.setContent=function(){var t=this.getTipElement();this.setElementContent(o.default(t.querySelectorAll(".tooltip-inner")),this.getTitle()),o.default(t).removeClass("fade show")},e.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=At(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?o.default(e).parent().is(t)||t.empty().append(e):t.text(o.default(e).text())},e.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},e._getPopperConfig=function(t){var e=this;return r({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=r({},e.offsets,t.config.offset(e.offsets,t.element)),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:d.isElement(this.config.container)?o.default(this.config.container):o.default(document).find(this.config.container)},e._getAttachment=function(t){return Bt[t.toUpperCase()]},e._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)o.default(t.element).on(t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n=e===Ft?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i=e===Ft?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;o.default(t.element).on(n,t.config.selector,(function(e){return t._enter(e)})).on(i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t.element&&t.hide()},o.default(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=r({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Qt:Ft]=!0),o.default(e.getTipElement()).hasClass(Rt)||e._hoverState===xt?e._hoverState=xt:(clearTimeout(e._timeout),e._hoverState=xt,e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){e._hoverState===xt&&e.show()}),e.config.delay.show):e.show())},e._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||o.default(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),o.default(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Qt:Ft]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=qt,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){e._hoverState===qt&&e.hide()}),e.config.delay.hide):e.hide())},e._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},e._getConfig=function(t){var e=o.default(this.element).data();return Object.keys(e).forEach((function(t){-1!==Pt.indexOf(t)&&delete e[t]})),"number"==typeof(t=r({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),d.typeCheckConfig(It,t,this.constructor.DefaultType),t.sanitize&&(t.template=At(t.template,t.whiteList,t.sanitizeFn)),t},e._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},e._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(jt);null!==e&&e.length&&t.removeClass(e.join(""))},e._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},e._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(o.default(t).removeClass(Lt),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(kt),a="object"==typeof e&&e;if((i||!/dispose|hide/.test(e))&&(i||(i=new t(this,a),n.data(kt,i)),"string"==typeof e)){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Ht}},{key:"NAME",get:function(){return It}},{key:"DATA_KEY",get:function(){return kt}},{key:"Event",get:function(){return Mt}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Ut}}]),t}();o.default.fn.tooltip=Wt._jQueryInterface,o.default.fn.tooltip.Constructor=Wt,o.default.fn.tooltip.noConflict=function(){return o.default.fn.tooltip=Ot,Wt._jQueryInterface};var Vt="bs.popover",zt=o.default.fn.popover,Kt=new RegExp("(^|\\s)bs-popover\\S+","g"),Xt=r({},Wt.Default,{placement:"right",trigger:"click",content:"",template:''}),Yt=r({},Wt.DefaultType,{content:"(string|element|function)"}),$t={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},Jt=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,u(e,n);var a=i.prototype;return a.isWithContent=function(){return this.getTitle()||this._getContent()},a.addAttachmentClass=function(t){o.default(this.getTipElement()).addClass("bs-popover-"+t)},a.getTipElement=function(){return this.tip=this.tip||o.default(this.config.template)[0],this.tip},a.setContent=function(){var t=o.default(this.getTipElement());this.setElementContent(t.find(".popover-header"),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(".popover-body"),e),t.removeClass("fade show")},a._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},a._cleanTipClass=function(){var t=o.default(this.getTipElement()),e=t.attr("class").match(Kt);null!==e&&e.length>0&&t.removeClass(e.join(""))},i._jQueryInterface=function(t){return this.each((function(){var e=o.default(this).data(Vt),n="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new i(this,n),o.default(this).data(Vt,e)),"string"==typeof t)){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},l(i,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"Default",get:function(){return Xt}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return Vt}},{key:"Event",get:function(){return $t}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Yt}}]),i}(Wt);o.default.fn.popover=Jt._jQueryInterface,o.default.fn.popover.Constructor=Jt,o.default.fn.popover.noConflict=function(){return o.default.fn.popover=zt,Jt._jQueryInterface};var Gt="scrollspy",Zt="bs.scrollspy",te=o.default.fn[Gt],ee="active",ne="position",ie=".nav, .list-group",oe={offset:10,method:"auto",target:""},ae={offset:"number",method:"string",target:"(string|element)"},se=function(){function t(t,e){var n=this;this._element=t,this._scrollElement="BODY"===t.tagName?window:t,this._config=this._getConfig(e),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,o.default(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return n._process(t)})),this.refresh(),this._process()}var e=t.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":ne,n="auto"===this._config.method?e:this._config.method,i=n===ne?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(t){var e,a=d.getSelectorFromElement(t);if(a&&(e=document.querySelector(a)),e){var s=e.getBoundingClientRect();if(s.width||s.height)return[o.default(e)[n]().top+i,a]}return null})).filter(Boolean).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},e.dispose=function(){o.default.removeData(this._element,Zt),o.default(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(t){if("string"!=typeof(t=r({},oe,"object"==typeof t&&t?t:{})).target&&d.isElement(t.target)){var e=o.default(t.target).attr("id");e||(e=d.getUID(Gt),o.default(t.target).attr("id",e)),t.target="#"+e}return d.typeCheckConfig(Gt,t,ae),t},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t li > .active",ge=function(){function t(t){this._element=t}var e=t.prototype;return e.show=function(){var t=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&o.default(this._element).hasClass(ue)||o.default(this._element).hasClass("disabled")||this._element.hasAttribute("disabled"))){var e,n,i=o.default(this._element).closest(".nav, .list-group")[0],a=d.getSelectorFromElement(this._element);if(i){var s="UL"===i.nodeName||"OL"===i.nodeName?he:ce;n=(n=o.default.makeArray(o.default(i).find(s)))[n.length-1]}var l=o.default.Event("hide.bs.tab",{relatedTarget:this._element}),r=o.default.Event("show.bs.tab",{relatedTarget:n});if(n&&o.default(n).trigger(l),o.default(this._element).trigger(r),!r.isDefaultPrevented()&&!l.isDefaultPrevented()){a&&(e=document.querySelector(a)),this._activate(this._element,i);var u=function(){var e=o.default.Event("hidden.bs.tab",{relatedTarget:t._element}),i=o.default.Event("shown.bs.tab",{relatedTarget:n});o.default(n).trigger(e),o.default(t._element).trigger(i)};e?this._activate(e,e.parentNode,u):u()}}},e.dispose=function(){o.default.removeData(this._element,le),this._element=null},e._activate=function(t,e,n){var i=this,a=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?o.default(e).children(ce):o.default(e).find(he))[0],s=n&&a&&o.default(a).hasClass(fe),l=function(){return i._transitionComplete(t,a,n)};if(a&&s){var r=d.getTransitionDurationFromElement(a);o.default(a).removeClass(de).one(d.TRANSITION_END,l).emulateTransitionEnd(r)}else l()},e._transitionComplete=function(t,e,n){if(e){o.default(e).removeClass(ue);var i=o.default(e.parentNode).find("> .dropdown-menu .active")[0];i&&o.default(i).removeClass(ue),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}o.default(t).addClass(ue),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),d.reflow(t),t.classList.contains(fe)&&t.classList.add(de);var a=t.parentNode;if(a&&"LI"===a.nodeName&&(a=a.parentNode),a&&o.default(a).hasClass("dropdown-menu")){var s=o.default(t).closest(".dropdown")[0];if(s){var l=[].slice.call(s.querySelectorAll(".dropdown-toggle"));o.default(l).addClass(ue)}t.setAttribute("aria-expanded",!0)}n&&n()},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(le);if(i||(i=new t(this),n.data(le,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}}]),t}();o.default(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',(function(t){t.preventDefault(),ge._jQueryInterface.call(o.default(this),"show")})),o.default.fn.tab=ge._jQueryInterface,o.default.fn.tab.Constructor=ge,o.default.fn.tab.noConflict=function(){return o.default.fn.tab=re,ge._jQueryInterface};var me="bs.toast",pe=o.default.fn.toast,_e="hide",ve="show",ye="showing",be="click.dismiss.bs.toast",Ee={animation:!0,autohide:!0,delay:500},Te={animation:"boolean",autohide:"boolean",delay:"number"},we=function(){function t(t,e){this._element=t,this._config=this._getConfig(e),this._timeout=null,this._setListeners()}var e=t.prototype;return e.show=function(){var t=this,e=o.default.Event("show.bs.toast");if(o.default(this._element).trigger(e),!e.isDefaultPrevented()){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var n=function(){t._element.classList.remove(ye),t._element.classList.add(ve),o.default(t._element).trigger("shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove(_e),d.reflow(this._element),this._element.classList.add(ye),this._config.animation){var i=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains(ve)){var t=o.default.Event("hide.bs.toast");o.default(this._element).trigger(t),t.isDefaultPrevented()||this._close()}},e.dispose=function(){this._clearTimeout(),this._element.classList.contains(ve)&&this._element.classList.remove(ve),o.default(this._element).off(be),o.default.removeData(this._element,me),this._element=null,this._config=null},e._getConfig=function(t){return t=r({},Ee,o.default(this._element).data(),"object"==typeof t&&t?t:{}),d.typeCheckConfig("toast",t,this.constructor.DefaultType),t},e._setListeners=function(){var t=this;o.default(this._element).on(be,'[data-dismiss="toast"]',(function(){return t.hide()}))},e._close=function(){var t=this,e=function(){t._element.classList.add(_e),o.default(t._element).trigger("hidden.bs.toast")};if(this._element.classList.remove(ve),this._config.animation){var n=d.getTransitionDurationFromElement(this._element);o.default(this._element).one(d.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},e._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},t._jQueryInterface=function(e){return this.each((function(){var n=o.default(this),i=n.data(me);if(i||(i=new t(this,"object"==typeof e&&e),n.data(me,i)),"string"==typeof e){if("undefined"==typeof i[e])throw new TypeError('No method named "'+e+'"');i[e](this)}}))},l(t,null,[{key:"VERSION",get:function(){return"4.6.2"}},{key:"DefaultType",get:function(){return Te}},{key:"Default",get:function(){return Ee}}]),t}();o.default.fn.toast=we._jQueryInterface,o.default.fn.toast.Constructor=we,o.default.fn.toast.noConflict=function(){return o.default.fn.toast=pe,we._jQueryInterface},t.Alert=g,t.Button=E,t.Carousel=P,t.Collapse=V,t.Dropdown=lt,t.Modal=Ct,t.Popover=Jt,t.Scrollspy=se,t.Tab=ge,t.Toast=we,t.Tooltip=Wt,t.Util=d,Object.defineProperty(t,"__esModule",{value:!0})})); +//# sourceMappingURL=bootstrap.min.js.map \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js new file mode 100644 index 000000000..166487309 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/d3.min.js @@ -0,0 +1,5 @@ +!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function i(n){return!isNaN(n)}function u(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)<0?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n(t[u],e)>0?i=u:r=u+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function f(n){return(n+="")===bo||n[0]===_o?_o+n:n}function s(n){return(n+="")[0]===_o?n.slice(1):n}function h(n){return f(n)in this._}function p(n){return(n=f(n))in this._&&delete this._[n]}function g(){var n=[];for(var t in this._)n.push(s(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function y(){this._=Object.create(null)}function m(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=wo.length;r>e;++e){var i=wo[e]+t;if(i in n)return i}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,i=-1,u=r.length;++ie;e++)for(var i,u=n[e],o=0,a=u.length;a>o;o++)(i=u[o])&&t(i,o,e);return n}function Z(n){return ko(n,qo),n}function V(n){var t,e;return function(r,i,u){var o,a=n[u].update,l=a.length;for(u!=e&&(e=u,t=0),i>=t&&(t=i+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var c=To.get(n);return c&&(n=c,l=B),a?t?i:r:t?b:u}function $(n,t){return function(e){var r=ao.event;ao.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ao.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Do,i="click"+r,u=ao.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ro&&(Ro="onselectstart"in e?!1:x(e.style,"userSelect")),Ro){var o=n(e).style,a=o[Ro];o[Ro]="none"}return function(n){if(u.on(r,null),Ro&&(o[Ro]=a),n){var t=function(){u.on(i,null)};u.on(i,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var i=r.createSVGPoint();if(0>Po){var u=t(n);if(u.scrollX||u.scrollY){r=ao.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Po=!(o.f||o.e),r.remove()}}return Po?(i.x=e.pageX,i.y=e.pageY):(i.x=e.clientX,i.y=e.clientY),i=i.matrixTransform(n.getScreenCTM().inverse()),[i.x,i.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ao.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?Fo:Math.acos(n)}function tn(n){return n>1?Io:-1>n?-Io:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function on(n){return(n=Math.sin(n/2))*n}function an(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(o-u)*n/60:180>n?o:240>n?u+(o-u)*(240-n)/60:u}function i(n){return Math.round(255*r(n))}var u,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,u=2*e-o,new mn(i(n+120),i(n),i(n-120))}function fn(n,t,e){return this instanceof fn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof fn?new fn(n.h,n.c,n.l):n instanceof hn?gn(n.l,n.a,n.b):gn((n=Sn((n=ao.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new fn(n,t,e)}function sn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Yo)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof fn?sn(n.h,n.c,n.l):Sn((n=mn(n)).r,n.g,n.b):new hn(n,t,e)}function pn(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=vn(i)*na,r=vn(r)*ta,u=vn(u)*ea,new mn(yn(3.2404542*i-1.5371385*r-.4985314*u),yn(-.969266*i+1.8760108*r+.041556*u),yn(.0556434*i-.2040259*r+1.0572252*u))}function gn(n,t,e){return n>0?new fn(Math.atan2(e,t)*Zo,Math.sqrt(t*t+e*e),n):new fn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function yn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mn(n,t,e){return this instanceof mn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mn?new mn(n.r,n.g,n.b):_n(""+n,mn,cn):new mn(n,t,e)}function Mn(n){return new mn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,i,u,o=0,a=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Nn(i[0]),Nn(i[1]),Nn(i[2]))}return(u=ua.get(n))?t(u.r,u.g,u.b):(null==n||"#"!==n.charAt(0)||isNaN(u=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&u)>>4,o=o>>4|o,a=240&u,a=a>>4|a,l=15&u,l=l<<4|l):7===n.length&&(o=(16711680&u)>>16,a=(65280&u)>>8,l=255&u)),t(o,a,l))}function wn(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-u,l=(o+u)/2;return a?(i=.5>l?a/(o+u):a/(2-o-u),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=NaN,i=l>0&&1>l?0:r),new ln(r,i,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/na),i=dn((.2126729*n+.7151522*t+.072175*e)/ta),u=dn((.0193339*n+.119192*t+.9503041*e)/ea);return hn(116*i-16,500*(r-i),200*(i-u))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function i(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(u,l)}catch(r){return void o.error.call(u,r)}o.load.call(u,n)}else o.error.call(u,l)}var u={},o=ao.dispatch("beforesend","progress","load","error"),a={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=i:l.onreadystatechange=function(){l.readyState>3&&i()},l.onprogress=function(n){var t=ao.event;ao.event=n;try{o.progress.call(u,l)}finally{ao.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.responseType=function(n){return arguments.length?(c=n,u):c},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(co(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),l.setRequestHeader)for(var f in a)l.setRequestHeader(f,a[f]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),o.beforesend.call(u,l),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},ao.rebind(u,o,"on"),null==r?u:u.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var i=e+t,u={c:n,t:i,n:null};return aa?aa.n=u:oa=u,aa=u,la||(ca=clearTimeout(ca),la=1,fa(Tn)),u}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(ca),ca=setTimeout(Tn,t)),la=0):(la=1,fa(Tn))}function Rn(){for(var n=Date.now(),t=oa;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=oa,e=1/0;t;)t.c?(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function jn(n){var t=n.decimal,e=n.thousands,r=n.grouping,i=n.currency,u=r&&e?function(n,t){for(var i=n.length,u=[],o=0,a=r[0],l=0;i>0&&a>0&&(l+a+1>t&&(a=Math.max(1,t-l)),u.push(n.substring(i-=a,i+a)),!((l+=a+1)>t));)a=r[o=(o+1)%r.length];return u.reverse().join(e)}:m;return function(n){var e=ha.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",l=e[4]||"",c=e[5],f=+e[6],s=e[7],h=e[8],p=e[9],g=1,v="",d="",y=!1,m=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===o)&&(c=r="0",o="="),p){case"n":s=!0,p="g";break;case"%":g=100,d="%",p="f";break;case"p":g=100,d="%",p="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+p.toLowerCase());case"c":m=!1;case"d":y=!0,h=0;break;case"s":g=-1,p="r"}"$"===l&&(v=i[0],d=i[1]),"r"!=p||h||(p="g"),null!=h&&("g"==p?h=Math.max(1,Math.min(21,h)):"e"!=p&&"f"!=p||(h=Math.max(0,Math.min(20,h)))),p=pa.get(p)||Fn;var M=c&&s;return function(n){var e=d;if(y&&n%1)return"";var i=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>g){var l=ao.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=g;n=p(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=m?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&s&&(x=u(x,1/0));var S=v.length+x.length+b.length+(M?0:i.length),k=f>S?new Array(S=f-S+1).join(r):"";return M&&(x=u(k+x,k.length?f-b.length:1/0)),i+=v,n=x+b,("<"===o?i+n+k:">"===o?k+i+n:"^"===o?k.substring(0,S>>=1)+i+n+k.substring(S):i+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new va(e-1)),1),e}function u(n,e){return t(n=new va(+n),e),n}function o(n,r,u){var o=i(n),a=[];if(u>1)for(;r>o;)e(o)%u||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{va=Hn;var r=new Hn;return r._=n,o(r,t,e)}finally{va=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.range=o;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(i),l.offset=In(u),l.range=a,n}function In(n){return function(t,e){try{va=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{va=Date}}}function Yn(n){function t(n){function t(t){for(var e,i,u,o=[],a=-1,l=0;++aa;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(o=t.charAt(a++),u=C[o in ya?t.charAt(a++):o],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function f(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var s=n.dateTime,h=n.date,p=n.time,g=n.periods,v=n.days,d=n.shortDays,y=n.months,m=n.shortMonths;t.utc=function(n){function e(n){try{va=Hn;var t=new va;return t._=n,r(t)}finally{va=Date}}var r=t(n);return e.parse=function(n){try{va=Hn;var t=r.parse(n);return t&&t._}finally{va=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=ao.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(y),k=Xn(y),N=Vn(m),E=Xn(m);g.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return m[n.getMonth()]},B:function(n){return y[n.getMonth()]},c:t(s),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ga.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return g[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ga.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ga.mondayOfYear(n),t,2)},x:t(h),X:t(p),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:at,"%":function(){return"%"}},C={a:r,A:i,b:u,B:o,c:a,d:tt,e:tt,H:rt,I:rt,j:et,L:ot,m:nt,M:it,p:f,S:ut,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",i=(r?-n:n)+"",u=i.length;return r+(e>u?new Array(e-u+1).join(t)+i:i)}function Vn(n){return new RegExp("^(?:"+n.map(ao.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e68?1900:2e3)}function nt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function it(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function ut(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ot(n,t,e){ma.lastIndex=0;var r=ma.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function at(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=xo(t)/60|0,i=xo(t)%60;return e+Zn(r,"0",2)+Zn(i,"0",2)}function lt(n,t,e){Ma.lastIndex=0;var r=Ma.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,l=Math.cos(t),c=Math.sin(t),f=u*c,s=i*l+f*Math.cos(a),h=f*o*Math.sin(a);ka.add(Math.atan2(h,s)),r=n,i=l,u=c}var t,e,r,i,u;Na.point=function(o,a){Na.point=n,r=(t=o)*Yo,i=Math.cos(a=(e=a)*Yo/2+Fo/4),u=Math.sin(a)},Na.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function yt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function mt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return xo(n[0]-t[0])a;++a)i.point((e=n[a])[0],e[1]);return void i.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,u.push(l),o.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,u.push(l),o.push(c)}}),o.sort(t),qt(u),qt(o),u.length){for(var a=0,l=e,c=o.length;c>a;++a)o[a].e=l=!l;for(var f,s,h=u[0];;){for(var p=h,g=!0;p.v;)if((p=p.n)===h)return;f=p.z,i.lineStart();do{if(p.v=p.o.v=!0,p.e){if(g)for(var a=0,c=f.length;c>a;++a)i.point((s=f[a])[0],s[1]);else r(p.x,p.n.x,1,i);p=p.n}else{if(g){f=p.p.z;for(var a=f.length-1;a>=0;--a)i.point((s=f[a])[0],s[1])}else r(p.x,p.p.x,-1,i);p=p.p}p=p.o,f=p.z,g=!g}while(!p.v);i.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r0){for(b||(u.polygonStart(),b=!0),u.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),p.push(e.filter(Dt))}var p,g,v,d=t(u),y=i.invert(r[0],r[1]),m={point:o,lineStart:l,lineEnd:c,polygonStart:function(){m.point=f,m.lineStart=s,m.lineEnd=h,p=[],g=[]},polygonEnd:function(){m.point=o,m.lineStart=l,m.lineEnd=c,p=ao.merge(p);var n=Ot(y,g);p.length?(b||(u.polygonStart(),b=!0),Lt(p,Ut,n,e,u)):n&&(b||(u.polygonStart(),b=!0),u.lineStart(),e(null,null,1,u),u.lineEnd()),b&&(u.polygonEnd(),b=!1),p=g=null},sphere:function(){u.polygonStart(),u.lineStart(),e(null,null,1,u),u.lineEnd(),u.polygonEnd()}},M=Pt(),x=t(M),b=!1;return m}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ut(n,t){return((n=n.x)[0]<0?n[1]-Io-Uo:Io-n[1])-((t=t.x)[0]<0?t[1]-Io-Uo:Io-t[1])}function jt(n){var t,e=NaN,r=NaN,i=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(u,o){var a=u>0?Fo:-Fo,l=xo(u-e);xo(l-Fo)0?Io:-Io),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(u,r),t=0):i!==a&&l>=Fo&&(xo(e-i)Uo?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*o)):(t+r)/2}function Ht(n,t,e,r){var i;if(null==n)i=e*Io,r.point(-Fo,i),r.point(0,i),r.point(Fo,i),r.point(Fo,0),r.point(Fo,-i),r.point(0,-i),r.point(-Fo,-i),r.point(-Fo,0),r.point(-Fo,i);else if(xo(n[0]-t[0])>Uo){var u=n[0]a;++a){var c=t[a],f=c.length;if(f)for(var s=c[0],h=s[0],p=s[1]/2+Fo/4,g=Math.sin(p),v=Math.cos(p),d=1;;){d===f&&(d=0),n=c[d];var y=n[0],m=n[1]/2+Fo/4,M=Math.sin(m),x=Math.cos(m),b=y-h,_=b>=0?1:-1,w=_*b,S=w>Fo,k=g*M;if(ka.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),u+=S?b+_*Ho:b,S^h>=e^y>=e){var N=mt(dt(s),dt(n));bt(N);var E=mt(i,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=y,g=M,v=x,s=n}}return(-Uo>u||Uo>u&&-Uo>ka)^1&o}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,l,c,f;return{lineStart:function(){c=l=!1,f=1},point:function(s,h){var p,g=[s,h],v=t(s,h),d=o?v?0:i(s,h):v?i(s+(0>s?Fo:-Fo),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(p=r(e,g),(wt(e,p)||wt(g,p))&&(g[0]+=Uo,g[1]+=Uo,v=t(g[0],g[1]))),v!==l)f=0,v?(n.lineStart(),p=r(g,e),n.point(p[0],p[1])):(p=r(e,g),n.point(p[0],p[1]),n.lineEnd()),e=p;else if(a&&e&&o^v){var y;d&u||!(y=r(g,e,!0))||(f=0,o?(n.lineStart(),n.point(y[0][0],y[0][1]),n.point(y[1][0],y[1][1]),n.lineEnd()):(n.point(y[1][0],y[1][1]),n.lineEnd(),n.lineStart(),n.point(y[0][0],y[0][1])))}!v||e&&wt(e,g)||n.point(g[0],g[1]),e=g,l=v,u=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return f|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),i=dt(t),o=[1,0,0],a=mt(r,i),l=yt(a,a),c=a[0],f=l-c*c;if(!f)return!e&&n;var s=u*l/f,h=-u*c/f,p=mt(o,a),g=xt(o,s),v=xt(a,h);Mt(g,v);var d=p,y=yt(g,d),m=yt(d,d),M=y*y-m*(yt(g,g)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-y-x)/m);if(Mt(b,g),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=xo(E-Fo)E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(xo(b[0]-w)Fo^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-y+x)/m);return Mt(z,g),[b,_t(z)]}}}function i(t,e){var r=o?n:Fo-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),o=u>0,a=xo(u)>Uo,l=ve(n,6*Yo);return Rt(t,e,l,o?[0,-n]:[-Fo,n-Fo])}function Yt(n,t,e,r){return function(i){var u,o=i.a,a=i.b,l=o.x,c=o.y,f=a.x,s=a.y,h=0,p=1,g=f-l,v=s-c;if(u=n-l,g||!(u>0)){if(u/=g,0>g){if(h>u)return;p>u&&(p=u)}else if(g>0){if(u>p)return;u>h&&(h=u)}if(u=e-l,g||!(0>u)){if(u/=g,0>g){if(u>p)return;u>h&&(h=u)}else if(g>0){if(h>u)return;p>u&&(p=u)}if(u=t-c,v||!(u>0)){if(u/=v,0>v){if(h>u)return;p>u&&(p=u)}else if(v>0){if(u>p)return;u>h&&(h=u)}if(u=r-c,v||!(0>u)){if(u/=v,0>v){if(u>p)return;u>h&&(h=u)}else if(v>0){if(h>u)return;p>u&&(p=u)}return h>0&&(i.a={x:l+h*g,y:c+h*v}),1>p&&(i.b={x:l+p*g,y:c+p*v}),i}}}}}}function Zt(n,t,e,r){function i(r,i){return xo(r[0]-n)0?0:3:xo(r[0]-e)0?2:1:xo(r[1]-t)0?1:0:i>0?3:2}function u(n,t){return o(n.x,t.x)}function o(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function l(n){for(var t=0,e=d.length,r=n[1],i=0;e>i;++i)for(var u,o=1,a=d[i],l=a.length,c=a[0];l>o;++o)u=a[o],c[1]<=r?u[1]>r&&Q(c,u,n)>0&&++t:u[1]<=r&&Q(c,u,n)<0&&--t,c=u;return 0!==t}function c(u,a,l,c){var f=0,s=0;if(null==u||(f=i(u,l))!==(s=i(a,l))||o(u,a)<0^l>0){do c.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+l+4)%4)!==s)}else c.point(a[0],a[1])}function f(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function s(n,t){f(n,t)&&a.point(n,t)}function h(){C.point=g,d&&d.push(y=[]),S=!0,w=!1,b=_=NaN}function p(){v&&(g(m,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=s,w&&a.lineEnd()}function g(n,t){n=Math.max(-Ha,Math.min(Ha,n)),t=Math.max(-Ha,Math.min(Ha,t));var e=f(n,t);if(d&&y.push([n,t]),S)m=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,y,m,M,x,b,_,w,S,k,N=a,E=Pt(),A=Yt(n,t,e,r),C={point:s,lineStart:h,lineEnd:p,polygonStart:function(){a=E,v=[],d=[],k=!0},polygonEnd:function(){a=N,v=ao.merge(v);var t=l([n,r]),e=k&&t,i=v.length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),c(null,null,1,a),a.lineEnd()),i&&Lt(v,u,t,c,a),a.polygonEnd()),v=d=y=null}};return C}}function Vt(n){var t=0,e=Fo/3,r=ae(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Fo/180,e=n[1]*Fo/180):[t/Fo*180,e/Fo*180]},i}function Xt(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),o-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),o=Math.sqrt(u)/i;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/i,tn((u-(n*n+e*e)*i*i)/(2*i))]},e}function $t(){function n(n,t){Ia+=i*n-r*t,r=n,i=t}var t,e,r,i;$a.point=function(u,o){$a.point=n,t=r=u,e=i=o},$a.lineEnd=function(){n(t,e)}}function Bt(n,t){Ya>n&&(Ya=n),n>Va&&(Va=n),Za>t&&(Za=t),t>Xa&&(Xa=t)}function Wt(){function n(n,t){o.push("M",n,",",t,u)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function i(){o.push("Z")}var u=Jt(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return u=Jt(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ca+=n,za+=t,++La}function Kt(){function n(n,r){var i=n-t,u=r-e,o=Math.sqrt(i*i+u*u);qa+=o*(t+n)/2,Ta+=o*(e+r)/2,Ra+=o,Gt(t=n,e=r)}var t,e;Wa.point=function(r,i){Wa.point=n,Gt(t=r,e=i)}}function Qt(){Wa.point=Gt}function ne(){function n(n,t){var e=n-r,u=t-i,o=Math.sqrt(e*e+u*u);qa+=o*(r+n)/2,Ta+=o*(i+t)/2,Ra+=o,o=i*n-r*t,Da+=o*(r+n),Pa+=o*(i+t),Ua+=3*o,Gt(r=n,i=t)}var t,e,r,i;Wa.point=function(u,o){Wa.point=n,Gt(t=r=u,e=i=o)},Wa.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,Ho)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function i(){a.point=t}function u(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=i,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function ee(n){function t(n){return(a?r:e)(n)}function e(t){return ue(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=u,t.lineStart()}function u(e,r){var u=dt([e,r]),o=n(e,r);i(M,x,m,b,_,w,M=o[0],x=o[1],m=e,b=u[0],_=u[1],w=u[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function l(){ +r(),S.point=c,S.lineEnd=f}function c(n,t){u(s=n,h=t),p=M,g=x,v=b,d=_,y=w,S.point=u}function f(){i(M,x,m,b,_,w,p,g,s,v,d,y,a,t),S.lineEnd=o,o()}var s,h,p,g,v,d,y,m,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function i(t,e,r,a,l,c,f,s,h,p,g,v,d,y){var m=f-t,M=s-e,x=m*m+M*M;if(x>4*u&&d--){var b=a+p,_=l+g,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=xo(xo(w)-1)u||xo((m*z+M*L)/x-.5)>.3||o>a*p+l*g+c*v)&&(i(t,e,r,a,l,c,A,C,N,b/=S,_/=S,w,d,y),y.point(A,C),i(A,C,N,b,_,w,f,s,h,p,g,v,d,y))}}var u=.5,o=Math.cos(30*Yo),a=16;return t.precision=function(n){return arguments.length?(a=(u=n*n)>0&&16,t):Math.sqrt(u)},t}function re(n){var t=ee(function(t,e){return n([t*Zo,e*Zo])});return function(n){return le(t(n))}}function ie(n){this.stream=n}function ue(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function oe(n){return ae(function(){return n})()}function ae(n){function t(n){return n=a(n[0]*Yo,n[1]*Yo),[n[0]*h+l,c-n[1]*h]}function e(n){return n=a.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Zo,n[1]*Zo]}function r(){a=Ct(o=se(y,M,x),u);var n=u(v,d);return l=p-n[0]*h,c=g+n[1]*h,i()}function i(){return f&&(f.valid=!1,f=null),t}var u,o,a,l,c,f,s=ee(function(n,t){return n=u(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,p=480,g=250,v=0,d=0,y=0,M=0,x=0,b=Fa,_=m,w=null,S=null;return t.stream=function(n){return f&&(f.valid=!1),f=le(b(o,s(_(n)))),f.valid=!0,f},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Fa):It((w=+n)*Yo),i()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):m,i()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(p=+n[0],g=+n[1],r()):[p,g]},t.center=function(n){return arguments.length?(v=n[0]%360*Yo,d=n[1]%360*Yo,r()):[v*Zo,d*Zo]},t.rotate=function(n){return arguments.length?(y=n[0]%360*Yo,M=n[1]%360*Yo,x=n.length>2?n[2]%360*Yo:0,r()):[y*Zo,M*Zo,x*Zo]},ao.rebind(t,s,"precision"),function(){return u=n.apply(this,arguments),t.invert=u.invert&&e,r()}}function le(n){return ue(n,function(t,e){n.point(t*Yo,e*Yo)})}function ce(n,t){return[n,t]}function fe(n,t){return[n>Fo?n-Ho:-Fo>n?n+Ho:n,t]}function se(n,t,e){return n?t||e?Ct(pe(n),ge(t,e)):pe(n):t||e?ge(t,e):fe}function he(n){return function(t,e){return t+=n,[t>Fo?t-Ho:-Fo>t?t+Ho:t,e]}}function pe(n){var t=he(n);return t.invert=he(-n),t}function ge(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*r+a*i;return[Math.atan2(l*u-f*o,a*r-c*i),tn(f*u+l*o)]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),f=c*u-l*o;return[Math.atan2(l*u+c*o,a*r+f*i),tn(f*r-a*i)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(i,u,o,a){var l=o*t;null!=i?(i=de(e,i),u=de(e,u),(o>0?u>i:i>u)&&(i+=o*Ho)):(i=n+o*Ho,u=n-.5*l);for(var c,f=i;o>0?f>u:u>f;f-=l)a.point((c=_t([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Uo)%(2*Math.PI)}function ye(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function me(n,t,e){var r=ao.range(n,t-Uo,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),o=Math.cos(r),a=Math.sin(r),l=i*Math.cos(n),c=i*Math.sin(n),f=o*Math.cos(e),s=o*Math.sin(e),h=2*Math.asin(Math.sqrt(on(r-t)+i*o*on(e-n))),p=1/Math.sin(h),g=h?function(n){var t=Math.sin(n*=h)*p,e=Math.sin(h-n)*p,r=e*l+t*f,i=e*c+t*s,o=e*u+t*a;return[Math.atan2(i,r)*Zo,Math.atan2(o,Math.sqrt(r*r+i*i))*Zo]}:function(){return[n*Zo,t*Zo]};return g.distance=h,g}function _e(){function n(n,i){var u=Math.sin(i*=Yo),o=Math.cos(i),a=xo((n*=Yo)-t),l=Math.cos(a);Ja+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*u-e*o*l)*a),e*u+r*o*l),t=n,e=u,r=o}var t,e,r;Ga.point=function(i,u){t=i*Yo,e=Math.sin(u*=Yo),r=Math.cos(u),Ga.point=n},Ga.lineEnd=function(){Ga.point=Ga.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),o=Math.cos(i);return[Math.atan2(n*u,r*o),Math.asin(r&&e*u/r)]},e}function Se(n,t){function e(n,t){o>0?-Io+Uo>t&&(t=-Io+Uo):t>Io-Uo&&(t=Io-Uo);var e=o/Math.pow(i(t),u);return[e*Math.sin(u*n),o-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Fo/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),o=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=o-t,r=K(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(o/r,1/u))-Io]},e):Ne}function ke(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return xo(i)i;i++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var i=n[0],u=e[0],o=t[0]-i,a=r[0]-u,l=n[1],c=e[1],f=t[1]-l,s=r[1]-c,h=(a*(l-c)-s*(i-u))/(s*o-a*f);return[i+h*o,l+h*f]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function Ue(n){var t=cl.pop()||new Pe;return t.site=n,t}function je(n){Be(n),ol.remove(n),cl.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,i={x:e,y:r},u=n.P,o=n.N,a=[n];je(n);for(var l=u;l.circle&&xo(e-l.circle.x)f;++f)c=a[f],l=a[f-1],nr(c.edge,l.site,c.site,i);l=a[0],c=a[s-1],c.edge=Ke(l.site,c.site,null,i),$e(l),$e(c)}function He(n){for(var t,e,r,i,u=n.x,o=n.y,a=ol._;a;)if(r=Oe(a,o)-u,r>Uo)a=a.L;else{if(i=u-Ie(a,o),!(i>Uo)){r>-Uo?(t=a.P,e=a):i>-Uo?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var l=Ue(n);if(ol.insert(t,l),t||e){if(t===e)return Be(t),e=Ue(t.site),ol.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,f=c.x,s=c.y,h=n.x-f,p=n.y-s,g=e.site,v=g.x-f,d=g.y-s,y=2*(h*d-p*v),m=h*h+p*p,M=v*v+d*d,x={x:(d*m-p*M)/y+f,y:(h*M-v*m)/y+s};nr(e.edge,c,g,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,g,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,i=e.y,u=i-t;if(!u)return r;var o=n.P;if(!o)return-(1/0);e=o.site;var a=e.x,l=e.y,c=l-t;if(!c)return a;var f=a-r,s=1/u-1/c,h=f/c;return s?(-h+Math.sqrt(h*h-2*s*(f*f/(-2*c)-l+c/2+i-u/2)))/s+r:(r+a)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,i,u,o,a,l,c,f,s=n[0][0],h=n[1][0],p=n[0][1],g=n[1][1],v=ul,d=v.length;d--;)if(u=v[d],u&&u.prepare())for(a=u.edges,l=a.length,o=0;l>o;)f=a[o].end(),r=f.x,i=f.y,c=a[++o%l].start(),t=c.x,e=c.y,(xo(r-t)>Uo||xo(i-e)>Uo)&&(a.splice(o,0,new tr(Qe(u.site,f,xo(r-s)Uo?{x:s,y:xo(t-s)Uo?{x:xo(e-g)Uo?{x:h,y:xo(t-h)Uo?{x:xo(e-p)=-jo)){var p=l*l+c*c,g=f*f+s*s,v=(s*p-c*g)/h,d=(l*g-f*p)/h,s=d+a,y=fl.pop()||new Xe;y.arc=n,y.site=i,y.x=v+o,y.y=s+Math.sqrt(v*v+d*d),y.cy=s,n.circle=y;for(var m=null,M=ll._;M;)if(y.yd||d>=a)return;if(h>g){if(u){if(u.y>=c)return}else u={x:d,y:l};e={x:d,y:c}}else{if(u){if(u.yr||r>1)if(h>g){if(u){if(u.y>=c)return}else u={x:(l-i)/r,y:l};e={x:(c-i)/r,y:c}}else{if(u){if(u.yp){if(u){if(u.x>=a)return}else u={x:o,y:r*o+i};e={x:a,y:r*a+i}}else{if(u){if(u.xu||s>o||r>h||i>p)){if(g=n.point){var g,v=t-n.x,d=e-n.y,y=v*v+d*d;if(l>y){var m=Math.sqrt(l=y);r=t-m,i=e-m,u=t+m,o=e+m,a=g}}for(var M=n.nodes,x=.5*(f+h),b=.5*(s+p),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,f,s,x,b);break;case 1:c(n,x,s,h,b);break;case 2:c(n,f,b,x,p);break;case 3:c(n,x,b,h,p)}}}(n,r,i,u,o),a}function vr(n,t){n=ao.rgb(n),t=ao.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,o=t.g-r,a=t.b-i;return function(n){return"#"+bn(Math.round(e+u*n))+bn(Math.round(r+o*n))+bn(Math.round(i+a*n))}}function dr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function yr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function mr(n,t){var e,r,i,u=hl.lastIndex=pl.lastIndex=0,o=-1,a=[],l=[];for(n+="",t+="";(e=hl.exec(n))&&(r=pl.exec(t));)(i=r.index)>u&&(i=t.slice(u,i),a[o]?a[o]+=i:a[++o]=i),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,l.push({i:o,x:yr(e,r)})),u=pl.lastIndex;return ur;++r)a[(e=l[r]).i]=e.x(n);return a.join("")})}function Mr(n,t){for(var e,r=ao.interpolators.length;--r>=0&&!(e=ao.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],i=[],u=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(Mr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;o>e;++e)i[e]=t[e];return function(n){for(e=0;a>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Io)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ho*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ho/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=ao.hcl(n),t=ao.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,o=t.c-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return sn(e+u*n,r+o*n,i+a*n)+""}}function Dr(n,t){n=ao.hsl(n),t=ao.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,o=t.s-r,a=t.l-i;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return cn(e+u*n,r+o*n,i+a*n)+""}}function Pr(n,t){n=ao.lab(n),t=ao.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,o=t.a-r,a=t.b-i;return function(n){return pn(e+u*n,r+o*n,i+a*n)+""}}function Ur(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function jr(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),i=Fr(t,e),u=Hr(Or(e,t,-i))||0;t[0]*e[1]180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:yr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:yr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var i=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:i-4,x:yr(n[0],t[0])},{i:i-2,x:yr(n[1],t[1])})}else 1===t[0]&&1===t[1]||e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=ao.transform(n),t=ao.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,i=-1,u=r.length;++i=0;)e.push(i[r])}function oi(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(u=n.children)&&(i=u.length))for(var i,u,o=-1;++oe;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function yi(n){return n.reduce(mi,0)}function mi(n,t){return n+t[1]}function Mi(n,t){return xi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xi(n,t){for(var e=-1,r=+n[0],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function bi(n){return[ao.min(n),ao.max(n)]}function _i(n,t){return n.value-t.value}function wi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Si(n,t){n._pack_next=t,t._pack_prev=n}function ki(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return.999*i*i>e*e+r*r}function Ni(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),p=Math.max(n.y+n.r,p)}if((e=n.children)&&(c=e.length)){var e,r,i,u,o,a,l,c,f=1/0,s=-(1/0),h=1/0,p=-(1/0);if(e.forEach(Ei),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(i=e[1],i.x=i.r,i.y=0,t(i),c>2))for(u=e[2],zi(r,i,u),t(u),wi(r,u),r._pack_prev=u,wi(u,i),i=r._pack_next,o=3;c>o;o++){zi(r,i,u=e[o]);var g=0,v=1,d=1;for(a=i._pack_next;a!==i;a=a._pack_next,v++)if(ki(a,u)){g=1;break}if(1==g)for(l=r._pack_prev;l!==a._pack_prev&&!ki(l,u);l=l._pack_prev,d++);g?(d>v||v==d&&i.ro;o++)u=e[o],u.x-=y,u.y-=m,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function Ei(n){n._pack_next=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ci(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,o=i.length;++u=0;)t=i[u],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pi(n,t,e){return n.a.parent===t.parent?n.a:e}function Ui(n){return 1+ao.max(n,function(n){return n.y})}function ji(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fi(n){var t=n.children;return t&&t.length?Fi(t[0]):n}function Hi(n){var t,e=n.children;return e&&(t=e.length)?Hi(e[t-1]):n}function Oi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Ii(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Yi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zi(n){return n.rangeExtent?n.rangeExtent():Yi(n.range())}function Vi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Xi(n,t){var e,r=0,i=n.length-1,u=n[r],o=n[i];return u>o&&(e=r,r=i,i=e,e=u,u=o,o=e),n[r]=t.floor(u),n[i]=t.ceil(o),n}function $i(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:Sl}function Bi(n,t,e,r){var i=[],u=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Bi:Vi,l=r?Wr:Br;return o=i(n,t,l,e),a=i(t,n,l,Mr),u}function u(n){return o(n)}var o,a;return u.invert=function(n){return a(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Ur)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.length?(e=n,i()):e},u.ticks=function(t){return Qi(n,t)},u.tickFormat=function(t,e){return nu(n,t,e)},u.nice=function(t){return Gi(n,t),i()},u.copy=function(){return Wi(n,t,e,r)},i()}function Ji(n,t){return ao.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gi(n,t){return Xi(n,$i(Ki(n,t)[2])),Xi(n,$i(Ki(n,t)[2])),n}function Ki(n,t){null==t&&(t=10);var e=Yi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Qi(n,t){return ao.range.apply(ao,Ki(n,t))}function nu(n,t,e){var r=Ki(n,t);if(e){var i=ha.exec(e);if(i.shift(),"s"===i[8]){var u=ao.formatPrefix(Math.max(xo(r[0]),xo(r[1])));return i[7]||(i[7]="."+tu(u.scale(r[2]))),i[8]="f",e=ao.format(i.join("")),function(n){return e(u.scale(n))+u.symbol}}i[7]||(i[7]="."+eu(i[8],r)),e=i.join("")}else e=",."+tu(r[2])+"f";return ao.format(e)}function tu(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function eu(n,t){var e=tu(t[2]);return n in kl?Math.abs(e-tu(Math.max(xo(t[0]),xo(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ru(n,t,e,r){function i(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function u(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(i(t))}return o.invert=function(t){return u(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(i)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(i)),o):t},o.nice=function(){var t=Xi(r.map(i),e?Math:El);return n.domain(t),r=t.map(u),o},o.ticks=function(){var n=Yi(r),o=[],a=n[0],l=n[1],c=Math.floor(i(a)),f=Math.ceil(i(l)),s=t%1?2:t;if(isFinite(f-c)){if(e){for(;f>c;c++)for(var h=1;s>h;h++)o.push(u(c)*h);o.push(u(c))}else for(o.push(u(c));c++0;h--)o.push(u(c)*h);for(c=0;o[c]l;f--);o=o.slice(c,f)}return o},o.tickFormat=function(n,e){if(!arguments.length)return Nl;arguments.length<2?e=Nl:"function"!=typeof e&&(e=ao.format(e));var r=Math.max(1,t*n/o.ticks().length);return function(n){var o=n/u(Math.round(i(n)));return t-.5>o*t&&(o*=t),r>=o?e(n):""}},o.copy=function(){return ru(n.copy(),t,e,r)},Ji(o,n)}function iu(n,t,e){function r(t){return n(i(t))}var i=uu(t),u=uu(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Qi(e,n)},r.tickFormat=function(n,t){return nu(e,n,t)},r.nice=function(n){return r.domain(Gi(e,n))},r.exponent=function(o){return arguments.length?(i=uu(t=o),u=uu(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return iu(n.copy(),t,e)},Ji(r,n)}function uu(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ou(n,t){function e(e){return u[((i.get(e)||("range"===t.t?i.set(e,n.push(e)):NaN))-1)%u.length]}function r(t,e){return ao.range(n.length).map(function(n){return t+e*n})}var i,u,o;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new c;for(var u,o=-1,a=r.length;++oe?[NaN,NaN]:[e>0?a[e-1]:n[0],et?NaN:t/u+n,[t,t+1/u]},r.copy=function(){return lu(n,t,e)},i()}function cu(n,t){function e(e){return e>=e?t[ao.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return cu(n,t)},e}function fu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qi(n,t)},t.tickFormat=function(t,e){return nu(n,t,e)},t.copy=function(){return fu(n)},t}function su(){return 0}function hu(n){return n.innerRadius}function pu(n){return n.outerRadius}function gu(n){return n.startAngle}function vu(n){return n.endAngle}function du(n){return n&&n.padAngle}function yu(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function mu(n,t,e,r,i){var u=n[0]-t[0],o=n[1]-t[1],a=(i?r:-r)/Math.sqrt(u*u+o*o),l=a*o,c=-a*u,f=n[0]+l,s=n[1]+c,h=t[0]+l,p=t[1]+c,g=(f+h)/2,v=(s+p)/2,d=h-f,y=p-s,m=d*d+y*y,M=e-r,x=f*p-h*s,b=(0>y?-1:1)*Math.sqrt(Math.max(0,M*M*m-x*x)),_=(x*y-d*b)/m,w=(-x*d-y*b)/m,S=(x*y+d*b)/m,k=(-x*d+y*b)/m,N=_-g,E=w-v,A=S-g,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mu(n){function t(t){function o(){c.push("M",u(n(f),a))}for(var l,c=[],f=[],s=-1,h=t.length,p=En(e),g=En(r);++s1?n.join("L"):n+"Z"}function bu(n){return n.join("L")+"Z"}function _u(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1&&i.push("H",r[0]),i.join("")}function wu(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t1){a=t[1],u=n[l],l++,r+="C"+(i[0]+o[0])+","+(i[1]+o[1])+","+(u[0]-a[0])+","+(u[1]-a[1])+","+u[0]+","+u[1];for(var c=2;c9&&(i=3*t/Math.sqrt(i),o[a]=i*e,o[a+1]=i*r));for(a=-1;++a<=l;)i=(n[Math.min(l,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),u.push([i||0,o[a]*i||0]);return u}function Fu(n){return n.length<3?xu(n):n[0]+Au(n,ju(n))}function Hu(n){for(var t,e,r,i=-1,u=n.length;++i=t?o(n-t):void(f.c=o)}function o(e){var i=g.active,u=g[i];u&&(u.timer.c=null,u.timer.t=NaN,--g.count,delete g[i],u.event&&u.event.interrupt.call(n,n.__data__,u.index));for(var o in g)if(r>+o){var c=g[o];c.timer.c=null,c.timer.t=NaN,--g.count,delete g[o]}f.c=a,qn(function(){return f.c&&a(e||1)&&(f.c=null,f.t=NaN),1},0,l),g.active=r,v.event&&v.event.start.call(n,n.__data__,t),p=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&p.push(r)}),h=v.ease,s=v.duration}function a(i){for(var u=i/s,o=h(u),a=p.length;a>0;)p[--a].call(n,o);return u>=1?(v.event&&v.event.end.call(n,n.__data__,t),--g.count?delete g[r]:delete n[e],1):void 0}var l,f,s,h,p,g=n[e]||(n[e]={active:0,count:0}),v=g[r];v||(l=i.time,f=qn(u,0,l),v=g[r]={tween:new c,time:l,timer:f,delay:i.delay,duration:i.duration,ease:i.ease,index:t},i=null,++g.count)}function no(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function to(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function eo(n){return n.toISOString()}function ro(n,t,e){function r(t){return n(t)}function i(n,e){var r=n[1]-n[0],i=r/e,u=ao.bisect(Kl,i);return u==Kl.length?[t.year,Ki(n.map(function(n){return n/31536e6}),e)[2]]:u?t[i/Kl[u-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yi(r.domain()),u=null==n?i(e,10):"number"==typeof n?i(e,n):!n.range&&[{range:n},t];return u&&(n=u[0],t=u[1]),n.range(e[0],io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ro(n.copy(),t,e)},Ji(r,n)}function io(n){return new Date(n)}function uo(n){return JSON.parse(n.responseText)}function oo(n){var t=fo.createRange();return t.selectNode(fo.body),t.createContextualFragment(n.responseText)}var ao={version:"3.5.17"},lo=[].slice,co=function(n){return lo.call(n)},fo=this.document;if(fo)try{co(fo.documentElement.childNodes)[0].nodeType}catch(so){co=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),fo)try{fo.createElement("DIV").style.setProperty("opacity",0,"")}catch(ho){var po=this.Element.prototype,go=po.setAttribute,vo=po.setAttributeNS,yo=this.CSSStyleDeclaration.prototype,mo=yo.setProperty;po.setAttribute=function(n,t){go.call(this,n,t+"")},po.setAttributeNS=function(n,t,e){vo.call(this,n,t,e+"")},yo.setProperty=function(n,t,e){mo.call(this,n,t+"",e)}}ao.ascending=e,ao.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},ao.min=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ir&&(e=r)}else{for(;++i=r){e=r;break}for(;++ir&&(e=r)}return e},ao.max=function(n,t){var e,r,i=-1,u=n.length;if(1===arguments.length){for(;++i=r){e=r;break}for(;++ie&&(e=r)}else{for(;++i=r){e=r;break}for(;++ie&&(e=r)}return e},ao.extent=function(n,t){var e,r,i,u=-1,o=n.length;if(1===arguments.length){for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}else{for(;++u=r){e=i=r;break}for(;++ur&&(e=r),r>i&&(i=r))}return[e,i]},ao.sum=function(n,t){var e,r=0,u=n.length,o=-1;if(1===arguments.length)for(;++o1?l/(f-1):void 0},ao.deviation=function(){var n=ao.variance.apply(this,arguments);return n?Math.sqrt(n):n};var Mo=u(e);ao.bisectLeft=Mo.left,ao.bisect=ao.bisectRight=Mo.right,ao.bisector=function(n){return u(1===n.length?function(t,r){return e(n(t),r)}:n)},ao.shuffle=function(n,t,e){(u=arguments.length)<3&&(e=n.length,2>u&&(t=0));for(var r,i,u=e-t;u;)i=Math.random()*u--|0,r=n[u+t],n[u+t]=n[i+t],n[i+t]=r;return n},ao.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ao.pairs=function(n){for(var t,e=0,r=n.length-1,i=n[0],u=new Array(0>r?0:r);r>e;)u[e]=[t=i,i=n[++e]];return u},ao.transpose=function(n){if(!(i=n.length))return[];for(var t=-1,e=ao.min(n,o),r=new Array(e);++t=0;)for(r=n[i],t=r.length;--t>=0;)e[--o]=r[t];return e};var xo=Math.abs;ao.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,i=[],u=a(xo(e)),o=-1;if(n*=u,t*=u,e*=u,0>e)for(;(r=n+e*++o)>t;)i.push(r/u);else for(;(r=n+e*++o)=u.length)return r?r.call(i,o):e?o.sort(e):o;for(var l,f,s,h,p=-1,g=o.length,v=u[a++],d=new c;++p=u.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,i={},u=[],o=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(ao.map,e,0),0)},i.key=function(n){return u.push(n),i},i.sortKeys=function(n){return o[u.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},ao.set=function(n){var t=new y;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(y,{has:h,add:function(n){return this._[f(n+="")]=!0,n},remove:p,values:g,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,s(t))}}),ao.behavior={},ao.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ao.event=null,ao.requote=function(n){return n.replace(So,"\\$&")};var So=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ko={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},No=function(n,t){return t.querySelector(n)},Eo=function(n,t){return t.querySelectorAll(n)},Ao=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ao=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(No=function(n,t){return Sizzle(n,t)[0]||null},Eo=Sizzle,Ao=Sizzle.matchesSelector),ao.selection=function(){return ao.select(fo.documentElement)};var Co=ao.selection.prototype=[];Co.select=function(n){var t,e,r,i,u=[];n=A(n);for(var o=-1,a=this.length;++o=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Lo.hasOwnProperty(e)?{space:Lo[e],local:n}:n}},Co.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ao.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Co.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,i=-1;if(t=e.classList){for(;++ii){if("string"!=typeof n){2>i&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>i){var u=this.node();return t(u).getComputedStyle(u,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Co.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},Co.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Co.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Co.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Co.insert=function(n,t){return n=j(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Co.remove=function(){return this.each(F)},Co.data=function(n,t){function e(n,e){var r,i,u,o=n.length,s=e.length,h=Math.min(o,s),p=new Array(s),g=new Array(s),v=new Array(o);if(t){var d,y=new c,m=new Array(o);for(r=-1;++rr;++r)g[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}g.update=p,g.parentNode=p.parentNode=v.parentNode=n.parentNode,a.push(g),l.push(p),f.push(v)}var r,i,u=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++uu;u++){i.push(t=[]),t.parentNode=(e=this[u]).parentNode;for(var a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return E(i)},Co.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Co.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Co.size=function(){var n=0;return Y(this,function(){++n}),n};var qo=[];ao.selection.enter=Z,ao.selection.enter.prototype=qo,qo.append=Co.append,qo.empty=Co.empty,qo.node=Co.node,qo.call=Co.call,qo.size=Co.size,qo.select=function(n){for(var t,e,r,i,u,o=[],a=-1,l=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var To=ao.map({mouseenter:"mouseover",mouseleave:"mouseout"});fo&&To.forEach(function(n){"on"+n in fo&&To.remove(n)});var Ro,Do=0;ao.mouse=function(n){return J(n,k())};var Po=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ao.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,i=0,u=t.length;u>i;++i)if((r=t[i]).identifier===e)return J(n,r)},ao.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",o)}function e(n,t,e,u,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],g|=n|e,M=r,p({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(y.on(u+d,null).on(o+d,null),m(g),p({type:"dragend"}))}var c,f=this,s=ao.event.target.correspondingElement||ao.event.target,h=f.parentNode,p=r.of(f,arguments),g=0,v=n(),d=".drag"+(null==v?"":"-"+v),y=ao.select(e(s)).on(u+d,a).on(o+d,l),m=W(s),M=t(h,v);i?(c=i.apply(f,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],p({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),i=null,u=e(b,ao.mouse,t,"mousemove","mouseup"),o=e(G,ao.touch,m,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},ao.rebind(n,r,"on")},ao.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?co(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Uo=1e-6,jo=Uo*Uo,Fo=Math.PI,Ho=2*Fo,Oo=Ho-Uo,Io=Fo/2,Yo=Fo/180,Zo=180/Fo,Vo=Math.SQRT2,Xo=2,$o=4;ao.interpolateZoom=function(n,t){var e,r,i=n[0],u=n[1],o=n[2],a=t[0],l=t[1],c=t[2],f=a-i,s=l-u,h=f*f+s*s;if(jo>h)r=Math.log(c/o)/Vo,e=function(n){return[i+n*f,u+n*s,o*Math.exp(Vo*n*r)]};else{var p=Math.sqrt(h),g=(c*c-o*o+$o*h)/(2*o*Xo*p),v=(c*c-o*o-$o*h)/(2*c*Xo*p),d=Math.log(Math.sqrt(g*g+1)-g),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-d)/Vo,e=function(n){var t=n*r,e=rn(d),a=o/(Xo*p)*(e*un(Vo*t+d)-en(d));return[i+a*f,u+a*s,o*e/rn(Vo*t+d)]}}return e.duration=1e3*r,e},ao.behavior.zoom=function(){function n(n){n.on(L,s).on(Wo+".zoom",p).on("dblclick.zoom",g).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function i(n){k.k=Math.max(A[0],Math.min(A[1],n))}function u(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},i(Math.pow(2,o)),u(d=e,r),t=ao.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function f(n){--z||(n({type:"zoomend"}),d=null)}function s(){function n(){a=1,u(ao.mouse(i),h),c(o)}function r(){s.on(q,null).on(T,null),p(a),f(o)}var i=this,o=D.of(i,arguments),a=0,s=ao.select(t(i)).on(q,n).on(T,r),h=e(ao.mouse(i)),p=W(i);Il.call(i),l(o)}function h(){function n(){var n=ao.touches(g);return p=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ao.event.target;ao.select(t).on(x,r).on(b,a),_.push(t);for(var e=ao.event.changedTouches,i=0,u=e.length;u>i;++i)d[e[i].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var f=l[0];o(g,f,d[f.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var f=l[0],s=l[1],h=f[0]-s[0],p=f[1]-s[1];y=h*h+p*p}}function r(){var n,t,e,r,o=ao.touches(g);Il.call(g);for(var a=0,l=o.length;l>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var f=(f=e[0]-n[0])*f+(f=e[1]-n[1])*f,s=y&&Math.sqrt(f/y);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],i(s*p)}M=null,u(n,t),c(v)}function a(){if(ao.event.touches.length){for(var t=ao.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var i in d)return void n()}ao.selectAll(_).on(m,null),w.on(L,s).on(R,h),N(),f(v)}var p,g=this,v=D.of(g,arguments),d={},y=0,m=".zoom-"+ao.event.changedTouches[0].identifier,x="touchmove"+m,b="touchend"+m,_=[],w=ao.select(g),N=W(g);t(),l(v),w.on(L,null).on(R,t)}function p(){var n=D.of(this,arguments);m?clearTimeout(m):(Il.call(this),v=e(d=y||ao.mouse(this)),l(n)),m=setTimeout(function(){m=null,f(n)},50),S(),i(Math.pow(2,.002*Bo())*k.k),u(d,v),c(n)}function g(){var n=ao.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ao.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,y,m,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Jo,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return Wo||(Wo="onwheel"in fo?(Bo=function(){return-ao.event.deltaY*(ao.event.deltaMode?120:1)},"wheel"):"onmousewheel"in fo?(Bo=function(){return ao.event.wheelDelta},"mousewheel"):(Bo=function(){return-ao.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Hl?ao.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],i=d?d[0]:e/2,u=d?d[1]:r/2,o=ao.interpolateZoom([(i-k.x)/k.k,(u-k.y)/k.k,e/k.k],[(i-t.x)/t.k,(u-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:i-r[0]*a,y:u-r[1]*a,k:a},c(n)}}).each("interrupt.zoom",function(){f(n)}).each("end.zoom",function(){f(n)}):(this.__chart__=k,l(n),c(n),f(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},i(+t),a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Jo:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(y=t&&[+t[0],+t[1]],n):y},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ao.rebind(n,D,"on")};var Bo,Wo,Jo=[0,1/0];ao.color=an,an.prototype.toString=function(){return this.rgb()+""},ao.hsl=ln;var Go=ln.prototype=new an;Go.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Go.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Go.rgb=function(){return cn(this.h,this.s,this.l)},ao.hcl=fn;var Ko=fn.prototype=new an;Ko.brighter=function(n){return new fn(this.h,this.c,Math.min(100,this.l+Qo*(arguments.length?n:1)))},Ko.darker=function(n){return new fn(this.h,this.c,Math.max(0,this.l-Qo*(arguments.length?n:1)))},Ko.rgb=function(){return sn(this.h,this.c,this.l).rgb()},ao.lab=hn;var Qo=18,na=.95047,ta=1,ea=1.08883,ra=hn.prototype=new an;ra.brighter=function(n){return new hn(Math.min(100,this.l+Qo*(arguments.length?n:1)),this.a,this.b)},ra.darker=function(n){return new hn(Math.max(0,this.l-Qo*(arguments.length?n:1)),this.a,this.b)},ra.rgb=function(){return pn(this.l,this.a,this.b)},ao.rgb=mn;var ia=mn.prototype=new an;ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),new mn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mn(i,i,i)},ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mn(n*this.r,n*this.g,n*this.b)},ia.hsl=function(){return wn(this.r,this.g,this.b)},ia.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ua=ao.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ua.forEach(function(n,t){ua.set(n,Mn(t))}),ao.functor=En,ao.xhr=An(m),ao.dsv=function(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var o=Cn(n,t,null==e?r:i(e),u);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:i(n)):e},o}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function u(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return o;if(i)return i=!1,u;var t=f;if(34===n.charCodeAt(t)){for(var e=t;e++f;){var r=n.charCodeAt(f++),a=1;if(10===r)i=!0;else if(13===r)i=!0,10===n.charCodeAt(f)&&(++f,++a);else if(r!==l)continue;return n.slice(t,f-a)}return n.slice(t)}for(var r,i,u={},o={},a=[],c=n.length,f=0,s=0;(r=e())!==o;){for(var h=[];r!==u&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,s++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new y,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(u).join("\n")},e},ao.csv=ao.dsv(",","text/csv"),ao.tsv=ao.dsv(" ","text/tab-separated-values");var oa,aa,la,ca,fa=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ao.timer=function(){qn.apply(this,arguments)},ao.timer.flush=function(){Rn(),Dn()},ao.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var sa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Un);ao.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=ao.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),sa[8+e/3]};var ha=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,pa=ao.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ao.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ga=ao.time={},va=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){da.setUTCDate.apply(this._,arguments)},setDay:function(){da.setUTCDay.apply(this._,arguments)},setFullYear:function(){da.setUTCFullYear.apply(this._,arguments)},setHours:function(){da.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){da.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){da.setUTCMinutes.apply(this._,arguments)},setMonth:function(){da.setUTCMonth.apply(this._,arguments)},setSeconds:function(){da.setUTCSeconds.apply(this._,arguments)},setTime:function(){da.setTime.apply(this._,arguments)}};var da=Date.prototype;ga.year=On(function(n){return n=ga.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ga.years=ga.year.range,ga.years.utc=ga.year.utc.range,ga.day=On(function(n){var t=new va(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ga.days=ga.day.range,ga.days.utc=ga.day.utc.range,ga.dayOfYear=function(n){var t=ga.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ga[n]=On(function(n){return(n=ga.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ga[n+"s"]=e.range,ga[n+"s"].utc=e.utc.range,ga[n+"OfYear"]=function(n){var e=ga.year(n).getDay();return Math.floor((ga.dayOfYear(n)+(e+t)%7)/7)}}),ga.week=ga.sunday,ga.weeks=ga.sunday.range,ga.weeks.utc=ga.sunday.utc.range,ga.weekOfYear=ga.sundayOfYear;var ya={"-":"",_:" ",0:"0"},ma=/^\s*\d+/,Ma=/^%/;ao.locale=function(n){return{numberFormat:jn(n),timeFormat:Yn(n)}};var xa=ao.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], +shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ao.format=xa.numberFormat,ao.geo={},ft.prototype={s:0,t:0,add:function(n){st(n,this.t,ba),st(ba.s,this.s,this),this.s?this.t+=ba.t:this.s=ba.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var ba=new ft;ao.geo.stream=function(n,t){n&&_a.hasOwnProperty(n.type)?_a[n.type](n,t):ht(n,t)};var _a={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++rn?4*Fo+n:n,Na.lineStart=Na.lineEnd=Na.point=b}};ao.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>p&&(p=t)}function t(t,e){var r=dt([t*Yo,e*Yo]);if(y){var i=mt(y,r),u=[i[1],-i[0],0],o=mt(u,i);bt(o),o=_t(o);var l=t-g,c=l>0?1:-1,v=o[0]*Zo*c,d=xo(l)>180;if(d^(v>c*g&&c*t>v)){var m=o[1]*Zo;m>p&&(p=m)}else if(v=(v+360)%360-180,d^(v>c*g&&c*t>v)){var m=-o[1]*Zo;s>m&&(s=m)}else s>e&&(s=e),e>p&&(p=e);d?g>t?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>g?a(f,t)>a(f,h)&&(h=t):a(t,h)>a(f,h)&&(f=t)}else n(t,e);y=r,g=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,y=null}function i(n,e){if(y){var r=n-g;m+=xo(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Na.point(n,e),t(n,e)}function u(){Na.lineStart()}function o(){i(v,d),Na.lineEnd(),xo(m)>Uo&&(f=-(h=180)),x[0]=f,x[1]=h,y=null}function a(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nka?(f=-(h=180),s=-(p=90)):m>Uo?p=90:-Uo>m&&(s=-90),x[0]=f,x[1]=h}};return function(n){p=h=-(f=s=1/0),M=[],ao.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,i=M[0],u=[i];t>r;++r)e=M[r],c(e[0],i)||c(e[1],i)?(a(i[0],e[1])>a(i[0],i[1])&&(i[1]=e[1]),a(e[0],i[1])>a(i[0],i[1])&&(i[0]=e[0])):u.push(i=e);for(var o,e,g=-(1/0),t=u.length-1,r=0,i=u[t];t>=r;i=e,++r)e=u[r],(o=a(i[1],e[0]))>g&&(g=o,f=e[0],h=i[1])}return M=x=null,f===1/0||s===1/0?[[NaN,NaN],[NaN,NaN]]:[[f,s],[h,p]]}}(),ao.geo.centroid=function(n){Ea=Aa=Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,ja);var t=Da,e=Pa,r=Ua,i=t*t+e*e+r*r;return jo>i&&(t=qa,e=Ta,r=Ra,Uo>Aa&&(t=Ca,e=za,r=La),i=t*t+e*e+r*r,jo>i)?[NaN,NaN]:[Math.atan2(e,t)*Zo,tn(r/Math.sqrt(i))*Zo]};var Ea,Aa,Ca,za,La,qa,Ta,Ra,Da,Pa,Ua,ja={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){ja.lineStart=At},polygonEnd:function(){ja.lineStart=Nt}},Fa=Rt(zt,jt,Ht,[-Fo,-Fo/2]),Ha=1e9;ao.geo.clipExtent=function(){var n,t,e,r,i,u,o={stream:function(n){return i&&(i.valid=!1),i=u(n),i.valid=!0,i},extent:function(a){return arguments.length?(u=Zt(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),i&&(i.valid=!1,i=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ao.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,ao.geo.albers=function(){return ao.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ao.geo.albersUsa=function(){function n(n){var u=n[0],o=n[1];return t=null,e(u,o),t||(r(u,o),t)||i(u,o),t}var t,e,r,i,u=ao.geo.albers(),o=ao.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ao.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale(),e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?o:i>=.166&&.234>i&&r>=-.214&&-.115>r?a:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),o.precision(t),a.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),o.scale(.35*t),a.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var c=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*c,s-.238*c],[f+.455*c,s+.238*c]]).stream(l).point,r=o.translate([f-.307*c,s+.201*c]).clipExtent([[f-.425*c+Uo,s+.12*c+Uo],[f-.214*c-Uo,s+.234*c-Uo]]).stream(l).point,i=a.translate([f-.205*c,s+.212*c]).clipExtent([[f-.214*c+Uo,s+.166*c+Uo],[f-.115*c-Uo,s+.234*c-Uo]]).stream(l).point,n},n.scale(1070)};var Oa,Ia,Ya,Za,Va,Xa,$a={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Ia=0,$a.lineStart=$t},polygonEnd:function(){$a.lineStart=$a.lineEnd=$a.point=b,Oa+=xo(Ia/2)}},Ba={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Wa={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Wa.lineStart=ne},polygonEnd:function(){Wa.point=Gt,Wa.lineStart=Kt,Wa.lineEnd=Qt}};ao.geo.path=function(){function n(n){return n&&("function"==typeof a&&u.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=i(u)),ao.geo.stream(n,o)),u.result()}function t(){return o=null,n}var e,r,i,u,o,a=4.5;return n.area=function(n){return Oa=0,ao.geo.stream(n,i($a)),Oa},n.centroid=function(n){return Ca=za=La=qa=Ta=Ra=Da=Pa=Ua=0,ao.geo.stream(n,i(Wa)),Ua?[Da/Ua,Pa/Ua]:Ra?[qa/Ra,Ta/Ra]:La?[Ca/La,za/La]:[NaN,NaN]},n.bounds=function(n){return Va=Xa=-(Ya=Za=1/0),ao.geo.stream(n,i(Ba)),[[Ya,Za],[Va,Xa]]},n.projection=function(n){return arguments.length?(i=(e=n)?n.stream||re(n):m,t()):e},n.context=function(n){return arguments.length?(u=null==(r=n)?new Wt:new te(n),"function"!=typeof a&&u.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(u.pointRadius(+t),+t),n):a},n.projection(ao.geo.albersUsa()).context(null)},ao.geo.transform=function(n){return{stream:function(t){var e=new ie(t);for(var r in n)e[r]=n[r];return e}}},ie.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ao.geo.projection=oe,ao.geo.projectionMutator=ae,(ao.geo.equirectangular=function(){return oe(ce)}).raw=ce.invert=ce,ao.geo.rotation=function(n){function t(t){return t=n(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t}return n=se(n[0]%360*Yo,n[1]*Yo,n.length>2?n[2]*Yo:0),t.invert=function(t){return t=n.invert(t[0]*Yo,t[1]*Yo),t[0]*=Zo,t[1]*=Zo,t},t},fe.invert=ce,ao.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=se(-n[0]*Yo,-n[1]*Yo,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Zo,n[1]*=Zo}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Yo,i*Yo),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Yo,(i=+r)*Yo),n):i},n.angle(90)},ao.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Yo,i=n[1]*Yo,u=t[1]*Yo,o=Math.sin(r),a=Math.cos(r),l=Math.sin(i),c=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*o)*e+(e=c*f-l*s*a)*e),l*f+c*s*a)},ao.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ao.range(Math.ceil(u/d)*d,i,d).map(h).concat(ao.range(Math.ceil(c/y)*y,l,y).map(p)).concat(ao.range(Math.ceil(r/g)*g,e,g).filter(function(n){return xo(n%d)>Uo}).map(f)).concat(ao.range(Math.ceil(a/v)*v,o,v).filter(function(n){return xo(n%y)>Uo}).map(s))}var e,r,i,u,o,a,l,c,f,s,h,p,g=10,v=g,d=90,y=360,m=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(p(l).slice(1),h(i).reverse().slice(1),p(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(u=+t[0][0],i=+t[1][0],c=+t[0][1],l=+t[1][1],u>i&&(t=u,u=i,i=t),c>l&&(t=c,c=l,l=t),n.precision(m)):[[u,c],[i,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(m)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],y=+t[1],n):[d,y]},n.minorStep=function(t){return arguments.length?(g=+t[0],v=+t[1],n):[g,v]},n.precision=function(t){return arguments.length?(m=+t,f=ye(a,o,90),s=me(r,e,m),h=ye(c,l,90),p=me(u,i,m),n):m},n.majorExtent([[-180,-90+Uo],[180,90-Uo]]).minorExtent([[-180,-80-Uo],[180,80+Uo]])},ao.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=Me,i=xe;return n.distance=function(){return ao.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ao.geo.interpolate=function(n,t){return be(n[0]*Yo,n[1]*Yo,t[0]*Yo,t[1]*Yo)},ao.geo.length=function(n){return Ja=0,ao.geo.stream(n,Ga),Ja};var Ja,Ga={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Ka=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ao.geo.azimuthalEqualArea=function(){return oe(Ka)}).raw=Ka;var Qa=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},m);(ao.geo.azimuthalEquidistant=function(){return oe(Qa)}).raw=Qa,(ao.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(ao.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var nl=we(function(n){return 1/n},Math.atan);(ao.geo.gnomonic=function(){return oe(nl)}).raw=nl,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Io]},(ao.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var tl=we(function(){return 1},Math.asin);(ao.geo.orthographic=function(){return oe(tl)}).raw=tl;var el=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ao.geo.stereographic=function(){return oe(el)}).raw=el,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Io]},(ao.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,ao.geom={},ao.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i=En(e),u=En(r),o=n.length,a=[],l=[];for(t=0;o>t;t++)a.push([+i.call(this,n[t],t),+u.call(this,n[t],t),t]);for(a.sort(qe),t=0;o>t;t++)l.push([a[t][0],-a[t][1]]);var c=Le(a),f=Le(l),s=f[0]===c[0],h=f[f.length-1]===c[c.length-1],p=[];for(t=c.length-1;t>=0;--t)p.push(n[a[c[t]][2]]);for(t=+s;t=r&&c.x<=u&&c.y>=i&&c.y<=o?[[r,o],[u,o],[u,i],[r,i]]:[];f.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(u(n,t)/Uo)*Uo,y:Math.round(o(n,t)/Uo)*Uo,i:t}})}var r=Ce,i=ze,u=r,o=i,a=sl;return n?t(n):(t.links=function(n){return ar(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return ar(e(n)).cells.forEach(function(e,r){for(var i,u,o=e.site,a=e.edges.sort(Ve),l=-1,c=a.length,f=a[c-1].edge,s=f.l===o?f.r:f.l;++l=c,h=r>=f,p=h<<1|s;n.leaf=!1,n=n.nodes[p]||(n.nodes[p]=hr()),s?i=c:a=c,h?o=f:l=f,u(n,t,e,r,i,o,a,l)}var f,s,h,p,g,v,d,y,m,M=En(a),x=En(l);if(null!=t)v=t,d=e,y=r,m=i;else if(y=m=-(v=d=1/0),s=[],h=[],g=n.length,o)for(p=0;g>p;++p)f=n[p],f.xy&&(y=f.x),f.y>m&&(m=f.y),s.push(f.x),h.push(f.y);else for(p=0;g>p;++p){var b=+M(f=n[p],p),_=+x(f,p);v>b&&(v=b),d>_&&(d=_),b>y&&(y=b),_>m&&(m=_),s.push(b),h.push(_)}var w=y-v,S=m-d;w>S?m=d+w:y=v+S;var k=hr();if(k.add=function(n){u(k,n,+M(n,++p),+x(n,p),v,d,y,m)},k.visit=function(n){pr(n,k,v,d,y,m)},k.find=function(n){return gr(k,n[0],n[1],v,d,y,m)},p=-1,null==t){for(;++p=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=vl.get(e)||gl,r=dl.get(r)||m,br(r(e.apply(null,lo.call(arguments,1))))},ao.interpolateHcl=Rr,ao.interpolateHsl=Dr,ao.interpolateLab=Pr,ao.interpolateRound=Ur,ao.transform=function(n){var t=fo.createElementNS(ao.ns.prefix.svg,"g");return(ao.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new jr(e?e.matrix:yl)})(n)},jr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var yl={a:1,b:0,c:0,d:1,e:0,f:0};ao.interpolateTransform=$r,ao.layout={},ao.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/y){if(v>l){var c=t.charge/l;n.px-=u*c,n.py-=o*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=u*c,n.py-=o*c}}return!t.charge}}function t(n){n.px=ao.event.x,n.py=ao.event.y,l.resume()}var e,r,i,u,o,a,l={},c=ao.dispatch("start","tick","end"),f=[1,1],s=.9,h=ml,p=Ml,g=-30,v=xl,d=.1,y=.64,M=[],x=[];return l.tick=function(){if((i*=.99)<.005)return e=null,c.end({type:"end",alpha:i=0}),!0;var t,r,l,h,p,v,y,m,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,p=l.target,m=p.x-h.x,b=p.y-h.y,(v=m*m+b*b)&&(v=i*o[r]*((v=Math.sqrt(v))-u[r])/v,m*=v,b*=v,p.x-=m*(y=h.weight+p.weight?h.weight/(h.weight+p.weight):.5),p.y-=b*y,h.x+=m*(y=1-y),h.y+=b*y);if((y=i*d)&&(m=f[0]/2,b=f[1]/2,r=-1,y))for(;++r<_;)l=M[r],l.x+=(m-l.x)*y,l.y+=(b-l.y)*y;if(g)for(ri(t=ao.geom.quadtree(M),i,a),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*s,l.y-=(l.py-(l.py=l.y))*s);c.tick({type:"tick",alpha:i})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(f=n,l):f},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.friction=function(n){return arguments.length?(s=+n,l):s},l.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(y=n*n,l):Math.sqrt(y)},l.alpha=function(n){return arguments.length?(n=+n,i?n>0?i=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:i=0})):n>0&&(c.start({type:"start",alpha:i=n}),e=qn(l.tick)),l):i},l.start=function(){function n(n,r){if(!e){for(e=new Array(i),l=0;i>l;++l)e[l]=[];for(l=0;c>l;++l){var u=x[l];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var o,a=e[t],l=-1,f=a.length;++lt;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;i>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",s)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof h)for(t=0;c>t;++t)u[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)u[t]=h;if(o=[],"function"==typeof p)for(t=0;c>t;++t)o[t]=+p.call(this,x[t],t);else for(t=0;c>t;++t)o[t]=p;if(a=[],"function"==typeof g)for(t=0;i>t;++t)a[t]=+g.call(this,M[t],t);else for(t=0;i>t;++t)a[t]=g;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=ao.behavior.drag().origin(m).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",ni)),arguments.length?void this.on("mouseover.force",ti).on("mouseout.force",ei).call(r):r},ao.rebind(l,c,"on")};var ml=20,Ml=1,xl=1/0;ao.layout.hierarchy=function(){function n(i){var u,o=[i],a=[];for(i.depth=0;null!=(u=o.pop());)if(a.push(u),(c=e.call(n,u,u.depth))&&(l=c.length)){for(var l,c,f;--l>=0;)o.push(f=c[l]),f.parent=u,f.depth=u.depth+1;r&&(u.value=0),u.children=c}else r&&(u.value=+r.call(n,u,u.depth)||0),delete u.children;return oi(i,function(n){var e,i;t&&(e=n.children)&&e.sort(t),r&&(i=n.parent)&&(i.value+=n.value)}),a}var t=ci,e=ai,r=li;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(ui(t,function(n){n.children&&(n.value=0)}),oi(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ao.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(o=u.length)){var o,a,l,c=-1;for(r=t.value?r/t.value:0;++cs?-1:1),g=ao.sum(c),v=g?(s-l*p)/g:0,d=ao.range(l),y=[];return null!=e&&d.sort(e===bl?function(n,t){return c[t]-c[n]}:function(n,t){return e(o[n],o[t])}),d.forEach(function(n){y[n]={data:o[n],value:a=c[n],startAngle:f,endAngle:f+=a*v+p,padAngle:h}}),y}var t=Number,e=bl,r=0,i=Ho,u=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n.padAngle=function(t){return arguments.length?(u=t,n):u},n};var bl={};ao.layout.stack=function(){function n(a,l){if(!(h=a.length))return a;var c=a.map(function(e,r){return t.call(n,e,r)}),f=c.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),o.call(n,t,e)]})}),s=e.call(n,f,l);c=ao.permute(c,s),f=ao.permute(f,s);var h,p,g,v,d=r.call(n,f,l),y=c[0].length;for(g=0;y>g;++g)for(i.call(n,c[0][g],v=d[g],f[0][g][1]),p=1;h>p;++p)i.call(n,c[p][g],v+=f[p-1][g][1],f[p][g][1]);return a}var t=m,e=gi,r=vi,i=pi,u=si,o=hi;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:_l.get(t)||gi,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:wl.get(t)||vi,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(i=t,n):i},n};var _l=ao.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(di),u=n.map(yi),o=ao.range(r).sort(function(n,t){return i[n]-i[t]}),a=0,l=0,c=[],f=[];for(t=0;r>t;++t)e=o[t],l>a?(a+=u[e],c.push(e)):(l+=u[e],f.push(e));return f.reverse().concat(c)},reverse:function(n){return ao.range(n.length).reverse()},"default":gi}),wl=ao.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,o=[],a=0,l=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;u>e;++e)l[e]=(a-o[e])/2;return l},wiggle:function(n){var t,e,r,i,u,o,a,l,c,f=n.length,s=n[0],h=s.length,p=[];for(p[0]=l=c=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,a=s[e][0]-s[e-1][0];f>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;u+=o*n[t][e][1]}p[e]=l-=i?u/i*a:0,c>l&&(c=l)}for(e=0;h>e;++e)p[e]-=c;return p},expand:function(n){var t,e,r,i=n.length,u=n[0].length,o=1/i,a=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=o}for(e=0;u>e;++e)a[e]=0;return a},zero:vi});ao.layout.histogram=function(){function n(n,u){for(var o,a,l=[],c=n.map(e,this),f=r.call(this,c,u),s=i.call(this,f,c,u),u=-1,h=c.length,p=s.length-1,g=t?1:1/h;++u0)for(u=-1;++u=f[0]&&a<=f[1]&&(o=l[ao.bisect(s,a,1,p)-1],o.y+=g,o.push(n[u]));return l}var t=!0,e=Number,r=bi,i=Mi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return xi(n,t)}:En(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ao.layout.pack=function(){function n(n,u){var o=e.call(this,n,u),a=o[0],l=i[0],c=i[1],f=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,oi(a,function(n){n.r=+f(n.value)}),oi(a,Ni),r){var s=r*(t?1:Math.max(2*a.r/l,2*a.r/c))/2;oi(a,function(n){n.r+=s}),oi(a,Ni),oi(a,function(n){n.r-=s})}return Ci(a,l/2,c/2,t?1:1/Math.max(2*a.r/l,2*a.r/c)),o}var t,e=ao.layout.hierarchy().sort(_i),r=0,i=[1,1];return n.size=function(t){return arguments.length?(i=t,n):i},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},ii(n,e)},ao.layout.tree=function(){function n(n,i){var f=o.call(this,n,i),s=f[0],h=t(s);if(oi(h,e),h.parent.m=-h.z,ui(h,r),c)ui(s,u);else{var p=s,g=s,v=s;ui(s,function(n){n.xg.x&&(g=n),n.depth>v.depth&&(v=n)});var d=a(p,g)/2-p.x,y=l[0]/(g.x+a(g,p)/2+d),m=l[1]/(v.depth||1);ui(s,function(n){n.x=(n.x+d)*y,n.y=n.depth*m})}return f}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var i,u=t.children,o=0,a=u.length;a>o;++o)r.push((u[o]=i={_:u[o],parent:t,children:(i=u[o].children)&&i.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=i);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Di(n);var u=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-u):n.z=u}else r&&(n.z=r.z+a(n._,r._));n.parent.A=i(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function i(n,t,e){if(t){for(var r,i=n,u=n,o=t,l=i.parent.children[0],c=i.m,f=u.m,s=o.m,h=l.m;o=Ti(o),i=qi(i),o&&i;)l=qi(l),u=Ti(u),u.a=n,r=o.z+s-i.z-c+a(o._,i._),r>0&&(Ri(Pi(o,n,e),n,r),c+=r,f+=r),s+=o.m,c+=i.m,h+=l.m,f+=u.m;o&&!Ti(u)&&(u.t=o,u.m+=s-f),i&&!qi(l)&&(l.t=i,l.m+=c-h,e=n)}return e}function u(n){n.x*=l[0],n.y=n.depth*l[1]}var o=ao.layout.hierarchy().sort(null).value(null),a=Li,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(c=null==(l=t)?u:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:u,n):c?l:null},ii(n,o)},ao.layout.cluster=function(){function n(n,u){var o,a=t.call(this,n,u),l=a[0],c=0;oi(l,function(n){var t=n.children;t&&t.length?(n.x=ji(t),n.y=Ui(t)):(n.x=o?c+=e(n,o):0,n.y=0,o=n)});var f=Fi(l),s=Hi(l),h=f.x-e(f,s)/2,p=s.x+e(s,f)/2;return oi(l,i?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(p-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),a}var t=ao.layout.hierarchy().sort(null).value(null),e=Li,r=[1,1],i=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(i=null==(r=t),n):i?null:r},n.nodeSize=function(t){return arguments.length?(i=null!=(r=t),n):i?r:null},ii(n,t)},ao.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++it?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length){var o,a,l,c=s(e),f=[],h=u.slice(),g=1/0,v="slice"===p?c.dx:"dice"===p?c.dy:"slice-dice"===p?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),f.area=0;(l=h.length)>0;)f.push(o=h[l-1]),f.area+=o.area,"squarify"!==p||(a=r(f,v))<=g?(h.pop(),g=a):(f.area-=f.pop().area,i(f,v,c,!1),v=Math.min(c.dx,c.dy),f.length=f.area=0,g=1/0);f.length&&(i(f,v,c,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,o=s(t),a=r.slice(),l=[];for(n(a,o.dx*o.dy/t.value),l.area=0;u=a.pop();)l.push(u),l.area+=u.area,null!=u.z&&(i(l,u.z?o.dx:o.dy,o,!a.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,o=-1,a=n.length;++oe&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*g/r,r/(t*u*g)):1/0}function i(n,t,e,r){var i,u=-1,o=n.length,a=e.x,c=e.y,f=t?l(n.area/t):0; +if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++ue.dx)&&(f=e.dx);++ue&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ao.random.normal.apply(ao,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ao.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ao.scale={};var Sl={floor:m,ceil:m};ao.scale.linear=function(){return Wi([0,1],[0,1],Mr,!1)};var kl={s:1,g:1,p:1,r:1,e:1};ao.scale.log=function(){return ru(ao.scale.linear().domain([0,1]),10,!0,[1,10])};var Nl=ao.format(".0e"),El={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ao.scale.pow=function(){return iu(ao.scale.linear(),1,[0,1])},ao.scale.sqrt=function(){return ao.scale.pow().exponent(.5)},ao.scale.ordinal=function(){return ou([],{t:"range",a:[[]]})},ao.scale.category10=function(){return ao.scale.ordinal().range(Al)},ao.scale.category20=function(){return ao.scale.ordinal().range(Cl)},ao.scale.category20b=function(){return ao.scale.ordinal().range(zl)},ao.scale.category20c=function(){return ao.scale.ordinal().range(Ll)};var Al=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Cl=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),zl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),Ll=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);ao.scale.quantile=function(){return au([],[])},ao.scale.quantize=function(){return lu(0,1,[0,1])},ao.scale.threshold=function(){return cu([.5],[0,1])},ao.scale.identity=function(){return fu([0,1])},ao.svg={},ao.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),f=o.apply(this,arguments)-Io,s=a.apply(this,arguments)-Io,h=Math.abs(s-f),p=f>s?0:1;if(n>c&&(g=c,c=n,n=g),h>=Oo)return t(c,p)+(n?t(n,1-p):"")+"Z";var g,v,d,y,m,M,x,b,_,w,S,k,N=0,E=0,A=[];if((y=(+l.apply(this,arguments)||0)/2)&&(d=u===ql?Math.sqrt(n*n+c*c):+u.apply(this,arguments),p||(E*=-1),c&&(E=tn(d/c*Math.sin(y))),n&&(N=tn(d/n*Math.sin(y)))),c){m=c*Math.cos(f+E),M=c*Math.sin(f+E),x=c*Math.cos(s-E),b=c*Math.sin(s-E);var C=Math.abs(s-f-2*E)<=Fo?0:1;if(E&&yu(m,M,x,b)===p^C){var z=(f+s)/2;m=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else m=M=0;if(n){_=n*Math.cos(s-N),w=n*Math.sin(s-N),S=n*Math.cos(f+N),k=n*Math.sin(f+N);var L=Math.abs(f-s+2*N)<=Fo?0:1;if(N&&yu(_,w,S,k)===1-p^L){var q=(f+s)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Uo&&(g=Math.min(Math.abs(c-n)/2,+i.apply(this,arguments)))>.001){v=c>n^p?0:1;var T=g,R=g;if(Fo>h){var D=null==S?[_,w]:null==x?[m,M]:Re([m,M],[S,k],[x,b],[_,w]),P=m-D[0],U=M-D[1],j=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*j+U*F)/(Math.sqrt(P*P+U*U)*Math.sqrt(j*j+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(g,(n-O)/(H-1)),T=Math.min(g,(c-O)/(H+1))}if(null!=x){var I=mu(null==S?[_,w]:[S,k],[m,M],c,T,p),Y=mu([x,b],[_,w],c,T,p);g===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-p^yu(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",p," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",m,",",M);if(null!=S){var Z=mu([m,M],[S,k],n,-R,p),V=mu([_,w],null==x?[m,M]:[x,b],n,-R,p);g===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",p^yu(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-p," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",m,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",p," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-p," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hu,r=pu,i=su,u=ql,o=gu,a=vu,l=du;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(i=En(t),n):i},n.padRadius=function(t){return arguments.length?(u=t==ql?ql:En(t),n):u},n.startAngle=function(t){return arguments.length?(o=En(t),n):o},n.endAngle=function(t){return arguments.length?(a=En(t),n):a},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Io;return[Math.cos(t)*n,Math.sin(t)*n]},n};var ql="auto";ao.svg.line=function(){return Mu(m)};var Tl=ao.map({linear:xu,"linear-closed":bu,step:_u,"step-before":wu,"step-after":Su,basis:zu,"basis-open":Lu,"basis-closed":qu,bundle:Tu,cardinal:Eu,"cardinal-open":ku,"cardinal-closed":Nu,monotone:Fu});Tl.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Rl=[0,2/3,1/3,0],Dl=[0,1/3,2/3,0],Pl=[0,1/6,2/3,1/6];ao.svg.line.radial=function(){var n=Mu(Hu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wu.reverse=Su,Su.reverse=wu,ao.svg.area=function(){return Ou(m)},ao.svg.area.radial=function(){var n=Ou(Hu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ao.svg.chord=function(){function n(n,a){var l=t(this,u,n,a),c=t(this,o,n,a);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?i(l.r,l.p1,l.r,l.p0):i(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+i(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=a.call(n,i,r),o=l.call(n,i,r)-Io,f=c.call(n,i,r)-Io;return{r:u,a0:o,a1:f,p0:[u*Math.cos(o),u*Math.sin(o)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Fo)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=Me,o=xe,a=Iu,l=gu,c=vu;return n.radius=function(t){return arguments.length?(a=En(t),n):a},n.source=function(t){return arguments.length?(u=En(t),n):u},n.target=function(t){return arguments.length?(o=En(t),n):o},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},ao.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),o=e.call(this,n,i),a=(u.y+o.y)/2,l=[u,{x:u.x,y:a},{x:o.x,y:a},o];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yu;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ao.svg.diagonal.radial=function(){var n=ao.svg.diagonal(),t=Yu,e=n.projection;return n.projection=function(n){return arguments.length?e(Zu(t=n)):t},n},ao.svg.symbol=function(){function n(n,r){return(Ul.get(t.call(this,n,r))||$u)(e.call(this,n,r))}var t=Xu,e=Vu;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Ul=ao.map({circle:$u,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Fl)),e=t*Fl;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ao.svg.symbolTypes=Ul.keys();var jl=Math.sqrt(3),Fl=Math.tan(30*Yo);Co.transition=function(n){for(var t,e,r=Hl||++Zl,i=Ku(n),u=[],o=Ol||{time:Date.now(),ease:Nr,delay:0,duration:250},a=-1,l=this.length;++au;u++){i.push(t=[]);for(var e=this[u],a=0,l=e.length;l>a;a++)(r=e[a])&&n.call(r,r.__data__,a,u)&&t.push(r)}return Wu(i,this.namespace,this.id)},Yl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(i){i[r][e].tween.set(n,t)})},Yl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?$r:Mr,a=ao.ns.qualify(n);return Ju(this,"attr."+n,t,a.local?u:i)},Yl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ao.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},Yl.style=function(n,e,r){function i(){this.style.removeProperty(n)}function u(e){return null==e?i:(e+="",function(){var i,u=t(this).getComputedStyle(this,null).getPropertyValue(n);return u!==e&&(i=Mr(u,e),function(t){this.style.setProperty(n,i(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ju(this,"style."+n,e,u)},Yl.styleTween=function(n,e,r){function i(i,u){var o=e.call(this,i,u,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,i)},Yl.text=function(n){return Ju(this,"text",n,Gu)},Yl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Yl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ao.ease.apply(ao,arguments)),Y(this,function(r){r[e][t].ease=n}))},Yl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,i,u){r[e][t].delay=+n.call(r,r.__data__,i,u)}:(n=+n,function(r){r[e][t].delay=n}))},Yl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,i,u){r[e][t].duration=Math.max(1,n.call(r,r.__data__,i,u))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Yl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var i=Ol,u=Hl;try{Hl=e,Y(this,function(t,i,u){Ol=t[r][e],n.call(t,t.__data__,i,u)})}finally{Ol=i,Hl=u}}else Y(this,function(i){var u=i[r][e];(u.event||(u.event=ao.dispatch("start","end","interrupt"))).on(n,t)});return this},Yl.transition=function(){for(var n,t,e,r,i=this.id,u=++Zl,o=this.namespace,a=[],l=0,c=this.length;c>l;l++){a.push(n=[]);for(var t=this[l],f=0,s=t.length;s>f;f++)(e=t[f])&&(r=e[o][i],Qu(e,f,o,u,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wu(a,o,u)},ao.svg.axis=function(){function n(n){n.each(function(){var n,c=ao.select(this),f=this.__chart__||e,s=this.__chart__=e.copy(),h=null==l?s.ticks?s.ticks.apply(s,a):s.domain():l,p=null==t?s.tickFormat?s.tickFormat.apply(s,a):m:t,g=c.selectAll(".tick").data(h,s),v=g.enter().insert("g",".domain").attr("class","tick").style("opacity",Uo),d=ao.transition(g.exit()).style("opacity",Uo).remove(),y=ao.transition(g.order()).style("opacity",1),M=Math.max(i,0)+o,x=Zi(s),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ao.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=y.select("line"),C=g.select("text").text(p),z=v.select("text"),L=y.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=no,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*u+"V0H"+x[1]+"V"+q*u)):(n=to,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*u+","+x[0]+"H0V"+x[1]+"H"+q*u)),E.attr(N,q*i),z.attr(k,q*M),A.attr(S,0).attr(N,q*i),L.attr(w,0).attr(k,q*M),s.rangeBand){var T=s,R=T.rangeBand()/2;f=s=function(n){return T(n)+R}}else f.rangeBand?f=s:d.call(n,s,f);v.call(n,f,s),y.call(n,s,s)})}var t,e=ao.scale.linear(),r=Vl,i=6,u=6,o=3,a=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Xl?t+"":Vl,n):r},n.ticks=function(){return arguments.length?(a=co(arguments),n):a},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(i=+t,u=+arguments[e-1],n):i},n.innerTickSize=function(t){return arguments.length?(i=+t,n):i},n.outerTickSize=function(t){return arguments.length?(u=+t,n):u},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Vl="bottom",Xl={top:1,right:1,bottom:1,left:1};ao.svg.brush=function(){function n(t){t.each(function(){var t=ao.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,m);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return $l[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,s=ao.transition(t),h=ao.transition(o);c&&(l=Zi(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(s)),f&&(l=Zi(f),h.attr("y",l[0]).attr("height",l[1]-l[0]),i(s)),e(s)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+s[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",s[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1]-s[0])}function i(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function u(){function u(){32==ao.event.keyCode&&(C||(M=null,L[0]-=s[1],L[1]-=h[1],C=2),S())}function v(){32==ao.event.keyCode&&2==C&&(L[0]+=s[1],L[1]+=h[1],C=0,S())}function d(){var n=ao.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ao.event.altKey?(M||(M=[(s[0]+s[1])/2,(h[0]+h[1])/2]),L[0]=s[+(n[0]f?(i=r,r=f):i=f),v[0]!=r||v[1]!=i?(e?a=null:o=null,v[0]=r,v[1]=i,!0):void 0}function m(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ao.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ao.select(ao.event.target),w=l.of(b,arguments),k=ao.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&f,C=_.classed("extent"),z=W(b),L=ao.mouse(b),q=ao.select(t(b)).on("keydown.brush",u).on("keyup.brush",v);if(ao.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",m):q.on("mousemove.brush",d).on("mouseup.brush",m),k.interrupt().selectAll("*").interrupt(),C)L[0]=s[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[s[1-T]-L[0],h[1-R]-L[1]],L[0]=s[T],L[1]=h[R]}else ao.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ao.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,l=N(n,"brushstart","brush","brushend"),c=null,f=null,s=[0,0],h=[0,0],p=!0,g=!0,v=Bl[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:s,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Hl?ao.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,s=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(s,t.x),r=xr(h,t.y);return o=a=null,function(i){s=t.x=e(i),h=t.y=r(i),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=Bl[!c<<1|!f],n):c},n.y=function(t){return arguments.length?(f=t,v=Bl[!c<<1|!f],n):f},n.clamp=function(t){return arguments.length?(c&&f?(p=!!t[0],g=!!t[1]):c?p=!!t:f&&(g=!!t),n):c&&f?[p,g]:c?p:f?g:null},n.extent=function(t){var e,r,i,u,l;return arguments.length?(c&&(e=t[0],r=t[1],f&&(e=e[0],r=r[0]),o=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),e==s[0]&&r==s[1]||(s=[e,r])),f&&(i=t[0],u=t[1],c&&(i=i[1],u=u[1]),a=[i,u],f.invert&&(i=f(i),u=f(u)),i>u&&(l=i,i=u,u=l),i==h[0]&&u==h[1]||(h=[i,u])),n):(c&&(o?(e=o[0],r=o[1]):(e=s[0],r=s[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),f&&(a?(i=a[0],u=a[1]):(i=h[0],u=h[1],f.invert&&(i=f.invert(i),u=f.invert(u)),i>u&&(l=i,i=u,u=l))),c&&f?[[e,i],[r,u]]:c?[e,r]:f&&[i,u])},n.clear=function(){return n.empty()||(s=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!c&&s[0]==s[1]||!!f&&h[0]==h[1]},ao.rebind(n,l,"on")};var $l={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Bl=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Wl=ga.format=xa.timeFormat,Jl=Wl.utc,Gl=Jl("%Y-%m-%dT%H:%M:%S.%LZ");Wl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?eo:Gl,eo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},eo.toString=Gl.toString,ga.second=On(function(n){return new va(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ga.seconds=ga.second.range,ga.seconds.utc=ga.second.utc.range,ga.minute=On(function(n){return new va(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ga.minutes=ga.minute.range,ga.minutes.utc=ga.minute.utc.range,ga.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new va(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ga.hours=ga.hour.range,ga.hours.utc=ga.hour.utc.range,ga.month=On(function(n){return n=ga.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ga.months=ga.month.range,ga.months.utc=ga.month.utc.range;var Kl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Ql=[[ga.second,1],[ga.second,5],[ga.second,15],[ga.second,30],[ga.minute,1],[ga.minute,5],[ga.minute,15],[ga.minute,30],[ga.hour,1],[ga.hour,3],[ga.hour,6],[ga.hour,12],[ga.day,1],[ga.day,2],[ga.week,1],[ga.month,1],[ga.month,3],[ga.year,1]],nc=Wl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),tc={range:function(n,t,e){return ao.range(Math.ceil(n/e)*e,+t,e).map(io)},floor:m,ceil:m};Ql.year=ga.year,ga.scale=function(){return ro(ao.scale.linear(),Ql,nc)};var ec=Ql.map(function(n){return[n[0].utc,n[1]]}),rc=Jl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);ec.year=ga.year.utc,ga.scale.utc=function(){return ro(ao.scale.linear(),ec,rc)},ao.text=An(function(n){return n.responseText}),ao.json=function(n,t){return Cn(n,"application/json",uo,t)},ao.html=function(n,t){return Cn(n,"text/html",oo,t)},ao.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=ao,define(ao)):"object"==typeof module&&module.exports?module.exports=ao:this.d3=ao}(); \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js new file mode 100644 index 000000000..29cacd4d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/file.js @@ -0,0 +1,62 @@ + $(function() { + var $window = $(window) + , $top_link = $('#toplink') + , $body = $('body, html') + , offset = $('#code').offset().top + , hidePopover = function ($target) { + $target.data('popover-hover', false); + + setTimeout(function () { + if (!$target.data('popover-hover')) { + $target.popover('hide'); + } + }, 300); + }; + + $top_link.hide().click(function(event) { + event.preventDefault(); + $body.animate({scrollTop:0}, 800); + }); + + $window.scroll(function() { + if($window.scrollTop() > offset) { + $top_link.fadeIn(); + } else { + $top_link.fadeOut(); + } + }).scroll(); + + $('.popin') + .popover({trigger: 'manual'}) + .on({ + 'mouseenter.popover': function () { + var $target = $(this); + var $container = $target.children().first(); + + $target.data('popover-hover', true); + + // popover already displayed + if ($target.next('.popover').length) { + return; + } + + // show the popover + $container.popover('show'); + + // register mouse events on the popover + $target.next('.popover:not(.popover-initialized)') + .on({ + 'mouseenter': function () { + $target.data('popover-hover', true); + }, + 'mouseleave': function () { + hidePopover($container); + } + }) + .addClass('popover-initialized'); + }, + 'mouseleave.popover': function () { + hidePopover($(this).children().first()); + } + }); + }); diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js new file mode 100644 index 000000000..2c69bc908 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(c.nvPointerEventsClass)))return;return h.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void c.hidden(!0)}c.hidden(!1);var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){i&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c=a.models.tooltip();c.duration(0).hideDelay(0)._isInteractiveLayer(!0).hidden(!1);var d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick"),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";a.models.tooltip=function(){function b(){if(k){var a=d3.select(k);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"),10)/b[2];p.left=p.left*c,p.top=p.top*c}}}function c(){if(!n){var a;a=k?k:document.body,n=d3.select(a).append("div").attr("class","nvtooltip "+(j?j:"xy-tooltip")).attr("id",v),n.style("top",0).style("left",0),n.style("opacity",0),n.selectAll("div, table, td, tr").classed(w,!0),n.classed(w,!0),o=n.node()}}function d(){if(r&&B(e)){b();var f=p.left,g=null!==i?i:p.top;return a.dom.write(function(){c();var b=A(e);b&&(o.innerHTML=b),k&&u?a.dom.read(function(){var a=k.getElementsByTagName("svg")[0],b={left:0,top:0};if(a){var c=a.getBoundingClientRect(),d=k.getBoundingClientRect(),e=c.top;if(0>e){var i=k.getBoundingClientRect();e=Math.abs(e)>i.height?0:e}b.top=Math.abs(e-d.top),b.left=Math.abs(c.left-d.left)}f+=k.offsetLeft+b.left-2*k.scrollLeft,g+=k.offsetTop+b.top-2*k.scrollTop,h&&h>0&&(g=Math.floor(g/h)*h),C([f,g])}):C([f,g])}),d}}var e=null,f="w",g=25,h=0,i=null,j=null,k=null,l=!0,m=400,n=null,o=null,p={left:null,top:null},q={left:0,top:0},r=!0,s=100,t=!0,u=!1,v="nvtooltip-"+Math.floor(1e5*Math.random()),w="nv-pointer-events-none",x=function(a){return a},y=function(a){return a},z=function(a){return a},A=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(t){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(y(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).html(function(a,b){return z(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return x(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}});var f=b.node().outerHTML;return void 0!==a.footer&&(f+=""),f},B=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},C=function(b){o&&a.dom.read(function(){var c,d,e=parseInt(o.offsetHeight,10),h=parseInt(o.offsetWidth,10),i=a.utils.windowSize().width,j=a.utils.windowSize().height,k=window.pageYOffset,p=window.pageXOffset;j=window.innerWidth>=document.body.scrollWidth?j:j-16,i=window.innerHeight>=document.body.scrollHeight?i:i-16;var r,t,u=function(a){var b=d;do isNaN(a.offsetTop)||(b+=a.offsetTop),a=a.offsetParent;while(a);return b},v=function(a){var b=c;do isNaN(a.offsetLeft)||(b+=a.offsetLeft),a=a.offsetParent;while(a);return b};switch(f){case"e":c=b[0]-h-g,d=b[1]-e/2,r=v(o),t=u(o),p>r&&(c=b[0]+g>p?b[0]+g:p-r+c),k>t&&(d=k-t+d),t+e>k+j&&(d=k+j-t+d-e);break;case"w":c=b[0]+g,d=b[1]-e/2,r=v(o),t=u(o),r+h>i&&(c=b[0]-h-g),k>t&&(d=k+5),t+e>k+j&&(d=k+j-t+d-e);break;case"n":c=b[0]-h/2-5,d=b[1]+g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),t+e>k+j&&(d=k+j-t+d-e);break;case"s":c=b[0]-h/2,d=b[1]-e-g,r=v(o),t=u(o),p>r&&(c=p+5),r+h>i&&(c=c-h/2+5),k>t&&(d=k);break;case"none":c=b[0],d=b[1]-g,r=v(o),t=u(o)}c-=q.left,d-=q.top;var w=o.getBoundingClientRect(),k=window.pageYOffset||document.documentElement.scrollTop,p=window.pageXOffset||document.documentElement.scrollLeft,x="translate("+(w.left+p)+"px, "+(w.top+k)+"px)",y="translate("+c+"px, "+d+"px)",z=d3.interpolateString(x,y),A=n.style("opacity")<.1;l?n.transition().delay(m).duration(0).style("opacity",0):n.interrupt().transition().duration(A?0:s).styleTween("transform",function(){return z},"important").style("-webkit-transform",y).style("opacity",1)})};return d.nvPointerEventsClass=w,d.options=a.utils.optionsFunc.bind(d),d._options=Object.create({},{duration:{get:function(){return s},set:function(a){s=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return j},set:function(a){j=a}},chartContainer:{get:function(){return k},set:function(a){k=a}},fixedTop:{get:function(){return i},set:function(a){i=a}},enabled:{get:function(){return r},set:function(a){r=a}},hideDelay:{get:function(){return m},set:function(a){m=a}},contentGenerator:{get:function(){return A},set:function(a){A=a}},valueFormatter:{get:function(){return x},set:function(a){x=a}},headerFormatter:{get:function(){return y},set:function(a){y=a}},keyFormatter:{get:function(){return z},set:function(a){z=a}},headerEnabled:{get:function(){return t},set:function(a){t=a}},_isInteractiveLayer:{get:function(){return u},set:function(a){u=!!a}},position:{get:function(){return p},set:function(a){p.left=void 0!==a.left?a.left:p.left,p.top=void 0!==a.top?a.top:p.top}},offset:{get:function(){return q},set:function(a){q.left=void 0!==a.left?a.left:q.left,q.top=void 0!==a.top?a.top:q.top}},hidden:{get:function(){return l},set:function(a){l!=a&&(l=!!a,d())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},tooltipElem:{get:function(){return o},set:function(){}},id:{get:function(){return v},set:function(){}}}),a.utils.initOptions(d),d}}(),a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e){var f=b(e);return"function"==typeof a[f]?a[f]():void 0!==a[f]?a[f]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a||a===-1/0?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;a.__rendered=0===a.length?!0:a.every(function(a){return!a.length})?!0:!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(d.height(),c,e),i=a.utils.availableWidth(d.width(),c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(){var a=this.getBoundingClientRect(),b=a.width;A=a.height,b>z&&(z=b)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max bottom").attr("transform",function(b){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a){var b=u(a);return(""+b).match("NaN")?"":b}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a){(d(a)E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g"); +x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){p.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return tooltips},set:function(a){tooltips=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch("tooltipShow","tooltipHide");return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},tooltips:{get:function(){return d.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),d.enabled(!!b)}},tooltipContent:{get:function(){return d.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),d.contentGenerator(b)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();{var H=G.enter().append("g").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}c.selectAll(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),c.selectAll(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(){d3.select(b.container).style("cursor","ew-resize")}function E(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){bb.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)z[P]=y[P]instanceof Array?y[P].slice(0):y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),ab=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",ab).attr("y2",ab),_.exit().remove();var bb=Z.selectAll(".nv-indexLine").data([G]);bb.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),bb.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(j.map(function(a){return a.value}),o,q);null!==r&&(j[r].highlight=!0)}var s=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+m.left,top:c.mouseY+m.top}).chartContainer(M.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:s,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,bb.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b){if(!b.values)return b;var c=b.values[a];if(null==c)return b;var d=K(c,a);return-.95>d&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-d)/(1+d)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).position(a.pos).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},tooltips:{get:function(){return l.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),l.enabled(!!b)}},tooltipContent:{get:function(){return l.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),l.contentGenerator(b)}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return t.reset(),t.models(e),m&&t.models(f),n&&t.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var q=a.utils.availableWidth(j,l,i),t=a.utils.availableHeight(k,l,i);if(b.update=function(){r.beforeUpdate(),l.transition().duration(s).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var u=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),w=v.append("defs"),x=u.select("g");v.append("g").attr("class","nv-x nv-axis"),v.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),v.append("g").attr("class","nv-barsWrap"),x.attr("transform","translate("+i.left+","+i.top+")"),o&&x.select(".nv-y.nv-axis").attr("transform","translate("+q+",0)"),e.width(q).height(t);var y=x.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(y.transition().call(e),w.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),x.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(q/100,h)).tickSize(-t,0),x.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),x.select(".nv-x.nv-axis").call(f); +var z=x.select(".nv-x.nv-axis").selectAll("g");p&&z.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}n&&(g.scale(d)._ticks(a.utils.calcTicksY(t/36,h)).tickSize(-q,0),x.select(".nv-y.nv-axis").call(g)),x.select(".nv-zeroLine line").attr("x1",0).attr("x2",q).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=null,r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){h.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=r,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return h.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),h.enabled(!!b)}},tooltipContent:{get:function(){return h.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),h.contentGenerator(b)}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?g(a,b):"#fff":m?void 0:a.disabled?g(a,b):"#fff"}function r(a,b){return m&&"furious"==o?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return p.each(function(b){var p=d-c.left-c.right,s=d3.select(this);a.utils.initSVG(s);var t=s.selectAll("g.nv-legend").data([b]),u=(t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),t.select("g"));t.attr("transform","translate("+c.left+","+c.top+")");var v,w=u.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),x=w.enter().append("g").attr("class","nv-series");if("classic"==o)x.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),v=w.select("circle");else if("furious"==o){x.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),v=w.select("rect"),x.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var y=w.select(".nv-check-box");y.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}x.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var z=w.select("text.nv-legend-text");w.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=w.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=w.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),w.classed("nv-disabled",function(a){return a.userDisabled}),w.exit().remove(),z.attr("fill",q).text(f);var A;switch(o){case"furious":A=23;break;case"classic":A=20}if(h){var B=[];w.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}B.push(b+i)});for(var C=0,D=0,E=[];p>D&&Cp&&C>1;){E=[],C--;for(var F=0;F(E[F%C]||0)&&(E[F%C]=B[F]);D=E.reduce(function(a,b){return a+b})}for(var G=[],H=0,I=0;C>H;H++)G[H]=I,I+=E[H];w.attr("transform",function(a,b){return"translate("+G[b%C]+","+(5+Math.floor(b/C)*A)+")"}),j?u.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):u.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(B.length/C)*A}else{var J,K=5,L=5,M=0;w.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return J=L,dM&&(M=L),"translate("+J+","+K+")"}),u.attr("transform","translate("+(d-c.right-M)+","+c.top+")"),e=c.top+c.bottom+K+15}"furious"==o&&v.attr("width",function(a,b){return z[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.style("fill",r).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=28,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,n=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var h=g.values[e];void 0!==h&&(void 0===d&&(d=h),void 0===i&&(i=c.xScale()(c.x()(h,e))),n.push({key:g.key,value:c.y()(h,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var o=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(A.parentNode).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:o,index:e,series:n})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(){k.position({top:d3.event.pageY,left:d3.event.pageX})()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
    open:"+b.yAxis.tickFormat()(c.open)+"
    close:"+b.yAxis.tickFormat()(c.close)+"
    high"+b.yAxis.tickFormat()(c.high)+"
    low:"+b.yAxis.tickFormat()(c.low)+"
    "}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
    open:"+b.yAxis.tickFormat()(c.open)+"
    close:"+b.yAxis.tickFormat()(c.close)+"
    high"+b.yAxis.tickFormat()(c.high)+"
    low:"+b.yAxis.tickFormat()(c.low)+"
    "}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var A=y.select(".nv-check-box");A.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",q(a,b))})}z.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var B=y.select("text.nv-legend-text");y.on("mouseover",function(a,b){n.legendMouseover(a,b)}).on("mouseout",function(a,b){n.legendMouseout(a,b)}).on("click",function(a,b){n.legendClick(a,b);var c=y.data();if(k){if("classic"==o)l?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==o)if(m)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!m){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}n.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=o||!m)&&(n.legendDblclick(a,b),k)){var c=y.data();c.forEach(function(a){a.disabled=!0,"furious"==o&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==o&&(a.userDisabled=a.disabled),n.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),y.classed("nv-disabled",function(a){return a.userDisabled}),y.exit().remove(),B.attr("fill",q).text(f);var C=0;if(h){var D=[];y.each(function(){var b,c=d3.select(this).select("text");try{if(b=c.node().getComputedTextLength(),0>=b)throw Error()}catch(d){b=a.utils.calcApproxTextWidth(c)}D.push(b+i)});var E=0,F=[];for(C=0;g>C&&Eg&&E>1;){F=[],E--;for(var G=0;G(F[G%E]||0)&&(F[G%E]=D[G]);C=F.reduce(function(a,b){return a+b})}for(var H=[],I=0,J=0;E>I;I++)H[I]=J,J+=F[I];y.attr("transform",function(a,b){return"translate("+H[b%E]+","+(5+Math.floor(b/E)*x)+")"}),j?v.attr("transform","translate("+(d-c.right-C)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(D.length/E)*x}else{var K,L=5,M=5,N=0;y.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+i;return K=M,dN&&(N=M),K+N>C&&(C=K+N),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}if("furious"==o){w.attr("width",function(a,b){return B[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),u.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var O=v.select(".nv-legend-bg");O.transition().duration(300).attr("x",-x).attr("width",C+x-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",m?1:0)}w.style("fill",r).style("fill-opacity",s).style("stroke",r)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=!0,i=32,j=!0,k=!0,l=!1,m=!1,n=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),o="classic";return b.dispatch=n,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return j},set:function(a){j=a}},padding:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return k},set:function(a){k=a}},radioButtonMode:{get:function(){return l},set:function(a){l=a}},expanded:{get:function(){return m},set:function(a){m=a}},vers:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)u[D]=t[D]instanceof Array?t[D].slice(0):t[D] +}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),G.select("rect").attr("width",B).attr("height",C>0?C:0),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var H=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));H.call(e),p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,m,n=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===m&&(m=b.xScale()(b.x()(i,h))),n.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),n.length>2){var o=b.yScale().invert(c.mouseY),p=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*p,r=a.nearestValueIndex(n.map(function(a){return a.value}),o,q);null!==r&&(n[r].highlight=!0)}var s=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:c.mouseX+k.left,top:c.mouseY+k.top}).chartContainer(y.parentNode).valueFormatter(function(a){return null==a?"N/A":g.tickFormat()(a)}).data({value:s,index:h,series:n})(),i.renderGuideLine(m)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=X/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function S(){u.empty()||u.extent(I),kb.data([u.empty()?e.domain():I]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function T(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),S(),l.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(V).height(W).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=db.select(".nv-focus .nv-barsWrap").datum(Z.length?Z.map(function(a){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=db.select(".nv-focus .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$.map(function(a){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=Z.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-W,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),db.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),db.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(-V,0),q.scale(g)._ticks(a.utils.calcTicksY(W/36,v)).tickSize(Z.length?0:-V,0),db.select(".nv-focus .nv-y1.nv-axis").style("opacity",Z.length?1:0),db.select(".nv-focus .nv-y2.nv-axis").style("opacity",$.length&&!$[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),db.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),db.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var U=d3.select(this);a.utils.initSVG(U);var V=a.utils.availableWidth(y,U,w),W=a.utils.availableHeight(z,U,w)-(E?H:0),X=H-x.top-x.bottom;if(b.update=function(){U.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Y;N={};for(Y in M)N[Y]=M[Y]instanceof Array?M[Y].slice(0):M[Y]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,U),b;U.selectAll(".nv-noData").remove();var Z=v.filter(function(a){return!a.disabled&&a.bar}),$=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var _=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ab=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,V]),e.domain(d3.extent(d3.merge(_.concat(ab)),function(a){return a.x})).range([0,V]);var bb=U.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),cb=bb.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),db=bb.select("g");cb.append("g").attr("class","nv-legendWrap");var eb=cb.append("g").attr("class","nv-focus");eb.append("g").attr("class","nv-x nv-axis"),eb.append("g").attr("class","nv-y1 nv-axis"),eb.append("g").attr("class","nv-y2 nv-axis"),eb.append("g").attr("class","nv-barsWrap"),eb.append("g").attr("class","nv-linesWrap");var fb=cb.append("g").attr("class","nv-context");if(fb.append("g").attr("class","nv-x nv-axis"),fb.append("g").attr("class","nv-y1 nv-axis"),fb.append("g").attr("class","nv-y2 nv-axis"),fb.append("g").attr("class","nv-barsWrap"),fb.append("g").attr("class","nv-linesWrap"),fb.append("g").attr("class","nv-brushBackground"),fb.append("g").attr("class","nv-x nv-brush"),D){var gb=t.align()?V/2:V,hb=t.align()?gb:0;t.width(gb),db.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),W=a.utils.availableHeight(z,U,w)-H),db.select(".nv-legendWrap").attr("transform","translate("+hb+","+-w.top+")")}bb.attr("transform","translate("+w.left+","+w.top+")"),db.select(".nv-context").style("display",E?"initial":"none"),m.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(V).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ib=db.select(".nv-context .nv-barsWrap").datum(Z.length?Z:[{values:[]}]),jb=db.select(".nv-context .nv-linesWrap").datum($[0].disabled?[{values:[]}]:$);db.select(".nv-context").attr("transform","translate(0,"+(W+w.bottom+x.top)+")"),ib.transition().call(m),jb.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(V/100,v)).tickSize(-X,0),db.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),db.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(X/36).tickSize(-V,0),s.scale(i)._ticks(X/36).tickSize(Z.length?0:-V,0),db.select(".nv-context .nv-y3.nv-axis").style("opacity",Z.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),db.select(".nv-context .nv-y2.nv-axis").style("opacity",$.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),db.select(".nv-context .nv-y1.nv-axis").transition().call(r),db.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",T),I&&u.extent(I);var kb=db.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),lb=kb.enter().append("g");lb.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",X),lb.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",X);var mb=db.select(".nv-x.nv-brush").call(u);mb.selectAll("rect").attr("height",X),mb.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),T()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).position(a.pos).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(){v.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},tooltips:{get:function(){return v.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),v.enabled(!!b)}},tooltipContent:{get:function(){return v.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),v.contentGenerator(b)}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a){var b=e(a[0])-c.range()[0],d=K-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),r=.03*m,t=a.nearestValueIndex(k.map(function(a){return a.value}),l,r);null!==t&&(k[t].highlight=!0)}var u=i.tickFormat()(b.x()(d,f));p.tooltip.position({left:c.mouseX+q.left,top:c.mouseY+q.top}).chartContainer(J.parentNode).valueFormatter(function(a){return null==a?"N/A":j.tickFormat()(a)}).data({value:u,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).position(a.pos).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},tooltips:{get:function(){return o.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),o.enabled(!!b)}},tooltipContent:{get:function(){return o.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),o.contentGenerator(b)}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(E){return C.reset(),E.each(function(b){var E=k-j.left-j.right,F=l-j.top-j.bottom;p=d3.select(this),a.utils.initSVG(p);var G=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var H=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);H.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=G++,H[c]=b[c]):c>0&&H[c-1].nonStackable&&H[c].values.map(function(a,b){a.y0-=H[c-1].values[b].y,a.y1=a.y0+a.y})}),b=H}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var I=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(I).map(function(a){return a.x})).rangeBands(f||[0,E],A),n.domain(e||d3.extent(d3.merge(I).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[F,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var J=p.selectAll("g.nv-wrap.nv-multibar").data([b]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),L=K.append("defs"),M=K.append("g"),N=J.select("g");M.append("g").attr("class","nv-groups"),J.attr("transform","translate("+j.left+","+j.top+")"),L.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),J.select("#nv-edge-clip-"+o+" rect").attr("width",E).attr("height",F),N.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var O=J.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var P=C.transition(O.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a){var c=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(c=i(a.y0)),c}).attr("height",0).remove();P.delay&&P.delay(function(a,b){var c=b*(z/(D+1))-b;return c}),O.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){return w(a,b)}),O.style("stroke-opacity",1).style("fill-opacity",.75);var Q=O.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});Q.exit().remove();Q.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});Q.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){B.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){B.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){B.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),Q.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),Q.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var R=Q.watchTransition(C,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?R.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),1)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),1)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==G&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*G))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/G;return b.length!==G&&(e=m.rangeBand()/(2*G)),e}return m.rangeBand()}):R.attr("x",function(a){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(D=b[0].values.length)}),C.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=a.utils.renderWatch(B,z),D=0;return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return D.reset(),D.models(e),r&&D.models(f),s&&D.models(g),j.each(function(j){var z=d3.select(this);a.utils.initSVG(z);var D=a.utils.availableWidth(l,z,k),H=a.utils.availableHeight(m,z,k);if(b.update=function(){0===C?z.call(b):z.transition().duration(C).call(b)},b.container=this,x.setter(G(j),b.update).getter(F(j)).update(),x.disabled=j.map(function(a){return!!a.disabled}),!y){var I;y={};for(I in x)y[I]=x[I]instanceof Array?x[I].slice(0):x[I]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale(); +var J=z.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),q&&(h.width(D-B()),L.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),H=a.utils.availableHeight(m,z,k)),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-k.top+")")),o){var M=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-k.top+")").call(i)}J.attr("transform","translate("+k.left+","+k.top+")"),t&&L.select(".nv-y.nv-axis").attr("transform","translate("+D+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(D).height(H).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var N=L.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(N.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-H,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),v){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,c%2==0?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||S%2!==0?R:Q)})}u&&O.filter(function(a,b){return b%Math.ceil(j[0].values.length/(D/100))!==0}).selectAll("text, line").style("opacity",0),w&&O.selectAll(".tick text").attr("transform","rotate("+w+" 0,0)").style("text-anchor",w>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(H/36,j)).tickSize(-D,0),L.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),b.update()}}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),x.stacked=a.stacked,E=a.stacked),b.update()})}),D.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=0,x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=function(){return o?180:0},C=250;x.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var D=a.utils.renderWatch(A),E=!1,F=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:E}}},G=function(a){return function(b){void 0!==b.stacked&&(E=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=A,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=x,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return w},set:function(a){w=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return C},set:function(a){C=a,e.duration(C),f.duration(C),g.duration(C),D.reset(C)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return E.reset(),m.each(function(b){var m=k-j.left-j.right,C=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var F=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(F).map(function(a){return a.x})).rangeBands(f||[0,C],A),p.domain(e||d3.extent(d3.merge(F).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),p.range(x&&!w?g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var G=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),I=(H.append("defs"),H.append("g"));G.select("g")}I.append("g").attr("class","nv-groups"),G.attr("transform","translate("+j.left+","+j.top+")");var J=G.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});J.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),J.exit().watchTransition(E,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),J.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),J.watchTransition(E,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("g.nv-bar").data(function(a){return a.values});K.exit().remove();var L=K.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});L.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),K.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(L.append("polyline"),K.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),L.append("text"),x&&!w?(K.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=B(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+B(Math.abs(d[1]))+"-"+B(Math.abs(d[0])):c+"±"+B(Math.abs(d))}),K.watchTransition(E,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):K.selectAll("text").text(""),y&&!w?(L.append("text").classed("nv-bar-label",!0),K.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),K.watchTransition(E,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):K.selectAll("text.nv-bar-label").text(""),K.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),K.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))}).attr("height",o.rangeBand()):K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)}),h=o.copy(),i=p.copy()}),E.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=d3.format(",.2f"),C=250,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,C);return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return B},set:function(a){B=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(){j.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},tooltips:{get:function(){return j.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),j.enabled(!!b)}},tooltipContent:{get:function(){return j.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),j.contentGenerator(b)}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function k(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color},B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function l(a){var b=2===j[a.seriesIndex].yAxis?z:y;a.point.x=v.x()(a.point),a.point.y=v.y()(a.point),B.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).position(a.pos).hidden(!1)}function n(a){var b=2===j[a.data.series].yAxis?z:y;a.value=t.x()(a.data),a.series={value:t.y()(a.data),color:a.color},B.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var C=d3.select(this);a.utils.initSVG(C),b.update=function(){C.transition().call(b)},b.container=this;var D=a.utils.availableWidth(g,C,e),E=a.utils.availableHeight(h,C,e),F=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),G=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),H=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),I=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),J=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),K=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,C),b;C.selectAll(".nv-noData").remove();var L=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),M=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});o.domain(d3.extent(d3.merge(L.concat(M)),function(a){return a.x})).range([0,D]);var N=C.selectAll("g.wrap.multiChart").data([j]),O=N.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y1 nv-axis"),O.append("g").attr("class","nv-y2 nv-axis"),O.append("g").attr("class","lines1Wrap"),O.append("g").attr("class","lines2Wrap"),O.append("g").attr("class","bars1Wrap"),O.append("g").attr("class","bars2Wrap"),O.append("g").attr("class","stack1Wrap"),O.append("g").attr("class","stack2Wrap"),O.append("g").attr("class","legendWrap");var P=N.select("g"),Q=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var R=A.align()?D/2:D,S=A.align()?R:0;A.width(R),A.color(Q),P.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(A),e.top!=A.height()&&(e.top=A.height(),E=a.utils.availableHeight(h,C,e)),P.select(".legendWrap").attr("transform","translate("+S+","+-e.top+")")}r.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(D).height(E).interpolate(m).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),u.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),v.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),w.width(D).height(E).color(Q.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),P.attr("transform","translate("+e.left+","+e.top+")");var T=P.select(".lines1Wrap").datum(F.filter(function(a){return!a.disabled})),U=P.select(".bars1Wrap").datum(H.filter(function(a){return!a.disabled})),V=P.select(".stack1Wrap").datum(J.filter(function(a){return!a.disabled})),W=P.select(".lines2Wrap").datum(G.filter(function(a){return!a.disabled})),X=P.select(".bars2Wrap").datum(I.filter(function(a){return!a.disabled})),Y=P.select(".stack2Wrap").datum(K.filter(function(a){return!a.disabled})),Z=J.length?J.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(L).concat(Z),function(a){return a.y})).range([0,E]),q.domain(d||d3.extent(d3.merge(M).concat($),function(a){return a.y})).range([0,E]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),J.length&&d3.transition(V).call(v),K.length&&d3.transition(Y).call(w),H.length&&d3.transition(U).call(t),I.length&&d3.transition(X).call(u),F.length&&d3.transition(T).call(r),G.length&&d3.transition(W).call(s),x._ticks(a.utils.calcTicksX(D/100,j)).tickSize(-E,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+E+")"),d3.transition(P.select(".nv-x.nv-axis")).call(x),y._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y1.nv-axis")).call(y),z._ticks(a.utils.calcTicksY(E/36,j)).tickSize(-D,0),d3.transition(P.select(".nv-y2.nv-axis")).call(z),P.select(".nv-y1.nv-axis").classed("nv-disabled",L.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),P.select(".nv-y2.nv-axis").classed("nv-disabled",M.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),A.dispatch.on("stateChange",function(){b.update()}),r.dispatch.on("elementMouseover.tooltip",k),s.dispatch.on("elementMouseover.tooltip",k),r.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",l),w.dispatch.on("elementMouseover.tooltip",l),v.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",n),u.dispatch.on("elementMouseover.tooltip",n),t.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(){B.hidden(!0)}),t.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()}),u.dispatch.on("elementMousemove.tooltip",function(){B.position({top:d3.event.pageY,left:d3.event.pageX})()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.multiBar().stacked(!1).yScale(p),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.stackedArea().yScale(p),w=a.models.stackedArea().yScale(q),x=a.models.axis().scale(o).orient("bottom").tickPadding(5),y=a.models.axis().scale(p).orient("left"),z=a.models.axis().scale(q).orient("right"),A=a.models.legend().height(30),B=a.models.tooltip(),C=d3.dispatch();return b.dispatch=C,b.lines1=r,b.lines2=s,b.bars1=t,b.bars2=u,b.stack1=v,b.stack2=w,b.xAxis=x,b.yAxis1=y,b.yAxis2=z,b.tooltip=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return B.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),B.enabled(!!b)}},tooltipContent:{get:function(){return B.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),B.contentGenerator(b)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),v.y(a),w.y(a),t.y(a),u.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),v.useVoronoi(a),w.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(){return x[0]}).attr("stroke",function(){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left +}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;Mc)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)m[q]=l[q]instanceof Array?l[q].slice(0):l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd");e.headerEnabled(!1).duration(0).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){e.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return e.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),e.enabled(!!b)}},tooltipContent:{get:function(){return e.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),e.contentGenerator(b)}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"});C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B&&(U.select(".nv-point-clips").selectAll("clipPath").remove(),U.select(".nv-point-clips").selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D));var k=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=window.pageYOffset||document.documentElement.scrollTop,i=window.pageXOffset||document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){k(a,L.elementClick)}).on("dblclick",function(a){k(a,L.elementDblClick)}).on("mouseover",function(a){k(a,L.elementMouseover)}).on("mouseout",function(a){k(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(" .nv-series-"+b+" .nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)x[I]=w[I]instanceof Array?w[I].slice(0):w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos.top-H-j.top),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos.left+g.size()-j.left),i.position(a.pos).data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return i.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),i.enabled(!!b) +}},tooltipContent:{get:function(){return i.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),i.contentGenerator(b)}},tooltipXContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},tooltipYContent:{get:function(){return i.contentGenerator()},set:function(){a.deprecated("tooltipContent","This option is removed, put values into main tooltip.")}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a){return l(n(a,a.pointIndex))}).attr("cy",function(a){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return F.reset(),F.models(e),r&&F.models(f),s&&F.models(g),k.each(function(k){var x=d3.select(this),F=this;a.utils.initSVG(x);var K=a.utils.availableWidth(m,x,l),L=a.utils.availableHeight(n,x,l);if(b.update=function(){x.transition().duration(C).call(b)},b.container=this,v.setter(I(k),b.update).getter(H(k)).update(),v.disabled=k.map(function(a){return!!a.disabled}),!w){var M;w={};for(M in v)w[M]=v[M]instanceof Array?v[M].slice(0):v[M]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,x),b;x.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var N=x.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),P=N.select("g");if(O.append("rect").style("opacity",0),O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),O.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",K).attr("height",L),q){var Q=p?K-z:K;h.width(Q),P.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),L=a.utils.availableHeight(n,x,l)),P.select(".nv-legendWrap").attr("transform","translate("+(K-Q)+","+-l.top+")")}if(p){var R=[{key:B.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:B.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:B.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:B.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];z=A.length/3*260,R=R.filter(function(a){return-1!==A.indexOf(a.metaKey)}),i.width(z).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(R).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),L=a.utils.availableHeight(n,x,l)),P.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}N.attr("transform","translate("+l.left+","+l.top+")"),t&&P.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),u&&(j.width(K).height(L).margin({left:l.left,top:l.top}).svgContainer(x).xScale(c),N.select(".nv-interactive").call(j)),e.width(K).height(L);var S=P.select(".nv-stackedWrap").datum(k);if(S.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(K/100,k)).tickSize(-L,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+L+")"),P.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var T;if(T="wiggle"===e.offset()?0:a.utils.calcTicksY(L/36,k),g.scale(d)._ticks(T).tickSize(-K,0),"expand"===e.style()||"stack_percent"===e.style()){var U=g.tickFormat();D&&U===J||(D=U),g.tickFormat(J)}else D&&(g.tickFormat(D),D=null);P.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),v.disabled=k.map(function(a){return!!a.disabled}),y.stateChange(v),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a){a.disabled&&(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),v.style=e.style(),y.stateChange(v),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[];if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],l=b.y()(k,g);if(null!=l&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var m="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:m,color:o(f,f.seriesIndex),stackedValue:k.display})}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(E||(E=q),q=d3.format(".1%")):E&&(q=E,E=null),j.tooltip.position({left:h+l.left,top:c.mouseY+l.top}).chartContainer(F.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(){e.clearHighlights()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=a.utils.state(),w=null,x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=250,A=["Stacked","Stream","Expanded"],B={},C=250;v.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var D=null,E=null;i.updateState(!1);var F=a.utils.renderWatch(y),G=e.style(),H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},I=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},J=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).position(a.pos).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(){k.hidden(!0)}),b.dispatch=y,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return B},set:function(a){B=a}},controlOptions:{get:function(){return A},set:function(a){A=a}},tooltips:{get:function(){return k.enabled()},set:function(b){a.deprecated("tooltips","use chart.tooltip.enabled() instead"),k.enabled(!!b)}},tooltipContent:{get:function(){return k.contentGenerator()},set:function(b){a.deprecated("tooltipContent","use chart.tooltip.contentGenerator() instead"),k.contentGenerator(b)}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return C},set:function(a){C=a,F.reset(C),e.duration(C),f.duration(C),g.duration(C)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),m=a.utils.renderWatch(l);return d.headerEnabled(!1).duration(0).valueFormatter(function(a){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(){d.position({top:d3.event.pageY,left:d3.event.pageX})()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1"}(); \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js new file mode 100644 index 000000000..bb1aaae3e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/js/popper.min.js @@ -0,0 +1,5 @@ +/* + Copyright (C) Federico Zivolo 2020 + Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT). + */(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e.Popper=t()})(this,function(){'use strict';function e(e){return e&&'[object Function]'==={}.toString.call(e)}function t(e,t){if(1!==e.nodeType)return[];var o=e.ownerDocument.defaultView,n=o.getComputedStyle(e,null);return t?n[t]:n}function o(e){return'HTML'===e.nodeName?e:e.parentNode||e.host}function n(e){if(!e)return document.body;switch(e.nodeName){case'HTML':case'BODY':return e.ownerDocument.body;case'#document':return e.body;}var i=t(e),r=i.overflow,p=i.overflowX,s=i.overflowY;return /(auto|scroll|overlay)/.test(r+s+p)?e:n(o(e))}function i(e){return e&&e.referenceNode?e.referenceNode:e}function r(e){return 11===e?re:10===e?pe:re||pe}function p(e){if(!e)return document.documentElement;for(var o=r(10)?document.body:null,n=e.offsetParent||null;n===o&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&'BODY'!==i&&'HTML'!==i?-1!==['TH','TD','TABLE'].indexOf(n.nodeName)&&'static'===t(n,'position')?p(n):n:e?e.ownerDocument.documentElement:document.documentElement}function s(e){var t=e.nodeName;return'BODY'!==t&&('HTML'===t||p(e.firstElementChild)===e)}function d(e){return null===e.parentNode?e:d(e.parentNode)}function a(e,t){if(!e||!e.nodeType||!t||!t.nodeType)return document.documentElement;var o=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,n=o?e:t,i=o?t:e,r=document.createRange();r.setStart(n,0),r.setEnd(i,0);var l=r.commonAncestorContainer;if(e!==l&&t!==l||n.contains(i))return s(l)?l:p(l);var f=d(e);return f.host?a(f.host,t):a(e,d(t).host)}function l(e){var t=1=o.clientWidth&&n>=o.clientHeight}),l=0a[e]&&!t.escapeWithReference&&(n=Q(f[o],a[e]-('right'===e?f.width:f.height))),ae({},o,n)}};return l.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';f=le({},f,m[t](e))}),e.offsets.popper=f,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,n=t.reference,i=e.placement.split('-')[0],r=Z,p=-1!==['top','bottom'].indexOf(i),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(n[s])&&(e.offsets.popper[d]=r(n[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,o){var n;if(!K(e.instance.modifiers,'arrow','keepTogether'))return e;var i=o.element;if('string'==typeof i){if(i=e.instance.popper.querySelector(i),!i)return e;}else if(!e.instance.popper.contains(i))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var r=e.placement.split('-')[0],p=e.offsets,s=p.popper,d=p.reference,a=-1!==['left','right'].indexOf(r),l=a?'height':'width',f=a?'Top':'Left',m=f.toLowerCase(),h=a?'left':'top',c=a?'bottom':'right',u=S(i)[l];d[c]-us[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f]),E=parseFloat(w['border'+f+'Width']),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,$(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ce.FLIP:p=[n,i];break;case ce.CLOCKWISE:p=G(n);break;case ce.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)f(l.top)||'bottom'===n&&f(a.top)f(o.right),g=f(a.top)f(o.bottom),b='left'===n&&h||'right'===n&&c||'top'===n&&g||'bottom'===n&&u,w=-1!==['top','bottom'].indexOf(n),y=!!t.flipVariations&&(w&&'start'===r&&h||w&&'end'===r&&c||!w&&'start'===r&&g||!w&&'end'===r&&u),E=!!t.flipVariationsByContent&&(w&&'start'===r&&c||w&&'end'===r&&h||!w&&'start'===r&&u||!w&&'end'===r&&g),v=y||E;(m||b||v)&&(e.flipped=!0,(m||b)&&(n=p[d+1]),v&&(r=z(r)),e.placement=n+(r?'-'+r:''),e.offsets.popper=le({},e.offsets.popper,C(e.instance.popper,e.offsets.reference,e.placement)),e=P(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport',flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],n=e.offsets,i=n.popper,r=n.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return i[p?'left':'top']=r[o]-(s?i[p?'width':'height']:0),e.placement=T(t),e.offsets.popper=g(i),e}},hide:{order:800,enabled:!0,fn:function(e){if(!K(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=D(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.rightwindow.devicePixelRatio||!fe),c='bottom'===o?'top':'bottom',g='right'===n?'left':'right',b=B('transform');if(d='bottom'==c?'HTML'===l.nodeName?-l.clientHeight+h.bottom:-f.height+h.bottom:h.top,s='right'==g?'HTML'===l.nodeName?-l.clientWidth+h.right:-f.width+h.right:h.left,a&&b)m[b]='translate3d('+s+'px, '+d+'px, 0)',m[c]=0,m[g]=0,m.willChange='transform';else{var w='bottom'==c?-1:1,y='right'==g?-1:1;m[c]=d*w,m[g]=s*y,m.willChange=c+', '+g}var E={"x-placement":e.placement};return e.attributes=le({},E,e.attributes),e.styles=le({},m,e.styles),e.arrowStyles=le({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:'bottom',y:'right'},applyStyle:{order:900,enabled:!0,fn:function(e){return V(e.instance.popper,e.styles),j(e.instance.popper,e.attributes),e.arrowElement&&Object.keys(e.arrowStyles).length&&V(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,o,n,i){var r=L(i,t,e,o.positionFixed),p=O(o.placement,r,t,e,o.modifiers.flip.boundariesElement,o.modifiers.flip.padding);return t.setAttribute('x-placement',p),V(t,{position:o.positionFixed?'fixed':'absolute'}),o},gpuAcceleration:void 0}}},ge}); +//# sourceMappingURL=popper.min.js.map diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist new file mode 100644 index 000000000..89810d157 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/line.html.dist @@ -0,0 +1 @@ + {{lineNumber}}{{lineContent}} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist new file mode 100644 index 000000000..add40e4e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/lines.html.dist @@ -0,0 +1,5 @@ + + +{{lines}} + +
    diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist new file mode 100644 index 000000000..2311d4564 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item.html.dist @@ -0,0 +1,12 @@ + + {{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist new file mode 100644 index 000000000..36d6cb741 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/method_item_branch.html.dist @@ -0,0 +1,18 @@ + + {{name}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + {{branches_bar}} +
    {{branches_executed_percent}}
    +
    {{branches_number}}
    + {{paths_bar}} +
    {{paths_executed_percent}}
    +
    {{paths_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist new file mode 100644 index 000000000..d14b8ad9d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Html/Renderer/Template/paths.html.dist @@ -0,0 +1,9 @@ +
    +

    Paths

    +

    + Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not + necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. + Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement + always has an else as part of its logical flow even if you didn't write one. +

    +{{paths}} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/PHP.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/PHP.php new file mode 100644 index 000000000..6f46f990f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/PHP.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 SebastianBergmann\CodeCoverage\Report; + +use function dirname; +use function file_put_contents; +use function serialize; +use function str_contains; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Util\Filesystem; + +final class PHP +{ + public function process(CodeCoverage $coverage, ?string $target = null): string + { + $coverage->clearCache(); + + $buffer = " + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use const PHP_EOL; +use function array_map; +use function date; +use function ksort; +use function max; +use function sprintf; +use function str_pad; +use function strlen; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util\Percentage; + +final class Text +{ + /** + * @var string + */ + private const COLOR_GREEN = "\x1b[30;42m"; + + /** + * @var string + */ + private const COLOR_YELLOW = "\x1b[30;43m"; + + /** + * @var string + */ + private const COLOR_RED = "\x1b[37;41m"; + + /** + * @var string + */ + private const COLOR_HEADER = "\x1b[1;37;40m"; + + /** + * @var string + */ + private const COLOR_RESET = "\x1b[0m"; + private readonly Thresholds $thresholds; + private readonly bool $showUncoveredFiles; + private readonly bool $showOnlySummary; + + public function __construct(Thresholds $thresholds, bool $showUncoveredFiles = false, bool $showOnlySummary = false) + { + $this->thresholds = $thresholds; + $this->showUncoveredFiles = $showUncoveredFiles; + $this->showOnlySummary = $showOnlySummary; + } + + public function process(CodeCoverage $coverage, bool $showColors = false): string + { + $hasBranchCoverage = !empty($coverage->getData(true)->functionCoverage()); + + $output = PHP_EOL . PHP_EOL; + $report = $coverage->getReport(); + + $colors = [ + 'header' => '', + 'classes' => '', + 'methods' => '', + 'lines' => '', + 'branches' => '', + 'paths' => '', + 'reset' => '', + ]; + + if ($showColors) { + $colors['classes'] = $this->coverageColor( + $report->numberOfTestedClassesAndTraits(), + $report->numberOfClassesAndTraits(), + ); + + $colors['methods'] = $this->coverageColor( + $report->numberOfTestedMethods(), + $report->numberOfMethods(), + ); + + $colors['lines'] = $this->coverageColor( + $report->numberOfExecutedLines(), + $report->numberOfExecutableLines(), + ); + + $colors['branches'] = $this->coverageColor( + $report->numberOfExecutedBranches(), + $report->numberOfExecutableBranches(), + ); + + $colors['paths'] = $this->coverageColor( + $report->numberOfExecutedPaths(), + $report->numberOfExecutablePaths(), + ); + + $colors['reset'] = self::COLOR_RESET; + $colors['header'] = self::COLOR_HEADER; + } + + $classes = sprintf( + ' Classes: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfTestedClassesAndTraits(), + $report->numberOfClassesAndTraits(), + )->asString(), + $report->numberOfTestedClassesAndTraits(), + $report->numberOfClassesAndTraits(), + ); + + $methods = sprintf( + ' Methods: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfTestedMethods(), + $report->numberOfMethods(), + )->asString(), + $report->numberOfTestedMethods(), + $report->numberOfMethods(), + ); + + $paths = ''; + $branches = ''; + + if ($hasBranchCoverage) { + $paths = sprintf( + ' Paths: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfExecutedPaths(), + $report->numberOfExecutablePaths(), + )->asString(), + $report->numberOfExecutedPaths(), + $report->numberOfExecutablePaths(), + ); + + $branches = sprintf( + ' Branches: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfExecutedBranches(), + $report->numberOfExecutableBranches(), + )->asString(), + $report->numberOfExecutedBranches(), + $report->numberOfExecutableBranches(), + ); + } + + $lines = sprintf( + ' Lines: %6s (%d/%d)', + Percentage::fromFractionAndTotal( + $report->numberOfExecutedLines(), + $report->numberOfExecutableLines(), + )->asString(), + $report->numberOfExecutedLines(), + $report->numberOfExecutableLines(), + ); + + $padding = max(array_map('strlen', [$classes, $methods, $lines])); + + if ($this->showOnlySummary) { + $title = 'Code Coverage Report Summary:'; + $padding = max($padding, strlen($title)); + + $output .= $this->format($colors['header'], $padding, $title); + } else { + $date = date(' Y-m-d H:i:s'); + $title = 'Code Coverage Report:'; + + $output .= $this->format($colors['header'], $padding, $title); + $output .= $this->format($colors['header'], $padding, $date); + $output .= $this->format($colors['header'], $padding, ''); + $output .= $this->format($colors['header'], $padding, ' Summary:'); + } + + $output .= $this->format($colors['classes'], $padding, $classes); + $output .= $this->format($colors['methods'], $padding, $methods); + + if ($hasBranchCoverage) { + $output .= $this->format($colors['paths'], $padding, $paths); + $output .= $this->format($colors['branches'], $padding, $branches); + } + $output .= $this->format($colors['lines'], $padding, $lines); + + if ($this->showOnlySummary) { + return $output . PHP_EOL; + } + + $classCoverage = []; + + foreach ($report as $item) { + if (!$item instanceof File) { + continue; + } + + $classes = $item->classesAndTraits(); + + foreach ($classes as $className => $class) { + $classExecutableLines = 0; + $classExecutedLines = 0; + $classExecutableBranches = 0; + $classExecutedBranches = 0; + $classExecutablePaths = 0; + $classExecutedPaths = 0; + $coveredMethods = 0; + $classMethods = 0; + + foreach ($class['methods'] as $method) { + if ($method['executableLines'] == 0) { + continue; + } + + $classMethods++; + $classExecutableLines += $method['executableLines']; + $classExecutedLines += $method['executedLines']; + $classExecutableBranches += $method['executableBranches']; + $classExecutedBranches += $method['executedBranches']; + $classExecutablePaths += $method['executablePaths']; + $classExecutedPaths += $method['executedPaths']; + + if ($method['coverage'] == 100) { + $coveredMethods++; + } + } + + $classCoverage[$className] = [ + 'namespace' => $class['namespace'], + 'className' => $className, + 'methodsCovered' => $coveredMethods, + 'methodCount' => $classMethods, + 'statementsCovered' => $classExecutedLines, + 'statementCount' => $classExecutableLines, + 'branchesCovered' => $classExecutedBranches, + 'branchesCount' => $classExecutableBranches, + 'pathsCovered' => $classExecutedPaths, + 'pathsCount' => $classExecutablePaths, + ]; + } + } + + ksort($classCoverage); + + $methodColor = ''; + $pathsColor = ''; + $branchesColor = ''; + $linesColor = ''; + $resetColor = ''; + + foreach ($classCoverage as $fullQualifiedPath => $classInfo) { + if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) { + if ($showColors) { + $methodColor = $this->coverageColor($classInfo['methodsCovered'], $classInfo['methodCount']); + $pathsColor = $this->coverageColor($classInfo['pathsCovered'], $classInfo['pathsCount']); + $branchesColor = $this->coverageColor($classInfo['branchesCovered'], $classInfo['branchesCount']); + $linesColor = $this->coverageColor($classInfo['statementsCovered'], $classInfo['statementCount']); + $resetColor = $colors['reset']; + } + + $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL + . ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '; + + if ($hasBranchCoverage) { + $output .= ' ' . $pathsColor . 'Paths: ' . $this->printCoverageCounts($classInfo['pathsCovered'], $classInfo['pathsCount'], 3) . $resetColor . ' ' + . ' ' . $branchesColor . 'Branches: ' . $this->printCoverageCounts($classInfo['branchesCovered'], $classInfo['branchesCount'], 3) . $resetColor . ' '; + } + $output .= ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor; + } + } + + return $output . PHP_EOL; + } + + private function coverageColor(int $numberOfCoveredElements, int $totalNumberOfElements): string + { + $coverage = Percentage::fromFractionAndTotal( + $numberOfCoveredElements, + $totalNumberOfElements, + ); + + if ($coverage->asFloat() >= $this->thresholds->highLowerBound()) { + return self::COLOR_GREEN; + } + + if ($coverage->asFloat() > $this->thresholds->lowUpperBound()) { + return self::COLOR_YELLOW; + } + + return self::COLOR_RED; + } + + private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision): string + { + $format = '%' . $precision . 's'; + + return Percentage::fromFractionAndTotal( + $numberOfCoveredElements, + $totalNumberOfElements, + )->asFixedWidthString() . + ' (' . sprintf($format, $numberOfCoveredElements) . '/' . + sprintf($format, $totalNumberOfElements) . ')'; + } + + private function format(string $color, int $padding, false|string $string): string + { + if ($color === '') { + return (string) $string . PHP_EOL; + } + + return $color . str_pad((string) $string, $padding) . self::COLOR_RESET . PHP_EOL; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Thresholds.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Thresholds.php new file mode 100644 index 000000000..af6c6ce5b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Thresholds.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\InvalidArgumentException; + +/** + * @psalm-immutable + */ +final class Thresholds +{ + private readonly int $lowUpperBound; + private readonly int $highLowerBound; + + public static function default(): self + { + return new self(50, 90); + } + + /** + * @throws InvalidArgumentException + */ + public static function from(int $lowUpperBound, int $highLowerBound): self + { + if ($lowUpperBound > $highLowerBound) { + throw new InvalidArgumentException( + '$lowUpperBound must not be larger than $highLowerBound', + ); + } + + return new self($lowUpperBound, $highLowerBound); + } + + private function __construct(int $lowUpperBound, int $highLowerBound) + { + $this->lowUpperBound = $lowUpperBound; + $this->highLowerBound = $highLowerBound; + } + + public function lowUpperBound(): int + { + return $this->lowUpperBound; + } + + public function highLowerBound(): int + { + return $this->highLowerBound; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php new file mode 100644 index 000000000..264bf713d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/BuildInformation.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use function phpversion; +use DateTimeImmutable; +use DOMElement; +use SebastianBergmann\Environment\Runtime; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class BuildInformation +{ + private readonly DOMElement $contextNode; + + public function __construct(DOMElement $contextNode) + { + $this->contextNode = $contextNode; + } + + public function setRuntimeInformation(Runtime $runtime): void + { + $runtimeNode = $this->nodeByName('runtime'); + + $runtimeNode->setAttribute('name', $runtime->getName()); + $runtimeNode->setAttribute('version', $runtime->getVersion()); + $runtimeNode->setAttribute('url', $runtime->getVendorUrl()); + + $driverNode = $this->nodeByName('driver'); + + if ($runtime->hasXdebug()) { + $driverNode->setAttribute('name', 'xdebug'); + $driverNode->setAttribute('version', phpversion('xdebug')); + } + + if ($runtime->hasPCOV()) { + $driverNode->setAttribute('name', 'pcov'); + $driverNode->setAttribute('version', phpversion('pcov')); + } + } + + public function setBuildTime(DateTimeImmutable $date): void + { + $this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y')); + } + + public function setGeneratorVersions(string $phpUnitVersion, string $coverageVersion): void + { + $this->contextNode->setAttribute('phpunit', $phpUnitVersion); + $this->contextNode->setAttribute('coverage', $coverageVersion); + } + + private function nodeByName(string $name): DOMElement + { + $node = $this->contextNode->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + $name, + )->item(0); + + if (!$node) { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + $name, + ), + ); + } + + return $node; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php new file mode 100644 index 000000000..bb41dfb59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Coverage.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; +use SebastianBergmann\CodeCoverage\ReportAlreadyFinalizedException; +use XMLWriter; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Coverage +{ + private readonly XMLWriter $writer; + private readonly DOMElement $contextNode; + private bool $finalized = false; + + public function __construct(DOMElement $context, string $line) + { + $this->contextNode = $context; + + $this->writer = new XMLWriter; + $this->writer->openMemory(); + $this->writer->startElementNS(null, $context->nodeName, 'https://schema.phpunit.de/coverage/1.0'); + $this->writer->writeAttribute('nr', $line); + } + + /** + * @throws ReportAlreadyFinalizedException + */ + public function addTest(string $test): void + { + if ($this->finalized) { + throw new ReportAlreadyFinalizedException; + } + + $this->writer->startElement('covered'); + $this->writer->writeAttribute('by', $test); + $this->writer->endElement(); + } + + public function finalize(): void + { + $this->writer->endElement(); + + $fragment = $this->contextNode->ownerDocument->createDocumentFragment(); + $fragment->appendXML($this->writer->outputMemory()); + + $this->contextNode->parentNode->replaceChild( + $fragment, + $this->contextNode, + ); + + $this->finalized = true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php new file mode 100644 index 000000000..b712953ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Directory.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Directory extends Node +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php new file mode 100644 index 000000000..3264718cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Facade.php @@ -0,0 +1,304 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; +use function count; +use function dirname; +use function file_get_contents; +use function file_put_contents; +use function is_array; +use function is_dir; +use function is_file; +use function is_writable; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; +use function strlen; +use function substr; +use DateTimeImmutable; +use DOMDocument; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Driver\PathExistsButIsNotDirectoryException; +use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Util\Filesystem as DirectoryUtil; +use SebastianBergmann\CodeCoverage\Version; +use SebastianBergmann\CodeCoverage\XmlException; +use SebastianBergmann\Environment\Runtime; + +final class Facade +{ + private string $target; + private Project $project; + private readonly string $phpUnitVersion; + + public function __construct(string $version) + { + $this->phpUnitVersion = $version; + } + + /** + * @throws XmlException + */ + public function process(CodeCoverage $coverage, string $target): void + { + if (substr($target, -1, 1) !== DIRECTORY_SEPARATOR) { + $target .= DIRECTORY_SEPARATOR; + } + + $this->target = $target; + $this->initTargetDirectory($target); + + $report = $coverage->getReport(); + + $this->project = new Project( + $coverage->getReport()->name(), + ); + + $this->setBuildInformation(); + $this->processTests($coverage->getTests()); + $this->processDirectory($report, $this->project); + + $this->saveDocument($this->project->asDom(), 'index'); + } + + private function setBuildInformation(): void + { + $buildNode = $this->project->buildInformation(); + $buildNode->setRuntimeInformation(new Runtime); + $buildNode->setBuildTime(new DateTimeImmutable); + $buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id()); + } + + /** + * @throws PathExistsButIsNotDirectoryException + * @throws WriteOperationFailedException + */ + private function initTargetDirectory(string $directory): void + { + if (is_file($directory)) { + if (!is_dir($directory)) { + throw new PathExistsButIsNotDirectoryException($directory); + } + + if (!is_writable($directory)) { + throw new WriteOperationFailedException($directory); + } + } + + DirectoryUtil::createDirectory($directory); + } + + /** + * @throws XmlException + */ + private function processDirectory(DirectoryNode $directory, Node $context): void + { + $directoryName = $directory->name(); + + if ($this->project->projectSourceDirectory() === $directoryName) { + $directoryName = '/'; + } + + $directoryObject = $context->addDirectory($directoryName); + + $this->setTotals($directory, $directoryObject->totals()); + + foreach ($directory->directories() as $node) { + $this->processDirectory($node, $directoryObject); + } + + foreach ($directory->files() as $node) { + $this->processFile($node, $directoryObject); + } + } + + /** + * @throws XmlException + */ + private function processFile(FileNode $file, Directory $context): void + { + $fileObject = $context->addFile( + $file->name(), + $file->id() . '.xml', + ); + + $this->setTotals($file, $fileObject->totals()); + + $path = substr( + $file->pathAsString(), + strlen($this->project->projectSourceDirectory()), + ); + + $fileReport = new Report($path); + + $this->setTotals($file, $fileReport->totals()); + + foreach ($file->classesAndTraits() as $unit) { + $this->processUnit($unit, $fileReport); + } + + foreach ($file->functions() as $function) { + $this->processFunction($function, $fileReport); + } + + foreach ($file->lineCoverageData() as $line => $tests) { + if (!is_array($tests) || count($tests) === 0) { + continue; + } + + $coverage = $fileReport->lineCoverage((string) $line); + + foreach ($tests as $test) { + $coverage->addTest($test); + } + + $coverage->finalize(); + } + + $fileReport->source()->setSourceCode( + file_get_contents($file->pathAsString()), + ); + + $this->saveDocument($fileReport->asDom(), $file->id()); + } + + private function processUnit(array $unit, Report $report): void + { + if (isset($unit['className'])) { + $unitObject = $report->classObject($unit['className']); + } else { + $unitObject = $report->traitObject($unit['traitName']); + } + + $unitObject->setLines( + $unit['startLine'], + $unit['executableLines'], + $unit['executedLines'], + ); + + $unitObject->setCrap((float) $unit['crap']); + $unitObject->setNamespace($unit['namespace']); + + foreach ($unit['methods'] as $method) { + $methodObject = $unitObject->addMethod($method['methodName']); + $methodObject->setSignature($method['signature']); + $methodObject->setLines((string) $method['startLine'], (string) $method['endLine']); + $methodObject->setCrap($method['crap']); + $methodObject->setTotals( + (string) $method['executableLines'], + (string) $method['executedLines'], + (string) $method['coverage'], + ); + } + } + + private function processFunction(array $function, Report $report): void + { + $functionObject = $report->functionObject($function['functionName']); + + $functionObject->setSignature($function['signature']); + $functionObject->setLines((string) $function['startLine']); + $functionObject->setCrap($function['crap']); + $functionObject->setTotals((string) $function['executableLines'], (string) $function['executedLines'], (string) $function['coverage']); + } + + private function processTests(array $tests): void + { + $testsObject = $this->project->tests(); + + foreach ($tests as $test => $result) { + $testsObject->addTest($test, $result); + } + } + + private function setTotals(AbstractNode $node, Totals $totals): void + { + $loc = $node->linesOfCode(); + + $totals->setNumLines( + $loc['linesOfCode'], + $loc['commentLinesOfCode'], + $loc['nonCommentLinesOfCode'], + $node->numberOfExecutableLines(), + $node->numberOfExecutedLines(), + ); + + $totals->setNumClasses( + $node->numberOfClasses(), + $node->numberOfTestedClasses(), + ); + + $totals->setNumTraits( + $node->numberOfTraits(), + $node->numberOfTestedTraits(), + ); + + $totals->setNumMethods( + $node->numberOfMethods(), + $node->numberOfTestedMethods(), + ); + + $totals->setNumFunctions( + $node->numberOfFunctions(), + $node->numberOfTestedFunctions(), + ); + } + + private function targetDirectory(): string + { + return $this->target; + } + + /** + * @throws XmlException + */ + private function saveDocument(DOMDocument $document, string $name): void + { + $filename = sprintf('%s/%s.xml', $this->targetDirectory(), $name); + + $document->formatOutput = true; + $document->preserveWhiteSpace = false; + $this->initTargetDirectory(dirname($filename)); + + file_put_contents($filename, $this->documentAsString($document)); + } + + /** + * @throws XmlException + * + * @see https://bugs.php.net/bug.php?id=79191 + */ + private function documentAsString(DOMDocument $document): string + { + $xmlErrorHandling = libxml_use_internal_errors(true); + $xml = $document->saveXML(); + + if ($xml === false) { + $message = 'Unable to generate the XML'; + + foreach (libxml_get_errors() as $error) { + $message .= PHP_EOL . $error->message; + } + + throw new XmlException($message); + } + + libxml_clear_errors(); + libxml_use_internal_errors($xmlErrorHandling); + + return $xml; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php new file mode 100644 index 000000000..69b275106 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/File.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +class File +{ + private readonly DOMDocument $dom; + private readonly DOMElement $contextNode; + + public function __construct(DOMElement $context) + { + $this->dom = $context->ownerDocument; + $this->contextNode = $context; + } + + public function totals(): Totals + { + $totalsContainer = $this->contextNode->firstChild; + + if (!$totalsContainer) { + $totalsContainer = $this->contextNode->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'totals', + ), + ); + } + + return new Totals($totalsContainer); + } + + public function lineCoverage(string $line): Coverage + { + $coverage = $this->contextNode->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'coverage', + )->item(0); + + if (!$coverage) { + $coverage = $this->contextNode->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'coverage', + ), + ); + } + + $lineNode = $coverage->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'line', + ), + ); + + return new Coverage($lineNode, $line); + } + + protected function contextNode(): DOMElement + { + return $this->contextNode; + } + + protected function dom(): DOMDocument + { + return $this->dom; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php new file mode 100644 index 000000000..b1ab9ae53 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Method.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Method +{ + private readonly DOMElement $contextNode; + + public function __construct(DOMElement $context, string $name) + { + $this->contextNode = $context; + + $this->setName($name); + } + + public function setSignature(string $signature): void + { + $this->contextNode->setAttribute('signature', $signature); + } + + public function setLines(string $start, ?string $end = null): void + { + $this->contextNode->setAttribute('start', $start); + + if ($end !== null) { + $this->contextNode->setAttribute('end', $end); + } + } + + public function setTotals(string $executable, string $executed, string $coverage): void + { + $this->contextNode->setAttribute('executable', $executable); + $this->contextNode->setAttribute('executed', $executed); + $this->contextNode->setAttribute('coverage', $coverage); + } + + public function setCrap(string $crap): void + { + $this->contextNode->setAttribute('crap', $crap); + } + + private function setName(string $name): void + { + $this->contextNode->setAttribute('name', $name); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php new file mode 100644 index 000000000..b2ba54b23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Node.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMDocument; +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +abstract class Node +{ + private DOMDocument $dom; + private DOMElement $contextNode; + + public function __construct(DOMElement $context) + { + $this->setContextNode($context); + } + + public function dom(): DOMDocument + { + return $this->dom; + } + + public function totals(): Totals + { + $totalsContainer = $this->contextNode()->firstChild; + + if (!$totalsContainer) { + $totalsContainer = $this->contextNode()->appendChild( + $this->dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'totals', + ), + ); + } + + return new Totals($totalsContainer); + } + + public function addDirectory(string $name): Directory + { + $dirNode = $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'directory', + ); + + $dirNode->setAttribute('name', $name); + $this->contextNode()->appendChild($dirNode); + + return new Directory($dirNode); + } + + public function addFile(string $name, string $href): File + { + $fileNode = $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'file', + ); + + $fileNode->setAttribute('name', $name); + $fileNode->setAttribute('href', $href); + $this->contextNode()->appendChild($fileNode); + + return new File($fileNode); + } + + protected function setContextNode(DOMElement $context): void + { + $this->dom = $context->ownerDocument; + $this->contextNode = $context; + } + + protected function contextNode(): DOMElement + { + return $this->contextNode; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php new file mode 100644 index 000000000..b450beb4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Project.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Project extends Node +{ + public function __construct(string $directory) + { + $this->init(); + $this->setProjectSourceDirectory($directory); + } + + public function projectSourceDirectory(): string + { + return $this->contextNode()->getAttribute('source'); + } + + public function buildInformation(): BuildInformation + { + $buildNode = $this->dom()->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'build', + )->item(0); + + if (!$buildNode) { + $buildNode = $this->dom()->documentElement->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'build', + ), + ); + } + + return new BuildInformation($buildNode); + } + + public function tests(): Tests + { + $testsNode = $this->contextNode()->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'tests', + )->item(0); + + if (!$testsNode) { + $testsNode = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'tests', + ), + ); + } + + return new Tests($testsNode); + } + + public function asDom(): DOMDocument + { + return $this->dom(); + } + + private function init(): void + { + $dom = new DOMDocument; + $dom->loadXML(''); + + $this->setContextNode( + $dom->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'project', + )->item(0), + ); + } + + private function setProjectSourceDirectory(string $name): void + { + $this->contextNode()->setAttribute('source', $name); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php new file mode 100644 index 000000000..09d103416 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Report.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use function basename; +use function dirname; +use DOMDocument; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Report extends File +{ + public function __construct(string $name) + { + $dom = new DOMDocument; + $dom->loadXML(''); + + $contextNode = $dom->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'file', + )->item(0); + + parent::__construct($contextNode); + + $this->setName($name); + } + + public function asDom(): DOMDocument + { + return $this->dom(); + } + + public function functionObject($name): Method + { + $node = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'function', + ), + ); + + return new Method($node, $name); + } + + public function classObject($name): Unit + { + return $this->unitObject('class', $name); + } + + public function traitObject($name): Unit + { + return $this->unitObject('trait', $name); + } + + public function source(): Source + { + $source = $this->contextNode()->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'source', + )->item(0); + + if (!$source) { + $source = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'source', + ), + ); + } + + return new Source($source); + } + + private function setName(string $name): void + { + $this->contextNode()->setAttribute('name', basename($name)); + $this->contextNode()->setAttribute('path', dirname($name)); + } + + private function unitObject(string $tagName, $name): Unit + { + $node = $this->contextNode()->appendChild( + $this->dom()->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + $tagName, + ), + ); + + return new Unit($node, $name); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.php new file mode 100644 index 000000000..cd1fb90c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Source.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 SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; +use TheSeer\Tokenizer\NamespaceUri; +use TheSeer\Tokenizer\Tokenizer; +use TheSeer\Tokenizer\XMLSerializer; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Source +{ + private readonly DOMElement $context; + + public function __construct(DOMElement $context) + { + $this->context = $context; + } + + public function setSourceCode(string $source): void + { + $context = $this->context; + + $tokens = (new Tokenizer)->parse($source); + $srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens); + + $context->parentNode->replaceChild( + $context->ownerDocument->importNode($srcDom->documentElement, true), + $context, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.php new file mode 100644 index 000000000..44d6010b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Tests.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 SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type TestType from \SebastianBergmann\CodeCoverage\CodeCoverage + */ +final class Tests +{ + private readonly DOMElement $contextNode; + + public function __construct(DOMElement $context) + { + $this->contextNode = $context; + } + + /** + * @param TestType $result + */ + public function addTest(string $test, array $result): void + { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'test', + ), + ); + + $node->setAttribute('name', $test); + $node->setAttribute('size', $result['size']); + $node->setAttribute('status', $result['status']); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php new file mode 100644 index 000000000..239f6d43d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Totals.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use function sprintf; +use DOMElement; +use DOMNode; +use SebastianBergmann\CodeCoverage\Util\Percentage; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Totals +{ + private readonly DOMNode $container; + private readonly DOMElement $linesNode; + private readonly DOMElement $methodsNode; + private readonly DOMElement $functionsNode; + private readonly DOMElement $classesNode; + private readonly DOMElement $traitsNode; + + public function __construct(DOMElement $container) + { + $this->container = $container; + $dom = $container->ownerDocument; + + $this->linesNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'lines', + ); + + $this->methodsNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'methods', + ); + + $this->functionsNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'functions', + ); + + $this->classesNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'classes', + ); + + $this->traitsNode = $dom->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'traits', + ); + + $container->appendChild($this->linesNode); + $container->appendChild($this->methodsNode); + $container->appendChild($this->functionsNode); + $container->appendChild($this->classesNode); + $container->appendChild($this->traitsNode); + } + + public function container(): DOMNode + { + return $this->container; + } + + public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed): void + { + $this->linesNode->setAttribute('total', (string) $loc); + $this->linesNode->setAttribute('comments', (string) $cloc); + $this->linesNode->setAttribute('code', (string) $ncloc); + $this->linesNode->setAttribute('executable', (string) $executable); + $this->linesNode->setAttribute('executed', (string) $executed); + $this->linesNode->setAttribute( + 'percent', + $executable === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($executed, $executable)->asFloat()), + ); + } + + public function setNumClasses(int $count, int $tested): void + { + $this->classesNode->setAttribute('count', (string) $count); + $this->classesNode->setAttribute('tested', (string) $tested); + $this->classesNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), + ); + } + + public function setNumTraits(int $count, int $tested): void + { + $this->traitsNode->setAttribute('count', (string) $count); + $this->traitsNode->setAttribute('tested', (string) $tested); + $this->traitsNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), + ); + } + + public function setNumMethods(int $count, int $tested): void + { + $this->methodsNode->setAttribute('count', (string) $count); + $this->methodsNode->setAttribute('tested', (string) $tested); + $this->methodsNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), + ); + } + + public function setNumFunctions(int $count, int $tested): void + { + $this->functionsNode->setAttribute('count', (string) $count); + $this->functionsNode->setAttribute('tested', (string) $tested); + $this->functionsNode->setAttribute( + 'percent', + $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.php new file mode 100644 index 000000000..ea1a47f24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Report/Xml/Unit.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 SebastianBergmann\CodeCoverage\Report\Xml; + +use DOMElement; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Unit +{ + private readonly DOMElement $contextNode; + + public function __construct(DOMElement $context, string $name) + { + $this->contextNode = $context; + + $this->setName($name); + } + + public function setLines(int $start, int $executable, int $executed): void + { + $this->contextNode->setAttribute('start', (string) $start); + $this->contextNode->setAttribute('executable', (string) $executable); + $this->contextNode->setAttribute('executed', (string) $executed); + } + + public function setCrap(float $crap): void + { + $this->contextNode->setAttribute('crap', (string) $crap); + } + + public function setNamespace(string $namespace): void + { + $node = $this->contextNode->getElementsByTagNameNS( + 'https://schema.phpunit.de/coverage/1.0', + 'namespace', + )->item(0); + + if (!$node) { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'namespace', + ), + ); + } + + $node->setAttribute('name', $namespace); + } + + public function addMethod(string $name): Method + { + $node = $this->contextNode->appendChild( + $this->contextNode->ownerDocument->createElementNS( + 'https://schema.phpunit.de/coverage/1.0', + 'method', + ), + ); + + return new Method($node, $name); + } + + private function setName(string $name): void + { + $this->contextNode->setAttribute('name', $name); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php new file mode 100644 index 000000000..47cc756c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CacheWarmer.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use SebastianBergmann\CodeCoverage\Filter; + +final class CacheWarmer +{ + public function warmCache(string $cacheDirectory, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode, Filter $filter): void + { + $analyser = new CachingFileAnalyser( + $cacheDirectory, + new ParsingFileAnalyser( + $useAnnotationsForIgnoringCode, + $ignoreDeprecatedCode, + ), + $useAnnotationsForIgnoringCode, + $ignoreDeprecatedCode, + ); + + foreach ($filter->files() as $file) { + $analyser->process($file); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php new file mode 100644 index 000000000..2ce4d604c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CachingFileAnalyser.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function file_get_contents; +use function file_put_contents; +use function implode; +use function is_file; +use function md5; +use function serialize; +use function unserialize; +use SebastianBergmann\CodeCoverage\Util\Filesystem; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + */ +final class CachingFileAnalyser implements FileAnalyser +{ + private static ?string $cacheVersion = null; + private readonly string $directory; + private readonly FileAnalyser $analyser; + private readonly bool $useAnnotationsForIgnoringCode; + private readonly bool $ignoreDeprecatedCode; + private array $cache = []; + + public function __construct(string $directory, FileAnalyser $analyser, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode) + { + Filesystem::createDirectory($directory); + + $this->analyser = $analyser; + $this->directory = $directory; + $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; + $this->ignoreDeprecatedCode = $ignoreDeprecatedCode; + } + + public function classesIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['classesIn']; + } + + public function traitsIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['traitsIn']; + } + + public function functionsIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['functionsIn']; + } + + /** + * @psalm-return LinesOfCodeType + */ + public function linesOfCodeFor(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['linesOfCodeFor']; + } + + public function executableLinesIn(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['executableLinesIn']; + } + + public function ignoredLinesFor(string $filename): array + { + if (!isset($this->cache[$filename])) { + $this->process($filename); + } + + return $this->cache[$filename]['ignoredLinesFor']; + } + + public function process(string $filename): void + { + $cache = $this->read($filename); + + if ($cache !== false) { + $this->cache[$filename] = $cache; + + return; + } + + $this->cache[$filename] = [ + 'classesIn' => $this->analyser->classesIn($filename), + 'traitsIn' => $this->analyser->traitsIn($filename), + 'functionsIn' => $this->analyser->functionsIn($filename), + 'linesOfCodeFor' => $this->analyser->linesOfCodeFor($filename), + 'ignoredLinesFor' => $this->analyser->ignoredLinesFor($filename), + 'executableLinesIn' => $this->analyser->executableLinesIn($filename), + ]; + + $this->write($filename, $this->cache[$filename]); + } + + private function read(string $filename): array|false + { + $cacheFile = $this->cacheFile($filename); + + if (!is_file($cacheFile)) { + return false; + } + + return unserialize( + file_get_contents($cacheFile), + ['allowed_classes' => false], + ); + } + + private function write(string $filename, array $data): void + { + file_put_contents( + $this->cacheFile($filename), + serialize($data), + ); + } + + private function cacheFile(string $filename): string + { + $cacheKey = md5( + implode( + "\0", + [ + $filename, + file_get_contents($filename), + self::cacheVersion(), + $this->useAnnotationsForIgnoringCode, + $this->ignoreDeprecatedCode, + ], + ), + ); + + return $this->directory . DIRECTORY_SEPARATOR . $cacheKey; + } + + private static function cacheVersion(): string + { + if (self::$cacheVersion !== null) { + return self::$cacheVersion; + } + + $buffer = []; + + foreach ((new FileIteratorFacade)->getFilesAsArray(__DIR__, '.php') as $file) { + $buffer[] = $file; + $buffer[] = file_get_contents($file); + } + + self::$cacheVersion = md5(implode("\0", $buffer)); + + return self::$cacheVersion; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php new file mode 100644 index 000000000..5530221dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/CodeUnitFindingVisitor.php @@ -0,0 +1,360 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function assert; +use function implode; +use function rtrim; +use function trim; +use PhpParser\Node; +use PhpParser\Node\ComplexType; +use PhpParser\Node\Identifier; +use PhpParser\Node\IntersectionType; +use PhpParser\Node\Name; +use PhpParser\Node\NullableType; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Enum_; +use PhpParser\Node\Stmt\Function_; +use PhpParser\Node\Stmt\Interface_; +use PhpParser\Node\Stmt\Trait_; +use PhpParser\Node\UnionType; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitorAbstract; +use SebastianBergmann\Complexity\CyclomaticComplexityCalculatingVisitor; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-type CodeUnitFunctionType = array{ + * name: string, + * namespacedName: string, + * namespace: string, + * signature: string, + * startLine: int, + * endLine: int, + * ccn: int + * } + * @psalm-type CodeUnitMethodType = array{ + * methodName: string, + * signature: string, + * visibility: string, + * startLine: int, + * endLine: int, + * ccn: int + * } + * @psalm-type CodeUnitClassType = array{ + * name: string, + * namespacedName: string, + * namespace: string, + * startLine: int, + * endLine: int, + * methods: array + * } + * @psalm-type CodeUnitTraitType = array{ + * name: string, + * namespacedName: string, + * namespace: string, + * startLine: int, + * endLine: int, + * methods: array + * } + */ +final class CodeUnitFindingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var array + */ + private array $classes = []; + + /** + * @psalm-var array + */ + private array $traits = []; + + /** + * @psalm-var array + */ + private array $functions = []; + + public function enterNode(Node $node): void + { + if ($node instanceof Class_) { + if ($node->isAnonymous()) { + return; + } + + $this->processClass($node); + } + + if ($node instanceof Trait_) { + $this->processTrait($node); + } + + if (!$node instanceof ClassMethod && !$node instanceof Function_) { + return; + } + + if ($node instanceof ClassMethod) { + $parentNode = $node->getAttribute('parent'); + + if ($parentNode instanceof Class_ && $parentNode->isAnonymous()) { + return; + } + + $this->processMethod($node); + + return; + } + + $this->processFunction($node); + } + + /** + * @psalm-return array + */ + public function classes(): array + { + return $this->classes; + } + + /** + * @psalm-return array + */ + public function traits(): array + { + return $this->traits; + } + + /** + * @psalm-return array + */ + public function functions(): array + { + return $this->functions; + } + + private function cyclomaticComplexity(ClassMethod|Function_ $node): int + { + $nodes = $node->getStmts(); + + if ($nodes === null) { + return 0; + } + + $traverser = new NodeTraverser; + + $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor; + + $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor); + + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + + return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity(); + } + + private function signature(ClassMethod|Function_ $node): string + { + $signature = ($node->returnsByRef() ? '&' : '') . $node->name->toString() . '('; + $parameters = []; + + foreach ($node->getParams() as $parameter) { + assert(isset($parameter->var->name)); + + $parameterAsString = ''; + + if ($parameter->type !== null) { + $parameterAsString = $this->type($parameter->type) . ' '; + } + + $parameterAsString .= '$' . $parameter->var->name; + + /* @todo Handle default values */ + + $parameters[] = $parameterAsString; + } + + $signature .= implode(', ', $parameters) . ')'; + + $returnType = $node->getReturnType(); + + if ($returnType !== null) { + $signature .= ': ' . $this->type($returnType); + } + + return $signature; + } + + private function type(ComplexType|Identifier|Name $type): string + { + if ($type instanceof NullableType) { + return '?' . $type->type; + } + + if ($type instanceof UnionType) { + return $this->unionTypeAsString($type); + } + + if ($type instanceof IntersectionType) { + return $this->intersectionTypeAsString($type); + } + + return $type->toString(); + } + + private function visibility(ClassMethod $node): string + { + if ($node->isPrivate()) { + return 'private'; + } + + if ($node->isProtected()) { + return 'protected'; + } + + return 'public'; + } + + private function processClass(Class_ $node): void + { + $name = $node->name->toString(); + $namespacedName = $node->namespacedName->toString(); + + $this->classes[$namespacedName] = [ + 'name' => $name, + 'namespacedName' => $namespacedName, + 'namespace' => $this->namespace($namespacedName, $name), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'methods' => [], + ]; + } + + private function processTrait(Trait_ $node): void + { + $name = $node->name->toString(); + $namespacedName = $node->namespacedName->toString(); + + $this->traits[$namespacedName] = [ + 'name' => $name, + 'namespacedName' => $namespacedName, + 'namespace' => $this->namespace($namespacedName, $name), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'methods' => [], + ]; + } + + private function processMethod(ClassMethod $node): void + { + $parentNode = $node->getAttribute('parent'); + + if ($parentNode instanceof Interface_) { + return; + } + + assert($parentNode instanceof Class_ || $parentNode instanceof Trait_ || $parentNode instanceof Enum_); + assert(isset($parentNode->name)); + assert(isset($parentNode->namespacedName)); + assert($parentNode->namespacedName instanceof Name); + + $parentName = $parentNode->name->toString(); + $parentNamespacedName = $parentNode->namespacedName->toString(); + + if ($parentNode instanceof Class_) { + $storage = &$this->classes; + } else { + $storage = &$this->traits; + } + + if (!isset($storage[$parentNamespacedName])) { + $storage[$parentNamespacedName] = [ + 'name' => $parentName, + 'namespacedName' => $parentNamespacedName, + 'namespace' => $this->namespace($parentNamespacedName, $parentName), + 'startLine' => $parentNode->getStartLine(), + 'endLine' => $parentNode->getEndLine(), + 'methods' => [], + ]; + } + + $storage[$parentNamespacedName]['methods'][$node->name->toString()] = [ + 'methodName' => $node->name->toString(), + 'signature' => $this->signature($node), + 'visibility' => $this->visibility($node), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'ccn' => $this->cyclomaticComplexity($node), + ]; + } + + private function processFunction(Function_ $node): void + { + assert(isset($node->name)); + assert(isset($node->namespacedName)); + assert($node->namespacedName instanceof Name); + + $name = $node->name->toString(); + $namespacedName = $node->namespacedName->toString(); + + $this->functions[$namespacedName] = [ + 'name' => $name, + 'namespacedName' => $namespacedName, + 'namespace' => $this->namespace($namespacedName, $name), + 'signature' => $this->signature($node), + 'startLine' => $node->getStartLine(), + 'endLine' => $node->getEndLine(), + 'ccn' => $this->cyclomaticComplexity($node), + ]; + } + + private function namespace(string $namespacedName, string $name): string + { + return trim(rtrim($namespacedName, $name), '\\'); + } + + private function unionTypeAsString(UnionType $node): string + { + $types = []; + + foreach ($node->types as $type) { + if ($type instanceof IntersectionType) { + $types[] = '(' . $this->intersectionTypeAsString($type) . ')'; + + continue; + } + + $types[] = $this->typeAsString($type); + } + + return implode('|', $types); + } + + private function intersectionTypeAsString(IntersectionType $node): string + { + $types = []; + + foreach ($node->types as $type) { + $types[] = $this->typeAsString($type); + } + + return implode('&', $types); + } + + private function typeAsString(Identifier|Name $node): string + { + if ($node instanceof Name) { + return $node->toCodeString(); + } + + return $node->toString(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php new file mode 100644 index 000000000..a15894da3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ExecutableLinesFindingVisitor.php @@ -0,0 +1,413 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function array_diff_key; +use function assert; +use function count; +use function current; +use function end; +use function explode; +use function max; +use function preg_match; +use function preg_quote; +use function range; +use function reset; +use function sprintf; +use PhpParser\Node; +use PhpParser\NodeVisitorAbstract; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type LinesType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + */ +final class ExecutableLinesFindingVisitor extends NodeVisitorAbstract +{ + private int $nextBranch = 0; + private readonly string $source; + + /** + * @psalm-var LinesType + */ + private array $executableLinesGroupedByBranch = []; + + /** + * @psalm-var array + */ + private array $unsets = []; + + /** + * @psalm-var array + */ + private array $commentsToCheckForUnset = []; + + public function __construct(string $source) + { + $this->source = $source; + } + + public function enterNode(Node $node): void + { + foreach ($node->getComments() as $comment) { + $commentLine = $comment->getStartLine(); + + if (!isset($this->executableLinesGroupedByBranch[$commentLine])) { + continue; + } + + foreach (explode("\n", $comment->getText()) as $text) { + $this->commentsToCheckForUnset[$commentLine] = $text; + $commentLine++; + } + } + + if ($node instanceof Node\Scalar\String_ || + $node instanceof Node\Scalar\EncapsedStringPart) { + $startLine = $node->getStartLine() + 1; + $endLine = $node->getEndLine() - 1; + + if ($startLine <= $endLine) { + foreach (range($startLine, $endLine) as $line) { + unset($this->executableLinesGroupedByBranch[$line]); + } + } + + return; + } + + if ($node instanceof Node\Stmt\Interface_) { + foreach (range($node->getStartLine(), $node->getEndLine()) as $line) { + $this->unsets[$line] = true; + } + + return; + } + + if ($node instanceof Node\Stmt\Declare_ || + $node instanceof Node\Stmt\DeclareDeclare || + $node instanceof Node\Stmt\Else_ || + $node instanceof Node\Stmt\EnumCase || + $node instanceof Node\Stmt\Finally_ || + $node instanceof Node\Stmt\GroupUse || + $node instanceof Node\Stmt\Label || + $node instanceof Node\Stmt\Namespace_ || + $node instanceof Node\Stmt\Nop || + $node instanceof Node\Stmt\Switch_ || + $node instanceof Node\Stmt\TryCatch || + $node instanceof Node\Stmt\Use_ || + $node instanceof Node\Stmt\UseUse || + $node instanceof Node\Expr\ConstFetch || + $node instanceof Node\Expr\Variable || + $node instanceof Node\Expr\Throw_ || + $node instanceof Node\ComplexType || + $node instanceof Node\Const_ || + $node instanceof Node\Identifier || + $node instanceof Node\Name || + $node instanceof Node\Param || + $node instanceof Node\Scalar) { + return; + } + + if ($node instanceof Node\Expr\Match_) { + foreach ($node->arms as $arm) { + $this->setLineBranch( + $arm->body->getStartLine(), + $arm->body->getEndLine(), + ++$this->nextBranch, + ); + } + + return; + } + + /* + * nikic/php-parser ^4.18 represents throw statements + * as Stmt\Throw_ objects + */ + if ($node instanceof Node\Stmt\Throw_) { + $this->setLineBranch($node->expr->getEndLine(), $node->expr->getEndLine(), ++$this->nextBranch); + + return; + } + + /* + * nikic/php-parser ^5 represents throw statements + * as Stmt\Expression objects that contain an + * Expr\Throw_ object + */ + if ($node instanceof Node\Stmt\Expression && $node->expr instanceof Node\Expr\Throw_) { + $this->setLineBranch($node->expr->expr->getEndLine(), $node->expr->expr->getEndLine(), ++$this->nextBranch); + + return; + } + + if ($node instanceof Node\Stmt\Enum_ || + $node instanceof Node\Stmt\Function_ || + $node instanceof Node\Stmt\Class_ || + $node instanceof Node\Stmt\ClassMethod || + $node instanceof Node\Expr\Closure || + $node instanceof Node\Stmt\Trait_) { + if ($node instanceof Node\Stmt\Function_ || $node instanceof Node\Stmt\ClassMethod) { + $unsets = []; + + foreach ($node->getParams() as $param) { + foreach (range($param->getStartLine(), $param->getEndLine()) as $line) { + $unsets[$line] = true; + } + } + + unset($unsets[$node->getEndLine()]); + + $this->unsets += $unsets; + } + + $isConcreteClassLike = $node instanceof Node\Stmt\Enum_ || $node instanceof Node\Stmt\Class_ || $node instanceof Node\Stmt\Trait_; + + if (null !== $node->stmts) { + foreach ($node->stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Nop) { + continue; + } + + foreach (range($stmt->getStartLine(), $stmt->getEndLine()) as $line) { + unset($this->executableLinesGroupedByBranch[$line]); + + if ( + $isConcreteClassLike && + !$stmt instanceof Node\Stmt\ClassMethod + ) { + $this->unsets[$line] = true; + } + } + } + } + + if ($isConcreteClassLike) { + return; + } + + $hasEmptyBody = [] === $node->stmts || + null === $node->stmts || + ( + 1 === count($node->stmts) && + $node->stmts[0] instanceof Node\Stmt\Nop + ); + + if ($hasEmptyBody) { + if ($node->getEndLine() === $node->getStartLine() && isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + return; + } + + $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); + + return; + } + + return; + } + + if ($node instanceof Node\Expr\ArrowFunction) { + $startLine = max( + $node->getStartLine() + 1, + $node->expr->getStartLine(), + ); + + $endLine = $node->expr->getEndLine(); + + if ($endLine < $startLine) { + return; + } + + $this->setLineBranch($startLine, $endLine, ++$this->nextBranch); + + return; + } + + if ($node instanceof Node\Expr\Ternary) { + if (null !== $node->if && + $node->getStartLine() !== $node->if->getEndLine()) { + $this->setLineBranch($node->if->getStartLine(), $node->if->getEndLine(), ++$this->nextBranch); + } + + if ($node->getStartLine() !== $node->else->getEndLine()) { + $this->setLineBranch($node->else->getStartLine(), $node->else->getEndLine(), ++$this->nextBranch); + } + + return; + } + + if ($node instanceof Node\Expr\BinaryOp\Coalesce) { + if ($node->getStartLine() !== $node->getEndLine()) { + $this->setLineBranch($node->getEndLine(), $node->getEndLine(), ++$this->nextBranch); + } + + return; + } + + if ($node instanceof Node\Stmt\If_ || + $node instanceof Node\Stmt\ElseIf_ || + $node instanceof Node\Stmt\Case_) { + if (null === $node->cond) { + return; + } + + $this->setLineBranch( + $node->cond->getStartLine(), + $node->cond->getStartLine(), + ++$this->nextBranch, + ); + + return; + } + + if ($node instanceof Node\Stmt\For_) { + $startLine = null; + $endLine = null; + + if ([] !== $node->init) { + $startLine = $node->init[0]->getStartLine(); + + end($node->init); + + $endLine = current($node->init)->getEndLine(); + + reset($node->init); + } + + if ([] !== $node->cond) { + if (null === $startLine) { + $startLine = $node->cond[0]->getStartLine(); + } + + end($node->cond); + + $endLine = current($node->cond)->getEndLine(); + + reset($node->cond); + } + + if ([] !== $node->loop) { + if (null === $startLine) { + $startLine = $node->loop[0]->getStartLine(); + } + + end($node->loop); + + $endLine = current($node->loop)->getEndLine(); + + reset($node->loop); + } + + if (null === $startLine || null === $endLine) { + return; + } + + $this->setLineBranch( + $startLine, + $endLine, + ++$this->nextBranch, + ); + + return; + } + + if ($node instanceof Node\Stmt\Foreach_) { + $this->setLineBranch( + $node->expr->getStartLine(), + $node->valueVar->getEndLine(), + ++$this->nextBranch, + ); + + return; + } + + if ($node instanceof Node\Stmt\While_ || + $node instanceof Node\Stmt\Do_) { + $this->setLineBranch( + $node->cond->getStartLine(), + $node->cond->getEndLine(), + ++$this->nextBranch, + ); + + return; + } + + if ($node instanceof Node\Stmt\Catch_) { + assert([] !== $node->types); + $startLine = $node->types[0]->getStartLine(); + end($node->types); + $endLine = current($node->types)->getEndLine(); + + $this->setLineBranch( + $startLine, + $endLine, + ++$this->nextBranch, + ); + + return; + } + + if ($node instanceof Node\Expr\CallLike) { + if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + $branch = $this->executableLinesGroupedByBranch[$node->getStartLine()]; + } else { + $branch = ++$this->nextBranch; + } + + $this->setLineBranch($node->getStartLine(), $node->getEndLine(), $branch); + + return; + } + + if (isset($this->executableLinesGroupedByBranch[$node->getStartLine()])) { + return; + } + + $this->setLineBranch($node->getStartLine(), $node->getEndLine(), ++$this->nextBranch); + } + + public function afterTraverse(array $nodes): void + { + $lines = explode("\n", $this->source); + + foreach ($lines as $lineNumber => $line) { + $lineNumber++; + + if (1 === preg_match('/^\s*$/', $line) || + ( + isset($this->commentsToCheckForUnset[$lineNumber]) && + 1 === preg_match(sprintf('/^\s*%s\s*$/', preg_quote($this->commentsToCheckForUnset[$lineNumber], '/')), $line) + )) { + unset($this->executableLinesGroupedByBranch[$lineNumber]); + } + } + + $this->executableLinesGroupedByBranch = array_diff_key( + $this->executableLinesGroupedByBranch, + $this->unsets, + ); + } + + /** + * @psalm-return LinesType + */ + public function executableLinesGroupedByBranch(): array + { + return $this->executableLinesGroupedByBranch; + } + + private function setLineBranch(int $start, int $end, int $branch): void + { + foreach (range($start, $end) as $line) { + $this->executableLinesGroupedByBranch[$line] = $branch; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.php new file mode 100644 index 000000000..f260341b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/FileAnalyser.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 SebastianBergmann\CodeCoverage\StaticAnalysis; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type CodeUnitFunctionType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitMethodType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitClassType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitTraitType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + * @psalm-import-type LinesType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + * + * @psalm-type LinesOfCodeType = array{ + * linesOfCode: int, + * commentLinesOfCode: int, + * nonCommentLinesOfCode: int + * } + * @psalm-type LinesType = array + */ +interface FileAnalyser +{ + /** + * @psalm-return array + */ + public function classesIn(string $filename): array; + + /** + * @psalm-return array + */ + public function traitsIn(string $filename): array; + + /** + * @psalm-return array + */ + public function functionsIn(string $filename): array; + + /** + * @psalm-return LinesOfCodeType + */ + public function linesOfCodeFor(string $filename): array; + + /** + * @psalm-return LinesType + */ + public function executableLinesIn(string $filename): array; + + /** + * @psalm-return LinesType + */ + public function ignoredLinesFor(string $filename): array; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php new file mode 100644 index 000000000..a3be120b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/IgnoredLinesFindingVisitor.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function assert; +use function str_contains; +use PhpParser\Node; +use PhpParser\Node\Attribute; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Enum_; +use PhpParser\Node\Stmt\Function_; +use PhpParser\Node\Stmt\Interface_; +use PhpParser\Node\Stmt\Trait_; +use PhpParser\NodeVisitorAbstract; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class IgnoredLinesFindingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var array + */ + private array $ignoredLines = []; + private readonly bool $useAnnotationsForIgnoringCode; + private readonly bool $ignoreDeprecated; + + public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecated) + { + $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; + $this->ignoreDeprecated = $ignoreDeprecated; + } + + public function enterNode(Node $node): void + { + if (!$node instanceof Class_ && + !$node instanceof Trait_ && + !$node instanceof Interface_ && + !$node instanceof Enum_ && + !$node instanceof ClassMethod && + !$node instanceof Function_ && + !$node instanceof Attribute) { + return; + } + + if ($node instanceof Class_ && $node->isAnonymous()) { + return; + } + + if ($node instanceof Class_ || + $node instanceof Trait_ || + $node instanceof Interface_ || + $node instanceof Attribute) { + $this->ignoredLines[] = $node->getStartLine(); + + assert($node->name !== null); + + // Workaround for https://github.com/nikic/PHP-Parser/issues/886 + $this->ignoredLines[] = $node->name->getStartLine(); + } + + if (!$this->useAnnotationsForIgnoringCode) { + return; + } + + if ($node instanceof Interface_) { + return; + } + + if ($node instanceof Attribute && + $node->name->toString() === 'PHPUnit\Framework\Attributes\CodeCoverageIgnore') { + $attributeGroup = $node->getAttribute('parent'); + $attributedNode = $attributeGroup->getAttribute('parent'); + + for ($line = $attributedNode->getStartLine(); $line <= $attributedNode->getEndLine(); $line++) { + $this->ignoredLines[] = $line; + } + + return; + } + + $this->processDocComment($node); + } + + /** + * @psalm-return array + */ + public function ignoredLines(): array + { + return $this->ignoredLines; + } + + private function processDocComment(Node $node): void + { + $docComment = $node->getDocComment(); + + if ($docComment === null) { + return; + } + + if (str_contains($docComment->getText(), '@codeCoverageIgnore')) { + for ($line = $node->getStartLine(); $line <= $node->getEndLine(); $line++) { + $this->ignoredLines[] = $line; + } + } + + if ($this->ignoreDeprecated && str_contains($docComment->getText(), '@deprecated')) { + for ($line = $node->getStartLine(); $line <= $node->getEndLine(); $line++) { + $this->ignoredLines[] = $line; + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php new file mode 100644 index 000000000..ae2619fa7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/StaticAnalysis/ParsingFileAnalyser.php @@ -0,0 +1,247 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\StaticAnalysis; + +use function array_merge; +use function array_unique; +use function assert; +use function file_get_contents; +use function is_array; +use function max; +use function range; +use function sort; +use function sprintf; +use function substr_count; +use function token_get_all; +use function trim; +use PhpParser\Error; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor\NameResolver; +use PhpParser\NodeVisitor\ParentConnectingVisitor; +use PhpParser\ParserFactory; +use SebastianBergmann\CodeCoverage\ParserException; +use SebastianBergmann\LinesOfCode\LineCountingVisitor; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + * + * @psalm-import-type CodeUnitFunctionType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitMethodType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitClassType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type CodeUnitTraitType from \SebastianBergmann\CodeCoverage\StaticAnalysis\CodeUnitFindingVisitor + * @psalm-import-type LinesOfCodeType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + * @psalm-import-type LinesType from \SebastianBergmann\CodeCoverage\StaticAnalysis\FileAnalyser + */ +final class ParsingFileAnalyser implements FileAnalyser +{ + /** + * @psalm-var array> + */ + private array $classes = []; + + /** + * @psalm-var array> + */ + private array $traits = []; + + /** + * @psalm-var array> + */ + private array $functions = []; + + /** + * @var array + */ + private array $linesOfCode = []; + + /** + * @var array + */ + private array $ignoredLines = []; + + /** + * @var array + */ + private array $executableLines = []; + private readonly bool $useAnnotationsForIgnoringCode; + private readonly bool $ignoreDeprecatedCode; + + public function __construct(bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode) + { + $this->useAnnotationsForIgnoringCode = $useAnnotationsForIgnoringCode; + $this->ignoreDeprecatedCode = $ignoreDeprecatedCode; + } + + public function classesIn(string $filename): array + { + $this->analyse($filename); + + return $this->classes[$filename]; + } + + public function traitsIn(string $filename): array + { + $this->analyse($filename); + + return $this->traits[$filename]; + } + + public function functionsIn(string $filename): array + { + $this->analyse($filename); + + return $this->functions[$filename]; + } + + public function linesOfCodeFor(string $filename): array + { + $this->analyse($filename); + + return $this->linesOfCode[$filename]; + } + + public function executableLinesIn(string $filename): array + { + $this->analyse($filename); + + return $this->executableLines[$filename]; + } + + public function ignoredLinesFor(string $filename): array + { + $this->analyse($filename); + + return $this->ignoredLines[$filename]; + } + + /** + * @throws ParserException + */ + private function analyse(string $filename): void + { + if (isset($this->classes[$filename])) { + return; + } + + $source = file_get_contents($filename); + $linesOfCode = max(substr_count($source, "\n") + 1, substr_count($source, "\r") + 1); + + if ($linesOfCode === 0 && !empty($source)) { + $linesOfCode = 1; + } + + assert($linesOfCode > 0); + + $parser = (new ParserFactory)->createForHostVersion(); + + try { + $nodes = $parser->parse($source); + + assert($nodes !== null); + + $traverser = new NodeTraverser; + $codeUnitFindingVisitor = new CodeUnitFindingVisitor; + $lineCountingVisitor = new LineCountingVisitor($linesOfCode); + $ignoredLinesFindingVisitor = new IgnoredLinesFindingVisitor($this->useAnnotationsForIgnoringCode, $this->ignoreDeprecatedCode); + $executableLinesFindingVisitor = new ExecutableLinesFindingVisitor($source); + + $traverser->addVisitor(new NameResolver); + $traverser->addVisitor(new ParentConnectingVisitor); + $traverser->addVisitor($codeUnitFindingVisitor); + $traverser->addVisitor($lineCountingVisitor); + $traverser->addVisitor($ignoredLinesFindingVisitor); + $traverser->addVisitor($executableLinesFindingVisitor); + + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new ParserException( + sprintf( + 'Cannot parse %s: %s', + $filename, + $error->getMessage(), + ), + $error->getCode(), + $error, + ); + } + // @codeCoverageIgnoreEnd + + $this->classes[$filename] = $codeUnitFindingVisitor->classes(); + $this->traits[$filename] = $codeUnitFindingVisitor->traits(); + $this->functions[$filename] = $codeUnitFindingVisitor->functions(); + $this->executableLines[$filename] = $executableLinesFindingVisitor->executableLinesGroupedByBranch(); + $this->ignoredLines[$filename] = []; + + $this->findLinesIgnoredByLineBasedAnnotations($filename, $source, $this->useAnnotationsForIgnoringCode); + + $this->ignoredLines[$filename] = array_unique( + array_merge( + $this->ignoredLines[$filename], + $ignoredLinesFindingVisitor->ignoredLines(), + ), + ); + + sort($this->ignoredLines[$filename]); + + $result = $lineCountingVisitor->result(); + + $this->linesOfCode[$filename] = [ + 'linesOfCode' => $result->linesOfCode(), + 'commentLinesOfCode' => $result->commentLinesOfCode(), + 'nonCommentLinesOfCode' => $result->nonCommentLinesOfCode(), + ]; + } + + private function findLinesIgnoredByLineBasedAnnotations(string $filename, string $source, bool $useAnnotationsForIgnoringCode): void + { + if (!$useAnnotationsForIgnoringCode) { + return; + } + + $start = false; + + foreach (token_get_all($source) as $token) { + if (!is_array($token) || + !(T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0])) { + continue; + } + + $comment = trim($token[1]); + + if ($comment === '// @codeCoverageIgnore' || + $comment === '//@codeCoverageIgnore') { + $this->ignoredLines[$filename][] = $token[2]; + + continue; + } + + if ($comment === '// @codeCoverageIgnoreStart' || + $comment === '//@codeCoverageIgnoreStart') { + $start = $token[2]; + + continue; + } + + if ($comment === '// @codeCoverageIgnoreEnd' || + $comment === '//@codeCoverageIgnoreEnd') { + if (false === $start) { + $start = $token[2]; + } + + $this->ignoredLines[$filename] = array_merge( + $this->ignoredLines[$filename], + range($start, $token[2]), + ); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Known.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Known.php new file mode 100644 index 000000000..785fa8656 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Known.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestSize; + +/** + * @psalm-immutable + */ +abstract class Known extends TestSize +{ + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return true; + } + + abstract public function isGreaterThan(self $other): bool; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Large.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Large.php new file mode 100644 index 000000000..cdf3441df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Large.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestSize; + +/** + * @psalm-immutable + */ +final class Large extends Known +{ + /** + * @psalm-assert-if-true Large $this + */ + public function isLarge(): bool + { + return true; + } + + public function isGreaterThan(TestSize $other): bool + { + return !$other->isLarge(); + } + + public function asString(): string + { + return 'large'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Medium.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Medium.php new file mode 100644 index 000000000..309655461 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Medium.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestSize; + +/** + * @psalm-immutable + */ +final class Medium extends Known +{ + /** + * @psalm-assert-if-true Medium $this + */ + public function isMedium(): bool + { + return true; + } + + public function isGreaterThan(TestSize $other): bool + { + return $other->isSmall(); + } + + public function asString(): string + { + return 'medium'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Small.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Small.php new file mode 100644 index 000000000..6697bdef5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Small.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestSize; + +/** + * @psalm-immutable + */ +final class Small extends Known +{ + /** + * @psalm-assert-if-true Small $this + */ + public function isSmall(): bool + { + return true; + } + + public function isGreaterThan(TestSize $other): bool + { + return false; + } + + public function asString(): string + { + return 'small'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/TestSize.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/TestSize.php new file mode 100644 index 000000000..0eacc59a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/TestSize.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestSize; + +/** + * @psalm-immutable + */ +abstract class TestSize +{ + public static function unknown(): self + { + return new Unknown; + } + + public static function small(): self + { + return new Small; + } + + public static function medium(): self + { + return new Medium; + } + + public static function large(): self + { + return new Large; + } + + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Small $this + */ + public function isSmall(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Medium $this + */ + public function isMedium(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Large $this + */ + public function isLarge(): bool + { + return false; + } + + abstract public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Unknown.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Unknown.php new file mode 100644 index 000000000..24116f946 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestSize/Unknown.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestSize; + +/** + * @psalm-immutable + */ +final class Unknown extends TestSize +{ + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return true; + } + + public function asString(): string + { + return 'unknown'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Failure.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Failure.php new file mode 100644 index 000000000..1867d81d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Failure.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestStatus; + +/** + * @psalm-immutable + */ +final class Failure extends Known +{ + /** + * @psalm-assert-if-true Failure $this + */ + public function isFailure(): bool + { + return true; + } + + public function asString(): string + { + return 'failure'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Known.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Known.php new file mode 100644 index 000000000..9c0a52a5d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Known.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestStatus; + +/** + * @psalm-immutable + */ +abstract class Known extends TestStatus +{ + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Success.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Success.php new file mode 100644 index 000000000..dcb81a3ca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Success.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestStatus; + +/** + * @psalm-immutable + */ +final class Success extends Known +{ + /** + * @psalm-assert-if-true Success $this + */ + public function isSuccess(): bool + { + return true; + } + + public function asString(): string + { + return 'success'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/TestStatus.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/TestStatus.php new file mode 100644 index 000000000..5d532eaac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/TestStatus.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestStatus; + +/** + * @psalm-immutable + */ +abstract class TestStatus +{ + public static function unknown(): self + { + return new Unknown; + } + + public static function success(): self + { + return new Success; + } + + public static function failure(): self + { + return new Failure; + } + + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Success $this + */ + public function isSuccess(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Failure $this + */ + public function isFailure(): bool + { + return false; + } + + abstract public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Unknown.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Unknown.php new file mode 100644 index 000000000..d9183fb33 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/TestStatus/Unknown.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Test\TestStatus; + +/** + * @psalm-immutable + */ +final class Unknown extends TestStatus +{ + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return true; + } + + public function asString(): string + { + return 'unknown'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php new file mode 100644 index 000000000..0e99b1593 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Filesystem.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Util; + +use function is_dir; +use function mkdir; +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Filesystem +{ + /** + * @throws DirectoryCouldNotBeCreatedException + */ + public static function createDirectory(string $directory): void + { + $success = !(!is_dir($directory) && !@mkdir($directory, 0o777, true) && !is_dir($directory)); + + if (!$success) { + throw new DirectoryCouldNotBeCreatedException( + sprintf( + 'Directory "%s" could not be created', + $directory, + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Percentage.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Percentage.php new file mode 100644 index 000000000..a69f2366e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Util/Percentage.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Util; + +use function sprintf; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage + */ +final class Percentage +{ + private readonly float $fraction; + private readonly float $total; + + public static function fromFractionAndTotal(float $fraction, float $total): self + { + return new self($fraction, $total); + } + + private function __construct(float $fraction, float $total) + { + $this->fraction = $fraction; + $this->total = $total; + } + + public function asFloat(): float + { + if ($this->total > 0) { + return ($this->fraction / $this->total) * 100; + } + + return 100.0; + } + + public function asString(): string + { + if ($this->total > 0) { + return sprintf('%01.2F%%', $this->asFloat()); + } + + return ''; + } + + public function asFixedWidthString(): string + { + if ($this->total > 0) { + return sprintf('%6.2F%%', $this->asFloat()); + } + + return ''; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Version.php b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Version.php new file mode 100644 index 000000000..80b27f4d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-code-coverage/src/Version.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage; + +use function dirname; +use SebastianBergmann\Version as VersionId; + +final class Version +{ + private static string $version = ''; + + public static function id(): string + { + if (self::$version === '') { + self::$version = (new VersionId('10.1.16', dirname(__DIR__)))->asString(); + } + + return self::$version; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/ChangeLog.md b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/ChangeLog.md new file mode 100644 index 000000000..e2ddc6468 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/ChangeLog.md @@ -0,0 +1,174 @@ +# Change Log + +All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). + +## [4.1.0] - 2023-08-31 + +### Added + +* [#81](https://github.com/sebastianbergmann/php-file-iterator/issues/81): Accept `array|string $paths` in `Facade::getFilesAsArray()` + +## [4.0.2] - 2023-05-07 + +### Fixed + +* [#80](https://github.com/sebastianbergmann/php-file-iterator/pull/80): Ignore unresolvable symbolic link + +## [4.0.1] - 2023-02-10 + +### Fixed + +* [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/61): Excluded directories are traversed unnecessarily + +## [4.0.0] - 2023-02-03 + +### Removed + +* The optional `$commonPath` parameter of `SebastianBergmann\FileIterator\Facade` as well as the functionality it controlled has been removed +* The `SebastianBergmann\FileIterator\Factory` and `SebastianBergmann\FileIterator\Iterator` classes are now marked `@internal` +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [3.0.6] - 2021-12-02 + +### Changed + +* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths + +## [3.0.5] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.0.4] - 2020-07-11 + +### Fixed + +* [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/67): `TypeError` in `SebastianBergmann\FileIterator\Iterator::accept()` + +## [3.0.3] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.2] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [3.0.1] - 2020-04-18 + +### Fixed + +* [#64](https://github.com/sebastianbergmann/php-file-iterator/issues/64): Release tarball contains Composer PHAR + +## [3.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [2.0.5] - 2021-12-02 + +### Changed + +* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths + +### Fixed + +* [#74](https://github.com/sebastianbergmann/php-file-iterator/pull/74): Document return type of `SebastianBergmann\FileIterator\Iterator::accept()` so that Symfony's `DebugClassLoader` does not trigger a deprecation warning + +## [2.0.4] - 2021-07-19 + +### Changed + +* Added `ReturnTypeWillChange` attribute to `SebastianBergmann\FileIterator\Iterator::accept()` because the return type of `\FilterIterator::accept()` will change in PHP 8.1 + +## [2.0.3] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1` + +## [2.0.2] - 2018-09-13 + +### Fixed + +* [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory + +## [2.0.1] - 2018-06-11 + +### Fixed + +* [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory + +## [2.0.0] - 2018-05-28 + +### Fixed + +* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path + +### Changed + +* This component now uses namespaces + +### Removed + +* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0 + +## [1.4.5] - 2017-11-27 + +### Fixed + +* [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30) + +## [1.4.4] - 2017-11-27 + +### Fixed + +* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path + +## [1.4.3] - 2017-11-25 + +### Fixed + +* [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names + +## [1.4.2] - 2016-11-26 + +No changes + +## [1.4.1] - 2015-07-26 + +No changes + +## 1.4.0 - 2015-04-02 + +### Added + +* [#23](https://github.com/sebastianbergmann/php-file-iterator/pull/23): Added support for wildcards (glob) in exclude + +[4.1.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.0.2...4.1.0 +[4.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.6...4.0.0 +[3.0.6]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.5...3.0.6 +[3.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.4...3.0.5 +[3.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.5...3.0.0 +[2.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.4...2.0.5 +[2.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.5...2.0.0 +[1.4.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.4...1.4.5 +[1.4.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.3...1.4.4 +[1.4.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.2...1.4.3 +[1.4.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.0...1.4.1 diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/LICENSE b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/LICENSE new file mode 100644 index 000000000..80e09f7be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2009-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/README.md b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/README.md new file mode 100644 index 000000000..f012ba735 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/README.md @@ -0,0 +1,17 @@ +[![Latest Stable Version](https://poser.pugx.org/phpunit/php-file-iterator/v/stable.png)](https://packagist.org/packages/phpunit/php-file-iterator) +[![CI Status](https://github.com/sebastianbergmann/php-file-iterator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-file-iterator/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-file-iterator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-file-iterator) +[![codecov](https://codecov.io/gh/sebastianbergmann/php-file-iterator/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/php-file-iterator) + +# php-file-iterator + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phpunit/php-file-iterator + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phpunit/php-file-iterator + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/SECURITY.md b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/composer.json b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/composer.json new file mode 100644 index 000000000..3f0089c2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/composer.json @@ -0,0 +1,46 @@ +{ + "name": "phpunit/php-file-iterator", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "type": "library", + "keywords": [ + "iterator", + "filesystem" + ], + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/ExcludeIterator.php b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/ExcludeIterator.php new file mode 100644 index 000000000..a928b4ba7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/ExcludeIterator.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use function assert; +use function str_starts_with; +use RecursiveDirectoryIterator; +use RecursiveFilterIterator; +use SplFileInfo; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator + */ +final class ExcludeIterator extends RecursiveFilterIterator +{ + /** + * @psalm-var list + */ + private array $exclude; + + /** + * @psalm-param list $exclude + */ + public function __construct(RecursiveDirectoryIterator $iterator, array $exclude) + { + parent::__construct($iterator); + + $this->exclude = $exclude; + } + + public function accept(): bool + { + $current = $this->current(); + + assert($current instanceof SplFileInfo); + + $path = $current->getRealPath(); + + if ($path === false) { + return false; + } + + foreach ($this->exclude as $exclude) { + if (str_starts_with($path, $exclude)) { + return false; + } + } + + return true; + } + + public function hasChildren(): bool + { + return $this->getInnerIterator()->hasChildren(); + } + + public function getChildren(): self + { + return new self( + $this->getInnerIterator()->getChildren(), + $this->exclude + ); + } + + public function getInnerIterator(): RecursiveDirectoryIterator + { + $innerIterator = parent::getInnerIterator(); + + assert($innerIterator instanceof RecursiveDirectoryIterator); + + return $innerIterator; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Facade.php new file mode 100644 index 000000000..b782bf96a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Facade.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use function array_unique; +use function assert; +use function sort; +use SplFileInfo; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Facade +{ + /** + * @psalm-param list|non-empty-string $paths + * @psalm-param list|string $suffixes + * @psalm-param list|string $prefixes + * @psalm-param list $exclude + * + * @psalm-return list + */ + public function getFilesAsArray(array|string $paths, array|string $suffixes = '', array|string $prefixes = '', array $exclude = []): array + { + $iterator = (new Factory)->getFileIterator($paths, $suffixes, $prefixes, $exclude); + + $files = []; + + foreach ($iterator as $file) { + assert($file instanceof SplFileInfo); + + $file = $file->getRealPath(); + + if ($file) { + $files[] = $file; + } + } + + $files = array_unique($files); + + sort($files); + + return $files; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Factory.php b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Factory.php new file mode 100644 index 000000000..35f9ca08d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Factory.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use const GLOB_ONLYDIR; +use function array_filter; +use function array_map; +use function array_merge; +use function array_values; +use function glob; +use function is_dir; +use function is_string; +use function realpath; +use AppendIterator; +use FilesystemIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; + +/** + * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator + */ +final class Factory +{ + /** + * @psalm-param list|non-empty-string $paths + * @psalm-param list|string $suffixes + * @psalm-param list|string $prefixes + * @psalm-param list $exclude + */ + public function getFileIterator(array|string $paths, array|string $suffixes = '', array|string $prefixes = '', array $exclude = []): AppendIterator + { + if (is_string($paths)) { + $paths = [$paths]; + } + + $paths = $this->resolveWildcards($paths); + $exclude = $this->resolveWildcards($exclude); + + if (is_string($prefixes)) { + if ($prefixes !== '') { + $prefixes = [$prefixes]; + } else { + $prefixes = []; + } + } + + if (is_string($suffixes)) { + if ($suffixes !== '') { + $suffixes = [$suffixes]; + } else { + $suffixes = []; + } + } + + $iterator = new AppendIterator; + + foreach ($paths as $path) { + if (is_dir($path)) { + $iterator->append( + new Iterator( + $path, + new RecursiveIteratorIterator( + new ExcludeIterator( + new RecursiveDirectoryIterator($path, FilesystemIterator::FOLLOW_SYMLINKS | FilesystemIterator::SKIP_DOTS), + $exclude, + ), + ), + $suffixes, + $prefixes, + ) + ); + } + } + + return $iterator; + } + + /** + * @psalm-param list $paths + * + * @psalm-return list + */ + private function resolveWildcards(array $paths): array + { + $_paths = [[]]; + + foreach ($paths as $path) { + if ($locals = glob($path, GLOB_ONLYDIR)) { + $_paths[] = array_map('\realpath', $locals); + } else { + // @codeCoverageIgnoreStart + $_paths[] = [realpath($path)]; + // @codeCoverageIgnoreEnd + } + } + + return array_values(array_filter(array_merge(...$_paths))); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Iterator.php b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Iterator.php new file mode 100644 index 000000000..d071205a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-file-iterator/src/Iterator.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\FileIterator; + +use function assert; +use function preg_match; +use function realpath; +use function str_ends_with; +use function str_replace; +use function str_starts_with; +use AppendIterator; +use FilterIterator; +use SplFileInfo; + +/** + * @template-extends FilterIterator + * + * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator + */ +final class Iterator extends FilterIterator +{ + public const PREFIX = 0; + public const SUFFIX = 1; + private string|false $basePath; + + /** + * @psalm-var list + */ + private array $suffixes; + + /** + * @psalm-var list + */ + private array $prefixes; + + /** + * @psalm-param list $suffixes + * @psalm-param list $prefixes + */ + public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = []) + { + $this->basePath = realpath($basePath); + $this->prefixes = $prefixes; + $this->suffixes = $suffixes; + + parent::__construct($iterator); + } + + public function accept(): bool + { + $current = $this->getInnerIterator()->current(); + + assert($current instanceof SplFileInfo); + + $filename = $current->getFilename(); + $realPath = $current->getRealPath(); + + if ($realPath === false) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + return $this->acceptPath($realPath) && + $this->acceptPrefix($filename) && + $this->acceptSuffix($filename); + } + + private function acceptPath(string $path): bool + { + // Filter files in hidden directories by checking path that is relative to the base path. + if (preg_match('=/\.[^/]*/=', str_replace((string) $this->basePath, '', $path))) { + return false; + } + + return true; + } + + private function acceptPrefix(string $filename): bool + { + return $this->acceptSubString($filename, $this->prefixes, self::PREFIX); + } + + private function acceptSuffix(string $filename): bool + { + return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX); + } + + /** + * @psalm-param list $subStrings + */ + private function acceptSubString(string $filename, array $subStrings, int $type): bool + { + if (empty($subStrings)) { + return true; + } + + foreach ($subStrings as $string) { + if (($type === self::PREFIX && str_starts_with($filename, $string)) || + ($type === self::SUFFIX && str_ends_with($filename, $string))) { + return true; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/baseline.xml b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/baseline.xml new file mode 100644 index 000000000..7aaad59df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/baseline.xml @@ -0,0 +1,8 @@ + + + + + $timeout + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/config.xml b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/config.xml new file mode 100644 index 000000000..a23123689 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/.psalm/config.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/ChangeLog.md b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/ChangeLog.md new file mode 100644 index 000000000..c6e815d8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/ChangeLog.md @@ -0,0 +1,55 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [4.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [3.1.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.1.0] - 2020-08-06 + +### Changed + +* [#14](https://github.com/sebastianbergmann/php-invoker/pull/14): Clear alarm in `finally` block + +## [3.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [3.0.0] - 2020-02-07 + +### Added + +* Added `canInvokeWithTimeout()` method to check requirements for the functionality provided by this component to work + +### Changed + +* Moved `"ext-pcntl": "*"` requirement from `require` to `suggest` so that this component can be installed even if `ext/pcntl` is not available +* `invoke()` now raises an exception when the requirements for the functionality provided by this component to work are not met + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +[4.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/3.1.1...4.0.0 +[3.1.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.1.0...3.1.1 +[3.1.0]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.2...3.1.0 +[3.0.2]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/2.0.0...3.0.0 diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/LICENSE b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/LICENSE new file mode 100644 index 000000000..453013107 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2011-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/phpunit/php-invoker/README.md b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/README.md new file mode 100644 index 000000000..7b6ff1338 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/README.md @@ -0,0 +1,20 @@ +# phpunit/php-invoker + +[![Latest Stable Version](https://poser.pugx.org/phpunit/php-invoker/v/stable.png)](https://packagist.org/packages/phpunit/php-invoker) +[![CI Status](https://github.com/sebastianbergmann/php-invoker/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-invoker/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-invoker/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-invoker) +[![codecov](https://codecov.io/gh/sebastianbergmann/php-invoker/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/php-invoker) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require phpunit/php-invoker +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev phpunit/php-invoker +``` diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/SECURITY.md b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/composer.json b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/composer.json new file mode 100644 index 000000000..c3dc5acba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/composer.json @@ -0,0 +1,54 @@ +{ + "name": "phpunit/php-invoker", + "description": "Invoke callables with a timeout", + "type": "library", + "keywords": [ + "process" + ], + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues" + }, + "prefer-stable": true, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ] + }, + "suggest": { + "ext-pcntl": "*" + }, + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + } +} + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/Invoker.php b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/Invoker.php new file mode 100644 index 000000000..d5765219b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/Invoker.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use const SIGALRM; +use function call_user_func_array; +use function function_exists; +use function pcntl_alarm; +use function pcntl_async_signals; +use function pcntl_signal; +use function sprintf; +use Throwable; + +final class Invoker +{ + private int $timeout; + + /** + * @throws Throwable + */ + public function invoke(callable $callable, array $arguments, int $timeout): mixed + { + if (!$this->canInvokeWithTimeout()) { + throw new ProcessControlExtensionNotLoadedException( + 'The pcntl (process control) extension for PHP is required' + ); + } + + pcntl_signal( + SIGALRM, + function (): void + { + throw new TimeoutException( + sprintf( + 'Execution aborted after %d second%s', + $this->timeout, + $this->timeout === 1 ? '' : 's' + ) + ); + }, + true + ); + + $this->timeout = $timeout; + + pcntl_async_signals(true); + pcntl_alarm($timeout); + + try { + return call_user_func_array($callable, $arguments); + } finally { + pcntl_alarm(0); + } + } + + public function canInvokeWithTimeout(): bool + { + return function_exists('pcntl_signal') && function_exists('pcntl_async_signals') && function_exists('pcntl_alarm'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/Exception.php new file mode 100644 index 000000000..6ecbf5dd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php new file mode 100644 index 000000000..ef42fd195 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use RuntimeException; + +final class ProcessControlExtensionNotLoadedException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php new file mode 100644 index 000000000..2f7631c0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-invoker/src/exceptions/TimeoutException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Invoker; + +use RuntimeException; + +final class TimeoutException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/ChangeLog.md b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/ChangeLog.md new file mode 100644 index 000000000..012f02b2d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/ChangeLog.md @@ -0,0 +1,57 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.0.1] - 2023-08-31 + +### Changed + +* Warnings from `file_put_contents()` are now suppressed + +## [3.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [2.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Template\Exception` now correctly extends `\Throwable` + +## [2.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [2.0.0] - 2020-02-07 + +### Changed + +* The `Text_Template` class was renamed to `SebastianBergmann\Template\Template` + +### Removed + +* Removed support for PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2 + +[3.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.4...3.0.0 +[2.0.4]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/1.2.1...2.0.0 diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/LICENSE b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/LICENSE new file mode 100644 index 000000000..80e09f7be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2009-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/phpunit/php-text-template/README.md b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/README.md new file mode 100644 index 000000000..5144a6a94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/README.md @@ -0,0 +1,17 @@ +[![Latest Stable Version](https://poser.pugx.org/phpunit/php-text-template/v/stable.png)](https://packagist.org/packages/phpunit/php-text-template) +[![CI Status](https://github.com/sebastianbergmann/php-text-template/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-text-template/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-text-template/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-text-template) +[![codecov](https://codecov.io/gh/sebastianbergmann/php-text-template/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/php-text-template) + +# php-text-template + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require phpunit/php-text-template + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev phpunit/php-text-template + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/SECURITY.md b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/composer.json b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/composer.json new file mode 100644 index 000000000..cd6cf754a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/composer.json @@ -0,0 +1,45 @@ +{ + "name": "phpunit/php-text-template", + "description": "Simple template engine.", + "type": "library", + "keywords": [ + "template" + ], + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/Template.php b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/Template.php new file mode 100644 index 000000000..167e2385c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/Template.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +use function array_keys; +use function array_merge; +use function file_get_contents; +use function file_put_contents; +use function is_file; +use function sprintf; +use function str_replace; + +final class Template +{ + private string $template = ''; + private string $openDelimiter; + private string $closeDelimiter; + + /** + * @psalm-var array + */ + private array $values = []; + + /** + * @throws InvalidArgumentException + */ + public function __construct(string $file = '', string $openDelimiter = '{', string $closeDelimiter = '}') + { + $this->setFile($file); + + $this->openDelimiter = $openDelimiter; + $this->closeDelimiter = $closeDelimiter; + } + + /** + * @throws InvalidArgumentException + */ + public function setFile(string $file): void + { + if (is_file($file)) { + $this->template = file_get_contents($file); + + return; + } + + $distFile = $file . '.dist'; + + if (is_file($distFile)) { + $this->template = file_get_contents($distFile); + + return; + } + + throw new InvalidArgumentException( + sprintf( + 'Failed to load template "%s"', + $file + ) + ); + } + + /** + * @psalm-param array $values + */ + public function setVar(array $values, bool $merge = true): void + { + if (!$merge || empty($this->values)) { + $this->values = $values; + + return; + } + + $this->values = array_merge($this->values, $values); + } + + public function render(): string + { + $keys = []; + + foreach (array_keys($this->values) as $key) { + $keys[] = $this->openDelimiter . $key . $this->closeDelimiter; + } + + return str_replace($keys, $this->values, $this->template); + } + + /** + * @codeCoverageIgnore + */ + public function renderTo(string $target): void + { + if (!@file_put_contents($target, $this->render())) { + throw new RuntimeException( + sprintf( + 'Writing rendered result to "%s" failed', + $target + ) + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/Exception.php new file mode 100644 index 000000000..d7dc5cbea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php new file mode 100644 index 000000000..10e1cd11f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +final class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php new file mode 100644 index 000000000..131498e61 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-text-template/src/exceptions/RuntimeException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Template; + +use InvalidArgumentException; + +final class RuntimeException extends InvalidArgumentException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/ChangeLog.md b/.extlib/simplesamlphp/vendor/phpunit/php-timer/ChangeLog.md new file mode 100644 index 000000000..2814b0070 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/ChangeLog.md @@ -0,0 +1,145 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [6.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [5.0.3] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Timer\Exception` now correctly extends `\Throwable` + +## [5.0.2] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [5.0.1] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [5.0.0] - 2020-06-07 + +### Changed + +* Parameter type for `SebastianBergmann\Timer\Duration::fromMicroseconds()` was changed from `int` to `float` +* Parameter type for `SebastianBergmann\Timer\Duration::fromNanoseconds()` was changed from `int` to `float` +* Return type for `SebastianBergmann\Timer\Duration::asNanoseconds()` was changed from `int` to `float` + +### Fixed + +* [#31](https://github.com/sebastianbergmann/php-timer/issues/31): Type Error on 32-bit systems (where `hrtime()` returns `float` instead of `int`) + +## [4.0.0] - 2020-06-01 + +### Added + +* Introduced `Duration` value object for encapsulating a duration with nanosecond granularity +* Introduced `ResourceUsageFormatter` object for formatting resource usage with option to explicitly pass a duration (instead of looking at the unreliable `$_SERVER['REQUEST_TIME_FLOAT']` variable) + +### Changed + +* The methods of `Timer` are no longer static +* `Timer::stop()` now returns a `Duration` value object + +### Removed + +* Functionality that is now implemented in `Duration` and `ResourceUsageFormatter` has been removed from `Timer` + +## [3.1.4] - 2020-04-20 + +### Changed + +* `Timer::timeSinceStartOfRequest()` no longer tries `$_SERVER['REQUEST_TIME']` when `$_SERVER['REQUEST_TIME_FLOAT']` is not available (`$_SERVER['REQUEST_TIME_FLOAT']` was added in PHP 5.4 and this library requires PHP 7.3) +* Improved exception messages when `$_SERVER['REQUEST_TIME_FLOAT']` is not set or is not of type `float` + +### Changed + +## [3.1.3] - 2020-04-20 + +### Changed + +* `Timer::timeSinceStartOfRequest()` now raises an exception if `$_SERVER['REQUEST_TIME_FLOAT']` does not contain a `float` (or `$_SERVER['REQUEST_TIME']` does not contain an `int`) + +## [3.1.2] - 2020-04-17 + +### Changed + +* Improved the fix for [#30](https://github.com/sebastianbergmann/php-timer/issues/30) and restored usage of `hrtime()` + +## [3.1.1] - 2020-04-17 + +### Fixed + +* [#30](https://github.com/sebastianbergmann/php-timer/issues/30): Resolution of time returned by `Timer::stop()` is different than before (this reverts using `hrtime()` instead of `microtime()`) + +## [3.1.0] - 2020-04-17 + +### Added + +* `Timer::secondsToShortTimeString()` as alternative to `Timer::secondsToTimeString()` + +### Changed + +* `Timer::start()` and `Timer::stop()` now use `hrtime()` (high resolution monotonic timer) instead of `microtime()` +* `Timer::timeSinceStartOfRequest()` now uses `Timer::secondsToShortTimeString()` for time formatting +* Improved formatting of `Timer::secondsToTimeString()` result + +## [3.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [2.1.2] - 2019-06-07 + +### Fixed + +* [#21](https://github.com/sebastianbergmann/php-timer/pull/21): Formatting of memory consumption does not work on 32bit systems + +## [2.1.1] - 2019-02-20 + +### Changed + +* Improved formatting of memory consumption for `resourceUsage()` + +## [2.1.0] - 2019-02-20 + +### Changed + +* Improved formatting of memory consumption for `resourceUsage()` + +## [2.0.0] - 2018-02-01 + +### Changed + +* This component now uses namespaces + +### Removed + +* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0 + +[6.0.0]: https://github.com/sebastianbergmann/php-timer/compare/5.0.3...6.0.0 +[5.0.3]: https://github.com/sebastianbergmann/php-timer/compare/5.0.2...5.0.3 +[5.0.2]: https://github.com/sebastianbergmann/php-timer/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/php-timer/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/php-timer/compare/4.0.0...5.0.0 +[4.0.0]: https://github.com/sebastianbergmann/php-timer/compare/3.1.4...4.0.0 +[3.1.4]: https://github.com/sebastianbergmann/php-timer/compare/3.1.3...3.1.4 +[3.1.3]: https://github.com/sebastianbergmann/php-timer/compare/3.1.2...3.1.3 +[3.1.2]: https://github.com/sebastianbergmann/php-timer/compare/3.1.1...3.1.2 +[3.1.1]: https://github.com/sebastianbergmann/php-timer/compare/3.1.0...3.1.1 +[3.1.0]: https://github.com/sebastianbergmann/php-timer/compare/3.0.0...3.1.0 +[3.0.0]: https://github.com/sebastianbergmann/php-timer/compare/2.1.2...3.0.0 +[2.1.2]: https://github.com/sebastianbergmann/php-timer/compare/2.1.1...2.1.2 +[2.1.1]: https://github.com/sebastianbergmann/php-timer/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/sebastianbergmann/php-timer/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/sebastianbergmann/php-timer/compare/1.0.9...2.0.0 diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/LICENSE b/.extlib/simplesamlphp/vendor/phpunit/php-timer/LICENSE new file mode 100644 index 000000000..bf96e0e87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2010-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/phpunit/php-timer/README.md b/.extlib/simplesamlphp/vendor/phpunit/php-timer/README.md new file mode 100644 index 000000000..b553e32c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/README.md @@ -0,0 +1,106 @@ +# phpunit/php-timer + +[![Latest Stable Version](https://poser.pugx.org/phpunit/php-timer/v/stable.png)](https://packagist.org/packages/phpunit/php-timer) +[![CI Status](https://github.com/sebastianbergmann/php-timer/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/php-timer/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/php-timer/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/php-timer) +[![codecov](https://codecov.io/gh/sebastianbergmann/php-timer/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/php-timer) + +Utility class for timing things, factored out of PHPUnit into a stand-alone component. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require phpunit/php-timer +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev phpunit/php-timer +``` + +## Usage + +### Basic Timing + +```php +require __DIR__ . '/vendor/autoload.php'; + +use SebastianBergmann\Timer\Timer; + +$timer = new Timer; + +$timer->start(); + +foreach (\range(0, 100000) as $i) { + // ... +} + +$duration = $timer->stop(); + +var_dump(get_class($duration)); +var_dump($duration->asString()); +var_dump($duration->asSeconds()); +var_dump($duration->asMilliseconds()); +var_dump($duration->asMicroseconds()); +var_dump($duration->asNanoseconds()); +``` + +The code above yields the output below: + +``` +string(32) "SebastianBergmann\Timer\Duration" +string(9) "00:00.002" +float(0.002851062) +float(2.851062) +float(2851.062) +int(2851062) +``` + +### Resource Consumption + +#### Explicit duration + +```php +require __DIR__ . '/vendor/autoload.php'; + +use SebastianBergmann\Timer\ResourceUsageFormatter; +use SebastianBergmann\Timer\Timer; + +$timer = new Timer; +$timer->start(); + +foreach (\range(0, 100000) as $i) { + // ... +} + +print (new ResourceUsageFormatter)->resourceUsage($timer->stop()); +``` + +The code above yields the output below: + +``` +Time: 00:00.002, Memory: 6.00 MB +``` + +#### Duration since PHP Startup (using unreliable `$_SERVER['REQUEST_TIME_FLOAT']`) + +```php +require __DIR__ . '/vendor/autoload.php'; + +use SebastianBergmann\Timer\ResourceUsageFormatter; + +foreach (\range(0, 100000) as $i) { + // ... +} + +print (new ResourceUsageFormatter)->resourceUsageSinceStartOfRequest(); +``` + +The code above yields the output below: + +``` +Time: 00:00.002, Memory: 6.00 MB +``` diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/SECURITY.md b/.extlib/simplesamlphp/vendor/phpunit/php-timer/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/composer.json b/.extlib/simplesamlphp/vendor/phpunit/php-timer/composer.json new file mode 100644 index 000000000..6f5880b6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/composer.json @@ -0,0 +1,45 @@ +{ + "name": "phpunit/php-timer", + "description": "Utility class for timing", + "type": "library", + "keywords": [ + "timer" + ], + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + } +} + diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/Duration.php b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/Duration.php new file mode 100644 index 000000000..ef3f3bee6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/Duration.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use function floor; +use function sprintf; + +/** + * @psalm-immutable + */ +final class Duration +{ + private readonly float $nanoseconds; + private readonly int $hours; + private readonly int $minutes; + private readonly int $seconds; + private readonly int $milliseconds; + + public static function fromMicroseconds(float $microseconds): self + { + return new self($microseconds * 1000); + } + + public static function fromNanoseconds(float $nanoseconds): self + { + return new self($nanoseconds); + } + + private function __construct(float $nanoseconds) + { + $this->nanoseconds = $nanoseconds; + $timeInMilliseconds = $nanoseconds / 1000000; + $hours = floor($timeInMilliseconds / 60 / 60 / 1000); + $hoursInMilliseconds = $hours * 60 * 60 * 1000; + $minutes = floor($timeInMilliseconds / 60 / 1000) % 60; + $minutesInMilliseconds = $minutes * 60 * 1000; + $seconds = floor(($timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds) / 1000); + $secondsInMilliseconds = $seconds * 1000; + $milliseconds = $timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds - $secondsInMilliseconds; + $this->hours = (int) $hours; + $this->minutes = $minutes; + $this->seconds = (int) $seconds; + $this->milliseconds = (int) $milliseconds; + } + + public function asNanoseconds(): float + { + return $this->nanoseconds; + } + + public function asMicroseconds(): float + { + return $this->nanoseconds / 1000; + } + + public function asMilliseconds(): float + { + return $this->nanoseconds / 1000000; + } + + public function asSeconds(): float + { + return $this->nanoseconds / 1000000000; + } + + public function asString(): string + { + $result = ''; + + if ($this->hours > 0) { + $result = sprintf('%02d', $this->hours) . ':'; + } + + $result .= sprintf('%02d', $this->minutes) . ':'; + $result .= sprintf('%02d', $this->seconds); + + if ($this->milliseconds > 0) { + $result .= '.' . sprintf('%03d', $this->milliseconds); + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php new file mode 100644 index 000000000..0c94b9b3c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/ResourceUsageFormatter.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use function is_float; +use function memory_get_peak_usage; +use function microtime; +use function sprintf; + +final class ResourceUsageFormatter +{ + /** + * @psalm-var array + */ + private const SIZES = [ + 'GB' => 1073741824, + 'MB' => 1048576, + 'KB' => 1024, + ]; + + public function resourceUsage(Duration $duration): string + { + return sprintf( + 'Time: %s, Memory: %s', + $duration->asString(), + $this->bytesToString(memory_get_peak_usage(true)) + ); + } + + /** + * @throws TimeSinceStartOfRequestNotAvailableException + */ + public function resourceUsageSinceStartOfRequest(): string + { + if (!isset($_SERVER['REQUEST_TIME_FLOAT'])) { + throw new TimeSinceStartOfRequestNotAvailableException( + 'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not available' + ); + } + + if (!is_float($_SERVER['REQUEST_TIME_FLOAT'])) { + throw new TimeSinceStartOfRequestNotAvailableException( + 'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not of type float' + ); + } + + return $this->resourceUsage( + Duration::fromMicroseconds( + (1000000 * (microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'])) + ) + ); + } + + private function bytesToString(int $bytes): string + { + foreach (self::SIZES as $unit => $value) { + if ($bytes >= $value) { + return sprintf('%.2f %s', $bytes / $value, $unit); + } + } + + // @codeCoverageIgnoreStart + return $bytes . ' byte' . ($bytes !== 1 ? 's' : ''); + // @codeCoverageIgnoreEnd + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/Timer.php b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/Timer.php new file mode 100644 index 000000000..ead261818 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/Timer.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use function array_pop; +use function hrtime; + +final class Timer +{ + /** + * @psalm-var list + */ + private array $startTimes = []; + + public function start(): void + { + $this->startTimes[] = (float) hrtime(true); + } + + /** + * @throws NoActiveTimerException + */ + public function stop(): Duration + { + if (empty($this->startTimes)) { + throw new NoActiveTimerException( + 'Timer::start() has to be called before Timer::stop()' + ); + } + + return Duration::fromNanoseconds((float) hrtime(true) - array_pop($this->startTimes)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/Exception.php new file mode 100644 index 000000000..996da0860 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php new file mode 100644 index 000000000..40fe45e86 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/NoActiveTimerException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use LogicException; + +final class NoActiveTimerException extends LogicException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php new file mode 100644 index 000000000..a2d94ce80 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Timer; + +use RuntimeException; + +final class TimeSinceStartOfRequestNotAvailableException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/ChangeLog-10.5.md b/.extlib/simplesamlphp/vendor/phpunit/phpunit/ChangeLog-10.5.md new file mode 100644 index 000000000..771ab2f19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/ChangeLog-10.5.md @@ -0,0 +1,387 @@ +# Changes in PHPUnit 10.5 + +All notable changes of the PHPUnit 10.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [10.5.38] - 2024-10-28 + +### Changed + +* [#6012](https://github.com/sebastianbergmann/phpunit/pull/6012): Remove empty lines between TeamCity events + +## [10.5.37] - 2024-10-19 + +### Fixed + +* [#5982](https://github.com/sebastianbergmann/phpunit/pull/5982): Typo in exception message + +## [10.5.36] - 2024-10-08 + +### Changed + +* [#5957](https://github.com/sebastianbergmann/phpunit/pull/5957): Skip data provider build when requirements are not satisfied +* [#5969](https://github.com/sebastianbergmann/phpunit/pull/5969): Check for requirements before creating a separate process +* Updated regular expressions used by `StringMatchesFormatDescription` constraint to be consistent with PHP's `run-tests.php` + +### Fixed + +* [#5965](https://github.com/sebastianbergmann/phpunit/issues/5965): `PHPUnit\Framework\Exception` does not handle string error codes (`PDOException` with error code `'HY000'`, for example) + +## [10.5.35] - 2024-09-19 + +### Changed + +* [#5956](https://github.com/sebastianbergmann/phpunit/issues/5956): Deprecation of the `E_STRICT` constant in PHP 8.4 + +### Fixed + +* [#5950](https://github.com/sebastianbergmann/phpunit/pull/5950): TestDox text should not be `trim()`med when it contains `$` character +* The attribute parser will no longer try to instantiate attribute classes that do not exist + +## [10.5.34] - 2024-09-13 + +### Fixed + +* [#5931](https://github.com/sebastianbergmann/phpunit/pull/5931): Reverted addition of `name` property on `` element in JUnit XML logfile +* [#5946](https://github.com/sebastianbergmann/phpunit/issues/5946): `Callback` throws a `TypeError` when checking a `callable` has variadic parameters + +## [10.5.33] - 2024-09-09 + +### Fixed + +* [#4584](https://github.com/sebastianbergmann/phpunit/issues/4584): `assertJsonStringEqualsJsonString()` considers objects with sequential numeric keys equal to be arrays +* [#4625](https://github.com/sebastianbergmann/phpunit/issues/4625): Generator yielding keys that are neither integer or string leads to hard-to-understand error message when used as data provider +* [#4674](https://github.com/sebastianbergmann/phpunit/issues/4674): JSON assertions should treat objects as unordered +* [#5891](https://github.com/sebastianbergmann/phpunit/issues/5891): `Callback` constraint does not handle variadic arguments correctly when used for mock object expectations +* [#5929](https://github.com/sebastianbergmann/phpunit/issues/5929): TestDox output containing `$` at the beginning gets truncated when used with a data provider + +## [10.5.32] - 2024-09-04 + +### Added + +* [#5937](https://github.com/sebastianbergmann/phpunit/issues/5937): `failOnPhpunitDeprecation` attribute on the `` element of the XML configuration file and `--fail-on-phpunit-deprecation` CLI option for controlling whether PHPUnit deprecations should be considered when determining the test runner's shell exit code (default: do not consider) +* `displayDetailsOnPhpunitDeprecations` attribute on the `` element of the XML configuration file and `--display-phpunit-deprecations` CLI option for controlling whether details on PHPUnit deprecations should be displayed (default: do not display) + +### Changed + +* [#5937](https://github.com/sebastianbergmann/phpunit/issues/5937): PHPUnit deprecations will, by default, no longer affect the test runner's shell exit code. This can optionally be turned back on using the `--fail-on-phpunit-deprecation` CLI option or the `failOnPhpunitDeprecation="true"` attribute on the `` element of the XML configuration file. +* Details for PHPUnit deprecations will, by default, no longer be displayed. This can optionally be turned back on using the `--display-phpunit-deprecations` CLI option or the `displayDetailsOnPhpunitDeprecations` attribute on the `` element of the XML configuration file. + +## [10.5.31] - 2024-09-03 + +### Changed + +* [#5931](https://github.com/sebastianbergmann/phpunit/pull/5931): `name` property on `` element in JUnit XML logfile +* Removed `.phpstorm.meta.php` file as methods such as `TestCase::createStub()` use generics / template types for their return types and PhpStorm, for example, uses that information + +### Fixed + +* [#5884](https://github.com/sebastianbergmann/phpunit/issues/5884): TestDox printer does not consider that issues can be suppressed by attribute, baseline, source location, or `@` operator + +## [10.5.30] - 2024-08-13 + +### Changed + +* Improved error message when stubbed method is called more often than return values were configured for it + +## [10.5.29] - 2024-07-30 + +### Fixed + +* [#5887](https://github.com/sebastianbergmann/phpunit/pull/5887): Issue baseline generator does not correctly handle ignoring suppressed issues +* [#5908](https://github.com/sebastianbergmann/phpunit/issues/5908): `--list-tests` and `--list-tests-xml` CLI options do not report error when data provider method throws exception + +## [10.5.28] - 2024-07-18 + +### Fixed + +* [#5898](https://github.com/sebastianbergmann/phpunit/issues/5898): `Test\Passed` event is not emitted for PHPT tests +* `--coverage-filter` CLI option could not be used multiple times + +## [10.5.27] - 2024-07-10 + +### Changed + +* Updated dependencies (so that users that install using Composer's `--prefer-lowest` CLI option also get recent versions) + +### Fixed + +* [#5892](https://github.com/sebastianbergmann/phpunit/issues/5892): Errors during write of `phpunit.xml` are not handled correctly when `--generate-configuration` is used + +## [10.5.26] - 2024-07-08 + +### Added + +* `--only-summary-for-coverage-text` CLI option to reduce the code coverage report in text format to a summary +* `--show-uncovered-for-coverage-text` CLI option to expand the code coverage report in text format to include a list of uncovered files + +## [10.5.25] - 2024-07-03 + +### Changed + +* Updated dependencies for PHAR distribution + +## [10.5.24] - 2024-06-20 + +### Changed + +* [#5877](https://github.com/sebastianbergmann/phpunit/pull/5877): Use `array_pop()` instead of `array_shift()` for processing `Test` objects in `TestSuite::run()` and optimize `TestSuite::isEmpty()` + +## [10.5.23] - 2024-06-20 + +### Changed + +* [#5875](https://github.com/sebastianbergmann/phpunit/pull/5875): Also destruct `TestCase` objects early that use a data provider + +## [10.5.22] - 2024-06-19 + +### Changed + +* [#5871](https://github.com/sebastianbergmann/phpunit/pull/5871): Do not collect unnecessary information using `debug_backtrace()` + +## [10.5.21] - 2024-06-15 + +### Changed + +* [#5861](https://github.com/sebastianbergmann/phpunit/pull/5861): Destroy `TestCase` object after its test was run + +## [10.5.20] - 2024-04-24 + +* [#5771](https://github.com/sebastianbergmann/phpunit/issues/5771): JUnit XML logger may crash when test that is run in separate process exits unexpectedly +* [#5819](https://github.com/sebastianbergmann/phpunit/issues/5819): Duplicate keys from different data providers are not handled properly + +## [10.5.19] - 2024-04-17 + +### Fixed + +* [#5818](https://github.com/sebastianbergmann/phpunit/issues/5818): Calling `method()` on a test stub created using `createStubForIntersectionOfInterfaces()` throws an unexpected exception + +## [10.5.18] - 2024-04-14 + +### Deprecated + +* [#5812](https://github.com/sebastianbergmann/phpunit/pull/5812): Support for string array keys in data sets returned by data provider methods that do not match the parameter names of the test method(s) that use(s) them + +### Fixed + +* [#5795](https://github.com/sebastianbergmann/phpunit/issues/5795): Using `@testWith` annotation may generate `PHP Warning: Uninitialized string offset 0` + +## [10.5.17] - 2024-04-05 + +### Changed + +* The namespaces of dependencies are now prefixed with `PHPUnitPHAR` instead of just `PHPUnit` for the PHAR distribution of PHPUnit + +## [10.5.16] - 2024-03-28 + +### Changed + +* [#5766](https://github.com/sebastianbergmann/phpunit/pull/5766): Do not use a shell in `proc_open()` if not really needed +* [#5772](https://github.com/sebastianbergmann/phpunit/pull/5772): Cleanup process handling after dropping temp-file handling + +### Fixed + +* [#5570](https://github.com/sebastianbergmann/phpunit/pull/5570): Windows does not support exclusive locks on stdout + +## [10.5.15] - 2024-03-22 + +### Fixed + +* [#5765](https://github.com/sebastianbergmann/phpunit/pull/5765): Be more forgiving with error handlers that do not respect error suppression + +## [10.5.14] - 2024-03-21 + +### Changed + +* [#5747](https://github.com/sebastianbergmann/phpunit/pull/5747): Cache result of `Groups::groups()` +* [#5748](https://github.com/sebastianbergmann/phpunit/pull/5748): Improve performance of `NamePrettifier::prettifyTestMethodName()` +* [#5750](https://github.com/sebastianbergmann/phpunit/pull/5750): Micro-optimize `NamePrettifier::prettifyTestMethodName()` once again + +### Fixed + +* [#5760](https://github.com/sebastianbergmann/phpunit/issues/5760): TestDox printer does not display details about exceptions raised in before-test methods + +## [10.5.13] - 2024-03-12 + +### Changed + +* [#5727](https://github.com/sebastianbergmann/phpunit/pull/5727): Prevent duplicate call of `NamePrettifier::prettifyTestMethodName()` +* [#5739](https://github.com/sebastianbergmann/phpunit/pull/5739): Micro-optimize `NamePrettifier::prettifyTestMethodName()` +* [#5740](https://github.com/sebastianbergmann/phpunit/pull/5740): Micro-optimize `TestRunner::runTestWithTimeout()` +* [#5741](https://github.com/sebastianbergmann/phpunit/pull/5741): Save call to `Telemetry\System::snapshot()` +* [#5742](https://github.com/sebastianbergmann/phpunit/pull/5742): Prevent file IO when not strictly necessary +* [#5743](https://github.com/sebastianbergmann/phpunit/pull/5743): Prevent unnecessary `ExecutionOrderDependency::getTarget()` call +* [#5744](https://github.com/sebastianbergmann/phpunit/pull/5744): Simplify `NamePrettifier::prettifyTestMethodName()` + +### Fixed + +* [#5351](https://github.com/sebastianbergmann/phpunit/issues/5351): Incorrect code coverage metadata does not prevent code coverage data from being collected +* [#5746](https://github.com/sebastianbergmann/phpunit/issues/5746): Using `-d` CLI option multiple times triggers warning + +## [10.5.12] - 2024-03-09 + +### Fixed + +* [#5652](https://github.com/sebastianbergmann/phpunit/issues/5652): `HRTime::duration()` throws `InvalidArgumentException` + +## [10.5.11] - 2024-02-25 + +### Fixed + +* [#5704](https://github.com/sebastianbergmann/phpunit/issues/5704#issuecomment-1951105254): No warning when CLI options are used multiple times +* [#5707](https://github.com/sebastianbergmann/phpunit/issues/5707): `--fail-on-empty-test-suite` CLI option is not documented in `--help` output +* No warning when the `#[CoversClass]` and `#[UsesClass]` attributes are used with the name of an interface +* Resource usage information is printed when the `--debug` CLI option is used + +## [10.5.10] - 2024-02-04 + +### Changed + +* Improve output of `--check-version` CLI option +* Improve description of `--check-version` CLI option + +### Fixed + +* [#5692](https://github.com/sebastianbergmann/phpunit/issues/5692): `--log-events-text` and `--log-events-verbose-text` require the destination file to exit + +## [10.5.9] - 2024-01-22 + +### Changed + +* Show help for `--manifest`, `--sbom`, and `--composer-lock` when the PHAR is used + +### Fixed + +* [#5676](https://github.com/sebastianbergmann/phpunit/issues/5676): PHPUnit's test runner overwrites custom error handler registered using `set_error_handler()` in bootstrap script + +## [10.5.8] - 2024-01-19 + +### Fixed + +* [#5673](https://github.com/sebastianbergmann/phpunit/issues/5673): Confusing error message when migration of a configuration is requested that does not need to be migrated + +## [10.5.7] - 2024-01-14 + +### Fixed + +* [#5662](https://github.com/sebastianbergmann/phpunit/issues/5662): PHPUnit errors out on startup when the `ctype` extension is not loaded but a polyfill for it was installed + +## [10.5.6] - 2024-01-13 + +### Added + +* Added the `--debug` CLI option as an alias for `--no-output --log-events-text php://stdout` + +### Fixed + +* [#5455](https://github.com/sebastianbergmann/phpunit/issues/5455): `willReturnCallback()` does not pass unknown named variadic arguments to callback +* [#5488](https://github.com/sebastianbergmann/phpunit/issues/5488): Details about tests that are considered risky are not displayed when the TestDox result printer is used +* [#5516](https://github.com/sebastianbergmann/phpunit/issues/5516): Assertions that use the `LogicalNot` constraint (`assertNotEquals()`, `assertStringNotContainsString()`, ...) can generate confusing failure messages +* [#5518](https://github.com/sebastianbergmann/phpunit/issues/5518): Details about deprecations, notices, and warnings are not displayed when the TestDox result printer is used +* [#5574](https://github.com/sebastianbergmann/phpunit/issues/5574): Wrong backtrace line is reported +* [#5633](https://github.com/sebastianbergmann/phpunit/pull/5633): `--log-events-text` and `--log-events-verbose-text` CLI options do not handle absolute and relative paths +* [#5634](https://github.com/sebastianbergmann/phpunit/pull/5634): Exceptions in the destructor of a test double are ignored +* [#5641](https://github.com/sebastianbergmann/phpunit/issues/5641): The `TestSuite` value object returned by `TestSuite\Filtered::testSuite()` contains all tests instead of only the filtered tests + +## [10.5.5] - 2023-12-27 + +### Fixed + +* [#5619](https://github.com/sebastianbergmann/phpunit/pull/5619): Reverted change introduced in PHPUnit 10.5.4 that broke backward compatibility + +## [10.5.4] - 2023-12-27 + +### Fixed + +* [#5592](https://github.com/sebastianbergmann/phpunit/issues/5592): Error Handler prevents `error_get_last()` usage in tests +* [#5592](https://github.com/sebastianbergmann/phpunit/issues/5592): `E_USER_ERROR` does not abort test execution +* [#5612](https://github.com/sebastianbergmann/phpunit/issues/5612): Empty `` element in XML configuration after migrating configuration +* [#5616](https://github.com/sebastianbergmann/phpunit/issues/5616): Values from data provider are not shown for failed test +* [#5619](https://github.com/sebastianbergmann/phpunit/pull/5619): Check and restore error/exception global handlers +* [#5621](https://github.com/sebastianbergmann/phpunit/issues/5621): Name of data set is missing from TeamCity output + +## [10.5.3] - 2023-12-13 + +### Changed + +* Make PHAR build reproducible (the only remaining differences were in the timestamps for the files in the PHAR) + +### Deprecated + +* `Test\AssertionFailed` and `Test\AssertionSucceeded` events +* `PHPUnit\Runner\Extension\Facade::requireExportOfObjects()` and `PHPUnit\Runner\Extension\Facade::requiresExportOfObjects()` +* `registerMockObjectsFromTestArgumentsRecursively` attribute on the `` element of the XML configuration file +* `PHPUnit\TextUI\Configuration\Configuration::registerMockObjectsFromTestArgumentsRecursively()` + +### Fixed + +* [#5614](https://github.com/sebastianbergmann/phpunit/issues/5614): Infinite recursion when data provider provides recursive array + +## [10.5.2] - 2023-12-05 + +### Fixed + +* [#5561](https://github.com/sebastianbergmann/phpunit/issues/5561): JUnit XML logger does not handle assertion failures in before-test methods +* [#5567](https://github.com/sebastianbergmann/phpunit/issues/5567): Infinite recursion when recursive / self-referencing arrays are checked whether they contain only scalar values + +## [10.5.1] - 2023-12-01 + +### Fixed + +* [#5593](https://github.com/sebastianbergmann/phpunit/issues/5593): Return Value Generator fails to correctly create test stub for method with `static` return type declaration when used recursively +* [#5596](https://github.com/sebastianbergmann/phpunit/issues/5596): `PHPUnit\Framework\TestCase` has `@internal` annotation in PHAR + +## [10.5.0] - 2023-12-01 + +### Added + +* [#5532](https://github.com/sebastianbergmann/phpunit/issues/5532): `#[IgnoreDeprecations]` attribute to ignore `E_(USER_)DEPRECATED` issues on test class and test method level +* [#5551](https://github.com/sebastianbergmann/phpunit/issues/5551): Support for omitting parameter default values for `willReturnMap()` +* [#5577](https://github.com/sebastianbergmann/phpunit/issues/5577): `--composer-lock` CLI option for PHAR binary that displays the `composer.lock` used to build the PHAR + +### Changed + +* `MockBuilder::disableAutoReturnValueGeneration()` and `MockBuilder::enableAutoReturnValueGeneration()` are no longer deprecated + +### Fixed + +* [#5563](https://github.com/sebastianbergmann/phpunit/issues/5563): `createMockForIntersectionOfInterfaces()` does not automatically register mock object for expectation verification + +[10.5.38]: https://github.com/sebastianbergmann/phpunit/compare/10.5.37...10.5.38 +[10.5.37]: https://github.com/sebastianbergmann/phpunit/compare/10.5.36...10.5.37 +[10.5.36]: https://github.com/sebastianbergmann/phpunit/compare/10.5.35...10.5.36 +[10.5.35]: https://github.com/sebastianbergmann/phpunit/compare/10.5.34...10.5.35 +[10.5.34]: https://github.com/sebastianbergmann/phpunit/compare/10.5.33...10.5.34 +[10.5.33]: https://github.com/sebastianbergmann/phpunit/compare/10.5.32...10.5.33 +[10.5.32]: https://github.com/sebastianbergmann/phpunit/compare/10.5.31...10.5.32 +[10.5.31]: https://github.com/sebastianbergmann/phpunit/compare/10.5.30...10.5.31 +[10.5.30]: https://github.com/sebastianbergmann/phpunit/compare/10.5.29...10.5.30 +[10.5.29]: https://github.com/sebastianbergmann/phpunit/compare/10.5.28...10.5.29 +[10.5.28]: https://github.com/sebastianbergmann/phpunit/compare/10.5.27...10.5.28 +[10.5.27]: https://github.com/sebastianbergmann/phpunit/compare/10.5.26...10.5.27 +[10.5.26]: https://github.com/sebastianbergmann/phpunit/compare/10.5.25...10.5.26 +[10.5.25]: https://github.com/sebastianbergmann/phpunit/compare/10.5.24...10.5.25 +[10.5.24]: https://github.com/sebastianbergmann/phpunit/compare/10.5.23...10.5.24 +[10.5.23]: https://github.com/sebastianbergmann/phpunit/compare/10.5.22...10.5.23 +[10.5.22]: https://github.com/sebastianbergmann/phpunit/compare/10.5.21...10.5.22 +[10.5.21]: https://github.com/sebastianbergmann/phpunit/compare/10.5.20...10.5.21 +[10.5.20]: https://github.com/sebastianbergmann/phpunit/compare/10.5.19...10.5.20 +[10.5.19]: https://github.com/sebastianbergmann/phpunit/compare/10.5.18...10.5.19 +[10.5.18]: https://github.com/sebastianbergmann/phpunit/compare/10.5.17...10.5.18 +[10.5.17]: https://github.com/sebastianbergmann/phpunit/compare/10.5.16...10.5.17 +[10.5.16]: https://github.com/sebastianbergmann/phpunit/compare/10.5.15...10.5.16 +[10.5.15]: https://github.com/sebastianbergmann/phpunit/compare/10.5.14...10.5.15 +[10.5.14]: https://github.com/sebastianbergmann/phpunit/compare/10.5.13...10.5.14 +[10.5.13]: https://github.com/sebastianbergmann/phpunit/compare/10.5.12...10.5.13 +[10.5.12]: https://github.com/sebastianbergmann/phpunit/compare/10.5.11...10.5.12 +[10.5.11]: https://github.com/sebastianbergmann/phpunit/compare/10.5.10...10.5.11 +[10.5.10]: https://github.com/sebastianbergmann/phpunit/compare/10.5.9...10.5.10 +[10.5.9]: https://github.com/sebastianbergmann/phpunit/compare/10.5.8...10.5.9 +[10.5.8]: https://github.com/sebastianbergmann/phpunit/compare/10.5.7...10.5.8 +[10.5.7]: https://github.com/sebastianbergmann/phpunit/compare/10.5.6...10.5.7 +[10.5.6]: https://github.com/sebastianbergmann/phpunit/compare/10.5.5...10.5.6 +[10.5.5]: https://github.com/sebastianbergmann/phpunit/compare/10.5.4...10.5.5 +[10.5.4]: https://github.com/sebastianbergmann/phpunit/compare/10.5.3...10.5.4 +[10.5.3]: https://github.com/sebastianbergmann/phpunit/compare/10.5.2...10.5.3 +[10.5.2]: https://github.com/sebastianbergmann/phpunit/compare/10.5.1...10.5.2 +[10.5.1]: https://github.com/sebastianbergmann/phpunit/compare/10.5.0...10.5.1 +[10.5.0]: https://github.com/sebastianbergmann/phpunit/compare/10.4.2...10.5.0 diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/DEPRECATIONS.md b/.extlib/simplesamlphp/vendor/phpunit/phpunit/DEPRECATIONS.md new file mode 100644 index 000000000..7fa82a2b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/DEPRECATIONS.md @@ -0,0 +1,92 @@ +# Deprecations + +## Soft Deprecations + +This functionality is currently [soft-deprecated](https://phpunit.de/backward-compatibility.html#soft-deprecation): + +### Writing Tests + +#### Assertions, Constraints, and Expectations + +| Issue | Description | Since | Replacement | +|-------------------------------------------------------------------|------------------------------------------------|--------|-------------| +| [#5472](https://github.com/sebastianbergmann/phpunit/issues/5472) | `TestCase::assertStringNotMatchesFormat()` | 10.4.0 | | +| [#5472](https://github.com/sebastianbergmann/phpunit/issues/5472) | `TestCase::assertStringNotMatchesFormatFile()` | 10.4.0 | | + +#### Test Double API + +| Issue | Description | Since | Replacement | +|-------------------------------------------------------------------|---------------------------------------------------|--------|-----------------------------------------------------------------------------------------| +| [#5240](https://github.com/sebastianbergmann/phpunit/issues/5240) | `TestCase::createTestProxy()` | 10.1.0 | | +| [#5241](https://github.com/sebastianbergmann/phpunit/issues/5241) | `TestCase::getMockForAbstractClass()` | 10.1.0 | | +| [#5242](https://github.com/sebastianbergmann/phpunit/issues/5242) | `TestCase::getMockFromWsdl()` | 10.1.0 | | +| [#5243](https://github.com/sebastianbergmann/phpunit/issues/5243) | `TestCase::getMockForTrait()` | 10.1.0 | | +| [#5244](https://github.com/sebastianbergmann/phpunit/issues/5244) | `TestCase::getObjectForTrait()` | 10.1.0 | | +| [#5305](https://github.com/sebastianbergmann/phpunit/issues/5305) | `MockBuilder::getMockForAbstractClass()` | 10.1.0 | | +| [#5306](https://github.com/sebastianbergmann/phpunit/issues/5306) | `MockBuilder::getMockForTrait()` | 10.1.0 | | +| [#5307](https://github.com/sebastianbergmann/phpunit/issues/5307) | `MockBuilder::disableProxyingToOriginalMethods()` | 10.1.0 | | +| [#5307](https://github.com/sebastianbergmann/phpunit/issues/5307) | `MockBuilder::enableProxyingToOriginalMethods()` | 10.1.0 | | +| [#5307](https://github.com/sebastianbergmann/phpunit/issues/5307) | `MockBuilder::setProxyTarget()` | 10.1.0 | | +| [#5308](https://github.com/sebastianbergmann/phpunit/issues/5308) | `MockBuilder::allowMockingUnknownTypes()` | 10.1.0 | | +| [#5308](https://github.com/sebastianbergmann/phpunit/issues/5308) | `MockBuilder::disallowMockingUnknownTypes()` | 10.1.0 | | +| [#5309](https://github.com/sebastianbergmann/phpunit/issues/5309) | `MockBuilder::disableAutoload()` | 10.1.0 | | +| [#5309](https://github.com/sebastianbergmann/phpunit/issues/5309) | `MockBuilder::enableAutoload()` | 10.1.0 | | +| [#5315](https://github.com/sebastianbergmann/phpunit/issues/5315) | `MockBuilder::disableArgumentCloning()` | 10.1.0 | | +| [#5315](https://github.com/sebastianbergmann/phpunit/issues/5315) | `MockBuilder::enableArgumentCloning()` | 10.1.0 | | +| [#5320](https://github.com/sebastianbergmann/phpunit/issues/5320) | `MockBuilder::addMethods()` | 10.1.0 | | +| [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::onConsecutiveCalls()` | 10.3.0 | Use `$double->willReturn()` instead of `$double->will($this->onConsecutiveCalls())` | +| [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnArgument()` | 10.3.0 | Use `$double->willReturnArgument()` instead of `$double->will($this->returnArgument())` | +| [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnCallback()` | 10.3.0 | Use `$double->willReturnCallback()` instead of `$double->will($this->returnCallback())` | +| [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnSelf()` | 10.3.0 | Use `$double->willReturnSelf()` instead of `$double->will($this->returnSelf())` | +| [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnValue()` | 10.3.0 | Use `$double->willReturn()` instead of `$double->will($this->returnValue())` | +| [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnValueMap()` | 10.3.0 | Use `$double->willReturnMap()` instead of `$double->will($this->returnValueMap())` | + +#### Miscellaneous + +| Issue | Description | Since | Replacement | +|-------------------------------------------------------------------|----------------------------------------------------------------|--------|--------------------------------------------------------------------| +| [#5236](https://github.com/sebastianbergmann/phpunit/issues/5236) | `PHPUnit\Framework\Attributes\CodeCoverageIgnore()` | 10.1.0 | | +| [#5214](https://github.com/sebastianbergmann/phpunit/issues/5214) | `TestCase::iniSet()` | 10.3.0 | | +| [#5216](https://github.com/sebastianbergmann/phpunit/issues/5216) | `TestCase::setLocale()` | 10.3.0 | | +| [#5236](https://github.com/sebastianbergmann/phpunit/issues/5513) | `PHPUnit\Framework\Attributes\IgnoreClassForCodeCoverage()` | 10.4.0 | Use `@codeCoverageIgnore` annotation in the class' doc-comment | +| [#5236](https://github.com/sebastianbergmann/phpunit/issues/5513) | `PHPUnit\Framework\Attributes\IgnoreMethodForCodeCoverage()` | 10.4.0 | Use `@codeCoverageIgnore` annotation in the method's doc-comment | +| [#5236](https://github.com/sebastianbergmann/phpunit/issues/5513) | `PHPUnit\Framework\Attributes\IgnoreFunctionForCodeCoverage()` | 10.4.0 | Use `@codeCoverageIgnore` annotation in the function's doc-comment | + +### Running Tests + +| Issue | Description | Since | Replacement | +|-------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|--------|-------------| +| [#5481](https://github.com/sebastianbergmann/phpunit/issues/5481) | `dataSet` attribute for `testCaseMethod` elements in the XML document generated by `--list-tests-xml` | 10.4.0 | | + +### Extending PHPUnit + +| Issue | Description | Since | Replacement | +|-------|------------------------------------------------------------------------------------------------------------------------------|--------|--------------------------------------------------------------------------------| +| | `PHPUnit\TextUI\Configuration\Configuration::coverageExcludeDirectories()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->excludeDirectories()` | +| | `PHPUnit\TextUI\Configuration\Configuration::coverageExcludeFiles()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->excludeFiles()` | +| | `PHPUnit\TextUI\Configuration\Configuration::coverageIncludeDirectories()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->includeDirectories()` | +| | `PHPUnit\TextUI\Configuration\Configuration::coverageIncludeFiles()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->includeFiles()` | +| | `PHPUnit\TextUI\Configuration\Configuration::loadPharExtensions()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::noExtensions()` | +| | `PHPUnit\TextUI\Configuration\Configuration::hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->notEmpty()` | +| | `PHPUnit\TextUI\Configuration\Configuration::restrictDeprecations()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->restrictDeprecations()` | +| | `PHPUnit\TextUI\Configuration\Configuration::restrictNotices()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->restrictNotices()` | +| | `PHPUnit\TextUI\Configuration\Configuration::restrictWarnings()` | 10.2.0 | `PHPUnit\TextUI\Configuration\Configuration::source()->restrictWarnings()` | +| | `PHPUnit\TextUI\Configuration\Configuration::cliArgument()` | 10.4.0 | `PHPUnit\TextUI\Configuration\Configuration::cliArguments()[0]` | +| | `PHPUnit\TextUI\Configuration\Configuration::hasCliArgument()` | 10.4.0 | `PHPUnit\TextUI\Configuration\Configuration::hasCliArguments()` | +| | `PHPUnit\Framework\Constraint\Constraint::exporter()` | 10.4.0 | | +| | `PHPUnit\TextUI\Configuration\Configuration::registerMockObjectsFromTestArgumentsRecursively()` | 10.5.3 | | +| | `Test\AssertionFailed` and `Test\AssertionSucceeded` events | 10.5.3 | | +| | `PHPUnit\Runner\Extension\Facade::requireExportOfObjects()` and `PHPUnit\Runner\Extension\Facade::requiresExportOfObjects()` | 10.5.3 | | + +## Hard Deprecations + +This functionality is currently [hard-deprecated](https://phpunit.de/backward-compatibility.html#hard-deprecation): + +### Writing Tests + +#### Miscellaneous + +| Issue | Description | Since | Replacement | +|-------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-------------| +| [#5100](https://github.com/sebastianbergmann/phpunit/issues/5100) | Support for non-static data provider methods, non-public data provider methods, and data provider methods that declare parameters | 10.0.0 | | +| [#5812](https://github.com/sebastianbergmann/phpunit/pull/5812) | Support for string array keys in data sets returned by data provider methods that do not match the parameter names of the test method(s) that use(s) them | 10.5.18 | | diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/LICENSE b/.extlib/simplesamlphp/vendor/phpunit/phpunit/LICENSE new file mode 100644 index 000000000..bdb57ec66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2001-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/phpunit/phpunit/README.md b/.extlib/simplesamlphp/vendor/phpunit/phpunit/README.md new file mode 100644 index 000000000..1ca144aeb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/README.md @@ -0,0 +1,34 @@ +# PHPUnit + +[![Latest Stable Version](https://poser.pugx.org/phpunit/phpunit/v)](https://packagist.org/packages/phpunit/phpunit) +[![CI Status](https://github.com/sebastianbergmann/phpunit/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/phpunit/actions) +[![codecov](https://codecov.io/gh/sebastianbergmann/phpunit/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/phpunit) + +PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. + +## Installation + +We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit bundled in a single file: + +```bash +$ wget https://phar.phpunit.de/phpunit-X.Y.phar + +$ php phpunit-X.Y.phar --version +``` + +Please replace `X.Y` with the version of PHPUnit you are interested in. + +Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the [documentation](https://phpunit.de/documentation.html) for details on how to install PHPUnit. + +## Contribute + +Please refer to [CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/main/.github/CONTRIBUTING.md) for information on how to contribute to PHPUnit and its related projects. + +## List of Contributors + +Thanks to everyone who has contributed to PHPUnit! You can find a detailed list of contributors on every PHPUnit related package on GitHub. This list shows only the major components: + +* [PHPUnit](https://github.com/sebastianbergmann/phpunit/graphs/contributors) +* [php-code-coverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) + +A very special thanks to everyone who has contributed to the [documentation](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors). diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/SECURITY.md b/.extlib/simplesamlphp/vendor/phpunit/phpunit/SECURITY.md new file mode 100644 index 000000000..5f55c4194 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/SECURITY.md @@ -0,0 +1,33 @@ +# Security Policy + +If you believe you have found a security vulnerability in PHPUnit, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +PHPUnit is a framework for writing as well as a command-line tool for running tests. Writing and running tests is a development-time activity. There is no reason why PHPUnit should be installed on a webserver and/or in a production environment. + +**If you upload PHPUnit to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +Please note that if you upload PHPUnit to a webserver "bad things" may happen. [You have been warned.](https://thephp.cc/articles/phpunit-a-security-risk?ref=phpunit) + +PHPUnit is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using PHPUnit in an HTTP or web context or with untrusted input data is performed. PHPUnit might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If PHPUnit is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/composer.json b/.extlib/simplesamlphp/vendor/phpunit/phpunit/composer.json new file mode 100644 index 000000000..a9578dca5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/composer.json @@ -0,0 +1,94 @@ +{ + "name": "phpunit/phpunit", + "description": "The PHP Unit Testing framework.", + "type": "library", + "keywords": [ + "phpunit", + "xunit", + "testing" + ], + "homepage": "https://phpunit.de/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.3", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_files" + ], + "files": [ + "tests/unit/Event/AbstractEventTestCase.php", + "tests/unit/Framework/MockObject/TestDoubleTestCase.php", + "tests/unit/Metadata/Parser/AnnotationParserTestCase.php", + "tests/unit/Metadata/Parser/AttributeParserTestCase.php", + "tests/_files/CoverageNamespacedFunctionTest.php", + "tests/_files/CoveredFunction.php", + "tests/_files/Generator.php", + "tests/_files/NamespaceCoveredFunction.php", + "tests/end-to-end/code-coverage/ignore-function-using-attribute/src/CoveredFunction.php" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/composer.lock b/.extlib/simplesamlphp/vendor/phpunit/phpunit/composer.lock new file mode 100644 index 000000000..42e1f0f39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/composer.lock @@ -0,0 +1,1553 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "3f8433322d9a621495cea3e2c0c1723a", + "packages": [ + { + "name": "myclabs/deep-copy", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + }, + "time": "2024-10-08T18:51:32+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.16", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-22T04:31:57+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T06:24:48+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:12:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-18T14:56:07+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:37:17+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:15:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-23T08:47:14+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:17:12+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.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": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T07:19:19+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:38:20+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": ">=8.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*" + }, + "platform-dev": [], + "platform-overrides": { + "php": "8.1.0" + }, + "plugin-api-version": "2.6.0" +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit b/.extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit new file mode 100644 index 000000000..95aaf92d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit @@ -0,0 +1,104 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!version_compare(PHP_VERSION, PHP_VERSION, '=')) { + fwrite( + STDERR, + sprintf( + '%s declares an invalid value for PHP_VERSION.' . PHP_EOL . + 'This breaks fundamental functionality such as version_compare().' . PHP_EOL . + 'Please use a different PHP interpreter.' . PHP_EOL, + + PHP_BINARY + ) + ); + + die(1); +} + +if (version_compare('8.1.0', PHP_VERSION, '>')) { + fwrite( + STDERR, + sprintf( + 'This version of PHPUnit requires PHP >= 8.1.' . PHP_EOL . + 'You are using PHP %s (%s).' . PHP_EOL, + PHP_VERSION, + PHP_BINARY + ) + ); + + die(1); +} + +if (!ini_get('date.timezone')) { + ini_set('date.timezone', 'UTC'); +} + +if (isset($GLOBALS['_composer_autoload_path'])) { + define('PHPUNIT_COMPOSER_INSTALL', $GLOBALS['_composer_autoload_path']); + + unset($GLOBALS['_composer_autoload_path']); +} else { + foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) { + if (file_exists($file)) { + define('PHPUNIT_COMPOSER_INSTALL', $file); + + break; + } + } + + unset($file); +} + +if (!defined('PHPUNIT_COMPOSER_INSTALL')) { + fwrite( + STDERR, + 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL . + ' composer install' . PHP_EOL . PHP_EOL . + 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL + ); + + die(1); +} + +require PHPUNIT_COMPOSER_INSTALL; + +$requiredExtensions = ['dom', 'json', 'libxml', 'mbstring', 'tokenizer', 'xml', 'xmlwriter']; + +$unavailableExtensions = array_filter( + $requiredExtensions, + static function ($extension) { + return !extension_loaded($extension); + } +); + +// Workaround for https://github.com/sebastianbergmann/phpunit/issues/5662 +if (!function_exists('ctype_alnum')) { + $unavailableExtensions[] = 'ctype'; +} + +if ([] !== $unavailableExtensions) { + fwrite( + STDERR, + sprintf( + 'PHPUnit requires the "%s" extensions, but the "%s" %s not available.' . PHP_EOL, + implode('", "', $requiredExtensions), + implode('", "', $unavailableExtensions), + count($unavailableExtensions) === 1 ? 'extension is' : 'extensions are' + ) + ); + + die(1); +} + +unset($requiredExtensions, $unavailableExtensions); + +exit((new PHPUnit\TextUI\Application)->run($_SERVER['argv'])); diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit.xsd new file mode 100644 index 000000000..8fa5451a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/phpunit.xsd @@ -0,0 +1,323 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 10.5 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.0.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.0.xsd new file mode 100644 index 000000000..480d54dec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.0.xsd @@ -0,0 +1,284 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 10.0 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.1.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.1.xsd new file mode 100644 index 000000000..1b190c21b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.1.xsd @@ -0,0 +1,312 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 10.1 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.2.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.2.xsd new file mode 100644 index 000000000..269b7a3ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.2.xsd @@ -0,0 +1,319 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 10.2 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.3.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.3.xsd new file mode 100644 index 000000000..03a54ee0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.3.xsd @@ -0,0 +1,321 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 10.3 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.4.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.4.xsd new file mode 100644 index 000000000..bd22b2ca2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/10.4.xsd @@ -0,0 +1,322 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 10.4 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/8.5.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/8.5.xsd new file mode 100644 index 000000000..75e222894 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/8.5.xsd @@ -0,0 +1,319 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 8.5 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.0.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.0.xsd new file mode 100644 index 000000000..6db04c097 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.0.xsd @@ -0,0 +1,315 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.0 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.1.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.1.xsd new file mode 100644 index 000000000..b10d30b46 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.1.xsd @@ -0,0 +1,317 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.0 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.2.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.2.xsd new file mode 100644 index 000000000..d770e8b03 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.2.xsd @@ -0,0 +1,317 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.2 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.3.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.3.xsd new file mode 100644 index 000000000..638f663ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.3.xsd @@ -0,0 +1,327 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.3 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.4.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.4.xsd new file mode 100644 index 000000000..75a91e832 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.4.xsd @@ -0,0 +1,328 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.4 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.5.xsd b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.5.xsd new file mode 100644 index 000000000..eabefac30 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/schema/9.5.xsd @@ -0,0 +1,330 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 9.5 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.php new file mode 100644 index 000000000..c431b93e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/CollectingDispatcher.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 PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CollectingDispatcher implements Dispatcher +{ + private EventCollection $events; + + public function __construct() + { + $this->events = new EventCollection; + } + + public function dispatch(Event $event): void + { + $this->events->add($event); + } + + public function flush(): EventCollection + { + $events = $this->events; + + $this->events = new EventCollection; + + return $events; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.php new file mode 100644 index 000000000..6895facb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DeferringDispatcher.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 PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DeferringDispatcher implements SubscribableDispatcher +{ + private readonly SubscribableDispatcher $dispatcher; + private EventCollection $events; + private bool $recording = true; + + public function __construct(SubscribableDispatcher $dispatcher) + { + $this->dispatcher = $dispatcher; + $this->events = new EventCollection; + } + + public function registerTracer(Tracer\Tracer $tracer): void + { + $this->dispatcher->registerTracer($tracer); + } + + public function registerSubscriber(Subscriber $subscriber): void + { + $this->dispatcher->registerSubscriber($subscriber); + } + + public function dispatch(Event $event): void + { + if ($this->recording) { + $this->events->add($event); + + return; + } + + $this->dispatcher->dispatch($event); + } + + public function flush(): void + { + $this->recording = false; + + foreach ($this->events as $event) { + $this->dispatcher->dispatch($event); + } + + $this->events = new EventCollection; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php new file mode 100644 index 000000000..8e83d7463 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/DirectDispatcher.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use const PHP_EOL; +use function array_key_exists; +use function dirname; +use function sprintf; +use function str_starts_with; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DirectDispatcher implements SubscribableDispatcher +{ + private readonly TypeMap $typeMap; + + /** + * @psalm-var array> + */ + private array $subscribers = []; + + /** + * @psalm-var list + */ + private array $tracers = []; + + public function __construct(TypeMap $map) + { + $this->typeMap = $map; + } + + public function registerTracer(Tracer\Tracer $tracer): void + { + $this->tracers[] = $tracer; + } + + /** + * @throws MapError + * @throws UnknownSubscriberTypeException + */ + public function registerSubscriber(Subscriber $subscriber): void + { + if (!$this->typeMap->isKnownSubscriberType($subscriber)) { + throw new UnknownSubscriberTypeException( + sprintf( + 'Subscriber "%s" does not implement any known interface - did you forget to register it?', + $subscriber::class, + ), + ); + } + + $eventClassName = $this->typeMap->map($subscriber); + + if (!array_key_exists($eventClassName, $this->subscribers)) { + $this->subscribers[$eventClassName] = []; + } + + $this->subscribers[$eventClassName][] = $subscriber; + } + + /** + * @throws Throwable + * @throws UnknownEventTypeException + */ + public function dispatch(Event $event): void + { + $eventClassName = $event::class; + + if (!$this->typeMap->isKnownEventType($event)) { + throw new UnknownEventTypeException( + sprintf( + 'Unknown event type "%s"', + $eventClassName, + ), + ); + } + + foreach ($this->tracers as $tracer) { + try { + $tracer->trace($event); + // @codeCoverageIgnoreStart + } catch (Throwable $t) { + $this->handleThrowable($t); + } + // @codeCoverageIgnoreEnd + } + + if (!array_key_exists($eventClassName, $this->subscribers)) { + return; + } + + foreach ($this->subscribers[$eventClassName] as $subscriber) { + try { + $subscriber->notify($event); + } catch (Throwable $t) { + $this->handleThrowable($t); + } + } + } + + /** + * @throws Throwable + */ + public function handleThrowable(Throwable $t): void + { + if ($this->isThrowableFromThirdPartySubscriber($t)) { + Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Exception in third-party event subscriber: %s%s%s', + $t->getMessage(), + PHP_EOL, + $t->getTraceAsString(), + ), + ); + + return; + } + + // @codeCoverageIgnoreStart + throw $t; + // @codeCoverageIgnoreEnd + } + + private function isThrowableFromThirdPartySubscriber(Throwable $t): bool + { + return !str_starts_with($t->getFile(), dirname(__DIR__, 2)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php new file mode 100644 index 000000000..e70865395 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/Dispatcher.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Dispatcher +{ + /** + * @throws UnknownEventTypeException + */ + public function dispatch(Event $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php new file mode 100644 index 000000000..c4393da12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Dispatcher/SubscribableDispatcher.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface SubscribableDispatcher extends Dispatcher +{ + /** + * @throws UnknownSubscriberTypeException + */ + public function registerSubscriber(Subscriber $subscriber): void; + + public function registerTracer(Tracer\Tracer $tracer): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php new file mode 100644 index 000000000..07528570f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/DispatchingEmitter.php @@ -0,0 +1,1230 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use PHPUnit\Event\Code\ClassMethod; +use PHPUnit\Event\Code\ComparisonFailure; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Test\DataProviderMethodCalled; +use PHPUnit\Event\Test\DataProviderMethodFinished; +use PHPUnit\Event\TestSuite\Filtered as TestSuiteFiltered; +use PHPUnit\Event\TestSuite\Finished as TestSuiteFinished; +use PHPUnit\Event\TestSuite\Loaded as TestSuiteLoaded; +use PHPUnit\Event\TestSuite\Skipped as TestSuiteSkipped; +use PHPUnit\Event\TestSuite\Sorted as TestSuiteSorted; +use PHPUnit\Event\TestSuite\Started as TestSuiteStarted; +use PHPUnit\Event\TestSuite\TestSuite; +use PHPUnit\Framework\Constraint; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DispatchingEmitter implements Emitter +{ + private readonly Dispatcher $dispatcher; + private readonly Telemetry\System $system; + private readonly Telemetry\Snapshot $startSnapshot; + private Telemetry\Snapshot $previousSnapshot; + private bool $exportObjects = false; + + public function __construct(Dispatcher $dispatcher, Telemetry\System $system) + { + $this->dispatcher = $dispatcher; + $this->system = $system; + + $this->startSnapshot = $system->snapshot(); + $this->previousSnapshot = $this->startSnapshot; + } + + /** + * @deprecated + */ + public function exportObjects(): void + { + $this->exportObjects = true; + } + + /** + * @deprecated + */ + public function exportsObjects(): bool + { + return $this->exportObjects; + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function applicationStarted(): void + { + $this->dispatcher->dispatch( + new Application\Started( + $this->telemetryInfo(), + new Runtime\Runtime, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerStarted(): void + { + $this->dispatcher->dispatch( + new TestRunner\Started( + $this->telemetryInfo(), + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerConfigured(Configuration $configuration): void + { + $this->dispatcher->dispatch( + new TestRunner\Configured( + $this->telemetryInfo(), + $configuration, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerBootstrapFinished(string $filename): void + { + $this->dispatcher->dispatch( + new TestRunner\BootstrapFinished( + $this->telemetryInfo(), + $filename, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerLoadedExtensionFromPhar(string $filename, string $name, string $version): void + { + $this->dispatcher->dispatch( + new TestRunner\ExtensionLoadedFromPhar( + $this->telemetryInfo(), + $filename, + $name, + $version, + ), + ); + } + + /** + * @psalm-param class-string $className + * @psalm-param array $parameters + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerBootstrappedExtension(string $className, array $parameters): void + { + $this->dispatcher->dispatch( + new TestRunner\ExtensionBootstrapped( + $this->telemetryInfo(), + $className, + $parameters, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function dataProviderMethodCalled(ClassMethod $testMethod, ClassMethod $dataProviderMethod): void + { + $this->dispatcher->dispatch( + new DataProviderMethodCalled( + $this->telemetryInfo(), + $testMethod, + $dataProviderMethod, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function dataProviderMethodFinished(ClassMethod $testMethod, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new DataProviderMethodFinished( + $this->telemetryInfo(), + $testMethod, + ...$calledMethods, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSuiteLoaded(TestSuite $testSuite): void + { + $this->dispatcher->dispatch( + new TestSuiteLoaded( + $this->telemetryInfo(), + $testSuite, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSuiteFiltered(TestSuite $testSuite): void + { + $this->dispatcher->dispatch( + new TestSuiteFiltered( + $this->telemetryInfo(), + $testSuite, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSuiteSorted(int $executionOrder, int $executionOrderDefects, bool $resolveDependencies): void + { + $this->dispatcher->dispatch( + new TestSuiteSorted( + $this->telemetryInfo(), + $executionOrder, + $executionOrderDefects, + $resolveDependencies, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerEventFacadeSealed(): void + { + $this->dispatcher->dispatch( + new TestRunner\EventFacadeSealed( + $this->telemetryInfo(), + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerExecutionStarted(TestSuite $testSuite): void + { + $this->dispatcher->dispatch( + new TestRunner\ExecutionStarted( + $this->telemetryInfo(), + $testSuite, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerDisabledGarbageCollection(): void + { + $this->dispatcher->dispatch( + new TestRunner\GarbageCollectionDisabled($this->telemetryInfo()), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerTriggeredGarbageCollection(): void + { + $this->dispatcher->dispatch( + new TestRunner\GarbageCollectionTriggered($this->telemetryInfo()), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSuiteSkipped(TestSuite $testSuite, string $message): void + { + $this->dispatcher->dispatch( + new TestSuiteSkipped( + $this->telemetryInfo(), + $testSuite, + $message, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSuiteStarted(TestSuite $testSuite): void + { + $this->dispatcher->dispatch( + new TestSuiteStarted( + $this->telemetryInfo(), + $testSuite, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPreparationStarted(Code\Test $test): void + { + $this->dispatcher->dispatch( + new Test\PreparationStarted( + $this->telemetryInfo(), + $test, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPreparationFailed(Code\Test $test): void + { + $this->dispatcher->dispatch( + new Test\PreparationFailed( + $this->telemetryInfo(), + $test, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testBeforeFirstTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void + { + $this->dispatcher->dispatch( + new Test\BeforeFirstTestMethodCalled( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testBeforeFirstTestMethodErrored(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void + { + $this->dispatcher->dispatch( + new Test\BeforeFirstTestMethodErrored( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + $throwable, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testBeforeFirstTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new Test\BeforeFirstTestMethodFinished( + $this->telemetryInfo(), + $testClassName, + ...$calledMethods, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testBeforeTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void + { + $this->dispatcher->dispatch( + new Test\BeforeTestMethodCalled( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testBeforeTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new Test\BeforeTestMethodFinished( + $this->telemetryInfo(), + $testClassName, + ...$calledMethods, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPreConditionCalled(string $testClassName, ClassMethod $calledMethod): void + { + $this->dispatcher->dispatch( + new Test\PreConditionCalled( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPreConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new Test\PreConditionFinished( + $this->telemetryInfo(), + $testClassName, + ...$calledMethods, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPrepared(Code\Test $test): void + { + $this->dispatcher->dispatch( + new Test\Prepared( + $this->telemetryInfo(), + $test, + ), + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRegisteredComparator(string $className): void + { + $this->dispatcher->dispatch( + new Test\ComparatorRegistered( + $this->telemetryInfo(), + $className, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + * + * @deprecated + */ + public function testAssertionSucceeded(mixed $value, Constraint\Constraint $constraint, string $message): void + { + $this->dispatcher->dispatch( + new Test\AssertionSucceeded( + $this->telemetryInfo(), + Exporter::export($value, $this->exportObjects), + $constraint->toString($this->exportObjects), + $constraint->count(), + $message, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + * + * @deprecated + */ + public function testAssertionFailed(mixed $value, Constraint\Constraint $constraint, string $message): void + { + $this->dispatcher->dispatch( + new Test\AssertionFailed( + $this->telemetryInfo(), + Exporter::export($value, $this->exportObjects), + $constraint->toString($this->exportObjects), + $constraint->count(), + $message, + ), + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedMockObject(string $className): void + { + $this->dispatcher->dispatch( + new Test\MockObjectCreated( + $this->telemetryInfo(), + $className, + ), + ); + } + + /** + * @psalm-param list $interfaces + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedMockObjectForIntersectionOfInterfaces(array $interfaces): void + { + $this->dispatcher->dispatch( + new Test\MockObjectForIntersectionOfInterfacesCreated( + $this->telemetryInfo(), + $interfaces, + ), + ); + } + + /** + * @psalm-param trait-string $traitName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedMockObjectForTrait(string $traitName): void + { + $this->dispatcher->dispatch( + new Test\MockObjectForTraitCreated( + $this->telemetryInfo(), + $traitName, + ), + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedMockObjectForAbstractClass(string $className): void + { + $this->dispatcher->dispatch( + new Test\MockObjectForAbstractClassCreated( + $this->telemetryInfo(), + $className, + ), + ); + } + + /** + * @psalm-param class-string $originalClassName + * @psalm-param class-string $mockClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedMockObjectFromWsdl(string $wsdlFile, string $originalClassName, string $mockClassName, array $methods, bool $callOriginalConstructor, array $options): void + { + $this->dispatcher->dispatch( + new Test\MockObjectFromWsdlCreated( + $this->telemetryInfo(), + $wsdlFile, + $originalClassName, + $mockClassName, + $methods, + $callOriginalConstructor, + $options, + ), + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedPartialMockObject(string $className, string ...$methodNames): void + { + $this->dispatcher->dispatch( + new Test\PartialMockObjectCreated( + $this->telemetryInfo(), + $className, + ...$methodNames, + ), + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedTestProxy(string $className, array $constructorArguments): void + { + $this->dispatcher->dispatch( + new Test\TestProxyCreated( + $this->telemetryInfo(), + $className, + Exporter::export($constructorArguments, $this->exportObjects), + ), + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedStub(string $className): void + { + $this->dispatcher->dispatch( + new Test\TestStubCreated( + $this->telemetryInfo(), + $className, + ), + ); + } + + /** + * @psalm-param list $interfaces + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testCreatedStubForIntersectionOfInterfaces(array $interfaces): void + { + $this->dispatcher->dispatch( + new Test\TestStubForIntersectionOfInterfacesCreated( + $this->telemetryInfo(), + $interfaces, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testErrored(Code\Test $test, Throwable $throwable): void + { + $this->dispatcher->dispatch( + new Test\Errored( + $this->telemetryInfo(), + $test, + $throwable, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testFailed(Code\Test $test, Throwable $throwable, ?ComparisonFailure $comparisonFailure): void + { + $this->dispatcher->dispatch( + new Test\Failed( + $this->telemetryInfo(), + $test, + $throwable, + $comparisonFailure, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPassed(Code\Test $test): void + { + $this->dispatcher->dispatch( + new Test\Passed( + $this->telemetryInfo(), + $test, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testConsideredRisky(Code\Test $test, string $message): void + { + $this->dispatcher->dispatch( + new Test\ConsideredRisky( + $this->telemetryInfo(), + $test, + $message, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testMarkedAsIncomplete(Code\Test $test, Throwable $throwable): void + { + $this->dispatcher->dispatch( + new Test\MarkedIncomplete( + $this->telemetryInfo(), + $test, + $throwable, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSkipped(Code\Test $test, string $message): void + { + $this->dispatcher->dispatch( + new Test\Skipped( + $this->telemetryInfo(), + $test, + $message, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredPhpunitDeprecation(Code\Test $test, string $message): void + { + $this->dispatcher->dispatch( + new Test\PhpunitDeprecationTriggered( + $this->telemetryInfo(), + $test, + $message, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredPhpDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest): void + { + $this->dispatcher->dispatch( + new Test\PhpDeprecationTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + $ignoredByBaseline, + $ignoredByTest, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest): void + { + $this->dispatcher->dispatch( + new Test\DeprecationTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + $ignoredByBaseline, + $ignoredByTest, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredError(Code\Test $test, string $message, string $file, int $line, bool $suppressed): void + { + $this->dispatcher->dispatch( + new Test\ErrorTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void + { + $this->dispatcher->dispatch( + new Test\NoticeTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + $ignoredByBaseline, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredPhpNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void + { + $this->dispatcher->dispatch( + new Test\PhpNoticeTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + $ignoredByBaseline, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void + { + $this->dispatcher->dispatch( + new Test\WarningTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + $ignoredByBaseline, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredPhpWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void + { + $this->dispatcher->dispatch( + new Test\PhpWarningTriggered( + $this->telemetryInfo(), + $test, + $message, + $file, + $line, + $suppressed, + $ignoredByBaseline, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredPhpunitError(Code\Test $test, string $message): void + { + $this->dispatcher->dispatch( + new Test\PhpunitErrorTriggered( + $this->telemetryInfo(), + $test, + $message, + ), + ); + } + + /** + * @psalm-param non-empty-string $message + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testTriggeredPhpunitWarning(Code\Test $test, string $message): void + { + $this->dispatcher->dispatch( + new Test\PhpunitWarningTriggered( + $this->telemetryInfo(), + $test, + $message, + ), + ); + } + + /** + * @psalm-param non-empty-string $output + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPrintedUnexpectedOutput(string $output): void + { + $this->dispatcher->dispatch( + new Test\PrintedUnexpectedOutput( + $this->telemetryInfo(), + $output, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testFinished(Code\Test $test, int $numberOfAssertionsPerformed): void + { + $this->dispatcher->dispatch( + new Test\Finished( + $this->telemetryInfo(), + $test, + $numberOfAssertionsPerformed, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPostConditionCalled(string $testClassName, ClassMethod $calledMethod): void + { + $this->dispatcher->dispatch( + new Test\PostConditionCalled( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testPostConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new Test\PostConditionFinished( + $this->telemetryInfo(), + $testClassName, + ...$calledMethods, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testAfterTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void + { + $this->dispatcher->dispatch( + new Test\AfterTestMethodCalled( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testAfterTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new Test\AfterTestMethodFinished( + $this->telemetryInfo(), + $testClassName, + ...$calledMethods, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testAfterLastTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void + { + $this->dispatcher->dispatch( + new Test\AfterLastTestMethodCalled( + $this->telemetryInfo(), + $testClassName, + $calledMethod, + ), + ); + } + + /** + * @psalm-param class-string $testClassName + * + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testAfterLastTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void + { + $this->dispatcher->dispatch( + new Test\AfterLastTestMethodFinished( + $this->telemetryInfo(), + $testClassName, + ...$calledMethods, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testSuiteFinished(TestSuite $testSuite): void + { + $this->dispatcher->dispatch( + new TestSuiteFinished( + $this->telemetryInfo(), + $testSuite, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerTriggeredDeprecation(string $message): void + { + $this->dispatcher->dispatch( + new TestRunner\DeprecationTriggered( + $this->telemetryInfo(), + $message, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerTriggeredWarning(string $message): void + { + $this->dispatcher->dispatch( + new TestRunner\WarningTriggered( + $this->telemetryInfo(), + $message, + ), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerEnabledGarbageCollection(): void + { + $this->dispatcher->dispatch( + new TestRunner\GarbageCollectionEnabled($this->telemetryInfo()), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerExecutionAborted(): void + { + $this->dispatcher->dispatch( + new TestRunner\ExecutionAborted($this->telemetryInfo()), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerExecutionFinished(): void + { + $this->dispatcher->dispatch( + new TestRunner\ExecutionFinished($this->telemetryInfo()), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function testRunnerFinished(): void + { + $this->dispatcher->dispatch( + new TestRunner\Finished($this->telemetryInfo()), + ); + } + + /** + * @throws InvalidArgumentException + * @throws UnknownEventTypeException + */ + public function applicationFinished(int $shellExitCode): void + { + $this->dispatcher->dispatch( + new Application\Finished( + $this->telemetryInfo(), + $shellExitCode, + ), + ); + } + + /** + * @throws InvalidArgumentException + */ + private function telemetryInfo(): Telemetry\Info + { + $current = $this->system->snapshot(); + + $info = new Telemetry\Info( + $current, + $current->time()->duration($this->startSnapshot->time()), + $current->memoryUsage()->diff($this->startSnapshot->memoryUsage()), + $current->time()->duration($this->previousSnapshot->time()), + $current->memoryUsage()->diff($this->previousSnapshot->memoryUsage()), + ); + + $this->previousSnapshot = $current; + + return $info; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/Emitter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/Emitter.php new file mode 100644 index 000000000..c66cbdc06 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Emitter/Emitter.php @@ -0,0 +1,310 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use PHPUnit\Event\Code\ClassMethod; +use PHPUnit\Event\Code\ComparisonFailure; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\TestSuite\TestSuite; +use PHPUnit\Framework\Constraint; +use PHPUnit\TextUI\Configuration\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Emitter +{ + /** + * @deprecated + */ + public function exportObjects(): void; + + /** + * @deprecated + */ + public function exportsObjects(): bool; + + public function applicationStarted(): void; + + public function testRunnerStarted(): void; + + public function testRunnerConfigured(Configuration $configuration): void; + + public function testRunnerBootstrapFinished(string $filename): void; + + public function testRunnerLoadedExtensionFromPhar(string $filename, string $name, string $version): void; + + /** + * @psalm-param class-string $className + * @psalm-param array $parameters + */ + public function testRunnerBootstrappedExtension(string $className, array $parameters): void; + + public function dataProviderMethodCalled(ClassMethod $testMethod, ClassMethod $dataProviderMethod): void; + + public function dataProviderMethodFinished(ClassMethod $testMethod, ClassMethod ...$calledMethods): void; + + public function testSuiteLoaded(TestSuite $testSuite): void; + + public function testSuiteFiltered(TestSuite $testSuite): void; + + public function testSuiteSorted(int $executionOrder, int $executionOrderDefects, bool $resolveDependencies): void; + + public function testRunnerEventFacadeSealed(): void; + + public function testRunnerExecutionStarted(TestSuite $testSuite): void; + + public function testRunnerDisabledGarbageCollection(): void; + + public function testRunnerTriggeredGarbageCollection(): void; + + public function testSuiteSkipped(TestSuite $testSuite, string $message): void; + + public function testSuiteStarted(TestSuite $testSuite): void; + + public function testPreparationStarted(Code\Test $test): void; + + public function testPreparationFailed(Code\Test $test): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testBeforeFirstTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testBeforeFirstTestMethodErrored(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testBeforeFirstTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testBeforeTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testBeforeTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testPreConditionCalled(string $testClassName, ClassMethod $calledMethod): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testPreConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void; + + public function testPrepared(Code\Test $test): void; + + /** + * @psalm-param class-string $className + */ + public function testRegisteredComparator(string $className): void; + + /** + * @deprecated + */ + public function testAssertionSucceeded(mixed $value, Constraint\Constraint $constraint, string $message): void; + + /** + * @deprecated + */ + public function testAssertionFailed(mixed $value, Constraint\Constraint $constraint, string $message): void; + + /** + * @psalm-param class-string $className + */ + public function testCreatedMockObject(string $className): void; + + /** + * @psalm-param list $interfaces + */ + public function testCreatedMockObjectForIntersectionOfInterfaces(array $interfaces): void; + + /** + * @psalm-param trait-string $traitName + */ + public function testCreatedMockObjectForTrait(string $traitName): void; + + /** + * @psalm-param class-string $className + */ + public function testCreatedMockObjectForAbstractClass(string $className): void; + + /** + * @psalm-param class-string $originalClassName + * @psalm-param class-string $mockClassName + */ + public function testCreatedMockObjectFromWsdl(string $wsdlFile, string $originalClassName, string $mockClassName, array $methods, bool $callOriginalConstructor, array $options): void; + + /** + * @psalm-param class-string $className + */ + public function testCreatedPartialMockObject(string $className, string ...$methodNames): void; + + /** + * @psalm-param class-string $className + */ + public function testCreatedTestProxy(string $className, array $constructorArguments): void; + + /** + * @psalm-param class-string $className + */ + public function testCreatedStub(string $className): void; + + /** + * @psalm-param list $interfaces + */ + public function testCreatedStubForIntersectionOfInterfaces(array $interfaces): void; + + public function testErrored(Code\Test $test, Throwable $throwable): void; + + public function testFailed(Code\Test $test, Throwable $throwable, ?ComparisonFailure $comparisonFailure): void; + + public function testPassed(Code\Test $test): void; + + /** + * @psalm-param non-empty-string $message + */ + public function testConsideredRisky(Code\Test $test, string $message): void; + + public function testMarkedAsIncomplete(Code\Test $test, Throwable $throwable): void; + + /** + * @psalm-param non-empty-string $message + */ + public function testSkipped(Code\Test $test, string $message): void; + + /** + * @psalm-param non-empty-string $message + */ + public function testTriggeredPhpunitDeprecation(Code\Test $test, string $message): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredPhpDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredError(Code\Test $test, string $message, string $file, int $line, bool $suppressed): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredPhpNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function testTriggeredPhpWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; + + /** + * @psalm-param non-empty-string $message + */ + public function testTriggeredPhpunitError(Code\Test $test, string $message): void; + + /** + * @psalm-param non-empty-string $message + */ + public function testTriggeredPhpunitWarning(Code\Test $test, string $message): void; + + /** + * @psalm-param non-empty-string $output + */ + public function testPrintedUnexpectedOutput(string $output): void; + + public function testFinished(Code\Test $test, int $numberOfAssertionsPerformed): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testPostConditionCalled(string $testClassName, ClassMethod $calledMethod): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testPostConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testAfterTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testAfterTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testAfterLastTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; + + /** + * @psalm-param class-string $testClassName + */ + public function testAfterLastTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; + + public function testSuiteFinished(TestSuite $testSuite): void; + + public function testRunnerTriggeredDeprecation(string $message): void; + + public function testRunnerTriggeredWarning(string $message): void; + + public function testRunnerEnabledGarbageCollection(): void; + + public function testRunnerExecutionAborted(): void; + + public function testRunnerExecutionFinished(): void; + + public function testRunnerFinished(): void; + + public function applicationFinished(int $shellExitCode): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Finished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Finished.php new file mode 100644 index 000000000..e196c4f6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Finished.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Application; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Finished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly int $shellExitCode; + + public function __construct(Telemetry\Info $telemetryInfo, int $shellExitCode) + { + $this->telemetryInfo = $telemetryInfo; + $this->shellExitCode = $shellExitCode; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function shellExitCode(): int + { + return $this->shellExitCode; + } + + public function asString(): string + { + return sprintf( + 'PHPUnit Finished (Shell Exit Code: %d)', + $this->shellExitCode, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php new file mode 100644 index 000000000..1e7597761 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/FinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Application; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface FinishedSubscriber extends Subscriber +{ + public function notify(Finished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Started.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Started.php new file mode 100644 index 000000000..da570a027 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/Started.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Application; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Runtime\Runtime; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Started implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Runtime $runtime; + + public function __construct(Telemetry\Info $telemetryInfo, Runtime $runtime) + { + $this->telemetryInfo = $telemetryInfo; + $this->runtime = $runtime; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function runtime(): Runtime + { + return $this->runtime; + } + + public function asString(): string + { + return sprintf( + 'PHPUnit Started (%s)', + $this->runtime->asString(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php new file mode 100644 index 000000000..f2ebee2fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Application/StartedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Application; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface StartedSubscriber extends Subscriber +{ + public function notify(Started $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Event.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Event.php new file mode 100644 index 000000000..8aa014b0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Event.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Event +{ + public function telemetryInfo(): Telemetry\Info; + + public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollection.php new file mode 100644 index 000000000..ecefb3763 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollection.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class EventCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private array $events = []; + + public function add(Event ...$events): void + { + foreach ($events as $event) { + $this->events[] = $event; + } + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->events; + } + + public function count(): int + { + return count($this->events); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } + + public function isNotEmpty(): bool + { + return $this->count() > 0; + } + + public function getIterator(): EventCollectionIterator + { + return new EventCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php new file mode 100644 index 000000000..7a09fa405 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/EventCollectionIterator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use function count; +use Iterator; + +/** + * @template-implements Iterator + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class EventCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private readonly array $events; + private int $position = 0; + + public function __construct(EventCollection $events) + { + $this->events = $events->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->events); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Event + { + return $this->events[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php new file mode 100644 index 000000000..68954f207 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailed.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +final class AssertionFailed implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $value; + private readonly string $constraint; + private readonly int $count; + private readonly string $message; + + public function __construct(Telemetry\Info $telemetryInfo, string $value, string $constraint, int $count, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->value = $value; + $this->constraint = $constraint; + $this->count = $count; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function value(): string + { + return $this->value; + } + + public function count(): int + { + return $this->count; + } + + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + $message = ''; + + if (!empty($this->message)) { + $message = sprintf( + ', Message: %s', + $this->message, + ); + } + + return sprintf( + 'Assertion Failed (Constraint: %s, Value: %s%s)', + $this->constraint, + $this->value, + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php new file mode 100644 index 000000000..c569bcc22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionFailedSubscriber.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +interface AssertionFailedSubscriber extends Subscriber +{ + public function notify(AssertionFailed $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php new file mode 100644 index 000000000..d4f854841 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceeded.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +final class AssertionSucceeded implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $value; + private readonly string $constraint; + private readonly int $count; + private readonly string $message; + + public function __construct(Telemetry\Info $telemetryInfo, string $value, string $constraint, int $count, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->value = $value; + $this->constraint = $constraint; + $this->count = $count; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function value(): string + { + return $this->value; + } + + public function count(): int + { + return $this->count; + } + + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + $message = ''; + + if (!empty($this->message)) { + $message = sprintf( + ', Message: %s', + $this->message, + ); + } + + return sprintf( + 'Assertion Succeeded (Constraint: %s, Value: %s%s)', + $this->constraint, + $this->value, + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php new file mode 100644 index 000000000..59d72c0f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Assertion/AssertionSucceededSubscriber.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +interface AssertionSucceededSubscriber extends Subscriber +{ + public function notify(AssertionSucceeded $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php new file mode 100644 index 000000000..9e83d3d21 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegistered.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ComparatorRegistered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function asString(): string + { + return sprintf( + 'Comparator Registered (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php new file mode 100644 index 000000000..10ba78e4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ComparatorRegisteredSubscriber extends Subscriber +{ + public function notify(ComparatorRegistered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php new file mode 100644 index 000000000..fec2a79e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class AfterLastTestMethodCalled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function asString(): string + { + return sprintf( + 'After Last Test Method Called (%s::%s)', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php new file mode 100644 index 000000000..08530ab7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface AfterLastTestMethodCalledSubscriber extends Subscriber +{ + public function notify(AfterLastTestMethodCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php new file mode 100644 index 000000000..40a6c9fcc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class AfterLastTestMethodFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = 'After Last Test Method Finished:'; + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php new file mode 100644 index 000000000..0a366b0d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface AfterLastTestMethodFinishedSubscriber extends Subscriber +{ + public function notify(AfterLastTestMethodFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php new file mode 100644 index 000000000..52afc14c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class AfterTestMethodCalled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function asString(): string + { + return sprintf( + 'After Test Method Called (%s::%s)', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php new file mode 100644 index 000000000..3e72fc91c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface AfterTestMethodCalledSubscriber extends Subscriber +{ + public function notify(AfterTestMethodCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php new file mode 100644 index 000000000..e934eea84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class AfterTestMethodFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = 'After Test Method Finished:'; + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php new file mode 100644 index 000000000..5e5668898 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface AfterTestMethodFinishedSubscriber extends Subscriber +{ + public function notify(AfterTestMethodFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php new file mode 100644 index 000000000..da28f2bf2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeFirstTestMethodCalled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function asString(): string + { + return sprintf( + 'Before First Test Method Called (%s::%s)', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php new file mode 100644 index 000000000..a0d4281ff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface BeforeFirstTestMethodCalledSubscriber extends Subscriber +{ + public function notify(BeforeFirstTestMethodCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php new file mode 100644 index 000000000..959b1350d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeFirstTestMethodErrored implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + private readonly Throwable $throwable; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod, Throwable $throwable) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + $this->throwable = $throwable; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function throwable(): Throwable + { + return $this->throwable; + } + + public function asString(): string + { + $message = $this->throwable->message(); + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Before First Test Method Errored (%s::%s)%s', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php new file mode 100644 index 000000000..9a1b87542 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface BeforeFirstTestMethodErroredSubscriber extends Subscriber +{ + public function notify(BeforeFirstTestMethodErrored $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php new file mode 100644 index 000000000..fba563d71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeFirstTestMethodFinished implements Event +{ + private readonly Telemetry\Info$telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = 'Before First Test Method Finished:'; + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php new file mode 100644 index 000000000..c9f180641 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface BeforeFirstTestMethodFinishedSubscriber extends Subscriber +{ + public function notify(BeforeFirstTestMethodFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php new file mode 100644 index 000000000..3b300fa30 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeTestMethodCalled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function asString(): string + { + return sprintf( + 'Before Test Method Called (%s::%s)', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php new file mode 100644 index 000000000..5f4e180e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface BeforeTestMethodCalledSubscriber extends Subscriber +{ + public function notify(BeforeTestMethodCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php new file mode 100644 index 000000000..f84b51bb0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeTestMethodFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = 'Before Test Method Finished:'; + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php new file mode 100644 index 000000000..2a6c758ca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface BeforeTestMethodFinishedSubscriber extends Subscriber +{ + public function notify(BeforeTestMethodFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php new file mode 100644 index 000000000..e7b6c435b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PostConditionCalled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function asString(): string + { + return sprintf( + 'Post Condition Method Called (%s::%s)', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php new file mode 100644 index 000000000..2c135f504 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PostConditionCalledSubscriber extends Subscriber +{ + public function notify(PostConditionCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php new file mode 100644 index 000000000..fff07ce7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PostConditionFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = 'Post Condition Method Finished:'; + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php new file mode 100644 index 000000000..f24d94800 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PostConditionFinishedSubscriber extends Subscriber +{ + public function notify(PostConditionFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php new file mode 100644 index 000000000..93752546a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PreConditionCalled implements Event +{ + private readonly Telemetry\Info$telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + private readonly Code\ClassMethod $calledMethod; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethod = $calledMethod; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + public function calledMethod(): Code\ClassMethod + { + return $this->calledMethod; + } + + public function asString(): string + { + return sprintf( + 'Pre Condition Method Called (%s::%s)', + $this->calledMethod->className(), + $this->calledMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php new file mode 100644 index 000000000..431dfcc40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PreConditionCalledSubscriber extends Subscriber +{ + public function notify(PreConditionCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php new file mode 100644 index 000000000..05340796c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PreConditionFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $testClassName; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + /** + * @psalm-param class-string $testClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testClassName = $testClassName; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function testClassName(): string + { + return $this->testClassName; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = 'Pre Condition Method Finished:'; + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php new file mode 100644 index 000000000..9c499407e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PreConditionFinishedSubscriber extends Subscriber +{ + public function notify(PreConditionFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php new file mode 100644 index 000000000..5b90d1bf9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ConsideredRisky implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-param non-empty-string $message + */ + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + return sprintf( + 'Test Considered Risky (%s)%s%s', + $this->test->id(), + PHP_EOL, + $this->message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php new file mode 100644 index 000000000..a0c714a91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ConsideredRiskySubscriber extends Subscriber +{ + public function notify(ConsideredRisky $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php new file mode 100644 index 000000000..d4d495da2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DeprecationTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + private readonly bool $ignoredByBaseline; + private readonly bool $ignoredByTest; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + $this->ignoredByBaseline = $ignoredByBaseline; + $this->ignoredByTest = $ignoredByTest; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function ignoredByBaseline(): bool + { + return $this->ignoredByBaseline; + } + + public function ignoredByTest(): bool + { + return $this->ignoredByTest; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + $status = ''; + + if ($this->ignoredByTest) { + $status = 'Test-Ignored '; + } elseif ($this->ignoredByBaseline) { + $status = 'Baseline-Ignored '; + } elseif ($this->suppressed) { + $status = 'Suppressed '; + } + + return sprintf( + 'Test Triggered %sDeprecation (%s)%s', + $status, + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php new file mode 100644 index 000000000..e166dbed9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface DeprecationTriggeredSubscriber extends Subscriber +{ + public function notify(DeprecationTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php new file mode 100644 index 000000000..0407c0b70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggered.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 PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ErrorTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Triggered %sError (%s)%s', + $this->wasSuppressed() ? 'Suppressed ' : '', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php new file mode 100644 index 000000000..901d88556 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ErrorTriggeredSubscriber extends Subscriber +{ + public function notify(ErrorTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php new file mode 100644 index 000000000..d8a27bbd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class NoticeTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + private readonly bool $ignoredByBaseline; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + $this->ignoredByBaseline = $ignoredByBaseline; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function ignoredByBaseline(): bool + { + return $this->ignoredByBaseline; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + $status = ''; + + if ($this->ignoredByBaseline) { + $status = 'Baseline-Ignored '; + } elseif ($this->suppressed) { + $status = 'Suppressed '; + } + + return sprintf( + 'Test Triggered %sNotice (%s)%s', + $status, + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php new file mode 100644 index 000000000..95230d0ff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface NoticeTriggeredSubscriber extends Subscriber +{ + public function notify(NoticeTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php new file mode 100644 index 000000000..9c93fd42d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PhpDeprecationTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + private readonly bool $ignoredByBaseline; + private readonly bool $ignoredByTest; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + $this->ignoredByBaseline = $ignoredByBaseline; + $this->ignoredByTest = $ignoredByTest; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function ignoredByBaseline(): bool + { + return $this->ignoredByBaseline; + } + + public function ignoredByTest(): bool + { + return $this->ignoredByTest; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + $status = ''; + + if ($this->ignoredByTest) { + $status = 'Test-Ignored '; + } elseif ($this->ignoredByBaseline) { + $status = 'Baseline-Ignored '; + } elseif ($this->suppressed) { + $status = 'Suppressed '; + } + + return sprintf( + 'Test Triggered %sPHP Deprecation (%s)%s', + $status, + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php new file mode 100644 index 000000000..06159a7ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PhpDeprecationTriggeredSubscriber extends Subscriber +{ + public function notify(PhpDeprecationTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php new file mode 100644 index 000000000..f03d0ba9e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PhpNoticeTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + private readonly bool $ignoredByBaseline; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + $this->ignoredByBaseline = $ignoredByBaseline; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function ignoredByBaseline(): bool + { + return $this->ignoredByBaseline; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + $status = ''; + + if ($this->ignoredByBaseline) { + $status = 'Baseline-Ignored '; + } elseif ($this->suppressed) { + $status = 'Suppressed '; + } + + return sprintf( + 'Test Triggered %sPHP Notice (%s)%s', + $status, + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php new file mode 100644 index 000000000..98649bda3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PhpNoticeTriggeredSubscriber extends Subscriber +{ + public function notify(PhpNoticeTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php new file mode 100644 index 000000000..a93dc73e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PhpWarningTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + private readonly bool $ignoredByBaseline; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + $this->ignoredByBaseline = $ignoredByBaseline; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function ignoredByBaseline(): bool + { + return $this->ignoredByBaseline; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + $status = ''; + + if ($this->ignoredByBaseline) { + $status = 'Baseline-Ignored '; + } elseif ($this->suppressed) { + $status = 'Suppressed '; + } + + return sprintf( + 'Test Triggered %sPHP Warning (%s)%s', + $status, + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php new file mode 100644 index 000000000..3638ba1aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PhpWarningTriggeredSubscriber extends Subscriber +{ + public function notify(PhpWarningTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php new file mode 100644 index 000000000..3b1162f47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.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 PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PhpunitDeprecationTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-param non-empty-string $message + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Triggered PHPUnit Deprecation (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php new file mode 100644 index 000000000..f6b3a239a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PhpunitDeprecationTriggeredSubscriber extends Subscriber +{ + public function notify(PhpunitDeprecationTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php new file mode 100644 index 000000000..8e7d7d4d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use function trim; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PhpunitErrorTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-param non-empty-string $message + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + $message = trim($this->message); + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Triggered PHPUnit Error (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php new file mode 100644 index 000000000..e94d1dde2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PhpunitErrorTriggeredSubscriber extends Subscriber +{ + public function notify(PhpunitErrorTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php new file mode 100644 index 000000000..164c6eb12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.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 PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PhpunitWarningTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-param non-empty-string $message + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Triggered PHPUnit Warning (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php new file mode 100644 index 000000000..72149b2c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PhpunitWarningTriggeredSubscriber extends Subscriber +{ + public function notify(PhpunitWarningTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php new file mode 100644 index 000000000..9bccafa1e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggered.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class WarningTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Test $test; + + /** + * @psalm-var non-empty-string + */ + private readonly string $message; + + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + private readonly bool $suppressed; + private readonly bool $ignoredByBaseline; + + /** + * @psalm-param non-empty-string $message + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + */ + public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + $this->file = $file; + $this->line = $line; + $this->suppressed = $suppressed; + $this->ignoredByBaseline = $ignoredByBaseline; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Test + { + return $this->test; + } + + /** + * @psalm-return non-empty-string + */ + public function message(): string + { + return $this->message; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + public function wasSuppressed(): bool + { + return $this->suppressed; + } + + public function ignoredByBaseline(): bool + { + return $this->ignoredByBaseline; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + $status = ''; + + if ($this->ignoredByBaseline) { + $status = 'Baseline-Ignored '; + } elseif ($this->suppressed) { + $status = 'Suppressed '; + } + + return sprintf( + 'Test Triggered %sWarning (%s)%s', + $status, + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php new file mode 100644 index 000000000..8eb66648e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface WarningTriggeredSubscriber extends Subscriber +{ + public function notify(WarningTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php new file mode 100644 index 000000000..2b6becab7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.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 PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code\ClassMethod; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry\Info; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DataProviderMethodCalled implements Event +{ + private readonly Info $telemetryInfo; + private readonly ClassMethod $testMethod; + private readonly ClassMethod $dataProviderMethod; + + public function __construct(Info $telemetryInfo, ClassMethod $testMethod, ClassMethod $dataProviderMethod) + { + $this->telemetryInfo = $telemetryInfo; + $this->testMethod = $testMethod; + $this->dataProviderMethod = $dataProviderMethod; + } + + public function telemetryInfo(): Info + { + return $this->telemetryInfo; + } + + public function testMethod(): ClassMethod + { + return $this->testMethod; + } + + public function dataProviderMethod(): ClassMethod + { + return $this->dataProviderMethod; + } + + public function asString(): string + { + return sprintf( + 'Data Provider Method Called (%s::%s for test method %s::%s)', + $this->dataProviderMethod->className(), + $this->dataProviderMethod->methodName(), + $this->testMethod->className(), + $this->testMethod->methodName(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php new file mode 100644 index 000000000..5f7d4013b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface DataProviderMethodCalledSubscriber extends Subscriber +{ + public function notify(DataProviderMethodCalled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php new file mode 100644 index 000000000..0036e4089 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Code\ClassMethod; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DataProviderMethodFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly ClassMethod $testMethod; + + /** + * @psalm-var list + */ + private readonly array $calledMethods; + + public function __construct(Telemetry\Info $telemetryInfo, ClassMethod $testMethod, ClassMethod ...$calledMethods) + { + $this->telemetryInfo = $telemetryInfo; + $this->testMethod = $testMethod; + $this->calledMethods = $calledMethods; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testMethod(): ClassMethod + { + return $this->testMethod; + } + + /** + * @psalm-return list + */ + public function calledMethods(): array + { + return $this->calledMethods; + } + + public function asString(): string + { + $buffer = sprintf( + 'Data Provider Method Finished for %s::%s:', + $this->testMethod->className(), + $this->testMethod->methodName(), + ); + + foreach ($this->calledMethods as $calledMethod) { + $buffer .= sprintf( + PHP_EOL . '- %s::%s', + $calledMethod->className(), + $calledMethod->methodName(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php new file mode 100644 index 000000000..624f8921d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface DataProviderMethodFinishedSubscriber extends Subscriber +{ + public function notify(DataProviderMethodFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php new file mode 100644 index 000000000..fd8281520 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Finished.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Finished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + private readonly int $numberOfAssertionsPerformed; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, int $numberOfAssertionsPerformed) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->numberOfAssertionsPerformed = $numberOfAssertionsPerformed; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function numberOfAssertionsPerformed(): int + { + return $this->numberOfAssertionsPerformed; + } + + public function asString(): string + { + return sprintf( + 'Test Finished (%s)', + $this->test->id(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php new file mode 100644 index 000000000..5751e3df7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface FinishedSubscriber extends Subscriber +{ + public function notify(Finished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php new file mode 100644 index 000000000..4989d9ee8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PreparationFailed implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function asString(): string + { + return sprintf( + 'Test Preparation Failed (%s)', + $this->test->id(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php new file mode 100644 index 000000000..da20f11ef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PreparationFailedSubscriber extends Subscriber +{ + public function notify(PreparationFailed $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php new file mode 100644 index 000000000..a6e8b8a03 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PreparationStarted implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function asString(): string + { + return sprintf( + 'Test Preparation Started (%s)', + $this->test->id(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php new file mode 100644 index 000000000..f13296b4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PreparationStartedSubscriber extends Subscriber +{ + public function notify(PreparationStarted $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php new file mode 100644 index 000000000..250758555 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/Prepared.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Prepared implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function asString(): string + { + return sprintf( + 'Test Prepared (%s)', + $this->test->id(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php new file mode 100644 index 000000000..f53e227f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PreparedSubscriber extends Subscriber +{ + public function notify(Prepared $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php new file mode 100644 index 000000000..0c3f4aa27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Errored.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use function trim; +use PHPUnit\Event\Code; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Errored implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + private readonly Throwable $throwable; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, Throwable $throwable) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->throwable = $throwable; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function throwable(): Throwable + { + return $this->throwable; + } + + public function asString(): string + { + $message = trim($this->throwable->message()); + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Errored (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php new file mode 100644 index 000000000..42dd5b24d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ErroredSubscriber extends Subscriber +{ + public function notify(Errored $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php new file mode 100644 index 000000000..0bce79efe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Failed.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use function trim; +use PHPUnit\Event\Code; +use PHPUnit\Event\Code\ComparisonFailure; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Failed implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + private readonly Throwable $throwable; + private readonly ?ComparisonFailure $comparisonFailure; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, Throwable $throwable, ?ComparisonFailure $comparisonFailure) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->throwable = $throwable; + $this->comparisonFailure = $comparisonFailure; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function throwable(): Throwable + { + return $this->throwable; + } + + /** + * @psalm-assert-if-true !null $this->comparisonFailure + */ + public function hasComparisonFailure(): bool + { + return $this->comparisonFailure !== null; + } + + /** + * @throws NoComparisonFailureException + */ + public function comparisonFailure(): ComparisonFailure + { + if ($this->comparisonFailure === null) { + throw new NoComparisonFailureException; + } + + return $this->comparisonFailure; + } + + public function asString(): string + { + $message = trim($this->throwable->message()); + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Failed (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php new file mode 100644 index 000000000..8da6a85f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface FailedSubscriber extends Subscriber +{ + public function notify(Failed $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php new file mode 100644 index 000000000..c501fa46c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use function trim; +use PHPUnit\Event\Code; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MarkedIncomplete implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + private readonly Throwable $throwable; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, Throwable $throwable) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->throwable = $throwable; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function throwable(): Throwable + { + return $this->throwable; + } + + public function asString(): string + { + $message = trim($this->throwable->message()); + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Marked Incomplete (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php new file mode 100644 index 000000000..ff0acd863 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MarkedIncompleteSubscriber extends Subscriber +{ + public function notify(MarkedIncomplete $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php new file mode 100644 index 000000000..256923d49 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Passed.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Passed implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function asString(): string + { + return sprintf( + 'Test Passed (%s)', + $this->test->id(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php new file mode 100644 index 000000000..4a5673816 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PassedSubscriber extends Subscriber +{ + public function notify(Passed $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php new file mode 100644 index 000000000..14501058a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/Skipped.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Code; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Skipped implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Code\Test $test; + private readonly string $message; + + public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->test = $test; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function test(): Code\Test + { + return $this->test; + } + + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + $message = $this->message; + + if (!empty($message)) { + $message = PHP_EOL . $message; + } + + return sprintf( + 'Test Skipped (%s)%s', + $this->test->id(), + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php new file mode 100644 index 000000000..5fd48ac6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface SkippedSubscriber extends Subscriber +{ + public function notify(Skipped $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php new file mode 100644 index 000000000..308332e88 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PrintedUnexpectedOutput implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var non-empty-string + */ + private readonly string $output; + + /** + * @psalm-param non-empty-string $output + */ + public function __construct(Telemetry\Info $telemetryInfo, string $output) + { + $this->telemetryInfo = $telemetryInfo; + $this->output = $output; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return non-empty-string + */ + public function output(): string + { + return $this->output; + } + + public function asString(): string + { + return sprintf( + 'Test Printed Unexpected Output%s%s', + PHP_EOL, + $this->output, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php new file mode 100644 index 000000000..ee2015723 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PrintedUnexpectedOutputSubscriber extends Subscriber +{ + public function notify(PrintedUnexpectedOutput $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php new file mode 100644 index 000000000..ad462440f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockObjectCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function asString(): string + { + return sprintf( + 'Mock Object Created (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php new file mode 100644 index 000000000..8ad2f176b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObjectCreatedSubscriber extends Subscriber +{ + public function notify(MockObjectCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php new file mode 100644 index 000000000..7976a1c9d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockObjectForAbstractClassCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function asString(): string + { + return sprintf( + 'Mock Object Created (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php new file mode 100644 index 000000000..c335d1917 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObjectForAbstractClassCreatedSubscriber extends Subscriber +{ + public function notify(MockObjectForAbstractClassCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php new file mode 100644 index 000000000..deb7ec75d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.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 PHPUnit\Event\Test; + +use function implode; +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockObjectForIntersectionOfInterfacesCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var list + */ + private readonly array $interfaces; + + /** + * @psalm-param list $interfaces + */ + public function __construct(Telemetry\Info $telemetryInfo, array $interfaces) + { + $this->telemetryInfo = $telemetryInfo; + $this->interfaces = $interfaces; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @return list + */ + public function interfaces(): array + { + return $this->interfaces; + } + + public function asString(): string + { + return sprintf( + 'Mock Object Created (%s)', + implode('&', $this->interfaces), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php new file mode 100644 index 000000000..5b345b563 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObjectForIntersectionOfInterfacesCreatedSubscriber extends Subscriber +{ + public function notify(MockObjectForIntersectionOfInterfacesCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php new file mode 100644 index 000000000..fd09d5949 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockObjectForTraitCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var trait-string + */ + private readonly string $traitName; + + /** + * @psalm-param trait-string $traitName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $traitName) + { + $this->telemetryInfo = $telemetryInfo; + $this->traitName = $traitName; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return trait-string + */ + public function traitName(): string + { + return $this->traitName; + } + + public function asString(): string + { + return sprintf( + 'Mock Object Created (%s)', + $this->traitName, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php new file mode 100644 index 000000000..a7e7dd07c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObjectForTraitCreatedSubscriber extends Subscriber +{ + public function notify(MockObjectForTraitCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php new file mode 100644 index 000000000..09992831d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockObjectFromWsdlCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $wsdlFile; + + /** + * @psalm-var class-string + */ + private readonly string $originalClassName; + + /** + * @psalm-var class-string + */ + private readonly string $mockClassName; + + /** + * @psalm-var list + */ + private readonly array $methods; + private readonly bool $callOriginalConstructor; + private readonly array $options; + + /** + * @psalm-param class-string $originalClassName + * @psalm-param class-string $mockClassName + */ + public function __construct(Telemetry\Info $telemetryInfo, string $wsdlFile, string $originalClassName, string $mockClassName, array $methods, bool $callOriginalConstructor, array $options) + { + $this->telemetryInfo = $telemetryInfo; + $this->wsdlFile = $wsdlFile; + $this->originalClassName = $originalClassName; + $this->mockClassName = $mockClassName; + $this->methods = $methods; + $this->callOriginalConstructor = $callOriginalConstructor; + $this->options = $options; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function wsdlFile(): string + { + return $this->wsdlFile; + } + + /** + * @psalm-return class-string + */ + public function originalClassName(): string + { + return $this->originalClassName; + } + + /** + * @psalm-return class-string + */ + public function mockClassName(): string + { + return $this->mockClassName; + } + + /** + * @psalm-return list + */ + public function methods(): array + { + return $this->methods; + } + + public function callOriginalConstructor(): bool + { + return $this->callOriginalConstructor; + } + + public function options(): array + { + return $this->options; + } + + public function asString(): string + { + return sprintf( + 'Mock Object Created (%s)', + $this->wsdlFile, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php new file mode 100644 index 000000000..fb0524b21 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObjectFromWsdlCreatedSubscriber extends Subscriber +{ + public function notify(MockObjectFromWsdlCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php new file mode 100644 index 000000000..604ba3ce0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PartialMockObjectCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var list + */ + private readonly array $methodNames; + + /** + * @psalm-param class-string $className + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className, string ...$methodNames) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + $this->methodNames = $methodNames; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return list + */ + public function methodNames(): array + { + return $this->methodNames; + } + + public function asString(): string + { + return sprintf( + 'Partial Mock Object Created (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php new file mode 100644 index 000000000..e76407418 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface PartialMockObjectCreatedSubscriber extends Subscriber +{ + public function notify(PartialMockObjectCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php new file mode 100644 index 000000000..3f0894128 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestProxyCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $className; + private readonly string $constructorArguments; + + /** + * @psalm-param class-string $className + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className, string $constructorArguments) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + $this->constructorArguments = $constructorArguments; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function constructorArguments(): string + { + return $this->constructorArguments; + } + + public function asString(): string + { + return sprintf( + 'Test Proxy Created (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php new file mode 100644 index 000000000..8af83844a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface TestProxyCreatedSubscriber extends Subscriber +{ + public function notify(TestProxyCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php new file mode 100644 index 000000000..9d0330f6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestStubCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @return class-string + */ + public function className(): string + { + return $this->className; + } + + public function asString(): string + { + return sprintf( + 'Test Stub Created (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php new file mode 100644 index 000000000..6b5deaf37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface TestStubCreatedSubscriber extends Subscriber +{ + public function notify(TestStubCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php new file mode 100644 index 000000000..4aded8c83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.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 PHPUnit\Event\Test; + +use function implode; +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestStubForIntersectionOfInterfacesCreated implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var list + */ + private readonly array $interfaces; + + /** + * @psalm-param list $interfaces + */ + public function __construct(Telemetry\Info $telemetryInfo, array $interfaces) + { + $this->telemetryInfo = $telemetryInfo; + $this->interfaces = $interfaces; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @return list + */ + public function interfaces(): array + { + return $this->interfaces; + } + + public function asString(): string + { + return sprintf( + 'Test Stub Created (%s)', + implode('&', $this->interfaces), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php new file mode 100644 index 000000000..aec6f66ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface TestStubForIntersectionOfInterfacesCreatedSubscriber extends Subscriber +{ + public function notify(TestStubForIntersectionOfInterfacesCreated $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php new file mode 100644 index 000000000..9ec3f348a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinished.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BootstrapFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $filename; + + public function __construct(Telemetry\Info $telemetryInfo, string $filename) + { + $this->telemetryInfo = $telemetryInfo; + $this->filename = $filename; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function filename(): string + { + return $this->filename; + } + + public function asString(): string + { + return sprintf( + 'Bootstrap Finished (%s)', + $this->filename, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php new file mode 100644 index 000000000..749648ec4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface BootstrapFinishedSubscriber extends Subscriber +{ + public function notify(BootstrapFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Configured.php new file mode 100644 index 000000000..e27fd7b87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Configured.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 PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; +use PHPUnit\TextUI\Configuration\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Configured implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly Configuration $configuration; + + public function __construct(Telemetry\Info $telemetryInfo, Configuration $configuration) + { + $this->telemetryInfo = $telemetryInfo; + $this->configuration = $configuration; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function configuration(): Configuration + { + return $this->configuration; + } + + public function asString(): string + { + return 'Test Runner Configured'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php new file mode 100644 index 000000000..0b58f70bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ConfiguredSubscriber extends Subscriber +{ + public function notify(Configured $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php new file mode 100644 index 000000000..31d27e281 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DeprecationTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $message; + + public function __construct(Telemetry\Info $telemetryInfo, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + return sprintf( + 'Test Runner Triggered Deprecation (%s)', + $this->message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php new file mode 100644 index 000000000..627ffbd0f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface DeprecationTriggeredSubscriber extends Subscriber +{ + public function notify(DeprecationTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php new file mode 100644 index 000000000..ea8ab985e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class EventFacadeSealed implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Event Facade Sealed'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php new file mode 100644 index 000000000..4d0d3d010 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface EventFacadeSealedSubscriber extends Subscriber +{ + public function notify(EventFacadeSealed $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php new file mode 100644 index 000000000..2e2b92ced --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAborted.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionAborted implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Execution Aborted'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php new file mode 100644 index 000000000..00397cca2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ExecutionAbortedSubscriber extends Subscriber +{ + public function notify(ExecutionAborted $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php new file mode 100644 index 000000000..5496d1e6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinished.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionFinished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Execution Finished'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php new file mode 100644 index 000000000..9945fc77e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ExecutionFinishedSubscriber extends Subscriber +{ + public function notify(ExecutionFinished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php new file mode 100644 index 000000000..77fd570d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStarted.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; +use PHPUnit\Event\TestSuite\TestSuite; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionStarted implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly TestSuite $testSuite; + + public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) + { + $this->telemetryInfo = $telemetryInfo; + $this->testSuite = $testSuite; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testSuite(): TestSuite + { + return $this->testSuite; + } + + public function asString(): string + { + return sprintf( + 'Test Runner Execution Started (%d test%s)', + $this->testSuite->count(), + $this->testSuite->count() !== 1 ? 's' : '', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php new file mode 100644 index 000000000..532f4409a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ExecutionStartedSubscriber extends Subscriber +{ + public function notify(ExecutionStarted $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php new file mode 100644 index 000000000..8ef3ff1b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExtensionBootstrapped implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var array + */ + private readonly array $parameters; + + /** + * @psalm-param class-string $className + * @psalm-param array $parameters + */ + public function __construct(Telemetry\Info $telemetryInfo, string $className, array $parameters) + { + $this->telemetryInfo = $telemetryInfo; + $this->className = $className; + $this->parameters = $parameters; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return array + */ + public function parameters(): array + { + return $this->parameters; + } + + public function asString(): string + { + return sprintf( + 'Extension Bootstrapped (%s)', + $this->className, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php new file mode 100644 index 000000000..c4c7d55c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ExtensionBootstrappedSubscriber extends Subscriber +{ + public function notify(ExtensionBootstrapped $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php new file mode 100644 index 000000000..a2f1f1476 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExtensionLoadedFromPhar implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $filename; + private readonly string $name; + private readonly string $version; + + public function __construct(Telemetry\Info $telemetryInfo, string $filename, string $name, string $version) + { + $this->telemetryInfo = $telemetryInfo; + $this->filename = $filename; + $this->name = $name; + $this->version = $version; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function filename(): string + { + return $this->filename; + } + + public function name(): string + { + return $this->name; + } + + public function version(): string + { + return $this->version; + } + + public function asString(): string + { + return sprintf( + 'Extension Loaded from PHAR (%s %s)', + $this->name, + $this->version, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php new file mode 100644 index 000000000..fc7c2b0ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ExtensionLoadedFromPharSubscriber extends Subscriber +{ + public function notify(ExtensionLoadedFromPhar $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php new file mode 100644 index 000000000..3b984068b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Finished.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Finished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Finished'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php new file mode 100644 index 000000000..6efc622d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface FinishedSubscriber extends Subscriber +{ + public function notify(Finished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php new file mode 100644 index 000000000..b7ac6a055 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class GarbageCollectionDisabled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Disabled Garbage Collection'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php new file mode 100644 index 000000000..bb7e224fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface GarbageCollectionDisabledSubscriber extends Subscriber +{ + public function notify(GarbageCollectionDisabled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php new file mode 100644 index 000000000..9f3e8b8bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class GarbageCollectionEnabled implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Enabled Garbage Collection'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php new file mode 100644 index 000000000..437eddc23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface GarbageCollectionEnabledSubscriber extends Subscriber +{ + public function notify(GarbageCollectionEnabled $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php new file mode 100644 index 000000000..5ab2f8289 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class GarbageCollectionTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Triggered Garbage Collection'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php new file mode 100644 index 000000000..8b941c535 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface GarbageCollectionTriggeredSubscriber extends Subscriber +{ + public function notify(GarbageCollectionTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Started.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Started.php new file mode 100644 index 000000000..fd2f494a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/Started.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Started implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + + public function __construct(Telemetry\Info $telemetryInfo) + { + $this->telemetryInfo = $telemetryInfo; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function asString(): string + { + return 'Test Runner Started'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php new file mode 100644 index 000000000..342407031 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/StartedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface StartedSubscriber extends Subscriber +{ + public function notify(Started $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php new file mode 100644 index 000000000..cb80a07ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggered.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class WarningTriggered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly string $message; + + public function __construct(Telemetry\Info $telemetryInfo, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + return sprintf( + 'Test Runner Triggered Warning (%s)', + $this->message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php new file mode 100644 index 000000000..9afdd18f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestRunner; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface WarningTriggeredSubscriber extends Subscriber +{ + public function notify(WarningTriggered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php new file mode 100644 index 000000000..1beadde5e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Filtered.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Filtered implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly TestSuite $testSuite; + + public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) + { + $this->telemetryInfo = $telemetryInfo; + $this->testSuite = $testSuite; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testSuite(): TestSuite + { + return $this->testSuite; + } + + public function asString(): string + { + return sprintf( + 'Test Suite Filtered (%d test%s)', + $this->testSuite->count(), + $this->testSuite->count() !== 1 ? 's' : '', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php new file mode 100644 index 000000000..6bba3ad40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface FilteredSubscriber extends Subscriber +{ + public function notify(Filtered $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php new file mode 100644 index 000000000..e89076c12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Finished.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Finished implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly TestSuite $testSuite; + + public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) + { + $this->telemetryInfo = $telemetryInfo; + $this->testSuite = $testSuite; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testSuite(): TestSuite + { + return $this->testSuite; + } + + public function asString(): string + { + return sprintf( + 'Test Suite Finished (%s, %d test%s)', + $this->testSuite->name(), + $this->testSuite->count(), + $this->testSuite->count() !== 1 ? 's' : '', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php new file mode 100644 index 000000000..463c62136 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface FinishedSubscriber extends Subscriber +{ + public function notify(Finished $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php new file mode 100644 index 000000000..271ab37f5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Loaded.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Loaded implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly TestSuite $testSuite; + + public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) + { + $this->telemetryInfo = $telemetryInfo; + $this->testSuite = $testSuite; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testSuite(): TestSuite + { + return $this->testSuite; + } + + public function asString(): string + { + return sprintf( + 'Test Suite Loaded (%d test%s)', + $this->testSuite->count(), + $this->testSuite->count() !== 1 ? 's' : '', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php new file mode 100644 index 000000000..e43886c40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface LoadedSubscriber extends Subscriber +{ + public function notify(Loaded $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php new file mode 100644 index 000000000..9a8f52309 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Skipped.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Skipped implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly TestSuite $testSuite; + private readonly string $message; + + public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite, string $message) + { + $this->telemetryInfo = $telemetryInfo; + $this->testSuite = $testSuite; + $this->message = $message; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testSuite(): TestSuite + { + return $this->testSuite; + } + + public function message(): string + { + return $this->message; + } + + public function asString(): string + { + return sprintf( + 'Test Suite Skipped (%s, %s)', + $this->testSuite->name(), + $this->message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php new file mode 100644 index 000000000..30f509fc6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface SkippedSubscriber extends Subscriber +{ + public function notify(Skipped $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php new file mode 100644 index 000000000..ae2b53cdd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Sorted.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Sorted implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly int $executionOrder; + private readonly int $executionOrderDefects; + private readonly bool $resolveDependencies; + + public function __construct(Telemetry\Info $telemetryInfo, int $executionOrder, int $executionOrderDefects, bool $resolveDependencies) + { + $this->telemetryInfo = $telemetryInfo; + $this->executionOrder = $executionOrder; + $this->executionOrderDefects = $executionOrderDefects; + $this->resolveDependencies = $resolveDependencies; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function executionOrder(): int + { + return $this->executionOrder; + } + + public function executionOrderDefects(): int + { + return $this->executionOrderDefects; + } + + public function resolveDependencies(): bool + { + return $this->resolveDependencies; + } + + public function asString(): string + { + return 'Test Suite Sorted'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php new file mode 100644 index 000000000..481eabb04 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/SortedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface SortedSubscriber extends Subscriber +{ + public function notify(Sorted $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Started.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Started.php new file mode 100644 index 000000000..1e34aa7d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/Started.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use function sprintf; +use PHPUnit\Event\Event; +use PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Started implements Event +{ + private readonly Telemetry\Info $telemetryInfo; + private readonly TestSuite $testSuite; + + public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) + { + $this->telemetryInfo = $telemetryInfo; + $this->testSuite = $testSuite; + } + + public function telemetryInfo(): Telemetry\Info + { + return $this->telemetryInfo; + } + + public function testSuite(): TestSuite + { + return $this->testSuite; + } + + public function asString(): string + { + return sprintf( + 'Test Suite Started (%s, %d test%s)', + $this->testSuite->name(), + $this->testSuite->count(), + $this->testSuite->count() !== 1 ? 's' : '', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php new file mode 100644 index 000000000..66c4e1b2d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Events/TestSuite/StartedSubscriber.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Subscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface StartedSubscriber extends Subscriber +{ + public function notify(Started $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php new file mode 100644 index 000000000..a7dba264c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventAlreadyAssignedException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class EventAlreadyAssignedException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php new file mode 100644 index 000000000..96bf949d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/EventFacadeIsSealedException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class EventFacadeIsSealedException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/Exception.php new file mode 100644 index 000000000..88b526d20 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/Exception.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +interface Exception extends \PHPUnit\Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..3fb060cf7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidArgumentException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidEventException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidEventException.php new file mode 100644 index 000000000..05290372f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidEventException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidEventException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php new file mode 100644 index 000000000..d12deb7f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/InvalidSubscriberException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidSubscriberException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MapError.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MapError.php new file mode 100644 index 000000000..b97a18e6b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MapError.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MapError extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php new file mode 100644 index 000000000..0d26b7f6c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/MoreThanOneDataSetFromDataProviderException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestData; + +use PHPUnit\Event\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MoreThanOneDataSetFromDataProviderException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php new file mode 100644 index 000000000..f9926772c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoComparisonFailureException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Test; + +use PHPUnit\Event\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class NoComparisonFailureException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php new file mode 100644 index 000000000..b17a4d154 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestData; + +use PHPUnit\Event\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class NoDataSetFromDataProviderException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php new file mode 100644 index 000000000..e339323cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoPreviousThrowableException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class NoPreviousThrowableException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php new file mode 100644 index 000000000..35b4c25af --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use PHPUnit\Event\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoTestCaseObjectOnCallStackException extends RuntimeException implements Exception +{ + public function __construct() + { + parent::__construct('Cannot find TestCase object on call stack'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/RuntimeException.php new file mode 100644 index 000000000..2a444db2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/RuntimeException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php new file mode 100644 index 000000000..ebbbd3fa0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class SubscriberTypeAlreadyRegisteredException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventException.php new file mode 100644 index 000000000..0c1211473 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownEventException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php new file mode 100644 index 000000000..ab9432dec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownEventTypeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownEventTypeException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php new file mode 100644 index 000000000..b9aaedb1d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownSubscriberException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php new file mode 100644 index 000000000..d44ff0e9c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Exception/UnknownSubscriberTypeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownSubscriberTypeException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Facade.php new file mode 100644 index 000000000..c0a15e259 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Facade.php @@ -0,0 +1,269 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use function gc_status; +use PHPUnit\Event\Telemetry\HRTime; +use PHPUnit\Event\Telemetry\Php81GarbageCollectorStatusProvider; +use PHPUnit\Event\Telemetry\Php83GarbageCollectorStatusProvider; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Facade +{ + private static ?self $instance = null; + private Emitter $emitter; + private ?TypeMap $typeMap = null; + private ?DeferringDispatcher $deferringDispatcher = null; + private bool $sealed = false; + + public static function instance(): self + { + if (self::$instance === null) { + self::$instance = new self; + } + + return self::$instance; + } + + public static function emitter(): Emitter + { + return self::instance()->emitter; + } + + public function __construct() + { + $this->emitter = $this->createDispatchingEmitter(); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function registerSubscribers(Subscriber ...$subscribers): void + { + foreach ($subscribers as $subscriber) { + $this->registerSubscriber($subscriber); + } + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function registerSubscriber(Subscriber $subscriber): void + { + if ($this->sealed) { + throw new EventFacadeIsSealedException; + } + + $this->deferredDispatcher()->registerSubscriber($subscriber); + } + + /** + * @throws EventFacadeIsSealedException + */ + public function registerTracer(Tracer\Tracer $tracer): void + { + if ($this->sealed) { + throw new EventFacadeIsSealedException; + } + + $this->deferredDispatcher()->registerTracer($tracer); + } + + /** + * @codeCoverageIgnore + * + * @noinspection PhpUnused + */ + public function initForIsolation(HRTime $offset, bool $exportObjects): CollectingDispatcher + { + $dispatcher = new CollectingDispatcher; + + $this->emitter = new DispatchingEmitter( + $dispatcher, + new Telemetry\System( + new Telemetry\SystemStopWatchWithOffset($offset), + new Telemetry\SystemMemoryMeter, + $this->garbageCollectorStatusProvider(), + ), + ); + + if ($exportObjects) { + $this->emitter->exportObjects(); + } + + $this->sealed = true; + + return $dispatcher; + } + + public function forward(EventCollection $events): void + { + $dispatcher = $this->deferredDispatcher(); + + foreach ($events as $event) { + $dispatcher->dispatch($event); + } + } + + public function seal(): void + { + $this->deferredDispatcher()->flush(); + + $this->sealed = true; + + $this->emitter->testRunnerEventFacadeSealed(); + } + + private function createDispatchingEmitter(): DispatchingEmitter + { + return new DispatchingEmitter( + $this->deferredDispatcher(), + $this->createTelemetrySystem(), + ); + } + + private function createTelemetrySystem(): Telemetry\System + { + return new Telemetry\System( + new Telemetry\SystemStopWatch, + new Telemetry\SystemMemoryMeter, + $this->garbageCollectorStatusProvider(), + ); + } + + private function deferredDispatcher(): DeferringDispatcher + { + if ($this->deferringDispatcher === null) { + $this->deferringDispatcher = new DeferringDispatcher( + new DirectDispatcher($this->typeMap()), + ); + } + + return $this->deferringDispatcher; + } + + private function typeMap(): TypeMap + { + if ($this->typeMap === null) { + $typeMap = new TypeMap; + + $this->registerDefaultTypes($typeMap); + + $this->typeMap = $typeMap; + } + + return $this->typeMap; + } + + private function registerDefaultTypes(TypeMap $typeMap): void + { + $defaultEvents = [ + Application\Started::class, + Application\Finished::class, + + Test\DataProviderMethodCalled::class, + Test\DataProviderMethodFinished::class, + Test\MarkedIncomplete::class, + Test\AfterLastTestMethodCalled::class, + Test\AfterLastTestMethodFinished::class, + Test\AfterTestMethodCalled::class, + Test\AfterTestMethodFinished::class, + Test\AssertionSucceeded::class, + Test\AssertionFailed::class, + Test\BeforeFirstTestMethodCalled::class, + Test\BeforeFirstTestMethodErrored::class, + Test\BeforeFirstTestMethodFinished::class, + Test\BeforeTestMethodCalled::class, + Test\BeforeTestMethodFinished::class, + Test\ComparatorRegistered::class, + Test\ConsideredRisky::class, + Test\DeprecationTriggered::class, + Test\Errored::class, + Test\ErrorTriggered::class, + Test\Failed::class, + Test\Finished::class, + Test\NoticeTriggered::class, + Test\Passed::class, + Test\PhpDeprecationTriggered::class, + Test\PhpNoticeTriggered::class, + Test\PhpunitDeprecationTriggered::class, + Test\PhpunitErrorTriggered::class, + Test\PhpunitWarningTriggered::class, + Test\PhpWarningTriggered::class, + Test\PostConditionCalled::class, + Test\PostConditionFinished::class, + Test\PreConditionCalled::class, + Test\PreConditionFinished::class, + Test\PreparationStarted::class, + Test\Prepared::class, + Test\PreparationFailed::class, + Test\PrintedUnexpectedOutput::class, + Test\Skipped::class, + Test\WarningTriggered::class, + + Test\MockObjectCreated::class, + Test\MockObjectForAbstractClassCreated::class, + Test\MockObjectForIntersectionOfInterfacesCreated::class, + Test\MockObjectForTraitCreated::class, + Test\MockObjectFromWsdlCreated::class, + Test\PartialMockObjectCreated::class, + Test\TestProxyCreated::class, + Test\TestStubCreated::class, + Test\TestStubForIntersectionOfInterfacesCreated::class, + + TestRunner\BootstrapFinished::class, + TestRunner\Configured::class, + TestRunner\EventFacadeSealed::class, + TestRunner\ExecutionAborted::class, + TestRunner\ExecutionFinished::class, + TestRunner\ExecutionStarted::class, + TestRunner\ExtensionLoadedFromPhar::class, + TestRunner\ExtensionBootstrapped::class, + TestRunner\Finished::class, + TestRunner\Started::class, + TestRunner\DeprecationTriggered::class, + TestRunner\WarningTriggered::class, + TestRunner\GarbageCollectionDisabled::class, + TestRunner\GarbageCollectionTriggered::class, + TestRunner\GarbageCollectionEnabled::class, + + TestSuite\Filtered::class, + TestSuite\Finished::class, + TestSuite\Loaded::class, + TestSuite\Skipped::class, + TestSuite\Sorted::class, + TestSuite\Started::class, + ]; + + foreach ($defaultEvents as $eventClass) { + $typeMap->addMapping( + $eventClass . 'Subscriber', + $eventClass, + ); + } + } + + private function garbageCollectorStatusProvider(): Telemetry\GarbageCollectorStatusProvider + { + if (!isset(gc_status()['running'])) { + // @codeCoverageIgnoreStart + return new Php81GarbageCollectorStatusProvider; + // @codeCoverageIgnoreEnd + } + + return new Php83GarbageCollectorStatusProvider; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Subscriber.php new file mode 100644 index 000000000..e0455c025 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Subscriber.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Subscriber +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Tracer.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Tracer.php new file mode 100644 index 000000000..3b029fdf2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Tracer.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Tracer; + +use PHPUnit\Event\Event; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Tracer +{ + public function trace(Event $event): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/TypeMap.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/TypeMap.php new file mode 100644 index 000000000..df5e79cc3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/TypeMap.php @@ -0,0 +1,192 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event; + +use function array_key_exists; +use function class_exists; +use function class_implements; +use function in_array; +use function interface_exists; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TypeMap +{ + /** + * @psalm-var array + */ + private array $mapping = []; + + /** + * @psalm-param class-string $subscriberInterface + * @psalm-param class-string $eventClass + * + * @throws EventAlreadyAssignedException + * @throws InvalidEventException + * @throws InvalidSubscriberException + * @throws SubscriberTypeAlreadyRegisteredException + * @throws UnknownEventException + * @throws UnknownSubscriberException + */ + public function addMapping(string $subscriberInterface, string $eventClass): void + { + $this->ensureSubscriberInterfaceExists($subscriberInterface); + $this->ensureSubscriberInterfaceExtendsInterface($subscriberInterface); + $this->ensureEventClassExists($eventClass); + $this->ensureEventClassImplementsEventInterface($eventClass); + $this->ensureSubscriberWasNotAlreadyRegistered($subscriberInterface); + $this->ensureEventWasNotAlreadyAssigned($eventClass); + + $this->mapping[$subscriberInterface] = $eventClass; + } + + public function isKnownSubscriberType(Subscriber $subscriber): bool + { + foreach (class_implements($subscriber) as $interface) { + if (array_key_exists($interface, $this->mapping)) { + return true; + } + } + + return false; + } + + public function isKnownEventType(Event $event): bool + { + return in_array($event::class, $this->mapping, true); + } + + /** + * @psalm-return class-string + * + * @throws MapError + */ + public function map(Subscriber $subscriber): string + { + foreach (class_implements($subscriber) as $interface) { + if (array_key_exists($interface, $this->mapping)) { + return $this->mapping[$interface]; + } + } + + throw new MapError( + sprintf( + 'Subscriber "%s" does not implement a known interface', + $subscriber::class, + ), + ); + } + + /** + * @psalm-param class-string $subscriberInterface + * + * @throws UnknownSubscriberException + */ + private function ensureSubscriberInterfaceExists(string $subscriberInterface): void + { + if (!interface_exists($subscriberInterface)) { + throw new UnknownSubscriberException( + sprintf( + 'Subscriber "%s" does not exist or is not an interface', + $subscriberInterface, + ), + ); + } + } + + /** + * @psalm-param class-string $eventClass + * + * @throws UnknownEventException + */ + private function ensureEventClassExists(string $eventClass): void + { + if (!class_exists($eventClass)) { + throw new UnknownEventException( + sprintf( + 'Event class "%s" does not exist', + $eventClass, + ), + ); + } + } + + /** + * @psalm-param class-string $subscriberInterface + * + * @throws InvalidSubscriberException + */ + private function ensureSubscriberInterfaceExtendsInterface(string $subscriberInterface): void + { + if (!in_array(Subscriber::class, class_implements($subscriberInterface), true)) { + throw new InvalidSubscriberException( + sprintf( + 'Subscriber "%s" does not extend Subscriber interface', + $subscriberInterface, + ), + ); + } + } + + /** + * @psalm-param class-string $eventClass + * + * @throws InvalidEventException + */ + private function ensureEventClassImplementsEventInterface(string $eventClass): void + { + if (!in_array(Event::class, class_implements($eventClass), true)) { + throw new InvalidEventException( + sprintf( + 'Event "%s" does not implement Event interface', + $eventClass, + ), + ); + } + } + + /** + * @psalm-param class-string $subscriberInterface + * + * @throws SubscriberTypeAlreadyRegisteredException + */ + private function ensureSubscriberWasNotAlreadyRegistered(string $subscriberInterface): void + { + if (array_key_exists($subscriberInterface, $this->mapping)) { + throw new SubscriberTypeAlreadyRegisteredException( + sprintf( + 'Subscriber type "%s" already registered', + $subscriberInterface, + ), + ); + } + } + + /** + * @psalm-param class-string $eventClass + * + * @throws EventAlreadyAssignedException + */ + private function ensureEventWasNotAlreadyAssigned(string $eventClass): void + { + if (in_array($eventClass, $this->mapping, true)) { + throw new EventAlreadyAssignedException( + sprintf( + 'Event "%s" already assigned', + $eventClass, + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ClassMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ClassMethod.php new file mode 100644 index 000000000..5b7d56c2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ClassMethod.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ClassMethod +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailure.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailure.php new file mode 100644 index 000000000..b8e5cc934 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailure.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 PHPUnit\Event\Code; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonFailure +{ + private readonly string $expected; + private readonly string $actual; + private readonly string $diff; + + public function __construct(string $expected, string $actual, string $diff) + { + $this->expected = $expected; + $this->actual = $actual; + $this->diff = $diff; + } + + public function expected(): string + { + return $this->expected; + } + + public function actual(): string + { + return $this->actual; + } + + public function diff(): string + { + return $this->diff; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php new file mode 100644 index 000000000..ece034277 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ComparisonFailureBuilder.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use function is_bool; +use function is_scalar; +use function print_r; +use PHPUnit\Framework\ExpectationFailedException; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonFailureBuilder +{ + public static function from(Throwable $t): ?ComparisonFailure + { + if (!$t instanceof ExpectationFailedException) { + return null; + } + + if (!$t->getComparisonFailure()) { + return null; + } + + $expectedAsString = $t->getComparisonFailure()->getExpectedAsString(); + + if (empty($expectedAsString)) { + $expectedAsString = self::mapScalarValueToString($t->getComparisonFailure()->getExpected()); + } + + $actualAsString = $t->getComparisonFailure()->getActualAsString(); + + if (empty($actualAsString)) { + $actualAsString = self::mapScalarValueToString($t->getComparisonFailure()->getActual()); + } + + return new ComparisonFailure( + $expectedAsString, + $actualAsString, + $t->getComparisonFailure()->getDiff(), + ); + } + + private static function mapScalarValueToString(mixed $value): string + { + if ($value === null) { + return 'null'; + } + + if (is_bool($value)) { + return $value ? 'true' : 'false'; + } + + if (is_scalar($value)) { + return print_r($value, true); + } + + return ''; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php new file mode 100644 index 000000000..a901be430 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/OperatingSystem.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Runtime; + +use const PHP_OS; +use const PHP_OS_FAMILY; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class OperatingSystem +{ + private readonly string $operatingSystem; + private readonly string $operatingSystemFamily; + + public function __construct() + { + $this->operatingSystem = PHP_OS; + $this->operatingSystemFamily = PHP_OS_FAMILY; + } + + public function operatingSystem(): string + { + return $this->operatingSystem; + } + + public function operatingSystemFamily(): string + { + return $this->operatingSystemFamily; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHP.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHP.php new file mode 100644 index 000000000..717f3c120 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHP.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Runtime; + +use const PHP_EXTRA_VERSION; +use const PHP_MAJOR_VERSION; +use const PHP_MINOR_VERSION; +use const PHP_RELEASE_VERSION; +use const PHP_SAPI; +use const PHP_VERSION; +use const PHP_VERSION_ID; +use function array_merge; +use function get_loaded_extensions; +use function sort; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PHP +{ + private readonly string $version; + private readonly int $versionId; + private readonly int $majorVersion; + private readonly int $minorVersion; + private readonly int $releaseVersion; + private readonly string $extraVersion; + private readonly string $sapi; + + /** + * @psalm-var list + */ + private readonly array $extensions; + + public function __construct() + { + $this->version = PHP_VERSION; + $this->versionId = PHP_VERSION_ID; + $this->majorVersion = PHP_MAJOR_VERSION; + $this->minorVersion = PHP_MINOR_VERSION; + $this->releaseVersion = PHP_RELEASE_VERSION; + $this->extraVersion = PHP_EXTRA_VERSION; + $this->sapi = PHP_SAPI; + + $extensions = array_merge( + get_loaded_extensions(true), + get_loaded_extensions(), + ); + + sort($extensions); + + $this->extensions = $extensions; + } + + public function version(): string + { + return $this->version; + } + + public function sapi(): string + { + return $this->sapi; + } + + public function majorVersion(): int + { + return $this->majorVersion; + } + + public function minorVersion(): int + { + return $this->minorVersion; + } + + public function releaseVersion(): int + { + return $this->releaseVersion; + } + + public function extraVersion(): string + { + return $this->extraVersion; + } + + public function versionId(): int + { + return $this->versionId; + } + + /** + * @psalm-return list + */ + public function extensions(): array + { + return $this->extensions; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.php new file mode 100644 index 000000000..f6fb03754 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/PHPUnit.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 PHPUnit\Event\Runtime; + +use PHPUnit\Runner\Version; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PHPUnit +{ + private readonly string $versionId; + private readonly string $releaseSeries; + + public function __construct() + { + $this->versionId = Version::id(); + $this->releaseSeries = Version::series(); + } + + public function versionId(): string + { + return $this->versionId; + } + + public function releaseSeries(): string + { + return $this->releaseSeries; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php new file mode 100644 index 000000000..cea7ba322 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Runtime/Runtime.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Runtime; + +use function sprintf; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Runtime +{ + private readonly OperatingSystem $operatingSystem; + private readonly PHP $php; + private readonly PHPUnit $phpunit; + + public function __construct() + { + $this->operatingSystem = new OperatingSystem; + $this->php = new PHP; + $this->phpunit = new PHPUnit; + } + + public function asString(): string + { + $php = $this->php(); + + return sprintf( + 'PHPUnit %s using PHP %s (%s) on %s', + $this->phpunit()->versionId(), + $php->version(), + $php->sapi(), + $this->operatingSystem()->operatingSystem(), + ); + } + + public function operatingSystem(): OperatingSystem + { + return $this->operatingSystem; + } + + public function php(): PHP + { + return $this->php; + } + + public function phpunit(): PHPUnit + { + return $this->phpunit; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php new file mode 100644 index 000000000..000216cd4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Duration.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use function floor; +use function sprintf; +use PHPUnit\Event\InvalidArgumentException; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Duration +{ + private readonly int $seconds; + private readonly int $nanoseconds; + + /** + * @throws InvalidArgumentException + */ + public static function fromSecondsAndNanoseconds(int $seconds, int $nanoseconds): self + { + return new self( + $seconds, + $nanoseconds, + ); + } + + /** + * @throws InvalidArgumentException + */ + private function __construct(int $seconds, int $nanoseconds) + { + $this->ensureNotNegative($seconds, 'seconds'); + $this->ensureNotNegative($nanoseconds, 'nanoseconds'); + $this->ensureNanoSecondsInRange($nanoseconds); + + $this->seconds = $seconds; + $this->nanoseconds = $nanoseconds; + } + + public function seconds(): int + { + return $this->seconds; + } + + public function nanoseconds(): int + { + return $this->nanoseconds; + } + + public function asFloat(): float + { + return $this->seconds() + ($this->nanoseconds() / 1000000000); + } + + public function asString(): string + { + $seconds = $this->seconds(); + $minutes = 0; + $hours = 0; + + if ($seconds > 60 * 60) { + $hours = floor($seconds / 60 / 60); + $seconds -= ($hours * 60 * 60); + } + + if ($seconds > 60) { + $minutes = floor($seconds / 60); + $seconds -= ($minutes * 60); + } + + return sprintf( + '%02d:%02d:%02d.%09d', + $hours, + $minutes, + $seconds, + $this->nanoseconds(), + ); + } + + public function equals(self $other): bool + { + return $this->seconds === $other->seconds && + $this->nanoseconds === $other->nanoseconds; + } + + public function isLessThan(self $other): bool + { + if ($this->seconds < $other->seconds) { + return true; + } + + if ($this->seconds > $other->seconds) { + return false; + } + + return $this->nanoseconds < $other->nanoseconds; + } + + public function isGreaterThan(self $other): bool + { + if ($this->seconds > $other->seconds) { + return true; + } + + if ($this->seconds < $other->seconds) { + return false; + } + + return $this->nanoseconds > $other->nanoseconds; + } + + /** + * @throws InvalidArgumentException + */ + private function ensureNotNegative(int $value, string $type): void + { + if ($value < 0) { + throw new InvalidArgumentException( + sprintf( + 'Value for %s must not be negative.', + $type, + ), + ); + } + } + + /** + * @throws InvalidArgumentException + */ + private function ensureNanoSecondsInRange(int $nanoseconds): void + { + if ($nanoseconds > 999999999) { + throw new InvalidArgumentException( + 'Value for nanoseconds must not be greater than 999999999.', + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php new file mode 100644 index 000000000..51a5ac68e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use PHPUnit\Event\RuntimeException; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class GarbageCollectorStatus +{ + private readonly int $runs; + private readonly int $collected; + private readonly int $threshold; + private readonly int $roots; + private readonly ?float $applicationTime; + private readonly ?float $collectorTime; + private readonly ?float $destructorTime; + private readonly ?float $freeTime; + private readonly ?bool $running; + private readonly ?bool $protected; + private readonly ?bool $full; + private readonly ?int $bufferSize; + + public function __construct(int $runs, int $collected, int $threshold, int $roots, ?float $applicationTime, ?float $collectorTime, ?float $destructorTime, ?float $freeTime, ?bool $running, ?bool $protected, ?bool $full, ?int $bufferSize) + { + $this->runs = $runs; + $this->collected = $collected; + $this->threshold = $threshold; + $this->roots = $roots; + $this->applicationTime = $applicationTime; + $this->collectorTime = $collectorTime; + $this->destructorTime = $destructorTime; + $this->freeTime = $freeTime; + $this->running = $running; + $this->protected = $protected; + $this->full = $full; + $this->bufferSize = $bufferSize; + } + + public function runs(): int + { + return $this->runs; + } + + public function collected(): int + { + return $this->collected; + } + + public function threshold(): int + { + return $this->threshold; + } + + public function roots(): int + { + return $this->roots; + } + + /** + * @psalm-assert-if-true !null $this->applicationTime + * @psalm-assert-if-true !null $this->collectorTime + * @psalm-assert-if-true !null $this->destructorTime + * @psalm-assert-if-true !null $this->freeTime + * @psalm-assert-if-true !null $this->running + * @psalm-assert-if-true !null $this->protected + * @psalm-assert-if-true !null $this->full + * @psalm-assert-if-true !null $this->bufferSize + */ + public function hasExtendedInformation(): bool + { + return $this->running !== null; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function applicationTime(): float + { + if ($this->applicationTime === null) { + throw new RuntimeException('Information not available'); + } + + return $this->applicationTime; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function collectorTime(): float + { + if ($this->collectorTime === null) { + throw new RuntimeException('Information not available'); + } + + return $this->collectorTime; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function destructorTime(): float + { + if ($this->destructorTime === null) { + throw new RuntimeException('Information not available'); + } + + return $this->destructorTime; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function freeTime(): float + { + if ($this->freeTime === null) { + throw new RuntimeException('Information not available'); + } + + return $this->freeTime; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function isRunning(): bool + { + if ($this->running === null) { + throw new RuntimeException('Information not available'); + } + + return $this->running; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function isProtected(): bool + { + if ($this->protected === null) { + throw new RuntimeException('Information not available'); + } + + return $this->protected; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function isFull(): bool + { + if ($this->full === null) { + throw new RuntimeException('Information not available'); + } + + return $this->full; + } + + /** + * @throws RuntimeException on PHP < 8.3 + */ + public function bufferSize(): int + { + if ($this->bufferSize === null) { + throw new RuntimeException('Information not available'); + } + + return $this->bufferSize; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php new file mode 100644 index 000000000..09bede2e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface GarbageCollectorStatusProvider +{ + public function status(): GarbageCollectorStatus; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php new file mode 100644 index 000000000..df2aa656c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/HRTime.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use function sprintf; +use PHPUnit\Event\InvalidArgumentException; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class HRTime +{ + private readonly int $seconds; + private readonly int $nanoseconds; + + /** + * @throws InvalidArgumentException + */ + public static function fromSecondsAndNanoseconds(int $seconds, int $nanoseconds): self + { + return new self( + $seconds, + $nanoseconds, + ); + } + + /** + * @throws InvalidArgumentException + */ + private function __construct(int $seconds, int $nanoseconds) + { + $this->ensureNotNegative($seconds, 'seconds'); + $this->ensureNotNegative($nanoseconds, 'nanoseconds'); + $this->ensureNanoSecondsInRange($nanoseconds); + + $this->seconds = $seconds; + $this->nanoseconds = $nanoseconds; + } + + public function seconds(): int + { + return $this->seconds; + } + + public function nanoseconds(): int + { + return $this->nanoseconds; + } + + public function duration(self $start): Duration + { + $seconds = $this->seconds - $start->seconds(); + $nanoseconds = $this->nanoseconds - $start->nanoseconds(); + + if ($nanoseconds < 0) { + $seconds--; + + $nanoseconds += 1000000000; + } + + if ($seconds < 0) { + return Duration::fromSecondsAndNanoseconds(0, 0); + } + + return Duration::fromSecondsAndNanoseconds( + $seconds, + $nanoseconds, + ); + } + + /** + * @throws InvalidArgumentException + */ + private function ensureNotNegative(int $value, string $type): void + { + if ($value < 0) { + throw new InvalidArgumentException( + sprintf( + 'Value for %s must not be negative.', + $type, + ), + ); + } + } + + /** + * @throws InvalidArgumentException + */ + private function ensureNanoSecondsInRange(int $nanoseconds): void + { + if ($nanoseconds > 999999999) { + throw new InvalidArgumentException( + 'Value for nanoseconds must not be greater than 999999999.', + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Info.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Info.php new file mode 100644 index 000000000..1546d9403 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Info.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 PHPUnit\Event\Telemetry; + +use function sprintf; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Info +{ + private readonly Snapshot $current; + private readonly Duration $durationSinceStart; + private readonly MemoryUsage $memorySinceStart; + private readonly Duration $durationSincePrevious; + private readonly MemoryUsage $memorySincePrevious; + + public function __construct(Snapshot $current, Duration $durationSinceStart, MemoryUsage $memorySinceStart, Duration $durationSincePrevious, MemoryUsage $memorySincePrevious) + { + $this->current = $current; + $this->durationSinceStart = $durationSinceStart; + $this->memorySinceStart = $memorySinceStart; + $this->durationSincePrevious = $durationSincePrevious; + $this->memorySincePrevious = $memorySincePrevious; + } + + public function time(): HRTime + { + return $this->current->time(); + } + + public function memoryUsage(): MemoryUsage + { + return $this->current->memoryUsage(); + } + + public function peakMemoryUsage(): MemoryUsage + { + return $this->current->peakMemoryUsage(); + } + + public function durationSinceStart(): Duration + { + return $this->durationSinceStart; + } + + public function memoryUsageSinceStart(): MemoryUsage + { + return $this->memorySinceStart; + } + + public function durationSincePrevious(): Duration + { + return $this->durationSincePrevious; + } + + public function memoryUsageSincePrevious(): MemoryUsage + { + return $this->memorySincePrevious; + } + + public function garbageCollectorStatus(): GarbageCollectorStatus + { + return $this->current->garbageCollectorStatus(); + } + + public function asString(): string + { + return sprintf( + '[%s / %s] [%d bytes]', + $this->durationSinceStart()->asString(), + $this->durationSincePrevious()->asString(), + $this->memoryUsage()->bytes(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php new file mode 100644 index 000000000..4d116ff3e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryMeter.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface MemoryMeter +{ + public function memoryUsage(): MemoryUsage; + + public function peakMemoryUsage(): MemoryUsage; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php new file mode 100644 index 000000000..7e8bc699c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/MemoryUsage.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MemoryUsage +{ + private readonly int $bytes; + + public static function fromBytes(int $bytes): self + { + return new self($bytes); + } + + private function __construct(int $bytes) + { + $this->bytes = $bytes; + } + + public function bytes(): int + { + return $this->bytes; + } + + public function diff(self $other): self + { + return self::fromBytes($this->bytes - $other->bytes); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php new file mode 100644 index 000000000..a96eff391 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use function gc_status; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ +final class Php81GarbageCollectorStatusProvider implements GarbageCollectorStatusProvider +{ + public function status(): GarbageCollectorStatus + { + $status = gc_status(); + + return new GarbageCollectorStatus( + $status['runs'], + $status['collected'], + $status['threshold'], + $status['roots'], + null, + null, + null, + null, + null, + null, + null, + null, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php new file mode 100644 index 000000000..ffac76ff7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use function gc_status; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Php83GarbageCollectorStatusProvider implements GarbageCollectorStatusProvider +{ + public function status(): GarbageCollectorStatus + { + $status = gc_status(); + + return new GarbageCollectorStatus( + $status['runs'], + $status['collected'], + $status['threshold'], + $status['roots'], + $status['application_time'], + $status['collector_time'], + $status['destructor_time'], + $status['free_time'], + $status['running'], + $status['protected'], + $status['full'], + $status['buffer_size'], + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php new file mode 100644 index 000000000..6c5a16594 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/Snapshot.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Snapshot +{ + private readonly HRTime $time; + private readonly MemoryUsage $memoryUsage; + private readonly MemoryUsage $peakMemoryUsage; + private readonly GarbageCollectorStatus $garbageCollectorStatus; + + public function __construct(HRTime $time, MemoryUsage $memoryUsage, MemoryUsage $peakMemoryUsage, GarbageCollectorStatus $garbageCollectorStatus) + { + $this->time = $time; + $this->memoryUsage = $memoryUsage; + $this->peakMemoryUsage = $peakMemoryUsage; + $this->garbageCollectorStatus = $garbageCollectorStatus; + } + + public function time(): HRTime + { + return $this->time; + } + + public function memoryUsage(): MemoryUsage + { + return $this->memoryUsage; + } + + public function peakMemoryUsage(): MemoryUsage + { + return $this->peakMemoryUsage; + } + + public function garbageCollectorStatus(): GarbageCollectorStatus + { + return $this->garbageCollectorStatus; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php new file mode 100644 index 000000000..07ce5227f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/StopWatch.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface StopWatch +{ + public function current(): HRTime; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/System.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/System.php new file mode 100644 index 000000000..368054de2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/System.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 PHPUnit\Event\Telemetry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class System +{ + private readonly StopWatch $stopWatch; + private readonly MemoryMeter $memoryMeter; + private readonly GarbageCollectorStatusProvider $garbageCollectorStatusProvider; + + public function __construct(StopWatch $stopWatch, MemoryMeter $memoryMeter, GarbageCollectorStatusProvider $garbageCollectorStatusProvider) + { + $this->stopWatch = $stopWatch; + $this->memoryMeter = $memoryMeter; + $this->garbageCollectorStatusProvider = $garbageCollectorStatusProvider; + } + + public function snapshot(): Snapshot + { + return new Snapshot( + $this->stopWatch->current(), + $this->memoryMeter->memoryUsage(), + $this->memoryMeter->peakMemoryUsage(), + $this->garbageCollectorStatusProvider->status(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php new file mode 100644 index 000000000..f52566501 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use function memory_get_peak_usage; +use function memory_get_usage; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SystemMemoryMeter implements MemoryMeter +{ + public function memoryUsage(): MemoryUsage + { + return MemoryUsage::fromBytes(memory_get_usage(true)); + } + + public function peakMemoryUsage(): MemoryUsage + { + return MemoryUsage::fromBytes(memory_get_peak_usage(true)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php new file mode 100644 index 000000000..9c9373e5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatch.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Telemetry; + +use function hrtime; +use PHPUnit\Event\InvalidArgumentException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SystemStopWatch implements StopWatch +{ + /** + * @throws InvalidArgumentException + */ + public function current(): HRTime + { + return HRTime::fromSecondsAndNanoseconds(...hrtime()); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php new file mode 100644 index 000000000..d27fd98c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.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 PHPUnit\Event\Telemetry; + +use function hrtime; +use PHPUnit\Event\InvalidArgumentException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ +final class SystemStopWatchWithOffset implements StopWatch +{ + private ?HRTime $offset; + + public function __construct(HRTime $offset) + { + $this->offset = $offset; + } + + /** + * @throws InvalidArgumentException + */ + public function current(): HRTime + { + if ($this->offset !== null) { + $offset = $this->offset; + + $this->offset = null; + + return $offset; + } + + return HRTime::fromSecondsAndNanoseconds(...hrtime()); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Phpt.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Phpt.php new file mode 100644 index 000000000..105678714 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Phpt.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Phpt extends Test +{ + /** + * @psalm-assert-if-true Phpt $this + */ + public function isPhpt(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function id(): string + { + return $this->file(); + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->file(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Test.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Test.php new file mode 100644 index 000000000..6ec899c60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/Test.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Test +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-param non-empty-string $file + */ + public function __construct(string $file) + { + $this->file = $file; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-assert-if-true TestMethod $this + */ + public function isTestMethod(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Phpt $this + */ + public function isPhpt(): bool + { + return false; + } + + /** + * @psalm-return non-empty-string + */ + abstract public function id(): string; + + /** + * @psalm-return non-empty-string + */ + abstract public function name(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollection.php new file mode 100644 index 000000000..2656e1ce8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollection.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 PHPUnit\Event\Code; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $tests; + + /** + * @psalm-param list $tests + */ + public static function fromArray(array $tests): self + { + return new self(...$tests); + } + + private function __construct(Test ...$tests) + { + $this->tests = $tests; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->tests; + } + + public function count(): int + { + return count($this->tests); + } + + public function getIterator(): TestCollectionIterator + { + return new TestCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php new file mode 100644 index 000000000..a392a60e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestCollectionIterator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use function count; +use Iterator; + +/** + * @template-implements Iterator + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private readonly array $tests; + private int $position = 0; + + public function __construct(TestCollection $tests) + { + $this->tests = $tests->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->tests); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Test + { + return $this->tests[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php new file mode 100644 index 000000000..fb7d56106 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestData; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DataFromDataProvider extends TestData +{ + private readonly int|string $dataSetName; + private readonly string $dataAsStringForResultOutput; + + public static function from(int|string $dataSetName, string $data, string $dataAsStringForResultOutput): self + { + return new self($dataSetName, $data, $dataAsStringForResultOutput); + } + + protected function __construct(int|string $dataSetName, string $data, string $dataAsStringForResultOutput) + { + $this->dataSetName = $dataSetName; + $this->dataAsStringForResultOutput = $dataAsStringForResultOutput; + + parent::__construct($data); + } + + public function dataSetName(): int|string + { + return $this->dataSetName; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function dataAsStringForResultOutput(): string + { + return $this->dataAsStringForResultOutput; + } + + /** + * @psalm-assert-if-true DataFromDataProvider $this + */ + public function isFromDataProvider(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php new file mode 100644 index 000000000..48fa5cdcd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestData; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DataFromTestDependency extends TestData +{ + public static function from(string $data): self + { + return new self($data); + } + + /** + * @psalm-assert-if-true DataFromTestDependency $this + */ + public function isFromTestDependency(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.php new file mode 100644 index 000000000..dd68d1f6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestData.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 PHPUnit\Event\TestData; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class TestData +{ + private readonly string $data; + + protected function __construct(string $data) + { + $this->data = $data; + } + + public function data(): string + { + return $this->data; + } + + /** + * @psalm-assert-if-true DataFromDataProvider $this + */ + public function isFromDataProvider(): bool + { + return false; + } + + /** + * @psalm-assert-if-true DataFromTestDependency $this + */ + public function isFromTestDependency(): bool + { + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php new file mode 100644 index 000000000..550122597 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollection.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestData; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestDataCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $data; + private ?DataFromDataProvider $fromDataProvider = null; + + /** + * @psalm-param list $data + * + * @throws MoreThanOneDataSetFromDataProviderException + */ + public static function fromArray(array $data): self + { + return new self(...$data); + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function __construct(TestData ...$data) + { + $this->ensureNoMoreThanOneDataFromDataProvider($data); + + $this->data = $data; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->data; + } + + public function count(): int + { + return count($this->data); + } + + /** + * @psalm-assert-if-true !null $this->fromDataProvider + */ + public function hasDataFromDataProvider(): bool + { + return $this->fromDataProvider !== null; + } + + /** + * @throws NoDataSetFromDataProviderException + */ + public function dataFromDataProvider(): DataFromDataProvider + { + if (!$this->hasDataFromDataProvider()) { + throw new NoDataSetFromDataProviderException; + } + + return $this->fromDataProvider; + } + + public function getIterator(): TestDataCollectionIterator + { + return new TestDataCollectionIterator($this); + } + + /** + * @psalm-param list $data + * + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function ensureNoMoreThanOneDataFromDataProvider(array $data): void + { + foreach ($data as $_data) { + if ($_data->isFromDataProvider()) { + if ($this->fromDataProvider !== null) { + throw new MoreThanOneDataSetFromDataProviderException; + } + + $this->fromDataProvider = $_data; + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php new file mode 100644 index 000000000..93f02c490 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestData; + +use function count; +use Iterator; + +/** + * @template-implements Iterator + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestDataCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private readonly array $data; + private int $position = 0; + + public function __construct(TestDataCollection $data) + { + $this->data = $data->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->data); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestData + { + return $this->data[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDox.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDox.php new file mode 100644 index 000000000..948d55fd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDox.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestDox +{ + private readonly string $prettifiedClassName; + private readonly string $prettifiedMethodName; + private readonly string $prettifiedAndColorizedMethodName; + + public function __construct(string $prettifiedClassName, string $prettifiedMethodName, string $prettifiedAndColorizedMethodName) + { + $this->prettifiedClassName = $prettifiedClassName; + $this->prettifiedMethodName = $prettifiedMethodName; + $this->prettifiedAndColorizedMethodName = $prettifiedAndColorizedMethodName; + } + + public function prettifiedClassName(): string + { + return $this->prettifiedClassName; + } + + public function prettifiedMethodName(bool $colorize = false): string + { + if ($colorize) { + return $this->prettifiedAndColorizedMethodName; + } + + return $this->prettifiedMethodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php new file mode 100644 index 000000000..e59197974 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestDoxBuilder.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Logging\TestDox\NamePrettifier; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestDoxBuilder +{ + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + public static function fromTestCase(TestCase $testCase): TestDox + { + $prettifier = new NamePrettifier; + + return new TestDox( + $prettifier->prettifyTestClassName($testCase::class), + $prettifier->prettifyTestCase($testCase, false), + $prettifier->prettifyTestCase($testCase, true), + ); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public static function fromClassNameAndMethodName(string $className, string $methodName): TestDox + { + $prettifier = new NamePrettifier; + + $prettifiedMethodName = $prettifier->prettifyTestMethodName($methodName); + + return new TestDox( + $prettifier->prettifyTestClassName($className), + $prettifiedMethodName, + $prettifiedMethodName, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethod.php new file mode 100644 index 000000000..403308912 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethod.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use function assert; +use function is_int; +use function sprintf; +use PHPUnit\Event\TestData\TestDataCollection; +use PHPUnit\Metadata\MetadataCollection; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestMethod extends Test +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-var non-negative-int + */ + private readonly int $line; + private readonly TestDox $testDox; + private readonly MetadataCollection $metadata; + private readonly TestDataCollection $testData; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * @psalm-param non-empty-string $file + * @psalm-param non-negative-int $line + */ + public function __construct(string $className, string $methodName, string $file, int $line, TestDox $testDox, MetadataCollection $metadata, TestDataCollection $testData) + { + parent::__construct($file); + + $this->className = $className; + $this->methodName = $methodName; + $this->line = $line; + $this->testDox = $testDox; + $this->metadata = $metadata; + $this->testData = $testData; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } + + /** + * @psalm-return non-negative-int + */ + public function line(): int + { + return $this->line; + } + + public function testDox(): TestDox + { + return $this->testDox; + } + + public function metadata(): MetadataCollection + { + return $this->metadata; + } + + public function testData(): TestDataCollection + { + return $this->testData; + } + + /** + * @psalm-assert-if-true TestMethod $this + */ + public function isTestMethod(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function id(): string + { + $buffer = $this->className . '::' . $this->methodName; + + if ($this->testData()->hasDataFromDataProvider()) { + $buffer .= '#' . $this->testData->dataFromDataProvider()->dataSetName(); + } + + return $buffer; + } + + /** + * @psalm-return non-empty-string + */ + public function nameWithClass(): string + { + return $this->className . '::' . $this->name(); + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + if (!$this->testData->hasDataFromDataProvider()) { + return $this->methodName; + } + + $dataSetName = $this->testData->dataFromDataProvider()->dataSetName(); + + if (is_int($dataSetName)) { + $dataSetName = sprintf( + ' with data set #%d', + $dataSetName, + ); + } else { + $dataSetName = sprintf( + ' with data set "%s"', + $dataSetName, + ); + } + + return $this->methodName . $dataSetName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php new file mode 100644 index 000000000..25ccf02f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Test/TestMethodBuilder.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use const DEBUG_BACKTRACE_IGNORE_ARGS; +use const DEBUG_BACKTRACE_PROVIDE_OBJECT; +use function assert; +use function debug_backtrace; +use function is_numeric; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\TestData\DataFromDataProvider; +use PHPUnit\Event\TestData\DataFromTestDependency; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Event\TestData\TestDataCollection; +use PHPUnit\Framework\TestCase; +use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; +use PHPUnit\Util\Exporter; +use PHPUnit\Util\Reflection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMethodBuilder +{ + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + public static function fromTestCase(TestCase $testCase): TestMethod + { + $methodName = $testCase->name(); + + assert(!empty($methodName)); + + $location = Reflection::sourceLocationFor($testCase::class, $methodName); + + return new TestMethod( + $testCase::class, + $methodName, + $location['file'], + $location['line'], + TestDoxBuilder::fromTestCase($testCase), + MetadataRegistry::parser()->forClassAndMethod($testCase::class, $methodName), + self::dataFor($testCase), + ); + } + + /** + * @throws NoTestCaseObjectOnCallStackException + */ + public static function fromCallStack(): TestMethod + { + foreach (debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { + if (isset($frame['object']) && $frame['object'] instanceof TestCase) { + return $frame['object']->valueObjectForEvents(); + } + } + + throw new NoTestCaseObjectOnCallStackException; + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private static function dataFor(TestCase $testCase): TestDataCollection + { + $testData = []; + + if ($testCase->usesDataProvider()) { + $dataSetName = $testCase->dataName(); + + if (is_numeric($dataSetName)) { + $dataSetName = (int) $dataSetName; + } + + $testData[] = DataFromDataProvider::from( + $dataSetName, + Exporter::export($testCase->providedData(), EventFacade::emitter()->exportsObjects()), + $testCase->dataSetAsStringWithData(), + ); + } + + if ($testCase->hasDependencyInput()) { + $testData[] = DataFromTestDependency::from( + Exporter::export($testCase->dependencyInput(), EventFacade::emitter()->exportsObjects()), + ); + } + + return TestDataCollection::fromArray($testData); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php new file mode 100644 index 000000000..744f7095e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuite.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Code\TestCollection; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class TestSuite +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $name; + private readonly int $count; + private readonly TestCollection $tests; + + /** + * @psalm-param non-empty-string $name + */ + public function __construct(string $name, int $size, TestCollection $tests) + { + $this->name = $name; + $this->count = $size; + $this->tests = $tests; + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->name; + } + + public function count(): int + { + return $this->count; + } + + public function tests(): TestCollection + { + return $this->tests; + } + + /** + * @psalm-assert-if-true TestSuiteWithName $this + */ + public function isWithName(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TestSuiteForTestClass $this + */ + public function isForTestClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TestSuiteForTestMethodWithDataProvider $this + */ + public function isForTestMethodWithDataProvider(): bool + { + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php new file mode 100644 index 000000000..96a293752 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use function explode; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Code\TestCollection; +use PHPUnit\Event\RuntimeException; +use PHPUnit\Framework\DataProviderTestSuite; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite as FrameworkTestSuite; +use PHPUnit\Runner\PhptTestCase; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteBuilder +{ + /** + * @throws RuntimeException + */ + public static function from(FrameworkTestSuite $testSuite): TestSuite + { + $tests = []; + + self::process($testSuite, $tests); + + if ($testSuite instanceof DataProviderTestSuite) { + [$className, $methodName] = explode('::', $testSuite->name()); + + try { + $reflector = new ReflectionMethod($className, $methodName); + + return new TestSuiteForTestMethodWithDataProvider( + $testSuite->name(), + $testSuite->count(), + TestCollection::fromArray($tests), + $className, + $methodName, + $reflector->getFileName(), + $reflector->getStartLine(), + ); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + } + + if ($testSuite->isForTestClass()) { + try { + $reflector = new ReflectionClass($testSuite->name()); + + return new TestSuiteForTestClass( + $testSuite->name(), + $testSuite->count(), + TestCollection::fromArray($tests), + $reflector->getFileName(), + $reflector->getStartLine(), + ); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + } + + return new TestSuiteWithName( + $testSuite->name(), + $testSuite->count(), + TestCollection::fromArray($tests), + ); + } + + /** + * @psalm-param list $tests + */ + private static function process(FrameworkTestSuite $testSuite, array &$tests): void + { + foreach ($testSuite->getIterator() as $test) { + if ($test instanceof FrameworkTestSuite) { + self::process($test, $tests); + + continue; + } + + if ($test instanceof TestCase || $test instanceof PhptTestCase) { + $tests[] = $test->valueObjectForEvents(); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php new file mode 100644 index 000000000..fcfc9d0a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Code\TestCollection; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteForTestClass extends TestSuite +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + private readonly string $file; + private readonly int $line; + + /** + * @psalm-param class-string $name + */ + public function __construct(string $name, int $size, TestCollection $tests, string $file, int $line) + { + parent::__construct($name, $size, $tests); + + $this->className = $name; + $this->file = $file; + $this->line = $line; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function file(): string + { + return $this->file; + } + + public function line(): int + { + return $this->line; + } + + /** + * @psalm-assert-if-true TestSuiteForTestClass $this + */ + public function isForTestClass(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php new file mode 100644 index 000000000..29bebc6f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +use PHPUnit\Event\Code\TestCollection; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteForTestMethodWithDataProvider extends TestSuite +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + private readonly string $file; + private readonly int $line; + + /** + * @psalm-param non-empty-string $name + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $name, int $size, TestCollection $tests, string $className, string $methodName, string $file, int $line) + { + parent::__construct($name, $size, $tests); + + $this->className = $className; + $this->methodName = $methodName; + $this->file = $file; + $this->line = $line; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } + + public function file(): string + { + return $this->file; + } + + public function line(): int + { + return $this->line; + } + + /** + * @psalm-assert-if-true TestSuiteForTestMethodWithDataProvider $this + */ + public function isForTestMethodWithDataProvider(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php new file mode 100644 index 000000000..68c2f706c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\TestSuite; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteWithName extends TestSuite +{ + /** + * @psalm-assert-if-true TestSuiteWithName $this + */ + public function isWithName(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Throwable.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Throwable.php new file mode 100644 index 000000000..f94a8a222 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/Throwable.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Event\Code; + +use const PHP_EOL; +use PHPUnit\Event\NoPreviousThrowableException; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Throwable +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + private readonly string $message; + private readonly string $description; + private readonly string $stackTrace; + private readonly ?Throwable $previous; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className, string $message, string $description, string $stackTrace, ?self $previous) + { + $this->className = $className; + $this->message = $message; + $this->description = $description; + $this->stackTrace = $stackTrace; + $this->previous = $previous; + } + + /** + * @throws NoPreviousThrowableException + */ + public function asString(): string + { + $buffer = $this->description(); + + if (!empty($this->stackTrace())) { + $buffer .= PHP_EOL . $this->stackTrace(); + } + + if ($this->hasPrevious()) { + $buffer .= PHP_EOL . 'Caused by' . PHP_EOL . $this->previous()->asString(); + } + + return $buffer; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function message(): string + { + return $this->message; + } + + public function description(): string + { + return $this->description; + } + + public function stackTrace(): string + { + return $this->stackTrace; + } + + /** + * @psalm-assert-if-true !null $this->previous + */ + public function hasPrevious(): bool + { + return $this->previous !== null; + } + + /** + * @throws NoPreviousThrowableException + */ + public function previous(): self + { + if ($this->previous === null) { + throw new NoPreviousThrowableException; + } + + return $this->previous; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ThrowableBuilder.php new file mode 100644 index 000000000..4c12b6ed3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Event/Value/ThrowableBuilder.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 PHPUnit\Event\Code; + +use PHPUnit\Event\NoPreviousThrowableException; +use PHPUnit\Framework\Exception; +use PHPUnit\Util\Filter; +use PHPUnit\Util\ThrowableToStringMapper; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ThrowableBuilder +{ + /** + * @throws Exception + * @throws NoPreviousThrowableException + */ + public static function from(\Throwable $t): Throwable + { + $previous = $t->getPrevious(); + + if ($previous !== null) { + $previous = self::from($previous); + } + + return new Throwable( + $t::class, + $t->getMessage(), + ThrowableToStringMapper::map($t), + Filter::getFilteredStacktrace($t, false), + $previous, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Exception.php new file mode 100644 index 000000000..21721b70f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert.php new file mode 100644 index 000000000..6694fb6c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert.php @@ -0,0 +1,2332 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function class_exists; +use function count; +use function file_get_contents; +use function interface_exists; +use function is_bool; +use ArrayAccess; +use Countable; +use Generator; +use PHPUnit\Event; +use PHPUnit\Framework\Constraint\ArrayHasKey; +use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\Count; +use PHPUnit\Framework\Constraint\DirectoryExists; +use PHPUnit\Framework\Constraint\FileExists; +use PHPUnit\Framework\Constraint\GreaterThan; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEmpty; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; +use PHPUnit\Framework\Constraint\IsEqualIgnoringCase; +use PHPUnit\Framework\Constraint\IsEqualWithDelta; +use PHPUnit\Framework\Constraint\IsFalse; +use PHPUnit\Framework\Constraint\IsFinite; +use PHPUnit\Framework\Constraint\IsIdentical; +use PHPUnit\Framework\Constraint\IsInfinite; +use PHPUnit\Framework\Constraint\IsInstanceOf; +use PHPUnit\Framework\Constraint\IsJson; +use PHPUnit\Framework\Constraint\IsList; +use PHPUnit\Framework\Constraint\IsNan; +use PHPUnit\Framework\Constraint\IsNull; +use PHPUnit\Framework\Constraint\IsReadable; +use PHPUnit\Framework\Constraint\IsTrue; +use PHPUnit\Framework\Constraint\IsType; +use PHPUnit\Framework\Constraint\IsWritable; +use PHPUnit\Framework\Constraint\JsonMatches; +use PHPUnit\Framework\Constraint\LessThan; +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; +use PHPUnit\Framework\Constraint\LogicalOr; +use PHPUnit\Framework\Constraint\LogicalXor; +use PHPUnit\Framework\Constraint\ObjectEquals; +use PHPUnit\Framework\Constraint\ObjectHasProperty; +use PHPUnit\Framework\Constraint\RegularExpression; +use PHPUnit\Framework\Constraint\SameSize; +use PHPUnit\Framework\Constraint\StringContains; +use PHPUnit\Framework\Constraint\StringEndsWith; +use PHPUnit\Framework\Constraint\StringEqualsStringIgnoringLineEndings; +use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; +use PHPUnit\Framework\Constraint\StringStartsWith; +use PHPUnit\Framework\Constraint\TraversableContainsEqual; +use PHPUnit\Framework\Constraint\TraversableContainsIdentical; +use PHPUnit\Framework\Constraint\TraversableContainsOnly; +use PHPUnit\Util\Xml\Loader as XmlLoader; +use PHPUnit\Util\Xml\XmlException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Assert +{ + private static int $count = 0; + + /** + * Asserts that an array has a specified key. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertArrayHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void + { + $constraint = new ArrayHasKey($key); + + static::assertThat($array, $constraint, $message); + } + + /** + * Asserts that an array does not have a specified key. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertArrayNotHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void + { + $constraint = new LogicalNot( + new ArrayHasKey($key), + ); + + static::assertThat($array, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertIsList(mixed $array, string $message = ''): void + { + static::assertThat( + $array, + new IsList, + $message, + ); + } + + /** + * Asserts that a haystack contains a needle. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertContains(mixed $needle, iterable $haystack, string $message = ''): void + { + $constraint = new TraversableContainsIdentical($needle); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void + { + $constraint = new TraversableContainsEqual($needle); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a haystack does not contain a needle. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertNotContains(mixed $needle, iterable $haystack, string $message = ''): void + { + $constraint = new LogicalNot( + new TraversableContainsIdentical($needle), + ); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertNotContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new TraversableContainsEqual($needle)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a haystack contains only values of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + if ($isNativeType === null) { + $isNativeType = self::isNativeType($type); + } + + static::assertThat( + $haystack, + new TraversableContainsOnly( + $type, + $isNativeType, + ), + $message, + ); + } + + /** + * Asserts that a haystack contains only instances of a given class name. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void + { + static::assertThat( + $haystack, + new TraversableContainsOnly( + $className, + false, + ), + $message, + ); + } + + /** + * Asserts that a haystack does not contain only values of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + */ + final public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + if ($isNativeType === null) { + $isNativeType = self::isNativeType($type); + } + + static::assertThat( + $haystack, + new LogicalNot( + new TraversableContainsOnly( + $type, + $isNativeType, + ), + ), + $message, + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + */ + final public static function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void + { + if ($haystack instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$haystack'); + } + + static::assertThat( + $haystack, + new Count($expectedCount), + $message, + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + */ + final public static function assertNotCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void + { + if ($haystack instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$haystack'); + } + + $constraint = new LogicalNot( + new Count($expectedCount), + ); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that two variables are equal. + * + * @throws ExpectationFailedException + */ + final public static function assertEquals(mixed $expected, mixed $actual, string $message = ''): void + { + $constraint = new IsEqual($expected); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (canonicalizing). + * + * @throws ExpectationFailedException + */ + final public static function assertEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void + { + $constraint = new IsEqualCanonicalizing($expected); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (ignoring case). + * + * @throws ExpectationFailedException + */ + final public static function assertEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void + { + $constraint = new IsEqualIgnoringCase($expected); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (with delta). + * + * @throws ExpectationFailedException + */ + final public static function assertEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void + { + $constraint = new IsEqualWithDelta( + $expected, + $delta, + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal. + * + * @throws ExpectationFailedException + */ + final public static function assertNotEquals(mixed $expected, mixed $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqual($expected), + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (canonicalizing). + * + * @throws ExpectationFailedException + */ + final public static function assertNotEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqualCanonicalizing($expected), + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (ignoring case). + * + * @throws ExpectationFailedException + */ + final public static function assertNotEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqualIgnoringCase($expected), + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (with delta). + * + * @throws ExpectationFailedException + */ + final public static function assertNotEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqualWithDelta( + $expected, + $delta, + ), + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void + { + static::assertThat( + $actual, + static::objectEquals($expected, $method), + $message, + ); + } + + /** + * Asserts that a variable is empty. + * + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @psalm-assert empty $actual + */ + final public static function assertEmpty(mixed $actual, string $message = ''): void + { + if ($actual instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$actual'); + } + + static::assertThat($actual, static::isEmpty(), $message); + } + + /** + * Asserts that a variable is not empty. + * + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @psalm-assert !empty $actual + */ + final public static function assertNotEmpty(mixed $actual, string $message = ''): void + { + if ($actual instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$actual'); + } + + static::assertThat($actual, static::logicalNot(static::isEmpty()), $message); + } + + /** + * Asserts that a value is greater than another value. + * + * @throws ExpectationFailedException + */ + final public static function assertGreaterThan(mixed $expected, mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::greaterThan($expected), $message); + } + + /** + * Asserts that a value is greater than or equal to another value. + * + * @throws ExpectationFailedException + */ + final public static function assertGreaterThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + static::greaterThanOrEqual($expected), + $message, + ); + } + + /** + * Asserts that a value is smaller than another value. + * + * @throws ExpectationFailedException + */ + final public static function assertLessThan(mixed $expected, mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::lessThan($expected), $message); + } + + /** + * Asserts that a value is smaller than or equal to another value. + * + * @throws ExpectationFailedException + */ + final public static function assertLessThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::lessThanOrEqual($expected), $message); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @throws ExpectationFailedException + */ + final public static function assertFileEquals(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new IsEqual(file_get_contents($expected)); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file (canonicalizing). + * + * @throws ExpectationFailedException + */ + final public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new IsEqualCanonicalizing( + file_get_contents($expected), + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file (ignoring case). + * + * @throws ExpectationFailedException + */ + final public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new IsEqualIgnoringCase(file_get_contents($expected)); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @throws ExpectationFailedException + */ + final public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new LogicalNot( + new IsEqual(file_get_contents($expected)), + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (canonicalizing). + * + * @throws ExpectationFailedException + */ + final public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new LogicalNot( + new IsEqualCanonicalizing(file_get_contents($expected)), + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (ignoring case). + * + * @throws ExpectationFailedException + */ + final public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + static::assertFileExists($expected, $message); + static::assertFileExists($actual, $message); + + $constraint = new LogicalNot( + new IsEqualIgnoringCase(file_get_contents($expected)), + ); + + static::assertThat(file_get_contents($actual), $constraint, $message); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @throws ExpectationFailedException + */ + final public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new IsEqual(file_get_contents($expectedFile)); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file (canonicalizing). + * + * @throws ExpectationFailedException + */ + final public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile)); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file (ignoring case). + * + * @throws ExpectationFailedException + */ + final public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile)); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @throws ExpectationFailedException + */ + final public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new LogicalNot( + new IsEqual(file_get_contents($expectedFile)), + ); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (canonicalizing). + * + * @throws ExpectationFailedException + */ + final public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new LogicalNot( + new IsEqualCanonicalizing(file_get_contents($expectedFile)), + ); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (ignoring case). + * + * @throws ExpectationFailedException + */ + final public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + + $constraint = new LogicalNot( + new IsEqualIgnoringCase(file_get_contents($expectedFile)), + ); + + static::assertThat($actualString, $constraint, $message); + } + + /** + * Asserts that a file/dir is readable. + * + * @throws ExpectationFailedException + */ + final public static function assertIsReadable(string $filename, string $message = ''): void + { + static::assertThat($filename, new IsReadable, $message); + } + + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws ExpectationFailedException + */ + final public static function assertIsNotReadable(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new IsReadable), $message); + } + + /** + * Asserts that a file/dir exists and is writable. + * + * @throws ExpectationFailedException + */ + final public static function assertIsWritable(string $filename, string $message = ''): void + { + static::assertThat($filename, new IsWritable, $message); + } + + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws ExpectationFailedException + */ + final public static function assertIsNotWritable(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new IsWritable), $message); + } + + /** + * Asserts that a directory exists. + * + * @throws ExpectationFailedException + */ + final public static function assertDirectoryExists(string $directory, string $message = ''): void + { + static::assertThat($directory, new DirectoryExists, $message); + } + + /** + * Asserts that a directory does not exist. + * + * @throws ExpectationFailedException + */ + final public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void + { + static::assertThat($directory, new LogicalNot(new DirectoryExists), $message); + } + + /** + * Asserts that a directory exists and is readable. + * + * @throws ExpectationFailedException + */ + final public static function assertDirectoryIsReadable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is not readable. + * + * @throws ExpectationFailedException + */ + final public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsNotReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is writable. + * + * @throws ExpectationFailedException + */ + final public static function assertDirectoryIsWritable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsWritable($directory, $message); + } + + /** + * Asserts that a directory exists and is not writable. + * + * @throws ExpectationFailedException + */ + final public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsNotWritable($directory, $message); + } + + /** + * Asserts that a file exists. + * + * @throws ExpectationFailedException + */ + final public static function assertFileExists(string $filename, string $message = ''): void + { + static::assertThat($filename, new FileExists, $message); + } + + /** + * Asserts that a file does not exist. + * + * @throws ExpectationFailedException + */ + final public static function assertFileDoesNotExist(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new FileExists), $message); + } + + /** + * Asserts that a file exists and is readable. + * + * @throws ExpectationFailedException + */ + final public static function assertFileIsReadable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsReadable($file, $message); + } + + /** + * Asserts that a file exists and is not readable. + * + * @throws ExpectationFailedException + */ + final public static function assertFileIsNotReadable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsNotReadable($file, $message); + } + + /** + * Asserts that a file exists and is writable. + * + * @throws ExpectationFailedException + */ + final public static function assertFileIsWritable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsWritable($file, $message); + } + + /** + * Asserts that a file exists and is not writable. + * + * @throws ExpectationFailedException + */ + final public static function assertFileIsNotWritable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsNotWritable($file, $message); + } + + /** + * Asserts that a condition is true. + * + * @throws ExpectationFailedException + * + * @psalm-assert true $condition + */ + final public static function assertTrue(mixed $condition, string $message = ''): void + { + static::assertThat($condition, static::isTrue(), $message); + } + + /** + * Asserts that a condition is not true. + * + * @throws ExpectationFailedException + * + * @psalm-assert !true $condition + */ + final public static function assertNotTrue(mixed $condition, string $message = ''): void + { + static::assertThat($condition, static::logicalNot(static::isTrue()), $message); + } + + /** + * Asserts that a condition is false. + * + * @throws ExpectationFailedException + * + * @psalm-assert false $condition + */ + final public static function assertFalse(mixed $condition, string $message = ''): void + { + static::assertThat($condition, static::isFalse(), $message); + } + + /** + * Asserts that a condition is not false. + * + * @throws ExpectationFailedException + * + * @psalm-assert !false $condition + */ + final public static function assertNotFalse(mixed $condition, string $message = ''): void + { + static::assertThat($condition, static::logicalNot(static::isFalse()), $message); + } + + /** + * Asserts that a variable is null. + * + * @throws ExpectationFailedException + * + * @psalm-assert null $actual + */ + final public static function assertNull(mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::isNull(), $message); + } + + /** + * Asserts that a variable is not null. + * + * @throws ExpectationFailedException + * + * @psalm-assert !null $actual + */ + final public static function assertNotNull(mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::logicalNot(static::isNull()), $message); + } + + /** + * Asserts that a variable is finite. + * + * @throws ExpectationFailedException + */ + final public static function assertFinite(mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::isFinite(), $message); + } + + /** + * Asserts that a variable is infinite. + * + * @throws ExpectationFailedException + */ + final public static function assertInfinite(mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::isInfinite(), $message); + } + + /** + * Asserts that a variable is nan. + * + * @throws ExpectationFailedException + */ + final public static function assertNan(mixed $actual, string $message = ''): void + { + static::assertThat($actual, static::isNan(), $message); + } + + /** + * Asserts that an object has a specified property. + * + * @throws ExpectationFailedException + */ + final public static function assertObjectHasProperty(string $propertyName, object $object, string $message = ''): void + { + static::assertThat( + $object, + new ObjectHasProperty($propertyName), + $message, + ); + } + + /** + * Asserts that an object does not have a specified property. + * + * @throws ExpectationFailedException + */ + final public static function assertObjectNotHasProperty(string $propertyName, object $object, string $message = ''): void + { + static::assertThat( + $object, + new LogicalNot( + new ObjectHasProperty($propertyName), + ), + $message, + ); + } + + /** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType + * + * @psalm-param ExpectedType $expected + * + * @psalm-assert =ExpectedType $actual + */ + final public static function assertSame(mixed $expected, mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsIdentical($expected), + $message, + ); + } + + /** + * Asserts that two variables do not have the same type and value. + * Used on objects, it asserts that two variables do not reference + * the same object. + * + * @throws ExpectationFailedException + */ + final public static function assertNotSame(mixed $expected, mixed $actual, string $message = ''): void + { + if (is_bool($expected) && is_bool($actual)) { + static::assertNotEquals($expected, $actual, $message); + } + + static::assertThat( + $actual, + new LogicalNot( + new IsIdentical($expected), + ), + $message, + ); + } + + /** + * Asserts that a variable is of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws UnknownClassOrInterfaceException + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert =ExpectedType $actual + */ + final public static function assertInstanceOf(string $expected, mixed $actual, string $message = ''): void + { + if (!class_exists($expected) && !interface_exists($expected)) { + throw new UnknownClassOrInterfaceException($expected); + } + + static::assertThat( + $actual, + new IsInstanceOf($expected), + $message, + ); + } + + /** + * Asserts that a variable is not of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert !ExpectedType $actual + */ + final public static function assertNotInstanceOf(string $expected, mixed $actual, string $message = ''): void + { + if (!class_exists($expected) && !interface_exists($expected)) { + throw new UnknownClassOrInterfaceException($expected); + } + + static::assertThat( + $actual, + new LogicalNot( + new IsInstanceOf($expected), + ), + $message, + ); + } + + /** + * Asserts that a variable is of type array. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert array $actual + */ + final public static function assertIsArray(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_ARRAY), + $message, + ); + } + + /** + * Asserts that a variable is of type bool. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert bool $actual + */ + final public static function assertIsBool(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_BOOL), + $message, + ); + } + + /** + * Asserts that a variable is of type float. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert float $actual + */ + final public static function assertIsFloat(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_FLOAT), + $message, + ); + } + + /** + * Asserts that a variable is of type int. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert int $actual + */ + final public static function assertIsInt(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_INT), + $message, + ); + } + + /** + * Asserts that a variable is of type numeric. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert numeric $actual + */ + final public static function assertIsNumeric(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_NUMERIC), + $message, + ); + } + + /** + * Asserts that a variable is of type object. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert object $actual + */ + final public static function assertIsObject(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_OBJECT), + $message, + ); + } + + /** + * Asserts that a variable is of type resource. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert resource $actual + */ + final public static function assertIsResource(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_RESOURCE), + $message, + ); + } + + /** + * Asserts that a variable is of type resource and is closed. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert resource $actual + */ + final public static function assertIsClosedResource(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_CLOSED_RESOURCE), + $message, + ); + } + + /** + * Asserts that a variable is of type string. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert string $actual + */ + final public static function assertIsString(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_STRING), + $message, + ); + } + + /** + * Asserts that a variable is of type scalar. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert scalar $actual + */ + final public static function assertIsScalar(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_SCALAR), + $message, + ); + } + + /** + * Asserts that a variable is of type callable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert callable $actual + */ + final public static function assertIsCallable(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_CALLABLE), + $message, + ); + } + + /** + * Asserts that a variable is of type iterable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert iterable $actual + */ + final public static function assertIsIterable(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_ITERABLE), + $message, + ); + } + + /** + * Asserts that a variable is not of type array. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !array $actual + */ + final public static function assertIsNotArray(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_ARRAY)), + $message, + ); + } + + /** + * Asserts that a variable is not of type bool. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !bool $actual + */ + final public static function assertIsNotBool(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_BOOL)), + $message, + ); + } + + /** + * Asserts that a variable is not of type float. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !float $actual + */ + final public static function assertIsNotFloat(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_FLOAT)), + $message, + ); + } + + /** + * Asserts that a variable is not of type int. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !int $actual + */ + final public static function assertIsNotInt(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_INT)), + $message, + ); + } + + /** + * Asserts that a variable is not of type numeric. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !numeric $actual + */ + final public static function assertIsNotNumeric(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_NUMERIC)), + $message, + ); + } + + /** + * Asserts that a variable is not of type object. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !object $actual + */ + final public static function assertIsNotObject(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_OBJECT)), + $message, + ); + } + + /** + * Asserts that a variable is not of type resource. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !resource $actual + */ + final public static function assertIsNotResource(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_RESOURCE)), + $message, + ); + } + + /** + * Asserts that a variable is not of type resource. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !resource $actual + */ + final public static function assertIsNotClosedResource(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_CLOSED_RESOURCE)), + $message, + ); + } + + /** + * Asserts that a variable is not of type string. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !string $actual + */ + final public static function assertIsNotString(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_STRING)), + $message, + ); + } + + /** + * Asserts that a variable is not of type scalar. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !scalar $actual + */ + final public static function assertIsNotScalar(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_SCALAR)), + $message, + ); + } + + /** + * Asserts that a variable is not of type callable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !callable $actual + */ + final public static function assertIsNotCallable(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_CALLABLE)), + $message, + ); + } + + /** + * Asserts that a variable is not of type iterable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !iterable $actual + */ + final public static function assertIsNotIterable(mixed $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_ITERABLE)), + $message, + ); + } + + /** + * Asserts that a string matches a given regular expression. + * + * @throws ExpectationFailedException + */ + final public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void + { + static::assertThat($string, new RegularExpression($pattern), $message); + } + + /** + * Asserts that a string does not match a given regular expression. + * + * @throws ExpectationFailedException + */ + final public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new RegularExpression($pattern), + ), + $message, + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + */ + final public static function assertSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void + { + if ($expected instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$expected'); + } + + if ($actual instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$actual'); + } + + static::assertThat( + $actual, + new SameSize($expected), + $message, + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + */ + final public static function assertNotSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void + { + if ($expected instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$expected'); + } + + if ($actual instanceof Generator) { + throw GeneratorNotSupportedException::fromParameterName('$actual'); + } + + static::assertThat( + $actual, + new LogicalNot( + new SameSize($expected), + ), + $message, + ); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertStringContainsStringIgnoringLineEndings(string $needle, string $haystack, string $message = ''): void + { + static::assertThat($haystack, new StringContains($needle, false, true), $message); + } + + /** + * Asserts that two strings are equal except for line endings. + * + * @throws ExpectationFailedException + */ + final public static function assertStringEqualsStringIgnoringLineEndings(string $expected, string $actual, string $message = ''): void + { + static::assertThat($actual, new StringEqualsStringIgnoringLineEndings($expected), $message); + } + + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + */ + final public static function assertFileMatchesFormat(string $format, string $actualFile, string $message = ''): void + { + static::assertFileExists($actualFile, $message); + + static::assertThat( + file_get_contents($actualFile), + new StringMatchesFormatDescription($format), + $message, + ); + } + + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + */ + final public static function assertFileMatchesFormatFile(string $formatFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + static::assertFileExists($actualFile, $message); + + static::assertThat( + file_get_contents($actualFile), + new StringMatchesFormatDescription(file_get_contents($formatFile)), + $message, + ); + } + + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + */ + final public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void + { + static::assertThat($string, new StringMatchesFormatDescription($format), $message); + } + + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 + */ + final public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringMatchesFormatDescription($format), + ), + $message, + ); + } + + /** + * Asserts that a string matches a given format file. + * + * @throws ExpectationFailedException + */ + final public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + + static::assertThat( + $string, + new StringMatchesFormatDescription( + file_get_contents($formatFile), + ), + $message, + ); + } + + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 + */ + final public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + + static::assertThat( + $string, + new LogicalNot( + new StringMatchesFormatDescription( + file_get_contents($formatFile), + ), + ), + $message, + ); + } + + /** + * Asserts that a string starts with a given prefix. + * + * @psalm-param non-empty-string $prefix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + */ + final public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void + { + static::assertThat($string, new StringStartsWith($prefix), $message); + } + + /** + * Asserts that a string starts not with a given prefix. + * + * @psalm-param non-empty-string $prefix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + */ + final public static function assertStringStartsNotWith(string $prefix, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringStartsWith($prefix), + ), + $message, + ); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void + { + $constraint = new StringContains($needle); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + $constraint = new StringContains($needle, true); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new StringContains($needle)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new StringContains($needle, true)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a string ends with a given suffix. + * + * @psalm-param non-empty-string $suffix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + */ + final public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void + { + static::assertThat($string, new StringEndsWith($suffix), $message); + } + + /** + * Asserts that a string ends not with a given suffix. + * + * @psalm-param non-empty-string $suffix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + */ + final public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringEndsWith($suffix), + ), + $message, + ); + } + + /** + * Asserts that two XML files are equal. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws XmlException + */ + final public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + $expected = (new XmlLoader)->loadFile($expectedFile); + $actual = (new XmlLoader)->loadFile($actualFile); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML files are not equal. + * + * @throws \PHPUnit\Util\Exception + * @throws ExpectationFailedException + */ + final public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + $expected = (new XmlLoader)->loadFile($expectedFile); + $actual = (new XmlLoader)->loadFile($actualFile); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @throws ExpectationFailedException + * @throws XmlException + */ + final public static function assertXmlStringEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void + { + $expected = (new XmlLoader)->loadFile($expectedFile); + $actual = (new XmlLoader)->load($actualXml); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @throws ExpectationFailedException + * @throws XmlException + */ + final public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void + { + $expected = (new XmlLoader)->loadFile($expectedFile); + $actual = (new XmlLoader)->load($actualXml); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @throws ExpectationFailedException + * @throws XmlException + */ + final public static function assertXmlStringEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void + { + $expected = (new XmlLoader)->load($expectedXml); + $actual = (new XmlLoader)->load($actualXml); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @throws ExpectationFailedException + * @throws XmlException + */ + final public static function assertXmlStringNotEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void + { + $expected = (new XmlLoader)->load($expectedXml); + $actual = (new XmlLoader)->load($actualXml); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Evaluates a PHPUnit\Framework\Constraint matcher object. + * + * @throws ExpectationFailedException + */ + final public static function assertThat(mixed $value, Constraint $constraint, string $message = ''): void + { + self::$count += count($constraint); + + $hasFailed = true; + + try { + $constraint->evaluate($value, $message); + + $hasFailed = false; + } finally { + if ($hasFailed) { + Event\Facade::emitter()->testAssertionFailed( + $value, + $constraint, + $message, + ); + } else { + Event\Facade::emitter()->testAssertionSucceeded( + $value, + $constraint, + $message, + ); + } + } + } + + /** + * Asserts that a string is a valid JSON string. + * + * @throws ExpectationFailedException + */ + final public static function assertJson(string $actual, string $message = ''): void + { + static::assertThat($actual, static::isJson(), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @throws ExpectationFailedException + */ + final public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat($actualJson, new JsonMatches($expectedJson), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @throws ExpectationFailedException + */ + final public static function assertJsonStringNotEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat( + $actualJson, + new LogicalNot( + new JsonMatches($expectedJson), + ), + $message, + ); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @throws ExpectationFailedException + */ + final public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat($actualJson, new JsonMatches($expectedJson), $message); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @throws ExpectationFailedException + */ + final public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat( + $actualJson, + new LogicalNot( + new JsonMatches($expectedJson), + ), + $message, + ); + } + + /** + * Asserts that two JSON files are equal. + * + * @throws ExpectationFailedException + */ + final public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + static::assertFileExists($actualFile, $message); + + $actualJson = file_get_contents($actualFile); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + $constraintExpected = new JsonMatches( + $expectedJson, + ); + + $constraintActual = new JsonMatches($actualJson); + + static::assertThat($expectedJson, $constraintActual, $message); + static::assertThat($actualJson, $constraintExpected, $message); + } + + /** + * Asserts that two JSON files are not equal. + * + * @throws ExpectationFailedException + */ + final public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + static::assertFileExists($actualFile, $message); + + $actualJson = file_get_contents($actualFile); + $expectedJson = file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + $constraintExpected = new JsonMatches( + $expectedJson, + ); + + $constraintActual = new JsonMatches($actualJson); + + static::assertThat($expectedJson, new LogicalNot($constraintActual), $message); + static::assertThat($actualJson, new LogicalNot($constraintExpected), $message); + } + + /** + * @throws Exception + */ + final public static function logicalAnd(mixed ...$constraints): LogicalAnd + { + return LogicalAnd::fromConstraints(...$constraints); + } + + final public static function logicalOr(mixed ...$constraints): LogicalOr + { + return LogicalOr::fromConstraints(...$constraints); + } + + final public static function logicalNot(Constraint $constraint): LogicalNot + { + return new LogicalNot($constraint); + } + + final public static function logicalXor(mixed ...$constraints): LogicalXor + { + return LogicalXor::fromConstraints(...$constraints); + } + + final public static function anything(): IsAnything + { + return new IsAnything; + } + + final public static function isTrue(): IsTrue + { + return new IsTrue; + } + + /** + * @psalm-template CallbackInput of mixed + * + * @psalm-param callable(CallbackInput $callback): bool $callback + * + * @psalm-return Callback + */ + final public static function callback(callable $callback): Callback + { + return new Callback($callback); + } + + final public static function isFalse(): IsFalse + { + return new IsFalse; + } + + final public static function isJson(): IsJson + { + return new IsJson; + } + + final public static function isNull(): IsNull + { + return new IsNull; + } + + final public static function isFinite(): IsFinite + { + return new IsFinite; + } + + final public static function isInfinite(): IsInfinite + { + return new IsInfinite; + } + + final public static function isNan(): IsNan + { + return new IsNan; + } + + final public static function containsEqual(mixed $value): TraversableContainsEqual + { + return new TraversableContainsEqual($value); + } + + final public static function containsIdentical(mixed $value): TraversableContainsIdentical + { + return new TraversableContainsIdentical($value); + } + + /** + * @throws Exception + */ + final public static function containsOnly(string $type): TraversableContainsOnly + { + return new TraversableContainsOnly($type); + } + + /** + * @throws Exception + */ + final public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly + { + return new TraversableContainsOnly($className, false); + } + + final public static function arrayHasKey(int|string $key): ArrayHasKey + { + return new ArrayHasKey($key); + } + + final public static function isList(): IsList + { + return new IsList; + } + + final public static function equalTo(mixed $value): IsEqual + { + return new IsEqual($value, 0.0, false, false); + } + + final public static function equalToCanonicalizing(mixed $value): IsEqualCanonicalizing + { + return new IsEqualCanonicalizing($value); + } + + final public static function equalToIgnoringCase(mixed $value): IsEqualIgnoringCase + { + return new IsEqualIgnoringCase($value); + } + + final public static function equalToWithDelta(mixed $value, float $delta): IsEqualWithDelta + { + return new IsEqualWithDelta($value, $delta); + } + + final public static function isEmpty(): IsEmpty + { + return new IsEmpty; + } + + final public static function isWritable(): IsWritable + { + return new IsWritable; + } + + final public static function isReadable(): IsReadable + { + return new IsReadable; + } + + final public static function directoryExists(): DirectoryExists + { + return new DirectoryExists; + } + + final public static function fileExists(): FileExists + { + return new FileExists; + } + + final public static function greaterThan(mixed $value): GreaterThan + { + return new GreaterThan($value); + } + + final public static function greaterThanOrEqual(mixed $value): LogicalOr + { + return static::logicalOr( + new IsEqual($value), + new GreaterThan($value), + ); + } + + final public static function identicalTo(mixed $value): IsIdentical + { + return new IsIdentical($value); + } + + /** + * @throws UnknownClassOrInterfaceException + */ + final public static function isInstanceOf(string $className): IsInstanceOf + { + return new IsInstanceOf($className); + } + + /** + * @psalm-param 'array'|'boolean'|'bool'|'double'|'float'|'integer'|'int'|'null'|'numeric'|'object'|'real'|'resource'|'resource (closed)'|'string'|'scalar'|'callable'|'iterable' $type + * + * @throws Exception + */ + final public static function isType(string $type): IsType + { + return new IsType($type); + } + + final public static function lessThan(mixed $value): LessThan + { + return new LessThan($value); + } + + final public static function lessThanOrEqual(mixed $value): LogicalOr + { + return static::logicalOr( + new IsEqual($value), + new LessThan($value), + ); + } + + final public static function matchesRegularExpression(string $pattern): RegularExpression + { + return new RegularExpression($pattern); + } + + final public static function matches(string $string): StringMatchesFormatDescription + { + return new StringMatchesFormatDescription($string); + } + + /** + * @psalm-param non-empty-string $prefix + * + * @throws InvalidArgumentException + */ + final public static function stringStartsWith(string $prefix): StringStartsWith + { + return new StringStartsWith($prefix); + } + + final public static function stringContains(string $string, bool $case = true): StringContains + { + return new StringContains($string, $case); + } + + /** + * @psalm-param non-empty-string $suffix + * + * @throws InvalidArgumentException + */ + final public static function stringEndsWith(string $suffix): StringEndsWith + { + return new StringEndsWith($suffix); + } + + final public static function stringEqualsStringIgnoringLineEndings(string $string): StringEqualsStringIgnoringLineEndings + { + return new StringEqualsStringIgnoringLineEndings($string); + } + + final public static function countOf(int $count): Count + { + return new Count($count); + } + + final public static function objectEquals(object $object, string $method = 'equals'): ObjectEquals + { + return new ObjectEquals($object, $method); + } + + /** + * Fails a test with the given message. + * + * @throws AssertionFailedError + */ + final public static function fail(string $message = ''): never + { + self::$count++; + + throw new AssertionFailedError($message); + } + + /** + * Mark the test as incomplete. + * + * @throws IncompleteTestError + */ + final public static function markTestIncomplete(string $message = ''): never + { + throw new IncompleteTestError($message); + } + + /** + * Mark the test as skipped. + * + * @throws SkippedWithMessageException + */ + final public static function markTestSkipped(string $message = ''): never + { + throw new SkippedWithMessageException($message); + } + + /** + * Return the current assertion count. + */ + final public static function getCount(): int + { + return self::$count; + } + + /** + * Reset the assertion counter. + */ + final public static function resetCount(): void + { + self::$count = 0; + } + + private static function isNativeType(string $type): bool + { + return match ($type) { + 'numeric', 'integer', 'int', 'iterable', 'float', 'string', 'boolean', 'bool', 'null', 'array', 'object', 'resource', 'scalar' => true, + default => false, + }; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php new file mode 100644 index 000000000..cc26cee51 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Assert/Functions.php @@ -0,0 +1,2707 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function func_get_args; +use function function_exists; +use ArrayAccess; +use Countable; +use PHPUnit\Framework\Constraint\ArrayHasKey; +use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\Count; +use PHPUnit\Framework\Constraint\DirectoryExists; +use PHPUnit\Framework\Constraint\FileExists; +use PHPUnit\Framework\Constraint\GreaterThan; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEmpty; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; +use PHPUnit\Framework\Constraint\IsEqualIgnoringCase; +use PHPUnit\Framework\Constraint\IsEqualWithDelta; +use PHPUnit\Framework\Constraint\IsFalse; +use PHPUnit\Framework\Constraint\IsFinite; +use PHPUnit\Framework\Constraint\IsIdentical; +use PHPUnit\Framework\Constraint\IsInfinite; +use PHPUnit\Framework\Constraint\IsInstanceOf; +use PHPUnit\Framework\Constraint\IsJson; +use PHPUnit\Framework\Constraint\IsList; +use PHPUnit\Framework\Constraint\IsNan; +use PHPUnit\Framework\Constraint\IsNull; +use PHPUnit\Framework\Constraint\IsReadable; +use PHPUnit\Framework\Constraint\IsTrue; +use PHPUnit\Framework\Constraint\IsType; +use PHPUnit\Framework\Constraint\IsWritable; +use PHPUnit\Framework\Constraint\LessThan; +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; +use PHPUnit\Framework\Constraint\LogicalOr; +use PHPUnit\Framework\Constraint\LogicalXor; +use PHPUnit\Framework\Constraint\ObjectEquals; +use PHPUnit\Framework\Constraint\RegularExpression; +use PHPUnit\Framework\Constraint\StringContains; +use PHPUnit\Framework\Constraint\StringEndsWith; +use PHPUnit\Framework\Constraint\StringEqualsStringIgnoringLineEndings; +use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; +use PHPUnit\Framework\Constraint\StringStartsWith; +use PHPUnit\Framework\Constraint\TraversableContainsEqual; +use PHPUnit\Framework\Constraint\TraversableContainsIdentical; +use PHPUnit\Framework\Constraint\TraversableContainsOnly; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; +use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; +use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; +use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; +use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; +use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; +use PHPUnit\Framework\MockObject\Stub\ReturnStub; +use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; +use PHPUnit\Util\Xml\XmlException; +use Throwable; + +if (!function_exists('PHPUnit\Framework\assertArrayHasKey')) { + /** + * Asserts that an array has a specified key. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertArrayHasKey + */ + function assertArrayHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void + { + Assert::assertArrayHasKey(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertArrayNotHasKey')) { + /** + * Asserts that an array does not have a specified key. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertArrayNotHasKey + */ + function assertArrayNotHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void + { + Assert::assertArrayNotHasKey(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsList')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsList + */ + function assertIsList(mixed $array, string $message = ''): void + { + Assert::assertIsList(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContains')) { + /** + * Asserts that a haystack contains a needle. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContains + */ + function assertContains(mixed $needle, iterable $haystack, string $message = ''): void + { + Assert::assertContains(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContainsEquals')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContainsEquals + */ + function assertContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void + { + Assert::assertContainsEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotContains')) { + /** + * Asserts that a haystack does not contain a needle. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotContains + */ + function assertNotContains(mixed $needle, iterable $haystack, string $message = ''): void + { + Assert::assertNotContains(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotContainsEquals')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotContainsEquals + */ + function assertNotContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void + { + Assert::assertNotContainsEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContainsOnly')) { + /** + * Asserts that a haystack contains only values of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContainsOnly + */ + function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + Assert::assertContainsOnly(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertContainsOnlyInstancesOf')) { + /** + * Asserts that a haystack contains only instances of a given class name. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertContainsOnlyInstancesOf + */ + function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void + { + Assert::assertContainsOnlyInstancesOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotContainsOnly')) { + /** + * Asserts that a haystack does not contain only values of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotContainsOnly + */ + function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + Assert::assertNotContainsOnly(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertCount')) { + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertCount + */ + function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void + { + Assert::assertCount(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotCount')) { + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotCount + */ + function assertNotCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void + { + Assert::assertNotCount(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEquals')) { + /** + * Asserts that two variables are equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEquals + */ + function assertEquals(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualsCanonicalizing')) { + /** + * Asserts that two variables are equal (canonicalizing). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualsCanonicalizing + */ + function assertEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualsIgnoringCase')) { + /** + * Asserts that two variables are equal (ignoring case). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualsIgnoringCase + */ + function assertEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEqualsWithDelta')) { + /** + * Asserts that two variables are equal (with delta). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEqualsWithDelta + */ + function assertEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void + { + Assert::assertEqualsWithDelta(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEquals')) { + /** + * Asserts that two variables are not equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEquals + */ + function assertNotEquals(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertNotEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEqualsCanonicalizing')) { + /** + * Asserts that two variables are not equal (canonicalizing). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEqualsCanonicalizing + */ + function assertNotEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertNotEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEqualsIgnoringCase')) { + /** + * Asserts that two variables are not equal (ignoring case). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEqualsIgnoringCase + */ + function assertNotEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertNotEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEqualsWithDelta')) { + /** + * Asserts that two variables are not equal (with delta). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEqualsWithDelta + */ + function assertNotEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void + { + Assert::assertNotEqualsWithDelta(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertObjectEquals')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertObjectEquals + */ + function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void + { + Assert::assertObjectEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertEmpty')) { + /** + * Asserts that a variable is empty. + * + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @psalm-assert empty $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertEmpty + */ + function assertEmpty(mixed $actual, string $message = ''): void + { + Assert::assertEmpty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotEmpty')) { + /** + * Asserts that a variable is not empty. + * + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @psalm-assert !empty $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotEmpty + */ + function assertNotEmpty(mixed $actual, string $message = ''): void + { + Assert::assertNotEmpty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertGreaterThan')) { + /** + * Asserts that a value is greater than another value. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertGreaterThan + */ + function assertGreaterThan(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertGreaterThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertGreaterThanOrEqual')) { + /** + * Asserts that a value is greater than or equal to another value. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertGreaterThanOrEqual + */ + function assertGreaterThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertGreaterThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertLessThan')) { + /** + * Asserts that a value is smaller than another value. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertLessThan + */ + function assertLessThan(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertLessThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertLessThanOrEqual')) { + /** + * Asserts that a value is smaller than or equal to another value. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertLessThanOrEqual + */ + function assertLessThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertLessThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileEquals')) { + /** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileEquals + */ + function assertFileEquals(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileEqualsCanonicalizing')) { + /** + * Asserts that the contents of one file is equal to the contents of another + * file (canonicalizing). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileEqualsCanonicalizing + */ + function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileEqualsIgnoringCase')) { + /** + * Asserts that the contents of one file is equal to the contents of another + * file (ignoring case). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileEqualsIgnoringCase + */ + function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotEquals')) { + /** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotEquals + */ + function assertFileNotEquals(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileNotEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotEqualsCanonicalizing')) { + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (canonicalizing). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotEqualsCanonicalizing + */ + function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileNotEqualsCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileNotEqualsIgnoringCase')) { + /** + * Asserts that the contents of one file is not equal to the contents of another + * file (ignoring case). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileNotEqualsIgnoringCase + */ + function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void + { + Assert::assertFileNotEqualsIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsFile')) { + /** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsFile + */ + function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringEqualsFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsFileCanonicalizing')) { + /** + * Asserts that the contents of a string is equal + * to the contents of a file (canonicalizing). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsFileCanonicalizing + */ + function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringEqualsFileCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsFileIgnoringCase')) { + /** + * Asserts that the contents of a string is equal + * to the contents of a file (ignoring case). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsFileIgnoringCase + */ + function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringEqualsFileIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFile')) { + /** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotEqualsFile + */ + function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringNotEqualsFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileCanonicalizing')) { + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (canonicalizing). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotEqualsFileCanonicalizing + */ + function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringNotEqualsFileCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileIgnoringCase')) { + /** + * Asserts that the contents of a string is not equal + * to the contents of a file (ignoring case). + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotEqualsFileIgnoringCase + */ + function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void + { + Assert::assertStringNotEqualsFileIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsReadable')) { + /** + * Asserts that a file/dir is readable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsReadable + */ + function assertIsReadable(string $filename, string $message = ''): void + { + Assert::assertIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotReadable')) { + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotReadable + */ + function assertIsNotReadable(string $filename, string $message = ''): void + { + Assert::assertIsNotReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsWritable')) { + /** + * Asserts that a file/dir exists and is writable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsWritable + */ + function assertIsWritable(string $filename, string $message = ''): void + { + Assert::assertIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotWritable')) { + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotWritable + */ + function assertIsNotWritable(string $filename, string $message = ''): void + { + Assert::assertIsNotWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryExists')) { + /** + * Asserts that a directory exists. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryExists + */ + function assertDirectoryExists(string $directory, string $message = ''): void + { + Assert::assertDirectoryExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryDoesNotExist')) { + /** + * Asserts that a directory does not exist. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryDoesNotExist + */ + function assertDirectoryDoesNotExist(string $directory, string $message = ''): void + { + Assert::assertDirectoryDoesNotExist(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsReadable')) { + /** + * Asserts that a directory exists and is readable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsReadable + */ + function assertDirectoryIsReadable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotReadable')) { + /** + * Asserts that a directory exists and is not readable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsNotReadable + */ + function assertDirectoryIsNotReadable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsNotReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsWritable')) { + /** + * Asserts that a directory exists and is writable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsWritable + */ + function assertDirectoryIsWritable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotWritable')) { + /** + * Asserts that a directory exists and is not writable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDirectoryIsNotWritable + */ + function assertDirectoryIsNotWritable(string $directory, string $message = ''): void + { + Assert::assertDirectoryIsNotWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileExists')) { + /** + * Asserts that a file exists. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileExists + */ + function assertFileExists(string $filename, string $message = ''): void + { + Assert::assertFileExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileDoesNotExist')) { + /** + * Asserts that a file does not exist. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileDoesNotExist + */ + function assertFileDoesNotExist(string $filename, string $message = ''): void + { + Assert::assertFileDoesNotExist(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsReadable')) { + /** + * Asserts that a file exists and is readable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsReadable + */ + function assertFileIsReadable(string $file, string $message = ''): void + { + Assert::assertFileIsReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsNotReadable')) { + /** + * Asserts that a file exists and is not readable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsNotReadable + */ + function assertFileIsNotReadable(string $file, string $message = ''): void + { + Assert::assertFileIsNotReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsWritable')) { + /** + * Asserts that a file exists and is writable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsWritable + */ + function assertFileIsWritable(string $file, string $message = ''): void + { + Assert::assertFileIsWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileIsNotWritable')) { + /** + * Asserts that a file exists and is not writable. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileIsNotWritable + */ + function assertFileIsNotWritable(string $file, string $message = ''): void + { + Assert::assertFileIsNotWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertTrue')) { + /** + * Asserts that a condition is true. + * + * @throws ExpectationFailedException + * + * @psalm-assert true $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertTrue + */ + function assertTrue(mixed $condition, string $message = ''): void + { + Assert::assertTrue(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotTrue')) { + /** + * Asserts that a condition is not true. + * + * @throws ExpectationFailedException + * + * @psalm-assert !true $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotTrue + */ + function assertNotTrue(mixed $condition, string $message = ''): void + { + Assert::assertNotTrue(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFalse')) { + /** + * Asserts that a condition is false. + * + * @throws ExpectationFailedException + * + * @psalm-assert false $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFalse + */ + function assertFalse(mixed $condition, string $message = ''): void + { + Assert::assertFalse(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotFalse')) { + /** + * Asserts that a condition is not false. + * + * @throws ExpectationFailedException + * + * @psalm-assert !false $condition + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotFalse + */ + function assertNotFalse(mixed $condition, string $message = ''): void + { + Assert::assertNotFalse(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNull')) { + /** + * Asserts that a variable is null. + * + * @throws ExpectationFailedException + * + * @psalm-assert null $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNull + */ + function assertNull(mixed $actual, string $message = ''): void + { + Assert::assertNull(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotNull')) { + /** + * Asserts that a variable is not null. + * + * @throws ExpectationFailedException + * + * @psalm-assert !null $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotNull + */ + function assertNotNull(mixed $actual, string $message = ''): void + { + Assert::assertNotNull(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFinite')) { + /** + * Asserts that a variable is finite. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFinite + */ + function assertFinite(mixed $actual, string $message = ''): void + { + Assert::assertFinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertInfinite')) { + /** + * Asserts that a variable is infinite. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertInfinite + */ + function assertInfinite(mixed $actual, string $message = ''): void + { + Assert::assertInfinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNan')) { + /** + * Asserts that a variable is nan. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNan + */ + function assertNan(mixed $actual, string $message = ''): void + { + Assert::assertNan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertObjectHasProperty')) { + /** + * Asserts that an object has a specified property. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertObjectHasProperty + */ + function assertObjectHasProperty(string $propertyName, object $object, string $message = ''): void + { + Assert::assertObjectHasProperty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertObjectNotHasProperty')) { + /** + * Asserts that an object does not have a specified property. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertObjectNotHasProperty + */ + function assertObjectNotHasProperty(string $propertyName, object $object, string $message = ''): void + { + Assert::assertObjectNotHasProperty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertSame')) { + /** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType + * + * @psalm-param ExpectedType $expected + * + * @psalm-assert =ExpectedType $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertSame + */ + function assertSame(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertSame(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotSame')) { + /** + * Asserts that two variables do not have the same type and value. + * Used on objects, it asserts that two variables do not reference + * the same object. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotSame + */ + function assertNotSame(mixed $expected, mixed $actual, string $message = ''): void + { + Assert::assertNotSame(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertInstanceOf')) { + /** + * Asserts that a variable is of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws UnknownClassOrInterfaceException + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert =ExpectedType $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertInstanceOf + */ + function assertInstanceOf(string $expected, mixed $actual, string $message = ''): void + { + Assert::assertInstanceOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotInstanceOf')) { + /** + * Asserts that a variable is not of a given type. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-template ExpectedType of object + * + * @psalm-param class-string $expected + * + * @psalm-assert !ExpectedType $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotInstanceOf + */ + function assertNotInstanceOf(string $expected, mixed $actual, string $message = ''): void + { + Assert::assertNotInstanceOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsArray')) { + /** + * Asserts that a variable is of type array. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert array $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsArray + */ + function assertIsArray(mixed $actual, string $message = ''): void + { + Assert::assertIsArray(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsBool')) { + /** + * Asserts that a variable is of type bool. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert bool $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsBool + */ + function assertIsBool(mixed $actual, string $message = ''): void + { + Assert::assertIsBool(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsFloat')) { + /** + * Asserts that a variable is of type float. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert float $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsFloat + */ + function assertIsFloat(mixed $actual, string $message = ''): void + { + Assert::assertIsFloat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsInt')) { + /** + * Asserts that a variable is of type int. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert int $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsInt + */ + function assertIsInt(mixed $actual, string $message = ''): void + { + Assert::assertIsInt(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNumeric')) { + /** + * Asserts that a variable is of type numeric. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert numeric $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNumeric + */ + function assertIsNumeric(mixed $actual, string $message = ''): void + { + Assert::assertIsNumeric(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsObject')) { + /** + * Asserts that a variable is of type object. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert object $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsObject + */ + function assertIsObject(mixed $actual, string $message = ''): void + { + Assert::assertIsObject(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsResource')) { + /** + * Asserts that a variable is of type resource. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsResource + */ + function assertIsResource(mixed $actual, string $message = ''): void + { + Assert::assertIsResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsClosedResource')) { + /** + * Asserts that a variable is of type resource and is closed. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsClosedResource + */ + function assertIsClosedResource(mixed $actual, string $message = ''): void + { + Assert::assertIsClosedResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsString')) { + /** + * Asserts that a variable is of type string. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert string $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsString + */ + function assertIsString(mixed $actual, string $message = ''): void + { + Assert::assertIsString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsScalar')) { + /** + * Asserts that a variable is of type scalar. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert scalar $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsScalar + */ + function assertIsScalar(mixed $actual, string $message = ''): void + { + Assert::assertIsScalar(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsCallable')) { + /** + * Asserts that a variable is of type callable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert callable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsCallable + */ + function assertIsCallable(mixed $actual, string $message = ''): void + { + Assert::assertIsCallable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsIterable')) { + /** + * Asserts that a variable is of type iterable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert iterable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsIterable + */ + function assertIsIterable(mixed $actual, string $message = ''): void + { + Assert::assertIsIterable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotArray')) { + /** + * Asserts that a variable is not of type array. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !array $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotArray + */ + function assertIsNotArray(mixed $actual, string $message = ''): void + { + Assert::assertIsNotArray(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotBool')) { + /** + * Asserts that a variable is not of type bool. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !bool $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotBool + */ + function assertIsNotBool(mixed $actual, string $message = ''): void + { + Assert::assertIsNotBool(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotFloat')) { + /** + * Asserts that a variable is not of type float. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !float $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotFloat + */ + function assertIsNotFloat(mixed $actual, string $message = ''): void + { + Assert::assertIsNotFloat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotInt')) { + /** + * Asserts that a variable is not of type int. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !int $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotInt + */ + function assertIsNotInt(mixed $actual, string $message = ''): void + { + Assert::assertIsNotInt(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotNumeric')) { + /** + * Asserts that a variable is not of type numeric. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !numeric $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotNumeric + */ + function assertIsNotNumeric(mixed $actual, string $message = ''): void + { + Assert::assertIsNotNumeric(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotObject')) { + /** + * Asserts that a variable is not of type object. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !object $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotObject + */ + function assertIsNotObject(mixed $actual, string $message = ''): void + { + Assert::assertIsNotObject(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotResource')) { + /** + * Asserts that a variable is not of type resource. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotResource + */ + function assertIsNotResource(mixed $actual, string $message = ''): void + { + Assert::assertIsNotResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotClosedResource')) { + /** + * Asserts that a variable is not of type resource. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !resource $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotClosedResource + */ + function assertIsNotClosedResource(mixed $actual, string $message = ''): void + { + Assert::assertIsNotClosedResource(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotString')) { + /** + * Asserts that a variable is not of type string. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !string $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotString + */ + function assertIsNotString(mixed $actual, string $message = ''): void + { + Assert::assertIsNotString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotScalar')) { + /** + * Asserts that a variable is not of type scalar. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !scalar $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotScalar + */ + function assertIsNotScalar(mixed $actual, string $message = ''): void + { + Assert::assertIsNotScalar(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotCallable')) { + /** + * Asserts that a variable is not of type callable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !callable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotCallable + */ + function assertIsNotCallable(mixed $actual, string $message = ''): void + { + Assert::assertIsNotCallable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertIsNotIterable')) { + /** + * Asserts that a variable is not of type iterable. + * + * @throws Exception + * @throws ExpectationFailedException + * + * @psalm-assert !iterable $actual + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertIsNotIterable + */ + function assertIsNotIterable(mixed $actual, string $message = ''): void + { + Assert::assertIsNotIterable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertMatchesRegularExpression')) { + /** + * Asserts that a string matches a given regular expression. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertMatchesRegularExpression + */ + function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void + { + Assert::assertMatchesRegularExpression(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertDoesNotMatchRegularExpression')) { + /** + * Asserts that a string does not match a given regular expression. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertDoesNotMatchRegularExpression + */ + function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void + { + Assert::assertDoesNotMatchRegularExpression(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertSameSize')) { + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertSameSize + */ + function assertSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void + { + Assert::assertSameSize(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertNotSameSize')) { + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws GeneratorNotSupportedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertNotSameSize + */ + function assertNotSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void + { + Assert::assertNotSameSize(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringContainsStringIgnoringLineEndings')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringContainsStringIgnoringLineEndings + */ + function assertStringContainsStringIgnoringLineEndings(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringContainsStringIgnoringLineEndings(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEqualsStringIgnoringLineEndings')) { + /** + * Asserts that two strings are equal except for line endings. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEqualsStringIgnoringLineEndings + */ + function assertStringEqualsStringIgnoringLineEndings(string $expected, string $actual, string $message = ''): void + { + Assert::assertStringEqualsStringIgnoringLineEndings(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileMatchesFormat')) { + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileMatchesFormat + */ + function assertFileMatchesFormat(string $format, string $actualFile, string $message = ''): void + { + Assert::assertFileMatchesFormat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertFileMatchesFormatFile')) { + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertFileMatchesFormatFile + */ + function assertFileMatchesFormatFile(string $formatFile, string $actualFile, string $message = ''): void + { + Assert::assertFileMatchesFormatFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringMatchesFormat')) { + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringMatchesFormat + */ + function assertStringMatchesFormat(string $format, string $string, string $message = ''): void + { + Assert::assertStringMatchesFormat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormat')) { + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotMatchesFormat + */ + function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void + { + Assert::assertStringNotMatchesFormat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringMatchesFormatFile')) { + /** + * Asserts that a string matches a given format file. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringMatchesFormatFile + */ + function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + Assert::assertStringMatchesFormatFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormatFile')) { + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotMatchesFormatFile + */ + function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + Assert::assertStringNotMatchesFormatFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringStartsWith')) { + /** + * Asserts that a string starts with a given prefix. + * + * @psalm-param non-empty-string $prefix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringStartsWith + */ + function assertStringStartsWith(string $prefix, string $string, string $message = ''): void + { + Assert::assertStringStartsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringStartsNotWith')) { + /** + * Asserts that a string starts not with a given prefix. + * + * @psalm-param non-empty-string $prefix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringStartsNotWith + */ + function assertStringStartsNotWith(string $prefix, string $string, string $message = ''): void + { + Assert::assertStringStartsNotWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringContainsString')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringContainsString + */ + function assertStringContainsString(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringContainsString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringContainsStringIgnoringCase')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringContainsStringIgnoringCase + */ + function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringContainsStringIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotContainsString')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotContainsString + */ + function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringNotContainsString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringNotContainsStringIgnoringCase')) { + /** + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringNotContainsStringIgnoringCase + */ + function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + Assert::assertStringNotContainsStringIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEndsWith')) { + /** + * Asserts that a string ends with a given suffix. + * + * @psalm-param non-empty-string $suffix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEndsWith + */ + function assertStringEndsWith(string $suffix, string $string, string $message = ''): void + { + Assert::assertStringEndsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertStringEndsNotWith')) { + /** + * Asserts that a string ends not with a given suffix. + * + * @psalm-param non-empty-string $suffix + * + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertStringEndsNotWith + */ + function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void + { + Assert::assertStringEndsNotWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlFileEqualsXmlFile')) { + /** + * Asserts that two XML files are equal. + * + * @throws Exception + * @throws ExpectationFailedException + * @throws XmlException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlFileEqualsXmlFile + */ + function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertXmlFileEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlFileNotEqualsXmlFile')) { + /** + * Asserts that two XML files are not equal. + * + * @throws \PHPUnit\Util\Exception + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlFileNotEqualsXmlFile + */ + function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertXmlFileNotEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlFile')) { + /** + * Asserts that two XML documents are equal. + * + * @throws ExpectationFailedException + * @throws XmlException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringEqualsXmlFile + */ + function assertXmlStringEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void + { + Assert::assertXmlStringEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlFile')) { + /** + * Asserts that two XML documents are not equal. + * + * @throws ExpectationFailedException + * @throws XmlException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringNotEqualsXmlFile + */ + function assertXmlStringNotEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void + { + Assert::assertXmlStringNotEqualsXmlFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlString')) { + /** + * Asserts that two XML documents are equal. + * + * @throws ExpectationFailedException + * @throws XmlException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringEqualsXmlString + */ + function assertXmlStringEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void + { + Assert::assertXmlStringEqualsXmlString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlString')) { + /** + * Asserts that two XML documents are not equal. + * + * @throws ExpectationFailedException + * @throws XmlException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertXmlStringNotEqualsXmlString + */ + function assertXmlStringNotEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void + { + Assert::assertXmlStringNotEqualsXmlString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertThat')) { + /** + * Evaluates a PHPUnit\Framework\Constraint matcher object. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertThat + */ + function assertThat(mixed $value, Constraint $constraint, string $message = ''): void + { + Assert::assertThat(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJson')) { + /** + * Asserts that a string is a valid JSON string. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJson + */ + function assertJson(string $actual, string $message = ''): void + { + Assert::assertJson(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonString')) { + /** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringEqualsJsonString + */ + function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringEqualsJsonString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonString')) { + /** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringNotEqualsJsonString + */ + function assertJsonStringNotEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringNotEqualsJsonString(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonFile')) { + /** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringEqualsJsonFile + */ + function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonFile')) { + /** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonStringNotEqualsJsonFile + */ + function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + Assert::assertJsonStringNotEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonFileEqualsJsonFile')) { + /** + * Asserts that two JSON files are equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonFileEqualsJsonFile + */ + function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertJsonFileEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\assertJsonFileNotEqualsJsonFile')) { + /** + * Asserts that two JSON files are not equal. + * + * @throws ExpectationFailedException + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @see Assert::assertJsonFileNotEqualsJsonFile + */ + function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + Assert::assertJsonFileNotEqualsJsonFile(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalAnd')) { + function logicalAnd(mixed ...$constraints): LogicalAnd + { + return Assert::logicalAnd(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalOr')) { + function logicalOr(mixed ...$constraints): LogicalOr + { + return Assert::logicalOr(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalNot')) { + function logicalNot(Constraint $constraint): LogicalNot + { + return Assert::logicalNot(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\logicalXor')) { + function logicalXor(mixed ...$constraints): LogicalXor + { + return Assert::logicalXor(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\anything')) { + function anything(): IsAnything + { + return Assert::anything(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isTrue')) { + function isTrue(): IsTrue + { + return Assert::isTrue(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isFalse')) { + function isFalse(): IsFalse + { + return Assert::isFalse(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isJson')) { + function isJson(): IsJson + { + return Assert::isJson(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isNull')) { + function isNull(): IsNull + { + return Assert::isNull(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isFinite')) { + function isFinite(): IsFinite + { + return Assert::isFinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isInfinite')) { + function isInfinite(): IsInfinite + { + return Assert::isInfinite(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isNan')) { + function isNan(): IsNan + { + return Assert::isNan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsEqual')) { + function containsEqual(mixed $value): TraversableContainsEqual + { + return Assert::containsEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsIdentical')) { + function containsIdentical(mixed $value): TraversableContainsIdentical + { + return Assert::containsIdentical(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsOnly')) { + function containsOnly(string $type): TraversableContainsOnly + { + return Assert::containsOnly(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\containsOnlyInstancesOf')) { + function containsOnlyInstancesOf(string $className): TraversableContainsOnly + { + return Assert::containsOnlyInstancesOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\arrayHasKey')) { + function arrayHasKey(int|string $key): ArrayHasKey + { + return Assert::arrayHasKey(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isList')) { + function isList(): IsList + { + return Assert::isList(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalTo')) { + function equalTo(mixed $value): IsEqual + { + return Assert::equalTo(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalToCanonicalizing')) { + function equalToCanonicalizing(mixed $value): IsEqualCanonicalizing + { + return Assert::equalToCanonicalizing(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalToIgnoringCase')) { + function equalToIgnoringCase(mixed $value): IsEqualIgnoringCase + { + return Assert::equalToIgnoringCase(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\equalToWithDelta')) { + function equalToWithDelta(mixed $value, float $delta): IsEqualWithDelta + { + return Assert::equalToWithDelta(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isEmpty')) { + function isEmpty(): IsEmpty + { + return Assert::isEmpty(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isWritable')) { + function isWritable(): IsWritable + { + return Assert::isWritable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isReadable')) { + function isReadable(): IsReadable + { + return Assert::isReadable(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\directoryExists')) { + function directoryExists(): DirectoryExists + { + return Assert::directoryExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\fileExists')) { + function fileExists(): FileExists + { + return Assert::fileExists(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\greaterThan')) { + function greaterThan(mixed $value): GreaterThan + { + return Assert::greaterThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\greaterThanOrEqual')) { + function greaterThanOrEqual(mixed $value): LogicalOr + { + return Assert::greaterThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\identicalTo')) { + function identicalTo(mixed $value): IsIdentical + { + return Assert::identicalTo(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isInstanceOf')) { + function isInstanceOf(string $className): IsInstanceOf + { + return Assert::isInstanceOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\isType')) { + function isType(string $type): IsType + { + return Assert::isType(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\lessThan')) { + function lessThan(mixed $value): LessThan + { + return Assert::lessThan(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\lessThanOrEqual')) { + function lessThanOrEqual(mixed $value): LogicalOr + { + return Assert::lessThanOrEqual(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\matchesRegularExpression')) { + function matchesRegularExpression(string $pattern): RegularExpression + { + return Assert::matchesRegularExpression(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\matches')) { + function matches(string $string): StringMatchesFormatDescription + { + return Assert::matches(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringStartsWith')) { + function stringStartsWith(string $prefix): StringStartsWith + { + return Assert::stringStartsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringContains')) { + function stringContains(string $string, bool $case = true): StringContains + { + return Assert::stringContains(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringEndsWith')) { + function stringEndsWith(string $suffix): StringEndsWith + { + return Assert::stringEndsWith(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\stringEqualsStringIgnoringLineEndings')) { + function stringEqualsStringIgnoringLineEndings(string $string): StringEqualsStringIgnoringLineEndings + { + return Assert::stringEqualsStringIgnoringLineEndings(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\countOf')) { + function countOf(int $count): Count + { + return Assert::countOf(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\objectEquals')) { + function objectEquals(object $object, string $method = 'equals'): ObjectEquals + { + return Assert::objectEquals(...func_get_args()); + } +} + +if (!function_exists('PHPUnit\Framework\callback')) { + /** + * @psalm-template CallbackInput of mixed + * + * @psalm-param callable(CallbackInput $callback): bool $callback + * + * @psalm-return Callback + */ + function callback(callable $callback): Callback + { + return Assert::callback($callback); + } +} + +if (!function_exists('PHPUnit\Framework\any')) { + /** + * Returns a matcher that matches when the method is executed + * zero or more times. + */ + function any(): AnyInvokedCountMatcher + { + return new AnyInvokedCountMatcher; + } +} + +if (!function_exists('PHPUnit\Framework\never')) { + /** + * Returns a matcher that matches when the method is never executed. + */ + function never(): InvokedCountMatcher + { + return new InvokedCountMatcher(0); + } +} + +if (!function_exists('PHPUnit\Framework\atLeast')) { + /** + * Returns a matcher that matches when the method is executed + * at least N times. + */ + function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher + { + return new InvokedAtLeastCountMatcher( + $requiredInvocations, + ); + } +} + +if (!function_exists('PHPUnit\Framework\atLeastOnce')) { + /** + * Returns a matcher that matches when the method is executed at least once. + */ + function atLeastOnce(): InvokedAtLeastOnceMatcher + { + return new InvokedAtLeastOnceMatcher; + } +} + +if (!function_exists('PHPUnit\Framework\once')) { + /** + * Returns a matcher that matches when the method is executed exactly once. + */ + function once(): InvokedCountMatcher + { + return new InvokedCountMatcher(1); + } +} + +if (!function_exists('PHPUnit\Framework\exactly')) { + /** + * Returns a matcher that matches when the method is executed + * exactly $count times. + */ + function exactly(int $count): InvokedCountMatcher + { + return new InvokedCountMatcher($count); + } +} + +if (!function_exists('PHPUnit\Framework\atMost')) { + /** + * Returns a matcher that matches when the method is executed + * at most N times. + */ + function atMost(int $allowedInvocations): InvokedAtMostCountMatcher + { + return new InvokedAtMostCountMatcher($allowedInvocations); + } +} + +if (!function_exists('PHPUnit\Framework\returnValue')) { + function returnValue(mixed $value): ReturnStub + { + return new ReturnStub($value); + } +} + +if (!function_exists('PHPUnit\Framework\returnValueMap')) { + function returnValueMap(array $valueMap): ReturnValueMapStub + { + return new ReturnValueMapStub($valueMap); + } +} + +if (!function_exists('PHPUnit\Framework\returnArgument')) { + function returnArgument(int $argumentIndex): ReturnArgumentStub + { + return new ReturnArgumentStub($argumentIndex); + } +} + +if (!function_exists('PHPUnit\Framework\returnCallback')) { + function returnCallback(callable $callback): ReturnCallbackStub + { + return new ReturnCallbackStub($callback); + } +} + +if (!function_exists('PHPUnit\Framework\returnSelf')) { + /** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + */ + function returnSelf(): ReturnSelfStub + { + return new ReturnSelfStub; + } +} + +if (!function_exists('PHPUnit\Framework\throwException')) { + function throwException(Throwable $exception): ExceptionStub + { + return new ExceptionStub($exception); + } +} + +if (!function_exists('PHPUnit\Framework\onConsecutiveCalls')) { + function onConsecutiveCalls(): ConsecutiveCallsStub + { + $arguments = func_get_args(); + + return new ConsecutiveCallsStub($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/After.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/After.php new file mode 100644 index 000000000..6fe0a3c83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/After.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class After +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/AfterClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/AfterClass.php new file mode 100644 index 000000000..8ef97f250 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/AfterClass.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class AfterClass +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php new file mode 100644 index 000000000..481687e45 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupGlobals.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class BackupGlobals +{ + private readonly bool $enabled; + + public function __construct(bool $enabled) + { + $this->enabled = $enabled; + } + + public function enabled(): bool + { + return $this->enabled; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php new file mode 100644 index 000000000..8fa215b0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BackupStaticProperties.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class BackupStaticProperties +{ + private readonly bool $enabled; + + public function __construct(bool $enabled) + { + $this->enabled = $enabled; + } + + public function enabled(): bool + { + return $this->enabled; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Before.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Before.php new file mode 100644 index 000000000..39ecf437c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Before.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class Before +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php new file mode 100644 index 000000000..4ea55e0d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/BeforeClass.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class BeforeClass +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php new file mode 100644 index 000000000..38ec37ad4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CodeCoverageIgnore.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5236 + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class CodeCoverageIgnore +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversClass.php new file mode 100644 index 000000000..9b070c8af --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversClass.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class CoversClass +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php new file mode 100644 index 000000000..ad0bbd283 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversFunction.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class CoversFunction +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param non-empty-string $functionName + */ + public function __construct(string $functionName) + { + $this->functionName = $functionName; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php new file mode 100644 index 000000000..8ac6a2ed1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/CoversNothing.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class CoversNothing +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProvider.php new file mode 100644 index 000000000..d31130fb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProvider.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DataProvider +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $methodName) + { + $this->methodName = $methodName; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php new file mode 100644 index 000000000..37f85868d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DataProviderExternal.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DataProviderExternal +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Depends.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Depends.php new file mode 100644 index 000000000..38daf1efc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Depends.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class Depends +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $methodName) + { + $this->methodName = $methodName; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php new file mode 100644 index 000000000..ba5bc3229 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternal.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsExternal +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php new file mode 100644 index 000000000..9e426abac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsExternalUsingDeepClone +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php new file mode 100644 index 000000000..5b9a85dfc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsExternalUsingShallowClone +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php new file mode 100644 index 000000000..73722e36c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClass.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsOnClass +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php new file mode 100644 index 000000000..7ce05476d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsOnClassUsingDeepClone +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php new file mode 100644 index 000000000..206c0add4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsOnClassUsingShallowClone +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php new file mode 100644 index 000000000..11c4091c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingDeepClone.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsUsingDeepClone +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $methodName) + { + $this->methodName = $methodName; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php new file mode 100644 index 000000000..0812c85c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DependsUsingShallowClone.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class DependsUsingShallowClone +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $methodName) + { + $this->methodName = $methodName; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php new file mode 100644 index 000000000..3d6045a22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class DoesNotPerformAssertions +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php new file mode 100644 index 000000000..dcd7a12b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class ExcludeGlobalVariableFromBackup +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $globalVariableName; + + /** + * @psalm-param non-empty-string $globalVariableName + */ + public function __construct(string $globalVariableName) + { + $this->globalVariableName = $globalVariableName; + } + + /** + * @psalm-return non-empty-string + */ + public function globalVariableName(): string + { + return $this->globalVariableName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php new file mode 100644 index 000000000..64b25ed50 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class ExcludeStaticPropertyFromBackup +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $propertyName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $propertyName + */ + public function __construct(string $className, string $propertyName) + { + $this->className = $className; + $this->propertyName = $propertyName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function propertyName(): string + { + return $this->propertyName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Group.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Group.php new file mode 100644 index 000000000..feccb287c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Group.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class Group +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $name; + + /** + * @psalm-param non-empty-string $name + */ + public function __construct(string $name) + { + $this->name = $name; + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->name; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.php new file mode 100644 index 000000000..283550742 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreClassForCodeCoverage.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 PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class IgnoreClassForCodeCoverage +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php new file mode 100644 index 000000000..cf48aac1e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreDeprecations.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class IgnoreDeprecations +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.php new file mode 100644 index 000000000..90a4bab0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreFunctionForCodeCoverage.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 PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class IgnoreFunctionForCodeCoverage +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param non-empty-string $functionName + */ + public function __construct(string $functionName) + { + $this->functionName = $functionName; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php new file mode 100644 index 000000000..a76188f9e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/IgnoreMethodForCodeCoverage.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class IgnoreMethodForCodeCoverage +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Large.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Large.php new file mode 100644 index 000000000..6d46c1b44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Large.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS)] +final class Large +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Medium.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Medium.php new file mode 100644 index 000000000..40e9c4518 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Medium.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS)] +final class Medium +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PostCondition.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PostCondition.php new file mode 100644 index 000000000..461aab42d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PostCondition.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class PostCondition +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreCondition.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreCondition.php new file mode 100644 index 000000000..120ed6c19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreCondition.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class PreCondition +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php new file mode 100644 index 000000000..69bc3f52e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/PreserveGlobalState.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class PreserveGlobalState +{ + private readonly bool $enabled; + + public function __construct(bool $enabled) + { + $this->enabled = $enabled; + } + + public function enabled(): bool + { + return $this->enabled; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php new file mode 100644 index 000000000..250915d66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresFunction.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class RequiresFunction +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param non-empty-string $functionName + */ + public function __construct(string $functionName) + { + $this->functionName = $functionName; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php new file mode 100644 index 000000000..120c705a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresMethod.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class RequiresMethod +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php new file mode 100644 index 000000000..cbf821170 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystem.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class RequiresOperatingSystem +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $regularExpression; + + /** + * @psalm-param non-empty-string $regularExpression + */ + public function __construct(string $regularExpression) + { + $this->regularExpression = $regularExpression; + } + + /** + * @psalm-return non-empty-string + */ + public function regularExpression(): string + { + return $this->regularExpression; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php new file mode 100644 index 000000000..d4e2c92b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class RequiresOperatingSystemFamily +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $operatingSystemFamily; + + /** + * @psalm-param non-empty-string $operatingSystemFamily + */ + public function __construct(string $operatingSystemFamily) + { + $this->operatingSystemFamily = $operatingSystemFamily; + } + + /** + * @psalm-return non-empty-string + */ + public function operatingSystemFamily(): string + { + return $this->operatingSystemFamily; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php new file mode 100644 index 000000000..a6c20b37e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhp.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class RequiresPhp +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $versionRequirement; + + /** + * @psalm-param non-empty-string $versionRequirement + */ + public function __construct(string $versionRequirement) + { + $this->versionRequirement = $versionRequirement; + } + + /** + * @psalm-return non-empty-string + */ + public function versionRequirement(): string + { + return $this->versionRequirement; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php new file mode 100644 index 000000000..ab3b57a39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpExtension.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class RequiresPhpExtension +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $extension; + + /** + * @psalm-var null|non-empty-string + */ + private readonly ?string $versionRequirement; + + /** + * @psalm-param non-empty-string $extension + * @psalm-param null|non-empty-string $versionRequirement + */ + public function __construct(string $extension, ?string $versionRequirement = null) + { + $this->extension = $extension; + $this->versionRequirement = $versionRequirement; + } + + /** + * @psalm-return non-empty-string + */ + public function extension(): string + { + return $this->extension; + } + + /** + * @psalm-return null|non-empty-string + */ + public function versionRequirement(): ?string + { + return $this->versionRequirement; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php new file mode 100644 index 000000000..908e400b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresPhpunit.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class RequiresPhpunit +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $versionRequirement; + + /** + * @psalm-param non-empty-string $versionRequirement + */ + public function __construct(string $versionRequirement) + { + $this->versionRequirement = $versionRequirement; + } + + /** + * @psalm-return non-empty-string + */ + public function versionRequirement(): string + { + return $this->versionRequirement; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php new file mode 100644 index 000000000..cb7127ab8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RequiresSetting.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class RequiresSetting +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $setting; + + /** + * @psalm-var non-empty-string + */ + private readonly string $value; + + /** + * @psalm-param non-empty-string $setting + * @psalm-param non-empty-string $value + */ + public function __construct(string $setting, string $value) + { + $this->setting = $setting; + $this->value = $value; + } + + /** + * @psalm-return non-empty-string + */ + public function setting(): string + { + return $this->setting; + } + + /** + * @psalm-return non-empty-string + */ + public function value(): string + { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php new file mode 100644 index 000000000..621774fb4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS)] +final class RunClassInSeparateProcess +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php new file mode 100644 index 000000000..dd0066bfa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunInSeparateProcess.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class RunInSeparateProcess +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php new file mode 100644 index 000000000..b823ccb13 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS)] +final class RunTestsInSeparateProcesses +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Small.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Small.php new file mode 100644 index 000000000..598b6540b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Small.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS)] +final class Small +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Test.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Test.php new file mode 100644 index 000000000..711d58d24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Test.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class Test +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestDox.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestDox.php new file mode 100644 index 000000000..f49c4bd59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestDox.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +final class TestDox +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $text; + + /** + * @psalm-param non-empty-string $text + */ + public function __construct(string $text) + { + $this->text = $text; + } + + /** + * @psalm-return non-empty-string + */ + public function text(): string + { + return $this->text; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWith.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWith.php new file mode 100644 index 000000000..ed20baa8e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWith.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class TestWith +{ + private readonly array $data; + + public function __construct(array $data) + { + $this->data = $data; + } + + public function data(): array + { + return $this->data; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php new file mode 100644 index 000000000..b1cbc3408 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/TestWithJson.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class TestWithJson +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $json; + + /** + * @psalm-param non-empty-string $json + */ + public function __construct(string $json) + { + $this->json = $json; + } + + /** + * @psalm-return non-empty-string + */ + public function json(): string + { + return $this->json; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Ticket.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Ticket.php new file mode 100644 index 000000000..c0418e537 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/Ticket.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +final class Ticket +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $text; + + /** + * @psalm-param non-empty-string $text + */ + public function __construct(string $text) + { + $this->text = $text; + } + + /** + * @psalm-return non-empty-string + */ + public function text(): string + { + return $this->text; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesClass.php new file mode 100644 index 000000000..78c64e7bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesClass.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class UsesClass +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php new file mode 100644 index 000000000..9e108adb0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/UsesFunction.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] +final class UsesFunction +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param non-empty-string $functionName + */ + public function __construct(string $functionName) + { + $this->functionName = $functionName; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php new file mode 100644 index 000000000..2dce1e98d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Attributes/WithoutErrorHandler.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Attributes; + +use Attribute; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +#[Attribute(Attribute::TARGET_METHOD)] +final class WithoutErrorHandler +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php new file mode 100644 index 000000000..5846cf19c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsFalse.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsFalse extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is false'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $other === false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php new file mode 100644 index 000000000..be589523b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Boolean/IsTrue.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsTrue extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is true'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $other === true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php new file mode 100644 index 000000000..8a0e1b8a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Callback.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use Closure; +use ReflectionFunction; + +/** + * @psalm-template CallbackInput of mixed + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Callback extends Constraint +{ + /** + * @psalm-var callable(CallbackInput $input): bool + */ + private readonly mixed $callback; + + /** + * @psalm-param callable(CallbackInput $input): bool $callback + */ + public function __construct(callable $callback) + { + $this->callback = $callback; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is accepted by specified callback'; + } + + /** + * @psalm-suppress ArgumentTypeCoercion + */ + public function isVariadic(): bool + { + foreach ((new ReflectionFunction(Closure::fromCallable($this->callback)))->getParameters() as $parameter) { + if ($parameter->isVariadic()) { + return true; + } + } + + return false; + } + + /** + * Evaluates the constraint for parameter $value. Returns true if the + * constraint is met, false otherwise. + * + * @psalm-param CallbackInput $other + * + * @psalm-suppress InvalidArgument + */ + protected function matches(mixed $other): bool + { + if ($this->isVariadic()) { + return ($this->callback)(...$other); + } + + return ($this->callback)($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php new file mode 100644 index 000000000..2ec012a0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/Count.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function count; +use function is_countable; +use function iterator_count; +use function sprintf; +use EmptyIterator; +use Generator; +use Iterator; +use IteratorAggregate; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\GeneratorNotSupportedException; +use Traversable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +class Count extends Constraint +{ + private readonly int $expectedCount; + + public function __construct(int $expected) + { + $this->expectedCount = $expected; + } + + public function toString(): string + { + return sprintf( + 'count matches %d', + $this->expectedCount, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @throws Exception + */ + protected function matches(mixed $other): bool + { + return $this->expectedCount === $this->getCountOf($other); + } + + /** + * @throws Exception + */ + protected function getCountOf(mixed $other): ?int + { + if (is_countable($other)) { + return count($other); + } + + if ($other instanceof EmptyIterator) { + return 0; + } + + if ($other instanceof Traversable) { + while ($other instanceof IteratorAggregate) { + try { + $other = $other->getIterator(); + } catch (\Exception $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } + + $iterator = $other; + + if ($iterator instanceof Generator) { + throw new GeneratorNotSupportedException; + } + + if (!$iterator instanceof Iterator) { + return iterator_count($iterator); + } + + $key = $iterator->key(); + $count = iterator_count($iterator); + + // Manually rewind $iterator to previous key, since iterator_count + // moves pointer. + if ($key !== null) { + $iterator->rewind(); + + while ($iterator->valid() && $key !== $iterator->key()) { + $iterator->next(); + } + } + + return $count; + } + + return null; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @throws Exception + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + 'actual size %d matches expected size %d', + (int) $this->getCountOf($other), + $this->expectedCount, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php new file mode 100644 index 000000000..7e8f0ee64 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class GreaterThan extends Constraint +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + return 'is greater than ' . Exporter::export($this->value, $exportObjects); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $this->value < $other; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php new file mode 100644 index 000000000..ddf4a9f7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function count; +use function gettype; +use function sprintf; +use function str_starts_with; +use Countable; +use EmptyIterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEmpty extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is empty'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + if ($other instanceof EmptyIterator) { + return true; + } + + if ($other instanceof Countable) { + return count($other) === 0; + } + + return empty($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + $type = gettype($other); + + return sprintf( + '%s %s %s', + str_starts_with($type, 'a') || str_starts_with($type, 'o') ? 'an' : 'a', + $type, + $this->toString(true), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php new file mode 100644 index 000000000..cc3ec3440 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/LessThan.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LessThan extends Constraint +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + return 'is less than ' . Exporter::export($this->value, $exportObjects); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $this->value > $other; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php new file mode 100644 index 000000000..f3cd3c3d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Cardinality/SameSize.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use Countable; +use PHPUnit\Framework\Exception; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class SameSize extends Count +{ + /** + * @psalm-param Countable|iterable $expected + * + * @throws Exception + */ + public function __construct($expected) + { + parent::__construct((int) $this->getCountOf($expected)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php new file mode 100644 index 000000000..1fead9ade --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php @@ -0,0 +1,264 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function gettype; +use function sprintf; +use function strtolower; +use Countable; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Util\Exporter; +use SebastianBergmann\Comparator\ComparisonFailure; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Constraint implements Countable, SelfDescribing +{ + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + $success = false; + + if ($this->matches($other)) { + $success = true; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return 1; + } + + /** + * @deprecated + */ + protected function exporter(): \SebastianBergmann\Exporter\Exporter + { + return new \SebastianBergmann\Exporter\Exporter; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + */ + protected function matches(mixed $other): bool + { + return false; + } + + /** + * Throws an exception for the given compared value and test description. + * + * @throws ExpectationFailedException + */ + protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never + { + $failureDescription = sprintf( + 'Failed asserting that %s.', + $this->failureDescription($other), + ); + + $additionalFailureDescription = $this->additionalFailureDescription($other); + + if ($additionalFailureDescription) { + $failureDescription .= "\n" . $additionalFailureDescription; + } + + if (!empty($description)) { + $failureDescription = $description . "\n" . $failureDescription; + } + + throw new ExpectationFailedException( + $failureDescription, + $comparisonFailure, + ); + } + + /** + * Return additional failure description where needed. + * + * The function can be overridden to provide additional failure + * information like a diff + */ + protected function additionalFailureDescription(mixed $other): string + { + return ''; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * To provide additional failure information additionalFailureDescription + * can be used. + */ + protected function failureDescription(mixed $other): string + { + return Exporter::export($other, true) . ' ' . $this->toString(true); + } + + /** + * Returns a custom string representation of the constraint object when it + * appears in context of an $operator expression. + * + * The purpose of this method is to provide meaningful descriptive string + * in context of operators such as LogicalNot. Native PHPUnit constraints + * are supported out of the box by LogicalNot, but externally developed + * ones had no way to provide correct strings in this context. + * + * The method shall return empty string, when it does not handle + * customization by itself. + */ + protected function toStringInContext(Operator $operator, mixed $role): string + { + return ''; + } + + /** + * Returns the description of the failure when this constraint appears in + * context of an $operator expression. + * + * The purpose of this method is to provide meaningful failure description + * in context of operators such as LogicalNot. Native PHPUnit constraints + * are supported out of the box by LogicalNot, but externally developed + * ones had no way to provide correct messages in this context. + * + * The method shall return empty string, when it does not handle + * customization by itself. + */ + protected function failureDescriptionInContext(Operator $operator, mixed $role, mixed $other): string + { + $string = $this->toStringInContext($operator, $role); + + if ($string === '') { + return ''; + } + + return Exporter::export($other, true) . ' ' . $string; + } + + /** + * Reduces the sub-expression starting at $this by skipping degenerate + * sub-expression and returns first descendant constraint that starts + * a non-reducible sub-expression. + * + * Returns $this for terminal constraints and for operators that start + * non-reducible sub-expression, or the nearest descendant of $this that + * starts a non-reducible sub-expression. + * + * A constraint expression may be modelled as a tree with non-terminal + * nodes (operators) and terminal nodes. For example: + * + * LogicalOr (operator, non-terminal) + * + LogicalAnd (operator, non-terminal) + * | + IsType('int') (terminal) + * | + GreaterThan(10) (terminal) + * + LogicalNot (operator, non-terminal) + * + IsType('array') (terminal) + * + * A degenerate sub-expression is a part of the tree, that effectively does + * not contribute to the evaluation of the expression it appears in. An example + * of degenerate sub-expression is a BinaryOperator constructed with single + * operand or nested BinaryOperators, each with single operand. An + * expression involving a degenerate sub-expression is equivalent to a + * reduced expression with the degenerate sub-expression removed, for example + * + * LogicalAnd (operator) + * + LogicalOr (degenerate operator) + * | + LogicalAnd (degenerate operator) + * | + IsType('int') (terminal) + * + GreaterThan(10) (terminal) + * + * is equivalent to + * + * LogicalAnd (operator) + * + IsType('int') (terminal) + * + GreaterThan(10) (terminal) + * + * because the subexpression + * + * + LogicalOr + * + LogicalAnd + * + - + * + * is degenerate. Calling reduce() on the LogicalOr object above, as well + * as on LogicalAnd, shall return the IsType('int') instance. + * + * Other specific reductions can be implemented, for example cascade of + * LogicalNot operators + * + * + LogicalNot + * + LogicalNot + * +LogicalNot + * + IsTrue + * + * can be reduced to + * + * LogicalNot + * + IsTrue + */ + protected function reduce(): self + { + return $this; + } + + /** + * @psalm-return non-empty-string + */ + protected function valueToTypeStringFragment(mixed $value): string + { + $type = strtolower(gettype($value)); + + if ($type === 'double') { + $type = 'float'; + } + + if ($type === 'resource (closed)') { + $type = 'closed resource'; + } + + return match ($type) { + 'array', 'integer', 'object' => 'an ' . $type . ' ', + 'boolean', 'closed resource', 'float', 'resource', 'string' => 'a ' . $type . ' ', + 'null' => 'null ', + default => 'a value of ' . $type . ' ', + }; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php new file mode 100644 index 000000000..2238475d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function sprintf; +use function str_contains; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\Exporter; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqual extends Constraint +{ + private readonly mixed $value; + private readonly float $delta; + private readonly bool $canonicalize; + private readonly bool $ignoreCase; + + public function __construct(mixed $value, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false) + { + $this->value = $value; + $this->delta = $delta; + $this->canonicalize = $canonicalize; + $this->ignoreCase = $ignoreCase; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other, + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta, + $this->canonicalize, + $this->ignoreCase, + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f, + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + $delta = ''; + + if (is_string($this->value)) { + if (str_contains($this->value, "\n")) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value, + ); + } + + if ($this->delta != 0) { + $delta = sprintf( + ' with delta <%F>', + $this->delta, + ); + } + + return sprintf( + 'is equal to %s%s', + Exporter::export($this->value, $exportObjects), + $delta, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php new file mode 100644 index 000000000..425569d1a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function sprintf; +use function str_contains; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\Exporter; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqualCanonicalizing extends Constraint +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other, + ); + + $comparator->assertEquals( + $this->value, + $other, + 0.0, + true, + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f, + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + if (is_string($this->value)) { + if (str_contains($this->value, "\n")) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value, + ); + } + + return sprintf( + 'is equal to %s', + Exporter::export($this->value, $exportObjects), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php new file mode 100644 index 000000000..f5b9b99d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function sprintf; +use function str_contains; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\Exporter; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqualIgnoringCase extends Constraint +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other, + ); + + $comparator->assertEquals( + $this->value, + $other, + 0.0, + false, + true, + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f, + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + if (is_string($this->value)) { + if (str_contains($this->value, "\n")) { + return 'is equal to '; + } + + return sprintf( + "is equal to '%s'", + $this->value, + ); + } + + return sprintf( + 'is equal to %s', + Exporter::export($this->value, $exportObjects), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php new file mode 100644 index 000000000..d587f6f70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.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 PHPUnit\Framework\Constraint; + +use function sprintf; +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\Exporter; +use SebastianBergmann\Comparator\ComparisonFailure; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsEqualWithDelta extends Constraint +{ + private readonly mixed $value; + private readonly float $delta; + + public function __construct(mixed $value, float $delta) + { + $this->value = $value; + $this->delta = $delta; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + // If $this->value and $other are identical, they are also equal. + // This is the most common path and will allow us to skip + // initialization of all the comparators. + if ($this->value === $other) { + return true; + } + + $comparatorFactory = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other, + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta, + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f, + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + return sprintf( + 'is equal to %s with delta <%F>', + Exporter::export($this->value, $exportObjects), + $this->delta, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php new file mode 100644 index 000000000..3bbae762c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/Exception.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use PHPUnit\Util\Filter; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends Constraint +{ + private readonly string $className; + + public function __construct(string $className) + { + $this->className = $className; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'exception of type "%s"', + $this->className, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $other instanceof $this->className; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @throws \PHPUnit\Framework\Exception + */ + protected function failureDescription(mixed $other): string + { + if ($other === null) { + return sprintf( + 'exception of type "%s" is thrown', + $this->className, + ); + } + + $message = ''; + + if ($other instanceof Throwable) { + $message = '. Message was: "' . $other->getMessage() . '" at' + . "\n" . Filter::getFilteredStacktrace($other); + } + + return sprintf( + 'exception of type "%s" matches expected exception "%s"%s', + $other::class, + $this->className, + $message, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php new file mode 100644 index 000000000..338588eeb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionCode.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionCode extends Constraint +{ + private readonly int|string $expectedCode; + + public function __construct(int|string $expected) + { + $this->expectedCode = $expected; + } + + public function toString(): string + { + return 'exception code is ' . $this->expectedCode; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return (string) $other === (string) $this->expectedCode; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + '%s is equal to expected exception code %s', + Exporter::export($other, true), + Exporter::export($this->expectedCode, true), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php new file mode 100644 index 000000000..ae9209039 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use function str_contains; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionMessageIsOrContains extends Constraint +{ + private readonly string $expectedMessage; + + public function __construct(string $expectedMessage) + { + $this->expectedMessage = $expectedMessage; + } + + public function toString(): string + { + if ($this->expectedMessage === '') { + return 'exception message is empty'; + } + + return 'exception message contains ' . Exporter::export($this->expectedMessage); + } + + protected function matches(mixed $other): bool + { + if ($this->expectedMessage === '') { + return $other === ''; + } + + return str_contains((string) $other, $this->expectedMessage); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + if ($this->expectedMessage === '') { + return sprintf( + "exception message is empty but is '%s'", + $other, + ); + } + + return sprintf( + "exception message '%s' contains '%s'", + $other, + $this->expectedMessage, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php new file mode 100644 index 000000000..611af0374 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function preg_match; +use function sprintf; +use Exception; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExceptionMessageMatchesRegularExpression extends Constraint +{ + private readonly string $regularExpression; + + public function __construct(string $regularExpression) + { + $this->regularExpression = $regularExpression; + } + + public function toString(): string + { + return 'exception message matches ' . Exporter::export($this->regularExpression); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @throws \PHPUnit\Framework\Exception + * @throws Exception + */ + protected function matches(mixed $other): bool + { + $match = @preg_match($this->regularExpression, (string) $other); + + if ($match === false) { + throw new \PHPUnit\Framework\Exception( + sprintf( + 'Invalid expected exception message regular expression given: %s', + $this->regularExpression, + ), + ); + } + + return $match === 1; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + "exception message '%s' matches '%s'", + $other, + $this->regularExpression, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php new file mode 100644 index 000000000..83b991e1a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_dir; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DirectoryExists extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'directory exists'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return is_dir($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + 'directory "%s" exists', + $other, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php new file mode 100644 index 000000000..cfc3b1b6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/FileExists.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function file_exists; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class FileExists extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'file exists'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return file_exists($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + 'file "%s" exists', + $other, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php new file mode 100644 index 000000000..1a32546ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsReadable.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_readable; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsReadable extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is readable'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return is_readable($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + '"%s" is readable', + $other, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php new file mode 100644 index 000000000..24e94f821 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Filesystem/IsWritable.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_writable; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsWritable extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is writable'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return is_writable($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + '"%s" is writable', + $other, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php new file mode 100644 index 000000000..ef1b8bdf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsAnything.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsAnything extends Constraint +{ + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + return $returnResult ? true : null; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is anything'; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php new file mode 100644 index 000000000..48ef3d648 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function explode; +use function gettype; +use function is_array; +use function is_object; +use function is_string; +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\Exporter; +use SebastianBergmann\Comparator\ComparisonFailure; +use UnitEnum; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsIdentical extends Constraint +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool + { + $success = $this->value === $other; + + if ($returnResult) { + return $success; + } + + if (!$success) { + $f = null; + + // if both values are strings, make sure a diff is generated + if (is_string($this->value) && is_string($other)) { + $f = new ComparisonFailure( + $this->value, + $other, + sprintf("'%s'", $this->value), + sprintf("'%s'", $other), + ); + } + + // if both values are array or enums, make sure a diff is generated + if ((is_array($this->value) && is_array($other)) || ($this->value instanceof UnitEnum && $other instanceof UnitEnum)) { + $f = new ComparisonFailure( + $this->value, + $other, + Exporter::export($this->value, true), + Exporter::export($other, true), + ); + } + + $this->fail($other, $description, $f); + } + + return null; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + if (is_object($this->value)) { + return 'is identical to an object of class "' . + $this->value::class . '"'; + } + + return 'is identical to ' . Exporter::export($this->value, $exportObjects); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + if (is_object($this->value) && is_object($other)) { + return 'two variables reference the same object'; + } + + if (explode(' ', gettype($this->value), 2)[0] === 'resource' && explode(' ', gettype($other), 2)[0] === 'resource') { + return 'two variables reference the same resource'; + } + + if (is_string($this->value) && is_string($other)) { + return 'two strings are identical'; + } + + if (is_array($this->value) && is_array($other)) { + return 'two arrays are identical'; + } + + return parent::failureDescription($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php new file mode 100644 index 000000000..dc3be3b4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function json_decode; +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Util\InvalidJsonException; +use PHPUnit\Util\Json; +use SebastianBergmann\Comparator\ComparisonFailure; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class JsonMatches extends Constraint +{ + private readonly string $value; + + public function __construct(string $value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the object. + */ + public function toString(): string + { + return sprintf( + 'matches JSON string "%s"', + $this->value, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + */ + protected function matches(mixed $other): bool + { + [$error, $recodedOther] = Json::canonicalize($other); + + if ($error) { + return false; + } + + [$error, $recodedValue] = Json::canonicalize($this->value); + + if ($error) { + return false; + } + + return $recodedOther == $recodedValue; + } + + /** + * Throws an exception for the given compared value and test description. + * + * @throws ExpectationFailedException + * @throws InvalidJsonException + */ + protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never + { + if ($comparisonFailure === null) { + [$error, $recodedOther] = Json::canonicalize($other); + + if ($error) { + parent::fail($other, $description); + } + + [$error, $recodedValue] = Json::canonicalize($this->value); + + if ($error) { + parent::fail($other, $description); + } + + $comparisonFailure = new ComparisonFailure( + json_decode($this->value), + json_decode($other), + Json::prettify($recodedValue), + Json::prettify($recodedOther), + 'Failed asserting that two json values are equal.', + ); + } + + parent::fail($other, $description, $comparisonFailure); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php new file mode 100644 index 000000000..b70de503d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsFinite.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_finite; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsFinite extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is finite'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return is_finite($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php new file mode 100644 index 000000000..dbf4803bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsInfinite.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_infinite; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsInfinite extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is infinite'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return is_infinite($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php new file mode 100644 index 000000000..f9c47219e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Math/IsNan.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_nan; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsNan extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is nan'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return is_nan($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.php new file mode 100644 index 000000000..b513545fa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectEquals.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 PHPUnit\Framework\Constraint; + +use function is_object; +use PHPUnit\Framework\ActualValueIsNotAnObjectException; +use PHPUnit\Framework\ComparisonMethodDoesNotAcceptParameterTypeException; +use PHPUnit\Framework\ComparisonMethodDoesNotDeclareBoolReturnTypeException; +use PHPUnit\Framework\ComparisonMethodDoesNotDeclareExactlyOneParameterException; +use PHPUnit\Framework\ComparisonMethodDoesNotDeclareParameterTypeException; +use PHPUnit\Framework\ComparisonMethodDoesNotExistException; +use ReflectionNamedType; +use ReflectionObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ObjectEquals extends Constraint +{ + private readonly object $expected; + private readonly string $method; + + public function __construct(object $object, string $method = 'equals') + { + $this->expected = $object; + $this->method = $method; + } + + public function toString(): string + { + return 'two objects are equal'; + } + + /** + * @throws ActualValueIsNotAnObjectException + * @throws ComparisonMethodDoesNotAcceptParameterTypeException + * @throws ComparisonMethodDoesNotDeclareBoolReturnTypeException + * @throws ComparisonMethodDoesNotDeclareExactlyOneParameterException + * @throws ComparisonMethodDoesNotDeclareParameterTypeException + * @throws ComparisonMethodDoesNotExistException + */ + protected function matches(mixed $other): bool + { + if (!is_object($other)) { + throw new ActualValueIsNotAnObjectException; + } + + $object = new ReflectionObject($other); + + if (!$object->hasMethod($this->method)) { + throw new ComparisonMethodDoesNotExistException( + $other::class, + $this->method, + ); + } + + $method = $object->getMethod($this->method); + + if (!$method->hasReturnType()) { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + $other::class, + $this->method, + ); + } + + $returnType = $method->getReturnType(); + + if (!$returnType instanceof ReflectionNamedType) { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + $other::class, + $this->method, + ); + } + + if ($returnType->allowsNull()) { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + $other::class, + $this->method, + ); + } + + if ($returnType->getName() !== 'bool') { + throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( + $other::class, + $this->method, + ); + } + + if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) { + throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException( + $other::class, + $this->method, + ); + } + + $parameter = $method->getParameters()[0]; + + if (!$parameter->hasType()) { + throw new ComparisonMethodDoesNotDeclareParameterTypeException( + $other::class, + $this->method, + ); + } + + $type = $parameter->getType(); + + if (!$type instanceof ReflectionNamedType) { + throw new ComparisonMethodDoesNotDeclareParameterTypeException( + $other::class, + $this->method, + ); + } + + $typeName = $type->getName(); + + if ($typeName === 'self') { + $typeName = $other::class; + } + + if (!$this->expected instanceof $typeName) { + throw new ComparisonMethodDoesNotAcceptParameterTypeException( + $other::class, + $this->method, + $this->expected::class, + ); + } + + return $other->{$this->method}($this->expected); + } + + protected function failureDescription(mixed $other): string + { + return $this->toString(true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php new file mode 100644 index 000000000..6c8bc415e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function gettype; +use function is_object; +use function sprintf; +use ReflectionObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ObjectHasProperty extends Constraint +{ + private readonly string $propertyName; + + public function __construct(string $propertyName) + { + $this->propertyName = $propertyName; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'has property "%s"', + $this->propertyName, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches(mixed $other): bool + { + if (!is_object($other)) { + return false; + } + + return (new ReflectionObject($other))->hasProperty($this->propertyName); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription(mixed $other): string + { + if (is_object($other)) { + return sprintf( + 'object of class "%s" %s', + $other::class, + $this->toString(true), + ); + } + + return sprintf( + '"%s" (%s) %s', + $other, + gettype($other), + $this->toString(true), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php new file mode 100644 index 000000000..4c3d8e4b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/BinaryOperator.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_map; +use function count; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class BinaryOperator extends Operator +{ + /** + * @psalm-var list + */ + private readonly array $constraints; + + protected function __construct(mixed ...$constraints) + { + $this->constraints = array_map( + fn ($constraint): Constraint => $this->checkConstraint($constraint), + $constraints, + ); + } + + /** + * Returns the number of operands (constraints). + */ + final public function arity(): int + { + return count($this->constraints); + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + $reduced = $this->reduce(); + + if ($reduced !== $this) { + return $reduced->toString(); + } + + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + $constraint = $constraint->reduce(); + + $text .= $this->constraintToString($constraint, $key); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += count($constraint); + } + + return $count; + } + + /** + * @psalm-return list + */ + final protected function constraints(): array + { + return $this->constraints; + } + + /** + * Returns true if the $constraint needs to be wrapped with braces. + */ + final protected function constraintNeedsParentheses(Constraint $constraint): bool + { + return $this->arity() > 1 && parent::constraintNeedsParentheses($constraint); + } + + /** + * Reduces the sub-expression starting at $this by skipping degenerate + * sub-expression and returns first descendant constraint that starts + * a non-reducible sub-expression. + * + * See Constraint::reduce() for more. + */ + protected function reduce(): Constraint + { + if ($this->arity() === 1 && $this->constraints[0] instanceof Operator) { + return $this->constraints[0]->reduce(); + } + + return parent::reduce(); + } + + /** + * Returns string representation of given operand in context of this operator. + */ + private function constraintToString(Constraint $constraint, int $position): string + { + $prefix = ''; + + if ($position > 0) { + $prefix = (' ' . $this->operator() . ' '); + } + + if ($this->constraintNeedsParentheses($constraint)) { + return $prefix . '( ' . $constraint->toString() . ' )'; + } + + $string = $constraint->toStringInContext($this, $position); + + if ($string === '') { + $string = $constraint->toString(); + } + + return $prefix . $string; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php new file mode 100644 index 000000000..e0a00a0ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalAnd.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalAnd extends BinaryOperator +{ + public static function fromConstraints(mixed ...$constraints): self + { + return new self(...$constraints); + } + + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'and'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + public function precedence(): int + { + return 22; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + foreach ($this->constraints() as $constraint) { + if (!$constraint->evaluate($other, '', true)) { + return false; + } + } + + return [] !== $this->constraints(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php new file mode 100644 index 000000000..837e3a50a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalNot.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_map; +use function count; +use function preg_match; +use function preg_quote; +use function preg_replace; +use PHPUnit\Framework\ExpectationFailedException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalNot extends UnaryOperator +{ + public static function negate(string $string): string + { + $positives = [ + 'contains ', + 'exists', + 'has ', + 'is ', + 'are ', + 'matches ', + 'starts with ', + 'ends with ', + 'reference ', + 'not not ', + ]; + + $negatives = [ + 'does not contain ', + 'does not exist', + 'does not have ', + 'is not ', + 'are not ', + 'does not match ', + 'starts not with ', + 'ends not with ', + 'don\'t reference ', + 'not ', + ]; + + preg_match('/(\'[\w\W]*\')([\w\W]*)("[\w\W]*")/i', $string, $matches); + + if (count($matches) === 0) { + preg_match('/(\'[\w\W]*\')([\w\W]*)(\'[\w\W]*\')/i', $string, $matches); + } + + $positives = array_map( + static fn (string $s) => '/\\b' . preg_quote($s, '/') . '/', + $positives, + ); + + if (count($matches) > 0) { + $nonInput = $matches[2]; + + $negatedString = preg_replace( + '/' . preg_quote($nonInput, '/') . '/', + preg_replace( + $positives, + $negatives, + $nonInput, + ), + $string, + ); + } else { + $negatedString = preg_replace( + $positives, + $negatives, + $string, + ); + } + + return $negatedString; + } + + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'not'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + public function precedence(): int + { + return 5; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @throws ExpectationFailedException + */ + protected function matches(mixed $other): bool + { + return !$this->constraint()->evaluate($other, '', true); + } + + /** + * Applies additional transformation to strings returned by toString() or + * failureDescription(). + */ + protected function transformString(string $string): string + { + return self::negate($string); + } + + /** + * Reduces the sub-expression starting at $this by skipping degenerate + * sub-expression and returns first descendant constraint that starts + * a non-reducible sub-expression. + * + * See Constraint::reduce() for more. + */ + protected function reduce(): Constraint + { + $constraint = $this->constraint(); + + if ($constraint instanceof self) { + return $constraint->constraint()->reduce(); + } + + return parent::reduce(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php new file mode 100644 index 000000000..cbd87b9c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalOr.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalOr extends BinaryOperator +{ + public static function fromConstraints(mixed ...$constraints): self + { + return new self(...$constraints); + } + + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'or'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + public function precedence(): int + { + return 24; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + public function matches(mixed $other): bool + { + foreach ($this->constraints() as $constraint) { + if ($constraint->evaluate($other, '', true)) { + return true; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php new file mode 100644 index 000000000..e8ffc34d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/LogicalXor.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_reduce; +use function array_shift; +use PHPUnit\Framework\ExpectationFailedException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class LogicalXor extends BinaryOperator +{ + public static function fromConstraints(mixed ...$constraints): self + { + return new self(...$constraints); + } + + /** + * Returns the name of this operator. + */ + public function operator(): string + { + return 'xor'; + } + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php. + */ + public function precedence(): int + { + return 23; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @throws ExpectationFailedException + */ + public function matches(mixed $other): bool + { + $constraints = $this->constraints(); + + $initial = array_shift($constraints); + + if ($initial === null) { + return false; + } + + return array_reduce( + $constraints, + static fn (bool $matches, Constraint $constraint): bool => $matches xor $constraint->evaluate($other, '', true), + $initial->evaluate($other, '', true), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php new file mode 100644 index 000000000..1195156e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/Operator.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Operator extends Constraint +{ + /** + * Returns the name of this operator. + */ + abstract public function operator(): string; + + /** + * Returns this operator's precedence. + * + * @see https://www.php.net/manual/en/language.operators.precedence.php + */ + abstract public function precedence(): int; + + /** + * Returns the number of operands. + */ + abstract public function arity(): int; + + /** + * Validates $constraint argument. + */ + protected function checkConstraint(mixed $constraint): Constraint + { + if (!$constraint instanceof Constraint) { + return new IsEqual($constraint); + } + + return $constraint; + } + + /** + * Returns true if the $constraint needs to be wrapped with braces. + */ + protected function constraintNeedsParentheses(Constraint $constraint): bool + { + return $constraint instanceof self && + $constraint->arity() > 1 && + $this->precedence() <= $constraint->precedence(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php new file mode 100644 index 000000000..d6ac6e3f6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Operator/UnaryOperator.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function count; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class UnaryOperator extends Operator +{ + private readonly Constraint $constraint; + + public function __construct(mixed $constraint) + { + $this->constraint = $this->checkConstraint($constraint); + } + + /** + * Returns the number of operands (constraints). + */ + public function arity(): int + { + return 1; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + $reduced = $this->reduce(); + + if ($reduced !== $this) { + return $reduced->toString(); + } + + $constraint = $this->constraint->reduce(); + + if ($this->constraintNeedsParentheses($constraint)) { + return $this->operator() . '( ' . $constraint->toString() . ' )'; + } + + $string = $constraint->toStringInContext($this, 0); + + if ($string === '') { + return $this->transformString($constraint->toString()); + } + + return $string; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return count($this->constraint); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + $reduced = $this->reduce(); + + if ($reduced !== $this) { + return $reduced->failureDescription($other); + } + + $constraint = $this->constraint->reduce(); + + if ($this->constraintNeedsParentheses($constraint)) { + return $this->operator() . '( ' . $constraint->failureDescription($other) . ' )'; + } + + $string = $constraint->failureDescriptionInContext($this, 0, $other); + + if ($string === '') { + return $this->transformString($constraint->failureDescription($other)); + } + + return $string; + } + + /** + * Transforms string returned by the member constraint's toString() or + * failureDescription() such that it reflects constraint's participation in + * this expression. + * + * The method may be overwritten in a subclass to apply default + * transformation in case the operand constraint does not provide its own + * custom strings via toStringInContext() or failureDescriptionInContext(). + */ + protected function transformString(string $string): string + { + return $string; + } + + /** + * Provides access to $this->constraint for subclasses. + */ + final protected function constraint(): Constraint + { + return $this->constraint; + } + + /** + * Returns true if the $constraint needs to be wrapped with parentheses. + */ + protected function constraintNeedsParentheses(Constraint $constraint): bool + { + $constraint = $constraint->reduce(); + + return $constraint instanceof self || parent::constraintNeedsParentheses($constraint); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php new file mode 100644 index 000000000..79b2c7046 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/IsJson.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use const JSON_ERROR_CTRL_CHAR; +use const JSON_ERROR_DEPTH; +use const JSON_ERROR_NONE; +use const JSON_ERROR_STATE_MISMATCH; +use const JSON_ERROR_SYNTAX; +use const JSON_ERROR_UTF8; +use function is_string; +use function json_decode; +use function json_last_error; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsJson extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is valid JSON'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + if (!is_string($other) || $other === '') { + return false; + } + + json_decode($other); + + if (json_last_error()) { + return false; + } + + return true; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + if (!is_string($other)) { + return $this->valueToTypeStringFragment($other) . 'is valid JSON'; + } + + if ($other === '') { + return 'an empty string is valid JSON'; + } + + return sprintf( + 'a string is valid JSON (%s)', + $this->determineJsonError($other), + ); + } + + private function determineJsonError(string $json): string + { + json_decode($json); + + return match (json_last_error()) { + JSON_ERROR_NONE => '', + JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', + JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', + JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', + JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', + JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', + default => 'Unknown error', + }; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.php new file mode 100644 index 000000000..03b0e4ea1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/RegularExpression.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 PHPUnit\Framework\Constraint; + +use function preg_match; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RegularExpression extends Constraint +{ + private readonly string $pattern; + + public function __construct(string $pattern) + { + $this->pattern = $pattern; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'matches PCRE pattern "%s"', + $this->pattern, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return preg_match($this->pattern, $other) > 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php new file mode 100644 index 000000000..7a805edde --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringContains.php @@ -0,0 +1,160 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_string; +use function mb_detect_encoding; +use function mb_stripos; +use function mb_strtolower; +use function sprintf; +use function str_contains; +use function strlen; +use function strtr; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringContains extends Constraint +{ + private readonly string $needle; + private readonly bool $ignoreCase; + private readonly bool $ignoreLineEndings; + + public function __construct(string $needle, bool $ignoreCase = false, bool $ignoreLineEndings = false) + { + if ($ignoreLineEndings) { + $needle = $this->normalizeLineEndings($needle); + } + + $this->needle = $needle; + $this->ignoreCase = $ignoreCase; + $this->ignoreLineEndings = $ignoreLineEndings; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + $needle = $this->needle; + + if ($this->ignoreCase) { + $needle = mb_strtolower($this->needle, 'UTF-8'); + } + + return sprintf( + 'contains "%s" [%s](length: %s)', + $needle, + $this->getDetectedEncoding($needle), + strlen($needle), + ); + } + + public function failureDescription(mixed $other): string + { + $stringifiedHaystack = Exporter::export($other, true); + $haystackEncoding = $this->getDetectedEncoding($other); + $haystackLength = $this->getHaystackLength($other); + + $haystackInformation = sprintf( + '%s [%s](length: %s) ', + $stringifiedHaystack, + $haystackEncoding, + $haystackLength, + ); + + $needleInformation = $this->toString(true); + + return $haystackInformation . $needleInformation; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + $haystack = $other; + + if ('' === $this->needle) { + return true; + } + + if (!is_string($haystack)) { + return false; + } + + if ($this->ignoreLineEndings) { + $haystack = $this->normalizeLineEndings($haystack); + } + + if ($this->ignoreCase) { + /* + * We must use the multibyte-safe version, so we can accurately compare non-latin uppercase characters with + * their lowercase equivalents. + */ + return mb_stripos($haystack, $this->needle, 0, 'UTF-8') !== false; + } + + /* + * Use the non-multibyte safe functions to see if the string is contained in $other. + * + * This function is very fast, and we don't care about the character position in the string. + * + * Additionally, we want this method to be binary safe, so we can check if some binary data is in other binary + * data. + */ + return str_contains($haystack, $this->needle); + } + + private function getDetectedEncoding(mixed $other): string + { + if ($this->ignoreCase) { + return 'Encoding ignored'; + } + + if (!is_string($other)) { + return 'Encoding detection failed'; + } + + $detectedEncoding = mb_detect_encoding($other, null, true); + + if ($detectedEncoding === false) { + return 'Encoding detection failed'; + } + + return $detectedEncoding; + } + + private function getHaystackLength(mixed $haystack): int + { + if (!is_string($haystack)) { + return 0; + } + + if ($this->ignoreLineEndings) { + $haystack = $this->normalizeLineEndings($haystack); + } + + return strlen($haystack); + } + + private function normalizeLineEndings(string $string): string + { + return strtr( + $string, + [ + "\r\n" => "\n", + "\r" => "\n", + ], + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php new file mode 100644 index 000000000..1dd43b84b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEndsWith.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function str_ends_with; +use PHPUnit\Framework\EmptyStringException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringEndsWith extends Constraint +{ + private readonly string $suffix; + + /** + * @throws EmptyStringException + */ + public function __construct(string $suffix) + { + if ($suffix === '') { + throw new EmptyStringException; + } + + $this->suffix = $suffix; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'ends with "' . $this->suffix . '"'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return str_ends_with((string) $other, $this->suffix); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php new file mode 100644 index 000000000..56c59943e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function sprintf; +use function strtr; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringEqualsStringIgnoringLineEndings extends Constraint +{ + private readonly string $string; + + public function __construct(string $string) + { + $this->string = $this->normalizeLineEndings($string); + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'is equal to "%s" ignoring line endings', + $this->string, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $this->string === $this->normalizeLineEndings((string) $other); + } + + private function normalizeLineEndings(string $string): string + { + return strtr( + $string, + [ + "\r\n" => "\n", + "\r" => "\n", + ], + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php new file mode 100644 index 000000000..f9659e2e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; +use function explode; +use function implode; +use function preg_match; +use function preg_quote; +use function preg_replace; +use function strtr; +use SebastianBergmann\Diff\Differ; +use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringMatchesFormatDescription extends Constraint +{ + private readonly string $formatDescription; + + public function __construct(string $formatDescription) + { + $this->formatDescription = $formatDescription; + } + + public function toString(): string + { + return 'matches format description:' . PHP_EOL . $this->formatDescription; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + $other = $this->convertNewlines($other); + + $matches = preg_match( + $this->regularExpressionForFormatDescription( + $this->convertNewlines($this->formatDescription), + ), + $other, + ); + + return $matches > 0; + } + + protected function failureDescription(mixed $other): string + { + return 'string matches format description'; + } + + protected function additionalFailureDescription(mixed $other): string + { + $from = explode("\n", $this->formatDescription); + $to = explode("\n", $this->convertNewlines($other)); + + foreach ($from as $index => $line) { + if (isset($to[$index]) && $line !== $to[$index]) { + $line = $this->regularExpressionForFormatDescription($line); + + if (preg_match($line, $to[$index]) > 0) { + $from[$index] = $to[$index]; + } + } + } + + $from = implode("\n", $from); + $to = implode("\n", $to); + + return $this->differ()->diff($from, $to); + } + + private function regularExpressionForFormatDescription(string $string): string + { + $string = strtr( + preg_quote($string, '/'), + [ + '%%' => '%', + '%e' => preg_quote(DIRECTORY_SEPARATOR, '/'), + '%s' => '[^\r\n]+', + '%S' => '[^\r\n]*', + '%a' => '.+?', + '%A' => '.*?', + '%w' => '\s*', + '%i' => '[+-]?\d+', + '%d' => '\d+', + '%x' => '[0-9a-fA-F]+', + '%f' => '[+-]?(?:\d+|(?=\.\d))(?:\.\d+)?(?:[Ee][+-]?\d+)?', + '%c' => '.', + '%0' => '\x00', + ], + ); + + return '/^' . $string . '$/s'; + } + + private function convertNewlines(string $text): string + { + return preg_replace('/\r\n/', "\n", $text); + } + + private function differ(): Differ + { + return new Differ(new UnifiedDiffOutputBuilder("--- Expected\n+++ Actual\n")); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php new file mode 100644 index 000000000..eee545c78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/String/StringStartsWith.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function str_starts_with; +use PHPUnit\Framework\EmptyStringException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class StringStartsWith extends Constraint +{ + private readonly string $prefix; + + /** + * @throws EmptyStringException + */ + public function __construct(string $prefix) + { + if ($prefix === '') { + throw new EmptyStringException; + } + + $this->prefix = $prefix; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'starts with "' . $this->prefix . '"'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return str_starts_with((string) $other, $this->prefix); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php new file mode 100644 index 000000000..07bfa4fd7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_key_exists; +use function is_array; +use ArrayAccess; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ArrayHasKey extends Constraint +{ + private readonly int|string $key; + + public function __construct(int|string $key) + { + $this->key = $key; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'has the key ' . Exporter::export($this->key); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + if (is_array($other)) { + return array_key_exists($this->key, $other); + } + + if ($other instanceof ArrayAccess) { + return $other->offsetExists($this->key); + } + + return false; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return 'an array ' . $this->toString(true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php new file mode 100644 index 000000000..2e2f60cb0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/IsList.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function array_is_list; +use function is_array; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsList extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is a list'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + if (!is_array($other)) { + return false; + } + + return array_is_list($other); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return $this->valueToTypeStringFragment($other) . $this->toString(true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php new file mode 100644 index 000000000..770bdb8a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContains.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function is_array; +use function sprintf; +use PHPUnit\Util\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class TraversableContains extends Constraint +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(bool $exportObjects = false): string + { + return 'contains ' . Exporter::export($this->value, $exportObjects); + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return sprintf( + '%s %s', + is_array($other) ? 'an array' : 'a traversable', + $this->toString(true), + ); + } + + protected function value(): mixed + { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php new file mode 100644 index 000000000..9bb0f3c08 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use SplObjectStorage; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TraversableContainsEqual extends TraversableContains +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + if ($other instanceof SplObjectStorage) { + return $other->contains($this->value()); + } + + foreach ($other as $element) { + /* @noinspection TypeUnsafeComparisonInspection */ + if ($this->value() == $element) { + return true; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php new file mode 100644 index 000000000..fc0703589 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use SplObjectStorage; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TraversableContainsIdentical extends TraversableContains +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + if ($other instanceof SplObjectStorage) { + return $other->contains($this->value()); + } + + foreach ($other as $element) { + if ($this->value() === $element) { + return true; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php new file mode 100644 index 000000000..274d76ff8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.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 PHPUnit\Framework\Constraint; + +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\ExpectationFailedException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TraversableContainsOnly extends Constraint +{ + private Constraint $constraint; + private readonly string $type; + + /** + * @throws Exception + */ + public function __construct(string $type, bool $isNativeType = true) + { + if ($isNativeType) { + $this->constraint = new IsType($type); + } else { + $this->constraint = new IsInstanceOf($type); + } + + $this->type = $type; + } + + /** + * Evaluates the constraint for parameter $other. + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @throws ExpectationFailedException + */ + public function evaluate(mixed $other, string $description = '', bool $returnResult = false): bool + { + $success = true; + + foreach ($other as $item) { + if (!$this->constraint->evaluate($item, '', true)) { + $success = false; + + break; + } + } + + if (!$success && !$returnResult) { + $this->fail($other, $description); + } + + return $success; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'contains only values of type "' . $this->type . '"'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php new file mode 100644 index 000000000..e69f4f862 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsInstanceOf.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function class_exists; +use function interface_exists; +use function sprintf; +use PHPUnit\Framework\UnknownClassOrInterfaceException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsInstanceOf extends Constraint +{ + /** + * @psalm-var class-string + */ + private readonly string $name; + + /** + * @psalm-var 'class'|'interface' + */ + private readonly string $type; + + /** + * @throws UnknownClassOrInterfaceException + */ + public function __construct(string $name) + { + if (class_exists($name)) { + $this->type = 'class'; + } elseif (interface_exists($name)) { + $this->type = 'interface'; + } else { + throw new UnknownClassOrInterfaceException($name); + } + + $this->name = $name; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'is an instance of %s %s', + $this->type, + $this->name, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $other instanceof $this->name; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + */ + protected function failureDescription(mixed $other): string + { + return $this->valueToTypeStringFragment($other) . $this->toString(true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php new file mode 100644 index 000000000..37c89f7a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsNull.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsNull extends Constraint +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is null'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + return $other === null; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php new file mode 100644 index 000000000..84c422f81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Constraint/Type/IsType.php @@ -0,0 +1,205 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use function gettype; +use function is_array; +use function is_bool; +use function is_callable; +use function is_float; +use function is_int; +use function is_iterable; +use function is_numeric; +use function is_object; +use function is_scalar; +use function is_string; +use function sprintf; +use PHPUnit\Framework\UnknownTypeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IsType extends Constraint +{ + /** + * @var string + */ + public const TYPE_ARRAY = 'array'; + + /** + * @var string + */ + public const TYPE_BOOL = 'bool'; + + /** + * @var string + */ + public const TYPE_FLOAT = 'float'; + + /** + * @var string + */ + public const TYPE_INT = 'int'; + + /** + * @var string + */ + public const TYPE_NULL = 'null'; + + /** + * @var string + */ + public const TYPE_NUMERIC = 'numeric'; + + /** + * @var string + */ + public const TYPE_OBJECT = 'object'; + + /** + * @var string + */ + public const TYPE_RESOURCE = 'resource'; + + /** + * @var string + */ + public const TYPE_CLOSED_RESOURCE = 'resource (closed)'; + + /** + * @var string + */ + public const TYPE_STRING = 'string'; + + /** + * @var string + */ + public const TYPE_SCALAR = 'scalar'; + + /** + * @var string + */ + public const TYPE_CALLABLE = 'callable'; + + /** + * @var string + */ + public const TYPE_ITERABLE = 'iterable'; + + /** + * @psalm-var array + */ + private const KNOWN_TYPES = [ + 'array' => true, + 'boolean' => true, + 'bool' => true, + 'double' => true, + 'float' => true, + 'integer' => true, + 'int' => true, + 'null' => true, + 'numeric' => true, + 'object' => true, + 'real' => true, + 'resource' => true, + 'resource (closed)' => true, + 'string' => true, + 'scalar' => true, + 'callable' => true, + 'iterable' => true, + ]; + + /** + * @psalm-var 'array'|'boolean'|'bool'|'double'|'float'|'integer'|'int'|'null'|'numeric'|'object'|'real'|'resource'|'resource (closed)'|'string'|'scalar'|'callable'|'iterable' + */ + private readonly string $type; + + /** + * @psalm-param 'array'|'boolean'|'bool'|'double'|'float'|'integer'|'int'|'null'|'numeric'|'object'|'real'|'resource'|'resource (closed)'|'string'|'scalar'|'callable'|'iterable' $type + * + * @throws UnknownTypeException + */ + public function __construct(string $type) + { + if (!isset(self::KNOWN_TYPES[$type])) { + throw new UnknownTypeException($type); + } + + $this->type = $type; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return sprintf( + 'is of type %s', + $this->type, + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches(mixed $other): bool + { + switch ($this->type) { + case 'numeric': + return is_numeric($other); + + case 'integer': + case 'int': + return is_int($other); + + case 'double': + case 'float': + case 'real': + return is_float($other); + + case 'string': + return is_string($other); + + case 'boolean': + case 'bool': + return is_bool($other); + + case 'null': + return null === $other; + + case 'array': + return is_array($other); + + case 'object': + return is_object($other); + + case 'resource': + $type = gettype($other); + + return $type === 'resource' || $type === 'resource (closed)'; + + case 'resource (closed)': + return gettype($other) === 'resource (closed)'; + + case 'scalar': + return is_scalar($other); + + case 'callable': + return is_callable($other); + + case 'iterable': + return is_iterable($other); + + default: + return false; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php new file mode 100644 index 000000000..e506cec4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/DataProviderTestSuite.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function explode; +use PHPUnit\Framework\TestSize\TestSize; +use PHPUnit\Metadata\Api\Groups; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DataProviderTestSuite extends TestSuite +{ + /** + * @psalm-var list + */ + private array $dependencies = []; + private ?array $providedTests = null; + + /** + * @psalm-param list $dependencies + */ + public function setDependencies(array $dependencies): void + { + $this->dependencies = $dependencies; + + foreach ($this->tests() as $test) { + if (!$test instanceof TestCase) { + continue; + } + + $test->setDependencies($dependencies); + } + } + + /** + * @psalm-return list + */ + public function provides(): array + { + if ($this->providedTests === null) { + $this->providedTests = [new ExecutionOrderDependency($this->name())]; + } + + return $this->providedTests; + } + + /** + * @psalm-return list + */ + public function requires(): array + { + // A DataProviderTestSuite does not have to traverse its child tests + // as these are inherited and cannot reference dataProvider rows directly + return $this->dependencies; + } + + /** + * Returns the size of each test created using the data provider(s). + */ + public function size(): TestSize + { + [$className, $methodName] = explode('::', $this->name()); + + return (new Groups)->size($className, $methodName); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php new file mode 100644 index 000000000..6bd59c4ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/AssertionFailedError.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class AssertionFailedError extends Exception implements SelfDescribing +{ + /** + * Wrapper for getMessage() which is declared as final. + */ + public function toString(): string + { + return $this->getMessage(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php new file mode 100644 index 000000000..41169ff1b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/CodeCoverageException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class CodeCoverageException extends Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php new file mode 100644 index 000000000..f5980cd71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/EmptyStringException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class EmptyStringException extends InvalidArgumentException +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php new file mode 100644 index 000000000..4c2e29574 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Exception.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function array_keys; +use function get_object_vars; +use function is_int; +use function sprintf; +use RuntimeException; +use Throwable; + +/** + * Base class for all PHPUnit Framework exceptions. + * + * Ensures that exceptions thrown during a test run do not leave stray + * references behind. + * + * Every Exception contains a stack trace. Each stack frame contains the 'args' + * of the called function. The function arguments can contain references to + * instantiated objects. The references prevent the objects from being + * destructed (until test results are eventually printed), so memory cannot be + * freed up. + * + * With enabled process isolation, test results are serialized in the child + * process and unserialized in the parent process. The stack trace of Exceptions + * may contain objects that cannot be serialized or unserialized (e.g., PDO + * connections). Unserializing user-space objects from the child process into + * the parent would break the intended encapsulation of process isolation. + * + * @see http://fabien.potencier.org/article/9/php-serialization-stack-traces-and-exceptions + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class Exception extends RuntimeException implements \PHPUnit\Exception +{ + protected array $serializableTrace; + + public function __construct(string $message = '', int|string $code = 0, ?Throwable $previous = null) + { + /** + * @see https://github.com/sebastianbergmann/phpunit/issues/5965 + */ + if (!is_int($code)) { + $message .= sprintf( + ' (exception code: %s)', + $code, + ); + + $code = 0; + } + + parent::__construct($message, $code, $previous); + + $this->serializableTrace = $this->getTrace(); + + foreach (array_keys($this->serializableTrace) as $key) { + unset($this->serializableTrace[$key]['args']); + } + } + + public function __sleep(): array + { + return array_keys(get_object_vars($this)); + } + + /** + * Returns the serializable trace (without 'args'). + */ + public function getSerializableTrace(): array + { + return $this->serializableTrace; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.php new file mode 100644 index 000000000..bff863f9f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ExpectationFailedException.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 PHPUnit\Framework; + +use Exception; +use SebastianBergmann\Comparator\ComparisonFailure; + +/** + * Exception for expectations which failed their check. + * + * The exception contains the error message and optionally a + * SebastianBergmann\Comparator\ComparisonFailure which is used to + * generate diff output of the failed expectations. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExpectationFailedException extends AssertionFailedError +{ + protected ?ComparisonFailure $comparisonFailure = null; + + public function __construct(string $message, ?ComparisonFailure $comparisonFailure = null, ?Exception $previous = null) + { + $this->comparisonFailure = $comparisonFailure; + + parent::__construct($message, 0, $previous); + } + + public function getComparisonFailure(): ?ComparisonFailure + { + return $this->comparisonFailure; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php new file mode 100644 index 000000000..b3b179531 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/GeneratorNotSupportedException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class GeneratorNotSupportedException extends InvalidArgumentException +{ + public static function fromParameterName(string $parameterName): self + { + return new self( + sprintf( + 'Passing an argument of type Generator for the %s parameter is not supported', + $parameterName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php new file mode 100644 index 000000000..4492ef226 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface IncompleteTest extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php new file mode 100644 index 000000000..a45564da8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncompleteTestError extends AssertionFailedError implements IncompleteTest +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..700abf038 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class InvalidArgumentException extends Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php new file mode 100644 index 000000000..c6300d9e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidCoversTargetException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidCoversTargetException extends CodeCoverageException +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php new file mode 100644 index 000000000..a29f4bde3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDataProviderException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidDataProviderException extends Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php new file mode 100644 index 000000000..8a636fd48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/InvalidDependencyException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidDependencyException extends AssertionFailedError implements SkippedTest +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php new file mode 100644 index 000000000..e59df81df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/NoChildTestSuiteException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoChildTestSuiteException extends Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php new file mode 100644 index 000000000..258b940ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ActualValueIsNotAnObjectException extends Exception +{ + public function __construct() + { + parent::__construct( + 'Actual value is not an object', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php new file mode 100644 index 000000000..74d00a17d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotAcceptParameterTypeException extends Exception +{ + public function __construct(string $className, string $methodName, string $type) + { + parent::__construct( + sprintf( + '%s is not an accepted argument type for comparison method %s::%s().', + $type, + $className, + $methodName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php new file mode 100644 index 000000000..62dc7e8cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotDeclareBoolReturnTypeException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Comparison method %s::%s() does not declare bool return type.', + $className, + $methodName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php new file mode 100644 index 000000000..d57607447 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotDeclareExactlyOneParameterException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Comparison method %s::%s() does not declare exactly one parameter.', + $className, + $methodName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php new file mode 100644 index 000000000..657186829 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotDeclareParameterTypeException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Parameter of comparison method %s::%s() does not have a declared type.', + $className, + $methodName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php new file mode 100644 index 000000000..94590b510 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonMethodDoesNotExistException extends Exception +{ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Comparison method %s::%s() does not exist.', + $className, + $methodName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php new file mode 100644 index 000000000..73f602aa5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/PhptAssertionFailedError.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhptAssertionFailedError extends AssertionFailedError +{ + private readonly string $syntheticFile; + private readonly int $syntheticLine; + private readonly array $syntheticTrace; + private readonly string $diff; + + public function __construct(string $message, int $code, string $file, int $line, array $trace, string $diff) + { + parent::__construct($message, $code); + + $this->syntheticFile = $file; + $this->syntheticLine = $line; + $this->syntheticTrace = $trace; + $this->diff = $diff; + } + + public function syntheticFile(): string + { + return $this->syntheticFile; + } + + public function syntheticLine(): int + { + return $this->syntheticLine; + } + + public function syntheticTrace(): array + { + return $this->syntheticTrace; + } + + public function diff(): string + { + return $this->diff; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php new file mode 100644 index 000000000..e59c9c603 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/ProcessIsolationException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ProcessIsolationException extends Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php new file mode 100644 index 000000000..ab2f67496 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTest.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface SkippedTest extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php new file mode 100644 index 000000000..d3a4788b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SkippedTestSuiteError extends AssertionFailedError implements SkippedTest +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php new file mode 100644 index 000000000..d09a760a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SkippedWithMessageException extends AssertionFailedError implements SkippedTest +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php new file mode 100644 index 000000000..6a10f97fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownClassOrInterfaceException extends InvalidArgumentException +{ + public function __construct(string $name) + { + parent::__construct( + sprintf( + 'Class or interface "%s" does not exist', + $name, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php new file mode 100644 index 000000000..b58b695c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Exception/UnknownTypeException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownTypeException extends InvalidArgumentException +{ + public function __construct(string $name) + { + parent::__construct( + sprintf( + 'Type "%s" is not known', + $name, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php new file mode 100644 index 000000000..091628cc9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/ExecutionOrderDependency.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function array_filter; +use function array_map; +use function array_values; +use function explode; +use function in_array; +use function str_contains; +use PHPUnit\Metadata\DependsOnClass; +use PHPUnit\Metadata\DependsOnMethod; +use Stringable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionOrderDependency implements Stringable +{ + private string $className = ''; + private string $methodName = ''; + private readonly bool $shallowClone; + private readonly bool $deepClone; + + public static function invalid(): self + { + return new self( + '', + '', + false, + false, + ); + } + + public static function forClass(DependsOnClass $metadata): self + { + return new self( + $metadata->className(), + 'class', + $metadata->deepClone(), + $metadata->shallowClone(), + ); + } + + public static function forMethod(DependsOnMethod $metadata): self + { + return new self( + $metadata->className(), + $metadata->methodName(), + $metadata->deepClone(), + $metadata->shallowClone(), + ); + } + + /** + * @psalm-param list $dependencies + * + * @psalm-return list + */ + public static function filterInvalid(array $dependencies): array + { + return array_values( + array_filter( + $dependencies, + static fn (self $d) => $d->isValid(), + ), + ); + } + + /** + * @psalm-param list $existing + * @psalm-param list $additional + * + * @psalm-return list + */ + public static function mergeUnique(array $existing, array $additional): array + { + $existingTargets = array_map( + static fn ($dependency) => $dependency->getTarget(), + $existing, + ); + + foreach ($additional as $dependency) { + $additionalTarget = $dependency->getTarget(); + + if (in_array($additionalTarget, $existingTargets, true)) { + continue; + } + + $existingTargets[] = $additionalTarget; + $existing[] = $dependency; + } + + return $existing; + } + + /** + * @psalm-param list $left + * @psalm-param list $right + * + * @psalm-return list + */ + public static function diff(array $left, array $right): array + { + if ($right === []) { + return $left; + } + + if ($left === []) { + return []; + } + + $diff = []; + $rightTargets = array_map( + static fn ($dependency) => $dependency->getTarget(), + $right, + ); + + foreach ($left as $dependency) { + if (in_array($dependency->getTarget(), $rightTargets, true)) { + continue; + } + + $diff[] = $dependency; + } + + return $diff; + } + + public function __construct(string $classOrCallableName, ?string $methodName = null, bool $deepClone = false, bool $shallowClone = false) + { + $this->deepClone = $deepClone; + $this->shallowClone = $shallowClone; + + if ($classOrCallableName === '') { + return; + } + + if (str_contains($classOrCallableName, '::')) { + [$this->className, $this->methodName] = explode('::', $classOrCallableName); + } else { + $this->className = $classOrCallableName; + $this->methodName = !empty($methodName) ? $methodName : 'class'; + } + } + + public function __toString(): string + { + return $this->getTarget(); + } + + public function isValid(): bool + { + // Invalid dependencies can be declared and are skipped by the runner + return $this->className !== '' && $this->methodName !== ''; + } + + public function shallowClone(): bool + { + return $this->shallowClone; + } + + public function deepClone(): bool + { + return $this->deepClone; + } + + public function targetIsClass(): bool + { + return $this->methodName === 'class'; + } + + public function getTarget(): string + { + return $this->isValid() + ? $this->className . '::' . $this->methodName + : ''; + } + + public function getTargetClassName(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.php new file mode 100644 index 000000000..54d408c0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/ConfigurableMethod.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 PHPUnit\Framework\MockObject; + +use SebastianBergmann\Type\Type; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConfigurableMethod +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $name; + + /** + * @psalm-var array + */ + private readonly array $defaultParameterValues; + + /** + * @psalm-var non-negative-int + */ + private readonly int $numberOfParameters; + private readonly Type $returnType; + + /** + * @psalm-param non-empty-string $name + * @psalm-param array $defaultParameterValues + * @psalm-param non-negative-int $numberOfParameters + */ + public function __construct(string $name, array $defaultParameterValues, int $numberOfParameters, Type $returnType) + { + $this->name = $name; + $this->defaultParameterValues = $defaultParameterValues; + $this->numberOfParameters = $numberOfParameters; + $this->returnType = $returnType; + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->name; + } + + /** + * @psalm-return array + */ + public function defaultParameterValues(): array + { + return $this->defaultParameterValues; + } + + /** + * @psalm-return non-negative-int + */ + public function numberOfParameters(): int + { + return $this->numberOfParameters; + } + + public function mayReturn(mixed $value): bool + { + return $this->returnType->isAssignable(Type::fromValue($value, false)); + } + + public function returnTypeDeclaration(): string + { + return $this->returnType->asString(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php new file mode 100644 index 000000000..e8ddadda5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class BadMethodCallException extends \BadMethodCallException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php new file mode 100644 index 000000000..6cb399e53 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotUseOnlyMethodsException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $type, string $methodName) + { + parent::__construct( + sprintf( + 'Trying to configure method "%s" with onlyMethods(), but it does not exist in class "%s"', + $methodName, + $type, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php new file mode 100644 index 000000000..f7994f20f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php new file mode 100644 index 000000000..faf8a498d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function get_debug_type; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncompatibleReturnValueException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(ConfigurableMethod $method, mixed $value) + { + parent::__construct( + sprintf( + 'Method %s may not return value of type %s, its declared return type is "%s"', + $method->name(), + get_debug_type($value), + $method->returnTypeDeclaration(), + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php new file mode 100644 index 000000000..8bf8967b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MatchBuilderNotFoundException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $id) + { + parent::__construct( + sprintf( + 'No builder found for match builder identification <%s>', + $id, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php new file mode 100644 index 000000000..de62b8679 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MatcherAlreadyRegisteredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $id) + { + parent::__construct( + sprintf( + 'Matcher with id <%s> is already registered', + $id, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php new file mode 100644 index 000000000..4d39b5d92 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodCannotBeConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $method) + { + parent::__construct( + sprintf( + 'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static', + $method, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php new file mode 100644 index 000000000..e4a375927 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodNameAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Method name is already configured'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php new file mode 100644 index 000000000..25c113416 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodNameNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Method name is not configured'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php new file mode 100644 index 000000000..fba96cf45 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodParametersAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Method parameters already configured'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php new file mode 100644 index 000000000..21aa6982c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class NeverReturningMethodException extends RuntimeException implements Exception +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName) + { + parent::__construct( + sprintf( + 'Method %s::%s() is declared to never return', + $className, + $methodName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php new file mode 100644 index 000000000..c4b181653 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoMoreReturnValuesConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(Invocation $invocation, int $numberOfConfiguredReturnValues) + { + parent::__construct( + sprintf( + 'Only %d return values have been configured for %s::%s()', + $numberOfConfiguredReturnValues, + $invocation->className(), + $invocation->methodName(), + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php new file mode 100644 index 000000000..cf193f10c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnValueNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(Invocation $invocation) + { + parent::__construct( + sprintf( + 'No return value is configured for %s::%s() and return value generation is disabled', + $invocation->className(), + $invocation->methodName(), + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php new file mode 100644 index 000000000..b99a903e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php new file mode 100644 index 000000000..9fc507887 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotUseAddMethodsException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $type, string $methodName) + { + parent::__construct( + sprintf( + 'Trying to configure method "%s" with addMethods(), but it exists in class "%s". Use onlyMethods() for methods that exist in the class', + $methodName, + $type, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php new file mode 100644 index 000000000..e2cde18b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassIsEnumerationException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" is an enumeration and cannot be doubled', + $className, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php new file mode 100644 index 000000000..f10100b90 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassIsFinalException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" is declared "final" and cannot be doubled', + $className, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php new file mode 100644 index 000000000..2b549c7a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ClassIsReadonlyException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassIsReadonlyException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" is declared "readonly" and cannot be doubled', + $className, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php new file mode 100644 index 000000000..f9a0a766a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function array_diff_assoc; +use function array_unique; +use function implode; +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DuplicateMethodException extends \PHPUnit\Framework\Exception implements Exception +{ + /** + * @psalm-param list $methods + */ + public function __construct(array $methods) + { + parent::__construct( + sprintf( + 'Cannot double using a method list that contains duplicates: "%s" (duplicate: "%s")', + implode(', ', $methods), + implode(', ', array_unique(array_diff_assoc($methods, array_unique($methods)))), + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php new file mode 100644 index 000000000..8d62606fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use PHPUnit\Framework\MockObject\Exception as BaseException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends BaseException +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php new file mode 100644 index 000000000..32296ce39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidMethodNameException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $method) + { + parent::__construct( + sprintf( + 'Cannot double method with invalid name "%s"', + $method, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php new file mode 100644 index 000000000..c73e717aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NameAlreadyInUseException extends \PHPUnit\Framework\Exception implements Exception +{ + /** + * @psalm-param class-string|trait-string $name + */ + public function __construct(string $name) + { + parent::__construct( + sprintf( + 'The name "%s" is already in use', + $name, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php new file mode 100644 index 000000000..b284d94d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class OriginalConstructorInvocationRequiredException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct('Proxying to original methods requires invoking the original constructor'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php new file mode 100644 index 000000000..f4a84f18e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReflectionException extends \PHPUnit\Framework\Exception implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php new file mode 100644 index 000000000..eed41c37a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RuntimeException extends \PHPUnit\Framework\Exception implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php new file mode 100644 index 000000000..f6f513b8f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SoapExtensionNotAvailableException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct() + { + parent::__construct( + 'The SOAP extension is required to generate a test double from WSDL', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php new file mode 100644 index 000000000..c51274591 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownClassException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Class "%s" does not exist', + $className, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php new file mode 100644 index 000000000..a536b1565 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 + */ +final class UnknownTraitException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $traitName) + { + parent::__construct( + sprintf( + 'Trait "%s" does not exist', + $traitName, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php new file mode 100644 index 000000000..cd1e1e072 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnknownTypeException extends \PHPUnit\Framework\Exception implements Exception +{ + public function __construct(string $type) + { + parent::__construct( + sprintf( + 'Class or interface "%s" does not exist', + $type, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php new file mode 100644 index 000000000..e4a63abd5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/Generator.php @@ -0,0 +1,1074 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use const PHP_EOL; +use const PREG_OFFSET_CAPTURE; +use const WSDL_CACHE_NONE; +use function array_merge; +use function array_pop; +use function array_unique; +use function assert; +use function class_exists; +use function count; +use function explode; +use function extension_loaded; +use function implode; +use function in_array; +use function interface_exists; +use function is_array; +use function is_object; +use function md5; +use function method_exists; +use function mt_rand; +use function preg_match; +use function preg_match_all; +use function range; +use function serialize; +use function sort; +use function sprintf; +use function str_contains; +use function str_replace; +use function strlen; +use function strpos; +use function substr; +use function trait_exists; +use Exception; +use Iterator; +use IteratorAggregate; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\MockObject\ConfigurableMethod; +use PHPUnit\Framework\MockObject\DoubledCloneMethod; +use PHPUnit\Framework\MockObject\Method; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\MockObjectApi; +use PHPUnit\Framework\MockObject\MockObjectInternal; +use PHPUnit\Framework\MockObject\ProxiedCloneMethod; +use PHPUnit\Framework\MockObject\Stub; +use PHPUnit\Framework\MockObject\StubApi; +use PHPUnit\Framework\MockObject\StubInternal; +use ReflectionClass; +use ReflectionMethod; +use SoapClient; +use SoapFault; +use Throwable; +use Traversable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Generator +{ + use TemplateLoader; + + /** + * @var array + */ + private const EXCLUDED_METHOD_NAMES = [ + '__CLASS__' => true, + '__DIR__' => true, + '__FILE__' => true, + '__FUNCTION__' => true, + '__LINE__' => true, + '__METHOD__' => true, + '__NAMESPACE__' => true, + '__TRAIT__' => true, + '__clone' => true, + '__halt_compiler' => true, + ]; + + /** + * @psalm-var array + */ + private static array $cache = []; + + /** + * Returns a test double for the specified class. + * + * @throws ClassIsEnumerationException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidMethodNameException + * @throws NameAlreadyInUseException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownTypeException + */ + public function testDouble(string $type, bool $mockObject, ?array $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false, ?object $proxyTarget = null, bool $allowMockingUnknownTypes = true, bool $returnValueGeneration = true): MockObject|Stub + { + if ($type === Traversable::class) { + $type = Iterator::class; + } + + if (!$allowMockingUnknownTypes) { + $this->ensureKnownType($type, $callAutoload); + } + + $this->ensureValidMethods($methods); + $this->ensureNameForTestDoubleClassIsAvailable($mockClassName); + + if (!$callOriginalConstructor && $callOriginalMethods) { + throw new OriginalConstructorInvocationRequiredException; + } + + $mock = $this->generate( + $type, + $mockObject, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods, + ); + + $object = $this->getObject( + $mock, + $type, + $callOriginalConstructor, + $arguments, + $callOriginalMethods, + $proxyTarget, + $returnValueGeneration, + ); + + assert($object instanceof $type); + + if ($mockObject) { + assert($object instanceof MockObject); + } else { + assert($object instanceof Stub); + } + + return $object; + } + + /** + * @psalm-param list $interfaces + * + * @throws RuntimeException + * @throws UnknownTypeException + */ + public function testDoubleForInterfaceIntersection(array $interfaces, bool $mockObject, bool $callAutoload = true): MockObject|Stub + { + if (count($interfaces) < 2) { + throw new RuntimeException('At least two interfaces must be specified'); + } + + foreach ($interfaces as $interface) { + if (!interface_exists($interface, $callAutoload)) { + throw new UnknownTypeException($interface); + } + } + + sort($interfaces); + + $methods = []; + + foreach ($interfaces as $interface) { + $methods = array_merge($methods, $this->namesOfMethodsIn($interface)); + } + + if (count(array_unique($methods)) < count($methods)) { + throw new RuntimeException('Interfaces must not declare the same method'); + } + + $unqualifiedNames = []; + + foreach ($interfaces as $interface) { + $parts = explode('\\', $interface); + $unqualifiedNames[] = array_pop($parts); + } + + sort($unqualifiedNames); + + do { + $intersectionName = sprintf( + 'Intersection_%s_%s', + implode('_', $unqualifiedNames), + substr(md5((string) mt_rand()), 0, 8), + ); + } while (interface_exists($intersectionName, false)); + + $template = $this->loadTemplate('intersection.tpl'); + + $template->setVar( + [ + 'intersection' => $intersectionName, + 'interfaces' => implode(', ', $interfaces), + ], + ); + + eval($template->render()); + + return $this->testDouble($intersectionName, $mockObject); + } + + /** + * Returns a mock object for the specified abstract class with all abstract + * methods of the class mocked. + * + * Concrete methods to mock can be specified with the $mockedMethods parameter. + * + * @throws ClassIsEnumerationException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidArgumentException + * @throws InvalidMethodNameException + * @throws NameAlreadyInUseException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownClassException + * @throws UnknownTypeException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5241 + */ + public function mockObjectForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, ?array $mockedMethods = null, bool $cloneArguments = true): MockObject + { + if (class_exists($originalClassName, $callAutoload) || + interface_exists($originalClassName, $callAutoload)) { + $reflector = $this->reflectClass($originalClassName); + $methods = $mockedMethods; + + foreach ($reflector->getMethods() as $method) { + if ($method->isAbstract() && !in_array($method->getName(), $methods ?? [], true)) { + $methods[] = $method->getName(); + } + } + + if (empty($methods)) { + $methods = null; + } + + $mockObject = $this->testDouble( + $originalClassName, + true, + $methods, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments, + ); + + assert($mockObject instanceof $originalClassName); + assert($mockObject instanceof MockObject); + + return $mockObject; + } + + throw new UnknownClassException($originalClassName); + } + + /** + * Returns a mock object for the specified trait with all abstract methods + * of the trait mocked. Concrete methods to mock can be specified with the + * `$mockedMethods` parameter. + * + * @psalm-param trait-string $traitName + * + * @throws ClassIsEnumerationException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidArgumentException + * @throws InvalidMethodNameException + * @throws NameAlreadyInUseException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownClassException + * @throws UnknownTraitException + * @throws UnknownTypeException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 + */ + public function mockObjectForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, ?array $mockedMethods = null, bool $cloneArguments = true): MockObject + { + if (!trait_exists($traitName, $callAutoload)) { + throw new UnknownTraitException($traitName); + } + + $className = $this->generateClassName( + $traitName, + '', + 'Trait_', + ); + + $classTemplate = $this->loadTemplate('trait_class.tpl'); + + $classTemplate->setVar( + [ + 'prologue' => 'abstract ', + 'class_name' => $className['className'], + 'trait_name' => $traitName, + ], + ); + + $mockTrait = new MockTrait($classTemplate->render(), $className['className']); + $mockTrait->generate(); + + return $this->mockObjectForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments); + } + + /** + * Returns an object for the specified trait. + * + * @psalm-param trait-string $traitName + * + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownTraitException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5244 + */ + public function objectForTrait(string $traitName, string $traitClassName = '', bool $callAutoload = true, bool $callOriginalConstructor = false, array $arguments = []): object + { + if (!trait_exists($traitName, $callAutoload)) { + throw new UnknownTraitException($traitName); + } + + $className = $this->generateClassName( + $traitName, + $traitClassName, + 'Trait_', + ); + + $classTemplate = $this->loadTemplate('trait_class.tpl'); + + $classTemplate->setVar( + [ + 'prologue' => '', + 'class_name' => $className['className'], + 'trait_name' => $traitName, + ], + ); + + return $this->getObject( + new MockTrait( + $classTemplate->render(), + $className['className'], + ), + '', + $callOriginalConstructor, + $arguments, + ); + } + + /** + * @throws ClassIsEnumerationException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws ReflectionException + * @throws RuntimeException + * + * @todo This method is only public because it is used to test generated code in PHPT tests + * + * @see https://github.com/sebastianbergmann/phpunit/issues/5476 + */ + public function generate(string $type, bool $mockObject, ?array $methods = null, string $mockClassName = '', bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false): MockClass + { + if ($mockClassName !== '') { + return $this->generateCodeForTestDoubleClass( + $type, + $mockObject, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods, + ); + } + + $key = md5( + $type . + ($mockObject ? 'MockObject' : 'TestStub') . + serialize($methods) . + serialize($callOriginalClone) . + serialize($cloneArguments) . + serialize($callOriginalMethods), + ); + + if (!isset(self::$cache[$key])) { + self::$cache[$key] = $this->generateCodeForTestDoubleClass( + $type, + $mockObject, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods, + ); + } + + return self::$cache[$key]; + } + + /** + * @throws RuntimeException + * @throws SoapExtensionNotAvailableException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5242 + */ + public function generateClassFromWsdl(string $wsdlFile, string $className, array $methods = [], array $options = []): string + { + if (!extension_loaded('soap')) { + throw new SoapExtensionNotAvailableException; + } + + $options['cache_wsdl'] = WSDL_CACHE_NONE; + + try { + $client = new SoapClient($wsdlFile, $options); + $_methods = array_unique($client->__getFunctions()); + + unset($client); + } catch (SoapFault $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + sort($_methods); + + $methodTemplate = $this->loadTemplate('wsdl_method.tpl'); + $methodsBuffer = ''; + + foreach ($_methods as $method) { + preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(/', $method, $matches, PREG_OFFSET_CAPTURE); + + $lastFunction = array_pop($matches[0]); + $nameStart = $lastFunction[1]; + $nameEnd = $nameStart + strlen($lastFunction[0]) - 1; + $name = str_replace('(', '', $lastFunction[0]); + + if (empty($methods) || in_array($name, $methods, true)) { + $arguments = explode( + ',', + str_replace(')', '', substr($method, $nameEnd + 1)), + ); + + foreach (range(0, count($arguments) - 1) as $i) { + $parameterStart = strpos($arguments[$i], '$'); + + if (!$parameterStart) { + continue; + } + + $arguments[$i] = substr($arguments[$i], $parameterStart); + } + + $methodTemplate->setVar( + [ + 'method_name' => $name, + 'arguments' => implode(', ', $arguments), + ], + ); + + $methodsBuffer .= $methodTemplate->render(); + } + } + + $optionsBuffer = '['; + + foreach ($options as $key => $value) { + $optionsBuffer .= $key . ' => ' . $value; + } + + $optionsBuffer .= ']'; + + $classTemplate = $this->loadTemplate('wsdl_class.tpl'); + $namespace = ''; + + if (str_contains($className, '\\')) { + $parts = explode('\\', $className); + $className = array_pop($parts); + $namespace = 'namespace ' . implode('\\', $parts) . ';' . "\n\n"; + } + + $classTemplate->setVar( + [ + 'namespace' => $namespace, + 'class_name' => $className, + 'wsdl' => $wsdlFile, + 'options' => $optionsBuffer, + 'methods' => $methodsBuffer, + ], + ); + + return $classTemplate->render(); + } + + /** + * @throws ReflectionException + * + * @psalm-return list + */ + public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments): array + { + $class = $this->reflectClass($className); + $methods = []; + + foreach ($class->getMethods() as $method) { + if (($method->isPublic() || $method->isAbstract()) && $this->canMethodBeDoubled($method)) { + $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments); + } + } + + return $methods; + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws ReflectionException + * + * @psalm-return list + */ + private function userDefinedInterfaceMethods(string $interfaceName): array + { + $interface = $this->reflectClass($interfaceName); + $methods = []; + + foreach ($interface->getMethods() as $method) { + if (!$method->isUserDefined()) { + continue; + } + + $methods[] = $method; + } + + return $methods; + } + + /** + * @throws ReflectionException + * @throws RuntimeException + */ + private function getObject(MockType $mockClass, string $type = '', bool $callOriginalConstructor = false, array $arguments = [], bool $callOriginalMethods = false, ?object $proxyTarget = null, bool $returnValueGeneration = true): object + { + $className = $mockClass->generate(); + $object = $this->instantiate($className, $callOriginalConstructor, $arguments); + + if ($callOriginalMethods) { + $this->instantiateProxyTarget($proxyTarget, $object, $type, $arguments); + } + + if ($object instanceof StubInternal) { + $object->__phpunit_setReturnValueGeneration($returnValueGeneration); + } + + return $object; + } + + /** + * @throws ClassIsEnumerationException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws ReflectionException + * @throws RuntimeException + */ + private function generateCodeForTestDoubleClass(string $type, bool $mockObject, ?array $explicitMethods, string $mockClassName, bool $callOriginalClone, bool $callAutoload, bool $cloneArguments, bool $callOriginalMethods): MockClass + { + $classTemplate = $this->loadTemplate('test_double_class.tpl'); + $additionalInterfaces = []; + $doubledCloneMethod = false; + $proxiedCloneMethod = false; + $isClass = false; + $isInterface = false; + $class = null; + $mockMethods = new MockMethodSet; + $testDoubleClassPrefix = $mockObject ? 'MockObject_' : 'TestStub_'; + + $_mockClassName = $this->generateClassName( + $type, + $mockClassName, + $testDoubleClassPrefix, + ); + + if (class_exists($_mockClassName['fullClassName'], $callAutoload)) { + $isClass = true; + } elseif (interface_exists($_mockClassName['fullClassName'], $callAutoload)) { + $isInterface = true; + } + + if (!$isClass && !$isInterface) { + $prologue = 'class ' . $_mockClassName['originalClassName'] . "\n{\n}\n\n"; + + if (!empty($_mockClassName['namespaceName'])) { + $prologue = 'namespace ' . $_mockClassName['namespaceName'] . + " {\n\n" . $prologue . "}\n\n" . + "namespace {\n\n"; + + $epilogue = "\n\n}"; + } + + $doubledCloneMethod = true; + } else { + $class = $this->reflectClass($_mockClassName['fullClassName']); + + if ($class->isEnum()) { + throw new ClassIsEnumerationException($_mockClassName['fullClassName']); + } + + if ($class->isFinal()) { + throw new ClassIsFinalException($_mockClassName['fullClassName']); + } + + if (method_exists($class, 'isReadOnly') && $class->isReadOnly()) { + throw new ClassIsReadonlyException($_mockClassName['fullClassName']); + } + + // @see https://github.com/sebastianbergmann/phpunit/issues/2995 + if ($isInterface && $class->implementsInterface(Throwable::class)) { + $actualClassName = Exception::class; + $additionalInterfaces[] = $class->getName(); + $isInterface = false; + $class = $this->reflectClass($actualClassName); + + foreach ($this->userDefinedInterfaceMethods($_mockClassName['fullClassName']) as $method) { + $methodName = $method->getName(); + + if ($class->hasMethod($methodName)) { + $classMethod = $class->getMethod($methodName); + + if (!$this->canMethodBeDoubled($classMethod)) { + continue; + } + } + + $mockMethods->addMethods( + MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments), + ); + } + + $_mockClassName = $this->generateClassName( + $actualClassName, + $_mockClassName['className'], + $testDoubleClassPrefix, + ); + } + + // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103 + if ($isInterface && $class->implementsInterface(Traversable::class) && + !$class->implementsInterface(Iterator::class) && + !$class->implementsInterface(IteratorAggregate::class)) { + $additionalInterfaces[] = Iterator::class; + + $mockMethods->addMethods( + ...$this->mockClassMethods(Iterator::class, $callOriginalMethods, $cloneArguments), + ); + } + + if ($class->hasMethod('__clone')) { + $cloneMethod = $class->getMethod('__clone'); + + if (!$cloneMethod->isFinal()) { + if ($callOriginalClone && !$isInterface) { + $proxiedCloneMethod = true; + } else { + $doubledCloneMethod = true; + } + } + } else { + $doubledCloneMethod = true; + } + } + + if ($isClass && $explicitMethods === []) { + $mockMethods->addMethods( + ...$this->mockClassMethods($_mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments), + ); + } + + if ($isInterface && ($explicitMethods === [] || $explicitMethods === null)) { + $mockMethods->addMethods( + ...$this->interfaceMethods($_mockClassName['fullClassName'], $cloneArguments), + ); + } + + if (is_array($explicitMethods)) { + foreach ($explicitMethods as $methodName) { + if ($class !== null && $class->hasMethod($methodName)) { + $method = $class->getMethod($methodName); + + if ($this->canMethodBeDoubled($method)) { + $mockMethods->addMethods( + MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments), + ); + } + } else { + $mockMethods->addMethods( + MockMethod::fromName( + $_mockClassName['fullClassName'], + $methodName, + $cloneArguments, + ), + ); + } + } + } + + $mockedMethods = ''; + $configurable = []; + + foreach ($mockMethods->asArray() as $mockMethod) { + $mockedMethods .= $mockMethod->generateCode(); + + $configurable[] = new ConfigurableMethod( + $mockMethod->methodName(), + $mockMethod->defaultParameterValues(), + $mockMethod->numberOfParameters(), + $mockMethod->returnType(), + ); + } + + /** @psalm-var trait-string[] $traits */ + $traits = [StubApi::class]; + + if ($mockObject) { + $traits[] = MockObjectApi::class; + } + + if (!$mockMethods->hasMethod('method') && (!isset($class) || !$class->hasMethod('method'))) { + $traits[] = Method::class; + } + + if ($doubledCloneMethod) { + $traits[] = DoubledCloneMethod::class; + } + + if ($proxiedCloneMethod) { + $traits[] = ProxiedCloneMethod::class; + } + + $useStatements = ''; + + foreach ($traits as $trait) { + $useStatements .= sprintf( + ' use %s;' . PHP_EOL, + $trait, + ); + } + + unset($traits); + + $classTemplate->setVar( + [ + 'prologue' => $prologue ?? '', + 'epilogue' => $epilogue ?? '', + 'class_declaration' => $this->generateTestDoubleClassDeclaration( + $mockObject, + $_mockClassName, + $isInterface, + $additionalInterfaces, + ), + 'use_statements' => $useStatements, + 'mock_class_name' => $_mockClassName['className'], + 'mocked_methods' => $mockedMethods, + ], + ); + + return new MockClass( + $classTemplate->render(), + $_mockClassName['className'], + $configurable, + ); + } + + private function generateClassName(string $type, string $className, string $prefix): array + { + if ($type[0] === '\\') { + $type = substr($type, 1); + } + + $classNameParts = explode('\\', $type); + + if (count($classNameParts) > 1) { + $type = array_pop($classNameParts); + $namespaceName = implode('\\', $classNameParts); + $fullClassName = $namespaceName . '\\' . $type; + } else { + $namespaceName = ''; + $fullClassName = $type; + } + + if ($className === '') { + do { + $className = $prefix . $type . '_' . + substr(md5((string) mt_rand()), 0, 8); + } while (class_exists($className, false)); + } + + return [ + 'className' => $className, + 'originalClassName' => $type, + 'fullClassName' => $fullClassName, + 'namespaceName' => $namespaceName, + ]; + } + + private function generateTestDoubleClassDeclaration(bool $mockObject, array $mockClassName, bool $isInterface, array $additionalInterfaces = []): string + { + if ($mockObject) { + $additionalInterfaces[] = MockObjectInternal::class; + } else { + $additionalInterfaces[] = StubInternal::class; + } + + $buffer = 'class '; + $interfaces = implode(', ', $additionalInterfaces); + + if ($isInterface) { + $buffer .= sprintf( + '%s implements %s', + $mockClassName['className'], + $interfaces, + ); + + if (!in_array($mockClassName['originalClassName'], $additionalInterfaces, true)) { + $buffer .= ', '; + + if (!empty($mockClassName['namespaceName'])) { + $buffer .= $mockClassName['namespaceName'] . '\\'; + } + + $buffer .= $mockClassName['originalClassName']; + } + } else { + $buffer .= sprintf( + '%s extends %s%s implements %s', + $mockClassName['className'], + !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '', + $mockClassName['originalClassName'], + $interfaces, + ); + } + + return $buffer; + } + + private function canMethodBeDoubled(ReflectionMethod $method): bool + { + if ($method->isConstructor()) { + return false; + } + + if ($method->isDestructor()) { + return false; + } + + if ($method->isFinal()) { + return false; + } + + if ($method->isPrivate()) { + return false; + } + + return !$this->isMethodNameExcluded($method->getName()); + } + + private function isMethodNameExcluded(string $name): bool + { + return isset(self::EXCLUDED_METHOD_NAMES[$name]); + } + + /** + * @throws UnknownTypeException + */ + private function ensureKnownType(string $type, bool $callAutoload): void + { + if (!class_exists($type, $callAutoload) && !interface_exists($type, $callAutoload)) { + throw new UnknownTypeException($type); + } + } + + /** + * @throws DuplicateMethodException + * @throws InvalidMethodNameException + */ + private function ensureValidMethods(?array $methods): void + { + if ($methods === null) { + return; + } + + foreach ($methods as $method) { + if (!preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*~', (string) $method)) { + throw new InvalidMethodNameException((string) $method); + } + } + + if ($methods !== array_unique($methods)) { + throw new DuplicateMethodException($methods); + } + } + + /** + * @throws NameAlreadyInUseException + * @throws ReflectionException + */ + private function ensureNameForTestDoubleClassIsAvailable(string $className): void + { + if ($className === '') { + return; + } + + if (class_exists($className, false) || + interface_exists($className, false) || + trait_exists($className, false)) { + throw new NameAlreadyInUseException($className); + } + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function instantiate(string $className, bool $callOriginalConstructor, array $arguments): object + { + if ($callOriginalConstructor) { + if (count($arguments) === 0) { + return new $className; + } + + try { + return (new ReflectionClass($className))->newInstanceArgs($arguments); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + } + + try { + return (new ReflectionClass($className))->newInstanceWithoutConstructor(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + // @codeCoverageIgnoreEnd + } + } + + /** + * @psalm-param class-string $type + * + * @throws ReflectionException + */ + private function instantiateProxyTarget(?object $proxyTarget, object $object, string $type, array $arguments): void + { + if (!is_object($proxyTarget)) { + assert(class_exists($type)); + + if (count($arguments) === 0) { + $proxyTarget = new $type; + } else { + $class = new ReflectionClass($type); + + try { + $proxyTarget = $class->newInstanceArgs($arguments); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + } + } + + $object->__phpunit_setOriginalObject($proxyTarget); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function reflectClass(string $className): ReflectionClass + { + try { + $class = new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + + return $class; + } + + /** + * @psalm-param class-string $classOrInterfaceName + * + * @psalm-return list + * + * @throws ReflectionException + */ + private function namesOfMethodsIn(string $classOrInterfaceName): array + { + $class = $this->reflectClass($classOrInterfaceName); + $methods = []; + + foreach ($class->getMethods() as $method) { + if ($method->isPublic() || $method->isAbstract()) { + $methods[] = $method->getName(); + } + } + + return $methods; + } + + /** + * @psalm-param class-string $interfaceName + * + * @psalm-return list + * + * @throws ReflectionException + */ + private function interfaceMethods(string $interfaceName, bool $cloneArguments): array + { + $class = $this->reflectClass($interfaceName); + $methods = []; + + foreach ($class->getMethods() as $method) { + $methods[] = MockMethod::fromReflection($method, false, $cloneArguments); + } + + return $methods; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php new file mode 100644 index 000000000..8fe3c8278 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockClass.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function call_user_func; +use function class_exists; +use PHPUnit\Framework\MockObject\ConfigurableMethod; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockClass implements MockType +{ + private readonly string $classCode; + + /** + * @psalm-var class-string + */ + private readonly string $mockName; + + /** + * @psalm-var list + */ + private readonly array $configurableMethods; + + /** + * @psalm-param class-string $mockName + * @psalm-param list $configurableMethods + */ + public function __construct(string $classCode, string $mockName, array $configurableMethods) + { + $this->classCode = $classCode; + $this->mockName = $mockName; + $this->configurableMethods = $configurableMethods; + } + + /** + * @psalm-return class-string + */ + public function generate(): string + { + if (!class_exists($this->mockName, false)) { + eval($this->classCode); + + call_user_func( + [ + $this->mockName, + '__phpunit_initConfigurableMethods', + ], + ...$this->configurableMethods, + ); + } + + return $this->mockName; + } + + public function classCode(): string + { + return $this->classCode; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php new file mode 100644 index 000000000..497cd114f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethod.php @@ -0,0 +1,396 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function count; +use function explode; +use function implode; +use function is_object; +use function is_string; +use function preg_match; +use function preg_replace; +use function sprintf; +use function str_contains; +use function strlen; +use function strpos; +use function substr; +use function substr_count; +use function trim; +use function var_export; +use ReflectionMethod; +use ReflectionParameter; +use SebastianBergmann\Type\ReflectionMapper; +use SebastianBergmann\Type\Type; +use SebastianBergmann\Type\UnknownType; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockMethod +{ + use TemplateLoader; + + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + private readonly bool $cloneArguments; + private readonly string $modifier; + private readonly string $argumentsForDeclaration; + private readonly string $argumentsForCall; + private readonly Type $returnType; + private readonly string $reference; + private readonly bool $callOriginalMethod; + private readonly bool $static; + private readonly ?string $deprecation; + + /** + * @psalm-var array + */ + private readonly array $defaultParameterValues; + + /** + * @psalm-var non-negative-int + */ + private readonly int $numberOfParameters; + + /** + * @throws ReflectionException + * @throws RuntimeException + */ + public static function fromReflection(ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments): self + { + if ($method->isPrivate()) { + $modifier = 'private'; + } elseif ($method->isProtected()) { + $modifier = 'protected'; + } else { + $modifier = 'public'; + } + + if ($method->isStatic()) { + $modifier .= ' static'; + } + + if ($method->returnsReference()) { + $reference = '&'; + } else { + $reference = ''; + } + + $docComment = $method->getDocComment(); + + if (is_string($docComment) && + preg_match('#\*[ \t]*+@deprecated[ \t]*+(.*?)\r?+\n[ \t]*+\*(?:[ \t]*+@|/$)#s', $docComment, $deprecation)) { + $deprecation = trim(preg_replace('#[ \t]*\r?\n[ \t]*+\*[ \t]*+#', ' ', $deprecation[1])); + } else { + $deprecation = null; + } + + return new self( + $method->getDeclaringClass()->getName(), + $method->getName(), + $cloneArguments, + $modifier, + self::methodParametersForDeclaration($method), + self::methodParametersForCall($method), + self::methodParametersDefaultValues($method), + count($method->getParameters()), + (new ReflectionMapper)->fromReturnType($method), + $reference, + $callOriginalMethod, + $method->isStatic(), + $deprecation, + ); + } + + /** + * @param class-string $className + * @param non-empty-string $methodName + */ + public static function fromName(string $className, string $methodName, bool $cloneArguments): self + { + return new self( + $className, + $methodName, + $cloneArguments, + 'public', + '', + '', + [], + 0, + new UnknownType, + '', + false, + false, + null, + ); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * @psalm-param array $defaultParameterValues + * @psalm-param non-negative-int $numberOfParameters + */ + private function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, array $defaultParameterValues, int $numberOfParameters, Type $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation) + { + $this->className = $className; + $this->methodName = $methodName; + $this->cloneArguments = $cloneArguments; + $this->modifier = $modifier; + $this->argumentsForDeclaration = $argumentsForDeclaration; + $this->argumentsForCall = $argumentsForCall; + $this->defaultParameterValues = $defaultParameterValues; + $this->numberOfParameters = $numberOfParameters; + $this->returnType = $returnType; + $this->reference = $reference; + $this->callOriginalMethod = $callOriginalMethod; + $this->static = $static; + $this->deprecation = $deprecation; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } + + /** + * @throws RuntimeException + */ + public function generateCode(): string + { + if ($this->static) { + $templateFile = 'doubled_static_method.tpl'; + } else { + $templateFile = sprintf( + '%s_method.tpl', + $this->callOriginalMethod ? 'proxied' : 'doubled', + ); + } + + $deprecation = $this->deprecation; + $returnResult = ''; + + if (!$this->returnType->isNever() && !$this->returnType->isVoid()) { + $returnResult = <<<'EOT' + + + return $__phpunit_result; +EOT; + } + + if (null !== $this->deprecation) { + $deprecation = "The {$this->className}::{$this->methodName} method is deprecated ({$this->deprecation})."; + $deprecationTemplate = $this->loadTemplate('deprecation.tpl'); + + $deprecationTemplate->setVar( + [ + 'deprecation' => var_export($deprecation, true), + ], + ); + + $deprecation = $deprecationTemplate->render(); + } + + $template = $this->loadTemplate($templateFile); + + $argumentsCount = 0; + + if (str_contains($this->argumentsForCall, '...')) { + $argumentsCount = null; + } elseif (!empty($this->argumentsForCall)) { + $argumentsCount = substr_count($this->argumentsForCall, ',') + 1; + } + + $template->setVar( + [ + 'arguments_decl' => $this->argumentsForDeclaration, + 'arguments_call' => $this->argumentsForCall, + 'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '', + 'return_type' => $this->returnType->asString(), + 'arguments_count' => $argumentsCount, + 'class_name' => $this->className, + 'method_name' => $this->methodName, + 'modifier' => $this->modifier, + 'reference' => $this->reference, + 'clone_arguments' => $this->cloneArguments ? 'true' : 'false', + 'deprecation' => $deprecation, + 'return_result' => $returnResult, + ], + ); + + return $template->render(); + } + + public function returnType(): Type + { + return $this->returnType; + } + + /** + * @psalm-return array + */ + public function defaultParameterValues(): array + { + return $this->defaultParameterValues; + } + + /** + * @psalm-return non-negative-int + */ + public function numberOfParameters(): int + { + return $this->numberOfParameters; + } + + /** + * Returns the parameters of a function or method. + * + * @throws RuntimeException + */ + private static function methodParametersForDeclaration(ReflectionMethod $method): string + { + $parameters = []; + $types = (new ReflectionMapper)->fromParameterTypes($method); + + foreach ($method->getParameters() as $i => $parameter) { + $name = '$' . $parameter->getName(); + + /* Note: PHP extensions may use empty names for reference arguments + * or "..." for methods taking a variable number of arguments. + */ + if ($name === '$' || $name === '$...') { + $name = '$arg' . $i; + } + + $default = ''; + $reference = ''; + $typeDeclaration = ''; + + if (!$types[$i]->type()->isUnknown()) { + $typeDeclaration = $types[$i]->type()->asString() . ' '; + } + + if ($parameter->isPassedByReference()) { + $reference = '&'; + } + + if ($parameter->isVariadic()) { + $name = '...' . $name; + } elseif ($parameter->isDefaultValueAvailable()) { + $default = ' = ' . self::exportDefaultValue($parameter); + } elseif ($parameter->isOptional()) { + $default = ' = null'; + } + + $parameters[] = $typeDeclaration . $reference . $name . $default; + } + + return implode(', ', $parameters); + } + + /** + * Returns the parameters of a function or method. + * + * @throws ReflectionException + */ + private static function methodParametersForCall(ReflectionMethod $method): string + { + $parameters = []; + + foreach ($method->getParameters() as $i => $parameter) { + $name = '$' . $parameter->getName(); + + /* Note: PHP extensions may use empty names for reference arguments + * or "..." for methods taking a variable number of arguments. + */ + if ($name === '$' || $name === '$...') { + $name = '$arg' . $i; + } + + if ($parameter->isVariadic()) { + continue; + } + + if ($parameter->isPassedByReference()) { + $parameters[] = '&' . $name; + } else { + $parameters[] = $name; + } + } + + return implode(', ', $parameters); + } + + /** + * @throws ReflectionException + */ + private static function exportDefaultValue(ReflectionParameter $parameter): string + { + try { + $defaultValue = $parameter->getDefaultValue(); + + if (!is_object($defaultValue)) { + return var_export($defaultValue, true); + } + + $parameterAsString = $parameter->__toString(); + + return explode( + ' = ', + substr( + substr( + $parameterAsString, + strpos($parameterAsString, ' ') + strlen(' '), + ), + 0, + -2, + ), + )[1]; + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-return array + */ + private static function methodParametersDefaultValues(ReflectionMethod $method): array + { + $result = []; + + foreach ($method->getParameters() as $i => $parameter) { + if (!$parameter->isDefaultValueAvailable()) { + continue; + } + + $result[$i] = $parameter->getDefaultValue(); + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php new file mode 100644 index 000000000..92785cc11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockMethodSet.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function array_key_exists; +use function array_values; +use function strtolower; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MockMethodSet +{ + /** + * @psalm-var array + */ + private array $methods = []; + + public function addMethods(MockMethod ...$methods): void + { + foreach ($methods as $method) { + $this->methods[strtolower($method->methodName())] = $method; + } + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return array_values($this->methods); + } + + public function hasMethod(string $methodName): bool + { + return array_key_exists(strtolower($methodName), $this->methods); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php new file mode 100644 index 000000000..2e78a6a3a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockTrait.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +use function class_exists; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 + */ +final class MockTrait implements MockType +{ + private readonly string $classCode; + + /** + * @psalm-var class-string + */ + private readonly string $mockName; + + /** + * @psalm-param class-string $mockName + */ + public function __construct(string $classCode, string $mockName) + { + $this->classCode = $classCode; + $this->mockName = $mockName; + } + + /** + * @psalm-return class-string + */ + public function generate(): string + { + if (!class_exists($this->mockName, false)) { + eval($this->classCode); + } + + return $this->mockName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php new file mode 100644 index 000000000..6003d987a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/MockType.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Generator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface MockType +{ + /** + * @psalm-return class-string + */ + public function generate(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.php new file mode 100644 index 000000000..37545fc9b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/TemplateLoader.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 PHPUnit\Framework\MockObject\Generator; + +use SebastianBergmann\Template\Template; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait TemplateLoader +{ + /** + * @psalm-var array + */ + private static array $templates = []; + + /** + * @psalm-suppress MissingThrowsDocblock + */ + private function loadTemplate(string $template): Template + { + $filename = __DIR__ . '/templates/' . $template; + + if (!isset(self::$templates[$filename])) { + self::$templates[$filename] = new Template($filename); + } + + return self::$templates[$filename]; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/deprecation.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/deprecation.tpl new file mode 100644 index 000000000..5bf06f52d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/deprecation.tpl @@ -0,0 +1,2 @@ + + @trigger_error({deprecation}, E_USER_DEPRECATED); diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_method.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_method.tpl new file mode 100644 index 000000000..1b1b663fe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_method.tpl @@ -0,0 +1,35 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + {{deprecation} + $__phpunit_definedVariables = get_defined_vars(); + $__phpunit_namedVariadicParameters = []; + + foreach ($__phpunit_definedVariables as $__phpunit_definedVariableName => $__phpunit_definedVariableValue) { + if ((new ReflectionParameter([__CLASS__, __FUNCTION__], $__phpunit_definedVariableName))->isVariadic()) { + foreach ($__phpunit_definedVariableValue as $__phpunit_key => $__phpunit_namedValue) { + if (is_string($__phpunit_key)) { + $__phpunit_namedVariadicParameters[$__phpunit_key] = $__phpunit_namedValue; + } + } + } + } + + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ({arguments_count} !== null && $__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $__phpunit_arguments = array_merge($__phpunit_arguments, $__phpunit_namedVariadicParameters); + + $__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke( + new \PHPUnit\Framework\MockObject\Invocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + );{return_result} + } diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_static_method.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_static_method.tpl new file mode 100644 index 000000000..5e5cf23cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/doubled_static_method.tpl @@ -0,0 +1,5 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + { + throw new \PHPUnit\Framework\MockObject\BadMethodCallException('Static method "{method_name}" cannot be invoked on mock object'); + } diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/intersection.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/intersection.tpl new file mode 100644 index 000000000..75cd27a6c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/intersection.tpl @@ -0,0 +1,5 @@ +declare(strict_types=1); + +interface {intersection} extends {interfaces} +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/proxied_method.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/proxied_method.tpl new file mode 100644 index 000000000..94db4665e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/proxied_method.tpl @@ -0,0 +1,37 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} + { + $__phpunit_definedVariables = get_defined_vars(); + $__phpunit_namedVariadicParameters = []; + + foreach ($__phpunit_definedVariables as $__phpunit_definedVariableName => $__phpunit_definedVariableValue) { + if ((new ReflectionParameter([__CLASS__, __FUNCTION__], $__phpunit_definedVariableName))->isVariadic()) { + foreach ($__phpunit_definedVariableValue as $__phpunit_key => $__phpunit_namedValue) { + if (is_string($__phpunit_key)) { + $__phpunit_namedVariadicParameters[$__phpunit_key] = $__phpunit_namedValue; + } + } + } + } + + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $__phpunit_arguments = array_merge($__phpunit_arguments, $__phpunit_namedVariadicParameters); + + $this->__phpunit_getInvocationHandler()->invoke( + new \PHPUnit\Framework\MockObject\Invocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true + ) + ); + + $__phpunit_result = call_user_func_array([$this->__phpunit_originalObject, "{method_name}"], $__phpunit_arguments);{return_result} + } diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/test_double_class.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/test_double_class.tpl new file mode 100644 index 000000000..369a47a68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/test_double_class.tpl @@ -0,0 +1,5 @@ +declare(strict_types=1); + +{prologue}{class_declaration} +{ +{use_statements}{mocked_methods}}{epilogue} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/trait_class.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/trait_class.tpl new file mode 100644 index 000000000..a8fe470fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/trait_class.tpl @@ -0,0 +1,6 @@ +declare(strict_types=1); + +{prologue}class {class_name} +{ + use {trait_name}; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_class.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_class.tpl new file mode 100644 index 000000000..b3100b414 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_class.tpl @@ -0,0 +1,9 @@ +declare(strict_types=1); + +{namespace}class {class_name} extends \SoapClient +{ + public function __construct($wsdl, array $options) + { + parent::__construct('{wsdl}', $options); + } +{methods}} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_method.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_method.tpl new file mode 100644 index 000000000..bb16e763e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Generator/templates/wsdl_method.tpl @@ -0,0 +1,4 @@ + + public function {method_name}({arguments}) + { + } diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php new file mode 100644 index 000000000..3e99351ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/MockBuilder.php @@ -0,0 +1,491 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_merge; +use function assert; +use function trait_exists; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\MockObject\Generator\CannotUseAddMethodsException; +use PHPUnit\Framework\MockObject\Generator\ClassIsEnumerationException; +use PHPUnit\Framework\MockObject\Generator\ClassIsFinalException; +use PHPUnit\Framework\MockObject\Generator\ClassIsReadonlyException; +use PHPUnit\Framework\MockObject\Generator\DuplicateMethodException; +use PHPUnit\Framework\MockObject\Generator\Generator; +use PHPUnit\Framework\MockObject\Generator\InvalidMethodNameException; +use PHPUnit\Framework\MockObject\Generator\NameAlreadyInUseException; +use PHPUnit\Framework\MockObject\Generator\OriginalConstructorInvocationRequiredException; +use PHPUnit\Framework\MockObject\Generator\ReflectionException; +use PHPUnit\Framework\MockObject\Generator\RuntimeException; +use PHPUnit\Framework\MockObject\Generator\UnknownTypeException; +use PHPUnit\Framework\TestCase; +use ReflectionClass; + +/** + * @psalm-template MockedType + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MockBuilder +{ + private readonly TestCase $testCase; + + /** + * @psalm-var class-string|trait-string + */ + private readonly string $type; + + /** + * @psalm-var list + */ + private array $methods = []; + private bool $emptyMethodsArray = false; + + /** + * @psalm-var ?class-string + */ + private ?string $mockClassName = null; + private array $constructorArgs = []; + private bool $originalConstructor = true; + private bool $originalClone = true; + private bool $autoload = true; + private bool $cloneArguments = false; + private bool $callOriginalMethods = false; + private ?object $proxyTarget = null; + private bool $allowMockingUnknownTypes = true; + private bool $returnValueGeneration = true; + private readonly Generator $generator; + + /** + * @psalm-param class-string|trait-string $type + */ + public function __construct(TestCase $testCase, string $type) + { + $this->testCase = $testCase; + $this->type = $type; + $this->generator = new Generator; + } + + /** + * Creates a mock object using a fluent interface. + * + * @throws ClassIsEnumerationException + * @throws ClassIsFinalException + * @throws ClassIsReadonlyException + * @throws DuplicateMethodException + * @throws InvalidArgumentException + * @throws InvalidMethodNameException + * @throws NameAlreadyInUseException + * @throws OriginalConstructorInvocationRequiredException + * @throws ReflectionException + * @throws RuntimeException + * @throws UnknownTypeException + * + * @psalm-return MockObject&MockedType + */ + public function getMock(): MockObject + { + $object = $this->generator->testDouble( + $this->type, + true, + !$this->emptyMethodsArray ? $this->methods : null, + $this->constructorArgs, + $this->mockClassName ?? '', + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->cloneArguments, + $this->callOriginalMethods, + $this->proxyTarget, + $this->allowMockingUnknownTypes, + $this->returnValueGeneration, + ); + + assert($object instanceof $this->type); + assert($object instanceof MockObject); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Creates a mock object for an abstract class using a fluent interface. + * + * @psalm-return MockObject&MockedType + * + * @throws Exception + * @throws ReflectionException + * @throws RuntimeException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5305 + */ + public function getMockForAbstractClass(): MockObject + { + $object = $this->generator->mockObjectForAbstractClass( + $this->type, + $this->constructorArgs, + $this->mockClassName ?? '', + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->methods, + $this->cloneArguments, + ); + + assert($object instanceof MockObject); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Creates a mock object for a trait using a fluent interface. + * + * @psalm-return MockObject&MockedType + * + * @throws Exception + * @throws ReflectionException + * @throws RuntimeException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5306 + */ + public function getMockForTrait(): MockObject + { + assert(trait_exists($this->type)); + + $object = $this->generator->mockObjectForTrait( + $this->type, + $this->constructorArgs, + $this->mockClassName ?? '', + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->methods, + $this->cloneArguments, + ); + + assert($object instanceof MockObject); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Specifies the subset of methods to mock, requiring each to exist in the class. + * + * @psalm-param list $methods + * + * @throws CannotUseOnlyMethodsException + * @throws ReflectionException + * + * @return $this + */ + public function onlyMethods(array $methods): self + { + if (empty($methods)) { + $this->emptyMethodsArray = true; + + return $this; + } + + try { + $reflector = new ReflectionClass($this->type); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + // @codeCoverageIgnoreEnd + } + + foreach ($methods as $method) { + if (!$reflector->hasMethod($method)) { + throw new CannotUseOnlyMethodsException($this->type, $method); + } + } + + $this->methods = array_merge($this->methods, $methods); + + return $this; + } + + /** + * Specifies methods that don't exist in the class which you want to mock. + * + * @psalm-param list $methods + * + * @throws CannotUseAddMethodsException + * @throws ReflectionException + * @throws RuntimeException + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5320 + */ + public function addMethods(array $methods): self + { + if (empty($methods)) { + $this->emptyMethodsArray = true; + + return $this; + } + + try { + $reflector = new ReflectionClass($this->type); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + // @codeCoverageIgnoreEnd + } + + foreach ($methods as $method) { + if ($reflector->hasMethod($method)) { + throw new CannotUseAddMethodsException($this->type, $method); + } + } + + $this->methods = array_merge($this->methods, $methods); + + return $this; + } + + /** + * Specifies the arguments for the constructor. + * + * @return $this + */ + public function setConstructorArgs(array $arguments): self + { + $this->constructorArgs = $arguments; + + return $this; + } + + /** + * Specifies the name for the mock class. + * + * @psalm-param class-string $name + * + * @return $this + */ + public function setMockClassName(string $name): self + { + $this->mockClassName = $name; + + return $this; + } + + /** + * Disables the invocation of the original constructor. + * + * @return $this + */ + public function disableOriginalConstructor(): self + { + $this->originalConstructor = false; + + return $this; + } + + /** + * Enables the invocation of the original constructor. + * + * @return $this + */ + public function enableOriginalConstructor(): self + { + $this->originalConstructor = true; + + return $this; + } + + /** + * Disables the invocation of the original clone constructor. + * + * @return $this + */ + public function disableOriginalClone(): self + { + $this->originalClone = false; + + return $this; + } + + /** + * Enables the invocation of the original clone constructor. + * + * @return $this + */ + public function enableOriginalClone(): self + { + $this->originalClone = true; + + return $this; + } + + /** + * Disables the use of class autoloading while creating the mock object. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5309 + * + * @codeCoverageIgnore + */ + public function disableAutoload(): self + { + $this->autoload = false; + + return $this; + } + + /** + * Enables the use of class autoloading while creating the mock object. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5309 + */ + public function enableAutoload(): self + { + $this->autoload = true; + + return $this; + } + + /** + * Disables the cloning of arguments passed to mocked methods. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5315 + */ + public function disableArgumentCloning(): self + { + $this->cloneArguments = false; + + return $this; + } + + /** + * Enables the cloning of arguments passed to mocked methods. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5315 + */ + public function enableArgumentCloning(): self + { + $this->cloneArguments = true; + + return $this; + } + + /** + * Enables the invocation of the original methods. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5307 + * + * @codeCoverageIgnore + */ + public function enableProxyingToOriginalMethods(): self + { + $this->callOriginalMethods = true; + + return $this; + } + + /** + * Disables the invocation of the original methods. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5307 + */ + public function disableProxyingToOriginalMethods(): self + { + $this->callOriginalMethods = false; + $this->proxyTarget = null; + + return $this; + } + + /** + * Sets the proxy target. + * + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5307 + * + * @codeCoverageIgnore + */ + public function setProxyTarget(object $object): self + { + $this->proxyTarget = $object; + + return $this; + } + + /** + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5308 + */ + public function allowMockingUnknownTypes(): self + { + $this->allowMockingUnknownTypes = true; + + return $this; + } + + /** + * @return $this + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5308 + */ + public function disallowMockingUnknownTypes(): self + { + $this->allowMockingUnknownTypes = false; + + return $this; + } + + /** + * @return $this + */ + public function enableAutoReturnValueGeneration(): self + { + $this->returnValueGeneration = true; + + return $this; + } + + /** + * @return $this + */ + public function disableAutoReturnValueGeneration(): self + { + $this->returnValueGeneration = false; + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php new file mode 100644 index 000000000..17ad85d7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait DoubledCloneMethod +{ + public function __clone(): void + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php new file mode 100644 index 000000000..ef77e3cb5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/Method.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function call_user_func_array; +use function func_get_args; +use PHPUnit\Framework\MockObject\Builder\InvocationMocker; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait Method +{ + public function method(): InvocationMocker + { + $expects = $this->expects(new AnyInvokedCount); + + return call_user_func_array( + [$expects, 'method'], + func_get_args(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php new file mode 100644 index 000000000..28b55d6b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\MockObject\Builder\InvocationMocker as InvocationMockerBuilder; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait MockObjectApi +{ + private object $__phpunit_originalObject; + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_hasMatchers(): bool + { + return $this->__phpunit_getInvocationHandler()->hasMatchers(); + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_setOriginalObject(object $originalObject): void + { + $this->__phpunit_originalObject = $originalObject; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_verify(bool $unsetInvocationMocker = true): void + { + $this->__phpunit_getInvocationHandler()->verify(); + + if ($unsetInvocationMocker) { + $this->__phpunit_unsetInvocationMocker(); + } + } + + abstract public function __phpunit_getInvocationHandler(): InvocationHandler; + + abstract public function __phpunit_unsetInvocationMocker(): void; + + public function expects(InvocationOrder $matcher): InvocationMockerBuilder + { + return $this->__phpunit_getInvocationHandler()->expects($matcher); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php new file mode 100644 index 000000000..4099a6417 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait ProxiedCloneMethod +{ + public function __clone(): void + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationHandler(); + + parent::__clone(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php new file mode 100644 index 000000000..10dfe4cdd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This trait is not covered by the backward compatibility promise for PHPUnit + */ +trait StubApi +{ + /** + * @psalm-var list + */ + private static array $__phpunit_configurableMethods; + private bool $__phpunit_returnValueGeneration = true; + private ?InvocationHandler $__phpunit_invocationMocker = null; + + /** @noinspection MagicMethodsValidityInspection */ + public static function __phpunit_initConfigurableMethods(ConfigurableMethod ...$configurableMethods): void + { + static::$__phpunit_configurableMethods = $configurableMethods; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void + { + $this->__phpunit_returnValueGeneration = $returnValueGeneration; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_getInvocationHandler(): InvocationHandler + { + if ($this->__phpunit_invocationMocker === null) { + $this->__phpunit_invocationMocker = new InvocationHandler( + static::$__phpunit_configurableMethods, + $this->__phpunit_returnValueGeneration, + ); + } + + return $this->__phpunit_invocationMocker; + } + + /** @noinspection MagicMethodsValidityInspection */ + public function __phpunit_unsetInvocationMocker(): void + { + $this->__phpunit_invocationMocker = null; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php new file mode 100644 index 000000000..07a9d37cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Identity +{ + /** + * Sets the identification of the expectation to $id. + * + * @note The identifier is unique per mock object. + */ + public function id(string $id): self; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php new file mode 100644 index 000000000..fbff6cbda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.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 PHPUnit\Framework\MockObject\Builder; + +use function array_flip; +use function array_key_exists; +use function array_map; +use function array_merge; +use function array_pop; +use function assert; +use function count; +use function is_string; +use function range; +use function strtolower; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\MockObject\ConfigurableMethod; +use PHPUnit\Framework\MockObject\IncompatibleReturnValueException; +use PHPUnit\Framework\MockObject\InvocationHandler; +use PHPUnit\Framework\MockObject\Matcher; +use PHPUnit\Framework\MockObject\MatcherAlreadyRegisteredException; +use PHPUnit\Framework\MockObject\MethodCannotBeConfiguredException; +use PHPUnit\Framework\MockObject\MethodNameAlreadyConfiguredException; +use PHPUnit\Framework\MockObject\MethodNameNotConfiguredException; +use PHPUnit\Framework\MockObject\MethodParametersAlreadyConfiguredException; +use PHPUnit\Framework\MockObject\Rule; +use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls; +use PHPUnit\Framework\MockObject\Stub\Exception; +use PHPUnit\Framework\MockObject\Stub\ReturnArgument; +use PHPUnit\Framework\MockObject\Stub\ReturnCallback; +use PHPUnit\Framework\MockObject\Stub\ReturnReference; +use PHPUnit\Framework\MockObject\Stub\ReturnSelf; +use PHPUnit\Framework\MockObject\Stub\ReturnStub; +use PHPUnit\Framework\MockObject\Stub\ReturnValueMap; +use PHPUnit\Framework\MockObject\Stub\Stub; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class InvocationMocker implements InvocationStubber, MethodNameMatch +{ + private readonly InvocationHandler $invocationHandler; + private readonly Matcher $matcher; + + /** + * @psalm-var list + */ + private readonly array $configurableMethods; + + /** + * @psalm-var ?array + */ + private ?array $configurableMethodNames = null; + + public function __construct(InvocationHandler $handler, Matcher $matcher, ConfigurableMethod ...$configurableMethods) + { + $this->invocationHandler = $handler; + $this->matcher = $matcher; + $this->configurableMethods = $configurableMethods; + } + + /** + * @throws MatcherAlreadyRegisteredException + * + * @return $this + */ + public function id(string $id): self + { + $this->invocationHandler->registerMatcher($id, $this->matcher); + + return $this; + } + + /** + * @return $this + */ + public function will(Stub $stub): Identity + { + $this->matcher->setStub($stub); + + return $this; + } + + /** + * @throws IncompatibleReturnValueException + */ + public function willReturn(mixed $value, mixed ...$nextValues): self + { + if (count($nextValues) === 0) { + $this->ensureTypeOfReturnValues([$value]); + + $stub = $value instanceof Stub ? $value : new ReturnStub($value); + + return $this->will($stub); + } + + $values = array_merge([$value], $nextValues); + + $this->ensureTypeOfReturnValues($values); + + $stub = new ConsecutiveCalls($values); + + return $this->will($stub); + } + + public function willReturnReference(mixed &$reference): self + { + $stub = new ReturnReference($reference); + + return $this->will($stub); + } + + public function willReturnMap(array $valueMap): self + { + $method = $this->configuredMethod(); + + assert($method instanceof ConfigurableMethod); + + $numberOfParameters = $method->numberOfParameters(); + $defaultValues = $method->defaultParameterValues(); + $hasDefaultValues = !empty($defaultValues); + + $_valueMap = []; + + foreach ($valueMap as $mapping) { + $numberOfConfiguredParameters = count($mapping) - 1; + + if ($numberOfConfiguredParameters === $numberOfParameters || !$hasDefaultValues) { + $_valueMap[] = $mapping; + + continue; + } + + $_mapping = []; + $returnValue = array_pop($mapping); + + foreach (range(0, $numberOfParameters - 1) as $i) { + if (isset($mapping[$i])) { + $_mapping[] = $mapping[$i]; + + continue; + } + + if (isset($defaultValues[$i])) { + $_mapping[] = $defaultValues[$i]; + } + } + + $_mapping[] = $returnValue; + $_valueMap[] = $_mapping; + } + + $stub = new ReturnValueMap($_valueMap); + + return $this->will($stub); + } + + public function willReturnArgument(int $argumentIndex): self + { + $stub = new ReturnArgument($argumentIndex); + + return $this->will($stub); + } + + public function willReturnCallback(callable $callback): self + { + $stub = new ReturnCallback($callback); + + return $this->will($stub); + } + + public function willReturnSelf(): self + { + $stub = new ReturnSelf; + + return $this->will($stub); + } + + public function willReturnOnConsecutiveCalls(mixed ...$values): self + { + $stub = new ConsecutiveCalls($values); + + return $this->will($stub); + } + + public function willThrowException(Throwable $exception): self + { + $stub = new Exception($exception); + + return $this->will($stub); + } + + /** + * @return $this + */ + public function after(string $id): self + { + $this->matcher->setAfterMatchBuilderId($id); + + return $this; + } + + /** + * @throws \PHPUnit\Framework\Exception + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + * + * @return $this + */ + public function with(mixed ...$arguments): self + { + $this->ensureParametersCanBeConfigured(); + + $this->matcher->setParametersRule(new Rule\Parameters($arguments)); + + return $this; + } + + /** + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + * + * @return $this + */ + public function withAnyParameters(): self + { + $this->ensureParametersCanBeConfigured(); + + $this->matcher->setParametersRule(new Rule\AnyParameters); + + return $this; + } + + /** + * @throws InvalidArgumentException + * @throws MethodCannotBeConfiguredException + * @throws MethodNameAlreadyConfiguredException + * + * @return $this + */ + public function method(Constraint|string $constraint): self + { + if ($this->matcher->hasMethodNameRule()) { + throw new MethodNameAlreadyConfiguredException; + } + + if (is_string($constraint)) { + $this->configurableMethodNames ??= array_flip( + array_map( + static fn (ConfigurableMethod $configurable) => strtolower($configurable->name()), + $this->configurableMethods, + ), + ); + + if (!array_key_exists(strtolower($constraint), $this->configurableMethodNames)) { + throw new MethodCannotBeConfiguredException($constraint); + } + } + + $this->matcher->setMethodNameRule(new Rule\MethodName($constraint)); + + return $this; + } + + /** + * @throws MethodNameNotConfiguredException + * @throws MethodParametersAlreadyConfiguredException + */ + private function ensureParametersCanBeConfigured(): void + { + if (!$this->matcher->hasMethodNameRule()) { + throw new MethodNameNotConfiguredException; + } + + if ($this->matcher->hasParametersRule()) { + throw new MethodParametersAlreadyConfiguredException; + } + } + + private function configuredMethod(): ?ConfigurableMethod + { + $configuredMethod = null; + + foreach ($this->configurableMethods as $configurableMethod) { + if ($this->matcher->methodNameRule()->matchesName($configurableMethod->name())) { + if ($configuredMethod !== null) { + return null; + } + + $configuredMethod = $configurableMethod; + } + } + + return $configuredMethod; + } + + /** + * @throws IncompatibleReturnValueException + */ + private function ensureTypeOfReturnValues(array $values): void + { + $configuredMethod = $this->configuredMethod(); + + if ($configuredMethod === null) { + return; + } + + foreach ($values as $value) { + if (!$configuredMethod->mayReturn($value)) { + throw new IncompatibleReturnValueException( + $configuredMethod, + $value, + ); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php new file mode 100644 index 000000000..9918b77f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\MockObject\Stub\Stub; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface InvocationStubber +{ + public function will(Stub $stub): Identity; + + public function willReturn(mixed $value, mixed ...$nextValues): self; + + public function willReturnReference(mixed &$reference): self; + + /** + * @psalm-param array> $valueMap + */ + public function willReturnMap(array $valueMap): self; + + public function willReturnArgument(int $argumentIndex): self; + + public function willReturnCallback(callable $callback): self; + + public function willReturnSelf(): self; + + public function willReturnOnConsecutiveCalls(mixed ...$values): self; + + public function willThrowException(Throwable $exception): self; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php new file mode 100644 index 000000000..c25e8df7c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\Constraint\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface MethodNameMatch extends ParametersMatch +{ + /** + * Adds a new method name match and returns the parameter match object for + * further matching possibilities. + */ + public function method(Constraint|string $constraint): self; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php new file mode 100644 index 000000000..96493d441 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface ParametersMatch extends Stub +{ + /** + * Defines the expectation which must occur before the current is valid. + */ + public function after(string $id): Stub; + + /** + * Sets the parameters to match for, each parameter to this function will + * be part of match. To perform specific matches or constraints create a + * new PHPUnit\Framework\Constraint\Constraint and use it for the parameter. + * If the parameter value is not a constraint it will use the + * PHPUnit\Framework\Constraint\IsEqual for the value. + * + * Some examples: + * + * // match first parameter with value 2 + * $b->with(2); + * // match first parameter with value 'smock' and second identical to 42 + * $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42)); + * + */ + public function with(mixed ...$arguments): self; + + /** + * Sets a rule which allows any kind of parameters. + * + * Some examples: + * + * // match any number of parameters + * $b->withAnyParameters(); + * + */ + public function withAnyParameters(): self; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php new file mode 100644 index 000000000..fce475490 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\MockObject\Stub\Stub as BaseStub; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Stub extends Identity +{ + /** + * Stubs the matching method with the stub object $stub. Any invocations of + * the matched method will now be handled by the stub instead. + */ + public function will(BaseStub $stub): Identity; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php new file mode 100644 index 000000000..4096d73f9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\MockObject\Builder\InvocationMocker; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; + +/** + * @method InvocationMocker method($constraint) + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface MockObject extends Stub +{ + public function expects(InvocationOrder $invocationRule): InvocationMocker; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php new file mode 100644 index 000000000..fe5bbdf6d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface MockObjectInternal extends MockObject, StubInternal +{ + public function __phpunit_hasMatchers(): bool; + + public function __phpunit_setOriginalObject(object $originalObject): void; + + public function __phpunit_verify(bool $unsetInvocationMocker = true): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php new file mode 100644 index 000000000..96f84d231 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\MockObject\Builder\InvocationStubber; + +/** + * @method InvocationStubber method($constraint) + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Stub +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php new file mode 100644 index 000000000..91f6464f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface StubInternal extends Stub +{ + public static function __phpunit_initConfigurableMethods(ConfigurableMethod ...$configurableMethods): void; + + public function __phpunit_getInvocationHandler(): InvocationHandler; + + public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration): void; + + public function __phpunit_unsetInvocationMocker(): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php new file mode 100644 index 000000000..008b372b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Invocation.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_map; +use function implode; +use function is_object; +use function sprintf; +use function str_starts_with; +use function strtolower; +use function substr; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Util\Cloner; +use SebastianBergmann\Exporter\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Invocation implements SelfDescribing +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + private readonly array $parameters; + private readonly string $returnType; + private readonly bool $isReturnTypeNullable; + private readonly bool $proxiedCall; + private readonly MockObjectInternal|StubInternal $object; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function __construct(string $className, string $methodName, array $parameters, string $returnType, MockObjectInternal|StubInternal $object, bool $cloneObjects = false, bool $proxiedCall = false) + { + $this->className = $className; + $this->methodName = $methodName; + $this->object = $object; + $this->proxiedCall = $proxiedCall; + + if (strtolower($methodName) === '__tostring') { + $returnType = 'string'; + } + + if (str_starts_with($returnType, '?')) { + $returnType = substr($returnType, 1); + $this->isReturnTypeNullable = true; + } else { + $this->isReturnTypeNullable = false; + } + + $this->returnType = $returnType; + + if (!$cloneObjects) { + $this->parameters = $parameters; + + return; + } + + foreach ($parameters as $key => $value) { + if (is_object($value)) { + $parameters[$key] = Cloner::clone($value); + } + } + + $this->parameters = $parameters; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } + + public function parameters(): array + { + return $this->parameters; + } + + /** + * @throws Exception + */ + public function generateReturnValue(): mixed + { + if ($this->returnType === 'never') { + throw new NeverReturningMethodException( + $this->className, + $this->methodName, + ); + } + + if ($this->isReturnTypeNullable || $this->proxiedCall) { + return null; + } + + return (new ReturnValueGenerator)->generate( + $this->className, + $this->methodName, + $this->object::class, + $this->returnType, + ); + } + + public function toString(): string + { + $exporter = new Exporter; + + return sprintf( + '%s::%s(%s)%s', + $this->className, + $this->methodName, + implode( + ', ', + array_map( + [$exporter, 'shortenedExport'], + $this->parameters, + ), + ), + $this->returnType ? sprintf(': %s', $this->returnType) : '', + ); + } + + public function object(): MockObjectInternal|StubInternal + { + return $this->object; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php new file mode 100644 index 000000000..4228d17d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function strtolower; +use Exception; +use PHPUnit\Framework\MockObject\Builder\InvocationMocker; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvocationHandler +{ + /** + * @psalm-var list + */ + private array $matchers = []; + + /** + * @psalm-var array + */ + private array $matcherMap = []; + + /** + * @psalm-var list + */ + private readonly array $configurableMethods; + private readonly bool $returnValueGeneration; + + /** + * @psalm-param list $configurableMethods + */ + public function __construct(array $configurableMethods, bool $returnValueGeneration) + { + $this->configurableMethods = $configurableMethods; + $this->returnValueGeneration = $returnValueGeneration; + } + + public function hasMatchers(): bool + { + foreach ($this->matchers as $matcher) { + if ($matcher->hasMatchers()) { + return true; + } + } + + return false; + } + + /** + * Looks up the match builder with identification $id and returns it. + */ + public function lookupMatcher(string $id): ?Matcher + { + return $this->matcherMap[$id] ?? null; + } + + /** + * Registers a matcher with the identification $id. The matcher can later be + * looked up using lookupMatcher() to figure out if it has been invoked. + * + * @throws MatcherAlreadyRegisteredException + */ + public function registerMatcher(string $id, Matcher $matcher): void + { + if (isset($this->matcherMap[$id])) { + throw new MatcherAlreadyRegisteredException($id); + } + + $this->matcherMap[$id] = $matcher; + } + + public function expects(InvocationOrder $rule): InvocationMocker + { + $matcher = new Matcher($rule); + $this->addMatcher($matcher); + + return new InvocationMocker( + $this, + $matcher, + ...$this->configurableMethods, + ); + } + + /** + * @throws \PHPUnit\Framework\MockObject\Exception + * @throws Exception + */ + public function invoke(Invocation $invocation): mixed + { + $exception = null; + $hasReturnValue = false; + $returnValue = null; + + foreach ($this->matchers as $match) { + try { + if ($match->matches($invocation)) { + $value = $match->invoked($invocation); + + if (!$hasReturnValue) { + $returnValue = $value; + $hasReturnValue = true; + } + } + } catch (Exception $e) { + $exception = $e; + } + } + + if ($exception !== null) { + throw $exception; + } + + if ($hasReturnValue) { + return $returnValue; + } + + if (!$this->returnValueGeneration) { + if (strtolower($invocation->methodName()) === '__tostring') { + return ''; + } + + throw new ReturnValueNotConfiguredException($invocation); + } + + return $invocation->generateReturnValue(); + } + + /** + * @throws Throwable + */ + public function verify(): void + { + foreach ($this->matchers as $matcher) { + $matcher->verify(); + } + } + + private function addMatcher(Matcher $matcher): void + { + $this->matchers[] = $matcher; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php new file mode 100644 index 000000000..128a5856b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Matcher.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount; +use PHPUnit\Framework\MockObject\Rule\AnyParameters; +use PHPUnit\Framework\MockObject\Rule\InvocationOrder; +use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount; +use PHPUnit\Framework\MockObject\Rule\InvokedCount; +use PHPUnit\Framework\MockObject\Rule\MethodName; +use PHPUnit\Framework\MockObject\Rule\ParametersRule; +use PHPUnit\Framework\MockObject\Stub\Stub; +use PHPUnit\Util\ThrowableToStringMapper; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Matcher +{ + private readonly InvocationOrder $invocationRule; + private ?string $afterMatchBuilderId = null; + private ?MethodName $methodNameRule = null; + private ?ParametersRule $parametersRule = null; + private ?Stub $stub = null; + + public function __construct(InvocationOrder $rule) + { + $this->invocationRule = $rule; + } + + public function hasMatchers(): bool + { + return !$this->invocationRule instanceof AnyInvokedCount; + } + + public function hasMethodNameRule(): bool + { + return $this->methodNameRule !== null; + } + + public function methodNameRule(): MethodName + { + return $this->methodNameRule; + } + + public function setMethodNameRule(MethodName $rule): void + { + $this->methodNameRule = $rule; + } + + public function hasParametersRule(): bool + { + return $this->parametersRule !== null; + } + + public function setParametersRule(ParametersRule $rule): void + { + $this->parametersRule = $rule; + } + + public function setStub(Stub $stub): void + { + $this->stub = $stub; + } + + public function setAfterMatchBuilderId(string $id): void + { + $this->afterMatchBuilderId = $id; + } + + /** + * @throws Exception + * @throws ExpectationFailedException + * @throws MatchBuilderNotFoundException + * @throws MethodNameNotConfiguredException + * @throws RuntimeException + */ + public function invoked(Invocation $invocation): mixed + { + if ($this->methodNameRule === null) { + throw new MethodNameNotConfiguredException; + } + + if ($this->afterMatchBuilderId !== null) { + $matcher = $invocation->object() + ->__phpunit_getInvocationHandler() + ->lookupMatcher($this->afterMatchBuilderId); + + if (!$matcher) { + throw new MatchBuilderNotFoundException($this->afterMatchBuilderId); + } + } + + $this->invocationRule->invoked($invocation); + + try { + $this->parametersRule?->apply($invocation); + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + sprintf( + "Expectation failed for %s when %s\n%s", + $this->methodNameRule->toString(), + $this->invocationRule->toString(), + $e->getMessage(), + ), + $e->getComparisonFailure(), + ); + } + + if ($this->stub) { + return $this->stub->invoke($invocation); + } + + return $invocation->generateReturnValue(); + } + + /** + * @throws ExpectationFailedException + * @throws MatchBuilderNotFoundException + * @throws MethodNameNotConfiguredException + * @throws RuntimeException + */ + public function matches(Invocation $invocation): bool + { + if ($this->afterMatchBuilderId !== null) { + $matcher = $invocation->object() + ->__phpunit_getInvocationHandler() + ->lookupMatcher($this->afterMatchBuilderId); + + if (!$matcher) { + throw new MatchBuilderNotFoundException($this->afterMatchBuilderId); + } + + if (!$matcher->invocationRule->hasBeenInvoked()) { + return false; + } + } + + if ($this->methodNameRule === null) { + throw new MethodNameNotConfiguredException; + } + + if (!$this->invocationRule->matches($invocation)) { + return false; + } + + try { + if (!$this->methodNameRule->matches($invocation)) { + return false; + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + sprintf( + "Expectation failed for %s when %s\n%s", + $this->methodNameRule->toString(), + $this->invocationRule->toString(), + $e->getMessage(), + ), + $e->getComparisonFailure(), + ); + } + + return true; + } + + /** + * @throws ExpectationFailedException + * @throws MethodNameNotConfiguredException + */ + public function verify(): void + { + if ($this->methodNameRule === null) { + throw new MethodNameNotConfiguredException; + } + + try { + $this->invocationRule->verify(); + + if ($this->parametersRule === null) { + $this->parametersRule = new AnyParameters; + } + + $invocationIsAny = $this->invocationRule instanceof AnyInvokedCount; + $invocationIsNever = $this->invocationRule instanceof InvokedCount && $this->invocationRule->isNever(); + $invocationIsAtMost = $this->invocationRule instanceof InvokedAtMostCount; + + if (!$invocationIsAny && !$invocationIsNever && !$invocationIsAtMost) { + $this->parametersRule->verify(); + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + sprintf( + "Expectation failed for %s when %s.\n%s", + $this->methodNameRule->toString(), + $this->invocationRule->toString(), + ThrowableToStringMapper::map($e), + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php new file mode 100644 index 000000000..db17134be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function sprintf; +use function strtolower; +use PHPUnit\Framework\Constraint\Constraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodNameConstraint extends Constraint +{ + private readonly string $methodName; + + public function __construct(string $methodName) + { + $this->methodName = $methodName; + } + + public function toString(): string + { + return sprintf( + 'is "%s"', + $this->methodName, + ); + } + + protected function matches(mixed $other): bool + { + return strtolower($this->methodName) === strtolower((string) $other); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php new file mode 100644 index 000000000..7cf1cd6a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php @@ -0,0 +1,250 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use function array_keys; +use function array_map; +use function explode; +use function in_array; +use function interface_exists; +use function sprintf; +use function str_contains; +use function str_ends_with; +use function str_starts_with; +use function substr; +use PHPUnit\Framework\MockObject\Generator\Generator; +use ReflectionClass; +use stdClass; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnValueGenerator +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * @psalm-param class-string $stubClassName + * + * @throws Exception + */ + public function generate(string $className, string $methodName, string $stubClassName, string $returnType): mixed + { + $intersection = false; + $union = false; + + if (str_contains($returnType, '|')) { + $types = explode('|', $returnType); + $union = true; + + foreach (array_keys($types) as $key) { + if (str_starts_with($types[$key], '(') && str_ends_with($types[$key], ')')) { + $types[$key] = substr($types[$key], 1, -1); + } + } + } elseif (str_contains($returnType, '&')) { + $types = explode('&', $returnType); + $intersection = true; + } else { + $types = [$returnType]; + } + + if (!$intersection) { + $lowerTypes = array_map('strtolower', $types); + + if (in_array('', $lowerTypes, true) || + in_array('null', $lowerTypes, true) || + in_array('mixed', $lowerTypes, true) || + in_array('void', $lowerTypes, true)) { + return null; + } + + if (in_array('true', $lowerTypes, true)) { + return true; + } + + if (in_array('false', $lowerTypes, true) || + in_array('bool', $lowerTypes, true)) { + return false; + } + + if (in_array('float', $lowerTypes, true)) { + return 0.0; + } + + if (in_array('int', $lowerTypes, true)) { + return 0; + } + + if (in_array('string', $lowerTypes, true)) { + return ''; + } + + if (in_array('array', $lowerTypes, true)) { + return []; + } + + if (in_array('static', $lowerTypes, true)) { + return $this->newInstanceOf($stubClassName, $className, $methodName); + } + + if (in_array('object', $lowerTypes, true)) { + return new stdClass; + } + + if (in_array('callable', $lowerTypes, true) || + in_array('closure', $lowerTypes, true)) { + return static function (): void + { + }; + } + + if (in_array('traversable', $lowerTypes, true) || + in_array('generator', $lowerTypes, true) || + in_array('iterable', $lowerTypes, true)) { + $generator = static function (): \Generator + { + yield from []; + }; + + return $generator(); + } + + if (!$union) { + return $this->testDoubleFor($returnType, $className, $methodName); + } + } + + if ($union) { + foreach ($types as $type) { + if (str_contains($type, '&')) { + $_types = explode('&', $type); + + if ($this->onlyInterfaces($_types)) { + return $this->testDoubleForIntersectionOfInterfaces($_types, $className, $methodName); + } + } + } + } + + if ($intersection && $this->onlyInterfaces($types)) { + return $this->testDoubleForIntersectionOfInterfaces($types, $className, $methodName); + } + + $reason = ''; + + if ($union) { + $reason = ' because the declared return type is a union'; + } elseif ($intersection) { + $reason = ' because the declared return type is an intersection'; + } + + throw new RuntimeException( + sprintf( + 'Return value for %s::%s() cannot be generated%s, please configure a return value for this method', + $className, + $methodName, + $reason, + ), + ); + } + + /** + * @psalm-param non-empty-list $types + */ + private function onlyInterfaces(array $types): bool + { + foreach ($types as $type) { + if (!interface_exists($type)) { + return false; + } + } + + return true; + } + + /** + * @psalm-param class-string $stubClassName + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws RuntimeException + */ + private function newInstanceOf(string $stubClassName, string $className, string $methodName): Stub + { + try { + return (new ReflectionClass($stubClassName))->newInstanceWithoutConstructor(); + // @codeCoverageIgnoreStart + } catch (Throwable $t) { + throw new RuntimeException( + sprintf( + 'Return value for %s::%s() cannot be generated: %s', + $className, + $methodName, + $t->getMessage(), + ), + ); + // @codeCoverageIgnoreEnd + } + } + + /** + * @psalm-param class-string $type + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws RuntimeException + */ + private function testDoubleFor(string $type, string $className, string $methodName): Stub + { + try { + return (new Generator)->testDouble($type, false, [], [], '', false); + // @codeCoverageIgnoreStart + } catch (Throwable $t) { + throw new RuntimeException( + sprintf( + 'Return value for %s::%s() cannot be generated: %s', + $className, + $methodName, + $t->getMessage(), + ), + ); + // @codeCoverageIgnoreEnd + } + } + + /** + * @psalm-param non-empty-list $types + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws RuntimeException + */ + private function testDoubleForIntersectionOfInterfaces(array $types, string $className, string $methodName): Stub + { + try { + return (new Generator)->testDoubleForInterfaceIntersection($types, false); + // @codeCoverageIgnoreStart + } catch (Throwable $t) { + throw new RuntimeException( + sprintf( + 'Return value for %s::%s() cannot be generated: %s', + $className, + $methodName, + $t->getMessage(), + ), + ); + // @codeCoverageIgnoreEnd + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php new file mode 100644 index 000000000..382f93081 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AnyInvokedCount extends InvocationOrder +{ + public function toString(): string + { + return 'invoked zero or more times'; + } + + public function verify(): void + { + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php new file mode 100644 index 000000000..01a54d1b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AnyParameters implements ParametersRule +{ + public function apply(BaseInvocation $invocation): void + { + } + + public function verify(): void + { + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php new file mode 100644 index 000000000..5d8429d87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function count; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Framework\SelfDescribing; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class InvocationOrder implements SelfDescribing +{ + /** + * @psalm-var list + */ + private array $invocations = []; + + public function numberOfInvocations(): int + { + return count($this->invocations); + } + + public function hasBeenInvoked(): bool + { + return count($this->invocations) > 0; + } + + final public function invoked(BaseInvocation $invocation): void + { + $this->invocations[] = $invocation; + + $this->invokedDo($invocation); + } + + abstract public function matches(BaseInvocation $invocation): bool; + + abstract public function verify(): void; + + protected function invokedDo(BaseInvocation $invocation): void + { + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php new file mode 100644 index 000000000..a78d933d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedAtLeastCount extends InvocationOrder +{ + private readonly int $requiredInvocations; + + public function __construct(int $requiredInvocations) + { + $this->requiredInvocations = $requiredInvocations; + } + + public function toString(): string + { + return sprintf( + 'invoked at least %d time%s', + $this->requiredInvocations, + $this->requiredInvocations !== 1 ? 's' : '', + ); + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $actualInvocations = $this->numberOfInvocations(); + + if ($actualInvocations < $this->requiredInvocations) { + throw new ExpectationFailedException( + sprintf( + 'Expected invocation at least %d time%s but it occurred %d time%s.', + $this->requiredInvocations, + $this->requiredInvocations !== 1 ? 's' : '', + $actualInvocations, + $actualInvocations !== 1 ? 's' : '', + ), + ); + } + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php new file mode 100644 index 000000000..91026f53d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.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 PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedAtLeastOnce extends InvocationOrder +{ + public function toString(): string + { + return 'invoked at least once'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->numberOfInvocations(); + + if ($count < 1) { + throw new ExpectationFailedException( + 'Expected invocation at least once but it never occurred.', + ); + } + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php new file mode 100644 index 000000000..0cfda5e18 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedAtMostCount extends InvocationOrder +{ + private readonly int $allowedInvocations; + + public function __construct(int $allowedInvocations) + { + $this->allowedInvocations = $allowedInvocations; + } + + public function toString(): string + { + return sprintf( + 'invoked at most %d time%s', + $this->allowedInvocations, + $this->allowedInvocations !== 1 ? 's' : '', + ); + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $actualInvocations = $this->numberOfInvocations(); + + if ($actualInvocations > $this->allowedInvocations) { + throw new ExpectationFailedException( + sprintf( + 'Expected invocation at most %d time%s but it occurred %d time%s.', + $this->allowedInvocations, + $this->allowedInvocations !== 1 ? 's' : '', + $actualInvocations, + $actualInvocations !== 1 ? 's' : '', + ), + ); + } + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php new file mode 100644 index 000000000..3f0e505a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.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 PHPUnit\Framework\MockObject\Rule; + +use function sprintf; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvokedCount extends InvocationOrder +{ + private readonly int $expectedCount; + + public function __construct(int $expectedCount) + { + $this->expectedCount = $expectedCount; + } + + public function isNever(): bool + { + return $this->expectedCount === 0; + } + + public function toString(): string + { + return sprintf( + 'invoked %d time%s', + $this->expectedCount, + $this->expectedCount !== 1 ? 's' : '', + ); + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $actualCount = $this->numberOfInvocations(); + + if ($actualCount !== $this->expectedCount) { + throw new ExpectationFailedException( + sprintf( + 'Method was expected to be called %d time%s, actually called %d time%s.', + $this->expectedCount, + $this->expectedCount !== 1 ? 's' : '', + $actualCount, + $actualCount !== 1 ? 's' : '', + ), + ); + } + } + + /** + * @throws ExpectationFailedException + */ + protected function invokedDo(BaseInvocation $invocation): void + { + $count = $this->numberOfInvocations(); + + if ($count > $this->expectedCount) { + $message = $invocation->toString() . ' '; + + $message .= match ($this->expectedCount) { + 0 => 'was not expected to be called.', + 1 => 'was not expected to be called more than once.', + default => sprintf( + 'was not expected to be called more than %d times.', + $this->expectedCount, + ), + }; + + throw new ExpectationFailedException($message); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php new file mode 100644 index 000000000..8ca6da680 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.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 PHPUnit\Framework\MockObject\Rule; + +use function is_string; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Framework\MockObject\MethodNameConstraint; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MethodName +{ + private readonly Constraint $constraint; + + /** + * @throws InvalidArgumentException + */ + public function __construct(Constraint|string $constraint) + { + if (is_string($constraint)) { + $constraint = new MethodNameConstraint($constraint); + } + + $this->constraint = $constraint; + } + + public function toString(): string + { + return 'method name ' . $this->constraint->toString(); + } + + /** + * @throws ExpectationFailedException + */ + public function matches(BaseInvocation $invocation): bool + { + return $this->matchesName($invocation->methodName()); + } + + /** + * @throws ExpectationFailedException + */ + public function matchesName(string $methodName): bool + { + return (bool) $this->constraint->evaluate($methodName, '', true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php new file mode 100644 index 000000000..a1f100d08 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.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 PHPUnit\Framework\MockObject\Rule; + +use function count; +use function sprintf; +use Exception; +use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Parameters implements ParametersRule +{ + /** + * @psalm-var list + */ + private array $parameters = []; + private ?BaseInvocation $invocation = null; + private null|bool|ExpectationFailedException $parameterVerificationResult; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(array $parameters) + { + foreach ($parameters as $parameter) { + if (!($parameter instanceof Constraint)) { + $parameter = new IsEqual( + $parameter, + ); + } + + $this->parameters[] = $parameter; + } + } + + /** + * @throws Exception + */ + public function apply(BaseInvocation $invocation): void + { + $this->invocation = $invocation; + $this->parameterVerificationResult = null; + + try { + $this->parameterVerificationResult = $this->doVerify(); + } catch (ExpectationFailedException $e) { + $this->parameterVerificationResult = $e; + + throw $this->parameterVerificationResult; + } + } + + /** + * Checks if the invocation $invocation matches the current rules. If it + * does the rule will get the invoked() method called which should check + * if an expectation is met. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $this->doVerify(); + } + + /** + * @throws ExpectationFailedException + */ + private function doVerify(): bool + { + if (isset($this->parameterVerificationResult)) { + return $this->guardAgainstDuplicateEvaluationOfParameterConstraints(); + } + + if ($this->invocation === null) { + throw new ExpectationFailedException('Mocked method does not exist.'); + } + + if (count($this->invocation->parameters()) < count($this->parameters)) { + $message = 'Parameter count for invocation %s is too low.'; + + // The user called `->with($this->anything())`, but may have meant + // `->withAnyParameters()`. + // + // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199 + if (count($this->parameters) === 1 && + $this->parameters[0]::class === IsAnything::class) { + $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead."; + } + + throw new ExpectationFailedException( + sprintf($message, $this->invocation->toString()), + ); + } + + foreach ($this->parameters as $i => $parameter) { + if ($parameter instanceof Callback && $parameter->isVariadic()) { + $other = $this->invocation->parameters(); + } else { + $other = $this->invocation->parameters()[$i]; + } + $parameter->evaluate( + $other, + sprintf( + 'Parameter %s for invocation %s does not match expected ' . + 'value.', + $i, + $this->invocation->toString(), + ), + ); + } + + return true; + } + + /** + * @throws ExpectationFailedException + */ + private function guardAgainstDuplicateEvaluationOfParameterConstraints(): bool + { + if ($this->parameterVerificationResult instanceof ExpectationFailedException) { + throw $this->parameterVerificationResult; + } + + return (bool) $this->parameterVerificationResult; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php new file mode 100644 index 000000000..03cfe2a48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Rule; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface ParametersRule +{ + /** + * @throws ExpectationFailedException if the invocation violates the rule + */ + public function apply(BaseInvocation $invocation): void; + + public function verify(): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php new file mode 100644 index 000000000..7b1297de5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function array_shift; +use function count; +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\NoMoreReturnValuesConfiguredException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConsecutiveCalls implements Stub +{ + private array $stack; + private int $numberOfConfiguredReturnValues; + + public function __construct(array $stack) + { + $this->stack = $stack; + $this->numberOfConfiguredReturnValues = count($stack); + } + + /** + * @throws NoMoreReturnValuesConfiguredException + */ + public function invoke(Invocation $invocation): mixed + { + if (empty($this->stack)) { + throw new NoMoreReturnValuesConfiguredException( + $invocation, + $this->numberOfConfiguredReturnValues, + ); + } + + $value = array_shift($this->stack); + + if ($value instanceof Stub) { + $value = $value->invoke($invocation); + } + + return $value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php new file mode 100644 index 000000000..a17fe97ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception implements Stub +{ + private readonly Throwable $exception; + + public function __construct(Throwable $exception) + { + $this->exception = $exception; + } + + /** + * @throws Throwable + */ + public function invoke(Invocation $invocation): never + { + throw $this->exception; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php new file mode 100644 index 000000000..18fdce0fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnArgument implements Stub +{ + private readonly int $argumentIndex; + + public function __construct(int $argumentIndex) + { + $this->argumentIndex = $argumentIndex; + } + + public function invoke(Invocation $invocation): mixed + { + return $invocation->parameters()[$this->argumentIndex] ?? null; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php new file mode 100644 index 000000000..4e4cd5310 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function call_user_func_array; +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnCallback implements Stub +{ + /** + * @var callable + */ + private $callback; + + public function __construct(callable $callback) + { + $this->callback = $callback; + } + + public function invoke(Invocation $invocation): mixed + { + return call_user_func_array($this->callback, $invocation->parameters()); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php new file mode 100644 index 000000000..448df4527 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnReference implements Stub +{ + private mixed $reference; + + public function __construct(mixed &$reference) + { + $this->reference = &$reference; + } + + public function invoke(Invocation $invocation): mixed + { + return $this->reference; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php new file mode 100644 index 000000000..4101d71ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnSelf implements Stub +{ + /** + * @throws RuntimeException + */ + public function invoke(Invocation $invocation): object + { + return $invocation->object(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php new file mode 100644 index 000000000..278c4da94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnStub implements Stub +{ + private readonly mixed $value; + + public function __construct(mixed $value) + { + $this->value = $value; + } + + public function invoke(Invocation $invocation): mixed + { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php new file mode 100644 index 000000000..b1b62c5fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use function array_pop; +use function count; +use function is_array; +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReturnValueMap implements Stub +{ + private readonly array $valueMap; + + public function __construct(array $valueMap) + { + $this->valueMap = $valueMap; + } + + public function invoke(Invocation $invocation): mixed + { + $parameterCount = count($invocation->parameters()); + + foreach ($this->valueMap as $map) { + if (!is_array($map) || $parameterCount !== (count($map) - 1)) { + continue; + } + + $return = array_pop($map); + + if ($invocation->parameters() === $map) { + return $return; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php new file mode 100644 index 000000000..46d9e53a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Stub +{ + /** + * Fakes the processing of the invocation $invocation by returning a + * specific value. + */ + public function invoke(Invocation $invocation): mixed; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Reorderable.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Reorderable.php new file mode 100644 index 000000000..cc035d962 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Reorderable.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Reorderable +{ + public function sortId(): string; + + /** + * @psalm-return list + */ + public function provides(): array; + + /** + * @psalm-return list + */ + public function requires(): array; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php new file mode 100644 index 000000000..122c31b56 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/SelfDescribing.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface SelfDescribing +{ + /** + * Returns a string representation of the object. + */ + public function toString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Test.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Test.php new file mode 100644 index 000000000..b3e862f7c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/Test.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use Countable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Test extends Countable +{ + public function run(): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestBuilder.php new file mode 100644 index 000000000..9bf77b31f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestBuilder.php @@ -0,0 +1,282 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function assert; +use PHPUnit\Metadata\Api\DataProvider; +use PHPUnit\Metadata\Api\Groups; +use PHPUnit\Metadata\Api\Requirements; +use PHPUnit\Metadata\BackupGlobals; +use PHPUnit\Metadata\BackupStaticProperties; +use PHPUnit\Metadata\ExcludeGlobalVariableFromBackup; +use PHPUnit\Metadata\ExcludeStaticPropertyFromBackup; +use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; +use PHPUnit\Metadata\PreserveGlobalState; +use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; +use ReflectionClass; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestBuilder +{ + /** + * @psalm-param non-empty-string $methodName + * + * @throws InvalidDataProviderException + */ + public function build(ReflectionClass $theClass, string $methodName): Test + { + $className = $theClass->getName(); + + $data = null; + + if ($this->requirementsSatisfied($className, $methodName)) { + $data = (new DataProvider)->providedData($className, $methodName); + } + + if ($data !== null) { + return $this->buildDataProviderTestSuite( + $methodName, + $className, + $data, + $this->shouldTestMethodBeRunInSeparateProcess($className, $methodName), + $this->shouldGlobalStateBePreserved($className, $methodName), + $this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className), + $this->backupSettings($className, $methodName), + ); + } + + $test = new $className($methodName); + + assert($test instanceof TestCase); + + $this->configureTestCase( + $test, + $this->shouldTestMethodBeRunInSeparateProcess($className, $methodName), + $this->shouldGlobalStateBePreserved($className, $methodName), + $this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className), + $this->backupSettings($className, $methodName), + ); + + return $test; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * @psalm-param array{backupGlobals: ?bool, backupGlobalsExcludeList: list, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array>} $backupSettings + */ + private function buildDataProviderTestSuite(string $methodName, string $className, array $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings): DataProviderTestSuite + { + $dataProviderTestSuite = DataProviderTestSuite::empty( + $className . '::' . $methodName, + ); + + $groups = (new Groups)->groups($className, $methodName); + + foreach ($data as $_dataName => $_data) { + $_test = new $className($methodName); + + assert($_test instanceof TestCase); + + $_test->setData($_dataName, $_data); + + $this->configureTestCase( + $_test, + $runTestInSeparateProcess, + $preserveGlobalState, + $runClassInSeparateProcess, + $backupSettings, + ); + + $dataProviderTestSuite->addTest($_test, $groups); + } + + return $dataProviderTestSuite; + } + + /** + * @psalm-param array{backupGlobals: ?bool, backupGlobalsExcludeList: list, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array>} $backupSettings + */ + private function configureTestCase(TestCase $test, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings): void + { + if ($runTestInSeparateProcess) { + $test->setRunTestInSeparateProcess(true); + } + + if ($runClassInSeparateProcess) { + $test->setRunClassInSeparateProcess(true); + } + + if ($preserveGlobalState !== null) { + $test->setPreserveGlobalState($preserveGlobalState); + } + + if ($backupSettings['backupGlobals'] !== null) { + $test->setBackupGlobals($backupSettings['backupGlobals']); + } else { + $test->setBackupGlobals(ConfigurationRegistry::get()->backupGlobals()); + } + + $test->setBackupGlobalsExcludeList($backupSettings['backupGlobalsExcludeList']); + + if ($backupSettings['backupStaticProperties'] !== null) { + $test->setBackupStaticProperties($backupSettings['backupStaticProperties']); + } else { + $test->setBackupStaticProperties(ConfigurationRegistry::get()->backupStaticProperties()); + } + + $test->setBackupStaticPropertiesExcludeList($backupSettings['backupStaticPropertiesExcludeList']); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return array{backupGlobals: ?bool, backupGlobalsExcludeList: list, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array>} + */ + private function backupSettings(string $className, string $methodName): array + { + $metadataForClass = MetadataRegistry::parser()->forClass($className); + $metadataForMethod = MetadataRegistry::parser()->forMethod($className, $methodName); + $metadataForClassAndMethod = MetadataRegistry::parser()->forClassAndMethod($className, $methodName); + + $backupGlobals = null; + $backupGlobalsExcludeList = []; + + if ($metadataForMethod->isBackupGlobals()->isNotEmpty()) { + $metadata = $metadataForMethod->isBackupGlobals()->asArray()[0]; + + assert($metadata instanceof BackupGlobals); + + if ($metadata->enabled()) { + $backupGlobals = true; + } + } elseif ($metadataForClass->isBackupGlobals()->isNotEmpty()) { + $metadata = $metadataForClass->isBackupGlobals()->asArray()[0]; + + assert($metadata instanceof BackupGlobals); + + if ($metadata->enabled()) { + $backupGlobals = true; + } + } + + foreach ($metadataForClassAndMethod->isExcludeGlobalVariableFromBackup() as $metadata) { + assert($metadata instanceof ExcludeGlobalVariableFromBackup); + + $backupGlobalsExcludeList[] = $metadata->globalVariableName(); + } + + $backupStaticProperties = null; + $backupStaticPropertiesExcludeList = []; + + if ($metadataForMethod->isBackupStaticProperties()->isNotEmpty()) { + $metadata = $metadataForMethod->isBackupStaticProperties()->asArray()[0]; + + assert($metadata instanceof BackupStaticProperties); + + if ($metadata->enabled()) { + $backupStaticProperties = true; + } + } elseif ($metadataForClass->isBackupStaticProperties()->isNotEmpty()) { + $metadata = $metadataForClass->isBackupStaticProperties()->asArray()[0]; + + assert($metadata instanceof BackupStaticProperties); + + if ($metadata->enabled()) { + $backupStaticProperties = true; + } + } + + foreach ($metadataForClassAndMethod->isExcludeStaticPropertyFromBackup() as $metadata) { + assert($metadata instanceof ExcludeStaticPropertyFromBackup); + + if (!isset($backupStaticPropertiesExcludeList[$metadata->className()])) { + $backupStaticPropertiesExcludeList[$metadata->className()] = []; + } + + $backupStaticPropertiesExcludeList[$metadata->className()][] = $metadata->propertyName(); + } + + return [ + 'backupGlobals' => $backupGlobals, + 'backupGlobalsExcludeList' => $backupGlobalsExcludeList, + 'backupStaticProperties' => $backupStaticProperties, + 'backupStaticPropertiesExcludeList' => $backupStaticPropertiesExcludeList, + ]; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + private function shouldGlobalStateBePreserved(string $className, string $methodName): ?bool + { + $metadataForMethod = MetadataRegistry::parser()->forMethod($className, $methodName); + + if ($metadataForMethod->isPreserveGlobalState()->isNotEmpty()) { + $metadata = $metadataForMethod->isPreserveGlobalState()->asArray()[0]; + + assert($metadata instanceof PreserveGlobalState); + + return $metadata->enabled(); + } + + $metadataForClass = MetadataRegistry::parser()->forClass($className); + + if ($metadataForClass->isPreserveGlobalState()->isNotEmpty()) { + $metadata = $metadataForClass->isPreserveGlobalState()->asArray()[0]; + + assert($metadata instanceof PreserveGlobalState); + + return $metadata->enabled(); + } + + return null; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + private function shouldTestMethodBeRunInSeparateProcess(string $className, string $methodName): bool + { + if (MetadataRegistry::parser()->forClass($className)->isRunTestsInSeparateProcesses()->isNotEmpty()) { + return true; + } + + if (MetadataRegistry::parser()->forMethod($className, $methodName)->isRunInSeparateProcess()->isNotEmpty()) { + return true; + } + + return false; + } + + /** + * @psalm-param class-string $className + */ + private function shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess(string $className): bool + { + return MetadataRegistry::parser()->forClass($className)->isRunClassInSeparateProcess()->isNotEmpty(); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + private function requirementsSatisfied(string $className, string $methodName): bool + { + return (new Requirements)->requirementsNotSatisfiedFor($className, $methodName) === []; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestCase.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestCase.php new file mode 100644 index 000000000..06dcd0554 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestCase.php @@ -0,0 +1,2387 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const LC_ALL; +use const LC_COLLATE; +use const LC_CTYPE; +use const LC_MONETARY; +use const LC_NUMERIC; +use const LC_TIME; +use const PATHINFO_FILENAME; +use const PHP_EOL; +use const PHP_URL_PATH; +use function array_is_list; +use function array_keys; +use function array_map; +use function array_merge; +use function array_values; +use function assert; +use function basename; +use function chdir; +use function class_exists; +use function clearstatcache; +use function count; +use function defined; +use function explode; +use function getcwd; +use function implode; +use function in_array; +use function ini_set; +use function is_array; +use function is_callable; +use function is_int; +use function is_object; +use function is_string; +use function libxml_clear_errors; +use function method_exists; +use function ob_end_clean; +use function ob_get_clean; +use function ob_get_contents; +use function ob_get_level; +use function ob_start; +use function parse_url; +use function pathinfo; +use function preg_replace; +use function setlocale; +use function sprintf; +use function str_contains; +use function trim; +use AssertionError; +use DeepCopy\DeepCopy; +use PHPUnit\Event; +use PHPUnit\Event\NoPreviousThrowableException; +use PHPUnit\Event\RuntimeException; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint; +use PHPUnit\Framework\Constraint\ExceptionCode; +use PHPUnit\Framework\Constraint\ExceptionMessageIsOrContains; +use PHPUnit\Framework\Constraint\ExceptionMessageMatchesRegularExpression; +use PHPUnit\Framework\MockObject\Exception as MockObjectException; +use PHPUnit\Framework\MockObject\Generator\Generator as MockGenerator; +use PHPUnit\Framework\MockObject\MockBuilder; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\MockObjectInternal; +use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher; +use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; +use PHPUnit\Framework\MockObject\Stub; +use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; +use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; +use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; +use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; +use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; +use PHPUnit\Framework\MockObject\Stub\ReturnStub; +use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; +use PHPUnit\Framework\TestSize\TestSize; +use PHPUnit\Framework\TestStatus\TestStatus; +use PHPUnit\Metadata\Api\Groups; +use PHPUnit\Metadata\Api\HookMethods; +use PHPUnit\Metadata\Api\Requirements; +use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; +use PHPUnit\TestRunner\TestResult\PassedTests; +use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; +use PHPUnit\Util\Cloner; +use PHPUnit\Util\Test as TestUtil; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; +use ReflectionObject; +use ReflectionParameter; +use SebastianBergmann\CodeCoverage\StaticAnalysisCacheNotConfiguredException; +use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; +use SebastianBergmann\Diff\Differ; +use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; +use SebastianBergmann\Exporter\Exporter; +use SebastianBergmann\GlobalState\ExcludeList as GlobalStateExcludeList; +use SebastianBergmann\GlobalState\Restorer; +use SebastianBergmann\GlobalState\Snapshot; +use SebastianBergmann\Invoker\TimeoutException; +use SebastianBergmann\ObjectEnumerator\Enumerator; +use SebastianBergmann\RecursionContext\Context; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class TestCase extends Assert implements Reorderable, SelfDescribing, Test +{ + private const LOCALE_CATEGORIES = [LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME]; + private ?bool $backupGlobals = null; + + /** + * @psalm-var list + */ + private array $backupGlobalsExcludeList = []; + private ?bool $backupStaticProperties = null; + + /** + * @psalm-var array> + */ + private array $backupStaticPropertiesExcludeList = []; + private ?Snapshot $snapshot = null; + private ?bool $runClassInSeparateProcess = null; + private ?bool $runTestInSeparateProcess = null; + private bool $preserveGlobalState = false; + private bool $inIsolation = false; + private ?string $expectedException = null; + private ?string $expectedExceptionMessage = null; + private ?string $expectedExceptionMessageRegExp = null; + private null|int|string $expectedExceptionCode = null; + + /** + * @psalm-var list + */ + private array $providedTests = []; + private array $data = []; + private int|string $dataName = ''; + + /** + * @psalm-var non-empty-string + */ + private string $name; + + /** + * @psalm-var list + */ + private array $groups = []; + + /** + * @psalm-var list + */ + private array $dependencies = []; + private array $dependencyInput = []; + + /** + * @psalm-var array + */ + private array $iniSettings = []; + private array $locale = []; + + /** + * @psalm-var list + */ + private array $mockObjects = []; + private bool $registerMockObjectsFromTestArgumentsRecursively = false; + private TestStatus $status; + private int $numberOfAssertionsPerformed = 0; + private mixed $testResult = null; + private string $output = ''; + private ?string $outputExpectedRegex = null; + private ?string $outputExpectedString = null; + private bool $outputBufferingActive = false; + private int $outputBufferingLevel; + private bool $outputRetrievedForAssertion = false; + private bool $doesNotPerformAssertions = false; + + /** + * @psalm-var list + */ + private array $customComparators = []; + private ?Event\Code\TestMethod $testValueObjectForEvents = null; + private bool $wasPrepared = false; + + /** + * @psalm-var array + */ + private array $failureTypes = []; + + /** + * Returns a matcher that matches when the method is executed + * zero or more times. + */ + final public static function any(): AnyInvokedCountMatcher + { + return new AnyInvokedCountMatcher; + } + + /** + * Returns a matcher that matches when the method is never executed. + */ + final public static function never(): InvokedCountMatcher + { + return new InvokedCountMatcher(0); + } + + /** + * Returns a matcher that matches when the method is executed + * at least N times. + */ + final public static function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher + { + return new InvokedAtLeastCountMatcher( + $requiredInvocations, + ); + } + + /** + * Returns a matcher that matches when the method is executed at least once. + */ + final public static function atLeastOnce(): InvokedAtLeastOnceMatcher + { + return new InvokedAtLeastOnceMatcher; + } + + /** + * Returns a matcher that matches when the method is executed exactly once. + */ + final public static function once(): InvokedCountMatcher + { + return new InvokedCountMatcher(1); + } + + /** + * Returns a matcher that matches when the method is executed + * exactly $count times. + */ + final public static function exactly(int $count): InvokedCountMatcher + { + return new InvokedCountMatcher($count); + } + + /** + * Returns a matcher that matches when the method is executed + * at most N times. + */ + final public static function atMost(int $allowedInvocations): InvokedAtMostCountMatcher + { + return new InvokedAtMostCountMatcher($allowedInvocations); + } + + /** + * @deprecated Use $double->willReturn() instead of $double->will($this->returnValue()) + * @see https://github.com/sebastianbergmann/phpunit/issues/5423 + * + * @codeCoverageIgnore + */ + final public static function returnValue(mixed $value): ReturnStub + { + return new ReturnStub($value); + } + + /** + * @deprecated Use $double->willReturnMap() instead of $double->will($this->returnValueMap()) + * @see https://github.com/sebastianbergmann/phpunit/issues/5423 + * + * @codeCoverageIgnore + */ + final public static function returnValueMap(array $valueMap): ReturnValueMapStub + { + return new ReturnValueMapStub($valueMap); + } + + /** + * @deprecated Use $double->willReturnArgument() instead of $double->will($this->returnArgument()) + * @see https://github.com/sebastianbergmann/phpunit/issues/5423 + * + * @codeCoverageIgnore + */ + final public static function returnArgument(int $argumentIndex): ReturnArgumentStub + { + return new ReturnArgumentStub($argumentIndex); + } + + /** + * @deprecated Use $double->willReturnCallback() instead of $double->will($this->returnCallback()) + * @see https://github.com/sebastianbergmann/phpunit/issues/5423 + * + * @codeCoverageIgnore + */ + final public static function returnCallback(callable $callback): ReturnCallbackStub + { + return new ReturnCallbackStub($callback); + } + + /** + * @deprecated Use $double->willReturnSelf() instead of $double->will($this->returnSelf()) + * @see https://github.com/sebastianbergmann/phpunit/issues/5423 + * + * @codeCoverageIgnore + */ + final public static function returnSelf(): ReturnSelfStub + { + return new ReturnSelfStub; + } + + final public static function throwException(Throwable $exception): ExceptionStub + { + return new ExceptionStub($exception); + } + + /** + * @deprecated Use $double->willReturn() instead of $double->will($this->onConsecutiveCalls()) + * @see https://github.com/sebastianbergmann/phpunit/issues/5423 + * @see https://github.com/sebastianbergmann/phpunit/issues/5425 + * + * @codeCoverageIgnore + */ + final public static function onConsecutiveCalls(mixed ...$arguments): ConsecutiveCallsStub + { + return new ConsecutiveCallsStub($arguments); + } + + /** + * @psalm-param non-empty-string $name + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function __construct(string $name) + { + $this->setName($name); + + $this->status = TestStatus::unknown(); + } + + /** + * This method is called before the first test of this test class is run. + * + * @codeCoverageIgnore + */ + public static function setUpBeforeClass(): void + { + } + + /** + * This method is called after the last test of this test class is run. + * + * @codeCoverageIgnore + */ + public static function tearDownAfterClass(): void + { + } + + /** + * This method is called before each test. + * + * @codeCoverageIgnore + */ + protected function setUp(): void + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called between setUp() and test. + * + * @codeCoverageIgnore + */ + protected function assertPreConditions(): void + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called between test and tearDown(). + * + * @codeCoverageIgnore + */ + protected function assertPostConditions(): void + { + } + + /** + * This method is called after each test. + * + * @codeCoverageIgnore + */ + protected function tearDown(): void + { + } + + /** + * Returns a string representation of the test case. + * + * @throws Exception + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function toString(): string + { + $buffer = sprintf( + '%s::%s', + (new ReflectionClass($this))->getName(), + $this->name, + ); + + return $buffer . $this->dataSetAsStringWithData(); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function count(): int + { + return 1; + } + + final public function getActualOutputForAssertion(): string + { + $this->outputRetrievedForAssertion = true; + + return $this->output(); + } + + final public function expectOutputRegex(string $expectedRegex): void + { + $this->outputExpectedRegex = $expectedRegex; + } + + final public function expectOutputString(string $expectedString): void + { + $this->outputExpectedString = $expectedString; + } + + /** + * @psalm-param class-string $exception + */ + final public function expectException(string $exception): void + { + $this->expectedException = $exception; + } + + final public function expectExceptionCode(int|string $code): void + { + $this->expectedExceptionCode = $code; + } + + final public function expectExceptionMessage(string $message): void + { + $this->expectedExceptionMessage = $message; + } + + final public function expectExceptionMessageMatches(string $regularExpression): void + { + $this->expectedExceptionMessageRegExp = $regularExpression; + } + + /** + * Sets up an expectation for an exception to be raised by the code under test. + * Information for expected exception class, expected exception message, and + * expected exception code are retrieved from a given Exception object. + */ + final public function expectExceptionObject(\Exception $exception): void + { + $this->expectException($exception::class); + $this->expectExceptionMessage($exception->getMessage()); + $this->expectExceptionCode($exception->getCode()); + } + + final public function expectNotToPerformAssertions(): void + { + $this->doesNotPerformAssertions = true; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function status(): TestStatus + { + return $this->status; + } + + /** + * @throws \PHPUnit\Runner\Exception + * @throws \PHPUnit\Util\Exception + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\Template\InvalidArgumentException + * @throws CodeCoverageException + * @throws Exception + * @throws MoreThanOneDataSetFromDataProviderException + * @throws NoPreviousThrowableException + * @throws ProcessIsolationException + * @throws StaticAnalysisCacheNotConfiguredException + * @throws UnintentionallyCoveredCodeException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function run(): void + { + if (!$this->handleDependencies()) { + return; + } + + if (!$this->shouldRunInSeparateProcess() || $this->requirementsNotSatisfied()) { + (new TestRunner)->run($this); + } else { + (new TestRunner)->runInSeparateProcess( + $this, + $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess, + $this->preserveGlobalState, + ); + } + } + + /** + * Returns a builder object to create mock objects using a fluent interface. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $className + * + * @psalm-return MockBuilder + */ + final public function getMockBuilder(string $className): MockBuilder + { + return new MockBuilder($this, $className); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function groups(): array + { + return $this->groups; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setGroups(array $groups): void + { + $this->groups = $groups; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function nameWithDataSet(): string + { + return $this->name . $this->dataSetAsString(); + } + + /** + * @psalm-return non-empty-string + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function name(): string + { + return $this->name; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function size(): TestSize + { + return (new Groups)->size( + static::class, + $this->name, + ); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function hasUnexpectedOutput(): bool + { + if ($this->output === '') { + return false; + } + + if ($this->expectsOutput()) { + return false; + } + + return true; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function output(): string + { + if (!$this->outputBufferingActive) { + return $this->output; + } + + return (string) ob_get_contents(); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function doesNotPerformAssertions(): bool + { + return $this->doesNotPerformAssertions; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function expectsOutput(): bool + { + return $this->hasExpectationOnOutput() || $this->outputRetrievedForAssertion; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + * + * @codeCoverageIgnore + */ + final public function registerMockObjectsFromTestArgumentsRecursively(): void + { + $this->registerMockObjectsFromTestArgumentsRecursively = true; + } + + /** + * @throws Throwable + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function runBare(): void + { + $emitter = Event\Facade::emitter(); + + $emitter->testPreparationStarted( + $this->valueObjectForEvents(), + ); + + $this->snapshotGlobalState(); + $this->startOutputBuffering(); + clearstatcache(); + + $hookMethods = (new HookMethods)->hookMethods(static::class); + $hasMetRequirements = false; + $this->numberOfAssertionsPerformed = 0; + $currentWorkingDirectory = getcwd(); + + try { + $this->checkRequirements(); + $hasMetRequirements = true; + + if ($this->inIsolation) { + // @codeCoverageIgnoreStart + $this->invokeBeforeClassHookMethods($hookMethods, $emitter); + // @codeCoverageIgnoreEnd + } + + if (method_exists(static::class, $this->name) && + MetadataRegistry::parser()->forClassAndMethod(static::class, $this->name)->isDoesNotPerformAssertions()->isNotEmpty()) { + $this->doesNotPerformAssertions = true; + } + + $this->invokeBeforeTestHookMethods($hookMethods, $emitter); + $this->invokePreConditionHookMethods($hookMethods, $emitter); + + $emitter->testPrepared( + $this->valueObjectForEvents(), + ); + + $this->wasPrepared = true; + $this->testResult = $this->runTest(); + + $this->verifyMockObjects(); + $this->invokePostConditionHookMethods($hookMethods, $emitter); + + $this->status = TestStatus::success(); + } catch (IncompleteTest $e) { + $this->status = TestStatus::incomplete($e->getMessage()); + + $emitter->testMarkedAsIncomplete( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($e), + ); + } catch (SkippedTest $e) { + $this->status = TestStatus::skipped($e->getMessage()); + + $emitter->testSkipped( + $this->valueObjectForEvents(), + $e->getMessage(), + ); + } catch (AssertionError|AssertionFailedError $e) { + if (!$this->wasPrepared) { + $this->wasPrepared = true; + + $emitter->testPreparationFailed( + $this->valueObjectForEvents(), + ); + } + + $this->status = TestStatus::failure($e->getMessage()); + + $emitter->testFailed( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($e), + Event\Code\ComparisonFailureBuilder::from($e), + ); + } catch (TimeoutException $e) { + $this->status = TestStatus::risky($e->getMessage()); + } catch (Throwable $_e) { + if ($this->isRegisteredFailure($_e)) { + $this->status = TestStatus::failure($_e->getMessage()); + + $emitter->testFailed( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($_e), + null, + ); + } else { + $e = $this->transformException($_e); + + $this->status = TestStatus::error($e->getMessage()); + + $emitter->testErrored( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($e), + ); + } + } + + $outputBufferingStopped = false; + + if (!isset($e) && + $this->hasExpectationOnOutput() && + $this->stopOutputBuffering()) { + $outputBufferingStopped = true; + + $this->performAssertionsOnOutput(); + } + + if ($this->status->isSuccess()) { + $emitter->testPassed( + $this->valueObjectForEvents(), + ); + + if (!$this->usesDataProvider()) { + PassedTests::instance()->testMethodPassed( + $this->valueObjectForEvents(), + $this->testResult, + ); + } + } + + try { + $this->mockObjects = []; + } catch (Throwable $t) { + Event\Facade::emitter()->testErrored( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($t), + ); + } + + // Tear down the fixture. An exception raised in tearDown() will be + // caught and passed on when no exception was raised before. + try { + if ($hasMetRequirements) { + $this->invokeAfterTestHookMethods($hookMethods, $emitter); + + if ($this->inIsolation) { + // @codeCoverageIgnoreStart + $this->invokeAfterClassHookMethods($hookMethods, $emitter); + // @codeCoverageIgnoreEnd + } + } + } catch (AssertionError|AssertionFailedError $e) { + $this->status = TestStatus::failure($e->getMessage()); + + $emitter->testFailed( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($e), + Event\Code\ComparisonFailureBuilder::from($e), + ); + } catch (Throwable $exceptionRaisedDuringTearDown) { + if (!isset($e)) { + $this->status = TestStatus::error($exceptionRaisedDuringTearDown->getMessage()); + $e = $exceptionRaisedDuringTearDown; + + $emitter->testErrored( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($exceptionRaisedDuringTearDown), + ); + } + } + + if (!$outputBufferingStopped) { + $this->stopOutputBuffering(); + } + + clearstatcache(); + + if ($currentWorkingDirectory !== getcwd()) { + chdir($currentWorkingDirectory); + } + + $this->restoreGlobalState(); + $this->unregisterCustomComparators(); + $this->cleanupIniSettings(); + $this->cleanupLocaleSettings(); + libxml_clear_errors(); + + $this->testValueObjectForEvents = null; + + if (isset($e)) { + $this->onNotSuccessfulTest($e); + } + } + + /** + * @psalm-param non-empty-string $name + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setName(string $name): void + { + $this->name = $name; + + if (is_callable($this->sortId(), true)) { + $this->providedTests = [new ExecutionOrderDependency($this->sortId())]; + } + } + + /** + * @psalm-param list $dependencies + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setDependencies(array $dependencies): void + { + $this->dependencies = $dependencies; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ + final public function setDependencyInput(array $dependencyInput): void + { + $this->dependencyInput = $dependencyInput; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function dependencyInput(): array + { + return $this->dependencyInput; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function hasDependencyInput(): bool + { + return !empty($this->dependencyInput); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setBackupGlobals(bool $backupGlobals): void + { + $this->backupGlobals = $backupGlobals; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setBackupGlobalsExcludeList(array $backupGlobalsExcludeList): void + { + $this->backupGlobalsExcludeList = $backupGlobalsExcludeList; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setBackupStaticProperties(bool $backupStaticProperties): void + { + $this->backupStaticProperties = $backupStaticProperties; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setBackupStaticPropertiesExcludeList(array $backupStaticPropertiesExcludeList): void + { + $this->backupStaticPropertiesExcludeList = $backupStaticPropertiesExcludeList; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void + { + if ($this->runTestInSeparateProcess === null) { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess): void + { + $this->runClassInSeparateProcess = $runClassInSeparateProcess; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setPreserveGlobalState(bool $preserveGlobalState): void + { + $this->preserveGlobalState = $preserveGlobalState; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ + final public function setInIsolation(bool $inIsolation): void + { + $this->inIsolation = $inIsolation; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ + final public function result(): mixed + { + return $this->testResult; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setResult(mixed $result): void + { + $this->testResult = $result; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function registerMockObject(MockObject $mockObject): void + { + assert($mockObject instanceof MockObjectInternal); + + $this->mockObjects[] = $mockObject; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function addToAssertionCount(int $count): void + { + $this->numberOfAssertionsPerformed += $count; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function numberOfAssertionsPerformed(): int + { + return $this->numberOfAssertionsPerformed; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function usesDataProvider(): bool + { + return !empty($this->data); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function dataName(): int|string + { + return $this->dataName; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function dataSetAsString(): string + { + $buffer = ''; + + if (!empty($this->data)) { + if (is_int($this->dataName)) { + $buffer .= sprintf(' with data set #%d', $this->dataName); + } else { + $buffer .= sprintf(' with data set "%s"', $this->dataName); + } + } + + return $buffer; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function dataSetAsStringWithData(): string + { + if (empty($this->data)) { + return ''; + } + + return $this->dataSetAsString() . sprintf( + ' (%s)', + (new Exporter)->shortenedRecursiveExport($this->data), + ); + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function providedData(): array + { + return $this->data; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function sortId(): string + { + $id = $this->name; + + if (!str_contains($id, '::')) { + $id = static::class . '::' . $id; + } + + if ($this->usesDataProvider()) { + $id .= $this->dataSetAsString(); + } + + return $id; + } + + /** + * @psalm-return list + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function provides(): array + { + return $this->providedTests; + } + + /** + * @psalm-return list + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function requires(): array + { + return $this->dependencies; + } + + /** + * @throws RuntimeException + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function setData(int|string $dataName, array $data): void + { + $this->dataName = $dataName; + $this->data = $data; + + if (array_is_list($data)) { + return; + } + + try { + $reflector = new ReflectionMethod($this, $this->name); + $parameters = array_map(static fn (ReflectionParameter $parameter) => $parameter->name, $reflector->getParameters()); + + foreach (array_keys($data) as $parameter) { + if (is_string($parameter) && !in_array($parameter, $parameters, true)) { + Event\Facade::emitter()->testTriggeredPhpunitDeprecation( + $this->valueObjectForEvents(), + sprintf( + 'Providing invalid named argument $%s for method %s::%s() is deprecated and will not be supported in PHPUnit 11.0.', + $parameter, + $this::class, + $this->name, + ), + ); + } + } + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + * + * @throws MoreThanOneDataSetFromDataProviderException + */ + final public function valueObjectForEvents(): Event\Code\TestMethod + { + if ($this->testValueObjectForEvents !== null) { + return $this->testValueObjectForEvents; + } + + $this->testValueObjectForEvents = Event\Code\TestMethodBuilder::fromTestCase($this); + + return $this->testValueObjectForEvents; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + final public function wasPrepared(): bool + { + return $this->wasPrepared; + } + + final protected function registerComparator(Comparator $comparator): void + { + ComparatorFactory::getInstance()->register($comparator); + + Event\Facade::emitter()->testRegisteredComparator($comparator::class); + + $this->customComparators[] = $comparator; + } + + /** + * @psalm-param class-string $classOrInterface + */ + final protected function registerFailureType(string $classOrInterface): void + { + $this->failureTypes[$classOrInterface] = true; + } + + /** + * @throws AssertionFailedError + * @throws Exception + * @throws ExpectationFailedException + * @throws Throwable + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + protected function runTest(): mixed + { + $testArguments = array_merge($this->data, $this->dependencyInput); + + $this->registerMockObjectsFromTestArguments($testArguments); + + try { + $testResult = $this->{$this->name}(...array_values($testArguments)); + } catch (Throwable $exception) { + if (!$this->shouldExceptionExpectationsBeVerified($exception)) { + throw $exception; + } + + $this->verifyExceptionExpectations($exception); + + return null; + } + + $this->expectedExceptionWasNotRaised(); + + return $testResult; + } + + /** + * This method is a wrapper for the ini_set() function that automatically + * resets the modified php.ini setting to its original value after the + * test is run. + * + * @throws Exception + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5214 + * + * @codeCoverageIgnore + */ + protected function iniSet(string $varName, string $newValue): void + { + $currentValue = ini_set($varName, $newValue); + + if ($currentValue !== false) { + $this->iniSettings[$varName] = $currentValue; + } else { + throw new Exception( + sprintf( + 'INI setting "%s" could not be set to "%s".', + $varName, + $newValue, + ), + ); + } + } + + /** + * This method is a wrapper for the setlocale() function that automatically + * resets the locale to its original value after the test is run. + * + * @throws Exception + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5216 + * + * @codeCoverageIgnore + */ + protected function setLocale(mixed ...$arguments): void + { + if (count($arguments) < 2) { + throw new Exception; + } + + [$category, $locale] = $arguments; + + if (!in_array($category, self::LOCALE_CATEGORIES, true)) { + throw new Exception; + } + + if (!is_array($locale) && !is_string($locale)) { + throw new Exception; + } + + $this->locale[$category] = setlocale($category, '0'); + + $result = setlocale(...$arguments); + + if ($result === false) { + throw new Exception( + 'The locale functionality is not implemented on your platform, ' . + 'the specified locale does not exist or the category name is ' . + 'invalid.', + ); + } + } + + /** + * Creates a mock object for the specified interface or class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + * @throws NoPreviousThrowableException + */ + protected function createMock(string $originalClassName): MockObject + { + $mock = (new MockGenerator)->testDouble( + $originalClassName, + true, + callOriginalConstructor: false, + callOriginalClone: false, + cloneArguments: false, + allowMockingUnknownTypes: false, + ); + + assert($mock instanceof $originalClassName); + assert($mock instanceof MockObject); + + $this->registerMockObject($mock); + + Event\Facade::emitter()->testCreatedMockObject($originalClassName); + + return $mock; + } + + /** + * @psalm-param list $interfaces + * + * @throws MockObjectException + */ + protected function createMockForIntersectionOfInterfaces(array $interfaces): MockObject + { + $mock = (new MockGenerator)->testDoubleForInterfaceIntersection($interfaces, true); + + assert($mock instanceof MockObject); + + $this->registerMockObject($mock); + + Event\Facade::emitter()->testCreatedMockObjectForIntersectionOfInterfaces($interfaces); + + return $mock; + } + + /** + * Creates (and configures) a mock object for the specified interface or class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + * @throws NoPreviousThrowableException + */ + protected function createConfiguredMock(string $originalClassName, array $configuration): MockObject + { + $o = $this->createMock($originalClassName); + + foreach ($configuration as $method => $return) { + $o->method($method)->willReturn($return); + } + + return $o; + } + + /** + * Creates a partial mock object for the specified interface or class. + * + * @psalm-param list $methods + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + */ + protected function createPartialMock(string $originalClassName, array $methods): MockObject + { + $partialMock = $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->onlyMethods($methods) + ->getMock(); + + Event\Facade::emitter()->testCreatedPartialMockObject( + $originalClassName, + ...$methods, + ); + + return $partialMock; + } + + /** + * Creates a test proxy for the specified class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5240 + */ + protected function createTestProxy(string $originalClassName, array $constructorArguments = []): MockObject + { + $testProxy = $this->getMockBuilder($originalClassName) + ->setConstructorArgs($constructorArguments) + ->enableProxyingToOriginalMethods() + ->getMock(); + + Event\Facade::emitter()->testCreatedTestProxy( + $originalClassName, + $constructorArguments, + ); + + return $testProxy; + } + + /** + * Creates a mock object for the specified abstract class with all abstract + * methods of the class mocked. Concrete methods are not mocked by default. + * To mock concrete methods, use the 7th parameter ($mockedMethods). + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return MockObject&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5241 + */ + protected function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject + { + $mockObject = (new MockGenerator)->mockObjectForAbstractClass( + $originalClassName, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $mockedMethods, + $cloneArguments, + ); + + $this->registerMockObject($mockObject); + + Event\Facade::emitter()->testCreatedMockObjectForAbstractClass($originalClassName); + + assert($mockObject instanceof $originalClassName); + assert($mockObject instanceof MockObject); + + return $mockObject; + } + + /** + * Creates a mock object based on the given WSDL file. + * + * @throws MockObjectException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5242 + */ + protected function getMockFromWsdl(string $wsdlFile, string $originalClassName = '', string $mockClassName = '', array $methods = [], bool $callOriginalConstructor = true, array $options = []): MockObject + { + if ($originalClassName === '') { + $fileName = pathinfo(basename(parse_url($wsdlFile, PHP_URL_PATH)), PATHINFO_FILENAME); + $originalClassName = preg_replace('/\W/', '', $fileName); + } + + if (!class_exists($originalClassName)) { + eval( + (new MockGenerator)->generateClassFromWsdl( + $wsdlFile, + $originalClassName, + $methods, + $options, + ) + ); + } + + $mockObject = (new MockGenerator)->testDouble( + $originalClassName, + true, + $methods, + ['', $options], + $mockClassName, + $callOriginalConstructor, + false, + false, + ); + + Event\Facade::emitter()->testCreatedMockObjectFromWsdl( + $wsdlFile, + $originalClassName, + $mockClassName, + $methods, + $callOriginalConstructor, + $options, + ); + + assert($mockObject instanceof MockObject); + + $this->registerMockObject($mockObject); + + return $mockObject; + } + + /** + * Creates a mock object for the specified trait with all abstract methods + * of the trait mocked. Concrete methods to mock can be specified with the + * `$mockedMethods` parameter. + * + * @psalm-param trait-string $traitName + * + * @throws InvalidArgumentException + * @throws MockObjectException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 + */ + protected function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject + { + $mockObject = (new MockGenerator)->mockObjectForTrait( + $traitName, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $mockedMethods, + $cloneArguments, + ); + + $this->registerMockObject($mockObject); + + Event\Facade::emitter()->testCreatedMockObjectForTrait($traitName); + + return $mockObject; + } + + /** + * Creates an object that uses the specified trait. + * + * @psalm-param trait-string $traitName + * + * @throws MockObjectException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5244 + */ + protected function getObjectForTrait(string $traitName, array $arguments = [], string $traitClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true): object + { + return (new MockGenerator)->objectForTrait( + $traitName, + $traitClassName, + $callAutoload, + $callOriginalConstructor, + $arguments, + ); + } + + protected function transformException(Throwable $t): Throwable + { + return $t; + } + + /** + * This method is called when a test method did not execute successfully. + * + * @throws Throwable + */ + protected function onNotSuccessfulTest(Throwable $t): never + { + throw $t; + } + + /** + * @throws Throwable + */ + private function verifyMockObjects(): void + { + foreach ($this->mockObjects as $mockObject) { + if ($mockObject->__phpunit_hasMatchers()) { + $this->numberOfAssertionsPerformed++; + } + + $mockObject->__phpunit_verify( + $this->shouldInvocationMockerBeReset($mockObject), + ); + } + } + + /** + * @throws SkippedTest + */ + private function checkRequirements(): void + { + if (!$this->name || !method_exists($this, $this->name)) { + return; + } + + $missingRequirements = (new Requirements)->requirementsNotSatisfiedFor( + static::class, + $this->name, + ); + + if (!empty($missingRequirements)) { + $this->markTestSkipped(implode(PHP_EOL, $missingRequirements)); + } + } + + private function handleDependencies(): bool + { + if ([] === $this->dependencies || $this->inIsolation) { + return true; + } + + $passedTests = PassedTests::instance(); + + foreach ($this->dependencies as $dependency) { + if (!$dependency->isValid()) { + $this->markErrorForInvalidDependency(); + + return false; + } + + if ($dependency->targetIsClass()) { + $dependencyClassName = $dependency->getTargetClassName(); + + if (!class_exists($dependencyClassName)) { + $this->markErrorForInvalidDependency($dependency); + + return false; + } + + if (!$passedTests->hasTestClassPassed($dependencyClassName)) { + $this->markSkippedForMissingDependency($dependency); + + return false; + } + + continue; + } + + $dependencyTarget = $dependency->getTarget(); + + if (!$passedTests->hasTestMethodPassed($dependencyTarget)) { + if (!$this->isCallableTestMethod($dependencyTarget)) { + $this->markErrorForInvalidDependency($dependency); + } else { + $this->markSkippedForMissingDependency($dependency); + } + + return false; + } + + if ($passedTests->isGreaterThan($dependencyTarget, $this->size())) { + Event\Facade::emitter()->testConsideredRisky( + $this->valueObjectForEvents(), + 'This test depends on a test that is larger than itself', + ); + + return false; + } + + $returnValue = $passedTests->returnValue($dependencyTarget); + + if ($dependency->deepClone()) { + $deepCopy = new DeepCopy; + $deepCopy->skipUncloneable(false); + + $this->dependencyInput[$dependencyTarget] = $deepCopy->copy($returnValue); + } elseif ($dependency->shallowClone()) { + $this->dependencyInput[$dependencyTarget] = clone $returnValue; + } else { + $this->dependencyInput[$dependencyTarget] = $returnValue; + } + } + + $this->testValueObjectForEvents = null; + + return true; + } + + /** + * @throws Exception + * @throws MoreThanOneDataSetFromDataProviderException + * @throws NoPreviousThrowableException + */ + private function markErrorForInvalidDependency(?ExecutionOrderDependency $dependency = null): void + { + $message = 'This test has an invalid dependency'; + + if ($dependency !== null) { + $message = sprintf( + 'This test depends on "%s" which does not exist', + $dependency->targetIsClass() ? $dependency->getTargetClassName() : $dependency->getTarget(), + ); + } + + $exception = new InvalidDependencyException($message); + + Event\Facade::emitter()->testErrored( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($exception), + ); + + $this->status = TestStatus::error($message); + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function markSkippedForMissingDependency(ExecutionOrderDependency $dependency): void + { + $message = sprintf( + 'This test depends on "%s" to pass', + $dependency->getTarget(), + ); + + Event\Facade::emitter()->testSkipped( + $this->valueObjectForEvents(), + $message, + ); + + $this->status = TestStatus::skipped($message); + } + + private function startOutputBuffering(): void + { + ob_start(); + + $this->outputBufferingActive = true; + $this->outputBufferingLevel = ob_get_level(); + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function stopOutputBuffering(): bool + { + $bufferingLevel = ob_get_level(); + + if ($bufferingLevel !== $this->outputBufferingLevel) { + if ($bufferingLevel > $this->outputBufferingLevel) { + $message = 'Test code or tested code did not close its own output buffers'; + } else { + $message = 'Test code or tested code closed output buffers other than its own'; + } + + while (ob_get_level() >= $this->outputBufferingLevel) { + ob_end_clean(); + } + + Event\Facade::emitter()->testConsideredRisky( + $this->valueObjectForEvents(), + $message, + ); + + $this->status = TestStatus::risky($message); + + return false; + } + + $this->output = ob_get_clean(); + + $this->outputBufferingActive = false; + $this->outputBufferingLevel = ob_get_level(); + + return true; + } + + private function snapshotGlobalState(): void + { + if ($this->runTestInSeparateProcess || $this->inIsolation || + (!$this->backupGlobals && !$this->backupStaticProperties)) { + return; + } + + $snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true); + + $this->snapshot = $snapshot; + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function restoreGlobalState(): void + { + if (!$this->snapshot instanceof Snapshot) { + return; + } + + if (ConfigurationRegistry::get()->beStrictAboutChangesToGlobalState()) { + $this->compareGlobalStateSnapshots( + $this->snapshot, + $this->createGlobalStateSnapshot($this->backupGlobals === true), + ); + } + + $restorer = new Restorer; + + if ($this->backupGlobals) { + $restorer->restoreGlobalVariables($this->snapshot); + } + + if ($this->backupStaticProperties) { + $restorer->restoreStaticProperties($this->snapshot); + } + + $this->snapshot = null; + } + + private function createGlobalStateSnapshot(bool $backupGlobals): Snapshot + { + $excludeList = new GlobalStateExcludeList; + + foreach ($this->backupGlobalsExcludeList as $globalVariable) { + $excludeList->addGlobalVariable($globalVariable); + } + + if (!defined('PHPUNIT_TESTSUITE')) { + $excludeList->addClassNamePrefix('PHPUnit'); + $excludeList->addClassNamePrefix('SebastianBergmann\CodeCoverage'); + $excludeList->addClassNamePrefix('SebastianBergmann\FileIterator'); + $excludeList->addClassNamePrefix('SebastianBergmann\Invoker'); + $excludeList->addClassNamePrefix('SebastianBergmann\Template'); + $excludeList->addClassNamePrefix('SebastianBergmann\Timer'); + $excludeList->addStaticProperty(ComparatorFactory::class, 'instance'); + + foreach ($this->backupStaticPropertiesExcludeList as $class => $properties) { + foreach ($properties as $property) { + $excludeList->addStaticProperty($class, $property); + } + } + } + + return new Snapshot( + $excludeList, + $backupGlobals, + (bool) $this->backupStaticProperties, + false, + false, + false, + false, + false, + false, + false, + ); + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after): void + { + $backupGlobals = $this->backupGlobals === null || $this->backupGlobals; + + if ($backupGlobals) { + $this->compareGlobalStateSnapshotPart( + $before->globalVariables(), + $after->globalVariables(), + "--- Global variables before the test\n+++ Global variables after the test\n", + ); + + $this->compareGlobalStateSnapshotPart( + $before->superGlobalVariables(), + $after->superGlobalVariables(), + "--- Super-global variables before the test\n+++ Super-global variables after the test\n", + ); + } + + if ($this->backupStaticProperties) { + $this->compareGlobalStateSnapshotPart( + $before->staticProperties(), + $after->staticProperties(), + "--- Static properties before the test\n+++ Static properties after the test\n", + ); + } + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function compareGlobalStateSnapshotPart(array $before, array $after, string $header): void + { + if ($before != $after) { + $differ = new Differ(new UnifiedDiffOutputBuilder($header)); + $exporter = new Exporter; + + Event\Facade::emitter()->testConsideredRisky( + $this->valueObjectForEvents(), + 'This test modified global state but was not expected to do so' . PHP_EOL . + trim( + $differ->diff( + $exporter->export($before), + $exporter->export($after), + ), + ), + ); + } + } + + private function shouldInvocationMockerBeReset(MockObject $mock): bool + { + $enumerator = new Enumerator; + + if (in_array($mock, $enumerator->enumerate($this->dependencyInput), true)) { + return false; + } + + if (!is_array($this->testResult) && !is_object($this->testResult)) { + return true; + } + + return !in_array($mock, $enumerator->enumerate($this->testResult), true); + } + + /** + * @deprecated + */ + private function registerMockObjectsFromTestArguments(array $testArguments, Context $context = new Context): void + { + if ($this->registerMockObjectsFromTestArgumentsRecursively) { + foreach ((new Enumerator)->enumerate($testArguments) as $object) { + if ($object instanceof MockObject) { + $this->registerMockObject($object); + } + } + } else { + foreach ($testArguments as &$testArgument) { + if ($testArgument instanceof MockObject) { + $testArgument = Cloner::clone($testArgument); + + $this->registerMockObject($testArgument); + } elseif (is_array($testArgument) && !$context->contains($testArgument)) { + $testArgumentCopy = $testArgument; + $context->add($testArgument); + + $this->registerMockObjectsFromTestArguments( + $testArgumentCopy, + $context, + ); + } + } + } + } + + private function unregisterCustomComparators(): void + { + $factory = ComparatorFactory::getInstance(); + + foreach ($this->customComparators as $comparator) { + $factory->unregister($comparator); + } + + $this->customComparators = []; + } + + private function cleanupIniSettings(): void + { + foreach ($this->iniSettings as $varName => $oldValue) { + ini_set($varName, $oldValue); + } + + $this->iniSettings = []; + } + + private function cleanupLocaleSettings(): void + { + foreach ($this->locale as $category => $locale) { + setlocale($category, $locale); + } + + $this->locale = []; + } + + /** + * @throws Exception + */ + private function shouldExceptionExpectationsBeVerified(Throwable $throwable): bool + { + $result = false; + + if ($this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) { + $result = true; + } + + if ($throwable instanceof Exception) { + $result = false; + } + + if (is_string($this->expectedException)) { + try { + $reflector = new ReflectionClass($this->expectedException); + // @codeCoverageIgnoreStart + } catch (ReflectionException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + + if ($this->expectedException === 'PHPUnit\Framework\Exception' || + $this->expectedException === '\PHPUnit\Framework\Exception' || + $reflector->isSubclassOf(Exception::class)) { + $result = true; + } + } + + return $result; + } + + private function shouldRunInSeparateProcess(): bool + { + if ($this->inIsolation) { + return false; + } + + if ($this->runTestInSeparateProcess) { + return true; + } + + if ($this->runClassInSeparateProcess) { + return true; + } + + return ConfigurationRegistry::get()->processIsolation(); + } + + private function isCallableTestMethod(string $dependency): bool + { + [$className, $methodName] = explode('::', $dependency); + + if (!class_exists($className)) { + return false; + } + + $class = new ReflectionClass($className); + + if (!$class->isSubclassOf(__CLASS__)) { + return false; + } + + if (!$class->hasMethod($methodName)) { + return false; + } + + return TestUtil::isTestMethod( + $class->getMethod($methodName), + ); + } + + /** + * @throws Exception + * @throws ExpectationFailedException + * @throws MoreThanOneDataSetFromDataProviderException + * @throws NoPreviousThrowableException + */ + private function performAssertionsOnOutput(): void + { + try { + if ($this->outputExpectedRegex !== null) { + $this->assertMatchesRegularExpression($this->outputExpectedRegex, $this->output); + } elseif ($this->outputExpectedString !== null) { + $this->assertSame($this->outputExpectedString, $this->output); + } + } catch (ExpectationFailedException $e) { + $this->status = TestStatus::failure($e->getMessage()); + + Event\Facade::emitter()->testFailed( + $this->valueObjectForEvents(), + Event\Code\ThrowableBuilder::from($e), + Event\Code\ComparisonFailureBuilder::from($e), + ); + + throw $e; + } + } + + /** + * @throws Throwable + * + * @codeCoverageIgnore + */ + private function invokeBeforeClassHookMethods(array $hookMethods, Event\Emitter $emitter): void + { + $this->invokeHookMethods( + $hookMethods['beforeClass'], + $emitter, + 'testBeforeFirstTestMethodCalled', + 'testBeforeFirstTestMethodFinished', + ); + } + + /** + * @throws Throwable + */ + private function invokeBeforeTestHookMethods(array $hookMethods, Event\Emitter $emitter): void + { + $this->invokeHookMethods( + $hookMethods['before'], + $emitter, + 'testBeforeTestMethodCalled', + 'testBeforeTestMethodFinished', + ); + } + + /** + * @throws Throwable + */ + private function invokePreConditionHookMethods(array $hookMethods, Event\Emitter $emitter): void + { + $this->invokeHookMethods( + $hookMethods['preCondition'], + $emitter, + 'testPreConditionCalled', + 'testPreConditionFinished', + ); + } + + /** + * @throws Throwable + */ + private function invokePostConditionHookMethods(array $hookMethods, Event\Emitter $emitter): void + { + $this->invokeHookMethods( + $hookMethods['postCondition'], + $emitter, + 'testPostConditionCalled', + 'testPostConditionFinished', + ); + } + + /** + * @throws Throwable + */ + private function invokeAfterTestHookMethods(array $hookMethods, Event\Emitter $emitter): void + { + $this->invokeHookMethods( + $hookMethods['after'], + $emitter, + 'testAfterTestMethodCalled', + 'testAfterTestMethodFinished', + ); + } + + /** + * @throws Throwable + * + * @codeCoverageIgnore + */ + private function invokeAfterClassHookMethods(array $hookMethods, Event\Emitter $emitter): void + { + $this->invokeHookMethods( + $hookMethods['afterClass'], + $emitter, + 'testAfterLastTestMethodCalled', + 'testAfterLastTestMethodFinished', + ); + } + + /** + * @psalm-param list $hookMethods + * @psalm-param 'testBeforeFirstTestMethodCalled'|'testBeforeTestMethodCalled'|'testPreConditionCalled'|'testPostConditionCalled'|'testAfterTestMethodCalled'|'testAfterLastTestMethodCalled' $calledMethod + * @psalm-param 'testBeforeFirstTestMethodFinished'|'testBeforeTestMethodFinished'|'testPreConditionFinished'|'testPostConditionFinished'|'testAfterTestMethodFinished'|'testAfterLastTestMethodFinished' $finishedMethod + * + * @throws Throwable + */ + private function invokeHookMethods(array $hookMethods, Event\Emitter $emitter, string $calledMethod, string $finishedMethod): void + { + $methodsInvoked = []; + + foreach ($hookMethods as $methodName) { + if ($this->methodDoesNotExistOrIsDeclaredInTestCase($methodName)) { + continue; + } + + try { + $this->{$methodName}(); + } catch (Throwable $t) { + } + + $methodInvoked = new Event\Code\ClassMethod( + static::class, + $methodName, + ); + + $emitter->{$calledMethod}( + static::class, + $methodInvoked + ); + + $methodsInvoked[] = $methodInvoked; + + if (isset($t)) { + break; + } + } + + if (!empty($methodsInvoked)) { + $emitter->{$finishedMethod}( + static::class, + ...$methodsInvoked + ); + } + + if (isset($t)) { + throw $t; + } + } + + private function methodDoesNotExistOrIsDeclaredInTestCase(string $methodName): bool + { + $reflector = new ReflectionObject($this); + + return !$reflector->hasMethod($methodName) || + $reflector->getMethod($methodName)->getDeclaringClass()->getName() === self::class; + } + + /** + * @throws ExpectationFailedException + */ + private function verifyExceptionExpectations(\Exception|Throwable $exception): void + { + if ($this->expectedException !== null) { + $this->assertThat( + $exception, + new ExceptionConstraint( + $this->expectedException, + ), + ); + } + + if ($this->expectedExceptionMessage !== null) { + $this->assertThat( + $exception->getMessage(), + new ExceptionMessageIsOrContains( + $this->expectedExceptionMessage, + ), + ); + } + + if ($this->expectedExceptionMessageRegExp !== null) { + $this->assertThat( + $exception->getMessage(), + new ExceptionMessageMatchesRegularExpression( + $this->expectedExceptionMessageRegExp, + ), + ); + } + + if ($this->expectedExceptionCode !== null) { + $this->assertThat( + $exception->getCode(), + new ExceptionCode( + $this->expectedExceptionCode, + ), + ); + } + } + + /** + * @throws AssertionFailedError + */ + private function expectedExceptionWasNotRaised(): void + { + if ($this->expectedException !== null) { + $this->assertThat( + null, + new ExceptionConstraint($this->expectedException), + ); + } elseif ($this->expectedExceptionMessage !== null) { + $this->numberOfAssertionsPerformed++; + + throw new AssertionFailedError( + sprintf( + 'Failed asserting that exception with message "%s" is thrown', + $this->expectedExceptionMessage, + ), + ); + } elseif ($this->expectedExceptionMessageRegExp !== null) { + $this->numberOfAssertionsPerformed++; + + throw new AssertionFailedError( + sprintf( + 'Failed asserting that exception with message matching "%s" is thrown', + $this->expectedExceptionMessageRegExp, + ), + ); + } elseif ($this->expectedExceptionCode !== null) { + $this->numberOfAssertionsPerformed++; + + throw new AssertionFailedError( + sprintf( + 'Failed asserting that exception with code "%s" is thrown', + $this->expectedExceptionCode, + ), + ); + } + } + + private function isRegisteredFailure(Throwable $t): bool + { + foreach (array_keys($this->failureTypes) as $failureType) { + if ($t instanceof $failureType) { + return true; + } + } + + return false; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + private function hasExpectationOnOutput(): bool + { + return is_string($this->outputExpectedString) || is_string($this->outputExpectedRegex); + } + + private function requirementsNotSatisfied(): bool + { + return (new Requirements)->requirementsNotSatisfiedFor(static::class, $this->name) !== []; + } + + /** + * Creates a test stub for the specified interface or class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return Stub&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + * @throws NoPreviousThrowableException + */ + protected static function createStub(string $originalClassName): Stub + { + $stub = (new MockGenerator)->testDouble( + $originalClassName, + true, + callOriginalConstructor: false, + callOriginalClone: false, + cloneArguments: false, + allowMockingUnknownTypes: false, + ); + + Event\Facade::emitter()->testCreatedStub($originalClassName); + + assert($stub instanceof $originalClassName); + assert($stub instanceof Stub); + + return $stub; + } + + /** + * @psalm-param list $interfaces + * + * @throws MockObjectException + */ + protected static function createStubForIntersectionOfInterfaces(array $interfaces): Stub + { + $stub = (new MockGenerator)->testDoubleForInterfaceIntersection($interfaces, true); + + Event\Facade::emitter()->testCreatedStubForIntersectionOfInterfaces($interfaces); + + return $stub; + } + + /** + * Creates (and configures) a test stub for the specified interface or class. + * + * @psalm-template RealInstanceType of object + * + * @psalm-param class-string $originalClassName + * + * @psalm-return Stub&RealInstanceType + * + * @throws InvalidArgumentException + * @throws MockObjectException + * @throws NoPreviousThrowableException + */ + final protected static function createConfiguredStub(string $originalClassName, array $configuration): Stub + { + $o = self::createStub($originalClassName); + + foreach ($configuration as $method => $return) { + $o->method($method)->willReturn($return); + } + + return $o; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestRunner.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestRunner.php new file mode 100644 index 000000000..3e2da2541 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestRunner.php @@ -0,0 +1,472 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function assert; +use function defined; +use function error_clear_last; +use function extension_loaded; +use function get_include_path; +use function hrtime; +use function serialize; +use function sprintf; +use function sys_get_temp_dir; +use function tempnam; +use function unlink; +use function var_export; +use AssertionError; +use PHPUnit\Event; +use PHPUnit\Event\NoPreviousThrowableException; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Metadata\Api\CodeCoverage as CodeCoverageMetadataApi; +use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; +use PHPUnit\Runner\CodeCoverage; +use PHPUnit\Runner\ErrorHandler; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; +use PHPUnit\Util\GlobalState; +use PHPUnit\Util\PHP\AbstractPhpProcess; +use ReflectionClass; +use SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException; +use SebastianBergmann\CodeCoverage\InvalidArgumentException; +use SebastianBergmann\CodeCoverage\StaticAnalysisCacheNotConfiguredException; +use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; +use SebastianBergmann\Invoker\Invoker; +use SebastianBergmann\Invoker\TimeoutException; +use SebastianBergmann\Template\Template; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunner +{ + private ?bool $timeLimitCanBeEnforced = null; + private readonly Configuration $configuration; + + public function __construct() + { + $this->configuration = ConfigurationRegistry::get(); + } + + /** + * @throws \PHPUnit\Runner\Exception + * @throws CodeCoverageException + * @throws InvalidArgumentException + * @throws MoreThanOneDataSetFromDataProviderException + * @throws UnintentionallyCoveredCodeException + */ + public function run(TestCase $test): void + { + Assert::resetCount(); + + if ($this->configuration->registerMockObjectsFromTestArgumentsRecursively()) { + $test->registerMockObjectsFromTestArgumentsRecursively(); + } + + $shouldCodeCoverageBeCollected = (new CodeCoverageMetadataApi)->shouldCodeCoverageBeCollectedFor( + $test::class, + $test->name(), + ); + + $error = false; + $failure = false; + $incomplete = false; + $risky = false; + $skipped = false; + + error_clear_last(); + + if ($this->shouldErrorHandlerBeUsed($test)) { + ErrorHandler::instance()->enable(); + } + + $collectCodeCoverage = CodeCoverage::instance()->isActive() && + $shouldCodeCoverageBeCollected; + + if ($collectCodeCoverage) { + CodeCoverage::instance()->start($test); + } + + try { + if ($this->canTimeLimitBeEnforced() && + $this->shouldTimeLimitBeEnforced($test)) { + $risky = $this->runTestWithTimeout($test); + } else { + $test->runBare(); + } + } catch (AssertionFailedError $e) { + $failure = true; + + if ($e instanceof IncompleteTestError) { + $incomplete = true; + } elseif ($e instanceof SkippedTest) { + $skipped = true; + } + } catch (AssertionError $e) { + $test->addToAssertionCount(1); + + $failure = true; + $frame = $e->getTrace()[0]; + + assert(isset($frame['file'])); + assert(isset($frame['line'])); + + $e = new AssertionFailedError( + sprintf( + '%s in %s:%s', + $e->getMessage(), + $frame['file'], + $frame['line'], + ), + ); + } catch (Throwable $e) { + $error = true; + } + + $test->addToAssertionCount(Assert::getCount()); + + if ($this->configuration->reportUselessTests() && + !$test->doesNotPerformAssertions() && + $test->numberOfAssertionsPerformed() === 0) { + $risky = true; + } + + if (!$error && !$failure && !$incomplete && !$skipped && !$risky && + $this->configuration->requireCoverageMetadata() && + !$this->hasCoverageMetadata($test::class, $test->name())) { + Event\Facade::emitter()->testConsideredRisky( + $test->valueObjectForEvents(), + 'This test does not define a code coverage target but is expected to do so', + ); + + $risky = true; + } + + if ($collectCodeCoverage) { + $append = !$risky && !$incomplete && !$skipped; + $linesToBeCovered = []; + $linesToBeUsed = []; + + if ($append) { + try { + $linesToBeCovered = (new CodeCoverageMetadataApi)->linesToBeCovered( + $test::class, + $test->name(), + ); + + $linesToBeUsed = (new CodeCoverageMetadataApi)->linesToBeUsed( + $test::class, + $test->name(), + ); + } catch (InvalidCoversTargetException $cce) { + Event\Facade::emitter()->testTriggeredPhpunitWarning( + $test->valueObjectForEvents(), + $cce->getMessage(), + ); + + $append = false; + } + } + + try { + CodeCoverage::instance()->stop( + $append, + $linesToBeCovered, + $linesToBeUsed, + ); + } catch (UnintentionallyCoveredCodeException $cce) { + Event\Facade::emitter()->testConsideredRisky( + $test->valueObjectForEvents(), + 'This test executed code that is not listed as code to be covered or used:' . + PHP_EOL . + $cce->getMessage(), + ); + } catch (OriginalCodeCoverageException $cce) { + $error = true; + + $e = $e ?? $cce; + } + } + + ErrorHandler::instance()->disable(); + + if (!$error && + !$incomplete && + !$skipped && + $this->configuration->reportUselessTests() && + !$test->doesNotPerformAssertions() && + $test->numberOfAssertionsPerformed() === 0) { + Event\Facade::emitter()->testConsideredRisky( + $test->valueObjectForEvents(), + 'This test did not perform any assertions', + ); + } + + if ($test->doesNotPerformAssertions() && + $test->numberOfAssertionsPerformed() > 0) { + Event\Facade::emitter()->testConsideredRisky( + $test->valueObjectForEvents(), + sprintf( + 'This test is not expected to perform assertions but performed %d assertion%s', + $test->numberOfAssertionsPerformed(), + $test->numberOfAssertionsPerformed() > 1 ? 's' : '', + ), + ); + } + + if ($test->hasUnexpectedOutput()) { + Event\Facade::emitter()->testPrintedUnexpectedOutput($test->output()); + } + + if ($this->configuration->disallowTestOutput() && $test->hasUnexpectedOutput()) { + Event\Facade::emitter()->testConsideredRisky( + $test->valueObjectForEvents(), + sprintf( + 'This test printed output: %s', + $test->output(), + ), + ); + } + + if ($test->wasPrepared()) { + Event\Facade::emitter()->testFinished( + $test->valueObjectForEvents(), + $test->numberOfAssertionsPerformed(), + ); + } + } + + /** + * @throws \PHPUnit\Runner\Exception + * @throws \PHPUnit\Util\Exception + * @throws \SebastianBergmann\Template\InvalidArgumentException + * @throws Exception + * @throws MoreThanOneDataSetFromDataProviderException + * @throws NoPreviousThrowableException + * @throws ProcessIsolationException + * @throws StaticAnalysisCacheNotConfiguredException + */ + public function runInSeparateProcess(TestCase $test, bool $runEntireClass, bool $preserveGlobalState): void + { + $class = new ReflectionClass($test); + + if ($runEntireClass) { + $template = new Template( + __DIR__ . '/../Util/PHP/Template/TestCaseClass.tpl', + ); + } else { + $template = new Template( + __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl', + ); + } + + $bootstrap = ''; + $constants = ''; + $globals = ''; + $includedFiles = ''; + $iniSettings = ''; + + if (ConfigurationRegistry::get()->hasBootstrap()) { + $bootstrap = ConfigurationRegistry::get()->bootstrap(); + } + + if ($preserveGlobalState) { + $constants = GlobalState::getConstantsAsString(); + $globals = GlobalState::getGlobalsAsString(); + $includedFiles = GlobalState::getIncludedFilesAsString(); + $iniSettings = GlobalState::getIniSettingsAsString(); + } + + $exportObjects = Event\Facade::emitter()->exportsObjects() ? 'true' : 'false'; + $coverage = CodeCoverage::instance()->isActive() ? 'true' : 'false'; + $linesToBeIgnored = var_export(CodeCoverage::instance()->linesToBeIgnored(), true); + + if (defined('PHPUNIT_COMPOSER_INSTALL')) { + $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); + } else { + $composerAutoload = '\'\''; + } + + if (defined('__PHPUNIT_PHAR__')) { + $phar = var_export(__PHPUNIT_PHAR__, true); + } else { + $phar = '\'\''; + } + + $data = var_export(serialize($test->providedData()), true); + $dataName = var_export($test->dataName(), true); + $dependencyInput = var_export(serialize($test->dependencyInput()), true); + $includePath = var_export(get_include_path(), true); + // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC + // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences + $data = "'." . $data . ".'"; + $dataName = "'.(" . $dataName . ").'"; + $dependencyInput = "'." . $dependencyInput . ".'"; + $includePath = "'." . $includePath . ".'"; + $offset = hrtime(); + $serializedConfiguration = $this->saveConfigurationForChildProcess(); + $processResultFile = tempnam(sys_get_temp_dir(), 'phpunit_'); + + $var = [ + 'bootstrap' => $bootstrap, + 'composerAutoload' => $composerAutoload, + 'phar' => $phar, + 'filename' => $class->getFileName(), + 'className' => $class->getName(), + 'collectCodeCoverageInformation' => $coverage, + 'linesToBeIgnored' => $linesToBeIgnored, + 'data' => $data, + 'dataName' => $dataName, + 'dependencyInput' => $dependencyInput, + 'constants' => $constants, + 'globals' => $globals, + 'include_path' => $includePath, + 'included_files' => $includedFiles, + 'iniSettings' => $iniSettings, + 'name' => $test->name(), + 'offsetSeconds' => $offset[0], + 'offsetNanoseconds' => $offset[1], + 'serializedConfiguration' => $serializedConfiguration, + 'processResultFile' => $processResultFile, + 'exportObjects' => $exportObjects, + ]; + + if (!$runEntireClass) { + $var['methodName'] = $test->name(); + } + + $template->setVar($var); + + $php = AbstractPhpProcess::factory(); + $php->runTestJob($template->render(), $test, $processResultFile); + + @unlink($serializedConfiguration); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + private function hasCoverageMetadata(string $className, string $methodName): bool + { + foreach (MetadataRegistry::parser()->forClassAndMethod($className, $methodName) as $metadata) { + if ($metadata->isCovers()) { + return true; + } + + if ($metadata->isCoversClass()) { + return true; + } + + if ($metadata->isCoversFunction()) { + return true; + } + + if ($metadata->isCoversNothing()) { + return true; + } + } + + return false; + } + + private function canTimeLimitBeEnforced(): bool + { + if ($this->timeLimitCanBeEnforced !== null) { + return $this->timeLimitCanBeEnforced; + } + + $this->timeLimitCanBeEnforced = (new Invoker)->canInvokeWithTimeout(); + + return $this->timeLimitCanBeEnforced; + } + + private function shouldTimeLimitBeEnforced(TestCase $test): bool + { + if (!$this->configuration->enforceTimeLimit()) { + return false; + } + + if (!(($this->configuration->defaultTimeLimit() || $test->size()->isKnown()))) { + return false; + } + + if (extension_loaded('xdebug') && xdebug_is_debugger_active()) { + return false; + } + + return true; + } + + /** + * @throws Throwable + */ + private function runTestWithTimeout(TestCase $test): bool + { + $_timeout = $this->configuration->defaultTimeLimit(); + $testSize = $test->size(); + + if ($testSize->isSmall()) { + $_timeout = $this->configuration->timeoutForSmallTests(); + } elseif ($testSize->isMedium()) { + $_timeout = $this->configuration->timeoutForMediumTests(); + } elseif ($testSize->isLarge()) { + $_timeout = $this->configuration->timeoutForLargeTests(); + } + + try { + (new Invoker)->invoke([$test, 'runBare'], [], $_timeout); + } catch (TimeoutException) { + Event\Facade::emitter()->testConsideredRisky( + $test->valueObjectForEvents(), + sprintf( + 'This test was aborted after %d second%s', + $_timeout, + $_timeout !== 1 ? 's' : '', + ), + ); + + return true; + } + + return false; + } + + /** + * @throws ProcessIsolationException + */ + private function saveConfigurationForChildProcess(): string + { + $path = tempnam(sys_get_temp_dir(), 'phpunit_'); + + if ($path === false) { + throw new ProcessIsolationException; + } + + if (!ConfigurationRegistry::saveTo($path)) { + throw new ProcessIsolationException; + } + + return $path; + } + + private function shouldErrorHandlerBeUsed(TestCase $test): bool + { + if (MetadataRegistry::parser()->forMethod($test::class, $test->name())->isWithoutErrorHandler()->isNotEmpty()) { + return false; + } + + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Known.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Known.php new file mode 100644 index 000000000..ea8cb2933 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Known.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestSize; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +abstract class Known extends TestSize +{ + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return true; + } + + abstract public function isGreaterThan(self $other): bool; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Large.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Large.php new file mode 100644 index 000000000..833dbc064 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Large.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestSize; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Large extends Known +{ + /** + * @psalm-assert-if-true Large $this + */ + public function isLarge(): bool + { + return true; + } + + public function isGreaterThan(TestSize $other): bool + { + return !$other->isLarge(); + } + + public function asString(): string + { + return 'large'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Medium.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Medium.php new file mode 100644 index 000000000..dd934bed7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Medium.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestSize; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Medium extends Known +{ + /** + * @psalm-assert-if-true Medium $this + */ + public function isMedium(): bool + { + return true; + } + + public function isGreaterThan(TestSize $other): bool + { + return $other->isSmall(); + } + + public function asString(): string + { + return 'medium'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Small.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Small.php new file mode 100644 index 000000000..eb7250dbd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Small.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestSize; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Small extends Known +{ + /** + * @psalm-assert-if-true Small $this + */ + public function isSmall(): bool + { + return true; + } + + public function isGreaterThan(TestSize $other): bool + { + return false; + } + + public function asString(): string + { + return 'small'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/TestSize.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/TestSize.php new file mode 100644 index 000000000..82b0bb23f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/TestSize.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestSize; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +abstract class TestSize +{ + public static function unknown(): self + { + return new Unknown; + } + + public static function small(): self + { + return new Small; + } + + public static function medium(): self + { + return new Medium; + } + + public static function large(): self + { + return new Large; + } + + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Small $this + */ + public function isSmall(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Medium $this + */ + public function isMedium(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Large $this + */ + public function isLarge(): bool + { + return false; + } + + abstract public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Unknown.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Unknown.php new file mode 100644 index 000000000..5089f3f2c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSize/Unknown.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestSize; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Unknown extends TestSize +{ + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return true; + } + + public function asString(): string + { + return 'unknown'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php new file mode 100644 index 000000000..545f6aaca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Deprecation.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Deprecation extends Known +{ + /** + * @psalm-assert-if-true Deprecation $this + */ + public function isDeprecation(): bool + { + return true; + } + + public function asInt(): int + { + return 4; + } + + public function asString(): string + { + return 'deprecation'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Error.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Error.php new file mode 100644 index 000000000..8dedfdfc5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Error.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Error extends Known +{ + /** + * @psalm-assert-if-true Error $this + */ + public function isError(): bool + { + return true; + } + + public function asInt(): int + { + return 8; + } + + public function asString(): string + { + return 'error'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Failure.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Failure.php new file mode 100644 index 000000000..2568445b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Failure.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Failure extends Known +{ + /** + * @psalm-assert-if-true Failure $this + */ + public function isFailure(): bool + { + return true; + } + + public function asInt(): int + { + return 7; + } + + public function asString(): string + { + return 'failure'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php new file mode 100644 index 000000000..6b81dce93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Incomplete.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Incomplete extends Known +{ + /** + * @psalm-assert-if-true Incomplete $this + */ + public function isIncomplete(): bool + { + return true; + } + + public function asInt(): int + { + return 2; + } + + public function asString(): string + { + return 'incomplete'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Known.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Known.php new file mode 100644 index 000000000..30838d38c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Known.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Known extends TestStatus +{ + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Notice.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Notice.php new file mode 100644 index 000000000..322db6f7f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Notice.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Notice extends Known +{ + /** + * @psalm-assert-if-true Notice $this + */ + public function isNotice(): bool + { + return true; + } + + public function asInt(): int + { + return 3; + } + + public function asString(): string + { + return 'notice'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Risky.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Risky.php new file mode 100644 index 000000000..7e7db7018 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Risky.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Risky extends Known +{ + /** + * @psalm-assert-if-true Risky $this + */ + public function isRisky(): bool + { + return true; + } + + public function asInt(): int + { + return 5; + } + + public function asString(): string + { + return 'risky'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Skipped.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Skipped.php new file mode 100644 index 000000000..345aae951 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Skipped.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Skipped extends Known +{ + /** + * @psalm-assert-if-true Skipped $this + */ + public function isSkipped(): bool + { + return true; + } + + public function asInt(): int + { + return 1; + } + + public function asString(): string + { + return 'skipped'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Success.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Success.php new file mode 100644 index 000000000..973fbdf5a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Success.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Success extends Known +{ + /** + * @psalm-assert-if-true Success $this + */ + public function isSuccess(): bool + { + return true; + } + + public function asInt(): int + { + return 0; + } + + public function asString(): string + { + return 'success'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php new file mode 100644 index 000000000..444840831 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/TestStatus.php @@ -0,0 +1,195 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class TestStatus +{ + private readonly string $message; + + public static function from(int $status): self + { + return match ($status) { + 0 => self::success(), + 1 => self::skipped(), + 2 => self::incomplete(), + 3 => self::notice(), + 4 => self::deprecation(), + 5 => self::risky(), + 6 => self::warning(), + 7 => self::failure(), + 8 => self::error(), + default => self::unknown(), + }; + } + + public static function unknown(): self + { + return new Unknown; + } + + public static function success(): self + { + return new Success; + } + + public static function skipped(string $message = ''): self + { + return new Skipped($message); + } + + public static function incomplete(string $message = ''): self + { + return new Incomplete($message); + } + + public static function notice(string $message = ''): self + { + return new Notice($message); + } + + public static function deprecation(string $message = ''): self + { + return new Deprecation($message); + } + + public static function failure(string $message = ''): self + { + return new Failure($message); + } + + public static function error(string $message = ''): self + { + return new Error($message); + } + + public static function warning(string $message = ''): self + { + return new Warning($message); + } + + public static function risky(string $message = ''): self + { + return new Risky($message); + } + + private function __construct(string $message = '') + { + $this->message = $message; + } + + /** + * @psalm-assert-if-true Known $this + */ + public function isKnown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Success $this + */ + public function isSuccess(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Skipped $this + */ + public function isSkipped(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Incomplete $this + */ + public function isIncomplete(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Notice $this + */ + public function isNotice(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Deprecation $this + */ + public function isDeprecation(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Failure $this + */ + public function isFailure(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Error $this + */ + public function isError(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Warning $this + */ + public function isWarning(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Risky $this + */ + public function isRisky(): bool + { + return false; + } + + public function message(): string + { + return $this->message; + } + + public function isMoreImportantThan(self $other): bool + { + return $this->asInt() > $other->asInt(); + } + + abstract public function asInt(): int; + + abstract public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Unknown.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Unknown.php new file mode 100644 index 000000000..7a391638b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Unknown.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Unknown extends TestStatus +{ + /** + * @psalm-assert-if-true Unknown $this + */ + public function isUnknown(): bool + { + return true; + } + + public function asInt(): int + { + return -1; + } + + public function asString(): string + { + return 'unknown'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Warning.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Warning.php new file mode 100644 index 000000000..ebb05b0f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestStatus/Warning.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Warning extends Known +{ + /** + * @psalm-assert-if-true Warning $this + */ + public function isWarning(): bool + { + return true; + } + + public function asInt(): int + { + return 6; + } + + public function asString(): string + { + return 'warning'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuite.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuite.php new file mode 100644 index 000000000..42245f8ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuite.php @@ -0,0 +1,716 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use const PHP_EOL; +use function array_keys; +use function array_map; +use function array_pop; +use function array_reverse; +use function assert; +use function call_user_func; +use function class_exists; +use function count; +use function implode; +use function is_callable; +use function is_file; +use function is_subclass_of; +use function sprintf; +use function str_ends_with; +use function str_starts_with; +use function trim; +use Iterator; +use IteratorAggregate; +use PHPUnit\Event; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\NoPreviousThrowableException; +use PHPUnit\Metadata\Api\Dependencies; +use PHPUnit\Metadata\Api\Groups; +use PHPUnit\Metadata\Api\HookMethods; +use PHPUnit\Metadata\Api\Requirements; +use PHPUnit\Metadata\MetadataCollection; +use PHPUnit\Runner\Exception as RunnerException; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Runner\TestSuiteLoader; +use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; +use PHPUnit\Util\Filter; +use PHPUnit\Util\Reflection; +use PHPUnit\Util\Test as TestUtil; +use ReflectionClass; +use ReflectionMethod; +use SebastianBergmann\CodeCoverage\InvalidArgumentException; +use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; +use Throwable; + +/** + * @template-implements IteratorAggregate + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class TestSuite implements IteratorAggregate, Reorderable, SelfDescribing, Test +{ + /** + * @psalm-var non-empty-string + */ + private string $name; + + /** + * @psalm-var array> + */ + private array $groups = []; + + /** + * @psalm-var ?list + */ + private ?array $requiredTests = null; + + /** + * @psalm-var list + */ + private array $tests = []; + + /** + * @psalm-var ?list + */ + private ?array $providedTests = null; + private ?Factory $iteratorFilter = null; + private bool $wasRun = false; + + /** + * @psalm-param non-empty-string $name + */ + public static function empty(string $name): static + { + return new static($name); + } + + /** + * @psalm-param class-string $className + */ + public static function fromClassName(string $className): static + { + assert(class_exists($className)); + + $class = new ReflectionClass($className); + + return static::fromClassReflector($class); + } + + public static function fromClassReflector(ReflectionClass $class): static + { + $testSuite = new static($class->getName()); + + $constructor = $class->getConstructor(); + + if ($constructor !== null && !$constructor->isPublic()) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Class "%s" has no public constructor.', + $class->getName(), + ), + ); + + return $testSuite; + } + + foreach (Reflection::publicMethodsInTestClass($class) as $method) { + if ($method->getDeclaringClass()->getName() === Assert::class) { + continue; + } + + if ($method->getDeclaringClass()->getName() === TestCase::class) { + continue; + } + + if (!TestUtil::isTestMethod($method)) { + continue; + } + + $testSuite->addTestMethod($class, $method); + } + + if ($testSuite->isEmpty()) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'No tests found in class "%s".', + $class->getName(), + ), + ); + } + + return $testSuite; + } + + /** + * @psalm-param non-empty-string $name + */ + final private function __construct(string $name) + { + $this->name = $name; + } + + /** + * Returns a string representation of the test suite. + */ + public function toString(): string + { + return $this->name(); + } + + /** + * Adds a test to the suite. + */ + public function addTest(Test $test, array $groups = []): void + { + $class = new ReflectionClass($test); + + if ($class->isAbstract()) { + return; + } + + $this->tests[] = $test; + $this->clearCaches(); + + if ($test instanceof self && empty($groups)) { + $groups = $test->groups(); + } + + if ($this->containsOnlyVirtualGroups($groups)) { + $groups[] = 'default'; + } + + foreach ($groups as $group) { + if (!isset($this->groups[$group])) { + $this->groups[$group] = [$test]; + } else { + $this->groups[$group][] = $test; + } + } + + if ($test instanceof TestCase) { + $test->setGroups($groups); + } + } + + /** + * Adds the tests from the given class to the suite. + * + * @throws Exception + */ + public function addTestSuite(ReflectionClass $testClass): void + { + if ($testClass->isAbstract()) { + throw new Exception( + sprintf( + 'Class %s is abstract', + $testClass->getName(), + ), + ); + } + + if (!$testClass->isSubclassOf(TestCase::class)) { + throw new Exception( + sprintf( + 'Class %s is not a subclass of %s', + $testClass->getName(), + TestCase::class, + ), + ); + } + + $this->addTest(self::fromClassReflector($testClass)); + } + + /** + * Wraps both addTest() and addTestSuite + * as well as the separate import statements for the user's convenience. + * + * If the named file cannot be read or there are no new tests that can be + * added, a PHPUnit\Framework\WarningTestCase will be created instead, + * leaving the current test run untouched. + * + * @throws Exception + */ + public function addTestFile(string $filename): void + { + try { + if (str_ends_with($filename, '.phpt') && is_file($filename)) { + $this->addTest(new PhptTestCase($filename)); + } else { + $this->addTestSuite( + (new TestSuiteLoader)->load($filename), + ); + } + } catch (RunnerException $e) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + $e->getMessage(), + ); + } + } + + /** + * Wrapper for addTestFile() that adds multiple test files. + * + * @throws Exception + */ + public function addTestFiles(iterable $fileNames): void + { + foreach ($fileNames as $filename) { + $this->addTestFile((string) $filename); + } + } + + /** + * Counts the number of test cases that will be run by this test. + */ + public function count(): int + { + $numTests = 0; + + foreach ($this as $test) { + $numTests += count($test); + } + + return $numTests; + } + + public function isEmpty(): bool + { + foreach ($this as $test) { + if (count($test) !== 0) { + return false; + } + } + + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->name; + } + + /** + * Returns the test groups of the suite. + * + * @psalm-return list + */ + public function groups(): array + { + return array_map( + 'strval', + array_keys($this->groups), + ); + } + + public function groupDetails(): array + { + return $this->groups; + } + + /** + * @throws CodeCoverageException + * @throws Event\RuntimeException + * @throws Exception + * @throws InvalidArgumentException + * @throws NoPreviousThrowableException + * @throws UnintentionallyCoveredCodeException + */ + public function run(): void + { + if ($this->wasRun) { + // @codeCoverageIgnoreStart + throw new Exception('The tests aggregated by this TestSuite were already run'); + // @codeCoverageIgnoreEnd + } + + $this->wasRun = true; + + if ($this->isEmpty()) { + return; + } + + $emitter = Event\Facade::emitter(); + $testSuiteValueObjectForEvents = Event\TestSuite\TestSuiteBuilder::from($this); + + $emitter->testSuiteStarted($testSuiteValueObjectForEvents); + + if (!$this->invokeMethodsBeforeFirstTest($emitter, $testSuiteValueObjectForEvents)) { + return; + } + + /** @psalm-var list $tests */ + $tests = []; + + foreach ($this as $test) { + $tests[] = $test; + } + + $tests = array_reverse($tests); + + $this->tests = []; + $this->groups = []; + + while (($test = array_pop($tests)) !== null) { + if (TestResultFacade::shouldStop()) { + $emitter->testRunnerExecutionAborted(); + + break; + } + + $test->run(); + } + + $this->invokeMethodsAfterLastTest($emitter); + + $emitter->testSuiteFinished($testSuiteValueObjectForEvents); + } + + /** + * Returns the tests as an enumeration. + * + * @psalm-return list + */ + public function tests(): array + { + return $this->tests; + } + + /** + * Set tests of the test suite. + * + * @psalm-param list $tests + */ + public function setTests(array $tests): void + { + $this->tests = $tests; + } + + /** + * Mark the test suite as skipped. + * + * @throws SkippedTestSuiteError + */ + public function markTestSuiteSkipped(string $message = ''): never + { + throw new SkippedTestSuiteError($message); + } + + /** + * Returns an iterator for this test suite. + */ + public function getIterator(): Iterator + { + $iterator = new TestSuiteIterator($this); + + if ($this->iteratorFilter !== null) { + $iterator = $this->iteratorFilter->factory($iterator, $this); + } + + return $iterator; + } + + public function injectFilter(Factory $filter): void + { + $this->iteratorFilter = $filter; + + foreach ($this as $test) { + if ($test instanceof self) { + $test->injectFilter($filter); + } + } + } + + /** + * @psalm-return list + */ + public function provides(): array + { + if ($this->providedTests === null) { + $this->providedTests = []; + + if (is_callable($this->sortId(), true)) { + $this->providedTests[] = new ExecutionOrderDependency($this->sortId()); + } + + foreach ($this->tests as $test) { + if (!($test instanceof Reorderable)) { + continue; + } + + $this->providedTests = ExecutionOrderDependency::mergeUnique($this->providedTests, $test->provides()); + } + } + + return $this->providedTests; + } + + /** + * @psalm-return list + */ + public function requires(): array + { + if ($this->requiredTests === null) { + $this->requiredTests = []; + + foreach ($this->tests as $test) { + if (!($test instanceof Reorderable)) { + continue; + } + + $this->requiredTests = ExecutionOrderDependency::mergeUnique( + ExecutionOrderDependency::filterInvalid($this->requiredTests), + $test->requires(), + ); + } + + $this->requiredTests = ExecutionOrderDependency::diff($this->requiredTests, $this->provides()); + } + + return $this->requiredTests; + } + + public function sortId(): string + { + return $this->name() . '::class'; + } + + /** + * @psalm-assert-if-true class-string $this->name + */ + public function isForTestClass(): bool + { + return class_exists($this->name, false) && is_subclass_of($this->name, TestCase::class); + } + + /** + * @throws Event\TestData\MoreThanOneDataSetFromDataProviderException + * @throws Exception + */ + protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method): void + { + $className = $class->getName(); + $methodName = $method->getName(); + + assert(!empty($methodName)); + + try { + $test = (new TestBuilder)->build($class, $methodName); + } catch (InvalidDataProviderException $e) { + Event\Facade::emitter()->testTriggeredPhpunitError( + new TestMethod( + $className, + $methodName, + $class->getFileName(), + $method->getStartLine(), + Event\Code\TestDoxBuilder::fromClassNameAndMethodName( + $className, + $methodName, + ), + MetadataCollection::fromArray([]), + Event\TestData\TestDataCollection::fromArray([]), + ), + sprintf( + "The data provider specified for %s::%s is invalid\n%s", + $className, + $methodName, + $this->throwableToString($e), + ), + ); + + return; + } + + if ($test instanceof TestCase || $test instanceof DataProviderTestSuite) { + $test->setDependencies( + Dependencies::dependencies($class->getName(), $methodName), + ); + } + + $this->addTest( + $test, + (new Groups)->groups($class->getName(), $methodName), + ); + } + + private function clearCaches(): void + { + $this->providedTests = null; + $this->requiredTests = null; + } + + private function containsOnlyVirtualGroups(array $groups): bool + { + foreach ($groups as $group) { + if (!str_starts_with($group, '__phpunit_')) { + return false; + } + } + + return true; + } + + private function methodDoesNotExistOrIsDeclaredInTestCase(string $methodName): bool + { + $reflector = new ReflectionClass($this->name); + + return !$reflector->hasMethod($methodName) || + $reflector->getMethod($methodName)->getDeclaringClass()->getName() === TestCase::class; + } + + /** + * @throws Exception + */ + private function throwableToString(Throwable $t): string + { + $message = $t->getMessage(); + + if (empty(trim($message))) { + $message = ''; + } + + if ($t instanceof InvalidDataProviderException) { + return sprintf( + "%s\n%s", + $message, + Filter::getFilteredStacktrace($t), + ); + } + + return sprintf( + "%s: %s\n%s", + $t::class, + $message, + Filter::getFilteredStacktrace($t), + ); + } + + /** + * @throws Exception + * @throws NoPreviousThrowableException + */ + private function invokeMethodsBeforeFirstTest(Event\Emitter $emitter, Event\TestSuite\TestSuite $testSuiteValueObjectForEvents): bool + { + if (!$this->isForTestClass()) { + return true; + } + + $methodsCalledBeforeFirstTest = []; + + $beforeClassMethods = (new HookMethods)->hookMethods($this->name)['beforeClass']; + + try { + foreach ($beforeClassMethods as $beforeClassMethod) { + if ($this->methodDoesNotExistOrIsDeclaredInTestCase($beforeClassMethod)) { + continue; + } + + if ($missingRequirements = (new Requirements)->requirementsNotSatisfiedFor($this->name, $beforeClassMethod)) { + $this->markTestSuiteSkipped(implode(PHP_EOL, $missingRequirements)); + } + + $methodCalledBeforeFirstTest = new Event\Code\ClassMethod( + $this->name, + $beforeClassMethod, + ); + + $emitter->testBeforeFirstTestMethodCalled( + $this->name, + $methodCalledBeforeFirstTest, + ); + + $methodsCalledBeforeFirstTest[] = $methodCalledBeforeFirstTest; + + call_user_func([$this->name, $beforeClassMethod]); + } + } catch (SkippedTest|SkippedTestSuiteError $e) { + $emitter->testSuiteSkipped( + $testSuiteValueObjectForEvents, + $e->getMessage(), + ); + + return false; + } catch (Throwable $t) { + assert(isset($methodCalledBeforeFirstTest)); + + $emitter->testBeforeFirstTestMethodErrored( + $this->name, + $methodCalledBeforeFirstTest, + Event\Code\ThrowableBuilder::from($t), + ); + + if (!empty($methodsCalledBeforeFirstTest)) { + $emitter->testBeforeFirstTestMethodFinished( + $this->name, + ...$methodsCalledBeforeFirstTest, + ); + } + + return false; + } + + if (!empty($methodsCalledBeforeFirstTest)) { + $emitter->testBeforeFirstTestMethodFinished( + $this->name, + ...$methodsCalledBeforeFirstTest, + ); + } + + return true; + } + + private function invokeMethodsAfterLastTest(Event\Emitter $emitter): void + { + if (!$this->isForTestClass()) { + return; + } + + $methodsCalledAfterLastTest = []; + + $afterClassMethods = (new HookMethods)->hookMethods($this->name)['afterClass']; + + foreach ($afterClassMethods as $afterClassMethod) { + if ($this->methodDoesNotExistOrIsDeclaredInTestCase($afterClassMethod)) { + continue; + } + + try { + call_user_func([$this->name, $afterClassMethod]); + + $methodCalledAfterLastTest = new Event\Code\ClassMethod( + $this->name, + $afterClassMethod, + ); + + $emitter->testAfterLastTestMethodCalled( + $this->name, + $methodCalledAfterLastTest, + ); + + $methodsCalledAfterLastTest[] = $methodCalledAfterLastTest; + } catch (Throwable) { + // @todo + } + } + + if (!empty($methodsCalledAfterLastTest)) { + $emitter->testAfterLastTestMethodFinished( + $this->name, + ...$methodsCalledAfterLastTest, + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php new file mode 100644 index 000000000..8af012183 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Framework/TestSuiteIterator.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +use function assert; +use function count; +use RecursiveIterator; + +/** + * @template-implements RecursiveIterator + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteIterator implements RecursiveIterator +{ + private int $position = 0; + + /** + * @psalm-var list + */ + private readonly array $tests; + + public function __construct(TestSuite $testSuite) + { + $this->tests = $testSuite->tests(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->tests); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Test + { + return $this->tests[$this->position]; + } + + public function next(): void + { + $this->position++; + } + + /** + * @throws NoChildTestSuiteException + */ + public function getChildren(): self + { + if (!$this->hasChildren()) { + throw new NoChildTestSuiteException( + 'The current item is not a TestSuite instance and therefore does not have any children.', + ); + } + + $current = $this->current(); + + assert($current instanceof TestSuite); + + return new self($current); + } + + public function hasChildren(): bool + { + return $this->valid() && $this->current() instanceof TestSuite; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/EventLogger.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/EventLogger.php new file mode 100644 index 000000000..083502133 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/EventLogger.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging; + +use const FILE_APPEND; +use const LOCK_EX; +use const PHP_EOL; +use const PHP_OS_FAMILY; +use function file_put_contents; +use function implode; +use function preg_split; +use function str_repeat; +use function strlen; +use PHPUnit\Event\Event; +use PHPUnit\Event\Tracer\Tracer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class EventLogger implements Tracer +{ + private readonly string $path; + private readonly bool $includeTelemetryInfo; + + public function __construct(string $path, bool $includeTelemetryInfo) + { + $this->path = $path; + $this->includeTelemetryInfo = $includeTelemetryInfo; + } + + public function trace(Event $event): void + { + $telemetryInfo = $this->telemetryInfo($event); + $indentation = PHP_EOL . str_repeat(' ', strlen($telemetryInfo)); + $lines = preg_split('/\r\n|\r|\n/', $event->asString()); + + $flags = FILE_APPEND; + + if (!(PHP_OS_FAMILY === 'Windows' || PHP_OS_FAMILY === 'Darwin') || + $this->path !== 'php://stdout') { + $flags |= LOCK_EX; + } + + file_put_contents( + $this->path, + $telemetryInfo . implode($indentation, $lines) . PHP_EOL, + $flags, + ); + } + + private function telemetryInfo(Event $event): string + { + if (!$this->includeTelemetryInfo) { + return ''; + } + + return $event->telemetryInfo()->asString() . ' '; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php new file mode 100644 index 000000000..f68bdc99a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/JunitXmlLogger.php @@ -0,0 +1,446 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use const PHP_EOL; +use function assert; +use function basename; +use function is_int; +use function sprintf; +use function str_replace; +use function trim; +use DOMDocument; +use DOMElement; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Telemetry\HRTime; +use PHPUnit\Event\Telemetry\Info; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\PreparationStarted; +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\TestSuite\Started; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\TextUI\Output\Printer; +use PHPUnit\Util\Xml; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class JunitXmlLogger +{ + private readonly Printer $printer; + private DOMDocument $document; + private DOMElement $root; + + /** + * @var DOMElement[] + */ + private array $testSuites = []; + + /** + * @psalm-var array + */ + private array $testSuiteTests = [0]; + + /** + * @psalm-var array + */ + private array $testSuiteAssertions = [0]; + + /** + * @psalm-var array + */ + private array $testSuiteErrors = [0]; + + /** + * @psalm-var array + */ + private array $testSuiteFailures = [0]; + + /** + * @psalm-var array + */ + private array $testSuiteSkipped = [0]; + + /** + * @psalm-var array + */ + private array $testSuiteTimes = [0]; + private int $testSuiteLevel = 0; + private ?DOMElement $currentTestCase = null; + private ?HRTime $time = null; + private bool $prepared = false; + private bool $preparationFailed = false; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Printer $printer, Facade $facade) + { + $this->printer = $printer; + + $this->registerSubscribers($facade); + $this->createDocument(); + } + + public function flush(): void + { + $this->printer->print($this->document->saveXML()); + + $this->printer->flush(); + } + + public function testSuiteStarted(Started $event): void + { + $testSuite = $this->document->createElement('testsuite'); + $testSuite->setAttribute('name', $event->testSuite()->name()); + + if ($event->testSuite()->isForTestClass()) { + $testSuite->setAttribute('file', $event->testSuite()->file()); + } + + if ($this->testSuiteLevel > 0) { + $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite); + } else { + $this->root->appendChild($testSuite); + } + + $this->testSuiteLevel++; + $this->testSuites[$this->testSuiteLevel] = $testSuite; + $this->testSuiteTests[$this->testSuiteLevel] = 0; + $this->testSuiteAssertions[$this->testSuiteLevel] = 0; + $this->testSuiteErrors[$this->testSuiteLevel] = 0; + $this->testSuiteFailures[$this->testSuiteLevel] = 0; + $this->testSuiteSkipped[$this->testSuiteLevel] = 0; + $this->testSuiteTimes[$this->testSuiteLevel] = 0; + } + + public function testSuiteFinished(): void + { + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'tests', + (string) $this->testSuiteTests[$this->testSuiteLevel], + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'assertions', + (string) $this->testSuiteAssertions[$this->testSuiteLevel], + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'errors', + (string) $this->testSuiteErrors[$this->testSuiteLevel], + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'failures', + (string) $this->testSuiteFailures[$this->testSuiteLevel], + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'skipped', + (string) $this->testSuiteSkipped[$this->testSuiteLevel], + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'time', + sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]), + ); + + if ($this->testSuiteLevel > 1) { + $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel]; + $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel]; + $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel]; + $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel]; + $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel]; + $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel]; + } + + $this->testSuiteLevel--; + } + + /** + * @throws InvalidArgumentException + */ + public function testPreparationStarted(PreparationStarted $event): void + { + $this->createTestCase($event); + } + + /** + * @throws InvalidArgumentException + */ + public function testPreparationFailed(): void + { + $this->preparationFailed = true; + } + + /** + * @throws InvalidArgumentException + */ + public function testPrepared(): void + { + $this->prepared = true; + } + + /** + * @throws InvalidArgumentException + */ + public function testFinished(Finished $event): void + { + if (!$this->prepared || $this->preparationFailed) { + return; + } + + $this->handleFinish($event->telemetryInfo(), $event->numberOfAssertionsPerformed()); + } + + /** + * @throws InvalidArgumentException + */ + public function testMarkedIncomplete(MarkedIncomplete $event): void + { + $this->handleIncompleteOrSkipped($event); + } + + /** + * @throws InvalidArgumentException + */ + public function testSkipped(Skipped $event): void + { + $this->handleIncompleteOrSkipped($event); + } + + /** + * @throws InvalidArgumentException + */ + public function testErrored(Errored $event): void + { + $this->handleFault($event, 'error'); + + $this->testSuiteErrors[$this->testSuiteLevel]++; + } + + /** + * @throws InvalidArgumentException + */ + public function testFailed(Failed $event): void + { + $this->handleFault($event, 'failure'); + + $this->testSuiteFailures[$this->testSuiteLevel]++; + } + + /** + * @throws InvalidArgumentException + */ + private function handleFinish(Info $telemetryInfo, int $numberOfAssertionsPerformed): void + { + assert($this->currentTestCase !== null); + assert($this->time !== null); + + $time = $telemetryInfo->time()->duration($this->time)->asFloat(); + + $this->testSuiteAssertions[$this->testSuiteLevel] += $numberOfAssertionsPerformed; + + $this->currentTestCase->setAttribute( + 'assertions', + (string) $numberOfAssertionsPerformed, + ); + + $this->currentTestCase->setAttribute( + 'time', + sprintf('%F', $time), + ); + + $this->testSuites[$this->testSuiteLevel]->appendChild( + $this->currentTestCase, + ); + + $this->testSuiteTests[$this->testSuiteLevel]++; + $this->testSuiteTimes[$this->testSuiteLevel] += $time; + + $this->currentTestCase = null; + $this->time = null; + $this->prepared = false; + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerSubscribers(Facade $facade): void + { + $facade->registerSubscribers( + new TestSuiteStartedSubscriber($this), + new TestSuiteFinishedSubscriber($this), + new TestPreparationStartedSubscriber($this), + new TestPreparationFailedSubscriber($this), + new TestPreparedSubscriber($this), + new TestFinishedSubscriber($this), + new TestErroredSubscriber($this), + new TestFailedSubscriber($this), + new TestMarkedIncompleteSubscriber($this), + new TestSkippedSubscriber($this), + new TestRunnerExecutionFinishedSubscriber($this), + ); + } + + private function createDocument(): void + { + $this->document = new DOMDocument('1.0', 'UTF-8'); + $this->document->formatOutput = true; + + $this->root = $this->document->createElement('testsuites'); + $this->document->appendChild($this->root); + } + + /** + * @throws InvalidArgumentException + */ + private function handleFault(Errored|Failed $event, string $type): void + { + if (!$this->prepared) { + $this->createTestCase($event); + } + + assert($this->currentTestCase !== null); + + $buffer = $this->testAsString($event->test()); + + $throwable = $event->throwable(); + $buffer .= trim( + $throwable->description() . PHP_EOL . + $throwable->stackTrace(), + ); + + $fault = $this->document->createElement( + $type, + Xml::prepareString($buffer), + ); + + $fault->setAttribute('type', $throwable->className()); + + $this->currentTestCase->appendChild($fault); + + if (!$this->prepared) { + $this->handleFinish($event->telemetryInfo(), 0); + } + } + + /** + * @throws InvalidArgumentException + */ + private function handleIncompleteOrSkipped(MarkedIncomplete|Skipped $event): void + { + if (!$this->prepared) { + $this->createTestCase($event); + } + + assert($this->currentTestCase !== null); + + $skipped = $this->document->createElement('skipped'); + + $this->currentTestCase->appendChild($skipped); + + $this->testSuiteSkipped[$this->testSuiteLevel]++; + + if (!$this->prepared) { + $this->handleFinish($event->telemetryInfo(), 0); + } + } + + /** + * @throws InvalidArgumentException + */ + private function testAsString(Test $test): string + { + if ($test->isPhpt()) { + return basename($test->file()); + } + + assert($test instanceof TestMethod); + + return sprintf( + '%s::%s%s', + $test->className(), + $this->name($test), + PHP_EOL, + ); + } + + /** + * @throws InvalidArgumentException + */ + private function name(Test $test): string + { + if ($test->isPhpt()) { + return basename($test->file()); + } + + assert($test instanceof TestMethod); + + if (!$test->testData()->hasDataFromDataProvider()) { + return $test->methodName(); + } + + $dataSetName = $test->testData()->dataFromDataProvider()->dataSetName(); + + if (is_int($dataSetName)) { + return sprintf( + '%s with data set #%d', + $test->methodName(), + $dataSetName, + ); + } + + return sprintf( + '%s with data set "%s"', + $test->methodName(), + $dataSetName, + ); + } + + /** + * @throws InvalidArgumentException + * + * @psalm-assert !null $this->currentTestCase + */ + private function createTestCase(Errored|Failed|MarkedIncomplete|PreparationStarted|Prepared|Skipped $event): void + { + $testCase = $this->document->createElement('testcase'); + + $test = $event->test(); + + $testCase->setAttribute('name', $this->name($test)); + $testCase->setAttribute('file', $test->file()); + + if ($test->isTestMethod()) { + assert($test instanceof TestMethod); + + $testCase->setAttribute('line', (string) $test->line()); + $testCase->setAttribute('class', $test->className()); + $testCase->setAttribute('classname', str_replace('\\', '.', $test->className())); + } + + $this->currentTestCase = $testCase; + $this->time = $event->telemetryInfo()->time(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php new file mode 100644 index 000000000..7067461e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly JunitXmlLogger $logger; + + public function __construct(JunitXmlLogger $logger) + { + $this->logger = $logger; + } + + protected function logger(): JunitXmlLogger + { + return $this->logger; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php new file mode 100644 index 000000000..1c5ca7be5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestErroredSubscriber extends Subscriber implements ErroredSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Errored $event): void + { + $this->logger()->testErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php new file mode 100644 index 000000000..286012aec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\FailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailedSubscriber extends Subscriber implements FailedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Failed $event): void + { + $this->logger()->testFailed($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..3f3ecac11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Finished $event): void + { + $this->logger()->testFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php new file mode 100644 index 000000000..5354427e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\MarkedIncompleteSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(MarkedIncomplete $event): void + { + $this->logger()->testMarkedIncomplete($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php new file mode 100644 index 000000000..d052f8dd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\PreparationFailed; +use PHPUnit\Event\Test\PreparationFailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparationFailedSubscriber extends Subscriber implements PreparationFailedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(PreparationFailed $event): void + { + $this->logger()->testPreparationFailed(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php new file mode 100644 index 000000000..91ce18f70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\PreparationStarted; +use PHPUnit\Event\Test\PreparationStartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparationStartedSubscriber extends Subscriber implements PreparationStartedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(PreparationStarted $event): void + { + $this->logger()->testPreparationStarted($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php new file mode 100644 index 000000000..d3de506be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\PreparedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Prepared $event): void + { + $this->logger()->testPrepared(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php new file mode 100644 index 000000000..b544b04f9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\TestRunner\ExecutionFinished; +use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunnerExecutionFinishedSubscriber extends Subscriber implements ExecutionFinishedSubscriber +{ + public function notify(ExecutionFinished $event): void + { + $this->logger()->flush(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php new file mode 100644 index 000000000..383b89db9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Skipped $event): void + { + $this->logger()->testSkipped($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php new file mode 100644 index 000000000..122f4aa7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\TestSuite\Finished; +use PHPUnit\Event\TestSuite\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $this->logger()->testSuiteFinished(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php new file mode 100644 index 000000000..c213d7742 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\JUnit; + +use PHPUnit\Event\TestSuite\Started; +use PHPUnit\Event\TestSuite\StartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber +{ + public function notify(Started $event): void + { + $this->logger()->testSuiteStarted($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php new file mode 100644 index 000000000..ae72b8b4b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly TeamCityLogger $logger; + + public function __construct(TeamCityLogger $logger) + { + $this->logger = $logger; + } + + protected function logger(): TeamCityLogger + { + return $this->logger; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php new file mode 100644 index 000000000..ab2663473 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\ConsideredRiskySubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(ConsideredRisky $event): void + { + $this->logger()->testConsideredRisky($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php new file mode 100644 index 000000000..2c4141b49 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestErroredSubscriber extends Subscriber implements ErroredSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Errored $event): void + { + $this->logger()->testErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php new file mode 100644 index 000000000..248cc1b54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\FailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailedSubscriber extends Subscriber implements FailedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Failed $event): void + { + $this->logger()->testFailed($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..82eaab664 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Finished $event): void + { + $this->logger()->testFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php new file mode 100644 index 000000000..d0cb92143 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\MarkedIncompleteSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(MarkedIncomplete $event): void + { + $this->logger()->testMarkedIncomplete($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php new file mode 100644 index 000000000..34e920072 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\PreparedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber +{ + public function notify(Prepared $event): void + { + $this->logger()->testPrepared($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php new file mode 100644 index 000000000..e87aa21d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\TestRunner\ExecutionFinished; +use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunnerExecutionFinishedSubscriber extends Subscriber implements ExecutionFinishedSubscriber +{ + public function notify(ExecutionFinished $event): void + { + $this->logger()->flush(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php new file mode 100644 index 000000000..17951c36e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Skipped $event): void + { + $this->logger()->testSkipped($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php new file mode 100644 index 000000000..ff96fb227 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\TestSuite\Finished; +use PHPUnit\Event\TestSuite\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $this->logger()->testSuiteFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php new file mode 100644 index 000000000..6bebe6a76 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use PHPUnit\Event\TestSuite\Started; +use PHPUnit\Event\TestSuite\StartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber +{ + public function notify(Started $event): void + { + $this->logger()->testSuiteStarted($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php new file mode 100644 index 000000000..c7062128f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TeamCity/TeamCityLogger.php @@ -0,0 +1,373 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TeamCity; + +use function assert; +use function getmypid; +use function ini_get; +use function is_a; +use function round; +use function sprintf; +use function str_replace; +use function stripos; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\Event; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Telemetry\HRTime; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\TestSuite\Finished as TestSuiteFinished; +use PHPUnit\Event\TestSuite\Started as TestSuiteStarted; +use PHPUnit\Event\TestSuite\TestSuiteForTestClass; +use PHPUnit\Event\TestSuite\TestSuiteForTestMethodWithDataProvider; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Framework\Exception as FrameworkException; +use PHPUnit\TextUI\Output\Printer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TeamCityLogger +{ + private readonly Printer $printer; + private bool $isSummaryTestCountPrinted = false; + private ?HRTime $time = null; + private ?int $flowId; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Printer $printer, Facade $facade) + { + $this->printer = $printer; + + $this->registerSubscribers($facade); + $this->setFlowId(); + } + + public function testSuiteStarted(TestSuiteStarted $event): void + { + $testSuite = $event->testSuite(); + + if (!$this->isSummaryTestCountPrinted) { + $this->isSummaryTestCountPrinted = true; + + $this->writeMessage( + 'testCount', + ['count' => $testSuite->count()], + ); + } + + $parameters = ['name' => $testSuite->name()]; + + if ($testSuite->isForTestClass()) { + assert($testSuite instanceof TestSuiteForTestClass); + + $parameters['locationHint'] = sprintf( + 'php_qn://%s::\\%s', + $testSuite->file(), + $testSuite->name(), + ); + } elseif ($testSuite->isForTestMethodWithDataProvider()) { + assert($testSuite instanceof TestSuiteForTestMethodWithDataProvider); + + $parameters['locationHint'] = sprintf( + 'php_qn://%s::\\%s', + $testSuite->file(), + $testSuite->name(), + ); + + $parameters['name'] = $testSuite->methodName(); + } + + $this->writeMessage('testSuiteStarted', $parameters); + } + + public function testSuiteFinished(TestSuiteFinished $event): void + { + $testSuite = $event->testSuite(); + + $parameters = ['name' => $testSuite->name()]; + + if ($testSuite->isForTestMethodWithDataProvider()) { + assert($testSuite instanceof TestSuiteForTestMethodWithDataProvider); + + $parameters['name'] = $testSuite->methodName(); + } + + $this->writeMessage('testSuiteFinished', $parameters); + } + + public function testPrepared(Prepared $event): void + { + $test = $event->test(); + + $parameters = [ + 'name' => $test->name(), + ]; + + if ($test->isTestMethod()) { + assert($test instanceof TestMethod); + + $parameters['locationHint'] = sprintf( + 'php_qn://%s::\\%s::%s', + $test->file(), + $test->className(), + $test->name(), + ); + } + + $this->writeMessage('testStarted', $parameters); + + $this->time = $event->telemetryInfo()->time(); + } + + /** + * @throws InvalidArgumentException + */ + public function testMarkedIncomplete(MarkedIncomplete $event): void + { + if ($this->time === null) { + $this->time = $event->telemetryInfo()->time(); + } + + $this->writeMessage( + 'testIgnored', + [ + 'name' => $event->test()->name(), + 'message' => $event->throwable()->message(), + 'details' => $this->details($event->throwable()), + 'duration' => $this->duration($event), + ], + ); + } + + /** + * @throws InvalidArgumentException + */ + public function testSkipped(Skipped $event): void + { + if ($this->time === null) { + $this->time = $event->telemetryInfo()->time(); + } + + $parameters = [ + 'name' => $event->test()->name(), + 'message' => $event->message(), + ]; + + $parameters['duration'] = $this->duration($event); + + $this->writeMessage('testIgnored', $parameters); + } + + /** + * @throws InvalidArgumentException + */ + public function testErrored(Errored $event): void + { + if ($this->time === null) { + $this->time = $event->telemetryInfo()->time(); + } + + $this->writeMessage( + 'testFailed', + [ + 'name' => $event->test()->name(), + 'message' => $this->message($event->throwable()), + 'details' => $this->details($event->throwable()), + 'duration' => $this->duration($event), + ], + ); + } + + /** + * @throws InvalidArgumentException + */ + public function testFailed(Failed $event): void + { + if ($this->time === null) { + $this->time = $event->telemetryInfo()->time(); + } + + $parameters = [ + 'name' => $event->test()->name(), + 'message' => $this->message($event->throwable()), + 'details' => $this->details($event->throwable()), + 'duration' => $this->duration($event), + ]; + + if ($event->hasComparisonFailure()) { + $parameters['type'] = 'comparisonFailure'; + $parameters['actual'] = $event->comparisonFailure()->actual(); + $parameters['expected'] = $event->comparisonFailure()->expected(); + } + + $this->writeMessage('testFailed', $parameters); + } + + /** + * @throws InvalidArgumentException + */ + public function testConsideredRisky(ConsideredRisky $event): void + { + if ($this->time === null) { + $this->time = $event->telemetryInfo()->time(); + } + + $this->writeMessage( + 'testFailed', + [ + 'name' => $event->test()->name(), + 'message' => $event->message(), + 'details' => '', + 'duration' => $this->duration($event), + ], + ); + } + + /** + * @throws InvalidArgumentException + */ + public function testFinished(Finished $event): void + { + $this->writeMessage( + 'testFinished', + [ + 'name' => $event->test()->name(), + 'duration' => $this->duration($event), + ], + ); + + $this->time = null; + } + + public function flush(): void + { + $this->printer->flush(); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerSubscribers(Facade $facade): void + { + $facade->registerSubscribers( + new TestSuiteStartedSubscriber($this), + new TestSuiteFinishedSubscriber($this), + new TestPreparedSubscriber($this), + new TestFinishedSubscriber($this), + new TestErroredSubscriber($this), + new TestFailedSubscriber($this), + new TestMarkedIncompleteSubscriber($this), + new TestSkippedSubscriber($this), + new TestConsideredRiskySubscriber($this), + new TestRunnerExecutionFinishedSubscriber($this), + ); + } + + private function setFlowId(): void + { + if (stripos(ini_get('disable_functions'), 'getmypid') === false) { + $this->flowId = getmypid(); + } + } + + private function writeMessage(string $eventName, array $parameters = []): void + { + $this->printer->print( + sprintf( + '##teamcity[%s', + $eventName, + ), + ); + + if ($this->flowId !== null) { + $parameters['flowId'] = $this->flowId; + } + + foreach ($parameters as $key => $value) { + $this->printer->print( + sprintf( + " %s='%s'", + $key, + $this->escape((string) $value), + ), + ); + } + + $this->printer->print("]\n"); + } + + /** + * @throws InvalidArgumentException + */ + private function duration(Event $event): int + { + if ($this->time === null) { + return 0; + } + + return (int) round($event->telemetryInfo()->time()->duration($this->time)->asFloat() * 1000); + } + + private function escape(string $string): string + { + return str_replace( + ['|', "'", "\n", "\r", ']', '['], + ['||', "|'", '|n', '|r', '|]', '|['], + $string, + ); + } + + private function message(Throwable $throwable): string + { + if (is_a($throwable->className(), FrameworkException::class, true)) { + return $throwable->message(); + } + + $buffer = $throwable->className(); + + if (!empty($throwable->message())) { + $buffer .= ': ' . $throwable->message(); + } + + return $buffer; + } + + private function details(Throwable $throwable): string + { + $buffer = $throwable->stackTrace(); + + while ($throwable->hasPrevious()) { + $throwable = $throwable->previous(); + + $buffer .= sprintf( + "\nCaused by\n%s\n%s", + $throwable->description(), + $throwable->stackTrace(), + ); + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php new file mode 100644 index 000000000..35bc243e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/HtmlRenderer.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class HtmlRenderer +{ + /** + * @var string + */ + private const PAGE_HEADER = <<<'EOT' + + + + + Test Documentation + + + +EOT; + + /** + * @var string + */ + private const CLASS_HEADER = <<<'EOT' + +

    %s

    +
      + +EOT; + + /** + * @var string + */ + private const CLASS_FOOTER = <<<'EOT' +
    +EOT; + + /** + * @var string + */ + private const PAGE_FOOTER = <<<'EOT' + + + +EOT; + + /** + * @psalm-param array $tests + */ + public function render(array $tests): string + { + $buffer = self::PAGE_HEADER; + + foreach ($tests as $prettifiedClassName => $_tests) { + $buffer .= sprintf( + self::CLASS_HEADER, + $prettifiedClassName, + ); + + foreach ($this->reduce($_tests) as $prettifiedMethodName => $outcome) { + $buffer .= sprintf( + "
  • %s
  • \n", + $outcome, + $prettifiedMethodName, + ); + } + + $buffer .= self::CLASS_FOOTER; + } + + return $buffer . self::PAGE_FOOTER; + } + + /** + * @psalm-return array + */ + private function reduce(TestResultCollection $tests): array + { + $result = []; + + foreach ($tests as $test) { + $prettifiedMethodName = $test->test()->testDox()->prettifiedMethodName(); + + if (!isset($result[$prettifiedMethodName])) { + $result[$prettifiedMethodName] = $test->status()->isSuccess() ? 'success' : 'defect'; + + continue; + } + + if ($test->status()->isSuccess()) { + continue; + } + + $result[$prettifiedMethodName] = 'defect'; + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php new file mode 100644 index 000000000..d8b948b2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/NamePrettifier.php @@ -0,0 +1,295 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use function array_key_exists; +use function array_keys; +use function array_map; +use function array_pop; +use function array_values; +use function assert; +use function class_exists; +use function explode; +use function gettype; +use function implode; +use function is_bool; +use function is_float; +use function is_int; +use function is_object; +use function is_scalar; +use function method_exists; +use function preg_quote; +use function preg_replace; +use function rtrim; +use function sprintf; +use function str_contains; +use function str_ends_with; +use function str_replace; +use function str_starts_with; +use function strlen; +use function strtolower; +use function strtoupper; +use function substr; +use function trim; +use PHPUnit\Framework\TestCase; +use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; +use PHPUnit\Metadata\TestDox; +use PHPUnit\Util\Color; +use ReflectionEnum; +use ReflectionMethod; +use ReflectionObject; +use SebastianBergmann\Exporter\Exporter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NamePrettifier +{ + /** + * @psalm-var array + */ + private static array $strings = []; + + /** + * @psalm-param class-string $className + */ + public function prettifyTestClassName(string $className): string + { + if (class_exists($className)) { + $classLevelTestDox = MetadataRegistry::parser()->forClass($className)->isTestDox(); + + if ($classLevelTestDox->isNotEmpty()) { + $classLevelTestDox = $classLevelTestDox->asArray()[0]; + + assert($classLevelTestDox instanceof TestDox); + + return $classLevelTestDox->text(); + } + } + + $parts = explode('\\', $className); + $className = array_pop($parts); + + if (str_ends_with($className, 'Test')) { + $className = substr($className, 0, strlen($className) - strlen('Test')); + } + + if (str_starts_with($className, 'Tests')) { + $className = substr($className, strlen('Tests')); + } elseif (str_starts_with($className, 'Test')) { + $className = substr($className, strlen('Test')); + } + + if (empty($className)) { + $className = 'UnnamedTests'; + } + + if (!empty($parts)) { + $parts[] = $className; + $fullyQualifiedName = implode('\\', $parts); + } else { + $fullyQualifiedName = $className; + } + + $result = preg_replace('/(?<=[[:lower:]])(?=[[:upper:]])/u', ' ', $className); + + if ($fullyQualifiedName !== $className) { + return $result . ' (' . $fullyQualifiedName . ')'; + } + + return $result; + } + + // NOTE: this method is on a hot path and very performance sensitive. change with care. + public function prettifyTestMethodName(string $name): string + { + if ($name === '') { + return ''; + } + + $string = rtrim($name, '0123456789'); + + if (array_key_exists($string, self::$strings)) { + $name = $string; + } elseif ($string === $name) { + self::$strings[$string] = 1; + } + + if (str_starts_with($name, 'test_')) { + $name = substr($name, 5); + } elseif (str_starts_with($name, 'test')) { + $name = substr($name, 4); + } + + if ($name === '') { + return ''; + } + + $name[0] = strtoupper($name[0]); + + $noUnderscore = str_replace('_', ' ', $name); + + if ($noUnderscore !== $name) { + return trim($noUnderscore); + } + + $wasNumeric = false; + + $buffer = ''; + + $len = strlen($name); + + for ($i = 0; $i < $len; $i++) { + if ($i > 0 && $name[$i] >= 'A' && $name[$i] <= 'Z') { + $buffer .= ' ' . strtolower($name[$i]); + } else { + $isNumeric = $name[$i] >= '0' && $name[$i] <= '9'; + + if (!$wasNumeric && $isNumeric) { + $buffer .= ' '; + $wasNumeric = true; + } + + if ($wasNumeric && !$isNumeric) { + $wasNumeric = false; + } + + $buffer .= $name[$i]; + } + } + + return $buffer; + } + + public function prettifyTestCase(TestCase $test, bool $colorize): string + { + $annotationWithPlaceholders = false; + $methodLevelTestDox = MetadataRegistry::parser()->forMethod($test::class, $test->name())->isTestDox()->isMethodLevel(); + + if ($methodLevelTestDox->isNotEmpty()) { + $methodLevelTestDox = $methodLevelTestDox->asArray()[0]; + + assert($methodLevelTestDox instanceof TestDox); + + $result = $methodLevelTestDox->text(); + + if (str_contains($result, '$')) { + $annotation = $result; + $providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test, $colorize); + + $variables = array_map( + static fn (string $variable): string => sprintf( + '/%s(?=\b)/', + preg_quote($variable, '/'), + ), + array_keys($providedData), + ); + + $result = preg_replace($variables, $providedData, $annotation); + + $annotationWithPlaceholders = true; + } + } else { + $result = $this->prettifyTestMethodName($test->name()); + } + + if (!$annotationWithPlaceholders && $test->usesDataProvider()) { + $result .= $this->prettifyDataSet($test, $colorize); + } + + return $result; + } + + public function prettifyDataSet(TestCase $test, bool $colorize): string + { + if (!$colorize) { + return $test->dataSetAsString(); + } + + if (is_int($test->dataName())) { + return Color::dim(' with data set ') . Color::colorize('fg-cyan', (string) $test->dataName()); + } + + return Color::dim(' with ') . Color::colorize('fg-cyan', Color::visualizeWhitespace($test->dataName())); + } + + private function mapTestMethodParameterNamesToProvidedDataValues(TestCase $test, bool $colorize): array + { + assert(method_exists($test, $test->name())); + + /** @noinspection PhpUnhandledExceptionInspection */ + $reflector = new ReflectionMethod($test::class, $test->name()); + + $providedData = []; + $providedDataValues = array_values($test->providedData()); + $i = 0; + + $providedData['$_dataName'] = $test->dataName(); + + foreach ($reflector->getParameters() as $parameter) { + if (!array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) { + $providedDataValues[$i] = $parameter->getDefaultValue(); + } + + $value = $providedDataValues[$i++] ?? null; + + if (is_object($value)) { + $reflector = new ReflectionObject($value); + + if ($reflector->isEnum()) { + $enumReflector = new ReflectionEnum($value); + + if ($enumReflector->isBacked()) { + $value = $value->value; + } else { + $value = $value->name; + } + } elseif ($reflector->hasMethod('__toString')) { + $value = (string) $value; + } else { + $value = $value::class; + } + } + + if (!is_scalar($value)) { + $value = gettype($value); + + if ($value === 'NULL') { + $value = 'null'; + } + } + + if (is_bool($value) || is_int($value) || is_float($value)) { + $value = (new Exporter)->export($value); + } + + if ($value === '') { + if ($colorize) { + $value = Color::colorize('dim,underlined', 'empty'); + } else { + $value = "''"; + } + } + + $providedData['$' . $parameter->getName()] = str_replace('$', '\\$', $value); + } + + if ($colorize) { + $providedData = array_map( + static fn ($value) => Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $value, true)), + $providedData, + ); + } + + return $providedData; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php new file mode 100644 index 000000000..8d11c1c20 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/PlainTextRenderer.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use function sprintf; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PlainTextRenderer +{ + /** + * @psalm-param array $tests + */ + public function render(array $tests): string + { + $buffer = ''; + + foreach ($tests as $prettifiedClassName => $_tests) { + $buffer .= $prettifiedClassName . "\n"; + + foreach ($this->reduce($_tests) as $prettifiedMethodName => $outcome) { + $buffer .= sprintf( + ' [%s] %s' . "\n", + $outcome, + $prettifiedMethodName, + ); + } + + $buffer .= "\n"; + } + + return $buffer; + } + + /** + * @psalm-return array + */ + private function reduce(TestResultCollection $tests): array + { + $result = []; + + foreach ($tests as $test) { + $prettifiedMethodName = $test->test()->testDox()->prettifiedMethodName(); + + $success = true; + + if ($test->status()->isError() || + $test->status()->isFailure() || + $test->status()->isIncomplete() || + $test->status()->isSkipped()) { + $success = false; + } + + if (!isset($result[$prettifiedMethodName])) { + $result[$prettifiedMethodName] = $success ? 'x' : ' '; + + continue; + } + + if ($success) { + continue; + } + + $result[$prettifiedMethodName] = ' '; + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php new file mode 100644 index 000000000..9d7e347c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly TestResultCollector $collector; + + public function __construct(TestResultCollector $collector) + { + $this->collector = $collector; + } + + protected function collector(): TestResultCollector + { + return $this->collector; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php new file mode 100644 index 000000000..9bace366f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\ConsideredRiskySubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber +{ + public function notify(ConsideredRisky $event): void + { + $this->collector()->testConsideredRisky($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php new file mode 100644 index 000000000..bd5c56eff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestErroredSubscriber extends Subscriber implements ErroredSubscriber +{ + public function notify(Errored $event): void + { + $this->collector()->testErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php new file mode 100644 index 000000000..8efe91c18 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\FailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailedSubscriber extends Subscriber implements FailedSubscriber +{ + public function notify(Failed $event): void + { + $this->collector()->testFailed($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..2ec85f875 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + /** + * @throws InvalidArgumentException + */ + public function notify(Finished $event): void + { + $this->collector()->testFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php new file mode 100644 index 000000000..6c2e40770 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\MarkedIncompleteSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber +{ + public function notify(MarkedIncomplete $event): void + { + $this->collector()->testMarkedIncomplete($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php new file mode 100644 index 000000000..2821d8e3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\Passed; +use PHPUnit\Event\Test\PassedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPassedSubscriber extends Subscriber implements PassedSubscriber +{ + public function notify(Passed $event): void + { + $this->collector()->testPassed($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php new file mode 100644 index 000000000..a2bf06a97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\PreparedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber +{ + public function notify(Prepared $event): void + { + $this->collector()->testPrepared($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php new file mode 100644 index 000000000..f6ea04b01 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + public function notify(Skipped $event): void + { + $this->collector()->testSkipped($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php new file mode 100644 index 000000000..15872b728 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber +{ + public function notify(DeprecationTriggered $event): void + { + $this->collector()->testTriggeredDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php new file mode 100644 index 000000000..a6d5a0a8d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\NoticeTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber +{ + public function notify(NoticeTriggered $event): void + { + $this->collector()->testTriggeredNotice($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php new file mode 100644 index 000000000..bcdd3947e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber +{ + public function notify(PhpDeprecationTriggered $event): void + { + $this->collector()->testTriggeredPhpDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php new file mode 100644 index 000000000..2601c197d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber +{ + public function notify(PhpNoticeTriggered $event): void + { + $this->collector()->testTriggeredPhpNotice($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php new file mode 100644 index 000000000..3af20b899 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber +{ + public function notify(PhpWarningTriggered $event): void + { + $this->collector()->testTriggeredPhpWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php new file mode 100644 index 000000000..9fc4f268c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitDeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitDeprecationSubscriber extends Subscriber implements PhpunitDeprecationTriggeredSubscriber +{ + public function notify(PhpunitDeprecationTriggered $event): void + { + $this->collector()->testTriggeredPhpunitDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php new file mode 100644 index 000000000..43f32d956 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitErrorTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitErrorSubscriber extends Subscriber implements PhpunitErrorTriggeredSubscriber +{ + public function notify(PhpunitErrorTriggered $event): void + { + $this->collector()->testTriggeredPhpunitError($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php new file mode 100644 index 000000000..3774b8281 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitWarningSubscriber extends Subscriber implements PhpunitWarningTriggeredSubscriber +{ + public function notify(PhpunitWarningTriggered $event): void + { + $this->collector()->testTriggeredPhpunitWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php new file mode 100644 index 000000000..fc8979dc7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\Test\WarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber +{ + public function notify(WarningTriggered $event): void + { + $this->collector()->testTriggeredWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php new file mode 100644 index 000000000..74c6e9dfb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResult.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Framework\TestStatus\TestStatus; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestResult +{ + private readonly TestMethod $test; + private readonly TestStatus $status; + private readonly ?Throwable $throwable; + + public function __construct(TestMethod $test, TestStatus $status, ?Throwable $throwable) + { + $this->test = $test; + $this->status = $status; + $this->throwable = $throwable; + } + + public function test(): TestMethod + { + return $this->test; + } + + public function status(): TestStatus + { + return $this->status; + } + + /** + * @psalm-assert-if-true !null $this->throwable + */ + public function hasThrowable(): bool + { + return $this->throwable !== null; + } + + public function throwable(): ?Throwable + { + return $this->throwable; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php new file mode 100644 index 000000000..1ef1d83d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestResultCollection implements IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $testResults; + + /** + * @psalm-param list $testResults + */ + public static function fromArray(array $testResults): self + { + return new self(...$testResults); + } + + private function __construct(TestResult ...$testResults) + { + $this->testResults = $testResults; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->testResults; + } + + public function getIterator(): TestResultCollectionIterator + { + return new TestResultCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php new file mode 100644 index 000000000..b409fe116 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use function count; +use Iterator; + +/** + * @template-implements Iterator + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestResultCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private readonly array $testResults; + private int $position = 0; + + public function __construct(TestResultCollection $testResults) + { + $this->testResults = $testResults->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->testResults); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestResult + { + return $this->testResults[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php new file mode 100644 index 000000000..df1de66b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php @@ -0,0 +1,447 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Logging\TestDox; + +use function array_keys; +use function array_merge; +use function assert; +use function is_subclass_of; +use function ksort; +use function uksort; +use function usort; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\Passed; +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Framework\TestStatus\TestStatus; +use PHPUnit\Logging\TestDox\TestResult as TestDoxTestMethod; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\SourceFilter; +use ReflectionMethod; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestResultCollector +{ + private readonly Source $source; + + /** + * @psalm-var array> + */ + private array $tests = []; + private ?TestStatus $status = null; + private ?Throwable $throwable = null; + private bool $prepared = false; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Facade $facade, Source $source) + { + $this->source = $source; + + $this->registerSubscribers($facade); + } + + /** + * @psalm-return array + */ + public function testMethodsGroupedByClass(): array + { + $result = []; + + foreach ($this->tests as $prettifiedClassName => $tests) { + $testsByDeclaringClass = []; + + foreach ($tests as $test) { + $declaringClassName = (new ReflectionMethod($test->test()->className(), $test->test()->methodName()))->getDeclaringClass()->getName(); + + if (!isset($testsByDeclaringClass[$declaringClassName])) { + $testsByDeclaringClass[$declaringClassName] = []; + } + + $testsByDeclaringClass[$declaringClassName][] = $test; + } + + foreach (array_keys($testsByDeclaringClass) as $declaringClassName) { + usort( + $testsByDeclaringClass[$declaringClassName], + static function (TestDoxTestMethod $a, TestDoxTestMethod $b): int + { + return $a->test()->line() <=> $b->test()->line(); + }, + ); + } + + uksort( + $testsByDeclaringClass, + /** + * @psalm-param class-string $a + * @psalm-param class-string $b + */ + static function (string $a, string $b): int + { + if (is_subclass_of($b, $a)) { + return -1; + } + + if (is_subclass_of($a, $b)) { + return 1; + } + + return 0; + }, + ); + + $tests = []; + + foreach ($testsByDeclaringClass as $_tests) { + $tests = array_merge($tests, $_tests); + } + + $result[$prettifiedClassName] = TestResultCollection::fromArray($tests); + } + + ksort($result); + + return $result; + } + + public function testPrepared(Prepared $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->status = TestStatus::unknown(); + $this->throwable = null; + $this->prepared = true; + } + + public function testErrored(Errored $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->status = TestStatus::error($event->throwable()->message()); + $this->throwable = $event->throwable(); + + if (!$this->prepared) { + $test = $event->test(); + + assert($test instanceof TestMethod); + + $this->process($test); + } + } + + public function testFailed(Failed $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->status = TestStatus::failure($event->throwable()->message()); + $this->throwable = $event->throwable(); + } + + public function testPassed(Passed $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::success()); + } + + public function testSkipped(Skipped $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::skipped($event->message())); + } + + public function testMarkedIncomplete(MarkedIncomplete $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::incomplete($event->throwable()->message())); + + $this->throwable = $event->throwable(); + } + + public function testConsideredRisky(ConsideredRisky $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::risky()); + } + + public function testTriggeredDeprecation(DeprecationTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + if ($event->ignoredByTest()) { + return; + } + + if ($event->ignoredByBaseline()) { + return; + } + + if (!$this->source->ignoreSuppressionOfDeprecations() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->updateTestStatus(TestStatus::deprecation()); + } + + public function testTriggeredNotice(NoticeTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + if ($event->ignoredByBaseline()) { + return; + } + + if (!$this->source->ignoreSuppressionOfNotices() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->updateTestStatus(TestStatus::notice()); + } + + public function testTriggeredWarning(WarningTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + if ($event->ignoredByBaseline()) { + return; + } + + if (!$this->source->ignoreSuppressionOfWarnings() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->updateTestStatus(TestStatus::warning()); + } + + public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + if ($event->ignoredByTest()) { + return; + } + + if ($event->ignoredByBaseline()) { + return; + } + + if (!$this->source->ignoreSuppressionOfPhpDeprecations() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->updateTestStatus(TestStatus::deprecation()); + } + + public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + if ($event->ignoredByBaseline()) { + return; + } + + if (!$this->source->ignoreSuppressionOfPhpNotices() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->updateTestStatus(TestStatus::notice()); + } + + public function testTriggeredPhpWarning(PhpWarningTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + if ($event->ignoredByBaseline()) { + return; + } + + if (!$this->source->ignoreSuppressionOfPhpWarnings() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->updateTestStatus(TestStatus::warning()); + } + + public function testTriggeredPhpunitDeprecation(PhpunitDeprecationTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::deprecation()); + } + + public function testTriggeredPhpunitError(PhpunitErrorTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::error()); + } + + public function testTriggeredPhpunitWarning(PhpunitWarningTriggered $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $this->updateTestStatus(TestStatus::warning()); + } + + /** + * @throws InvalidArgumentException + */ + public function testFinished(Finished $event): void + { + if (!$event->test()->isTestMethod()) { + return; + } + + $test = $event->test(); + + assert($test instanceof TestMethod); + + $this->process($test); + + $this->status = null; + $this->throwable = null; + $this->prepared = false; + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerSubscribers(Facade $facade): void + { + $facade->registerSubscribers( + new TestConsideredRiskySubscriber($this), + new TestErroredSubscriber($this), + new TestFailedSubscriber($this), + new TestFinishedSubscriber($this), + new TestMarkedIncompleteSubscriber($this), + new TestPassedSubscriber($this), + new TestPreparedSubscriber($this), + new TestSkippedSubscriber($this), + new TestTriggeredDeprecationSubscriber($this), + new TestTriggeredNoticeSubscriber($this), + new TestTriggeredPhpDeprecationSubscriber($this), + new TestTriggeredPhpNoticeSubscriber($this), + new TestTriggeredPhpunitDeprecationSubscriber($this), + new TestTriggeredPhpunitErrorSubscriber($this), + new TestTriggeredPhpunitWarningSubscriber($this), + new TestTriggeredPhpWarningSubscriber($this), + new TestTriggeredWarningSubscriber($this), + ); + } + + private function updateTestStatus(TestStatus $status): void + { + if ($this->status !== null && + $this->status->isMoreImportantThan($status)) { + return; + } + + $this->status = $status; + } + + private function process(TestMethod $test): void + { + if (!isset($this->tests[$test->testDox()->prettifiedClassName()])) { + $this->tests[$test->testDox()->prettifiedClassName()] = []; + } + + $this->tests[$test->testDox()->prettifiedClassName()][] = new TestDoxTestMethod( + $test, + $this->status, + $this->throwable, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/After.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/After.php new file mode 100644 index 000000000..879005904 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/After.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class After extends Metadata +{ + /** + * @psalm-assert-if-true After $this + */ + public function isAfter(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/AfterClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/AfterClass.php new file mode 100644 index 000000000..16bb5cc0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/AfterClass.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class AfterClass extends Metadata +{ + /** + * @psalm-assert-if-true AfterClass $this + */ + public function isAfterClass(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php new file mode 100644 index 000000000..fe5fab56f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/CodeCoverage.php @@ -0,0 +1,317 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Api; + +use function array_unique; +use function array_values; +use function assert; +use function count; +use function interface_exists; +use function sprintf; +use function str_starts_with; +use PHPUnit\Framework\CodeCoverageException; +use PHPUnit\Framework\InvalidCoversTargetException; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Metadata\Covers; +use PHPUnit\Metadata\CoversClass; +use PHPUnit\Metadata\CoversDefaultClass; +use PHPUnit\Metadata\CoversFunction; +use PHPUnit\Metadata\IgnoreClassForCodeCoverage; +use PHPUnit\Metadata\IgnoreFunctionForCodeCoverage; +use PHPUnit\Metadata\IgnoreMethodForCodeCoverage; +use PHPUnit\Metadata\Parser\Registry; +use PHPUnit\Metadata\Uses; +use PHPUnit\Metadata\UsesClass; +use PHPUnit\Metadata\UsesDefaultClass; +use PHPUnit\Metadata\UsesFunction; +use RecursiveIteratorIterator; +use SebastianBergmann\CodeUnit\CodeUnitCollection; +use SebastianBergmann\CodeUnit\Exception as CodeUnitException; +use SebastianBergmann\CodeUnit\InvalidCodeUnitException; +use SebastianBergmann\CodeUnit\Mapper; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CodeCoverage +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return array>|false + * + * @throws CodeCoverageException + */ + public function linesToBeCovered(string $className, string $methodName): array|false + { + if (!$this->shouldCodeCoverageBeCollectedFor($className, $methodName)) { + return false; + } + + $metadataForClass = Registry::parser()->forClass($className); + $classShortcut = null; + + if ($metadataForClass->isCoversDefaultClass()->isNotEmpty()) { + if (count($metadataForClass->isCoversDefaultClass()) > 1) { + throw new CodeCoverageException( + sprintf( + 'More than one @coversDefaultClass annotation for class or interface "%s"', + $className, + ), + ); + } + + $metadata = $metadataForClass->isCoversDefaultClass()->asArray()[0]; + + assert($metadata instanceof CoversDefaultClass); + + $classShortcut = $metadata->className(); + } + + $codeUnits = CodeUnitCollection::fromList(); + $mapper = new Mapper; + + foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { + if (!$metadata->isCoversClass() && !$metadata->isCoversFunction() && !$metadata->isCovers()) { + continue; + } + + assert($metadata instanceof CoversClass || $metadata instanceof CoversFunction || $metadata instanceof Covers); + + if ($metadata->isCoversClass() || $metadata->isCoversFunction()) { + $codeUnits = $codeUnits->mergeWith($this->mapToCodeUnits($metadata)); + } elseif ($metadata->isCovers()) { + assert($metadata instanceof Covers); + + $target = $metadata->target(); + + if (interface_exists($target)) { + throw new InvalidCoversTargetException( + sprintf( + 'Trying to @cover interface "%s".', + $target, + ), + ); + } + + if ($classShortcut !== null && str_starts_with($target, '::')) { + $target = $classShortcut . $target; + } + + try { + $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($target)); + } catch (InvalidCodeUnitException $e) { + throw new InvalidCoversTargetException( + sprintf( + '"@covers %s" is invalid', + $target, + ), + $e->getCode(), + $e, + ); + } + } + } + + return $mapper->codeUnitsToSourceLines($codeUnits); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return array> + * + * @throws CodeCoverageException + */ + public function linesToBeUsed(string $className, string $methodName): array + { + $metadataForClass = Registry::parser()->forClass($className); + $classShortcut = null; + + if ($metadataForClass->isUsesDefaultClass()->isNotEmpty()) { + if (count($metadataForClass->isUsesDefaultClass()) > 1) { + throw new CodeCoverageException( + sprintf( + 'More than one @usesDefaultClass annotation for class or interface "%s"', + $className, + ), + ); + } + + $metadata = $metadataForClass->isUsesDefaultClass()->asArray()[0]; + + assert($metadata instanceof UsesDefaultClass); + + $classShortcut = $metadata->className(); + } + + $codeUnits = CodeUnitCollection::fromList(); + $mapper = new Mapper; + + foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { + if (!$metadata->isUsesClass() && !$metadata->isUsesFunction() && !$metadata->isUses()) { + continue; + } + + assert($metadata instanceof UsesClass || $metadata instanceof UsesFunction || $metadata instanceof Uses); + + if ($metadata->isUsesClass() || $metadata->isUsesFunction()) { + $codeUnits = $codeUnits->mergeWith($this->mapToCodeUnits($metadata)); + } elseif ($metadata->isUses()) { + assert($metadata instanceof Uses); + + $target = $metadata->target(); + + if ($classShortcut !== null && str_starts_with($target, '::')) { + $target = $classShortcut . $target; + } + + try { + $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($target)); + } catch (InvalidCodeUnitException $e) { + throw new InvalidCoversTargetException( + sprintf( + '"@uses %s" is invalid', + $target, + ), + $e->getCode(), + $e, + ); + } + } + } + + return $mapper->codeUnitsToSourceLines($codeUnits); + } + + /** + * @psalm-return array> + */ + public function linesToBeIgnored(TestSuite $testSuite): array + { + $codeUnits = CodeUnitCollection::fromList(); + $mapper = new Mapper; + + foreach ($this->testCaseClassesIn($testSuite) as $testCaseClassName) { + $codeUnits = $codeUnits->mergeWith( + $this->codeUnitsIgnoredBy($testCaseClassName), + ); + } + + return $mapper->codeUnitsToSourceLines($codeUnits); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function shouldCodeCoverageBeCollectedFor(string $className, string $methodName): bool + { + $metadataForClass = Registry::parser()->forClass($className); + $metadataForMethod = Registry::parser()->forMethod($className, $methodName); + + if ($metadataForMethod->isCoversNothing()->isNotEmpty()) { + return false; + } + + if ($metadataForMethod->isCovers()->isNotEmpty() || + $metadataForMethod->isCoversClass()->isNotEmpty() || + $metadataForMethod->isCoversFunction()->isNotEmpty()) { + return true; + } + + if ($metadataForClass->isCoversNothing()->isNotEmpty()) { + return false; + } + + return true; + } + + /** + * @psalm-return list + */ + private function testCaseClassesIn(TestSuite $testSuite): array + { + $classNames = []; + + foreach (new RecursiveIteratorIterator($testSuite) as $test) { + $classNames[] = $test::class; + } + + return array_values(array_unique($classNames)); + } + + /** + * @psalm-param class-string $className + */ + private function codeUnitsIgnoredBy(string $className): CodeUnitCollection + { + $codeUnits = CodeUnitCollection::fromList(); + $mapper = new Mapper; + + foreach (Registry::parser()->forClass($className) as $metadata) { + if ($metadata instanceof IgnoreClassForCodeCoverage) { + $codeUnits = $codeUnits->mergeWith( + $mapper->stringToCodeUnits($metadata->className()), + ); + } + + if ($metadata instanceof IgnoreMethodForCodeCoverage) { + $codeUnits = $codeUnits->mergeWith( + $mapper->stringToCodeUnits($metadata->className() . '::' . $metadata->methodName()), + ); + } + + if ($metadata instanceof IgnoreFunctionForCodeCoverage) { + $codeUnits = $codeUnits->mergeWith( + $mapper->stringToCodeUnits('::' . $metadata->functionName()), + ); + } + } + + return $codeUnits; + } + + /** + * @throws InvalidCoversTargetException + */ + private function mapToCodeUnits(CoversClass|CoversFunction|UsesClass|UsesFunction $metadata): CodeUnitCollection + { + $mapper = new Mapper; + + try { + return $mapper->stringToCodeUnits($metadata->asStringForCodeUnitMapper()); + } catch (CodeUnitException $e) { + if ($metadata->isCoversClass() || $metadata->isUsesClass()) { + if (interface_exists($metadata->className())) { + $type = 'Interface'; + } else { + $type = 'Class'; + } + } else { + $type = 'Function'; + } + + throw new InvalidCoversTargetException( + sprintf( + '%s "%s" is not a valid target for code coverage', + $type, + $metadata->asStringForCodeUnitMapper(), + ), + $e->getCode(), + $e, + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/DataProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/DataProvider.php new file mode 100644 index 000000000..6f5921cd2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/DataProvider.php @@ -0,0 +1,313 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Api; + +use const JSON_ERROR_NONE; +use const PREG_OFFSET_CAPTURE; +use function array_key_exists; +use function assert; +use function explode; +use function get_debug_type; +use function is_array; +use function is_int; +use function is_string; +use function json_decode; +use function json_last_error; +use function json_last_error_msg; +use function preg_match; +use function preg_replace; +use function rtrim; +use function sprintf; +use function str_replace; +use function strlen; +use function substr; +use function trim; +use PHPUnit\Event; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Event\TestData\TestDataCollection; +use PHPUnit\Framework\InvalidDataProviderException; +use PHPUnit\Metadata\DataProvider as DataProviderMetadata; +use PHPUnit\Metadata\MetadataCollection; +use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; +use PHPUnit\Metadata\TestWith; +use PHPUnit\Util\Reflection; +use ReflectionClass; +use ReflectionMethod; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DataProvider +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws InvalidDataProviderException + */ + public function providedData(string $className, string $methodName): ?array + { + $dataProvider = MetadataRegistry::parser()->forMethod($className, $methodName)->isDataProvider(); + $testWith = MetadataRegistry::parser()->forMethod($className, $methodName)->isTestWith(); + + if ($dataProvider->isEmpty() && $testWith->isEmpty()) { + return $this->dataProvidedByTestWithAnnotation($className, $methodName); + } + + if ($dataProvider->isNotEmpty()) { + $data = $this->dataProvidedByMethods($className, $methodName, $dataProvider); + } else { + $data = $this->dataProvidedByMetadata($testWith); + } + + if ($data === []) { + throw new InvalidDataProviderException( + 'Empty data set provided by data provider', + ); + } + + foreach ($data as $key => $value) { + if (!is_array($value)) { + throw new InvalidDataProviderException( + sprintf( + 'Data set %s is invalid', + is_int($key) ? '#' . $key : '"' . $key . '"', + ), + ); + } + } + + return $data; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws InvalidDataProviderException + */ + private function dataProvidedByMethods(string $className, string $methodName, MetadataCollection $dataProvider): array + { + $testMethod = new Event\Code\ClassMethod($className, $methodName); + $methodsCalled = []; + $result = []; + + foreach ($dataProvider as $_dataProvider) { + assert($_dataProvider instanceof DataProviderMetadata); + + $dataProviderMethod = new Event\Code\ClassMethod($_dataProvider->className(), $_dataProvider->methodName()); + + Event\Facade::emitter()->dataProviderMethodCalled( + $testMethod, + $dataProviderMethod, + ); + + $methodsCalled[] = $dataProviderMethod; + + try { + $class = new ReflectionClass($_dataProvider->className()); + $method = $class->getMethod($_dataProvider->methodName()); + $object = null; + + if (!$method->isPublic()) { + Event\Facade::emitter()->testTriggeredPhpunitDeprecation( + $this->valueObjectForTestMethodWithoutTestData( + $className, + $methodName, + ), + sprintf( + 'Data Provider method %s::%s() is not public', + $_dataProvider->className(), + $_dataProvider->methodName(), + ), + ); + } + + if (!$method->isStatic()) { + Event\Facade::emitter()->testTriggeredPhpunitDeprecation( + $this->valueObjectForTestMethodWithoutTestData( + $className, + $methodName, + ), + sprintf( + 'Data Provider method %s::%s() is not static', + $_dataProvider->className(), + $_dataProvider->methodName(), + ), + ); + + $object = $class->newInstanceWithoutConstructor(); + } + + if ($method->getNumberOfParameters() === 0) { + $data = $method->invoke($object); + } else { + Event\Facade::emitter()->testTriggeredPhpunitDeprecation( + $this->valueObjectForTestMethodWithoutTestData( + $className, + $methodName, + ), + sprintf( + 'Data Provider method %s::%s() expects an argument', + $_dataProvider->className(), + $_dataProvider->methodName(), + ), + ); + + $data = $method->invoke($object, $_dataProvider->methodName()); + } + } catch (Throwable $e) { + Event\Facade::emitter()->dataProviderMethodFinished( + $testMethod, + ...$methodsCalled, + ); + + throw new InvalidDataProviderException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + foreach ($data as $key => $value) { + if (is_int($key)) { + $result[] = $value; + } elseif (is_string($key)) { + if (array_key_exists($key, $result)) { + Event\Facade::emitter()->dataProviderMethodFinished( + $testMethod, + ...$methodsCalled, + ); + + throw new InvalidDataProviderException( + sprintf( + 'The key "%s" has already been defined by a previous data provider', + $key, + ), + ); + } + + $result[$key] = $value; + } else { + throw new InvalidDataProviderException( + sprintf( + 'The key must be an integer or a string, %s given', + get_debug_type($key), + ), + ); + } + } + } + + Event\Facade::emitter()->dataProviderMethodFinished( + $testMethod, + ...$methodsCalled, + ); + + return $result; + } + + private function dataProvidedByMetadata(MetadataCollection $testWith): array + { + $result = []; + + foreach ($testWith as $_testWith) { + assert($_testWith instanceof TestWith); + + $result[] = $_testWith->data(); + } + + return $result; + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidDataProviderException + */ + private function dataProvidedByTestWithAnnotation(string $className, string $methodName): ?array + { + $docComment = (new ReflectionMethod($className, $methodName))->getDocComment(); + + if ($docComment === false) { + return null; + } + + $docComment = str_replace("\r\n", "\n", $docComment); + $docComment = preg_replace('/\n\s*\*\s?/', "\n", $docComment); + $docComment = substr($docComment, 0, -1); + $docComment = rtrim($docComment, "\n"); + + if (!preg_match('/@testWith\s+/', $docComment, $matches, PREG_OFFSET_CAPTURE)) { + return null; + } + + $offset = strlen($matches[0][0]) + (int) $matches[0][1]; + $annotationContent = substr($docComment, $offset); + $data = []; + + foreach (explode("\n", $annotationContent) as $candidateRow) { + $candidateRow = trim($candidateRow); + + if ($candidateRow === '' || $candidateRow[0] !== '[') { + break; + } + + $dataSet = json_decode($candidateRow, true); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new InvalidDataProviderException( + 'The data set for the @testWith annotation cannot be parsed: ' . json_last_error_msg(), + ); + } + + $data[] = $dataSet; + } + + if (!$data) { + throw new InvalidDataProviderException( + 'The data set for the @testWith annotation cannot be parsed.', + ); + } + + return $data; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws MoreThanOneDataSetFromDataProviderException + */ + private function valueObjectForTestMethodWithoutTestData(string $className, string $methodName): TestMethod + { + $location = Reflection::sourceLocationFor($className, $methodName); + + return new TestMethod( + $className, + $methodName, + $location['file'], + $location['line'], + Event\Code\TestDoxBuilder::fromClassNameAndMethodName( + $className, + $methodName, + ), + MetadataRegistry::parser()->forClassAndMethod( + $className, + $methodName, + ), + TestDataCollection::fromArray([]), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Dependencies.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Dependencies.php new file mode 100644 index 000000000..1b20df988 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Dependencies.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Api; + +use function assert; +use PHPUnit\Framework\ExecutionOrderDependency; +use PHPUnit\Metadata\DependsOnClass; +use PHPUnit\Metadata\DependsOnMethod; +use PHPUnit\Metadata\Parser\Registry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Dependencies +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return list + */ + public static function dependencies(string $className, string $methodName): array + { + $dependencies = []; + + foreach (Registry::parser()->forClassAndMethod($className, $methodName)->isDepends() as $metadata) { + if ($metadata->isDependsOnClass()) { + assert($metadata instanceof DependsOnClass); + + $dependencies[] = ExecutionOrderDependency::forClass($metadata); + + continue; + } + + assert($metadata instanceof DependsOnMethod); + + if (empty($metadata->methodName())) { + $dependencies[] = ExecutionOrderDependency::invalid(); + + continue; + } + + $dependencies[] = ExecutionOrderDependency::forMethod($metadata); + } + + return $dependencies; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Groups.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Groups.php new file mode 100644 index 000000000..dca8ef64c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Groups.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Api; + +use function array_flip; +use function array_key_exists; +use function array_unique; +use function assert; +use function strtolower; +use function trim; +use PHPUnit\Framework\TestSize\TestSize; +use PHPUnit\Metadata\Covers; +use PHPUnit\Metadata\CoversClass; +use PHPUnit\Metadata\CoversFunction; +use PHPUnit\Metadata\Group; +use PHPUnit\Metadata\Parser\Registry; +use PHPUnit\Metadata\Uses; +use PHPUnit\Metadata\UsesClass; +use PHPUnit\Metadata\UsesFunction; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Groups +{ + /** + * @var array> + */ + private static array $groupCache = []; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return array + */ + public function groups(string $className, string $methodName, bool $includeVirtual = true): array + { + $key = $className . '::' . $methodName . '::' . $includeVirtual; + + if (array_key_exists($key, self::$groupCache)) { + return self::$groupCache[$key]; + } + + $groups = []; + + foreach (Registry::parser()->forClassAndMethod($className, $methodName)->isGroup() as $group) { + assert($group instanceof Group); + + $groups[] = $group->groupName(); + } + + if ($groups === []) { + $groups[] = 'default'; + } + + if (!$includeVirtual) { + return self::$groupCache[$key] = array_unique($groups); + } + + foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { + if ($metadata->isCoversClass() || $metadata->isCoversFunction()) { + assert($metadata instanceof CoversClass || $metadata instanceof CoversFunction); + + $groups[] = '__phpunit_covers_' . $this->canonicalizeName($metadata->asStringForCodeUnitMapper()); + + continue; + } + + if ($metadata->isCovers()) { + assert($metadata instanceof Covers); + + $groups[] = '__phpunit_covers_' . $this->canonicalizeName($metadata->target()); + + continue; + } + + if ($metadata->isUsesClass() || $metadata->isUsesFunction()) { + assert($metadata instanceof UsesClass || $metadata instanceof UsesFunction); + + $groups[] = '__phpunit_uses_' . $this->canonicalizeName($metadata->asStringForCodeUnitMapper()); + + continue; + } + + if ($metadata->isUses()) { + assert($metadata instanceof Uses); + + $groups[] = '__phpunit_uses_' . $this->canonicalizeName($metadata->target()); + } + } + + return self::$groupCache[$key] = array_unique($groups); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function size(string $className, string $methodName): TestSize + { + $groups = array_flip($this->groups($className, $methodName)); + + if (isset($groups['large'])) { + return TestSize::large(); + } + + if (isset($groups['medium'])) { + return TestSize::medium(); + } + + if (isset($groups['small'])) { + return TestSize::small(); + } + + return TestSize::unknown(); + } + + private function canonicalizeName(string $name): string + { + return strtolower(trim($name, '\\')); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/HookMethods.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/HookMethods.php new file mode 100644 index 000000000..89b8c2c7c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/HookMethods.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Api; + +use function array_unshift; +use function assert; +use function class_exists; +use PHPUnit\Metadata\Parser\Registry; +use PHPUnit\Util\Reflection; +use ReflectionClass; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class HookMethods +{ + /** + * @psalm-var array, before: list, preCondition: list, postCondition: list, after: list, afterClass: list}> + */ + private static array $hookMethods = []; + + /** + * @psalm-param class-string $className + * + * @psalm-return array{beforeClass: list, before: list, preCondition: list, postCondition: list, after: list, afterClass: list} + */ + public function hookMethods(string $className): array + { + if (!class_exists($className)) { + return self::emptyHookMethodsArray(); + } + + if (isset(self::$hookMethods[$className])) { + return self::$hookMethods[$className]; + } + + self::$hookMethods[$className] = self::emptyHookMethodsArray(); + + foreach (Reflection::methodsInTestClass(new ReflectionClass($className)) as $method) { + $methodName = $method->getName(); + + assert(!empty($methodName)); + + $metadata = Registry::parser()->forMethod($className, $methodName); + + if ($method->isStatic()) { + if ($metadata->isBeforeClass()->isNotEmpty()) { + array_unshift( + self::$hookMethods[$className]['beforeClass'], + $methodName, + ); + } + + if ($metadata->isAfterClass()->isNotEmpty()) { + self::$hookMethods[$className]['afterClass'][] = $methodName; + } + } + + if ($metadata->isBefore()->isNotEmpty()) { + array_unshift( + self::$hookMethods[$className]['before'], + $methodName, + ); + } + + if ($metadata->isPreCondition()->isNotEmpty()) { + array_unshift( + self::$hookMethods[$className]['preCondition'], + $methodName, + ); + } + + if ($metadata->isPostCondition()->isNotEmpty()) { + self::$hookMethods[$className]['postCondition'][] = $methodName; + } + + if ($metadata->isAfter()->isNotEmpty()) { + self::$hookMethods[$className]['after'][] = $methodName; + } + } + + return self::$hookMethods[$className]; + } + + /** + * @psalm-return array{beforeClass: list, before: list, preCondition: list, postCondition: list, after: list, afterClass: list} + */ + private function emptyHookMethodsArray(): array + { + return [ + 'beforeClass' => ['setUpBeforeClass'], + 'before' => ['setUp'], + 'preCondition' => ['assertPreConditions'], + 'postCondition' => ['assertPostConditions'], + 'after' => ['tearDown'], + 'afterClass' => ['tearDownAfterClass'], + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Requirements.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Requirements.php new file mode 100644 index 000000000..922421f4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Api/Requirements.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Api; + +use const PHP_OS; +use const PHP_OS_FAMILY; +use const PHP_VERSION; +use function addcslashes; +use function assert; +use function extension_loaded; +use function function_exists; +use function ini_get; +use function method_exists; +use function phpversion; +use function preg_match; +use function sprintf; +use PHPUnit\Metadata\Parser\Registry; +use PHPUnit\Metadata\RequiresFunction; +use PHPUnit\Metadata\RequiresMethod; +use PHPUnit\Metadata\RequiresOperatingSystem; +use PHPUnit\Metadata\RequiresOperatingSystemFamily; +use PHPUnit\Metadata\RequiresPhp; +use PHPUnit\Metadata\RequiresPhpExtension; +use PHPUnit\Metadata\RequiresPhpunit; +use PHPUnit\Metadata\RequiresSetting; +use PHPUnit\Runner\Version; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Requirements +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return list + */ + public function requirementsNotSatisfiedFor(string $className, string $methodName): array + { + $notSatisfied = []; + + foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { + if ($metadata->isRequiresPhp()) { + assert($metadata instanceof RequiresPhp); + + if (!$metadata->versionRequirement()->isSatisfiedBy(PHP_VERSION)) { + $notSatisfied[] = sprintf( + 'PHP %s is required.', + $metadata->versionRequirement()->asString(), + ); + } + } + + if ($metadata->isRequiresPhpExtension()) { + assert($metadata instanceof RequiresPhpExtension); + + if (!extension_loaded($metadata->extension()) || + ($metadata->hasVersionRequirement() && + !$metadata->versionRequirement()->isSatisfiedBy(phpversion($metadata->extension())))) { + $notSatisfied[] = sprintf( + 'PHP extension %s%s is required.', + $metadata->extension(), + $metadata->hasVersionRequirement() ? (' ' . $metadata->versionRequirement()->asString()) : '', + ); + } + } + + if ($metadata->isRequiresPhpunit()) { + assert($metadata instanceof RequiresPhpunit); + + if (!$metadata->versionRequirement()->isSatisfiedBy(Version::id())) { + $notSatisfied[] = sprintf( + 'PHPUnit %s is required.', + $metadata->versionRequirement()->asString(), + ); + } + } + + if ($metadata->isRequiresOperatingSystemFamily()) { + assert($metadata instanceof RequiresOperatingSystemFamily); + + if ($metadata->operatingSystemFamily() !== PHP_OS_FAMILY) { + $notSatisfied[] = sprintf( + 'Operating system %s is required.', + $metadata->operatingSystemFamily(), + ); + } + } + + if ($metadata->isRequiresOperatingSystem()) { + assert($metadata instanceof RequiresOperatingSystem); + + $pattern = sprintf( + '/%s/i', + addcslashes($metadata->operatingSystem(), '/'), + ); + + if (!preg_match($pattern, PHP_OS)) { + $notSatisfied[] = sprintf( + 'Operating system %s is required.', + $metadata->operatingSystem(), + ); + } + } + + if ($metadata->isRequiresFunction()) { + assert($metadata instanceof RequiresFunction); + + if (!function_exists($metadata->functionName())) { + $notSatisfied[] = sprintf( + 'Function %s() is required.', + $metadata->functionName(), + ); + } + } + + if ($metadata->isRequiresMethod()) { + assert($metadata instanceof RequiresMethod); + + if (!method_exists($metadata->className(), $metadata->methodName())) { + $notSatisfied[] = sprintf( + 'Method %s::%s() is required.', + $metadata->className(), + $metadata->methodName(), + ); + } + } + + if ($metadata->isRequiresSetting()) { + assert($metadata instanceof RequiresSetting); + + if (ini_get($metadata->setting()) !== $metadata->value()) { + $notSatisfied[] = sprintf( + 'Setting "%s" is required to be "%s".', + $metadata->setting(), + $metadata->value(), + ); + } + } + } + + return $notSatisfied; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupGlobals.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupGlobals.php new file mode 100644 index 000000000..b6c485c88 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupGlobals.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BackupGlobals extends Metadata +{ + private readonly bool $enabled; + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level, bool $enabled) + { + parent::__construct($level); + + $this->enabled = $enabled; + } + + /** + * @psalm-assert-if-true BackupGlobals $this + */ + public function isBackupGlobals(): bool + { + return true; + } + + public function enabled(): bool + { + return $this->enabled; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupStaticProperties.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupStaticProperties.php new file mode 100644 index 000000000..30cb9c4d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BackupStaticProperties.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BackupStaticProperties extends Metadata +{ + private readonly bool $enabled; + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level, bool $enabled) + { + parent::__construct($level); + + $this->enabled = $enabled; + } + + /** + * @psalm-assert-if-true BackupStaticProperties $this + */ + public function isBackupStaticProperties(): bool + { + return true; + } + + public function enabled(): bool + { + return $this->enabled; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Before.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Before.php new file mode 100644 index 000000000..08a72b47f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Before.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Before extends Metadata +{ + /** + * @psalm-assert-if-true Before $this + */ + public function isBefore(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BeforeClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BeforeClass.php new file mode 100644 index 000000000..9ae35e514 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/BeforeClass.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeClass extends Metadata +{ + /** + * @psalm-assert-if-true BeforeClass $this + */ + public function isBeforeClass(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Covers.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Covers.php new file mode 100644 index 000000000..b4c723453 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Covers.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Covers extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $target; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $target + */ + protected function __construct(int $level, string $target) + { + parent::__construct($level); + + $this->target = $target; + } + + /** + * @psalm-assert-if-true Covers $this + */ + public function isCovers(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function target(): string + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversClass.php new file mode 100644 index 000000000..22889adf4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversClass.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 PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class CoversClass extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + */ + protected function __construct(int $level, string $className) + { + parent::__construct($level); + + $this->className = $className; + } + + /** + * @psalm-assert-if-true CoversClass $this + */ + public function isCoversClass(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return class-string + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function asStringForCodeUnitMapper(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversDefaultClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversDefaultClass.php new file mode 100644 index 000000000..3f7b57c44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversDefaultClass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class CoversDefaultClass extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + */ + protected function __construct(int $level, string $className) + { + parent::__construct($level); + + $this->className = $className; + } + + /** + * @psalm-assert-if-true CoversDefaultClass $this + */ + public function isCoversDefaultClass(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversFunction.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversFunction.php new file mode 100644 index 000000000..ee9f858ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversFunction.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class CoversFunction extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $functionName + */ + protected function __construct(int $level, string $functionName) + { + parent::__construct($level); + + $this->functionName = $functionName; + } + + /** + * @psalm-assert-if-true CoversFunction $this + */ + public function isCoversFunction(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function asStringForCodeUnitMapper(): string + { + return '::' . $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversNothing.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversNothing.php new file mode 100644 index 000000000..4703964e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/CoversNothing.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class CoversNothing extends Metadata +{ + /** + * @psalm-assert-if-true CoversNothing $this + */ + public function isCoversNothing(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DataProvider.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DataProvider.php new file mode 100644 index 000000000..d1a0bfd59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DataProvider.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DataProvider extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + protected function __construct(int $level, string $className, string $methodName) + { + parent::__construct($level); + + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-assert-if-true DataProvider $this + */ + public function isDataProvider(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnClass.php new file mode 100644 index 000000000..c146afd95 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnClass.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DependsOnClass extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + private readonly bool $deepClone; + private readonly bool $shallowClone; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + */ + protected function __construct(int $level, string $className, bool $deepClone, bool $shallowClone) + { + parent::__construct($level); + + $this->className = $className; + $this->deepClone = $deepClone; + $this->shallowClone = $shallowClone; + } + + /** + * @psalm-assert-if-true DependsOnClass $this + */ + public function isDependsOnClass(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + public function deepClone(): bool + { + return $this->deepClone; + } + + public function shallowClone(): bool + { + return $this->shallowClone; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnMethod.php new file mode 100644 index 000000000..1db27c7bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DependsOnMethod.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DependsOnMethod extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + private readonly bool $deepClone; + private readonly bool $shallowClone; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + protected function __construct(int $level, string $className, string $methodName, bool $deepClone, bool $shallowClone) + { + parent::__construct($level); + + $this->className = $className; + $this->methodName = $methodName; + $this->deepClone = $deepClone; + $this->shallowClone = $shallowClone; + } + + /** + * @psalm-assert-if-true DependsOnMethod $this + */ + public function isDependsOnMethod(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } + + public function deepClone(): bool + { + return $this->deepClone; + } + + public function shallowClone(): bool + { + return $this->shallowClone; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php new file mode 100644 index 000000000..0e1ac0e74 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/DoesNotPerformAssertions.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class DoesNotPerformAssertions extends Metadata +{ + /** + * @psalm-assert-if-true DoesNotPerformAssertions $this + */ + public function isDoesNotPerformAssertions(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php new file mode 100644 index 000000000..ddff62e05 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use function sprintf; +use PHPUnit\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AnnotationsAreNotSupportedForInternalClassesException extends RuntimeException implements Exception +{ + /** + * @psalm-param class-string $className + */ + public function __construct(string $className) + { + parent::__construct( + sprintf( + 'Annotations can only be parsed for user-defined classes, trying to parse annotations for class "%s"', + $className, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/Exception.php new file mode 100644 index 000000000..0faa9b7c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/Exception.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +interface Exception extends \PHPUnit\Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php new file mode 100644 index 000000000..cb82e8411 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use RuntimeException; + +final class InvalidVersionRequirementException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php new file mode 100644 index 000000000..835106796 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/NoVersionRequirementException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use RuntimeException; + +final class NoVersionRequirementException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php new file mode 100644 index 000000000..04e0d2299 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Exception/ReflectionException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use PHPUnit\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php new file mode 100644 index 000000000..a096d676b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExcludeGlobalVariableFromBackup extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $globalVariableName; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $globalVariableName + */ + protected function __construct(int $level, string $globalVariableName) + { + parent::__construct($level); + + $this->globalVariableName = $globalVariableName; + } + + /** + * @psalm-assert-if-true ExcludeGlobalVariableFromBackup $this + */ + public function isExcludeGlobalVariableFromBackup(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function globalVariableName(): string + { + return $this->globalVariableName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php new file mode 100644 index 000000000..53a3c523a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExcludeStaticPropertyFromBackup extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $propertyName; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + * @psalm-param non-empty-string $propertyName + */ + protected function __construct(int $level, string $className, string $propertyName) + { + parent::__construct($level); + + $this->className = $className; + $this->propertyName = $propertyName; + } + + /** + * @psalm-assert-if-true ExcludeStaticPropertyFromBackup $this + */ + public function isExcludeStaticPropertyFromBackup(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function propertyName(): string + { + return $this->propertyName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Group.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Group.php new file mode 100644 index 000000000..e609d2ed6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Group.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Group extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $groupName; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $groupName + */ + protected function __construct(int $level, string $groupName) + { + parent::__construct($level); + + $this->groupName = $groupName; + } + + /** + * @psalm-assert-if-true Group $this + */ + public function isGroup(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function groupName(): string + { + return $this->groupName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php new file mode 100644 index 000000000..5887ccad8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreClassForCodeCoverage.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ +final class IgnoreClassForCodeCoverage extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + */ + protected function __construct(int $level, string $className) + { + parent::__construct($level); + + $this->className = $className; + } + + /** + * @psalm-assert-if-true IgnoreClassForCodeCoverage $this + */ + public function isIgnoreClassForCodeCoverage(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php new file mode 100644 index 000000000..b84a868c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreDeprecations.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class IgnoreDeprecations extends Metadata +{ + /** + * @psalm-assert-if-true IgnoreDeprecations $this + */ + public function isIgnoreDeprecations(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php new file mode 100644 index 000000000..bc4c9b1e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreFunctionForCodeCoverage.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ +final class IgnoreFunctionForCodeCoverage extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $functionName + */ + protected function __construct(int $level, string $functionName) + { + parent::__construct($level); + + $this->functionName = $functionName; + } + + /** + * @psalm-assert-if-true IgnoreFunctionForCodeCoverage $this + */ + public function isIgnoreFunctionForCodeCoverage(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php new file mode 100644 index 000000000..398f0310d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/IgnoreMethodForCodeCoverage.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ +final class IgnoreMethodForCodeCoverage extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + protected function __construct(int $level, string $className, string $methodName) + { + parent::__construct($level); + + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-assert-if-true IgnoreMethodForCodeCoverage $this + */ + public function isIgnoreMethodForCodeCoverage(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Metadata.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Metadata.php new file mode 100644 index 000000000..4ac06b152 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Metadata.php @@ -0,0 +1,835 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use PHPUnit\Metadata\Version\Requirement; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Metadata +{ + private const CLASS_LEVEL = 0; + private const METHOD_LEVEL = 1; + + /** + * @psalm-var 0|1 + */ + private readonly int $level; + + public static function after(): After + { + return new After(self::METHOD_LEVEL); + } + + public static function afterClass(): AfterClass + { + return new AfterClass(self::METHOD_LEVEL); + } + + public static function backupGlobalsOnClass(bool $enabled): BackupGlobals + { + return new BackupGlobals(self::CLASS_LEVEL, $enabled); + } + + public static function backupGlobalsOnMethod(bool $enabled): BackupGlobals + { + return new BackupGlobals(self::METHOD_LEVEL, $enabled); + } + + public static function backupStaticPropertiesOnClass(bool $enabled): BackupStaticProperties + { + return new BackupStaticProperties(self::CLASS_LEVEL, $enabled); + } + + public static function backupStaticPropertiesOnMethod(bool $enabled): BackupStaticProperties + { + return new BackupStaticProperties(self::METHOD_LEVEL, $enabled); + } + + public static function before(): Before + { + return new Before(self::METHOD_LEVEL); + } + + public static function beforeClass(): BeforeClass + { + return new BeforeClass(self::METHOD_LEVEL); + } + + /** + * @psalm-param class-string $className + */ + public static function coversClass(string $className): CoversClass + { + return new CoversClass(self::CLASS_LEVEL, $className); + } + + /** + * @psalm-param non-empty-string $functionName + */ + public static function coversFunction(string $functionName): CoversFunction + { + return new CoversFunction(self::CLASS_LEVEL, $functionName); + } + + /** + * @psalm-param non-empty-string $target + */ + public static function coversOnClass(string $target): Covers + { + return new Covers(self::CLASS_LEVEL, $target); + } + + /** + * @psalm-param non-empty-string $target + */ + public static function coversOnMethod(string $target): Covers + { + return new Covers(self::METHOD_LEVEL, $target); + } + + /** + * @psalm-param class-string $className + */ + public static function coversDefaultClass(string $className): CoversDefaultClass + { + return new CoversDefaultClass(self::CLASS_LEVEL, $className); + } + + public static function coversNothingOnClass(): CoversNothing + { + return new CoversNothing(self::CLASS_LEVEL); + } + + public static function coversNothingOnMethod(): CoversNothing + { + return new CoversNothing(self::METHOD_LEVEL); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public static function dataProvider(string $className, string $methodName): DataProvider + { + return new DataProvider(self::METHOD_LEVEL, $className, $methodName); + } + + /** + * @psalm-param class-string $className + */ + public static function dependsOnClass(string $className, bool $deepClone, bool $shallowClone): DependsOnClass + { + return new DependsOnClass(self::METHOD_LEVEL, $className, $deepClone, $shallowClone); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public static function dependsOnMethod(string $className, string $methodName, bool $deepClone, bool $shallowClone): DependsOnMethod + { + return new DependsOnMethod(self::METHOD_LEVEL, $className, $methodName, $deepClone, $shallowClone); + } + + public static function doesNotPerformAssertionsOnClass(): DoesNotPerformAssertions + { + return new DoesNotPerformAssertions(self::CLASS_LEVEL); + } + + public static function doesNotPerformAssertionsOnMethod(): DoesNotPerformAssertions + { + return new DoesNotPerformAssertions(self::METHOD_LEVEL); + } + + /** + * @psalm-param non-empty-string $globalVariableName + */ + public static function excludeGlobalVariableFromBackupOnClass(string $globalVariableName): ExcludeGlobalVariableFromBackup + { + return new ExcludeGlobalVariableFromBackup(self::CLASS_LEVEL, $globalVariableName); + } + + /** + * @psalm-param non-empty-string $globalVariableName + */ + public static function excludeGlobalVariableFromBackupOnMethod(string $globalVariableName): ExcludeGlobalVariableFromBackup + { + return new ExcludeGlobalVariableFromBackup(self::METHOD_LEVEL, $globalVariableName); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $propertyName + */ + public static function excludeStaticPropertyFromBackupOnClass(string $className, string $propertyName): ExcludeStaticPropertyFromBackup + { + return new ExcludeStaticPropertyFromBackup(self::CLASS_LEVEL, $className, $propertyName); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $propertyName + */ + public static function excludeStaticPropertyFromBackupOnMethod(string $className, string $propertyName): ExcludeStaticPropertyFromBackup + { + return new ExcludeStaticPropertyFromBackup(self::METHOD_LEVEL, $className, $propertyName); + } + + /** + * @psalm-param non-empty-string $groupName + */ + public static function groupOnClass(string $groupName): Group + { + return new Group(self::CLASS_LEVEL, $groupName); + } + + /** + * @psalm-param non-empty-string $groupName + */ + public static function groupOnMethod(string $groupName): Group + { + return new Group(self::METHOD_LEVEL, $groupName); + } + + public static function ignoreDeprecationsOnClass(): IgnoreDeprecations + { + return new IgnoreDeprecations(self::CLASS_LEVEL); + } + + public static function ignoreDeprecationsOnMethod(): IgnoreDeprecations + { + return new IgnoreDeprecations(self::METHOD_LEVEL); + } + + /** + * @psalm-param class-string $className + */ + public static function ignoreClassForCodeCoverage(string $className): IgnoreClassForCodeCoverage + { + return new IgnoreClassForCodeCoverage(self::CLASS_LEVEL, $className); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public static function ignoreMethodForCodeCoverage(string $className, string $methodName): IgnoreMethodForCodeCoverage + { + return new IgnoreMethodForCodeCoverage(self::CLASS_LEVEL, $className, $methodName); + } + + /** + * @psalm-param non-empty-string $functionName + */ + public static function ignoreFunctionForCodeCoverage(string $functionName): IgnoreFunctionForCodeCoverage + { + return new IgnoreFunctionForCodeCoverage(self::CLASS_LEVEL, $functionName); + } + + public static function postCondition(): PostCondition + { + return new PostCondition(self::METHOD_LEVEL); + } + + public static function preCondition(): PreCondition + { + return new PreCondition(self::METHOD_LEVEL); + } + + public static function preserveGlobalStateOnClass(bool $enabled): PreserveGlobalState + { + return new PreserveGlobalState(self::CLASS_LEVEL, $enabled); + } + + public static function preserveGlobalStateOnMethod(bool $enabled): PreserveGlobalState + { + return new PreserveGlobalState(self::METHOD_LEVEL, $enabled); + } + + /** + * @psalm-param non-empty-string $functionName + */ + public static function requiresFunctionOnClass(string $functionName): RequiresFunction + { + return new RequiresFunction(self::CLASS_LEVEL, $functionName); + } + + /** + * @psalm-param non-empty-string $functionName + */ + public static function requiresFunctionOnMethod(string $functionName): RequiresFunction + { + return new RequiresFunction(self::METHOD_LEVEL, $functionName); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public static function requiresMethodOnClass(string $className, string $methodName): RequiresMethod + { + return new RequiresMethod(self::CLASS_LEVEL, $className, $methodName); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public static function requiresMethodOnMethod(string $className, string $methodName): RequiresMethod + { + return new RequiresMethod(self::METHOD_LEVEL, $className, $methodName); + } + + /** + * @psalm-param non-empty-string $operatingSystem + */ + public static function requiresOperatingSystemOnClass(string $operatingSystem): RequiresOperatingSystem + { + return new RequiresOperatingSystem(self::CLASS_LEVEL, $operatingSystem); + } + + /** + * @psalm-param non-empty-string $operatingSystem + */ + public static function requiresOperatingSystemOnMethod(string $operatingSystem): RequiresOperatingSystem + { + return new RequiresOperatingSystem(self::METHOD_LEVEL, $operatingSystem); + } + + /** + * @psalm-param non-empty-string $operatingSystemFamily + */ + public static function requiresOperatingSystemFamilyOnClass(string $operatingSystemFamily): RequiresOperatingSystemFamily + { + return new RequiresOperatingSystemFamily(self::CLASS_LEVEL, $operatingSystemFamily); + } + + /** + * @psalm-param non-empty-string $operatingSystemFamily + */ + public static function requiresOperatingSystemFamilyOnMethod(string $operatingSystemFamily): RequiresOperatingSystemFamily + { + return new RequiresOperatingSystemFamily(self::METHOD_LEVEL, $operatingSystemFamily); + } + + public static function requiresPhpOnClass(Requirement $versionRequirement): RequiresPhp + { + return new RequiresPhp(self::CLASS_LEVEL, $versionRequirement); + } + + public static function requiresPhpOnMethod(Requirement $versionRequirement): RequiresPhp + { + return new RequiresPhp(self::METHOD_LEVEL, $versionRequirement); + } + + /** + * @psalm-param non-empty-string $extension + */ + public static function requiresPhpExtensionOnClass(string $extension, ?Requirement $versionRequirement): RequiresPhpExtension + { + return new RequiresPhpExtension(self::CLASS_LEVEL, $extension, $versionRequirement); + } + + /** + * @psalm-param non-empty-string $extension + */ + public static function requiresPhpExtensionOnMethod(string $extension, ?Requirement $versionRequirement): RequiresPhpExtension + { + return new RequiresPhpExtension(self::METHOD_LEVEL, $extension, $versionRequirement); + } + + public static function requiresPhpunitOnClass(Requirement $versionRequirement): RequiresPhpunit + { + return new RequiresPhpunit(self::CLASS_LEVEL, $versionRequirement); + } + + public static function requiresPhpunitOnMethod(Requirement $versionRequirement): RequiresPhpunit + { + return new RequiresPhpunit(self::METHOD_LEVEL, $versionRequirement); + } + + /** + * @psalm-param non-empty-string $setting + * @psalm-param non-empty-string $value + */ + public static function requiresSettingOnClass(string $setting, string $value): RequiresSetting + { + return new RequiresSetting(self::CLASS_LEVEL, $setting, $value); + } + + /** + * @psalm-param non-empty-string $setting + * @psalm-param non-empty-string $value + */ + public static function requiresSettingOnMethod(string $setting, string $value): RequiresSetting + { + return new RequiresSetting(self::METHOD_LEVEL, $setting, $value); + } + + public static function runClassInSeparateProcess(): RunClassInSeparateProcess + { + return new RunClassInSeparateProcess(self::CLASS_LEVEL); + } + + public static function runTestsInSeparateProcesses(): RunTestsInSeparateProcesses + { + return new RunTestsInSeparateProcesses(self::CLASS_LEVEL); + } + + public static function runInSeparateProcess(): RunInSeparateProcess + { + return new RunInSeparateProcess(self::METHOD_LEVEL); + } + + public static function test(): Test + { + return new Test(self::METHOD_LEVEL); + } + + /** + * @psalm-param non-empty-string $text + */ + public static function testDoxOnClass(string $text): TestDox + { + return new TestDox(self::CLASS_LEVEL, $text); + } + + /** + * @psalm-param non-empty-string $text + */ + public static function testDoxOnMethod(string $text): TestDox + { + return new TestDox(self::METHOD_LEVEL, $text); + } + + public static function testWith(array $data): TestWith + { + return new TestWith(self::METHOD_LEVEL, $data); + } + + /** + * @psalm-param class-string $className + */ + public static function usesClass(string $className): UsesClass + { + return new UsesClass(self::CLASS_LEVEL, $className); + } + + /** + * @psalm-param non-empty-string $functionName + */ + public static function usesFunction(string $functionName): UsesFunction + { + return new UsesFunction(self::CLASS_LEVEL, $functionName); + } + + /** + * @psalm-param non-empty-string $target + */ + public static function usesOnClass(string $target): Uses + { + return new Uses(self::CLASS_LEVEL, $target); + } + + /** + * @psalm-param non-empty-string $target + */ + public static function usesOnMethod(string $target): Uses + { + return new Uses(self::METHOD_LEVEL, $target); + } + + /** + * @psalm-param class-string $className + */ + public static function usesDefaultClass(string $className): UsesDefaultClass + { + return new UsesDefaultClass(self::CLASS_LEVEL, $className); + } + + public static function withoutErrorHandler(): WithoutErrorHandler + { + return new WithoutErrorHandler(self::METHOD_LEVEL); + } + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level) + { + $this->level = $level; + } + + public function isClassLevel(): bool + { + return $this->level === self::CLASS_LEVEL; + } + + public function isMethodLevel(): bool + { + return $this->level === self::METHOD_LEVEL; + } + + /** + * @psalm-assert-if-true After $this + */ + public function isAfter(): bool + { + return false; + } + + /** + * @psalm-assert-if-true AfterClass $this + */ + public function isAfterClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true BackupGlobals $this + */ + public function isBackupGlobals(): bool + { + return false; + } + + /** + * @psalm-assert-if-true BackupStaticProperties $this + */ + public function isBackupStaticProperties(): bool + { + return false; + } + + /** + * @psalm-assert-if-true BeforeClass $this + */ + public function isBeforeClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Before $this + */ + public function isBefore(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Covers $this + */ + public function isCovers(): bool + { + return false; + } + + /** + * @psalm-assert-if-true CoversClass $this + */ + public function isCoversClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true CoversDefaultClass $this + */ + public function isCoversDefaultClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true CoversFunction $this + */ + public function isCoversFunction(): bool + { + return false; + } + + /** + * @psalm-assert-if-true CoversNothing $this + */ + public function isCoversNothing(): bool + { + return false; + } + + /** + * @psalm-assert-if-true DataProvider $this + */ + public function isDataProvider(): bool + { + return false; + } + + /** + * @psalm-assert-if-true DependsOnClass $this + */ + public function isDependsOnClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true DependsOnMethod $this + */ + public function isDependsOnMethod(): bool + { + return false; + } + + /** + * @psalm-assert-if-true DoesNotPerformAssertions $this + */ + public function isDoesNotPerformAssertions(): bool + { + return false; + } + + /** + * @psalm-assert-if-true ExcludeGlobalVariableFromBackup $this + */ + public function isExcludeGlobalVariableFromBackup(): bool + { + return false; + } + + /** + * @psalm-assert-if-true ExcludeStaticPropertyFromBackup $this + */ + public function isExcludeStaticPropertyFromBackup(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Group $this + */ + public function isGroup(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IgnoreDeprecations $this + */ + public function isIgnoreDeprecations(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IgnoreClassForCodeCoverage $this + */ + public function isIgnoreClassForCodeCoverage(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IgnoreMethodForCodeCoverage $this + */ + public function isIgnoreMethodForCodeCoverage(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IgnoreFunctionForCodeCoverage $this + */ + public function isIgnoreFunctionForCodeCoverage(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RunClassInSeparateProcess $this + */ + public function isRunClassInSeparateProcess(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RunInSeparateProcess $this + */ + public function isRunInSeparateProcess(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RunTestsInSeparateProcesses $this + */ + public function isRunTestsInSeparateProcesses(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Test $this + */ + public function isTest(): bool + { + return false; + } + + /** + * @psalm-assert-if-true PreCondition $this + */ + public function isPreCondition(): bool + { + return false; + } + + /** + * @psalm-assert-if-true PostCondition $this + */ + public function isPostCondition(): bool + { + return false; + } + + /** + * @psalm-assert-if-true PreserveGlobalState $this + */ + public function isPreserveGlobalState(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresMethod $this + */ + public function isRequiresMethod(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresFunction $this + */ + public function isRequiresFunction(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresOperatingSystem $this + */ + public function isRequiresOperatingSystem(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresOperatingSystemFamily $this + */ + public function isRequiresOperatingSystemFamily(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresPhp $this + */ + public function isRequiresPhp(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresPhpExtension $this + */ + public function isRequiresPhpExtension(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresPhpunit $this + */ + public function isRequiresPhpunit(): bool + { + return false; + } + + /** + * @psalm-assert-if-true RequiresSetting $this + */ + public function isRequiresSetting(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TestDox $this + */ + public function isTestDox(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TestWith $this + */ + public function isTestWith(): bool + { + return false; + } + + /** + * @psalm-assert-if-true Uses $this + */ + public function isUses(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UsesClass $this + */ + public function isUsesClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UsesDefaultClass $this + */ + public function isUsesDefaultClass(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UsesFunction $this + */ + public function isUsesFunction(): bool + { + return false; + } + + /** + * @psalm-assert-if-true WithoutErrorHandler $this + */ + public function isWithoutErrorHandler(): bool + { + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollection.php new file mode 100644 index 000000000..d0b965689 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollection.php @@ -0,0 +1,561 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use function array_filter; +use function array_merge; +use function count; +use Countable; +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MetadataCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $metadata; + + /** + * @psalm-param list $metadata + */ + public static function fromArray(array $metadata): self + { + return new self(...$metadata); + } + + private function __construct(Metadata ...$metadata) + { + $this->metadata = $metadata; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->metadata; + } + + public function count(): int + { + return count($this->metadata); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } + + public function isNotEmpty(): bool + { + return $this->count() > 0; + } + + public function getIterator(): MetadataCollectionIterator + { + return new MetadataCollectionIterator($this); + } + + public function mergeWith(self $other): self + { + return new self( + ...array_merge( + $this->asArray(), + $other->asArray(), + ), + ); + } + + public function isClassLevel(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isClassLevel(), + ), + ); + } + + public function isMethodLevel(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isMethodLevel(), + ), + ); + } + + public function isAfter(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isAfter(), + ), + ); + } + + public function isAfterClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isAfterClass(), + ), + ); + } + + public function isBackupGlobals(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isBackupGlobals(), + ), + ); + } + + public function isBackupStaticProperties(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isBackupStaticProperties(), + ), + ); + } + + public function isBeforeClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isBeforeClass(), + ), + ); + } + + public function isBefore(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isBefore(), + ), + ); + } + + public function isCovers(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isCovers(), + ), + ); + } + + public function isCoversClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isCoversClass(), + ), + ); + } + + public function isCoversDefaultClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isCoversDefaultClass(), + ), + ); + } + + public function isCoversFunction(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isCoversFunction(), + ), + ); + } + + public function isExcludeGlobalVariableFromBackup(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isExcludeGlobalVariableFromBackup(), + ), + ); + } + + public function isExcludeStaticPropertyFromBackup(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isExcludeStaticPropertyFromBackup(), + ), + ); + } + + public function isCoversNothing(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isCoversNothing(), + ), + ); + } + + public function isDataProvider(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isDataProvider(), + ), + ); + } + + public function isDepends(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isDependsOnClass() || $metadata->isDependsOnMethod(), + ), + ); + } + + public function isDependsOnClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isDependsOnClass(), + ), + ); + } + + public function isDependsOnMethod(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isDependsOnMethod(), + ), + ); + } + + public function isDoesNotPerformAssertions(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isDoesNotPerformAssertions(), + ), + ); + } + + public function isGroup(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isGroup(), + ), + ); + } + + public function isIgnoreDeprecations(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isIgnoreDeprecations(), + ), + ); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ + public function isIgnoreClassForCodeCoverage(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isIgnoreClassForCodeCoverage(), + ), + ); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ + public function isIgnoreMethodForCodeCoverage(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isIgnoreMethodForCodeCoverage(), + ), + ); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5513 + */ + public function isIgnoreFunctionForCodeCoverage(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isIgnoreFunctionForCodeCoverage(), + ), + ); + } + + public function isRunClassInSeparateProcess(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRunClassInSeparateProcess(), + ), + ); + } + + public function isRunInSeparateProcess(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRunInSeparateProcess(), + ), + ); + } + + public function isRunTestsInSeparateProcesses(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRunTestsInSeparateProcesses(), + ), + ); + } + + public function isTest(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isTest(), + ), + ); + } + + public function isPreCondition(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isPreCondition(), + ), + ); + } + + public function isPostCondition(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isPostCondition(), + ), + ); + } + + public function isPreserveGlobalState(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isPreserveGlobalState(), + ), + ); + } + + public function isRequiresMethod(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresMethod(), + ), + ); + } + + public function isRequiresFunction(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresFunction(), + ), + ); + } + + public function isRequiresOperatingSystem(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresOperatingSystem(), + ), + ); + } + + public function isRequiresOperatingSystemFamily(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresOperatingSystemFamily(), + ), + ); + } + + public function isRequiresPhp(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresPhp(), + ), + ); + } + + public function isRequiresPhpExtension(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresPhpExtension(), + ), + ); + } + + public function isRequiresPhpunit(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresPhpunit(), + ), + ); + } + + public function isRequiresSetting(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isRequiresSetting(), + ), + ); + } + + public function isTestDox(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isTestDox(), + ), + ); + } + + public function isTestWith(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isTestWith(), + ), + ); + } + + public function isUses(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isUses(), + ), + ); + } + + public function isUsesClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isUsesClass(), + ), + ); + } + + public function isUsesDefaultClass(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isUsesDefaultClass(), + ), + ); + } + + public function isUsesFunction(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isUsesFunction(), + ), + ); + } + + public function isWithoutErrorHandler(): self + { + return new self( + ...array_filter( + $this->metadata, + static fn (Metadata $metadata): bool => $metadata->isWithoutErrorHandler(), + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php new file mode 100644 index 000000000..4d4aa57fa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/MetadataCollectionIterator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use function count; +use Iterator; + +/** + * @template-implements Iterator + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class MetadataCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private readonly array $metadata; + private int $position = 0; + + public function __construct(MetadataCollection $metadata) + { + $this->metadata = $metadata->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->metadata); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Metadata + { + return $this->metadata[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php new file mode 100644 index 000000000..c2afdb262 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/DocBlock.php @@ -0,0 +1,267 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Annotation\Parser; + +use function array_filter; +use function array_map; +use function array_merge; +use function array_values; +use function count; +use function preg_match; +use function preg_match_all; +use function preg_replace; +use function preg_split; +use function realpath; +use function substr; +use function trim; +use PharIo\Version\Exception as PharIoVersionException; +use PharIo\Version\VersionConstraintParser; +use PHPUnit\Metadata\AnnotationsAreNotSupportedForInternalClassesException; +use PHPUnit\Metadata\InvalidVersionRequirementException; +use ReflectionClass; +use ReflectionFunctionAbstract; +use ReflectionMethod; + +/** + * This is an abstraction around a PHPUnit-specific docBlock, + * allowing us to ask meaningful questions about a specific + * reflection symbol. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DocBlock +{ + private const REGEX_REQUIRES_VERSION = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[<>=!]{0,2})\s*(?P[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; + private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[\d\t \-.|~^]+)[ \t]*\r?$/m'; + private const REGEX_REQUIRES_OS = '/@requires\s+(?POS(?:FAMILY)?)\s+(?P.+?)[ \t]*\r?$/m'; + private const REGEX_REQUIRES_SETTING = '/@requires\s+(?Psetting)\s+(?P([^ ]+?))\s*(?P[\w\.-]+[\w\.]?)?[ \t]*\r?$/m'; + private const REGEX_REQUIRES = '/@requires\s+(?Pfunction|extension)\s+(?P([^\s<>=!]+))\s*(?P[<>=!]{0,2})\s*(?P[\d\.-]+[\d\.]?)?[ \t]*\r?$/m'; + private readonly string $docComment; + + /** + * @psalm-var array> pre-parsed annotations indexed by name and occurrence index + */ + private readonly array $symbolAnnotations; + + /** + * @psalm-var null|(array{ + * __OFFSET: array&array{__FILE: string}, + * setting?: array, + * extension_versions?: array + * }&array< + * string, + * string|array{version: string, operator: string}|array{constraint: string}|array + * >) + */ + private ?array $parsedRequirements = null; + private readonly int $startLine; + private readonly string $fileName; + + /** + * @throws AnnotationsAreNotSupportedForInternalClassesException + */ + public static function ofClass(ReflectionClass $class): self + { + if ($class->isInternal()) { + throw new AnnotationsAreNotSupportedForInternalClassesException($class->getName()); + } + + return new self( + (string) $class->getDocComment(), + self::extractAnnotationsFromReflector($class), + $class->getStartLine(), + $class->getFileName(), + ); + } + + /** + * @throws AnnotationsAreNotSupportedForInternalClassesException + */ + public static function ofMethod(ReflectionMethod $method): self + { + if ($method->getDeclaringClass()->isInternal()) { + throw new AnnotationsAreNotSupportedForInternalClassesException($method->getDeclaringClass()->getName()); + } + + return new self( + (string) $method->getDocComment(), + self::extractAnnotationsFromReflector($method), + $method->getStartLine(), + $method->getFileName(), + ); + } + + /** + * Note: we do not preserve an instance of the reflection object, since it cannot be safely (de-)serialized. + * + * @param array> $symbolAnnotations + */ + private function __construct(string $docComment, array $symbolAnnotations, int $startLine, string $fileName) + { + $this->docComment = $docComment; + $this->symbolAnnotations = $symbolAnnotations; + $this->startLine = $startLine; + $this->fileName = $fileName; + } + + /** + * @psalm-return array{ + * __OFFSET: array&array{__FILE: string}, + * setting?: array, + * extension_versions?: array + * }&array< + * string, + * string|array{version: string, operator: string}|array{constraint: string}|array + * > + * + * @throws InvalidVersionRequirementException + */ + public function requirements(): array + { + if ($this->parsedRequirements !== null) { + return $this->parsedRequirements; + } + + $offset = $this->startLine; + $requires = []; + $recordedSettings = []; + $extensionVersions = []; + $recordedOffsets = [ + '__FILE' => realpath($this->fileName), + ]; + + // Trim docblock markers, split it into lines and rewind offset to start of docblock + $lines = preg_replace(['#^/\*{2}#', '#\*/$#'], '', preg_split('/\r\n|\r|\n/', $this->docComment)); + $offset -= count($lines); + + foreach ($lines as $line) { + if (preg_match(self::REGEX_REQUIRES_OS, $line, $matches)) { + $requires[$matches['name']] = $matches['value']; + $recordedOffsets[$matches['name']] = $offset; + } + + if (preg_match(self::REGEX_REQUIRES_VERSION, $line, $matches)) { + $requires[$matches['name']] = [ + 'version' => $matches['version'], + 'operator' => $matches['operator'], + ]; + + $recordedOffsets[$matches['name']] = $offset; + } + + if (preg_match(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $line, $matches)) { + if (!empty($requires[$matches['name']])) { + $offset++; + + continue; + } + + try { + $versionConstraintParser = new VersionConstraintParser; + + $requires[$matches['name'] . '_constraint'] = [ + 'constraint' => $versionConstraintParser->parse(trim($matches['constraint'])), + ]; + + $recordedOffsets[$matches['name'] . '_constraint'] = $offset; + } catch (PharIoVersionException $e) { + throw new InvalidVersionRequirementException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } + + if (preg_match(self::REGEX_REQUIRES_SETTING, $line, $matches)) { + $recordedSettings[$matches['setting']] = $matches['value']; + $recordedOffsets['__SETTING_' . $matches['setting']] = $offset; + } + + if (preg_match(self::REGEX_REQUIRES, $line, $matches)) { + $name = $matches['name'] . 's'; + + if (!isset($requires[$name])) { + $requires[$name] = []; + } + + $requires[$name][] = $matches['value']; + $recordedOffsets[$matches['name'] . '_' . $matches['value']] = $offset; + + if ($name === 'extensions' && !empty($matches['version'])) { + $extensionVersions[$matches['value']] = [ + 'version' => $matches['version'], + 'operator' => $matches['operator'], + ]; + } + } + + $offset++; + } + + return $this->parsedRequirements = array_merge( + $requires, + ['__OFFSET' => $recordedOffsets], + array_filter( + [ + 'setting' => $recordedSettings, + 'extension_versions' => $extensionVersions, + ], + ), + ); + } + + public function symbolAnnotations(): array + { + return $this->symbolAnnotations; + } + + /** + * @psalm-return array> + */ + private static function parseDocBlock(string $docBlock): array + { + // Strip away the docblock header and footer to ease parsing of one line annotations + $docBlock = substr($docBlock, 3, -2); + $annotations = []; + + if (preg_match_all('/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?$/m', $docBlock, $matches)) { + $numMatches = count($matches[0]); + + for ($i = 0; $i < $numMatches; $i++) { + $annotations[$matches['name'][$i]][] = $matches['value'][$i]; + } + } + + return $annotations; + } + + private static function extractAnnotationsFromReflector(ReflectionClass|ReflectionFunctionAbstract $reflector): array + { + $annotations = []; + + if ($reflector instanceof ReflectionClass) { + $annotations = array_merge( + $annotations, + ...array_map( + static fn (ReflectionClass $trait): array => self::parseDocBlock((string) $trait->getDocComment()), + array_values($reflector->getTraits()), + ), + ); + } + + return array_merge( + $annotations, + self::parseDocBlock((string) $reflector->getDocComment()), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.php new file mode 100644 index 000000000..51397a700 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Annotation/Registry.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 PHPUnit\Metadata\Annotation\Parser; + +use function array_key_exists; +use PHPUnit\Metadata\AnnotationsAreNotSupportedForInternalClassesException; +use PHPUnit\Metadata\ReflectionException; +use ReflectionClass; +use ReflectionMethod; + +/** + * Reflection information, and therefore DocBlock information, is static within + * a single PHP process. It is therefore okay to use a Singleton registry here. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Registry +{ + private static ?Registry $instance = null; + + /** + * @psalm-var array indexed by class name + */ + private array $classDocBlocks = []; + + /** + * @psalm-var array> indexed by class name and method name + */ + private array $methodDocBlocks = []; + + public static function getInstance(): self + { + return self::$instance ?? self::$instance = new self; + } + + /** + * @psalm-param class-string $class + * + * @throws AnnotationsAreNotSupportedForInternalClassesException + * @throws ReflectionException + */ + public function forClassName(string $class): DocBlock + { + if (array_key_exists($class, $this->classDocBlocks)) { + return $this->classDocBlocks[$class]; + } + + try { + $reflection = new ReflectionClass($class); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + + return $this->classDocBlocks[$class] = DocBlock::ofClass($reflection); + } + + /** + * @psalm-param class-string $classInHierarchy + * + * @throws AnnotationsAreNotSupportedForInternalClassesException + * @throws ReflectionException + */ + public function forMethod(string $classInHierarchy, string $method): DocBlock + { + if (isset($this->methodDocBlocks[$classInHierarchy][$method])) { + return $this->methodDocBlocks[$classInHierarchy][$method]; + } + + try { + $reflection = new ReflectionMethod($classInHierarchy, $method); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + // @codeCoverageIgnoreEnd + + return $this->methodDocBlocks[$classInHierarchy][$method] = DocBlock::ofMethod($reflection); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php new file mode 100644 index 000000000..1d485c727 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AnnotationParser.php @@ -0,0 +1,568 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Parser; + +use function array_merge; +use function assert; +use function class_exists; +use function count; +use function explode; +use function method_exists; +use function preg_replace; +use function rtrim; +use function sprintf; +use function str_contains; +use function str_starts_with; +use function strlen; +use function substr; +use function trim; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Metadata\Annotation\Parser\Registry as AnnotationRegistry; +use PHPUnit\Metadata\AnnotationsAreNotSupportedForInternalClassesException; +use PHPUnit\Metadata\InvalidVersionRequirementException; +use PHPUnit\Metadata\Metadata; +use PHPUnit\Metadata\MetadataCollection; +use PHPUnit\Metadata\ReflectionException; +use PHPUnit\Metadata\Version\ComparisonRequirement; +use PHPUnit\Metadata\Version\ConstraintRequirement; +use PHPUnit\Util\InvalidVersionOperatorException; +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AnnotationParser implements Parser +{ + /** + * @psalm-param class-string $className + * + * @throws AnnotationsAreNotSupportedForInternalClassesException + * @throws InvalidVersionOperatorException + * @throws ReflectionException + */ + public function forClass(string $className): MetadataCollection + { + assert(class_exists($className)); + + $result = []; + + foreach (AnnotationRegistry::getInstance()->forClassName($className)->symbolAnnotations() as $annotation => $values) { + switch ($annotation) { + case 'backupGlobals': + $result[] = Metadata::backupGlobalsOnClass($this->stringToBool($values[0])); + + break; + + case 'backupStaticAttributes': + case 'backupStaticProperties': + $result[] = Metadata::backupStaticPropertiesOnClass($this->stringToBool($values[0])); + + break; + + case 'covers': + foreach ($values as $value) { + $value = $this->cleanUpCoversOrUsesTarget($value); + + $result[] = Metadata::coversOnClass($value); + } + + break; + + case 'coversDefaultClass': + foreach ($values as $value) { + $result[] = Metadata::coversDefaultClass($value); + } + + break; + + case 'coversNothing': + $result[] = Metadata::coversNothingOnClass(); + + break; + + case 'doesNotPerformAssertions': + $result[] = Metadata::doesNotPerformAssertionsOnClass(); + + break; + + case 'group': + case 'ticket': + foreach ($values as $value) { + $result[] = Metadata::groupOnClass($value); + } + + break; + + case 'large': + $result[] = Metadata::groupOnClass('large'); + + break; + + case 'medium': + $result[] = Metadata::groupOnClass('medium'); + + break; + + case 'preserveGlobalState': + $result[] = Metadata::preserveGlobalStateOnClass($this->stringToBool($values[0])); + + break; + + case 'runClassInSeparateProcess': + $result[] = Metadata::runClassInSeparateProcess(); + + break; + + case 'runTestsInSeparateProcesses': + $result[] = Metadata::runTestsInSeparateProcesses(); + + break; + + case 'small': + $result[] = Metadata::groupOnClass('small'); + + break; + + case 'testdox': + $result[] = Metadata::testDoxOnClass($values[0]); + + break; + + case 'uses': + foreach ($values as $value) { + $value = $this->cleanUpCoversOrUsesTarget($value); + + $result[] = Metadata::usesOnClass($value); + } + + break; + + case 'usesDefaultClass': + foreach ($values as $value) { + $result[] = Metadata::usesDefaultClass($value); + } + + break; + } + } + + try { + $result = array_merge( + $result, + $this->parseRequirements( + AnnotationRegistry::getInstance()->forClassName($className)->requirements(), + 'class', + ), + ); + } catch (InvalidVersionRequirementException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Class %s is annotated using an invalid version requirement: %s', + $className, + $e->getMessage(), + ), + ); + } + + return MetadataCollection::fromArray($result); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws AnnotationsAreNotSupportedForInternalClassesException + * @throws InvalidVersionOperatorException + * @throws ReflectionException + */ + public function forMethod(string $className, string $methodName): MetadataCollection + { + assert(class_exists($className)); + assert(method_exists($className, $methodName)); + + $result = []; + + foreach (AnnotationRegistry::getInstance()->forMethod($className, $methodName)->symbolAnnotations() as $annotation => $values) { + switch ($annotation) { + case 'after': + $result[] = Metadata::after(); + + break; + + case 'afterClass': + $result[] = Metadata::afterClass(); + + break; + + case 'backupGlobals': + $result[] = Metadata::backupGlobalsOnMethod($this->stringToBool($values[0])); + + break; + + case 'backupStaticAttributes': + case 'backupStaticProperties': + $result[] = Metadata::backupStaticPropertiesOnMethod($this->stringToBool($values[0])); + + break; + + case 'before': + $result[] = Metadata::before(); + + break; + + case 'beforeClass': + $result[] = Metadata::beforeClass(); + + break; + + case 'covers': + foreach ($values as $value) { + $value = $this->cleanUpCoversOrUsesTarget($value); + + $result[] = Metadata::coversOnMethod($value); + } + + break; + + case 'coversNothing': + $result[] = Metadata::coversNothingOnMethod(); + + break; + + case 'dataProvider': + foreach ($values as $value) { + $value = rtrim($value, " ()\n\r\t\v\x00"); + + if (str_contains($value, '::')) { + $result[] = Metadata::dataProvider(...explode('::', $value)); + + continue; + } + + $result[] = Metadata::dataProvider($className, $value); + } + + break; + + case 'depends': + foreach ($values as $value) { + $deepClone = false; + $shallowClone = false; + + if (str_starts_with($value, 'clone ')) { + $deepClone = true; + $value = substr($value, strlen('clone ')); + } elseif (str_starts_with($value, '!clone ')) { + $value = substr($value, strlen('!clone ')); + } elseif (str_starts_with($value, 'shallowClone ')) { + $shallowClone = true; + $value = substr($value, strlen('shallowClone ')); + } elseif (str_starts_with($value, '!shallowClone ')) { + $value = substr($value, strlen('!shallowClone ')); + } + + if (str_contains($value, '::')) { + [$_className, $_methodName] = explode('::', $value); + + assert($_className !== ''); + assert($_methodName !== ''); + + if ($_methodName === 'class') { + $result[] = Metadata::dependsOnClass($_className, $deepClone, $shallowClone); + + continue; + } + + $result[] = Metadata::dependsOnMethod($_className, $_methodName, $deepClone, $shallowClone); + + continue; + } + + $result[] = Metadata::dependsOnMethod($className, $value, $deepClone, $shallowClone); + } + + break; + + case 'doesNotPerformAssertions': + $result[] = Metadata::doesNotPerformAssertionsOnMethod(); + + break; + + case 'excludeGlobalVariableFromBackup': + foreach ($values as $value) { + $result[] = Metadata::excludeGlobalVariableFromBackupOnMethod($value); + } + + break; + + case 'excludeStaticPropertyFromBackup': + foreach ($values as $value) { + $tmp = explode(' ', $value); + + if (count($tmp) !== 2) { + continue; + } + + $result[] = Metadata::excludeStaticPropertyFromBackupOnMethod( + trim($tmp[0]), + trim($tmp[1]), + ); + } + + break; + + case 'group': + case 'ticket': + foreach ($values as $value) { + $result[] = Metadata::groupOnMethod($value); + } + + break; + + case 'large': + $result[] = Metadata::groupOnMethod('large'); + + break; + + case 'medium': + $result[] = Metadata::groupOnMethod('medium'); + + break; + + case 'postCondition': + $result[] = Metadata::postCondition(); + + break; + + case 'preCondition': + $result[] = Metadata::preCondition(); + + break; + + case 'preserveGlobalState': + $result[] = Metadata::preserveGlobalStateOnMethod($this->stringToBool($values[0])); + + break; + + case 'runInSeparateProcess': + $result[] = Metadata::runInSeparateProcess(); + + break; + + case 'small': + $result[] = Metadata::groupOnMethod('small'); + + break; + + case 'test': + $result[] = Metadata::test(); + + break; + + case 'testdox': + $result[] = Metadata::testDoxOnMethod($values[0]); + + break; + + case 'uses': + foreach ($values as $value) { + $value = $this->cleanUpCoversOrUsesTarget($value); + + $result[] = Metadata::usesOnMethod($value); + } + + break; + } + } + + if (method_exists($className, $methodName)) { + try { + $result = array_merge( + $result, + $this->parseRequirements( + AnnotationRegistry::getInstance()->forMethod($className, $methodName)->requirements(), + 'method', + ), + ); + } catch (InvalidVersionRequirementException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Method %s::%s is annotated using an invalid version requirement: %s', + $className, + $methodName, + $e->getMessage(), + ), + ); + } + } + + return MetadataCollection::fromArray($result); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @throws AnnotationsAreNotSupportedForInternalClassesException + * @throws InvalidVersionOperatorException + * @throws ReflectionException + */ + public function forClassAndMethod(string $className, string $methodName): MetadataCollection + { + return $this->forClass($className)->mergeWith( + $this->forMethod($className, $methodName), + ); + } + + private function stringToBool(string $value): bool + { + if ($value === 'enabled') { + return true; + } + + return false; + } + + private function cleanUpCoversOrUsesTarget(string $value): string + { + $value = preg_replace('/[\s()]+$/', '', $value); + + return explode(' ', $value, 2)[0]; + } + + /** + * @psalm-return list + * + * @throws InvalidVersionOperatorException + */ + private function parseRequirements(array $requirements, string $level): array + { + $result = []; + + if (!empty($requirements['PHP'])) { + $versionRequirement = new ComparisonRequirement( + $requirements['PHP']['version'], + new VersionComparisonOperator(empty($requirements['PHP']['operator']) ? '>=' : $requirements['PHP']['operator']), + ); + + if ($level === 'class') { + $result[] = Metadata::requiresPhpOnClass($versionRequirement); + } else { + $result[] = Metadata::requiresPhpOnMethod($versionRequirement); + } + } elseif (!empty($requirements['PHP_constraint'])) { + $versionRequirement = new ConstraintRequirement($requirements['PHP_constraint']['constraint']); + + if ($level === 'class') { + $result[] = Metadata::requiresPhpOnClass($versionRequirement); + } else { + $result[] = Metadata::requiresPhpOnMethod($versionRequirement); + } + } + + if (!empty($requirements['extensions'])) { + foreach ($requirements['extensions'] as $extension) { + if (isset($requirements['extension_versions'][$extension])) { + continue; + } + + if ($level === 'class') { + $result[] = Metadata::requiresPhpExtensionOnClass($extension, null); + } else { + $result[] = Metadata::requiresPhpExtensionOnMethod($extension, null); + } + } + } + + if (!empty($requirements['extension_versions'])) { + foreach ($requirements['extension_versions'] as $extension => $version) { + $versionRequirement = new ComparisonRequirement( + $version['version'], + new VersionComparisonOperator(empty($version['operator']) ? '>=' : $version['operator']), + ); + + if ($level === 'class') { + $result[] = Metadata::requiresPhpExtensionOnClass($extension, $versionRequirement); + } else { + $result[] = Metadata::requiresPhpExtensionOnMethod($extension, $versionRequirement); + } + } + } + + if (!empty($requirements['PHPUnit'])) { + $versionRequirement = new ComparisonRequirement( + $requirements['PHPUnit']['version'], + new VersionComparisonOperator(empty($requirements['PHPUnit']['operator']) ? '>=' : $requirements['PHPUnit']['operator']), + ); + + if ($level === 'class') { + $result[] = Metadata::requiresPhpunitOnClass($versionRequirement); + } else { + $result[] = Metadata::requiresPhpunitOnMethod($versionRequirement); + } + } elseif (!empty($requirements['PHPUnit_constraint'])) { + $versionRequirement = new ConstraintRequirement($requirements['PHPUnit_constraint']['constraint']); + + if ($level === 'class') { + $result[] = Metadata::requiresPhpunitOnClass($versionRequirement); + } else { + $result[] = Metadata::requiresPhpunitOnMethod($versionRequirement); + } + } + + if (!empty($requirements['OSFAMILY'])) { + if ($level === 'class') { + $result[] = Metadata::requiresOperatingSystemFamilyOnClass($requirements['OSFAMILY']); + } else { + $result[] = Metadata::requiresOperatingSystemFamilyOnMethod($requirements['OSFAMILY']); + } + } + + if (!empty($requirements['OS'])) { + if ($level === 'class') { + $result[] = Metadata::requiresOperatingSystemOnClass($requirements['OS']); + } else { + $result[] = Metadata::requiresOperatingSystemOnMethod($requirements['OS']); + } + } + + if (!empty($requirements['functions'])) { + foreach ($requirements['functions'] as $function) { + $pieces = explode('::', $function); + + if (count($pieces) === 2) { + if ($level === 'class') { + $result[] = Metadata::requiresMethodOnClass($pieces[0], $pieces[1]); + } else { + $result[] = Metadata::requiresMethodOnMethod($pieces[0], $pieces[1]); + } + } elseif ($level === 'class') { + $result[] = Metadata::requiresFunctionOnClass($function); + } else { + $result[] = Metadata::requiresFunctionOnMethod($function); + } + } + } + + if (!empty($requirements['setting'])) { + foreach ($requirements['setting'] as $setting => $value) { + if ($level === 'class') { + $result[] = Metadata::requiresSettingOnClass($setting, $value); + } else { + $result[] = Metadata::requiresSettingOnMethod($setting, $value); + } + } + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php new file mode 100644 index 000000000..9a19f89a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/AttributeParser.php @@ -0,0 +1,674 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Parser; + +use const JSON_THROW_ON_ERROR; +use function assert; +use function class_exists; +use function json_decode; +use function method_exists; +use function str_starts_with; +use PHPUnit\Framework\Attributes\After; +use PHPUnit\Framework\Attributes\AfterClass; +use PHPUnit\Framework\Attributes\BackupGlobals; +use PHPUnit\Framework\Attributes\BackupStaticProperties; +use PHPUnit\Framework\Attributes\Before; +use PHPUnit\Framework\Attributes\BeforeClass; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\CoversFunction; +use PHPUnit\Framework\Attributes\CoversNothing; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\DataProviderExternal; +use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\DependsExternal; +use PHPUnit\Framework\Attributes\DependsExternalUsingDeepClone; +use PHPUnit\Framework\Attributes\DependsExternalUsingShallowClone; +use PHPUnit\Framework\Attributes\DependsOnClass; +use PHPUnit\Framework\Attributes\DependsOnClassUsingDeepClone; +use PHPUnit\Framework\Attributes\DependsOnClassUsingShallowClone; +use PHPUnit\Framework\Attributes\DependsUsingDeepClone; +use PHPUnit\Framework\Attributes\DependsUsingShallowClone; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; +use PHPUnit\Framework\Attributes\ExcludeGlobalVariableFromBackup; +use PHPUnit\Framework\Attributes\ExcludeStaticPropertyFromBackup; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\IgnoreClassForCodeCoverage; +use PHPUnit\Framework\Attributes\IgnoreDeprecations; +use PHPUnit\Framework\Attributes\IgnoreFunctionForCodeCoverage; +use PHPUnit\Framework\Attributes\IgnoreMethodForCodeCoverage; +use PHPUnit\Framework\Attributes\Large; +use PHPUnit\Framework\Attributes\Medium; +use PHPUnit\Framework\Attributes\PostCondition; +use PHPUnit\Framework\Attributes\PreCondition; +use PHPUnit\Framework\Attributes\PreserveGlobalState; +use PHPUnit\Framework\Attributes\RequiresFunction; +use PHPUnit\Framework\Attributes\RequiresMethod; +use PHPUnit\Framework\Attributes\RequiresOperatingSystem; +use PHPUnit\Framework\Attributes\RequiresOperatingSystemFamily; +use PHPUnit\Framework\Attributes\RequiresPhp; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; +use PHPUnit\Framework\Attributes\RequiresPhpunit; +use PHPUnit\Framework\Attributes\RequiresSetting; +use PHPUnit\Framework\Attributes\RunClassInSeparateProcess; +use PHPUnit\Framework\Attributes\RunInSeparateProcess; +use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses; +use PHPUnit\Framework\Attributes\Small; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\Attributes\TestDox; +use PHPUnit\Framework\Attributes\TestWith; +use PHPUnit\Framework\Attributes\TestWithJson; +use PHPUnit\Framework\Attributes\Ticket; +use PHPUnit\Framework\Attributes\UsesClass; +use PHPUnit\Framework\Attributes\UsesFunction; +use PHPUnit\Framework\Attributes\WithoutErrorHandler; +use PHPUnit\Metadata\Metadata; +use PHPUnit\Metadata\MetadataCollection; +use PHPUnit\Metadata\Version\ConstraintRequirement; +use ReflectionClass; +use ReflectionMethod; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AttributeParser implements Parser +{ + /** + * @psalm-param class-string $className + */ + public function forClass(string $className): MetadataCollection + { + assert(class_exists($className)); + + $result = []; + + foreach ((new ReflectionClass($className))->getAttributes() as $attribute) { + if (!str_starts_with($attribute->getName(), 'PHPUnit\\Framework\\Attributes\\')) { + continue; + } + + if (!class_exists($attribute->getName())) { + continue; + } + + $attributeInstance = $attribute->newInstance(); + + switch ($attribute->getName()) { + case BackupGlobals::class: + assert($attributeInstance instanceof BackupGlobals); + + $result[] = Metadata::backupGlobalsOnClass($attributeInstance->enabled()); + + break; + + case BackupStaticProperties::class: + assert($attributeInstance instanceof BackupStaticProperties); + + $result[] = Metadata::backupStaticPropertiesOnClass($attributeInstance->enabled()); + + break; + + case CoversClass::class: + assert($attributeInstance instanceof CoversClass); + + $result[] = Metadata::coversClass($attributeInstance->className()); + + break; + + case CoversFunction::class: + assert($attributeInstance instanceof CoversFunction); + + $result[] = Metadata::coversFunction($attributeInstance->functionName()); + + break; + + case CoversNothing::class: + $result[] = Metadata::coversNothingOnClass(); + + break; + + case DoesNotPerformAssertions::class: + $result[] = Metadata::doesNotPerformAssertionsOnClass(); + + break; + + case ExcludeGlobalVariableFromBackup::class: + assert($attributeInstance instanceof ExcludeGlobalVariableFromBackup); + + $result[] = Metadata::excludeGlobalVariableFromBackupOnClass($attributeInstance->globalVariableName()); + + break; + + case ExcludeStaticPropertyFromBackup::class: + assert($attributeInstance instanceof ExcludeStaticPropertyFromBackup); + + $result[] = Metadata::excludeStaticPropertyFromBackupOnClass( + $attributeInstance->className(), + $attributeInstance->propertyName(), + ); + + break; + + case Group::class: + assert($attributeInstance instanceof Group); + + $result[] = Metadata::groupOnClass($attributeInstance->name()); + + break; + + case Large::class: + $result[] = Metadata::groupOnClass('large'); + + break; + + case Medium::class: + $result[] = Metadata::groupOnClass('medium'); + + break; + + case IgnoreClassForCodeCoverage::class: + assert($attributeInstance instanceof IgnoreClassForCodeCoverage); + + $result[] = Metadata::ignoreClassForCodeCoverage($attributeInstance->className()); + + break; + + case IgnoreDeprecations::class: + assert($attributeInstance instanceof IgnoreDeprecations); + + $result[] = Metadata::ignoreDeprecationsOnClass(); + + break; + + case IgnoreMethodForCodeCoverage::class: + assert($attributeInstance instanceof IgnoreMethodForCodeCoverage); + + $result[] = Metadata::ignoreMethodForCodeCoverage($attributeInstance->className(), $attributeInstance->methodName()); + + break; + + case IgnoreFunctionForCodeCoverage::class: + assert($attributeInstance instanceof IgnoreFunctionForCodeCoverage); + + $result[] = Metadata::ignoreFunctionForCodeCoverage($attributeInstance->functionName()); + + break; + + case PreserveGlobalState::class: + assert($attributeInstance instanceof PreserveGlobalState); + + $result[] = Metadata::preserveGlobalStateOnClass($attributeInstance->enabled()); + + break; + + case RequiresMethod::class: + assert($attributeInstance instanceof RequiresMethod); + + $result[] = Metadata::requiresMethodOnClass( + $attributeInstance->className(), + $attributeInstance->methodName(), + ); + + break; + + case RequiresFunction::class: + assert($attributeInstance instanceof RequiresFunction); + + $result[] = Metadata::requiresFunctionOnClass($attributeInstance->functionName()); + + break; + + case RequiresOperatingSystem::class: + assert($attributeInstance instanceof RequiresOperatingSystem); + + $result[] = Metadata::requiresOperatingSystemOnClass($attributeInstance->regularExpression()); + + break; + + case RequiresOperatingSystemFamily::class: + assert($attributeInstance instanceof RequiresOperatingSystemFamily); + + $result[] = Metadata::requiresOperatingSystemFamilyOnClass($attributeInstance->operatingSystemFamily()); + + break; + + case RequiresPhp::class: + assert($attributeInstance instanceof RequiresPhp); + + $result[] = Metadata::requiresPhpOnClass( + ConstraintRequirement::from( + $attributeInstance->versionRequirement(), + ), + ); + + break; + + case RequiresPhpExtension::class: + assert($attributeInstance instanceof RequiresPhpExtension); + + $versionConstraint = null; + $versionRequirement = $attributeInstance->versionRequirement(); + + if ($versionRequirement !== null) { + $versionConstraint = ConstraintRequirement::from($versionRequirement); + } + + $result[] = Metadata::requiresPhpExtensionOnClass( + $attributeInstance->extension(), + $versionConstraint, + ); + + break; + + case RequiresPhpunit::class: + assert($attributeInstance instanceof RequiresPhpunit); + + $result[] = Metadata::requiresPhpunitOnClass( + ConstraintRequirement::from( + $attributeInstance->versionRequirement(), + ), + ); + + break; + + case RequiresSetting::class: + assert($attributeInstance instanceof RequiresSetting); + + $result[] = Metadata::requiresSettingOnClass( + $attributeInstance->setting(), + $attributeInstance->value(), + ); + + break; + + case RunClassInSeparateProcess::class: + $result[] = Metadata::runClassInSeparateProcess(); + + break; + + case RunTestsInSeparateProcesses::class: + $result[] = Metadata::runTestsInSeparateProcesses(); + + break; + + case Small::class: + $result[] = Metadata::groupOnClass('small'); + + break; + + case TestDox::class: + assert($attributeInstance instanceof TestDox); + + $result[] = Metadata::testDoxOnClass($attributeInstance->text()); + + break; + + case Ticket::class: + assert($attributeInstance instanceof Ticket); + + $result[] = Metadata::groupOnClass($attributeInstance->text()); + + break; + + case UsesClass::class: + assert($attributeInstance instanceof UsesClass); + + $result[] = Metadata::usesClass($attributeInstance->className()); + + break; + + case UsesFunction::class: + assert($attributeInstance instanceof UsesFunction); + + $result[] = Metadata::usesFunction($attributeInstance->functionName()); + + break; + } + } + + return MetadataCollection::fromArray($result); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forMethod(string $className, string $methodName): MetadataCollection + { + assert(class_exists($className)); + assert(method_exists($className, $methodName)); + + $result = []; + + foreach ((new ReflectionMethod($className, $methodName))->getAttributes() as $attribute) { + if (!str_starts_with($attribute->getName(), 'PHPUnit\\Framework\\Attributes\\')) { + continue; + } + + if (!class_exists($attribute->getName())) { + continue; + } + + $attributeInstance = $attribute->newInstance(); + + switch ($attribute->getName()) { + case After::class: + $result[] = Metadata::after(); + + break; + + case AfterClass::class: + $result[] = Metadata::afterClass(); + + break; + + case BackupGlobals::class: + assert($attributeInstance instanceof BackupGlobals); + + $result[] = Metadata::backupGlobalsOnMethod($attributeInstance->enabled()); + + break; + + case BackupStaticProperties::class: + assert($attributeInstance instanceof BackupStaticProperties); + + $result[] = Metadata::backupStaticPropertiesOnMethod($attributeInstance->enabled()); + + break; + + case Before::class: + $result[] = Metadata::before(); + + break; + + case BeforeClass::class: + $result[] = Metadata::beforeClass(); + + break; + + case CoversNothing::class: + $result[] = Metadata::coversNothingOnMethod(); + + break; + + case DataProvider::class: + assert($attributeInstance instanceof DataProvider); + + $result[] = Metadata::dataProvider($className, $attributeInstance->methodName()); + + break; + + case DataProviderExternal::class: + assert($attributeInstance instanceof DataProviderExternal); + + $result[] = Metadata::dataProvider($attributeInstance->className(), $attributeInstance->methodName()); + + break; + + case Depends::class: + assert($attributeInstance instanceof Depends); + + $result[] = Metadata::dependsOnMethod($className, $attributeInstance->methodName(), false, false); + + break; + + case DependsUsingDeepClone::class: + assert($attributeInstance instanceof DependsUsingDeepClone); + + $result[] = Metadata::dependsOnMethod($className, $attributeInstance->methodName(), true, false); + + break; + + case DependsUsingShallowClone::class: + assert($attributeInstance instanceof DependsUsingShallowClone); + + $result[] = Metadata::dependsOnMethod($className, $attributeInstance->methodName(), false, true); + + break; + + case DependsExternal::class: + assert($attributeInstance instanceof DependsExternal); + + $result[] = Metadata::dependsOnMethod($attributeInstance->className(), $attributeInstance->methodName(), false, false); + + break; + + case DependsExternalUsingDeepClone::class: + assert($attributeInstance instanceof DependsExternalUsingDeepClone); + + $result[] = Metadata::dependsOnMethod($attributeInstance->className(), $attributeInstance->methodName(), true, false); + + break; + + case DependsExternalUsingShallowClone::class: + assert($attributeInstance instanceof DependsExternalUsingShallowClone); + + $result[] = Metadata::dependsOnMethod($attributeInstance->className(), $attributeInstance->methodName(), false, true); + + break; + + case DependsOnClass::class: + assert($attributeInstance instanceof DependsOnClass); + + $result[] = Metadata::dependsOnClass($attributeInstance->className(), false, false); + + break; + + case DependsOnClassUsingDeepClone::class: + assert($attributeInstance instanceof DependsOnClassUsingDeepClone); + + $result[] = Metadata::dependsOnClass($attributeInstance->className(), true, false); + + break; + + case DependsOnClassUsingShallowClone::class: + assert($attributeInstance instanceof DependsOnClassUsingShallowClone); + + $result[] = Metadata::dependsOnClass($attributeInstance->className(), false, true); + + break; + + case DoesNotPerformAssertions::class: + assert($attributeInstance instanceof DoesNotPerformAssertions); + + $result[] = Metadata::doesNotPerformAssertionsOnMethod(); + + break; + + case ExcludeGlobalVariableFromBackup::class: + assert($attributeInstance instanceof ExcludeGlobalVariableFromBackup); + + $result[] = Metadata::excludeGlobalVariableFromBackupOnMethod($attributeInstance->globalVariableName()); + + break; + + case ExcludeStaticPropertyFromBackup::class: + assert($attributeInstance instanceof ExcludeStaticPropertyFromBackup); + + $result[] = Metadata::excludeStaticPropertyFromBackupOnMethod( + $attributeInstance->className(), + $attributeInstance->propertyName(), + ); + + break; + + case Group::class: + assert($attributeInstance instanceof Group); + + $result[] = Metadata::groupOnMethod($attributeInstance->name()); + + break; + + case IgnoreDeprecations::class: + assert($attributeInstance instanceof IgnoreDeprecations); + + $result[] = Metadata::ignoreDeprecationsOnMethod(); + + break; + + case PostCondition::class: + $result[] = Metadata::postCondition(); + + break; + + case PreCondition::class: + $result[] = Metadata::preCondition(); + + break; + + case PreserveGlobalState::class: + assert($attributeInstance instanceof PreserveGlobalState); + + $result[] = Metadata::preserveGlobalStateOnMethod($attributeInstance->enabled()); + + break; + + case RequiresMethod::class: + assert($attributeInstance instanceof RequiresMethod); + + $result[] = Metadata::requiresMethodOnMethod( + $attributeInstance->className(), + $attributeInstance->methodName(), + ); + + break; + + case RequiresFunction::class: + assert($attributeInstance instanceof RequiresFunction); + + $result[] = Metadata::requiresFunctionOnMethod($attributeInstance->functionName()); + + break; + + case RequiresOperatingSystem::class: + assert($attributeInstance instanceof RequiresOperatingSystem); + + $result[] = Metadata::requiresOperatingSystemOnMethod($attributeInstance->regularExpression()); + + break; + + case RequiresOperatingSystemFamily::class: + assert($attributeInstance instanceof RequiresOperatingSystemFamily); + + $result[] = Metadata::requiresOperatingSystemFamilyOnMethod($attributeInstance->operatingSystemFamily()); + + break; + + case RequiresPhp::class: + assert($attributeInstance instanceof RequiresPhp); + + $result[] = Metadata::requiresPhpOnMethod( + ConstraintRequirement::from( + $attributeInstance->versionRequirement(), + ), + ); + + break; + + case RequiresPhpExtension::class: + assert($attributeInstance instanceof RequiresPhpExtension); + + $versionConstraint = null; + $versionRequirement = $attributeInstance->versionRequirement(); + + if ($versionRequirement !== null) { + $versionConstraint = ConstraintRequirement::from($versionRequirement); + } + + $result[] = Metadata::requiresPhpExtensionOnMethod( + $attributeInstance->extension(), + $versionConstraint, + ); + + break; + + case RequiresPhpunit::class: + assert($attributeInstance instanceof RequiresPhpunit); + + $result[] = Metadata::requiresPhpunitOnMethod( + ConstraintRequirement::from( + $attributeInstance->versionRequirement(), + ), + ); + + break; + + case RequiresSetting::class: + assert($attributeInstance instanceof RequiresSetting); + + $result[] = Metadata::requiresSettingOnMethod( + $attributeInstance->setting(), + $attributeInstance->value(), + ); + + break; + + case RunInSeparateProcess::class: + $result[] = Metadata::runInSeparateProcess(); + + break; + + case Test::class: + $result[] = Metadata::test(); + + break; + + case TestDox::class: + assert($attributeInstance instanceof TestDox); + + $result[] = Metadata::testDoxOnMethod($attributeInstance->text()); + + break; + + case TestWith::class: + assert($attributeInstance instanceof TestWith); + + $result[] = Metadata::testWith($attributeInstance->data()); + + break; + + case TestWithJson::class: + assert($attributeInstance instanceof TestWithJson); + + $result[] = Metadata::testWith(json_decode($attributeInstance->json(), true, 512, JSON_THROW_ON_ERROR)); + + break; + + case Ticket::class: + assert($attributeInstance instanceof Ticket); + + $result[] = Metadata::groupOnMethod($attributeInstance->text()); + + break; + + case WithoutErrorHandler::class: + assert($attributeInstance instanceof WithoutErrorHandler); + + $result[] = Metadata::withoutErrorHandler(); + + break; + } + } + + return MetadataCollection::fromArray($result); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forClassAndMethod(string $className, string $methodName): MetadataCollection + { + return $this->forClass($className)->mergeWith( + $this->forMethod($className, $methodName), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/CachingParser.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/CachingParser.php new file mode 100644 index 000000000..a383006f9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/CachingParser.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Parser; + +use function assert; +use function class_exists; +use function method_exists; +use PHPUnit\Metadata\MetadataCollection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CachingParser implements Parser +{ + private readonly Parser $reader; + private array $classCache = []; + private array $methodCache = []; + private array $classAndMethodCache = []; + + public function __construct(Parser $reader) + { + $this->reader = $reader; + } + + /** + * @psalm-param class-string $className + */ + public function forClass(string $className): MetadataCollection + { + assert(class_exists($className)); + + if (isset($this->classCache[$className])) { + return $this->classCache[$className]; + } + + $this->classCache[$className] = $this->reader->forClass($className); + + return $this->classCache[$className]; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forMethod(string $className, string $methodName): MetadataCollection + { + assert(class_exists($className)); + assert(method_exists($className, $methodName)); + + $key = $className . '::' . $methodName; + + if (isset($this->methodCache[$key])) { + return $this->methodCache[$key]; + } + + $this->methodCache[$key] = $this->reader->forMethod($className, $methodName); + + return $this->methodCache[$key]; + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forClassAndMethod(string $className, string $methodName): MetadataCollection + { + $key = $className . '::' . $methodName; + + if (isset($this->classAndMethodCache[$key])) { + return $this->classAndMethodCache[$key]; + } + + $this->classAndMethodCache[$key] = $this->forClass($className)->mergeWith( + $this->forMethod($className, $methodName), + ); + + return $this->classAndMethodCache[$key]; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Parser.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Parser.php new file mode 100644 index 000000000..2af9191d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Parser.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Parser; + +use PHPUnit\Metadata\MetadataCollection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Parser +{ + /** + * @psalm-param class-string $className + */ + public function forClass(string $className): MetadataCollection; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forMethod(string $className, string $methodName): MetadataCollection; + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forClassAndMethod(string $className, string $methodName): MetadataCollection; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/ParserChain.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/ParserChain.php new file mode 100644 index 000000000..89d69dcec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/ParserChain.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Parser; + +use function assert; +use function class_exists; +use function method_exists; +use PHPUnit\Metadata\MetadataCollection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ParserChain implements Parser +{ + private readonly Parser $attributeReader; + private readonly Parser $annotationReader; + + public function __construct(Parser $attributeReader, Parser $annotationReader) + { + $this->attributeReader = $attributeReader; + $this->annotationReader = $annotationReader; + } + + /** + * @psalm-param class-string $className + */ + public function forClass(string $className): MetadataCollection + { + assert(class_exists($className)); + + $metadata = $this->attributeReader->forClass($className); + + if (!$metadata->isEmpty()) { + return $metadata; + } + + return $this->annotationReader->forClass($className); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forMethod(string $className, string $methodName): MetadataCollection + { + assert(class_exists($className)); + assert(method_exists($className, $methodName)); + + $metadata = $this->attributeReader->forMethod($className, $methodName); + + if (!$metadata->isEmpty()) { + return $metadata; + } + + return $this->annotationReader->forMethod($className, $methodName); + } + + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + public function forClassAndMethod(string $className, string $methodName): MetadataCollection + { + return $this->forClass($className)->mergeWith( + $this->forMethod($className, $methodName), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Registry.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Registry.php new file mode 100644 index 000000000..a68ab0148 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Parser/Registry.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Parser; + +/** + * Attribute and annotation information is static within a single PHP process. + * It is therefore okay to use a Singleton registry here. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Registry +{ + private static ?Parser $instance = null; + + public static function parser(): Parser + { + return self::$instance ?? self::$instance = self::build(); + } + + private static function build(): Parser + { + return new CachingParser( + new ParserChain( + new AttributeParser, + new AnnotationParser, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PostCondition.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PostCondition.php new file mode 100644 index 000000000..1e30f550f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PostCondition.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PostCondition extends Metadata +{ + /** + * @psalm-assert-if-true PostCondition $this + */ + public function isPostCondition(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreCondition.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreCondition.php new file mode 100644 index 000000000..4691f113d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreCondition.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PreCondition extends Metadata +{ + /** + * @psalm-assert-if-true PreCondition $this + */ + public function isPreCondition(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreserveGlobalState.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreserveGlobalState.php new file mode 100644 index 000000000..521af6d63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/PreserveGlobalState.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class PreserveGlobalState extends Metadata +{ + private readonly bool $enabled; + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level, bool $enabled) + { + parent::__construct($level); + + $this->enabled = $enabled; + } + + /** + * @psalm-assert-if-true PreserveGlobalState $this + */ + public function isPreserveGlobalState(): bool + { + return true; + } + + public function enabled(): bool + { + return $this->enabled; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresFunction.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresFunction.php new file mode 100644 index 000000000..638d35c07 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresFunction.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresFunction extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $functionName + */ + protected function __construct(int $level, string $functionName) + { + parent::__construct($level); + + $this->functionName = $functionName; + } + + /** + * @psalm-assert-if-true RequiresFunction $this + */ + public function isRequiresFunction(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresMethod.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresMethod.php new file mode 100644 index 000000000..45d611ffa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresMethod.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresMethod extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var non-empty-string + */ + private readonly string $methodName; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + */ + protected function __construct(int $level, string $className, string $methodName) + { + parent::__construct($level); + + $this->className = $className; + $this->methodName = $methodName; + } + + /** + * @psalm-assert-if-true RequiresMethod $this + */ + public function isRequiresMethod(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return non-empty-string + */ + public function methodName(): string + { + return $this->methodName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php new file mode 100644 index 000000000..a2b0de4f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystem.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresOperatingSystem extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $operatingSystem; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $operatingSystem + */ + public function __construct(int $level, string $operatingSystem) + { + parent::__construct($level); + + $this->operatingSystem = $operatingSystem; + } + + /** + * @psalm-assert-if-true RequiresOperatingSystem $this + */ + public function isRequiresOperatingSystem(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function operatingSystem(): string + { + return $this->operatingSystem; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php new file mode 100644 index 000000000..841827480 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresOperatingSystemFamily.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresOperatingSystemFamily extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $operatingSystemFamily; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $operatingSystemFamily + */ + protected function __construct(int $level, string $operatingSystemFamily) + { + parent::__construct($level); + + $this->operatingSystemFamily = $operatingSystemFamily; + } + + /** + * @psalm-assert-if-true RequiresOperatingSystemFamily $this + */ + public function isRequiresOperatingSystemFamily(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function operatingSystemFamily(): string + { + return $this->operatingSystemFamily; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhp.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhp.php new file mode 100644 index 000000000..e73bfb402 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhp.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use PHPUnit\Metadata\Version\Requirement; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresPhp extends Metadata +{ + private readonly Requirement $versionRequirement; + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level, Requirement $versionRequirement) + { + parent::__construct($level); + + $this->versionRequirement = $versionRequirement; + } + + /** + * @psalm-assert-if-true RequiresPhp $this + */ + public function isRequiresPhp(): bool + { + return true; + } + + public function versionRequirement(): Requirement + { + return $this->versionRequirement; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php new file mode 100644 index 000000000..053b89665 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpExtension.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use PHPUnit\Metadata\Version\Requirement; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresPhpExtension extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $extension; + private readonly ?Requirement $versionRequirement; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $extension + */ + protected function __construct(int $level, string $extension, ?Requirement $versionRequirement) + { + parent::__construct($level); + + $this->extension = $extension; + $this->versionRequirement = $versionRequirement; + } + + /** + * @psalm-assert-if-true RequiresPhpExtension $this + */ + public function isRequiresPhpExtension(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function extension(): string + { + return $this->extension; + } + + /** + * @psalm-assert-if-true !null $this->versionRequirement + */ + public function hasVersionRequirement(): bool + { + return $this->versionRequirement !== null; + } + + /** + * @throws NoVersionRequirementException + */ + public function versionRequirement(): Requirement + { + if ($this->versionRequirement === null) { + throw new NoVersionRequirementException; + } + + return $this->versionRequirement; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpunit.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpunit.php new file mode 100644 index 000000000..250190e58 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresPhpunit.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +use PHPUnit\Metadata\Version\Requirement; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresPhpunit extends Metadata +{ + private readonly Requirement $versionRequirement; + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level, Requirement $versionRequirement) + { + parent::__construct($level); + + $this->versionRequirement = $versionRequirement; + } + + /** + * @psalm-assert-if-true RequiresPhpunit $this + */ + public function isRequiresPhpunit(): bool + { + return true; + } + + public function versionRequirement(): Requirement + { + return $this->versionRequirement; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresSetting.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresSetting.php new file mode 100644 index 000000000..03f710d71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RequiresSetting.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RequiresSetting extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $setting; + + /** + * @psalm-var non-empty-string + */ + private readonly string $value; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $setting + * @psalm-param non-empty-string $value + */ + protected function __construct(int $level, string $setting, string $value) + { + parent::__construct($level); + + $this->setting = $setting; + $this->value = $value; + } + + /** + * @psalm-assert-if-true RequiresSetting $this + */ + public function isRequiresSetting(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function setting(): string + { + return $this->setting; + } + + /** + * @psalm-return non-empty-string + */ + public function value(): string + { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php new file mode 100644 index 000000000..eb0b7742f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunClassInSeparateProcess.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RunClassInSeparateProcess extends Metadata +{ + /** + * @psalm-assert-if-true RunClassInSeparateProcess $this + */ + public function isRunClassInSeparateProcess(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php new file mode 100644 index 000000000..62d552aec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunInSeparateProcess.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RunInSeparateProcess extends Metadata +{ + /** + * @psalm-assert-if-true RunInSeparateProcess $this + */ + public function isRunInSeparateProcess(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php new file mode 100644 index 000000000..ea0807a5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/RunTestsInSeparateProcesses.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class RunTestsInSeparateProcesses extends Metadata +{ + /** + * @psalm-assert-if-true RunTestsInSeparateProcesses $this + */ + public function isRunTestsInSeparateProcesses(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Test.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Test.php new file mode 100644 index 000000000..6d2aeecdd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Test.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Test extends Metadata +{ + /** + * @psalm-assert-if-true Test $this + */ + public function isTest(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestDox.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestDox.php new file mode 100644 index 000000000..d78d86cf5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestDox.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestDox extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $text; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $text + */ + protected function __construct(int $level, string $text) + { + parent::__construct($level); + + $this->text = $text; + } + + /** + * @psalm-assert-if-true TestDox $this + */ + public function isTestDox(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function text(): string + { + return $this->text; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestWith.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestWith.php new file mode 100644 index 000000000..98bef73d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/TestWith.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class TestWith extends Metadata +{ + private readonly array $data; + + /** + * @psalm-param 0|1 $level + */ + protected function __construct(int $level, array $data) + { + parent::__construct($level); + + $this->data = $data; + } + + /** + * @psalm-assert-if-true TestWith $this + */ + public function isTestWith(): bool + { + return true; + } + + public function data(): array + { + return $this->data; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Uses.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Uses.php new file mode 100644 index 000000000..d3fa216bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Uses.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Uses extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $target; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $target + */ + protected function __construct(int $level, string $target) + { + parent::__construct($level); + + $this->target = $target; + } + + /** + * @psalm-assert-if-true Uses $this + */ + public function isUses(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function target(): string + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesClass.php new file mode 100644 index 000000000..01e7741e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesClass.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 PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UsesClass extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + */ + protected function __construct(int $level, string $className) + { + parent::__construct($level); + + $this->className = $className; + } + + /** + * @psalm-assert-if-true UsesClass $this + */ + public function isUsesClass(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return class-string + * + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function asStringForCodeUnitMapper(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesDefaultClass.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesDefaultClass.php new file mode 100644 index 000000000..48a824710 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesDefaultClass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UsesDefaultClass extends Metadata +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-param 0|1 $level + * @psalm-param class-string $className + */ + protected function __construct(int $level, string $className) + { + parent::__construct($level); + + $this->className = $className; + } + + /** + * @psalm-assert-if-true UsesDefaultClass $this + */ + public function isUsesDefaultClass(): bool + { + return true; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesFunction.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesFunction.php new file mode 100644 index 000000000..8c46e76bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/UsesFunction.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class UsesFunction extends Metadata +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $functionName; + + /** + * @psalm-param 0|1 $level + * @psalm-param non-empty-string $functionName + */ + public function __construct(int $level, string $functionName) + { + parent::__construct($level); + + $this->functionName = $functionName; + } + + /** + * @psalm-assert-if-true UsesFunction $this + */ + public function isUsesFunction(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function functionName(): string + { + return $this->functionName; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function asStringForCodeUnitMapper(): string + { + return '::' . $this->functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php new file mode 100644 index 000000000..86aefaf28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ComparisonRequirement.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Version; + +use function version_compare; +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ComparisonRequirement extends Requirement +{ + private readonly string $version; + private readonly VersionComparisonOperator $operator; + + public function __construct(string $version, VersionComparisonOperator $operator) + { + $this->version = $version; + $this->operator = $operator; + } + + public function isSatisfiedBy(string $version): bool + { + return version_compare($version, $this->version, $this->operator->asString()); + } + + public function asString(): string + { + return $this->operator->asString() . ' ' . $this->version; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php new file mode 100644 index 000000000..32857899c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/ConstraintRequirement.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Version; + +use function preg_replace; +use PharIo\Version\Version; +use PharIo\Version\VersionConstraint; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ConstraintRequirement extends Requirement +{ + private readonly VersionConstraint $constraint; + + public function __construct(VersionConstraint $constraint) + { + $this->constraint = $constraint; + } + + /** + * @psalm-suppress ImpureMethodCall + */ + public function isSatisfiedBy(string $version): bool + { + return $this->constraint->complies( + new Version($this->sanitize($version)), + ); + } + + /** + * @psalm-suppress ImpureMethodCall + */ + public function asString(): string + { + return $this->constraint->asString(); + } + + private function sanitize(string $version): string + { + return preg_replace( + '/^(\d+\.\d+(?:.\d+)?).*$/', + '$1', + $version, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/Requirement.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/Requirement.php new file mode 100644 index 000000000..a61e50030 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/Version/Requirement.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata\Version; + +use function preg_match; +use PharIo\Version\UnsupportedVersionConstraintException; +use PharIo\Version\VersionConstraintParser; +use PHPUnit\Metadata\InvalidVersionRequirementException; +use PHPUnit\Util\InvalidVersionOperatorException; +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +abstract class Requirement +{ + private const VERSION_COMPARISON = '/(?P[<>=!]{0,2})\s*(?P[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; + + /** + * @throws InvalidVersionOperatorException + * @throws InvalidVersionRequirementException + */ + public static function from(string $versionRequirement): self + { + try { + return new ConstraintRequirement( + (new VersionConstraintParser)->parse( + $versionRequirement, + ), + ); + } catch (UnsupportedVersionConstraintException) { + if (preg_match(self::VERSION_COMPARISON, $versionRequirement, $matches)) { + return new ComparisonRequirement( + $matches['version'], + new VersionComparisonOperator( + !empty($matches['operator']) ? $matches['operator'] : '>=', + ), + ); + } + } + + throw new InvalidVersionRequirementException; + } + + abstract public function isSatisfiedBy(string $version): bool; + + abstract public function asString(): string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php new file mode 100644 index 000000000..d10f41e68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Metadata/WithoutErrorHandler.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Metadata; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class WithoutErrorHandler extends Metadata +{ + /** + * @psalm-assert-if-true WithoutErrorHandler $this + */ + public function isWithoutErrorHandler(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Baseline.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Baseline.php new file mode 100644 index 000000000..3e386171d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Baseline.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Baseline +{ + public const VERSION = 1; + + /** + * @psalm-var array>> + */ + private array $issues = []; + + public function add(Issue $issue): void + { + if (!isset($this->issues[$issue->file()])) { + $this->issues[$issue->file()] = []; + } + + if (!isset($this->issues[$issue->file()][$issue->line()])) { + $this->issues[$issue->file()][$issue->line()] = []; + } + + $this->issues[$issue->file()][$issue->line()][] = $issue; + } + + public function has(Issue $issue): bool + { + if (!isset($this->issues[$issue->file()][$issue->line()])) { + return false; + } + + foreach ($this->issues[$issue->file()][$issue->line()] as $_issue) { + if ($_issue->equals($issue)) { + return true; + } + } + + return false; + } + + /** + * @psalm-return array>> + */ + public function groupedByFileAndLine(): array + { + return $this->issues; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php new file mode 100644 index 000000000..c55901365 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Runner\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotLoadBaselineException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php new file mode 100644 index 000000000..20c6ca030 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use function sprintf; +use PHPUnit\Runner\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class FileDoesNotHaveLineException extends RuntimeException implements Exception +{ + public function __construct(string $file, int $line) + { + parent::__construct( + sprintf( + 'File "%s" does not have line %d', + $file, + $line, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Generator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Generator.php new file mode 100644 index 000000000..97c89f0a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Generator.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Runner\FileDoesNotExistException; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\SourceFilter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Generator +{ + private Baseline $baseline; + private readonly Source $source; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Facade $facade, Source $source) + { + $facade->registerSubscribers( + new TestTriggeredDeprecationSubscriber($this), + new TestTriggeredNoticeSubscriber($this), + new TestTriggeredPhpDeprecationSubscriber($this), + new TestTriggeredPhpNoticeSubscriber($this), + new TestTriggeredPhpWarningSubscriber($this), + new TestTriggeredWarningSubscriber($this), + ); + + $this->baseline = new Baseline; + $this->source = $source; + } + + public function baseline(): Baseline + { + return $this->baseline; + } + + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function testTriggeredIssue(DeprecationTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): void + { + if ($event->wasSuppressed() && !$this->isSuppressionIgnored($event)) { + return; + } + + if ($this->restrict($event) && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $this->baseline->add( + Issue::from( + $event->file(), + $event->line(), + null, + $event->message(), + ), + ); + } + + private function restrict(DeprecationTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): bool + { + if ($event instanceof WarningTriggered || $event instanceof PhpWarningTriggered) { + return $this->source->restrictWarnings(); + } + + if ($event instanceof NoticeTriggered || $event instanceof PhpNoticeTriggered) { + return $this->source->restrictNotices(); + } + + return $this->source->restrictDeprecations(); + } + + private function isSuppressionIgnored(DeprecationTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): bool + { + if ($event instanceof WarningTriggered) { + return $this->source->ignoreSuppressionOfWarnings(); + } + + if ($event instanceof PhpWarningTriggered) { + return $this->source->ignoreSuppressionOfPhpWarnings(); + } + + if ($event instanceof PhpNoticeTriggered) { + return $this->source->ignoreSuppressionOfPhpNotices(); + } + + if ($event instanceof NoticeTriggered) { + return $this->source->ignoreSuppressionOfNotices(); + } + + if ($event instanceof PhpDeprecationTriggered) { + return $this->source->ignoreSuppressionOfPhpDeprecations(); + } + + return $this->source->ignoreSuppressionOfDeprecations(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Issue.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Issue.php new file mode 100644 index 000000000..074a8f4e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Issue.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use const FILE_IGNORE_NEW_LINES; +use function assert; +use function file; +use function is_file; +use function sha1; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Issue +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + + /** + * @psalm-var non-empty-string + */ + private readonly string $hash; + + /** + * @psalm-var non-empty-string + */ + private readonly string $description; + + /** + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * @psalm-param ?non-empty-string $hash + * @psalm-param non-empty-string $description + * + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public static function from(string $file, int $line, ?string $hash, string $description): self + { + if ($hash === null) { + $hash = self::calculateHash($file, $line); + } + + return new self($file, $line, $hash, $description); + } + + /** + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * @psalm-param non-empty-string $hash + * @psalm-param non-empty-string $description + */ + private function __construct(string $file, int $line, string $hash, string $description) + { + $this->file = $file; + $this->line = $line; + $this->hash = $hash; + $this->description = $description; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + /** + * @psalm-return non-empty-string + */ + public function hash(): string + { + return $this->hash; + } + + /** + * @psalm-return non-empty-string + */ + public function description(): string + { + return $this->description; + } + + public function equals(self $other): bool + { + return $this->file() === $other->file() && + $this->line() === $other->line() && + $this->hash() === $other->hash() && + $this->description() === $other->description(); + } + + /** + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * + * @psalm-return non-empty-string + * + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + private static function calculateHash(string $file, int $line): string + { + $lines = @file($file, FILE_IGNORE_NEW_LINES); + + if ($lines === false && !is_file($file)) { + throw new FileDoesNotExistException($file); + } + + $key = $line - 1; + + if (!isset($lines[$key])) { + throw new FileDoesNotHaveLineException($file, $line); + } + + $hash = sha1($lines[$key]); + + assert($hash !== ''); + + return $hash; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Reader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Reader.php new file mode 100644 index 000000000..27e9ddb53 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Reader.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use const DIRECTORY_SEPARATOR; +use function assert; +use function dirname; +use function file_exists; +use function realpath; +use function sprintf; +use function str_replace; +use function trim; +use DOMElement; +use DOMXPath; +use PHPUnit\Util\Xml\Loader as XmlLoader; +use PHPUnit\Util\Xml\XmlException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Reader +{ + /** + * @psalm-param non-empty-string $baselineFile + * + * @throws CannotLoadBaselineException + */ + public function read(string $baselineFile): Baseline + { + if (!file_exists($baselineFile)) { + throw new CannotLoadBaselineException( + sprintf( + 'Cannot read baseline %s, file does not exist', + $baselineFile, + ), + ); + } + + try { + $document = (new XmlLoader)->loadFile($baselineFile); + } catch (XmlException $e) { + throw new CannotLoadBaselineException( + sprintf( + 'Cannot read baseline: %s', + trim($e->getMessage()), + ), + ); + } + + $version = (int) $document->documentElement->getAttribute('version'); + + if ($version !== Baseline::VERSION) { + throw new CannotLoadBaselineException( + sprintf( + 'Cannot read baseline %s, version %d is not supported', + $baselineFile, + $version, + ), + ); + } + + $baseline = new Baseline; + $baselineDirectory = dirname(realpath($baselineFile)); + $xpath = new DOMXPath($document); + + foreach ($xpath->query('file') as $fileElement) { + assert($fileElement instanceof DOMElement); + + $file = $baselineDirectory . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $fileElement->getAttribute('path')); + + foreach ($xpath->query('line', $fileElement) as $lineElement) { + assert($lineElement instanceof DOMElement); + + $line = (int) $lineElement->getAttribute('number'); + $hash = $lineElement->getAttribute('hash'); + + foreach ($xpath->query('issue', $lineElement) as $issueElement) { + assert($issueElement instanceof DOMElement); + + $description = $issueElement->textContent; + + assert($line > 0); + assert(!empty($hash)); + assert(!empty($description)); + + $baseline->add(Issue::from($file, $line, $hash, $description)); + } + } + } + + return $baseline; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php new file mode 100644 index 000000000..5172d6173 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/RelativePathCalculator.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use function array_fill; +use function array_merge; +use function array_slice; +use function assert; +use function count; +use function explode; +use function implode; +use function str_replace; +use function strpos; +use function substr; +use function trim; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @see Copied from https://github.com/phpstan/phpstan-src/blob/1.10.33/src/File/ParentDirectoryRelativePathHelper.php + */ +final class RelativePathCalculator +{ + /** + * @psalm-var non-empty-string $baselineDirectory + */ + private readonly string $baselineDirectory; + + /** + * @psalm-param non-empty-string $baselineDirectory + */ + public function __construct(string $baselineDirectory) + { + $this->baselineDirectory = $baselineDirectory; + } + + /** + * @psalm-param non-empty-string $filename + * + * @psalm-return non-empty-string + */ + public function calculate(string $filename): string + { + $result = implode('/', $this->parts($filename)); + + assert($result !== ''); + + return $result; + } + + /** + * @psalm-param non-empty-string $filename + * + * @psalm-return list + */ + public function parts(string $filename): array + { + $schemePosition = strpos($filename, '://'); + + if ($schemePosition !== false) { + $filename = substr($filename, $schemePosition + 3); + + assert($filename !== ''); + } + + $parentParts = explode('/', trim(str_replace('\\', '/', $this->baselineDirectory), '/')); + $parentPartsCount = count($parentParts); + $filenameParts = explode('/', trim(str_replace('\\', '/', $filename), '/')); + $filenamePartsCount = count($filenameParts); + + $i = 0; + + for (; $i < $filenamePartsCount; $i++) { + if ($parentPartsCount < $i + 1) { + break; + } + + $parentPath = implode('/', array_slice($parentParts, 0, $i + 1)); + $filenamePath = implode('/', array_slice($filenameParts, 0, $i + 1)); + + if ($parentPath !== $filenamePath) { + break; + } + } + + if ($i === 0) { + return [$filename]; + } + + $dotsCount = $parentPartsCount - $i; + + assert($dotsCount >= 0); + + return array_merge(array_fill(0, $dotsCount, '..'), array_slice($filenameParts, $i)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php new file mode 100644 index 000000000..5007bfc8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly Generator $generator; + + public function __construct(Generator $generator) + { + $this->generator = $generator; + } + + protected function generator(): Generator + { + return $this->generator; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php new file mode 100644 index 000000000..62c8ed168 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber +{ + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function notify(DeprecationTriggered $event): void + { + $this->generator()->testTriggeredIssue($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php new file mode 100644 index 000000000..9eec35ff1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\NoticeTriggeredSubscriber; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber +{ + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function notify(NoticeTriggered $event): void + { + $this->generator()->testTriggeredIssue($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php new file mode 100644 index 000000000..43ae64456 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber +{ + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function notify(PhpDeprecationTriggered $event): void + { + $this->generator()->testTriggeredIssue($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php new file mode 100644 index 000000000..d3e9625dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber +{ + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function notify(PhpNoticeTriggered $event): void + { + $this->generator()->testTriggeredIssue($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php new file mode 100644 index 000000000..00bd4b5e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber +{ + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function notify(PhpWarningTriggered $event): void + { + $this->generator()->testTriggeredIssue($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php new file mode 100644 index 000000000..ed21fe86e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\Test\WarningTriggeredSubscriber; +use PHPUnit\Runner\FileDoesNotExistException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber +{ + /** + * @throws FileDoesNotExistException + * @throws FileDoesNotHaveLineException + */ + public function notify(WarningTriggered $event): void + { + $this->generator()->testTriggeredIssue($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Writer.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Writer.php new file mode 100644 index 000000000..870326975 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Baseline/Writer.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Baseline; + +use function assert; +use function dirname; +use function file_put_contents; +use XMLWriter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Writer +{ + /** + * @psalm-param non-empty-string $baselineFile + */ + public function write(string $baselineFile, Baseline $baseline): void + { + $pathCalculator = new RelativePathCalculator(dirname($baselineFile)); + + $writer = new XMLWriter; + + $writer->openMemory(); + $writer->setIndent(true); + $writer->startDocument(); + + $writer->startElement('files'); + $writer->writeAttribute('version', (string) Baseline::VERSION); + + foreach ($baseline->groupedByFileAndLine() as $file => $lines) { + assert(!empty($file)); + + $writer->startElement('file'); + $writer->writeAttribute('path', $pathCalculator->calculate($file)); + + foreach ($lines as $line => $issues) { + $writer->startElement('line'); + $writer->writeAttribute('number', (string) $line); + $writer->writeAttribute('hash', $issues[0]->hash()); + + foreach ($issues as $issue) { + $writer->startElement('issue'); + $writer->writeCData($issue->description()); + $writer->endElement(); + } + + $writer->endElement(); + } + + $writer->endElement(); + } + + $writer->endElement(); + + file_put_contents($baselineFile, $writer->outputMemory()); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/CodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/CodeCoverage.php new file mode 100644 index 000000000..883e4f32a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/CodeCoverage.php @@ -0,0 +1,426 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function file_put_contents; +use function sprintf; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Framework\TestCase; +use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Output\Printer; +use SebastianBergmann\CodeCoverage\Driver\Driver; +use SebastianBergmann\CodeCoverage\Driver\Selector; +use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException; +use SebastianBergmann\CodeCoverage\Filter; +use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport; +use SebastianBergmann\CodeCoverage\Report\Cobertura as CoberturaReport; +use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport; +use SebastianBergmann\CodeCoverage\Report\Html\Colors; +use SebastianBergmann\CodeCoverage\Report\Html\CustomCssFile; +use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport; +use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport; +use SebastianBergmann\CodeCoverage\Report\Text as TextReport; +use SebastianBergmann\CodeCoverage\Report\Thresholds; +use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport; +use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize; +use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Timer\NoActiveTimerException; +use SebastianBergmann\Timer\Timer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ +final class CodeCoverage +{ + private static ?self $instance = null; + private ?\SebastianBergmann\CodeCoverage\CodeCoverage $codeCoverage = null; + private ?Driver $driver = null; + private bool $collecting = false; + private ?TestCase $test = null; + private ?Timer $timer = null; + + /** + * @psalm-var array> + */ + private array $linesToBeIgnored = []; + + public static function instance(): self + { + if (self::$instance === null) { + self::$instance = new self; + } + + return self::$instance; + } + + public function init(Configuration $configuration, CodeCoverageFilterRegistry $codeCoverageFilterRegistry, bool $extensionRequiresCodeCoverageCollection): void + { + $codeCoverageFilterRegistry->init($configuration); + + if (!$configuration->hasCoverageReport() && !$extensionRequiresCodeCoverageCollection) { + return; + } + + $this->activate($codeCoverageFilterRegistry->get(), $configuration->pathCoverage()); + + if (!$this->isActive()) { + return; + } + + if ($configuration->hasCoverageCacheDirectory()) { + $this->codeCoverage()->cacheStaticAnalysis($configuration->coverageCacheDirectory()); + } + + $this->codeCoverage()->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class); + + if ($configuration->strictCoverage()) { + $this->codeCoverage()->enableCheckForUnintentionallyCoveredCode(); + } + + if ($configuration->ignoreDeprecatedCodeUnitsFromCodeCoverage()) { + $this->codeCoverage()->ignoreDeprecatedCode(); + } else { + $this->codeCoverage()->doNotIgnoreDeprecatedCode(); + } + + if ($configuration->disableCodeCoverageIgnore()) { + $this->codeCoverage()->disableAnnotationsForIgnoringCode(); + } else { + $this->codeCoverage()->enableAnnotationsForIgnoringCode(); + } + + if ($configuration->includeUncoveredFiles()) { + $this->codeCoverage()->includeUncoveredFiles(); + } else { + $this->codeCoverage()->excludeUncoveredFiles(); + } + + if ($codeCoverageFilterRegistry->get()->isEmpty()) { + if (!$codeCoverageFilterRegistry->configured()) { + EventFacade::emitter()->testRunnerTriggeredWarning( + 'No filter is configured, code coverage will not be processed', + ); + } else { + EventFacade::emitter()->testRunnerTriggeredWarning( + 'Incorrect filter configuration, code coverage will not be processed', + ); + } + + $this->deactivate(); + } + } + + /** + * @psalm-assert-if-true !null $this->instance + */ + public function isActive(): bool + { + return $this->codeCoverage !== null; + } + + public function codeCoverage(): \SebastianBergmann\CodeCoverage\CodeCoverage + { + return $this->codeCoverage; + } + + public function driver(): Driver + { + return $this->driver; + } + + /** + * @throws MoreThanOneDataSetFromDataProviderException + */ + public function start(TestCase $test): void + { + if ($this->collecting) { + return; + } + + $size = TestSize::unknown(); + + if ($test->size()->isSmall()) { + $size = TestSize::small(); + } elseif ($test->size()->isMedium()) { + $size = TestSize::medium(); + } elseif ($test->size()->isLarge()) { + $size = TestSize::large(); + } + + $this->test = $test; + + $this->codeCoverage->start( + $test->valueObjectForEvents()->id(), + $size, + ); + + $this->collecting = true; + } + + public function stop(bool $append = true, array|false $linesToBeCovered = [], array $linesToBeUsed = []): void + { + if (!$this->collecting) { + return; + } + + $status = TestStatus::unknown(); + + if ($this->test !== null) { + if ($this->test->status()->isSuccess()) { + $status = TestStatus::success(); + } else { + $status = TestStatus::failure(); + } + } + + /* @noinspection UnusedFunctionResultInspection */ + $this->codeCoverage->stop($append, $status, $linesToBeCovered, $linesToBeUsed, $this->linesToBeIgnored); + + $this->test = null; + $this->collecting = false; + } + + public function deactivate(): void + { + $this->driver = null; + $this->codeCoverage = null; + $this->test = null; + } + + public function generateReports(Printer $printer, Configuration $configuration): void + { + if (!$this->isActive()) { + return; + } + + if ($configuration->hasCoveragePhp()) { + $this->codeCoverageGenerationStart($printer, 'PHP'); + + try { + $writer = new PhpReport; + $writer->process($this->codeCoverage(), $configuration->coveragePhp()); + + $this->codeCoverageGenerationSucceeded($printer); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($printer, $e); + } + } + + if ($configuration->hasCoverageClover()) { + $this->codeCoverageGenerationStart($printer, 'Clover XML'); + + try { + $writer = new CloverReport; + $writer->process($this->codeCoverage(), $configuration->coverageClover()); + + $this->codeCoverageGenerationSucceeded($printer); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($printer, $e); + } + } + + if ($configuration->hasCoverageCobertura()) { + $this->codeCoverageGenerationStart($printer, 'Cobertura XML'); + + try { + $writer = new CoberturaReport; + $writer->process($this->codeCoverage(), $configuration->coverageCobertura()); + + $this->codeCoverageGenerationSucceeded($printer); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($printer, $e); + } + } + + if ($configuration->hasCoverageCrap4j()) { + $this->codeCoverageGenerationStart($printer, 'Crap4J XML'); + + try { + $writer = new Crap4jReport($configuration->coverageCrap4jThreshold()); + $writer->process($this->codeCoverage(), $configuration->coverageCrap4j()); + + $this->codeCoverageGenerationSucceeded($printer); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($printer, $e); + } + } + + if ($configuration->hasCoverageHtml()) { + $this->codeCoverageGenerationStart($printer, 'HTML'); + + try { + $customCssFile = CustomCssFile::default(); + + if ($configuration->hasCoverageHtmlCustomCssFile()) { + $customCssFile = CustomCssFile::from($configuration->coverageHtmlCustomCssFile()); + } + + $writer = new HtmlReport( + sprintf( + ' and PHPUnit %s', + Version::id(), + ), + Colors::from( + $configuration->coverageHtmlColorSuccessLow(), + $configuration->coverageHtmlColorSuccessMedium(), + $configuration->coverageHtmlColorSuccessHigh(), + $configuration->coverageHtmlColorWarning(), + $configuration->coverageHtmlColorDanger(), + ), + Thresholds::from( + $configuration->coverageHtmlLowUpperBound(), + $configuration->coverageHtmlHighLowerBound(), + ), + $customCssFile, + ); + + $writer->process($this->codeCoverage(), $configuration->coverageHtml()); + + $this->codeCoverageGenerationSucceeded($printer); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($printer, $e); + } + } + + if ($configuration->hasCoverageText()) { + $processor = new TextReport( + Thresholds::default(), + $configuration->coverageTextShowUncoveredFiles(), + $configuration->coverageTextShowOnlySummary(), + ); + + $textReport = $processor->process($this->codeCoverage(), $configuration->colors()); + + if ($configuration->coverageText() === 'php://stdout') { + if (!$configuration->noOutput() && !$configuration->debug()) { + $printer->print($textReport); + } + } else { + file_put_contents($configuration->coverageText(), $textReport); + } + } + + if ($configuration->hasCoverageXml()) { + $this->codeCoverageGenerationStart($printer, 'PHPUnit XML'); + + try { + $writer = new XmlReport(Version::id()); + $writer->process($this->codeCoverage(), $configuration->coverageXml()); + + $this->codeCoverageGenerationSucceeded($printer); + + unset($writer); + } catch (CodeCoverageException $e) { + $this->codeCoverageGenerationFailed($printer, $e); + } + } + } + + /** + * @psalm-param array> $linesToBeIgnored + */ + public function ignoreLines(array $linesToBeIgnored): void + { + $this->linesToBeIgnored = $linesToBeIgnored; + } + + /** + * @psalm-return array> + */ + public function linesToBeIgnored(): array + { + return $this->linesToBeIgnored; + } + + private function activate(Filter $filter, bool $pathCoverage): void + { + try { + if ($pathCoverage) { + $this->driver = (new Selector)->forLineAndPathCoverage($filter); + } else { + $this->driver = (new Selector)->forLineCoverage($filter); + } + + $this->codeCoverage = new \SebastianBergmann\CodeCoverage\CodeCoverage( + $this->driver, + $filter, + ); + } catch (CodeCoverageException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + $e->getMessage(), + ); + } + } + + private function codeCoverageGenerationStart(Printer $printer, string $format): void + { + $printer->print( + sprintf( + "\nGenerating code coverage report in %s format ... ", + $format, + ), + ); + + $this->timer()->start(); + } + + /** + * @throws NoActiveTimerException + */ + private function codeCoverageGenerationSucceeded(Printer $printer): void + { + $printer->print( + sprintf( + "done [%s]\n", + $this->timer()->stop()->asString(), + ), + ); + } + + /** + * @throws NoActiveTimerException + */ + private function codeCoverageGenerationFailed(Printer $printer, CodeCoverageException $e): void + { + $printer->print( + sprintf( + "failed [%s]\n%s\n", + $this->timer()->stop()->asString(), + $e->getMessage(), + ), + ); + } + + private function timer(): Timer + { + if ($this->timer === null) { + $this->timer = new Timer; + } + + return $this->timer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ErrorHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ErrorHandler.php new file mode 100644 index 000000000..f3357f3d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ErrorHandler.php @@ -0,0 +1,226 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use const E_COMPILE_ERROR; +use const E_COMPILE_WARNING; +use const E_CORE_ERROR; +use const E_CORE_WARNING; +use const E_DEPRECATED; +use const E_ERROR; +use const E_NOTICE; +use const E_PARSE; +use const E_RECOVERABLE_ERROR; +use const E_STRICT; +use const E_USER_DEPRECATED; +use const E_USER_ERROR; +use const E_USER_NOTICE; +use const E_USER_WARNING; +use const E_WARNING; +use function defined; +use function error_reporting; +use function restore_error_handler; +use function set_error_handler; +use PHPUnit\Event; +use PHPUnit\Event\Code\NoTestCaseObjectOnCallStackException; +use PHPUnit\Runner\Baseline\Baseline; +use PHPUnit\Runner\Baseline\Issue; +use PHPUnit\Util\ExcludeList; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ErrorHandler +{ + private const UNHANDLEABLE_LEVELS = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING; + private const INSUPPRESSIBLE_LEVELS = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR; + private static ?self $instance = null; + private ?Baseline $baseline = null; + private bool $enabled = false; + private ?int $originalErrorReportingLevel = null; + + public static function instance(): self + { + return self::$instance ?? self::$instance = new self; + } + + /** + * @throws NoTestCaseObjectOnCallStackException + */ + public function __invoke(int $errorNumber, string $errorString, string $errorFile, int $errorLine): bool + { + $suppressed = (error_reporting() & ~self::INSUPPRESSIBLE_LEVELS) === 0; + + if ($suppressed && (new ExcludeList)->isExcluded($errorFile)) { + return false; + } + + /** + * E_STRICT is deprecated since PHP 8.4. + * + * @see https://github.com/sebastianbergmann/phpunit/issues/5956 + */ + if (defined('E_STRICT') && $errorNumber === @E_STRICT) { + $errorNumber = E_NOTICE; + } + + $test = Event\Code\TestMethodBuilder::fromCallStack(); + + $ignoredByBaseline = $this->ignoredByBaseline($errorFile, $errorLine, $errorString); + $ignoredByTest = $test->metadata()->isIgnoreDeprecations()->isNotEmpty(); + + switch ($errorNumber) { + case E_NOTICE: + Event\Facade::emitter()->testTriggeredPhpNotice( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + $ignoredByBaseline, + ); + + break; + + case E_USER_NOTICE: + Event\Facade::emitter()->testTriggeredNotice( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + $ignoredByBaseline, + ); + + break; + + case E_WARNING: + Event\Facade::emitter()->testTriggeredPhpWarning( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + $ignoredByBaseline, + ); + + break; + + case E_USER_WARNING: + Event\Facade::emitter()->testTriggeredWarning( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + $ignoredByBaseline, + ); + + break; + + case E_DEPRECATED: + Event\Facade::emitter()->testTriggeredPhpDeprecation( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + $ignoredByBaseline, + $ignoredByTest, + ); + + break; + + case E_USER_DEPRECATED: + Event\Facade::emitter()->testTriggeredDeprecation( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + $ignoredByBaseline, + $ignoredByTest, + ); + + break; + + case E_USER_ERROR: + Event\Facade::emitter()->testTriggeredError( + $test, + $errorString, + $errorFile, + $errorLine, + $suppressed, + ); + + throw new ErrorException('E_USER_ERROR was triggered'); + + default: + return false; + } + + return false; + } + + public function enable(): void + { + if ($this->enabled) { + return; + } + + $oldErrorHandler = set_error_handler($this); + + if ($oldErrorHandler !== null) { + restore_error_handler(); + + return; + } + + $this->enabled = true; + $this->originalErrorReportingLevel = error_reporting(); + + error_reporting($this->originalErrorReportingLevel & self::UNHANDLEABLE_LEVELS); + } + + public function disable(): void + { + if (!$this->enabled) { + return; + } + + restore_error_handler(); + + error_reporting(error_reporting() | $this->originalErrorReportingLevel); + + $this->enabled = false; + $this->originalErrorReportingLevel = null; + } + + public function use(Baseline $baseline): void + { + $this->baseline = $baseline; + } + + /** + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * @psalm-param non-empty-string $description + */ + private function ignoredByBaseline(string $file, int $line, string $description): bool + { + if ($this->baseline === null) { + return false; + } + + return $this->baseline->has(Issue::from($file, $line, null, $description)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php new file mode 100644 index 000000000..701cbb5b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassCannotBeFoundException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassCannotBeFoundException extends RuntimeException implements Exception +{ + public function __construct(string $className, string $file) + { + parent::__construct( + sprintf( + 'Class %s cannot be found in %s', + $className, + $file, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php new file mode 100644 index 000000000..c9d5474e3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassDoesNotExtendTestCaseException extends RuntimeException implements Exception +{ + public function __construct(string $className, string $file) + { + parent::__construct( + sprintf( + 'Class %s declared in %s does not extend PHPUnit\Framework\TestCase', + $className, + $file, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php new file mode 100644 index 000000000..bf9475899 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ClassIsAbstractException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ClassIsAbstractException extends RuntimeException implements Exception +{ + public function __construct(string $className, string $file) + { + parent::__construct( + sprintf( + 'Class %s declared in %s is abstract', + $className, + $file, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php new file mode 100644 index 000000000..626c42256 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DirectoryDoesNotExistException extends RuntimeException implements Exception +{ + public function __construct(string $directory) + { + parent::__construct( + sprintf( + 'Directory "%s" does not exist and could not be created', + $directory, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ErrorException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ErrorException.php new file mode 100644 index 000000000..954684e9f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ErrorException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use Error; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ErrorException extends Error implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/Exception.php new file mode 100644 index 000000000..ea0cf4244 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends \PHPUnit\Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php new file mode 100644 index 000000000..5b84c785d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/FileDoesNotExistException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class FileDoesNotExistException extends RuntimeException implements Exception +{ + public function __construct(string $file) + { + parent::__construct( + sprintf( + 'File "%s" does not exist', + $file, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php new file mode 100644 index 000000000..016ec85e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidOrderException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidOrderException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php new file mode 100644 index 000000000..d1f593b81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/InvalidPhptFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidPhptFileException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php new file mode 100644 index 000000000..5d7a09675 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/ParameterDoesNotExistException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ParameterDoesNotExistException extends RuntimeException implements Exception +{ + public function __construct(string $name) + { + parent::__construct( + sprintf( + 'Parameter "%s" does not exist', + $name, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php new file mode 100644 index 000000000..33977155b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhptExternalFileCannotBeLoadedException extends RuntimeException implements Exception +{ + public function __construct(string $section, string $file) + { + parent::__construct( + sprintf( + 'Could not load --%s-- %s for PHPT file', + $section . '_EXTERNAL', + $file, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php new file mode 100644 index 000000000..ca8647e6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UnsupportedPhptSectionException extends RuntimeException implements Exception +{ + public function __construct(string $section) + { + parent::__construct( + sprintf( + 'PHPUnit does not support PHPT %s sections', + $section, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Extension.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Extension.php new file mode 100644 index 000000000..35610bc3d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Extension.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use PHPUnit\TextUI\Configuration\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +interface Extension +{ + public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php new file mode 100644 index 000000000..4a7b5fa7d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ExtensionBootstrapper.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use const PHP_EOL; +use function assert; +use function class_exists; +use function class_implements; +use function in_array; +use function sprintf; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\TextUI\Configuration\Configuration; +use ReflectionClass; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExtensionBootstrapper +{ + private readonly Configuration $configuration; + private readonly Facade $facade; + + public function __construct(Configuration $configuration, Facade $facade) + { + $this->configuration = $configuration; + $this->facade = $facade; + } + + /** + * @psalm-param class-string $className + * @psalm-param array $parameters + */ + public function bootstrap(string $className, array $parameters): void + { + if (!class_exists($className)) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot bootstrap extension because class %s does not exist', + $className, + ), + ); + + return; + } + + if (!in_array(Extension::class, class_implements($className), true)) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot bootstrap extension because class %s does not implement interface %s', + $className, + Extension::class, + ), + ); + + return; + } + + try { + $instance = (new ReflectionClass($className))->newInstance(); + + assert($instance instanceof Extension); + + $instance->bootstrap( + $this->configuration, + $this->facade, + ParameterCollection::fromArray($parameters), + ); + } catch (Throwable $t) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Bootstrapping of extension %s failed: %s%s%s', + $className, + $t->getMessage(), + PHP_EOL, + $t->getTraceAsString(), + ), + ); + + return; + } + + EventFacade::emitter()->testRunnerBootstrappedExtension( + $className, + $parameters, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Facade.php new file mode 100644 index 000000000..b168eb622 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/Facade.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\Subscriber; +use PHPUnit\Event\Tracer\Tracer; +use PHPUnit\Event\UnknownSubscriberTypeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Facade +{ + private bool $replacesOutput = false; + private bool $replacesProgressOutput = false; + private bool $replacesResultOutput = false; + private bool $requiresCodeCoverageCollection = false; + private bool $requiresExportOfObjects = false; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function registerSubscribers(Subscriber ...$subscribers): void + { + EventFacade::instance()->registerSubscribers(...$subscribers); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function registerSubscriber(Subscriber $subscriber): void + { + EventFacade::instance()->registerSubscriber($subscriber); + } + + /** + * @throws EventFacadeIsSealedException + */ + public function registerTracer(Tracer $tracer): void + { + EventFacade::instance()->registerTracer($tracer); + } + + public function replaceOutput(): void + { + $this->replacesOutput = true; + } + + public function replacesOutput(): bool + { + return $this->replacesOutput; + } + + public function replaceProgressOutput(): void + { + $this->replacesProgressOutput = true; + } + + public function replacesProgressOutput(): bool + { + return $this->replacesOutput || $this->replacesProgressOutput; + } + + public function replaceResultOutput(): void + { + $this->replacesResultOutput = true; + } + + public function replacesResultOutput(): bool + { + return $this->replacesOutput || $this->replacesResultOutput; + } + + public function requireCodeCoverageCollection(): void + { + $this->requiresCodeCoverageCollection = true; + } + + public function requiresCodeCoverageCollection(): bool + { + return $this->requiresCodeCoverageCollection; + } + + /** + * @deprecated + */ + public function requireExportOfObjects(): void + { + $this->requiresExportOfObjects = true; + } + + /** + * @deprecated + */ + public function requiresExportOfObjects(): bool + { + return $this->requiresExportOfObjects; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php new file mode 100644 index 000000000..08b09966f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/ParameterCollection.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use function array_key_exists; +use PHPUnit\Runner\ParameterDoesNotExistException; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ParameterCollection +{ + private readonly array $parameters; + + /** + * @psalm-param array $parameters + */ + public static function fromArray(array $parameters): self + { + return new self($parameters); + } + + private function __construct(array $parameters) + { + $this->parameters = $parameters; + } + + public function has(string $name): bool + { + return array_key_exists($name, $this->parameters); + } + + /** + * @throws ParameterDoesNotExistException + */ + public function get(string $name): string + { + if (!$this->has($name)) { + throw new ParameterDoesNotExistException($name); + } + + return $this->parameters[$name]; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php new file mode 100644 index 000000000..bf79712e3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Extension/PharLoader.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Extension; + +use function count; +use function explode; +use function extension_loaded; +use function implode; +use function is_file; +use function sprintf; +use function str_contains; +use PharIo\Manifest\ApplicationName; +use PharIo\Manifest\Exception as ManifestException; +use PharIo\Manifest\ManifestLoader; +use PharIo\Version\Version as PharIoVersion; +use PHPUnit\Event; +use PHPUnit\Runner\Version; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PharLoader +{ + /** + * @psalm-param non-empty-string $directory + * + * @psalm-return list + */ + public function loadPharExtensionsInDirectory(string $directory): array + { + $pharExtensionLoaded = extension_loaded('phar'); + $loadedExtensions = []; + + foreach ((new FileIteratorFacade)->getFilesAsArray($directory, '.phar') as $file) { + if (!$pharExtensionLoaded) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot load extension from %s because the PHAR extension is not available', + $file, + ), + ); + + continue; + } + + if (!is_file('phar://' . $file . '/manifest.xml')) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + '%s is not an extension for PHPUnit', + $file, + ), + ); + + continue; + } + + try { + $applicationName = new ApplicationName('phpunit/phpunit'); + $version = new PharIoVersion($this->phpunitVersion()); + $manifest = ManifestLoader::fromFile('phar://' . $file . '/manifest.xml'); + + if (!$manifest->isExtensionFor($applicationName)) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + '%s is not an extension for PHPUnit', + $file, + ), + ); + + continue; + } + + if (!$manifest->isExtensionFor($applicationName, $version)) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + '%s is not compatible with PHPUnit %s', + $file, + Version::series(), + ), + ); + + continue; + } + } catch (ManifestException $e) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot load extension from %s: %s', + $file, + $e->getMessage(), + ), + ); + + continue; + } + + try { + /** @psalm-suppress UnresolvableInclude */ + @require $file; + } catch (Throwable $t) { + Event\Facade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot load extension from %s: %s', + $file, + $t->getMessage(), + ), + ); + + continue; + } + + $loadedExtensions[] = $manifest->getName()->asString() . ' ' . $manifest->getVersion()->getVersionString(); + + Event\Facade::emitter()->testRunnerLoadedExtensionFromPhar( + $file, + $manifest->getName()->asString(), + $manifest->getVersion()->getVersionString(), + ); + } + + return $loadedExtensions; + } + + private function phpunitVersion(): string + { + $version = Version::id(); + + if (!str_contains($version, '-')) { + return $version; + } + + $parts = explode('.', explode('-', $version)[0]); + + if (count($parts) === 2) { + $parts[] = 0; + } + + return implode('.', $parts); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php new file mode 100644 index 000000000..63a26b44a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function in_array; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExcludeGroupFilterIterator extends GroupFilterIterator +{ + protected function doAccept(int $id): bool + { + return !in_array($id, $this->groupTests, true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php new file mode 100644 index 000000000..4afa5d99f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/Factory.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function assert; +use FilterIterator; +use Iterator; +use PHPUnit\Framework\TestSuite; +use ReflectionClass; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Factory +{ + /** + * @psalm-var array + */ + private array $filters = []; + + /** + * @psalm-param list $testIds + */ + public function addTestIdFilter(array $testIds): void + { + $this->filters[] = [ + new ReflectionClass(TestIdFilterIterator::class), $testIds, + ]; + } + + /** + * @psalm-param list $groups + */ + public function addExcludeGroupFilter(array $groups): void + { + $this->filters[] = [ + new ReflectionClass(ExcludeGroupFilterIterator::class), $groups, + ]; + } + + /** + * @psalm-param list $groups + */ + public function addIncludeGroupFilter(array $groups): void + { + $this->filters[] = [ + new ReflectionClass(IncludeGroupFilterIterator::class), $groups, + ]; + } + + /** + * @psalm-param non-empty-string $name + */ + public function addNameFilter(string $name): void + { + $this->filters[] = [ + new ReflectionClass(NameFilterIterator::class), $name, + ]; + } + + public function factory(Iterator $iterator, TestSuite $suite): FilterIterator + { + foreach ($this->filters as $filter) { + [$class, $arguments] = $filter; + $iterator = $class->newInstance($iterator, $arguments, $suite); + } + + assert($iterator instanceof FilterIterator); + + return $iterator; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php new file mode 100644 index 000000000..f2114de9b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/GroupFilterIterator.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function array_map; +use function array_push; +use function in_array; +use function spl_object_id; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestSuite; +use RecursiveFilterIterator; +use RecursiveIterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class GroupFilterIterator extends RecursiveFilterIterator +{ + /** + * @psalm-var list + */ + protected array $groupTests = []; + + /** + * @psalm-param RecursiveIterator $iterator + * @psalm-param list $groups + */ + public function __construct(RecursiveIterator $iterator, array $groups, TestSuite $suite) + { + parent::__construct($iterator); + + foreach ($suite->groupDetails() as $group => $tests) { + if (in_array((string) $group, $groups, true)) { + $testHashes = array_map( + 'spl_object_id', + $tests, + ); + + array_push($this->groupTests, ...$testHashes); + } + } + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + return $this->doAccept(spl_object_id($test)); + } + + abstract protected function doAccept(int $id): bool; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php new file mode 100644 index 000000000..34b0652a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function in_array; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IncludeGroupFilterIterator extends GroupFilterIterator +{ + protected function doAccept(int $id): bool + { + return in_array($id, $this->groupTests, true); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.php new file mode 100644 index 000000000..5b0c63bba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/NameFilterIterator.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 PHPUnit\Runner\Filter; + +use function end; +use function implode; +use function preg_match; +use function sprintf; +use function str_replace; +use function substr; +use Exception; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use RecursiveFilterIterator; +use RecursiveIterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NameFilterIterator extends RecursiveFilterIterator +{ + private ?string $filter = null; + private ?int $filterMin = null; + private ?int $filterMax = null; + + /** + * @psalm-param RecursiveIterator $iterator + * @psalm-param non-empty-string $filter + * + * @throws Exception + */ + public function __construct(RecursiveIterator $iterator, string $filter) + { + parent::__construct($iterator); + + $this->setFilter($filter); + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + $tmp = $this->describe($test); + + if ($tmp[0] !== '') { + $name = implode('::', $tmp); + } else { + $name = $tmp[1]; + } + + $accepted = @preg_match($this->filter, $name, $matches); + + if ($accepted && isset($this->filterMax)) { + $set = end($matches); + $accepted = $set >= $this->filterMin && $set <= $this->filterMax; + } + + return (bool) $accepted; + } + + /** + * @throws Exception + */ + private function setFilter(string $filter): void + { + if (preg_match('/[a-zA-Z0-9]/', substr($filter, 0, 1)) === 1 || @preg_match($filter, '') === false) { + // Handles: + // * testAssertEqualsSucceeds#4 + // * testAssertEqualsSucceeds#4-8 + if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) { + if (isset($matches[3]) && $matches[2] < $matches[3]) { + $filter = sprintf( + '%s.*with data set #(\d+)$', + $matches[1], + ); + + $this->filterMin = (int) $matches[2]; + $this->filterMax = (int) $matches[3]; + } else { + $filter = sprintf( + '%s.*with data set #%s$', + $matches[1], + $matches[2], + ); + } + } // Handles: + // * testDetermineJsonError@JSON_ERROR_NONE + // * testDetermineJsonError@JSON.* + elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { + $filter = sprintf( + '%s.*with data set "%s"$', + $matches[1], + $matches[2], + ); + } + + // Escape delimiters in regular expression. Do NOT use preg_quote, + // to keep magic characters. + $filter = sprintf( + '/%s/i', + str_replace( + '/', + '\\/', + $filter, + ), + ); + } + + $this->filter = $filter; + } + + /** + * @psalm-return array{0: string, 1: string} + */ + private function describe(Test $test): array + { + if ($test instanceof TestCase) { + return [$test::class, $test->nameWithDataSet()]; + } + + if ($test instanceof SelfDescribing) { + return ['', $test->toString()]; + } + + return ['', $test::class]; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php new file mode 100644 index 000000000..3c6c77382 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Filter/TestIdFilterIterator.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\Filter; + +use function in_array; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Event\TestData\NoDataSetFromDataProviderException; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\PhptTestCase; +use RecursiveFilterIterator; +use RecursiveIterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestIdFilterIterator extends RecursiveFilterIterator +{ + /** + * @psalm-var non-empty-list + */ + private readonly array $testIds; + + /** + * @psalm-param RecursiveIterator $iterator + * @psalm-param non-empty-list $testIds + */ + public function __construct(RecursiveIterator $iterator, array $testIds) + { + parent::__construct($iterator); + + $this->testIds = $testIds; + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + if (!$test instanceof TestCase && !$test instanceof PhptTestCase) { + return false; + } + + try { + return in_array($test->valueObjectForEvents()->id(), $this->testIds, true); + } catch (MoreThanOneDataSetFromDataProviderException|NoDataSetFromDataProviderException) { + return false; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php new file mode 100644 index 000000000..be460557c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\GarbageCollection; + +use function gc_collect_cycles; +use function gc_disable; +use function gc_enable; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\UnknownSubscriberTypeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class GarbageCollectionHandler +{ + private readonly Facade $facade; + private readonly int $threshold; + private int $tests = 0; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Facade $facade, int $threshold) + { + $this->facade = $facade; + $this->threshold = $threshold; + + $this->registerSubscribers(); + } + + public function executionStarted(): void + { + gc_disable(); + + $this->facade->emitter()->testRunnerDisabledGarbageCollection(); + + gc_collect_cycles(); + + $this->facade->emitter()->testRunnerTriggeredGarbageCollection(); + } + + public function executionFinished(): void + { + gc_collect_cycles(); + + $this->facade->emitter()->testRunnerTriggeredGarbageCollection(); + + gc_enable(); + + $this->facade->emitter()->testRunnerEnabledGarbageCollection(); + } + + public function testFinished(): void + { + $this->tests++; + + if ($this->tests === $this->threshold) { + gc_collect_cycles(); + + $this->facade->emitter()->testRunnerTriggeredGarbageCollection(); + + $this->tests = 0; + } + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerSubscribers(): void + { + $this->facade->registerSubscribers( + new ExecutionStartedSubscriber($this), + new ExecutionFinishedSubscriber($this), + new TestFinishedSubscriber($this), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php new file mode 100644 index 000000000..7721d0d3a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\GarbageCollection; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\TestRunner\ExecutionFinished; +use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber as TestRunnerExecutionFinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionFinishedSubscriber extends Subscriber implements TestRunnerExecutionFinishedSubscriber +{ + /** + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function notify(ExecutionFinished $event): void + { + $this->handler()->executionFinished(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php new file mode 100644 index 000000000..2cccb2175 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\GarbageCollection; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\TestRunner\ExecutionStarted; +use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber as TestRunnerExecutionStartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionStartedSubscriber extends Subscriber implements TestRunnerExecutionStartedSubscriber +{ + /** + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function notify(ExecutionStarted $event): void + { + $this->handler()->executionStarted(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php new file mode 100644 index 000000000..c3b08c6f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\GarbageCollection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly GarbageCollectionHandler $handler; + + public function __construct(GarbageCollectionHandler $handler) + { + $this->handler = $handler; + } + + protected function handler(): GarbageCollectionHandler + { + return $this->handler; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..35806c4cc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\GarbageCollection; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + /** + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function notify(Finished $event): void + { + $this->handler()->testFinished(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php new file mode 100644 index 000000000..b56ac568b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/PhptTestCase.php @@ -0,0 +1,849 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use const DEBUG_BACKTRACE_IGNORE_ARGS; +use const DIRECTORY_SEPARATOR; +use function array_merge; +use function basename; +use function debug_backtrace; +use function defined; +use function dirname; +use function explode; +use function extension_loaded; +use function file; +use function file_get_contents; +use function file_put_contents; +use function is_array; +use function is_file; +use function is_readable; +use function is_string; +use function ltrim; +use function preg_match; +use function preg_replace; +use function preg_split; +use function realpath; +use function rtrim; +use function str_contains; +use function str_replace; +use function str_starts_with; +use function strncasecmp; +use function substr; +use function trim; +use function unlink; +use function unserialize; +use function var_export; +use PHPUnit\Event\Code\Phpt; +use PHPUnit\Event\Code\ThrowableBuilder; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\NoPreviousThrowableException; +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\ExecutionOrderDependency; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\IncompleteTestError; +use PHPUnit\Framework\PhptAssertionFailedError; +use PHPUnit\Framework\Reorderable; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Framework\Test; +use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; +use PHPUnit\Util\PHP\AbstractPhpProcess; +use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; +use SebastianBergmann\CodeCoverage\InvalidArgumentException; +use SebastianBergmann\CodeCoverage\ReflectionException; +use SebastianBergmann\CodeCoverage\StaticAnalysisCacheNotConfiguredException; +use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize; +use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus; +use SebastianBergmann\CodeCoverage\TestIdMissingException; +use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; +use SebastianBergmann\Template\Template; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhptTestCase implements Reorderable, SelfDescribing, Test +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $filename; + private readonly AbstractPhpProcess $phpUtil; + private string $output = ''; + + /** + * Constructs a test case with the given filename. + * + * @psalm-param non-empty-string $filename + * + * @throws Exception + */ + public function __construct(string $filename, ?AbstractPhpProcess $phpUtil = null) + { + if (!is_file($filename)) { + throw new FileDoesNotExistException($filename); + } + + $this->filename = $filename; + $this->phpUtil = $phpUtil ?: AbstractPhpProcess::factory(); + } + + /** + * Counts the number of test cases executed by run(TestResult result). + */ + public function count(): int + { + return 1; + } + + /** + * Runs a test and collects its result in a TestResult instance. + * + * @throws \PHPUnit\Framework\Exception + * @throws \SebastianBergmann\Template\InvalidArgumentException + * @throws Exception + * @throws InvalidArgumentException + * @throws NoPreviousThrowableException + * @throws ReflectionException + * @throws StaticAnalysisCacheNotConfiguredException + * @throws TestIdMissingException + * @throws UnintentionallyCoveredCodeException + * + * @noinspection RepetitiveMethodCallsInspection + */ + public function run(): void + { + $emitter = EventFacade::emitter(); + + $emitter->testPreparationStarted( + $this->valueObjectForEvents(), + ); + + try { + $sections = $this->parse(); + } catch (Exception $e) { + $emitter->testPrepared($this->valueObjectForEvents()); + $emitter->testErrored($this->valueObjectForEvents(), ThrowableBuilder::from($e)); + $emitter->testFinished($this->valueObjectForEvents(), 0); + + return; + } + + $code = $this->render($sections['FILE']); + $xfail = false; + $settings = $this->parseIniSection($this->settings(CodeCoverage::instance()->isActive())); + + $emitter->testPrepared($this->valueObjectForEvents()); + + if (isset($sections['INI'])) { + $settings = $this->parseIniSection($sections['INI'], $settings); + } + + if (isset($sections['ENV'])) { + $env = $this->parseEnvSection($sections['ENV']); + $this->phpUtil->setEnv($env); + } + + $this->phpUtil->setUseStderrRedirection(true); + + if ($this->shouldTestBeSkipped($sections, $settings)) { + return; + } + + if (isset($sections['XFAIL'])) { + $xfail = trim($sections['XFAIL']); + } + + if (isset($sections['STDIN'])) { + $this->phpUtil->setStdin($sections['STDIN']); + } + + if (isset($sections['ARGS'])) { + $this->phpUtil->setArgs($sections['ARGS']); + } + + if (CodeCoverage::instance()->isActive()) { + $codeCoverageCacheDirectory = null; + + if (CodeCoverage::instance()->codeCoverage()->cachesStaticAnalysis()) { + $codeCoverageCacheDirectory = CodeCoverage::instance()->codeCoverage()->cacheDirectory(); + } + + $this->renderForCoverage( + $code, + CodeCoverage::instance()->codeCoverage()->collectsBranchAndPathCoverage(), + $codeCoverageCacheDirectory, + ); + } + + $jobResult = $this->phpUtil->runJob($code, $this->stringifyIni($settings)); + $this->output = $jobResult['stdout'] ?? ''; + + if (CodeCoverage::instance()->isActive()) { + $coverage = $this->cleanupForCoverage(); + + CodeCoverage::instance()->codeCoverage()->start($this->filename, TestSize::large()); + + CodeCoverage::instance()->codeCoverage()->append( + $coverage, + $this->filename, + true, + TestStatus::unknown(), + ); + } + + $passed = true; + + try { + $this->assertPhptExpectation($sections, $this->output); + } catch (AssertionFailedError $e) { + $failure = $e; + + if ($xfail !== false) { + $failure = new IncompleteTestError($xfail, 0, $e); + } elseif ($e instanceof ExpectationFailedException) { + $comparisonFailure = $e->getComparisonFailure(); + + if ($comparisonFailure) { + $diff = $comparisonFailure->getDiff(); + } else { + $diff = $e->getMessage(); + } + + $hint = $this->getLocationHintFromDiff($diff, $sections); + $trace = array_merge($hint, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); + $failure = new PhptAssertionFailedError( + $e->getMessage(), + 0, + (string) $trace[0]['file'], + (int) $trace[0]['line'], + $trace, + $comparisonFailure ? $diff : '', + ); + } + + if ($failure instanceof IncompleteTestError) { + $emitter->testMarkedAsIncomplete($this->valueObjectForEvents(), ThrowableBuilder::from($failure)); + } else { + $emitter->testFailed($this->valueObjectForEvents(), ThrowableBuilder::from($failure), null); + } + + $passed = false; + } catch (Throwable $t) { + $emitter->testErrored($this->valueObjectForEvents(), ThrowableBuilder::from($t)); + + $passed = false; + } + + if ($passed) { + $emitter->testPassed($this->valueObjectForEvents()); + } + + $this->runClean($sections, CodeCoverage::instance()->isActive()); + + $emitter->testFinished($this->valueObjectForEvents(), 1); + } + + /** + * Returns the name of the test case. + */ + public function getName(): string + { + return $this->toString(); + } + + /** + * Returns a string representation of the test case. + */ + public function toString(): string + { + return $this->filename; + } + + public function usesDataProvider(): bool + { + return false; + } + + public function numberOfAssertionsPerformed(): int + { + return 1; + } + + public function output(): string + { + return $this->output; + } + + public function hasOutput(): bool + { + return !empty($this->output); + } + + public function sortId(): string + { + return $this->filename; + } + + /** + * @psalm-return list + */ + public function provides(): array + { + return []; + } + + /** + * @psalm-return list + */ + public function requires(): array + { + return []; + } + + /** + * @internal This method is not covered by the backward compatibility promise for PHPUnit + */ + public function valueObjectForEvents(): Phpt + { + return new Phpt($this->filename); + } + + /** + * Parse --INI-- section key value pairs and return as array. + */ + private function parseIniSection(array|string $content, array $ini = []): array + { + if (is_string($content)) { + $content = explode("\n", trim($content)); + } + + foreach ($content as $setting) { + if (!str_contains($setting, '=')) { + continue; + } + + $setting = explode('=', $setting, 2); + $name = trim($setting[0]); + $value = trim($setting[1]); + + if ($name === 'extension' || $name === 'zend_extension') { + if (!isset($ini[$name])) { + $ini[$name] = []; + } + + $ini[$name][] = $value; + + continue; + } + + $ini[$name] = $value; + } + + return $ini; + } + + private function parseEnvSection(string $content): array + { + $env = []; + + foreach (explode("\n", trim($content)) as $e) { + $e = explode('=', trim($e), 2); + + if ($e[0] !== '' && isset($e[1])) { + $env[$e[0]] = $e[1]; + } + } + + return $env; + } + + /** + * @throws Exception + * @throws ExpectationFailedException + */ + private function assertPhptExpectation(array $sections, string $output): void + { + $assertions = [ + 'EXPECT' => 'assertEquals', + 'EXPECTF' => 'assertStringMatchesFormat', + 'EXPECTREGEX' => 'assertMatchesRegularExpression', + ]; + + $actual = preg_replace('/\r\n/', "\n", trim($output)); + + foreach ($assertions as $sectionName => $sectionAssertion) { + if (isset($sections[$sectionName])) { + $sectionContent = preg_replace('/\r\n/', "\n", trim($sections[$sectionName])); + $expected = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent; + + Assert::$sectionAssertion($expected, $actual); + + return; + } + } + + throw new InvalidPhptFileException; + } + + private function shouldTestBeSkipped(array $sections, array $settings): bool + { + if (!isset($sections['SKIPIF'])) { + return false; + } + + $skipif = $this->render($sections['SKIPIF']); + $jobResult = $this->phpUtil->runJob($skipif, $this->stringifyIni($settings)); + + if (!strncasecmp('skip', ltrim($jobResult['stdout']), 4)) { + $message = ''; + + if (preg_match('/^\s*skip\s*(.+)\s*/i', $jobResult['stdout'], $skipMatch)) { + $message = substr($skipMatch[1], 2); + } + + EventFacade::emitter()->testSkipped( + $this->valueObjectForEvents(), + $message, + ); + + EventFacade::emitter()->testFinished($this->valueObjectForEvents(), 0); + + return true; + } + + return false; + } + + private function runClean(array $sections, bool $collectCoverage): void + { + $this->phpUtil->setStdin(''); + $this->phpUtil->setArgs(''); + + if (isset($sections['CLEAN'])) { + $cleanCode = $this->render($sections['CLEAN']); + + $this->phpUtil->runJob($cleanCode, $this->settings($collectCoverage)); + } + } + + /** + * @throws Exception + */ + private function parse(): array + { + $sections = []; + $section = ''; + + $unsupportedSections = [ + 'CGI', + 'COOKIE', + 'DEFLATE_POST', + 'EXPECTHEADERS', + 'EXTENSIONS', + 'GET', + 'GZIP_POST', + 'HEADERS', + 'PHPDBG', + 'POST', + 'POST_RAW', + 'PUT', + 'REDIRECTTEST', + 'REQUEST', + ]; + + $lineNr = 0; + + foreach (file($this->filename) as $line) { + $lineNr++; + + if (preg_match('/^--([_A-Z]+)--/', $line, $result)) { + $section = $result[1]; + $sections[$section] = ''; + $sections[$section . '_offset'] = $lineNr; + + continue; + } + + if (empty($section)) { + throw new InvalidPhptFileException; + } + + $sections[$section] .= $line; + } + + if (isset($sections['FILEEOF'])) { + $sections['FILE'] = rtrim($sections['FILEEOF'], "\r\n"); + unset($sections['FILEEOF']); + } + + $this->parseExternal($sections); + + if (!$this->validate($sections)) { + throw new InvalidPhptFileException; + } + + foreach ($unsupportedSections as $section) { + if (isset($sections[$section])) { + throw new UnsupportedPhptSectionException($section); + } + } + + return $sections; + } + + /** + * @throws Exception + */ + private function parseExternal(array &$sections): void + { + $allowSections = [ + 'FILE', + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ]; + $testDirectory = dirname($this->filename) . DIRECTORY_SEPARATOR; + + foreach ($allowSections as $section) { + if (isset($sections[$section . '_EXTERNAL'])) { + $externalFilename = trim($sections[$section . '_EXTERNAL']); + + if (!is_file($testDirectory . $externalFilename) || + !is_readable($testDirectory . $externalFilename)) { + throw new PhptExternalFileCannotBeLoadedException( + $section, + $testDirectory . $externalFilename, + ); + } + + $sections[$section] = file_get_contents($testDirectory . $externalFilename); + } + } + } + + private function validate(array $sections): bool + { + $requiredSections = [ + 'FILE', + [ + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ], + ]; + + foreach ($requiredSections as $section) { + if (is_array($section)) { + $foundSection = false; + + foreach ($section as $anySection) { + if (isset($sections[$anySection])) { + $foundSection = true; + + break; + } + } + + if (!$foundSection) { + return false; + } + + continue; + } + + if (!isset($sections[$section])) { + return false; + } + } + + return true; + } + + private function render(string $code): string + { + return str_replace( + [ + '__DIR__', + '__FILE__', + ], + [ + "'" . dirname($this->filename) . "'", + "'" . $this->filename . "'", + ], + $code, + ); + } + + private function getCoverageFiles(): array + { + $baseDir = dirname(realpath($this->filename)) . DIRECTORY_SEPARATOR; + $basename = basename($this->filename, 'phpt'); + + return [ + 'coverage' => $baseDir . $basename . 'coverage', + 'job' => $baseDir . $basename . 'php', + ]; + } + + /** + * @throws \SebastianBergmann\Template\InvalidArgumentException + */ + private function renderForCoverage(string &$job, bool $pathCoverage, ?string $codeCoverageCacheDirectory): void + { + $files = $this->getCoverageFiles(); + + $template = new Template( + __DIR__ . '/../Util/PHP/Template/PhptTestCase.tpl', + ); + + $composerAutoload = '\'\''; + + if (defined('PHPUNIT_COMPOSER_INSTALL')) { + $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); + } + + $phar = '\'\''; + + if (defined('__PHPUNIT_PHAR__')) { + $phar = var_export(__PHPUNIT_PHAR__, true); + } + + if ($codeCoverageCacheDirectory === null) { + $codeCoverageCacheDirectory = 'null'; + } else { + $codeCoverageCacheDirectory = "'" . $codeCoverageCacheDirectory . "'"; + } + + $bootstrap = ''; + + if (ConfigurationRegistry::get()->hasBootstrap()) { + $bootstrap = ConfigurationRegistry::get()->bootstrap(); + } + + $template->setVar( + [ + 'bootstrap' => $bootstrap, + 'composerAutoload' => $composerAutoload, + 'phar' => $phar, + 'job' => $files['job'], + 'coverageFile' => $files['coverage'], + 'driverMethod' => $pathCoverage ? 'forLineAndPathCoverage' : 'forLineCoverage', + 'codeCoverageCacheDirectory' => $codeCoverageCacheDirectory, + ], + ); + + file_put_contents($files['job'], $job); + + $job = $template->render(); + } + + private function cleanupForCoverage(): RawCodeCoverageData + { + $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]); + $files = $this->getCoverageFiles(); + + $buffer = false; + + if (is_file($files['coverage'])) { + $buffer = @file_get_contents($files['coverage']); + } + + if ($buffer !== false) { + $coverage = @unserialize($buffer); + + if ($coverage === false) { + $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]); + } + } + + foreach ($files as $file) { + @unlink($file); + } + + return $coverage; + } + + private function stringifyIni(array $ini): array + { + $settings = []; + + foreach ($ini as $key => $value) { + if (is_array($value)) { + foreach ($value as $val) { + $settings[] = $key . '=' . $val; + } + + continue; + } + + $settings[] = $key . '=' . $value; + } + + return $settings; + } + + private function getLocationHintFromDiff(string $message, array $sections): array + { + $needle = ''; + $previousLine = ''; + $block = 'message'; + + foreach (preg_split('/\r\n|\r|\n/', $message) as $line) { + $line = trim($line); + + if ($block === 'message' && $line === '--- Expected') { + $block = 'expected'; + } + + if ($block === 'expected' && $line === '@@ @@') { + $block = 'diff'; + } + + if ($block === 'diff') { + if (str_starts_with($line, '+')) { + $needle = $this->getCleanDiffLine($previousLine); + + break; + } + + if (str_starts_with($line, '-')) { + $needle = $this->getCleanDiffLine($line); + + break; + } + } + + if (!empty($line)) { + $previousLine = $line; + } + } + + return $this->getLocationHint($needle, $sections); + } + + private function getCleanDiffLine(string $line): string + { + if (preg_match('/^[\-+]([\'\"]?)(.*)\1$/', $line, $matches)) { + $line = $matches[2]; + } + + return $line; + } + + private function getLocationHint(string $needle, array $sections): array + { + $needle = trim($needle); + + if (empty($needle)) { + return [[ + 'file' => realpath($this->filename), + 'line' => 1, + ]]; + } + + $search = [ + // 'FILE', + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ]; + + foreach ($search as $section) { + if (!isset($sections[$section])) { + continue; + } + + if (isset($sections[$section . '_EXTERNAL'])) { + $externalFile = trim($sections[$section . '_EXTERNAL']); + + return [ + [ + 'file' => realpath(dirname($this->filename) . DIRECTORY_SEPARATOR . $externalFile), + 'line' => 1, + ], + [ + 'file' => realpath($this->filename), + 'line' => ($sections[$section . '_EXTERNAL_offset'] ?? 0) + 1, + ], + ]; + } + + $sectionOffset = $sections[$section . '_offset'] ?? 0; + $offset = $sectionOffset + 1; + + foreach (preg_split('/\r\n|\r|\n/', $sections[$section]) as $line) { + if (str_contains($line, $needle)) { + return [ + [ + 'file' => realpath($this->filename), + 'line' => $offset, + ], + ]; + } + + $offset++; + } + } + + return [ + [ + 'file' => realpath($this->filename), + 'line' => 1, + ], + ]; + } + + /** + * @psalm-return list + */ + private function settings(bool $collectCoverage): array + { + $settings = [ + 'allow_url_fopen=1', + 'auto_append_file=', + 'auto_prepend_file=', + 'disable_functions=', + 'display_errors=1', + 'docref_ext=.html', + 'docref_root=', + 'error_append_string=', + 'error_prepend_string=', + 'error_reporting=-1', + 'html_errors=0', + 'log_errors=0', + 'open_basedir=', + 'output_buffering=Off', + 'output_handler=', + 'report_memleaks=0', + 'report_zend_debug=0', + ]; + + if (extension_loaded('pcov')) { + if ($collectCoverage) { + $settings[] = 'pcov.enabled=1'; + } else { + $settings[] = 'pcov.enabled=0'; + } + } + + if (extension_loaded('xdebug')) { + if ($collectCoverage) { + $settings[] = 'xdebug.mode=coverage'; + } else { + $settings[] = 'xdebug.mode=off'; + } + } + + return $settings; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php new file mode 100644 index 000000000..a9e1eabb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/DefaultResultCache.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use const DIRECTORY_SEPARATOR; +use const LOCK_EX; +use function array_keys; +use function assert; +use function dirname; +use function file_get_contents; +use function file_put_contents; +use function is_array; +use function is_dir; +use function is_file; +use function json_decode; +use function json_encode; +use PHPUnit\Framework\TestStatus\TestStatus; +use PHPUnit\Runner\DirectoryDoesNotExistException; +use PHPUnit\Runner\Exception; +use PHPUnit\Util\Filesystem; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DefaultResultCache implements ResultCache +{ + /** + * @var int + */ + private const VERSION = 1; + + /** + * @var string + */ + private const DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache'; + private readonly string $cacheFilename; + + /** + * @psalm-var array + */ + private array $defects = []; + + /** + * @psalm-var array + */ + private array $times = []; + + public function __construct(?string $filepath = null) + { + if ($filepath !== null && is_dir($filepath)) { + $filepath .= DIRECTORY_SEPARATOR . self::DEFAULT_RESULT_CACHE_FILENAME; + } + + $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME; + } + + public function setStatus(string $id, TestStatus $status): void + { + if ($status->isSuccess()) { + return; + } + + $this->defects[$id] = $status; + } + + public function status(string $id): TestStatus + { + return $this->defects[$id] ?? TestStatus::unknown(); + } + + public function setTime(string $id, float $time): void + { + $this->times[$id] = $time; + } + + public function time(string $id): float + { + return $this->times[$id] ?? 0.0; + } + + public function load(): void + { + if (!is_file($this->cacheFilename)) { + return; + } + + $contents = file_get_contents($this->cacheFilename); + + if ($contents === false) { + return; + } + + $data = json_decode( + $contents, + true, + ); + + if ($data === null) { + return; + } + + if (!isset($data['version'])) { + return; + } + + if ($data['version'] !== self::VERSION) { + return; + } + + assert(isset($data['defects']) && is_array($data['defects'])); + assert(isset($data['times']) && is_array($data['times'])); + + foreach (array_keys($data['defects']) as $test) { + $data['defects'][$test] = TestStatus::from($data['defects'][$test]); + } + + $this->defects = $data['defects']; + $this->times = $data['times']; + } + + /** + * @throws Exception + */ + public function persist(): void + { + if (!Filesystem::createDirectory(dirname($this->cacheFilename))) { + throw new DirectoryDoesNotExistException(dirname($this->cacheFilename)); + } + + $data = [ + 'version' => self::VERSION, + 'defects' => [], + 'times' => $this->times, + ]; + + foreach ($this->defects as $test => $status) { + $data['defects'][$test] = $status->asInt(); + } + + file_put_contents( + $this->cacheFilename, + json_encode($data), + LOCK_EX, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.php new file mode 100644 index 000000000..f0cc4c302 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/NullResultCache.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 PHPUnit\Runner\ResultCache; + +use PHPUnit\Framework\TestStatus\TestStatus; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NullResultCache implements ResultCache +{ + public function setStatus(string $id, TestStatus $status): void + { + } + + public function status(string $id): TestStatus + { + return TestStatus::unknown(); + } + + public function setTime(string $id, float $time): void + { + } + + public function time(string $id): float + { + return 0; + } + + public function load(): void + { + } + + public function persist(): void + { + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php new file mode 100644 index 000000000..74efe2516 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCache.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Framework\TestStatus\TestStatus; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface ResultCache +{ + public function setStatus(string $id, TestStatus $status): void; + + public function status(string $id): TestStatus; + + public function setTime(string $id, float $time): void; + + public function time(string $id): float; + + public function load(): void; + + public function persist(): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php new file mode 100644 index 000000000..927725a83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/ResultCacheHandler.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use function round; +use PHPUnit\Event\Event; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\Telemetry\HRTime; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Framework\InvalidArgumentException; +use PHPUnit\Framework\TestStatus\TestStatus; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ResultCacheHandler +{ + private readonly ResultCache $cache; + private ?HRTime $time = null; + private int $testSuite = 0; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(ResultCache $cache, Facade $facade) + { + $this->cache = $cache; + + $this->registerSubscribers($facade); + } + + public function testSuiteStarted(): void + { + $this->testSuite++; + } + + public function testSuiteFinished(): void + { + $this->testSuite--; + + if ($this->testSuite === 0) { + $this->cache->persist(); + } + } + + public function testPrepared(Prepared $event): void + { + $this->time = $event->telemetryInfo()->time(); + } + + public function testMarkedIncomplete(MarkedIncomplete $event): void + { + $this->cache->setStatus( + $event->test()->id(), + TestStatus::incomplete($event->throwable()->message()), + ); + } + + public function testConsideredRisky(ConsideredRisky $event): void + { + $this->cache->setStatus( + $event->test()->id(), + TestStatus::risky($event->message()), + ); + } + + public function testErrored(Errored $event): void + { + $this->cache->setStatus( + $event->test()->id(), + TestStatus::error($event->throwable()->message()), + ); + } + + public function testFailed(Failed $event): void + { + $this->cache->setStatus( + $event->test()->id(), + TestStatus::failure($event->throwable()->message()), + ); + } + + /** + * @throws \PHPUnit\Event\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function testSkipped(Skipped $event): void + { + $this->cache->setStatus( + $event->test()->id(), + TestStatus::skipped($event->message()), + ); + + $this->cache->setTime($event->test()->id(), $this->duration($event)); + } + + /** + * @throws \PHPUnit\Event\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function testFinished(Finished $event): void + { + $this->cache->setTime($event->test()->id(), $this->duration($event)); + + $this->time = null; + } + + /** + * @throws \PHPUnit\Event\InvalidArgumentException + * @throws InvalidArgumentException + */ + private function duration(Event $event): float + { + if ($this->time === null) { + return 0.0; + } + + return round($event->telemetryInfo()->time()->duration($this->time)->asFloat(), 3); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerSubscribers(Facade $facade): void + { + $facade->registerSubscribers( + new TestSuiteStartedSubscriber($this), + new TestSuiteFinishedSubscriber($this), + new TestPreparedSubscriber($this), + new TestMarkedIncompleteSubscriber($this), + new TestConsideredRiskySubscriber($this), + new TestErroredSubscriber($this), + new TestFailedSubscriber($this), + new TestSkippedSubscriber($this), + new TestFinishedSubscriber($this), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php new file mode 100644 index 000000000..254b36a48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly ResultCacheHandler $handler; + + public function __construct(ResultCacheHandler $handler) + { + $this->handler = $handler; + } + + protected function handler(): ResultCacheHandler + { + return $this->handler; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php new file mode 100644 index 000000000..5675f46dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\ConsideredRiskySubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber +{ + public function notify(ConsideredRisky $event): void + { + $this->handler()->testConsideredRisky($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php new file mode 100644 index 000000000..6acc7fbf9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestErroredSubscriber extends Subscriber implements ErroredSubscriber +{ + public function notify(Errored $event): void + { + $this->handler()->testErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php new file mode 100644 index 000000000..d95289860 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\FailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailedSubscriber extends Subscriber implements FailedSubscriber +{ + public function notify(Failed $event): void + { + $this->handler()->testFailed($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..d04573790 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + /** + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function notify(Finished $event): void + { + $this->handler()->testFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php new file mode 100644 index 000000000..e98383591 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\MarkedIncompleteSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber +{ + public function notify(MarkedIncomplete $event): void + { + $this->handler()->testMarkedIncomplete($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php new file mode 100644 index 000000000..6e7cd77aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\PreparedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber +{ + public function notify(Prepared $event): void + { + $this->handler()->testPrepared($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php new file mode 100644 index 000000000..b9ad4e344 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\InvalidArgumentException; +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + /** + * @throws \PHPUnit\Framework\InvalidArgumentException + * @throws InvalidArgumentException + */ + public function notify(Skipped $event): void + { + $this->handler()->testSkipped($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php new file mode 100644 index 000000000..1c6fef3a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\TestSuite\Finished; +use PHPUnit\Event\TestSuite\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $this->handler()->testSuiteFinished(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php new file mode 100644 index 000000000..e56874fa4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner\ResultCache; + +use PHPUnit\Event\TestSuite\Started; +use PHPUnit\Event\TestSuite\StartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber +{ + public function notify(Started $event): void + { + $this->handler()->testSuiteStarted(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Collector.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Collector.php new file mode 100644 index 000000000..c26eef16a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Collector.php @@ -0,0 +1,660 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use function array_values; +use function assert; +use function implode; +use function str_contains; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErrorTriggered; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\Skipped as TestSkipped; +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\TestRunner\DeprecationTriggered as TestRunnerDeprecationTriggered; +use PHPUnit\Event\TestRunner\ExecutionStarted; +use PHPUnit\Event\TestRunner\WarningTriggered as TestRunnerWarningTriggered; +use PHPUnit\Event\TestSuite\Finished as TestSuiteFinished; +use PHPUnit\Event\TestSuite\Skipped as TestSuiteSkipped; +use PHPUnit\Event\TestSuite\Started as TestSuiteStarted; +use PHPUnit\Event\TestSuite\TestSuiteForTestClass; +use PHPUnit\Event\TestSuite\TestSuiteForTestMethodWithDataProvider; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\TestRunner\TestResult\Issues\Issue; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\SourceFilter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Collector +{ + private readonly Source $source; + private int $numberOfTests = 0; + private int $numberOfTestsRun = 0; + private int $numberOfAssertions = 0; + private bool $prepared = false; + private bool $currentTestSuiteForTestClassFailed = false; + + /** + * @psalm-var non-negative-int + */ + private int $numberOfIssuesIgnoredByBaseline = 0; + + /** + * @psalm-var list + */ + private array $testErroredEvents = []; + + /** + * @psalm-var list + */ + private array $testFailedEvents = []; + + /** + * @psalm-var list + */ + private array $testMarkedIncompleteEvents = []; + + /** + * @psalm-var list + */ + private array $testSuiteSkippedEvents = []; + + /** + * @psalm-var list + */ + private array $testSkippedEvents = []; + + /** + * @psalm-var array> + */ + private array $testConsideredRiskyEvents = []; + + /** + * @psalm-var array> + */ + private array $testTriggeredPhpunitDeprecationEvents = []; + + /** + * @psalm-var array> + */ + private array $testTriggeredPhpunitErrorEvents = []; + + /** + * @psalm-var array> + */ + private array $testTriggeredPhpunitWarningEvents = []; + + /** + * @psalm-var list + */ + private array $testRunnerTriggeredWarningEvents = []; + + /** + * @psalm-var list + */ + private array $testRunnerTriggeredDeprecationEvents = []; + + /** + * @psalm-var array + */ + private array $errors = []; + + /** + * @psalm-var array + */ + private array $deprecations = []; + + /** + * @psalm-var array + */ + private array $notices = []; + + /** + * @psalm-var array + */ + private array $warnings = []; + + /** + * @psalm-var array + */ + private array $phpDeprecations = []; + + /** + * @psalm-var array + */ + private array $phpNotices = []; + + /** + * @psalm-var array + */ + private array $phpWarnings = []; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Facade $facade, Source $source) + { + $facade->registerSubscribers( + new ExecutionStartedSubscriber($this), + new TestSuiteSkippedSubscriber($this), + new TestSuiteStartedSubscriber($this), + new TestSuiteFinishedSubscriber($this), + new TestPreparedSubscriber($this), + new TestFinishedSubscriber($this), + new BeforeTestClassMethodErroredSubscriber($this), + new TestErroredSubscriber($this), + new TestFailedSubscriber($this), + new TestMarkedIncompleteSubscriber($this), + new TestSkippedSubscriber($this), + new TestConsideredRiskySubscriber($this), + new TestTriggeredDeprecationSubscriber($this), + new TestTriggeredErrorSubscriber($this), + new TestTriggeredNoticeSubscriber($this), + new TestTriggeredPhpDeprecationSubscriber($this), + new TestTriggeredPhpNoticeSubscriber($this), + new TestTriggeredPhpunitDeprecationSubscriber($this), + new TestTriggeredPhpunitErrorSubscriber($this), + new TestTriggeredPhpunitWarningSubscriber($this), + new TestTriggeredPhpWarningSubscriber($this), + new TestTriggeredWarningSubscriber($this), + new TestRunnerTriggeredDeprecationSubscriber($this), + new TestRunnerTriggeredWarningSubscriber($this), + ); + + $this->source = $source; + } + + public function result(): TestResult + { + return new TestResult( + $this->numberOfTests, + $this->numberOfTestsRun, + $this->numberOfAssertions, + $this->testErroredEvents, + $this->testFailedEvents, + $this->testConsideredRiskyEvents, + $this->testSuiteSkippedEvents, + $this->testSkippedEvents, + $this->testMarkedIncompleteEvents, + $this->testTriggeredPhpunitDeprecationEvents, + $this->testTriggeredPhpunitErrorEvents, + $this->testTriggeredPhpunitWarningEvents, + $this->testRunnerTriggeredDeprecationEvents, + $this->testRunnerTriggeredWarningEvents, + array_values($this->errors), + array_values($this->deprecations), + array_values($this->notices), + array_values($this->warnings), + array_values($this->phpDeprecations), + array_values($this->phpNotices), + array_values($this->phpWarnings), + $this->numberOfIssuesIgnoredByBaseline, + ); + } + + public function executionStarted(ExecutionStarted $event): void + { + $this->numberOfTests = $event->testSuite()->count(); + } + + public function testSuiteSkipped(TestSuiteSkipped $event): void + { + $testSuite = $event->testSuite(); + + if (!$testSuite->isForTestClass()) { + return; + } + + $this->testSuiteSkippedEvents[] = $event; + } + + public function testSuiteStarted(TestSuiteStarted $event): void + { + $testSuite = $event->testSuite(); + + if (!$testSuite->isForTestClass()) { + return; + } + + $this->currentTestSuiteForTestClassFailed = false; + } + + public function testSuiteFinished(TestSuiteFinished $event): void + { + if ($this->currentTestSuiteForTestClassFailed) { + return; + } + + $testSuite = $event->testSuite(); + + if ($testSuite->isWithName()) { + return; + } + + if ($testSuite->isForTestMethodWithDataProvider()) { + assert($testSuite instanceof TestSuiteForTestMethodWithDataProvider); + + $test = $testSuite->tests()->asArray()[0]; + + assert($test instanceof TestMethod); + + PassedTests::instance()->testMethodPassed($test, null); + + return; + } + + assert($testSuite instanceof TestSuiteForTestClass); + + PassedTests::instance()->testClassPassed($testSuite->className()); + } + + public function testPrepared(): void + { + $this->prepared = true; + } + + public function testFinished(Finished $event): void + { + $this->numberOfAssertions += $event->numberOfAssertionsPerformed(); + + $this->numberOfTestsRun++; + + $this->prepared = false; + } + + public function beforeTestClassMethodErrored(BeforeFirstTestMethodErrored $event): void + { + $this->testErroredEvents[] = $event; + + $this->numberOfTestsRun++; + } + + public function testErrored(Errored $event): void + { + $this->testErroredEvents[] = $event; + + $this->currentTestSuiteForTestClassFailed = true; + + /* + * @todo Eliminate this special case + */ + if (str_contains($event->asString(), 'Test was run in child process and ended unexpectedly')) { + return; + } + + if (!$this->prepared) { + $this->numberOfTestsRun++; + } + } + + public function testFailed(Failed $event): void + { + $this->testFailedEvents[] = $event; + + $this->currentTestSuiteForTestClassFailed = true; + } + + public function testMarkedIncomplete(MarkedIncomplete $event): void + { + $this->testMarkedIncompleteEvents[] = $event; + } + + public function testSkipped(TestSkipped $event): void + { + $this->testSkippedEvents[] = $event; + + if (!$this->prepared) { + $this->numberOfTestsRun++; + } + } + + public function testConsideredRisky(ConsideredRisky $event): void + { + if (!isset($this->testConsideredRiskyEvents[$event->test()->id()])) { + $this->testConsideredRiskyEvents[$event->test()->id()] = []; + } + + $this->testConsideredRiskyEvents[$event->test()->id()][] = $event; + } + + public function testTriggeredDeprecation(DeprecationTriggered $event): void + { + if ($event->ignoredByTest()) { + return; + } + + if ($event->ignoredByBaseline()) { + $this->numberOfIssuesIgnoredByBaseline++; + + return; + } + + if (!$this->source->ignoreSuppressionOfDeprecations() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->deprecations[$id])) { + $this->deprecations[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->deprecations[$id]->triggeredBy($event->test()); + } + + public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void + { + if ($event->ignoredByTest()) { + return; + } + + if ($event->ignoredByBaseline()) { + $this->numberOfIssuesIgnoredByBaseline++; + + return; + } + + if (!$this->source->ignoreSuppressionOfPhpDeprecations() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->phpDeprecations[$id])) { + $this->phpDeprecations[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->phpDeprecations[$id]->triggeredBy($event->test()); + } + + public function testTriggeredPhpunitDeprecation(PhpunitDeprecationTriggered $event): void + { + if (!isset($this->testTriggeredPhpunitDeprecationEvents[$event->test()->id()])) { + $this->testTriggeredPhpunitDeprecationEvents[$event->test()->id()] = []; + } + + $this->testTriggeredPhpunitDeprecationEvents[$event->test()->id()][] = $event; + } + + public function testTriggeredError(ErrorTriggered $event): void + { + if (!$this->source->ignoreSuppressionOfErrors() && $event->wasSuppressed()) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->errors[$id])) { + $this->errors[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->errors[$id]->triggeredBy($event->test()); + } + + public function testTriggeredNotice(NoticeTriggered $event): void + { + if ($event->ignoredByBaseline()) { + $this->numberOfIssuesIgnoredByBaseline++; + + return; + } + + if (!$this->source->ignoreSuppressionOfNotices() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->notices[$id])) { + $this->notices[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->notices[$id]->triggeredBy($event->test()); + } + + public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void + { + if ($event->ignoredByBaseline()) { + $this->numberOfIssuesIgnoredByBaseline++; + + return; + } + + if (!$this->source->ignoreSuppressionOfPhpNotices() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->phpNotices[$id])) { + $this->phpNotices[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->phpNotices[$id]->triggeredBy($event->test()); + } + + public function testTriggeredWarning(WarningTriggered $event): void + { + if ($event->ignoredByBaseline()) { + $this->numberOfIssuesIgnoredByBaseline++; + + return; + } + + if (!$this->source->ignoreSuppressionOfWarnings() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->warnings[$id])) { + $this->warnings[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->warnings[$id]->triggeredBy($event->test()); + } + + public function testTriggeredPhpWarning(PhpWarningTriggered $event): void + { + if ($event->ignoredByBaseline()) { + $this->numberOfIssuesIgnoredByBaseline++; + + return; + } + + if (!$this->source->ignoreSuppressionOfPhpWarnings() && $event->wasSuppressed()) { + return; + } + + if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + $id = $this->issueId($event); + + if (!isset($this->phpWarnings[$id])) { + $this->phpWarnings[$id] = Issue::from( + $event->file(), + $event->line(), + $event->message(), + $event->test(), + ); + + return; + } + + $this->phpWarnings[$id]->triggeredBy($event->test()); + } + + public function testTriggeredPhpunitError(PhpunitErrorTriggered $event): void + { + if (!isset($this->testTriggeredPhpunitErrorEvents[$event->test()->id()])) { + $this->testTriggeredPhpunitErrorEvents[$event->test()->id()] = []; + } + + $this->testTriggeredPhpunitErrorEvents[$event->test()->id()][] = $event; + } + + public function testTriggeredPhpunitWarning(PhpunitWarningTriggered $event): void + { + if (!isset($this->testTriggeredPhpunitWarningEvents[$event->test()->id()])) { + $this->testTriggeredPhpunitWarningEvents[$event->test()->id()] = []; + } + + $this->testTriggeredPhpunitWarningEvents[$event->test()->id()][] = $event; + } + + public function testRunnerTriggeredDeprecation(TestRunnerDeprecationTriggered $event): void + { + $this->testRunnerTriggeredDeprecationEvents[] = $event; + } + + public function testRunnerTriggeredWarning(TestRunnerWarningTriggered $event): void + { + $this->testRunnerTriggeredWarningEvents[] = $event; + } + + public function hasErroredTests(): bool + { + return !empty($this->testErroredEvents); + } + + public function hasFailedTests(): bool + { + return !empty($this->testFailedEvents); + } + + public function hasRiskyTests(): bool + { + return !empty($this->testConsideredRiskyEvents); + } + + public function hasSkippedTests(): bool + { + return !empty($this->testSkippedEvents); + } + + public function hasIncompleteTests(): bool + { + return !empty($this->testMarkedIncompleteEvents); + } + + public function hasDeprecations(): bool + { + return !empty($this->deprecations) || + !empty($this->phpDeprecations) || + !empty($this->testTriggeredPhpunitDeprecationEvents) || + !empty($this->testRunnerTriggeredDeprecationEvents); + } + + public function hasNotices(): bool + { + return !empty($this->notices) || + !empty($this->phpNotices); + } + + public function hasWarnings(): bool + { + return !empty($this->warnings) || + !empty($this->phpWarnings) || + !empty($this->testTriggeredPhpunitWarningEvents) || + !empty($this->testRunnerTriggeredWarningEvents); + } + + /** + * @psalm-return non-empty-string + */ + private function issueId(DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): string + { + return implode(':', [$event->file(), $event->line(), $event->message()]); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Facade.php new file mode 100644 index 000000000..75b7471e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Facade.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Facade +{ + private static ?Collector $collector = null; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public static function init(): void + { + self::collector(); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public static function result(): TestResult + { + return self::collector()->result(); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public static function shouldStop(): bool + { + $configuration = ConfigurationRegistry::get(); + $collector = self::collector(); + + if (($configuration->stopOnDefect() || $configuration->stopOnError()) && $collector->hasErroredTests()) { + return true; + } + + if (($configuration->stopOnDefect() || $configuration->stopOnFailure()) && $collector->hasFailedTests()) { + return true; + } + + if (($configuration->stopOnDefect() || $configuration->stopOnWarning()) && $collector->hasWarnings()) { + return true; + } + + if (($configuration->stopOnDefect() || $configuration->stopOnRisky()) && $collector->hasRiskyTests()) { + return true; + } + + if ($configuration->stopOnDeprecation() && $collector->hasDeprecations()) { + return true; + } + + if ($configuration->stopOnNotice() && $collector->hasNotices()) { + return true; + } + + if ($configuration->stopOnIncomplete() && $collector->hasIncompleteTests()) { + return true; + } + + if ($configuration->stopOnSkipped() && $collector->hasSkippedTests()) { + return true; + } + + return false; + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private static function collector(): Collector + { + if (self::$collector === null) { + $configuration = ConfigurationRegistry::get(); + + self::$collector = new Collector( + EventFacade::instance(), + $configuration->source(), + ); + } + + return self::$collector; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Issue.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Issue.php new file mode 100644 index 000000000..dcfd17f82 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Issue.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult\Issues; + +use PHPUnit\Event\Code\Test; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Issue +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $file; + + /** + * @psalm-var positive-int + */ + private readonly int $line; + + /** + * @psalm-var non-empty-string + */ + private readonly string $description; + + /** + * @psalm-var non-empty-array + */ + private array $triggeringTests; + + /** + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * @psalm-param non-empty-string $description + */ + public static function from(string $file, int $line, string $description, Test $triggeringTest): self + { + return new self($file, $line, $description, $triggeringTest); + } + + /** + * @psalm-param non-empty-string $file + * @psalm-param positive-int $line + * @psalm-param non-empty-string $description + */ + private function __construct(string $file, int $line, string $description, Test $triggeringTest) + { + $this->file = $file; + $this->line = $line; + $this->description = $description; + + $this->triggeringTests = [ + $triggeringTest->id() => [ + 'test' => $triggeringTest, + 'count' => 1, + ], + ]; + } + + public function triggeredBy(Test $test): void + { + if (isset($this->triggeringTests[$test->id()])) { + $this->triggeringTests[$test->id()]['count']++; + + return; + } + + $this->triggeringTests[$test->id()] = [ + 'test' => $test, + 'count' => 1, + ]; + } + + /** + * @psalm-return non-empty-string + */ + public function file(): string + { + return $this->file; + } + + /** + * @psalm-return positive-int + */ + public function line(): int + { + return $this->line; + } + + /** + * @psalm-return non-empty-string + */ + public function description(): string + { + return $this->description; + } + + /** + * @psalm-return non-empty-array + */ + public function triggeringTests(): array + { + return $this->triggeringTests; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/PassedTests.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/PassedTests.php new file mode 100644 index 000000000..b448bc86e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/PassedTests.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use function array_merge; +use function assert; +use function in_array; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Framework\TestSize\Known; +use PHPUnit\Framework\TestSize\TestSize; +use PHPUnit\Metadata\Api\Groups; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PassedTests +{ + private static ?self $instance = null; + + /** + * @psalm-var list + */ + private array $passedTestClasses = []; + + /** + * @psalm-var array + */ + private array $passedTestMethods = []; + + public static function instance(): self + { + if (self::$instance !== null) { + return self::$instance; + } + + self::$instance = new self; + + return self::$instance; + } + + /** + * @psalm-param class-string $className + */ + public function testClassPassed(string $className): void + { + $this->passedTestClasses[] = $className; + } + + public function testMethodPassed(TestMethod $test, mixed $returnValue): void + { + $size = (new Groups)->size( + $test->className(), + $test->methodName(), + ); + + $this->passedTestMethods[$test->className() . '::' . $test->methodName()] = [ + 'returnValue' => $returnValue, + 'size' => $size, + ]; + } + + public function import(self $other): void + { + $this->passedTestClasses = array_merge( + $this->passedTestClasses, + $other->passedTestClasses, + ); + + $this->passedTestMethods = array_merge( + $this->passedTestMethods, + $other->passedTestMethods, + ); + } + + /** + * @psalm-param class-string $className + */ + public function hasTestClassPassed(string $className): bool + { + return in_array($className, $this->passedTestClasses, true); + } + + public function hasTestMethodPassed(string $method): bool + { + return isset($this->passedTestMethods[$method]); + } + + public function isGreaterThan(string $method, TestSize $other): bool + { + if ($other->isUnknown()) { + return false; + } + + assert($other instanceof Known); + + $size = $this->passedTestMethods[$method]['size']; + + if ($size->isUnknown()) { + return false; + } + + assert($size instanceof Known); + + return $size->isGreaterThan($other); + } + + public function returnValue(string $method): mixed + { + if (isset($this->passedTestMethods[$method])) { + return $this->passedTestMethods[$method]['returnValue']; + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php new file mode 100644 index 000000000..c9facc248 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; +use PHPUnit\Event\Test\BeforeFirstTestMethodErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeTestClassMethodErroredSubscriber extends Subscriber implements BeforeFirstTestMethodErroredSubscriber +{ + public function notify(BeforeFirstTestMethodErrored $event): void + { + $this->collector()->beforeTestClassMethodErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php new file mode 100644 index 000000000..56f16d76d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\TestRunner\ExecutionStarted; +use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber as TestRunnerExecutionStartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ExecutionStartedSubscriber extends Subscriber implements TestRunnerExecutionStartedSubscriber +{ + public function notify(ExecutionStarted $event): void + { + $this->collector()->executionStarted($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php new file mode 100644 index 000000000..f9abbb77a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly Collector $collector; + + public function __construct(Collector $collector) + { + $this->collector = $collector; + } + + protected function collector(): Collector + { + return $this->collector; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php new file mode 100644 index 000000000..b3656e435 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\ConsideredRiskySubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber +{ + public function notify(ConsideredRisky $event): void + { + $this->collector()->testConsideredRisky($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php new file mode 100644 index 000000000..272c99243 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestErroredSubscriber extends Subscriber implements ErroredSubscriber +{ + public function notify(Errored $event): void + { + $this->collector()->testErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php new file mode 100644 index 000000000..c0b059dfd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\FailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailedSubscriber extends Subscriber implements FailedSubscriber +{ + public function notify(Failed $event): void + { + $this->collector()->testFailed($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..6ce115b42 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $this->collector()->testFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php new file mode 100644 index 000000000..b57a0984b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\MarkedIncompleteSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber +{ + public function notify(MarkedIncomplete $event): void + { + $this->collector()->testMarkedIncomplete($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php new file mode 100644 index 000000000..b68c0d5e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\PreparedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber +{ + public function notify(Prepared $event): void + { + $this->collector()->testPrepared(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php new file mode 100644 index 000000000..0550adae1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\TestRunner\DeprecationTriggered; +use PHPUnit\Event\TestRunner\DeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunnerTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber +{ + public function notify(DeprecationTriggered $event): void + { + $this->collector()->testRunnerTriggeredDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php new file mode 100644 index 000000000..b66e74941 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\TestRunner\WarningTriggered; +use PHPUnit\Event\TestRunner\WarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunnerTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber +{ + public function notify(WarningTriggered $event): void + { + $this->collector()->testRunnerTriggeredWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php new file mode 100644 index 000000000..4cc445453 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + public function notify(Skipped $event): void + { + $this->collector()->testSkipped($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php new file mode 100644 index 000000000..125cd5199 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\TestSuite\Finished; +use PHPUnit\Event\TestSuite\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $this->collector()->testSuiteFinished($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php new file mode 100644 index 000000000..bf26b15cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\TestSuite\Skipped; +use PHPUnit\Event\TestSuite\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + public function notify(Skipped $event): void + { + $this->collector()->testSuiteSkipped($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php new file mode 100644 index 000000000..ef8c8d09c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\TestSuite\Started; +use PHPUnit\Event\TestSuite\StartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber +{ + public function notify(Started $event): void + { + $this->collector()->testSuiteStarted($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php new file mode 100644 index 000000000..6185723e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber +{ + public function notify(DeprecationTriggered $event): void + { + $this->collector()->testTriggeredDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php new file mode 100644 index 000000000..c5daf0d7f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\ErrorTriggered; +use PHPUnit\Event\Test\ErrorTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredErrorSubscriber extends Subscriber implements ErrorTriggeredSubscriber +{ + public function notify(ErrorTriggered $event): void + { + $this->collector()->testTriggeredError($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php new file mode 100644 index 000000000..e0c4b55a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\NoticeTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber +{ + public function notify(NoticeTriggered $event): void + { + $this->collector()->testTriggeredNotice($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php new file mode 100644 index 000000000..b0ddcba0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber +{ + public function notify(PhpDeprecationTriggered $event): void + { + $this->collector()->testTriggeredPhpDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php new file mode 100644 index 000000000..3f6e54c33 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber +{ + public function notify(PhpNoticeTriggered $event): void + { + $this->collector()->testTriggeredPhpNotice($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php new file mode 100644 index 000000000..c8af28990 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber +{ + public function notify(PhpWarningTriggered $event): void + { + $this->collector()->testTriggeredPhpWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php new file mode 100644 index 000000000..704895bef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitDeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitDeprecationSubscriber extends Subscriber implements PhpunitDeprecationTriggeredSubscriber +{ + public function notify(PhpunitDeprecationTriggered $event): void + { + $this->collector()->testTriggeredPhpunitDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php new file mode 100644 index 000000000..0fcb0176d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitErrorTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitErrorSubscriber extends Subscriber implements PhpunitErrorTriggeredSubscriber +{ + public function notify(PhpunitErrorTriggered $event): void + { + $this->collector()->testTriggeredPhpunitError($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php new file mode 100644 index 000000000..6c6c49ad4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitWarningSubscriber extends Subscriber implements PhpunitWarningTriggeredSubscriber +{ + public function notify(PhpunitWarningTriggered $event): void + { + $this->collector()->testTriggeredPhpunitWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php new file mode 100644 index 000000000..a68d1e231 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\Test\WarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber +{ + public function notify(WarningTriggered $event): void + { + $this->collector()->testTriggeredWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/TestResult.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/TestResult.php new file mode 100644 index 000000000..db9d45595 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestResult/TestResult.php @@ -0,0 +1,576 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TestRunner\TestResult; + +use function count; +use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\Skipped as TestSkipped; +use PHPUnit\Event\TestRunner\DeprecationTriggered as TestRunnerDeprecationTriggered; +use PHPUnit\Event\TestRunner\WarningTriggered as TestRunnerWarningTriggered; +use PHPUnit\Event\TestSuite\Skipped as TestSuiteSkipped; +use PHPUnit\TestRunner\TestResult\Issues\Issue; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestResult +{ + private readonly int $numberOfTests; + private readonly int $numberOfTestsRun; + private readonly int $numberOfAssertions; + + /** + * @psalm-var list + */ + private readonly array $testErroredEvents; + + /** + * @psalm-var list + */ + private readonly array $testFailedEvents; + + /** + * @psalm-var list + */ + private readonly array $testMarkedIncompleteEvents; + + /** + * @psalm-var list + */ + private readonly array $testSuiteSkippedEvents; + + /** + * @psalm-var list + */ + private readonly array $testSkippedEvents; + + /** + * @psalm-var array> + */ + private readonly array $testConsideredRiskyEvents; + + /** + * @psalm-var array> + */ + private readonly array $testTriggeredPhpunitDeprecationEvents; + + /** + * @psalm-var array> + */ + private readonly array $testTriggeredPhpunitErrorEvents; + + /** + * @psalm-var array> + */ + private readonly array $testTriggeredPhpunitWarningEvents; + + /** + * @psalm-var list + */ + private readonly array $testRunnerTriggeredDeprecationEvents; + + /** + * @psalm-var list + */ + private readonly array $testRunnerTriggeredWarningEvents; + + /** + * @psalm-var list + */ + private readonly array $errors; + + /** + * @psalm-var list + */ + private readonly array $deprecations; + + /** + * @psalm-var list + */ + private readonly array $notices; + + /** + * @psalm-var list + */ + private readonly array $warnings; + + /** + * @psalm-var list + */ + private readonly array $phpDeprecations; + + /** + * @psalm-var list + */ + private readonly array $phpNotices; + + /** + * @psalm-var list + */ + private readonly array $phpWarnings; + + /** + * @psalm-var non-negative-int + */ + private readonly int $numberOfIssuesIgnoredByBaseline; + + /** + * @psalm-param list $testErroredEvents + * @psalm-param list $testFailedEvents + * @psalm-param array> $testConsideredRiskyEvents + * @psalm-param list $testSuiteSkippedEvents + * @psalm-param list $testSkippedEvents + * @psalm-param list $testMarkedIncompleteEvents + * @psalm-param array> $testTriggeredPhpunitDeprecationEvents + * @psalm-param array> $testTriggeredPhpunitErrorEvents + * @psalm-param array> $testTriggeredPhpunitWarningEvents + * @psalm-param list $testRunnerTriggeredDeprecationEvents + * @psalm-param list $testRunnerTriggeredWarningEvents + * @psalm-param list $errors + * @psalm-param list $deprecations + * @psalm-param list $notices + * @psalm-param list $warnings + * @psalm-param list $phpDeprecations + * @psalm-param list $phpNotices + * @psalm-param list $phpWarnings + * @psalm-param non-negative-int $numberOfIssuesIgnoredByBaseline + */ + public function __construct(int $numberOfTests, int $numberOfTestsRun, int $numberOfAssertions, array $testErroredEvents, array $testFailedEvents, array $testConsideredRiskyEvents, array $testSuiteSkippedEvents, array $testSkippedEvents, array $testMarkedIncompleteEvents, array $testTriggeredPhpunitDeprecationEvents, array $testTriggeredPhpunitErrorEvents, array $testTriggeredPhpunitWarningEvents, array $testRunnerTriggeredDeprecationEvents, array $testRunnerTriggeredWarningEvents, array $errors, array $deprecations, array $notices, array $warnings, array $phpDeprecations, array $phpNotices, array $phpWarnings, int $numberOfIssuesIgnoredByBaseline) + { + $this->numberOfTests = $numberOfTests; + $this->numberOfTestsRun = $numberOfTestsRun; + $this->numberOfAssertions = $numberOfAssertions; + $this->testErroredEvents = $testErroredEvents; + $this->testFailedEvents = $testFailedEvents; + $this->testConsideredRiskyEvents = $testConsideredRiskyEvents; + $this->testSuiteSkippedEvents = $testSuiteSkippedEvents; + $this->testSkippedEvents = $testSkippedEvents; + $this->testMarkedIncompleteEvents = $testMarkedIncompleteEvents; + $this->testTriggeredPhpunitDeprecationEvents = $testTriggeredPhpunitDeprecationEvents; + $this->testTriggeredPhpunitErrorEvents = $testTriggeredPhpunitErrorEvents; + $this->testTriggeredPhpunitWarningEvents = $testTriggeredPhpunitWarningEvents; + $this->testRunnerTriggeredDeprecationEvents = $testRunnerTriggeredDeprecationEvents; + $this->testRunnerTriggeredWarningEvents = $testRunnerTriggeredWarningEvents; + $this->errors = $errors; + $this->deprecations = $deprecations; + $this->notices = $notices; + $this->warnings = $warnings; + $this->phpDeprecations = $phpDeprecations; + $this->phpNotices = $phpNotices; + $this->phpWarnings = $phpWarnings; + $this->numberOfIssuesIgnoredByBaseline = $numberOfIssuesIgnoredByBaseline; + } + + public function numberOfTestsRun(): int + { + return $this->numberOfTestsRun; + } + + public function numberOfAssertions(): int + { + return $this->numberOfAssertions; + } + + /** + * @psalm-return list + */ + public function testErroredEvents(): array + { + return $this->testErroredEvents; + } + + public function numberOfTestErroredEvents(): int + { + return count($this->testErroredEvents); + } + + public function hasTestErroredEvents(): bool + { + return $this->numberOfTestErroredEvents() > 0; + } + + /** + * @psalm-return list + */ + public function testFailedEvents(): array + { + return $this->testFailedEvents; + } + + public function numberOfTestFailedEvents(): int + { + return count($this->testFailedEvents); + } + + public function hasTestFailedEvents(): bool + { + return $this->numberOfTestFailedEvents() > 0; + } + + /** + * @psalm-return array> + */ + public function testConsideredRiskyEvents(): array + { + return $this->testConsideredRiskyEvents; + } + + public function numberOfTestsWithTestConsideredRiskyEvents(): int + { + return count($this->testConsideredRiskyEvents); + } + + public function hasTestConsideredRiskyEvents(): bool + { + return $this->numberOfTestsWithTestConsideredRiskyEvents() > 0; + } + + /** + * @psalm-return list + */ + public function testSuiteSkippedEvents(): array + { + return $this->testSuiteSkippedEvents; + } + + public function numberOfTestSuiteSkippedEvents(): int + { + return count($this->testSuiteSkippedEvents); + } + + public function hasTestSuiteSkippedEvents(): bool + { + return $this->numberOfTestSuiteSkippedEvents() > 0; + } + + /** + * @psalm-return list + */ + public function testSkippedEvents(): array + { + return $this->testSkippedEvents; + } + + public function numberOfTestSkippedEvents(): int + { + return count($this->testSkippedEvents); + } + + public function hasTestSkippedEvents(): bool + { + return $this->numberOfTestSkippedEvents() > 0; + } + + /** + * @psalm-return list + */ + public function testMarkedIncompleteEvents(): array + { + return $this->testMarkedIncompleteEvents; + } + + public function numberOfTestMarkedIncompleteEvents(): int + { + return count($this->testMarkedIncompleteEvents); + } + + public function hasTestMarkedIncompleteEvents(): bool + { + return $this->numberOfTestMarkedIncompleteEvents() > 0; + } + + /** + * @psalm-return array> + */ + public function testTriggeredPhpunitDeprecationEvents(): array + { + return $this->testTriggeredPhpunitDeprecationEvents; + } + + public function numberOfTestsWithTestTriggeredPhpunitDeprecationEvents(): int + { + return count($this->testTriggeredPhpunitDeprecationEvents); + } + + public function hasTestTriggeredPhpunitDeprecationEvents(): bool + { + return $this->numberOfTestsWithTestTriggeredPhpunitDeprecationEvents() > 0; + } + + /** + * @psalm-return array> + */ + public function testTriggeredPhpunitErrorEvents(): array + { + return $this->testTriggeredPhpunitErrorEvents; + } + + public function numberOfTestsWithTestTriggeredPhpunitErrorEvents(): int + { + return count($this->testTriggeredPhpunitErrorEvents); + } + + public function hasTestTriggeredPhpunitErrorEvents(): bool + { + return $this->numberOfTestsWithTestTriggeredPhpunitErrorEvents() > 0; + } + + /** + * @psalm-return array> + */ + public function testTriggeredPhpunitWarningEvents(): array + { + return $this->testTriggeredPhpunitWarningEvents; + } + + public function numberOfTestsWithTestTriggeredPhpunitWarningEvents(): int + { + return count($this->testTriggeredPhpunitWarningEvents); + } + + public function hasTestTriggeredPhpunitWarningEvents(): bool + { + return $this->numberOfTestsWithTestTriggeredPhpunitWarningEvents() > 0; + } + + /** + * @psalm-return list + */ + public function testRunnerTriggeredDeprecationEvents(): array + { + return $this->testRunnerTriggeredDeprecationEvents; + } + + public function numberOfTestRunnerTriggeredDeprecationEvents(): int + { + return count($this->testRunnerTriggeredDeprecationEvents); + } + + public function hasTestRunnerTriggeredDeprecationEvents(): bool + { + return $this->numberOfTestRunnerTriggeredDeprecationEvents() > 0; + } + + /** + * @psalm-return list + */ + public function testRunnerTriggeredWarningEvents(): array + { + return $this->testRunnerTriggeredWarningEvents; + } + + public function numberOfTestRunnerTriggeredWarningEvents(): int + { + return count($this->testRunnerTriggeredWarningEvents); + } + + public function hasTestRunnerTriggeredWarningEvents(): bool + { + return $this->numberOfTestRunnerTriggeredWarningEvents() > 0; + } + + public function wasSuccessful(): bool + { + return $this->wasSuccessfulIgnoringPhpunitWarnings() && + !$this->hasTestTriggeredPhpunitErrorEvents() && + !$this->hasTestRunnerTriggeredWarningEvents() && + !$this->hasTestTriggeredPhpunitWarningEvents(); + } + + public function wasSuccessfulIgnoringPhpunitWarnings(): bool + { + return !$this->hasTestErroredEvents() && + !$this->hasTestFailedEvents(); + } + + public function wasSuccessfulAndNoTestHasIssues(): bool + { + return $this->wasSuccessful() && !$this->hasTestsWithIssues(); + } + + public function hasTestsWithIssues(): bool + { + return $this->hasRiskyTests() || + $this->hasIncompleteTests() || + $this->hasDeprecations() || + !empty($this->errors) || + $this->hasNotices() || + $this->hasWarnings(); + } + + /** + * @psalm-return list + */ + public function errors(): array + { + return $this->errors; + } + + /** + * @psalm-return list + */ + public function deprecations(): array + { + return $this->deprecations; + } + + /** + * @psalm-return list + */ + public function notices(): array + { + return $this->notices; + } + + /** + * @psalm-return list + */ + public function warnings(): array + { + return $this->warnings; + } + + /** + * @psalm-return list + */ + public function phpDeprecations(): array + { + return $this->phpDeprecations; + } + + /** + * @psalm-return list + */ + public function phpNotices(): array + { + return $this->phpNotices; + } + + /** + * @psalm-return list + */ + public function phpWarnings(): array + { + return $this->phpWarnings; + } + + public function hasTests(): bool + { + return $this->numberOfTests > 0; + } + + public function hasErrors(): bool + { + return $this->numberOfErrors() > 0; + } + + public function numberOfErrors(): int + { + return $this->numberOfTestErroredEvents() + + count($this->errors) + + $this->numberOfTestsWithTestTriggeredPhpunitErrorEvents(); + } + + public function hasDeprecations(): bool + { + return $this->numberOfDeprecations() > 0; + } + + public function hasPhpOrUserDeprecations(): bool + { + return $this->numberOfPhpOrUserDeprecations() > 0; + } + + public function numberOfPhpOrUserDeprecations(): int + { + return count($this->deprecations) + + count($this->phpDeprecations); + } + + public function hasPhpunitDeprecations(): bool + { + return $this->numberOfPhpunitDeprecations() > 0; + } + + public function numberOfPhpunitDeprecations(): int + { + return count($this->testTriggeredPhpunitDeprecationEvents) + + count($this->testRunnerTriggeredDeprecationEvents); + } + + public function numberOfDeprecations(): int + { + return count($this->deprecations) + + count($this->phpDeprecations) + + count($this->testTriggeredPhpunitDeprecationEvents) + + count($this->testRunnerTriggeredDeprecationEvents); + } + + public function hasNotices(): bool + { + return $this->numberOfNotices() > 0; + } + + public function numberOfNotices(): int + { + return count($this->notices) + + count($this->phpNotices); + } + + public function hasWarnings(): bool + { + return $this->numberOfWarnings() > 0; + } + + public function numberOfWarnings(): int + { + return count($this->warnings) + + count($this->phpWarnings) + + count($this->testTriggeredPhpunitWarningEvents) + + count($this->testRunnerTriggeredWarningEvents); + } + + public function hasIncompleteTests(): bool + { + return !empty($this->testMarkedIncompleteEvents); + } + + public function hasRiskyTests(): bool + { + return !empty($this->testConsideredRiskyEvents); + } + + public function hasSkippedTests(): bool + { + return !empty($this->testSkippedEvents); + } + + public function hasIssuesIgnoredByBaseline(): bool + { + return $this->numberOfIssuesIgnoredByBaseline > 0; + } + + /** + * @psalm-return non-negative-int + */ + public function numberOfIssuesIgnoredByBaseline(): int + { + return $this->numberOfIssuesIgnoredByBaseline; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php new file mode 100644 index 000000000..e3b984cf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteLoader.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function array_diff; +use function array_values; +use function basename; +use function get_declared_classes; +use function realpath; +use function str_ends_with; +use function strpos; +use function strtolower; +use function substr; +use PHPUnit\Framework\TestCase; +use ReflectionClass; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteLoader +{ + /** + * @psalm-var list + */ + private static array $declaredClasses = []; + + /** + * @psalm-var array> + */ + private static array $fileToClassesMap = []; + + /** + * @throws Exception + */ + public function load(string $suiteClassFile): ReflectionClass + { + $suiteClassFile = realpath($suiteClassFile); + $suiteClassName = $this->classNameFromFileName($suiteClassFile); + $loadedClasses = $this->loadSuiteClassFile($suiteClassFile); + + foreach ($loadedClasses as $className) { + /** @noinspection PhpUnhandledExceptionInspection */ + $class = new ReflectionClass($className); + + if ($class->isAnonymous()) { + continue; + } + + if ($class->getFileName() !== $suiteClassFile) { + continue; + } + + if (!$class->isSubclassOf(TestCase::class)) { + continue; + } + + if (!str_ends_with(strtolower($class->getShortName()), strtolower($suiteClassName))) { + continue; + } + + if (!$class->isAbstract()) { + return $class; + } + + $e = new ClassIsAbstractException($class->getName(), $suiteClassFile); + } + + if (isset($e)) { + throw $e; + } + + foreach ($loadedClasses as $className) { + if (str_ends_with(strtolower($className), strtolower($suiteClassName))) { + throw new ClassDoesNotExtendTestCaseException($className, $suiteClassFile); + } + } + + throw new ClassCannotBeFoundException($suiteClassName, $suiteClassFile); + } + + private function classNameFromFileName(string $suiteClassFile): string + { + $className = basename($suiteClassFile, '.php'); + $dotPos = strpos($className, '.'); + + if ($dotPos !== false) { + $className = substr($className, 0, $dotPos); + } + + return $className; + } + + /** + * @psalm-return list + */ + private function loadSuiteClassFile(string $suiteClassFile): array + { + if (isset(self::$fileToClassesMap[$suiteClassFile])) { + return self::$fileToClassesMap[$suiteClassFile]; + } + + if (empty(self::$declaredClasses)) { + self::$declaredClasses = get_declared_classes(); + } + + require_once $suiteClassFile; + + $loadedClasses = array_values( + array_diff( + get_declared_classes(), + self::$declaredClasses, + ), + ); + + foreach ($loadedClasses as $loadedClass) { + /** @noinspection PhpUnhandledExceptionInspection */ + $class = new ReflectionClass($loadedClass); + + if (!isset(self::$fileToClassesMap[$class->getFileName()])) { + self::$fileToClassesMap[$class->getFileName()] = []; + } + + self::$fileToClassesMap[$class->getFileName()][] = $class->getName(); + } + + self::$declaredClasses = get_declared_classes(); + + if (empty($loadedClasses)) { + return self::$declaredClasses; + } + + return $loadedClasses; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php new file mode 100644 index 000000000..b5c0c19d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/TestSuiteSorter.php @@ -0,0 +1,344 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function array_diff; +use function array_merge; +use function array_reverse; +use function array_splice; +use function count; +use function in_array; +use function max; +use function shuffle; +use function usort; +use PHPUnit\Framework\DataProviderTestSuite; +use PHPUnit\Framework\Reorderable; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\ResultCache\NullResultCache; +use PHPUnit\Runner\ResultCache\ResultCache; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteSorter +{ + /** + * @var int + */ + public const ORDER_DEFAULT = 0; + + /** + * @var int + */ + public const ORDER_RANDOMIZED = 1; + + /** + * @var int + */ + public const ORDER_REVERSED = 2; + + /** + * @var int + */ + public const ORDER_DEFECTS_FIRST = 3; + + /** + * @var int + */ + public const ORDER_DURATION = 4; + + /** + * @var int + */ + public const ORDER_SIZE = 5; + + private const SIZE_SORT_WEIGHT = [ + 'small' => 1, + 'medium' => 2, + 'large' => 3, + 'unknown' => 4, + ]; + + /** + * @psalm-var array Associative array of (string => DEFECT_SORT_WEIGHT) elements + */ + private array $defectSortOrder = []; + private readonly ResultCache $cache; + + /** + * @psalm-var array A list of normalized names of tests before reordering + */ + private array $originalExecutionOrder = []; + + /** + * @psalm-var array A list of normalized names of tests affected by reordering + */ + private array $executionOrder = []; + + public function __construct(?ResultCache $cache = null) + { + $this->cache = $cache ?? new NullResultCache; + } + + /** + * @throws Exception + */ + public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = true): void + { + $allowedOrders = [ + self::ORDER_DEFAULT, + self::ORDER_REVERSED, + self::ORDER_RANDOMIZED, + self::ORDER_DURATION, + self::ORDER_SIZE, + ]; + + if (!in_array($order, $allowedOrders, true)) { + throw new InvalidOrderException; + } + + $allowedOrderDefects = [ + self::ORDER_DEFAULT, + self::ORDER_DEFECTS_FIRST, + ]; + + if (!in_array($orderDefects, $allowedOrderDefects, true)) { + throw new InvalidOrderException; + } + + if ($isRootTestSuite) { + $this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite); + } + + if ($suite instanceof TestSuite) { + foreach ($suite as $_suite) { + $this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, false); + } + + if ($orderDefects === self::ORDER_DEFECTS_FIRST) { + $this->addSuiteToDefectSortOrder($suite); + } + + $this->sort($suite, $order, $resolveDependencies, $orderDefects); + } + + if ($isRootTestSuite) { + $this->executionOrder = $this->calculateTestExecutionOrder($suite); + } + } + + public function getOriginalExecutionOrder(): array + { + return $this->originalExecutionOrder; + } + + public function getExecutionOrder(): array + { + return $this->executionOrder; + } + + private function sort(TestSuite $suite, int $order, bool $resolveDependencies, int $orderDefects): void + { + if (empty($suite->tests())) { + return; + } + + if ($order === self::ORDER_REVERSED) { + $suite->setTests($this->reverse($suite->tests())); + } elseif ($order === self::ORDER_RANDOMIZED) { + $suite->setTests($this->randomize($suite->tests())); + } elseif ($order === self::ORDER_DURATION) { + $suite->setTests($this->sortByDuration($suite->tests())); + } elseif ($order === self::ORDER_SIZE) { + $suite->setTests($this->sortBySize($suite->tests())); + } + + if ($orderDefects === self::ORDER_DEFECTS_FIRST) { + $suite->setTests($this->sortDefectsFirst($suite->tests())); + } + + if ($resolveDependencies && !($suite instanceof DataProviderTestSuite)) { + $tests = $suite->tests(); + + $suite->setTests($this->resolveDependencies($tests)); + } + } + + private function addSuiteToDefectSortOrder(TestSuite $suite): void + { + $max = 0; + + foreach ($suite->tests() as $test) { + if (!$test instanceof Reorderable) { + continue; + } + + if (!isset($this->defectSortOrder[$test->sortId()])) { + $this->defectSortOrder[$test->sortId()] = $this->cache->status($test->sortId())->asInt(); + $max = max($max, $this->defectSortOrder[$test->sortId()]); + } + } + + $this->defectSortOrder[$suite->sortId()] = $max; + } + + private function reverse(array $tests): array + { + return array_reverse($tests); + } + + private function randomize(array $tests): array + { + shuffle($tests); + + return $tests; + } + + private function sortDefectsFirst(array $tests): array + { + usort( + $tests, + fn ($left, $right) => $this->cmpDefectPriorityAndTime($left, $right), + ); + + return $tests; + } + + private function sortByDuration(array $tests): array + { + usort( + $tests, + fn ($left, $right) => $this->cmpDuration($left, $right), + ); + + return $tests; + } + + private function sortBySize(array $tests): array + { + usort( + $tests, + fn ($left, $right) => $this->cmpSize($left, $right), + ); + + return $tests; + } + + /** + * Comparator callback function to sort tests for "reach failure as fast as possible". + * + * 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT + * 2. when tests are equally defective, sort the fastest to the front + * 3. do not reorder successful tests + */ + private function cmpDefectPriorityAndTime(Test $a, Test $b): int + { + if (!($a instanceof Reorderable && $b instanceof Reorderable)) { + return 0; + } + + $priorityA = $this->defectSortOrder[$a->sortId()] ?? 0; + $priorityB = $this->defectSortOrder[$b->sortId()] ?? 0; + + if ($priorityB <=> $priorityA) { + // Sort defect weight descending + return $priorityB <=> $priorityA; + } + + if ($priorityA || $priorityB) { + return $this->cmpDuration($a, $b); + } + + // do not change execution order + return 0; + } + + /** + * Compares test duration for sorting tests by duration ascending. + */ + private function cmpDuration(Test $a, Test $b): int + { + if (!($a instanceof Reorderable && $b instanceof Reorderable)) { + return 0; + } + + return $this->cache->time($a->sortId()) <=> $this->cache->time($b->sortId()); + } + + /** + * Compares test size for sorting tests small->medium->large->unknown. + */ + private function cmpSize(Test $a, Test $b): int + { + $sizeA = ($a instanceof TestCase || $a instanceof DataProviderTestSuite) + ? $a->size()->asString() + : 'unknown'; + $sizeB = ($b instanceof TestCase || $b instanceof DataProviderTestSuite) + ? $b->size()->asString() + : 'unknown'; + + return self::SIZE_SORT_WEIGHT[$sizeA] <=> self::SIZE_SORT_WEIGHT[$sizeB]; + } + + /** + * Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible. + * The algorithm will leave the tests in original running order when it can. + * For more details see the documentation for test dependencies. + * + * Short description of algorithm: + * 1. Pick the next Test from remaining tests to be checked for dependencies. + * 2. If the test has no dependencies: mark done, start again from the top + * 3. If the test has dependencies but none left to do: mark done, start again from the top + * 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution. + * + * @psalm-param array $tests + * + * @psalm-return array + */ + private function resolveDependencies(array $tests): array + { + $newTestOrder = []; + $i = 0; + $provided = []; + + do { + if ([] === array_diff($tests[$i]->requires(), $provided)) { + $provided = array_merge($provided, $tests[$i]->provides()); + $newTestOrder = array_merge($newTestOrder, array_splice($tests, $i, 1)); + $i = 0; + } else { + $i++; + } + } while (!empty($tests) && ($i < count($tests))); + + return array_merge($newTestOrder, $tests); + } + + private function calculateTestExecutionOrder(Test $suite): array + { + $tests = []; + + if ($suite instanceof TestSuite) { + foreach ($suite->tests() as $test) { + if (!$test instanceof TestSuite && $test instanceof Reorderable) { + $tests[] = $test->sortId(); + } else { + $tests = array_merge($tests, $this->calculateTestExecutionOrder($test)); + } + } + } + + return $tests; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Version.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Version.php new file mode 100644 index 000000000..043cc88bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Runner/Version.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +use function array_slice; +use function dirname; +use function explode; +use function implode; +use function str_contains; +use SebastianBergmann\Version as VersionId; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Version +{ + private static string $pharVersion = ''; + private static string $version = ''; + + /** + * Returns the current version of PHPUnit. + */ + public static function id(): string + { + if (self::$pharVersion !== '') { + return self::$pharVersion; + } + + if (self::$version === '') { + self::$version = (new VersionId('10.5.38', dirname(__DIR__, 2)))->asString(); + } + + return self::$version; + } + + public static function series(): string + { + if (str_contains(self::id(), '-')) { + $version = explode('-', self::id(), 2)[0]; + } else { + $version = self::id(); + } + + return implode('.', array_slice(explode('.', $version), 0, 2)); + } + + public static function majorVersionNumber(): int + { + return (int) explode('.', self::series())[0]; + } + + public static function getVersionString(): string + { + return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Application.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Application.php new file mode 100644 index 000000000..d99c24339 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Application.php @@ -0,0 +1,754 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use const PHP_EOL; +use const PHP_VERSION; +use function is_file; +use function is_readable; +use function printf; +use function realpath; +use function sprintf; +use function trim; +use function unlink; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Logging\EventLogger; +use PHPUnit\Logging\JUnit\JunitXmlLogger; +use PHPUnit\Logging\TeamCity\TeamCityLogger; +use PHPUnit\Logging\TestDox\HtmlRenderer as TestDoxHtmlRenderer; +use PHPUnit\Logging\TestDox\PlainTextRenderer as TestDoxTextRenderer; +use PHPUnit\Logging\TestDox\TestResultCollector as TestDoxResultCollector; +use PHPUnit\Metadata\Api\CodeCoverage as CodeCoverageMetadataApi; +use PHPUnit\Runner\Baseline\CannotLoadBaselineException; +use PHPUnit\Runner\Baseline\Generator as BaselineGenerator; +use PHPUnit\Runner\Baseline\Reader; +use PHPUnit\Runner\Baseline\Writer; +use PHPUnit\Runner\CodeCoverage; +use PHPUnit\Runner\DirectoryDoesNotExistException; +use PHPUnit\Runner\ErrorHandler; +use PHPUnit\Runner\Extension\ExtensionBootstrapper; +use PHPUnit\Runner\Extension\Facade as ExtensionFacade; +use PHPUnit\Runner\Extension\PharLoader; +use PHPUnit\Runner\GarbageCollection\GarbageCollectionHandler; +use PHPUnit\Runner\ResultCache\DefaultResultCache; +use PHPUnit\Runner\ResultCache\NullResultCache; +use PHPUnit\Runner\ResultCache\ResultCache; +use PHPUnit\Runner\ResultCache\ResultCacheHandler; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\Runner\Version; +use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; +use PHPUnit\TextUI\CliArguments\Builder; +use PHPUnit\TextUI\CliArguments\Configuration as CliConfiguration; +use PHPUnit\TextUI\CliArguments\Exception as ArgumentsException; +use PHPUnit\TextUI\CliArguments\XmlConfigurationFileFinder; +use PHPUnit\TextUI\Command\AtLeastVersionCommand; +use PHPUnit\TextUI\Command\GenerateConfigurationCommand; +use PHPUnit\TextUI\Command\ListGroupsCommand; +use PHPUnit\TextUI\Command\ListTestsAsTextCommand; +use PHPUnit\TextUI\Command\ListTestsAsXmlCommand; +use PHPUnit\TextUI\Command\ListTestSuitesCommand; +use PHPUnit\TextUI\Command\MigrateConfigurationCommand; +use PHPUnit\TextUI\Command\Result; +use PHPUnit\TextUI\Command\ShowHelpCommand; +use PHPUnit\TextUI\Command\ShowVersionCommand; +use PHPUnit\TextUI\Command\VersionCheckCommand; +use PHPUnit\TextUI\Command\WarmCodeCoverageCacheCommand; +use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\PhpHandler; +use PHPUnit\TextUI\Configuration\Registry; +use PHPUnit\TextUI\Configuration\TestSuiteBuilder; +use PHPUnit\TextUI\Output\DefaultPrinter; +use PHPUnit\TextUI\Output\Facade as OutputFacade; +use PHPUnit\TextUI\Output\Printer; +use PHPUnit\TextUI\XmlConfiguration\Configuration as XmlConfiguration; +use PHPUnit\TextUI\XmlConfiguration\DefaultConfiguration; +use PHPUnit\TextUI\XmlConfiguration\Loader; +use PHPUnit\Util\Http\PhpDownloader; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Application +{ + public function run(array $argv): int + { + try { + EventFacade::emitter()->applicationStarted(); + + $cliConfiguration = $this->buildCliConfiguration($argv); + $pathToXmlConfigurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration); + + $this->executeCommandsThatOnlyRequireCliConfiguration($cliConfiguration, $pathToXmlConfigurationFile); + + $xmlConfiguration = $this->loadXmlConfiguration($pathToXmlConfigurationFile); + + $configuration = Registry::init( + $cliConfiguration, + $xmlConfiguration, + ); + + (new PhpHandler)->handle($configuration->php()); + + if ($configuration->hasBootstrap()) { + $this->loadBootstrapScript($configuration->bootstrap()); + } + + $this->executeCommandsThatRequireCompleteConfiguration($configuration, $cliConfiguration); + + $testSuite = $this->buildTestSuite($configuration); + + $this->executeCommandsThatRequireCliConfigurationAndTestSuite($cliConfiguration, $testSuite); + $this->executeHelpCommandWhenThereIsNothingElseToDo($configuration, $testSuite); + + $pharExtensions = null; + $extensionRequiresCodeCoverageCollection = false; + $extensionReplacesOutput = false; + $extensionReplacesProgressOutput = false; + $extensionReplacesResultOutput = false; + $extensionRequiresExportOfObjects = false; + + if (!$configuration->noExtensions()) { + if ($configuration->hasPharExtensionDirectory()) { + $pharExtensions = (new PharLoader)->loadPharExtensionsInDirectory( + $configuration->pharExtensionDirectory(), + ); + } + + $bootstrappedExtensions = $this->bootstrapExtensions($configuration); + $extensionRequiresCodeCoverageCollection = $bootstrappedExtensions['requiresCodeCoverageCollection']; + $extensionReplacesOutput = $bootstrappedExtensions['replacesOutput']; + $extensionReplacesProgressOutput = $bootstrappedExtensions['replacesProgressOutput']; + $extensionReplacesResultOutput = $bootstrappedExtensions['replacesResultOutput']; + $extensionRequiresExportOfObjects = $bootstrappedExtensions['requiresExportOfObjects']; + } + + if ($extensionRequiresExportOfObjects) { + EventFacade::emitter()->exportObjects(); + } + + CodeCoverage::instance()->init( + $configuration, + CodeCoverageFilterRegistry::instance(), + $extensionRequiresCodeCoverageCollection, + ); + + if (CodeCoverage::instance()->isActive()) { + CodeCoverage::instance()->ignoreLines( + (new CodeCoverageMetadataApi)->linesToBeIgnored($testSuite), + ); + } + + $printer = OutputFacade::init( + $configuration, + $extensionReplacesProgressOutput, + $extensionReplacesResultOutput, + ); + + if (!$configuration->debug() && !$extensionReplacesOutput) { + $this->writeRuntimeInformation($printer, $configuration); + $this->writePharExtensionInformation($printer, $pharExtensions); + $this->writeRandomSeedInformation($printer, $configuration); + + $printer->print(PHP_EOL); + } + + if ($configuration->debug()) { + EventFacade::instance()->registerTracer( + new EventLogger( + 'php://stdout', + false, + ), + ); + } + + $this->registerLogfileWriters($configuration); + + $testDoxResultCollector = $this->testDoxResultCollector($configuration); + + TestResultFacade::init(); + + $resultCache = $this->initializeTestResultCache($configuration); + + if ($configuration->controlGarbageCollector()) { + new GarbageCollectionHandler( + EventFacade::instance(), + $configuration->numberOfTestsBeforeGarbageCollection(), + ); + } + + $baselineGenerator = $this->configureBaseline($configuration); + + EventFacade::instance()->seal(); + + $timer = new Timer; + $timer->start(); + + $runner = new TestRunner; + + $runner->run( + $configuration, + $resultCache, + $testSuite, + ); + + $duration = $timer->stop(); + + $testDoxResult = null; + + if (isset($testDoxResultCollector)) { + $testDoxResult = $testDoxResultCollector->testMethodsGroupedByClass(); + } + + if ($testDoxResult !== null && + $configuration->hasLogfileTestdoxHtml()) { + try { + OutputFacade::printerFor($configuration->logfileTestdoxHtml())->print( + (new TestDoxHtmlRenderer)->render($testDoxResult), + ); + } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot log test results in TestDox HTML format to "%s": %s', + $configuration->logfileTestdoxHtml(), + $e->getMessage(), + ), + ); + } + } + + if ($testDoxResult !== null && + $configuration->hasLogfileTestdoxText()) { + try { + OutputFacade::printerFor($configuration->logfileTestdoxText())->print( + (new TestDoxTextRenderer)->render($testDoxResult), + ); + } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot log test results in TestDox plain text format to "%s": %s', + $configuration->logfileTestdoxText(), + $e->getMessage(), + ), + ); + } + } + + $result = TestResultFacade::result(); + + if (!$extensionReplacesResultOutput && !$configuration->debug()) { + OutputFacade::printResult($result, $testDoxResult, $duration); + } + + CodeCoverage::instance()->generateReports($printer, $configuration); + + if (isset($baselineGenerator)) { + (new Writer)->write( + $configuration->generateBaseline(), + $baselineGenerator->baseline(), + ); + + $printer->print( + sprintf( + PHP_EOL . 'Baseline written to %s.' . PHP_EOL, + realpath($configuration->generateBaseline()), + ), + ); + } + + $shellExitCode = (new ShellExitCodeCalculator)->calculate( + $configuration->failOnDeprecation(), + $configuration->failOnPhpunitDeprecation(), + $configuration->failOnEmptyTestSuite(), + $configuration->failOnIncomplete(), + $configuration->failOnNotice(), + $configuration->failOnRisky(), + $configuration->failOnSkipped(), + $configuration->failOnWarning(), + $result, + ); + + EventFacade::emitter()->applicationFinished($shellExitCode); + + return $shellExitCode; + // @codeCoverageIgnoreStart + } catch (Throwable $t) { + $this->exitWithCrashMessage($t); + } + // @codeCoverageIgnoreEnd + } + + private function execute(Command\Command $command, bool $requiresResultCollectedFromEvents = false): never + { + if ($requiresResultCollectedFromEvents) { + try { + TestResultFacade::init(); + EventFacade::instance()->seal(); + + $resultCollectedFromEvents = TestResultFacade::result(); + } catch (EventFacadeIsSealedException|UnknownSubscriberTypeException) { + } + } + + print Version::getVersionString() . PHP_EOL . PHP_EOL; + + $result = $command->execute(); + + print $result->output(); + + $shellExitCode = $result->shellExitCode(); + + if (isset($resultCollectedFromEvents) && + $resultCollectedFromEvents->hasTestTriggeredPhpunitErrorEvents()) { + $shellExitCode = Result::EXCEPTION; + + print PHP_EOL . PHP_EOL . 'There were errors:' . PHP_EOL; + + foreach ($resultCollectedFromEvents->testTriggeredPhpunitErrorEvents() as $events) { + foreach ($events as $event) { + print PHP_EOL . trim($event->message()) . PHP_EOL; + } + } + } + + exit($shellExitCode); + } + + private function loadBootstrapScript(string $filename): void + { + if (!is_readable($filename)) { + $this->exitWithErrorMessage( + sprintf( + 'Cannot open bootstrap script "%s"', + $filename, + ), + ); + } + + try { + include_once $filename; + } catch (Throwable $t) { + $message = sprintf( + 'Error in bootstrap script: %s:%s%s%s%s', + $t::class, + PHP_EOL, + $t->getMessage(), + PHP_EOL, + $t->getTraceAsString(), + ); + + while ($t = $t->getPrevious()) { + $message .= sprintf( + '%s%sPrevious error: %s:%s%s%s%s', + PHP_EOL, + PHP_EOL, + $t::class, + PHP_EOL, + $t->getMessage(), + PHP_EOL, + $t->getTraceAsString(), + ); + } + + $this->exitWithErrorMessage($message); + } + + EventFacade::emitter()->testRunnerBootstrapFinished($filename); + } + + private function buildCliConfiguration(array $argv): CliConfiguration + { + try { + $cliConfiguration = (new Builder)->fromParameters($argv); + } catch (ArgumentsException $e) { + $this->exitWithErrorMessage($e->getMessage()); + } + + return $cliConfiguration; + } + + private function loadXmlConfiguration(false|string $configurationFile): XmlConfiguration + { + if ($configurationFile === false) { + return DefaultConfiguration::create(); + } + + try { + return (new Loader)->load($configurationFile); + } catch (Throwable $e) { + $this->exitWithErrorMessage($e->getMessage()); + } + } + + private function buildTestSuite(Configuration $configuration): TestSuite + { + try { + return (new TestSuiteBuilder)->build($configuration); + } catch (Exception $e) { + $this->exitWithErrorMessage($e->getMessage()); + } + } + + /** + * @psalm-return array{requiresCodeCoverageCollection: bool, replacesOutput: bool, replacesProgressOutput: bool, replacesResultOutput: bool, requiresExportOfObjects: bool} + */ + private function bootstrapExtensions(Configuration $configuration): array + { + $facade = new ExtensionFacade; + + $extensionBootstrapper = new ExtensionBootstrapper( + $configuration, + $facade, + ); + + foreach ($configuration->extensionBootstrappers() as $bootstrapper) { + $extensionBootstrapper->bootstrap( + $bootstrapper['className'], + $bootstrapper['parameters'], + ); + } + + return [ + 'requiresCodeCoverageCollection' => $facade->requiresCodeCoverageCollection(), + 'replacesOutput' => $facade->replacesOutput(), + 'replacesProgressOutput' => $facade->replacesProgressOutput(), + 'replacesResultOutput' => $facade->replacesResultOutput(), + 'requiresExportOfObjects' => $facade->requiresExportOfObjects(), + ]; + } + + private function executeCommandsThatOnlyRequireCliConfiguration(CliConfiguration $cliConfiguration, false|string $configurationFile): void + { + if ($cliConfiguration->generateConfiguration()) { + $this->execute(new GenerateConfigurationCommand); + } + + if ($cliConfiguration->migrateConfiguration()) { + if ($configurationFile === false) { + $this->exitWithErrorMessage('No configuration file found to migrate'); + } + + $this->execute(new MigrateConfigurationCommand(realpath($configurationFile))); + } + + if ($cliConfiguration->hasAtLeastVersion()) { + $this->execute(new AtLeastVersionCommand($cliConfiguration->atLeastVersion())); + } + + if ($cliConfiguration->version()) { + $this->execute(new ShowVersionCommand); + } + + if ($cliConfiguration->checkVersion()) { + $this->execute(new VersionCheckCommand(new PhpDownloader, Version::majorVersionNumber(), Version::id())); + } + + if ($cliConfiguration->help()) { + $this->execute(new ShowHelpCommand(Result::SUCCESS)); + } + } + + private function executeCommandsThatRequireCliConfigurationAndTestSuite(CliConfiguration $cliConfiguration, TestSuite $testSuite): void + { + if ($cliConfiguration->listGroups()) { + $this->execute(new ListGroupsCommand($testSuite), true); + } + + if ($cliConfiguration->listTests()) { + $this->execute(new ListTestsAsTextCommand($testSuite), true); + } + + if ($cliConfiguration->hasListTestsXml()) { + $this->execute( + new ListTestsAsXmlCommand( + $cliConfiguration->listTestsXml(), + $testSuite, + ), + true, + ); + } + } + + private function executeCommandsThatRequireCompleteConfiguration(Configuration $configuration, CliConfiguration $cliConfiguration): void + { + if ($cliConfiguration->listSuites()) { + $this->execute(new ListTestSuitesCommand($configuration->testSuite())); + } + + if ($cliConfiguration->warmCoverageCache()) { + $this->execute(new WarmCodeCoverageCacheCommand($configuration, CodeCoverageFilterRegistry::instance())); + } + } + + private function executeHelpCommandWhenThereIsNothingElseToDo(Configuration $configuration, TestSuite $testSuite): void + { + if ($testSuite->isEmpty() && !$configuration->hasCliArguments() && $configuration->testSuite()->isEmpty()) { + $this->execute(new ShowHelpCommand(Result::FAILURE)); + } + } + + private function writeRuntimeInformation(Printer $printer, Configuration $configuration): void + { + $printer->print(Version::getVersionString() . PHP_EOL . PHP_EOL); + + $runtime = 'PHP ' . PHP_VERSION; + + if (CodeCoverage::instance()->isActive()) { + $runtime .= ' with ' . CodeCoverage::instance()->driver()->nameAndVersion(); + } + + $this->writeMessage($printer, 'Runtime', $runtime); + + if ($configuration->hasConfigurationFile()) { + $this->writeMessage( + $printer, + 'Configuration', + $configuration->configurationFile(), + ); + } + } + + /** + * @psalm-param ?list $pharExtensions + */ + private function writePharExtensionInformation(Printer $printer, ?array $pharExtensions): void + { + if ($pharExtensions === null) { + return; + } + + foreach ($pharExtensions as $extension) { + $this->writeMessage( + $printer, + 'Extension', + $extension, + ); + } + } + + private function writeMessage(Printer $printer, string $type, string $message): void + { + $printer->print( + sprintf( + "%-15s%s\n", + $type . ':', + $message, + ), + ); + } + + private function writeRandomSeedInformation(Printer $printer, Configuration $configuration): void + { + if ($configuration->executionOrder() === TestSuiteSorter::ORDER_RANDOMIZED) { + $this->writeMessage( + $printer, + 'Random Seed', + (string) $configuration->randomOrderSeed(), + ); + } + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerLogfileWriters(Configuration $configuration): void + { + if ($configuration->hasLogEventsText()) { + if (is_file($configuration->logEventsText())) { + unlink($configuration->logEventsText()); + } + + EventFacade::instance()->registerTracer( + new EventLogger( + $configuration->logEventsText(), + false, + ), + ); + } + + if ($configuration->hasLogEventsVerboseText()) { + if (is_file($configuration->logEventsVerboseText())) { + unlink($configuration->logEventsVerboseText()); + } + + EventFacade::instance()->registerTracer( + new EventLogger( + $configuration->logEventsVerboseText(), + true, + ), + ); + + EventFacade::emitter()->exportObjects(); + } + + if ($configuration->hasLogfileJunit()) { + try { + new JunitXmlLogger( + OutputFacade::printerFor($configuration->logfileJunit()), + EventFacade::instance(), + ); + } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot log test results in JUnit XML format to "%s": %s', + $configuration->logfileJunit(), + $e->getMessage(), + ), + ); + } + } + + if ($configuration->hasLogfileTeamcity()) { + try { + new TeamCityLogger( + DefaultPrinter::from( + $configuration->logfileTeamcity(), + ), + EventFacade::instance(), + ); + } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Cannot log test results in TeamCity format to "%s": %s', + $configuration->logfileTeamcity(), + $e->getMessage(), + ), + ); + } + } + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function testDoxResultCollector(Configuration $configuration): ?TestDoxResultCollector + { + if ($configuration->hasLogfileTestdoxHtml() || + $configuration->hasLogfileTestdoxText() || + $configuration->outputIsTestDox()) { + return new TestDoxResultCollector( + EventFacade::instance(), + $configuration->source(), + ); + } + + return null; + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function initializeTestResultCache(Configuration $configuration): ResultCache + { + if ($configuration->cacheResult()) { + $cache = new DefaultResultCache($configuration->testResultCacheFile()); + + new ResultCacheHandler($cache, EventFacade::instance()); + + return $cache; + } + + return new NullResultCache; + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function configureBaseline(Configuration $configuration): ?BaselineGenerator + { + if ($configuration->hasGenerateBaseline()) { + return new BaselineGenerator( + EventFacade::instance(), + $configuration->source(), + ); + } + + if ($configuration->source()->useBaseline()) { + /** @psalm-suppress MissingThrowsDocblock */ + $baselineFile = $configuration->source()->baseline(); + $baseline = null; + + try { + $baseline = (new Reader)->read($baselineFile); + } catch (CannotLoadBaselineException $e) { + EventFacade::emitter()->testRunnerTriggeredWarning($e->getMessage()); + } + + if ($baseline !== null) { + ErrorHandler::instance()->use($baseline); + } + } + + return null; + } + + /** + * @codeCoverageIgnore + */ + private function exitWithCrashMessage(Throwable $t): never + { + $message = $t->getMessage(); + + if (empty(trim($message))) { + $message = '(no message)'; + } + + printf( + '%s%sAn error occurred inside PHPUnit.%s%sMessage: %s', + PHP_EOL, + PHP_EOL, + PHP_EOL, + PHP_EOL, + $message, + ); + + $first = true; + + if ($t->getPrevious()) { + $t = $t->getPrevious(); + } + + do { + printf( + '%s%s: %s:%d%s%s%s%s', + PHP_EOL, + $first ? 'Location' : 'Caused by', + $t->getFile(), + $t->getLine(), + PHP_EOL, + PHP_EOL, + $t->getTraceAsString(), + PHP_EOL, + ); + + $first = false; + } while ($t = $t->getPrevious()); + + exit(Result::CRASH); + } + + private function exitWithErrorMessage(string $message): never + { + print Version::getVersionString() . PHP_EOL . PHP_EOL . $message . PHP_EOL; + + exit(Result::EXCEPTION); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Command.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Command.php new file mode 100644 index 000000000..4194551e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Command.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Command +{ + public function execute(): Result; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php new file mode 100644 index 000000000..06d78358f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use function version_compare; +use PHPUnit\Runner\Version; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class AtLeastVersionCommand implements Command +{ + private readonly string $version; + + public function __construct(string $version) + { + $this->version = $version; + } + + public function execute(): Result + { + if (version_compare(Version::id(), $this->version, '>=')) { + return Result::from(); + } + + return Result::from('', Result::FAILURE); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php new file mode 100644 index 000000000..b71d8b04d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use const PHP_EOL; +use const STDIN; +use function fgets; +use function file_put_contents; +use function getcwd; +use function sprintf; +use function trim; +use PHPUnit\Runner\Version; +use PHPUnit\TextUI\XmlConfiguration\Generator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class GenerateConfigurationCommand implements Command +{ + public function execute(): Result + { + print 'Generating phpunit.xml in ' . getcwd() . PHP_EOL . PHP_EOL; + print 'Bootstrap script (relative to path shown above; default: vendor/autoload.php): '; + + $bootstrapScript = $this->read(); + + print 'Tests directory (relative to path shown above; default: tests): '; + + $testsDirectory = $this->read(); + + print 'Source directory (relative to path shown above; default: src): '; + + $src = $this->read(); + + print 'Cache directory (relative to path shown above; default: .phpunit.cache): '; + + $cacheDirectory = $this->read(); + + if ($bootstrapScript === '') { + $bootstrapScript = 'vendor/autoload.php'; + } + + if ($testsDirectory === '') { + $testsDirectory = 'tests'; + } + + if ($src === '') { + $src = 'src'; + } + + if ($cacheDirectory === '') { + $cacheDirectory = '.phpunit.cache'; + } + + $generator = new Generator; + + $result = @file_put_contents( + 'phpunit.xml', + $generator->generateDefaultConfiguration( + Version::series(), + $bootstrapScript, + $testsDirectory, + $src, + $cacheDirectory, + ), + ); + + if ($result !== false) { + return Result::from( + sprintf( + PHP_EOL . 'Generated phpunit.xml in %s.' . PHP_EOL . + 'Make sure to exclude the %s directory from version control.' . PHP_EOL, + getcwd(), + $cacheDirectory, + ), + ); + } + + // @codeCoverageIgnoreStart + return Result::from( + sprintf( + PHP_EOL . 'Could not write phpunit.xml in %s.' . PHP_EOL, + getcwd(), + ), + Result::EXCEPTION, + ); + // @codeCoverageIgnoreEnd + } + + private function read(): string + { + return trim(fgets(STDIN)); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php new file mode 100644 index 000000000..f5f0fac08 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListGroupsCommand.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 PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function sort; +use function sprintf; +use function str_starts_with; +use PHPUnit\Framework\TestSuite; +use PHPUnit\TextUI\Configuration\Registry; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ListGroupsCommand implements Command +{ + private readonly TestSuite $suite; + + public function __construct(TestSuite $suite) + { + $this->suite = $suite; + } + + public function execute(): Result + { + $buffer = $this->warnAboutConflictingOptions(); + $buffer .= 'Available test group(s):' . PHP_EOL; + + $groups = $this->suite->groups(); + sort($groups); + + foreach ($groups as $group) { + if (str_starts_with($group, '__phpunit_')) { + continue; + } + + $buffer .= sprintf( + ' - %s' . PHP_EOL, + $group, + ); + } + + return Result::from($buffer); + } + + private function warnAboutConflictingOptions(): string + { + $buffer = ''; + + $configuration = Registry::get(); + + if ($configuration->hasFilter()) { + $buffer .= 'The --filter and --list-groups options cannot be combined, --filter is ignored' . PHP_EOL; + } + + if ($configuration->hasGroups()) { + $buffer .= 'The --group and --list-groups options cannot be combined, --group is ignored' . PHP_EOL; + } + + if ($configuration->hasExcludeGroups()) { + $buffer .= 'The --exclude-group and --list-groups options cannot be combined, --exclude-group is ignored' . PHP_EOL; + } + + if ($configuration->includeTestSuite() !== '') { + $buffer .= 'The --testsuite and --list-groups options cannot be combined, --exclude-group is ignored' . PHP_EOL; + } + + if (!empty($buffer)) { + $buffer .= PHP_EOL; + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php new file mode 100644 index 000000000..77c2cbb60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\TextUI\Configuration\Registry; +use PHPUnit\TextUI\Configuration\TestSuiteCollection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ListTestSuitesCommand implements Command +{ + private readonly TestSuiteCollection $suites; + + public function __construct(TestSuiteCollection $suites) + { + $this->suites = $suites; + } + + public function execute(): Result + { + $buffer = $this->warnAboutConflictingOptions(); + $buffer .= 'Available test suite(s):' . PHP_EOL; + + foreach ($this->suites as $suite) { + $buffer .= sprintf( + ' - %s' . PHP_EOL, + $suite->name(), + ); + } + + return Result::from($buffer); + } + + private function warnAboutConflictingOptions(): string + { + $buffer = ''; + + $configuration = Registry::get(); + + if ($configuration->hasFilter()) { + $buffer .= 'The --filter and --list-suites options cannot be combined, --filter is ignored' . PHP_EOL; + } + + if ($configuration->hasGroups()) { + $buffer .= 'The --group and --list-suites options cannot be combined, --group is ignored' . PHP_EOL; + } + + if ($configuration->hasExcludeGroups()) { + $buffer .= 'The --exclude-group and --list-suites options cannot be combined, --exclude-group is ignored' . PHP_EOL; + } + + if ($configuration->includeTestSuite() !== '') { + $buffer .= 'The --testsuite and --list-suites options cannot be combined, --exclude-group is ignored' . PHP_EOL; + } + + if (!empty($buffer)) { + $buffer .= PHP_EOL; + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php new file mode 100644 index 000000000..0d377011e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function sprintf; +use function str_replace; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\TextUI\Configuration\Registry; +use RecursiveIteratorIterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ListTestsAsTextCommand implements Command +{ + private readonly TestSuite $suite; + + public function __construct(TestSuite $suite) + { + $this->suite = $suite; + } + + public function execute(): Result + { + $buffer = $this->warnAboutConflictingOptions(); + + $buffer .= 'Available test(s):' . PHP_EOL; + + foreach (new RecursiveIteratorIterator($this->suite) as $test) { + if ($test instanceof TestCase) { + $name = sprintf( + '%s::%s', + $test::class, + str_replace(' with data set ', '', $test->nameWithDataSet()), + ); + } elseif ($test instanceof PhptTestCase) { + $name = $test->getName(); + } else { + continue; + } + + $buffer .= sprintf( + ' - %s' . PHP_EOL, + $name, + ); + } + + return Result::from($buffer); + } + + private function warnAboutConflictingOptions(): string + { + $buffer = ''; + + $configuration = Registry::get(); + + if ($configuration->hasFilter()) { + $buffer .= 'The --filter and --list-tests options cannot be combined, --filter is ignored' . PHP_EOL; + } + + if ($configuration->hasGroups()) { + $buffer .= 'The --group and --list-tests options cannot be combined, --group is ignored' . PHP_EOL; + } + + if ($configuration->hasExcludeGroups()) { + $buffer .= 'The --exclude-group and --list-tests options cannot be combined, --exclude-group is ignored' . PHP_EOL; + } + + if (!empty($buffer)) { + $buffer .= PHP_EOL; + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php new file mode 100644 index 000000000..5a1085f17 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.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 PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function file_put_contents; +use function implode; +use function sprintf; +use function str_replace; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\TextUI\Configuration\Registry; +use RecursiveIteratorIterator; +use XMLWriter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ListTestsAsXmlCommand implements Command +{ + private readonly string $filename; + private readonly TestSuite $suite; + + public function __construct(string $filename, TestSuite $suite) + { + $this->filename = $filename; + $this->suite = $suite; + } + + public function execute(): Result + { + $buffer = $this->warnAboutConflictingOptions(); + $writer = new XMLWriter; + + $writer->openMemory(); + $writer->setIndent(true); + $writer->startDocument(); + $writer->startElement('tests'); + + $currentTestCase = null; + + foreach (new RecursiveIteratorIterator($this->suite) as $test) { + if ($test instanceof TestCase) { + if ($test::class !== $currentTestCase) { + if ($currentTestCase !== null) { + $writer->endElement(); + } + + $writer->startElement('testCaseClass'); + $writer->writeAttribute('name', $test::class); + + $currentTestCase = $test::class; + } + + $writer->startElement('testCaseMethod'); + $writer->writeAttribute('id', $test->valueObjectForEvents()->id()); + $writer->writeAttribute('name', $test->name()); + $writer->writeAttribute('groups', implode(',', $test->groups())); + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5481 + */ + if (!empty($test->dataSetAsString())) { + $writer->writeAttribute( + 'dataSet', + str_replace( + ' with data set ', + '', + $test->dataSetAsString(), + ), + ); + } + + $writer->endElement(); + + continue; + } + + if ($test instanceof PhptTestCase) { + if ($currentTestCase !== null) { + $writer->endElement(); + + $currentTestCase = null; + } + + $writer->startElement('phptFile'); + $writer->writeAttribute('path', $test->getName()); + $writer->endElement(); + } + } + + if ($currentTestCase !== null) { + $writer->endElement(); + } + + $writer->endElement(); + + file_put_contents($this->filename, $writer->outputMemory()); + + $buffer .= sprintf( + 'Wrote list of tests that would have been run to %s' . PHP_EOL, + $this->filename, + ); + + return Result::from($buffer); + } + + private function warnAboutConflictingOptions(): string + { + $buffer = ''; + + $configuration = Registry::get(); + + if ($configuration->hasFilter()) { + $buffer .= 'The --filter and --list-tests-xml options cannot be combined, --filter is ignored' . PHP_EOL; + } + + if ($configuration->hasGroups()) { + $buffer .= 'The --group and --list-tests-xml options cannot be combined, --group is ignored' . PHP_EOL; + } + + if ($configuration->hasExcludeGroups()) { + $buffer .= 'The --exclude-group and --list-tests-xml options cannot be combined, --exclude-group is ignored' . PHP_EOL; + } + + if (!empty($buffer)) { + $buffer .= PHP_EOL; + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php new file mode 100644 index 000000000..cde391ab6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function copy; +use function file_put_contents; +use function sprintf; +use PHPUnit\TextUI\XmlConfiguration\Migrator; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MigrateConfigurationCommand implements Command +{ + private readonly string $filename; + + public function __construct(string $filename) + { + $this->filename = $filename; + } + + public function execute(): Result + { + try { + $migrated = (new Migrator)->migrate($this->filename); + + copy($this->filename, $this->filename . '.bak'); + + file_put_contents($this->filename, $migrated); + + return Result::from( + sprintf( + 'Created backup: %s.bak%sMigrated configuration: %s%s', + $this->filename, + PHP_EOL, + $this->filename, + PHP_EOL, + ), + ); + } catch (Throwable $t) { + return Result::from( + sprintf( + 'Migration of %s failed:%s%s%s', + $this->filename, + PHP_EOL, + $t->getMessage(), + PHP_EOL, + ), + Result::FAILURE, + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php new file mode 100644 index 000000000..654cbb883 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use PHPUnit\TextUI\Help; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ShowHelpCommand implements Command +{ + private readonly int $shellExitCode; + + public function __construct(int $shellExitCode) + { + $this->shellExitCode = $shellExitCode; + } + + public function execute(): Result + { + return Result::from( + (new Help)->generate(), + $this->shellExitCode, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php new file mode 100644 index 000000000..b1e66510e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ShowVersionCommand implements Command +{ + public function execute(): Result + { + return Result::from(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php new file mode 100644 index 000000000..95dabba8c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function assert; +use function sprintf; +use function version_compare; +use PHPUnit\Util\Http\Downloader; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class VersionCheckCommand implements Command +{ + private readonly Downloader $downloader; + private readonly int $majorVersionNumber; + private readonly string $versionId; + + public function __construct(Downloader $downloader, int $majorVersionNumber, string $versionId) + { + $this->downloader = $downloader; + $this->majorVersionNumber = $majorVersionNumber; + $this->versionId = $versionId; + } + + public function execute(): Result + { + $latestVersion = $this->downloader->download('https://phar.phpunit.de/latest-version-of/phpunit'); + + assert($latestVersion !== false); + + $latestCompatibleVersion = $this->downloader->download('https://phar.phpunit.de/latest-version-of/phpunit-' . $this->majorVersionNumber); + + assert($latestCompatibleVersion !== false); + + $notLatest = version_compare($latestVersion, $this->versionId, '>'); + $notLatestCompatible = version_compare($latestCompatibleVersion, $this->versionId, '>'); + + if (!$notLatest && !$notLatestCompatible) { + return Result::from( + 'You are using the latest version of PHPUnit.' . PHP_EOL, + ); + } + + $buffer = 'You are not using the latest version of PHPUnit.' . PHP_EOL; + + if ($notLatestCompatible) { + $buffer .= sprintf( + 'The latest version compatible with PHPUnit %s is PHPUnit %s.' . PHP_EOL, + $this->versionId, + $latestCompatibleVersion, + ); + } + + if ($notLatest) { + $buffer .= sprintf( + 'The latest version is PHPUnit %s.' . PHP_EOL, + $latestVersion, + ); + } + + return Result::from($buffer); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php new file mode 100644 index 000000000..fa8256e7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Command; + +use const PHP_EOL; +use function printf; +use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\NoCoverageCacheDirectoryException; +use SebastianBergmann\CodeCoverage\StaticAnalysis\CacheWarmer; +use SebastianBergmann\Timer\NoActiveTimerException; +use SebastianBergmann\Timer\Timer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ +final class WarmCodeCoverageCacheCommand implements Command +{ + private readonly Configuration $configuration; + private readonly CodeCoverageFilterRegistry $codeCoverageFilterRegistry; + + public function __construct(Configuration $configuration, CodeCoverageFilterRegistry $codeCoverageFilterRegistry) + { + $this->configuration = $configuration; + $this->codeCoverageFilterRegistry = $codeCoverageFilterRegistry; + } + + /** + * @throws NoActiveTimerException + * @throws NoCoverageCacheDirectoryException + */ + public function execute(): Result + { + if (!$this->configuration->hasCoverageCacheDirectory()) { + return Result::from( + 'Cache for static analysis has not been configured' . PHP_EOL, + Result::FAILURE, + ); + } + + $this->codeCoverageFilterRegistry->init($this->configuration, true); + + if (!$this->codeCoverageFilterRegistry->configured()) { + return Result::from( + 'Filter for code coverage has not been configured' . PHP_EOL, + Result::FAILURE, + ); + } + + $timer = new Timer; + $timer->start(); + + print 'Warming cache for static analysis ... '; + + (new CacheWarmer)->warmCache( + $this->configuration->coverageCacheDirectory(), + !$this->configuration->disableCodeCoverageIgnore(), + $this->configuration->ignoreDeprecatedCodeUnitsFromCodeCoverage(), + $this->codeCoverageFilterRegistry->get(), + ); + + printf( + '[%s]%s', + $timer->stop()->asString(), + PHP_EOL, + ); + + return Result::from(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Result.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Result.php new file mode 100644 index 000000000..b0544e7a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Command/Result.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 PHPUnit\TextUI\Command; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Result +{ + public const SUCCESS = 0; + public const FAILURE = 1; + public const EXCEPTION = 2; + public const CRASH = 255; + private readonly string $output; + private readonly int $shellExitCode; + + public static function from(string $output = '', int $shellExitCode = self::SUCCESS): self + { + return new self($output, $shellExitCode); + } + + private function __construct(string $output, int $shellExitCode) + { + $this->output = $output; + $this->shellExitCode = $shellExitCode; + } + + public function output(): string + { + return $this->output; + } + + public function shellExitCode(): int + { + return $this->shellExitCode; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Builder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Builder.php new file mode 100644 index 000000000..6ada9b4a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Builder.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use PHPUnit\TextUI\CliArguments\Builder as CliConfigurationBuilder; +use PHPUnit\TextUI\CliArguments\Exception as CliConfigurationException; +use PHPUnit\TextUI\CliArguments\XmlConfigurationFileFinder; +use PHPUnit\TextUI\XmlConfiguration\DefaultConfiguration; +use PHPUnit\TextUI\XmlConfiguration\Exception as XmlConfigurationException; +use PHPUnit\TextUI\XmlConfiguration\Loader; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @codeCoverageIgnore + */ +final class Builder +{ + /** + * @throws ConfigurationCannotBeBuiltException + */ + public function build(array $argv): Configuration + { + try { + $cliConfiguration = (new CliConfigurationBuilder)->fromParameters($argv); + $configurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration); + $xmlConfiguration = DefaultConfiguration::create(); + + if ($configurationFile !== false) { + $xmlConfiguration = (new Loader)->load($configurationFile); + } + + return Registry::init( + $cliConfiguration, + $xmlConfiguration, + ); + } catch (CliConfigurationException|XmlConfigurationException $e) { + throw new ConfigurationCannotBeBuiltException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php new file mode 100644 index 000000000..bc3bfd364 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Builder.php @@ -0,0 +1,1020 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +use const DIRECTORY_SEPARATOR; +use function array_map; +use function basename; +use function explode; +use function getcwd; +use function is_file; +use function is_numeric; +use function sprintf; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\Util\Filesystem; +use SebastianBergmann\CliParser\Exception as CliParserException; +use SebastianBergmann\CliParser\Parser as CliParser; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Builder +{ + private const LONG_OPTIONS = [ + 'atleast-version=', + 'bootstrap=', + 'cache-result', + 'do-not-cache-result', + 'cache-directory=', + 'cache-result-file=', + 'check-version', + 'colors==', + 'columns=', + 'configuration=', + 'coverage-cache=', + 'warm-coverage-cache', + 'coverage-filter=', + 'coverage-clover=', + 'coverage-cobertura=', + 'coverage-crap4j=', + 'coverage-html=', + 'coverage-php=', + 'coverage-text==', + 'only-summary-for-coverage-text', + 'show-uncovered-for-coverage-text', + 'coverage-xml=', + 'path-coverage', + 'disallow-test-output', + 'display-incomplete', + 'display-skipped', + 'display-deprecations', + 'display-phpunit-deprecations', + 'display-errors', + 'display-notices', + 'display-warnings', + 'default-time-limit=', + 'enforce-time-limit', + 'exclude-group=', + 'filter=', + 'generate-baseline=', + 'use-baseline=', + 'ignore-baseline', + 'generate-configuration', + 'globals-backup', + 'group=', + 'covers=', + 'uses=', + 'help', + 'resolve-dependencies', + 'ignore-dependencies', + 'include-path=', + 'list-groups', + 'list-suites', + 'list-tests', + 'list-tests-xml=', + 'log-junit=', + 'log-teamcity=', + 'migrate-configuration', + 'no-configuration', + 'no-coverage', + 'no-logging', + 'no-extensions', + 'no-output', + 'no-progress', + 'no-results', + 'order-by=', + 'process-isolation', + 'dont-report-useless-tests', + 'random-order', + 'random-order-seed=', + 'reverse-order', + 'reverse-list', + 'static-backup', + 'stderr', + 'fail-on-deprecation', + 'fail-on-phpunit-deprecation', + 'fail-on-empty-test-suite', + 'fail-on-incomplete', + 'fail-on-notice', + 'fail-on-risky', + 'fail-on-skipped', + 'fail-on-warning', + 'stop-on-defect', + 'stop-on-deprecation', + 'stop-on-error', + 'stop-on-failure', + 'stop-on-incomplete', + 'stop-on-notice', + 'stop-on-risky', + 'stop-on-skipped', + 'stop-on-warning', + 'strict-coverage', + 'disable-coverage-ignore', + 'strict-global-state', + 'teamcity', + 'testdox', + 'testdox-html=', + 'testdox-text=', + 'test-suffix=', + 'testsuite=', + 'exclude-testsuite=', + 'log-events-text=', + 'log-events-verbose-text=', + 'version', + 'debug', + ]; + private const SHORT_OPTIONS = 'd:c:h'; + + /** + * @psalm-var array + */ + private array $processed = []; + + /** + * @throws Exception + */ + public function fromParameters(array $parameters): Configuration + { + try { + $options = (new CliParser)->parse( + $parameters, + self::SHORT_OPTIONS, + self::LONG_OPTIONS, + ); + } catch (CliParserException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + $atLeastVersion = null; + $backupGlobals = null; + $backupStaticProperties = null; + $beStrictAboutChangesToGlobalState = null; + $bootstrap = null; + $cacheDirectory = null; + $cacheResult = null; + $cacheResultFile = null; + $checkVersion = false; + $colors = null; + $columns = null; + $configuration = null; + $coverageCacheDirectory = null; + $warmCoverageCache = false; + $coverageFilter = null; + $coverageClover = null; + $coverageCobertura = null; + $coverageCrap4J = null; + $coverageHtml = null; + $coveragePhp = null; + $coverageText = null; + $coverageTextShowUncoveredFiles = null; + $coverageTextShowOnlySummary = null; + $coverageXml = null; + $pathCoverage = null; + $defaultTimeLimit = null; + $disableCodeCoverageIgnore = null; + $disallowTestOutput = null; + $displayIncomplete = null; + $displaySkipped = null; + $displayDeprecations = null; + $displayPhpunitDeprecations = null; + $displayErrors = null; + $displayNotices = null; + $displayWarnings = null; + $enforceTimeLimit = null; + $excludeGroups = null; + $executionOrder = null; + $executionOrderDefects = null; + $failOnDeprecation = null; + $failOnPhpunitDeprecation = null; + $failOnEmptyTestSuite = null; + $failOnIncomplete = null; + $failOnNotice = null; + $failOnRisky = null; + $failOnSkipped = null; + $failOnWarning = null; + $stopOnDefect = null; + $stopOnDeprecation = null; + $stopOnError = null; + $stopOnFailure = null; + $stopOnIncomplete = null; + $stopOnNotice = null; + $stopOnRisky = null; + $stopOnSkipped = null; + $stopOnWarning = null; + $filter = null; + $generateBaseline = null; + $useBaseline = null; + $ignoreBaseline = false; + $generateConfiguration = false; + $migrateConfiguration = false; + $groups = null; + $testsCovering = null; + $testsUsing = null; + $help = false; + $includePath = null; + $iniSettings = []; + $junitLogfile = null; + $listGroups = false; + $listSuites = false; + $listTests = false; + $listTestsXml = null; + $noCoverage = null; + $noExtensions = null; + $noOutput = null; + $noProgress = null; + $noResults = null; + $noLogging = null; + $processIsolation = null; + $randomOrderSeed = null; + $reportUselessTests = null; + $resolveDependencies = null; + $reverseList = null; + $stderr = null; + $strictCoverage = null; + $teamcityLogfile = null; + $testdoxHtmlFile = null; + $testdoxTextFile = null; + $testSuffixes = null; + $testSuite = null; + $excludeTestSuite = null; + $useDefaultConfiguration = true; + $version = false; + $logEventsText = null; + $logEventsVerboseText = null; + $printerTeamCity = null; + $printerTestDox = null; + $debug = false; + + foreach ($options[0] as $option) { + $optionAllowedMultipleTimes = false; + + switch ($option[0]) { + case '--colors': + $colors = $option[1] ?: \PHPUnit\TextUI\Configuration\Configuration::COLOR_AUTO; + + break; + + case '--bootstrap': + $bootstrap = $option[1]; + + break; + + case '--cache-directory': + $cacheDirectory = $option[1]; + + break; + + case '--cache-result': + $cacheResult = true; + + break; + + case '--do-not-cache-result': + $cacheResult = false; + + break; + + case '--cache-result-file': + $cacheResultFile = $option[1]; + + break; + + case '--columns': + if (is_numeric($option[1])) { + $columns = (int) $option[1]; + } elseif ($option[1] === 'max') { + $columns = 'max'; + } + + break; + + case 'c': + case '--configuration': + $configuration = $option[1]; + + break; + + case '--coverage-cache': + $coverageCacheDirectory = $option[1]; + + break; + + case '--warm-coverage-cache': + $warmCoverageCache = true; + + break; + + case '--coverage-clover': + $coverageClover = $option[1]; + + break; + + case '--coverage-cobertura': + $coverageCobertura = $option[1]; + + break; + + case '--coverage-crap4j': + $coverageCrap4J = $option[1]; + + break; + + case '--coverage-html': + $coverageHtml = $option[1]; + + break; + + case '--coverage-php': + $coveragePhp = $option[1]; + + break; + + case '--coverage-text': + if ($option[1] === null) { + $option[1] = 'php://stdout'; + } + + $coverageText = $option[1]; + + break; + + case '--only-summary-for-coverage-text': + $coverageTextShowOnlySummary = true; + + break; + + case '--show-uncovered-for-coverage-text': + $coverageTextShowUncoveredFiles = true; + + break; + + case '--coverage-xml': + $coverageXml = $option[1]; + + break; + + case '--path-coverage': + $pathCoverage = true; + + break; + + case 'd': + $tmp = explode('=', $option[1]); + + if (isset($tmp[0])) { + if (isset($tmp[1])) { + $iniSettings[$tmp[0]] = $tmp[1]; + } else { + $iniSettings[$tmp[0]] = '1'; + } + } + + $optionAllowedMultipleTimes = true; + + break; + + case 'h': + case '--help': + $help = true; + + break; + + case '--filter': + $filter = $option[1]; + + break; + + case '--testsuite': + $testSuite = $option[1]; + + break; + + case '--exclude-testsuite': + $excludeTestSuite = $option[1]; + + break; + + case '--generate-baseline': + $generateBaseline = $option[1]; + + if (basename($generateBaseline) === $generateBaseline) { + $generateBaseline = getcwd() . DIRECTORY_SEPARATOR . $generateBaseline; + } + + break; + + case '--use-baseline': + $useBaseline = $option[1]; + + if (basename($useBaseline) === $useBaseline && !is_file($useBaseline)) { + $useBaseline = getcwd() . DIRECTORY_SEPARATOR . $useBaseline; + } + + break; + + case '--ignore-baseline': + $ignoreBaseline = true; + + break; + + case '--generate-configuration': + $generateConfiguration = true; + + break; + + case '--migrate-configuration': + $migrateConfiguration = true; + + break; + + case '--group': + $groups = explode(',', $option[1]); + + break; + + case '--exclude-group': + $excludeGroups = explode(',', $option[1]); + + break; + + case '--covers': + $testsCovering = array_map('strtolower', explode(',', $option[1])); + + break; + + case '--uses': + $testsUsing = array_map('strtolower', explode(',', $option[1])); + + break; + + case '--test-suffix': + $testSuffixes = explode(',', $option[1]); + + break; + + case '--include-path': + $includePath = $option[1]; + + break; + + case '--list-groups': + $listGroups = true; + + break; + + case '--list-suites': + $listSuites = true; + + break; + + case '--list-tests': + $listTests = true; + + break; + + case '--list-tests-xml': + $listTestsXml = $option[1]; + + break; + + case '--log-junit': + $junitLogfile = $option[1]; + + break; + + case '--log-teamcity': + $teamcityLogfile = $option[1]; + + break; + + case '--order-by': + foreach (explode(',', $option[1]) as $order) { + switch ($order) { + case 'default': + $executionOrder = TestSuiteSorter::ORDER_DEFAULT; + $executionOrderDefects = TestSuiteSorter::ORDER_DEFAULT; + $resolveDependencies = true; + + break; + + case 'defects': + $executionOrderDefects = TestSuiteSorter::ORDER_DEFECTS_FIRST; + + break; + + case 'depends': + $resolveDependencies = true; + + break; + + case 'duration': + $executionOrder = TestSuiteSorter::ORDER_DURATION; + + break; + + case 'no-depends': + $resolveDependencies = false; + + break; + + case 'random': + $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case 'reverse': + $executionOrder = TestSuiteSorter::ORDER_REVERSED; + + break; + + case 'size': + $executionOrder = TestSuiteSorter::ORDER_SIZE; + + break; + + default: + throw new Exception( + sprintf( + 'unrecognized --order-by option: %s', + $order, + ), + ); + } + } + + break; + + case '--process-isolation': + $processIsolation = true; + + break; + + case '--stderr': + $stderr = true; + + break; + + case '--fail-on-deprecation': + $failOnDeprecation = true; + + break; + + case '--fail-on-phpunit-deprecation': + $failOnPhpunitDeprecation = true; + + break; + + case '--fail-on-empty-test-suite': + $failOnEmptyTestSuite = true; + + break; + + case '--fail-on-incomplete': + $failOnIncomplete = true; + + break; + + case '--fail-on-notice': + $failOnNotice = true; + + break; + + case '--fail-on-risky': + $failOnRisky = true; + + break; + + case '--fail-on-skipped': + $failOnSkipped = true; + + break; + + case '--fail-on-warning': + $failOnWarning = true; + + break; + + case '--stop-on-defect': + $stopOnDefect = true; + + break; + + case '--stop-on-deprecation': + $stopOnDeprecation = true; + + break; + + case '--stop-on-error': + $stopOnError = true; + + break; + + case '--stop-on-failure': + $stopOnFailure = true; + + break; + + case '--stop-on-incomplete': + $stopOnIncomplete = true; + + break; + + case '--stop-on-notice': + $stopOnNotice = true; + + break; + + case '--stop-on-risky': + $stopOnRisky = true; + + break; + + case '--stop-on-skipped': + $stopOnSkipped = true; + + break; + + case '--stop-on-warning': + $stopOnWarning = true; + + break; + + case '--teamcity': + $printerTeamCity = true; + + break; + + case '--testdox': + $printerTestDox = true; + + break; + + case '--testdox-html': + $testdoxHtmlFile = $option[1]; + + break; + + case '--testdox-text': + $testdoxTextFile = $option[1]; + + break; + + case '--no-configuration': + $useDefaultConfiguration = false; + + break; + + case '--no-extensions': + $noExtensions = true; + + break; + + case '--no-coverage': + $noCoverage = true; + + break; + + case '--no-logging': + $noLogging = true; + + break; + + case '--no-output': + $noOutput = true; + + break; + + case '--no-progress': + $noProgress = true; + + break; + + case '--no-results': + $noResults = true; + + break; + + case '--globals-backup': + $backupGlobals = true; + + break; + + case '--static-backup': + $backupStaticProperties = true; + + break; + + case '--atleast-version': + $atLeastVersion = $option[1]; + + break; + + case '--version': + $version = true; + + break; + + case '--dont-report-useless-tests': + $reportUselessTests = false; + + break; + + case '--strict-coverage': + $strictCoverage = true; + + break; + + case '--disable-coverage-ignore': + $disableCodeCoverageIgnore = true; + + break; + + case '--strict-global-state': + $beStrictAboutChangesToGlobalState = true; + + break; + + case '--disallow-test-output': + $disallowTestOutput = true; + + break; + + case '--display-incomplete': + $displayIncomplete = true; + + break; + + case '--display-skipped': + $displaySkipped = true; + + break; + + case '--display-deprecations': + $displayDeprecations = true; + + break; + + case '--display-phpunit-deprecations': + $displayPhpunitDeprecations = true; + + break; + + case '--display-errors': + $displayErrors = true; + + break; + + case '--display-notices': + $displayNotices = true; + + break; + + case '--display-warnings': + $displayWarnings = true; + + break; + + case '--default-time-limit': + $defaultTimeLimit = (int) $option[1]; + + break; + + case '--enforce-time-limit': + $enforceTimeLimit = true; + + break; + + case '--reverse-list': + $reverseList = true; + + break; + + case '--check-version': + $checkVersion = true; + + break; + + case '--coverage-filter': + if ($coverageFilter === null) { + $coverageFilter = []; + } + + $coverageFilter[] = $option[1]; + + $optionAllowedMultipleTimes = true; + + break; + + case '--random-order': + $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case '--random-order-seed': + $randomOrderSeed = (int) $option[1]; + + break; + + case '--resolve-dependencies': + $resolveDependencies = true; + + break; + + case '--ignore-dependencies': + $resolveDependencies = false; + + break; + + case '--reverse-order': + $executionOrder = TestSuiteSorter::ORDER_REVERSED; + + break; + + case '--log-events-text': + $logEventsText = Filesystem::resolveStreamOrFile($option[1]); + + if ($logEventsText === false) { + throw new Exception( + sprintf( + 'The path "%s" specified for the --log-events-text option could not be resolved', + $option[1], + ), + ); + } + + break; + + case '--log-events-verbose-text': + $logEventsVerboseText = Filesystem::resolveStreamOrFile($option[1]); + + if ($logEventsVerboseText === false) { + throw new Exception( + sprintf( + 'The path "%s" specified for the --log-events-verbose-text option could not be resolved', + $option[1], + ), + ); + } + + break; + + case '--debug': + $debug = true; + + break; + } + + if (!$optionAllowedMultipleTimes) { + $this->markProcessed($option[0]); + } + } + + if (empty($iniSettings)) { + $iniSettings = null; + } + + if (empty($coverageFilter)) { + $coverageFilter = null; + } + + return new Configuration( + $options[1], + $atLeastVersion, + $backupGlobals, + $backupStaticProperties, + $beStrictAboutChangesToGlobalState, + $bootstrap, + $cacheDirectory, + $cacheResult, + $cacheResultFile, + $checkVersion, + $colors, + $columns, + $configuration, + $coverageClover, + $coverageCobertura, + $coverageCrap4J, + $coverageHtml, + $coveragePhp, + $coverageText, + $coverageTextShowUncoveredFiles, + $coverageTextShowOnlySummary, + $coverageXml, + $pathCoverage, + $coverageCacheDirectory, + $warmCoverageCache, + $defaultTimeLimit, + $disableCodeCoverageIgnore, + $disallowTestOutput, + $enforceTimeLimit, + $excludeGroups, + $executionOrder, + $executionOrderDefects, + $failOnDeprecation, + $failOnPhpunitDeprecation, + $failOnEmptyTestSuite, + $failOnIncomplete, + $failOnNotice, + $failOnRisky, + $failOnSkipped, + $failOnWarning, + $stopOnDefect, + $stopOnDeprecation, + $stopOnError, + $stopOnFailure, + $stopOnIncomplete, + $stopOnNotice, + $stopOnRisky, + $stopOnSkipped, + $stopOnWarning, + $filter, + $generateBaseline, + $useBaseline, + $ignoreBaseline, + $generateConfiguration, + $migrateConfiguration, + $groups, + $testsCovering, + $testsUsing, + $help, + $includePath, + $iniSettings, + $junitLogfile, + $listGroups, + $listSuites, + $listTests, + $listTestsXml, + $noCoverage, + $noExtensions, + $noOutput, + $noProgress, + $noResults, + $noLogging, + $processIsolation, + $randomOrderSeed, + $reportUselessTests, + $resolveDependencies, + $reverseList, + $stderr, + $strictCoverage, + $teamcityLogfile, + $testdoxHtmlFile, + $testdoxTextFile, + $testSuffixes, + $testSuite, + $excludeTestSuite, + $useDefaultConfiguration, + $displayIncomplete, + $displaySkipped, + $displayDeprecations, + $displayPhpunitDeprecations, + $displayErrors, + $displayNotices, + $displayWarnings, + $version, + $coverageFilter, + $logEventsText, + $logEventsVerboseText, + $printerTeamCity, + $printerTestDox, + $debug, + ); + } + + /** + * @psalm-param non-empty-string $option + */ + private function markProcessed(string $option): void + { + if (!isset($this->processed[$option])) { + $this->processed[$option] = 1; + + return; + } + + $this->processed[$option]++; + + if ($this->processed[$option] === 2) { + EventFacade::emitter()->testRunnerTriggeredWarning( + sprintf( + 'Option %s cannot be used more than once', + $option, + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php new file mode 100644 index 000000000..84cb00c19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Configuration.php @@ -0,0 +1,2054 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Configuration +{ + /** + * @psalm-var list + */ + private readonly array $arguments; + private readonly ?string $atLeastVersion; + private readonly ?bool $backupGlobals; + private readonly ?bool $backupStaticProperties; + private readonly ?bool $beStrictAboutChangesToGlobalState; + private readonly ?string $bootstrap; + private readonly ?string $cacheDirectory; + private readonly ?bool $cacheResult; + private readonly ?string $cacheResultFile; + private readonly bool $checkVersion; + private readonly ?string $colors; + private readonly null|int|string $columns; + private readonly ?string $configurationFile; + private readonly ?array $coverageFilter; + private readonly ?string $coverageClover; + private readonly ?string $coverageCobertura; + private readonly ?string $coverageCrap4J; + private readonly ?string $coverageHtml; + private readonly ?string $coveragePhp; + private readonly ?string $coverageText; + private readonly ?bool $coverageTextShowUncoveredFiles; + private readonly ?bool $coverageTextShowOnlySummary; + private readonly ?string $coverageXml; + private readonly ?bool $pathCoverage; + private readonly ?string $coverageCacheDirectory; + private readonly bool $warmCoverageCache; + private readonly ?int $defaultTimeLimit; + private readonly ?bool $disableCodeCoverageIgnore; + private readonly ?bool $disallowTestOutput; + private readonly ?bool $enforceTimeLimit; + private readonly ?array $excludeGroups; + private readonly ?int $executionOrder; + private readonly ?int $executionOrderDefects; + private readonly ?bool $failOnDeprecation; + private readonly ?bool $failOnPhpunitDeprecation; + private readonly ?bool $failOnEmptyTestSuite; + private readonly ?bool $failOnIncomplete; + private readonly ?bool $failOnNotice; + private readonly ?bool $failOnRisky; + private readonly ?bool $failOnSkipped; + private readonly ?bool $failOnWarning; + private readonly ?bool $stopOnDefect; + private readonly ?bool $stopOnDeprecation; + private readonly ?bool $stopOnError; + private readonly ?bool $stopOnFailure; + private readonly ?bool $stopOnIncomplete; + private readonly ?bool $stopOnNotice; + private readonly ?bool $stopOnRisky; + private readonly ?bool $stopOnSkipped; + private readonly ?bool $stopOnWarning; + private readonly ?string $filter; + private readonly ?string $generateBaseline; + private readonly ?string $useBaseline; + private readonly bool $ignoreBaseline; + private readonly bool $generateConfiguration; + private readonly bool $migrateConfiguration; + private readonly ?array $groups; + private readonly ?array $testsCovering; + private readonly ?array $testsUsing; + private readonly bool $help; + private readonly ?string $includePath; + private readonly ?array $iniSettings; + private readonly ?string $junitLogfile; + private readonly bool $listGroups; + private readonly bool $listSuites; + private readonly bool $listTests; + private readonly ?string $listTestsXml; + private readonly ?bool $noCoverage; + private readonly ?bool $noExtensions; + private readonly ?bool $noOutput; + private readonly ?bool $noProgress; + private readonly ?bool $noResults; + private readonly ?bool $noLogging; + private readonly ?bool $processIsolation; + private readonly ?int $randomOrderSeed; + private readonly ?bool $reportUselessTests; + private readonly ?bool $resolveDependencies; + private readonly ?bool $reverseList; + private readonly ?bool $stderr; + private readonly ?bool $strictCoverage; + private readonly ?string $teamcityLogfile; + private readonly ?bool $teamCityPrinter; + private readonly ?string $testdoxHtmlFile; + private readonly ?string $testdoxTextFile; + private readonly ?bool $testdoxPrinter; + + /** + * @psalm-var ?non-empty-list + */ + private readonly ?array $testSuffixes; + private readonly ?string $testSuite; + private readonly ?string $excludeTestSuite; + private readonly bool $useDefaultConfiguration; + private readonly ?bool $displayDetailsOnIncompleteTests; + private readonly ?bool $displayDetailsOnSkippedTests; + private readonly ?bool $displayDetailsOnTestsThatTriggerDeprecations; + private readonly ?bool $displayDetailsOnPhpunitDeprecations; + private readonly ?bool $displayDetailsOnTestsThatTriggerErrors; + private readonly ?bool $displayDetailsOnTestsThatTriggerNotices; + private readonly ?bool $displayDetailsOnTestsThatTriggerWarnings; + private readonly bool $version; + private readonly ?string $logEventsText; + private readonly ?string $logEventsVerboseText; + private readonly bool $debug; + + /** + * @psalm-param list $arguments + * @psalm-param ?non-empty-list $testSuffixes + */ + public function __construct(array $arguments, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, ?string $cacheResultFile, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, ?string $coverageCacheDirectory, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnDeprecation, ?bool $failOnPhpunitDeprecation, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, ?string $generateBaseline, ?string $useBaseline, bool $ignoreBaseline, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnPhpunitDeprecations, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $printerTestDox, bool $debug) + { + $this->arguments = $arguments; + $this->atLeastVersion = $atLeastVersion; + $this->backupGlobals = $backupGlobals; + $this->backupStaticProperties = $backupStaticProperties; + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + $this->bootstrap = $bootstrap; + $this->cacheDirectory = $cacheDirectory; + $this->cacheResult = $cacheResult; + $this->cacheResultFile = $cacheResultFile; + $this->checkVersion = $checkVersion; + $this->colors = $colors; + $this->columns = $columns; + $this->configurationFile = $configurationFile; + $this->coverageFilter = $coverageFilter; + $this->coverageClover = $coverageClover; + $this->coverageCobertura = $coverageCobertura; + $this->coverageCrap4J = $coverageCrap4J; + $this->coverageHtml = $coverageHtml; + $this->coveragePhp = $coveragePhp; + $this->coverageText = $coverageText; + $this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles; + $this->coverageTextShowOnlySummary = $coverageTextShowOnlySummary; + $this->coverageXml = $coverageXml; + $this->pathCoverage = $pathCoverage; + $this->coverageCacheDirectory = $coverageCacheDirectory; + $this->warmCoverageCache = $warmCoverageCache; + $this->defaultTimeLimit = $defaultTimeLimit; + $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; + $this->disallowTestOutput = $disallowTestOutput; + $this->enforceTimeLimit = $enforceTimeLimit; + $this->excludeGroups = $excludeGroups; + $this->executionOrder = $executionOrder; + $this->executionOrderDefects = $executionOrderDefects; + $this->failOnDeprecation = $failOnDeprecation; + $this->failOnPhpunitDeprecation = $failOnPhpunitDeprecation; + $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; + $this->failOnIncomplete = $failOnIncomplete; + $this->failOnNotice = $failOnNotice; + $this->failOnRisky = $failOnRisky; + $this->failOnSkipped = $failOnSkipped; + $this->failOnWarning = $failOnWarning; + $this->stopOnDefect = $stopOnDefect; + $this->stopOnDeprecation = $stopOnDeprecation; + $this->stopOnError = $stopOnError; + $this->stopOnFailure = $stopOnFailure; + $this->stopOnIncomplete = $stopOnIncomplete; + $this->stopOnNotice = $stopOnNotice; + $this->stopOnRisky = $stopOnRisky; + $this->stopOnSkipped = $stopOnSkipped; + $this->stopOnWarning = $stopOnWarning; + $this->filter = $filter; + $this->generateBaseline = $generateBaseline; + $this->useBaseline = $useBaseline; + $this->ignoreBaseline = $ignoreBaseline; + $this->generateConfiguration = $generateConfiguration; + $this->migrateConfiguration = $migrateConfiguration; + $this->groups = $groups; + $this->testsCovering = $testsCovering; + $this->testsUsing = $testsUsing; + $this->help = $help; + $this->includePath = $includePath; + $this->iniSettings = $iniSettings; + $this->junitLogfile = $junitLogfile; + $this->listGroups = $listGroups; + $this->listSuites = $listSuites; + $this->listTests = $listTests; + $this->listTestsXml = $listTestsXml; + $this->noCoverage = $noCoverage; + $this->noExtensions = $noExtensions; + $this->noOutput = $noOutput; + $this->noProgress = $noProgress; + $this->noResults = $noResults; + $this->noLogging = $noLogging; + $this->processIsolation = $processIsolation; + $this->randomOrderSeed = $randomOrderSeed; + $this->reportUselessTests = $reportUselessTests; + $this->resolveDependencies = $resolveDependencies; + $this->reverseList = $reverseList; + $this->stderr = $stderr; + $this->strictCoverage = $strictCoverage; + $this->teamcityLogfile = $teamcityLogfile; + $this->testdoxHtmlFile = $testdoxHtmlFile; + $this->testdoxTextFile = $testdoxTextFile; + $this->testSuffixes = $testSuffixes; + $this->testSuite = $testSuite; + $this->excludeTestSuite = $excludeTestSuite; + $this->useDefaultConfiguration = $useDefaultConfiguration; + $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; + $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; + $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; + $this->displayDetailsOnPhpunitDeprecations = $displayDetailsOnPhpunitDeprecations; + $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; + $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; + $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; + $this->version = $version; + $this->logEventsText = $logEventsText; + $this->logEventsVerboseText = $logEventsVerboseText; + $this->teamCityPrinter = $printerTeamCity; + $this->testdoxPrinter = $printerTestDox; + $this->debug = $debug; + } + + /** + * @psalm-return list + */ + public function arguments(): array + { + return $this->arguments; + } + + /** + * @psalm-assert-if-true !null $this->atLeastVersion + */ + public function hasAtLeastVersion(): bool + { + return $this->atLeastVersion !== null; + } + + /** + * @throws Exception + */ + public function atLeastVersion(): string + { + if (!$this->hasAtLeastVersion()) { + throw new Exception; + } + + return $this->atLeastVersion; + } + + /** + * @psalm-assert-if-true !null $this->backupGlobals + */ + public function hasBackupGlobals(): bool + { + return $this->backupGlobals !== null; + } + + /** + * @throws Exception + */ + public function backupGlobals(): bool + { + if (!$this->hasBackupGlobals()) { + throw new Exception; + } + + return $this->backupGlobals; + } + + /** + * @psalm-assert-if-true !null $this->backupStaticProperties + */ + public function hasBackupStaticProperties(): bool + { + return $this->backupStaticProperties !== null; + } + + /** + * @throws Exception + */ + public function backupStaticProperties(): bool + { + if (!$this->hasBackupStaticProperties()) { + throw new Exception; + } + + return $this->backupStaticProperties; + } + + /** + * @psalm-assert-if-true !null $this->beStrictAboutChangesToGlobalState + */ + public function hasBeStrictAboutChangesToGlobalState(): bool + { + return $this->beStrictAboutChangesToGlobalState !== null; + } + + /** + * @throws Exception + */ + public function beStrictAboutChangesToGlobalState(): bool + { + if (!$this->hasBeStrictAboutChangesToGlobalState()) { + throw new Exception; + } + + return $this->beStrictAboutChangesToGlobalState; + } + + /** + * @psalm-assert-if-true !null $this->bootstrap + */ + public function hasBootstrap(): bool + { + return $this->bootstrap !== null; + } + + /** + * @throws Exception + */ + public function bootstrap(): string + { + if (!$this->hasBootstrap()) { + throw new Exception; + } + + return $this->bootstrap; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + */ + public function hasCacheDirectory(): bool + { + return $this->cacheDirectory !== null; + } + + /** + * @throws Exception + */ + public function cacheDirectory(): string + { + if (!$this->hasCacheDirectory()) { + throw new Exception; + } + + return $this->cacheDirectory; + } + + /** + * @psalm-assert-if-true !null $this->cacheResult + */ + public function hasCacheResult(): bool + { + return $this->cacheResult !== null; + } + + /** + * @throws Exception + */ + public function cacheResult(): bool + { + if (!$this->hasCacheResult()) { + throw new Exception; + } + + return $this->cacheResult; + } + + /** + * @psalm-assert-if-true !null $this->cacheResultFile + * + * @deprecated + */ + public function hasCacheResultFile(): bool + { + return $this->cacheResultFile !== null; + } + + /** + * @throws Exception + * + * @deprecated + */ + public function cacheResultFile(): string + { + if (!$this->hasCacheResultFile()) { + throw new Exception; + } + + return $this->cacheResultFile; + } + + public function checkVersion(): bool + { + return $this->checkVersion; + } + + /** + * @psalm-assert-if-true !null $this->colors + */ + public function hasColors(): bool + { + return $this->colors !== null; + } + + /** + * @throws Exception + */ + public function colors(): string + { + if (!$this->hasColors()) { + throw new Exception; + } + + return $this->colors; + } + + /** + * @psalm-assert-if-true !null $this->columns + */ + public function hasColumns(): bool + { + return $this->columns !== null; + } + + /** + * @throws Exception + */ + public function columns(): int|string + { + if (!$this->hasColumns()) { + throw new Exception; + } + + return $this->columns; + } + + /** + * @psalm-assert-if-true !null $this->configurationFile + */ + public function hasConfigurationFile(): bool + { + return $this->configurationFile !== null; + } + + /** + * @throws Exception + */ + public function configurationFile(): string + { + if (!$this->hasConfigurationFile()) { + throw new Exception; + } + + return $this->configurationFile; + } + + /** + * @psalm-assert-if-true !null $this->coverageFilter + */ + public function hasCoverageFilter(): bool + { + return $this->coverageFilter !== null; + } + + /** + * @throws Exception + */ + public function coverageFilter(): array + { + if (!$this->hasCoverageFilter()) { + throw new Exception; + } + + return $this->coverageFilter; + } + + /** + * @psalm-assert-if-true !null $this->coverageClover + */ + public function hasCoverageClover(): bool + { + return $this->coverageClover !== null; + } + + /** + * @throws Exception + */ + public function coverageClover(): string + { + if (!$this->hasCoverageClover()) { + throw new Exception; + } + + return $this->coverageClover; + } + + /** + * @psalm-assert-if-true !null $this->coverageCobertura + */ + public function hasCoverageCobertura(): bool + { + return $this->coverageCobertura !== null; + } + + /** + * @throws Exception + */ + public function coverageCobertura(): string + { + if (!$this->hasCoverageCobertura()) { + throw new Exception; + } + + return $this->coverageCobertura; + } + + /** + * @psalm-assert-if-true !null $this->coverageCrap4J + */ + public function hasCoverageCrap4J(): bool + { + return $this->coverageCrap4J !== null; + } + + /** + * @throws Exception + */ + public function coverageCrap4J(): string + { + if (!$this->hasCoverageCrap4J()) { + throw new Exception; + } + + return $this->coverageCrap4J; + } + + /** + * @psalm-assert-if-true !null $this->coverageHtml + */ + public function hasCoverageHtml(): bool + { + return $this->coverageHtml !== null; + } + + /** + * @throws Exception + */ + public function coverageHtml(): string + { + if (!$this->hasCoverageHtml()) { + throw new Exception; + } + + return $this->coverageHtml; + } + + /** + * @psalm-assert-if-true !null $this->coveragePhp + */ + public function hasCoveragePhp(): bool + { + return $this->coveragePhp !== null; + } + + /** + * @throws Exception + */ + public function coveragePhp(): string + { + if (!$this->hasCoveragePhp()) { + throw new Exception; + } + + return $this->coveragePhp; + } + + /** + * @psalm-assert-if-true !null $this->coverageText + */ + public function hasCoverageText(): bool + { + return $this->coverageText !== null; + } + + /** + * @throws Exception + */ + public function coverageText(): string + { + if (!$this->hasCoverageText()) { + throw new Exception; + } + + return $this->coverageText; + } + + /** + * @psalm-assert-if-true !null $this->coverageTextShowUncoveredFiles + */ + public function hasCoverageTextShowUncoveredFiles(): bool + { + return $this->coverageTextShowUncoveredFiles !== null; + } + + /** + * @throws Exception + */ + public function coverageTextShowUncoveredFiles(): bool + { + if (!$this->hasCoverageTextShowUncoveredFiles()) { + throw new Exception; + } + + return $this->coverageTextShowUncoveredFiles; + } + + /** + * @psalm-assert-if-true !null $this->coverageTextShowOnlySummary + */ + public function hasCoverageTextShowOnlySummary(): bool + { + return $this->coverageTextShowOnlySummary !== null; + } + + /** + * @throws Exception + */ + public function coverageTextShowOnlySummary(): bool + { + if (!$this->hasCoverageTextShowOnlySummary()) { + throw new Exception; + } + + return $this->coverageTextShowOnlySummary; + } + + /** + * @psalm-assert-if-true !null $this->coverageXml + */ + public function hasCoverageXml(): bool + { + return $this->coverageXml !== null; + } + + /** + * @throws Exception + */ + public function coverageXml(): string + { + if (!$this->hasCoverageXml()) { + throw new Exception; + } + + return $this->coverageXml; + } + + /** + * @psalm-assert-if-true !null $this->pathCoverage + */ + public function hasPathCoverage(): bool + { + return $this->pathCoverage !== null; + } + + /** + * @throws Exception + */ + public function pathCoverage(): bool + { + if (!$this->hasPathCoverage()) { + throw new Exception; + } + + return $this->pathCoverage; + } + + /** + * @psalm-assert-if-true !null $this->coverageCacheDirectory + * + * @deprecated + */ + public function hasCoverageCacheDirectory(): bool + { + return $this->coverageCacheDirectory !== null; + } + + /** + * @throws Exception + * + * @deprecated + */ + public function coverageCacheDirectory(): string + { + if (!$this->hasCoverageCacheDirectory()) { + throw new Exception; + } + + return $this->coverageCacheDirectory; + } + + public function warmCoverageCache(): bool + { + return $this->warmCoverageCache; + } + + /** + * @psalm-assert-if-true !null $this->defaultTimeLimit + */ + public function hasDefaultTimeLimit(): bool + { + return $this->defaultTimeLimit !== null; + } + + /** + * @throws Exception + */ + public function defaultTimeLimit(): int + { + if (!$this->hasDefaultTimeLimit()) { + throw new Exception; + } + + return $this->defaultTimeLimit; + } + + /** + * @psalm-assert-if-true !null $this->disableCodeCoverageIgnore + */ + public function hasDisableCodeCoverageIgnore(): bool + { + return $this->disableCodeCoverageIgnore !== null; + } + + /** + * @throws Exception + */ + public function disableCodeCoverageIgnore(): bool + { + if (!$this->hasDisableCodeCoverageIgnore()) { + throw new Exception; + } + + return $this->disableCodeCoverageIgnore; + } + + /** + * @psalm-assert-if-true !null $this->disallowTestOutput + */ + public function hasDisallowTestOutput(): bool + { + return $this->disallowTestOutput !== null; + } + + /** + * @throws Exception + */ + public function disallowTestOutput(): bool + { + if (!$this->hasDisallowTestOutput()) { + throw new Exception; + } + + return $this->disallowTestOutput; + } + + /** + * @psalm-assert-if-true !null $this->enforceTimeLimit + */ + public function hasEnforceTimeLimit(): bool + { + return $this->enforceTimeLimit !== null; + } + + /** + * @throws Exception + */ + public function enforceTimeLimit(): bool + { + if (!$this->hasEnforceTimeLimit()) { + throw new Exception; + } + + return $this->enforceTimeLimit; + } + + /** + * @psalm-assert-if-true !null $this->excludeGroups + */ + public function hasExcludeGroups(): bool + { + return $this->excludeGroups !== null; + } + + /** + * @throws Exception + */ + public function excludeGroups(): array + { + if (!$this->hasExcludeGroups()) { + throw new Exception; + } + + return $this->excludeGroups; + } + + /** + * @psalm-assert-if-true !null $this->executionOrder + */ + public function hasExecutionOrder(): bool + { + return $this->executionOrder !== null; + } + + /** + * @throws Exception + */ + public function executionOrder(): int + { + if (!$this->hasExecutionOrder()) { + throw new Exception; + } + + return $this->executionOrder; + } + + /** + * @psalm-assert-if-true !null $this->executionOrderDefects + */ + public function hasExecutionOrderDefects(): bool + { + return $this->executionOrderDefects !== null; + } + + /** + * @throws Exception + */ + public function executionOrderDefects(): int + { + if (!$this->hasExecutionOrderDefects()) { + throw new Exception; + } + + return $this->executionOrderDefects; + } + + /** + * @psalm-assert-if-true !null $this->failOnDeprecation + */ + public function hasFailOnDeprecation(): bool + { + return $this->failOnDeprecation !== null; + } + + /** + * @throws Exception + */ + public function failOnDeprecation(): bool + { + if (!$this->hasFailOnDeprecation()) { + throw new Exception; + } + + return $this->failOnDeprecation; + } + + /** + * @psalm-assert-if-true !null $this->failOnPhpunitDeprecation + */ + public function hasFailOnPhpunitDeprecation(): bool + { + return $this->failOnPhpunitDeprecation !== null; + } + + /** + * @throws Exception + */ + public function failOnPhpunitDeprecation(): bool + { + if (!$this->hasFailOnPhpunitDeprecation()) { + throw new Exception; + } + + return $this->failOnPhpunitDeprecation; + } + + /** + * @psalm-assert-if-true !null $this->failOnEmptyTestSuite + */ + public function hasFailOnEmptyTestSuite(): bool + { + return $this->failOnEmptyTestSuite !== null; + } + + /** + * @throws Exception + */ + public function failOnEmptyTestSuite(): bool + { + if (!$this->hasFailOnEmptyTestSuite()) { + throw new Exception; + } + + return $this->failOnEmptyTestSuite; + } + + /** + * @psalm-assert-if-true !null $this->failOnIncomplete + */ + public function hasFailOnIncomplete(): bool + { + return $this->failOnIncomplete !== null; + } + + /** + * @throws Exception + */ + public function failOnIncomplete(): bool + { + if (!$this->hasFailOnIncomplete()) { + throw new Exception; + } + + return $this->failOnIncomplete; + } + + /** + * @psalm-assert-if-true !null $this->failOnNotice + */ + public function hasFailOnNotice(): bool + { + return $this->failOnNotice !== null; + } + + /** + * @throws Exception + */ + public function failOnNotice(): bool + { + if (!$this->hasFailOnNotice()) { + throw new Exception; + } + + return $this->failOnNotice; + } + + /** + * @psalm-assert-if-true !null $this->failOnRisky + */ + public function hasFailOnRisky(): bool + { + return $this->failOnRisky !== null; + } + + /** + * @throws Exception + */ + public function failOnRisky(): bool + { + if (!$this->hasFailOnRisky()) { + throw new Exception; + } + + return $this->failOnRisky; + } + + /** + * @psalm-assert-if-true !null $this->failOnSkipped + */ + public function hasFailOnSkipped(): bool + { + return $this->failOnSkipped !== null; + } + + /** + * @throws Exception + */ + public function failOnSkipped(): bool + { + if (!$this->hasFailOnSkipped()) { + throw new Exception; + } + + return $this->failOnSkipped; + } + + /** + * @psalm-assert-if-true !null $this->failOnWarning + */ + public function hasFailOnWarning(): bool + { + return $this->failOnWarning !== null; + } + + /** + * @throws Exception + */ + public function failOnWarning(): bool + { + if (!$this->hasFailOnWarning()) { + throw new Exception; + } + + return $this->failOnWarning; + } + + /** + * @psalm-assert-if-true !null $this->stopOnDefect + */ + public function hasStopOnDefect(): bool + { + return $this->stopOnDefect !== null; + } + + /** + * @throws Exception + */ + public function stopOnDefect(): bool + { + if (!$this->hasStopOnDefect()) { + throw new Exception; + } + + return $this->stopOnDefect; + } + + /** + * @psalm-assert-if-true !null $this->stopOnDeprecation + */ + public function hasStopOnDeprecation(): bool + { + return $this->stopOnDeprecation !== null; + } + + /** + * @throws Exception + */ + public function stopOnDeprecation(): bool + { + if (!$this->hasStopOnDeprecation()) { + throw new Exception; + } + + return $this->stopOnDeprecation; + } + + /** + * @psalm-assert-if-true !null $this->stopOnError + */ + public function hasStopOnError(): bool + { + return $this->stopOnError !== null; + } + + /** + * @throws Exception + */ + public function stopOnError(): bool + { + if (!$this->hasStopOnError()) { + throw new Exception; + } + + return $this->stopOnError; + } + + /** + * @psalm-assert-if-true !null $this->stopOnFailure + */ + public function hasStopOnFailure(): bool + { + return $this->stopOnFailure !== null; + } + + /** + * @throws Exception + */ + public function stopOnFailure(): bool + { + if (!$this->hasStopOnFailure()) { + throw new Exception; + } + + return $this->stopOnFailure; + } + + /** + * @psalm-assert-if-true !null $this->stopOnIncomplete + */ + public function hasStopOnIncomplete(): bool + { + return $this->stopOnIncomplete !== null; + } + + /** + * @throws Exception + */ + public function stopOnIncomplete(): bool + { + if (!$this->hasStopOnIncomplete()) { + throw new Exception; + } + + return $this->stopOnIncomplete; + } + + /** + * @psalm-assert-if-true !null $this->stopOnNotice + */ + public function hasStopOnNotice(): bool + { + return $this->stopOnNotice !== null; + } + + /** + * @throws Exception + */ + public function stopOnNotice(): bool + { + if (!$this->hasStopOnNotice()) { + throw new Exception; + } + + return $this->stopOnNotice; + } + + /** + * @psalm-assert-if-true !null $this->stopOnRisky + */ + public function hasStopOnRisky(): bool + { + return $this->stopOnRisky !== null; + } + + /** + * @throws Exception + */ + public function stopOnRisky(): bool + { + if (!$this->hasStopOnRisky()) { + throw new Exception; + } + + return $this->stopOnRisky; + } + + /** + * @psalm-assert-if-true !null $this->stopOnSkipped + */ + public function hasStopOnSkipped(): bool + { + return $this->stopOnSkipped !== null; + } + + /** + * @throws Exception + */ + public function stopOnSkipped(): bool + { + if (!$this->hasStopOnSkipped()) { + throw new Exception; + } + + return $this->stopOnSkipped; + } + + /** + * @psalm-assert-if-true !null $this->stopOnWarning + */ + public function hasStopOnWarning(): bool + { + return $this->stopOnWarning !== null; + } + + /** + * @throws Exception + */ + public function stopOnWarning(): bool + { + if (!$this->hasStopOnWarning()) { + throw new Exception; + } + + return $this->stopOnWarning; + } + + /** + * @psalm-assert-if-true !null $this->filter + */ + public function hasFilter(): bool + { + return $this->filter !== null; + } + + /** + * @throws Exception + */ + public function filter(): string + { + if (!$this->hasFilter()) { + throw new Exception; + } + + return $this->filter; + } + + /** + * @psalm-assert-if-true !null $this->generateBaseline + */ + public function hasGenerateBaseline(): bool + { + return $this->generateBaseline !== null; + } + + /** + * @throws Exception + */ + public function generateBaseline(): string + { + if (!$this->hasGenerateBaseline()) { + throw new Exception; + } + + return $this->generateBaseline; + } + + /** + * @psalm-assert-if-true !null $this->useBaseline + */ + public function hasUseBaseline(): bool + { + return $this->useBaseline !== null; + } + + /** + * @throws Exception + */ + public function useBaseline(): string + { + if (!$this->hasUseBaseline()) { + throw new Exception; + } + + return $this->useBaseline; + } + + public function ignoreBaseline(): bool + { + return $this->ignoreBaseline; + } + + public function generateConfiguration(): bool + { + return $this->generateConfiguration; + } + + public function migrateConfiguration(): bool + { + return $this->migrateConfiguration; + } + + /** + * @psalm-assert-if-true !null $this->groups + */ + public function hasGroups(): bool + { + return $this->groups !== null; + } + + /** + * @throws Exception + */ + public function groups(): array + { + if (!$this->hasGroups()) { + throw new Exception; + } + + return $this->groups; + } + + /** + * @psalm-assert-if-true !null $this->testsCovering + */ + public function hasTestsCovering(): bool + { + return $this->testsCovering !== null; + } + + /** + * @throws Exception + */ + public function testsCovering(): array + { + if (!$this->hasTestsCovering()) { + throw new Exception; + } + + return $this->testsCovering; + } + + /** + * @psalm-assert-if-true !null $this->testsUsing + */ + public function hasTestsUsing(): bool + { + return $this->testsUsing !== null; + } + + /** + * @throws Exception + */ + public function testsUsing(): array + { + if (!$this->hasTestsUsing()) { + throw new Exception; + } + + return $this->testsUsing; + } + + public function help(): bool + { + return $this->help; + } + + /** + * @psalm-assert-if-true !null $this->includePath + */ + public function hasIncludePath(): bool + { + return $this->includePath !== null; + } + + /** + * @throws Exception + */ + public function includePath(): string + { + if (!$this->hasIncludePath()) { + throw new Exception; + } + + return $this->includePath; + } + + /** + * @psalm-assert-if-true !null $this->iniSettings + */ + public function hasIniSettings(): bool + { + return $this->iniSettings !== null; + } + + /** + * @throws Exception + */ + public function iniSettings(): array + { + if (!$this->hasIniSettings()) { + throw new Exception; + } + + return $this->iniSettings; + } + + /** + * @psalm-assert-if-true !null $this->junitLogfile + */ + public function hasJunitLogfile(): bool + { + return $this->junitLogfile !== null; + } + + /** + * @throws Exception + */ + public function junitLogfile(): string + { + if (!$this->hasJunitLogfile()) { + throw new Exception; + } + + return $this->junitLogfile; + } + + public function listGroups(): bool + { + return $this->listGroups; + } + + public function listSuites(): bool + { + return $this->listSuites; + } + + public function listTests(): bool + { + return $this->listTests; + } + + /** + * @psalm-assert-if-true !null $this->listTestsXml + */ + public function hasListTestsXml(): bool + { + return $this->listTestsXml !== null; + } + + /** + * @throws Exception + */ + public function listTestsXml(): string + { + if (!$this->hasListTestsXml()) { + throw new Exception; + } + + return $this->listTestsXml; + } + + /** + * @psalm-assert-if-true !null $this->noCoverage + */ + public function hasNoCoverage(): bool + { + return $this->noCoverage !== null; + } + + /** + * @throws Exception + */ + public function noCoverage(): bool + { + if (!$this->hasNoCoverage()) { + throw new Exception; + } + + return $this->noCoverage; + } + + /** + * @psalm-assert-if-true !null $this->noExtensions + */ + public function hasNoExtensions(): bool + { + return $this->noExtensions !== null; + } + + /** + * @throws Exception + */ + public function noExtensions(): bool + { + if (!$this->hasNoExtensions()) { + throw new Exception; + } + + return $this->noExtensions; + } + + /** + * @psalm-assert-if-true !null $this->noOutput + */ + public function hasNoOutput(): bool + { + return $this->noOutput !== null; + } + + /** + * @throws Exception + */ + public function noOutput(): bool + { + if ($this->noOutput === null) { + throw new Exception; + } + + return $this->noOutput; + } + + /** + * @psalm-assert-if-true !null $this->noProgress + */ + public function hasNoProgress(): bool + { + return $this->noProgress !== null; + } + + /** + * @throws Exception + */ + public function noProgress(): bool + { + if ($this->noProgress === null) { + throw new Exception; + } + + return $this->noProgress; + } + + /** + * @psalm-assert-if-true !null $this->noResults + */ + public function hasNoResults(): bool + { + return $this->noResults !== null; + } + + /** + * @throws Exception + */ + public function noResults(): bool + { + if ($this->noResults === null) { + throw new Exception; + } + + return $this->noResults; + } + + /** + * @psalm-assert-if-true !null $this->noLogging + */ + public function hasNoLogging(): bool + { + return $this->noLogging !== null; + } + + /** + * @throws Exception + */ + public function noLogging(): bool + { + if (!$this->hasNoLogging()) { + throw new Exception; + } + + return $this->noLogging; + } + + /** + * @psalm-assert-if-true !null $this->processIsolation + */ + public function hasProcessIsolation(): bool + { + return $this->processIsolation !== null; + } + + /** + * @throws Exception + */ + public function processIsolation(): bool + { + if (!$this->hasProcessIsolation()) { + throw new Exception; + } + + return $this->processIsolation; + } + + /** + * @psalm-assert-if-true !null $this->randomOrderSeed + */ + public function hasRandomOrderSeed(): bool + { + return $this->randomOrderSeed !== null; + } + + /** + * @throws Exception + */ + public function randomOrderSeed(): int + { + if (!$this->hasRandomOrderSeed()) { + throw new Exception; + } + + return $this->randomOrderSeed; + } + + /** + * @psalm-assert-if-true !null $this->reportUselessTests + */ + public function hasReportUselessTests(): bool + { + return $this->reportUselessTests !== null; + } + + /** + * @throws Exception + */ + public function reportUselessTests(): bool + { + if (!$this->hasReportUselessTests()) { + throw new Exception; + } + + return $this->reportUselessTests; + } + + /** + * @psalm-assert-if-true !null $this->resolveDependencies + */ + public function hasResolveDependencies(): bool + { + return $this->resolveDependencies !== null; + } + + /** + * @throws Exception + */ + public function resolveDependencies(): bool + { + if (!$this->hasResolveDependencies()) { + throw new Exception; + } + + return $this->resolveDependencies; + } + + /** + * @psalm-assert-if-true !null $this->reverseList + */ + public function hasReverseList(): bool + { + return $this->reverseList !== null; + } + + /** + * @throws Exception + */ + public function reverseList(): bool + { + if (!$this->hasReverseList()) { + throw new Exception; + } + + return $this->reverseList; + } + + /** + * @psalm-assert-if-true !null $this->stderr + */ + public function hasStderr(): bool + { + return $this->stderr !== null; + } + + /** + * @throws Exception + */ + public function stderr(): bool + { + if (!$this->hasStderr()) { + throw new Exception; + } + + return $this->stderr; + } + + /** + * @psalm-assert-if-true !null $this->strictCoverage + */ + public function hasStrictCoverage(): bool + { + return $this->strictCoverage !== null; + } + + /** + * @throws Exception + */ + public function strictCoverage(): bool + { + if (!$this->hasStrictCoverage()) { + throw new Exception; + } + + return $this->strictCoverage; + } + + /** + * @psalm-assert-if-true !null $this->teamcityLogfile + */ + public function hasTeamcityLogfile(): bool + { + return $this->teamcityLogfile !== null; + } + + /** + * @throws Exception + */ + public function teamcityLogfile(): string + { + if (!$this->hasTeamcityLogfile()) { + throw new Exception; + } + + return $this->teamcityLogfile; + } + + /** + * @psalm-assert-if-true !null $this->teamcityPrinter + */ + public function hasTeamCityPrinter(): bool + { + return $this->teamCityPrinter !== null; + } + + /** + * @throws Exception + */ + public function teamCityPrinter(): bool + { + if (!$this->hasTeamCityPrinter()) { + throw new Exception; + } + + return $this->teamCityPrinter; + } + + /** + * @psalm-assert-if-true !null $this->testdoxHtmlFile + */ + public function hasTestdoxHtmlFile(): bool + { + return $this->testdoxHtmlFile !== null; + } + + /** + * @throws Exception + */ + public function testdoxHtmlFile(): string + { + if (!$this->hasTestdoxHtmlFile()) { + throw new Exception; + } + + return $this->testdoxHtmlFile; + } + + /** + * @psalm-assert-if-true !null $this->testdoxTextFile + */ + public function hasTestdoxTextFile(): bool + { + return $this->testdoxTextFile !== null; + } + + /** + * @throws Exception + */ + public function testdoxTextFile(): string + { + if (!$this->hasTestdoxTextFile()) { + throw new Exception; + } + + return $this->testdoxTextFile; + } + + /** + * @psalm-assert-if-true !null $this->testdoxPrinter + */ + public function hasTestDoxPrinter(): bool + { + return $this->testdoxPrinter !== null; + } + + /** + * @throws Exception + */ + public function testdoxPrinter(): bool + { + if (!$this->hasTestdoxPrinter()) { + throw new Exception; + } + + return $this->testdoxPrinter; + } + + /** + * @psalm-assert-if-true !null $this->testSuffixes + */ + public function hasTestSuffixes(): bool + { + return $this->testSuffixes !== null; + } + + /** + * @psalm-return non-empty-list + * + * @throws Exception + */ + public function testSuffixes(): array + { + if (!$this->hasTestSuffixes()) { + throw new Exception; + } + + return $this->testSuffixes; + } + + /** + * @psalm-assert-if-true !null $this->testSuite + */ + public function hasTestSuite(): bool + { + return $this->testSuite !== null; + } + + /** + * @throws Exception + */ + public function testSuite(): string + { + if (!$this->hasTestSuite()) { + throw new Exception; + } + + return $this->testSuite; + } + + /** + * @psalm-assert-if-true !null $this->excludedTestSuite + */ + public function hasExcludedTestSuite(): bool + { + return $this->excludeTestSuite !== null; + } + + /** + * @throws Exception + */ + public function excludedTestSuite(): string + { + if (!$this->hasExcludedTestSuite()) { + throw new Exception; + } + + return $this->excludeTestSuite; + } + + public function useDefaultConfiguration(): bool + { + return $this->useDefaultConfiguration; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnIncompleteTests + */ + public function hasDisplayDetailsOnIncompleteTests(): bool + { + return $this->displayDetailsOnIncompleteTests !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnIncompleteTests(): bool + { + if (!$this->hasDisplayDetailsOnIncompleteTests()) { + throw new Exception; + } + + return $this->displayDetailsOnIncompleteTests; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnSkippedTests + */ + public function hasDisplayDetailsOnSkippedTests(): bool + { + return $this->displayDetailsOnSkippedTests !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnSkippedTests(): bool + { + if (!$this->hasDisplayDetailsOnSkippedTests()) { + throw new Exception; + } + + return $this->displayDetailsOnSkippedTests; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnTestsThatTriggerDeprecations + */ + public function hasDisplayDetailsOnTestsThatTriggerDeprecations(): bool + { + return $this->displayDetailsOnTestsThatTriggerDeprecations !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnTestsThatTriggerDeprecations(): bool + { + if (!$this->hasDisplayDetailsOnTestsThatTriggerDeprecations()) { + throw new Exception; + } + + return $this->displayDetailsOnTestsThatTriggerDeprecations; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnPhpunitDeprecations + */ + public function hasDisplayDetailsOnPhpunitDeprecations(): bool + { + return $this->displayDetailsOnPhpunitDeprecations !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnPhpunitDeprecations(): bool + { + if (!$this->hasDisplayDetailsOnPhpunitDeprecations()) { + throw new Exception; + } + + return $this->displayDetailsOnPhpunitDeprecations; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnTestsThatTriggerErrors + */ + public function hasDisplayDetailsOnTestsThatTriggerErrors(): bool + { + return $this->displayDetailsOnTestsThatTriggerErrors !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnTestsThatTriggerErrors(): bool + { + if (!$this->hasDisplayDetailsOnTestsThatTriggerErrors()) { + throw new Exception; + } + + return $this->displayDetailsOnTestsThatTriggerErrors; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnTestsThatTriggerNotices + */ + public function hasDisplayDetailsOnTestsThatTriggerNotices(): bool + { + return $this->displayDetailsOnTestsThatTriggerNotices !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnTestsThatTriggerNotices(): bool + { + if (!$this->hasDisplayDetailsOnTestsThatTriggerNotices()) { + throw new Exception; + } + + return $this->displayDetailsOnTestsThatTriggerNotices; + } + + /** + * @psalm-assert-if-true !null $this->displayDetailsOnTestsThatTriggerWarnings + */ + public function hasDisplayDetailsOnTestsThatTriggerWarnings(): bool + { + return $this->displayDetailsOnTestsThatTriggerWarnings !== null; + } + + /** + * @throws Exception + */ + public function displayDetailsOnTestsThatTriggerWarnings(): bool + { + if (!$this->hasDisplayDetailsOnTestsThatTriggerWarnings()) { + throw new Exception; + } + + return $this->displayDetailsOnTestsThatTriggerWarnings; + } + + public function version(): bool + { + return $this->version; + } + + /** + * @psalm-assert-if-true !null $this->logEventsText + */ + public function hasLogEventsText(): bool + { + return $this->logEventsText !== null; + } + + /** + * @throws Exception + */ + public function logEventsText(): string + { + if (!$this->hasLogEventsText()) { + throw new Exception; + } + + return $this->logEventsText; + } + + /** + * @psalm-assert-if-true !null $this->logEventsVerboseText + */ + public function hasLogEventsVerboseText(): bool + { + return $this->logEventsVerboseText !== null; + } + + /** + * @throws Exception + */ + public function logEventsVerboseText(): string + { + if (!$this->hasLogEventsVerboseText()) { + throw new Exception; + } + + return $this->logEventsVerboseText; + } + + public function debug(): bool + { + return $this->debug; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php new file mode 100644 index 000000000..0d9a5a00e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php new file mode 100644 index 000000000..03ac43a07 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\CliArguments; + +use function getcwd; +use function is_dir; +use function is_file; +use function realpath; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class XmlConfigurationFileFinder +{ + public function find(Configuration $configuration): false|string + { + $useDefaultConfiguration = $configuration->useDefaultConfiguration(); + + if ($configuration->hasConfigurationFile()) { + if (is_dir($configuration->configurationFile())) { + $candidate = $this->configurationFileInDirectory($configuration->configurationFile()); + + if ($candidate !== false) { + return $candidate; + } + + return false; + } + + return $configuration->configurationFile(); + } + + if ($useDefaultConfiguration) { + $candidate = $this->configurationFileInDirectory(getcwd()); + + if ($candidate !== false) { + return $candidate; + } + } + + return false; + } + + private function configurationFileInDirectory(string $directory): false|string + { + $candidates = [ + $directory . '/phpunit.xml', + $directory . '/phpunit.dist.xml', + $directory . '/phpunit.xml.dist', + ]; + + foreach ($candidates as $candidate) { + if (is_file($candidate)) { + return realpath($candidate); + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php new file mode 100644 index 000000000..7051d2840 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function array_keys; +use function assert; +use SebastianBergmann\CodeCoverage\Filter; + +/** + * CLI options and XML configuration are static within a single PHPUnit process. + * It is therefore okay to use a Singleton registry here. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CodeCoverageFilterRegistry +{ + private static ?self $instance = null; + private ?Filter $filter = null; + private bool $configured = false; + + public static function instance(): self + { + if (self::$instance === null) { + self::$instance = new self; + } + + return self::$instance; + } + + /** + * @codeCoverageIgnore + */ + public function get(): Filter + { + assert($this->filter !== null); + + return $this->filter; + } + + /** + * @codeCoverageIgnore + */ + public function init(Configuration $configuration, bool $force = false): void + { + if (!$configuration->hasCoverageReport() && !$force) { + return; + } + + if ($this->configured && !$force) { + return; + } + + $this->filter = new Filter; + + if ($configuration->source()->notEmpty()) { + $this->filter->includeFiles(array_keys((new SourceMapper)->map($configuration->source()))); + + $this->configured = true; + } + } + + /** + * @codeCoverageIgnore + */ + public function configured(): bool + { + return $this->configured; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Configuration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Configuration.php new file mode 100644 index 000000000..466c311a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Configuration.php @@ -0,0 +1,1309 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @psalm-immutable + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class Configuration +{ + public const COLOR_NEVER = 'never'; + public const COLOR_AUTO = 'auto'; + public const COLOR_ALWAYS = 'always'; + public const COLOR_DEFAULT = self::COLOR_NEVER; + + /** + * @psalm-var list + */ + private readonly array $cliArguments; + private readonly ?string $configurationFile; + private readonly ?string $bootstrap; + private readonly bool $cacheResult; + private readonly ?string $cacheDirectory; + private readonly ?string $coverageCacheDirectory; + private readonly Source $source; + private readonly bool $pathCoverage; + private readonly ?string $coverageClover; + private readonly ?string $coverageCobertura; + private readonly ?string $coverageCrap4j; + private readonly int $coverageCrap4jThreshold; + private readonly ?string $coverageHtml; + private readonly int $coverageHtmlLowUpperBound; + private readonly int $coverageHtmlHighLowerBound; + private readonly string $coverageHtmlColorSuccessLow; + private readonly string $coverageHtmlColorSuccessMedium; + private readonly string $coverageHtmlColorSuccessHigh; + private readonly string $coverageHtmlColorWarning; + private readonly string $coverageHtmlColorDanger; + private readonly ?string $coverageHtmlCustomCssFile; + private readonly ?string $coveragePhp; + private readonly ?string $coverageText; + private readonly bool $coverageTextShowUncoveredFiles; + private readonly bool $coverageTextShowOnlySummary; + private readonly ?string $coverageXml; + private readonly string $testResultCacheFile; + private readonly bool $ignoreDeprecatedCodeUnitsFromCodeCoverage; + private readonly bool $disableCodeCoverageIgnore; + private readonly bool $failOnDeprecation; + private readonly bool $failOnPhpunitDeprecation; + private readonly bool $failOnEmptyTestSuite; + private readonly bool $failOnIncomplete; + private readonly bool $failOnNotice; + private readonly bool $failOnRisky; + private readonly bool $failOnSkipped; + private readonly bool $failOnWarning; + private readonly bool $stopOnDefect; + private readonly bool $stopOnDeprecation; + private readonly bool $stopOnError; + private readonly bool $stopOnFailure; + private readonly bool $stopOnIncomplete; + private readonly bool $stopOnNotice; + private readonly bool $stopOnRisky; + private readonly bool $stopOnSkipped; + private readonly bool $stopOnWarning; + private readonly bool $outputToStandardErrorStream; + private readonly int $columns; + private readonly bool $noExtensions; + + /** + * @psalm-var ?non-empty-string + */ + private readonly ?string $pharExtensionDirectory; + + /** + * @psalm-var list}> + */ + private readonly array $extensionBootstrappers; + private readonly bool $backupGlobals; + private readonly bool $backupStaticProperties; + private readonly bool $beStrictAboutChangesToGlobalState; + private readonly bool $colors; + private readonly bool $processIsolation; + private readonly bool $enforceTimeLimit; + private readonly int $defaultTimeLimit; + private readonly int $timeoutForSmallTests; + private readonly int $timeoutForMediumTests; + private readonly int $timeoutForLargeTests; + private readonly bool $reportUselessTests; + private readonly bool $strictCoverage; + private readonly bool $disallowTestOutput; + private readonly bool $displayDetailsOnIncompleteTests; + private readonly bool $displayDetailsOnSkippedTests; + private readonly bool $displayDetailsOnTestsThatTriggerDeprecations; + private readonly bool $displayDetailsOnPhpunitDeprecations; + private readonly bool $displayDetailsOnTestsThatTriggerErrors; + private readonly bool $displayDetailsOnTestsThatTriggerNotices; + private readonly bool $displayDetailsOnTestsThatTriggerWarnings; + private readonly bool $reverseDefectList; + private readonly bool $requireCoverageMetadata; + private readonly bool $registerMockObjectsFromTestArgumentsRecursively; + private readonly bool $noProgress; + private readonly bool $noResults; + private readonly bool $noOutput; + private readonly int $executionOrder; + private readonly int $executionOrderDefects; + private readonly bool $resolveDependencies; + private readonly ?string $logfileTeamcity; + private readonly ?string $logfileJunit; + private readonly ?string $logfileTestdoxHtml; + private readonly ?string $logfileTestdoxText; + private readonly ?string $logEventsText; + private readonly ?string $logEventsVerboseText; + private readonly ?array $testsCovering; + private readonly ?array $testsUsing; + private readonly bool $teamCityOutput; + private readonly bool $testDoxOutput; + private readonly ?string $filter; + private readonly ?array $groups; + private readonly ?array $excludeGroups; + private readonly int $randomOrderSeed; + private readonly bool $includeUncoveredFiles; + private readonly TestSuiteCollection $testSuite; + private readonly string $includeTestSuite; + private readonly string $excludeTestSuite; + private readonly ?string $defaultTestSuite; + + /** + * @psalm-var non-empty-list + */ + private readonly array $testSuffixes; + private readonly Php $php; + private readonly bool $controlGarbageCollector; + private readonly int $numberOfTestsBeforeGarbageCollection; + private readonly ?string $generateBaseline; + private readonly bool $debug; + + /** + * @psalm-param list $cliArguments + * @psalm-param ?non-empty-string $pharExtensionDirectory + * @psalm-param non-empty-list $testSuffixes + * @psalm-param list}> $extensionBootstrappers + */ + public function __construct(array $cliArguments, ?string $configurationFile, ?string $bootstrap, bool $cacheResult, ?string $cacheDirectory, ?string $coverageCacheDirectory, Source $source, string $testResultCacheFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4j, int $coverageCrap4jThreshold, ?string $coverageHtml, int $coverageHtmlLowUpperBound, int $coverageHtmlHighLowerBound, string $coverageHtmlColorSuccessLow, string $coverageHtmlColorSuccessMedium, string $coverageHtmlColorSuccessHigh, string $coverageHtmlColorWarning, string $coverageHtmlColorDanger, ?string $coverageHtmlCustomCssFile, ?string $coveragePhp, ?string $coverageText, bool $coverageTextShowUncoveredFiles, bool $coverageTextShowOnlySummary, ?string $coverageXml, bool $pathCoverage, bool $ignoreDeprecatedCodeUnitsFromCodeCoverage, bool $disableCodeCoverageIgnore, bool $failOnDeprecation, bool $failOnPhpunitDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnDeprecation, bool $stopOnError, bool $stopOnFailure, bool $stopOnIncomplete, bool $stopOnNotice, bool $stopOnRisky, bool $stopOnSkipped, bool $stopOnWarning, bool $outputToStandardErrorStream, int|string $columns, bool $noExtensions, ?string $pharExtensionDirectory, array $extensionBootstrappers, bool $backupGlobals, bool $backupStaticProperties, bool $beStrictAboutChangesToGlobalState, bool $colors, bool $processIsolation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, bool $reportUselessTests, bool $strictCoverage, bool $disallowTestOutput, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnPhpunitDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $reverseDefectList, bool $requireCoverageMetadata, bool $registerMockObjectsFromTestArgumentsRecursively, bool $noProgress, bool $noResults, bool $noOutput, int $executionOrder, int $executionOrderDefects, bool $resolveDependencies, ?string $logfileTeamcity, ?string $logfileJunit, ?string $logfileTestdoxHtml, ?string $logfileTestdoxText, ?string $logEventsText, ?string $logEventsVerboseText, bool $teamCityOutput, bool $testDoxOutput, ?array $testsCovering, ?array $testsUsing, ?string $filter, ?array $groups, ?array $excludeGroups, int $randomOrderSeed, bool $includeUncoveredFiles, TestSuiteCollection $testSuite, string $includeTestSuite, string $excludeTestSuite, ?string $defaultTestSuite, array $testSuffixes, Php $php, bool $controlGarbageCollector, int $numberOfTestsBeforeGarbageCollection, ?string $generateBaseline, bool $debug) + { + $this->cliArguments = $cliArguments; + $this->configurationFile = $configurationFile; + $this->bootstrap = $bootstrap; + $this->cacheResult = $cacheResult; + $this->cacheDirectory = $cacheDirectory; + $this->coverageCacheDirectory = $coverageCacheDirectory; + $this->source = $source; + $this->testResultCacheFile = $testResultCacheFile; + $this->coverageClover = $coverageClover; + $this->coverageCobertura = $coverageCobertura; + $this->coverageCrap4j = $coverageCrap4j; + $this->coverageCrap4jThreshold = $coverageCrap4jThreshold; + $this->coverageHtml = $coverageHtml; + $this->coverageHtmlLowUpperBound = $coverageHtmlLowUpperBound; + $this->coverageHtmlHighLowerBound = $coverageHtmlHighLowerBound; + $this->coverageHtmlColorSuccessLow = $coverageHtmlColorSuccessLow; + $this->coverageHtmlColorSuccessMedium = $coverageHtmlColorSuccessMedium; + $this->coverageHtmlColorSuccessHigh = $coverageHtmlColorSuccessHigh; + $this->coverageHtmlColorWarning = $coverageHtmlColorWarning; + $this->coverageHtmlColorDanger = $coverageHtmlColorDanger; + $this->coverageHtmlCustomCssFile = $coverageHtmlCustomCssFile; + $this->coveragePhp = $coveragePhp; + $this->coverageText = $coverageText; + $this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles; + $this->coverageTextShowOnlySummary = $coverageTextShowOnlySummary; + $this->coverageXml = $coverageXml; + $this->pathCoverage = $pathCoverage; + $this->ignoreDeprecatedCodeUnitsFromCodeCoverage = $ignoreDeprecatedCodeUnitsFromCodeCoverage; + $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; + $this->failOnDeprecation = $failOnDeprecation; + $this->failOnPhpunitDeprecation = $failOnPhpunitDeprecation; + $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; + $this->failOnIncomplete = $failOnIncomplete; + $this->failOnNotice = $failOnNotice; + $this->failOnRisky = $failOnRisky; + $this->failOnSkipped = $failOnSkipped; + $this->failOnWarning = $failOnWarning; + $this->stopOnDefect = $stopOnDefect; + $this->stopOnDeprecation = $stopOnDeprecation; + $this->stopOnError = $stopOnError; + $this->stopOnFailure = $stopOnFailure; + $this->stopOnIncomplete = $stopOnIncomplete; + $this->stopOnNotice = $stopOnNotice; + $this->stopOnRisky = $stopOnRisky; + $this->stopOnSkipped = $stopOnSkipped; + $this->stopOnWarning = $stopOnWarning; + $this->outputToStandardErrorStream = $outputToStandardErrorStream; + $this->columns = $columns; + $this->noExtensions = $noExtensions; + $this->pharExtensionDirectory = $pharExtensionDirectory; + $this->extensionBootstrappers = $extensionBootstrappers; + $this->backupGlobals = $backupGlobals; + $this->backupStaticProperties = $backupStaticProperties; + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + $this->colors = $colors; + $this->processIsolation = $processIsolation; + $this->enforceTimeLimit = $enforceTimeLimit; + $this->defaultTimeLimit = $defaultTimeLimit; + $this->timeoutForSmallTests = $timeoutForSmallTests; + $this->timeoutForMediumTests = $timeoutForMediumTests; + $this->timeoutForLargeTests = $timeoutForLargeTests; + $this->reportUselessTests = $reportUselessTests; + $this->strictCoverage = $strictCoverage; + $this->disallowTestOutput = $disallowTestOutput; + $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; + $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; + $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; + $this->displayDetailsOnPhpunitDeprecations = $displayDetailsOnPhpunitDeprecations; + $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; + $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; + $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; + $this->reverseDefectList = $reverseDefectList; + $this->requireCoverageMetadata = $requireCoverageMetadata; + $this->registerMockObjectsFromTestArgumentsRecursively = $registerMockObjectsFromTestArgumentsRecursively; + $this->noProgress = $noProgress; + $this->noResults = $noResults; + $this->noOutput = $noOutput; + $this->executionOrder = $executionOrder; + $this->executionOrderDefects = $executionOrderDefects; + $this->resolveDependencies = $resolveDependencies; + $this->logfileTeamcity = $logfileTeamcity; + $this->logfileJunit = $logfileJunit; + $this->logfileTestdoxHtml = $logfileTestdoxHtml; + $this->logfileTestdoxText = $logfileTestdoxText; + $this->logEventsText = $logEventsText; + $this->logEventsVerboseText = $logEventsVerboseText; + $this->teamCityOutput = $teamCityOutput; + $this->testDoxOutput = $testDoxOutput; + $this->testsCovering = $testsCovering; + $this->testsUsing = $testsUsing; + $this->filter = $filter; + $this->groups = $groups; + $this->excludeGroups = $excludeGroups; + $this->randomOrderSeed = $randomOrderSeed; + $this->includeUncoveredFiles = $includeUncoveredFiles; + $this->testSuite = $testSuite; + $this->includeTestSuite = $includeTestSuite; + $this->excludeTestSuite = $excludeTestSuite; + $this->defaultTestSuite = $defaultTestSuite; + $this->testSuffixes = $testSuffixes; + $this->php = $php; + $this->controlGarbageCollector = $controlGarbageCollector; + $this->numberOfTestsBeforeGarbageCollection = $numberOfTestsBeforeGarbageCollection; + $this->generateBaseline = $generateBaseline; + $this->debug = $debug; + } + + /** + * @psalm-assert-if-true !empty $this->cliArguments + */ + public function hasCliArguments(): bool + { + return !empty($this->cliArguments); + } + + /** + * @psalm-return list + */ + public function cliArguments(): array + { + return $this->cliArguments; + } + + /** + * @psalm-assert-if-true !empty $this->cliArguments + * + * @deprecated Use hasCliArguments() instead + */ + public function hasCliArgument(): bool + { + return !empty($this->cliArguments); + } + + /** + * @throws NoCliArgumentException + * + * @return non-empty-string + * + * @deprecated Use cliArguments()[0] instead + */ + public function cliArgument(): string + { + if (!$this->hasCliArguments()) { + throw new NoCliArgumentException; + } + + return $this->cliArguments[0]; + } + + /** + * @psalm-assert-if-true !null $this->configurationFile + */ + public function hasConfigurationFile(): bool + { + return $this->configurationFile !== null; + } + + /** + * @throws NoConfigurationFileException + */ + public function configurationFile(): string + { + if (!$this->hasConfigurationFile()) { + throw new NoConfigurationFileException; + } + + return $this->configurationFile; + } + + /** + * @psalm-assert-if-true !null $this->bootstrap + */ + public function hasBootstrap(): bool + { + return $this->bootstrap !== null; + } + + /** + * @throws NoBootstrapException + */ + public function bootstrap(): string + { + if (!$this->hasBootstrap()) { + throw new NoBootstrapException; + } + + return $this->bootstrap; + } + + public function cacheResult(): bool + { + return $this->cacheResult; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + */ + public function hasCacheDirectory(): bool + { + return $this->cacheDirectory !== null; + } + + /** + * @throws NoCacheDirectoryException + */ + public function cacheDirectory(): string + { + if (!$this->hasCacheDirectory()) { + throw new NoCacheDirectoryException; + } + + return $this->cacheDirectory; + } + + /** + * @psalm-assert-if-true !null $this->coverageCacheDirectory + */ + public function hasCoverageCacheDirectory(): bool + { + return $this->coverageCacheDirectory !== null; + } + + /** + * @throws NoCoverageCacheDirectoryException + */ + public function coverageCacheDirectory(): string + { + if (!$this->hasCoverageCacheDirectory()) { + throw new NoCoverageCacheDirectoryException; + } + + return $this->coverageCacheDirectory; + } + + public function source(): Source + { + return $this->source; + } + + /** + * @deprecated Use source()->restrictDeprecations() instead + */ + public function restrictDeprecations(): bool + { + return $this->source()->restrictDeprecations(); + } + + /** + * @deprecated Use source()->restrictNotices() instead + */ + public function restrictNotices(): bool + { + return $this->source()->restrictNotices(); + } + + /** + * @deprecated Use source()->restrictWarnings() instead + */ + public function restrictWarnings(): bool + { + return $this->source()->restrictWarnings(); + } + + /** + * @deprecated Use source()->notEmpty() instead + */ + public function hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport(): bool + { + return $this->source->notEmpty(); + } + + /** + * @deprecated Use source()->includeDirectories() instead + */ + public function coverageIncludeDirectories(): FilterDirectoryCollection + { + return $this->source()->includeDirectories(); + } + + /** + * @deprecated Use source()->includeFiles() instead + */ + public function coverageIncludeFiles(): FileCollection + { + return $this->source()->includeFiles(); + } + + /** + * @deprecated Use source()->excludeDirectories() instead + */ + public function coverageExcludeDirectories(): FilterDirectoryCollection + { + return $this->source()->excludeDirectories(); + } + + /** + * @deprecated Use source()->excludeFiles() instead + */ + public function coverageExcludeFiles(): FileCollection + { + return $this->source()->excludeFiles(); + } + + public function testResultCacheFile(): string + { + return $this->testResultCacheFile; + } + + public function ignoreDeprecatedCodeUnitsFromCodeCoverage(): bool + { + return $this->ignoreDeprecatedCodeUnitsFromCodeCoverage; + } + + public function disableCodeCoverageIgnore(): bool + { + return $this->disableCodeCoverageIgnore; + } + + public function pathCoverage(): bool + { + return $this->pathCoverage; + } + + public function hasCoverageReport(): bool + { + return $this->hasCoverageClover() || + $this->hasCoverageCobertura() || + $this->hasCoverageCrap4j() || + $this->hasCoverageHtml() || + $this->hasCoveragePhp() || + $this->hasCoverageText() || + $this->hasCoverageXml(); + } + + /** + * @psalm-assert-if-true !null $this->coverageClover + */ + public function hasCoverageClover(): bool + { + return $this->coverageClover !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coverageClover(): string + { + if (!$this->hasCoverageClover()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coverageClover; + } + + /** + * @psalm-assert-if-true !null $this->coverageCobertura + */ + public function hasCoverageCobertura(): bool + { + return $this->coverageCobertura !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coverageCobertura(): string + { + if (!$this->hasCoverageCobertura()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coverageCobertura; + } + + /** + * @psalm-assert-if-true !null $this->coverageCrap4j + */ + public function hasCoverageCrap4j(): bool + { + return $this->coverageCrap4j !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coverageCrap4j(): string + { + if (!$this->hasCoverageCrap4j()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coverageCrap4j; + } + + public function coverageCrap4jThreshold(): int + { + return $this->coverageCrap4jThreshold; + } + + /** + * @psalm-assert-if-true !null $this->coverageHtml + */ + public function hasCoverageHtml(): bool + { + return $this->coverageHtml !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coverageHtml(): string + { + if (!$this->hasCoverageHtml()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coverageHtml; + } + + public function coverageHtmlLowUpperBound(): int + { + return $this->coverageHtmlLowUpperBound; + } + + public function coverageHtmlHighLowerBound(): int + { + return $this->coverageHtmlHighLowerBound; + } + + public function coverageHtmlColorSuccessLow(): string + { + return $this->coverageHtmlColorSuccessLow; + } + + public function coverageHtmlColorSuccessMedium(): string + { + return $this->coverageHtmlColorSuccessMedium; + } + + public function coverageHtmlColorSuccessHigh(): string + { + return $this->coverageHtmlColorSuccessHigh; + } + + public function coverageHtmlColorWarning(): string + { + return $this->coverageHtmlColorWarning; + } + + public function coverageHtmlColorDanger(): string + { + return $this->coverageHtmlColorDanger; + } + + /** + * @psalm-assert-if-true !null $this->coverageHtmlCustomCssFile + */ + public function hasCoverageHtmlCustomCssFile(): bool + { + return $this->coverageHtmlCustomCssFile !== null; + } + + /** + * @throws NoCustomCssFileException + */ + public function coverageHtmlCustomCssFile(): string + { + if (!$this->hasCoverageHtmlCustomCssFile()) { + throw new NoCustomCssFileException; + } + + return $this->coverageHtmlCustomCssFile; + } + + /** + * @psalm-assert-if-true !null $this->coveragePhp + */ + public function hasCoveragePhp(): bool + { + return $this->coveragePhp !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coveragePhp(): string + { + if (!$this->hasCoveragePhp()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coveragePhp; + } + + /** + * @psalm-assert-if-true !null $this->coverageText + */ + public function hasCoverageText(): bool + { + return $this->coverageText !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coverageText(): string + { + if (!$this->hasCoverageText()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coverageText; + } + + public function coverageTextShowUncoveredFiles(): bool + { + return $this->coverageTextShowUncoveredFiles; + } + + public function coverageTextShowOnlySummary(): bool + { + return $this->coverageTextShowOnlySummary; + } + + /** + * @psalm-assert-if-true !null $this->coverageXml + */ + public function hasCoverageXml(): bool + { + return $this->coverageXml !== null; + } + + /** + * @throws CodeCoverageReportNotConfiguredException + */ + public function coverageXml(): string + { + if (!$this->hasCoverageXml()) { + throw new CodeCoverageReportNotConfiguredException; + } + + return $this->coverageXml; + } + + public function failOnDeprecation(): bool + { + return $this->failOnDeprecation; + } + + public function failOnPhpunitDeprecation(): bool + { + return $this->failOnPhpunitDeprecation; + } + + public function failOnEmptyTestSuite(): bool + { + return $this->failOnEmptyTestSuite; + } + + public function failOnIncomplete(): bool + { + return $this->failOnIncomplete; + } + + public function failOnNotice(): bool + { + return $this->failOnNotice; + } + + public function failOnRisky(): bool + { + return $this->failOnRisky; + } + + public function failOnSkipped(): bool + { + return $this->failOnSkipped; + } + + public function failOnWarning(): bool + { + return $this->failOnWarning; + } + + public function stopOnDefect(): bool + { + return $this->stopOnDefect; + } + + public function stopOnDeprecation(): bool + { + return $this->stopOnDeprecation; + } + + public function stopOnError(): bool + { + return $this->stopOnError; + } + + public function stopOnFailure(): bool + { + return $this->stopOnFailure; + } + + public function stopOnIncomplete(): bool + { + return $this->stopOnIncomplete; + } + + public function stopOnNotice(): bool + { + return $this->stopOnNotice; + } + + public function stopOnRisky(): bool + { + return $this->stopOnRisky; + } + + public function stopOnSkipped(): bool + { + return $this->stopOnSkipped; + } + + public function stopOnWarning(): bool + { + return $this->stopOnWarning; + } + + public function outputToStandardErrorStream(): bool + { + return $this->outputToStandardErrorStream; + } + + public function columns(): int + { + return $this->columns; + } + + /** + * @deprecated Use noExtensions() instead + */ + public function loadPharExtensions(): bool + { + return $this->noExtensions; + } + + public function noExtensions(): bool + { + return $this->noExtensions; + } + + /** + * @psalm-assert-if-true !null $this->pharExtensionDirectory + */ + public function hasPharExtensionDirectory(): bool + { + return $this->pharExtensionDirectory !== null; + } + + /** + * @psalm-return non-empty-string + * + * @throws NoPharExtensionDirectoryException + */ + public function pharExtensionDirectory(): string + { + if (!$this->hasPharExtensionDirectory()) { + throw new NoPharExtensionDirectoryException; + } + + return $this->pharExtensionDirectory; + } + + /** + * @psalm-return list}> + */ + public function extensionBootstrappers(): array + { + return $this->extensionBootstrappers; + } + + public function backupGlobals(): bool + { + return $this->backupGlobals; + } + + public function backupStaticProperties(): bool + { + return $this->backupStaticProperties; + } + + public function beStrictAboutChangesToGlobalState(): bool + { + return $this->beStrictAboutChangesToGlobalState; + } + + public function colors(): bool + { + return $this->colors; + } + + public function processIsolation(): bool + { + return $this->processIsolation; + } + + public function enforceTimeLimit(): bool + { + return $this->enforceTimeLimit; + } + + public function defaultTimeLimit(): int + { + return $this->defaultTimeLimit; + } + + public function timeoutForSmallTests(): int + { + return $this->timeoutForSmallTests; + } + + public function timeoutForMediumTests(): int + { + return $this->timeoutForMediumTests; + } + + public function timeoutForLargeTests(): int + { + return $this->timeoutForLargeTests; + } + + public function reportUselessTests(): bool + { + return $this->reportUselessTests; + } + + public function strictCoverage(): bool + { + return $this->strictCoverage; + } + + public function disallowTestOutput(): bool + { + return $this->disallowTestOutput; + } + + public function displayDetailsOnIncompleteTests(): bool + { + return $this->displayDetailsOnIncompleteTests; + } + + public function displayDetailsOnSkippedTests(): bool + { + return $this->displayDetailsOnSkippedTests; + } + + public function displayDetailsOnTestsThatTriggerDeprecations(): bool + { + return $this->displayDetailsOnTestsThatTriggerDeprecations; + } + + public function displayDetailsOnPhpunitDeprecations(): bool + { + return $this->displayDetailsOnPhpunitDeprecations; + } + + public function displayDetailsOnTestsThatTriggerErrors(): bool + { + return $this->displayDetailsOnTestsThatTriggerErrors; + } + + public function displayDetailsOnTestsThatTriggerNotices(): bool + { + return $this->displayDetailsOnTestsThatTriggerNotices; + } + + public function displayDetailsOnTestsThatTriggerWarnings(): bool + { + return $this->displayDetailsOnTestsThatTriggerWarnings; + } + + public function reverseDefectList(): bool + { + return $this->reverseDefectList; + } + + public function requireCoverageMetadata(): bool + { + return $this->requireCoverageMetadata; + } + + /** + * @deprecated + */ + public function registerMockObjectsFromTestArgumentsRecursively(): bool + { + return $this->registerMockObjectsFromTestArgumentsRecursively; + } + + public function noProgress(): bool + { + return $this->noProgress; + } + + public function noResults(): bool + { + return $this->noResults; + } + + public function noOutput(): bool + { + return $this->noOutput; + } + + public function executionOrder(): int + { + return $this->executionOrder; + } + + public function executionOrderDefects(): int + { + return $this->executionOrderDefects; + } + + public function resolveDependencies(): bool + { + return $this->resolveDependencies; + } + + /** + * @psalm-assert-if-true !null $this->logfileTeamcity + */ + public function hasLogfileTeamcity(): bool + { + return $this->logfileTeamcity !== null; + } + + /** + * @throws LoggingNotConfiguredException + */ + public function logfileTeamcity(): string + { + if (!$this->hasLogfileTeamcity()) { + throw new LoggingNotConfiguredException; + } + + return $this->logfileTeamcity; + } + + /** + * @psalm-assert-if-true !null $this->logfileJunit + */ + public function hasLogfileJunit(): bool + { + return $this->logfileJunit !== null; + } + + /** + * @throws LoggingNotConfiguredException + */ + public function logfileJunit(): string + { + if (!$this->hasLogfileJunit()) { + throw new LoggingNotConfiguredException; + } + + return $this->logfileJunit; + } + + /** + * @psalm-assert-if-true !null $this->logfileTestdoxHtml + */ + public function hasLogfileTestdoxHtml(): bool + { + return $this->logfileTestdoxHtml !== null; + } + + /** + * @throws LoggingNotConfiguredException + */ + public function logfileTestdoxHtml(): string + { + if (!$this->hasLogfileTestdoxHtml()) { + throw new LoggingNotConfiguredException; + } + + return $this->logfileTestdoxHtml; + } + + /** + * @psalm-assert-if-true !null $this->logfileTestdoxText + */ + public function hasLogfileTestdoxText(): bool + { + return $this->logfileTestdoxText !== null; + } + + /** + * @throws LoggingNotConfiguredException + */ + public function logfileTestdoxText(): string + { + if (!$this->hasLogfileTestdoxText()) { + throw new LoggingNotConfiguredException; + } + + return $this->logfileTestdoxText; + } + + /** + * @psalm-assert-if-true !null $this->logEventsText + */ + public function hasLogEventsText(): bool + { + return $this->logEventsText !== null; + } + + /** + * @throws LoggingNotConfiguredException + */ + public function logEventsText(): string + { + if (!$this->hasLogEventsText()) { + throw new LoggingNotConfiguredException; + } + + return $this->logEventsText; + } + + /** + * @psalm-assert-if-true !null $this->logEventsVerboseText + */ + public function hasLogEventsVerboseText(): bool + { + return $this->logEventsVerboseText !== null; + } + + /** + * @throws LoggingNotConfiguredException + */ + public function logEventsVerboseText(): string + { + if (!$this->hasLogEventsVerboseText()) { + throw new LoggingNotConfiguredException; + } + + return $this->logEventsVerboseText; + } + + public function outputIsTeamCity(): bool + { + return $this->teamCityOutput; + } + + public function outputIsTestDox(): bool + { + return $this->testDoxOutput; + } + + /** + * @psalm-assert-if-true !empty $this->testsCovering + */ + public function hasTestsCovering(): bool + { + return !empty($this->testsCovering); + } + + /** + * @psalm-return list + * + * @throws FilterNotConfiguredException + */ + public function testsCovering(): array + { + if (!$this->hasTestsCovering()) { + throw new FilterNotConfiguredException; + } + + return $this->testsCovering; + } + + /** + * @psalm-assert-if-true !empty $this->testsUsing + */ + public function hasTestsUsing(): bool + { + return !empty($this->testsUsing); + } + + /** + * @psalm-return list + * + * @throws FilterNotConfiguredException + */ + public function testsUsing(): array + { + if (!$this->hasTestsUsing()) { + throw new FilterNotConfiguredException; + } + + return $this->testsUsing; + } + + /** + * @psalm-assert-if-true !null $this->filter + */ + public function hasFilter(): bool + { + return $this->filter !== null; + } + + /** + * @throws FilterNotConfiguredException + */ + public function filter(): string + { + if (!$this->hasFilter()) { + throw new FilterNotConfiguredException; + } + + return $this->filter; + } + + /** + * @psalm-assert-if-true !empty $this->groups + */ + public function hasGroups(): bool + { + return !empty($this->groups); + } + + /** + * @throws FilterNotConfiguredException + */ + public function groups(): array + { + if (!$this->hasGroups()) { + throw new FilterNotConfiguredException; + } + + return $this->groups; + } + + /** + * @psalm-assert-if-true !empty $this->excludeGroups + */ + public function hasExcludeGroups(): bool + { + return !empty($this->excludeGroups); + } + + /** + * @throws FilterNotConfiguredException + */ + public function excludeGroups(): array + { + if (!$this->hasExcludeGroups()) { + throw new FilterNotConfiguredException; + } + + return $this->excludeGroups; + } + + public function randomOrderSeed(): int + { + return $this->randomOrderSeed; + } + + public function includeUncoveredFiles(): bool + { + return $this->includeUncoveredFiles; + } + + public function testSuite(): TestSuiteCollection + { + return $this->testSuite; + } + + public function includeTestSuite(): string + { + return $this->includeTestSuite; + } + + public function excludeTestSuite(): string + { + return $this->excludeTestSuite; + } + + /** + * @psalm-assert-if-true !null $this->defaultTestSuite + */ + public function hasDefaultTestSuite(): bool + { + return $this->defaultTestSuite !== null; + } + + /** + * @throws NoDefaultTestSuiteException + */ + public function defaultTestSuite(): string + { + if (!$this->hasDefaultTestSuite()) { + throw new NoDefaultTestSuiteException; + } + + return $this->defaultTestSuite; + } + + /** + * @psalm-return non-empty-list + */ + public function testSuffixes(): array + { + return $this->testSuffixes; + } + + public function php(): Php + { + return $this->php; + } + + public function controlGarbageCollector(): bool + { + return $this->controlGarbageCollector; + } + + public function numberOfTestsBeforeGarbageCollection(): int + { + return $this->numberOfTestsBeforeGarbageCollection; + } + + /** + * @psalm-assert-if-true !null $this->generateBaseline + */ + public function hasGenerateBaseline(): bool + { + return $this->generateBaseline !== null; + } + + /** + * @throws NoBaselineException + */ + public function generateBaseline(): string + { + if (!$this->hasGenerateBaseline()) { + throw new NoBaselineException; + } + + return $this->generateBaseline; + } + + public function debug(): bool + { + return $this->debug; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php new file mode 100644 index 000000000..6eef052db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\TextUI\Configuration\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotFindSchemaException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php new file mode 100644 index 000000000..83faa0a2d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CodeCoverageReportNotConfiguredException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php new file mode 100644 index 000000000..e95e09428 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConfigurationCannotBeBuiltException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php new file mode 100644 index 000000000..dc49125a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/Exception.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends \PHPUnit\TextUI\Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php new file mode 100644 index 000000000..5ae4331f6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class FilterNotConfiguredException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php new file mode 100644 index 000000000..63cf9b070 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class LoggingNotConfiguredException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php new file mode 100644 index 000000000..7611dceb1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoBaselineException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php new file mode 100644 index 000000000..ff1bddf0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoBootstrapException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php new file mode 100644 index 000000000..215fe21f6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoCacheDirectoryException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php new file mode 100644 index 000000000..42ed0d495 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoCliArgumentException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php new file mode 100644 index 000000000..f8ceb80ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoConfigurationFileException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php new file mode 100644 index 000000000..113950b5d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoCoverageCacheDirectoryException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php new file mode 100644 index 000000000..e524c8db5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoCustomCssFileException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php new file mode 100644 index 000000000..96e7a7ada --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoDefaultTestSuiteException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php new file mode 100644 index 000000000..ce573ca79 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NoPharExtensionDirectoryException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Merger.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Merger.php new file mode 100644 index 000000000..28a7db0f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Merger.php @@ -0,0 +1,879 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use const DIRECTORY_SEPARATOR; +use const PATH_SEPARATOR; +use function array_diff; +use function assert; +use function dirname; +use function explode; +use function is_int; +use function realpath; +use function time; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\TextUI\CliArguments\Configuration as CliConfiguration; +use PHPUnit\TextUI\CliArguments\Exception; +use PHPUnit\TextUI\XmlConfiguration\Configuration as XmlConfiguration; +use PHPUnit\TextUI\XmlConfiguration\LoadedFromFileConfiguration; +use PHPUnit\TextUI\XmlConfiguration\SchemaDetector; +use PHPUnit\Util\Filesystem; +use SebastianBergmann\CodeCoverage\Report\Html\Colors; +use SebastianBergmann\CodeCoverage\Report\Thresholds; +use SebastianBergmann\Environment\Console; +use SebastianBergmann\Invoker\Invoker; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Merger +{ + /** + * @throws \PHPUnit\TextUI\XmlConfiguration\Exception + * @throws Exception + * @throws NoCustomCssFileException + */ + public function merge(CliConfiguration $cliConfiguration, XmlConfiguration $xmlConfiguration): Configuration + { + $configurationFile = null; + + if ($xmlConfiguration->wasLoadedFromFile()) { + assert($xmlConfiguration instanceof LoadedFromFileConfiguration); + + $configurationFile = $xmlConfiguration->filename(); + } + + $bootstrap = null; + + if ($cliConfiguration->hasBootstrap()) { + $bootstrap = $cliConfiguration->bootstrap(); + } elseif ($xmlConfiguration->phpunit()->hasBootstrap()) { + $bootstrap = $xmlConfiguration->phpunit()->bootstrap(); + } + + if ($cliConfiguration->hasCacheResult()) { + $cacheResult = $cliConfiguration->cacheResult(); + } else { + $cacheResult = $xmlConfiguration->phpunit()->cacheResult(); + } + + $cacheDirectory = null; + $coverageCacheDirectory = null; + + if ($cliConfiguration->hasCacheDirectory() && Filesystem::createDirectory($cliConfiguration->cacheDirectory())) { + $cacheDirectory = realpath($cliConfiguration->cacheDirectory()); + } elseif ($xmlConfiguration->phpunit()->hasCacheDirectory() && Filesystem::createDirectory($xmlConfiguration->phpunit()->cacheDirectory())) { + $cacheDirectory = realpath($xmlConfiguration->phpunit()->cacheDirectory()); + } + + if ($cacheDirectory !== null) { + $coverageCacheDirectory = $cacheDirectory . DIRECTORY_SEPARATOR . 'code-coverage'; + $testResultCacheFile = $cacheDirectory . DIRECTORY_SEPARATOR . 'test-results'; + } + + if ($coverageCacheDirectory === null) { + if ($cliConfiguration->hasCoverageCacheDirectory() && Filesystem::createDirectory($cliConfiguration->coverageCacheDirectory())) { + $coverageCacheDirectory = realpath($cliConfiguration->coverageCacheDirectory()); + } elseif ($xmlConfiguration->codeCoverage()->hasCacheDirectory()) { + $coverageCacheDirectory = $xmlConfiguration->codeCoverage()->cacheDirectory()->path(); + } + } + + if (!isset($testResultCacheFile)) { + if ($cliConfiguration->hasCacheResultFile()) { + $testResultCacheFile = $cliConfiguration->cacheResultFile(); + } elseif ($xmlConfiguration->phpunit()->hasCacheResultFile()) { + $testResultCacheFile = $xmlConfiguration->phpunit()->cacheResultFile(); + } elseif ($xmlConfiguration->wasLoadedFromFile()) { + $testResultCacheFile = dirname(realpath($xmlConfiguration->filename())) . DIRECTORY_SEPARATOR . '.phpunit.result.cache'; + } else { + $candidate = realpath($_SERVER['PHP_SELF']); + + if ($candidate) { + $testResultCacheFile = dirname($candidate) . DIRECTORY_SEPARATOR . '.phpunit.result.cache'; + } else { + $testResultCacheFile = '.phpunit.result.cache'; + } + } + } + + if ($cliConfiguration->hasDisableCodeCoverageIgnore()) { + $disableCodeCoverageIgnore = $cliConfiguration->disableCodeCoverageIgnore(); + } else { + $disableCodeCoverageIgnore = $xmlConfiguration->codeCoverage()->disableCodeCoverageIgnore(); + } + + if ($cliConfiguration->hasFailOnDeprecation()) { + $failOnDeprecation = $cliConfiguration->failOnDeprecation(); + } else { + $failOnDeprecation = $xmlConfiguration->phpunit()->failOnDeprecation(); + } + + if ($cliConfiguration->hasFailOnPhpunitDeprecation()) { + $failOnPhpunitDeprecation = $cliConfiguration->failOnPhpunitDeprecation(); + } else { + $failOnPhpunitDeprecation = $xmlConfiguration->phpunit()->failOnPhpunitDeprecation(); + } + + if ($cliConfiguration->hasFailOnEmptyTestSuite()) { + $failOnEmptyTestSuite = $cliConfiguration->failOnEmptyTestSuite(); + } else { + $failOnEmptyTestSuite = $xmlConfiguration->phpunit()->failOnEmptyTestSuite(); + } + + if ($cliConfiguration->hasFailOnIncomplete()) { + $failOnIncomplete = $cliConfiguration->failOnIncomplete(); + } else { + $failOnIncomplete = $xmlConfiguration->phpunit()->failOnIncomplete(); + } + + if ($cliConfiguration->hasFailOnNotice()) { + $failOnNotice = $cliConfiguration->failOnNotice(); + } else { + $failOnNotice = $xmlConfiguration->phpunit()->failOnNotice(); + } + + if ($cliConfiguration->hasFailOnRisky()) { + $failOnRisky = $cliConfiguration->failOnRisky(); + } else { + $failOnRisky = $xmlConfiguration->phpunit()->failOnRisky(); + } + + if ($cliConfiguration->hasFailOnSkipped()) { + $failOnSkipped = $cliConfiguration->failOnSkipped(); + } else { + $failOnSkipped = $xmlConfiguration->phpunit()->failOnSkipped(); + } + + if ($cliConfiguration->hasFailOnWarning()) { + $failOnWarning = $cliConfiguration->failOnWarning(); + } else { + $failOnWarning = $xmlConfiguration->phpunit()->failOnWarning(); + } + + if ($cliConfiguration->hasStopOnDefect()) { + $stopOnDefect = $cliConfiguration->stopOnDefect(); + } else { + $stopOnDefect = $xmlConfiguration->phpunit()->stopOnDefect(); + } + + if ($cliConfiguration->hasStopOnDeprecation()) { + $stopOnDeprecation = $cliConfiguration->stopOnDeprecation(); + } else { + $stopOnDeprecation = $xmlConfiguration->phpunit()->stopOnDeprecation(); + } + + if ($cliConfiguration->hasStopOnError()) { + $stopOnError = $cliConfiguration->stopOnError(); + } else { + $stopOnError = $xmlConfiguration->phpunit()->stopOnError(); + } + + if ($cliConfiguration->hasStopOnFailure()) { + $stopOnFailure = $cliConfiguration->stopOnFailure(); + } else { + $stopOnFailure = $xmlConfiguration->phpunit()->stopOnFailure(); + } + + if ($cliConfiguration->hasStopOnIncomplete()) { + $stopOnIncomplete = $cliConfiguration->stopOnIncomplete(); + } else { + $stopOnIncomplete = $xmlConfiguration->phpunit()->stopOnIncomplete(); + } + + if ($cliConfiguration->hasStopOnNotice()) { + $stopOnNotice = $cliConfiguration->stopOnNotice(); + } else { + $stopOnNotice = $xmlConfiguration->phpunit()->stopOnNotice(); + } + + if ($cliConfiguration->hasStopOnRisky()) { + $stopOnRisky = $cliConfiguration->stopOnRisky(); + } else { + $stopOnRisky = $xmlConfiguration->phpunit()->stopOnRisky(); + } + + if ($cliConfiguration->hasStopOnSkipped()) { + $stopOnSkipped = $cliConfiguration->stopOnSkipped(); + } else { + $stopOnSkipped = $xmlConfiguration->phpunit()->stopOnSkipped(); + } + + if ($cliConfiguration->hasStopOnWarning()) { + $stopOnWarning = $cliConfiguration->stopOnWarning(); + } else { + $stopOnWarning = $xmlConfiguration->phpunit()->stopOnWarning(); + } + + if ($cliConfiguration->hasStderr() && $cliConfiguration->stderr()) { + $outputToStandardErrorStream = true; + } else { + $outputToStandardErrorStream = $xmlConfiguration->phpunit()->stderr(); + } + + if ($cliConfiguration->hasColumns()) { + $columns = $cliConfiguration->columns(); + } else { + $columns = $xmlConfiguration->phpunit()->columns(); + } + + if ($columns === 'max') { + $columns = (new Console)->getNumberOfColumns(); + } + + if ($columns < 16) { + $columns = 16; + + EventFacade::emitter()->testRunnerTriggeredWarning( + 'Less than 16 columns requested, number of columns set to 16', + ); + } + + assert(is_int($columns)); + + $noExtensions = false; + + if ($cliConfiguration->hasNoExtensions() && $cliConfiguration->noExtensions()) { + $noExtensions = true; + } + + $pharExtensionDirectory = null; + + if ($xmlConfiguration->phpunit()->hasExtensionsDirectory()) { + $pharExtensionDirectory = $xmlConfiguration->phpunit()->extensionsDirectory(); + } + + $extensionBootstrappers = []; + + foreach ($xmlConfiguration->extensions() as $extension) { + $extensionBootstrappers[] = [ + 'className' => $extension->className(), + 'parameters' => $extension->parameters(), + ]; + } + + if ($cliConfiguration->hasPathCoverage() && $cliConfiguration->pathCoverage()) { + $pathCoverage = $cliConfiguration->pathCoverage(); + } else { + $pathCoverage = $xmlConfiguration->codeCoverage()->pathCoverage(); + } + + $defaultColors = Colors::default(); + $defaultThresholds = Thresholds::default(); + + $coverageClover = null; + $coverageCobertura = null; + $coverageCrap4j = null; + $coverageCrap4jThreshold = 30; + $coverageHtml = null; + $coverageHtmlLowUpperBound = $defaultThresholds->lowUpperBound(); + $coverageHtmlHighLowerBound = $defaultThresholds->highLowerBound(); + $coverageHtmlColorSuccessLow = $defaultColors->successLow(); + $coverageHtmlColorSuccessMedium = $defaultColors->successMedium(); + $coverageHtmlColorSuccessHigh = $defaultColors->successHigh(); + $coverageHtmlColorWarning = $defaultColors->warning(); + $coverageHtmlColorDanger = $defaultColors->danger(); + $coverageHtmlCustomCssFile = null; + $coveragePhp = null; + $coverageText = null; + $coverageTextShowUncoveredFiles = false; + $coverageTextShowOnlySummary = false; + $coverageXml = null; + $coverageFromXmlConfiguration = true; + + if ($cliConfiguration->hasNoCoverage() && $cliConfiguration->noCoverage()) { + $coverageFromXmlConfiguration = false; + } + + if ($cliConfiguration->hasCoverageClover()) { + $coverageClover = $cliConfiguration->coverageClover(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasClover()) { + $coverageClover = $xmlConfiguration->codeCoverage()->clover()->target()->path(); + } + + if ($cliConfiguration->hasCoverageCobertura()) { + $coverageCobertura = $cliConfiguration->coverageCobertura(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasCobertura()) { + $coverageCobertura = $xmlConfiguration->codeCoverage()->cobertura()->target()->path(); + } + + if ($xmlConfiguration->codeCoverage()->hasCrap4j()) { + $coverageCrap4jThreshold = $xmlConfiguration->codeCoverage()->crap4j()->threshold(); + } + + if ($cliConfiguration->hasCoverageCrap4J()) { + $coverageCrap4j = $cliConfiguration->coverageCrap4J(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasCrap4j()) { + $coverageCrap4j = $xmlConfiguration->codeCoverage()->crap4j()->target()->path(); + } + + if ($xmlConfiguration->codeCoverage()->hasHtml()) { + $coverageHtmlHighLowerBound = $xmlConfiguration->codeCoverage()->html()->highLowerBound(); + $coverageHtmlLowUpperBound = $xmlConfiguration->codeCoverage()->html()->lowUpperBound(); + + if ($coverageHtmlLowUpperBound > $coverageHtmlHighLowerBound) { + $coverageHtmlLowUpperBound = $defaultThresholds->lowUpperBound(); + $coverageHtmlHighLowerBound = $defaultThresholds->highLowerBound(); + } + + $coverageHtmlColorSuccessLow = $xmlConfiguration->codeCoverage()->html()->colorSuccessLow(); + $coverageHtmlColorSuccessMedium = $xmlConfiguration->codeCoverage()->html()->colorSuccessMedium(); + $coverageHtmlColorSuccessHigh = $xmlConfiguration->codeCoverage()->html()->colorSuccessHigh(); + $coverageHtmlColorWarning = $xmlConfiguration->codeCoverage()->html()->colorWarning(); + $coverageHtmlColorDanger = $xmlConfiguration->codeCoverage()->html()->colorDanger(); + + if ($xmlConfiguration->codeCoverage()->html()->hasCustomCssFile()) { + $coverageHtmlCustomCssFile = $xmlConfiguration->codeCoverage()->html()->customCssFile(); + } + } + + if ($cliConfiguration->hasCoverageHtml()) { + $coverageHtml = $cliConfiguration->coverageHtml(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasHtml()) { + $coverageHtml = $xmlConfiguration->codeCoverage()->html()->target()->path(); + } + + if ($cliConfiguration->hasCoveragePhp()) { + $coveragePhp = $cliConfiguration->coveragePhp(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasPhp()) { + $coveragePhp = $xmlConfiguration->codeCoverage()->php()->target()->path(); + } + + if ($xmlConfiguration->codeCoverage()->hasText()) { + $coverageTextShowUncoveredFiles = $xmlConfiguration->codeCoverage()->text()->showUncoveredFiles(); + $coverageTextShowOnlySummary = $xmlConfiguration->codeCoverage()->text()->showOnlySummary(); + } + + if ($cliConfiguration->hasCoverageTextShowUncoveredFiles()) { + $coverageTextShowUncoveredFiles = $cliConfiguration->coverageTextShowUncoveredFiles(); + } + + if ($cliConfiguration->hasCoverageTextShowOnlySummary()) { + $coverageTextShowOnlySummary = $cliConfiguration->coverageTextShowOnlySummary(); + } + + if ($cliConfiguration->hasCoverageText()) { + $coverageText = $cliConfiguration->coverageText(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasText()) { + $coverageText = $xmlConfiguration->codeCoverage()->text()->target()->path(); + } + + if ($cliConfiguration->hasCoverageXml()) { + $coverageXml = $cliConfiguration->coverageXml(); + } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasXml()) { + $coverageXml = $xmlConfiguration->codeCoverage()->xml()->target()->path(); + } + + if ($cliConfiguration->hasBackupGlobals()) { + $backupGlobals = $cliConfiguration->backupGlobals(); + } else { + $backupGlobals = $xmlConfiguration->phpunit()->backupGlobals(); + } + + if ($cliConfiguration->hasBackupStaticProperties()) { + $backupStaticProperties = $cliConfiguration->backupStaticProperties(); + } else { + $backupStaticProperties = $xmlConfiguration->phpunit()->backupStaticProperties(); + } + + if ($cliConfiguration->hasBeStrictAboutChangesToGlobalState()) { + $beStrictAboutChangesToGlobalState = $cliConfiguration->beStrictAboutChangesToGlobalState(); + } else { + $beStrictAboutChangesToGlobalState = $xmlConfiguration->phpunit()->beStrictAboutChangesToGlobalState(); + } + + if ($cliConfiguration->hasProcessIsolation()) { + $processIsolation = $cliConfiguration->processIsolation(); + } else { + $processIsolation = $xmlConfiguration->phpunit()->processIsolation(); + } + + if ($cliConfiguration->hasEnforceTimeLimit()) { + $enforceTimeLimit = $cliConfiguration->enforceTimeLimit(); + } else { + $enforceTimeLimit = $xmlConfiguration->phpunit()->enforceTimeLimit(); + } + + if ($enforceTimeLimit && !(new Invoker)->canInvokeWithTimeout()) { + EventFacade::emitter()->testRunnerTriggeredWarning( + 'The pcntl extension is required for enforcing time limits', + ); + } + + if ($cliConfiguration->hasDefaultTimeLimit()) { + $defaultTimeLimit = $cliConfiguration->defaultTimeLimit(); + } else { + $defaultTimeLimit = $xmlConfiguration->phpunit()->defaultTimeLimit(); + } + + $timeoutForSmallTests = $xmlConfiguration->phpunit()->timeoutForSmallTests(); + $timeoutForMediumTests = $xmlConfiguration->phpunit()->timeoutForMediumTests(); + $timeoutForLargeTests = $xmlConfiguration->phpunit()->timeoutForLargeTests(); + + if ($cliConfiguration->hasReportUselessTests()) { + $reportUselessTests = $cliConfiguration->reportUselessTests(); + } else { + $reportUselessTests = $xmlConfiguration->phpunit()->beStrictAboutTestsThatDoNotTestAnything(); + } + + if ($cliConfiguration->hasStrictCoverage()) { + $strictCoverage = $cliConfiguration->strictCoverage(); + } else { + $strictCoverage = $xmlConfiguration->phpunit()->beStrictAboutCoverageMetadata(); + } + + if ($cliConfiguration->hasDisallowTestOutput()) { + $disallowTestOutput = $cliConfiguration->disallowTestOutput(); + } else { + $disallowTestOutput = $xmlConfiguration->phpunit()->beStrictAboutOutputDuringTests(); + } + + if ($cliConfiguration->hasDisplayDetailsOnIncompleteTests()) { + $displayDetailsOnIncompleteTests = $cliConfiguration->displayDetailsOnIncompleteTests(); + } else { + $displayDetailsOnIncompleteTests = $xmlConfiguration->phpunit()->displayDetailsOnIncompleteTests(); + } + + if ($cliConfiguration->hasDisplayDetailsOnSkippedTests()) { + $displayDetailsOnSkippedTests = $cliConfiguration->displayDetailsOnSkippedTests(); + } else { + $displayDetailsOnSkippedTests = $xmlConfiguration->phpunit()->displayDetailsOnSkippedTests(); + } + + if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerDeprecations()) { + $displayDetailsOnTestsThatTriggerDeprecations = $cliConfiguration->displayDetailsOnTestsThatTriggerDeprecations(); + } else { + $displayDetailsOnTestsThatTriggerDeprecations = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerDeprecations(); + } + + if ($cliConfiguration->hasDisplayDetailsOnPhpunitDeprecations()) { + $displayDetailsOnPhpunitDeprecations = $cliConfiguration->displayDetailsOnPhpunitDeprecations(); + } else { + $displayDetailsOnPhpunitDeprecations = $xmlConfiguration->phpunit()->displayDetailsOnPhpunitDeprecations(); + } + + if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerErrors()) { + $displayDetailsOnTestsThatTriggerErrors = $cliConfiguration->displayDetailsOnTestsThatTriggerErrors(); + } else { + $displayDetailsOnTestsThatTriggerErrors = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerErrors(); + } + + if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerNotices()) { + $displayDetailsOnTestsThatTriggerNotices = $cliConfiguration->displayDetailsOnTestsThatTriggerNotices(); + } else { + $displayDetailsOnTestsThatTriggerNotices = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerNotices(); + } + + if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerWarnings()) { + $displayDetailsOnTestsThatTriggerWarnings = $cliConfiguration->displayDetailsOnTestsThatTriggerWarnings(); + } else { + $displayDetailsOnTestsThatTriggerWarnings = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerWarnings(); + } + + if ($cliConfiguration->hasReverseList()) { + $reverseDefectList = $cliConfiguration->reverseList(); + } else { + $reverseDefectList = $xmlConfiguration->phpunit()->reverseDefectList(); + } + + $requireCoverageMetadata = $xmlConfiguration->phpunit()->requireCoverageMetadata(); + $registerMockObjectsFromTestArgumentsRecursively = $xmlConfiguration->phpunit()->registerMockObjectsFromTestArgumentsRecursively(); + + if ($cliConfiguration->hasExecutionOrder()) { + $executionOrder = $cliConfiguration->executionOrder(); + } else { + $executionOrder = $xmlConfiguration->phpunit()->executionOrder(); + } + + $executionOrderDefects = TestSuiteSorter::ORDER_DEFAULT; + + if ($cliConfiguration->hasExecutionOrderDefects()) { + $executionOrderDefects = $cliConfiguration->executionOrderDefects(); + } elseif ($xmlConfiguration->phpunit()->defectsFirst()) { + $executionOrderDefects = TestSuiteSorter::ORDER_DEFECTS_FIRST; + } + + if ($cliConfiguration->hasResolveDependencies()) { + $resolveDependencies = $cliConfiguration->resolveDependencies(); + } else { + $resolveDependencies = $xmlConfiguration->phpunit()->resolveDependencies(); + } + + $colors = false; + $colorsSupported = (new Console)->hasColorSupport(); + + if ($cliConfiguration->hasColors()) { + if ($cliConfiguration->colors() === Configuration::COLOR_ALWAYS) { + $colors = true; + } elseif ($colorsSupported && $cliConfiguration->colors() === Configuration::COLOR_AUTO) { + $colors = true; + } + } elseif ($xmlConfiguration->phpunit()->colors() === Configuration::COLOR_ALWAYS) { + $colors = true; + } elseif ($colorsSupported && $xmlConfiguration->phpunit()->colors() === Configuration::COLOR_AUTO) { + $colors = true; + } + + $logfileTeamcity = null; + $logfileJunit = null; + $logfileTestdoxHtml = null; + $logfileTestdoxText = null; + $loggingFromXmlConfiguration = true; + + if ($cliConfiguration->hasNoLogging() && $cliConfiguration->noLogging()) { + $loggingFromXmlConfiguration = false; + } + + if ($cliConfiguration->hasTeamcityLogfile()) { + $logfileTeamcity = $cliConfiguration->teamcityLogfile(); + } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasTeamCity()) { + $logfileTeamcity = $xmlConfiguration->logging()->teamCity()->target()->path(); + } + + if ($cliConfiguration->hasJunitLogfile()) { + $logfileJunit = $cliConfiguration->junitLogfile(); + } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasJunit()) { + $logfileJunit = $xmlConfiguration->logging()->junit()->target()->path(); + } + + if ($cliConfiguration->hasTestdoxHtmlFile()) { + $logfileTestdoxHtml = $cliConfiguration->testdoxHtmlFile(); + } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasTestDoxHtml()) { + $logfileTestdoxHtml = $xmlConfiguration->logging()->testDoxHtml()->target()->path(); + } + + if ($cliConfiguration->hasTestdoxTextFile()) { + $logfileTestdoxText = $cliConfiguration->testdoxTextFile(); + } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasTestDoxText()) { + $logfileTestdoxText = $xmlConfiguration->logging()->testDoxText()->target()->path(); + } + + $logEventsText = null; + + if ($cliConfiguration->hasLogEventsText()) { + $logEventsText = $cliConfiguration->logEventsText(); + } + + $logEventsVerboseText = null; + + if ($cliConfiguration->hasLogEventsVerboseText()) { + $logEventsVerboseText = $cliConfiguration->logEventsVerboseText(); + } + + $teamCityOutput = false; + + if ($cliConfiguration->hasTeamCityPrinter() && $cliConfiguration->teamCityPrinter()) { + $teamCityOutput = true; + } + + if ($cliConfiguration->hasTestDoxPrinter() && $cliConfiguration->testdoxPrinter()) { + $testDoxOutput = true; + } else { + $testDoxOutput = $xmlConfiguration->phpunit()->testdoxPrinter(); + } + + $noProgress = false; + + if ($cliConfiguration->hasNoProgress() && $cliConfiguration->noProgress()) { + $noProgress = true; + } + + $noResults = false; + + if ($cliConfiguration->hasNoResults() && $cliConfiguration->noResults()) { + $noResults = true; + } + + $noOutput = false; + + if ($cliConfiguration->hasNoOutput() && $cliConfiguration->noOutput()) { + $noOutput = true; + } + + $testsCovering = null; + + if ($cliConfiguration->hasTestsCovering()) { + $testsCovering = $cliConfiguration->testsCovering(); + } + + $testsUsing = null; + + if ($cliConfiguration->hasTestsUsing()) { + $testsUsing = $cliConfiguration->testsUsing(); + } + + $filter = null; + + if ($cliConfiguration->hasFilter()) { + $filter = $cliConfiguration->filter(); + } + + if ($cliConfiguration->hasGroups()) { + $groups = $cliConfiguration->groups(); + } else { + $groups = $xmlConfiguration->groups()->include()->asArrayOfStrings(); + } + + if ($cliConfiguration->hasExcludeGroups()) { + $excludeGroups = $cliConfiguration->excludeGroups(); + } else { + $excludeGroups = $xmlConfiguration->groups()->exclude()->asArrayOfStrings(); + } + + $excludeGroups = array_diff($excludeGroups, $groups); + + if ($cliConfiguration->hasRandomOrderSeed()) { + $randomOrderSeed = $cliConfiguration->randomOrderSeed(); + } else { + $randomOrderSeed = time(); + } + + if ($xmlConfiguration->wasLoadedFromFile() && $xmlConfiguration->hasValidationErrors()) { + if ((new SchemaDetector)->detect($xmlConfiguration->filename())->detected()) { + EventFacade::emitter()->testRunnerTriggeredDeprecation( + 'Your XML configuration validates against a deprecated schema. Migrate your XML configuration using "--migrate-configuration"!', + ); + } else { + EventFacade::emitter()->testRunnerTriggeredWarning( + "Test results may not be as expected because the XML configuration file did not pass validation:\n" . + $xmlConfiguration->validationErrors(), + ); + } + } + + $includeUncoveredFiles = $xmlConfiguration->codeCoverage()->includeUncoveredFiles(); + + $includePaths = []; + + if ($cliConfiguration->hasIncludePath()) { + foreach (explode(PATH_SEPARATOR, $cliConfiguration->includePath()) as $includePath) { + $includePaths[] = new Directory($includePath); + } + } + + foreach ($xmlConfiguration->php()->includePaths() as $includePath) { + $includePaths[] = $includePath; + } + + $iniSettings = []; + + if ($cliConfiguration->hasIniSettings()) { + foreach ($cliConfiguration->iniSettings() as $name => $value) { + $iniSettings[] = new IniSetting($name, $value); + } + } + + foreach ($xmlConfiguration->php()->iniSettings() as $iniSetting) { + $iniSettings[] = $iniSetting; + } + + $includeTestSuite = ''; + + if ($cliConfiguration->hasTestSuite()) { + $includeTestSuite = $cliConfiguration->testSuite(); + } elseif ($xmlConfiguration->phpunit()->hasDefaultTestSuite()) { + $includeTestSuite = $xmlConfiguration->phpunit()->defaultTestSuite(); + } + + $excludeTestSuite = ''; + + if ($cliConfiguration->hasExcludedTestSuite()) { + $excludeTestSuite = $cliConfiguration->excludedTestSuite(); + } + + $testSuffixes = ['Test.php', '.phpt']; + + if ($cliConfiguration->hasTestSuffixes()) { + $testSuffixes = $cliConfiguration->testSuffixes(); + } + + $sourceIncludeDirectories = []; + + if ($cliConfiguration->hasCoverageFilter()) { + foreach ($cliConfiguration->coverageFilter() as $directory) { + $sourceIncludeDirectories[] = new FilterDirectory($directory, '', '.php'); + } + } + + if ($xmlConfiguration->codeCoverage()->hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport()) { + foreach ($xmlConfiguration->codeCoverage()->directories() as $directory) { + $sourceIncludeDirectories[] = $directory; + } + + $sourceIncludeFiles = $xmlConfiguration->codeCoverage()->files(); + $sourceExcludeDirectories = $xmlConfiguration->codeCoverage()->excludeDirectories(); + $sourceExcludeFiles = $xmlConfiguration->codeCoverage()->excludeFiles(); + } else { + foreach ($xmlConfiguration->source()->includeDirectories() as $directory) { + $sourceIncludeDirectories[] = $directory; + } + + $sourceIncludeFiles = $xmlConfiguration->source()->includeFiles(); + $sourceExcludeDirectories = $xmlConfiguration->source()->excludeDirectories(); + $sourceExcludeFiles = $xmlConfiguration->source()->excludeFiles(); + } + + $useBaseline = null; + $generateBaseline = null; + + if (!$cliConfiguration->hasGenerateBaseline()) { + if ($cliConfiguration->hasUseBaseline()) { + $useBaseline = $cliConfiguration->useBaseline(); + } elseif ($xmlConfiguration->source()->hasBaseline()) { + $useBaseline = $xmlConfiguration->source()->baseline(); + } + } else { + $generateBaseline = $cliConfiguration->generateBaseline(); + } + + assert($useBaseline !== ''); + assert($generateBaseline !== ''); + + return new Configuration( + $cliConfiguration->arguments(), + $configurationFile, + $bootstrap, + $cacheResult, + $cacheDirectory, + $coverageCacheDirectory, + new Source( + $useBaseline, + $cliConfiguration->ignoreBaseline(), + FilterDirectoryCollection::fromArray($sourceIncludeDirectories), + $sourceIncludeFiles, + $sourceExcludeDirectories, + $sourceExcludeFiles, + $xmlConfiguration->source()->restrictDeprecations(), + $xmlConfiguration->source()->restrictNotices(), + $xmlConfiguration->source()->restrictWarnings(), + $xmlConfiguration->source()->ignoreSuppressionOfDeprecations(), + $xmlConfiguration->source()->ignoreSuppressionOfPhpDeprecations(), + $xmlConfiguration->source()->ignoreSuppressionOfErrors(), + $xmlConfiguration->source()->ignoreSuppressionOfNotices(), + $xmlConfiguration->source()->ignoreSuppressionOfPhpNotices(), + $xmlConfiguration->source()->ignoreSuppressionOfWarnings(), + $xmlConfiguration->source()->ignoreSuppressionOfPhpWarnings(), + ), + $testResultCacheFile, + $coverageClover, + $coverageCobertura, + $coverageCrap4j, + $coverageCrap4jThreshold, + $coverageHtml, + $coverageHtmlLowUpperBound, + $coverageHtmlHighLowerBound, + $coverageHtmlColorSuccessLow, + $coverageHtmlColorSuccessMedium, + $coverageHtmlColorSuccessHigh, + $coverageHtmlColorWarning, + $coverageHtmlColorDanger, + $coverageHtmlCustomCssFile, + $coveragePhp, + $coverageText, + $coverageTextShowUncoveredFiles, + $coverageTextShowOnlySummary, + $coverageXml, + $pathCoverage, + $xmlConfiguration->codeCoverage()->ignoreDeprecatedCodeUnits(), + $disableCodeCoverageIgnore, + $failOnDeprecation, + $failOnPhpunitDeprecation, + $failOnEmptyTestSuite, + $failOnIncomplete, + $failOnNotice, + $failOnRisky, + $failOnSkipped, + $failOnWarning, + $stopOnDefect, + $stopOnDeprecation, + $stopOnError, + $stopOnFailure, + $stopOnIncomplete, + $stopOnNotice, + $stopOnRisky, + $stopOnSkipped, + $stopOnWarning, + $outputToStandardErrorStream, + $columns, + $noExtensions, + $pharExtensionDirectory, + $extensionBootstrappers, + $backupGlobals, + $backupStaticProperties, + $beStrictAboutChangesToGlobalState, + $colors, + $processIsolation, + $enforceTimeLimit, + $defaultTimeLimit, + $timeoutForSmallTests, + $timeoutForMediumTests, + $timeoutForLargeTests, + $reportUselessTests, + $strictCoverage, + $disallowTestOutput, + $displayDetailsOnIncompleteTests, + $displayDetailsOnSkippedTests, + $displayDetailsOnTestsThatTriggerDeprecations, + $displayDetailsOnPhpunitDeprecations, + $displayDetailsOnTestsThatTriggerErrors, + $displayDetailsOnTestsThatTriggerNotices, + $displayDetailsOnTestsThatTriggerWarnings, + $reverseDefectList, + $requireCoverageMetadata, + $registerMockObjectsFromTestArgumentsRecursively, + $noProgress, + $noResults, + $noOutput, + $executionOrder, + $executionOrderDefects, + $resolveDependencies, + $logfileTeamcity, + $logfileJunit, + $logfileTestdoxHtml, + $logfileTestdoxText, + $logEventsText, + $logEventsVerboseText, + $teamCityOutput, + $testDoxOutput, + $testsCovering, + $testsUsing, + $filter, + $groups, + $excludeGroups, + $randomOrderSeed, + $includeUncoveredFiles, + $xmlConfiguration->testSuite(), + $includeTestSuite, + $excludeTestSuite, + $xmlConfiguration->phpunit()->hasDefaultTestSuite() ? $xmlConfiguration->phpunit()->defaultTestSuite() : null, + $testSuffixes, + new Php( + DirectoryCollection::fromArray($includePaths), + IniSettingCollection::fromArray($iniSettings), + $xmlConfiguration->php()->constants(), + $xmlConfiguration->php()->globalVariables(), + $xmlConfiguration->php()->envVariables(), + $xmlConfiguration->php()->postVariables(), + $xmlConfiguration->php()->getVariables(), + $xmlConfiguration->php()->cookieVariables(), + $xmlConfiguration->php()->serverVariables(), + $xmlConfiguration->php()->filesVariables(), + $xmlConfiguration->php()->requestVariables(), + ), + $xmlConfiguration->phpunit()->controlGarbageCollector(), + $xmlConfiguration->phpunit()->numberOfTestsBeforeGarbageCollection(), + $generateBaseline, + $cliConfiguration->debug(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php new file mode 100644 index 000000000..8bd727f2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/PhpHandler.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use const PATH_SEPARATOR; +use function constant; +use function define; +use function defined; +use function getenv; +use function implode; +use function ini_get; +use function ini_set; +use function putenv; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhpHandler +{ + public function handle(Php $configuration): void + { + $this->handleIncludePaths($configuration->includePaths()); + $this->handleIniSettings($configuration->iniSettings()); + $this->handleConstants($configuration->constants()); + $this->handleGlobalVariables($configuration->globalVariables()); + $this->handleServerVariables($configuration->serverVariables()); + $this->handleEnvVariables($configuration->envVariables()); + $this->handleVariables('_POST', $configuration->postVariables()); + $this->handleVariables('_GET', $configuration->getVariables()); + $this->handleVariables('_COOKIE', $configuration->cookieVariables()); + $this->handleVariables('_FILES', $configuration->filesVariables()); + $this->handleVariables('_REQUEST', $configuration->requestVariables()); + } + + private function handleIncludePaths(DirectoryCollection $includePaths): void + { + if (!$includePaths->isEmpty()) { + $includePathsAsStrings = []; + + foreach ($includePaths as $includePath) { + $includePathsAsStrings[] = $includePath->path(); + } + + ini_set( + 'include_path', + implode(PATH_SEPARATOR, $includePathsAsStrings) . + PATH_SEPARATOR . + ini_get('include_path'), + ); + } + } + + private function handleIniSettings(IniSettingCollection $iniSettings): void + { + foreach ($iniSettings as $iniSetting) { + $value = $iniSetting->value(); + + if (defined($value)) { + $value = (string) constant($value); + } + + ini_set($iniSetting->name(), $value); + } + } + + private function handleConstants(ConstantCollection $constants): void + { + foreach ($constants as $constant) { + if (!defined($constant->name())) { + define($constant->name(), $constant->value()); + } + } + } + + private function handleGlobalVariables(VariableCollection $variables): void + { + foreach ($variables as $variable) { + $GLOBALS[$variable->name()] = $variable->value(); + } + } + + private function handleServerVariables(VariableCollection $variables): void + { + foreach ($variables as $variable) { + $_SERVER[$variable->name()] = $variable->value(); + } + } + + private function handleVariables(string $target, VariableCollection $variables): void + { + foreach ($variables as $variable) { + $GLOBALS[$target][$variable->name()] = $variable->value(); + } + } + + private function handleEnvVariables(VariableCollection $variables): void + { + foreach ($variables as $variable) { + $name = $variable->name(); + $value = $variable->value(); + $force = $variable->force(); + + if ($force || getenv($name) === false) { + putenv("{$name}={$value}"); + } + + $value = getenv($name); + + if ($force || !isset($_ENV[$name])) { + $_ENV[$name] = $value; + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Registry.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Registry.php new file mode 100644 index 000000000..bde319a77 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Registry.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function assert; +use function file_get_contents; +use function file_put_contents; +use function serialize; +use function unserialize; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\TextUI\CliArguments\Configuration as CliConfiguration; +use PHPUnit\TextUI\CliArguments\Exception; +use PHPUnit\TextUI\XmlConfiguration\Configuration as XmlConfiguration; +use PHPUnit\Util\VersionComparisonOperator; + +/** + * CLI options and XML configuration are static within a single PHPUnit process. + * It is therefore okay to use a Singleton registry here. + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Registry +{ + private static ?Configuration $instance = null; + + public static function saveTo(string $path): bool + { + $result = file_put_contents( + $path, + serialize(self::get()), + ); + + if ($result) { + return true; + } + + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + /** + * This method is used by the "run test(s) in separate process" templates. + * + * @noinspection PhpUnused + * + * @codeCoverageIgnore + */ + public static function loadFrom(string $path): void + { + self::$instance = unserialize( + file_get_contents($path), + [ + 'allowed_classes' => [ + Configuration::class, + Php::class, + ConstantCollection::class, + Constant::class, + IniSettingCollection::class, + IniSetting::class, + VariableCollection::class, + Variable::class, + DirectoryCollection::class, + Directory::class, + FileCollection::class, + File::class, + FilterDirectoryCollection::class, + FilterDirectory::class, + TestDirectoryCollection::class, + TestDirectory::class, + TestFileCollection::class, + TestFile::class, + TestSuiteCollection::class, + TestSuite::class, + VersionComparisonOperator::class, + Source::class, + ], + ], + ); + } + + public static function get(): Configuration + { + assert(self::$instance instanceof Configuration); + + return self::$instance; + } + + /** + * @throws \PHPUnit\TextUI\XmlConfiguration\Exception + * @throws Exception + * @throws NoCustomCssFileException + */ + public static function init(CliConfiguration $cliConfiguration, XmlConfiguration $xmlConfiguration): Configuration + { + self::$instance = (new Merger)->merge($cliConfiguration, $xmlConfiguration); + + EventFacade::emitter()->testRunnerConfigured(self::$instance); + + return self::$instance; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php new file mode 100644 index 000000000..a6b1262b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceFilter.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SourceFilter +{ + public function includes(Source $source, string $path): bool + { + $files = (new SourceMapper)->map($source); + + return isset($files[$path]); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php new file mode 100644 index 000000000..f5d837f91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/SourceMapper.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function realpath; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; +use SplObjectStorage; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SourceMapper +{ + /** + * @psalm-var SplObjectStorage> + */ + private static ?SplObjectStorage $files = null; + + /** + * @psalm-return array + */ + public function map(Source $source): array + { + if (self::$files === null) { + self::$files = new SplObjectStorage; + } + + if (isset(self::$files[$source])) { + return self::$files[$source]; + } + + $files = []; + + foreach ($source->includeDirectories() as $directory) { + foreach ((new FileIteratorFacade)->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix()) as $file) { + $file = realpath($file); + + if (!$file) { + continue; + } + + $files[$file] = true; + } + } + + foreach ($source->includeFiles() as $file) { + $file = realpath($file->path()); + + if (!$file) { + continue; + } + + $files[$file] = true; + } + + foreach ($source->excludeDirectories() as $directory) { + foreach ((new FileIteratorFacade)->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix()) as $file) { + $file = realpath($file); + + if (!$file) { + continue; + } + + if (!isset($files[$file])) { + continue; + } + + unset($files[$file]); + } + } + + foreach ($source->excludeFiles() as $file) { + $file = realpath($file->path()); + + if (!$file) { + continue; + } + + if (!isset($files[$file])) { + continue; + } + + unset($files[$file]); + } + + self::$files[$source] = $files; + + return $files; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php new file mode 100644 index 000000000..0b948059b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/TestSuiteBuilder.php @@ -0,0 +1,146 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use const PHP_EOL; +use function assert; +use function count; +use function is_dir; +use function is_file; +use function realpath; +use function str_ends_with; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Exception; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\TestSuiteLoader; +use PHPUnit\TextUI\RuntimeException; +use PHPUnit\TextUI\TestDirectoryNotFoundException; +use PHPUnit\TextUI\TestFileNotFoundException; +use PHPUnit\TextUI\XmlConfiguration\TestSuiteMapper; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteBuilder +{ + /** + * @throws \PHPUnit\Framework\Exception + * @throws RuntimeException + * @throws TestDirectoryNotFoundException + * @throws TestFileNotFoundException + */ + public function build(Configuration $configuration): TestSuite + { + if ($configuration->hasCliArguments()) { + $arguments = []; + + foreach ($configuration->cliArguments() as $cliArgument) { + $argument = realpath($cliArgument); + + if (!$argument) { + throw new TestFileNotFoundException($cliArgument); + } + + $arguments[] = $argument; + } + + if (count($arguments) === 1) { + $testSuite = $this->testSuiteFromPath( + $arguments[0], + $configuration->testSuffixes(), + ); + } else { + $testSuite = $this->testSuiteFromPathList( + $arguments, + $configuration->testSuffixes(), + ); + } + } + + if (!isset($testSuite)) { + $xmlConfigurationFile = $configuration->hasConfigurationFile() ? $configuration->configurationFile() : 'Root Test Suite'; + + assert(!empty($xmlConfigurationFile)); + + $testSuite = (new TestSuiteMapper)->map( + $xmlConfigurationFile, + $configuration->testSuite(), + $configuration->includeTestSuite(), + $configuration->excludeTestSuite(), + ); + } + + EventFacade::emitter()->testSuiteLoaded(\PHPUnit\Event\TestSuite\TestSuiteBuilder::from($testSuite)); + + return $testSuite; + } + + /** + * @psalm-param non-empty-string $path + * @psalm-param list $suffixes + * @psalm-param ?TestSuite $suite + * + * @throws \PHPUnit\Framework\Exception + */ + private function testSuiteFromPath(string $path, array $suffixes, ?TestSuite $suite = null): TestSuite + { + if (str_ends_with($path, '.phpt') && is_file($path)) { + $suite = $suite ?: TestSuite::empty($path); + $suite->addTestFile($path); + + return $suite; + } + + if (is_dir($path)) { + $files = (new FileIteratorFacade)->getFilesAsArray($path, $suffixes); + + $suite = $suite ?: TestSuite::empty('CLI Arguments'); + $suite->addTestFiles($files); + + return $suite; + } + + try { + $testClass = (new TestSuiteLoader)->load($path); + } catch (Exception $e) { + print $e->getMessage() . PHP_EOL; + + exit(1); + } + + if (!$suite) { + return TestSuite::fromClassReflector($testClass); + } + + $suite->addTestSuite($testClass); + + return $suite; + } + + /** + * @psalm-param list $paths + * @psalm-param list $suffixes + * + * @throws \PHPUnit\Framework\Exception + */ + private function testSuiteFromPathList(array $paths, array $suffixes): TestSuite + { + $suite = TestSuite::empty('CLI Arguments'); + + foreach ($paths as $path) { + $this->testSuiteFromPath($path, $suffixes, $suite); + } + + return $suite; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php new file mode 100644 index 000000000..44a4a83a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Constant.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Constant +{ + private readonly string $name; + private readonly bool|string $value; + + public function __construct(string $name, bool|string $value) + { + $this->name = $name; + $this->value = $value; + } + + public function name(): string + { + return $this->name; + } + + public function value(): bool|string + { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.php new file mode 100644 index 000000000..f93ab5f2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollection.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 PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class ConstantCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $constants; + + /** + * @psalm-param list $constants + */ + public static function fromArray(array $constants): self + { + return new self(...$constants); + } + + private function __construct(Constant ...$constants) + { + $this->constants = $constants; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->constants; + } + + public function count(): int + { + return count($this->constants); + } + + public function getIterator(): ConstantCollectionIterator + { + return new ConstantCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php new file mode 100644 index 000000000..acb4c8b90 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class ConstantCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $constants; + private int $position = 0; + + public function __construct(ConstantCollection $constants) + { + $this->constants = $constants->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->constants); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Constant + { + return $this->constants[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php new file mode 100644 index 000000000..4158b656b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Directory.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Directory +{ + private readonly string $path; + + public function __construct(string $path) + { + $this->path = $path; + } + + public function path(): string + { + return $this->path; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php new file mode 100644 index 000000000..618adcc12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class DirectoryCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $directories; + + /** + * @psalm-param list $directories + */ + public static function fromArray(array $directories): self + { + return new self(...$directories); + } + + private function __construct(Directory ...$directories) + { + $this->directories = $directories; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->directories; + } + + public function count(): int + { + return count($this->directories); + } + + public function getIterator(): DirectoryCollectionIterator + { + return new DirectoryCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php new file mode 100644 index 000000000..4e5655ceb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class DirectoryCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $directories; + private int $position = 0; + + public function __construct(DirectoryCollection $directories) + { + $this->directories = $directories->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->directories); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Directory + { + return $this->directories[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php new file mode 100644 index 000000000..c68934223 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class ExtensionBootstrap +{ + /** + * @psalm-var class-string + */ + private readonly string $className; + + /** + * @psalm-var array + */ + private readonly array $parameters; + + /** + * @psalm-param class-string $className + * @psalm-param array $parameters + */ + public function __construct(string $className, array $parameters) + { + $this->className = $className; + $this->parameters = $parameters; + } + + /** + * @psalm-return class-string + */ + public function className(): string + { + return $this->className; + } + + /** + * @psalm-return array + */ + public function parameters(): array + { + return $this->parameters; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php new file mode 100644 index 000000000..2a1443782 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class ExtensionBootstrapCollection implements IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $extensionBootstraps; + + /** + * @psalm-param list $extensionBootstraps + */ + public static function fromArray(array $extensionBootstraps): self + { + return new self(...$extensionBootstraps); + } + + private function __construct(ExtensionBootstrap ...$extensionBootstraps) + { + $this->extensionBootstraps = $extensionBootstraps; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->extensionBootstraps; + } + + public function getIterator(): ExtensionBootstrapCollectionIterator + { + return new ExtensionBootstrapCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php new file mode 100644 index 000000000..0de1711fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class ExtensionBootstrapCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $extensionBootstraps; + private int $position = 0; + + public function __construct(ExtensionBootstrapCollection $extensionBootstraps) + { + $this->extensionBootstraps = $extensionBootstraps->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->extensionBootstraps); + } + + public function key(): int + { + return $this->position; + } + + public function current(): ExtensionBootstrap + { + return $this->extensionBootstraps[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/File.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/File.php new file mode 100644 index 000000000..035b9a350 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/File.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 PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class File +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $path; + + /** + * @psalm-param non-empty-string $path + */ + public function __construct(string $path) + { + $this->path = $path; + } + + /** + * @psalm-return non-empty-string + */ + public function path(): string + { + return $this->path; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php new file mode 100644 index 000000000..ee730aaa5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class FileCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $files; + + /** + * @psalm-param list $files + */ + public static function fromArray(array $files): self + { + return new self(...$files); + } + + private function __construct(File ...$files) + { + $this->files = $files; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->files; + } + + public function count(): int + { + return count($this->files); + } + + public function notEmpty(): bool + { + return !empty($this->files); + } + + public function getIterator(): FileCollectionIterator + { + return new FileCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php new file mode 100644 index 000000000..9627fca66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class FileCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $files; + private int $position = 0; + + public function __construct(FileCollection $files) + { + $this->files = $files->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->files); + } + + public function key(): int + { + return $this->position; + } + + public function current(): File + { + return $this->files[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php new file mode 100644 index 000000000..d66f95110 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectory.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class FilterDirectory +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $path; + private readonly string $prefix; + private readonly string $suffix; + + /** + * @psalm-param non-empty-string $path + */ + public function __construct(string $path, string $prefix, string $suffix) + { + $this->path = $path; + $this->prefix = $prefix; + $this->suffix = $suffix; + } + + /** + * @psalm-return non-empty-string + */ + public function path(): string + { + return $this->path; + } + + public function prefix(): string + { + return $this->prefix; + } + + public function suffix(): string + { + return $this->suffix; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php new file mode 100644 index 000000000..53b474d8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class FilterDirectoryCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $directories; + + /** + * @psalm-param list $directories + */ + public static function fromArray(array $directories): self + { + return new self(...$directories); + } + + private function __construct(FilterDirectory ...$directories) + { + $this->directories = $directories; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->directories; + } + + public function count(): int + { + return count($this->directories); + } + + public function notEmpty(): bool + { + return !empty($this->directories); + } + + public function getIterator(): FilterDirectoryCollectionIterator + { + return new FilterDirectoryCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php new file mode 100644 index 000000000..3d1459815 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class FilterDirectoryCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $directories; + private int $position = 0; + + public function __construct(FilterDirectoryCollection $directories) + { + $this->directories = $directories->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->directories); + } + + public function key(): int + { + return $this->position; + } + + public function current(): FilterDirectory + { + return $this->directories[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php new file mode 100644 index 000000000..1ee1baacb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Group.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Group +{ + private readonly string $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function name(): string + { + return $this->name; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php new file mode 100644 index 000000000..eb581de59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollection.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class GroupCollection implements IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $groups; + + /** + * @psalm-param list $groups + */ + public static function fromArray(array $groups): self + { + return new self(...$groups); + } + + private function __construct(Group ...$groups) + { + $this->groups = $groups; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->groups; + } + + /** + * @psalm-return list + */ + public function asArrayOfStrings(): array + { + $result = []; + + foreach ($this->groups as $group) { + $result[] = $group->name(); + } + + return $result; + } + + public function isEmpty(): bool + { + return empty($this->groups); + } + + public function getIterator(): GroupCollectionIterator + { + return new GroupCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php new file mode 100644 index 000000000..9b4795ac2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class GroupCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $groups; + private int $position = 0; + + public function __construct(GroupCollection $groups) + { + $this->groups = $groups->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->groups); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Group + { + return $this->groups[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php new file mode 100644 index 000000000..aa88d7318 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSetting.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class IniSetting +{ + private readonly string $name; + private readonly string $value; + + public function __construct(string $name, string $value) + { + $this->name = $name; + $this->value = $value; + } + + public function name(): string + { + return $this->name; + } + + public function value(): string + { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php new file mode 100644 index 000000000..2d405b4af --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollection.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 PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class IniSettingCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $iniSettings; + + /** + * @psalm-param list $iniSettings + */ + public static function fromArray(array $iniSettings): self + { + return new self(...$iniSettings); + } + + private function __construct(IniSetting ...$iniSettings) + { + $this->iniSettings = $iniSettings; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->iniSettings; + } + + public function count(): int + { + return count($this->iniSettings); + } + + public function getIterator(): IniSettingCollectionIterator + { + return new IniSettingCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php new file mode 100644 index 000000000..196358c09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class IniSettingCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $iniSettings; + private int $position = 0; + + public function __construct(IniSettingCollection $iniSettings) + { + $this->iniSettings = $iniSettings->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->iniSettings); + } + + public function key(): int + { + return $this->position; + } + + public function current(): IniSetting + { + return $this->iniSettings[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php new file mode 100644 index 000000000..17d084842 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Php.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Php +{ + private readonly DirectoryCollection $includePaths; + private readonly IniSettingCollection $iniSettings; + private readonly ConstantCollection $constants; + private readonly VariableCollection $globalVariables; + private readonly VariableCollection $envVariables; + private readonly VariableCollection $postVariables; + private readonly VariableCollection $getVariables; + private readonly VariableCollection $cookieVariables; + private readonly VariableCollection $serverVariables; + private readonly VariableCollection $filesVariables; + private readonly VariableCollection $requestVariables; + + public function __construct(DirectoryCollection $includePaths, IniSettingCollection $iniSettings, ConstantCollection $constants, VariableCollection $globalVariables, VariableCollection $envVariables, VariableCollection $postVariables, VariableCollection $getVariables, VariableCollection $cookieVariables, VariableCollection $serverVariables, VariableCollection $filesVariables, VariableCollection $requestVariables) + { + $this->includePaths = $includePaths; + $this->iniSettings = $iniSettings; + $this->constants = $constants; + $this->globalVariables = $globalVariables; + $this->envVariables = $envVariables; + $this->postVariables = $postVariables; + $this->getVariables = $getVariables; + $this->cookieVariables = $cookieVariables; + $this->serverVariables = $serverVariables; + $this->filesVariables = $filesVariables; + $this->requestVariables = $requestVariables; + } + + public function includePaths(): DirectoryCollection + { + return $this->includePaths; + } + + public function iniSettings(): IniSettingCollection + { + return $this->iniSettings; + } + + public function constants(): ConstantCollection + { + return $this->constants; + } + + public function globalVariables(): VariableCollection + { + return $this->globalVariables; + } + + public function envVariables(): VariableCollection + { + return $this->envVariables; + } + + public function postVariables(): VariableCollection + { + return $this->postVariables; + } + + public function getVariables(): VariableCollection + { + return $this->getVariables; + } + + public function cookieVariables(): VariableCollection + { + return $this->cookieVariables; + } + + public function serverVariables(): VariableCollection + { + return $this->serverVariables; + } + + public function filesVariables(): VariableCollection + { + return $this->filesVariables; + } + + public function requestVariables(): VariableCollection + { + return $this->requestVariables; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php new file mode 100644 index 000000000..b22edba85 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Source.php @@ -0,0 +1,166 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Source +{ + /** + * @psalm-var non-empty-string + */ + private readonly ?string $baseline; + private readonly bool $ignoreBaseline; + private readonly FilterDirectoryCollection $includeDirectories; + private readonly FileCollection $includeFiles; + private readonly FilterDirectoryCollection $excludeDirectories; + private readonly FileCollection $excludeFiles; + private readonly bool $restrictDeprecations; + private readonly bool $restrictNotices; + private readonly bool $restrictWarnings; + private readonly bool $ignoreSuppressionOfDeprecations; + private readonly bool $ignoreSuppressionOfPhpDeprecations; + private readonly bool $ignoreSuppressionOfErrors; + private readonly bool $ignoreSuppressionOfNotices; + private readonly bool $ignoreSuppressionOfPhpNotices; + private readonly bool $ignoreSuppressionOfWarnings; + private readonly bool $ignoreSuppressionOfPhpWarnings; + + /** + * @psalm-param non-empty-string $baseline + */ + public function __construct(?string $baseline, bool $ignoreBaseline, FilterDirectoryCollection $includeDirectories, FileCollection $includeFiles, FilterDirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $restrictDeprecations, bool $restrictNotices, bool $restrictWarnings, bool $ignoreSuppressionOfDeprecations, bool $ignoreSuppressionOfPhpDeprecations, bool $ignoreSuppressionOfErrors, bool $ignoreSuppressionOfNotices, bool $ignoreSuppressionOfPhpNotices, bool $ignoreSuppressionOfWarnings, bool $ignoreSuppressionOfPhpWarnings) + { + $this->baseline = $baseline; + $this->ignoreBaseline = $ignoreBaseline; + $this->includeDirectories = $includeDirectories; + $this->includeFiles = $includeFiles; + $this->excludeDirectories = $excludeDirectories; + $this->excludeFiles = $excludeFiles; + $this->restrictDeprecations = $restrictDeprecations; + $this->restrictNotices = $restrictNotices; + $this->restrictWarnings = $restrictWarnings; + $this->ignoreSuppressionOfDeprecations = $ignoreSuppressionOfDeprecations; + $this->ignoreSuppressionOfPhpDeprecations = $ignoreSuppressionOfPhpDeprecations; + $this->ignoreSuppressionOfErrors = $ignoreSuppressionOfErrors; + $this->ignoreSuppressionOfNotices = $ignoreSuppressionOfNotices; + $this->ignoreSuppressionOfPhpNotices = $ignoreSuppressionOfPhpNotices; + $this->ignoreSuppressionOfWarnings = $ignoreSuppressionOfWarnings; + $this->ignoreSuppressionOfPhpWarnings = $ignoreSuppressionOfPhpWarnings; + } + + /** + * @psalm-assert-if-true !null $this->baseline + */ + public function useBaseline(): bool + { + return $this->hasBaseline() && !$this->ignoreBaseline; + } + + /** + * @psalm-assert-if-true !null $this->baseline + */ + public function hasBaseline(): bool + { + return $this->baseline !== null; + } + + /** + * @psalm-return non-empty-string + * + * @throws NoBaselineException + */ + public function baseline(): string + { + if (!$this->hasBaseline()) { + throw new NoBaselineException; + } + + return $this->baseline; + } + + public function includeDirectories(): FilterDirectoryCollection + { + return $this->includeDirectories; + } + + public function includeFiles(): FileCollection + { + return $this->includeFiles; + } + + public function excludeDirectories(): FilterDirectoryCollection + { + return $this->excludeDirectories; + } + + public function excludeFiles(): FileCollection + { + return $this->excludeFiles; + } + + public function notEmpty(): bool + { + return $this->includeDirectories->notEmpty() || $this->includeFiles->notEmpty(); + } + + public function restrictDeprecations(): bool + { + return $this->restrictDeprecations; + } + + public function restrictNotices(): bool + { + return $this->restrictNotices; + } + + public function restrictWarnings(): bool + { + return $this->restrictWarnings; + } + + public function ignoreSuppressionOfDeprecations(): bool + { + return $this->ignoreSuppressionOfDeprecations; + } + + public function ignoreSuppressionOfPhpDeprecations(): bool + { + return $this->ignoreSuppressionOfPhpDeprecations; + } + + public function ignoreSuppressionOfErrors(): bool + { + return $this->ignoreSuppressionOfErrors; + } + + public function ignoreSuppressionOfNotices(): bool + { + return $this->ignoreSuppressionOfNotices; + } + + public function ignoreSuppressionOfPhpNotices(): bool + { + return $this->ignoreSuppressionOfPhpNotices; + } + + public function ignoreSuppressionOfWarnings(): bool + { + return $this->ignoreSuppressionOfWarnings; + } + + public function ignoreSuppressionOfPhpWarnings(): bool + { + return $this->ignoreSuppressionOfPhpWarnings; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php new file mode 100644 index 000000000..d19e8859e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectory.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TestDirectory +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $path; + private readonly string $prefix; + private readonly string $suffix; + private readonly string $phpVersion; + private readonly VersionComparisonOperator $phpVersionOperator; + + /** + * @psalm-param non-empty-string $path + */ + public function __construct(string $path, string $prefix, string $suffix, string $phpVersion, VersionComparisonOperator $phpVersionOperator) + { + $this->path = $path; + $this->prefix = $prefix; + $this->suffix = $suffix; + $this->phpVersion = $phpVersion; + $this->phpVersionOperator = $phpVersionOperator; + } + + /** + * @psalm-return non-empty-string + */ + public function path(): string + { + return $this->path; + } + + public function prefix(): string + { + return $this->prefix; + } + + public function suffix(): string + { + return $this->suffix; + } + + public function phpVersion(): string + { + return $this->phpVersion; + } + + public function phpVersionOperator(): VersionComparisonOperator + { + return $this->phpVersionOperator; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php new file mode 100644 index 000000000..a3667a8e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class TestDirectoryCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $directories; + + /** + * @psalm-param list $directories + */ + public static function fromArray(array $directories): self + { + return new self(...$directories); + } + + private function __construct(TestDirectory ...$directories) + { + $this->directories = $directories; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->directories; + } + + public function count(): int + { + return count($this->directories); + } + + public function getIterator(): TestDirectoryCollectionIterator + { + return new TestDirectoryCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php new file mode 100644 index 000000000..157c49830 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class TestDirectoryCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $directories; + private int $position = 0; + + public function __construct(TestDirectoryCollection $directories) + { + $this->directories = $directories->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->directories); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestDirectory + { + return $this->directories[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.php new file mode 100644 index 000000000..f0a810106 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFile.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 PHPUnit\TextUI\Configuration; + +use PHPUnit\Util\VersionComparisonOperator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TestFile +{ + private readonly string $path; + private readonly string $phpVersion; + private readonly VersionComparisonOperator $phpVersionOperator; + + public function __construct(string $path, string $phpVersion, VersionComparisonOperator $phpVersionOperator) + { + $this->path = $path; + $this->phpVersion = $phpVersion; + $this->phpVersionOperator = $phpVersionOperator; + } + + public function path(): string + { + return $this->path; + } + + public function phpVersion(): string + { + return $this->phpVersion; + } + + public function phpVersionOperator(): VersionComparisonOperator + { + return $this->phpVersionOperator; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php new file mode 100644 index 000000000..4582664b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class TestFileCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $files; + + /** + * @psalm-param list $files + */ + public static function fromArray(array $files): self + { + return new self(...$files); + } + + private function __construct(TestFile ...$files) + { + $this->files = $files; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->files; + } + + public function count(): int + { + return count($this->files); + } + + public function getIterator(): TestFileCollectionIterator + { + return new TestFileCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php new file mode 100644 index 000000000..4efdfdd36 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class TestFileCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $files; + private int $position = 0; + + public function __construct(TestFileCollection $files) + { + $this->files = $files->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->files); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestFile + { + return $this->files[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.php new file mode 100644 index 000000000..7105242bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuite.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 PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TestSuite +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $name; + private readonly TestDirectoryCollection $directories; + private readonly TestFileCollection $files; + private readonly FileCollection $exclude; + + /** + * @psalm-param non-empty-string $name + */ + public function __construct(string $name, TestDirectoryCollection $directories, TestFileCollection $files, FileCollection $exclude) + { + $this->name = $name; + $this->directories = $directories; + $this->files = $files; + $this->exclude = $exclude; + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->name; + } + + public function directories(): TestDirectoryCollection + { + return $this->directories; + } + + public function files(): TestFileCollection + { + return $this->files; + } + + public function exclude(): FileCollection + { + return $this->exclude; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php new file mode 100644 index 000000000..493ef0aa9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class TestSuiteCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $testSuites; + + /** + * @psalm-param list $testSuites + */ + public static function fromArray(array $testSuites): self + { + return new self(...$testSuites); + } + + private function __construct(TestSuite ...$testSuites) + { + $this->testSuites = $testSuites; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->testSuites; + } + + public function count(): int + { + return count($this->testSuites); + } + + public function getIterator(): TestSuiteCollectionIterator + { + return new TestSuiteCollectionIterator($this); + } + + public function isEmpty(): bool + { + return $this->count() === 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php new file mode 100644 index 000000000..89d35d9bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class TestSuiteCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $testSuites; + private int $position = 0; + + public function __construct(TestSuiteCollection $testSuites) + { + $this->testSuites = $testSuites->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->testSuites); + } + + public function key(): int + { + return $this->position; + } + + public function current(): TestSuite + { + return $this->testSuites[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.php new file mode 100644 index 000000000..edf41d94d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/Variable.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 PHPUnit\TextUI\Configuration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Variable +{ + private readonly string $name; + private readonly mixed $value; + private readonly bool $force; + + public function __construct(string $name, mixed $value, bool $force) + { + $this->name = $name; + $this->value = $value; + $this->force = $force; + } + + public function name(): string + { + return $this->name; + } + + public function value(): mixed + { + return $this->value; + } + + public function force(): bool + { + return $this->force; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.php new file mode 100644 index 000000000..9c3dc459c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollection.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 PHPUnit\TextUI\Configuration; + +use function count; +use Countable; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + * + * @template-implements IteratorAggregate + */ +final class VariableCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $variables; + + /** + * @psalm-param list $variables + */ + public static function fromArray(array $variables): self + { + return new self(...$variables); + } + + private function __construct(Variable ...$variables) + { + $this->variables = $variables; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->variables; + } + + public function count(): int + { + return count($this->variables); + } + + public function getIterator(): VariableCollectionIterator + { + return new VariableCollectionIterator($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php new file mode 100644 index 000000000..e9d6a3556 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Configuration; + +use function count; +use function iterator_count; +use Countable; +use Iterator; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @template-implements Iterator + */ +final class VariableCollectionIterator implements Countable, Iterator +{ + /** + * @psalm-var list + */ + private readonly array $variables; + private int $position = 0; + + public function __construct(VariableCollection $variables) + { + $this->variables = $variables->asArray(); + } + + public function count(): int + { + return iterator_count($this); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return $this->position < count($this->variables); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Variable + { + return $this->variables[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php new file mode 100644 index 000000000..4450970fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php @@ -0,0 +1,295 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage; + +use function count; +use PHPUnit\TextUI\Configuration\Directory; +use PHPUnit\TextUI\Configuration\FileCollection; +use PHPUnit\TextUI\Configuration\FilterDirectoryCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml; +use PHPUnit\TextUI\XmlConfiguration\Exception; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class CodeCoverage +{ + private readonly ?Directory $cacheDirectory; + private readonly FilterDirectoryCollection $directories; + private readonly FileCollection $files; + private readonly FilterDirectoryCollection $excludeDirectories; + private readonly FileCollection $excludeFiles; + private readonly bool $pathCoverage; + private readonly bool $includeUncoveredFiles; + private readonly bool $ignoreDeprecatedCodeUnits; + private readonly bool $disableCodeCoverageIgnore; + private readonly ?Clover $clover; + private readonly ?Cobertura $cobertura; + private readonly ?Crap4j $crap4j; + private readonly ?Html $html; + private readonly ?Php $php; + private readonly ?Text $text; + private readonly ?Xml $xml; + + public function __construct(?Directory $cacheDirectory, FilterDirectoryCollection $directories, FileCollection $files, FilterDirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $pathCoverage, bool $includeUncoveredFiles, bool $ignoreDeprecatedCodeUnits, bool $disableCodeCoverageIgnore, ?Clover $clover, ?Cobertura $cobertura, ?Crap4j $crap4j, ?Html $html, ?Php $php, ?Text $text, ?Xml $xml) + { + $this->cacheDirectory = $cacheDirectory; + $this->directories = $directories; + $this->files = $files; + $this->excludeDirectories = $excludeDirectories; + $this->excludeFiles = $excludeFiles; + $this->pathCoverage = $pathCoverage; + $this->includeUncoveredFiles = $includeUncoveredFiles; + $this->ignoreDeprecatedCodeUnits = $ignoreDeprecatedCodeUnits; + $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; + $this->clover = $clover; + $this->cobertura = $cobertura; + $this->crap4j = $crap4j; + $this->html = $html; + $this->php = $php; + $this->text = $text; + $this->xml = $xml; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + * + * @deprecated + */ + public function hasCacheDirectory(): bool + { + return $this->cacheDirectory !== null; + } + + /** + * @throws Exception + * + * @deprecated + */ + public function cacheDirectory(): Directory + { + if (!$this->hasCacheDirectory()) { + throw new Exception( + 'No cache directory has been configured', + ); + } + + return $this->cacheDirectory; + } + + public function hasNonEmptyListOfFilesToBeIncludedInCodeCoverageReport(): bool + { + return count($this->directories) > 0 || count($this->files) > 0; + } + + public function directories(): FilterDirectoryCollection + { + return $this->directories; + } + + public function files(): FileCollection + { + return $this->files; + } + + public function excludeDirectories(): FilterDirectoryCollection + { + return $this->excludeDirectories; + } + + public function excludeFiles(): FileCollection + { + return $this->excludeFiles; + } + + public function pathCoverage(): bool + { + return $this->pathCoverage; + } + + public function includeUncoveredFiles(): bool + { + return $this->includeUncoveredFiles; + } + + public function ignoreDeprecatedCodeUnits(): bool + { + return $this->ignoreDeprecatedCodeUnits; + } + + public function disableCodeCoverageIgnore(): bool + { + return $this->disableCodeCoverageIgnore; + } + + /** + * @psalm-assert-if-true !null $this->clover + */ + public function hasClover(): bool + { + return $this->clover !== null; + } + + /** + * @throws Exception + */ + public function clover(): Clover + { + if (!$this->hasClover()) { + throw new Exception( + 'Code Coverage report "Clover XML" has not been configured', + ); + } + + return $this->clover; + } + + /** + * @psalm-assert-if-true !null $this->cobertura + */ + public function hasCobertura(): bool + { + return $this->cobertura !== null; + } + + /** + * @throws Exception + */ + public function cobertura(): Cobertura + { + if (!$this->hasCobertura()) { + throw new Exception( + 'Code Coverage report "Cobertura XML" has not been configured', + ); + } + + return $this->cobertura; + } + + /** + * @psalm-assert-if-true !null $this->crap4j + */ + public function hasCrap4j(): bool + { + return $this->crap4j !== null; + } + + /** + * @throws Exception + */ + public function crap4j(): Crap4j + { + if (!$this->hasCrap4j()) { + throw new Exception( + 'Code Coverage report "Crap4J" has not been configured', + ); + } + + return $this->crap4j; + } + + /** + * @psalm-assert-if-true !null $this->html + */ + public function hasHtml(): bool + { + return $this->html !== null; + } + + /** + * @throws Exception + */ + public function html(): Html + { + if (!$this->hasHtml()) { + throw new Exception( + 'Code Coverage report "HTML" has not been configured', + ); + } + + return $this->html; + } + + /** + * @psalm-assert-if-true !null $this->php + */ + public function hasPhp(): bool + { + return $this->php !== null; + } + + /** + * @throws Exception + */ + public function php(): Php + { + if (!$this->hasPhp()) { + throw new Exception( + 'Code Coverage report "PHP" has not been configured', + ); + } + + return $this->php; + } + + /** + * @psalm-assert-if-true !null $this->text + */ + public function hasText(): bool + { + return $this->text !== null; + } + + /** + * @throws Exception + */ + public function text(): Text + { + if (!$this->hasText()) { + throw new Exception( + 'Code Coverage report "Text" has not been configured', + ); + } + + return $this->text; + } + + /** + * @psalm-assert-if-true !null $this->xml + */ + public function hasXml(): bool + { + return $this->xml !== null; + } + + /** + * @throws Exception + */ + public function xml(): Xml + { + if (!$this->hasXml()) { + throw new Exception( + 'Code Coverage report "XML" has not been configured', + ); + } + + return $this->xml; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php new file mode 100644 index 000000000..a815dc463 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Clover +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php new file mode 100644 index 000000000..c8b560d75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Cobertura +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php new file mode 100644 index 000000000..eff20d6b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.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 PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Crap4j +{ + private readonly File $target; + private readonly int $threshold; + + public function __construct(File $target, int $threshold) + { + $this->target = $target; + $this->threshold = $threshold; + } + + public function target(): File + { + return $this->target; + } + + public function threshold(): int + { + return $this->threshold; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php new file mode 100644 index 000000000..db6fa53dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\Directory; +use PHPUnit\TextUI\Configuration\NoCustomCssFileException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Html +{ + private readonly Directory $target; + private readonly int $lowUpperBound; + private readonly int $highLowerBound; + private readonly string $colorSuccessLow; + private readonly string $colorSuccessMedium; + private readonly string $colorSuccessHigh; + private readonly string $colorWarning; + private readonly string $colorDanger; + private readonly ?string $customCssFile; + + public function __construct(Directory $target, int $lowUpperBound, int $highLowerBound, string $colorSuccessLow, string $colorSuccessMedium, string $colorSuccessHigh, string $colorWarning, string $colorDanger, ?string $customCssFile) + { + $this->target = $target; + $this->lowUpperBound = $lowUpperBound; + $this->highLowerBound = $highLowerBound; + $this->colorSuccessLow = $colorSuccessLow; + $this->colorSuccessMedium = $colorSuccessMedium; + $this->colorSuccessHigh = $colorSuccessHigh; + $this->colorWarning = $colorWarning; + $this->colorDanger = $colorDanger; + $this->customCssFile = $customCssFile; + } + + public function target(): Directory + { + return $this->target; + } + + public function lowUpperBound(): int + { + return $this->lowUpperBound; + } + + public function highLowerBound(): int + { + return $this->highLowerBound; + } + + public function colorSuccessLow(): string + { + return $this->colorSuccessLow; + } + + public function colorSuccessMedium(): string + { + return $this->colorSuccessMedium; + } + + public function colorSuccessHigh(): string + { + return $this->colorSuccessHigh; + } + + public function colorWarning(): string + { + return $this->colorWarning; + } + + public function colorDanger(): string + { + return $this->colorDanger; + } + + /** + * @psalm-assert-if-true !null $this->customCssFile + */ + public function hasCustomCssFile(): bool + { + return $this->customCssFile !== null; + } + + /** + * @throws NoCustomCssFileException + */ + public function customCssFile(): string + { + if (!$this->hasCustomCssFile()) { + throw new NoCustomCssFileException; + } + + return $this->customCssFile; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php new file mode 100644 index 000000000..39a3762d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Php +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php new file mode 100644 index 000000000..6ff3c8ce8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.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 PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Text +{ + private readonly File $target; + private readonly bool $showUncoveredFiles; + private readonly bool $showOnlySummary; + + public function __construct(File $target, bool $showUncoveredFiles, bool $showOnlySummary) + { + $this->target = $target; + $this->showUncoveredFiles = $showUncoveredFiles; + $this->showOnlySummary = $showOnlySummary; + } + + public function target(): File + { + return $this->target; + } + + public function showUncoveredFiles(): bool + { + return $this->showUncoveredFiles; + } + + public function showOnlySummary(): bool + { + return $this->showOnlySummary; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php new file mode 100644 index 000000000..09dddc0c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; + +use PHPUnit\TextUI\Configuration\Directory; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Xml +{ + private readonly Directory $target; + + public function __construct(Directory $target) + { + $this->target = $target; + } + + public function target(): Directory + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php new file mode 100644 index 000000000..d9a74fa87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Configuration.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; +use PHPUnit\TextUI\Configuration\Php; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\TestSuiteCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; +use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +abstract class Configuration +{ + private readonly ExtensionBootstrapCollection $extensions; + private readonly Source $source; + private readonly CodeCoverage $codeCoverage; + private readonly Groups $groups; + private readonly Logging $logging; + private readonly Php $php; + private readonly PHPUnit $phpunit; + private readonly TestSuiteCollection $testSuite; + + public function __construct(ExtensionBootstrapCollection $extensions, Source $source, CodeCoverage $codeCoverage, Groups $groups, Logging $logging, Php $php, PHPUnit $phpunit, TestSuiteCollection $testSuite) + { + $this->extensions = $extensions; + $this->source = $source; + $this->codeCoverage = $codeCoverage; + $this->groups = $groups; + $this->logging = $logging; + $this->php = $php; + $this->phpunit = $phpunit; + $this->testSuite = $testSuite; + } + + public function extensions(): ExtensionBootstrapCollection + { + return $this->extensions; + } + + public function source(): Source + { + return $this->source; + } + + public function codeCoverage(): CodeCoverage + { + return $this->codeCoverage; + } + + public function groups(): Groups + { + return $this->groups; + } + + public function logging(): Logging + { + return $this->logging; + } + + public function php(): Php + { + return $this->php; + } + + public function phpunit(): PHPUnit + { + return $this->phpunit; + } + + public function testSuite(): TestSuiteCollection + { + return $this->testSuite; + } + + /** + * @psalm-assert-if-true DefaultConfiguration $this + */ + public function isDefault(): bool + { + return false; + } + + /** + * @psalm-assert-if-true LoadedFromFileConfiguration $this + */ + public function wasLoadedFromFile(): bool + { + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php new file mode 100644 index 000000000..7ec3a168f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\TextUI\Configuration\ConstantCollection; +use PHPUnit\TextUI\Configuration\DirectoryCollection; +use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; +use PHPUnit\TextUI\Configuration\FileCollection; +use PHPUnit\TextUI\Configuration\FilterDirectoryCollection as CodeCoverageFilterDirectoryCollection; +use PHPUnit\TextUI\Configuration\GroupCollection; +use PHPUnit\TextUI\Configuration\IniSettingCollection; +use PHPUnit\TextUI\Configuration\Php; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\TestSuiteCollection; +use PHPUnit\TextUI\Configuration\VariableCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; +use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class DefaultConfiguration extends Configuration +{ + public static function create(): self + { + return new self( + ExtensionBootstrapCollection::fromArray([]), + new Source( + null, + false, + CodeCoverageFilterDirectoryCollection::fromArray([]), + FileCollection::fromArray([]), + CodeCoverageFilterDirectoryCollection::fromArray([]), + FileCollection::fromArray([]), + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + ), + new CodeCoverage( + null, + CodeCoverageFilterDirectoryCollection::fromArray([]), + FileCollection::fromArray([]), + CodeCoverageFilterDirectoryCollection::fromArray([]), + FileCollection::fromArray([]), + false, + true, + false, + false, + null, + null, + null, + null, + null, + null, + null, + ), + new Groups( + GroupCollection::fromArray([]), + GroupCollection::fromArray([]), + ), + new Logging( + null, + null, + null, + null, + ), + new Php( + DirectoryCollection::fromArray([]), + IniSettingCollection::fromArray([]), + ConstantCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + VariableCollection::fromArray([]), + ), + new PHPUnit( + null, + true, + null, + 80, + \PHPUnit\TextUI\Configuration\Configuration::COLOR_DEFAULT, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + null, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + null, + false, + false, + true, + false, + false, + 1, + 1, + 10, + 60, + null, + TestSuiteSorter::ORDER_DEFAULT, + true, + false, + false, + false, + false, + false, + false, + 100, + ), + TestSuiteCollection::fromArray([]), + ); + } + + public function isDefault(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php new file mode 100644 index 000000000..60c3c9acc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Exception extends RuntimeException implements \PHPUnit\Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php new file mode 100644 index 000000000..865fb5d48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Generator.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function str_replace; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Generator +{ + /** + * @var string + */ + private const TEMPLATE = <<<'EOT' + + + + + {tests_directory} + + + + + + {src_directory} + + + + +EOT; + + public function generateDefaultConfiguration(string $phpunitVersion, string $bootstrapScript, string $testsDirectory, string $srcDirectory, string $cacheDirectory): string + { + return str_replace( + [ + '{phpunit_version}', + '{bootstrap_script}', + '{tests_directory}', + '{src_directory}', + '{cache_directory}', + ], + [ + $phpunitVersion, + $bootstrapScript, + $testsDirectory, + $srcDirectory, + $cacheDirectory, + ], + self::TEMPLATE, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php new file mode 100644 index 000000000..d89908caf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Groups.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\TextUI\Configuration\GroupCollection; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Groups +{ + private readonly GroupCollection $include; + private readonly GroupCollection $exclude; + + public function __construct(GroupCollection $include, GroupCollection $exclude) + { + $this->include = $include; + $this->exclude = $exclude; + } + + public function hasInclude(): bool + { + return !$this->include->isEmpty(); + } + + public function include(): GroupCollection + { + return $this->include; + } + + public function hasExclude(): bool + { + return !$this->exclude->isEmpty(); + } + + public function exclude(): GroupCollection + { + return $this->exclude; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php new file mode 100644 index 000000000..31106ed98 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; +use PHPUnit\TextUI\Configuration\Php; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\TestSuiteCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; +use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class LoadedFromFileConfiguration extends Configuration +{ + private readonly string $filename; + private readonly ValidationResult $validationResult; + + public function __construct(string $filename, ValidationResult $validationResult, ExtensionBootstrapCollection $extensions, Source $source, CodeCoverage $codeCoverage, Groups $groups, Logging $logging, Php $php, PHPUnit $phpunit, TestSuiteCollection $testSuite) + { + $this->filename = $filename; + $this->validationResult = $validationResult; + + parent::__construct( + $extensions, + $source, + $codeCoverage, + $groups, + $logging, + $php, + $phpunit, + $testSuite, + ); + } + + public function filename(): string + { + return $this->filename; + } + + public function hasValidationErrors(): bool + { + return $this->validationResult->hasValidationErrors(); + } + + public function validationErrors(): string + { + return $this->validationResult->asString(); + } + + public function wasLoadedFromFile(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php new file mode 100644 index 000000000..228dc785d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Loader.php @@ -0,0 +1,1049 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use const DIRECTORY_SEPARATOR; +use const PHP_VERSION; +use function assert; +use function defined; +use function dirname; +use function explode; +use function is_numeric; +use function preg_match; +use function realpath; +use function str_contains; +use function str_starts_with; +use function strlen; +use function strtolower; +use function substr; +use function trim; +use DOMDocument; +use DOMElement; +use DOMNode; +use DOMXPath; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\Runner\Version; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\Constant; +use PHPUnit\TextUI\Configuration\ConstantCollection; +use PHPUnit\TextUI\Configuration\Directory; +use PHPUnit\TextUI\Configuration\DirectoryCollection; +use PHPUnit\TextUI\Configuration\ExtensionBootstrap; +use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; +use PHPUnit\TextUI\Configuration\File; +use PHPUnit\TextUI\Configuration\FileCollection; +use PHPUnit\TextUI\Configuration\FilterDirectory; +use PHPUnit\TextUI\Configuration\FilterDirectoryCollection; +use PHPUnit\TextUI\Configuration\Group; +use PHPUnit\TextUI\Configuration\GroupCollection; +use PHPUnit\TextUI\Configuration\IniSetting; +use PHPUnit\TextUI\Configuration\IniSettingCollection; +use PHPUnit\TextUI\Configuration\Php; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\TestDirectory; +use PHPUnit\TextUI\Configuration\TestDirectoryCollection; +use PHPUnit\TextUI\Configuration\TestFile; +use PHPUnit\TextUI\Configuration\TestFileCollection; +use PHPUnit\TextUI\Configuration\TestSuite as TestSuiteConfiguration; +use PHPUnit\TextUI\Configuration\TestSuiteCollection; +use PHPUnit\TextUI\Configuration\Variable; +use PHPUnit\TextUI\Configuration\VariableCollection; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html as CodeCoverageHtml; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php as CodeCoveragePhp; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text as CodeCoverageText; +use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml as CodeCoverageXml; +use PHPUnit\TextUI\XmlConfiguration\Logging\Junit; +use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; +use PHPUnit\TextUI\XmlConfiguration\Logging\TeamCity; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText; +use PHPUnit\Util\VersionComparisonOperator; +use PHPUnit\Util\Xml\Loader as XmlLoader; +use PHPUnit\Util\Xml\XmlException; +use SebastianBergmann\CodeCoverage\Report\Html\Colors; +use SebastianBergmann\CodeCoverage\Report\Thresholds; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Loader +{ + /** + * @throws Exception + */ + public function load(string $filename): LoadedFromFileConfiguration + { + try { + $document = (new XmlLoader)->loadFile($filename); + } catch (XmlException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + $xpath = new DOMXPath($document); + + try { + $xsdFilename = (new SchemaFinder)->find(Version::series()); + } catch (CannotFindSchemaException $e) { + throw new Exception( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + + $configurationFileRealpath = realpath($filename); + + return new LoadedFromFileConfiguration( + $configurationFileRealpath, + (new Validator)->validate($document, $xsdFilename), + $this->extensions($xpath), + $this->source($configurationFileRealpath, $xpath), + $this->codeCoverage($configurationFileRealpath, $xpath), + $this->groups($xpath), + $this->logging($configurationFileRealpath, $xpath), + $this->php($configurationFileRealpath, $xpath), + $this->phpunit($configurationFileRealpath, $document), + $this->testSuite($configurationFileRealpath, $xpath), + ); + } + + private function logging(string $filename, DOMXPath $xpath): Logging + { + $junit = null; + $element = $this->element($xpath, 'logging/junit'); + + if ($element) { + $junit = new Junit( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + $teamCity = null; + $element = $this->element($xpath, 'logging/teamcity'); + + if ($element) { + $teamCity = new TeamCity( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + $testDoxHtml = null; + $element = $this->element($xpath, 'logging/testdoxHtml'); + + if ($element) { + $testDoxHtml = new TestDoxHtml( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + $testDoxText = null; + $element = $this->element($xpath, 'logging/testdoxText'); + + if ($element) { + $testDoxText = new TestDoxText( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + return new Logging( + $junit, + $teamCity, + $testDoxHtml, + $testDoxText, + ); + } + + private function extensions(DOMXPath $xpath): ExtensionBootstrapCollection + { + $extensionBootstrappers = []; + + foreach ($xpath->query('extensions/bootstrap') as $bootstrap) { + assert($bootstrap instanceof DOMElement); + + $parameters = []; + + foreach ($xpath->query('parameter', $bootstrap) as $parameter) { + assert($parameter instanceof DOMElement); + + $parameters[$parameter->getAttribute('name')] = $parameter->getAttribute('value'); + } + + $extensionBootstrappers[] = new ExtensionBootstrap( + $bootstrap->getAttribute('class'), + $parameters, + ); + } + + return ExtensionBootstrapCollection::fromArray($extensionBootstrappers); + } + + /** + * @psalm-return non-empty-string + */ + private function toAbsolutePath(string $filename, string $path): string + { + $path = trim($path); + + if (str_starts_with($path, '/')) { + return $path; + } + + // Matches the following on Windows: + // - \\NetworkComputer\Path + // - \\.\D: + // - \\.\c: + // - C:\Windows + // - C:\windows + // - C:/windows + // - c:/windows + if (defined('PHP_WINDOWS_VERSION_BUILD') && + !empty($path) && + ($path[0] === '\\' || (strlen($path) >= 3 && preg_match('#^[A-Z]:[/\\\]#i', substr($path, 0, 3))))) { + return $path; + } + + if (str_contains($path, '://')) { + return $path; + } + + return dirname($filename) . DIRECTORY_SEPARATOR . $path; + } + + private function source(string $filename, DOMXPath $xpath): Source + { + $baseline = null; + $restrictDeprecations = false; + $restrictNotices = false; + $restrictWarnings = false; + $ignoreSuppressionOfDeprecations = false; + $ignoreSuppressionOfPhpDeprecations = false; + $ignoreSuppressionOfErrors = false; + $ignoreSuppressionOfNotices = false; + $ignoreSuppressionOfPhpNotices = false; + $ignoreSuppressionOfWarnings = false; + $ignoreSuppressionOfPhpWarnings = false; + + $element = $this->element($xpath, 'source'); + + if ($element) { + $baseline = $this->getStringAttribute($element, 'baseline'); + + if ($baseline !== null) { + $baseline = $this->toAbsolutePath($filename, $baseline); + } + + $restrictDeprecations = $this->getBooleanAttribute($element, 'restrictDeprecations', false); + $restrictNotices = $this->getBooleanAttribute($element, 'restrictNotices', false); + $restrictWarnings = $this->getBooleanAttribute($element, 'restrictWarnings', false); + $ignoreSuppressionOfDeprecations = $this->getBooleanAttribute($element, 'ignoreSuppressionOfDeprecations', false); + $ignoreSuppressionOfPhpDeprecations = $this->getBooleanAttribute($element, 'ignoreSuppressionOfPhpDeprecations', false); + $ignoreSuppressionOfErrors = $this->getBooleanAttribute($element, 'ignoreSuppressionOfErrors', false); + $ignoreSuppressionOfNotices = $this->getBooleanAttribute($element, 'ignoreSuppressionOfNotices', false); + $ignoreSuppressionOfPhpNotices = $this->getBooleanAttribute($element, 'ignoreSuppressionOfPhpNotices', false); + $ignoreSuppressionOfWarnings = $this->getBooleanAttribute($element, 'ignoreSuppressionOfWarnings', false); + $ignoreSuppressionOfPhpWarnings = $this->getBooleanAttribute($element, 'ignoreSuppressionOfPhpWarnings', false); + } + + return new Source( + $baseline, + false, + $this->readFilterDirectories($filename, $xpath, 'source/include/directory'), + $this->readFilterFiles($filename, $xpath, 'source/include/file'), + $this->readFilterDirectories($filename, $xpath, 'source/exclude/directory'), + $this->readFilterFiles($filename, $xpath, 'source/exclude/file'), + $restrictDeprecations, + $restrictNotices, + $restrictWarnings, + $ignoreSuppressionOfDeprecations, + $ignoreSuppressionOfPhpDeprecations, + $ignoreSuppressionOfErrors, + $ignoreSuppressionOfNotices, + $ignoreSuppressionOfPhpNotices, + $ignoreSuppressionOfWarnings, + $ignoreSuppressionOfPhpWarnings, + ); + } + + private function codeCoverage(string $filename, DOMXPath $xpath): CodeCoverage + { + $cacheDirectory = null; + $pathCoverage = false; + $includeUncoveredFiles = true; + $ignoreDeprecatedCodeUnits = false; + $disableCodeCoverageIgnore = false; + + $element = $this->element($xpath, 'coverage'); + + if ($element) { + $cacheDirectory = $this->getStringAttribute($element, 'cacheDirectory'); + + if ($cacheDirectory !== null) { + $cacheDirectory = new Directory( + $this->toAbsolutePath($filename, $cacheDirectory), + ); + } + + $pathCoverage = $this->getBooleanAttribute( + $element, + 'pathCoverage', + false, + ); + + $includeUncoveredFiles = $this->getBooleanAttribute( + $element, + 'includeUncoveredFiles', + true, + ); + + $ignoreDeprecatedCodeUnits = $this->getBooleanAttribute( + $element, + 'ignoreDeprecatedCodeUnits', + false, + ); + + $disableCodeCoverageIgnore = $this->getBooleanAttribute( + $element, + 'disableCodeCoverageIgnore', + false, + ); + } + + $clover = null; + $element = $this->element($xpath, 'coverage/report/clover'); + + if ($element) { + $clover = new Clover( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + $cobertura = null; + $element = $this->element($xpath, 'coverage/report/cobertura'); + + if ($element) { + $cobertura = new Cobertura( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + $crap4j = null; + $element = $this->element($xpath, 'coverage/report/crap4j'); + + if ($element) { + $crap4j = new Crap4j( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + $this->getIntegerAttribute($element, 'threshold', 30), + ); + } + + $html = null; + $element = $this->element($xpath, 'coverage/report/html'); + + if ($element) { + $defaultColors = Colors::default(); + $defaultThresholds = Thresholds::default(); + + $html = new CodeCoverageHtml( + new Directory( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputDirectory'), + ), + ), + $this->getIntegerAttribute($element, 'lowUpperBound', $defaultThresholds->lowUpperBound()), + $this->getIntegerAttribute($element, 'highLowerBound', $defaultThresholds->highLowerBound()), + $this->getStringAttributeWithDefault($element, 'colorSuccessLow', $defaultColors->successLow()), + $this->getStringAttributeWithDefault($element, 'colorSuccessMedium', $defaultColors->successMedium()), + $this->getStringAttributeWithDefault($element, 'colorSuccessHigh', $defaultColors->successHigh()), + $this->getStringAttributeWithDefault($element, 'colorWarning', $defaultColors->warning()), + $this->getStringAttributeWithDefault($element, 'colorDanger', $defaultColors->danger()), + $this->getStringAttribute($element, 'customCssFile'), + ); + } + + $php = null; + $element = $this->element($xpath, 'coverage/report/php'); + + if ($element) { + $php = new CodeCoveragePhp( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + ); + } + + $text = null; + $element = $this->element($xpath, 'coverage/report/text'); + + if ($element) { + $text = new CodeCoverageText( + new File( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputFile'), + ), + ), + $this->getBooleanAttribute($element, 'showUncoveredFiles', false), + $this->getBooleanAttribute($element, 'showOnlySummary', false), + ); + } + + $xml = null; + $element = $this->element($xpath, 'coverage/report/xml'); + + if ($element) { + $xml = new CodeCoverageXml( + new Directory( + $this->toAbsolutePath( + $filename, + (string) $this->getStringAttribute($element, 'outputDirectory'), + ), + ), + ); + } + + return new CodeCoverage( + $cacheDirectory, + $this->readFilterDirectories($filename, $xpath, 'coverage/include/directory'), + $this->readFilterFiles($filename, $xpath, 'coverage/include/file'), + $this->readFilterDirectories($filename, $xpath, 'coverage/exclude/directory'), + $this->readFilterFiles($filename, $xpath, 'coverage/exclude/file'), + $pathCoverage, + $includeUncoveredFiles, + $ignoreDeprecatedCodeUnits, + $disableCodeCoverageIgnore, + $clover, + $cobertura, + $crap4j, + $html, + $php, + $text, + $xml, + ); + } + + private function getBoolean(string $value, bool $default): bool + { + if (strtolower($value) === 'false') { + return false; + } + + if (strtolower($value) === 'true') { + return true; + } + + return $default; + } + + private function getValue(string $value): bool|string + { + if (strtolower($value) === 'false') { + return false; + } + + if (strtolower($value) === 'true') { + return true; + } + + return $value; + } + + private function readFilterDirectories(string $filename, DOMXPath $xpath, string $query): FilterDirectoryCollection + { + $directories = []; + + foreach ($xpath->query($query) as $directoryNode) { + assert($directoryNode instanceof DOMElement); + + $directoryPath = $directoryNode->textContent; + + if (!$directoryPath) { + continue; + } + + $directories[] = new FilterDirectory( + $this->toAbsolutePath($filename, $directoryPath), + $directoryNode->hasAttribute('prefix') ? $directoryNode->getAttribute('prefix') : '', + $directoryNode->hasAttribute('suffix') ? $directoryNode->getAttribute('suffix') : '.php', + ); + } + + return FilterDirectoryCollection::fromArray($directories); + } + + private function readFilterFiles(string $filename, DOMXPath $xpath, string $query): FileCollection + { + $files = []; + + foreach ($xpath->query($query) as $file) { + assert($file instanceof DOMNode); + + $filePath = $file->textContent; + + if ($filePath) { + $files[] = new File($this->toAbsolutePath($filename, $filePath)); + } + } + + return FileCollection::fromArray($files); + } + + private function groups(DOMXPath $xpath): Groups + { + $include = []; + $exclude = []; + + foreach ($xpath->query('groups/include/group') as $group) { + assert($group instanceof DOMNode); + + $include[] = new Group($group->textContent); + } + + foreach ($xpath->query('groups/exclude/group') as $group) { + assert($group instanceof DOMNode); + + $exclude[] = new Group($group->textContent); + } + + return new Groups( + GroupCollection::fromArray($include), + GroupCollection::fromArray($exclude), + ); + } + + private function getBooleanAttribute(DOMElement $element, string $attribute, bool $default): bool + { + if (!$element->hasAttribute($attribute)) { + return $default; + } + + return $this->getBoolean( + $element->getAttribute($attribute), + false, + ); + } + + private function getIntegerAttribute(DOMElement $element, string $attribute, int $default): int + { + if (!$element->hasAttribute($attribute)) { + return $default; + } + + return $this->getInteger( + $element->getAttribute($attribute), + $default, + ); + } + + private function getStringAttribute(DOMElement $element, string $attribute): ?string + { + if (!$element->hasAttribute($attribute)) { + return null; + } + + return $element->getAttribute($attribute); + } + + private function getStringAttributeWithDefault(DOMElement $element, string $attribute, string $default): string + { + if (!$element->hasAttribute($attribute)) { + return $default; + } + + return $element->getAttribute($attribute); + } + + private function getInteger(string $value, int $default): int + { + if (is_numeric($value)) { + return (int) $value; + } + + return $default; + } + + private function php(string $filename, DOMXPath $xpath): Php + { + $includePaths = []; + + foreach ($xpath->query('php/includePath') as $includePath) { + assert($includePath instanceof DOMNode); + + $path = $includePath->textContent; + + if ($path) { + $includePaths[] = new Directory($this->toAbsolutePath($filename, $path)); + } + } + + $iniSettings = []; + + foreach ($xpath->query('php/ini') as $ini) { + assert($ini instanceof DOMElement); + + $iniSettings[] = new IniSetting( + $ini->getAttribute('name'), + $ini->getAttribute('value'), + ); + } + + $constants = []; + + foreach ($xpath->query('php/const') as $const) { + assert($const instanceof DOMElement); + + $value = $const->getAttribute('value'); + + $constants[] = new Constant( + $const->getAttribute('name'), + $this->getValue($value), + ); + } + + $variables = [ + 'var' => [], + 'env' => [], + 'post' => [], + 'get' => [], + 'cookie' => [], + 'server' => [], + 'files' => [], + 'request' => [], + ]; + + foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) { + foreach ($xpath->query('php/' . $array) as $var) { + assert($var instanceof DOMElement); + + $name = $var->getAttribute('name'); + $value = $var->getAttribute('value'); + $force = false; + $verbatim = false; + + if ($var->hasAttribute('force')) { + $force = $this->getBoolean($var->getAttribute('force'), false); + } + + if ($var->hasAttribute('verbatim')) { + $verbatim = $this->getBoolean($var->getAttribute('verbatim'), false); + } + + if (!$verbatim) { + $value = $this->getValue($value); + } + + $variables[$array][] = new Variable($name, $value, $force); + } + } + + return new Php( + DirectoryCollection::fromArray($includePaths), + IniSettingCollection::fromArray($iniSettings), + ConstantCollection::fromArray($constants), + VariableCollection::fromArray($variables['var']), + VariableCollection::fromArray($variables['env']), + VariableCollection::fromArray($variables['post']), + VariableCollection::fromArray($variables['get']), + VariableCollection::fromArray($variables['cookie']), + VariableCollection::fromArray($variables['server']), + VariableCollection::fromArray($variables['files']), + VariableCollection::fromArray($variables['request']), + ); + } + + private function phpunit(string $filename, DOMDocument $document): PHPUnit + { + $executionOrder = TestSuiteSorter::ORDER_DEFAULT; + $defectsFirst = false; + $resolveDependencies = $this->getBooleanAttribute($document->documentElement, 'resolveDependencies', true); + + if ($document->documentElement->hasAttribute('executionOrder')) { + foreach (explode(',', $document->documentElement->getAttribute('executionOrder')) as $order) { + switch ($order) { + case 'default': + $executionOrder = TestSuiteSorter::ORDER_DEFAULT; + $defectsFirst = false; + $resolveDependencies = true; + + break; + + case 'depends': + $resolveDependencies = true; + + break; + + case 'no-depends': + $resolveDependencies = false; + + break; + + case 'defects': + $defectsFirst = true; + + break; + + case 'duration': + $executionOrder = TestSuiteSorter::ORDER_DURATION; + + break; + + case 'random': + $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case 'reverse': + $executionOrder = TestSuiteSorter::ORDER_REVERSED; + + break; + + case 'size': + $executionOrder = TestSuiteSorter::ORDER_SIZE; + + break; + } + } + } + + $cacheDirectory = $this->getStringAttribute($document->documentElement, 'cacheDirectory'); + + if ($cacheDirectory !== null) { + $cacheDirectory = $this->toAbsolutePath($filename, $cacheDirectory); + } + + $cacheResultFile = $this->getStringAttribute($document->documentElement, 'cacheResultFile'); + + if ($cacheResultFile !== null) { + $cacheResultFile = $this->toAbsolutePath($filename, $cacheResultFile); + } + + $bootstrap = $this->getStringAttribute($document->documentElement, 'bootstrap'); + + if ($bootstrap !== null) { + $bootstrap = $this->toAbsolutePath($filename, $bootstrap); + } + + $extensionsDirectory = $this->getStringAttribute($document->documentElement, 'extensionsDirectory'); + + if ($extensionsDirectory !== null) { + $extensionsDirectory = $this->toAbsolutePath($filename, $extensionsDirectory); + } + + $backupStaticProperties = false; + + if ($document->documentElement->hasAttribute('backupStaticProperties')) { + $backupStaticProperties = $this->getBooleanAttribute($document->documentElement, 'backupStaticProperties', false); + } elseif ($document->documentElement->hasAttribute('backupStaticAttributes')) { + $backupStaticProperties = $this->getBooleanAttribute($document->documentElement, 'backupStaticAttributes', false); + } + + $requireCoverageMetadata = false; + + if ($document->documentElement->hasAttribute('requireCoverageMetadata')) { + $requireCoverageMetadata = $this->getBooleanAttribute($document->documentElement, 'requireCoverageMetadata', false); + } elseif ($document->documentElement->hasAttribute('forceCoversAnnotation')) { + $requireCoverageMetadata = $this->getBooleanAttribute($document->documentElement, 'forceCoversAnnotation', false); + } + + $beStrictAboutCoverageMetadata = false; + + if ($document->documentElement->hasAttribute('beStrictAboutCoverageMetadata')) { + $beStrictAboutCoverageMetadata = $this->getBooleanAttribute($document->documentElement, 'beStrictAboutCoverageMetadata', false); + } elseif ($document->documentElement->hasAttribute('forceCoversAnnotation')) { + $beStrictAboutCoverageMetadata = $this->getBooleanAttribute($document->documentElement, 'beStrictAboutCoversAnnotation', false); + } + + return new PHPUnit( + $cacheDirectory, + $this->getBooleanAttribute($document->documentElement, 'cacheResult', true), + $cacheResultFile, + $this->getColumns($document), + $this->getColors($document), + $this->getBooleanAttribute($document->documentElement, 'stderr', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnIncompleteTests', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnSkippedTests', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerDeprecations', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnPhpunitDeprecations', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerErrors', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerNotices', false), + $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerWarnings', false), + $this->getBooleanAttribute($document->documentElement, 'reverseDefectList', false), + $requireCoverageMetadata, + $bootstrap, + $this->getBooleanAttribute($document->documentElement, 'processIsolation', false), + $this->getBooleanAttribute($document->documentElement, 'failOnDeprecation', false), + $this->getBooleanAttribute($document->documentElement, 'failOnPhpunitDeprecation', false), + $this->getBooleanAttribute($document->documentElement, 'failOnEmptyTestSuite', false), + $this->getBooleanAttribute($document->documentElement, 'failOnIncomplete', false), + $this->getBooleanAttribute($document->documentElement, 'failOnNotice', false), + $this->getBooleanAttribute($document->documentElement, 'failOnRisky', false), + $this->getBooleanAttribute($document->documentElement, 'failOnSkipped', false), + $this->getBooleanAttribute($document->documentElement, 'failOnWarning', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnDefect', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnDeprecation', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnError', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnFailure', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnIncomplete', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnNotice', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnRisky', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnSkipped', false), + $this->getBooleanAttribute($document->documentElement, 'stopOnWarning', false), + $extensionsDirectory, + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutChangesToGlobalState', false), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutOutputDuringTests', false), + $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTestsThatDoNotTestAnything', true), + $beStrictAboutCoverageMetadata, + $this->getBooleanAttribute($document->documentElement, 'enforceTimeLimit', false), + $this->getIntegerAttribute($document->documentElement, 'defaultTimeLimit', 1), + $this->getIntegerAttribute($document->documentElement, 'timeoutForSmallTests', 1), + $this->getIntegerAttribute($document->documentElement, 'timeoutForMediumTests', 10), + $this->getIntegerAttribute($document->documentElement, 'timeoutForLargeTests', 60), + $this->getStringAttribute($document->documentElement, 'defaultTestSuite'), + $executionOrder, + $resolveDependencies, + $defectsFirst, + $this->getBooleanAttribute($document->documentElement, 'backupGlobals', false), + $backupStaticProperties, + $this->getBooleanAttribute($document->documentElement, 'registerMockObjectsFromTestArgumentsRecursively', false), + $this->getBooleanAttribute($document->documentElement, 'testdox', false), + $this->getBooleanAttribute($document->documentElement, 'controlGarbageCollector', false), + $this->getIntegerAttribute($document->documentElement, 'numberOfTestsBeforeGarbageCollection', 100), + ); + } + + private function getColors(DOMDocument $document): string + { + $colors = Configuration::COLOR_DEFAULT; + + if ($document->documentElement->hasAttribute('colors')) { + /* only allow boolean for compatibility with previous versions + 'always' only allowed from command line */ + if ($this->getBoolean($document->documentElement->getAttribute('colors'), false)) { + $colors = Configuration::COLOR_AUTO; + } else { + $colors = Configuration::COLOR_NEVER; + } + } + + return $colors; + } + + private function getColumns(DOMDocument $document): int|string + { + $columns = 80; + + if ($document->documentElement->hasAttribute('columns')) { + $columns = $document->documentElement->getAttribute('columns'); + + if ($columns !== 'max') { + $columns = $this->getInteger($columns, 80); + } + } + + return $columns; + } + + private function testSuite(string $filename, DOMXPath $xpath): TestSuiteCollection + { + $testSuites = []; + + foreach ($this->getTestSuiteElements($xpath) as $element) { + $exclude = []; + + foreach ($element->getElementsByTagName('exclude') as $excludeNode) { + $excludeFile = $excludeNode->textContent; + + if ($excludeFile) { + $exclude[] = new File($this->toAbsolutePath($filename, $excludeFile)); + } + } + + $directories = []; + + foreach ($element->getElementsByTagName('directory') as $directoryNode) { + assert($directoryNode instanceof DOMElement); + + $directory = $directoryNode->textContent; + + if (empty($directory)) { + continue; + } + + $prefix = ''; + + if ($directoryNode->hasAttribute('prefix')) { + $prefix = $directoryNode->getAttribute('prefix'); + } + + $suffix = 'Test.php'; + + if ($directoryNode->hasAttribute('suffix')) { + $suffix = $directoryNode->getAttribute('suffix'); + } + + $phpVersion = PHP_VERSION; + + if ($directoryNode->hasAttribute('phpVersion')) { + $phpVersion = $directoryNode->getAttribute('phpVersion'); + } + + $phpVersionOperator = new VersionComparisonOperator('>='); + + if ($directoryNode->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = new VersionComparisonOperator($directoryNode->getAttribute('phpVersionOperator')); + } + + $directories[] = new TestDirectory( + $this->toAbsolutePath($filename, $directory), + $prefix, + $suffix, + $phpVersion, + $phpVersionOperator, + ); + } + + $files = []; + + foreach ($element->getElementsByTagName('file') as $fileNode) { + assert($fileNode instanceof DOMElement); + + $file = $fileNode->textContent; + + if (empty($file)) { + continue; + } + + $phpVersion = PHP_VERSION; + + if ($fileNode->hasAttribute('phpVersion')) { + $phpVersion = $fileNode->getAttribute('phpVersion'); + } + + $phpVersionOperator = new VersionComparisonOperator('>='); + + if ($fileNode->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = new VersionComparisonOperator($fileNode->getAttribute('phpVersionOperator')); + } + + $files[] = new TestFile( + $this->toAbsolutePath($filename, $file), + $phpVersion, + $phpVersionOperator, + ); + } + + $name = $element->getAttribute('name'); + + assert(!empty($name)); + + $testSuites[] = new TestSuiteConfiguration( + $name, + TestDirectoryCollection::fromArray($directories), + TestFileCollection::fromArray($files), + FileCollection::fromArray($exclude), + ); + } + + return TestSuiteCollection::fromArray($testSuites); + } + + /** + * @psalm-return list + */ + private function getTestSuiteElements(DOMXPath $xpath): array + { + $elements = []; + + $testSuiteNodes = $xpath->query('testsuites/testsuite'); + + if ($testSuiteNodes->length === 0) { + $testSuiteNodes = $xpath->query('testsuite'); + } + + if ($testSuiteNodes->length === 1) { + $element = $testSuiteNodes->item(0); + + assert($element instanceof DOMElement); + + $elements[] = $element; + } else { + foreach ($testSuiteNodes as $testSuiteNode) { + assert($testSuiteNode instanceof DOMElement); + + $elements[] = $testSuiteNode; + } + } + + return $elements; + } + + private function element(DOMXPath $xpath, string $element): ?DOMElement + { + $nodes = $xpath->query($element); + + if ($nodes->length === 1) { + $node = $nodes->item(0); + + assert($node instanceof DOMElement); + + return $node; + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php new file mode 100644 index 000000000..406aaf2b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Junit +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php new file mode 100644 index 000000000..8fc34394a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\XmlConfiguration\Exception; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml; +use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Logging +{ + private readonly ?Junit $junit; + private readonly ?TeamCity $teamCity; + private readonly ?TestDoxHtml $testDoxHtml; + private readonly ?TestDoxText $testDoxText; + + public function __construct(?Junit $junit, ?TeamCity $teamCity, ?TestDoxHtml $testDoxHtml, ?TestDoxText $testDoxText) + { + $this->junit = $junit; + $this->teamCity = $teamCity; + $this->testDoxHtml = $testDoxHtml; + $this->testDoxText = $testDoxText; + } + + public function hasJunit(): bool + { + return $this->junit !== null; + } + + /** + * @throws Exception + */ + public function junit(): Junit + { + if ($this->junit === null) { + throw new Exception('Logger "JUnit XML" is not configured'); + } + + return $this->junit; + } + + public function hasTeamCity(): bool + { + return $this->teamCity !== null; + } + + /** + * @throws Exception + */ + public function teamCity(): TeamCity + { + if ($this->teamCity === null) { + throw new Exception('Logger "Team City" is not configured'); + } + + return $this->teamCity; + } + + public function hasTestDoxHtml(): bool + { + return $this->testDoxHtml !== null; + } + + /** + * @throws Exception + */ + public function testDoxHtml(): TestDoxHtml + { + if ($this->testDoxHtml === null) { + throw new Exception('Logger "TestDox HTML" is not configured'); + } + + return $this->testDoxHtml; + } + + public function hasTestDoxText(): bool + { + return $this->testDoxText !== null; + } + + /** + * @throws Exception + */ + public function testDoxText(): TestDoxText + { + if ($this->testDoxText === null) { + throw new Exception('Logger "TestDox Text" is not configured'); + } + + return $this->testDoxText; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php new file mode 100644 index 000000000..2025c1f4e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class TeamCity +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php new file mode 100644 index 000000000..e52587bb6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Html +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php new file mode 100644 index 000000000..db47a3eff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; + +use PHPUnit\TextUI\Configuration\File; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class Text +{ + private readonly File $target; + + public function __construct(File $target) + { + $this->target = $target; + } + + public function target(): File + { + return $this->target; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php new file mode 100644 index 000000000..147c4066d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function version_compare; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MigrationBuilder +{ + private const AVAILABLE_MIGRATIONS = [ + '8.5' => [ + RemoveLogTypes::class, + ], + + '9.2' => [ + RemoveCacheTokensAttribute::class, + IntroduceCoverageElement::class, + MoveAttributesFromRootToCoverage::class, + MoveAttributesFromFilterWhitelistToCoverage::class, + MoveWhitelistIncludesToCoverage::class, + MoveWhitelistExcludesToCoverage::class, + RemoveEmptyFilter::class, + CoverageCloverToReport::class, + CoverageCrap4jToReport::class, + CoverageHtmlToReport::class, + CoveragePhpToReport::class, + CoverageTextToReport::class, + CoverageXmlToReport::class, + ConvertLogTypes::class, + ], + + '9.5' => [ + RemoveListeners::class, + RemoveTestSuiteLoaderAttributes::class, + RemoveCacheResultFileAttribute::class, + RemoveCoverageElementCacheDirectoryAttribute::class, + RemoveCoverageElementProcessUncoveredFilesAttribute::class, + IntroduceCacheDirectoryAttribute::class, + RenameBackupStaticAttributesAttribute::class, + RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute::class, + RemoveBeStrictAboutTodoAnnotatedTestsAttribute::class, + RemovePrinterAttributes::class, + RemoveVerboseAttribute::class, + RenameForceCoversAnnotationAttribute::class, + RenameBeStrictAboutCoversAnnotationAttribute::class, + RemoveConversionToExceptionsAttributes::class, + RemoveNoInteractionAttribute::class, + RemoveLoggingElements::class, + RemoveTestDoxGroupsElement::class, + ], + + '10.0' => [ + MoveCoverageDirectoriesToSource::class, + ], + ]; + + public function build(string $fromVersion): array + { + $stack = [new UpdateSchemaLocation]; + + foreach (self::AVAILABLE_MIGRATIONS as $version => $migrations) { + if (version_compare($version, $fromVersion, '<')) { + continue; + } + + foreach ($migrations as $migration) { + $stack[] = new $migration; + } + } + + return $stack; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php new file mode 100644 index 000000000..bb35aca68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MigrationException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php new file mode 100644 index 000000000..43a9bf154 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ConvertLogTypes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $logging = $document->getElementsByTagName('logging')->item(0); + + if (!$logging instanceof DOMElement) { + return; + } + $types = [ + 'junit' => 'junit', + 'teamcity' => 'teamcity', + 'testdox-html' => 'testdoxHtml', + 'testdox-text' => 'testdoxText', + 'testdox-xml' => 'testdoxXml', + 'plain' => 'text', + ]; + + $logNodes = []; + + foreach ($logging->getElementsByTagName('log') as $logNode) { + if (!isset($types[$logNode->getAttribute('type')])) { + continue; + } + + $logNodes[] = $logNode; + } + + foreach ($logNodes as $oldNode) { + $newLogNode = $document->createElement($types[$oldNode->getAttribute('type')]); + $newLogNode->setAttribute('outputFile', $oldNode->getAttribute('target')); + + $logging->replaceChild($newLogNode, $oldNode); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php new file mode 100644 index 000000000..7d3ee4962 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageCloverToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-clover'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $clover = $logNode->ownerDocument->createElement('clover'); + + $clover->setAttribute('outputFile', $logNode->getAttribute('target')); + + return $clover; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php new file mode 100644 index 000000000..2b4947805 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageCrap4jToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-crap4j'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $crap4j = $logNode->ownerDocument->createElement('crap4j'); + $crap4j->setAttribute('outputFile', $logNode->getAttribute('target')); + + $this->migrateAttributes($logNode, $crap4j, ['threshold']); + + return $crap4j; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php new file mode 100644 index 000000000..64af982d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageHtmlToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-html'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $html = $logNode->ownerDocument->createElement('html'); + $html->setAttribute('outputDirectory', $logNode->getAttribute('target')); + + $this->migrateAttributes($logNode, $html, ['lowUpperBound', 'highLowerBound']); + + return $html; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php new file mode 100644 index 000000000..93868c473 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoveragePhpToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-php'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $php = $logNode->ownerDocument->createElement('php'); + $php->setAttribute('outputFile', $logNode->getAttribute('target')); + + return $php; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php new file mode 100644 index 000000000..f50be1d7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageTextToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-text'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $text = $logNode->ownerDocument->createElement('text'); + $text->setAttribute('outputFile', $logNode->getAttribute('target')); + + $this->migrateAttributes($logNode, $text, ['showUncoveredFiles', 'showOnlySummary']); + + return $text; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php new file mode 100644 index 000000000..2ea7cdc8b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CoverageXmlToReport extends LogToReportMigration +{ + protected function forType(): string + { + return 'coverage-xml'; + } + + protected function toReportFormat(DOMElement $logNode): DOMElement + { + $xml = $logNode->ownerDocument->createElement('xml'); + $xml->setAttribute('outputDirectory', $logNode->getAttribute('target')); + + return $xml; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php new file mode 100644 index 000000000..fe0e0a2b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IntroduceCacheDirectoryAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('cacheDirectory')) { + return; + } + + $root->setAttribute('cacheDirectory', '.phpunit.cache'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php new file mode 100644 index 000000000..54b5485db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class IntroduceCoverageElement implements Migration +{ + public function migrate(DOMDocument $document): void + { + $coverage = $document->createElement('coverage'); + + $document->documentElement->insertBefore( + $coverage, + $document->documentElement->firstChild, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php new file mode 100644 index 000000000..321260b53 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function sprintf; +use DOMDocument; +use DOMElement; +use DOMXPath; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class LogToReportMigration implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $logNode = $this->findLogNode($document); + + if ($logNode === null) { + return; + } + + $reportChild = $this->toReportFormat($logNode); + + $report = $coverage->getElementsByTagName('report')->item(0); + + if ($report === null) { + $report = $coverage->appendChild($document->createElement('report')); + } + + $report->appendChild($reportChild); + $logNode->parentNode->removeChild($logNode); + } + + protected function migrateAttributes(DOMElement $src, DOMElement $dest, array $attributes): void + { + foreach ($attributes as $attr) { + if (!$src->hasAttribute($attr)) { + continue; + } + + $dest->setAttribute($attr, $src->getAttribute($attr)); + $src->removeAttribute($attr); + } + } + + abstract protected function forType(): string; + + abstract protected function toReportFormat(DOMElement $logNode): DOMElement; + + private function findLogNode(DOMDocument $document): ?DOMElement + { + $logNode = (new DOMXPath($document))->query( + sprintf('//logging/log[@type="%s"]', $this->forType()), + )->item(0); + + if (!$logNode instanceof DOMElement) { + return null; + } + + return $logNode; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php new file mode 100644 index 000000000..05359a2d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Migration +{ + public function migrate(DOMDocument $document): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php new file mode 100644 index 000000000..b6ed401ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveAttributesFromFilterWhitelistToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if (!$whitelist) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $map = [ + 'addUncoveredFilesFromWhitelist' => 'includeUncoveredFiles', + 'processUncoveredFilesFromWhitelist' => 'processUncoveredFiles', + ]; + + foreach ($map as $old => $new) { + if (!$whitelist->hasAttribute($old)) { + continue; + } + + $coverage->setAttribute($new, $whitelist->getAttribute($old)); + $whitelist->removeAttribute($old); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php new file mode 100644 index 000000000..40b95fecf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveAttributesFromRootToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $map = [ + 'disableCodeCoverageIgnore' => 'disableCodeCoverageIgnore', + 'ignoreDeprecatedCodeUnitsFromCodeCoverage' => 'ignoreDeprecatedCodeUnits', + ]; + + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + foreach ($map as $old => $new) { + if (!$root->hasAttribute($old)) { + continue; + } + + $coverage->setAttribute($new, $root->getAttribute($old)); + $root->removeAttribute($old); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php new file mode 100644 index 000000000..737c473f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; +use DOMXPath; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveCoverageDirectoriesToSource implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $source = $document->getElementsByTagName('source')->item(0); + + if ($source !== null) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if ($coverage === null) { + return; + } + + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + $source = $document->createElement('source'); + $root->appendChild($source); + + $xpath = new DOMXPath($document); + + foreach (['include', 'exclude'] as $element) { + foreach (SnapshotNodeList::fromNodeList($xpath->query('//coverage/' . $element)) as $node) { + $source->appendChild($node); + } + } + + if ($coverage->childElementCount !== 0) { + return; + } + + assert($coverage->parentNode !== null); + + $coverage->parentNode->removeChild($coverage); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php new file mode 100644 index 000000000..311fb567b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use function in_array; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveWhitelistExcludesToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if ($whitelist === null) { + return; + } + + $excludeNodes = SnapshotNodeList::fromNodeList($whitelist->getElementsByTagName('exclude')); + + if ($excludeNodes->count() === 0) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $targetExclude = $coverage->getElementsByTagName('exclude')->item(0); + + if ($targetExclude === null) { + $targetExclude = $coverage->appendChild( + $document->createElement('exclude'), + ); + } + + foreach ($excludeNodes as $excludeNode) { + assert($excludeNode instanceof DOMElement); + + foreach (SnapshotNodeList::fromNodeList($excludeNode->childNodes) as $child) { + if (!$child instanceof DOMElement || !in_array($child->nodeName, ['directory', 'file'], true)) { + continue; + } + + $targetExclude->appendChild($child); + } + + if ($excludeNode->getElementsByTagName('*')->count() !== 0) { + throw new MigrationException('Dangling child elements in exclude found.'); + } + + $whitelist->removeChild($excludeNode); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php new file mode 100644 index 000000000..19c1f140d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class MoveWhitelistIncludesToCoverage implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if ($whitelist === null) { + return; + } + + $coverage = $document->getElementsByTagName('coverage')->item(0); + + if (!$coverage instanceof DOMElement) { + throw new MigrationException('Unexpected state - No coverage element'); + } + + $include = $document->createElement('include'); + $coverage->appendChild($include); + + foreach (SnapshotNodeList::fromNodeList($whitelist->childNodes) as $child) { + if (!$child instanceof DOMElement) { + continue; + } + + if (!($child->nodeName === 'directory' || $child->nodeName === 'file')) { + continue; + } + + $include->appendChild($child); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php new file mode 100644 index 000000000..ee49fcfce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('beStrictAboutResourceUsageDuringSmallTests')) { + $root->removeAttribute('beStrictAboutResourceUsageDuringSmallTests'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php new file mode 100644 index 000000000..d7ab28f68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveBeStrictAboutTodoAnnotatedTestsAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('beStrictAboutTodoAnnotatedTests')) { + $root->removeAttribute('beStrictAboutTodoAnnotatedTests'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php new file mode 100644 index 000000000..e283b64de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveCacheResultFileAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('cacheResultFile')) { + $root->removeAttribute('cacheResultFile'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php new file mode 100644 index 000000000..5ab7e041d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveCacheTokensAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('cacheTokens')) { + $root->removeAttribute('cacheTokens'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php new file mode 100644 index 000000000..339b3e202 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveConversionToExceptionsAttributes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('convertDeprecationsToExceptions')) { + $root->removeAttribute('convertDeprecationsToExceptions'); + } + + if ($root->hasAttribute('convertErrorsToExceptions')) { + $root->removeAttribute('convertErrorsToExceptions'); + } + + if ($root->hasAttribute('convertNoticesToExceptions')) { + $root->removeAttribute('convertNoticesToExceptions'); + } + + if ($root->hasAttribute('convertWarningsToExceptions')) { + $root->removeAttribute('convertWarningsToExceptions'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php new file mode 100644 index 000000000..4a71bbb8c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveCoverageElementCacheDirectoryAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $node = $document->getElementsByTagName('coverage')->item(0); + + if (!$node instanceof DOMElement || $node->parentNode === null) { + return; + } + + if ($node->hasAttribute('cacheDirectory')) { + $node->removeAttribute('cacheDirectory'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php new file mode 100644 index 000000000..720b65c57 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveCoverageElementProcessUncoveredFilesAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $node = $document->getElementsByTagName('coverage')->item(0); + + if (!$node instanceof DOMElement || $node->parentNode === null) { + return; + } + + if ($node->hasAttribute('processUncoveredFiles')) { + $node->removeAttribute('processUncoveredFiles'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php new file mode 100644 index 000000000..2d8fea528 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function sprintf; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveEmptyFilter implements Migration +{ + /** + * @throws MigrationException + */ + public function migrate(DOMDocument $document): void + { + $whitelist = $document->getElementsByTagName('whitelist')->item(0); + + if ($whitelist instanceof DOMElement) { + $this->ensureEmpty($whitelist); + $whitelist->parentNode->removeChild($whitelist); + } + + $filter = $document->getElementsByTagName('filter')->item(0); + + if ($filter instanceof DOMElement) { + $this->ensureEmpty($filter); + $filter->parentNode->removeChild($filter); + } + } + + /** + * @throws MigrationException + */ + private function ensureEmpty(DOMElement $element): void + { + if ($element->attributes->length > 0) { + throw new MigrationException(sprintf('%s element has unexpected attributes', $element->nodeName)); + } + + if ($element->getElementsByTagName('*')->length > 0) { + throw new MigrationException(sprintf('%s element has unexpected children', $element->nodeName)); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php new file mode 100644 index 000000000..b493d1c7c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveListeners implements Migration +{ + public function migrate(DOMDocument $document): void + { + $node = $document->getElementsByTagName('listeners')->item(0); + + if (!$node instanceof DOMElement || $node->parentNode === null) { + return; + } + + $node->parentNode->removeChild($node); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php new file mode 100644 index 000000000..9591f8c9c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.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 PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveLogTypes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $logging = $document->getElementsByTagName('logging')->item(0); + + if (!$logging instanceof DOMElement) { + return; + } + + foreach (SnapshotNodeList::fromNodeList($logging->getElementsByTagName('log')) as $logNode) { + assert($logNode instanceof DOMElement); + + switch ($logNode->getAttribute('type')) { + case 'json': + case 'tap': + $logging->removeChild($logNode); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php new file mode 100644 index 000000000..de09f8c40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; +use DOMXPath; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveLoggingElements implements Migration +{ + public function migrate(DOMDocument $document): void + { + $this->removeTestDoxElement($document); + $this->removeTextElement($document); + } + + private function removeTestDoxElement(DOMDocument $document): void + { + $node = (new DOMXPath($document))->query('logging/testdoxXml')->item(0); + + if (!$node instanceof DOMElement || $node->parentNode === null) { + return; + } + + $node->parentNode->removeChild($node); + } + + private function removeTextElement(DOMDocument $document): void + { + $node = (new DOMXPath($document))->query('logging/text')->item(0); + + if (!$node instanceof DOMElement || $node->parentNode === null) { + return; + } + + $node->parentNode->removeChild($node); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php new file mode 100644 index 000000000..c3dd3f105 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveNoInteractionAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('noInteraction')) { + $root->removeAttribute('noInteraction'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php new file mode 100644 index 000000000..2d1d03fa7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemovePrinterAttributes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('printerClass')) { + $root->removeAttribute('printerClass'); + } + + if ($root->hasAttribute('printerFile')) { + $root->removeAttribute('printerFile'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php new file mode 100644 index 000000000..eb2f13595 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveTestDoxGroupsElement implements Migration +{ + public function migrate(DOMDocument $document): void + { + $node = $document->getElementsByTagName('testdoxGroups')->item(0); + + if (!$node instanceof DOMElement || $node->parentNode === null) { + return; + } + + $node->parentNode->removeChild($node); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php new file mode 100644 index 000000000..823c96473 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveTestSuiteLoaderAttributes implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('testSuiteLoaderClass')) { + $root->removeAttribute('testSuiteLoaderClass'); + } + + if ($root->hasAttribute('testSuiteLoaderFile')) { + $root->removeAttribute('testSuiteLoaderFile'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php new file mode 100644 index 000000000..0233d8b4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RemoveVerboseAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('verbose')) { + $root->removeAttribute('verbose'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php new file mode 100644 index 000000000..b04bbdb2c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RenameBackupStaticAttributesAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('backupStaticProperties')) { + return; + } + + if (!$root->hasAttribute('backupStaticAttributes')) { + return; + } + + $root->setAttribute('backupStaticProperties', $root->getAttribute('backupStaticAttributes')); + $root->removeAttribute('backupStaticAttributes'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php new file mode 100644 index 000000000..3950e2a36 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RenameBeStrictAboutCoversAnnotationAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('beStrictAboutCoverageMetadata')) { + return; + } + + if (!$root->hasAttribute('beStrictAboutCoversAnnotation')) { + return; + } + + $root->setAttribute('beStrictAboutCoverageMetadata', $root->getAttribute('beStrictAboutCoversAnnotation')); + $root->removeAttribute('beStrictAboutCoversAnnotation'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php new file mode 100644 index 000000000..c384be21e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RenameForceCoversAnnotationAttribute implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + if ($root->hasAttribute('requireCoverageMetadata')) { + return; + } + + if (!$root->hasAttribute('forceCoversAnnotation')) { + return; + } + + $root->setAttribute('requireCoverageMetadata', $root->getAttribute('forceCoversAnnotation')); + $root->removeAttribute('forceCoversAnnotation'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php new file mode 100644 index 000000000..6f39eb4c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use DOMDocument; +use DOMElement; +use PHPUnit\Runner\Version; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class UpdateSchemaLocation implements Migration +{ + public function migrate(DOMDocument $document): void + { + $root = $document->documentElement; + + assert($root instanceof DOMElement); + + $root->setAttributeNS( + 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:noNamespaceSchemaLocation', + 'https://schema.phpunit.de/' . Version::series() . '/phpunit.xsd', + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php new file mode 100644 index 000000000..278789ff3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Runner\Version; +use PHPUnit\Util\Xml\Loader as XmlLoader; +use PHPUnit\Util\Xml\XmlException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Migrator +{ + /** + * @throws Exception + * @throws MigrationException + * @throws XmlException + */ + public function migrate(string $filename): string + { + $origin = (new SchemaDetector)->detect($filename); + + if (!$origin->detected()) { + throw new Exception('The file does not validate against any known schema'); + } + + if ($origin->version() === Version::series()) { + throw new Exception('The file does not need to be migrated'); + } + + $configurationDocument = (new XmlLoader)->loadFile($filename); + + foreach ((new MigrationBuilder)->build($origin->version()) as $migration) { + $migration->migrate($configurationDocument); + } + + $configurationDocument->formatOutput = true; + $configurationDocument->preserveWhiteSpace = false; + + return $configurationDocument->saveXML(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php new file mode 100644 index 000000000..c87d05468 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function count; +use ArrayIterator; +use Countable; +use DOMNode; +use DOMNodeList; +use IteratorAggregate; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @template-implements IteratorAggregate + */ +final class SnapshotNodeList implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private array $nodes = []; + + public static function fromNodeList(DOMNodeList $list): self + { + $snapshot = new self; + + foreach ($list as $node) { + $snapshot->nodes[] = $node; + } + + return $snapshot; + } + + public function count(): int + { + return count($this->nodes); + } + + public function getIterator(): ArrayIterator + { + return new ArrayIterator($this->nodes); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php new file mode 100644 index 000000000..ddae10a96 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/PHPUnit.php @@ -0,0 +1,494 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class PHPUnit +{ + private readonly ?string $cacheDirectory; + private readonly bool $cacheResult; + private readonly ?string $cacheResultFile; + private readonly int|string $columns; + private readonly string $colors; + private readonly bool $stderr; + private readonly bool $displayDetailsOnIncompleteTests; + private readonly bool $displayDetailsOnSkippedTests; + private readonly bool $displayDetailsOnTestsThatTriggerDeprecations; + private readonly bool $displayDetailsOnPhpunitDeprecations; + private readonly bool $displayDetailsOnTestsThatTriggerErrors; + private readonly bool $displayDetailsOnTestsThatTriggerNotices; + private readonly bool $displayDetailsOnTestsThatTriggerWarnings; + private readonly bool $reverseDefectList; + private readonly bool $requireCoverageMetadata; + private readonly ?string $bootstrap; + private readonly bool $processIsolation; + private readonly bool $failOnDeprecation; + private readonly bool $failOnPhpunitDeprecation; + private readonly bool $failOnEmptyTestSuite; + private readonly bool $failOnIncomplete; + private readonly bool $failOnNotice; + private readonly bool $failOnRisky; + private readonly bool $failOnSkipped; + private readonly bool $failOnWarning; + private readonly bool $stopOnDefect; + private readonly bool $stopOnDeprecation; + private readonly bool $stopOnError; + private readonly bool $stopOnFailure; + private readonly bool $stopOnIncomplete; + private readonly bool $stopOnNotice; + private readonly bool $stopOnRisky; + private readonly bool $stopOnSkipped; + private readonly bool $stopOnWarning; + + /** + * @psalm-var ?non-empty-string + */ + private readonly ?string $extensionsDirectory; + private readonly bool $beStrictAboutChangesToGlobalState; + private readonly bool $beStrictAboutOutputDuringTests; + private readonly bool $beStrictAboutTestsThatDoNotTestAnything; + private readonly bool $beStrictAboutCoverageMetadata; + private readonly bool $enforceTimeLimit; + private readonly int $defaultTimeLimit; + private readonly int $timeoutForSmallTests; + private readonly int $timeoutForMediumTests; + private readonly int $timeoutForLargeTests; + private readonly ?string $defaultTestSuite; + private readonly int $executionOrder; + private readonly bool $resolveDependencies; + private readonly bool $defectsFirst; + private readonly bool $backupGlobals; + private readonly bool $backupStaticProperties; + private readonly bool $registerMockObjectsFromTestArgumentsRecursively; + private readonly bool $testdoxPrinter; + private readonly bool $controlGarbageCollector; + private readonly int $numberOfTestsBeforeGarbageCollection; + + /** + * @psalm-param ?non-empty-string $extensionsDirectory + */ + public function __construct(?string $cacheDirectory, bool $cacheResult, ?string $cacheResultFile, int|string $columns, string $colors, bool $stderr, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnPhpunitDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $reverseDefectList, bool $requireCoverageMetadata, ?string $bootstrap, bool $processIsolation, bool $failOnDeprecation, bool $failOnPhpunitDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnDeprecation, bool $stopOnError, bool $stopOnFailure, bool $stopOnIncomplete, bool $stopOnNotice, bool $stopOnRisky, bool $stopOnSkipped, bool $stopOnWarning, ?string $extensionsDirectory, bool $beStrictAboutChangesToGlobalState, bool $beStrictAboutOutputDuringTests, bool $beStrictAboutTestsThatDoNotTestAnything, bool $beStrictAboutCoverageMetadata, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, ?string $defaultTestSuite, int $executionOrder, bool $resolveDependencies, bool $defectsFirst, bool $backupGlobals, bool $backupStaticProperties, bool $registerMockObjectsFromTestArgumentsRecursively, bool $testdoxPrinter, bool $controlGarbageCollector, int $numberOfTestsBeforeGarbageCollection) + { + $this->cacheDirectory = $cacheDirectory; + $this->cacheResult = $cacheResult; + $this->cacheResultFile = $cacheResultFile; + $this->columns = $columns; + $this->colors = $colors; + $this->stderr = $stderr; + $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; + $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; + $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; + $this->displayDetailsOnPhpunitDeprecations = $displayDetailsOnPhpunitDeprecations; + $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; + $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; + $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; + $this->reverseDefectList = $reverseDefectList; + $this->requireCoverageMetadata = $requireCoverageMetadata; + $this->bootstrap = $bootstrap; + $this->processIsolation = $processIsolation; + $this->failOnDeprecation = $failOnDeprecation; + $this->failOnPhpunitDeprecation = $failOnPhpunitDeprecation; + $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; + $this->failOnIncomplete = $failOnIncomplete; + $this->failOnNotice = $failOnNotice; + $this->failOnRisky = $failOnRisky; + $this->failOnSkipped = $failOnSkipped; + $this->failOnWarning = $failOnWarning; + $this->stopOnDefect = $stopOnDefect; + $this->stopOnDeprecation = $stopOnDeprecation; + $this->stopOnError = $stopOnError; + $this->stopOnFailure = $stopOnFailure; + $this->stopOnIncomplete = $stopOnIncomplete; + $this->stopOnNotice = $stopOnNotice; + $this->stopOnRisky = $stopOnRisky; + $this->stopOnSkipped = $stopOnSkipped; + $this->stopOnWarning = $stopOnWarning; + $this->extensionsDirectory = $extensionsDirectory; + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + $this->beStrictAboutOutputDuringTests = $beStrictAboutOutputDuringTests; + $this->beStrictAboutTestsThatDoNotTestAnything = $beStrictAboutTestsThatDoNotTestAnything; + $this->beStrictAboutCoverageMetadata = $beStrictAboutCoverageMetadata; + $this->enforceTimeLimit = $enforceTimeLimit; + $this->defaultTimeLimit = $defaultTimeLimit; + $this->timeoutForSmallTests = $timeoutForSmallTests; + $this->timeoutForMediumTests = $timeoutForMediumTests; + $this->timeoutForLargeTests = $timeoutForLargeTests; + $this->defaultTestSuite = $defaultTestSuite; + $this->executionOrder = $executionOrder; + $this->resolveDependencies = $resolveDependencies; + $this->defectsFirst = $defectsFirst; + $this->backupGlobals = $backupGlobals; + $this->backupStaticProperties = $backupStaticProperties; + $this->registerMockObjectsFromTestArgumentsRecursively = $registerMockObjectsFromTestArgumentsRecursively; + $this->testdoxPrinter = $testdoxPrinter; + $this->controlGarbageCollector = $controlGarbageCollector; + $this->numberOfTestsBeforeGarbageCollection = $numberOfTestsBeforeGarbageCollection; + } + + /** + * @psalm-assert-if-true !null $this->cacheDirectory + */ + public function hasCacheDirectory(): bool + { + return $this->cacheDirectory !== null; + } + + /** + * @throws Exception + */ + public function cacheDirectory(): string + { + if (!$this->hasCacheDirectory()) { + throw new Exception('Cache directory is not configured'); + } + + return $this->cacheDirectory; + } + + public function cacheResult(): bool + { + return $this->cacheResult; + } + + /** + * @psalm-assert-if-true !null $this->cacheResultFile + * + * @deprecated + */ + public function hasCacheResultFile(): bool + { + return $this->cacheResultFile !== null; + } + + /** + * @throws Exception + * + * @deprecated + */ + public function cacheResultFile(): string + { + if (!$this->hasCacheResultFile()) { + throw new Exception('Cache result file is not configured'); + } + + return $this->cacheResultFile; + } + + public function columns(): int|string + { + return $this->columns; + } + + public function colors(): string + { + return $this->colors; + } + + public function stderr(): bool + { + return $this->stderr; + } + + public function displayDetailsOnIncompleteTests(): bool + { + return $this->displayDetailsOnIncompleteTests; + } + + public function displayDetailsOnSkippedTests(): bool + { + return $this->displayDetailsOnSkippedTests; + } + + public function displayDetailsOnTestsThatTriggerDeprecations(): bool + { + return $this->displayDetailsOnTestsThatTriggerDeprecations; + } + + public function displayDetailsOnPhpunitDeprecations(): bool + { + return $this->displayDetailsOnPhpunitDeprecations; + } + + public function displayDetailsOnTestsThatTriggerErrors(): bool + { + return $this->displayDetailsOnTestsThatTriggerErrors; + } + + public function displayDetailsOnTestsThatTriggerNotices(): bool + { + return $this->displayDetailsOnTestsThatTriggerNotices; + } + + public function displayDetailsOnTestsThatTriggerWarnings(): bool + { + return $this->displayDetailsOnTestsThatTriggerWarnings; + } + + public function reverseDefectList(): bool + { + return $this->reverseDefectList; + } + + public function requireCoverageMetadata(): bool + { + return $this->requireCoverageMetadata; + } + + /** + * @psalm-assert-if-true !null $this->bootstrap + */ + public function hasBootstrap(): bool + { + return $this->bootstrap !== null; + } + + /** + * @throws Exception + */ + public function bootstrap(): string + { + if (!$this->hasBootstrap()) { + throw new Exception('Bootstrap script is not configured'); + } + + return $this->bootstrap; + } + + public function processIsolation(): bool + { + return $this->processIsolation; + } + + public function failOnDeprecation(): bool + { + return $this->failOnDeprecation; + } + + public function failOnPhpunitDeprecation(): bool + { + return $this->failOnPhpunitDeprecation; + } + + public function failOnEmptyTestSuite(): bool + { + return $this->failOnEmptyTestSuite; + } + + public function failOnIncomplete(): bool + { + return $this->failOnIncomplete; + } + + public function failOnNotice(): bool + { + return $this->failOnNotice; + } + + public function failOnRisky(): bool + { + return $this->failOnRisky; + } + + public function failOnSkipped(): bool + { + return $this->failOnSkipped; + } + + public function failOnWarning(): bool + { + return $this->failOnWarning; + } + + public function stopOnDefect(): bool + { + return $this->stopOnDefect; + } + + public function stopOnDeprecation(): bool + { + return $this->stopOnDeprecation; + } + + public function stopOnError(): bool + { + return $this->stopOnError; + } + + public function stopOnFailure(): bool + { + return $this->stopOnFailure; + } + + public function stopOnIncomplete(): bool + { + return $this->stopOnIncomplete; + } + + public function stopOnNotice(): bool + { + return $this->stopOnNotice; + } + + public function stopOnRisky(): bool + { + return $this->stopOnRisky; + } + + public function stopOnSkipped(): bool + { + return $this->stopOnSkipped; + } + + public function stopOnWarning(): bool + { + return $this->stopOnWarning; + } + + /** + * @psalm-assert-if-true !null $this->extensionsDirectory + */ + public function hasExtensionsDirectory(): bool + { + return $this->extensionsDirectory !== null; + } + + /** + * @psalm-return non-empty-string + * + * @throws Exception + */ + public function extensionsDirectory(): string + { + if (!$this->hasExtensionsDirectory()) { + throw new Exception('Extensions directory is not configured'); + } + + return $this->extensionsDirectory; + } + + public function beStrictAboutChangesToGlobalState(): bool + { + return $this->beStrictAboutChangesToGlobalState; + } + + public function beStrictAboutOutputDuringTests(): bool + { + return $this->beStrictAboutOutputDuringTests; + } + + public function beStrictAboutTestsThatDoNotTestAnything(): bool + { + return $this->beStrictAboutTestsThatDoNotTestAnything; + } + + public function beStrictAboutCoverageMetadata(): bool + { + return $this->beStrictAboutCoverageMetadata; + } + + public function enforceTimeLimit(): bool + { + return $this->enforceTimeLimit; + } + + public function defaultTimeLimit(): int + { + return $this->defaultTimeLimit; + } + + public function timeoutForSmallTests(): int + { + return $this->timeoutForSmallTests; + } + + public function timeoutForMediumTests(): int + { + return $this->timeoutForMediumTests; + } + + public function timeoutForLargeTests(): int + { + return $this->timeoutForLargeTests; + } + + /** + * @psalm-assert-if-true !null $this->defaultTestSuite + */ + public function hasDefaultTestSuite(): bool + { + return $this->defaultTestSuite !== null; + } + + /** + * @throws Exception + */ + public function defaultTestSuite(): string + { + if (!$this->hasDefaultTestSuite()) { + throw new Exception('Default test suite is not configured'); + } + + return $this->defaultTestSuite; + } + + public function executionOrder(): int + { + return $this->executionOrder; + } + + public function resolveDependencies(): bool + { + return $this->resolveDependencies; + } + + public function defectsFirst(): bool + { + return $this->defectsFirst; + } + + public function backupGlobals(): bool + { + return $this->backupGlobals; + } + + public function backupStaticProperties(): bool + { + return $this->backupStaticProperties; + } + + /** + * @deprecated + */ + public function registerMockObjectsFromTestArgumentsRecursively(): bool + { + return $this->registerMockObjectsFromTestArgumentsRecursively; + } + + public function testdoxPrinter(): bool + { + return $this->testdoxPrinter; + } + + public function controlGarbageCollector(): bool + { + return $this->controlGarbageCollector; + } + + public function numberOfTestsBeforeGarbageCollection(): int + { + return $this->numberOfTestsBeforeGarbageCollection; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php new file mode 100644 index 000000000..ef413ca0f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class FailedSchemaDetectionResult extends SchemaDetectionResult +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php new file mode 100644 index 000000000..7f036f9f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Util\Xml\XmlException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +abstract class SchemaDetectionResult +{ + /** + * @psalm-assert-if-true SuccessfulSchemaDetectionResult $this + */ + public function detected(): bool + { + return false; + } + + /** + * @throws XmlException + */ + public function version(): string + { + throw new XmlException('No supported schema was detected'); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php new file mode 100644 index 000000000..9ad74c61a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.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 PHPUnit\TextUI\XmlConfiguration; + +use PHPUnit\Util\Xml\Loader; +use PHPUnit\Util\Xml\XmlException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SchemaDetector +{ + /** + * @throws XmlException + */ + public function detect(string $filename): SchemaDetectionResult + { + $document = (new Loader)->loadFile($filename); + + $schemaFinder = new SchemaFinder; + + foreach ($schemaFinder->available() as $candidate) { + $schema = (new SchemaFinder)->find($candidate); + + if (!(new Validator)->validate($document, $schema)->hasValidationErrors()) { + return new SuccessfulSchemaDetectionResult($candidate); + } + } + + return new FailedSchemaDetectionResult; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php new file mode 100644 index 000000000..d7eabb11e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class SuccessfulSchemaDetectionResult extends SchemaDetectionResult +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $version; + + /** + * @psalm-param non-empty-string $version + */ + public function __construct(string $version) + { + $this->version = $version; + } + + /** + * @psalm-assert-if-true SuccessfulSchemaDetectionResult $this + */ + public function detected(): bool + { + return true; + } + + /** + * @psalm-return non-empty-string + */ + public function version(): string + { + return $this->version; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php new file mode 100644 index 000000000..b86e8d803 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function assert; +use function defined; +use function is_file; +use function rsort; +use function sprintf; +use DirectoryIterator; +use PHPUnit\Runner\Version; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SchemaFinder +{ + /** + * @psalm-return non-empty-list + */ + public function available(): array + { + $result = [Version::series()]; + + foreach ((new DirectoryIterator($this->path() . 'schema')) as $file) { + if ($file->isDot()) { + continue; + } + + $version = $file->getBasename('.xsd'); + + assert(!empty($version)); + + $result[] = $version; + } + + rsort($result); + + return $result; + } + + /** + * @throws CannotFindSchemaException + */ + public function find(string $version): string + { + if ($version === Version::series()) { + $filename = $this->path() . 'phpunit.xsd'; + } else { + $filename = $this->path() . 'schema/' . $version . '.xsd'; + } + + if (!is_file($filename)) { + throw new CannotFindSchemaException( + sprintf( + 'Schema for PHPUnit %s is not available', + $version, + ), + ); + } + + return $filename; + } + + private function path(): string + { + if (defined('__PHPUNIT_PHAR_ROOT__')) { + return __PHPUNIT_PHAR_ROOT__ . '/'; + } + + return __DIR__ . '/../../../../'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php new file mode 100644 index 000000000..7721ca4ed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use const PHP_VERSION; +use function array_merge; +use function array_unique; +use function explode; +use function in_array; +use function is_dir; +use function is_file; +use function str_contains; +use function version_compare; +use PHPUnit\Framework\Exception as FrameworkException; +use PHPUnit\Framework\TestSuite as TestSuiteObject; +use PHPUnit\TextUI\Configuration\TestSuiteCollection; +use PHPUnit\TextUI\RuntimeException; +use PHPUnit\TextUI\TestDirectoryNotFoundException; +use PHPUnit\TextUI\TestFileNotFoundException; +use SebastianBergmann\FileIterator\Facade; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteMapper +{ + /** + * @psalm-param non-empty-string $xmlConfigurationFile, + * + * @throws RuntimeException + * @throws TestDirectoryNotFoundException + * @throws TestFileNotFoundException + */ + public function map(string $xmlConfigurationFile, TestSuiteCollection $configuration, string $filter, string $excludedTestSuites): TestSuiteObject + { + try { + $filterAsArray = $filter ? explode(',', $filter) : []; + $excludedFilterAsArray = $excludedTestSuites ? explode(',', $excludedTestSuites) : []; + $result = TestSuiteObject::empty($xmlConfigurationFile); + + foreach ($configuration as $testSuiteConfiguration) { + if (!empty($filterAsArray) && !in_array($testSuiteConfiguration->name(), $filterAsArray, true)) { + continue; + } + + if (!empty($excludedFilterAsArray) && in_array($testSuiteConfiguration->name(), $excludedFilterAsArray, true)) { + continue; + } + + $exclude = []; + + foreach ($testSuiteConfiguration->exclude()->asArray() as $file) { + $exclude[] = $file->path(); + } + + $files = []; + + foreach ($testSuiteConfiguration->directories() as $directory) { + if (!str_contains($directory->path(), '*') && !is_dir($directory->path())) { + throw new TestDirectoryNotFoundException($directory->path()); + } + + if (!version_compare(PHP_VERSION, $directory->phpVersion(), $directory->phpVersionOperator()->asString())) { + continue; + } + + $files = array_merge( + $files, + (new Facade)->getFilesAsArray( + $directory->path(), + $directory->suffix(), + $directory->prefix(), + $exclude, + ), + ); + } + + foreach ($testSuiteConfiguration->files() as $file) { + if (!is_file($file->path())) { + throw new TestFileNotFoundException($file->path()); + } + + if (!version_compare(PHP_VERSION, $file->phpVersion(), $file->phpVersionOperator()->asString())) { + continue; + } + + $files[] = $file->path(); + } + + if (!empty($files)) { + $testSuite = TestSuiteObject::empty($testSuiteConfiguration->name()); + + $testSuite->addTestFiles(array_unique($files)); + + $result->addTest($testSuite); + } + } + + return $result; + } catch (FrameworkException $e) { + throw new RuntimeException( + $e->getMessage(), + $e->getCode(), + $e, + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php new file mode 100644 index 000000000..d62a38b9a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use const PHP_EOL; +use function sprintf; +use function trim; +use LibXMLError; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class ValidationResult +{ + /** + * @psalm-var array> + */ + private readonly array $validationErrors; + + /** + * @psalm-param array $errors + */ + public static function fromArray(array $errors): self + { + $validationErrors = []; + + foreach ($errors as $error) { + if (!isset($validationErrors[$error->line])) { + $validationErrors[$error->line] = []; + } + + $validationErrors[$error->line][] = trim($error->message); + } + + return new self($validationErrors); + } + + private function __construct(array $validationErrors) + { + $this->validationErrors = $validationErrors; + } + + public function hasValidationErrors(): bool + { + return !empty($this->validationErrors); + } + + public function asString(): string + { + $buffer = ''; + + foreach ($this->validationErrors as $line => $validationErrorsOnLine) { + $buffer .= sprintf(PHP_EOL . ' Line %d:' . PHP_EOL, $line); + + foreach ($validationErrorsOnLine as $validationError) { + $buffer .= sprintf(' - %s' . PHP_EOL, $validationError); + } + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php new file mode 100644 index 000000000..7f7889e09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\XmlConfiguration; + +use function file_get_contents; +use function libxml_clear_errors; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use DOMDocument; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Validator +{ + public function validate(DOMDocument $document, string $xsdFilename): ValidationResult + { + $originalErrorHandling = libxml_use_internal_errors(true); + + $document->schemaValidateSource(file_get_contents($xsdFilename)); + + $errors = libxml_get_errors(); + libxml_clear_errors(); + libxml_use_internal_errors($originalErrorHandling); + + return ValidationResult::fromArray($errors); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php new file mode 100644 index 000000000..519d13785 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/CannotOpenSocketException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class CannotOpenSocketException extends RuntimeException implements Exception +{ + public function __construct(string $hostname, int $port) + { + parent::__construct( + sprintf( + 'Cannot open socket %s:%d', + $hostname, + $port, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php new file mode 100644 index 000000000..6b370ca07 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php new file mode 100644 index 000000000..441afd2a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/InvalidSocketException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidSocketException extends RuntimeException implements Exception +{ + public function __construct(string $socket) + { + parent::__construct( + sprintf( + '"%s" does not match "socket://hostname:port" format', + $socket, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php new file mode 100644 index 000000000..875a0487c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php new file mode 100644 index 000000000..9b35390cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestDirectoryNotFoundException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct( + sprintf( + 'Test directory "%s" not found', + $path, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php new file mode 100644 index 000000000..46c9df806 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Exception/TestFileNotFoundException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFileNotFoundException extends RuntimeException implements Exception +{ + public function __construct(string $path) + { + parent::__construct( + sprintf( + 'Test file "%s" not found', + $path, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Help.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Help.php new file mode 100644 index 000000000..4e2b6afab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Help.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 PHPUnit\TextUI; + +use const PHP_EOL; +use function count; +use function defined; +use function explode; +use function max; +use function preg_replace_callback; +use function str_pad; +use function str_repeat; +use function strlen; +use function wordwrap; +use PHPUnit\Util\Color; +use SebastianBergmann\Environment\Console; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Help +{ + private const LEFT_MARGIN = ' '; + private int $lengthOfLongestOptionName = 0; + private readonly int $columnsAvailableForDescription; + private ?bool $hasColor; + + public function __construct(?int $width = null, ?bool $withColor = null) + { + if ($width === null) { + $width = (new Console)->getNumberOfColumns(); + } + + if ($withColor === null) { + $this->hasColor = (new Console)->hasColorSupport(); + } else { + $this->hasColor = $withColor; + } + + foreach ($this->elements() as $options) { + foreach ($options as $option) { + if (isset($option['arg'])) { + $this->lengthOfLongestOptionName = max($this->lengthOfLongestOptionName, strlen($option['arg'])); + } + } + } + + $this->columnsAvailableForDescription = $width - $this->lengthOfLongestOptionName - 4; + } + + public function generate(): string + { + if ($this->hasColor) { + return $this->writeWithColor(); + } + + return $this->writeWithoutColor(); + } + + private function writeWithoutColor(): string + { + $buffer = ''; + + foreach ($this->elements() as $section => $options) { + $buffer .= "{$section}:" . PHP_EOL; + + if ($section !== 'Usage') { + $buffer .= PHP_EOL; + } + + foreach ($options as $option) { + if (isset($option['spacer'])) { + $buffer .= PHP_EOL; + } + + if (isset($option['text'])) { + $buffer .= self::LEFT_MARGIN . $option['text'] . PHP_EOL; + } + + if (isset($option['arg'])) { + $arg = str_pad($option['arg'], $this->lengthOfLongestOptionName); + + $buffer .= self::LEFT_MARGIN . $arg . ' ' . $option['desc'] . PHP_EOL; + } + } + + $buffer .= PHP_EOL; + } + + return $buffer; + } + + private function writeWithColor(): string + { + $buffer = ''; + + foreach ($this->elements() as $section => $options) { + $buffer .= Color::colorize('fg-yellow', "{$section}:") . PHP_EOL; + + if ($section !== 'Usage') { + $buffer .= PHP_EOL; + } + + foreach ($options as $option) { + if (isset($option['spacer'])) { + $buffer .= PHP_EOL; + } + + if (isset($option['text'])) { + $buffer .= self::LEFT_MARGIN . $option['text'] . PHP_EOL; + } + + if (isset($option['arg'])) { + $arg = Color::colorize('fg-green', str_pad($option['arg'], $this->lengthOfLongestOptionName)); + $arg = preg_replace_callback( + '/(<[^>]+>)/', + static fn ($matches) => Color::colorize('fg-cyan', $matches[0]), + $arg, + ); + + $desc = explode(PHP_EOL, wordwrap($option['desc'], $this->columnsAvailableForDescription, PHP_EOL)); + + $buffer .= self::LEFT_MARGIN . $arg . ' ' . $desc[0] . PHP_EOL; + + for ($i = 1; $i < count($desc); $i++) { + $buffer .= str_repeat(' ', $this->lengthOfLongestOptionName + 3) . $desc[$i] . PHP_EOL; + } + } + } + + $buffer .= PHP_EOL; + } + + return $buffer; + } + + /** + * @psalm-return array> + */ + private function elements(): array + { + $elements = [ + 'Usage' => [ + ['text' => 'phpunit [options] ...'], + ], + + 'Configuration' => [ + ['arg' => '--bootstrap ', 'desc' => 'A PHP script that is included before the tests run'], + ['arg' => '-c|--configuration ', 'desc' => 'Read configuration from XML file'], + ['arg' => '--no-configuration', 'desc' => 'Ignore default configuration file (phpunit.xml)'], + ['arg' => '--no-extensions', 'desc' => 'Do not load PHPUnit extensions'], + ['arg' => '--include-path ', 'desc' => 'Prepend PHP\'s include_path with given path(s)'], + ['arg' => '-d ', 'desc' => 'Sets a php.ini value'], + ['arg' => '--cache-directory ', 'desc' => 'Specify cache directory'], + ['arg' => '--generate-configuration', 'desc' => 'Generate configuration file with suggested settings'], + ['arg' => '--migrate-configuration', 'desc' => 'Migrate configuration file to current format'], + ['arg' => '--generate-baseline ', 'desc' => 'Generate baseline for issues'], + ['arg' => '--use-baseline ', 'desc' => 'Use baseline to ignore issues'], + ['arg' => '--ignore-baseline', 'desc' => 'Do not use baseline to ignore issues'], + ], + + 'Selection' => [ + ['arg' => '--list-suites', 'desc' => 'List available test suites'], + ['arg' => '--testsuite ', 'desc' => 'Only run tests from the specified test suite(s)'], + ['arg' => '--exclude-testsuite ', 'desc' => 'Exclude tests from the specified test suite(s)'], + ['arg' => '--list-groups', 'desc' => 'List available test groups'], + ['arg' => '--group ', 'desc' => 'Only run tests from the specified group(s)'], + ['arg' => '--exclude-group ', 'desc' => 'Exclude tests from the specified group(s)'], + ['arg' => '--covers ', 'desc' => 'Only run tests that intend to cover '], + ['arg' => '--uses ', 'desc' => 'Only run tests that intend to use '], + ['arg' => '--list-tests', 'desc' => 'List available tests'], + ['arg' => '--list-tests-xml ', 'desc' => 'List available tests in XML format'], + ['arg' => '--filter ', 'desc' => 'Filter which tests to run'], + ['arg' => '--test-suffix ', 'desc' => 'Only search for test in files with specified suffix(es). Default: Test.php,.phpt'], + ], + + 'Execution' => [ + ['arg' => '--process-isolation', 'desc' => 'Run each test in a separate PHP process'], + ['arg' => '--globals-backup', 'desc' => 'Backup and restore $GLOBALS for each test'], + ['arg' => '--static-backup', 'desc' => 'Backup and restore static properties for each test'], + ['spacer' => ''], + + ['arg' => '--strict-coverage', 'desc' => 'Be strict about code coverage metadata'], + ['arg' => '--strict-global-state', 'desc' => 'Be strict about changes to global state'], + ['arg' => '--disallow-test-output', 'desc' => 'Be strict about output during tests'], + ['arg' => '--enforce-time-limit', 'desc' => 'Enforce time limit based on test size'], + ['arg' => '--default-time-limit ', 'desc' => 'Timeout in seconds for tests that have no declared size'], + ['arg' => '--dont-report-useless-tests', 'desc' => 'Do not report tests that do not test anything'], + ['spacer' => ''], + + ['arg' => '--stop-on-defect', 'desc' => 'Stop after first error, failure, warning, or risky test'], + ['arg' => '--stop-on-error', 'desc' => 'Stop after first error'], + ['arg' => '--stop-on-failure', 'desc' => 'Stop after first failure'], + ['arg' => '--stop-on-warning', 'desc' => 'Stop after first warning'], + ['arg' => '--stop-on-risky', 'desc' => 'Stop after first risky test'], + ['arg' => '--stop-on-deprecation', 'desc' => 'Stop after first test that triggered a deprecation'], + ['arg' => '--stop-on-notice', 'desc' => 'Stop after first test that triggered a notice'], + ['arg' => '--stop-on-skipped', 'desc' => 'Stop after first skipped test'], + ['arg' => '--stop-on-incomplete', 'desc' => 'Stop after first incomplete test'], + ['spacer' => ''], + + ['arg' => '--fail-on-empty-test-suite', 'desc' => 'Signal failure using shell exit code when no tests were run'], + ['arg' => '--fail-on-warning', 'desc' => 'Signal failure using shell exit code when a warning was triggered'], + ['arg' => '--fail-on-risky', 'desc' => 'Signal failure using shell exit code when a test was considered risky'], + ['arg' => '--fail-on-deprecation', 'desc' => 'Signal failure using shell exit code when a deprecation was triggered'], + ['arg' => '--fail-on-phpunit-deprecation', 'desc' => 'Signal failure using shell exit code when a PHPUnit deprecation was triggered'], + ['arg' => '--fail-on-notice', 'desc' => 'Signal failure using shell exit code when a notice was triggered'], + ['arg' => '--fail-on-skipped', 'desc' => 'Signal failure using shell exit code when a test was skipped'], + ['arg' => '--fail-on-incomplete', 'desc' => 'Signal failure using shell exit code when a test was marked incomplete'], + ['spacer' => ''], + + ['arg' => '--cache-result', 'desc' => 'Write test results to cache file'], + ['arg' => '--do-not-cache-result', 'desc' => 'Do not write test results to cache file'], + ['spacer' => ''], + + ['arg' => '--order-by ', 'desc' => 'Run tests in order: default|defects|depends|duration|no-depends|random|reverse|size'], + ['arg' => '--random-order-seed ', 'desc' => 'Use the specified random seed when running tests in random order'], + ], + + 'Reporting' => [ + ['arg' => '--colors ', 'desc' => 'Use colors in output ("never", "auto" or "always")'], + ['arg' => '--columns ', 'desc' => 'Number of columns to use for progress output'], + ['arg' => '--columns max', 'desc' => 'Use maximum number of columns for progress output'], + ['arg' => '--stderr', 'desc' => 'Write to STDERR instead of STDOUT'], + ['spacer' => ''], + + ['arg' => '--no-progress', 'desc' => 'Disable output of test execution progress'], + ['arg' => '--no-results', 'desc' => 'Disable output of test results'], + ['arg' => '--no-output', 'desc' => 'Disable all output'], + ['spacer' => ''], + + ['arg' => '--display-incomplete', 'desc' => 'Display details for incomplete tests'], + ['arg' => '--display-skipped', 'desc' => 'Display details for skipped tests'], + ['arg' => '--display-deprecations', 'desc' => 'Display details for deprecations triggered by tests'], + ['arg' => '--display-phpunit-deprecations', 'desc' => 'Display details for PHPUnit deprecations'], + ['arg' => '--display-errors', 'desc' => 'Display details for errors triggered by tests'], + ['arg' => '--display-notices', 'desc' => 'Display details for notices triggered by tests'], + ['arg' => '--display-warnings', 'desc' => 'Display details for warnings triggered by tests'], + ['arg' => '--reverse-list', 'desc' => 'Print defects in reverse order'], + ['spacer' => ''], + + ['arg' => '--teamcity', 'desc' => 'Replace default progress and result output with TeamCity format'], + ['arg' => '--testdox', 'desc' => 'Replace default result output with TestDox format'], + ['spacer' => ''], + + ['arg' => '--debug', 'desc' => 'Replace default progress and result output with debugging information'], + ], + + 'Logging' => [ + ['arg' => '--log-junit ', 'desc' => 'Write test results in JUnit XML format to file'], + ['arg' => '--log-teamcity ', 'desc' => 'Write test results in TeamCity format to file'], + ['arg' => '--testdox-html ', 'desc' => 'Write test results in TestDox format (HTML) to file'], + ['arg' => '--testdox-text ', 'desc' => 'Write test results in TestDox format (plain text) to file'], + ['arg' => '--log-events-text ', 'desc' => 'Stream events as plain text to file'], + ['arg' => '--log-events-verbose-text ', 'desc' => 'Stream events as plain text with extended information to file'], + ['arg' => '--no-logging', 'desc' => 'Ignore logging configured in the XML configuration file'], + ], + + 'Code Coverage' => [ + ['arg' => '--coverage-clover ', 'desc' => 'Write code coverage report in Clover XML format to file'], + ['arg' => '--coverage-cobertura ', 'desc' => 'Write code coverage report in Cobertura XML format to file'], + ['arg' => '--coverage-crap4j ', 'desc' => 'Write code coverage report in Crap4J XML format to file'], + ['arg' => '--coverage-html ', 'desc' => 'Write code coverage report in HTML format to directory'], + ['arg' => '--coverage-php ', 'desc' => 'Write serialized code coverage data to file'], + ['arg' => '--coverage-text=', 'desc' => 'Write code coverage report in text format to file [default: standard output]'], + ['arg' => '--only-summary-for-coverage-text', 'desc' => 'Option for code coverage report in text format: only show summary'], + ['arg' => '--show-uncovered-for-coverage-text', 'desc' => 'Option for code coverage report in text format: show uncovered files'], + ['arg' => '--coverage-xml ', 'desc' => 'Write code coverage report in XML format to directory'], + ['arg' => '--warm-coverage-cache', 'desc' => 'Warm static analysis cache'], + ['arg' => '--coverage-filter ', 'desc' => 'Include in code coverage reporting'], + ['arg' => '--path-coverage', 'desc' => 'Report path coverage in addition to line coverage'], + ['arg' => '--disable-coverage-ignore', 'desc' => 'Disable metadata for ignoring code coverage'], + ['arg' => '--no-coverage', 'desc' => 'Ignore code coverage reporting configured in the XML configuration file'], + ], + ]; + + if (defined('__PHPUNIT_PHAR__')) { + $elements['PHAR'] = [ + ['arg' => '--manifest', 'desc' => 'Print Software Bill of Materials (SBOM) in plain-text format'], + ['arg' => '--sbom', 'desc' => 'Print Software Bill of Materials (SBOM) in CycloneDX XML format'], + ['arg' => '--composer-lock', 'desc' => 'Print composer.lock file used to build the PHAR'], + ]; + } + + $elements['Miscellaneous'] = [ + ['arg' => '-h|--help', 'desc' => 'Prints this usage information'], + ['arg' => '--version', 'desc' => 'Prints the version and exits'], + ['arg' => '--atleast-version ', 'desc' => 'Checks that version is greater than and exits'], + ['arg' => '--check-version', 'desc' => 'Checks whether PHPUnit is the latest version and exits'], + ]; + + return $elements; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php new file mode 100644 index 000000000..ec8d3b6c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php @@ -0,0 +1,402 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use function floor; +use function sprintf; +use function str_contains; +use function str_repeat; +use function strlen; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErrorTriggered; +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\TestRunner\ExecutionStarted; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Framework\TestStatus\TestStatus; +use PHPUnit\TextUI\Configuration\Source; +use PHPUnit\TextUI\Configuration\SourceFilter; +use PHPUnit\TextUI\Output\Printer; +use PHPUnit\Util\Color; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ProgressPrinter +{ + private readonly Printer $printer; + private readonly bool $colors; + private readonly int $numberOfColumns; + private readonly Source $source; + private int $column = 0; + private int $numberOfTests = 0; + private int $numberOfTestsWidth = 0; + private int $maxColumn = 0; + private int $numberOfTestsRun = 0; + private ?TestStatus $status = null; + private bool $prepared = false; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Printer $printer, Facade $facade, bool $colors, int $numberOfColumns, Source $source) + { + $this->printer = $printer; + $this->colors = $colors; + $this->numberOfColumns = $numberOfColumns; + $this->source = $source; + + $this->registerSubscribers($facade); + } + + public function testRunnerExecutionStarted(ExecutionStarted $event): void + { + $this->numberOfTestsRun = 0; + $this->numberOfTests = $event->testSuite()->count(); + $this->numberOfTestsWidth = strlen((string) $this->numberOfTests); + $this->column = 0; + $this->maxColumn = $this->numberOfColumns - strlen(' / (XXX%)') - (2 * $this->numberOfTestsWidth); + } + + public function beforeTestClassMethodErrored(): void + { + $this->printProgressForError(); + $this->updateTestStatus(TestStatus::error()); + } + + public function testPrepared(): void + { + $this->prepared = true; + } + + public function testSkipped(): void + { + if (!$this->prepared) { + $this->printProgressForSkipped(); + } else { + $this->updateTestStatus(TestStatus::skipped()); + } + } + + public function testMarkedIncomplete(): void + { + $this->updateTestStatus(TestStatus::incomplete()); + } + + public function testTriggeredNotice(NoticeTriggered $event): void + { + if ($event->ignoredByBaseline()) { + return; + } + + if ($this->source->restrictNotices() && + !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + if (!$this->source->ignoreSuppressionOfNotices() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::notice()); + } + + public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void + { + if ($event->ignoredByBaseline()) { + return; + } + + if ($this->source->restrictNotices() && + !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + if (!$this->source->ignoreSuppressionOfPhpNotices() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::notice()); + } + + public function testTriggeredDeprecation(DeprecationTriggered $event): void + { + if ($event->ignoredByBaseline() || $event->ignoredByTest()) { + return; + } + + if ($this->source->restrictDeprecations() && + !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + if (!$this->source->ignoreSuppressionOfDeprecations() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::deprecation()); + } + + public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void + { + if ($event->ignoredByBaseline() || $event->ignoredByTest()) { + return; + } + + if ($this->source->restrictDeprecations() && + !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + if (!$this->source->ignoreSuppressionOfPhpDeprecations() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::deprecation()); + } + + public function testTriggeredPhpunitDeprecation(): void + { + $this->updateTestStatus(TestStatus::deprecation()); + } + + public function testConsideredRisky(): void + { + $this->updateTestStatus(TestStatus::risky()); + } + + public function testTriggeredWarning(WarningTriggered $event): void + { + if ($event->ignoredByBaseline()) { + return; + } + + if ($this->source->restrictWarnings() && + !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + if (!$this->source->ignoreSuppressionOfWarnings() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::warning()); + } + + public function testTriggeredPhpWarning(PhpWarningTriggered $event): void + { + if ($event->ignoredByBaseline()) { + return; + } + + if ($this->source->restrictWarnings() && + !(new SourceFilter)->includes($this->source, $event->file())) { + return; + } + + if (!$this->source->ignoreSuppressionOfPhpWarnings() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::warning()); + } + + public function testTriggeredPhpunitWarning(): void + { + $this->updateTestStatus(TestStatus::warning()); + } + + public function testTriggeredError(ErrorTriggered $event): void + { + if (!$this->source->ignoreSuppressionOfErrors() && $event->wasSuppressed()) { + return; + } + + $this->updateTestStatus(TestStatus::error()); + } + + public function testFailed(): void + { + $this->updateTestStatus(TestStatus::failure()); + } + + public function testErrored(Errored $event): void + { + /* + * @todo Eliminate this special case + */ + if (str_contains($event->asString(), 'Test was run in child process and ended unexpectedly')) { + $this->updateTestStatus(TestStatus::error()); + + return; + } + + if (!$this->prepared) { + $this->printProgressForError(); + } else { + $this->updateTestStatus(TestStatus::error()); + } + } + + public function testFinished(): void + { + if ($this->status === null) { + $this->printProgressForSuccess(); + } elseif ($this->status->isSkipped()) { + $this->printProgressForSkipped(); + } elseif ($this->status->isIncomplete()) { + $this->printProgressForIncomplete(); + } elseif ($this->status->isRisky()) { + $this->printProgressForRisky(); + } elseif ($this->status->isNotice()) { + $this->printProgressForNotice(); + } elseif ($this->status->isDeprecation()) { + $this->printProgressForDeprecation(); + } elseif ($this->status->isWarning()) { + $this->printProgressForWarning(); + } elseif ($this->status->isFailure()) { + $this->printProgressForFailure(); + } else { + $this->printProgressForError(); + } + + $this->status = null; + $this->prepared = false; + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private function registerSubscribers(Facade $facade): void + { + $facade->registerSubscribers( + new BeforeTestClassMethodErroredSubscriber($this), + new TestConsideredRiskySubscriber($this), + new TestErroredSubscriber($this), + new TestFailedSubscriber($this), + new TestFinishedSubscriber($this), + new TestMarkedIncompleteSubscriber($this), + new TestPreparedSubscriber($this), + new TestRunnerExecutionStartedSubscriber($this), + new TestSkippedSubscriber($this), + new TestTriggeredDeprecationSubscriber($this), + new TestTriggeredNoticeSubscriber($this), + new TestTriggeredPhpDeprecationSubscriber($this), + new TestTriggeredPhpNoticeSubscriber($this), + new TestTriggeredPhpunitDeprecationSubscriber($this), + new TestTriggeredPhpunitWarningSubscriber($this), + new TestTriggeredPhpWarningSubscriber($this), + new TestTriggeredWarningSubscriber($this), + ); + } + + private function updateTestStatus(TestStatus $status): void + { + if ($this->status !== null && + $this->status->isMoreImportantThan($status)) { + return; + } + + $this->status = $status; + } + + private function printProgressForSuccess(): void + { + $this->printProgress('.'); + } + + private function printProgressForSkipped(): void + { + $this->printProgressWithColor('fg-cyan, bold', 'S'); + } + + private function printProgressForIncomplete(): void + { + $this->printProgressWithColor('fg-yellow, bold', 'I'); + } + + private function printProgressForNotice(): void + { + $this->printProgressWithColor('fg-yellow, bold', 'N'); + } + + private function printProgressForDeprecation(): void + { + $this->printProgressWithColor('fg-yellow, bold', 'D'); + } + + private function printProgressForRisky(): void + { + $this->printProgressWithColor('fg-yellow, bold', 'R'); + } + + private function printProgressForWarning(): void + { + $this->printProgressWithColor('fg-yellow, bold', 'W'); + } + + private function printProgressForFailure(): void + { + $this->printProgressWithColor('bg-red, fg-white', 'F'); + } + + private function printProgressForError(): void + { + $this->printProgressWithColor('fg-red, bold', 'E'); + } + + private function printProgressWithColor(string $color, string $progress): void + { + if ($this->colors) { + $progress = Color::colorizeTextBox($color, $progress); + } + + $this->printProgress($progress); + } + + private function printProgress(string $progress): void + { + $this->printer->print($progress); + + $this->column++; + $this->numberOfTestsRun++; + + if ($this->column === $this->maxColumn || $this->numberOfTestsRun === $this->numberOfTests) { + if ($this->numberOfTestsRun === $this->numberOfTests) { + $this->printer->print(str_repeat(' ', $this->maxColumn - $this->column)); + } + + $this->printer->print( + sprintf( + ' %' . $this->numberOfTestsWidth . 'd / %' . + $this->numberOfTestsWidth . 'd (%3s%%)', + $this->numberOfTestsRun, + $this->numberOfTests, + floor(($this->numberOfTestsRun / $this->numberOfTests) * 100), + ), + ); + + if ($this->column === $this->maxColumn) { + $this->column = 0; + $this->printer->print("\n"); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php new file mode 100644 index 000000000..85e631592 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; +use PHPUnit\Event\Test\BeforeFirstTestMethodErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class BeforeTestClassMethodErroredSubscriber extends Subscriber implements BeforeFirstTestMethodErroredSubscriber +{ + public function notify(BeforeFirstTestMethodErrored $event): void + { + $this->printer()->beforeTestClassMethodErrored(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php new file mode 100644 index 000000000..f238ed22d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class Subscriber +{ + private readonly ProgressPrinter $printer; + + public function __construct(ProgressPrinter $printer) + { + $this->printer = $printer; + } + + protected function printer(): ProgressPrinter + { + return $this->printer; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php new file mode 100644 index 000000000..f72056de7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\ConsideredRiskySubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber +{ + public function notify(ConsideredRisky $event): void + { + $this->printer()->testConsideredRisky(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php new file mode 100644 index 000000000..2c07b789e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\Errored; +use PHPUnit\Event\Test\ErroredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestErroredSubscriber extends Subscriber implements ErroredSubscriber +{ + public function notify(Errored $event): void + { + $this->printer()->testErrored($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php new file mode 100644 index 000000000..27f330376 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\Failed; +use PHPUnit\Event\Test\FailedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFailedSubscriber extends Subscriber implements FailedSubscriber +{ + public function notify(Failed $event): void + { + $this->printer()->testFailed(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php new file mode 100644 index 000000000..fa4d95cb6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $this->printer()->testFinished(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php new file mode 100644 index 000000000..2be2d1f1f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\MarkedIncomplete; +use PHPUnit\Event\Test\MarkedIncompleteSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber +{ + public function notify(MarkedIncomplete $event): void + { + $this->printer()->testMarkedIncomplete(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php new file mode 100644 index 000000000..2225ea0ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\Prepared; +use PHPUnit\Event\Test\PreparedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber +{ + public function notify(Prepared $event): void + { + $this->printer()->testPrepared(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php new file mode 100644 index 000000000..666dcc93c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\TestRunner\ExecutionStarted; +use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunnerExecutionStartedSubscriber extends Subscriber implements ExecutionStartedSubscriber +{ + public function notify(ExecutionStarted $event): void + { + $this->printer()->testRunnerExecutionStarted($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php new file mode 100644 index 000000000..2b05a753b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\Skipped; +use PHPUnit\Event\Test\SkippedSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber +{ + public function notify(Skipped $event): void + { + $this->printer()->testSkipped(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php new file mode 100644 index 000000000..d7eb79702 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber +{ + public function notify(DeprecationTriggered $event): void + { + $this->printer()->testTriggeredDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php new file mode 100644 index 000000000..049a1e6d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\ErrorTriggered; +use PHPUnit\Event\Test\ErrorTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredErrorSubscriber extends Subscriber implements ErrorTriggeredSubscriber +{ + public function notify(ErrorTriggered $event): void + { + $this->printer()->testTriggeredError($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php new file mode 100644 index 000000000..e396c961a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\NoticeTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber +{ + public function notify(NoticeTriggered $event): void + { + $this->printer()->testTriggeredNotice($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php new file mode 100644 index 000000000..65a242081 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber +{ + public function notify(PhpDeprecationTriggered $event): void + { + $this->printer()->testTriggeredPhpDeprecation($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php new file mode 100644 index 000000000..f783fbc10 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber +{ + public function notify(PhpNoticeTriggered $event): void + { + $this->printer()->testTriggeredPhpNotice($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php new file mode 100644 index 000000000..18e723bd0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber +{ + public function notify(PhpWarningTriggered $event): void + { + $this->printer()->testTriggeredPhpWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php new file mode 100644 index 000000000..f273f8aad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitDeprecationTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitDeprecationSubscriber extends Subscriber implements PhpunitDeprecationTriggeredSubscriber +{ + public function notify(PhpunitDeprecationTriggered $event): void + { + $this->printer()->testTriggeredPhpunitDeprecation(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php new file mode 100644 index 000000000..12087c4dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredPhpunitWarningSubscriber extends Subscriber implements PhpunitWarningTriggeredSubscriber +{ + public function notify(PhpunitWarningTriggered $event): void + { + $this->printer()->testTriggeredPhpunitWarning(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php new file mode 100644 index 000000000..05188dce1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; + +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\Event\Test\WarningTriggeredSubscriber; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber +{ + public function notify(WarningTriggered $event): void + { + $this->printer()->testTriggeredWarning($event); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php new file mode 100644 index 000000000..4d1d37f15 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/ResultPrinter.php @@ -0,0 +1,626 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default; + +use const PHP_EOL; +use function array_keys; +use function array_merge; +use function array_reverse; +use function array_unique; +use function assert; +use function count; +use function explode; +use function ksort; +use function range; +use function sprintf; +use function str_starts_with; +use function strlen; +use function substr; +use function trim; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; +use PHPUnit\Event\Test\ConsideredRisky; +use PHPUnit\Event\Test\DeprecationTriggered; +use PHPUnit\Event\Test\ErrorTriggered; +use PHPUnit\Event\Test\NoticeTriggered; +use PHPUnit\Event\Test\PhpDeprecationTriggered; +use PHPUnit\Event\Test\PhpNoticeTriggered; +use PHPUnit\Event\Test\PhpunitDeprecationTriggered; +use PHPUnit\Event\Test\PhpunitErrorTriggered; +use PHPUnit\Event\Test\PhpunitWarningTriggered; +use PHPUnit\Event\Test\PhpWarningTriggered; +use PHPUnit\Event\Test\WarningTriggered; +use PHPUnit\TestRunner\TestResult\Issues\Issue; +use PHPUnit\TestRunner\TestResult\TestResult; +use PHPUnit\TextUI\Output\Printer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ResultPrinter +{ + private readonly Printer $printer; + private readonly bool $displayPhpunitErrors; + private readonly bool $displayPhpunitWarnings; + private readonly bool $displayTestsWithErrors; + private readonly bool $displayTestsWithFailedAssertions; + private readonly bool $displayRiskyTests; + private readonly bool $displayPhpunitDeprecations; + private readonly bool $displayDetailsOnIncompleteTests; + private readonly bool $displayDetailsOnSkippedTests; + private readonly bool $displayDetailsOnTestsThatTriggerDeprecations; + private readonly bool $displayDetailsOnTestsThatTriggerErrors; + private readonly bool $displayDetailsOnTestsThatTriggerNotices; + private readonly bool $displayDetailsOnTestsThatTriggerWarnings; + private readonly bool $displayDefectsInReverseOrder; + private bool $listPrinted = false; + + public function __construct(Printer $printer, bool $displayPhpunitErrors, bool $displayPhpunitWarnings, bool $displayPhpunitDeprecations, bool $displayTestsWithErrors, bool $displayTestsWithFailedAssertions, bool $displayRiskyTests, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $displayDefectsInReverseOrder) + { + $this->printer = $printer; + $this->displayPhpunitErrors = $displayPhpunitErrors; + $this->displayPhpunitWarnings = $displayPhpunitWarnings; + $this->displayPhpunitDeprecations = $displayPhpunitDeprecations; + $this->displayTestsWithErrors = $displayTestsWithErrors; + $this->displayTestsWithFailedAssertions = $displayTestsWithFailedAssertions; + $this->displayRiskyTests = $displayRiskyTests; + $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; + $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; + $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; + $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; + $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; + $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; + $this->displayDefectsInReverseOrder = $displayDefectsInReverseOrder; + } + + public function print(TestResult $result): void + { + if ($this->displayPhpunitErrors) { + $this->printPhpunitErrors($result); + } + + if ($this->displayPhpunitWarnings) { + $this->printTestRunnerWarnings($result); + } + + if ($this->displayPhpunitDeprecations) { + $this->printTestRunnerDeprecations($result); + } + + if ($this->displayTestsWithErrors) { + $this->printTestsWithErrors($result); + } + + if ($this->displayTestsWithFailedAssertions) { + $this->printTestsWithFailedAssertions($result); + } + + if ($this->displayPhpunitWarnings) { + $this->printDetailsOnTestsThatTriggeredPhpunitWarnings($result); + } + + if ($this->displayPhpunitDeprecations) { + $this->printDetailsOnTestsThatTriggeredPhpunitDeprecations($result); + } + + if ($this->displayRiskyTests) { + $this->printRiskyTests($result); + } + + if ($this->displayDetailsOnIncompleteTests) { + $this->printIncompleteTests($result); + } + + if ($this->displayDetailsOnSkippedTests) { + $this->printSkippedTestSuites($result); + $this->printSkippedTests($result); + } + + if ($this->displayDetailsOnTestsThatTriggerErrors) { + $this->printIssueList('error', $result->errors()); + } + + if ($this->displayDetailsOnTestsThatTriggerWarnings) { + $this->printIssueList('PHP warning', $result->phpWarnings()); + $this->printIssueList('warning', $result->warnings()); + } + + if ($this->displayDetailsOnTestsThatTriggerNotices) { + $this->printIssueList('PHP notice', $result->phpNotices()); + $this->printIssueList('notice', $result->notices()); + } + + if ($this->displayDetailsOnTestsThatTriggerDeprecations) { + $this->printIssueList('PHP deprecation', $result->phpDeprecations()); + $this->printIssueList('deprecation', $result->deprecations()); + } + } + + private function printPhpunitErrors(TestResult $result): void + { + if (!$result->hasTestTriggeredPhpunitErrorEvents()) { + return; + } + + $elements = $this->mapTestsWithIssuesEventsToElements($result->testTriggeredPhpunitErrorEvents()); + + $this->printListHeaderWithNumber($elements['numberOfTestsWithIssues'], 'PHPUnit error'); + $this->printList($elements['elements']); + } + + private function printDetailsOnTestsThatTriggeredPhpunitDeprecations(TestResult $result): void + { + if (!$result->hasTestTriggeredPhpunitDeprecationEvents()) { + return; + } + + $elements = $this->mapTestsWithIssuesEventsToElements($result->testTriggeredPhpunitDeprecationEvents()); + + $this->printListHeaderWithNumberOfTestsAndNumberOfIssues( + $elements['numberOfTestsWithIssues'], + $elements['numberOfIssues'], + 'PHPUnit deprecation', + ); + + $this->printList($elements['elements']); + } + + private function printTestRunnerWarnings(TestResult $result): void + { + if (!$result->hasTestRunnerTriggeredWarningEvents()) { + return; + } + + $elements = []; + + foreach ($result->testRunnerTriggeredWarningEvents() as $event) { + $elements[] = [ + 'title' => $event->message(), + 'body' => '', + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'PHPUnit test runner warning'); + $this->printList($elements); + } + + private function printTestRunnerDeprecations(TestResult $result): void + { + if (!$result->hasTestRunnerTriggeredDeprecationEvents()) { + return; + } + + $elements = []; + + foreach ($result->testRunnerTriggeredDeprecationEvents() as $event) { + $elements[] = [ + 'title' => $event->message(), + 'body' => '', + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'PHPUnit test runner deprecation'); + $this->printList($elements); + } + + private function printDetailsOnTestsThatTriggeredPhpunitWarnings(TestResult $result): void + { + if (!$result->hasTestTriggeredPhpunitWarningEvents()) { + return; + } + + $elements = $this->mapTestsWithIssuesEventsToElements($result->testTriggeredPhpunitWarningEvents()); + + $this->printListHeaderWithNumberOfTestsAndNumberOfIssues( + $elements['numberOfTestsWithIssues'], + $elements['numberOfIssues'], + 'PHPUnit warning', + ); + + $this->printList($elements['elements']); + } + + private function printTestsWithErrors(TestResult $result): void + { + if (!$result->hasTestErroredEvents()) { + return; + } + + $elements = []; + + foreach ($result->testErroredEvents() as $event) { + if ($event instanceof BeforeFirstTestMethodErrored) { + $title = $event->testClassName(); + } else { + $title = $this->name($event->test()); + } + + $elements[] = [ + 'title' => $title, + 'body' => $event->throwable()->asString(), + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'error'); + $this->printList($elements); + } + + private function printTestsWithFailedAssertions(TestResult $result): void + { + if (!$result->hasTestFailedEvents()) { + return; + } + + $elements = []; + + foreach ($result->testFailedEvents() as $event) { + $body = $event->throwable()->asString(); + + if (str_starts_with($body, 'AssertionError: ')) { + $body = substr($body, strlen('AssertionError: ')); + } + + $elements[] = [ + 'title' => $this->name($event->test()), + 'body' => $body, + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'failure'); + $this->printList($elements); + } + + private function printRiskyTests(TestResult $result): void + { + if (!$result->hasTestConsideredRiskyEvents()) { + return; + } + + $elements = $this->mapTestsWithIssuesEventsToElements($result->testConsideredRiskyEvents()); + + $this->printListHeaderWithNumber($elements['numberOfTestsWithIssues'], 'risky test'); + $this->printList($elements['elements']); + } + + private function printIncompleteTests(TestResult $result): void + { + if (!$result->hasTestMarkedIncompleteEvents()) { + return; + } + + $elements = []; + + foreach ($result->testMarkedIncompleteEvents() as $event) { + $elements[] = [ + 'title' => $this->name($event->test()), + 'body' => $event->throwable()->asString(), + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'incomplete test'); + $this->printList($elements); + } + + private function printSkippedTestSuites(TestResult $result): void + { + if (!$result->hasTestSuiteSkippedEvents()) { + return; + } + + $elements = []; + + foreach ($result->testSuiteSkippedEvents() as $event) { + $elements[] = [ + 'title' => $event->testSuite()->name(), + 'body' => $event->message(), + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'skipped test suite'); + $this->printList($elements); + } + + private function printSkippedTests(TestResult $result): void + { + if (!$result->hasTestSkippedEvents()) { + return; + } + + $elements = []; + + foreach ($result->testSkippedEvents() as $event) { + $elements[] = [ + 'title' => $this->name($event->test()), + 'body' => $event->message(), + ]; + } + + $this->printListHeaderWithNumber(count($elements), 'skipped test'); + $this->printList($elements); + } + + /** + * @psalm-param non-empty-string $type + * @psalm-param list $issues + */ + private function printIssueList(string $type, array $issues): void + { + if (empty($issues)) { + return; + } + + $numberOfUniqueIssues = count($issues); + $triggeringTests = []; + + foreach ($issues as $issue) { + $triggeringTests = array_merge($triggeringTests, array_keys($issue->triggeringTests())); + } + + $numberOfTests = count(array_unique($triggeringTests)); + unset($triggeringTests); + + $this->printListHeader( + sprintf( + '%d test%s triggered %d %s%s:' . PHP_EOL . PHP_EOL, + $numberOfTests, + $numberOfTests !== 1 ? 's' : '', + $numberOfUniqueIssues, + $type, + $numberOfUniqueIssues !== 1 ? 's' : '', + ), + ); + + $i = 1; + + foreach ($issues as $issue) { + $title = sprintf( + '%s:%d', + $issue->file(), + $issue->line(), + ); + + $body = trim($issue->description()) . PHP_EOL . PHP_EOL . 'Triggered by:'; + + $triggeringTests = $issue->triggeringTests(); + + ksort($triggeringTests); + + foreach ($triggeringTests as $triggeringTest) { + $body .= PHP_EOL . PHP_EOL . '* ' . $triggeringTest['test']->id(); + + if ($triggeringTest['count'] > 1) { + $body .= sprintf( + ' (%d times)', + $triggeringTest['count'], + ); + } + + if ($triggeringTest['test']->isTestMethod()) { + $body .= PHP_EOL . ' ' . $triggeringTest['test']->file() . ':' . $triggeringTest['test']->line(); + } + } + + $this->printIssueListElement($i++, $title, $body); + + $this->printer->print(PHP_EOL); + } + } + + private function printListHeaderWithNumberOfTestsAndNumberOfIssues(int $numberOfTestsWithIssues, int $numberOfIssues, string $type): void + { + $this->printListHeader( + sprintf( + "%d test%s triggered %d %s%s:\n\n", + $numberOfTestsWithIssues, + $numberOfTestsWithIssues !== 1 ? 's' : '', + $numberOfIssues, + $type, + $numberOfIssues !== 1 ? 's' : '', + ), + ); + } + + private function printListHeaderWithNumber(int $number, string $type): void + { + $this->printListHeader( + sprintf( + "There %s %d %s%s:\n\n", + ($number === 1) ? 'was' : 'were', + $number, + $type, + ($number === 1) ? '' : 's', + ), + ); + } + + private function printListHeader(string $header): void + { + if ($this->listPrinted) { + $this->printer->print("--\n\n"); + } + + $this->listPrinted = true; + + $this->printer->print($header); + } + + /** + * @psalm-param list $elements + */ + private function printList(array $elements): void + { + $i = 1; + + if ($this->displayDefectsInReverseOrder) { + $elements = array_reverse($elements); + } + + foreach ($elements as $element) { + $this->printListElement($i++, $element['title'], $element['body']); + } + + $this->printer->print("\n"); + } + + private function printListElement(int $number, string $title, string $body): void + { + $body = trim($body); + + $this->printer->print( + sprintf( + "%s%d) %s\n%s%s", + $number > 1 ? "\n" : '', + $number, + $title, + $body, + !empty($body) ? "\n" : '', + ), + ); + } + + private function printIssueListElement(int $number, string $title, string $body): void + { + $body = trim($body); + + $this->printer->print( + sprintf( + "%d) %s\n%s%s", + $number, + $title, + $body, + !empty($body) ? "\n" : '', + ), + ); + } + + private function name(Test $test): string + { + if ($test->isTestMethod()) { + assert($test instanceof TestMethod); + + if (!$test->testData()->hasDataFromDataProvider()) { + return $test->nameWithClass(); + } + + return $test->className() . '::' . $test->methodName() . $test->testData()->dataFromDataProvider()->dataAsStringForResultOutput(); + } + + return $test->name(); + } + + /** + * @psalm-param array> $events + * + * @psalm-return array{numberOfTestsWithIssues: int, numberOfIssues: int, elements: list} + */ + private function mapTestsWithIssuesEventsToElements(array $events): array + { + $elements = []; + $issues = 0; + + foreach ($events as $reasons) { + $test = $reasons[0]->test(); + $testLocation = $this->testLocation($test); + $title = $this->name($test); + $body = ''; + $first = true; + $single = count($reasons) === 1; + + foreach ($reasons as $reason) { + if ($first) { + $first = false; + } else { + $body .= PHP_EOL; + } + + $body .= $this->reasonMessage($reason, $single); + $body .= $this->reasonLocation($reason, $single); + + $issues++; + } + + if (!empty($testLocation)) { + $body .= $testLocation; + } + + $elements[] = [ + 'title' => $title, + 'body' => $body, + ]; + } + + return [ + 'numberOfTestsWithIssues' => count($events), + 'numberOfIssues' => $issues, + 'elements' => $elements, + ]; + } + + private function testLocation(Test $test): string + { + if (!$test->isTestMethod()) { + return ''; + } + + assert($test instanceof TestMethod); + + return sprintf( + '%s%s:%d%s', + PHP_EOL, + $test->file(), + $test->line(), + PHP_EOL, + ); + } + + private function reasonMessage(ConsideredRisky|DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpunitDeprecationTriggered|PhpunitErrorTriggered|PhpunitWarningTriggered|PhpWarningTriggered|WarningTriggered $reason, bool $single): string + { + $message = trim($reason->message()); + + if ($single) { + return $message . PHP_EOL; + } + + $lines = explode(PHP_EOL, $message); + $buffer = '* ' . $lines[0] . PHP_EOL; + + if (count($lines) > 1) { + foreach (range(1, count($lines) - 1) as $line) { + $buffer .= ' ' . $lines[$line] . PHP_EOL; + } + } + + return $buffer; + } + + private function reasonLocation(ConsideredRisky|DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpunitDeprecationTriggered|PhpunitErrorTriggered|PhpunitWarningTriggered|PhpWarningTriggered|WarningTriggered $reason, bool $single): string + { + if (!$reason instanceof DeprecationTriggered && + !$reason instanceof PhpDeprecationTriggered && + !$reason instanceof ErrorTriggered && + !$reason instanceof NoticeTriggered && + !$reason instanceof PhpNoticeTriggered && + !$reason instanceof WarningTriggered && + !$reason instanceof PhpWarningTriggered) { + return ''; + } + + return sprintf( + '%s%s:%d%s', + $single ? '' : ' ', + $reason->file(), + $reason->line(), + PHP_EOL, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php new file mode 100644 index 000000000..08c72d9b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\Default; + +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade; +use PHPUnit\Event\Test\PrintedUnexpectedOutput; +use PHPUnit\Event\Test\PrintedUnexpectedOutputSubscriber; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\TextUI\Output\Printer; + +final class UnexpectedOutputPrinter implements PrintedUnexpectedOutputSubscriber +{ + private readonly Printer $printer; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public function __construct(Printer $printer, Facade $facade) + { + $this->printer = $printer; + + $facade->registerSubscriber($this); + } + + public function notify(PrintedUnexpectedOutput $event): void + { + $this->printer->print($event->output()); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Facade.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Facade.php new file mode 100644 index 000000000..f08b2d7b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Facade.php @@ -0,0 +1,281 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output; + +use const PHP_EOL; +use function assert; +use PHPUnit\Event\EventFacadeIsSealedException; +use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\UnknownSubscriberTypeException; +use PHPUnit\Logging\TeamCity\TeamCityLogger; +use PHPUnit\Logging\TestDox\TestResultCollection; +use PHPUnit\Runner\DirectoryDoesNotExistException; +use PHPUnit\TestRunner\TestResult\TestResult; +use PHPUnit\TextUI\CannotOpenSocketException; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\InvalidSocketException; +use PHPUnit\TextUI\Output\Default\ProgressPrinter\ProgressPrinter as DefaultProgressPrinter; +use PHPUnit\TextUI\Output\Default\ResultPrinter as DefaultResultPrinter; +use PHPUnit\TextUI\Output\Default\UnexpectedOutputPrinter; +use PHPUnit\TextUI\Output\TestDox\ResultPrinter as TestDoxResultPrinter; +use SebastianBergmann\Timer\Duration; +use SebastianBergmann\Timer\ResourceUsageFormatter; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Facade +{ + private static ?Printer $printer = null; + private static ?DefaultResultPrinter $defaultResultPrinter = null; + private static ?TestDoxResultPrinter $testDoxResultPrinter = null; + private static ?SummaryPrinter $summaryPrinter = null; + private static bool $defaultProgressPrinter = false; + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + public static function init(Configuration $configuration, bool $extensionReplacesProgressOutput, bool $extensionReplacesResultOutput): Printer + { + self::createPrinter($configuration); + + assert(self::$printer !== null); + + if ($configuration->debug()) { + return self::$printer; + } + + self::createUnexpectedOutputPrinter(); + + if (!$extensionReplacesProgressOutput) { + self::createProgressPrinter($configuration); + } + + if (!$extensionReplacesResultOutput) { + self::createResultPrinter($configuration); + self::createSummaryPrinter($configuration); + } + + if ($configuration->outputIsTeamCity()) { + new TeamCityLogger( + DefaultPrinter::standardOutput(), + EventFacade::instance(), + ); + } + + return self::$printer; + } + + /** + * @psalm-param ?array $testDoxResult + */ + public static function printResult(TestResult $result, ?array $testDoxResult, Duration $duration): void + { + assert(self::$printer !== null); + + if ($result->numberOfTestsRun() > 0) { + if (self::$defaultProgressPrinter) { + self::$printer->print(PHP_EOL . PHP_EOL); + } + + self::$printer->print((new ResourceUsageFormatter)->resourceUsage($duration) . PHP_EOL . PHP_EOL); + } + + if (self::$testDoxResultPrinter !== null && $testDoxResult !== null) { + self::$testDoxResultPrinter->print($testDoxResult); + } + + if (self::$defaultResultPrinter !== null) { + self::$defaultResultPrinter->print($result); + } + + if (self::$summaryPrinter !== null) { + self::$summaryPrinter->print($result); + } + } + + /** + * @throws CannotOpenSocketException + * @throws DirectoryDoesNotExistException + * @throws InvalidSocketException + */ + public static function printerFor(string $target): Printer + { + if ($target === 'php://stdout') { + if (!self::$printer instanceof NullPrinter) { + return self::$printer; + } + + return DefaultPrinter::standardOutput(); + } + + return DefaultPrinter::from($target); + } + + private static function createPrinter(Configuration $configuration): void + { + $printerNeeded = false; + + if ($configuration->debug()) { + $printerNeeded = true; + } + + if ($configuration->outputIsTeamCity()) { + $printerNeeded = true; + } + + if ($configuration->outputIsTestDox()) { + $printerNeeded = true; + } + + if (!$configuration->noOutput() && !$configuration->noProgress()) { + $printerNeeded = true; + } + + if (!$configuration->noOutput() && !$configuration->noResults()) { + $printerNeeded = true; + } + + if ($printerNeeded) { + if ($configuration->outputToStandardErrorStream()) { + self::$printer = DefaultPrinter::standardError(); + + return; + } + + self::$printer = DefaultPrinter::standardOutput(); + + return; + } + + self::$printer = new NullPrinter; + } + + private static function createProgressPrinter(Configuration $configuration): void + { + assert(self::$printer !== null); + + if (!self::useDefaultProgressPrinter($configuration)) { + return; + } + + new DefaultProgressPrinter( + self::$printer, + EventFacade::instance(), + $configuration->colors(), + $configuration->columns(), + $configuration->source(), + ); + + self::$defaultProgressPrinter = true; + } + + private static function useDefaultProgressPrinter(Configuration $configuration): bool + { + if ($configuration->noOutput()) { + return false; + } + + if ($configuration->noProgress()) { + return false; + } + + if ($configuration->outputIsTeamCity()) { + return false; + } + + return true; + } + + private static function createResultPrinter(Configuration $configuration): void + { + assert(self::$printer !== null); + + if ($configuration->outputIsTestDox()) { + self::$defaultResultPrinter = new DefaultResultPrinter( + self::$printer, + true, + true, + $configuration->displayDetailsOnPhpunitDeprecations(), + false, + false, + true, + false, + false, + $configuration->displayDetailsOnTestsThatTriggerDeprecations(), + $configuration->displayDetailsOnTestsThatTriggerErrors(), + $configuration->displayDetailsOnTestsThatTriggerNotices(), + $configuration->displayDetailsOnTestsThatTriggerWarnings(), + $configuration->reverseDefectList(), + ); + } + + if ($configuration->outputIsTestDox()) { + self::$testDoxResultPrinter = new TestDoxResultPrinter( + self::$printer, + $configuration->colors(), + ); + } + + if ($configuration->noOutput() || $configuration->noResults()) { + return; + } + + if (self::$defaultResultPrinter !== null) { + return; + } + + self::$defaultResultPrinter = new DefaultResultPrinter( + self::$printer, + true, + true, + $configuration->displayDetailsOnPhpunitDeprecations(), + true, + true, + true, + $configuration->displayDetailsOnIncompleteTests(), + $configuration->displayDetailsOnSkippedTests(), + $configuration->displayDetailsOnTestsThatTriggerDeprecations(), + $configuration->displayDetailsOnTestsThatTriggerErrors(), + $configuration->displayDetailsOnTestsThatTriggerNotices(), + $configuration->displayDetailsOnTestsThatTriggerWarnings(), + $configuration->reverseDefectList(), + ); + } + + private static function createSummaryPrinter(Configuration $configuration): void + { + assert(self::$printer !== null); + + if (($configuration->noOutput() || $configuration->noResults()) && + !($configuration->outputIsTeamCity() || $configuration->outputIsTestDox())) { + return; + } + + self::$summaryPrinter = new SummaryPrinter( + self::$printer, + $configuration->colors(), + ); + } + + /** + * @throws EventFacadeIsSealedException + * @throws UnknownSubscriberTypeException + */ + private static function createUnexpectedOutputPrinter(): void + { + assert(self::$printer !== null); + + new UnexpectedOutputPrinter(self::$printer, EventFacade::instance()); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.php new file mode 100644 index 000000000..38f3b2b52 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/DefaultPrinter.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 PHPUnit\TextUI\Output; + +use function assert; +use function count; +use function dirname; +use function explode; +use function fclose; +use function fopen; +use function fsockopen; +use function fwrite; +use function str_replace; +use function str_starts_with; +use PHPUnit\Runner\DirectoryDoesNotExistException; +use PHPUnit\TextUI\CannotOpenSocketException; +use PHPUnit\TextUI\InvalidSocketException; +use PHPUnit\Util\Filesystem; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DefaultPrinter implements Printer +{ + /** + * @psalm-var closed-resource|resource + */ + private $stream; + private readonly bool $isPhpStream; + private bool $isOpen; + + /** + * @throws CannotOpenSocketException + * @throws DirectoryDoesNotExistException + * @throws InvalidSocketException + */ + public static function from(string $out): self + { + return new self($out); + } + + /** + * @throws CannotOpenSocketException + * @throws DirectoryDoesNotExistException + * @throws InvalidSocketException + */ + public static function standardOutput(): self + { + return new self('php://stdout'); + } + + /** + * @throws CannotOpenSocketException + * @throws DirectoryDoesNotExistException + * @throws InvalidSocketException + */ + public static function standardError(): self + { + return new self('php://stderr'); + } + + /** + * @throws CannotOpenSocketException + * @throws DirectoryDoesNotExistException + * @throws InvalidSocketException + */ + private function __construct(string $out) + { + $this->isPhpStream = str_starts_with($out, 'php://'); + + if (str_starts_with($out, 'socket://')) { + $tmp = explode(':', str_replace('socket://', '', $out)); + + if (count($tmp) !== 2) { + throw new InvalidSocketException($out); + } + + $stream = @fsockopen($tmp[0], (int) $tmp[1]); + + if ($stream === false) { + throw new CannotOpenSocketException($tmp[0], (int) $tmp[1]); + } + + $this->stream = $stream; + $this->isOpen = true; + + return; + } + + if (!$this->isPhpStream && !Filesystem::createDirectory(dirname($out))) { + throw new DirectoryDoesNotExistException(dirname($out)); + } + + $this->stream = fopen($out, 'wb'); + $this->isOpen = true; + } + + public function print(string $buffer): void + { + assert($this->isOpen); + + fwrite($this->stream, $buffer); + } + + public function flush(): void + { + if ($this->isOpen && $this->isPhpStream) { + fclose($this->stream); + + $this->isOpen = false; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php new file mode 100644 index 000000000..cf27e6b32 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/NullPrinter.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class NullPrinter implements Printer +{ + public function print(string $buffer): void + { + } + + public function flush(): void + { + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php new file mode 100644 index 000000000..c9b0fb970 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/Printer/Printer.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Printer +{ + public function print(string $buffer): void; + + public function flush(): void; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php new file mode 100644 index 000000000..0c540bb50 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/SummaryPrinter.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output; + +use const PHP_EOL; +use function sprintf; +use PHPUnit\TestRunner\TestResult\TestResult; +use PHPUnit\Util\Color; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class SummaryPrinter +{ + private readonly Printer $printer; + private readonly bool $colors; + private bool $countPrinted = false; + + public function __construct(Printer $printer, bool $colors) + { + $this->printer = $printer; + $this->colors = $colors; + } + + public function print(TestResult $result): void + { + if ($result->numberOfTestsRun() === 0) { + $this->printWithColor( + 'fg-black, bg-yellow', + 'No tests executed!', + ); + + return; + } + + if ($result->wasSuccessfulAndNoTestHasIssues() && + !$result->hasTestSuiteSkippedEvents() && + !$result->hasTestSkippedEvents()) { + $this->printWithColor( + 'fg-black, bg-green', + sprintf( + 'OK (%d test%s, %d assertion%s)', + $result->numberOfTestsRun(), + $result->numberOfTestsRun() === 1 ? '' : 's', + $result->numberOfAssertions(), + $result->numberOfAssertions() === 1 ? '' : 's', + ), + ); + + $this->printNumberOfIssuesIgnoredByBaseline($result); + + return; + } + + $color = 'fg-black, bg-yellow'; + + if ($result->wasSuccessful()) { + if (!$result->hasTestsWithIssues()) { + $this->printWithColor( + $color, + 'OK, but some tests were skipped!', + ); + } else { + $this->printWithColor( + $color, + 'OK, but there were issues!', + ); + } + } else { + if ($result->hasTestErroredEvents() || $result->hasTestTriggeredPhpunitErrorEvents()) { + $color = 'fg-white, bg-red'; + + $this->printWithColor( + $color, + 'ERRORS!', + ); + } elseif ($result->hasTestFailedEvents()) { + $color = 'fg-white, bg-red'; + + $this->printWithColor( + $color, + 'FAILURES!', + ); + } elseif ($result->hasWarnings()) { + $this->printWithColor( + $color, + 'WARNINGS!', + ); + } elseif ($result->hasDeprecations()) { + $this->printWithColor( + $color, + 'DEPRECATIONS!', + ); + } elseif ($result->hasNotices()) { + $this->printWithColor( + $color, + 'NOTICES!', + ); + } + } + + $this->printCountString($result->numberOfTestsRun(), 'Tests', $color, true); + $this->printCountString($result->numberOfAssertions(), 'Assertions', $color, true); + $this->printCountString($result->numberOfErrors(), 'Errors', $color); + $this->printCountString($result->numberOfTestFailedEvents(), 'Failures', $color); + $this->printCountString($result->numberOfWarnings(), 'Warnings', $color); + $this->printCountString($result->numberOfPhpOrUserDeprecations(), 'Deprecations', $color); + $this->printCountString($result->numberOfPhpunitDeprecations(), 'PHPUnit Deprecations', $color); + $this->printCountString($result->numberOfNotices(), 'Notices', $color); + $this->printCountString($result->numberOfTestSuiteSkippedEvents() + $result->numberOfTestSkippedEvents(), 'Skipped', $color); + $this->printCountString($result->numberOfTestMarkedIncompleteEvents(), 'Incomplete', $color); + $this->printCountString($result->numberOfTestsWithTestConsideredRiskyEvents(), 'Risky', $color); + $this->printWithColor($color, '.'); + + $this->printNumberOfIssuesIgnoredByBaseline($result); + } + + private function printCountString(int $count, string $name, string $color, bool $always = false): void + { + if ($always || $count > 0) { + $this->printWithColor( + $color, + sprintf( + '%s%s: %d', + $this->countPrinted ? ', ' : '', + $name, + $count, + ), + false, + ); + + $this->countPrinted = true; + } + } + + private function printWithColor(string $color, string $buffer, bool $lf = true): void + { + if ($this->colors) { + $buffer = Color::colorizeTextBox($color, $buffer); + } + + $this->printer->print($buffer); + + if ($lf) { + $this->printer->print(PHP_EOL); + } + } + + private function printNumberOfIssuesIgnoredByBaseline(TestResult $result): void + { + if ($result->hasIssuesIgnoredByBaseline()) { + $this->printer->print( + sprintf( + '%s%d issue%s %s ignored by baseline.%s', + PHP_EOL, + $result->numberOfIssuesIgnoredByBaseline(), + $result->numberOfIssuesIgnoredByBaseline() > 1 ? 's' : '', + $result->numberOfIssuesIgnoredByBaseline() > 1 ? 'were' : 'was', + PHP_EOL, + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php new file mode 100644 index 000000000..e063b909f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/Output/TestDox/ResultPrinter.php @@ -0,0 +1,366 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI\Output\TestDox; + +use const PHP_EOL; +use function array_map; +use function assert; +use function explode; +use function implode; +use function preg_match; +use function preg_split; +use function rtrim; +use function str_starts_with; +use function trim; +use PHPUnit\Event\Code\Throwable; +use PHPUnit\Framework\TestStatus\TestStatus; +use PHPUnit\Logging\TestDox\TestResult as TestDoxTestResult; +use PHPUnit\Logging\TestDox\TestResultCollection; +use PHPUnit\TextUI\Output\Printer; +use PHPUnit\Util\Color; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ResultPrinter +{ + private readonly Printer $printer; + private readonly bool $colors; + + public function __construct(Printer $printer, bool $colors) + { + $this->printer = $printer; + $this->colors = $colors; + } + + /** + * @psalm-param array $tests + */ + public function print(array $tests): void + { + foreach ($tests as $prettifiedClassName => $_tests) { + $this->printPrettifiedClassName($prettifiedClassName); + + foreach ($_tests as $test) { + $this->printTestResult($test); + } + + $this->printer->print(PHP_EOL); + } + } + + /** + * @psalm-param string $prettifiedClassName + */ + private function printPrettifiedClassName(string $prettifiedClassName): void + { + $buffer = $prettifiedClassName; + + if ($this->colors) { + $buffer = Color::colorizeTextBox('underlined', $buffer); + } + + $this->printer->print($buffer . PHP_EOL); + } + + private function printTestResult(TestDoxTestResult $test): void + { + $this->printTestResultHeader($test); + $this->printTestResultBody($test); + } + + private function printTestResultHeader(TestDoxTestResult $test): void + { + $buffer = ' ' . $this->symbolFor($test->status()) . ' '; + + if ($this->colors) { + $this->printer->print( + Color::colorizeTextBox( + $this->colorFor($test->status()), + $buffer, + ), + ); + } else { + $this->printer->print($buffer); + } + + $this->printer->print($test->test()->testDox()->prettifiedMethodName($this->colors) . PHP_EOL); + } + + private function printTestResultBody(TestDoxTestResult $test): void + { + if ($test->status()->isSuccess()) { + return; + } + + if (!$test->hasThrowable()) { + return; + } + + $this->printTestResultBodyStart($test); + $this->printThrowable($test); + $this->printTestResultBodyEnd($test); + } + + private function printTestResultBodyStart(TestDoxTestResult $test): void + { + $this->printer->print( + $this->prefixLines( + $this->prefixFor('start', $test->status()), + '', + ), + ); + + $this->printer->print(PHP_EOL); + } + + private function printTestResultBodyEnd(TestDoxTestResult $test): void + { + $this->printer->print(PHP_EOL); + + $this->printer->print( + $this->prefixLines( + $this->prefixFor('last', $test->status()), + '', + ), + ); + + $this->printer->print(PHP_EOL); + } + + private function printThrowable(TestDoxTestResult $test): void + { + $throwable = $test->throwable(); + + assert($throwable instanceof Throwable); + + $message = trim($throwable->description()); + $stackTrace = $this->formatStackTrace($throwable->stackTrace()); + $diff = ''; + + if (!empty($message) && $this->colors) { + ['message' => $message, 'diff' => $diff] = $this->colorizeMessageAndDiff( + $message, + $this->messageColorFor($test->status()), + ); + } + + if (!empty($message)) { + $this->printer->print( + $this->prefixLines( + $this->prefixFor('message', $test->status()), + $message, + ), + ); + + $this->printer->print(PHP_EOL); + } + + if (!empty($diff)) { + $this->printer->print( + $this->prefixLines( + $this->prefixFor('diff', $test->status()), + $diff, + ), + ); + + $this->printer->print(PHP_EOL); + } + + if (!empty($stackTrace)) { + if (!empty($message) || !empty($diff)) { + $prefix = $this->prefixFor('default', $test->status()); + } else { + $prefix = $this->prefixFor('trace', $test->status()); + } + + $this->printer->print( + $this->prefixLines($prefix, PHP_EOL . $stackTrace), + ); + } + } + + /** + * @psalm-return array{message: string, diff: string} + */ + private function colorizeMessageAndDiff(string $buffer, string $style): array + { + $lines = $buffer ? array_map('\rtrim', explode(PHP_EOL, $buffer)) : []; + $message = []; + $diff = []; + $insideDiff = false; + + foreach ($lines as $line) { + if ($line === '--- Expected') { + $insideDiff = true; + } + + if (!$insideDiff) { + $message[] = $line; + } else { + if (str_starts_with($line, '-')) { + $line = Color::colorize('fg-red', Color::visualizeWhitespace($line, true)); + } elseif (str_starts_with($line, '+')) { + $line = Color::colorize('fg-green', Color::visualizeWhitespace($line, true)); + } elseif ($line === '@@ @@') { + $line = Color::colorize('fg-cyan', $line); + } + + $diff[] = $line; + } + } + + $message = implode(PHP_EOL, $message); + $diff = implode(PHP_EOL, $diff); + + if (!empty($message)) { + $message = Color::colorizeTextBox($style, $message); + } + + return [ + 'message' => $message, + 'diff' => $diff, + ]; + } + + private function formatStackTrace(string $stackTrace): string + { + if (!$this->colors) { + return rtrim($stackTrace); + } + + $lines = []; + $previousPath = ''; + + foreach (explode(PHP_EOL, $stackTrace) as $line) { + if (preg_match('/^(.*):(\d+)$/', $line, $matches)) { + $lines[] = Color::colorizePath($matches[1], $previousPath) . Color::dim(':') . Color::colorize('fg-blue', $matches[2]) . "\n"; + $previousPath = $matches[1]; + + continue; + } + + $lines[] = $line; + $previousPath = ''; + } + + return rtrim(implode('', $lines)); + } + + private function prefixLines(string $prefix, string $message): string + { + return implode( + PHP_EOL, + array_map( + static fn (string $line) => ' ' . $prefix . ($line ? ' ' . $line : ''), + preg_split('/\r\n|\r|\n/', $message), + ), + ); + } + + /** + * @psalm-param 'default'|'start'|'message'|'diff'|'trace'|'last' $type + */ + private function prefixFor(string $type, TestStatus $status): string + { + if (!$this->colors) { + return '│'; + } + + return Color::colorize( + $this->colorFor($status), + match ($type) { + 'default' => '│', + 'start' => 'â”', + 'message' => '├', + 'diff' => '┊', + 'trace' => '╵', + 'last' => 'â”´', + }, + ); + } + + private function colorFor(TestStatus $status): string + { + if ($status->isSuccess()) { + return 'fg-green'; + } + + if ($status->isError()) { + return 'fg-yellow'; + } + + if ($status->isFailure()) { + return 'fg-red'; + } + + if ($status->isSkipped()) { + return 'fg-cyan'; + } + + if ($status->isIncomplete() || $status->isDeprecation() || $status->isNotice() || $status->isRisky() || $status->isWarning()) { + return 'fg-yellow'; + } + + return 'fg-blue'; + } + + private function messageColorFor(TestStatus $status): string + { + if ($status->isSuccess()) { + return ''; + } + + if ($status->isError()) { + return 'bg-yellow,fg-black'; + } + + if ($status->isFailure()) { + return 'bg-red,fg-white'; + } + + if ($status->isSkipped()) { + return 'fg-cyan'; + } + + if ($status->isIncomplete() || $status->isDeprecation() || $status->isNotice() || $status->isRisky() || $status->isWarning()) { + return 'fg-yellow'; + } + + return 'fg-white,bg-blue'; + } + + private function symbolFor(TestStatus $status): string + { + if ($status->isSuccess()) { + return '✔'; + } + + if ($status->isError() || $status->isFailure()) { + return '✘'; + } + + if ($status->isSkipped()) { + return '↩'; + } + + if ($status->isDeprecation() || $status->isNotice() || $status->isRisky() || $status->isWarning()) { + return 'âš '; + } + + if ($status->isIncomplete()) { + return '∅'; + } + + return '?'; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php new file mode 100644 index 000000000..6a1aad60a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/ShellExitCodeCalculator.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use PHPUnit\TestRunner\TestResult\TestResult; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ShellExitCodeCalculator +{ + private const SUCCESS_EXIT = 0; + private const FAILURE_EXIT = 1; + private const EXCEPTION_EXIT = 2; + + public function calculate(bool $failOnDeprecation, bool $failOnPhpunitDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, TestResult $result): int + { + $returnCode = self::FAILURE_EXIT; + + if ($result->wasSuccessful()) { + $returnCode = self::SUCCESS_EXIT; + } + + if ($failOnEmptyTestSuite && !$result->hasTests()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($result->wasSuccessfulIgnoringPhpunitWarnings()) { + if ($failOnDeprecation && $result->hasPhpOrUserDeprecations()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($failOnPhpunitDeprecation && $result->hasPhpunitDeprecations()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($failOnIncomplete && $result->hasIncompleteTests()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($failOnNotice && $result->hasNotices()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($failOnRisky && $result->hasRiskyTests()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($failOnSkipped && $result->hasSkippedTests()) { + $returnCode = self::FAILURE_EXIT; + } + + if ($failOnWarning && $result->hasWarnings()) { + $returnCode = self::FAILURE_EXIT; + } + } + + if ($result->hasErrors()) { + $returnCode = self::EXCEPTION_EXIT; + } + + return $returnCode; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestRunner.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestRunner.php new file mode 100644 index 000000000..2363ca290 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestRunner.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function mt_srand; +use PHPUnit\Event; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\ResultCache\ResultCache; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\TextUI\Configuration\Configuration; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestRunner +{ + /** + * @throws RuntimeException + */ + public function run(Configuration $configuration, ResultCache $resultCache, TestSuite $suite): void + { + try { + Event\Facade::emitter()->testRunnerStarted(); + + if ($configuration->executionOrder() === TestSuiteSorter::ORDER_RANDOMIZED) { + mt_srand($configuration->randomOrderSeed()); + } + + if ($configuration->executionOrder() !== TestSuiteSorter::ORDER_DEFAULT || + $configuration->executionOrderDefects() !== TestSuiteSorter::ORDER_DEFAULT || + $configuration->resolveDependencies()) { + $resultCache->load(); + + (new TestSuiteSorter($resultCache))->reorderTestsInSuite( + $suite, + $configuration->executionOrder(), + $configuration->resolveDependencies(), + $configuration->executionOrderDefects(), + ); + + Event\Facade::emitter()->testSuiteSorted( + $configuration->executionOrder(), + $configuration->executionOrderDefects(), + $configuration->resolveDependencies(), + ); + } + + (new TestSuiteFilterProcessor)->process($configuration, $suite); + + Event\Facade::emitter()->testRunnerExecutionStarted( + Event\TestSuite\TestSuiteBuilder::from($suite), + ); + + $suite->run(); + + Event\Facade::emitter()->testRunnerExecutionFinished(); + Event\Facade::emitter()->testRunnerFinished(); + } catch (Throwable $t) { + throw new RuntimeException( + $t->getMessage(), + (int) $t->getCode(), + $t, + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php new file mode 100644 index 000000000..63ba1b384 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/TextUI/TestSuiteFilterProcessor.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +use function array_map; +use PHPUnit\Event; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\FilterNotConfiguredException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFilterProcessor +{ + /** + * @throws Event\RuntimeException + * @throws FilterNotConfiguredException + */ + public function process(Configuration $configuration, TestSuite $suite): void + { + $factory = new Factory; + + if (!$configuration->hasFilter() && + !$configuration->hasGroups() && + !$configuration->hasExcludeGroups() && + !$configuration->hasTestsCovering() && + !$configuration->hasTestsUsing()) { + return; + } + + if ($configuration->hasExcludeGroups()) { + $factory->addExcludeGroupFilter( + $configuration->excludeGroups(), + ); + } + + if ($configuration->hasGroups()) { + $factory->addIncludeGroupFilter( + $configuration->groups(), + ); + } + + if ($configuration->hasTestsCovering()) { + $factory->addIncludeGroupFilter( + array_map( + static fn (string $name): string => '__phpunit_covers_' . $name, + $configuration->testsCovering(), + ), + ); + } + + if ($configuration->hasTestsUsing()) { + $factory->addIncludeGroupFilter( + array_map( + static fn (string $name): string => '__phpunit_uses_' . $name, + $configuration->testsUsing(), + ), + ); + } + + if ($configuration->hasFilter()) { + $factory->addNameFilter( + $configuration->filter(), + ); + } + + $suite->injectFilter($factory); + + Event\Facade::emitter()->testSuiteFiltered( + Event\TestSuite\TestSuiteBuilder::from($suite), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Cloner.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Cloner.php new file mode 100644 index 000000000..7e3e5aa02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Cloner.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Cloner +{ + /** + * @psalm-template OriginalType of object + * + * @psalm-param OriginalType $original + * + * @psalm-return OriginalType + */ + public static function clone(object $original): object + { + try { + return clone $original; + } catch (Throwable) { + return $original; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Color.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Color.php new file mode 100644 index 000000000..0e3642cac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Color.php @@ -0,0 +1,181 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use const PHP_EOL; +use function array_map; +use function count; +use function explode; +use function implode; +use function max; +use function min; +use function preg_replace; +use function preg_replace_callback; +use function preg_split; +use function sprintf; +use function str_pad; +use function strtr; +use function trim; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Color +{ + /** + * @psalm-var array + */ + private const WHITESPACE_MAP = [ + ' ' => '·', + "\t" => '⇥', + ]; + + /** + * @psalm-var array + */ + private const WHITESPACE_EOL_MAP = [ + ' ' => '·', + "\t" => '⇥', + "\n" => '↵', + "\r" => '⟵', + ]; + + /** + * @psalm-var array + */ + private static array $ansiCodes = [ + 'reset' => '0', + 'bold' => '1', + 'dim' => '2', + 'dim-reset' => '22', + 'underlined' => '4', + 'fg-default' => '39', + 'fg-black' => '30', + 'fg-red' => '31', + 'fg-green' => '32', + 'fg-yellow' => '33', + 'fg-blue' => '34', + 'fg-magenta' => '35', + 'fg-cyan' => '36', + 'fg-white' => '37', + 'bg-default' => '49', + 'bg-black' => '40', + 'bg-red' => '41', + 'bg-green' => '42', + 'bg-yellow' => '43', + 'bg-blue' => '44', + 'bg-magenta' => '45', + 'bg-cyan' => '46', + 'bg-white' => '47', + ]; + + public static function colorize(string $color, string $buffer): string + { + if (trim($buffer) === '') { + return $buffer; + } + + $codes = array_map('\trim', explode(',', $color)); + $styles = []; + + foreach ($codes as $code) { + if (isset(self::$ansiCodes[$code])) { + $styles[] = self::$ansiCodes[$code] ?? ''; + } + } + + if (empty($styles)) { + return $buffer; + } + + return self::optimizeColor(sprintf("\x1b[%sm", implode(';', $styles)) . $buffer . "\x1b[0m"); + } + + public static function colorizeTextBox(string $color, string $buffer): string + { + $lines = preg_split('/\r\n|\r|\n/', $buffer); + $padding = max(array_map('\strlen', $lines)); + + $styledLines = []; + + foreach ($lines as $line) { + $styledLines[] = self::colorize($color, str_pad($line, $padding)); + } + + return implode(PHP_EOL, $styledLines); + } + + public static function colorizePath(string $path, ?string $previousPath = null, bool $colorizeFilename = false): string + { + if ($previousPath === null) { + $previousPath = ''; + } + + $path = explode(DIRECTORY_SEPARATOR, $path); + $previousPath = explode(DIRECTORY_SEPARATOR, $previousPath); + + for ($i = 0; $i < min(count($path), count($previousPath)); $i++) { + if ($path[$i] === $previousPath[$i]) { + $path[$i] = self::dim($path[$i]); + } + } + + if ($colorizeFilename) { + $last = count($path) - 1; + $path[$last] = preg_replace_callback( + '/([\-_.]+|phpt$)/', + static fn ($matches) => self::dim($matches[0]), + $path[$last], + ); + } + + return self::optimizeColor(implode(self::dim(DIRECTORY_SEPARATOR), $path)); + } + + public static function dim(string $buffer): string + { + if (trim($buffer) === '') { + return $buffer; + } + + return "\e[2m{$buffer}\e[22m"; + } + + public static function visualizeWhitespace(string $buffer, bool $visualizeEOL = false): string + { + $replaceMap = $visualizeEOL ? self::WHITESPACE_EOL_MAP : self::WHITESPACE_MAP; + + return preg_replace_callback( + '/\s+/', + static fn ($matches) => self::dim(strtr($matches[0], $replaceMap)), + $buffer, + ); + } + + private static function optimizeColor(string $buffer): string + { + return preg_replace( + [ + "/\e\\[22m\e\\[2m/", + "/\e\\[([^m]*)m\e\\[([1-9][0-9;]*)m/", + "/(\e\\[[^m]*m)+(\e\\[0m)/", + ], + [ + '', + "\e[$1;$2m", + '$2', + ], + $buffer, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/Exception.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/Exception.php new file mode 100644 index 000000000..58f42db77 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This interface is not covered by the backward compatibility promise for PHPUnit + */ +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php new file mode 100644 index 000000000..623af2ded --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidDirectoryException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidDirectoryException extends RuntimeException implements Exception +{ + public function __construct(string $directory) + { + parent::__construct( + sprintf( + '"%s" is not a directory', + $directory, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php new file mode 100644 index 000000000..224f7115c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidJsonException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidJsonException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php new file mode 100644 index 000000000..bc2fe9a0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/InvalidVersionOperatorException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function sprintf; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class InvalidVersionOperatorException extends RuntimeException implements Exception +{ + public function __construct(string $operator) + { + parent::__construct( + sprintf( + '"%s" is not a valid version_compare() operator', + $operator, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/PhpProcessException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/PhpProcessException.php new file mode 100644 index 000000000..05069ef05 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/PhpProcessException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\PHP; + +use PHPUnit\Util\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhpProcessException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/XmlException.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/XmlException.php new file mode 100644 index 000000000..127e1ecaf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exception/XmlException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use PHPUnit\Util\Exception; +use RuntimeException; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class XmlException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ExcludeList.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ExcludeList.php new file mode 100644 index 000000000..88e80ba40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ExcludeList.php @@ -0,0 +1,231 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const PHP_OS_FAMILY; +use function class_exists; +use function defined; +use function dirname; +use function is_dir; +use function realpath; +use function str_starts_with; +use function sys_get_temp_dir; +use Composer\Autoload\ClassLoader; +use DeepCopy\DeepCopy; +use PharIo\Manifest\Manifest; +use PharIo\Version\Version as PharIoVersion; +use PhpParser\Parser; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use SebastianBergmann\CliParser\Parser as CliParser; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeUnit\CodeUnit; +use SebastianBergmann\CodeUnitReverseLookup\Wizard; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Complexity\Calculator; +use SebastianBergmann\Diff\Diff; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Exporter\Exporter; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; +use SebastianBergmann\GlobalState\Snapshot; +use SebastianBergmann\Invoker\Invoker; +use SebastianBergmann\LinesOfCode\Counter; +use SebastianBergmann\ObjectEnumerator\Enumerator; +use SebastianBergmann\ObjectReflector\ObjectReflector; +use SebastianBergmann\RecursionContext\Context; +use SebastianBergmann\Template\Template; +use SebastianBergmann\Timer\Timer; +use SebastianBergmann\Type\TypeName; +use SebastianBergmann\Version; +use TheSeer\Tokenizer\Tokenizer; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + */ +final class ExcludeList +{ + /** + * @psalm-var array + */ + private const EXCLUDED_CLASS_NAMES = [ + // composer + ClassLoader::class => 1, + + // myclabs/deepcopy + DeepCopy::class => 1, + + // nikic/php-parser + Parser::class => 1, + + // phar-io/manifest + Manifest::class => 1, + + // phar-io/version + PharIoVersion::class => 1, + + // phpunit/phpunit + TestCase::class => 2, + + // phpunit/php-code-coverage + CodeCoverage::class => 1, + + // phpunit/php-file-iterator + FileIteratorFacade::class => 1, + + // phpunit/php-invoker + Invoker::class => 1, + + // phpunit/php-text-template + Template::class => 1, + + // phpunit/php-timer + Timer::class => 1, + + // sebastian/cli-parser + CliParser::class => 1, + + // sebastian/code-unit + CodeUnit::class => 1, + + // sebastian/code-unit-reverse-lookup + Wizard::class => 1, + + // sebastian/comparator + Comparator::class => 1, + + // sebastian/complexity + Calculator::class => 1, + + // sebastian/diff + Diff::class => 1, + + // sebastian/environment + Runtime::class => 1, + + // sebastian/exporter + Exporter::class => 1, + + // sebastian/global-state + Snapshot::class => 1, + + // sebastian/lines-of-code + Counter::class => 1, + + // sebastian/object-enumerator + Enumerator::class => 1, + + // sebastian/object-reflector + ObjectReflector::class => 1, + + // sebastian/recursion-context + Context::class => 1, + + // sebastian/type + TypeName::class => 1, + + // sebastian/version + Version::class => 1, + + // theseer/tokenizer + Tokenizer::class => 1, + ]; + + /** + * @psalm-var list + */ + private static array $directories = []; + private static bool $initialized = false; + private readonly bool $enabled; + + /** + * @psalm-param non-empty-string $directory + * + * @throws InvalidDirectoryException + */ + public static function addDirectory(string $directory): void + { + if (!is_dir($directory)) { + throw new InvalidDirectoryException($directory); + } + + self::$directories[] = realpath($directory); + } + + public function __construct(?bool $enabled = null) + { + if ($enabled === null) { + $enabled = !defined('PHPUNIT_TESTSUITE'); + } + + $this->enabled = $enabled; + } + + /** + * @psalm-return list + */ + public function getExcludedDirectories(): array + { + self::initialize(); + + return self::$directories; + } + + public function isExcluded(string $file): bool + { + if (!$this->enabled) { + return false; + } + + self::initialize(); + + foreach (self::$directories as $directory) { + if (str_starts_with($file, $directory)) { + return true; + } + } + + return false; + } + + private static function initialize(): void + { + if (self::$initialized) { + return; + } + + foreach (self::EXCLUDED_CLASS_NAMES as $className => $parent) { + if (!class_exists($className)) { + continue; + } + + $directory = (new ReflectionClass($className))->getFileName(); + + for ($i = 0; $i < $parent; $i++) { + $directory = dirname($directory); + } + + self::$directories[] = $directory; + } + + /** + * Hide process isolation workaround on Windows: + * tempnam() prefix is limited to first 3 characters. + * + * @see https://php.net/manual/en/function.tempnam.php + */ + if (PHP_OS_FAMILY === 'Windows') { + // @codeCoverageIgnoreStart + self::$directories[] = sys_get_temp_dir() . '\\PHP'; + // @codeCoverageIgnoreEnd + } + + self::$initialized = true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exporter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exporter.php new file mode 100644 index 000000000..20cf6f4ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Exporter.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function is_array; +use function is_scalar; +use SebastianBergmann\RecursionContext\Context; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + * + * @deprecated + */ +final class Exporter +{ + public static function export(mixed $value, bool $exportObjects = false): string + { + if (self::isExportable($value) || $exportObjects) { + return (new \SebastianBergmann\Exporter\Exporter)->export($value); + } + + return '{enable export of objects to see this value}'; + } + + private static function isExportable(mixed &$value, ?Context $context = null): bool + { + if (is_scalar($value) || $value === null) { + return true; + } + + if (!is_array($value)) { + return false; + } + + if (!$context) { + $context = new Context; + } + + if ($context->contains($value) !== false) { + return true; + } + + $array = $value; + $context->add($value); + + foreach ($array as &$_value) { + if (!self::isExportable($_value, $context)) { + return false; + } + } + + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filesystem.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filesystem.php new file mode 100644 index 000000000..948ee2857 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filesystem.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const DIRECTORY_SEPARATOR; +use function basename; +use function dirname; +use function is_dir; +use function mkdir; +use function realpath; +use function str_starts_with; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Filesystem +{ + public static function createDirectory(string $directory): bool + { + return !(!is_dir($directory) && !@mkdir($directory, 0o777, true) && !is_dir($directory)); + } + + /** + * @psalm-param non-empty-string $path + * + * @return false|non-empty-string + */ + public static function resolveStreamOrFile(string $path): false|string + { + if (str_starts_with($path, 'php://') || str_starts_with($path, 'socket://')) { + return $path; + } + + $directory = dirname($path); + + if (is_dir($directory)) { + return realpath($directory) . DIRECTORY_SEPARATOR . basename($path); + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filter.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filter.php new file mode 100644 index 000000000..424e35af4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Filter.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function array_unshift; +use function defined; +use function in_array; +use function is_file; +use function realpath; +use function sprintf; +use function str_starts_with; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\PhptAssertionFailedError; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Filter +{ + /** + * @throws Exception + */ + public static function getFilteredStacktrace(Throwable $t, bool $unwrap = true): string + { + $filteredStacktrace = ''; + + if ($t instanceof PhptAssertionFailedError) { + $eTrace = $t->syntheticTrace(); + $eFile = $t->syntheticFile(); + $eLine = $t->syntheticLine(); + } elseif ($t instanceof Exception) { + $eTrace = $t->getSerializableTrace(); + $eFile = $t->getFile(); + $eLine = $t->getLine(); + } else { + if ($unwrap && $t->getPrevious()) { + $t = $t->getPrevious(); + } + + $eTrace = $t->getTrace(); + $eFile = $t->getFile(); + $eLine = $t->getLine(); + } + + if (!self::frameExists($eTrace, $eFile, $eLine)) { + array_unshift( + $eTrace, + ['file' => $eFile, 'line' => $eLine], + ); + } + + $prefix = defined('__PHPUNIT_PHAR_ROOT__') ? __PHPUNIT_PHAR_ROOT__ : false; + $excludeList = new ExcludeList; + + foreach ($eTrace as $frame) { + if (self::shouldPrintFrame($frame, $prefix, $excludeList)) { + $filteredStacktrace .= sprintf( + "%s:%s\n", + $frame['file'], + $frame['line'] ?? '?', + ); + } + } + + return $filteredStacktrace; + } + + private static function shouldPrintFrame(array $frame, false|string $prefix, ExcludeList $excludeList): bool + { + if (!isset($frame['file'])) { + return false; + } + + $file = $frame['file']; + $fileIsNotPrefixed = $prefix === false || !str_starts_with($file, $prefix); + + // @see https://github.com/sebastianbergmann/phpunit/issues/4033 + if (isset($GLOBALS['_SERVER']['SCRIPT_NAME'])) { + $script = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']); + } else { + $script = ''; + } + + return $fileIsNotPrefixed && + $file !== $script && + self::fileIsExcluded($file, $excludeList) && + is_file($file); + } + + private static function fileIsExcluded(string $file, ExcludeList $excludeList): bool + { + return (empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) || + !in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) && + !$excludeList->isExcluded($file); + } + + private static function frameExists(array $trace, string $file, int $line): bool + { + foreach ($trace as $frame) { + if (isset($frame['file'], $frame['line']) && $frame['file'] === $file && $frame['line'] === $line) { + return true; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/GlobalState.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/GlobalState.php new file mode 100644 index 000000000..0e298392a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/GlobalState.php @@ -0,0 +1,289 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const PHP_MAJOR_VERSION; +use const PHP_MINOR_VERSION; +use function array_keys; +use function array_reverse; +use function array_shift; +use function defined; +use function get_defined_constants; +use function get_included_files; +use function in_array; +use function ini_get_all; +use function is_array; +use function is_file; +use function is_scalar; +use function preg_match; +use function serialize; +use function sprintf; +use function str_ends_with; +use function str_starts_with; +use function strtr; +use function var_export; +use Closure; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class GlobalState +{ + /** + * @psalm-var list + */ + private const SUPER_GLOBAL_ARRAYS = [ + '_ENV', + '_POST', + '_GET', + '_COOKIE', + '_SERVER', + '_FILES', + '_REQUEST', + ]; + + /** + * @psalm-var array> + */ + private const DEPRECATED_INI_SETTINGS = [ + '7.3' => [ + 'iconv.input_encoding' => true, + 'iconv.output_encoding' => true, + 'iconv.internal_encoding' => true, + 'mbstring.func_overload' => true, + 'mbstring.http_input' => true, + 'mbstring.http_output' => true, + 'mbstring.internal_encoding' => true, + 'string.strip_tags' => true, + ], + + '7.4' => [ + 'iconv.input_encoding' => true, + 'iconv.output_encoding' => true, + 'iconv.internal_encoding' => true, + 'mbstring.func_overload' => true, + 'mbstring.http_input' => true, + 'mbstring.http_output' => true, + 'mbstring.internal_encoding' => true, + 'pdo_odbc.db2_instance_name' => true, + 'string.strip_tags' => true, + ], + + '8.0' => [ + 'iconv.input_encoding' => true, + 'iconv.output_encoding' => true, + 'iconv.internal_encoding' => true, + 'mbstring.http_input' => true, + 'mbstring.http_output' => true, + 'mbstring.internal_encoding' => true, + ], + + '8.1' => [ + 'auto_detect_line_endings' => true, + 'filter.default' => true, + 'iconv.input_encoding' => true, + 'iconv.output_encoding' => true, + 'iconv.internal_encoding' => true, + 'mbstring.http_input' => true, + 'mbstring.http_output' => true, + 'mbstring.internal_encoding' => true, + 'oci8.old_oci_close_semantics' => true, + ], + + '8.2' => [ + 'auto_detect_line_endings' => true, + 'filter.default' => true, + 'iconv.input_encoding' => true, + 'iconv.output_encoding' => true, + 'iconv.internal_encoding' => true, + 'mbstring.http_input' => true, + 'mbstring.http_output' => true, + 'mbstring.internal_encoding' => true, + 'oci8.old_oci_close_semantics' => true, + ], + + '8.3' => [ + 'auto_detect_line_endings' => true, + 'filter.default' => true, + 'iconv.input_encoding' => true, + 'iconv.output_encoding' => true, + 'iconv.internal_encoding' => true, + 'mbstring.http_input' => true, + 'mbstring.http_output' => true, + 'mbstring.internal_encoding' => true, + 'oci8.old_oci_close_semantics' => true, + ], + ]; + + /** + * @throws Exception + */ + public static function getIncludedFilesAsString(): string + { + return self::processIncludedFilesAsString(get_included_files()); + } + + /** + * @psalm-param list $files + * + * @throws Exception + */ + public static function processIncludedFilesAsString(array $files): string + { + $excludeList = new ExcludeList; + $prefix = false; + $result = ''; + + if (defined('__PHPUNIT_PHAR__')) { + $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/'; + } + + // Do not process bootstrap script + array_shift($files); + + // If bootstrap script was a Composer bin proxy, skip the second entry as well + if (str_ends_with(strtr($files[0], '\\', '/'), '/phpunit/phpunit/phpunit')) { + array_shift($files); + } + + foreach (array_reverse($files) as $file) { + if (!empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) && + in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) { + continue; + } + + if ($prefix !== false && str_starts_with($file, $prefix)) { + continue; + } + + // Skip virtual file system protocols + if (preg_match('/^(vfs|phpvfs[a-z0-9]+):/', $file)) { + continue; + } + + if (!$excludeList->isExcluded($file) && is_file($file)) { + $result = 'require_once \'' . $file . "';\n" . $result; + } + } + + return $result; + } + + public static function getIniSettingsAsString(): string + { + $result = ''; + + foreach (ini_get_all(null, false) as $key => $value) { + if (self::isIniSettingDeprecated($key)) { + continue; + } + + $result .= sprintf( + '@ini_set(%s, %s);' . "\n", + self::exportVariable($key), + self::exportVariable((string) $value), + ); + } + + return $result; + } + + public static function getConstantsAsString(): string + { + $constants = get_defined_constants(true); + $result = ''; + + if (isset($constants['user'])) { + foreach ($constants['user'] as $name => $value) { + $result .= sprintf( + 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", + $name, + $name, + self::exportVariable($value), + ); + } + } + + return $result; + } + + public static function getGlobalsAsString(): string + { + $result = ''; + + foreach (self::SUPER_GLOBAL_ARRAYS as $superGlobalArray) { + if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) { + foreach (array_keys($GLOBALS[$superGlobalArray]) as $key) { + if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) { + continue; + } + + $result .= sprintf( + '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", + $superGlobalArray, + $key, + self::exportVariable($GLOBALS[$superGlobalArray][$key]), + ); + } + } + } + + $excludeList = self::SUPER_GLOBAL_ARRAYS; + $excludeList[] = 'GLOBALS'; + + foreach (array_keys($GLOBALS) as $key) { + if (!$GLOBALS[$key] instanceof Closure && !in_array($key, $excludeList, true)) { + $result .= sprintf( + '$GLOBALS[\'%s\'] = %s;' . "\n", + $key, + self::exportVariable($GLOBALS[$key]), + ); + } + } + + return $result; + } + + private static function exportVariable(mixed $variable): string + { + if (is_scalar($variable) || $variable === null || + (is_array($variable) && self::arrayOnlyContainsScalars($variable))) { + return var_export($variable, true); + } + + return 'unserialize(' . var_export(serialize($variable), true) . ')'; + } + + private static function arrayOnlyContainsScalars(array $array): bool + { + $result = true; + + foreach ($array as $element) { + if (is_array($element)) { + $result = self::arrayOnlyContainsScalars($element); + } elseif (!is_scalar($element) && $element !== null) { + $result = false; + } + + if (!$result) { + break; + } + } + + return $result; + } + + private static function isIniSettingDeprecated(string $iniSetting): bool + { + return isset(self::DEPRECATED_INI_SETTINGS[PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION][$iniSetting]); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/Downloader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/Downloader.php new file mode 100644 index 000000000..a9af2e38f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/Downloader.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Http; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +interface Downloader +{ + /** + * @param non-empty-string $url + */ + public function download(string $url): false|string; +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/PhpDownloader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/PhpDownloader.php new file mode 100644 index 000000000..1f741833c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Http/PhpDownloader.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Http; + +use function file_get_contents; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class PhpDownloader implements Downloader +{ + /** + * @param non-empty-string $url + */ + public function download(string $url): false|string + { + return file_get_contents($url); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Json.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Json.php new file mode 100644 index 000000000..a9b5e2dcf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Json.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const JSON_PRETTY_PRINT; +use const JSON_UNESCAPED_SLASHES; +use const JSON_UNESCAPED_UNICODE; +use const SORT_STRING; +use function is_object; +use function is_scalar; +use function json_decode; +use function json_encode; +use function json_last_error; +use function ksort; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Json +{ + /** + * @throws InvalidJsonException + */ + public static function prettify(string $json): string + { + $decodedJson = json_decode($json, false); + + if (json_last_error()) { + throw new InvalidJsonException; + } + + return json_encode($decodedJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + /** + * To allow comparison of JSON strings, first process them into a consistent + * format so that they can be compared as strings. + * + * @return array ($error, $canonicalized_json) The $error parameter is used + * to indicate an error decoding the json. This is used to avoid ambiguity + * with JSON strings consisting entirely of 'null' or 'false'. + */ + public static function canonicalize(string $json): array + { + $decodedJson = json_decode($json); + + if (json_last_error()) { + return [true, null]; + } + + self::recursiveSort($decodedJson); + + $reencodedJson = json_encode($decodedJson); + + return [false, $reencodedJson]; + } + + /** + * JSON object keys are unordered while PHP array keys are ordered. + * + * Sort all array keys to ensure both the expected and actual values have + * their keys in the same order. + */ + private static function recursiveSort(mixed &$json): void + { + // Nulls, empty arrays, and scalars need no further handling. + if (!$json || is_scalar($json)) { + return; + } + + $isObject = is_object($json); + + if ($isObject) { + // Objects need to be sorted during canonicalization to ensure + // correct comparsion since JSON objects are unordered. It must be + // kept as an object so that the value correctly stays as a JSON + // object instead of potentially being converted to an array. This + // approach ensures that numeric string JSON keys are preserved and + // don't risk being flattened due to PHP's array semantics. + // See #2919, #4584, #4674 + $json = (array) $json; + ksort($json, SORT_STRING); + } + + foreach ($json as &$value) { + self::recursiveSort($value); + } + + if ($isObject) { + $json = (object) $json; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php new file mode 100644 index 000000000..178df1167 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/AbstractPhpProcess.php @@ -0,0 +1,322 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\PHP; + +use const PHP_BINARY; +use const PHP_SAPI; +use function array_keys; +use function array_merge; +use function assert; +use function explode; +use function file_exists; +use function file_get_contents; +use function ini_get_all; +use function restore_error_handler; +use function set_error_handler; +use function trim; +use function unlink; +use function unserialize; +use ErrorException; +use PHPUnit\Event\Code\TestMethodBuilder; +use PHPUnit\Event\Code\ThrowableBuilder; +use PHPUnit\Event\Facade; +use PHPUnit\Event\NoPreviousThrowableException; +use PHPUnit\Event\TestData\MoreThanOneDataSetFromDataProviderException; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Exception; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Runner\CodeCoverage; +use PHPUnit\TestRunner\TestResult\PassedTests; +use SebastianBergmann\Environment\Runtime; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +abstract class AbstractPhpProcess +{ + protected bool $stderrRedirection = false; + protected string $stdin = ''; + protected string $arguments = ''; + + /** + * @psalm-var array + */ + protected array $env = []; + + public static function factory(): self + { + return new DefaultPhpProcess; + } + + /** + * Defines if should use STDERR redirection or not. + * + * Then $stderrRedirection is TRUE, STDERR is redirected to STDOUT. + */ + public function setUseStderrRedirection(bool $stderrRedirection): void + { + $this->stderrRedirection = $stderrRedirection; + } + + /** + * Returns TRUE if uses STDERR redirection or FALSE if not. + */ + public function useStderrRedirection(): bool + { + return $this->stderrRedirection; + } + + /** + * Sets the input string to be sent via STDIN. + */ + public function setStdin(string $stdin): void + { + $this->stdin = $stdin; + } + + /** + * Returns the input string to be sent via STDIN. + */ + public function getStdin(): string + { + return $this->stdin; + } + + /** + * Sets the string of arguments to pass to the php job. + */ + public function setArgs(string $arguments): void + { + $this->arguments = $arguments; + } + + /** + * Returns the string of arguments to pass to the php job. + */ + public function getArgs(): string + { + return $this->arguments; + } + + /** + * Sets the array of environment variables to start the child process with. + * + * @psalm-param array $env + */ + public function setEnv(array $env): void + { + $this->env = $env; + } + + /** + * Returns the array of environment variables to start the child process with. + */ + public function getEnv(): array + { + return $this->env; + } + + /** + * Runs a single test in a separate PHP process. + * + * @throws \PHPUnit\Runner\Exception + * @throws Exception + * @throws MoreThanOneDataSetFromDataProviderException + * @throws NoPreviousThrowableException + */ + public function runTestJob(string $job, Test $test, string $processResultFile): void + { + $_result = $this->runJob($job); + + $processResult = ''; + + if (file_exists($processResultFile)) { + $processResult = file_get_contents($processResultFile); + + @unlink($processResultFile); + } + + $this->processChildResult( + $test, + $processResult, + $_result['stderr'], + ); + } + + /** + * Returns the command based into the configurations. + * + * @return string[] + */ + public function getCommand(array $settings, ?string $file = null): array + { + $runtime = new Runtime; + + $command = []; + $command[] = PHP_BINARY; + + if ($runtime->hasPCOV()) { + $settings = array_merge( + $settings, + $runtime->getCurrentSettings( + array_keys(ini_get_all('pcov')), + ), + ); + } elseif ($runtime->hasXdebug()) { + $settings = array_merge( + $settings, + $runtime->getCurrentSettings( + array_keys(ini_get_all('xdebug')), + ), + ); + } + + $command = array_merge($command, $this->settingsToParameters($settings)); + + if (PHP_SAPI === 'phpdbg') { + $command[] = '-qrr'; + + if (!$file) { + $command[] = 's='; + } + } + + if ($file) { + $command[] = '-f'; + $command[] = $file; + } + + if ($this->arguments) { + if (!$file) { + $command[] = '--'; + } + + foreach (explode(' ', $this->arguments) as $arg) { + $command[] = trim($arg); + } + } + + return $command; + } + + /** + * Runs a single job (PHP code) using a separate PHP process. + */ + abstract public function runJob(string $job, array $settings = []): array; + + /** + * @return list + */ + protected function settingsToParameters(array $settings): array + { + $buffer = []; + + foreach ($settings as $setting) { + $buffer[] = '-d'; + $buffer[] = $setting; + } + + return $buffer; + } + + /** + * @throws \PHPUnit\Runner\Exception + * @throws Exception + * @throws MoreThanOneDataSetFromDataProviderException + * @throws NoPreviousThrowableException + */ + private function processChildResult(Test $test, string $stdout, string $stderr): void + { + if (!empty($stderr)) { + $exception = new Exception(trim($stderr)); + + assert($test instanceof TestCase); + + Facade::emitter()->testErrored( + TestMethodBuilder::fromTestCase($test), + ThrowableBuilder::from($exception), + ); + + return; + } + + set_error_handler( + /** + * @throws ErrorException + */ + static function (int $errno, string $errstr, string $errfile, int $errline): never + { + throw new ErrorException($errstr, $errno, $errno, $errfile, $errline); + }, + ); + + try { + $childResult = unserialize($stdout); + + restore_error_handler(); + + if ($childResult === false) { + $exception = new AssertionFailedError('Test was run in child process and ended unexpectedly'); + + assert($test instanceof TestCase); + + Facade::emitter()->testErrored( + TestMethodBuilder::fromTestCase($test), + ThrowableBuilder::from($exception), + ); + + Facade::emitter()->testFinished( + TestMethodBuilder::fromTestCase($test), + 0, + ); + } + } catch (ErrorException $e) { + restore_error_handler(); + + $childResult = false; + + $exception = new Exception(trim($stdout), 0, $e); + + assert($test instanceof TestCase); + + Facade::emitter()->testErrored( + TestMethodBuilder::fromTestCase($test), + ThrowableBuilder::from($exception), + ); + } + + if ($childResult !== false) { + if (!empty($childResult['output'])) { + $output = $childResult['output']; + } + + Facade::instance()->forward($childResult['events']); + PassedTests::instance()->import($childResult['passedTests']); + + assert($test instanceof TestCase); + + $test->setResult($childResult['testResult']); + $test->addToAssertionCount($childResult['numAssertions']); + + if (CodeCoverage::instance()->isActive() && $childResult['codeCoverage'] instanceof \SebastianBergmann\CodeCoverage\CodeCoverage) { + CodeCoverage::instance()->codeCoverage()->merge( + $childResult['codeCoverage'], + ); + } + } + + if (!empty($output)) { + print $output; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php new file mode 100644 index 000000000..e933c24e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/DefaultPhpProcess.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\PHP; + +use function array_merge; +use function fclose; +use function file_put_contents; +use function fwrite; +use function is_array; +use function is_resource; +use function proc_close; +use function proc_open; +use function stream_get_contents; +use function sys_get_temp_dir; +use function tempnam; +use function unlink; +use PHPUnit\Framework\Exception; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +class DefaultPhpProcess extends AbstractPhpProcess +{ + private ?string $tempFile = null; + + /** + * Runs a single job (PHP code) using a separate PHP process. + * + * @psalm-return array{stdout: string, stderr: string} + * + * @throws Exception + * @throws PhpProcessException + */ + public function runJob(string $job, array $settings = []): array + { + if ($this->stdin) { + if (!($this->tempFile = tempnam(sys_get_temp_dir(), 'phpunit_')) || + file_put_contents($this->tempFile, $job) === false) { + throw new PhpProcessException( + 'Unable to write temporary file', + ); + } + + $job = $this->stdin; + } + + return $this->runProcess($job, $settings); + } + + /** + * Handles creating the child process and returning the STDOUT and STDERR. + * + * @psalm-return array{stdout: string, stderr: string} + * + * @throws Exception + * @throws PhpProcessException + */ + protected function runProcess(string $job, array $settings): array + { + $env = null; + + if ($this->env) { + $env = $_SERVER ?? []; + unset($env['argv'], $env['argc']); + $env = array_merge($env, $this->env); + + foreach ($env as $envKey => $envVar) { + if (is_array($envVar)) { + unset($env[$envKey]); + } + } + } + + $pipeSpec = [ + 0 => ['pipe', 'r'], + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + if ($this->stderrRedirection) { + $pipeSpec[2] = ['redirect', 1]; + } + + $process = proc_open( + $this->getCommand($settings, $this->tempFile), + $pipeSpec, + $pipes, + null, + $env, + ); + + if (!is_resource($process)) { + throw new PhpProcessException( + 'Unable to spawn worker process', + ); + } + + if ($job) { + $this->process($pipes[0], $job); + } + + fclose($pipes[0]); + + $stderr = $stdout = ''; + + if (isset($pipes[1])) { + $stdout = stream_get_contents($pipes[1]); + + fclose($pipes[1]); + } + + if (isset($pipes[2])) { + $stderr = stream_get_contents($pipes[2]); + + fclose($pipes[2]); + } + + proc_close($process); + + $this->cleanup(); + + return ['stdout' => $stdout, 'stderr' => $stderr]; + } + + /** + * @param resource $pipe + */ + protected function process($pipe, string $job): void + { + fwrite($pipe, $job); + } + + protected function cleanup(): void + { + if ($this->tempFile) { + unlink($this->tempFile); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl new file mode 100644 index 000000000..c42518886 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/PhptTestCase.tpl @@ -0,0 +1,56 @@ +{driverMethod}($filter), + $filter + ); + + if ({codeCoverageCacheDirectory}) { + $coverage->cacheStaticAnalysis({codeCoverageCacheDirectory}); + } + + $coverage->start(__FILE__); +} + +register_shutdown_function( + function() use ($coverage) { + $output = null; + + if ($coverage) { + $output = $coverage->stop(); + } + + file_put_contents('{coverageFile}', serialize($output)); + } +); + +ob_end_clean(); + +require '{job}'; diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl new file mode 100644 index 000000000..0a869c4d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseClass.tpl @@ -0,0 +1,116 @@ +initForIsolation( + PHPUnit\Event\Telemetry\HRTime::fromSecondsAndNanoseconds( + {offsetSeconds}, + {offsetNanoseconds} + ), + {exportObjects}, + ); + + require_once '{filename}'; + + if ({collectCodeCoverageInformation}) { + CodeCoverage::instance()->init(ConfigurationRegistry::get(), CodeCoverageFilterRegistry::instance(), true); + CodeCoverage::instance()->ignoreLines({linesToBeIgnored}); + } + + $test = new {className}('{name}'); + + $test->setData('{dataName}', unserialize('{data}')); + $test->setDependencyInput(unserialize('{dependencyInput}')); + $test->setInIsolation(true); + + ob_end_clean(); + + $test->run(); + + $output = ''; + + if (!$test->expectsOutput()) { + $output = $test->output(); + } + + ini_set('xdebug.scream', '0'); + + // Not every STDOUT target stream is rewindable + @rewind(STDOUT); + + if ($stdout = @stream_get_contents(STDOUT)) { + $output = $stdout . $output; + $streamMetaData = stream_get_meta_data(STDOUT); + + if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { + @ftruncate(STDOUT, 0); + @rewind(STDOUT); + } + } + + file_put_contents( + '{processResultFile}', + serialize( + [ + 'testResult' => $test->result(), + 'codeCoverage' => {collectCodeCoverageInformation} ? CodeCoverage::instance()->codeCoverage() : null, + 'numAssertions' => $test->numberOfAssertionsPerformed(), + 'output' => $output, + 'events' => $dispatcher->flush(), + 'passedTests' => PassedTests::instance() + ] + ) + ); +} + +function __phpunit_error_handler($errno, $errstr, $errfile, $errline) +{ + return true; +} + +set_error_handler('__phpunit_error_handler'); + +{constants} +{included_files} +{globals} + +restore_error_handler(); + +ConfigurationRegistry::loadFrom('{serializedConfiguration}'); +(new PhpHandler)->handle(ConfigurationRegistry::get()->php()); + +if ('{bootstrap}' !== '') { + require_once '{bootstrap}'; +} + +__phpunit_run_isolated_test(); diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl new file mode 100644 index 000000000..3e508ef62 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/PHP/Template/TestCaseMethod.tpl @@ -0,0 +1,116 @@ +initForIsolation( + PHPUnit\Event\Telemetry\HRTime::fromSecondsAndNanoseconds( + {offsetSeconds}, + {offsetNanoseconds} + ), + {exportObjects}, + ); + + require_once '{filename}'; + + if ({collectCodeCoverageInformation}) { + CodeCoverage::instance()->init(ConfigurationRegistry::get(), CodeCoverageFilterRegistry::instance(), true); + CodeCoverage::instance()->ignoreLines({linesToBeIgnored}); + } + + $test = new {className}('{methodName}'); + + $test->setData('{dataName}', unserialize('{data}')); + $test->setDependencyInput(unserialize('{dependencyInput}')); + $test->setInIsolation(true); + + ob_end_clean(); + + $test->run(); + + $output = ''; + + if (!$test->expectsOutput()) { + $output = $test->output(); + } + + ini_set('xdebug.scream', '0'); + + // Not every STDOUT target stream is rewindable + @rewind(STDOUT); + + if ($stdout = @stream_get_contents(STDOUT)) { + $output = $stdout . $output; + $streamMetaData = stream_get_meta_data(STDOUT); + + if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { + @ftruncate(STDOUT, 0); + @rewind(STDOUT); + } + } + + file_put_contents( + '{processResultFile}', + serialize( + [ + 'testResult' => $test->result(), + 'codeCoverage' => {collectCodeCoverageInformation} ? CodeCoverage::instance()->codeCoverage() : null, + 'numAssertions' => $test->numberOfAssertionsPerformed(), + 'output' => $output, + 'events' => $dispatcher->flush(), + 'passedTests' => PassedTests::instance() + ] + ) + ); +} + +function __phpunit_error_handler($errno, $errstr, $errfile, $errline) +{ + return true; +} + +set_error_handler('__phpunit_error_handler'); + +{constants} +{included_files} +{globals} + +restore_error_handler(); + +ConfigurationRegistry::loadFrom('{serializedConfiguration}'); +(new PhpHandler)->handle(ConfigurationRegistry::get()->php()); + +if ('{bootstrap}' !== '') { + require_once '{bootstrap}'; +} + +__phpunit_run_isolated_test(); diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Reflection.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Reflection.php new file mode 100644 index 000000000..0aac9259d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Reflection.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function array_keys; +use function array_merge; +use function array_reverse; +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Reflection +{ + /** + * @psalm-param class-string $className + * @psalm-param non-empty-string $methodName + * + * @psalm-return array{file: non-empty-string, line: non-negative-int} + */ + public static function sourceLocationFor(string $className, string $methodName): array + { + try { + $reflector = new ReflectionMethod($className, $methodName); + + $file = $reflector->getFileName(); + $line = $reflector->getStartLine(); + } catch (ReflectionException) { + $file = 'unknown'; + $line = 0; + } + + return [ + 'file' => $file, + 'line' => $line, + ]; + } + + /** + * @psalm-return list + */ + public static function publicMethodsInTestClass(ReflectionClass $class): array + { + return self::filterAndSortMethods($class, ReflectionMethod::IS_PUBLIC, true); + } + + /** + * @psalm-return list + */ + public static function methodsInTestClass(ReflectionClass $class): array + { + return self::filterAndSortMethods($class, null, false); + } + + /** + * @psalm-return list + */ + private static function filterAndSortMethods(ReflectionClass $class, ?int $filter, bool $sortHighestToLowest): array + { + $methodsByClass = []; + + foreach ($class->getMethods($filter) as $method) { + $declaringClassName = $method->getDeclaringClass()->getName(); + + if ($declaringClassName === TestCase::class) { + continue; + } + + if ($declaringClassName === Assert::class) { + continue; + } + + if (!isset($methodsByClass[$declaringClassName])) { + $methodsByClass[$declaringClassName] = []; + } + + $methodsByClass[$declaringClassName][] = $method; + } + + $classNames = array_keys($methodsByClass); + + if ($sortHighestToLowest) { + $classNames = array_reverse($classNames); + } + + $methods = []; + + foreach ($classNames as $className) { + $methods = array_merge($methods, $methodsByClass[$className]); + } + + return $methods; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Test.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Test.php new file mode 100644 index 000000000..51d907696 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Test.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function str_starts_with; +use PHPUnit\Metadata\Parser\Registry; +use ReflectionMethod; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Test +{ + public static function isTestMethod(ReflectionMethod $method): bool + { + if (!$method->isPublic()) { + return false; + } + + if (str_starts_with($method->getName(), 'test')) { + return true; + } + + $metadata = Registry::parser()->forMethod( + $method->getDeclaringClass()->getName(), + $method->getName(), + ); + + return $metadata->isTest()->isNotEmpty(); + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ThrowableToStringMapper.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ThrowableToStringMapper.php new file mode 100644 index 000000000..a0c1289a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/ThrowableToStringMapper.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function trim; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\PhptAssertionFailedError; +use PHPUnit\Framework\SelfDescribing; +use PHPUnit\Runner\ErrorException; +use Throwable; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class ThrowableToStringMapper +{ + public static function map(Throwable $t): string + { + if ($t instanceof ErrorException) { + return $t->getMessage(); + } + + if ($t instanceof SelfDescribing) { + $buffer = $t->toString(); + + if ($t instanceof ExpectationFailedException && $t->getComparisonFailure()) { + $buffer .= $t->getComparisonFailure()->getDiff(); + } + + if ($t instanceof PhptAssertionFailedError) { + $buffer .= $t->diff(); + } + + if (!empty($buffer)) { + $buffer = trim($buffer) . "\n"; + } + + return $buffer; + } + + return $t::class . ': ' . $t->getMessage() . "\n"; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php new file mode 100644 index 000000000..ad108335e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/VersionComparisonOperator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use function in_array; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @psalm-immutable + */ +final class VersionComparisonOperator +{ + /** + * @psalm-var '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' + */ + private readonly string $operator; + + /** + * @psalm-param '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' $operator + * + * @throws InvalidVersionOperatorException + */ + public function __construct(string $operator) + { + $this->ensureOperatorIsValid($operator); + + $this->operator = $operator; + } + + /** + * @psalm-return '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' + */ + public function asString(): string + { + return $this->operator; + } + + /** + * @psalm-param '<'|'lt'|'<='|'le'|'>'|'gt'|'>='|'ge'|'=='|'='|'eq'|'!='|'<>'|'ne' $operator + * + * @throws InvalidVersionOperatorException + */ + private function ensureOperatorIsValid(string $operator): void + { + if (!in_array($operator, ['<', 'lt', '<=', 'le', '>', 'gt', '>=', 'ge', '==', '=', 'eq', '!=', '<>', 'ne'], true)) { + throw new InvalidVersionOperatorException($operator); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Loader.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Loader.php new file mode 100644 index 000000000..3a027619e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Loader.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\Xml; + +use const PHP_OS_FAMILY; +use function chdir; +use function dirname; +use function error_reporting; +use function file_get_contents; +use function getcwd; +use function libxml_get_errors; +use function libxml_use_internal_errors; +use function sprintf; +use DOMDocument; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Loader +{ + /** + * @throws XmlException + */ + public function loadFile(string $filename): DOMDocument + { + $reporting = error_reporting(0); + $contents = file_get_contents($filename); + + error_reporting($reporting); + + if ($contents === false) { + throw new XmlException( + sprintf( + 'Could not read XML from file "%s"', + $filename, + ), + ); + } + + return $this->load($contents, $filename); + } + + /** + * @throws XmlException + */ + public function load(string $actual, ?string $filename = null): DOMDocument + { + if ($actual === '') { + if ($filename === null) { + throw new XmlException('Could not parse XML from empty string'); + } + + throw new XmlException( + sprintf( + 'Could not parse XML from empty file "%s"', + $filename, + ), + ); + } + + $document = new DOMDocument; + $document->preserveWhiteSpace = false; + + $internal = libxml_use_internal_errors(true); + $message = ''; + $reporting = error_reporting(0); + + // Required for XInclude + if ($filename !== null) { + // Required for XInclude on Windows + if (PHP_OS_FAMILY === 'Windows') { + $cwd = getcwd(); + @chdir(dirname($filename)); + } + + $document->documentURI = $filename; + } + + $loaded = $document->loadXML($actual); + + if ($filename !== null) { + $document->xinclude(); + } + + foreach (libxml_get_errors() as $error) { + $message .= "\n" . $error->message; + } + + libxml_use_internal_errors($internal); + error_reporting($reporting); + + if (isset($cwd)) { + @chdir($cwd); + } + + if ($loaded === false || $message !== '') { + if ($filename !== null) { + throw new XmlException( + sprintf( + 'Could not load "%s"%s', + $filename, + $message !== '' ? ":\n" . $message : '', + ), + ); + } + + if ($message === '') { + $message = 'Could not load XML for unknown reason'; + } + + throw new XmlException($message); + } + + return $document; + } +} diff --git a/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Xml.php b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Xml.php new file mode 100644 index 000000000..70c5fec7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/phpunit/phpunit/src/Util/Xml/Xml.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use const ENT_QUOTES; +use function htmlspecialchars; +use function mb_convert_encoding; +use function ord; +use function preg_replace; +use function strlen; + +/** + * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit + * + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class Xml +{ + /** + * Escapes a string for the use in XML documents. + * + * Any Unicode character is allowed, excluding the surrogate blocks, FFFE, + * and FFFF (not even as character reference). + * + * @see https://www.w3.org/TR/xml/#charsets + */ + public static function prepareString(string $string): string + { + return preg_replace( + '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/', + '', + htmlspecialchars( + self::convertToUtf8($string), + ENT_QUOTES, + ), + ); + } + + private static function convertToUtf8(string $string): string + { + if (!self::isUtf8($string)) { + $string = mb_convert_encoding($string, 'UTF-8'); + } + + return $string; + } + + private static function isUtf8(string $string): bool + { + $length = strlen($string); + + for ($i = 0; $i < $length; $i++) { + if (ord($string[$i]) < 0x80) { + $n = 0; + } elseif ((ord($string[$i]) & 0xE0) === 0xC0) { + $n = 1; + } elseif ((ord($string[$i]) & 0xF0) === 0xE0) { + $n = 2; + } elseif ((ord($string[$i]) & 0xF0) === 0xF0) { + $n = 3; + } else { + return false; + } + + for ($j = 0; $j < $n; $j++) { + if ((++$i === $length) || ((ord($string[$i]) & 0xC0) !== 0x80)) { + return false; + } + } + } + + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/LICENSE b/.extlib/simplesamlphp/vendor/predis/predis/LICENSE new file mode 100644 index 000000000..ee78cd7cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2009-2020 Daniele Alessandri (original work) +Copyright (c) 2021-2024 Till Krüss (modified work) + +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/.extlib/simplesamlphp/vendor/predis/predis/README.md b/.extlib/simplesamlphp/vendor/predis/predis/README.md new file mode 100644 index 000000000..c511471e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/README.md @@ -0,0 +1,466 @@ +# Predis # + +[![Software license][ico-license]](LICENSE) +[![Latest stable][ico-version-stable]][link-releases] +[![Latest development][ico-version-dev]][link-releases] +[![Monthly installs][ico-downloads-monthly]][link-downloads] +[![Build status][ico-build]][link-actions] +[![Coverage Status][ico-coverage]][link-coverage] + +A flexible and feature-complete [Redis](http://redis.io) client for PHP 7.2 and newer. + +More details about this project can be found on the [frequently asked questions](FAQ.md). + + +## Main features ## + +- Support for Redis from __3.0__ to __7.4__. +- Support for clustering using client-side sharding and pluggable keyspace distributors. +- Support for [redis-cluster](http://redis.io/topics/cluster-tutorial) (Redis >= 3.0). +- Support for master-slave replication setups and [redis-sentinel](http://redis.io/topics/sentinel). +- Transparent key prefixing of keys using a customizable prefix strategy. +- Command pipelining on both single nodes and clusters (client-side sharding only). +- Abstraction for Redis transactions (Redis >= 2.0) and CAS operations (Redis >= 2.2). +- Abstraction for Lua scripting (Redis >= 2.6) and automatic switching between `EVALSHA` or `EVAL`. +- Abstraction for `SCAN`, `SSCAN`, `ZSCAN` and `HSCAN` (Redis >= 2.8) based on PHP iterators. +- Connections are established lazily by the client upon the first command and can be persisted. +- Connections can be established via TCP/IP (also TLS/SSL-encrypted) or UNIX domain sockets. +- Support for custom connection classes for providing different network or protocol backends. +- Flexible system for defining custom commands and override the default ones. + + +## How to _install_ and use Predis ## + +This library can be found on [Packagist](http://packagist.org/packages/predis/predis) for an easier +management of projects dependencies using [Composer](http://packagist.org/about-composer). +Compressed archives of each release are [available on GitHub](https://github.com/predis/predis/releases). + +```shell +composer require predis/predis +``` + + +### Loading the library ### + +Predis relies on the autoloading features of PHP to load its files when needed and complies with the +[PSR-4 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md). +Autoloading is handled automatically when dependencies are managed through Composer, but it is also +possible to leverage its own autoloader in projects or scripts lacking any autoload facility: + +```php +// Prepend a base path if Predis is not available in your "include_path". +require 'Predis/Autoloader.php'; + +Predis\Autoloader::register(); +``` + + +### Connecting to Redis ### + +When creating a client instance without passing any connection parameter, Predis assumes `127.0.0.1` +and `6379` as default host and port. The default timeout for the `connect()` operation is 5 seconds: + +```php +$client = new Predis\Client(); +$client->set('foo', 'bar'); +$value = $client->get('foo'); +``` + +Connection parameters can be supplied either in the form of URI strings or named arrays. The latter +is the preferred way to supply parameters, but URI strings can be useful when parameters are read +from non-structured or partially-structured sources: + +```php +// Parameters passed using a named array: +$client = new Predis\Client([ + 'scheme' => 'tcp', + 'host' => '10.0.0.1', + 'port' => 6379, +]); + +// Same set of parameters, passed using an URI string: +$client = new Predis\Client('tcp://10.0.0.1:6379'); +``` + +Password protected servers can be accessed by adding `password` to the parameters set. When ACLs are +enabled on Redis >= 6.0, both `username` and `password` are required for user authentication. + +It is also possible to connect to local instances of Redis using UNIX domain sockets, in this case +the parameters must use the `unix` scheme and specify a path for the socket file: + +```php +$client = new Predis\Client(['scheme' => 'unix', 'path' => '/path/to/redis.sock']); +$client = new Predis\Client('unix:/path/to/redis.sock'); +``` + +The client can leverage TLS/SSL encryption to connect to secured remote Redis instances without the +need to configure an SSL proxy like stunnel. This can be useful when connecting to nodes running on +various cloud hosting providers. Encryption can be enabled with using the `tls` scheme and an array +of suitable [options](http://php.net/manual/context.ssl.php) passed via the `ssl` parameter: + +```php +// Named array of connection parameters: +$client = new Predis\Client([ + 'scheme' => 'tls', + 'ssl' => ['cafile' => 'private.pem', 'verify_peer' => true], +]); + +// Same set of parameters, but using an URI string: +$client = new Predis\Client('tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1'); +``` + +The connection schemes [`redis`](http://www.iana.org/assignments/uri-schemes/prov/redis) (alias of +`tcp`) and [`rediss`](http://www.iana.org/assignments/uri-schemes/prov/rediss) (alias of `tls`) are +also supported, with the difference that URI strings containing these schemes are parsed following +the rules described on their respective IANA provisional registration documents. + +The actual list of supported connection parameters can vary depending on each connection backend so +it is recommended to refer to their specific documentation or implementation for details. + +Predis can aggregate multiple connections when providing an array of connection parameters and the +appropriate option to instruct the client about how to aggregate them (clustering, replication or a +custom aggregation logic). Named arrays and URI strings can be mixed when providing configurations +for each node: + +```php +$client = new Predis\Client([ + 'tcp://10.0.0.1?alias=first-node', ['host' => '10.0.0.2', 'alias' => 'second-node'], +], [ + 'cluster' => 'predis', +]); +``` + +See the [aggregate connections](#aggregate-connections) section of this document for more details. + +Connections to Redis are lazy meaning that the client connects to a server only if and when needed. +While it is recommended to let the client do its own stuff under the hood, there may be times when +it is still desired to have control of when the connection is opened or closed: this can easily be +achieved by invoking `$client->connect()` and `$client->disconnect()`. Please note that the effect +of these methods on aggregate connections may differ depending on each specific implementation. + + +### Client configuration ### + +Many aspects and behaviors of the client can be configured by passing specific client options to the +second argument of `Predis\Client::__construct()`: + +```php +$client = new Predis\Client($parameters, ['prefix' => 'sample:']); +``` + +Options are managed using a mini DI-alike container and their values can be lazily initialized only +when needed. The client options supported by default in Predis are: + + - `prefix`: prefix string applied to every key found in commands. + - `exceptions`: whether the client should throw or return responses upon Redis errors. + - `connections`: list of connection backends or a connection factory instance. + - `cluster`: specifies a cluster backend (`predis`, `redis` or callable). + - `replication`: specifies a replication backend (`predis`, `sentinel` or callable). + - `aggregate`: configures the client with a custom aggregate connection (callable). + - `parameters`: list of default connection parameters for aggregate connections. + - `commands`: specifies a command factory instance to use through the library. + +Users can also provide custom options with values or callable objects (for lazy initialization) that +are stored in the options container for later use through the library. + + +### Aggregate connections ### + +Aggregate connections are the foundation upon which Predis implements clustering and replication and +they are used to group multiple connections to single Redis nodes and hide the specific logic needed +to handle them properly depending on the context. Aggregate connections usually require an array of +connection parameters along with the appropriate client option when creating a new client instance. + +#### Cluster #### + +Predis can be configured to work in clustering mode with a traditional client-side sharding approach +to create a cluster of independent nodes and distribute the keyspace among them. This approach needs +some sort of external health monitoring of nodes and requires the keyspace to be rebalanced manually +when nodes are added or removed: + +```php +$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3']; +$options = ['cluster' => 'predis']; + +$client = new Predis\Client($parameters); +``` + +Along with Redis 3.0, a new supervised and coordinated type of clustering was introduced in the form +of [redis-cluster](http://redis.io/topics/cluster-tutorial). This kind of approach uses a different +algorithm to distribute the keyspaces, with Redis nodes coordinating themselves by communicating via +a gossip protocol to handle health status, rebalancing, nodes discovery and request redirection. In +order to connect to a cluster managed by redis-cluster, the client requires a list of its nodes (not +necessarily complete since it will automatically discover new nodes if necessary) and the `cluster` +client options set to `redis`: + +```php +$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3']; +$options = ['cluster' => 'redis']; + +$client = new Predis\Client($parameters, $options); +``` + +#### Replication #### + +The client can be configured to operate in a single master / multiple slaves setup to provide better +service availability. When using replication, Predis recognizes read-only commands and sends them to +a random slave in order to provide some sort of load-balancing and switches to the master as soon as +it detects a command that performs any kind of operation that would end up modifying the keyspace or +the value of a key. Instead of raising a connection error when a slave fails, the client attempts to +fall back to a different slave among the ones provided in the configuration. + +The basic configuration needed to use the client in replication mode requires one Redis server to be +identified as the master (this can be done via connection parameters by setting the `role` parameter +to `master`) and one or more slaves (in this case setting `role` to `slave` for slaves is optional): + +```php +$parameters = ['tcp://10.0.0.1?role=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3']; +$options = ['replication' => 'predis']; + +$client = new Predis\Client($parameters, $options); +``` + +The above configuration has a static list of servers and relies entirely on the client's logic, but +it is possible to rely on [`redis-sentinel`](http://redis.io/topics/sentinel) for a more robust HA +environment with sentinel servers acting as a source of authority for clients for service discovery. +The minimum configuration required by the client to work with redis-sentinel is a list of connection +parameters pointing to a bunch of sentinel instances, the `replication` option set to `sentinel` and +the `service` option set to the name of the service: + +```php +$sentinels = ['tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3']; +$options = ['replication' => 'sentinel', 'service' => 'mymaster']; + +$client = new Predis\Client($sentinels, $options); +``` + +If the master and slave nodes are configured to require an authentication from clients, a password +must be provided via the global `parameters` client option. This option can also be used to specify +a different database index. The client options array would then look like this: + +```php +$options = [ + 'replication' => 'sentinel', + 'service' => 'mymaster', + 'parameters' => [ + 'password' => $secretpassword, + 'database' => 10, + ], +]; +``` + +While Predis is able to distinguish commands performing write and read-only operations, `EVAL` and +`EVALSHA` represent a corner case in which the client switches to the master node because it cannot +tell when a Lua script is safe to be executed on slaves. While this is indeed the default behavior, +when certain Lua scripts do not perform write operations it is possible to provide an hint to tell +the client to stick with slaves for their execution: + +```php +$parameters = ['tcp://10.0.0.1?role=master', 'tcp://10.0.0.2', 'tcp://10.0.0.3']; +$options = ['replication' => function () { + // Set scripts that won't trigger a switch from a slave to the master node. + $strategy = new Predis\Replication\ReplicationStrategy(); + $strategy->setScriptReadOnly($LUA_SCRIPT); + + return new Predis\Connection\Replication\MasterSlaveReplication($strategy); +}]; + +$client = new Predis\Client($parameters, $options); +$client->eval($LUA_SCRIPT, 0); // Sticks to slave using `eval`... +$client->evalsha(sha1($LUA_SCRIPT), 0); // ... and `evalsha`, too. +``` + +The [`examples`](examples/) directory contains a few scripts that demonstrate how the client can be +configured and used to leverage replication in both basic and complex scenarios. + + +### Command pipelines ### + +Pipelining can help with performances when many commands need to be sent to a server by reducing the +latency introduced by network round-trip timings. Pipelining also works with aggregate connections. +The client can execute the pipeline inside a callable block or return a pipeline instance with the +ability to chain commands thanks to its fluent interface: + +```php +// Executes a pipeline inside the given callable block: +$responses = $client->pipeline(function ($pipe) { + for ($i = 0; $i < 1000; $i++) { + $pipe->set("key:$i", str_pad($i, 4, '0', 0)); + $pipe->get("key:$i"); + } +}); + +// Returns a pipeline that can be chained thanks to its fluent interface: +$responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute(); +``` + + +### Transactions ### + +The client provides an abstraction for Redis transactions based on `MULTI` and `EXEC` with a similar +interface to command pipelines: + +```php +// Executes a transaction inside the given callable block: +$responses = $client->transaction(function ($tx) { + $tx->set('foo', 'bar'); + $tx->get('foo'); +}); + +// Returns a transaction that can be chained thanks to its fluent interface: +$responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute(); +``` + +This abstraction can perform check-and-set operations thanks to `WATCH` and `UNWATCH` and provides +automatic retries of transactions aborted by Redis when `WATCH`ed keys are touched. For an example +of a transaction using CAS you can see [the following example](examples/transaction_using_cas.php). + + +### Adding new commands ### + +While we try to update Predis to stay up to date with all the commands available in Redis, you might +prefer to stick with an old version of the library or provide a different way to filter arguments or +parse responses for specific commands. To achieve that, Predis provides the ability to implement new +command classes to define or override commands in the default command factory used by the client: + +```php +// Define a new command by extending Predis\Command\Command: +class BrandNewRedisCommand extends Predis\Command\Command +{ + public function getId() + { + return 'NEWCMD'; + } +} + +// Inject your command in the current command factory: +$client = new Predis\Client($parameters, [ + 'commands' => [ + 'newcmd' => 'BrandNewRedisCommand', + ], +]); + +$response = $client->newcmd(); +``` + +There is also a method to send raw commands without filtering their arguments or parsing responses. +Users must provide the list of arguments for the command as an array, following the signatures as +defined by the [Redis documentation for commands](http://redis.io/commands): + +```php +$response = $client->executeRaw(['SET', 'foo', 'bar']); +``` + + +### Script commands ### + +While it is possible to leverage [Lua scripting](http://redis.io/commands/eval) on Redis 2.6+ using +directly [`EVAL`](http://redis.io/commands/eval) and [`EVALSHA`](http://redis.io/commands/evalsha), +Predis offers script commands as an higher level abstraction built upon them to make things simple. +Script commands can be registered in the command factory used by the client and are accessible as if +they were plain Redis commands, but they define Lua scripts that get transmitted to the server for +remote execution. Internally they use [`EVALSHA`](http://redis.io/commands/evalsha) by default and +identify a script by its SHA1 hash to save bandwidth, but [`EVAL`](http://redis.io/commands/eval) +is used as a fall back when needed: + +```php +// Define a new script command by extending Predis\Command\ScriptCommand: +class ListPushRandomValue extends Predis\Command\ScriptCommand +{ + public function getKeysCount() + { + return 1; + } + + public function getScript() + { + return << [ + 'lpushrand' => 'ListPushRandomValue', + ], +]); + +$response = $client->lpushrand('random_values', $seed = mt_rand()); +``` + + +### Customizable connection backends ### + +Predis can use different connection backends to connect to Redis. The builtin Relay integration +leverages the [Relay](https://github.com/cachewerk/relay) extension for PHP for major performance +gains, by caching a partial replica of the Redis dataset in PHP shared runtime memory. + +```php +$client = new Predis\Client('tcp://127.0.0.1', [ + 'connections' => 'relay', +]); +``` + +Developers can create their own connection classes to support whole new network backends, extend +existing classes or provide completely different implementations. Connection classes must implement +`Predis\Connection\NodeConnectionInterface` or extend `Predis\Connection\AbstractConnection`: + +```php +class MyConnectionClass implements Predis\Connection\NodeConnectionInterface +{ + // Implementation goes here... +} + +// Use MyConnectionClass to handle connections for the `tcp` scheme: +$client = new Predis\Client('tcp://127.0.0.1', [ + 'connections' => ['tcp' => 'MyConnectionClass'], +]); +``` + +For a more in-depth insight on how to create new connection backends you can refer to the actual +implementation of the standard connection classes available in the `Predis\Connection` namespace. + + +## Development ## + + +### Reporting bugs and contributing code ### + +Contributions to Predis are highly appreciated either in the form of pull requests for new features, +bug fixes, or just bug reports. We only ask you to adhere to issue and pull request templates. + + +### Test suite ### + +__ATTENTION__: Do not ever run the test suite shipped with Predis against instances of Redis running +in production environments or containing data you are interested in! + +Predis has a comprehensive test suite covering every aspect of the library and that can optionally +perform integration tests against a running instance of Redis (required >= 2.4.0 in order to verify +the correct behavior of the implementation of each command. Integration tests for unsupported Redis +commands are automatically skipped. If you do not have Redis up and running, integration tests can +be disabled. See [the tests README](tests/README.md) for more details about testing this library. + +Predis uses GitHub Actions for continuous integration and the history for past and current builds can be +found [on its actions page](https://github.com/predis/predis/actions). + +### License ### + +The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)). + +[ico-license]: https://img.shields.io/github/license/predis/predis.svg?style=flat-square +[ico-version-stable]: https://img.shields.io/github/v/tag/predis/predis?label=stable&style=flat-square +[ico-version-dev]: https://img.shields.io/github/v/tag/predis/predis?include_prereleases&label=pre-release&style=flat-square +[ico-downloads-monthly]: https://img.shields.io/packagist/dm/predis/predis.svg?style=flat-square +[ico-build]: https://img.shields.io/github/actions/workflow/status/predis/predis/tests.yml?branch=main&style=flat-square +[ico-coverage]: https://img.shields.io/coverallsCoverage/github/predis/predis?style=flat-square + +[link-releases]: https://github.com/predis/predis/releases +[link-actions]: https://github.com/predis/predis/actions +[link-downloads]: https://packagist.org/packages/predis/predis/stats +[link-coverage]: https://coveralls.io/github/predis/predis diff --git a/.extlib/simplesamlphp/vendor/predis/predis/autoload.php b/.extlib/simplesamlphp/vendor/predis/predis/autoload.php new file mode 100644 index 000000000..5d96d680b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/autoload.php @@ -0,0 +1,12 @@ +=0.6.2)" + }, + "scripts": { + "phpstan": "phpstan analyse", + "style": "php-cs-fixer fix --diff --dry-run", + "style:fix": "php-cs-fixer fix" + }, + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "config": { + "sort-packages": true, + "preferred-install": "dist" + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Autoloader.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Autoloader.php new file mode 100644 index 000000000..5421409e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Autoloader.php @@ -0,0 +1,64 @@ + + * @author Daniele Alessandri + * @codeCoverageIgnore + */ +class Autoloader +{ + private $directory; + private $prefix; + private $prefixLength; + + /** + * @param string $baseDirectory Base directory where the source files are located. + */ + public function __construct($baseDirectory = __DIR__) + { + $this->directory = $baseDirectory; + $this->prefix = __NAMESPACE__ . '\\'; + $this->prefixLength = strlen($this->prefix); + } + + /** + * Registers the autoloader class with the PHP SPL autoloader. + * + * @param bool $prepend Prepend the autoloader on the stack instead of appending it. + */ + public static function register($prepend = false) + { + spl_autoload_register([new self(), 'autoload'], true, $prepend); + } + + /** + * Loads a class from a file using its fully qualified name. + * + * @param string $className Fully qualified name of a class. + */ + public function autoload($className) + { + if (0 === strpos($className, $this->prefix)) { + $parts = explode('\\', substr($className, $this->prefixLength)); + $filepath = $this->directory . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $parts) . '.php'; + + if (is_file($filepath)) { + require $filepath; + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Client.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Client.php new file mode 100644 index 000000000..28bb2eddc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Client.php @@ -0,0 +1,612 @@ + + */ +class Client implements ClientInterface, IteratorAggregate +{ + public const VERSION = '2.3.0'; + + /** @var OptionsInterface */ + private $options; + + /** @var ConnectionInterface */ + private $connection; + + /** @var Command\FactoryInterface */ + private $commands; + + /** + * @param mixed $parameters Connection parameters for one or more servers. + * @param mixed $options Options to configure some behaviours of the client. + */ + public function __construct($parameters = null, $options = null) + { + $this->options = static::createOptions($options ?? new Options()); + $this->connection = static::createConnection($this->options, $parameters ?? new Parameters()); + $this->commands = $this->options->commands; + } + + /** + * Creates a new set of client options for the client. + * + * @param array|OptionsInterface $options Set of client options + * + * @return OptionsInterface + * @throws InvalidArgumentException + */ + protected static function createOptions($options) + { + if (is_array($options)) { + return new Options($options); + } elseif ($options instanceof OptionsInterface) { + return $options; + } else { + throw new InvalidArgumentException('Invalid type for client options'); + } + } + + /** + * Creates single or aggregate connections from supplied arguments. + * + * This method accepts the following types to create a connection instance: + * + * - Array (dictionary: single connection, indexed: aggregate connections) + * - String (URI for a single connection) + * - Callable (connection initializer callback) + * - Instance of Predis\Connection\ParametersInterface (used as-is) + * - Instance of Predis\Connection\ConnectionInterface (returned as-is) + * + * When a callable is passed, it receives the original set of client options + * and must return an instance of Predis\Connection\ConnectionInterface. + * + * Connections are created using the connection factory (in case of single + * connections) or a specialized aggregate connection initializer (in case + * of cluster and replication) retrieved from the supplied client options. + * + * @param OptionsInterface $options Client options container + * @param mixed $parameters Connection parameters + * + * @return ConnectionInterface + * @throws InvalidArgumentException + */ + protected static function createConnection(OptionsInterface $options, $parameters) + { + if ($parameters instanceof ConnectionInterface) { + return $parameters; + } + + if ($parameters instanceof ParametersInterface || is_string($parameters)) { + return $options->connections->create($parameters); + } + + if (is_array($parameters)) { + if (!isset($parameters[0])) { + return $options->connections->create($parameters); + } elseif ($options->defined('cluster') && $initializer = $options->cluster) { + return $initializer($parameters, true); + } elseif ($options->defined('replication') && $initializer = $options->replication) { + return $initializer($parameters, true); + } elseif ($options->defined('aggregate') && $initializer = $options->aggregate) { + return $initializer($parameters, false); + } else { + throw new InvalidArgumentException( + 'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option' + ); + } + } + + if (is_callable($parameters)) { + $connection = call_user_func($parameters, $options); + + if (!$connection instanceof ConnectionInterface) { + throw new InvalidArgumentException('Callable parameters must return a valid connection'); + } + + return $connection; + } + + throw new InvalidArgumentException('Invalid type for connection parameters'); + } + + /** + * {@inheritdoc} + */ + public function getCommandFactory() + { + return $this->commands; + } + + /** + * {@inheritdoc} + */ + public function getOptions() + { + return $this->options; + } + + /** + * Creates a new client using a specific underlying connection. + * + * This method allows to create a new client instance by picking a specific + * connection out of an aggregate one, with the same options of the original + * client instance. + * + * The specified selector defines which logic to use to look for a suitable + * connection by the specified value. Supported selectors are: + * + * - `id` + * - `key` + * - `slot` + * - `command` + * - `alias` + * - `role` + * + * Internally the client relies on duck-typing and follows this convention: + * + * $selector string => getConnectionBy$selector($value) method + * + * This means that support for specific selectors may vary depending on the + * actual logic implemented by connection classes and there is no interface + * binding a connection class to implement any of these. + * + * @param string $selector Type of selector. + * @param mixed $value Value to be used by the selector. + * + * @return ClientInterface + */ + public function getClientBy($selector, $value) + { + $selector = strtolower($selector); + + if (!in_array($selector, ['id', 'key', 'slot', 'role', 'alias', 'command'])) { + throw new InvalidArgumentException("Invalid selector type: `$selector`"); + } + + if (!method_exists($this->connection, $method = "getConnectionBy$selector")) { + $class = get_class($this->connection); + throw new InvalidArgumentException("Selecting connection by $selector is not supported by $class"); + } + + if (!$connection = $this->connection->$method($value)) { + throw new InvalidArgumentException("Cannot find a connection by $selector matching `$value`"); + } + + return new static($connection, $this->getOptions()); + } + + /** + * Opens the underlying connection and connects to the server. + */ + public function connect() + { + $this->connection->connect(); + } + + /** + * Closes the underlying connection and disconnects from the server. + */ + public function disconnect() + { + $this->connection->disconnect(); + } + + /** + * Closes the underlying connection and disconnects from the server. + * + * This is the same as `Client::disconnect()` as it does not actually send + * the `QUIT` command to Redis, but simply closes the connection. + */ + public function quit() + { + $this->disconnect(); + } + + /** + * Returns the current state of the underlying connection. + * + * @return bool + */ + public function isConnected() + { + return $this->connection->isConnected(); + } + + /** + * {@inheritdoc} + */ + public function getConnection() + { + return $this->connection; + } + + /** + * Applies the configured serializer and compression to given value. + * + * @param mixed $value + * @return string + */ + public function pack($value) + { + return $this->connection instanceof RelayConnection + ? $this->connection->pack($value) + : $value; + } + + /** + * Deserializes and decompresses to given value. + * + * @param mixed $value + * @return string + */ + public function unpack($value) + { + return $this->connection instanceof RelayConnection + ? $this->connection->unpack($value) + : $value; + } + + /** + * Executes a command without filtering its arguments, parsing the response, + * applying any prefix to keys or throwing exceptions on Redis errors even + * regardless of client options. + * + * It is possible to identify Redis error responses from normal responses + * using the second optional argument which is populated by reference. + * + * @param array $arguments Command arguments as defined by the command signature. + * @param bool $error Set to TRUE when Redis returned an error response. + * + * @return mixed + */ + public function executeRaw(array $arguments, &$error = null) + { + $error = false; + $commandID = array_shift($arguments); + + $response = $this->connection->executeCommand( + new RawCommand($commandID, $arguments) + ); + + if ($response instanceof ResponseInterface) { + if ($response instanceof ErrorResponseInterface) { + $error = true; + } + + return (string) $response; + } + + return $response; + } + + /** + * {@inheritdoc} + */ + public function __call($commandID, $arguments) + { + return $this->executeCommand( + $this->createCommand($commandID, $arguments) + ); + } + + /** + * {@inheritdoc} + */ + public function createCommand($commandID, $arguments = []) + { + return $this->commands->create($commandID, $arguments); + } + + /** + * @param string $name + * @return ContainerInterface + */ + public function __get(string $name) + { + return ContainerFactory::create($this, $name); + } + + /** + * @param string $name + * @param mixed $value + * @return mixed + */ + public function __set(string $name, $value) + { + throw new RuntimeException('Not allowed'); + } + + /** + * @param string $name + * @return mixed + */ + public function __isset(string $name) + { + throw new RuntimeException('Not allowed'); + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + $response = $this->connection->executeCommand($command); + + if ($response instanceof ResponseInterface) { + if ($response instanceof ErrorResponseInterface) { + $response = $this->onErrorResponse($command, $response); + } + + return $response; + } + + return $command->parseResponse($response); + } + + /** + * Handles -ERR responses returned by Redis. + * + * @param CommandInterface $command Redis command that generated the error. + * @param ErrorResponseInterface $response Instance of the error response. + * + * @return mixed + * @throws ServerException + */ + protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response) + { + if ($command instanceof ScriptCommand && $response->getErrorType() === 'NOSCRIPT') { + $response = $this->executeCommand($command->getEvalCommand()); + + if (!$response instanceof ResponseInterface) { + $response = $command->parseResponse($response); + } + + return $response; + } + + if ($this->options->exceptions) { + throw new ServerException($response->getMessage()); + } + + return $response; + } + + /** + * Executes the specified initializer method on `$this` by adjusting the + * actual invocation depending on the arity (0, 1 or 2 arguments). This is + * simply an utility method to create Redis contexts instances since they + * follow a common initialization path. + * + * @param string $initializer Method name. + * @param array $argv Arguments for the method. + * + * @return mixed + */ + private function sharedContextFactory($initializer, $argv = null) + { + switch (count($argv)) { + case 0: + return $this->$initializer(); + + case 1: + return is_array($argv[0]) + ? $this->$initializer($argv[0]) + : $this->$initializer(null, $argv[0]); + + case 2: + [$arg0, $arg1] = $argv; + + return $this->$initializer($arg0, $arg1); + + default: + return $this->$initializer($this, $argv); + } + } + + /** + * Creates a new pipeline context and returns it, or returns the results of + * a pipeline executed inside the optionally provided callable object. + * + * @param mixed ...$arguments Array of options, a callable for execution, or both. + * + * @return Pipeline|array + */ + public function pipeline(...$arguments) + { + return $this->sharedContextFactory('createPipeline', func_get_args()); + } + + /** + * Actual pipeline context initializer method. + * + * @param array|null $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. + * + * @return Pipeline|array + */ + protected function createPipeline(?array $options = null, $callable = null) + { + if (isset($options['atomic']) && $options['atomic']) { + $class = Atomic::class; + } elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) { + $class = FireAndForget::class; + } else { + $class = Pipeline::class; + } + + if ($this->connection instanceof RelayConnection) { + if (isset($options['atomic']) && $options['atomic']) { + $class = RelayAtomic::class; + } elseif (isset($options['fire-and-forget']) && $options['fire-and-forget']) { + throw new NotSupportedException('The "relay" extension does not support fire-and-forget pipelines.'); + } else { + $class = RelayPipeline::class; + } + } + + /* + * @var ClientContextInterface + */ + $pipeline = new $class($this); + + if (isset($callable)) { + return $pipeline->execute($callable); + } + + return $pipeline; + } + + /** + * Creates a new transaction context and returns it, or returns the results + * of a transaction executed inside the optionally provided callable object. + * + * @param mixed ...$arguments Array of options, a callable for execution, or both. + * + * @return MultiExecTransaction|array + */ + public function transaction(...$arguments) + { + return $this->sharedContextFactory('createTransaction', func_get_args()); + } + + /** + * Actual transaction context initializer method. + * + * @param array|null $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. + * + * @return MultiExecTransaction|array + */ + protected function createTransaction(?array $options = null, $callable = null) + { + $transaction = new MultiExecTransaction($this, $options); + + if (isset($callable)) { + return $transaction->execute($callable); + } + + return $transaction; + } + + /** + * Creates a new publish/subscribe context and returns it, or starts its loop + * inside the optionally provided callable object. + * + * @param mixed ...$arguments Array of options, a callable for execution, or both. + * + * @return PubSubConsumer|null + */ + public function pubSubLoop(...$arguments) + { + return $this->sharedContextFactory('createPubSub', func_get_args()); + } + + /** + * Actual publish/subscribe context initializer method. + * + * @param array|null $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. + * + * @return PubSubConsumer|null + */ + protected function createPubSub(?array $options = null, $callable = null) + { + if ($this->connection instanceof RelayConnection) { + $pubsub = new RelayPubSubConsumer($this, $options); + } else { + $pubsub = new PubSubConsumer($this, $options); + } + + if (!isset($callable)) { + return $pubsub; + } + + foreach ($pubsub as $message) { + if (call_user_func($callable, $pubsub, $message) === false) { + $pubsub->stop(); + } + } + + return null; + } + + /** + * Creates a new monitor consumer and returns it. + * + * @return MonitorConsumer + */ + public function monitor() + { + return new MonitorConsumer($this); + } + + /** + * @return Traversable + */ + #[ReturnTypeWillChange] + public function getIterator() + { + $clients = []; + $connection = $this->getConnection(); + + if (!$connection instanceof Traversable) { + return new ArrayIterator([ + (string) $connection => new static($connection, $this->getOptions()), + ]); + } + + foreach ($connection as $node) { + $clients[(string) $node] = new static($node, $this->getOptions()); + } + + return new ArrayIterator($clients); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/ClientConfiguration.php b/.extlib/simplesamlphp/vendor/predis/predis/src/ClientConfiguration.php new file mode 100644 index 000000000..c36e5733b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/ClientConfiguration.php @@ -0,0 +1,42 @@ + [ + ['name' => 'Json', 'commandPrefix' => 'JSON'], + ['name' => 'BloomFilter', 'commandPrefix' => 'BF'], + ['name' => 'CuckooFilter', 'commandPrefix' => 'CF'], + ['name' => 'CountMinSketch', 'commandPrefix' => 'CMS'], + ['name' => 'TDigest', 'commandPrefix' => 'TDIGEST'], + ['name' => 'TopK', 'commandPrefix' => 'TOPK'], + ['name' => 'Search', 'commandPrefix' => 'FT'], + ['name' => 'TimeSeries', 'commandPrefix' => 'TS'], + ], + ]; + + /** + * Returns available modules with configuration. + * + * @return array|string[][] + */ + public static function getModules(): array + { + return self::$config['modules']; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/ClientContextInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/ClientContextInterface.php new file mode 100644 index 000000000..a64c08e89 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/ClientContextInterface.php @@ -0,0 +1,389 @@ +commands = $this->getDefaultCommands(); + } + + /** + * Returns the default map of supported commands with their handlers. + * + * @return array + */ + protected function getDefaultCommands() + { + $getKeyFromFirstArgument = [$this, 'getKeyFromFirstArgument']; + $getKeyFromAllArguments = [$this, 'getKeyFromAllArguments']; + + return [ + /* commands operating on the key space */ + 'EXISTS' => $getKeyFromAllArguments, + 'DEL' => $getKeyFromAllArguments, + 'TYPE' => $getKeyFromFirstArgument, + 'EXPIRE' => $getKeyFromFirstArgument, + 'EXPIREAT' => $getKeyFromFirstArgument, + 'PERSIST' => $getKeyFromFirstArgument, + 'PEXPIRE' => $getKeyFromFirstArgument, + 'PEXPIREAT' => $getKeyFromFirstArgument, + 'TTL' => $getKeyFromFirstArgument, + 'PTTL' => $getKeyFromFirstArgument, + 'SORT' => [$this, 'getKeyFromSortCommand'], + 'DUMP' => $getKeyFromFirstArgument, + 'RESTORE' => $getKeyFromFirstArgument, + 'FLUSHDB' => [$this, 'getFakeKey'], + + /* commands operating on string values */ + 'APPEND' => $getKeyFromFirstArgument, + 'DECR' => $getKeyFromFirstArgument, + 'DECRBY' => $getKeyFromFirstArgument, + 'GET' => $getKeyFromFirstArgument, + 'GETBIT' => $getKeyFromFirstArgument, + 'MGET' => $getKeyFromAllArguments, + 'SET' => $getKeyFromFirstArgument, + 'GETRANGE' => $getKeyFromFirstArgument, + 'GETSET' => $getKeyFromFirstArgument, + 'INCR' => $getKeyFromFirstArgument, + 'INCRBY' => $getKeyFromFirstArgument, + 'INCRBYFLOAT' => $getKeyFromFirstArgument, + 'SETBIT' => $getKeyFromFirstArgument, + 'SETEX' => $getKeyFromFirstArgument, + 'MSET' => [$this, 'getKeyFromInterleavedArguments'], + 'MSETNX' => [$this, 'getKeyFromInterleavedArguments'], + 'SETNX' => $getKeyFromFirstArgument, + 'SETRANGE' => $getKeyFromFirstArgument, + 'STRLEN' => $getKeyFromFirstArgument, + 'SUBSTR' => $getKeyFromFirstArgument, + 'BITOP' => [$this, 'getKeyFromBitOp'], + 'BITCOUNT' => $getKeyFromFirstArgument, + 'BITFIELD' => $getKeyFromFirstArgument, + + /* commands operating on lists */ + 'LINSERT' => $getKeyFromFirstArgument, + 'LINDEX' => $getKeyFromFirstArgument, + 'LLEN' => $getKeyFromFirstArgument, + 'LPOP' => $getKeyFromFirstArgument, + 'RPOP' => $getKeyFromFirstArgument, + 'RPOPLPUSH' => $getKeyFromAllArguments, + 'BLPOP' => [$this, 'getKeyFromBlockingListCommands'], + 'BRPOP' => [$this, 'getKeyFromBlockingListCommands'], + 'BRPOPLPUSH' => [$this, 'getKeyFromBlockingListCommands'], + 'LPUSH' => $getKeyFromFirstArgument, + 'LPUSHX' => $getKeyFromFirstArgument, + 'RPUSH' => $getKeyFromFirstArgument, + 'RPUSHX' => $getKeyFromFirstArgument, + 'LRANGE' => $getKeyFromFirstArgument, + 'LREM' => $getKeyFromFirstArgument, + 'LSET' => $getKeyFromFirstArgument, + 'LTRIM' => $getKeyFromFirstArgument, + + /* commands operating on sets */ + 'SADD' => $getKeyFromFirstArgument, + 'SCARD' => $getKeyFromFirstArgument, + 'SDIFF' => $getKeyFromAllArguments, + 'SDIFFSTORE' => $getKeyFromAllArguments, + 'SINTER' => $getKeyFromAllArguments, + 'SINTERSTORE' => $getKeyFromAllArguments, + 'SUNION' => $getKeyFromAllArguments, + 'SUNIONSTORE' => $getKeyFromAllArguments, + 'SISMEMBER' => $getKeyFromFirstArgument, + 'SMEMBERS' => $getKeyFromFirstArgument, + 'SSCAN' => $getKeyFromFirstArgument, + 'SPOP' => $getKeyFromFirstArgument, + 'SRANDMEMBER' => $getKeyFromFirstArgument, + 'SREM' => $getKeyFromFirstArgument, + + /* commands operating on sorted sets */ + 'ZADD' => $getKeyFromFirstArgument, + 'ZCARD' => $getKeyFromFirstArgument, + 'ZCOUNT' => $getKeyFromFirstArgument, + 'ZINCRBY' => $getKeyFromFirstArgument, + 'ZINTERSTORE' => [$this, 'getKeyFromZsetAggregationCommands'], + 'ZRANGE' => $getKeyFromFirstArgument, + 'ZRANGEBYSCORE' => $getKeyFromFirstArgument, + 'ZRANK' => $getKeyFromFirstArgument, + 'ZREM' => $getKeyFromFirstArgument, + 'ZREMRANGEBYRANK' => $getKeyFromFirstArgument, + 'ZREMRANGEBYSCORE' => $getKeyFromFirstArgument, + 'ZREVRANGE' => $getKeyFromFirstArgument, + 'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument, + 'ZREVRANK' => $getKeyFromFirstArgument, + 'ZSCORE' => $getKeyFromFirstArgument, + 'ZUNIONSTORE' => [$this, 'getKeyFromZsetAggregationCommands'], + 'ZSCAN' => $getKeyFromFirstArgument, + 'ZLEXCOUNT' => $getKeyFromFirstArgument, + 'ZRANGEBYLEX' => $getKeyFromFirstArgument, + 'ZREMRANGEBYLEX' => $getKeyFromFirstArgument, + 'ZREVRANGEBYLEX' => $getKeyFromFirstArgument, + + /* commands operating on hashes */ + 'HDEL' => $getKeyFromFirstArgument, + 'HEXISTS' => $getKeyFromFirstArgument, + 'HGET' => $getKeyFromFirstArgument, + 'HGETALL' => $getKeyFromFirstArgument, + 'HMGET' => $getKeyFromFirstArgument, + 'HMSET' => $getKeyFromFirstArgument, + 'HINCRBY' => $getKeyFromFirstArgument, + 'HINCRBYFLOAT' => $getKeyFromFirstArgument, + 'HKEYS' => $getKeyFromFirstArgument, + 'HLEN' => $getKeyFromFirstArgument, + 'HSET' => $getKeyFromFirstArgument, + 'HSETNX' => $getKeyFromFirstArgument, + 'HVALS' => $getKeyFromFirstArgument, + 'HSCAN' => $getKeyFromFirstArgument, + 'HSTRLEN' => $getKeyFromFirstArgument, + + /* commands operating on HyperLogLog */ + 'PFADD' => $getKeyFromFirstArgument, + 'PFCOUNT' => $getKeyFromAllArguments, + 'PFMERGE' => $getKeyFromAllArguments, + + /* scripting */ + 'EVAL' => [$this, 'getKeyFromScriptingCommands'], + 'EVALSHA' => [$this, 'getKeyFromScriptingCommands'], + + /* server */ + 'INFO' => [$this, 'getFakeKey'], + + /* commands performing geospatial operations */ + 'GEOADD' => $getKeyFromFirstArgument, + 'GEOHASH' => $getKeyFromFirstArgument, + 'GEOPOS' => $getKeyFromFirstArgument, + 'GEODIST' => $getKeyFromFirstArgument, + 'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'], + 'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'], + + /* cluster */ + 'CLUSTER' => [$this, 'getFakeKey'], + ]; + } + + /** + * Returns the list of IDs for the supported commands. + * + * @return array + */ + public function getSupportedCommands() + { + return array_keys($this->commands); + } + + /** + * Sets an handler for the specified command ID. + * + * The signature of the callback must have a single parameter of type + * Predis\Command\CommandInterface. + * + * When the callback argument is omitted or NULL, the previously associated + * handler for the specified command ID is removed. + * + * @param string $commandID Command ID. + * @param mixed $callback A valid callable object, or NULL to unset the handler. + * + * @throws InvalidArgumentException + */ + public function setCommandHandler($commandID, $callback = null) + { + $commandID = strtoupper($commandID); + + if (!isset($callback)) { + unset($this->commands[$commandID]); + + return; + } + + if (!is_callable($callback)) { + throw new InvalidArgumentException( + 'The argument must be a callable object or NULL.' + ); + } + + $this->commands[$commandID] = $callback; + } + + /** + * Get fake key for commands with no key argument. + * + * @return string + */ + protected function getFakeKey(): string + { + return 'key'; + } + + /** + * Extracts the key from the first argument of a command instance. + * + * @param CommandInterface $command Command instance. + * + * @return string + */ + protected function getKeyFromFirstArgument(CommandInterface $command) + { + return $command->getArgument(0); + } + + /** + * Extracts the key from a command with multiple keys only when all keys in + * the arguments array produce the same hash. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromAllArguments(CommandInterface $command) + { + $arguments = $command->getArguments(); + + if (!$this->checkSameSlotForKeys($arguments)) { + return null; + } + + return $arguments[0]; + } + + /** + * Extracts the key from a command with multiple keys only when all keys in + * the arguments array produce the same hash. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromInterleavedArguments(CommandInterface $command) + { + $arguments = $command->getArguments(); + $keys = []; + + for ($i = 0; $i < count($arguments); $i += 2) { + $keys[] = $arguments[$i]; + } + + if (!$this->checkSameSlotForKeys($keys)) { + return null; + } + + return $arguments[0]; + } + + /** + * Extracts the key from SORT command. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromSortCommand(CommandInterface $command) + { + $arguments = $command->getArguments(); + $firstKey = $arguments[0]; + + if (1 === $argc = count($arguments)) { + return $firstKey; + } + + $keys = [$firstKey]; + + for ($i = 1; $i < $argc; ++$i) { + if (strtoupper($arguments[$i]) === 'STORE') { + $keys[] = $arguments[++$i]; + } + } + + if (!$this->checkSameSlotForKeys($keys)) { + return null; + } + + return $firstKey; + } + + /** + * Extracts the key from BLPOP and BRPOP commands. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromBlockingListCommands(CommandInterface $command) + { + $arguments = $command->getArguments(); + + if (!$this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) { + return null; + } + + return $arguments[0]; + } + + /** + * Extracts the key from BITOP command. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromBitOp(CommandInterface $command) + { + $arguments = $command->getArguments(); + + if (!$this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) { + return null; + } + + return $arguments[1]; + } + + /** + * Extracts the key from GEORADIUS and GEORADIUSBYMEMBER commands. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromGeoradiusCommands(CommandInterface $command) + { + $arguments = $command->getArguments(); + $argc = count($arguments); + $startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4; + + if ($argc > $startIndex) { + $keys = [$arguments[0]]; + + for ($i = $startIndex; $i < $argc; ++$i) { + $argument = strtoupper($arguments[$i]); + if ($argument === 'STORE' || $argument === 'STOREDIST') { + $keys[] = $arguments[++$i]; + } + } + + if (!$this->checkSameSlotForKeys($keys)) { + return null; + } + } + + return $arguments[0]; + } + + /** + * Extracts the key from ZINTERSTORE and ZUNIONSTORE commands. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromZsetAggregationCommands(CommandInterface $command) + { + $arguments = $command->getArguments(); + $keys = array_merge([$arguments[0]], array_slice($arguments, 2, $arguments[1])); + + if (!$this->checkSameSlotForKeys($keys)) { + return null; + } + + return $arguments[0]; + } + + /** + * Extracts the key from EVAL and EVALSHA commands. + * + * @param CommandInterface $command Command instance. + * + * @return string|null + */ + protected function getKeyFromScriptingCommands(CommandInterface $command) + { + $keys = $command instanceof ScriptCommand + ? $command->getKeys() + : array_slice($args = $command->getArguments(), 2, $args[1]); + + if (!$keys || !$this->checkSameSlotForKeys($keys)) { + return null; + } + + return $keys[0]; + } + + /** + * {@inheritdoc} + */ + public function getSlot(CommandInterface $command) + { + $slot = $command->getSlot(); + + if (!isset($slot) && isset($this->commands[$cmdID = $command->getId()])) { + $key = call_user_func($this->commands[$cmdID], $command); + + if (isset($key)) { + $slot = $this->getSlotByKey($key); + $command->setSlot($slot); + } + } + + return $slot; + } + + /** + * Checks if the specified array of keys will generate the same hash. + * + * @param array $keys Array of keys. + * + * @return bool + */ + protected function checkSameSlotForKeys(array $keys) + { + if (!$count = count($keys)) { + return false; + } + + $currentSlot = $this->getSlotByKey($keys[0]); + + for ($i = 1; $i < $count; ++$i) { + $nextSlot = $this->getSlotByKey($keys[$i]); + + if ($currentSlot !== $nextSlot) { + return false; + } + + $currentSlot = $nextSlot; + } + + return true; + } + + /** + * Returns only the hashable part of a key (delimited by "{...}"), or the + * whole key if a key tag is not found in the string. + * + * @param string $key A key. + * + * @return string + */ + protected function extractKeyTag($key) + { + if (false !== $start = strpos($key, '{')) { + if (false !== ($end = strpos($key, '}', $start)) && $end !== ++$start) { + $key = substr($key, $start, $end - $start); + } + } + + return $key; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/DistributorInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/DistributorInterface.php new file mode 100644 index 000000000..162e50683 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/DistributorInterface.php @@ -0,0 +1,81 @@ + + */ +class HashRing implements DistributorInterface, HashGeneratorInterface +{ + public const DEFAULT_REPLICAS = 128; + public const DEFAULT_WEIGHT = 100; + + private $ring; + private $ringKeys; + private $ringKeysCount; + private $replicas; + private $nodeHashCallback; + private $nodes = []; + + /** + * @param int $replicas Number of replicas in the ring. + * @param mixed $nodeHashCallback Callback returning a string used to calculate the hash of nodes. + */ + public function __construct($replicas = self::DEFAULT_REPLICAS, $nodeHashCallback = null) + { + $this->replicas = $replicas; + $this->nodeHashCallback = $nodeHashCallback; + } + + /** + * Adds a node to the ring with an optional weight. + * + * @param mixed $node Node object. + * @param int $weight Weight for the node. + */ + public function add($node, $weight = null) + { + // In case of collisions in the hashes of the nodes, the node added + // last wins, thus the order in which nodes are added is significant. + $this->nodes[] = [ + 'object' => $node, + 'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT, + ]; + + $this->reset(); + } + + /** + * {@inheritdoc} + */ + public function remove($node) + { + // A node is removed by resetting the ring so that it's recreated from + // scratch, in order to reassign possible hashes with collisions to the + // right node according to the order in which they were added in the + // first place. + for ($i = 0; $i < count($this->nodes); ++$i) { + if ($this->nodes[$i]['object'] === $node) { + array_splice($this->nodes, $i, 1); + $this->reset(); + + break; + } + } + } + + /** + * Resets the distributor. + */ + private function reset() + { + unset( + $this->ring, + $this->ringKeys, + $this->ringKeysCount + ); + } + + /** + * Returns the initialization status of the distributor. + * + * @return bool + */ + private function isInitialized() + { + return isset($this->ringKeys); + } + + /** + * Calculates the total weight of all the nodes in the distributor. + * + * @return int + */ + private function computeTotalWeight() + { + $totalWeight = 0; + + foreach ($this->nodes as $node) { + $totalWeight += $node['weight']; + } + + return $totalWeight; + } + + /** + * Initializes the distributor. + */ + private function initialize() + { + if ($this->isInitialized()) { + return; + } + + if (!$this->nodes) { + throw new EmptyRingException('Cannot initialize an empty hashring.'); + } + + $this->ring = []; + $totalWeight = $this->computeTotalWeight(); + $nodesCount = count($this->nodes); + + foreach ($this->nodes as $node) { + $weightRatio = $node['weight'] / $totalWeight; + $this->addNodeToRing($this->ring, $node, $nodesCount, $this->replicas, $weightRatio); + } + + ksort($this->ring, SORT_NUMERIC); + $this->ringKeys = array_keys($this->ring); + $this->ringKeysCount = count($this->ringKeys); + } + + /** + * Implements the logic needed to add a node to the hashring. + * + * @param array $ring Source hashring. + * @param mixed $node Node object to be added. + * @param int $totalNodes Total number of nodes. + * @param int $replicas Number of replicas in the ring. + * @param float $weightRatio Weight ratio for the node. + */ + protected function addNodeToRing(&$ring, $node, $totalNodes, $replicas, $weightRatio) + { + $nodeObject = $node['object']; + $nodeHash = $this->getNodeHash($nodeObject); + $replicas = (int) round($weightRatio * $totalNodes * $replicas); + + for ($i = 0; $i < $replicas; ++$i) { + $key = $this->hash("$nodeHash:$i"); + $ring[$key] = $nodeObject; + } + } + + /** + * {@inheritdoc} + */ + protected function getNodeHash($nodeObject) + { + if (!isset($this->nodeHashCallback)) { + return (string) $nodeObject; + } + + return call_user_func($this->nodeHashCallback, $nodeObject); + } + + /** + * {@inheritdoc} + */ + public function hash($value) + { + return crc32($value); + } + + /** + * {@inheritdoc} + */ + public function getByHash($hash) + { + return $this->ring[$this->getSlot($hash)]; + } + + /** + * {@inheritdoc} + */ + public function getBySlot($slot) + { + $this->initialize(); + + if (isset($this->ring[$slot])) { + return $this->ring[$slot]; + } + } + + /** + * {@inheritdoc} + */ + public function getSlot($hash) + { + $this->initialize(); + + $ringKeys = $this->ringKeys; + $upper = $this->ringKeysCount - 1; + $lower = 0; + + while ($lower <= $upper) { + $index = ($lower + $upper) >> 1; + $item = $ringKeys[$index]; + + if ($item > $hash) { + $upper = $index - 1; + } elseif ($item < $hash) { + $lower = $index + 1; + } else { + return $item; + } + } + + return $ringKeys[$this->wrapAroundStrategy($upper, $lower, $this->ringKeysCount)]; + } + + /** + * {@inheritdoc} + */ + public function get($value) + { + $hash = $this->hash($value); + + return $this->getByHash($hash); + } + + /** + * Implements a strategy to deal with wrap-around errors during binary searches. + * + * @param int $upper + * @param int $lower + * @param int $ringKeysCount + * + * @return int + */ + protected function wrapAroundStrategy($upper, $lower, $ringKeysCount) + { + // Binary search for the last item in ringkeys with a value less or + // equal to the key. If no such item exists, return the last item. + return $upper >= 0 ? $upper : $ringKeysCount - 1; + } + + /** + * {@inheritdoc} + */ + public function getHashGenerator() + { + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/KetamaRing.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/KetamaRing.php new file mode 100644 index 000000000..cbb5c1458 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Distributor/KetamaRing.php @@ -0,0 +1,70 @@ + + */ +class KetamaRing extends HashRing +{ + public const DEFAULT_REPLICAS = 160; + + /** + * @param mixed $nodeHashCallback Callback returning a string used to calculate the hash of nodes. + */ + public function __construct($nodeHashCallback = null) + { + parent::__construct($this::DEFAULT_REPLICAS, $nodeHashCallback); + } + + /** + * {@inheritdoc} + */ + protected function addNodeToRing(&$ring, $node, $totalNodes, $replicas, $weightRatio) + { + $nodeObject = $node['object']; + $nodeHash = $this->getNodeHash($nodeObject); + $replicas = (int) floor($weightRatio * $totalNodes * ($replicas / 4)); + + for ($i = 0; $i < $replicas; ++$i) { + $unpackedDigest = unpack('V4', md5("$nodeHash-$i", true)); + + foreach ($unpackedDigest as $key) { + $ring[$key] = $nodeObject; + } + } + } + + /** + * {@inheritdoc} + */ + public function hash($value) + { + $hash = unpack('V', md5($value, true)); + + return $hash[1]; + } + + /** + * {@inheritdoc} + */ + protected function wrapAroundStrategy($upper, $lower, $ringKeysCount) + { + // Binary search for the first item in ringkeys with a value greater + // or equal to the key. If no such item exists, return the first item. + return $lower < $ringKeysCount ? $lower : 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/CRC16.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/CRC16.php new file mode 100644 index 000000000..7579f104c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/CRC16.php @@ -0,0 +1,73 @@ +> 8) ^ ord($value[$i])]) & 0xFFFF; + } + + return $crc; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/HashGeneratorInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/HashGeneratorInterface.php new file mode 100644 index 000000000..fc2db65e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/Hash/HashGeneratorInterface.php @@ -0,0 +1,29 @@ +distributor = $distributor ?: new HashRing(); + } + + /** + * {@inheritdoc} + */ + public function getSlotByKey($key) + { + $key = $this->extractKeyTag($key); + $hash = $this->distributor->hash($key); + + return $this->distributor->getSlot($hash); + } + + /** + * {@inheritdoc} + */ + protected function checkSameSlotForKeys(array $keys) + { + if (!$count = count($keys)) { + return false; + } + + $currentKey = $this->extractKeyTag($keys[0]); + + for ($i = 1; $i < $count; ++$i) { + $nextKey = $this->extractKeyTag($keys[$i]); + + if ($currentKey !== $nextKey) { + return false; + } + + $currentKey = $nextKey; + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function getDistributor() + { + return $this->distributor; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/RedisStrategy.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/RedisStrategy.php new file mode 100644 index 000000000..e222bdf0f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/RedisStrategy.php @@ -0,0 +1,55 @@ +hashGenerator = $hashGenerator ?: new CRC16(); + } + + /** + * {@inheritdoc} + */ + public function getSlotByKey($key) + { + $key = $this->extractKeyTag($key); + + return $this->hashGenerator->hash($key) & 0x3FFF; + } + + /** + * {@inheritdoc} + */ + public function getDistributor() + { + $class = get_class($this); + throw new NotSupportedException("$class does not provide an external distributor"); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/SlotMap.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/SlotMap.php new file mode 100644 index 000000000..10c8ba93a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/SlotMap.php @@ -0,0 +1,209 @@ += 0x0000 && $slot <= 0x3FFF; + } + + /** + * Checks if the given slot range is valid. + * + * @param int $first Initial slot of the range. + * @param int $last Last slot of the range. + * + * @return bool + */ + public static function isValidRange($first, $last) + { + return $first >= 0x0000 && $first <= 0x3FFF && $last >= 0x0000 && $last <= 0x3FFF && $first <= $last; + } + + /** + * Resets the slot map. + */ + public function reset() + { + $this->slots = []; + } + + /** + * Checks if the slot map is empty. + * + * @return bool + */ + public function isEmpty() + { + return empty($this->slots); + } + + /** + * Returns the current slot map as a dictionary of $slot => $node. + * + * The order of the slots in the dictionary is not guaranteed. + * + * @return array + */ + public function toArray() + { + return $this->slots; + } + + /** + * Returns the list of unique nodes in the slot map. + * + * @return array + */ + public function getNodes() + { + return array_keys(array_flip($this->slots)); + } + + /** + * Assigns the specified slot range to a node. + * + * @param int $first Initial slot of the range. + * @param int $last Last slot of the range. + * @param NodeConnectionInterface|string $connection ID or connection instance. + * + * @throws OutOfBoundsException + */ + public function setSlots($first, $last, $connection) + { + if (!static::isValidRange($first, $last)) { + throw new OutOfBoundsException("Invalid slot range $first-$last for `$connection`"); + } + + $this->slots += array_fill($first, $last - $first + 1, (string) $connection); + } + + /** + * Returns the specified slot range. + * + * @param int $first Initial slot of the range. + * @param int $last Last slot of the range. + * + * @return array + */ + public function getSlots($first, $last) + { + if (!static::isValidRange($first, $last)) { + throw new OutOfBoundsException("Invalid slot range $first-$last"); + } + + return array_intersect_key($this->slots, array_fill($first, $last - $first + 1, null)); + } + + /** + * Checks if the specified slot is assigned. + * + * @param int $slot Slot index. + * + * @return bool + */ + #[ReturnTypeWillChange] + public function offsetExists($slot) + { + return isset($this->slots[$slot]); + } + + /** + * Returns the node assigned to the specified slot. + * + * @param int $slot Slot index. + * + * @return string|null + */ + #[ReturnTypeWillChange] + public function offsetGet($slot) + { + return $this->slots[$slot] ?? null; + } + + /** + * Assigns the specified slot to a node. + * + * @param int $slot Slot index. + * @param NodeConnectionInterface|string $connection ID or connection instance. + * + * @return void + */ + #[ReturnTypeWillChange] + public function offsetSet($slot, $connection) + { + if (!static::isValid($slot)) { + throw new OutOfBoundsException("Invalid slot $slot for `$connection`"); + } + + $this->slots[(int) $slot] = (string) $connection; + } + + /** + * Returns the node assigned to the specified slot. + * + * @param int $slot Slot index. + * + * @return void + */ + #[ReturnTypeWillChange] + public function offsetUnset($slot) + { + unset($this->slots[$slot]); + } + + /** + * Returns the current number of assigned slots. + * + * @return int + */ + #[ReturnTypeWillChange] + public function count() + { + return count($this->slots); + } + + /** + * Returns an iterator over the slot map. + * + * @return Traversable + */ + #[ReturnTypeWillChange] + public function getIterator() + { + return new ArrayIterator($this->slots); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/StrategyInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/StrategyInterface.php new file mode 100644 index 000000000..e7476e191 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Cluster/StrategyInterface.php @@ -0,0 +1,52 @@ +client = $client; + $this->match = $match; + $this->count = $count; + + $this->reset(); + } + + /** + * Ensures that the client supports the specified Redis command required to + * fetch elements from the server to perform the iteration. + * + * @param ClientInterface $client Client connected to Redis. + * @param string $commandID Command ID. + * + * @throws NotSupportedException + */ + protected function requiredCommand(ClientInterface $client, $commandID) + { + if (!$client->getCommandFactory()->supports($commandID)) { + throw new NotSupportedException("'$commandID' is not supported by the current command factory."); + } + } + + /** + * Resets the inner state of the iterator. + */ + protected function reset() + { + $this->valid = true; + $this->fetchmore = true; + $this->elements = []; + $this->cursor = 0; + $this->position = -1; + $this->current = null; + } + + /** + * Returns an array of options for the `SCAN` command. + * + * @return array + */ + protected function getScanOptions() + { + $options = []; + + if (strlen(strval($this->match)) > 0) { + $options['MATCH'] = $this->match; + } + + if ($this->count > 0) { + $options['COUNT'] = $this->count; + } + + return $options; + } + + /** + * Fetches a new set of elements from the remote collection, effectively + * advancing the iteration process. + * + * @return array + */ + abstract protected function executeCommand(); + + /** + * Populates the local buffer of elements fetched from the server during + * the iteration. + */ + protected function fetch() + { + [$cursor, $elements] = $this->executeCommand(); + + if (!$cursor) { + $this->fetchmore = false; + } + + $this->cursor = $cursor; + $this->elements = $elements; + } + + /** + * Extracts next values for key() and current(). + */ + protected function extractNext() + { + ++$this->position; + $this->current = array_shift($this->elements); + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + $this->reset(); + $this->next(); + } + + /** + * @return mixed + */ + #[ReturnTypeWillChange] + public function current() + { + return $this->current; + } + + /** + * @return int|null + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->position; + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + tryFetch: + if (!$this->elements && $this->fetchmore) { + $this->fetch(); + } + + if ($this->elements) { + $this->extractNext(); + } elseif ($this->cursor) { + goto tryFetch; + } else { + $this->valid = false; + } + } + + /** + * @return bool + */ + #[ReturnTypeWillChange] + public function valid() + { + return $this->valid; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/HashKey.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/HashKey.php new file mode 100644 index 000000000..465fb7990 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/HashKey.php @@ -0,0 +1,57 @@ += 2.8) wrapped in a fully-rewindable PHP iterator. + * + * @see http://redis.io/commands/scan + */ +class HashKey extends CursorBasedIterator +{ + protected $key; + + /** + * {@inheritdoc} + */ + public function __construct(ClientInterface $client, $key, $match = null, $count = null) + { + $this->requiredCommand($client, 'HSCAN'); + + parent::__construct($client, $match, $count); + + $this->key = $key; + } + + /** + * {@inheritdoc} + */ + protected function executeCommand() + { + return $this->client->hscan($this->key, $this->cursor, $this->getScanOptions()); + } + + /** + * {@inheritdoc} + */ + protected function extractNext() + { + $this->position = key($this->elements); + $this->current = current($this->elements); + + unset($this->elements[$this->position]); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/Keyspace.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/Keyspace.php new file mode 100644 index 000000000..256b8b8e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/Keyspace.php @@ -0,0 +1,42 @@ += 2.8) wrapped in a fully-rewindable PHP iterator. + * + * @see http://redis.io/commands/scan + */ +class Keyspace extends CursorBasedIterator +{ + /** + * {@inheritdoc} + */ + public function __construct(ClientInterface $client, $match = null, $count = null) + { + $this->requiredCommand($client, 'SCAN'); + + parent::__construct($client, $match, $count); + } + + /** + * {@inheritdoc} + */ + protected function executeCommand() + { + return $this->client->scan($this->cursor, $this->getScanOptions()); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/ListKey.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/ListKey.php new file mode 100644 index 000000000..2531826ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/ListKey.php @@ -0,0 +1,183 @@ +requiredCommand($client, 'LRANGE'); + + if ((false === $count = filter_var($count, FILTER_VALIDATE_INT)) || $count < 0) { + throw new InvalidArgumentException('The $count argument must be a positive integer.'); + } + + $this->client = $client; + $this->key = $key; + $this->count = $count; + + $this->reset(); + } + + /** + * Ensures that the client instance supports the specified Redis command + * required to fetch elements from the server to perform the iteration. + * + * @param ClientInterface $client Client connected to Redis. + * @param string $commandID Command ID. + * + * @throws NotSupportedException + */ + protected function requiredCommand(ClientInterface $client, $commandID) + { + if (!$client->getCommandFactory()->supports($commandID)) { + throw new NotSupportedException("'$commandID' is not supported by the current command factory."); + } + } + + /** + * Resets the inner state of the iterator. + */ + protected function reset() + { + $this->valid = true; + $this->fetchmore = true; + $this->elements = []; + $this->position = -1; + $this->current = null; + } + + /** + * Fetches a new set of elements from the remote collection, effectively + * advancing the iteration process. + * + * @return array + */ + protected function executeCommand() + { + return $this->client->lrange($this->key, $this->position + 1, $this->position + $this->count); + } + + /** + * Populates the local buffer of elements fetched from the server during the + * iteration. + */ + protected function fetch() + { + $elements = $this->executeCommand(); + + if (count($elements) < $this->count) { + $this->fetchmore = false; + } + + $this->elements = $elements; + } + + /** + * Extracts next values for key() and current(). + */ + protected function extractNext() + { + ++$this->position; + $this->current = array_shift($this->elements); + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + $this->reset(); + $this->next(); + } + + /** + * @return mixed + */ + #[ReturnTypeWillChange] + public function current() + { + return $this->current; + } + + /** + * @return int|null + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->position; + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + if (!$this->elements && $this->fetchmore) { + $this->fetch(); + } + + if ($this->elements) { + $this->extractNext(); + } else { + $this->valid = false; + } + } + + /** + * @return bool + */ + #[ReturnTypeWillChange] + public function valid() + { + return $this->valid; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SetKey.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SetKey.php new file mode 100644 index 000000000..e7821457a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SetKey.php @@ -0,0 +1,46 @@ += 2.8) wrapped in a fully-rewindable PHP iterator. + * + * @see http://redis.io/commands/scan + */ +class SetKey extends CursorBasedIterator +{ + protected $key; + + /** + * {@inheritdoc} + */ + public function __construct(ClientInterface $client, $key, $match = null, $count = null) + { + $this->requiredCommand($client, 'SSCAN'); + + parent::__construct($client, $match, $count); + + $this->key = $key; + } + + /** + * {@inheritdoc} + */ + protected function executeCommand() + { + return $this->client->sscan($this->key, $this->cursor, $this->getScanOptions()); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SortedSetKey.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SortedSetKey.php new file mode 100644 index 000000000..49decef81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Collection/Iterator/SortedSetKey.php @@ -0,0 +1,57 @@ += 2.8) wrapped in a fully-rewindable PHP iterator. + * + * @see http://redis.io/commands/scan + */ +class SortedSetKey extends CursorBasedIterator +{ + protected $key; + + /** + * {@inheritdoc} + */ + public function __construct(ClientInterface $client, $key, $match = null, $count = null) + { + $this->requiredCommand($client, 'ZSCAN'); + + parent::__construct($client, $match, $count); + + $this->key = $key; + } + + /** + * {@inheritdoc} + */ + protected function executeCommand() + { + return $this->client->zscan($this->key, $this->cursor, $this->getScanOptions()); + } + + /** + * {@inheritdoc} + */ + protected function extractNext() + { + $this->position = key($this->elements); + $this->current = current($this->elements); + + unset($this->elements[$this->position]); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/ArrayableArgument.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/ArrayableArgument.php new file mode 100644 index 000000000..061c4003f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/ArrayableArgument.php @@ -0,0 +1,26 @@ +unit = $unit; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByBox.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByBox.php new file mode 100644 index 000000000..ddc9281ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByBox.php @@ -0,0 +1,43 @@ +width = $width; + $this->height = $height; + $this->setUnit($unit); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [self::KEYWORD, $this->width, $this->height, $this->unit]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByInterface.php new file mode 100644 index 000000000..f947da269 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/ByInterface.php @@ -0,0 +1,19 @@ +radius = $radius; + $this->setUnit($unit); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [self::KEYWORD, $this->radius, $this->unit]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromInterface.php new file mode 100644 index 000000000..0a1d73f76 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromInterface.php @@ -0,0 +1,19 @@ +longitude = $longitude; + $this->latitude = $latitude; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [self::KEYWORD, $this->longitude, $this->latitude]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromMember.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromMember.php new file mode 100644 index 000000000..da0587aec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Geospatial/FromMember.php @@ -0,0 +1,36 @@ +member = $member; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [self::KEYWORD, $this->member]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AggregateArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AggregateArguments.php new file mode 100644 index 000000000..38f78fc72 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AggregateArguments.php @@ -0,0 +1,161 @@ + 'ASC', + 'desc' => 'DESC', + ]; + + /** + * Loads document attributes from the source document. + * + * @param string ...$fields Could be just '*' to load all fields + * @return $this + */ + public function load(string ...$fields): self + { + $arguments = func_get_args(); + + $this->arguments[] = 'LOAD'; + + if ($arguments[0] === '*') { + $this->arguments[] = '*'; + + return $this; + } + + $this->arguments[] = count($arguments); + $this->arguments = array_merge($this->arguments, $arguments); + + return $this; + } + + /** + * Loads document attributes from the source document. + * + * @param string ...$properties + * @return $this + */ + public function groupBy(string ...$properties): self + { + $arguments = func_get_args(); + + array_push($this->arguments, 'GROUPBY', count($arguments)); + $this->arguments = array_merge($this->arguments, $arguments); + + return $this; + } + + /** + * Groups the results in the pipeline based on one or more properties. + * + * If you want to add alias property to your argument just add "true" value in arguments enumeration, + * next value will be considered as alias to previous one. + * + * Example: 'argument', true, 'name' => 'argument' AS 'name' + * + * @param string $function + * @param string|bool ...$argument + * @return $this + */ + public function reduce(string $function, ...$argument): self + { + $arguments = func_get_args(); + $functionValue = array_shift($arguments); + $argumentsCounter = 0; + + for ($i = 0, $iMax = count($arguments); $i < $iMax; $i++) { + if (true === $arguments[$i]) { + $arguments[$i] = 'AS'; + $i++; + continue; + } + + $argumentsCounter++; + } + + array_push($this->arguments, 'REDUCE', $functionValue); + $this->arguments = array_merge($this->arguments, [$argumentsCounter], $arguments); + + return $this; + } + + /** + * Sorts the pipeline up until the point of SORTBY, using a list of properties. + * + * @param int $max + * @param string ...$properties Enumeration of properties, including sorting direction (ASC, DESC) + * @return $this + */ + public function sortBy(int $max = 0, ...$properties): self + { + $arguments = func_get_args(); + $maxValue = array_shift($arguments); + + $this->arguments[] = 'SORTBY'; + $this->arguments = array_merge($this->arguments, [count($arguments)], $arguments); + + if ($maxValue !== 0) { + array_push($this->arguments, 'MAX', $maxValue); + } + + return $this; + } + + /** + * Applies a 1-to-1 transformation on one or more properties and either stores the result + * as a new property down the pipeline or replaces any property using this transformation. + * + * @param string $expression + * @param string $as + * @return $this + */ + public function apply(string $expression, string $as = ''): self + { + array_push($this->arguments, 'APPLY', $expression); + + if ($as !== '') { + array_push($this->arguments, 'AS', $as); + } + + return $this; + } + + /** + * Scan part of the results with a quicker alternative than LIMIT. + * + * @param int $readSize + * @param int $idleTime + * @return $this + */ + public function withCursor(int $readSize = 0, int $idleTime = 0): self + { + $this->arguments[] = 'WITHCURSOR'; + + if ($readSize !== 0) { + array_push($this->arguments, 'COUNT', $readSize); + } + + if ($idleTime !== 0) { + array_push($this->arguments, 'MAXIDLE', $idleTime); + } + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AlterArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AlterArguments.php new file mode 100644 index 000000000..79359ac9e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/AlterArguments.php @@ -0,0 +1,17 @@ +arguments[] = 'LANGUAGE'; + $this->arguments[] = $defaultLanguage; + + return $this; + } + + /** + * Selects the dialect version under which to execute the query. + * If not specified, the query will execute under the default dialect version + * set during module initial loading or via FT.CONFIG SET command. + * + * @param string $dialect + * @return $this + */ + public function dialect(string $dialect): self + { + $this->arguments[] = 'DIALECT'; + $this->arguments[] = $dialect; + + return $this; + } + + /** + * If set, does not scan and index. + * + * @return $this + */ + public function skipInitialScan(): self + { + $this->arguments[] = 'SKIPINITIALSCAN'; + + return $this; + } + + /** + * Adds an arbitrary, binary safe payload that is exposed to custom scoring functions. + * + * @param string $payload + * @return $this + */ + public function payload(string $payload): self + { + $this->arguments[] = 'PAYLOAD'; + $this->arguments[] = $payload; + + return $this; + } + + /** + * Also returns the relative internal score of each document. + * + * @return $this + */ + public function withScores(): self + { + $this->arguments[] = 'WITHSCORES'; + + return $this; + } + + /** + * Retrieves optional document payloads. + * + * @return $this + */ + public function withPayloads(): self + { + $this->arguments[] = 'WITHPAYLOADS'; + + return $this; + } + + /** + * Does not try to use stemming for query expansion but searches the query terms verbatim. + * + * @return $this + */ + public function verbatim(): self + { + $this->arguments[] = 'VERBATIM'; + + return $this; + } + + /** + * Overrides the timeout parameter of the module. + * + * @param int $timeout + * @return $this + */ + public function timeout(int $timeout): self + { + $this->arguments[] = 'TIMEOUT'; + $this->arguments[] = $timeout; + + return $this; + } + + /** + * Adds an arbitrary, binary safe payload that is exposed to custom scoring functions. + * + * @param int $offset + * @param int $num + * @return $this + */ + public function limit(int $offset, int $num): self + { + array_push($this->arguments, 'LIMIT', $offset, $num); + + return $this; + } + + /** + * Adds filter expression into index. + * + * @param string $filter + * @return $this + */ + public function filter(string $filter): self + { + $this->arguments[] = 'FILTER'; + $this->arguments[] = $filter; + + return $this; + } + + /** + * Defines one or more value parameters. Each parameter has a name and a value. + * + * Example: ['name1', 'value1', 'name2', 'value2'...] + * + * @param array $nameValuesDictionary + * @return $this + */ + public function params(array $nameValuesDictionary): self + { + $this->arguments[] = 'PARAMS'; + $this->arguments[] = count($nameValuesDictionary); + $this->arguments = array_merge($this->arguments, $nameValuesDictionary); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CreateArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CreateArguments.php new file mode 100644 index 000000000..b5a41f51d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CreateArguments.php @@ -0,0 +1,191 @@ + 'HASH', + 'json' => 'JSON', + ]; + + /** + * Specify data type for given index. To index JSON you must have the RedisJSON module to be installed. + * + * @param string $modifier + * @return $this + */ + public function on(string $modifier = 'HASH'): self + { + if (in_array(strtoupper($modifier), $this->supportedDataTypesEnum)) { + $this->arguments[] = 'ON'; + $this->arguments[] = $this->supportedDataTypesEnum[strtolower($modifier)]; + + return $this; + } + + $enumValues = implode(', ', array_values($this->supportedDataTypesEnum)); + throw new InvalidArgumentException("Wrong modifier value given. Currently supports: {$enumValues}"); + } + + /** + * Adds one or more prefixes into index. + * + * @param array $prefixes + * @return $this + */ + public function prefix(array $prefixes): self + { + $this->arguments[] = 'PREFIX'; + $this->arguments[] = count($prefixes); + $this->arguments = array_merge($this->arguments, $prefixes); + + return $this; + } + + /** + * Document attribute set as document language. + * + * @param string $languageAttribute + * @return $this + */ + public function languageField(string $languageAttribute): self + { + $this->arguments[] = 'LANGUAGE_FIELD'; + $this->arguments[] = $languageAttribute; + + return $this; + } + + /** + * Default score for documents in the index. + * + * @param float $defaultScore + * @return $this + */ + public function score(float $defaultScore = 1.0): self + { + $this->arguments[] = 'SCORE'; + $this->arguments[] = $defaultScore; + + return $this; + } + + /** + * Document attribute that used as the document rank based on the user ranking. + * + * @param string $scoreAttribute + * @return $this + */ + public function scoreField(string $scoreAttribute): self + { + $this->arguments[] = 'SCORE_FIELD'; + $this->arguments[] = $scoreAttribute; + + return $this; + } + + /** + * Forces RediSearch to encode indexes as if there were more than 32 text attributes. + * + * @return $this + */ + public function maxTextFields(): self + { + $this->arguments[] = 'MAXTEXTFIELDS'; + + return $this; + } + + /** + * Does not store term offsets for documents. + * + * @return $this + */ + public function noOffsets(): self + { + $this->arguments[] = 'NOOFFSETS'; + + return $this; + } + + /** + * Creates a lightweight temporary index that expires after a specified period of inactivity, in seconds. + * + * @param int $seconds + * @return $this + */ + public function temporary(int $seconds): self + { + $this->arguments[] = 'TEMPORARY'; + $this->arguments[] = $seconds; + + return $this; + } + + /** + * Conserves storage space and memory by disabling highlighting support. + * + * @return $this + */ + public function noHl(): self + { + $this->arguments[] = 'NOHL'; + + return $this; + } + + /** + * Does not store attribute bits for each term. + * + * @return $this + */ + public function noFields(): self + { + $this->arguments[] = 'NOFIELDS'; + + return $this; + } + + /** + * Avoids saving the term frequencies in the index. + * + * @return $this + */ + public function noFreqs(): self + { + $this->arguments[] = 'NOFREQS'; + + return $this; + } + + /** + * Sets the index with a custom stopword list, to be ignored during indexing and search time. + * + * @param array $stopWords + * @return $this + */ + public function stopWords(array $stopWords): self + { + $this->arguments[] = 'STOPWORDS'; + $this->arguments[] = count($stopWords); + $this->arguments = array_merge($this->arguments, $stopWords); + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CursorArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CursorArguments.php new file mode 100644 index 000000000..055013c8b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/CursorArguments.php @@ -0,0 +1,44 @@ +arguments, 'COUNT', $readSize); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/DropArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/DropArguments.php new file mode 100644 index 000000000..59e6614c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/DropArguments.php @@ -0,0 +1,43 @@ +arguments[] = 'DD'; + + return $this; + } + + /** + * @return array + */ + public function toArray(): array + { + return $this->arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/ExplainArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/ExplainArguments.php new file mode 100644 index 000000000..0311448db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/ExplainArguments.php @@ -0,0 +1,17 @@ +arguments[] = 'SEARCH'; + + return $this; + } + + /** + * Adds aggregate context. + * + * @return $this + */ + public function aggregate(): self + { + $this->arguments[] = 'AGGREGATE'; + + return $this; + } + + /** + * Removes details of reader iterator. + * + * @return $this + */ + public function limited(): self + { + $this->arguments[] = 'LIMITED'; + + return $this; + } + + /** + * Is query string, as if sent to FT.SEARCH. + * + * @param string $query + * @return $this + */ + public function query(string $query): self + { + $this->arguments[] = 'QUERY'; + $this->arguments[] = $query; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/AbstractField.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/AbstractField.php new file mode 100644 index 000000000..b5b1c4ba6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/AbstractField.php @@ -0,0 +1,75 @@ +fieldArguments[] = $identifier; + + if ($alias !== '') { + $this->fieldArguments[] = 'AS'; + $this->fieldArguments[] = $alias; + } + + $this->fieldArguments[] = $fieldType; + + if ($sortable === self::SORTABLE) { + $this->fieldArguments[] = 'SORTABLE'; + } elseif ($sortable === self::SORTABLE_UNF) { + $this->fieldArguments[] = 'SORTABLE'; + $this->fieldArguments[] = 'UNF'; + } + + if ($noIndex) { + $this->fieldArguments[] = 'NOINDEX'; + } + + if ($allowsMissing) { + $this->fieldArguments[] = 'INDEXMISSING'; + } + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->fieldArguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/FieldInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/FieldInterface.php new file mode 100644 index 000000000..0d12d0946 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/FieldInterface.php @@ -0,0 +1,22 @@ +setCommonOptions('GEO', $identifier, $alias, $sortable, $noIndex, $allowsMissing); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/GeoShapeField.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/GeoShapeField.php new file mode 100644 index 000000000..cac5714c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/GeoShapeField.php @@ -0,0 +1,57 @@ +fieldArguments[] = $identifier; + + if ($alias !== '') { + $this->fieldArguments[] = 'AS'; + $this->fieldArguments[] = $alias; + } + + $this->fieldArguments[] = 'GEOSHAPE'; + + if (null !== $coordSystem) { + $this->fieldArguments[] = $coordSystem; + } + + if ($sortable === self::SORTABLE) { + $this->fieldArguments[] = 'SORTABLE'; + } elseif ($sortable === self::SORTABLE_UNF) { + $this->fieldArguments[] = 'SORTABLE'; + $this->fieldArguments[] = 'UNF'; + } + + if ($noIndex) { + $this->fieldArguments[] = 'NOINDEX'; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/NumericField.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/NumericField.php new file mode 100644 index 000000000..2aba8c028 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/NumericField.php @@ -0,0 +1,33 @@ +setCommonOptions('NUMERIC', $identifier, $alias, $sortable, $noIndex, $allowsMissing); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TagField.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TagField.php new file mode 100644 index 000000000..b2b86c088 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TagField.php @@ -0,0 +1,51 @@ +setCommonOptions('TAG', $identifier, $alias, $sortable, $noIndex, $allowsMissing); + + if ($separator !== ',') { + $this->fieldArguments[] = 'SEPARATOR'; + $this->fieldArguments[] = $separator; + } + + if ($caseSensitive) { + $this->fieldArguments[] = 'CASESENSITIVE'; + } + + if ($allowsEmpty) { + $this->fieldArguments[] = 'INDEXEMPTY'; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TextField.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TextField.php new file mode 100644 index 000000000..f3213a9d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/TextField.php @@ -0,0 +1,65 @@ +setCommonOptions('TEXT', $identifier, $alias, $sortable, $noIndex, $allowsMissing); + + if ($noStem) { + $this->fieldArguments[] = 'NOSTEM'; + } + + if ($phonetic !== '') { + $this->fieldArguments[] = 'PHONETIC'; + $this->fieldArguments[] = $phonetic; + } + + if ($weight !== 1) { + $this->fieldArguments[] = 'WEIGHT'; + $this->fieldArguments[] = $weight; + } + + if ($withSuffixTrie) { + $this->fieldArguments[] = 'WITHSUFFIXTRIE'; + } + + if ($allowsEmpty) { + $this->fieldArguments[] = 'INDEXEMPTY'; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/VectorField.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/VectorField.php new file mode 100644 index 000000000..979a8de19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SchemaFields/VectorField.php @@ -0,0 +1,47 @@ +setCommonOptions('VECTOR', $fieldName, $alias); + + array_push($this->fieldArguments, $algorithm, count($attributeNameValueDictionary)); + $this->fieldArguments = array_merge($this->fieldArguments, $attributeNameValueDictionary); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->fieldArguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SearchArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SearchArguments.php new file mode 100644 index 000000000..8d8cdafb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SearchArguments.php @@ -0,0 +1,306 @@ + 'ASC', + 'desc' => 'DESC', + ]; + + /** + * Returns the document ids and not the content. + * + * @return $this + */ + public function noContent(): self + { + $this->arguments[] = 'NOCONTENT'; + + return $this; + } + + /** + * Returns the value of the sorting key, right after the id and score and/or payload, if requested. + * + * @return $this + */ + public function withSortKeys(): self + { + $this->arguments[] = 'WITHSORTKEYS'; + + return $this; + } + + /** + * Limits results to those having numeric values ranging between min and max, + * if numeric_attribute is defined as a numeric attribute in FT.CREATE. + * Min and max follow ZRANGE syntax, and can be -inf, +inf, and use( for exclusive ranges. + * Multiple numeric filters for different attributes are supported in one query. + * + * @param array ...$filter Should contain: numeric_field, min and max. Example: ['numeric_field', 1, 10] + * @return $this + */ + public function searchFilter(array ...$filter): self + { + $arguments = func_get_args(); + + foreach ($arguments as $argument) { + array_push($this->arguments, 'FILTER', ...$argument); + } + + return $this; + } + + /** + * Filter the results to a given radius from lon and lat. Radius is given as a number and units. + * + * @param array ...$filter Should contain: geo_field, lon, lat, radius, unit. Example: ['geo_field', 34.1231, 35.1231, 300, km] + * @return $this + */ + public function geoFilter(array ...$filter): self + { + $arguments = func_get_args(); + + foreach ($arguments as $argument) { + array_push($this->arguments, 'GEOFILTER', ...$argument); + } + + return $this; + } + + /** + * Limits the result to a given set of keys specified in the list. + * + * @param array $keys + * @return $this + */ + public function inKeys(array $keys): self + { + $this->arguments[] = 'INKEYS'; + $this->arguments[] = count($keys); + $this->arguments = array_merge($this->arguments, $keys); + + return $this; + } + + /** + * Filters the results to those appearing only in specific attributes of the document, like title or URL. + * + * @param array $fields + * @return $this + */ + public function inFields(array $fields): self + { + $this->arguments[] = 'INFIELDS'; + $this->arguments[] = count($fields); + $this->arguments = array_merge($this->arguments, $fields); + + return $this; + } + + /** + * Limits the attributes returned from the document. + * Num is the number of attributes following the keyword. + * If num is 0, it acts like NOCONTENT. + * Identifier is either an attribute name (for hashes and JSON) or a JSON Path expression (for JSON). + * Property is an optional name used in the result. If not provided, the identifier is used in the result. + * + * If you want to add alias property to your identifier just add "true" value in identifier enumeration, + * next value will be considered as alias to previous one. + * + * Example: 'identifier', true, 'property' => 'identifier' AS 'property' + * + * @param int $count + * @param string|bool ...$identifier + * @return $this + */ + public function addReturn(int $count, ...$identifier): self + { + $arguments = func_get_args(); + + $this->arguments[] = 'RETURN'; + + for ($i = 1, $iMax = count($arguments); $i < $iMax; $i++) { + if (true === $arguments[$i]) { + $arguments[$i] = 'AS'; + } + } + + $this->arguments = array_merge($this->arguments, $arguments); + + return $this; + } + + /** + * Returns only the sections of the attribute that contain the matched text. + * + * @param array $fields + * @param int $frags + * @param int $len + * @param string $separator + * @return $this + */ + public function summarize(array $fields = [], int $frags = 0, int $len = 0, string $separator = ''): self + { + $this->arguments[] = 'SUMMARIZE'; + + if (!empty($fields)) { + $this->arguments[] = 'FIELDS'; + $this->arguments[] = count($fields); + $this->arguments = array_merge($this->arguments, $fields); + } + + if ($frags !== 0) { + $this->arguments[] = 'FRAGS'; + $this->arguments[] = $frags; + } + + if ($len !== 0) { + $this->arguments[] = 'LEN'; + $this->arguments[] = $len; + } + + if ($separator !== '') { + $this->arguments[] = 'SEPARATOR'; + $this->arguments[] = $separator; + } + + return $this; + } + + /** + * Formats occurrences of matched text. + * + * @param array $fields + * @param string $openTag + * @param string $closeTag + * @return $this + */ + public function highlight(array $fields = [], string $openTag = '', string $closeTag = ''): self + { + $this->arguments[] = 'HIGHLIGHT'; + + if (!empty($fields)) { + $this->arguments[] = 'FIELDS'; + $this->arguments[] = count($fields); + $this->arguments = array_merge($this->arguments, $fields); + } + + if ($openTag !== '' && $closeTag !== '') { + array_push($this->arguments, 'TAGS', $openTag, $closeTag); + } + + return $this; + } + + /** + * Allows a maximum of N intervening number of unmatched offsets between phrase terms. + * In other words, the slop for exact phrases is 0. + * + * @param int $slop + * @return $this + */ + public function slop(int $slop): self + { + $this->arguments[] = 'SLOP'; + $this->arguments[] = $slop; + + return $this; + } + + /** + * Puts the query terms in the same order in the document as in the query, regardless of the offsets between them. + * Typically used in conjunction with SLOP. + * + * @return $this + */ + public function inOrder(): self + { + $this->arguments[] = 'INORDER'; + + return $this; + } + + /** + * Uses a custom query expander instead of the stemmer. + * + * @param string $expander + * @return $this + */ + public function expander(string $expander): self + { + $this->arguments[] = 'EXPANDER'; + $this->arguments[] = $expander; + + return $this; + } + + /** + * Uses a custom scoring function you define. + * + * @param string $scorer + * @return $this + */ + public function scorer(string $scorer): self + { + $this->arguments[] = 'SCORER'; + $this->arguments[] = $scorer; + + return $this; + } + + /** + * Returns a textual description of how the scores were calculated. + * Using this options requires the WITHSCORES option. + * + * @return $this + */ + public function explainScore(): self + { + $this->arguments[] = 'EXPLAINSCORE'; + + return $this; + } + + /** + * Orders the results by the value of this attribute. + * This applies to both text and numeric attributes. + * Attributes needed for SORTBY should be declared as SORTABLE in the index, in order to be available with very low latency. + * Note that this adds memory overhead. + * + * @param string $sortAttribute + * @param string $orderBy + * @return $this + */ + public function sortBy(string $sortAttribute, string $orderBy = 'asc'): self + { + $this->arguments[] = 'SORTBY'; + $this->arguments[] = $sortAttribute; + + if (in_array(strtoupper($orderBy), $this->sortingEnum)) { + $this->arguments[] = $this->sortingEnum[strtolower($orderBy)]; + } else { + $enumValues = implode(', ', array_values($this->sortingEnum)); + throw new InvalidArgumentException("Wrong order direction value given. Currently supports: {$enumValues}"); + } + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SpellcheckArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SpellcheckArguments.php new file mode 100644 index 000000000..5b7c6e696 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SpellcheckArguments.php @@ -0,0 +1,59 @@ + 'INCLUDE', + 'exclude' => 'EXCLUDE', + ]; + + /** + * Is maximum Levenshtein distance for spelling suggestions (default: 1, max: 4). + * + * @return $this + */ + public function distance(int $distance): self + { + $this->arguments[] = 'DISTANCE'; + $this->arguments[] = $distance; + + return $this; + } + + /** + * Specifies an inclusion (INCLUDE) or exclusion (EXCLUDE) of a custom dictionary named {dict}. + * + * @param string $dictionary + * @param string $modifier + * @param string ...$terms + * @return $this + */ + public function terms(string $dictionary, string $modifier = 'INCLUDE', string ...$terms): self + { + if (!in_array(strtoupper($modifier), $this->termsEnum)) { + $enumValues = implode(', ', array_values($this->termsEnum)); + throw new InvalidArgumentException("Wrong modifier value given. Currently supports: {$enumValues}"); + } + + array_push($this->arguments, 'TERMS', $this->termsEnum[strtolower($modifier)], $dictionary, ...$terms); + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugAddArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugAddArguments.php new file mode 100644 index 000000000..c0fdb99ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugAddArguments.php @@ -0,0 +1,28 @@ +arguments[] = 'INCR'; + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugGetArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugGetArguments.php new file mode 100644 index 000000000..99a062b87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SugGetArguments.php @@ -0,0 +1,41 @@ +arguments[] = 'FUZZY'; + + return $this; + } + + /** + * Limits the results to a maximum of num (default: 5). + * + * @param int $num + * @return $this + */ + public function max(int $num): self + { + array_push($this->arguments, 'MAX', $num); + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SynUpdateArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SynUpdateArguments.php new file mode 100644 index 000000000..0b8af7671 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Search/SynUpdateArguments.php @@ -0,0 +1,17 @@ +offset = $offset; + $this->count = $count; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [self::KEYWORD, $this->offset, $this->count]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Server/To.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Server/To.php new file mode 100644 index 000000000..b8c4c4705 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/Server/To.php @@ -0,0 +1,57 @@ +host = $host; + $this->port = $port; + $this->isForce = $isForce; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + $arguments = [self::KEYWORD, $this->host, $this->port]; + + if ($this->isForce) { + $arguments[] = self::FORCE_KEYWORD; + } + + return $arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AddArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AddArguments.php new file mode 100644 index 000000000..df4946d1e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AddArguments.php @@ -0,0 +1,30 @@ +arguments, 'ON_DUPLICATE', $policy); + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AlterArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AlterArguments.php new file mode 100644 index 000000000..9106c4a54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/AlterArguments.php @@ -0,0 +1,17 @@ +arguments, 'RETENTION', $retentionPeriod); + + return $this; + } + + /** + * Ignore samples with given time or value difference. + * + * @param int $maxTimeDiff Non-negative integer value in milliseconds + * @param float $maxValDiff Non-negative float value + * @return $this + */ + public function ignore(int $maxTimeDiff, float $maxValDiff): self + { + if ($maxTimeDiff < 0 || $maxValDiff < 0) { + throw new UnexpectedValueException('Ignore does not accept negative values'); + } + + array_push($this->arguments, 'IGNORE', $maxTimeDiff, $maxValDiff); + + return $this; + } + + /** + * Is initial allocation size, in bytes, for the data part of each new chunk. + * + * @param int $size + * @return $this + */ + public function chunkSize(int $size): self + { + array_push($this->arguments, 'CHUNK_SIZE', $size); + + return $this; + } + + /** + * Is policy for handling insertion of multiple samples with identical timestamps. + * + * @param string $policy + * @return $this + */ + public function duplicatePolicy(string $policy = self::POLICY_BLOCK): self + { + array_push($this->arguments, 'DUPLICATE_POLICY', $policy); + + return $this; + } + + /** + * Is set of label-value pairs that represent metadata labels of the key and serve as a secondary index. + * + * @param mixed ...$labelValuePair + * @return $this + */ + public function labels(...$labelValuePair): self + { + array_push($this->arguments, 'LABELS', ...$labelValuePair); + + return $this; + } + + /** + * Specifies the series samples encoding format. + * + * @param string $encoding + * @return $this + */ + public function encoding(string $encoding = self::ENCODING_COMPRESSED): self + { + array_push($this->arguments, 'ENCODING', $encoding); + + return $this; + } + + /** + * Is used when a time series is a compaction. + * With LATEST, TS.GET reports the compacted value of the latest, possibly partial, bucket. + * + * @return $this + */ + public function latest(): self + { + $this->arguments[] = 'LATEST'; + + return $this; + } + + /** + * Includes in the reply all label-value pairs representing metadata labels of the time series. + * + * @return $this + */ + public function withLabels(): self + { + $this->arguments[] = 'WITHLABELS'; + + return $this; + } + + /** + * Returns a subset of the label-value pairs that represent metadata labels of the time series. + * + * @return $this + */ + public function selectedLabels(string ...$labels): self + { + array_push($this->arguments, 'SELECTED_LABELS', ...$labels); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/CreateArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/CreateArguments.php new file mode 100644 index 000000000..b2ae5cc87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/CreateArguments.php @@ -0,0 +1,17 @@ +arguments, 'TIMESTAMP', $timeStamp); + + return $this; + } + + /** + * Changes data storage from compressed (default) to uncompressed. + * + * @return $this + */ + public function uncompressed(): self + { + $this->arguments[] = 'UNCOMPRESSED'; + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/InfoArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/InfoArguments.php new file mode 100644 index 000000000..86c4bd80f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/InfoArguments.php @@ -0,0 +1,43 @@ +arguments[] = 'DEBUG'; + + return $this; + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return $this->arguments; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/MGetArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/MGetArguments.php new file mode 100644 index 000000000..d2b0dfcdd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/MGetArguments.php @@ -0,0 +1,17 @@ +arguments, 'FILTER', ...$filterExpressions); + + return $this; + } + + /** + * Splits time series into groups, each group contains time series that share the same + * value for the provided label name, then aggregates results in each group. + * + * @param string $label + * @param string $reducer + * @return $this + */ + public function groupBy(string $label, string $reducer): self + { + array_push($this->arguments, 'GROUPBY', $label, 'REDUCE', $reducer); + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/RangeArguments.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/RangeArguments.php new file mode 100644 index 000000000..87f880808 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Argument/TimeSeries/RangeArguments.php @@ -0,0 +1,85 @@ +arguments, 'FILTER_BY_TS', ...$ts); + + return $this; + } + + /** + * Filters samples by minimum and maximum values. + * + * @param int $min + * @param int $max + * @return $this + */ + public function filterByValue(int $min, int $max): self + { + array_push($this->arguments, 'FILTER_BY_VALUE', $min, $max); + + return $this; + } + + /** + * Limits the number of returned samples. + * + * @param int $count + * @return $this + */ + public function count(int $count): self + { + array_push($this->arguments, 'COUNT', $count); + + return $this; + } + + /** + * Aggregates samples into time buckets. + * + * @param string $aggregator + * @param int $bucketDuration Is duration of each bucket, in milliseconds. + * @param int $align It controls the time bucket timestamps by changing the reference timestamp on which a bucket is defined. + * @param int $bucketTimestamp Controls how bucket timestamps are reported. + * @param bool $empty Is a flag, which, when specified, reports aggregations also for empty buckets. + * @return $this + */ + public function aggregation(string $aggregator, int $bucketDuration, int $align = 0, int $bucketTimestamp = 0, bool $empty = false): self + { + if ($align > 0) { + array_push($this->arguments, 'ALIGN', $align); + } + + array_push($this->arguments, 'AGGREGATION', $aggregator, $bucketDuration); + + if ($bucketTimestamp > 0) { + array_push($this->arguments, 'BUCKETTIMESTAMP', $bucketTimestamp); + } + + if (true === $empty) { + $this->arguments[] = 'EMPTY'; + } + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Command.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Command.php new file mode 100644 index 000000000..cbcc8d649 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Command.php @@ -0,0 +1,126 @@ +arguments = $arguments; + unset($this->slot); + } + + /** + * {@inheritdoc} + */ + public function setRawArguments(array $arguments) + { + $this->arguments = $arguments; + unset($this->slot); + } + + /** + * {@inheritdoc} + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * {@inheritdoc} + */ + public function getArgument($index) + { + if (isset($this->arguments[$index])) { + return $this->arguments[$index]; + } + } + + /** + * {@inheritdoc} + */ + public function setSlot($slot) + { + $this->slot = $slot; + } + + /** + * {@inheritdoc} + */ + public function getSlot() + { + return $this->slot ?? null; + } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + return $data; + } + + /** + * Normalizes the arguments array passed to a Redis command. + * + * @param array $arguments Arguments for a command. + * + * @return array + */ + public static function normalizeArguments(array $arguments) + { + if (count($arguments) === 1 && isset($arguments[0]) && is_array($arguments[0])) { + return $arguments[0]; + } + + return $arguments; + } + + /** + * Normalizes the arguments array passed to a variadic Redis command. + * + * @param array $arguments Arguments for a command. + * + * @return array + */ + public static function normalizeVariadic(array $arguments) + { + if (count($arguments) === 2 && is_array($arguments[1])) { + return array_merge([$arguments[0]], $arguments[1]); + } + + return $arguments; + } + + /** + * Remove all false values from arguments. + * + * @return void + */ + public function filterArguments(): void + { + $this->arguments = array_filter($this->arguments, static function ($argument) { + return $argument !== false && $argument !== null; + }); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/CommandInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/CommandInterface.php new file mode 100644 index 000000000..22e7c76cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/CommandInterface.php @@ -0,0 +1,80 @@ +getCommandClass($commandID) === null) { + return false; + } + } + + return true; + } + + /** + * Returns the FQCN of a class that represents the specified command ID. + * + * @codeCoverageIgnore + * + * @param string $commandID Command ID + * + * @return string|null + */ + public function getCommandClass(string $commandID): ?string + { + return $this->commands[strtoupper($commandID)] ?? null; + } + + /** + * {@inheritdoc} + */ + public function create(string $commandID, array $arguments = []): CommandInterface + { + if (!$commandClass = $this->getCommandClass($commandID)) { + $commandID = strtoupper($commandID); + + throw new ClientException("Command `$commandID` is not a registered Redis command."); + } + + $command = new $commandClass(); + $command->setArguments($arguments); + + if (isset($this->processor)) { + $this->processor->process($command); + } + + return $command; + } + + /** + * Defines a command in the factory. + * + * Only classes implementing Predis\Command\CommandInterface are allowed to + * handle a command. If the command specified by its ID is already handled + * by the factory, the underlying command class is replaced by the new one. + * + * @param string $commandID Command ID + * @param string $commandClass FQCN of a class implementing Predis\Command\CommandInterface + * + * @throws InvalidArgumentException + */ + public function define(string $commandID, string $commandClass): void + { + if (!is_a($commandClass, 'Predis\Command\CommandInterface', true)) { + throw new InvalidArgumentException( + "Class $commandClass must implement Predis\Command\CommandInterface" + ); + } + + $this->commands[strtoupper($commandID)] = $commandClass; + } + + /** + * Undefines a command in the factory. + * + * When the factory already has a class handler associated to the specified + * command ID it is removed from the map of known commands. Nothing happens + * when the command is not handled by the factory. + * + * @param string $commandID Command ID + */ + public function undefine(string $commandID): void + { + unset($this->commands[strtoupper($commandID)]); + } + + /** + * Sets a command processor for processing command arguments. + * + * Command processors are used to process and transform arguments of Redis + * commands before their newly created instances are returned to the caller + * of "create()". + * + * A NULL value can be used to effectively unset any processor if previously + * set for the command factory. + * + * @param ProcessorInterface|null $processor Command processor or NULL value. + */ + public function setProcessor(?ProcessorInterface $processor): void + { + $this->processor = $processor; + } + + /** + * Returns the current command processor. + * + * @return ProcessorInterface|null + */ + public function getProcessor(): ?ProcessorInterface + { + return $this->processor; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/FactoryInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/FactoryInterface.php new file mode 100644 index 000000000..0cab5f6c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/FactoryInterface.php @@ -0,0 +1,42 @@ +prefix = $prefix; + + $prefixFirst = static::class . '::first'; + $prefixFirstTwo = static::class . '::firstTwo'; + $prefixAll = static::class . '::all'; + $prefixInterleaved = static::class . '::interleaved'; + $prefixSkipFirst = static::class . '::skipFirst'; + $prefixSkipLast = static::class . '::skipLast'; + $prefixSort = static::class . '::sort'; + $prefixEvalKeys = static::class . '::evalKeys'; + $prefixZsetStore = static::class . '::zsetStore'; + $prefixMigrate = static::class . '::migrate'; + $prefixGeoradius = static::class . '::georadius'; + + $this->commands = [ + /* ---------------- Redis 1.2 ---------------- */ + 'EXISTS' => $prefixAll, + 'DEL' => $prefixAll, + 'TYPE' => $prefixFirst, + 'KEYS' => $prefixFirst, + 'RENAME' => $prefixAll, + 'RENAMENX' => $prefixAll, + 'EXPIRE' => $prefixFirst, + 'EXPIREAT' => $prefixFirst, + 'TTL' => $prefixFirst, + 'MOVE' => $prefixFirst, + 'SORT' => $prefixSort, + 'DUMP' => $prefixFirst, + 'RESTORE' => $prefixFirst, + 'SET' => $prefixFirst, + 'SETNX' => $prefixFirst, + 'MSET' => $prefixInterleaved, + 'MSETNX' => $prefixInterleaved, + 'GET' => $prefixFirst, + 'MGET' => $prefixAll, + 'GETSET' => $prefixFirst, + 'INCR' => $prefixFirst, + 'INCRBY' => $prefixFirst, + 'DECR' => $prefixFirst, + 'DECRBY' => $prefixFirst, + 'RPUSH' => $prefixFirst, + 'LPUSH' => $prefixFirst, + 'LLEN' => $prefixFirst, + 'LRANGE' => $prefixFirst, + 'LTRIM' => $prefixFirst, + 'LINDEX' => $prefixFirst, + 'LSET' => $prefixFirst, + 'LREM' => $prefixFirst, + 'LPOP' => $prefixFirst, + 'RPOP' => $prefixFirst, + 'RPOPLPUSH' => $prefixAll, + 'SADD' => $prefixFirst, + 'SREM' => $prefixFirst, + 'SPOP' => $prefixFirst, + 'SMOVE' => $prefixSkipLast, + 'SCARD' => $prefixFirst, + 'SISMEMBER' => $prefixFirst, + 'SINTER' => $prefixAll, + 'SINTERSTORE' => $prefixAll, + 'SUNION' => $prefixAll, + 'SUNIONSTORE' => $prefixAll, + 'SDIFF' => $prefixAll, + 'SDIFFSTORE' => $prefixAll, + 'SMEMBERS' => $prefixFirst, + 'SMISMEMBER' => $prefixFirst, + 'SRANDMEMBER' => $prefixFirst, + 'ZADD' => $prefixFirst, + 'ZINCRBY' => $prefixFirst, + 'ZREM' => $prefixFirst, + 'ZRANGE' => $prefixFirst, + 'ZREVRANGE' => $prefixFirst, + 'ZRANGEBYSCORE' => $prefixFirst, + 'ZCARD' => $prefixFirst, + 'ZSCORE' => $prefixFirst, + 'ZREMRANGEBYSCORE' => $prefixFirst, + + /* ---------------- Redis 2.0 ---------------- */ + 'SETEX' => $prefixFirst, + 'APPEND' => $prefixFirst, + 'SUBSTR' => $prefixFirst, + 'BLPOP' => $prefixSkipLast, + 'BRPOP' => $prefixSkipLast, + 'ZUNIONSTORE' => $prefixZsetStore, + 'ZINTERSTORE' => $prefixZsetStore, + 'ZCOUNT' => $prefixFirst, + 'ZRANK' => $prefixFirst, + 'ZREVRANK' => $prefixFirst, + 'ZREMRANGEBYRANK' => $prefixFirst, + 'HSET' => $prefixFirst, + 'HSETNX' => $prefixFirst, + 'HMSET' => $prefixFirst, + 'HINCRBY' => $prefixFirst, + 'HGET' => $prefixFirst, + 'HMGET' => $prefixFirst, + 'HDEL' => $prefixFirst, + 'HEXISTS' => $prefixFirst, + 'HLEN' => $prefixFirst, + 'HKEYS' => $prefixFirst, + 'HVALS' => $prefixFirst, + 'HGETALL' => $prefixFirst, + 'SUBSCRIBE' => $prefixAll, + 'UNSUBSCRIBE' => $prefixAll, + 'PSUBSCRIBE' => $prefixAll, + 'PUNSUBSCRIBE' => $prefixAll, + 'PUBLISH' => $prefixFirst, + + /* ---------------- Redis 2.2 ---------------- */ + 'PERSIST' => $prefixFirst, + 'STRLEN' => $prefixFirst, + 'SETRANGE' => $prefixFirst, + 'GETRANGE' => $prefixFirst, + 'SETBIT' => $prefixFirst, + 'GETBIT' => $prefixFirst, + 'RPUSHX' => $prefixFirst, + 'LPUSHX' => $prefixFirst, + 'LINSERT' => $prefixFirst, + 'BRPOPLPUSH' => $prefixSkipLast, + 'ZREVRANGEBYSCORE' => $prefixFirst, + 'WATCH' => $prefixAll, + + /* ---------------- Redis 2.6 ---------------- */ + 'PTTL' => $prefixFirst, + 'PEXPIRE' => $prefixFirst, + 'PEXPIREAT' => $prefixFirst, + 'PSETEX' => $prefixFirst, + 'INCRBYFLOAT' => $prefixFirst, + 'BITOP' => $prefixSkipFirst, + 'BITCOUNT' => $prefixFirst, + 'HINCRBYFLOAT' => $prefixFirst, + 'EVAL' => $prefixEvalKeys, + 'EVALSHA' => $prefixEvalKeys, + 'MIGRATE' => $prefixMigrate, + + /* ---------------- Redis 2.8 ---------------- */ + 'SSCAN' => $prefixFirst, + 'ZSCAN' => $prefixFirst, + 'HSCAN' => $prefixFirst, + 'PFADD' => $prefixFirst, + 'PFCOUNT' => $prefixAll, + 'PFMERGE' => $prefixAll, + 'ZLEXCOUNT' => $prefixFirst, + 'ZRANGEBYLEX' => $prefixFirst, + 'ZREMRANGEBYLEX' => $prefixFirst, + 'ZREVRANGEBYLEX' => $prefixFirst, + 'BITPOS' => $prefixFirst, + + /* ---------------- Redis 3.2 ---------------- */ + 'HSTRLEN' => $prefixFirst, + 'BITFIELD' => $prefixFirst, + 'GEOADD' => $prefixFirst, + 'GEOHASH' => $prefixFirst, + 'GEOPOS' => $prefixFirst, + 'GEODIST' => $prefixFirst, + 'GEORADIUS' => $prefixGeoradius, + 'GEORADIUSBYMEMBER' => $prefixGeoradius, + + /* ---------------- Redis 5.0 ---------------- */ + 'XADD' => $prefixFirst, + 'XRANGE' => $prefixFirst, + 'XREVRANGE' => $prefixFirst, + 'XDEL' => $prefixFirst, + 'XLEN' => $prefixFirst, + 'XACK' => $prefixFirst, + 'XTRIM' => $prefixFirst, + 'ZPOPMIN' => $prefixFirst, + 'ZPOPMAX' => $prefixFirst, + + /* ---------------- Redis 6.2 ---------------- */ + 'GETDEL' => $prefixFirst, + 'ZMSCORE' => $prefixFirst, + 'LMOVE' => $prefixFirstTwo, + 'BLMOVE' => $prefixFirstTwo, + 'GEOSEARCH' => $prefixFirst, + + /* ---------------- Redis 7.0 ---------------- */ + 'EXPIRETIME' => $prefixFirst, + + /* RedisJSON */ + 'JSON.ARRAPPEND' => $prefixFirst, + 'JSON.ARRINDEX' => $prefixFirst, + 'JSON.ARRINSERT' => $prefixFirst, + 'JSON.ARRLEN' => $prefixFirst, + 'JSON.ARRPOP' => $prefixFirst, + 'JSON.ARRTRIM' => $prefixFirst, + 'JSON.CLEAR' => $prefixFirst, + 'JSON.DEBUG MEMORY' => $prefixFirst, + 'JSON.DEL' => $prefixFirst, + 'JSON.FORGET' => $prefixFirst, + 'JSON.GET' => $prefixFirst, + 'JSON.MGET' => $prefixAll, + 'JSON.NUMINCRBY' => $prefixFirst, + 'JSON.OBJKEYS' => $prefixFirst, + 'JSON.OBJLEN' => $prefixFirst, + 'JSON.RESP' => $prefixFirst, + 'JSON.SET' => $prefixFirst, + 'JSON.STRAPPEND' => $prefixFirst, + 'JSON.STRLEN' => $prefixFirst, + 'JSON.TOGGLE' => $prefixFirst, + 'JSON.TYPE' => $prefixFirst, + + /* RedisBloom */ + 'BF.ADD' => $prefixFirst, + 'BF.EXISTS' => $prefixFirst, + 'BF.INFO' => $prefixFirst, + 'BF.INSERT' => $prefixFirst, + 'BF.LOADCHUNK' => $prefixFirst, + 'BF.MADD' => $prefixFirst, + 'BF.MEXISTS' => $prefixFirst, + 'BF.RESERVE' => $prefixFirst, + 'BF.SCANDUMP' => $prefixFirst, + 'CF.ADD' => $prefixFirst, + 'CF.ADDNX' => $prefixFirst, + 'CF.COUNT' => $prefixFirst, + 'CF.DEL' => $prefixFirst, + 'CF.EXISTS' => $prefixFirst, + 'CF.INFO' => $prefixFirst, + 'CF.INSERT' => $prefixFirst, + 'CF.INSERTNX' => $prefixFirst, + 'CF.LOADCHUNK' => $prefixFirst, + 'CF.MEXISTS' => $prefixFirst, + 'CF.RESERVE' => $prefixFirst, + 'CF.SCANDUMP' => $prefixFirst, + 'CMS.INCRBY' => $prefixFirst, + 'CMS.INFO' => $prefixFirst, + 'CMS.INITBYDIM' => $prefixFirst, + 'CMS.INITBYPROB' => $prefixFirst, + 'CMS.QUERY' => $prefixFirst, + 'TDIGEST.ADD' => $prefixFirst, + 'TDIGEST.BYRANK' => $prefixFirst, + 'TDIGEST.BYREVRANK' => $prefixFirst, + 'TDIGEST.CDF' => $prefixFirst, + 'TDIGEST.CREATE' => $prefixFirst, + 'TDIGEST.INFO' => $prefixFirst, + 'TDIGEST.MAX' => $prefixFirst, + 'TDIGEST.MIN' => $prefixFirst, + 'TDIGEST.QUANTILE' => $prefixFirst, + 'TDIGEST.RANK' => $prefixFirst, + 'TDIGEST.RESET' => $prefixFirst, + 'TDIGEST.REVRANK' => $prefixFirst, + 'TDIGEST.TRIMMED_MEAN' => $prefixFirst, + 'TOPK.ADD' => $prefixFirst, + 'TOPK.INCRBY' => $prefixFirst, + 'TOPK.INFO' => $prefixFirst, + 'TOPK.LIST' => $prefixFirst, + 'TOPK.QUERY' => $prefixFirst, + 'TOPK.RESERVE' => $prefixFirst, + + /* RediSearch */ + 'FT.AGGREGATE' => $prefixFirst, + 'FT.ALTER' => $prefixFirst, + 'FT.CREATE' => $prefixFirst, + 'FT.CURSOR DEL' => $prefixFirst, + 'FT.CURSOR READ' => $prefixFirst, + 'FT.DROPINDEX' => $prefixFirst, + 'FT.EXPLAIN' => $prefixFirst, + 'FT.INFO' => $prefixFirst, + 'FT.PROFILE' => $prefixFirst, + 'FT.SEARCH' => $prefixFirst, + 'FT.SPELLCHECK' => $prefixFirst, + 'FT.SYNDUMP' => $prefixFirst, + 'FT.SYNUPDATE' => $prefixFirst, + 'FT.TAGVALS' => $prefixFirst, + + /* Redis TimeSeries */ + 'TS.ADD' => $prefixFirst, + 'TS.ALTER' => $prefixFirst, + 'TS.CREATE' => $prefixFirst, + 'TS.DECRBY' => $prefixFirst, + 'TS.DEL' => $prefixFirst, + 'TS.GET' => $prefixFirst, + 'TS.INCRBY' => $prefixFirst, + 'TS.INFO' => $prefixFirst, + 'TS.MGET' => $prefixFirst, + 'TS.MRANGE' => $prefixFirst, + 'TS.MREVRANGE' => $prefixFirst, + 'TS.QUERYINDEX' => $prefixFirst, + 'TS.RANGE' => $prefixFirst, + 'TS.REVRANGE' => $prefixFirst, + ]; + } + + /** + * Sets a prefix that is applied to all the keys. + * + * @param string $prefix Prefix for the keys. + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + } + + /** + * Gets the current prefix. + * + * @return string + */ + public function getPrefix() + { + return $this->prefix; + } + + /** + * {@inheritdoc} + */ + public function process(CommandInterface $command) + { + if ($command instanceof PrefixableCommandInterface) { + $command->prefixKeys($this->prefix); + } elseif (isset($this->commands[$commandID = strtoupper($command->getId())])) { + $this->commands[$commandID]($command, $this->prefix); + } + } + + /** + * Sets an handler for the specified command ID. + * + * The callback signature must have 2 parameters of the following types: + * + * - Predis\Command\CommandInterface (command instance) + * - String (prefix) + * + * When the callback argument is omitted or NULL, the previously + * associated handler for the specified command ID is removed. + * + * @param string $commandID The ID of the command to be handled. + * @param mixed $callback A valid callable object or NULL. + * + * @throws InvalidArgumentException + */ + public function setCommandHandler($commandID, $callback = null) + { + $commandID = strtoupper($commandID); + + if (!isset($callback)) { + unset($this->commands[$commandID]); + + return; + } + + if (!is_callable($callback)) { + throw new InvalidArgumentException( + 'Callback must be a valid callable object or NULL' + ); + } + + $this->commands[$commandID] = $callback; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->getPrefix(); + } + + /** + * Applies the specified prefix only the first argument. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function first(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $arguments[0] = "$prefix{$arguments[0]}"; + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix only to the first two arguments. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function firstTwo(CommandInterface $command, $prefix) + { + $arguments = $command->getArguments(); + $length = min(count($arguments), 2); + + for ($i = 0; $i < $length; $i++) { + $arguments[$i] = "$prefix{$arguments[$i]}"; + } + + $command->setRawArguments($arguments); + } + + /** + * Applies the specified prefix to all the arguments. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function all(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + foreach ($arguments as &$key) { + $key = "$prefix$key"; + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix only to even arguments in the list. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function interleaved(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $length = count($arguments); + + for ($i = 0; $i < $length; $i += 2) { + $arguments[$i] = "$prefix{$arguments[$i]}"; + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to all the arguments but the first one. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function skipFirst(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $length = count($arguments); + + for ($i = 1; $i < $length; ++$i) { + $arguments[$i] = "$prefix{$arguments[$i]}"; + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to all the arguments but the last one. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function skipLast(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $length = count($arguments); + + for ($i = 0; $i < $length - 1; ++$i) { + $arguments[$i] = "$prefix{$arguments[$i]}"; + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to the keys of a SORT command. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function sort(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $arguments[0] = "$prefix{$arguments[0]}"; + + if (($count = count($arguments)) > 1) { + for ($i = 1; $i < $count; ++$i) { + switch (strtoupper($arguments[$i])) { + case 'BY': + case 'STORE': + $arguments[$i] = "$prefix{$arguments[++$i]}"; + break; + + case 'GET': + $value = $arguments[++$i]; + if ($value !== '#') { + $arguments[$i] = "$prefix$value"; + } + break; + + case 'LIMIT': + $i += 2; + break; + } + } + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to the keys of an EVAL-based command. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function evalKeys(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + for ($i = 2; $i < $arguments[1] + 2; ++$i) { + $arguments[$i] = "$prefix{$arguments[$i]}"; + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to the keys of Z[INTERSECTION|UNION]STORE. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function zsetStore(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $arguments[0] = "$prefix{$arguments[0]}"; + $length = ((int) $arguments[1]) + 2; + + for ($i = 2; $i < $length; ++$i) { + $arguments[$i] = "$prefix{$arguments[$i]}"; + } + + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to the key of a MIGRATE command. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function migrate(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $arguments[2] = "$prefix{$arguments[2]}"; + $command->setRawArguments($arguments); + } + } + + /** + * Applies the specified prefix to the key of a GEORADIUS command. + * + * @param CommandInterface $command Command instance. + * @param string $prefix Prefix string. + */ + public static function georadius(CommandInterface $command, $prefix) + { + if ($arguments = $command->getArguments()) { + $arguments[0] = "$prefix{$arguments[0]}"; + $startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4; + + if (($count = count($arguments)) > $startIndex) { + for ($i = $startIndex; $i < $count; ++$i) { + switch (strtoupper($arguments[$i])) { + case 'STORE': + case 'STOREDIST': + $arguments[$i] = "$prefix{$arguments[++$i]}"; + break; + } + } + } + + $command->setRawArguments($arguments); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorChain.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorChain.php new file mode 100644 index 000000000..6b7665c37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorChain.php @@ -0,0 +1,142 @@ +add($processor); + } + } + + /** + * {@inheritdoc} + */ + public function add(ProcessorInterface $processor) + { + $this->processors[] = $processor; + } + + /** + * {@inheritdoc} + */ + public function remove(ProcessorInterface $processor) + { + if (false !== $index = array_search($processor, $this->processors, true)) { + unset($this[$index]); + } + } + + /** + * {@inheritdoc} + */ + public function process(CommandInterface $command) + { + for ($i = 0; $i < $count = count($this->processors); ++$i) { + $this->processors[$i]->process($command); + } + } + + /** + * {@inheritdoc} + */ + public function getProcessors() + { + return $this->processors; + } + + /** + * Returns an iterator over the list of command processor in the chain. + * + * @return Traversable + */ + public function getIterator() + { + return new ArrayIterator($this->processors); + } + + /** + * Returns the number of command processors in the chain. + * + * @return int + */ + public function count() + { + return count($this->processors); + } + + /** + * @param int $index + * @return bool + */ + #[ReturnTypeWillChange] + public function offsetExists($index) + { + return isset($this->processors[$index]); + } + + /** + * @param int $index + * @return ProcessorInterface + */ + #[ReturnTypeWillChange] + public function offsetGet($index) + { + return $this->processors[$index]; + } + + /** + * @param int $index + * @param ProcessorInterface $processor + * @return void + */ + #[ReturnTypeWillChange] + public function offsetSet($index, $processor) + { + if (!$processor instanceof ProcessorInterface) { + throw new InvalidArgumentException( + 'Processor chain accepts only instances of `Predis\Command\Processor\ProcessorInterface`' + ); + } + + $this->processors[$index] = $processor; + } + + /** + * @param int $index + * @return void + */ + #[ReturnTypeWillChange] + public function offsetUnset($index) + { + unset($this->processors[$index]); + $this->processors = array_values($this->processors); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorInterface.php new file mode 100644 index 000000000..f711e060a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Processor/ProcessorInterface.php @@ -0,0 +1,28 @@ +commandID = strtoupper($commandID); + $this->setArguments($arguments); + } + + /** + * Creates a new raw command using a variadic method. + * + * @param string $commandID Redis command ID + * @param string ...$args Arguments list for the command + * + * @return CommandInterface + */ + public static function create($commandID, ...$args) + { + $arguments = func_get_args(); + + return new static(array_shift($arguments), $arguments); + } + + /** + * {@inheritdoc} + */ + public function getId() + { + return $this->commandID; + } + + /** + * {@inheritdoc} + */ + public function setArguments(array $arguments) + { + $this->arguments = $arguments; + unset($this->slot); + } + + /** + * {@inheritdoc} + */ + public function setRawArguments(array $arguments) + { + $this->setArguments($arguments); + } + + /** + * {@inheritdoc} + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * {@inheritdoc} + */ + public function getArgument($index) + { + if (isset($this->arguments[$index])) { + return $this->arguments[$index]; + } + } + + /** + * {@inheritdoc} + */ + public function setSlot($slot) + { + $this->slot = $slot; + } + + /** + * {@inheritdoc} + */ + public function getSlot() + { + return $this->slot ?? null; + } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/RawFactory.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/RawFactory.php new file mode 100644 index 000000000..fb01d8692 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/RawFactory.php @@ -0,0 +1,43 @@ +setKeys($arguments, false); + } + + public function parseResponse($data) + { + $key = array_shift($data); + + if (null === $key) { + return [$key]; + } + + return array_combine([$key], [[$data[0] => $data[1]]]); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BGREWRITEAOF.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BGREWRITEAOF.php new file mode 100644 index 000000000..b75af633a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BGREWRITEAOF.php @@ -0,0 +1,37 @@ + 'CAPACITY', + 'size' => 'SIZE', + 'filters' => 'FILTERS', + 'items' => 'ITEMS', + 'expansion' => 'EXPANSION', + ]; + + public function getId() + { + return 'BF.INFO'; + } + + public function setArguments(array $arguments) + { + if (isset($arguments[1])) { + $modifier = array_pop($arguments); + + if ($modifier === '') { + parent::setArguments($arguments); + + return; + } + + if (!in_array(strtoupper($modifier), $this->modifierEnum)) { + $enumValues = implode(', ', array_keys($this->modifierEnum)); + throw new UnexpectedValueException("Argument accepts only: {$enumValues} values"); + } + + $arguments[] = $this->modifierEnum[strtolower($modifier)]; + } + + parent::setArguments($arguments); + } + + public function parseResponse($data) + { + if (count($data) > 1) { + $result = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { + if (array_key_exists($i + 1, $data)) { + $result[(string) $data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFINSERT.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFINSERT.php new file mode 100644 index 000000000..86099bd93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFINSERT.php @@ -0,0 +1,72 @@ +setNoCreate($arguments); + $arguments = $this->getArguments(); + + if (array_key_exists(5, $arguments) && $arguments[5]) { + $arguments[5] = 'NONSCALING'; + } + + $this->setItems($arguments); + $arguments = $this->getArguments(); + + $this->setExpansion($arguments); + $arguments = $this->getArguments(); + + $this->setErrorRate($arguments); + $arguments = $this->getArguments(); + + $this->setCapacity($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFLOADCHUNK.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFLOADCHUNK.php new file mode 100644 index 000000000..1ae6732c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFLOADCHUNK.php @@ -0,0 +1,28 @@ +setExpansion($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFSCANDUMP.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFSCANDUMP.php new file mode 100644 index 000000000..96100b589 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/BloomFilter/BFSCANDUMP.php @@ -0,0 +1,29 @@ +getArguments(), CASE_UPPER); + + switch (strtoupper($args[0])) { + case 'LIST': + return $this->parseClientList($data); + case 'KILL': + case 'GETNAME': + case 'SETNAME': + default: + return $data; + } // @codeCoverageIgnore + } + + /** + * Parses the response to CLIENT LIST and returns a structured list. + * + * @param string $data Response buffer. + * + * @return array + */ + protected function parseClientList($data) + { + $clients = []; + + foreach (explode("\n", $data, -1) as $clientData) { + $client = []; + + foreach (explode(' ', $clientData) as $kv) { + @[$k, $v] = explode('=', $kv); + $client[$k] = $v; + } + + $clients[] = $client; + } + + return $clients; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CLUSTER.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CLUSTER.php new file mode 100644 index 000000000..e0a5ffb29 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CLUSTER.php @@ -0,0 +1,26 @@ +setDB($arguments); + $arguments = $this->getArguments(); + + $this->setReplace($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ACL.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ACL.php new file mode 100644 index 000000000..a5982ffa8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ACL.php @@ -0,0 +1,28 @@ +client = $client; + } + + /** + * {@inheritDoc} + */ + public function __call(string $subcommandID, array $arguments) + { + array_unshift($arguments, strtoupper($subcommandID)); + + return $this->client->executeCommand( + $this->client->createCommand($this->getContainerCommandId(), $arguments) + ); + } + + abstract public function getContainerCommandId(): string; +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/CLUSTER.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/CLUSTER.php new file mode 100644 index 000000000..bba5d0c83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/CLUSTER.php @@ -0,0 +1,29 @@ + FunctionContainer::class, + ]; + + /** + * Creates container command. + * + * @param ClientInterface $client + * @param string $containerCommandID + * @return ContainerInterface + */ + public static function create(ClientInterface $client, string $containerCommandID): ContainerInterface + { + $containerCommandID = strtoupper($containerCommandID); + $commandModule = self::resolveCommandModuleByPrefix($containerCommandID); + + if (null !== $commandModule) { + if (class_exists($containerClass = self::CONTAINER_NAMESPACE . '\\' . $commandModule . '\\' . $containerCommandID)) { + return new $containerClass($client); + } + + throw new UnexpectedValueException('Given module container command is not supported.'); + } + + if (class_exists($containerClass = self::CONTAINER_NAMESPACE . '\\' . $containerCommandID)) { + return new $containerClass($client); + } + + if (array_key_exists($containerCommandID, self::$specialMappings)) { + $containerClass = self::$specialMappings[$containerCommandID]; + + return new $containerClass($client); + } + + throw new UnexpectedValueException('Given container command is not supported.'); + } + + /** + * @param string $commandID + * @return string|null + */ + private static function resolveCommandModuleByPrefix(string $commandID): ?string + { + $modules = ClientConfiguration::getModules(); + + foreach ($modules as $module) { + if (preg_match("/^{$module['commandPrefix']}/", $commandID)) { + return $module['name']; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ContainerInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ContainerInterface.php new file mode 100644 index 000000000..e69478a37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Container/ContainerInterface.php @@ -0,0 +1,33 @@ + 1) { + $result = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { + if (array_key_exists($i + 1, $data)) { + $result[(string) $data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINITBYDIM.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINITBYDIM.php new file mode 100644 index 000000000..1922d40da --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CountMinSketch/CMSINITBYDIM.php @@ -0,0 +1,28 @@ + 1) { + $result = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { + if (array_key_exists($i + 1, $data)) { + $result[(string) $data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERT.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERT.php new file mode 100644 index 000000000..dfdfcc3ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERT.php @@ -0,0 +1,52 @@ +setNoCreate($arguments); + $arguments = $this->getArguments(); + + $this->setItems($arguments); + $arguments = $this->getArguments(); + + $this->setCapacity($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERTNX.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERTNX.php new file mode 100644 index 000000000..afee07a16 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFINSERTNX.php @@ -0,0 +1,27 @@ +setExpansion($arguments); + $arguments = $this->getArguments(); + + $this->setMaxIterations($arguments); + $arguments = $this->getArguments(); + + $this->setBucketSize($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFSCANDUMP.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFSCANDUMP.php new file mode 100644 index 000000000..3045f6ca2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/CuckooFilter/CFSCANDUMP.php @@ -0,0 +1,29 @@ +getArgument(0); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVALSHA_RO.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVALSHA_RO.php new file mode 100644 index 000000000..cd0009f02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVALSHA_RO.php @@ -0,0 +1,27 @@ +getArgument(0)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVAL_RO.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVAL_RO.php new file mode 100644 index 000000000..081607b52 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/EVAL_RO.php @@ -0,0 +1,34 @@ +setTimeout($arguments); + $arguments = $this->getArguments(); + + $this->setTo($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FCALL.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FCALL.php new file mode 100644 index 000000000..95da15225 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FCALL.php @@ -0,0 +1,33 @@ + 2) { + for ($i = 2, $iMax = count($arguments); $i < $iMax; $i++) { + $processedArguments[] = $arguments[$i]; + } + } + + parent::setArguments($processedArguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FLUSHALL.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FLUSHALL.php new file mode 100644 index 000000000..b9e8b5bb6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/FLUSHALL.php @@ -0,0 +1,29 @@ +strategyResolver = new SubcommandStrategyResolver(); + } + + public function getId() + { + return 'FUNCTION'; + } + + public function setArguments(array $arguments) + { + $strategy = $this->strategyResolver->resolve('functions', strtolower($arguments[0])); + $arguments = $strategy->processArguments($arguments); + + parent::setArguments($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOADD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOADD.php new file mode 100644 index 000000000..a124b9011 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOADD.php @@ -0,0 +1,43 @@ +setSorting($arguments); + $arguments = $this->getArguments(); + + $this->setWithCoord($arguments); + $arguments = $this->getArguments(); + + $this->setWithDist($arguments); + $arguments = $this->getArguments(); + + $this->setWithHash($arguments); + $arguments = $this->getArguments(); + + $this->setCount($arguments, $arguments[5] ?? false); + $arguments = $this->getArguments(); + + $this->setFrom($arguments); + $arguments = $this->getArguments(); + + $this->setBy($arguments); + $this->filterArguments(); + } + + public function parseResponse($data) + { + $parsedData = []; + $itemKey = ''; + + foreach ($data as $item) { + if (!is_array($item)) { + $parsedData[] = $item; + continue; + } + + foreach ($item as $key => $itemRow) { + if ($key === 0) { + $itemKey = $itemRow; + continue; + } + + if (is_string($itemRow)) { + $parsedData[$itemKey]['dist'] = round((float) $itemRow, 5); + } elseif (is_int($itemRow)) { + $parsedData[$itemKey]['hash'] = $itemRow; + } else { + $parsedData[$itemKey]['lng'] = round($itemRow[0], 5); + $parsedData[$itemKey]['lat'] = round($itemRow[1], 5); + } + } + } + + return $parsedData; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOSEARCHSTORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOSEARCHSTORE.php new file mode 100644 index 000000000..5d30eda7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GEOSEARCHSTORE.php @@ -0,0 +1,71 @@ +setStoreDist($arguments); + $arguments = $this->getArguments(); + + $this->setCount($arguments, $arguments[6] ?? false); + $arguments = $this->getArguments(); + + $this->setSorting($arguments); + $arguments = $this->getArguments(); + + $this->setFrom($arguments); + $arguments = $this->getArguments(); + + $this->setBy($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GET.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GET.php new file mode 100644 index 000000000..537a8fb84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GET.php @@ -0,0 +1,29 @@ + 'EX', + 'px' => 'PX', + 'exat' => 'EXAT', + 'pxat' => 'PXAT', + 'persist' => 'PERSIST', + ]; + + public function getId() + { + return 'GETEX'; + } + + public function setArguments(array $arguments) + { + if (!array_key_exists(1, $arguments) || $arguments[1] === '') { + parent::setArguments([$arguments[0]]); + + return; + } + + if (!in_array(strtoupper($arguments[1]), self::$modifierEnum)) { + $enumValues = implode(', ', array_keys(self::$modifierEnum)); + throw new UnexpectedValueException("Modifier argument accepts only: {$enumValues} values"); + } + + if ($arguments[1] === 'persist') { + parent::setArguments([$arguments[0], self::$modifierEnum[$arguments[1]]]); + + return; + } + + $arguments[1] = self::$modifierEnum[$arguments[1]]; + + if (!array_key_exists(2, $arguments)) { + throw new UnexpectedValueException('You should provide value for current modifier'); + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETRANGE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETRANGE.php new file mode 100644 index 000000000..f590ca302 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/GETRANGE.php @@ -0,0 +1,29 @@ +flagsEnum, true)) { + $processedArguments[] = strtoupper($arguments[3]); + } else { + throw new UnexpectedValueException('Unsupported flag value'); + } + } + + if (array_key_exists(2, $arguments) && null !== $arguments[2]) { + array_push($processedArguments, 'FIELDS', count($arguments[2])); + $processedArguments = array_merge($processedArguments, $arguments[2]); + } + + parent::setArguments($processedArguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXPIREAT.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXPIREAT.php new file mode 100644 index 000000000..5fc7a2a99 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HEXPIREAT.php @@ -0,0 +1,21 @@ + $v) { + $flattenedKVs[] = $k; + $flattenedKVs[] = $v; + } + + $arguments = $flattenedKVs; + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPERSIST.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPERSIST.php new file mode 100644 index 000000000..dae45acd2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HPERSIST.php @@ -0,0 +1,31 @@ +prepareOptions(array_pop($arguments)); + $arguments = array_merge($arguments, $options); + } + + $this->arguments = $arguments; + parent::setArguments($arguments); + } + + /** + * Returns a list of options and modifiers compatible with Redis. + * + * @param array $options List of options. + * + * @return array + */ + protected function prepareOptions($options) + { + $options = array_change_key_case($options, CASE_UPPER); + $normalized = []; + + if (!empty($options['MATCH'])) { + $normalized[] = 'MATCH'; + $normalized[] = $options['MATCH']; + } + + if (!empty($options['COUNT'])) { + $normalized[] = 'COUNT'; + $normalized[] = $options['COUNT']; + } + + if (!empty($options['NOVALUES']) && true === $options['NOVALUES']) { + $normalized[] = 'NOVALUES'; + } + + return $normalized; + } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (!in_array('NOVALUES', $this->arguments, true)) { + if (is_array($data)) { + $fields = $data[1]; + $result = []; + + for ($i = 0; $i < count($fields); ++$i) { + $result[$fields[$i]] = $fields[++$i]; + } + + $data[1] = $result; + } + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSET.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSET.php new file mode 100644 index 000000000..00a949c59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/HSET.php @@ -0,0 +1,29 @@ +parseNewResponseFormat($lines); + } else { + return $this->parseOldResponseFormat($lines); + } + } + + /** + * {@inheritdoc} + */ + public function parseNewResponseFormat($lines) + { + $info = []; + $current = null; + + foreach ($lines as $row) { + if ($row === '') { + continue; + } + + if (preg_match('/^# (\w+)$/', $row, $matches)) { + $info[$matches[1]] = []; + $current = &$info[$matches[1]]; + continue; + } + + [$k, $v] = $this->parseRow($row); + $current[$k] = $v; + } + + return $info; + } + + /** + * {@inheritdoc} + */ + public function parseOldResponseFormat($lines) + { + $info = []; + + foreach ($lines as $row) { + if (strpos($row, ':') === false) { + continue; + } + + [$k, $v] = $this->parseRow($row); + $info[$k] = $v; + } + + return $info; + } + + /** + * Parses a single row of the response and returns the key-value pair. + * + * @param string $row Single row of the response. + * + * @return array + */ + protected function parseRow($row) + { + if (preg_match('/^module:name/', $row)) { + return $this->parseModuleRow($row); + } + + [$k, $v] = explode(':', $row, 2); + + if (preg_match('/^db\d+$/', $k)) { + $v = $this->parseDatabaseStats($v); + } + + return [$k, $v]; + } + + /** + * Extracts the statistics of each logical DB from the string buffer. + * + * @param string $str Response buffer. + * + * @return array + */ + protected function parseDatabaseStats($str) + { + $db = []; + + foreach (explode(',', $str) as $dbvar) { + [$dbvk, $dbvv] = explode('=', $dbvar); + $db[trim($dbvk)] = $dbvv; + } + + return $db; + } + + /** + * Parsing module rows because of different format. + * + * @param string $row + * @return array + */ + protected function parseModuleRow(string $row): array + { + [$moduleKeyword, $moduleData] = explode(':', $row); + $explodedData = explode(',', $moduleData); + $parsedData = []; + + foreach ($explodedData as $moduleDataRow) { + [$k, $v] = explode('=', $moduleDataRow); + + if ($k === 'name') { + $parsedData[0] = $v; + continue; + } + + $parsedData[1][$k] = $v; + } + + return $parsedData; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRAPPEND.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRAPPEND.php new file mode 100644 index 000000000..bac255a85 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONARRAPPEND.php @@ -0,0 +1,28 @@ +setSpace($arguments); + $arguments = $this->getArguments(); + + $this->setNewline($arguments); + $arguments = $this->getArguments(); + + $this->setIndent($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONMERGE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONMERGE.php new file mode 100644 index 000000000..39e3c92b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONMERGE.php @@ -0,0 +1,29 @@ +setSubcommand($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONSTRAPPEND.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONSTRAPPEND.php new file mode 100644 index 000000000..54b472494 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Json/JSONSTRAPPEND.php @@ -0,0 +1,28 @@ +filterArguments(); + } + + public function parseResponse($data) + { + if (is_array($data)) { + if ($data !== array_values($data)) { + return $data; // Relay + } + + return [$data[0] => $data[1], $data[2] => $data[3]]; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LINDEX.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LINDEX.php new file mode 100644 index 000000000..2ddfbe5cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LINDEX.php @@ -0,0 +1,29 @@ +setCount($arguments); + $arguments = $this->getArguments(); + + $this->setLeftRight($arguments); + $arguments = $this->getArguments(); + + $this->setKeys($arguments); + $this->filterArguments(); + } + + public function parseResponse($data) + { + if (null === $data) { + return null; + } + + return [$data[0] => $data[1]]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LPOP.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LPOP.php new file mode 100644 index 000000000..d4f462325 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/LPOP.php @@ -0,0 +1,29 @@ + $value) { + $modifier = strtoupper($modifier); + + if ($modifier === 'COPY' && $value == true) { + $arguments[] = $modifier; + } + + if ($modifier === 'REPLACE' && $value == true) { + $arguments[] = $modifier; + } + } + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MONITOR.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MONITOR.php new file mode 100644 index 000000000..0093270ca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MONITOR.php @@ -0,0 +1,29 @@ + $v) { + $flattenedKVs[] = $k; + $flattenedKVs[] = $v; + } + + $arguments = $flattenedKVs; + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MSETNX.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MSETNX.php new file mode 100644 index 000000000..ebee44778 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/MSETNX.php @@ -0,0 +1,27 @@ +getArgument(0))) { + case 'numsub': + return self::processNumsub($data); + + default: + return $data; + } + } + + /** + * Returns the processed response to PUBSUB NUMSUB. + * + * @param array $channels List of channels + * + * @return array + */ + protected static function processNumsub(array $channels) + { + $processed = []; + $count = count($channels); + + for ($i = 0; $i < $count; ++$i) { + $processed[$channels[$i]] = $channels[++$i]; + } + + return $processed; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PUNSUBSCRIBE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PUNSUBSCRIBE.php new file mode 100644 index 000000000..9a0ccdcd1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/PUNSUBSCRIBE.php @@ -0,0 +1,39 @@ +prepareOptions(array_pop($arguments)); + $arguments = array_merge($arguments, $options); + } + + parent::setArguments($arguments); + } + + /** + * Returns a list of options and modifiers compatible with Redis. + * + * @param array $options List of options. + * + * @return array + */ + protected function prepareOptions($options) + { + $options = array_change_key_case($options, CASE_UPPER); + $normalized = []; + + if (!empty($options['MATCH'])) { + $normalized[] = 'MATCH'; + $normalized[] = $options['MATCH']; + } + + if (!empty($options['COUNT'])) { + $normalized[] = 'COUNT'; + $normalized[] = $options['COUNT']; + } + + return $normalized; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SCARD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SCARD.php new file mode 100644 index 000000000..71aeca359 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SCARD.php @@ -0,0 +1,29 @@ +getArgument(0); + $argument = is_null($argument) ? null : strtolower($argument); + + switch ($argument) { + case 'masters': + case 'slaves': + return self::processMastersOrSlaves($data); + + default: + return $data; + } + } + + /** + * Returns a processed response to SENTINEL MASTERS or SENTINEL SLAVES. + * + * @param array $servers List of Redis servers. + * + * @return array + */ + protected static function processMastersOrSlaves(array $servers) + { + foreach ($servers as $idx => $node) { + $processed = []; + $count = count($node); + + for ($i = 0; $i < $count; ++$i) { + $processed[$node[$i]] = $node[++$i]; + } + + $servers[$idx] = $processed; + } + + return $servers; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SET.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SET.php new file mode 100644 index 000000000..eb22b8498 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SET.php @@ -0,0 +1,44 @@ + $value) { + if ($index < 2) { + continue; + } + + if (false === $value || null === $value) { + unset($arguments[$index]); + } + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETBIT.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETBIT.php new file mode 100644 index 000000000..929eca24b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SETBIT.php @@ -0,0 +1,29 @@ +setLimit($arguments); + $arguments = $this->getArguments(); + + $this->setKeys($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SINTERSTORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SINTERSTORE.php new file mode 100644 index 000000000..fef133b7c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SINTERSTORE.php @@ -0,0 +1,41 @@ + $entry) { + $log[$index] = [ + 'id' => $entry[0], + 'timestamp' => $entry[1], + 'duration' => $entry[2], + 'command' => $entry[3], + ]; + } + + return $log; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SMEMBERS.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SMEMBERS.php new file mode 100644 index 000000000..024037caa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SMEMBERS.php @@ -0,0 +1,29 @@ +setSorting($arguments); + $arguments = $this->getArguments(); + + $this->setGetArgument($arguments); + $arguments = $this->getArguments(); + + $this->setLimit($arguments); + $arguments = $this->getArguments(); + + $this->setBy($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SPOP.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SPOP.php new file mode 100644 index 000000000..94ab1ba23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/SPOP.php @@ -0,0 +1,29 @@ +prepareOptions(array_pop($arguments)); + $arguments = array_merge($arguments, $options); + } + + parent::setArguments($arguments); + } + + /** + * Returns a list of options and modifiers compatible with Redis. + * + * @param array $options List of options. + * + * @return array + */ + protected function prepareOptions($options) + { + $options = array_change_key_case($options, CASE_UPPER); + $normalized = []; + + if (!empty($options['MATCH'])) { + $normalized[] = 'MATCH'; + $normalized[] = $options['MATCH']; + } + + if (!empty($options['COUNT'])) { + $normalized[] = 'COUNT'; + $normalized[] = $options['COUNT']; + } + + return $normalized; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/STRLEN.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/STRLEN.php new file mode 100644 index 000000000..976ffdce2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/STRLEN.php @@ -0,0 +1,29 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$index, $query], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALIASADD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALIASADD.php new file mode 100644 index 000000000..9ae3e9b38 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTALIASADD.php @@ -0,0 +1,28 @@ +toArray() : []; + + $schema = array_reduce($schema, static function (array $carry, FieldInterface $field) { + return array_merge($carry, $field->toArray()); + }, []); + + array_unshift($schema, 'SCHEMA', 'ADD'); + + parent::setArguments(array_merge( + [$index], + $commandArguments, + $schema + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCONFIG.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCONFIG.php new file mode 100644 index 000000000..2dbbc4a82 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCONFIG.php @@ -0,0 +1,30 @@ +toArray() : []; + + $schema = array_reduce($schema, static function (array $carry, FieldInterface $field) { + return array_merge($carry, $field->toArray()); + }, []); + + array_unshift($schema, 'SCHEMA'); + + parent::setArguments(array_merge( + [$index], + $commandArguments, + $schema + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCURSOR.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCURSOR.php new file mode 100644 index 000000000..90b3d1d21 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTCURSOR.php @@ -0,0 +1,34 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$subcommand, $index, $cursorId], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDICTADD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDICTADD.php new file mode 100644 index 000000000..39c9d82c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTDICTADD.php @@ -0,0 +1,28 @@ +toArray(); + } + + parent::setArguments(array_merge( + [$index], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTEXPLAIN.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTEXPLAIN.php new file mode 100644 index 000000000..7c6878a4a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTEXPLAIN.php @@ -0,0 +1,43 @@ +toArray(); + } + + parent::setArguments(array_merge( + [$index, $query], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTINFO.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTINFO.php new file mode 100644 index 000000000..d4b86e170 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTINFO.php @@ -0,0 +1,28 @@ +toArray() + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSEARCH.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSEARCH.php new file mode 100644 index 000000000..6a10ee236 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSEARCH.php @@ -0,0 +1,39 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$index, $query], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSPELLCHECK.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSPELLCHECK.php new file mode 100644 index 000000000..b3939ca4b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSPELLCHECK.php @@ -0,0 +1,38 @@ +toArray(); + } + + parent::setArguments(array_merge( + [$index, $query], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGADD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGADD.php new file mode 100644 index 000000000..3a76fe0a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGADD.php @@ -0,0 +1,39 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key, $string, $score], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGDEL.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGDEL.php new file mode 100644 index 000000000..973282429 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGDEL.php @@ -0,0 +1,28 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key, $prefix], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGLEN.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGLEN.php new file mode 100644 index 000000000..46219332b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTSUGLEN.php @@ -0,0 +1,28 @@ +toArray(); + } + + $terms = array_slice($arguments, 3); + + parent::setArguments(array_merge( + [$index, $synonymGroupId], + $commandArguments, + $terms + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTTAGVALS.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTTAGVALS.php new file mode 100644 index 000000000..2fca9a921 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/Search/FTTAGVALS.php @@ -0,0 +1,28 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key, $timestamp, $value], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSALTER.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSALTER.php new file mode 100644 index 000000000..f91e9d04d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSALTER.php @@ -0,0 +1,39 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATE.php new file mode 100644 index 000000000..7cf73fa82 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATE.php @@ -0,0 +1,39 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATERULE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATERULE.php new file mode 100644 index 000000000..047c35cda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSCREATERULE.php @@ -0,0 +1,40 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key, $value], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSDEL.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSDEL.php new file mode 100644 index 000000000..86982cdaf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSDEL.php @@ -0,0 +1,28 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINCRBY.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINCRBY.php new file mode 100644 index 000000000..fbe570c00 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINCRBY.php @@ -0,0 +1,41 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key, $value], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINFO.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINFO.php new file mode 100644 index 000000000..ee259ab24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSINFO.php @@ -0,0 +1,39 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMADD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMADD.php new file mode 100644 index 000000000..af8d459a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMADD.php @@ -0,0 +1,28 @@ +toArray(); + + array_push($processedArguments, 'FILTER', ...$arguments); + + parent::setArguments(array_merge( + $commandArguments, + $processedArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMRANGE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMRANGE.php new file mode 100644 index 000000000..edce0d35c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMRANGE.php @@ -0,0 +1,39 @@ +toArray(); + + parent::setArguments(array_merge( + [$fromTimestamp, $toTimestamp], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMREVRANGE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMREVRANGE.php new file mode 100644 index 000000000..5937bb0c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSMREVRANGE.php @@ -0,0 +1,26 @@ +toArray() : []; + + parent::setArguments(array_merge( + [$key, $fromTimestamp, $toTimestamp], + $commandArguments + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSREVRANGE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSREVRANGE.php new file mode 100644 index 000000000..a1676d102 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TimeSeries/TSREVRANGE.php @@ -0,0 +1,26 @@ +filterArguments(); + } + + public function parseResponse($data) + { + if ($this->isWithCountModifier()) { + $result = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { + if (array_key_exists($i + 1, $data)) { + $result[(string) $data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } + + /** + * Checks for the presence of the WITHCOUNT modifier. + * + * @return bool + */ + private function isWithCountModifier(): bool + { + $arguments = $this->getArguments(); + $lastArgument = (!empty($arguments)) ? $arguments[count($arguments) - 1] : null; + + return is_string($lastArgument) && strtoupper($lastArgument) === 'WITHCOUNT'; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKQUERY.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKQUERY.php new file mode 100644 index 000000000..443a2117d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/TopK/TOPKQUERY.php @@ -0,0 +1,29 @@ + $val) { + $args[] = $key; + $args[] = $val; + } + } + + parent::setArguments($args); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XDEL.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XDEL.php new file mode 100644 index 000000000..dba7c6004 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/XDEL.php @@ -0,0 +1,39 @@ + $score) { + $arguments[] = $score; + $arguments[] = $member; + } + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZCARD.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZCARD.php new file mode 100644 index 000000000..d83ab619d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZCARD.php @@ -0,0 +1,29 @@ +setKeys($arguments); + $arguments = $this->getArguments(); + + $this->setWithScore($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZDIFFSTORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZDIFFSTORE.php new file mode 100644 index 000000000..ccae228e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZDIFFSTORE.php @@ -0,0 +1,40 @@ +setLimit($arguments); + $arguments = $this->getArguments(); + + $this->setKeys($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINTERSTORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINTERSTORE.php new file mode 100644 index 000000000..8b729c779 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZINTERSTORE.php @@ -0,0 +1,27 @@ +setCount($arguments); + $arguments = $this->getArguments(); + + $this->resolveModifier(static::$modifierArgumentPositionOffset, $arguments); + + $this->setKeys($arguments); + $arguments = $this->getArguments(); + + parent::setArguments($arguments); + } + + public function parseResponse($data) + { + $key = array_shift($data); + + if (null === $key) { + return [$key]; + } + + $data = $data[0]; + $parsedData = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; $i++) { + for ($j = 0, $jMax = count($data[$i]); $j < $jMax; ++$j) { + if ($data[$i][$j + 1] ?? false) { + $parsedData[$data[$i][$j]] = $data[$i][++$j]; + } + } + } + + return array_combine([$key], [$parsedData]); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZMSCORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZMSCORE.php new file mode 100644 index 000000000..8feb7ce90 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZMSCORE.php @@ -0,0 +1,34 @@ + true]; + $lastType = 'array'; + } + + if ($lastType === 'array') { + $options = $this->prepareOptions(array_pop($arguments)); + $arguments = array_merge($arguments, $options); + } + } + + parent::setArguments($arguments); + } + + /** + * Returns a list of options and modifiers compatible with Redis. + * + * @param array $options List of options. + * + * @return array + */ + protected function prepareOptions($options) + { + $opts = array_change_key_case($options, CASE_UPPER); + $finalizedOpts = []; + + if (!empty($opts['WITHSCORES'])) { + $finalizedOpts[] = 'WITHSCORES'; + } + + return $finalizedOpts; + } + + /** + * Checks for the presence of the WITHSCORES modifier. + * + * @return bool + */ + protected function withScores() + { + $arguments = $this->getArguments(); + + if (count($arguments) < 4) { + return false; + } + + return strtoupper($arguments[3]) === 'WITHSCORES'; + } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if ($this->withScores()) { + $result = []; + + for ($i = 0; $i < count($data); ++$i) { + if (is_array($data[$i])) { + $result[$data[$i][0]] = $data[$i][1]; // Relay + } else { + $result[$data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGEBYLEX.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGEBYLEX.php new file mode 100644 index 000000000..34e7e1e09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGEBYLEX.php @@ -0,0 +1,54 @@ +getArguments(); + + for ($i = 3; $i < count($arguments); ++$i) { + switch (strtoupper($arguments[$i])) { + case 'WITHSCORES': + return true; + + case 'LIMIT': + $i += 2; + break; + } + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGESTORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGESTORE.php new file mode 100644 index 000000000..ff1935238 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANGESTORE.php @@ -0,0 +1,57 @@ +setByLexByScoreArgument($arguments); + $arguments = $this->getArguments(); + + $this->setReversedArgument($arguments); + $arguments = $this->getArguments(); + + $this->setLimitArguments($arguments); + $this->filterArguments(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANK.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANK.php new file mode 100644 index 000000000..c734a71b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZRANK.php @@ -0,0 +1,29 @@ +prepareOptions(array_pop($arguments)); + $arguments = array_merge($arguments, $options); + } + + parent::setArguments($arguments); + } + + /** + * Returns a list of options and modifiers compatible with Redis. + * + * @param array $options List of options. + * + * @return array + */ + protected function prepareOptions($options) + { + $options = array_change_key_case($options, CASE_UPPER); + $normalized = []; + + if (!empty($options['MATCH'])) { + $normalized[] = 'MATCH'; + $normalized[] = $options['MATCH']; + } + + if (!empty($options['COUNT'])) { + $normalized[] = 'COUNT'; + $normalized[] = $options['COUNT']; + } + + return $normalized; + } + + /** + * {@inheritdoc} + */ + public function parseResponse($data) + { + if (is_array($data)) { + $members = $data[1]; + $result = []; + + for ($i = 0; $i < count($members); ++$i) { + $result[$members[$i]] = (float) $members[++$i]; + } + + $data[1] = $result; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZSCORE.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZSCORE.php new file mode 100644 index 000000000..5aeaf7ab5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Redis/ZSCORE.php @@ -0,0 +1,29 @@ +setAggregate($arguments); + $arguments = $this->getArguments(); + + $this->setWeights($arguments); + $arguments = $this->getArguments(); + + $this->setKeys($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/RedisFactory.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/RedisFactory.php new file mode 100644 index 000000000..c7d785a0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/RedisFactory.php @@ -0,0 +1,112 @@ +commands = [ + 'ECHO' => 'Predis\Command\Redis\ECHO_', + 'EVAL' => 'Predis\Command\Redis\EVAL_', + 'OBJECT' => 'Predis\Command\Redis\OBJECT_', + // Class name corresponds to PHP reserved word "function", added mapping to bypass restrictions + 'FUNCTION' => FUNCTIONS::class, + ]; + } + + /** + * {@inheritdoc} + */ + public function getCommandClass(string $commandID): ?string + { + $commandID = strtoupper($commandID); + + if (isset($this->commands[$commandID]) || array_key_exists($commandID, $this->commands)) { + return $this->commands[$commandID]; + } + + $commandClass = $this->resolve($commandID); + + if (null === $commandClass) { + return null; + } + + $this->commands[$commandID] = $commandClass; + + return $commandClass; + } + + /** + * {@inheritdoc} + */ + public function undefine(string $commandID): void + { + // NOTE: we explicitly associate `NULL` to the command ID in the map + // instead of the parent's `unset()` because our subclass tries to load + // a predefined class from the Predis\Command\Redis namespace when no + // explicit mapping is defined, see RedisFactory::getCommandClass() for + // details of the implementation of this mechanism. + $this->commands[strtoupper($commandID)] = null; + } + + /** + * Resolves command object from given command ID. + * + * @param string $commandID Command ID of virtual method call + * @return string|null FQDN of corresponding command object + */ + private function resolve(string $commandID): ?string + { + if (class_exists($commandClass = self::COMMANDS_NAMESPACE . '\\' . $commandID)) { + return $commandClass; + } + + $commandModule = $this->resolveCommandModuleByPrefix($commandID); + + if (null === $commandModule) { + return null; + } + + if (class_exists($commandClass = self::COMMANDS_NAMESPACE . '\\' . $commandModule . '\\' . $commandID)) { + return $commandClass; + } + + return null; + } + + private function resolveCommandModuleByPrefix(string $commandID): ?string + { + foreach (ClientConfiguration::getModules() as $module) { + if (preg_match("/^{$module['commandPrefix']}/", $commandID)) { + return $module['name']; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/ScriptCommand.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/ScriptCommand.php new file mode 100644 index 000000000..b9b845c63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/ScriptCommand.php @@ -0,0 +1,108 @@ +getScript()); + } + + /** + * Specifies the number of arguments that should be considered as keys. + * + * The default behaviour for the base class is to return 0 to indicate that + * all the elements of the arguments array should be considered as keys, but + * subclasses can enforce a static number of keys. + * + * @return int + */ + protected function getKeysCount() + { + return 0; + } + + /** + * Returns the elements from the arguments that are identified as keys. + * + * @return array + */ + public function getKeys() + { + return array_slice($this->getArguments(), 2, $this->getKeysCount()); + } + + /** + * {@inheritdoc} + */ + public function setArguments(array $arguments) + { + if (($numkeys = $this->getKeysCount()) && $numkeys < 0) { + $numkeys = count($arguments) + $numkeys; + } + + $arguments = array_merge([$this->getScriptHash(), (int) $numkeys], $arguments); + + parent::setArguments($arguments); + } + + /** + * Returns arguments for EVAL command. + * + * @return array + */ + public function getEvalArguments() + { + $arguments = $this->getArguments(); + $arguments[0] = $this->getScript(); + + return $arguments; + } + + /** + * Returns the equivalent EVAL command as a raw command instance. + * + * @return RawCommand + */ + public function getEvalCommand() + { + return new RawCommand('EVAL', $this->getEvalArguments()); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/DeleteStrategy.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/DeleteStrategy.php new file mode 100644 index 000000000..d759799e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Strategy/ContainerCommands/Functions/DeleteStrategy.php @@ -0,0 +1,26 @@ +separator = $separator; + } + + /** + * {@inheritDoc} + */ + public function resolve(string $commandId, string $subcommandId): SubcommandStrategyInterface + { + $subcommandStrategyClass = ucwords($subcommandId) . 'Strategy'; + $commandDirectoryName = ucwords($commandId); + + if (!is_null($this->separator)) { + $subcommandStrategyClass = str_replace($this->separator, '', $subcommandStrategyClass); + $commandDirectoryName = str_replace($this->separator, '', $commandDirectoryName); + } + + if (class_exists( + $containerCommandClass = self::CONTAINER_COMMANDS_NAMESPACE . '\\' . $commandDirectoryName . '\\' . $subcommandStrategyClass + )) { + return new $containerCommandClass(); + } + + throw new InvalidArgumentException('Non-existing container command given'); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Aggregate.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Aggregate.php new file mode 100644 index 000000000..79b8c6e9e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Aggregate.php @@ -0,0 +1,66 @@ + 'MIN', + 'max' => 'MAX', + 'sum' => 'SUM', + ]; + + /** + * @var string + */ + private static $aggregateModifier = 'AGGREGATE'; + + public function setArguments(array $arguments) + { + $argumentsLength = count($arguments); + + if (static::$aggregateArgumentPositionOffset >= $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$aggregateArgumentPositionOffset]; + + if (is_string($argument) && in_array(strtoupper($argument), self::$aggregateValuesEnum)) { + $argument = self::$aggregateValuesEnum[$argument]; + } else { + $enumValues = implode(', ', array_keys(self::$aggregateValuesEnum)); + throw new UnexpectedValueException("Aggregate argument accepts only: {$enumValues} values"); + } + + $argumentsBefore = array_slice($arguments, 0, static::$aggregateArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$aggregateArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$aggregateModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BitByte.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BitByte.php new file mode 100644 index 000000000..827c5320a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BitByte.php @@ -0,0 +1,40 @@ + 'BIT', + 'byte' => 'BYTE', + ]; + + public function setArguments(array $arguments) + { + $value = array_pop($arguments); + + if (null === $value) { + parent::setArguments($arguments); + + return; + } + + if (in_array(strtoupper($value), self::$argumentEnum, true)) { + $arguments[] = self::$argumentEnum[$value]; + } else { + $arguments[] = $value; + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/BucketSize.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/BucketSize.php new file mode 100644 index 000000000..a784b0931 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/BucketSize.php @@ -0,0 +1,57 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$bucketSizeArgumentPositionOffset] === -1) { + array_splice($arguments, static::$bucketSizeArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$bucketSizeArgumentPositionOffset] < 1) { + throw new UnexpectedValueException('Wrong bucket size argument value or position offset'); + } + + $argument = $arguments[static::$bucketSizeArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$bucketSizeArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$bucketSizeArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$bucketSizeModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Capacity.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Capacity.php new file mode 100644 index 000000000..f29ccc29e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Capacity.php @@ -0,0 +1,57 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$capacityArgumentPositionOffset] === -1) { + array_splice($arguments, static::$capacityArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$capacityArgumentPositionOffset] < 1) { + throw new UnexpectedValueException('Wrong capacity argument value or position offset'); + } + + $argument = $arguments[static::$capacityArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$capacityArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$capacityArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$capacityModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Error.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Error.php new file mode 100644 index 000000000..b410ec399 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Error.php @@ -0,0 +1,57 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$errorArgumentPositionOffset] === -1) { + array_splice($arguments, static::$errorArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$errorArgumentPositionOffset] < 0) { + throw new UnexpectedValueException('Wrong error argument value or position offset'); + } + + $argument = $arguments[static::$errorArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$errorArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$errorArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$errorModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Expansion.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Expansion.php new file mode 100644 index 000000000..1cd244d8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Expansion.php @@ -0,0 +1,53 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$expansionArgumentPositionOffset] === -1) { + array_splice($arguments, static::$expansionArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$expansionArgumentPositionOffset] < 1) { + throw new UnexpectedValueException('Wrong expansion argument value or position offset'); + } + + $argument = $arguments[static::$expansionArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$expansionArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$expansionArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$expansionModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Items.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Items.php new file mode 100644 index 000000000..198e6e083 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/Items.php @@ -0,0 +1,45 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$itemsArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$itemsArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$itemsArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$itemsModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/MaxIterations.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/MaxIterations.php new file mode 100644 index 000000000..e5ad76f39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/MaxIterations.php @@ -0,0 +1,57 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$maxIterationsArgumentPositionOffset] === -1) { + array_splice($arguments, static::$maxIterationsArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$maxIterationsArgumentPositionOffset] < 1) { + throw new UnexpectedValueException('Wrong max iterations argument value or position offset'); + } + + $argument = $arguments[static::$maxIterationsArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$maxIterationsArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$maxIterationsArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$maxIterationsModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/NoCreate.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/NoCreate.php new file mode 100644 index 000000000..d243afdd7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/BloomFilters/NoCreate.php @@ -0,0 +1,49 @@ += $argumentsLength + || false === $arguments[static::$noCreateArgumentPositionOffset] + ) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$noCreateArgumentPositionOffset]; + + if (true === $argument) { + $argument = 'NOCREATE'; + } else { + throw new UnexpectedValueException('Wrong NOCREATE argument type'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$noCreateArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$noCreateArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByArgument.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByArgument.php new file mode 100644 index 000000000..db8081047 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByArgument.php @@ -0,0 +1,40 @@ += $argumentsLength || null === $arguments[static::$byArgumentPositionOffset]) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$byArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$byArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$byArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$this->byModifier, $argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByLexByScore.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByLexByScore.php new file mode 100644 index 000000000..67ebfb6f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/ByLexByScore.php @@ -0,0 +1,49 @@ + 'BYLEX', + 'byscore' => 'BYSCORE', + ]; + + public function setArguments(array $arguments) + { + $argument = $arguments[static::$byLexByScoreArgumentPositionOffset]; + + if (false === $argument) { + parent::setArguments($arguments); + + return; + } + + if (is_string($argument) && in_array(strtoupper($argument), self::$argumentsEnum)) { + $argument = self::$argumentsEnum[$argument]; + } else { + throw new UnexpectedValueException('By argument accepts only "bylex" and "byscore" values'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$byLexByScoreArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$byLexByScoreArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/GeoBy.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/GeoBy.php new file mode 100644 index 000000000..d17613ef1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/By/GeoBy.php @@ -0,0 +1,49 @@ +getByArgumentPositionOffset($arguments); + + if (null === $argumentPositionOffset) { + throw new InvalidArgumentException('Invalid BY argument value given'); + } + + $byArgumentObject = $arguments[$argumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, $argumentPositionOffset); + $argumentsAfter = array_slice($arguments, $argumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + $byArgumentObject->toArray(), + $argumentsAfter + )); + } + + private function getByArgumentPositionOffset(array $arguments): ?int + { + foreach ($arguments as $i => $value) { + if ($value instanceof ByInterface) { + return $i; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Count.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Count.php new file mode 100644 index 000000000..c78e54418 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Count.php @@ -0,0 +1,71 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$countArgumentPositionOffset] === -1) { + array_splice($arguments, static::$countArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$countArgumentPositionOffset] < 1) { + throw new UnexpectedValueException('Wrong count argument value or position offset'); + } + + $countArgument = $arguments[static::$countArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$countArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$countArgumentPositionOffset + 2); + + if (!$any) { + $argumentsAfter = array_slice($arguments, static::$countArgumentPositionOffset + 1); + parent::setArguments(array_merge( + $argumentsBefore, + [$this->countModifier], + [$countArgument], + $argumentsAfter + )); + + return; + } + + parent::setArguments(array_merge( + $argumentsBefore, + [$this->countModifier], + [$countArgument], + [$this->anyModifier], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/DB.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/DB.php new file mode 100644 index 000000000..f113aa096 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/DB.php @@ -0,0 +1,53 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if (!is_numeric($arguments[static::$dbArgumentPositionOffset])) { + throw new UnexpectedValueException('DB argument should be a valid numeric value'); + } + + if ($arguments[static::$dbArgumentPositionOffset] < 0) { + array_splice($arguments, static::$dbArgumentPositionOffset, 1); + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$dbArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$dbArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$dbArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [$this->dbModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Expire/ExpireOptions.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Expire/ExpireOptions.php new file mode 100644 index 000000000..33dfb9e55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Expire/ExpireOptions.php @@ -0,0 +1,42 @@ + 'NX', + 'xx' => 'XX', + 'gt' => 'GT', + 'lt' => 'LT', + ]; + + public function setArguments(array $arguments) + { + $value = array_pop($arguments); + + if (null === $value) { + parent::setArguments($arguments); + + return; + } + + if (in_array(strtoupper($value), self::$argumentEnum, true)) { + $arguments[] = self::$argumentEnum[strtolower($value)]; + } else { + $arguments[] = $value; + } + + parent::setArguments($arguments); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/From/GeoFrom.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/From/GeoFrom.php new file mode 100644 index 000000000..3ef56ce68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/From/GeoFrom.php @@ -0,0 +1,49 @@ +getFromArgumentPositionOffset($arguments); + + if (null === $argumentPositionOffset) { + throw new InvalidArgumentException('Invalid FROM argument value given'); + } + + $fromArgumentObject = $arguments[$argumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, $argumentPositionOffset); + $argumentsAfter = array_slice($arguments, $argumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + $fromArgumentObject->toArray(), + $argumentsAfter + )); + } + + private function getFromArgumentPositionOffset(array $arguments): ?int + { + foreach ($arguments as $i => $value) { + if ($value instanceof FromInterface) { + return $i; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Get/Get.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Get/Get.php new file mode 100644 index 000000000..7d213d339 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Get/Get.php @@ -0,0 +1,47 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if (!is_array($arguments[static::$getArgumentPositionOffset])) { + throw new UnexpectedValueException('Wrong get argument type'); + } + + $patterns = []; + + foreach ($arguments[static::$getArgumentPositionOffset] as $pattern) { + $patterns[] = self::$getModifier; + $patterns[] = $pattern; + } + + $argumentsBeforeKeys = array_slice($arguments, 0, static::$getArgumentPositionOffset); + $argumentsAfterKeys = array_slice($arguments, static::$getArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBeforeKeys, $patterns, $argumentsAfterKeys)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Indent.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Indent.php new file mode 100644 index 000000000..25707adb7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Indent.php @@ -0,0 +1,54 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$indentArgumentPositionOffset] === '') { + array_splice($arguments, static::$indentArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$indentArgumentPositionOffset]; + + if (!is_string($argument)) { + throw new UnexpectedValueException('Indent argument value should be a string'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$indentArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$indentArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$indentModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Newline.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Newline.php new file mode 100644 index 000000000..170a0370c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Newline.php @@ -0,0 +1,54 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$newlineArgumentPositionOffset] === '') { + array_splice($arguments, static::$newlineArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$newlineArgumentPositionOffset]; + + if (!is_string($argument)) { + throw new UnexpectedValueException('Newline argument value should be a string'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$newlineArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$newlineArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$newlineModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/NxXxArgument.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/NxXxArgument.php new file mode 100644 index 000000000..40b9e32db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/NxXxArgument.php @@ -0,0 +1,64 @@ + 'NX', + 'xx' => 'XX', + ]; + + public function setArguments(array $arguments) + { + $argumentsLength = count($arguments); + + if (static::$nxXxArgumentPositionOffset >= $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if (null === $arguments[static::$nxXxArgumentPositionOffset]) { + array_splice($arguments, static::$nxXxArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$nxXxArgumentPositionOffset]; + + if (!in_array(strtoupper($argument), self::$argumentEnum, true)) { + $enumValues = implode(', ', array_keys(self::$argumentEnum)); + throw new UnexpectedValueException("Argument accepts only: {$enumValues} values"); + } + + $argumentsBefore = array_slice($arguments, 0, static::$nxXxArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$nxXxArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$argumentEnum[strtolower($argument)]], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Space.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Space.php new file mode 100644 index 000000000..acd77fa3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Json/Space.php @@ -0,0 +1,54 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$spaceArgumentPositionOffset] === '') { + array_splice($arguments, static::$spaceArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$spaceArgumentPositionOffset]; + + if (!is_string($argument)) { + throw new UnexpectedValueException('Space argument value should be a string'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$spaceArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$spaceArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$spaceModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Keys.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Keys.php new file mode 100644 index 000000000..42b8d1ef4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Keys.php @@ -0,0 +1,47 @@ + $argumentsLength + || !is_array($arguments[static::$keysArgumentPositionOffset]) + ) { + throw new UnexpectedValueException('Wrong keys argument type or position offset'); + } + + $keysArgument = $arguments[static::$keysArgumentPositionOffset]; + $argumentsBeforeKeys = array_slice($arguments, 0, static::$keysArgumentPositionOffset); + $argumentsAfterKeys = array_slice($arguments, static::$keysArgumentPositionOffset + 1); + + if ($withNumkeys) { + $numkeys = count($keysArgument); + parent::setArguments(array_merge($argumentsBeforeKeys, [$numkeys], $keysArgument, $argumentsAfterKeys)); + + return; + } + + parent::setArguments(array_merge($argumentsBeforeKeys, $keysArgument, $argumentsAfterKeys)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/LeftRight.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/LeftRight.php new file mode 100644 index 000000000..419548418 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/LeftRight.php @@ -0,0 +1,60 @@ + 'LEFT', + 'right' => 'RIGHT', + ]; + + public function setArguments(array $arguments) + { + $argumentsLength = count($arguments); + + if (static::$leftRightArgumentPositionOffset >= $argumentsLength) { + $arguments[] = 'LEFT'; + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$leftRightArgumentPositionOffset]; + + if (is_string($argument) && in_array(strtoupper($argument), self::$leftRightEnum, true)) { + $argument = self::$leftRightEnum[$argument]; + } else { + $enumValues = implode(', ', array_keys(self::$leftRightEnum)); + throw new UnexpectedValueException("Left/Right argument accepts only: {$enumValues} values"); + } + + $argumentsBefore = array_slice($arguments, 0, static::$leftRightArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$leftRightArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/Limit.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/Limit.php new file mode 100644 index 000000000..fd13e68e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/Limit.php @@ -0,0 +1,54 @@ += $argumentsLength + || false === $arguments[static::$limitArgumentPositionOffset] + ) { + parent::setArguments($argumentsBefore); + + return; + } + + $argument = $arguments[static::$limitArgumentPositionOffset]; + $argumentsAfter = array_slice($arguments, static::$limitArgumentPositionOffset + 1); + + if (true === $argument) { + parent::setArguments(array_merge($argumentsBefore, [self::$limitModifier], $argumentsAfter)); + + return; + } + + if (!is_int($argument)) { + throw new UnexpectedValueException('Wrong limit argument type'); + } + + parent::setArguments(array_merge($argumentsBefore, [self::$limitModifier], [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/LimitObject.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/LimitObject.php new file mode 100644 index 000000000..244b475c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Limit/LimitObject.php @@ -0,0 +1,50 @@ +getLimitArgumentPositionOffset($arguments); + + if (null === $argumentPositionOffset) { + parent::setArguments($arguments); + + return; + } + + $limitObject = $arguments[$argumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, $argumentPositionOffset); + $argumentsAfter = array_slice($arguments, $argumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + $limitObject->toArray(), + $argumentsAfter + )); + } + + private function getLimitArgumentPositionOffset(array $arguments): ?int + { + foreach ($arguments as $i => $value) { + if ($value instanceof LimitInterface) { + return $i; + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/MinMaxModifier.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/MinMaxModifier.php new file mode 100644 index 000000000..11ac7f2c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/MinMaxModifier.php @@ -0,0 +1,45 @@ + 'MIN', + 'max' => 'MAX', + ]; + + public function resolveModifier(int $offset, array &$arguments): void + { + if ($offset >= count($arguments)) { + $arguments[$offset] = $this->modifierEnum['min']; + + return; + } + + if (!is_string($arguments[$offset]) || !array_key_exists($arguments[$offset], $this->modifierEnum)) { + throw new UnexpectedValueException('Wrong type of modifier given'); + } + + $arguments[$offset] = $this->modifierEnum[$arguments[$offset]]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Replace.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Replace.php new file mode 100644 index 000000000..3753e6d7d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Replace.php @@ -0,0 +1,34 @@ + 'ASC', + 'desc' => 'DESC', + ]; + + public function setArguments(array $arguments) + { + $argumentsLength = count($arguments); + + if (static::$sortArgumentPositionOffset >= $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$sortArgumentPositionOffset]; + + if (null === $argument) { + array_splice($arguments, static::$sortArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if (!in_array(strtoupper($argument), self::$sortingEnum, true)) { + $enumValues = implode(', ', array_keys(self::$sortingEnum)); + throw new UnexpectedValueException("Sorting argument accepts only: {$enumValues} values"); + } + + $argumentsBefore = array_slice($arguments, 0, static::$sortArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$sortArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$sortingEnum[$argument]], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Storedist.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Storedist.php new file mode 100644 index 000000000..0b9856a32 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Storedist.php @@ -0,0 +1,49 @@ += $argumentsLength + || false === $arguments[static::$storeDistArgumentPositionOffset] + ) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$storeDistArgumentPositionOffset]; + + if (true === $argument) { + $argument = 'STOREDIST'; + } else { + throw new UnexpectedValueException('Wrong STOREDIST argument type'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$storeDistArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$storeDistArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Timeout.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Timeout.php new file mode 100644 index 000000000..62b1c9f40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Timeout.php @@ -0,0 +1,53 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$timeoutArgumentPositionOffset] === -1) { + array_splice($arguments, static::$timeoutArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + if ($arguments[static::$timeoutArgumentPositionOffset] < 1) { + throw new UnexpectedValueException('Wrong timeout argument value or position offset'); + } + + $argument = $arguments[static::$timeoutArgumentPositionOffset]; + $argumentsBefore = array_slice($arguments, 0, static::$timeoutArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$timeoutArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$timeoutModifier], + [$argument], + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/To/ServerTo.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/To/ServerTo.php new file mode 100644 index 000000000..1bcdccb2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/To/ServerTo.php @@ -0,0 +1,48 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + /** @var To|null $toArgument */ + $toArgument = $arguments[static::$toArgumentPositionOffset]; + + if (null === $toArgument) { + array_splice($arguments, static::$toArgumentPositionOffset, 1, [false]); + parent::setArguments($arguments); + + return; + } + + $argumentsBefore = array_slice($arguments, 0, static::$toArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$toArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + $toArgument->toArray(), + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Weights.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Weights.php new file mode 100644 index 000000000..7df8ac8ef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/Weights.php @@ -0,0 +1,61 @@ += $argumentsLength) { + parent::setArguments($arguments); + + return; + } + + if (!is_array($arguments[static::$weightsArgumentPositionOffset])) { + throw new UnexpectedValueException('Wrong weights argument type'); + } + + $weightsArray = $arguments[static::$weightsArgumentPositionOffset]; + + if (empty($weightsArray)) { + unset($arguments[static::$weightsArgumentPositionOffset]); + parent::setArguments($arguments); + + return; + } + + $argumentsBefore = array_slice($arguments, 0, static::$weightsArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$weightsArgumentPositionOffset + 1); + + parent::setArguments(array_merge( + $argumentsBefore, + [self::$weightsModifier], + $weightsArray, + $argumentsAfter + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithCoord.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithCoord.php new file mode 100644 index 000000000..a2b982eea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithCoord.php @@ -0,0 +1,49 @@ += $argumentsLength + || false === $arguments[static::$withCoordArgumentPositionOffset] + ) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$withCoordArgumentPositionOffset]; + + if (true === $argument) { + $argument = 'WITHCOORD'; + } else { + throw new UnexpectedValueException('Wrong WITHCOORD argument type'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$withCoordArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$withCoordArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithDist.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithDist.php new file mode 100644 index 000000000..25c99f293 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithDist.php @@ -0,0 +1,45 @@ += $argumentsLength + || false === $arguments[static::$withDistArgumentPositionOffset] + ) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$withDistArgumentPositionOffset]; + + if (true === $argument) { + $argument = 'WITHDIST'; + } else { + throw new UnexpectedValueException('Wrong WITHDIST argument type'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$withDistArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$withDistArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithHash.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithHash.php new file mode 100644 index 000000000..05647c72d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithHash.php @@ -0,0 +1,45 @@ += $argumentsLength + || false === $arguments[static::$withHashArgumentPositionOffset] + ) { + parent::setArguments($arguments); + + return; + } + + $argument = $arguments[static::$withHashArgumentPositionOffset]; + + if (true === $argument) { + $argument = 'WITHHASH'; + } else { + throw new UnexpectedValueException('Wrong WITHHASH argument type'); + } + + $argumentsBefore = array_slice($arguments, 0, static::$withHashArgumentPositionOffset); + $argumentsAfter = array_slice($arguments, static::$withHashArgumentPositionOffset + 1); + + parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter)); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithScores.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithScores.php new file mode 100644 index 000000000..e8872386f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithScores.php @@ -0,0 +1,68 @@ +isWithScoreModifier()) { + $result = []; + + for ($i = 0, $iMax = count($data); $i < $iMax; ++$i) { + if (is_array($data[$i])) { + $result[$data[$i][0]] = $data[$i][1]; // Relay + } elseif (array_key_exists($i + 1, $data)) { + $result[$data[$i]] = $data[++$i]; + } + } + + return $result; + } + + return $data; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithValues.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithValues.php new file mode 100644 index 000000000..70900d438 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Command/Traits/With/WithValues.php @@ -0,0 +1,34 @@ +connection = $connection; + } + + /** + * Gets the connection that generated the exception. + * + * @return NodeConnectionInterface + */ + public function getConnection() + { + return $this->connection; + } + + /** + * Indicates if the receiver should reset the underlying connection. + * + * @return bool + */ + public function shouldResetConnection() + { + return true; + } + + /** + * Helper method to handle exceptions generated by a connection object. + * + * @param CommunicationException $exception Exception. + * + * @throws CommunicationException + */ + public static function handle(CommunicationException $exception) + { + if ($exception->shouldResetConnection()) { + $connection = $exception->getConnection(); + + if ($connection->isConnected()) { + $connection->disconnect(); + } + } + + throw $exception; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Aggregate.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Aggregate.php new file mode 100644 index 000000000..76b623b25 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Aggregate.php @@ -0,0 +1,114 @@ +getConnectionInitializer($options, $value); + } + + /** + * Wraps a user-supplied callable used to create a new aggregate connection. + * + * When the original callable acting as a connection initializer is executed + * by the client to create a new aggregate connection, it will receive the + * following arguments: + * + * - $parameters (same as passed to Predis\Client::__construct()) + * - $options (options container, Predis\Configuration\OptionsInterface) + * - $option (current option, Predis\Configuration\OptionInterface) + * + * The original callable must return a valid aggregation connection instance + * of type Predis\Connection\AggregateConnectionInterface, this is enforced + * by the wrapper returned by this method and an exception is thrown when + * invalid values are returned. + * + * @param OptionsInterface $options Client options + * @param callable $callable Callable initializer + * + * @return callable + * @throws InvalidArgumentException + */ + protected function getConnectionInitializer(OptionsInterface $options, callable $callable) + { + return function ($parameters = null, $autoaggregate = false) use ($callable, $options) { + $connection = call_user_func_array($callable, [&$parameters, $options, $this]); + + if (!$connection instanceof AggregateConnectionInterface) { + throw new InvalidArgumentException(sprintf( + '%s expects the supplied callable to return an instance of %s, but %s was returned', + static::class, + AggregateConnectionInterface::class, + is_object($connection) ? get_class($connection) : gettype($connection) + )); + } + + if ($parameters && $autoaggregate) { + static::aggregate($options, $connection, $parameters); + } + + return $connection; + }; + } + + /** + * Adds single connections to an aggregate connection instance. + * + * @param OptionsInterface $options Client options + * @param AggregateConnectionInterface $connection Target aggregate connection + * @param array $nodes List of nodes to be added to the target aggregate connection + */ + public static function aggregate(OptionsInterface $options, AggregateConnectionInterface $connection, array $nodes) + { + $connections = $options->connections; + + foreach ($nodes as $node) { + $connection->add($node instanceof NodeConnectionInterface ? $node : $connections->create($node)); + } + } + + /** + * {@inheritdoc} + */ + public function getDefault(OptionsInterface $options) + { + return; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/CRC16.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/CRC16.php new file mode 100644 index 000000000..1b3f10939 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/CRC16.php @@ -0,0 +1,74 @@ +getHashGeneratorByDescription($options, $value); + } elseif ($value instanceof Hash\HashGeneratorInterface) { + return $value; + } else { + $class = get_class($this); + throw new InvalidArgumentException("$class expects a valid hash generator"); + } + } + + /** + * {@inheritdoc} + */ + public function getDefault(OptionsInterface $options) + { + return function_exists('phpiredis_utils_crc16') + ? new Hash\PhpiredisCRC16() + : new Hash\CRC16(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Cluster.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Cluster.php new file mode 100644 index 000000000..c3c505529 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Cluster.php @@ -0,0 +1,99 @@ +getConnectionInitializerByString($options, $value); + } + + if (is_callable($value)) { + return $this->getConnectionInitializer($options, $value); + } else { + throw new InvalidArgumentException(sprintf( + '%s expects either a string or a callable value, %s given', + static::class, + is_object($value) ? get_class($value) : gettype($value) + )); + } + } + + /** + * Returns a connection initializer from a descriptive name. + * + * @param OptionsInterface $options Client options + * @param string $description Identifier of a replication backend (`predis`, `sentinel`) + * + * @return callable + */ + protected function getConnectionInitializerByString(OptionsInterface $options, string $description) + { + switch ($description) { + case 'redis': + case 'redis-cluster': + return function ($parameters, $options, $option) { + return new RedisCluster($options->connections, new RedisStrategy($options->crc16)); + }; + + case 'predis': + return $this->getDefaultConnectionInitializer(); + + default: + throw new InvalidArgumentException(sprintf( + '%s expects either `predis`, `redis` or `redis-cluster` as valid string values, `%s` given', + static::class, + $description + )); + } + } + + /** + * Returns the default connection initializer. + * + * @return callable + */ + protected function getDefaultConnectionInitializer() + { + return function ($parameters, $options, $option) { + return new PredisCluster(); + }; + } + + /** + * {@inheritdoc} + */ + public function getDefault(OptionsInterface $options) + { + return $this->getConnectionInitializer( + $options, + $this->getDefaultConnectionInitializer() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Commands.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Commands.php new file mode 100644 index 000000000..6f9a31b33 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Commands.php @@ -0,0 +1,146 @@ +createFactoryByArray($options, $value); + } elseif (is_string($value)) { + return $this->createFactoryByString($options, $value); + } else { + throw new InvalidArgumentException(sprintf( + '%s expects a valid command factory', + static::class + )); + } + } + + /** + * Creates a new default command factory from a named array. + * + * The factory instance is configured according to the supplied named array + * mapping command IDs (passed as keys) to the FCQN of classes implementing + * Predis\Command\CommandInterface. + * + * @param OptionsInterface $options Client options container + * @param array $value Named array mapping command IDs to classes + * + * @return FactoryInterface + */ + protected function createFactoryByArray(OptionsInterface $options, array $value) + { + /** + * @var FactoryInterface + */ + $commands = $this->getDefault($options); + + foreach ($value as $commandID => $commandClass) { + if ($commandClass === null) { + $commands->undefine($commandID); + } else { + $commands->define($commandID, $commandClass); + } + } + + return $commands; + } + + /** + * Creates a new command factory from a descriptive string. + * + * The factory instance is configured according to the supplied descriptive + * string that identifies specific configurations of schemes and connection + * classes. Supported configuration values are: + * + * - "predis" returns the default command factory used by Predis + * - "raw" returns a command factory that creates only raw commands + * - "default" is simply an alias of "predis" + * + * @param OptionsInterface $options Client options container + * @param string $value Descriptive string identifying the desired configuration + * + * @return FactoryInterface + */ + protected function createFactoryByString(OptionsInterface $options, string $value) + { + switch (strtolower($value)) { + case 'default': + case 'predis': + return $this->getDefault($options); + + case 'raw': + return $this->createRawFactory($options); + + default: + throw new InvalidArgumentException(sprintf( + '%s does not recognize `%s` as a supported configuration string', + static::class, + $value + )); + } + } + + /** + * Creates a new raw command factory instance. + * + * @param OptionsInterface $options Client options container + */ + protected function createRawFactory(OptionsInterface $options): FactoryInterface + { + $commands = new RawFactory(); + + if (isset($options->prefix)) { + throw new InvalidArgumentException(sprintf( + '%s does not support key prefixing', RawFactory::class + )); + } + + return $commands; + } + + /** + * {@inheritdoc} + */ + public function getDefault(OptionsInterface $options) + { + $commands = new RedisFactory(); + + if (isset($options->prefix)) { + $commands->setProcessor($options->prefix); + } + + return $commands; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Connections.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Connections.php new file mode 100644 index 000000000..40988feda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Connections.php @@ -0,0 +1,152 @@ +createFactoryByArray($options, $value); + } elseif (is_string($value)) { + return $this->createFactoryByString($options, $value); + } else { + throw new InvalidArgumentException(sprintf( + '%s expects a valid connection factory', static::class + )); + } + } + + /** + * Creates a new connection factory from a named array. + * + * The factory instance is configured according to the supplied named array + * mapping URI schemes (passed as keys) to the FCQN of classes implementing + * Predis\Connection\NodeConnectionInterface, or callable objects acting as + * lazy initializers and returning new instances of classes implementing + * Predis\Connection\NodeConnectionInterface. + * + * @param OptionsInterface $options Client options + * @param array $value Named array mapping URI schemes to classes or callables + * + * @return FactoryInterface + */ + protected function createFactoryByArray(OptionsInterface $options, array $value) + { + /** + * @var FactoryInterface + */ + $factory = $this->getDefault($options); + + foreach ($value as $scheme => $initializer) { + $factory->define($scheme, $initializer); + } + + return $factory; + } + + /** + * Creates a new connection factory from a descriptive string. + * + * The factory instance is configured according to the supplied descriptive + * string that identifies specific configurations of schemes and connection + * classes. Supported configuration values are: + * + * - "phpiredis-stream" maps tcp, redis, unix to PhpiredisStreamConnection + * - "phpiredis-socket" maps tcp, redis, unix to PhpiredisSocketConnection + * - "phpiredis" is an alias of "phpiredis-stream" + * - "relay" maps tcp, redis, unix, tls, rediss to RelayConnection + * + * @param OptionsInterface $options Client options + * @param string $value Descriptive string identifying the desired configuration + * + * @return FactoryInterface + */ + protected function createFactoryByString(OptionsInterface $options, string $value) + { + /** + * @var FactoryInterface + */ + $factory = $this->getDefault($options); + + switch (strtolower($value)) { + case 'phpiredis': + case 'phpiredis-stream': + $factory->define('tcp', PhpiredisStreamConnection::class); + $factory->define('redis', PhpiredisStreamConnection::class); + $factory->define('unix', PhpiredisStreamConnection::class); + break; + + case 'phpiredis-socket': + $factory->define('tcp', PhpiredisSocketConnection::class); + $factory->define('redis', PhpiredisSocketConnection::class); + $factory->define('unix', PhpiredisSocketConnection::class); + break; + + case 'relay': + $factory->define('tcp', RelayConnection::class); + $factory->define('redis', RelayConnection::class); + $factory->define('unix', RelayConnection::class); + break; + + case 'default': + return $factory; + + default: + throw new InvalidArgumentException(sprintf( + '%s does not recognize `%s` as a supported configuration string', static::class, $value + )); + } + + return $factory; + } + + /** + * {@inheritdoc} + */ + public function getDefault(OptionsInterface $options) + { + $factory = new Factory(); + + if ($options->defined('parameters')) { + $factory->setDefaultParameters($options->parameters); + } + + return $factory; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Exceptions.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Exceptions.php new file mode 100644 index 000000000..2a7798456 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/Option/Exceptions.php @@ -0,0 +1,39 @@ +getConnectionInitializerByString($options, $value); + } + + if (is_callable($value)) { + return $this->getConnectionInitializer($options, $value); + } else { + throw new InvalidArgumentException(sprintf( + '%s expects either a string or a callable value, %s given', + static::class, + is_object($value) ? get_class($value) : gettype($value) + )); + } + } + + /** + * Returns a connection initializer (callable) from a descriptive string. + * + * Each connection initializer is specialized for the specified replication + * backend so that all the necessary steps for the configuration of the new + * aggregate connection are performed inside the initializer and the client + * receives a ready-to-use connection. + * + * Supported configuration values are: + * + * - `predis` for unmanaged replication setups + * - `redis-sentinel` for replication setups managed by redis-sentinel + * - `sentinel` is an alias of `redis-sentinel` + * + * @param OptionsInterface $options Client options + * @param string $description Identifier of a replication backend + * + * @return callable + */ + protected function getConnectionInitializerByString(OptionsInterface $options, string $description) + { + switch ($description) { + case 'sentinel': + case 'redis-sentinel': + return function ($parameters, $options) { + return new SentinelReplication($options->service, $parameters, $options->connections); + }; + + case 'predis': + return $this->getDefaultConnectionInitializer(); + + default: + throw new InvalidArgumentException(sprintf( + '%s expects either `predis`, `sentinel` or `redis-sentinel` as valid string values, `%s` given', + static::class, + $description + )); + } + } + + /** + * Returns the default connection initializer. + * + * @return callable + */ + protected function getDefaultConnectionInitializer() + { + return function ($parameters, $options) { + $connection = new MasterSlaveReplication(); + + if ($options->autodiscovery) { + $connection->setConnectionFactory($options->connections); + $connection->setAutoDiscovery(true); + } + + return $connection; + }; + } + + /** + * {@inheritdoc} + */ + public static function aggregate(OptionsInterface $options, AggregateConnectionInterface $connection, array $nodes) + { + if (!$connection instanceof SentinelReplication) { + parent::aggregate($options, $connection, $nodes); + } + } + + /** + * {@inheritdoc} + */ + public function getDefault(OptionsInterface $options) + { + return $this->getConnectionInitializer( + $options, + $this->getDefaultConnectionInitializer() + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionInterface.php new file mode 100644 index 000000000..6250216a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionInterface.php @@ -0,0 +1,39 @@ + Option\Aggregate::class, + 'cluster' => Option\Cluster::class, + 'replication' => Option\Replication::class, + 'connections' => Option\Connections::class, + 'commands' => Option\Commands::class, + 'exceptions' => Option\Exceptions::class, + 'prefix' => Option\Prefix::class, + 'crc16' => Option\CRC16::class, + ]; + + /** @var array */ + protected $options = []; + + /** @var array */ + protected $input; + + /** + * @param array|null $options Named array of client options + */ + public function __construct(?array $options = null) + { + $this->input = $options ?? []; + } + + /** + * {@inheritdoc} + */ + public function getDefault($option) + { + if (isset($this->handlers[$option])) { + $handler = $this->handlers[$option]; + $handler = new $handler(); + + return $handler->getDefault($this); + } + } + + /** + * {@inheritdoc} + */ + public function defined($option) + { + return + array_key_exists($option, $this->options) + || array_key_exists($option, $this->input) + ; + } + + /** + * {@inheritdoc} + */ + public function __isset($option) + { + return ( + array_key_exists($option, $this->options) + || array_key_exists($option, $this->input) + ) && $this->__get($option) !== null; + } + + /** + * {@inheritdoc} + */ + public function __get($option) + { + if (isset($this->options[$option]) || array_key_exists($option, $this->options)) { + return $this->options[$option]; + } + + if (isset($this->input[$option]) || array_key_exists($option, $this->input)) { + $value = $this->input[$option]; + unset($this->input[$option]); + + if (isset($this->handlers[$option])) { + $handler = $this->handlers[$option]; + $handler = new $handler(); + $value = $handler->filter($this, $value); + } elseif (is_object($value) && method_exists($value, '__invoke')) { + $value = $value($this); + } + + return $this->options[$option] = $value; + } + + if (isset($this->handlers[$option])) { + return $this->options[$option] = $this->getDefault($option); + } + + return; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionsInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionsInterface.php new file mode 100644 index 000000000..96fd647ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Configuration/OptionsInterface.php @@ -0,0 +1,63 @@ +parameters = $this->assertParameters($parameters); + } + + /** + * Disconnects from the server and destroys the underlying resource when + * PHP's garbage collector kicks in. + */ + public function __destruct() + { + $this->disconnect(); + } + + /** + * Checks some of the parameters used to initialize the connection. + * + * @param ParametersInterface $parameters Initialization parameters for the connection. + * + * @return ParametersInterface + * @throws InvalidArgumentException + */ + abstract protected function assertParameters(ParametersInterface $parameters); + + /** + * Creates the underlying resource used to communicate with Redis. + * + * @return mixed + */ + abstract protected function createResource(); + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return isset($this->resource); + } + + /** + * {@inheritdoc} + */ + public function connect() + { + if (!$this->isConnected()) { + $this->resource = $this->createResource(); + + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + unset($this->resource); + } + + /** + * {@inheritdoc} + */ + public function addConnectCommand(CommandInterface $command) + { + $this->initCommands[] = $command; + } + + /** + * {@inheritdoc} + */ + public function getInitCommands(): array + { + return $this->initCommands; + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + $this->writeRequest($command); + + return $this->readResponse($command); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + return $this->read(); + } + + /** + * Helper method to handle connection errors. + * + * @param string $message Error message. + * @param int $code Error code. + */ + protected function onConnectionError($message, $code = 0) + { + CommunicationException::handle( + new ConnectionException($this, "$message [{$this->getParameters()}]", $code) + ); + } + + /** + * Helper method to handle protocol errors. + * + * @param string $message Error message. + */ + protected function onProtocolError($message) + { + CommunicationException::handle( + new ProtocolException($this, "$message [{$this->getParameters()}]") + ); + } + + /** + * {@inheritdoc} + */ + public function getResource() + { + if (isset($this->resource)) { + return $this->resource; + } + + $this->connect(); + + return $this->resource; + } + + /** + * {@inheritdoc} + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Gets an identifier for the connection. + * + * @return string + */ + protected function getIdentifier() + { + if ($this->parameters->scheme === 'unix') { + return $this->parameters->path; + } + + return "{$this->parameters->host}:{$this->parameters->port}"; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + if (!isset($this->cachedId)) { + $this->cachedId = $this->getIdentifier(); + } + + return $this->cachedId; + } + + /** + * {@inheritdoc} + */ + public function __sleep() + { + return ['parameters', 'initCommands']; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/AggregateConnectionInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/AggregateConnectionInterface.php new file mode 100644 index 000000000..e5849ef55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/AggregateConnectionInterface.php @@ -0,0 +1,56 @@ +strategy = $strategy ?: new PredisStrategy(); + $this->distributor = $this->strategy->getDistributor(); + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + foreach ($this->pool as $connection) { + if ($connection->isConnected()) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function connect() + { + foreach ($this->pool as $connection) { + $connection->connect(); + } + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + foreach ($this->pool as $connection) { + $connection->disconnect(); + } + } + + /** + * {@inheritdoc} + */ + public function add(NodeConnectionInterface $connection) + { + $parameters = $connection->getParameters(); + + $this->pool[(string) $connection] = $connection; + + if (isset($parameters->alias)) { + $this->aliases[$parameters->alias] = $connection; + } + + $this->distributor->add($connection, $parameters->weight); + } + + /** + * {@inheritdoc} + */ + public function remove(NodeConnectionInterface $connection) + { + if (false !== $id = array_search($connection, $this->pool, true)) { + unset($this->pool[$id]); + $this->distributor->remove($connection); + + if ($this->aliases && $alias = $connection->getParameters()->alias) { + unset($this->aliases[$alias]); + } + + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getConnectionByCommand(CommandInterface $command) + { + $slot = $this->strategy->getSlot($command); + + if (!isset($slot)) { + throw new NotSupportedException( + "Cannot use '{$command->getId()}' over clusters of connections." + ); + } + + return $this->distributor->getBySlot($slot); + } + + /** + * {@inheritdoc} + */ + public function getConnectionById($id) + { + return $this->pool[$id] ?? null; + } + + /** + * Returns a connection instance by its alias. + * + * @param string $alias Connection alias. + * + * @return NodeConnectionInterface|null + */ + public function getConnectionByAlias($alias) + { + return $this->aliases[$alias] ?? null; + } + + /** + * Retrieves a connection instance by slot. + * + * @param string $slot Slot name. + * + * @return NodeConnectionInterface|null + */ + public function getConnectionBySlot($slot) + { + return $this->distributor->getBySlot($slot); + } + + /** + * Retrieves a connection instance from the cluster using a key. + * + * @param string $key Key string. + * + * @return NodeConnectionInterface + */ + public function getConnectionByKey($key) + { + $hash = $this->strategy->getSlotByKey($key); + + return $this->distributor->getBySlot($hash); + } + + /** + * Returns the underlying command hash strategy used to hash commands by + * using keys found in their arguments. + * + * @return StrategyInterface + */ + public function getClusterStrategy() + { + return $this->strategy; + } + + /** + * @return int + */ + #[ReturnTypeWillChange] + public function count() + { + return count($this->pool); + } + + /** + * @return Traversable + */ + #[ReturnTypeWillChange] + public function getIterator() + { + return new ArrayIterator($this->pool); + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $this->getConnectionByCommand($command)->writeRequest($command); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + return $this->getConnectionByCommand($command)->readResponse($command); + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + return $this->getConnectionByCommand($command)->executeCommand($command); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Cluster/RedisCluster.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Cluster/RedisCluster.php new file mode 100644 index 000000000..ddcb5da63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Cluster/RedisCluster.php @@ -0,0 +1,681 @@ += 3.0.0). + * + * This connection backend offers smart support for redis-cluster by handling + * automatic slots map (re)generation upon -MOVED or -ASK responses returned by + * Redis when redirecting a client to a different node. + * + * The cluster can be pre-initialized using only a subset of the actual nodes in + * the cluster, Predis will do the rest by adjusting the slots map and creating + * the missing underlying connection instances on the fly. + * + * It is possible to pre-associate connections to a slots range with the "slots" + * parameter in the form "$first-$last". This can greatly reduce runtime node + * guessing and redirections. + * + * It is also possible to ask for the full and updated slots map directly to one + * of the nodes and optionally enable such a behaviour upon -MOVED redirections. + * Asking for the cluster configuration to Redis is actually done by issuing a + * CLUSTER SLOTS command to a random node in the pool. + */ +class RedisCluster implements ClusterInterface, IteratorAggregate, Countable +{ + private $useClusterSlots = true; + private $pool = []; + private $slots = []; + private $slotmap; + private $strategy; + private $connections; + private $retryLimit = 5; + private $retryInterval = 10; + + /** + * @param FactoryInterface $connections Optional connection factory. + * @param StrategyInterface|null $strategy Optional cluster strategy. + */ + public function __construct( + FactoryInterface $connections, + ?StrategyInterface $strategy = null + ) { + $this->connections = $connections; + $this->strategy = $strategy ?: new RedisClusterStrategy(); + $this->slotmap = new SlotMap(); + } + + /** + * Sets the maximum number of retries for commands upon server failure. + * + * -1 = unlimited retry attempts + * 0 = no retry attempts (fails immediately) + * n = fail only after n retry attempts + * + * @param int $retry Number of retry attempts. + */ + public function setRetryLimit($retry) + { + $this->retryLimit = (int) $retry; + } + + /** + * Sets the initial retry interval (milliseconds). + * + * @param int $retryInterval Milliseconds between retries. + */ + public function setRetryInterval($retryInterval) + { + $this->retryInterval = (int) $retryInterval; + } + + /** + * Returns the retry interval (milliseconds). + * + * @return int Milliseconds between retries. + */ + public function getRetryInterval() + { + return (int) $this->retryInterval; + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + foreach ($this->pool as $connection) { + if ($connection->isConnected()) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function connect() + { + if ($connection = $this->getRandomConnection()) { + $connection->connect(); + } + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + foreach ($this->pool as $connection) { + $connection->disconnect(); + } + } + + /** + * {@inheritdoc} + */ + public function add(NodeConnectionInterface $connection) + { + $this->pool[(string) $connection] = $connection; + $this->slotmap->reset(); + } + + /** + * {@inheritdoc} + */ + public function remove(NodeConnectionInterface $connection) + { + if (false !== $id = array_search($connection, $this->pool, true)) { + $this->slotmap->reset(); + $this->slots = array_diff($this->slots, [$connection]); + unset($this->pool[$id]); + + return true; + } + + return false; + } + + /** + * Removes a connection instance by using its identifier. + * + * @param string $connectionID Connection identifier. + * + * @return bool True if the connection was in the pool. + */ + public function removeById($connectionID) + { + if (isset($this->pool[$connectionID])) { + $this->slotmap->reset(); + $this->slots = array_diff($this->slots, [$connectionID]); + unset($this->pool[$connectionID]); + + return true; + } + + return false; + } + + /** + * Generates the current slots map by guessing the cluster configuration out + * of the connection parameters of the connections in the pool. + * + * Generation is based on the same algorithm used by Redis to generate the + * cluster, so it is most effective when all of the connections supplied on + * initialization have the "slots" parameter properly set accordingly to the + * current cluster configuration. + */ + public function buildSlotMap() + { + $this->slotmap->reset(); + + foreach ($this->pool as $connectionID => $connection) { + $parameters = $connection->getParameters(); + + if (!isset($parameters->slots)) { + continue; + } + + foreach (explode(',', $parameters->slots) as $slotRange) { + $slots = explode('-', $slotRange, 2); + + if (!isset($slots[1])) { + $slots[1] = $slots[0]; + } + + $this->slotmap->setSlots($slots[0], $slots[1], $connectionID); + } + } + } + + /** + * Queries the specified node of the cluster to fetch the updated slots map. + * + * When the connection fails, this method tries to execute the same command + * on a different connection picked at random from the pool of known nodes, + * up until the retry limit is reached. + * + * @param NodeConnectionInterface $connection Connection to a node of the cluster. + * + * @return mixed + */ + private function queryClusterNodeForSlotMap(NodeConnectionInterface $connection) + { + $retries = 0; + $retryAfter = $this->retryInterval; + $command = RawCommand::create('CLUSTER', 'SLOTS'); + + while ($retries <= $this->retryLimit) { + try { + $response = $connection->executeCommand($command); + break; + } catch (ConnectionException $exception) { + $connection = $exception->getConnection(); + $connection->disconnect(); + + $this->remove($connection); + + if ($retries === $this->retryLimit) { + throw $exception; + } + + if (!$connection = $this->getRandomConnection()) { + throw new ClientException('No connections left in the pool for `CLUSTER SLOTS`'); + } + + usleep($retryAfter * 1000); + $retryAfter *= 2; + ++$retries; + } + } + + return $response; + } + + /** + * Generates an updated slots map fetching the cluster configuration using + * the CLUSTER SLOTS command against the specified node or a random one from + * the pool. + * + * @param NodeConnectionInterface|null $connection Optional connection instance. + */ + public function askSlotMap(?NodeConnectionInterface $connection = null) + { + if (!$connection && !$connection = $this->getRandomConnection()) { + return; + } + + $this->slotmap->reset(); + + $response = $this->queryClusterNodeForSlotMap($connection); + + foreach ($response as $slots) { + // We only support master servers for now, so we ignore subsequent + // elements in the $slots array identifying slaves. + [$start, $end, $master] = $slots; + + if ($master[0] === '') { + $this->slotmap->setSlots($start, $end, (string) $connection); + } else { + $this->slotmap->setSlots($start, $end, "{$master[0]}:{$master[1]}"); + } + } + } + + /** + * Guesses the correct node associated to a given slot using a precalculated + * slots map, falling back to the same logic used by Redis to initialize a + * cluster (best-effort). + * + * @param int $slot Slot index. + * + * @return string Connection ID. + */ + protected function guessNode($slot) + { + if (!$this->pool) { + throw new ClientException('No connections available in the pool'); + } + + if ($this->slotmap->isEmpty()) { + $this->buildSlotMap(); + } + + if ($node = $this->slotmap[$slot]) { + return $node; + } + + $count = count($this->pool); + $index = min((int) ($slot / (int) (16384 / $count)), $count - 1); + $nodes = array_keys($this->pool); + + return $nodes[$index]; + } + + /** + * Creates a new connection instance from the given connection ID. + * + * @param string $connectionID Identifier for the connection. + * + * @return NodeConnectionInterface + */ + protected function createConnection($connectionID) + { + $separator = strrpos($connectionID, ':'); + + return $this->connections->create([ + 'host' => substr($connectionID, 0, $separator), + 'port' => substr($connectionID, $separator + 1), + ]); + } + + /** + * {@inheritdoc} + */ + public function getConnectionByCommand(CommandInterface $command) + { + $slot = $this->strategy->getSlot($command); + + if (!isset($slot)) { + throw new NotSupportedException( + "Cannot use '{$command->getId()}' with redis-cluster." + ); + } + + if (isset($this->slots[$slot])) { + return $this->slots[$slot]; + } else { + return $this->getConnectionBySlot($slot); + } + } + + /** + * Returns the connection currently associated to a given slot. + * + * @param int $slot Slot index. + * + * @return NodeConnectionInterface + * @throws OutOfBoundsException + */ + public function getConnectionBySlot($slot) + { + if (!SlotMap::isValid($slot)) { + throw new OutOfBoundsException("Invalid slot [$slot]."); + } + + if (isset($this->slots[$slot])) { + return $this->slots[$slot]; + } + + $connectionID = $this->guessNode($slot); + + if (!$connection = $this->getConnectionById($connectionID)) { + $connection = $this->createConnection($connectionID); + $this->pool[$connectionID] = $connection; + } + + return $this->slots[$slot] = $connection; + } + + /** + * {@inheritdoc} + */ + public function getConnectionById($connectionID) + { + return $this->pool[$connectionID] ?? null; + } + + /** + * Returns a random connection from the pool. + * + * @return NodeConnectionInterface|null + */ + protected function getRandomConnection() + { + if (!$this->pool) { + return null; + } + + return $this->pool[array_rand($this->pool)]; + } + + /** + * Permanently associates the connection instance to a new slot. + * The connection is added to the connections pool if not yet included. + * + * @param NodeConnectionInterface $connection Connection instance. + * @param int $slot Target slot index. + */ + protected function move(NodeConnectionInterface $connection, $slot) + { + $this->pool[(string) $connection] = $connection; + $this->slots[(int) $slot] = $connection; + $this->slotmap[(int) $slot] = $connection; + } + + /** + * Handles -ERR responses returned by Redis. + * + * @param CommandInterface $command Command that generated the -ERR response. + * @param ErrorResponseInterface $error Redis error response object. + * + * @return mixed + */ + protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $error) + { + $details = explode(' ', $error->getMessage(), 2); + + switch ($details[0]) { + case 'MOVED': + return $this->onMovedResponse($command, $details[1]); + + case 'ASK': + return $this->onAskResponse($command, $details[1]); + + default: + return $error; + } + } + + /** + * Handles -MOVED responses by executing again the command against the node + * indicated by the Redis response. + * + * @param CommandInterface $command Command that generated the -MOVED response. + * @param string $details Parameters of the -MOVED response. + * + * @return mixed + */ + protected function onMovedResponse(CommandInterface $command, $details) + { + [$slot, $connectionID] = explode(' ', $details, 2); + + // Handle connection ID in the form of "IP:port (details about exception)" + // by trimming everything after first space (including the space) + $startPositionOfExtraDetails = strpos($connectionID, ' '); + + if ($startPositionOfExtraDetails !== false) { + $connectionID = substr($connectionID, 0, $startPositionOfExtraDetails); + } + + if (!$connection = $this->getConnectionById($connectionID)) { + $connection = $this->createConnection($connectionID); + } + + if ($this->useClusterSlots) { + $this->askSlotMap($connection); + } + + $this->move($connection, $slot); + + return $this->executeCommand($command); + } + + /** + * Handles -ASK responses by executing again the command against the node + * indicated by the Redis response. + * + * @param CommandInterface $command Command that generated the -ASK response. + * @param string $details Parameters of the -ASK response. + * + * @return mixed + */ + protected function onAskResponse(CommandInterface $command, $details) + { + [$slot, $connectionID] = explode(' ', $details, 2); + + if (!$connection = $this->getConnectionById($connectionID)) { + $connection = $this->createConnection($connectionID); + } + + $connection->executeCommand(RawCommand::create('ASKING')); + + return $connection->executeCommand($command); + } + + /** + * Ensures that a command is executed one more time on connection failure. + * + * The connection to the node that generated the error is evicted from the + * pool before trying to fetch an updated slots map from another node. If + * the new slots map points to an unreachable server the client gives up and + * throws the exception as the nodes participating in the cluster may still + * have to agree that something changed in the configuration of the cluster. + * + * @param CommandInterface $command Command instance. + * @param string $method Actual method. + * + * @return mixed + */ + private function retryCommandOnFailure(CommandInterface $command, $method) + { + $retries = 0; + $retryAfter = $this->retryInterval; + + while ($retries <= $this->retryLimit) { + try { + $response = $this->getConnectionByCommand($command)->$method($command); + + if ($response instanceof ErrorResponse) { + $message = $response->getMessage(); + + if (strpos($message, 'CLUSTERDOWN') !== false) { + throw new ServerException($message); + } + } + + break; + } catch (Throwable $exception) { + usleep($retryAfter * 1000); + $retryAfter *= 2; + + if ($exception instanceof ConnectionException) { + $connection = $exception->getConnection(); + + if ($connection) { + $connection->disconnect(); + $this->remove($connection); + } + } + + if ($retries === $this->retryLimit) { + throw $exception; + } + + if ($this->useClusterSlots) { + $this->askSlotMap(); + } + + ++$retries; + } + } + + return $response; + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + return $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + $response = $this->retryCommandOnFailure($command, __FUNCTION__); + + if ($response instanceof ErrorResponseInterface) { + return $this->onErrorResponse($command, $response); + } + + return $response; + } + + /** + * @return int + */ + #[ReturnTypeWillChange] + public function count() + { + return count($this->pool); + } + + /** + * @return Traversable + */ + #[ReturnTypeWillChange] + public function getIterator() + { + if ($this->slotmap->isEmpty()) { + $this->useClusterSlots ? $this->askSlotMap() : $this->buildSlotMap(); + } + + $connections = []; + + foreach ($this->slotmap->getNodes() as $node) { + if (!$connection = $this->getConnectionById($node)) { + $this->add($connection = $this->createConnection($node)); + } + + $connections[] = $connection; + } + + return new ArrayIterator($connections); + } + + /** + * Returns the underlying slot map. + * + * @return SlotMap + */ + public function getSlotMap() + { + return $this->slotmap; + } + + /** + * Returns the underlying command hash strategy used to hash commands by + * using keys found in their arguments. + * + * @return StrategyInterface + */ + public function getClusterStrategy() + { + return $this->strategy; + } + + /** + * Returns the underlying connection factory used to create new connection + * instances to Redis nodes indicated by redis-cluster. + * + * @return FactoryInterface + */ + public function getConnectionFactory() + { + return $this->connections; + } + + /** + * Enables automatic fetching of the current slots map from one of the nodes + * using the CLUSTER SLOTS command. This option is enabled by default as + * asking the current slots map to Redis upon -MOVED responses may reduce + * overhead by eliminating the trial-and-error nature of the node guessing + * procedure, mostly when targeting many keys that would end up in a lot of + * redirections. + * + * The slots map can still be manually fetched using the askSlotMap() + * method whether or not this option is enabled. + * + * @param bool $value Enable or disable the use of CLUSTER SLOTS. + */ + public function useClusterSlots($value) + { + $this->useClusterSlots = (bool) $value; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/CompositeConnectionInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/CompositeConnectionInterface.php new file mode 100644 index 000000000..5d02a2588 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/CompositeConnectionInterface.php @@ -0,0 +1,48 @@ +parameters = $this->assertParameters($parameters); + $this->protocol = $protocol ?: new TextProtocolProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getProtocol() + { + return $this->protocol; + } + + /** + * {@inheritdoc} + */ + public function writeBuffer($buffer) + { + $this->write($buffer); + } + + /** + * {@inheritdoc} + */ + public function readBuffer($length) + { + if ($length <= 0) { + throw new InvalidArgumentException('Length parameter must be greater than 0.'); + } + + $value = ''; + $socket = $this->getResource(); + + do { + $chunk = fread($socket, $length); + + if ($chunk === false || $chunk === '') { + $this->onConnectionError('Error while reading bytes from the server.'); + } + + $value .= $chunk; + } while (($length -= strlen($chunk)) > 0); + + return $value; + } + + /** + * {@inheritdoc} + */ + public function readLine() + { + $value = ''; + $socket = $this->getResource(); + + do { + $chunk = fgets($socket); + + if ($chunk === false || $chunk === '') { + $this->onConnectionError('Error while reading line from the server.'); + } + + $value .= $chunk; + } while (substr($value, -2) !== "\r\n"); + + return substr($value, 0, -2); + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $this->protocol->write($this, $command); + } + + /** + * {@inheritdoc} + */ + public function read() + { + return $this->protocol->read($this); + } + + /** + * {@inheritdoc} + */ + public function __sleep() + { + return array_merge(parent::__sleep(), ['protocol']); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/ConnectionException.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/ConnectionException.php new file mode 100644 index 000000000..322f0d837 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/ConnectionException.php @@ -0,0 +1,22 @@ + 'Predis\Connection\StreamConnection', + 'unix' => 'Predis\Connection\StreamConnection', + 'tls' => 'Predis\Connection\StreamConnection', + 'redis' => 'Predis\Connection\StreamConnection', + 'rediss' => 'Predis\Connection\StreamConnection', + 'http' => 'Predis\Connection\WebdisConnection', + ]; + + /** + * Checks if the provided argument represents a valid connection class + * implementing Predis\Connection\NodeConnectionInterface. Optionally, + * callable objects are used for lazy initialization of connection objects. + * + * @param mixed $initializer FQN of a connection class or a callable for lazy initialization. + * + * @return mixed + * @throws InvalidArgumentException + */ + protected function checkInitializer($initializer) + { + if (is_callable($initializer)) { + return $initializer; + } + + $class = new ReflectionClass($initializer); + + if (!$class->isSubclassOf('Predis\Connection\NodeConnectionInterface')) { + throw new InvalidArgumentException( + 'A connection initializer must be a valid connection class or a callable object.' + ); + } + + return $initializer; + } + + /** + * {@inheritdoc} + */ + public function define($scheme, $initializer) + { + $this->schemes[$scheme] = $this->checkInitializer($initializer); + } + + /** + * {@inheritdoc} + */ + public function undefine($scheme) + { + unset($this->schemes[$scheme]); + } + + /** + * {@inheritdoc} + */ + public function create($parameters) + { + if (!$parameters instanceof ParametersInterface) { + $parameters = $this->createParameters($parameters); + } + + $scheme = $parameters->scheme; + + if (!isset($this->schemes[$scheme])) { + throw new InvalidArgumentException("Unknown connection scheme: '$scheme'."); + } + + $initializer = $this->schemes[$scheme]; + + if (is_callable($initializer)) { + $connection = call_user_func($initializer, $parameters, $this); + } else { + $connection = new $initializer($parameters); + $this->prepareConnection($connection); + } + + if (!$connection instanceof NodeConnectionInterface) { + throw new UnexpectedValueException( + 'Objects returned by connection initializers must implement ' . + "'Predis\Connection\NodeConnectionInterface'." + ); + } + + return $connection; + } + + /** + * Assigns a default set of parameters applied to new connections. + * + * The set of parameters passed to create a new connection have precedence + * over the default values set for the connection factory. + * + * @param array $parameters Set of connection parameters. + */ + public function setDefaultParameters(array $parameters) + { + $this->defaults = $parameters; + } + + /** + * Returns the default set of parameters applied to new connections. + * + * @return array + */ + public function getDefaultParameters() + { + return $this->defaults; + } + + /** + * Creates a connection parameters instance from the supplied argument. + * + * @param mixed $parameters Original connection parameters. + * + * @return ParametersInterface + */ + protected function createParameters($parameters) + { + if (is_string($parameters)) { + $parameters = Parameters::parse($parameters); + } else { + $parameters = $parameters ?: []; + } + + if ($this->defaults) { + $parameters += $this->defaults; + } + + return new Parameters($parameters); + } + + /** + * Prepares a connection instance after its initialization. + * + * @param NodeConnectionInterface $connection Connection instance. + */ + protected function prepareConnection(NodeConnectionInterface $connection) + { + $parameters = $connection->getParameters(); + + if (isset($parameters->password) && strlen($parameters->password)) { + $cmdAuthArgs = isset($parameters->username) && strlen($parameters->username) + ? [$parameters->username, $parameters->password] + : [$parameters->password]; + + $connection->addConnectCommand( + new RawCommand('AUTH', $cmdAuthArgs) + ); + } + + if (($parameters->client_info ?? false) && !$connection instanceof RelayConnection) { + $connection->addConnectCommand( + new RawCommand('CLIENT', ['SETINFO', 'LIB-NAME', 'predis']) + ); + + $connection->addConnectCommand( + new RawCommand('CLIENT', ['SETINFO', 'LIB-VER', Client::VERSION]) + ); + } + + if (isset($parameters->database) && strlen($parameters->database)) { + $connection->addConnectCommand( + new RawCommand('SELECT', [$parameters->database]) + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/FactoryInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/FactoryInterface.php new file mode 100644 index 000000000..1f1633242 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/FactoryInterface.php @@ -0,0 +1,43 @@ + 'tcp', + 'host' => '127.0.0.1', + 'port' => 6379, + ]; + + /** + * Set of connection parameters already filtered + * for NULL or 0-length string values. + * + * @var array + */ + protected $parameters; + + /** + * @param array $parameters Named array of connection parameters. + */ + public function __construct(array $parameters = []) + { + $this->parameters = $this->filter($parameters + static::$defaults); + } + + /** + * Filters parameters removing entries with NULL or 0-length string values. + * + * @params array $parameters Array of parameters to be filtered + * + * @return array + */ + protected function filter(array $parameters) + { + return array_filter($parameters, function ($value) { + return $value !== null && $value !== ''; + }); + } + + /** + * Creates a new instance by supplying the initial parameters either in the + * form of an URI string or a named array. + * + * @param array|string $parameters Set of connection parameters. + * + * @return Parameters + */ + public static function create($parameters) + { + if (is_string($parameters)) { + $parameters = static::parse($parameters); + } + + return new static($parameters ?: []); + } + + /** + * Parses an URI string returning an array of connection parameters. + * + * When using the "redis" and "rediss" schemes the URI is parsed according + * to the rules defined by the provisional registration documents approved + * by IANA. If the URI has a password in its "user-information" part or a + * database number in the "path" part these values override the values of + * "password" and "database" if they are present in the "query" part. + * + * @see http://www.iana.org/assignments/uri-schemes/prov/redis + * @see http://www.iana.org/assignments/uri-schemes/prov/rediss + * + * @param string $uri URI string. + * + * @return array + * @throws InvalidArgumentException + */ + public static function parse($uri) + { + if (stripos($uri, 'unix://') === 0) { + // parse_url() can parse unix:/path/to/sock so we do not need the + // unix:///path/to/sock hack, we will support it anyway until 2.0. + $uri = str_ireplace('unix://', 'unix:', $uri); + } + + if (!$parsed = parse_url($uri)) { + throw new InvalidArgumentException("Invalid parameters URI: $uri"); + } + + if ( + isset($parsed['host']) + && false !== strpos($parsed['host'], '[') + && false !== strpos($parsed['host'], ']') + ) { + $parsed['host'] = substr($parsed['host'], 1, -1); + } + + if (isset($parsed['query'])) { + parse_str($parsed['query'], $queryarray); + unset($parsed['query']); + + $parsed = array_merge($parsed, $queryarray); + } + + if (stripos($uri, 'redis') === 0) { + if (isset($parsed['user'])) { + if (strlen($parsed['user'])) { + $parsed['username'] = $parsed['user']; + } + unset($parsed['user']); + } + + if (isset($parsed['pass'])) { + if (strlen($parsed['pass'])) { + $parsed['password'] = $parsed['pass']; + } + unset($parsed['pass']); + } + + if (isset($parsed['path']) && preg_match('/^\/(\d+)(\/.*)?/', $parsed['path'], $path)) { + $parsed['database'] = $path[1]; + + if (isset($path[2])) { + $parsed['path'] = $path[2]; + } else { + unset($parsed['path']); + } + } + } + + return $parsed; + } + + /** + * {@inheritdoc} + */ + public function toArray() + { + return $this->parameters; + } + + /** + * {@inheritdoc} + */ + public function __get($parameter) + { + if (isset($this->parameters[$parameter])) { + return $this->parameters[$parameter]; + } + } + + /** + * {@inheritdoc} + */ + public function __isset($parameter) + { + return isset($this->parameters[$parameter]); + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + if ($this->scheme === 'unix') { + return "$this->scheme:$this->path"; + } + + if (filter_var($this->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + return "$this->scheme://[$this->host]:$this->port"; + } + + return "$this->scheme://$this->host:$this->port"; + } + + /** + * {@inheritdoc} + */ + public function __sleep() + { + return ['parameters']; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/ParametersInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/ParametersInterface.php new file mode 100644 index 000000000..b48d118de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/ParametersInterface.php @@ -0,0 +1,72 @@ +assertExtensions(); + + parent::__construct($parameters); + + $this->reader = $this->createReader(); + } + + /** + * Disconnects from the server and destroys the underlying resource and the + * protocol reader resource when PHP's garbage collector kicks in. + */ + public function __destruct() + { + parent::__destruct(); + + phpiredis_reader_destroy($this->reader); + } + + /** + * Checks if the socket and phpiredis extensions are loaded in PHP. + */ + protected function assertExtensions() + { + if (!extension_loaded('sockets')) { + throw new NotSupportedException( + 'The "sockets" extension is required by this connection backend.' + ); + } + + if (!extension_loaded('phpiredis')) { + throw new NotSupportedException( + 'The "phpiredis" extension is required by this connection backend.' + ); + } + } + + /** + * {@inheritdoc} + */ + protected function assertParameters(ParametersInterface $parameters) + { + switch ($parameters->scheme) { + case 'tcp': + case 'redis': + case 'unix': + break; + + default: + throw new InvalidArgumentException("Invalid scheme: '$parameters->scheme'."); + } + + if (isset($parameters->persistent)) { + throw new NotSupportedException( + 'Persistent connections are not supported by this connection backend.' + ); + } + + return $parameters; + } + + /** + * Creates a new instance of the protocol reader resource. + * + * @return resource + */ + private function createReader() + { + $reader = phpiredis_reader_create(); + + phpiredis_reader_set_status_handler($reader, $this->getStatusHandler()); + phpiredis_reader_set_error_handler($reader, $this->getErrorHandler()); + + return $reader; + } + + /** + * Returns the underlying protocol reader resource. + * + * @return resource + */ + protected function getReader() + { + return $this->reader; + } + + /** + * Returns the handler used by the protocol reader for inline responses. + * + * @return Closure + */ + protected function getStatusHandler() + { + static $statusHandler; + + if (!$statusHandler) { + $statusHandler = function ($payload) { + return StatusResponse::get($payload); + }; + } + + return $statusHandler; + } + + /** + * Returns the handler used by the protocol reader for error responses. + * + * @return Closure + */ + protected function getErrorHandler() + { + static $errorHandler; + + if (!$errorHandler) { + $errorHandler = function ($errorMessage) { + return new ErrorResponse($errorMessage); + }; + } + + return $errorHandler; + } + + /** + * Helper method used to throw exceptions on socket errors. + */ + private function emitSocketError() + { + $errno = socket_last_error(); + $errstr = socket_strerror($errno); + + $this->disconnect(); + + $this->onConnectionError(trim($errstr), $errno); + } + + /** + * Gets the address of an host from connection parameters. + * + * @param ParametersInterface $parameters Parameters used to initialize the connection. + * + * @return string + */ + protected static function getAddress(ParametersInterface $parameters) + { + if (filter_var($host = $parameters->host, FILTER_VALIDATE_IP)) { + return $host; + } + + if ($host === $address = gethostbyname($host)) { + return false; + } + + return $address; + } + + /** + * {@inheritdoc} + */ + protected function createResource() + { + $parameters = $this->parameters; + + if ($parameters->scheme === 'unix') { + $address = $parameters->path; + $domain = AF_UNIX; + $protocol = 0; + } else { + if (false === $address = self::getAddress($parameters)) { + $this->onConnectionError("Cannot resolve the address of '$parameters->host'."); + } + + $domain = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) ? AF_INET6 : AF_INET; + $protocol = SOL_TCP; + } + + if (false === $socket = @socket_create($domain, SOCK_STREAM, $protocol)) { + $this->emitSocketError(); + } + + $this->setSocketOptions($socket, $parameters); + $this->connectWithTimeout($socket, $address, $parameters); + + return $socket; + } + + /** + * Sets options on the socket resource from the connection parameters. + * + * @param resource $socket Socket resource. + * @param ParametersInterface $parameters Parameters used to initialize the connection. + */ + private function setSocketOptions($socket, ParametersInterface $parameters) + { + if ($parameters->scheme !== 'unix') { + if (!socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1)) { + $this->emitSocketError(); + } + + if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) { + $this->emitSocketError(); + } + } + + if (isset($parameters->read_write_timeout)) { + $rwtimeout = (float) $parameters->read_write_timeout; + $timeoutSec = floor($rwtimeout); + $timeoutUsec = ($rwtimeout - $timeoutSec) * 1000000; + + $timeout = [ + 'sec' => $timeoutSec, + 'usec' => $timeoutUsec, + ]; + + if (!socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout)) { + $this->emitSocketError(); + } + + if (!socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout)) { + $this->emitSocketError(); + } + } + } + + /** + * Opens the actual connection to the server with a timeout. + * + * @param resource $socket Socket resource. + * @param string $address IP address (DNS-resolved from hostname) + * @param ParametersInterface $parameters Parameters used to initialize the connection. + * + * @return void + */ + private function connectWithTimeout($socket, $address, ParametersInterface $parameters) + { + socket_set_nonblock($socket); + + if (@socket_connect($socket, $address, (int) $parameters->port) === false) { + $error = socket_last_error(); + + if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) { + $this->emitSocketError(); + } + } + + socket_set_block($socket); + + $null = null; + $selectable = [$socket]; + + $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0); + $timeoutSecs = floor($timeout); + $timeoutUSecs = ($timeout - $timeoutSecs) * 1000000; + + $selected = socket_select($selectable, $selectable, $null, $timeoutSecs, $timeoutUSecs); + + if ($selected === 2) { + $this->onConnectionError('Connection refused.', SOCKET_ECONNREFUSED); + } + + if ($selected === 0) { + $this->onConnectionError('Connection timed out.', SOCKET_ETIMEDOUT); + } + + if ($selected === false) { + $this->emitSocketError(); + } + } + + /** + * {@inheritdoc} + */ + public function connect() + { + if (parent::connect() && $this->initCommands) { + foreach ($this->initCommands as $command) { + $response = $this->executeCommand($command); + + if ($response instanceof ErrorResponseInterface) { + $this->onConnectionError("`{$command->getId()}` failed: {$response->getMessage()}", 0); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + if ($this->isConnected()) { + phpiredis_reader_reset($this->reader); + socket_close($this->getResource()); + + parent::disconnect(); + } + } + + /** + * {@inheritdoc} + */ + protected function write($buffer) + { + $socket = $this->getResource(); + + while (($length = strlen($buffer)) > 0) { + $written = socket_write($socket, $buffer, $length); + + if ($length === $written) { + return; + } + + if ($written === false) { + $this->onConnectionError('Error while writing bytes to the server.'); + } + + $buffer = substr($buffer, $written); + } + } + + /** + * {@inheritdoc} + */ + public function read() + { + $socket = $this->getResource(); + $reader = $this->reader; + + while (PHPIREDIS_READER_STATE_INCOMPLETE === $state = phpiredis_reader_get_state($reader)) { + if (@socket_recv($socket, $buffer, 4096, 0) === false || $buffer === '' || $buffer === null) { + $this->emitSocketError(); + } + + phpiredis_reader_feed($reader, $buffer); + } + + if ($state === PHPIREDIS_READER_STATE_COMPLETE) { + return phpiredis_reader_get_reply($reader); + } else { + $this->onProtocolError(phpiredis_reader_get_error($reader)); + + return; + } + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $arguments = $command->getArguments(); + array_unshift($arguments, $command->getId()); + + $this->write(phpiredis_format_command($arguments)); + } + + /** + * {@inheritdoc} + */ + public function __wakeup() + { + $this->assertExtensions(); + $this->reader = $this->createReader(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/PhpiredisStreamConnection.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/PhpiredisStreamConnection.php new file mode 100644 index 000000000..2a6e0ce23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/PhpiredisStreamConnection.php @@ -0,0 +1,262 @@ +assertExtensions(); + + parent::__construct($parameters); + + $this->reader = $this->createReader(); + } + + /** + * {@inheritdoc} + */ + public function __destruct() + { + parent::__destruct(); + + phpiredis_reader_destroy($this->reader); + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + phpiredis_reader_reset($this->reader); + + parent::disconnect(); + } + + /** + * Checks if the phpiredis extension is loaded in PHP. + */ + private function assertExtensions() + { + if (!extension_loaded('phpiredis')) { + throw new NotSupportedException( + 'The "phpiredis" extension is required by this connection backend.' + ); + } + } + + /** + * {@inheritdoc} + */ + protected function assertParameters(ParametersInterface $parameters) + { + switch ($parameters->scheme) { + case 'tcp': + case 'redis': + case 'unix': + break; + + case 'tls': + case 'rediss': + throw new InvalidArgumentException('SSL encryption is not supported by this connection backend.'); + default: + throw new InvalidArgumentException("Invalid scheme: '$parameters->scheme'."); + } + + return $parameters; + } + + /** + * {@inheritdoc} + */ + protected function createStreamSocket(ParametersInterface $parameters, $address, $flags) + { + $socket = null; + $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0); + $context = stream_context_create(['socket' => ['tcp_nodelay' => (bool) $parameters->tcp_nodelay]]); + + if (!$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context)) { + $this->onConnectionError(trim($errstr), $errno); + } + + if (isset($parameters->read_write_timeout) && function_exists('socket_import_stream')) { + $rwtimeout = (float) $parameters->read_write_timeout; + $rwtimeout = $rwtimeout > 0 ? $rwtimeout : -1; + + $timeout = [ + 'sec' => $timeoutSeconds = floor($rwtimeout), + 'usec' => ($rwtimeout - $timeoutSeconds) * 1000000, + ]; + + $socket = $socket ?: socket_import_stream($resource); + @socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $timeout); + @socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $timeout); + } + + if (isset($parameters->tcp_nodelay) && function_exists('socket_import_stream')) { + $socket = $socket ?: socket_import_stream($resource); + socket_set_option($socket, SOL_TCP, TCP_NODELAY, (int) $parameters->tcp_nodelay); + } + + return $resource; + } + + /** + * Creates a new instance of the protocol reader resource. + * + * @return resource + */ + private function createReader() + { + $reader = phpiredis_reader_create(); + + phpiredis_reader_set_status_handler($reader, $this->getStatusHandler()); + phpiredis_reader_set_error_handler($reader, $this->getErrorHandler()); + + return $reader; + } + + /** + * Returns the underlying protocol reader resource. + * + * @return resource + */ + protected function getReader() + { + return $this->reader; + } + + /** + * Returns the handler used by the protocol reader for inline responses. + * + * @return Closure + */ + protected function getStatusHandler() + { + static $statusHandler; + + if (!$statusHandler) { + $statusHandler = function ($payload) { + return StatusResponse::get($payload); + }; + } + + return $statusHandler; + } + + /** + * Returns the handler used by the protocol reader for error responses. + * + * @return Closure + */ + protected function getErrorHandler() + { + static $errorHandler; + + if (!$errorHandler) { + $errorHandler = function ($errorMessage) { + return new ErrorResponse($errorMessage); + }; + } + + return $errorHandler; + } + + /** + * {@inheritdoc} + */ + public function read() + { + $socket = $this->getResource(); + $reader = $this->reader; + + while (PHPIREDIS_READER_STATE_INCOMPLETE === $state = phpiredis_reader_get_state($reader)) { + $buffer = stream_socket_recvfrom($socket, 4096); + + if ($buffer === false || $buffer === '') { + $this->onConnectionError('Error while reading bytes from the server.'); + } + + phpiredis_reader_feed($reader, $buffer); + } + + if ($state === PHPIREDIS_READER_STATE_COMPLETE) { + return phpiredis_reader_get_reply($reader); + } else { + $this->onProtocolError(phpiredis_reader_get_error($reader)); + + return; + } + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $arguments = $command->getArguments(); + array_unshift($arguments, $command->getId()); + + $this->write(phpiredis_format_command($arguments)); + } + + /** + * {@inheritdoc} + */ + public function __wakeup() + { + $this->assertExtensions(); + $this->reader = $this->createReader(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayConnection.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayConnection.php new file mode 100644 index 000000000..b71b60b19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayConnection.php @@ -0,0 +1,348 @@ +assertExtensions(); + + $this->parameters = $this->assertParameters($parameters); + $this->client = $this->createClient(); + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return $this->client->isConnected(); + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + if ($this->client->isConnected()) { + $this->client->close(); + } + } + + /** + * Checks if the Relay extension is loaded in PHP. + */ + private function assertExtensions() + { + if (!extension_loaded('relay')) { + throw new NotSupportedException( + 'The "relay" extension is required by this connection backend.' + ); + } + } + + /** + * {@inheritdoc} + */ + protected function assertParameters(ParametersInterface $parameters) + { + if (!in_array($parameters->scheme, ['tcp', 'tls', 'unix', 'redis', 'rediss'])) { + throw new InvalidArgumentException("Invalid scheme: '{$parameters->scheme}'."); + } + + if (!in_array($parameters->serializer, [null, 'php', 'igbinary', 'msgpack', 'json'])) { + throw new InvalidArgumentException("Invalid serializer: '{$parameters->serializer}'."); + } + + if (!in_array($parameters->compression, [null, 'lzf', 'lz4', 'zstd'])) { + throw new InvalidArgumentException("Invalid compression algorithm: '{$parameters->compression}'."); + } + + return $parameters; + } + + /** + * Creates a new instance of the client. + * + * @return Relay + */ + private function createClient() + { + $client = new Relay(); + + // throw when errors occur and return `null` for non-existent keys + $client->setOption(Relay::OPT_PHPREDIS_COMPATIBILITY, false); + + // use reply literals + $client->setOption(Relay::OPT_REPLY_LITERAL, true); + + // disable Relay's command/connection retry + $client->setOption(Relay::OPT_MAX_RETRIES, 0); + + // whether to use in-memory caching + $client->setOption(Relay::OPT_USE_CACHE, $this->parameters->cache ?? true); + + // set data serializer + $client->setOption(Relay::OPT_SERIALIZER, constant(sprintf( + '%s::SERIALIZER_%s', + Relay::class, + strtoupper($this->parameters->serializer ?? 'none') + ))); + + // set data compression algorithm + $client->setOption(Relay::OPT_COMPRESSION, constant(sprintf( + '%s::COMPRESSION_%s', + Relay::class, + strtoupper($this->parameters->compression ?? 'none') + ))); + + return $client; + } + + /** + * Returns the underlying client. + * + * @return Relay + */ + public function getClient() + { + return $this->client; + } + + /** + * {@inheritdoc} + */ + public function getIdentifier() + { + try { + return $this->client->endpointId(); + } catch (RelayException $ex) { + return parent::getIdentifier(); + } + } + + /** + * {@inheritdoc} + */ + protected function createStreamSocket(ParametersInterface $parameters, $address, $flags) + { + $timeout = isset($parameters->timeout) ? (float) $parameters->timeout : 5.0; + + $retry_interval = 0; + $read_timeout = 5.0; + + if (isset($parameters->read_write_timeout)) { + $read_timeout = (float) $parameters->read_write_timeout; + $read_timeout = $read_timeout > 0 ? $read_timeout : 0; + } + + try { + $this->client->connect( + $parameters->path ?? $parameters->host, + isset($parameters->path) ? 0 : $parameters->port, + $timeout, + null, + $retry_interval, + $read_timeout + ); + } catch (RelayException $ex) { + $this->onConnectionError($ex->getMessage(), $ex->getCode()); + } + + return $this->client; + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + if (!$this->client->isConnected()) { + $this->getResource(); + } + + try { + $name = $command->getId(); + + // When using compression or a serializer, we'll need a dedicated + // handler for `Predis\Command\RawCommand` calls, currently both + // parameters are unsupported until a future Relay release + return in_array($name, $this->atypicalCommands) + ? $this->client->{$name}(...$command->getArguments()) + : $this->client->rawCommand($name, ...$command->getArguments()); + } catch (RelayException $ex) { + $exception = $this->onCommandError($ex, $command); + + if ($exception instanceof ErrorResponseInterface) { + return $exception; + } + + throw $exception; + } + } + + /** + * {@inheritdoc} + */ + public function onCommandError(RelayException $exception, CommandInterface $command) + { + $code = $exception->getCode(); + $message = $exception->getMessage(); + + if (strpos($message, 'RELAY_ERR_IO') !== false) { + return new ConnectionException($this, $message, $code, $exception); + } + + if (strpos($message, 'RELAY_ERR_REDIS') !== false) { + return new ServerException($message, $code, $exception); + } + + if (strpos($message, 'RELAY_ERR_WRONGTYPE') !== false && strpos($message, "Got reply-type 'status'") !== false) { + $message = 'Operation against a key holding the wrong kind of value'; + } + + return new ClientException($message, $code, $exception); + } + + /** + * Applies the configured serializer and compression to given value. + * + * @param mixed $value + * @return string + */ + public function pack($value) + { + return $this->client->_pack($value); + } + + /** + * Deserializes and decompresses to given value. + * + * @param mixed $value + * @return string + */ + public function unpack($value) + { + return $this->client->_unpack($value); + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + throw new NotSupportedException('The "relay" extension does not support writing requests.'); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + throw new NotSupportedException('The "relay" extension does not support reading responses.'); + } + + /** + * {@inheritdoc} + */ + public function __destruct() + { + $this->disconnect(); + } + + /** + * {@inheritdoc} + */ + public function __wakeup() + { + $this->assertExtensions(); + $this->client = $this->createClient(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayMethods.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayMethods.php new file mode 100644 index 000000000..116c8754a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/RelayMethods.php @@ -0,0 +1,136 @@ +client->onFlushed($callback); + } + + /** + * Registers a new `invalidated` event listener. + * + * @param callable $callback + * @param string|null $pattern + * @return bool + */ + public function onInvalidated(?callable $callback, ?string $pattern = null) + { + return $this->client->onInvalidated($callback, $pattern); + } + + /** + * Dispatches all pending events. + * + * @return int|false + */ + public function dispatchEvents() + { + return $this->client->dispatchEvents(); + } + + /** + * Adds ignore pattern(s). Matching keys will not be cached in memory. + * + * @param string $pattern,... + * @return int + */ + public function addIgnorePatterns(string ...$pattern) + { + return $this->client->addIgnorePatterns(...$pattern); + } + + /** + * Adds allow pattern(s). Only matching keys will be cached in memory. + * + * @param string $pattern,... + * @return int + */ + public function addAllowPatterns(string ...$pattern) + { + return $this->client->addAllowPatterns(...$pattern); + } + + /** + * Returns the connection's endpoint identifier. + * + * @return string|false + */ + public function endpointId() + { + return $this->client->endpointId(); + } + + /** + * Returns a unique representation of the underlying socket connection identifier. + * + * @return string|false + */ + public function socketId() + { + return $this->client->socketId(); + } + + /** + * Returns information about the license. + * + * @return array + */ + public function license() + { + return $this->client->license(); + } + + /** + * Returns statistics about Relay. + * + * @return array> + */ + public function stats() + { + return $this->client->stats(); + } + + /** + * Returns the number of bytes allocated, or `0` in client-only mode. + * + * @return int + */ + public function maxMemory() + { + return $this->client->maxMemory(); + } + + /** + * Flushes Relay's in-memory cache of all databases. + * When given an endpoint, only that connection will be flushed. + * When given an endpoint and database index, only that database + * for that connection will be flushed. + * + * @param ?string $endpointId + * @param ?int $db + * @return bool + */ + public function flushMemory(?string $endpointId = null, ?int $db = null) + { + return $this->client->flushMemory($endpointId, $db); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/MasterSlaveReplication.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/MasterSlaveReplication.php new file mode 100644 index 000000000..10246fc81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/MasterSlaveReplication.php @@ -0,0 +1,553 @@ +strategy = $strategy ?: new ReplicationStrategy(); + } + + /** + * Configures the automatic discovery of the replication configuration on failure. + * + * @param bool $value Enable or disable auto discovery. + */ + public function setAutoDiscovery($value) + { + if (!$this->connectionFactory) { + throw new ClientException('Automatic discovery requires a connection factory'); + } + + $this->autoDiscovery = (bool) $value; + } + + /** + * Sets the connection factory used to create the connections by the auto + * discovery procedure. + * + * @param FactoryInterface $connectionFactory Connection factory instance. + */ + public function setConnectionFactory(FactoryInterface $connectionFactory) + { + $this->connectionFactory = $connectionFactory; + } + + /** + * Resets the connection state. + */ + protected function reset() + { + $this->current = null; + } + + /** + * {@inheritdoc} + */ + public function add(NodeConnectionInterface $connection) + { + $parameters = $connection->getParameters(); + + if ('master' === $parameters->role) { + $this->master = $connection; + } else { + // everything else is considered a slvave. + $this->slaves[] = $connection; + } + + if (isset($parameters->alias)) { + $this->aliases[$parameters->alias] = $connection; + } + + $this->pool[(string) $connection] = $connection; + + $this->reset(); + } + + /** + * {@inheritdoc} + */ + public function remove(NodeConnectionInterface $connection) + { + if ($connection === $this->master) { + $this->master = null; + } elseif (false !== $id = array_search($connection, $this->slaves, true)) { + unset($this->slaves[$id]); + } else { + return false; + } + + unset($this->pool[(string) $connection]); + + if ($this->aliases && $alias = $connection->getParameters()->alias) { + unset($this->aliases[$alias]); + } + + $this->reset(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function getConnectionByCommand(CommandInterface $command) + { + if (!$this->current) { + if ($this->strategy->isReadOperation($command) && $slave = $this->pickSlave()) { + $this->current = $slave; + } else { + $this->current = $this->getMasterOrDie(); + } + + return $this->current; + } + + if ($this->current === $master = $this->getMasterOrDie()) { + return $master; + } + + if (!$this->strategy->isReadOperation($command) || !$this->slaves) { + $this->current = $master; + } + + return $this->current; + } + + /** + * {@inheritdoc} + */ + public function getConnectionById($id) + { + return $this->pool[$id] ?? null; + } + + /** + * Returns a connection instance by its alias. + * + * @param string $alias Connection alias. + * + * @return NodeConnectionInterface|null + */ + public function getConnectionByAlias($alias) + { + return $this->aliases[$alias] ?? null; + } + + /** + * Returns a connection by its role. + * + * @param string $role Connection role (`master` or `slave`) + * + * @return NodeConnectionInterface|null + */ + public function getConnectionByRole($role) + { + if ($role === 'master') { + return $this->getMaster(); + } elseif ($role === 'slave') { + return $this->pickSlave(); + } + + return null; + } + + /** + * Switches the internal connection in use by the backend. + * + * @param NodeConnectionInterface $connection Connection instance in the pool. + */ + public function switchTo(NodeConnectionInterface $connection) + { + if ($connection && $connection === $this->current) { + return; + } + + if ($connection !== $this->master && !in_array($connection, $this->slaves, true)) { + throw new InvalidArgumentException('Invalid connection or connection not found.'); + } + + $this->current = $connection; + } + + /** + * {@inheritdoc} + */ + public function switchToMaster() + { + if (!$connection = $this->getConnectionByRole('master')) { + throw new InvalidArgumentException('Invalid connection or connection not found.'); + } + + $this->switchTo($connection); + } + + /** + * {@inheritdoc} + */ + public function switchToSlave() + { + if (!$connection = $this->getConnectionByRole('slave')) { + throw new InvalidArgumentException('Invalid connection or connection not found.'); + } + + $this->switchTo($connection); + } + + /** + * {@inheritdoc} + */ + public function getCurrent() + { + return $this->current; + } + + /** + * {@inheritdoc} + */ + public function getMaster() + { + return $this->master; + } + + /** + * Returns the connection associated to the master server. + * + * @return NodeConnectionInterface + */ + private function getMasterOrDie() + { + if (!$connection = $this->getMaster()) { + throw new MissingMasterException('No master server available for replication'); + } + + return $connection; + } + + /** + * {@inheritdoc} + */ + public function getSlaves() + { + return $this->slaves; + } + + /** + * Returns the underlying replication strategy. + * + * @return ReplicationStrategy + */ + public function getReplicationStrategy() + { + return $this->strategy; + } + + /** + * Returns a random slave. + * + * @return NodeConnectionInterface|null + */ + protected function pickSlave() + { + if (!$this->slaves) { + return null; + } + + return $this->slaves[array_rand($this->slaves)]; + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return $this->current ? $this->current->isConnected() : false; + } + + /** + * {@inheritdoc} + */ + public function connect() + { + if (!$this->current) { + if (!$this->current = $this->pickSlave()) { + if (!$this->current = $this->getMaster()) { + throw new ClientException('No available connection for replication'); + } + } + } + + $this->current->connect(); + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + foreach ($this->pool as $connection) { + $connection->disconnect(); + } + } + + /** + * Handles response from INFO. + * + * @param string $response + * + * @return array + */ + private function handleInfoResponse($response) + { + $info = []; + + foreach (preg_split('/\r?\n/', $response) as $row) { + if (strpos($row, ':') === false) { + continue; + } + + [$k, $v] = explode(':', $row, 2); + $info[$k] = $v; + } + + return $info; + } + + /** + * Fetches the replication configuration from one of the servers. + */ + public function discover() + { + if (!$this->connectionFactory) { + throw new ClientException('Discovery requires a connection factory'); + } + + while (true) { + try { + if ($connection = $this->getMaster()) { + $this->discoverFromMaster($connection, $this->connectionFactory); + break; + } elseif ($connection = $this->pickSlave()) { + $this->discoverFromSlave($connection, $this->connectionFactory); + break; + } else { + throw new ClientException('No connection available for discovery'); + } + } catch (ConnectionException $exception) { + $this->remove($connection); + } + } + } + + /** + * Discovers the replication configuration by contacting the master node. + * + * @param NodeConnectionInterface $connection Connection to the master node. + * @param FactoryInterface $connectionFactory Connection factory instance. + */ + protected function discoverFromMaster(NodeConnectionInterface $connection, FactoryInterface $connectionFactory) + { + $response = $connection->executeCommand(RawCommand::create('INFO', 'REPLICATION')); + $replication = $this->handleInfoResponse($response); + + if ($replication['role'] !== 'master') { + throw new ClientException("Role mismatch (expected master, got slave) [$connection]"); + } + + $this->slaves = []; + + foreach ($replication as $k => $v) { + $parameters = null; + + if (strpos($k, 'slave') === 0 && preg_match('/ip=(?P.*),port=(?P\d+)/', $v, $parameters)) { + $slaveConnection = $connectionFactory->create([ + 'host' => $parameters['host'], + 'port' => $parameters['port'], + 'role' => 'slave', + ]); + + $this->add($slaveConnection); + } + } + } + + /** + * Discovers the replication configuration by contacting one of the slaves. + * + * @param NodeConnectionInterface $connection Connection to one of the slaves. + * @param FactoryInterface $connectionFactory Connection factory instance. + */ + protected function discoverFromSlave(NodeConnectionInterface $connection, FactoryInterface $connectionFactory) + { + $response = $connection->executeCommand(RawCommand::create('INFO', 'REPLICATION')); + $replication = $this->handleInfoResponse($response); + + if ($replication['role'] !== 'slave') { + throw new ClientException("Role mismatch (expected slave, got master) [$connection]"); + } + + $masterConnection = $connectionFactory->create([ + 'host' => $replication['master_host'], + 'port' => $replication['master_port'], + 'role' => 'master', + ]); + + $this->add($masterConnection); + + $this->discoverFromMaster($masterConnection, $connectionFactory); + } + + /** + * Retries the execution of a command upon slave failure. + * + * @param CommandInterface $command Command instance. + * @param string $method Actual method. + * + * @return mixed + */ + private function retryCommandOnFailure(CommandInterface $command, $method) + { + while (true) { + try { + $connection = $this->getConnectionByCommand($command); + $response = $connection->$method($command); + + if ($response instanceof ResponseErrorInterface && $response->getErrorType() === 'LOADING') { + throw new ConnectionException($connection, "Redis is loading the dataset in memory [$connection]"); + } + + break; + } catch (ConnectionException $exception) { + $connection = $exception->getConnection(); + $connection->disconnect(); + + if ($connection === $this->master && !$this->autoDiscovery) { + // Throw immediately when master connection is failing, even + // when the command represents a read-only operation, unless + // automatic discovery has been enabled. + throw $exception; + } else { + // Otherwise remove the failing slave and attempt to execute + // the command again on one of the remaining slaves... + $this->remove($connection); + } + + // ... that is, unless we have no more connections to use. + if (!$this->slaves && !$this->master) { + throw $exception; + } elseif ($this->autoDiscovery) { + $this->discover(); + } + } catch (MissingMasterException $exception) { + if ($this->autoDiscovery) { + $this->discover(); + } else { + throw $exception; + } + } + } + + return $response; + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + return $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + return $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function __sleep() + { + return ['master', 'slaves', 'pool', 'aliases', 'strategy']; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/ReplicationInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/ReplicationInterface.php new file mode 100644 index 000000000..a59a53516 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/Replication/ReplicationInterface.php @@ -0,0 +1,53 @@ + + * @author Ville Mattila + */ +class SentinelReplication implements ReplicationInterface +{ + /** + * @var NodeConnectionInterface + */ + protected $master; + + /** + * @var NodeConnectionInterface[] + */ + protected $slaves = []; + + /** + * @var NodeConnectionInterface[] + */ + protected $pool = []; + + /** + * @var NodeConnectionInterface + */ + protected $current; + + /** + * @var string + */ + protected $service; + + /** + * @var ConnectionFactoryInterface + */ + protected $connectionFactory; + + /** + * @var ReplicationStrategy + */ + protected $strategy; + + /** + * @var NodeConnectionInterface[] + */ + protected $sentinels = []; + + /** + * @var int + */ + protected $sentinelIndex = 0; + + /** + * @var NodeConnectionInterface + */ + protected $sentinelConnection; + + /** + * @var float + */ + protected $sentinelTimeout = 0.100; + + /** + * Max number of automatic retries of commands upon server failure. + * + * -1 = unlimited retry attempts + * 0 = no retry attempts (fails immediately) + * n = fail only after n retry attempts + * + * @var int + */ + protected $retryLimit = 20; + + /** + * Time to wait in milliseconds before fetching a new configuration from one + * of the sentinel servers. + * + * @var int + */ + protected $retryWait = 1000; + + /** + * Flag for automatic fetching of available sentinels. + * + * @var bool + */ + protected $updateSentinels = false; + + /** + * @param string $service Name of the service for autodiscovery. + * @param array $sentinels Sentinel servers connection parameters. + * @param ConnectionFactoryInterface $connectionFactory Connection factory instance. + * @param ReplicationStrategy|null $strategy Replication strategy instance. + */ + public function __construct( + $service, + array $sentinels, + ConnectionFactoryInterface $connectionFactory, + ?ReplicationStrategy $strategy = null + ) { + $this->sentinels = $sentinels; + $this->service = $service; + $this->connectionFactory = $connectionFactory; + $this->strategy = $strategy ?: new ReplicationStrategy(); + } + + /** + * Sets a default timeout for connections to sentinels. + * + * When "timeout" is present in the connection parameters of sentinels, its + * value overrides the default sentinel timeout. + * + * @param float $timeout Timeout value. + */ + public function setSentinelTimeout($timeout) + { + $this->sentinelTimeout = (float) $timeout; + } + + /** + * Sets the maximum number of retries for commands upon server failure. + * + * -1 = unlimited retry attempts + * 0 = no retry attempts (fails immediately) + * n = fail only after n retry attempts + * + * @param int $retry Number of retry attempts. + */ + public function setRetryLimit($retry) + { + $this->retryLimit = (int) $retry; + } + + /** + * Sets the time to wait (in milliseconds) before fetching a new configuration + * from one of the sentinels. + * + * @param float $milliseconds Time to wait before the next attempt. + */ + public function setRetryWait($milliseconds) + { + $this->retryWait = (float) $milliseconds; + } + + /** + * Set automatic fetching of available sentinels. + * + * @param bool $update Enable or disable automatic updates. + */ + public function setUpdateSentinels($update) + { + $this->updateSentinels = (bool) $update; + } + + /** + * Resets the current connection. + */ + protected function reset() + { + $this->current = null; + } + + /** + * Wipes the current list of master and slaves nodes. + */ + protected function wipeServerList() + { + $this->reset(); + + $this->master = null; + $this->slaves = []; + $this->pool = []; + } + + /** + * {@inheritdoc} + */ + public function add(NodeConnectionInterface $connection) + { + $parameters = $connection->getParameters(); + $role = $parameters->role; + + if ('master' === $role) { + $this->master = $connection; + } elseif ('sentinel' === $role) { + $this->sentinels[] = $connection; + + // sentinels are not considered part of the pool. + return; + } else { + // everything else is considered a slave. + $this->slaves[] = $connection; + } + + $this->pool[(string) $connection] = $connection; + + $this->reset(); + } + + /** + * {@inheritdoc} + */ + public function remove(NodeConnectionInterface $connection) + { + if ($connection === $this->master) { + $this->master = null; + } elseif (false !== $id = array_search($connection, $this->slaves, true)) { + unset($this->slaves[$id]); + } elseif (false !== $id = array_search($connection, $this->sentinels, true)) { + unset($this->sentinels[$id]); + + return true; + } else { + return false; + } + + unset($this->pool[(string) $connection]); + + $this->reset(); + + return true; + } + + /** + * Creates a new connection to a sentinel server. + * + * @return NodeConnectionInterface + */ + protected function createSentinelConnection($parameters) + { + if ($parameters instanceof NodeConnectionInterface) { + return $parameters; + } + + if (is_string($parameters)) { + $parameters = Parameters::parse($parameters); + } + + if (is_array($parameters)) { + // NOTE: sentinels do not accept AUTH and SELECT commands so we must + // explicitly set them to NULL to avoid problems when using default + // parameters set via client options. Actually AUTH is supported for + // sentinels starting with Redis 5 but we have to differentiate from + // sentinels passwords and nodes passwords, this will be implemented + // in a later release. + $parameters['database'] = null; + $parameters['username'] = null; + + // don't leak password from between configurations + // https://github.com/predis/predis/pull/807/#discussion_r985764770 + if (!isset($parameters['password'])) { + $parameters['password'] = null; + } + + if (!isset($parameters['timeout'])) { + $parameters['timeout'] = $this->sentinelTimeout; + } + } + + return $this->connectionFactory->create($parameters); + } + + /** + * Returns the current sentinel connection. + * + * If there is no active sentinel connection, a new connection is created. + * + * @return NodeConnectionInterface + */ + public function getSentinelConnection() + { + if (!$this->sentinelConnection) { + if ($this->sentinelIndex >= count($this->sentinels)) { + $this->sentinelIndex = 0; + throw new \Predis\ClientException('No sentinel server available for autodiscovery.'); + } + + $sentinel = $this->sentinels[$this->sentinelIndex]; + ++$this->sentinelIndex; + $this->sentinelConnection = $this->createSentinelConnection($sentinel); + } + + return $this->sentinelConnection; + } + + /** + * Fetches an updated list of sentinels from a sentinel. + */ + public function updateSentinels() + { + SENTINEL_QUERY: { + $sentinel = $this->getSentinelConnection(); + + try { + $payload = $sentinel->executeCommand( + RawCommand::create('SENTINEL', 'sentinels', $this->service) + ); + + $this->sentinels = []; + $this->sentinelIndex = 0; + // NOTE: sentinel server does not return itself, so we add it back. + $this->sentinels[] = $sentinel->getParameters()->toArray(); + + foreach ($payload as $sentinel) { + $this->sentinels[] = [ + 'host' => $sentinel[3], + 'port' => $sentinel[5], + 'role' => 'sentinel', + ]; + } + } catch (ConnectionException $exception) { + $this->sentinelConnection = null; + + goto SENTINEL_QUERY; + } + } + } + + /** + * Fetches the details for the master and slave servers from a sentinel. + */ + public function querySentinel() + { + $this->wipeServerList(); + + $this->updateSentinels(); + $this->getMaster(); + $this->getSlaves(); + } + + /** + * Handles error responses returned by redis-sentinel. + * + * @param NodeConnectionInterface $sentinel Connection to a sentinel server. + * @param ErrorResponseInterface $error Error response. + */ + private function handleSentinelErrorResponse(NodeConnectionInterface $sentinel, ErrorResponseInterface $error) + { + if ($error->getErrorType() === 'IDONTKNOW') { + throw new ConnectionException($sentinel, $error->getMessage()); + } else { + throw new ServerException($error->getMessage()); + } + } + + /** + * Fetches the details for the master server from a sentinel. + * + * @param NodeConnectionInterface $sentinel Connection to a sentinel server. + * @param string $service Name of the service. + * + * @return array + */ + protected function querySentinelForMaster(NodeConnectionInterface $sentinel, $service) + { + $payload = $sentinel->executeCommand( + RawCommand::create('SENTINEL', 'get-master-addr-by-name', $service) + ); + + if ($payload === null) { + throw new ServerException('ERR No such master with that name'); + } + + if ($payload instanceof ErrorResponseInterface) { + $this->handleSentinelErrorResponse($sentinel, $payload); + } + + return [ + 'host' => $payload[0], + 'port' => $payload[1], + 'role' => 'master', + ]; + } + + /** + * Fetches the details for the slave servers from a sentinel. + * + * @param NodeConnectionInterface $sentinel Connection to a sentinel server. + * @param string $service Name of the service. + * + * @return array + */ + protected function querySentinelForSlaves(NodeConnectionInterface $sentinel, $service) + { + $slaves = []; + + $payload = $sentinel->executeCommand( + RawCommand::create('SENTINEL', 'slaves', $service) + ); + + if ($payload instanceof ErrorResponseInterface) { + $this->handleSentinelErrorResponse($sentinel, $payload); + } + + foreach ($payload as $slave) { + $flags = explode(',', $slave[9]); + + if (array_intersect($flags, ['s_down', 'o_down', 'disconnected'])) { + continue; + } + + // ensure `master-link-status` is ok + if (isset($slave[31]) && $slave[31] === 'err') { + continue; + } + + $slaves[] = [ + 'host' => $slave[3], + 'port' => $slave[5], + 'role' => 'slave', + ]; + } + + return $slaves; + } + + /** + * {@inheritdoc} + */ + public function getCurrent() + { + return $this->current; + } + + /** + * {@inheritdoc} + */ + public function getMaster() + { + if ($this->master) { + return $this->master; + } + + if ($this->updateSentinels) { + $this->updateSentinels(); + } + + SENTINEL_QUERY: { + $sentinel = $this->getSentinelConnection(); + + try { + $masterParameters = $this->querySentinelForMaster($sentinel, $this->service); + $masterConnection = $this->connectionFactory->create($masterParameters); + + $this->add($masterConnection); + } catch (ConnectionException $exception) { + $this->sentinelConnection = null; + + goto SENTINEL_QUERY; + } + } + + return $masterConnection; + } + + /** + * {@inheritdoc} + */ + public function getSlaves() + { + if ($this->slaves) { + return array_values($this->slaves); + } + + if ($this->updateSentinels) { + $this->updateSentinels(); + } + + SENTINEL_QUERY: { + $sentinel = $this->getSentinelConnection(); + + try { + $slavesParameters = $this->querySentinelForSlaves($sentinel, $this->service); + + foreach ($slavesParameters as $slaveParameters) { + $this->add($this->connectionFactory->create($slaveParameters)); + } + } catch (ConnectionException $exception) { + $this->sentinelConnection = null; + + goto SENTINEL_QUERY; + } + } + + return array_values($this->slaves); + } + + /** + * Returns a random slave. + * + * @return NodeConnectionInterface|null + */ + protected function pickSlave() + { + $slaves = $this->getSlaves(); + + return $slaves + ? $slaves[rand(1, count($slaves)) - 1] + : null; + } + + /** + * Returns the connection instance in charge for the given command. + * + * @param CommandInterface $command Command instance. + * + * @return NodeConnectionInterface + */ + private function getConnectionInternal(CommandInterface $command) + { + if (!$this->current) { + if ($this->strategy->isReadOperation($command) && $slave = $this->pickSlave()) { + $this->current = $slave; + } else { + $this->current = $this->getMaster(); + } + + return $this->current; + } + + if ($this->current === $this->master) { + return $this->current; + } + + if (!$this->strategy->isReadOperation($command)) { + $this->current = $this->getMaster(); + } + + return $this->current; + } + + /** + * Asserts that the specified connection matches an expected role. + * + * @param NodeConnectionInterface $connection Connection to a redis server. + * @param string $role Expected role of the server ("master", "slave" or "sentinel"). + * + * @throws RoleException|ConnectionException + */ + protected function assertConnectionRole(NodeConnectionInterface $connection, $role) + { + $role = strtolower($role); + $actualRole = $connection->executeCommand(RawCommand::create('ROLE')); + + if ($actualRole instanceof Error) { + throw new ConnectionException($connection, $actualRole->getMessage()); + } + + if ($role !== $actualRole[0]) { + throw new RoleException($connection, "Expected $role but got $actualRole[0] [$connection]"); + } + } + + /** + * {@inheritdoc} + */ + public function getConnectionByCommand(CommandInterface $command) + { + $connection = $this->getConnectionInternal($command); + + if (!$connection->isConnected()) { + // When we do not have any available slave in the pool we can expect + // read-only operations to hit the master server. + $expectedRole = $this->strategy->isReadOperation($command) && $this->slaves ? 'slave' : 'master'; + $this->assertConnectionRole($connection, $expectedRole); + } + + return $connection; + } + + /** + * {@inheritdoc} + */ + public function getConnectionById($id) + { + return $this->pool[$id] ?? null; + } + + /** + * Returns a connection by its role. + * + * @param string $role Connection role (`master`, `slave` or `sentinel`) + * + * @return NodeConnectionInterface|null + */ + public function getConnectionByRole($role) + { + if ($role === 'master') { + return $this->getMaster(); + } elseif ($role === 'slave') { + return $this->pickSlave(); + } elseif ($role === 'sentinel') { + return $this->getSentinelConnection(); + } else { + return null; + } + } + + /** + * Switches the internal connection in use by the backend. + * + * Sentinel connections are not considered as part of the pool, meaning that + * trying to switch to a sentinel will throw an exception. + * + * @param NodeConnectionInterface $connection Connection instance in the pool. + */ + public function switchTo(NodeConnectionInterface $connection) + { + if ($connection && $connection === $this->current) { + return; + } + + if ($connection !== $this->master && !in_array($connection, $this->slaves, true)) { + throw new InvalidArgumentException('Invalid connection or connection not found.'); + } + + $connection->connect(); + + if ($this->current) { + $this->current->disconnect(); + } + + $this->current = $connection; + } + + /** + * {@inheritdoc} + */ + public function switchToMaster() + { + $connection = $this->getConnectionByRole('master'); + $this->switchTo($connection); + } + + /** + * {@inheritdoc} + */ + public function switchToSlave() + { + $connection = $this->getConnectionByRole('slave'); + $this->switchTo($connection); + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return $this->current ? $this->current->isConnected() : false; + } + + /** + * {@inheritdoc} + */ + public function connect() + { + if (!$this->current) { + if (!$this->current = $this->pickSlave()) { + $this->current = $this->getMaster(); + } + } + + $this->current->connect(); + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + foreach ($this->pool as $connection) { + $connection->disconnect(); + } + } + + /** + * Retries the execution of a command upon server failure after asking a new + * configuration to one of the sentinels. + * + * @param CommandInterface $command Command instance. + * @param string $method Actual method. + * + * @return mixed + */ + private function retryCommandOnFailure(CommandInterface $command, $method) + { + $retries = 0; + + while ($retries <= $this->retryLimit) { + try { + $response = $this->getConnectionByCommand($command)->$method($command); + break; + } catch (CommunicationException $exception) { + $this->wipeServerList(); + $exception->getConnection()->disconnect(); + + if ($retries === $this->retryLimit) { + throw $exception; + } + + usleep($this->retryWait * 1000); + + ++$retries; + } + } + + return $response; + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + return $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + return $this->retryCommandOnFailure($command, __FUNCTION__); + } + + /** + * Returns the underlying replication strategy. + * + * @return ReplicationStrategy + */ + public function getReplicationStrategy() + { + return $this->strategy; + } + + /** + * {@inheritdoc} + */ + public function __sleep() + { + return [ + 'master', 'slaves', 'pool', 'service', 'sentinels', 'connectionFactory', 'strategy', + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/StreamConnection.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/StreamConnection.php new file mode 100644 index 000000000..18827c1cc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/StreamConnection.php @@ -0,0 +1,374 @@ +parameters->persistent) && $this->parameters->persistent) { + return; + } + + $this->disconnect(); + } + + /** + * {@inheritdoc} + */ + protected function assertParameters(ParametersInterface $parameters) + { + switch ($parameters->scheme) { + case 'tcp': + case 'redis': + case 'unix': + case 'tls': + case 'rediss': + break; + + default: + throw new InvalidArgumentException("Invalid scheme: '$parameters->scheme'."); + } + + return $parameters; + } + + /** + * {@inheritdoc} + */ + protected function createResource() + { + switch ($this->parameters->scheme) { + case 'tcp': + case 'redis': + return $this->tcpStreamInitializer($this->parameters); + + case 'unix': + return $this->unixStreamInitializer($this->parameters); + + case 'tls': + case 'rediss': + return $this->tlsStreamInitializer($this->parameters); + + default: + throw new InvalidArgumentException("Invalid scheme: '{$this->parameters->scheme}'."); + } + } + + /** + * Creates a connected stream socket resource. + * + * @param ParametersInterface $parameters Connection parameters. + * @param string $address Address for stream_socket_client(). + * @param int $flags Flags for stream_socket_client(). + * + * @return resource + */ + protected function createStreamSocket(ParametersInterface $parameters, $address, $flags) + { + $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0); + $context = stream_context_create(['socket' => ['tcp_nodelay' => (bool) $parameters->tcp_nodelay]]); + + if (!$resource = @stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context)) { + $this->onConnectionError(trim($errstr), $errno); + } + + if (isset($parameters->read_write_timeout)) { + $rwtimeout = (float) $parameters->read_write_timeout; + $rwtimeout = $rwtimeout > 0 ? $rwtimeout : -1; + $timeoutSeconds = floor($rwtimeout); + $timeoutUSeconds = ($rwtimeout - $timeoutSeconds) * 1000000; + stream_set_timeout($resource, $timeoutSeconds, $timeoutUSeconds); + } + + return $resource; + } + + /** + * Initializes a TCP stream resource. + * + * @param ParametersInterface $parameters Initialization parameters for the connection. + * + * @return resource + */ + protected function tcpStreamInitializer(ParametersInterface $parameters) + { + if (!filter_var($parameters->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $address = "tcp://$parameters->host:$parameters->port"; + } else { + $address = "tcp://[$parameters->host]:$parameters->port"; + } + + $flags = STREAM_CLIENT_CONNECT; + + if (isset($parameters->async_connect) && $parameters->async_connect) { + $flags |= STREAM_CLIENT_ASYNC_CONNECT; + } + + if (isset($parameters->persistent)) { + if (false !== $persistent = filter_var($parameters->persistent, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) { + $flags |= STREAM_CLIENT_PERSISTENT; + + if ($persistent === null) { + $address = "{$address}/{$parameters->persistent}"; + } + } + } + + return $this->createStreamSocket($parameters, $address, $flags); + } + + /** + * Initializes a UNIX stream resource. + * + * @param ParametersInterface $parameters Initialization parameters for the connection. + * + * @return resource + */ + protected function unixStreamInitializer(ParametersInterface $parameters) + { + if (!isset($parameters->path)) { + throw new InvalidArgumentException('Missing UNIX domain socket path.'); + } + + $flags = STREAM_CLIENT_CONNECT; + + if (isset($parameters->persistent)) { + if (false !== $persistent = filter_var($parameters->persistent, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)) { + $flags |= STREAM_CLIENT_PERSISTENT; + + if ($persistent === null) { + throw new InvalidArgumentException( + 'Persistent connection IDs are not supported when using UNIX domain sockets.' + ); + } + } + } + + return $this->createStreamSocket($parameters, "unix://{$parameters->path}", $flags); + } + + /** + * Initializes a SSL-encrypted TCP stream resource. + * + * @param ParametersInterface $parameters Initialization parameters for the connection. + * + * @return resource + */ + protected function tlsStreamInitializer(ParametersInterface $parameters) + { + $resource = $this->tcpStreamInitializer($parameters); + $metadata = stream_get_meta_data($resource); + + // Detect if crypto mode is already enabled for this stream (PHP >= 7.0.0). + if (isset($metadata['crypto'])) { + return $resource; + } + + if (isset($parameters->ssl) && is_array($parameters->ssl)) { + $options = $parameters->ssl; + } else { + $options = []; + } + + if (!isset($options['crypto_type'])) { + $options['crypto_type'] = STREAM_CRYPTO_METHOD_TLS_CLIENT; + } + + if (!stream_context_set_option($resource, ['ssl' => $options])) { + $this->onConnectionError('Error while setting SSL context options'); + } + + if (!stream_socket_enable_crypto($resource, true, $options['crypto_type'])) { + $this->onConnectionError('Error while switching to encrypted communication'); + } + + return $resource; + } + + /** + * {@inheritdoc} + */ + public function connect() + { + if (parent::connect() && $this->initCommands) { + foreach ($this->initCommands as $command) { + $response = $this->executeCommand($command); + + if ($response instanceof ErrorResponseInterface && $command->getId() === 'CLIENT') { + // Do nothing on CLIENT SETINFO command failure + } elseif ($response instanceof ErrorResponseInterface) { + $this->onConnectionError("`{$command->getId()}` failed: {$response->getMessage()}", 0); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + if ($this->isConnected()) { + $resource = $this->getResource(); + if (is_resource($resource)) { + fclose($resource); + } + parent::disconnect(); + } + } + + /** + * Performs a write operation over the stream of the buffer containing a + * command serialized with the Redis wire protocol. + * + * @param string $buffer Representation of a command in the Redis wire protocol. + */ + protected function write($buffer) + { + $socket = $this->getResource(); + + while (($length = strlen($buffer)) > 0) { + $written = is_resource($socket) ? @fwrite($socket, $buffer) : false; + + if ($length === $written) { + return; + } + + if ($written === false || $written === 0) { + $this->onConnectionError('Error while writing bytes to the server.'); + } + + $buffer = substr($buffer, $written); + } + } + + /** + * {@inheritdoc} + */ + public function read() + { + $socket = $this->getResource(); + $chunk = fgets($socket); + + if ($chunk === false || $chunk === '') { + $this->onConnectionError('Error while reading line from the server.'); + } + + $prefix = $chunk[0]; + $payload = substr($chunk, 1, -2); + + switch ($prefix) { + case '+': + return StatusResponse::get($payload); + + case '$': + $size = (int) $payload; + + if ($size === -1) { + return; + } + + $bulkData = ''; + $bytesLeft = ($size += 2); + + do { + $chunk = is_resource($socket) ? fread($socket, min($bytesLeft, 4096)) : false; + + if ($chunk === false || $chunk === '') { + $this->onConnectionError('Error while reading bytes from the server.'); + } + + $bulkData .= $chunk; + $bytesLeft = $size - strlen($bulkData); + } while ($bytesLeft > 0); + + return substr($bulkData, 0, -2); + + case '*': + $count = (int) $payload; + + if ($count === -1) { + return; + } + + $multibulk = []; + + for ($i = 0; $i < $count; ++$i) { + $multibulk[$i] = $this->read(); + } + + return $multibulk; + + case ':': + $integer = (int) $payload; + + return $integer == $payload ? $integer : $payload; + + case '-': + return new ErrorResponse($payload); + + default: + $this->onProtocolError("Unknown response prefix: '$prefix'."); + + return; + } + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $commandID = $command->getId(); + $arguments = $command->getArguments(); + + $cmdlen = strlen($commandID); + $reqlen = count($arguments) + 1; + + $buffer = "*{$reqlen}\r\n\${$cmdlen}\r\n{$commandID}\r\n"; + + foreach ($arguments as $argument) { + $arglen = strlen(strval($argument)); + $buffer .= "\${$arglen}\r\n{$argument}\r\n"; + } + + $this->write($buffer); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/WebdisConnection.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/WebdisConnection.php new file mode 100644 index 000000000..040f557bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Connection/WebdisConnection.php @@ -0,0 +1,366 @@ +assertExtensions(); + + if ($parameters->scheme !== 'http') { + throw new InvalidArgumentException("Invalid scheme: '{$parameters->scheme}'."); + } + + $this->parameters = $parameters; + + $this->resource = $this->createCurl(); + $this->reader = $this->createReader(); + } + + /** + * Frees the underlying cURL and protocol reader resources when the garbage + * collector kicks in. + */ + public function __destruct() + { + curl_close($this->resource); + phpiredis_reader_destroy($this->reader); + } + + /** + * Helper method used to throw on unsupported methods. + * + * @param string $method Name of the unsupported method. + * + * @throws NotSupportedException + */ + private function throwNotSupportedException($method) + { + $class = __CLASS__; + throw new NotSupportedException("The method $class::$method() is not supported."); + } + + /** + * Checks if the cURL and phpiredis extensions are loaded in PHP. + */ + private function assertExtensions() + { + if (!extension_loaded('curl')) { + throw new NotSupportedException( + 'The "curl" extension is required by this connection backend.' + ); + } + + if (!extension_loaded('phpiredis')) { + throw new NotSupportedException( + 'The "phpiredis" extension is required by this connection backend.' + ); + } + } + + /** + * Initializes cURL. + * + * @return resource + */ + private function createCurl() + { + $parameters = $this->getParameters(); + $timeout = (isset($parameters->timeout) ? (float) $parameters->timeout : 5.0) * 1000; + + if (filter_var($host = $parameters->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $host = "[$host]"; + } + + $options = [ + CURLOPT_FAILONERROR => true, + CURLOPT_CONNECTTIMEOUT_MS => $timeout, + CURLOPT_URL => "$parameters->scheme://$host:$parameters->port", + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_POST => true, + CURLOPT_WRITEFUNCTION => [$this, 'feedReader'], + ]; + + if (isset($parameters->user, $parameters->pass)) { + $options[CURLOPT_USERPWD] = "{$parameters->user}:{$parameters->pass}"; + } + + curl_setopt_array($resource = curl_init(), $options); + + return $resource; + } + + /** + * Initializes the phpiredis protocol reader. + * + * @return resource + */ + private function createReader() + { + $reader = phpiredis_reader_create(); + + phpiredis_reader_set_status_handler($reader, $this->getStatusHandler()); + phpiredis_reader_set_error_handler($reader, $this->getErrorHandler()); + + return $reader; + } + + /** + * Returns the handler used by the protocol reader for inline responses. + * + * @return Closure + */ + protected function getStatusHandler() + { + static $statusHandler; + + if (!$statusHandler) { + $statusHandler = function ($payload) { + return StatusResponse::get($payload); + }; + } + + return $statusHandler; + } + + /** + * Returns the handler used by the protocol reader for error responses. + * + * @return Closure + */ + protected function getErrorHandler() + { + static $errorHandler; + + if (!$errorHandler) { + $errorHandler = function ($errorMessage) { + return new ErrorResponse($errorMessage); + }; + } + + return $errorHandler; + } + + /** + * Feeds the phpredis reader resource with the data read from the network. + * + * @param resource $resource Reader resource. + * @param string $buffer Buffer of data read from a connection. + * + * @return int + */ + protected function feedReader($resource, $buffer) + { + phpiredis_reader_feed($this->reader, $buffer); + + return strlen($buffer); + } + + /** + * {@inheritdoc} + */ + public function connect() + { + // NOOP + } + + /** + * {@inheritdoc} + */ + public function disconnect() + { + // NOOP + } + + /** + * {@inheritdoc} + */ + public function isConnected() + { + return true; + } + + /** + * Checks if the specified command is supported by this connection class. + * + * @param CommandInterface $command Command instance. + * + * @return string + * @throws NotSupportedException + */ + protected function getCommandId(CommandInterface $command) + { + switch ($commandID = $command->getId()) { + case 'AUTH': + case 'SELECT': + case 'MULTI': + case 'EXEC': + case 'WATCH': + case 'UNWATCH': + case 'DISCARD': + case 'MONITOR': + throw new NotSupportedException("Command '$commandID' is not allowed by Webdis."); + default: + return $commandID; + } + } + + /** + * {@inheritdoc} + */ + public function writeRequest(CommandInterface $command) + { + $this->throwNotSupportedException(__FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function readResponse(CommandInterface $command) + { + $this->throwNotSupportedException(__FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + $resource = $this->resource; + $commandId = $this->getCommandId($command); + + if ($arguments = $command->getArguments()) { + $arguments = implode('/', array_map('urlencode', $arguments)); + $serializedCommand = "$commandId/$arguments.raw"; + } else { + $serializedCommand = "$commandId.raw"; + } + + curl_setopt($resource, CURLOPT_POSTFIELDS, $serializedCommand); + + if (curl_exec($resource) === false) { + $error = trim(curl_error($resource)); + $errno = curl_errno($resource); + + throw new ConnectionException($this, "$error{$this->getParameters()}]", $errno); + } + + if (phpiredis_reader_get_state($this->reader) !== PHPIREDIS_READER_STATE_COMPLETE) { + throw new ProtocolException($this, phpiredis_reader_get_error($this->reader)); + } + + return phpiredis_reader_get_reply($this->reader); + } + + /** + * {@inheritdoc} + */ + public function getResource() + { + return $this->resource; + } + + /** + * {@inheritdoc} + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * {@inheritdoc} + */ + public function addConnectCommand(CommandInterface $command) + { + $this->throwNotSupportedException(__FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function read() + { + $this->throwNotSupportedException(__FUNCTION__); + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return "{$this->parameters->host}:{$this->parameters->port}"; + } + + /** + * {@inheritdoc} + */ + public function __sleep() + { + return ['parameters']; + } + + /** + * {@inheritdoc} + */ + public function __wakeup() + { + $this->assertExtensions(); + + $this->resource = $this->createCurl(); + $this->reader = $this->createReader(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Monitor/Consumer.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Monitor/Consumer.php new file mode 100644 index 000000000..7fd6c6be8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Monitor/Consumer.php @@ -0,0 +1,179 @@ +assertClient($client); + + $this->client = $client; + + $this->start(); + } + + /** + * Automatically stops the consumer when the garbage collector kicks in. + */ + public function __destruct() + { + $this->stop(); + } + + /** + * Checks if the passed client instance satisfies the required conditions + * needed to initialize a monitor consumer. + * + * @param ClientInterface $client Client instance used by the consumer. + * + * @throws NotSupportedException + */ + private function assertClient(ClientInterface $client) + { + if ($client->getConnection() instanceof ClusterInterface) { + throw new NotSupportedException( + 'Cannot initialize a monitor consumer over cluster connections.' + ); + } + + if (!$client->getCommandFactory()->supports('MONITOR')) { + throw new NotSupportedException("'MONITOR' is not supported by the current command factory."); + } + } + + /** + * Initializes the consumer and sends the MONITOR command to the server. + */ + protected function start() + { + $this->client->executeCommand( + $this->client->createCommand('MONITOR') + ); + $this->valid = true; + } + + /** + * Stops the consumer. Internally this is done by disconnecting from server + * since there is no way to terminate the stream initialized by MONITOR. + */ + public function stop() + { + $this->client->disconnect(); + $this->valid = false; + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + // NOOP + } + + /** + * Returns the last message payload retrieved from the server. + * + * @return object + */ + #[ReturnTypeWillChange] + public function current() + { + return $this->getValue(); + } + + /** + * @return int|null + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->position; + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + ++$this->position; + } + + /** + * Checks if the the consumer is still in a valid state to continue. + * + * @return bool + */ + #[ReturnTypeWillChange] + public function valid() + { + return $this->valid; + } + + /** + * Waits for a new message from the server generated by MONITOR and returns + * it when available. + * + * @return object + */ + private function getValue() + { + $database = 0; + $client = null; + $event = $this->client->getConnection()->read(); + + $callback = function ($matches) use (&$database, &$client) { + if (2 === $count = count($matches)) { + // Redis <= 2.4 + $database = (int) $matches[1]; + } + + if (4 === $count) { + // Redis >= 2.6 + $database = (int) $matches[2]; + $client = $matches[3]; + } + + return ' '; + }; + + $event = preg_replace_callback('/ \(db (\d+)\) | \[(\d+) (.*?)\] /', $callback, $event, 1); + @[$timestamp, $command, $arguments] = explode(' ', $event, 3); + + return (object) [ + 'timestamp' => (float) $timestamp, + 'database' => $database, + 'client' => $client, + 'command' => substr($command, 1, -1), + 'arguments' => $arguments, + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/NotSupportedException.php b/.extlib/simplesamlphp/vendor/predis/predis/src/NotSupportedException.php new file mode 100644 index 000000000..e766c9a11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/NotSupportedException.php @@ -0,0 +1,21 @@ +getCommandFactory()->supports('multi', 'exec', 'discard')) { + throw new ClientException( + "'MULTI', 'EXEC' and 'DISCARD' are not supported by the current command factory." + ); + } + + parent::__construct($client); + } + + /** + * {@inheritdoc} + */ + protected function getConnection() + { + $connection = $this->getClient()->getConnection(); + + if (!$connection instanceof NodeConnectionInterface) { + $class = __CLASS__; + + throw new ClientException("The class '$class' does not support aggregate connections."); + } + + return $connection; + } + + /** + * {@inheritdoc} + */ + protected function executePipeline(ConnectionInterface $connection, SplQueue $commands) + { + $commandFactory = $this->getClient()->getCommandFactory(); + $connection->executeCommand($commandFactory->create('multi')); + + foreach ($commands as $command) { + $connection->writeRequest($command); + } + + foreach ($commands as $command) { + $response = $connection->readResponse($command); + + if ($response instanceof ErrorResponseInterface) { + $connection->executeCommand($commandFactory->create('discard')); + throw new ServerException($response->getMessage()); + } + } + + $executed = $connection->executeCommand($commandFactory->create('exec')); + + if (!isset($executed)) { + throw new ClientException( + 'The underlying transaction has been aborted by the server.' + ); + } + + if (count($executed) !== count($commands)) { + $expected = count($commands); + $received = count($executed); + + throw new ClientException( + "Invalid number of responses [expected $expected, received $received]." + ); + } + + $responses = []; + $sizeOfPipe = count($commands); + $exceptions = $this->throwServerExceptions(); + + for ($i = 0; $i < $sizeOfPipe; ++$i) { + $command = $commands->dequeue(); + $response = $executed[$i]; + + if (!$response instanceof ResponseInterface) { + $responses[] = $command->parseResponse($response); + } elseif ($response instanceof ErrorResponseInterface && $exceptions) { + $this->exception($connection, $response); + } else { + $responses[] = $response; + } + + unset($executed[$i]); + } + + return $responses; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/ConnectionErrorProof.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/ConnectionErrorProof.php new file mode 100644 index 000000000..e6d96ee2c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/ConnectionErrorProof.php @@ -0,0 +1,128 @@ +getClient()->getConnection(); + } + + /** + * {@inheritdoc} + */ + protected function executePipeline(ConnectionInterface $connection, SplQueue $commands) + { + if ($connection instanceof NodeConnectionInterface) { + return $this->executeSingleNode($connection, $commands); + } elseif ($connection instanceof ClusterInterface) { + return $this->executeCluster($connection, $commands); + } else { + $class = get_class($connection); + + throw new NotSupportedException("The connection class '$class' is not supported."); + } + } + + /** + * {@inheritdoc} + */ + protected function executeSingleNode(NodeConnectionInterface $connection, SplQueue $commands) + { + $responses = []; + $sizeOfPipe = count($commands); + + foreach ($commands as $command) { + try { + $connection->writeRequest($command); + } catch (CommunicationException $exception) { + return array_fill(0, $sizeOfPipe, $exception); + } + } + + for ($i = 0; $i < $sizeOfPipe; ++$i) { + $command = $commands->dequeue(); + + try { + $responses[$i] = $connection->readResponse($command); + } catch (CommunicationException $exception) { + $add = count($commands) - count($responses); + $responses = array_merge($responses, array_fill(0, $add, $exception)); + + break; + } + } + + return $responses; + } + + /** + * {@inheritdoc} + */ + protected function executeCluster(ClusterInterface $connection, SplQueue $commands) + { + $responses = []; + $sizeOfPipe = count($commands); + $exceptions = []; + + foreach ($commands as $command) { + $cmdConnection = $connection->getConnectionByCommand($command); + + if (isset($exceptions[spl_object_hash($cmdConnection)])) { + continue; + } + + try { + $cmdConnection->writeRequest($command); + } catch (CommunicationException $exception) { + $exceptions[spl_object_hash($cmdConnection)] = $exception; + } + } + + for ($i = 0; $i < $sizeOfPipe; ++$i) { + $command = $commands->dequeue(); + + $cmdConnection = $connection->getConnectionByCommand($command); + $connectionHash = spl_object_hash($cmdConnection); + + if (isset($exceptions[$connectionHash])) { + $responses[$i] = $exceptions[$connectionHash]; + continue; + } + + try { + $responses[$i] = $cmdConnection->readResponse($command); + } catch (CommunicationException $exception) { + $responses[$i] = $exception; + $exceptions[$connectionHash] = $exception; + } + } + + return $responses; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/FireAndForget.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/FireAndForget.php new file mode 100644 index 000000000..1f646ff77 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/FireAndForget.php @@ -0,0 +1,36 @@ +isEmpty()) { + $connection->writeRequest($commands->dequeue()); + } + + $connection->disconnect(); + + return []; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/Pipeline.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/Pipeline.php new file mode 100644 index 000000000..30c5601d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/Pipeline.php @@ -0,0 +1,248 @@ +client = $client; + $this->pipeline = new SplQueue(); + } + + /** + * Queues a command into the pipeline buffer. + * + * @param string $method Command ID. + * @param array $arguments Arguments for the command. + * + * @return $this + */ + public function __call($method, $arguments) + { + $command = $this->client->createCommand($method, $arguments); + $this->recordCommand($command); + + return $this; + } + + /** + * Queues a command instance into the pipeline buffer. + * + * @param CommandInterface $command Command to be queued in the buffer. + */ + protected function recordCommand(CommandInterface $command) + { + $this->pipeline->enqueue($command); + } + + /** + * Queues a command instance into the pipeline buffer. + * + * @param CommandInterface $command Command instance to be queued in the buffer. + * + * @return $this + */ + public function executeCommand(CommandInterface $command) + { + $this->recordCommand($command); + + return $this; + } + + /** + * Throws an exception on -ERR responses returned by Redis. + * + * @param ConnectionInterface $connection Redis connection that returned the error. + * @param ErrorResponseInterface $response Instance of the error response. + * + * @throws ServerException + */ + protected function exception(ConnectionInterface $connection, ErrorResponseInterface $response) + { + $connection->disconnect(); + $message = $response->getMessage(); + + throw new ServerException($message); + } + + /** + * Returns the underlying connection to be used by the pipeline. + * + * @return ConnectionInterface + */ + protected function getConnection() + { + $connection = $this->getClient()->getConnection(); + + if ($connection instanceof ReplicationInterface) { + $connection->switchToMaster(); + } + + return $connection; + } + + /** + * Implements the logic to flush the queued commands and read the responses + * from the current connection. + * + * @param ConnectionInterface $connection Current connection instance. + * @param SplQueue $commands Queued commands. + * + * @return array + */ + protected function executePipeline(ConnectionInterface $connection, SplQueue $commands) + { + foreach ($commands as $command) { + $connection->writeRequest($command); + } + + $responses = []; + $exceptions = $this->throwServerExceptions(); + + while (!$commands->isEmpty()) { + $command = $commands->dequeue(); + $response = $connection->readResponse($command); + + if (!$response instanceof ResponseInterface) { + $responses[] = $command->parseResponse($response); + } elseif ($response instanceof ErrorResponseInterface && $exceptions) { + $this->exception($connection, $response); + } else { + $responses[] = $response; + } + } + + return $responses; + } + + /** + * Flushes the buffer holding all of the commands queued so far. + * + * @param bool $send Specifies if the commands in the buffer should be sent to Redis. + * + * @return $this + */ + public function flushPipeline($send = true) + { + if ($send && !$this->pipeline->isEmpty()) { + $responses = $this->executePipeline($this->getConnection(), $this->pipeline); + $this->responses = array_merge($this->responses, $responses); + } else { + $this->pipeline = new SplQueue(); + } + + return $this; + } + + /** + * Marks the running status of the pipeline. + * + * @param bool $bool Sets the running status of the pipeline. + * + * @throws ClientException + */ + private function setRunning($bool) + { + if ($bool && $this->running) { + throw new ClientException('The current pipeline context is already being executed.'); + } + + $this->running = $bool; + } + + /** + * Handles the actual execution of the whole pipeline. + * + * @param mixed $callable Optional callback for execution. + * + * @return array + * @throws Exception + * @throws InvalidArgumentException + */ + public function execute($callable = null) + { + if ($callable && !is_callable($callable)) { + throw new InvalidArgumentException('The argument must be a callable object.'); + } + + $exception = null; + $this->setRunning(true); + + try { + if ($callable) { + call_user_func($callable, $this); + } + + $this->flushPipeline(); + } catch (Exception $exception) { + // NOOP + } + + $this->setRunning(false); + + if ($exception) { + throw $exception; + } + + return $this->responses; + } + + /** + * Returns if the pipeline should throw exceptions on server errors. + * + * @return bool + */ + protected function throwServerExceptions() + { + return (bool) $this->client->getOptions()->exceptions; + } + + /** + * Returns the underlying client instance used by the pipeline object. + * + * @return ClientInterface + */ + public function getClient() + { + return $this->client; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayAtomic.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayAtomic.php new file mode 100644 index 000000000..c3fce43ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayAtomic.php @@ -0,0 +1,69 @@ +getClient(); + + $throw = $this->client->getOptions()->exceptions; + + try { + $transaction = $client->multi(); + + foreach ($commands as $command) { + $name = $command->getId(); + + in_array($name, $connection->atypicalCommands) + ? $transaction->{$name}(...$command->getArguments()) + : $transaction->rawCommand($name, ...$command->getArguments()); + } + + $responses = $transaction->exec(); + + if (!is_array($responses)) { + return $responses; + } + + foreach ($responses as $key => $response) { + if ($response instanceof RelayException) { + if ($throw) { + throw $response; + } + + $responses[$key] = new Error($response->getMessage()); + } + } + + return $responses; + } catch (RelayException $ex) { + if ($client->getMode() !== $client::ATOMIC) { + $client->discard(); + } + + throw new ServerException($ex->getMessage(), $ex->getCode(), $ex); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayPipeline.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayPipeline.php new file mode 100644 index 000000000..00f083352 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Pipeline/RelayPipeline.php @@ -0,0 +1,75 @@ +getClient(); + + $throw = $this->client->getOptions()->exceptions; + + try { + $pipeline = $client->pipeline(); + + foreach ($commands as $command) { + $name = $command->getId(); + + in_array($name, $connection->atypicalCommands) + ? $pipeline->{$name}(...$command->getArguments()) + : $pipeline->rawCommand($name, ...$command->getArguments()); + } + + $responses = $pipeline->exec(); + + if (!is_array($responses)) { + return $responses; + } + + foreach ($responses as $key => $response) { + if ($response instanceof RelayException) { + if ($throw) { + throw $response; + } + + $responses[$key] = new Error($response->getMessage()); + } + } + + return $responses; + } catch (RelayException $ex) { + if ($client->getMode() !== $client::ATOMIC) { + $client->discard(); + } + + throw new ServerException($ex->getMessage(), $ex->getCode(), $ex); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/PredisException.php b/.extlib/simplesamlphp/vendor/predis/predis/src/PredisException.php new file mode 100644 index 000000000..dc11c0d1c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/PredisException.php @@ -0,0 +1,22 @@ +setRequestSerializer($serializer ?: new RequestSerializer()); + $this->setResponseReader($reader ?: new ResponseReader()); + } + + /** + * {@inheritdoc} + */ + public function write(CompositeConnectionInterface $connection, CommandInterface $command) + { + $connection->writeBuffer($this->serializer->serialize($command)); + } + + /** + * {@inheritdoc} + */ + public function read(CompositeConnectionInterface $connection) + { + return $this->reader->read($connection); + } + + /** + * Sets the request serializer used by the protocol processor. + * + * @param RequestSerializerInterface $serializer Request serializer. + */ + public function setRequestSerializer(RequestSerializerInterface $serializer) + { + $this->serializer = $serializer; + } + + /** + * Returns the request serializer used by the protocol processor. + * + * @return RequestSerializerInterface + */ + public function getRequestSerializer() + { + return $this->serializer; + } + + /** + * Sets the response reader used by the protocol processor. + * + * @param ResponseReaderInterface $reader Response reader. + */ + public function setResponseReader(ResponseReaderInterface $reader) + { + $this->reader = $reader; + } + + /** + * Returns the Response reader used by the protocol processor. + * + * @return ResponseReaderInterface + */ + public function getResponseReader() + { + return $this->reader; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/BulkResponse.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/BulkResponse.php new file mode 100644 index 000000000..39963333d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/BulkResponse.php @@ -0,0 +1,54 @@ +getParameters()}]" + )); + } + + if ($length >= 0) { + return substr($connection->readBuffer($length + 2), 0, -2); + } + + if ($length == -1) { + return; + } + + CommunicationException::handle(new ProtocolException( + $connection, "Value '$payload' is not a valid length for a bulk response [{$connection->getParameters()}]" + )); + + return; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ErrorResponse.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ErrorResponse.php new file mode 100644 index 000000000..fb980407e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ErrorResponse.php @@ -0,0 +1,33 @@ +getParameters()}]" + )); + } + + return; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/MultiBulkResponse.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/MultiBulkResponse.php new file mode 100644 index 000000000..f470d9167 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/MultiBulkResponse.php @@ -0,0 +1,67 @@ +getParameters()}]" + )); + } + + if ($length === -1) { + return; + } + + $list = []; + + if ($length > 0) { + $handlersCache = []; + $reader = $connection->getProtocol()->getResponseReader(); + + for ($i = 0; $i < $length; ++$i) { + $header = $connection->readLine(); + $prefix = $header[0]; + + if (isset($handlersCache[$prefix])) { + $handler = $handlersCache[$prefix]; + } else { + $handler = $reader->getHandler($prefix); + $handlersCache[$prefix] = $handler; + } + + $list[$i] = $handler->handle($connection, substr($header, 1)); + } + } + + return $list; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ResponseHandlerInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ResponseHandlerInterface.php new file mode 100644 index 000000000..870074a62 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/Handler/ResponseHandlerInterface.php @@ -0,0 +1,32 @@ +getParameters()}]" + )); + } + + return new MultiBulkIterator($connection, $length); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ProtocolProcessor.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ProtocolProcessor.php new file mode 100644 index 000000000..ac44e231c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ProtocolProcessor.php @@ -0,0 +1,120 @@ +mbiterable = false; + $this->serializer = new RequestSerializer(); + } + + /** + * {@inheritdoc} + */ + public function write(CompositeConnectionInterface $connection, CommandInterface $command) + { + $request = $this->serializer->serialize($command); + $connection->writeBuffer($request); + } + + /** + * {@inheritdoc} + */ + public function read(CompositeConnectionInterface $connection) + { + $chunk = $connection->readLine(); + $prefix = $chunk[0]; + $payload = substr($chunk, 1); + + switch ($prefix) { + case '+': + return new StatusResponse($payload); + + case '$': + $size = (int) $payload; + if ($size === -1) { + return; + } + + return substr($connection->readBuffer($size + 2), 0, -2); + + case '*': + $count = (int) $payload; + + if ($count === -1) { + return; + } + if ($this->mbiterable) { + return new MultiBulkIterator($connection, $count); + } + + $multibulk = []; + + for ($i = 0; $i < $count; ++$i) { + $multibulk[$i] = $this->read($connection); + } + + return $multibulk; + + case ':': + $integer = (int) $payload; + + return $integer == $payload ? $integer : $payload; + + case '-': + return new ErrorResponse($payload); + + default: + CommunicationException::handle(new ProtocolException( + $connection, "Unknown response prefix: '$prefix' [{$connection->getParameters()}]" + )); + + return; + } + } + + /** + * Enables or disables returning multibulk responses as specialized PHP + * iterators used to stream bulk elements of a multibulk response instead + * returning a plain array. + * + * Streamable multibulk responses are not globally supported by the + * abstractions built-in into Predis, such as transactions or pipelines. + * Use them with care! + * + * @param bool $value Enable or disable streamable multibulk responses. + */ + public function useIterableMultibulk($value) + { + $this->mbiterable = (bool) $value; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/RequestSerializer.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/RequestSerializer.php new file mode 100644 index 000000000..31d110b2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/RequestSerializer.php @@ -0,0 +1,45 @@ +getId(); + $arguments = $command->getArguments(); + + $cmdlen = strlen($commandID); + $reqlen = count($arguments) + 1; + + $buffer = "*{$reqlen}\r\n\${$cmdlen}\r\n{$commandID}\r\n"; + + foreach ($arguments as $argument) { + $arglen = strlen($argument); + $buffer .= "\${$arglen}\r\n{$argument}\r\n"; + } + + return $buffer; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ResponseReader.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ResponseReader.php new file mode 100644 index 000000000..0c7c0e90e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Protocol/Text/ResponseReader.php @@ -0,0 +1,110 @@ +handlers = $this->getDefaultHandlers(); + } + + /** + * Returns the default handlers for the supported type of responses. + * + * @return array + */ + protected function getDefaultHandlers() + { + return [ + '+' => new Handler\StatusResponse(), + '-' => new Handler\ErrorResponse(), + ':' => new Handler\IntegerResponse(), + '$' => new Handler\BulkResponse(), + '*' => new Handler\MultiBulkResponse(), + ]; + } + + /** + * Sets the handler for the specified prefix identifying the response type. + * + * @param string $prefix Identifier of the type of response. + * @param Handler\ResponseHandlerInterface $handler Response handler. + */ + public function setHandler($prefix, Handler\ResponseHandlerInterface $handler) + { + $this->handlers[$prefix] = $handler; + } + + /** + * Returns the response handler associated to a certain type of response. + * + * @param string $prefix Identifier of the type of response. + * + * @return Handler\ResponseHandlerInterface + */ + public function getHandler($prefix) + { + if (isset($this->handlers[$prefix])) { + return $this->handlers[$prefix]; + } + + return; + } + + /** + * {@inheritdoc} + */ + public function read(CompositeConnectionInterface $connection) + { + $header = $connection->readLine(); + + if ($header === '') { + $this->onProtocolError($connection, 'Unexpected empty response header'); + } + + $prefix = $header[0]; + + if (!isset($this->handlers[$prefix])) { + $this->onProtocolError($connection, "Unknown response prefix: '$prefix'"); + } + + return $this->handlers[$prefix]->handle($connection, substr($header, 1)); + } + + /** + * Handles protocol errors generated while reading responses from a + * connection. + * + * @param CompositeConnectionInterface $connection Redis connection that generated the error. + * @param string $message Error message. + */ + protected function onProtocolError(CompositeConnectionInterface $connection, $message) + { + CommunicationException::handle( + new ProtocolException($connection, "$message [{$connection->getParameters()}]") + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/AbstractConsumer.php b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/AbstractConsumer.php new file mode 100644 index 000000000..98b1fb002 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/AbstractConsumer.php @@ -0,0 +1,226 @@ +stop(true); + } + + /** + * Checks if the specified flag is valid based on the state of the consumer. + * + * @param int $value Flag. + * + * @return bool + */ + protected function isFlagSet($value) + { + return ($this->statusFlags & $value) === $value; + } + + /** + * Subscribes to the specified channels. + * + * @param string ...$channel One or more channel names. + */ + public function subscribe($channel /* , ... */) + { + $this->writeRequest(self::SUBSCRIBE, func_get_args()); + $this->statusFlags |= self::STATUS_SUBSCRIBED; + } + + /** + * Unsubscribes from the specified channels. + * + * @param string ...$channel One or more channel names. + */ + public function unsubscribe(...$channel) + { + $this->writeRequest(self::UNSUBSCRIBE, func_get_args()); + } + + /** + * Subscribes to the specified channels using a pattern. + * + * @param string ...$pattern One or more channel name patterns. + */ + public function psubscribe(...$pattern) + { + $this->writeRequest(self::PSUBSCRIBE, func_get_args()); + $this->statusFlags |= self::STATUS_PSUBSCRIBED; + } + + /** + * Unsubscribes from the specified channels using a pattern. + * + * @param string ...$pattern One or more channel name patterns. + */ + public function punsubscribe(...$pattern) + { + $this->writeRequest(self::PUNSUBSCRIBE, func_get_args()); + } + + /** + * PING the server with an optional payload that will be echoed as a + * PONG message in the pub/sub loop. + * + * @param string $payload Optional PING payload. + */ + public function ping($payload = null) + { + $this->writeRequest('PING', [$payload]); + } + + /** + * Closes the context by unsubscribing from all the subscribed channels. The + * context can be forcefully closed by dropping the underlying connection. + * + * @param bool $drop Indicates if the context should be closed by dropping the connection. + * + * @return bool Returns false when there are no pending messages. + */ + public function stop($drop = false) + { + if (!$this->valid()) { + return false; + } + + if ($drop) { + $this->invalidate(); + $this->disconnect(); + } else { + if ($this->isFlagSet(self::STATUS_SUBSCRIBED)) { + $this->unsubscribe(); + } + if ($this->isFlagSet(self::STATUS_PSUBSCRIBED)) { + $this->punsubscribe(); + } + } + + return !$drop; + } + + /** + * Closes the underlying connection when forcing a disconnection. + */ + abstract protected function disconnect(); + + /** + * Writes a Redis command on the underlying connection. + * + * @param string $method Command ID. + * @param array $arguments Arguments for the command. + */ + abstract protected function writeRequest($method, $arguments); + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + // NOOP + } + + /** + * Returns the last message payload retrieved from the server and generated + * by one of the active subscriptions. + * + * @return array + */ + #[ReturnTypeWillChange] + public function current() + { + return $this->getValue(); + } + + /** + * @return int|null + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->position; + } + + /** + * @return int|null + */ + #[ReturnTypeWillChange] + public function next() + { + if ($this->valid()) { + ++$this->position; + } + + return $this->position; + } + + /** + * Checks if the the consumer is still in a valid state to continue. + * + * @return bool + */ + #[ReturnTypeWillChange] + public function valid() + { + $isValid = $this->isFlagSet(self::STATUS_VALID); + $subscriptionFlags = self::STATUS_SUBSCRIBED | self::STATUS_PSUBSCRIBED; + $hasSubscriptions = ($this->statusFlags & $subscriptionFlags) > 0; + + return $isValid && $hasSubscriptions; + } + + /** + * Resets the state of the consumer. + */ + protected function invalidate() + { + $this->statusFlags = 0; // 0b0000; + } + + /** + * Waits for a new message from the server generated by one of the active + * subscriptions and returns it when available. + * + * @return array + */ + abstract protected function getValue(); +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/Consumer.php b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/Consumer.php new file mode 100644 index 000000000..7c3e244e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/Consumer.php @@ -0,0 +1,157 @@ +checkCapabilities($client); + + $this->options = $options ?: []; + $this->client = $client; + + $this->genericSubscribeInit('subscribe'); + $this->genericSubscribeInit('psubscribe'); + } + + /** + * Returns the underlying client instance used by the pub/sub iterator. + * + * @return ClientInterface + */ + public function getClient() + { + return $this->client; + } + + /** + * Checks if the client instance satisfies the required conditions needed to + * initialize a PUB/SUB consumer. + * + * @param ClientInterface $client Client instance used by the consumer. + * + * @throws NotSupportedException + */ + protected function checkCapabilities(ClientInterface $client) + { + if ($client->getConnection() instanceof ClusterInterface) { + throw new NotSupportedException( + 'Cannot initialize a PUB/SUB consumer over cluster connections.' + ); + } + + $commands = ['publish', 'subscribe', 'unsubscribe', 'psubscribe', 'punsubscribe']; + + if (!$client->getCommandFactory()->supports(...$commands)) { + throw new NotSupportedException( + 'PUB/SUB commands are not supported by the current command factory.' + ); + } + } + + /** + * This method shares the logic to handle both SUBSCRIBE and PSUBSCRIBE. + * + * @param string $subscribeAction Type of subscription. + */ + protected function genericSubscribeInit($subscribeAction) + { + if (isset($this->options[$subscribeAction])) { + $this->$subscribeAction($this->options[$subscribeAction]); + } + } + + /** + * {@inheritdoc} + */ + protected function writeRequest($method, $arguments) + { + $this->client->getConnection()->writeRequest( + $this->client->createCommand($method, + Command::normalizeArguments($arguments) + ) + ); + } + + /** + * {@inheritdoc} + */ + protected function disconnect() + { + $this->client->disconnect(); + } + + /** + * {@inheritdoc} + */ + protected function getValue() + { + $response = $this->client->getConnection()->read(); + + switch ($response[0]) { + case self::SUBSCRIBE: + case self::UNSUBSCRIBE: + case self::PSUBSCRIBE: + case self::PUNSUBSCRIBE: + if ($response[2] === 0) { + $this->invalidate(); + } + // The missing break here is intentional as we must process + // subscriptions and unsubscriptions as standard messages. + // no break + + case self::MESSAGE: + return (object) [ + 'kind' => $response[0], + 'channel' => $response[1], + 'payload' => $response[2], + ]; + + case self::PMESSAGE: + return (object) [ + 'kind' => $response[0], + 'pattern' => $response[1], + 'channel' => $response[2], + 'payload' => $response[3], + ]; + + case self::PONG: + return (object) [ + 'kind' => $response[0], + 'payload' => $response[1], + ]; + + default: + throw new ClientException( + "Unknown message type '{$response[0]}' received in the PUB/SUB context." + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/DispatcherLoop.php b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/DispatcherLoop.php new file mode 100644 index 000000000..c3ba306e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/DispatcherLoop.php @@ -0,0 +1,171 @@ +callbacks = []; + $this->pubsub = $pubsub; + } + + /** + * Checks if the passed argument is a valid callback. + * + * @param mixed $callable A callback. + * + * @throws InvalidArgumentException + */ + protected function assertCallback($callable) + { + if (!is_callable($callable)) { + throw new InvalidArgumentException('The given argument must be a callable object.'); + } + } + + /** + * Returns the underlying PUB / SUB context. + * + * @return Consumer + */ + public function getPubSubConsumer() + { + return $this->pubsub; + } + + /** + * Sets a callback that gets invoked upon new subscriptions. + * + * @param mixed $callable A callback. + */ + public function subscriptionCallback($callable = null) + { + if (isset($callable)) { + $this->assertCallback($callable); + } + + $this->subscriptionCallback = $callable; + } + + /** + * Sets a callback that gets invoked when a message is received on a + * channel that does not have an associated callback. + * + * @param mixed $callable A callback. + */ + public function defaultCallback($callable = null) + { + if (isset($callable)) { + $this->assertCallback($callable); + } + + $this->subscriptionCallback = $callable; + } + + /** + * Binds a callback to a channel. + * + * @param string $channel Channel name. + * @param callable $callback A callback. + */ + public function attachCallback($channel, $callback) + { + $callbackName = $this->getPrefixKeys() . $channel; + + $this->assertCallback($callback); + $this->callbacks[$callbackName] = $callback; + $this->pubsub->subscribe($channel); + } + + /** + * Stops listening to a channel and removes the associated callback. + * + * @param string $channel Redis channel. + */ + public function detachCallback($channel) + { + $callbackName = $this->getPrefixKeys() . $channel; + + if (isset($this->callbacks[$callbackName])) { + unset($this->callbacks[$callbackName]); + $this->pubsub->unsubscribe($channel); + } + } + + /** + * Starts the dispatcher loop. + */ + public function run() + { + foreach ($this->pubsub as $message) { + $kind = $message->kind; + + if ($kind !== Consumer::MESSAGE && $kind !== Consumer::PMESSAGE) { + if (isset($this->subscriptionCallback)) { + $callback = $this->subscriptionCallback; + call_user_func($callback, $message, $this); + } + + continue; + } + + if (isset($this->callbacks[$message->channel])) { + $callback = $this->callbacks[$message->channel]; + call_user_func($callback, $message->payload, $this); + } elseif (isset($this->defaultCallback)) { + $callback = $this->defaultCallback; + call_user_func($callback, $message, $this); + } + } + } + + /** + * Terminates the dispatcher loop. + */ + public function stop() + { + $this->pubsub->stop(); + } + + /** + * Return the prefix used for keys. + * + * @return string + */ + protected function getPrefixKeys() + { + $options = $this->pubsub->getClient()->getOptions(); + + if (isset($options->prefix)) { + return $options->prefix->getPrefix(); + } + + return ''; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/RelayConsumer.php b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/RelayConsumer.php new file mode 100644 index 000000000..5c15325df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/PubSub/RelayConsumer.php @@ -0,0 +1,114 @@ +statusFlags |= self::STATUS_SUBSCRIBED; + + $command = $this->client->createCommand('subscribe', [ + $channels, + function ($relay, $channel, $message) use ($callback) { + $callback((object) [ + 'kind' => is_null($message) ? self::SUBSCRIBE : self::MESSAGE, + 'channel' => $channel, + 'payload' => $message, + ], $relay); + }, + ]); + + $this->client->getConnection()->executeCommand($command); + + $this->invalidate(); + } + + /** + * Subscribes to the specified channels using a pattern. + * + * @param string ...$pattern One or more channel name patterns. + * @param callable $callback The message callback. + */ + public function psubscribe(...$pattern) // @phpstan-ignore-line + { + $patterns = func_get_args(); + $callback = array_pop($patterns); + + $this->statusFlags |= self::STATUS_PSUBSCRIBED; + + $command = $this->client->createCommand('psubscribe', [ + $patterns, + function ($relay, $pattern, $channel, $message) use ($callback) { + $callback((object) [ + 'kind' => is_null($message) ? self::PSUBSCRIBE : self::PMESSAGE, + 'pattern' => $pattern, + 'channel' => $channel, + 'payload' => $message, + ], $relay); + }, + ]); + + $this->client->getConnection()->executeCommand($command); + + $this->invalidate(); + } + + /** + * {@inheritDoc} + */ + protected function genericSubscribeInit($subscribeAction) + { + if (isset($this->options[$subscribeAction])) { + throw new NotSupportedException('Relay does not support Pub/Sub constructor options.'); + } + } + + /** + * {@inheritDoc} + */ + public function ping($payload = null) + { + throw new NotSupportedException('Relay does not support PING in Pub/Sub.'); + } + + /** + * {@inheritDoc} + */ + public function stop($drop = false) + { + return false; + } + + /** + * {@inheritDoc} + */ + public function __destruct() + { + // NOOP + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Replication/MissingMasterException.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Replication/MissingMasterException.php new file mode 100644 index 000000000..6550aeb54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Replication/MissingMasterException.php @@ -0,0 +1,22 @@ +disallowed = $this->getDisallowedOperations(); + $this->readonly = $this->getReadOnlyOperations(); + $this->readonlySHA1 = []; + } + + /** + * Returns if the specified command will perform a read-only operation + * on Redis or not. + * + * @param CommandInterface $command Command instance. + * + * @return bool + * @throws NotSupportedException + */ + public function isReadOperation(CommandInterface $command) + { + if (!$this->loadBalancing) { + return false; + } + + if (isset($this->disallowed[$id = $command->getId()])) { + throw new NotSupportedException( + "The command '$id' is not allowed in replication mode." + ); + } + + if (isset($this->readonly[$id])) { + if (true === $readonly = $this->readonly[$id]) { + return true; + } + + return call_user_func($readonly, $command); + } + + if (($eval = $id === 'EVAL') || $id === 'EVALSHA') { + $argument = $command->getArgument(0); + $sha1 = $eval ? sha1(strval($argument)) : $argument; + + if (isset($this->readonlySHA1[$sha1])) { + if (true === $readonly = $this->readonlySHA1[$sha1]) { + return true; + } + + return call_user_func($readonly, $command); + } + } + + return false; + } + + /** + * Returns if the specified command is not allowed for execution in a master + * / slave replication context. + * + * @param CommandInterface $command Command instance. + * + * @return bool + */ + public function isDisallowedOperation(CommandInterface $command) + { + return isset($this->disallowed[$command->getId()]); + } + + /** + * Checks if BITFIELD performs a read-only operation by looking for certain + * SET and INCRYBY modifiers in the arguments array of the command. + * + * @param CommandInterface $command Command instance. + * + * @return bool + */ + protected function isBitfieldReadOnly(CommandInterface $command) + { + $arguments = $command->getArguments(); + $argc = count($arguments); + + if ($argc >= 2) { + for ($i = 1; $i < $argc; ++$i) { + $argument = strtoupper($arguments[$i]); + if ($argument === 'SET' || $argument === 'INCRBY') { + return false; + } + } + } + + return true; + } + + /** + * Checks if a GEORADIUS command is a readable operation by parsing the + * arguments array of the specified command instance. + * + * @param CommandInterface $command Command instance. + * + * @return bool + */ + protected function isGeoradiusReadOnly(CommandInterface $command) + { + $arguments = $command->getArguments(); + $argc = count($arguments); + $startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4; + + if ($argc > $startIndex) { + for ($i = $startIndex; $i < $argc; ++$i) { + $argument = strtoupper($arguments[$i]); + if ($argument === 'STORE' || $argument === 'STOREDIST') { + return false; + } + } + } + + return true; + } + + /** + * Marks a command as a read-only operation. + * + * When the behavior of a command can be decided only at runtime depending + * on its arguments, a callable object can be provided to dynamically check + * if the specified command performs a read or a write operation. + * + * @param string $commandID Command ID. + * @param mixed $readonly A boolean value or a callable object. + */ + public function setCommandReadOnly($commandID, $readonly = true) + { + $commandID = strtoupper($commandID); + + if ($readonly) { + $this->readonly[$commandID] = $readonly; + } else { + unset($this->readonly[$commandID]); + } + } + + /** + * Marks a Lua script for EVAL and EVALSHA as a read-only operation. When + * the behaviour of a script can be decided only at runtime depending on + * its arguments, a callable object can be provided to dynamically check + * if the passed instance of EVAL or EVALSHA performs write operations or + * not. + * + * @param string $script Body of the Lua script. + * @param mixed $readonly A boolean value or a callable object. + */ + public function setScriptReadOnly($script, $readonly = true) + { + $sha1 = sha1($script); + + if ($readonly) { + $this->readonlySHA1[$sha1] = $readonly; + } else { + unset($this->readonlySHA1[$sha1]); + } + } + + /** + * Returns the default list of disallowed commands. + * + * @return array + */ + protected function getDisallowedOperations() + { + return [ + 'SHUTDOWN' => true, + 'INFO' => true, + 'DBSIZE' => true, + 'LASTSAVE' => true, + 'CONFIG' => true, + 'MONITOR' => true, + 'SLAVEOF' => true, + 'SAVE' => true, + 'BGSAVE' => true, + 'BGREWRITEAOF' => true, + 'SLOWLOG' => true, + ]; + } + + /** + * Returns the default list of commands performing read-only operations. + * + * @return array + */ + protected function getReadOnlyOperations() + { + return [ + 'EXISTS' => true, + 'TYPE' => true, + 'KEYS' => true, + 'SCAN' => true, + 'RANDOMKEY' => true, + 'TTL' => true, + 'GET' => true, + 'MGET' => true, + 'SUBSTR' => true, + 'STRLEN' => true, + 'GETRANGE' => true, + 'GETBIT' => true, + 'LLEN' => true, + 'LRANGE' => true, + 'LINDEX' => true, + 'SCARD' => true, + 'SISMEMBER' => true, + 'SINTER' => true, + 'SUNION' => true, + 'SDIFF' => true, + 'SMEMBERS' => true, + 'SSCAN' => true, + 'SRANDMEMBER' => true, + 'ZRANGE' => true, + 'ZREVRANGE' => true, + 'ZRANGEBYSCORE' => true, + 'ZREVRANGEBYSCORE' => true, + 'ZCARD' => true, + 'ZSCORE' => true, + 'ZCOUNT' => true, + 'ZRANK' => true, + 'ZREVRANK' => true, + 'ZSCAN' => true, + 'ZLEXCOUNT' => true, + 'ZRANGEBYLEX' => true, + 'ZREVRANGEBYLEX' => true, + 'HGET' => true, + 'HMGET' => true, + 'HEXISTS' => true, + 'HLEN' => true, + 'HKEYS' => true, + 'HVALS' => true, + 'HGETALL' => true, + 'HSCAN' => true, + 'HSTRLEN' => true, + 'PING' => true, + 'AUTH' => true, + 'SELECT' => true, + 'ECHO' => true, + 'QUIT' => true, + 'OBJECT' => true, + 'BITCOUNT' => true, + 'BITPOS' => true, + 'TIME' => true, + 'PFCOUNT' => true, + 'BITFIELD' => [$this, 'isBitfieldReadOnly'], + 'GEOHASH' => true, + 'GEOPOS' => true, + 'GEODIST' => true, + 'GEORADIUS' => [$this, 'isGeoradiusReadOnly'], + 'GEORADIUSBYMEMBER' => [$this, 'isGeoradiusReadOnly'], + ]; + } + + /** + * Disables reads to slaves when using + * a replication topology. + * + * @return self + */ + public function disableLoadBalancing(): self + { + $this->loadBalancing = false; + + return $this; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Replication/RoleException.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Replication/RoleException.php new file mode 100644 index 000000000..415432e2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Replication/RoleException.php @@ -0,0 +1,23 @@ +message = $message; + } + + /** + * {@inheritdoc} + */ + public function getMessage() + { + return $this->message; + } + + /** + * {@inheritdoc} + */ + public function getErrorType() + { + [$errorType] = explode(' ', $this->getMessage(), 2); + + return $errorType; + } + + /** + * Converts the object to its string representation. + * + * @return string + */ + public function __toString() + { + return $this->getMessage(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Response/ErrorInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/ErrorInterface.php new file mode 100644 index 000000000..a90420d74 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/ErrorInterface.php @@ -0,0 +1,34 @@ +connection = $connection; + $this->size = $size; + $this->position = 0; + $this->current = $size > 0 ? $this->getValue() : null; + } + + /** + * Handles the synchronization of the client with the Redis protocol when + * the garbage collector kicks in (e.g. when the iterator goes out of the + * scope of a foreach or it is unset). + */ + public function __destruct() + { + $this->drop(true); + } + + /** + * Drop queued elements that have not been read from the connection either + * by consuming the rest of the multibulk response or quickly by closing the + * underlying connection. + * + * @param bool $disconnect Consume the iterator or drop the connection. + */ + public function drop($disconnect = false) + { + if ($disconnect) { + if ($this->valid()) { + $this->position = $this->size; + $this->connection->disconnect(); + } + } else { + while ($this->valid()) { + $this->next(); + } + } + } + + /** + * Reads the next item of the multibulk response from the connection. + * + * @return mixed + */ + protected function getValue() + { + return $this->connection->read(); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkIterator.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkIterator.php new file mode 100644 index 000000000..0584a1ada --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkIterator.php @@ -0,0 +1,112 @@ +current; + } + + /** + * @return int|null + */ + #[ReturnTypeWillChange] + public function key() + { + return $this->position; + } + + /** + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + if (++$this->position < $this->size) { + $this->current = $this->getValue(); + } + } + + /** + * @return bool + */ + #[ReturnTypeWillChange] + public function valid() + { + return $this->position < $this->size; + } + + /** + * Returns the number of items comprising the whole multibulk response. + * + * This method should be used instead of iterator_count() to get the size of + * the current multibulk response since the former consumes the iteration to + * count the number of elements, but our iterators do not support rewinding. + * + * @return int + */ + #[ReturnTypeWillChange] + public function count() + { + return $this->size; + } + + /** + * Returns the current position of the iterator. + * + * @return int + */ + public function getPosition() + { + return $this->position; + } + + /** + * {@inheritdoc} + */ + abstract protected function getValue(); +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkTuple.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkTuple.php new file mode 100644 index 000000000..b8740300a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Iterator/MultiBulkTuple.php @@ -0,0 +1,95 @@ + $value pairs. + */ +class MultiBulkTuple extends MultiBulk implements OuterIterator +{ + private $iterator; + + /** + * @param MultiBulk $iterator Inner multibulk response iterator. + */ + public function __construct(MultiBulk $iterator) + { + $this->checkPreconditions($iterator); + + $this->size = count($iterator) / 2; + $this->iterator = $iterator; + $this->position = $iterator->getPosition(); + $this->current = $this->size > 0 ? $this->getValue() : null; + } + + /** + * Checks for valid preconditions. + * + * @param MultiBulk $iterator Inner multibulk response iterator. + * + * @throws InvalidArgumentException + * @throws UnexpectedValueException + */ + protected function checkPreconditions(MultiBulk $iterator) + { + if ($iterator->getPosition() !== 0) { + throw new InvalidArgumentException( + 'Cannot initialize a tuple iterator using an already initiated iterator.' + ); + } + + if (($size = count($iterator)) % 2 !== 0) { + throw new UnexpectedValueException('Invalid response size for a tuple iterator.'); + } + } + + /** + * @return MultiBulk + */ + #[ReturnTypeWillChange] + public function getInnerIterator() + { + return $this->iterator; + } + + /** + * {@inheritdoc} + */ + public function __destruct() + { + $this->iterator->drop(true); + } + + /** + * {@inheritdoc} + */ + protected function getValue() + { + $k = $this->iterator->current(); + $this->iterator->next(); + + $v = $this->iterator->current(); + $this->iterator->next(); + + return [$k, $v]; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Response/ResponseInterface.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/ResponseInterface.php new file mode 100644 index 000000000..bd7671b47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/ResponseInterface.php @@ -0,0 +1,20 @@ +getMessage(), 2); + + return $errorType; + } + + /** + * Converts the exception to an instance of Predis\Response\Error. + * + * @return Error + */ + public function toErrorResponse() + { + return new Error($this->getMessage()); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Status.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Status.php new file mode 100644 index 000000000..9b5ea1f11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Response/Status.php @@ -0,0 +1,78 @@ +payload = $payload; + } + + /** + * Converts the response object to its string representation. + * + * @return string + */ + public function __toString() + { + return $this->payload; + } + + /** + * Returns the payload of status response. + * + * @return string + */ + public function getPayload() + { + return $this->payload; + } + + /** + * Returns an instance of a status response object. + * + * Common status responses such as OK or QUEUED are cached in order to lower + * the global memory usage especially when using pipelines. + * + * @param string $payload Status response payload. + * + * @return self + */ + public static function get($payload) + { + switch ($payload) { + case 'OK': + case 'QUEUED': + if (isset(self::$$payload)) { + return self::$$payload; + } + + return self::$$payload = new self($payload); + + default: + return new self($payload); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Session/Handler.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Session/Handler.php new file mode 100644 index 000000000..2da5bfce7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Session/Handler.php @@ -0,0 +1,146 @@ +client = $client; + + if (isset($options['gc_maxlifetime'])) { + $this->ttl = (int) $options['gc_maxlifetime']; + } else { + $this->ttl = ini_get('session.gc_maxlifetime'); + } + } + + /** + * Registers this instance as the current session handler. + */ + public function register() + { + session_set_save_handler($this, true); + } + + /** + * @param string $save_path + * @param string $session_id + * @return bool + */ + #[ReturnTypeWillChange] + public function open($save_path, $session_id) + { + // NOOP + return true; + } + + /** + * @return bool + */ + #[ReturnTypeWillChange] + public function close() + { + // NOOP + return true; + } + + /** + * @param int $maxlifetime + * @return bool + */ + #[ReturnTypeWillChange] + public function gc($maxlifetime) + { + // NOOP + return true; + } + + /** + * @param string $session_id + * @return string + */ + #[ReturnTypeWillChange] + public function read($session_id) + { + if ($data = $this->client->get($session_id)) { + return $data; + } + + return ''; + } + + /** + * @param string $session_id + * @param string $session_data + * @return bool + */ + #[ReturnTypeWillChange] + public function write($session_id, $session_data) + { + $this->client->setex($session_id, $this->ttl, $session_data); + + return true; + } + + /** + * @param string $session_id + * @return bool + */ + #[ReturnTypeWillChange] + public function destroy($session_id) + { + $this->client->del($session_id); + + return true; + } + + /** + * Returns the underlying client instance. + * + * @return ClientInterface + */ + public function getClient() + { + return $this->client; + } + + /** + * Returns the session max lifetime value. + * + * @return int + */ + public function getMaxLifeTime() + { + return $this->ttl; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/AbortedMultiExecException.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/AbortedMultiExecException.php new file mode 100644 index 000000000..06329c967 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/AbortedMultiExecException.php @@ -0,0 +1,45 @@ +transaction = $transaction; + } + + /** + * Returns the transaction that generated the exception. + * + * @return MultiExec + */ + public function getTransaction() + { + return $this->transaction; + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExec.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExec.php new file mode 100644 index 000000000..7ef7f6dd0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExec.php @@ -0,0 +1,492 @@ +assertClient($client); + + $this->client = $client; + $this->state = new MultiExecState(); + + $this->configure($client, $options ?: []); + $this->reset(); + } + + /** + * Checks if the passed client instance satisfies the required conditions + * needed to initialize the transaction object. + * + * @param ClientInterface $client Client instance used by the transaction object. + * + * @throws NotSupportedException + */ + private function assertClient(ClientInterface $client) + { + if ($client->getConnection() instanceof ClusterInterface) { + throw new NotSupportedException( + 'Cannot initialize a MULTI/EXEC transaction over cluster connections.' + ); + } + + if (!$client->getCommandFactory()->supports('MULTI', 'EXEC', 'DISCARD')) { + throw new NotSupportedException( + 'MULTI, EXEC and DISCARD are not supported by the current command factory.' + ); + } + } + + /** + * Configures the transaction using the provided options. + * + * @param ClientInterface $client Underlying client instance. + * @param array $options Array of options for the transaction. + **/ + protected function configure(ClientInterface $client, array $options) + { + if (isset($options['exceptions'])) { + $this->exceptions = (bool) $options['exceptions']; + } else { + $this->exceptions = $client->getOptions()->exceptions; + } + + if (isset($options['cas'])) { + $this->modeCAS = (bool) $options['cas']; + } + + if (isset($options['watch']) && $keys = $options['watch']) { + $this->watchKeys = $keys; + } + + if (isset($options['retry'])) { + $this->attempts = (int) $options['retry']; + } + } + + /** + * Resets the state of the transaction. + */ + protected function reset() + { + $this->state->reset(); + $this->commands = new SplQueue(); + } + + /** + * Initializes the transaction context. + */ + protected function initialize() + { + if ($this->state->isInitialized()) { + return; + } + + if ($this->modeCAS) { + $this->state->flag(MultiExecState::CAS); + } + + if ($this->watchKeys) { + $this->watch($this->watchKeys); + } + + $cas = $this->state->isCAS(); + $discarded = $this->state->isDiscarded(); + + if (!$cas || ($cas && $discarded)) { + $this->call('MULTI'); + + if ($discarded) { + $this->state->unflag(MultiExecState::CAS); + } + } + + $this->state->unflag(MultiExecState::DISCARDED); + $this->state->flag(MultiExecState::INITIALIZED); + } + + /** + * Dynamically invokes a Redis command with the specified arguments. + * + * @param string $method Command ID. + * @param array $arguments Arguments for the command. + * + * @return mixed + */ + public function __call($method, $arguments) + { + return $this->executeCommand( + $this->client->createCommand($method, $arguments) + ); + } + + /** + * Executes a Redis command bypassing the transaction logic. + * + * @param string $commandID Command ID. + * @param array $arguments Arguments for the command. + * + * @return mixed + * @throws ServerException + */ + protected function call($commandID, array $arguments = []) + { + try { + $response = $this->client->executeCommand( + $this->client->createCommand($commandID, $arguments) + ); + } catch (ServerException $exception) { + if (!$this->client->getConnection() instanceof RelayConnection) { + throw $exception; + } + + if (strcasecmp($commandID, 'EXEC') != 0) { + throw $exception; + } + + if (!strpos($exception->getMessage(), 'RELAY_ERR_REDIS')) { + throw $exception; + } + + return null; + } + + if ($response instanceof ErrorResponseInterface) { + throw new ServerException($response->getMessage()); + } + + return $response; + } + + /** + * Executes the specified Redis command. + * + * @param CommandInterface $command Command instance. + * + * @return $this|mixed + * @throws AbortedMultiExecException + * @throws CommunicationException + */ + public function executeCommand(CommandInterface $command) + { + $this->initialize(); + + if ($this->state->isCAS()) { + return $this->client->executeCommand($command); + } + + $response = $this->client->getConnection()->executeCommand($command); + + if ($response instanceof StatusResponse && $response == 'QUEUED') { + $this->commands->enqueue($command); + } elseif ($response instanceof Relay) { + $this->commands->enqueue($command); + } elseif ($response instanceof ErrorResponseInterface) { + throw new AbortedMultiExecException($this, $response->getMessage()); + } else { + $this->onProtocolError('The server did not return a +QUEUED status response.'); + } + + return $this; + } + + /** + * Executes WATCH against one or more keys. + * + * @param string|array $keys One or more keys. + * + * @return mixed + * @throws NotSupportedException + * @throws ClientException + */ + public function watch($keys) + { + if (!$this->client->getCommandFactory()->supports('WATCH')) { + throw new NotSupportedException('WATCH is not supported by the current command factory.'); + } + + if ($this->state->isWatchAllowed()) { + throw new ClientException('Sending WATCH after MULTI is not allowed.'); + } + + $response = $this->call('WATCH', is_array($keys) ? $keys : [$keys]); + $this->state->flag(MultiExecState::WATCH); + + return $response; + } + + /** + * Finalizes the transaction by executing MULTI on the server. + * + * @return MultiExec + */ + public function multi() + { + if ($this->state->check(MultiExecState::INITIALIZED | MultiExecState::CAS)) { + $this->state->unflag(MultiExecState::CAS); + $this->call('MULTI'); + } else { + $this->initialize(); + } + + return $this; + } + + /** + * Executes UNWATCH. + * + * @return MultiExec + * @throws NotSupportedException + */ + public function unwatch() + { + if (!$this->client->getCommandFactory()->supports('UNWATCH')) { + throw new NotSupportedException( + 'UNWATCH is not supported by the current command factory.' + ); + } + + $this->state->unflag(MultiExecState::WATCH); + $this->__call('UNWATCH', []); + + return $this; + } + + /** + * Resets the transaction by UNWATCH-ing the keys that are being WATCHed and + * DISCARD-ing pending commands that have been already sent to the server. + * + * @return MultiExec + */ + public function discard() + { + if ($this->state->isInitialized()) { + $this->call($this->state->isCAS() ? 'UNWATCH' : 'DISCARD'); + + $this->reset(); + $this->state->flag(MultiExecState::DISCARDED); + } + + return $this; + } + + /** + * Executes the whole transaction. + * + * @return mixed + */ + public function exec() + { + return $this->execute(); + } + + /** + * Checks the state of the transaction before execution. + * + * @param mixed $callable Callback for execution. + * + * @throws InvalidArgumentException + * @throws ClientException + */ + private function checkBeforeExecution($callable) + { + if ($this->state->isExecuting()) { + throw new ClientException( + 'Cannot invoke "execute" or "exec" inside an active transaction context.' + ); + } + + if ($callable) { + if (!is_callable($callable)) { + throw new InvalidArgumentException('The argument must be a callable object.'); + } + + if (!$this->commands->isEmpty()) { + $this->discard(); + + throw new ClientException( + 'Cannot execute a transaction block after using fluent interface.' + ); + } + } elseif ($this->attempts) { + $this->discard(); + + throw new ClientException( + 'Automatic retries are supported only when a callable block is provided.' + ); + } + } + + /** + * Handles the actual execution of the whole transaction. + * + * @param mixed $callable Optional callback for execution. + * + * @return array + * @throws CommunicationException + * @throws AbortedMultiExecException + * @throws ServerException + */ + public function execute($callable = null) + { + $this->checkBeforeExecution($callable); + + $execResponse = null; + $attempts = $this->attempts; + + do { + if ($callable) { + $this->executeTransactionBlock($callable); + } + + if ($this->commands->isEmpty()) { + if ($this->state->isWatching()) { + $this->discard(); + } + + return; + } + + $execResponse = $this->call('EXEC'); + + // The additional `false` check is needed for Relay, + // let's hope it won't break anything + if ($execResponse === null || $execResponse === false) { + if ($attempts === 0) { + throw new AbortedMultiExecException( + $this, 'The current transaction has been aborted by the server.' + ); + } + + $this->reset(); + + continue; + } + + break; + } while ($attempts-- > 0); + + $response = []; + $commands = $this->commands; + $size = count($execResponse); + + if ($size !== count($commands)) { + $this->onProtocolError('EXEC returned an unexpected number of response items.'); + } + + for ($i = 0; $i < $size; ++$i) { + $cmdResponse = $execResponse[$i]; + + if ($this->exceptions && $cmdResponse instanceof ErrorResponseInterface) { + throw new ServerException($cmdResponse->getMessage()); + } + + if ($cmdResponse instanceof RelayException) { + if ($this->exceptions) { + throw new ServerException($cmdResponse->getMessage(), $cmdResponse->getCode(), $cmdResponse); + } + + $commands->dequeue(); + $response[$i] = new Error($cmdResponse->getMessage()); + continue; + } + + $response[$i] = $commands->dequeue()->parseResponse($cmdResponse); + } + + return $response; + } + + /** + * Passes the current transaction object to a callable block for execution. + * + * @param mixed $callable Callback. + * + * @throws CommunicationException + * @throws ServerException + */ + protected function executeTransactionBlock($callable) + { + $exception = null; + $this->state->flag(MultiExecState::INSIDEBLOCK); + + try { + call_user_func($callable, $this); + } catch (CommunicationException $exception) { + // NOOP + } catch (ServerException $exception) { + // NOOP + } catch (Exception $exception) { + $this->discard(); + } + + $this->state->unflag(MultiExecState::INSIDEBLOCK); + + if ($exception) { + throw $exception; + } + } + + /** + * Helper method for protocol errors encountered inside the transaction. + * + * @param string $message Error message. + */ + private function onProtocolError($message) + { + // Since a MULTI/EXEC block cannot be initialized when using aggregate + // connections we can safely assume that Predis\Client::getConnection() + // will return a Predis\Connection\NodeConnectionInterface instance. + CommunicationException::handle(new ProtocolException( + $this->client->getConnection(), $message + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExecState.php b/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExecState.php new file mode 100644 index 000000000..97598bf8f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/predis/predis/src/Transaction/MultiExecState.php @@ -0,0 +1,162 @@ +flags = 0; + } + + /** + * Sets the internal state flags. + * + * @param int $flags Set of flags + */ + public function set($flags) + { + $this->flags = $flags; + } + + /** + * Gets the internal state flags. + * + * @return int + */ + public function get() + { + return $this->flags; + } + + /** + * Sets one or more flags. + * + * @param int $flags Set of flags + */ + public function flag($flags) + { + $this->flags |= $flags; + } + + /** + * Resets one or more flags. + * + * @param int $flags Set of flags + */ + public function unflag($flags) + { + $this->flags &= ~$flags; + } + + /** + * Returns if the specified flag or set of flags is set. + * + * @param int $flags Flag + * + * @return bool + */ + public function check($flags) + { + return ($this->flags & $flags) === $flags; + } + + /** + * Resets the state of a transaction. + */ + public function reset() + { + $this->flags = 0; + } + + /** + * Returns the state of the RESET flag. + * + * @return bool + */ + public function isReset() + { + return $this->flags === 0; + } + + /** + * Returns the state of the INITIALIZED flag. + * + * @return bool + */ + public function isInitialized() + { + return $this->check(self::INITIALIZED); + } + + /** + * Returns the state of the INSIDEBLOCK flag. + * + * @return bool + */ + public function isExecuting() + { + return $this->check(self::INSIDEBLOCK); + } + + /** + * Returns the state of the CAS flag. + * + * @return bool + */ + public function isCAS() + { + return $this->check(self::CAS); + } + + /** + * Returns if WATCH is allowed in the current state. + * + * @return bool + */ + public function isWatchAllowed() + { + return $this->check(self::INITIALIZED) && !$this->check(self::CAS); + } + + /** + * Returns the state of the WATCH flag. + * + * @return bool + */ + public function isWatching() + { + return $this->check(self::WATCH); + } + + /** + * Returns the state of the DISCARDED flag. + * + * @return bool + */ + public function isDiscarded() + { + return $this->check(self::DISCARDED); + } +} diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/.github/workflows/ci.yml b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/.github/workflows/ci.yml new file mode 100644 index 000000000..d4d395acf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/.github/workflows/ci.yml @@ -0,0 +1,112 @@ +name: Tests + +on: [push, pull_request] + +jobs: + tests-legacy: + name: PHP ${{ matrix.php-versions }} Tests + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['5.4', '5.5', '5.6'] + + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: openssl + tools: phpunit:4.8 + + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run tests + run: phpunit --coverage-clover clover.xml tests + + - uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./clover.xml + + tests-older: + name: PHP ${{ matrix.php-versions }} Tests + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['7.0', '7.1'] + + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: openssl + tools: phpunit:6.5 + + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run tests + run: phpunit --coverage-clover clover.xml tests + + - uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./clover.xml + + tests-old: + name: PHP ${{ matrix.php-versions }} Tests + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['7.2', '7.3', '7.4'] + + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: openssl + tools: phpunit:8.5 + + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run tests + run: phpunit --coverage-clover clover.xml tests + + - uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./clover.xml + + tests: + name: PHP ${{ matrix.php-versions }} Tests + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: ['ubuntu-latest'] + php-versions: ['8.0', '8.1'] + + steps: + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + extensions: openssl + tools: phpunit/phpunit:9.5 + + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Run tests + run: phpunit --coverage-clover clover.xml tests + + - uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./clover.xml diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/CHANGELOG.txt b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/CHANGELOG.txt index 351b10421..51654e838 100644 --- a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/CHANGELOG.txt +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/CHANGELOG.txt @@ -1,5 +1,15 @@ xmlseclibs.php ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +20, Nov 2024, 3.1.3 +Bug Fixes: +- remove loadKey check due to BC issues + +20, Nov 2024, 3.1.2 +Improvements: +- Add tab to list of whitespace values to remove from cert. refs #252 +- loadKey should check return value for openssl_get_privatekey (sammarshallou) +- Switch to GitHub actions (SharkMachine) + 05, Sep 2020, 3.1.1 Features: - Support OAEP (iggyvolz) diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/LICENSE b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/LICENSE index 4fe5e5ffb..b516c0093 100644 --- a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/LICENSE +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2019, Robert Richards . +Copyright (c) 2007-2024, Robert Richards . All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/phpunit.xml b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/phpunit.xml new file mode 100644 index 000000000..4f326275f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/phpunit.xml @@ -0,0 +1,7 @@ + + + + src + + + diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php index b9df7611f..807f279dc 100644 --- a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecEnc.php @@ -11,7 +11,7 @@ /** * xmlseclibs.php * - * Copyright (c) 2007-2020, Robert Richards . + * Copyright (c) 2007-2024, Robert Richards . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @author Robert Richards - * @copyright 2007-2020 Robert Richards + * @copyright 2007-2024 Robert Richards * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ @@ -485,7 +485,7 @@ public static function staticLocateKeyInfo($objBaseKey=null, $node=null) if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) { if ($x509certNodes->length > 0) { $x509cert = $x509certNodes->item(0)->textContent; - $x509cert = str_replace(array("\r", "\n", " "), "", $x509cert); + $x509cert = str_replace(array("\r", "\n", " ", "\t"), "", $x509cert); $x509cert = "-----BEGIN CERTIFICATE-----\n".chunk_split($x509cert, 64, "\n")."-----END CERTIFICATE-----\n"; $objBaseKey->loadKey($x509cert, false, true); } diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php index 9986123e3..507edad9e 100644 --- a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityDSig.php @@ -11,7 +11,7 @@ /** * xmlseclibs.php * - * Copyright (c) 2007-2020, Robert Richards . + * Copyright (c) 2007-2024, Robert Richards . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @author Robert Richards - * @copyright 2007-2020 Robert Richards + * @copyright 2007-2024 Robert Richards * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ @@ -1050,7 +1050,7 @@ public static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=true, $i } $subjectNameValue = implode(',', $parts); } else { - $subjectNameValue = $certData['issuer']; + $subjectNameValue = $certData['subject']; } $x509SubjectNode = $baseDoc->createElementNS(self::XMLDSIGNS, $dsig_pfx.'X509SubjectName', $subjectNameValue); $x509DataNode->appendChild($x509SubjectNode); diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php index 7eed04d22..2fd2a3862 100644 --- a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/src/XMLSecurityKey.php @@ -7,7 +7,7 @@ /** * xmlseclibs.php * - * Copyright (c) 2007-2020, Robert Richards . + * Copyright (c) 2007-2024, Robert Richards . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,7 +40,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * @author Robert Richards - * @copyright 2007-2020 Robert Richards + * @copyright 2007-2024 Robert Richards * @license http://www.opensource.org/licenses/bsd-license.php BSD License */ diff --git a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/xmlseclibs.php b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/xmlseclibs.php index 1c10acc73..05b7a1fe5 100644 --- a/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/xmlseclibs.php +++ b/.extlib/simplesamlphp/vendor/robrichards/xmlseclibs/xmlseclibs.php @@ -2,7 +2,7 @@ /** * xmlseclibs.php * - * Copyright (c) 2007-2020, Robert Richards . + * Copyright (c) 2007-2024, Robert Richards . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,9 +35,9 @@ * POSSIBILITY OF SUCH DAMAGE. * * @author Robert Richards - * @copyright 2007-2020 Robert Richards + * @copyright 2007-2024 Robert Richards * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version 3.1.1 + * @version 3.1.3 */ $xmlseclibs_srcdir = dirname(__FILE__) . '/src/'; diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/ChangeLog.md new file mode 100644 index 000000000..0cc528ea3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/ChangeLog.md @@ -0,0 +1,30 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [2.0.1] - 2024-03-02 + +### Changed + +* Do not use implicitly nullable parameters + +## [2.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4, and PHP 8.0 + +## [1.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [1.0.0] - 2020-08-12 + +* Initial release + +[2.0.1]: https://github.com/sebastianbergmann/cli-parser/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/cli-parser/compare/1.0.1...2.0.0 +[1.0.1]: https://github.com/sebastianbergmann/cli-parser/compare/1.0.0...1.0.1 +[1.0.0]: https://github.com/sebastianbergmann/cli-parser/compare/bb7bb3297957927962b0a3335befe7b66f7462e9...1.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/LICENSE new file mode 100644 index 000000000..edaedf619 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/cli-parser/README.md b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/README.md new file mode 100644 index 000000000..4db2c0423 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/cli-parser/v/stable.png)](https://packagist.org/packages/sebastian/cli-parser) +[![CI Status](https://github.com/sebastianbergmann/cli-parser/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/cli-parser/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/cli-parser/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/cli-parser) +[![codecov](https://codecov.io/gh/sebastianbergmann/cli-parser/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/cli-parser) + +# sebastian/cli-parser + +Library for parsing `$_SERVER['argv']`, extracted from `phpunit/phpunit`. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/cli-parser +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/cli-parser +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/composer.json b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/composer.json new file mode 100644 index 000000000..51b744726 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/composer.json @@ -0,0 +1,42 @@ +{ + "name": "sebastian/cli-parser", + "description": "Library for parsing CLI options", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/Parser.php b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/Parser.php new file mode 100644 index 000000000..ab2d975c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/Parser.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function array_map; +use function array_merge; +use function array_shift; +use function array_slice; +use function assert; +use function count; +use function current; +use function explode; +use function is_array; +use function is_int; +use function is_string; +use function key; +use function next; +use function preg_replace; +use function reset; +use function sort; +use function str_ends_with; +use function str_starts_with; +use function strlen; +use function strstr; +use function substr; + +final class Parser +{ + /** + * @psalm-param list $argv + * @psalm-param list $longOptions + * + * @psalm-return array{0: array, 1: array} + * + * @throws AmbiguousOptionException + * @throws OptionDoesNotAllowArgumentException + * @throws RequiredOptionArgumentMissingException + * @throws UnknownOptionException + */ + public function parse(array $argv, string $shortOptions, ?array $longOptions = null): array + { + if (empty($argv)) { + return [[], []]; + } + + $options = []; + $nonOptions = []; + + if ($longOptions) { + sort($longOptions); + } + + if (isset($argv[0][0]) && $argv[0][0] !== '-') { + array_shift($argv); + } + + reset($argv); + + $argv = array_map('trim', $argv); + + while (false !== $arg = current($argv)) { + $i = key($argv); + + assert(is_int($i)); + + next($argv); + + if ($arg === '') { + continue; + } + + if ($arg === '--') { + $nonOptions = array_merge($nonOptions, array_slice($argv, $i + 1)); + + break; + } + + if ($arg[0] !== '-' || (strlen($arg) > 1 && $arg[1] === '-' && !$longOptions)) { + $nonOptions[] = $arg; + + continue; + } + + if (strlen($arg) > 1 && $arg[1] === '-' && is_array($longOptions)) { + $this->parseLongOption( + substr($arg, 2), + $longOptions, + $options, + $argv, + ); + + continue; + } + + $this->parseShortOption( + substr($arg, 1), + $shortOptions, + $options, + $argv, + ); + } + + return [$options, $nonOptions]; + } + + /** + * @throws RequiredOptionArgumentMissingException + */ + private function parseShortOption(string $argument, string $shortOptions, array &$options, array &$argv): void + { + $argumentLength = strlen($argument); + + for ($i = 0; $i < $argumentLength; $i++) { + $option = $argument[$i]; + $optionArgument = null; + + if ($argument[$i] === ':' || ($spec = strstr($shortOptions, $option)) === false) { + throw new UnknownOptionException('-' . $option); + } + + if (strlen($spec) > 1 && $spec[1] === ':') { + if ($i + 1 < $argumentLength) { + $options[] = [$option, substr($argument, $i + 1)]; + + break; + } + + if (!(strlen($spec) > 2 && $spec[2] === ':')) { + $optionArgument = current($argv); + + if (!$optionArgument) { + throw new RequiredOptionArgumentMissingException('-' . $option); + } + + assert(is_string($optionArgument)); + + next($argv); + } + } + + $options[] = [$option, $optionArgument]; + } + } + + /** + * @psalm-param list $longOptions + * + * @throws AmbiguousOptionException + * @throws OptionDoesNotAllowArgumentException + * @throws RequiredOptionArgumentMissingException + * @throws UnknownOptionException + */ + private function parseLongOption(string $argument, array $longOptions, array &$options, array &$argv): void + { + $count = count($longOptions); + $list = explode('=', $argument); + $option = $list[0]; + $optionArgument = null; + + if (count($list) > 1) { + $optionArgument = $list[1]; + } + + $optionLength = strlen($option); + + foreach ($longOptions as $i => $longOption) { + $opt_start = substr($longOption, 0, $optionLength); + + if ($opt_start !== $option) { + continue; + } + + $opt_rest = substr($longOption, $optionLength); + + if ($opt_rest !== '' && $i + 1 < $count && $option[0] !== '=' && str_starts_with($longOptions[$i + 1], $option)) { + throw new AmbiguousOptionException('--' . $option); + } + + if (str_ends_with($longOption, '=')) { + if (!str_ends_with($longOption, '==') && !strlen((string) $optionArgument)) { + if (false === $optionArgument = current($argv)) { + throw new RequiredOptionArgumentMissingException('--' . $option); + } + + next($argv); + } + } elseif ($optionArgument) { + throw new OptionDoesNotAllowArgumentException('--' . $option); + } + + $fullOption = '--' . preg_replace('/={1,2}$/', '', $longOption); + $options[] = [$fullOption, $optionArgument]; + + return; + } + + throw new UnknownOptionException('--' . $option); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php new file mode 100644 index 000000000..99eb625a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/AmbiguousOptionException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class AmbiguousOptionException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Option "%s" is ambiguous', + $option, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/Exception.php new file mode 100644 index 000000000..f35ad2457 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php new file mode 100644 index 000000000..7fea616be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/OptionDoesNotAllowArgumentException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class OptionDoesNotAllowArgumentException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Option "%s" does not allow an argument', + $option, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php new file mode 100644 index 000000000..9add49a96 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/RequiredOptionArgumentMissingException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class RequiredOptionArgumentMissingException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Required argument for option "%s" is missing', + $option, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php new file mode 100644 index 000000000..560c7ad22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/cli-parser/src/exceptions/UnknownOptionException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CliParser; + +use function sprintf; +use RuntimeException; + +final class UnknownOptionException extends RuntimeException implements Exception +{ + public function __construct(string $option) + { + parent::__construct( + sprintf( + 'Unknown option "%s"', + $option, + ), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/baseline.xml b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/baseline.xml new file mode 100644 index 000000000..0ba3bcc4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/baseline.xml @@ -0,0 +1,9 @@ + + + + + assert(is_array($traits)) + is_array($traits) + + + diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/config.xml b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/config.xml new file mode 100644 index 000000000..a23123689 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/.psalm/config.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md new file mode 100644 index 000000000..4ff97182d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/ChangeLog.md @@ -0,0 +1,45 @@ +# Change Log + +All notable changes to `sebastianbergmann/code-unit-reverse-lookup` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4, and PHP 8.0 + +## [2.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## 2.0.0 - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2 + +## 1.0.0 - 2016-02-13 + +### Added + +* Initial release + +[3.0.0]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.3...3.0.0 +[2.0.3]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/code-unit-reverse-lookup/compare/1.0.0...2.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/LICENSE new file mode 100644 index 000000000..16e1ba9a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2016-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/README.md b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/README.md new file mode 100644 index 000000000..fb2c0dfec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/code-unit-reverse-lookup/v/stable.png)](https://packagist.org/packages/sebastian/code-unit-reverse-lookup) +[![CI Status](https://github.com/sebastianbergmann/code-unit-reverse-lookup/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/code-unit-reverse-lookup/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/code-unit-reverse-lookup/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/code-unit-reverse-lookup) +[![codecov](https://codecov.io/gh/sebastianbergmann/code-unit-reverse-lookup/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/code-unit-reverse-lookup) + +# sebastian/code-unit-reverse-lookup + +Looks up which function or method a line of code belongs to. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/code-unit-reverse-lookup +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/code-unit-reverse-lookup +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/composer.json b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/composer.json new file mode 100644 index 000000000..37cc1ccf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/composer.json @@ -0,0 +1,36 @@ +{ + "name": "sebastian/code-unit-reverse-lookup", + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php new file mode 100644 index 000000000..355405edb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit-reverse-lookup/src/Wizard.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnitReverseLookup; + +use function array_merge; +use function assert; +use function get_declared_classes; +use function get_declared_traits; +use function get_defined_functions; +use function is_array; +use function range; +use ReflectionClass; +use ReflectionFunction; +use ReflectionFunctionAbstract; +use ReflectionMethod; + +class Wizard +{ + /** + * @psalm-var array> + */ + private array $lookupTable = []; + + /** + * @psalm-var array + */ + private array $processedClasses = []; + + /** + * @psalm-var array + */ + private array $processedFunctions = []; + + public function lookup(string $filename, int $lineNumber): string + { + if (!isset($this->lookupTable[$filename][$lineNumber])) { + $this->updateLookupTable(); + } + + if (isset($this->lookupTable[$filename][$lineNumber])) { + return $this->lookupTable[$filename][$lineNumber]; + } + + return $filename . ':' . $lineNumber; + } + + private function updateLookupTable(): void + { + $this->processClassesAndTraits(); + $this->processFunctions(); + } + + private function processClassesAndTraits(): void + { + $classes = get_declared_classes(); + $traits = get_declared_traits(); + + /* @noinspection PhpConditionAlreadyCheckedInspection */ + assert(is_array($traits)); + + foreach (array_merge($classes, $traits) as $classOrTrait) { + if (isset($this->processedClasses[$classOrTrait])) { + continue; + } + + foreach ((new ReflectionClass($classOrTrait))->getMethods() as $method) { + $this->processFunctionOrMethod($method); + } + + $this->processedClasses[$classOrTrait] = true; + } + } + + private function processFunctions(): void + { + foreach (get_defined_functions()['user'] as $function) { + if (isset($this->processedFunctions[$function])) { + continue; + } + + $this->processFunctionOrMethod(new ReflectionFunction($function)); + + $this->processedFunctions[$function] = true; + } + } + + private function processFunctionOrMethod(ReflectionFunctionAbstract $functionOrMethod): void + { + if ($functionOrMethod->isInternal()) { + return; + } + + $name = $functionOrMethod->getName(); + + if ($functionOrMethod instanceof ReflectionMethod) { + $name = $functionOrMethod->getDeclaringClass()->getName() . '::' . $name; + } + + if (!isset($this->lookupTable[$functionOrMethod->getFileName()])) { + $this->lookupTable[$functionOrMethod->getFileName()] = []; + } + + foreach (range($functionOrMethod->getStartLine(), $functionOrMethod->getEndLine()) as $line) { + $this->lookupTable[$functionOrMethod->getFileName()][$line] = $name; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/code-unit/ChangeLog.md new file mode 100644 index 000000000..8b9c88bc2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/ChangeLog.md @@ -0,0 +1,78 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.0.0] - 2023-02-03 + +### Added + +* Added `SebastianBergmann\CodeUnit\FileUnit` value object that represents a sourcecode file + +### Removed + +* `SebastianBergmann\CodeUnit\CodeUnitCollection::fromArray()` has been removed +* `SebastianBergmann\CodeUnit\Mapper::stringToCodeUnits()` no longer supports `ClassName<*>` +* This component is no longer supported on PHP 7.3, PHP 7.4, and PHP 8.0 + +## [1.0.8] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\CodeUnit\Exception` now correctly extends `\Throwable` + +## [1.0.7] - 2020-10-02 + +### Fixed + +* `SebastianBergmann\CodeUnit\Mapper::stringToCodeUnits()` no longer attempts to create `CodeUnit` objects for code units that are not declared in userland + +## [1.0.6] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [1.0.5] - 2020-06-26 + +### Fixed + +* [#3](https://github.com/sebastianbergmann/code-unit/issues/3): Regression in 1.0.4 + +## [1.0.4] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [1.0.3] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [1.0.2] - 2020-04-30 + +### Fixed + +* `Mapper::stringToCodeUnits()` raised the wrong exception for `Class::method` when a class named `Class` exists but does not have a method named `method` + +## [1.0.1] - 2020-04-27 + +### Fixed + +* [#2](https://github.com/sebastianbergmann/code-unit/issues/2): `Mapper::stringToCodeUnits()` breaks when `ClassName` is used for class that extends built-in class + +## [1.0.0] - 2020-03-30 + +* Initial release + +[2.0.0]: https://github.com/sebastianbergmann/code-unit/compare/1.0.8...2.0.0 +[1.0.8]: https://github.com/sebastianbergmann/code-unit/compare/1.0.7...1.0.8 +[1.0.7]: https://github.com/sebastianbergmann/code-unit/compare/1.0.6...1.0.7 +[1.0.6]: https://github.com/sebastianbergmann/code-unit/compare/1.0.5...1.0.6 +[1.0.5]: https://github.com/sebastianbergmann/code-unit/compare/1.0.4...1.0.5 +[1.0.4]: https://github.com/sebastianbergmann/code-unit/compare/1.0.3...1.0.4 +[1.0.3]: https://github.com/sebastianbergmann/code-unit/compare/1.0.2...1.0.3 +[1.0.2]: https://github.com/sebastianbergmann/code-unit/compare/1.0.1...1.0.2 +[1.0.1]: https://github.com/sebastianbergmann/code-unit/compare/1.0.0...1.0.1 +[1.0.0]: https://github.com/sebastianbergmann/code-unit/compare/530c3900e5db9bcb8516da545bef0d62536cedaa...1.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/code-unit/LICENSE new file mode 100644 index 000000000..5716d9654 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/code-unit/README.md b/.extlib/simplesamlphp/vendor/sebastian/code-unit/README.md new file mode 100644 index 000000000..95839c486 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/code-unit/v/stable.png)](https://packagist.org/packages/sebastian/code-unit) +[![CI Status](https://github.com/sebastianbergmann/code-unit/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/code-unit/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/code-unit/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/code-unit) +[![codecov](https://codecov.io/gh/sebastianbergmann/code-unit/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/code-unit) + +# sebastian/code-unit + +Collection of value objects that represent the PHP code units. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/code-unit +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/code-unit +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/code-unit/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/composer.json b/.extlib/simplesamlphp/vendor/sebastian/code-unit/composer.json new file mode 100644 index 000000000..8cec5285e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/composer.json @@ -0,0 +1,50 @@ +{ + "name": "sebastian/code-unit", + "description": "Collection of value objects that represent the PHP code units", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ], + "files": [ + "tests/_fixture/file_with_multiple_code_units.php", + "tests/_fixture/function.php" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassMethodUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassMethodUnit.php new file mode 100644 index 000000000..f9ddac29e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassMethodUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class ClassMethodUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true ClassMethodUnit $this + */ + public function isClassMethod(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassUnit.php new file mode 100644 index 000000000..3ba0ee661 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/ClassUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class ClassUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true ClassUnit $this + */ + public function isClass(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnit.php new file mode 100644 index 000000000..ced52b43a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnit.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 SebastianBergmann\CodeUnit; + +use function count; +use function file; +use function file_exists; +use function is_readable; +use function range; +use function sprintf; +use ReflectionClass; +use ReflectionFunction; +use ReflectionMethod; + +/** + * @psalm-immutable + */ +abstract class CodeUnit +{ + private readonly string $name; + private readonly string $sourceFileName; + + /** + * @psalm-var list + */ + private readonly array $sourceLines; + + /** + * @psalm-param class-string $className + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forClass(string $className): ClassUnit + { + self::ensureUserDefinedClass($className); + + $reflector = self::reflectorForClass($className); + + return new ClassUnit( + $className, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forClassMethod(string $className, string $methodName): ClassMethodUnit + { + self::ensureUserDefinedClass($className); + + $reflector = self::reflectorForClassMethod($className, $methodName); + + return new ClassMethodUnit( + $className . '::' . $methodName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @throws InvalidCodeUnitException + */ + public static function forFileWithAbsolutePath(string $path): FileUnit + { + self::ensureFileExistsAndIsReadable($path); + + return new FileUnit( + $path, + $path, + range( + 1, + count(file($path)) + ) + ); + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forInterface(string $interfaceName): InterfaceUnit + { + self::ensureUserDefinedInterface($interfaceName); + + $reflector = self::reflectorForClass($interfaceName); + + return new InterfaceUnit( + $interfaceName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forInterfaceMethod(string $interfaceName, string $methodName): InterfaceMethodUnit + { + self::ensureUserDefinedInterface($interfaceName); + + $reflector = self::reflectorForClassMethod($interfaceName, $methodName); + + return new InterfaceMethodUnit( + $interfaceName . '::' . $methodName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $traitName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forTrait(string $traitName): TraitUnit + { + self::ensureUserDefinedTrait($traitName); + + $reflector = self::reflectorForClass($traitName); + + return new TraitUnit( + $traitName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param class-string $traitName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forTraitMethod(string $traitName, string $methodName): TraitMethodUnit + { + self::ensureUserDefinedTrait($traitName); + + $reflector = self::reflectorForClassMethod($traitName, $methodName); + + return new TraitMethodUnit( + $traitName . '::' . $methodName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param callable-string $functionName + * + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public static function forFunction(string $functionName): FunctionUnit + { + $reflector = self::reflectorForFunction($functionName); + + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined function', + $functionName + ) + ); + } + + return new FunctionUnit( + $functionName, + $reflector->getFileName(), + range( + $reflector->getStartLine(), + $reflector->getEndLine() + ) + ); + } + + /** + * @psalm-param list $sourceLines + */ + private function __construct(string $name, string $sourceFileName, array $sourceLines) + { + $this->name = $name; + $this->sourceFileName = $sourceFileName; + $this->sourceLines = $sourceLines; + } + + public function name(): string + { + return $this->name; + } + + public function sourceFileName(): string + { + return $this->sourceFileName; + } + + /** + * @psalm-return list + */ + public function sourceLines(): array + { + return $this->sourceLines; + } + + public function isClass(): bool + { + return false; + } + + public function isClassMethod(): bool + { + return false; + } + + public function isInterface(): bool + { + return false; + } + + public function isInterfaceMethod(): bool + { + return false; + } + + public function isTrait(): bool + { + return false; + } + + public function isTraitMethod(): bool + { + return false; + } + + public function isFunction(): bool + { + return false; + } + + public function isFile(): bool + { + return false; + } + + /** + * @throws InvalidCodeUnitException + */ + private static function ensureFileExistsAndIsReadable(string $path): void + { + if (!(file_exists($path) && is_readable($path))) { + throw new InvalidCodeUnitException( + sprintf( + 'File "%s" does not exist or is not readable', + $path + ) + ); + } + } + + /** + * @psalm-param class-string $className + * + * @throws InvalidCodeUnitException + */ + private static function ensureUserDefinedClass(string $className): void + { + try { + $reflector = new ReflectionClass($className); + + if ($reflector->isInterface()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is an interface and not a class', + $className + ) + ); + } + + if ($reflector->isTrait()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is a trait and not a class', + $className + ) + ); + } + + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined class', + $className + ) + ); + } + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $interfaceName + * + * @throws InvalidCodeUnitException + */ + private static function ensureUserDefinedInterface(string $interfaceName): void + { + try { + $reflector = new ReflectionClass($interfaceName); + + if (!$reflector->isInterface()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not an interface', + $interfaceName + ) + ); + } + + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined interface', + $interfaceName + ) + ); + } + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $traitName + * + * @throws InvalidCodeUnitException + */ + private static function ensureUserDefinedTrait(string $traitName): void + { + try { + $reflector = new ReflectionClass($traitName); + + if (!$reflector->isTrait()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a trait', + $traitName + ) + ); + } + + // @codeCoverageIgnoreStart + if (!$reflector->isUserDefined()) { + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a user-defined trait', + $traitName + ) + ); + } + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private static function reflectorForClass(string $className): ReflectionClass + { + try { + return new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private static function reflectorForClassMethod(string $className, string $methodName): ReflectionMethod + { + try { + return new ReflectionMethod($className, $methodName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param callable-string $functionName + * + * @throws ReflectionException + */ + private static function reflectorForFunction(string $functionName): ReflectionFunction + { + try { + return new ReflectionFunction($functionName); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollection.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollection.php new file mode 100644 index 000000000..a23a7c463 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollection.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use function array_merge; +use function count; +use Countable; +use IteratorAggregate; + +/** + * @template-implements IteratorAggregate + * + * @psalm-immutable + */ +final class CodeUnitCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $codeUnits; + + public static function fromList(CodeUnit ...$codeUnits): self + { + return new self($codeUnits); + } + + /** + * @psalm-param list $codeUnits + */ + private function __construct(array $codeUnits) + { + $this->codeUnits = $codeUnits; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->codeUnits; + } + + public function getIterator(): CodeUnitCollectionIterator + { + return new CodeUnitCollectionIterator($this); + } + + public function count(): int + { + return count($this->codeUnits); + } + + public function isEmpty(): bool + { + return empty($this->codeUnits); + } + + public function mergeWith(self $other): self + { + return new self( + array_merge( + $this->asArray(), + $other->asArray() + ) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php new file mode 100644 index 000000000..f04bd6550 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/CodeUnitCollectionIterator.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use Iterator; + +/** + * @template-implements Iterator + */ +final class CodeUnitCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private array $codeUnits; + private int $position = 0; + + public function __construct(CodeUnitCollection $collection) + { + $this->codeUnits = $collection->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return isset($this->codeUnits[$this->position]); + } + + public function key(): int + { + return $this->position; + } + + public function current(): CodeUnit + { + return $this->codeUnits[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/FileUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/FileUnit.php new file mode 100644 index 000000000..3bd9a36a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/FileUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class FileUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true FileUnit $this + */ + public function isFile(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/FunctionUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/FunctionUnit.php new file mode 100644 index 000000000..df76cf195 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/FunctionUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class FunctionUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true FunctionUnit $this + */ + public function isFunction(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php new file mode 100644 index 000000000..fcd44f41a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceMethodUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class InterfaceMethodUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true InterfaceMethod $this + */ + public function isInterfaceMethod(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceUnit.php new file mode 100644 index 000000000..5cf585bfd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/InterfaceUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class InterfaceUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true InterfaceUnit $this + */ + public function isInterface(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/Mapper.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/Mapper.php new file mode 100644 index 000000000..ad11259f7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/Mapper.php @@ -0,0 +1,259 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use function array_keys; +use function array_merge; +use function array_unique; +use function array_values; +use function class_exists; +use function explode; +use function function_exists; +use function interface_exists; +use function ksort; +use function method_exists; +use function sort; +use function sprintf; +use function str_contains; +use function trait_exists; +use ReflectionClass; +use ReflectionFunction; +use ReflectionMethod; + +final class Mapper +{ + /** + * @psalm-return array> + */ + public function codeUnitsToSourceLines(CodeUnitCollection $codeUnits): array + { + $result = []; + + foreach ($codeUnits as $codeUnit) { + $sourceFileName = $codeUnit->sourceFileName(); + + if (!isset($result[$sourceFileName])) { + $result[$sourceFileName] = []; + } + + $result[$sourceFileName] = array_merge($result[$sourceFileName], $codeUnit->sourceLines()); + } + + foreach (array_keys($result) as $sourceFileName) { + $result[$sourceFileName] = array_values(array_unique($result[$sourceFileName])); + + sort($result[$sourceFileName]); + } + + ksort($result); + + return $result; + } + + /** + * @throws InvalidCodeUnitException + * @throws ReflectionException + */ + public function stringToCodeUnits(string $unit): CodeUnitCollection + { + if (str_contains($unit, '::')) { + [$firstPart, $secondPart] = explode('::', $unit); + + if ($this->isUserDefinedFunction($secondPart)) { + return CodeUnitCollection::fromList(CodeUnit::forFunction($secondPart)); + } + + if ($this->isUserDefinedMethod($firstPart, $secondPart)) { + return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart)); + } + + if ($this->isUserDefinedInterface($firstPart)) { + return CodeUnitCollection::fromList(CodeUnit::forInterfaceMethod($firstPart, $secondPart)); + } + + if ($this->isUserDefinedTrait($firstPart)) { + return CodeUnitCollection::fromList(CodeUnit::forTraitMethod($firstPart, $secondPart)); + } + } else { + if ($this->isUserDefinedClass($unit)) { + $units = [CodeUnit::forClass($unit)]; + + foreach ($this->reflectorForClass($unit)->getTraits() as $trait) { + if (!$trait->isUserDefined()) { + // @codeCoverageIgnoreStart + continue; + // @codeCoverageIgnoreEnd + } + + $units[] = CodeUnit::forTrait($trait->getName()); + } + + return CodeUnitCollection::fromList(...$units); + } + + if ($this->isUserDefinedInterface($unit)) { + return CodeUnitCollection::fromList(CodeUnit::forInterface($unit)); + } + + if ($this->isUserDefinedTrait($unit)) { + return CodeUnitCollection::fromList(CodeUnit::forTrait($unit)); + } + + if ($this->isUserDefinedFunction($unit)) { + return CodeUnitCollection::fromList(CodeUnit::forFunction($unit)); + } + } + + throw new InvalidCodeUnitException( + sprintf( + '"%s" is not a valid code unit', + $unit + ) + ); + } + + /** + * @psalm-param class-string $className + * + * @throws ReflectionException + */ + private function reflectorForClass(string $className): ReflectionClass + { + try { + return new ReflectionClass($className); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedFunction(string $functionName): bool + { + if (!function_exists($functionName)) { + return false; + } + + try { + return (new ReflectionFunction($functionName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedClass(string $className): bool + { + if (!class_exists($className)) { + return false; + } + + try { + return (new ReflectionClass($className))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedInterface(string $interfaceName): bool + { + if (!interface_exists($interfaceName)) { + return false; + } + + try { + return (new ReflectionClass($interfaceName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedTrait(string $traitName): bool + { + if (!trait_exists($traitName)) { + return false; + } + + try { + return (new ReflectionClass($traitName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @throws ReflectionException + */ + private function isUserDefinedMethod(string $className, string $methodName): bool + { + if (!class_exists($className)) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + if (!method_exists($className, $methodName)) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + try { + return (new ReflectionMethod($className, $methodName))->isUserDefined(); + // @codeCoverageIgnoreStart + } catch (\ReflectionException $e) { + throw new ReflectionException( + $e->getMessage(), + $e->getCode(), + $e + ); + } + // @codeCoverageIgnoreEnd + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitMethodUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitMethodUnit.php new file mode 100644 index 000000000..a58f7249f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitMethodUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class TraitMethodUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true TraitMethodUnit $this + */ + public function isTraitMethod(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitUnit.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitUnit.php new file mode 100644 index 000000000..abddfc112 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/TraitUnit.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +/** + * @psalm-immutable + */ +final class TraitUnit extends CodeUnit +{ + /** + * @psalm-assert-if-true TraitUnit $this + */ + public function isTrait(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/Exception.php new file mode 100644 index 000000000..74d0eeef8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php new file mode 100644 index 000000000..60a3da82b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/InvalidCodeUnitException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use RuntimeException; + +final class InvalidCodeUnitException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php new file mode 100644 index 000000000..e9b9b9c7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/NoTraitException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use RuntimeException; + +final class NoTraitException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php new file mode 100644 index 000000000..232012783 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/code-unit/src/exceptions/ReflectionException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeUnit; + +use RuntimeException; + +final class ReflectionException extends RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/comparator/ChangeLog.md new file mode 100644 index 000000000..d0ce173f5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/ChangeLog.md @@ -0,0 +1,181 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [5.0.3] - 2024-10-18 + +### Fixed + +* Reverted [#113](https://github.com/sebastianbergmann/comparator/pull/113) as it broke backward compatibility + +## [5.0.2] - 2024-08-12 + +### Fixed + +* [#112](https://github.com/sebastianbergmann/comparator/issues/112): Arrays with different keys and the same values are considered equal in canonicalize mode + +## [5.0.1] - 2023-08-14 + +### Fixed + +* `MockObjectComparator` only works on instances of `PHPUnit\Framework\MockObject\MockObject`, but not on instances of `PHPUnit\Framework\MockObject\Stub` +* `MockObjectComparator` only ignores the `$__phpunit_invocationMocker` property, but not other properties with names prefixed with `__phpunit_` + +## [5.0.0] - 2023-02-03 + +### Changed + +* Methods now have parameter and return type declarations +* `Comparator::$factory` is now private, use `Comparator::factory()` instead +* `ComparisonFailure`, `DOMNodeComparator`, `DateTimeComparator`, `ExceptionComparator`, `MockObjectComparator`, `NumericComparator`, `ResourceComparator`, `SplObjectStorageComparator`, and `TypeComparator` are now `final` +* `ScalarComparator` and `DOMNodeComparator` now use `mb_strtolower($string, 'UTF-8')` instead of `strtolower($string)` + +### Removed + +* Removed `$identical` parameter from `ComparisonFailure::__construct()` +* Removed `Comparator::$exporter` +* Removed support for PHP 7.3, PHP 7.4, and PHP 8.0 + +## [4.0.8] - 2022-09-14 + +### Fixed + +* [#102](https://github.com/sebastianbergmann/comparator/pull/102): Fix `float` comparison precision + +## [4.0.7] - 2022-09-14 + +### Fixed + +* [#99](https://github.com/sebastianbergmann/comparator/pull/99): Fix weak comparison between `'0'` and `false` + +## [4.0.6] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Comparator\Exception` now correctly extends `\Throwable` + +## [4.0.5] - 2020-09-30 + +### Fixed + +* [#89](https://github.com/sebastianbergmann/comparator/pull/89): Handle PHP 8 `ValueError` + +## [4.0.4] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.3] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.2] - 2020-06-15 + +### Fixed + +* [#85](https://github.com/sebastianbergmann/comparator/issues/85): Version 4.0.1 breaks backward compatibility + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [4.0.0] - 2020-02-07 + +### Removed + +* Removed support for PHP 7.1 and PHP 7.2 + +## [3.0.5] - 2022-09-14 + +### Fixed + +* [#102](https://github.com/sebastianbergmann/comparator/pull/102): Fix `float` comparison precision + +## [3.0.4] - 2022-09-14 + +### Fixed + +* [#99](https://github.com/sebastianbergmann/comparator/pull/99): Fix weak comparison between `'0'` and `false` + +## [3.0.3] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1` + +## [3.0.2] - 2018-07-12 + +### Changed + +* By default, `MockObjectComparator` is now tried before all other (default) comparators + +## [3.0.1] - 2018-06-14 + +### Fixed + +* [#53](https://github.com/sebastianbergmann/comparator/pull/53): `DOMNodeComparator` ignores `$ignoreCase` parameter +* [#58](https://github.com/sebastianbergmann/comparator/pull/58): `ScalarComparator` does not handle extremely ugly string comparison edge cases + +## [3.0.0] - 2018-04-18 + +### Fixed + +* [#48](https://github.com/sebastianbergmann/comparator/issues/48): `DateTimeComparator` does not support fractional second deltas + +### Removed + +* Removed support for PHP 7.0 + +## [2.1.3] - 2018-02-01 + +### Changed + +* This component is now compatible with version 3 of `sebastian/diff` + +## [2.1.2] - 2018-01-12 + +### Fixed + +* Fix comparison of `DateTimeImmutable` objects + +## [2.1.1] - 2017-12-22 + +### Fixed + +* [phpunit/#2923](https://github.com/sebastianbergmann/phpunit/issues/2923): Unexpected failed date matching + +## [2.1.0] - 2017-11-03 + +### Added + +* Added `SebastianBergmann\Comparator\Factory::reset()` to unregister all non-default comparators +* Added support for `phpunit/phpunit-mock-objects` version `^5.0` + +[5.0.3]: https://github.com/sebastianbergmann/comparator/compare/5.0.2...5.0.3 +[5.0.2]: https://github.com/sebastianbergmann/comparator/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/comparator/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/comparator/compare/4.0.8...5.0.0 +[4.0.8]: https://github.com/sebastianbergmann/comparator/compare/4.0.7...4.0.8 +[4.0.7]: https://github.com/sebastianbergmann/comparator/compare/4.0.6...4.0.7 +[4.0.6]: https://github.com/sebastianbergmann/comparator/compare/4.0.5...4.0.6 +[4.0.5]: https://github.com/sebastianbergmann/comparator/compare/4.0.4...4.0.5 +[4.0.4]: https://github.com/sebastianbergmann/comparator/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/comparator/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/comparator/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/comparator/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/comparator/compare/3.0.5...4.0.0 +[3.0.5]: https://github.com/sebastianbergmann/comparator/compare/3.0.4...3.0.5 +[3.0.4]: https://github.com/sebastianbergmann/comparator/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/sebastianbergmann/comparator/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/comparator/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/comparator/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/comparator/compare/2.1.3...3.0.0 +[2.1.3]: https://github.com/sebastianbergmann/comparator/compare/2.1.2...2.1.3 +[2.1.2]: https://github.com/sebastianbergmann/comparator/compare/2.1.1...2.1.2 +[2.1.1]: https://github.com/sebastianbergmann/comparator/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/sebastianbergmann/comparator/compare/2.0.2...2.1.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/comparator/LICENSE new file mode 100644 index 000000000..5b4705a48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2002-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/comparator/README.md b/.extlib/simplesamlphp/vendor/sebastian/comparator/README.md new file mode 100644 index 000000000..edce75d6c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/README.md @@ -0,0 +1,43 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/comparator/v/stable.png)](https://packagist.org/packages/sebastian/comparator) +[![CI Status](https://github.com/sebastianbergmann/comparator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/comparator/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/comparator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/comparator) +[![codecov](https://codecov.io/gh/sebastianbergmann/comparator/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/comparator) + +# sebastian/comparator + +This component provides the functionality to compare PHP values for equality. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/comparator +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/comparator +``` + +## Usage + +```php +getComparatorFor($date1, $date2); + +try { + $comparator->assertEquals($date1, $date2); + print "Dates match"; +} catch (ComparisonFailure $failure) { + print "Dates don't match"; +} +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/comparator/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/composer.json b/.extlib/simplesamlphp/vendor/sebastian/comparator/composer.json new file mode 100644 index 000000000..16bf52555 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/composer.json @@ -0,0 +1,63 @@ +{ + "name": "sebastian/comparator", + "description": "Provides the functionality to compare PHP values for equality", + "keywords": ["comparator","compare","equality"], + "homepage": "https://github.com/sebastianbergmann/comparator", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0", + "ext-dom": "*", + "ext-mbstring": "*" + }, + "require-dev": { + "phpunit/phpunit": "^10.5" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + } +} + diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ArrayComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ArrayComparator.php new file mode 100644 index 000000000..755083271 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ArrayComparator.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function array_key_exists; +use function assert; +use function is_array; +use function sort; +use function sprintf; +use function str_replace; +use function trim; +use SebastianBergmann\Exporter\Exporter; + +/** + * Arrays are equal if they contain the same key-value pairs. + * The order of the keys does not matter. + * The types of key-value pairs do not matter. + */ +class ArrayComparator extends Comparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return is_array($expected) && is_array($actual); + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void + { + assert(is_array($expected)); + assert(is_array($actual)); + + if ($canonicalize) { + sort($expected); + sort($actual); + } + + $remaining = $actual; + $actualAsString = "Array (\n"; + $expectedAsString = "Array (\n"; + $equal = true; + $exporter = new Exporter; + + foreach ($expected as $key => $value) { + unset($remaining[$key]); + + if (!array_key_exists($key, $actual)) { + $expectedAsString .= sprintf( + " %s => %s\n", + $exporter->export($key), + $exporter->shortenedExport($value), + ); + + $equal = false; + + continue; + } + + try { + $comparator = $this->factory()->getComparatorFor($value, $actual[$key]); + $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed); + + $expectedAsString .= sprintf( + " %s => %s\n", + $exporter->export($key), + $exporter->shortenedExport($value), + ); + + $actualAsString .= sprintf( + " %s => %s\n", + $exporter->export($key), + $exporter->shortenedExport($actual[$key]), + ); + } catch (ComparisonFailure $e) { + $expectedAsString .= sprintf( + " %s => %s\n", + $exporter->export($key), + $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $exporter->shortenedExport($e->getExpected()), + ); + + $actualAsString .= sprintf( + " %s => %s\n", + $exporter->export($key), + $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $exporter->shortenedExport($e->getActual()), + ); + + $equal = false; + } + } + + foreach ($remaining as $key => $value) { + $actualAsString .= sprintf( + " %s => %s\n", + $exporter->export($key), + $exporter->shortenedExport($value), + ); + + $equal = false; + } + + $expectedAsString .= ')'; + $actualAsString .= ')'; + + if (!$equal) { + throw new ComparisonFailure( + $expected, + $actual, + $expectedAsString, + $actualAsString, + 'Failed asserting that two arrays are equal.', + ); + } + } + + private function indent(string $lines): string + { + return trim(str_replace("\n", "\n ", $lines)); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/Comparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/Comparator.php new file mode 100644 index 000000000..69347ef88 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/Comparator.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +abstract class Comparator +{ + private Factory $factory; + + public function setFactory(Factory $factory): void + { + $this->factory = $factory; + } + + abstract public function accepts(mixed $expected, mixed $actual): bool; + + /** + * @throws ComparisonFailure + */ + abstract public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void; + + protected function factory(): Factory + { + return $this->factory; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ComparisonFailure.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ComparisonFailure.php new file mode 100644 index 000000000..b5c2ac2dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ComparisonFailure.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use RuntimeException; +use SebastianBergmann\Diff\Differ; +use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; + +final class ComparisonFailure extends RuntimeException +{ + private mixed $expected; + private mixed $actual; + private string $expectedAsString; + private string $actualAsString; + + public function __construct(mixed $expected, mixed $actual, string $expectedAsString, string $actualAsString, string $message = '') + { + parent::__construct($message); + + $this->expected = $expected; + $this->actual = $actual; + $this->expectedAsString = $expectedAsString; + $this->actualAsString = $actualAsString; + } + + public function getActual(): mixed + { + return $this->actual; + } + + public function getExpected(): mixed + { + return $this->expected; + } + + public function getActualAsString(): string + { + return $this->actualAsString; + } + + public function getExpectedAsString(): string + { + return $this->expectedAsString; + } + + public function getDiff(): string + { + if (!$this->actualAsString && !$this->expectedAsString) { + return ''; + } + + $differ = new Differ(new UnifiedDiffOutputBuilder("\n--- Expected\n+++ Actual\n")); + + return $differ->diff($this->expectedAsString, $this->actualAsString); + } + + public function toString(): string + { + return $this->getMessage() . $this->getDiff(); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/DOMNodeComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/DOMNodeComparator.php new file mode 100644 index 000000000..e78a401f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/DOMNodeComparator.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function assert; +use function mb_strtolower; +use function sprintf; +use DOMDocument; +use DOMNode; +use ValueError; + +final class DOMNodeComparator extends ObjectComparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return $expected instanceof DOMNode && $actual instanceof DOMNode; + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void + { + assert($expected instanceof DOMNode); + assert($actual instanceof DOMNode); + + $expectedAsString = $this->nodeToText($expected, true, $ignoreCase); + $actualAsString = $this->nodeToText($actual, true, $ignoreCase); + + if ($expectedAsString !== $actualAsString) { + $type = $expected instanceof DOMDocument ? 'documents' : 'nodes'; + + throw new ComparisonFailure( + $expected, + $actual, + $expectedAsString, + $actualAsString, + sprintf("Failed asserting that two DOM %s are equal.\n", $type), + ); + } + } + + /** + * Returns the normalized, whitespace-cleaned, and indented textual + * representation of a DOMNode. + */ + private function nodeToText(DOMNode $node, bool $canonicalize, bool $ignoreCase): string + { + if ($canonicalize) { + $document = new DOMDocument; + + try { + $c14n = $node->C14N(); + + assert(!empty($c14n)); + + @$document->loadXML($c14n); + } catch (ValueError) { + } + + $node = $document; + } + + $document = $node instanceof DOMDocument ? $node : $node->ownerDocument; + + $document->formatOutput = true; + $document->normalizeDocument(); + + $text = $node instanceof DOMDocument ? $node->saveXML() : $document->saveXML($node); + + return $ignoreCase ? mb_strtolower($text, 'UTF-8') : $text; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/DateTimeComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/DateTimeComparator.php new file mode 100644 index 000000000..16792d777 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/DateTimeComparator.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function abs; +use function assert; +use function floor; +use function sprintf; +use DateInterval; +use DateTimeInterface; +use DateTimeZone; + +final class DateTimeComparator extends ObjectComparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return ($expected instanceof DateTimeInterface) && + ($actual instanceof DateTimeInterface); + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void + { + assert($expected instanceof DateTimeInterface); + assert($actual instanceof DateTimeInterface); + + $absDelta = abs($delta); + $delta = new DateInterval(sprintf('PT%dS', $absDelta)); + $delta->f = $absDelta - floor($absDelta); + + $actualClone = (clone $actual) + ->setTimezone(new DateTimeZone('UTC')); + + $expectedLower = (clone $expected) + ->setTimezone(new DateTimeZone('UTC')) + ->sub($delta); + + $expectedUpper = (clone $expected) + ->setTimezone(new DateTimeZone('UTC')) + ->add($delta); + + if ($actualClone < $expectedLower || $actualClone > $expectedUpper) { + throw new ComparisonFailure( + $expected, + $actual, + $this->dateTimeToString($expected), + $this->dateTimeToString($actual), + 'Failed asserting that two DateTime objects are equal.', + ); + } + } + + /** + * Returns an ISO 8601 formatted string representation of a datetime or + * 'Invalid DateTimeInterface object' if the provided DateTimeInterface was not properly + * initialized. + */ + private function dateTimeToString(DateTimeInterface $datetime): string + { + $string = $datetime->format('Y-m-d\TH:i:s.uO'); + + return $string ?: 'Invalid DateTimeInterface object'; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ExceptionComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ExceptionComparator.php new file mode 100644 index 000000000..b44dd8169 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ExceptionComparator.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 SebastianBergmann\Comparator; + +use function assert; +use Exception; + +/** + * Compares Exception instances for equality. + */ +final class ExceptionComparator extends ObjectComparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return $expected instanceof Exception && $actual instanceof Exception; + } + + protected function toArray(object $object): array + { + assert($object instanceof Exception); + + $array = parent::toArray($object); + + unset( + $array['file'], + $array['line'], + $array['trace'], + $array['string'], + $array['xdebug_message'], + ); + + return $array; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/Factory.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/Factory.php new file mode 100644 index 000000000..7285c75f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/Factory.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function array_unshift; + +final class Factory +{ + private static ?Factory $instance = null; + + /** + * @psalm-var list + */ + private array $customComparators = []; + + /** + * @psalm-var list + */ + private array $defaultComparators = []; + + public static function getInstance(): self + { + if (self::$instance === null) { + self::$instance = new self; // @codeCoverageIgnore + } + + return self::$instance; + } + + public function __construct() + { + $this->registerDefaultComparators(); + } + + public function getComparatorFor(mixed $expected, mixed $actual): Comparator + { + foreach ($this->customComparators as $comparator) { + if ($comparator->accepts($expected, $actual)) { + return $comparator; + } + } + + foreach ($this->defaultComparators as $comparator) { + if ($comparator->accepts($expected, $actual)) { + return $comparator; + } + } + + throw new RuntimeException('No suitable Comparator implementation found'); + } + + /** + * Registers a new comparator. + * + * This comparator will be returned by getComparatorFor() if its accept() method + * returns TRUE for the compared values. It has higher priority than the + * existing comparators, meaning that its accept() method will be invoked + * before those of the other comparators. + */ + public function register(Comparator $comparator): void + { + array_unshift($this->customComparators, $comparator); + + $comparator->setFactory($this); + } + + /** + * Unregisters a comparator. + * + * This comparator will no longer be considered by getComparatorFor(). + */ + public function unregister(Comparator $comparator): void + { + foreach ($this->customComparators as $key => $_comparator) { + if ($comparator === $_comparator) { + unset($this->customComparators[$key]); + } + } + } + + public function reset(): void + { + $this->customComparators = []; + } + + private function registerDefaultComparators(): void + { + $this->registerDefaultComparator(new MockObjectComparator); + $this->registerDefaultComparator(new DateTimeComparator); + $this->registerDefaultComparator(new DOMNodeComparator); + $this->registerDefaultComparator(new SplObjectStorageComparator); + $this->registerDefaultComparator(new ExceptionComparator); + $this->registerDefaultComparator(new ObjectComparator); + $this->registerDefaultComparator(new ResourceComparator); + $this->registerDefaultComparator(new ArrayComparator); + $this->registerDefaultComparator(new NumericComparator); + $this->registerDefaultComparator(new ScalarComparator); + $this->registerDefaultComparator(new TypeComparator); + } + + private function registerDefaultComparator(Comparator $comparator): void + { + $this->defaultComparators[] = $comparator; + + $comparator->setFactory($this); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/MockObjectComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/MockObjectComparator.php new file mode 100644 index 000000000..67d5ade00 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/MockObjectComparator.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function array_keys; +use function assert; +use function str_starts_with; +use PHPUnit\Framework\MockObject\Stub; + +/** + * Compares PHPUnit\Framework\MockObject\MockObject instances for equality. + */ +final class MockObjectComparator extends ObjectComparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return $expected instanceof Stub && $actual instanceof Stub; + } + + protected function toArray(object $object): array + { + assert($object instanceof Stub); + + $array = parent::toArray($object); + + foreach (array_keys($array) as $key) { + if (!str_starts_with($key, '__phpunit_')) { + continue; + } + + unset($array[$key]); + } + + return $array; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/NumericComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/NumericComparator.php new file mode 100644 index 000000000..3d783edb8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/NumericComparator.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function abs; +use function is_float; +use function is_infinite; +use function is_nan; +use function is_numeric; +use function is_string; +use function sprintf; +use SebastianBergmann\Exporter\Exporter; + +final class NumericComparator extends ScalarComparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + // all numerical values, but not if both of them are strings + return is_numeric($expected) && is_numeric($actual) && + !(is_string($expected) && is_string($actual)); + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void + { + if ($this->isInfinite($actual) && $this->isInfinite($expected)) { + return; + } + + if (($this->isInfinite($actual) xor $this->isInfinite($expected)) || + ($this->isNan($actual) || $this->isNan($expected)) || + abs($actual - $expected) > $delta) { + $exporter = new Exporter; + + throw new ComparisonFailure( + $expected, + $actual, + '', + '', + sprintf( + 'Failed asserting that %s matches expected %s.', + $exporter->export($actual), + $exporter->export($expected), + ), + ); + } + } + + private function isInfinite(mixed $value): bool + { + return is_float($value) && is_infinite($value); + } + + private function isNan(mixed $value): bool + { + return is_float($value) && is_nan($value); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ObjectComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ObjectComparator.php new file mode 100644 index 000000000..95f97ed1e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ObjectComparator.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function assert; +use function in_array; +use function is_object; +use function sprintf; +use function substr_replace; +use SebastianBergmann\Exporter\Exporter; + +class ObjectComparator extends ArrayComparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return is_object($expected) && is_object($actual); + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void + { + assert(is_object($expected)); + assert(is_object($actual)); + + if ($actual::class !== $expected::class) { + $exporter = new Exporter; + + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected), + $exporter->export($actual), + sprintf( + '%s is not instance of expected class "%s".', + $exporter->export($actual), + $expected::class, + ), + ); + } + + // don't compare twice to allow for cyclic dependencies + if (in_array([$actual, $expected], $processed, true) || + in_array([$expected, $actual], $processed, true)) { + return; + } + + $processed[] = [$actual, $expected]; + + // don't compare objects if they are identical + // this helps to avoid the error "maximum function nesting level reached" + // CAUTION: this conditional clause is not tested + if ($actual !== $expected) { + try { + parent::assertEquals( + $this->toArray($expected), + $this->toArray($actual), + $delta, + $canonicalize, + $ignoreCase, + $processed, + ); + } catch (ComparisonFailure $e) { + throw new ComparisonFailure( + $expected, + $actual, + // replace "Array" with "MyClass object" + substr_replace($e->getExpectedAsString(), $expected::class . ' Object', 0, 5), + substr_replace($e->getActualAsString(), $actual::class . ' Object', 0, 5), + 'Failed asserting that two objects are equal.', + ); + } + } + } + + protected function toArray(object $object): array + { + return (new Exporter)->toArray($object); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ResourceComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ResourceComparator.php new file mode 100644 index 000000000..16995623b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ResourceComparator.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function assert; +use function is_resource; +use SebastianBergmann\Exporter\Exporter; + +final class ResourceComparator extends Comparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return is_resource($expected) && is_resource($actual); + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void + { + assert(is_resource($expected)); + assert(is_resource($actual)); + + $exporter = new Exporter; + + if ($actual != $expected) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected), + $exporter->export($actual), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ScalarComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ScalarComparator.php new file mode 100644 index 000000000..79c50457f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/ScalarComparator.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function is_bool; +use function is_object; +use function is_scalar; +use function is_string; +use function mb_strtolower; +use function method_exists; +use function sprintf; +use SebastianBergmann\Exporter\Exporter; + +/** + * Compares scalar or NULL values for equality. + */ +class ScalarComparator extends Comparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return ((is_scalar($expected) xor null === $expected) && + (is_scalar($actual) xor null === $actual)) || + // allow comparison between strings and objects featuring __toString() + (is_string($expected) && is_object($actual) && method_exists($actual, '__toString')) || + (is_object($expected) && method_exists($expected, '__toString') && is_string($actual)); + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void + { + $expectedToCompare = $expected; + $actualToCompare = $actual; + $exporter = new Exporter; + + // always compare as strings to avoid strange behaviour + // otherwise 0 == 'Foobar' + if ((is_string($expected) && !is_bool($actual)) || (is_string($actual) && !is_bool($expected))) { + $expectedToCompare = (string) $expectedToCompare; + $actualToCompare = (string) $actualToCompare; + + if ($ignoreCase) { + $expectedToCompare = mb_strtolower($expectedToCompare, 'UTF-8'); + $actualToCompare = mb_strtolower($actualToCompare, 'UTF-8'); + } + } + + if ($expectedToCompare !== $actualToCompare && is_string($expected) && is_string($actual)) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected), + $exporter->export($actual), + 'Failed asserting that two strings are equal.', + ); + } + + if ($expectedToCompare != $actualToCompare) { + throw new ComparisonFailure( + $expected, + $actual, + // no diff is required + '', + '', + sprintf( + 'Failed asserting that %s matches expected %s.', + $exporter->export($actual), + $exporter->export($expected), + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/SplObjectStorageComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/SplObjectStorageComparator.php new file mode 100644 index 000000000..a1eeda390 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/SplObjectStorageComparator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function assert; +use SebastianBergmann\Exporter\Exporter; +use SplObjectStorage; + +final class SplObjectStorageComparator extends Comparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return $expected instanceof SplObjectStorage && $actual instanceof SplObjectStorage; + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void + { + assert($expected instanceof SplObjectStorage); + assert($actual instanceof SplObjectStorage); + + $exporter = new Exporter; + + foreach ($actual as $object) { + if (!$expected->contains($object)) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected), + $exporter->export($actual), + 'Failed asserting that two objects are equal.', + ); + } + } + + foreach ($expected as $object) { + if (!$actual->contains($object)) { + throw new ComparisonFailure( + $expected, + $actual, + $exporter->export($expected), + $exporter->export($actual), + 'Failed asserting that two objects are equal.', + ); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/TypeComparator.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/TypeComparator.php new file mode 100644 index 000000000..67994e9f6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/TypeComparator.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use function gettype; +use function sprintf; +use SebastianBergmann\Exporter\Exporter; + +final class TypeComparator extends Comparator +{ + public function accepts(mixed $expected, mixed $actual): bool + { + return true; + } + + /** + * @throws ComparisonFailure + */ + public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void + { + if (gettype($expected) != gettype($actual)) { + throw new ComparisonFailure( + $expected, + $actual, + // we don't need a diff + '', + '', + sprintf( + '%s does not match expected type "%s".', + (new Exporter)->shortenedExport($actual), + gettype($expected), + ), + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/Exception.php new file mode 100644 index 000000000..8975aaf1b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/RuntimeException.php b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/RuntimeException.php new file mode 100644 index 000000000..ca726084a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/comparator/src/exceptions/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Comparator; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/complexity/ChangeLog.md new file mode 100644 index 000000000..eb168af75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/ChangeLog.md @@ -0,0 +1,68 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [3.2.0] - 2023-12-21 + +### Added + +* `ComplexityCollection::sortByDescendingCyclomaticComplexity()` + +### Changed + +* This component is now compatible with `nikic/php-parser` 5.0 + +## [3.1.0] - 2023-09-28 + +### Added + +* `Complexity::isFunction()` and `Complexity::isMethod()` +* `ComplexityCollection::isFunction()` and `ComplexityCollection::isMethod()` +* `ComplexityCollection::mergeWith()` + +### Fixed + +* Anonymous classes are not processed correctly + +## [3.0.1] - 2023-08-31 + +### Fixed + +* [#7](https://github.com/sebastianbergmann/complexity/pull/7): `ComplexityCalculatingVisitor` tries to process interface methods + +## [3.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [2.0.2] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Complexity\Exception` now correctly extends `\Throwable` + +## [2.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.0] - 2020-07-25 + +### Removed + +* The `ParentConnectingVisitor` has been removed (it should have been marked as `@internal`) + +## [1.0.0] - 2020-07-22 + +* Initial release + +[3.2.0]: https://github.com/sebastianbergmann/complexity/compare/3.1.0...3.2.0 +[3.1.0]: https://github.com/sebastianbergmann/complexity/compare/3.0.1...3.1.0 +[3.0.1]: https://github.com/sebastianbergmann/complexity/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/complexity/compare/2.0.2...3.0.0 +[2.0.2]: https://github.com/sebastianbergmann/complexity/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/complexity/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/complexity/compare/1.0.0...2.0.0 +[1.0.0]: https://github.com/sebastianbergmann/complexity/compare/70ee0ad32d9e2be3f85beffa3e2eb474193f2487...1.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/complexity/LICENSE new file mode 100644 index 000000000..5716d9654 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/complexity/README.md b/.extlib/simplesamlphp/vendor/sebastian/complexity/README.md new file mode 100644 index 000000000..3903c36be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/complexity/v/stable.png)](https://packagist.org/packages/sebastian/complexity) +[![CI Status](https://github.com/sebastianbergmann/complexity/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/complexity/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/complexity/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/complexity) +[![codecov](https://codecov.io/gh/sebastianbergmann/complexity/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/complexity) + +# sebastian/complexity + +Library for calculating the complexity of PHP code units. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/complexity +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/complexity +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/complexity/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/composer.json b/.extlib/simplesamlphp/vendor/sebastian/complexity/composer.json new file mode 100644 index 000000000..77001bb22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/composer.json @@ -0,0 +1,43 @@ +{ + "name": "sebastian/complexity", + "description": "Library for calculating the complexity of PHP code units", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/complexity", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1", + "nikic/php-parser": "^4.18 || ^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Calculator.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Calculator.php new file mode 100644 index 000000000..18580bdb1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Calculator.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 SebastianBergmann\Complexity; + +use function assert; +use function file_get_contents; +use PhpParser\Error; +use PhpParser\Node; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor\NameResolver; +use PhpParser\NodeVisitor\ParentConnectingVisitor; +use PhpParser\ParserFactory; + +final class Calculator +{ + /** + * @throws RuntimeException + */ + public function calculateForSourceFile(string $sourceFile): ComplexityCollection + { + return $this->calculateForSourceString(file_get_contents($sourceFile)); + } + + /** + * @throws RuntimeException + */ + public function calculateForSourceString(string $source): ComplexityCollection + { + try { + $nodes = (new ParserFactory)->createForHostVersion()->parse($source); + + assert($nodes !== null); + + return $this->calculateForAbstractSyntaxTree($nodes); + + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + $error->getCode(), + $error, + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @param Node[] $nodes + * + * @throws RuntimeException + */ + public function calculateForAbstractSyntaxTree(array $nodes): ComplexityCollection + { + $traverser = new NodeTraverser; + $complexityCalculatingVisitor = new ComplexityCalculatingVisitor(true); + + $traverser->addVisitor(new NameResolver); + $traverser->addVisitor(new ParentConnectingVisitor); + $traverser->addVisitor($complexityCalculatingVisitor); + + try { + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + $error->getCode(), + $error, + ); + } + // @codeCoverageIgnoreEnd + + return $complexityCalculatingVisitor->result(); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/Complexity.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/Complexity.php new file mode 100644 index 000000000..5203454bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/Complexity.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use function str_contains; + +/** + * @psalm-immutable + */ +final class Complexity +{ + /** + * @psalm-var non-empty-string + */ + private readonly string $name; + + /** + * @psalm-var positive-int + */ + private int $cyclomaticComplexity; + + /** + * @psalm-param non-empty-string $name + * @psalm-param positive-int $cyclomaticComplexity + */ + public function __construct(string $name, int $cyclomaticComplexity) + { + $this->name = $name; + $this->cyclomaticComplexity = $cyclomaticComplexity; + } + + /** + * @psalm-return non-empty-string + */ + public function name(): string + { + return $this->name; + } + + /** + * @psalm-return positive-int + */ + public function cyclomaticComplexity(): int + { + return $this->cyclomaticComplexity; + } + + public function isFunction(): bool + { + return !$this->isMethod(); + } + + public function isMethod(): bool + { + return str_contains($this->name, '::'); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php new file mode 100644 index 000000000..0f851c2a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollection.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use function array_filter; +use function array_merge; +use function array_reverse; +use function array_values; +use function count; +use function usort; +use Countable; +use IteratorAggregate; + +/** + * @psalm-immutable + */ +final class ComplexityCollection implements Countable, IteratorAggregate +{ + /** + * @psalm-var list + */ + private readonly array $items; + + public static function fromList(Complexity ...$items): self + { + return new self($items); + } + + /** + * @psalm-param list $items + */ + private function __construct(array $items) + { + $this->items = $items; + } + + /** + * @psalm-return list + */ + public function asArray(): array + { + return $this->items; + } + + public function getIterator(): ComplexityCollectionIterator + { + return new ComplexityCollectionIterator($this); + } + + /** + * @psalm-return non-negative-int + */ + public function count(): int + { + return count($this->items); + } + + public function isEmpty(): bool + { + return empty($this->items); + } + + /** + * @psalm-return non-negative-int + */ + public function cyclomaticComplexity(): int + { + $cyclomaticComplexity = 0; + + foreach ($this as $item) { + $cyclomaticComplexity += $item->cyclomaticComplexity(); + } + + return $cyclomaticComplexity; + } + + public function isFunction(): self + { + return new self( + array_values( + array_filter( + $this->items, + static fn (Complexity $complexity): bool => $complexity->isFunction(), + ), + ), + ); + } + + public function isMethod(): self + { + return new self( + array_values( + array_filter( + $this->items, + static fn (Complexity $complexity): bool => $complexity->isMethod(), + ), + ), + ); + } + + public function mergeWith(self $other): self + { + return new self( + array_merge( + $this->asArray(), + $other->asArray(), + ), + ); + } + + public function sortByDescendingCyclomaticComplexity(): self + { + $items = $this->items; + + usort( + $items, + static function (Complexity $a, Complexity $b): int + { + return $a->cyclomaticComplexity() <=> $b->cyclomaticComplexity(); + }, + ); + + return new self(array_reverse($items)); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php new file mode 100644 index 000000000..c3ac69080 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Complexity/ComplexityCollectionIterator.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use Iterator; + +final class ComplexityCollectionIterator implements Iterator +{ + /** + * @psalm-var list + */ + private readonly array $items; + private int $position = 0; + + public function __construct(ComplexityCollection $items) + { + $this->items = $items->asArray(); + } + + public function rewind(): void + { + $this->position = 0; + } + + public function valid(): bool + { + return isset($this->items[$this->position]); + } + + public function key(): int + { + return $this->position; + } + + public function current(): Complexity + { + return $this->items[$this->position]; + } + + public function next(): void + { + $this->position++; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/Exception.php new file mode 100644 index 000000000..897ecdcf7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/RuntimeException.php new file mode 100644 index 000000000..6c68a6f0f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php new file mode 100644 index 000000000..0314bf1dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/ComplexityCalculatingVisitor.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Complexity; + +use function assert; +use function is_array; +use PhpParser\Node; +use PhpParser\Node\Expr\New_; +use PhpParser\Node\Name; +use PhpParser\Node\Stmt; +use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Function_; +use PhpParser\Node\Stmt\Interface_; +use PhpParser\Node\Stmt\Trait_; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitorAbstract; + +final class ComplexityCalculatingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var list + */ + private array $result = []; + private bool $shortCircuitTraversal; + + public function __construct(bool $shortCircuitTraversal) + { + $this->shortCircuitTraversal = $shortCircuitTraversal; + } + + public function enterNode(Node $node): ?int + { + if (!$node instanceof ClassMethod && !$node instanceof Function_) { + return null; + } + + if ($node instanceof ClassMethod) { + if ($node->getAttribute('parent') instanceof Interface_) { + return null; + } + + if ($node->isAbstract()) { + return null; + } + + $name = $this->classMethodName($node); + } else { + $name = $this->functionName($node); + } + + $statements = $node->getStmts(); + + assert(is_array($statements)); + + $this->result[] = new Complexity( + $name, + $this->cyclomaticComplexity($statements), + ); + + if ($this->shortCircuitTraversal) { + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + } + + return null; + } + + public function result(): ComplexityCollection + { + return ComplexityCollection::fromList(...$this->result); + } + + /** + * @param Stmt[] $statements + * + * @psalm-return positive-int + */ + private function cyclomaticComplexity(array $statements): int + { + $traverser = new NodeTraverser; + + $cyclomaticComplexityCalculatingVisitor = new CyclomaticComplexityCalculatingVisitor; + + $traverser->addVisitor($cyclomaticComplexityCalculatingVisitor); + + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($statements); + + return $cyclomaticComplexityCalculatingVisitor->cyclomaticComplexity(); + } + + /** + * @psalm-return non-empty-string + */ + private function classMethodName(ClassMethod $node): string + { + $parent = $node->getAttribute('parent'); + + assert($parent instanceof Class_ || $parent instanceof Trait_); + + if ($parent->getAttribute('parent') instanceof New_) { + return 'anonymous class'; + } + + assert(isset($parent->namespacedName)); + assert($parent->namespacedName instanceof Name); + + return $parent->namespacedName->toString() . '::' . $node->name->toString(); + } + + /** + * @psalm-return non-empty-string + */ + private function functionName(Function_ $node): string + { + assert(isset($node->namespacedName)); + assert($node->namespacedName instanceof Name); + + $functionName = $node->namespacedName->toString(); + + assert($functionName !== ''); + + return $functionName; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.php new file mode 100644 index 000000000..551ed1a05 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/complexity/src/Visitor/CyclomaticComplexityCalculatingVisitor.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 SebastianBergmann\Complexity; + +use PhpParser\Node; +use PhpParser\Node\Expr\BinaryOp\BooleanAnd; +use PhpParser\Node\Expr\BinaryOp\BooleanOr; +use PhpParser\Node\Expr\BinaryOp\LogicalAnd; +use PhpParser\Node\Expr\BinaryOp\LogicalOr; +use PhpParser\Node\Expr\Ternary; +use PhpParser\Node\Stmt\Case_; +use PhpParser\Node\Stmt\Catch_; +use PhpParser\Node\Stmt\ElseIf_; +use PhpParser\Node\Stmt\For_; +use PhpParser\Node\Stmt\Foreach_; +use PhpParser\Node\Stmt\If_; +use PhpParser\Node\Stmt\While_; +use PhpParser\NodeVisitorAbstract; + +final class CyclomaticComplexityCalculatingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var positive-int + */ + private int $cyclomaticComplexity = 1; + + public function enterNode(Node $node): void + { + switch ($node::class) { + case BooleanAnd::class: + case BooleanOr::class: + case Case_::class: + case Catch_::class: + case ElseIf_::class: + case For_::class: + case Foreach_::class: + case If_::class: + case LogicalAnd::class: + case LogicalOr::class: + case Ternary::class: + case While_::class: + $this->cyclomaticComplexity++; + } + } + + /** + * @psalm-return positive-int + */ + public function cyclomaticComplexity(): int + { + return $this->cyclomaticComplexity; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/diff/ChangeLog.md new file mode 100644 index 000000000..10c545290 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/ChangeLog.md @@ -0,0 +1,148 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [5.1.1] - 2024-03-02 + +### Changed + +* Do not use implicitly nullable parameters + +## [5.1.0] - 2023-12-22 + +### Added + +* `SebastianBergmann\Diff\Chunk::start()`, `SebastianBergmann\Diff\Chunk::startRange()`, `SebastianBergmann\Diff\Chunk::end()`, `SebastianBergmann\Diff\Chunk::endRange()`, and `SebastianBergmann\Diff\Chunk::lines()` +* `SebastianBergmann\Diff\Diff::from()`, `SebastianBergmann\Diff\Diff::to()`, and `SebastianBergmann\Diff\Diff::chunks()` +* `SebastianBergmann\Diff\Line::content()` and `SebastianBergmann\Diff\Diff::type()` +* `SebastianBergmann\Diff\Line::isAdded()`,`SebastianBergmann\Diff\Line::isRemoved()`, and `SebastianBergmann\Diff\Line::isUnchanged()` + +### Changed + +* `SebastianBergmann\Diff\Diff` now implements `IteratorAggregate`, iterating over it yields the aggregated `SebastianBergmann\Diff\Chunk` objects +* `SebastianBergmann\Diff\Chunk` now implements `IteratorAggregate`, iterating over it yields the aggregated `SebastianBergmann\Diff\Line` objects + +### Deprecated + +* `SebastianBergmann\Diff\Chunk::getStart()`, `SebastianBergmann\Diff\Chunk::getStartRange()`, `SebastianBergmann\Diff\Chunk::getEnd()`, `SebastianBergmann\Diff\Chunk::getEndRange()`, and `SebastianBergmann\Diff\Chunk::getLines()` +* `SebastianBergmann\Diff\Diff::getFrom()`, `SebastianBergmann\Diff\Diff::getTo()`, and `SebastianBergmann\Diff\Diff::getChunks()` +* `SebastianBergmann\Diff\Line::getContent()` and `SebastianBergmann\Diff\Diff::getType()` + +## [5.0.3] - 2023-05-01 + +### Changed + +* [#119](https://github.com/sebastianbergmann/diff/pull/119): Improve performance of `TimeEfficientLongestCommonSubsequenceCalculator` + +## [5.0.2] - 2023-05-01 + +### Changed + +* [#118](https://github.com/sebastianbergmann/diff/pull/118): Improve performance of `MemoryEfficientLongestCommonSubsequenceCalculator` + +## [5.0.1] - 2023-03-23 + +### Fixed + +* [#115](https://github.com/sebastianbergmann/diff/pull/115): `Parser::parseFileDiff()` does not handle diffs correctly that only add lines or only remove lines + +## [5.0.0] - 2023-02-03 + +### Changed + +* Passing a `DiffOutputBuilderInterface` instance to `Differ::__construct()` is no longer optional + +### Removed + +* Removed support for PHP 7.3, PHP 7.4, and PHP 8.0 + +## [4.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Diff\Exception` now correctly extends `\Throwable` + +## [4.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-30 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-05-08 + +### Fixed + +* [#99](https://github.com/sebastianbergmann/diff/pull/99): Regression in unified diff output of identical strings + +## [4.0.0] - 2020-02-07 + +### Removed + +* Removed support for PHP 7.1 and PHP 7.2 + +## [3.0.2] - 2019-02-04 + +### Changed + +* `Chunk::setLines()` now ensures that the `$lines` array only contains `Line` objects + +## [3.0.1] - 2018-06-10 + +### Fixed + +* Removed `"minimum-stability": "dev",` from `composer.json` + +## [3.0.0] - 2018-02-01 + +* The `StrictUnifiedDiffOutputBuilder` implementation of the `DiffOutputBuilderInterface` was added + +### Changed + +* The default `DiffOutputBuilderInterface` implementation now generates context lines (unchanged lines) + +### Removed + +* Removed support for PHP 7.0 + +### Fixed + +* [#70](https://github.com/sebastianbergmann/diff/issues/70): Diffing of arrays no longer works + +## [2.0.1] - 2017-08-03 + +### Fixed + +* [#66](https://github.com/sebastianbergmann/diff/pull/66): Restored backwards compatibility for PHPUnit 6.1.4, 6.2.0, 6.2.1, 6.2.2, and 6.2.3 + +## [2.0.0] - 2017-07-11 [YANKED] + +### Added + +* [#64](https://github.com/sebastianbergmann/diff/pull/64): Show line numbers for chunks of a diff + +### Removed + +* This component is no longer supported on PHP 5.6 + +[5.1.1]: https://github.com/sebastianbergmann/diff/compare/5.1.0...5.1.1 +[5.1.0]: https://github.com/sebastianbergmann/diff/compare/5.0.3...5.1.0 +[5.0.3]: https://github.com/sebastianbergmann/diff/compare/5.0.2...5.0.3 +[5.0.2]: https://github.com/sebastianbergmann/diff/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/diff/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/diff/compare/4.0.4...5.0.0 +[4.0.4]: https://github.com/sebastianbergmann/diff/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/diff/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/diff/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/diff/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/diff/compare/3.0.2...4.0.0 +[3.0.2]: https://github.com/sebastianbergmann/diff/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/diff/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/diff/compare/2.0...3.0.0 +[2.0.1]: https://github.com/sebastianbergmann/diff/compare/c341c98ce083db77f896a0aa64f5ee7652915970...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/diff/compare/1.4...c341c98ce083db77f896a0aa64f5ee7652915970 diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/diff/LICENSE new file mode 100644 index 000000000..5b4705a48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2002-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/diff/README.md b/.extlib/simplesamlphp/vendor/sebastian/diff/README.md new file mode 100644 index 000000000..539dc59ed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/README.md @@ -0,0 +1,206 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/diff/v/stable.png)](https://packagist.org/packages/sebastian/diff) +[![CI Status](https://github.com/sebastianbergmann/diff/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/diff/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/diff/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/diff) +[![codecov](https://codecov.io/gh/sebastianbergmann/diff/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/diff) + +# sebastian/diff + +Diff implementation for PHP, factored out of PHPUnit into a stand-alone component. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/diff +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/diff +``` + +### Usage + +#### Generating diff + +The `Differ` class can be used to generate a textual representation of the difference between two strings: + +```php +diff('foo', 'bar'); +``` + +The code above yields the output below: +```diff +--- Original ++++ New +@@ @@ +-foo ++bar +``` + +There are three output builders available in this package: + +#### UnifiedDiffOutputBuilder + +This is default builder, which generates the output close to udiff and is used by PHPUnit. + +```php +diff('foo', 'bar'); +``` + +#### StrictUnifiedDiffOutputBuilder + +Generates (strict) Unified diff's (unidiffs) with hunks, +similar to `diff -u` and compatible with `patch` and `git apply`. + +```php + 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' => '', + 'fromFileDate' => null, + 'toFile' => '', + 'toFileDate' => null, +]); + +$differ = new Differ($builder); +print $differ->diff('foo', 'bar'); +``` + +#### DiffOnlyOutputBuilder + +Output only the lines that differ. + +```php +diff('foo', 'bar'); +``` + +#### DiffOutputBuilderInterface + +You can pass any output builder to the `Differ` class as longs as it implements the `DiffOutputBuilderInterface`. + +#### Parsing diff + +The `Parser` class can be used to parse a unified diff into an object graph: + +```php +use SebastianBergmann\Diff\Parser; +use SebastianBergmann\Git; + +$git = new Git('/usr/local/src/money'); + +$diff = $git->getDiff( + '948a1a07768d8edd10dcefa8315c1cbeffb31833', + 'c07a373d2399f3e686234c4f7f088d635eb9641b' +); + +$parser = new Parser; + +print_r($parser->parse($diff)); +``` + +The code above yields the output below: + + Array + ( + [0] => SebastianBergmann\Diff\Diff Object + ( + [from:SebastianBergmann\Diff\Diff:private] => a/tests/MoneyTest.php + [to:SebastianBergmann\Diff\Diff:private] => b/tests/MoneyTest.php + [chunks:SebastianBergmann\Diff\Diff:private] => Array + ( + [0] => SebastianBergmann\Diff\Chunk Object + ( + [start:SebastianBergmann\Diff\Chunk:private] => 87 + [startRange:SebastianBergmann\Diff\Chunk:private] => 7 + [end:SebastianBergmann\Diff\Chunk:private] => 87 + [endRange:SebastianBergmann\Diff\Chunk:private] => 7 + [lines:SebastianBergmann\Diff\Chunk:private] => Array + ( + [0] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => * @covers SebastianBergmann\Money\Money::add + ) + + [1] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => * @covers SebastianBergmann\Money\Money::newMoney + ) + + [2] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => */ + ) + + [3] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 2 + [content:SebastianBergmann\Diff\Line:private] => public function testAnotherMoneyWithSameCurrencyObjectCanBeAdded() + ) + + [4] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 1 + [content:SebastianBergmann\Diff\Line:private] => public function testAnotherMoneyObjectWithSameCurrencyCanBeAdded() + ) + + [5] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => { + ) + + [6] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => $a = new Money(1, new Currency('EUR')); + ) + + [7] => SebastianBergmann\Diff\Line Object + ( + [type:SebastianBergmann\Diff\Line:private] => 3 + [content:SebastianBergmann\Diff\Line:private] => $b = new Money(2, new Currency('EUR')); + ) + ) + ) + ) + ) + ) + +Note: If the chunk size is 0 lines, i.e., `getStartRange()` or `getEndRange()` return 0, the number of line returned by `getStart()` or `getEnd()` is one lower than one would expect. It is the line number after which the chunk should be inserted or deleted; in all other cases, it gives the first line number of the replaced range of lines. diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/diff/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/composer.json b/.extlib/simplesamlphp/vendor/sebastian/diff/composer.json new file mode 100644 index 000000000..c6ebec9c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/composer.json @@ -0,0 +1,51 @@ +{ + "name": "sebastian/diff", + "description": "Diff implementation", + "keywords": ["diff", "udiff", "unidiff", "unified diff"], + "homepage": "https://github.com/sebastianbergmann/diff", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy" + }, + "prefer-stable": true, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Chunk.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Chunk.php new file mode 100644 index 000000000..a95685452 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Chunk.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use ArrayIterator; +use IteratorAggregate; +use Traversable; + +/** + * @template-implements IteratorAggregate + */ +final class Chunk implements IteratorAggregate +{ + private int $start; + private int $startRange; + private int $end; + private int $endRange; + private array $lines; + + public function __construct(int $start = 0, int $startRange = 1, int $end = 0, int $endRange = 1, array $lines = []) + { + $this->start = $start; + $this->startRange = $startRange; + $this->end = $end; + $this->endRange = $endRange; + $this->lines = $lines; + } + + public function start(): int + { + return $this->start; + } + + public function startRange(): int + { + return $this->startRange; + } + + public function end(): int + { + return $this->end; + } + + public function endRange(): int + { + return $this->endRange; + } + + /** + * @psalm-return list + */ + public function lines(): array + { + return $this->lines; + } + + /** + * @psalm-param list $lines + */ + public function setLines(array $lines): void + { + foreach ($lines as $line) { + if (!$line instanceof Line) { + throw new InvalidArgumentException; + } + } + + $this->lines = $lines; + } + + /** + * @deprecated Use start() instead + */ + public function getStart(): int + { + return $this->start; + } + + /** + * @deprecated Use startRange() instead + */ + public function getStartRange(): int + { + return $this->startRange; + } + + /** + * @deprecated Use end() instead + */ + public function getEnd(): int + { + return $this->end; + } + + /** + * @deprecated Use endRange() instead + */ + public function getEndRange(): int + { + return $this->endRange; + } + + /** + * @psalm-return list + * + * @deprecated Use lines() instead + */ + public function getLines(): array + { + return $this->lines; + } + + public function getIterator(): Traversable + { + return new ArrayIterator($this->lines); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Diff.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Diff.php new file mode 100644 index 000000000..5dc8dd082 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Diff.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use ArrayIterator; +use IteratorAggregate; +use Traversable; + +/** + * @template-implements IteratorAggregate + */ +final class Diff implements IteratorAggregate +{ + /** + * @psalm-var non-empty-string + */ + private string $from; + + /** + * @psalm-var non-empty-string + */ + private string $to; + + /** + * @psalm-var list + */ + private array $chunks; + + /** + * @psalm-param non-empty-string $from + * @psalm-param non-empty-string $to + * @psalm-param list $chunks + */ + public function __construct(string $from, string $to, array $chunks = []) + { + $this->from = $from; + $this->to = $to; + $this->chunks = $chunks; + } + + /** + * @psalm-return non-empty-string + */ + public function from(): string + { + return $this->from; + } + + /** + * @psalm-return non-empty-string + */ + public function to(): string + { + return $this->to; + } + + /** + * @psalm-return list + */ + public function chunks(): array + { + return $this->chunks; + } + + /** + * @psalm-param list $chunks + */ + public function setChunks(array $chunks): void + { + $this->chunks = $chunks; + } + + /** + * @psalm-return non-empty-string + * + * @deprecated + */ + public function getFrom(): string + { + return $this->from; + } + + /** + * @psalm-return non-empty-string + * + * @deprecated + */ + public function getTo(): string + { + return $this->to; + } + + /** + * @psalm-return list + * + * @deprecated + */ + public function getChunks(): array + { + return $this->chunks; + } + + public function getIterator(): Traversable + { + return new ArrayIterator($this->chunks); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Differ.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Differ.php new file mode 100644 index 000000000..801fe02aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Differ.php @@ -0,0 +1,239 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use const PHP_INT_SIZE; +use const PREG_SPLIT_DELIM_CAPTURE; +use const PREG_SPLIT_NO_EMPTY; +use function array_shift; +use function array_unshift; +use function array_values; +use function count; +use function current; +use function end; +use function is_string; +use function key; +use function min; +use function preg_split; +use function prev; +use function reset; +use function str_ends_with; +use function substr; +use SebastianBergmann\Diff\Output\DiffOutputBuilderInterface; + +final class Differ +{ + public const OLD = 0; + public const ADDED = 1; + public const REMOVED = 2; + public const DIFF_LINE_END_WARNING = 3; + public const NO_LINE_END_EOF_WARNING = 4; + private DiffOutputBuilderInterface $outputBuilder; + + public function __construct(DiffOutputBuilderInterface $outputBuilder) + { + $this->outputBuilder = $outputBuilder; + } + + public function diff(array|string $from, array|string $to, ?LongestCommonSubsequenceCalculator $lcs = null): string + { + $diff = $this->diffToArray($from, $to, $lcs); + + return $this->outputBuilder->getDiff($diff); + } + + public function diffToArray(array|string $from, array|string $to, ?LongestCommonSubsequenceCalculator $lcs = null): array + { + if (is_string($from)) { + $from = $this->splitStringByLines($from); + } + + if (is_string($to)) { + $to = $this->splitStringByLines($to); + } + + [$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, ["#Warning: Strings contain different line endings!\n", self::DIFF_LINE_END_WARNING]); + } + + return $diff; + } + + private function splitStringByLines(string $input): array + { + return preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + } + + private function selectLcsImplementation(array $from, array $to): LongestCommonSubsequenceCalculator + { + // 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; + } + + private function calculateEstimatedFootprint(array $from, array $to): float|int + { + $itemSize = PHP_INT_SIZE === 4 ? 76 : 144; + + return $itemSize * min(count($from), count($to)) ** 2; + } + + private function detectUnmatchedLineEndings(array $diff): bool + { + $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): string + { + if (!is_string($line)) { + return ''; + } + + $lc = substr($line, -1); + + if ("\r" === $lc) { + return "\r"; + } + + if ("\n" !== $lc) { + return ''; + } + + if (str_ends_with($line, "\r\n")) { + return "\r\n"; + } + + return "\n"; + } + + private static function getArrayDiffParted(array &$from, array &$to): array + { + $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/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/ConfigurationException.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/ConfigurationException.php new file mode 100644 index 000000000..b2abf0cbf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/ConfigurationException.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function gettype; +use function is_object; +use function sprintf; +use Exception; + +final class ConfigurationException extends InvalidArgumentException +{ + public function __construct( + string $option, + string $expected, + $value, + int $code = 0, + ?Exception $previous = null + ) { + parent::__construct( + sprintf( + 'Option "%s" must be %s, got "%s".', + $option, + $expected, + is_object($value) ? $value::class : (null === $value ? '' : gettype($value) . '#' . $value), + ), + $code, + $previous, + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/Exception.php new file mode 100644 index 000000000..e20d32036 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..846ac3fbd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Exception/InvalidArgumentException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Line.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Line.php new file mode 100644 index 000000000..4e708abb6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Line.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +final class Line +{ + public const ADDED = 1; + public const REMOVED = 2; + public const UNCHANGED = 3; + private int $type; + private string $content; + + public function __construct(int $type = self::UNCHANGED, string $content = '') + { + $this->type = $type; + $this->content = $content; + } + + public function content(): string + { + return $this->content; + } + + public function type(): int + { + return $this->type; + } + + public function isAdded(): bool + { + return $this->type === self::ADDED; + } + + public function isRemoved(): bool + { + return $this->type === self::REMOVED; + } + + public function isUnchanged(): bool + { + return $this->type === self::UNCHANGED; + } + + /** + * @deprecated + */ + public function getContent(): string + { + return $this->content; + } + + /** + * @deprecated + */ + public function getType(): int + { + return $this->type; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php new file mode 100644 index 000000000..dea8fe1cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/LongestCommonSubsequenceCalculator.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +interface LongestCommonSubsequenceCalculator +{ + /** + * Calculates the longest common subsequence of two arrays. + */ + public function calculate(array $from, array $to): array; +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 000000000..b9846c37e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/MemoryEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function array_fill; +use function array_merge; +use function array_reverse; +use function array_slice; +use function count; +use function in_array; +use function max; + +final class MemoryEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * @inheritDoc + */ + public function calculate(array $from, array $to): array + { + $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): array + { + $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 { + /** + * @noinspection PhpConditionCanBeReplacedWithMinMaxCallInspection + * + * We do not use max() here to avoid the function call overhead + */ + if ($current[$j] > $prev[$j + 1]) { + $current[$j + 1] = $current[$j]; + } else { + $current[$j + 1] = $prev[$j + 1]; + } + } + } + } + + return $current; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php new file mode 100644 index 000000000..6c706839f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/AbstractChunkOutputBuilder.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function count; + +abstract class AbstractChunkOutputBuilder implements DiffOutputBuilderInterface +{ + /** + * Takes input of the diff array and returns the common parts. + * Iterates through diff line by line. + */ + protected function getCommonChunks(array $diff, int $lineThreshold = 5): array + { + $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/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php new file mode 100644 index 000000000..fd6ce768a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOnlyOutputBuilder.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function fclose; +use function fopen; +use function fwrite; +use function str_ends_with; +use function stream_get_contents; +use function substr; +use SebastianBergmann\Diff\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 +{ + private string $header; + + public function __construct(string $header = "--- Original\n+++ New\n") + { + $this->header = $header; + } + + public function getDiff(array $diff): string + { + $buffer = fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + fwrite($buffer, $this->header); + + if (!str_ends_with($this->header, "\n")) { + 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 not-changed 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/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php new file mode 100644 index 000000000..0e18f9f2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/DiffOutputBuilderInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\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): string; +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php new file mode 100644 index 000000000..a2a73b679 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/StrictUnifiedDiffOutputBuilder.php @@ -0,0 +1,326 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function array_merge; +use function array_splice; +use function count; +use function fclose; +use function fopen; +use function fwrite; +use function is_bool; +use function is_int; +use function is_string; +use function max; +use function min; +use function sprintf; +use function stream_get_contents; +use function substr; +use SebastianBergmann\Diff\ConfigurationException; +use SebastianBergmann\Diff\Differ; + +/** + * Strict Unified diff output builder. + * + * Generates (strict) Unified diff's (unidiffs) with hunks. + */ +final class StrictUnifiedDiffOutputBuilder implements DiffOutputBuilderInterface +{ + private static array $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, + ]; + private bool $changed; + private bool $collapseRanges; + + /** + * @psalm-var positive-int + */ + private int $commonLineThreshold; + private string $header; + + /** + * @psalm-var positive-int + */ + private int $contextLines; + + 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']); + } + + $this->assertString($options, 'fromFile'); + $this->assertString($options, 'toFile'); + $this->assertStringOrNull($options, 'fromFileDate'); + $this->assertStringOrNull($options, 'toFileDate'); + + $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): string + { + 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): void + { + // 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 it has a trailing linebreak, else add a 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; + $i = 0; + + /** @var int $i */ + 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 were 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, + int $diffStartIndex, + int $diffEndIndex, + int $fromStart, + int $fromRange, + int $toStart, + int $toRange, + $output + ): void { + 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 + // } + } + } + + private function assertString(array $options, string $option): void + { + if (!is_string($options[$option])) { + throw new ConfigurationException($option, 'a string', $options[$option]); + } + } + + private function assertStringOrNull(array $options, string $option): void + { + if (null !== $options[$option] && !is_string($options[$option])) { + throw new ConfigurationException($option, 'a string or ', $options[$option]); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php new file mode 100644 index 000000000..683ab1b6d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Output/UnifiedDiffOutputBuilder.php @@ -0,0 +1,257 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff\Output; + +use function array_splice; +use function count; +use function fclose; +use function fopen; +use function fwrite; +use function max; +use function min; +use function str_ends_with; +use function stream_get_contents; +use function substr; +use SebastianBergmann\Diff\Differ; + +/** + * Builds a diff string representation in unified diff format in chunks. + */ +final class UnifiedDiffOutputBuilder extends AbstractChunkOutputBuilder +{ + private bool $collapseRanges = true; + private int $commonLineThreshold = 6; + + /** + * @psalm-var positive-int + */ + private int $contextLines = 3; + private string $header; + private bool $addLineNumbers; + + public function __construct(string $header = "--- Original\n+++ New\n", bool $addLineNumbers = false) + { + $this->header = $header; + $this->addLineNumbers = $addLineNumbers; + } + + public function getDiff(array $diff): string + { + $buffer = fopen('php://memory', 'r+b'); + + if ('' !== $this->header) { + fwrite($buffer, $this->header); + + if (!str_ends_with($this->header, "\n")) { + 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 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 '' !== $diff && "\n" !== $last && "\r" !== $last + ? $diff . "\n" + : $diff; + } + + private function writeDiffHunks($output, array $diff): void + { + // 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 it has trailing linebreak, else add a 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; + $i = 0; + + /** @var int $i */ + 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 were 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, + int $diffStartIndex, + int $diffEndIndex, + int $fromStart, + int $fromRange, + int $toStart, + int $toRange, + $output + ): void { + 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/.extlib/simplesamlphp/vendor/sebastian/diff/src/Parser.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Parser.php new file mode 100644 index 000000000..9293fc919 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/Parser.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function array_pop; +use function assert; +use function count; +use function max; +use function preg_match; +use function preg_split; + +/** + * Unified diff parser. + */ +final class Parser +{ + /** + * @return Diff[] + */ + public function parse(string $string): array + { + $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('#^---\h+"?(?P[^\\v\\t"]+)#', $lines[$i], $fromMatch) && + preg_match('#^\\+\\+\\+\\h+"?(?P[^\\v\\t"]+)#', $lines[$i + 1], $toMatch)) { + if ($diff !== null) { + $this->parseFileDiff($diff, $collected); + + $diffs[] = $diff; + $collected = []; + } + + assert(!empty($fromMatch['file'])); + assert(!empty($toMatch['file'])); + + $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): void + { + $chunks = []; + $chunk = null; + $diffLines = []; + + foreach ($lines as $line) { + if (preg_match('/^@@\s+-(?P\d+)(?:,\s*(?P\d+))?\s+\+(?P\d+)(?:,\s*(?P\d+))?\s+@@/', $line, $match, PREG_UNMATCHED_AS_NULL)) { + $chunk = new Chunk( + (int) $match['start'], + isset($match['startrange']) ? max(0, (int) $match['startrange']) : 1, + (int) $match['end'], + isset($match['endrange']) ? max(0, (int) $match['endrange']) : 1, + ); + + $chunks[] = $chunk; + $diffLines = []; + + continue; + } + + if (preg_match('/^(?P[+ -])?(?P.*)/', $line, $match)) { + $type = Line::UNCHANGED; + + if ($match['type'] === '+') { + $type = Line::ADDED; + } elseif ($match['type'] === '-') { + $type = Line::REMOVED; + } + + $diffLines[] = new Line($type, $match['line']); + + $chunk?->setLines($diffLines); + } + } + + $diff->setChunks($chunks); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php b/.extlib/simplesamlphp/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php new file mode 100644 index 000000000..93b762887 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/diff/src/TimeEfficientLongestCommonSubsequenceCalculator.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Diff; + +use function array_reverse; +use function count; +use function max; +use SplFixedArray; + +final class TimeEfficientLongestCommonSubsequenceCalculator implements LongestCommonSubsequenceCalculator +{ + /** + * @inheritDoc + */ + public function calculate(array $from, array $to): array + { + $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; + + // don't use max() to avoid function call overhead + $firstOrLast = $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0; + + if ($matrix[$o - 1] > $matrix[$o - $width]) { + if ($firstOrLast > $matrix[$o - 1]) { + $matrix[$o] = $firstOrLast; + } else { + $matrix[$o] = $matrix[$o - 1]; + } + } else { + if ($firstOrLast > $matrix[$o - $width]) { + $matrix[$o] = $firstOrLast; + } else { + $matrix[$o] = $matrix[$o - $width]; + } + } + } + } + + $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/.extlib/simplesamlphp/vendor/sebastian/environment/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/environment/ChangeLog.md new file mode 100644 index 000000000..d3f29e16b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/ChangeLog.md @@ -0,0 +1,207 @@ +# Changes in sebastianbergmann/environment + +All notable changes in `sebastianbergmann/environment` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [6.1.0] - 2024-03-23 + +### Added + +* [#72](https://github.com/sebastianbergmann/environment/pull/72): `Runtime::getRawBinary()` + +## [6.0.1] - 2023-04-11 + +### Fixed + +* [#68](https://github.com/sebastianbergmann/environment/pull/68): The Just-in-Time compiler is disabled when `opcache.jit_buffer_size` is set to `0` +* [#70](https://github.com/sebastianbergmann/environment/pull/70): The first `0` of `opcache.jit` only disables CPU-specific optimizations, not the Just-in-Time compiler itself + +## [6.0.0] - 2023-02-03 + +### Removed + +* Removed `SebastianBergmann\Environment\OperatingSystem::getFamily()` because this component is no longer supported on PHP versions that do not have `PHP_OS_FAMILY` +* Removed `SebastianBergmann\Environment\Runtime::isHHVM()` +* This component is no longer supported on PHP 7.3, PHP 7.4, and PHP 8.0 + +## [5.1.5] - 2022-MM-DD + +### Fixed + +* [#59](https://github.com/sebastianbergmann/environment/issues/59): Wrong usage of `stream_isatty()`, `fstat()` used without checking whether the function is available + +## [5.1.4] - 2022-04-03 + +### Fixed + +* [#63](https://github.com/sebastianbergmann/environment/pull/63): `Runtime::getCurrentSettings()` does not correctly process INI settings + +## [5.1.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [5.1.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [5.1.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [5.1.0] - 2020-04-14 + +### Added + +* `Runtime::performsJustInTimeCompilation()` returns `true` if PHP 8's JIT is active, `false` otherwise + +## [5.0.2] - 2020-03-31 + +### Fixed + +* [#55](https://github.com/sebastianbergmann/environment/issues/55): `stty` command is executed even if no tty is available + +## [5.0.1] - 2020-02-19 + +### Changed + +* `Runtime::getNameWithVersionAndCodeCoverageDriver()` now prioritizes PCOV over Xdebug when both extensions are loaded (just like php-code-coverage does) + +## [5.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +## [4.2.3] - 2019-11-20 + +### Changed + +* [#50](https://github.com/sebastianbergmann/environment/pull/50): Windows improvements to console capabilities + +### Fixed + +* [#49](https://github.com/sebastianbergmann/environment/issues/49): Detection how OpCache handles docblocks does not work correctly when PHPDBG is used + +## [4.2.2] - 2019-05-05 + +### Fixed + +* [#44](https://github.com/sebastianbergmann/environment/pull/44): `TypeError` in `Console::getNumberOfColumnsInteractive()` + +## [4.2.1] - 2019-04-25 + +### Fixed + +* Fixed an issue in `Runtime::getCurrentSettings()` + +## [4.2.0] - 2019-04-25 + +### Added + +* [#36](https://github.com/sebastianbergmann/environment/pull/36): `Runtime::getCurrentSettings()` + +## [4.1.0] - 2019-02-01 + +### Added + +* Implemented `Runtime::getNameWithVersionAndCodeCoverageDriver()` method +* [#34](https://github.com/sebastianbergmann/environment/pull/34): Support for PCOV extension + +## [4.0.2] - 2019-01-28 + +### Fixed + +* [#33](https://github.com/sebastianbergmann/environment/issues/33): `Runtime::discardsComments()` returns true too eagerly + +### Removed + +* Removed support for Zend Optimizer+ in `Runtime::discardsComments()` + +## [4.0.1] - 2018-11-25 + +### Fixed + +* [#31](https://github.com/sebastianbergmann/environment/issues/31): Regressions in `Console` class + +## [4.0.0] - 2018-10-23 [YANKED] + +### Fixed + +* [#25](https://github.com/sebastianbergmann/environment/pull/25): `Console::hasColorSupport()` does not work on Windows + +### Removed + +* This component is no longer supported on PHP 7.0 + +## [3.1.0] - 2017-07-01 + +### Added + +* [#21](https://github.com/sebastianbergmann/environment/issues/21): Equivalent of `PHP_OS_FAMILY` (for PHP < 7.2) + +## [3.0.4] - 2017-06-20 + +### Fixed + +* [#20](https://github.com/sebastianbergmann/environment/pull/20): PHP 7 mode of HHVM not forced + +## [3.0.3] - 2017-05-18 + +### Fixed + +* [#18](https://github.com/sebastianbergmann/environment/issues/18): `Uncaught TypeError: preg_match() expects parameter 2 to be string, null given` + +## [3.0.2] - 2017-04-21 + +### Fixed + +* [#17](https://github.com/sebastianbergmann/environment/issues/17): `Uncaught TypeError: trim() expects parameter 1 to be string, boolean given` + +## [3.0.1] - 2017-04-21 + +### Fixed + +* Fixed inverted logic in `Runtime::discardsComments()` + +## [3.0.0] - 2017-04-21 + +### Added + +* Implemented `Runtime::discardsComments()` for querying whether the PHP runtime discards annotations + +### Removed + +* This component is no longer supported on PHP 5.6 + +[6.1.0]: https://github.com/sebastianbergmann/environment/compare/6.0.1...6.1.0 +[6.0.1]: https://github.com/sebastianbergmann/environment/compare/6.0.0...6.0.1 +[6.0.0]: https://github.com/sebastianbergmann/environment/compare/5.1.5...6.0.0 +[5.1.5]: https://github.com/sebastianbergmann/environment/compare/5.1.4...5.1.5 +[5.1.4]: https://github.com/sebastianbergmann/environment/compare/5.1.3...5.1.4 +[5.1.3]: https://github.com/sebastianbergmann/environment/compare/5.1.2...5.1.3 +[5.1.2]: https://github.com/sebastianbergmann/environment/compare/5.1.1...5.1.2 +[5.1.1]: https://github.com/sebastianbergmann/environment/compare/5.1.0...5.1.1 +[5.1.0]: https://github.com/sebastianbergmann/environment/compare/5.0.2...5.1.0 +[5.0.2]: https://github.com/sebastianbergmann/environment/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/environment/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/environment/compare/4.2.3...5.0.0 +[4.2.3]: https://github.com/sebastianbergmann/environment/compare/4.2.2...4.2.3 +[4.2.2]: https://github.com/sebastianbergmann/environment/compare/4.2.1...4.2.2 +[4.2.1]: https://github.com/sebastianbergmann/environment/compare/4.2.0...4.2.1 +[4.2.0]: https://github.com/sebastianbergmann/environment/compare/4.1.0...4.2.0 +[4.1.0]: https://github.com/sebastianbergmann/environment/compare/4.0.2...4.1.0 +[4.0.2]: https://github.com/sebastianbergmann/environment/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/environment/compare/66691f8e2dc4641909166b275a9a4f45c0e89092...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/environment/compare/3.1.0...66691f8e2dc4641909166b275a9a4f45c0e89092 +[3.1.0]: https://github.com/sebastianbergmann/environment/compare/3.0...3.1.0 +[3.0.4]: https://github.com/sebastianbergmann/environment/compare/3.0.3...3.0.4 +[3.0.3]: https://github.com/sebastianbergmann/environment/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/environment/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/environment/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/environment/compare/2.0...3.0.0 + diff --git a/.extlib/simplesamlphp/vendor/sebastian/environment/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/environment/LICENSE new file mode 100644 index 000000000..aecdbc7ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2014-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/environment/README.md b/.extlib/simplesamlphp/vendor/sebastian/environment/README.md new file mode 100644 index 000000000..efe0a8646 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/environment/v/stable.png)](https://packagist.org/packages/sebastian/environment) +[![CI Status](https://github.com/sebastianbergmann/environment/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/environment/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/environment/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/environment) +[![codecov](https://codecov.io/gh/sebastianbergmann/environment/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/environment) + +# sebastian/environment + +This component provides functionality that helps writing PHP code that has runtime-specific (PHP / HHVM) execution paths. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/environment +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/environment +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/environment/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/environment/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/environment/composer.json b/.extlib/simplesamlphp/vendor/sebastian/environment/composer.json new file mode 100644 index 000000000..61e419323 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/composer.json @@ -0,0 +1,44 @@ +{ + "name": "sebastian/environment", + "description": "Provides functionality to handle HHVM/PHP environments", + "keywords": ["environment","hhvm","xdebug"], + "homepage": "https://github.com/sebastianbergmann/environment", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/environment/src/Console.php b/.extlib/simplesamlphp/vendor/sebastian/environment/src/Console.php new file mode 100644 index 000000000..4f5943c70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/src/Console.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Environment; + +use const DIRECTORY_SEPARATOR; +use const STDIN; +use const STDOUT; +use function defined; +use function fclose; +use function fstat; +use function function_exists; +use function getenv; +use function is_resource; +use function is_string; +use function posix_isatty; +use function preg_match; +use function proc_close; +use function proc_open; +use function sapi_windows_vt100_support; +use function shell_exec; +use function stream_get_contents; +use function stream_isatty; +use function trim; + +final class Console +{ + /** + * @var int + */ + public const STDIN = 0; + + /** + * @var int + */ + public const STDOUT = 1; + + /** + * @var int + */ + public const STDERR = 2; + + /** + * Returns true if STDOUT supports colorization. + * + * This code has been copied and adapted from + * Symfony\Component\Console\Output\StreamOutput. + */ + public function hasColorSupport(): bool + { + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + if ($this->isWindows()) { + // @codeCoverageIgnoreStart + return (defined('STDOUT') && function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support(STDOUT)) || + false !== getenv('ANSICON') || + 'ON' === getenv('ConEmuANSI') || + 'xterm' === getenv('TERM'); + // @codeCoverageIgnoreEnd + } + + if (!defined('STDOUT')) { + // @codeCoverageIgnoreStart + return false; + // @codeCoverageIgnoreEnd + } + + return $this->isInteractive(STDOUT); + } + + /** + * Returns the number of columns of the terminal. + * + * @codeCoverageIgnore + */ + public function getNumberOfColumns(): int + { + if (!$this->isInteractive(defined('STDIN') ? STDIN : self::STDIN)) { + return 80; + } + + if ($this->isWindows()) { + return $this->getNumberOfColumnsWindows(); + } + + return $this->getNumberOfColumnsInteractive(); + } + + /** + * Returns if the file descriptor is an interactive terminal or not. + * + * Normally, we want to use a resource as a parameter, yet sadly it's not always available, + * eg when running code in interactive console (`php -a`), STDIN/STDOUT/STDERR constants are not defined. + * + * @param int|resource $fileDescriptor + */ + public function isInteractive($fileDescriptor = self::STDOUT): bool + { + if (is_resource($fileDescriptor)) { + if (function_exists('stream_isatty') && @stream_isatty($fileDescriptor)) { + return true; + } + + if (function_exists('fstat')) { + $stat = @fstat(STDOUT); + + return $stat && 0o020000 === ($stat['mode'] & 0o170000); + } + + return false; + } + + return function_exists('posix_isatty') && @posix_isatty($fileDescriptor); + } + + private function isWindows(): bool + { + return DIRECTORY_SEPARATOR === '\\'; + } + + /** + * @codeCoverageIgnore + */ + private function getNumberOfColumnsInteractive(): int + { + if (function_exists('shell_exec') && preg_match('#\d+ (\d+)#', shell_exec('stty size') ?: '', $match) === 1) { + if ((int) $match[1] > 0) { + return (int) $match[1]; + } + } + + if (function_exists('shell_exec') && preg_match('#columns = (\d+);#', shell_exec('stty') ?: '', $match) === 1) { + if ((int) $match[1] > 0) { + return (int) $match[1]; + } + } + + return 80; + } + + /** + * @codeCoverageIgnore + */ + private function getNumberOfColumnsWindows(): int + { + $ansicon = getenv('ANSICON'); + $columns = 80; + + if (is_string($ansicon) && preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim($ansicon), $matches)) { + $columns = (int) $matches[1]; + } elseif (function_exists('proc_open')) { + $process = proc_open( + 'mode CON', + [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ], + $pipes, + null, + null, + ['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)) { + $columns = (int) $matches[2]; + } + } + } + + return $columns - 1; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/environment/src/Runtime.php b/.extlib/simplesamlphp/vendor/sebastian/environment/src/Runtime.php new file mode 100644 index 000000000..f9ec057ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/environment/src/Runtime.php @@ -0,0 +1,294 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Environment; + +use const PHP_BINARY; +use const PHP_BINDIR; +use const PHP_MAJOR_VERSION; +use const PHP_SAPI; +use const PHP_VERSION; +use function array_map; +use function array_merge; +use function escapeshellarg; +use function explode; +use function extension_loaded; +use function ini_get; +use function is_readable; +use function parse_ini_file; +use function php_ini_loaded_file; +use function php_ini_scanned_files; +use function phpversion; +use function sprintf; +use function strrpos; + +final class Runtime +{ + private static string $rawBinary; + private static bool $initialized = false; + + /** + * Returns true when Xdebug or PCOV is available or + * the runtime used is PHPDBG. + */ + public function canCollectCodeCoverage(): bool + { + return $this->hasXdebug() || $this->hasPCOV() || $this->hasPHPDBGCodeCoverage(); + } + + /** + * Returns true when Zend OPcache is loaded, enabled, + * and is configured to discard comments. + */ + public function discardsComments(): bool + { + if (!$this->isOpcacheActive()) { + return false; + } + + if (ini_get('opcache.save_comments') !== '0') { + return false; + } + + return true; + } + + /** + * Returns true when Zend OPcache is loaded, enabled, + * and is configured to perform just-in-time compilation. + */ + public function performsJustInTimeCompilation(): bool + { + if (PHP_MAJOR_VERSION < 8) { + return false; + } + + if (!$this->isOpcacheActive()) { + return false; + } + + if (ini_get('opcache.jit_buffer_size') === '0') { + return false; + } + + $jit = ini_get('opcache.jit'); + + if (($jit === 'disable') || ($jit === 'off')) { + return false; + } + + if (strrpos($jit, '0') === 3) { + return false; + } + + return true; + } + + /** + * Returns the raw path to the binary of the current runtime. + */ + public function getRawBinary(): string + { + if (self::$initialized) { + return self::$rawBinary; + } + + if (PHP_BINARY !== '') { + self::$rawBinary = PHP_BINARY; + self::$initialized = true; + + return self::$rawBinary; + } + + // @codeCoverageIgnoreStart + $possibleBinaryLocations = [ + PHP_BINDIR . '/php', + PHP_BINDIR . '/php-cli.exe', + PHP_BINDIR . '/php.exe', + ]; + + foreach ($possibleBinaryLocations as $binary) { + if (is_readable($binary)) { + self::$rawBinary = $binary; + self::$initialized = true; + + return self::$rawBinary; + } + } + + self::$rawBinary = 'php'; + self::$initialized = true; + + return self::$rawBinary; + // @codeCoverageIgnoreEnd + } + + /** + * Returns the escaped path to the binary of the current runtime. + */ + public function getBinary(): string + { + return escapeshellarg($this->getRawBinary()); + } + + public function getNameWithVersion(): string + { + return $this->getName() . ' ' . $this->getVersion(); + } + + public function getNameWithVersionAndCodeCoverageDriver(): string + { + if ($this->hasPCOV()) { + return sprintf( + '%s with PCOV %s', + $this->getNameWithVersion(), + phpversion('pcov'), + ); + } + + if ($this->hasXdebug()) { + return sprintf( + '%s with Xdebug %s', + $this->getNameWithVersion(), + phpversion('xdebug'), + ); + } + + return $this->getNameWithVersion(); + } + + public function getName(): string + { + if ($this->isPHPDBG()) { + // @codeCoverageIgnoreStart + return 'PHPDBG'; + // @codeCoverageIgnoreEnd + } + + return 'PHP'; + } + + public function getVendorUrl(): string + { + return 'https://www.php.net/'; + } + + public function getVersion(): string + { + return PHP_VERSION; + } + + /** + * Returns true when the runtime used is PHP and Xdebug is loaded. + */ + public function hasXdebug(): bool + { + return $this->isPHP() && extension_loaded('xdebug'); + } + + /** + * Returns true when the runtime used is PHP without the PHPDBG SAPI. + */ + public function isPHP(): bool + { + return !$this->isPHPDBG(); + } + + /** + * Returns true when the runtime used is PHP with the PHPDBG SAPI. + */ + public function isPHPDBG(): bool + { + return PHP_SAPI === 'phpdbg'; + } + + /** + * Returns true when the runtime used is PHP with the PHPDBG SAPI + * and the phpdbg_*_oplog() functions are available (PHP >= 7.0). + */ + public function hasPHPDBGCodeCoverage(): bool + { + return $this->isPHPDBG(); + } + + /** + * Returns true when the runtime used is PHP with PCOV loaded and enabled. + */ + public function hasPCOV(): bool + { + return $this->isPHP() && extension_loaded('pcov') && ini_get('pcov.enabled'); + } + + /** + * Parses the loaded php.ini file (if any) as well as all + * additional php.ini files from the additional ini dir for + * a list of all configuration settings loaded from files + * at startup. Then checks for each php.ini setting passed + * via the `$values` parameter whether this setting has + * been changed at runtime. Returns an array of strings + * where each string has the format `key=value` denoting + * the name of a changed php.ini setting with its new value. + * + * @return string[] + */ + public function getCurrentSettings(array $values): array + { + $diff = []; + $files = []; + + if ($file = php_ini_loaded_file()) { + $files[] = $file; + } + + if ($scanned = php_ini_scanned_files()) { + $files = array_merge( + $files, + array_map( + 'trim', + explode(",\n", $scanned), + ), + ); + } + + foreach ($files as $ini) { + $config = parse_ini_file($ini, true); + + foreach ($values as $value) { + $set = ini_get($value); + + if (empty($set)) { + continue; + } + + if ((!isset($config[$value]) || ($set !== $config[$value]))) { + $diff[$value] = sprintf('%s=%s', $value, $set); + } + } + } + + return $diff; + } + + private function isOpcacheActive(): bool + { + if (!extension_loaded('Zend OPcache')) { + return false; + } + + if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && ini_get('opcache.enable_cli') === '1') { + return true; + } + + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && ini_get('opcache.enable') === '1') { + return true; + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/exporter/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/exporter/ChangeLog.md new file mode 100644 index 000000000..f261d31c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/exporter/ChangeLog.md @@ -0,0 +1,117 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [5.1.2] - 2024-03-02 + +### Changed + +* Do not use implicitly nullable parameters + +## [5.1.1] - 2023-09-24 + +### Changed + +* [#52](https://github.com/sebastianbergmann/exporter/pull/52): Optimize export of large arrays and object graphs + +## [5.1.0] - 2023-09-18 + +### Changed + +* [#51](https://github.com/sebastianbergmann/exporter/pull/51): Export arrays using short array syntax + +## [5.0.1] - 2023-09-08 + +### Fixed + +* [#49](https://github.com/sebastianbergmann/exporter/issues/49): `Exporter::toArray()` changes `SplObjectStorage` index + +## [5.0.0] - 2023-02-03 + +### Changed + +* [#42](https://github.com/sebastianbergmann/exporter/pull/42): Improve export of enumerations + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [4.0.5] - 2022-09-14 + +### Fixed + +* [#47](https://github.com/sebastianbergmann/exporter/pull/47): Fix `float` export precision + +## [4.0.4] - 2021-11-11 + +### Changed + +* [#37](https://github.com/sebastianbergmann/exporter/pull/37): Improve export of closed resources + +## [4.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [4.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2 + +## [3.1.5] - 2022-09-14 + +### Fixed + +* [#47](https://github.com/sebastianbergmann/exporter/pull/47): Fix `float` export precision + +## [3.1.4] - 2021-11-11 + +### Changed + +* [#38](https://github.com/sebastianbergmann/exporter/pull/38): Improve export of closed resources + +## [3.1.3] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.0` to `>=7.0` + +## [3.1.2] - 2019-09-14 + +### Fixed + +* [#29](https://github.com/sebastianbergmann/exporter/pull/29): Second parameter for `str_repeat()` must be an integer + +### Removed + +* Remove HHVM-specific code that is no longer needed + +[5.1.2]: https://github.com/sebastianbergmann/exporter/compare/5.1.1...5.1.2 +[5.1.1]: https://github.com/sebastianbergmann/exporter/compare/5.1.0...5.1.1 +[5.1.0]: https://github.com/sebastianbergmann/exporter/compare/5.0.1...5.1.0 +[5.0.1]: https://github.com/sebastianbergmann/exporter/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/exporter/compare/4.0.5...5.0.0 +[4.0.5]: https://github.com/sebastianbergmann/exporter/compare/4.0.4...4.0.5 +[4.0.4]: https://github.com/sebastianbergmann/exporter/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/exporter/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/exporter/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/exporter/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/exporter/compare/3.1.2...4.0.0 +[3.1.5]: https://github.com/sebastianbergmann/exporter/compare/3.1.4...3.1.5 +[3.1.4]: https://github.com/sebastianbergmann/exporter/compare/3.1.3...3.1.4 +[3.1.3]: https://github.com/sebastianbergmann/exporter/compare/3.1.2...3.1.3 +[3.1.2]: https://github.com/sebastianbergmann/exporter/compare/3.1.1...3.1.2 diff --git a/.extlib/simplesamlphp/vendor/sebastian/exporter/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/exporter/LICENSE new file mode 100644 index 000000000..5b4705a48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/exporter/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2002-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/exporter/README.md b/.extlib/simplesamlphp/vendor/sebastian/exporter/README.md new file mode 100644 index 000000000..ea62a31dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/exporter/README.md @@ -0,0 +1,176 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/exporter/v/stable.png)](https://packagist.org/packages/sebastian/exporter) +[![CI Status](https://github.com/sebastianbergmann/exporter/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/exporter/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/exporter/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/exporter) +[![codecov](https://codecov.io/gh/sebastianbergmann/exporter/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/exporter) + +# sebastian/exporter + +This component provides the functionality to export PHP variables for visualization. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/exporter +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/exporter +``` + +## Usage + +Exporting: + +```php + '' + 'string' => '' + 'code' => 0 + 'file' => '/home/sebastianbergmann/test.php' + 'line' => 34 + 'previous' => null +) +*/ + +print $exporter->export(new Exception); +``` + +## Data Types + +Exporting simple types: + +```php +export(46); + +// 4.0 +print $exporter->export(4.0); + +// 'hello, world!' +print $exporter->export('hello, world!'); + +// false +print $exporter->export(false); + +// NAN +print $exporter->export(acos(8)); + +// -INF +print $exporter->export(log(0)); + +// null +print $exporter->export(null); + +// resource(13) of type (stream) +print $exporter->export(fopen('php://stderr', 'w')); + +// Binary String: 0x000102030405 +print $exporter->export(chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5)); +``` + +Exporting complex types: + +```php + Array &1 ( + 0 => 1 + 1 => 2 + 2 => 3 + ) + 1 => Array &2 ( + 0 => '' + 1 => 0 + 2 => false + ) +) +*/ + +print $exporter->export(array(array(1,2,3), array("",0,FALSE))); + +/* +Array &0 ( + 'self' => Array &1 ( + 'self' => Array &1 + ) +) +*/ + +$array = array(); +$array['self'] = &$array; +print $exporter->export($array); + +/* +stdClass Object &0000000003a66dcc0000000025e723e2 ( + 'self' => stdClass Object &0000000003a66dcc0000000025e723e2 +) +*/ + +$obj = new stdClass(); +$obj->self = $obj; +print $exporter->export($obj); +``` + +Compact exports: + +```php +shortenedExport(array()); + +// Array (...) +print $exporter->shortenedExport(array(1,2,3,4,5)); + +// stdClass Object () +print $exporter->shortenedExport(new stdClass); + +// Exception Object (...) +print $exporter->shortenedExport(new Exception); + +// this\nis\na\nsuper\nlong\nstring\nt...\nspace +print $exporter->shortenedExport( +<<=8.1", + "ext-mbstring": "*", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + } +} + diff --git a/.extlib/simplesamlphp/vendor/sebastian/exporter/src/Exporter.php b/.extlib/simplesamlphp/vendor/sebastian/exporter/src/Exporter.php new file mode 100644 index 000000000..057707595 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/exporter/src/Exporter.php @@ -0,0 +1,339 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Exporter; + +use function bin2hex; +use function count; +use function get_resource_type; +use function gettype; +use function implode; +use function ini_get; +use function ini_set; +use function is_array; +use function is_float; +use function is_object; +use function is_resource; +use function is_string; +use function mb_strlen; +use function mb_substr; +use function preg_match; +use function spl_object_id; +use function sprintf; +use function str_repeat; +use function str_replace; +use function var_export; +use BackedEnum; +use SebastianBergmann\RecursionContext\Context; +use SplObjectStorage; +use UnitEnum; + +final class Exporter +{ + /** + * Exports a value as a string. + * + * The output of this method is similar to the output of print_r(), but + * improved in various aspects: + * + * - NULL is rendered as "null" (instead of "") + * - TRUE is rendered as "true" (instead of "1") + * - FALSE is rendered as "false" (instead of "") + * - Strings are always quoted with single quotes + * - Carriage returns and newlines are normalized to \n + * - Recursion and repeated rendering is treated properly + */ + public function export(mixed $value, int $indentation = 0): string + { + return $this->recursiveExport($value, $indentation); + } + + public function shortenedRecursiveExport(array &$data, ?Context $context = null): string + { + $result = []; + $exporter = new self; + + if (!$context) { + $context = new Context; + } + + $array = $data; + + /* @noinspection UnusedFunctionResultInspection */ + $context->add($data); + + foreach ($array as $key => $value) { + if (is_array($value)) { + if ($context->contains($data[$key]) !== false) { + $result[] = '*RECURSION*'; + } else { + $result[] = sprintf('[%s]', $this->shortenedRecursiveExport($data[$key], $context)); + } + } else { + $result[] = $exporter->shortenedExport($value); + } + } + + return implode(', ', $result); + } + + /** + * Exports a value into a single-line string. + * + * The output of this method is similar to the output of + * SebastianBergmann\Exporter\Exporter::export(). + * + * Newlines are replaced by the visible string '\n'. + * Contents of arrays and objects (if any) are replaced by '...'. + */ + public function shortenedExport(mixed $value): string + { + if (is_string($value)) { + $string = str_replace("\n", '', $this->export($value)); + + if (mb_strlen($string) > 40) { + return mb_substr($string, 0, 30) . '...' . mb_substr($string, -7); + } + + return $string; + } + + if ($value instanceof BackedEnum) { + return sprintf( + '%s Enum (%s, %s)', + $value::class, + $value->name, + $this->export($value->value), + ); + } + + if ($value instanceof UnitEnum) { + return sprintf( + '%s Enum (%s)', + $value::class, + $value->name, + ); + } + + if (is_object($value)) { + return sprintf( + '%s Object (%s)', + $value::class, + count($this->toArray($value)) > 0 ? '...' : '', + ); + } + + if (is_array($value)) { + return sprintf( + '[%s]', + count($value) > 0 ? '...' : '', + ); + } + + return $this->export($value); + } + + /** + * Converts an object to an array containing all of its private, protected + * and public properties. + */ + public function toArray(mixed $value): array + { + if (!is_object($value)) { + return (array) $value; + } + + $array = []; + + foreach ((array) $value as $key => $val) { + // Exception traces commonly reference hundreds to thousands of + // objects currently loaded in memory. Including them in the result + // has a severe negative performance impact. + if ("\0Error\0trace" === $key || "\0Exception\0trace" === $key) { + continue; + } + + // properties are transformed to keys in the following way: + // private $propertyName => "\0ClassName\0propertyName" + // protected $propertyName => "\0*\0propertyName" + // public $propertyName => "propertyName" + if (preg_match('/^\0.+\0(.+)$/', (string) $key, $matches)) { + $key = $matches[1]; + } + + // See https://github.com/php/php-src/commit/5721132 + if ($key === "\0gcdata") { + continue; + } + + $array[$key] = $val; + } + + // Some internal classes like SplObjectStorage do not work with the + // above (fast) mechanism nor with reflection in Zend. + // Format the output similarly to print_r() in this case + if ($value instanceof SplObjectStorage) { + foreach ($value as $_value) { + $array['Object #' . spl_object_id($_value)] = [ + 'obj' => $_value, + 'inf' => $value->getInfo(), + ]; + } + + $value->rewind(); + } + + return $array; + } + + private function recursiveExport(mixed &$value, int $indentation, ?Context $processed = null): string + { + if ($value === null) { + return 'null'; + } + + if ($value === true) { + return 'true'; + } + + if ($value === false) { + return 'false'; + } + + if (is_float($value)) { + $precisionBackup = ini_get('precision'); + + ini_set('precision', '-1'); + + try { + $valueStr = (string) $value; + + if ((string) (int) $value === $valueStr) { + return $valueStr . '.0'; + } + + return $valueStr; + } finally { + ini_set('precision', $precisionBackup); + } + } + + if (gettype($value) === 'resource (closed)') { + return 'resource (closed)'; + } + + if (is_resource($value)) { + return sprintf( + 'resource(%d) of type (%s)', + $value, + get_resource_type($value), + ); + } + + if ($value instanceof BackedEnum) { + return sprintf( + '%s Enum #%d (%s, %s)', + $value::class, + spl_object_id($value), + $value->name, + $this->export($value->value, $indentation), + ); + } + + if ($value instanceof UnitEnum) { + return sprintf( + '%s Enum #%d (%s)', + $value::class, + spl_object_id($value), + $value->name, + ); + } + + if (is_string($value)) { + // Match for most non-printable chars somewhat taking multibyte chars into account + if (preg_match('/[^\x09-\x0d\x1b\x20-\xff]/', $value)) { + return 'Binary String: 0x' . bin2hex($value); + } + + return "'" . + str_replace( + '', + "\n", + str_replace( + ["\r\n", "\n\r", "\r", "\n"], + ['\r\n', '\n\r', '\r', '\n'], + $value, + ), + ) . + "'"; + } + + $whitespace = str_repeat(' ', 4 * $indentation); + + if (!$processed) { + $processed = new Context; + } + + if (is_array($value)) { + if (($key = $processed->contains($value)) !== false) { + return 'Array &' . $key; + } + + $array = $value; + $key = $processed->add($value); + $values = ''; + + if (count($array) > 0) { + foreach ($array as $k => $v) { + $values .= + $whitespace + . ' ' . + $this->recursiveExport($k, $indentation) + . ' => ' . + $this->recursiveExport($value[$k], $indentation + 1, $processed) + . ",\n"; + } + + $values = "\n" . $values . $whitespace; + } + + return 'Array &' . (string) $key . ' [' . $values . ']'; + } + + if (is_object($value)) { + $class = $value::class; + + if ($processed->contains($value)) { + return $class . ' Object #' . spl_object_id($value); + } + + $processed->add($value); + $values = ''; + $array = $this->toArray($value); + + if (count($array) > 0) { + foreach ($array as $k => $v) { + $values .= + $whitespace + . ' ' . + $this->recursiveExport($k, $indentation) + . ' => ' . + $this->recursiveExport($v, $indentation + 1, $processed) + . ",\n"; + } + + $values = "\n" . $values . $whitespace; + } + + return $class . ' Object #' . spl_object_id($value) . ' (' . $values . ')'; + } + + return var_export($value, true); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/global-state/ChangeLog.md new file mode 100644 index 000000000..03f254709 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/ChangeLog.md @@ -0,0 +1,108 @@ +# Changes in sebastian/global-state + +All notable changes in `sebastian/global-state` are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [6.0.2] - 2024-03-02 + +### Changed + +* Do not use implicitly nullable parameters + +## [6.0.1] - 2023-07-19 + +### Changed + +* Changed usage of `ReflectionProperty::setValue()` to be compatible with PHP 8.3 + +## [6.0.0] - 2023-02-03 + +### Changed + +* Renamed `SebastianBergmann\GlobalState\ExcludeList::addStaticAttribute()` to `SebastianBergmann\GlobalState\ExcludeList::addStaticProperty()` +* Renamed `SebastianBergmann\GlobalState\ExcludeList::isStaticAttributeExcluded()` to `SebastianBergmann\GlobalState\ExcludeList::isStaticPropertyExcluded()` +* Renamed `SebastianBergmann\GlobalState\Restorer::restoreStaticAttributes()` to `SebastianBergmann\GlobalState\Restorer::restoreStaticProperties()` +* Renamed `SebastianBergmann\GlobalState\Snapshot::staticAttributes()` to `SebastianBergmann\GlobalState\Snapshot::staticProperties()` + +### Removed + +* Removed `SebastianBergmann\GlobalState\Restorer::restoreFunctions()` +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [5.0.5] - 2022-02-14 + +### Fixed + +* [#34](https://github.com/sebastianbergmann/global-state/pull/34): Uninitialised typed static properties are not handled correctly + +## [5.0.4] - 2022-02-10 + +### Fixed + +* The `$includeTraits` parameter of `SebastianBergmann\GlobalState\Snapshot::__construct()` is not respected + +## [5.0.3] - 2021-06-11 + +### Changed + +* `SebastianBergmann\GlobalState\CodeExporter::globalVariables()` now generates code that is compatible with PHP 8.1 + +## [5.0.2] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\GlobalState\Exception` now correctly extends `\Throwable` + +## [5.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [5.0.0] - 2020-08-07 + +### Changed + +* The `SebastianBergmann\GlobalState\Blacklist` class has been renamed to `SebastianBergmann\GlobalState\ExcludeList` + +## [4.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.2 + +## [3.0.2] - 2022-02-10 + +### Fixed + +* The `$includeTraits` parameter of `SebastianBergmann\GlobalState\Snapshot::__construct()` is not respected + +## [3.0.1] - 2020-11-30 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.2` to `>=7.2` + +## [3.0.0] - 2019-02-01 + +### Changed + +* `Snapshot::canBeSerialized()` now recursively checks arrays and object graphs for variables that cannot be serialized + +### Removed + +* This component is no longer supported on PHP 7.0 and PHP 7.1 + +[6.0.2]: https://github.com/sebastianbergmann/global-state/compare/6.0.1...6.0.2 +[6.0.1]: https://github.com/sebastianbergmann/global-state/compare/6.0.0...6.0.1 +[6.0.0]: https://github.com/sebastianbergmann/global-state/compare/5.0.5...6.0.0 +[5.0.5]: https://github.com/sebastianbergmann/global-state/compare/5.0.4...5.0.5 +[5.0.4]: https://github.com/sebastianbergmann/global-state/compare/5.0.3...5.0.4 +[5.0.3]: https://github.com/sebastianbergmann/global-state/compare/5.0.2...5.0.3 +[5.0.2]: https://github.com/sebastianbergmann/global-state/compare/5.0.1...5.0.2 +[5.0.1]: https://github.com/sebastianbergmann/global-state/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/sebastianbergmann/global-state/compare/4.0.0...5.0.0 +[4.0.0]: https://github.com/sebastianbergmann/global-state/compare/3.0.2...4.0.0 +[3.0.2]: https://github.com/sebastianbergmann/phpunit/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/phpunit/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/phpunit/compare/2.0.0...3.0.0 + diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/global-state/LICENSE new file mode 100644 index 000000000..bdb57ec66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2001-2024, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/global-state/README.md b/.extlib/simplesamlphp/vendor/sebastian/global-state/README.md new file mode 100644 index 000000000..d4bd4cf5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/global-state/v/stable.png)](https://packagist.org/packages/sebastian/global-state) +[![CI Status](https://github.com/sebastianbergmann/global-state/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/global-state/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/global-state/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/global-state) +[![codecov](https://codecov.io/gh/sebastianbergmann/global-state/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/global-state) + +# sebastian/global-state + +Snapshotting of global state, factored out of PHPUnit into a stand-alone component. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/global-state +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/global-state +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/global-state/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/composer.json b/.extlib/simplesamlphp/vendor/sebastian/global-state/composer.json new file mode 100644 index 000000000..d38d64d26 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/composer.json @@ -0,0 +1,52 @@ +{ + "name": "sebastian/global-state", + "description": "Snapshotting of global state", + "keywords": ["global state"], + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy" + }, + "prefer-stable": true, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ], + "files": [ + "tests/_fixture/SnapshotFunctions.php" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/src/CodeExporter.php b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/CodeExporter.php new file mode 100644 index 000000000..6b720811f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/CodeExporter.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use const PHP_EOL; +use function is_array; +use function is_scalar; +use function serialize; +use function sprintf; +use function var_export; + +final class CodeExporter +{ + public function constants(Snapshot $snapshot): string + { + $result = ''; + + foreach ($snapshot->constants() as $name => $value) { + $result .= sprintf( + 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", + $name, + $name, + $this->exportVariable($value), + ); + } + + return $result; + } + + public function globalVariables(Snapshot $snapshot): string + { + $result = <<<'EOT' +call_user_func( + function () + { + foreach (array_keys($GLOBALS) as $key) { + unset($GLOBALS[$key]); + } + } +); + + +EOT; + + foreach ($snapshot->globalVariables() as $name => $value) { + $result .= sprintf( + '$GLOBALS[%s] = %s;' . PHP_EOL, + $this->exportVariable($name), + $this->exportVariable($value), + ); + } + + return $result; + } + + public function iniSettings(Snapshot $snapshot): string + { + $result = ''; + + foreach ($snapshot->iniSettings() as $key => $value) { + $result .= sprintf( + '@ini_set(%s, %s);' . "\n", + $this->exportVariable($key), + $this->exportVariable($value), + ); + } + + return $result; + } + + private function exportVariable(mixed $variable): string + { + if (is_scalar($variable) || null === $variable || + (is_array($variable) && $this->arrayOnlyContainsScalars($variable))) { + return var_export($variable, true); + } + + return 'unserialize(' . var_export(serialize($variable), true) . ')'; + } + + private function arrayOnlyContainsScalars(array $array): bool + { + $result = true; + + foreach ($array as $element) { + if (is_array($element)) { + $result = $this->arrayOnlyContainsScalars($element); + } elseif (!is_scalar($element) && null !== $element) { + $result = false; + } + + if ($result === false) { + break; + } + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/src/ExcludeList.php b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/ExcludeList.php new file mode 100644 index 000000000..3754e8146 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/ExcludeList.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use function in_array; +use function str_starts_with; +use ReflectionClass; + +final class ExcludeList +{ + private array $globalVariables = []; + private array $classes = []; + private array $classNamePrefixes = []; + private array $parentClasses = []; + private array $interfaces = []; + private array $staticProperties = []; + + public function addGlobalVariable(string $variableName): void + { + $this->globalVariables[$variableName] = true; + } + + public function addClass(string $className): void + { + $this->classes[] = $className; + } + + public function addSubclassesOf(string $className): void + { + $this->parentClasses[] = $className; + } + + public function addImplementorsOf(string $interfaceName): void + { + $this->interfaces[] = $interfaceName; + } + + public function addClassNamePrefix(string $classNamePrefix): void + { + $this->classNamePrefixes[] = $classNamePrefix; + } + + public function addStaticProperty(string $className, string $propertyName): void + { + if (!isset($this->staticProperties[$className])) { + $this->staticProperties[$className] = []; + } + + $this->staticProperties[$className][$propertyName] = true; + } + + public function isGlobalVariableExcluded(string $variableName): bool + { + return isset($this->globalVariables[$variableName]); + } + + /** + * @psalm-param class-string $className + */ + public function isStaticPropertyExcluded(string $className, string $propertyName): bool + { + if (in_array($className, $this->classes, true)) { + return true; + } + + foreach ($this->classNamePrefixes as $prefix) { + if (str_starts_with($className, $prefix)) { + return true; + } + } + + $class = new ReflectionClass($className); + + foreach ($this->parentClasses as $type) { + if ($class->isSubclassOf($type)) { + return true; + } + } + + foreach ($this->interfaces as $type) { + if ($class->implementsInterface($type)) { + return true; + } + } + + return isset($this->staticProperties[$className][$propertyName]); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/src/Restorer.php b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/Restorer.php new file mode 100644 index 000000000..d84e155e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/Restorer.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use function array_diff; +use function array_key_exists; +use function array_keys; +use function array_merge; +use function in_array; +use function is_array; +use ReflectionClass; +use ReflectionProperty; + +final class Restorer +{ + public function restoreGlobalVariables(Snapshot $snapshot): void + { + $superGlobalArrays = $snapshot->superGlobalArrays(); + + foreach ($superGlobalArrays as $superGlobalArray) { + $this->restoreSuperGlobalArray($snapshot, $superGlobalArray); + } + + $globalVariables = $snapshot->globalVariables(); + + foreach (array_keys($GLOBALS) as $key) { + if ($key !== 'GLOBALS' && + !in_array($key, $superGlobalArrays, true) && + !$snapshot->excludeList()->isGlobalVariableExcluded($key)) { + if (array_key_exists($key, $globalVariables)) { + $GLOBALS[$key] = $globalVariables[$key]; + } else { + unset($GLOBALS[$key]); + } + } + } + } + + public function restoreStaticProperties(Snapshot $snapshot): void + { + $current = new Snapshot($snapshot->excludeList(), false, false, false, false, true, false, false, false, false); + $newClasses = array_diff($current->classes(), $snapshot->classes()); + + unset($current); + + foreach ($snapshot->staticProperties() as $className => $staticProperties) { + foreach ($staticProperties as $name => $value) { + $reflector = new ReflectionProperty($className, $name); + $reflector->setValue(null, $value); + } + } + + foreach ($newClasses as $className) { + $class = new ReflectionClass($className); + $defaults = $class->getDefaultProperties(); + + foreach ($class->getProperties() as $property) { + if (!$property->isStatic()) { + continue; + } + + $name = $property->getName(); + + if ($snapshot->excludeList()->isStaticPropertyExcluded($className, $name)) { + continue; + } + + if (!isset($defaults[$name])) { + continue; + } + + $property->setValue(null, $defaults[$name]); + } + } + } + + private function restoreSuperGlobalArray(Snapshot $snapshot, string $superGlobalArray): void + { + $superGlobalVariables = $snapshot->superGlobalVariables(); + + if (isset($GLOBALS[$superGlobalArray], $superGlobalVariables[$superGlobalArray]) && + is_array($GLOBALS[$superGlobalArray])) { + $keys = array_keys( + array_merge( + $GLOBALS[$superGlobalArray], + $superGlobalVariables[$superGlobalArray], + ), + ); + + foreach ($keys as $key) { + if (isset($superGlobalVariables[$superGlobalArray][$key])) { + $GLOBALS[$superGlobalArray][$key] = $superGlobalVariables[$superGlobalArray][$key]; + } else { + unset($GLOBALS[$superGlobalArray][$key]); + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/src/Snapshot.php b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/Snapshot.php new file mode 100644 index 000000000..310c8566e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/Snapshot.php @@ -0,0 +1,371 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use function array_keys; +use function array_merge; +use function array_reverse; +use function assert; +use function func_get_args; +use function get_declared_classes; +use function get_declared_interfaces; +use function get_declared_traits; +use function get_defined_constants; +use function get_defined_functions; +use function get_included_files; +use function in_array; +use function ini_get_all; +use function is_array; +use function is_object; +use function is_resource; +use function is_scalar; +use function serialize; +use function unserialize; +use ReflectionClass; +use SebastianBergmann\ObjectReflector\ObjectReflector; +use SebastianBergmann\RecursionContext\Context; +use Throwable; + +/** + * A snapshot of global state. + */ +class Snapshot +{ + private ExcludeList $excludeList; + private array $globalVariables = []; + private array $superGlobalArrays = []; + private array $superGlobalVariables = []; + private array $staticProperties = []; + private array $iniSettings = []; + private array $includedFiles = []; + private array $constants = []; + private array $functions = []; + private array $interfaces = []; + private array $classes = []; + private array $traits = []; + + public function __construct(?ExcludeList $excludeList = null, bool $includeGlobalVariables = true, bool $includeStaticProperties = true, bool $includeConstants = true, bool $includeFunctions = true, bool $includeClasses = true, bool $includeInterfaces = true, bool $includeTraits = true, bool $includeIniSettings = true, bool $includeIncludedFiles = true) + { + $this->excludeList = $excludeList ?: new ExcludeList; + + if ($includeConstants) { + $this->snapshotConstants(); + } + + if ($includeFunctions) { + $this->snapshotFunctions(); + } + + if ($includeClasses || $includeStaticProperties) { + $this->snapshotClasses(); + } + + if ($includeInterfaces) { + $this->snapshotInterfaces(); + } + + if ($includeGlobalVariables) { + $this->setupSuperGlobalArrays(); + $this->snapshotGlobals(); + } + + if ($includeStaticProperties) { + $this->snapshotStaticProperties(); + } + + if ($includeIniSettings) { + $this->iniSettings = ini_get_all(null, false); + } + + if ($includeIncludedFiles) { + $this->includedFiles = get_included_files(); + } + + if ($includeTraits) { + $this->traits = get_declared_traits(); + } + } + + public function excludeList(): ExcludeList + { + return $this->excludeList; + } + + public function globalVariables(): array + { + return $this->globalVariables; + } + + public function superGlobalVariables(): array + { + return $this->superGlobalVariables; + } + + public function superGlobalArrays(): array + { + return $this->superGlobalArrays; + } + + public function staticProperties(): array + { + return $this->staticProperties; + } + + public function iniSettings(): array + { + return $this->iniSettings; + } + + public function includedFiles(): array + { + return $this->includedFiles; + } + + public function constants(): array + { + return $this->constants; + } + + public function functions(): array + { + return $this->functions; + } + + public function interfaces(): array + { + return $this->interfaces; + } + + public function classes(): array + { + return $this->classes; + } + + public function traits(): array + { + return $this->traits; + } + + private function snapshotConstants(): void + { + $constants = get_defined_constants(true); + + if (isset($constants['user'])) { + $this->constants = $constants['user']; + } + } + + private function snapshotFunctions(): void + { + $functions = get_defined_functions(); + + $this->functions = $functions['user']; + } + + private function snapshotClasses(): void + { + foreach (array_reverse(get_declared_classes()) as $className) { + $class = new ReflectionClass($className); + + if (!$class->isUserDefined()) { + break; + } + + $this->classes[] = $className; + } + + $this->classes = array_reverse($this->classes); + } + + private function snapshotInterfaces(): void + { + foreach (array_reverse(get_declared_interfaces()) as $interfaceName) { + $class = new ReflectionClass($interfaceName); + + if (!$class->isUserDefined()) { + break; + } + + $this->interfaces[] = $interfaceName; + } + + $this->interfaces = array_reverse($this->interfaces); + } + + private function snapshotGlobals(): void + { + $superGlobalArrays = $this->superGlobalArrays(); + + foreach ($superGlobalArrays as $superGlobalArray) { + $this->snapshotSuperGlobalArray($superGlobalArray); + } + + foreach (array_keys($GLOBALS) as $key) { + if ($key !== 'GLOBALS' && + !in_array($key, $superGlobalArrays, true) && + $this->canBeSerialized($GLOBALS[$key]) && + !$this->excludeList->isGlobalVariableExcluded($key)) { + /* @noinspection UnserializeExploitsInspection */ + $this->globalVariables[$key] = unserialize(serialize($GLOBALS[$key])); + } + } + } + + private function snapshotSuperGlobalArray(string $superGlobalArray): void + { + $this->superGlobalVariables[$superGlobalArray] = []; + + if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) { + foreach ($GLOBALS[$superGlobalArray] as $key => $value) { + /* @noinspection UnserializeExploitsInspection */ + $this->superGlobalVariables[$superGlobalArray][$key] = unserialize(serialize($value)); + } + } + } + + private function snapshotStaticProperties(): void + { + foreach ($this->classes as $className) { + $class = new ReflectionClass($className); + $snapshot = []; + + foreach ($class->getProperties() as $property) { + if ($property->isStatic()) { + $name = $property->getName(); + + if ($this->excludeList->isStaticPropertyExcluded($className, $name)) { + continue; + } + + if (!$property->isInitialized()) { + continue; + } + + $value = $property->getValue(); + + if ($this->canBeSerialized($value)) { + /* @noinspection UnserializeExploitsInspection */ + $snapshot[$name] = unserialize(serialize($value)); + } + } + } + + if (!empty($snapshot)) { + $this->staticProperties[$className] = $snapshot; + } + } + } + + private function setupSuperGlobalArrays(): void + { + $this->superGlobalArrays = [ + '_ENV', + '_POST', + '_GET', + '_COOKIE', + '_SERVER', + '_FILES', + '_REQUEST', + ]; + } + + private function canBeSerialized(mixed $variable): bool + { + if (is_scalar($variable) || $variable === null) { + return true; + } + + if (is_resource($variable)) { + return false; + } + + foreach ($this->enumerateObjectsAndResources($variable) as $value) { + if (is_resource($value)) { + return false; + } + + if (is_object($value)) { + $class = new ReflectionClass($value); + + if ($class->isAnonymous()) { + return false; + } + + try { + @serialize($value); + } catch (Throwable $t) { + return false; + } + } + } + + return true; + } + + private function enumerateObjectsAndResources(mixed $variable): array + { + if (isset(func_get_args()[1])) { + $processed = func_get_args()[1]; + } else { + $processed = new Context; + } + + assert($processed instanceof Context); + + $result = []; + + if ($processed->contains($variable)) { + return $result; + } + + $array = $variable; + + /* @noinspection UnusedFunctionResultInspection */ + $processed->add($variable); + + if (is_array($variable)) { + foreach ($array as $element) { + if (!is_array($element) && !is_object($element) && !is_resource($element)) { + continue; + } + + if (!is_resource($element)) { + /** @noinspection SlowArrayOperationsInLoopInspection */ + $result = array_merge( + $result, + $this->enumerateObjectsAndResources($element, $processed), + ); + } else { + $result[] = $element; + } + } + } else { + $result[] = $variable; + + foreach ((new ObjectReflector)->getProperties($variable) as $value) { + if (!is_array($value) && !is_object($value) && !is_resource($value)) { + continue; + } + + if (!is_resource($value)) { + /** @noinspection SlowArrayOperationsInLoopInspection */ + $result = array_merge( + $result, + $this->enumerateObjectsAndResources($value, $processed), + ); + } else { + $result[] = $value; + } + } + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/Exception.php new file mode 100644 index 000000000..94432008e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/RuntimeException.php b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/RuntimeException.php new file mode 100644 index 000000000..79f02a114 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/global-state/src/exceptions/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\GlobalState; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/ChangeLog.md new file mode 100644 index 000000000..27db58051 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/ChangeLog.md @@ -0,0 +1,55 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [2.0.2] - 2023-12-21 + +### Changed + +* This component is now compatible with `nikic/php-parser` 5.0 + +## [2.0.1] - 2023-08-31 + +### Changed + +* Improved type information + +## [2.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [1.0.3] - 2020-11-28 + +### Fixed + +* Files that do not contain a newline were not handled correctly + +### Changed + +* A line of code is no longer considered to be a Logical Line of Code if it does not contain an `Expr` node + +## [1.0.2] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\LinesOfCode\Exception` now correctly extends `\Throwable` + +## [1.0.1] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [1.0.0] - 2020-07-22 + +* Initial release + +[2.0.2]: https://github.com/sebastianbergmann/lines-of-code/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/lines-of-code/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.3...2.0.0 +[1.0.3]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.2...1.0.3 +[1.0.2]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.1...1.0.2 +[1.0.1]: https://github.com/sebastianbergmann/lines-of-code/compare/1.0.0...1.0.1 +[1.0.0]: https://github.com/sebastianbergmann/lines-of-code/compare/f959e71f00e591288acc024afe9cb966c6cf9bd6...1.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/LICENSE new file mode 100644 index 000000000..5716d9654 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/README.md b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/README.md new file mode 100644 index 000000000..79daa1061 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/lines-of-code/v/stable.png)](https://packagist.org/packages/sebastian/lines-of-code) +[![CI Status](https://github.com/sebastianbergmann/lines-of-code/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/lines-of-code/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/lines-of-code/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/lines-of-code) +[![codecov](https://codecov.io/gh/sebastianbergmann/lines-of-code/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/lines-of-code) + +# sebastian/lines-of-code + +Library for counting the lines of code in PHP source code. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/lines-of-code +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/lines-of-code +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/SECURITY.md new file mode 100644 index 000000000..d88ff0019 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. + +**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** + +Instead, please email `sebastian@phpunit.de`. + +Please include as much of the information listed below as you can to help us better understand and resolve the issue: + +* The type of issue +* Full paths of source file(s) related to the manifestation of the issue +* The location of the affected source code (tag/branch/commit or direct URL) +* Any special configuration required to reproduce the issue +* Step-by-step instructions to reproduce the issue +* Proof-of-concept or exploit code (if possible) +* Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +## Web Context + +The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. + +The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. + +If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. + +Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. + diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/composer.json b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/composer.json new file mode 100644 index 000000000..1f3b74795 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/composer.json @@ -0,0 +1,43 @@ +{ + "name": "sebastian/lines-of-code", + "description": "Library for counting the lines of code in PHP source code", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1", + "nikic/php-parser": "^4.18 || ^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "config": { + "platform": { + "php": "8.1" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Counter.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Counter.php new file mode 100644 index 000000000..9519268b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Counter.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use function assert; +use function file_get_contents; +use function substr_count; +use PhpParser\Error; +use PhpParser\Node; +use PhpParser\NodeTraverser; +use PhpParser\ParserFactory; + +final class Counter +{ + /** + * @throws RuntimeException + */ + public function countInSourceFile(string $sourceFile): LinesOfCode + { + return $this->countInSourceString(file_get_contents($sourceFile)); + } + + /** + * @throws RuntimeException + */ + public function countInSourceString(string $source): LinesOfCode + { + $linesOfCode = substr_count($source, "\n"); + + if ($linesOfCode === 0 && !empty($source)) { + $linesOfCode = 1; + } + + assert($linesOfCode >= 0); + + try { + $nodes = (new ParserFactory)->createForHostVersion()->parse($source); + + assert($nodes !== null); + + return $this->countInAbstractSyntaxTree($linesOfCode, $nodes); + + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + $error->getCode(), + $error, + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * @psalm-param non-negative-int $linesOfCode + * + * @param Node[] $nodes + * + * @throws RuntimeException + */ + public function countInAbstractSyntaxTree(int $linesOfCode, array $nodes): LinesOfCode + { + $traverser = new NodeTraverser; + $visitor = new LineCountingVisitor($linesOfCode); + + $traverser->addVisitor($visitor); + + try { + /* @noinspection UnusedFunctionResultInspection */ + $traverser->traverse($nodes); + // @codeCoverageIgnoreStart + } catch (Error $error) { + throw new RuntimeException( + $error->getMessage(), + $error->getCode(), + $error, + ); + } + // @codeCoverageIgnoreEnd + + return $visitor->result(); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/Exception.php new file mode 100644 index 000000000..11d543aa7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php new file mode 100644 index 000000000..46a5c1b1f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/IllogicalValuesException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use LogicException; + +final class IllogicalValuesException extends LogicException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php new file mode 100644 index 000000000..40d27e1f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/NegativeValueException.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use InvalidArgumentException; + +final class NegativeValueException extends InvalidArgumentException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php new file mode 100644 index 000000000..4e6d66d0d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/Exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php new file mode 100644 index 000000000..ec394d986 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LineCountingVisitor.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +use function array_merge; +use function array_unique; +use function assert; +use function count; +use PhpParser\Comment; +use PhpParser\Node; +use PhpParser\Node\Expr; +use PhpParser\NodeVisitorAbstract; + +final class LineCountingVisitor extends NodeVisitorAbstract +{ + /** + * @psalm-var non-negative-int + */ + private readonly int $linesOfCode; + + /** + * @var Comment[] + */ + private array $comments = []; + + /** + * @var int[] + */ + private array $linesWithStatements = []; + + /** + * @psalm-param non-negative-int $linesOfCode + */ + public function __construct(int $linesOfCode) + { + $this->linesOfCode = $linesOfCode; + } + + public function enterNode(Node $node): void + { + $this->comments = array_merge($this->comments, $node->getComments()); + + if (!$node instanceof Expr) { + return; + } + + $this->linesWithStatements[] = $node->getStartLine(); + } + + public function result(): LinesOfCode + { + $commentLinesOfCode = 0; + + foreach ($this->comments() as $comment) { + $commentLinesOfCode += ($comment->getEndLine() - $comment->getStartLine() + 1); + } + + $nonCommentLinesOfCode = $this->linesOfCode - $commentLinesOfCode; + $logicalLinesOfCode = count(array_unique($this->linesWithStatements)); + + assert($commentLinesOfCode >= 0); + assert($nonCommentLinesOfCode >= 0); + assert($logicalLinesOfCode >= 0); + + return new LinesOfCode( + $this->linesOfCode, + $commentLinesOfCode, + $nonCommentLinesOfCode, + $logicalLinesOfCode, + ); + } + + /** + * @return Comment[] + */ + private function comments(): array + { + $comments = []; + + foreach ($this->comments as $comment) { + $comments[$comment->getStartLine() . '_' . $comment->getStartTokenPos() . '_' . $comment->getEndLine() . '_' . $comment->getEndTokenPos()] = $comment; + } + + return $comments; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LinesOfCode.php b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LinesOfCode.php new file mode 100644 index 000000000..729eba528 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/lines-of-code/src/LinesOfCode.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\LinesOfCode; + +/** + * @psalm-immutable + */ +final class LinesOfCode +{ + /** + * @psalm-var non-negative-int + */ + private readonly int $linesOfCode; + + /** + * @psalm-var non-negative-int + */ + private readonly int $commentLinesOfCode; + + /** + * @psalm-var non-negative-int + */ + private readonly int $nonCommentLinesOfCode; + + /** + * @psalm-var non-negative-int + */ + private readonly int $logicalLinesOfCode; + + /** + * @psalm-param non-negative-int $linesOfCode + * @psalm-param non-negative-int $commentLinesOfCode + * @psalm-param non-negative-int $nonCommentLinesOfCode + * @psalm-param non-negative-int $logicalLinesOfCode + * + * @throws IllogicalValuesException + * @throws NegativeValueException + */ + public function __construct(int $linesOfCode, int $commentLinesOfCode, int $nonCommentLinesOfCode, int $logicalLinesOfCode) + { + /** @psalm-suppress DocblockTypeContradiction */ + if ($linesOfCode < 0) { + throw new NegativeValueException('$linesOfCode must not be negative'); + } + + /** @psalm-suppress DocblockTypeContradiction */ + if ($commentLinesOfCode < 0) { + throw new NegativeValueException('$commentLinesOfCode must not be negative'); + } + + /** @psalm-suppress DocblockTypeContradiction */ + if ($nonCommentLinesOfCode < 0) { + throw new NegativeValueException('$nonCommentLinesOfCode must not be negative'); + } + + /** @psalm-suppress DocblockTypeContradiction */ + if ($logicalLinesOfCode < 0) { + throw new NegativeValueException('$logicalLinesOfCode must not be negative'); + } + + if ($linesOfCode - $commentLinesOfCode !== $nonCommentLinesOfCode) { + throw new IllogicalValuesException('$linesOfCode !== $commentLinesOfCode + $nonCommentLinesOfCode'); + } + + $this->linesOfCode = $linesOfCode; + $this->commentLinesOfCode = $commentLinesOfCode; + $this->nonCommentLinesOfCode = $nonCommentLinesOfCode; + $this->logicalLinesOfCode = $logicalLinesOfCode; + } + + /** + * @psalm-return non-negative-int + */ + public function linesOfCode(): int + { + return $this->linesOfCode; + } + + /** + * @psalm-return non-negative-int + */ + public function commentLinesOfCode(): int + { + return $this->commentLinesOfCode; + } + + /** + * @psalm-return non-negative-int + */ + public function nonCommentLinesOfCode(): int + { + return $this->nonCommentLinesOfCode; + } + + /** + * @psalm-return non-negative-int + */ + public function logicalLinesOfCode(): int + { + return $this->logicalLinesOfCode; + } + + public function plus(self $other): self + { + return new self( + $this->linesOfCode() + $other->linesOfCode(), + $this->commentLinesOfCode() + $other->commentLinesOfCode(), + $this->nonCommentLinesOfCode() + $other->nonCommentLinesOfCode(), + $this->logicalLinesOfCode() + $other->logicalLinesOfCode(), + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/ChangeLog.md new file mode 100644 index 000000000..c04f46fa1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/ChangeLog.md @@ -0,0 +1,95 @@ +# Change Log + +All notable changes to `sebastianbergmann/object-enumerator` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [5.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [4.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\ObjectEnumerator\Exception` now correctly extends `\Throwable` + +## [4.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [4.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2 + +## [3.0.3] - 2017-08-03 + +### Changed + +* Bumped required version of `sebastian/object-reflector` + +## [3.0.2] - 2017-03-12 + +### Changed + +* `sebastian/object-reflector` is now a dependency + +## [3.0.1] - 2017-03-12 + +### Fixed + +* Objects aggregated in inherited attributes are not enumerated + +## [3.0.0] - 2017-03-03 + +### Removed + +* This component is no longer supported on PHP 5.6 + +## [2.0.1] - 2017-02-18 + +### Fixed + +* Fixed [#2](https://github.com/sebastianbergmann/phpunit/pull/2): Exceptions in `ReflectionProperty::getValue()` are not handled + +## [2.0.0] - 2016-11-19 + +### Changed + +* This component is now compatible with `sebastian/recursion-context: ~1.0.4` + +## 1.0.0 - 2016-02-04 + +### Added + +* Initial release + +[5.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.4...5.0.0 +[4.0.4]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.3...4.0.0 +[3.0.3]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.2...3.0.3 +[3.0.2]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/2.0...3.0.0 +[2.0.1]: https://github.com/sebastianbergmann/object-enumerator/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/object-enumerator/compare/1.0...2.0.0 + diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/LICENSE new file mode 100644 index 000000000..16e1ba9a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2016-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/README.md b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/README.md new file mode 100644 index 000000000..fc1a7aabf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/object-enumerator/v/stable.png)](https://packagist.org/packages/sebastian/object-enumerator) +[![CI Status](https://github.com/sebastianbergmann/object-enumerator/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/object-enumerator/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/object-enumerator/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/object-enumerator) +[![codecov](https://codecov.io/gh/sebastianbergmann/object-enumerator/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/object-enumerator) + +# sebastian/object-enumerator + +Traverses array structures and object graphs to enumerate all referenced objects. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/object-enumerator +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/object-enumerator +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/composer.json b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/composer.json new file mode 100644 index 000000000..1d1a7149c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/composer.json @@ -0,0 +1,43 @@ +{ + "name": "sebastian/object-enumerator", + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/phpunit.xml b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/phpunit.xml new file mode 100644 index 000000000..bf94af038 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/phpunit.xml @@ -0,0 +1,24 @@ + + + + + tests + + + + + + src + + + diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/src/Enumerator.php b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/src/Enumerator.php new file mode 100644 index 000000000..c0897e54e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-enumerator/src/Enumerator.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\ObjectEnumerator; + +use function array_merge; +use function is_array; +use function is_object; +use SebastianBergmann\ObjectReflector\ObjectReflector; +use SebastianBergmann\RecursionContext\Context; + +final class Enumerator +{ + /** + * @psalm-return list + */ + public function enumerate(array|object $variable, Context $processed = new Context): array + { + $objects = []; + + if ($processed->contains($variable)) { + return $objects; + } + + $array = $variable; + + /* @noinspection UnusedFunctionResultInspection */ + $processed->add($variable); + + if (is_array($variable)) { + foreach ($array as $element) { + if (!is_array($element) && !is_object($element)) { + continue; + } + + /** @noinspection SlowArrayOperationsInLoopInspection */ + $objects = array_merge( + $objects, + $this->enumerate($element, $processed) + ); + } + + return $objects; + } + + $objects[] = $variable; + + foreach ((new ObjectReflector)->getProperties($variable) as $value) { + if (!is_array($value) && !is_object($value)) { + continue; + } + + /** @noinspection SlowArrayOperationsInLoopInspection */ + $objects = array_merge( + $objects, + $this->enumerate($value, $processed) + ); + } + + return $objects; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-reflector/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/ChangeLog.md new file mode 100644 index 000000000..f6deff8d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/ChangeLog.md @@ -0,0 +1,66 @@ +# Change Log + +All notable changes to `sebastianbergmann/object-reflector` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.0.0] - 2023-02-03 + +### Changed + +* `ObjectReflector::getAttributes()` has been renamed to `ObjectReflector::getProperties()` + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [2.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\ObjectReflector\Exception` now correctly extends `\Throwable` + +## [2.0.3] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +## [2.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.0, PHP 7.1, and PHP 7.2 + +## [1.1.1] - 2017-03-29 + +* Fixed [#1](https://github.com/sebastianbergmann/object-reflector/issues/1): Attributes with non-string names are not handled correctly + +## [1.1.0] - 2017-03-16 + +### Changed + +* Changed implementation of `ObjectReflector::getattributes()` to use `(array)` cast instead of `ReflectionObject` + +## 1.0.0 - 2017-03-12 + +* Initial release + +[3.0.0]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.4...3.0.0 +[2.0.4]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/sebastianbergmann/object-reflector/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/sebastianbergmann/object-reflector/compare/1.1.1...2.0.0 +[1.1.1]: https://github.com/sebastianbergmann/object-reflector/compare/1.1.0...1.1.1 +[1.1.0]: https://github.com/sebastianbergmann/object-reflector/compare/1.0.0...1.1.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-reflector/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/LICENSE new file mode 100644 index 000000000..371decf45 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2017-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/object-reflector/README.md b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/README.md new file mode 100644 index 000000000..629c82deb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/object-reflector/v/stable.png)](https://packagist.org/packages/sebastian/object-reflector) +[![CI Status](https://github.com/sebastianbergmann/object-reflector/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/object-reflector/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/object-reflector/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/object-reflector) +[![codecov](https://codecov.io/gh/sebastianbergmann/object-reflector/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/object-reflector) + +# sebastian/object-reflector + +Allows reflection of object properties, including inherited and private as well as protected ones. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/object-reflector +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/object-reflector +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-reflector/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-reflector/composer.json b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/composer.json new file mode 100644 index 000000000..c9dcad0fa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/composer.json @@ -0,0 +1,41 @@ +{ + "name": "sebastian/object-reflector", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/object-reflector/src/ObjectReflector.php b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/src/ObjectReflector.php new file mode 100644 index 000000000..ba9cbaf40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/object-reflector/src/ObjectReflector.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 SebastianBergmann\ObjectReflector; + +use function count; +use function explode; + +final class ObjectReflector +{ + /** + * @psalm-return array + */ + public function getProperties(object $object): array + { + $properties = []; + $className = $object::class; + + foreach ((array) $object as $name => $value) { + $name = explode("\0", (string) $name); + + if (count($name) === 1) { + $name = $name[0]; + } elseif ($name[1] !== $className) { + $name = $name[1] . '::' . $name[2]; + } else { + $name = $name[2]; + } + + $properties[$name] = $value; + } + + return $properties; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/recursion-context/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/ChangeLog.md new file mode 100644 index 000000000..836de86c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/ChangeLog.md @@ -0,0 +1,47 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [5.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [4.0.5] - 2023-02-03 + +### Fixed + +* [#26](https://github.com/sebastianbergmann/recursion-context/pull/26): Don't clobber `null` values if `array_key_exists(PHP_INT_MAX, $array)` + +## [4.0.4] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\RecursionContext\Exception` now correctly extends `\Throwable` + +## [4.0.3] - 2020-09-28 + +### Changed + +* [#21](https://github.com/sebastianbergmann/recursion-context/pull/21): Add type annotations for in/out parameters +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [4.0.2] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [4.0.1] - 2020-06-15 + +### Changed + +* Tests etc. are now ignored for archive exports + +[5.0.0]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.5...5.0.0 +[4.0.5]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.4...4.0.5 +[4.0.4]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.3...4.0.4 +[4.0.3]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.2...4.0.3 +[4.0.2]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.1...4.0.2 +[4.0.1]: https://github.com/sebastianbergmann/recursion-context/compare/4.0.0...4.0.1 diff --git a/.extlib/simplesamlphp/vendor/sebastian/recursion-context/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/LICENSE new file mode 100644 index 000000000..a453252d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2002-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/recursion-context/README.md b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/README.md new file mode 100644 index 000000000..8204e10e3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/README.md @@ -0,0 +1,20 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/recursion-context/v/stable.png)](https://packagist.org/packages/sebastian/recursion-context) +[![CI Status](https://github.com/sebastianbergmann/recursion-context/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/recursion-context/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/recursion-context/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/recursion-context) +[![codecov](https://codecov.io/gh/sebastianbergmann/recursion-context/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/recursion-context) + +# sebastian/recursion-context + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/recursion-context +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/recursion-context +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/recursion-context/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/recursion-context/composer.json b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/composer.json new file mode 100644 index 000000000..3a00b680a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/composer.json @@ -0,0 +1,44 @@ +{ + "name": "sebastian/recursion-context", + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "prefer-stable": true, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/recursion-context/src/Context.php b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/src/Context.php new file mode 100644 index 000000000..e900e21d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/recursion-context/src/Context.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\RecursionContext; + +use const PHP_INT_MAX; +use const PHP_INT_MIN; +use function array_key_exists; +use function array_pop; +use function array_slice; +use function count; +use function is_array; +use function random_int; +use function spl_object_hash; +use SplObjectStorage; + +final class Context +{ + private array $arrays = []; + private SplObjectStorage $objects; + + public function __construct() + { + $this->objects = new SplObjectStorage; + } + + /** + * @codeCoverageIgnore + */ + public function __destruct() + { + foreach ($this->arrays as &$array) { + if (is_array($array)) { + array_pop($array); + array_pop($array); + } + } + } + + /** + * @psalm-template T + * + * @psalm-param T $value + * + * @param-out T $value + */ + public function add(object|array &$value): int|string|false + { + if (is_array($value)) { + return $this->addArray($value); + } + + return $this->addObject($value); + } + + /** + * @psalm-template T + * + * @psalm-param T $value + * + * @param-out T $value + */ + public function contains(object|array &$value): int|string|false + { + if (is_array($value)) { + return $this->containsArray($value); + } + + return $this->containsObject($value); + } + + private function addArray(array &$array): int + { + $key = $this->containsArray($array); + + if ($key !== false) { + return $key; + } + + $key = count($this->arrays); + $this->arrays[] = &$array; + + if (!array_key_exists(PHP_INT_MAX, $array) && !array_key_exists(PHP_INT_MAX - 1, $array)) { + $array[] = $key; + $array[] = $this->objects; + } else { + /* Cover the improbable case, too. + * + * Note that array_slice() (used in containsArray()) will return the + * last two values added, *not necessarily* the highest integer keys + * in the array. Therefore, the order of these writes to $array is + * important, but the actual keys used is not. */ + do { + /** @noinspection PhpUnhandledExceptionInspection */ + $key = random_int(PHP_INT_MIN, PHP_INT_MAX); + } while (array_key_exists($key, $array)); + + $array[$key] = $key; + + do { + /** @noinspection PhpUnhandledExceptionInspection */ + $key = random_int(PHP_INT_MIN, PHP_INT_MAX); + } while (array_key_exists($key, $array)); + + $array[$key] = $this->objects; + } + + return $key; + } + + private function addObject(object $object): string + { + if (!$this->objects->contains($object)) { + $this->objects->attach($object); + } + + return spl_object_hash($object); + } + + private function containsArray(array $array): int|false + { + $end = array_slice($array, -2); + + return isset($end[1]) && $end[1] === $this->objects ? $end[0] : false; + } + + private function containsObject(object $value): string|false + { + if ($this->objects->contains($value)) { + return spl_object_hash($value); + } + + return false; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/type/ChangeLog.md new file mode 100644 index 000000000..6c66140fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/ChangeLog.md @@ -0,0 +1,176 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [4.0.0] - 2023-02-03 + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 + +## [3.2.1] - 2023-02-03 + +### Fixed + +* [#28](https://github.com/sebastianbergmann/type/pull/28): Potential undefined offset warning/notice + +## [3.2.0] - 2022-09-12 + +### Added + +* [#25](https://github.com/sebastianbergmann/type/issues/25): Support Disjunctive Normal Form types +* Added `ReflectionMapper::fromParameterTypes()` +* Added `IntersectionType::types()` and `UnionType::types()` +* Added `UnionType::containsIntersectionTypes()` + +## [3.1.0] - 2022-08-29 + +### Added + +* [#21](https://github.com/sebastianbergmann/type/issues/21): Support `true` as stand-alone type + +## [3.0.0] - 2022-03-15 + +### Added + +* Support for intersection types introduced in PHP 8.1 +* Support for the `never` return type introduced in PHP 8.1 +* Added `Type::isCallable()`, `Type::isGenericObject()`, `Type::isIterable()`, `Type::isMixed()`, `Type::isNever()`, `Type::isNull()`, `Type::isObject()`, `Type::isSimple()`, `Type::isStatic()`, `Type::isUnion()`, `Type::isUnknown()`, and `Type::isVoid()` + +### Changed + +* Renamed `ReflectionMapper::fromMethodReturnType(ReflectionMethod $method)` to `ReflectionMapper::fromReturnType(ReflectionFunctionAbstract $functionOrMethod)` + +### Removed + +* Removed `Type::getReturnTypeDeclaration()` (use `Type::asString()` instead and prefix its result with `': '`) +* Removed `TypeName::getNamespaceName()` (use `TypeName::namespaceName()` instead) +* Removed `TypeName::getSimpleName()` (use `TypeName::simpleName()` instead) +* Removed `TypeName::getQualifiedName()` (use `TypeName::qualifiedName()` instead) + +## [2.3.4] - 2021-06-15 + +### Fixed + +* Fixed regression introduced in 2.3.3 + +## [2.3.3] - 2021-06-15 [YANKED] + +### Fixed + +* [#15](https://github.com/sebastianbergmann/type/issues/15): "false" pseudo type is not handled properly + +## [2.3.2] - 2021-06-04 + +### Fixed + +* Fixed handling of tentatively declared return types + +## [2.3.1] - 2020-10-26 + +### Fixed + +* `SebastianBergmann\Type\Exception` now correctly extends `\Throwable` + +## [2.3.0] - 2020-10-06 + +### Added + +* [#14](https://github.com/sebastianbergmann/type/issues/14): Support for `static` return type that is introduced in PHP 8 + +## [2.2.2] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [2.2.1] - 2020-07-05 + +### Fixed + +* Fixed handling of `mixed` type in `ReflectionMapper::fromMethodReturnType()` + +## [2.2.0] - 2020-07-05 + +### Added + +* Added `MixedType` object for representing PHP 8's `mixed` type + +## [2.1.1] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [2.1.0] - 2020-06-01 + +### Added + +* Added `UnionType` object for representing PHP 8's Union Types +* Added `ReflectionMapper::fromMethodReturnType()` for mapping `\ReflectionMethod::getReturnType()` to a `Type` object +* Added `Type::name()` for retrieving the name of a type +* Added `Type::asString()` for retrieving a textual representation of a type + +### Changed + +* Deprecated `Type::getReturnTypeDeclaration()` (use `Type::asString()` instead and prefix its result with `': '`) +* Deprecated `TypeName::getNamespaceName()` (use `TypeName::namespaceName()` instead) +* Deprecated `TypeName::getSimpleName()` (use `TypeName::simpleName()` instead) +* Deprecated `TypeName::getQualifiedName()` (use `TypeName::qualifiedName()` instead) + +## [2.0.0] - 2020-02-07 + +### Removed + +* This component is no longer supported on PHP 7.2 + +## [1.1.3] - 2019-07-02 + +### Fixed + +* Fixed class name comparison in `ObjectType` to be case-insensitive + +## [1.1.2] - 2019-06-19 + +### Fixed + +* Fixed handling of `object` type + +## [1.1.1] - 2019-06-08 + +### Fixed + +* Fixed autoloading of `callback_function.php` fixture file + +## [1.1.0] - 2019-06-07 + +### Added + +* Added support for `callable` type +* Added support for `iterable` type + +## [1.0.0] - 2019-06-06 + +* Initial release based on [code contributed by Michel Hartmann to PHPUnit](https://github.com/sebastianbergmann/phpunit/pull/3673) + +[4.0.0]: https://github.com/sebastianbergmann/type/compare/3.2.1...4.0.0 +[3.2.1]: https://github.com/sebastianbergmann/type/compare/3.2.0...3.2.1 +[3.2.0]: https://github.com/sebastianbergmann/type/compare/3.1.0...3.2.0 +[3.1.0]: https://github.com/sebastianbergmann/type/compare/3.0.0...3.1.0 +[3.0.0]: https://github.com/sebastianbergmann/type/compare/2.3.4...3.0.0 +[2.3.4]: https://github.com/sebastianbergmann/type/compare/ca39369c41313ed12c071ed38ecda8fcdb248859...2.3.4 +[2.3.3]: https://github.com/sebastianbergmann/type/compare/2.3.2...ca39369c41313ed12c071ed38ecda8fcdb248859 +[2.3.2]: https://github.com/sebastianbergmann/type/compare/2.3.1...2.3.2 +[2.3.1]: https://github.com/sebastianbergmann/type/compare/2.3.0...2.3.1 +[2.3.0]: https://github.com/sebastianbergmann/type/compare/2.2.2...2.3.0 +[2.2.2]: https://github.com/sebastianbergmann/type/compare/2.2.1...2.2.2 +[2.2.1]: https://github.com/sebastianbergmann/type/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/sebastianbergmann/type/compare/2.1.1...2.2.0 +[2.1.1]: https://github.com/sebastianbergmann/type/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/sebastianbergmann/type/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/sebastianbergmann/type/compare/1.1.3...2.0.0 +[1.1.3]: https://github.com/sebastianbergmann/type/compare/1.1.2...1.1.3 +[1.1.2]: https://github.com/sebastianbergmann/type/compare/1.1.1...1.1.2 +[1.1.1]: https://github.com/sebastianbergmann/type/compare/1.1.0...1.1.1 +[1.1.0]: https://github.com/sebastianbergmann/type/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/sebastianbergmann/type/compare/ff74aa41746bd8d10e931843ebf37d42da513ede...1.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/type/LICENSE new file mode 100644 index 000000000..5b4bf454a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/type/README.md b/.extlib/simplesamlphp/vendor/sebastian/type/README.md new file mode 100644 index 000000000..fef3de237 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/README.md @@ -0,0 +1,22 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/type/v/stable.png)](https://packagist.org/packages/sebastian/type) +[![CI Status](https://github.com/sebastianbergmann/type/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/type/actions) +[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/type/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/type) +[![codecov](https://codecov.io/gh/sebastianbergmann/type/branch/main/graph/badge.svg)](https://codecov.io/gh/sebastianbergmann/type) + +# sebastian/type + +Collection of value objects that represent the types of the PHP type system. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/type +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/type +``` diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/type/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/composer.json b/.extlib/simplesamlphp/vendor/sebastian/type/composer.json new file mode 100644 index 000000000..faf8a0e81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/composer.json @@ -0,0 +1,50 @@ +{ + "name": "sebastian/type", + "description": "Collection of value objects that represent the types of the PHP type system", + "type": "library", + "homepage": "https://github.com/sebastianbergmann/type", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues" + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/_fixture" + ], + "files": [ + "tests/_fixture/callback_function.php", + "tests/_fixture/functions_that_declare_return_types.php" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/infection.json b/.extlib/simplesamlphp/vendor/sebastian/type/infection.json new file mode 100644 index 000000000..09546514f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/infection.json @@ -0,0 +1,12 @@ +{ + "source": { + "directories": [ + "src" + ] + }, + "mutators": { + "@default": true + }, + "minMsi": 100, + "minCoveredMsi": 100 +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/Parameter.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/Parameter.php new file mode 100644 index 000000000..b8cd8b111 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/Parameter.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class Parameter +{ + /** + * @psalm-var non-empty-string + */ + private string $name; + private Type $type; + + /** + * @psalm-param non-empty-string $name + */ + public function __construct(string $name, Type $type) + { + $this->name = $name; + $this->type = $type; + } + + public function name(): string + { + return $this->name; + } + + public function type(): Type + { + return $this->type; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/ReflectionMapper.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/ReflectionMapper.php new file mode 100644 index 000000000..a39d619de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/ReflectionMapper.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use ReflectionFunction; +use ReflectionIntersectionType; +use ReflectionMethod; +use ReflectionNamedType; +use ReflectionType; +use ReflectionUnionType; + +final class ReflectionMapper +{ + /** + * @psalm-return list + */ + public function fromParameterTypes(ReflectionFunction|ReflectionMethod $functionOrMethod): array + { + $parameters = []; + + foreach ($functionOrMethod->getParameters() as $parameter) { + $name = $parameter->getName(); + + assert($name !== ''); + + if (!$parameter->hasType()) { + $parameters[] = new Parameter($name, new UnknownType); + + continue; + } + + $type = $parameter->getType(); + + if ($type instanceof ReflectionNamedType) { + $parameters[] = new Parameter( + $name, + $this->mapNamedType($type, $functionOrMethod) + ); + + continue; + } + + if ($type instanceof ReflectionUnionType) { + $parameters[] = new Parameter( + $name, + $this->mapUnionType($type, $functionOrMethod) + ); + + continue; + } + + if ($type instanceof ReflectionIntersectionType) { + $parameters[] = new Parameter( + $name, + $this->mapIntersectionType($type, $functionOrMethod) + ); + } + } + + return $parameters; + } + + public function fromReturnType(ReflectionFunction|ReflectionMethod $functionOrMethod): Type + { + if (!$this->hasReturnType($functionOrMethod)) { + return new UnknownType; + } + + $returnType = $this->returnType($functionOrMethod); + + assert($returnType instanceof ReflectionNamedType || $returnType instanceof ReflectionUnionType || $returnType instanceof ReflectionIntersectionType); + + if ($returnType instanceof ReflectionNamedType) { + return $this->mapNamedType($returnType, $functionOrMethod); + } + + if ($returnType instanceof ReflectionUnionType) { + return $this->mapUnionType($returnType, $functionOrMethod); + } + + if ($returnType instanceof ReflectionIntersectionType) { + return $this->mapIntersectionType($returnType, $functionOrMethod); + } + } + + private function mapNamedType(ReflectionNamedType $type, ReflectionFunction|ReflectionMethod $functionOrMethod): Type + { + if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'self') { + return ObjectType::fromName( + $functionOrMethod->getDeclaringClass()->getName(), + $type->allowsNull() + ); + } + + if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'static') { + return new StaticType( + TypeName::fromReflection($functionOrMethod->getDeclaringClass()), + $type->allowsNull() + ); + } + + if ($type->getName() === 'mixed') { + return new MixedType; + } + + if ($functionOrMethod instanceof ReflectionMethod && $type->getName() === 'parent') { + return ObjectType::fromName( + $functionOrMethod->getDeclaringClass()->getParentClass()->getName(), + $type->allowsNull() + ); + } + + return Type::fromName( + $type->getName(), + $type->allowsNull() + ); + } + + private function mapUnionType(ReflectionUnionType $type, ReflectionFunction|ReflectionMethod $functionOrMethod): Type + { + $types = []; + + foreach ($type->getTypes() as $_type) { + assert($_type instanceof ReflectionNamedType || $_type instanceof ReflectionIntersectionType); + + if ($_type instanceof ReflectionNamedType) { + $types[] = $this->mapNamedType($_type, $functionOrMethod); + + continue; + } + + $types[] = $this->mapIntersectionType($_type, $functionOrMethod); + } + + return new UnionType(...$types); + } + + private function mapIntersectionType(ReflectionIntersectionType $type, ReflectionFunction|ReflectionMethod $functionOrMethod): Type + { + $types = []; + + foreach ($type->getTypes() as $_type) { + assert($_type instanceof ReflectionNamedType); + + $types[] = $this->mapNamedType($_type, $functionOrMethod); + } + + return new IntersectionType(...$types); + } + + private function hasReturnType(ReflectionFunction|ReflectionMethod $functionOrMethod): bool + { + if ($functionOrMethod->hasReturnType()) { + return true; + } + + return $functionOrMethod->hasTentativeReturnType(); + } + + private function returnType(ReflectionFunction|ReflectionMethod $functionOrMethod): ?ReflectionType + { + if ($functionOrMethod->hasReturnType()) { + return $functionOrMethod->getReturnType(); + } + + return $functionOrMethod->getTentativeReturnType(); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/TypeName.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/TypeName.php new file mode 100644 index 000000000..e63b57cc8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/TypeName.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function array_pop; +use function explode; +use function implode; +use function substr; +use ReflectionClass; + +final class TypeName +{ + private ?string $namespaceName; + private string $simpleName; + + public static function fromQualifiedName(string $fullClassName): self + { + if ($fullClassName[0] === '\\') { + $fullClassName = substr($fullClassName, 1); + } + + $classNameParts = explode('\\', $fullClassName); + + $simpleName = array_pop($classNameParts); + $namespaceName = implode('\\', $classNameParts); + + return new self($namespaceName, $simpleName); + } + + public static function fromReflection(ReflectionClass $type): self + { + return new self( + $type->getNamespaceName(), + $type->getShortName() + ); + } + + public function __construct(?string $namespaceName, string $simpleName) + { + if ($namespaceName === '') { + $namespaceName = null; + } + + $this->namespaceName = $namespaceName; + $this->simpleName = $simpleName; + } + + public function namespaceName(): ?string + { + return $this->namespaceName; + } + + public function simpleName(): string + { + return $this->simpleName; + } + + public function qualifiedName(): string + { + return $this->namespaceName === null + ? $this->simpleName + : $this->namespaceName . '\\' . $this->simpleName; + } + + public function isNamespaced(): bool + { + return $this->namespaceName !== null; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/exception/Exception.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/exception/Exception.php new file mode 100644 index 000000000..e0e7ee579 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/exception/Exception.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use Throwable; + +interface Exception extends Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/exception/RuntimeException.php new file mode 100644 index 000000000..4dfea6a6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/CallableType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/CallableType.php new file mode 100644 index 000000000..0da42a74e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/CallableType.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use function class_exists; +use function count; +use function explode; +use function function_exists; +use function is_array; +use function is_object; +use function is_string; +use function str_contains; +use Closure; +use ReflectionClass; +use ReflectionObject; + +final class CallableType extends Type +{ + private bool $allowsNull; + + public function __construct(bool $nullable) + { + $this->allowsNull = $nullable; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($other instanceof self) { + return true; + } + + if ($other instanceof ObjectType) { + if ($this->isClosure($other)) { + return true; + } + + if ($this->hasInvokeMethod($other)) { + return true; + } + } + + if ($other instanceof SimpleType) { + if ($this->isFunction($other)) { + return true; + } + + if ($this->isClassCallback($other)) { + return true; + } + + if ($this->isObjectCallback($other)) { + return true; + } + } + + return false; + } + + public function name(): string + { + return 'callable'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true CallableType $this + */ + public function isCallable(): bool + { + return true; + } + + private function isClosure(ObjectType $type): bool + { + return $type->className()->qualifiedName() === Closure::class; + } + + private function hasInvokeMethod(ObjectType $type): bool + { + $className = $type->className()->qualifiedName(); + + assert(class_exists($className)); + + return (new ReflectionClass($className))->hasMethod('__invoke'); + } + + private function isFunction(SimpleType $type): bool + { + if (!is_string($type->value())) { + return false; + } + + return function_exists($type->value()); + } + + private function isObjectCallback(SimpleType $type): bool + { + if (!is_array($type->value())) { + return false; + } + + if (count($type->value()) !== 2) { + return false; + } + + if (!isset($type->value()[0], $type->value()[1])) { + return false; + } + + if (!is_object($type->value()[0]) || !is_string($type->value()[1])) { + return false; + } + + [$object, $methodName] = $type->value(); + + return (new ReflectionObject($object))->hasMethod($methodName); + } + + private function isClassCallback(SimpleType $type): bool + { + if (!is_string($type->value()) && !is_array($type->value())) { + return false; + } + + if (is_string($type->value())) { + if (!str_contains($type->value(), '::')) { + return false; + } + + [$className, $methodName] = explode('::', $type->value()); + } + + if (is_array($type->value())) { + if (count($type->value()) !== 2) { + return false; + } + + if (!isset($type->value()[0], $type->value()[1])) { + return false; + } + + if (!is_string($type->value()[0]) || !is_string($type->value()[1])) { + return false; + } + + [$className, $methodName] = $type->value(); + } + + assert(isset($className) && is_string($className)); + assert(isset($methodName) && is_string($methodName)); + + if (!class_exists($className)) { + return false; + } + + $class = new ReflectionClass($className); + + if (!$class->hasMethod($methodName)) { + return false; + } + + $method = $class->getMethod($methodName); + + return $method->isPublic() && $method->isStatic(); + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/FalseType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/FalseType.php new file mode 100644 index 000000000..f417fb699 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/FalseType.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class FalseType extends Type +{ + public function isAssignable(Type $other): bool + { + if ($other instanceof self) { + return true; + } + + return $other instanceof SimpleType && + $other->name() === 'bool' && + $other->value() === false; + } + + public function name(): string + { + return 'false'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true FalseType $this + */ + public function isFalse(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/GenericObjectType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/GenericObjectType.php new file mode 100644 index 000000000..76ab6a9fa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/GenericObjectType.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class GenericObjectType extends Type +{ + private bool $allowsNull; + + public function __construct(bool $nullable) + { + $this->allowsNull = $nullable; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if (!$other instanceof ObjectType) { + return false; + } + + return true; + } + + public function name(): string + { + return 'object'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true GenericObjectType $this + */ + public function isGenericObject(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/IntersectionType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/IntersectionType.php new file mode 100644 index 000000000..71d5dc28d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/IntersectionType.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use function count; +use function implode; +use function in_array; +use function sort; + +final class IntersectionType extends Type +{ + /** + * @psalm-var non-empty-list + */ + private array $types; + + /** + * @throws RuntimeException + */ + public function __construct(Type ...$types) + { + $this->ensureMinimumOfTwoTypes(...$types); + $this->ensureOnlyValidTypes(...$types); + $this->ensureNoDuplicateTypes(...$types); + + $this->types = $types; + } + + public function isAssignable(Type $other): bool + { + return $other->isObject(); + } + + public function asString(): string + { + return $this->name(); + } + + public function name(): string + { + $types = []; + + foreach ($this->types as $type) { + $types[] = $type->name(); + } + + sort($types); + + return implode('&', $types); + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IntersectionType $this + */ + public function isIntersection(): bool + { + return true; + } + + /** + * @psalm-return non-empty-list + */ + public function types(): array + { + return $this->types; + } + + /** + * @throws RuntimeException + */ + private function ensureMinimumOfTwoTypes(Type ...$types): void + { + if (count($types) < 2) { + throw new RuntimeException( + 'An intersection type must be composed of at least two types' + ); + } + } + + /** + * @throws RuntimeException + */ + private function ensureOnlyValidTypes(Type ...$types): void + { + foreach ($types as $type) { + if (!$type->isObject()) { + throw new RuntimeException( + 'An intersection type can only be composed of interfaces and classes' + ); + } + } + } + + /** + * @throws RuntimeException + */ + private function ensureNoDuplicateTypes(Type ...$types): void + { + $names = []; + + foreach ($types as $type) { + assert($type instanceof ObjectType); + + $classQualifiedName = $type->className()->qualifiedName(); + + if (in_array($classQualifiedName, $names, true)) { + throw new RuntimeException('An intersection type must not contain duplicate types'); + } + + $names[] = $classQualifiedName; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/IterableType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/IterableType.php new file mode 100644 index 000000000..d2499532c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/IterableType.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function assert; +use function class_exists; +use function is_iterable; +use ReflectionClass; + +final class IterableType extends Type +{ + private bool $allowsNull; + + public function __construct(bool $nullable) + { + $this->allowsNull = $nullable; + } + + /** + * @throws RuntimeException + */ + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($other instanceof self) { + return true; + } + + if ($other instanceof SimpleType) { + return is_iterable($other->value()); + } + + if ($other instanceof ObjectType) { + $className = $other->className()->qualifiedName(); + + assert(class_exists($className)); + + return (new ReflectionClass($className))->isIterable(); + } + + return false; + } + + public function name(): string + { + return 'iterable'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true IterableType $this + */ + public function isIterable(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/MixedType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/MixedType.php new file mode 100644 index 000000000..a1412e453 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/MixedType.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 SebastianBergmann\Type; + +final class MixedType extends Type +{ + public function isAssignable(Type $other): bool + { + return !$other instanceof VoidType; + } + + public function asString(): string + { + return 'mixed'; + } + + public function name(): string + { + return 'mixed'; + } + + public function allowsNull(): bool + { + return true; + } + + /** + * @psalm-assert-if-true MixedType $this + */ + public function isMixed(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/NeverType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/NeverType.php new file mode 100644 index 000000000..6c144743e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/NeverType.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class NeverType extends Type +{ + public function isAssignable(Type $other): bool + { + return $other instanceof self; + } + + public function name(): string + { + return 'never'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true NeverType $this + */ + public function isNever(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/NullType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/NullType.php new file mode 100644 index 000000000..93834eabf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/NullType.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 SebastianBergmann\Type; + +final class NullType extends Type +{ + public function isAssignable(Type $other): bool + { + return !($other instanceof VoidType); + } + + public function name(): string + { + return 'null'; + } + + public function asString(): string + { + return 'null'; + } + + public function allowsNull(): bool + { + return true; + } + + /** + * @psalm-assert-if-true NullType $this + */ + public function isNull(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/ObjectType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/ObjectType.php new file mode 100644 index 000000000..717cb9238 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/ObjectType.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function is_subclass_of; +use function strcasecmp; + +final class ObjectType extends Type +{ + private TypeName $className; + private bool $allowsNull; + + public function __construct(TypeName $className, bool $allowsNull) + { + $this->className = $className; + $this->allowsNull = $allowsNull; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($other instanceof self) { + if (0 === strcasecmp($this->className->qualifiedName(), $other->className->qualifiedName())) { + return true; + } + + if (is_subclass_of($other->className->qualifiedName(), $this->className->qualifiedName(), true)) { + return true; + } + } + + return false; + } + + public function name(): string + { + return $this->className->qualifiedName(); + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + public function className(): TypeName + { + return $this->className; + } + + /** + * @psalm-assert-if-true ObjectType $this + */ + public function isObject(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/SimpleType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/SimpleType.php new file mode 100644 index 000000000..4f210a807 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/SimpleType.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 SebastianBergmann\Type; + +use function strtolower; + +final class SimpleType extends Type +{ + private string $name; + private bool $allowsNull; + private mixed $value; + + public function __construct(string $name, bool $nullable, mixed $value = null) + { + $this->name = $this->normalize($name); + $this->allowsNull = $nullable; + $this->value = $value; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if ($this->name === 'bool' && $other->name() === 'true') { + return true; + } + + if ($this->name === 'bool' && $other->name() === 'false') { + return true; + } + + if ($other instanceof self) { + return $this->name === $other->name; + } + + return false; + } + + public function name(): string + { + return $this->name; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + public function value(): mixed + { + return $this->value; + } + + /** + * @psalm-assert-if-true SimpleType $this + */ + public function isSimple(): bool + { + return true; + } + + private function normalize(string $name): string + { + $name = strtolower($name); + + return match ($name) { + 'boolean' => 'bool', + 'real', 'double' => 'float', + 'integer' => 'int', + '[]' => 'array', + default => $name, + }; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/StaticType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/StaticType.php new file mode 100644 index 000000000..b53708b22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/StaticType.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function is_subclass_of; +use function strcasecmp; + +final class StaticType extends Type +{ + private TypeName $className; + private bool $allowsNull; + + public function __construct(TypeName $className, bool $allowsNull) + { + $this->className = $className; + $this->allowsNull = $allowsNull; + } + + public function isAssignable(Type $other): bool + { + if ($this->allowsNull && $other instanceof NullType) { + return true; + } + + if (!$other instanceof ObjectType) { + return false; + } + + if (0 === strcasecmp($this->className->qualifiedName(), $other->className()->qualifiedName())) { + return true; + } + + if (is_subclass_of($other->className()->qualifiedName(), $this->className->qualifiedName(), true)) { + return true; + } + + return false; + } + + public function name(): string + { + return 'static'; + } + + public function allowsNull(): bool + { + return $this->allowsNull; + } + + /** + * @psalm-assert-if-true StaticType $this + */ + public function isStatic(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/TrueType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/TrueType.php new file mode 100644 index 000000000..94e5be99d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/TrueType.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class TrueType extends Type +{ + public function isAssignable(Type $other): bool + { + if ($other instanceof self) { + return true; + } + + return $other instanceof SimpleType && + $other->name() === 'bool' && + $other->value() === true; + } + + public function name(): string + { + return 'true'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TrueType $this + */ + public function isTrue(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/Type.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/Type.php new file mode 100644 index 000000000..76029cfd1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/Type.php @@ -0,0 +1,192 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function gettype; +use function strtolower; + +abstract class Type +{ + public static function fromValue(mixed $value, bool $allowsNull): self + { + if ($allowsNull === false) { + if ($value === true) { + return new TrueType; + } + + if ($value === false) { + return new FalseType; + } + } + + $typeName = gettype($value); + + if ($typeName === 'object') { + return new ObjectType(TypeName::fromQualifiedName($value::class), $allowsNull); + } + + $type = self::fromName($typeName, $allowsNull); + + if ($type instanceof SimpleType) { + $type = new SimpleType($typeName, $allowsNull, $value); + } + + return $type; + } + + public static function fromName(string $typeName, bool $allowsNull): self + { + return match (strtolower($typeName)) { + 'callable' => new CallableType($allowsNull), + 'true' => new TrueType, + 'false' => new FalseType, + 'iterable' => new IterableType($allowsNull), + 'never' => new NeverType, + 'null' => new NullType, + 'object' => new GenericObjectType($allowsNull), + 'unknown type' => new UnknownType, + 'void' => new VoidType, + 'array', 'bool', 'boolean', 'double', 'float', 'int', 'integer', 'real', 'resource', 'resource (closed)', 'string' => new SimpleType($typeName, $allowsNull), + 'mixed' => new MixedType, + default => new ObjectType(TypeName::fromQualifiedName($typeName), $allowsNull), + }; + } + + public function asString(): string + { + return ($this->allowsNull() ? '?' : '') . $this->name(); + } + + /** + * @psalm-assert-if-true CallableType $this + */ + public function isCallable(): bool + { + return false; + } + + /** + * @psalm-assert-if-true TrueType $this + */ + public function isTrue(): bool + { + return false; + } + + /** + * @psalm-assert-if-true FalseType $this + */ + public function isFalse(): bool + { + return false; + } + + /** + * @psalm-assert-if-true GenericObjectType $this + */ + public function isGenericObject(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IntersectionType $this + */ + public function isIntersection(): bool + { + return false; + } + + /** + * @psalm-assert-if-true IterableType $this + */ + public function isIterable(): bool + { + return false; + } + + /** + * @psalm-assert-if-true MixedType $this + */ + public function isMixed(): bool + { + return false; + } + + /** + * @psalm-assert-if-true NeverType $this + */ + public function isNever(): bool + { + return false; + } + + /** + * @psalm-assert-if-true NullType $this + */ + public function isNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true ObjectType $this + */ + public function isObject(): bool + { + return false; + } + + /** + * @psalm-assert-if-true SimpleType $this + */ + public function isSimple(): bool + { + return false; + } + + /** + * @psalm-assert-if-true StaticType $this + */ + public function isStatic(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UnionType $this + */ + public function isUnion(): bool + { + return false; + } + + /** + * @psalm-assert-if-true UnknownType $this + */ + public function isUnknown(): bool + { + return false; + } + + /** + * @psalm-assert-if-true VoidType $this + */ + public function isVoid(): bool + { + return false; + } + + abstract public function isAssignable(self $other): bool; + + abstract public function name(): string; + + abstract public function allowsNull(): bool; +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/UnionType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/UnionType.php new file mode 100644 index 000000000..01c4b71d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/UnionType.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +use function count; +use function implode; +use function sort; + +final class UnionType extends Type +{ + /** + * @psalm-var non-empty-list + */ + private array $types; + + /** + * @throws RuntimeException + */ + public function __construct(Type ...$types) + { + $this->ensureMinimumOfTwoTypes(...$types); + $this->ensureOnlyValidTypes(...$types); + + $this->types = $types; + } + + public function isAssignable(Type $other): bool + { + foreach ($this->types as $type) { + if ($type->isAssignable($other)) { + return true; + } + } + + return false; + } + + public function asString(): string + { + return $this->name(); + } + + public function name(): string + { + $types = []; + + foreach ($this->types as $type) { + if ($type->isIntersection()) { + $types[] = '(' . $type->name() . ')'; + + continue; + } + + $types[] = $type->name(); + } + + sort($types); + + return implode('|', $types); + } + + public function allowsNull(): bool + { + foreach ($this->types as $type) { + if ($type instanceof NullType) { + return true; + } + } + + return false; + } + + /** + * @psalm-assert-if-true UnionType $this + */ + public function isUnion(): bool + { + return true; + } + + public function containsIntersectionTypes(): bool + { + foreach ($this->types as $type) { + if ($type->isIntersection()) { + return true; + } + } + + return false; + } + + /** + * @psalm-return non-empty-list + */ + public function types(): array + { + return $this->types; + } + + /** + * @throws RuntimeException + */ + private function ensureMinimumOfTwoTypes(Type ...$types): void + { + if (count($types) < 2) { + throw new RuntimeException( + 'A union type must be composed of at least two types' + ); + } + } + + /** + * @throws RuntimeException + */ + private function ensureOnlyValidTypes(Type ...$types): void + { + foreach ($types as $type) { + if ($type instanceof UnknownType) { + throw new RuntimeException( + 'A union type must not be composed of an unknown type' + ); + } + + if ($type instanceof VoidType) { + throw new RuntimeException( + 'A union type must not be composed of a void type' + ); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/UnknownType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/UnknownType.php new file mode 100644 index 000000000..dc2744077 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/UnknownType.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 SebastianBergmann\Type; + +final class UnknownType extends Type +{ + public function isAssignable(Type $other): bool + { + return true; + } + + public function name(): string + { + return 'unknown type'; + } + + public function asString(): string + { + return ''; + } + + public function allowsNull(): bool + { + return true; + } + + /** + * @psalm-assert-if-true UnknownType $this + */ + public function isUnknown(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/type/src/type/VoidType.php b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/VoidType.php new file mode 100644 index 000000000..f740fe29f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/type/src/type/VoidType.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\Type; + +final class VoidType extends Type +{ + public function isAssignable(Type $other): bool + { + return $other instanceof self; + } + + public function name(): string + { + return 'void'; + } + + public function allowsNull(): bool + { + return false; + } + + /** + * @psalm-assert-if-true VoidType $this + */ + public function isVoid(): bool + { + return true; + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/version/ChangeLog.md b/.extlib/simplesamlphp/vendor/sebastian/version/ChangeLog.md new file mode 100644 index 000000000..f589eb9e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/version/ChangeLog.md @@ -0,0 +1,43 @@ +# ChangeLog + +All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. + +## [4.0.1] - 2023-02-07 + +### Fixed + +* [#17](https://github.com/sebastianbergmann/version/pull/17): Release archive contains unnecessary assets + +## [4.0.0] - 2023-02-03 + +### Changed + +* `Version::getVersion()` has been renamed to `Version::asString()` + +### Removed + +* This component is no longer supported on PHP 7.3, PHP 7.4, and PHP 8.0 + +## [3.0.2] - 2020-09-28 + +### Changed + +* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` + +## [3.0.1] - 2020-06-26 + +### Added + +* This component is now supported on PHP 8 + +## [3.0.0] - 2020-01-21 + +### Removed + +* This component is no longer supported on PHP 7.1 and PHP 7.2 + +[4.0.1]: https://github.com/sebastianbergmann/version/compare/4.0.0...4.0.1 +[4.0.0]: https://github.com/sebastianbergmann/version/compare/3.0.2...4.0.0 +[3.0.2]: https://github.com/sebastianbergmann/version/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/version/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/version/compare/2.0.1...3.0.0 diff --git a/.extlib/simplesamlphp/vendor/sebastian/version/LICENSE b/.extlib/simplesamlphp/vendor/sebastian/version/LICENSE new file mode 100644 index 000000000..2a4db824b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/version/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2013-2023, Sebastian Bergmann +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder nor the names of its + 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 HOLDER 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/.extlib/simplesamlphp/vendor/sebastian/version/README.md b/.extlib/simplesamlphp/vendor/sebastian/version/README.md new file mode 100644 index 000000000..61357886f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/version/README.md @@ -0,0 +1,50 @@ +[![Latest Stable Version](https://poser.pugx.org/sebastian/version/v/stable.png)](https://packagist.org/packages/sebastian/version) + +# sebastian/version + +**sebastian/version** is a library that helps with managing the version number of Git-hosted PHP projects. + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + +``` +composer require sebastian/version +``` + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + +``` +composer require --dev sebastian/version +``` +## Usage + +The constructor of the `SebastianBergmann\Version` class expects two parameters: + +* `$release` is the version number of the latest release (`X.Y.Z`, for instance) or the name of the release series (`X.Y`) when no release has been made from that branch / for that release series yet. +* `$path` is the path to the directory (or a subdirectory thereof) where the sourcecode of the project can be found. Simply passing `__DIR__` here usually suffices. + +Apart from the constructor, the `SebastianBergmann\Version` class has a single public method: `asString()`. + +Here is a contrived example that shows the basic usage: + +```php +asString()); +``` +``` +string(18) "1.0.0-17-g00f3408" +``` + +When a new release is prepared, the string that is passed to the constructor as the first argument needs to be updated. + +### How SebastianBergmann\Version::asString() works + +* If `$path` is not (part of) a Git repository and `$release` is in `X.Y.Z` format then `$release` is returned as-is. +* If `$path` is not (part of) a Git repository and `$release` is in `X.Y` format then `$release` is returned suffixed with `-dev`. +* If `$path` is (part of) a Git repository and `$release` is in `X.Y.Z` format then the output of `git describe --tags` is returned as-is. +* If `$path` is (part of) a Git repository and `$release` is in `X.Y` format then a string is returned that begins with `X.Y` and ends with information from `git describe --tags`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/version/SECURITY.md b/.extlib/simplesamlphp/vendor/sebastian/version/SECURITY.md new file mode 100644 index 000000000..d4ee967bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/version/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +This library is intended to be used in development environments only. For instance, it is used by the testing framework PHPUnit. There is no reason why this library should be installed on a webserver. + +**If you upload this library to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** + +## Security Contact Information + +After the above, if you still would like to report a security vulnerability, please email `sebastian@phpunit.de`. diff --git a/.extlib/simplesamlphp/vendor/sebastian/version/composer.json b/.extlib/simplesamlphp/vendor/sebastian/version/composer.json new file mode 100644 index 000000000..1215a327f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/version/composer.json @@ -0,0 +1,37 @@ +{ + "name": "sebastian/version", + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues" + }, + "config": { + "platform": { + "php": "8.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "prefer-stable": true, + "require": { + "php": ">=8.1" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/sebastian/version/src/Version.php b/.extlib/simplesamlphp/vendor/sebastian/version/src/Version.php new file mode 100644 index 000000000..4b7c8586d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/sebastian/version/src/Version.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann; + +use function end; +use function explode; +use function fclose; +use function is_dir; +use function is_resource; +use function proc_close; +use function proc_open; +use function stream_get_contents; +use function substr_count; +use function trim; + +final class Version +{ + private readonly string $version; + + public function __construct(string $release, string $path) + { + $this->version = $this->generate($release, $path); + } + + public function asString(): string + { + return $this->version; + } + + private function generate(string $release, string $path): string + { + if (substr_count($release, '.') + 1 === 3) { + $version = $release; + } else { + $version = $release . '-dev'; + } + + $git = $this->getGitInformation($path); + + if (!$git) { + return $version; + } + + if (substr_count($release, '.') + 1 === 3) { + return $git; + } + + $git = explode('-', $git); + + return $release . '-' . end($git); + } + + private function getGitInformation(string $path): bool|string + { + if (!is_dir($path . DIRECTORY_SEPARATOR . '.git')) { + return false; + } + + $process = proc_open( + 'git describe --tags', + [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ], + $pipes, + $path + ); + + if (!is_resource($process)) { + return false; + } + + $result = trim(stream_get_contents($pipes[1])); + + fclose($pipes[1]); + fclose($pipes[2]); + + $returnCode = proc_close($process); + + if ($returnCode !== 0) { + return false; + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/Assert.php b/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/Assert.php index 59de7b1e5..2ce4587a6 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/Assert.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/Assert.php @@ -15,6 +15,9 @@ use function array_unshift; use function call_user_func_array; use function end; +use function enum_exists; +use function function_exists; +use function get_class; use function is_object; use function is_resource; use function is_string; @@ -465,6 +468,10 @@ protected static function valueToString(mixed $value): string return $value::class . ': ' . self::valueToString($value->format('c')); } + if (function_exists('enum_exists') && enum_exists(get_class($value))) { + return get_class($value) . '::' . $value->name; + } + return $value::class; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/CustomAssertionTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/CustomAssertionTrait.php index f8ed12471..7884861af 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/CustomAssertionTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/assert/src/CustomAssertionTrait.php @@ -23,29 +23,26 @@ trait CustomAssertionTrait { /** @var string */ - private static string $nmtoken_regex = '/^[\w.:-]+$/u'; + private static string $nmtoken_regex = '/^[\w.:-]+$/Du'; /** @var string */ - private static string $nmtokens_regex = '/^([\w.:-]+)([\s][\w.:-]+)*$/u'; + private static string $nmtokens_regex = '/^([\w.:-]+)([\s][\w.:-]+)*$/Du'; /** @var string */ - private static string $datetime_regex = '/-?[0-9]{4}-(((0(1|3|5|7|8)|1(0|2))-(0[1-9]|(1|2)[0-9]|3[0-1]))|((0(4|6|9)|11)-(0[1-9]|(1|2)[0-9]|30))|(02-(0[1-9]|(1|2)[0-9])))T([0-1][0-9]|2[0-4]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])(\.[0-999])?((\+|-)([0-1][0-9]|2[0-4]):(0[0-9]|[1-5][0-9])|Z)?/i'; + private static string $datetime_regex = '/-?[0-9]{4}-(((0(1|3|5|7|8)|1(0|2))-(0[1-9]|(1|2)[0-9]|3[0-1]))|((0(4|6|9)|11)-(0[1-9]|(1|2)[0-9]|30))|(02-(0[1-9]|(1|2)[0-9])))T([0-1][0-9]|2[0-4]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])(\.[0-999])?((\+|-)([0-1][0-9]|2[0-4]):(0[0-9]|[1-5][0-9])|Z)?/Di'; /** @var string */ - private static string $duration_regex = '/^([-+]?)P(?!$)(?:(?\d+(?:[\.\,]\d+)?)Y)?(?:(?\d+(?:[\.\,]\d+)?)M)?(?:(?\d+(?:[\.\,]\d+)?)W)?(?:(?\d+(?:[\.\,]\d+)?)D)?(T(?=\d)(?:(?\d+(?:[\.\,]\d+)?)H)?(?:(?\d+(?:[\.\,]\d+)?)M)?(?:(?\d+(?:[\.\,]\d+)?)S)?)?$/'; + private static string $duration_regex = '/^([-+]?)P(?!$)(?:(?\d+(?:[\.\,]\d+)?)Y)?(?:(?\d+(?:[\.\,]\d+)?)M)?(?:(?\d+(?:[\.\,]\d+)?)W)?(?:(?\d+(?:[\.\,]\d+)?)D)?(T(?=\d)(?:(?\d+(?:[\.\,]\d+)?)H)?(?:(?\d+(?:[\.\,]\d+)?)M)?(?:(?\d+(?:[\.\,]\d+)?)S)?)?$/D'; /** @var string */ - private static string $qname_regex = '/^[a-zA-Z_][\w.-]*:[a-zA-Z_][\w.-]*$/'; + private static string $qname_regex = '/^[a-zA-Z_][\w.-]*:[a-zA-Z_][\w.-]*$/D'; /** @var string */ - private static string $ncname_regex = '/^[a-zA-Z_][\w.-]*$/'; + private static string $ncname_regex = '/^[a-zA-Z_][\w.-]*$/D'; /** @var string */ private static string $base64_regex = '/^(?:[a-z0-9+\/]{4})*(?:[a-z0-9+\/]{2}==|[a-z0-9+\/]{3}=)?$/i'; - /** @var string */ - private static string $hostname_regex = '/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/'; - /*********************************************************************************** * NOTE: Custom assertions may be added below this line. * * They SHOULD be marked as `private` to ensure the call is forced * diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.gitignore b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.gitignore deleted file mode 100644 index ce45e2079..000000000 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -.phpunit.result.cache -composer.lock -composer.phar -/vendor/ - -# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control -# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file -# composer.lock diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.php_cs.dist b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.php_cs.dist deleted file mode 100644 index b861fd268..000000000 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/.php_cs.dist +++ /dev/null @@ -1,15 +0,0 @@ -in([ - __DIR__ . '/src', - __DIR__ . '/tests', - ]) -; - -return PhpCsFixer\Config::create() - ->setRules([ - '@PSR2' => true, - ]) - ->setFinder($finder) -; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/README.md b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/README.md index ba3d6c4c8..6edce8dd8 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/README.md +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/README.md @@ -1,4 +1,4 @@ -# SimpleSAMLphpSimpleSAMLphp Composer module installer +# SimpleSAMLphp Composer module installer ![Build Status](https://github.com/simplesamlphp/composer-module-installer/workflows/CI/badge.svg?branch=master) [![Coverage Status](https://codecov.io/gh/simplesamlphp/composer-module-installer/branch/master/graph/badge.svg)](https://codecov.io/gh/simplesamlphp/composer-module-installer) diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/codecov.yml b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/codecov.yml deleted file mode 100644 index 1e5da3250..000000000 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/codecov.yml +++ /dev/null @@ -1,16 +0,0 @@ -coverage: - status: - project: - default: - target: 0% - threshold: 2% - patch: off -comment: - layout: "diff" - behavior: once - require_changes: true - require_base: no - require_head: yes - branches: null -github_checks: - annotations: false diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpcs.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpcs.xml deleted file mode 100644 index b93cbf3c1..000000000 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpcs.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - By default it is less stringent about long lines than other coding standards - - - src - tests - - - - - diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpunit.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpunit.xml deleted file mode 100644 index a00446c1c..000000000 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/phpunit.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - ./src - - - ./tests - - - - - - - - - - ./tests - - - - diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/psalm.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/psalm.xml deleted file mode 100644 index 7b5e6f56c..000000000 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/psalm.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/src/ModuleInstaller.php b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/src/ModuleInstaller.php index 4a03ff3a4..923d91c1f 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/src/ModuleInstaller.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-module-installer/src/ModuleInstaller.php @@ -36,10 +36,10 @@ public function getInstallPath(PackageInterface $package) */ protected function getPackageBasePath(PackageInterface $package) { - if($this->composer->getPackage()->getPrettyName() === 'simplesamlphp/simplesamlphp') { + if ($this->composer->getPackage()->getPrettyName() === 'simplesamlphp/simplesamlphp') { $ssp_path = "."; } else { - $ssp_path = $this->composer->getConfig()->get('vendor-dir').'/simplesamlphp/simplesamlphp'; + $ssp_path = $this->composer->getConfig()->get('vendor-dir') . '/simplesamlphp/simplesamlphp'; } $matches = []; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/element.registry.e2caf4bd4863521540091558bb31dc3a1899181e.php b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/element.registry.9eadaddda070e6fc2370298410b63dbaf3d3a3eb.php similarity index 95% rename from .extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/element.registry.e2caf4bd4863521540091558bb31dc3a1899181e.php rename to .extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/element.registry.9eadaddda070e6fc2370298410b63dbaf3d3a3eb.php index 5a371ef84..9a55180d1 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/element.registry.e2caf4bd4863521540091558bb31dc3a1899181e.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/composer-xmlprovider-installer/classes/element.registry.9eadaddda070e6fc2370298410b63dbaf3d3a3eb.php @@ -43,10 +43,10 @@ 'InclusiveNamespaces' => '\SimpleSAML\XMLSecurity\XML\ec\InclusiveNamespaces', ], 'http://www.w3.org/2001/04/xmlenc#' => [ -// 'AgreementMethod' => '\SimpleSAML\XMLSecurity\XML\xenc\AgreementMethod', + 'AgreementMethod' => '\SimpleSAML\XMLSecurity\XML\xenc\AgreementMethod', 'CipherData' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherData', 'CipherReference' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherReference', -// 'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue', + 'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue', 'EncryptedData' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedData', 'EncryptedKey' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey', 'EncryptionProperties' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptionProperties', diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/.github/workflows/php.yml b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/.github/workflows/php.yml new file mode 100644 index 000000000..afde3e03d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/.github/workflows/php.yml @@ -0,0 +1,195 @@ +name: CI + +on: + push: + branches: [ '**' ] + pull_request: + branches: [ master, release-* ] + +jobs: + basic-tests: + name: Syntax and unit tests, PHP ${{ matrix.php-versions }}, ${{ matrix.operating-system }} + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest] + php-versions: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] + + steps: + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: ${{ matrix.php-versions }} + ini-values: error_reporting=E_ALL^E_DEPRECATED + extensions: mbstring, xml + coverage: xdebug + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - name: Setup problem matchers for PHPUnit + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Set git to use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - uses: actions/checkout@v3 + + - name: Get composer cache directory (linux) + if: ${{ matrix.operating-system == 'ubuntu-latest' }} + run: echo "COMPOSER_CACHE=$(composer config cache-files-dir)" >> $GITHUB_ENV + + - name: Get composer cache directory (windows) + if: ${{ matrix.operating-system == 'windows-latest' }} + run: echo "COMPOSER_CACHE=$(composer config cache-files-dir)" >> $env:GITHUB_ENV + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: $COMPOSER_CACHE + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Validate composer.json and composer.lock + run: composer validate + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Syntax check PHP + run: bash vendor/bin/check-syntax-php.sh + + - name: Decide whether to run code coverage or not + if: ${{ matrix.php-versions != '8.0' || matrix.operating-system != 'ubuntu-latest' }} + run: | + echo "NO_COVERAGE=--no-coverage" >> $GITHUB_ENV + + - name: Run unit tests + run: | + echo $NO_COVERAGE + ./vendor/bin/phpunit $NO_COVERAGE + + - name: Save coverage data + if: ${{ matrix.php-versions == '8.0' && matrix.operating-system == 'ubuntu-latest' }} + uses: actions/upload-artifact@v3 + with: + name: build-data + path: ${{ github.workspace }}/build + + security: + name: Security checks + runs-on: [ubuntu-latest] + steps: + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: '8.0' + extensions: mbstring, xml + tools: composer:v2 + coverage: none + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - uses: actions/checkout@v3 + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: $COMPOSER_CACHE + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-progress --prefer-dist --optimize-autoloader + + - name: Security check for locked dependencies + uses: symfonycorp/security-checker-action@v3 + + - name: Update Composer dependencies + run: composer update --no-progress --prefer-dist --optimize-autoloader + + - name: Security check for updated dependencies + uses: symfonycorp/security-checker-action@v3 + + sanity-check: + name: Sanity checks + runs-on: [ubuntu-latest] + + steps: + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: '8.0' + extensions: mbstring, xml + coverage: none + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - uses: actions/checkout@v3 + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: $COMPOSER_CACHE + 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: Syntax check YAML / XML / JSON + run: | + bash vendor/bin/check-syntax-yaml.sh + bash vendor/bin/check-syntax-xml.sh + bash vendor/bin/check-syntax-json.sh + + quality: + name: Quality control + runs-on: [ubuntu-latest] + needs: [basic-tests] + + steps: + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: '8.0' + extensions: mbstring, xml + + - name: Setup problem matchers for PHP + run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" + + - uses: actions/checkout@v3 + + - name: Cache composer dependencies + uses: actions/cache@v3 + with: + path: $COMPOSER_CACHE + 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 + + - uses: actions/download-artifact@v3 + with: + name: build-data + path: ${{ github.workspace }}/build + + - name: Codecov + uses: codecov/codecov-action@v3 + + - name: PHP Code Sniffer + continue-on-error: true + run: php vendor/bin/phpcs src/ + + - name: Psalm + continue-on-error: true + run: php vendor/bin/psalm --show-info=true + + - name: Psalter + run: php vendor/bin/psalter --issues=UnnecessaryVarAnnotation --dry-run diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/LICENSE b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/LICENSE new file mode 100644 index 000000000..a48e6e374 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/LICENSE @@ -0,0 +1,458 @@ +GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/README.md b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/README.md new file mode 100644 index 000000000..54241fabd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/README.md @@ -0,0 +1,78 @@ +SimpleSAMLphp SAML2 library +=========================== +[![Build Status](https://travis-ci.org/simplesamlphp/saml2.png?branch=feature/fix-build)](https://travis-ci.org/simplesamlphp/saml2) [![Coverage Status](https://img.shields.io/coveralls/simplesamlphp/saml2.svg)](https://coveralls.io/r/simplesamlphp/saml2) + + +A PHP library for SAML2 related functionality. Extracted from [SimpleSAMLphp](https://www.simplesamlphp.org), +used by [OpenConext](https://www.openconext.org). +This library started as a collaboration between [UNINETT](https://www.uninett.no) and [SURFnet](https://www.surfnet.nl) but everyone is invited to contribute. + + +Before you use it +----------------- +**DO NOT USE THIS LIBRARY UNLESS YOU ARE INTIMATELY FAMILIAR WITH THE SAML2 SPECIFICATION.** + +If you are not familiar with the SAML2 specification and are simply looking to connect your application using SAML2, +you should probably use [SimpleSAMLphp](https://www.simplesamlphp.org). + +Note that the **HTTP Artifact Binding and SOAP client do not work** outside of SimpleSAMLphp. + +Which version to pick? +---------------------- +The latest released version (`4.x` range) is the _only supported version_. + +All other branches (`3.x` and earlier) are no longer supported and will not receive any maintenance or +(security) fixes. Do not use these versions. + +Also be sure to check the [UPGRADING.md](UPGRADING.md) file if you are upgrading from an older version to `>= 4.x`. Here +you will find instructions on how to deal with BC breaking changes between versions. + +Usage +----- + +* Install with [Composer](https://getcomposer.org/doc/00-intro.md), run the following command in your project: + +```bash +composer require simplesamlphp/saml2:^4.0 +``` + +* Provide the required external dependencies by extending and implementing the ```SAML2\Compat\AbstractContainer``` + then injecting it in the ContainerSingleton (see example below). + +* **Make sure you've read the security section below**. + +* Use at will. +Example: +```php + // Use Composers autoloading + require 'vendor/autoload.php'; + + // Implement the Container interface (out of scope for example) + require 'container.php'; + SAML2\Compat\ContainerSingleton::setContainer($container); + + // Set up an AuthnRequest + $request = new SAML2\AuthnRequest(); + $request->setId($container->generateId()); + $issuer = new SAML2\XML\saml\Issuer(); + $issuer->setValue('https://sp.example.edu'); + $request->setIssuer($issuer); + $request->setDestination('https://idp.example.edu'); + + // Send it off using the HTTP-Redirect binding + $binding = new SAML2\HTTPRedirect(); + $binding->send($request); +``` + +Security +-------- +* Should you need to create a DOMDocument instance, use the `SAML2\DOMDocumentFactory` to create DOMDocuments from + either a string (`SAML2\DOMDocumentFactory::fromString($theXmlAsString)`), a file (`SAML2\DOMDocumentFactory::fromFile($pathToTheFile)`) + or just a new instance (`SAML2\DOMDocumentFactory::create()`). This in order to protect yourself against the + [XXE Processing Vulnerability](https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Processing), as well as + [XML Entity Expansion](https://phpsecurity.readthedocs.org/en/latest/Injection-Attacks.html#defenses-against-xml-entity-expansion) attacks + +License +------- +This library is licensed under the LGPL license version 2.1. +For more details see [LICENSE](https://raw.github.com/simplesamlphp/saml2/master/LICENSE). diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/composer.json b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/composer.json new file mode 100644 index 000000000..4b6fad87c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/composer.json @@ -0,0 +1,53 @@ +{ + "name": "simplesamlphp/saml2-legacy", + "description": "SAML2 PHP library from SimpleSAMLphp", + "license": "LGPL-2.1-or-later", + "authors": [ + { + "name": "Andreas Åkre Solberg", + "email": "andreas.solberg@uninett.no" + } + ], + "require": { + "php": ">=7.1 || ^8.0", + "ext-openssl": "*", + "ext-dom": "*", + "ext-zlib": "*", + + "psr/log": "~1.1 || ^2.0 || ^3.0", + "robrichards/xmlseclibs": "^3.1.1", + "webmozart/assert": "^1.9" + }, + "conflict": { + "robrichards/xmlseclibs": "3.1.2" + }, + "require-dev": { + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "simplesamlphp/simplesamlphp-test-framework": "~0.1.0", + "sebastian/phpcpd": "~4.1 || ^5.0 || ^6.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "autoload": { + "psr-4": { + "SAML2\\": "src/SAML2" + } + }, + "autoload-dev": { + "psr-4": { + "Test\\SAML2\\": "tests/SAML2/", + "SAML2\\": "tests/SAML2/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "v4.2.x-dev" + } + }, + "config": { + "allow-plugins": { + "composer/package-versions-deprecated": true, + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-assertion-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-assertion-2.0.xsd new file mode 100644 index 000000000..2b2f7b801 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-assertion-2.0.xsd @@ -0,0 +1,283 @@ + + + + + + + Document identifier: saml-schema-assertion-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V1.0 (November, 2002): + Initial Standard Schema. + V1.1 (September, 2003): + Updates within the same V1.0 namespace. + V2.0 (March, 2005): + New assertion schema for SAML V2.0 namespace. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-2.0.xsd new file mode 100644 index 000000000..e4754faf8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-2.0.xsd @@ -0,0 +1,23 @@ + + + + + + Document identifier: saml-schema-authn-context-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New core authentication context schema for SAML V2.0. + This is just an include of all types from the schema + referred to in the include statement below. + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-auth-telephony-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-auth-telephony-2.0.xsd new file mode 100644 index 000000000..da59934be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-auth-telephony-2.0.xsd @@ -0,0 +1,81 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:AuthenticatedTelephony + Document identifier: saml-schema-authn-context-auth-telephony-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ip-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ip-2.0.xsd new file mode 100644 index 000000000..d4e7dfba1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ip-2.0.xsd @@ -0,0 +1,65 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol + Document identifier: saml-schema-authn-context-ip-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ippword-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ippword-2.0.xsd new file mode 100644 index 000000000..708f59643 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ippword-2.0.xsd @@ -0,0 +1,67 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword + Document identifier: saml-schema-authn-context-ippword-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-kerberos-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-kerberos-2.0.xsd new file mode 100644 index 000000000..4b6a3a5da --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-kerberos-2.0.xsd @@ -0,0 +1,83 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos + Document identifier: saml-schema-authn-context-kerberos-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-reg-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-reg-2.0.xsd new file mode 100644 index 000000000..f72443437 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-reg-2.0.xsd @@ -0,0 +1,186 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract + Document identifier: saml-schema-authn-context-mobileonefactor-reg-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-unreg-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-unreg-2.0.xsd new file mode 100644 index 000000000..9727c45fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobileonefactor-unreg-2.0.xsd @@ -0,0 +1,183 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorUnregistered + Document identifier: saml-schema-authn-context-mobileonefactor-unreg-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-reg-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-reg-2.0.xsd new file mode 100644 index 000000000..d0c59aa13 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-reg-2.0.xsd @@ -0,0 +1,202 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract + Document identifier: saml-schema-authn-context-mobiletwofactor-reg-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-unreg-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-unreg-2.0.xsd new file mode 100644 index 000000000..1a4578cd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-mobiletwofactor-unreg-2.0.xsd @@ -0,0 +1,200 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorUnregistered + Document identifier: saml-schema-authn-context-mobiletwofactor-unreg-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-nomad-telephony-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-nomad-telephony-2.0.xsd new file mode 100644 index 000000000..0eb861f93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-nomad-telephony-2.0.xsd @@ -0,0 +1,81 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:NomadTelephony + Document identifier: saml-schema-authn-context-nomad-telephony-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-personal-telephony-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-personal-telephony-2.0.xsd new file mode 100644 index 000000000..a9eebf425 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-personal-telephony-2.0.xsd @@ -0,0 +1,80 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:PersonalizedTelephony + Document identifier: saml-schema-authn-context-personal-telephony-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pgp-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pgp-2.0.xsd new file mode 100644 index 000000000..74c73c1c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pgp-2.0.xsd @@ -0,0 +1,83 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:PGP + Document identifier: saml-schema-authn-context-pgp-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ppt-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ppt-2.0.xsd new file mode 100644 index 000000000..257296541 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-ppt-2.0.xsd @@ -0,0 +1,81 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + Document identifier: saml-schema-authn-context-ppt-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pword-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pword-2.0.xsd new file mode 100644 index 000000000..0c18a42c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-pword-2.0.xsd @@ -0,0 +1,64 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:Password + Document identifier: saml-schema-authn-context-pword-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-session-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-session-2.0.xsd new file mode 100644 index 000000000..77ef000ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-session-2.0.xsd @@ -0,0 +1,64 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession + Document identifier: saml-schema-authn-context-session-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcard-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcard-2.0.xsd new file mode 100644 index 000000000..1bd084a41 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcard-2.0.xsd @@ -0,0 +1,64 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard + Document identifier: saml-schema-authn-context-smartcard-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcardpki-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcardpki-2.0.xsd new file mode 100644 index 000000000..0508d4d5d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-smartcardpki-2.0.xsd @@ -0,0 +1,129 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI + Document identifier: saml-schema-authn-context-smartcardpki-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-softwarepki-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-softwarepki-2.0.xsd new file mode 100644 index 000000000..5c41a2f24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-softwarepki-2.0.xsd @@ -0,0 +1,129 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:SoftwarePKI + Document identifier: saml-schema-authn-context-softwarepki-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-spki-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-spki-2.0.xsd new file mode 100644 index 000000000..ce57d7957 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-spki-2.0.xsd @@ -0,0 +1,83 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:SPKI + Document identifier: saml-schema-authn-context-spki-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-srp-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-srp-2.0.xsd new file mode 100644 index 000000000..9051dd5ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-srp-2.0.xsd @@ -0,0 +1,82 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword + Document identifier: saml-schema-authn-context-srp-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-sslcert-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-sslcert-2.0.xsd new file mode 100644 index 000000000..723103b00 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-sslcert-2.0.xsd @@ -0,0 +1,97 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient + Document identifier: saml-schema-authn-context-sslcert-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-telephony-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-telephony-2.0.xsd new file mode 100644 index 000000000..15ff75313 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-telephony-2.0.xsd @@ -0,0 +1,79 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:Telephony + Document identifier: saml-schema-authn-context-telephony-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-timesync-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-timesync-2.0.xsd new file mode 100644 index 000000000..afc92f398 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-timesync-2.0.xsd @@ -0,0 +1,105 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken + Document identifier: saml-schema-authn-context-timesync-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-types-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-types-2.0.xsd new file mode 100644 index 000000000..8513959a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-types-2.0.xsd @@ -0,0 +1,821 @@ + + + + + + Document identifier: saml-schema-authn-context-types-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New core authentication context schema types for SAML V2.0. + + + + + + + A particular assertion on an identity + provider's part with respect to the authentication + context associated with an authentication assertion. + + + + + + + + Refers to those characteristics that describe the + processes and mechanisms + the Authentication Authority uses to initially create + an association between a Principal + and the identity (or name) by which the Principal will + be known + + + + + + + + This element indicates that identification has been + performed in a physical + face-to-face meeting with the principal and not in an + online manner. + + + + + + + + + + + + + + + + + + + + Refers to those characterstics that describe how the + 'secret' (the knowledge or possession + of which allows the Principal to authenticate to the + Authentication Authority) is kept secure + + + + + + + + This element indicates the types and strengths of + facilities + of a UA used to protect a shared secret key from + unauthorized access and/or use. + + + + + + + + This element indicates the types and strengths of + facilities + of a UA used to protect a private key from + unauthorized access and/or use. + + + + + + + The actions that must be performed + before the private key can be used. + + + + + + Whether or not the private key is shared + with the certificate authority. + + + + + + + In which medium is the key stored. + memory - the key is stored in memory. + smartcard - the key is stored in a smartcard. + token - the key is stored in a hardware token. + MobileDevice - the key is stored in a mobile device. + MobileAuthCard - the key is stored in a mobile + authentication card. + + + + + + + + + + + This element indicates that a password (or passphrase) + has been used to + authenticate the Principal to a remote system. + + + + + + + + This element indicates that a Pin (Personal + Identification Number) has been used to authenticate the Principal to + some local system in order to activate a key. + + + + + + + + This element indicates that a hardware or software + token is used + as a method of identifying the Principal. + + + + + + + + This element indicates that a time synchronization + token is used to identify the Principal. hardware - + the time synchonization + token has been implemented in hardware. software - the + time synchronization + token has been implemented in software. SeedLength - + the length, in bits, of the + random seed used in the time synchronization token. + + + + + + + + This element indicates that a smartcard is used to + identity the Principal. + + + + + + + + This element indicates the minimum and/or maximum + ASCII length of the password which is enforced (by the UA or the + IdP). In other words, this is the minimum and/or maximum number of + ASCII characters required to represent a valid password. + min - the minimum number of ASCII characters required + in a valid password, as enforced by the UA or the IdP. + max - the maximum number of ASCII characters required + in a valid password, as enforced by the UA or the IdP. + + + + + + + + This element indicates the length of time for which an + PIN-based authentication is valid. + + + + + + + + Indicates whether the password was chosen by the + Principal or auto-supplied by the Authentication Authority. + principalchosen - the Principal is allowed to choose + the value of the password. This is true even if + the initial password is chosen at random by the UA or + the IdP and the Principal is then free to change + the password. + automatic - the password is chosen by the UA or the + IdP to be cryptographically strong in some sense, + or to satisfy certain password rules, and that the + Principal is not free to change it or to choose a new password. + + + + + + + + + + + + + + + + + + + Refers to those characteristics that define the + mechanisms by which the Principal authenticates to the Authentication + Authority. + + + + + + + + The method that a Principal employs to perform + authentication to local system components. + + + + + + + + The method applied to validate a principal's + authentication across a network + + + + + + + + Supports Authenticators with nested combinations of + additional complexity. + + + + + + + + Indicates that the Principal has been strongly + authenticated in a previous session during which the IdP has set a + cookie in the UA. During the present session the Principal has only + been authenticated by the UA returning the cookie to the IdP. + + + + + + + + Rather like PreviousSession but using stronger + security. A secret that was established in a previous session with + the Authentication Authority has been cached by the local system and + is now re-used (e.g. a Master Secret is used to derive new session + keys in TLS, SSL, WTLS). + + + + + + + + This element indicates that the Principal has been + authenticated by a zero knowledge technique as specified in ISO/IEC + 9798-5. + + + + + + + + + + This element indicates that the Principal has been + authenticated by a challenge-response protocol utilizing shared secret + keys and symmetric cryptography. + + + + + + + + + + + + This element indicates that the Principal has been + authenticated by a mechanism which involves the Principal computing a + digital signature over at least challenge data provided by the IdP. + + + + + + + + The local system has a private key but it is used + in decryption mode, rather than signature mode. For example, the + Authentication Authority generates a secret and encrypts it using the + local system's public key: the local system then proves it has + decrypted the secret. + + + + + + + + The local system has a private key and uses it for + shared secret key agreement with the Authentication Authority (e.g. + via Diffie Helman). + + + + + + + + + + + + + + + This element indicates that the Principal has been + authenticated through connection from a particular IP address. + + + + + + + + The local system and Authentication Authority + share a secret key. The local system uses this to encrypt a + randomised string to pass to the Authentication Authority. + + + + + + + + The protocol across which Authenticator information is + transferred to an Authentication Authority verifier. + + + + + + + + This element indicates that the Authenticator has been + transmitted using bare HTTP utilizing no additional security + protocols. + + + + + + + + This element indicates that the Authenticator has been + transmitted using a transport mechanism protected by an IPSEC session. + + + + + + + + This element indicates that the Authenticator has been + transmitted using a transport mechanism protected by a WTLS session. + + + + + + + + This element indicates that the Authenticator has been + transmitted solely across a mobile network using no additional + security mechanism. + + + + + + + + + + + This element indicates that the Authenticator has been + transmitted using a transport mechnanism protected by an SSL or TLS + session. + + + + + + + + + + + + Refers to those characteristics that describe + procedural security controls employed by the Authentication Authority. + + + + + + + + + + + + Provides a mechanism for linking to external (likely + human readable) documents in which additional business agreements, + (e.g. liability constraints, obligations, etc) can be placed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This attribute indicates whether or not the + Identification mechanisms allow the actions of the Principal to be + linked to an actual end user. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element indicates that the Key Activation Limit is + defined as a specific duration of time. + + + + + + + + This element indicates that the Key Activation Limit is + defined as a number of usages. + + + + + + + + This element indicates that the Key Activation Limit is + the session. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-x509-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-x509-2.0.xsd new file mode 100644 index 000000000..ce4bd65e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-x509-2.0.xsd @@ -0,0 +1,83 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:X509 + Document identifier: saml-schema-authn-context-x509-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-xmldsig-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-xmldsig-2.0.xsd new file mode 100644 index 000000000..61fe0ac8e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-authn-context-xmldsig-2.0.xsd @@ -0,0 +1,83 @@ + + + + + + + + + Class identifier: urn:oasis:names:tc:SAML:2.0:ac:classes:XMLDSig + Document identifier: saml-schema-authn-context-xmldsig-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + New authentication context class schema for SAML V2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-dce-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-dce-2.0.xsd new file mode 100644 index 000000000..e89be866a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-dce-2.0.xsd @@ -0,0 +1,29 @@ + + + + + Document identifier: saml-schema-dce-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + Custom schema for DCE attribute profile, first published in SAML 2.0. + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-ecp-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-ecp-2.0.xsd new file mode 100644 index 000000000..e3f24b9a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-ecp-2.0.xsd @@ -0,0 +1,57 @@ + + + + + + + + Document identifier: saml-schema-ecp-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + Custom schema for ECP profile, first published in SAML 2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-metadata-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-metadata-2.0.xsd new file mode 100644 index 000000000..b656d4f41 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-metadata-2.0.xsd @@ -0,0 +1,337 @@ + + + + + + + + + Document identifier: saml-schema-metadata-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + Schema for SAML metadata, first published in SAML 2.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-protocol-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-protocol-2.0.xsd new file mode 100644 index 000000000..7fa6f489d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-protocol-2.0.xsd @@ -0,0 +1,302 @@ + + + + + + + Document identifier: saml-schema-protocol-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V1.0 (November, 2002): + Initial Standard Schema. + V1.1 (September, 2003): + Updates within the same V1.0 namespace. + V2.0 (March, 2005): + New protocol schema based in a SAML V2.0 namespace. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-x500-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-x500-2.0.xsd new file mode 100644 index 000000000..f67f1b04a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-x500-2.0.xsd @@ -0,0 +1,20 @@ + + + + + Document identifier: saml-schema-x500-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + Custom schema for X.500 attribute profile, first published in SAML 2.0. + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-xacml-2.0.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-xacml-2.0.xsd new file mode 100644 index 000000000..836f9db04 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/saml-schema-xacml-2.0.xsd @@ -0,0 +1,19 @@ + + + + + Document identifier: saml-schema-xacml-2.0 + Location: http://docs.oasis-open.org/security/saml/v2.0/ + Revision history: + V2.0 (March, 2005): + Custom schema for XACML attribute profile, first published in SAML 2.0. + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xenc-schema.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xenc-schema.xsd new file mode 100644 index 000000000..d61229fd5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xenc-schema.xsd @@ -0,0 +1,146 @@ + + + + + + ]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xml.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xml.xsd new file mode 100644 index 000000000..aea7d0db0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xml.xsd @@ -0,0 +1,287 @@ + + + + + + +
    +

    About the XML namespace

    + +
    +

    + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

    +

    + See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

    +

    + Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

    +

    + See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

    +
    +
    +
    +
    + + + + +
    + +

    lang (as an attribute name)

    +

    + denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

    + +
    +
    +

    Notes

    +

    + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

    +

    + See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

    +

    + The union allows for the 'un-declaration' of xml:lang with + the empty string. +

    +
    +
    +
    + + + + + + + + + +
    + + + + +
    + +

    space (as an attribute name)

    +

    + denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

    + +
    +
    +
    + + + + + + +
    + + + +
    + +

    base (as an attribute name)

    +

    + denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

    + +

    + See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

    +
    +
    +
    +
    + + + + +
    + +

    id (as an attribute name)

    +

    + denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

    + +

    + See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

    +
    +
    +
    +
    + + + + + + + + + + +
    + +

    Father (in any context at all)

    + +
    +

    + denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

    +
    +

    + In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

    +
    +
    +
    +
    +
    + + + +
    +

    About this schema document

    + +
    +

    + This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

    +

    + To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

    +
    +          <schema . . .>
    +           . . .
    +           <import namespace="http://www.w3.org/XML/1998/namespace"
    +                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
    +     
    +

    + or +

    +
    +           <import namespace="http://www.w3.org/XML/1998/namespace"
    +                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
    +     
    +

    + Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

    +
    +          <type . . .>
    +           . . .
    +           <attributeGroup ref="xml:specialAttrs"/>
    +     
    +

    + will define a type which will schema-validate an instance element + with any of those attributes. +

    +
    +
    +
    +
    + + + +
    +

    Versioning policy for this schema document

    +
    +

    + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

    +

    + At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

    +

    + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

    +

    + Previous dated (and unchanging) versions of this schema + document are at: +

    + +
    +
    +
    +
    + +
    + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xmldsig-core-schema.xsd b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xmldsig-core-schema.xsd new file mode 100644 index 000000000..df126b30e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/schemas/xmldsig-core-schema.xsd @@ -0,0 +1,318 @@ + + + + + + ]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResolve.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResolve.php new file mode 100644 index 000000000..651864e92 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResolve.php @@ -0,0 +1,74 @@ + + * @package SimpleSAMLphp + */ +class ArtifactResolve extends Request +{ + /** @var string */ + private $artifact; + + + /** + * Constructor for SAML 2 ArtifactResolve. + * + * @param \DOMElement|null $xml The input assertion. + */ + public function __construct(DOMElement $xml = null) + { + parent::__construct('ArtifactResolve', $xml); + + if (!is_null($xml)) { + $results = Utils::xpQuery($xml, './saml_protocol:Artifact'); + $this->artifact = $results[0]->textContent; + } + } + + /** + * Retrieve the Artifact in this response. + * + * @return string artifact. + */ + public function getArtifact() : string + { + return $this->artifact; + } + + + /** + * Set the artifact that should be included in this response. + * + * @param string $artifact + * @return void + */ + public function setArtifact(string $artifact) : void + { + $this->artifact = $artifact; + } + + + /** + * Convert the response message to an XML element. + * + * @return \DOMElement This response. + */ + public function toUnsignedXML() : DOMElement + { + $root = parent::toUnsignedXML(); + $artifactelement = $this->document->createElementNS(Constants::NS_SAMLP, 'Artifact', $this->artifact); + $root->appendChild($artifactelement); + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResponse.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResponse.php new file mode 100644 index 000000000..f398c3d49 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/ArtifactResponse.php @@ -0,0 +1,87 @@ + + * @package SimpleSAMLphp + */ +class ArtifactResponse extends StatusResponse +{ + /** + * The \DOMElement with the message the artifact refers + * to, or null if we don't refer to any artifact. + * + * @var \DOMElement|null + */ + private $any = null; + + + /** + * Constructor for SAML 2 ArtifactResponse. + * + * @param \DOMElement|null $xml The input assertion. + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + parent::__construct('ArtifactResponse', $xml); + + if (!is_null($xml)) { + $status = Utils::xpQuery($xml, './saml_protocol:Status'); + $status = $status[0]; + + /** @psalm-suppress RedundantCondition */ + for ($any = $status->nextSibling; $any instanceof DOMNode; $any = $any->nextSibling) { + if ($any instanceof DOMElement) { + $this->any = $any; + break; + } + /* Ignore comments and text nodes. */ + } + } + } + + + /** + * @param \DOMElement|null $any + * @return void + */ + public function setAny(DOMElement $any = null) : void + { + $this->any = $any; + } + + + /** + * @return \DOMElement|null + */ + public function getAny() : ?DOMElement + { + return $this->any; + } + + + /** + * Convert the response message to an XML element. + * + * @return \DOMElement This response. + */ + public function toUnsignedXML() : DOMElement + { + $root = parent::toUnsignedXML(); + if (isset($this->any)) { + $node = $root->ownerDocument->importNode($this->any, true); + $root->appendChild($node); + } + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion.php new file mode 100644 index 000000000..48f1b4cbc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion.php @@ -0,0 +1,1821 @@ + => [|null, |null, ...] + * array will always have the same size of the array of vaules in $attributes for the same + * + * when generating assertion, the varuable can be: + * - null : backward compatibility + * - => : all values for the given attribute will have the same xs type + * - => [|null, |null, ...] : Nth value will have type of the + * Nth in the array + * + * @var array multi-dimensional array of array + */ + private $attributesValueTypes = []; + + /** + * The NameFormat used on all attributes. + * + * If more than one NameFormat is used, this will contain the unspecified nameformat. + * + * @var string + */ + private $nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + + /** + * The data needed to verify the signature. + * + * @var array|null + */ + private $signatureData = null; + + /** + * Boolean that indicates if attributes are encrypted in the assertion or not. + * + * @var boolean + */ + private $requiredEncAttributes = false; + + /** + * The SubjectConfirmation elements of the Subject in the assertion. + * + * @var \SAML2\XML\saml\SubjectConfirmation[] + */ + private $SubjectConfirmation = []; + + /** + * @var bool + */ + protected $wasSignedAtConstruction = false; + + /** + * @var string|null + */ + private $signatureMethod; + + + /** + * Constructor for SAML 2 assertions. + * + * @param \DOMElement|null $xml The input assertion. + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + // Create an Issuer + $issuer = new Issuer(); + $issuer->setValue(''); + + $this->id = Utils::getContainer()->generateId(); + $this->issueInstant = Temporal::getTime(); + $this->issuer = $issuer; + $this->authnInstant = Temporal::getTime(); + + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('ID')) { + throw new \Exception('Missing ID attribute on SAML assertion.'); + } + $this->id = $xml->getAttribute('ID'); + + if ($xml->getAttribute('Version') !== '2.0') { + /* Currently a very strict check. */ + throw new \Exception('Unsupported version: '.$xml->getAttribute('Version')); + } + + $this->issueInstant = Utils::xsDateTimeToTimestamp($xml->getAttribute('IssueInstant')); + + /** @var \DOMElement[] $issuer */ + $issuer = Utils::xpQuery($xml, './saml_assertion:Issuer'); + if (empty($issuer)) { + throw new \Exception('Missing in assertion.'); + } + + $this->issuer = new Issuer($issuer[0]); + + $this->parseSubject($xml); + $this->parseConditions($xml); + $this->parseAuthnStatement($xml); + $this->parseAttributes($xml); + $this->parseEncryptedAttributes($xml); + $this->parseSignature($xml); + } + + + /** + * Parse subject in assertion. + * + * @param \DOMElement $xml The assertion XML element. + * @throws \Exception + * @return void + */ + private function parseSubject(DOMElement $xml) : void + { + /** @var \DOMElement[] $subject */ + $subject = Utils::xpQuery($xml, './saml_assertion:Subject'); + if (empty($subject)) { + /* No Subject node. */ + + return; + } elseif (count($subject) > 1) { + throw new \Exception('More than one in .'); + } + $subject = $subject[0]; + + /** @var \DOMElement[] $nameId */ + $nameId = Utils::xpQuery( + $subject, + './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData' + ); + if (count($nameId) > 1) { + throw new \Exception('More than one or in .'); + } elseif (!empty($nameId)) { + $nameId = $nameId[0]; + if ($nameId->localName === 'EncryptedData') { + /* The NameID element is encrypted. */ + $this->encryptedNameId = $nameId; + } else { + $this->nameId = new NameID($nameId); + } + } + + /** @var \DOMElement[] $subjectConfirmation */ + $subjectConfirmation = Utils::xpQuery($subject, './saml_assertion:SubjectConfirmation'); + if (empty($subjectConfirmation) && empty($nameId)) { + throw new \Exception('Missing in .'); + } + + foreach ($subjectConfirmation as $sc) { + $this->SubjectConfirmation[] = new SubjectConfirmation($sc); + } + } + + + /** + * Parse conditions in assertion. + * + * @param \DOMElement $xml The assertion XML element. + * @throws \Exception + * @return void + */ + private function parseConditions(DOMElement $xml) : void + { + /** @var \DOMElement[] $conditions */ + $conditions = Utils::xpQuery($xml, './saml_assertion:Conditions'); + if (empty($conditions)) { + /* No node. */ + + return; + } elseif (count($conditions) > 1) { + throw new \Exception('More than one in .'); + } + $conditions = $conditions[0]; + + if ($conditions->hasAttribute('NotBefore')) { + $notBefore = Utils::xsDateTimeToTimestamp($conditions->getAttribute('NotBefore')); + if ($this->getNotBefore() === null || $this->getNotBefore() < $notBefore) { + $this->setNotBefore($notBefore); + } + } + if ($conditions->hasAttribute('NotOnOrAfter')) { + $notOnOrAfter = Utils::xsDateTimeToTimestamp($conditions->getAttribute('NotOnOrAfter')); + if ($this->getNotOnOrAfter() === null || $this->getNotOnOrAfter() > $notOnOrAfter) { + $this->setNotOnOrAfter($notOnOrAfter); + } + } + + foreach ($conditions->childNodes as $node) { + if (!$node instanceof DOMElement) { + continue; + } + if ($node->namespaceURI !== Constants::NS_SAML) { + throw new \Exception('Unknown namespace of condition: '.var_export($node->namespaceURI, true)); + } + switch ($node->localName) { + case 'AudienceRestriction': + $audiences = Utils::extractStrings($node, Constants::NS_SAML, 'Audience'); + if ($this->validAudiences === null) { + /* The first (and probably last) AudienceRestriction element. */ + $this->validAudiences = $audiences; + } else { + /* + * The set of AudienceRestriction are ANDed together, so we need + * the subset that are present in all of them. + */ + $this->validAudiences = array_intersect($this->validAudiences, $audiences); + } + break; + case 'OneTimeUse': + /* Currently ignored. */ + break; + case 'ProxyRestriction': + /* Currently ignored. */ + break; + default: + throw new \Exception('Unknown condition: '.var_export($node->localName, true)); + } + } + } + + + /** + * Parse AuthnStatement in assertion. + * + * @param \DOMElement $xml The assertion XML element. + * @throws \Exception + * @return void + */ + private function parseAuthnStatement(DOMElement $xml) : void + { + /** @var \DOMElement[] $authnStatements */ + $authnStatements = Utils::xpQuery($xml, './saml_assertion:AuthnStatement'); + if (empty($authnStatements)) { + $this->authnInstant = null; + + return; + } elseif (count($authnStatements) > 1) { + throw new \Exception('More than one in not supported.'); + } + $authnStatement = $authnStatements[0]; + + if (!$authnStatement->hasAttribute('AuthnInstant')) { + throw new \Exception('Missing required AuthnInstant attribute on .'); + } + $this->authnInstant = Utils::xsDateTimeToTimestamp($authnStatement->getAttribute('AuthnInstant')); + + if ($authnStatement->hasAttribute('SessionNotOnOrAfter')) { + $this->sessionNotOnOrAfter = Utils::xsDateTimeToTimestamp( + $authnStatement->getAttribute('SessionNotOnOrAfter') + ); + } + + if ($authnStatement->hasAttribute('SessionIndex')) { + $this->sessionIndex = $authnStatement->getAttribute('SessionIndex'); + } + + $this->parseAuthnContext($authnStatement); + } + + + /** + * Parse AuthnContext in AuthnStatement. + * + * @param \DOMElement $authnStatementEl + * @throws \Exception + * @return void + */ + private function parseAuthnContext(DOMElement $authnStatementEl) : void + { + // Get the AuthnContext element + /** @var \DOMElement[] $authnContexts */ + $authnContexts = Utils::xpQuery($authnStatementEl, './saml_assertion:AuthnContext'); + if (count($authnContexts) > 1) { + throw new \Exception('More than one in .'); + } elseif (empty($authnContexts)) { + throw new \Exception('Missing required in .'); + } + $authnContextEl = $authnContexts[0]; + + // Get the AuthnContextDeclRef (if available) + /** @var \DOMElement[] $authnContextDeclRefs */ + $authnContextDeclRefs = Utils::xpQuery($authnContextEl, './saml_assertion:AuthnContextDeclRef'); + if (count($authnContextDeclRefs) > 1) { + throw new \Exception( + 'More than one found?' + ); + } elseif (count($authnContextDeclRefs) === 1) { + $this->setAuthnContextDeclRef(trim($authnContextDeclRefs[0]->textContent)); + } + + // Get the AuthnContextDecl (if available) + /** @var \DOMElement[] $authnContextDecls */ + $authnContextDecls = Utils::xpQuery($authnContextEl, './saml_assertion:AuthnContextDecl'); + if (count($authnContextDecls) > 1) { + throw new \Exception( + 'More than one found?' + ); + } elseif (count($authnContextDecls) === 1) { + $this->setAuthnContextDecl(new Chunk($authnContextDecls[0])); + } + + // Get the AuthnContextClassRef (if available) + /** @var \DOMElement[] $authnContextClassRefs */ + $authnContextClassRefs = Utils::xpQuery($authnContextEl, './saml_assertion:AuthnContextClassRef'); + if (count($authnContextClassRefs) > 1) { + throw new \Exception('More than one in .'); + } elseif (count($authnContextClassRefs) === 1) { + $this->setAuthnContextClassRef(trim($authnContextClassRefs[0]->textContent)); + } + + // Constraint from XSD: MUST have one of the three + if (empty($this->authnContextClassRef) && empty($this->authnContextDecl) && empty($this->authnContextDeclRef)) { + throw new \Exception( + 'Missing either or or ' + ); + } + + $this->AuthenticatingAuthority = Utils::extractStrings( + $authnContextEl, + Constants::NS_SAML, + 'AuthenticatingAuthority' + ); + } + + + /** + * Parse attribute statements in assertion. + * + * @param \DOMElement $xml The XML element with the assertion. + * @throws \Exception + * @return void + */ + private function parseAttributes(DOMElement $xml) : void + { + $firstAttribute = true; + /** @var \DOMElement[] $attributes */ + $attributes = Utils::xpQuery($xml, './saml_assertion:AttributeStatement/saml_assertion:Attribute'); + foreach ($attributes as $attribute) { + if (!$attribute->hasAttribute('Name')) { + throw new \Exception('Missing name on element.'); + } + $name = $attribute->getAttribute('Name'); + + if ($attribute->hasAttribute('NameFormat')) { + $nameFormat = $attribute->getAttribute('NameFormat'); + } else { + $nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + } + + if ($firstAttribute) { + $this->nameFormat = $nameFormat; + $firstAttribute = false; + } else { + if ($this->nameFormat !== $nameFormat) { + $this->nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + } + } + + if (!array_key_exists($name, $this->attributes)) { + $this->attributes[$name] = []; + $this->attributesValueTypes[$name] = []; + } + + $this->parseAttributeValue($attribute, $name); + } + } + + + /** + * @param \DOMNode $attribute + * @param string $attributeName + * @return void + */ + private function parseAttributeValue(DOMNode $attribute, string $attributeName) : void + { + /** @var \DOMElement[] $values */ + $values = Utils::xpQuery($attribute, './saml_assertion:AttributeValue'); + + if ($attributeName === Constants::EPTI_URN_MACE || $attributeName === Constants::EPTI_URN_OID) { + foreach ($values as $index => $eptiAttributeValue) { + /** @var \DOMElement[] $eptiNameId */ + $eptiNameId = Utils::xpQuery($eptiAttributeValue, './saml_assertion:NameID'); + + if (count($eptiNameId) === 1) { + $this->attributes[$attributeName][] = new NameID($eptiNameId[0]); + } else { + /* Fall back for legacy IdPs sending string value (e.g. SSP < 1.15) */ + Utils::getContainer()->getLogger()->warning( + sprintf("Attribute %s (EPTI) value %d is not an XML NameId", $attributeName, $index) + ); + $nameId = new NameID(); + $nameId->setValue($eptiAttributeValue->textContent); + $this->attributes[$attributeName][] = $nameId; + } + } + + return; + } + + foreach ($values as $value) { + $hasNonTextChildElements = false; + foreach ($value->childNodes as $childNode) { + /** @var \DOMNode $childNode */ + if ($childNode->nodeType !== XML_TEXT_NODE) { + $hasNonTextChildElements = true; + break; + } + } + + $type = $value->getAttribute('xsi:type'); + if ($type === '') { + $type = null; + } + $this->attributesValueTypes[$attributeName][] = $type; + + if ($hasNonTextChildElements) { + $this->attributes[$attributeName][] = $value->childNodes; + continue; + } + + if ($type === 'xs:integer') { + $this->attributes[$attributeName][] = (int) $value->textContent; + } else { + $this->attributes[$attributeName][] = trim($value->textContent); + } + } + } + + + /** + * Parse encrypted attribute statements in assertion. + * + * @param \DOMElement $xml The XML element with the assertion. + * @return void + */ + private function parseEncryptedAttributes(DOMElement $xml) : void + { + /** @var \DOMElement[] encryptedAttributes */ + $this->encryptedAttributes = Utils::xpQuery( + $xml, + './saml_assertion:AttributeStatement/saml_assertion:EncryptedAttribute' + ); + } + + + /** + * Parse signature on assertion. + * + * @param \DOMElement $xml The assertion XML element. + * @return void + */ + private function parseSignature(DOMElement $xml) : void + { + /** @var \DOMAttr[] $signatureMethod */ + $signatureMethod = Utils::xpQuery($xml, './ds:Signature/ds:SignedInfo/ds:SignatureMethod/@Algorithm'); + + /* Validate the signature element of the message. */ + $sig = Utils::validateElement($xml); + if ($sig !== false) { + $this->wasSignedAtConstruction = true; + $this->setCertificates($sig['Certificates']); + $this->setSignatureData($sig); + $this->setSignatureMethod($signatureMethod[0]->value); + } + } + + + /** + * Validate this assertion against a public key. + * + * If no signature was present on the assertion, we will return false. + * Otherwise, true will be returned. An exception is thrown if the + * signature validation fails. + * + * @param XMLSecurityKey $key The key we should check against. + * @return boolean true if successful, false if it is unsigned. + */ + public function validate(XMLSecurityKey $key) : bool + { + Assert::same($key->type, XMLSecurityKey::RSA_SHA256); + + if ($this->signatureData === null) { + return false; + } + + Utils::validateSignature($this->signatureData, $key); + + return true; + } + + + /** + * Retrieve the identifier of this assertion. + * + * @return string The identifier of this assertion. + */ + public function getId() : string + { + return $this->id; + } + + + /** + * Set the identifier of this assertion. + * + * @param string $id The new identifier of this assertion. + * @return void + */ + public function setId(string $id) : void + { + $this->id = $id; + } + + + /** + * Retrieve the issue timestamp of this assertion. + * + * @return int The issue timestamp of this assertion, as an UNIX timestamp. + */ + public function getIssueInstant() : int + { + return $this->issueInstant; + } + + + /** + * Set the issue timestamp of this assertion. + * + * @param int $issueInstant The new issue timestamp of this assertion, as an UNIX timestamp. + * @return void + */ + public function setIssueInstant(int $issueInstant) : void + { + $this->issueInstant = $issueInstant; + } + + + /** + * Retrieve the issuer if this assertion. + * + * @return \SAML2\XML\saml\Issuer The issuer of this assertion. + */ + public function getIssuer() : Issuer + { + return $this->issuer; + } + + + /** + * Set the issuer of this message. + * + * @param \SAML2\XML\saml\Issuer $issuer The new issuer of this assertion. + * @return void + */ + public function setIssuer(Issuer $issuer) : void + { + $this->issuer = $issuer; + } + + + /** + * Retrieve the NameId of the subject in the assertion. + * + * @throws \Exception + * @return \SAML2\XML\saml\NameID|null The name identifier of the assertion. + */ + public function getNameId() : ?NameID + { + if ($this->encryptedNameId !== null) { + throw new \Exception('Attempted to retrieve encrypted NameID without decrypting it first.'); + } + + return $this->nameId; + } + + + /** + * Set the NameId of the subject in the assertion. + * + * The NameId must be a \SAML2\XML\saml\NameID object. + * + * @see \SAML2\Utils::addNameId() + * @param \SAML2\XML\saml\NameID|null $nameId The name identifier of the assertion. + * @return void + */ + public function setNameId(NameID $nameId = null) : void + { + $this->nameId = $nameId; + } + + + /** + * Check whether the NameId is encrypted. + * + * @return bool True if the NameId is encrypted, false if not. + */ + public function isNameIdEncrypted() : bool + { + return $this->encryptedNameId !== null; + } + + + /** + * Encrypt the NameID in the Assertion. + * + * @param XMLSecurityKey $key The encryption key. + * @return void + */ + public function encryptNameId(XMLSecurityKey $key) : void + { + if ($this->nameId === null) { + throw new \Exception('Cannot encrypt NameID, no NameID set.'); + } + /* First create an XML representation of the NameID. */ + $doc = DOMDocumentFactory::create(); + $root = $doc->createElement('root'); + $doc->appendChild($root); + $this->nameId->toXML($root); + /** @var \DOMElement $nameId */ + $nameId = $root->firstChild; + + Utils::getContainer()->debugMessage($nameId, 'encrypt'); + + /* Encrypt the NameID. */ + $enc = new XMLSecEnc(); + $enc->setNode($nameId); + // @codingStandardsIgnoreStart + $enc->type = XMLSecEnc::Element; + // @codingStandardsIgnoreEnd + + $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); + $symmetricKey->generateSessionKey(); + $enc->encryptKey($key, $symmetricKey); + + /** + * @var \DOMElement encryptedNameId + * @psalm-suppress UndefinedClass + */ + $this->encryptedNameId = $enc->encryptNode($symmetricKey); + $this->nameId = null; + } + + + /** + * Decrypt the NameId of the subject in the assertion. + * + * @param XMLSecurityKey $key The decryption key. + * @param array $blacklist Blacklisted decryption algorithms. + * @return void + */ + public function decryptNameId(XMLSecurityKey $key, array $blacklist = []) : void + { + if ($this->encryptedNameId === null) { + /* No NameID to decrypt. */ + + return; + } + + $nameId = Utils::decryptElement($this->encryptedNameId, $key, $blacklist); + Utils::getContainer()->debugMessage($nameId, 'decrypt'); + $this->nameId = new NameID($nameId); + + $this->encryptedNameId = null; + } + + + /** + * Did this Assertion contain encrypted Attributes? + * + * @return bool + */ + public function hasEncryptedAttributes() : bool + { + return $this->encryptedAttributes !== []; + } + + + /** + * Decrypt the assertion attributes. + * + * @param XMLSecurityKey $key + * @param array $blacklist + * @throws \Exception + * @return void + */ + public function decryptAttributes(XMLSecurityKey $key, array $blacklist = []) : void + { + if (!$this->hasEncryptedAttributes()) { + return; + } + $firstAttribute = true; + $attributes = $this->getEncryptedAttributes(); + foreach ($attributes as $attributeEnc) { + /* Decrypt node */ + $attribute = Utils::decryptElement( + $attributeEnc->getElementsByTagName('EncryptedData')->item(0), + $key, + $blacklist + ); + + if (!$attribute->hasAttribute('Name')) { + throw new \Exception('Missing name on element.'); + } + $name = $attribute->getAttribute('Name'); + + if ($attribute->hasAttribute('NameFormat')) { + $nameFormat = $attribute->getAttribute('NameFormat'); + } else { + $nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + } + + if ($firstAttribute) { + $this->nameFormat = $nameFormat; + $firstAttribute = false; + } else { + if ($this->nameFormat !== $nameFormat) { + $this->nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + } + } + + if (!array_key_exists($name, $this->attributes)) { + $this->attributes[$name] = []; + } + + $this->parseAttributeValue($attribute, $name); + } + } + + + /** + * Retrieve the earliest timestamp this assertion is valid. + * + * This function returns null if there are no restrictions on how early the + * assertion can be used. + * + * @return int|null The earliest timestamp this assertion is valid. + */ + public function getNotBefore() : ?int + { + return $this->notBefore; + } + + + /** + * Set the earliest timestamp this assertion can be used. + * + * Set this to null if no limit is required. + * + * @param int|null $notBefore The earliest timestamp this assertion is valid. + * @return void + */ + public function setNotBefore(int $notBefore = null) : void + { + $this->notBefore = $notBefore; + } + + + /** + * Retrieve the expiration timestamp of this assertion. + * + * This function returns null if there are no restrictions on how + * late the assertion can be used. + * + * @return int|null The latest timestamp this assertion is valid. + */ + public function getNotOnOrAfter() : ?int + { + return $this->notOnOrAfter; + } + + + /** + * Set the expiration timestamp of this assertion. + * + * Set this to null if no limit is required. + * + * @param int|null $notOnOrAfter The latest timestamp this assertion is valid. + * @return void + */ + public function setNotOnOrAfter(int $notOnOrAfter = null) : void + { + $this->notOnOrAfter = $notOnOrAfter; + } + + + /** + * Retrieve $requiredEncAttributes if attributes will be send encrypted + * + * @return bool True to encrypt attributes in the assertion. + */ + public function getRequiredEncAttributes() : bool + { + return $this->requiredEncAttributes; + } + + + /** + * Set $requiredEncAttributes if attributes will be send encrypted + * + * @param bool $ea true to encrypt attributes in the assertion. + * @return void + */ + public function setRequiredEncAttributes(bool $ea) : void + { + $this->requiredEncAttributes = $ea; + } + + + /** + * Retrieve the audiences that are allowed to receive this assertion. + * + * This may be null, in which case all audiences are allowed. + * + * @return array|null The allowed audiences. + */ + public function getValidAudiences() : ?array + { + return $this->validAudiences; + } + + + /** + * Set the audiences that are allowed to receive this assertion. + * + * This may be null, in which case all audiences are allowed. + * + * @param array|null $validAudiences The allowed audiences. + * @return void + */ + public function setValidAudiences(array $validAudiences = null) : void + { + $this->validAudiences = $validAudiences; + } + + + /** + * Retrieve the AuthnInstant of the assertion. + * + * @return int|null The timestamp the user was authenticated, or NULL if the user isn't authenticated. + */ + public function getAuthnInstant() : ?int + { + return $this->authnInstant; + } + + + /** + * Set the AuthnInstant of the assertion. + * + * @param int|null $authnInstant Timestamp the user was authenticated, or NULL if we don't want an AuthnStatement. + * @return void + */ + public function setAuthnInstant(int $authnInstant = null) : void + { + $this->authnInstant = $authnInstant; + } + + + /** + * Retrieve the session expiration timestamp. + * + * This function returns null if there are no restrictions on the + * session lifetime. + * + * @return int|null The latest timestamp this session is valid. + */ + public function getSessionNotOnOrAfter() : ?int + { + return $this->sessionNotOnOrAfter; + } + + + /** + * Set the session expiration timestamp. + * + * Set this to null if no limit is required. + * + * @param int|null $sessionNotOnOrAfter The latest timestamp this session is valid. + * @return void + */ + public function setSessionNotOnOrAfter(int $sessionNotOnOrAfter = null) : void + { + $this->sessionNotOnOrAfter = $sessionNotOnOrAfter; + } + + + /** + * Retrieve the session index of the user at the IdP. + * + * @return string|null The session index of the user at the IdP. + */ + public function getSessionIndex() : ?string + { + return $this->sessionIndex; + } + + + /** + * Set the session index of the user at the IdP. + * + * Note that the authentication context must be set before the + * session index can be inluded in the assertion. + * + * @param string|null $sessionIndex The session index of the user at the IdP. + * @return void + */ + public function setSessionIndex(string $sessionIndex = null) : void + { + $this->sessionIndex = $sessionIndex; + } + + + /** + * Retrieve the authentication method used to authenticate the user. + * + * This will return null if no authentication statement was + * included in the assertion. + * + * @return string|null The authentication method. + */ + public function getAuthnContextClassRef() : ?string + { + return $this->authnContextClassRef; + } + + + /** + * Set the authentication method used to authenticate the user. + * + * If this is set to null, no authentication statement will be + * included in the assertion. The default is null. + * + * @param string|null $authnContextClassRef The authentication method. + * @return void + */ + public function setAuthnContextClassRef(string $authnContextClassRef = null) : void + { + $this->authnContextClassRef = $authnContextClassRef; + } + + + /** + * Retrieve the signature method. + * + * @return string|null The signature method. + */ + public function getSignatureMethod() : ?string + { + return $this->signatureMethod; + } + + + /** + * Set the signature method used. + * + * @param string|null $signatureMethod + * @return void + */ + public function setSignatureMethod(string $signatureMethod = null) : void + { + $this->signatureMethod = $signatureMethod; + } + + + /** + * Set the authentication context declaration. + * + * @param \SAML2\XML\Chunk $authnContextDecl + * @throws \Exception + * @return void + */ + public function setAuthnContextDecl(Chunk $authnContextDecl) : void + { + if (!empty($this->authnContextDeclRef)) { + throw new \Exception( + 'AuthnContextDeclRef is already registered! May only have either a Decl or a DeclRef, not both!' + ); + } + + $this->authnContextDecl = $authnContextDecl; + } + + + /** + * Get the authentication context declaration. + * + * See: + * @url http://docs.oasis-open.org/security/saml/v2.0/saml-authn-context-2.0-os.pdf + * + * @return \SAML2\XML\Chunk|null + */ + public function getAuthnContextDecl() : ?Chunk + { + return $this->authnContextDecl; + } + + + /** + * Set the authentication context declaration reference. + * + * @param string|null $authnContextDeclRef + * @throws \Exception + * @return void + */ + public function setAuthnContextDeclRef(string $authnContextDeclRef = null) : void + { + if (!empty($this->authnContextDecl)) { + throw new \Exception( + 'AuthnContextDecl is already registered! May only have either a Decl or a DeclRef, not both!' + ); + } + + $this->authnContextDeclRef = $authnContextDeclRef; + } + + + /** + * Get the authentication context declaration reference. + * URI reference that identifies an authentication context declaration. + * + * The URI reference MAY directly resolve into an XML document containing the referenced declaration. + * + * @return string|null + */ + public function getAuthnContextDeclRef() : ?string + { + return $this->authnContextDeclRef; + } + + + /** + * Retrieve the AuthenticatingAuthority. + * + * @return array + */ + public function getAuthenticatingAuthority() : array + { + return $this->AuthenticatingAuthority; + } + + + /** + * Set the AuthenticatingAuthority + * + * @param array $authenticatingAuthority + * @return void + */ + public function setAuthenticatingAuthority(array $authenticatingAuthority) : void + { + $this->AuthenticatingAuthority = $authenticatingAuthority; + } + + + /** + * Retrieve all attributes. + * + * @return array All attributes, as an associative array. + */ + public function getAttributes() : array + { + return $this->attributes; + } + + + /** + * Replace all attributes. + * + * @param array $attributes All new attributes, as an associative array. + * @return void + */ + public function setAttributes(array $attributes) : void + { + $this->attributes = $attributes; + } + + /** + * @return array|null + */ + public function getSignatureData() : ?array + { + return $this->signatureData; + } + + + /** + * @param array|null $signatureData + * @return void + */ + public function setSignatureData(array $signatureData = null) : void + { + $this->signatureData = $signatureData; + } + + + /** + * Retrieve all attributes value types. + * + * @return array All attributes value types, as an associative array. + */ + public function getAttributesValueTypes() : array + { + return $this->attributesValueTypes; + } + + + /** + * Replace all attributes value types.. + * + * @param array $attributesValueTypes All new attribute value types, as an associative array. + * @return void + */ + public function setAttributesValueTypes(array $attributesValueTypes) : void + { + $this->attributesValueTypes = $attributesValueTypes; + } + + + /** + * Retrieve the NameFormat used on all attributes. + * + * If more than one NameFormat is used in the received attributes, this + * returns the unspecified NameFormat. + * + * @return string The NameFormat used on all attributes. + */ + public function getAttributeNameFormat() : string + { + return $this->nameFormat; + } + + + /** + * Set the NameFormat used on all attributes. + * + * @param string $nameFormat The NameFormat used on all attributes. + * @return void + */ + public function setAttributeNameFormat(string $nameFormat) : void + { + $this->nameFormat = $nameFormat; + } + + + /** + * Retrieve the SubjectConfirmation elements we have in our Subject element. + * + * @return array Array of \SAML2\XML\saml\SubjectConfirmation elements. + */ + public function getSubjectConfirmation() : array + { + return $this->SubjectConfirmation; + } + + + /** + * Set the SubjectConfirmation elements that should be included in the assertion. + * + * @param array $SubjectConfirmation Array of \SAML2\XML\saml\SubjectConfirmation elements. + * @return void + */ + public function setSubjectConfirmation(array $SubjectConfirmation) : void + { + $this->SubjectConfirmation = $SubjectConfirmation; + } + + + /** + * Retrieve the encryptedAttributes elements we have. + * + * @return array Array of \DOMElement elements. + */ + public function getEncryptedAttributes() : array + { + return $this->encryptedAttributes; + } + + + /** + * Set the encryptedAttributes elements + * + * @param array $encAttrs Array of \DOMElement elements. + * @return void + */ + public function setEncryptedAttributes(array $encAttrs) : void + { + $this->encryptedAttributes = $encAttrs; + } + + + /** + * Retrieve the private key we should use to sign the assertion. + * + * @return XMLSecurityKey|null The key, or NULL if no key is specified. + */ + public function getSignatureKey() : ?XMLSecurityKey + { + return $this->signatureKey; + } + + + /** + * Set the private key we should use to sign the assertion. + * + * If the key is null, the assertion will be sent unsigned. + * + * @param XMLSecurityKey|null $signatureKey + * @return void + */ + public function setSignatureKey(XMLSecurityKey $signatureKey = null) : void + { + $this->signatureKey = $signatureKey; + } + + + /** + * Return the key we should use to encrypt the assertion. + * + * @return XMLSecurityKey|null The key, or NULL if no key is specified.. + * + */ + public function getEncryptionKey() : ?XMLSecurityKey + { + return $this->encryptionKey; + } + + + /** + * Set the private key we should use to encrypt the attributes. + * + * @param XMLSecurityKey|null $Key + * @return void + */ + public function setEncryptionKey(XMLSecurityKey $Key = null) : void + { + $this->encryptionKey = $Key; + } + + + /** + * Set the certificates that should be included in the assertion. + * + * The certificates should be strings with the PEM encoded data. + * + * @param array $certificates An array of certificates. + * @return void + */ + public function setCertificates(array $certificates) : void + { + $this->certificates = $certificates; + } + + + /** + * Retrieve the certificates that are included in the assertion. + * + * @return array An array of certificates. + */ + public function getCertificates() : array + { + return $this->certificates; + } + + + /** + * @return bool + */ + public function wasSignedAtConstruction() : bool + { + return $this->wasSignedAtConstruction; + } + + + /** + * Convert this assertion to an XML element. + * + * @param \DOMNode|null $parentElement The DOM node the assertion should be created in. + * @return \DOMElement This assertion. + */ + public function toXML(\DOMNode $parentElement = null) : DOMElement + { + if ($parentElement === null) { + $document = DOMDocumentFactory::create(); + $parentElement = $document; + } else { + $document = $parentElement->ownerDocument; + } + + $root = $document->createElementNS(Constants::NS_SAML, 'saml:'.'Assertion'); + $parentElement->appendChild($root); + + /* Ugly hack to add another namespace declaration to the root element. */ + $root->setAttributeNS(Constants::NS_SAMLP, 'samlp:tmp', 'tmp'); + $root->removeAttributeNS(Constants::NS_SAMLP, 'tmp'); + $root->setAttributeNS(Constants::NS_XSI, 'xsi:tmp', 'tmp'); + $root->removeAttributeNS(Constants::NS_XSI, 'tmp'); + $root->setAttributeNS(Constants::NS_XS, 'xs:tmp', 'tmp'); + $root->removeAttributeNS(Constants::NS_XS, 'tmp'); + + $root->setAttribute('ID', $this->id); + $root->setAttribute('Version', '2.0'); + $root->setAttribute('IssueInstant', gmdate('Y-m-d\TH:i:s\Z', $this->issueInstant)); + + $issuer = $this->issuer->toXML($root); + + $this->addSubject($root); + $this->addConditions($root); + $this->addAuthnStatement($root); + if ($this->getRequiredEncAttributes() === false) { + $this->addAttributeStatement($root); + } else { + $this->addEncryptedAttributeStatement($root); + } + + if ($this->signatureKey !== null) { + Utils::insertSignature($this->signatureKey, $this->certificates, $root, $issuer->nextSibling); + } + + return $root; + } + + + /** + * Add a Subject-node to the assertion. + * + * @param \DOMElement $root The assertion element we should add the subject to. + * @return void + */ + private function addSubject(DOMElement $root) : void + { + if ($this->nameId === null && $this->encryptedNameId === null) { + /* We don't have anything to create a Subject node for. */ + + return; + } + + $subject = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:Subject'); + $root->appendChild($subject); + + if ($this->encryptedNameId === null) { + $this->nameId->toXML($subject); + } else { + $eid = $subject->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:'.'EncryptedID'); + $subject->appendChild($eid); + $eid->appendChild($subject->ownerDocument->importNode($this->encryptedNameId, true)); + } + + foreach ($this->SubjectConfirmation as $sc) { + $sc->toXML($subject); + } + } + + + /** + * Add a Conditions-node to the assertion. + * + * @param \DOMElement $root The assertion element we should add the conditions to. + * @return void + */ + private function addConditions(DOMElement $root) : void + { + $document = $root->ownerDocument; + + $conditions = $document->createElementNS(Constants::NS_SAML, 'saml:Conditions'); + $root->appendChild($conditions); + + if ($this->notBefore !== null) { + $conditions->setAttribute('NotBefore', gmdate('Y-m-d\TH:i:s\Z', $this->notBefore)); + } + if ($this->notOnOrAfter !== null) { + $conditions->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter)); + } + + if ($this->validAudiences !== null) { + $ar = $document->createElementNS(Constants::NS_SAML, 'saml:AudienceRestriction'); + $conditions->appendChild($ar); + + Utils::addStrings($ar, Constants::NS_SAML, 'saml:Audience', false, $this->validAudiences); + } + } + + + /** + * Add a AuthnStatement-node to the assertion. + * + * @param \DOMElement $root The assertion element we should add the authentication statement to. + * @return void + */ + private function addAuthnStatement(DOMElement $root) : void + { + if ($this->authnInstant === null || + ( + $this->authnContextClassRef === null && + $this->authnContextDecl === null && + $this->authnContextDeclRef === null + ) + ) { + /* No authentication context or AuthnInstant => no authentication statement. */ + + return; + } + + $document = $root->ownerDocument; + + $authnStatementEl = $document->createElementNS(Constants::NS_SAML, 'saml:AuthnStatement'); + $root->appendChild($authnStatementEl); + + $authnStatementEl->setAttribute('AuthnInstant', gmdate('Y-m-d\TH:i:s\Z', $this->authnInstant)); + + if ($this->sessionNotOnOrAfter !== null) { + $authnStatementEl->setAttribute( + 'SessionNotOnOrAfter', + gmdate('Y-m-d\TH:i:s\Z', $this->sessionNotOnOrAfter) + ); + } + if ($this->sessionIndex !== null) { + $authnStatementEl->setAttribute('SessionIndex', $this->sessionIndex); + } + + $authnContextEl = $document->createElementNS(Constants::NS_SAML, 'saml:AuthnContext'); + $authnStatementEl->appendChild($authnContextEl); + + if (!empty($this->authnContextClassRef)) { + Utils::addString( + $authnContextEl, + Constants::NS_SAML, + 'saml:AuthnContextClassRef', + $this->authnContextClassRef + ); + } + if (!empty($this->authnContextDecl)) { + $this->authnContextDecl->toXML($authnContextEl); + } + if (!empty($this->authnContextDeclRef)) { + Utils::addString( + $authnContextEl, + Constants::NS_SAML, + 'saml:AuthnContextDeclRef', + $this->authnContextDeclRef + ); + } + + Utils::addStrings( + $authnContextEl, + Constants::NS_SAML, + 'saml:AuthenticatingAuthority', + false, + $this->AuthenticatingAuthority + ); + } + + + /** + * Add an AttributeStatement-node to the assertion. + * + * @param \DOMElement $root The assertion element we should add the subject to. + * @return void + */ + private function addAttributeStatement(DOMElement $root) : void + { + if (empty($this->attributes)) { + return; + } + + $document = $root->ownerDocument; + + $attributeStatement = $document->createElementNS(Constants::NS_SAML, 'saml:AttributeStatement'); + $root->appendChild($attributeStatement); + + foreach ($this->attributes as $name => $values) { + $attribute = $document->createElementNS(Constants::NS_SAML, 'saml:Attribute'); + $attributeStatement->appendChild($attribute); + $attribute->setAttribute('Name', $name); + + if ($this->nameFormat !== Constants::NAMEFORMAT_UNSPECIFIED) { + $attribute->setAttribute('NameFormat', $this->nameFormat); + } + + // make sure eduPersonTargetedID can be handled properly as a NameID + if ($name === Constants::EPTI_URN_MACE || $name === Constants::EPTI_URN_OID) { + foreach ($values as $eptiValue) { + $attributeValue = $document->createElementNS(Constants::NS_SAML, 'saml:AttributeValue'); + $attribute->appendChild($attributeValue); + if ($eptiValue instanceof NameID) { + $eptiValue->toXML($attributeValue); + } elseif ($eptiValue instanceof DOMNodeList) { + /** @var \DOMElement $value */ + $value = $eptiValue->item(0); + $node = $root->ownerDocument->importNode($value, true); + $attributeValue->appendChild($node); + } else { + $attributeValue->textContent = $eptiValue; + } + } + + continue; + } + + // get value type(s) for the current attribute + if (array_key_exists($name, $this->attributesValueTypes)) { + $valueTypes = $this->attributesValueTypes[$name]; + if (is_array($valueTypes) && count($valueTypes) != count($values)) { + throw new \Exception('Array of value types and array of values have different size for attribute '. + var_export($name, true)); + } + } else { + // if no type(s), default behaviour + $valueTypes = null; + } + + $vidx = -1; + foreach ($values as $value) { + $vidx++; + + // try to get type from current types + $type = null; + if (!is_null($valueTypes)) { + if (is_array($valueTypes)) { + $type = $valueTypes[$vidx]; + } else { + $type = $valueTypes; + } + } + + // if no type get from types, use default behaviour + if (is_null($type)) { + if (is_string($value)) { + $type = 'xs:string'; + } elseif (is_int($value)) { + $type = 'xs:integer'; + } else { + $type = null; + } + } + + $attributeValue = $document->createElementNS(Constants::NS_SAML, 'saml:AttributeValue'); + $attribute->appendChild($attributeValue); + if ($type !== null) { + $attributeValue->setAttributeNS(Constants::NS_XSI, 'xsi:type', $type); + } + if (is_null($value)) { + $attributeValue->setAttributeNS(Constants::NS_XSI, 'xsi:nil', 'true'); + } + + if ($value instanceof \DOMNodeList) { + foreach ($value as $v) { + $node = $document->importNode($v, true); + $attributeValue->appendChild($node); + } + } else { + $value = strval($value); + $attributeValue->appendChild($document->createTextNode($value)); + } + } + } + } + + + /** + * Add an EncryptedAttribute Statement-node to the assertion. + * + * @param \DOMElement $root The assertion element we should add the Encrypted Attribute Statement to. + * @return void + */ + private function addEncryptedAttributeStatement(DOMElement $root) : void + { + if ($this->getRequiredEncAttributes() === false) { + return; + } + Assert::notNull($this->encryptionKey); + + $document = $root->ownerDocument; + + $attributeStatement = $document->createElementNS(Constants::NS_SAML, 'saml:AttributeStatement'); + $root->appendChild($attributeStatement); + + foreach ($this->attributes as $name => $values) { + $document2 = DOMDocumentFactory::create(); + $attribute = $document2->createElementNS(Constants::NS_SAML, 'saml:Attribute'); + $attribute->setAttribute('Name', $name); + $document2->appendChild($attribute); + + if ($this->nameFormat !== Constants::NAMEFORMAT_UNSPECIFIED) { + $attribute->setAttribute('NameFormat', $this->getAttributeNameFormat()); + } + + foreach ($values as $value) { + if (is_string($value)) { + $type = 'xs:string'; + } elseif (is_int($value)) { + $type = 'xs:integer'; + } else { + $type = null; + } + + $attributeValue = $document2->createElementNS(Constants::NS_SAML, 'saml:AttributeValue'); + $attribute->appendChild($attributeValue); + if ($type !== null) { + $attributeValue->setAttributeNS(Constants::NS_XSI, 'xsi:type', $type); + } + + if ($value instanceof DOMNodeList) { + foreach ($value as $v) { + $node = $document2->importNode($v, true); + $attributeValue->appendChild($node); + } + } else { + $value = strval($value); + $attributeValue->appendChild($document2->createTextNode($value)); + } + } + /*Once the attribute nodes are built, the are encrypted*/ + $EncAssert = new XMLSecEnc(); + $EncAssert->setNode($document2->documentElement); + $EncAssert->type = 'http://www.w3.org/2001/04/xmlenc#Element'; + /* + * Attributes are encrypted with a session key and this one with + * $EncryptionKey + */ + $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); + $symmetricKey->generateSessionKey(); + /** @psalm-suppress PossiblyNullArgument */ + $EncAssert->encryptKey($this->encryptionKey, $symmetricKey); + /** @psalm-suppress UndefinedClass */ + $EncrNode = $EncAssert->encryptNode($symmetricKey); + + $EncAttribute = $document->createElementNS(Constants::NS_SAML, 'saml:EncryptedAttribute'); + $attributeStatement->appendChild($EncAttribute); + /** @psalm-suppress InvalidArgument */ + $n = $document->importNode($EncrNode, true); + $EncAttribute->appendChild($n); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Decrypter.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Decrypter.php new file mode 100644 index 000000000..9a97f9767 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Decrypter.php @@ -0,0 +1,108 @@ +logger = $logger; + $this->identityProvider = $identityProvider; + $this->serviceProvider = $serviceProvider; + $this->privateKeyLoader = $privateKeyLoader; + } + + + /** + * Allows for checking whether either the SP or the IdP requires assertion encryption + * + * @return bool + */ + public function isEncryptionRequired() : bool + { + return $this->identityProvider->isAssertionEncryptionRequired() + || $this->serviceProvider->isAssertionEncryptionRequired(); + } + + + /** + * @param \SAML2\EncryptedAssertion $assertion + * + * @return \SAML2\Assertion + */ + public function decrypt(EncryptedAssertion $assertion) : Assertion + { + $decryptionKeys = $this->privateKeyLoader->loadDecryptionKeys($this->identityProvider, $this->serviceProvider); + $blacklistedKeys = $this->identityProvider->getBlacklistedAlgorithms(); + if (is_null($blacklistedKeys)) { + $blacklistedKeys = $this->serviceProvider->getBlacklistedAlgorithms(); + } + + // reflects the simplesamlphp behaviour for BC, see + // https://github.com/simplesamlphp/simplesamlphp/blob/3d735912342767d391297cc5e13272a76730aca0/modules/saml/lib/Message.php#L369 + foreach ($decryptionKeys as $index => $key) { + try { + $decryptedAssertion = $assertion->getAssertion($key, $blacklistedKeys); + $this->logger->debug(sprintf('Decrypted Assertion with key "#%d"', $index)); + + return $decryptedAssertion; + } catch (\Exception $e) { + $this->logger->debug(sprintf( + 'Could not decrypt assertion with key "#%d", "%s" thrown: "%s"', + $index, + get_class($e), + $e->getMessage() + )); + } + } + + throw new NotDecryptedException(sprintf( + 'Could not decrypt the assertion, tried with "%d" keys. See the debug log for more information', + count($decryptionKeys) + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Exception/InvalidAssertionException.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Exception/InvalidAssertionException.php new file mode 100644 index 000000000..0ac6bffeb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Exception/InvalidAssertionException.php @@ -0,0 +1,11 @@ +assertionValidator = $assertionValidator; + $this->signatureValidator = $signatureValidator; + $this->decrypter = $decrypter; + $this->subjectConfirmationValidator = $subjectConfirmationValidator; + $this->transformer = $transformer; + $this->identityProviderConfiguration = $identityProviderConfiguration; + $this->logger = $logger; + } + + + /** + * Decrypt assertions, or do nothing if assertions are already decrypted. + * + * @param \SAML2\Utilities\ArrayCollection $assertions + * @return \SAML2\Utilities\ArrayCollection Collection of processed assertions + */ + public function decryptAssertions(ArrayCollection $assertions) + { + $decrypted = new ArrayCollection(); + foreach ($assertions->getIterator() as $assertion) { + if ($assertion instanceof EncryptedAssertion) { + $decrypted->add($this->decryptAssertion($assertion)); + } elseif ($assertion instanceof Assertion) { + $decrypted->add($assertion); + } else { + throw new InvalidAssertionException('The assertion must be of type: EncryptedAssertion or Assertion'); + } + } + + return $decrypted; + } + + /** + * @param \SAML2\Utilities\ArrayCollection $assertions Collection of decrypted assertions + * @return \SAML2\Utilities\ArrayCollection Collection of processed assertions + */ + public function processAssertions(ArrayCollection $assertions) : ArrayCollection + { + $processed = new ArrayCollection(); + foreach ($assertions->getIterator() as $assertion) { + $processed->add($this->process($assertion)); + } + + return $processed; + } + + + /** + * @param \SAML2\Assertion $assertion + * @return \SAML2\Assertion + */ + public function process(Assertion $assertion): Assertion + { + if (!$assertion->wasSignedAtConstruction()) { + $this->logger->info(sprintf( + 'Assertion with id "%s" was not signed at construction, not verifying the signature', + $assertion->getId() + )); + } else { + $this->logger->info(sprintf('Verifying signature of Assertion with id "%s"', $assertion->getId())); + + if (!$this->signatureValidator->hasValidSignature($assertion, $this->identityProviderConfiguration)) { + throw new InvalidSignatureException( + sprintf('The assertion with id "%s" does not have a valid signature', $assertion->getId()) + ); + } + } + + $this->validateAssertion($assertion); + + $assertion = $this->transformAssertion($assertion); + + return $assertion; + } + + + /** + * @param \SAML2\EncryptedAssertion $assertion + * @return \SAML2\Assertion + */ + private function decryptAssertion(EncryptedAssertion $assertion): Assertion + { + return $this->decrypter->decrypt($assertion); + } + + + /** + * @param \SAML2\Assertion $assertion + * @return void + */ + public function validateAssertion(Assertion $assertion) : void + { + $assertionValidationResult = $this->assertionValidator->validate($assertion); + if (!$assertionValidationResult->isValid()) { + throw new InvalidAssertionException(sprintf( + 'Invalid Assertion in SAML Response, errors: "%s"', + implode('", "', $assertionValidationResult->getErrors()) + )); + } + + foreach ($assertion->getSubjectConfirmation() as $subjectConfirmation) { + $subjectConfirmationValidationResult = $this->subjectConfirmationValidator->validate( + $subjectConfirmation + ); + if (!$subjectConfirmationValidationResult->isValid()) { + throw new InvalidSubjectConfirmationException(sprintf( + 'Invalid SubjectConfirmation in Assertion, errors: "%s"', + implode('", "', $subjectConfirmationValidationResult->getErrors()) + )); + } + } + } + + + /** + * @param \SAML2\Assertion $assertion + * @return \SAML2\Assertion + */ + private function transformAssertion(Assertion $assertion) : Assertion + { + return $this->transformer->transform($assertion); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/ProcessorBuilder.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/ProcessorBuilder.php new file mode 100644 index 000000000..aff5ca709 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/ProcessorBuilder.php @@ -0,0 +1,160 @@ +addConstraintValidator(new NotBefore()); + $validator->addConstraintValidator(new NotOnOrAfter()); + $validator->addConstraintValidator(new SessionNotOnOrAfter()); + $validator->addConstraintValidator(new SpIsValidAudience()); + + return $validator; + } + + + /** + * @param IdentityProvider $identityProvider + * @param ServiceProvider $serviceProvider + * @param Destination $currentDestination + * @param Response $response + * @return SubjectConfirmationValidator + */ + private static function createSubjectConfirmationValidator( + IdentityProvider $identityProvider, + ServiceProvider $serviceProvider, + Destination $currentDestination, + Response $response + ) : SubjectConfirmationValidator { + $validator = new SubjectConfirmationValidator($identityProvider, $serviceProvider); + $validator->addConstraintValidator( + new SubjectConfirmationMethod() + ); + $validator->addConstraintValidator( + new SubjectConfirmationNotBefore() + ); + $validator->addConstraintValidator( + new SubjectConfirmationNotOnOrAfter() + ); + $validator->addConstraintValidator( + new SubjectConfirmationRecipientMatches( + $currentDestination + ) + ); + $validator->addConstraintValidator( + new SubjectConfirmationResponseToMatches( + $response + ) + ); + + return $validator; + } + + /** + * @param LoggerInterface $logger + * @param PrivateKeyLoader $keyLoader + * @param IdentityProvider $identityProvider + * @param ServiceProvider $serviceProvider + * @return TransformerChain + */ + private static function createAssertionTransformerChain( + LoggerInterface $logger, + PrivateKeyLoader $keyloader, + IdentityProvider $identityProvider, + ServiceProvider $serviceProvider + ) : TransformerChain { + $chain = new TransformerChain($identityProvider, $serviceProvider); + $chain->addTransformerStep(new DecodeBase64Transformer()); + $chain->addTransformerStep( + new NameIdDecryptionTransformer($logger, $keyloader) + ); + + return $chain; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/DecodeBase64Transformer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/DecodeBase64Transformer.php new file mode 100644 index 000000000..c5aa0e383 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/DecodeBase64Transformer.php @@ -0,0 +1,61 @@ +identityProvider = $identityProvider; + } + + + /** + * @param Assertion $assertion + * @return Assertion + */ + public function transform(Assertion $assertion) : Assertion + { + if (!$this->identityProvider->hasBase64EncodedAttributes()) { + return $assertion; + } + + $attributes = $assertion->getAttributes(); + $keys = array_keys($attributes); + $decoded = array_map([$this, 'decodeValue'], $attributes); + + $attributes = array_combine($keys, $decoded); + + $assertion->setAttributes($attributes); + return $assertion; + } + + + /** + * @param string $value + * @return array + */ + private function decodeValue(string $value) : array + { + $elements = explode('_', $value); + return array_map('base64_decode', $elements); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/NameIdDecryptionTransformer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/NameIdDecryptionTransformer.php new file mode 100644 index 000000000..cdd0a9cca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/NameIdDecryptionTransformer.php @@ -0,0 +1,117 @@ +logger = $logger; + $this->privateKeyLoader = $privateKeyLoader; + } + + + /** + * @param Assertion $assertion + * @throws \Exception + * @return Assertion + */ + public function transform(Assertion $assertion) : Assertion + { + if (!$assertion->isNameIdEncrypted()) { + return $assertion; + } + + $decryptionKeys = $this->privateKeyLoader->loadDecryptionKeys($this->identityProvider, $this->serviceProvider); + $blacklistedKeys = $this->identityProvider->getBlacklistedAlgorithms(); + if (is_null($blacklistedKeys)) { + $blacklistedKeys = $this->serviceProvider->getBlacklistedAlgorithms(); + } + + foreach ($decryptionKeys as $index => $key) { + try { + $assertion->decryptNameId($key, $blacklistedKeys); + $this->logger->debug(sprintf('Decrypted assertion NameId with key "#%d"', $index)); + } catch (\Exception $e) { + $this->logger->debug(sprintf( + 'Decrypting assertion NameId with key "#%d" failed, "%s" thrown: "%s"', + $index, + get_class($e), + $e->getMessage() + )); + } + } + + if ($assertion->isNameIdEncrypted()) { + throw new NotDecryptedException( + 'Could not decrypt the assertion NameId with the configured keys, see the debug log for information' + ); + } + + return $assertion; + } + + + /** + * @param IdentityProvider $identityProvider + * @return void + */ + public function setIdentityProvider(IdentityProvider $identityProvider) : void + { + $this->identityProvider = $identityProvider; + } + + + /** + * @param ServiceProvider $serviceProvider + * @return void + */ + public function setServiceProvider(ServiceProvider $serviceProvider) : void + { + $this->serviceProvider = $serviceProvider; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/Transformer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/Transformer.php new file mode 100644 index 000000000..4aac46941 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Transformer/Transformer.php @@ -0,0 +1,17 @@ +identityProvider = $identityProvider; + $this->serviceProvider = $serviceProvider; + } + + + /** + * @param Transformer $transformer + * @return void + */ + public function addTransformerStep(Transformer $transformer) : void + { + if ($transformer instanceof IdentityProviderAware) { + $transformer->setIdentityProvider($this->identityProvider); + } + + if ($transformer instanceof ServiceProviderAware) { + $transformer->setServiceProvider($this->serviceProvider); + } + + $this->transformers[] = $transformer; + } + + + /** + * @param \SAML2\Assertion $assertion + * + * @return \SAML2\Assertion + */ + public function transform(Assertion $assertion) : Assertion + { + foreach ($this->transformers as $transformer) { + $assertion = $transformer->transform($assertion); + } + + return $assertion; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/AssertionConstraintValidator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/AssertionConstraintValidator.php new file mode 100644 index 000000000..279cf63a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/AssertionConstraintValidator.php @@ -0,0 +1,17 @@ +identityProvider = $identityProvider; + $this->serviceProvider = $serviceProvider; + } + + + /** + * @param AssertionConstraintValidator $constraint + * @return void + */ + public function addConstraintValidator(AssertionConstraintValidator $constraint) : void + { + if ($constraint instanceof IdentityProviderAware) { + $constraint->setIdentityProvider($this->identityProvider); + } + + if ($constraint instanceof ServiceProviderAware) { + $constraint->setServiceProvider($this->serviceProvider); + } + + $this->constraints[] = $constraint; + } + + + /** + * @param Assertion $assertion + * @return Result + */ + public function validate(Assertion $assertion) : Result + { + $result = new Result(); + foreach ($this->constraints as $validator) { + $validator->validate($assertion, $result); + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotBefore.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotBefore.php new file mode 100644 index 000000000..d0046138b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotBefore.php @@ -0,0 +1,29 @@ +getNotBefore(); + if (($notBeforeTimestamp !== null) && ($notBeforeTimestamp > (Temporal::getTime() + 60))) { + $result->addError( + 'Received an assertion that is valid in the future. Check clock synchronization on IdP and SP.' + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php new file mode 100644 index 000000000..06baf9d09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/NotOnOrAfter.php @@ -0,0 +1,29 @@ +getNotOnOrAfter(); + if (($notValidOnOrAfterTimestamp !== null) && ($notValidOnOrAfterTimestamp <= (Temporal::getTime() - 60))) { + $result->addError( + 'Received an assertion that has expired. Check clock synchronization on IdP and SP.' + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfter.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfter.php new file mode 100644 index 000000000..bb570f8a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SessionNotOnOrAfter.php @@ -0,0 +1,30 @@ +getSessionNotOnOrAfter(); + $currentTime = Temporal::getTime(); + if (($sessionNotOnOrAfterTimestamp !== null) && ($sessionNotOnOrAfterTimestamp <= ($currentTime - 60))) { + $result->addError( + 'Received an assertion with a session that has expired. Check clock synchronization on IdP and SP.' + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php new file mode 100644 index 000000000..fd962a751 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SpIsValidAudience.php @@ -0,0 +1,54 @@ +serviceProvider = $serviceProvider; + } + + + /** + * @param Assertion $assertion + * @param Result $result + * @return void + */ + public function validate(Assertion $assertion, Result $result) : void + { + $intendedAudiences = $assertion->getValidAudiences(); + if ($intendedAudiences === null) { + return; + } + + $entityId = $this->serviceProvider->getEntityId(); + if (!in_array($entityId, $intendedAudiences, true)) { + $result->addError(sprintf( + 'The configured Service Provider [%s] is not a valid audience for the assertion. Audiences: [%s]', + strval($entityId), + implode('], [', $intendedAudiences) + )); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php new file mode 100644 index 000000000..9296114b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationMethod.php @@ -0,0 +1,30 @@ +getMethod() !== Constants::CM_BEARER) { + $result->addError(sprintf( + 'Invalid Method on SubjectConfirmation, current;y only Bearer (%s) is supported', + Constants::CM_BEARER + )); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php new file mode 100644 index 000000000..4ccd6e778 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotBefore.php @@ -0,0 +1,34 @@ +getSubjectConfirmationData(); + Assert::notNull($data); + + /** @psalm-suppress PossiblyNullReference */ + $notBefore = $data->getNotBefore(); + if ($notBefore && $notBefore > Temporal::getTime() + 60) { + $result->addError('NotBefore in SubjectConfirmationData is in the future'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php new file mode 100644 index 000000000..e17e388d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationNotOnOrAfter.php @@ -0,0 +1,34 @@ +getSubjectConfirmationData(); + Assert::notNull($data); + + /** @psalm-suppress PossiblyNullReference */ + $notOnOrAfter = $data->getNotOnOrAfter(); + if ($notOnOrAfter && $notOnOrAfter <= Temporal::getTime() - 60) { + $result->addError('NotOnOrAfter in SubjectConfirmationData is in the past'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php new file mode 100644 index 000000000..b9f1399c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationRecipientMatches.php @@ -0,0 +1,53 @@ +destination = $destination; + } + + + /** + * @param SubjectConfirmation $subjectConfirmation + * @param Result $result + * @return void + */ + public function validate(SubjectConfirmation $subjectConfirmation, Result $result) : void + { + $data = $subjectConfirmation->getSubjectConfirmationData(); + Assert::notNull($data); + + /** @psalm-suppress PossiblyNullReference */ + $recipient = $data->getRecipient(); + if ($recipient && !$this->destination->equals(new Destination($recipient))) { + $result->addError(sprintf( + 'Recipient in SubjectConfirmationData ("%s") does not match the current destination ("%s")', + $recipient, + strval($this->destination) + )); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php new file mode 100644 index 000000000..e01fefb59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/ConstraintValidator/SubjectConfirmationResponseToMatches.php @@ -0,0 +1,65 @@ +response = $response; + } + + + /** + * @param \SAML2\XML\saml\SubjectConfirmation $subjectConfirmation + * @param Result $result + * @return void + */ + public function validate(SubjectConfirmation $subjectConfirmation, Result $result) : void + { + $data = $subjectConfirmation->getSubjectConfirmationData(); + Assert::notNull($data); + + /** @psalm-suppress PossiblyNullReference */ + $inResponseTo = $data->getInResponseTo(); + if ($inResponseTo && ($this->getInResponseTo() !== false) && ($this->getInResponseTo() !== $inResponseTo)) { + $result->addError(sprintf( + 'InResponseTo in SubjectConfirmationData ("%s") does not match the Response InResponseTo ("%s")', + $inResponseTo, + strval($this->getInResponseTo()) + )); + } + } + + + /** + * @return string|bool + */ + private function getInResponseTo() + { + $inResponseTo = $this->response->getInResponseTo(); + if ($inResponseTo === null) { + return false; + } + + return $inResponseTo; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/Result.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/Result.php new file mode 100644 index 000000000..44d84f930 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/Result.php @@ -0,0 +1,46 @@ +errors[] = $message; + } + + + /** + * @return bool + */ + public function isValid() : bool + { + return empty($this->errors); + } + + + /** + * @return array + */ + public function getErrors() : array + { + return $this->errors; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/SubjectConfirmationConstraintValidator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/SubjectConfirmationConstraintValidator.php new file mode 100644 index 000000000..a6ce33f95 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Assertion/Validation/SubjectConfirmationConstraintValidator.php @@ -0,0 +1,20 @@ +identityProvider = $identityProvider; + $this->serviceProvider = $serviceProvider; + } + + + /** + * @param SubjectConfirmationConstraintValidator $constraint + * @return void + */ + public function addConstraintValidator( + SubjectConfirmationConstraintValidator $constraint + ) : void { + if ($constraint instanceof IdentityProviderAware) { + $constraint->setIdentityProvider($this->identityProvider); + } + + if ($constraint instanceof ServiceProviderAware) { + $constraint->setServiceProvider($this->serviceProvider); + } + + $this->constraints[] = $constraint; + } + + + /** + * @param SubjectConfirmation $subjectConfirmation + * @return Result + */ + public function validate(SubjectConfirmation $subjectConfirmation) : Result + { + $result = new Result(); + foreach ($this->constraints as $validator) { + $validator->validate($subjectConfirmation, $result); + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AttributeQuery.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AttributeQuery.php new file mode 100644 index 000000000..8102aa236 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AttributeQuery.php @@ -0,0 +1,187 @@ +attributes = []; + $this->nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + + if ($xml === null) { + return; + } + + $firstAttribute = true; + /** @var \DOMElement[] $attributes */ + $attributes = Utils::xpQuery($xml, './saml_assertion:Attribute'); + foreach ($attributes as $attribute) { + if (!$attribute->hasAttribute('Name')) { + throw new \Exception('Missing name on element.'); + } + $name = $attribute->getAttribute('Name'); + + if ($attribute->hasAttribute('NameFormat')) { + $nameFormat = $attribute->getAttribute('NameFormat'); + } else { + $nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + } + + if ($firstAttribute) { + $this->nameFormat = $nameFormat; + $firstAttribute = false; + } else { + if ($this->nameFormat !== $nameFormat) { + $this->nameFormat = Constants::NAMEFORMAT_UNSPECIFIED; + } + } + + if (!array_key_exists($name, $this->attributes)) { + $this->attributes[$name] = []; + } + + $values = Utils::xpQuery($attribute, './saml_assertion:AttributeValue'); + foreach ($values as $value) { + $this->attributes[$name][] = trim($value->textContent); + } + } + } + + + /** + * Retrieve all requested attributes. + * + * @return array All requested attributes, as an associative array. + */ + public function getAttributes() : array + { + return $this->attributes; + } + + + /** + * Set all requested attributes. + * + * @param array $attributes All requested attributes, as an associative array. + * @return void + */ + public function setAttributes(array $attributes) : void + { + $this->attributes = $attributes; + } + + + /** + * Retrieve the NameFormat used on all attributes. + * + * If more than one NameFormat is used in the received attributes, this + * returns the unspecified NameFormat. + * + * @return string The NameFormat used on all attributes. + */ + public function getAttributeNameFormat() : string + { + return $this->nameFormat; + } + + + /** + * Set the NameFormat used on all attributes. + * + * @param string $nameFormat The NameFormat used on all attributes. + * @return void + */ + public function setAttributeNameFormat(string $nameFormat) : void + { + $this->nameFormat = $nameFormat; + } + + + /** + * Convert the attribute query message to an XML element. + * + * @return \DOMElement This attribute query. + */ + public function toUnsignedXML() : DOMElement + { + $root = parent::toUnsignedXML(); + + foreach ($this->attributes as $name => $values) { + $attribute = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:Attribute'); + $root->appendChild($attribute); + $attribute->setAttribute('Name', $name); + + if ($this->nameFormat !== Constants::NAMEFORMAT_UNSPECIFIED) { + $attribute->setAttribute('NameFormat', $this->nameFormat); + } + + foreach ($values as $value) { + if (is_string($value)) { + $type = 'xs:string'; + } elseif (is_int($value)) { + $type = 'xs:integer'; + } else { + $type = null; + } + + $attributeValue = Utils::addString( + $attribute, + Constants::NS_SAML, + 'saml:AttributeValue', + strval($value) + ); + if ($type !== null) { + $attributeValue->setAttributeNS(Constants::NS_XSI, 'xsi:type', $type); + } + } + } + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AuthnRequest.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AuthnRequest.php new file mode 100644 index 000000000..a3756a46b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/AuthnRequest.php @@ -0,0 +1,934 @@ +forceAuthn = Utils::parseBoolean($xml, 'ForceAuthn', false); + $this->isPassive = Utils::parseBoolean($xml, 'IsPassive', false); + + if ($xml->hasAttribute('AssertionConsumerServiceURL')) { + $this->assertionConsumerServiceURL = $xml->getAttribute('AssertionConsumerServiceURL'); + } + + if ($xml->hasAttribute('ProtocolBinding')) { + $this->protocolBinding = $xml->getAttribute('ProtocolBinding'); + } + + if ($xml->hasAttribute('AttributeConsumingServiceIndex')) { + $this->attributeConsumingServiceIndex = intval($xml->getAttribute('AttributeConsumingServiceIndex')); + } + + if ($xml->hasAttribute('AssertionConsumerServiceIndex')) { + $this->assertionConsumerServiceIndex = intval($xml->getAttribute('AssertionConsumerServiceIndex')); + } + + if ($xml->hasAttribute('ProviderName')) { + $this->ProviderName = $xml->getAttribute('ProviderName'); + } + + $this->parseSubject($xml); + $this->parseNameIdPolicy($xml); + $this->parseRequestedAuthnContext($xml); + $this->parseScoping($xml); + $this->parseConditions($xml); + } + + + /** + * @param $xml + * @throws \Exception + * @return void + */ + private function parseSubject(DOMElement $xml) : void + { + /** @var \DOMElement[] $subject */ + $subject = Utils::xpQuery($xml, './saml_assertion:Subject'); + if (empty($subject)) { + return; + } + + if (count($subject) > 1) { + throw new \Exception('More than one in .'); + } + $subject = $subject[0]; + + /** @var \DOMElement[] $nameId */ + $nameId = Utils::xpQuery( + $subject, + './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData' + ); + if (empty($nameId)) { + throw new \Exception('Missing or in .'); + } elseif (count($nameId) > 1) { + throw new \Exception('More than one or in .'); + } + $nameId = $nameId[0]; + if ($nameId->localName === 'EncryptedData') { // the NameID element is encrypted + $this->encryptedNameId = $nameId; + } else { + $this->nameId = new NameID($nameId); + } + + /** @var \DOMElement[] $subjectConfirmation */ + $subjectConfirmation = Utils::xpQuery($subject, './saml_assertion:SubjectConfirmation'); + foreach ($subjectConfirmation as $sc) { + $this->subjectConfirmation[] = new SubjectConfirmation($sc); + } + } + + + /** + * @param \DOMElement $xml + * @throws \Exception + * @return void + */ + protected function parseNameIdPolicy(DOMElement $xml) : void + { + /** @var \DOMElement[] $nameIdPolicy */ + $nameIdPolicy = Utils::xpQuery($xml, './saml_protocol:NameIDPolicy'); + if (empty($nameIdPolicy)) { + return; + } + + $nameIdPolicy = $nameIdPolicy[0]; + if ($nameIdPolicy->hasAttribute('Format')) { + $this->nameIdPolicy['Format'] = $nameIdPolicy->getAttribute('Format'); + } + if ($nameIdPolicy->hasAttribute('SPNameQualifier')) { + $this->nameIdPolicy['SPNameQualifier'] = $nameIdPolicy->getAttribute('SPNameQualifier'); + } + if ($nameIdPolicy->hasAttribute('AllowCreate')) { + $this->nameIdPolicy['AllowCreate'] = Utils::parseBoolean($nameIdPolicy, 'AllowCreate', false); + } + } + + + /** + * @param \DOMElement $xml + * @return void + */ + protected function parseRequestedAuthnContext(DOMElement $xml) : void + { + /** @var \DOMElement[] $requestedAuthnContext */ + $requestedAuthnContext = Utils::xpQuery($xml, './saml_protocol:RequestedAuthnContext'); + if (empty($requestedAuthnContext)) { + return; + } + + $requestedAuthnContext = $requestedAuthnContext[0]; + + $rac = [ + 'AuthnContextClassRef' => [], + 'Comparison' => Constants::COMPARISON_EXACT, + ]; + + /** @var \DOMElement[] $accr */ + $accr = Utils::xpQuery($requestedAuthnContext, './saml_assertion:AuthnContextClassRef'); + foreach ($accr as $i) { + $rac['AuthnContextClassRef'][] = trim($i->textContent); + } + + if ($requestedAuthnContext->hasAttribute('Comparison')) { + $rac['Comparison'] = $requestedAuthnContext->getAttribute('Comparison'); + } + + $this->requestedAuthnContext = $rac; + } + + + /** + * @param \DOMElement $xml + * @throws \Exception + * @return void + */ + protected function parseScoping(DOMElement $xml) : void + { + /** @var \DOMElement[] $scoping */ + $scoping = Utils::xpQuery($xml, './saml_protocol:Scoping'); + if (empty($scoping)) { + return; + } + + $scoping = $scoping[0]; + + if ($scoping->hasAttribute('ProxyCount')) { + $this->ProxyCount = (int) $scoping->getAttribute('ProxyCount'); + } + /** @var \DOMElement[] $idpEntries */ + $idpEntries = Utils::xpQuery($scoping, './saml_protocol:IDPList/saml_protocol:IDPEntry'); + + foreach ($idpEntries as $idpEntry) { + if (!$idpEntry->hasAttribute('ProviderID')) { + throw new \Exception("Could not get ProviderID from Scoping/IDPEntry element in AuthnRequest object"); + } + $this->IDPList[] = $idpEntry->getAttribute('ProviderID'); + } + + /** @var \DOMElement[] $requesterIDs */ + $requesterIDs = Utils::xpQuery($scoping, './saml_protocol:RequesterID'); + foreach ($requesterIDs as $requesterID) { + $this->RequesterID[] = trim($requesterID->textContent); + } + } + + + /** + * @param \DOMElement $xml + * @return void + */ + protected function parseConditions(DOMElement $xml) : void + { + /** @var \DOMElement[] $conditions */ + $conditions = Utils::xpQuery($xml, './saml_assertion:Conditions'); + if (empty($conditions)) { + return; + } + $conditions = $conditions[0]; + + /** @var \DOMElement[] $ar */ + $ar = Utils::xpQuery($conditions, './saml_assertion:AudienceRestriction'); + if (empty($ar)) { + return; + } + $ar = $ar[0]; + + /** @var \DOMElement[] $audiences */ + $audiences = Utils::xpQuery($ar, './saml_assertion:Audience'); + $this->audiences = array(); + foreach ($audiences as $a) { + $this->audiences[] = trim($a->textContent); + } + } + + + /** + * Retrieve the NameIdPolicy. + * + * @see \SAML2\AuthnRequest::setNameIdPolicy() + * @return array The NameIdPolicy. + */ + public function getNameIdPolicy() : array + { + return $this->nameIdPolicy; + } + + + /** + * Set the NameIDPolicy. + * + * This function accepts an array with the following options: + * - 'Format' (string) + * - 'SPNameQualifier' (string) + * - 'AllowCreate' (bool) + * + * @param array $nameIdPolicy The NameIDPolicy. + * @return void + */ + public function setNameIdPolicy(array $nameIdPolicy) : void + { + if (isset($nameIdPolicy['Format']) && !is_string($nameIdPolicy['Format'])) { + throw InvalidArgumentException::invalidType('string', $nameIdPolicy['Format']); + } + if (isset($nameIdPolicy['SPNameQualifier']) && !is_string($nameIdPolicy['SPNameQualifier'])) { + throw InvalidArgumentException::invalidType('string', $nameIdPolicy['SPNameQualifier']); + } + if (isset($nameIdPolicy['AllowCreate']) && !is_bool($nameIdPolicy['AllowCreate'])) { + throw InvalidArgumentException::invalidType('bool', $nameIdPolicy['AllowCreate']); + } + + $this->nameIdPolicy = $nameIdPolicy; + } + + + /** + * Retrieve the value of the ForceAuthn attribute. + * + * @return bool The ForceAuthn attribute. + */ + public function getForceAuthn() : bool + { + return $this->forceAuthn; + } + + + /** + * Set the value of the ForceAuthn attribute. + * + * @param bool $forceAuthn The ForceAuthn attribute. + * @return void + */ + public function setForceAuthn(bool $forceAuthn) : void + { + $this->forceAuthn = $forceAuthn; + } + + + /** + * Retrieve the value of the ProviderName attribute. + * + * @return string|null The ProviderName attribute. + */ + public function getProviderName() : ?string + { + return $this->ProviderName; + } + + + /** + * Set the value of the ProviderName attribute. + * + * @param string $ProviderName The ProviderName attribute. + * @return void + */ + public function setProviderName(string $ProviderName) : void + { + $this->ProviderName = $ProviderName; + } + + + /** + * Retrieve the value of the IsPassive attribute. + * + * @return bool The IsPassive attribute. + */ + public function getIsPassive() : bool + { + return $this->isPassive; + } + + + /** + * Set the value of the IsPassive attribute. + * + * @param bool $isPassive The IsPassive attribute. + * @return void + */ + public function setIsPassive(bool $isPassive) : void + { + $this->isPassive = $isPassive; + } + + + /** + * Retrieve the audiences from the request. + * This may be an empty string, in which case no audience is included. + * + * @return array The audiences. + */ + public function getAudiences() : array + { + return $this->audiences; + } + + + /** + * Set the audiences to send in the request. + * This may be an empty string, in which case no audience will be sent. + * + * @param array $audiences The audiences. + * @return void + */ + public function setAudiences(array $audiences) : void + { + $this->audiences = $audiences; + } + + + /** + * This function sets the scoping for the request. + * See Core 3.4.1.2 for the definition of scoping. + * Currently we support an IDPList of idpEntries. + * + * Each idpEntries consists of an array, containing + * keys (mapped to attributes) and corresponding values. + * Allowed attributes: Loc, Name, ProviderID. + * + * For backward compatibility, an idpEntries can also + * be a string instead of an array, where each string + * is mapped to the value of attribute ProviderID. + * + * @param array $IDPList List of idpEntries to scope the request to. + * @return void + */ + public function setIDPList(array $IDPList) : void + { + $this->IDPList = $IDPList; + } + + + /** + * This function retrieves the list of providerIDs from this authentication request. + * Currently we only support a list of ipd ientity id's. + * + * @return array List of idp EntityIDs from the request + */ + public function getIDPList() : array + { + return $this->IDPList; + } + + + /** + * @param int $ProxyCount + * @return void + */ + public function setProxyCount(int $ProxyCount) : void + { + $this->ProxyCount = $ProxyCount; + } + + + /** + * @return int|null + */ + public function getProxyCount() : ?int + { + return $this->ProxyCount; + } + + + /** + * @param array $RequesterID + * @return void + */ + public function setRequesterID(array $RequesterID) : void + { + $this->RequesterID = $RequesterID; + } + + + /** + * @return array + */ + public function getRequesterID() : array + { + return $this->RequesterID; + } + + + /** + * Retrieve the value of the AssertionConsumerServiceURL attribute. + * + * @return string|null The AssertionConsumerServiceURL attribute. + */ + public function getAssertionConsumerServiceURL() : ?string + { + return $this->assertionConsumerServiceURL; + } + + + /** + * Set the value of the AssertionConsumerServiceURL attribute. + * + * @param string|null $assertionConsumerServiceURL The AssertionConsumerServiceURL attribute. + * @return void + */ + public function setAssertionConsumerServiceURL(string $assertionConsumerServiceURL = null) : void + { + $this->assertionConsumerServiceURL = $assertionConsumerServiceURL; + } + + + /** + * Retrieve the value of the ProtocolBinding attribute. + * + * @return string|null The ProtocolBinding attribute. + */ + public function getProtocolBinding() : ?string + { + return $this->protocolBinding; + } + + + /** + * Set the value of the ProtocolBinding attribute. + * + * @param string $protocolBinding The ProtocolBinding attribute. + * @return void + */ + public function setProtocolBinding(string $protocolBinding = null) : void + { + $this->protocolBinding = $protocolBinding; + } + + + /** + * Retrieve the value of the AttributeConsumingServiceIndex attribute. + * + * @return int|null The AttributeConsumingServiceIndex attribute. + */ + public function getAttributeConsumingServiceIndex() : ?int + { + return $this->attributeConsumingServiceIndex; + } + + + /** + * Set the value of the AttributeConsumingServiceIndex attribute. + * + * @param int|null $attributeConsumingServiceIndex The AttributeConsumingServiceIndex attribute. + * @return void + */ + public function setAttributeConsumingServiceIndex(int $attributeConsumingServiceIndex = null) : void + { + $this->attributeConsumingServiceIndex = $attributeConsumingServiceIndex; + } + + + /** + * Retrieve the value of the AssertionConsumerServiceIndex attribute. + * + * @return int|null The AssertionConsumerServiceIndex attribute. + */ + public function getAssertionConsumerServiceIndex() : ?int + { + return $this->assertionConsumerServiceIndex; + } + + + /** + * Set the value of the AssertionConsumerServiceIndex attribute. + * + * @param int|null $assertionConsumerServiceIndex The AssertionConsumerServiceIndex attribute. + * @return void + */ + public function setAssertionConsumerServiceIndex(int $assertionConsumerServiceIndex = null) : void + { + $this->assertionConsumerServiceIndex = $assertionConsumerServiceIndex; + } + + + /** + * Retrieve the RequestedAuthnContext. + * + * @return array|null The RequestedAuthnContext. + */ + public function getRequestedAuthnContext() : ?array + { + return $this->requestedAuthnContext; + } + + + /** + * Set the RequestedAuthnContext. + * + * @param array|null $requestedAuthnContext The RequestedAuthnContext. + * @return void + */ + public function setRequestedAuthnContext(array $requestedAuthnContext = null) : void + { + $this->requestedAuthnContext = $requestedAuthnContext; + } + + + /** + * Retrieve the NameId of the subject in the assertion. + * + * @throws \Exception + * @return \SAML2\XML\saml\NameID|null The name identifier of the assertion. + */ + public function getNameId() : ?NameID + { + if ($this->encryptedNameId !== null) { + throw new \Exception('Attempted to retrieve encrypted NameID without decrypting it first.'); + } + + return $this->nameId; + } + + + /** + * Set the NameId of the subject in the assertion. + * + * @param \SAML2\XML\saml\NameID|null $nameId The name identifier of the assertion. + * @return void + */ + public function setNameId(NameID $nameId = null) : void + { + $this->nameId = $nameId; + } + + + /** + * Encrypt the NameID in the AuthnRequest. + * + * @param XMLSecurityKey $key The encryption key. + * @return void + */ + public function encryptNameId(XMLSecurityKey $key) : void + { + Assert::notNull($this->nameId, 'Cannot encrypt NameID if no NameID has been set.'); + + /* First create a XML representation of the NameID. */ + $doc = new DOMDocument(); + $root = $doc->createElement('root'); + $doc->appendChild($root); + /** @psalm-suppress PossiblyNullReference */ + $this->nameId->toXML($root); + /** @var \DOMElement $nameId */ + $nameId = $root->firstChild; + + Utils::getContainer()->debugMessage($nameId, 'encrypt'); + + /* Encrypt the NameID. */ + $enc = new XMLSecEnc(); + $enc->setNode($nameId); + // @codingStandardsIgnoreStart + $enc->type = XMLSecEnc::Element; + // @codingStandardsIgnoreEnd + + $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); + $symmetricKey->generateSessionKey(); + $enc->encryptKey($key, $symmetricKey); + + /** + * @var \DOMElement encryptedNameId + * @psalm-suppress UndefinedClass + */ + $this->encryptedNameId = $enc->encryptNode($symmetricKey); + $this->nameId = null; + } + + + /** + * Decrypt the NameId of the subject in the assertion. + * + * @param XMLSecurityKey $key The decryption key. + * @param array $blacklist Blacklisted decryption algorithms. + * @return void + */ + public function decryptNameId(XMLSecurityKey $key, array $blacklist = []) : void + { + if ($this->encryptedNameId === null) { + /* No NameID to decrypt. */ + return; + } + + $nameId = Utils::decryptElement($this->encryptedNameId, $key, $blacklist); + Utils::getContainer()->debugMessage($nameId, 'decrypt'); + $this->nameId = new NameID($nameId); + + $this->encryptedNameId = null; + } + + + /** + * Retrieve the SubjectConfirmation elements we have in our Subject element. + * + * @return \SAML2\XML\saml\SubjectConfirmation[] + */ + public function getSubjectConfirmation() : array + { + return $this->subjectConfirmation; + } + + + /** + * Set the SubjectConfirmation elements that should be included in the assertion. + * + * @param array \SAML2\XML\saml\SubjectConfirmation[] + * @return void + */ + public function setSubjectConfirmation(array $subjectConfirmation) : void + { + $this->subjectConfirmation = $subjectConfirmation; + } + + + /** + * Convert this authentication request to an XML element. + * + * @return \DOMElement This authentication request. + */ + public function toUnsignedXML() : DOMElement + { + $root = parent::toUnsignedXML(); + + if ($this->forceAuthn) { + $root->setAttribute('ForceAuthn', 'true'); + } + + if (!empty($this->ProviderName)) { + $root->setAttribute('ProviderName', $this->ProviderName); + } + + if ($this->isPassive) { + $root->setAttribute('IsPassive', 'true'); + } + + if ($this->assertionConsumerServiceIndex !== null) { + $root->setAttribute('AssertionConsumerServiceIndex', strval($this->assertionConsumerServiceIndex)); + } else { + if ($this->assertionConsumerServiceURL !== null) { + $root->setAttribute('AssertionConsumerServiceURL', $this->assertionConsumerServiceURL); + } + if ($this->protocolBinding !== null) { + $root->setAttribute('ProtocolBinding', $this->protocolBinding); + } + } + + if ($this->attributeConsumingServiceIndex !== null) { + $root->setAttribute('AttributeConsumingServiceIndex', strval($this->attributeConsumingServiceIndex)); + } + + $this->addSubject($root); + + if (!empty($this->nameIdPolicy)) { + $nameIdPolicy = $this->document->createElementNS(Constants::NS_SAMLP, 'NameIDPolicy'); + if (array_key_exists('Format', $this->nameIdPolicy)) { + $nameIdPolicy->setAttribute('Format', $this->nameIdPolicy['Format']); + } + if (array_key_exists('SPNameQualifier', $this->nameIdPolicy)) { + $nameIdPolicy->setAttribute('SPNameQualifier', $this->nameIdPolicy['SPNameQualifier']); + } + if (array_key_exists('AllowCreate', $this->nameIdPolicy)) { + $nameIdPolicy->setAttribute('AllowCreate', ($this->nameIdPolicy['AllowCreate']) ? 'true' : 'false'); + } + $root->appendChild($nameIdPolicy); + } + + $this->addConditions($root); + + $rac = $this->requestedAuthnContext; + if (!empty($rac) && !empty($rac['AuthnContextClassRef'])) { + $e = $this->document->createElementNS(Constants::NS_SAMLP, 'RequestedAuthnContext'); + $root->appendChild($e); + if (isset($rac['Comparison']) && $rac['Comparison'] !== Constants::COMPARISON_EXACT) { + $e->setAttribute('Comparison', $rac['Comparison']); + } + foreach ($rac['AuthnContextClassRef'] as $accr) { + Utils::addString($e, Constants::NS_SAML, 'AuthnContextClassRef', $accr); + } + } + + if ($this->ProxyCount !== null || count($this->IDPList) > 0 || count($this->RequesterID) > 0) { + $scoping = $this->document->createElementNS(Constants::NS_SAMLP, 'Scoping'); + $root->appendChild($scoping); + if ($this->ProxyCount !== null) { + $scoping->setAttribute('ProxyCount', strval($this->ProxyCount)); + } + if (count($this->IDPList) > 0) { + $idplist = $this->document->createElementNS(Constants::NS_SAMLP, 'IDPList'); + foreach ($this->IDPList as $provider) { + $idpEntry = $this->document->createElementNS(Constants::NS_SAMLP, 'IDPEntry'); + if (is_string($provider)) { + $idpEntry->setAttribute('ProviderID', $provider); + } elseif (is_array($provider)) { + foreach ($provider as $attribute => $value) { + if (in_array($attribute, [ + 'ProviderID', + 'Loc', + 'Name' + ], true)) { + $idpEntry->setAttribute($attribute, $value); + } + } + } + $idplist->appendChild($idpEntry); + } + $scoping->appendChild($idplist); + } + if (count($this->RequesterID) > 0) { + Utils::addStrings($scoping, Constants::NS_SAMLP, 'RequesterID', false, $this->RequesterID); + } + } + + return $root; + } + + + /** + * Add a Subject-node to the assertion. + * + * @param \DOMElement $root The assertion element we should add the subject to. + * @return void + */ + private function addSubject(DOMElement $root) : void + { + // If there is no nameId (encrypted or not) there is nothing to create a subject for + if ($this->nameId === null && $this->encryptedNameId === null) { + return; + } + + $subject = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:Subject'); + $root->appendChild($subject); + + if ($this->encryptedNameId === null) { + $this->nameId->toXML($subject); + } else { + $eid = $subject->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:EncryptedID'); + $eid->appendChild($subject->ownerDocument->importNode($this->encryptedNameId, true)); + $subject->appendChild($eid); + } + + foreach ($this->subjectConfirmation as $sc) { + $sc->toXML($subject); + } + } + + + /** + * Add a Conditions-node to the request. + * + * @param \DOMElement $root The request element we should add the conditions to. + * @return void + */ + private function addConditions(DOMElement $root) : void + { + if ($this->audiences !== []) { + $document = $root->ownerDocument; + + $conditions = $document->createElementNS(Constants::NS_SAML, 'saml:Conditions'); + $root->appendChild($conditions); + + $ar = $document->createElementNS(Constants::NS_SAML, 'saml:AudienceRestriction'); + $conditions->appendChild($ar); + + Utils::addStrings($ar, Constants::NS_SAML, 'saml:Audience', false, $this->getAudiences()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Binding.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Binding.php new file mode 100644 index 000000000..48552da7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Binding.php @@ -0,0 +1,167 @@ +getLogger(); + $logger->warning('Unable to find the SAML 2 binding used for this request.'); + $logger->warning('Request method: '.var_export($_SERVER['REQUEST_METHOD'], true)); + if (!empty($_GET)) { + $logger->warning("GET parameters: '".implode("', '", array_map('addslashes', array_keys($_GET)))."'"); + } + if (!empty($_POST)) { + $logger->warning("POST parameters: '".implode("', '", array_map('addslashes', array_keys($_POST)))."'"); + } + if (isset($_SERVER['CONTENT_TYPE'])) { + $logger->warning('Content-Type: '.var_export($_SERVER['CONTENT_TYPE'], true)); + } + + throw new UnsupportedBindingException('Unable to find the SAML 2 binding used for this request.'); + } + + + /** + * Retrieve the destination of a message. + * + * @return string|null $destination The destination the message will be delivered to. + */ + public function getDestination() : ?string + { + return $this->destination; + } + + + /** + * Override the destination of a message. + * + * Set to null to use the destination set in the message. + * + * @param string|null $destination The destination the message should be delivered to. + * @return void + */ + public function setDestination(string $destination = null) : void + { + $this->destination = $destination; + } + + + /** + * Send a SAML 2 message. + * + * This function will send a message using the specified binding. + * The message will be delivered to the destination set in the message. + * + * @param \SAML2\Message $message The message which should be sent. + * @return void + */ + abstract public function send(Message $message) : void; + + + /** + * Receive a SAML 2 message. + * + * This function will extract the message from the current request. + * An exception will be thrown if we are unable to process the message. + * + * @return \SAML2\Message The received message. + */ + abstract public function receive(): Message; +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Exception/InvalidCertificateStructureException.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Exception/InvalidCertificateStructureException.php new file mode 100644 index 000000000..5c6ff17f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/Exception/InvalidCertificateStructureException.php @@ -0,0 +1,16 @@ + $value) { + $this->offsetSet($property, $value); + } + } + + + /** + * Whether or not the key is configured to be used for usage given + * + * @param string $usage + * @return bool + */ + public function canBeUsedFor(string $usage) : bool + { + if (!in_array($usage, static::getValidKeyUsages(), true)) { + throw new InvalidKeyUsageException($usage); + } + + return isset($this->keyData[$usage]) && $this->keyData[$usage]; + } + + + /** + * Returns the list of valid key usage options + * @return array + */ + public static function getValidKeyUsages() : array + { + return [ + self::USAGE_ENCRYPTION, + self::USAGE_SIGNING + ]; + } + + + /** + * @param mixed $offset + * @throws InvalidArgumentException + * @return bool + * + * Type hint not possible due to upstream method signature + */ + public function offsetExists($offset) : bool + { + if (!is_string($offset)) { + throw InvalidArgumentException::invalidType('string', $offset); + } + return array_key_exists($offset, $this->keyData); + } + + + /** + * @param mixed $offset + * @throws InvalidArgumentException + * @return mixed + * + * Type hint not possible due to upstream method signature + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + if (!is_string($offset)) { + throw InvalidArgumentException::invalidType('string', $offset); + } + return $this->keyData[$offset]; + } + + + /** + * @param mixed $offset + * @param mixed $value + * @throws InvalidArgumentException + * @return void + */ + public function offsetSet($offset, $value) : void + { + if (!is_string($offset)) { + throw InvalidArgumentException::invalidType('string', $offset); + } + $this->keyData[$offset] = $value; + } + + + /** + * @param mixed $offset + * @throws InvalidArgumentException + * @return void + * + * Type hint not possible due to upstream method signature + */ + public function offsetUnset($offset) : void + { + if (!is_string($offset)) { + throw InvalidArgumentException::invalidType('string', $offset); + } + unset($this->keyData[$offset]); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/KeyCollection.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/KeyCollection.php new file mode 100644 index 000000000..3b44cbce7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/KeyCollection.php @@ -0,0 +1,31 @@ +loadedKeys = new KeyCollection(); + } + + + /** + * Extracts the public keys given by the configuration. Mainly exists for BC purposes. + * Prioritisation order is keys > certData > certificate + * + * @param \SAML2\Configuration\CertificateProvider $config + * @param string|null $usage + * @param bool $required + * @return \SAML2\Certificate\KeyCollection + */ + public static function extractPublicKeys( + CertificateProvider $config, + string $usage = null, + bool $required = false + ) : KeyCollection { + $keyLoader = new self(); + + return $keyLoader->loadKeysFromConfiguration($config, $usage, $required); + } + + + /** + * @param \SAML2\Configuration\CertificateProvider $config + * @param null|string $usage + * @param bool $required + * @return \SAML2\Certificate\KeyCollection + */ + public function loadKeysFromConfiguration( + CertificateProvider $config, + string $usage = null, + bool $required = false + ) : KeyCollection { + $keys = $config->getKeys(); + $certificateData = $config->getCertificateData(); + $certificateFile = $config->getCertificateFile(); + + if ($keys !== null) { + $this->loadKeys($keys, $usage); + } elseif ($certificateData !== null) { + $this->loadCertificateData($certificateData); + } elseif ($certificateFile !== null) { + $this->loadCertificateFile($certificateFile); + } + + if ($required && !$this->hasKeys()) { + throw new NoKeysFoundException( + 'No keys found in configured metadata, please ensure that either the "keys", "certData" or ' + .'"certificate" entries is available.' + ); + } + + return $this->getKeys(); + } + + + /** + * Loads the keys given, optionally excluding keys when a usage is given and they + * are not configured to be used with the usage given + * + * @param array|\Traversable $configuredKeys + * @param string|null $usage + * @return void + */ + public function loadKeys($configuredKeys, string $usage = null) : void + { + foreach ($configuredKeys as $keyData) { + if (isset($keyData['X509Certificate'])) { + $key = new X509($keyData); + } else { + $key = new Key($keyData); + } + + if ($usage && !$key->canBeUsedFor($usage)) { + continue; + } + + $this->loadedKeys->add($key); + } + } + + + /** + * Attempts to load a key based on the given certificateData + * + * @param string $certificateData + * @return void + */ + public function loadCertificateData(string $certificateData) : void + { + $this->loadedKeys->add(X509::createFromCertificateData($certificateData)); + } + + + /** + * Loads the certificate in the file given + * + * @param string $certificateFile the full path to the cert file. + * @return void + */ + public function loadCertificateFile(string $certificateFile) : void + { + $certificate = File::getFileContents($certificateFile); + + if (!Certificate::hasValidStructure($certificate)) { + throw new InvalidCertificateStructureException(sprintf( + 'Could not find PEM encoded certificate in "%s"', + $certificateFile + )); + } + + // capture the certificate contents without the delimiters + preg_match(Certificate::CERTIFICATE_PATTERN, $certificate, $matches); + $this->loadedKeys->add(X509::createFromCertificateData($matches[1])); + } + + + /** + * @return \SAML2\Certificate\KeyCollection + */ + public function getKeys() : KeyCollection + { + return $this->loadedKeys; + } + + + /** + * @return bool + */ + public function hasKeys() : bool + { + return count($this->loadedKeys) && true; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKey.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKey.php new file mode 100644 index 000000000..3b7f56289 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKey.php @@ -0,0 +1,44 @@ + $keyContents, self::USAGE_ENCRYPTION => true]; + if ($passphrase) { + $keyData['passphrase'] = $passphrase; + } + + return new self($keyData); + } + + + /** + * @return string + */ + public function getKeyAsString() : string + { + return $this->keyData['PEM']; + } + + + /** + * @return string|null + */ + public function getPassphrase() : ?string + { + return isset($this->keyData['passphrase']) ? $this->keyData['passphrase'] : null; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKeyLoader.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKeyLoader.php new file mode 100644 index 000000000..5b7dd8ca2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/PrivateKeyLoader.php @@ -0,0 +1,87 @@ +isFile()) { + $privateKey = File::getFileContents($key->getFilePath()); + } else { + $privateKey = $key->getContents(); + } + + return PrivateKey::create($privateKey, $key->getPassPhrase()); + } + + + /** + * @param \SAML2\Configuration\DecryptionProvider $identityProvider + * @param \SAML2\Configuration\DecryptionProvider $serviceProvider + * @throws \Exception + * @return \SAML2\Utilities\ArrayCollection + */ + public function loadDecryptionKeys( + DecryptionProvider $identityProvider, + DecryptionProvider $serviceProvider + ) : ArrayCollection { + $decryptionKeys = new ArrayCollection(); + + $senderSharedKey = $identityProvider->getSharedKey(); + if ($senderSharedKey !== null) { + $key = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); + $key->loadKey($senderSharedKey); + $decryptionKeys->add($key); + + return $decryptionKeys; + } + + $newPrivateKey = $serviceProvider->getPrivateKey(PrivateKeyConfiguration::NAME_NEW); + if ($newPrivateKey instanceof PrivateKeyConfiguration) { + $loadedKey = $this->loadPrivateKey($newPrivateKey); + $decryptionKeys->add($this->convertPrivateKeyToRsaKey($loadedKey)); + } + + $privateKey = $serviceProvider->getPrivateKey(PrivateKeyConfiguration::NAME_DEFAULT, true); + $loadedKey = $this->loadPrivateKey($privateKey); + $decryptionKeys->add($this->convertPrivateKeyToRsaKey($loadedKey)); + + return $decryptionKeys; + } + + + /** + * @param \SAML2\Certificate\PrivateKey $privateKey + * @throws \Exception + * @return \RobRichards\XMLSecLibs\XMLSecurityKey + */ + private function convertPrivateKeyToRsaKey(PrivateKey $privateKey) : XMLSecurityKey + { + $key = new XMLSecurityKey(XMLSecurityKey::RSA_1_5, ['type' => 'private']); + $passphrase = $privateKey->getPassphrase(); + if ($passphrase) { + $key->passphrase = $passphrase; + } + + $key->loadKey($privateKey->getKeyAsString()); + + return $key; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/X509.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/X509.php new file mode 100644 index 000000000..0a43c294a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Certificate/X509.php @@ -0,0 +1,55 @@ + true, + 'signing' => true, + 'type' => 'X509Certificate', + 'X509Certificate' => $certificateContents + ]; + + return new self($data); + } + + + /** + * {@inheritdoc} Best place to ensure the logic is encapsulated in a single place + * + * @param mixed $offset + * @param mixed $value + * @return void + * + * Type hint not possible due to upstream method signature + */ + public function offsetSet($offset, $value) : void + { + if ($offset === 'X509Certificate') { + $value = preg_replace('~\s+~', '', $value); + } + + parent::offsetSet($offset, $value); + } + + + /** + * Get the certificate representation + * + * @return string + */ + public function getCertificate() : string + { + return "-----BEGIN CERTIFICATE-----\n" + . chunk_split($this->keyData['X509Certificate'], 64) + . "-----END CERTIFICATE-----\n"; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/AbstractContainer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/AbstractContainer.php new file mode 100644 index 000000000..e6b0ac98b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/AbstractContainer.php @@ -0,0 +1,84 @@ +id; + } + + + /** + * Log an incoming message to the debug log. + * + * Type can be either: + * - **in** XML received from third party + * - **out** XML that will be sent to third party + * - **encrypt** XML that is about to be encrypted + * - **decrypt** XML that was just decrypted + * + * @param \DOMElement|string $message + * @param string $type + * @return void + */ + public function debugMessage($message, string $type) : void + { + $this->debugMessages[$type] = $message; + } + + + /** + * Trigger the user to perform a GET to the given URL with the given data. + * + * @param string $url + * @param array $data + * @return void + */ + public function redirect(string $url, array $data = []) : void + { + $this->redirectUrl = $url; + $this->redirectData = $data; + } + + + /** + * Trigger the user to perform a POST to the given URL with the given data. + * + * @param string|null $url + * @param array $data + * @return void + */ + public function postRedirect(string $url = null, array $data = []) : void + { + $this->postRedirectUrl = $url; + $this->postRedirectData = $data; + } + + + /** + * @return string + */ + public function getTempDir() : string + { + return sys_get_temp_dir(); + } + + + /** + * @param string $filename + * @param string $data + * @param int|null $mode + * @return void + */ + public function writeFile(string $filename, string $data, int $mode = null) : void + { + if ($mode === null) { + $mode = 0600; + } + file_put_contents($filename, $data); + chmod($filename, $mode); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Container.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Container.php new file mode 100644 index 000000000..10e179e16 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Container.php @@ -0,0 +1,135 @@ +logger = new Logger(); + $this->utilsHttp = new HTTP(); + $this->utilsRandom = new Random(); + $this->utilsSystem = new System(); + $this->utilsXml = new XML(); + } + + + /** + * {@inheritdoc} + * @return \Psr\Log\LoggerInterface + */ + public function getLogger() : LoggerInterface + { + return $this->logger; + } + + + /** + * {@inheritdoc} + * @return string + */ + public function generateId() : string + { + return $this->utilsRandom->generateID(); + } + + + /** + * {@inheritdoc} + * @param mixed $message + * @param string $type + * @return void + */ + public function debugMessage($message, string $type) : void + { + $this->utilsXml->debugSAMLMessage($message, $type); + } + + + /** + * {@inheritdoc} + * @param string $url + * @param array $data + * @return void + */ + public function redirect(string $url, array $data = []) : void + { + $this->utilsHttp->redirectTrustedURL($url, $data); + } + + + /** + * {@inheritdoc} + * @param string $url + * @param array $data + * @return void + */ + public function postRedirect(string $url, array $data = []) : void + { + $this->utilsHttp->submitPOSTData($url, $data); + } + + + /** + * {@inheritdoc} + * @return string + */ + public function getTempDir() : string + { + return $this->utilsSystem->getTempDir(); + } + + + /** + * {@inheritdoc} + * @param string $filename + * @param string $date + * @param int|null $mode + * @return void + */ + public function writeFile(string $filename, string $data, int $mode = null) : void + { + if ($mode === null) { + $mode = 0600; + } + $this->utilsSystem->writeFile($filename, $data, $mode); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Logger.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Logger.php new file mode 100644 index 000000000..b318d86aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Compat/Ssp/Logger.php @@ -0,0 +1,201 @@ +alert($message, $context); + break; + case LogLevel::CRITICAL: + $this->critical($message, $context); + break; + case LogLevel::DEBUG: + $this->debug($message, $context); + break; + case LogLevel::EMERGENCY: + $this->emergency($message, $context); + break; + case LogLevel::ERROR: + $this->error($message, $context); + break; + case LogLevel::INFO: + $this->info($message, $context); + break; + case LogLevel::NOTICE: + $this->notice($message, $context); + break; + case LogLevel::WARNING: + $this->warning($message, $context); + break; + default: + throw new InvalidArgumentException("Unrecognized log level '$level''"); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ArrayAdapter.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ArrayAdapter.php new file mode 100644 index 000000000..493eb10b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ArrayAdapter.php @@ -0,0 +1,50 @@ +configuration = $configuration; + } + + + /** + * @param string $key + * @param mixed|null $defaultValue + * @return mixed + */ + public function get(string $key, $defaultValue = null) + { + if (!$this->has($key)) { + return $defaultValue; + } + + return $this->configuration[$key]; + } + + + /** + * @param string $key + * @return bool + */ + public function has(string $key) : bool + { + return array_key_exists($key, $this->configuration); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/CertificateProvider.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/CertificateProvider.php new file mode 100644 index 000000000..47d64cec3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/CertificateProvider.php @@ -0,0 +1,37 @@ +destination = $destination; + } + + + /** + * @param \SAML2\Configuration\Destination $otherDestination + * + * @return bool + */ + public function equals(Destination $otherDestination) : bool + { + return $this->destination === $otherDestination->destination; + } + + + /** + * @return string + */ + public function __toString() : string + { + return $this->destination; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/EntityIdProvider.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/EntityIdProvider.php new file mode 100644 index 000000000..9a79890de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/EntityIdProvider.php @@ -0,0 +1,16 @@ +get('keys'); + } + + + /** + * @return string|null + */ + public function getCertificateData() : ?string + { + return $this->get('certificateData'); + } + + + /** + * @return string|null + */ + public function getCertificateFile() : ?string + { + return $this->get('certificateFile'); + } + + + /** + * @return array|mixed|\Traversable|null + */ + public function getCertificateFingerprints() + { + return $this->get('certificateFingerprints'); + } + + + /** + * @return bool|null + */ + public function isAssertionEncryptionRequired() : ?bool + { + return $this->get('assertionEncryptionEnabled'); + } + + + /** + * @return string|null + */ + public function getSharedKey() : ?string + { + return $this->get('sharedKey'); + } + + + /** + * @return mixed|null + */ + public function hasBase64EncodedAttributes() + { + return $this->get('base64EncodedAttributes'); + } + + + /** + * @param string $name + * @param bool $required + * @return mixed|null + */ + public function getPrivateKey(string $name, bool $required = null) + { + if ($required === null) { + $required = false; + } + $privateKeys = $this->get('privateKeys'); + $key = array_filter($privateKeys, function (PrivateKey $key) use ($name) { + return $key->getName() === $name; + }); + + $keyCount = count($key); + if ($keyCount !== 1 && $required) { + throw new \RuntimeException(sprintf( + 'Attempted to get privateKey by name "%s", found "%d" keys, where only one was expected. Please ' + . 'verify that your configuration is correct', + $name, + $keyCount + )); + } + + if (!$keyCount) { + return null; + } + + return array_pop($key); + } + + + /** + * @return array|null + */ + public function getBlacklistedAlgorithms() : ?array + { + return $this->get('blacklistedEncryptionAlgorithms'); + } + + + /** + * @return string|null + */ + public function getEntityId() : ?string + { + return $this->get('entityId'); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/IdentityProviderAware.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/IdentityProviderAware.php new file mode 100644 index 000000000..72c74e896 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/IdentityProviderAware.php @@ -0,0 +1,18 @@ +filePathOrContents = $filePathOrContents; + $this->passphrase = $passphrase; + $this->name = $name; + $this->isFile = $isFile; + } + + + /** + * @return string + */ + public function getFilePath() : string + { + if (!$this->isFile()) { + throw new RuntimeException('No path provided.'); + } + + return $this->filePathOrContents; + } + + + /** + * @return bool + */ + public function hasPassPhrase() : bool + { + return $this->passphrase !== null; + } + + + /** + * @return string|null + */ + public function getPassPhrase() : ?string + { + return $this->passphrase; + } + + + /** + * @return string + */ + public function getName() : string + { + return $this->name; + } + + /** + * @return string + */ + public function getContents() : string + { + if ($this->isFile()) { + throw new RuntimeException('No contents provided'); + } + + return $this->filePathOrContents; + } + + /** + * @return bool + */ + public function isFile() : bool + { + return $this->isFile; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/Queryable.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/Queryable.php new file mode 100644 index 000000000..665bc4a2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/Queryable.php @@ -0,0 +1,31 @@ +get('keys'); + } + + + /** + * @return null|string + */ + public function getCertificateData() : ?string + { + return $this->get('certificateData'); + } + + + /** + * @return null|string + */ + public function getCertificateFile() : ?string + { + return $this->get('certificateFile'); + } + + + /** + * @return array|\Traversable|null + */ + public function getCertificateFingerprints() + { + return $this->get('certificateFingerprints'); + } + + + /** + * @return string|null + */ + public function getEntityId() : ?string + { + return $this->get('entityId'); + } + + + /** + * @return null|bool + */ + public function isAssertionEncryptionRequired() : ?bool + { + return $this->get('assertionEncryptionEnabled'); + } + + + /** + * @return null|string + */ + public function getSharedKey() : ?string + { + return $this->get('sharedKey'); + } + + + /** + * @param string $name + * @param bool $required + * @return mixed|null + */ + public function getPrivateKey(string $name, bool $required = null) + { + if ($required === null) { + $required = false; + } + $privateKeys = $this->get('privateKeys'); + $key = array_filter($privateKeys, function (PrivateKey $key) use ($name) { + return $key->getName() === $name; + }); + + $keyCount = count($key); + if ($keyCount !== 1 && $required) { + throw new \RuntimeException(sprintf( + 'Attempted to get privateKey by name "%s", found "%d" keys, where only one was expected. Please ' + . 'verify that your configuration is correct', + $name, + $keyCount + )); + } + + if (!$keyCount) { + return null; + } + + return array_pop($key); + } + + + /** + * @return array + */ + public function getBlacklistedAlgorithms() : array + { + return $this->get('blacklistedEncryptionAlgorithms', [XMLSecurityKey::RSA_1_5]); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ServiceProviderAware.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ServiceProviderAware.php new file mode 100644 index 000000000..f569bd23e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Configuration/ServiceProviderAware.php @@ -0,0 +1,17 @@ +hasValue($prefix.'keys')) { + $extracted['keys'] = $configuration->getArray($prefix.'keys'); + } + + // ported from + // https://github.com/simplesamlphp/simplesamlphp/blob/3d735912342767d391297cc5e13272a76730aca0/lib/SimpleSAML/Configuration.php#L1108 + if ($configuration->hasValue($prefix.'certData')) { + $extracted['certificateData'] = $configuration->getString($prefix.'certData'); + } + + // ported from + // https://github.com/simplesamlphp/simplesamlphp/blob/3d735912342767d391297cc5e13272a76730aca0/lib/SimpleSAML/Configuration.php#L1119 + if ($configuration->hasValue($prefix.'certificate')) { + $extracted['certificateData'] = $configuration->getString($prefix.'certificate'); + } + + $extracted['assertionEncryptionEnabled'] = $configuration->getBoolean('assertion.encryption', false); + + if ($configuration->hasValue('sharedKey')) { + $extracted['sharedKey'] = $configuration->getString('sharedKey'); + } + + return $extracted; + } + + + /** + * @param \SimpleSAML\Configuration $configuration + * @param array $baseConfiguration + * + * @return void + * + * @psalm-suppress UndefinedClass + */ + protected static function enrichForIdentityProvider(Configuration $configuration, array &$baseConfiguration) : void + { + $baseConfiguration['base64EncodedAttributes'] = $configuration->getBoolean('base64attributes', false); + $baseConfiguration['entityId'] = $configuration->getString('entityid'); + } + + + /** + * @param \SimpleSAML\Configuration $configuration + * @param array $baseConfiguration + * + * @return void + * + * @psalm-suppress UndefinedClass + */ + protected static function enrichForServiceProvider(Configuration $configuration, array &$baseConfiguration) : void + { + $baseConfiguration['entityId'] = $configuration->getString('entityid'); + } + + + /** + * @param \SimpleSAML\Configuration $configuration + * @param array $baseConfiguration + * + * @return void + * + * @psalm-suppress UndefinedClass + */ + protected static function enrichForDecryptionProvider( + Configuration $configuration, + array &$baseConfiguration + ) : void { + if ($configuration->hasValue('sharedKey')) { + $baseConfiguration['sharedKey'] = $configuration->getString('sharedKey', null); + } + + if ($configuration->hasValue('new_privatekey')) { + $baseConfiguration['privateKeys'][] = new PrivateKey( + $configuration->getString('new_privatekey'), + PrivateKey::NAME_NEW, + $configuration->getString('new_privatekey_pass', null) + ); + } + + if ($configuration->getBoolean('assertion.encryption', false)) { + $baseConfiguration['privateKeys'][] = new PrivateKey( + $configuration->getString('privatekey'), + PrivateKey::NAME_DEFAULT, + $configuration->getString('privatekey_pass', null) + ); + + if ($configuration->hasValue('encryption.blacklisted-algorithms')) { + $baseConfiguration['blacklistedEncryptionAlgorithms'] = $configuration + ->getValue('encryption.blacklisted-algorithms'); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Constants.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Constants.php new file mode 100644 index 000000000..0cc5cee71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Constants.php @@ -0,0 +1,455 @@ + + * and/or elements. + * + * Top-level status code. + */ + const STATUS_SUCCESS = 'urn:oasis:names:tc:SAML:2.0:status:Success'; + + /** + * The request could not be performed due to an error on the part of the requester. + * + * Top-level status code. + */ + const STATUS_REQUESTER = 'urn:oasis:names:tc:SAML:2.0:status:Requester'; + + /** + * The request could not be performed due to an error on the part of the SAML responder or SAML authority. + * + * Top-level status code. + */ + const STATUS_RESPONDER = 'urn:oasis:names:tc:SAML:2.0:status:Responder'; + + /** + * The SAML responder could not process the request because the version of the request message was incorrect. + * + * Top-level status code. + */ + const STATUS_VERSION_MISMATCH = 'urn:oasis:names:tc:SAML:2.0:status:VersionMismatch'; + + /** + * The responding provider was unable to successfully authenticate the principal. + * + * Second-level status code. + */ + const STATUS_AUTHN_FAILED = 'urn:oasis:names:tc:SAML:2.0:status:AuthnFailed'; + + /** + * Unexpected or invalid content was encountered within a or element. + * + * Second-level status code. + */ + const STATUS_INVALID_ATTR = 'urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue'; + + /** + * The responding provider cannot or will not support the requested name identifier policy. + * + * Second-level status code. + */ + const STATUS_INVALID_NAMEID_POLICY = 'urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy'; + + /** + * The specified authentication context requirements cannot be met by the responder. + * + * Second-level status code. + */ + const STATUS_NO_AUTHN_CONTEXT = 'urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext'; + + /** + * Used by an intermediary to indicate that none of the supported identity provider elements in an + * can be resolved or that none of the supported identity providers are available. + * + * Second-level status code. + */ + const STATUS_NO_AVAILABLE_IDP = 'urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP'; + + /** + * Indicates the responding provider cannot authenticate the principal passively, as has been requested. + * + * Second-level status code. + */ + const STATUS_NO_PASSIVE = 'urn:oasis:names:tc:SAML:2.0:status:NoPassive'; + + /** + * Used by an intermediary to indicate that none of the identity providers in an are + * supported by the intermediary. + * + * Second-level status code. + */ + const STATUS_NO_SUPPORTED_IDP = 'urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP'; + + /** + * Used by a session authority to indicate to a session participant that it was not able to propagate logout + * to all other session participants. + * + * Second-level status code. + */ + const STATUS_PARTIAL_LOGOUT = 'urn:oasis:names:tc:SAML:2.0:status:PartialLogout'; + + /** + * Indicates that a responding provider cannot authenticate the principal directly and is not permitted + * to proxy the request further. + * + * Second-level status code. + */ + const STATUS_PROXY_COUNT_EXCEEDED = 'urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded'; + + /** + * The SAML responder or SAML authority is able to process the request but has chosen not to respond. + * This status code MAY be used when there is concern about the security context of the request message or + * the sequence of request messages received from a particular requester. + * + * Second-level status code. + */ + const STATUS_REQUEST_DENIED = 'urn:oasis:names:tc:SAML:2.0:status:RequestDenied'; + + /** + * The SAML responder or SAML authority does not support the request. + * + * Second-level status code. + */ + const STATUS_REQUEST_UNSUPPORTED = 'urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported'; + + /** + * The SAML responder cannot process any requests with the protocol version specified in the request. + * + * Second-level status code. + */ + const STATUS_REQUEST_VERSION_DEPRECATED = 'urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated'; + + /** + * The SAML responder cannot process the request because the protocol version specified in the request message + * is a major upgrade from the highest protocol version supported by the responder. + * + * Second-level status code. + */ + const STATUS_REQUEST_VERSION_TOO_HIGH = 'urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh'; + + /** + * The SAML responder cannot process the request because the protocol version specified in the request message + * is too low. + * + * Second-level status code. + */ + const STATUS_REQUEST_VERSION_TOO_LOW = 'urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow'; + + /** + * The resource value provided in the request message is invalid or unrecognized. + * + * Second-level status code. + */ + const STATUS_RESOURCE_NOT_RECOGNIZED = 'urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized'; + + /** + * The response message would contain more elements than the SAML responder is able to return. + * + * Second-level status code. + */ + const STATUS_TOO_MANY_RESPONSES = 'urn:oasis:names:tc:SAML:2.0:status:TooManyResponses'; + + /** + * An entity that has no knowledge of a particular attribute profile has been presented with an attribute + * drawn from that profile. + * + * Second-level status code. + */ + const STATUS_UNKNOWN_ATTR_PROFILE = 'urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile'; + + /** + * The responding provider does not recognize the principal specified or implied by the request. + * + * Second-level status code. + */ + const STATUS_UNKNOWN_PRINCIPAL = 'urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal'; + + /** + * The SAML responder cannot properly fulfill the request using the protocol binding specified in the request. + * + * Second-level status code. + */ + const STATUS_UNSUPPORTED_BINDING = 'urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding'; + + /** + * The maximum size for any entityid as per specification + */ + public const ENTITYID_MAX_LENGTH = 1024; + + /** + * The maximum size for any entityid as per SAML2INT-specification + */ + public const SAML2INT_ENTITYID_MAX_LENGTH = 256; +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/DOMDocumentFactory.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/DOMDocumentFactory.php new file mode 100644 index 000000000..f69a49e4b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/DOMDocumentFactory.php @@ -0,0 +1,127 @@ +loadXML($xml, $options); + libxml_use_internal_errors($internalErrors); + + if (PHP_VERSION_ID < 80000) { + /** @psalm-suppress PossiblyUndefinedVariable */ + libxml_disable_entity_loader($entityLoader); + } + + if (!$loaded) { + $error = libxml_get_last_error(); + libxml_clear_errors(); + + throw new UnparseableXmlException($error); + } + + libxml_clear_errors(); + + foreach ($domDocument->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new RuntimeException( + 'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body' + ); + } + } + + return $domDocument; + } + + + /** + * @param string $file + * + * @return \DOMDocument + */ + public static function fromFile(string $file) : DOMDocument + { + if (!is_file($file)) { + throw new InvalidArgumentException(sprintf('Path "%s" is not a file', $file)); + } + + if (!is_readable($file)) { + throw new InvalidArgumentException(sprintf('File "%s" is not readable', $file)); + } + + // libxml_disable_entity_loader(true) disables \DOMDocument::load() method + // so we need to read the content and use \DOMDocument::loadXML() + $xml = file_get_contents($file); + if ($xml === false) { + throw new RuntimeException(sprintf( + 'Contents of readable file "%s" could not be gotten', + $file + )); + } + + if (trim($xml) === '') { + throw new RuntimeException(sprintf('File "%s" does not have content', $file)); + } + + return static::fromString($xml); + } + + + /** + * @return \DOMDocument + */ + public static function create() : DOMDocument + { + return new DOMDocument('1.0', 'UTF-8'); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/EncryptedAssertion.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/EncryptedAssertion.php new file mode 100644 index 000000000..fde149ac2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/EncryptedAssertion.php @@ -0,0 +1,152 @@ +.'); + } elseif (count($data) > 1) { + throw new \Exception('More than one encrypted data element in .'); + } + $this->encryptedData = $data[0]; + } + + + /** + * @return bool + */ + public function wasSignedAtConstruction() : bool + { + return $this->wasSignedAtConstruction; + } + + /** + * Set the assertion. + * + * @param \SAML2\Assertion $assertion The assertion. + * @param XMLSecurityKey $key The key we should use to encrypt the assertion. + * @throws \Exception + * @return void + */ + public function setAssertion(Assertion $assertion, XMLSecurityKey $key) : void + { + $xml = $assertion->toXML(); + + Utils::getContainer()->debugMessage($xml, 'encrypt'); + + $enc = new XMLSecEnc(); + $enc->setNode($xml); + $enc->type = XMLSecEnc::Element; + + switch ($key->type) { + case XMLSecurityKey::TRIPLEDES_CBC: + case XMLSecurityKey::AES128_CBC: + case XMLSecurityKey::AES192_CBC: + case XMLSecurityKey::AES256_CBC: + case XMLSecurityKey::AES128_GCM: + case XMLSecurityKey::AES192_GCM: + case XMLSecurityKey::AES256_GCM: + $symmetricKey = $key; + break; + + case XMLSecurityKey::RSA_1_5: + case XMLSecurityKey::RSA_OAEP_MGF1P: + $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); + $symmetricKey->generateSessionKey(); + + $enc->encryptKey($key, $symmetricKey); + + break; + + default: + throw new \Exception('Unknown key type for encryption: '.$key->type); + } + + /** + * @var \DOMElement encryptedData + * @psalm-suppress UndefinedClass + */ + $this->encryptedData = $enc->encryptNode($symmetricKey); + } + + + /** + * Retrieve the assertion. + * + * @param XMLSecurityKey $inputKey The key we should use to decrypt the assertion. + * @param array $blacklist Blacklisted decryption algorithms. + * @return \SAML2\Assertion The decrypted assertion. + */ + public function getAssertion(XMLSecurityKey $inputKey, array $blacklist = []) : Assertion + { + $assertionXML = Utils::decryptElement($this->encryptedData, $inputKey, $blacklist); + + Utils::getContainer()->debugMessage($assertionXML, 'decrypt'); + + return new Assertion($assertionXML); + } + + + /** + * Convert this encrypted assertion to an XML element. + * + * @param \DOMNode|null $parentElement The DOM node the assertion should be created in. + * @return \DOMElement This encrypted assertion. + */ + public function toXML(DOMNode $parentElement = null) : DOMElement + { + if ($parentElement === null) { + $document = DOMDocumentFactory::create(); + $parentElement = $document; + } else { + $document = $parentElement->ownerDocument; + } + + $root = $document->createElementNS(Constants::NS_SAML, 'saml:'.'EncryptedAssertion'); + $parentElement->appendChild($root); + + $root->appendChild($document->importNode($this->encryptedData, true)); + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..0335e7790 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/InvalidArgumentException.php @@ -0,0 +1,27 @@ + or element. + * + * @package simplesamlphp/saml2 + */ +class InvalidAttrNameOrValueException extends ProtocolViolationException +{ + /** + * @param string $message + */ + public function __construct(string $message = 'Invalid attribute name or value.') + { + parent::__construct($message); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/InvalidNameIDPolicyException.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/InvalidNameIDPolicyException.php new file mode 100644 index 000000000..57187cb84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Exception/Protocol/InvalidNameIDPolicyException.php @@ -0,0 +1,23 @@ + 'WARNING', + LIBXML_ERR_ERROR => 'ERROR', + LIBXML_ERR_FATAL => 'FATAL' + ]; + + + /** + * Constructor for UnparseableXmlException + * + * @param \LibXMLError $error + */ + public function __construct(LibXMLError $error) + { + $message = sprintf( + 'Unable to parse XML - "%s[%d]": "%s" in "%s" at line %d on column %d"', + self::$levelMap[$error->level], + $error->code, + $error->message, + $error->file ?: '(string)', + $error->line, + $error->column + ); + + parent::__construct($message); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPArtifact.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPArtifact.php new file mode 100644 index 000000000..812f29ae6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPArtifact.php @@ -0,0 +1,200 @@ + + * @package SimpleSAMLphp + */ +class HTTPArtifact extends Binding +{ + /** + * @var mixed + */ + private $spMetadata; + + + /** + * Create the redirect URL for a message. + * + * @param \SAML2\Message $message The message. + * @throws \Exception + * @return string The URL the user should be redirected to in order to send a message. + */ + public function getRedirectURL(Message $message) : string + { + /** @psalm-suppress UndefinedClass */ + $config = Configuration::getInstance(); + + /** @psalm-suppress UndefinedClass */ + $store = StoreFactory::getInstance($config->getString('store.type')); + if ($store === false) { + throw new \Exception('Unable to send artifact without a datastore configured.'); + } + + $generatedId = pack('H*', bin2hex(openssl_random_pseudo_bytes(20))); + $issuer = $message->getIssuer(); + if ($issuer === null) { + throw new \Exception('Cannot get redirect URL, no Issuer set in the message.'); + } + $artifact = base64_encode("\x00\x04\x00\x00".sha1($issuer->getValue(), true).$generatedId); + $artifactData = $message->toUnsignedXML(); + $artifactDataString = $artifactData->ownerDocument->saveXML($artifactData); + + $store->set('artifact', $artifact, $artifactDataString, Temporal::getTime() + 15*60); + + $params = [ + 'SAMLart' => $artifact, + ]; + $relayState = $message->getRelayState(); + if ($relayState !== null) { + $params['RelayState'] = $relayState; + } + + $destination = $message->getDestination(); + if ($destination === null) { + throw new \Exception('Cannot get redirect URL, no destination set in the message.'); + } + $httpUtils = new HTTP(); + return $httpUtils->addURLparameters($destination, $params); + } + + + /** + * Send a SAML 2 message using the HTTP-Redirect binding. + * + * Note: This function never returns. + * + * @param \SAML2\Message $message The message we should send. + * @return void + */ + public function send(Message $message) : void + { + $destination = $this->getRedirectURL($message); + Utils::getContainer()->redirect($destination); + } + + + /** + * Receive a SAML 2 message sent using the HTTP-Artifact binding. + * + * Throws an exception if it is unable receive the message. + * + * @throws \Exception + * @return \SAML2\Message The received message. + */ + public function receive(): Message + { + if (array_key_exists('SAMLart', $_REQUEST)) { + $artifact = base64_decode($_REQUEST['SAMLart'], true); + $endpointIndex = bin2hex(substr($artifact, 2, 2)); + $sourceId = bin2hex(substr($artifact, 4, 20)); + } else { + throw new \Exception('Missing SAMLart parameter.'); + } + + /** @psalm-suppress UndefinedClass */ + $metadataHandler = MetaDataStorageHandler::getMetadataHandler(); + + $idpMetadata = $metadataHandler->getMetaDataConfigForSha1($sourceId, 'saml20-idp-remote'); + + if ($idpMetadata === null) { + throw new \Exception('No metadata found for remote provider with SHA1 ID: '.var_export($sourceId, true)); + } + + $endpoint = null; + foreach ($idpMetadata->getEndpoints('ArtifactResolutionService') as $ep) { + if ($ep['index'] === hexdec($endpointIndex)) { + $endpoint = $ep; + break; + } + } + + if ($endpoint === null) { + throw new \Exception('No ArtifactResolutionService with the correct index.'); + } + + Utils::getContainer()->getLogger()->debug("ArtifactResolutionService endpoint being used is := ".$endpoint['Location']); + + //Construct the ArtifactResolve Request + $ar = new ArtifactResolve(); + + /* Set the request attributes */ + $issuer = new Issuer(); + $issuer->setValue($this->spMetadata->getString('entityid')); + + $ar->setIssuer($issuer); + $ar->setArtifact($_REQUEST['SAMLart']); + $ar->setDestination($endpoint['Location']); + + // sign the request + /** @psalm-suppress UndefinedClass */ + MSG::addSign($this->spMetadata, $idpMetadata, $ar); // Shoaib - moved from the SOAPClient. + + $soap = new SOAPClient(); + + // Send message through SoapClient + /** @var \SimpleSAML\SAML2\XML\samlp\ArtifactResponse $artifactResponse */ + $artifactResponse = $soap->send($ar, $this->spMetadata, $idpMetadata); + + if (!$artifactResponse->isSuccess()) { + throw new \Exception('Received error from ArtifactResolutionService.'); + } + + $xml = $artifactResponse->getAny(); + if ($xml === null) { + /* Empty ArtifactResponse - possibly because of Artifact replay? */ + + throw new \Exception('Empty ArtifactResponse received, maybe a replay?'); + } + + $samlResponse = Message::fromXML($xml); + $samlResponse->addValidator([get_class($this), 'validateSignature'], $artifactResponse); + + if (isset($_REQUEST['RelayState'])) { + $samlResponse->setRelayState($_REQUEST['RelayState']); + } + + return $samlResponse; + } + + + /** + * @param \SimpleSAML\Configuration $sp + * + * @return void + * + * @psalm-suppress UndefinedClass + */ + public function setSPMetadata(Configuration $sp) : void + { + $this->spMetadata = $sp; + } + + + /** + * A validator which returns true if the ArtifactResponse was signed with the given key + * + * @param \SAML2\ArtifactResponse $message + * @param XMLSecurityKey $key + * @return bool + */ + public static function validateSignature(ArtifactResponse $message, XMLSecurityKey $key) : bool + { + return $message->validate($key); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPPost.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPPost.php new file mode 100644 index 000000000..6aac058cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPPost.php @@ -0,0 +1,109 @@ +destination === null) { + $destination = $message->getDestination(); + if ($destination === null) { + throw new \Exception('Cannot send message, no destination set.'); + } + } else { + $destination = $this->destination; + } + $relayState = $message->getRelayState(); + + $msgStr = $message->toSignedXML(); + + Utils::getContainer()->debugMessage($msgStr, 'out'); + $msgStr = $msgStr->ownerDocument->saveXML($msgStr); + + $msgStr = base64_encode($msgStr); + + if ($message instanceof Request) { + $msgType = 'SAMLRequest'; + } else { + $msgType = 'SAMLResponse'; + } + + $post = []; + $post[$msgType] = $msgStr; + + if ($relayState !== null) { + $post['RelayState'] = $relayState; + } + + Utils::getContainer()->postRedirect($destination, $post); + } + + + /** + * Receive a SAML 2 message sent using the HTTP-POST binding. + * + * Throws an exception if it is unable receive the message. + * + * @return \SAML2\Message The received message. + * @throws \Exception + */ + public function receive(): Message + { + if (array_key_exists('SAMLRequest', $_POST)) { + $msgStr = $_POST['SAMLRequest']; + } elseif (array_key_exists('SAMLResponse', $_POST)) { + $msgStr = $_POST['SAMLResponse']; + } else { + throw new \Exception('Missing SAMLRequest or SAMLResponse parameter.'); + } + + $msgStr = base64_decode($msgStr, true); + + $xml = new \DOMDocument(); + $xml->loadXML($msgStr); + $msgStr = $xml->saveXML(); + + $document = DOMDocumentFactory::fromString($msgStr); + Utils::getContainer()->debugMessage($document->documentElement, 'in'); + if (!$document->firstChild instanceof \DOMElement) { + throw new \Exception('Malformed SAML message received.'); + } + + $msg = Message::fromXML($document->firstChild); + + /** + * 3.5.5.2 - SAML Bindings + * + * If the message is signed, the Destination XML attribute in the root SAML element of the protocol + * message MUST contain the URL to which the sender has instructed the user agent to deliver the + * message. + */ + if ($msg->isMessageConstructedWithSignature()) { + Assert::notNull($msg->getDestination()); // Validation of the value must be done upstream + } + + if (array_key_exists('RelayState', $_POST)) { + $msg->setRelayState($_POST['RelayState']); + } + + return $msg; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPRedirect.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPRedirect.php new file mode 100644 index 000000000..ebd67933c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/HTTPRedirect.php @@ -0,0 +1,254 @@ +destination === null) { + $destination = $message->getDestination(); + if ($destination === null) { + throw new \Exception('Cannot build a redirect URL, no destination set.'); + } + } else { + $destination = $this->destination; + } + + $relayState = $message->getRelayState(); + + $key = $message->getSignatureKey(); + + $msgStr = $message->toUnsignedXML(); + + Utils::getContainer()->debugMessage($msgStr, 'out'); + $msgStr = $msgStr->ownerDocument->saveXML($msgStr); + + $msgStr = gzdeflate($msgStr); + $msgStr = base64_encode($msgStr); + + /* Build the query string. */ + + if ($message instanceof Request) { + $msg = 'SAMLRequest='; + } else { + $msg = 'SAMLResponse='; + } + $msg .= urlencode($msgStr); + + if ($relayState !== null) { + $msg .= '&RelayState='.urlencode($relayState); + } + + if ($key !== null) { // add the signature + /** @psalm-suppress PossiblyInvalidArgument */ + $msg .= '&SigAlg='.urlencode($key->type); + + $signature = $key->signData($msg); + $msg .= '&Signature='.urlencode(base64_encode($signature)); + } + + if (strpos($destination, '?') === false) { + $destination .= '?'.$msg; + } else { + $destination .= '&'.$msg; + } + + return $destination; + } + + + /** + * Send a SAML 2 message using the HTTP-Redirect binding. + * Note: This function never returns. + * + * @param \SAML2\Message $message The message we should send. + * @return void + */ + public function send(Message $message) : void + { + $destination = $this->getRedirectURL($message); + Utils::getContainer()->getLogger()->debug('Redirect to '.strlen($destination).' byte URL: '.$destination); + Utils::getContainer()->redirect($destination); + } + + + /** + * Receive a SAML 2 message sent using the HTTP-Redirect binding. + * + * Throws an exception if it is unable receive the message. + * + * @throws \Exception + * @return \SAML2\Message The received message. + * + * NPath is currently too high but solving that just moves code around. + */ + public function receive(): Message + { + $data = self::parseQuery(); + if (array_key_exists('SAMLRequest', $data)) { + $message = $data['SAMLRequest']; + } elseif (array_key_exists('SAMLResponse', $data)) { + $message = $data['SAMLResponse']; + } else { + throw new \Exception('Missing SAMLRequest or SAMLResponse parameter.'); + } + + if (isset($data['SAMLEncoding']) && $data['SAMLEncoding'] !== self::DEFLATE) { + throw new \Exception('Unknown SAMLEncoding: '.var_export($data['SAMLEncoding'], true)); + } + + $message = base64_decode($message, true); + if ($message === false) { + throw new \Exception('Error while base64 decoding SAML message.'); + } + + $message = gzinflate($message); + if ($message === false) { + throw new \Exception('Error while inflating SAML message.'); + } + + $document = DOMDocumentFactory::fromString($message); + Utils::getContainer()->debugMessage($document->documentElement, 'in'); + if (!$document->firstChild instanceof \DOMElement) { + throw new \Exception('Malformed SAML message received.'); + } + $message = Message::fromXML($document->firstChild); + + if (array_key_exists('RelayState', $data)) { + $message->setRelayState($data['RelayState']); + } + + if (!array_key_exists('Signature', $data)) { + return $message; + } + + /** + * 3.4.5.2 - SAML Bindings + * + * If the message is signed, the Destination XML attribute in the root SAML element of the protocol + * message MUST contain the URL to which the sender has instructed the user agent to deliver the + * message. + */ + Assert::notNull($message->getDestination()); // Validation of the value must be done upstream + + if (!array_key_exists('SigAlg', $data)) { + throw new \Exception('Missing signature algorithm.'); + } + + $signData = [ + 'Signature' => $data['Signature'], + 'SigAlg' => $data['SigAlg'], + 'Query' => $data['SignedQuery'], + ]; + + $message->addValidator([get_class($this), 'validateSignature'], $signData); + + return $message; + } + + + /** + * Helper function to parse query data. + * + * This function returns the query string split into key=>value pairs. + * It also adds a new parameter, SignedQuery, which contains the data that is + * signed. + * + * @return array The query data that is signed. + */ + private static function parseQuery() : array + { + /* + * Parse the query string. We need to do this ourself, so that we get access + * to the raw (urlencoded) values. This is required because different software + * can urlencode to different values. + */ + $data = []; + $relayState = ''; + $sigAlg = ''; + $sigQuery = ''; + foreach (explode('&', $_SERVER['QUERY_STRING']) as $e) { + $tmp = explode('=', $e, 2); + $name = $tmp[0]; + if (count($tmp) === 2) { + $value = $tmp[1]; + } else { + /* No value for this parameter. */ + $value = ''; + } + $name = urldecode($name); + $data[$name] = urldecode($value); + + switch ($name) { + case 'SAMLRequest': + case 'SAMLResponse': + $sigQuery = $name.'='.$value; + break; + case 'RelayState': + $relayState = '&RelayState='.$value; + break; + case 'SigAlg': + $sigAlg = '&SigAlg='.$value; + break; + } + } + + $data['SignedQuery'] = $sigQuery.$relayState.$sigAlg; + + return $data; + } + + + /** + * Validate the signature on a HTTP-Redirect message. + * + * Throws an exception if we are unable to validate the signature. + * + * @param array $data The data we need to validate the query string. + * @param XMLSecurityKey $key The key we should validate the query against. + * @throws \Exception + * @return void + */ + public static function validateSignature(array $data, XMLSecurityKey $key) : void + { + Assert::keyExists($data, "Query"); + Assert::keyExists($data, "SigAlg"); + Assert::keyExists($data, "Signature"); + + $query = $data['Query']; + $sigAlg = $data['SigAlg']; + $signature = $data['Signature']; + + $signature = base64_decode($signature); + + if ($key->type !== XMLSecurityKey::RSA_SHA256) { + throw new \Exception('Invalid key type for validating signature on query string.'); + } + if ($key->type !== $sigAlg) { + $key = Utils::castKey($key, $sigAlg); + } + + if ($key->verifySignature($query, $signature) !== 1) { + throw new \Exception('Unable to validate signature on query string.'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutRequest.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutRequest.php new file mode 100644 index 000000000..2ad66d435 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutRequest.php @@ -0,0 +1,343 @@ +sessionIndexes = []; + + if ($xml === null) { + return; + } + + if ($xml->hasAttribute('NotOnOrAfter')) { + $this->notOnOrAfter = Utils::xsDateTimeToTimestamp($xml->getAttribute('NotOnOrAfter')); + } + + if ($xml->hasAttribute('Reason')) { + $this->reason = $xml->getAttribute('Reason'); + } + + /** @var \DOMElement[] $nameId */ + $nameId = Utils::xpQuery($xml, './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData'); + if (empty($nameId)) { + throw new \Exception('Missing or in .'); + } elseif (count($nameId) > 1) { + throw new \Exception('More than one or in .'); + } + if ($nameId[0]->localName === 'EncryptedData') { + /* The NameID element is encrypted. */ + $this->encryptedNameId = $nameId[0]; + } else { + $this->nameId = new NameID($nameId[0]); + } + + /** @var \DOMElement[] $sessionIndexes */ + $sessionIndexes = Utils::xpQuery($xml, './saml_protocol:SessionIndex'); + foreach ($sessionIndexes as $sessionIndex) { + $this->sessionIndexes[] = trim($sessionIndex->textContent); + } + } + + + /** + * Retrieve the expiration time of this request. + * + * @return int|null The expiration time of this request. + */ + public function getNotOnOrAfter() : ?int + { + return $this->notOnOrAfter; + } + + + /** + * Set the expiration time of this request. + * + * @param int|null $notOnOrAfter The expiration time of this request. + * @return void + */ + public function setNotOnOrAfter(int $notOnOrAfter = null) : void + { + $this->notOnOrAfter = $notOnOrAfter; + } + + /** + * Retrieve the reason for this request. + * + * @return string|null The reason for this request. + */ + public function getReason(): ?string + { + return $this->reason; + } + + + /** + * Set the reason for this request. + * + * @param string|null $reason The optional reason for this request in URN format + * @return void + */ + public function setReason($reason = null): void + { + $this->reason = $reason; + } + + + /** + * Check whether the NameId is encrypted. + * + * @return bool True if the NameId is encrypted, false if not. + */ + public function isNameIdEncrypted() : bool + { + if ($this->encryptedNameId !== null) { + return true; + } + + return false; + } + + + /** + * Encrypt the NameID in the LogoutRequest. + * + * @param XMLSecurityKey $key The encryption key. + * @return void + */ + public function encryptNameId(XMLSecurityKey $key) : void + { + if ($this->nameId === null) { + throw new \Exception('Cannot encrypt NameID without a NameID set.'); + } + /* First create a XML representation of the NameID. */ + $doc = DOMDocumentFactory::create(); + $root = $doc->createElement('root'); + $doc->appendChild($root); + $this->nameId->toXML($root); + /** @var \DOMElement $nameId */ + $nameId = $root->firstChild; + + Utils::getContainer()->debugMessage($nameId, 'encrypt'); + + /* Encrypt the NameID. */ + $enc = new XMLSecEnc(); + $enc->setNode($nameId); + $enc->type = XMLSecEnc::Element; + + $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES128_CBC); + $symmetricKey->generateSessionKey(); + $enc->encryptKey($key, $symmetricKey); + + /** + * @var \DOMElement encryptedNameId + * @psalm-suppress UndefinedClass + */ + $this->encryptedNameId = $enc->encryptNode($symmetricKey); + $this->nameId = null; + } + + + /** + * Decrypt the NameID in the LogoutRequest. + * + * @param XMLSecurityKey $key The decryption key. + * @param array $blacklist Blacklisted decryption algorithms. + * @return void + */ + public function decryptNameId(XMLSecurityKey $key, array $blacklist = []) : void + { + if ($this->encryptedNameId === null) { + /* No NameID to decrypt. */ + return; + } + + $nameId = Utils::decryptElement($this->encryptedNameId, $key, $blacklist); + Utils::getContainer()->debugMessage($nameId, 'decrypt'); + $this->nameId = new NameID($nameId); + $this->encryptedNameId = null; + } + + + /** + * Retrieve the name identifier of the session that should be terminated. + * + * @throws \Exception + * @return \SAML2\XML\saml\NameID|null The name identifier of the session that should be terminated. + */ + public function getNameId() : ?NameID + { + if ($this->encryptedNameId !== null) { + throw new \Exception('Attempted to retrieve encrypted NameID without decrypting it first.'); + } + + return $this->nameId; + } + + + /** + * Set the name identifier of the session that should be terminated. + * + * @param \SAML2\XML\saml\NameID $nameId The name identifier of the session that should be terminated. + * @return void + */ + public function setNameId(NameID $nameId) : void + { + $this->nameId = $nameId; + } + + + /** + * Retrieve the SessionIndexes of the sessions that should be terminated. + * + * @return array The SessionIndexes, or an empty array if all sessions should be terminated. + */ + public function getSessionIndexes() : array + { + return $this->sessionIndexes; + } + + + /** + * Set the SessionIndexes of the sessions that should be terminated. + * + * @param array $sessionIndexes The SessionIndexes, or an empty array if all sessions should be terminated. + * @return void + */ + public function setSessionIndexes(array $sessionIndexes) : void + { + $this->sessionIndexes = $sessionIndexes; + } + + + /** + * Retrieve the sesion index of the session that should be terminated. + * + * @return string|null The sesion index of the session that should be terminated. + */ + public function getSessionIndex() : ?string + { + if (empty($this->sessionIndexes)) { + return null; + } + + return $this->sessionIndexes[0]; + } + + + /** + * Set the sesion index of the session that should be terminated. + * + * @param string|null $sessionIndex The sesion index of the session that should be terminated. + * @return void + */ + public function setSessionIndex(string $sessionIndex = null) : void + { + if (is_null($sessionIndex)) { + $this->sessionIndexes = []; + } else { + $this->sessionIndexes = [$sessionIndex]; + } + } + + + /** + * Convert this logout request message to an XML element. + * + * @return \DOMElement This logout request. + */ + public function toUnsignedXML() : DOMElement + { + if ($this->encryptedNameId === null && $this->nameId === null) { + throw new \Exception('Cannot convert LogoutRequest to XML without a NameID set.'); + } + + $root = parent::toUnsignedXML(); + + if ($this->notOnOrAfter !== null) { + $root->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter)); + } + + if ($this->reason !== null) { + $root->setAttribute('Reason', $this->reason); + } + + if ($this->encryptedNameId === null) { + $this->nameId->toXML($root); + } else { + $eid = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:'.'EncryptedID'); + $root->appendChild($eid); + $eid->appendChild($root->ownerDocument->importNode($this->encryptedNameId, true)); + } + + foreach ($this->sessionIndexes as $sessionIndex) { + Utils::addString($root, Constants::NS_SAMLP, 'SessionIndex', $sessionIndex); + } + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutResponse.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutResponse.php new file mode 100644 index 000000000..c588fad84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/LogoutResponse.php @@ -0,0 +1,27 @@ +tagName = $tagName; + + $this->id = Utils::getContainer()->generateId(); + $this->issueInstant = Temporal::getTime(); + $this->certificates = []; + $this->validators = []; + + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('ID')) { + throw new \Exception('Missing ID attribute on SAML message.'); + } + $this->id = $xml->getAttribute('ID'); + + if ($xml->getAttribute('Version') !== '2.0') { + /* Currently a very strict check. */ + throw new \Exception('Unsupported version: '.$xml->getAttribute('Version')); + } + + $this->issueInstant = Utils::xsDateTimeToTimestamp($xml->getAttribute('IssueInstant')); + + if ($xml->hasAttribute('Destination')) { + $this->destination = $xml->getAttribute('Destination'); + } + + if ($xml->hasAttribute('Consent')) { + $this->consent = $xml->getAttribute('Consent'); + } + + /** @var \DOMElement[] $issuer */ + $issuer = Utils::xpQuery($xml, './saml_assertion:Issuer'); + if (!empty($issuer)) { + $this->issuer = new Issuer($issuer[0]); + } + + $this->validateSignature($xml); + + $this->extensions = Extensions::getList($xml); + } + + + /** + * Validate the signature element of a SAML message, and configure this object appropriately to perform the + * signature verification afterwards. + * + * Please note this method does NOT verify the signature, it just validates the signature construction and prepares + * this object to do the verification. + * + * @param \DOMElement $xml The SAML message whose signature we want to validate. + * @return void + */ + private function validateSignature(DOMElement $xml) : void + { + try { + /** @var \DOMAttr[] $signatureMethod */ + $signatureMethod = Utils::xpQuery($xml, './ds:Signature/ds:SignedInfo/ds:SignatureMethod/@Algorithm'); + if (empty($signatureMethod)) { + throw new \Exception('No Algorithm specified in signature.'); + } + + $sig = Utils::validateElement($xml); + + if ($sig !== false) { + $this->messageContainedSignatureUponConstruction = true; + $this->certificates = $sig['Certificates']; + $this->validators[] = [ + 'Function' => ['\SAML2\Utils', 'validateSignature'], + 'Data' => $sig, + ]; + $this->signatureMethod = $signatureMethod[0]->value; + } + } catch (\Exception $e) { + // ignore signature validation errors + } + } + + + /** + * Add a method for validating this message. + * + * This function is used by the HTTP-Redirect binding, to make it possible to + * check the signature against the one included in the query string. + * + * @param callable $function The function which should be called + * @param mixed $data The data that should be included as the first parameter to the function + * @return void + */ + public function addValidator(callable $function, $data) : void + { + $this->validators[] = [ + 'Function' => $function, + 'Data' => $data, + ]; + } + + + /** + * Validate this message against a public key. + * + * true is returned on success, false is returned if we don't have any + * signature we can validate. An exception is thrown if the signature + * validation fails. + * + * @param XMLSecurityKey $key The key we should check against + * @throws \Exception + * @return bool true on success, false when we don't have a signature + */ + public function validate(XMLSecurityKey $key) : bool + { + if (count($this->validators) === 0) { + return false; + } + + $exceptions = []; + + foreach ($this->validators as $validator) { + $function = $validator['Function']; + $data = $validator['Data']; + + try { + call_user_func($function, $data, $key); + /* We were able to validate the message with this validator. */ + + return true; + } catch (\Exception $e) { + $exceptions[] = $e; + } + } + + /* No validators were able to validate the message. */ + throw $exceptions[0]; + } + + + /** + * Retrieve the identifier of this message. + * + * @return string The identifier of this message + */ + public function getId() : string + { + return $this->id; + } + + + /** + * Set the identifier of this message. + * + * @param string $id The new identifier of this message + * @return void + */ + public function setId(string $id) : void + { + $this->id = $id; + } + + + /** + * Retrieve the issue timestamp of this message. + * + * @return int The issue timestamp of this message, as an UNIX timestamp + */ + public function getIssueInstant() : int + { + return $this->issueInstant; + } + + + /** + * Set the issue timestamp of this message. + * + * @param int $issueInstant The new issue timestamp of this message, as an UNIX timestamp + * @return void + */ + public function setIssueInstant(int $issueInstant) : void + { + $this->issueInstant = $issueInstant; + } + + + /** + * Retrieve the destination of this message. + * + * @return string|null The destination of this message, or NULL if no destination is given + */ + public function getDestination() : ?string + { + return $this->destination; + } + + + /** + * Set the destination of this message. + * + * @param string|null $destination The new destination of this message + * @return void + */ + public function setDestination(string $destination = null) : void + { + $this->destination = $destination; + } + + + /** + * Set the given consent for this message. + * Most likely (though not required) a value of urn:oasis:names:tc:SAML:2.0:consent. + * + * @see \SAML2\Constants + * @param string $consent + * @return void + */ + public function setConsent(string $consent) : void + { + $this->consent = $consent; + } + + + /** + * Get the given consent for this message. + * Most likely (though not required) a value of urn:oasis:names:tc:SAML:2.0:consent. + * + * @see \SAML2\Constants + * @return string|null Consent + */ + public function getConsent() : ?string + { + return $this->consent; + } + + + /** + * Retrieve the issuer if this message. + * + * @return \SAML2\XML\saml\Issuer|null The issuer of this message, or NULL if no issuer is given + */ + public function getIssuer() : ?Issuer + { + return $this->issuer; + } + + + /** + * Set the issuer of this message. + * + * @param \SAML2\XML\saml\Issuer|null $issuer The new issuer of this message + * @return void + */ + public function setIssuer(Issuer $issuer = null) : void + { + $this->issuer = $issuer; + } + + + /** + * Query whether or not the message contained a signature at the root level when the object was constructed. + * + * @return bool + */ + public function isMessageConstructedWithSignature() : bool + { + return $this->messageContainedSignatureUponConstruction; + } + + + /** + * Retrieve the RelayState associated with this message. + * + * @return string|null The RelayState, or NULL if no RelayState is given + */ + public function getRelayState() : ?string + { + return $this->relayState; + } + + + /** + * Set the RelayState associated with this message. + * + * @param string|null $relayState The new RelayState + * @return void + */ + public function setRelayState(string $relayState = null) : void + { + $this->relayState = $relayState; + } + + + /** + * Convert this message to an unsigned XML document. + * This method does not sign the resulting XML document. + * + * @return \DOMElement The root element of the DOM tree + */ + public function toUnsignedXML() : DOMElement + { + $this->document = DOMDocumentFactory::create(); + + $root = $this->document->createElementNS(Constants::NS_SAMLP, 'samlp:'.$this->tagName); + $this->document->appendChild($root); + + /* Ugly hack to add another namespace declaration to the root element. */ + $root->setAttributeNS(Constants::NS_SAML, 'saml:tmp', 'tmp'); + $root->removeAttributeNS(Constants::NS_SAML, 'tmp'); + + $root->setAttribute('ID', $this->id); + $root->setAttribute('Version', '2.0'); + $root->setAttribute('IssueInstant', gmdate('Y-m-d\TH:i:s\Z', $this->issueInstant)); + + if ($this->destination !== null) { + $root->setAttribute('Destination', $this->destination); + } + if ($this->consent !== Constants::CONSENT_UNSPECIFIED) { + $root->setAttribute('Consent', $this->consent); + } + + if ($this->issuer !== null) { + $this->issuer->toXML($root); + } + + Extensions::addList($root, $this->extensions); + + return $root; + } + + + /** + * Convert this message to a signed XML document. + * This method sign the resulting XML document if the private key for + * the signature is set. + * + * @return \DOMElement The root element of the DOM tree + */ + public function toSignedXML() : DOMElement + { + $root = $this->toUnsignedXML(); + + if ($this->signatureKey === null) { + /* We don't have a key to sign it with. */ + + return $root; + } + + /* Find the position we should insert the signature node at. */ + if ($this->issuer !== null) { + /* + * We have an issuer node. The signature node should come + * after the issuer node. + */ + $issuerNode = $root->firstChild; + /** @psalm-suppress PossiblyNullPropertyFetch */ + $insertBefore = $issuerNode->nextSibling; + } else { + /* No issuer node - the signature element should be the first element. */ + $insertBefore = $root->firstChild; + } + + Utils::insertSignature($this->signatureKey, $this->certificates, $root, $insertBefore); + + return $root; + } + + + /** + * Retrieve the private key we should use to sign the message. + * + * @return XMLSecurityKey|null The key, or NULL if no key is specified + */ + public function getSignatureKey() : ?XMLSecurityKey + { + return $this->signatureKey; + } + + + /** + * Set the private key we should use to sign the message. + * If the key is null, the message will be sent unsigned. + * + * @param XMLSecurityKey|null $signatureKey + * @return void + */ + public function setSignatureKey(XMLSecurityKey $signatureKey = null) : void + { + $this->signatureKey = $signatureKey; + } + + + /** + * Set the certificates that should be included in the message. + * The certificates should be strings with the PEM encoded data. + * + * @param array $certificates An array of certificates + * @return void + */ + public function setCertificates(array $certificates) : void + { + $this->certificates = $certificates; + } + + + /** + * Retrieve the certificates that are included in the message. + * + * @return array An array of certificates + */ + public function getCertificates() : array + { + return $this->certificates; + } + + + /** + * Convert an XML element into a message. + * + * @param \DOMElement $xml The root XML element + * @throws \Exception + * @return \SAML2\Message The message + */ + public static function fromXML(\DOMElement $xml) : Message + { + if ($xml->namespaceURI !== Constants::NS_SAMLP) { + throw new \Exception('Unknown namespace of SAML message: '.var_export($xml->namespaceURI, true)); + } + + switch ($xml->localName) { + case 'AttributeQuery': + return new AttributeQuery($xml); + case 'AuthnRequest': + return new AuthnRequest($xml); + case 'LogoutResponse': + return new LogoutResponse($xml); + case 'LogoutRequest': + return new LogoutRequest($xml); + case 'Response': + return new Response($xml); + case 'ArtifactResponse': + return new ArtifactResponse($xml); + case 'ArtifactResolve': + return new ArtifactResolve($xml); + default: + throw new \Exception('Unknown SAML message: '.var_export($xml->localName, true)); + } + } + + + /** + * Retrieve the Extensions. + * + * @return \SAML2\XML\samlp\Extensions[] + */ + public function getExtensions() : array + { + return $this->extensions; + } + + + /** + * Set the Extensions. + * + * @param array $extensions The Extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param \SAML2\XML\samlp\Extensions $extensions The Extensions + * @return void + */ + public function addExtension(Extensions $extension) : void + { + $this->extensions[] = $extension; + } + + + /** + * @return null|string + */ + public function getSignatureMethod() : ?string + { + return $this->signatureMethod; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Request.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Request.php new file mode 100644 index 000000000..1ba202db1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Request.php @@ -0,0 +1,18 @@ +assertions = []; + + if ($xml === null) { + return; + } + + foreach ($xml->childNodes as $node) { + if ($node->namespaceURI !== Constants::NS_SAML) { + continue; + } else if (!($node instanceof DOMElement)) { + continue; + } + + if ($node->localName === 'Assertion') { + $this->assertions[] = new Assertion($node); + } elseif ($node->localName === 'EncryptedAssertion') { + $this->assertions[] = new EncryptedAssertion($node); + } + } + } + + + /** + * Retrieve the assertions in this response. + * + * @return \SAML2\Assertion[]|\SAML2\EncryptedAssertion[] + */ + public function getAssertions() : array + { + return $this->assertions; + } + + + /** + * Set the assertions that should be included in this response. + * + * @param \SAML2\Assertion[]|\SAML2\EncryptedAssertion[] $assertions The assertions. + * @return void + */ + public function setAssertions(array $assertions) : void + { + $this->assertions = $assertions; + } + + + /** + * Convert the response message to an XML element. + * + * @return \DOMElement This response. + */ + public function toUnsignedXML() : DOMElement + { + $root = parent::toUnsignedXML(); + + /** @var \SAML2\Assertion|\SAML2\EncryptedAssertion $assertion */ + foreach ($this->assertions as $assertion) { + $assertion->toXML($root); + } + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/InvalidResponseException.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/InvalidResponseException.php new file mode 100644 index 000000000..56491a1bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/InvalidResponseException.php @@ -0,0 +1,11 @@ +getErrors()) + ); + + return new self($message); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/UnencryptedAssertionFoundException.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/UnencryptedAssertionFoundException.php new file mode 100644 index 000000000..de4d2e881 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Exception/UnencryptedAssertionFoundException.php @@ -0,0 +1,12 @@ +logger = $logger; + $this->signatureValidator = new Validator($logger); + } + + + /** + * @param \SAML2\Configuration\ServiceProvider $serviceProviderConfiguration + * @param \SAML2\Configuration\IdentityProvider $identityProviderConfiguration + * @param \SAML2\Configuration\Destination $currentDestination + * @param \SAML2\Response $response + * + * @return \SAML2\Utilities\ArrayCollection Collection of \SAML2\Assertion objects + */ + public function process( + ServiceProvider $serviceProviderConfiguration, + IdentityProvider $identityProviderConfiguration, + Destination $currentDestination, + Response $response + ) : ArrayCollection { + $this->preconditionValidator = new PreconditionValidator($currentDestination); + $this->assertionProcessor = ProcessorBuilder::build( + $this->logger, + $this->signatureValidator, + $currentDestination, + $identityProviderConfiguration, + $serviceProviderConfiguration, + $response + ); + + $this->enforcePreconditions($response); + $this->verifySignature($response, $identityProviderConfiguration); + return $this->processAssertions($response); + } + + + /** + * Checks the preconditions that must be valid in order for the response to be processed. + * + * @param \SAML2\Response $response + * @throws PreconditionNotMetException + * @return void + */ + private function enforcePreconditions(Response $response) : void + { + $result = $this->preconditionValidator->validate($response); + + if (!$result->isValid()) { + throw PreconditionNotMetException::createFromValidationResult($result); + } + } + + + /** + * @param \SAML2\Response $response + * @param \SAML2\Configuration\IdentityProvider $identityProviderConfiguration + * @throws InvalidResponseException + * @return void + */ + private function verifySignature(Response $response, IdentityProvider $identityProviderConfiguration) : void + { + if (!$response->isMessageConstructedWithSignature()) { + $this->logger->info(sprintf( + 'SAMLResponse with id "%s" was not signed at root level, not attempting to verify the signature of the' + . ' reponse itself', + $response->getId() + )); + + return; + } + + $this->logger->info(sprintf( + 'Attempting to verify the signature of SAMLResponse with id "%s"', + $response->getId() + )); + + $this->responseIsSigned = true; + + if (!$this->signatureValidator->hasValidSignature($response, $identityProviderConfiguration)) { + throw new InvalidResponseException( + sprintf('The SAMLResponse with id "%s", does not have a valid signature', $response->getId()) + ); + } + } + + + /** + * @param \SAML2\Response $response + * @throws UnsignedResponseException + * @throws NoAssertionsFoundException + * @return \SAML2\Utilities\ArrayCollection + */ + private function processAssertions(Response $response) : ArrayCollection + { + $assertions = $response->getAssertions(); + if (empty($assertions)) { + throw new NoAssertionsFoundException('No assertions found in response from IdP.'); + } + + $decryptedAssertions = $this->assertionProcessor->decryptAssertions( + new ArrayCollection($assertions) + ); + + if (!$this->responseIsSigned) { + foreach ($assertions as $assertion) { + if (!$assertion->wasSignedAtConstruction()) { + throw new UnsignedResponseException( + 'Both the response and the assertion it contains are not signed.' + ); + } + } + } + + return $this->assertionProcessor->processAssertions($decryptedAssertions); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator.php new file mode 100644 index 000000000..c4c20df50 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator.php @@ -0,0 +1,17 @@ +expectedDestination = $destination; + } + + + /** + * @param Response $response + * @param Result $result + * @return void + */ + public function validate(Response $response, Result $result) : void + { + $destination = $response->getDestination(); + if ($destination === null) { + throw new \Exception('No destination set in the response.'); + } + if (!$this->expectedDestination->equals(new Destination($destination))) { + $result->addError(sprintf( + 'Destination in response "%s" does not match the expected destination "%s"', + $destination, + strval($this->expectedDestination) + )); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator/IsSuccessful.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator/IsSuccessful.php new file mode 100644 index 000000000..06440c7b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/ConstraintValidator/IsSuccessful.php @@ -0,0 +1,60 @@ +isSuccess()) { + $result->addError($this->buildMessage($response->getStatus())); + } + } + + + /** + * @param array $responseStatus + * + * @return string + */ + private function buildMessage(array $responseStatus) : string + { + return sprintf( + '%s%s%s', + $this->truncateStatus($responseStatus['Code']), + $responseStatus['SubCode'] ? '/'.$this->truncateStatus($responseStatus['SubCode']) : '', + $responseStatus['Message'] ? ' '.$responseStatus['Message'] : '' + ); + } + + + /** + * Truncate the status if it is prefixed by its urn. + * @param string $status + * + * @return string + */ + private function truncateStatus(string $status) : string + { + $prefixLength = strlen(Constants::STATUS_PREFIX); + if (strpos($status, Constants::STATUS_PREFIX) !== 0) { + return $status; + } + + return substr($status, $prefixLength); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/PreconditionValidator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/PreconditionValidator.php new file mode 100644 index 000000000..2f61468dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/PreconditionValidator.php @@ -0,0 +1,29 @@ +addConstraintValidator(new IsSuccessful()); + $this->addConstraintValidator( + new DestinationMatches($destination) + ); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Result.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Result.php new file mode 100644 index 000000000..a0d352ec0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Result.php @@ -0,0 +1,47 @@ +errors[] = $message; + } + + + /** + * @return bool + */ + public function isValid() : bool + { + return empty($this->errors); + } + + + /** + * @return array + */ + public function getErrors() : array + { + return $this->errors; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Validator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Validator.php new file mode 100644 index 000000000..1f5f4021f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Response/Validation/Validator.php @@ -0,0 +1,40 @@ +constraints[] = $constraint; + } + + + /** + * @param Response $response + * @return Result + */ + public function validate(Response $response) : Result + { + $result = new Result(); + foreach ($this->constraints as $validator) { + $validator->validate($response, $result); + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAP.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAP.php new file mode 100644 index 000000000..1a442a87b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAP.php @@ -0,0 +1,126 @@ + + + + + +SOAP; + $envelope = sprintf($envelope, Constants::NS_SOAP); + + $doc = new DOMDocument; + $doc->loadXML($envelope); + + // In the Artifact Resolution profile, this will be an ArtifactResolve + // containing another message (e.g. a Response), however in the ECP + // profile, this is the Response itself. + if ($message instanceof Response) { + /** @var \DOMElement $header */ + $header = $doc->getElementsByTagNameNS(Constants::NS_SOAP, 'Header')->item(0); + + $response = new ECPResponse(); + $destination = $this->destination ?: $message->getDestination(); + if ($destination === null) { + throw new \Exception('No destination available for SOAP message.'); + } + $response->setAssertionConsumerServiceURL($destination); + + $response->toXML($header); + + // TODO We SHOULD add ecp:RequestAuthenticated SOAP header if we + // authenticated the AuthnRequest. It may make sense to have a + // standardized way for Message objects to contain (optional) SOAP + // headers for use with the SOAP binding. + // + // https://docs.oasis-open.org/security/saml/Post2.0/saml-ecp/v2.0/cs01/saml-ecp-v2.0-cs01.html#_Toc366664733 + // See Section 2.3.6.1 + } + + /** @var \DOMElement $body */ + $body = $doc->getElementsByTagNameNs(Constants::NS_SOAP, 'Body')->item(0); + + $body->appendChild($doc->importNode($message->toSignedXML(), true)); + + return $doc->saveXML(); + } + + + /** + * Send a SAML 2 message using the SOAP binding. + * + * Note: This function never returns. + * + * @param \SAML2\Message $message The message we should send. + * @return void + */ + public function send(Message $message) : void + { + header('Content-Type: text/xml', true); + + $xml = $this->getOutputToSend($message); + if ($xml !== false) { + Utils::getContainer()->debugMessage($xml, 'out'); + echo $xml; + } + + // DOMDocument::saveXML() returned false. Something is seriously wrong here. Not much we can do. + exit(0); + } + + + /** + * Receive a SAML 2 message sent using the HTTP-POST binding. + * + * @throws \Exception If unable to receive the message + * @return \SAML2\Message The received message. + */ + public function receive() : Message + { + $postText = $this->getInputStream(); + + if (empty($postText)) { + throw new UnsupportedBindingException('Invalid message received at AssertionConsumerService endpoint.'); + } + + $document = DOMDocumentFactory::fromString($postText); + /** @var \DOMNode $xml */ + $xml = $document->firstChild; + Utils::getContainer()->debugMessage($document->documentElement, 'in'); + /** @var \DOMElement[] $results */ + $results = Utils::xpQuery($xml, '/soap-env:Envelope/soap-env:Body/*[1]'); + + return Message::fromXML($results[0]); + } + + /** + * @return string|false + */ + protected function getInputStream() + { + return file_get_contents('php://input'); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAPClient.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAPClient.php new file mode 100644 index 000000000..1a33d7129 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SOAPClient.php @@ -0,0 +1,280 @@ +\ + '; + const END_SOAP_ENVELOPE = ''; + + + /** + * This function sends the SOAP message to the service location and returns SOAP response + * + * @param \SAML2\Message $msg The request that should be sent. + * @param \SimpleSAML\Configuration $srcMetadata The metadata of the issuer of the message. + * @param \SimpleSAML\Configuration $dstMetadata The metadata of the destination of the message. + * @throws \Exception + * @return \SAML2\Message The response we received. + * + * @psalm-suppress UndefinedClass + */ + public function send(Message $msg, Configuration $srcMetadata, Configuration $dstMetadata = null) : Message + { + $issuer = $msg->getIssuer(); + + $ctxOpts = [ + 'ssl' => [ + 'capture_peer_cert' => true, + 'allow_self_signed' => true + ], + ]; + + $container = ContainerSingleton::getInstance(); + + // Determine if we are going to do a MutualSSL connection between the IdP and SP - Shoaib + if ($srcMetadata->hasValue('saml.SOAPClient.certificate')) { + $cert = $srcMetadata->getValue('saml.SOAPClient.certificate'); + if ($cert !== false) { + $configUtils = new Config(); + $ctxOpts['ssl']['local_cert'] = $configUtils->getCertPath( + $srcMetadata->getString('saml.SOAPClient.certificate') + ); + if ($srcMetadata->hasValue('saml.SOAPClient.privatekey_pass')) { + $ctxOpts['ssl']['passphrase'] = $srcMetadata->getString('saml.SOAPClient.privatekey_pass'); + } + } + } else { + $cryptoUtils = new Crypto(); + + /* Use the SP certificate and privatekey if it is configured. */ + $privateKey = $cryptoUtils->loadPrivateKey($srcMetadata); + $publicKey = $cryptoUtils->loadPublicKey($srcMetadata); + if ($privateKey !== null && $publicKey !== null && isset($publicKey['PEM'])) { + $keyCertData = $privateKey['PEM'].$publicKey['PEM']; + $file = $container->getTempDir().'/'.sha1($keyCertData).'.pem'; + if (!file_exists($file)) { + $container->writeFile($file, $keyCertData); + } + $ctxOpts['ssl']['local_cert'] = $file; + if (isset($privateKey['password'])) { + $ctxOpts['ssl']['passphrase'] = $privateKey['password']; + } + } + } + + // do peer certificate verification + if ($dstMetadata !== null) { + $peerPublicKeys = $dstMetadata->getPublicKeys('signing', true); + $certData = ''; + foreach ($peerPublicKeys as $key) { + if ($key['type'] !== 'X509Certificate') { + continue; + } + $certData .= "-----BEGIN CERTIFICATE-----\n". + chunk_split($key['X509Certificate'], 64). + "-----END CERTIFICATE-----\n"; + } + $peerCertFile = $container->getTempDir().'/'.sha1($certData).'.pem'; + if (!file_exists($peerCertFile)) { + $container->writeFile($peerCertFile, $certData); + } + // create ssl context + $ctxOpts['ssl']['verify_peer'] = true; + $ctxOpts['ssl']['verify_depth'] = 1; + $ctxOpts['ssl']['cafile'] = $peerCertFile; + } + + if ($srcMetadata->hasValue('saml.SOAPClient.stream_context.ssl.peer_name')) { + $ctxOpts['ssl']['peer_name'] = $srcMetadata->getString('saml.SOAPClient.stream_context.ssl.peer_name'); + } + + $context = stream_context_create($ctxOpts); + + $options = [ + 'uri' => $issuer->getValue(), + 'location' => $msg->getDestination(), + 'stream_context' => $context, + ]; + + if ($srcMetadata->hasValue('saml.SOAPClient.proxyhost')) { + $options['proxy_host'] = $srcMetadata->getValue('saml.SOAPClient.proxyhost'); + } + + if ($srcMetadata->hasValue('saml.SOAPClient.proxyport')) { + $options['proxy_port'] = $srcMetadata->getValue('saml.SOAPClient.proxyport'); + } + + $x = new \SoapClient(null, $options); + + // Add soap-envelopes + $request = $msg->toSignedXML(); + $request = self::START_SOAP_ENVELOPE.$request->ownerDocument->saveXML($request).self::END_SOAP_ENVELOPE; + + $container->debugMessage($request, 'out'); + + $action = 'http://www.oasis-open.org/committees/security'; + $destination = $msg->getDestination(); + if ($destination === null) { + throw new Exception('Cannot send SOAP message, no destination set.'); + } + + /* Perform SOAP Request over HTTP */ + $soapresponsexml = $x->__doRequest($request, $destination, $action, SOAP_1_1); + if (empty($soapresponsexml)) { + throw new Exception('Empty SOAP response, check peer certificate.'); + } + + Utils::getContainer()->debugMessage($soapresponsexml, 'in'); + + // Convert to SAML2\Message (\DOMElement) + try { + $dom = DOMDocumentFactory::fromString($soapresponsexml); + } catch (InvalidArgumentException | UnparseableXmlException | RuntimeException $e) { + throw new Exception($e->getMessage(), 0, $e); + } + $soapresponse = Utils::xpQuery($dom->firstChild, '/soap-env:Envelope/soap-env:Body/*[1]'); + if (empty($soapresponse)) { + throw new Exception('Not a SOAP response', 0); + } + $container->debugMessage($dom->documentElement, 'in'); + + $soapfault = $this->getSOAPFault($dom); + if (isset($soapfault)) { + throw new Exception($soapfault); + } + //Extract the message from the response + /** @var \DOMElement[] $samlresponse */ + $samlresponse = Utils::xpQuery($dom->firstChild, '/soap-env:Envelope/soap-env:Body/*[1]'); + $samlresponse = Message::fromXML($samlresponse[0]); + + /* Add validator to message which uses the SSL context. */ + self::addSSLValidator($samlresponse, $context); + + $container->getLogger()->debug("Valid ArtifactResponse received from IdP"); + + return $samlresponse; + } + + + /** + * Add a signature validator based on a SSL context. + * + * @param \SAML2\Message $msg The message we should add a validator to. + * @param resource $context The stream context. + * @return void + */ + private static function addSSLValidator(Message $msg, $context) : void + { + $options = stream_context_get_options($context); + if (!isset($options['ssl']['peer_certificate'])) { + return; + } + + $container = ContainerSingleton::getInstance(); + $key = openssl_pkey_get_public($options['ssl']['peer_certificate']); + if ($key === false) { + $container->getLogger()->warning('Unable to get public key from peer certificate.'); + + return; + } + + $keyInfo = openssl_pkey_get_details($key); + if ($keyInfo === false) { + $container->getLogger()->warning('Unable to get key details from public key.'); + + return; + } + + if (!isset($keyInfo['key'])) { + $container->getLogger()->warning('Missing key in public key details.'); + + return; + } + + $msg->addValidator([SOAPClient::class, 'validateSSL'], $keyInfo['key']); + } + + + /** + * Validate a SOAP message against the certificate on the SSL connection. + * + * @param string $data The public key that was used on the connection. + * @param XMLSecurityKey $key The key we should validate the certificate against. + * @throws \Exception + * @return void + */ + public static function validateSSL(string $data, XMLSecurityKey $key) : void + { + $container = ContainerSingleton::getInstance(); + /** @psalm-suppress PossiblyNullArgument */ + $keyInfo = openssl_pkey_get_details($key->key); + if ($keyInfo === false) { + throw new Exception('Unable to get key details from XMLSecurityKey.'); + } + + if (!isset($keyInfo['key'])) { + throw new Exception('Missing key in public key details.'); + } + + if ($keyInfo['key'] !== $data) { + $container->getLogger()->debug('Key on SSL connection did not match key we validated against.'); + + return; + } + + $container->getLogger()->debug('Message validated based on SSL certificate.'); + } + + + /** + * Extracts the SOAP Fault from SOAP message + * + * @param \DOMDocument $soapMessage Soap response needs to be type DOMDocument + * @return string|null $soapfaultstring + */ + private function getSOAPFault(DOMDocument $soapMessage) : ?string + { + /** @psalm-suppress PossiblyNullArgument */ + $soapFault = Utils::xpQuery($soapMessage->firstChild, '/soap-env:Envelope/soap-env:Body/soap-env:Fault'); + + if (empty($soapFault)) { + /* No fault. */ + + return null; + } + /** @var \DOMNode $soapFaultElement */ + $soapFaultElement = $soapFault[0]; + // There is a fault element but we haven't found out what the fault string is + $soapFaultString = "Unknown fault string found"; + // find out the fault string + $faultStringElement = Utils::xpQuery($soapFaultElement, './soap-env:faultstring'); + if (!empty($faultStringElement)) { + return $faultStringElement[0]->textContent; + } + + return $soapFaultString; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/AbstractChainedValidator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/AbstractChainedValidator.php new file mode 100644 index 000000000..0481d7701 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/AbstractChainedValidator.php @@ -0,0 +1,77 @@ +logger = $logger; + } + + + /** + * BC compatible version of the signature check + * + * @param \SAML2\SignedElement $element + * @param \SAML2\Utilities\ArrayCollection $pemCandidates + * + * @throws \Exception + * + * @return bool + */ + protected function validateElementWithKeys( + SignedElement $element, + \SAML2\Utilities\ArrayCollection $pemCandidates + ) : bool { + $lastException = null; + foreach ($pemCandidates as $index => $candidateKey) { + $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type' => 'public']); + $key->loadKey($candidateKey->getCertificate()); + + try { + /* + * Make sure that we have a valid signature on either the response or the assertion. + */ + $result = $element->validate($key); + if ($result) { + $this->logger->debug(sprintf('Validation with key "#%d" succeeded', $index)); + return true; + } + $this->logger->debug(sprintf('Validation with key "#%d" failed without exception.', $index)); + } catch (\Exception $e) { + $this->logger->debug(sprintf( + 'Validation with key "#%d" failed with exception: %s', + $index, + $e->getMessage() + )); + + $lastException = $e; + } + } + + if ($lastException !== null) { + throw $lastException; + } else { + return false; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ChainedValidator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ChainedValidator.php new file mode 100644 index 000000000..e00848303 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ChainedValidator.php @@ -0,0 +1,29 @@ +keyLoader = $keyLoader; + + parent::__construct($logger); + } + + + /** + * @param \SAML2\SignedElement $signedElement + * @param \SAML2\Configuration\CertificateProvider $configuration + * + * @return bool + */ + public function canValidate( + SignedElement $signedElement, + CertificateProvider $configuration + ) : bool { + $this->configuredKeys = $this->keyLoader->extractPublicKeys($configuration); + + return !!count($this->configuredKeys); + } + + + /** + * @param \SAML2\SignedElement $signedElement + * @param \SAML2\Configuration\CertificateProvider $configuration + * + * @return bool + */ + public function hasValidSignature( + SignedElement $signedElement, + CertificateProvider $configuration + ) : bool { + $logger = $this->logger; + $pemCandidates = $this->configuredKeys->filter(function (Key $key) use ($logger) { + if (!$key instanceof X509) { + $logger->debug(sprintf('Skipping unknown key type: "%s"', $key['type'])); + return false; + } + return true; + }); + + if (!count($pemCandidates)) { + $this->logger->debug('No configured X509 certificate found to verify the signature with'); + + return false; + } + + return $this->validateElementWithKeys($signedElement, $pemCandidates); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/Validator.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/Validator.php new file mode 100644 index 000000000..1d416ceed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/Validator.php @@ -0,0 +1,55 @@ +logger = $logger; + } + + + /** + * @param SignedElement $signedElement + * @param CertificateProvider $configuration + * + * @return bool + */ + public function hasValidSignature( + SignedElement $signedElement, + CertificateProvider $configuration + ) : bool { + // should be DI + $validator = new ValidatorChain( + $this->logger, + [ + new PublicKeyValidator($this->logger, new KeyLoader()) + ] + ); + + return $validator->hasValidSignature($signedElement, $configuration); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorChain.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorChain.php new file mode 100644 index 000000000..4987c5201 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorChain.php @@ -0,0 +1,87 @@ +logger = $logger; + + // should be done through "adder" injection in the container. + foreach ($validators as $validator) { + $this->appendValidator($validator); + } + } + + + /** + * @param \SAML2\Signature\ChainedValidator $validator + * @return void + */ + public function appendValidator(ChainedValidator $validator) : void + { + $this->validators[] = $validator; + } + + + /** + * @param \SAML2\SignedElement $signedElement + * @param \SAML2\Configuration\CertificateProvider $configuration + * + * @return bool + */ + public function hasValidSignature( + SignedElement $signedElement, + CertificateProvider $configuration + ) : bool { + foreach ($this->validators as $validator) { + if ($validator->canValidate($signedElement, $configuration)) { + $this->logger->debug(sprintf( + 'Validating the signed element with validator of type "%s"', + get_class($validator) + )); + + return $validator->hasValidSignature($signedElement, $configuration); + } + + $this->logger->debug(sprintf( + 'Could not validate the signed element with validator of type "%s"', + get_class($validator) + )); + } + + throw new MissingConfigurationException(sprintf( + 'No certificates have been configured%s', + $configuration->has('entityid') ? ' for "'.$configuration->get('entityid').'"' : '' + )); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorInterface.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorInterface.php new file mode 100644 index 000000000..6e8552c54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Signature/ValidatorInterface.php @@ -0,0 +1,24 @@ +certificates = $certificates; + } + + + /** + * Retrieve the certificates that are included in the message. + * + * @return array An array of certificates + */ + public function getCertificates() : array + { + return $this->certificates; + } + + + /** + * Retrieve the private key we should use to sign the message. + * + * @return XMLSecurityKey|null The key, or NULL if no key is specified + */ + public function getSignatureKey() : ?XMLSecurityKey + { + return $this->signatureKey; + } + + + /** + * Set the private key we should use to sign the message. + * + * If the key is null, the message will be sent unsigned. + * + * @param XMLSecurityKey|null $signatureKey + * @return void + */ + public function setSignatureKey(XMLSecurityKey $signatureKey = null) : void + { + $this->signatureKey = $signatureKey; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SignedElementHelper.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SignedElementHelper.php new file mode 100644 index 000000000..47e87d97f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SignedElementHelper.php @@ -0,0 +1,275 @@ +certificates = []; + $this->validators = []; + + if ($xml === null) { + return; + } + + /* Validate the signature element of the message. */ + try { + $sig = Utils::validateElement($xml); + + if ($sig) { + $this->certificates = $sig['Certificates']; + $this->validators[] = [ + 'Function' => [Utils::class, 'validateSignature'], + 'Data' => $sig, + ]; + } + } catch (\Exception $e) { + /* Ignore signature validation errors. */ + } + } + + + /** + * Add a method for validating this element. + * + * This function is used for custom validation extensions + * + * @param callable $function The function which should be called. + * @param mixed $data The data that should be included as the first parameter to the function. + * @return void + */ + public function addValidator(callable $function, $data) : void + { + $this->validators[] = [ + 'Function' => $function, + 'Data' => $data, + ]; + } + + + /** + * Validate this element against a public key. + * + * true is returned on success, false is returned if we don't have any + * signature we can validate. An exception is thrown if the signature + * validation fails. + * + * @param XMLSecurityKey $key The key we should check against. + * @return bool True on success, false when we don't have a signature. + * @throws \Exception + * @return bool true on success, false when we don't have a signature. + */ + public function validate(XMLSecurityKey $key) : bool + { + if (count($this->validators) === 0) { + return false; + } + + $exceptions = []; + + foreach ($this->validators as $validator) { + $function = $validator['Function']; + $data = $validator['Data']; + + try { + call_user_func($function, $data, $key); + /* We were able to validate the message with this validator. */ + + return true; + } catch (\Exception $e) { + $exceptions[] = $e; + } + } + + /* No validators were able to validate the message. */ + throw $exceptions[0]; + } + + + /** + * Retrieve the private key we should use to sign the message. + * + * @return XMLSecurityKey|null The key, or NULL if no key is specified. + */ + public function getSignatureKey() : ?XMLSecurityKey + { + return $this->signatureKey; + } + + + /** + * Set the private key we should use to sign the message. + * + * If the key is null, the message will be sent unsigned. + * + * @param XMLSecurityKey|null $signatureKey + * @return void + */ + public function setSignatureKey(XMLSecurityKey $signatureKey = null) : void + { + $this->signatureKey = $signatureKey; + } + + + /** + * Set the certificates that should be included in the message. + * + * The certificates should be strings with the PEM encoded data. + * + * @param array $certificates An array of certificates. + * @return void + */ + public function setCertificates(array $certificates) : void + { + $this->certificates = $certificates; + } + + + /** + * Retrieve the certificates that are included in the message. + * + * @return array An array of certificates. + */ + public function getCertificates() : array + { + return $this->certificates; + } + + + /** + * Retrieve certificates that sign this element. + * + * @return array Array with certificates. + */ + public function getValidatingCertificates() : array + { + $ret = []; + foreach ($this->certificates as $cert) { + /* Construct a PEM formatted certificate */ + $pemCert = "-----BEGIN CERTIFICATE-----\n". + chunk_split($cert, 64). + "-----END CERTIFICATE-----\n"; + + /* Extract the public key from the certificate for validation. */ + $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, ['type'=>'public']); + $key->loadKey($pemCert); + + try { + /* Check the signature. */ + if ($this->validate($key)) { + $ret[] = $cert; + } + } catch (\Exception $e) { + /* This certificate does not sign this element. */ + } + } + + return $ret; + } + + + /** + * Collect the value of the validUntil property. + * + * @return int|null + */ + public function getValidUntil() : ?int + { + return $this->validUntil; + } + + /** + * Set the value of the validUntil property. + * + * @param int|null $validUntil + * @return void + */ + public function setValidUntil(int $validUntil = null) : void + { + $this->validUntil = $validUntil; + } + + + /** + * Collect the value of the cacheDuration property. + * + * @return string|null + */ + public function getCacheDuration() : ?string + { + return $this->cacheDuration; + } + + + /** + * Set the value of the cacheDuration property. + * + * @param string|null $cacheDuration + * @return void + */ + public function setCacheDuration(string $cacheDuration = null) : void + { + $this->cacheDuration = $cacheDuration; + } + + + /** + * Sign the given XML element. + * + * @param \DOMElement $root The element we should sign. + * @param \DOMNode|null $insertBefore The element we should insert the signature node before. + * @return \DOMElement|null + */ + protected function signElement(DOMElement $root, DOMNode $insertBefore = null) : ?DOMElement + { + if ($this->signatureKey === null) { + /* We cannot sign this element. */ + return null; + } + + Utils::insertSignature($this->signatureKey, $this->certificates, $root, $insertBefore); + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/StatusResponse.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/StatusResponse.php new file mode 100644 index 000000000..885bbc4b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/StatusResponse.php @@ -0,0 +1,199 @@ + '', + * 'SubCode' => '', + * 'Message' => '', + * ] + * + * Only the 'Code' field is required. The others will be set to null if they + * aren't present. + * + * @package SimpleSAMLphp + */ +abstract class StatusResponse extends Message +{ + /** + * The ID of the request this is a response to, or null if this is an unsolicited response. + * + * @var string|null + */ + private $inResponseTo; + + + /** + * The status code of the response. + * + * @var array + */ + private $status; + + + /** + * Constructor for SAML 2 response messages. + * + * @param string $tagName The tag name of the root element. + * @param \DOMElement|null $xml The input message. + * @throws \Exception + */ + protected function __construct(string $tagName, DOMElement $xml = null) + { + parent::__construct($tagName, $xml); + + $this->status = [ + 'Code' => Constants::STATUS_SUCCESS, + 'SubCode' => null, + 'Message' => null, + ]; + + if ($xml === null) { + return; + } + + if ($xml->hasAttribute('InResponseTo')) { + $this->inResponseTo = $xml->getAttribute('InResponseTo'); + } + + /** @var \DOMElement[] $status */ + $status = Utils::xpQuery($xml, './saml_protocol:Status'); + if (empty($status)) { + throw new \Exception('Missing status code on response.'); + } + + /** @var \DOMElement[] $statusCode */ + $statusCode = Utils::xpQuery($status[0], './saml_protocol:StatusCode'); + if (empty($statusCode)) { + throw new \Exception('Missing status code in status element.'); + } + $this->status['Code'] = $statusCode[0]->getAttribute('Value'); + + /** @var \DOMElement[] $subCode */ + $subCode = Utils::xpQuery($statusCode[0], './saml_protocol:StatusCode'); + if (!empty($subCode)) { + $this->status['SubCode'] = $subCode[0]->getAttribute('Value'); + } + + /** @var \DOMElement[] $message */ + $message = Utils::xpQuery($status[0], './saml_protocol:StatusMessage'); + if (!empty($message)) { + $this->status['Message'] = trim($message[0]->textContent); + } + } + + + /** + * Determine whether this is a successful response. + * + * @return bool true if the status code is success, false if not. + */ + public function isSuccess() : bool + { + Assert::keyExists($this->status, "Code"); + + return $this->status['Code'] === Constants::STATUS_SUCCESS; + } + + + /** + * Retrieve the ID of the request this is a response to. + * + * @return string|null The ID of the request. + */ + public function getInResponseTo() : ?string + { + return $this->inResponseTo; + } + + + /** + * Set the ID of the request this is a response to. + * + * @param string|null $inResponseTo The ID of the request. + * @return void + */ + public function setInResponseTo(string $inResponseTo = null) : void + { + $this->inResponseTo = $inResponseTo; + } + + + /** + * Retrieve the status code. + * + * @return array The status code. + */ + public function getStatus() : array + { + return $this->status; + } + + + /** + * Set the status code. + * + * @param array $status The status code. + * @return void + */ + public function setStatus(array $status) : void + { + Assert::keyExists($status, "Code", 'Cannot set status without a Code key in the array.'); + + $this->status = $status; + if (!array_key_exists('SubCode', $status)) { + $this->status['SubCode'] = null; + } + if (!array_key_exists('Message', $status)) { + $this->status['Message'] = null; + } + } + + + /** + * Convert status response message to an XML element. + * + * @return \DOMElement This status response. + */ + public function toUnsignedXML() : DOMElement + { + $root = parent::toUnsignedXML(); + + if ($this->inResponseTo !== null) { + $root->setAttribute('InResponseTo', $this->inResponseTo); + } + + $status = $this->document->createElementNS(Constants::NS_SAMLP, 'Status'); + $root->appendChild($status); + + $statusCode = $this->document->createElementNS(Constants::NS_SAMLP, 'StatusCode'); + $statusCode->setAttribute('Value', $this->status['Code']); + $status->appendChild($statusCode); + + if (!is_null($this->status['SubCode'])) { + $subStatusCode = $this->document->createElementNS(Constants::NS_SAMLP, 'StatusCode'); + $subStatusCode->setAttribute('Value', $this->status['SubCode']); + $statusCode->appendChild($subStatusCode); + } + + if (!is_null($this->status['Message'])) { + Utils::addString($status, Constants::NS_SAMLP, 'StatusMessage', $this->status['Message']); + } + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SubjectQuery.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SubjectQuery.php new file mode 100644 index 000000000..7d025d94e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/SubjectQuery.php @@ -0,0 +1,120 @@ +parseSubject($xml); + } + + + /** + * Parse subject in query. + * + * @param \DOMElement $xml The SubjectQuery XML element. + * @throws \Exception + * @return void + */ + private function parseSubject(\DOMElement $xml) : void + { + /** @var \DOMElement[] $subject */ + $subject = Utils::xpQuery($xml, './saml_assertion:Subject'); + if (empty($subject)) { + throw new \Exception('Missing subject in subject query.'); + } elseif (count($subject) > 1) { + throw new \Exception('More than one in subject query.'); + } + + /** @var \DOMElement[] $nameId */ + $nameId = Utils::xpQuery($subject[0], './saml_assertion:NameID'); + if (empty($nameId)) { + throw new \Exception('Missing in .'); + } elseif (count($nameId) > 1) { + throw new \Exception('More than one in .'); + } + $this->nameId = new NameID($nameId[0]); + } + + + /** + * Retrieve the NameId of the subject in the query. + * + * @return \SAML2\XML\saml\NameID|null The name identifier of the assertion. + */ + public function getNameId() : ?NameID + { + return $this->nameId; + } + + + /** + * Set the NameId of the subject in the query. + * + * @param \SAML2\XML\saml\NameID|null $nameId The name identifier of the assertion. + * @return void + */ + public function setNameId(NameID $nameId = null) : void + { + $this->nameId = $nameId; + } + + + /** + * Convert subject query message to an XML element. + * + * @return \DOMElement This subject query. + */ + public function toUnsignedXML() : DOMElement + { + if ($this->nameId === null) { + throw new \Exception('Cannot convert SubjectQuery to XML without a NameID set.'); + } + $root = parent::toUnsignedXML(); + + $subject = $root->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:Subject'); + $root->appendChild($subject); + + $this->nameId->toXML($subject); + + return $root; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/ArrayCollection.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/ArrayCollection.php new file mode 100644 index 000000000..355c0d6f5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/ArrayCollection.php @@ -0,0 +1,200 @@ +elements = $elements; + } + + + /** + * @param mixed $key + * + * @return void + */ + public function add($key) : void + { + $this->elements[] = $key; + } + + + /** + * @param mixed $key + * + * @return mixed|null + */ + public function get($key) + { + return isset($this->elements[$key]) ? $this->elements[$key] : null; + } + + + /** + * @param \Closure $f + * + * @return ArrayCollection + */ + public function filter(Closure $filterFunction) : Collection + { + return new self(array_filter($this->elements, $filterFunction)); + } + + + /** + * @param mixed $key + * @param mixed $value + * @return void + */ + public function set($key, $value) : void + { + $this->elements[$key] = $value; + } + + + /** + * @param mixed $key + * + * @return void + */ + public function remove($key) : void + { + $elt = array_search($key, $this->elements); + if ($elt === false) { + return; + } + unset($this->elements[$elt]); + } + + + /** + * @throws RuntimeException + * @return bool|mixed + */ + public function getOnlyElement() + { + if ($this->count() !== 1) { + throw new RuntimeException(sprintf( + __CLASS__.'::'.__METHOD__.' requires that the collection has exactly one element, ' + . '"%d" elements found', + $this->count() + )); + } + + return reset($this->elements); + } + + + /** + * @return bool|mixed + */ + public function first() + { + return reset($this->elements); + } + + + /** + * @return bool|mixed + */ + public function last() + { + return end($this->elements); + } + + + /** + * @param \Closure $function + * + * @return ArrayCollection + */ + public function map(Closure $function) : ArrayCollection + { + return new self(array_map($function, $this->elements)); + } + + + /** + * @return int + */ + public function count() : int + { + return count($this->elements); + } + + + /** + * @return \ArrayIterator + */ + public function getIterator() : ArrayIterator + { + return new ArrayIterator($this->elements); + } + + + /** + * @param mixed $offset + * + * @return bool + */ + public function offsetExists($offset) : bool + { + return isset($this->elements[$offset]); + } + + + /** + * @param mixed $offset + * + * @return mixed + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->elements[$offset]; + } + + + /** + * @param mixed $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset, $value) : void + { + $this->elements[$offset] = $value; + } + + + /** + * @param $offset + * @return void + */ + public function offsetUnset($offset) : void + { + unset($this->elements[$offset]); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/Certificate.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/Certificate.php new file mode 100644 index 000000000..9a338fd81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/Utilities/Certificate.php @@ -0,0 +1,39 @@ +idKeys[] = 'ID'; + + /* Locate the XMLDSig Signature element to be used. */ + /** @var \DOMElement[] $signatureElement */ + $signatureElement = self::xpQuery($root, './ds:Signature'); + if (empty($signatureElement)) { + /* We don't have a signature element ot validate. */ + + return false; + } elseif (count($signatureElement) > 1) { + throw new \Exception('XMLSec: more than one signature element in root.'); + } + $signatureElement = $signatureElement[0]; + $objXMLSecDSig->sigNode = $signatureElement; + + /* Canonicalize the XMLDSig SignedInfo element in the message. */ + $objXMLSecDSig->canonicalizeSignedInfo(); + + /* Validate referenced xml nodes. */ + if (!$objXMLSecDSig->validateReference()) { + throw new \Exception('XMLsec: digest validation failed'); + } + + /* Check that $root is one of the signed nodes. */ + $rootSigned = false; + /** @var \DOMNode $signedNode */ + foreach ($objXMLSecDSig->getValidatedNodes() as $signedNode) { + if ($signedNode->isSameNode($root)) { + $rootSigned = true; + break; + } elseif ($root->parentNode instanceof \DOMDocument && $signedNode->isSameNode($root->ownerDocument)) { + /* $root is the root element of a signed document. */ + $rootSigned = true; + break; + } + } + if (!$rootSigned) { + throw new \Exception('XMLSec: The root element is not signed.'); + } + + /* Now we extract all available X509 certificates in the signature element. */ + $certificates = []; + foreach (self::xpQuery($signatureElement, './ds:KeyInfo/ds:X509Data/ds:X509Certificate') as $certNode) { + $certData = trim($certNode->textContent); + $certData = str_replace(["\r", "\n", "\t", ' '], '', $certData); + $certificates[] = $certData; + } + + $ret = [ + 'Signature' => $objXMLSecDSig, + 'Certificates' => $certificates, + ]; + + return $ret; + } + + + /** + * Helper function to convert a XMLSecurityKey to the correct algorithm. + * + * @param XMLSecurityKey $key The key. + * @param string $algorithm The desired algorithm. + * @param string $type Public or private key, defaults to public. + * @return XMLSecurityKey The new key. + */ + public static function castKey(XMLSecurityKey $key, string $algorithm, string $type = null) : XMLSecurityKey + { + $type = $type ?: 'public'; + Assert::oneOf($type, ["private", "public"]); + + // do nothing if algorithm is already the type of the key + if ($key->type === $algorithm) { + return $key; + } + + if (!in_array($algorithm, [ + XMLSecurityKey::RSA_1_5, + XMLSecurityKey::RSA_SHA1, + XMLSecurityKey::RSA_SHA256, + XMLSecurityKey::RSA_SHA384, + XMLSecurityKey::RSA_SHA512 + ], true)) { + throw new \Exception('Unsupported signing algorithm.'); + } + + /** @psalm-suppress PossiblyNullArgument */ + $keyInfo = openssl_pkey_get_details($key->key); + if ($keyInfo === false) { + throw new \Exception('Unable to get key details from XMLSecurityKey.'); + } + if (!isset($keyInfo['key'])) { + throw new \Exception('Missing key in public key details.'); + } + + $newKey = new XMLSecurityKey($algorithm, ['type' => $type]); + $newKey->loadKey($keyInfo['key']); + + return $newKey; + } + + + /** + * Check a signature against a key. + * + * An exception is thrown if we are unable to validate the signature. + * + * @param array $info The information returned by the validateElement() function. + * @param XMLSecurityKey $key The publickey that should validate the Signature object. + * @throws \Exception + * @return void + */ + public static function validateSignature(array $info, XMLSecurityKey $key) : void + { + Assert::keyExists($info, "Signature"); + + /** @var XMLSecurityDSig $objXMLSecDSig */ + $objXMLSecDSig = $info['Signature']; + + /** + * @var \DOMElement[] $sigMethod + * @var \DOMElement $objXMLSecDSig->sigNode + */ + $sigMethod = self::xpQuery($objXMLSecDSig->sigNode, './ds:SignedInfo/ds:SignatureMethod'); + if (empty($sigMethod)) { + throw new \Exception('Missing SignatureMethod element.'); + } + $sigMethod = $sigMethod[0]; + if (!$sigMethod->hasAttribute('Algorithm')) { + throw new \Exception('Missing Algorithm-attribute on SignatureMethod element.'); + } + $algo = $sigMethod->getAttribute('Algorithm'); + + if ($key->type === XMLSecurityKey::RSA_SHA256 && $algo !== $key->type) { + $key = self::castKey($key, $algo); + } + + /* Check the signature. */ + if ($objXMLSecDSig->verify($key) !== 1) { + throw new \Exception("Unable to validate Signature"); + } + } + + + /** + * Do an XPath query on an XML node. + * + * @param \DOMNode $node The XML node. + * @param string $query The query. + * @return \DOMNode[] Array with matching DOM nodes. + */ + public static function xpQuery(DOMNode $node, string $query) : array + { + static $xpCache = null; + + if ($node instanceof DOMDocument) { + $doc = $node; + } else { + $doc = $node->ownerDocument; + } + + if ($xpCache === null || !$xpCache->document->isSameNode($doc)) { + $xpCache = new DOMXPath($doc); + $xpCache->registerNamespace('soap-env', Constants::NS_SOAP); + $xpCache->registerNamespace('saml_protocol', Constants::NS_SAMLP); + $xpCache->registerNamespace('saml_assertion', Constants::NS_SAML); + $xpCache->registerNamespace('saml_metadata', Constants::NS_MD); + $xpCache->registerNamespace('ds', XMLSecurityDSig::XMLDSIGNS); + $xpCache->registerNamespace('xenc', XMLSecEnc::XMLENCNS); + } + + $results = $xpCache->query($query, $node); + $ret = []; + for ($i = 0; $i < $results->length; $i++) { + $ret[$i] = $results->item($i); + } + + return $ret; + } + + + /** + * Make an exact copy the specific \DOMElement. + * + * @param \DOMElement $element The element we should copy. + * @param \DOMElement|null $parent The target parent element. + * @return \DOMElement The copied element. + */ + public static function copyElement(DOMElement $element, DOMElement $parent = null) : DOMElement + { + if ($parent === null) { + $document = DOMDocumentFactory::create(); + } else { + $document = $parent->ownerDocument; + } + + $namespaces = []; + for ($e = $element; $e instanceof DOMNode; $e = $e->parentNode) { + foreach (Utils::xpQuery($e, './namespace::*') as $ns) { + $prefix = $ns->localName; + if ($prefix === 'xml' || $prefix === 'xmlns') { + continue; + } + $uri = $ns->nodeValue; + if (!isset($namespaces[$prefix])) { + $namespaces[$prefix] = $uri; + } + } + } + + /** @var \DOMElement $newElement */ + $newElement = $document->importNode($element, true); + if ($parent !== null) { + /* We need to append the child to the parent before we add the namespaces. */ + $parent->appendChild($newElement); + } + + foreach ($namespaces as $prefix => $uri) { + $newElement->setAttributeNS($uri, $prefix.':__ns_workaround__', 'tmp'); + $newElement->removeAttributeNS($uri, '__ns_workaround__'); + } + + return $newElement; + } + + + /** + * Parse a boolean attribute. + * + * @param \DOMElement $node The element we should fetch the attribute from. + * @param string $attributeName The name of the attribute. + * @param mixed|null $default The value that should be returned if the attribute doesn't exist. + * @return bool|mixed The value of the attribute, or $default if the attribute doesn't exist. + */ + public static function parseBoolean(DOMElement $node, string $attributeName, $default = null) + { + if (!$node->hasAttribute($attributeName)) { + return $default; + } + $value = $node->getAttribute($attributeName); + switch (strtolower($value)) { + case '0': + case 'false': + return false; + case '1': + case 'true': + return true; + default: + throw new \Exception('Invalid value of boolean attribute '.var_export($attributeName, true).': '. + var_export($value, true)); + } + } + + + /** + * Insert a Signature node. + * + * @param XMLSecurityKey $key The key we should use to sign the message. + * @param array $certificates The certificates we should add to the signature node. + * @param \DOMElement $root The XML node we should sign. + * @param \DOMNode $insertBefore The XML element we should insert the signature element before. + * @return void + */ + public static function insertSignature( + XMLSecurityKey $key, + array $certificates, + DOMElement $root, + DOMNode $insertBefore = null + ) : void { + $objXMLSecDSig = new XMLSecurityDSig(); + $objXMLSecDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); + + switch ($key->type) { + case XMLSecurityKey::RSA_SHA256: + $type = XMLSecurityDSig::SHA256; + break; + case XMLSecurityKey::RSA_SHA384: + $type = XMLSecurityDSig::SHA384; + break; + case XMLSecurityKey::RSA_SHA512: + $type = XMLSecurityDSig::SHA512; + break; + default: + $type = XMLSecurityDSig::SHA1; + } + + $objXMLSecDSig->addReferenceList( + [$root], + $type, + ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', XMLSecurityDSig::EXC_C14N], + ['id_name' => 'ID', 'overwrite' => false] + ); + + $objXMLSecDSig->sign($key); + + foreach ($certificates as $certificate) { + $objXMLSecDSig->add509Cert($certificate, true); + } + + $objXMLSecDSig->insertSignature($root, $insertBefore); + } + + + /** + * Decrypt an encrypted element. + * + * This is an internal helper function. + * + * @param \DOMElement $encryptedData The encrypted data. + * @param XMLSecurityKey $inputKey The decryption key. + * @param array &$blacklist Blacklisted decryption algorithms. + * @throws \Exception + * @return \DOMElement The decrypted element. + */ + private static function doDecryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey, array &$blacklist) : DOMElement + { + $enc = new XMLSecEnc(); + + $enc->setNode($encryptedData); + $enc->type = $encryptedData->getAttribute("Type"); + + $symmetricKey = $enc->locateKey($encryptedData); + if (!$symmetricKey) { + throw new \Exception('Could not locate key algorithm in encrypted data.'); + } + + $symmetricKeyInfo = $enc->locateKeyInfo($symmetricKey); + if (!$symmetricKeyInfo) { + throw new \Exception('Could not locate for the encrypted key.'); + } + + $inputKeyAlgo = $inputKey->getAlgorithm(); + if ($symmetricKeyInfo->isEncrypted) { + $symKeyInfoAlgo = $symmetricKeyInfo->getAlgorithm(); + + if (in_array($symKeyInfoAlgo, $blacklist, true)) { + throw new \Exception('Algorithm disabled: '.var_export($symKeyInfoAlgo, true)); + } + + if ($symKeyInfoAlgo === XMLSecurityKey::RSA_OAEP_MGF1P && $inputKeyAlgo === XMLSecurityKey::RSA_1_5) { + /* + * The RSA key formats are equal, so loading an RSA_1_5 key + * into an RSA_OAEP_MGF1P key can be done without problems. + * We therefore pretend that the input key is an + * RSA_OAEP_MGF1P key. + */ + $inputKeyAlgo = XMLSecurityKey::RSA_OAEP_MGF1P; + } + + /* Make sure that the input key format is the same as the one used to encrypt the key. */ + if ($inputKeyAlgo !== $symKeyInfoAlgo) { + throw new \Exception( + 'Algorithm mismatch between input key and key used to encrypt '. + ' the symmetric key for the message. Key was: '. + var_export($inputKeyAlgo, true).'; message was: '. + var_export($symKeyInfoAlgo, true) + ); + } + + /** @var XMLSecEnc $encKey */ + $encKey = $symmetricKeyInfo->encryptedCtx; + $symmetricKeyInfo->key = $inputKey->key; + + $keySize = $symmetricKey->getSymmetricKeySize(); + if ($keySize === null) { + /* To protect against "key oracle" attacks, we need to be able to create a + * symmetric key, and for that we need to know the key size. + */ + throw new \Exception( + 'Unknown key size for encryption algorithm: '.var_export($symmetricKey->type, true) + ); + } + + try { + /** + * @var string $key + * @psalm-suppress UndefinedClass + */ + $key = $encKey->decryptKey($symmetricKeyInfo); + if (strlen($key) !== $keySize) { + throw new \Exception( + 'Unexpected key size ('.strval(strlen($key)*8).'bits) for encryption algorithm: '. + var_export($symmetricKey->type, true) + ); + } + } catch (\Exception $e) { + /* We failed to decrypt this key. Log it, and substitute a "random" key. */ + Utils::getContainer()->getLogger()->error('Failed to decrypt symmetric key: '.$e->getMessage()); + /* Create a replacement key, so that it looks like we fail in the same way as if the key was correctly + * padded. */ + + /* We base the symmetric key on the encrypted key and private key, so that we always behave the + * same way for a given input key. + */ + $encryptedKey = $encKey->getCipherValue(); + if ($encryptedKey === null) { + throw new \Exception('No CipherValue available in the encrypted element.'); + } + + /** @psalm-suppress PossiblyNullArgument */ + $pkey = openssl_pkey_get_details($symmetricKeyInfo->key); + $pkey = sha1(serialize($pkey), true); + $key = sha1($encryptedKey.$pkey, true); + + /* Make sure that the key has the correct length. */ + if (strlen($key) > $keySize) { + $key = substr($key, 0, $keySize); + } elseif (strlen($key) < $keySize) { + $key = str_pad($key, $keySize); + } + } + $symmetricKey->loadkey($key); + } else { + $symKeyAlgo = $symmetricKey->getAlgorithm(); + /* Make sure that the input key has the correct format. */ + if ($inputKeyAlgo !== $symKeyAlgo) { + throw new \Exception( + 'Algorithm mismatch between input key and key in message. '. + 'Key was: '.var_export($inputKeyAlgo, true).'; message was: '. + var_export($symKeyAlgo, true) + ); + } + $symmetricKey = $inputKey; + } + + $algorithm = $symmetricKey->getAlgorithm(); + if (in_array($algorithm, $blacklist, true)) { + throw new \Exception('Algorithm disabled: '.var_export($algorithm, true)); + } + + /** + * @var string $decrypted + * @psalm-suppress UndefinedClass + */ + $decrypted = $enc->decryptNode($symmetricKey, false); + + /* + * This is a workaround for the case where only a subset of the XML + * tree was serialized for encryption. In that case, we may miss the + * namespaces needed to parse the XML. + */ + $xml = ''. + $decrypted. + ''; + + try { + $newDoc = DOMDocumentFactory::fromString($xml); + } catch (RuntimeException $e) { + throw new \Exception('Failed to parse decrypted XML. Maybe the wrong sharedkey was used?', 0, $e); + } + + /** @psalm-suppress PossiblyNullPropertyFetch */ + $decryptedElement = $newDoc->firstChild->firstChild; + if (!($decryptedElement instanceof DOMElement)) { + throw new \Exception('Missing decrypted element or it was not actually a DOMElement.'); + } + + return $decryptedElement; + } + + + /** + * Decrypt an encrypted element. + * + * @param \DOMElement $encryptedData The encrypted data. + * @param XMLSecurityKey $inputKey The decryption key. + * @param array $blacklist Blacklisted decryption algorithms. + * @throws \Exception + * @return \DOMElement The decrypted element. + */ + public static function decryptElement(DOMElement $encryptedData, XMLSecurityKey $inputKey, array $blacklist = []) : DOMElement + { + try { + return self::doDecryptElement($encryptedData, $inputKey, $blacklist); + } catch (\Exception $e) { + /* + * Something went wrong during decryption, but for security + * reasons we cannot tell the user what failed. + */ + Utils::getContainer()->getLogger()->error('Decryption failed: '.$e->getMessage()); + throw new \Exception('Failed to decrypt XML element.', 0, $e); + } + } + + + /** + * Extract localized strings from a set of nodes. + * + * @param \DOMElement $parent The element that contains the localized strings. + * @param string $namespaceURI The namespace URI the localized strings should have. + * @param string $localName The localName of the localized strings. + * @return array Localized strings. + */ + public static function extractLocalizedStrings(\DOMElement $parent, string $namespaceURI, string $localName) : array + { + $ret = []; + foreach ($parent->childNodes as $node) { + if ($node->namespaceURI !== $namespaceURI || $node->localName !== $localName) { + continue; + } else if (!($node instanceof DOMElement)) { + continue; + } + + if ($node->hasAttribute('xml:lang')) { + $language = $node->getAttribute('xml:lang'); + } else { + $language = 'en'; + } + $ret[$language] = trim($node->textContent); + } + + return $ret; + } + + + /** + * Extract strings from a set of nodes. + * + * @param \DOMElement $parent The element that contains the localized strings. + * @param string $namespaceURI The namespace URI the string elements should have. + * @param string $localName The localName of the string elements. + * @return array The string values of the various nodes. + */ + public static function extractStrings(DOMElement $parent, string $namespaceURI, string $localName) : array + { + $ret = []; + foreach ($parent->childNodes as $node) { + if ($node->namespaceURI !== $namespaceURI || $node->localName !== $localName) { + continue; + } + $ret[] = trim($node->textContent); + } + + return $ret; + } + + + /** + * Append string element. + * + * @param \DOMElement $parent The parent element we should append the new nodes to. + * @param string $namespace The namespace of the created element. + * @param string $name The name of the created element. + * @param string $value The value of the element. + * @return \DOMElement The generated element. + */ + public static function addString( + DOMElement $parent, + string $namespace, + string $name, + string $value + ) : DOMElement { + $doc = $parent->ownerDocument; + + $n = $doc->createElementNS($namespace, $name); + $n->appendChild($doc->createTextNode($value)); + $parent->appendChild($n); + + return $n; + } + + + /** + * Append string elements. + * + * @param \DOMElement $parent The parent element we should append the new nodes to. + * @param string $namespace The namespace of the created elements + * @param string $name The name of the created elements + * @param bool $localized Whether the strings are localized, and should include the xml:lang attribute. + * @param array $values The values we should create the elements from. + * @return void + */ + public static function addStrings( + DOMElement $parent, + string $namespace, + string $name, + bool $localized, + array $values + ) : void { + $doc = $parent->ownerDocument; + + foreach ($values as $index => $value) { + $n = $doc->createElementNS($namespace, $name); + $n->appendChild($doc->createTextNode($value)); + if ($localized) { + $n->setAttribute('xml:lang', $index); + } + $parent->appendChild($n); + } + } + + + /** + * Create a KeyDescriptor with the given certificate. + * + * @param string|null $x509Data The certificate, as a base64-encoded DER data. + * @param string|null $keyName The name of the key as specified in the KeyInfo + * @return \SAML2\XML\md\KeyDescriptor The keydescriptor. + */ + public static function createKeyDescriptor(?string $x509Data = null, ?string $keyName = null) : KeyDescriptor + { + if ($keyName === null && $x509Data === null) { + throw new \Exception('KeyDescriptor should contain either x509Data and/or keyName!'); + } + + $keyInfo = new KeyInfo(); + + if ($keyName !== null) { + $keynameEl = new KeyName(); + $keynameEl->setName($keyName); + $keyInfo->addInfo($keynameEl); + } + + if ($x509Data !== null) { + $x509Certificate = new X509Certificate(); + $x509Certificate->setCertificate($x509Data); + $x509Data = new X509Data(); + $x509Data->addData($x509Certificate); + $keyInfo->addInfo($x509Data); + } + + $keyDescriptor = new KeyDescriptor(); + $keyDescriptor->setKeyInfo($keyInfo); + return $keyDescriptor; + } + + + /** + * This function converts a SAML2 timestamp on the form + * yyyy-mm-ddThh:mm:ss(\.s+)?Z to a UNIX timestamp. The sub-second + * part is ignored. + * + * Andreas comments: + * I got this timestamp from Shibboleth 1.3 IdP: 2008-01-17T11:28:03.577Z + * Therefore I added to possibility to have microseconds to the format. + * Added: (\.\\d{1,3})? to the regex. + * + * Note that we always require a 'Z' timezone for the dateTime to be valid. + * This is not in the SAML spec but that's considered to be a bug in the + * spec. See https://github.com/simplesamlphp/saml2/pull/36 for some + * background. + * + * @param string $time The time we should convert. + * @throws \Exception + * @return int Converted to a unix timestamp. + */ + public static function xsDateTimeToTimestamp(string $time) : int + { + $matches = []; + + // We use a very strict regex to parse the timestamp. + $regex = '/^(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)(?:\\.\\d{1,9})?Z$/D'; + if (preg_match($regex, $time, $matches) == 0) { + throw new \Exception( + 'Invalid SAML2 timestamp passed to xsDateTimeToTimestamp: '.$time + ); + } + + // Extract the different components of the time from the matches in the regex. + // intval will ignore leading zeroes in the string. + $year = intval($matches[1]); + $month = intval($matches[2]); + $day = intval($matches[3]); + $hour = intval($matches[4]); + $minute = intval($matches[5]); + $second = intval($matches[6]); + + // We use gmmktime because the timestamp will always be given + //in UTC. + $ts = gmmktime($hour, $minute, $second, $month, $day, $year); + + return $ts; + } + + + /** + * @return \SAML2\Compat\AbstractContainer + */ + public static function getContainer() : AbstractContainer + { + return ContainerSingleton::getInstance(); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/Chunk.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/Chunk.php new file mode 100644 index 000000000..72db68a55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/Chunk.php @@ -0,0 +1,188 @@ +localName = $xml->localName; + $this->namespaceURI = $xml->namespaceURI; + + $this->xml = Utils::copyElement($xml); + } + + + /** + * Get this \DOMElement. + * + * @return \DOMElement This element. + */ + public function getXML() : DOMElement + { + return $this->xml; + } + + + /** + * Append this XML element to a different XML element. + * + * @param \DOMElement $parent The element we should append this element to. + * @return \DOMElement The new element. + */ + public function toXML(DOMElement $parent) : DOMElement + { + return Utils::copyElement($this->xml, $parent); + } + + + /** + * Collect the value of the localName-property + * + * @return string + */ + public function getLocalName() : string + { + return $this->localName; + } + + + /** + * Set the value of the localName-property + * + * @param string $localName + * @return void + */ + public function setLocalName(string $localName) : void + { + $this->localName = $localName; + } + + + /** + * Collect the value of the namespaceURI-property + * + * @return string|null + */ + public function getNamespaceURI() : ?string + { + return $this->namespaceURI; + } + + + /** + * Set the value of the namespaceURI-property + * + * @param string|null $namespaceURI + * @return void + */ + public function setNamespaceURI(string $namespaceURI = null) : void + { + $this->namespaceURI = $namespaceURI; + } + + + /** + * Serialize this XML chunk. + * + * @return string The serialized chunk. + */ + public function serialize() : string + { + return serialize($this->xml->ownerDocument->saveXML($this->xml)); + } + + + /** + * Un-serialize this XML chunk. + * + * @param string $serialized The serialized chunk. + * @return void + * + * Type hint not possible due to upstream method signature + */ + public function unserialize($serialized) : void + { + $doc = DOMDocumentFactory::fromString(unserialize($serialized)); + $this->xml = $doc->documentElement; + $this->setLocalName($this->xml->localName); + $this->setNamespaceURI($this->xml->namespaceURI); + } + + + + /** + * Serialize this XML chunk. + * + * This method will be invoked by any calls to serialize(). + * + * @return array The serialized representation of this XML object. + */ + public function __serialize(): array + { + $xml = $this->getXML(); + /** @psalm-var \DOMDocument $xml->ownerDocument */ + return [$xml->ownerDocument->saveXML($xml)]; + } + + + /** + * Unserialize an XML object and load it.. + * + * This method will be invoked by any calls to unserialize(), allowing us to restore any data that might not + * be serializable in its original form (e.g.: DOM objects). + * + * @param array $vars The XML object that we want to restore. + */ + public function __unserialize(array $serialized): void + { + $xml = new self( + DOMDocumentFactory::fromString(array_pop($serialized))->documentElement + ); + + $vars = get_object_vars($xml); + foreach ($vars as $k => $v) { + $this->$k = $v; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/Common.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/Common.php new file mode 100644 index 000000000..bd7760a0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/Common.php @@ -0,0 +1,17 @@ + + * @package simplesamlphp/saml2 + */ +class Common +{ + const NS = 'urn:oasis:names:tc:SAML:metadata:algsupport'; +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/DigestMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/DigestMethod.php new file mode 100644 index 000000000..196ab9c01 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/DigestMethod.php @@ -0,0 +1,88 @@ + + * @package simplesamlphp/saml2 + */ +class DigestMethod +{ + /** + * An URI identifying an algorithm supported for digest operations. + * + * @var string + */ + private $Algorithm = ''; + + + /** + * Create/parse an alg:DigestMethod element. + * + * @param \DOMElement|null $xml The XML element we should load or null to create a new one from scratch. + * + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('Algorithm')) { + throw new \Exception('Missing required attribute "Algorithm" in alg:DigestMethod element.'); + } + $this->setAlgorithm($xml->getAttribute('Algorithm')); + } + + + /** + * Collect the value of the algorithm-property + * + * @return string + */ + public function getAlgorithm() : string + { + return $this->Algorithm; + } + + + /** + * Set the value of the Algorithm-property + * + * @param string $algorithm + * @return void + */ + public function setAlgorithm(string $algorithm) : void + { + $this->Algorithm = $algorithm; + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement + * @throws \Exception + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->Algorithm, 'Cannot convert DigestMethod to XML without an Algorithm set.'); + + $doc = $parent->ownerDocument; + $e = $doc->createElementNS(Common::NS, 'alg:DigestMethod'); + $parent->appendChild($e); + $e->setAttribute('Algorithm', $this->Algorithm); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/SigningMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/SigningMethod.php new file mode 100644 index 000000000..3719c566a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/alg/SigningMethod.php @@ -0,0 +1,168 @@ + + * @package simplesamlphp/saml2 + */ +class SigningMethod +{ + /** + * An URI identifying the algorithm supported for XML signature operations. + * + * @var string + */ + private $Algorithm = ''; + + /** + * The smallest key size, in bits, that the entity supports in conjunction with the algorithm. If omitted, no + * minimum is implied. + * + * @var int|null + */ + private $MinKeySize = null; + + /** + * The largest key size, in bits, that the entity supports in conjunction with the algorithm. If omitted, no + * maximum is implied. + * + * @var int|null + */ + private $MaxKeySize = null; + + + /** + * Create/parse an alg:SigningMethod element. + * + * @param \DOMElement|null $xml The XML element we should load or null to create a new one from scratch. + * + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('Algorithm')) { + throw new \Exception('Missing required attribute "Algorithm" in alg:SigningMethod element.'); + } + $this->Algorithm = $xml->getAttribute('Algorithm'); + + if ($xml->hasAttribute('MinKeySize')) { + $this->MinKeySize = intval($xml->getAttribute('MinKeySize')); + } + + if ($xml->hasAttribute('MaxKeySize')) { + $this->MaxKeySize = intval($xml->getAttribute('MaxKeySize')); + } + } + + + /** + * Collect the value of the Algorithm-property + * + * @return string + */ + public function getAlgorithm() + { + return $this->Algorithm; + } + + + /** + * Set the value of the Algorithm-property + * + * @param string $algorithm + * @return void + */ + public function setAlgorithm(string $algorithm) : void + { + $this->Algorithm = $algorithm; + } + + + /** + * Collect the value of the MinKeySize-property + * + * @return int|null + */ + public function getMinKeySize() : ?int + { + return $this->MinKeySize; + } + + + /** + * Set the value of the MinKeySize-property + * + * @param int|null $minKeySize + * @return void + */ + public function setMinKeySize(int $minKeySize = null) : void + { + $this->MinKeySize = $minKeySize; + } + + + /** + * Collect the value of the MaxKeySize-property + * + * @return int|null + */ + public function getMaxKeySize() : ?int + { + return $this->MaxKeySize; + } + + + /** + * Set the value of the MaxKeySize-property + * + * @param int|null $maxKeySize + * @return void + */ + public function setMaxKeySize(int $maxKeySize = null) : void + { + $this->MaxKeySize = $maxKeySize; + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement + * @throws \Exception + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->Algorithm, 'Cannot convert SigningMethod to XML without an Algorithm set.'); + Assert::nullOrInteger($this->MinKeySize); + Assert::nullOrInteger($this->MaxKeySize); + + $doc = $parent->ownerDocument; + $e = $doc->createElementNS(Common::NS, 'alg:SigningMethod'); + $parent->appendChild($e); + $e->setAttribute('Algorithm', $this->Algorithm); + + if ($this->MinKeySize !== null) { + $e->setAttribute('MinKeySize', strval($this->MinKeySize)); + } + + if ($this->MaxKeySize !== null) { + $e->setAttribute('MaxKeySize', strval($this->MaxKeySize)); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyInfo.php new file mode 100644 index 000000000..f53c5f4d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyInfo.php @@ -0,0 +1,164 @@ +hasAttribute('Id')) { + $this->Id = $xml->getAttribute('Id'); + } + + foreach ($xml->childNodes as $n) { + if (!($n instanceof \DOMElement)) { + continue; + } + + if ($n->namespaceURI !== XMLSecurityDSig::XMLDSIGNS) { + $this->info[] = new Chunk($n); + continue; + } + switch ($n->localName) { + case 'KeyName': + $this->info[] = new KeyName($n); + break; + case 'X509Data': + $this->info[] = new X509Data($n); + break; + default: + $this->info[] = new Chunk($n); + break; + } + } + } + + + /** + * Collect the value of the Id-property + * + * @return string|null + */ + public function getId() : ?string + { + return $this->Id; + } + + + /** + * Set the value of the Id-property + * + * @param string|null $id + * @return void + */ + public function setId(string $id = null) : void + { + $this->Id = $id; + } + + + /** + * Collect the value of the info-property + * + * @return array + */ + public function getInfo() : array + { + return $this->info; + } + + + /** + * Set the value of the info-property + * + * @param array $info + * @return void + */ + public function setInfo(array $info) : void + { + $this->info = $info; + } + + + /** + * Add the value to the info-property + * + * @param \SAML2\XML\Chunk|\SAML2\XML\ds\KeyName|\SAML2\XML\ds\X509Data $info + * @throws \Exception + * @return void + */ + public function addInfo($info) : void + { + Assert::isInstanceOfAny( + $info, + [Chunk::class, KeyName::class, X509Data::class], + 'KeyInfo can only contain instances of KeyName, X509Data or Chunk.' + ); + $this->info[] = $info; + } + + + /** + * Convert this KeyInfo to XML. + * + * @param \DOMElement $parent The element we should append this KeyInfo to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo'); + $parent->appendChild($e); + + if ($this->Id !== null) { + $e->setAttribute('Id', $this->Id); + } + + foreach ($this->info as $n) { + $n->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyName.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyName.php new file mode 100644 index 000000000..b025f1a27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/KeyName.php @@ -0,0 +1,75 @@ +setName($xml->textContent); + } + + + /** + * Collect the value of the name-property + * + * @return string + */ + public function getName() : string + { + return $this->name; + } + + + /** + * Set the value of the name-property + * + * @param string $name + * @return void + */ + public function setName(string $name) : void + { + $this->name = $name; + } + + + /** + * Convert this KeyName element to XML. + * + * @param \DOMElement $parent The element we should append this KeyName element to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + return Utils::addString($parent, XMLSecurityDSig::XMLDSIGNS, 'ds:KeyName', $this->name); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Certificate.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Certificate.php new file mode 100644 index 000000000..979c16343 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Certificate.php @@ -0,0 +1,75 @@ +setCertificate($xml->textContent); + } + + + /** + * Collect the value of the certificate-property + * + * @return string + */ + public function getCertificate() : string + { + return str_replace(["\r\n", "\r", "\n", "\t", ' '], '', $this->certificate); + } + + + /** + * Set the value of the certificate-property + * + * @param string $certificate + * @return void + */ + public function setCertificate(string $certificate) : void + { + $this->certificate = $certificate; + } + + + /** + * Convert this X509Certificate element to XML. + * + * @param \DOMElement $parent The element we should append this X509Certificate element to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + return Utils::addString($parent, XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $this->getCertificate()); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Data.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Data.php new file mode 100644 index 000000000..f5d1cdec0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ds/X509Data.php @@ -0,0 +1,120 @@ +firstChild; $n !== null; $n = $n->nextSibling) { + if (!($n instanceof DOMElement)) { + continue; + } + + if ($n->namespaceURI !== XMLSecurityDSig::XMLDSIGNS) { + $this->addData(new Chunk($n)); + continue; + } + switch ($n->localName) { + case 'X509Certificate': + $this->addData(new X509Certificate($n)); + break; + default: + $this->addData(new Chunk($n)); + break; + } + } + } + + + /** + * Collect the value of the data-property + * + * @return array + */ + public function getData() : array + { + return $this->data; + } + + + /** + * Set the value of the data-property + * + * @param array $data + * @return void + */ + public function setData(array $data) : void + { + $this->data = $data; + } + + + /** + * Add the value to the data-property + * + * @param \SAML2\XML\Chunk|\SAML2\XML\ds\X509Certificate $data + * @return void + */ + public function addData($data) : void + { + Assert::isInstanceOfAny($data, [Chunk::class, X509Certificate::class]); + $this->data[] = $data; + } + + + /** + * Convert this X509Data element to XML. + * + * @param \DOMElement $parent The element we should append this X509Data element to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data'); + $parent->appendChild($e); + + /** @var \SAML2\XML\Chunk|\SAML2\XML\ds\X509Certificate $n */ + foreach ($this->getData() as $n) { + $n->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ecp/Response.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ecp/Response.php new file mode 100644 index 000000000..ab4558e93 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/ecp/Response.php @@ -0,0 +1,110 @@ +hasAttributeNS(Constants::NS_SOAP, 'mustUnderstand')) { + throw new \Exception('Missing SOAP-ENV:mustUnderstand attribute in .'); + } + if ($xml->getAttributeNS(Constants::NS_SOAP, 'mustUnderstand') !== '1') { + throw new \Exception('Invalid value of SOAP-ENV:mustUnderstand attribute in .'); + } + + if (!$xml->hasAttributeNS(Constants::NS_SOAP, 'actor')) { + throw new \Exception('Missing SOAP-ENV:actor attribute in .'); + } + if ($xml->getAttributeNS(Constants::NS_SOAP, 'actor') !== 'http://schemas.xmlsoap.org/soap/actor/next') { + throw new \Exception('Invalid value of SOAP-ENV:actor attribute in .'); + } + + if (!$xml->hasAttribute('AssertionConsumerServiceURL')) { + throw new \Exception('Missing AssertionConsumerServiceURL attribute in .'); + } + + $this->setAssertionConsumerServiceURL($xml->getAttribute('AssertionConsumerServiceURL')); + } + + + /** + * Collect the value of the AssertionConsumerServiceURL-property + * + * @return string + */ + public function getAssertionConsumerServiceURL() : string + { + return $this->AssertionConsumerServiceURL; + } + + + /** + * Set the value of the AssertionConsumerServiceURL-property + * + * @param string $assertionConsumerServiceURL + * @throws InvalidArgumentException + * @return void +- */ + public function setAssertionConsumerServiceURL(string $assertionConsumerServiceURL) : void + { + if (!filter_var($assertionConsumerServiceURL, FILTER_VALIDATE_URL)) { + throw new InvalidArgumentException('AssertionConsumerServiceURL is not a valid URL.'); + } + $this->AssertionConsumerServiceURL = $assertionConsumerServiceURL; + } + + + /** + * Convert this ECP Response to XML. + * + * @param \DOMElement $parent The element we should append this element to. + * @throws InvalidArgumentException + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $acs = $this->getAssertionConsumerServiceURL(); + if (!isset($acs)) { + throw new InvalidArgumentException("AssertionConsumerServiceURL must be a string"); + } + + $doc = $parent->ownerDocument; + $response = $doc->createElementNS(Constants::NS_ECP, 'ecp:Response'); + + $parent->appendChild($response); + + $response->setAttributeNS(Constants::NS_SOAP, 'SOAP-ENV:mustUnderstand', '1'); + $response->setAttributeNS(Constants::NS_SOAP, 'SOAP-ENV:actor', 'http://schemas.xmlsoap.org/soap/actor/next'); + $response->setAttribute('AssertionConsumerServiceURL', $acs); + + return $response; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AdditionalMetadataLocation.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AdditionalMetadataLocation.php new file mode 100644 index 000000000..55fab5966 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AdditionalMetadataLocation.php @@ -0,0 +1,114 @@ +hasAttribute('namespace')) { + throw new \Exception('Missing namespace attribute on AdditionalMetadataLocation element.'); + } + $this->setNamespace($xml->getAttribute('namespace')); + + $this->setLocation($xml->textContent); + } + + + /** + * Collect the value of the namespace-property + * + * @return string + */ + public function getNamespace() : string + { + return $this->namespace; + } + + + /** + * Set the value of the namespace-property + * + * @param string $namespace + * @return void + */ + public function setNamespace(string $namespace) : void + { + $this->namespace = $namespace; + } + + + /** + * Collect the value of the location-property + * + * @return string + */ + public function getLocation() : string + { + return $this->location; + } + + + /** + * Set the value of the location-property + * + * @param string $location + * @return void + */ + public function setLocation(string $location) : void + { + $this->location = $location; + } + + + /** + * Convert this AdditionalMetadataLocation to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement This AdditionalMetadataLocation-element. + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = Utils::addString($parent, Constants::NS_MD, 'md:AdditionalMetadataLocation', $this->getLocation()); + $e->setAttribute('namespace', $this->getNamespace()); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AffiliationDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AffiliationDescriptor.php new file mode 100644 index 000000000..5cd06822b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AffiliationDescriptor.php @@ -0,0 +1,286 @@ +hasAttribute('affiliationOwnerID')) { + throw new \Exception('Missing affiliationOwnerID on AffiliationDescriptor.'); + } + $this->setAffiliationOwnerID($xml->getAttribute('affiliationOwnerID')); + + if ($xml->hasAttribute('ID')) { + $this->setID($xml->getAttribute('ID')); + } + + if ($xml->hasAttribute('validUntil')) { + $this->setValidUntil(Utils::xsDateTimeToTimestamp($xml->getAttribute('validUntil'))); + } + + if ($xml->hasAttribute('cacheDuration')) { + $this->setCacheDuration($xml->getAttribute('cacheDuration')); + } + + $this->setExtensions(Extensions::getList($xml)); + + $this->setAffiliateMember(Utils::extractStrings($xml, Constants::NS_MD, 'AffiliateMember')); + if (empty($this->AffiliateMember)) { + throw new \Exception('Missing AffiliateMember in AffiliationDescriptor.'); + } + + /** @var \DOMElement $kd */ + foreach (Utils::xpQuery($xml, './saml_metadata:KeyDescriptor') as $kd) { + $this->addKeyDescriptor(new KeyDescriptor($kd)); + } + } + + + /** + * Collect the value of the affiliationOwnerId-property + * + * @return string + */ + public function getAffiliationOwnerID() : string + { + return $this->affiliationOwnerID; + } + + + /** + * Set the value of the affiliationOwnerId-property + * + * @param string $affiliationOwnerId + * @return void + */ + public function setAffiliationOwnerID(string $affiliationOwnerId) : void + { + $this->affiliationOwnerID = $affiliationOwnerId; + } + + + /** + * Collect the value of the ID-property + * + * @return string|null + */ + public function getID() : ?string + { + return $this->ID; + } + + + /** + * Set the value of the ID-property + * + * @param string|null $Id + * @return void + */ + public function setID(string $Id = null) : void + { + $this->ID = $Id; + } + + + /** + * Collect the value of the Extensions-property + * + * @return \SAML2\XML\Chunk[] + */ + public function getExtensions() : array + { + return $this->Extensions; + } + + + /** + * Set the value of the Extensions-property + * + * @param array $extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->Extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param Extensions $extensions The Extensions + * @return void + */ + public function addExtension(Extensions $extension) : void + { + $this->Extensions[] = $extension; + } + + + /** + * Collect the value of the AffiliateMember-property + * + * @return array + */ + public function getAffiliateMember() : array + { + return $this->AffiliateMember; + } + + + /** + * Set the value of the AffiliateMember-property + * + * @param array $affiliateMember + * @return void + */ + public function setAffiliateMember(array $affiliateMember) : void + { + $this->AffiliateMember = $affiliateMember; + } + + + /** + * Collect the value of the KeyDescriptor-property + * + * @return \SAML2\XML\md\KeyDescriptor[] + */ + public function getKeyDescriptor() : array + { + return $this->KeyDescriptor; + } + + + /** + * Set the value of the KeyDescriptor-property + * + * @param array $keyDescriptor + * @return void + */ + public function setKeyDescriptor(array $keyDescriptor) : void + { + $this->KeyDescriptor = $keyDescriptor; + } + + + /** + * Add the value to the KeyDescriptor-property + * + * @param \SAML2\XML\md\KeyDescriptor $keyDescriptor + * @return void + */ + public function addKeyDescriptor(KeyDescriptor $keyDescriptor) : void + { + $this->KeyDescriptor[] = $keyDescriptor; + } + + + /** + * Add this AffiliationDescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this endpoint to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->affiliationOwnerID); + + $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, 'md:AffiliationDescriptor'); + $parent->appendChild($e); + + $e->setAttribute('affiliationOwnerID', $this->affiliationOwnerID); + + if ($this->ID !== null) { + $e->setAttribute('ID', $this->ID); + } + + if ($this->validUntil !== null) { + $e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil)); + } + + if ($this->cacheDuration !== null) { + $e->setAttribute('cacheDuration', $this->cacheDuration); + } + + Extensions::addList($e, $this->Extensions); + + Utils::addStrings($e, Constants::NS_MD, 'md:AffiliateMember', false, $this->AffiliateMember); + + foreach ($this->KeyDescriptor as $kd) { + $kd->toXML($e); + } + + $this->signElement($e, $e->firstChild); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeAuthorityDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeAuthorityDescriptor.php new file mode 100644 index 000000000..1d3132356 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeAuthorityDescriptor.php @@ -0,0 +1,286 @@ +addAttributeService(new EndpointType($ep)); + } + if ($this->getAttributeService() === []) { + throw new \Exception('Must have at least one AttributeService in AttributeAuthorityDescriptor.'); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:AssertionIDRequestService') as $ep) { + $this->addAssertionIDRequestService(new EndpointType($ep)); + } + + $this->setNameIDFormat(Utils::extractStrings($xml, Constants::NS_MD, 'NameIDFormat')); + + $this->setAttributeProfile(Utils::extractStrings($xml, Constants::NS_MD, 'AttributeProfile')); + + /** @var \DOMElement $a */ + foreach (Utils::xpQuery($xml, './saml_assertion:Attribute') as $a) { + $this->addAttribute(new Attribute($a)); + } + } + + + /** + * Collect the value of the AttributeService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAttributeService() : array + { + return $this->AttributeService; + } + + + /** + * Set the value of the AttributeService-property + * + * @param \SAML2\XML\md\EndpointType[] $attributeService + * @return void + */ + public function setAttributeService(array $attributeService) : void + { + $this->AttributeService = $attributeService; + } + + + /** + * Add the value to the AttributeService-property + * + * @param \SAML2\XML\md\EndpointType $attributeService + * @return void + */ + public function addAttributeService(EndpointType $attributeService) : void + { + $this->AttributeService[] = $attributeService; + } + + + /** + * Collect the value of the NameIDFormat-property + * + * @return string[] + */ + public function getNameIDFormat() : array + { + return $this->NameIDFormat; + } + + + /** + * Set the value of the NameIDFormat-property + * + * @param string[] $nameIDFormat + * @return void + */ + public function setNameIDFormat(array $nameIDFormat) : void + { + $this->NameIDFormat = $nameIDFormat; + } + + + /** + * Collect the value of the AssertionIDRequestService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAssertionIDRequestService() : array + { + return $this->AssertionIDRequestService; + } + + + /** + * Set the value of the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType[] $assertionIDRequestService + * @return void + */ + public function setAssertionIDRequestService(array $assertionIDRequestService) : void + { + $this->AssertionIDRequestService = $assertionIDRequestService; + } + + + /** + * Add the value to the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType $assertionIDRequestService + * @return void + */ + public function addAssertionIDRequestService(EndpointType $assertionIDRequestService) : void + { + $this->AssertionIDRequestService[] = $assertionIDRequestService; + } + + + /** + * Collect the value of the AttributeProfile-property + * + * @return string[] + */ + public function getAttributeProfile() : array + { + return $this->AttributeProfile; + } + + + /** + * Set the value of the AttributeProfile-property + * + * @param string[] $attributeProfile + * @return void + */ + public function setAttributeProfile(array $attributeProfile) : void + { + $this->AttributeProfile = $attributeProfile; + } + + + /** + * Collect the value of the Attribute-property + * + * @return \SAML2\XML\saml\Attribute[] + */ + public function getAttribute() : array + { + return $this->Attribute; + } + + + /** + * Set the value of the Attribute-property + * + * @param \SAML2\XML\saml\Attribute[] $attribute + * @return void + */ + public function setAttribute(array $attribute) : void + { + $this->Attribute = $attribute; + } + + + /** + * Add the value to the Attribute-property + * + * @param \SAML2\XML\saml\Attribute $attribute + * @return void + */ + public function addAttribute(Attribute $attribute) : void + { + $this->Attribute[] = $attribute; + } + + + /** + * Add this AttributeAuthorityDescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this IDPSSODescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->AttributeService); + + $e = parent::toXML($parent); + + foreach ($this->AttributeService as $ep) { + $ep->toXML($e, 'md:AttributeService'); + } + + foreach ($this->AssertionIDRequestService as $ep) { + $ep->toXML($e, 'md:AssertionIDRequestService'); + } + + Utils::addStrings($e, Constants::NS_MD, 'md:NameIDFormat', false, $this->NameIDFormat); + + Utils::addStrings($e, Constants::NS_MD, 'md:AttributeProfile', false, $this->AttributeProfile); + + foreach ($this->Attribute as $a) { + $a->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeConsumingService.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeConsumingService.php new file mode 100644 index 000000000..82162e57f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AttributeConsumingService.php @@ -0,0 +1,251 @@ + translation. + * + * @var array + */ + private $ServiceName = []; + + /** + * The ServiceDescription of this AttributeConsumingService. + * + * This is an associative array with language => translation. + * + * @var array + */ + private $ServiceDescription = []; + + /** + * The RequestedAttribute elements. + * + * This is an array of SAML_RequestedAttributeType elements. + * + * @var \SAML2\XML\md\RequestedAttribute[] + */ + private $RequestedAttribute = []; + + + /** + * Initialize / parse an AttributeConsumingService. + * + * @param \DOMElement|null $xml The XML element we should load. + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('index')) { + throw new \Exception('Missing index on AttributeConsumingService.'); + } + $this->setIndex(intval($xml->getAttribute('index'))); + + $this->setIsDefault(Utils::parseBoolean($xml, 'isDefault', null)); + + $this->setServiceName(Utils::extractLocalizedStrings($xml, Constants::NS_MD, 'ServiceName')); + if ($this->getServiceName() === []) { + throw new \Exception('Missing ServiceName in AttributeConsumingService.'); + } + + $this->setServiceDescription(Utils::extractLocalizedStrings($xml, Constants::NS_MD, 'ServiceDescription')); + + /** @var \DOMElement $ra */ + foreach (Utils::xpQuery($xml, './saml_metadata:RequestedAttribute') as $ra) { + $this->addRequestedAttribute(new RequestedAttribute($ra)); + } + } + + + /** + * Collect the value of the index-property + * + * @return int + */ + public function getIndex() : int + { + return $this->index; + } + + + /** + * Set the value of the index-property + * + * @param int $index + * @return void + */ + public function setIndex(int $index) : void + { + $this->index = $index; + } + + + /** + * Collect the value of the isDefault-property + * + * @return bool|null + */ + public function getIsDefault() : ?bool + { + return $this->isDefault; + } + + + /** + * Set the value of the isDefault-property + * + * @param bool|null $flag + * @return void + */ + public function setIsDefault(bool $flag = null) : void + { + $this->isDefault = $flag; + } + + + /** + * Collect the value of the ServiceName-property + * + * @return string[] + */ + public function getServiceName() : array + { + return $this->ServiceName; + } + + + /** + * Set the value of the ServiceName-property + * + * @param string[] $serviceName + * @return void + */ + public function setServiceName(array $serviceName) : void + { + $this->ServiceName = $serviceName; + } + + + /** + * Collect the value of the ServiceDescription-property + * + * @return string[] + */ + public function getServiceDescription() : array + { + return $this->ServiceDescription; + } + + + /** + * Set the value of the ServiceDescription-property + * + * @param string[] $serviceDescription + * @return void + */ + public function setServiceDescription(array $serviceDescription) : void + { + $this->ServiceDescription = $serviceDescription; + } + + + /** + * Collect the value of the RequestedAttribute-property + * + * @return \SAML2\XML\md\RequestedAttribute[] + */ + public function getRequestedAttribute() : array + { + return $this->RequestedAttribute; + } + + + /** + * Set the value of the RequestedAttribute-property + * + * @param \SAML2\XML\md\RequestedAttribute[] $requestedAttribute + * @return void + */ + public function setRequestedAttribute(array $requestedAttribute) : void + { + $this->RequestedAttribute = $requestedAttribute; + } + + + /** + * Add the value to the RequestedAttribute-property + * + * @param \SAML2\XML\md\RequestedAttribute $requestedAttribute + * @return void + */ + public function addRequestedAttribute(RequestedAttribute $requestedAttribute) : void + { + $this->RequestedAttribute[] = $requestedAttribute; + } + + + /** + * Convert to \DOMElement. + * + * @param \DOMElement $parent The element we should append this AttributeConsumingService to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Constants::NS_MD, 'md:AttributeConsumingService'); + $parent->appendChild($e); + + $e->setAttribute('index', strval($this->getIndex())); + + if ($this->getIsDefault() === true) { + $e->setAttribute('isDefault', 'true'); + } elseif ($this->getIsDefault() === false) { + $e->setAttribute('isDefault', 'false'); + } + + Utils::addStrings($e, Constants::NS_MD, 'md:ServiceName', true, $this->getServiceName()); + Utils::addStrings($e, Constants::NS_MD, 'md:ServiceDescription', true, $this->getServiceDescription()); + + foreach ($this->getRequestedAttribute() as $ra) { + $ra->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AuthnAuthorityDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AuthnAuthorityDescriptor.php new file mode 100644 index 000000000..89ddd80d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/AuthnAuthorityDescriptor.php @@ -0,0 +1,196 @@ +addAuthnQueryService(new EndpointType($ep)); + } + if ($this->getAuthnQueryService() === []) { + throw new \Exception('Must have at least one AuthnQueryService in AuthnAuthorityDescriptor.'); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:AssertionIDRequestService') as $ep) { + $this->addAssertionIDRequestService(new EndpointType($ep)); + } + + $this->setNameIDFormat(Utils::extractStrings($xml, Constants::NS_MD, 'NameIDFormat')); + } + + + /** + * Collect the value of the AuthnQueryService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAuthnQueryService() : array + { + return $this->AuthnQueryService; + } + + + /** + * Set the value of the AuthnQueryService-property + * + * @param \SAML2\XML\md\EndpointType[] $authnQueryService + * @return void + */ + public function setAuthnQueryService(array $authnQueryService) : void + { + $this->AuthnQueryService = $authnQueryService; + } + + + /** + * Add the value to the AuthnQueryService-property + * + * @param \SAML2\XML\md\EndpointType $authnQueryService + * @return void + */ + public function addAuthnQueryService(EndpointType $authnQueryService) : void + { + $this->AuthnQueryService[] = $authnQueryService; + } + + + /** + * Collect the value of the AssertionIDRequestService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAssertionIDRequestService() : array + { + return $this->AssertionIDRequestService; + } + + + /** + * Set the value of the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType[] $assertionIDRequestService + * @return void + */ + public function setAssertionIDRequestService(array $assertionIDRequestService) : void + { + $this->AssertionIDRequestService = $assertionIDRequestService; + } + + + /** + * Add the value to the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType $assertionIDRequestService + * @return void + */ + public function addAssertionIDRequestService(EndpointType $assertionIDRequestService) : void + { + $this->AssertionIDRequestService[] = $assertionIDRequestService; + } + + + /** + * Collect the value of the NameIDFormat-property + * + * @return string[] + */ + public function getNameIDFormat() : array + { + return $this->NameIDFormat; + } + + + /** + * Set the value of the NameIDFormat-property + * + * @param string[] $nameIDFormat + * @return void + */ + public function setNameIDFormat(array $nameIDFormat) : void + { + $this->NameIDFormat = $nameIDFormat; + } + + + /** + * Add this IDPSSODescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this AuthnAuthorityDescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->AuthnQueryService); + + $e = parent::toXML($parent); + + foreach ($this->AuthnQueryService as $ep) { + $ep->toXML($e, 'md:AuthnQueryService'); + } + + foreach ($this->AssertionIDRequestService as $ep) { + $ep->toXML($e, 'md:AssertionIDRequestService'); + } + + Utils::addStrings($e, Constants::NS_MD, 'md:NameIDFormat', false, $this->NameIDFormat); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/ContactPerson.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/ContactPerson.php new file mode 100644 index 000000000..7e230a71a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/ContactPerson.php @@ -0,0 +1,444 @@ +hasAttribute('contactType')) { + throw new \Exception('Missing contactType on ContactPerson.'); + } + $this->setContactType($xml->getAttribute('contactType')); + + $this->setExtensions(Extensions::getList($xml)); + + $this->setCompany(self::getStringElement($xml, 'Company')); + $this->setGivenName(self::getStringElement($xml, 'GivenName')); + $this->setSurName(self::getStringElement($xml, 'SurName')); + $this->setEmailAddress(self::getStringElements($xml, 'EmailAddress')); + $this->setTelephoneNumber(self::getStringElements($xml, 'TelephoneNumber')); + + foreach ($xml->attributes as $attr) { + if ($attr->nodeName == "contactType") { + continue; + } + + $this->addContactPersonAttributes($attr->nodeName, $attr->nodeValue); + } + } + + + /** + * Retrieve the value of a child \DOMElements as an array of strings. + * + * @param \DOMElement $parent The parent element. + * @param string $name The name of the child elements. + * @return array The value of the child elements. + */ + private static function getStringElements(\DOMElement $parent, string $name) : array + { + $e = Utils::xpQuery($parent, './saml_metadata:'.$name); + + $ret = []; + foreach ($e as $i) { + $ret[] = $i->textContent; + } + + return $ret; + } + + + /** + * Retrieve the value of a child \DOMElement as a string. + * + * @param \DOMElement $parent The parent element. + * @param string $name The name of the child element. + * @throws \Exception + * @return string|null The value of the child element. + */ + private static function getStringElement(\DOMElement $parent, string $name) : ?string + { + $e = self::getStringElements($parent, $name); + if (empty($e)) { + return null; + } + if (count($e) > 1) { + throw new \Exception('More than one '.$name.' in '.$parent->tagName); + } + + return $e[0]; + } + + + /** + * Collect the value of the contactType-property + * + * @return string + */ + public function getContactType() : string + { + return $this->contactType; + } + + + /** + * Set the value of the contactType-property + * + * @param string $contactType + * @return void + */ + public function setContactType(string $contactType) : void + { + $this->contactType = $contactType; + } + + + /** + * Collect the value of the Company-property + * + * @return string|null + */ + public function getCompany() : ?string + { + return $this->Company; + } + + + /** + * Set the value of the Company-property + * + * @param string|null $company + * @return void + */ + public function setCompany(string $company = null) : void + { + $this->Company = $company; + } + + + /** + * Collect the value of the GivenName-property + * + * @return string|null + */ + public function getGivenName() : ?string + { + return $this->GivenName; + } + + + /** + * Set the value of the GivenName-property + * + * @param string|null $givenName + * @return void + */ + public function setGivenName(string $givenName = null) : void + { + $this->GivenName = $givenName; + } + + + /** + * Collect the value of the SurName-property + * + * @return string|null + */ + public function getSurName() : ?string + { + return $this->SurName; + } + + + /** + * Set the value of the SurName-property + * + * @param string|null $surName + * @return void + */ + public function setSurName(string $surName = null) : void + { + $this->SurName = $surName; + } + + + /** + * Collect the value of the EmailAddress-property + * + * @return string[] + */ + public function getEmailAddress() : array + { + return $this->EmailAddress; + } + + + /** + * Set the value of the EmailAddress-property + * + * @param string[] $emailAddress + * @return void + */ + public function setEmailAddress(array $emailAddress) : void + { + $emailAddress = preg_replace('/^mailto:/i', '', $emailAddress); + $this->EmailAddress = $emailAddress; + } + + + /** + * Add the value to the EmailAddress-property + * + * @param string $emailAddress + * @return void + */ + public function addEmailAddress($emailAddress) : void + { + $emailAddress = preg_replace('/^mailto:/i', '', $emailAddress); + $this->EmailAddress[] = $emailAddress; + } + + + /** + * Collect the value of the TelephoneNumber-property + * + * @return string[] + */ + public function getTelephoneNumber() : array + { + return $this->TelephoneNumber; + } + + + /** + * Set the value of the TelephoneNumber-property + * + * @param string[] $telephoneNumber + * @return void + */ + public function setTelephoneNumber(array $telephoneNumber) : void + { + $this->TelephoneNumber = $telephoneNumber; + } + + + /** + * Add the value to the TelephoneNumber-property + * + * @param string $telephoneNumber + * @return void + */ + public function addTelephoneNumber($telephoneNumber) : void + { + $this->TelephoneNumber[] = $telephoneNumber; + } + + + /** + * Collect the value of the Extensions-property + * + * @return \SAML2\XML\Chunk[] + */ + public function getExtensions() : array + { + return $this->Extensions; + } + + + /** + * Set the value of the Extensions-property + * + * @param array $extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->Extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param \SAML2\XML\Chunk $extensions The Extensions + * @return void + */ + public function addExtension(Chunk $extension) : void + { + $this->Extensions[] = $extension; + } + + + /** + * Collect the value of the ContactPersonAttributes-property + * + * @return string[] + */ + public function getContactPersonAttributes() : array + { + return $this->ContactPersonAttributes; + } + + + /** + * Set the value of the ContactPersonAttributes-property + * + * @param string[] $contactPersonAttributes + * @return void + */ + public function setContactPersonAttributes(array $contactPersonAttributes) : void + { + $this->ContactPersonAttributes = $contactPersonAttributes; + } + + + /** + * Add the key/value of the ContactPersonAttributes-property + * + * @param string $attr + * @param string $value + * @return void + */ + public function addContactPersonAttributes(string $attr, string $value) : void + { + $this->ContactPersonAttributes[$attr] = $value; + } + + + /** + * Convert this ContactPerson to XML. + * + * @param \DOMElement $parent The element we should add this contact to. + * @return \DOMElement The new ContactPerson-element. + */ + public function toXML(DOMElement $parent) : DOMElement + { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Constants::NS_MD, 'md:ContactPerson'); + $parent->appendChild($e); + + $e->setAttribute('contactType', $this->getContactType()); + + foreach ($this->getContactPersonAttributes() as $attr => $val) { + $e->setAttribute($attr, $val); + } + + Extensions::addList($e, $this->getExtensions()); + + if ($this->Company !== null) { + Utils::addString($e, Constants::NS_MD, 'md:Company', $this->Company); + } + if ($this->GivenName !== null) { + Utils::addString($e, Constants::NS_MD, 'md:GivenName', $this->GivenName); + } + if ($this->SurName !== null) { + Utils::addString($e, Constants::NS_MD, 'md:SurName', $this->SurName); + } + if (!empty($this->getEmailAddress())) { + /** @var array $addresses */ + $addresses = preg_filter('/^/', 'mailto:', $this->EmailAddress); + + Utils::addStrings($e, Constants::NS_MD, 'md:EmailAddress', false, $addresses); + } + if (!empty($this->getTelephoneNumber())) { + Utils::addStrings($e, Constants::NS_MD, 'md:TelephoneNumber', false, $this->getTelephoneNumber()); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EndpointType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EndpointType.php new file mode 100644 index 000000000..7b0832d2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EndpointType.php @@ -0,0 +1,260 @@ +hasAttribute('Binding')) { + throw new \Exception('Missing Binding on '.$xml->tagName); + } + $this->Binding = $xml->getAttribute('Binding'); + + if (!$xml->hasAttribute('Location')) { + throw new \Exception('Missing Location on '.$xml->tagName); + } + $this->Location = $xml->getAttribute('Location'); + + if ($xml->hasAttribute('ResponseLocation')) { + $this->ResponseLocation = $xml->getAttribute('ResponseLocation'); + } + + foreach ($xml->attributes as $a) { + if ($a->namespaceURI === null) { + continue; /* Not namespace-qualified -- skip. */ + } + $fullName = '{'.$a->namespaceURI.'}'.$a->localName; + $this->attributes[$fullName] = [ + 'qualifiedName' => $a->nodeName, + 'namespaceURI' => $a->namespaceURI, + 'value' => $a->value, + ]; + } + } + + + /** + * Check if a namespace-qualified attribute exists. + * + * @param string $namespaceURI The namespace URI. + * @param string $localName The local name. + * @return bool true if the attribute exists, false if not. + */ + public function hasAttributeNS(string $namespaceURI, string $localName) : bool + { + $fullName = '{'.$namespaceURI.'}'.$localName; + + return isset($this->attributes[$fullName]); + } + + + /** + * Get a namespace-qualified attribute. + * + * @param string $namespaceURI The namespace URI. + * @param string $localName The local name. + * @return string The value of the attribute, or an empty string if the attribute does not exist. + */ + public function getAttributeNS(string $namespaceURI, string $localName) : string + { + $fullName = '{'.$namespaceURI.'}'.$localName; + if (!isset($this->attributes[$fullName])) { + return ''; + } + + return $this->attributes[$fullName]['value']; + } + + + /** + * Get a namespace-qualified attribute. + * + * @param string $namespaceURI The namespace URI. + * @param string $qualifiedName The local name. + * @param string $value The attribute value. + * @throws \Exception + * @return void + */ + public function setAttributeNS(string $namespaceURI, string $qualifiedName, string $value) : void + { + $name = explode(':', $qualifiedName, 2); + if (count($name) < 2) { + throw new \Exception('Not a qualified name.'); + } + $localName = $name[1]; + + $fullName = '{'.$namespaceURI.'}'.$localName; + $this->attributes[$fullName] = [ + 'qualifiedName' => $qualifiedName, + 'namespaceURI' => $namespaceURI, + 'value' => $value, + ]; + } + + + /** + * Remove a namespace-qualified attribute. + * + * @param string $namespaceURI The namespace URI. + * @param string $localName The local name. + * @return void + */ + public function removeAttributeNS(string $namespaceURI, string $localName) : void + { + $fullName = '{'.$namespaceURI.'}'.$localName; + unset($this->attributes[$fullName]); + } + + + /** + * Collect the value of the Binding property. + * + * @return string|null + */ + public function getBinding() : ?string + { + return $this->Binding; + } + + + /** + * Set the value of the Binding property. + * + * @param string $binding + * @return void + */ + public function setBinding(string $binding) : void + { + $this->Binding = $binding; + } + + + /** + * Collect the value of the Location property. + * + * @return string|null + */ + public function getLocation() : ?string + { + return $this->Location; + } + + + /** + * Set the value of the Location-property. + * @param string|null $location + * @return void + */ + public function setLocation(string $location = null) : void + { + $this->Location = $location; + } + + + /** + * Collect the value of the ResponseLocation property. + * + * @return string|null + */ + public function getResponseLocation() : ?string + { + return $this->ResponseLocation; + } + + + /** + * Set the value of the ResponseLocation property. + * + * @param string|null $responseLocation + * @return void + */ + public function setResponseLocation(string $responseLocation = null) : void + { + $this->ResponseLocation = $responseLocation; + } + + + /** + * Add this endpoint to an XML element. + * + * @param \DOMElement $parent The element we should append this endpoint to. + * @param string $name The name of the element we should create. + * @return \DOMElement + */ + public function toXML(DOMElement $parent, string $name) : DOMElement + { + $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, $name); + $parent->appendChild($e); + + if (empty($this->Binding)) { + throw new \Exception('Cannot convert endpoint to XML without a Binding set.'); + } + if (empty($this->Location)) { + throw new \Exception('Cannot convert endpoint to XML without a Location set.'); + } + + $e->setAttribute('Binding', $this->Binding); + $e->setAttribute('Location', $this->Location); + + if ($this->ResponseLocation !== null) { + $e->setAttribute('ResponseLocation', $this->ResponseLocation); + } + + foreach ($this->attributes as $a) { + $e->setAttributeNS($a['namespaceURI'], $a['qualifiedName'], $a['value']); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntitiesDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntitiesDescriptor.php new file mode 100644 index 000000000..a1b1cce25 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntitiesDescriptor.php @@ -0,0 +1,296 @@ +hasAttribute('ID')) { + $this->ID = $xml->getAttribute('ID'); + } + if ($xml->hasAttribute('validUntil')) { + $this->validUntil = Utils::xsDateTimeToTimestamp($xml->getAttribute('validUntil')); + } + if ($xml->hasAttribute('cacheDuration')) { + $this->cacheDuration = $xml->getAttribute('cacheDuration'); + } + if ($xml->hasAttribute('Name')) { + $this->Name = $xml->getAttribute('Name'); + } + + $this->Extensions = Extensions::getList($xml); + + /** @var \DOMElement $node */ + foreach (Utils::xpQuery($xml, './saml_metadata:EntityDescriptor|./saml_metadata:EntitiesDescriptor') as $node) { + if ($node->localName === 'EntityDescriptor') { + $this->children[] = new EntityDescriptor($node); + } else { + $this->children[] = new EntitiesDescriptor($node); + } + } + } + + + /** + * Collect the value of the Name property. + * + * @return string|null + */ + public function getName() : ?string + { + return $this->Name; + } + + + /** + * Set the value of the Name property. + * + * @param string|null $name + * @return void + */ + public function setName(string $name = null) : void + { + $this->Name = $name; + } + + + /** + * Collect the value of the ID property. + * + * @return string|null + */ + public function getID() : ?string + { + return $this->ID; + } + + + /** + * Set the value of the ID property. + * + * @param string|null $Id + * @return void + */ + public function setID(string $Id = null) : void + { + $this->ID = $Id; + } + + + /** + * Collect the value of the validUntil-property + * @return int|null + */ + public function getValidUntil() : ?int + { + return $this->validUntil; + } + + + /** + * Set the value of the validUntil-property + * @param int|null $validUntil + * @return void + */ + public function setValidUntil(int $validUntil = null) : void + { + $this->validUntil = $validUntil; + } + + + /** + * Collect the value of the cacheDuration-property + * @return string|null + */ + public function getCacheDuration() : ?string + { + return $this->cacheDuration; + } + + + /** + * Set the value of the cacheDuration-property + * @param string|null $cacheDuration + * @return void + */ + public function setCacheDuration(string $cacheDuration = null) : void + { + $this->cacheDuration = $cacheDuration; + } + + + /** + * Collect the value of the Extensions property. + * + * @return \SAML2\XML\Chunk[] + */ + public function getExtensions() : array + { + return $this->Extensions; + } + + + /** + * Set the value of the Extensions property. + * + * @param array $extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->Extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param \SAML2\XML\Chunk $extensions The Extensions + * @return void + */ + public function addExtension(Extensions $extension) : void + { + $this->Extensions[] = $extension; + } + + + /** + * Collect the value of the children property. + * + * @return (\SAML2\XML\md\EntityDescriptor|\SAML2\XML\md\EntitiesDescriptor)[] + */ + public function getChildren() : array + { + return $this->children; + } + + + /** + * Set the value of the childen property. + * + * @param array $children + * @return void + */ + public function setChildren(array $children) : void + { + $this->children = $children; + } + + + /** + * Add the value to the children property. + * + * @param \SAML2\XML\md\EntityDescriptor|\SAML2\XML\md\EntitiesDescriptor $child + * @return void + */ + public function addChildren($child) : void + { + Assert::isInstanceOfAny($child, [EntityDescriptor::class, EntitiesDescriptor::class]); + $this->children[] = $child; + } + + + /** + * Convert this EntitiesDescriptor to XML. + * + * @param \DOMElement|null $parent The EntitiesDescriptor we should append this EntitiesDescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null) : DOMElement + { + if ($parent === null) { + $doc = DOMDocumentFactory::create(); + $e = $doc->createElementNS(Constants::NS_MD, 'md:EntitiesDescriptor'); + $doc->appendChild($e); + } else { + $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, 'md:EntitiesDescriptor'); + $parent->appendChild($e); + } + + if ($this->ID !== null) { + $e->setAttribute('ID', $this->ID); + } + + if ($this->validUntil !== null) { + $e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil)); + } + + if ($this->cacheDuration !== null) { + $e->setAttribute('cacheDuration', $this->cacheDuration); + } + + if ($this->Name !== null) { + $e->setAttribute('Name', $this->Name); + } + + Extensions::addList($e, $this->Extensions); + + /** @var \SAML2\XML\md\EntityDescriptor|\SAML2\XML\md\EntitiesDescriptor $node */ + foreach ($this->children as $node) { + $node->toXML($e); + } + + $this->signElement($e, $e->firstChild); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntityDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntityDescriptor.php new file mode 100644 index 000000000..7ed69997d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/EntityDescriptor.php @@ -0,0 +1,511 @@ +hasAttribute('entityID')) { + throw new \Exception('Missing required attribute entityID on EntityDescriptor.'); + } + $this->entityID = $xml->getAttribute('entityID'); + + if ($xml->hasAttribute('ID')) { + $this->ID = $xml->getAttribute('ID'); + } + if ($xml->hasAttribute('validUntil')) { + $this->validUntil = Utils::xsDateTimeToTimestamp($xml->getAttribute('validUntil')); + } + if ($xml->hasAttribute('cacheDuration')) { + $this->cacheDuration = $xml->getAttribute('cacheDuration'); + } + + $this->Extensions = Extensions::getList($xml); + + foreach ($xml->childNodes as $node) { + if (!($node instanceof DOMElement)) { + continue; + } + + if ($node->namespaceURI !== Constants::NS_MD) { + continue; + } + + switch ($node->localName) { + case 'RoleDescriptor': + $this->RoleDescriptor[] = new UnknownRoleDescriptor($node); + break; + case 'IDPSSODescriptor': + $this->RoleDescriptor[] = new IDPSSODescriptor($node); + break; + case 'SPSSODescriptor': + $this->RoleDescriptor[] = new SPSSODescriptor($node); + break; + case 'AuthnAuthorityDescriptor': + $this->RoleDescriptor[] = new AuthnAuthorityDescriptor($node); + break; + case 'AttributeAuthorityDescriptor': + $this->RoleDescriptor[] = new AttributeAuthorityDescriptor($node); + break; + case 'PDPDescriptor': + $this->RoleDescriptor[] = new PDPDescriptor($node); + break; + case 'AffiliationDescriptor': + if ($this->AffiliationDescriptor !== null) { + throw new \Exception('More than one AffiliationDescriptor in the entity.'); + } + $this->AffiliationDescriptor = new AffiliationDescriptor($node); + break; + case 'Organization': + if ($this->Organization !== null) { + throw new \Exception('More than one Organization in the entity.'); + } + $this->Organization = new Organization($node); + break; + case 'ContactPerson': + $this->ContactPerson[] = new ContactPerson($node); + break; + case 'AdditionalMetadataLocation': + $this->AdditionalMetadataLocation[] = new AdditionalMetadataLocation($node); + break; + } + } + + if (empty($this->RoleDescriptor) && is_null($this->AffiliationDescriptor)) { + throw new \Exception( + 'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.' + ); + } elseif (!empty($this->RoleDescriptor) && !is_null($this->AffiliationDescriptor)) { + throw new \Exception( + 'AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.' + ); + } + } + + + /** + * Collect the value of the entityID property. + * + * @return string + */ + public function getEntityID() : string + { + return $this->entityID; + } + + + /** + * Set the value of the entityID-property + * @param string $entityId + * @return void + */ + public function setEntityID(string $entityId) : void + { + $this->entityID = $entityId; + } + + + /** + * Collect the value of the ID property. + * + * @return string|null + */ + public function getID() : ?string + { + return $this->ID; + } + + + /** + * Set the value of the ID property. + * + * @param string|null $Id + * @return void + */ + public function setID(string $Id = null) : void + { + $this->ID = $Id; + } + + + /** + * Collect the value of the validUntil-property + * @return int|null + */ + public function getValidUntil() : ?int + { + return $this->validUntil; + } + + + /** + * Set the value of the validUntil-property + * @param int|null $validUntil + * @return void + */ + public function setValidUntil(int $validUntil = null) : void + { + $this->validUntil = $validUntil; + } + + + /** + * Collect the value of the cacheDuration-property + * @return string|null + */ + public function getCacheDuration() : ?string + { + return $this->cacheDuration; + } + + + /** + * Set the value of the cacheDuration-property + * @param string|null $cacheDuration + * @return void + */ + public function setCacheDuration(string $cacheDuration = null) : void + { + $this->cacheDuration = $cacheDuration; + } + + + /** + * Collect the value of the Extensions property. + * + * @return \SAML2\XML\Chunk[] + */ + public function getExtensions() : array + { + return $this->Extensions; + } + + + /** + * Set the value of the Extensions property. + * + * @param array $extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->Extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param \SAML2\XML\Chunk $extensions The Extensions + * @return void + */ + public function addExtension(Extensions $extension) : void + { + $this->Extensions[] = $extension; + } + + + /** + * Collect the value of the RoleDescriptor property. + * + * @return \SAML2\XML\md\RoleDescriptor[] + */ + public function getRoleDescriptor() : array + { + return $this->RoleDescriptor; + } + + + /** + * Set the value of the RoleDescriptor property. + * + * @param \SAML2\XML\md\RoleDescriptor[] $roleDescriptor + * @return void + */ + public function setRoleDescriptor(array $roleDescriptor) : void + { + $this->RoleDescriptor = $roleDescriptor; + } + + + /** + * Add the value to the RoleDescriptor property. + * + * @param \SAML2\XML\md\RoleDescriptor $roleDescriptor + * @return void + */ + public function addRoleDescriptor(RoleDescriptor $roleDescriptor) : void + { + $this->RoleDescriptor[] = $roleDescriptor; + } + + + /** + * Collect the value of the AffiliationDescriptor property. + * + * @return \SAML2\XML\md\AffiliationDescriptor|null + */ + public function getAffiliationDescriptor() : ?AffiliationDescriptor + { + return $this->AffiliationDescriptor; + } + + + /** + * Set the value of the AffliationDescriptor property. + * + * @param \SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor + * @return void + */ + public function setAffiliationDescriptor(AffiliationDescriptor $affiliationDescriptor = null) : void + { + $this->AffiliationDescriptor = $affiliationDescriptor; + } + + + /** + * Collect the value of the Organization property. + * + * @return \SAML2\XML\md\Organization|null + */ + public function getOrganization() : ?Organization + { + return $this->Organization; + } + + + /** + * Set the value of the Organization property. + * + * @param \SAML2\XML\md\Organization|null $organization + * @return void + */ + public function setOrganization(Organization $organization = null) : void + { + $this->Organization = $organization; + } + + + /** + * Collect the value of the ContactPerson property. + * + * @return \SAML2\XML\md\ContactPerson[] + */ + public function getContactPerson() : array + { + return $this->ContactPerson; + } + + + /** + * Set the value of the ContactPerson property. + * + * @param array $contactPerson + * @return void + */ + public function setContactPerson(array $contactPerson) : void + { + $this->ContactPerson = $contactPerson; + } + + + /** + * Add the value to the ContactPerson property. + * + * @param \SAML2\XML\md\ContactPerson $contactPerson + * @return void + */ + public function addContactPerson(ContactPerson $contactPerson) : void + { + $this->ContactPerson[] = $contactPerson; + } + + + /** + * Collect the value of the AdditionalMetadataLocation property. + * + * @return \SAML2\XML\md\AdditionalMetadataLocation[] + */ + public function getAdditionalMetadataLocation() : array + { + return $this->AdditionalMetadataLocation; + } + + + /** + * Set the value of the AdditionalMetadataLocation property. + * + * @param array $additionalMetadataLocation + * @return void + */ + public function setAdditionalMetadataLocation(array $additionalMetadataLocation) : void + { + $this->AdditionalMetadataLocation = $additionalMetadataLocation; + } + + + /** + * Add the value to the AdditionalMetadataLocation property. + * + * @param AdditionalMetadataLocation $additionalMetadataLocation + * @return void + */ + public function addAdditionalMetadataLocation(AdditionalMetadataLocation $additionalMetadataLocation) : void + { + $this->AdditionalMetadataLocation[] = $additionalMetadataLocation; + } + + + /** + * Create this EntityDescriptor. + * + * @param \DOMElement|null $parent The EntitiesDescriptor we should append this EntityDescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null) : DOMElement + { + if (empty($this->entityID)) { + throw new \Exception('Cannot convert EntityDescriptor to XML without an EntityID set.'); + } + + if ($parent === null) { + $doc = DOMDocumentFactory::create(); + $e = $doc->createElementNS(Constants::NS_MD, 'md:EntityDescriptor'); + $doc->appendChild($e); + } else { + $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, 'md:EntityDescriptor'); + $parent->appendChild($e); + } + + $e->setAttribute('entityID', $this->entityID); + + if ($this->ID !== null) { + $e->setAttribute('ID', $this->ID); + } + + if ($this->validUntil !== null) { + $e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil)); + } + + if ($this->cacheDuration !== null) { + $e->setAttribute('cacheDuration', $this->cacheDuration); + } + + Extensions::addList($e, $this->Extensions); + + foreach ($this->RoleDescriptor as $n) { + $n->toXML($e); + } + + if ($this->AffiliationDescriptor !== null) { + $this->AffiliationDescriptor->toXML($e); + } + + if ($this->Organization !== null) { + $this->Organization->toXML($e); + } + + foreach ($this->ContactPerson as $cp) { + $cp->toXML($e); + } + + foreach ($this->AdditionalMetadataLocation as $n) { + $n->toXML($e); + } + + /** @var \DOMElement $child */ + $child = $e->firstChild; + $this->signElement($e, $child); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Extensions.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Extensions.php new file mode 100644 index 000000000..fda7a4a3c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Extensions.php @@ -0,0 +1,103 @@ + [ + 'Scope' => Scope::class, + ], + EntityAttributes::NS => [ + 'EntityAttributes' => EntityAttributes::class, + ], + MDRPI::NS_MDRPI => [ + 'RegistrationInfo' => RegistrationInfo::class, + 'PublicationInfo' => PublicationInfo::class, + ], + MDUI::NS => [ + 'UIInfo' => UIInfo::class, + 'DiscoHints' => DiscoHints::class, + ], + ALG::NS => [ + 'DigestMethod' => DigestMethod::class, + 'SigningMethod' => SigningMethod::class, + ], + ]; + + /** @var \DOMElement $node */ + foreach (Utils::xpQuery($parent, './saml_metadata:Extensions/*') as $node) { + if (!is_null($node->namespaceURI) && array_key_exists($node->namespaceURI, $supported) && + array_key_exists($node->localName, $supported[$node->namespaceURI]) + ) { + $ret[] = new $supported[$node->namespaceURI][$node->localName]($node); + } else { + $ret[] = new Chunk($node); + } + } + + return $ret; + } + + + /** + * Add a list of Extensions to the given element. + * + * @param \DOMElement $parent The element we should add the extensions to. + * @param \SAML2\XML\Chunk[] $extensions List of extension objects. + * @return void + */ + public static function addList(DOMElement $parent, array $extensions) : void + { + if (empty($extensions)) { + return; + } + + $extElement = $parent->ownerDocument->createElementNS(Constants::NS_MD, 'md:Extensions'); + $parent->appendChild($extElement); + + foreach ($extensions as $ext) { + $ext->toXML($extElement); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IDPSSODescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IDPSSODescriptor.php new file mode 100644 index 000000000..c8690eddb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IDPSSODescriptor.php @@ -0,0 +1,331 @@ +WantAuthnRequestsSigned = Utils::parseBoolean($xml, 'WantAuthnRequestsSigned', null); + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:SingleSignOnService') as $ep) { + $this->SingleSignOnService[] = new EndpointType($ep); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:NameIDMappingService') as $ep) { + $this->NameIDMappingService[] = new EndpointType($ep); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:AssertionIDRequestService') as $ep) { + $this->AssertionIDRequestService[] = new EndpointType($ep); + } + + $this->AttributeProfile = Utils::extractStrings($xml, Constants::NS_MD, 'AttributeProfile'); + + /** @var \DOMElement $a */ + foreach (Utils::xpQuery($xml, './saml_assertion:Attribute') as $a) { + $this->Attribute[] = new Attribute($a); + } + } + + + /** + * Collect the value of the WantAuthnRequestsSigned-property + * + * @return bool|null + */ + public function wantAuthnRequestsSigned() : ?bool + { + return $this->WantAuthnRequestsSigned; + } + + + /** + * Set the value of the WantAuthnRequestsSigned-property + * + * @param bool|null $flag + * @return void + */ + public function setWantAuthnRequestsSigned(bool $flag = null) : void + { + $this->WantAuthnRequestsSigned = $flag; + } + + + /** + * Collect the value of the SingleSignOnService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getSingleSignOnService() : array + { + return $this->SingleSignOnService; + } + + + /** + * Set the value of the SingleSignOnService-property + * + * @param array $singleSignOnService + * @return void + */ + public function setSingleSignOnService(array $singleSignOnService) : void + { + $this->SingleSignOnService = $singleSignOnService; + } + + + /** + * Add the value to the SingleSignOnService-property + * + * @param \SAML2\XML\md\EndpointType $singleSignOnService + * @return void + */ + public function addSingleSignOnService(EndpointType $singleSignOnService) : void + { + $this->SingleSignOnService[] = $singleSignOnService; + } + + + /** + * Collect the value of the NameIDMappingService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getNameIDMappingService() : array + { + return $this->NameIDMappingService; + } + + + /** + * Set the value of the NameIDMappingService-property + * + * @param array $nameIDMappingService + * @return void + */ + public function setNameIDMappingService(array $nameIDMappingService) : void + { + $this->NameIDMappingService = $nameIDMappingService; + } + + + /** + * Add the value to the NameIDMappingService-property + * + * @param \SAML2\XML\md\EndpointType $nameIDMappingService + * @return void + */ + public function addNameIDMappingService(EndpointType $nameIDMappingService) : void + { + $this->NameIDMappingService[] = $nameIDMappingService; + } + + + /** + * Collect the value of the AssertionIDRequestService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAssertionIDRequestService() : array + { + return $this->AssertionIDRequestService; + } + + + /** + * Set the value of the AssertionIDRequestService-property + * + * @param array $assertionIDRequestService + * @return void + */ + public function setAssertionIDRequestService(array $assertionIDRequestService) : void + { + $this->AssertionIDRequestService = $assertionIDRequestService; + } + + + /** + * Add the value to the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType $assertionIDRequestService + * @return void + */ + public function addAssertionIDRequestService(EndpointType $assertionIDRequestService) : void + { + $this->AssertionIDRequestService[] = $assertionIDRequestService; + } + + + /** + * Collect the value of the AttributeProfile-property + * @return array + */ + public function getAttributeProfile() : array + { + return $this->AttributeProfile; + } + + + /** + * Set the value of the AttributeProfile-property + * + * @param array $attributeProfile + * @return void + */ + public function setAttributeProfile(array $attributeProfile) : void + { + $this->AttributeProfile = $attributeProfile; + } + + + /** + * Collect the value of the Attribute-property + * + * @return \SAML2\XML\saml\Attribute[] + */ + public function getAttribute() : array + { + return $this->Attribute; + } + + + /** + * Set the value of the Attribute-property + * + * @param array $attribute + * @return void + */ + public function setAttribute(array $attribute) : void + { + $this->Attribute = $attribute; + } + + + /** + * Addthe value to the Attribute-property + * + * @param \SAML2\XML\saml\Attribute $attribute + * @return void + */ + public function addAttribute(Attribute $attribute) : void + { + $this->Attribute[] = $attribute; + } + + + /** + * Add this IDPSSODescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this IDPSSODescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = parent::toXML($parent); + + if (is_bool($this->WantAuthnRequestsSigned)) { + $e->setAttribute('WantAuthnRequestsSigned', $this->WantAuthnRequestsSigned ? 'true' : 'false'); + } + + foreach ($this->SingleSignOnService as $ep) { + $ep->toXML($e, 'md:SingleSignOnService'); + } + + foreach ($this->NameIDMappingService as $ep) { + $ep->toXML($e, 'md:NameIDMappingService'); + } + + foreach ($this->AssertionIDRequestService as $ep) { + $ep->toXML($e, 'md:AssertionIDRequestService'); + } + + Utils::addStrings($e, Constants::NS_MD, 'md:AttributeProfile', false, $this->AttributeProfile); + + foreach ($this->Attribute as $a) { + $a->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IndexedEndpointType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IndexedEndpointType.php new file mode 100644 index 000000000..c874b58eb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/IndexedEndpointType.php @@ -0,0 +1,120 @@ +hasAttribute('index')) { + throw new \Exception('Missing index on '.$xml->tagName); + } + $this->index = intval($xml->getAttribute('index')); + + $this->isDefault = Utils::parseBoolean($xml, 'isDefault', null); + } + + + /** + * Collect the value of the index property. + * + * @return int + */ + public function getIndex() : int + { + return $this->index; + } + + + /** + * Set the value of the index property. + * + * @param int $index + * @return void + */ + public function setIndex(int $index) : void + { + $this->index = $index; + } + + + /** + * Collect the value of the isDefault property. + * + * @return bool|null + */ + public function getIsDefault() : ?bool + { + return $this->isDefault; + } + + + /** + * Set the value of the isDefault property. + * + * @param bool|null $flag + * @return void + */ + public function setIsDefault(bool $flag = null) : void + { + $this->isDefault = $flag; + } + + + /** + * Add this endpoint to an XML element. + * + * @param \DOMElement $parent The element we should append this endpoint to. + * @param string $name The name of the element we should create. + * @return \DOMElement + */ + public function toXML(DOMElement $parent, string $name) : DOMElement + { + $e = parent::toXML($parent, $name); + $e->setAttribute('index', strval($this->index)); + + if (is_bool($this->isDefault)) { + $e->setAttribute('isDefault', $this->isDefault ? 'true' : 'false'); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/KeyDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/KeyDescriptor.php new file mode 100644 index 000000000..8463a1bbf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/KeyDescriptor.php @@ -0,0 +1,190 @@ +hasAttribute('use')) { + $this->use = $xml->getAttribute('use'); + } + + $keyInfo = Utils::xpQuery($xml, './ds:KeyInfo'); + if (count($keyInfo) > 1) { + throw new \Exception('More than one ds:KeyInfo in the KeyDescriptor.'); + } elseif (empty($keyInfo)) { + throw new \Exception('No ds:KeyInfo in the KeyDescriptor.'); + } + /** @var \DOMElement $keyInfo[0] */ + $this->KeyInfo = new KeyInfo($keyInfo[0]); + + /** @var \DOMElement $em */ + foreach (Utils::xpQuery($xml, './saml_metadata:EncryptionMethod') as $em) { + $this->EncryptionMethod[] = new Chunk($em); + } + } + + + /** + * Collect the value of the use property. + * + * @return string|null + */ + public function getUse() : ?string + { + return $this->use; + } + + + /** + * Set the value of the use property. + * + * @param string|null $use + * @return void + */ + public function setUse(string $use = null) : void + { + $this->use = $use; + } + + + /** + * Collect the value of the KeyInfo property. + * + * @return \SAML2\XML\ds\KeyInfo|null + */ + public function getKeyInfo() : ?KeyInfo + { + return $this->KeyInfo; + } + + + /** + * Set the value of the KeyInfo property. + * + * @param \SAML2\XML\ds\KeyInfo $keyInfo + * @return void + */ + public function setKeyInfo(KeyInfo $keyInfo) : void + { + $this->KeyInfo = $keyInfo; + } + + + /** + * Collect the value of the EncryptionMethod property. + * + * @return \SAML2\XML\Chunk[] + */ + public function getEncryptionMethod() : array + { + return $this->EncryptionMethod; + } + + + /** + * Set the value of the EncryptionMethod property. + * + * @param \SAML2\XML\Chunk[] $encryptionMethod + * @return void + */ + public function setEncryptionMethod(array $encryptionMethod) : void + { + $this->EncryptionMethod = $encryptionMethod; + } + + + /** + * Add the value to the EncryptionMethod property. + * + * @param \SAML2\XML\Chunk $encryptionMethod + * @return void + */ + public function addEncryptionMethod(Chunk $encryptionMethod) : void + { + $this->EncryptionMethod[] = $encryptionMethod; + } + + + /** + * Convert this KeyDescriptor to XML. + * + * @param \DOMElement $parent The element we should append this KeyDescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + if ($this->KeyInfo === null) { + throw new \Exception('Cannot convert KeyDescriptor to XML without KeyInfo set.'); + } + + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Constants::NS_MD, 'md:KeyDescriptor'); + $parent->appendChild($e); + + if ($this->use !== null) { + $e->setAttribute('use', $this->use); + } + + $this->KeyInfo->toXML($e); + + foreach ($this->EncryptionMethod as $em) { + $em->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Organization.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Organization.php new file mode 100644 index 000000000..38543a9f5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/Organization.php @@ -0,0 +1,206 @@ + translation. + * + * @var array + */ + private $OrganizationName = []; + + /** + * The OrganizationDisplayName, as an array of language => translation. + * + * @var array + */ + private $OrganizationDisplayName = []; + + /** + * The OrganizationURL, as an array of language => translation. + * + * @var array + */ + private $OrganizationURL = []; + + + /** + * Initialize an Organization element. + * + * @param \DOMElement|null $xml The XML element we should load. + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + $this->Extensions = Extensions::getList($xml); + + $this->OrganizationName = Utils::extractLocalizedStrings($xml, Constants::NS_MD, 'OrganizationName'); + + $this->OrganizationDisplayName = Utils::extractLocalizedStrings( + $xml, + Constants::NS_MD, + 'OrganizationDisplayName' + ); + + $this->OrganizationURL = Utils::extractLocalizedStrings($xml, Constants::NS_MD, 'OrganizationURL'); + } + + + /** + * Collect the value of the Extensions property. + * + * @return \SAML2\XML\Chunk[] + */ + public function getExtensions() : array + { + return $this->Extensions; + } + + + /** + * Set the value of the Extensions property. + * + * @param array $extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->Extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param \SAML2\XML\Chunk $extensions The Extensions + * @return void + */ + public function addExtension(Extensions $extension) : void + { + $this->Extensions[] = $extension; + } + + + /** + * Collect the value of the OrganizationName property. + * + * @return string[] + */ + public function getOrganizationName() : array + { + return $this->OrganizationName; + } + + + /** + * Set the value of the OrganizationName property. + * + * @param array $organizationName + * @return void + */ + public function setOrganizationName(array $organizationName) : void + { + $this->OrganizationName = $organizationName; + } + + + /** + * Collect the value of the OrganizationDisplayName property. + * + * @return string[] + */ + public function getOrganizationDisplayName() : array + { + return $this->OrganizationDisplayName; + } + + + /** + * Set the value of the OrganizationDisplayName property. + * + * @param array $organizationDisplayName + * @return void + */ + public function setOrganizationDisplayName(array $organizationDisplayName) : void + { + $this->OrganizationDisplayName = $organizationDisplayName; + } + + + /** + * Collect the value of the OrganizationURL property. + * + * @return string[] + */ + public function getOrganizationURL() : array + { + return $this->OrganizationURL; + } + + + /** + * Set the value of the OrganizationURL property. + * + * @param array $organizationURL + * @return void + */ + public function setOrganizationURL(array $organizationURL) : void + { + $this->OrganizationURL = $organizationURL; + } + + + /** + * Convert this Organization to XML. + * + * @param \DOMElement $parent The element we should add this organization to. + * @return \DOMElement This Organization-element. + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->OrganizationName); + Assert::notEmpty($this->OrganizationDisplayName); + Assert::notEmpty($this->OrganizationURL); + + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Constants::NS_MD, 'md:Organization'); + $parent->appendChild($e); + + Extensions::addList($e, $this->Extensions); + + Utils::addStrings($e, Constants::NS_MD, 'md:OrganizationName', true, $this->OrganizationName); + Utils::addStrings($e, Constants::NS_MD, 'md:OrganizationDisplayName', true, $this->OrganizationDisplayName); + Utils::addStrings($e, Constants::NS_MD, 'md:OrganizationURL', true, $this->OrganizationURL); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/PDPDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/PDPDescriptor.php new file mode 100644 index 000000000..eb3dfb221 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/PDPDescriptor.php @@ -0,0 +1,196 @@ +AuthzService[] = new EndpointType($ep); + } + if ($this->getAuthzService() !== []) { + throw new \Exception('Must have at least one AuthzService in PDPDescriptor.'); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:AssertionIDRequestService') as $ep) { + $this->AssertionIDRequestService[] = new EndpointType($ep); + } + + $this->NameIDFormat = Utils::extractStrings($xml, Constants::NS_MD, 'NameIDFormat'); + } + + + /** + * Collect the value of the AuthzService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAuthzService() : array + { + return $this->AuthzService; + } + + + /** + * Set the value of the AuthzService-property + * + * @param \SAML2\XML\md\EndpointType[] $authzService + * @return void + */ + public function setAuthzService(array $authzService = []) : void + { + $this->AuthzService = $authzService; + } + + + /** + * Add the value to the AuthzService-property + * + * @param \SAML2\XML\md\EndpointType $authzService + * @return void + */ + public function addAuthzService(EndpointType $authzService) : void + { + $this->AuthzService[] = $authzService; + } + + + /** + * Collect the value of the AssertionIDRequestService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getAssertionIDRequestService() : array + { + return $this->AssertionIDRequestService; + } + + + /** + * Set the value of the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType[] $assertionIDRequestService + * @return void + */ + public function setAssertionIDRequestService(array $assertionIDRequestService) : void + { + $this->AssertionIDRequestService = $assertionIDRequestService; + } + + + /** + * Add the value to the AssertionIDRequestService-property + * + * @param \SAML2\XML\md\EndpointType $assertionIDRequestService + * @return void + */ + public function addAssertionIDRequestService(EndpointType $assertionIDRequestService) : void + { + $this->AssertionIDRequestService[] = $assertionIDRequestService; + } + + + /** + * Collect the value of the NameIDFormat-property + * + * @return string[] + */ + public function getNameIDFormat() : array + { + return $this->NameIDFormat; + } + + + /** + * Set the value of the NameIDFormat-property + * + * @param string[] $nameIDFormat + * @return void + */ + public function setNameIDFormat(array $nameIDFormat) : void + { + $this->NameIDFormat = $nameIDFormat; + } + + + /** + * Add this PDPDescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this IDPSSODescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->AuthzService); + + $e = parent::toXML($parent); + + foreach ($this->AuthzService as $ep) { + $ep->toXML($e, 'md:AuthzService'); + } + + foreach ($this->AssertionIDRequestService as $ep) { + $ep->toXML($e, 'md:AssertionIDRequestService'); + } + + Utils::addStrings($e, Constants::NS_MD, 'md:NameIDFormat', false, $this->NameIDFormat); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RequestedAttribute.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RequestedAttribute.php new file mode 100644 index 000000000..816804434 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RequestedAttribute.php @@ -0,0 +1,84 @@ +isRequired = Utils::parseBoolean($xml, 'isRequired', null); + } + + + /** + * Collect the value of the isRequired-property + * + * @return bool|null + */ + public function getIsRequired() : ?bool + { + return $this->isRequired; + } + + + /** + * Set the value of the isRequired-property + * + * @param bool|null $flag + * @return void + */ + public function setIsRequired(bool $flag = null) : void + { + $this->isRequired = $flag; + } + + + /** + * Convert this RequestedAttribute to XML. + * + * @param \DOMElement $parent The element we should append this RequestedAttribute to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = $this->toXMLInternal($parent, Constants::NS_MD, 'md:RequestedAttribute'); + + if (is_bool($this->isRequired)) { + $e->setAttribute('isRequired', $this->isRequired ? 'true' : 'false'); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RoleDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RoleDescriptor.php new file mode 100644 index 000000000..5457e19ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/RoleDescriptor.php @@ -0,0 +1,440 @@ +elementName = $elementName; + + if ($xml === null) { + return; + } + + if ($xml->hasAttribute('ID')) { + $this->ID = $xml->getAttribute('ID'); + } + if ($xml->hasAttribute('validUntil')) { + $this->validUntil = Utils::xsDateTimeToTimestamp($xml->getAttribute('validUntil')); + } + if ($xml->hasAttribute('cacheDuration')) { + $this->cacheDuration = $xml->getAttribute('cacheDuration'); + } + + if (!$xml->hasAttribute('protocolSupportEnumeration')) { + throw new \Exception('Missing protocolSupportEnumeration attribute on '.$xml->localName); + } + $this->protocolSupportEnumeration = preg_split('/[\s]+/', $xml->getAttribute('protocolSupportEnumeration')); + + if ($xml->hasAttribute('errorURL')) { + $this->errorURL = $xml->getAttribute('errorURL'); + } + + $this->Extensions = Extensions::getList($xml); + + foreach (Utils::xpQuery($xml, './saml_metadata:KeyDescriptor') as $kd) { + /** @var \DOMElement $kd */ + $this->KeyDescriptor[] = new KeyDescriptor($kd); + } + + $organization = Utils::xpQuery($xml, './saml_metadata:Organization'); + if (count($organization) > 1) { + throw new \Exception('More than one Organization in the entity.'); + } elseif (!empty($organization)) { + /** @var \DOMElement $organization[0] */ + $this->Organization = new Organization($organization[0]); + } + + foreach (Utils::xpQuery($xml, './saml_metadata:ContactPerson') as $cp) { + /** @var \DOMElement $cp */ + $this->ContactPerson[] = new ContactPerson($cp); + } + } + + + /** + * Collect the value of the ID property. + * + * @return string|null + */ + public function getID() : ?string + { + return $this->ID; + } + + + /** + * Set the value of the ID property. + * + * @param string|null $Id + * @return void + */ + public function setID(string $Id = null) : void + { + $this->ID = $Id; + } + + + /** + * Collect the value of the validUntil-property + * @return int|null + */ + public function getValidUntil() : ?int + { + return $this->validUntil; + } + + + /** + * Set the value of the validUntil-property + * @param int|null $validUntil + * @return void + */ + public function setValidUntil(int $validUntil = null) : void + { + $this->validUntil = $validUntil; + } + + + /** + * Collect the value of the cacheDuration-property + * @return string|null + */ + public function getCacheDuration() : ?string + { + return $this->cacheDuration; + } + + + /** + * Set the value of the cacheDuration-property + * @param string|null $cacheDuration + * @return void + */ + public function setCacheDuration(string $cacheDuration = null) : void + { + $this->cacheDuration = $cacheDuration; + } + + + /** + * Collect the value of the Extensions property. + * + * @return \SAML2\XML\Chunk[] + */ + public function getExtensions() : array + { + return $this->Extensions; + } + + + /** + * Set the value of the Extensions property. + * + * @param array $extensions + * @return void + */ + public function setExtensions(array $extensions) : void + { + $this->Extensions = $extensions; + } + + + /** + * Add an Extension. + * + * @param \SAML2\XML\Chunk $extensions The Extensions + * @return void + */ + public function addExtension(Extensions $extension) : void + { + $this->Extensions[] = $extension; + } + + + /** + * Set the value of the errorURL property. + * + * @param string|null $errorURL + * @return void + */ + public function setErrorURL(string $errorURL = null) : void + { + if (!is_null($errorURL) && !filter_var($errorURL, FILTER_VALIDATE_URL)) { + throw new \InvalidArgumentException('RoleDescriptor errorURL is not a valid URL.'); + } + $this->errorURL = $errorURL; + } + + + /** + * Collect the value of the errorURL property. + * + * @return string|null + */ + public function getErrorURL() : ?string + { + return $this->errorURL; + } + + + /** + * Collect the value of the ProtocolSupportEnumeration property. + * + * @return string[] + */ + public function getProtocolSupportEnumeration() : array + { + return $this->protocolSupportEnumeration; + } + + + /** + * Set the value of the ProtocolSupportEnumeration property. + * + * @param array $protocols + * @return void + */ + public function setProtocolSupportEnumeration(array $protocols) : void + { + $this->protocolSupportEnumeration = $protocols; + } + + + /** + * Add the value to the ProtocolSupportEnumeration property. + * + * @param string $protocol + * @return void + */ + public function addProtocolSupportEnumeration(string $protocol) : void + { + $this->protocolSupportEnumeration[] = $protocol; + } + + + /** + * Collect the value of the Organization property. + * + * @return \SAML2\XML\md\Organization|null + */ + public function getOrganization() : ?Organization + { + return $this->Organization; + } + + + /** + * Set the value of the Organization property. + * + * @param \SAML2\XML\md\Organization|null $organization + * @return void + */ + public function setOrganization(Organization $organization = null) : void + { + $this->Organization = $organization; + } + + + /** + * Collect the value of the ContactPerson property. + * + * @return \SAML2\XML\md\ContactPerson[] + */ + public function getContactPerson() : array + { + return $this->ContactPerson; + } + + + /** + * Set the value of the ContactPerson property. + * + * @param array $contactPerson + * @return void + */ + public function setContactPerson(array $contactPerson) : void + { + $this->ContactPerson = $contactPerson; + } + + + /** + * Add the value to the ContactPerson property. + * + * @param \SAML2\XML\md\ContactPerson $contactPerson + * @return void + */ + public function addContactPerson(ContactPerson $contactPerson) : void + { + $this->ContactPerson[] = $contactPerson; + } + + + /** + * Collect the value of the KeyDescriptor property. + * + * @return \SAML2\XML\md\KeyDescriptor[] + */ + public function getKeyDescriptor() : array + { + return $this->KeyDescriptor; + } + + + /** + * Set the value of the KeyDescriptor property. + * + * @param array $keyDescriptor + * @return void + */ + public function setKeyDescriptor(array $keyDescriptor) : void + { + $this->KeyDescriptor = $keyDescriptor; + } + + + /** + * Add the value to the KeyDescriptor property. + * + * @param \SAML2\XML\md\KeyDescriptor $keyDescriptor + * @return void + */ + public function addKeyDescriptor(KeyDescriptor $keyDescriptor) : void + { + $this->KeyDescriptor[] = $keyDescriptor; + } + + + /** + * Add this RoleDescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this endpoint to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, $this->elementName); + $parent->appendChild($e); + + if ($this->ID !== null) { + $e->setAttribute('ID', $this->ID); + } + + if ($this->validUntil !== null) { + $e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil)); + } + + if ($this->cacheDuration !== null) { + $e->setAttribute('cacheDuration', $this->cacheDuration); + } + + $e->setAttribute('protocolSupportEnumeration', implode(' ', $this->protocolSupportEnumeration)); + + if ($this->errorURL !== null) { + $e->setAttribute('errorURL', $this->errorURL); + } + + Extensions::addList($e, $this->Extensions); + + foreach ($this->KeyDescriptor as $kd) { + $kd->toXML($e); + } + + if ($this->Organization !== null) { + $this->Organization->toXML($e); + } + + foreach ($this->ContactPerson as $cp) { + $cp->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SPSSODescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SPSSODescriptor.php new file mode 100644 index 000000000..4d27270ef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SPSSODescriptor.php @@ -0,0 +1,223 @@ +AuthnRequestsSigned = Utils::parseBoolean($xml, 'AuthnRequestsSigned', null); + $this->WantAssertionsSigned = Utils::parseBoolean($xml, 'WantAssertionsSigned', null); + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:AssertionConsumerService') as $ep) { + $this->AssertionConsumerService[] = new IndexedEndpointType($ep); + } + + /** @var \DOMElement $acs */ + foreach (Utils::xpQuery($xml, './saml_metadata:AttributeConsumingService') as $acs) { + $this->AttributeConsumingService[] = new AttributeConsumingService($acs); + } + } + + + /** + * Collect the value of the AuthnRequestsSigned-property + * + * @return bool|null + */ + public function getAuthnRequestsSigned() : ?bool + { + return $this->AuthnRequestsSigned; + } + + + /** + * Set the value of the AuthnRequestsSigned-property + * + * @param bool|null $flag + * @return void + */ + public function setAuthnRequestsSigned(bool $flag = null) : void + { + $this->AuthnRequestsSigned = $flag; + } + + + /** + * Collect the value of the WantAssertionsSigned-property + * + * @return bool|null + */ + public function wantAssertionsSigned() : ?bool + { + return $this->WantAssertionsSigned; + } + + + /** + * Set the value of the WantAssertionsSigned-property + * + * @param bool|null $flag + * @return void + */ + public function setWantAssertionsSigned(bool $flag = null) : void + { + $this->WantAssertionsSigned = $flag; + } + + + /** + * Collect the value of the AssertionConsumerService-property + * + * @return array + */ + public function getAssertionConsumerService() : array + { + return $this->AssertionConsumerService; + } + + + /** + * Set the value of the AssertionConsumerService-property + * + * @param array $acs + * @return void + */ + public function setAssertionConsumerService(array $acs) : void + { + $this->AssertionConsumerService = $acs; + } + + + /** + * Add the value to the AssertionConsumerService-property + * + * @param \SAML2\XML\md\IndexedEndpointType $acs + * @return void + */ + public function addAssertionConsumerService(IndexedEndpointType $acs) : void + { + $this->AssertionConsumerService[] = $acs; + } + + + /** + * Collect the value of the AttributeConsumingService-property + * + * @return array + */ + public function getAttributeConsumingService() : array + { + return $this->AttributeConsumingService; + } + + + /** + * Add the value to the AttributeConsumingService-property + * + * @param \SAML2\XML\md\AttributeConsumingService $acs + * @return void + */ + public function addAttributeConsumingService(AttributeConsumingService $acs) : void + { + $this->AttributeConsumingService[] = $acs; + } + + + /** + * Set the value of the AttributeConsumingService-property + * + * @param array $acs + * @return void + */ + public function setAttributeConsumingService(array $acs) : void + { + $this->AttributeConsumingService = $acs; + } + + + /** + * Add this SPSSODescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this SPSSODescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = parent::toXML($parent); + + if (is_bool($this->AuthnRequestsSigned)) { + $e->setAttribute('AuthnRequestsSigned', $this->AuthnRequestsSigned ? 'true' : 'false'); + } + + if (is_bool($this->WantAssertionsSigned)) { + $e->setAttribute('WantAssertionsSigned', $this->WantAssertionsSigned ? 'true' : 'false'); + } + + foreach ($this->AssertionConsumerService as $ep) { + $ep->toXML($e, 'md:AssertionConsumerService'); + } + + foreach ($this->AttributeConsumingService as $acs) { + $acs->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SSODescriptorType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SSODescriptorType.php new file mode 100644 index 000000000..ff179b1a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/SSODescriptorType.php @@ -0,0 +1,243 @@ +addArtifactResolutionService(new IndexedEndpointType($ep)); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:SingleLogoutService') as $ep) { + $this->addSingleLogoutService(new EndpointType($ep)); + } + + /** @var \DOMElement $ep */ + foreach (Utils::xpQuery($xml, './saml_metadata:ManageNameIDService') as $ep) { + $this->addManageNameIDService(new EndpointType($ep)); + } + + $this->setNameIDFormat(Utils::extractStrings($xml, Constants::NS_MD, 'NameIDFormat')); + } + + + /** + * Collect the value of the ArtifactResolutionService-property + * + * @return \SAML2\XML\md\IndexedEndpointType[] + */ + public function getArtifactResolutionService() : array + { + return $this->ArtifactResolutionService; + } + + + /** + * Set the value of the ArtifactResolutionService-property + * + * @param \SAML2\XML\md\IndexedEndpointType[] $artifactResolutionService + * @return void + */ + public function setArtifactResolutionService(array $artifactResolutionService) : void + { + $this->ArtifactResolutionService = $artifactResolutionService; + } + + + /** + * Add the value to the ArtifactResolutionService-property + * + * @param \SAML2\XML\md\IndexedEndpointType $artifactResolutionService + * @return void + */ + public function addArtifactResolutionService(IndexedEndpointType $artifactResolutionService) : void + { + $this->ArtifactResolutionService[] = $artifactResolutionService; + } + + + /** + * Collect the value of the SingleLogoutService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getSingleLogoutService() : array + { + return $this->SingleLogoutService; + } + + + /** + * Set the value of the SingleLogoutService-property + * + * @param \SAML2\XML\md\EndpointType[] $singleLogoutService + * @return void + */ + public function setSingleLogoutService(array $singleLogoutService) : void + { + $this->SingleLogoutService = $singleLogoutService; + } + + + /** + * Add the value to the SingleLogoutService-property + * + * @param \SAML2\XML\md\EndpointType $singleLogoutService + * @return void + */ + public function addSingleLogoutService(EndpointType $singleLogoutService) : void + { + $this->SingleLogoutService[] = $singleLogoutService; + } + + + /** + * Collect the value of the ManageNameIDService-property + * + * @return \SAML2\XML\md\EndpointType[] + */ + public function getManageNameIDService() : array + { + return $this->ManageNameIDService; + } + + + /** + * Set the value of the ManageNameIDService-property + * + * @param \SAML2\XML\md\EndpointType[] $manageNameIDService + * @return void + */ + public function setManageNameIDService(array $manageNameIDService) : void + { + $this->ManageNameIDService = $manageNameIDService; + } + + + /** + * Add the value to the ManageNameIDService-property + * + * @param \SAML2\XML\md\EndpointType $manageNameIDService + * @return void + */ + public function addManageNameIDService(EndpointType $manageNameIDService) : void + { + $this->ManageNameIDService[] = $manageNameIDService; + } + + + /** + * Collect the value of the NameIDFormat-property + * + * @return string[] + */ + public function getNameIDFormat() : array + { + return $this->NameIDFormat; + } + + + /** + * Set the value of the NameIDFormat-property + * + * @param string[] $nameIDFormat + * @return void + */ + public function setNameIDFormat(array $nameIDFormat) : void + { + $this->NameIDFormat = $nameIDFormat; + } + + + /** + * Add this SSODescriptorType to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this SSODescriptorType to. + * @return \DOMElement The generated SSODescriptor DOMElement. + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = parent::toXML($parent); + + foreach ($this->ArtifactResolutionService as $ep) { + $ep->toXML($e, 'md:ArtifactResolutionService'); + } + + foreach ($this->SingleLogoutService as $ep) { + $ep->toXML($e, 'md:SingleLogoutService'); + } + + foreach ($this->ManageNameIDService as $ep) { + $ep->toXML($e, 'md:ManageNameIDService'); + } + + Utils::addStrings($e, Constants::NS_MD, 'md:NameIDFormat', false, $this->NameIDFormat); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/UnknownRoleDescriptor.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/UnknownRoleDescriptor.php new file mode 100644 index 000000000..ccb7c2b14 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/md/UnknownRoleDescriptor.php @@ -0,0 +1,49 @@ +xml = new Chunk($xml); + } + + + /** + * Add this RoleDescriptor to an EntityDescriptor. + * + * @param \DOMElement $parent The EntityDescriptor we should append this RoleDescriptor to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + return $this->xml->toXML($parent); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdattr/EntityAttributes.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdattr/EntityAttributes.php new file mode 100644 index 000000000..2131170f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdattr/EntityAttributes.php @@ -0,0 +1,115 @@ +localName === 'Attribute') { + $this->children[] = new Attribute($node); + } else { + $this->children[] = new Chunk($node); + } + } + } + + + /** + * Collect the value of the children-property + * + * @return (\SAML2\XML\Chunk|\SAML2\XML\saml\Attribute)[] + */ + public function getChildren() : array + { + return $this->children; + } + + + /** + * Set the value of the childen-property + * + * @param array $children + * @return void + */ + public function setChildren(array $children) : void + { + $this->children = $children; + } + + + /** + * Add the value to the children-property + * + * @param \SAML2\XML\Chunk|\SAML2\XML\saml\Attribute $child + * @return void + */ + public function addChildren($child) : void + { + Assert::isInstanceOfAny($child, [Chunk::class, Attribute::class]); + $this->children[] = $child; + } + + + /** + * Convert this EntityAttributes to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(EntityAttributes::NS, 'mdattr:EntityAttributes'); + $parent->appendChild($e); + + /** @var \SAML2\XML\saml\Attribute|\SAML2\XML\Chunk $child */ + foreach ($this->children as $child) { + $child->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/Common.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/Common.php new file mode 100644 index 000000000..f80a85825 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/Common.php @@ -0,0 +1,16 @@ +URL. + * + * @var array + */ + private $UsagePolicy = []; + + + /** + * Create/parse a mdrpi:PublicationInfo element. + * + * @param \DOMElement|null $xml The XML element we should load. + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('publisher')) { + throw new \Exception('Missing required attribute "publisher" in mdrpi:PublicationInfo element.'); + } + $this->publisher = $xml->getAttribute('publisher'); + + if ($xml->hasAttribute('creationInstant')) { + $this->creationInstant = Utils::xsDateTimeToTimestamp($xml->getAttribute('creationInstant')); + } + + if ($xml->hasAttribute('publicationId')) { + $this->publicationId = $xml->getAttribute('publicationId'); + } + + $this->UsagePolicy = Utils::extractLocalizedStrings($xml, Common::NS_MDRPI, 'UsagePolicy'); + } + + + /** + * Collect the value of the publisher-property + * + * @return string + */ + public function getPublisher() : string + { + return $this->publisher; + } + + + /** + * Collect the value of the creationInstant-property + * + * @return int|null + */ + public function getCreationInstant() : ?int + { + return $this->creationInstant; + } + + + /** + * Collect the value of the publicationId-property + * + * @return string|null + */ + public function getPublicationId() : ?string + { + return $this->publicationId; + } + + + /** + * Collect the value of the UsagePolicy-property + * + * @return array + */ + public function getUsagePolicy() : array + { + return $this->UsagePolicy; + } + + + /** + * Set the value of the publisher-property + * + * @param string $publisher + * @return void + */ + public function setPublisher(string $publisher) : void + { + $this->publisher = $publisher; + } + + + /** + * Set the value of the creationInstant-property + * + * @param int|null $creationInstant + * @return void + */ + public function setCreationInstant(int $creationInstant = null) : void + { + $this->creationInstant = $creationInstant; + } + + + /** + * Set the value of the publicationId-property + * + * @param string|null $publicationId + * @return void + */ + public function setPublicationId(string $publicationId = null) : void + { + $this->publicationId = $publicationId; + } + + + /** + * Set the value of the UsagePolicy-property + * + * @param array $usagePolicy + * @return void + */ + public function setUsagePolicy(array $usagePolicy) : void + { + $this->UsagePolicy = $usagePolicy; + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->publisher, "Cannot convert PublicationInfo to XML without a publisher set."); + + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Common::NS_MDRPI, 'mdrpi:PublicationInfo'); + $parent->appendChild($e); + + $e->setAttribute('publisher', $this->publisher); + + if ($this->creationInstant !== null) { + $e->setAttribute('creationInstant', gmdate('Y-m-d\TH:i:s\Z', $this->creationInstant)); + } + + if ($this->publicationId !== null) { + $e->setAttribute('publicationId', $this->publicationId); + } + + Utils::addStrings($e, Common::NS_MDRPI, 'mdrpi:UsagePolicy', true, $this->UsagePolicy); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/RegistrationInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/RegistrationInfo.php new file mode 100644 index 000000000..ea2ee751c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdrpi/RegistrationInfo.php @@ -0,0 +1,166 @@ +URL. + * + * @var array + */ + private $RegistrationPolicy = []; + + + /** + * Create/parse a mdrpi:RegistrationInfo element. + * + * @param \DOMElement|null $xml The XML element we should load. + * @throws \Exception + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if (!$xml->hasAttribute('registrationAuthority')) { + throw new \Exception( + 'Missing required attribute "registrationAuthority" in mdrpi:RegistrationInfo element.' + ); + } + $this->registrationAuthority = $xml->getAttribute('registrationAuthority'); + + if ($xml->hasAttribute('registrationInstant')) { + $this->registrationInstant = Utils::xsDateTimeToTimestamp($xml->getAttribute('registrationInstant')); + } + + $this->RegistrationPolicy = Utils::extractLocalizedStrings($xml, Common::NS_MDRPI, 'RegistrationPolicy'); + } + + + /** + * Collect the value of the RegistrationAuthority property + * + * @return string|null + */ + public function getRegistrationAuthority() : ?string + { + return $this->registrationAuthority; + } + + + /** + * Set the value of the registrationAuthority property + * + * @param string $registrationAuthority + * @return void + */ + public function setRegistrationAuthority(string $registrationAuthority) : void + { + $this->registrationAuthority = $registrationAuthority; + } + + + /** + * Collect the value of the registrationInstant property + * + * @return int|null + */ + public function getRegistrationInstant() : ?int + { + return $this->registrationInstant; + } + + + /** + * Set the value of the registrationInstant property + * + * @param int|null $registrationInstant + * @return void + */ + public function setRegistrationInstant(int $registrationInstant = null) : void + { + $this->registrationInstant = $registrationInstant; + } + + + /** + * Collect the value of the RegistrationPolicy property + * + * @return array + */ + public function getRegistrationPolicy() : array + { + return $this->RegistrationPolicy; + } + + + /** + * Set the value of the RegistrationPolicy property + * + * @param array $registrationPolicy + * @return void + */ + public function setRegistrationPolicy(array $registrationPolicy) : void + { + $this->RegistrationPolicy = $registrationPolicy; + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + if (empty($this->registrationAuthority)) { + throw new \Exception('Missing required registration authority.'); + } + + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Common::NS_MDRPI, 'mdrpi:RegistrationInfo'); + $parent->appendChild($e); + + $e->setAttribute('registrationAuthority', $this->registrationAuthority); + + if ($this->registrationInstant !== null) { + $e->setAttribute('registrationInstant', gmdate('Y-m-d\TH:i:s\Z', $this->registrationInstant)); + } + + Utils::addStrings($e, Common::NS_MDRPI, 'mdrpi:RegistrationPolicy', true, $this->RegistrationPolicy); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Common.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Common.php new file mode 100644 index 000000000..f9b980857 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Common.php @@ -0,0 +1,17 @@ + + * @package simplesamlphp/saml2 + */ +class Common +{ + const NS = 'urn:oasis:names:tc:SAML:metadata:ui'; +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/DiscoHints.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/DiscoHints.php new file mode 100644 index 000000000..728fb53c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/DiscoHints.php @@ -0,0 +1,208 @@ +IPHint = Utils::extractStrings($xml, Common::NS, 'IPHint'); + $this->DomainHint = Utils::extractStrings($xml, Common::NS, 'DomainHint'); + $this->GeolocationHint = Utils::extractStrings($xml, Common::NS, 'GeolocationHint'); + + /** @var \DOMElement $node */ + foreach (Utils::xpQuery($xml, "./*[namespace-uri()!='".Common::NS."']") as $node) { + $this->children[] = new Chunk($node); + } + } + + + /** + * Collect the value of the IPHint-property + * + * @return string[] + */ + public function getIPHint() : array + { + return $this->IPHint; + } + + + /** + * Set the value of the IPHint-property + * + * @param string[] $hints + * @return void + */ + public function setIPHint(array $hints) : void + { + $this->IPHint = $hints; + } + + + /** + * Collect the value of the DomainHint-property + * + * @return string[] + */ + public function getDomainHint() : array + { + return $this->DomainHint; + } + + + /** + * Set the value of the DomainHint-property + * + * @param string[] $hints + * @return void + */ + public function setDomainHint(array $hints) : void + { + $this->DomainHint = $hints; + } + + + /** + * Collect the value of the GeolocationHint-property + * + * @return string[] + */ + public function getGeolocationHint() : array + { + return $this->GeolocationHint; + } + + + /** + * Set the value of the GeolocationHint-property + * + * @param string[] $hints + * @return void + */ + public function setGeolocationHint(array $hints) : void + { + $this->GeolocationHint = $hints; + } + + + /** + * Collect the value of the children-property + * + * @return \SAML2\XML\Chunk[] + */ + public function getChildren() : array + { + return $this->children; + } + + + /** + * Set the value of the childen-property + * + * @param array $children + * @return void + */ + public function setChildren(array $children) : void + { + $this->children = $children; + } + + + /** + * Add the value to the children-property + * + * @param \SAML2\XML\Chunk $child + * @return void + */ + public function addChildren(Chunk $child) : void + { + $this->children[] = $child; + } + + + /** + * Convert this DiscoHints to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement|null + */ + public function toXML(DOMElement $parent) : ?DOMElement + { + if (!empty($this->IPHint) + || !empty($this->DomainHint) + || !empty($this->GeolocationHint) + || !empty($this->children) + ) { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Common::NS, 'mdui:DiscoHints'); + $parent->appendChild($e); + + foreach ($this->getChildren() as $child) { + $child->toXML($e); + } + + Utils::addStrings($e, Common::NS, 'mdui:IPHint', false, $this->IPHint); + Utils::addStrings($e, Common::NS, 'mdui:DomainHint', false, $this->DomainHint); + Utils::addStrings($e, Common::NS, 'mdui:GeolocationHint', false, $this->GeolocationHint); + + return $e; + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Keywords.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Keywords.php new file mode 100644 index 000000000..c79c9e598 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Keywords.php @@ -0,0 +1,146 @@ +hasAttribute('xml:lang')) { + throw new \Exception('Missing lang on Keywords.'); + } + if (!strlen($xml->textContent)) { + throw new \Exception('Missing value for Keywords.'); + } + foreach (explode(' ', $xml->textContent) as $keyword) { + $this->Keywords[] = str_replace('+', ' ', $keyword); + } + $this->lang = $xml->getAttribute('xml:lang'); + } + + + /** + * Collect the value of the lang-property + * + * @return string + */ + public function getLanguage() : string + { + return $this->lang; + } + + + /** + * Set the value of the lang-property + * + * @param string $lang + * @return void + */ + public function setLanguage(string $lang) : void + { + $this->lang = $lang; + } + + + /** + * Collect the value of the Keywords-property + * + * @return string[] + */ + public function getKeywords() : array + { + return $this->Keywords; + } + + + /** + * Set the value of the Keywords-property + * + * @param string[] $keywords + * @return void + */ + public function setKeywords(array $keywords) : void + { + $this->Keywords = $keywords; + } + + + /** + * Add the value to the Keywords-property + * + * @param string $keyword + * @return void + */ + public function addKeyword(string $keyword) : void + { + $this->Keywords[] = $keyword; + } + + + /** + * Convert this Keywords to XML. + * + * @param \DOMElement $parent The element we should append this Keywords to. + * @throws \Exception + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->lang, "Cannot convert Keywords to XML without a language set."); + + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Common::NS, 'mdui:Keywords'); + $e->setAttribute('xml:lang', $this->lang); + $value = ''; + foreach ($this->Keywords as $keyword) { + if (strpos($keyword, "+") !== false) { + throw new \Exception('Keywords may not contain a "+" character.'); + } + $value .= str_replace(' ', '+', $keyword).' '; + } + $value = rtrim($value); + $e->appendChild($doc->createTextNode($value)); + $parent->appendChild($e); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Logo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Logo.php new file mode 100644 index 000000000..b680a759b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/Logo.php @@ -0,0 +1,192 @@ +hasAttribute('width')) { + throw new \Exception('Missing width of Logo.'); + } + if (!$xml->hasAttribute('height')) { + throw new \Exception('Missing height of Logo.'); + } + if (!strlen($xml->textContent)) { + throw new \Exception('Missing url value for Logo.'); + } + $this->setUrl($xml->textContent); + $this->setWidth(intval($xml->getAttribute('width'))); + $this->setHeight(intval($xml->getAttribute('height'))); + if ($xml->hasAttribute('xml:lang')) { + $this->setLanguage($xml->getAttribute('xml:lang')); + } + } + + + /** + * Collect the value of the url-property + * + * @return string + */ + public function getUrl() : string + { + return $this->url; + } + + + /** + * Set the value of the url-property + * + * @param string $url + * @return void + */ + public function setUrl(string $url) : void + { + if (!filter_var(trim($url), FILTER_VALIDATE_URL) && substr(trim($url), 0, 5) !== 'data:') { + throw new \InvalidArgumentException('mdui:Logo is not a valid URL.'); + } + $this->url = $url; + } + + + /** + * Collect the value of the lang-property + * + * @return string|null + */ + public function getLanguage() : ?string + { + return $this->lang; + } + + + /** + * Set the value of the lang-property + * + * @param string $lang + * @return void + */ + public function setLanguage(string $lang) : void + { + $this->lang = $lang; + } + + + /** + * Collect the value of the height-property + * + * @return int + */ + public function getHeight() : int + { + return $this->height; + } + + + /** + * Set the value of the height-property + * + * @param int $height + * @return void + */ + public function setHeight(int $height) : void + { + $this->height = $height; + } + + + /** + * Collect the value of the width-property + * + * @return int + */ + public function getWidth() : int + { + return $this->width; + } + + + /** + * Set the value of the width-property + * + * @param int $width + * @return void + */ + public function setWidth(int $width) : void + { + $this->width = $width; + } + + + /** + * Convert this Logo to XML. + * + * @param \DOMElement $parent The element we should append this Logo to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Common::NS, 'mdui:Logo'); + $e->appendChild($doc->createTextNode($this->url)); + $e->setAttribute('width', strval($this->width)); + $e->setAttribute('height', strval($this->height)); + if ($this->lang !== null) { + $e->setAttribute('xml:lang', $this->lang); + } + $parent->appendChild($e); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/UIInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/UIInfo.php new file mode 100644 index 000000000..4871c95b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/mdui/UIInfo.php @@ -0,0 +1,345 @@ + translation. + * + * @var array + */ + private $DisplayName = []; + + /** + * The Description, as an array of language => translation. + * + * @var array + */ + private $Description = []; + + /** + * The InformationURL, as an array of language => url. + * + * @var array + */ + private $InformationURL = []; + + /** + * The PrivacyStatementURL, as an array of language => url. + * + * @var array + */ + private $PrivacyStatementURL = []; + + /** + * The Keywords, as an array of Keywords objects + * + * @var \SAML2\XML\mdui\Keywords[] + */ + private $Keywords = []; + + /** + * The Logo, as an array of Logo objects + * + * @var \SAML2\XML\mdui\Logo[] + */ + private $Logo = []; + + + /** + * Create a UIInfo element. + * + * @param \DOMElement|null $xml The XML element we should load. + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + $this->DisplayName = Utils::extractLocalizedStrings($xml, Common::NS, 'DisplayName'); + $this->Description = Utils::extractLocalizedStrings($xml, Common::NS, 'Description'); + $this->InformationURL = Utils::extractLocalizedStrings($xml, Common::NS, 'InformationURL'); + $this->PrivacyStatementURL = Utils::extractLocalizedStrings($xml, Common::NS, 'PrivacyStatementURL'); + + /** @var \DOMElement $node */ + foreach (Utils::xpQuery($xml, './*') as $node) { + if ($node->namespaceURI === Common::NS) { + switch ($node->localName) { + case 'Keywords': + $this->Keywords[] = new Keywords($node); + break; + case 'Logo': + $this->Logo[] = new Logo($node); + break; + } + } else { + $this->children[] = new Chunk($node); + } + } + } + + + /** + * Collect the value of the Keywords-property + * + * @return \SAML2\XML\mdui\Keywords[] + */ + public function getKeywords() : array + { + return $this->Keywords; + } + + + /** + * Set the value of the Keywords-property + * + * @param \SAML2\XML\mdui\Keywords[] $keywords + * @return void + */ + public function setKeywords(array $keywords) : void + { + Assert::allIsInstanceOf($keywords, Keywords::class); + $this->Keywords = $keywords; + } + + + /** + * Add the value to the Keywords-property + * + * @param \SAML2\XML\mdui\Keywords $keyword + * @return void + */ + public function addKeyword(Keywords $keyword) : void + { + $this->Keywords[] = $keyword; + } + + + /** + * Collect the value of the DisplayName-property + * + * @return string[] + */ + public function getDisplayName() : array + { + return $this->DisplayName; + } + + + /** + * Set the value of the DisplayName-property + * + * @param array $displayName + * @return void + */ + public function setDisplayName(array $displayName) : void + { + $this->DisplayName = $displayName; + } + + + /** + * Collect the value of the Description-property + * + * @return string[] + */ + public function getDescription() : array + { + return $this->Description; + } + + + /** + * Set the value of the Description-property + * + * @param array $description + * @return void + */ + public function setDescription(array $description) : void + { + $this->Description = $description; + } + + + /** + * Collect the value of the InformationURL-property + * @return string[] + */ + public function getInformationURL() : array + { + return $this->InformationURL; + } + + + /** + * Set the value of the InformationURL-property + * + * @param array $informationURL + * @return void + */ + public function setInformationURL(array $informationURL) : void + { + $this->InformationURL = $informationURL; + } + + + /** + * Collect the value of the PrivacyStatementURL-property + * + * @return string[] + */ + public function getPrivacyStatementURL() : array + { + return $this->PrivacyStatementURL; + } + + + /** + * Set the value of the PrivacyStatementURL-property + * + * @param array $privacyStatementURL + * @return void + */ + public function setPrivacyStatementURL(array $privacyStatementURL) : void + { + $this->PrivacyStatementURL = $privacyStatementURL; + } + + + /** + * Collect the value of the Logo-property + * + * @return \SAML2\XML\mdui\Logo[] + */ + public function getLogo() : array + { + return $this->Logo; + } + + + /** + * Set the value of the Logo-property + * + * @param \SAML2\XML\mdui\Logo[] $logo + * @return void + */ + public function setLogo(array $logo) : void + { + $this->Logo = $logo; + } + + + /** + * Add the value to the Logo-property + * + * @param \SAML2\XML\mdui\Logo $logo + * @return void + */ + public function addLogo(Logo $logo) : void + { + $this->Logo[] = $logo; + } + + + /** + * Collect the value of the children-property + * + * @return \SAML2\XML\Chunk[] + */ + public function getChildren() : array + { + return $this->children; + } + + + /** + * Set the value of the childen-property + * + * @param array $children + * @return void + */ + public function setChildren(array $children) : void + { + $this->children = $children; + } + + + /** + * Add the value to the children-property + * + * @param \SAML2\XML\Chunk $child + * @return void + */ + public function addChildren(Chunk $child) : void + { + $this->children[] = $child; + } + + + /** + * Convert this UIInfo to XML. + * + * @param \DOMElement $parent The element we should append to. + * @return \DOMElement|null + */ + public function toXML(DOMElement $parent) : ?DOMElement + { + $e = null; + if (!empty($this->DisplayName) + || !empty($this->Description) + || !empty($this->InformationURL) + || !empty($this->PrivacyStatementURL) + || !empty($this->Keywords) + || !empty($this->Logo) + || !empty($this->children) + ) { + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Common::NS, 'mdui:UIInfo'); + $parent->appendChild($e); + + Utils::addStrings($e, Common::NS, 'mdui:DisplayName', true, $this->DisplayName); + Utils::addStrings($e, Common::NS, 'mdui:Description', true, $this->Description); + Utils::addStrings($e, Common::NS, 'mdui:InformationURL', true, $this->InformationURL); + Utils::addStrings($e, Common::NS, 'mdui:PrivacyStatementURL', true, $this->PrivacyStatementURL); + + foreach ($this->Keywords as $child) { + $child->toXML($e); + } + + foreach ($this->Logo as $child) { + $child->toXML($e); + } + + foreach ($this->children as $child) { + $child->toXML($e); + } + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Attribute.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Attribute.php new file mode 100644 index 000000000..ec86fab77 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Attribute.php @@ -0,0 +1,230 @@ +hasAttribute('Name')) { + throw new \Exception('Missing Name on Attribute.'); + } + $this->setName($xml->getAttribute('Name')); + + if ($xml->hasAttribute('NameFormat')) { + $this->setNameFormat($xml->getAttribute('NameFormat')); + } + + if ($xml->hasAttribute('FriendlyName')) { + $this->setFriendlyName($xml->getAttribute('FriendlyName')); + } + + foreach (Utils::xpQuery($xml, './saml_assertion:AttributeValue') as $av) { + $this->addAttributeValue(new AttributeValue($av)); + } + } + + + /** + * Collect the value of the Name-property + * + * @return string|null + */ + public function getName() : ?string + { + return $this->Name; + } + + + /** + * Set the value of the Name-property + * + * @param string $name + * @return void + */ + public function setName(string $name) : void + { + $this->Name = $name; + } + + + /** + * Collect the value of the NameFormat-property + * + * @return string|null + */ + public function getNameFormat() : ?string + { + return $this->NameFormat; + } + + + /** + * Set the value of the NameFormat-property + * + * @param string|null $nameFormat + * @return void + */ + public function setNameFormat(string $nameFormat = null) : void + { + $this->NameFormat = $nameFormat; + } + + + /** + * Collect the value of the FriendlyName-property + * + * @return string|null + */ + public function getFriendlyName() : ?string + { + return $this->FriendlyName; + } + + + /** + * Set the value of the FriendlyName-property + * + * @param string|null $friendlyName + * @return void + */ + public function setFriendlyName(string $friendlyName = null) : void + { + $this->FriendlyName = $friendlyName; + } + + + /** + * Collect the value of the AttributeValue-property + * + * @return \SAML2\XML\saml\AttributeValue[] + */ + public function getAttributeValue() : array + { + return $this->AttributeValue; + } + + + /** + * Set the value of the AttributeValue-property + * + * @param array $attributeValue + * @return void + */ + public function setAttributeValue(array $attributeValue) : void + { + $this->AttributeValue = $attributeValue; + } + + + /** + * Add the value to the AttributeValue-property + * + * @param \SAML2\XML\saml\AttributeValue $attributeValue + * @return void + */ + public function addAttributeValue(AttributeValue $attributeValue) : void + { + $this->AttributeValue[] = $attributeValue; + } + + + /** + * Internal implementation of toXML. + * This function allows RequestedAttribute to specify the element name and namespace. + * + * @param \DOMElement $parent The element we should append this Attribute to. + * @param string $namespace The namespace the element should be created in. + * @param string $name The name of the element. + * @return \DOMElement + */ + protected function toXMLInternal(DOMElement $parent, string $namespace, string $name) : DOMElement + { + $e = $parent->ownerDocument->createElementNS($namespace, $name); + $parent->appendChild($e); + + if (empty($this->Name)) { + throw new \Exception('Cannot convert Attribute to XML with no Name set.'); + } + $e->setAttribute('Name', $this->Name); + + if ($this->NameFormat !== null) { + $e->setAttribute('NameFormat', $this->NameFormat); + } + + if ($this->FriendlyName !== null) { + $e->setAttribute('FriendlyName', $this->FriendlyName); + } + + foreach ($this->AttributeValue as $av) { + $av->toXML($e); + } + + return $e; + } + + + /** + * Convert this Attribute to XML. + * + * @param \DOMElement $parent The element we should append this Attribute to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : \DOMElement + { + return $this->toXMLInternal($parent, Constants::NS_SAML, 'saml:Attribute'); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/AttributeValue.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/AttributeValue.php new file mode 100644 index 000000000..55c1c5b1e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/AttributeValue.php @@ -0,0 +1,188 @@ +element = $doc->createElementNS(Constants::NS_SAML, 'saml:AttributeValue'); + $this->element->setAttributeNS(Constants::NS_XSI, 'xsi:type', 'xs:string'); + $this->element->appendChild($doc->createTextNode($value)); + + /* Make sure that the xs-namespace is available in the AttributeValue (for xs:string). */ + $this->element->setAttributeNS(Constants::NS_XS, 'xs:tmp', 'tmp'); + $this->element->removeAttributeNS(Constants::NS_XS, 'tmp'); + return; + } + + $doc = DOMDocumentFactory::create(); + if ($value->namespaceURI === Constants::NS_SAML && $value->localName === 'AttributeValue') { + $doc->appendChild($doc->importNode($value, true)); + $this->element = $doc->documentElement; + return; + } + + $this->element = $doc->createElementNS(Constants::NS_SAML, 'saml:AttributeValue'); + Utils::copyElement($value, $this->element); + } + + + /** + * Collect the value of the element-property + * + * @return \DOMElement + */ + public function getElement() : DOMElement + { + return $this->element; + } + + + /** + * Set the value of the element-property + * + * @param \DOMElement $element + * @return void + */ + public function setElement(DOMElement $element) : void + { + $this->element = $element; + } + + + /** + * Append this attribute value to an element. + * + * @param \DOMElement $parent The element we should append this attribute value to. + * @return \DOMElement The generated AttributeValue element. + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::same($this->getElement()->namespaceURI, Constants::NS_SAML); + Assert::same($this->getElement()->localName, "AttributeValue"); + + return $parent->appendChild($parent->ownerDocument->importNode($this->element, true)); + } + + + /** + * Returns a plain text content of the attribute value. + * + * @return string + */ + public function getString() : string + { + return $this->element->textContent; + } + + + /** + * Convert this attribute value to a string. + * + * If this element contains XML data, that data will be encoded as a string and returned. + * + * @return string This attribute value. + */ + public function __toString() : string + { + $doc = $this->element->ownerDocument; + + $ret = ''; + foreach ($this->element->childNodes as $c) { + $ret .= $doc->saveXML($c); + } + + return $ret; + } + + + /** + * Serialize this AttributeValue. + * + * @return string The AttributeValue serialized. + */ + public function serialize() : string + { + return serialize($this->element->ownerDocument->saveXML($this->element)); + } + + + /** + * Un-serialize this AttributeValue. + * + * @param string $serialized The serialized AttributeValue. + * @return void + * + * Type hint not possible due to upstream method signature + */ + public function unserialize($serialized) : void + { + $element = DOMDocumentFactory::fromString(unserialize($serialized)); + $this->setElement($element->documentElement); + } + + + + /** + * Serialize this XML chunk. + * + * This method will be invoked by any calls to serialize(). + * + * @return array The serialized representation of this XML object. + */ + public function __serialize(): array + { + return [serialize($this->element->ownerDocument->saveXML($this->element))]; + } + + + /** + * Unserialize an XML object and load it.. + * + * This method will be invoked by any calls to unserialize(), allowing us to restore any data that might not + * be serializable in its original form (e.g.: DOM objects). + * + * @param array $vars The XML object that we want to restore. + */ + public function __unserialize(array $serialized): void + { + $element = DOMDocumentFactory::fromString(unserialize(array_pop($serialized))); + $this->setElement($element->documentElement); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/BaseIDType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/BaseIDType.php new file mode 100644 index 000000000..aa54e2793 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/BaseIDType.php @@ -0,0 +1,81 @@ + + * @package simplesamlphp/saml2 + */ + +namespace SAML2\XML\saml; + +use DOMElement; +use SAML2\Constants; +use SAML2\DOMDocumentFactory; + +abstract class BaseIDType +{ + use IDNameQualifiersTrait; + + + /** + * The name for this BaseID. + * + * Override in classes extending this class to get the desired name. + * + * @var string + */ + protected $nodeName; + + + /** + * Initialize a saml:BaseID, either from scratch or from an existing \DOMElement. + * + * @param \DOMElement|null $xml The XML element we should load, if any. + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if ($xml->hasAttribute('NameQualifier')) { + $this->NameQualifier = $xml->getAttribute('NameQualifier'); + } + + if ($xml->hasAttribute('SPNameQualifier')) { + $this->SPNameQualifier = $xml->getAttribute('SPNameQualifier'); + } + } + + + /** + * Convert this BaseID to XML. + * + * @param \DOMElement $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this BaseID. + */ + public function toXML(DOMElement $parent = null) : DOMElement + { + if ($parent === null) { + $parent = DOMDocumentFactory::create(); + $doc = $parent; + } else { + $doc = $parent->ownerDocument; + } + $element = $doc->createElementNS(Constants::NS_SAML, $this->nodeName); + $parent->appendChild($element); + + if ($this->NameQualifier !== null) { + $element->setAttribute('NameQualifier', $this->getNameQualifier()); + } + + if ($this->SPNameQualifier !== null) { + $element->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + } + + return $element; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/IDNameQualifiersTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/IDNameQualifiersTrait.php new file mode 100644 index 000000000..d3ac25e67 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/IDNameQualifiersTrait.php @@ -0,0 +1,80 @@ +NameQualifier; + } + + + /** + * Set the value of the NameQualifier-property + * + * @param string|null $nameQualifier + * @return void + */ + public function setNameQualifier(string $nameQualifier = null) : void + { + $this->NameQualifier = $nameQualifier; + } + + + /** + * Collect the value of the SPNameQualifier-property + * + * @return string|null + */ + public function getSPNameQualifier(): ?string + { + return $this->SPNameQualifier; + } + + + /** + * Set the value of the SPNameQualifier-property + * + * @param string|null $spNameQualifier + * @return void + */ + public function setSPNameQualifier(string $spNameQualifier = null) : void + { + $this->SPNameQualifier = $spNameQualifier; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Issuer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Issuer.php new file mode 100644 index 000000000..f37f11611 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/Issuer.php @@ -0,0 +1,135 @@ + + * @package simplesamlphp/saml2 + */ +class Issuer extends NameIDType +{ + + /** + * @var string + */ + protected $nodeName = 'saml:Issuer'; + + /** + * if $this->SAML2IssuerShowAll is set false + * From saml-core-2.0-os 8.3.6, when the entity Format is used: "The NameQualifier, SPNameQualifier, and + * SPProvidedID attributes MUST be omitted." + * + * if $this->SAML2IssuerShowAll is set true + * when the entity Format is used: "The NameQualifier, SPNameQualifier, and SPProvidedID attributes are not omitted" + * @see saml-core-2.0-os 8.3.6 + * + * @var boolean + */ + private $Saml2IssuerShowAll = false; //setting true breaks saml-core-2.0-os 8.3.6 + + + /** + * Initialize a saml:NameIDType, either from scratch or from an existing \DOMElement. + * + * @param \DOMElement|null $xml The XML element we should load, if any. + */ + public function __construct(DOMElement $xml = null) + { + /** + * The format of this NameIDType. + * + * Defaults to urn:oasis:names:tc:SAML:2.0:nameid-format:entity: + * + * Indicates that the content of the element is the identifier of an entity that provides SAML-based services + * (such as a SAML authority, requester, or responder) or is a participant in SAML profiles (such as a service + * provider supporting the browser SSO profile). Such an identifier can be used in the element to + * identify the issuer of a SAML request, response, or assertion, or within the element to make + * assertions about system entities that can issue SAML requests, responses, and assertions. It can also be + * used in other elements and attributes whose purpose is to identify a system entity in various protocol + * exchanges. + * + * The syntax of such an identifier is a URI of not more than 1024 characters in length. It is RECOMMENDED that + * a system entity use a URL containing its own domain name to identify itself. + * + * @see saml-core-2.0-os + * + * @var string + */ + $this->setFormat(Constants::NAMEID_ENTITY); + + parent::__construct($xml); + } + + + /** + * Collect the value of the Saml2IssuerShowAll-property + * + * @return bool + */ + public function isSaml2IssuerShowAll() : bool + { + return $this->Saml2IssuerShowAll; + } + + + /** + * Set the value of the Saml2IssuerShowAll-property + * + * @param bool $saml2IssuerShowAll + * @return void + */ + public function setSaml2IssuerShowAll(bool $saml2IssuerShowAll) : void + { + $this->Saml2IssuerShowAll = $saml2IssuerShowAll; + } + + + /** + * Convert this Issuer to XML. + * + * @param \DOMElement|null $parent The element we should append to. + * @return \DOMElement The current Issuer object converted into a \DOMElement. + */ + public function toXML(DOMElement $parent = null) : DOMElement + { + if (($this->Saml2IssuerShowAll && ($this->Format === Constants::NAMEID_ENTITY)) + || ($this->Format !== Constants::NAMEID_ENTITY) + ) { + return parent::toXML($parent); + } + + /* + * if $this->Saml2IssuerShowAll is set false + * From saml-core-2.0-os 8.3.6, when the entity Format is used: "The NameQualifier, SPNameQualifier, and + * SPProvidedID attributes MUST be omitted." + * if $this->isSaml2IssuerShowAll() is set true when the entity Format is used: "The NameQualifier, + * SPNameQualifier, and SPProvidedID attributes are not omitted." + */ + + if ($parent === null) { + $parent = DOMDocumentFactory::create(); + $doc = $parent; + } else { + $doc = $parent->ownerDocument; + } + $element = $doc->createElementNS(Constants::NS_SAML, 'saml:Issuer'); + $parent->appendChild($element); + + if (empty($this->value)) { + throw new \Exception("Cannot convert Issuer to XML with no value."); + } + $value = $element->ownerDocument->createTextNode($this->value); + $element->appendChild($value); + + return $element; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameID.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameID.php new file mode 100644 index 000000000..eb2679541 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameID.php @@ -0,0 +1,22 @@ + + * @package SimpleSAMLphp + */ +class NameID extends NameIDType +{ + + /** + * Set the name of this XML element to "saml:NameID" + * + * @var string + */ + protected $nodeName = 'saml:NameID'; +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameIDType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameIDType.php new file mode 100644 index 000000000..602d43b65 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/NameIDType.php @@ -0,0 +1,270 @@ + + * @package simplesamlphp/saml2 + */ + +declare(strict_types=1); + +namespace SAML2\XML\saml; + +use DOMElement; +use SAML2\Constants; +use SAML2\DOMDocumentFactory; +use Serializable; + +abstract class NameIDType implements Serializable +{ + use IDNameQualifiersTrait; + + + /** + * A URI reference representing the classification of string-based identifier information. See Section 8.3 for the + * SAML-defined URI references that MAY be used as the value of the Format attribute and their associated + * descriptions and processing rules. Unless otherwise specified by an element based on this type, if no Format + * value is provided, then the value urn:oasis:names:tc:SAML:1.0:nameid-format:unspecified (see Section 8.3.1) is in + * effect. + * + * When a Format value other than one specified in Section 8.3 is used, the content of an element of this type is to + * be interpreted according to the definition of that format as provided outside of this specification. If not + * otherwise indicated by the definition of the format, issues of anonymity, pseudonymity, and the persistence of + * the identifier with respect to the asserting and relying parties are implementation-specific. + * + * @var string|null + * + * @see saml-core-2.0-os + */ + protected $Format = null; + + /** + * A name identifier established by a service provider or affiliation of providers for the entity, if different from + * the primary name identifier given in the content of the element. This attribute provides a means of integrating + * the use of SAML with existing identifiers already in use by a service provider. For example, an existing + * identifier can be "attached" to the entity using the Name Identifier Management protocol defined in Section 3.6. + * + * @var string|null + * + * @see saml-core-2.0-os + */ + protected $SPProvidedID = null; + + /** + * The NameIDType complex type is used when an element serves to represent an entity by a string-valued name. + * + * @var string + */ + protected $value = ''; + + + /** + * Initialize a saml:NameIDType, either from scratch or from an existing \DOMElement. + * + * @param \DOMElement|null $xml The XML element we should load, if any. + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if ($xml->hasAttribute('NameQualifier')) { + $this->NameQualifier = $xml->getAttribute('NameQualifier'); + } + + if ($xml->hasAttribute('SPNameQualifier')) { + $this->SPNameQualifier = $xml->getAttribute('SPNameQualifier'); + } + + if ($xml->hasAttribute('Format')) { + $this->Format = $xml->getAttribute('Format'); + } + + if ($xml->hasAttribute('SPProvidedID')) { + $this->SPProvidedID = $xml->getAttribute('SPProvidedID'); + } + + $this->value = trim($xml->textContent); + } + + + /** + * Collect the value of the Format-property + * + * @return string|null + */ + public function getFormat() : ?string + { + return $this->Format; + } + + + /** + * Set the value of the Format-property + * + * @param string|null $format + * @return void + */ + public function setFormat(string $format = null) : void + { + $this->Format = $format; + } + + + /** + * Collect the value of the value-property + * + * @return string + */ + public function getValue() : string + { + return $this->value; + } + + + /** + * Set the value of the value-property + * @param string $value + * + * @return void + */ + public function setValue(string $value) : void + { + $this->value = $value; + } + + + /** + * Collect the value of the SPProvidedID-property + * + * @return string|null + */ + public function getSPProvidedID() : ?string + { + return $this->SPProvidedID; + } + + + /** + * Set the value of the SPProvidedID-property + * + * @param string|null $spProvidedID + * @return void + */ + public function setSPProvidedID(string $spProvidedID = null) : void + { + $this->SPProvidedID = $spProvidedID; + } + + + /** + * Convert this NameIDType to XML. + * + * @param \DOMElement $parent The element we are converting to XML. + * @return \DOMElement The XML element after adding the data corresponding to this NameIDType. + */ + public function toXML(DOMElement $parent = null) : DOMElement + { + if ($parent === null) { + $parent = DOMDocumentFactory::create(); + $doc = $parent; + } else { + $doc = $parent->ownerDocument; + } + $element = $doc->createElementNS(Constants::NS_SAML, $this->nodeName); + $parent->appendChild($element); + + if ($this->NameQualifier !== null) { + $element->setAttribute('NameQualifier', $this->getNameQualifier()); + } + + if ($this->SPNameQualifier !== null) { + $element->setAttribute('SPNameQualifier', $this->getSPNameQualifier()); + } + + if ($this->Format !== null) { + $element->setAttribute('Format', $this->Format); + } + + if ($this->SPProvidedID !== null) { + $element->setAttribute('SPProvidedID', $this->SPProvidedID); + } + + $value = $element->ownerDocument->createTextNode($this->value); + $element->appendChild($value); + + return $element; + } + + + /** + * Serialize this NameID. + * + * @return string The NameID serialized. + */ + public function serialize() : string + { + return serialize([ + 'NameQualifier' => $this->NameQualifier, + 'SPNameQualifier' => $this->SPNameQualifier, + 'nodeName' => $this->nodeName, + 'Format' => $this->Format, + 'SPProvidedID' => $this->SPProvidedID, + 'value' => $this->value + ]); + } + + + /** + * Un-serialize this NameID. + * + * @param string $serialized The serialized NameID. + * @return void + * + * Type hint not possible due to upstream method signature + */ + public function unserialize($serialized) : void + { + $unserialized = unserialize($serialized); + foreach ($unserialized as $k => $v) { + $this->$k = $v; + } + } + + + public function __serialize(): array + { + return [ + 'NameQualifier' => $this->getNameQualifier(), + 'SPNameQualifier' => $this->getSPNameQualifier(), + 'nodeName' => $this->nodeName, + 'Format' => $this->Format, + 'SPProvidedID' => $this->SPProvidedID, + 'value' => $this->value + ]; + } + + + public function __unserialize($serialized): void + { + foreach ($serialized as $k => $v) { + $this->$k = $v; + } + } + + + /** + * Get a string representation of this BaseIDType object. + * + * @return string The resulting XML, as a string. + */ + public function __toString() + { + $doc = DOMDocumentFactory::create(); + $root = $doc->createElementNS(Constants::NS_SAML, 'root'); + $ele = $this->toXML($root); + + return $doc->saveXML($ele); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmation.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmation.php new file mode 100644 index 000000000..f933ece1e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmation.php @@ -0,0 +1,171 @@ +hasAttribute('Method')) { + throw new \Exception('SubjectConfirmation element without Method attribute.'); + } + $this->Method = $xml->getAttribute('Method'); + + /** @var \DOMElement[] $nid */ + $nid = Utils::xpQuery($xml, './saml_assertion:NameID'); + if (count($nid) > 1) { + throw new \Exception('More than one NameID in a SubjectConfirmation element.'); + } elseif (!empty($nid)) { + $this->NameID = new NameID($nid[0]); + } + + /** @var \DOMElement[] $scd */ + $scd = Utils::xpQuery($xml, './saml_assertion:SubjectConfirmationData'); + if (count($scd) > 1) { + throw new \Exception('More than one SubjectConfirmationData child in a SubjectConfirmation element.'); + } elseif (!empty($scd)) { + $this->SubjectConfirmationData = new SubjectConfirmationData($scd[0]); + } + } + + + /** + * Collect the value of the Method-property + * + * @return string|null + */ + public function getMethod() : ?string + { + return $this->Method; + } + + + /** + * Set the value of the Method-property + * + * @param string $method + * @return void + */ + public function setMethod(string $method) : void + { + $this->Method = $method; + } + + + /** + * Collect the value of the NameID-property + * + * @return \SAML2\XML\saml\NameID|null + */ + public function getNameID() : ?NameID + { + return $this->NameID; + } + + + /** + * Set the value of the NameID-property + * + * @param \SAML2\XML\saml\NameID $nameId + * @return void + */ + public function setNameID(NameID $nameId = null) : void + { + $this->NameID = $nameId; + } + + + /** + * Collect the value of the SubjectConfirmationData-property + * + * @return \SAML2\XML\saml\SubjectConfirmationData|null + */ + public function getSubjectConfirmationData() : ?SubjectConfirmationData + { + return $this->SubjectConfirmationData; + } + + + /** + * Set the value of the SubjectConfirmationData-property + * + * @param \SAML2\XML\saml\SubjectConfirmationData|null $subjectConfirmationData + * @return void + */ + public function setSubjectConfirmationData(SubjectConfirmationData $subjectConfirmationData = null) : void + { + $this->SubjectConfirmationData = $subjectConfirmationData; + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement $parent The parent element we should append this element to. + * @return \DOMElement This element, as XML. + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notNull($this->Method, "Cannot convert SubjectConfirmation to XML without a Method set."); + + $e = $parent->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:SubjectConfirmation'); + $parent->appendChild($e); + + /** @psalm-suppress PossiblyNullArgument */ + $e->setAttribute('Method', $this->Method); + + if ($this->NameID !== null) { + $this->NameID->toXML($e); + } + if ($this->SubjectConfirmationData !== null) { + $this->SubjectConfirmationData->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmationData.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmationData.php new file mode 100644 index 000000000..a37dc9c4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/saml/SubjectConfirmationData.php @@ -0,0 +1,302 @@ +NotBefore; + } + + + /** + * Set the value of the NotBefore-property + * + * @param int|null $notBefore + * @return void + */ + public function setNotBefore(int $notBefore = null) : void + { + $this->NotBefore = $notBefore; + } + + + /** + * Collect the value of the NotOnOrAfter-property + * + * @return int|null + */ + public function getNotOnOrAfter() : ?int + { + return $this->NotOnOrAfter; + } + + + /** + * Set the value of the NotOnOrAfter-property + * + * @param int|null $notOnOrAfter + * @return void + */ + public function setNotOnOrAfter(int $notOnOrAfter = null) : void + { + $this->NotOnOrAfter = $notOnOrAfter; + } + + + /** + * Collect the value of the Recipient-property + * + * @return string|null + */ + public function getRecipient() : ?string + { + return $this->Recipient; + } + + + /** + * Set the value of the Recipient-property + * + * @param string|null $recipient + * @return void + */ + public function setRecipient(string $recipient = null) : void + { + $this->Recipient = $recipient; + } + + + /** + * Collect the value of the InResponseTo-property + * + * @return string|null + */ + public function getInResponseTo() : ?string + { + return $this->InResponseTo; + } + + + /** + * Set the value of the InResponseTo-property + * + * @param string|null $inResponseTo + * @return void + */ + public function setInResponseTo(string $inResponseTo = null) : void + { + $this->InResponseTo = $inResponseTo; + } + + + /** + * Collect the value of the Address-property + * + * @return string|null + */ + public function getAddress() : ?string + { + return $this->Address; + } + + + /** + * Set the value of the Address-property + * + * @param string|null $address + * @return void + */ + public function setAddress(string $address = null) : void + { + if (!is_null($address) && !filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { + Utils::getContainer()->getLogger()->warning(sprintf('Provided argument (%s) is not a valid IP address.', $address)); + } + $this->Address = $address; + } + + + /** + * Collect the value of the info-property + * + * @return (\SAML2\XML\ds\KeyInfo|\SAML2\XML\Chunk)[] + */ + public function getInfo() : array + { + return $this->info; + } + + + /** + * Set the value of the info-property + * + * @param (\SAML2\XML\ds\KeyInfo|\SAML2\XML\Chunk)[] $info + * @return void + */ + public function setInfo(array $info) : void + { + $this->info = $info; + } + + + /** + * Add the value to the info-property + * + * @param \SAML2\XML\Chunk|\SAML2\XML\ds\KeyInfo $info + * @return void + */ + public function addInfo($info) : void + { + Assert::isInstanceOfAny($info, [Chunk::class, KeyInfo::class]); + $this->info[] = $info; + } + + + /** + * Initialize (and parse) a SubjectConfirmationData element. + * + * @param \DOMElement|null $xml The XML element we should load. + */ + public function __construct(DOMElement $xml = null) + { + if ($xml === null) { + return; + } + + if ($xml->hasAttribute('NotBefore')) { + $this->setNotBefore(Utils::xsDateTimeToTimestamp($xml->getAttribute('NotBefore'))); + } + if ($xml->hasAttribute('NotOnOrAfter')) { + $this->setNotOnOrAfter(Utils::xsDateTimeToTimestamp($xml->getAttribute('NotOnOrAfter'))); + } + if ($xml->hasAttribute('Recipient')) { + $this->setRecipient($xml->getAttribute('Recipient')); + } + if ($xml->hasAttribute('InResponseTo')) { + $this->setInResponseTo($xml->getAttribute('InResponseTo')); + } + if ($xml->hasAttribute('Address')) { + $this->setAddress($xml->getAttribute('Address')); + } + foreach ($xml->childNodes as $n) { + if (!($n instanceof DOMElement)) { + continue; + } + if ($n->namespaceURI !== XMLSecurityDSig::XMLDSIGNS) { + $this->addInfo(new Chunk($n)); + continue; + } + switch ($n->localName) { + case 'KeyInfo': + $this->addInfo(new KeyInfo($n)); + break; + default: + $this->addInfo(new Chunk($n)); + break; + } + } + } + + + /** + * Convert this element to XML. + * + * @param \DOMElement $parent The parent element we should append this element to. + * @return \DOMElement This element, as XML. + */ + public function toXML(DOMElement $parent) : DOMElement + { + $e = $parent->ownerDocument->createElementNS(Constants::NS_SAML, 'saml:SubjectConfirmationData'); + $parent->appendChild($e); + + if ($this->NotBefore !== null) { + $e->setAttribute('NotBefore', gmdate('Y-m-d\TH:i:s\Z', $this->NotBefore)); + } + if ($this->NotOnOrAfter !== null) { + $e->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->NotOnOrAfter)); + } + if ($this->Recipient !== null) { + $e->setAttribute('Recipient', $this->Recipient); + } + if ($this->InResponseTo !== null) { + $e->setAttribute('InResponseTo', $this->InResponseTo); + } + if ($this->Address !== null) { + $e->setAttribute('Address', $this->Address); + } + /** @var \SAML2\XML\ds\KeyInfo|\SAML2\XML\Chunk $n */ + foreach ($this->getInfo() as $n) { + $n->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/samlp/Extensions.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/samlp/Extensions.php new file mode 100644 index 000000000..0f9904da6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/samlp/Extensions.php @@ -0,0 +1,58 @@ +ownerDocument->createElementNS(Constants::NS_SAMLP, 'samlp:Extensions'); + $parent->appendChild($extElement); + + foreach ($extensions as $ext) { + $ext->toXML($extElement); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/shibmd/Scope.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/shibmd/Scope.php new file mode 100644 index 000000000..b1dab87d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/SAML2/XML/shibmd/Scope.php @@ -0,0 +1,127 @@ +scope = $xml->textContent; + $this->regexp = Utils::parseBoolean($xml, 'regexp', false); + } + + + /** + * Collect the value of the scope-property + * + * @return string + */ + public function getScope() : string + { + return $this->scope; + } + + + /** + * Set the value of the scope-property + * + * @param string $scope + * @return void + */ + public function setScope(string $scope) : void + { + $this->scope = $scope; + } + + + /** + * Collect the value of the regexp-property + * + * @return bool + */ + public function isRegexpScope() : bool + { + return $this->regexp; + } + + + /** + * Set the value of the regexp-property + * + * @param bool $regexp + * @return void + */ + public function setIsRegexpScope(bool $regexp) : void + { + $this->regexp = $regexp; + } + + + /** + * Convert this Scope to XML. + * + * @param \DOMElement $parent The element we should append this Scope to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent) : DOMElement + { + Assert::notEmpty($this->scope); + + $doc = $parent->ownerDocument; + + $e = $doc->createElementNS(Scope::NS, 'shibmd:Scope'); + $parent->appendChild($e); + + $e->appendChild($doc->createTextNode($this->scope)); + + if ($this->regexp === true) { + $e->setAttribute('regexp', 'true'); + } else { + $e->setAttribute('regexp', 'false'); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/_autoload.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/_autoload.php new file mode 100644 index 000000000..e002b6745 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/src/_autoload.php @@ -0,0 +1,37 @@ + + * @package SimpleSAMLphp + */ + +/** + * Autoload function that looks for classes migrated to PSR-4. + * + * @param string $className Name of the class. + * @return void + */ +function SAML2_autoload(string $className) : void +{ + // handle classes that have been renamed + $renamed = [ + 'SAML2_Const' => 'SAML2_Constants', + ]; + $oldName = $className; + if (array_key_exists($className, $renamed)) { + $className = $renamed[$className]; + } + + $file = dirname(__FILE__).'/'.str_replace('_', '/', $className).'.php'; + if (file_exists($file)) { + require_once($file); + $newName = '\\'.str_replace('_', '\\', $className); + class_alias($newName, $oldName); + } +} + +spl_autoload_register('SAML2_autoload'); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/autoload.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/autoload.php new file mode 100644 index 000000000..10bf4fcc9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/autoload.php @@ -0,0 +1,12 @@ + + + + + dM5kF0HTkW9fnJOS77yNgTAwBj4=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 + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/expired-metadata.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/expired-metadata.xml new file mode 100644 index 000000000..9fea64a11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/expired-metadata.xml @@ -0,0 +1,23 @@ + + + + + + + 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 + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/valid-metadata-selfsigned.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/valid-metadata-selfsigned.xml new file mode 100644 index 000000000..67ed45b80 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2-legacy/tests/resources/xml/metadata/valid-metadata-selfsigned.xml @@ -0,0 +1,27 @@ + + + + + dM5kF0HTkW9fnJOS77yNgTAwBj4=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 + + + + + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/composer.json b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/composer.json index 872baa73e..6b5567f21 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/composer.json +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/composer.json @@ -25,6 +25,9 @@ "sebastian/phpcpd": "~4.1 || ^5.0 || ^6.0", "squizlabs/php_codesniffer": "~3.5" }, + "conflict": { + "robrichards/xmlseclibs": "3.1.2" + }, "autoload": { "psr-4": { "SAML2\\": "src/SAML2" diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/DOMDocumentFactory.php b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/DOMDocumentFactory.php index 811ae10b6..f69a49e4b 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/DOMDocumentFactory.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/saml2/src/SAML2/DOMDocumentFactory.php @@ -30,15 +30,27 @@ public static function fromString(string $xml) : DOMDocument { if (trim($xml) === '') { throw InvalidArgumentException::invalidType('non-empty string', $xml); + } elseif (preg_match('/<(\s*)!(\s*)DOCTYPE/', $xml)) { + throw new RuntimeException( + 'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body' + ); } elseif (PHP_VERSION_ID < 80000) { $entityLoader = libxml_disable_entity_loader(true); + } else { + libxml_set_external_entity_loader(null); } $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); $domDocument = self::create(); - $options = LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_NONET | LIBXML_PARSEHUGE; + $options = LIBXML_NONET | LIBXML_PARSEHUGE; + + /* LIBXML_NO_XXE available from PHP 8.4 */ + if (defined('LIBXML_NO_XXE')) { + $options |= LIBXML_NO_XXE; + } + if (defined('LIBXML_COMPACT')) { $options |= LIBXML_COMPACT; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/LICENSE b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/LICENSE new file mode 100644 index 000000000..a345e48d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/LICENSE @@ -0,0 +1,459 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/README.md b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/README.md new file mode 100644 index 000000000..0b15ffe27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/README.md @@ -0,0 +1,2 @@ +# simplesamlphp-test-framework +Test framework for SimpleSAMLphp and related repositories diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/composer.json b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/composer.json new file mode 100644 index 000000000..94153716b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/composer.json @@ -0,0 +1,50 @@ +{ + "name": "simplesamlphp/simplesamlphp-test-framework", + "description": "Test framework for SimpleSAMLphp and related repositories ", + "type": "project", + "keywords": ["test-framework"], + "license": "LGPL-2.1-or-later", + "authors": [ + { + "name": "Tim van Dijen", + "email": "tvdijen@gmail.com" + } + ], + "autoload": { + "psr-4": { + "SimpleSAML\\TestUtils\\": "lib/" + } + }, + "autoload-dev": { + "psr-4": { + "SimpleSAML\\Test\\TestUtils\\": "tests/src/" + } + }, + "require": { + "php": "^8.1", + "ext-curl": "*", + + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1", + "phpunit/phpunit": "^10.0 || ^11.0", + "psr/log": "^2.0 || ^3.0", + "slevomat/coding-standard": "^8.15", + "symfony/phpunit-bridge": "^6.4 || ^7.0" + }, + "require-dev": { + "simplesamlphp/simplesamlphp": "^2" + }, + "support": { + "issues": "https://github.com/simplesamlphp/simplesamlphp-test-framework/issues", + "source": "https://github.com/simplesamlphp/simplesamlphp-test-framework" + }, + "config": { + "allow-plugins": { + "composer/package-versions-deprecated": true, + "simplesamlphp/composer-module-installer": true, + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ArrayLogger.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ArrayLogger.php new file mode 100644 index 000000000..8504798a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ArrayLogger.php @@ -0,0 +1,34 @@ +logs[$level][] = $string; + } + + public function setLogFormat(string $format): void + { + // ignored + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/BuiltInServer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/BuiltInServer.php new file mode 100644 index 000000000..0f0a907f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/BuiltInServer.php @@ -0,0 +1,229 @@ + + * @package SimpleSAMLphp + */ +class BuiltInServer +{ + /** + * The PID of the running server. + * + * @var int + */ + protected $pid = 0; + + /** + * The address (host:port) where the server is listening for connections after being started. + * + * @var string + */ + protected $address = 'example.org'; + + /** + * The name of a "router" file to run for every request performed to this server. + * + * @var string + */ + protected $router = ''; + + /** + * The document root of the server. + * + * @var string + */ + protected $docroot; + + + /** + * BuiltInServer constructor. + * + * @param string|null $router The name of a "router" file to run first for every request performed to this server. + * @param string|null $docroot The document root to use when starting the server. + * + * @see http://php.net/manual/en/features.commandline.webserver.php + */ + public function __construct(string $router = null, string $docroot = null) + { + if (!is_null($router)) { + $this->setRouter($router); + } + + if (!is_null($docroot)) { + $this->docroot = $docroot; + } else { + $this->docroot = dirname(__FILE__, 5) . '/public/'; + } + + // Rationalize docroot + $this->docroot = str_replace('\\', '/', $this->docroot); + $this->docroot = rtrim($this->docroot, '/'); + } + + + /** + * Start the built-in server in a random port. + * + * This method will wait up to 5 seconds for the server to start. When it returns an address, it is guaranteed that + * the server has started and is listening for connections. If it returns the default value on the other hand, + * there will be no guarantee that the server started properly. + * + * @return string The address where the server is listening for connections, or false if the server failed to start + * for some reason. + * + * @todo This method should be resilient to clashes in the randomly-picked port number. + */ + public function start(): string + { + $port = mt_rand(1025, 65535); + $this->address = 'localhost:' . $port; + $sysUtils = new Utils\System(); + + if ($sysUtils->getOS() === $sysUtils::WINDOWS) { + $command = sprintf( + 'powershell $proc = start-process ' + . ' php -ArgumentList (\'-S %s\', \'-t %s\', \'%s\') -Passthru; Write-output $proc.Id;', + $this->address, + $this->docroot, + $this->router, + ); + } else { + $command = sprintf( + 'php -S %s -t %s %s >> /dev/null 2>&1 & echo $!', + $this->address, + $this->docroot, + $this->router, + ); + } + + // execute the command and store the process ID + $output = []; + exec($command, $output); + $this->pid = intval($output[0]); + + // wait until it's listening for connections to avoid race conditions + $start = microtime(true); + do { + $sock = @fsockopen('localhost', $port, $errno, $errstr, 10); + if ($sock === false) { + // set a 5 secs timeout waiting for the server to start + if (microtime(true) > $start + 5.0) { + $this->pid = 0; // signal failure + break; + } + } + } while ($sock === false); + + if ($sock !== false) { + fclose($sock); + } + + sleep(2); // Ensure the service is able to prepare itself before receiving requests + return $this->address; + } + + + /** + * Stop the built-in server. + * @return void + */ + public function stop(): void + { + $sysUtils = new Utils\System(); + if ($this->pid === 0) { + return; + } elseif ($sysUtils->getOS() === $sysUtils::WINDOWS) { + exec('taskkill /PID ' . $this->pid); + } else { + exec('kill ' . $this->pid); + } + $this->pid = 0; + } + + + /** + * Get the PID of the running server. + * + * @return int The PID of the server, or 0 if the server was not started. + */ + public function getPid(): int + { + return $this->pid; + } + + + /** + * Get the name of the "router" file. + * + * @return string The name of the "router" file. + */ + public function getRouter(): string + { + return $this->router; + } + + + /** + * Set the "router" file. + * + * @param string $router The name of a "router" file to use when starting the server. + * @return void + */ + public function setRouter(string $router): void + { + $file = dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/tests/routers/' . $router . '.php'; + if (!file_exists($file)) { + throw new \InvalidArgumentException('Unknown router "' . $router . '".'); + } + $this->router = $file; + } + + + /** + * This function performs an HTTP GET request to the built-in server. + * + * @param string $query The query to perform. + * @param array $parameters An array (can be empty) with parameters for the requested URI. + * @param array $curlopts An array (can be empty) with options for cURL. + * + * @return array The response obtained from the built-in server. + */ + public function get(string $query, array $parameters, array $curlopts = []): array + { + $ch = curl_init(); + $url = 'http://' . $this->address . $query; + $url .= (!empty($parameters)) ? '?' . http_build_query($parameters) : ''; + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_HEADER => 1, + ]); + curl_setopt_array($ch, $curlopts); + /** @var mixed $resp */ + $resp = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + list($header, $body) = explode("\r\n\r\n", $resp, 2); + $raw_headers = explode("\r\n", $header); + array_shift($raw_headers); + $headers = []; + foreach ($raw_headers as $header) { + list($name, $value) = explode(':', $header, 2); + $headers[trim($name)] = trim($value); + } + curl_close($ch); + return [ + 'code' => $code, + 'headers' => $headers, + 'body' => $body, + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ClearStateTestCase.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ClearStateTestCase.php new file mode 100644 index 000000000..f66ca4464 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ClearStateTestCase.php @@ -0,0 +1,62 @@ +backupGlobals(); + } + } + + + /** + * @return void + */ + protected function setUp(): void + { + self::clearState(); + } + + + /** + * @return void + */ + public static function tearDownAfterClass(): void + { + self::clearState(); + } + + + /** + * Clear any SSP global state to reduce spill over between tests. + * @return void + */ + public static function clearState(): void + { + if (isset(self::$stateClearer)) { + self::$stateClearer->clearGlobals(); + self::$stateClearer->clearSSPState(); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/InMemoryStore.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/InMemoryStore.php new file mode 100644 index 000000000..5c0a41e86 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/InMemoryStore.php @@ -0,0 +1,81 @@ +delete($type, $key); + return null; + } + return $item['value']; + } + return null; + } + + + /** + * Save a value to the data store. + * + * @param string $type The data type. + * @param string $key The key. + * @param mixed $value The value. + * @param int|null $expire The expiration time (unix timestamp), or null if it never expires. + */ + public function set(string $type, string $key, mixed $value, ?int $expire = null): void + { + self::$store[$key] = [ + 'type' => $type, + 'value' => $value, + 'expire' => $expire, + ]; + } + + + /** + * Delete a value from the data store. + * + * @param string $type The data type. + * @param string $key The key. + */ + public function delete(string $type, string $key): void + { + unset(self::$store[$key]); + } + + + /** + * Clear any cached internal state. + */ + public static function clearInternalState(): void + { + self::$store = []; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ReduceSpillOverTest.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ReduceSpillOverTest.php new file mode 100644 index 000000000..542b22c04 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/ReduceSpillOverTest.php @@ -0,0 +1,48 @@ + 'b'], '[ARRAY]', 'simplesaml'); + $this->assertEquals('b', Configuration::getInstance()->getString('a')); + putenv('SIMPLESAMLPHP_CONFIG_DIR=' . __DIR__); + } + + + /** + * Confirm global state removed prior to next test + * @return void + * @throws \SimpleSAML\Error\ConfigurationError + */ + public function testStateRemoved(): void + { + $this->assertArrayNotHasKey('QUERY_STRING', $_SERVER); + + /** @var false $env */ + $env = getenv('SIMPLESAMLPHP_CONFIG_DIR'); + + try { + Configuration::getInstance(); + $this->fail('Expected config configured in other tests to no longer be valid'); + } catch (ConfigurationError $error) { + // Expected error + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SigningTestCase.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SigningTestCase.php new file mode 100644 index 000000000..3df76fc9a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SigningTestCase.php @@ -0,0 +1,119 @@ +root_directory = dirname(dirname(__FILE__)); + $base = $this->root_directory . DIRECTORY_SEPARATOR . $this->cert_directory; + $this->ca_private_key = file_get_contents($base . DIRECTORY_SEPARATOR . $this->ca_private_key_file); + $this->ca_certificate = file_get_contents($base . DIRECTORY_SEPARATOR . $this->ca_certificate_file); + $this->good_private_key = file_get_contents($base . DIRECTORY_SEPARATOR . $this->good_private_key_file); + $this->good_certificate = file_get_contents($base . DIRECTORY_SEPARATOR . $this->good_certificate_file); + } + + + /** + * @return array + */ + public function getCertDirContent(): array + { + return [ + $this->ca_private_key_file => $this->ca_private_key, + $this->ca_certificate_file => $this->ca_certificate, + $this->good_private_key_file => $this->good_private_key, + $this->good_certificate_file => $this->good_certificate, + ]; + } + + + /** + * @return void + */ + public function setUp(): void + { + $this->config = Configuration::loadFromArray([ + 'certdir' => $this->cert_directory, + ], '[ARRAY]', 'simplesaml'); + } + + + /** + * @return void + */ + public function tearDown(): void + { + $this->clearInstance($this->config, Configuration::class, []); + } + + + /** + * @param \SimpleSAML\Configuration $service + * @param class-string $className + * @param mixed|null $value + * @return void + */ + protected function clearInstance(Configuration $service, string $className, $value = null): void + { + $reflectedClass = new ReflectionClass($className); + $reflectedInstance = $reflectedClass->getProperty('instance'); + $reflectedInstance->setAccessible(true); + $reflectedInstance->setValue($service, $value); + $reflectedInstance->setAccessible(false); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SimpleTestLogger.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SimpleTestLogger.php new file mode 100644 index 000000000..18b123af9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/SimpleTestLogger.php @@ -0,0 +1,73 @@ +messages[] = [ + 'level' => $level, + 'message' => $message, + 'context' => $context, + ]; + } + + + /** + * Get all the messages logged at the specified level + * + * @param mixed $level + * + * @return array + */ + public function getMessagesForLevel($level): array + { + return array_filter($this->messages, function (string $message) use ($level) { + return $message['level'] === $level; + }); + } + + + /** + * Check if the given message exists within the log + * + * @param string|\Stringable $messageToFind + * + * @return bool + */ + public function hasMessage(string|Stringable $messageToFind): bool + { + $count = array_filter($this->messages, function ($message) use ($messageToFind) { + return $message['message'] === $messageToFind; + }); + + return !!count($count); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/StateClearer.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/StateClearer.php new file mode 100644 index 000000000..b61060863 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/lib/StateClearer.php @@ -0,0 +1,95 @@ +backups['$_COOKIE'] = $_COOKIE; + $this->backups['$_ENV'] = $_ENV; + $this->backups['$_FILES'] = $_FILES; + $this->backups['$_GET'] = $_GET; + $this->backups['$_POST'] = $_POST; + $this->backups['$_SERVER'] = $_SERVER; + /** @psalm-suppress RedundantCondition */ + $this->backups['$_SESSION'] = isset($_SESSION) ? $_SESSION : []; + $this->backups['$_REQUEST'] = $_REQUEST; + } + + + /** + * Clear any global state. + * @return void + */ + public function clearGlobals() + { + if (!empty($this->backups)) { + $_COOKIE = $this->backups['$_COOKIE']; + $_ENV = $this->backups['$_ENV']; + $_FILES = $this->backups['$_FILES']; + $_GET = $this->backups['$_GET']; + $_POST = $this->backups['$_POST']; + $_SERVER = $this->backups['$_SERVER']; + $_SESSION = $this->backups['$_SESSION']; + $_REQUEST = $this->backups['$_REQUEST']; + } else { + //TODO: what should this behavior be? + } + } + + + /** + * Clear any SSP specific state, such as SSP enviormental variables or cached internals. + * @return void + */ + public function clearSSPState() + { + foreach ($this->clearableState as $var) { + $var::clearInternalState(); + } + + foreach ($this->vars_to_unset as $var) { + putenv($var); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_expired.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_expired.php new file mode 100644 index 000000000..571c1d908 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_expired.php @@ -0,0 +1,29 @@ + 'saml20-idp-remote', + 'entityid' => 'https://idp.example.org/saml2/idp/metadata.php', + 'SingleSignOnService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SSOService.php', + ], + ], + 'SingleLogoutService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SingleLogoutService.php', + ], + ], + 'certData' => 'MIICqTCCAhICAQMwDQYJKoZIhvcNAQELBQAwgZgxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZIYXdhaWkxETAPBgNVBAcMCEhvbm9sdWx1MRYwFAYDVQQKDA1TaW1wbGVTQU1McGhwMRMwEQYDVQQLDApEZXZlbG9wZXJzMRQwEgYDVQQDDAtleGFtcGxlLm9yZzEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBleGFtcGxlLm9yZzAeFw0xOTA3MjAwODAwNDVaFw0xOTA3MjEwODAwNDVaMIGgMQswCQYDVQQGEwJVUzEPMA0GA1UECAwGSGF3YWlpMREwDwYDVQQHDAhIb25vbHVsdTEWMBQGA1UECgwNU2ltcGxlU0FNTHBocDETMBEGA1UECwwKRGV2ZWxvcGVyczEcMBoGA1UEAwwTZXhwaXJlZC5leGFtcGxlLm9yZzEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBleGFtcGxlLm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2r6LqKka+9YwWzt32YWAIE/L/HKlVVYJAHBkWWVvHP16EL44LmTSCPZkNg27ha/vuWU0Qd8kW+hn1PiiNxI8dtR9uLaRaBhsHXEvgJtG9A2IrWtgbhMgRrMeSh9bDurgPEnGkXEpEghZpwEQ50ToFAukFJnx7EVK2UvbKtwfkv8CAwEAATANBgkqhkiG9w0BAQsFAAOBgQBfSFYHEiaKYIR2uOxOMpQQBigziuPKK7J4+IDrG1uCXV/YkEV8txgcUDZXTvchhVvLskOu5vrMFtaAXftySv6prS+TQZlCKo3OQQkiNFj/IJFaNq/bPascwJsd0VpB37daUqd65oK33Q1JgNY3b+gKWWUhZoHysURch5bO7jh8rA==', + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', + 'contacts' => [ + 0 => [ + 'emailAddress' => 'idp@example.org', + 'contactType' => 'technical', + 'givenName' => 'Administrator', + ], + ], +]; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_selfsigned.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_selfsigned.php new file mode 100644 index 000000000..41ad310a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_selfsigned.php @@ -0,0 +1,29 @@ + 'saml20-idp-remote', + 'entityid' => 'https://idp.example.org/saml2/idp/metadata.php', + 'SingleSignOnService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SSOService.php', + ], + ], + 'SingleLogoutService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SingleLogoutService.php', + ], + ], + 'certData' => 'MIIDEjCCAnugAwIBAgIJANIdJROXilWcMA0GCSqGSIb3DQEBCwUAMIGgMQswCQYDVQQGEwJVUzELMAkGA1UECAwCSEkxETAPBgNVBAcMCEhvbm9sdWx1MRYwFAYDVQQKDA1TaW1wbGVTQU1McGhwMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEfMB0GA1UEAwwWc2VsZnNpZ25lZC5leGFtcGxlLm9yZzEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBleGFtcGxlLm9yZzAgFw0xOTA3MTgxNjMwMTZaGA8yMTE5MDYyNDE2MzAxNlowgaAxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJISTERMA8GA1UEBwwISG9ub2x1bHUxFjAUBgNVBAoMDVNpbXBsZVNBTUxwaHAxFDASBgNVBAsMC0RldmVsb3BtZW50MR8wHQYDVQQDDBZzZWxmc2lnbmVkLmV4YW1wbGUub3JnMSIwIAYJKoZIhvcNAQkBFhNub3JlcGx5QGV4YW1wbGUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwjX17mpEFt9pdka/jnseuSNosBqTRH6Pw9sQkuTH19xrRMdlGigfgdOQqvwUN1LcOF+zvFNQnZ3yTqpRxjGGcTtExKPeRI5Avef6aFO6AiDCKt831b95pnZuRsC0XweojS1xkEyiplzFZ0UjGTEG06QYvPYXJwDrTqSZuTOZGAQIDAQABo1AwTjAdBgNVHQ4EFgQUdWqf6TRDUhnJNM7vZB60oZ6bEgIwHwYDVR0jBBgwFoAUdWqf6TRDUhnJNM7vZB60oZ6bEgIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBS+7YLLJJiDJ7OIg4PQb1bK2JpSNAimT1ZuhcgeeApM81OTh9AAS5OchRcjYmf4u1nJmfXk5RnJUHpFGGzjXoTtCrdwTUFV+u0WEkM+bB1nfuQHaHqr1UC6H956keHpedQ0N/9+0/hMoqwERQiaQLfoH9tIHv83Lq3iTc8uuJ/XA==', + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', + 'contacts' => [ + 0 => [ + 'emailAddress' => 'idp@example.org', + 'contactType' => 'technical', + 'givenName' => 'Administrator', + ], + ], +]; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_signed.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_signed.php new file mode 100644 index 000000000..9eab22c9c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_cert_signed.php @@ -0,0 +1,29 @@ + 'saml20-idp-remote', + 'entityid' => 'https://idp.example.org/saml2/idp/metadata.php', + 'SingleSignOnService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SSOService.php', + ], + ], + 'SingleLogoutService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SingleLogoutService.php', + ], + ], + 'certData' => 'MIICqDCCAhECAQIwDQYJKoZIhvcNAQELBQAwgZgxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIDAZIYXdhaWkxETAPBgNVBAcMCEhvbm9sdWx1MRYwFAYDVQQKDA1TaW1wbGVTQU1McGhwMRMwEQYDVQQLDApEZXZlbG9wZXJzMRQwEgYDVQQDDAtleGFtcGxlLm9yZzEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBleGFtcGxlLm9yZzAeFw0xOTA3MjAwNzU4MDFaFw0zOTA3MTUwNzU4MDFaMIGfMQswCQYDVQQGEwJVUzEPMA0GA1UECAwGSGF3YWlpMREwDwYDVQQHDAhIb25vbHVsdTEWMBQGA1UECgwNU2ltcGxlU0FNTHBocDETMBEGA1UECwwKRGV2ZWxvcGVyczEbMBkGA1UEAwwSc2lnbmVkLmV4YW1wbGUub3JnMSIwIAYJKoZIhvcNAQkBFhNub3JlcGx5QGV4YW1wbGUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcYmwkO1lHel3sFpQtVnCQInGac8MYVWiXKrxWKsWAqrcsRnjGvIMQU5oz2KNhensx7C2Baa3yOmhyfoGEIoMnntQO6gqYAVskuAKGJhUzpPP1qP4ZV/FjZZ224u9+25gOkZO3Hr5PVCNBPloc+K8ppjRoUbwxFos8i9xou5v6xQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAD5jvsrGp0rv33XwbfWwhTNSBzwa61qr1fs1OjTfN2DJf/3i46uywHMZOfkDGstxmoqS7DcpNhMblv4eQDjYBADI1a6O5atAbtdu3D9qN67Ucc20xwQdZ0fBO9prH6pl6dm4zeF0pboZRi1s1GbxgixCPT5UQWvDnL7YM/pW8ttA', + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', + 'contacts' => [ + 0 => [ + 'emailAddress' => 'idp@example.org', + 'contactType' => 'technical', + 'givenName' => 'Administrator', + ], + ], +]; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_expired.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_expired.php new file mode 100644 index 000000000..2b9a2ec88 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/metadata/simplesamlphp/saml20-idp-remote_expired.php @@ -0,0 +1,30 @@ + 'saml20-idp-remote', + 'entityid' => 'https://idp.example.org/saml2/idp/metadata.php', + 'SingleSignOnService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SSOService.php', + ], + ], + 'SingleLogoutService' => [ + 0 => [ + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'https://idp.example.org/saml2/idp/SingleLogoutService.php', + ], + ], + 'expire' => 1563554760, + 'certData' => 'MIIDEjCCAnugAwIBAgIJANIdJROXilWcMA0GCSqGSIb3DQEBCwUAMIGgMQswCQYDVQQGEwJVUzELMAkGA1UECAwCSEkxETAPBgNVBAcMCEhvbm9sdWx1MRYwFAYDVQQKDA1TaW1wbGVTQU1McGhwMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEfMB0GA1UEAwwWc2VsZnNpZ25lZC5leGFtcGxlLm9yZzEiMCAGCSqGSIb3DQEJARYTbm9yZXBseUBleGFtcGxlLm9yZzAgFw0xOTA3MTgxNjMwMTZaGA8yMTE5MDYyNDE2MzAxNlowgaAxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJISTERMA8GA1UEBwwISG9ub2x1bHUxFjAUBgNVBAoMDVNpbXBsZVNBTUxwaHAxFDASBgNVBAsMC0RldmVsb3BtZW50MR8wHQYDVQQDDBZzZWxmc2lnbmVkLmV4YW1wbGUub3JnMSIwIAYJKoZIhvcNAQkBFhNub3JlcGx5QGV4YW1wbGUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwjX17mpEFt9pdka/jnseuSNosBqTRH6Pw9sQkuTH19xrRMdlGigfgdOQqvwUN1LcOF+zvFNQnZ3yTqpRxjGGcTtExKPeRI5Avef6aFO6AiDCKt831b95pnZuRsC0XweojS1xkEyiplzFZ0UjGTEG06QYvPYXJwDrTqSZuTOZGAQIDAQABo1AwTjAdBgNVHQ4EFgQUdWqf6TRDUhnJNM7vZB60oZ6bEgIwHwYDVR0jBBgwFoAUdWqf6TRDUhnJNM7vZB60oZ6bEgIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQBS+7YLLJJiDJ7OIg4PQb1bK2JpSNAimT1ZuhcgeeApM81OTh9AAS5OchRcjYmf4u1nJmfXk5RnJUHpFGGzjXoTtCrdwTUFV+u0WEkM+bB1nfuQHaHqr1UC6H956keHpedQ0N/9+0/hMoqwERQiaQLfoH9tIHv83Lq3iTc8uuJ/XA==', + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient', + 'contacts' => [ + 0 => [ + 'emailAddress' => 'idp@example.org', + 'contactType' => 'technical', + 'givenName' => 'Administrator', + ], + ], +]; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpcs-simplesamlphp.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpcs-simplesamlphp.xml new file mode 100644 index 000000000..a3ccab19c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpcs-simplesamlphp.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan-dev.neon b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan-dev.neon new file mode 100644 index 000000000..57972f5d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan-dev.neon @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - tests diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan.neon b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan.neon new file mode 100644 index 000000000..db37782f9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + level: 6 + paths: + - src diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/src/TemplateTest.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/src/TemplateTest.php new file mode 100644 index 000000000..9eaa18231 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/src/TemplateTest.php @@ -0,0 +1,82 @@ + + * @package SimpleSAMLphp + * + * @psalm-suppress InternalMethod + */ +class TemplateTest extends TestCase +{ + /** + * @return void + */ + public function testSyntax() + { + $config = Configuration::loadFromArray([ + 'module.enable' => array_fill_keys(Module::getModules(), true), + ]); + Configuration::setPreLoadedConfig($config); + + $basedir = $config->getBaseDir() . 'templates'; + if (file_exists($basedir)) { + $files = array_diff(scandir($basedir), ['.', '..']); + + // Base templates + foreach ($files as $file) { + if (preg_match('/.twig$/', $file)) { + $t = new Template($config, $file); + + $source = new Source(file_get_contents($basedir . DIRECTORY_SEPARATOR . $file), $file); + + try { + $t->getTwig()->tokenize($source); + $this->addToAssertionCount(1); + } catch (SyntaxError $e) { + $this->fail($e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine()); + } + } + } + } + + // See if this is the base repository or a module. If module, skip + if (strpos($basedir, 'vendor') === false) { + // Module templates + + foreach (Module::getModules() as $module) { + $basedir = Module::getModuleDir($module) . DIRECTORY_SEPARATOR . 'templates'; + + if (file_exists($basedir)) { + $files = array_diff(scandir($basedir), ['.', '..']); + foreach ($files as $file) { + if (preg_match('/.twig$/', $file)) { + $t = new Template($config, $module . ':' . $file); + + $source = new Source(file_get_contents($basedir . DIRECTORY_SEPARATOR . $file), $file); + + try { + $t->getTwig()->tokenize($source); + $this->addToAssertionCount(1); + } catch (SyntaxError $e) { + $this->fail($e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine()); + } + } + } + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/krb5.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/krb5.php new file mode 100644 index 000000000..8844667be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/krb5.php @@ -0,0 +1,257 @@ + + * Open memcached server connection + * @link https://php.net/manual/en/memcache.connect.php + * @param string $host

    + * Point to the host where memcached is listening for connections. This parameter + * may also specify other transports like unix:///path/to/memcached.sock + * to use UNIX domain sockets, in this case port must also + * be set to 0. + *

    + * @param int $port [optional]

    + * Point to the port where memcached is listening for connections. Set this + * parameter to 0 when using UNIX domain sockets. + *

    + *

    + * Please note: port defaults to + * {@link https://php.net/manual/ru/memcache.ini.php#ini.memcache.default-port memcache.default_port} + * if not specified. For this reason it is wise to specify the port + * explicitly in this method call. + *

    + * @param int $timeout [optional]

    Value in seconds which will be used for connecting to the daemon. Think twice before changing the default value of 1 second - you can lose all the advantages of caching if your connection is too slow.

    + * @return boolean

    Returns TRUE on success or FALSE on failure.

    + */ + public function connect ($host, $port, $timeout = 1) {} + + /** + * (PECL memcache >= 2.0.0)
    + * Add a memcached server to connection pool + * @link https://php.net/manual/en/memcache.addserver.php + * @param string $host

    + * Point to the host where memcached is listening for connections. This parameter + * may also specify other transports like unix:///path/to/memcached.sock + * to use UNIX domain sockets, in this case port must also + * be set to 0. + *

    + * @param int $port [optional]

    + * Point to the port where memcached is listening for connections. + * Set this + * parameter to 0 when using UNIX domain sockets. + *

    + *

    + * Please note: port defaults to + * memcache.default_port + * if not specified. For this reason it is wise to specify the port + * explicitly in this method call. + *

    + * @param bool $persistent [optional]

    + * Controls the use of a persistent connection. Default to TRUE. + *

    + * @param int $weight [optional]

    + * Number of buckets to create for this server which in turn control its + * probability of it being selected. The probability is relative to the + * total weight of all servers. + *

    + * @param int $timeout [optional]

    + * Value in seconds which will be used for connecting to the daemon. Think + * twice before changing the default value of 1 second - you can lose all + * the advantages of caching if your connection is too slow. + *

    + * @param int $retry_interval [optional]

    + * Controls how often a failed server will be retried, the default value + * is 15 seconds. Setting this parameter to -1 disables automatic retry. + * Neither this nor the persistent parameter has any + * effect when the extension is loaded dynamically via dl. + *

    + *

    + * Each failed connection struct has its own timeout and before it has expired + * the struct will be skipped when selecting backends to serve a request. Once + * expired the connection will be successfully reconnected or marked as failed + * for another retry_interval seconds. The typical + * effect is that each web server child will retry the connection about every + * retry_interval seconds when serving a page. + *

    + * @param bool $status [optional]

    + * Controls if the server should be flagged as online. Setting this parameter + * to FALSE and retry_interval to -1 allows a failed + * server to be kept in the pool so as not to affect the key distribution + * algorithm. Requests for this server will then failover or fail immediately + * depending on the memcache.allow_failover setting. + * Default to TRUE, meaning the server should be considered online. + *

    + * @param callable $failure_callback [optional]

    + * Allows the user to specify a callback function to run upon encountering an + * error. The callback is run before failover is attempted. The function takes + * two parameters, the hostname and port of the failed server. + *

    + * @param int $timeoutms [optional]

    + *

    + * @return bool TRUE on success or FALSE on failure. + */ + public function addServer ($host, $port = 11211, $persistent = true, $weight = null, $timeout = 1, $retry_interval = 15, $status = true, callable $failure_callback = null, $timeoutms = null) {} + + /** + * (PECL memcache >= 2.1.0)
    + * Changes server parameters and status at runtime + * @link https://secure.php.net/manual/en/memcache.setserverparams.php + * @param string $host

    Point to the host where memcached is listening for connections. + * Point to the port where memcached is listening for connections. + *

    + * @param int $timeout [optional]

    + * Value in seconds which will be used for connecting to the daemon. Think twice before changing the default value of 1 second - you can lose all the advantages of caching if your connection is too slow. + *

    + * @param int $retry_interval [optional]

    + * Controls how often a failed server will be retried, the default value + * is 15 seconds. Setting this parameter to -1 disables automatic retry. + * Neither this nor the persistent parameter has any + * effect when the extension is loaded dynamically via {@link https://secure.php.net/manual/en/function.dl.php dl()}. + *

    + * @param bool $status [optional]

    + * Controls if the server should be flagged as online. Setting this parameter + * to FALSE and retry_interval to -1 allows a failed + * server to be kept in the pool so as not to affect the key distribution + * algorithm. Requests for this server will then failover or fail immediately + * depending on the memcache.allow_failover setting. + * Default to TRUE, meaning the server should be considered online. + *

    + * @param callable $failure_callback [optional]

    + * Allows the user to specify a callback function to run upon encountering an error. The callback is run before failover is attempted. + * The function takes two parameters, the hostname and port of the failed server. + *

    + * @return boolean

    Returns TRUE on success or FALSE on failure.

    + */ + public function setServerParams ($host, $port = 11211, $timeout = 1, $retry_interval = 15, $status = true, callable $failure_callback = null) {} + + /** + * + */ + public function setFailureCallback () {} + + /** + * (PECL memcache >= 2.1.0)
    + * Returns server status + * @link https://php.net/manual/en/memcache.getserverstatus.php + * @param string $host Point to the host where memcached is listening for connections. + * @param int $port Point to the port where memcached is listening for connections. + * @return int Returns a the servers status. 0 if server is failed, non-zero otherwise + */ + public function getServerStatus ($host, $port = 11211) {} + + /** + * + */ + public function findServer () {} + + /** + * (PECL memcache >= 0.2.0)
    + * Return version of the server + * @link https://php.net/manual/en/memcache.getversion.php + * @return string|boolean Returns a string of server version number or FALSE on failure. + */ + public function getVersion () {} + + /** + * (PECL memcache >= 2.0.0)
    + * Add an item to the server. If the key already exists, the value will not be added and FALSE will be returned. + * @link https://php.net/manual/en/memcache.add.php + * @param string $key The key that will be associated with the item. + * @param mixed $var The variable to store. Strings and integers are stored as is, other types are stored serialized. + * @param int $flag [optional]

    + * Use MEMCACHE_COMPRESSED to store the item + * compressed (uses zlib). + *

    + * @param int $expire [optional]

    Expiration time of the item. + * If it's equal to zero, the item will never expire. + * You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days).

    + * @return boolean Returns TRUE on success or FALSE on failure. Returns FALSE if such key already exist. For the rest Memcache::add() behaves similarly to Memcache::set(). + */ + public function add ($key , $var, $flag = null, $expire = null) {} + + /** + * (PECL memcache >= 0.2.0)
    + * Stores an item var with key on the memcached server. Parameter expire is expiration time in seconds. + * If it's 0, the item never expires (but memcached server doesn't guarantee this item to be stored all the time, + * it could be deleted from the cache to make place for other items). + * You can use MEMCACHE_COMPRESSED constant as flag value if you want to use on-the-fly compression (uses zlib). + * @link https://php.net/manual/en/memcache.set.php + * @param string $key The key that will be associated with the item. + * @param mixed $var The variable to store. Strings and integers are stored as is, other types are stored serialized. + * @param int $flag [optional] Use MEMCACHE_COMPRESSED to store the item compressed (uses zlib). + * @param int $expire [optional] Expiration time of the item. If it's equal to zero, the item will never expire. You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days). + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function set ($key, $var, $flag = null, $expire = null) {} + + /** + * (PECL memcache >= 0.2.0)
    + * Replace value of the existing item + * @link https://php.net/manual/en/memcache.replace.php + * @param string $key

    The key that will be associated with the item.

    + * @param mixed $var

    The variable to store. Strings and integers are stored as is, other types are stored serialized.

    + * @param int $flag [optional]

    Use MEMCACHE_COMPRESSED to store the item compressed (uses zlib).

    + * @param int $expire [optional]

    Expiration time of the item. If it's equal to zero, the item will never expire. You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days).

    + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function replace ($key, $var, $flag = null, $expire = null) {} + + public function cas () {} + + public function append () {} + + /** + * @return string + */ + public function prepend () {} + + /** + * (PECL memcache >= 0.2.0)
    + * Retrieve item from the server + * @link https://php.net/manual/en/memcache.get.php + * @param string|array $key

    + * The key or array of keys to fetch. + *

    + * @param int|array $flags [optional]

    + * If present, flags fetched along with the values will be written to this parameter. These + * flags are the same as the ones given to for example {@link https://php.net/manual/en/memcache.set.php Memcache::set()}. + * The lowest byte of the int is reserved for pecl/memcache internal usage (e.g. to indicate + * compression and serialization status). + *

    + * @return string|array

    + * Returns the string associated with the key or + * an array of found key-value pairs when key is an {@link https://php.net/manual/en/language.types.array.php array}. + * Returns FALSE on failure, key is not found or + * key is an empty {@link https://php.net/manual/en/language.types.array.php array}. + *

    + */ + public function get ($key, &$flags = null) {} + + /** + * (PECL memcache >= 0.2.0)
    + * Delete item from the server + * https://secure.php.net/manual/ru/memcache.delete.php + * @param $key string The key associated with the item to delete. + * @param $timeout int [optional] This deprecated parameter is not supported, and defaults to 0 seconds. Do not use this parameter. + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function delete ($key, $timeout = 0 ) {} + + /** + * (PECL memcache >= 0.2.0)
    + * Get statistics of the server + * @link https://php.net/manual/ru/memcache.getstats.php + * @param string $type [optional]

    + * The type of statistics to fetch. + * Valid values are {reset, malloc, maps, cachedump, slabs, items, sizes}. + * According to the memcached protocol spec these additional arguments "are subject to change for the convenience of memcache developers".

    + * @param int $slabid [optional]

    + * Used in conjunction with type set to + * cachedump to identify the slab to dump from. The cachedump + * command ties up the server and is strictly to be used for + * debugging purposes. + *

    + * @param int $limit [optional]

    + * Used in conjunction with type set to cachedump to limit the number of entries to dump. + *

    + * @return array|bool Returns an associative array of server statistics or FALSE on failure. + */ + public function getStats ($type = null, $slabid = null, $limit = 100) {} + + /** + * (PECL memcache >= 2.0.0)
    + * Get statistics from all servers in pool + * @link https://php.net/manual/en/memcache.getextendedstats.php + * @param string $type [optional]

    The type of statistics to fetch. Valid values are {reset, malloc, maps, cachedump, slabs, items, sizes}. According to the memcached protocol spec these additional arguments "are subject to change for the convenience of memcache developers".

    + * @param int $slabid [optional]

    + * Used in conjunction with type set to + * cachedump to identify the slab to dump from. The cachedump + * command ties up the server and is strictly to be used for + * debugging purposes. + *

    + * @param int $limit Used in conjunction with type set to cachedump to limit the number of entries to dump. + * @return array|bool Returns a two-dimensional associative array of server statistics or FALSE + * Returns a two-dimensional associative array of server statistics or FALSE + * on failure. + */ + public function getExtendedStats ($type = null, $slabid = null, $limit = 100) {} + + /** + * (PECL memcache >= 2.0.0)
    + * Enable automatic compression of large values + * @link https://php.net/manual/en/memcache.setcompressthreshold.php + * @param int $thresold

    Controls the minimum value length before attempting to compress automatically.

    + * @param float $min_saving [optional]

    Specifies the minimum amount of savings to actually store the value compressed. The supplied value must be between 0 and 1. Default value is 0.2 giving a minimum 20% compression savings.

    + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function setCompressThreshold ($thresold, $min_saving = 0.2) {} + /** + * (PECL memcache >= 0.2.0)
    + * Increment item's value + * @link https://php.net/manual/en/memcache.increment.php + * @param $key string Key of the item to increment. + * @param $value int [optional] increment the item by value + * @return int|boolean Returns new items value on success or FALSE on failure. + */ + public function increment ($key, $value = 1) {} + + /** + * (PECL memcache >= 0.2.0)
    + * Decrement item's value + * @link https://php.net/manual/en/memcache.decrement.php + * @param $key string Key of the item do decrement. + * @param $value int Decrement the item by value. + * @return int|boolean Returns item's new value on success or FALSE on failure. + */ + public function decrement ($key, $value = 1) {} + + /** + * (PECL memcache >= 0.4.0)
    + * Close memcached server connection + * @link https://php.net/manual/en/memcache.close.php + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function close () {} + + /** + * (PECL memcache >= 1.0.0)
    + * Flush all existing items at the server + * @link https://php.net/manual/en/memcache.flush.php + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function flush () {} +} + +/** + * Represents a connection to a set of memcache servers. + * @link https://php.net/manual/en/class.memcache.php + */ +class Memcache extends MemcachePool +{ + /** + * (PECL memcache >= 0.4.0)
    + * Open memcached server persistent connection + * @link https://php.net/manual/en/memcache.pconnect.php + * @param string $host

    + * Point to the host where memcached is listening for connections. This parameter + * may also specify other transports like unix:///path/to/memcached.sock + * to use UNIX domain sockets, in this case port must also + * be set to 0. + *

    + * @param int $port [optional]

    + * Point to the port where memcached is listening for connections. Set this + * parameter to 0 when using UNIX domain sockets. + *

    + * @param int $timeout [optional]

    + * Value in seconds which will be used for connecting to the daemon. Think + * twice before changing the default value of 1 second - you can lose all + * the advantages of caching if your connection is too slow. + *

    + * @return mixed a Memcache object or FALSE on failure. + */ + public function pconnect ($host, $port, $timeout = 1) {} +} + +// string $host [, int $port [, int $timeout ]] + +/** + * (PECL memcache >= 0.2.0)
    + * Memcache::connect — Open memcached server connection + * @link https://php.net/manual/en/memcache.connect.php + * @param string $host

    + * Point to the host where memcached is listening for connections. + * This parameter may also specify other transports like + * unix:///path/to/memcached.sock to use UNIX domain sockets, + * in this case port must also be set to 0. + *

    + * @param int $port [optional]

    + * Point to the port where memcached is listening for connections. + * Set this parameter to 0 when using UNIX domain sockets. + * Note: port defaults to memcache.default_port if not specified. + * For this reason it is wise to specify the port explicitly in this method call. + *

    + * @param int $timeout [optional]

    + * Value in seconds which will be used for connecting to the daemon. + *

    + * @return bool Returns TRUE on success or FALSE on failure. + */ +function memcache_connect ($host, $port, $timeout = 1) {} + +/** + * (PECL memcache >= 0.4.0) + * Memcache::pconnect — Open memcached server persistent connection + * + * @link https://php.net/manual/en/memcache.pconnect.php#example-5242 + * @param $host + * @param null $port + * @param int $timeout + * @return Memcache + */ +function memcache_pconnect ($host, $port=null, $timeout=1) {} + +function memcache_add_server () {} + +function memcache_set_server_params () {} + +function memcache_set_failure_callback () {} + +function memcache_get_server_status () {} + +function memcache_get_version () {} + +function memcache_add () {} + +function memcache_set () {} + +function memcache_replace () {} + +function memcache_cas () {} + +function memcache_append () {} + +function memcache_prepend () {} + +function memcache_get () {} + +function memcache_delete () {} + +/** + * (PECL memcache >= 0.2.0)
    + * Turn debug output on/off + * @link https://php.net/manual/en/function.memcache-debug.php + * @param bool $on_off

    + * Turns debug output on if equals to TRUE. + * Turns debug output off if equals to FALSE. + *

    + * @return bool TRUE if PHP was built with --enable-debug option, otherwise + * returns FALSE. + */ +function memcache_debug ($on_off) {} + +function memcache_get_stats () {} + +function memcache_get_extended_stats () {} + +function memcache_set_compress_threshold () {} + +function memcache_increment () {} + +function memcache_decrement () {} + +function memcache_close () {} + +function memcache_flush () {} + +define ('MEMCACHE_COMPRESSED', 2); +define ('MEMCACHE_USER1', 65536); +define ('MEMCACHE_USER2', 131072); +define ('MEMCACHE_USER3', 262144); +define ('MEMCACHE_USER4', 524288); +define ('MEMCACHE_HAVE_SESSION', 1); + +// End of memcache v.3.0.8 +?> diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/memcached.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/memcached.php new file mode 100644 index 000000000..a7c906977 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/memcached.php @@ -0,0 +1,1309 @@ +Enables or disables payload compression. When enabled, + * item values longer than a certain threshold (currently 100 bytes) will be + * compressed during storage and decompressed during retrieval + * transparently.

    + *

    Type: boolean, default: TRUE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_COMPRESSION = -1001; + const OPT_COMPRESSION_TYPE = -1004; + + /** + *

    This can be used to create a "domain" for your item keys. The value + * specified here will be prefixed to each of the keys. It cannot be + * longer than 128 characters and will reduce the + * maximum available key size. The prefix is applied only to the item keys, + * not to the server keys.

    + *

    Type: string, default: "".

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_PREFIX_KEY = -1002; + + /** + *

    + * Specifies the serializer to use for serializing non-scalar values. + * The valid serializers are Memcached::SERIALIZER_PHP + * or Memcached::SERIALIZER_IGBINARY. The latter is + * supported only when memcached is configured with + * --enable-memcached-igbinary option and the + * igbinary extension is loaded. + *

    + *

    Type: integer, default: Memcached::SERIALIZER_PHP.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_SERIALIZER = -1003; + + /** + *

    Indicates whether igbinary serializer support is available.

    + *

    Type: boolean.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HAVE_IGBINARY = 0; + + /** + *

    Indicates whether JSON serializer support is available.

    + *

    Type: boolean.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HAVE_JSON = 0; + const HAVE_SESSION = 1; + const HAVE_SASL = 0; + + /** + *

    Specifies the hashing algorithm used for the item keys. The valid + * values are supplied via Memcached::HASH_* constants. + * Each hash algorithm has its advantages and its disadvantages. Go with the + * default if you don't know or don't care.

    + *

    Type: integer, default: Memcached::HASH_DEFAULT

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_HASH = 2; + + /** + *

    The default (Jenkins one-at-a-time) item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_DEFAULT = 0; + + /** + *

    MD5 item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_MD5 = 1; + + /** + *

    CRC item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_CRC = 2; + + /** + *

    FNV1_64 item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_FNV1_64 = 3; + + /** + *

    FNV1_64A item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_FNV1A_64 = 4; + + /** + *

    FNV1_32 item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_FNV1_32 = 5; + + /** + *

    FNV1_32A item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_FNV1A_32 = 6; + + /** + *

    Hsieh item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_HSIEH = 7; + + /** + *

    Murmur item key hashing algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const HASH_MURMUR = 8; + + /** + *

    Specifies the method of distributing item keys to the servers. + * Currently supported methods are modulo and consistent hashing. Consistent + * hashing delivers better distribution and allows servers to be added to + * the cluster with minimal cache losses.

    + *

    Type: integer, default: Memcached::DISTRIBUTION_MODULA.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_DISTRIBUTION = 9; + + /** + *

    Modulo-based key distribution algorithm.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const DISTRIBUTION_MODULA = 0; + + /** + *

    Consistent hashing key distribution algorithm (based on libketama).

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const DISTRIBUTION_CONSISTENT = 1; + const DISTRIBUTION_VIRTUAL_BUCKET = 6; + + /** + *

    Enables or disables compatibility with libketama-like behavior. When + * enabled, the item key hashing algorithm is set to MD5 and distribution is + * set to be weighted consistent hashing distribution. This is useful + * because other libketama-based clients (Python, Ruby, etc.) with the same + * server configuration will be able to access the keys transparently. + *

    + *

    + * It is highly recommended to enable this option if you want to use + * consistent hashing, and it may be enabled by default in future + * releases. + *

    + *

    Type: boolean, default: FALSE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_LIBKETAMA_COMPATIBLE = 16; + const OPT_LIBKETAMA_HASH = 17; + const OPT_TCP_KEEPALIVE = 32; + + /** + *

    Enables or disables buffered I/O. Enabling buffered I/O causes + * storage commands to "buffer" instead of being sent. Any action that + * retrieves data causes this buffer to be sent to the remote connection. + * Quitting the connection or closing down the connection will also cause + * the buffered data to be pushed to the remote connection.

    + *

    Type: boolean, default: FALSE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_BUFFER_WRITES = 10; + + /** + *

    Enable the use of the binary protocol. Please note that you cannot + * toggle this option on an open connection.

    + *

    Type: boolean, default: FALSE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_BINARY_PROTOCOL = 18; + + /** + *

    Enables or disables asynchronous I/O. This is the fastest transport + * available for storage functions.

    + *

    Type: boolean, default: FALSE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_NO_BLOCK = 0; + + /** + *

    Enables or disables the no-delay feature for connecting sockets (may + * be faster in some environments).

    + *

    Type: boolean, default: FALSE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_TCP_NODELAY = 1; + + /** + *

    The maximum socket send buffer in bytes.

    + *

    Type: integer, default: varies by platform/kernel + * configuration.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_SOCKET_SEND_SIZE = 4; + + /** + *

    The maximum socket receive buffer in bytes.

    + *

    Type: integer, default: varies by platform/kernel + * configuration.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_SOCKET_RECV_SIZE = 5; + + /** + *

    In non-blocking mode this set the value of the timeout during socket + * connection, in milliseconds.

    + *

    Type: integer, default: 1000.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_CONNECT_TIMEOUT = 14; + + /** + *

    The amount of time, in seconds, to wait until retrying a failed + * connection attempt.

    + *

    Type: integer, default: 0.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_RETRY_TIMEOUT = 15; + + /** + *

    Socket sending timeout, in microseconds. In cases where you cannot + * use non-blocking I/O this will allow you to still have timeouts on the + * sending of data.

    + *

    Type: integer, default: 0.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_SEND_TIMEOUT = 19; + + /** + *

    Socket reading timeout, in microseconds. In cases where you cannot + * use non-blocking I/O this will allow you to still have timeouts on the + * reading of data.

    + *

    Type: integer, default: 0.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_RECV_TIMEOUT = 20; + + /** + *

    Timeout for connection polling, in milliseconds.

    + *

    Type: integer, default: 1000.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_POLL_TIMEOUT = 8; + + /** + *

    Enables or disables caching of DNS lookups.

    + *

    Type: boolean, default: FALSE.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_CACHE_LOOKUPS = 6; + + /** + *

    Specifies the failure limit for server connection attempts. The + * server will be removed after this many continuous connection + * failures.

    + *

    Type: integer, default: 0.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const OPT_SERVER_FAILURE_LIMIT = 21; + const OPT_AUTO_EJECT_HOSTS = 28; + const OPT_HASH_WITH_PREFIX_KEY = 25; + const OPT_NOREPLY = 26; + const OPT_SORT_HOSTS = 12; + const OPT_VERIFY_KEY = 13; + const OPT_USE_UDP = 27; + const OPT_NUMBER_OF_REPLICAS = 29; + const OPT_RANDOMIZE_REPLICA_READ = 30; + const OPT_CORK = 31; + const OPT_REMOVE_FAILED_SERVERS = 35; + const OPT_DEAD_TIMEOUT = 36; + const OPT_SERVER_TIMEOUT_LIMIT = 37; + const OPT_MAX = 38; + const OPT_IO_BYTES_WATERMARK = 23; + const OPT_IO_KEY_PREFETCH = 24; + const OPT_IO_MSG_WATERMARK = 22; + const OPT_LOAD_FROM_FILE = 34; + const OPT_SUPPORT_CAS = 7; + const OPT_TCP_KEEPIDLE = 33; + const OPT_USER_DATA = 11; + + + /** + *

    The operation was successful.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_SUCCESS = 0; + + /** + *

    The operation failed in some fashion.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_FAILURE = 1; + + /** + *

    DNS lookup failed.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_HOST_LOOKUP_FAILURE = 2; + + /** + *

    Failed to read network data.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_UNKNOWN_READ_FAILURE = 7; + + /** + *

    Bad command in memcached protocol.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_PROTOCOL_ERROR = 8; + + /** + *

    Error on the client side.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_CLIENT_ERROR = 9; + + /** + *

    Error on the server side.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_SERVER_ERROR = 10; + + /** + *

    Failed to write network data.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_WRITE_FAILURE = 5; + + /** + *

    Failed to do compare-and-swap: item you are trying to store has been + * modified since you last fetched it.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_DATA_EXISTS = 12; + + /** + *

    Item was not stored: but not because of an error. This normally + * means that either the condition for an "add" or a "replace" command + * wasn't met, or that the item is in a delete queue.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_NOTSTORED = 14; + + /** + *

    Item with this key was not found (with "get" operation or "cas" + * operations).

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_NOTFOUND = 16; + + /** + *

    Partial network data read error.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_PARTIAL_READ = 18; + + /** + *

    Some errors occurred during multi-get.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_SOME_ERRORS = 19; + + /** + *

    Server list is empty.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_NO_SERVERS = 20; + + /** + *

    End of result set.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_END = 21; + + /** + *

    System error.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_ERRNO = 26; + + /** + *

    The operation was buffered.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_BUFFERED = 32; + + /** + *

    The operation timed out.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_TIMEOUT = 31; + + /** + *

    Bad key.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_BAD_KEY_PROVIDED = 33; + const RES_STORED = 15; + const RES_DELETED = 22; + const RES_STAT = 24; + const RES_ITEM = 25; + const RES_NOT_SUPPORTED = 28; + const RES_FETCH_NOTFINISHED = 30; + const RES_SERVER_MARKED_DEAD = 35; + const RES_UNKNOWN_STAT_KEY = 36; + const RES_INVALID_HOST_PROTOCOL = 34; + const RES_MEMORY_ALLOCATION_FAILURE = 17; + const RES_E2BIG = 37; + const RES_KEY_TOO_BIG = 39; + const RES_SERVER_TEMPORARILY_DISABLED = 47; + const RES_SERVER_MEMORY_ALLOCATION_FAILURE = 48; + const RES_AUTH_PROBLEM = 40; + const RES_AUTH_FAILURE = 41; + const RES_AUTH_CONTINUE = 42; + const RES_CONNECTION_FAILURE = 3; + const RES_CONNECTION_BIND_FAILURE = 4; + const RES_READ_FAILURE = 6; + const RES_DATA_DOES_NOT_EXIST = 13; + const RES_VALUE = 23; + const RES_FAIL_UNIX_SOCKET = 27; + const RES_NO_KEY_PROVIDED = 29; + const RES_INVALID_ARGUMENTS = 38; + const RES_PARSE_ERROR = 43; + const RES_PARSE_USER_ERROR = 44; + const RES_DEPRECATED = 45; + const RES_IN_PROGRESS = 46; + const RES_MAXIMUM_RETURN = 49; + + + + /** + *

    Failed to create network socket.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_CONNECTION_SOCKET_CREATE_FAILURE = 11; + + /** + *

    Payload failure: could not compress/decompress or serialize/unserialize the value.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const RES_PAYLOAD_FAILURE = -1001; + + /** + *

    The default PHP serializer.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const SERIALIZER_PHP = 1; + + /** + *

    The igbinary serializer. + * Instead of textual representation it stores PHP data structures in a + * compact binary form, resulting in space and time gains.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const SERIALIZER_IGBINARY = 2; + + /** + *

    The JSON serializer. Requires PHP 5.2.10+.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const SERIALIZER_JSON = 3; + const SERIALIZER_JSON_ARRAY = 4; + const COMPRESSION_FASTLZ = 2; + const COMPRESSION_ZLIB = 1; + + /** + *

    A flag for Memcached::getMulti and + * Memcached::getMultiByKey to ensure that the keys are + * returned in the same order as they were requested in. Non-existing keys + * get a default value of NULL.

    + * @link https://php.net/manual/en/memcached.constants.php + */ + const GET_PRESERVE_ORDER = 1; + const GET_ERROR_RETURN_VALUE = false; + + + /** + * (PECL memcached >= 0.1.0)
    + * Create a Memcached instance + * @link https://php.net/manual/en/memcached.construct.php + * @param $persistent_id [optional] + * @param $callback [optional] + */ + public function __construct ($persistent_id = '', $on_new_object_cb = null) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Return the result code of the last operation + * @link https://php.net/manual/en/memcached.getresultcode.php + * @return int Result code of the last Memcached operation. + */ + public function getResultCode () {} + + /** + * (PECL memcached >= 1.0.0)
    + * Return the message describing the result of the last operation + * @link https://php.net/manual/en/memcached.getresultmessage.php + * @return string Message describing the result of the last Memcached operation. + */ + public function getResultMessage () {} + + /** + * (PECL memcached >= 0.1.0)
    + * Retrieve an item + * @link https://php.net/manual/en/memcached.get.php + * @param string $key

    + * The key of the item to retrieve. + *

    + * @param callable $cache_cb [optional]

    + * Read-through caching callback or NULL. + *

    + * @param int $flags [optional]

    + * The flags for the get operation. + *

    + * @return mixed the value stored in the cache or FALSE otherwise. + * The Memcached::getResultCode will return + * Memcached::RES_NOTFOUND if the key does not exist. + */ + public function get ($key, callable $cache_cb = null, $flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Retrieve an item from a specific server + * @link https://php.net/manual/en/memcached.getbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key of the item to fetch. + *

    + * @param callable $cache_cb [optional]

    + * Read-through caching callback or NULL + *

    + * @param int $flags [optional]

    + * The flags for the get operation. + *

    + * @return mixed the value stored in the cache or FALSE otherwise. + * The Memcached::getResultCode will return + * Memcached::RES_NOTFOUND if the key does not exist. + */ + public function getByKey ($server_key, $key, callable $cache_cb = null, $flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Retrieve multiple items + * @link https://php.net/manual/en/memcached.getmulti.php + * @param array $keys

    + * Array of keys to retrieve. + *

    + * @param int $flags [optional]

    + * The flags for the get operation. + *

    + * @return mixed the array of found items or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function getMulti (array $keys, $flags = null) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Retrieve multiple items from a specific server + * @link https://php.net/manual/en/memcached.getmultibykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param array $keys

    + * Array of keys to retrieve. + *

    + * @param int $flags [optional]

    + * The flags for the get operation. + *

    + * @return array the array of found items or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function getMultiByKey ($server_key, array $keys, $flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Request multiple items + * @link https://php.net/manual/en/memcached.getdelayed.php + * @param array $keys

    + * Array of keys to request. + *

    + * @param bool $with_cas [optional]

    + * Whether to request CAS token values also. + *

    + * @param callable $value_cb [optional]

    + * The result callback or NULL. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function getDelayed (array $keys, $with_cas = null, callable $value_cb = null) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Request multiple items from a specific server + * @link https://php.net/manual/en/memcached.getdelayedbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param array $keys

    + * Array of keys to request. + *

    + * @param bool $with_cas [optional]

    + * Whether to request CAS token values also. + *

    + * @param callable $value_cb [optional]

    + * The result callback or NULL. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function getDelayedByKey ($server_key, array $keys, $with_cas = null, callable $value_cb = null) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Fetch the next result + * @link https://php.net/manual/en/memcached.fetch.php + * @return array the next result or FALSE otherwise. + * The Memcached::getResultCode will return + * Memcached::RES_END if result set is exhausted. + */ + public function fetch () {} + + /** + * (PECL memcached >= 0.1.0)
    + * Fetch all the remaining results + * @link https://php.net/manual/en/memcached.fetchall.php + * @return array the results or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function fetchAll () {} + + /** + * (PECL memcached >= 0.1.0)
    + * Store an item + * @link https://php.net/manual/en/memcached.set.php + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function set ($key, $value, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Store an item on a specific server + * @link https://php.net/manual/en/memcached.setbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function setByKey ($server_key, $key, $value, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Set a new expiration on an item + * @link https://php.net/manual/en/memcached.touch.php + * @param string $key

    + * The key under which to store the value. + *

    + * @param int $expiration

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function touch ($key, $expiration = 0) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Set a new expiration on an item on a specific server + * @link https://php.net/manual/en/memcached.touchbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param int $expiration

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function touchByKey ($server_key, $key, $expiration) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Store multiple items + * @link https://php.net/manual/en/memcached.setmulti.php + * @param array $items

    + * An array of key/value pairs to store on the server. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function setMulti (array $items, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Store multiple items on a specific server + * @link https://php.net/manual/en/memcached.setmultibykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param array $items

    + * An array of key/value pairs to store on the server. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function setMultiByKey ($server_key, array $items, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Compare and swap an item + * @link https://php.net/manual/en/memcached.cas.php + * @param float $cas_token

    + * Unique value associated with the existing item. Generated by memcache. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_DATA_EXISTS if the item you are trying + * to store has been modified since you last fetched it. + */ + public function cas ($cas_token, $key, $value, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Compare and swap an item on a specific server + * @link https://php.net/manual/en/memcached.casbykey.php + * @param float $cas_token

    + * Unique value associated with the existing item. Generated by memcache. + *

    + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_DATA_EXISTS if the item you are trying + * to store has been modified since you last fetched it. + */ + public function casByKey ($cas_token, $server_key, $key, $value, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Add an item under a new key + * @link https://php.net/manual/en/memcached.add.php + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key already exists. + */ + public function add ($key, $value, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Add an item under a new key on a specific server + * @link https://php.net/manual/en/memcached.addbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key already exists. + */ + public function addByKey ($server_key, $key, $value, $expiration = 0, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Append data to an existing item + * @link https://php.net/manual/en/memcached.append.php + * @param string $key

    + * The key under which to store the value. + *

    + * @param string $value

    + * The string to append. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key does not exist. + */ + public function append ($key, $value) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Append data to an existing item on a specific server + * @link https://php.net/manual/en/memcached.appendbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param string $value

    + * The string to append. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key does not exist. + */ + public function appendByKey ($server_key, $key, $value) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Prepend data to an existing item + * @link https://php.net/manual/en/memcached.prepend.php + * @param string $key

    + * The key of the item to prepend the data to. + *

    + * @param string $value

    + * The string to prepend. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key does not exist. + */ + public function prepend ($key, $value) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Prepend data to an existing item on a specific server + * @link https://php.net/manual/en/memcached.prependbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key of the item to prepend the data to. + *

    + * @param string $value

    + * The string to prepend. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key does not exist. + */ + public function prependByKey ($server_key, $key, $value) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Replace the item under an existing key + * @link https://php.net/manual/en/memcached.replace.php + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key does not exist. + */ + public function replace ($key, $value, $expiration = null, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Replace the item under an existing key on a specific server + * @link https://php.net/manual/en/memcached.replacebykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key under which to store the value. + *

    + * @param mixed $value

    + * The value to store. + *

    + * @param int $expiration [optional]

    + * The expiration time, defaults to 0. See Expiration Times for more info. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTSTORED if the key does not exist. + */ + public function replaceByKey ($server_key, $key, $value, $expiration = null, $udf_flags = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Delete an item + * @link https://php.net/manual/en/memcached.delete.php + * @param string $key

    + * The key to be deleted. + *

    + * @param int $time [optional]

    + * The amount of time the server will wait to delete the item. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTFOUND if the key does not exist. + */ + public function delete ($key, $time = 0) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Delete multiple items + * @link https://php.net/manual/en/memcached.deletemulti.php + * @param array $keys

    + * The keys to be deleted. + *

    + * @param int $time [optional]

    + * The amount of time the server will wait to delete the items. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTFOUND if the key does not exist. + */ + public function deleteMulti (array $keys, $time = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Delete an item from a specific server + * @link https://php.net/manual/en/memcached.deletebykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key to be deleted. + *

    + * @param int $time [optional]

    + * The amount of time the server will wait to delete the item. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTFOUND if the key does not exist. + */ + public function deleteByKey ($server_key, $key, $time = 0) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Delete multiple items from a specific server + * @link https://php.net/manual/en/memcached.deletemultibykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param array $keys

    + * The keys to be deleted. + *

    + * @param int $time [optional]

    + * The amount of time the server will wait to delete the items. + *

    + * @return bool TRUE on success or FALSE on failure. + * The Memcached::getResultCode will return + * Memcached::RES_NOTFOUND if the key does not exist. + */ + public function deleteMultiByKey ($server_key, array $keys, $time = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Increment numeric item's value + * @link https://php.net/manual/en/memcached.increment.php + * @param string $key

    + * The key of the item to increment. + *

    + * @param int $offset [optional]

    + * The amount by which to increment the item's value. + *

    + * @param int $initial_value [optional]

    + * The value to set the item to if it doesn't currently exist. + *

    + * @param int $expiry [optional]

    + * The expiry time to set on the item. + *

    + * @return int new item's value on success or FALSE on failure. + */ + public function increment ($key, $offset = 1, $initial_value = 0, $expiry = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Decrement numeric item's value + * @link https://php.net/manual/en/memcached.decrement.php + * @param string $key

    + * The key of the item to decrement. + *

    + * @param int $offset [optional]

    + * The amount by which to decrement the item's value. + *

    + * @param int $initial_value [optional]

    + * The value to set the item to if it doesn't currently exist. + *

    + * @param int $expiry [optional]

    + * The expiry time to set on the item. + *

    + * @return int item's new value on success or FALSE on failure. + */ + public function decrement ($key, $offset = 1, $initial_value = 0, $expiry = 0) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Increment numeric item's value, stored on a specific server + * @link https://php.net/manual/en/memcached.incrementbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key of the item to increment. + *

    + * @param int $offset [optional]

    + * The amount by which to increment the item's value. + *

    + * @param int $initial_value [optional]

    + * The value to set the item to if it doesn't currently exist. + *

    + * @param int $expiry [optional]

    + * The expiry time to set on the item. + *

    + * @return int new item's value on success or FALSE on failure. + */ + public function incrementByKey ($server_key, $key, $offset = 1, $initial_value = 0, $expiry = 0) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Decrement numeric item's value, stored on a specific server + * @link https://php.net/manual/en/memcached.decrementbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @param string $key

    + * The key of the item to decrement. + *

    + * @param int $offset [optional]

    + * The amount by which to decrement the item's value. + *

    + * @param int $initial_value [optional]

    + * The value to set the item to if it doesn't currently exist. + *

    + * @param int $expiry [optional]

    + * The expiry time to set on the item. + *

    + * @return int item's new value on success or FALSE on failure. + */ + public function decrementByKey ($server_key, $key, $offset = 1, $initial_value = 0, $expiry = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Add a server to the server pool + * @link https://php.net/manual/en/memcached.addserver.php + * @param string $host

    + * The hostname of the memcache server. If the hostname is invalid, data-related + * operations will set + * Memcached::RES_HOST_LOOKUP_FAILURE result code. + *

    + * @param int $port

    + * The port on which memcache is running. Usually, this is + * 11211. + *

    + * @param int $weight [optional]

    + * The weight of the server relative to the total weight of all the + * servers in the pool. This controls the probability of the server being + * selected for operations. This is used only with consistent distribution + * option and usually corresponds to the amount of memory available to + * memcache on that server. + *

    + * @return bool TRUE on success or FALSE on failure. + */ + public function addServer ($host, $port, $weight = 0) {} + + /** + * (PECL memcached >= 0.1.1)
    + * Add multiple servers to the server pool + * @link https://php.net/manual/en/memcached.addservers.php + * @param array $servers + * @return bool TRUE on success or FALSE on failure. + */ + public function addServers (array $servers) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Get the list of the servers in the pool + * @link https://php.net/manual/en/memcached.getserverlist.php + * @return array The list of all servers in the server pool. + */ + public function getServerList () {} + + /** + * (PECL memcached >= 0.1.0)
    + * Map a key to a server + * @link https://php.net/manual/en/memcached.getserverbykey.php + * @param string $server_key

    + * The key identifying the server to store the value on or retrieve it from. Instead of hashing on the actual key for the item, we hash on the server key when deciding which memcached server to talk to. This allows related items to be grouped together on a single server for efficiency with multi operations. + *

    + * @return array an array containing three keys of host, + * port, and weight on success or FALSE + * on failure. + * Use Memcached::getResultCode if necessary. + */ + public function getServerByKey ($server_key) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Clears all servers from the server list + * @link https://php.net/manual/en/memcached.resetserverlist.php + * @return bool TRUE on success or FALSE on failure. + */ + public function resetServerList () {} + + /** + * (PECL memcached >= 2.0.0)
    + * Close any open connections + * @link https://php.net/manual/en/memcached.quit.php + * @return bool TRUE on success or FALSE on failure. + */ + public function quit () {} + + /** + * (PECL memcached >= 0.1.0)
    + * Get server pool statistics + * @link https://php.net/manual/en/memcached.getstats.php + * @param string $type + * @return array Array of server statistics, one entry per server. + */ + public function getStats ($type = null) {} + + /** + * (PECL memcached >= 0.1.5)
    + * Get server pool version info + * @link https://php.net/manual/en/memcached.getversion.php + * @return array Array of server versions, one entry per server. + */ + public function getVersion () {} + + /** + * (PECL memcached >= 2.0.0)
    + * Gets the keys stored on all the servers + * @link https://php.net/manual/en/memcached.getallkeys.php + * @return array the keys stored on all the servers on success or FALSE on failure. + */ + public function getAllKeys () {} + + /** + * (PECL memcached >= 0.1.0)
    + * Invalidate all items in the cache + * @link https://php.net/manual/en/memcached.flush.php + * @param int $delay [optional]

    + * Numer of seconds to wait before invalidating the items. + *

    + * @return bool TRUE on success or FALSE on failure. + * Use Memcached::getResultCode if necessary. + */ + public function flush ($delay = 0) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Retrieve a Memcached option value + * @link https://php.net/manual/en/memcached.getoption.php + * @param int $option

    + * One of the Memcached::OPT_* constants. + *

    + * @return mixed the value of the requested option, or FALSE on + * error. + */ + public function getOption ($option) {} + + /** + * (PECL memcached >= 0.1.0)
    + * Set a Memcached option + * @link https://php.net/manual/en/memcached.setoption.php + * @param int $option + * @param mixed $value + * @return bool TRUE on success or FALSE on failure. + */ + public function setOption ($option, $value) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Set Memcached options + * @link https://php.net/manual/en/memcached.setoptions.php + * @param array $options

    + * An associative array of options where the key is the option to set and + * the value is the new value for the option. + *

    + * @return bool TRUE on success or FALSE on failure. + */ + public function setOptions (array $options) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Set the credentials to use for authentication + * @link https://secure.php.net/manual/en/memcached.setsaslauthdata.php + * @param string $username

    + * The username to use for authentication. + *

    + * @param string $password

    + * The password to use for authentication. + *

    + * @return bool TRUE on success or FALSE on failure. + */ + public function setSaslAuthData (string $username , string $password) {} + + /** + * (PECL memcached >= 2.0.0)
    + * Check if a persitent connection to memcache is being used + * @link https://php.net/manual/en/memcached.ispersistent.php + * @return bool true if Memcache instance uses a persistent connection, false otherwise. + */ + public function isPersistent () {} + + /** + * (PECL memcached >= 2.0.0)
    + * Check if the instance was recently created + * @link https://php.net/manual/en/memcached.ispristine.php + * @return bool the true if instance is recently created, false otherwise. + */ + public function isPristine () {} + + public function flushBuffers () {} + + public function setEncodingKey ( $key ) {} + + public function getLastDisconnectedServer () {} + + public function getLastErrorErrno () {} + + public function getLastErrorCode () {} + + public function getLastErrorMessage () {} + + public function setBucket (array $host_map, array $forward_map, $replicas) {} + +} + +/** + * @link https://php.net/manual/en/class.memcachedexception.php + */ +if (!class_exists('MemcachedException')) { + class MemcachedException extends RuntimeException + { + } +} +// End of memcached v.3.0.4 diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/predis.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/predis.php new file mode 100644 index 000000000..de29405ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/predis.php @@ -0,0 +1,299 @@ + + */ +class Client +{ + /** + * @param mixed $parameters Connection parameters for one or more servers. + * @param mixed $options Options to configure some behaviours of the client. + */ + public function __construct($parameters = null, $options = null) + { + } + + /** + * Creates a new instance of Predis\Configuration\Options from different + * types of arguments or simply returns the passed argument if it is an + * instance of Predis\Configuration\OptionsInterface. + * + * @param mixed $options Client options. + * + * @throws \InvalidArgumentException + * + * @return OptionsInterface + */ + protected function createOptions($options) + { + } + + /** + * Creates single or aggregate connections from different types of arguments + * (string, array) or returns the passed argument if it is an instance of a + * class implementing Predis\Connection\ConnectionInterface. + * + * Accepted types for connection parameters are: + * + * - Instance of Predis\Connection\ConnectionInterface. + * - Instance of Predis\Connection\ParametersInterface. + * - Array + * - String + * - Callable + * + * @param mixed $parameters Connection parameters or connection instance. + * + * @throws \InvalidArgumentException + * + * @return ConnectionInterface + */ + protected function createConnection($parameters) + { + } + + /** + * Wraps a callable to make sure that its returned value represents a valid + * connection type. + * + * @param mixed $callable + * + * @return \Closure + */ + protected function getConnectionInitializerWrapper($callable) + { + } + + /** + * {@inheritdoc} + */ + public function getProfile() + { + } + + /** + * {@inheritdoc} + */ + public function getOptions() + { + } + + /** + * Creates a new client instance for the specified connection ID or alias, + * only when working with an aggregate connection (cluster, replication). + * The new client instances uses the same options of the original one. + * + * @param string $connectionID Identifier of a connection. + * + * @throws \InvalidArgumentException + * + * @return Client + */ + public function getClientFor($connectionID) + { + } + + /** + * Opens the underlying connection and connects to the server. + */ + public function connect() + { + } + + /** + * Closes the underlying connection and disconnects from the server. + */ + public function disconnect() + { + } + + /** + * Closes the underlying connection and disconnects from the server. + * + * This is the same as `Client::disconnect()` as it does not actually send + * the `QUIT` command to Redis, but simply closes the connection. + */ + public function quit() + { + } + + /** + * Returns the current state of the underlying connection. + * + * @return bool + */ + public function isConnected() + { + } + + /** + * {@inheritdoc} + */ + public function getConnection() + { + } + + /** + * Retrieves the specified connection from the aggregate connection when the + * client is in cluster or replication mode. + * + * @param string $connectionID Index or alias of the single connection. + * + * @throws NotSupportedException + * + * @return Connection\NodeConnectionInterface + */ + public function getConnectionById($connectionID) + { + } + + /** + * Executes a command without filtering its arguments, parsing the response, + * applying any prefix to keys or throwing exceptions on Redis errors even + * regardless of client options. + * + * It is possible to identify Redis error responses from normal responses + * using the second optional argument which is populated by reference. + * + * @param array $arguments Command arguments as defined by the command signature. + * @param bool $error Set to TRUE when Redis returned an error response. + * + * @return mixed + */ + public function executeRaw(array $arguments, &$error = null) + { + } + + /** + * {@inheritdoc} + */ + public function __call($commandID, $arguments) + { + } + + /** + * {@inheritdoc} + */ + public function createCommand($commandID, $arguments = array()) + { + } + + /** + * {@inheritdoc} + */ + public function executeCommand(CommandInterface $command) + { + } + + /** + * Handles -ERR responses returned by Redis. + * + * @param CommandInterface $command Redis command that generated the error. + * @param ErrorResponseInterface $response Instance of the error response. + * + * @throws ServerException + * + * @return mixed + */ + protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response) + { + } + + /** + * Creates a new pipeline context and returns it, or returns the results of + * a pipeline executed inside the optionally provided callable object. + * + * @param mixed ... Array of options, a callable for execution, or both. + * + * @return Pipeline|array + */ + public function pipeline(/* arguments */) + { + } + + /** + * Actual pipeline context initializer method. + * + * @param array $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. + * + * @return Pipeline|array + */ + protected function createPipeline(array $options = null, $callable = null) + { + } + + /** + * Creates a new transaction context and returns it, or returns the results + * of a transaction executed inside the optionally provided callable object. + * + * @param mixed ... Array of options, a callable for execution, or both. + * + * @return MultiExecTransaction|array + */ + public function transaction(/* arguments */) + { + } + + /** + * Actual transaction context initializer method. + * + * @param array $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. + * + * @return MultiExecTransaction|array + */ + protected function createTransaction(array $options = null, $callable = null) + { + } + + /** + * Creates a new publish/subscribe context and returns it, or starts its loop + * inside the optionally provided callable object. + * + * @param mixed ... Array of options, a callable for execution, or both. + * + * @return PubSubConsumer|null + */ + public function pubSubLoop(/* arguments */) + { + } + + /** + * Actual publish/subscribe context initializer method. + * + * @param array $options Options for the context. + * @param mixed $callable Optional callable used to execute the context. + * + * @return PubSubConsumer|null + */ + protected function createPubSub(array $options = null, $callable = null) + { + } + + /** + * Creates a new monitor consumer and returns it. + * + * @return MonitorConsumer + */ + public function monitor() + { + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + } +} + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/radius.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/radius.php new file mode 100644 index 000000000..1b4413b10 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/radius.php @@ -0,0 +1,441 @@ +RADIUS_NAS_IP_ADDRESS or a RADIUS_NAS_IDENTIFIER attribute, must also include a RADIUS_USER_PASSWORD, RADIUS_CHAP_PASSWORD or a RADIUS_STATE attribute, and should include a RADIUS_USER_NAME attribute. */ +define('RADIUS_ACCESS_REQUEST', 1); + +/** An Access-Accept response to an Access-Request indicating that the RADIUS server authenticated the user successfully. */ +define('RADIUS_ACCESS_ACCEPT', 2); + +/** An Access-Reject response to an Access-Request indicating that the RADIUS server could not authenticate the user. */ +define('RADIUS_ACCESS_REJECT', 3); + +/** An Accounting-Request, used to convey accounting information for a service to the RADIUS server. */ +define('RADIUS_ACCOUNTING_REQUEST', 4); + +/** An Accounting-Response response to an Accounting-Request. */ +define('RADIUS_ACCOUNTING_RESPONSE', 5); + +/** An Access-Challenge response to an Access-Request indicating that the RADIUS server requires further information in another Access-Request before authenticating the user. */ +define('RADIUS_ACCESS_CHALLENGE', 11); + +/** + * A Disconnect-Request, sent from the RADIUS server to indicate that the user session must be terminated. + * @since 1.3.0 + */ +define('RADIUS_DISCONNECT_REQUEST', 40); + +/** + * A Disconnect-ACK, sent to the RADIUS server to indicate that the user session has been terminated. + * @since 1.3.0 + */ +define('RADIUS_DISCONNECT_ACK', 41); + +/** + * A Disconnect-NAK, sent to the RADIUS server to indicate that the user session could not be terminated. + * @since 1.3.0 + */ +define('RADIUS_DISCONNECT_NAK', 42); + +/** + * A CoA-Request, sent from the RADIUS server to indicate that the authorisations within the user session have changed. A response must be sent in the form of a CoA-ACK or a CoA-NAK. + * @since 1.3.0 + */ +define('RADIUS_COA_REQUEST', 43); + +/** + * A CoA-ACK, sent to the RADIUS server to indicate that the user authorisations have been updated. + * @since 1.3.0 + */ +define('RADIUS_COA_ACK', 44); + +/** + * A CoA-NAK, sent to the RADIUS server to indicate that the user authorisations could not be updated. + * @since 1.3.0 + */ +define('RADIUS_COA_NAK', 45); + +/** + * RADIUS Attribute Types + * @link https://secure.php.net/manual/en/radius.constants.attributes.php + */ + +/** The User-Name attribute. The attribute value is expected to be a string containing the name of the user being authenticated, and can be set using {@see radius_put_attr()}. */ +define('RADIUS_USER_NAME', 1); + +/** + * The User-Password attribute. The attribute value is expected to be a string containing the user's password, and can be set using {@see radius_put_attr()}. This value will be obfuscated on transmission as described in section 5.2 of RFC 2865. + * @link https://secure.php.net/manual/de/radius.constants.attributes.php */ +define('RADIUS_USER_PASSWORD', 2); + +/** The Chap-Password attribute. The attribute value is expected to be a string with the first byte containing the CHAP identifier, and the subsequent 16 bytes containing the MD5 hash of the CHAP identifier, the plaintext password and the CHAP challenge value concatenated together. Note that the CHAP challenge value should also be sent separately in a {@see RADIUS_CHAP_CHALLENGE} attribute. */ +define('RADIUS_CHAP_PASSWORD', 3); + +/** The NAS-IP-Address attribute. The attribute value is expected to the IP address of the RADIUS client encoded as an integer, which can be set using {@see radius_put_addr()}. */ +define('RADIUS_NAS_IP_ADDRESS', 4); + +/** The NAS-Port attribute. The attribute value is expected to be the physical port of the user on the RADIUS client encoded as an integer, which can be set using {@see radius_put_int()}. */ +define('RADIUS_NAS_PORT', 5); + +/** + * The Service-Type attribute. The attribute value indicates the service type the user is requesting, and is expected to be an integer, which can be set using {@see radius_put_int()}. + * A number of constants are provided to represent the possible values of this attribute. They include: + * - RADIUS_LOGIN + * - RADIUS_FRAMED + * - RADIUS_CALLBACK_LOGIN + * - RADIUS_CALLBACK_FRAMED + * - RADIUS_OUTBOUND + * - RADIUS_ADMINISTRATIVE + * - RADIUS_NAS_PROMPT + * - RADIUS_AUTHENTICATE_ONLY + * - RADIUS_CALLBACK_NAS_PROMPT + */ +define('RADIUS_SERVICE_TYPE', 6); +define('RADIUS_LOGIN', 1); +define('RADIUS_FRAMED', 2); +define('RADIUS_CALLBACK_LOGIN', 3); +define('RADIUS_CALLBACK_FRAMED', 4); +define('RADIUS_OUTBOUND', 5); +define('RADIUS_ADMINISTRATIVE', 6); +define('RADIUS_NAS_PROMPT', 7); +define('RADIUS_AUTHENTICATE_ONLY', 8); +define('RADIUS_CALLBACK_NAS_PROMPT', 9); + +/** + * The Framed-Protocol attribute. The attribute value is expected to be an integer indicating the framing to be used for framed access, and can be set using {@see radius_put_int()}. The possible attribute values include these constants: + * - RADIUS_PPP + * - RADIUS_SLIP + * - RADIUS_ARAP + * - RADIUS_GANDALF + * - RADIUS_XYLOGICS + */ +define('RADIUS_FRAMED_PROTOCOL', 7); +define('RADIUS_PPP', 1); +define('RADIUS_SLIP', 2); +define('RADIUS_ARAP', 3); +define('RADIUS_GANDALF', 4); +define('RADIUS_XYLOGICS', 5); + +/** The Framed-IP-Address attribute. The attribute value is expected to be the address of the user's network encoded as an integer, which can be set using {@see radius_put_addr()} and retrieved using {@see radius_cvt_addr()}. */ +define('RADIUS_FRAMED_IP_ADDRESS', 8); + +/** The Framed-IP-Netmask attribute. The attribute value is expected to be the netmask of the user's network encoded as an integer, which can be set using {@see radius_put_addr()} and retrieved using {@see radius_cvt_addr()}. */ +define('RADIUS_FRAMED_IP_NETMASK', 9); + +/** + * The Framed-Routing attribute. The attribute value is expected to be an integer indicating the routing method for the user, which can be set using {@see radius_put_int()}.
    + *
    + * Possible values include: + * - 0: No routing + * - 1: Send routing packets + * - 2: Listen for routing packets + * - 3: Send and listen + */ +define('RADIUS_FRAMED_ROUTING', 10); + +/** The Filter-ID attribute. The attribute value is expected to be an implementation-specific, human-readable string of filters, which can be set using {@see radius_put_attr()}.*/ +define('RADIUS_FILTER_ID', 11); + +/** The Framed-MTU attribute. The attribute value is expected to be an integer indicating the MTU to be configured for the user, and can be set using {@see radius_put_int()}.*/ +define('RADIUS_FRAMED_MTU', 12); + +/** The Framed-Compression attribute. The attribute value is expected to be an integer indicating the compression protocol to be used, and can be set using radius_put_int(). Possible values include these constants: + * - RADIUS_COMP_NONE: No compression + * - RADIUS_COMP_VJ: VJ TCP/IP header compression + * - RADIUS_COMP_IPXHDR: IPX header compression + * - RADIUS_COMP_STAC_LZS: Stac-LZS compression (added in PECL radius 1.3.0b2) + */ +define('RADIUS_FRAMED_COMPRESSION', 13); +define('RADIUS_COMP_NONE', 0); +define('RADIUS_COMP_VJ', 1); +define('RADIUS_COMP_IPXHDR', 2); + +/** The Login-IP-Host attribute. The attribute value is expected to the IP address to connect the user to, encoded as an integer, which can be set using {@see radius_put_addr()}. */ +define('RADIUS_LOGIN_IP_HOST', 14); + +/** The Login-Service attribute. The attribute value is an integer indicating the service to connect the user to on the login host. The value can be converted to a PHP integer via {@see radius_cvt_int()}.*/ +define('RADIUS_LOGIN_SERVICE', 15); +define('RADIUS_LOGIN_TCP_PORT', 16); +define('RADIUS_REPLY_MESSAGE', 18); +define('RADIUS_CALLBACK_NUMBER', 19); +define('RADIUS_CALLBACK_ID', 20); +define('RADIUS_FRAMED_ROUTE', 22); +define('RADIUS_FRAMED_IPX_NETWORK', 23); +define('RADIUS_STATE', 24); +define('RADIUS_CLASS', 25); +define('RADIUS_VENDOR_SPECIFIC', 26); +define('RADIUS_SESSION_TIMEOUT', 27); +define('RADIUS_IDLE_TIMEOUT', 28); +define('RADIUS_TERMINATION_ACTION', 29); +define('RADIUS_CALLED_STATION_ID', 30); +define('RADIUS_CALLING_STATION_ID', 31); +define('RADIUS_NAS_IDENTIFIER', 32); +define('RADIUS_PROXY_STATE', 33); +define('RADIUS_LOGIN_LAT_SERVICE', 34); +define('RADIUS_LOGIN_LAT_NODE', 35); +define('RADIUS_LOGIN_LAT_GROUP', 36); +define('RADIUS_FRAMED_APPLETALK_LINK', 37); +define('RADIUS_FRAMED_APPLETALK_NETWORK', 38); +define('RADIUS_FRAMED_APPLETALK_ZONE', 39); +define('RADIUS_CHAP_CHALLENGE', 60); +define('RADIUS_NAS_PORT_TYPE', 61); +define('RADIUS_ASYNC', 0); +define('RADIUS_SYNC', 1); +define('RADIUS_ISDN_SYNC', 2); +define('RADIUS_ISDN_ASYNC_V120', 3); +define('RADIUS_ISDN_ASYNC_V110', 4); +define('RADIUS_VIRTUAL', 5); +define('RADIUS_PIAFS', 6); +define('RADIUS_HDLC_CLEAR_CHANNEL', 7); +define('RADIUS_X_25', 8); +define('RADIUS_X_75', 9); +define('RADIUS_G_3_FAX', 10); +define('RADIUS_SDSL', 11); +define('RADIUS_ADSL_CAP', 12); +define('RADIUS_ADSL_DMT', 13); +define('RADIUS_IDSL', 14); +define('RADIUS_ETHERNET', 15); +define('RADIUS_XDSL', 16); +define('RADIUS_CABLE', 17); +define('RADIUS_WIRELESS_OTHER', 18); +define('RADIUS_WIRELESS_IEEE_802_11', 19); +define('RADIUS_PORT_LIMIT', 62); +define('RADIUS_LOGIN_LAT_PORT', 63); +define('RADIUS_CONNECT_INFO', 77); +define('RADIUS_NAS_IPV6_ADDRESS', 95); +define('RADIUS_FRAMED_INTERFACE_ID', 96); +define('RADIUS_FRAMED_IPV6_PREFIX', 97); +define('RADIUS_LOGIN_IPV6_HOST', 98); +define('RADIUS_FRAMED_IPV6_ROUTE', 99); +define('RADIUS_FRAMED_IPV6_POOL', 100); +define('RADIUS_ERROR_CAUSE', 101); +define('RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_CONTEXT_REMOVED', 201); +define('RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET', 202); +define('RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE', 401); +define('RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE', 402); +define('RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH', 403); +define('RADIUS_ERROR_CAUSE_INVALID_REQUEST', 404); +define('RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE', 405); +define('RADIUS_ERROR_CAUSE_UNSUPPORTED_EXCEPTION', 406); +define('RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED', 501); +define('RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE', 502); +define('RADIUS_ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND', 503); +define('RADIUS_ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE', 504); +define('RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR', 505); +define('RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE', 506); +define('RADIUS_ERROR_CAUSE_REQUEST_INITIATED', 507); +define('RADIUS_ACCT_STATUS_TYPE', 40); +define('RADIUS_START', 1); +define('RADIUS_STOP', 2); +define('RADIUS_ACCOUNTING_ON', 7); +define('RADIUS_ACCOUNTING_OFF', 8); +define('RADIUS_ACCT_DELAY_TIME', 41); +define('RADIUS_ACCT_INPUT_OCTETS', 42); +define('RADIUS_ACCT_OUTPUT_OCTETS', 43); +define('RADIUS_ACCT_SESSION_ID', 44); +define('RADIUS_ACCT_AUTHENTIC', 45); +define('RADIUS_AUTH_RADIUS', 1); +define('RADIUS_AUTH_LOCAL', 2); +define('RADIUS_AUTH_REMOTE', 3); +define('RADIUS_ACCT_SESSION_TIME', 46); +define('RADIUS_ACCT_INPUT_PACKETS', 47); +define('RADIUS_ACCT_OUTPUT_PACKETS', 48); +define('RADIUS_ACCT_TERMINATE_CAUSE', 49); +define('RADIUS_TERM_USER_REQUEST', 1); +define('RADIUS_TERM_LOST_CARRIER', 2); +define('RADIUS_TERM_LOST_SERVICE', 3); +define('RADIUS_TERM_IDLE_TIMEOUT', 4); +define('RADIUS_TERM_SESSION_TIMEOUT', 5); +define('RADIUS_TERM_ADMIN_RESET', 6); +define('RADIUS_TERM_ADMIN_REBOOT', 7); +define('RADIUS_TERM_PORT_ERROR', 8); +define('RADIUS_TERM_NAS_ERROR', 9); +define('RADIUS_TERM_NAS_REQUEST', 10); +define('RADIUS_TERM_NAS_REBOOT', 11); +define('RADIUS_TERM_PORT_UNNEEDED', 12); +define('RADIUS_TERM_PORT_PREEMPTED', 13); +define('RADIUS_TERM_PORT_SUSPENDED', 14); +define('RADIUS_TERM_SERVICE_UNAVAILABLE', 15); +define('RADIUS_TERM_CALLBACK', 16); +define('RADIUS_TERM_USER_ERROR', 17); +define('RADIUS_TERM_HOST_REQUEST', 18); +define('RADIUS_ACCT_MULTI_SESSION_ID', 50); +define('RADIUS_ACCT_LINK_COUNT', 51); +define('RADIUS_VENDOR_MICROSOFT', 311); +define('RADIUS_MICROSOFT_MS_CHAP_RESPONSE', 1); +define('RADIUS_MICROSOFT_MS_CHAP_ERROR', 2); +define('RADIUS_MICROSOFT_MS_CHAP_PW_1', 3); +define('RADIUS_MICROSOFT_MS_CHAP_PW_2', 4); +define('RADIUS_MICROSOFT_MS_CHAP_LM_ENC_PW', 5); +define('RADIUS_MICROSOFT_MS_CHAP_NT_ENC_PW', 6); +define('RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY', 7); +define('RADIUS_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES', 8); +define('RADIUS_MICROSOFT_MS_RAS_VENDOR', 9); +define('RADIUS_MICROSOFT_MS_CHAP_DOMAIN', 10); +define('RADIUS_MICROSOFT_MS_CHAP_CHALLENGE', 11); +define('RADIUS_MICROSOFT_MS_CHAP_MPPE_KEYS', 12); +define('RADIUS_MICROSOFT_MS_BAP_USAGE', 13); +define('RADIUS_MICROSOFT_MS_LINK_UTILIZATION_THRESHOLD', 14); +define('RADIUS_MICROSOFT_MS_LINK_DROP_TIME_LIMIT', 15); +define('RADIUS_MICROSOFT_MS_MPPE_SEND_KEY', 16); +define('RADIUS_MICROSOFT_MS_MPPE_RECV_KEY', 17); +define('RADIUS_MICROSOFT_MS_RAS_VERSION', 18); +define('RADIUS_MICROSOFT_MS_OLD_ARAP_PASSWORD', 19); +define('RADIUS_MICROSOFT_MS_NEW_ARAP_PASSWORD', 20); +define('RADIUS_MICROSOFT_MS_ARAP_PASSWORD_CHANGE_REASON', 21); +define('RADIUS_MICROSOFT_MS_FILTER', 22); +define('RADIUS_MICROSOFT_MS_ACCT_AUTH_TYPE', 23); +define('RADIUS_MICROSOFT_MS_ACCT_EAP_TYPE', 24); +define('RADIUS_MICROSOFT_MS_CHAP2_RESPONSE', 25); +define('RADIUS_MICROSOFT_MS_CHAP2_SUCCESS', 26); +define('RADIUS_MICROSOFT_MS_CHAP2_PW', 27); +define('RADIUS_MICROSOFT_MS_PRIMARY_DNS_SERVER', 28); +define('RADIUS_MICROSOFT_MS_SECONDARY_DNS_SERVER', 29); +define('RADIUS_MICROSOFT_MS_PRIMARY_NBNS_SERVER', 30); +define('RADIUS_MICROSOFT_MS_SECONDARY_NBNS_SERVER', 31); +define('RADIUS_MICROSOFT_MS_ARAP_CHALLENGE', 33); +define('RADIUS_OPTION_NONE', RADIUS_OPTION_NONE); +define('RADIUS_OPTION_TAGGED', RADIUS_OPTION_TAGGED); +define('RADIUS_OPTION_SALT', RADIUS_OPTION_SALT); + +/** + * Creates a Radius handle for accounting + * @link https://secure.php.net/manual/en/function.radius-acct-open.php + * @return resource|bool Returns a handle on success, FALSE on error. This function only fails if insufficient memory is available. + * @since 1.1.0 + */ +function radius_acct_open() +{ +} + +/** + * radius_add_server() may be called multiple times, and it may be used together with {@see radius_config()}. At most 10 servers may be specified. When multiple servers are given, they are tried in round-robin fashion until a valid response is received, or until each server's max_tries limit has been reached. + * @link https://secure.php.net/manual/en/function.radius-add-server.php + * @param resource $radius_handle + * @param string $hostname The hostname parameter specifies the server host, either as a fully qualified domain name or as a dotted-quad IP address in text form. + * @param int $port The port specifies the UDP port to contact on the server.
    + * If port is given as 0, the library looks up the radius/udp or radacct/udp service in the network services database, and uses the port found there.
    + * If no entry is found, the library uses the standard Radius ports, 1812 for authentication and 1813 for accounting. + * @param string $secret The shared secret for the server host is passed to the secret parameter. The Radius protocol ignores all but the leading 128 bytes of the shared secret. + * @param int $timeout The timeout for receiving replies from the server is passed to the timeout parameter, in units of seconds. + * @param int $max_tries The maximum number of repeated requests to make before giving up is passed into the max_tries. + * @return bool Returns TRUE on success or FALSE on failure. + * @see radius_config() + * @since 1.1.0 + */ +function radius_add_server($radius_handle, $hostname, $port, $secret, $timeout, $max_tries) +{ +} + +/** + * Creates a Radius handle for authentication + * @link https://secure.php.net/manual/en/function.radius-auth-open.php + * @return resource|bool Returns a handle on success, FALSE on error. This function only fails if insufficient memory is available. + * @since 1.1.0 + */ +function radius_auth_open() +{ +} + +/** + * Free all ressources. It is not needed to call this function because php frees all resources at the end of each request. + * @link https://secure.php.net/manual/en/function.radius-close.php + * @param resource $radius_handle + * @return bool Returns TRUE on success or FALSE on failure. + * @since 1.1.0 + */ +function radius_close($radius_handle) +{ +} + +/** + * Before issuing any Radius requests, the library must be made aware of the servers it can contact. The easiest way to configure the library is to call radius_config(). radius_config() causes the library to read a configuration file whose format is described in radius.conf. + * @link https://secure.php.net/manual/en/function.radius-config.php + * @link https://www.freebsd.org/cgi/man.cgi?query=radius.conf + * @param resource $radius_handle + * @param string $file The pathname of the configuration file is passed as the file argument to {@see radius_config()}. The library can also be configured programmatically by calls to {@see radius_add_server()}. + * @return bool Returns TRUE on success or FALSE on failure. + * @see radius_add_server() + * @since 1.1.0 + */ +function radius_config($radius_handle, $file) +{ +} + +/** + * A Radius request consists of a code specifying the kind of request, and zero or more attributes which provide additional information. To begin constructing a new request, call radius_create_request().
    + * Note: Attention: You must call this function, before you can put any attribute! + * @link https://secure.php.net/manual/en/function.radius-create-request.php + * @param resource $radius_handle + * @param int $type Type is RADIUS_ACCESS_REQUEST or RADIUS_ACCOUNTING_REQUEST. + * @return bool Returns TRUE on success or FALSE on failure. + * @see radius_send_request() + * @since 1.1.0 + */ +function radius_create_request($radius_handle, $type) +{ +} + +/** + * Extracts a vendor specific attribute + * @param string $data + * @return array|false + * @since 1.1.0 + */ +function radius_get_vendor_attr($data) +{ +} + +/** + * Attaches a binary attribute + * @param resource $radius_handle + * @param int $type + * @param string $value + * @param int $options + * @param int $tag + * @return bool + * @since 1.1.0 + */ +function radius_put_attr(resource $radius_handle, $type, $value, $options = 0, $tag = null) +{ +} + +/** + * Extracts an attribute + * @param resource $radius_handle + * @return mixed + * @since 1.1.0 + */ +function radius_get_attr($radius_handle) +{ +} + +/** + * Returns an error message + * @param resource $radius_handle + * @return string + * @since 1.1.0 + */ +function radius_strerror(resource $radius_handle) +{ +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/soap.php b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/soap.php new file mode 100644 index 000000000..b2a29c79e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/simplesamlphp-test-framework/stubs/soap.php @@ -0,0 +1,882 @@ + + * URI of the WSDL file or NULL if working in + * non-WSDL mode. + *

    + *

    + * During development, WSDL caching may be disabled by the + * use of the soap.wsdl_cache_ttl php.ini setting + * otherwise changes made to the WSDL file will have no effect until + * soap.wsdl_cache_ttl is expired. + *

    + * @param array $options [optional]

    + * An array of options. If working in WSDL mode, this parameter is optional. + * If working in non-WSDL mode, the location and + * uri options must be set, where location + * is the URL of the SOAP server to send the request to, and uri + * is the target namespace of the SOAP service. + *

    + *

    + * The style and use options only work in + * non-WSDL mode. In WSDL mode, they come from the WSDL file. + *

    + *

    + * The soap_version option should be one of either + * SOAP_1_1 or SOAP_1_2 to + * select SOAP 1.1 or 1.2, respectively. If omitted, 1.1 is used. + *

    + *

    + * For HTTP authentication, the login and + * password options can be used to supply credentials. + * For making an HTTP connection through + * a proxy server, the options proxy_host, + * proxy_port, proxy_login + * and proxy_password are also available. + * For HTTPS client certificate authentication use + * local_cert and passphrase options. An + * authentication may be supplied in the authentication + * option. The authentication method may be either + * SOAP_AUTHENTICATION_BASIC (default) or + * SOAP_AUTHENTICATION_DIGEST. + *

    + *

    + * The compression option allows to use compression + * of HTTP SOAP requests and responses. + *

    + *

    + * The encoding option defines internal character + * encoding. This option does not change the encoding of SOAP requests (it is + * always utf-8), but converts strings into it. + *

    + *

    + * The trace option enables tracing of request so faults + * can be backtraced. This defaults to FALSE + *

    + *

    + * The classmap option can be used to map some WSDL + * types to PHP classes. This option must be an array with WSDL types + * as keys and names of PHP classes as values. + *

    + *

    + * Setting the boolean trace option enables use of the + * methods + * SoapClient->__getLastRequest, + * SoapClient->__getLastRequestHeaders, + * SoapClient->__getLastResponse and + * SoapClient->__getLastResponseHeaders. + *

    + *

    + * The exceptions option is a boolean value defining whether + * soap errors throw exceptions of type + * SoapFault. + *

    + *

    + * The connection_timeout option defines a timeout in seconds + * for the connection to the SOAP service. This option does not define a timeout + * for services with slow responses. To limit the time to wait for calls to finish the + * default_socket_timeout setting + * is available. + *

    + *

    + * The typemap option is an array of type mappings. + * Type mapping is an array with keys type_name, + * type_ns (namespace URI), from_xml + * (callback accepting one string parameter) and to_xml + * (callback accepting one object parameter). + *

    + *

    + * The cache_wsdl option is one of + * WSDL_CACHE_NONE, + * WSDL_CACHE_DISK, + * WSDL_CACHE_MEMORY or + * WSDL_CACHE_BOTH. + *

    + *

    + * The user_agent option specifies string to use in + * User-Agent header. + *

    + *

    + * The stream_context option is a resource + * for context. + *

    + *

    + * The features option is a bitmask of + * SOAP_SINGLE_ELEMENT_ARRAYS, + * SOAP_USE_XSI_ARRAY_TYPE, + * SOAP_WAIT_ONE_WAY_CALLS. + *

    + *

    + * The keep_alive option is a boolean value defining whether + * to send the Connection: Keep-Alive header or + * Connection: close. + *

    + *

    + * The ssl_method option is one of + * SOAP_SSL_METHOD_TLS, + * SOAP_SSL_METHOD_SSLv2, + * SOAP_SSL_METHOD_SSLv3 or + * SOAP_SSL_METHOD_SSLv23. + *

    + * @since 5.0.1 + */ + public function SoapClient ($wsdl, array $options = null) {} + + /** + * SoapClient constructor + * @link http://php.net/manual/en/soapclient.soapclient.php + * @param mixed $wsdl

    + * URI of the WSDL file or NULL if working in + * non-WSDL mode. + *

    + *

    + * During development, WSDL caching may be disabled by the + * use of the soap.wsdl_cache_ttl php.ini setting + * otherwise changes made to the WSDL file will have no effect until + * soap.wsdl_cache_ttl is expired. + *

    + * @param array $options [optional]

    + * An array of options. If working in WSDL mode, this parameter is optional. + * If working in non-WSDL mode, the location and + * uri options must be set, where location + * is the URL of the SOAP server to send the request to, and uri + * is the target namespace of the SOAP service. + *

    + *

    + * The style and use options only work in + * non-WSDL mode. In WSDL mode, they come from the WSDL file. + *

    + *

    + * The soap_version option should be one of either + * SOAP_1_1 or SOAP_1_2 to + * select SOAP 1.1 or 1.2, respectively. If omitted, 1.1 is used. + *

    + *

    + * For HTTP authentication, the login and + * password options can be used to supply credentials. + * For making an HTTP connection through + * a proxy server, the options proxy_host, + * proxy_port, proxy_login + * and proxy_password are also available. + * For HTTPS client certificate authentication use + * local_cert and passphrase options. An + * authentication may be supplied in the authentication + * option. The authentication method may be either + * SOAP_AUTHENTICATION_BASIC (default) or + * SOAP_AUTHENTICATION_DIGEST. + *

    + *

    + * The compression option allows to use compression + * of HTTP SOAP requests and responses. + *

    + *

    + * The encoding option defines internal character + * encoding. This option does not change the encoding of SOAP requests (it is + * always utf-8), but converts strings into it. + *

    + *

    + * The trace option enables tracing of request so faults + * can be backtraced. This defaults to FALSE + *

    + *

    + * The classmap option can be used to map some WSDL + * types to PHP classes. This option must be an array with WSDL types + * as keys and names of PHP classes as values. + *

    + *

    + * Setting the boolean trace option enables use of the + * methods + * SoapClient->__getLastRequest, + * SoapClient->__getLastRequestHeaders, + * SoapClient->__getLastResponse and + * SoapClient->__getLastResponseHeaders. + *

    + *

    + * The exceptions option is a boolean value defining whether + * soap errors throw exceptions of type + * SoapFault. + *

    + *

    + * The connection_timeout option defines a timeout in seconds + * for the connection to the SOAP service. This option does not define a timeout + * for services with slow responses. To limit the time to wait for calls to finish the + * default_socket_timeout setting + * is available. + *

    + *

    + * The typemap option is an array of type mappings. + * Type mapping is an array with keys type_name, + * type_ns (namespace URI), from_xml + * (callback accepting one string parameter) and to_xml + * (callback accepting one object parameter). + *

    + *

    + * The cache_wsdl option is one of + * WSDL_CACHE_NONE, + * WSDL_CACHE_DISK, + * WSDL_CACHE_MEMORY or + * WSDL_CACHE_BOTH. + *

    + *

    + * The user_agent option specifies string to use in + * User-Agent header. + *

    + *

    + * The stream_context option is a resource + * for context. + *

    + *

    + * The features option is a bitmask of + * SOAP_SINGLE_ELEMENT_ARRAYS, + * SOAP_USE_XSI_ARRAY_TYPE, + * SOAP_WAIT_ONE_WAY_CALLS. + *

    + *

    + * The keep_alive option is a boolean value defining whether + * to send the Connection: Keep-Alive header or + * Connection: close. + *

    + *

    + * The ssl_method option is one of + * SOAP_SSL_METHOD_TLS, + * SOAP_SSL_METHOD_SSLv2, + * SOAP_SSL_METHOD_SSLv3 or + * SOAP_SSL_METHOD_SSLv23. + *

    + * @since 5.0.1 + */ + public function __construct ($wsdl, array $options = null) {} + + /** + * Calls a SOAP function (deprecated) + * @link http://php.net/manual/en/soapclient.call.php + * @param string $function_name + * @param array $arguments + * @return mixed + * @since 5.0.1 + */ + public function __call ($function_name, $arguments) {} + + /** + * Calls a SOAP function + * @link http://php.net/manual/en/soapclient.soapcall.php + * @param string $function_name

    + * The name of the SOAP function to call. + *

    + * @param array $arguments

    + * An array of the arguments to pass to the function. This can be either + * an ordered or an associative array. Note that most SOAP servers require + * parameter names to be provided, in which case this must be an + * associative array. + *

    + * @param array $options [optional]

    + * An associative array of options to pass to the client. + *

    + *

    + * The location option is the URL of the remote Web service. + *

    + *

    + * The uri option is the target namespace of the SOAP service. + *

    + *

    + * The soapaction option is the action to call. + *

    + * @param mixed $input_headers [optional]

    + * An array of headers to be sent along with the SOAP request. + *

    + * @param array $output_headers [optional]

    + * If supplied, this array will be filled with the headers from the SOAP response. + *

    + * @return mixed SOAP functions may return one, or multiple values. If only one value is returned + * by the SOAP function, the return value of __soapCall will be + * a simple value (e.g. an integer, a string, etc). If multiple values are + * returned, __soapCall will return + * an associative array of named output parameters. + *

    + *

    + * On error, if the SoapClient object was constructed with the exceptions + * option set to FALSE, a SoapFault object will be returned. + * @since 5.0.1 + */ + public function __soapCall ($function_name, array $arguments, array $options = null, $input_headers = null, array &$output_headers = null) {} + + /** + * Returns last SOAP request + * @link http://php.net/manual/en/soapclient.getlastrequest.php + * @return string The last SOAP request, as an XML string. + * @since 5.0.1 + */ + public function __getLastRequest () {} + + /** + * Returns last SOAP response + * @link http://php.net/manual/en/soapclient.getlastresponse.php + * @return string The last SOAP response, as an XML string. + * @since 5.0.1 + */ + public function __getLastResponse () {} + + /** + * Returns the SOAP headers from the last request + * @link http://php.net/manual/en/soapclient.getlastrequestheaders.php + * @return string The last SOAP request headers. + * @since 5.0.1 + */ + public function __getLastRequestHeaders () {} + + /** + * Returns the SOAP headers from the last response + * @link http://php.net/manual/en/soapclient.getlastresponseheaders.php + * @return string The last SOAP response headers. + * @since 5.0.1 + */ + public function __getLastResponseHeaders () {} + + /** + * Returns list of available SOAP functions + * @link http://php.net/manual/en/soapclient.getfunctions.php + * @return array The array of SOAP function prototypes, detailing the return type, + * the function name and type-hinted paramaters. + * @since 5.0.1 + */ + public function __getFunctions () {} + + /** + * Returns a list of SOAP types + * @link http://php.net/manual/en/soapclient.gettypes.php + * @return array The array of SOAP types, detailing all structures and types. + * @since 5.0.1 + */ + public function __getTypes () {} + + /** + * Performs a SOAP request + * @link http://php.net/manual/en/soapclient.dorequest.php + * @param string $request

    + * The XML SOAP request. + *

    + * @param string $location

    + * The URL to request. + *

    + * @param string $action

    + * The SOAP action. + *

    + * @param int $version

    + * The SOAP version. + *

    + * @param int $one_way [optional]

    + * If one_way is set to 1, this method returns nothing. + * Use this where a response is not expected. + *

    + * @return string The XML SOAP response. + * @since 5.0.1 + */ + public function __doRequest ($request, $location, $action, $version, $one_way = 0) {} + + /** + * The __setCookie purpose + * @link http://php.net/manual/en/soapclient.setcookie.php + * @param string $name

    + * The name of the cookie. + *

    + * @param string $value [optional]

    + * The value of the cookie. If not specified, the cookie will be deleted. + *

    + * @return void No value is returned. + * @since 5.0.4 + */ + public function __setCookie ($name, $value = null) {} + + /** + * Sets the location of the Web service to use + * @link http://php.net/manual/en/soapclient.setlocation.php + * @param string $new_location [optional]

    + * The new endpoint URL. + *

    + * @return string The old endpoint URL. + * @since 5.0.1 + */ + public function __setLocation ($new_location = null) {} + + /** + * Sets SOAP headers for subsequent calls + * @link http://php.net/manual/en/soapclient.setsoapheaders.php + * @param mixed $soapheaders [optional]

    + * The headers to be set. It could be SoapHeader + * object or array of SoapHeader objects. + * If not specified or set to NULL, the headers will be deleted. + *

    + * @return bool TRUE on success or FALSE on failure. + * @since 5.0.5 + */ + public function __setSoapHeaders ($soapheaders = null) {} + +} + +/** + * A class representing a variable or object for use with SOAP services. + * @link http://php.net/manual/en/class.soapvar.php + */ +class SoapVar { + + /** + * SoapVar constructor + * @link http://php.net/manual/en/soapvar.soapvar.php + * @param mixed $data

    + * The data to pass or return. + *

    + * @param string $encoding

    + * The encoding ID, one of the XSD_... constants. + *

    + * @param string $type_name [optional]

    + * The type name. + *

    + * @param string $type_namespace [optional]

    + * The type namespace. + *

    + * @param string $node_name [optional]

    + * The XML node name. + *

    + * @param string $node_namespace [optional]

    + * The XML node namespace. + *

    + * @since 5.0.1 + */ + public function SoapVar ($data, $encoding, $type_name = null, $type_namespace = null, $node_name = null, $node_namespace = null) {} + +} + +/** + * The SoapServer class provides a server for the SOAP 1.1 and SOAP 1.2 protocols. It can be used with or without a WSDL service description. + * @link http://php.net/manual/en/class.soapserver.php + */ +class SoapServer { + + /** + * SoapServer constructor + * @link http://php.net/manual/en/soapserver.soapserver.php + * @param mixed $wsdl

    + * To use the SoapServer in WSDL mode, pass the URI of a WSDL file. + * Otherwise, pass NULL and set the uri option to the + * target namespace for the server. + *

    + * @param array $options [optional]

    + * Allow setting a default SOAP version (soap_version), + * internal character encoding (encoding), + * and actor URI (actor). + *

    + *

    + * The classmap option can be used to map some WSDL + * types to PHP classes. This option must be an array with WSDL types + * as keys and names of PHP classes as values. + *

    + *

    + * The typemap option is an array of type mappings. + * Type mapping is an array with keys type_name, + * type_ns (namespace URI), from_xml + * (callback accepting one string parameter) and to_xml + * (callback accepting one object parameter). + *

    + *

    + * The cache_wsdl option is one of + * WSDL_CACHE_NONE, + * WSDL_CACHE_DISK, + * WSDL_CACHE_MEMORY or + * WSDL_CACHE_BOTH. + *

    + *

    + * There is also a features option which can be set to + * SOAP_WAIT_ONE_WAY_CALLS, + * SOAP_SINGLE_ELEMENT_ARRAYS, + * SOAP_USE_XSI_ARRAY_TYPE. + *

    + * @since 5.0.1 + */ + public function SoapServer ($wsdl, array $options = null) {} + + /** + * Sets SoapServer persistence mode + * @link http://php.net/manual/en/soapserver.setpersistence.php + * @param int $mode

    + * One of the SOAP_PERSISTENCE_XXX constants. + *

    + *

    + * SOAP_PERSISTENCE_REQUEST - SoapServer data does not persist between + * requests. This is the default behavior of any SoapServer + * object after setClass is called. + *

    + *

    + * SOAP_PERSISTENCE_SESSION - SoapServer data persists between requests. + * This is accomplished by serializing the SoapServer class data into + * $_SESSION['_bogus_session_name'], because of this + * session_start must be called before this persistence mode is set. + *

    + * @return void No value is returned. + * @since 5.1.2 + */ + public function setPersistence ($mode) {} + + /** + * Sets the class which handles SOAP requests + * @link http://php.net/manual/en/soapserver.setclass.php + * @param string $class_name

    + * The name of the exported class. + *

    + * @param mixed $args [optional]

    + * These optional parameters will be passed to the default class constructor + * during object creation. + *

    + * @param mixed $_ [optional] + * @return void No value is returned. + * @since 5.0.1 + */ + public function setClass ($class_name, $args = null, $_ = null) {} + + /** + * Sets the object which will be used to handle SOAP requests + * @link http://php.net/manual/en/soapserver.setobject.php + * @param object $object

    + * The object to handle the requests. + *

    + * @return void No value is returned. + * @since 5.2.0 + */ + public function setObject ($object) {} + + /** + * Adds one or more functions to handle SOAP requests + * @link http://php.net/manual/en/soapserver.addfunction.php + * @param mixed $functions

    + * To export one function, pass the function name into this parameter as + * a string. + *

    + *

    + * To export several functions, pass an array of function names. + *

    + *

    + * To export all the functions, pass a special constant SOAP_FUNCTIONS_ALL. + *

    + *

    + * functions must receive all input arguments in the same + * order as defined in the WSDL file (They should not receive any output parameters + * as arguments) and return one or more values. To return several values they must + * return an array with named output parameters. + *

    + * @return void No value is returned. + * @since 5.0.1 + */ + public function addFunction ($functions) {} + + /** + * Returns list of defined functions + * @link http://php.net/manual/en/soapserver.getfunctions.php + * @return array An array of the defined functions. + * @since 5.0.1 + */ + public function getFunctions () {} + + /** + * Handles a SOAP request + * @link http://php.net/manual/en/soapserver.handle.php + * @param string $soap_request [optional]

    + * The SOAP request. If this argument is omitted, the request is assumed to be + * in the raw POST data of the HTTP request. + *

    + * @return void No value is returned. + * @since 5.0.1 + */ + public function handle ($soap_request = null) {} + + /** + * Issue SoapServer fault indicating an error + * @link http://php.net/manual/en/soapserver.fault.php + * @param string $code

    + * The error code to return + *

    + * @param string $string

    + * A brief description of the error + *

    + * @param string $actor [optional]

    + * A string identifying the actor that caused the fault. + *

    + * @param string $details [optional]

    + * More details of the fault + *

    + * @param string $name [optional]

    + * The name of the fault. This can be used to select a name from a WSDL file. + *

    + * @return void No value is returned. + * @since 5.0.1 + */ + public function fault ($code, $string, $actor = null, $details = null, $name = null) {} + + /** + * Add a SOAP header to the response + * @link http://php.net/manual/en/soapserver.addsoapheader.php + * @param SoapHeader $object

    + * The header to be returned. + *

    + * @return void No value is returned. + * @since 5.0.1 + */ + public function addSoapHeader (SoapHeader $object) {} + +} + +/** + * Represents a SOAP fault. + * @link http://php.net/manual/en/class.soapfault.php + */ +class SoapFault extends Exception { + /** + * @var string + */ + public $faultcode; + /** + * @var string + */ + public $faultstring; + /** + * @var string + */ + public $faultactor; + /** + * @var mixed + */ + public $detail; + /** + * @var string + */ + public $faultname; + /** + * @var mixed + */ + public $headerfault; + + /** + * SoapFault constructor + * @link http://php.net/manual/en/soapfault.soapfault.php + * @param string $faultcode

    + * The error code of the SoapFault. + *

    + * @param string $faultstring

    + * The error message of the SoapFault. + *

    + * @param string $faultactor [optional]

    + * A string identifying the actor that caused the error. + *

    + * @param mixed $detail [optional]

    + * More details about the cause of the error. + *

    + * @param string $faultname [optional]

    + * Can be used to select the proper fault encoding from WSDL. + *

    + * @param mixed $headerfault [optional]

    + * Can be used during SOAP header handling to report an error in the + * response header. + *

    + * @since 5.0.1 + */ + public function SoapFault ($faultcode, $faultstring, $faultactor = null, $detail = null, $faultname = null, $headerfault = null) {} + + /** + * Obtain a string representation of a SoapFault + * @link http://php.net/manual/en/soapfault.tostring.php + * @return string A string describing the SoapFault. + * @since 5.0.1 + */ + public function __toString () {} + + +} + +/** + * Represents parameter to a SOAP call. + * @link http://php.net/manual/en/class.soapparam.php + */ +class SoapParam { + + /** + * SoapParam constructor + * @link http://php.net/manual/en/soapparam.soapparam.php + * @param mixed $data

    + * The data to pass or return. This parameter can be passed directly as PHP + * value, but in this case it will be named as paramN and + * the SOAP service may not understand it. + *

    + * @param string $name

    + * The parameter name. + *

    + * @since 5.0.1 + */ + public function SoapParam ($data, $name) {} + +} + +/** + * Represents a SOAP header. + * @link http://php.net/manual/en/class.soapheader.php + */ +class SoapHeader { + + /** + * SoapHeader constructor + * @link http://php.net/manual/en/soapheader.soapheader.php + * @param string $namespace

    + * The namespace of the SOAP header element. + *

    + * @param string $name

    + * The name of the SoapHeader object. + *

    + * @param mixed $data [optional]

    + * A SOAP header's content. It can be a PHP value or a + * SoapVar object. + *

    + * @param bool $mustunderstand [optional] + * @param string $actor [optional]

    + * Value of the actor attribute of the SOAP header + * element. + *

    + * @since 5.0.1 + */ + public function SoapHeader ($namespace, $name, $data = null, $mustunderstand = false, $actor = null) {} + +} + +/** + * Set whether to use the SOAP error handler + * @link http://php.net/manual/en/function.use-soap-error-handler.php + * @param bool $handler [optional]

    + * Set to TRUE to send error details to clients. + *

    + * @return bool the original value. + */ +function use_soap_error_handler ($handler = true) {} + +/** + * Checks if a SOAP call has failed + * @link http://php.net/manual/en/function.is-soap-fault.php + * @param mixed $object

    + * The object to test. + *

    + * @return bool This will return TRUE on error, and FALSE otherwise. + */ +function is_soap_fault ($object) {} + +define ('SOAP_1_1', 1); +define ('SOAP_1_2', 2); +define ('SOAP_PERSISTENCE_SESSION', 1); +define ('SOAP_PERSISTENCE_REQUEST', 2); +define ('SOAP_FUNCTIONS_ALL', 999); +define ('SOAP_ENCODED', 1); +define ('SOAP_LITERAL', 2); +define ('SOAP_RPC', 1); +define ('SOAP_DOCUMENT', 2); +define ('SOAP_ACTOR_NEXT', 1); +define ('SOAP_ACTOR_NONE', 2); +define ('SOAP_ACTOR_UNLIMATERECEIVER', 3); +define ('SOAP_COMPRESSION_ACCEPT', 32); +define ('SOAP_COMPRESSION_GZIP', 0); +define ('SOAP_COMPRESSION_DEFLATE', 16); +define ('SOAP_AUTHENTICATION_BASIC', 0); +define ('SOAP_AUTHENTICATION_DIGEST', 1); +define ('UNKNOWN_TYPE', 999998); +define ('XSD_STRING', 101); +define ('XSD_BOOLEAN', 102); +define ('XSD_DECIMAL', 103); +define ('XSD_FLOAT', 104); +define ('XSD_DOUBLE', 105); +define ('XSD_DURATION', 106); +define ('XSD_DATETIME', 107); +define ('XSD_TIME', 108); +define ('XSD_DATE', 109); +define ('XSD_GYEARMONTH', 110); +define ('XSD_GYEAR', 111); +define ('XSD_GMONTHDAY', 112); +define ('XSD_GDAY', 113); +define ('XSD_GMONTH', 114); +define ('XSD_HEXBINARY', 115); +define ('XSD_BASE64BINARY', 116); +define ('XSD_ANYURI', 117); +define ('XSD_QNAME', 118); +define ('XSD_NOTATION', 119); +define ('XSD_NORMALIZEDSTRING', 120); +define ('XSD_TOKEN', 121); +define ('XSD_LANGUAGE', 122); +define ('XSD_NMTOKEN', 123); +define ('XSD_NAME', 124); +define ('XSD_NCNAME', 125); +define ('XSD_ID', 126); +define ('XSD_IDREF', 127); +define ('XSD_IDREFS', 128); +define ('XSD_ENTITY', 129); +define ('XSD_ENTITIES', 130); +define ('XSD_INTEGER', 131); +define ('XSD_NONPOSITIVEINTEGER', 132); +define ('XSD_NEGATIVEINTEGER', 133); +define ('XSD_LONG', 134); +define ('XSD_INT', 135); +define ('XSD_SHORT', 136); +define ('XSD_BYTE', 137); +define ('XSD_NONNEGATIVEINTEGER', 138); +define ('XSD_UNSIGNEDLONG', 139); +define ('XSD_UNSIGNEDINT', 140); +define ('XSD_UNSIGNEDSHORT', 141); +define ('XSD_UNSIGNEDBYTE', 142); +define ('XSD_POSITIVEINTEGER', 143); +define ('XSD_NMTOKENS', 144); +define ('XSD_ANYTYPE', 145); +define ('XSD_ANYXML', 147); +define ('APACHE_MAP', 200); +define ('SOAP_ENC_OBJECT', 301); +define ('SOAP_ENC_ARRAY', 300); +define ('XSD_1999_TIMEINSTANT', 401); +define ('XSD_NAMESPACE', "http://www.w3.org/2001/XMLSchema"); +define ('XSD_1999_NAMESPACE', "http://www.w3.org/1999/XMLSchema"); +define ('SOAP_SINGLE_ELEMENT_ARRAYS', 1); +define ('SOAP_WAIT_ONE_WAY_CALLS', 2); +define ('SOAP_USE_XSI_ARRAY_TYPE', 4); +define ('WSDL_CACHE_NONE', 0); +define ('WSDL_CACHE_DISK', 1); +define ('WSDL_CACHE_MEMORY', 2); +define ('WSDL_CACHE_BOTH', 3); + +/** + * @link http://php.net/manual/en/soap.constants.php + * @since 5.5.0 + */ +define ('SOAP_SSL_METHOD_TLS', 0); + +/** + * @link http://php.net/manual/en/soap.constants.php + * @since 5.5.0 + */ +define ('SOAP_SSL_METHOD_SSLv2', 1); + +/** + * @link http://php.net/manual/en/soap.constants.php + * @since 5.5.0 + */ +define ('SOAP_SSL_METHOD_SSLv3', 2); + +/** + * @link http://php.net/manual/en/soap.constants.php + * @since 5.5.0 + */ +define ('SOAP_SSL_METHOD_SSLv23', 3); + +// End of soap v. +?> + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/AbstractElement.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/AbstractElement.php index 83771a0e8..3ab8487b6 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/AbstractElement.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/AbstractElement.php @@ -36,7 +36,7 @@ abstract class AbstractElement implements SerializableElementInterface * @param \DOMElement|null $parent The element we should append to. * @return \DOMElement */ - public function instantiateParentElement(DOMElement $parent = null): DOMElement + public function instantiateParentElement(?DOMElement $parent = null): DOMElement { $qualifiedName = $this->getQualifiedName(); $namespace = static::getNamespaceURI(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Base64ElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Base64ElementTrait.php index e78c52efe..fa47cd9fc 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Base64ElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Base64ElementTrait.php @@ -7,7 +7,6 @@ use DOMElement; use SimpleSAML\Assert\Assert; use SimpleSAML\XML\Exception\SchemaViolationException; -use SimpleSAML\XML\StringElementTrait; use function str_replace; @@ -61,5 +60,5 @@ abstract public static function getLocalName(): string; * @param \DOMElement|null $parent The element we should append to. * @return \DOMElement */ - abstract public function instantiateParentElement(DOMElement $parent = null): DOMElement; + abstract public function instantiateParentElement(?DOMElement $parent = null): DOMElement; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/BooleanElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/BooleanElementTrait.php index fa1ad383d..c74e41925 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/BooleanElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/BooleanElementTrait.php @@ -58,7 +58,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent * @return \DOMElement */ - final public function toXML(DOMElement $parent = null): DOMElement + final public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getContent(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Chunk.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Chunk.php index 6d923240d..32063db43 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Chunk.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Chunk.php @@ -99,7 +99,7 @@ public function getNamespaceURI(): ?string * * @param string|null $namespaceURI */ - protected function setNamespaceURI(string $namespaceURI = null): void + protected function setNamespaceURI(?string $namespaceURI = null): void { Assert::nullOrValidURI($namespaceURI, SchemaViolationException::class); $this->namespaceURI = $namespaceURI; @@ -133,7 +133,7 @@ public function getPrefix(): string * * @param string|null $prefix */ - protected function setPrefix(string $prefix = null): void + protected function setPrefix(?string $prefix = null): void { $this->prefix = strval($prefix); } @@ -304,7 +304,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this element to. * @return \DOMElement The new element. */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { if ($parent === null) { $doc = DOMDocumentFactory::create(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Constants.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Constants.php index 6d6a5dc9a..60712ecc5 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Constants.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/Constants.php @@ -28,6 +28,7 @@ class Constants /** * The maximum amount of child nodes this library is willing to handle. + * By specification, this limit is 150K, but that opens up for denial of service. */ public const UNBOUNDED_LIMIT = 10000; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/DOMDocumentFactory.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/DOMDocumentFactory.php index 9ab2a767c..144748300 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/DOMDocumentFactory.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/DOMDocumentFactory.php @@ -5,15 +5,16 @@ namespace SimpleSAML\XML; use DOMDocument; -use RuntimeException; use SimpleSAML\Assert\Assert; use SimpleSAML\XML\Exception\IOException; +use SimpleSAML\XML\Exception\RuntimeException; use SimpleSAML\XML\Exception\UnparseableXMLException; -use function defined; use function file_get_contents; +use function func_num_args; use function libxml_clear_errors; use function libxml_get_last_error; +use function libxml_set_external_entity_loader; use function libxml_use_internal_errors; use function sprintf; @@ -22,25 +23,41 @@ */ final class DOMDocumentFactory { + /** + * @var non-negative-int + * TODO: Add LIBXML_NO_XXE to the defaults when PHP 8.4.0 + libxml 2.13.0 become generally available + */ + public const DEFAULT_OPTIONS = LIBXML_COMPACT | LIBXML_NONET | LIBXML_NSCLEAN; + + /** * @param string $xml - * @param non-empty-string $xml + * @param non-negative-int $options * * @return \DOMDocument */ - public static function fromString(string $xml): DOMDocument - { + public static function fromString( + string $xml, + int $options = self::DEFAULT_OPTIONS, + ): DOMDocument { + libxml_set_external_entity_loader(null); Assert::notWhitespaceOnly($xml); + Assert::notRegex( + $xml, + '/<(\s*)!(\s*)DOCTYPE/', + 'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body', + RuntimeException::class, + ); $internalErrors = libxml_use_internal_errors(true); libxml_clear_errors(); - $domDocument = self::create(); - $options = LIBXML_DTDLOAD | LIBXML_DTDATTR | LIBXML_NONET | LIBXML_PARSEHUGE | LIBXML_NSCLEAN; - if (defined('LIBXML_COMPACT')) { - $options |= LIBXML_COMPACT; + // If LIBXML_NO_XXE is available and option not set + if (func_num_args() === 1 && defined('LIBXML_NO_XXE')) { + $options != LIBXML_NO_XXE; } + $domDocument = self::create(); $loaded = $domDocument->loadXML($xml, $options); libxml_use_internal_errors($internalErrors); @@ -55,11 +72,11 @@ public static function fromString(string $xml): DOMDocument libxml_clear_errors(); foreach ($domDocument->childNodes as $child) { - if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { - throw new RuntimeException( - 'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body', - ); - } + Assert::false( + $child->nodeType === XML_DOCUMENT_TYPE_NODE, + 'Dangerous XML detected, DOCTYPE nodes are not allowed in the XML body', + RuntimeException::class, + ); } return $domDocument; @@ -68,10 +85,11 @@ public static function fromString(string $xml): DOMDocument /** * @param string $file + * @param non-negative-int $options * * @return \DOMDocument */ - public static function fromFile(string $file): DOMDocument + public static function fromFile(string $file, int $options = self::DEFAULT_OPTIONS): DOMDocument { error_clear_last(); $xml = @file_get_contents($file); @@ -83,7 +101,7 @@ public static function fromFile(string $file): DOMDocument } Assert::notWhitespaceOnly($xml, sprintf('File "%s" does not have content', $file), RuntimeException::class); - return static::fromString($xml); + return (func_num_args() === 1) ? static::fromString($xml) : static::fromString($xml, $options); } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableAttributesTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableAttributesTrait.php index 4eb33a4bd..d16fa02a4 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableAttributesTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableAttributesTrait.php @@ -93,7 +93,7 @@ public function getAttributesNS(): array * * @return array $attributes */ - protected static function getAttributesNSFromXML(DOMElement $xml, NS|array $namespace = null): array + protected static function getAttributesNSFromXML(DOMElement $xml, NS|array|null $namespace = null): array { $namespace = $namespace ?? self::XS_ANY_ATTR_NAMESPACE; $exclusionList = self::getAttributeExclusions(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableElementTrait.php index 45016f33f..3e5c84b0b 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/ExtendableElementTrait.php @@ -42,7 +42,7 @@ trait ExtendableElementTrait * * @return list<\SimpleSAML\XML\SerializableElementInterface> $elements */ - protected static function getChildElementsFromXML(DOMElement $xml, NS|array $namespace = null): array + protected static function getChildElementsFromXML(DOMElement $xml, NS|array|null $namespace = null): array { $namespace = $namespace ?? self::XS_ANY_ELT_NAMESPACE; $exclusionList = self::getElementExclusions(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/IntegerElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/IntegerElementTrait.php new file mode 100644 index 000000000..ded61955b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/IntegerElementTrait.php @@ -0,0 +1,35 @@ +instantiateParentElement($parent); - $e->setAttributeNS(C::NS_XML, 'xml:lang', $this->language); + $e->setAttributeNS(C::NS_XML, 'xml:lang', $this->getLanguage()); $e->textContent = $this->getContent(); return $e; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/QNameElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/QNameElementTrait.php index 800fcc81a..02c143a06 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/QNameElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/QNameElementTrait.php @@ -111,7 +111,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); @@ -140,5 +140,5 @@ abstract public static function getLocalName(): string; * @param \DOMElement|null $parent The element we should append to. * @return \DOMElement */ - abstract public function instantiateParentElement(DOMElement $parent = null): DOMElement; + abstract public function instantiateParentElement(?DOMElement $parent = null): DOMElement; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementInterface.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementInterface.php index 2baa9d1ac..527240ff1 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementInterface.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementInterface.php @@ -44,5 +44,5 @@ public static function fromXML(DOMElement $xml): static; * @param \DOMElement|null $parent * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement; + public function toXML(?DOMElement $parent = null): DOMElement; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementTrait.php index 28d34e768..e5cb179ca 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/SerializableElementTrait.php @@ -86,5 +86,5 @@ public function __unserialize(array $serialized): void * @param \DOMElement|null $parent * @return \DOMElement */ - abstract public function toXML(DOMElement $parent = null): DOMElement; + abstract public function toXML(?DOMElement $parent = null): DOMElement; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/StringElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/StringElementTrait.php index 835ca9060..abdfd7aae 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/StringElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/StringElementTrait.php @@ -110,7 +110,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getContent(); @@ -131,5 +131,5 @@ abstract public static function getLocalName(): string; * @param \DOMElement|null $parent The element we should append to. * @return \DOMElement */ - abstract public function instantiateParentElement(DOMElement $parent = null): DOMElement; + abstract public function instantiateParentElement(?DOMElement $parent = null): DOMElement; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/URIElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/URIElementTrait.php index f5d7fc8eb..cb7c79fc8 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/URIElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-common/src/URIElementTrait.php @@ -53,7 +53,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent * @return \DOMElement */ - final public function toXML(DOMElement $parent = null): DOMElement + final public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getContent(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/composer.json b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/composer.json index 687c3455b..f891a767b 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/composer.json +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/composer.json @@ -43,8 +43,8 @@ "ext-pcre": "*", "ext-spl": "*", - "simplesamlphp/assert": "^1.3", - "simplesamlphp/xml-common": "^1.18" + "simplesamlphp/assert": "^1.5", + "simplesamlphp/xml-common": "^1.20.0" }, "require-dev": { "simplesamlphp/simplesamlphp-test-framework": "^1.7" diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Constants.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Constants.php index f9e64f35a..7b39c1597 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Constants.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Constants.php @@ -153,5 +153,6 @@ class Constants extends \SimpleSAML\XML\Constants public const XMLENC_ENCRYPTEDKEY = 'http://www.w3.org/2001/04/xmlenc#EncryptedKey'; public const XMLENC_EXI = 'http://www.w3.org/2009/xmlenc11#EXI'; - public const XPATH_URI = 'http://www.w3.org/TR/1999/REC-xpath-19991116'; + // The namespace for the Elliptic Curve Diffie-Hellman Ephemeral Static (ECDH-ES) algorithm + public const XMLENC11_ECDH_ES = 'http://www.w3.org/2009/xmlenc11#ECDH-ES'; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Key/PrivateKey.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Key/PrivateKey.php index 602ce28d2..87bdaa6ae 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Key/PrivateKey.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Key/PrivateKey.php @@ -56,7 +56,7 @@ public static function fromFile( ): static { if (preg_match(PEM::PEM_REGEX, $file) !== 1) { // Not a PEM-encoded key. Must be a file - if (preg_match('/^(file:\/\/)/i', $file) !== 1) { + if (preg_match('/^(file:\/\/)/Di', $file) !== 1) { $file = preg_filter('/^/', 'file://', $file); } } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Utils/XML.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Utils/XML.php index b7a3df3cf..f2dafca5d 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Utils/XML.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/Utils/XML.php @@ -33,8 +33,8 @@ class XML public static function canonicalizeData( DOMElement $element, string $c14nMethod, - array $xpaths = null, - array $prefixes = null, + ?array $xpaths = null, + ?array $prefixes = null, ): string { $withComments = match ($c14nMethod) { C::C14N_EXCLUSIVE_WITH_COMMENTS, C::C14N_INCLUSIVE_WITH_COMMENTS => true, @@ -101,7 +101,7 @@ public static function processTransforms( } } break; - case C::XPATH_URI: + case C::XPATH10_URI: $xpath = $transform->getXPath(); if ($xpath !== null) { $arXPath = []; diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/EncryptedElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/EncryptedElementTrait.php index 5c8c95487..48b381f86 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/EncryptedElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/EncryptedElementTrait.php @@ -179,7 +179,7 @@ public static function fromXML(DOMElement $xml): static /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $this->encryptedData->toXML($e); @@ -196,7 +196,7 @@ public function toXML(DOMElement $parent = null): DOMElement * @param \DOMElement|null $parent The element we should append to. * @return \DOMElement */ - abstract public function instantiateParentElement(DOMElement $parent = null): DOMElement; + abstract public function instantiateParentElement(?DOMElement $parent = null): DOMElement; /** diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementInterface.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementInterface.php index cf2e3c9ab..d48ef0c31 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementInterface.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementInterface.php @@ -65,5 +65,5 @@ public function isSigned(): bool; * in the signature. * @throws \SimpleSAML\XMLSecurity\Exception\RuntimeException if the signature fails to validate. */ - public function verify(SignatureAlgorithmInterface $verifier = null): SignedElementInterface; + public function verify(?SignatureAlgorithmInterface $verifier = null): SignedElementInterface; } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementTrait.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementTrait.php index 10b7ccbea..8fa736589 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementTrait.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/SignedElementTrait.php @@ -251,7 +251,7 @@ public function isSigned(): bool * in the signature. * @throws \SimpleSAML\XMLSecurity\Exception\RuntimeException if the signature fails to verify. */ - public function verify(SignatureAlgorithmInterface $verifier = null): SignedElementInterface + public function verify(?SignatureAlgorithmInterface $verifier = null): SignedElementInterface { if (!$this->isSigned()) { throw new NoSignatureFoundException(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/AbstractKeyInfoType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/AbstractKeyInfoType.php new file mode 100644 index 000000000..2de04d673 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/AbstractKeyInfoType.php @@ -0,0 +1,117 @@ +Id; + } + + + /** + * Collect the value of the info-property + * + * @return list<\SimpleSAML\XML\SerializableElementInterface> + */ + public function getInfo(): array + { + return $this->info; + } + + + /** + * Convert this KeyInfo to XML. + * + * @param \DOMElement|null $parent The element we should append this KeyInfo to. + * @return \DOMElement + */ + public function toXML(?DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + if ($this->getId() !== null) { + $e->setAttribute('Id', $this->getId()); + } + + foreach ($this->getInfo() as $elt) { + $elt->toXML($e); + } + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/CanonicalizationMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/CanonicalizationMethod.php index f7844a3f6..ddb319f5c 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/CanonicalizationMethod.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/CanonicalizationMethod.php @@ -78,7 +78,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this KeyName element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('Algorithm', $this->getAlgorithm()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DigestMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DigestMethod.php index 9ce95f549..335d5d4e1 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DigestMethod.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DigestMethod.php @@ -84,7 +84,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this DigestMethod element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('Algorithm', $this->getAlgorithm()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DsObject.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DsObject.php index 72f78f5ad..00f0fae04 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DsObject.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/DsObject.php @@ -123,7 +123,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this ds:Object element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyInfo.php index e33f2a1b1..5f4993451 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyInfo.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyInfo.php @@ -7,85 +7,16 @@ use DOMElement; use SimpleSAML\Assert\Assert; use SimpleSAML\XML\Exception\InvalidDOMElementException; -use SimpleSAML\XML\Exception\SchemaViolationException; -use SimpleSAML\XML\ExtendableElementTrait; -use SimpleSAML\XML\SerializableElementInterface; -use SimpleSAML\XML\XsNamespace as NS; -use SimpleSAML\XMLSecurity\Constants as C; -use SimpleSAML\XMLSecurity\Exception\InvalidArgumentException; + +use function array_merge; /** * Class representing a ds:KeyInfo element. * * @package simplesamlphp/xml-security */ -final class KeyInfo extends AbstractDsElement +final class KeyInfo extends AbstractKeyInfoType { - use ExtendableElementTrait; - - /** @var \SimpleSAML\XML\XsNamespace */ - public const XS_ANY_ELT_NAMESPACE = NS::OTHER; - - - /** - * Initialize a KeyInfo element. - * - * @param ( - * \SimpleSAML\XMLSecurity\XML\ds\KeyName| - * \SimpleSAML\XMLSecurity\XML\ds\KeyValue| - * \SimpleSAML\XMLSecurity\XML\ds\RetrievalMethod| - * \SimpleSAML\XMLSecurity\XML\ds\X509Data| - * \SimpleSAML\XML\SerializableElementInterface - * )[] $info - * @param string|null $Id - */ - public function __construct( - protected array $info, - protected ?string $Id = null, - ) { - Assert::notEmpty($info, 'ds:KeyInfo cannot be empty', InvalidArgumentException::class); - Assert::maxCount($info, C::UNBOUNDED_LIMIT); - Assert::allIsInstanceOf( - $info, - SerializableElementInterface::class, - InvalidArgumentException::class, - ); - Assert::nullOrValidNCName($Id); - - foreach ($info as $item) { - if ($item->getNamespaceURI() === static::NS) { - Assert::isInstanceOfAny( - $item, - [KeyName::class, KeyValue::class, RetrievalMethod::class, X509Data::class], - SchemaViolationException::class, - ); - } - } - } - - - /** - * Collect the value of the Id-property - * - * @return string|null - */ - public function getId(): ?string - { - return $this->Id; - } - - - /** - * Collect the value of the info-property - * - * @return list<\SimpleSAML\XML\SerializableElementInterface> - */ - public function getInfo(): array - { - return $this->info; - } - - /** * Convert XML into a KeyInfo * @@ -124,26 +55,4 @@ public static function fromXML(DOMElement $xml): static return new static($info, $Id); } - - - /** - * Convert this KeyInfo to XML. - * - * @param \DOMElement|null $parent The element we should append this KeyInfo to. - * @return \DOMElement - */ - public function toXML(DOMElement $parent = null): DOMElement - { - $e = $this->instantiateParentElement($parent); - - if ($this->getId() !== null) { - $e->setAttribute('Id', $this->getId()); - } - - foreach ($this->getInfo() as $elt) { - $elt->toXML($e); - } - - return $e; - } } diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyValue.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyValue.php index b6f2d0183..7677371b6 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyValue.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/KeyValue.php @@ -100,7 +100,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this KeyValue element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Manifest.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Manifest.php index b78c53cd0..9eac89ab4 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Manifest.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Manifest.php @@ -88,7 +88,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this Manifest element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RSAKeyValue.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RSAKeyValue.php index 1a23e70bf..ff56e9353 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RSAKeyValue.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RSAKeyValue.php @@ -104,7 +104,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this RSAKeyValue element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Reference.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Reference.php index fc7e2e830..86baeab8b 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Reference.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Reference.php @@ -167,7 +167,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this Reference element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); if ($this->getId() !== null) { diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RetrievalMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RetrievalMethod.php index e75fcca8d..e14b15c44 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RetrievalMethod.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/RetrievalMethod.php @@ -100,7 +100,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this RetrievalMethod element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('URI', $this->getURI()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Signature.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Signature.php index d004a3143..936587068 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Signature.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Signature.php @@ -161,7 +161,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this Signature element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureMethod.php index 095e1ecb3..df2470e37 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureMethod.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureMethod.php @@ -76,7 +76,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this SignatureMethod element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('Algorithm', $this->getAlgorithm()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperties.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperties.php index cd5ff1960..cb8cbe109 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperties.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperties.php @@ -89,7 +89,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this SignatureProperties element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperty.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperty.php index c8b312c6c..858b16f47 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperty.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureProperty.php @@ -102,7 +102,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this SignatureProperty element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('Target', $this->getTarget()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureValue.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureValue.php index d023cf4e0..d90f3c7db 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureValue.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignatureValue.php @@ -70,7 +70,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this SignatureValue element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getContent(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignedInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignedInfo.php index 0779cc428..4c83d61d9 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignedInfo.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/SignedInfo.php @@ -172,7 +172,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this SignedInfo element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transform.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transform.php index a10258816..b18abb314 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transform.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transform.php @@ -38,8 +38,8 @@ final public function __construct( if ($xpath !== null) { Assert::nullOrEq( $this->algorithm, - C::XPATH_URI, - sprintf('Transform algorithm "%s" required if XPath provided.', C::XPATH_URI), + C::XPATH10_URI, + sprintf('Transform algorithm "%s" required if XPath provided.', C::XPATH10_URI), ); } @@ -127,7 +127,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this Transform element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); @@ -135,7 +135,7 @@ public function toXML(DOMElement $parent = null): DOMElement $e->setAttribute('Algorithm', $algorithm); switch ($algorithm) { - case C::XPATH_URI: + case C::XPATH10_URI: $this->getXpath()?->toXML($e); break; case C::C14N_EXCLUSIVE_WITH_COMMENTS: diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transforms.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transforms.php index db46c4fe2..aef932030 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transforms.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/Transforms.php @@ -76,7 +76,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this Transforms element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509Data.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509Data.php index b9c68947b..d810143d3 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509Data.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509Data.php @@ -98,7 +98,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this X509Data element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509IssuerSerial.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509IssuerSerial.php index 483d19067..dc0a70da8 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509IssuerSerial.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509IssuerSerial.php @@ -90,7 +90,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this X509IssuerSerial element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509SerialNumber.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509SerialNumber.php index d7b659139..a24f19c9d 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509SerialNumber.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/X509SerialNumber.php @@ -66,7 +66,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this X509SerialNumber element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getContent(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/XPath.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/XPath.php index cf84778d3..087c8b17a 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/XPath.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ds/XPath.php @@ -88,7 +88,7 @@ public static function fromXML(DOMElement $xml): static * @param DOMElement|null $parent * @return DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getExpression(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/KeyInfoReference.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/KeyInfoReference.php index e1bdc5f65..b9a6a78e2 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/KeyInfoReference.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/KeyInfoReference.php @@ -80,7 +80,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this KeyInfoReference element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('URI', $this->getURI()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/X509Digest.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/X509Digest.php index 277dee82a..0eda198a3 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/X509Digest.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/dsig11/X509Digest.php @@ -81,7 +81,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this X509Digest element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = $this->getContent(); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ec/InclusiveNamespaces.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ec/InclusiveNamespaces.php index 7deff9eb0..eb79c964e 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ec/InclusiveNamespaces.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/ec/InclusiveNamespaces.php @@ -68,7 +68,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this InclusiveNamespaces to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/element.registry.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/element.registry.php index 5a371ef84..9a55180d1 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/element.registry.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/element.registry.php @@ -43,10 +43,10 @@ 'InclusiveNamespaces' => '\SimpleSAML\XMLSecurity\XML\ec\InclusiveNamespaces', ], 'http://www.w3.org/2001/04/xmlenc#' => [ -// 'AgreementMethod' => '\SimpleSAML\XMLSecurity\XML\xenc\AgreementMethod', + 'AgreementMethod' => '\SimpleSAML\XMLSecurity\XML\xenc\AgreementMethod', 'CipherData' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherData', 'CipherReference' => '\SimpleSAML\XMLSecurity\XML\xenc\CipherReference', -// 'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue', + 'DHKeyValue' => '\SimpleSAML\XMLSecurity\XML\xenc\DHKeyValue', 'EncryptedData' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedData', 'EncryptedKey' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptedKey', 'EncryptionProperties' => '\SimpleSAML\XMLSecurity\XML\xenc\EncryptionProperties', diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractAgreementMethodType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractAgreementMethodType.php new file mode 100644 index 000000000..978dbb62a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractAgreementMethodType.php @@ -0,0 +1,159 @@ + $children + */ + final public function __construct( + protected string $algorithm, + protected ?KANonce $kaNonce = null, + protected ?OriginatorKeyInfo $originatorKeyInfo = null, + protected ?RecipientKeyInfo $recipientKeyInfo = null, + protected array $children = [], + ) { + Assert::validURI($algorithm, SchemaViolationException::class); // Covers the empty string + + $this->setElements($children); + } + + + /** + * Get the URI identifying the algorithm used by this agreement method. + * + * @return string + */ + public function getAlgorithm(): string + { + return $this->algorithm; + } + + + /** + * Get the KA-Nonce. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\KANonce|null + */ + public function getKANonce(): ?KANonce + { + return $this->kaNonce; + } + + + /** + * Get the Originator KeyInfo. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\OriginatorKeyInfo|null + */ + public function getOriginatorKeyInfo(): ?OriginatorKeyInfo + { + return $this->originatorKeyInfo; + } + + + /** + * Get the Recipient KeyInfo. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\RecipientKeyInfo|null + */ + public function getRecipientKeyInfo(): ?RecipientKeyInfo + { + return $this->recipientKeyInfo; + } + + + /** + * Initialize an AgreementMethod object from an existing XML. + * + * @param \DOMElement $xml + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * if the supplied element is missing one of the mandatory attributes + * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * if too many child-elements of a type are specified + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, 'AgreementMethod', InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $algorithm = self::getAttribute($xml, 'Algorithm'); + + $kaNonce = KANonce::getChildrenOfClass($xml); + Assert::maxCount($kaNonce, 1, TooManyElementsException::class); + + $originatorKeyInfo = OriginatorKeyInfo::getChildrenOfClass($xml); + Assert::maxCount($originatorKeyInfo, 1, TooManyElementsException::class); + + $recipientKeyInfo = RecipientKeyInfo::getChildrenOfClass($xml); + Assert::maxCount($recipientKeyInfo, 1, TooManyElementsException::class); + + $children = self::getChildElementsFromXML($xml); + + return new static( + $algorithm, + array_pop($kaNonce), + array_pop($originatorKeyInfo), + array_pop($recipientKeyInfo), + $children, + ); + } + + + /** + * Convert this AgreementMethod object to XML. + * + * @param \DOMElement|null $parent The element we should append this AgreementMethod to. + * @return \DOMElement + */ + public function toXML(?DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + $e->setAttribute('Algorithm', $this->getAlgorithm()); + + $this->getKANonce()?->toXML($e); + + foreach ($this->getElements() as $child) { + $child->toXML($e); + } + + $this->getOriginatorKeyInfo()?->toXML($e); + $this->getRecipientKeyInfo()?->toXML($e); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractDHKeyValueType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractDHKeyValueType.php new file mode 100644 index 000000000..ff1afde26 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractDHKeyValueType.php @@ -0,0 +1,188 @@ +xencPublic; + } + + + /** + * Get the P. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\P|null + */ + public function getP(): ?P + { + return $this->p; + } + + + /** + * Get the Q. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\Q|null + */ + public function getQ(): ?Q + { + return $this->q; + } + + + /** + * Get the Generator. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\Generator|null + */ + public function getGenerator(): ?Generator + { + return $this->generator; + } + + + /** + * Get the Seed. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\Seed|null + */ + public function getSeed(): ?Seed + { + return $this->seed; + } + + + /** + * Get the PgenCounter. + * + * @return \SimpleSAML\XMLSecurity\XML\xenc\PgenCounter|null + */ + public function getPgenCounter(): ?PgenCounter + { + return $this->pgenCounter; + } + + + /** + * Initialize an DHKeyValue object from an existing XML. + * + * @param \DOMElement $xml + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + * @throws \SimpleSAML\XML\Exception\MissingAttributeException + * if the supplied element is missing one of the mandatory attributes + * @throws \SimpleSAML\XML\Exception\TooManyElementsException + * if too many child-elements of a type are specified + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, 'DHKeyValue', InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $xencPublic = XencPublic::getChildrenOfClass($xml); + Assert::minCount($xencPublic, 1, MissingElementException::class); + Assert::maxCount($xencPublic, 1, TooManyElementsException::class); + + $p = P::getChildrenOfClass($xml); + Assert::maxCount($p, 1, TooManyElementsException::class); + + $q = Q::getChildrenOfClass($xml); + Assert::maxCount($q, 1, TooManyElementsException::class); + + $generator = Generator::getChildrenOfClass($xml); + Assert::maxCount($generator, 1, TooManyElementsException::class); + + $seed = Seed::getChildrenOfClass($xml); + Assert::maxCount($seed, 1, TooManyElementsException::class); + + $pgenCounter = PgenCounter::getChildrenOfClass($xml); + Assert::maxCount($pgenCounter, 1, TooManyElementsException::class); + + return new static( + array_pop($xencPublic), + array_pop($p), + array_pop($q), + array_pop($generator), + array_pop($seed), + array_pop($pgenCounter), + ); + } + + + /** + * Convert this DHKeyValue object to XML. + * + * @param \DOMElement|null $parent The element we should append this DHKeyValue to. + * @return \DOMElement + */ + public function toXML(?DOMElement $parent = null): DOMElement + { + $e = $this->instantiateParentElement($parent); + + $this->getP()?->toXML($e); + $this->getQ()?->toXML($e); + $this->getGenerator()?->toXML($e); + $this->getPublic()->toXML($e); + $this->getSeed()?->toXML($e); + $this->getPgenCounter()?->toXML($e); + + return $e; + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptedType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptedType.php index 6a3e7c964..ad005c03b 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptedType.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptedType.php @@ -125,7 +125,7 @@ public function getType(): ?string /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionMethod.php index bafc54fa0..0b3861621 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionMethod.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionMethod.php @@ -118,7 +118,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this EncryptionMethod to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('Algorithm', $this->getAlgorithm()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertiesType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertiesType.php index 63c79f3c1..5b9810b85 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertiesType.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertiesType.php @@ -75,7 +75,7 @@ public static function fromXML(DOMElement $xml): static /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertyType.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertyType.php index 9a56bc771..a70ff2376 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertyType.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractEncryptionPropertyType.php @@ -99,7 +99,7 @@ public static function fromXML(DOMElement $xml): static /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractReference.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractReference.php index f67f6e1db..225fdbf18 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractReference.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AbstractReference.php @@ -74,7 +74,7 @@ public static function fromXML(DOMElement $xml): static /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('URI', $this->getUri()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AgreementMethod.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AgreementMethod.php new file mode 100644 index 000000000..3a7bc106c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/AgreementMethod.php @@ -0,0 +1,14 @@ +instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/CipherReference.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/CipherReference.php index e2a169f35..592ee0cf9 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/CipherReference.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/CipherReference.php @@ -68,7 +68,7 @@ public static function fromXML(DOMElement $xml): static /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->setAttribute('URI', $this->getUri()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/DHKeyValue.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/DHKeyValue.php new file mode 100644 index 000000000..66ab70826 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/DHKeyValue.php @@ -0,0 +1,14 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KANonce.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KANonce.php new file mode 100644 index 000000000..44e72e2a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KANonce.php @@ -0,0 +1,29 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KeySize.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KeySize.php index c2faef38f..c08649221 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KeySize.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/KeySize.php @@ -60,7 +60,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); $e->textContent = strval($this->getKeySize()); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/OriginatorKeyInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/OriginatorKeyInfo.php new file mode 100644 index 000000000..2f7db9a15 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/OriginatorKeyInfo.php @@ -0,0 +1,71 @@ +localName, 'OriginatorKeyInfo', InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, OriginatorKeyInfo::NS, InvalidDOMElementException::class); + + $Id = self::getOptionalAttribute($xml, 'Id', null); + + $keyName = KeyName::getChildrenOfClass($xml); + $keyValue = KeyValue::getChildrenOfClass($xml); + $retrievalMethod = RetrievalMethod::getChildrenOfClass($xml); + $x509Data = X509Data::getChildrenOfClass($xml); + //$pgpData = PGPData::getChildrenOfClass($xml); + //$spkiData = SPKIData::getChildrenOfClass($xml); + //$mgmtData = MgmtData::getChildrenOfClass($xml); + $other = self::getChildElementsFromXML($xml); + + $info = array_merge( + $keyName, + $keyValue, + $retrievalMethod, + $x509Data, + //$pgpdata, + //$spkidata, + //$mgmtdata, + $other, + ); + + return new static($info, $Id); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/P.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/P.php new file mode 100644 index 000000000..a9f4a530b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/P.php @@ -0,0 +1,26 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/PgenCounter.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/PgenCounter.php new file mode 100644 index 000000000..5350a3c4b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/PgenCounter.php @@ -0,0 +1,29 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Q.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Q.php new file mode 100644 index 000000000..379ecb545 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Q.php @@ -0,0 +1,26 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/RecipientKeyInfo.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/RecipientKeyInfo.php new file mode 100644 index 000000000..c5eb61b9d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/RecipientKeyInfo.php @@ -0,0 +1,71 @@ +localName, 'RecipientKeyInfo', InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, RecipientKeyInfo::NS, InvalidDOMElementException::class); + + $Id = self::getOptionalAttribute($xml, 'Id', null); + + $keyName = KeyName::getChildrenOfClass($xml); + $keyValue = KeyValue::getChildrenOfClass($xml); + $retrievalMethod = RetrievalMethod::getChildrenOfClass($xml); + $x509Data = X509Data::getChildrenOfClass($xml); + //$pgpData = PGPData::getChildrenOfClass($xml); + //$spkiData = SPKIData::getChildrenOfClass($xml); + //$mgmtData = MgmtData::getChildrenOfClass($xml); + $other = self::getChildElementsFromXML($xml); + + $info = array_merge( + $keyName, + $keyValue, + $retrievalMethod, + $x509Data, + //$pgpdata, + //$spkidata, + //$mgmtdata, + $other, + ); + + return new static($info, $Id); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/ReferenceList.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/ReferenceList.php index 1791b75dd..537768e8f 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/ReferenceList.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/ReferenceList.php @@ -98,7 +98,7 @@ public static function fromXML(DOMElement $xml): static /** * @inheritDoc */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Seed.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Seed.php new file mode 100644 index 000000000..7eb7823a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Seed.php @@ -0,0 +1,29 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Transforms.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Transforms.php index 02f204493..078f252c7 100644 --- a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Transforms.php +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/Transforms.php @@ -77,7 +77,7 @@ public static function fromXML(DOMElement $xml): static * @param \DOMElement|null $parent The element we should append this Transforms element to. * @return \DOMElement */ - public function toXML(DOMElement $parent = null): DOMElement + public function toXML(?DOMElement $parent = null): DOMElement { $e = $this->instantiateParentElement($parent); diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/XencPublic.php b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/XencPublic.php new file mode 100644 index 000000000..d8169c0e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/src/XML/xenc/XencPublic.php @@ -0,0 +1,29 @@ +setContent($content); + } +} diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_AgreementMethod.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_AgreementMethod.xml new file mode 100644 index 000000000..f4847ade6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_AgreementMethod.xml @@ -0,0 +1,22 @@ + + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + + some + + + testkey + + MIICxDCCAi2gAwIBAgIUZ9QDx+SBFHednUWDFGm9tyVKrgQwDQYJKoZIhvcNAQELBQAwczElMCMGA1UEAwwcc2VsZnNpZ25lZC5zaW1wbGVzYW1scGhwLm9yZzEZMBcGA1UECgwQU2ltcGxlU0FNTHBocCBIUTERMA8GA1UEBwwISG9ub2x1bHUxDzANBgNVBAgMBkhhd2FpaTELMAkGA1UEBhMCVVMwIBcNMjIxMjAzMTAzNTQwWhgPMjEyMjExMDkxMDM1NDBaMHMxJTAjBgNVBAMMHHNlbGZzaWduZWQuc2ltcGxlc2FtbHBocC5vcmcxGTAXBgNVBAoMEFNpbXBsZVNBTUxwaHAgSFExETAPBgNVBAcMCEhvbm9sdWx1MQ8wDQYDVQQIDAZIYXdhaWkxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDessdFRVDTMQQW3Na81B1CjJV1tmY3nopoIhZrkbDxLa+pv7jGDRcYreyu1DoQxEs06V2nHLoyOPhqJXSFivqtUwVYhR6NYgbNI6RRSsIJCweH0YOdlHna7gULPcLX0Bfbi4odStaFwG9yzDySwSEPtsKxm5pENPjNVGh+jJ+H/QIDAQABo1MwUTAdBgNVHQ4EFgQUvV75t8EoQo2fVa0E9otdtIGK5X0wHwYDVR0jBBgwFoAUvV75t8EoQo2fVa0E9otdtIGK5X0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQANQUeiwPJXkWMXuaDHToEBKcezYGqGEYnGUi9LMjeb+Kln7X8nn5iknlz4k77rWCbSwLPC/WDr0ySYQA+HagaeUaFpoiYFJKS6uFlK1HYWnM3W4PUiGHg1/xeZlMO44wTwybXVo0y9KMhchfB5XNbDdoJcqWYvi6xtmZZNRbxUyw== + /CN=selfsigned.simplesamlphp.org/O=SimpleSAMLphp HQ/L=Honolulu/ST=Hawaii/C=US + + originator + + + testkey + + MIICxDCCAi2gAwIBAgIUZ9QDx+SBFHednUWDFGm9tyVKrgQwDQYJKoZIhvcNAQELBQAwczElMCMGA1UEAwwcc2VsZnNpZ25lZC5zaW1wbGVzYW1scGhwLm9yZzEZMBcGA1UECgwQU2ltcGxlU0FNTHBocCBIUTERMA8GA1UEBwwISG9ub2x1bHUxDzANBgNVBAgMBkhhd2FpaTELMAkGA1UEBhMCVVMwIBcNMjIxMjAzMTAzNTQwWhgPMjEyMjExMDkxMDM1NDBaMHMxJTAjBgNVBAMMHHNlbGZzaWduZWQuc2ltcGxlc2FtbHBocC5vcmcxGTAXBgNVBAoMEFNpbXBsZVNBTUxwaHAgSFExETAPBgNVBAcMCEhvbm9sdWx1MQ8wDQYDVQQIDAZIYXdhaWkxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDessdFRVDTMQQW3Na81B1CjJV1tmY3nopoIhZrkbDxLa+pv7jGDRcYreyu1DoQxEs06V2nHLoyOPhqJXSFivqtUwVYhR6NYgbNI6RRSsIJCweH0YOdlHna7gULPcLX0Bfbi4odStaFwG9yzDySwSEPtsKxm5pENPjNVGh+jJ+H/QIDAQABo1MwUTAdBgNVHQ4EFgQUvV75t8EoQo2fVa0E9otdtIGK5X0wHwYDVR0jBBgwFoAUvV75t8EoQo2fVa0E9otdtIGK5X0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQANQUeiwPJXkWMXuaDHToEBKcezYGqGEYnGUi9LMjeb+Kln7X8nn5iknlz4k77rWCbSwLPC/WDr0ySYQA+HagaeUaFpoiYFJKS6uFlK1HYWnM3W4PUiGHg1/xeZlMO44wTwybXVo0y9KMhchfB5XNbDdoJcqWYvi6xtmZZNRbxUyw== + /CN=selfsigned.simplesamlphp.org/O=SimpleSAMLphp HQ/L=Honolulu/ST=Hawaii/C=US + + recipient + + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_DHKeyValue.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_DHKeyValue.xml new file mode 100644 index 000000000..68e0969fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_DHKeyValue.xml @@ -0,0 +1,8 @@ + + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + /CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Generator.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Generator.xml new file mode 100644 index 000000000..a87db2210 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Generator.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_KA-Nonce.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_KA-Nonce.xml new file mode 100644 index 000000000..285522773 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_KA-Nonce.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_OriginatorKeyInfo.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_OriginatorKeyInfo.xml new file mode 100644 index 000000000..080836d04 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_OriginatorKeyInfo.xml @@ -0,0 +1,8 @@ + + testkey + + MIICxDCCAi2gAwIBAgIUZ9QDx+SBFHednUWDFGm9tyVKrgQwDQYJKoZIhvcNAQELBQAwczElMCMGA1UEAwwcc2VsZnNpZ25lZC5zaW1wbGVzYW1scGhwLm9yZzEZMBcGA1UECgwQU2ltcGxlU0FNTHBocCBIUTERMA8GA1UEBwwISG9ub2x1bHUxDzANBgNVBAgMBkhhd2FpaTELMAkGA1UEBhMCVVMwIBcNMjIxMjAzMTAzNTQwWhgPMjEyMjExMDkxMDM1NDBaMHMxJTAjBgNVBAMMHHNlbGZzaWduZWQuc2ltcGxlc2FtbHBocC5vcmcxGTAXBgNVBAoMEFNpbXBsZVNBTUxwaHAgSFExETAPBgNVBAcMCEhvbm9sdWx1MQ8wDQYDVQQIDAZIYXdhaWkxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDessdFRVDTMQQW3Na81B1CjJV1tmY3nopoIhZrkbDxLa+pv7jGDRcYreyu1DoQxEs06V2nHLoyOPhqJXSFivqtUwVYhR6NYgbNI6RRSsIJCweH0YOdlHna7gULPcLX0Bfbi4odStaFwG9yzDySwSEPtsKxm5pENPjNVGh+jJ+H/QIDAQABo1MwUTAdBgNVHQ4EFgQUvV75t8EoQo2fVa0E9otdtIGK5X0wHwYDVR0jBBgwFoAUvV75t8EoQo2fVa0E9otdtIGK5X0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQANQUeiwPJXkWMXuaDHToEBKcezYGqGEYnGUi9LMjeb+Kln7X8nn5iknlz4k77rWCbSwLPC/WDr0ySYQA+HagaeUaFpoiYFJKS6uFlK1HYWnM3W4PUiGHg1/xeZlMO44wTwybXVo0y9KMhchfB5XNbDdoJcqWYvi6xtmZZNRbxUyw== + /CN=selfsigned.simplesamlphp.org/O=SimpleSAMLphp HQ/L=Honolulu/ST=Hawaii/C=US + + some + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_P.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_P.xml new file mode 100644 index 000000000..9c7ff0e6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_P.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Public.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Public.xml new file mode 100644 index 000000000..55f5b592d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Public.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Q.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Q.xml new file mode 100644 index 000000000..421da4f6d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_Q.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_RecipientKeyInfo.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_RecipientKeyInfo.xml new file mode 100644 index 000000000..bee00edee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_RecipientKeyInfo.xml @@ -0,0 +1,8 @@ + + testkey + + MIICxDCCAi2gAwIBAgIUZ9QDx+SBFHednUWDFGm9tyVKrgQwDQYJKoZIhvcNAQELBQAwczElMCMGA1UEAwwcc2VsZnNpZ25lZC5zaW1wbGVzYW1scGhwLm9yZzEZMBcGA1UECgwQU2ltcGxlU0FNTHBocCBIUTERMA8GA1UEBwwISG9ub2x1bHUxDzANBgNVBAgMBkhhd2FpaTELMAkGA1UEBhMCVVMwIBcNMjIxMjAzMTAzNTQwWhgPMjEyMjExMDkxMDM1NDBaMHMxJTAjBgNVBAMMHHNlbGZzaWduZWQuc2ltcGxlc2FtbHBocC5vcmcxGTAXBgNVBAoMEFNpbXBsZVNBTUxwaHAgSFExETAPBgNVBAcMCEhvbm9sdWx1MQ8wDQYDVQQIDAZIYXdhaWkxCzAJBgNVBAYTAlVTMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDessdFRVDTMQQW3Na81B1CjJV1tmY3nopoIhZrkbDxLa+pv7jGDRcYreyu1DoQxEs06V2nHLoyOPhqJXSFivqtUwVYhR6NYgbNI6RRSsIJCweH0YOdlHna7gULPcLX0Bfbi4odStaFwG9yzDySwSEPtsKxm5pENPjNVGh+jJ+H/QIDAQABo1MwUTAdBgNVHQ4EFgQUvV75t8EoQo2fVa0E9otdtIGK5X0wHwYDVR0jBBgwFoAUvV75t8EoQo2fVa0E9otdtIGK5X0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQANQUeiwPJXkWMXuaDHToEBKcezYGqGEYnGUi9LMjeb+Kln7X8nn5iknlz4k77rWCbSwLPC/WDr0ySYQA+HagaeUaFpoiYFJKS6uFlK1HYWnM3W4PUiGHg1/xeZlMO44wTwybXVo0y9KMhchfB5XNbDdoJcqWYvi6xtmZZNRbxUyw== + /CN=selfsigned.simplesamlphp.org/O=SimpleSAMLphp HQ/L=Honolulu/ST=Hawaii/C=US + + some + diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_pgenCounter.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_pgenCounter.xml new file mode 100644 index 000000000..f56ccdd46 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_pgenCounter.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_seed.xml b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_seed.xml new file mode 100644 index 000000000..019a5caf5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/simplesamlphp/xml-security/tests/resources/xml/xenc_seed.xml @@ -0,0 +1 @@ +/CTj03d1DB5e2t7CTo9BEzCf5S9NRzwnBgZRlm32REI= diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/.editorconfig b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/.editorconfig new file mode 100644 index 000000000..a604040eb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = tab +insert_final_newline = true +tab_width = 4 +trim_trailing_whitespace = true diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/.typos.toml b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/.typos.toml new file mode 100644 index 000000000..5f43f72e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/.typos.toml @@ -0,0 +1,10 @@ +[files] +extend-exclude = [ + ".git/", +] +ignore-hidden = false + +[default] +extend-ignore-re = [ + "const BA =", +] diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/CODE_OF_CONDUCT.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..162e250c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project maintainer at . All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/LICENSE.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/LICENSE.md new file mode 100644 index 000000000..5e1e4bee3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/LICENSE.md @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2015 Slevomat.cz, s.r.o. + +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/.extlib/simplesamlphp/vendor/slevomat/coding-standard/README.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/README.md new file mode 100644 index 000000000..c13bde58a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/README.md @@ -0,0 +1,319 @@ +# Slevomat Coding Standard + +[![Latest version](https://img.shields.io/packagist/v/slevomat/coding-standard.svg?colorB=007EC6)](https://packagist.org/packages/slevomat/coding-standard) +[![Downloads](https://img.shields.io/packagist/dt/slevomat/coding-standard.svg?colorB=007EC6)](https://packagist.org/packages/slevomat/coding-standard) +[![Build status](https://github.com/slevomat/coding-standard/workflows/Build/badge.svg?branch=master)](https://github.com/slevomat/coding-standard/actions?query=workflow%3ABuild+branch%3Amaster) +[![Code coverage](https://codecov.io/gh/slevomat/coding-standard/branch/master/graph/badge.svg)](https://codecov.io/gh/slevomat/coding-standard) +![PHPStan](https://img.shields.io/badge/style-level%207-brightgreen.svg?&label=phpstan) + +Slevomat Coding Standard for [PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer) provides sniffs that fall into three categories: + +* Functional - improving the safety and behaviour of code +* Cleaning - detecting dead code +* Formatting - rules for consistent code looks + +## Table of contents + +1. [Alphabetical list of sniffs](#alphabetical-list-of-sniffs) +2. [Installation](#installation) +3. [How to run the sniffs](#how-to-run-the-sniffs) + - [Choose which sniffs to run](#choose-which-sniffs-to-run) + - [Exclude sniffs you don't want to run](#exclude-sniffs-you-dont-want-to-run) +4. [Fixing errors automatically](#fixing-errors-automatically) +5. [Suppressing sniffs locally](#suppressing-sniffs-locally) +6. [Contributing](#contributing) + +## Alphabetical list of sniffs + +🔧 = [Automatic errors fixing](#fixing-errors-automatically) + +🚧 = [Sniff check can be suppressed locally](#suppressing-sniffs-locally) + + - [SlevomatCodingStandard.Arrays.AlphabeticallySortedByKeys](doc/arrays.md#slevomatcodingstandardarrayalphabeticallysortedbykeys) 🔧 + - [SlevomatCodingStandard.Arrays.DisallowImplicitArrayCreation](doc/arrays.md#slevomatcodingstandardarraysdisallowimplicitarraycreation) + - [SlevomatCodingStandard.Arrays.DisallowPartiallyKeyed](doc/arrays.md#slevomatcodingstandardarraysdisallowpartiallykeyed) 🚧 + - [SlevomatCodingStandard.Arrays.MultiLineArrayEndBracketPlacement](doc/arrays.md#slevomatcodingstandardarraysmultilinearrayendbracketplacement-) 🔧 + - [SlevomatCodingStandard.Arrays.ArrayAccessSniff.php](doc/arrays.md#slevomatcodingstandardarraysarrayaccess-) 🔧 + - [SlevomatCodingStandard.Arrays.SingleLineArrayWhitespace](doc/arrays.md#slevomatcodingstandardarrayssinglelinearraywhitespace-) 🔧 + - [SlevomatCodingStandard.Arrays.TrailingArrayComma](doc/arrays.md#slevomatcodingstandardarraystrailingarraycomma-) 🔧 + - [SlevomatCodingStandard.Attributes.AttributeAndTargetSpacing](doc/attributes.md#slevomatcodingstandardattributesattributeandtargetspacing-) 🔧 + - [SlevomatCodingStandard.Attributes.AttributesOrder](doc/attributes.md#slevomatcodingstandardattributesattributesorder-) 🔧 + - [SlevomatCodingStandard.Attributes.DisallowAttributesJoining](doc/attributes.md#slevomatcodingstandardattributesdisallowattributesjoining-) 🔧 + - [SlevomatCodingStandard.Attributes.DisallowMultipleAttributesPerLine](doc/attributes.md#slevomatcodingstandardattributesdisallowmultipleattributesperline-) 🔧 + - [SlevomatCodingStandard.Attributes.RequireAttributeAfterDocComment](doc/attributes.md#slevomatcodingstandardattributesrequireattributeafterdoccomment-) 🔧 + - [SlevomatCodingStandard.Classes.BackedEnumTypeSpacing](doc/classes.md#slevomatcodingstandardclassesbackedenumtypespacing-) 🔧 + - [SlevomatCodingStandard.Classes.ClassConstantVisibility](doc/classes.md#slevomatcodingstandardclassesclassconstantvisibility-) 🔧 + - [SlevomatCodingStandard.Classes.ClassLength](doc/classes.md#slevomatcodingstandardclassesclasslength) + - [SlevomatCodingStandard.Classes.ClassMemberSpacing](doc/classes.md#slevomatcodingstandardclassesclassmemberspacing-) 🔧 + - [SlevomatCodingStandard.Classes.ClassStructure](doc/classes.md#slevomatcodingstandardclassesclassstructure-) 🔧 + - [SlevomatCodingStandard.Classes.ConstantSpacing](doc/classes.md#slevomatcodingstandardclassesconstantspacing-) 🔧 + - [SlevomatCodingStandard.Classes.DisallowConstructorPropertyPromotion](doc/classes.md#slevomatcodingstandardclassesdisallowconstructorpropertypromotion) + - [SlevomatCodingStandard.Classes.DisallowLateStaticBindingForConstants](doc/classes.md#slevomatcodingstandardclassesdisallowlatestaticbindingforconstants-) 🔧 + - [SlevomatCodingStandard.Classes.DisallowMultiConstantDefinition](doc/classes.md#slevomatcodingstandardclassesdisallowmulticonstantdefinition-) 🔧 + - [SlevomatCodingStandard.Classes.DisallowMultiPropertyDefinition](doc/classes.md#slevomatcodingstandardclassesdisallowmultipropertydefinition-) 🔧 + - [SlevomatCodingStandard.Classes.DisallowStringExpressionPropertyFetch](doc/classes.md#slevomatcodingstandardclassesdisallowstringexpressionpropertyfetch-) 🔧 + - [SlevomatCodingStandard.Classes.EmptyLinesAroundClassBraces](doc/classes.md#slevomatcodingstandardclassesemptylinesaroundclassbraces-) 🔧 + - [SlevomatCodingStandard.Classes.EnumCaseSpacing](doc/classes.md#slevomatcodingstandardclassesenumcasespacing-) 🔧 + - [SlevomatCodingStandard.Classes.ForbiddenPublicProperty](doc/classes.md#slevomatcodingstandardclassesforbiddenpublicproperty) + - [SlevomatCodingStandard.Classes.MethodSpacing](doc/classes.md#slevomatcodingstandardclassesmethodspacing-) 🔧 + - [SlevomatCodingStandard.Classes.ModernClassNameReference](doc/classes.md#slevomatcodingstandardclassesmodernclassnamereference-) 🔧 + - [SlevomatCodingStandard.Classes.ParentCallSpacing](doc/classes.md#slevomatcodingstandardclassesparentcallspacing-) 🔧 + - [SlevomatCodingStandard.Classes.PropertyDeclaration](doc/classes.md#slevomatcodingstandardclassespropertydeclaration-) 🔧 + - [SlevomatCodingStandard.Classes.PropertySpacing](doc/classes.md#slevomatcodingstandardclassespropertyspacing-) 🔧 + - [SlevomatCodingStandard.Classes.RequireAbstractOrFinal](doc/classes.md#slevomatcodingstandardclassesrequireabstractorfinal-) 🔧 + - [SlevomatCodingStandard.Classes.RequireConstructorPropertyPromotion](doc/classes.md#slevomatcodingstandardclassesrequireconstructorpropertypromotion-) 🔧 + - [SlevomatCodingStandard.Classes.RequireMultiLineMethodSignature](doc/classes.md#slevomatcodingstandardclassesrequiremultilinemethodsignature-) 🔧 + - [SlevomatCodingStandard.Classes.RequireSelfReference](doc/classes.md#slevomatcodingstandardclassesrequireselfreference-) 🔧 + - [SlevomatCodingStandard.Classes.RequireSingleLineMethodSignature](doc/classes.md#slevomatcodingstandardclassesrequiresinglelinemethodsignature-) 🔧 + - [SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming](doc/classes.md#slevomatcodingstandardclassessuperfluousabstractclassnaming) + - [SlevomatCodingStandard.Classes.SuperfluousErrorNaming](doc/classes.md#slevomatcodingstandardclassessuperfluouserrornaming) + - [SlevomatCodingStandard.Classes.SuperfluousExceptionNaming](doc/classes.md#slevomatcodingstandardclassessuperfluousexceptionnaming) + - [SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming](doc/classes.md#slevomatcodingstandardclassessuperfluousinterfacenaming) + - [SlevomatCodingStandard.Classes.SuperfluousTraitNaming](doc/classes.md#slevomatcodingstandardclassessuperfluoustraitnaming) + - [SlevomatCodingStandard.Classes.TraitUseDeclaration](doc/classes.md#slevomatcodingstandardclassestraitusedeclaration-) 🔧 + - [SlevomatCodingStandard.Classes.TraitUseSpacing](doc/classes.md#slevomatcodingstandardclassestraitusespacing-) 🔧 + - [SlevomatCodingStandard.Classes.UselessLateStaticBinding](doc/classes.md#slevomatcodingstandardclassesuselesslatestaticbinding-) 🔧 + - [SlevomatCodingStandard.Commenting.AnnotationName](doc/commenting.md#slevomatcodingstandardcommentingannotationname-) + - [SlevomatCodingStandard.Commenting.DeprecatedAnnotationDeclaration](doc/commenting.md#slevomatcodingstandardcommentingdeprecatedannotationdeclaration) + - [SlevomatCodingStandard.Commenting.DisallowCommentAfterCode](doc/commenting.md#slevomatcodingstandardcommentingdisallowcommentaftercode-) 🔧 + - [SlevomatCodingStandard.Commenting.DisallowOneLinePropertyDocComment](doc/commenting.md#slevomatcodingstandardcommentingdisallowonelinepropertydoccomment-) 🔧 + - [SlevomatCodingStandard.Commenting.DocCommentSpacing](doc/commenting.md#slevomatcodingstandardcommentingdoccommentspacing-) 🔧 + - [SlevomatCodingStandard.Commenting.EmptyComment](doc/commenting.md#slevomatcodingstandardcommentingemptycomment-) 🔧 + - [SlevomatCodingStandard.Commenting.ForbiddenAnnotations](doc/commenting.md#slevomatcodingstandardcommentingforbiddenannotations-) 🔧 + - [SlevomatCodingStandard.Commenting.ForbiddenComments](doc/commenting.md#slevomatcodingstandardcommentingforbiddencomments-) 🔧 + - [SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration](doc/commenting.md#slevomatcodingstandardcommentinginlinedoccommentdeclaration-) 🔧 + - [SlevomatCodingStandard.Commenting.RequireOneLineDocComment](doc/commenting.md#slevomatcodingstandardcommentingrequireonelinedoccomment-) 🔧 + - [SlevomatCodingStandard.Commenting.RequireOneLinePropertyDocComment](doc/commenting.md#slevomatcodingstandardcommentingrequireonelinepropertydoccomment-) 🔧 + - [SlevomatCodingStandard.Commenting.UselessFunctionDocComment](doc/commenting.md#slevomatcodingstandardcommentinguselessfunctiondoccomment-) 🔧 + - [SlevomatCodingStandard.Commenting.UselessInheritDocComment](doc/commenting.md#slevomatcodingstandardcommentinguselessinheritdoccomment-) 🔧 + - [SlevomatCodingStandard.Complexity.Cognitive](doc/complexity.md#slevomatcodingstandardcomplexitycognitive) + - [SlevomatCodingStandard.ControlStructures.AssignmentInCondition](doc/control-structures.md#slevomatcodingstandardcontrolstructuresassignmentincondition) + - [SlevomatCodingStandard.ControlStructures.BlockControlStructureSpacing](doc/control-structures.md#slevomatcodingstandardcontrolstructuresblockcontrolstructurespacing-) 🔧 + - [SlevomatCodingStandard.ControlStructures.DisallowContinueWithoutIntegerOperandInSwitch](doc/control-structures.md#slevomatcodingstandardcontrolstructuresdisallowcontinuewithoutintegeroperandinswitch-) 🔧 + - [SlevomatCodingStandard.ControlStructures.DisallowEmpty](doc/control-structures.md#slevomatcodingstandardcontrolstructuresdisallowempty) + - [SlevomatCodingStandard.ControlStructures.DisallowNullSafeObjectOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresdisallownullsafeobjectoperator) + - [SlevomatCodingStandard.ControlStructures.DisallowShortTernaryOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresdisallowshortternaryoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.DisallowTrailingMultiLineTernaryOperatorSniff](doc/control-structures.md#slevomatcodingstandardcontrolstructuresdisallowtrailingmultilineternaryoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.DisallowYodaComparison](doc/control-structures.md#slevomatcodingstandardcontrolstructuresdisallowyodacomparison-) 🔧 + - [SlevomatCodingStandard.ControlStructures.EarlyExit](doc/control-structures.md#slevomatcodingstandardcontrolstructuresearlyexit-) 🔧 + - [SlevomatCodingStandard.ControlStructures.JumpStatementsSpacing](doc/control-structures.md#slevomatcodingstandardcontrolstructuresjumpstatementsspacing-) 🔧 + - [SlevomatCodingStandard.ControlStructures.LanguageConstructWithParentheses](doc/control-structures.md#slevomatcodingstandardcontrolstructureslanguageconstructwithparentheses-) 🔧 + - [SlevomatCodingStandard.ControlStructures.NewWithParentheses](doc/control-structures.md#slevomatcodingstandardcontrolstructuresnewwithparentheses-) 🔧 + - [SlevomatCodingStandard.ControlStructures.NewWithoutParentheses](doc/control-structures.md#slevomatcodingstandardcontrolstructuresnewwithoutparentheses-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireMultiLineCondition](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequiremultilinecondition-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireMultiLineTernaryOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequiremultilineternaryoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireNullCoalesceEqualOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequirenullcoalesceequaloperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequirenullcoalesceoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireNullSafeObjectOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequirenullsafeobjectoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireShortTernaryOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequireshortternaryoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireSingleLineCondition](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequiresinglelinecondition-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireTernaryOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequireternaryoperator-) 🔧 + - [SlevomatCodingStandard.ControlStructures.RequireYodaComparison](doc/control-structures.md#slevomatcodingstandardcontrolstructuresrequireyodacomparison-) 🔧 + - [SlevomatCodingStandard.ControlStructures.UselessIfConditionWithReturn](doc/control-structures.md#slevomatcodingstandardcontrolstructuresuselessifconditionwithreturn-) 🔧 + - [SlevomatCodingStandard.ControlStructures.UselessTernaryOperator](doc/control-structures.md#slevomatcodingstandardcontrolstructuresuselessternaryoperator-) 🔧 + - [SlevomatCodingStandard.Exceptions.DeadCatch](doc/exceptions.md#slevomatcodingstandardexceptionsdeadcatch) + - [SlevomatCodingStandard.Exceptions.DisallowNonCapturingCatch](doc/exceptions.md#slevomatcodingstandardexceptionsdisallownoncapturingcatch) + - [SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly](doc/exceptions.md#slevomatcodingstandardexceptionsreferencethrowableonly-) 🔧🚧 + - [SlevomatCodingStandard.Exceptions.RequireNonCapturingCatch](doc/exceptions.md#slevomatcodingstandardexceptionsrequirenoncapturingcatch-) 🔧 + - [SlevomatCodingStandard.Files.FileLength](doc/files.md#slevomatcodingstandardfilesfilelength) + - [SlevomatCodingStandard.Files.LineLength](doc/files.md#slevomatcodingstandardfileslinelength) + - [SlevomatCodingStandard.Files.TypeNameMatchesFileName](doc/files.md#slevomatcodingstandardfilestypenamematchesfilename) + - [SlevomatCodingStandard.Functions.ArrowFunctionDeclaration](doc/functions.md#slevomatcodingstandardfunctionsarrowfunctiondeclaration-) 🔧 + - [SlevomatCodingStandard.Functions.DisallowArrowFunction](doc/functions.md#slevomatcodingstandardfunctionsdisallowarrowfunction) + - [SlevomatCodingStandard.Functions.DisallowEmptyFunction](doc/functions.md#slevomatcodingstandardfunctionsdisallowemptyfunction) + - [SlevomatCodingStandard.Functions.DisallowNamedArguments](doc/functions.md#slevomatcodingstandardfunctionsdisallownamedarguments) + - [SlevomatCodingStandard.Functions.DisallowTrailingCommaInCall](doc/functions.md#slevomatcodingstandardfunctionsdisallowtrailingcommaincall-) 🔧 + - [SlevomatCodingStandard.Functions.DisallowTrailingCommaInClosureUse](doc/functions.md#slevomatcodingstandardfunctionsdisallowtrailingcommainclosureuse-) 🔧 + - [SlevomatCodingStandard.Functions.DisallowTrailingCommaInDeclaration](doc/functions.md#slevomatcodingstandardfunctionsdisallowtrailingcommaindeclaration-) 🔧 + - [SlevomatCodingStandard.Functions.FunctionLength](doc/functions.md#slevomatcodingstandardfunctionsfunctionlength) + - [SlevomatCodingStandard.Functions.NamedArgumentSpacing](doc/functions.md#slevomatcodingstandardfunctionsnamedargumentspacing-) 🔧 + - [SlevomatCodingStandard.Functions.RequireArrowFunction](doc/functions.md#slevomatcodingstandardfunctionsrequirearrowfunction-) 🔧 + - [SlevomatCodingStandard.Functions.RequireMultiLineCall](doc/functions.md#slevomatcodingstandardfunctionsrequiremultilinecall-) 🔧 + - [SlevomatCodingStandard.Functions.RequireSingleLineCall](doc/functions.md#slevomatcodingstandardfunctionsrequiresinglelinecall-) 🔧 + - [SlevomatCodingStandard.Functions.RequireTrailingCommaInCall](doc/functions.md#slevomatcodingstandardfunctionsrequiretrailingcommaincall-) 🔧 + - [SlevomatCodingStandard.Functions.RequireTrailingCommaInClosureUse](doc/functions.md#slevomatcodingstandardfunctionsrequiretrailingcommainclosureuse-) 🔧 + - [SlevomatCodingStandard.Functions.RequireTrailingCommaInDeclaration](doc/functions.md#slevomatcodingstandardfunctionsrequiretrailingcommaindeclaration-) 🔧 + - [SlevomatCodingStandard.Functions.StaticClosure](doc/functions.md#slevomatcodingstandardfunctionsstaticclosure-) 🔧 + - [SlevomatCodingStandard.Functions.StrictCall](doc/functions.md#slevomatcodingstandardfunctionsstrictcall) + - [SlevomatCodingStandard.Functions.UnusedInheritedVariablePassedToClosure](doc/functions.md#slevomatcodingstandardfunctionsunusedinheritedvariablepassedtoclosure-) 🔧 + - [SlevomatCodingStandard.Functions.UnusedParameter](doc/functions.md#slevomatcodingstandardfunctionsunusedparameter-) 🚧 + - [SlevomatCodingStandard.Functions.UselessParameterDefaultValue](doc/functions.md#slevomatcodingstandardfunctionsuselessparameterdefaultvalue-) 🚧 + - [SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses](doc/namespaces.md#slevomatcodingstandardnamespacesalphabeticallysorteduses-) 🔧 + - [SlevomatCodingStandard.Namespaces.DisallowGroupUse](doc/namespaces.md#slevomatcodingstandardnamespacesdisallowgroupuse) + - [SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameInAnnotation](doc/namespaces.md#slevomatcodingstandardnamespacesfullyqualifiedclassnameinannotation-) 🔧 + - [SlevomatCodingStandard.Namespaces.FullyQualifiedExceptions](doc/namespaces.md#slevomatcodingstandardnamespacesfullyqualifiedexceptions-) 🔧 + - [SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalConstants](doc/namespaces.md#slevomatcodingstandardnamespacesfullyqualifiedglobalconstants-) 🔧 + - [SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions](doc/namespaces.md#slevomatcodingstandardnamespacesfullyqualifiedglobalfunctions-) 🔧 + - [SlevomatCodingStandard.Namespaces.MultipleUsesPerLine](doc/namespaces.md#slevomatcodingstandardnamespacesmultipleusesperline) + - [SlevomatCodingStandard.Namespaces.NamespaceDeclaration](doc/namespaces.md#slevomatcodingstandardnamespacesnamespacedeclaration-) 🔧 + - [SlevomatCodingStandard.Namespaces.NamespaceSpacing](doc/namespaces.md#slevomatcodingstandardnamespacesnamespacespacing-) 🔧 + - [SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly](doc/namespaces.md#slevomatcodingstandardnamespacesreferenceusednamesonly-) 🔧 + - [SlevomatCodingStandard.Namespaces.RequireOneNamespaceInFile](doc/namespaces.md#slevomatcodingstandardnamespacesrequireonenamespaceinfile) + - [SlevomatCodingStandard.Namespaces.UnusedUses](doc/namespaces.md#slevomatcodingstandardnamespacesunuseduses-) 🔧 + - [SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash](doc/namespaces.md#slevomatcodingstandardnamespacesusedoesnotstartwithbackslash-) 🔧 + - [SlevomatCodingStandard.Namespaces.UseFromSameNamespace](doc/namespaces.md#slevomatcodingstandardnamespacesusefromsamenamespace-) 🔧 + - [SlevomatCodingStandard.Namespaces.UseOnlyWhitelistedNamespaces](doc/namespaces.md#slevomatcodingstandardnamespacesuseonlywhitelistednamespaces) + - [SlevomatCodingStandard.Namespaces.UseSpacing](doc/namespaces.md#slevomatcodingstandardnamespacesusespacing-) 🔧 + - [SlevomatCodingStandard.Namespaces.UselessAlias](doc/namespaces.md#slevomatcodingstandardnamespacesuselessalias-) 🔧 + - [SlevomatCodingStandard.Numbers.DisallowNumericLiteralSeparator](doc/numbers.md#slevomatcodingstandardnumbersdisallownumericliteralseparator-) 🔧 + - [SlevomatCodingStandard.Numbers.RequireNumericLiteralSeparator](doc/numbers.md#slevomatcodingstandardnumbersrequirenumericliteralseparator) + - [SlevomatCodingStandard.Operators.DisallowEqualOperators](doc/operators.md#slevomatcodingstandardoperatorsdisallowequaloperators-) 🔧 + - [SlevomatCodingStandard.Operators.DisallowIncrementAndDecrementOperators](doc/operators.md#slevomatcodingstandardoperatorsdisallowincrementanddecrementoperators) + - [SlevomatCodingStandard.Operators.NegationOperatorSpacing](doc/operators.md#slevomatcodingstandardoperatorsnegationoperatorspacing-) 🔧 + - [SlevomatCodingStandard.Operators.RequireCombinedAssignmentOperator](doc/operators.md#slevomatcodingstandardoperatorsrequirecombinedassignmentoperator-) 🔧 + - [SlevomatCodingStandard.Operators.RequireOnlyStandaloneIncrementAndDecrementOperators](doc/operators.md#slevomatcodingstandardoperatorsrequireonlystandaloneincrementanddecrementoperators) + - [SlevomatCodingStandard.Operators.SpreadOperatorSpacing](doc/operators.md#slevomatcodingstandardoperatorsspreadoperatorspacing-) 🔧 + - [SlevomatCodingStandard.PHP.DisallowDirectMagicInvokeCall](doc/php.md#slevomatcodingstandardphpdisallowdirectmagicinvokecall-) 🔧 + - [SlevomatCodingStandard.PHP.DisallowReference](doc/php.md#slevomatcodingstandardphpdisallowreference) + - [SlevomatCodingStandard.PHP.ForbiddenClasses](doc/php.md#slevomatcodingstandardphpforbiddenclasses-) 🔧 + - [SlevomatCodingStandard.PHP.OptimizedFunctionsWithoutUnpacking](doc/php.md#slevomatcodingstandardphpoptimizedfunctionswithoutunpacking) + - [SlevomatCodingStandard.PHP.ReferenceSpacing](doc/php.md#slevomatcodingstandardphpreferencespacing-) 🔧 + - [SlevomatCodingStandard.PHP.RequireExplicitAssertion](doc/php.md#slevomatcodingstandardphprequireexplicitassertion-) 🔧 + - [SlevomatCodingStandard.PHP.RequireNowdoc](doc/php.md#slevomatcodingstandardphprequirenowdoc-) 🔧 + - [SlevomatCodingStandard.PHP.ShortList](doc/php.md#slevomatcodingstandardphpshortlist-) 🔧 + - [SlevomatCodingStandard.PHP.TypeCast](doc/php.md#slevomatcodingstandardphptypecast-) 🔧 + - [SlevomatCodingStandard.PHP.UselessParentheses](doc/php.md#slevomatcodingstandardphpuselessparentheses-) 🔧 + - [SlevomatCodingStandard.PHP.UselessSemicolon](doc/php.md#slevomatcodingstandardphpuselesssemicolon-) 🔧 + - [SlevomatCodingStandard.Strings.DisallowVariableParsing](doc/strings.md#slevomatcodingstandardstringsdisallowvariableparsing) + - [SlevomatCodingStandard.TypeHints.DeclareStrictTypes](doc/type-hints.md#slevomatcodingstandardtypehintsdeclarestricttypes-) 🔧 + - [SlevomatCodingStandard.TypeHints.DisallowArrayTypeHintSyntax](doc/type-hints.md#slevomatcodingstandardtypehintsdisallowarraytypehintsyntax-) 🔧 + - [SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint](doc/type-hints.md#slevomatcodingstandardtypehintsdisallowmixedtypehint) + - [SlevomatCodingStandard.TypeHints.LongTypeHints](doc/type-hints.md#slevomatcodingstandardtypehintslongtypehints-) 🔧 + - [SlevomatCodingStandard.TypeHints.NullTypeHintOnLastPosition](doc/type-hints.md#slevomatcodingstandardtypehintsnulltypehintonlastposition-) 🔧 + - [SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue](doc/type-hints.md#slevomatcodingstandardtypehintsnullabletypefornulldefaultvalue-) 🔧🚧 + - [SlevomatCodingStandard.TypeHints.ParameterTypeHint](doc/type-hints.md#slevomatcodingstandardtypehintsparametertypehint-) 🔧🚧 + - [SlevomatCodingStandard.TypeHints.ParameterTypeHintSpacing](doc/type-hints.md#slevomatcodingstandardtypehintsparametertypehintspacing-) 🔧 + - [SlevomatCodingStandard.TypeHints.PropertyTypeHint](doc/type-hints.md#slevomatcodingstandardtypehintspropertytypehint-) 🔧🚧 + - [SlevomatCodingStandard.TypeHints.ReturnTypeHint](doc/type-hints.md#slevomatcodingstandardtypehintsreturntypehint-) 🔧🚧 + - [SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing](doc/type-hints.md#slevomatcodingstandardtypehintsreturntypehintspacing-) 🔧 + - [SlevomatCodingStandard.TypeHints.UnionTypeHintFormat](doc/type-hints.md#slevomatcodingstandardtypehintsuniontypehintformat-) 🔧 + - [SlevomatCodingStandard.TypeHints.UselessConstantTypeHint](doc/type-hints.md#slevomatcodingstandardtypehintsuselessconstanttypehint-) 🔧 + - [SlevomatCodingStandard.Variables.DisallowVariableVariable](doc/variables.md#slevomatcodingstandardvariablesdisallowvariablevariable) + - [SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable](doc/variables.md#slevomatcodingstandardvariablesdisallowsuperglobalvariable) + - [SlevomatCodingStandard.Variables.DuplicateAssignmentToVariable](doc/variables.md#slevomatcodingstandardvariablesduplicateassignmenttovariable) + - [SlevomatCodingStandard.Variables.UnusedVariable](doc/variables.md#slevomatcodingstandardvariablesunusedvariable) + - [SlevomatCodingStandard.Variables.UselessVariable](doc/variables.md#slevomatcodingstandardvariablesuselessvariable-) 🔧 + - [SlevomatCodingStandard.Whitespaces.DuplicateSpaces](doc/whitespaces.md#slevomatcodingstandardwhitespacesduplicatespaces-) 🔧 + +## Installation + +The recommended way to install Slevomat Coding Standard is [through Composer](http://getcomposer.org). + +```JSON +{ + "require-dev": { + "slevomat/coding-standard": "~8.0" + } +} +``` + +It's also recommended to install [php-parallel-lint/php-parallel-lint](https://github.com/php-parallel-lint/PHP-Parallel-Lint) which checks source code for syntax errors. Sniffs count on the processed code to be syntactically valid (no parse errors), otherwise they can behave unexpectedly. It is advised to run `PHP-Parallel-Lint` in your build tool before running `PHP_CodeSniffer` and exiting the build process early if `PHP-Parallel-Lint` fails. + +## How to run the sniffs + +You can choose one of two ways to run only selected sniffs from the standard on your codebase: + +### Choose which sniffs to run + +The recommended way is to write your own ruleset.xml by referencing only the selected sniffs. This is a sample ruleset.xml: + +```xml + + + + + + +``` + +Then run the `phpcs` executable the usual way: + +``` +vendor/bin/phpcs --standard=ruleset.xml --extensions=php --tab-width=4 -sp src tests +``` + +### Exclude sniffs you don't want to run + +You can also mention Slevomat Coding Standard in your project's `ruleset.xml` and exclude only some sniffs: + +```xml + + + + + + +``` + +However it is not a recommended way to use Slevomat Coding Standard, because your build can break when moving between minor versions of the standard (which can happen if you use `^` or `~` version constraint in `composer.json`). We regularly add new sniffs even in minor versions meaning your code won't most likely comply with new minor versions of the package. + +## Fixing errors automatically + +Sniffs in this standard marked by the 🔧 symbol support [automatic fixing of coding standard violations](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/Fixing-Errors-Automatically). To fix your code automatically, run phpcbf instead of phpcs: + +``` +vendor/bin/phpcbf --standard=ruleset.xml --extensions=php --tab-width=4 -sp src tests +``` + +Always remember to back up your code before performing automatic fixes and check the results with your own eyes as the automatic fixer can sometimes produce unwanted results. + +## Suppressing sniffs locally + +Selected sniffs in this standard marked by the 🚧 symbol can be suppressed for a specific piece of code using an annotation. Consider the following example: + +```php +/** + * @param int $max + */ +public function createProgressBar($max = 0): ProgressBar +{ + +} +``` + +The parameter `$max` could have a native `int` scalar typehint. But because the method in the parent class does not have this typehint, so this one cannot have it either. PHP_CodeSniffer shows a following error: + +``` +---------------------------------------------------------------------- +FOUND 1 ERROR AFFECTING 1 LINE +---------------------------------------------------------------------- + 67 | ERROR | [x] Method ErrorsConsoleStyle::createProgressBar() + | | does not have native type hint for its parameter $max + | | but it should be possible to add it based on @param + | | annotation "int". + | | (SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint) +``` + +If we want to suppress this error instead of fixing it, we can take the error code (`SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint`) and use it with a `@phpcsSuppress` annotation like this: + +```php +/** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $max + */ +public function createProgressBar($max = 0): ProgressBar +{ + +} +``` + +## Contributing + +To make this repository work on your machine, clone it and run these two commands in the root directory of the repository: + +``` +composer install +bin/phing +``` + +After writing some code and editing or adding unit tests, run phing again to check that everything is OK: + +``` +bin/phing +``` + +We are always looking forward to your bugreports, feature requests and pull requests. Thank you. + +## Code of Conduct + +This project adheres to a [Contributor Code of Conduct](https://github.com/slevomat/coding-standard/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Annotation.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Annotation.php new file mode 100644 index 000000000..d5b6343c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Annotation.php @@ -0,0 +1,66 @@ +node = $node; + $this->startPointer = $startPointer; + $this->endPointer = $endPointer; + } + + public function getNode(): PhpDocTagNode + { + return $this->node; + } + + public function getName(): string + { + return $this->node->name; + } + + /** + * @return T + */ + public function getValue(): PhpDocTagValueNode + { + /** @phpstan-ignore-next-line */ + return $this->node->value; + } + + public function getStartPointer(): int + { + return $this->startPointer; + } + + public function getEndPointer(): int + { + return $this->endPointer; + } + + public function isInvalid(): bool + { + return $this->node->value instanceof InvalidTagValueNode; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationHelper.php new file mode 100644 index 000000000..108a4e3c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationHelper.php @@ -0,0 +1,366 @@ + + */ + public static function getAnnotations(File $phpcsFile, int $pointer, ?string $name = null): array + { + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $pointer); + if ($docCommentOpenPointer === null) { + return []; + } + + return SniffLocalCache::getAndSetIfNotCached( + $phpcsFile, + sprintf('annotations-%d-%s', $docCommentOpenPointer, $name ?? 'all'), + static function () use ($phpcsFile, $docCommentOpenPointer, $name): array { + $annotations = []; + + if ($name !== null) { + foreach (self::getAnnotations($phpcsFile, $docCommentOpenPointer) as $annotation) { + if ($annotation->getName() === $name) { + $annotations[] = $annotation; + } + } + } else { + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + if ($parsedDocComment !== null) { + foreach ($parsedDocComment->getNode()->getTags() as $node) { + $annotationStartPointer = $parsedDocComment->getNodeStartPointer($phpcsFile, $node); + $annotations[] = new Annotation( + $node, + $annotationStartPointer, + $parsedDocComment->getNodeEndPointer($phpcsFile, $node, $annotationStartPointer) + ); + } + } + } + + return $annotations; + } + ); + } + + /** + * @param class-string $type + * @return list + */ + public static function getAnnotationNodesByType(Node $node, string $type): array + { + static $visitor; + static $traverser; + + if ($visitor === null) { + $visitor = new class extends AbstractNodeVisitor { + + /** @var class-string */ + private $type; + + /** @var list */ + private $nodes = []; + + /** @var list */ + private $nodesToIgnore = []; + + /** + * @return Node|list|NodeTraverser::*|null + */ + public function enterNode(Node $node) + { + if ($this->type === IdentifierTypeNode::class) { + if ($node instanceof ArrayShapeItemNode || $node instanceof ObjectShapeItemNode) { + $this->nodesToIgnore[] = $node->keyName; + } elseif ($node instanceof DoctrineArgument) { + $this->nodesToIgnore[] = $node->key; + } + } + + if ($node instanceof $this->type && !in_array($node, $this->nodesToIgnore, true)) { + $this->nodes[] = $node; + } + + return null; + } + + /** + * @param class-string $type + */ + public function setType(string $type): void + { + $this->type = $type; + } + + public function clean(): void + { + $this->nodes = []; + $this->nodesToIgnore = []; + } + + /** + * @return list + */ + public function getNodes(): array + { + return $this->nodes; + } + + }; + } + + if ($traverser === null) { + $traverser = new NodeTraverser([$visitor]); + } + + $visitor->setType($type); + $visitor->clean(); + + $traverser->traverse([$node]); + + return $visitor->getNodes(); + } + + public static function fixAnnotation( + ParsedDocComment $parsedDocComment, + Annotation $annotation, + Node $nodeToFix, + Node $fixedNode + ): string + { + $originalNode = $annotation->getNode(); + + /** @var PhpDocNode $newPhpDocNode */ + $newPhpDocNode = PhpDocParserHelper::cloneNode($parsedDocComment->getNode()); + + foreach ($newPhpDocNode->getTags() as $node) { + if ($node->getAttribute(Attribute::ORIGINAL_NODE) === $originalNode) { + self::changeAnnotationNode($node, $nodeToFix, $fixedNode); + break; + } + } + + return PhpDocParserHelper::getPrinter()->printFormatPreserving( + $newPhpDocNode, + $parsedDocComment->getNode(), + $parsedDocComment->getTokens() + ); + } + + /** + * @param array $traversableTypeHints + */ + public static function isAnnotationUseless( + File $phpcsFile, + int $functionPointer, + ?TypeHint $typeHint, + Annotation $annotation, + array $traversableTypeHints, + bool $enableUnionTypeHint = false, + bool $enableIntersectionTypeHint = false, + bool $enableStandaloneNullTrueFalseTypeHints = false + ): bool + { + if ($annotation->isInvalid()) { + return false; + } + + if ($typeHint === null) { + return false; + } + + /** @var ParamTagValueNode|TypelessParamTagValueNode|ReturnTagValueNode|VarTagValueNode $annotationValue */ + $annotationValue = $annotation->getValue(); + + if ($annotationValue->description !== '') { + return false; + } + + if ($annotationValue instanceof TypelessParamTagValueNode) { + return true; + } + + $annotationType = $annotationValue->type; + + if ( + TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $functionPointer, $typeHint->getTypeHintWithoutNullabilitySymbol()), + $traversableTypeHints + ) + && !( + $annotationType instanceof IdentifierTypeNode + && TypeHintHelper::isSimpleIterableTypeHint(strtolower($annotationType->name)) + ) + ) { + return false; + } + + if (AnnotationTypeHelper::containsStaticOrThisType($annotationType)) { + return false; + } + + if ( + AnnotationTypeHelper::containsJustTwoTypes($annotationType) + || ( + $enableUnionTypeHint + && ( + $annotationType instanceof UnionTypeNode + || ( + $annotationType instanceof IdentifierTypeNode + && TypeHintHelper::isUnofficialUnionTypeHint($annotationType->name) + ) + ) + ) + || ( + $enableIntersectionTypeHint + && $annotationType instanceof IntersectionTypeNode + ) + ) { + $annotationTypeHint = AnnotationTypeHelper::print($annotationType); + return TypeHintHelper::typeHintEqualsAnnotation( + $phpcsFile, + $functionPointer, + $typeHint->getTypeHint(), + $annotationTypeHint + ); + } + + if ($annotationType instanceof ObjectShapeNode) { + return false; + } + + if ($annotationType instanceof ConstTypeNode) { + return false; + } + + if ($annotationType instanceof GenericTypeNode) { + return false; + } + + if ($annotationType instanceof CallableTypeNode) { + return false; + } + + if ($annotationType instanceof ConditionalTypeNode) { + return false; + } + + if ($annotationType instanceof ConditionalTypeForParameterNode) { + return false; + } + + if ($annotationType instanceof IdentifierTypeNode) { + if (in_array( + strtolower($annotationType->name), + ['true', 'false', 'null'], + true + )) { + return $enableStandaloneNullTrueFalseTypeHints; + } + + if (in_array( + strtolower($annotationType->name), + ['class-string', 'trait-string', 'callable-string', 'numeric-string', 'non-empty-string', 'non-falsy-string', 'literal-string', 'positive-int', 'negative-int'], + true + )) { + return false; + } + } + + $annotationTypeHint = AnnotationTypeHelper::getTypeHintFromOneType($annotationType); + return TypeHintHelper::typeHintEqualsAnnotation( + $phpcsFile, + $functionPointer, + $typeHint->getTypeHintWithoutNullabilitySymbol(), + $annotationTypeHint + ); + } + + private static function changeAnnotationNode(PhpDocTagNode $tagNode, Node $nodeToChange, Node $changedNode): PhpDocTagNode + { + static $visitor; + static $traverser; + + if ($visitor === null) { + $visitor = new class extends AbstractNodeVisitor { + + /** @var Node */ + private $nodeToChange; + + /** @var Node */ + private $changedNode; + + /** + * @return Node|list|NodeTraverser::*|null + */ + public function enterNode(Node $node) + { + if ($node->getAttribute(Attribute::ORIGINAL_NODE) === $this->nodeToChange) { + return $this->changedNode; + } + + return null; + } + + public function setNodeToChange(Node $nodeToChange): void + { + $this->nodeToChange = $nodeToChange; + } + + public function setChangedNode(Node $changedNode): void + { + $this->changedNode = $changedNode; + } + + }; + } + + if ($traverser === null) { + $traverser = new NodeTraverser([$visitor]); + } + + $visitor->setNodeToChange($nodeToChange); + $visitor->setChangedNode($changedNode); + + [$changedTagNode] = $traverser->traverse([$tagNode]); + + return $changedTagNode; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationTypeHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationTypeHelper.php new file mode 100644 index 000000000..058c5b33e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationTypeHelper.php @@ -0,0 +1,409 @@ +print($typeNode); + } + + public static function containsStaticOrThisType(TypeNode $typeNode): bool + { + if ($typeNode instanceof ThisTypeNode) { + return true; + } + + if ($typeNode instanceof IdentifierTypeNode) { + return strtolower($typeNode->name) === 'static'; + } + + if ( + $typeNode instanceof UnionTypeNode + || $typeNode instanceof IntersectionTypeNode + ) { + foreach ($typeNode->types as $innerTypeNode) { + if (self::containsStaticOrThisType($innerTypeNode)) { + return true; + } + } + } + + return false; + } + + public static function containsOneType(TypeNode $typeNode): bool + { + if ($typeNode instanceof IdentifierTypeNode) { + return true; + } + + if ($typeNode instanceof ThisTypeNode) { + return true; + } + + if ($typeNode instanceof GenericTypeNode) { + return true; + } + + if ($typeNode instanceof CallableTypeNode) { + return true; + } + + if ($typeNode instanceof ObjectShapeNode) { + return true; + } + + if ($typeNode instanceof ArrayShapeNode) { + return true; + } + + if ($typeNode instanceof ArrayTypeNode) { + return true; + } + + if ($typeNode instanceof ConstTypeNode) { + if ($typeNode->constExpr instanceof ConstExprIntegerNode) { + return true; + } + + if ($typeNode->constExpr instanceof ConstExprFloatNode) { + return true; + } + + if ($typeNode->constExpr instanceof ConstExprStringNode) { + return true; + } + } + + return false; + } + + public static function containsJustTwoTypes(TypeNode $typeNode): bool + { + if ($typeNode instanceof NullableTypeNode && self::containsOneType($typeNode->type)) { + return true; + } + + if ( + !$typeNode instanceof UnionTypeNode + && !$typeNode instanceof IntersectionTypeNode + ) { + return false; + } + + return count($typeNode->types) === 2; + } + + /** + * @param array $traversableTypeHints + */ + public static function containsTraversableType(TypeNode $typeNode, File $phpcsFile, int $pointer, array $traversableTypeHints): bool + { + if ($typeNode instanceof GenericTypeNode) { + return true; + } + + if ($typeNode instanceof ObjectShapeNode) { + return false; + } + + if ($typeNode instanceof ArrayShapeNode) { + return true; + } + + if ($typeNode instanceof ArrayTypeNode) { + return true; + } + + if ($typeNode instanceof IdentifierTypeNode) { + $fullyQualifiedType = TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $pointer, $typeNode->name); + return TypeHintHelper::isTraversableType($fullyQualifiedType, $traversableTypeHints); + } + + if ( + $typeNode instanceof UnionTypeNode + || $typeNode instanceof IntersectionTypeNode + ) { + foreach ($typeNode->types as $innerTypeNode) { + if (self::containsTraversableType($innerTypeNode, $phpcsFile, $pointer, $traversableTypeHints)) { + return true; + } + } + } + + return + ( + $typeNode instanceof ConditionalTypeNode + || $typeNode instanceof ConditionalTypeForParameterNode + ) && ( + self::containsTraversableType($typeNode->if, $phpcsFile, $pointer, $traversableTypeHints) + || self::containsTraversableType($typeNode->else, $phpcsFile, $pointer, $traversableTypeHints) + ); + } + + /** + * @param array $traversableTypeHints + */ + public static function containsItemsSpecificationForTraversable( + TypeNode $typeNode, + File $phpcsFile, + int $pointer, + array $traversableTypeHints, + bool $inTraversable = false + ): bool + { + if ($typeNode instanceof GenericTypeNode) { + foreach ($typeNode->genericTypes as $genericType) { + if (!self::containsItemsSpecificationForTraversable($genericType, $phpcsFile, $pointer, $traversableTypeHints, true)) { + return false; + } + } + + return true; + } + + if ($typeNode instanceof ArrayShapeNode) { + foreach ($typeNode->items as $arrayShapeItemNode) { + if (!self::containsItemsSpecificationForTraversable( + $arrayShapeItemNode->valueType, + $phpcsFile, + $pointer, + $traversableTypeHints, + true + )) { + return false; + } + } + + return true; + } + + if ($typeNode instanceof NullableTypeNode) { + return self::containsItemsSpecificationForTraversable($typeNode->type, $phpcsFile, $pointer, $traversableTypeHints, true); + } + + if ($typeNode instanceof IdentifierTypeNode) { + if (TypeHintHelper::isTypeDefinedInAnnotation($phpcsFile, $pointer, $typeNode->name)) { + // We can expect it's better type for traversable + return true; + } + + if (!$inTraversable) { + return false; + } + + return !TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $pointer, $typeNode->name), + $traversableTypeHints + ); + } + + if ($typeNode instanceof ConstTypeNode) { + return $inTraversable; + } + + if ($typeNode instanceof CallableTypeNode) { + return $inTraversable; + } + + if ($typeNode instanceof ArrayTypeNode) { + return self::containsItemsSpecificationForTraversable($typeNode->type, $phpcsFile, $pointer, $traversableTypeHints, true); + } + + if ( + $typeNode instanceof UnionTypeNode + || $typeNode instanceof IntersectionTypeNode + ) { + foreach ($typeNode->types as $innerTypeNode) { + if ( + !$inTraversable + && $innerTypeNode instanceof IdentifierTypeNode + && strtolower($innerTypeNode->name) === 'null' + ) { + continue; + } + + if (self::containsItemsSpecificationForTraversable( + $innerTypeNode, + $phpcsFile, + $pointer, + $traversableTypeHints, + $inTraversable + )) { + return true; + } + } + } + + if ($typeNode instanceof ConditionalTypeNode || $typeNode instanceof ConditionalTypeForParameterNode) { + return + self::containsItemsSpecificationForTraversable($typeNode->if, $phpcsFile, $pointer, $traversableTypeHints, $inTraversable) + || self::containsItemsSpecificationForTraversable( + $typeNode->else, + $phpcsFile, + $pointer, + $traversableTypeHints, + $inTraversable + ); + } + + return false; + } + + public static function getTypeHintFromOneType( + TypeNode $typeNode, + bool $enableUnionTypeHint = false, + bool $enableStandaloneNullTrueFalseTypeHints = false + ): string + { + if ($typeNode instanceof GenericTypeNode) { + $genericName = $typeNode->type->name; + + if (in_array(strtolower($genericName), ['non-empty-array', 'list', 'non-empty-list'], true)) { + return 'array'; + } + + return $genericName; + } + + if ($typeNode instanceof IdentifierTypeNode) { + if (strtolower($typeNode->name) === 'true') { + return $enableStandaloneNullTrueFalseTypeHints ? 'true' : 'bool'; + } + + if (strtolower($typeNode->name) === 'false') { + return $enableUnionTypeHint || $enableStandaloneNullTrueFalseTypeHints ? 'false' : 'bool'; + } + + if (in_array(strtolower($typeNode->name), ['positive-int', 'negative-int'], true)) { + return 'int'; + } + + if (in_array( + strtolower($typeNode->name), + ['class-string', 'trait-string', 'callable-string', 'numeric-string', 'non-empty-string', 'non-falsy-string', 'literal-string'], + true + )) { + return 'string'; + } + + return $typeNode->name; + } + + if ($typeNode instanceof CallableTypeNode) { + return $typeNode->identifier->name; + } + + if ($typeNode instanceof ArrayTypeNode) { + return 'array'; + } + + if ($typeNode instanceof ArrayShapeNode) { + return 'array'; + } + + if ($typeNode instanceof ObjectShapeNode) { + return 'object'; + } + + if ($typeNode instanceof ConstTypeNode) { + if ($typeNode->constExpr instanceof ConstExprIntegerNode) { + return 'int'; + } + + if ($typeNode->constExpr instanceof ConstExprFloatNode) { + return 'float'; + } + + if ($typeNode->constExpr instanceof ConstExprStringNode) { + return 'string'; + } + } + + return (string) $typeNode; + } + + /** + * @param UnionTypeNode|IntersectionTypeNode $typeNode + * @param array $traversableTypeHints + * @return list + */ + public static function getTraversableTypeHintsFromType( + TypeNode $typeNode, + File $phpcsFile, + int $pointer, + array $traversableTypeHints, + bool $enableUnionTypeHint = false + ): array + { + $typeHints = []; + + foreach ($typeNode->types as $type) { + if ( + $type instanceof GenericTypeNode + || $type instanceof ThisTypeNode + || $type instanceof IdentifierTypeNode + ) { + $typeHints[] = self::getTypeHintFromOneType($type); + } + } + + if (!$enableUnionTypeHint && count($typeHints) > 1) { + return []; + } + + foreach ($typeHints as $typeHint) { + if (!TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $pointer, $typeHint), + $traversableTypeHints + )) { + return []; + } + } + + return $typeHints; + } + + /** + * @param UnionTypeNode|IntersectionTypeNode $typeNode + */ + public static function getItemsSpecificationTypeFromType(TypeNode $typeNode): ?TypeNode + { + foreach ($typeNode->types as $type) { + if ($type instanceof ArrayTypeNode) { + return $type; + } + } + + return null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayHelper.php new file mode 100644 index 000000000..8bf354b48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayHelper.php @@ -0,0 +1,232 @@ + + */ + public static function parse(File $phpcsFile, int $arrayPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $arrayToken = $tokens[$arrayPointer]; + [$arrayOpenerPointer, $arrayCloserPointer] = self::openClosePointers($arrayToken); + + $keyValues = []; + + $firstPointerOnNextLine = TokenHelper::findFirstTokenOnNextLine($phpcsFile, $arrayOpenerPointer + 1); + $firstEffectivePointer = TokenHelper::findNextEffective($phpcsFile, $arrayOpenerPointer + 1); + + $arrayKeyValueStartPointer = $firstPointerOnNextLine !== null && $firstPointerOnNextLine < $firstEffectivePointer + ? $firstPointerOnNextLine + : $firstEffectivePointer; + $arrayKeyValueEndPointer = $arrayKeyValueStartPointer; + + $indentation = $tokens[$arrayOpenerPointer]['line'] < $tokens[$firstEffectivePointer]['line'] + ? IndentationHelper::getIndentation($phpcsFile, $firstEffectivePointer) + : ''; + + for ($i = $arrayKeyValueStartPointer; $i < $arrayCloserPointer; $i++) { + $token = $tokens[$i]; + + if (in_array($token['code'], TokenHelper::$arrayTokenCodes, true)) { + $i = self::openClosePointers($token)[1]; + continue; + } + + if (array_key_exists('scope_closer', $token) && $token['scope_closer'] > $i) { + $i = $token['scope_closer'] - 1; + continue; + } + + if (array_key_exists('parenthesis_closer', $token) && $token['parenthesis_closer'] > $i) { + $i = $token['parenthesis_closer'] - 1; + continue; + } + + $nextEffectivePointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + + if ($nextEffectivePointer === $arrayCloserPointer) { + $arrayKeyValueEndPointer = self::getValueEndPointer($phpcsFile, $i, $arrayCloserPointer, $indentation); + break; + } + + if ($token['code'] !== T_COMMA || !ScopeHelper::isInSameScope($phpcsFile, $arrayOpenerPointer, $i)) { + $arrayKeyValueEndPointer = $i; + continue; + } + + $arrayKeyValueEndPointer = self::getValueEndPointer($phpcsFile, $i, $arrayCloserPointer, $indentation); + + $keyValues[] = new ArrayKeyValue($phpcsFile, $arrayKeyValueStartPointer, $arrayKeyValueEndPointer); + + $arrayKeyValueStartPointer = $arrayKeyValueEndPointer + 1; + $i = $arrayKeyValueEndPointer; + } + + $keyValues[] = new ArrayKeyValue($phpcsFile, $arrayKeyValueStartPointer, $arrayKeyValueEndPointer); + + return $keyValues; + } + + /** + * @param list $keyValues + */ + public static function getIndentation(array $keyValues): ?string + { + $indents = []; + foreach ($keyValues as $keyValue) { + $indent = $keyValue->getIndent() ?? 'null'; + $indents[$indent] = isset($indents[$indent]) + ? $indents[$indent] + 1 + : 1; + } + arsort($indents); + $indent = key($indents); + return $indent !== 'null' + ? (string) $indent + : null; + } + + /** + * @param list $keyValues + */ + public static function isKeyed(array $keyValues): bool + { + foreach ($keyValues as $keyValue) { + if ($keyValue->getKey() !== null) { + return true; + } + } + return false; + } + + /** + * @param list $keyValues + */ + public static function isKeyedAll(array $keyValues): bool + { + foreach ($keyValues as $keyValue) { + if (!$keyValue->isUnpacking() && $keyValue->getKey() === null) { + return false; + } + } + return true; + } + + /** + * Test if non-empty array with opening & closing brackets on separate lines + */ + public static function isMultiLine(File $phpcsFile, int $pointer): bool + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$pointer]; + [$pointerOpener, $pointerCloser] = self::openClosePointers($token); + $tokenOpener = $tokens[$pointerOpener]; + $tokenCloser = $tokens[$pointerCloser]; + + return $tokenOpener['line'] !== $tokenCloser['line']; + } + + /** + * Test if effective tokens between open & closing tokens + */ + public static function isNotEmpty(File $phpcsFile, int $pointer): bool + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$pointer]; + [$pointerOpener, $pointerCloser] = self::openClosePointers($token); + + /** @var int $pointerPreviousToClose */ + $pointerPreviousToClose = TokenHelper::findPreviousEffective($phpcsFile, $pointerCloser - 1); + + return $pointerPreviousToClose !== $pointerOpener; + } + + /** + * @param list $keyValues + */ + public static function isSortedByKey(array $keyValues): bool + { + $previousKey = ''; + foreach ($keyValues as $keyValue) { + if ($keyValue->isUnpacking()) { + continue; + } + + if (strnatcasecmp($previousKey, $keyValue->getKey()) === 1) { + return false; + } + + $previousKey = $keyValue->getKey(); + } + + return true; + } + + /** + * @param array|int|string> $token + * @return array{0: int, 1: int} + */ + public static function openClosePointers(array $token): array + { + $isShortArray = $token['code'] === T_OPEN_SHORT_ARRAY; + $pointerOpener = $isShortArray + ? $token['bracket_opener'] + : $token['parenthesis_opener']; + $pointerCloser = $isShortArray + ? $token['bracket_closer'] + : $token['parenthesis_closer']; + return [(int) $pointerOpener, (int) $pointerCloser]; + } + + private static function getValueEndPointer(File $phpcsFile, int $endPointer, int $arrayCloserPointer, string $indentation): int + { + $tokens = $phpcsFile->getTokens(); + + $nextEffectivePointer = TokenHelper::findNextEffective($phpcsFile, $endPointer + 1, $arrayCloserPointer + 1); + + if ($tokens[$nextEffectivePointer]['line'] === $tokens[$endPointer]['line']) { + return $nextEffectivePointer - 1; + } + + for ($i = $endPointer + 1; $i < $nextEffectivePointer; $i++) { + if ($tokens[$i]['line'] === $tokens[$endPointer]['line']) { + $endPointer = $i; + continue; + } + + $nextNonWhitespacePointer = TokenHelper::findNextNonWhitespace($phpcsFile, $i); + + if (!in_array($tokens[$nextNonWhitespacePointer]['code'], TokenHelper::$inlineCommentTokenCodes, true)) { + break; + } + + if ($indentation === IndentationHelper::getIndentation($phpcsFile, $nextNonWhitespacePointer)) { + $endPointer = $i - 1; + break; + } + + $i = TokenHelper::findLastTokenOnLine($phpcsFile, $i); + $endPointer = $i; + } + + return $endPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayKeyValue.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayKeyValue.php new file mode 100644 index 000000000..3588426df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ArrayKeyValue.php @@ -0,0 +1,172 @@ +pointerStart = $pointerStart; + $this->pointerEnd = $pointerEnd; + $this->addValues($phpcsFile); + } + + public function getContent(File $phpcsFile, bool $normalize = false, ?string $indent = null): string + { + if ($normalize === false) { + return TokenHelper::getContent($phpcsFile, $this->pointerStart, $this->pointerEnd); + } + $content = ''; + $addCommaPtr = $this->pointerComma === null + ? TokenHelper::findPreviousEffective($phpcsFile, $this->pointerEnd) + : null; + $tokens = $phpcsFile->getTokens(); + for ($pointer = $this->pointerStart; $pointer <= $this->pointerEnd; $pointer++) { + $token = $tokens[$pointer]; + $content .= $token['content']; + if ($pointer === $addCommaPtr) { + $content .= ','; + } + } + + // Trim, but keep leading empty lines + $content = ltrim($content, " \t"); + $content = rtrim($content); + + if ($indent !== null && strpos($content, $phpcsFile->eolChar) !== 0) { + $content = $indent . $content; + } + + return $content; + } + + public function getIndent(): ?string + { + return $this->indent; + } + + public function getKey(): ?string + { + return $this->key; + } + + public function getPointerArrow(): ?int + { + return $this->pointerArrow; + } + + public function getPointerComma(): ?int + { + return $this->pointerComma; + } + + public function getPointerEnd(): int + { + return $this->pointerEnd; + } + + public function getPointerStart(): int + { + return $this->pointerStart; + } + + public function isUnpacking(): bool + { + return $this->unpacking; + } + + private function addValues(File $phpcsFile): void + { + $key = ''; + $tokens = $phpcsFile->getTokens(); + $firstNonWhitespace = null; + + for ($i = $this->pointerStart; $i <= $this->pointerEnd; $i++) { + $token = $tokens[$i]; + + if (in_array($token['code'], TokenHelper::$arrayTokenCodes, true)) { + $i = ArrayHelper::openClosePointers($token)[1]; + continue; + } + + if ($token['code'] === T_DOUBLE_ARROW) { + $this->pointerArrow = $i; + continue; + } + + if ($token['code'] === T_COMMA) { + $this->pointerComma = $i; + continue; + + } + + if ($token['code'] === T_ELLIPSIS) { + $this->unpacking = true; + continue; + } + + if ($this->pointerArrow !== null) { + continue; + } + + if ($firstNonWhitespace === null && $token['code'] !== T_WHITESPACE) { + $firstNonWhitespace = $i; + } + + if (in_array($token['code'], TokenHelper::$inlineCommentTokenCodes, true) === false) { + $key .= $token['content']; + } + } + $haveIndent = $firstNonWhitespace !== null && TokenHelper::findFirstNonWhitespaceOnLine( + $phpcsFile, + $firstNonWhitespace + ) === $firstNonWhitespace; + $this->indent = $haveIndent + ? TokenHelper::getContent( + $phpcsFile, + TokenHelper::findFirstTokenOnLine($phpcsFile, $firstNonWhitespace), + $firstNonWhitespace - 1 + ) + : null; + $this->key = $this->pointerArrow !== null + ? trim($key) + : null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Attribute.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Attribute.php new file mode 100644 index 000000000..bc6cb89b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Attribute.php @@ -0,0 +1,60 @@ +attributePointer = $attributePointer; + $this->name = $name; + $this->startPointer = $startPointer; + $this->endPointer = $endPointer; + $this->content = $content; + } + + public function getAttributePointer(): int + { + return $this->attributePointer; + } + + public function getName(): string + { + return $this->name; + } + + public function getStartPointer(): int + { + return $this->startPointer; + } + + public function getEndPointer(): int + { + return $this->endPointer; + } + + public function getContent(): ?string + { + return $this->content; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AttributeHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AttributeHelper.php new file mode 100644 index 000000000..c5ce72ee4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AttributeHelper.php @@ -0,0 +1,153 @@ + + */ + public static function getAttributes(File $phpcsFile, int $attributeOpenerPointer): array + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$attributeOpenerPointer]['code'] !== T_ATTRIBUTE) { + throw new InvalidArgumentException( + sprintf('Token %d must be attribute, %s given.', $attributeOpenerPointer, $tokens[$attributeOpenerPointer]['type']) + ); + } + + $attributeCloserPointer = $tokens[$attributeOpenerPointer]['attribute_closer']; + + $actualPointer = $attributeOpenerPointer; + $attributes = []; + + do { + $attributeNameStartPointer = TokenHelper::findNextEffective($phpcsFile, $actualPointer + 1, $attributeCloserPointer); + + if ($attributeNameStartPointer === null) { + break; + } + + $attributeNameEndPointer = TokenHelper::findNextExcluding( + $phpcsFile, + TokenHelper::getNameTokenCodes(), + $attributeNameStartPointer + 1 + ) - 1; + $attributeName = TokenHelper::getContent($phpcsFile, $attributeNameStartPointer, $attributeNameEndPointer); + + $pointerAfterAttributeName = TokenHelper::findNextEffective($phpcsFile, $attributeNameEndPointer + 1, $attributeCloserPointer); + + if ($pointerAfterAttributeName === null) { + $attributes[] = new Attribute( + $attributeOpenerPointer, + $attributeName, + $attributeNameStartPointer, + $attributeNameEndPointer + ); + break; + } + + if ($tokens[$pointerAfterAttributeName]['code'] === T_COMMA) { + $attributes[] = new Attribute( + $attributeOpenerPointer, + $attributeName, + $attributeNameStartPointer, + $attributeNameEndPointer + ); + + $actualPointer = $pointerAfterAttributeName; + } + + if ($tokens[$pointerAfterAttributeName]['code'] === T_OPEN_PARENTHESIS) { + $attributes[] = new Attribute( + $attributeOpenerPointer, + $attributeName, + $attributeNameStartPointer, + $tokens[$pointerAfterAttributeName]['parenthesis_closer'], + TokenHelper::getContent( + $phpcsFile, + $pointerAfterAttributeName, + $tokens[$pointerAfterAttributeName]['parenthesis_closer'] + ) + ); + + $actualPointer = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$pointerAfterAttributeName]['parenthesis_closer'] + 1, + $attributeCloserPointer + ); + + continue; + } + + } while ($actualPointer !== null); + + return $attributes; + } + + /** + * Attributes have syntax that when defined incorrectly or in older PHP version, they are treated as comments. + * An example of incorrect declaration is variables that are not properties. + */ + public static function isValidAttribute(File $phpcsFile, int $attributeOpenerPointer): bool + { + return self::getAttributeTarget($phpcsFile, $attributeOpenerPointer) !== null; + } + + public static function getAttributeTarget(File $phpcsFile, int $attributeOpenerPointer): ?int + { + $attributeTargetPointer = TokenHelper::findNext($phpcsFile, self::ATTRIBUTE_TARGETS, $attributeOpenerPointer); + + if ($attributeTargetPointer === null) { + return null; + } + + if ( + $phpcsFile->getTokens()[$attributeTargetPointer]['code'] === T_VARIABLE + && !PropertyHelper::isProperty($phpcsFile, $attributeTargetPointer) + && !ParameterHelper::isParameter($phpcsFile, $attributeTargetPointer) + ) { + return null; + } + + return $attributeTargetPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CatchHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CatchHelper.php new file mode 100644 index 000000000..b188b40d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CatchHelper.php @@ -0,0 +1,83 @@ +getTokens(); + + $endPointer = $tokens[$catchPointer]['scope_closer']; + + do { + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $endPointer + 1); + + if ($nextPointer === null || !in_array($tokens[$nextPointer]['code'], [T_CATCH, T_FINALLY], true)) { + break; + } + + $endPointer = $tokens[$nextPointer]['scope_closer']; + + } while (true); + + return $endPointer; + } + + /** + * @param array|int|string> $catchToken + * @return list + */ + public static function findCaughtTypesInCatch(File $phpcsFile, array $catchToken): array + { + /** @var int $catchParenthesisOpenerPointer */ + $catchParenthesisOpenerPointer = $catchToken['parenthesis_opener']; + /** @var int $catchParenthesisCloserPointer */ + $catchParenthesisCloserPointer = $catchToken['parenthesis_closer']; + + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + + $nameEndPointer = $catchParenthesisOpenerPointer; + $tokens = $phpcsFile->getTokens(); + $caughtTypes = []; + do { + $nameStartPointer = TokenHelper::findNext( + $phpcsFile, + array_merge([T_BITWISE_OR], $nameTokenCodes), + $nameEndPointer + 1, + $catchParenthesisCloserPointer + ); + if ($nameStartPointer === null) { + break; + } + + if ($tokens[$nameStartPointer]['code'] === T_BITWISE_OR) { + /** @var int $nameStartPointer */ + $nameStartPointer = TokenHelper::findNextEffective($phpcsFile, $nameStartPointer + 1, $catchParenthesisCloserPointer); + } + + $pointerAfterNameEndPointer = TokenHelper::findNextExcluding($phpcsFile, $nameTokenCodes, $nameStartPointer + 1); + $nameEndPointer = $pointerAfterNameEndPointer === null ? $nameStartPointer : $pointerAfterNameEndPointer - 1; + + $caughtTypes[] = NamespaceHelper::resolveClassName( + $phpcsFile, + TokenHelper::getContent($phpcsFile, $nameStartPointer, $nameEndPointer), + $catchParenthesisOpenerPointer + ); + } while (true); + + return $caughtTypes; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ClassHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ClassHelper.php new file mode 100644 index 000000000..8683e7141 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ClassHelper.php @@ -0,0 +1,120 @@ +getTokens(); + + $classPointers = array_reverse(self::getAllClassPointers($phpcsFile)); + foreach ($classPointers as $classPointer) { + if ($tokens[$classPointer]['scope_opener'] < $pointer && $tokens[$classPointer]['scope_closer'] > $pointer) { + return $classPointer; + } + } + + return null; + } + + public static function isFinal(File $phpcsFile, int $classPointer): bool + { + return $phpcsFile->getTokens()[TokenHelper::findPreviousEffective($phpcsFile, $classPointer - 1)]['code'] === T_FINAL; + } + + public static function getFullyQualifiedName(File $phpcsFile, int $classPointer): string + { + $className = self::getName($phpcsFile, $classPointer); + + $tokens = $phpcsFile->getTokens(); + if ($tokens[$classPointer]['code'] === T_ANON_CLASS) { + return $className; + } + + $name = sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $className); + $namespace = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $classPointer); + return $namespace !== null ? sprintf('%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, $name) : $name; + } + + public static function getName(File $phpcsFile, int $classPointer): string + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$classPointer]['code'] === T_ANON_CLASS) { + return 'class@anonymous'; + } + + return $tokens[TokenHelper::findNext($phpcsFile, T_STRING, $classPointer + 1, $tokens[$classPointer]['scope_opener'])]['content']; + } + + /** + * @return array + */ + public static function getAllNames(File $phpcsFile): array + { + $tokens = $phpcsFile->getTokens(); + + $names = []; + /** @var int $classPointer */ + foreach (self::getAllClassPointers($phpcsFile) as $classPointer) { + if ($tokens[$classPointer]['code'] === T_ANON_CLASS) { + continue; + } + + $names[$classPointer] = self::getName($phpcsFile, $classPointer); + } + + return $names; + } + + /** + * @return list + */ + public static function getTraitUsePointers(File $phpcsFile, int $classPointer): array + { + $useStatements = []; + + $tokens = $phpcsFile->getTokens(); + + $scopeLevel = $tokens[$classPointer]['level'] + 1; + for ($i = $tokens[$classPointer]['scope_opener'] + 1; $i < $tokens[$classPointer]['scope_closer']; $i++) { + if ($tokens[$i]['code'] !== T_USE) { + continue; + } + + if ($tokens[$i]['level'] !== $scopeLevel) { + continue; + } + + $useStatements[] = $i; + } + + return $useStatements; + } + + /** + * @return list + */ + private static function getAllClassPointers(File $phpcsFile): array + { + $lazyValue = static function () use ($phpcsFile): array { + return TokenHelper::findNextAll($phpcsFile, TokenHelper::$typeWithAnonymousClassKeywordTokenCodes, 0); + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'classPointers', $lazyValue); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Comment.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Comment.php new file mode 100644 index 000000000..7a9fd3fdf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/Comment.php @@ -0,0 +1,33 @@ +pointer = $pointer; + $this->content = $content; + } + + public function getPointer(): int + { + return $this->pointer; + } + + public function getContent(): string + { + return $this->content; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CommentHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CommentHelper.php new file mode 100644 index 000000000..3b8cb9236 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/CommentHelper.php @@ -0,0 +1,102 @@ +getTokens()[$commentPointer]['content']); + } + + public static function getCommentEndPointer(File $phpcsFile, int $commentStartPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + if (array_key_exists('comment_closer', $tokens[$commentStartPointer])) { + return $tokens[$commentStartPointer]['comment_closer']; + } + + if (self::isLineComment($phpcsFile, $commentStartPointer)) { + return $commentStartPointer; + } + + if (strpos($tokens[$commentStartPointer]['content'], '/*') !== 0) { + // Part of block comment + return null; + } + + $commentEndPointer = $commentStartPointer; + + for ($i = $commentStartPointer + 1; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] === T_COMMENT) { + $commentEndPointer = $i; + continue; + } + + if (in_array($tokens[$i]['code'], Tokens::$phpcsCommentTokens, true)) { + $commentEndPointer = $i; + continue; + } + + break; + } + + return $commentEndPointer; + } + + public static function getMultilineCommentStartPointer(File $phpcsFile, int $commentEndPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $commentStartPointer = $commentEndPointer; + do { + $commentBefore = TokenHelper::findPrevious($phpcsFile, TokenHelper::$inlineCommentTokenCodes, $commentStartPointer - 1); + if ($commentBefore === null) { + break; + } + if ($tokens[$commentBefore]['line'] + 1 !== $tokens[$commentStartPointer]['line']) { + break; + } + + /** @var int $commentStartPointer */ + $commentStartPointer = $commentBefore; + } while (true); + + return $commentStartPointer; + } + + public static function getMultilineCommentEndPointer(File $phpcsFile, int $commentStartPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $commentEndPointer = $commentStartPointer; + do { + $commentAfter = TokenHelper::findNext($phpcsFile, TokenHelper::$inlineCommentTokenCodes, $commentEndPointer + 1); + if ($commentAfter === null) { + break; + } + if ($tokens[$commentAfter]['line'] - 1 !== $tokens[$commentEndPointer]['line']) { + break; + } + + /** @var int $commentEndPointer */ + $commentEndPointer = $commentAfter; + } while (true); + + return $commentEndPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConditionHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConditionHelper.php new file mode 100644 index 000000000..865e8250b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConditionHelper.php @@ -0,0 +1,355 @@ +getTokens(); + + $conditionContent = strtolower( + trim(TokenHelper::getContent($phpcsFile, $conditionBoundaryStartPointer, $conditionBoundaryEndPointer)) + ); + + if ($conditionContent === 'false' || $conditionContent === 'true') { + return true; + } + + $actualPointer = $conditionBoundaryStartPointer; + + do { + $actualPointer = TokenHelper::findNext( + $phpcsFile, + array_merge( + [T_OPEN_PARENTHESIS, T_LESS_THAN, T_GREATER_THAN], + Tokens::$booleanOperators, + Tokens::$equalityTokens + ), + $actualPointer, + $conditionBoundaryEndPointer + 1 + ); + + if ($actualPointer === null) { + break; + } + + if ($tokens[$actualPointer]['code'] === T_OPEN_PARENTHESIS) { + $actualPointer = $tokens[$actualPointer]['parenthesis_closer']; + continue; + } + + return true; + + } while (true); + + return false; + } + + public static function getNegativeCondition( + File $phpcsFile, + int $conditionBoundaryStartPointer, + int $conditionBoundaryEndPointer, + bool $nested = false + ): string + { + /** @var int $conditionStartPointer */ + $conditionStartPointer = TokenHelper::findNextEffective($phpcsFile, $conditionBoundaryStartPointer); + /** @var int $conditionEndPointer */ + $conditionEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $conditionBoundaryEndPointer); + + $tokens = $phpcsFile->getTokens(); + if ( + $tokens[$conditionStartPointer]['code'] === T_OPEN_PARENTHESIS + && $tokens[$conditionStartPointer]['parenthesis_closer'] === $conditionEndPointer + ) { + /** @var int $conditionStartPointer */ + $conditionStartPointer = TokenHelper::findNextEffective($phpcsFile, $conditionStartPointer + 1); + /** @var int $conditionEndPointer */ + $conditionEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $conditionEndPointer - 1); + } + + return sprintf( + '%s%s%s', + $conditionBoundaryStartPointer !== $conditionStartPointer + ? TokenHelper::getContent( + $phpcsFile, + $conditionBoundaryStartPointer, + $conditionStartPointer - 1 + ) + : '', + self::getNegativeConditionPart($phpcsFile, $conditionStartPointer, $conditionEndPointer, $nested), + $conditionBoundaryEndPointer !== $conditionEndPointer + ? TokenHelper::getContent( + $phpcsFile, + $conditionEndPointer + 1, + $conditionBoundaryEndPointer + ) + : '' + ); + } + + private static function getNegativeConditionPart( + File $phpcsFile, + int $conditionBoundaryStartPointer, + int $conditionBoundaryEndPointer, + bool $nested + ): string + { + $tokens = $phpcsFile->getTokens(); + + $condition = TokenHelper::getContent($phpcsFile, $conditionBoundaryStartPointer, $conditionBoundaryEndPointer); + + if (strtolower($condition) === 'true') { + return 'false'; + } + if (strtolower($condition) === 'false') { + return 'true'; + } + + $pointerAfterConditionStart = TokenHelper::findNextEffective($phpcsFile, $conditionBoundaryStartPointer); + $booleanPointers = TokenHelper::findNextAll( + $phpcsFile, + Tokens::$booleanOperators, + $conditionBoundaryStartPointer, + $conditionBoundaryEndPointer + 1 + ); + + if ($tokens[$pointerAfterConditionStart]['code'] === T_BOOLEAN_NOT) { + $pointerAfterBooleanNot = TokenHelper::findNextEffective($phpcsFile, $pointerAfterConditionStart + 1); + if ($tokens[$pointerAfterBooleanNot]['code'] === T_OPEN_PARENTHESIS) { + if ($nested && $booleanPointers !== []) { + return self::removeBooleanNot($condition); + } + + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$pointerAfterBooleanNot]['parenthesis_closer'] + 1, + $conditionBoundaryEndPointer + 1 + ); + if ( + $pointerAfterParenthesisCloser === null + || $pointerAfterParenthesisCloser === $conditionBoundaryEndPointer + ) { + return TokenHelper::getContent( + $phpcsFile, + $pointerAfterBooleanNot + 1, + $tokens[$pointerAfterBooleanNot]['parenthesis_closer'] - 1 + ); + } + } + } + + if (count($booleanPointers) > 0) { + return self::getNegativeLogicalCondition($phpcsFile, $conditionBoundaryStartPointer, $conditionBoundaryEndPointer); + } + + if ($tokens[$pointerAfterConditionStart]['code'] === T_BOOLEAN_NOT) { + return self::removeBooleanNot($condition); + } + + if (TokenHelper::findNext( + $phpcsFile, + [T_INSTANCEOF, T_BITWISE_AND, T_COALESCE, T_INLINE_THEN], + $conditionBoundaryStartPointer, + $conditionBoundaryEndPointer + 1 + ) !== null) { + return sprintf('!(%s)', $condition); + } + + if ($tokens[$pointerAfterConditionStart]['code'] === T_STRING) { + $pointerAfterConditionStart = TokenHelper::findNextEffective($phpcsFile, $pointerAfterConditionStart + 1); + if ( + $tokens[$pointerAfterConditionStart]['code'] === T_OPEN_PARENTHESIS + && $tokens[$pointerAfterConditionStart]['parenthesis_closer'] === $conditionBoundaryEndPointer + ) { + return sprintf('!%s', $condition); + } + } + + if (in_array($tokens[$pointerAfterConditionStart]['code'], [T_VARIABLE, T_SELF, T_STATIC, T_PARENT], true)) { + $identificatorEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $pointerAfterConditionStart); + $pointerAfterIdentificatorEnd = TokenHelper::findNextEffective($phpcsFile, $identificatorEndPointer + 1); + if ( + $tokens[$pointerAfterIdentificatorEnd]['code'] === T_OPEN_PARENTHESIS + && $tokens[$pointerAfterIdentificatorEnd]['parenthesis_closer'] === $conditionBoundaryEndPointer + ) { + return sprintf('!%s', $condition); + } + } + + $comparisonPointer = TokenHelper::findNext( + $phpcsFile, + [T_IS_EQUAL, T_IS_NOT_EQUAL, T_IS_IDENTICAL, T_IS_NOT_IDENTICAL, T_IS_SMALLER_OR_EQUAL, T_IS_GREATER_OR_EQUAL, T_LESS_THAN, T_GREATER_THAN], + $conditionBoundaryStartPointer, + $conditionBoundaryEndPointer + 1 + ); + if ($comparisonPointer !== null) { + $comparisonReplacements = [ + T_IS_EQUAL => '!=', + T_IS_NOT_EQUAL => '==', + T_IS_IDENTICAL => '!==', + T_IS_NOT_IDENTICAL => '===', + T_IS_GREATER_OR_EQUAL => '<', + T_IS_SMALLER_OR_EQUAL => '>', + T_GREATER_THAN => '<=', + T_LESS_THAN => '>=', + ]; + + $negativeCondition = ''; + for ($i = $conditionBoundaryStartPointer; $i <= $conditionBoundaryEndPointer; $i++) { + // Skip calls() + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $negativeCondition .= TokenHelper::getContent($phpcsFile, $i, $tokens[$i]['parenthesis_closer']); + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + $negativeCondition .= array_key_exists($tokens[$i]['code'], $comparisonReplacements) + ? $comparisonReplacements[$tokens[$i]['code']] + : $tokens[$i]['content']; + } + + return $negativeCondition; + } + + return sprintf('!%s', $condition); + } + + private static function removeBooleanNot(string $condition): string + { + return preg_replace('~^!\\s*~', '', $condition); + } + + private static function getNegativeLogicalCondition( + File $phpcsFile, + int $conditionBoundaryStartPointer, + int $conditionBoundaryEndPointer + ): string + { + if (TokenHelper::findNext($phpcsFile, T_LOGICAL_XOR, $conditionBoundaryStartPointer, $conditionBoundaryEndPointer) !== null) { + return sprintf('!(%s)', TokenHelper::getContent($phpcsFile, $conditionBoundaryStartPointer, $conditionBoundaryEndPointer)); + } + + $tokens = $phpcsFile->getTokens(); + + $booleanOperatorReplacements = [ + T_BOOLEAN_AND => '||', + T_BOOLEAN_OR => '&&', + T_LOGICAL_AND => 'or', + T_LOGICAL_OR => 'and', + ]; + + $negativeCondition = ''; + + $nestedConditionStartPointer = $conditionBoundaryStartPointer; + $actualPointer = $conditionBoundaryStartPointer; + $parenthesesLevel = 0; + + $operatorsOnLevel = []; + + do { + $actualPointer = TokenHelper::findNext( + $phpcsFile, + array_merge([T_OPEN_PARENTHESIS, T_CLOSE_PARENTHESIS], Tokens::$booleanOperators), + $actualPointer, + $conditionBoundaryEndPointer + 1 + ); + + if ($actualPointer === null) { + break; + } + + if ($tokens[$actualPointer]['code'] === T_OPEN_PARENTHESIS) { + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $actualPointer - 1); + if ($tokens[$pointerBeforeParenthesisOpener]['code'] === T_STRING) { + $actualPointer = $tokens[$actualPointer]['parenthesis_closer'] + 1; + continue; + } + + $parenthesesLevel++; + $actualPointer++; + continue; + } + + if ($tokens[$actualPointer]['code'] === T_CLOSE_PARENTHESIS) { + $parenthesesLevel--; + $actualPointer++; + continue; + } + + if ($parenthesesLevel !== 0) { + $actualPointer++; + continue; + } + + if ( + array_key_exists($parenthesesLevel, $operatorsOnLevel) + && $operatorsOnLevel[$parenthesesLevel] !== $tokens[$actualPointer]['code'] + ) { + return sprintf('!(%s)', TokenHelper::getContent($phpcsFile, $conditionBoundaryStartPointer, $conditionBoundaryEndPointer)); + } + + $operatorsOnLevel[$parenthesesLevel] = $tokens[$actualPointer]['code']; + + $negativeCondition .= self::getNegativeCondition($phpcsFile, $nestedConditionStartPointer, $actualPointer - 1, true); + $negativeCondition .= $booleanOperatorReplacements[$tokens[$actualPointer]['code']]; + + $nestedConditionStartPointer = $actualPointer + 1; + $actualPointer++; + + } while (true); + + return $negativeCondition . self::getNegativeCondition( + $phpcsFile, + $nestedConditionStartPointer, + $conditionBoundaryEndPointer, + true + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConstantHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConstantHelper.php new file mode 100644 index 000000000..99978a093 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ConstantHelper.php @@ -0,0 +1,79 @@ +getTokens(); + return $tokens[TokenHelper::findNext($phpcsFile, T_STRING, $constantPointer + 1)]['content']; + } + + public static function getFullyQualifiedName(File $phpcsFile, int $constantPointer): string + { + $name = self::getName($phpcsFile, $constantPointer); + $namespace = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $constantPointer); + + return $namespace !== null + ? sprintf('%s%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, NamespaceHelper::NAMESPACE_SEPARATOR, $name) + : $name; + } + + /** + * @return list + */ + public static function getAllNames(File $phpcsFile): array + { + $previousConstantPointer = 0; + + return array_map( + static function (int $constantPointer) use ($phpcsFile): string { + return self::getName($phpcsFile, $constantPointer); + }, + array_filter( + iterator_to_array(self::getAllConstantPointers($phpcsFile, $previousConstantPointer)), + static function (int $constantPointer) use ($phpcsFile): bool { + foreach (array_reverse($phpcsFile->getTokens()[$constantPointer]['conditions']) as $conditionTokenCode) { + return $conditionTokenCode === T_NAMESPACE; + } + + return true; + } + ) + ); + } + + /** + * @return Generator + */ + private static function getAllConstantPointers(File $phpcsFile, int &$previousConstantPointer): Generator + { + do { + $nextConstantPointer = TokenHelper::findNext($phpcsFile, T_CONST, $previousConstantPointer + 1); + if ($nextConstantPointer === null) { + break; + } + + $previousConstantPointer = $nextConstantPointer; + + yield $nextConstantPointer; + } while (true); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/DocCommentHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/DocCommentHelper.php new file mode 100644 index 000000000..ffed9954d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/DocCommentHelper.php @@ -0,0 +1,275 @@ +getTokens()[$docCommentOpenToken]['comment_closer'] + ) + ); + } + + /** + * @return list|null + */ + public static function getDocCommentDescription(File $phpcsFile, int $pointer): ?array + { + $docCommentOpenPointer = self::findDocCommentOpenPointer($phpcsFile, $pointer); + + if ($docCommentOpenPointer === null) { + return null; + } + + $tokens = $phpcsFile->getTokens(); + $descriptionStartPointer = TokenHelper::findNextExcluding( + $phpcsFile, + [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], + $docCommentOpenPointer + 1, + $tokens[$docCommentOpenPointer]['comment_closer'] + ); + + if ($descriptionStartPointer === null) { + return null; + } + + if ($tokens[$descriptionStartPointer]['code'] !== T_DOC_COMMENT_STRING) { + return null; + } + + $tokenAfterDescriptionPointer = TokenHelper::findNext( + $phpcsFile, + [T_DOC_COMMENT_TAG, T_DOC_COMMENT_CLOSE_TAG], + $descriptionStartPointer + 1, + $tokens[$docCommentOpenPointer]['comment_closer'] + 1 + ); + + /** @var list $comments */ + $comments = []; + for ($i = $descriptionStartPointer; $i < $tokenAfterDescriptionPointer; $i++) { + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STRING) { + continue; + } + + $comments[] = new Comment($i, trim($tokens[$i]['content'])); + } + + return count($comments) > 0 ? $comments : null; + } + + public static function hasInheritdocAnnotation(File $phpcsFile, int $pointer): bool + { + $docCommentOpenPointer = self::findDocCommentOpenPointer($phpcsFile, $pointer); + + if ($docCommentOpenPointer === null) { + return false; + } + + $parsedDocComment = self::parseDocComment($phpcsFile, $docCommentOpenPointer); + + if ($parsedDocComment === null) { + return false; + } + + foreach ($parsedDocComment->getNode()->children as $child) { + if ($child instanceof PhpDocTextNode && stripos($child->text, '{@inheritdoc}') !== false) { + return true; + } + + if ($child instanceof PhpDocTagNode && strtolower($child->name) === '@inheritdoc') { + return true; + } + } + + return false; + } + + public static function hasDocCommentDescription(File $phpcsFile, int $pointer): bool + { + return self::getDocCommentDescription($phpcsFile, $pointer) !== null; + } + + public static function findDocCommentOpenPointer(File $phpcsFile, int $pointer): ?int + { + return SniffLocalCache::getAndSetIfNotCached( + $phpcsFile, + sprintf('doc-comment-open-pointer-%d', $pointer), + static function () use ($phpcsFile, $pointer): ?int { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_DOC_COMMENT_OPEN_TAG) { + return $pointer; + } + + $found = TokenHelper::findPrevious( + $phpcsFile, + [T_DOC_COMMENT_CLOSE_TAG, T_SEMICOLON, T_CLOSE_CURLY_BRACKET, T_OPEN_CURLY_BRACKET], + $pointer - 1 + ); + if ($found !== null && $tokens[$found]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + return $tokens[$found]['comment_opener']; + } + + return null; + } + ); + } + + public static function findDocCommentOwnerPointer(File $phpcsFile, int $docCommentOpenPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $docCommentCloserPointer = $tokens[$docCommentOpenPointer]['comment_closer']; + + if (self::isInline($phpcsFile, $docCommentOpenPointer)) { + return null; + } + + $docCommentOwnerPointer = null; + + for ($i = $docCommentCloserPointer + 1; $i < count($tokens); $i++) { + if ($tokens[$i]['code'] === T_ATTRIBUTE) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + if (in_array( + $tokens[$i]['code'], + [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_VAR, T_READONLY, T_FINAL, T_STATIC, T_ABSTRACT, T_WHITESPACE], + true + )) { + continue; + } + + if (in_array( + $tokens[$i]['code'], + array_merge([T_FUNCTION, T_VARIABLE, T_CONST], TokenHelper::$typeKeywordTokenCodes), + true + )) { + $docCommentOwnerPointer = $i; + } + + break; + } + + return $docCommentOwnerPointer; + } + + public static function isInline(File $phpcsFile, int $docCommentOpenPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextNonWhitespace($phpcsFile, $tokens[$docCommentOpenPointer]['comment_closer'] + 1); + + if ( + $nextPointer !== null + && in_array( + $tokens[$nextPointer]['code'], + [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_FINAL, T_STATIC, T_ABSTRACT, T_CONST, T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], + true + ) + ) { + return false; + } + + $parsedDocComment = self::parseDocComment($phpcsFile, $docCommentOpenPointer); + + if ($parsedDocComment === null) { + return false; + } + + foreach ($parsedDocComment->getNode()->getTags() as $annotation) { + if (preg_match('~^@(?:(?:phpstan|psalm)-)?var~i', $annotation->name) === 1) { + return true; + } + } + + return false; + } + + public static function parseDocComment(File $phpcsFile, int $docCommentOpenPointer): ?ParsedDocComment + { + return SniffLocalCache::getAndSetIfNotCached( + $phpcsFile, + sprintf('parsed-doc-comment-%d', $docCommentOpenPointer), + static function () use ($phpcsFile, $docCommentOpenPointer): ?ParsedDocComment { + $docComment = self::getDocComment($phpcsFile, $docCommentOpenPointer); + + $docCommentTokens = new TokenIterator(PhpDocParserHelper::getLexer()->tokenize($docComment)); + + try { + $parsedDocComment = PhpDocParserHelper::getParser()->parse($docCommentTokens); + + return new ParsedDocComment( + $docCommentOpenPointer, + $phpcsFile->getTokens()[$docCommentOpenPointer]['comment_closer'], + $parsedDocComment, + $docCommentTokens + ); + } catch (ParserException $e) { + return null; + } + } + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/EmptyFileException.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/EmptyFileException.php new file mode 100644 index 000000000..cbcdf7400 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/EmptyFileException.php @@ -0,0 +1,33 @@ +filename = $filename; + } + + public function getFilename(): string + { + return $this->filename; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FixerHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FixerHelper.php new file mode 100644 index 000000000..d994bc6ca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FixerHelper.php @@ -0,0 +1,55 @@ +fixer->replaceToken($startPointer, $content); + } + + public static function removeBetween(File $phpcsFile, int $startPointer, int $endPointer): void + { + self::removeBetweenIncluding($phpcsFile, $startPointer + 1, $endPointer - 1); + } + + public static function removeBetweenIncluding(File $phpcsFile, int $startPointer, int $endPointer): void + { + for ($i = $startPointer; $i <= $endPointer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + public static function removeWhitespaceBefore(File $phpcsFile, int $pointer): void + { + for ($i = $pointer - 1; $i > 0; $i--) { + if (preg_match('~^\\s+$~', $phpcsFile->fixer->getTokenContent($i)) === 0) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + public static function removeWhitespaceAfter(File $phpcsFile, int $pointer): void + { + for ($i = $pointer + 1; $i < count($phpcsFile->getTokens()); $i++) { + if (preg_match('~^\\s+$~', $phpcsFile->fixer->getTokenContent($i)) === 0) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FunctionHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FunctionHelper.php new file mode 100644 index 000000000..633e80b1c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/FunctionHelper.php @@ -0,0 +1,572 @@ +getTokens(); + return $tokens[TokenHelper::findNext( + $phpcsFile, + T_STRING, + $functionPointer + 1, + $tokens[$functionPointer]['parenthesis_opener'] + )]['content']; + } + + public static function getFullyQualifiedName(File $phpcsFile, int $functionPointer): string + { + $name = self::getName($phpcsFile, $functionPointer); + $namespace = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $functionPointer); + + if (self::isMethod($phpcsFile, $functionPointer)) { + foreach (array_reverse( + $phpcsFile->getTokens()[$functionPointer]['conditions'], + true + ) as $conditionPointer => $conditionTokenCode) { + if ($conditionTokenCode === T_ANON_CLASS) { + return sprintf('class@anonymous::%s', $name); + } + + if (in_array($conditionTokenCode, [T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], true)) { + $name = sprintf( + '%s%s::%s', + NamespaceHelper::NAMESPACE_SEPARATOR, + ClassHelper::getName($phpcsFile, $conditionPointer), + $name + ); + break; + } + } + + return $namespace !== null ? sprintf('%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, $name) : $name; + } + + return $namespace !== null + ? sprintf('%s%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, NamespaceHelper::NAMESPACE_SEPARATOR, $name) + : $name; + } + + public static function isAbstract(File $phpcsFile, int $functionPointer): bool + { + return !isset($phpcsFile->getTokens()[$functionPointer]['scope_opener']); + } + + public static function isMethod(File $phpcsFile, int $functionPointer): bool + { + $functionPointerConditions = $phpcsFile->getTokens()[$functionPointer]['conditions']; + if ($functionPointerConditions === []) { + return false; + } + $lastFunctionPointerCondition = array_pop($functionPointerConditions); + return in_array($lastFunctionPointerCondition, Tokens::$ooScopeTokens, true); + } + + public static function findClassPointer(File $phpcsFile, int $functionPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$functionPointer]['code'] === T_CLOSURE) { + return null; + } + + foreach (array_reverse($tokens[$functionPointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (!in_array($conditionTokenCode, Tokens::$ooScopeTokens, true)) { + continue; + } + + return $conditionPointer; + } + + return null; + } + + /** + * @return list + */ + public static function getParametersNames(File $phpcsFile, int $functionPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $parametersNames = []; + for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + $parametersNames[] = $tokens[$i]['content']; + } + + return $parametersNames; + } + + /** + * @return array + */ + public static function getParametersTypeHints(File $phpcsFile, int $functionPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $parametersTypeHints = []; + for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + $parameterName = $tokens[$i]['content']; + + $pointerBeforeVariable = TokenHelper::findPreviousExcluding( + $phpcsFile, + array_merge(TokenHelper::$ineffectiveTokenCodes, [T_BITWISE_AND, T_ELLIPSIS]), + $i - 1 + ); + + if (!in_array($tokens[$pointerBeforeVariable]['code'], TokenHelper::getTypeHintTokenCodes(), true)) { + $parametersTypeHints[$parameterName] = null; + continue; + } + + $typeHintEndPointer = $pointerBeforeVariable; + $typeHintStartPointer = TypeHintHelper::getStartPointer($phpcsFile, $typeHintEndPointer); + + $pointerBeforeTypeHint = TokenHelper::findPreviousEffective($phpcsFile, $typeHintStartPointer - 1); + $isNullable = $tokens[$pointerBeforeTypeHint]['code'] === T_NULLABLE; + if ($isNullable) { + $typeHintStartPointer = $pointerBeforeTypeHint; + } + + $typeHint = TokenHelper::getContent($phpcsFile, $typeHintStartPointer, $typeHintEndPointer); + + /** @var string $typeHint */ + $typeHint = preg_replace('~\s+~', '', $typeHint); + + if (!$isNullable) { + $isNullable = preg_match('~(?:^|\|)null(?:\||$)~i', $typeHint) === 1; + } + + $parametersTypeHints[$parameterName] = new TypeHint($typeHint, $isNullable, $typeHintStartPointer, $typeHintEndPointer); + } + + return $parametersTypeHints; + } + + public static function returnsValue(File $phpcsFile, int $functionPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $firstPointerInScope = $tokens[$functionPointer]['scope_opener'] + 1; + + for ($i = $firstPointerInScope; $i < $tokens[$functionPointer]['scope_closer']; $i++) { + if (!in_array($tokens[$i]['code'], [T_YIELD, T_YIELD_FROM], true)) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $i, $firstPointerInScope)) { + continue; + } + + return true; + } + + for ($i = $firstPointerInScope; $i < $tokens[$functionPointer]['scope_closer']; $i++) { + if ($tokens[$i]['code'] !== T_RETURN) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $i, $firstPointerInScope)) { + continue; + } + + $nextEffectiveTokenPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + return $tokens[$nextEffectiveTokenPointer]['code'] !== T_SEMICOLON; + } + + return false; + } + + public static function findReturnTypeHint(File $phpcsFile, int $functionPointer): ?TypeHint + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$functionPointer]['parenthesis_closer'] + 1); + + if ($tokens[$nextPointer]['code'] === T_USE) { + $useParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $nextPointer + 1); + $colonPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$useParenthesisOpener]['parenthesis_closer'] + 1); + } else { + $colonPointer = $nextPointer; + } + + if ($tokens[$colonPointer]['code'] !== T_COLON) { + return null; + } + + $typeHintStartPointer = TokenHelper::findNextEffective($phpcsFile, $colonPointer + 1); + $nullable = $tokens[$typeHintStartPointer]['code'] === T_NULLABLE; + + $pointerAfterTypeHint = self::isAbstract($phpcsFile, $functionPointer) + ? TokenHelper::findNext($phpcsFile, T_SEMICOLON, $typeHintStartPointer + 1) + : $tokens[$functionPointer]['scope_opener']; + + $typeHintEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $pointerAfterTypeHint - 1); + + $typeHint = TokenHelper::getContent($phpcsFile, $typeHintStartPointer, $typeHintEndPointer); + + /** @var string $typeHint */ + $typeHint = preg_replace('~\s+~', '', $typeHint); + + if (!$nullable) { + $nullable = preg_match('~(?:^|\|)null(?:\||$)~i', $typeHint) === 1; + } + + return new TypeHint($typeHint, $nullable, $typeHintStartPointer, $typeHintEndPointer); + } + + public static function hasReturnTypeHint(File $phpcsFile, int $functionPointer): bool + { + return self::findReturnTypeHint($phpcsFile, $functionPointer) !== null; + } + + /** + * @return list|Annotation> + */ + public static function getParametersAnnotations(File $phpcsFile, int $functionPointer): array + { + return AnnotationHelper::getAnnotations($phpcsFile, $functionPointer, '@param'); + } + + /** + * @return array|Annotation|Annotation> + */ + public static function getValidParametersAnnotations(File $phpcsFile, int $functionPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $parametersAnnotations = []; + + if (self::getName($phpcsFile, $functionPointer) === '__construct') { + for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + $varAnnotations = AnnotationHelper::getAnnotations($phpcsFile, $i, '@var'); + if ($varAnnotations === []) { + continue; + } + + $parametersAnnotations[$tokens[$i]['content']] = $varAnnotations[0]; + } + } + + foreach (self::getParametersAnnotations($phpcsFile, $functionPointer) as $parameterAnnotation) { + if ($parameterAnnotation->isInvalid()) { + continue; + } + + $parametersAnnotations[$parameterAnnotation->getValue()->parameterName] = $parameterAnnotation; + } + + return $parametersAnnotations; + } + + /** + * @return array|Annotation> + */ + public static function getValidPrefixedParametersAnnotations(File $phpcsFile, int $functionPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $parametersAnnotations = []; + foreach (AnnotationHelper::STATIC_ANALYSIS_PREFIXES as $prefix) { + if (self::getName($phpcsFile, $functionPointer) === '__construct') { + for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + /** @var list> $varAnnotations */ + $varAnnotations = AnnotationHelper::getAnnotations($phpcsFile, $i, sprintf('@%s-var', $prefix)); + if ($varAnnotations === []) { + continue; + } + + $parametersAnnotations[$tokens[$i]['content']] = $varAnnotations[0]; + } + } + + /** @var list> $annotations */ + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $functionPointer, sprintf('@%s-param', $prefix)); + foreach ($annotations as $parameterAnnotation) { + if ($parameterAnnotation->isInvalid()) { + continue; + } + + $parametersAnnotations[$parameterAnnotation->getValue()->parameterName] = $parameterAnnotation; + } + } + + return $parametersAnnotations; + } + + /** + * @return Annotation|null + */ + public static function findReturnAnnotation(File $phpcsFile, int $functionPointer): ?Annotation + { + /** @var list> $returnAnnotations */ + $returnAnnotations = AnnotationHelper::getAnnotations($phpcsFile, $functionPointer, '@return'); + + if ($returnAnnotations === []) { + return null; + } + + return $returnAnnotations[0]; + } + + /** + * @return list + */ + public static function getValidPrefixedReturnAnnotations(File $phpcsFile, int $functionPointer): array + { + $returnAnnotations = []; + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $functionPointer); + + foreach (AnnotationHelper::STATIC_ANALYSIS_PREFIXES as $prefix) { + $prefixedAnnotationName = sprintf('@%s-return', $prefix); + + foreach ($annotations as $annotation) { + if ($annotation->isInvalid()) { + continue; + } + + if ($annotation->getName() === $prefixedAnnotationName) { + $returnAnnotations[] = $annotation; + } + } + } + + return $returnAnnotations; + } + + /** + * @return list + */ + public static function getAllFunctionNames(File $phpcsFile): array + { + $previousFunctionPointer = 0; + + return array_map( + static function (int $functionPointer) use ($phpcsFile): string { + return self::getName($phpcsFile, $functionPointer); + }, + array_filter( + iterator_to_array(self::getAllFunctionOrMethodPointers($phpcsFile, $previousFunctionPointer)), + static function (int $functionOrMethodPointer) use ($phpcsFile): bool { + return !self::isMethod($phpcsFile, $functionOrMethodPointer); + } + ) + ); + } + + /** + * @param int $flags optional bitmask of self::LINE_INCLUDE_* constants + */ + public static function getFunctionLengthInLines(File $file, int $functionPosition, int $flags = 0): int + { + if (self::isAbstract($file, $functionPosition)) { + return 0; + } + return self::getLineCount($file, $functionPosition, $flags); + } + + public static function getLineCount(File $file, int $tokenPosition, int $flags = 0): int + { + $includeWhitespace = ($flags & self::LINE_INCLUDE_WHITESPACE) === self::LINE_INCLUDE_WHITESPACE; + $includeComments = ($flags & self::LINE_INCLUDE_COMMENT) === self::LINE_INCLUDE_COMMENT; + + $tokens = $file->getTokens(); + $token = $tokens[$tokenPosition]; + + $tokenOpenerPosition = $token['scope_opener'] ?? $tokenPosition; + $tokenCloserPosition = $token['scope_closer'] ?? $file->numTokens - 1; + $tokenOpenerLine = $tokens[$tokenOpenerPosition]['line']; + $tokenCloserLine = $tokens[$tokenCloserPosition]['line']; + + $lineCount = 0; + $lastCommentLine = null; + $previousIncludedPosition = null; + + for ($position = $tokenOpenerPosition; $position <= $tokenCloserPosition - 1; $position++) { + $token = $tokens[$position]; + if ($includeComments === false) { + if (in_array($token['code'], Tokens::$commentTokens, true)) { + if ( + $previousIncludedPosition !== null && + substr_count($token['content'], $file->eolChar) > 0 && + $token['line'] === $tokens[$previousIncludedPosition]['line'] + ) { + // Comment with linebreak starting on same line as included Token + $lineCount++; + } + // Don't include comment + $lastCommentLine = $token['line']; + continue; + } + if ( + $previousIncludedPosition !== null && + $token['code'] === T_WHITESPACE && + $token['line'] === $lastCommentLine && + $token['line'] !== $tokens[$previousIncludedPosition]['line'] + ) { + // Whitespace after block comment... still on comment line... + // Ignore along with the comment + continue; + } + } + if ($token['code'] === T_WHITESPACE) { + $nextNonWhitespacePosition = $file->findNext(T_WHITESPACE, $position + 1, $tokenCloserPosition + 1, true); + if ( + $includeWhitespace === false && + $token['column'] === 1 && + $nextNonWhitespacePosition !== false && + $tokens[$nextNonWhitespacePosition]['line'] !== $token['line'] + ) { + // This line is nothing but whitepace + $position = $nextNonWhitespacePosition - 1; + continue; + } + if ($previousIncludedPosition === $tokenOpenerPosition && $token['line'] === $tokenOpenerLine) { + // Don't linclude line break after opening "{" + // Unless there was code or an (included) comment following the "{" + continue; + } + } + if ($token['code'] !== T_WHITESPACE) { + $previousIncludedPosition = $position; + } + $newLineFoundCount = substr_count($token['content'], $file->eolChar); + $lineCount += $newLineFoundCount; + } + if ($tokens[$previousIncludedPosition]['line'] === $tokenCloserLine) { + // There is code or comment on the closing "}" line... + $lineCount++; + } + return $lineCount; + } + + /** + * @return Generator + */ + private static function getAllFunctionOrMethodPointers(File $phpcsFile, int &$previousFunctionPointer): Generator + { + do { + $nextFunctionPointer = TokenHelper::findNext($phpcsFile, T_FUNCTION, $previousFunctionPointer + 1); + if ($nextFunctionPointer === null) { + break; + } + + $previousFunctionPointer = $nextFunctionPointer; + + yield $nextFunctionPointer; + } while (true); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IdentificatorHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IdentificatorHelper.php new file mode 100644 index 000000000..b64d3093e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IdentificatorHelper.php @@ -0,0 +1,216 @@ +getTokens(); + + $variableContent = ''; + for ($i = $startPointer; $i <= $endPointer; $i++) { + if (in_array($tokens[$i]['code'], TokenHelper::$ineffectiveTokenCodes, true)) { + continue; + } + + $variableContent .= $tokens[$i]['content']; + } + + return $variableContent; + } + + public static function findStartPointer(File $phpcsFile, int $endPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + if (in_array($tokens[$endPointer]['code'], TokenHelper::getNameTokenCodes(), true)) { + /** @var int $previousPointer */ + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $endPointer - 1); + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + $pointerBeforeOperator = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + if ($tokens[$pointerBeforeOperator]['code'] !== T_CLOSE_PARENTHESIS) { + return self::getStartPointerBeforeOperator($phpcsFile, $previousPointer); + } + } + + return $endPointer; + } + + if (in_array($tokens[$endPointer]['code'], [T_CLOSE_CURLY_BRACKET, T_CLOSE_SQUARE_BRACKET], true)) { + return self::getStartPointerBeforeVariablePart($phpcsFile, $tokens[$endPointer]['bracket_opener']); + } + + if ($tokens[$endPointer]['code'] === T_VARIABLE) { + return self::getStartPointerBeforeVariablePart($phpcsFile, $endPointer); + } + + return null; + } + + public static function findEndPointer(File $phpcsFile, int $startPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + + if (in_array($tokens[$startPointer]['code'], $nameTokenCodes, true)) { + $startPointer = TokenHelper::findNextExcluding($phpcsFile, $nameTokenCodes, $startPointer + 1) - 1; + } elseif ($tokens[$startPointer]['code'] === T_DOLLAR) { + $startPointer = TokenHelper::findNextEffective($phpcsFile, $startPointer + 1); + } + + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $startPointer + 1); + + if ( + in_array($tokens[$startPointer]['code'], array_merge([T_SELF, T_STATIC, T_PARENT], $nameTokenCodes), true) + && $tokens[$nextPointer]['code'] === T_DOUBLE_COLON + ) { + return self::getEndPointerAfterOperator($phpcsFile, $nextPointer); + } + + if ($tokens[$startPointer]['code'] === T_VARIABLE) { + if (in_array($tokens[$nextPointer]['code'], [T_DOUBLE_COLON, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], true)) { + return self::getEndPointerAfterOperator($phpcsFile, $nextPointer); + } + + if ($tokens[$nextPointer]['code'] === T_OPEN_SQUARE_BRACKET) { + return self::getEndPointerAfterVariablePart($phpcsFile, $startPointer); + } + + return $startPointer; + } + + return null; + } + + private static function getStartPointerBeforeOperator(File $phpcsFile, int $operatorPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + + /** @var int $previousPointer */ + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $operatorPointer - 1); + + if (in_array($tokens[$previousPointer]['code'], $nameTokenCodes, true)) { + $previousPointer = TokenHelper::findPreviousExcluding($phpcsFile, $nameTokenCodes, $previousPointer - 1) + 1; + } + + if ( + $tokens[$operatorPointer]['code'] === T_DOUBLE_COLON + && in_array($tokens[$previousPointer]['code'], array_merge([T_SELF, T_STATIC, T_PARENT], $nameTokenCodes), true) + ) { + return $previousPointer; + } + + if (in_array($tokens[$previousPointer]['code'], $nameTokenCodes, true)) { + /** @var int $possibleOperatorPointer */ + $possibleOperatorPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + if (in_array($tokens[$possibleOperatorPointer]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], true)) { + return self::getStartPointerBeforeOperator($phpcsFile, $possibleOperatorPointer); + } + } + + if (in_array($tokens[$previousPointer]['code'], [T_CLOSE_CURLY_BRACKET, T_CLOSE_SQUARE_BRACKET], true)) { + return self::getStartPointerBeforeVariablePart($phpcsFile, $tokens[$previousPointer]['bracket_opener']); + } + + return self::getStartPointerBeforeVariablePart($phpcsFile, $previousPointer); + } + + private static function getStartPointerBeforeVariablePart(File $phpcsFile, int $variablePartPointer): int + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $previousPointer */ + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePartPointer - 1); + + if ($tokens[$previousPointer]['code'] === T_DOLLAR) { + /** @var int $previousPointer */ + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } + + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + return self::getStartPointerBeforeOperator($phpcsFile, $previousPointer); + } + + if ($tokens[$previousPointer]['code'] === T_CLOSE_SQUARE_BRACKET) { + return self::getStartPointerBeforeVariablePart($phpcsFile, $tokens[$previousPointer]['bracket_opener']); + } + + if ( + $tokens[$previousPointer]['code'] === T_CLOSE_CURLY_BRACKET + && !array_key_exists('scope_condition', $tokens[$previousPointer]) + ) { + return self::getStartPointerBeforeVariablePart($phpcsFile, $tokens[$previousPointer]['bracket_opener']); + } + + if (in_array($tokens[$previousPointer]['code'], array_merge([T_VARIABLE], TokenHelper::getNameTokenCodes()), true)) { + return self::getStartPointerBeforeVariablePart($phpcsFile, $previousPointer); + } + + return $variablePartPointer; + } + + private static function getEndPointerAfterOperator(File $phpcsFile, int $operatorPointer): int + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $operatorPointer + 1); + + if ($tokens[$nextPointer]['code'] === T_DOLLAR) { + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $nextPointer + 1); + } + + if ($tokens[$nextPointer]['code'] === T_OPEN_CURLY_BRACKET) { + return self::getEndPointerAfterVariablePart($phpcsFile, $tokens[$nextPointer]['bracket_closer']); + } + + return self::getEndPointerAfterVariablePart($phpcsFile, $nextPointer); + } + + private static function getEndPointerAfterVariablePart(File $phpcsFile, int $variablePartPointer): int + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $variablePartPointer + 1); + + if (in_array($tokens[$nextPointer]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + return self::getEndPointerAfterOperator($phpcsFile, $nextPointer); + } + + if ($tokens[$nextPointer]['code'] === T_OPEN_SQUARE_BRACKET) { + return self::getEndPointerAfterVariablePart($phpcsFile, $tokens[$nextPointer]['bracket_closer']); + } + + return $variablePartPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IndentationHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IndentationHelper.php new file mode 100644 index 000000000..e6daae0d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/IndentationHelper.php @@ -0,0 +1,106 @@ + $codePointers + */ + public static function fixIndentation(File $phpcsFile, array $codePointers, string $defaultIndentation): string + { + $tokens = $phpcsFile->getTokens(); + + $eolLength = strlen($phpcsFile->eolChar); + + $code = ''; + $inHeredoc = false; + + foreach ($codePointers as $no => $codePointer) { + $content = $tokens[$codePointer]['content']; + + if ( + !$inHeredoc + && ( + $no === 0 + || substr($tokens[$codePointer - 1]['content'], -$eolLength) === $phpcsFile->eolChar + ) + ) { + if ($content === $phpcsFile->eolChar) { + // Nothing + } elseif ($content[0] === self::TAB_INDENT) { + $content = substr($content, 1); + } elseif (substr($content, 0, self::DEFAULT_INDENTATION_WIDTH) === self::SPACES_INDENT) { + $content = substr($content, self::DEFAULT_INDENTATION_WIDTH); + } else { + $content = $defaultIndentation . ltrim($content); + } + } + + if (in_array($tokens[$codePointer]['code'], [T_START_HEREDOC, T_START_NOWDOC], true)) { + $inHeredoc = true; + } elseif (in_array($tokens[$codePointer]['code'], [T_END_HEREDOC, T_END_NOWDOC], true)) { + $inHeredoc = false; + } + + $code .= $content; + } + + return rtrim($code); + } + + public static function convertTabsToSpaces(File $phpcsFile, string $code): string + { + return preg_replace_callback('~^(\t+)~', static function (array $matches) use ($phpcsFile): string { + $indentation = str_repeat( + ' ', + $phpcsFile->config->tabWidth !== 0 ? $phpcsFile->config->tabWidth : self::DEFAULT_INDENTATION_WIDTH + ); + return str_repeat($indentation, strlen($matches[1])); + }, $code); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/NamespaceHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/NamespaceHelper.php new file mode 100644 index 000000000..708f7d935 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/NamespaceHelper.php @@ -0,0 +1,201 @@ + + */ + public static function getAllNamespacesPointers(File $phpcsFile): array + { + $tokens = $phpcsFile->getTokens(); + $lazyValue = static function () use ($phpcsFile, $tokens): array { + $all = TokenHelper::findNextAll($phpcsFile, T_NAMESPACE, 0); + $all = array_filter( + $all, + static function ($pointer) use ($phpcsFile, $tokens) { + $next = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + return $next === null || $tokens[$next]['code'] !== T_NS_SEPARATOR; + } + ); + + return array_values($all); + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'namespacePointers', $lazyValue); + } + + public static function isFullyQualifiedName(string $typeName): bool + { + return StringHelper::startsWith($typeName, self::NAMESPACE_SEPARATOR); + } + + public static function isFullyQualifiedPointer(File $phpcsFile, int $pointer): bool + { + return in_array($phpcsFile->getTokens()[$pointer]['code'], [T_NS_SEPARATOR, T_NAME_FULLY_QUALIFIED], true); + } + + public static function getFullyQualifiedTypeName(string $typeName): string + { + if (self::isFullyQualifiedName($typeName)) { + return $typeName; + } + + return sprintf('%s%s', self::NAMESPACE_SEPARATOR, $typeName); + } + + public static function hasNamespace(string $typeName): bool + { + $parts = self::getNameParts($typeName); + + return count($parts) > 1; + } + + /** + * @return list + */ + public static function getNameParts(string $name): array + { + $name = self::normalizeToCanonicalName($name); + + return explode(self::NAMESPACE_SEPARATOR, $name); + } + + public static function getLastNamePart(string $name): string + { + return array_slice(self::getNameParts($name), -1)[0]; + } + + public static function getName(File $phpcsFile, int $namespacePointer): string + { + /** @var int $namespaceNameStartPointer */ + $namespaceNameStartPointer = TokenHelper::findNextEffective($phpcsFile, $namespacePointer + 1); + $namespaceNameEndPointer = TokenHelper::findNextExcluding( + $phpcsFile, + TokenHelper::getNameTokenCodes(), + $namespaceNameStartPointer + 1 + ) - 1; + + return TokenHelper::getContent($phpcsFile, $namespaceNameStartPointer, $namespaceNameEndPointer); + } + + public static function findCurrentNamespacePointer(File $phpcsFile, int $pointer): ?int + { + $allNamespacesPointers = array_reverse(self::getAllNamespacesPointers($phpcsFile)); + foreach ($allNamespacesPointers as $namespacesPointer) { + if ($namespacesPointer < $pointer) { + return $namespacesPointer; + } + } + + return null; + } + + public static function findCurrentNamespaceName(File $phpcsFile, int $anyPointer): ?string + { + $namespacePointer = self::findCurrentNamespacePointer($phpcsFile, $anyPointer); + if ($namespacePointer === null) { + return null; + } + + return self::getName($phpcsFile, $namespacePointer); + } + + public static function getUnqualifiedNameFromFullyQualifiedName(string $name): string + { + $parts = self::getNameParts($name); + return $parts[count($parts) - 1]; + } + + public static function isQualifiedName(string $name): bool + { + return strpos($name, self::NAMESPACE_SEPARATOR) !== false; + } + + public static function normalizeToCanonicalName(string $fullyQualifiedName): string + { + return ltrim($fullyQualifiedName, self::NAMESPACE_SEPARATOR); + } + + public static function isTypeInNamespace(string $typeName, string $namespace): bool + { + return StringHelper::startsWith( + self::normalizeToCanonicalName($typeName) . '\\', + $namespace . '\\' + ); + } + + public static function resolveClassName(File $phpcsFile, string $nameAsReferencedInFile, int $currentPointer): string + { + return self::resolveName($phpcsFile, $nameAsReferencedInFile, ReferencedName::TYPE_CLASS, $currentPointer); + } + + public static function resolveName(File $phpcsFile, string $nameAsReferencedInFile, string $type, int $currentPointer): string + { + if (self::isFullyQualifiedName($nameAsReferencedInFile)) { + return $nameAsReferencedInFile; + } + + $useStatements = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $currentPointer); + + $uniqueId = UseStatement::getUniqueId($type, self::normalizeToCanonicalName($nameAsReferencedInFile)); + + if (isset($useStatements[$uniqueId])) { + return sprintf('%s%s', self::NAMESPACE_SEPARATOR, $useStatements[$uniqueId]->getFullyQualifiedTypeName()); + } + + $nameParts = self::getNameParts($nameAsReferencedInFile); + $firstPartUniqueId = UseStatement::getUniqueId($type, $nameParts[0]); + if (count($nameParts) > 1 && isset($useStatements[$firstPartUniqueId])) { + return sprintf( + '%s%s%s%s', + self::NAMESPACE_SEPARATOR, + $useStatements[$firstPartUniqueId]->getFullyQualifiedTypeName(), + self::NAMESPACE_SEPARATOR, + implode(self::NAMESPACE_SEPARATOR, array_slice($nameParts, 1)) + ); + } + + $name = sprintf('%s%s', self::NAMESPACE_SEPARATOR, $nameAsReferencedInFile); + + if ($type === ReferencedName::TYPE_CONSTANT && defined($name)) { + return $name; + } + + $namespaceName = self::findCurrentNamespaceName($phpcsFile, $currentPointer); + if ($namespaceName !== null) { + $name = sprintf('%s%s%s', self::NAMESPACE_SEPARATOR, $namespaceName, $name); + } + return $name; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParameterHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParameterHelper.php new file mode 100644 index 000000000..6c4c55565 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParameterHelper.php @@ -0,0 +1,34 @@ +getTokens(); + + if (!array_key_exists('nested_parenthesis', $tokens[$variablePointer])) { + return false; + } + + $parenthesisOpenerPointer = array_reverse(array_keys($tokens[$variablePointer]['nested_parenthesis']))[0]; + if (!array_key_exists('parenthesis_owner', $tokens[$parenthesisOpenerPointer])) { + return false; + } + + $parenthesisOwnerPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_owner']; + return in_array($tokens[$parenthesisOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParsedDocComment.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParsedDocComment.php new file mode 100644 index 000000000..2c4fa0113 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ParsedDocComment.php @@ -0,0 +1,108 @@ +openPointer = $openPointer; + $this->closePointer = $closePointer; + $this->node = $node; + $this->tokens = $tokens; + } + + public function getOpenPointer(): int + { + return $this->openPointer; + } + + public function getClosePointer(): int + { + return $this->closePointer; + } + + public function getNode(): PhpDocNode + { + return $this->node; + } + + public function getTokens(): TokenIterator + { + return $this->tokens; + } + + public function getNodeStartPointer(File $phpcsFile, Node $node): int + { + $tokens = $phpcsFile->getTokens(); + + $tagStartLine = $tokens[$this->openPointer]['line'] + $node->getAttribute('startLine') - 1; + + $searchPointer = $this->openPointer + 1; + for ($i = $this->openPointer + 1; $i < $this->closePointer; $i++) { + if ($tagStartLine === $tokens[$i]['line']) { + $searchPointer = $i; + break; + } + } + + return TokenHelper::findNext($phpcsFile, array_merge(TokenHelper::$annotationTokenCodes, [T_DOC_COMMENT_STRING]), $searchPointer); + } + + public function getNodeEndPointer(File $phpcsFile, Node $node, int $nodeStartPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $content = trim($this->tokens->getContentBetween( + $node->getAttribute(Attribute::START_INDEX), + $node->getAttribute(Attribute::END_INDEX) + 1 + )); + $length = strlen($content); + + $searchPointer = $nodeStartPointer; + + $content = ''; + for ($i = $nodeStartPointer; $i < count($tokens); $i++) { + $content .= $tokens[$i]['content']; + + if (strlen($content) >= $length) { + $searchPointer = $i; + break; + } + } + + return TokenHelper::findPrevious( + $phpcsFile, + array_merge(TokenHelper::$annotationTokenCodes, [T_DOC_COMMENT_STRING]), + $searchPointer + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PhpDocParserHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PhpDocParserHelper.php new file mode 100644 index 000000000..6cc06d61a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PhpDocParserHelper.php @@ -0,0 +1,82 @@ + true, 'indexes' => true]; + + $constantExpressionParser = new ConstExprParser(true, true, $usedAttributes); + $parser = new PhpDocParser( + new TypeParser($constantExpressionParser, true, $usedAttributes), + $constantExpressionParser, + true, + true, + $usedAttributes, + true, + true + ); + } + + return $parser; + } + + public static function getPrinter(): Printer + { + static $printer; + + if ($printer === null) { + $printer = new Printer(); + } + + return $printer; + } + + /** + * @template T of Node + * @param T $node + * @return T + */ + public static function cloneNode(Node $node): Node + { + static $cloningTraverser; + + if ($cloningTraverser === null) { + $cloningTraverser = new NodeTraverser([new CloningVisitor()]); + } + + [$cloneNode] = $cloningTraverser->traverse([$node]); + + return $cloneNode; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PropertyHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PropertyHelper.php new file mode 100644 index 000000000..74a0726fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/PropertyHelper.php @@ -0,0 +1,140 @@ +getTokens(); + + $previousPointer = TokenHelper::findPreviousExcluding( + $phpcsFile, + array_merge(TokenHelper::$ineffectiveTokenCodes, TokenHelper::getTypeHintTokenCodes(), [T_NULLABLE]), + $variablePointer - 1 + ); + + if ($tokens[$previousPointer]['code'] === T_STATIC) { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } + + if (in_array($tokens[$previousPointer]['code'], [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_VAR, T_READONLY], true)) { + $constructorPointer = TokenHelper::findPrevious($phpcsFile, T_FUNCTION, $previousPointer - 1); + + if ($constructorPointer === null) { + return true; + } + + return $tokens[$constructorPointer]['parenthesis_closer'] < $previousPointer || $promoted; + } + + if ( + !array_key_exists('conditions', $tokens[$variablePointer]) + || count($tokens[$variablePointer]['conditions']) === 0 + ) { + return false; + } + + $functionPointer = TokenHelper::findPrevious( + $phpcsFile, + array_merge(TokenHelper::$functionTokenCodes, [T_SEMICOLON, T_CLOSE_CURLY_BRACKET, T_OPEN_CURLY_BRACKET]), + $variablePointer - 1 + ); + if ( + $functionPointer !== null + && in_array($tokens[$functionPointer]['code'], TokenHelper::$functionTokenCodes, true) + ) { + return false; + } + + $conditionCode = array_values($tokens[$variablePointer]['conditions'])[count($tokens[$variablePointer]['conditions']) - 1]; + + return in_array($conditionCode, Tokens::$ooScopeTokens, true); + } + + public static function findTypeHint(File $phpcsFile, int $propertyPointer): ?TypeHint + { + $tokens = $phpcsFile->getTokens(); + + $propertyStartPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR, T_STATIC, T_READONLY], + $propertyPointer - 1 + ); + + $typeHintEndPointer = TokenHelper::findPrevious( + $phpcsFile, + TokenHelper::getTypeHintTokenCodes(), + $propertyPointer - 1, + $propertyStartPointer + ); + if ($typeHintEndPointer === null) { + return null; + } + + $typeHintStartPointer = TypeHintHelper::getStartPointer($phpcsFile, $typeHintEndPointer); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $typeHintStartPointer - 1, $propertyStartPointer); + $nullable = $previousPointer !== null && $tokens[$previousPointer]['code'] === T_NULLABLE; + + if ($nullable) { + $typeHintStartPointer = $previousPointer; + } + + $typeHint = TokenHelper::getContent($phpcsFile, $typeHintStartPointer, $typeHintEndPointer); + + if (!$nullable) { + $nullable = preg_match('~(?:^|\|\s*)null(?:\s*\||$)~i', $typeHint) === 1; + } + + /** @var string $typeHint */ + $typeHint = preg_replace('~\s+~', '', $typeHint); + + return new TypeHint($typeHint, $nullable, $typeHintStartPointer, $typeHintEndPointer); + } + + public static function getFullyQualifiedName(File $phpcsFile, int $propertyPointer): string + { + $propertyToken = $phpcsFile->getTokens()[$propertyPointer]; + $propertyName = $propertyToken['content']; + + $classPointer = array_reverse(array_keys($propertyToken['conditions']))[0]; + if ($phpcsFile->getTokens()[$classPointer]['code'] === T_ANON_CLASS) { + return sprintf('class@anonymous::%s', $propertyName); + } + + $name = sprintf('%s%s::%s', NamespaceHelper::NAMESPACE_SEPARATOR, ClassHelper::getName($phpcsFile, $classPointer), $propertyName); + $namespace = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $propertyPointer); + return $namespace !== null ? sprintf('%s%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $namespace, $name) : $name; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedName.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedName.php new file mode 100644 index 000000000..8890db40d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedName.php @@ -0,0 +1,75 @@ +nameAsReferencedInFile = $nameAsReferencedInFile; + $this->startPointer = $startPointer; + $this->endPointer = $endPointer; + $this->type = $type; + } + + public function getNameAsReferencedInFile(): string + { + return $this->nameAsReferencedInFile; + } + + public function getStartPointer(): int + { + return $this->startPointer; + } + + public function getType(): string + { + return $this->type; + } + + public function getEndPointer(): int + { + return $this->endPointer; + } + + public function isClass(): bool + { + return $this->type === self::TYPE_CLASS; + } + + public function isConstant(): bool + { + return $this->type === self::TYPE_CONSTANT; + } + + public function isFunction(): bool + { + return $this->type === self::TYPE_FUNCTION; + } + + public function hasSameUseStatementType(UseStatement $useStatement): bool + { + return $this->getType() === $useStatement->getType(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedNameHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedNameHelper.php new file mode 100644 index 000000000..1e215f13f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ReferencedNameHelper.php @@ -0,0 +1,532 @@ + + */ + public static function getAllReferencedNames(File $phpcsFile, int $openTagPointer): array + { + $lazyValue = static function () use ($phpcsFile, $openTagPointer): array { + return self::createAllReferencedNames($phpcsFile, $openTagPointer); + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'references', $lazyValue); + } + + /** + * @return list + */ + public static function getAllReferencedNamesInAttributes(File $phpcsFile, int $openTagPointer): array + { + $lazyValue = static function () use ($phpcsFile, $openTagPointer): array { + return self::createAllReferencedNamesInAttributes($phpcsFile, $openTagPointer); + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'referencesFromAttributes', $lazyValue); + } + + public static function getReferenceName(File $phpcsFile, int $nameStartPointer, int $nameEndPointer): string + { + $tokens = $phpcsFile->getTokens(); + + $referencedName = ''; + for ($i = $nameStartPointer; $i <= $nameEndPointer; $i++) { + if (in_array($tokens[$i]['code'], Tokens::$emptyTokens, true)) { + continue; + } + + $referencedName .= $tokens[$i]['content']; + } + + return $referencedName; + } + + public static function getReferencedNameEndPointer(File $phpcsFile, int $startPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + + $nameTokenCodesWithWhitespace = array_merge($nameTokenCodes, Tokens::$emptyTokens); + + $lastNamePointer = $startPointer; + for ($i = $startPointer + 1; $i < count($tokens); $i++) { + if (!in_array($tokens[$i]['code'], $nameTokenCodesWithWhitespace, true)) { + break; + } + + if (!in_array($tokens[$i]['code'], $nameTokenCodes, true)) { + continue; + } + + $lastNamePointer = $i; + } + + return $lastNamePointer; + } + + /** + * @return list + */ + private static function createAllReferencedNames(File $phpcsFile, int $openTagPointer): array + { + $referencedNames = []; + + $beginSearchAtPointer = $openTagPointer + 1; + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + $nameTokenCodes[] = T_DOUBLE_QUOTED_STRING; + $nameTokenCodes[] = T_HEREDOC; + + $tokens = $phpcsFile->getTokens(); + while (true) { + $nameStartPointer = TokenHelper::findNext($phpcsFile, $nameTokenCodes, $beginSearchAtPointer); + if ($nameStartPointer === null) { + break; + } + + // Find referenced names inside double quotes string + if (self::isNeedParsedContent($tokens[$nameStartPointer]['code'])) { + $content = $tokens[$nameStartPointer]['content']; + $currentPointer = $nameStartPointer + 1; + while (self::isNeedParsedContent($tokens[$currentPointer]['code'])) { + $content .= $tokens[$currentPointer]['content']; + $currentPointer++; + } + + $names = self::getReferencedNamesFromString($content); + foreach ($names as $name) { + $referencedNames[] = new ReferencedName($name, $nameStartPointer, $nameStartPointer, ReferencedName::TYPE_CLASS); + } + + $beginSearchAtPointer = $currentPointer; + continue; + } + + // Attributes are parsed in specific method + $attributeStartPointerBefore = TokenHelper::findPrevious($phpcsFile, T_ATTRIBUTE, $nameStartPointer - 1, $beginSearchAtPointer); + if ($attributeStartPointerBefore !== null) { + if ($tokens[$attributeStartPointerBefore]['attribute_closer'] > $nameStartPointer) { + $beginSearchAtPointer = $tokens[$attributeStartPointerBefore]['attribute_closer'] + 1; + continue; + } + } + + if (!self::isReferencedName($phpcsFile, $nameStartPointer)) { + /** @var int $beginSearchAtPointer */ + $beginSearchAtPointer = TokenHelper::findNextExcluding( + $phpcsFile, + array_merge(TokenHelper::$ineffectiveTokenCodes, $nameTokenCodes), + $nameStartPointer + 1 + ); + continue; + } + + $nameEndPointer = self::getReferencedNameEndPointer($phpcsFile, $nameStartPointer); + + $referencedNames[] = new ReferencedName( + self::getReferenceName($phpcsFile, $nameStartPointer, $nameEndPointer), + $nameStartPointer, + $nameEndPointer, + self::getReferenceType($phpcsFile, $nameStartPointer, $nameEndPointer) + ); + $beginSearchAtPointer = $nameEndPointer + 1; + } + return $referencedNames; + } + + private static function getReferenceType(File $phpcsFile, int $nameStartPointer, int $nameEndPointer): string + { + $tokens = $phpcsFile->getTokens(); + + $nextTokenAfterEndPointer = TokenHelper::findNextEffective($phpcsFile, $nameEndPointer + 1); + $previousTokenBeforeStartPointer = TokenHelper::findPreviousEffective($phpcsFile, $nameStartPointer - 1); + + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + + if ($tokens[$nextTokenAfterEndPointer]['code'] === T_OPEN_PARENTHESIS) { + return $tokens[$previousTokenBeforeStartPointer]['code'] === T_NEW + ? ReferencedName::TYPE_CLASS + : ReferencedName::TYPE_FUNCTION; + } + + if ( + $tokens[$previousTokenBeforeStartPointer]['code'] === T_TYPE_UNION + || $tokens[$nextTokenAfterEndPointer]['code'] === T_TYPE_UNION + ) { + return ReferencedName::TYPE_CLASS; + } + + if ( + $tokens[$previousTokenBeforeStartPointer]['code'] === T_TYPE_INTERSECTION + || $tokens[$nextTokenAfterEndPointer]['code'] === T_TYPE_INTERSECTION + ) { + return ReferencedName::TYPE_CLASS; + } + + if ($tokens[$nextTokenAfterEndPointer]['code'] === T_BITWISE_AND) { + $tokenAfterNextToken = TokenHelper::findNextEffective($phpcsFile, $nextTokenAfterEndPointer + 1); + + return in_array($tokens[$tokenAfterNextToken]['code'], [T_VARIABLE, T_ELLIPSIS], true) + ? ReferencedName::TYPE_CLASS + : ReferencedName::TYPE_CONSTANT; + } + + if ( + in_array($tokens[$nextTokenAfterEndPointer]['code'], [ + T_VARIABLE, + // Variadic parameter + T_ELLIPSIS, + ], true) + ) { + return ReferencedName::TYPE_CLASS; + } + + if ($tokens[$previousTokenBeforeStartPointer]['code'] === T_COLON) { + $previousTokenPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousTokenBeforeStartPointer - 1); + + if ( + $tokens[$previousTokenPointer]['code'] === T_PARAM_NAME + && $tokens[$nextTokenAfterEndPointer]['code'] !== T_DOUBLE_COLON + ) { + return ReferencedName::TYPE_CONSTANT; + } + + // Return type hint + return ReferencedName::TYPE_CLASS; + } + + if ( + in_array($tokens[$previousTokenBeforeStartPointer]['code'], [ + T_EXTENDS, + T_IMPLEMENTS, + T_INSTANCEOF, + // Trait + T_USE, + T_NEW, + // Nullable type hint + T_NULLABLE, + ], true) + || $tokens[$nextTokenAfterEndPointer]['code'] === T_DOUBLE_COLON + ) { + return ReferencedName::TYPE_CLASS; + } + + if ($tokens[$previousTokenBeforeStartPointer]['code'] === T_COMMA) { + $previousTokenPointer = TokenHelper::findPreviousExcluding( + $phpcsFile, + array_merge([T_COMMA], $nameTokenCodes, TokenHelper::$ineffectiveTokenCodes), + $previousTokenBeforeStartPointer - 1 + ); + + return in_array($tokens[$previousTokenPointer]['code'], [ + T_IMPLEMENTS, + T_EXTENDS, + T_USE, + ], true) + ? ReferencedName::TYPE_CLASS + : ReferencedName::TYPE_CONSTANT; + } + + if (in_array($tokens[$previousTokenBeforeStartPointer]['code'], [T_BITWISE_OR, T_OPEN_PARENTHESIS], true)) { + $catchPointer = TokenHelper::findPreviousExcluding( + $phpcsFile, + array_merge([T_BITWISE_OR, T_OPEN_PARENTHESIS], $nameTokenCodes, TokenHelper::$ineffectiveTokenCodes), + $previousTokenBeforeStartPointer - 1 + ); + + if ($tokens[$catchPointer]['code'] === T_CATCH) { + return ReferencedName::TYPE_CLASS; + } + } + + return ReferencedName::TYPE_CONSTANT; + } + + private static function isReferencedName(File $phpcsFile, int $startPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $startPointer + 1); + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $startPointer - 1); + + if ($nextPointer !== null && $tokens[$nextPointer]['code'] === T_DOUBLE_COLON) { + return !in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], true); + } + + if ( + count($tokens[$startPointer]['conditions']) > 0 + && array_values(array_reverse($tokens[$startPointer]['conditions']))[0] === T_USE + ) { + // Method imported from trait + return false; + } + + $previousToken = $tokens[$previousPointer]; + + $skipTokenCodes = [ + T_FUNCTION, + T_AS, + T_DOUBLE_COLON, + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + T_NAMESPACE, + T_CONST, + T_ENUM_CASE, + ]; + + if ($previousToken['code'] === T_USE) { + $classPointer = TokenHelper::findPrevious($phpcsFile, [T_CLASS, T_TRAIT, T_ANON_CLASS, T_ENUM], $startPointer - 1); + if ($classPointer !== null) { + $classToken = $tokens[$classPointer]; + return $startPointer > $classToken['scope_opener'] && $startPointer < $classToken['scope_closer']; + } + + return false; + } + + if ( + $previousToken['code'] === T_OPEN_PARENTHESIS + && isset($previousToken['parenthesis_owner']) + && $tokens[$previousToken['parenthesis_owner']]['code'] === T_DECLARE + ) { + return false; + } + + if ( + $previousToken['code'] === T_COMMA + && TokenHelper::findPreviousLocal($phpcsFile, T_DECLARE, $previousPointer - 1) !== null + ) { + return false; + } + + if ($previousToken['code'] === T_COMMA) { + $constPointer = TokenHelper::findPreviousLocal($phpcsFile, T_CONST, $previousPointer - 1); + if ( + $constPointer !== null + && TokenHelper::findNext($phpcsFile, [T_OPEN_SHORT_ARRAY, T_ARRAY], $constPointer + 1, $startPointer) === null + ) { + return false; + } + } elseif ($previousToken['code'] === T_BITWISE_AND) { + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + $isFunctionPointerBefore = TokenHelper::findPreviousLocal($phpcsFile, T_FUNCTION, $previousPointer - 1) !== null; + + if ($tokens[$pointerBefore]['code'] !== T_VARIABLE && $isFunctionPointerBefore) { + return false; + } + } elseif ($previousToken['code'] === T_GOTO) { + return false; + } + + $isProbablyReferencedName = !in_array( + $previousToken['code'], + array_merge($skipTokenCodes, TokenHelper::$typeKeywordTokenCodes), + true + ); + + if (!$isProbablyReferencedName) { + return false; + } + + $endPointer = self::getReferencedNameEndPointer($phpcsFile, $startPointer); + $referencedName = self::getReferenceName($phpcsFile, $startPointer, $endPointer); + + if (TypeHintHelper::isSimpleTypeHint($referencedName) || $referencedName === 'object') { + return $tokens[$nextPointer]['code'] === T_OPEN_PARENTHESIS; + } + + return true; + } + + /** + * @return list + */ + private static function createAllReferencedNamesInAttributes(File $phpcsFile, int $openTagPointer): array + { + $referencedNames = []; + + $tokens = $phpcsFile->getTokens(); + + $attributePointers = TokenHelper::findNextAll($phpcsFile, T_ATTRIBUTE, $openTagPointer + 1); + + foreach ($attributePointers as $attributeStartPointer) { + $searchStartPointer = $attributeStartPointer + 1; + $searchEndPointer = $tokens[$attributeStartPointer]['attribute_closer']; + + $searchPointer = $searchStartPointer; + $searchTokens = array_merge(TokenHelper::getNameTokenCodes(), [T_OPEN_PARENTHESIS, T_CLOSE_PARENTHESIS]); + $level = 0; + do { + $pointer = TokenHelper::findNext($phpcsFile, $searchTokens, $searchPointer, $searchEndPointer); + + if ($pointer === null) { + break; + } + + if ($tokens[$pointer]['code'] === T_OPEN_PARENTHESIS) { + $level++; + $searchPointer = $pointer + 1; + continue; + } + + if ($tokens[$pointer]['code'] === T_CLOSE_PARENTHESIS) { + $level--; + $searchPointer = $pointer + 1; + continue; + } + + $referencedNameEndPointer = self::getReferencedNameEndPointer($phpcsFile, $pointer); + + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + + if (in_array($tokens[$pointerBefore]['code'], [T_OPEN_TAG, T_ATTRIBUTE], true)) { + $referenceType = ReferencedName::TYPE_CLASS; + } elseif ($tokens[$pointerBefore]['code'] === T_COMMA && $level === 0) { + $referenceType = ReferencedName::TYPE_CLASS; + } elseif (self::isReferencedName($phpcsFile, $pointer)) { + $referenceType = self::getReferenceType($phpcsFile, $pointer, $referencedNameEndPointer); + } else { + $searchPointer = $pointer + 1; + continue; + } + + $referencedName = self::getReferenceName($phpcsFile, $pointer, $referencedNameEndPointer); + + $referencedNames[] = new ReferencedName( + $referencedName, + $attributeStartPointer, + $tokens[$attributeStartPointer]['attribute_closer'], + $referenceType + ); + + $searchPointer = $referencedNameEndPointer + 1; + + } while (true); + } + + return $referencedNames; + } + + /** + * @param int|string $code + */ + private static function isNeedParsedContent($code): bool + { + return in_array($code, [T_DOUBLE_QUOTED_STRING, T_HEREDOC], true); + } + + /** + * @return list + */ + private static function getReferencedNamesFromString(string $content): array + { + $referencedNames = []; + $subTokens = token_get_all(' $token) { + if (is_array($token) && $token[0] === T_DOUBLE_COLON) { + $referencedName = ''; + $tmpPosition = $position - 1; + while (true) { + if (!is_array($subTokens[$tmpPosition]) || !in_array($subTokens[$tmpPosition][0], [T_NS_SEPARATOR, T_STRING], true)) { + break; + } + + $referencedName = $subTokens[$tmpPosition][1] . $referencedName; + $tmpPosition--; + } + + $referencedNames[] = $referencedName; + } elseif (is_array($token) && $token[0] === T_NEW) { + $referencedName = ''; + $tmpPosition = $position + 1; + while (true) { + if (!is_array($subTokens[$tmpPosition])) { + break; + } + if ($subTokens[$tmpPosition][0] === T_WHITESPACE) { + $tmpPosition++; + continue; + } + if (!in_array( + $subTokens[$tmpPosition][0], + [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED, T_NAME_RELATIVE], + true + )) { + break; + } + + $referencedName .= $subTokens[$tmpPosition][1]; + $tmpPosition++; + } + if ($referencedName !== '') { + $referencedNames[] = $referencedName; + } + } + } + + return $referencedNames; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ScopeHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ScopeHelper.php new file mode 100644 index 000000000..68c65b73d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/ScopeHelper.php @@ -0,0 +1,65 @@ +getTokens(); + + $getScope = static function (int $pointer) use ($tokens): int { + $scope = 0; + + foreach (array_reverse($tokens[$pointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (!in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) { + continue; + } + + $scope = $tokens[$conditionPointer]['level'] + 1; + break; + } + + return $scope; + }; + + return $getScope($firstPointer) === $getScope($secondPointer); + } + + public static function getRootPointer(File $phpcsFile, int $pointer): int + { + $rootPointer = TokenHelper::findNext($phpcsFile, T_OPEN_TAG, 0); + + $rootPointers = array_reverse(self::getAllRootPointers($phpcsFile)); + foreach ($rootPointers as $currentRootPointer) { + if ($currentRootPointer < $pointer) { + $rootPointer = $currentRootPointer; + break; + } + } + + return $rootPointer; + } + + /** + * @return list + */ + public static function getAllRootPointers(File $phpcsFile): array + { + $lazyValue = static function () use ($phpcsFile): array { + return TokenHelper::findNextAll($phpcsFile, T_OPEN_TAG, 0); + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'openTagPointers', $lazyValue); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffLocalCache.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffLocalCache.php new file mode 100644 index 000000000..fac1f790e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffLocalCache.php @@ -0,0 +1,49 @@ +> + */ + private static $cache = []; + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint + * @return mixed + */ + public static function getAndSetIfNotCached(File $phpcsFile, string $key, Closure $lazyValue) + { + $fixerLoops = $phpcsFile->fixer !== null ? $phpcsFile->fixer->loops : 0; + $internalKey = sprintf('%s-%s', $phpcsFile->getFilename(), $key); + + self::setIfNotCached($fixerLoops, $internalKey, $lazyValue); + + return self::$cache[$fixerLoops][$internalKey] ?? null; + } + + private static function setIfNotCached(int $fixerLoops, string $internalKey, Closure $lazyValue): void + { + if (array_key_exists($fixerLoops, self::$cache) && array_key_exists($internalKey, self::$cache[$fixerLoops])) { + return; + } + + self::$cache[$fixerLoops][$internalKey] = $lazyValue(); + + if ($fixerLoops > 0) { + unset(self::$cache[$fixerLoops - 1]); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffSettingsHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffSettingsHelper.php new file mode 100644 index 000000000..ade9c26ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/SniffSettingsHelper.php @@ -0,0 +1,90 @@ + $settings + * @return list + */ + public static function normalizeArray(array $settings): array + { + $settings = array_map(static function (string $value): string { + return trim($value); + }, $settings); + $settings = array_filter($settings, static function (string $value): bool { + return $value !== ''; + }); + return array_values($settings); + } + + /** + * @param array $settings + * @return array + */ + public static function normalizeAssociativeArray(array $settings): array + { + $normalizedSettings = []; + foreach ($settings as $key => $value) { + if (is_string($key)) { + $key = trim($key); + } + if (is_string($value)) { + $value = trim($value); + } + if ($key === '' || $value === '') { + continue; + } + $normalizedSettings[$key] = $value; + } + + return $normalizedSettings; + } + + public static function isValidRegularExpression(string $expression): bool + { + return preg_match('~^(?:\(.*\)|\{.*\}|\[.*\])[a-z]*\z~i', $expression) !== 0 + || preg_match('~^([^a-z\s\\\\]).*\\1[a-z]*\z~i', $expression) !== 0; + } + + public static function isEnabledByPhpVersion(?bool $value, int $phpVersionLimit): bool + { + if ($value !== null) { + return $value; + } + + $phpVersion = Config::getConfigData('php_version') !== null ? (int) Config::getConfigData('php_version') : PHP_VERSION_ID; + return $phpVersion >= $phpVersionLimit; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/StringHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/StringHelper.php new file mode 100644 index 000000000..52db3a81f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/StringHelper.php @@ -0,0 +1,25 @@ +> $annotations */ + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $pointer, self::ANNOTATION); + + return array_reduce( + $annotations, + static function (bool $carry, Annotation $annotation) use ($suppressName): bool { + $annotationSuppressName = explode(' ', $annotation->getValue()->value)[0]; + + if ( + $suppressName === $annotationSuppressName + || strpos($suppressName, sprintf('%s.', $annotationSuppressName)) === 0 + ) { + $carry = true; + } + + return $carry; + }, + false + ); + } + + public static function removeSuppressAnnotation(File $phpcsFile, int $pointer, string $suppressName): void + { + $suppressAnnotation = null; + /** @var Annotation $annotation */ + foreach (AnnotationHelper::getAnnotations($phpcsFile, $pointer, self::ANNOTATION) as $annotation) { + if ($annotation->getValue()->value === $suppressName) { + $suppressAnnotation = $annotation; + break; + } + } + + assert($suppressAnnotation !== null); + + $tokens = $phpcsFile->getTokens(); + + /** @var int $pointerBefore */ + $pointerBefore = TokenHelper::findPrevious( + $phpcsFile, + [T_DOC_COMMENT_OPEN_TAG, T_DOC_COMMENT_STAR], + $suppressAnnotation->getStartPointer() - 1 + ); + + $changeStart = $tokens[$pointerBefore]['code'] === T_DOC_COMMENT_STAR ? $pointerBefore : $suppressAnnotation->getStartPointer(); + + /** @var int $changeEnd */ + $changeEnd = TokenHelper::findNext( + $phpcsFile, + [T_DOC_COMMENT_CLOSE_TAG, T_DOC_COMMENT_STAR], + $suppressAnnotation->getEndPointer() + 1 + ) - 1; + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $changeStart, $changeEnd); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TernaryOperatorHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TernaryOperatorHelper.php new file mode 100644 index 000000000..ce1f675f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TernaryOperatorHelper.php @@ -0,0 +1,182 @@ +getTokens(); + + $pointer = $inlineThenPointer; + do { + $pointer = TokenHelper::findNext( + $phpcsFile, + [T_INLINE_ELSE, T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY, T_OPEN_SQUARE_BRACKET], + $pointer + 1 + ); + + if ($tokens[$pointer]['code'] === T_OPEN_PARENTHESIS) { + $pointer = $tokens[$pointer]['parenthesis_closer']; + continue; + } + + if (in_array($tokens[$pointer]['code'], [T_OPEN_SHORT_ARRAY, T_OPEN_SQUARE_BRACKET], true)) { + $pointer = $tokens[$pointer]['bracket_closer']; + continue; + } + + if (ScopeHelper::isInSameScope($phpcsFile, $inlineThenPointer, $pointer)) { + break; + } + } while ($pointer !== null); + + return $pointer; + } + + public static function getStartPointer(File $phpcsFile, int $inlineThenPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $pointerBeforeCondition = $inlineThenPointer; + do { + $pointerBeforeCondition = TokenHelper::findPrevious( + $phpcsFile, + [T_EQUAL, T_DOUBLE_ARROW, T_COMMA, T_RETURN, T_THROW, T_CASE, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY, T_OPEN_PARENTHESIS], + $pointerBeforeCondition - 1 + ); + + if ( + in_array($tokens[$pointerBeforeCondition]['code'], [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY], true) + && $tokens[$pointerBeforeCondition]['bracket_closer'] < $inlineThenPointer + ) { + continue; + } + + if ( + $tokens[$pointerBeforeCondition]['code'] === T_OPEN_PARENTHESIS + && $tokens[$pointerBeforeCondition]['parenthesis_closer'] < $inlineThenPointer + ) { + continue; + } + + break; + + } while (true); + + return TokenHelper::findNextEffective($phpcsFile, $pointerBeforeCondition + 1); + } + + public static function getEndPointer(File $phpcsFile, int $inlineThenPointer, int $inlineElsePointer): int + { + $tokens = $phpcsFile->getTokens(); + + $pointerAfterInlineElseEnd = $inlineElsePointer; + do { + $pointerAfterInlineElseEnd = TokenHelper::findNext( + $phpcsFile, + [T_SEMICOLON, T_COLON, T_COMMA, T_DOUBLE_ARROW, T_CLOSE_PARENTHESIS, T_CLOSE_SHORT_ARRAY, T_CLOSE_SQUARE_BRACKET, T_COALESCE], + $pointerAfterInlineElseEnd + 1 + ); + + if ($pointerAfterInlineElseEnd === null) { + continue; + } + + if ($tokens[$pointerAfterInlineElseEnd]['code'] === T_CLOSE_PARENTHESIS) { + if ($tokens[$pointerAfterInlineElseEnd]['parenthesis_opener'] < $inlineThenPointer) { + break; + } + } elseif (in_array($tokens[$pointerAfterInlineElseEnd]['code'], [T_CLOSE_SHORT_ARRAY, T_CLOSE_SQUARE_BRACKET], true)) { + if ($tokens[$pointerAfterInlineElseEnd]['bracket_opener'] < $inlineThenPointer) { + break; + } + } elseif ($tokens[$pointerAfterInlineElseEnd]['code'] === T_COMMA) { + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY], + $pointerAfterInlineElseEnd - 1, + $inlineThenPointer + ); + + if ($previousPointer === null) { + break; + } + + if ( + $tokens[$previousPointer]['code'] === T_OPEN_PARENTHESIS + && $tokens[$previousPointer]['parenthesis_closer'] < $pointerAfterInlineElseEnd + ) { + break; + } + + if ( + $tokens[$previousPointer]['code'] === T_OPEN_SHORT_ARRAY + && $tokens[$previousPointer]['bracket_closer'] < $pointerAfterInlineElseEnd + ) { + break; + } + + } elseif ($tokens[$pointerAfterInlineElseEnd]['code'] === T_DOUBLE_ARROW) { + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + T_OPEN_SHORT_ARRAY, + $pointerAfterInlineElseEnd - 1, + $inlineThenPointer + ); + if ($previousPointer === null) { + break; + } + } elseif (ScopeHelper::isInSameScope($phpcsFile, $inlineElsePointer, $pointerAfterInlineElseEnd)) { + break; + } + } while ($pointerAfterInlineElseEnd !== null); + + if ($pointerAfterInlineElseEnd !== null) { + return TokenHelper::findPreviousEffective($phpcsFile, $pointerAfterInlineElseEnd - 1); + } + + return TokenHelper::findPreviousEffective($phpcsFile, count($tokens) - 1); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenHelper.php new file mode 100644 index 000000000..4773a923f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenHelper.php @@ -0,0 +1,534 @@ + */ + public static $arrayTokenCodes = [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + /** @var array */ + public static $typeKeywordTokenCodes = [ + T_CLASS, + T_TRAIT, + T_INTERFACE, + T_ENUM, + ]; + + /** @var array */ + public static $typeWithAnonymousClassKeywordTokenCodes = [ + T_CLASS, + T_ANON_CLASS, + T_TRAIT, + T_INTERFACE, + T_ENUM, + ]; + + /** @var array */ + public static $ineffectiveTokenCodes = [ + T_WHITESPACE, + T_COMMENT, + T_DOC_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STAR, + T_DOC_COMMENT_STRING, + T_DOC_COMMENT_TAG, + T_DOC_COMMENT_WHITESPACE, + T_PHPCS_DISABLE, + T_PHPCS_ENABLE, + T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE, + T_PHPCS_SET, + ]; + + /** @var array */ + public static $annotationTokenCodes = [ + T_DOC_COMMENT_TAG, + T_PHPCS_DISABLE, + T_PHPCS_ENABLE, + T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE, + T_PHPCS_SET, + ]; + + /** @var array */ + public static $inlineCommentTokenCodes = [ + T_COMMENT, + T_PHPCS_DISABLE, + T_PHPCS_ENABLE, + T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE, + T_PHPCS_SET, + ]; + + /** @var array */ + public static $earlyExitTokenCodes = [ + T_RETURN, + T_CONTINUE, + T_BREAK, + T_THROW, + T_EXIT, + ]; + + /** @var array */ + public static $functionTokenCodes = [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + /** @var array */ + public static $propertyModifiersTokenCodes = [ + T_VAR, + T_PUBLIC, + T_PROTECTED, + T_PRIVATE, + T_READONLY, + T_STATIC, + ]; + + /** + * @param int|string|array $types + */ + public static function findNext(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findNext($types, $startPointer, $endPointer, false); + return $token === false ? null : $token; + } + + /** + * @param int|string|array $types + * @return list + */ + public static function findNextAll(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): array + { + $pointers = []; + + $actualStartPointer = $startPointer; + while (true) { + $pointer = self::findNext($phpcsFile, $types, $actualStartPointer, $endPointer); + if ($pointer === null) { + break; + } + + $pointers[] = $pointer; + $actualStartPointer = $pointer + 1; + } + + return $pointers; + } + + /** + * @param int|string|array $types + */ + public static function findNextContent(File $phpcsFile, $types, string $content, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findNext($types, $startPointer, $endPointer, false, $content); + return $token === false ? null : $token; + } + + /** + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findNextEffective(File $phpcsFile, int $startPointer, ?int $endPointer = null): ?int + { + return self::findNextExcluding($phpcsFile, self::$ineffectiveTokenCodes, $startPointer, $endPointer); + } + + /** + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findNextNonWhitespace(File $phpcsFile, int $startPointer, ?int $endPointer = null): ?int + { + return self::findNextExcluding($phpcsFile, T_WHITESPACE, $startPointer, $endPointer); + } + + /** + * @param int|string|array $types + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findNextExcluding(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findNext($types, $startPointer, $endPointer, true); + return $token === false ? null : $token; + } + + /** + * @param int|string|array $types + */ + public static function findNextLocal(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findNext($types, $startPointer, $endPointer, false, null, true); + return $token === false ? null : $token; + } + + /** + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findNextAnyToken(File $phpcsFile, int $startPointer, ?int $endPointer = null): ?int + { + return self::findNextExcluding($phpcsFile, [], $startPointer, $endPointer); + } + + /** + * @param int|string|array $types + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findPrevious(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findPrevious($types, $startPointer, $endPointer, false); + return $token === false ? null : $token; + } + + /** + * @param int|string|array $types + */ + public static function findPreviousContent(File $phpcsFile, $types, string $content, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findPrevious($types, $startPointer, $endPointer, false, $content); + return $token === false ? null : $token; + } + + /** + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findPreviousEffective(File $phpcsFile, int $startPointer, ?int $endPointer = null): ?int + { + return self::findPreviousExcluding($phpcsFile, self::$ineffectiveTokenCodes, $startPointer, $endPointer); + } + + /** + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findPreviousNonWhitespace(File $phpcsFile, int $startPointer, ?int $endPointer = null): ?int + { + return self::findPreviousExcluding($phpcsFile, T_WHITESPACE, $startPointer, $endPointer); + } + + /** + * @param int|string|array $types + * @param int $startPointer Search starts at this token, inclusive + * @param int|null $endPointer Search ends at this token, exclusive + */ + public static function findPreviousExcluding(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findPrevious($types, $startPointer, $endPointer, true); + return $token === false ? null : $token; + } + + /** + * @param int|string|array $types + */ + public static function findPreviousLocal(File $phpcsFile, $types, int $startPointer, ?int $endPointer = null): ?int + { + /** @var int|false $token */ + $token = $phpcsFile->findPrevious($types, $startPointer, $endPointer, false, null, true); + return $token === false ? null : $token; + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findFirstTokenOnLine(File $phpcsFile, int $pointer): int + { + if ($pointer === 0) { + return $pointer; + } + + $tokens = $phpcsFile->getTokens(); + + $line = $tokens[$pointer]['line']; + + do { + $pointer--; + } while ($tokens[$pointer]['line'] === $line); + + return $pointer + 1; + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findLastTokenOnLine(File $phpcsFile, int $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $line = $tokens[$pointer]['line']; + + do { + $pointer++; + } while (array_key_exists($pointer, $tokens) && $tokens[$pointer]['line'] === $line); + + return $pointer - 1; + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findLastTokenOnPreviousLine(File $phpcsFile, int $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $line = $tokens[$pointer]['line']; + + do { + $pointer--; + } while ($tokens[$pointer]['line'] === $line); + + return $pointer; + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findFirstTokenOnNextLine(File $phpcsFile, int $pointer): ?int + { + $tokens = $phpcsFile->getTokens(); + if ($pointer >= count($tokens)) { + return null; + } + + $line = $tokens[$pointer]['line']; + + do { + $pointer++; + if (!array_key_exists($pointer, $tokens)) { + return null; + } + } while ($tokens[$pointer]['line'] === $line); + + return $pointer; + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findFirstNonWhitespaceOnLine(File $phpcsFile, int $pointer): int + { + if ($pointer === 0) { + return $pointer; + } + + $tokens = $phpcsFile->getTokens(); + + $line = $tokens[$pointer]['line']; + + do { + $pointer--; + } while ($pointer >= 0 && $tokens[$pointer]['line'] === $line); + + return self::findNextExcluding($phpcsFile, [T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], $pointer + 1); + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findFirstNonWhitespaceOnNextLine(File $phpcsFile, int $pointer): ?int + { + $newLinePointer = self::findNextContent($phpcsFile, [T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], $phpcsFile->eolChar, $pointer); + if ($newLinePointer === null) { + return null; + } + + $nextPointer = self::findNextExcluding($phpcsFile, [T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], $newLinePointer + 1); + + $tokens = $phpcsFile->getTokens(); + if ($nextPointer !== null && $tokens[$pointer]['line'] === $tokens[$nextPointer]['line'] - 1) { + return $nextPointer; + } + + return null; + } + + /** + * @param int $pointer Search starts at this token, inclusive + */ + public static function findFirstNonWhitespaceOnPreviousLine(File $phpcsFile, int $pointer): ?int + { + $newLinePointerOnPreviousLine = self::findPreviousContent( + $phpcsFile, + [T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], + $phpcsFile->eolChar, + $pointer + ); + if ($newLinePointerOnPreviousLine === null) { + return null; + } + + $newLinePointerBeforePreviousLine = self::findPreviousContent( + $phpcsFile, + [T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], + $phpcsFile->eolChar, + $newLinePointerOnPreviousLine - 1 + ); + if ($newLinePointerBeforePreviousLine === null) { + return null; + } + + $nextPointer = self::findNextExcluding($phpcsFile, [T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], $newLinePointerBeforePreviousLine + 1); + + $tokens = $phpcsFile->getTokens(); + if ($nextPointer !== null && $tokens[$pointer]['line'] === $tokens[$nextPointer]['line'] + 1) { + return $nextPointer; + } + + return null; + } + + public static function getContent(File $phpcsFile, int $startPointer, ?int $endPointer = null): string + { + $tokens = $phpcsFile->getTokens(); + $endPointer = $endPointer ?? self::getLastTokenPointer($phpcsFile); + + $content = ''; + for ($i = $startPointer; $i <= $endPointer; $i++) { + $content .= $tokens[$i]['content']; + } + + return $content; + } + + public static function getLastTokenPointer(File $phpcsFile): int + { + $tokenCount = count($phpcsFile->getTokens()); + if ($tokenCount === 0) { + throw new EmptyFileException($phpcsFile->getFilename()); + } + return $tokenCount - 1; + } + + /** + * @return array + */ + public static function getNameTokenCodes(): array + { + return [T_STRING, T_NS_SEPARATOR, T_NAME_FULLY_QUALIFIED, T_NAME_QUALIFIED, T_NAME_RELATIVE]; + } + + /** + * @return array + */ + public static function getOnlyNameTokenCodes(): array + { + return [T_STRING, T_NAME_FULLY_QUALIFIED, T_NAME_QUALIFIED, T_NAME_RELATIVE]; + } + + /** + * @return array + */ + public static function getOnlyTypeHintTokenCodes(): array + { + static $typeHintTokenCodes = null; + + if ($typeHintTokenCodes === null) { + $typeHintTokenCodes = array_merge( + self::getNameTokenCodes(), + [ + T_SELF, + T_PARENT, + T_ARRAY_HINT, + T_CALLABLE, + T_FALSE, + T_TRUE, + T_NULL, + ] + ); + } + + return $typeHintTokenCodes; + } + + /** + * @return array + */ + public static function getTypeHintTokenCodes(): array + { + static $typeHintTokenCodes = null; + + if ($typeHintTokenCodes === null) { + $typeHintTokenCodes = array_merge( + self::getOnlyTypeHintTokenCodes(), + [T_TYPE_UNION, T_TYPE_INTERSECTION] + ); + } + + return $typeHintTokenCodes; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenPointerOutOfBoundsException.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenPointerOutOfBoundsException.php new file mode 100644 index 000000000..32ff5368f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TokenPointerOutOfBoundsException.php @@ -0,0 +1,47 @@ +pointer = $pointer; + $this->lastTokenPointer = $lastTokenPointer; + } + + public function getPointer(): int + { + return $this->pointer; + } + + public function getLastTokenPointer(): int + { + return $this->lastTokenPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHelper.php new file mode 100644 index 000000000..8539c98d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHelper.php @@ -0,0 +1,35 @@ +typeHint = $typeHint; + $this->nullable = $nullable; + $this->startPointer = $startPointer; + $this->endPointer = $endPointer; + } + + public function getTypeHint(): string + { + return $this->typeHint; + } + + public function getTypeHintWithoutNullabilitySymbol(): string + { + return strpos($this->typeHint, '?') === 0 ? substr($this->typeHint, 1) : $this->typeHint; + } + + public function isNullable(): bool + { + return $this->nullable; + } + + public function getStartPointer(): int + { + return $this->startPointer; + } + + public function getEndPointer(): int + { + return $this->endPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHintHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHintHelper.php new file mode 100644 index 000000000..abde19b64 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/TypeHintHelper.php @@ -0,0 +1,417 @@ + 'int', + 'boolean' => 'bool', + ]; + return array_key_exists($typeHint, $longToShort) ? $longToShort[$typeHint] : $typeHint; + } + + public static function isUnofficialUnionTypeHint(string $typeHint): bool + { + return in_array($typeHint, ['scalar', 'numeric'], true); + } + + public static function isVoidTypeHint(string $typeHint): bool + { + return $typeHint === 'void'; + } + + public static function isNeverTypeHint(string $typeHint): bool + { + return in_array($typeHint, ['never', 'never-return', 'never-returns', 'no-return'], true); + } + + /** + * @return list + */ + public static function convertUnofficialUnionTypeHintToOfficialTypeHints(string $typeHint): array + { + $conversion = [ + 'scalar' => ['string', 'int', 'float', 'bool'], + 'numeric' => ['int', 'float'], + ]; + + return $conversion[$typeHint]; + } + + public static function isTypeDefinedInAnnotation(File $phpcsFile, int $pointer, string $typeHint): bool + { + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $pointer); + + if ($docCommentOpenPointer === null) { + return false; + } + + return self::isTemplate($phpcsFile, $docCommentOpenPointer, $typeHint) + || self::isAlias($phpcsFile, $docCommentOpenPointer, $typeHint); + } + + public static function getFullyQualifiedTypeHint(File $phpcsFile, int $pointer, string $typeHint): string + { + if (self::isSimpleTypeHint($typeHint)) { + return self::convertLongSimpleTypeHintToShort($typeHint); + } + + return NamespaceHelper::resolveClassName($phpcsFile, $typeHint, $pointer); + } + + /** + * @return list + */ + public static function getSimpleTypeHints(): array + { + static $simpleTypeHints; + + if ($simpleTypeHints === null) { + $simpleTypeHints = [ + 'int', + 'integer', + 'false', + 'float', + 'string', + 'bool', + 'boolean', + 'callable', + 'self', + 'array', + 'iterable', + 'void', + 'never', + ]; + } + + return $simpleTypeHints; + } + + /** + * @return list + */ + public static function getSimpleIterableTypeHints(): array + { + return [ + 'array', + 'iterable', + ]; + } + + public static function isSimpleUnofficialTypeHints(string $typeHint): bool + { + static $simpleUnofficialTypeHints; + + if ($simpleUnofficialTypeHints === null) { + $simpleUnofficialTypeHints = [ + 'null', + 'mixed', + 'scalar', + 'numeric', + 'true', + 'object', + 'resource', + 'static', + '$this', + 'class-string', + 'trait-string', + 'callable-string', + 'numeric-string', + 'non-empty-string', + 'non-falsy-string', + 'literal-string', + 'array-key', + 'list', + 'empty', + 'positive-int', + 'negative-int', + 'min', + 'max', + ]; + } + + return in_array($typeHint, $simpleUnofficialTypeHints, true); + } + + /** + * @param list $traversableTypeHints + */ + public static function isTraversableType(string $type, array $traversableTypeHints): bool + { + return self::isSimpleIterableTypeHint($type) || in_array($type, $traversableTypeHints, true); + } + + public static function typeHintEqualsAnnotation( + File $phpcsFile, + int $functionPointer, + string $typeHint, + string $typeHintInAnnotation + ): bool + { + /** @var list $typeHintParts */ + $typeHintParts = preg_split('~([&|])~', self::normalize($typeHint), -1, PREG_SPLIT_DELIM_CAPTURE); + /** @var list $typeHintInAnnotationParts */ + $typeHintInAnnotationParts = preg_split('~([&|])~', self::normalize($typeHintInAnnotation), -1, PREG_SPLIT_DELIM_CAPTURE); + + if (count($typeHintParts) !== count($typeHintInAnnotationParts)) { + return false; + } + + for ($i = 0; $i < count($typeHintParts); $i++) { + if ( + ( + $typeHintParts[$i] === '|' + || $typeHintParts[$i] === '&' + ) + && $typeHintParts[$i] !== $typeHintInAnnotationParts[$i] + ) { + return false; + } + + if (self::getFullyQualifiedTypeHint($phpcsFile, $functionPointer, $typeHintParts[$i]) !== self::getFullyQualifiedTypeHint( + $phpcsFile, + $functionPointer, + $typeHintInAnnotationParts[$i] + )) { + return false; + } + } + + return true; + } + + public static function getStartPointer(File $phpcsFile, int $endPointer): int + { + $previousPointer = TokenHelper::findPreviousExcluding( + $phpcsFile, + array_merge([T_WHITESPACE], TokenHelper::getTypeHintTokenCodes()), + $endPointer - 1 + ); + return TokenHelper::findNextNonWhitespace($phpcsFile, $previousPointer + 1); + } + + private static function isTemplate(File $phpcsFile, int $docCommentOpenPointer, string $typeHint): bool + { + static $templateAnnotationNames = null; + if ($templateAnnotationNames === null) { + foreach (['template', 'template-covariant'] as $annotationName) { + $templateAnnotationNames[] = sprintf('@%s', $annotationName); + foreach (AnnotationHelper::STATIC_ANALYSIS_PREFIXES as $prefixAnnotationName) { + $templateAnnotationNames[] = sprintf('@%s-%s', $prefixAnnotationName, $annotationName); + } + } + } + + $containsTypeHintInTemplateAnnotation = static function (int $docCommentOpenPointer) use ($phpcsFile, $templateAnnotationNames, $typeHint): bool { + foreach ($templateAnnotationNames as $templateAnnotationName) { + /** @var list> $annotations */ + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer, $templateAnnotationName); + + foreach ($annotations as $templateAnnotation) { + if ($templateAnnotation->isInvalid()) { + continue; + } + + if ($templateAnnotation->getValue()->name === $typeHint) { + return true; + } + } + } + + return false; + }; + + $tokens = $phpcsFile->getTokens(); + + $docCommentOwnerPointer = DocCommentHelper::findDocCommentOwnerPointer($phpcsFile, $docCommentOpenPointer); + if ($docCommentOwnerPointer !== null) { + if (in_array($tokens[$docCommentOwnerPointer]['code'], TokenHelper::$typeKeywordTokenCodes, true)) { + return $containsTypeHintInTemplateAnnotation($docCommentOpenPointer); + } + + if ($tokens[$docCommentOwnerPointer]['code'] === T_FUNCTION && $containsTypeHintInTemplateAnnotation($docCommentOpenPointer)) { + return true; + } + } + + $classPointer = ClassHelper::getClassPointer($phpcsFile, $docCommentOpenPointer); + + if ($classPointer === null) { + return false; + } + + $classDocCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $classPointer); + if ($classDocCommentOpenPointer === null) { + return false; + } + + return $containsTypeHintInTemplateAnnotation($classDocCommentOpenPointer); + } + + private static function isAlias(File $phpcsFile, int $docCommentOpenPointer, string $typeHint): bool + { + static $aliasAnnotationNames = null; + if ($aliasAnnotationNames === null) { + foreach (['type', 'import-type'] as $annotationName) { + foreach (AnnotationHelper::STATIC_ANALYSIS_PREFIXES as $prefixAnnotationName) { + $aliasAnnotationNames[] = sprintf('@%s-%s', $prefixAnnotationName, $annotationName); + } + } + } + + $classPointer = ClassHelper::getClassPointer($phpcsFile, $docCommentOpenPointer); + + if ($classPointer === null) { + return false; + } + + $classDocCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $classPointer); + if ($classDocCommentOpenPointer === null) { + return false; + } + + foreach ($aliasAnnotationNames as $aliasAnnotationName) { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $classDocCommentOpenPointer, $aliasAnnotationName); + + foreach ($annotations as $aliasAnnotation) { + $aliasAnnotationValue = $aliasAnnotation->getValue(); + + if ($aliasAnnotationValue instanceof TypeAliasTagValueNode && $aliasAnnotationValue->alias === $typeHint) { + return true; + } + + if (!($aliasAnnotationValue instanceof TypeAliasImportTagValueNode)) { + continue; + } + + if ($aliasAnnotationValue->importedAs === $typeHint) { + return true; + } + + if ($aliasAnnotationValue->importedAlias === $typeHint) { + return true; + } + } + } + + return false; + } + + private static function normalize(string $typeHint): string + { + if (StringHelper::startsWith($typeHint, '?')) { + $typeHint = substr($typeHint, 1) . '|null'; + } + + if (self::isNeverTypeHint($typeHint)) { + return 'never'; + } + + /** @var list $parts */ + $parts = preg_split('~([&|])~', $typeHint, -1, PREG_SPLIT_DELIM_CAPTURE); + + $hints = []; + $delimiter = '|'; + foreach ($parts as $part) { + if ($part === '|' || $part === '&') { + $delimiter = $part; + continue; + } + + $hints[] = $part; + } + + if (in_array('mixed', $hints, true)) { + return 'mixed'; + } + + $convertedHints = []; + foreach ($hints as $hint) { + if (self::isUnofficialUnionTypeHint($hint) && $delimiter !== '&') { + $convertedHints = array_merge($convertedHints, self::convertUnofficialUnionTypeHintToOfficialTypeHints($hint)); + } else { + $convertedHints[] = $hint; + } + } + + $convertedHints = array_unique($convertedHints); + + if (count($convertedHints) > 1) { + $convertedHints = array_map(static function (string $part): string { + return self::isVoidTypeHint($part) ? 'null' : $part; + }, $convertedHints); + } + + sort($convertedHints); + + return implode($delimiter, $convertedHints); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatement.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatement.php new file mode 100644 index 000000000..fb5eb5150 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatement.php @@ -0,0 +1,135 @@ +nameAsReferencedInFile = $nameAsReferencedInFile; + $this->normalizedNameAsReferencedInFile = self::normalizedNameAsReferencedInFile($type, $nameAsReferencedInFile); + $this->fullyQualifiedTypeName = $fullyQualifiedClassName; + $this->usePointer = $usePointer; + $this->type = $type; + $this->alias = $alias; + } + + public function getNameAsReferencedInFile(): string + { + return $this->nameAsReferencedInFile; + } + + public function getCanonicalNameAsReferencedInFile(): string + { + return $this->normalizedNameAsReferencedInFile; + } + + public function getFullyQualifiedTypeName(): string + { + return $this->fullyQualifiedTypeName; + } + + public function getPointer(): int + { + return $this->usePointer; + } + + public function getType(): string + { + return $this->type; + } + + public function getAlias(): ?string + { + return $this->alias; + } + + public function isClass(): bool + { + return $this->type === self::TYPE_CLASS; + } + + public function isConstant(): bool + { + return $this->type === self::TYPE_CONSTANT; + } + + public function isFunction(): bool + { + return $this->type === self::TYPE_FUNCTION; + } + + public function hasSameType(self $that): bool + { + return $this->type === $that->type; + } + + public static function getUniqueId(string $type, string $name): string + { + $normalizedName = self::normalizedNameAsReferencedInFile($type, $name); + + if ($type === self::TYPE_CLASS) { + return $normalizedName; + } + + return sprintf('%s %s', $type, $normalizedName); + } + + public static function normalizedNameAsReferencedInFile(string $type, string $name): string + { + if ($type === self::TYPE_CONSTANT) { + return $name; + } + + return strtolower($name); + } + + public static function getTypeName(string $type): ?string + { + if ($type === self::TYPE_CONSTANT) { + return 'const'; + } + + if ($type === self::TYPE_FUNCTION) { + return 'function'; + } + + return null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatementHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatementHelper.php new file mode 100644 index 000000000..9ef25bcd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/UseStatementHelper.php @@ -0,0 +1,270 @@ +getTokens(); + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + + // Anonymous function use + if ($tokens[$nextPointer]['code'] === T_OPEN_PARENTHESIS) { + return false; + } + + if ( + $tokens[$nextPointer]['code'] === T_STRING + && in_array(strtolower($tokens[$nextPointer]['content']), ['function', 'const'], true) + ) { + return true; + } + + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_OPEN_TAG, T_DECLARE, T_NAMESPACE, T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET], + $usePointer + ); + + if (in_array($tokens[$previousPointer]['code'], [T_OPEN_TAG, T_DECLARE, T_NAMESPACE], true)) { + return true; + } + + if (array_key_exists('scope_condition', $tokens[$previousPointer])) { + $scopeConditionPointer = $tokens[$previousPointer]['scope_condition']; + + if ( + $tokens[$previousPointer]['code'] === T_OPEN_CURLY_BRACKET + && in_array($tokens[$scopeConditionPointer]['code'], TokenHelper::$typeWithAnonymousClassKeywordTokenCodes, true) + ) { + return false; + } + + // Trait use after another trait use + if ($tokens[$scopeConditionPointer]['code'] === T_USE) { + return false; + } + + // Trait use after method or import use after function + if ($tokens[$scopeConditionPointer]['code'] === T_FUNCTION) { + return ClassHelper::getClassPointer($phpcsFile, $usePointer) === null; + } + } + + return true; + } + + public static function isTraitUse(File $phpcsFile, int $usePointer): bool + { + $tokens = $phpcsFile->getTokens(); + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + + // Anonymous function use + if ($tokens[$nextPointer]['code'] === T_OPEN_PARENTHESIS) { + return false; + } + + return !self::isImportUse($phpcsFile, $usePointer); + } + + public static function getAlias(File $phpcsFile, int $usePointer): ?string + { + $endPointer = TokenHelper::findNext($phpcsFile, [T_SEMICOLON, T_COMMA], $usePointer + 1); + $asPointer = TokenHelper::findNext($phpcsFile, T_AS, $usePointer + 1, $endPointer); + + if ($asPointer === null) { + return null; + } + + $tokens = $phpcsFile->getTokens(); + return $tokens[TokenHelper::findNext($phpcsFile, T_STRING, $asPointer + 1)]['content']; + } + + public static function getNameAsReferencedInClassFromUse(File $phpcsFile, int $usePointer): string + { + $alias = self::getAlias($phpcsFile, $usePointer); + if ($alias !== null) { + return $alias; + } + + $name = self::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer); + return NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($name); + } + + public static function getFullyQualifiedTypeNameFromUse(File $phpcsFile, int $usePointer): string + { + $tokens = $phpcsFile->getTokens(); + + $nameEndPointer = TokenHelper::findNext($phpcsFile, [T_SEMICOLON, T_AS, T_COMMA], $usePointer + 1) - 1; + if (in_array($tokens[$nameEndPointer]['code'], TokenHelper::$ineffectiveTokenCodes, true)) { + $nameEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $nameEndPointer); + } + $nameStartPointer = TokenHelper::findPreviousExcluding($phpcsFile, TokenHelper::getNameTokenCodes(), $nameEndPointer - 1) + 1; + + $name = TokenHelper::getContent($phpcsFile, $nameStartPointer, $nameEndPointer); + + return NamespaceHelper::normalizeToCanonicalName($name); + } + + /** + * @return array + */ + public static function getUseStatementsForPointer(File $phpcsFile, int $pointer): array + { + $allUseStatements = self::getFileUseStatements($phpcsFile); + + if (count($allUseStatements) === 1) { + return current($allUseStatements); + } + + foreach (array_reverse($allUseStatements, true) as $pointerBeforeUseStatements => $useStatements) { + if ($pointerBeforeUseStatements < $pointer) { + return $useStatements; + } + } + + return []; + } + + /** + * @return array> + */ + public static function getFileUseStatements(File $phpcsFile): array + { + $lazyValue = static function () use ($phpcsFile): array { + $useStatements = []; + $tokens = $phpcsFile->getTokens(); + + $namespaceAndOpenTagPointers = TokenHelper::findNextAll($phpcsFile, [T_OPEN_TAG, T_NAMESPACE], 0); + $openTagPointer = $namespaceAndOpenTagPointers[0]; + + foreach (self::getUseStatementPointers($phpcsFile, $openTagPointer) as $usePointer) { + $pointerBeforeUseStatements = $openTagPointer; + if (count($namespaceAndOpenTagPointers) > 1) { + foreach (array_reverse($namespaceAndOpenTagPointers) as $namespaceAndOpenTagPointer) { + if ($namespaceAndOpenTagPointer < $usePointer) { + $pointerBeforeUseStatements = $namespaceAndOpenTagPointer; + break; + } + } + } + + $nextTokenFromUsePointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + $type = UseStatement::TYPE_CLASS; + if ($tokens[$nextTokenFromUsePointer]['code'] === T_STRING) { + if ($tokens[$nextTokenFromUsePointer]['content'] === 'const') { + $type = UseStatement::TYPE_CONSTANT; + } elseif ($tokens[$nextTokenFromUsePointer]['content'] === 'function') { + $type = UseStatement::TYPE_FUNCTION; + } + } + $name = self::getNameAsReferencedInClassFromUse($phpcsFile, $usePointer); + $useStatement = new UseStatement( + $name, + self::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer), + $usePointer, + $type, + self::getAlias($phpcsFile, $usePointer) + ); + $useStatements[$pointerBeforeUseStatements][UseStatement::getUniqueId($type, $name)] = $useStatement; + } + + return $useStatements; + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'useStatements', $lazyValue); + } + + public static function getUseStatementPointer(File $phpcsFile, int $pointer): ?int + { + $pointers = self::getUseStatementPointers($phpcsFile, 0); + + foreach (array_reverse($pointers) as $pointerBeforeUseStatements) { + if ($pointerBeforeUseStatements < $pointer) { + return $pointerBeforeUseStatements; + } + } + + return null; + } + + /** + * Searches for all use statements in a file, skips bodies of classes and traits. + * + * @return list + */ + private static function getUseStatementPointers(File $phpcsFile, int $openTagPointer): array + { + $lazy = static function () use ($phpcsFile, $openTagPointer): array { + $tokens = $phpcsFile->getTokens(); + $pointer = $openTagPointer + 1; + $pointers = []; + while (true) { + $typesToFind = array_merge([T_USE], TokenHelper::$typeKeywordTokenCodes); + $pointer = TokenHelper::findNext($phpcsFile, $typesToFind, $pointer); + if ($pointer === null) { + break; + } + + $token = $tokens[$pointer]; + if (in_array($token['code'], TokenHelper::$typeKeywordTokenCodes, true)) { + $pointer = $token['scope_closer'] + 1; + continue; + } + + if (self::isGroupUse($phpcsFile, $pointer)) { + $pointer++; + continue; + } + + if (!self::isImportUse($phpcsFile, $pointer)) { + $pointer++; + continue; + } + + $pointers[] = $pointer; + $pointer++; + } + + return $pointers; + }; + + return SniffLocalCache::getAndSetIfNotCached($phpcsFile, 'useStatementPointers', $lazy); + } + + private static function isGroupUse(File $phpcsFile, int $usePointer): bool + { + $tokens = $phpcsFile->getTokens(); + $semicolonOrGroupUsePointer = TokenHelper::findNext($phpcsFile, [T_SEMICOLON, T_OPEN_USE_GROUP], $usePointer + 1); + + return $tokens[$semicolonOrGroupUsePointer]['code'] === T_OPEN_USE_GROUP; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/VariableHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/VariableHelper.php new file mode 100644 index 000000000..676b0ab7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/VariableHelper.php @@ -0,0 +1,178 @@ +getTokens(); + + if ($tokens[$variablePointer]['content'] !== $tokens[$variableToCheckPointer]['content']) { + return false; + } + + if ($tokens[$variableToCheckPointer - 1]['code'] === T_DOUBLE_COLON) { + $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $variableToCheckPointer + 1); + return $tokens[$pointerAfterVariable]['code'] === T_OPEN_PARENTHESIS; + } + + return !ParameterHelper::isParameter($phpcsFile, $variableToCheckPointer); + } + + public static function isUsedInCompactFunction(File $phpcsFile, int $variablePointer, int $stringPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $stringContent = $tokens[$stringPointer]['content']; + if (strtolower($stringContent) !== 'compact') { + return false; + } + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + if ($tokens[$parenthesisOpenerPointer]['code'] !== T_OPEN_PARENTHESIS) { + return false; + } + + $variableNameWithoutDollar = substr($tokens[$variablePointer]['content'], 1); + for ($i = $parenthesisOpenerPointer + 1; $i < $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; $i++) { + if (preg_match('~^([\'"])' . $variableNameWithoutDollar . '\\1$~', $tokens[$i]['content']) !== 0) { + return true; + } + } + + return false; + } + + public static function isUsedInScopeInString(File $phpcsFile, string $variableName, int $stringPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $stringContent = $tokens[$stringPointer]['content']; + + if (preg_match('~(\\\\)?(' . preg_quote($variableName, '~') . ')\b~', $stringContent, $matches) !== 0) { + if ($matches[1] === '') { + return true; + } + + if (strlen($matches[1]) % 2 === 1) { + return true; + } + } + + $variableNameWithoutDollar = substr($variableName, 1); + return preg_match('~\$\{' . preg_quote($variableNameWithoutDollar, '~') . '(<=\}|\b)~', $stringContent) !== 0; + } + + private static function isUsedInScopeInternal( + File $phpcsFile, + int $scopeOwnerPointer, + int $variablePointer, + ?int $startCheckPointer + ): bool + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG) { + $scopeCloserPointer = count($tokens) - 1; + } elseif ($tokens[$scopeOwnerPointer]['code'] === T_FN) { + $scopeCloserPointer = $tokens[$scopeOwnerPointer]['scope_closer']; + } else { + $scopeCloserPointer = $tokens[$scopeOwnerPointer]['scope_closer'] - 1; + } + + if ($tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG) { + $firstPointerInScope = $scopeOwnerPointer + 1; + } elseif ($tokens[$scopeOwnerPointer]['code'] === T_FN) { + $firstPointerInScope = $tokens[$scopeOwnerPointer]['scope_opener']; + } else { + $firstPointerInScope = $tokens[$scopeOwnerPointer]['scope_opener'] + 1; + } + + if ($startCheckPointer === null) { + $startCheckPointer = $firstPointerInScope; + } + + for ($i = $startCheckPointer; $i <= $scopeCloserPointer; $i++) { + if (!ScopeHelper::isInSameScope($phpcsFile, $i, $firstPointerInScope)) { + continue; + } + + if ( + $tokens[$i]['code'] === T_VARIABLE + && self::isUsedAsVariable($phpcsFile, $variablePointer, $i) + ) { + return true; + } + + if ($tokens[$i]['code'] === T_STRING) { + if (self::isGetDefinedVarsCall($phpcsFile, $i)) { + return true; + } + + if (self::isUsedInCompactFunction($phpcsFile, $variablePointer, $i)) { + return true; + } + } + + if ( + in_array($tokens[$i]['code'], [T_DOUBLE_QUOTED_STRING, T_HEREDOC], true) + && self::isUsedInScopeInString($phpcsFile, $tokens[$variablePointer]['content'], $i) + ) { + return true; + } + } + + return false; + } + + private static function isGetDefinedVarsCall(File $phpcsFile, int $stringPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $stringContent = $tokens[$stringPointer]['content']; + if (strtolower($stringContent) !== 'get_defined_vars') { + return false; + } + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + return $tokens[$parenthesisOpenerPointer]['code'] === T_OPEN_PARENTHESIS; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/YodaHelper.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/YodaHelper.php new file mode 100644 index 000000000..9b0c3ad97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/YodaHelper.php @@ -0,0 +1,358 @@ +|int|string>> $leftSideTokens + * @param array|int|string>> $rightSideTokens + */ + public static function fix(File $phpcsFile, array $leftSideTokens, array $rightSideTokens): void + { + $phpcsFile->fixer->beginChangeset(); + self::replace($phpcsFile, $leftSideTokens, $rightSideTokens); + self::replace($phpcsFile, $rightSideTokens, $leftSideTokens); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param array|int|string>> $tokens + * @return array|int|string>> + */ + public static function getLeftSideTokens(array $tokens, int $comparisonTokenPointer): array + { + $parenthesisDepth = 0; + $shortArrayDepth = 0; + $examinedTokenPointer = $comparisonTokenPointer; + $sideTokens = []; + $stopTokenCodes = self::getStopTokenCodes(); + while (true) { + $examinedTokenPointer--; + $examinedToken = $tokens[$examinedTokenPointer]; + /** @var string|int $examinedTokenCode */ + $examinedTokenCode = $examinedToken['code']; + if ($parenthesisDepth === 0 && $shortArrayDepth === 0 && isset($stopTokenCodes[$examinedTokenCode])) { + break; + } + + if ($examinedTokenCode === T_CLOSE_SHORT_ARRAY) { + $shortArrayDepth++; + } elseif ($examinedTokenCode === T_OPEN_SHORT_ARRAY) { + if ($shortArrayDepth === 0) { + break; + } + + $shortArrayDepth--; + } + + if ($examinedTokenCode === T_CLOSE_PARENTHESIS) { + $parenthesisDepth++; + } elseif ($examinedTokenCode === T_OPEN_PARENTHESIS) { + if ($parenthesisDepth === 0) { + break; + } + + $parenthesisDepth--; + } + + $sideTokens[$examinedTokenPointer] = $examinedToken; + } + + return self::trimWhitespaceTokens(array_reverse($sideTokens, true)); + } + + /** + * @param array|int|string>> $tokens + * @return array|int|string>> + */ + public static function getRightSideTokens(array $tokens, int $comparisonTokenPointer): array + { + $parenthesisDepth = 0; + $shortArrayDepth = 0; + $examinedTokenPointer = $comparisonTokenPointer; + $sideTokens = []; + $stopTokenCodes = self::getStopTokenCodes(); + while (true) { + $examinedTokenPointer++; + $examinedToken = $tokens[$examinedTokenPointer]; + /** @var string|int $examinedTokenCode */ + $examinedTokenCode = $examinedToken['code']; + if ($parenthesisDepth === 0 && $shortArrayDepth === 0 && isset($stopTokenCodes[$examinedTokenCode])) { + break; + } + + if ($examinedTokenCode === T_OPEN_SHORT_ARRAY) { + $shortArrayDepth++; + } elseif ($examinedTokenCode === T_CLOSE_SHORT_ARRAY) { + if ($shortArrayDepth === 0) { + break; + } + + $shortArrayDepth--; + } + + if ($examinedTokenCode === T_OPEN_PARENTHESIS) { + $parenthesisDepth++; + } elseif ($examinedTokenCode === T_CLOSE_PARENTHESIS) { + if ($parenthesisDepth === 0) { + break; + } + + $parenthesisDepth--; + } + + $sideTokens[$examinedTokenPointer] = $examinedToken; + } + + return self::trimWhitespaceTokens($sideTokens); + } + + /** + * @param array|int|string>> $tokens + * @param array|int|string>> $sideTokens + */ + public static function getDynamismForTokens(array $tokens, array $sideTokens): ?int + { + $sideTokens = array_values(array_filter($sideTokens, static function (array $token): bool { + return !in_array( + $token['code'], + [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, T_NS_SEPARATOR, T_PLUS, T_MINUS, T_INT_CAST, T_DOUBLE_CAST, T_STRING_CAST, T_ARRAY_CAST, T_OBJECT_CAST, T_BOOL_CAST, T_UNSET_CAST], + true + ); + })); + + $sideTokensCount = count($sideTokens); + + $dynamism = self::getTokenDynamism(); + + if ($sideTokensCount > 0) { + if ($sideTokens[0]['code'] === T_VARIABLE) { + // Expression starts with a variable - wins over everything else + return self::DYNAMISM_VARIABLE; + } + + if ($sideTokens[$sideTokensCount - 1]['code'] === T_CLOSE_PARENTHESIS) { + if (array_key_exists('parenthesis_owner', $sideTokens[$sideTokensCount - 1])) { + /** @var int $parenthesisOwner */ + $parenthesisOwner = $sideTokens[$sideTokensCount - 1]['parenthesis_owner']; + if ($tokens[$parenthesisOwner]['code'] === T_ARRAY) { + // Array + return $dynamism[T_ARRAY]; + } + } + + // Function or method call + return self::DYNAMISM_FUNCTION_CALL; + } + + if ($sideTokensCount === 1 && $sideTokens[0]['code'] === T_STRING) { + // Constant + return self::DYNAMISM_CONSTANT; + } + } + + if ($sideTokensCount > 2 && $sideTokens[$sideTokensCount - 2]['code'] === T_DOUBLE_COLON) { + if ($sideTokens[$sideTokensCount - 1]['code'] === T_VARIABLE) { + // Static property access + return self::DYNAMISM_VARIABLE; + } + + if ($sideTokens[$sideTokensCount - 1]['code'] === T_STRING) { + // Class constant + return self::DYNAMISM_CONSTANT; + } + } + + if (array_key_exists(0, $sideTokens)) { + /** @var int $sideTokenCode */ + $sideTokenCode = $sideTokens[0]['code']; + if (array_key_exists($sideTokenCode, $dynamism)) { + return $dynamism[$sideTokenCode]; + } + } + + return null; + } + + /** + * @param array|int|string>> $tokens + * @return array|int|string>> + */ + public static function trimWhitespaceTokens(array $tokens): array + { + foreach ($tokens as $pointer => $token) { + if ($token['code'] !== T_WHITESPACE) { + break; + } + + unset($tokens[$pointer]); + } + + foreach (array_reverse($tokens, true) as $pointer => $token) { + if ($token['code'] !== T_WHITESPACE) { + break; + } + + unset($tokens[$pointer]); + } + + return $tokens; + } + + /** + * @param array|int|string>> $oldTokens + * @param array|int|string>> $newTokens + */ + private static function replace(File $phpcsFile, array $oldTokens, array $newTokens): void + { + reset($oldTokens); + /** @var int $firstOldPointer */ + $firstOldPointer = key($oldTokens); + end($oldTokens); + /** @var int $lastOldPointer */ + $lastOldPointer = key($oldTokens); + + $content = implode('', array_map(static function (array $token): string { + /** @var string $content */ + $content = $token['content']; + return $content; + }, $newTokens)); + + FixerHelper::change($phpcsFile, $firstOldPointer, $lastOldPointer, $content); + } + + /** + * @return array + */ + private static function getTokenDynamism(): array + { + static $tokenDynamism; + + if ($tokenDynamism === null) { + $tokenDynamism = [ + T_TRUE => 0, + T_FALSE => 0, + T_NULL => 0, + T_DNUMBER => 0, + T_LNUMBER => 0, + T_OPEN_SHORT_ARRAY => 0, + // Do not stack error messages when the old-style array syntax is used + T_ARRAY => 0, + T_CONSTANT_ENCAPSED_STRING => 0, + T_VARIABLE => self::DYNAMISM_VARIABLE, + T_STRING => self::DYNAMISM_FUNCTION_CALL, + ]; + + $tokenDynamism += array_fill_keys(array_keys(Tokens::$castTokens), 3); + } + + return $tokenDynamism; + } + + /** + * @return array + */ + private static function getStopTokenCodes(): array + { + static $stopTokenCodes; + + if ($stopTokenCodes === null) { + $stopTokenCodes = [ + T_BOOLEAN_AND => true, + T_BOOLEAN_OR => true, + T_SEMICOLON => true, + T_OPEN_TAG => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + T_LOGICAL_AND => true, + T_LOGICAL_OR => true, + T_LOGICAL_XOR => true, + T_COALESCE => true, + T_CASE => true, + T_COLON => true, + T_RETURN => true, + T_COMMA => true, + T_CLOSE_CURLY_BRACKET => true, + T_MATCH_ARROW => true, + T_FN_ARROW => true, + ]; + + $stopTokenCodes += array_fill_keys(array_keys(Tokens::$assignmentTokens), true); + $stopTokenCodes += array_fill_keys(array_keys(Tokens::$commentTokens), true); + } + + return $stopTokenCodes; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/AlphabeticallySortedByKeysSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/AlphabeticallySortedByKeysSniff.php new file mode 100644 index 000000000..27f47b01a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/AlphabeticallySortedByKeysSniff.php @@ -0,0 +1,85 @@ + + */ + public function register(): array + { + return TokenHelper::$arrayTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): void + { + if (ArrayHelper::isMultiLine($phpcsFile, $stackPointer) === false) { + return; + } + + // "Parse" the array... get info for each key/value pair + $keyValues = ArrayHelper::parse($phpcsFile, $stackPointer); + + if (ArrayHelper::isKeyedAll($keyValues) === false) { + return; + } + + if (ArrayHelper::isSortedByKey($keyValues)) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Keyed multi-line arrays must be sorted alphabetically.', + $stackPointer, + self::CODE_INCORRECT_KEY_ORDER + ); + if ($fix) { + $this->fix($phpcsFile, $keyValues); + } + } + + /** + * @param list $keyValues + */ + private function fix(File $phpcsFile, array $keyValues): void + { + $pointerStart = $keyValues[0]->getPointerStart(); + $pointerEnd = $keyValues[count($keyValues) - 1]->getPointerEnd(); + + // determine indent to use + $indent = ArrayHelper::getIndentation($keyValues); + + usort($keyValues, static function ($a1, $a2) { + return strnatcasecmp((string) $a1->getKey(), (string) $a2->getKey()); + }); + + $content = implode('', array_map(static function (ArrayKeyValue $keyValue) use ($phpcsFile, $indent) { + return $keyValue->getContent($phpcsFile, true, $indent) . $phpcsFile->eolChar; + }, $keyValues)); + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::change($phpcsFile, $pointerStart, $pointerEnd, $content); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/ArrayAccessSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/ArrayAccessSniff.php new file mode 100644 index 000000000..e5d9ffaaa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/ArrayAccessSniff.php @@ -0,0 +1,76 @@ + + */ + public function register(): array + { + return [T_OPEN_SQUARE_BRACKET]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousToken = TokenHelper::findPreviousNonWhitespace($phpcsFile, $stackPointer - 1); + + if ( + $previousToken === null + || $previousToken === $stackPointer - 1) { + return; + } + + if ($tokens[$previousToken]['code'] === T_VARIABLE) { + $this->addError( + $phpcsFile, + $stackPointer, + 'There should be no space between array variable and array access operator.', + self::CODE_NO_SPACE_BEFORE_BRACKETS + ); + } + + if ($tokens[$previousToken]['code'] !== T_CLOSE_SQUARE_BRACKET) { + return; + } + + $this->addError( + $phpcsFile, + $stackPointer, + 'There should be no space between array access operators.', + self::CODE_NO_SPACE_BETWEEN_BRACKETS + ); + } + + private function addError(File $phpcsFile, int $stackPointer, string $error, string $code): void + { + $fix = $phpcsFile->addFixableError($error, $stackPointer, $code); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPointer - 1, ''); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowImplicitArrayCreationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowImplicitArrayCreationSniff.php new file mode 100644 index 000000000..59997e616 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowImplicitArrayCreationSniff.php @@ -0,0 +1,280 @@ + + */ + public function register(): array + { + return [ + T_OPEN_SQUARE_BRACKET, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $bracketOpenerPointer + */ + public function process(File $phpcsFile, $bracketOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$bracketOpenerPointer]['bracket_closer'] + 1); + if ($tokens[$assignmentPointer]['code'] !== T_EQUAL) { + return; + } + + /** @var int $variablePointer */ + $variablePointer = TokenHelper::findPreviousEffective($phpcsFile, $bracketOpenerPointer - 1); + if ($tokens[$variablePointer]['code'] !== T_VARIABLE) { + return; + } + + if (in_array($tokens[$variablePointer]['content'], [ + '$GLOBALS', + '$_SERVER', + '$_REQUEST', + '$_POST', + '$_GET', + '$_FILES', + '$_ENV', + '$_COOKIE', + '$_SESSION', + '$this', + ], true)) { + return; + } + + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + if (in_array($tokens[$pointerBeforeVariable]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + return; + } + + $scopeOwnerPointer = null; + foreach (array_reverse($tokens[$variablePointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (!in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) { + continue; + } + + $scopeOwnerPointer = $conditionPointer; + break; + } + + if ($scopeOwnerPointer === null) { + $scopeOwnerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $variablePointer - 1); + } + + $scopeOpenerPointer = $tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG + ? $scopeOwnerPointer + : $tokens[$scopeOwnerPointer]['scope_opener']; + $scopeCloserPointer = $tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG + ? count($tokens) - 1 + : $tokens[$scopeOwnerPointer]['scope_closer']; + + if (in_array($tokens[$scopeOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + if ($this->isParameter($phpcsFile, $scopeOwnerPointer, $variablePointer)) { + return; + } + + if ( + $tokens[$scopeOwnerPointer]['code'] === T_CLOSURE + && $this->isInheritedVariable($phpcsFile, $scopeOwnerPointer, $variablePointer) + ) { + return; + } + } + + if ($this->hasExplicitCreation($phpcsFile, $scopeOpenerPointer, $scopeCloserPointer, $variablePointer)) { + return; + } + + $phpcsFile->addError('Implicit array creation is disallowed.', $variablePointer, self::CODE_IMPLICIT_ARRAY_CREATION_USED); + } + + private function isParameter(File $phpcsFile, int $functionPointer, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + $variableName = $tokens[$variablePointer]['content']; + + $parameterPointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $tokens[$functionPointer]['parenthesis_opener'] + 1, + $tokens[$functionPointer]['parenthesis_closer'] + ); + return $parameterPointer !== null; + } + + private function isInheritedVariable(File $phpcsFile, int $closurePointer, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + $variableName = $tokens[$variablePointer]['content']; + + $usePointer = TokenHelper::findNext( + $phpcsFile, + T_USE, + $tokens[$closurePointer]['parenthesis_closer'] + 1, + $tokens[$closurePointer]['scope_opener'] + ); + if ($usePointer === null) { + return false; + } + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + + $inheritedVariablePointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $parenthesisOpenerPointer + 1, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + ); + return $inheritedVariablePointer !== null; + } + + private function hasExplicitCreation(File $phpcsFile, int $scopeOpenerPointer, int $scopeCloserPointer, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $variableName = $tokens[$variablePointer]['content']; + + for ($i = $scopeOpenerPointer + 1; $i < $variablePointer; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $variablePointer, $i)) { + continue; + } + + $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if ($tokens[$assignmentPointer]['code'] === T_EQUAL) { + return true; + } + + $staticPointer = TokenHelper::findPreviousEffective($phpcsFile, $i - 1); + if ($tokens[$staticPointer]['code'] === T_STATIC) { + return true; + } + + if ($this->isCreatedInForeach($phpcsFile, $i, $scopeCloserPointer)) { + return true; + } + + if ($this->isCreatedInList($phpcsFile, $i, $scopeOpenerPointer)) { + return true; + } + + if ($this->isCreatedByReferencedParameterInFunctionCall($phpcsFile, $i, $scopeOpenerPointer)) { + return true; + } + + if ($this->isImportedUsingGlobalStatement($phpcsFile, $i)) { + return true; + } + } + + return false; + } + + private function isCreatedInList(File $phpcsFile, int $variablePointer, int $scopeOpenerPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY, T_OPEN_SQUARE_BRACKET], + $variablePointer - 1, + $scopeOpenerPointer + ); + if ($parenthesisOpenerPointer === null) { + return false; + } + + if ($tokens[$parenthesisOpenerPointer]['code'] === T_OPEN_PARENTHESIS) { + if ($tokens[$parenthesisOpenerPointer]['parenthesis_closer'] < $variablePointer) { + return false; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + return $tokens[$pointerBeforeParenthesisOpener]['code'] === T_LIST; + } + + return $tokens[$parenthesisOpenerPointer]['bracket_closer'] > $variablePointer; + } + + private function isCreatedInForeach(File $phpcsFile, int $variablePointer, int $scopeCloserPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisCloserPointer = TokenHelper::findNext($phpcsFile, T_CLOSE_PARENTHESIS, $variablePointer + 1, $scopeCloserPointer); + return $parenthesisCloserPointer !== null + && array_key_exists('parenthesis_owner', $tokens[$parenthesisCloserPointer]) + && $tokens[$tokens[$parenthesisCloserPointer]['parenthesis_owner']]['code'] === T_FOREACH + && $tokens[$parenthesisCloserPointer]['parenthesis_opener'] < $variablePointer; + } + + private function isCreatedByReferencedParameterInFunctionCall(File $phpcsFile, int $variablePointer, int $scopeOpenerPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_PARENTHESIS, $variablePointer - 1, $scopeOpenerPointer); + + if ( + $parenthesisOpenerPointer === null + || $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] < $variablePointer + ) { + return false; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + return $tokens[$pointerBeforeParenthesisOpener]['code'] === T_STRING; + } + + private function isImportedUsingGlobalStatement(File $phpcsFile, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $startOfStatement = $phpcsFile->findStartOfStatement($variablePointer, T_COMMA); + + return $tokens[$startOfStatement]['code'] === T_GLOBAL; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowPartiallyKeyedSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowPartiallyKeyedSniff.php new file mode 100644 index 000000000..28af0d876 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/DisallowPartiallyKeyedSniff.php @@ -0,0 +1,42 @@ + + */ + public function register(): array + { + return TokenHelper::$arrayTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): void + { + $keyValues = ArrayHelper::parse($phpcsFile, $stackPointer); + + if (!ArrayHelper::isKeyed($keyValues)) { + return; + } + + if (ArrayHelper::isKeyedAll($keyValues)) { + return; + } + + $phpcsFile->addError('Partially keyed array disallowed.', $stackPointer, self::CODE_DISALLOWED_PARTIALLY_KEYED); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/MultiLineArrayEndBracketPlacementSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/MultiLineArrayEndBracketPlacementSniff.php new file mode 100644 index 000000000..46980e91a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/MultiLineArrayEndBracketPlacementSniff.php @@ -0,0 +1,60 @@ + + */ + public function register(): array + { + return TokenHelper::$arrayTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (ArrayHelper::isMultiLine($phpcsFile, $stackPointer) === false) { + return; + } + + [$arrayOpenerPointer, $arrayCloserPointer] = ArrayHelper::openClosePointers($tokens[$stackPointer]); + + $nextEffective = TokenHelper::findNextEffective($phpcsFile, $arrayOpenerPointer + 1, $arrayCloserPointer); + if ($nextEffective === null || in_array($tokens[$nextEffective]['code'], TokenHelper::$arrayTokenCodes, true) === false) { + return; + } + + [$nextPointerOpener, $nextPointerCloser] = ArrayHelper::openClosePointers($tokens[$nextEffective]); + + $arraysStartAtSameLine = $tokens[$arrayOpenerPointer]['line'] === $tokens[$nextPointerOpener]['line']; + $arraysEndAtSameLine = $tokens[$arrayCloserPointer]['line'] === $tokens[$nextPointerCloser]['line']; + if (!$arraysStartAtSameLine || $arraysEndAtSameLine) { + return; + } + + $error = "Expected nested array to end at the same line as it's parent. Either put the nested array's end at the same line as the parent's end, or put the nested array start on it's own line."; + $fix = $phpcsFile->addFixableError($error, $arrayOpenerPointer, self::CODE_ARRAY_END_WRONG_PLACEMENT); + if (!$fix) { + return; + } + + $phpcsFile->fixer->addContent($arrayOpenerPointer, $phpcsFile->eolChar); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/SingleLineArrayWhitespaceSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/SingleLineArrayWhitespaceSniff.php new file mode 100644 index 000000000..98ce9ea62 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/SingleLineArrayWhitespaceSniff.php @@ -0,0 +1,228 @@ + + */ + public function register(): array + { + return TokenHelper::$arrayTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): int + { + $this->spacesAroundBrackets = SniffSettingsHelper::normalizeInteger($this->spacesAroundBrackets); + + $tokens = $phpcsFile->getTokens(); + + [$arrayOpenerPointer, $arrayCloserPointer] = ArrayHelper::openClosePointers($tokens[$stackPointer]); + + // Check only single-line arrays. + if ($tokens[$arrayOpenerPointer]['line'] !== $tokens[$arrayCloserPointer]['line']) { + return $arrayCloserPointer; + } + + $pointerContent = TokenHelper::findNextNonWhitespace($phpcsFile, $arrayOpenerPointer + 1, $arrayCloserPointer + 1); + if ($pointerContent === $arrayCloserPointer) { + // Empty array, but if the brackets aren't together, there's a problem. + if ($this->enableEmptyArrayCheck) { + $this->checkWhitespaceInEmptyArray($phpcsFile, $arrayOpenerPointer, $arrayCloserPointer); + } + + // We can return here because there is nothing else to check. + // All code below can assume that the array is not empty. + return $arrayCloserPointer + 1; + } + + $this->checkWhitespaceAfterOpeningBracket($phpcsFile, $arrayOpenerPointer); + $this->checkWhitespaceBeforeClosingBracket($phpcsFile, $arrayCloserPointer); + + for ($i = $arrayOpenerPointer + 1; $i < $arrayCloserPointer; $i++) { + // Skip bracketed statements, like function calls. + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_closer']; + + continue; + } + + // Skip nested arrays as they will be processed separately + if (in_array($tokens[$i]['code'], TokenHelper::$arrayTokenCodes, true)) { + $i = ArrayHelper::openClosePointers($tokens[$i])[1]; + + continue; + } + + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + // Before checking this comma, make sure we are not at the end of the array. + $next = TokenHelper::findNextNonWhitespace($phpcsFile, $i + 1, $arrayCloserPointer); + if ($next === null) { + return $arrayOpenerPointer + 1; + } + + $this->checkWhitespaceBeforeComma($phpcsFile, $i); + $this->checkWhitespaceAfterComma($phpcsFile, $i); + } + + return $arrayOpenerPointer + 1; + } + + private function checkWhitespaceInEmptyArray(File $phpcsFile, int $arrayStart, int $arrayEnd): void + { + if ($arrayEnd - $arrayStart === 1) { + return; + } + + $error = 'Empty array declaration must have no space between the parentheses.'; + $fix = $phpcsFile->addFixableError($error, $arrayStart, self::CODE_SPACE_IN_EMPTY_ARRAY); + if (!$fix) { + return; + } + + $phpcsFile->fixer->replaceToken($arrayStart + 1, ''); + } + + private function checkWhitespaceAfterOpeningBracket(File $phpcsFile, int $arrayStart): void + { + $tokens = $phpcsFile->getTokens(); + + $whitespacePointer = $arrayStart + 1; + + $spaceLength = 0; + if ($tokens[$whitespacePointer]['code'] === T_WHITESPACE) { + $spaceLength = $tokens[$whitespacePointer]['length']; + } + + if ($spaceLength === $this->spacesAroundBrackets) { + return; + } + + $error = sprintf('Expected %d spaces after array opening bracket, %d found.', $this->spacesAroundBrackets, $spaceLength); + $fix = $phpcsFile->addFixableError($error, $arrayStart, self::CODE_SPACE_AFTER_ARRAY_OPEN); + if (!$fix) { + return; + } + + if ($spaceLength === 0) { + $phpcsFile->fixer->addContent($arrayStart, str_repeat(' ', $this->spacesAroundBrackets)); + } else { + $phpcsFile->fixer->replaceToken($whitespacePointer, str_repeat(' ', $this->spacesAroundBrackets)); + } + } + + private function checkWhitespaceBeforeClosingBracket(File $phpcsFile, int $arrayEnd): void + { + $tokens = $phpcsFile->getTokens(); + + $whitespacePointer = $arrayEnd - 1; + + $spaceLength = 0; + if ($tokens[$whitespacePointer]['code'] === T_WHITESPACE) { + $spaceLength = $tokens[$whitespacePointer]['length']; + } + + if ($spaceLength === $this->spacesAroundBrackets) { + return; + } + + $error = sprintf('Expected %d spaces before array closing bracket, %d found.', $this->spacesAroundBrackets, $spaceLength); + $fix = $phpcsFile->addFixableError($error, $arrayEnd, self::CODE_SPACE_BEFORE_ARRAY_CLOSE); + if (!$fix) { + return; + } + + if ($spaceLength === 0) { + $phpcsFile->fixer->addContentBefore($arrayEnd, str_repeat(' ', $this->spacesAroundBrackets)); + } else { + $phpcsFile->fixer->replaceToken($whitespacePointer, str_repeat(' ', $this->spacesAroundBrackets)); + } + } + + private function checkWhitespaceBeforeComma(File $phpcsFile, int $comma): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$comma - 1]['code'] !== T_WHITESPACE) { + return; + } + + if ($tokens[$comma - 2]['code'] === T_COMMA) { + return; + } + + $error = sprintf( + 'Expected 0 spaces between "%s" and comma, %d found.', + $tokens[$comma - 2]['content'], + $tokens[$comma - 1]['length'] + ); + $fix = $phpcsFile->addFixableError($error, $comma, self::CODE_SPACE_BEFORE_COMMA); + if (!$fix) { + return; + } + + $phpcsFile->fixer->replaceToken($comma - 1, ''); + } + + private function checkWhitespaceAfterComma(File $phpcsFile, int $comma): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$comma + 1]['code'] !== T_WHITESPACE) { + $error = sprintf('Expected 1 space between comma and "%s", 0 found.', $tokens[$comma + 1]['content']); + $fix = $phpcsFile->addFixableError($error, $comma, self::CODE_SPACE_AFTER_COMMA); + if ($fix) { + $phpcsFile->fixer->addContent($comma, ' '); + } + + return; + } + + $spaceLength = $tokens[$comma + 1]['length']; + if ($spaceLength === 1) { + return; + } + + $error = sprintf('Expected 1 space between comma and "%s", %d found.', $tokens[$comma + 2]['content'], $spaceLength); + $fix = $phpcsFile->addFixableError($error, $comma, self::CODE_SPACE_AFTER_COMMA); + if (!$fix) { + return; + } + + $phpcsFile->fixer->replaceToken($comma + 1, ' '); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php new file mode 100644 index 000000000..3ced79010 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php @@ -0,0 +1,80 @@ + + */ + public function register(): array + { + return TokenHelper::$arrayTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): void + { + $this->enableAfterHeredoc = SniffSettingsHelper::isEnabledByPhpVersion($this->enableAfterHeredoc, 70300); + + $tokens = $phpcsFile->getTokens(); + + [$arrayOpenerPointer, $arrayCloserPointer] = ArrayHelper::openClosePointers($tokens[$stackPointer]); + + if ($tokens[$arrayOpenerPointer]['line'] === $tokens[$arrayCloserPointer]['line']) { + return; + } + + /** @var int $pointerPreviousToClose */ + $pointerPreviousToClose = TokenHelper::findPreviousEffective($phpcsFile, $arrayCloserPointer - 1); + $tokenPreviousToClose = $tokens[$pointerPreviousToClose]; + + if ( + $pointerPreviousToClose === $arrayOpenerPointer + || $tokenPreviousToClose['code'] === T_COMMA + || $tokens[$arrayCloserPointer]['line'] === $tokenPreviousToClose['line'] + ) { + return; + } + + if ( + !$this->enableAfterHeredoc + && in_array($tokenPreviousToClose['code'], [T_END_HEREDOC, T_END_NOWDOC], true) + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Multi-line arrays must have a trailing comma after the last element.', + $pointerPreviousToClose, + self::CODE_MISSING_TRAILING_COMMA + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($pointerPreviousToClose, ','); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributeAndTargetSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributeAndTargetSpacingSniff.php new file mode 100644 index 000000000..143391bd6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributeAndTargetSpacingSniff.php @@ -0,0 +1,120 @@ + + */ + public function register(): array + { + return [T_ATTRIBUTE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $attributeOpenerPointer + */ + public function process(File $phpcsFile, $attributeOpenerPointer): void + { + $this->linesCount = SniffSettingsHelper::normalizeInteger($this->linesCount); + + if (!AttributeHelper::isValidAttribute($phpcsFile, $attributeOpenerPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $attributeCloserPointer = $tokens[$attributeOpenerPointer]['attribute_closer']; + + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $attributeCloserPointer + 1); + + while ($tokens[$pointerAfter]['code'] === T_COMMENT) { + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $pointerAfter + 1); + } + + if ($tokens[$pointerAfter]['code'] === T_ATTRIBUTE) { + return; + } + + $areOnSameLine = $tokens[$pointerAfter]['line'] === $tokens[$attributeCloserPointer]['line']; + + if ($areOnSameLine) { + if ($this->allowOnSameLine) { + return; + } + + $errorMessage = $this->linesCount === 1 + ? 'Expected 1 blank line between attribute and its target, both are on same line.' + : sprintf('Expected %1$d blank lines between attribute and its target, both are on same line.', $this->linesCount); + } else { + $actualLinesCount = $tokens[$pointerAfter]['line'] - $tokens[$attributeCloserPointer]['line'] - 1; + + if ($this->linesCount === $actualLinesCount) { + return; + } + + $errorMessage = $this->linesCount === 1 + ? sprintf('Expected 1 blank line between attribute and its target, found %1$d.', $actualLinesCount) + : sprintf('Expected %1$d blank lines between attribute and its target, found %2$d.', $this->linesCount, $actualLinesCount); + } + + $fix = $phpcsFile->addFixableError( + $errorMessage, + $attributeOpenerPointer, + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_ATTRIBUTE_AND_TARGET + ); + + if (!$fix) { + return; + } + + if ($areOnSameLine) { + $indentation = IndentationHelper::getIndentation( + $phpcsFile, + TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $pointerAfter) + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeWhitespaceAfter($phpcsFile, $attributeCloserPointer); + $phpcsFile->fixer->addContentBefore($pointerAfter, str_repeat($phpcsFile->eolChar, $this->linesCount + 1) . $indentation); + + $phpcsFile->fixer->endChangeset(); + + return; + } + + $firstTokenOnLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $pointerAfter); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $attributeCloserPointer, $firstTokenOnLine); + + $phpcsFile->fixer->addContentBefore($firstTokenOnLine, str_repeat($phpcsFile->eolChar, $this->linesCount + 1)); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributesOrderSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributesOrderSniff.php new file mode 100644 index 000000000..337c98e60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/AttributesOrderSniff.php @@ -0,0 +1,197 @@ + */ + public $order = []; + + /** @var bool */ + public $orderAlphabetically = false; + + /** + * @return array + */ + public function register(): array + { + return [T_ATTRIBUTE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $attributeOpenerPointer + */ + public function process(File $phpcsFile, $attributeOpenerPointer): void + { + if (!AttributeHelper::isValidAttribute($phpcsFile, $attributeOpenerPointer)) { + return; + } + + if ($this->order === [] && !$this->orderAlphabetically) { + throw new UnexpectedValueException('Neither manual or alphabetical order is set.'); + } + + if ($this->order !== [] && $this->orderAlphabetically) { + throw new UnexpectedValueException('Only one order can be set.'); + } + + $this->order = $this->normalizeOrder($this->order); + + $tokens = $phpcsFile->getTokens(); + + $pointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $attributeOpenerPointer - 1); + + if ($tokens[$pointerBefore]['code'] === T_ATTRIBUTE_END) { + return; + } + + $attributesGroups = [AttributeHelper::getAttributes($phpcsFile, $attributeOpenerPointer)]; + + $lastAttributeCloserPointer = $tokens[$attributeOpenerPointer]['attribute_closer']; + + do { + $nextPointer = TokenHelper::findNextNonWhitespace($phpcsFile, $lastAttributeCloserPointer + 1); + + if ($tokens[$nextPointer]['code'] !== T_ATTRIBUTE) { + break; + } + + $attributesGroups[] = AttributeHelper::getAttributes($phpcsFile, $nextPointer); + + $lastAttributeCloserPointer = $tokens[$nextPointer]['attribute_closer']; + + } while (true); + + if ($this->orderAlphabetically) { + $actualOrder = $attributesGroups; + $expectedOrder = $actualOrder; + + uasort($expectedOrder, static function (array $attributesGroup1, array $attributesGroup2): int { + return strnatcmp($attributesGroup1[0]->getName(), $attributesGroup2[0]->getName()); + }); + + } else { + $actualOrder = []; + + foreach ($attributesGroups as $attributesGroupNo => $attributesGroup) { + $attributeName = $this->normalizeAttributeName($attributesGroup[0]->getName()); + + foreach ($this->order as $orderPosition => $attributeNameOnPosition) { + if ( + $attributeName === $attributeNameOnPosition + || ( + substr($attributeNameOnPosition, -1) === '\\' + && strpos($attributeName, $attributeNameOnPosition) === 0 + ) + || ( + substr($attributeNameOnPosition, -1) === '*' + && strpos($attributeName, substr($attributeNameOnPosition, 0, -1)) === 0 + ) + ) { + $actualOrder[$attributesGroupNo] = $orderPosition; + continue 2; + } + } + + // Unknown order - add to the end + $actualOrder[$attributesGroupNo] = 999; + } + + $expectedOrder = $actualOrder; + asort($expectedOrder); + } + + if ($expectedOrder === $actualOrder) { + return; + } + + $fix = $phpcsFile->addFixableError('Incorrect order of attributes.', $attributeOpenerPointer, self::CODE_INCORRECT_ORDER); + + if (!$fix) { + return; + } + + $attributesGroupsContent = []; + foreach ($attributesGroups as $attributesGroupNo => $attributesGroup) { + $attributesGroupsContent[$attributesGroupNo] = TokenHelper::getContent( + $phpcsFile, + $attributesGroup[0]->getAttributePointer(), + $tokens[$attributesGroup[0]->getAttributePointer()]['attribute_closer'] + ); + } + + $areOnSameLine = $tokens[$attributeOpenerPointer]['line'] === $tokens[$lastAttributeCloserPointer]['line']; + + $attributesStartPointer = $attributeOpenerPointer; + $attributesEndPointer = $lastAttributeCloserPointer; + $indentation = IndentationHelper::getIndentation($phpcsFile, $attributeOpenerPointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $attributesStartPointer, $attributesEndPointer); + + foreach (array_keys($expectedOrder) as $position => $attributesGroupNo) { + if ($areOnSameLine) { + if ($position !== 0) { + $phpcsFile->fixer->addContent($attributesStartPointer, ' '); + } + + $phpcsFile->fixer->addContent($attributesStartPointer, $attributesGroupsContent[$attributesGroupNo]); + } else { + if ($position !== 0) { + $phpcsFile->fixer->addContent($attributesStartPointer, $indentation); + } + + $phpcsFile->fixer->addContent($attributesStartPointer, $attributesGroupsContent[$attributesGroupNo]); + + if ($position !== count($attributesGroups) - 1) { + $phpcsFile->fixer->addNewline($attributesStartPointer); + } + } + } + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $order + * @return list + */ + private function normalizeOrder(array $order): array + { + foreach ($order as $itemNo => $item) { + $order[$itemNo] = $this->normalizeAttributeName(trim($item)); + } + + return $order; + } + + private function normalizeAttributeName(string $name): string + { + return ltrim($name, '\\'); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowAttributesJoiningSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowAttributesJoiningSniff.php new file mode 100644 index 000000000..a86f110f2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowAttributesJoiningSniff.php @@ -0,0 +1,72 @@ + + */ + public function register(): array + { + return [T_ATTRIBUTE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $attributeOpenerPointer + */ + public function process(File $phpcsFile, $attributeOpenerPointer): void + { + if (!AttributeHelper::isValidAttribute($phpcsFile, $attributeOpenerPointer)) { + return; + } + + $attributes = AttributeHelper::getAttributes($phpcsFile, $attributeOpenerPointer); + $attributeCount = count($attributes); + + if ($attributeCount === 1) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('%d attributes are joined.', $attributeCount), + $attributeOpenerPointer, + self::CODE_DISALLOWED_ATTRIBUTES_JOINING + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + for ($i = 1; $i < count($attributes); $i++) { + $previousAttribute = $attributes[$i - 1]; + $attribute = $attributes[$i]; + + $phpcsFile->fixer->addContent($previousAttribute->getEndPointer(), ']'); + + for ($j = $previousAttribute->getEndPointer() + 1; $j < $attribute->getStartPointer(); $j++) { + if ($phpcsFile->fixer->getTokenContent($j) === ',') { + $phpcsFile->fixer->replaceToken($j, ''); + } + } + + $phpcsFile->fixer->addContentBefore($attribute->getStartPointer(), '#['); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowMultipleAttributesPerLineSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowMultipleAttributesPerLineSniff.php new file mode 100644 index 000000000..ca6f9200e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/DisallowMultipleAttributesPerLineSniff.php @@ -0,0 +1,82 @@ + + */ + public function register(): array + { + return [T_ATTRIBUTE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $attributeOpenerPointer + */ + public function process(File $phpcsFile, $attributeOpenerPointer): void + { + if (!AttributeHelper::isValidAttribute($phpcsFile, $attributeOpenerPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $attributeCloserPointer = $tokens[$attributeOpenerPointer]['attribute_closer']; + + $nextAttributeOpenerPointer = TokenHelper::findNext($phpcsFile, T_ATTRIBUTE, $attributeCloserPointer + 1); + + if ($nextAttributeOpenerPointer === null) { + return; + } + + if ($tokens[$attributeCloserPointer]['line'] !== $tokens[$nextAttributeOpenerPointer]['line']) { + return; + } + + $attributeTargetPointer = AttributeHelper::getAttributeTarget($phpcsFile, $attributeOpenerPointer); + $nextAttributeTargetPointer = AttributeHelper::getAttributeTarget($phpcsFile, $nextAttributeOpenerPointer); + + if ($attributeTargetPointer !== $nextAttributeTargetPointer) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Multiple attributes per line are disallowed.', + $nextAttributeOpenerPointer, + self::CODE_DISALLOWED_MULTIPLE_ATTRIBUTES_PER_LINE + ); + + if (!$fix) { + return; + } + + $nonWhitespacePointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $nextAttributeOpenerPointer - 1); + $indentation = IndentationHelper::getIndentation( + $phpcsFile, + TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $attributeOpenerPointer) + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $nonWhitespacePointerBefore, $nextAttributeOpenerPointer); + + $phpcsFile->fixer->addContentBefore($nextAttributeOpenerPointer, $phpcsFile->eolChar . $indentation); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/RequireAttributeAfterDocCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/RequireAttributeAfterDocCommentSniff.php new file mode 100644 index 000000000..9729e99a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Attributes/RequireAttributeAfterDocCommentSniff.php @@ -0,0 +1,86 @@ + + */ + public function register(): array + { + return [T_ATTRIBUTE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $attributeOpenerPointer + */ + public function process(File $phpcsFile, $attributeOpenerPointer): void + { + if (!AttributeHelper::isValidAttribute($phpcsFile, $attributeOpenerPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $docCommentOpenerPointer = TokenHelper::findNextExcluding( + $phpcsFile, + T_WHITESPACE, + $tokens[$attributeOpenerPointer]['attribute_closer'] + 1 + ); + + if ($tokens[$docCommentOpenerPointer]['code'] !== T_DOC_COMMENT_OPEN_TAG) { + return; + } + + $docCommentStartPointer = TokenHelper::findFirstTokenOnLine($phpcsFile, $docCommentOpenerPointer); + $docCommentEndPointer = TokenHelper::findLastTokenOnLine($phpcsFile, $tokens[$docCommentOpenerPointer]['comment_closer']); + $docComment = TokenHelper::getContent($phpcsFile, $docCommentStartPointer, $docCommentEndPointer); + + $firstAttributeOpenerPointer = $attributeOpenerPointer; + do { + $nonWhitespacePointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $firstAttributeOpenerPointer - 1); + + if ($tokens[$nonWhitespacePointerBefore]['code'] !== T_ATTRIBUTE_END) { + break; + } + + $firstAttributeOpenerPointer = $tokens[$nonWhitespacePointerBefore]['attribute_opener']; + } while (true); + + $attributeStartPointer = TokenHelper::findFirstTokenOnLine($phpcsFile, $firstAttributeOpenerPointer); + + $fix = $phpcsFile->addFixableError( + 'Attribute should be placed after documentation comment.', + $attributeOpenerPointer, + self::CODE_ATTRIBUTE_BEFORE_DOC_COMMENT + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContentBefore($attributeStartPointer, $docComment); + + FixerHelper::removeBetweenIncluding($phpcsFile, $docCommentStartPointer, $docCommentEndPointer); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractMethodSignature.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractMethodSignature.php new file mode 100644 index 000000000..5e00be600 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractMethodSignature.php @@ -0,0 +1,69 @@ + + */ + public function register(): array + { + return [T_FUNCTION]; + } + + /** + * @return array + */ + protected function getSignatureStartAndEndPointers(File $phpcsFile, int $methodPointer): array + { + $signatureStartPointer = TokenHelper::findFirstTokenOnLine($phpcsFile, $methodPointer); + + /** @var int $pointerAfterSignatureEnd */ + $pointerAfterSignatureEnd = TokenHelper::findNext($phpcsFile, [T_OPEN_CURLY_BRACKET, T_SEMICOLON], $methodPointer + 1); + if ($phpcsFile->getTokens()[$pointerAfterSignatureEnd]['code'] === T_SEMICOLON) { + return [$signatureStartPointer, $pointerAfterSignatureEnd]; + } + + /** @var int $signatureEndPointer */ + $signatureEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $pointerAfterSignatureEnd - 1); + + return [$signatureStartPointer, $signatureEndPointer]; + } + + protected function getSignature(File $phpcsFile, int $signatureStartPointer, int $signatureEndPointer): string + { + $signature = TokenHelper::getContent($phpcsFile, $signatureStartPointer, $signatureEndPointer); + $signature = preg_replace(sprintf('~%s[ \t]*~', $phpcsFile->eolChar), ' ', $signature); + assert(is_string($signature)); + + $signature = str_replace(['( ', ' )'], ['(', ')'], $signature); + $signature = rtrim($signature); + + return $signature; + } + + protected function getSignatureWithoutTabs(File $phpcsFile, string $signature): string + { + return IndentationHelper::convertTabsToSpaces($phpcsFile, $signature); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.php new file mode 100644 index 000000000..eeb2f68c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/AbstractPropertyConstantAndEnumCaseSpacing.php @@ -0,0 +1,137 @@ +minLinesCountBeforeWithComment = SniffSettingsHelper::normalizeInteger($this->minLinesCountBeforeWithComment); + $this->maxLinesCountBeforeWithComment = SniffSettingsHelper::normalizeInteger($this->maxLinesCountBeforeWithComment); + $this->minLinesCountBeforeWithoutComment = SniffSettingsHelper::normalizeInteger($this->minLinesCountBeforeWithoutComment); + $this->maxLinesCountBeforeWithoutComment = SniffSettingsHelper::normalizeInteger($this->maxLinesCountBeforeWithoutComment); + + $tokens = $phpcsFile->getTokens(); + + $classPointer = ClassHelper::getClassPointer($phpcsFile, $pointer); + + $semicolonPointer = TokenHelper::findNext($phpcsFile, [T_SEMICOLON], $pointer + 1); + assert($semicolonPointer !== null); + + $firstOnLinePointer = TokenHelper::findFirstTokenOnNextLine($phpcsFile, $semicolonPointer); + assert($firstOnLinePointer !== null); + + $nextFunctionPointer = TokenHelper::findNext( + $phpcsFile, + [T_FUNCTION, T_ENUM_CASE, T_CONST, T_VARIABLE, T_USE], + $firstOnLinePointer + 1 + ); + if ( + $nextFunctionPointer === null + || $tokens[$nextFunctionPointer]['code'] === T_FUNCTION + || $tokens[$nextFunctionPointer]['conditions'] !== $tokens[$pointer]['conditions'] + ) { + return $nextFunctionPointer ?? $firstOnLinePointer; + } + + $types = [T_COMMENT, T_DOC_COMMENT_OPEN_TAG, T_ATTRIBUTE, T_ENUM_CASE, T_CONST, T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC, T_USE]; + $nextPointer = TokenHelper::findNext($phpcsFile, $types, $firstOnLinePointer + 1, $tokens[$classPointer]['scope_closer']); + + if (!$this->isNextMemberValid($phpcsFile, $nextPointer)) { + return $nextPointer; + } + + $linesBetween = $tokens[$nextPointer]['line'] - $tokens[$semicolonPointer]['line'] - 1; + if (in_array($tokens[$nextPointer]['code'], [T_DOC_COMMENT_OPEN_TAG, T_COMMENT, T_ATTRIBUTE], true)) { + $minExpectedLines = $this->minLinesCountBeforeWithComment; + $maxExpectedLines = $this->maxLinesCountBeforeWithComment; + } else { + $minExpectedLines = $this->minLinesCountBeforeWithoutComment; + $maxExpectedLines = $this->maxLinesCountBeforeWithoutComment; + } + + if ($linesBetween >= $minExpectedLines && $linesBetween <= $maxExpectedLines) { + return $firstOnLinePointer; + } + + $fix = $this->addError($phpcsFile, $pointer, $minExpectedLines, $maxExpectedLines, $linesBetween); + if (!$fix) { + return $firstOnLinePointer; + } + + if ($linesBetween > $maxExpectedLines) { + $lastPointerOnLine = TokenHelper::findLastTokenOnLine($phpcsFile, $semicolonPointer); + $firstPointerOnNextLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $nextPointer); + + $phpcsFile->fixer->beginChangeset(); + + if ($maxExpectedLines > 0) { + $phpcsFile->fixer->addContent($lastPointerOnLine, str_repeat($phpcsFile->eolChar, $maxExpectedLines)); + } + + FixerHelper::removeBetween($phpcsFile, $lastPointerOnLine, $firstPointerOnNextLine); + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->beginChangeset(); + + for ($i = 0; $i < $minExpectedLines; $i++) { + $phpcsFile->fixer->addNewlineBefore($firstOnLinePointer); + } + + $phpcsFile->fixer->endChangeset(); + } + + return $firstOnLinePointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/BackedEnumTypeSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/BackedEnumTypeSpacingSniff.php new file mode 100644 index 000000000..0af9932de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/BackedEnumTypeSpacingSniff.php @@ -0,0 +1,121 @@ + + */ + public function register(): array + { + return [T_ENUM]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $enumPointer + */ + public function process(File $phpcsFile, $enumPointer): void + { + $this->spacesCountBeforeColon = SniffSettingsHelper::normalizeInteger($this->spacesCountBeforeColon); + $this->spacesCountBeforeType = SniffSettingsHelper::normalizeInteger($this->spacesCountBeforeType); + + $tokens = $phpcsFile->getTokens(); + + $colonPointer = TokenHelper::findNext($phpcsFile, T_COLON, $enumPointer + 1, $tokens[$enumPointer]['scope_opener']); + + if ($colonPointer === null) { + return; + } + + $this->checkSpacesBeforeColon($phpcsFile, $colonPointer); + $this->checkSpacesBeforeType($phpcsFile, $colonPointer); + } + + public function checkSpacesBeforeColon(File $phpcsFile, int $colonPointer): void + { + $namePointer = TokenHelper::findPreviousEffective($phpcsFile, $colonPointer - 1); + + $whitespace = TokenHelper::getContent($phpcsFile, $namePointer + 1, $colonPointer - 1); + + if ($this->spacesCountBeforeColon === strlen($whitespace)) { + return; + } + + $fix = $phpcsFile->addFixableError( + $this->formatErrorMessage('before colon', $this->spacesCountBeforeColon), + $colonPointer, + self::CODE_INCORRECT_SPACES_BEFORE_COLON + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $namePointer, $colonPointer); + + $phpcsFile->fixer->addContentBefore($colonPointer, str_repeat(' ', $this->spacesCountBeforeColon)); + + $phpcsFile->fixer->endChangeset(); + } + + public function checkSpacesBeforeType(File $phpcsFile, int $colonPointer): void + { + $typePointer = TokenHelper::findNextEffective($phpcsFile, $colonPointer + 1); + + $whitespace = TokenHelper::getContent($phpcsFile, $colonPointer + 1, $typePointer - 1); + + if ($this->spacesCountBeforeType === strlen($whitespace)) { + return; + } + + $fix = $phpcsFile->addFixableError( + $this->formatErrorMessage('before type', $this->spacesCountBeforeType), + $typePointer, + self::CODE_INCORRECT_SPACES_BEFORE_TYPE + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $colonPointer, $typePointer); + + $phpcsFile->fixer->addContentBefore($typePointer, str_repeat(' ', $this->spacesCountBeforeType)); + + $phpcsFile->fixer->endChangeset(); + } + + private function formatErrorMessage(string $suffix, int $requiredSpaces): string + { + return $requiredSpaces === 0 + ? sprintf('There must be no whitespace %s.', $suffix) + : sprintf('There must be exactly %d whitespace%s %s.', $requiredSpaces, $requiredSpaces !== 1 ? 's' : '', $suffix); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassConstantVisibilitySniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassConstantVisibilitySniff.php new file mode 100644 index 000000000..19ee9f1bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassConstantVisibilitySniff.php @@ -0,0 +1,87 @@ + + */ + public function register(): array + { + return [ + T_CONST, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $constantPointer + */ + public function process(File $phpcsFile, $constantPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (count($tokens[$constantPointer]['conditions']) === 0) { + return; + } + + /** @var int $classPointer */ + $classPointer = array_keys($tokens[$constantPointer]['conditions'])[count($tokens[$constantPointer]['conditions']) - 1]; + if (!in_array($tokens[$classPointer]['code'], Tokens::$ooScopeTokens, true)) { + return; + } + + $visibilityPointer = TokenHelper::findPreviousEffective($phpcsFile, $constantPointer - 1); + if ($tokens[$visibilityPointer]['code'] === T_FINAL) { + $visibilityPointer = TokenHelper::findPreviousEffective($phpcsFile, $visibilityPointer - 1); + } + + if (in_array($tokens[$visibilityPointer]['code'], [T_PUBLIC, T_PROTECTED, T_PRIVATE], true)) { + return; + } + + $equalSignPointer = TokenHelper::findNext($phpcsFile, T_EQUAL, $constantPointer + 1); + $namePointer = TokenHelper::findPreviousEffective($phpcsFile, $equalSignPointer - 1); + + $message = sprintf( + 'Constant %s::%s visibility missing.', + ClassHelper::getFullyQualifiedName($phpcsFile, $classPointer), + $tokens[$namePointer]['content'] + ); + + if ($this->fixable) { + $fix = $phpcsFile->addFixableError($message, $constantPointer, self::CODE_MISSING_CONSTANT_VISIBILITY); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($constantPointer, 'public '); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($message, $constantPointer, self::CODE_MISSING_CONSTANT_VISIBILITY); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassLengthSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassLengthSniff.php new file mode 100644 index 000000000..bdc035d7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassLengthSniff.php @@ -0,0 +1,64 @@ + + */ + public function register(): array + { + return array_values(Tokens::$ooScopeTokens); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->maxLinesLength = SniffSettingsHelper::normalizeInteger($this->maxLinesLength); + $flags = array_keys(array_filter([ + FunctionHelper::LINE_INCLUDE_COMMENT => $this->includeComments, + FunctionHelper::LINE_INCLUDE_WHITESPACE => $this->includeWhitespace, + ])); + $flags = array_reduce($flags, static function ($carry, $flag): int { + return $carry | $flag; + }, 0); + + $length = FunctionHelper::getLineCount($phpcsFile, $pointer, $flags); + + if ($length <= $this->maxLinesLength) { + return; + } + + $errorMessage = sprintf('Your class is too long. Currently using %d lines. Can be up to %d lines.', $length, $this->maxLinesLength); + + $phpcsFile->addError($errorMessage, $pointer, self::CODE_CLASS_TOO_LONG); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassMemberSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassMemberSpacingSniff.php new file mode 100644 index 000000000..ffac3ad36 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassMemberSpacingSniff.php @@ -0,0 +1,278 @@ + + */ + public function register(): array + { + return TokenHelper::$typeWithAnonymousClassKeywordTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $this->linesCountBetweenMembers = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenMembers); + + $tokens = $phpcsFile->getTokens(); + + $memberPointer = null; + $previousMemberPointer = null; + + do { + $previousMemberPointer = $memberPointer; + + $memberPointer = $this->findNextMember( + $phpcsFile, + $classPointer, + $previousMemberPointer ?? $tokens[$classPointer]['scope_opener'] + ); + + if ($memberPointer === null) { + break; + } + + if ($previousMemberPointer === null) { + continue; + } + + if ($tokens[$previousMemberPointer]['code'] === $tokens[$memberPointer]['code']) { + continue; + } + + $previousMemberEndPointer = $this->getMemberEndPointer($phpcsFile, $previousMemberPointer); + + $hasCommentWithNewLineAfterPreviousMember = false; + + $commentPointerAfterPreviousMember = TokenHelper::findNextNonWhitespace($phpcsFile, $previousMemberEndPointer + 1); + if ( + in_array($tokens[$commentPointerAfterPreviousMember]['code'], TokenHelper::$inlineCommentTokenCodes, true) + && ( + $tokens[$previousMemberEndPointer]['line'] === $tokens[$commentPointerAfterPreviousMember]['line'] + || $tokens[$previousMemberEndPointer]['line'] + 1 === $tokens[$commentPointerAfterPreviousMember]['line'] + ) + ) { + $previousMemberEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $commentPointerAfterPreviousMember); + + if (StringHelper::endsWith($tokens[$commentPointerAfterPreviousMember]['content'], $phpcsFile->eolChar)) { + $hasCommentWithNewLineAfterPreviousMember = true; + } + } + + $memberStartPointer = $this->getMemberStartPointer($phpcsFile, $memberPointer); + + $actualLinesCount = $tokens[$memberStartPointer]['line'] - $tokens[$previousMemberEndPointer]['line'] - 1; + + if ($actualLinesCount === $this->linesCountBetweenMembers) { + continue; + } + + $errorMessage = $this->linesCountBetweenMembers === 1 + ? 'Expected 1 blank line between class members, found %2$d.' + : 'Expected %1$d blank lines between class members, found %2$d.'; + + $fix = $phpcsFile->addFixableError( + sprintf($errorMessage, $this->linesCountBetweenMembers, $actualLinesCount), + $memberPointer, + self::CODE_INCORRECT_COUNT_OF_BLANK_LINES_BETWEEN_MEMBERS + ); + if (!$fix) { + continue; + } + + $newLines = str_repeat( + $phpcsFile->eolChar, + $this->linesCountBetweenMembers + ($hasCommentWithNewLineAfterPreviousMember ? 0 : 1) + ); + + $firstPointerOnMemberLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $memberStartPointer); + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($previousMemberEndPointer, $newLines); + + FixerHelper::removeBetween($phpcsFile, $previousMemberEndPointer, $firstPointerOnMemberLine); + + $phpcsFile->fixer->endChangeset(); + + } while (true); + } + + private function findNextMember(File $phpcsFile, int $classPointer, int $previousMemberPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $memberPointer = $previousMemberPointer; + do { + $memberPointer = TokenHelper::findNext( + $phpcsFile, + [T_USE, T_CONST, T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC, T_FUNCTION, T_ENUM_CASE], + $memberPointer + 1, + $tokens[$classPointer]['scope_closer'] + ); + + if ($memberPointer === null) { + return null; + } + + if ($tokens[$memberPointer]['code'] === T_USE) { + if (!UseStatementHelper::isTraitUse($phpcsFile, $memberPointer)) { + continue; + } + } elseif (in_array($tokens[$memberPointer]['code'], [T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC], true)) { + $asPointer = TokenHelper::findPreviousEffective($phpcsFile, $memberPointer - 1); + if ($tokens[$asPointer]['code'] === T_AS) { + continue; + } + + $propertyPointer = TokenHelper::findNext($phpcsFile, [T_VARIABLE, T_FUNCTION, T_CONST, T_ENUM_CASE], $memberPointer + 1); + if ( + $propertyPointer === null + || $tokens[$propertyPointer]['code'] !== T_VARIABLE + || !PropertyHelper::isProperty($phpcsFile, $propertyPointer) + ) { + continue; + } + + $memberPointer = $propertyPointer; + } + + if (ScopeHelper::isInSameScope($phpcsFile, $memberPointer, $previousMemberPointer)) { + break; + } + + } while (true); + + return $memberPointer; + } + + private function getMemberStartPointer(File $phpcsFile, int $memberPointer): int + { + $tokens = $phpcsFile->getTokens(); + + $memberFirstCodePointer = $this->getMemberFirstCodePointer($phpcsFile, $memberPointer); + + do { + $pointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $memberFirstCodePointer - 1); + + if ($tokens[$pointerBefore]['code'] === T_ATTRIBUTE_END) { + $memberFirstCodePointer = $tokens[$pointerBefore]['attribute_opener']; + continue; + } + + if ( + in_array($tokens[$pointerBefore]['code'], Tokens::$commentTokens, true) + && $tokens[$pointerBefore]['line'] + 1 === $tokens[$memberFirstCodePointer]['line'] + ) { + $pointerBeforeComment = TokenHelper::findPreviousEffective($phpcsFile, $pointerBefore - 1); + if ($tokens[$pointerBeforeComment]['line'] !== $tokens[$pointerBefore]['line']) { + $memberFirstCodePointer = array_key_exists('comment_opener', $tokens[$pointerBefore]) + ? $tokens[$pointerBefore]['comment_opener'] + : CommentHelper::getMultilineCommentStartPointer($phpcsFile, $pointerBefore); + continue; + } + } + + break; + + } while (true); + + return $memberFirstCodePointer; + } + + private function getMemberFirstCodePointer(File $phpcsFile, int $memberPointer): int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$memberPointer]['code'] === T_USE) { + return $memberPointer; + } + + $firstCodePointer = $memberPointer; + $previousFirstCodePointer = $memberPointer; + do { + /** @var int $firstCodePointer */ + $firstCodePointer = TokenHelper::findPrevious( + $phpcsFile, + [T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_ABSTRACT, T_FINAL, T_SEMICOLON, T_CLOSE_CURLY_BRACKET], + $firstCodePointer - 1 + ); + + if (in_array($tokens[$firstCodePointer]['code'], [T_SEMICOLON, T_CLOSE_CURLY_BRACKET], true)) { + break; + } + + $previousFirstCodePointer = $firstCodePointer; + + } while (true); + + return $previousFirstCodePointer; + } + + private function getMemberEndPointer(File $phpcsFile, int $memberPointer): int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$memberPointer]['code'] === T_USE) { + $pointer = TokenHelper::findNextLocal($phpcsFile, [T_SEMICOLON, T_OPEN_CURLY_BRACKET], $memberPointer + 1); + + return $tokens[$pointer]['code'] === T_OPEN_CURLY_BRACKET + ? $tokens[$pointer]['bracket_closer'] + : $pointer; + } + + if ($tokens[$memberPointer]['code'] === T_FUNCTION && !FunctionHelper::isAbstract($phpcsFile, $memberPointer)) { + return $tokens[$memberPointer]['scope_closer']; + } + + return TokenHelper::findNext($phpcsFile, T_SEMICOLON, $memberPointer + 1); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassStructureSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassStructureSniff.php new file mode 100644 index 000000000..e01288ba7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassStructureSniff.php @@ -0,0 +1,666 @@ + [ + self::GROUP_PUBLIC_CONSTANTS, + self::GROUP_PROTECTED_CONSTANTS, + self::GROUP_PRIVATE_CONSTANTS, + ], + self::GROUP_SHORTCUT_STATIC_PROPERTIES => [ + self::GROUP_PUBLIC_STATIC_PROPERTIES, + self::GROUP_PROTECTED_STATIC_PROPERTIES, + self::GROUP_PRIVATE_STATIC_PROPERTIES, + ], + self::GROUP_SHORTCUT_PROPERTIES => [ + self::GROUP_SHORTCUT_STATIC_PROPERTIES, + self::GROUP_PUBLIC_PROPERTIES, + self::GROUP_PROTECTED_PROPERTIES, + self::GROUP_PRIVATE_PROPERTIES, + ], + self::GROUP_SHORTCUT_PUBLIC_METHODS => [ + self::GROUP_PUBLIC_FINAL_METHODS, + self::GROUP_PUBLIC_STATIC_FINAL_METHODS, + self::GROUP_PUBLIC_ABSTRACT_METHODS, + self::GROUP_PUBLIC_STATIC_ABSTRACT_METHODS, + self::GROUP_PUBLIC_STATIC_METHODS, + self::GROUP_PUBLIC_METHODS, + ], + self::GROUP_SHORTCUT_PROTECTED_METHODS => [ + self::GROUP_PROTECTED_FINAL_METHODS, + self::GROUP_PROTECTED_STATIC_FINAL_METHODS, + self::GROUP_PROTECTED_ABSTRACT_METHODS, + self::GROUP_PROTECTED_STATIC_ABSTRACT_METHODS, + self::GROUP_PROTECTED_STATIC_METHODS, + self::GROUP_PROTECTED_METHODS, + ], + self::GROUP_SHORTCUT_PRIVATE_METHODS => [ + self::GROUP_PRIVATE_STATIC_METHODS, + self::GROUP_PRIVATE_METHODS, + ], + self::GROUP_SHORTCUT_FINAL_METHODS => [ + self::GROUP_PUBLIC_FINAL_METHODS, + self::GROUP_PROTECTED_FINAL_METHODS, + self::GROUP_PUBLIC_STATIC_FINAL_METHODS, + self::GROUP_PROTECTED_STATIC_FINAL_METHODS, + ], + self::GROUP_SHORTCUT_ABSTRACT_METHODS => [ + self::GROUP_PUBLIC_ABSTRACT_METHODS, + self::GROUP_PROTECTED_ABSTRACT_METHODS, + self::GROUP_PUBLIC_STATIC_ABSTRACT_METHODS, + self::GROUP_PROTECTED_STATIC_ABSTRACT_METHODS, + ], + self::GROUP_SHORTCUT_STATIC_METHODS => [ + self::GROUP_STATIC_CONSTRUCTORS, + self::GROUP_PUBLIC_STATIC_FINAL_METHODS, + self::GROUP_PROTECTED_STATIC_FINAL_METHODS, + self::GROUP_PUBLIC_STATIC_ABSTRACT_METHODS, + self::GROUP_PROTECTED_STATIC_ABSTRACT_METHODS, + self::GROUP_PUBLIC_STATIC_METHODS, + self::GROUP_PROTECTED_STATIC_METHODS, + self::GROUP_PRIVATE_STATIC_METHODS, + ], + self::GROUP_SHORTCUT_METHODS => [ + self::GROUP_SHORTCUT_FINAL_METHODS, + self::GROUP_SHORTCUT_ABSTRACT_METHODS, + self::GROUP_SHORTCUT_STATIC_METHODS, + self::GROUP_CONSTRUCTOR, + self::GROUP_DESTRUCTOR, + self::GROUP_PUBLIC_METHODS, + self::GROUP_PROTECTED_METHODS, + self::GROUP_PRIVATE_METHODS, + self::GROUP_MAGIC_METHODS, + ], + ]; + + private const SPECIAL_METHODS = [ + '__construct' => self::GROUP_CONSTRUCTOR, + '__destruct' => self::GROUP_DESTRUCTOR, + '__call' => self::GROUP_MAGIC_METHODS, + '__callstatic' => self::GROUP_MAGIC_METHODS, + '__get' => self::GROUP_MAGIC_METHODS, + '__set' => self::GROUP_MAGIC_METHODS, + '__isset' => self::GROUP_MAGIC_METHODS, + '__unset' => self::GROUP_MAGIC_METHODS, + '__sleep' => self::GROUP_MAGIC_METHODS, + '__wakeup' => self::GROUP_MAGIC_METHODS, + '__serialize' => self::GROUP_MAGIC_METHODS, + '__unserialize' => self::GROUP_MAGIC_METHODS, + '__tostring' => self::GROUP_MAGIC_METHODS, + '__invoke' => self::GROUP_MAGIC_METHODS, + '__set_state' => self::GROUP_MAGIC_METHODS, + '__clone' => self::GROUP_MAGIC_METHODS, + '__debuginfo' => self::GROUP_MAGIC_METHODS, + ]; + + /** @var list */ + public $groups = []; + + /** @var array|null */ + private $normalizedGroups; + + /** + * @return array + */ + public function register(): array + { + return array_values(Tokens::$ooScopeTokens); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): int + { + $tokens = $phpcsFile->getTokens(); + /** @var array{scope_closer: int, level: int} $rootScopeToken */ + $rootScopeToken = $tokens[$pointer]; + + $groupsOrder = $this->getNormalizedGroups(); + + $groupLastMemberPointer = $rootScopeToken['scope_opener']; + $expectedGroup = null; + $groupsFirstMembers = []; + while (true) { + $nextGroup = $this->findNextGroup($phpcsFile, $groupLastMemberPointer, $rootScopeToken); + if ($nextGroup === null) { + break; + } + + [$groupFirstMemberPointer, $groupLastMemberPointer, $group] = $nextGroup; + + if ($groupsOrder[$group] >= ($groupsOrder[$expectedGroup] ?? 0)) { + $groupsFirstMembers[$group] = $groupFirstMemberPointer; + $expectedGroup = $group; + + continue; + } + + $expectedGroups = array_filter( + $groupsOrder, + static function (int $order) use ($groupsOrder, $expectedGroup): bool { + return $order >= $groupsOrder[$expectedGroup]; + } + ); + $fix = $phpcsFile->addFixableError( + sprintf( + 'The placement of "%s" group is invalid. Last group was "%s" and one of these is expected after it: %s', + $group, + $expectedGroup, + implode(', ', array_keys($expectedGroups)) + ), + $groupFirstMemberPointer, + self::CODE_INCORRECT_GROUP_ORDER + ); + if (!$fix) { + continue; + } + + foreach ($groupsFirstMembers as $memberGroup => $firstMemberPointer) { + if ($groupsOrder[$memberGroup] <= $groupsOrder[$group]) { + continue; + } + + $this->fixIncorrectGroupOrder($phpcsFile, $groupFirstMemberPointer, $groupLastMemberPointer, $firstMemberPointer); + + // run the sniff again to fix the rest of the groups + return $pointer - 1; + } + } + + return $pointer + 1; + } + + /** + * @param array{scope_closer: int, level: int} $rootScopeToken + * @return array{int, int, string}|null + */ + private function findNextGroup(File $phpcsFile, int $pointer, array $rootScopeToken): ?array + { + $tokens = $phpcsFile->getTokens(); + $groupTokenTypes = [T_USE, T_ENUM_CASE, T_CONST, T_VARIABLE, T_FUNCTION]; + + $currentTokenPointer = $pointer; + while (true) { + $currentTokenPointer = TokenHelper::findNext( + $phpcsFile, + $groupTokenTypes, + ($currentToken['scope_closer'] ?? $currentTokenPointer) + 1, + $rootScopeToken['scope_closer'] + ); + if ($currentTokenPointer === null) { + break; + } + + $currentToken = $tokens[$currentTokenPointer]; + + if ($currentToken['code'] === T_VARIABLE && !PropertyHelper::isProperty($phpcsFile, $currentTokenPointer)) { + continue; + } + + if ($currentToken['level'] - $rootScopeToken['level'] !== 1) { + continue; + } + + $group = $this->getGroupForToken($phpcsFile, $currentTokenPointer); + + if (!isset($currentGroup)) { + $currentGroup = $group; + $groupFirstMemberPointer = $currentTokenPointer; + } + + if ($group !== $currentGroup) { + break; + } + + $groupLastMemberPointer = $currentTokenPointer; + } + + if (!isset($currentGroup)) { + return null; + } + + assert(isset($groupFirstMemberPointer) === true); + assert(isset($groupLastMemberPointer) === true); + + return [$groupFirstMemberPointer, $groupLastMemberPointer, $currentGroup]; + } + + private function getGroupForToken(File $phpcsFile, int $pointer): string + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$pointer]['code']) { + case T_USE: + return self::GROUP_USES; + case T_ENUM_CASE: + return self::GROUP_ENUM_CASES; + case T_CONST: + switch ($this->getVisibilityForToken($phpcsFile, $pointer)) { + case T_PUBLIC: + return self::GROUP_PUBLIC_CONSTANTS; + case T_PROTECTED: + return self::GROUP_PROTECTED_CONSTANTS; + } + + return self::GROUP_PRIVATE_CONSTANTS; + case T_FUNCTION: + $name = strtolower(FunctionHelper::getName($phpcsFile, $pointer)); + if (array_key_exists($name, self::SPECIAL_METHODS)) { + return self::SPECIAL_METHODS[$name]; + } + + $visibility = $this->getVisibilityForToken($phpcsFile, $pointer); + $isStatic = $this->isMemberStatic($phpcsFile, $pointer); + $isFinal = $this->isMethodFinal($phpcsFile, $pointer); + + if ($this->isMethodAbstract($phpcsFile, $pointer)) { + if ($visibility === T_PUBLIC) { + return $isStatic ? self::GROUP_PUBLIC_STATIC_ABSTRACT_METHODS : self::GROUP_PUBLIC_ABSTRACT_METHODS; + } + + return $isStatic ? self::GROUP_PROTECTED_STATIC_ABSTRACT_METHODS : self::GROUP_PROTECTED_ABSTRACT_METHODS; + } + + if ($isStatic && $visibility === T_PUBLIC && $this->isStaticConstructor($phpcsFile, $pointer)) { + return self::GROUP_STATIC_CONSTRUCTORS; + } + + switch ($visibility) { + case T_PUBLIC: + if ($isFinal) { + return $isStatic ? self::GROUP_PUBLIC_STATIC_FINAL_METHODS : self::GROUP_PUBLIC_FINAL_METHODS; + } + + return $isStatic ? self::GROUP_PUBLIC_STATIC_METHODS : self::GROUP_PUBLIC_METHODS; + case T_PROTECTED: + if ($isFinal) { + return $isStatic ? self::GROUP_PROTECTED_STATIC_FINAL_METHODS : self::GROUP_PROTECTED_FINAL_METHODS; + } + + return $isStatic ? self::GROUP_PROTECTED_STATIC_METHODS : self::GROUP_PROTECTED_METHODS; + } + + return $isStatic ? self::GROUP_PRIVATE_STATIC_METHODS : self::GROUP_PRIVATE_METHODS; + default: + $isStatic = $this->isMemberStatic($phpcsFile, $pointer); + $visibility = $this->getVisibilityForToken($phpcsFile, $pointer); + + switch ($visibility) { + case T_PUBLIC: + return $isStatic ? self::GROUP_PUBLIC_STATIC_PROPERTIES : self::GROUP_PUBLIC_PROPERTIES; + case T_PROTECTED: + return $isStatic + ? self::GROUP_PROTECTED_STATIC_PROPERTIES + : self::GROUP_PROTECTED_PROPERTIES; + default: + return $isStatic ? self::GROUP_PRIVATE_STATIC_PROPERTIES : self::GROUP_PRIVATE_PROPERTIES; + } + } + } + + private function getVisibilityForToken(File $phpcsFile, int $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + array_merge(Tokens::$scopeModifiers, [T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_SEMICOLON]), + $pointer - 1 + ); + + /** @var int $visibilityPointer */ + $visibilityPointer = in_array($tokens[$previousPointer]['code'], Tokens::$scopeModifiers, true) + ? $tokens[$previousPointer]['code'] + : T_PUBLIC; + return $visibilityPointer; + } + + private function isMemberStatic(File $phpcsFile, int $pointer): bool + { + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_SEMICOLON, T_STATIC], + $pointer - 1 + ); + return $phpcsFile->getTokens()[$previousPointer]['code'] === T_STATIC; + } + + private function isMethodFinal(File $phpcsFile, int $pointer): bool + { + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_SEMICOLON, T_FINAL], + $pointer - 1 + ); + return $phpcsFile->getTokens()[$previousPointer]['code'] === T_FINAL; + } + + private function isMethodAbstract(File $phpcsFile, int $pointer): bool + { + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_SEMICOLON, T_ABSTRACT], + $pointer - 1 + ); + return $phpcsFile->getTokens()[$previousPointer]['code'] === T_ABSTRACT; + } + + private function isStaticConstructor(File $phpcsFile, int $pointer): bool + { + $parentClassName = $this->getParentClassName($phpcsFile, $pointer); + + $returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $pointer); + if ($returnTypeHint !== null) { + return in_array($returnTypeHint->getTypeHintWithoutNullabilitySymbol(), ['self', $parentClassName], true); + } + + $returnAnnotation = FunctionHelper::findReturnAnnotation($phpcsFile, $pointer); + if ($returnAnnotation === null) { + return false; + } + + return in_array((string) $returnAnnotation->getValue()->type, ['static', 'self', $parentClassName], true); + } + + private function getParentClassName(File $phpcsFile, int $pointer): string + { + $classPointer = TokenHelper::findPrevious($phpcsFile, Tokens::$ooScopeTokens, $pointer - 1); + assert($classPointer !== null); + + return ClassHelper::getName($phpcsFile, $classPointer); + } + + private function fixIncorrectGroupOrder( + File $file, + int $groupFirstMemberPointer, + int $groupLastMemberPointer, + int $nextGroupMemberPointer + ): void + { + $previousMemberEndPointer = $this->findPreviousMemberEndPointer($file, $groupFirstMemberPointer); + + $groupStartPointer = $this->findGroupStartPointer($file, $groupFirstMemberPointer, $previousMemberEndPointer); + $groupEndPointer = $this->findGroupEndPointer($file, $groupLastMemberPointer); + $groupContent = TokenHelper::getContent($file, $groupStartPointer, $groupEndPointer); + + $nextGroupMemberStartPointer = $this->findGroupStartPointer($file, $nextGroupMemberPointer); + + $file->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($file, $groupStartPointer, $groupEndPointer); + + $linesBetween = $this->removeBlankLinesAfterMember($file, $previousMemberEndPointer, $groupStartPointer); + + $newLines = str_repeat($file->eolChar, $linesBetween); + $file->fixer->addContentBefore($nextGroupMemberStartPointer, $groupContent . $newLines); + + $file->fixer->endChangeset(); + } + + private function findPreviousMemberEndPointer(File $phpcsFile, int $memberPointer): int + { + $endTypes = [T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_SEMICOLON]; + $previousMemberEndPointer = TokenHelper::findPrevious($phpcsFile, $endTypes, $memberPointer - 1); + assert($previousMemberEndPointer !== null); + + return $previousMemberEndPointer; + } + + private function findGroupStartPointer(File $phpcsFile, int $memberPointer, ?int $previousMemberEndPointer = null): int + { + $startPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $memberPointer - 1); + if ($startPointer === null) { + if ($previousMemberEndPointer === null) { + $previousMemberEndPointer = $this->findPreviousMemberEndPointer($phpcsFile, $memberPointer); + } + + $startPointer = TokenHelper::findNextEffective($phpcsFile, $previousMemberEndPointer + 1); + assert($startPointer !== null); + } + + $types = [T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_SEMICOLON]; + + return (int) $phpcsFile->findFirstOnLine($types, $startPointer, true); + } + + private function findGroupEndPointer(File $phpcsFile, int $memberPointer): int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$memberPointer]['code'] === T_FUNCTION && !FunctionHelper::isAbstract($phpcsFile, $memberPointer)) { + $endPointer = $tokens[$memberPointer]['scope_closer']; + } elseif ($tokens[$memberPointer]['code'] === T_USE && array_key_exists('scope_closer', $tokens[$memberPointer])) { + $endPointer = $tokens[$memberPointer]['scope_closer']; + } else { + $endPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $memberPointer + 1); + assert($endPointer !== null); + } + + return $endPointer; + } + + private function removeBlankLinesAfterMember(File $phpcsFile, int $memberEndPointer, int $endPointer): int + { + $whitespacePointer = $memberEndPointer; + + $linesToRemove = 0; + while (true) { + $whitespacePointer = TokenHelper::findNext($phpcsFile, T_WHITESPACE, $whitespacePointer, $endPointer); + if ($whitespacePointer === null) { + break; + } + + $linesToRemove++; + $phpcsFile->fixer->replaceToken($whitespacePointer, ''); + $whitespacePointer++; + } + + return $linesToRemove; + } + + /** + * @return array + */ + private function getNormalizedGroups(): array + { + if ($this->normalizedGroups === null) { + $supportedGroups = [ + self::GROUP_USES, + self::GROUP_ENUM_CASES, + self::GROUP_PUBLIC_CONSTANTS, + self::GROUP_PROTECTED_CONSTANTS, + self::GROUP_PRIVATE_CONSTANTS, + self::GROUP_PUBLIC_PROPERTIES, + self::GROUP_PUBLIC_STATIC_PROPERTIES, + self::GROUP_PROTECTED_PROPERTIES, + self::GROUP_PROTECTED_STATIC_PROPERTIES, + self::GROUP_PRIVATE_PROPERTIES, + self::GROUP_PRIVATE_STATIC_PROPERTIES, + self::GROUP_PUBLIC_STATIC_FINAL_METHODS, + self::GROUP_PUBLIC_STATIC_ABSTRACT_METHODS, + self::GROUP_PROTECTED_STATIC_FINAL_METHODS, + self::GROUP_PROTECTED_STATIC_ABSTRACT_METHODS, + self::GROUP_PUBLIC_FINAL_METHODS, + self::GROUP_PUBLIC_ABSTRACT_METHODS, + self::GROUP_PROTECTED_FINAL_METHODS, + self::GROUP_PROTECTED_ABSTRACT_METHODS, + self::GROUP_CONSTRUCTOR, + self::GROUP_STATIC_CONSTRUCTORS, + self::GROUP_DESTRUCTOR, + self::GROUP_PUBLIC_METHODS, + self::GROUP_PUBLIC_STATIC_METHODS, + self::GROUP_PROTECTED_METHODS, + self::GROUP_PROTECTED_STATIC_METHODS, + self::GROUP_PRIVATE_METHODS, + self::GROUP_PRIVATE_STATIC_METHODS, + self::GROUP_MAGIC_METHODS, + ]; + + $normalizedGroupsWithShortcuts = []; + $order = 1; + foreach (SniffSettingsHelper::normalizeArray($this->groups) as $groupsString) { + /** @var list $groups */ + $groups = preg_split('~\\s*,\\s*~', strtolower($groupsString)); + foreach ($groups as $groupOrShortcut) { + $groupOrShortcut = preg_replace('~\\s+~', ' ', $groupOrShortcut); + + if ( + !in_array($groupOrShortcut, $supportedGroups, true) + && !array_key_exists($groupOrShortcut, self::SHORTCUTS) + ) { + throw new UnsupportedClassGroupException($groupOrShortcut); + } + + $normalizedGroupsWithShortcuts[$groupOrShortcut] = $order; + } + + $order++; + } + + $normalizedGroups = []; + foreach ($normalizedGroupsWithShortcuts as $groupOrShortcut => $groupOrder) { + if (in_array($groupOrShortcut, $supportedGroups, true)) { + $normalizedGroups[$groupOrShortcut] = $groupOrder; + } else { + foreach ($this->unpackShortcut($groupOrShortcut, $supportedGroups) as $group) { + if ( + array_key_exists($group, $normalizedGroupsWithShortcuts) + || array_key_exists($group, $normalizedGroups) + ) { + continue; + } + + $normalizedGroups[$group] = $groupOrder; + } + } + } + + if ($normalizedGroups === []) { + $normalizedGroups = array_flip($supportedGroups); + } else { + $missingGroups = array_diff($supportedGroups, array_keys($normalizedGroups)); + if ($missingGroups !== []) { + throw new MissingClassGroupsException($missingGroups); + } + } + + $this->normalizedGroups = $normalizedGroups; + } + + return $this->normalizedGroups; + } + + /** + * @param array $supportedGroups + * @return array + */ + private function unpackShortcut(string $shortcut, array $supportedGroups): array + { + $groups = []; + + foreach (self::SHORTCUTS[$shortcut] as $groupOrShortcut) { + if (in_array($groupOrShortcut, $supportedGroups, true)) { + $groups[] = $groupOrShortcut; + } elseif ( + !array_key_exists($groupOrShortcut, self::SHORTCUTS) + && in_array($groupOrShortcut, self::SHORTCUTS[self::GROUP_SHORTCUT_FINAL_METHODS], true) + ) { + // Nothing + } else { + $groups = array_merge($groups, $this->unpackShortcut($groupOrShortcut, $supportedGroups)); + } + } + + return $groups; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ConstantSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ConstantSpacingSniff.php new file mode 100644 index 000000000..70defe2b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ConstantSpacingSniff.php @@ -0,0 +1,79 @@ + + */ + public function register(): array + { + return [T_CONST]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $constantPointer + */ + public function process(File $phpcsFile, $constantPointer): int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$constantPointer]['conditions'] === []) { + return $constantPointer; + } + + /** @var int $classPointer */ + $classPointer = array_keys($tokens[$constantPointer]['conditions'])[count($tokens[$constantPointer]['conditions']) - 1]; + if (!in_array($tokens[$classPointer]['code'], Tokens::$ooScopeTokens, true)) { + return $constantPointer; + } + + return parent::process($phpcsFile, $constantPointer); + } + + protected function isNextMemberValid(File $phpcsFile, int $pointer): bool + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_CONST) { + return true; + } + + $nextPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_ENUM_CASE, T_CONST, T_VARIABLE, T_USE], $pointer + 1); + + return $tokens[$nextPointer]['code'] === T_CONST; + } + + protected function addError(File $phpcsFile, int $pointer, int $minExpectedLines, int $maxExpectedLines, int $found): bool + { + if ($minExpectedLines === $maxExpectedLines) { + $errorMessage = $minExpectedLines === 1 + ? 'Expected 1 blank line after constant, found %3$d.' + : 'Expected %2$d blank lines after constant, found %3$d.'; + } else { + $errorMessage = 'Expected %1$d to %2$d blank lines after constant, found %3$d.'; + } + $error = sprintf($errorMessage, $minExpectedLines, $maxExpectedLines, $found); + + return $phpcsFile->addFixableError($error, $pointer, self::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_CONSTANT); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowConstructorPropertyPromotionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowConstructorPropertyPromotionSniff.php new file mode 100644 index 000000000..fd4106386 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowConstructorPropertyPromotionSniff.php @@ -0,0 +1,69 @@ + + */ + public function register(): array + { + return [T_FUNCTION]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $namePointer = TokenHelper::findNextEffective($phpcsFile, $functionPointer + 1); + + if (strtolower($tokens[$namePointer]['content']) !== '__construct') { + return; + } + + $modifierPointers = TokenHelper::findNextAll( + $phpcsFile, + [T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY], + $tokens[$functionPointer]['parenthesis_opener'] + 1, + $tokens[$functionPointer]['parenthesis_closer'] + ); + + if ($modifierPointers === []) { + return; + } + + foreach ($modifierPointers as $modifierPointer) { + $variablePointer = TokenHelper::findNext($phpcsFile, T_VARIABLE, $modifierPointer + 1); + + $phpcsFile->addError( + sprintf( + 'Constructor property promotion is disallowed, promotion of property %s found.', + $tokens[$variablePointer]['content'] + ), + $variablePointer, + self::CODE_DISALLOWED_CONSTRUCTOR_PROPERTY_PROMOTION + ); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowLateStaticBindingForConstantsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowLateStaticBindingForConstantsSniff.php new file mode 100644 index 000000000..2863e0877 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowLateStaticBindingForConstantsSniff.php @@ -0,0 +1,71 @@ + + */ + public function register(): array + { + return [ + T_STATIC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $staticPointer + */ + public function process(File $phpcsFile, $staticPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $doubleColonPointer = TokenHelper::findNextEffective($phpcsFile, $staticPointer + 1); + if ($tokens[$doubleColonPointer]['code'] !== T_DOUBLE_COLON) { + return; + } + + $stringPointer = TokenHelper::findNextEffective($phpcsFile, $doubleColonPointer + 1); + if ($tokens[$stringPointer]['code'] !== T_STRING) { + return; + } + + if (strtolower($tokens[$stringPointer]['content']) === 'class') { + return; + } + + $pointerAfterString = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + if ($tokens[$pointerAfterString]['code'] === T_OPEN_PARENTHESIS) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Late static binding for constants is disallowed.', + $staticPointer, + self::CODE_DISALLOWED_LATE_STATIC_BINDING_FOR_CONSTANT + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($staticPointer, 'self'); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiConstantDefinitionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiConstantDefinitionSniff.php new file mode 100644 index 000000000..73238b08c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiConstantDefinitionSniff.php @@ -0,0 +1,128 @@ + + */ + public function register(): array + { + return [T_CONST]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $constantPointer + */ + public function process(File $phpcsFile, $constantPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $semicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $constantPointer + 1); + $commaPointers = []; + $nextPointer = $constantPointer; + do { + $nextPointer = TokenHelper::findNext($phpcsFile, [T_COMMA, T_OPEN_SHORT_ARRAY], $nextPointer + 1, $semicolonPointer); + + if ($nextPointer === null) { + break; + } + + if ($tokens[$nextPointer]['code'] === T_OPEN_SHORT_ARRAY) { + $nextPointer = $tokens[$nextPointer]['bracket_closer']; + continue; + } + + $commaPointers[] = $nextPointer; + + } while (true); + + if (count($commaPointers) === 0) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use of multi constant definition is disallowed.', + $constantPointer, + self::CODE_DISALLOWED_MULTI_CONSTANT_DEFINITION + ); + if (!$fix) { + return; + } + + $possibleVisibilityPointer = TokenHelper::findPreviousEffective($phpcsFile, $constantPointer - 1); + $visibilityPointer = in_array($tokens[$possibleVisibilityPointer]['code'], Tokens::$scopeModifiers, true) + ? $possibleVisibilityPointer + : null; + $visibility = $visibilityPointer !== null ? $tokens[$possibleVisibilityPointer]['content'] : null; + + $pointerAfterConst = TokenHelper::findNextEffective($phpcsFile, $constantPointer + 1); + $pointerBeforeSemicolon = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1); + + $indentation = IndentationHelper::getIndentation($phpcsFile, $visibilityPointer ?? $constantPointer); + + $docCommentPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $constantPointer); + $docComment = $docCommentPointer !== null + ? trim(TokenHelper::getContent($phpcsFile, $docCommentPointer, $tokens[$docCommentPointer]['comment_closer'])) + : null; + + $data = []; + foreach ($commaPointers as $commaPointer) { + $data[$commaPointer] = [ + 'pointerBeforeComma' => TokenHelper::findPreviousEffective($phpcsFile, $commaPointer - 1), + 'pointerAfterComma' => TokenHelper::findNextEffective($phpcsFile, $commaPointer + 1), + ]; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($constantPointer, ' '); + + FixerHelper::removeBetween($phpcsFile, $constantPointer, $pointerAfterConst); + + foreach ($commaPointers as $commaPointer) { + FixerHelper::removeBetween($phpcsFile, $data[$commaPointer]['pointerBeforeComma'], $commaPointer); + + $phpcsFile->fixer->replaceToken( + $commaPointer, + sprintf( + ';%s%s%s%sconst ', + $phpcsFile->eolChar, + $docComment !== null + ? sprintf('%s%s%s', $indentation, $docComment, $phpcsFile->eolChar) + : '', + $indentation, + $visibility !== null ? sprintf('%s ', $visibility) : '' + ) + ); + + FixerHelper::removeBetween($phpcsFile, $commaPointer, $data[$commaPointer]['pointerAfterComma']); + } + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeSemicolon, $semicolonPointer); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiPropertyDefinitionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiPropertyDefinitionSniff.php new file mode 100644 index 000000000..ed126df5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowMultiPropertyDefinitionSniff.php @@ -0,0 +1,168 @@ + + */ + public function register(): array + { + return [T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $visibilityPointer + */ + public function process(File $phpcsFile, $visibilityPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $asPointer = TokenHelper::findPreviousEffective($phpcsFile, $visibilityPointer - 1); + if ($tokens[$asPointer]['code'] === T_AS) { + return; + } + + $propertyPointer = TokenHelper::findNext($phpcsFile, [T_VARIABLE, T_FUNCTION], $visibilityPointer + 1); + if ( + $propertyPointer === null + || $tokens[$propertyPointer]['code'] !== T_VARIABLE + || !PropertyHelper::isProperty($phpcsFile, $propertyPointer) + ) { + return; + } + + $semicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $propertyPointer + 1); + $commaPointers = []; + $nextPointer = $propertyPointer; + do { + $nextPointer = TokenHelper::findNext($phpcsFile, [T_COMMA, T_OPEN_SHORT_ARRAY, T_ARRAY], $nextPointer + 1, $semicolonPointer); + + if ($nextPointer === null) { + break; + } + + if ($tokens[$nextPointer]['code'] === T_OPEN_SHORT_ARRAY) { + $nextPointer = $tokens[$nextPointer]['bracket_closer']; + continue; + } + + if ($tokens[$nextPointer]['code'] === T_ARRAY) { + $nextPointer = $tokens[$nextPointer]['parenthesis_closer']; + continue; + } + + $commaPointers[] = $nextPointer; + + } while (true); + + if (count($commaPointers) === 0) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use of multi property definition is disallowed.', + $visibilityPointer, + self::CODE_DISALLOWED_MULTI_PROPERTY_DEFINITION + ); + if (!$fix) { + return; + } + + $visibility = $tokens[$visibilityPointer]['content']; + + $pointerAfterVisibility = TokenHelper::findNextEffective($phpcsFile, $visibilityPointer + 1); + $pointerBeforeSemicolon = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1); + + $indentation = IndentationHelper::getIndentation($phpcsFile, $visibilityPointer); + + $nameTokenCodes = TokenHelper::getNameTokenCodes(); + + $typeHint = null; + $typeHintStartPointer = TokenHelper::findNext($phpcsFile, $nameTokenCodes, $visibilityPointer + 1, $propertyPointer); + $typeHintEndPointer = null; + $pointerAfterTypeHint = null; + if ($typeHintStartPointer !== null) { + $typeHintEndPointer = TokenHelper::findNextExcluding($phpcsFile, $nameTokenCodes, $typeHintStartPointer + 1) - 1; + $typeHint = TokenHelper::getContent($phpcsFile, $typeHintStartPointer, $typeHintEndPointer); + + $pointerAfterTypeHint = TokenHelper::findNextEffective($phpcsFile, $typeHintEndPointer + 1); + } + + $docCommentPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $propertyPointer); + $docComment = $docCommentPointer !== null + ? trim(TokenHelper::getContent($phpcsFile, $docCommentPointer, $tokens[$docCommentPointer]['comment_closer'])) + : null; + + $data = []; + foreach ($commaPointers as $commaPointer) { + $data[$commaPointer] = [ + 'pointerBeforeComma' => TokenHelper::findPreviousEffective($phpcsFile, $commaPointer - 1), + 'pointerAfterComma' => TokenHelper::findNextEffective($phpcsFile, $commaPointer + 1), + ]; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($visibilityPointer, ' '); + + FixerHelper::removeBetween($phpcsFile, $visibilityPointer, $pointerAfterVisibility); + + if ($typeHint !== null) { + $phpcsFile->fixer->addContent($typeHintEndPointer, ' '); + FixerHelper::removeBetween($phpcsFile, $typeHintEndPointer, $pointerAfterTypeHint); + } + + foreach ($commaPointers as $commaPointer) { + FixerHelper::removeBetween($phpcsFile, $data[$commaPointer]['pointerBeforeComma'], $commaPointer); + + $phpcsFile->fixer->replaceToken( + $commaPointer, + sprintf( + ';%s%s%s%s%s ', + $phpcsFile->eolChar, + $docComment !== null + ? sprintf('%s%s%s', $indentation, $docComment, $phpcsFile->eolChar) + : '', + $indentation, + $visibility, + $typeHint !== null ? sprintf(' %s', $typeHint) : '' + ) + ); + + FixerHelper::removeBetween($phpcsFile, $commaPointer, $data[$commaPointer]['pointerAfterComma']); + } + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeSemicolon, $semicolonPointer); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowStringExpressionPropertyFetchSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowStringExpressionPropertyFetchSniff.php new file mode 100644 index 000000000..d34e68400 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/DisallowStringExpressionPropertyFetchSniff.php @@ -0,0 +1,84 @@ + + */ + public function register(): array + { + return [T_OBJECT_OPERATOR]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $objectOperatorPointer + */ + public function process(File $phpcsFile, $objectOperatorPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $curlyBracketOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $objectOperatorPointer + 1); + + if ($tokens[$curlyBracketOpenerPointer]['code'] !== T_OPEN_CURLY_BRACKET) { + return; + } + + $curlyBracketCloserPointer = $tokens[$curlyBracketOpenerPointer]['bracket_closer']; + + if (TokenHelper::findNextExcluding( + $phpcsFile, + T_CONSTANT_ENCAPSED_STRING, + $curlyBracketOpenerPointer + 1, + $curlyBracketCloserPointer + ) !== null) { + return; + } + + $pointerAfterCurlyBracketCloser = TokenHelper::findNextEffective($phpcsFile, $curlyBracketCloserPointer + 1); + + if ($tokens[$pointerAfterCurlyBracketCloser]['code'] === T_OPEN_PARENTHESIS) { + return; + } + + if (preg_match( + '~^(["\'])([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\1$~', + $tokens[$curlyBracketOpenerPointer + 1]['content'], + $matches + ) !== 1) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'String expression property fetch is disallowed, use identifier property fetch.', + $curlyBracketOpenerPointer, + self::CODE_DISALLOWED_STRING_EXPRESSION_PROPERTY_FETCH + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $curlyBracketOpenerPointer, $curlyBracketCloserPointer, $matches[2]); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EmptyLinesAroundClassBracesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EmptyLinesAroundClassBracesSniff.php new file mode 100644 index 000000000..160d1d4ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EmptyLinesAroundClassBracesSniff.php @@ -0,0 +1,159 @@ + + */ + public function register(): array + { + return array_values(Tokens::$ooScopeTokens); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPointer + */ + public function process(File $phpcsFile, $stackPointer): void + { + $this->linesCountAfterOpeningBrace = SniffSettingsHelper::normalizeInteger($this->linesCountAfterOpeningBrace); + $this->linesCountBeforeClosingBrace = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeClosingBrace); + + $this->processOpeningBrace($phpcsFile, $stackPointer); + $this->processClosingBrace($phpcsFile, $stackPointer); + } + + private function processOpeningBrace(File $phpcsFile, int $stackPointer): void + { + $tokens = $phpcsFile->getTokens(); + $typeToken = $tokens[$stackPointer]; + $openerPointer = $typeToken['scope_opener']; + $openerToken = $tokens[$openerPointer]; + $nextPointerAfterOpeningBrace = TokenHelper::findNextNonWhitespace($phpcsFile, $openerPointer + 1); + $nextTokenAfterOpeningBrace = $tokens[$nextPointerAfterOpeningBrace]; + $lines = $nextTokenAfterOpeningBrace['line'] - $openerToken['line'] - 1; + + if ($lines === $this->linesCountAfterOpeningBrace) { + return; + } + + if ($this->linesCountAfterOpeningBrace === 1) { + $fix = $phpcsFile->addFixableError( + sprintf('There must be one empty line after %s opening brace.', $typeToken['content']), + $openerPointer, + $lines === 0 + ? self::CODE_NO_EMPTY_LINE_AFTER_OPENING_BRACE + : self::CODE_MULTIPLE_EMPTY_LINES_AFTER_OPENING_BRACE + ); + } else { + $fix = $phpcsFile->addFixableError(sprintf( + 'There must be exactly %d empty lines after %s opening brace.', + $this->linesCountAfterOpeningBrace, + $typeToken['content'] + ), $openerPointer, self::CODE_INCORRECT_EMPTY_LINES_AFTER_OPENING_BRACE); + } + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + if ($lines < $this->linesCountAfterOpeningBrace) { + for ($i = $lines; $i < $this->linesCountAfterOpeningBrace; $i++) { + $phpcsFile->fixer->addNewline($openerPointer); + } + } else { + for ($i = $openerPointer + $this->linesCountAfterOpeningBrace + 2; $i < $nextPointerAfterOpeningBrace; $i++) { + if ($phpcsFile->fixer->getTokenContent($i) !== $phpcsFile->eolChar) { + break; + } + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + $phpcsFile->fixer->endChangeset(); + } + + private function processClosingBrace(File $phpcsFile, int $stackPointer): void + { + $tokens = $phpcsFile->getTokens(); + $typeToken = $tokens[$stackPointer]; + $closerPointer = $typeToken['scope_closer']; + $closerToken = $tokens[$closerPointer]; + $previousPointerBeforeClosingBrace = TokenHelper::findPreviousNonWhitespace($phpcsFile, $closerPointer - 1); + $previousTokenBeforeClosingBrace = $tokens[$previousPointerBeforeClosingBrace]; + $lines = $closerToken['line'] - $previousTokenBeforeClosingBrace['line'] - 1; + + if ($lines === $this->linesCountBeforeClosingBrace) { + return; + } + + if ($this->linesCountBeforeClosingBrace === 1) { + $fix = $phpcsFile->addFixableError( + sprintf('There must be one empty line before %s closing brace.', $typeToken['content']), + $closerPointer, + $lines === 0 + ? self::CODE_NO_EMPTY_LINE_BEFORE_CLOSING_BRACE + : self::CODE_MULTIPLE_EMPTY_LINES_BEFORE_CLOSING_BRACE + ); + } else { + $fix = $phpcsFile->addFixableError(sprintf( + 'There must be exactly %d empty lines before %s closing brace.', + $this->linesCountBeforeClosingBrace, + $typeToken['content'] + ), $closerPointer, self::CODE_INCORRECT_EMPTY_LINES_BEFORE_CLOSING_BRACE); + } + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + if ($lines < $this->linesCountBeforeClosingBrace) { + for ($i = $lines; $i < $this->linesCountBeforeClosingBrace; $i++) { + $phpcsFile->fixer->addNewlineBefore($closerPointer); + } + } else { + FixerHelper::removeBetween( + $phpcsFile, + $previousPointerBeforeClosingBrace + $this->linesCountBeforeClosingBrace + 1, + $closerPointer + ); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EnumCaseSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EnumCaseSpacingSniff.php new file mode 100644 index 000000000..286d6ec27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/EnumCaseSpacingSniff.php @@ -0,0 +1,54 @@ + + */ + public function register(): array + { + return [T_ENUM_CASE]; + } + + protected function isNextMemberValid(File $phpcsFile, int $pointer): bool + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_ENUM_CASE) { + return true; + } + + $nextPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_CONST, T_VARIABLE, T_USE, T_ENUM_CASE], $pointer + 1); + + return $tokens[$nextPointer]['code'] === T_ENUM_CASE; + } + + protected function addError(File $phpcsFile, int $pointer, int $minExpectedLines, int $maxExpectedLines, int $found): bool + { + if ($minExpectedLines === $maxExpectedLines) { + $errorMessage = $minExpectedLines === 1 + ? 'Expected 1 blank line after enum case, found %3$d.' + : 'Expected %2$d blank lines after enum case, found %3$d.'; + } else { + $errorMessage = 'Expected %1$d to %2$d blank lines after enum case, found %3$d.'; + } + $error = sprintf($errorMessage, $minExpectedLines, $maxExpectedLines, $found); + + return $phpcsFile->addFixableError($error, $pointer, self::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_ENUM_CASE); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ForbiddenPublicPropertySniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ForbiddenPublicPropertySniff.php new file mode 100644 index 000000000..58636062b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ForbiddenPublicPropertySniff.php @@ -0,0 +1,77 @@ + + */ + public function register(): array + { + return [T_VARIABLE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $variablePointer + */ + public function process(File $file, $variablePointer): void + { + if (!PropertyHelper::isProperty($file, $variablePointer, $this->checkPromoted)) { + return; + } + + // skip Sniff classes, they have public properties for configuration (unfortunately) + if ($this->isSniffClass($file, $variablePointer)) { + return; + } + + $scopeModifierToken = $this->getPropertyScopeModifier($file, $variablePointer); + if ($scopeModifierToken['code'] === T_PROTECTED || $scopeModifierToken['code'] === T_PRIVATE) { + return; + } + + $errorMessage = 'Do not use public properties. Use method access instead.'; + $file->addError($errorMessage, $variablePointer, self::CODE_FORBIDDEN_PUBLIC_PROPERTY); + } + + private function isSniffClass(File $file, int $position): bool + { + $classTokenPosition = ClassHelper::getClassPointer($file, $position); + $classNameToken = ClassHelper::getName($file, $classTokenPosition); + + return StringHelper::endsWith($classNameToken, 'Sniff'); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint + * @return array{code: int|string} + */ + private function getPropertyScopeModifier(File $file, int $position): array + { + $scopeModifierPosition = TokenHelper::findPrevious($file, array_merge([T_VAR], Tokens::$scopeModifiers), $position - 1); + + return $file->getTokens()[$scopeModifierPosition]; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MethodSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MethodSpacingSniff.php new file mode 100644 index 000000000..afe4c7b0c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MethodSpacingSniff.php @@ -0,0 +1,133 @@ + + */ + public function register(): array + { + return [T_FUNCTION]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $methodPointer + */ + public function process(File $phpcsFile, $methodPointer): void + { + $this->minLinesCount = SniffSettingsHelper::normalizeInteger($this->minLinesCount); + $this->maxLinesCount = SniffSettingsHelper::normalizeInteger($this->maxLinesCount); + + if (!FunctionHelper::isMethod($phpcsFile, $methodPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $methodEndPointer = array_key_exists('scope_closer', $tokens[$methodPointer]) + ? $tokens[$methodPointer]['scope_closer'] + : TokenHelper::findNext($phpcsFile, T_SEMICOLON, $methodPointer + 1); + + $classPointer = ClassHelper::getClassPointer($phpcsFile, $methodPointer); + + $nextMethodPointer = TokenHelper::findNext($phpcsFile, T_FUNCTION, $methodEndPointer + 1, $tokens[$classPointer]['scope_closer']); + if ($nextMethodPointer === null) { + return; + } + + $nextMethodDocCommentStartPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $nextMethodPointer); + if ( + $nextMethodDocCommentStartPointer !== null + && $tokens[$tokens[$nextMethodDocCommentStartPointer]['comment_closer']]['line'] + 1 !== $tokens[$nextMethodPointer]['line'] + ) { + $nextMethodDocCommentStartPointer = null; + } + + $nextMethodFirstLinePointer = $tokens[$nextMethodPointer]['line'] === $tokens[$methodEndPointer]['line'] + ? TokenHelper::findNextEffective($phpcsFile, $methodEndPointer + 1) + : TokenHelper::findFirstTokenOnLine($phpcsFile, $nextMethodDocCommentStartPointer ?? $nextMethodPointer); + + if (TokenHelper::findNextNonWhitespace($phpcsFile, $methodEndPointer + 1, $nextMethodFirstLinePointer) !== null) { + return; + } + + $linesBetween = $tokens[$nextMethodFirstLinePointer]['line'] !== $tokens[$methodEndPointer]['line'] + ? $tokens[$nextMethodFirstLinePointer]['line'] - $tokens[$methodEndPointer]['line'] - 1 + : null; + + if ($linesBetween !== null && $linesBetween >= $this->minLinesCount && $linesBetween <= $this->maxLinesCount) { + return; + } + + if ($this->minLinesCount === $this->maxLinesCount) { + $errorMessage = $this->minLinesCount === 1 + ? 'Expected 1 blank line after method, found %3$d.' + : 'Expected %2$d blank lines after method, found %3$d.'; + } else { + $errorMessage = 'Expected %1$d to %2$d blank lines after method, found %3$d.'; + } + + $fix = $phpcsFile->addFixableError( + sprintf($errorMessage, $this->minLinesCount, $this->maxLinesCount, $linesBetween ?? 0), + $methodPointer, + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_METHODS + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + if ($linesBetween === null) { + $phpcsFile->fixer->addContent( + $methodEndPointer, + $phpcsFile->eolChar . str_repeat($phpcsFile->eolChar, $this->minLinesCount) . IndentationHelper::getIndentation( + $phpcsFile, + TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $methodPointer) + ) + ); + + FixerHelper::removeBetween($phpcsFile, $methodEndPointer, $nextMethodFirstLinePointer); + + } elseif ($linesBetween > $this->maxLinesCount) { + $phpcsFile->fixer->addContent($methodEndPointer, str_repeat($phpcsFile->eolChar, $this->maxLinesCount + 1)); + + $firstPointerOnNextMethodLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $nextMethodFirstLinePointer); + + FixerHelper::removeBetween($phpcsFile, $methodEndPointer, $firstPointerOnNextMethodLine); + } else { + $phpcsFile->fixer->addContent($methodEndPointer, str_repeat($phpcsFile->eolChar, $this->minLinesCount - $linesBetween)); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MissingClassGroupsException.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MissingClassGroupsException.php new file mode 100644 index 000000000..2faddecc9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/MissingClassGroupsException.php @@ -0,0 +1,23 @@ + $groups */ + public function __construct(array $groups) + { + parent::__construct( + sprintf( + 'You need configure all class groups. These groups are missing from your configuration: %s.', + implode(', ', $groups) + ) + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ModernClassNameReferenceSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ModernClassNameReferenceSniff.php new file mode 100644 index 000000000..e58a453db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ModernClassNameReferenceSniff.php @@ -0,0 +1,178 @@ + + */ + public function register(): array + { + $tokens = TokenHelper::getOnlyNameTokenCodes(); + $tokens[] = T_CLASS_C; + + return $tokens; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->enableOnObjects = SniffSettingsHelper::isEnabledByPhpVersion($this->enableOnObjects, 80000); + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_CLASS_C) { + $this->checkMagicConstant($phpcsFile, $pointer); + return; + } + + $this->checkFunctionCall($phpcsFile, $pointer); + } + + private function checkMagicConstant(File $phpcsFile, int $pointer): void + { + $fix = $phpcsFile->addFixableError( + 'Class name referenced via magic constant.', + $pointer, + self::CODE_CLASS_NAME_REFERENCED_VIA_MAGIC_CONSTANT + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($pointer, 'self::class'); + $phpcsFile->fixer->endChangeset(); + } + + private function checkFunctionCall(File $phpcsFile, int $functionPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $functionName = ltrim(strtolower($tokens[$functionPointer]['content']), '\\'); + + $functionNames = [ + 'get_class', + 'get_parent_class', + 'get_called_class', + ]; + + if (!in_array($functionName, $functionNames, true)) { + return; + } + + $openParenthesisPointer = TokenHelper::findNextEffective($phpcsFile, $functionPointer + 1); + if ($tokens[$openParenthesisPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $functionPointer - 1); + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_FUNCTION], true)) { + return; + } + + $parameterPointer = TokenHelper::findNextEffective( + $phpcsFile, + $openParenthesisPointer + 1, + $tokens[$openParenthesisPointer]['parenthesis_closer'] + ); + + $isObjectParameter = static function () use ($phpcsFile, $tokens, $openParenthesisPointer, $parameterPointer): bool { + if ($tokens[$parameterPointer]['code'] !== T_VARIABLE) { + return false; + } + + $pointerAfterParameterPointer = TokenHelper::findNextEffective($phpcsFile, $parameterPointer + 1); + return $pointerAfterParameterPointer === $tokens[$openParenthesisPointer]['parenthesis_closer']; + }; + + $isThisParameter = static function () use ($tokens, $parameterPointer, $isObjectParameter): bool { + if (!$isObjectParameter()) { + return false; + } + + $parameterName = strtolower($tokens[$parameterPointer]['content']); + return $parameterName === '$this'; + }; + + if ($functionName === 'get_class') { + if ($parameterPointer === null) { + $fixedContent = 'self::class'; + } elseif ($isThisParameter()) { + $fixedContent = 'static::class'; + } elseif ($this->enableOnObjects && $isObjectParameter()) { + $fixedContent = sprintf('%s::class', $tokens[$parameterPointer]['content']); + } else { + return; + } + + } elseif ($functionName === 'get_parent_class') { + if ($parameterPointer !== null) { + if (!$isThisParameter()) { + return; + } + + /** @var int $classPointer */ + $classPointer = FunctionHelper::findClassPointer($phpcsFile, $functionPointer); + if (!ClassHelper::isFinal($phpcsFile, $classPointer)) { + return; + } + } + + $fixedContent = 'parent::class'; + } else { + $fixedContent = 'static::class'; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Class name referenced via call of function %s().', $functionName), + $functionPointer, + self::CODE_CLASS_NAME_REFERENCED_VIA_FUNCTION_CALL + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$functionPointer - 1]['code'] === T_NS_SEPARATOR) { + $phpcsFile->fixer->replaceToken($functionPointer - 1, ''); + } + + FixerHelper::change($phpcsFile, $functionPointer, $tokens[$openParenthesisPointer]['parenthesis_closer'], $fixedContent); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ParentCallSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ParentCallSpacingSniff.php new file mode 100644 index 000000000..2755349bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ParentCallSpacingSniff.php @@ -0,0 +1,122 @@ +linesCountBefore = SniffSettingsHelper::normalizeInteger($this->linesCountBefore); + $this->linesCountBeforeFirst = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirst); + $this->linesCountAfter = SniffSettingsHelper::normalizeInteger($this->linesCountAfter); + $this->linesCountAfterLast = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLast); + + $tokens = $phpcsFile->getTokens(); + + if (array_key_exists('nested_parenthesis', $tokens[$parentPointer])) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $parentPointer - 1); + if (in_array($tokens[$previousPointer]['code'], array_merge(Tokens::$castTokens, [T_ASPERAND]), true)) { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } + + $tokensToIgnore = array_merge( + Tokens::$assignmentTokens, + Tokens::$equalityTokens, + Tokens::$booleanOperators, + [T_RETURN, T_YIELD, T_YIELD_FROM, T_COLON, T_STRING_CONCAT, T_INLINE_THEN, T_INLINE_ELSE, T_COALESCE, T_MATCH_ARROW] + ); + if (in_array($tokens[$previousPointer]['code'], $tokensToIgnore, true)) { + return; + } + + $previousShortArrayOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_SHORT_ARRAY, $parentPointer - 1); + if ($previousShortArrayOpenerPointer !== null && $tokens[$previousShortArrayOpenerPointer]['bracket_closer'] > $parentPointer) { + return; + } + + parent::process($phpcsFile, $parentPointer); + } + + /** + * @return list + */ + protected function getSupportedKeywords(): array + { + return [self::KEYWORD_PARENT]; + } + + /** + * @return list + */ + protected function getKeywordsToCheck(): array + { + return [self::KEYWORD_PARENT]; + } + + protected function getLinesCountBefore(): int + { + return $this->linesCountBefore; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + */ + protected function getLinesCountBeforeFirst(File $phpcsFile, int $parentPointer): int + { + return $this->linesCountBeforeFirst; + } + + protected function getLinesCountAfter(): int + { + return $this->linesCountAfter; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + */ + protected function getLinesCountAfterLast(File $phpcsFile, int $parentPointer, int $parentEndPointer): int + { + return $this->linesCountAfterLast; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertyDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertyDeclarationSniff.php new file mode 100644 index 000000000..48dd3ccbf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertyDeclarationSniff.php @@ -0,0 +1,401 @@ +|null */ + public $modifiersOrder = []; + + /** @var bool */ + public $checkPromoted = false; + + /** @var bool */ + public $enableMultipleSpacesBetweenModifiersCheck = false; + + /** @var array>|null */ + private $normalizedModifiersOrder = null; + + /** + * @return array + */ + public function register(): array + { + return TokenHelper::$propertyModifiersTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $modifierPointer + */ + public function process(File $phpcsFile, $modifierPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $asPointer = TokenHelper::findPreviousEffective($phpcsFile, $modifierPointer - 1); + if ($tokens[$asPointer]['code'] === T_AS) { + return; + } + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $modifierPointer + 1); + if (in_array($tokens[$nextPointer]['code'], TokenHelper::$propertyModifiersTokenCodes, true)) { + // We don't want to report the same property twice + return; + } + + if ($tokens[$nextPointer]['code'] === T_DOUBLE_COLON) { + // Ignore static:: + return; + } + + $propertyPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_CONST, T_VARIABLE], $modifierPointer + 1); + + if ($propertyPointer === null || $tokens[$propertyPointer]['code'] !== T_VARIABLE) { + return; + } + + if (!PropertyHelper::isProperty($phpcsFile, $propertyPointer, $this->checkPromoted)) { + return; + } + + $firstModifierPointer = $modifierPointer; + do { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $firstModifierPointer - 1); + if (!in_array($tokens[$previousPointer]['code'], TokenHelper::$propertyModifiersTokenCodes, true)) { + break; + } + + $firstModifierPointer = $previousPointer; + } while (true); + + $this->checkModifiersOrder($phpcsFile, $propertyPointer, $firstModifierPointer, $modifierPointer); + $this->checkSpacesBetweenModifiers($phpcsFile, $propertyPointer, $firstModifierPointer, $modifierPointer); + $this->checkTypeHintSpacing($phpcsFile, $propertyPointer, $modifierPointer); + } + + private function checkModifiersOrder(File $phpcsFile, int $propertyPointer, int $firstModifierPointer, int $lastModifierPointer): void + { + $modifiersPointers = TokenHelper::findNextAll( + $phpcsFile, + TokenHelper::$propertyModifiersTokenCodes, + $firstModifierPointer, + $lastModifierPointer + 1 + ); + + if (count($modifiersPointers) < 2) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $modifiersGroups = $this->getNormalizedModifiersOrder(); + + $expectedModifiersPositions = []; + foreach ($modifiersPointers as $modifierPointer) { + for ($i = 0; $i < count($modifiersGroups); $i++) { + if (in_array($tokens[$modifierPointer]['code'], $modifiersGroups[$i], true)) { + $expectedModifiersPositions[$modifierPointer] = $i; + continue 2; + } + } + + // Modifier position is not defined so add it to the end + $expectedModifiersPositions[$modifierPointer] = count($modifiersGroups); + } + + $error = false; + + for ($i = 1; $i < count($modifiersPointers); $i++) { + for ($j = 0; $j < $i; $j++) { + if ($expectedModifiersPositions[$modifiersPointers[$i]] < $expectedModifiersPositions[$modifiersPointers[$j]]) { + $error = true; + break; + } + } + } + + if (!$error) { + return; + } + + $actualModifiers = array_map(static function (int $modifierPointer) use ($tokens): string { + return $tokens[$modifierPointer]['content']; + }, $modifiersPointers); + $actualModifiersFormatted = implode(' ', $actualModifiers); + + asort($expectedModifiersPositions); + $expectedModifiers = array_map(static function (int $modifierPointer) use ($tokens): string { + return $tokens[$modifierPointer]['content']; + }, array_keys($expectedModifiersPositions)); + $expectedModifiersFormatted = implode(' ', $expectedModifiers); + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Incorrect order of modifiers "%s" of property %s, expected "%s".', + $actualModifiersFormatted, + $tokens[$propertyPointer]['content'], + $expectedModifiersFormatted + ), + $firstModifierPointer, + self::CODE_INCORRECT_ORDER_OF_MODIFIERS + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $firstModifierPointer, $lastModifierPointer, $expectedModifiersFormatted); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkSpacesBetweenModifiers( + File $phpcsFile, + int $propertyPointer, + int $firstModifierPointer, + int $lastModifierPointer + ): void + { + if (!$this->enableMultipleSpacesBetweenModifiersCheck) { + return; + } + + $modifiersPointers = TokenHelper::findNextAll( + $phpcsFile, + TokenHelper::$propertyModifiersTokenCodes, + $firstModifierPointer, + $lastModifierPointer + 1 + ); + + if (count($modifiersPointers) < 2) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $error = false; + for ($i = 0; $i < count($modifiersPointers) - 1; $i++) { + $whitespace = TokenHelper::getContent($phpcsFile, $modifiersPointers[$i] + 1, $modifiersPointers[$i + 1] - 1); + if ($whitespace !== ' ') { + $error = true; + break; + } + } + + if (!$error) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('There must be exactly one space between modifiers of property %s.', $tokens[$propertyPointer]['content']), + $firstModifierPointer, + self::CODE_MULTIPLE_SPACES_BETWEEN_MODIFIERS + ); + if (!$fix) { + return; + } + + $expectedModifiers = array_map(static function (int $modifierPointer) use ($tokens): string { + return $tokens[$modifierPointer]['content']; + }, $modifiersPointers); + $expectedModifiersFormatted = implode(' ', $expectedModifiers); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $firstModifierPointer, $lastModifierPointer, $expectedModifiersFormatted); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkTypeHintSpacing(File $phpcsFile, int $propertyPointer, int $lastModifierPointer): void + { + $typeHintEndPointer = TokenHelper::findPrevious( + $phpcsFile, + TokenHelper::getTypeHintTokenCodes(), + $propertyPointer - 1, + $lastModifierPointer + ); + if ($typeHintEndPointer === null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $typeHintStartPointer = TypeHintHelper::getStartPointer($phpcsFile, $typeHintEndPointer); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $typeHintStartPointer - 1, $lastModifierPointer); + $nullabilitySymbolPointer = $previousPointer !== null && $tokens[$previousPointer]['code'] === T_NULLABLE ? $previousPointer : null; + + $propertyName = $tokens[$propertyPointer]['content']; + + if ($tokens[$lastModifierPointer + 1]['code'] !== T_WHITESPACE) { + $errorMessage = sprintf('There must be exactly one space before type hint nullability symbol of property %s.', $propertyName); + $errorCode = self::CODE_NO_SPACE_BEFORE_NULLABILITY_SYMBOL; + + $fix = $phpcsFile->addFixableError($errorMessage, $typeHintEndPointer, $errorCode); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($lastModifierPointer, ' '); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$lastModifierPointer + 1]['content'] !== ' ') { + if ($nullabilitySymbolPointer !== null) { + $errorMessage = sprintf( + 'There must be exactly one space before type hint nullability symbol of property %s.', + $propertyName + ); + $errorCode = self::CODE_MULTIPLE_SPACES_BEFORE_NULLABILITY_SYMBOL; + } else { + $errorMessage = sprintf('There must be exactly one space before type hint of property %s.', $propertyName); + $errorCode = self::CODE_MULTIPLE_SPACES_BEFORE_TYPE_HINT; + } + + $fix = $phpcsFile->addFixableError($errorMessage, $lastModifierPointer, $errorCode); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($lastModifierPointer + 1, ' '); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[$typeHintEndPointer + 1]['code'] !== T_WHITESPACE) { + $fix = $phpcsFile->addFixableError( + sprintf('There must be exactly one space between type hint and property %s.', $propertyName), + $typeHintEndPointer, + self::CODE_NO_SPACE_BETWEEN_TYPE_HINT_AND_PROPERTY + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($typeHintEndPointer, ' '); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$typeHintEndPointer + 1]['content'] !== ' ') { + $fix = $phpcsFile->addFixableError( + sprintf('There must be exactly one space between type hint and property %s.', $propertyName), + $typeHintEndPointer, + self::CODE_MULTIPLE_SPACES_BETWEEN_TYPE_HINT_AND_PROPERTY + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($typeHintEndPointer + 1, ' '); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($nullabilitySymbolPointer === null) { + return; + } + + if ($nullabilitySymbolPointer + 1 === $typeHintStartPointer) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('There must be no whitespace between type hint nullability symbol and type hint of property %s.', $propertyName), + $typeHintStartPointer, + self::CODE_WHITESPACE_AFTER_NULLABILITY_SYMBOL + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($nullabilitySymbolPointer + 1, ''); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @return array> + */ + private function getNormalizedModifiersOrder(): array + { + if ($this->normalizedModifiersOrder === null) { + $modifiersGroups = SniffSettingsHelper::normalizeArray($this->modifiersOrder); + + if ($modifiersGroups === []) { + $modifiersGroups = [ + 'var, public, protected, private', + 'static, readonly', + ]; + } + + $this->normalizedModifiersOrder = []; + + $mapping = [ + 'var' => T_VAR, + 'public' => T_PUBLIC, + 'protected' => T_PROTECTED, + 'private' => T_PRIVATE, + 'static' => T_STATIC, + 'readonly' => T_READONLY, + ]; + + foreach ($modifiersGroups as $modifiersGroupNo => $modifiersGroup) { + $this->normalizedModifiersOrder[$modifiersGroupNo] = []; + + /** @var list $modifiers */ + $modifiers = preg_split('~\\s*,\\s*~', strtolower($modifiersGroup)); + + foreach ($modifiers as $modifier) { + if (!array_key_exists($modifier, $mapping)) { + throw new UnexpectedValueException(sprintf('Unknown property modifier "%s".', $modifier)); + } + + $this->normalizedModifiersOrder[$modifiersGroupNo][] = $mapping[$modifier]; + } + } + } + + return $this->normalizedModifiersOrder; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertySpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertySpacingSniff.php new file mode 100644 index 000000000..e7adf9697 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/PropertySpacingSniff.php @@ -0,0 +1,87 @@ + + */ + public function register(): array + { + return [T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $asPointer = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + if ($tokens[$asPointer]['code'] === T_AS) { + return $pointer; + } + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + if (in_array($tokens[$nextPointer]['code'], [T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC], true)) { + // We don't want to report the same property twice + return $nextPointer; + } + + $propertyPointer = TokenHelper::findNext($phpcsFile, [T_VARIABLE, T_FUNCTION, T_CONST, T_USE], $pointer + 1); + if ( + $propertyPointer === null + || $tokens[$propertyPointer]['code'] !== T_VARIABLE + || !PropertyHelper::isProperty($phpcsFile, $propertyPointer) + ) { + return $propertyPointer ?? $pointer; + } + + return parent::process($phpcsFile, $propertyPointer); + } + + protected function isNextMemberValid(File $phpcsFile, int $pointer): bool + { + $nextPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_VARIABLE], $pointer + 1); + + return $nextPointer !== null && $phpcsFile->getTokens()[$nextPointer]['code'] === T_VARIABLE; + } + + protected function addError(File $phpcsFile, int $pointer, int $minExpectedLines, int $maxExpectedLines, int $found): bool + { + if ($minExpectedLines === $maxExpectedLines) { + $errorMessage = $minExpectedLines === 1 + ? 'Expected 1 blank line after property, found %3$d.' + : 'Expected %2$d blank lines after property, found %3$d.'; + } else { + $errorMessage = 'Expected %1$d to %2$d blank lines after property, found %3$d.'; + } + $error = sprintf($errorMessage, $minExpectedLines, $maxExpectedLines, $found); + + return $phpcsFile->addFixableError($error, $pointer, self::CODE_INCORRECT_COUNT_OF_BLANK_LINES_AFTER_PROPERTY); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireAbstractOrFinalSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireAbstractOrFinalSniff.php new file mode 100644 index 000000000..6b21041a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireAbstractOrFinalSniff.php @@ -0,0 +1,62 @@ + + */ + public function register(): array + { + return [ + T_CLASS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $classPointer - 1); + + if ($tokens[$previousPointer]['code'] === T_READONLY) { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } + + if (in_array($tokens[$previousPointer]['code'], [T_ABSTRACT, T_FINAL], true)) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'All classes should be declared using either the "abstract" or "final" keyword.', + $classPointer, + self::CODE_NO_ABSTRACT_OR_FINAL + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($classPointer, 'final '); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireConstructorPropertyPromotionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireConstructorPropertyPromotionSniff.php new file mode 100644 index 000000000..d1736c8aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireConstructorPropertyPromotionSniff.php @@ -0,0 +1,398 @@ + + */ + public function register(): array + { + return [T_FUNCTION]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $namePointer = TokenHelper::findNextEffective($phpcsFile, $functionPointer + 1); + + if (strtolower($tokens[$namePointer]['content']) !== '__construct') { + return; + } + + if (FunctionHelper::isAbstract($phpcsFile, $functionPointer)) { + return; + } + + $parameterPointers = $this->getParameterPointers($phpcsFile, $functionPointer); + + if (count($parameterPointers) === 0) { + return; + } + + $parameterWithoutPromotionPointers = []; + foreach ($parameterPointers as $parameterPointer) { + $pointerBefore = TokenHelper::findPrevious($phpcsFile, [T_COMMA, T_OPEN_PARENTHESIS], $parameterPointer - 1); + + $visibilityPointer = TokenHelper::findNextEffective($phpcsFile, $pointerBefore + 1); + + if (in_array($tokens[$visibilityPointer]['code'], Tokens::$scopeModifiers, true)) { + continue; + } + + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $parameterPointer - 1); + + if ($tokens[$pointerBefore]['code'] === T_ELLIPSIS) { + continue; + } + + if ($tokens[$pointerBefore]['code'] === T_BITWISE_AND) { + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $pointerBefore - 1); + } + + if ($tokens[$pointerBefore]['code'] === T_CALLABLE) { + continue; + } + + $parameterWithoutPromotionPointers[] = $parameterPointer; + } + + if (count($parameterWithoutPromotionPointers) === 0) { + return; + } + + /** @var int $classPointer */ + $classPointer = FunctionHelper::findClassPointer($phpcsFile, $functionPointer); + + $propertyPointers = $this->getPropertyPointers($phpcsFile, $classPointer); + + if (count($propertyPointers) === 0) { + return; + } + + foreach ($parameterWithoutPromotionPointers as $parameterPointer) { + $parameterName = $tokens[$parameterPointer]['content']; + + foreach ($propertyPointers as $propertyPointer) { + $propertyName = $tokens[$propertyPointer]['content']; + + if ($parameterName !== $propertyName) { + continue; + } + + if ($this->isPropertyDocCommentUseful($phpcsFile, $propertyPointer)) { + continue; + } + + if ($this->isPropertyWithAttribute($phpcsFile, $propertyPointer)) { + continue; + } + + $propertyTypeHint = PropertyHelper::findTypeHint($phpcsFile, $propertyPointer); + $parameterTypeHint = FunctionHelper::getParametersTypeHints($phpcsFile, $functionPointer)[$parameterName]; + if (!$this->areTypeHintEqual($parameterTypeHint, $propertyTypeHint)) { + continue; + } + + $assignmentPointer = $this->getAssignment($phpcsFile, $functionPointer, $parameterName); + if ($assignmentPointer === null) { + continue; + } + + if ($this->isParameterModifiedBeforeAssignment($phpcsFile, $functionPointer, $parameterName, $assignmentPointer)) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Required promotion of property %s.', $propertyName), + $propertyPointer, + self::CODE_REQUIRED_CONSTRUCTOR_PROPERTY_PROMOTION + ); + + if (!$fix) { + continue; + } + + $propertyDocCommentOpenerPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $propertyPointer); + $pointerBeforeProperty = TokenHelper::findFirstTokenOnLine( + $phpcsFile, + $propertyDocCommentOpenerPointer ?? $propertyPointer + ); + $propertyEndPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $propertyPointer + 1); + + $visibilityPointer = TokenHelper::findPrevious( + $phpcsFile, + Tokens::$scopeModifiers, + $propertyPointer - 1, + $pointerBeforeProperty + ); + $visibility = $tokens[$visibilityPointer]['content']; + + $readonlyPointer = TokenHelper::findPrevious($phpcsFile, T_READONLY, $propertyPointer - 1, $pointerBeforeProperty); + $isReadonly = $readonlyPointer !== null; + + $propertyEqualPointer = TokenHelper::findNext($phpcsFile, T_EQUAL, $propertyPointer + 1, $propertyEndPointer); + $propertyDefaultValue = $propertyEqualPointer !== null + ? trim(TokenHelper::getContent($phpcsFile, $propertyEqualPointer + 1, $propertyEndPointer - 1)) + : null; + + $propertyEndPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $propertyPointer + 1); + $pointerAfterProperty = TokenHelper::findFirstTokenOnLine( + $phpcsFile, + TokenHelper::findNextNonWhitespace($phpcsFile, $propertyEndPointer + 1) + ); + + $pointerBeforeParameterStart = TokenHelper::findPrevious($phpcsFile, [T_COMMA, T_OPEN_PARENTHESIS], $parameterPointer - 1); + $parameterStartPointer = TokenHelper::findNextEffective($phpcsFile, $pointerBeforeParameterStart + 1); + + $parameterEqualPointer = TokenHelper::findNextEffective($phpcsFile, $parameterPointer + 1); + $parameterHasDefaultValue = $tokens[$parameterEqualPointer]['code'] === T_EQUAL; + + $pointerBeforeAssignment = TokenHelper::findFirstTokenOnLine($phpcsFile, $assignmentPointer - 1); + $pointerAfterAssignment = TokenHelper::findLastTokenOnLine($phpcsFile, $assignmentPointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $pointerBeforeProperty, $pointerAfterProperty - 1); + + if ($isReadonly) { + $phpcsFile->fixer->addContentBefore($parameterStartPointer, 'readonly '); + } + + $phpcsFile->fixer->addContentBefore($parameterStartPointer, sprintf('%s ', $visibility)); + + if (!$parameterHasDefaultValue && $propertyDefaultValue !== null) { + $phpcsFile->fixer->addContent($parameterPointer, sprintf(' = %s', $propertyDefaultValue)); + } + + FixerHelper::removeBetweenIncluding($phpcsFile, $pointerBeforeAssignment, $pointerAfterAssignment); + + $phpcsFile->fixer->endChangeset(); + } + } + } + + private function getAssignment(File $phpcsFile, int $constructorPointer, string $parameterName): ?int + { + $tokens = $phpcsFile->getTokens(); + + $parameterNameWithoutDollar = substr($parameterName, 1); + + for ($i = $tokens[$constructorPointer]['scope_opener'] + 1; $i < $tokens[$constructorPointer]['scope_closer']; $i++) { + if ($tokens[$i]['content'] !== '$this') { + continue; + } + + $objectOperatorPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if ($tokens[$objectOperatorPointer]['code'] !== T_OBJECT_OPERATOR) { + continue; + } + + $namePointer = TokenHelper::findNextEffective($phpcsFile, $objectOperatorPointer + 1); + if ($tokens[$namePointer]['content'] !== $parameterNameWithoutDollar) { + continue; + } + + $equalPointer = TokenHelper::findNextEffective($phpcsFile, $namePointer + 1); + if ($tokens[$equalPointer]['code'] !== T_EQUAL) { + continue; + } + + $variablePointer = TokenHelper::findNextEffective($phpcsFile, $equalPointer + 1); + if ($tokens[$variablePointer]['content'] !== $parameterName) { + continue; + } + + $semicolonPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); + if ($tokens[$semicolonPointer]['code'] !== T_SEMICOLON) { + continue; + } + + foreach (array_reverse($tokens[$semicolonPointer]['conditions']) as $conditionTokenCode) { + if (in_array($conditionTokenCode, [T_IF, T_ELSEIF, T_ELSE, T_SWITCH], true)) { + return null; + } + } + + return $i; + } + + return null; + } + + /** + * @return list + */ + private function getParameterPointers(File $phpcsFile, int $functionPointer): array + { + $tokens = $phpcsFile->getTokens(); + return TokenHelper::findNextAll( + $phpcsFile, + T_VARIABLE, + $tokens[$functionPointer]['parenthesis_opener'] + 1, + $tokens[$functionPointer]['parenthesis_closer'] + ); + } + + /** + * @return list + */ + private function getPropertyPointers(File $phpcsFile, int $classPointer): array + { + $tokens = $phpcsFile->getTokens(); + + return array_filter( + TokenHelper::findNextAll( + $phpcsFile, + T_VARIABLE, + $tokens[$classPointer]['scope_opener'] + 1, + $tokens[$classPointer]['scope_closer'] + ), + static function (int $variablePointer) use ($phpcsFile): bool { + return PropertyHelper::isProperty($phpcsFile, $variablePointer); + } + ); + } + + private function isPropertyDocCommentUseful(File $phpcsFile, int $propertyPointer): bool + { + if (DocCommentHelper::hasDocCommentDescription($phpcsFile, $propertyPointer)) { + return true; + } + + foreach (AnnotationHelper::getAnnotations($phpcsFile, $propertyPointer) as $annotation) { + $annotationValue = $annotation->getValue(); + if (!$annotationValue instanceof VarTagValueNode) { + return true; + } + + if ($annotationValue->description !== '') { + return true; + } + } + + return false; + } + + private function isPropertyWithAttribute(File $phpcsFile, int $propertyPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_ATTRIBUTE_END, T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET], + $propertyPointer - 1 + ); + + return $tokens[$previousPointer]['code'] === T_ATTRIBUTE_END; + } + + private function areTypeHintEqual(?TypeHint $parameterTypeHint, ?TypeHint $propertyTypeHint): bool + { + if ($parameterTypeHint === null && $propertyTypeHint === null) { + return true; + } + + if ($parameterTypeHint === null || $propertyTypeHint === null) { + return false; + } + + return $parameterTypeHint->getTypeHint() === $propertyTypeHint->getTypeHint(); + } + + private function isParameterModifiedBeforeAssignment( + File $phpcsFile, + int $functionPointer, + string $parameterName, + int $assignmentPointer + ): bool + { + $tokens = $phpcsFile->getTokens(); + + for ($i = $assignmentPointer - 1; $i > $tokens[$functionPointer]['scope_opener']; $i--) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + if ($tokens[$i]['content'] !== $parameterName) { + continue; + } + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if (in_array($tokens[$nextPointer]['code'], Tokens::$assignmentTokens, true)) { + return true; + } + + if ($tokens[$nextPointer]['code'] === T_INC) { + return true; + } + + $previousPointer = TokenHelper::findNextEffective($phpcsFile, $i - 1); + if ($tokens[$previousPointer]['code'] === T_DEC) { + return true; + } + } + + return false; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireMultiLineMethodSignatureSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireMultiLineMethodSignatureSniff.php new file mode 100644 index 000000000..abac22a86 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireMultiLineMethodSignatureSniff.php @@ -0,0 +1,176 @@ + */ + public $includedMethodPatterns = []; + + /** @var list|null */ + public $includedMethodNormalizedPatterns; + + /** @var list */ + public $excludedMethodPatterns = []; + + /** @var list|null */ + public $excludedMethodNormalizedPatterns; + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $methodPointer + */ + public function process(File $phpcsFile, $methodPointer): void + { + $this->minLineLength = SniffSettingsHelper::normalizeNullableInteger($this->minLineLength); + $this->minParametersCount = SniffSettingsHelper::normalizeNullableInteger($this->minParametersCount); + + if ($this->minLineLength !== null && $this->minParametersCount !== null) { + throw new UnexpectedValueException('Either minLineLength or minParametersCount can be set.'); + } + + // Maintain backward compatibility if no configuration provided + if ($this->minLineLength === null && $this->minParametersCount === null) { + $this->minLineLength = self::DEFAULT_MIN_LINE_LENGTH; + } + + if (!FunctionHelper::isMethod($phpcsFile, $methodPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + [$signatureStartPointer, $signatureEndPointer] = $this->getSignatureStartAndEndPointers($phpcsFile, $methodPointer); + + if ($tokens[$signatureStartPointer]['line'] < $tokens[$signatureEndPointer]['line']) { + return; + } + + $parameters = $phpcsFile->getMethodParameters($methodPointer); + $parametersCount = count($parameters); + if ($parametersCount === 0) { + return; + } + + $signature = $this->getSignature($phpcsFile, $signatureStartPointer, $signatureEndPointer); + $signatureWithoutTabIndentation = $this->getSignatureWithoutTabs($phpcsFile, $signature); + $methodName = FunctionHelper::getName($phpcsFile, $methodPointer); + + if ( + count($this->includedMethodPatterns) !== 0 + && !$this->isMethodNameInPatterns($methodName, $this->getIncludedMethodNormalizedPatterns()) + ) { + return; + } + + if ( + count($this->excludedMethodPatterns) !== 0 + && $this->isMethodNameInPatterns($methodName, $this->getExcludedMethodNormalizedPatterns()) + ) { + return; + } + + if ($this->minLineLength !== null && $this->minLineLength !== 0 && strlen($signatureWithoutTabIndentation) < $this->minLineLength) { + return; + } + + if ($this->minParametersCount !== null && $parametersCount < $this->minParametersCount) { + return; + } + + $error = sprintf('Signature of method "%s" should be split to more lines so each parameter is on its own line.', $methodName); + $fix = $phpcsFile->addFixableError($error, $methodPointer, self::CODE_REQUIRED_MULTI_LINE_SIGNATURE); + if (!$fix) { + return; + } + + $indentation = $tokens[$signatureStartPointer]['content']; + + $phpcsFile->fixer->beginChangeset(); + + foreach ($parameters as $parameter) { + $pointerBeforeParameter = TokenHelper::findPrevious( + $phpcsFile, + T_COMMA, + $parameter['token'] - 1, + $tokens[$methodPointer]['parenthesis_opener'] + ); + if ($pointerBeforeParameter === null) { + $pointerBeforeParameter = $tokens[$methodPointer]['parenthesis_opener']; + } + + $phpcsFile->fixer->addContent($pointerBeforeParameter, $phpcsFile->eolChar . IndentationHelper::addIndentation($indentation)); + + FixerHelper::removeWhitespaceAfter($phpcsFile, $pointerBeforeParameter); + } + + $phpcsFile->fixer->addContentBefore($tokens[$methodPointer]['parenthesis_closer'], $phpcsFile->eolChar . $indentation); + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $normalizedPatterns + */ + private function isMethodNameInPatterns(string $methodName, array $normalizedPatterns): bool + { + foreach ($normalizedPatterns as $pattern) { + if (!SniffSettingsHelper::isValidRegularExpression($pattern)) { + throw new Exception(sprintf('%s is not valid PCRE pattern.', $pattern)); + } + + if (preg_match($pattern, $methodName) !== 0) { + return true; + } + } + + return false; + } + + /** + * @return list + */ + private function getIncludedMethodNormalizedPatterns(): array + { + if ($this->includedMethodNormalizedPatterns === null) { + $this->includedMethodNormalizedPatterns = SniffSettingsHelper::normalizeArray($this->includedMethodPatterns); + } + return $this->includedMethodNormalizedPatterns; + } + + /** + * @return list + */ + private function getExcludedMethodNormalizedPatterns(): array + { + if ($this->excludedMethodNormalizedPatterns === null) { + $this->excludedMethodNormalizedPatterns = SniffSettingsHelper::normalizeArray($this->excludedMethodPatterns); + } + return $this->excludedMethodNormalizedPatterns; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSelfReferenceSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSelfReferenceSniff.php new file mode 100644 index 000000000..50c7b3332 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSelfReferenceSniff.php @@ -0,0 +1,118 @@ + + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $referencedNames = array_merge( + ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer), + ReferencedNameHelper::getAllReferencedNamesInAttributes($phpcsFile, $openTagPointer) + ); + + foreach ($referencedNames as $referencedName) { + if (!$referencedName->isClass()) { + continue; + } + + $anonymousClassPointer = TokenHelper::findPrevious($phpcsFile, T_ANON_CLASS, $referencedName->getStartPointer() - 1); + + if ( + $anonymousClassPointer !== null + && $tokens[$anonymousClassPointer]['scope_closer'] > $referencedName->getEndPointer() + ) { + continue; + } + + $classPointer = ClassHelper::getClassPointer($phpcsFile, $referencedName->getStartPointer()); + if ($classPointer === null) { + continue; + } + + $className = ClassHelper::getFullyQualifiedName($phpcsFile, $classPointer); + + $resolvedName = NamespaceHelper::resolveClassName( + $phpcsFile, + $referencedName->getNameAsReferencedInFile(), + $referencedName->getStartPointer() + ); + + if ($className !== $resolvedName) { + continue; + } + + $fix = $phpcsFile->addFixableError( + '"self" for local reference is required.', + $referencedName->getStartPointer(), + self::CODE_REQUIRED_SELF_REFERENCE + ); + if (!$fix) { + continue; + } + + $inAttribute = $tokens[$referencedName->getStartPointer()]['code'] === T_ATTRIBUTE; + + $phpcsFile->fixer->beginChangeset(); + + if ($inAttribute) { + $attributeContent = TokenHelper::getContent( + $phpcsFile, + $referencedName->getStartPointer(), + $referencedName->getEndPointer() + ); + $fixedAttributeContent = preg_replace( + '~(?<=\W)' . preg_quote($referencedName->getNameAsReferencedInFile(), '~') . '(?=\W)~', + 'self', + $attributeContent + ); + $phpcsFile->fixer->replaceToken($referencedName->getStartPointer(), $fixedAttributeContent); + + } else { + $phpcsFile->fixer->replaceToken($referencedName->getStartPointer(), 'self'); + } + + FixerHelper::removeBetweenIncluding($phpcsFile, $referencedName->getStartPointer() + 1, $referencedName->getEndPointer()); + + $phpcsFile->fixer->endChangeset(); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSingleLineMethodSignatureSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSingleLineMethodSignatureSniff.php new file mode 100644 index 000000000..4a2342ead --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/RequireSingleLineMethodSignatureSniff.php @@ -0,0 +1,130 @@ + */ + public $includedMethodPatterns = []; + + /** @var list|null */ + public $includedMethodNormalizedPatterns; + + /** @var list */ + public $excludedMethodPatterns = []; + + /** @var list|null */ + public $excludedMethodNormalizedPatterns; + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $methodPointer + */ + public function process(File $phpcsFile, $methodPointer): void + { + $this->maxLineLength = SniffSettingsHelper::normalizeInteger($this->maxLineLength); + + if (!FunctionHelper::isMethod($phpcsFile, $methodPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + [$signatureStartPointer, $signatureEndPointer] = $this->getSignatureStartAndEndPointers($phpcsFile, $methodPointer); + + if ($tokens[$signatureStartPointer]['line'] === $tokens[$signatureEndPointer]['line']) { + return; + } + + $signature = $this->getSignature($phpcsFile, $signatureStartPointer, $signatureEndPointer); + $signatureWithoutTabIndentation = $this->getSignatureWithoutTabs($phpcsFile, $signature); + $methodName = FunctionHelper::getName($phpcsFile, $methodPointer); + + if ( + count($this->includedMethodPatterns) !== 0 + && !$this->isMethodNameInPatterns($methodName, $this->getIncludedMethodNormalizedPatterns()) + ) { + return; + } + + if ( + count($this->excludedMethodPatterns) !== 0 + && $this->isMethodNameInPatterns($methodName, $this->getExcludedMethodNormalizedPatterns()) + ) { + return; + } + + if ($this->maxLineLength !== 0 && strlen($signatureWithoutTabIndentation) > $this->maxLineLength) { + return; + } + + $error = sprintf('Signature of method "%s" should be placed on a single line.', $methodName); + $fix = $phpcsFile->addFixableError($error, $methodPointer, self::CODE_REQUIRED_SINGLE_LINE_SIGNATURE); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $signatureStartPointer, $signatureEndPointer, $signature); + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $normalizedPatterns + */ + private function isMethodNameInPatterns(string $methodName, array $normalizedPatterns): bool + { + foreach ($normalizedPatterns as $pattern) { + if (!SniffSettingsHelper::isValidRegularExpression($pattern)) { + throw new Exception(sprintf('%s is not valid PCRE pattern.', $pattern)); + } + + if (preg_match($pattern, $methodName) !== 0) { + return true; + } + } + + return false; + } + + /** + * @return list + */ + private function getIncludedMethodNormalizedPatterns(): array + { + if ($this->includedMethodNormalizedPatterns === null) { + $this->includedMethodNormalizedPatterns = SniffSettingsHelper::normalizeArray($this->includedMethodPatterns); + } + return $this->includedMethodNormalizedPatterns; + } + + /** + * @return list + */ + private function getExcludedMethodNormalizedPatterns(): array + { + if ($this->excludedMethodNormalizedPatterns === null) { + $this->excludedMethodNormalizedPatterns = SniffSettingsHelper::normalizeArray($this->excludedMethodPatterns); + } + return $this->excludedMethodNormalizedPatterns; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousAbstractClassNamingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousAbstractClassNamingSniff.php new file mode 100644 index 000000000..5c5800fb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousAbstractClassNamingSniff.php @@ -0,0 +1,70 @@ + + */ + public function register(): array + { + return [ + T_CLASS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $className = ClassHelper::getName($phpcsFile, $classPointer); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $classPointer - 1); + if ($phpcsFile->getTokens()[$previousPointer]['code'] !== T_ABSTRACT) { + return; + } + + $this->checkPrefix($phpcsFile, $classPointer, $className); + $this->checkSuffix($phpcsFile, $classPointer, $className); + } + + private function checkPrefix(File $phpcsFile, int $classPointer, string $className): void + { + $prefix = substr($className, 0, 8); + + if (strtolower($prefix) !== 'abstract') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous prefix "%s".', $prefix), $classPointer, self::CODE_SUPERFLUOUS_PREFIX); + } + + private function checkSuffix(File $phpcsFile, int $classPointer, string $className): void + { + $suffix = substr($className, -8); + + if (strtolower($suffix) !== 'abstract') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous suffix "%s".', $suffix), $classPointer, self::CODE_SUPERFLUOUS_SUFFIX); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousErrorNamingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousErrorNamingSniff.php new file mode 100644 index 000000000..108c97eae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousErrorNamingSniff.php @@ -0,0 +1,55 @@ + + */ + public function register(): array + { + return [ + T_CLASS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $className = ClassHelper::getName($phpcsFile, $classPointer); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $classPointer - 1); + if ($phpcsFile->getTokens()[$previousPointer]['code'] === T_ABSTRACT) { + return; + } + + if (strtolower($className) === 'error') { + return; + } + + $suffix = substr($className, -5); + if (strtolower($suffix) !== 'error') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous suffix "%s".', $suffix), $classPointer, self::CODE_SUPERFLUOUS_SUFFIX); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousExceptionNamingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousExceptionNamingSniff.php new file mode 100644 index 000000000..5c1d58618 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousExceptionNamingSniff.php @@ -0,0 +1,55 @@ + + */ + public function register(): array + { + return [ + T_CLASS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $className = ClassHelper::getName($phpcsFile, $classPointer); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $classPointer - 1); + if ($phpcsFile->getTokens()[$previousPointer]['code'] === T_ABSTRACT) { + return; + } + + if (strtolower($className) === 'exception') { + return; + } + + $suffix = substr($className, -9); + if (strtolower($suffix) !== 'exception') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous suffix "%s".', $suffix), $classPointer, self::CODE_SUPERFLUOUS_SUFFIX); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousInterfaceNamingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousInterfaceNamingSniff.php new file mode 100644 index 000000000..448d83f5b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousInterfaceNamingSniff.php @@ -0,0 +1,63 @@ + + */ + public function register(): array + { + return [ + T_INTERFACE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $interfacePointer + */ + public function process(File $phpcsFile, $interfacePointer): void + { + $interfaceName = ClassHelper::getName($phpcsFile, $interfacePointer); + + $this->checkPrefix($phpcsFile, $interfacePointer, $interfaceName); + $this->checkSuffix($phpcsFile, $interfacePointer, $interfaceName); + } + + private function checkPrefix(File $phpcsFile, int $interfacePointer, string $interfaceName): void + { + $prefix = substr($interfaceName, 0, 9); + + if (strtolower($prefix) !== 'interface') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous prefix "%s".', $prefix), $interfacePointer, self::CODE_SUPERFLUOUS_PREFIX); + } + + private function checkSuffix(File $phpcsFile, int $interfacePointer, string $interfaceName): void + { + $suffix = substr($interfaceName, -9); + + if (strtolower($suffix) !== 'interface') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous suffix "%s".', $suffix), $interfacePointer, self::CODE_SUPERFLUOUS_SUFFIX); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousTraitNamingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousTraitNamingSniff.php new file mode 100644 index 000000000..22e7ea61b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/SuperfluousTraitNamingSniff.php @@ -0,0 +1,50 @@ + + */ + public function register(): array + { + return [ + T_TRAIT, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $traitPointer + */ + public function process(File $phpcsFile, $traitPointer): void + { + $traitName = ClassHelper::getName($phpcsFile, $traitPointer); + + $this->checkSuffix($phpcsFile, $traitPointer, $traitName); + } + + private function checkSuffix(File $phpcsFile, int $traitPointer, string $traitName): void + { + $suffix = substr($traitName, -5); + + if (strtolower($suffix) !== 'trait') { + return; + } + + $phpcsFile->addError(sprintf('Superfluous suffix "%s".', $suffix), $traitPointer, self::CODE_SUPERFLUOUS_SUFFIX); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseDeclarationSniff.php new file mode 100644 index 000000000..0ed15b4e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseDeclarationSniff.php @@ -0,0 +1,101 @@ + + */ + public function register(): array + { + return [ + T_CLASS, + T_ANON_CLASS, + T_TRAIT, + T_ENUM, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $usePointers = ClassHelper::getTraitUsePointers($phpcsFile, $classPointer); + + foreach ($usePointers as $usePointer) { + $this->checkDeclaration($phpcsFile, $usePointer); + } + } + + private function checkDeclaration(File $phpcsFile, int $usePointer): void + { + $commaPointer = TokenHelper::findNextLocal($phpcsFile, T_COMMA, $usePointer + 1); + if ($commaPointer === null) { + return; + } + + $endPointer = TokenHelper::findNext($phpcsFile, [T_OPEN_CURLY_BRACKET, T_SEMICOLON], $usePointer + 1); + + $tokens = $phpcsFile->getTokens(); + if ($tokens[$endPointer]['code'] === T_OPEN_CURLY_BRACKET) { + $phpcsFile->addError( + 'Multiple traits per use statement are forbidden.', + $usePointer, + self::CODE_MULTIPLE_TRAITS_PER_DECLARATION + ); + return; + } + + $fix = $phpcsFile->addFixableError( + 'Multiple traits per use statement are forbidden.', + $usePointer, + self::CODE_MULTIPLE_TRAITS_PER_DECLARATION + ); + + if (!$fix) { + return; + } + + $indentation = ''; + $currentPointer = $usePointer - 1; + while ( + $tokens[$currentPointer]['code'] === T_WHITESPACE + && $tokens[$currentPointer]['content'] !== $phpcsFile->eolChar + ) { + $indentation .= $tokens[$currentPointer]['content']; + $currentPointer--; + } + + $phpcsFile->fixer->beginChangeset(); + + $otherCommaPointers = TokenHelper::findNextAll($phpcsFile, T_COMMA, $usePointer + 1, $endPointer); + foreach ($otherCommaPointers as $otherCommaPointer) { + $pointerAfterComma = TokenHelper::findNextEffective($phpcsFile, $otherCommaPointer + 1); + + FixerHelper::change($phpcsFile, $otherCommaPointer, $pointerAfterComma - 1, ';' . $phpcsFile->eolChar . $indentation . 'use '); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseSpacingSniff.php new file mode 100644 index 000000000..0a4f4ef71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/TraitUseSpacingSniff.php @@ -0,0 +1,304 @@ + + */ + public function register(): array + { + return [ + T_CLASS, + T_ANON_CLASS, + T_TRAIT, + T_ENUM, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $classPointer + */ + public function process(File $phpcsFile, $classPointer): void + { + $this->linesCountBeforeFirstUse = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirstUse); + $this->linesCountBeforeFirstUseWhenFirstInClass = SniffSettingsHelper::normalizeNullableInteger( + $this->linesCountBeforeFirstUseWhenFirstInClass + ); + $this->linesCountBetweenUses = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenUses); + $this->linesCountAfterLastUse = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLastUse); + $this->linesCountAfterLastUseWhenLastInClass = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLastUseWhenLastInClass); + + $usePointers = ClassHelper::getTraitUsePointers($phpcsFile, $classPointer); + + if (count($usePointers) === 0) { + return; + } + + $this->checkLinesBeforeFirstUse($phpcsFile, $usePointers[0]); + $this->checkLinesAfterLastUse($phpcsFile, $usePointers[count($usePointers) - 1]); + $this->checkLinesBetweenUses($phpcsFile, $usePointers); + } + + private function checkLinesBeforeFirstUse(File $phpcsFile, int $firstUsePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $useStartPointer = $firstUsePointer; + + /** @var int $pointerBeforeFirstUse */ + $pointerBeforeFirstUse = TokenHelper::findPreviousNonWhitespace($phpcsFile, $firstUsePointer - 1); + + if (in_array($tokens[$pointerBeforeFirstUse]['code'], Tokens::$commentTokens, true)) { + $pointerBeforeFirstUse = TokenHelper::findPreviousEffective($phpcsFile, $pointerBeforeFirstUse - 1); + $useStartPointer = TokenHelper::findNext($phpcsFile, Tokens::$commentTokens, $pointerBeforeFirstUse + 1); + } + + $isAtTheStartOfClass = $tokens[$pointerBeforeFirstUse]['code'] === T_OPEN_CURLY_BRACKET; + + $whitespaceBeforeFirstUse = ''; + + if ($pointerBeforeFirstUse + 1 !== $firstUsePointer) { + $whitespaceBeforeFirstUse .= TokenHelper::getContent($phpcsFile, $pointerBeforeFirstUse + 1, $useStartPointer - 1); + } + + $requiredLinesCountBeforeFirstUse = $this->linesCountBeforeFirstUse; + if ( + $isAtTheStartOfClass + && $this->linesCountBeforeFirstUseWhenFirstInClass !== null + ) { + $requiredLinesCountBeforeFirstUse = $this->linesCountBeforeFirstUseWhenFirstInClass; + } + + $actualLinesCountBeforeFirstUse = substr_count($whitespaceBeforeFirstUse, $phpcsFile->eolChar) - 1; + + if ($actualLinesCountBeforeFirstUse === $requiredLinesCountBeforeFirstUse) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s before first use statement, found %d.', + $requiredLinesCountBeforeFirstUse, + $requiredLinesCountBeforeFirstUse === 1 ? '' : 's', + $actualLinesCountBeforeFirstUse + ), + $firstUsePointer, + self::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_USE + ); + + if (!$fix) { + return; + } + + $pointerBeforeIndentation = TokenHelper::findPreviousContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $firstUsePointer, + $pointerBeforeFirstUse + ); + + $phpcsFile->fixer->beginChangeset(); + + if ($pointerBeforeIndentation !== null) { + FixerHelper::removeBetweenIncluding($phpcsFile, $pointerBeforeFirstUse + 1, $pointerBeforeIndentation); + } + for ($i = 0; $i <= $requiredLinesCountBeforeFirstUse; $i++) { + $phpcsFile->fixer->addNewline($pointerBeforeFirstUse); + } + + $phpcsFile->fixer->endChangeset(); + } + + private function checkLinesAfterLastUse(File $phpcsFile, int $lastUsePointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $lastUseEndPointer */ + $lastUseEndPointer = TokenHelper::findNextLocal($phpcsFile, [T_SEMICOLON, T_OPEN_CURLY_BRACKET], $lastUsePointer + 1); + if ($tokens[$lastUseEndPointer]['code'] === T_OPEN_CURLY_BRACKET) { + $lastUseEndPointer = $tokens[$lastUseEndPointer]['bracket_closer']; + } + + $pointerAfterLastUse = TokenHelper::findNextEffective($phpcsFile, $lastUseEndPointer + 1); + $isAtTheEndOfClass = $tokens[$pointerAfterLastUse]['code'] === T_CLOSE_CURLY_BRACKET; + + $whitespaceEnd = TokenHelper::findNextNonWhitespace($phpcsFile, $lastUseEndPointer + 1) - 1; + if ($lastUseEndPointer !== $whitespaceEnd && $tokens[$whitespaceEnd]['content'] !== $phpcsFile->eolChar) { + $lastEolPointer = TokenHelper::findPreviousContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $whitespaceEnd - 1, + $lastUseEndPointer + ); + $whitespaceEnd = $lastEolPointer ?? $lastUseEndPointer; + } + $whitespaceAfterLastUse = TokenHelper::getContent($phpcsFile, $lastUseEndPointer + 1, $whitespaceEnd); + + $requiredLinesCountAfterLastUse = $isAtTheEndOfClass ? $this->linesCountAfterLastUseWhenLastInClass : $this->linesCountAfterLastUse; + $actualLinesCountAfterLastUse = substr_count($whitespaceAfterLastUse, $phpcsFile->eolChar) - 1; + + if ($actualLinesCountAfterLastUse === $requiredLinesCountAfterLastUse) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s after last use statement, found %d.', + $requiredLinesCountAfterLastUse, + $requiredLinesCountAfterLastUse === 1 ? '' : 's', + $actualLinesCountAfterLastUse + ), + $lastUsePointer, + self::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_USE + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $lastUseEndPointer + 1, $whitespaceEnd); + + for ($i = 0; $i <= $requiredLinesCountAfterLastUse; $i++) { + $phpcsFile->fixer->addNewline($lastUseEndPointer); + } + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $usePointers + */ + private function checkLinesBetweenUses(File $phpcsFile, array $usePointers): void + { + if (count($usePointers) === 1) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $previousUsePointer = null; + foreach ($usePointers as $usePointer) { + if ($previousUsePointer === null) { + $previousUsePointer = $usePointer; + continue; + } + + /** @var int $previousUseEndPointer */ + $previousUseEndPointer = TokenHelper::findNextLocal($phpcsFile, [T_SEMICOLON, T_OPEN_CURLY_BRACKET], $previousUsePointer + 1); + if ($tokens[$previousUseEndPointer]['code'] === T_OPEN_CURLY_BRACKET) { + /** @var int $previousUseEndPointer */ + $previousUseEndPointer = $tokens[$previousUseEndPointer]['bracket_closer']; + } + + $useStartPointer = $usePointer; + $pointerBeforeUse = TokenHelper::findPreviousNonWhitespace($phpcsFile, $usePointer - 1); + + if (in_array($tokens[$pointerBeforeUse]['code'], Tokens::$commentTokens, true)) { + $useStartPointer = TokenHelper::findNext( + $phpcsFile, + Tokens::$commentTokens, + TokenHelper::findPreviousEffective($phpcsFile, $pointerBeforeUse - 1) + 1 + ); + } + + $actualLinesCountAfterPreviousUse = $tokens[$useStartPointer]['line'] - $tokens[$previousUseEndPointer]['line'] - 1; + + if ($actualLinesCountAfterPreviousUse === $this->linesCountBetweenUses) { + $previousUsePointer = $usePointer; + continue; + } + + $errorParameters = [ + sprintf( + 'Expected %d line%s between same types of use statement, found %d.', + $this->linesCountBetweenUses, + $this->linesCountBetweenUses === 1 ? '' : 's', + $actualLinesCountAfterPreviousUse + ), + $usePointer, + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_USES, + ]; + + $pointerBeforeUse = TokenHelper::findPreviousEffective($phpcsFile, $usePointer - 1); + + if ($previousUseEndPointer !== $pointerBeforeUse) { + $phpcsFile->addError(...$errorParameters); + $previousUsePointer = $usePointer; + continue; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + $previousUsePointer = $usePointer; + continue; + } + + $pointerBeforeIndentation = TokenHelper::findPreviousContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $usePointer, + $previousUseEndPointer + ); + + $phpcsFile->fixer->beginChangeset(); + if ($pointerBeforeIndentation !== null) { + FixerHelper::removeBetweenIncluding($phpcsFile, $previousUseEndPointer + 1, $pointerBeforeIndentation); + } + for ($i = 0; $i <= $this->linesCountBetweenUses; $i++) { + $phpcsFile->fixer->addNewline($previousUseEndPointer); + } + $phpcsFile->fixer->endChangeset(); + + $previousUsePointer = $usePointer; + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UnsupportedClassGroupException.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UnsupportedClassGroupException.php new file mode 100644 index 000000000..be76e9cb7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/UnsupportedClassGroupException.php @@ -0,0 +1,16 @@ + + */ + public function register(): array + { + return [ + T_STATIC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $staticPointer + */ + public function process(File $phpcsFile, $staticPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $doubleColonPointer = TokenHelper::findNextEffective($phpcsFile, $staticPointer + 1); + if ($tokens[$doubleColonPointer]['code'] !== T_DOUBLE_COLON) { + return; + } + + $classPointer = null; + foreach (array_reverse($tokens[$staticPointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (!in_array($conditionTokenCode, Tokens::$ooScopeTokens, true)) { + continue; + } + + $classPointer = $conditionPointer; + break; + } + + if (!ClassHelper::isFinal($phpcsFile, $classPointer)) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Useless late static binding because class is final.', + $staticPointer, + self::CODE_USELESS_LATE_STATIC_BINDING + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($staticPointer, 'self'); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AbstractRequireOneLineDocComment.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AbstractRequireOneLineDocComment.php new file mode 100644 index 000000000..3c1104618 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AbstractRequireOneLineDocComment.php @@ -0,0 +1,137 @@ + + */ + public function register(): array + { + return [T_DOC_COMMENT_OPEN_TAG]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentStartPointer + */ + public function process(File $phpcsFile, $docCommentStartPointer): void + { + $tokens = $phpcsFile->getTokens(); + + // Only validate properties without description + if (DocCommentHelper::hasDocCommentDescription($phpcsFile, $docCommentStartPointer)) { + return; + } + + $docCommentEndPointer = $tokens[$docCommentStartPointer]['comment_closer']; + $lineDifference = $tokens[$docCommentEndPointer]['line'] - $tokens[$docCommentStartPointer]['line']; + + // Already one-line + if ($lineDifference === 0) { + return; + } + + // Ignore empty lines + $currentLinePointer = $docCommentStartPointer; + do { + $currentLinePointer = TokenHelper::findFirstTokenOnNextLine($phpcsFile, $currentLinePointer); + + if ($currentLinePointer === null || $currentLinePointer >= $docCommentEndPointer) { + break; + } + + $types = [T_DOC_COMMENT_STAR, T_DOC_COMMENT_CLOSE_TAG]; + $startingPointer = TokenHelper::findNext($phpcsFile, $types, $currentLinePointer, $docCommentEndPointer); + + if ($startingPointer === null || $tokens[$startingPointer]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + break; + } + + $nextEffectivePointer = TokenHelper::findNextExcluding( + $phpcsFile, + [T_DOC_COMMENT_WHITESPACE], + $startingPointer + 1, + $docCommentEndPointer + 1 + ); + + if ($tokens[$currentLinePointer]['line'] === $tokens[$nextEffectivePointer]['line']) { + continue; + } + + $lineDifference--; + } while (true); + + // Looks like a compound doc-comment + if ($lineDifference > 2) { + return; + } + + $fix = $this->addError($phpcsFile, $docCommentStartPointer); + if (!$fix) { + return; + } + + $contentStartPointer = TokenHelper::findNextExcluding( + $phpcsFile, + [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ], + $docCommentStartPointer + 1, + $docCommentEndPointer + ); + $contentEndPointer = TokenHelper::findPreviousExcluding( + $phpcsFile, + [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ], + $docCommentEndPointer - 1, + $docCommentStartPointer + ); + + if ($contentStartPointer === null) { + FixerHelper::removeBetween($phpcsFile, $docCommentStartPointer, $docCommentEndPointer); + return; + } + + $phpcsFile->fixer->beginChangeset(); + + for ($i = $docCommentStartPointer + 1; $i < $docCommentEndPointer; $i++) { + if ($i >= $contentStartPointer && $i <= $contentEndPointer) { + if ($i === $contentEndPointer) { + $phpcsFile->fixer->replaceToken($i, rtrim($phpcsFile->fixer->getTokenContent($i), ' ')); + } + + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($contentStartPointer, ' '); + $phpcsFile->fixer->addContentBefore($docCommentEndPointer, ' '); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AnnotationNameSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AnnotationNameSniff.php new file mode 100644 index 000000000..26c223418 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AnnotationNameSniff.php @@ -0,0 +1,299 @@ +|null */ + public $annotations; + + /** @var array|null */ + private $normalizedAnnotations; + + /** + * @return array + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + $correctAnnotationNames = $this->getNormalizedAnnotationNames(); + + foreach ($annotations as $annotation) { + $lowerCasedAnnotationName = strtolower($annotation->getName()); + + if (!array_key_exists($lowerCasedAnnotationName, $correctAnnotationNames)) { + continue; + } + + $correctAnnotationName = $correctAnnotationNames[$lowerCasedAnnotationName]; + + if ($correctAnnotationName === $annotation->getName()) { + continue; + } + + $annotationNameWithoutAtSign = ltrim($annotation->getName(), '@'); + $fullyQualifiedAnnotationName = NamespaceHelper::resolveClassName( + $phpcsFile, + $annotationNameWithoutAtSign, + $annotation->getStartPointer() + ); + + if (NamespaceHelper::normalizeToCanonicalName($fullyQualifiedAnnotationName) !== $annotationNameWithoutAtSign) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Annotation name is incorrect. Expected %s, found %s.', $correctAnnotationName, $annotation->getName()), + $annotation->getStartPointer(), + self::CODE_ANNOTATION_NAME_INCORRECT + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->replaceToken($annotation->getStartPointer(), $correctAnnotationName); + + $phpcsFile->fixer->endChangeset(); + } + + $tokens = $phpcsFile->getTokens(); + + $docCommentContent = TokenHelper::getContent($phpcsFile, $docCommentOpenPointer, $tokens[$docCommentOpenPointer]['comment_closer']); + + if (preg_match_all( + '~\{(' . implode('|', $correctAnnotationNames) . ')\}~i', + $docCommentContent, + $matches, + PREG_OFFSET_CAPTURE + ) === 0) { + return; + } + + foreach ($matches[1] as $match) { + $correctAnnotationName = $correctAnnotationNames[strtolower($match[0])]; + + if ($correctAnnotationName === $match[0]) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Annotation name is incorrect. Expected %s, found %s.', $correctAnnotationName, $match[0]), + $docCommentOpenPointer, + self::CODE_ANNOTATION_NAME_INCORRECT + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + $fixedDocCommentContent = substr($docCommentContent, 0, $match[1]) . $correctAnnotationName . substr( + $docCommentContent, + $match[1] + strlen($match[0]) + ); + + FixerHelper::change( + $phpcsFile, + $docCommentOpenPointer, + $tokens[$docCommentOpenPointer]['comment_closer'], + $fixedDocCommentContent + ); + + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * @return array + */ + private function getNormalizedAnnotationNames(): array + { + if ($this->normalizedAnnotations !== null) { + return $this->normalizedAnnotations; + } + + if ($this->annotations !== null) { + $annotationNames = array_map(static function (string $annotationName): string { + return ltrim($annotationName, '@'); + }, SniffSettingsHelper::normalizeArray($this->annotations)); + } else { + $annotationNames = array_merge(self::STANDARD_ANNOTATIONS, self::PHPUNIT_ANNOTATIONS, self::STATIC_ANALYSIS_ANNOTATIONS); + + foreach (self::STATIC_ANALYSIS_ANNOTATIONS as $annotationName) { + if (strpos($annotationName, 'psalm') === 0) { + continue; + } + + foreach (AnnotationHelper::STATIC_ANALYSIS_PREFIXES as $prefix) { + $annotationNames[] = sprintf('%s-%s', $prefix, $annotationName); + } + } + } + + $annotationNames = array_map(static function (string $annotationName): string { + return '@' . $annotationName; + }, array_unique($annotationNames)); + + $this->normalizedAnnotations = array_combine(array_map(static function (string $annotationName): string { + return strtolower($annotationName); + }, $annotationNames), $annotationNames); + + return $this->normalizedAnnotations; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DeprecatedAnnotationDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DeprecatedAnnotationDeclarationSniff.php new file mode 100644 index 000000000..633403d2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DeprecatedAnnotationDeclarationSniff.php @@ -0,0 +1,50 @@ + */ + public function register(): array + { + return [T_DOC_COMMENT_OPEN_TAG]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentStartPointer + */ + public function process(File $phpcsFile, $docCommentStartPointer): void + { + /** @var list> $annotations */ + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentStartPointer, '@deprecated'); + + if (count($annotations) === 0) { + return; + } + + foreach ($annotations as $annotation) { + if ($annotation->getValue()->description !== '') { + continue; + } + + $phpcsFile->addError( + 'Deprecated annotation must have a description.', + $annotation->getStartPointer(), + self::MISSING_DESCRIPTION + ); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowCommentAfterCodeSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowCommentAfterCodeSniff.php new file mode 100644 index 000000000..b7ae8c53f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowCommentAfterCodeSniff.php @@ -0,0 +1,135 @@ + + */ + public function register(): array + { + /** @phpstan-var array */ + return array_merge(TokenHelper::$inlineCommentTokenCodes, [T_DOC_COMMENT_OPEN_TAG]); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $commentPointer + */ + public function process(File $phpcsFile, $commentPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$commentPointer]['column'] === 1) { + return; + } + + $firstNonWhitespacePointerOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $commentPointer); + + if ($firstNonWhitespacePointerOnLine === $commentPointer) { + return; + } + + if ( + $tokens[$firstNonWhitespacePointerOnLine]['code'] === T_DOC_COMMENT_OPEN_TAG + && $tokens[$firstNonWhitespacePointerOnLine]['comment_closer'] > $commentPointer + ) { + return; + } + + $commentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $commentPointer); + $nextNonWhitespacePointer = TokenHelper::findNextNonWhitespace($phpcsFile, $commentEndPointer + 1); + + if ( + $nextNonWhitespacePointer !== null + && $commentEndPointer !== null + && $tokens[$nextNonWhitespacePointer]['line'] === $tokens[$commentEndPointer]['line'] + + ) { + return; + } + + $fix = $phpcsFile->addFixableError('Comment after code is disallowed.', $commentPointer, self::CODE_DISALLOWED_COMMENT_AFTER_CODE); + if (!$fix) { + return; + } + + $commentContent = TokenHelper::getContent($phpcsFile, $commentPointer, $commentEndPointer); + $commentHasNewLineAtTheEnd = substr($commentContent, -strlen($phpcsFile->eolChar)) === $phpcsFile->eolChar; + + if (!$commentHasNewLineAtTheEnd) { + $commentContent .= $phpcsFile->eolChar; + } + + $firstNonWhiteSpacePointerBeforeComment = TokenHelper::findPreviousNonWhitespace($phpcsFile, $commentPointer - 1); + + $newLineAfterComment = $commentHasNewLineAtTheEnd + ? $commentEndPointer + : TokenHelper::findLastTokenOnLine($phpcsFile, $commentEndPointer); + + $indentation = IndentationHelper::getIndentation($phpcsFile, $firstNonWhitespacePointerOnLine); + $firstPointerOnLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $firstNonWhitespacePointerOnLine); + + $phpcsFile->fixer->beginChangeset(); + + if ( + $tokens[$firstNonWhiteSpacePointerBeforeComment]['code'] === T_OPEN_CURLY_BRACKET + && array_key_exists('scope_condition', $tokens[$firstNonWhiteSpacePointerBeforeComment]) + && in_array( + $tokens[$tokens[$firstNonWhiteSpacePointerBeforeComment]['scope_condition']]['code'], + [T_ELSEIF, T_ELSE, T_CLOSURE], + true + ) + ) { + $phpcsFile->fixer->addContent( + $firstNonWhiteSpacePointerBeforeComment, + $phpcsFile->eolChar . IndentationHelper::addIndentation($indentation) . $commentContent + ); + } elseif ($tokens[$firstNonWhitespacePointerOnLine]['code'] === T_CLOSE_CURLY_BRACKET) { + $phpcsFile->fixer->addContent($firstNonWhiteSpacePointerBeforeComment, $phpcsFile->eolChar . $indentation . $commentContent); + } elseif (isset(Tokens::$stringTokens[$tokens[$firstPointerOnLine]['code']])) { + $prevNonStringToken = TokenHelper::findPreviousExcluding( + $phpcsFile, + [T_WHITESPACE] + Tokens::$stringTokens, + $firstPointerOnLine - 1 + ); + $firstTokenOnNonStringTokenLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $prevNonStringToken); + $firstNonWhitespacePointerOnNonStringTokenLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $prevNonStringToken); + $prevLineIndentation = IndentationHelper::getIndentation($phpcsFile, $firstNonWhitespacePointerOnNonStringTokenLine); + $phpcsFile->fixer->addContentBefore($firstTokenOnNonStringTokenLine, $prevLineIndentation . $commentContent); + $phpcsFile->fixer->addNewline($firstNonWhiteSpacePointerBeforeComment); + } else { + $phpcsFile->fixer->addContentBefore($firstPointerOnLine, $indentation . $commentContent); + $phpcsFile->fixer->addNewline($firstNonWhiteSpacePointerBeforeComment); + } + + FixerHelper::removeBetweenIncluding($phpcsFile, $firstNonWhiteSpacePointerBeforeComment + 1, $newLineAfterComment); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowOneLinePropertyDocCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowOneLinePropertyDocCommentSniff.php new file mode 100644 index 000000000..bbb4e8102 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DisallowOneLinePropertyDocCommentSniff.php @@ -0,0 +1,108 @@ + + */ + public function register(): array + { + return [T_VARIABLE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $propertyPointer + */ + public function process(File $phpcsFile, $propertyPointer): void + { + $tokens = $phpcsFile->getTokens(); + + // Not a property + if (!PropertyHelper::isProperty($phpcsFile, $propertyPointer)) { + return; + } + + // Only validate properties with comment + if (!DocCommentHelper::hasDocComment($phpcsFile, $propertyPointer)) { + return; + } + + /** @var int $docCommentStartPointer */ + $docCommentStartPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $propertyPointer); + $docCommentEndPointer = $tokens[$docCommentStartPointer]['comment_closer']; + $lineDifference = $tokens[$docCommentEndPointer]['line'] - $tokens[$docCommentStartPointer]['line']; + + // Already multi-line + if ($lineDifference !== 0) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Found one-line comment for property %s, use multi-line comment instead.', + PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer) + ), + $docCommentStartPointer, + self::CODE_ONE_LINE_PROPERTY_COMMENT + ); + + if (!$fix) { + return; + } + + $commentWhitespacePointer = TokenHelper::findPrevious($phpcsFile, [T_WHITESPACE], $docCommentStartPointer); + $indent = ($commentWhitespacePointer !== null ? $tokens[$commentWhitespacePointer]['content'] : '') . ' '; + + /** empty comment is not split into start & end tokens properly */ + if ($tokens[$docCommentStartPointer]['content'] === '/***/') { + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->replaceToken($docCommentStartPointer, '/**'); + $phpcsFile->fixer->addNewline($docCommentStartPointer); + $phpcsFile->fixer->addContent($docCommentStartPointer, $indent); + $phpcsFile->fixer->addContent($docCommentStartPointer, '*'); + $phpcsFile->fixer->addNewline($docCommentStartPointer); + $phpcsFile->fixer->addContent($docCommentStartPointer, $indent); + $phpcsFile->fixer->addContent($docCommentStartPointer, '*/'); + + $phpcsFile->fixer->endChangeset(); + + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addNewline($docCommentStartPointer); + $phpcsFile->fixer->addContent($docCommentStartPointer, $indent); + $phpcsFile->fixer->addContent($docCommentStartPointer, '*'); + + if ($docCommentEndPointer - 1 !== $docCommentStartPointer) { + $phpcsFile->fixer->replaceToken( + $docCommentEndPointer - 1, + rtrim($phpcsFile->fixer->getTokenContent($docCommentEndPointer - 1), ' ') + ); + } + + $phpcsFile->fixer->addContentBefore($docCommentEndPointer, $indent); + $phpcsFile->fixer->addNewlineBefore($docCommentEndPointer); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.php new file mode 100644 index 000000000..f2ac58b73 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.php @@ -0,0 +1,781 @@ + */ + public $annotationsGroups = []; + + /** @var array>|null */ + private $normalizedAnnotationsGroups = null; + + /** + * @return array + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenerPointer + */ + public function process(File $phpcsFile, $docCommentOpenerPointer): void + { + $this->linesCountBeforeFirstContent = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirstContent); + $this->linesCountBetweenDescriptionAndAnnotations = SniffSettingsHelper::normalizeInteger( + $this->linesCountBetweenDescriptionAndAnnotations + ); + $this->linesCountBetweenDifferentAnnotationsTypes = SniffSettingsHelper::normalizeInteger( + $this->linesCountBetweenDifferentAnnotationsTypes + ); + $this->linesCountBetweenAnnotationsGroups = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenAnnotationsGroups); + $this->linesCountAfterLastContent = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLastContent); + + if (DocCommentHelper::isInline($phpcsFile, $docCommentOpenerPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (TokenHelper::findNextExcluding( + $phpcsFile, + [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], + $docCommentOpenerPointer + 1, + $tokens[$docCommentOpenerPointer]['comment_closer'] + ) === null) { + return; + } + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenerPointer); + + if ($parsedDocComment === null) { + return; + } + + $firstContentStartPointer = $parsedDocComment->getNodeStartPointer($phpcsFile, $parsedDocComment->getNode()->children[0]); + $firstContentEndPointer = $parsedDocComment->getNodeEndPointer( + $phpcsFile, + $parsedDocComment->getNode()->children[0], + $firstContentStartPointer + ); + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenerPointer); + usort($annotations, static function (Annotation $a, Annotation $b): int { + return $a->getStartPointer() <=> $b->getStartPointer(); + }); + $annotationsCount = count($annotations); + + $firstAnnotationPointer = $annotationsCount > 0 ? $annotations[0]->getStartPointer() : null; + + /** @var int $lastContentEndPointer */ + $lastContentEndPointer = $annotationsCount > 0 + ? $annotations[$annotationsCount - 1]->getEndPointer() + : $firstContentEndPointer; + + $this->checkLinesBeforeFirstContent($phpcsFile, $docCommentOpenerPointer, $firstContentStartPointer); + $this->checkLinesBetweenDescriptionAndFirstAnnotation( + $phpcsFile, + $docCommentOpenerPointer, + $firstContentStartPointer, + $firstContentEndPointer, + $firstAnnotationPointer + ); + + if (count($annotations) > 1) { + if (count($this->getAnnotationsGroups()) === 0) { + $this->checkLinesBetweenDifferentAnnotationsTypes($phpcsFile, $docCommentOpenerPointer, $annotations); + } else { + $this->checkAnnotationsGroups($phpcsFile, $docCommentOpenerPointer, $annotations); + } + } + + $this->checkLinesAfterLastContent( + $phpcsFile, + $docCommentOpenerPointer, + $tokens[$docCommentOpenerPointer]['comment_closer'], + $lastContentEndPointer + ); + } + + private function checkLinesBeforeFirstContent(File $phpcsFile, int $docCommentOpenerPointer, int $firstContentStartPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $whitespaceBeforeFirstContent = substr($tokens[$docCommentOpenerPointer]['content'], 0, strlen('/**')); + $whitespaceBeforeFirstContent .= TokenHelper::getContent($phpcsFile, $docCommentOpenerPointer + 1, $firstContentStartPointer - 1); + + $linesCountBeforeFirstContent = max(substr_count($whitespaceBeforeFirstContent, $phpcsFile->eolChar) - 1, 0); + if ($linesCountBeforeFirstContent === $this->linesCountBeforeFirstContent) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s before first content, found %d.', + $this->linesCountBeforeFirstContent, + $this->linesCountBeforeFirstContent === 1 ? '' : 's', + $linesCountBeforeFirstContent + ), + $firstContentStartPointer, + self::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTENT + ); + + if (!$fix) { + return; + } + + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $docCommentOpenerPointer, $firstContentStartPointer - 1, '/**' . $phpcsFile->eolChar); + + for ($i = 1; $i <= $this->linesCountBeforeFirstContent; $i++) { + $phpcsFile->fixer->addContent($docCommentOpenerPointer, sprintf('%s *%s', $indentation, $phpcsFile->eolChar)); + } + + $phpcsFile->fixer->addContentBefore($firstContentStartPointer, $indentation . ' * '); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkLinesBetweenDescriptionAndFirstAnnotation( + File $phpcsFile, + int $docCommentOpenerPointer, + int $firstContentStartPointer, + int $firstContentEndPointer, + ?int $firstAnnotationPointer + ): void + { + if ($firstAnnotationPointer === null) { + return; + } + + if ($firstContentStartPointer === $firstAnnotationPointer) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + preg_match('~(\\s+)$~', $tokens[$firstContentEndPointer]['content'], $matches); + + $whitespaceBetweenDescriptionAndFirstAnnotation = $matches[1] ?? ''; + $whitespaceBetweenDescriptionAndFirstAnnotation .= TokenHelper::getContent( + $phpcsFile, + $firstContentEndPointer + 1, + $firstAnnotationPointer - 1 + ); + + $linesCountBetweenDescriptionAndAnnotations = max( + substr_count($whitespaceBetweenDescriptionAndFirstAnnotation, $phpcsFile->eolChar) - 1, + 0 + ); + if ($linesCountBetweenDescriptionAndAnnotations === $this->linesCountBetweenDescriptionAndAnnotations) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s between description and annotations, found %d.', + $this->linesCountBetweenDescriptionAndAnnotations, + $this->linesCountBetweenDescriptionAndAnnotations === 1 ? '' : 's', + $linesCountBetweenDescriptionAndAnnotations + ), + $firstAnnotationPointer, + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_DESCRIPTION_AND_ANNOTATIONS + ); + + if (!$fix) { + return; + } + + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer); + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addNewline($firstContentEndPointer); + + FixerHelper::removeBetween($phpcsFile, $firstContentEndPointer, $firstAnnotationPointer); + + for ($i = 1; $i <= $this->linesCountBetweenDescriptionAndAnnotations; $i++) { + $phpcsFile->fixer->addContent($firstContentEndPointer, sprintf('%s *%s', $indentation, $phpcsFile->eolChar)); + } + + $phpcsFile->fixer->addContentBefore($firstAnnotationPointer, $indentation . ' * '); + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $annotations + */ + private function checkLinesBetweenDifferentAnnotationsTypes(File $phpcsFile, int $docCommentOpenerPointer, array $annotations): void + { + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer); + + $previousAnnotation = null; + foreach ($annotations as $annotation) { + if ($previousAnnotation === null) { + $previousAnnotation = $annotation; + continue; + } + + if ($annotation->getName() === $previousAnnotation->getName()) { + $previousAnnotation = $annotation; + continue; + } + + $whitespaceAfterPreviousAnnotation = TokenHelper::getContent( + $phpcsFile, + $previousAnnotation->getEndPointer() + 1, + $annotation->getStartPointer() - 1 + ); + + $linesCountAfterPreviousAnnotation = max(substr_count($whitespaceAfterPreviousAnnotation, $phpcsFile->eolChar) - 1, 0); + + if ($linesCountAfterPreviousAnnotation === $this->linesCountBetweenDifferentAnnotationsTypes) { + $previousAnnotation = $annotation; + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s between different annotations types, found %d.', + $this->linesCountBetweenDifferentAnnotationsTypes, + $this->linesCountBetweenDifferentAnnotationsTypes === 1 ? '' : 's', + $linesCountAfterPreviousAnnotation + ), + $annotation->getStartPointer(), + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_DIFFERENT_ANNOTATIONS_TYPES + ); + + if (!$fix) { + $previousAnnotation = $annotation; + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $previousAnnotation->getEndPointer(), $annotation->getStartPointer()); + + $phpcsFile->fixer->addNewline($previousAnnotation->getEndPointer()); + + for ($i = 1; $i <= $this->linesCountBetweenDifferentAnnotationsTypes; $i++) { + $phpcsFile->fixer->addContent($previousAnnotation->getEndPointer(), sprintf('%s *%s', $indentation, $phpcsFile->eolChar)); + } + + $phpcsFile->fixer->addContentBefore($annotation->getStartPointer(), $indentation . ' * '); + + $phpcsFile->fixer->endChangeset(); + + $previousAnnotation = $annotation; + } + } + + /** + * @param list $annotations + */ + private function checkAnnotationsGroups(File $phpcsFile, int $docCommentOpenerPointer, array $annotations): void + { + $tokens = $phpcsFile->getTokens(); + + $annotationsGroups = []; + $annotationsGroup = []; + $previousAnnotation = null; + foreach ($annotations as $annotation) { + if ( + $previousAnnotation === null + || $tokens[$previousAnnotation->getEndPointer()]['line'] + 1 === $tokens[$annotation->getStartPointer()]['line'] + ) { + $annotationsGroup[] = $annotation; + $previousAnnotation = $annotation; + continue; + } + + $annotationsGroups[] = $annotationsGroup; + $annotationsGroup = [$annotation]; + $previousAnnotation = $annotation; + } + + if (count($annotationsGroup) > 0) { + $annotationsGroups[] = $annotationsGroup; + } + + $this->checkAnnotationsGroupsOrder($phpcsFile, $docCommentOpenerPointer, $annotationsGroups, $annotations); + $this->checkLinesBetweenAnnotationsGroups($phpcsFile, $docCommentOpenerPointer, $annotationsGroups); + } + + /** + * @param list> $annotationsGroups + */ + private function checkLinesBetweenAnnotationsGroups(File $phpcsFile, int $docCommentOpenerPointer, array $annotationsGroups): void + { + $tokens = $phpcsFile->getTokens(); + + $previousAnnotationsGroup = null; + foreach ($annotationsGroups as $annotationsGroup) { + if ($previousAnnotationsGroup === null) { + $previousAnnotationsGroup = $annotationsGroup; + continue; + } + + $lastAnnotationInPreviousGroup = $previousAnnotationsGroup[count($previousAnnotationsGroup) - 1]; + $firstAnnotationInActualGroup = $annotationsGroup[0]; + + $actualLinesCountBetweenAnnotationsGroups = $tokens[$firstAnnotationInActualGroup->getStartPointer()]['line'] - $tokens[$lastAnnotationInPreviousGroup->getEndPointer()]['line'] - 1; + if ($actualLinesCountBetweenAnnotationsGroups === $this->linesCountBetweenAnnotationsGroups) { + $previousAnnotationsGroup = $annotationsGroup; + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s between annotations groups, found %d.', + $this->linesCountBetweenAnnotationsGroups, + $this->linesCountBetweenAnnotationsGroups === 1 ? '' : 's', + $actualLinesCountBetweenAnnotationsGroups + ), + $firstAnnotationInActualGroup->getStartPointer(), + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_ANNOTATIONS_GROUPS + ); + + if (!$fix) { + $previousAnnotationsGroup = $annotationsGroup; + continue; + } + + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer); + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addNewline($lastAnnotationInPreviousGroup->getEndPointer()); + + FixerHelper::removeBetween( + $phpcsFile, + $lastAnnotationInPreviousGroup->getEndPointer(), + $firstAnnotationInActualGroup->getStartPointer() + ); + + for ($i = 1; $i <= $this->linesCountBetweenAnnotationsGroups; $i++) { + $phpcsFile->fixer->addContent( + $lastAnnotationInPreviousGroup->getEndPointer(), + sprintf('%s *%s', $indentation, $phpcsFile->eolChar) + ); + } + + $phpcsFile->fixer->addContentBefore( + $firstAnnotationInActualGroup->getStartPointer(), + $indentation . ' * ' + ); + + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * @param list> $annotationsGroups + * @param list $annotations + */ + private function checkAnnotationsGroupsOrder( + File $phpcsFile, + int $docCommentOpenerPointer, + array $annotationsGroups, + array $annotations + ): void + { + $getAnnotationsPointers = static function (Annotation $annotation): int { + return $annotation->getStartPointer(); + }; + + $equals = static function (array $firstAnnotationsGroup, array $secondAnnotationsGroup) use ($getAnnotationsPointers): bool { + $firstAnnotationsPointers = array_map($getAnnotationsPointers, $firstAnnotationsGroup); + $secondAnnotationsPointers = array_map($getAnnotationsPointers, $secondAnnotationsGroup); + + return count(array_diff($firstAnnotationsPointers, $secondAnnotationsPointers)) === 0 + && count(array_diff($secondAnnotationsPointers, $firstAnnotationsPointers)) === 0; + }; + + $sortedAnnotationsGroups = $this->sortAnnotationsToGroups($annotations); + $incorrectAnnotationsGroupsExist = false; + $annotationsGroupsPositions = []; + + $fix = false; + $undefinedAnnotationsGroups = []; + foreach ($annotationsGroups as $annotationsGroupPosition => $annotationsGroup) { + foreach ($sortedAnnotationsGroups as $sortedAnnotationsGroupPosition => $sortedAnnotationsGroup) { + if ($equals($annotationsGroup, $sortedAnnotationsGroup)) { + $annotationsGroupsPositions[$annotationsGroupPosition] = $sortedAnnotationsGroupPosition; + continue 2; + } + + $undefinedAnnotationsGroup = true; + foreach ($annotationsGroup as $annotation) { + foreach ($this->getAnnotationsGroups() as $annotationNames) { + foreach ($annotationNames as $annotationName) { + if ($this->isAnnotationMatched($annotation, $annotationName)) { + $undefinedAnnotationsGroup = false; + break 3; + } + } + } + } + + if ($undefinedAnnotationsGroup) { + $undefinedAnnotationsGroups[] = $annotationsGroupPosition; + continue 2; + } + } + + $incorrectAnnotationsGroupsExist = true; + + $fix = $phpcsFile->addFixableError( + 'Incorrect annotations group.', + $annotationsGroup[0]->getStartPointer(), + self::CODE_INCORRECT_ANNOTATIONS_GROUP + ); + } + + if (count($annotationsGroupsPositions) === 0 && count($undefinedAnnotationsGroups) > 1) { + $incorrectAnnotationsGroupsExist = true; + + $fix = $phpcsFile->addFixableError( + 'Incorrect annotations group.', + $annotationsGroups[0][0]->getStartPointer(), + self::CODE_INCORRECT_ANNOTATIONS_GROUP + ); + } + + if (!$incorrectAnnotationsGroupsExist) { + foreach ($undefinedAnnotationsGroups as $undefinedAnnotationsGroupPosition) { + $annotationsGroupsPositions[$undefinedAnnotationsGroupPosition] = (count($annotationsGroupsPositions) > 0 + ? max($annotationsGroupsPositions) + : 0) + 1; + } + ksort($annotationsGroupsPositions); + + $positionsMappedToGroups = array_keys($annotationsGroupsPositions); + $tmp = array_values($annotationsGroupsPositions); + asort($tmp); + /** @var list $normalizedAnnotationsGroupsPositions */ + $normalizedAnnotationsGroupsPositions = array_combine(array_keys($positionsMappedToGroups), array_keys($tmp)); + + foreach ($normalizedAnnotationsGroupsPositions as $normalizedAnnotationsGroupPosition => $sortedAnnotationsGroupPosition) { + if ($normalizedAnnotationsGroupPosition === $sortedAnnotationsGroupPosition) { + continue; + } + + $fix = $phpcsFile->addFixableError( + 'Incorrect order of annotations groups.', + $annotationsGroups[$positionsMappedToGroups[$normalizedAnnotationsGroupPosition]][0]->getStartPointer(), + self::CODE_INCORRECT_ORDER_OF_ANNOTATIONS_GROUPS + ); + break; + } + } + + foreach ($annotationsGroups as $annotationsGroupPosition => $annotationsGroup) { + if (!array_key_exists($annotationsGroupPosition, $annotationsGroupsPositions)) { + continue; + } + + if (!array_key_exists($annotationsGroupsPositions[$annotationsGroupPosition], $sortedAnnotationsGroups)) { + continue; + } + + $sortedAnnotationsGroup = $sortedAnnotationsGroups[$annotationsGroupsPositions[$annotationsGroupPosition]]; + + foreach ($annotationsGroup as $annotationPosition => $annotation) { + if ($annotation === $sortedAnnotationsGroup[$annotationPosition]) { + continue; + } + + $fix = $phpcsFile->addFixableError( + 'Incorrect order of annotations in group.', + $annotation->getStartPointer(), + self::CODE_INCORRECT_ORDER_OF_ANNOTATIONS_IN_GROUP + ); + break; + } + } + + if (!$fix) { + return; + } + + $firstAnnotation = $annotationsGroups[0][0]; + $lastAnnotationsGroup = $annotationsGroups[count($annotationsGroups) - 1]; + $lastAnnotation = $lastAnnotationsGroup[count($lastAnnotationsGroup) - 1]; + + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer); + + $fixedAnnotations = ''; + $firstGroup = true; + foreach ($sortedAnnotationsGroups as $sortedAnnotationsGroup) { + if ($firstGroup) { + $firstGroup = false; + } else { + for ($i = 0; $i < $this->linesCountBetweenAnnotationsGroups; $i++) { + $fixedAnnotations .= sprintf('%s *%s', $indentation, $phpcsFile->eolChar); + } + } + + foreach ($sortedAnnotationsGroup as $sortedAnnotation) { + $fixedAnnotations .= sprintf( + '%s * %s%s', + $indentation, + trim(TokenHelper::getContent($phpcsFile, $sortedAnnotation->getStartPointer(), $sortedAnnotation->getEndPointer())), + $phpcsFile->eolChar + ); + } + } + + $tokens = $phpcsFile->getTokens(); + $docCommentCloserPointer = $tokens[$docCommentOpenerPointer]['comment_closer']; + + $endOfLineBeforeFirstAnnotation = TokenHelper::findPreviousContent( + $phpcsFile, + T_DOC_COMMENT_WHITESPACE, + $phpcsFile->eolChar, + $firstAnnotation->getStartPointer() - 1, + $docCommentOpenerPointer + ); + $docCommentContentEndPointer = TokenHelper::findNextContent( + $phpcsFile, + T_DOC_COMMENT_WHITESPACE, + $phpcsFile->eolChar, + $lastAnnotation->getEndPointer() + 1, + $docCommentCloserPointer + ); + + if ($docCommentContentEndPointer === null) { + $docCommentContentEndPointer = $lastAnnotation->getEndPointer(); + } + + $phpcsFile->fixer->beginChangeset(); + + if ($endOfLineBeforeFirstAnnotation === null) { + FixerHelper::change( + $phpcsFile, + $docCommentOpenerPointer, + $docCommentContentEndPointer, + '/**' . $phpcsFile->eolChar . $fixedAnnotations + ); + } else { + FixerHelper::change($phpcsFile, $endOfLineBeforeFirstAnnotation + 1, $docCommentContentEndPointer, $fixedAnnotations); + } + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $annotations + * @return list> + */ + private function sortAnnotationsToGroups(array $annotations): array + { + $expectedAnnotationsGroups = $this->getAnnotationsGroups(); + + $sortedAnnotationsGroups = []; + $annotationsNotInAnyGroup = []; + foreach ($annotations as $annotation) { + foreach ($expectedAnnotationsGroups as $annotationsGroupPosition => $annotationsGroup) { + foreach ($annotationsGroup as $annotationName) { + if ($this->isAnnotationMatched($annotation, $annotationName)) { + $sortedAnnotationsGroups[$annotationsGroupPosition][] = $annotation; + continue 3; + } + } + } + + $annotationsNotInAnyGroup[] = $annotation; + } + + ksort($sortedAnnotationsGroups); + + foreach (array_keys($sortedAnnotationsGroups) as $annotationsGroupPosition) { + $expectedAnnotationsGroupOrder = array_flip($expectedAnnotationsGroups[$annotationsGroupPosition]); + usort( + $sortedAnnotationsGroups[$annotationsGroupPosition], + function (Annotation $firstAnnotation, Annotation $secondAnnotation) use ($expectedAnnotationsGroupOrder): int { + $getExpectedOrder = function (string $annotationName) use ($expectedAnnotationsGroupOrder): int { + if (array_key_exists($annotationName, $expectedAnnotationsGroupOrder)) { + return $expectedAnnotationsGroupOrder[$annotationName]; + } + + $order = 0; + foreach ($expectedAnnotationsGroupOrder as $expectedAnnotationName => $expectedAnnotationOrder) { + if ($this->isAnnotationNameInAnnotationNamespace($expectedAnnotationName, $annotationName)) { + $order = $expectedAnnotationOrder; + break; + } + } + + return $order; + }; + + $expectedOrder = $getExpectedOrder($firstAnnotation->getName()) <=> $getExpectedOrder($secondAnnotation->getName()); + + return $expectedOrder !== 0 + ? $expectedOrder + : $firstAnnotation->getStartPointer() <=> $secondAnnotation->getStartPointer(); + } + ); + } + + if (count($annotationsNotInAnyGroup) > 0) { + $sortedAnnotationsGroups[] = $annotationsNotInAnyGroup; + } + + return $sortedAnnotationsGroups; + } + + private function isAnnotationNameInAnnotationNamespace(string $annotationNamespace, string $annotationName): bool + { + return $this->isAnnotationStartedFrom($annotationNamespace, $annotationName) + || ( + in_array(substr($annotationNamespace, -1), ['\\', '-', ':'], true) + && strpos($annotationName, $annotationNamespace) === 0 + ); + } + + private function isAnnotationStartedFrom(string $annotationNamespace, string $annotationName): bool + { + return substr($annotationNamespace, -1) === '*' + && strpos($annotationName, substr($annotationNamespace, 0, -1)) === 0; + } + + private function isAnnotationMatched(Annotation $annotation, string $annotationName): bool + { + if ($annotation->getName() === $annotationName) { + return true; + } + + return $this->isAnnotationNameInAnnotationNamespace($annotationName, $annotation->getName()); + } + + private function checkLinesAfterLastContent( + File $phpcsFile, + int $docCommentOpenerPointer, + int $docCommentCloserPointer, + int $lastContentEndPointer + ): void + { + $whitespaceAfterLastContent = TokenHelper::getContent($phpcsFile, $lastContentEndPointer + 1, $docCommentCloserPointer); + + $linesCountAfterLastContent = max(substr_count($whitespaceAfterLastContent, $phpcsFile->eolChar) - 1, 0); + if ($linesCountAfterLastContent === $this->linesCountAfterLastContent) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s after last content, found %d.', + $this->linesCountAfterLastContent, + $this->linesCountAfterLastContent === 1 ? '' : 's', + $linesCountAfterLastContent + ), + $lastContentEndPointer, + self::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTENT + ); + + if (!$fix) { + return; + } + + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenerPointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $lastContentEndPointer, $docCommentCloserPointer); + + $phpcsFile->fixer->addNewline($lastContentEndPointer); + + for ($i = 1; $i <= $this->linesCountAfterLastContent; $i++) { + $phpcsFile->fixer->addContent($lastContentEndPointer, sprintf('%s *%s', $indentation, $phpcsFile->eolChar)); + } + + $phpcsFile->fixer->addContentBefore($docCommentCloserPointer, $indentation . ' '); + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @return array> + */ + private function getAnnotationsGroups(): array + { + if ($this->normalizedAnnotationsGroups === null) { + $this->normalizedAnnotationsGroups = []; + foreach ($this->annotationsGroups as $annotationsGroup) { + $this->normalizedAnnotationsGroups[] = SniffSettingsHelper::normalizeArray(explode(',', $annotationsGroup)); + } + } + + return $this->normalizedAnnotationsGroups; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/EmptyCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/EmptyCommentSniff.php new file mode 100644 index 000000000..ad5fda84e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/EmptyCommentSniff.php @@ -0,0 +1,198 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + T_COMMENT, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $commentStartPointer + */ + public function process(File $phpcsFile, $commentStartPointer): void + { + $commentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $commentStartPointer); + + if ($commentEndPointer === null) { + // Part of block comment + return; + } + + $commentContent = $this->getCommentContent($phpcsFile, $commentStartPointer, $commentEndPointer); + + $isLineComment = CommentHelper::isLineComment($phpcsFile, $commentStartPointer); + $isEmpty = $this->isEmpty($commentContent, $isLineComment); + + if (!$isEmpty) { + return; + } + + if ( + $isLineComment + && $this->isPartOfMultiLineInlineComments($phpcsFile, $commentStartPointer, $commentEndPointer) + ) { + return; + } + + $fix = $phpcsFile->addFixableError('Empty comment', $commentStartPointer, self::CODE_EMPTY_COMMENT); + + if (!$fix) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + /** @var int $pointerBeforeWhitespaceBeforeComment */ + $pointerBeforeWhitespaceBeforeComment = TokenHelper::findPreviousNonWhitespace($phpcsFile, $commentStartPointer - 1); + $whitespaceBeforeComment = $pointerBeforeWhitespaceBeforeComment !== $commentStartPointer - 1 + ? TokenHelper::getContent($phpcsFile, $pointerBeforeWhitespaceBeforeComment + 1, $commentStartPointer - 1) + : ''; + $fixedWhitespaceBeforeComment = preg_replace('~[ \\t]+$~', '', $whitespaceBeforeComment); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeWhitespaceBeforeComment, $commentStartPointer); + + $phpcsFile->fixer->addContent($pointerBeforeWhitespaceBeforeComment, $fixedWhitespaceBeforeComment); + + FixerHelper::removeBetweenIncluding($phpcsFile, $commentStartPointer, $commentEndPointer); + + $whitespacePointerAfterComment = $commentEndPointer + 1; + + if ($tokens[$pointerBeforeWhitespaceBeforeComment]['line'] === $tokens[$commentStartPointer]['line']) { + if (StringHelper::endsWith($tokens[$commentEndPointer]['content'], $phpcsFile->eolChar)) { + $phpcsFile->fixer->addNewline($commentEndPointer); + } + } elseif ( + array_key_exists($whitespacePointerAfterComment, $tokens) + && $tokens[$whitespacePointerAfterComment]['code'] === T_WHITESPACE + ) { + $fixedWhitespaceAfterComment = preg_replace( + '~^[ \\t]*' . $phpcsFile->eolChar . '~', + '', + $tokens[$whitespacePointerAfterComment]['content'] + ); + $phpcsFile->fixer->replaceToken($whitespacePointerAfterComment, $fixedWhitespaceAfterComment); + } + + $phpcsFile->fixer->endChangeset(); + } + + private function isEmpty(string $comment, bool $isLineComment): bool + { + return $isLineComment + ? (bool) preg_match('~^\\s*$~', $comment) + : (bool) preg_match('~^[\\s\*]*$~', $comment); + } + + private function getCommentContent(File $phpcsFile, int $commentStartPointer, int $commentEndPointer): string + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$commentStartPointer]['code'] === T_DOC_COMMENT_OPEN_TAG) { + return TokenHelper::getContent($phpcsFile, $commentStartPointer + 1, $commentEndPointer - 1); + } + + if (preg_match('~^(?://|#)(.*)~', $tokens[$commentStartPointer]['content'], $matches) !== 0) { + return $matches[1]; + } + + return substr(TokenHelper::getContent($phpcsFile, $commentStartPointer, $commentEndPointer), 2, -2); + } + + private function isPartOfMultiLineInlineComments(File $phpcsFile, int $commentStartPointer, int $commentEndPointer): bool + { + if (!$this->isNonEmptyLineCommentBefore($phpcsFile, $commentStartPointer)) { + return false; + } + + return $this->isNonEmptyLineCommentAfter($phpcsFile, $commentEndPointer); + } + + private function isNonEmptyLineCommentBefore(File $phpcsFile, int $commentStartPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $beforeCommentStartPointer */ + $beforeCommentStartPointer = TokenHelper::findPreviousNonWhitespace($phpcsFile, $commentStartPointer - 1); + + if ($tokens[$beforeCommentStartPointer]['code'] !== T_COMMENT) { + return false; + } + + if (!CommentHelper::isLineComment($phpcsFile, $beforeCommentStartPointer)) { + return false; + } + + if ($tokens[$beforeCommentStartPointer]['line'] + 1 !== $tokens[$commentStartPointer]['line']) { + return false; + } + + /** @var int $beforeCommentEndPointer */ + $beforeCommentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $beforeCommentStartPointer); + if (!$this->isEmpty($this->getCommentContent($phpcsFile, $beforeCommentStartPointer, $beforeCommentEndPointer), true)) { + return true; + } + + return $this->isNonEmptyLineCommentBefore($phpcsFile, $beforeCommentStartPointer); + } + + private function isNonEmptyLineCommentAfter(File $phpcsFile, int $commentEndPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $afterCommentStartPointer = TokenHelper::findNextNonWhitespace($phpcsFile, $commentEndPointer + 1); + + if ($afterCommentStartPointer === null) { + return false; + } + + if ($tokens[$afterCommentStartPointer]['code'] !== T_COMMENT) { + return false; + } + + if (!CommentHelper::isLineComment($phpcsFile, $afterCommentStartPointer)) { + return false; + } + + if ($tokens[$commentEndPointer]['line'] + 1 !== $tokens[$afterCommentStartPointer]['line']) { + return false; + } + + /** @var int $afterCommentEndPointer */ + $afterCommentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $afterCommentStartPointer); + if (!$this->isEmpty($this->getCommentContent($phpcsFile, $afterCommentStartPointer, $afterCommentEndPointer), true)) { + return true; + } + + return $this->isNonEmptyLineCommentAfter($phpcsFile, $afterCommentEndPointer); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php new file mode 100644 index 000000000..bbce185bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php @@ -0,0 +1,132 @@ + */ + public $forbiddenAnnotations = []; + + /** @var list|null */ + private $normalizedForbiddenAnnotations; + + /** + * @return array + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach ($annotations as $annotation) { + if (!in_array($annotation->getName(), $this->getNormalizedForbiddenAnnotations(), true)) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Use of annotation %s is forbidden.', $annotation->getName()), + $annotation->getStartPointer(), + self::CODE_ANNOTATION_FORBIDDEN + ); + if (!$fix) { + continue; + } + + $starPointer = TokenHelper::findPrevious( + $phpcsFile, + T_DOC_COMMENT_STAR, + $annotation->getStartPointer() - 1, + $docCommentOpenPointer + ); + $annotationStartPointer = $starPointer ?? $annotation->getStartPointer(); + + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNext( + $phpcsFile, + [T_DOC_COMMENT_TAG, T_DOC_COMMENT_CLOSE_TAG], + $annotation->getEndPointer() + 1 + ); + if ($tokens[$nextPointer]['code'] === T_DOC_COMMENT_TAG) { + $nextPointer = TokenHelper::findPrevious($phpcsFile, T_DOC_COMMENT_STAR, $nextPointer - 1); + } + $annotationEndPointer = $nextPointer - 1; + + if ($tokens[$nextPointer]['code'] === T_DOC_COMMENT_CLOSE_TAG && $starPointer !== null) { + $pointerBeforeWhitespace = TokenHelper::findPreviousExcluding( + $phpcsFile, + [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], + $annotationStartPointer - 1 + ); + /** @var int $annotationStartPointer */ + $annotationStartPointer = TokenHelper::findNext($phpcsFile, T_DOC_COMMENT_STAR, $pointerBeforeWhitespace + 1); + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $annotationStartPointer, $annotationEndPointer); + + $docCommentUseful = false; + $docCommentClosePointer = $tokens[$docCommentOpenPointer]['comment_closer']; + for ($i = $docCommentOpenPointer + 1; $i < $docCommentClosePointer; $i++) { + $tokenContent = trim($phpcsFile->fixer->getTokenContent($i)); + if ($tokenContent === '' || $tokenContent === '*') { + continue; + } + + $docCommentUseful = true; + break; + } + + if (!$docCommentUseful) { + /** @var int $nextPointerAfterDocComment */ + $nextPointerAfterDocComment = TokenHelper::findNextEffective($phpcsFile, $docCommentClosePointer + 1); + + FixerHelper::removeBetweenIncluding($phpcsFile, $docCommentOpenPointer, $nextPointerAfterDocComment - 1); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * @return list + */ + private function getNormalizedForbiddenAnnotations(): array + { + if ($this->normalizedForbiddenAnnotations === null) { + $this->normalizedForbiddenAnnotations = SniffSettingsHelper::normalizeArray($this->forbiddenAnnotations); + } + return $this->normalizedForbiddenAnnotations; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenCommentsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenCommentsSniff.php new file mode 100644 index 000000000..f89881ab3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenCommentsSniff.php @@ -0,0 +1,132 @@ + */ + public $forbiddenCommentPatterns = []; + + /** + * @return array + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $comments = DocCommentHelper::getDocCommentDescription($phpcsFile, $docCommentOpenPointer); + + if ($comments === null) { + return; + } + + foreach (SniffSettingsHelper::normalizeArray($this->forbiddenCommentPatterns) as $forbiddenCommentPattern) { + if (!SniffSettingsHelper::isValidRegularExpression($forbiddenCommentPattern)) { + throw new Exception(sprintf('%s is not valid PCRE pattern.', $forbiddenCommentPattern)); + } + + foreach ($comments as $comment) { + if (preg_match($forbiddenCommentPattern, $comment->getContent()) === 0) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Documentation comment contains forbidden comment "%s".', $comment->getContent()), + $comment->getPointer(), + self::CODE_COMMENT_FORBIDDEN + ); + + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + $fixedDocComment = preg_replace($forbiddenCommentPattern, '', $comment->getContent()); + + $phpcsFile->fixer->replaceToken($comment->getPointer(), $fixedDocComment); + + for ($i = $comment->getPointer() - 1; $i > $docCommentOpenPointer; $i--) { + $contentWithoutSpaces = preg_replace('~ +$~', '', $tokens[$i]['content'], -1, $replacedCount); + + if ($replacedCount === 0) { + break; + } + + $phpcsFile->fixer->replaceToken($i, $contentWithoutSpaces); + } + + $docCommentContent = ''; + for ($i = $docCommentOpenPointer + 1; $i < $tokens[$docCommentOpenPointer]['comment_closer']; $i++) { + /** @var string|array<(string|int)> $token */ + $token = $phpcsFile->fixer->getTokenContent($i); + $docCommentContent .= is_array($token) ? $token['content'] : $token; + } + + if (preg_match('~^[\\s\*]*$~', $docCommentContent) !== 0) { + $pointerBeforeDocComment = $docCommentOpenPointer - 1; + $contentBeforeWithoutSpaces = preg_replace( + '~[\t ]+$~', + '', + $tokens[$pointerBeforeDocComment]['content'], + -1, + $replacedCount + ); + if ($replacedCount !== 0) { + $phpcsFile->fixer->replaceToken($pointerBeforeDocComment, $contentBeforeWithoutSpaces); + } + + FixerHelper::removeBetweenIncluding( + $phpcsFile, + $docCommentOpenPointer, + $tokens[$docCommentOpenPointer]['comment_closer'] + ); + + $pointerAfterDocComment = $tokens[$docCommentOpenPointer]['comment_closer'] + 1; + if (array_key_exists($pointerAfterDocComment, $tokens)) { + $contentAfterWithoutSpaces = preg_replace( + '~^[\r\n]+~', + '', + $tokens[$pointerAfterDocComment]['content'], + -1, + $replacedCount + ); + if ($replacedCount !== 0) { + $phpcsFile->fixer->replaceToken($pointerAfterDocComment, $contentAfterWithoutSpaces); + } + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/InlineDocCommentDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/InlineDocCommentDeclarationSniff.php new file mode 100644 index 000000000..1ce816b11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/InlineDocCommentDeclarationSniff.php @@ -0,0 +1,495 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + T_COMMENT, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $commentOpenPointer + */ + public function process(File $phpcsFile, $commentOpenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $commentClosePointer = $tokens[$commentOpenPointer]['code'] === T_COMMENT + ? $commentOpenPointer + : $tokens[$commentOpenPointer]['comment_closer']; + + $pointerAfterCommentClosePointer = TokenHelper::findNextEffective($phpcsFile, $commentClosePointer + 1); + if ($pointerAfterCommentClosePointer !== null) { + do { + if ($tokens[$pointerAfterCommentClosePointer]['code'] !== T_ATTRIBUTE) { + break; + } + + $pointerAfterCommentClosePointer = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$pointerAfterCommentClosePointer]['attribute_closer'] + 1 + ); + } while (true); + + if (in_array( + $tokens[$pointerAfterCommentClosePointer]['code'], + [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_READONLY, T_FINAL, T_CONST], + true + )) { + return; + } + + if ($tokens[$pointerAfterCommentClosePointer]['code'] === T_STATIC) { + $pointerAfterStatic = TokenHelper::findNextEffective($phpcsFile, $pointerAfterCommentClosePointer + 1); + if (in_array($tokens[$pointerAfterStatic]['code'], [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_READONLY], true)) { + return; + } + + if ($tokens[$pointerAfterStatic]['code'] === T_VARIABLE && PropertyHelper::isProperty($phpcsFile, $pointerAfterStatic)) { + return; + } + } + } + + if ($tokens[$commentOpenPointer]['code'] === T_COMMENT) { + $this->checkCommentType($phpcsFile, $commentOpenPointer); + return; + } + + /** @var list> $annotations */ + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $commentOpenPointer, '@var'); + + if ($annotations === []) { + return; + } + + if ($this->allowDocCommentAboveReturn) { + $pointerAfterCommentClosePointer = TokenHelper::findNextEffective($phpcsFile, $commentClosePointer + 1); + if ($tokens[$pointerAfterCommentClosePointer]['code'] === T_RETURN) { + return; + } + } + + $this->checkFormat($phpcsFile, $annotations); + $this->checkVariable($phpcsFile, $annotations, $commentOpenPointer, $commentClosePointer); + } + + private function checkCommentType(File $phpcsFile, int $commentOpenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match('~^/\*\\s*@var\\s+~', $tokens[$commentOpenPointer]['content']) === 0) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Invalid comment type /* */ for inline documentation comment, use /** */.', + $commentOpenPointer, + self::CODE_INVALID_COMMENT_TYPE + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($commentOpenPointer, sprintf('/**%s', substr($tokens[$commentOpenPointer]['content'], 2))); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list> $annotations + */ + private function checkFormat(File $phpcsFile, array $annotations): void + { + foreach ($annotations as $annotation) { + if (!$annotation->isInvalid() && $annotation->getValue()->variableName !== '') { + continue; + } + + $variableName = '$variableName'; + + $annotationContent = (string) $annotation->getValue(); + + $type = null; + + if ( + $annotationContent !== '' + && preg_match('~(\$\w+)(?:\s+(.+))?$~i', $annotationContent, $matches) === 1 + ) { + $variableName = $matches[1]; + $type = $matches[2] ?? null; + } + + // It may be description when it contains whitespaces + $isFixable = $type !== null && preg_match('~\s~', $type) === 0; + + if (!$isFixable) { + $phpcsFile->addError( + sprintf( + 'Invalid inline documentation comment format "@var %1$s", expected "@var type %2$s Optional description".', + $annotationContent, + $variableName + ), + $annotation->getStartPointer(), + self::CODE_INVALID_FORMAT + ); + + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Invalid inline documentation comment format "@var %1$s", expected "@var %2$s %3$s".', + $annotationContent, + $type, + $variableName + ), + $annotation->getStartPointer(), + self::CODE_INVALID_FORMAT + ); + + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent( + $annotation->getStartPointer(), + sprintf( + ' %s %s ', + $type, + $variableName + ) + ); + + FixerHelper::removeBetweenIncluding($phpcsFile, $annotation->getStartPointer() + 1, $annotation->getEndPointer()); + + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * @param list> $annotations + */ + private function checkVariable(File $phpcsFile, array $annotations, int $docCommentOpenerPointer, int $docCommentCloserPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $checkedTokens = [T_VARIABLE, T_FOREACH, T_WHILE, T_LIST, T_OPEN_SHORT_ARRAY, T_CLOSURE, T_FN]; + + $variableNames = []; + + foreach ($annotations as $variableAnnotation) { + if ($variableAnnotation->isInvalid()) { + continue; + } + + $variableName = $variableAnnotation->getValue()->variableName; + if ($variableName === '') { + continue; + } + + $variableNames[] = $variableName; + } + + $improveCodePointer = function (int $codePointer) use ($phpcsFile, $tokens, $checkedTokens, $variableNames): int { + $shouldSearchClosure = false; + + if (!in_array($tokens[$codePointer]['code'], $checkedTokens, true)) { + $shouldSearchClosure = true; + } elseif ( + $tokens[$codePointer]['code'] === T_VARIABLE + && ( + !$this->isAssignment($phpcsFile, $codePointer) + || !in_array($tokens[$codePointer]['content'], $variableNames, true) + ) + ) { + $shouldSearchClosure = true; + } + + if (!$shouldSearchClosure) { + return $codePointer; + } + + $closurePointer = TokenHelper::findNext($phpcsFile, [T_CLOSURE, T_FN], $codePointer + 1); + if ($closurePointer !== null && $tokens[$codePointer]['line'] === $tokens[$closurePointer]['line']) { + return $closurePointer; + } + + return $codePointer; + }; + + $firstPointerOnNextLine = TokenHelper::findFirstNonWhitespaceOnNextLine($phpcsFile, $docCommentCloserPointer); + + $codePointerAfter = $firstPointerOnNextLine; + while ($codePointerAfter !== null && $tokens[$codePointerAfter]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $codePointerAfter = TokenHelper::findFirstNonWhitespaceOnNextLine($phpcsFile, $codePointerAfter + 1); + } + + if ($codePointerAfter !== null) { + if ($tokens[$codePointerAfter]['code'] === T_STATIC) { + $codePointerAfter = TokenHelper::findNextEffective($phpcsFile, $codePointerAfter + 1); + } + + $codePointerAfter = $improveCodePointer($codePointerAfter); + } + + $codePointerBefore = TokenHelper::findFirstNonWhitespaceOnPreviousLine($phpcsFile, $docCommentOpenerPointer); + while ($codePointerBefore !== null && $tokens[$codePointerBefore]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $codePointerBefore = TokenHelper::findFirstNonWhitespaceOnPreviousLine($phpcsFile, $codePointerBefore - 1); + } + + if ($codePointerBefore !== null) { + $codePointerBefore = $improveCodePointer($codePointerBefore); + } + + foreach ($annotations as $variableAnnotation) { + if ($variableAnnotation->isInvalid()) { + continue; + } + + $variableName = $variableAnnotation->getValue()->variableName; + if ($variableName === '') { + continue; + } + + $missingVariableErrorParameters = [ + sprintf('Missing variable %s before or after the documentation comment.', $variableName), + $docCommentOpenerPointer, + self::CODE_MISSING_VARIABLE, + ]; + + $noAssignmentErrorParameters = [ + sprintf('No assignment to %s variable before or after the documentation comment.', $variableName), + $docCommentOpenerPointer, + self::CODE_NO_ASSIGNMENT, + ]; + + if ($this->allowAboveNonAssignment && $firstPointerOnNextLine !== null) { + for ($i = $firstPointerOnNextLine; $i < count($tokens); $i++) { + if ($tokens[$i]['line'] > $tokens[$firstPointerOnNextLine]['line']) { + break; + } + + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + if ($tokens[$i]['content'] === $variableName) { + return; + } + } + } + + foreach ([1 => $codePointerBefore, 2 => $codePointerAfter] as $tryNo => $codePointer) { + if ($codePointer === null || !in_array($tokens[$codePointer]['code'], $checkedTokens, true)) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + + if ($tokens[$codePointer]['code'] === T_VARIABLE) { + if ($tokens[$codePointer]['content'] !== '$this' && !$this->isAssignment($phpcsFile, $codePointer)) { + if ($tryNo === 2) { + $phpcsFile->addError(...$noAssignmentErrorParameters); + } + + continue; + } + + if ($variableName !== $tokens[$codePointer]['content']) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + } elseif ($tokens[$codePointer]['code'] === T_LIST) { + $listParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $codePointer + 1); + + $variablePointerInList = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $listParenthesisOpener + 1, + $tokens[$listParenthesisOpener]['parenthesis_closer'] + ); + if ($variablePointerInList === null) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + + } elseif ($tokens[$codePointer]['code'] === T_OPEN_SHORT_ARRAY) { + $pointerAfterList = TokenHelper::findNextEffective($phpcsFile, $tokens[$codePointer]['bracket_closer'] + 1); + if ($tokens[$pointerAfterList]['code'] !== T_EQUAL) { + if ($tryNo === 2) { + $phpcsFile->addError(...$noAssignmentErrorParameters); + } + + continue; + } + + $variablePointerInList = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $codePointer + 1, + $tokens[$codePointer]['bracket_closer'] + ); + if ($variablePointerInList === null) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + + } elseif (in_array($tokens[$codePointer]['code'], [T_CLOSURE, T_FN], true)) { + $parameterPointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $tokens[$codePointer]['parenthesis_opener'] + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + if ($parameterPointer === null) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + + } else { + if ($tokens[$codePointer]['code'] === T_WHILE) { + $variablePointerInWhile = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $tokens[$codePointer]['parenthesis_opener'] + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + if ($variablePointerInWhile === null) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + + $pointerAfterVariableInWhile = TokenHelper::findNextEffective($phpcsFile, $variablePointerInWhile + 1); + if ($tokens[$pointerAfterVariableInWhile]['code'] !== T_EQUAL) { + if ($tryNo === 2) { + $phpcsFile->addError(...$noAssignmentErrorParameters); + } + + continue; + } + } else { + $asPointer = TokenHelper::findNext( + $phpcsFile, + T_AS, + $tokens[$codePointer]['parenthesis_opener'] + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + $variablePointerInForeach = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $asPointer + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + if ($variablePointerInForeach === null) { + if ($tryNo === 2) { + $phpcsFile->addError(...$missingVariableErrorParameters); + } + + continue; + } + } + } + + // No error, don't check second $codePointer + continue 2; + } + } + } + + private function isAssignment(File $phpcsFile, int $pointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + if ($tokens[$pointerAfterVariable]['code'] === T_SEMICOLON) { + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + return $tokens[$pointerBeforeVariable]['code'] === T_STATIC; + } + + return in_array($tokens[$pointerAfterVariable]['code'], [T_EQUAL, T_COALESCE_EQUAL], true); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLineDocCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLineDocCommentSniff.php new file mode 100644 index 000000000..3b19cf1cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLineDocCommentSniff.php @@ -0,0 +1,19 @@ +addFixableError($error, $docCommentStartPointer, self::CODE_MULTI_LINE_DOC_COMMENT); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLinePropertyDocCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLinePropertyDocCommentSniff.php new file mode 100644 index 000000000..0c04e2d20 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/RequireOneLinePropertyDocCommentSniff.php @@ -0,0 +1,61 @@ +findNext(T_VARIABLE, $docCommentStartPointer); + + return $phpcsFile->addFixableError( + sprintf($error, PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer)), + $docCommentStartPointer, + self::CODE_MULTI_LINE_PROPERTY_COMMENT + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessFunctionDocCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessFunctionDocCommentSniff.php new file mode 100644 index 000000000..502b058ec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessFunctionDocCommentSniff.php @@ -0,0 +1,143 @@ + */ + public $traversableTypeHints = []; + + /** @var array|null */ + private $normalizedTraversableTypeHints; + + /** + * @return array + */ + public function register(): array + { + return [ + T_FUNCTION, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + if (!DocCommentHelper::hasDocComment($phpcsFile, $functionPointer)) { + return; + } + + if (DocCommentHelper::hasInheritdocAnnotation($phpcsFile, $functionPointer)) { + return; + } + + if (DocCommentHelper::hasDocCommentDescription($phpcsFile, $functionPointer)) { + return; + } + + $returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $functionPointer); + $returnAnnotation = FunctionHelper::findReturnAnnotation($phpcsFile, $functionPointer); + + if ( + $returnAnnotation !== null + && !AnnotationHelper::isAnnotationUseless( + $phpcsFile, + $functionPointer, + $returnTypeHint, + $returnAnnotation, + $this->getTraversableTypeHints() + ) + ) { + return; + } + + $parameterTypeHints = FunctionHelper::getParametersTypeHints($phpcsFile, $functionPointer); + $parametersAnnotations = FunctionHelper::getValidParametersAnnotations($phpcsFile, $functionPointer); + + foreach ($parametersAnnotations as $parameterName => $parameterAnnotation) { + if (!array_key_exists($parameterName, $parameterTypeHints)) { + return; + } + + if (!AnnotationHelper::isAnnotationUseless( + $phpcsFile, + $functionPointer, + $parameterTypeHints[$parameterName], + $parameterAnnotation, + $this->getTraversableTypeHints() + )) { + return; + } + } + + foreach (AnnotationHelper::getAnnotations($phpcsFile, $functionPointer) as $annotation) { + if (!in_array($annotation->getName(), ['@param', '@return'], true)) { + return; + } + } + + $fix = $phpcsFile->addFixableError( + sprintf( + '%s %s() does not need documentation comment.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer) + ), + $functionPointer, + self::CODE_USELESS_DOC_COMMENT + ); + if (!$fix) { + return; + } + + /** @var int $docCommentOpenPointer */ + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $functionPointer); + $docCommentClosePointer = $phpcsFile->getTokens()[$docCommentOpenPointer]['comment_closer']; + + $changeStart = $docCommentOpenPointer; + /** @var int $changeEnd */ + $changeEnd = TokenHelper::findNextEffective($phpcsFile, $docCommentClosePointer + 1) - 1; + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $changeStart, $changeEnd); + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @return array + */ + private function getTraversableTypeHints(): array + { + if ($this->normalizedTraversableTypeHints === null) { + $this->normalizedTraversableTypeHints = array_map(static function (string $typeHint): string { + return NamespaceHelper::isFullyQualifiedName($typeHint) + ? $typeHint + : sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $typeHint); + }, SniffSettingsHelper::normalizeArray($this->traversableTypeHints)); + } + return $this->normalizedTraversableTypeHints; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessInheritDocCommentSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessInheritDocCommentSniff.php new file mode 100644 index 000000000..4add28612 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/UselessInheritDocCommentSniff.php @@ -0,0 +1,118 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $docCommentContent = ''; + for ($i = $docCommentOpenPointer + 1; $i < $tokens[$docCommentOpenPointer]['comment_closer']; $i++) { + if (in_array($tokens[$i]['code'], [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR], true)) { + continue; + } + + $docCommentContent .= $tokens[$i]['content']; + } + + if (preg_match('~^(?:\{@inheritDoc\}|@inheritDoc)$~i', $docCommentContent) === 0) { + return; + } + + $searchPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1; + do { + $docCommentOwnerPointer = TokenHelper::findNext( + $phpcsFile, + array_merge(TokenHelper::$functionTokenCodes, TokenHelper::getTypeHintTokenCodes(), [T_ATTRIBUTE]), + $searchPointer + ); + + if ($docCommentOwnerPointer === null) { + return; + } + + if ($tokens[$docCommentOwnerPointer]['code'] === T_ATTRIBUTE) { + $searchPointer = $tokens[$docCommentOwnerPointer]['attribute_closer'] + 1; + continue; + } + + break; + + } while (true); + + if (in_array($tokens[$docCommentOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + $returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $docCommentOwnerPointer); + if ($returnTypeHint === null) { + return; + } + + if (TypeHintHelper::isSimpleIterableTypeHint($returnTypeHint->getTypeHintWithoutNullabilitySymbol())) { + return; + } + + $parametersTypeHints = FunctionHelper::getParametersTypeHints($phpcsFile, $docCommentOwnerPointer); + foreach ($parametersTypeHints as $parameterTypeHint) { + if ($parameterTypeHint === null) { + return; + } + + if (TypeHintHelper::isSimpleIterableTypeHint($parameterTypeHint->getTypeHint())) { + return; + } + } + } + + $fix = $phpcsFile->addFixableError( + 'Useless documentation comment with @inheritDoc.', + $docCommentOpenPointer, + self::CODE_USELESS_INHERIT_DOC_COMMENT + ); + + if (!$fix) { + return; + } + + /** @var int $fixerStart */ + $fixerStart = TokenHelper::findLastTokenOnPreviousLine($phpcsFile, $docCommentOpenPointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $fixerStart, $tokens[$docCommentOpenPointer]['comment_closer']); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Complexity/CognitiveSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Complexity/CognitiveSniff.php new file mode 100644 index 000000000..a42830ad3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Complexity/CognitiveSniff.php @@ -0,0 +1,310 @@ + T_CATCH, + T_DO => T_DO, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_IF => T_IF, + T_SWITCH => T_SWITCH, + T_WHILE => T_WHILE, + ]; + + private const BOOLEAN_OPERATORS = [ + T_BOOLEAN_AND => T_BOOLEAN_AND, + T_BOOLEAN_OR => T_BOOLEAN_OR, + ]; + + private const OPERATOR_CHAIN_BREAKS = [ + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + T_SEMICOLON => T_SEMICOLON, + T_INLINE_THEN => T_INLINE_THEN, + T_INLINE_ELSE => T_INLINE_ELSE, + ]; + + /** + * B3. Nesting increments + */ + private const NESTING_INCREMENTS = [ + T_CLOSURE => T_CLOSURE, + // increments, but does not receive + T_ELSEIF => T_ELSEIF, + // increments, but does not receive + T_ELSE => T_ELSE, + T_IF => T_IF, + T_INLINE_THEN => T_INLINE_THEN, + T_SWITCH => T_SWITCH, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_WHILE => T_WHILE, + T_DO => T_DO, + T_CATCH => T_CATCH, + ]; + + /** + * B1. Increments + */ + private const BREAKING_TOKENS = [ + T_CONTINUE => T_CONTINUE, + T_GOTO => T_GOTO, + T_BREAK => T_BREAK, + ]; + + /** + * @deprecated + * @var ?int maximum allowed complexity + */ + public $maxComplexity = null; + + /** @var int complexity which will raise warning */ + public $warningThreshold = 6; + + /** @var int complexity which will raise error */ + public $errorThreshold = 6; + + /** @var int */ + private $cognitiveComplexity = 0; + + /** @var int|string */ + private $lastBooleanOperator = 0; + + /** @var File */ + private $phpcsFile; + + /** + * @return array + */ + public function register(): array + { + return [ + T_CLOSURE, + T_FUNCTION, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stackPtr + */ + public function process(File $phpcsFile, $stackPtr): void + { + $this->phpcsFile = $phpcsFile; + + if ($phpcsFile->getCondition($stackPtr, T_FUNCTION) !== false) { + return; + } + + if ($this->maxComplexity !== null) { + // maxComplexity is deprecated... if set use it + $this->warningThreshold = $this->maxComplexity + 1; + $this->errorThreshold = $this->maxComplexity + 1; + } + + $cognitiveComplexity = $this->computeForFunctionFromTokensAndPosition($stackPtr); + + if ($cognitiveComplexity < $this->warningThreshold) { + return; + } + + $name = $phpcsFile->getDeclarationName($stackPtr); + + $errorParameters = [ + 'Cognitive complexity for "%s" is %d but has to be less than or equal to %d.', + $stackPtr, + self::CODE_COMPLEXITY, + [ + $name, + $cognitiveComplexity, + $this->warningThreshold - 1, + ], + ]; + + $cognitiveComplexity >= $this->errorThreshold + ? $phpcsFile->addError(...$errorParameters) + : $phpcsFile->addWarning(...$errorParameters); + } + + public function computeForFunctionFromTokensAndPosition(int $position): int + { + if (FunctionHelper::isAbstract($this->phpcsFile, $position)) { + return 0; + } + + $tokens = $this->phpcsFile->getTokens(); + + // Detect start and end of this function definition + $functionStartPosition = $tokens[$position]['scope_opener']; + $functionEndPosition = $tokens[$position]['scope_closer']; + + $this->lastBooleanOperator = 0; + $this->cognitiveComplexity = 0; + + /* + Keep track of parser's level stack + We push to this stak whenever we encounter a Tokens::$scopeOpeners + */ + $levelStack = []; + /* + We look for changes in token[level] to know when to remove from the stack + however ['level'] only increases when there are tokens inside {} + after pushing to the stack watch for a level change + */ + $levelIncreased = false; + + for ($i = $functionStartPosition + 1; $i < $functionEndPosition; $i++) { + $currentToken = $tokens[$i]; + + $isNestingToken = false; + if (in_array($currentToken['code'], Tokens::$scopeOpeners, true)) { + $isNestingToken = true; + if ($levelIncreased === false && count($levelStack) > 0) { + // parser's level never increased + // caused by empty condition such as `if ($x) { }` + array_pop($levelStack); + } + $levelStack[] = $currentToken; + $levelIncreased = false; + } elseif (isset($tokens[$i - 1]) && $currentToken['level'] < $tokens[$i - 1]['level']) { + $diff = $tokens[$i - 1]['level'] - $currentToken['level']; + array_splice($levelStack, 0 - $diff); + } elseif (isset($tokens[$i - 1]) && $currentToken['level'] > $tokens[$i - 1]['level']) { + $levelIncreased = true; + } + + $this->resolveBooleanOperatorChain($currentToken); + + if (!$this->isIncrementingToken($currentToken, $tokens, $i)) { + continue; + } + + $this->cognitiveComplexity++; + + $addNestingIncrement = isset(self::NESTING_INCREMENTS[$currentToken['code']]) + && in_array($currentToken['code'], [T_ELSEIF, T_ELSE], true) === false; + if (!$addNestingIncrement) { + continue; + } + $measuredNestingLevel = count(array_filter($levelStack, static function (array $token) { + return in_array($token['code'], self::NESTING_INCREMENTS, true); + })); + if ($isNestingToken) { + $measuredNestingLevel--; + } + // B3. Nesting increment + if ($measuredNestingLevel > 0) { + $this->cognitiveComplexity += $measuredNestingLevel; + } + } + + return $this->cognitiveComplexity; + } + + /** + * Keep track of consecutive matching boolean operators, that don't receive increment. + * + * @param array{code:int|string} $token + */ + private function resolveBooleanOperatorChain(array $token): void + { + $code = $token['code']; + + // Whenever we cross anything that interrupts possible condition we reset chain. + if ($this->lastBooleanOperator > 0 && isset(self::OPERATOR_CHAIN_BREAKS[$code])) { + $this->lastBooleanOperator = 0; + return; + } + + if (isset(self::BOOLEAN_OPERATORS[$code]) === false) { + return; + } + + // If we match last operator, there is no increment added for current one. + if ($this->lastBooleanOperator === $code) { + return; + } + + $this->cognitiveComplexity++; + + $this->lastBooleanOperator = $code; + } + + /** + * @param array{code:int|string} $token + * @param array|int|string>> $tokens + */ + private function isIncrementingToken(array $token, array $tokens, int $position): bool + { + $code = $token['code']; + + if (isset(self::INCREMENTS[$code])) { + return true; + } + + // B1. ternary operator + if ($code === T_INLINE_THEN) { + return true; + } + + // B1. goto LABEL, break LABEL, continue LABEL + if (isset(self::BREAKING_TOKENS[$code])) { + $nextToken = $this->phpcsFile->findNext(Tokens::$emptyTokens, $position + 1, null, true); + if ($nextToken === false || $tokens[$nextToken]['code'] !== T_SEMICOLON) { + return true; + } + } + + return false; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractControlStructureSpacing.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractControlStructureSpacing.php new file mode 100644 index 000000000..2c1bb8077 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractControlStructureSpacing.php @@ -0,0 +1,510 @@ +|null */ + private $tokensToCheck; + + /** + * @return list + */ + abstract protected function getSupportedKeywords(): array; + + /** + * @return list + */ + abstract protected function getKeywordsToCheck(): array; + + abstract protected function getLinesCountBefore(): int; + + abstract protected function getLinesCountBeforeFirst(File $phpcsFile, int $controlStructurePointer): int; + + abstract protected function getLinesCountAfter(): int; + + abstract protected function getLinesCountAfterLast(File $phpcsFile, int $controlStructurePointer, int $controlStructureEndPointer): int; + + /** + * @return array + */ + public function register(): array + { + return $this->getTokensToCheck(); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $controlStructurePointer + */ + public function process(File $phpcsFile, $controlStructurePointer): void + { + $this->checkLinesBefore($phpcsFile, $controlStructurePointer); + + try { + $this->checkLinesAfter($phpcsFile, $controlStructurePointer); + } catch (Throwable $e) { + // Unsupported syntax without curly braces. + return; + } + } + + protected function checkLinesBefore(File $phpcsFile, int $controlStructurePointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (in_array($tokens[$controlStructurePointer]['code'], [T_CASE, T_DEFAULT], true)) { + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $controlStructurePointer - 1); + if ($tokens[$pointerBefore]['code'] === T_COLON) { + return; + } + } + + $nonWhitespacePointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $controlStructurePointer - 1); + + $controlStructureStartPointer = $controlStructurePointer; + $pointerBefore = $nonWhitespacePointerBefore; + + $pointerToCheckFirst = $pointerBefore; + + if (in_array($tokens[$nonWhitespacePointerBefore]['code'], Tokens::$commentTokens, true)) { + $effectivePointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $pointerBefore - 1); + + if ($tokens[$effectivePointerBefore]['line'] === $tokens[$nonWhitespacePointerBefore]['line']) { + $pointerToCheckFirst = $effectivePointerBefore; + } elseif ($tokens[$nonWhitespacePointerBefore]['line'] + 1 === $tokens[$controlStructurePointer]['line']) { + if ($tokens[$effectivePointerBefore]['line'] !== $tokens[$nonWhitespacePointerBefore]['line']) { + $controlStructureStartPointer = array_key_exists('comment_opener', $tokens[$nonWhitespacePointerBefore]) + ? $tokens[$nonWhitespacePointerBefore]['comment_opener'] + : CommentHelper::getMultilineCommentStartPointer($phpcsFile, $nonWhitespacePointerBefore); + $pointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $controlStructureStartPointer - 1); + } + $pointerToCheckFirst = $pointerBefore; + } + } + + $isFirstControlStructure = in_array($tokens[$pointerToCheckFirst]['code'], [T_OPEN_CURLY_BRACKET, T_COLON], true); + $whitespaceBefore = ''; + + if ($tokens[$pointerBefore]['code'] === T_OPEN_TAG) { + $whitespaceBefore .= substr($tokens[$pointerBefore]['content'], strlen('eolChar)) === $phpcsFile->eolChar; + if ($hasCommentWithLineEndBefore) { + $whitespaceBefore .= $phpcsFile->eolChar; + } + + if ($pointerBefore + 1 !== $controlStructurePointer) { + $whitespaceBefore .= TokenHelper::getContent($phpcsFile, $pointerBefore + 1, $controlStructureStartPointer - 1); + } + + $requiredLinesCountBefore = $isFirstControlStructure + ? $this->getLinesCountBeforeFirst($phpcsFile, $controlStructurePointer) + : $this->getLinesCountBefore(); + $actualLinesCountBefore = substr_count($whitespaceBefore, $phpcsFile->eolChar) - 1; + + if ($requiredLinesCountBefore === $actualLinesCountBefore) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s before "%s", found %d.', + $requiredLinesCountBefore, + $requiredLinesCountBefore === 1 ? '' : 's', + $tokens[$controlStructurePointer]['content'], + $actualLinesCountBefore + ), + $controlStructurePointer, + $isFirstControlStructure + ? self::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_CONTROL_STRUCTURE + : self::CODE_INCORRECT_LINES_COUNT_BEFORE_CONTROL_STRUCTURE + ); + + if (!$fix) { + return; + } + + $endOfLineBeforePointer = TokenHelper::findPreviousContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $controlStructureStartPointer - 1 + ); + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$pointerBefore]['code'] === T_OPEN_TAG) { + $phpcsFile->fixer->replaceToken($pointerBefore, 'fixer->addNewline($pointerBefore); + } + + $phpcsFile->fixer->endChangeset(); + } + + protected function checkLinesAfter(File $phpcsFile, int $controlStructurePointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (in_array($tokens[$controlStructurePointer]['code'], [T_CASE, T_DEFAULT], true)) { + $colonPointer = TokenHelper::findNext($phpcsFile, T_COLON, $controlStructurePointer + 1); + $pointerAfterColon = TokenHelper::findNextEffective($phpcsFile, $colonPointer + 1); + + if (in_array($tokens[$pointerAfterColon]['code'], [T_CASE, T_DEFAULT], true)) { + return; + } + } + + $controlStructureEndPointer = $this->findControlStructureEnd($phpcsFile, $controlStructurePointer); + + $pointerAfterControlStructureEnd = TokenHelper::findNextEffective($phpcsFile, $controlStructureEndPointer + 1); + if ( + $pointerAfterControlStructureEnd !== null + && $tokens[$pointerAfterControlStructureEnd]['code'] === T_SEMICOLON + ) { + $controlStructureEndPointer = $pointerAfterControlStructureEnd; + } + + $notWhitespacePointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $controlStructureEndPointer + 1); + + if ($notWhitespacePointerAfter === null) { + return; + } + + $hasCommentAfter = in_array($tokens[$notWhitespacePointerAfter]['code'], Tokens::$commentTokens, true); + $isCommentAfterOnSameLine = false; + $pointerAfter = $notWhitespacePointerAfter; + + $isControlStructureEndAfterPointer = static function (int $pointer) use ($tokens, $controlStructurePointer): bool { + return in_array($tokens[$controlStructurePointer]['code'], [T_CASE, T_DEFAULT], true) + ? $tokens[$pointer]['code'] === T_CLOSE_CURLY_BRACKET + : in_array($tokens[$pointer]['code'], [T_CLOSE_CURLY_BRACKET, T_CASE, T_DEFAULT], true); + }; + + if ($hasCommentAfter) { + if ($tokens[$notWhitespacePointerAfter]['line'] === $tokens[$controlStructureEndPointer]['line'] + 1) { + $commentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $notWhitespacePointerAfter); + $pointerAfterComment = TokenHelper::findNextNonWhitespace($phpcsFile, $commentEndPointer + 1); + + if ($isControlStructureEndAfterPointer($pointerAfterComment)) { + $controlStructureEndPointer = $commentEndPointer; + $pointerAfter = $pointerAfterComment; + } + } elseif ($tokens[$notWhitespacePointerAfter]['line'] === $tokens[$controlStructureEndPointer]['line']) { + $isCommentAfterOnSameLine = true; + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $notWhitespacePointerAfter + 1); + } + } + + $isLastControlStructure = $isControlStructureEndAfterPointer($pointerAfter); + + $requiredLinesCountAfter = $isLastControlStructure + ? $this->getLinesCountAfterLast($phpcsFile, $controlStructurePointer, $controlStructureEndPointer) + : $this->getLinesCountAfter(); + $actualLinesCountAfter = $tokens[$pointerAfter]['line'] - $tokens[$controlStructureEndPointer]['line'] - 1; + + if ($requiredLinesCountAfter === $actualLinesCountAfter) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s after "%s", found %d.', + $requiredLinesCountAfter, + $requiredLinesCountAfter === 1 ? '' : 's', + $tokens[$controlStructurePointer]['content'], + $actualLinesCountAfter + ), + $controlStructurePointer, + $isLastControlStructure + ? self::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_CONTROL_STRUCTURE + : self::CODE_INCORRECT_LINES_COUNT_AFTER_CONTROL_STRUCTURE + ); + + if (!$fix) { + return; + } + + $replaceStartPointer = $isCommentAfterOnSameLine ? $notWhitespacePointerAfter : $controlStructureEndPointer; + $endOfLineBeforeAfterPointer = TokenHelper::findLastTokenOnPreviousLine($phpcsFile, $pointerAfter); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $replaceStartPointer + 1, $endOfLineBeforeAfterPointer); + + if ($isCommentAfterOnSameLine) { + for ($i = 0; $i < $requiredLinesCountAfter; $i++) { + $phpcsFile->fixer->addNewline($notWhitespacePointerAfter); + } + } else { + $linesToAdd = substr($tokens[$controlStructureEndPointer]['content'], -strlen($phpcsFile->eolChar)) === $phpcsFile->eolChar + ? $requiredLinesCountAfter - 1 + : $requiredLinesCountAfter; + for ($i = 0; $i <= $linesToAdd; $i++) { + $phpcsFile->fixer->addNewline($controlStructureEndPointer); + } + } + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @return array + */ + private function getTokensToCheck(): array + { + if ($this->tokensToCheck === null) { + $supportedKeywords = $this->getSupportedKeywords(); + $supportedTokens = [ + self::KEYWORD_IF => T_IF, + self::KEYWORD_DO => T_DO, + self::KEYWORD_WHILE => T_WHILE, + self::KEYWORD_FOR => T_FOR, + self::KEYWORD_FOREACH => T_FOREACH, + self::KEYWORD_SWITCH => T_SWITCH, + self::KEYWORD_CASE => T_CASE, + self::KEYWORD_DEFAULT => T_DEFAULT, + self::KEYWORD_TRY => T_TRY, + self::KEYWORD_PARENT => T_PARENT, + self::KEYWORD_GOTO => T_GOTO, + self::KEYWORD_BREAK => T_BREAK, + self::KEYWORD_CONTINUE => T_CONTINUE, + self::KEYWORD_RETURN => T_RETURN, + self::KEYWORD_THROW => T_THROW, + self::KEYWORD_YIELD => T_YIELD, + self::KEYWORD_YIELD_FROM => T_YIELD_FROM, + ]; + + $this->tokensToCheck = array_values(array_map( + static function (string $keyword) use ($supportedKeywords, $supportedTokens) { + if (!in_array($keyword, $supportedKeywords, true)) { + throw new UnsupportedKeywordException($keyword); + } + + return $supportedTokens[$keyword]; + }, + SniffSettingsHelper::normalizeArray($this->getKeywordsToCheck()) + )); + + if (count($this->tokensToCheck) === 0) { + $this->tokensToCheck = array_map(static function (string $keyword) use ($supportedTokens) { + return $supportedTokens[$keyword]; + }, $supportedKeywords); + } + } + + return $this->tokensToCheck; + } + + private function findControlStructureEnd(File $phpcsFile, int $controlStructurePointer): int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$controlStructurePointer]['code'] === T_IF) { + if (!array_key_exists('scope_closer', $tokens[$controlStructurePointer])) { + throw new Exception('"if" without curly braces is not supported.'); + } + + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$controlStructurePointer]['parenthesis_closer'] + 1 + ); + if ($pointerAfterParenthesisCloser !== null && $tokens[$pointerAfterParenthesisCloser]['code'] === T_COLON) { + throw new Exception('"if" without curly braces is not supported.'); + } + + $controlStructureEndPointer = $tokens[$controlStructurePointer]['scope_closer']; + do { + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $controlStructureEndPointer + 1); + if ($nextPointer === null) { + return $controlStructureEndPointer; + } + + if ($tokens[$nextPointer]['code'] === T_ELSE) { + if (!array_key_exists('scope_closer', $tokens[$nextPointer])) { + throw new Exception('"else" without curly braces is not supported.'); + } + + return $tokens[$nextPointer]['scope_closer']; + } + + if ($tokens[$nextPointer]['code'] !== T_ELSEIF) { + return $controlStructureEndPointer; + } + + $controlStructureEndPointer = $tokens[$nextPointer]['scope_closer']; + } while (true); + } + + if ($tokens[$controlStructurePointer]['code'] === T_DO) { + $whilePointer = TokenHelper::findNext($phpcsFile, T_WHILE, $tokens[$controlStructurePointer]['scope_closer'] + 1); + return (int) TokenHelper::findNext($phpcsFile, T_SEMICOLON, $tokens[$whilePointer]['parenthesis_closer'] + 1); + } + + if ($tokens[$controlStructurePointer]['code'] === T_TRY) { + $controlStructureEndPointer = $tokens[$controlStructurePointer]['scope_closer']; + do { + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $controlStructureEndPointer + 1); + + if ($nextPointer === null) { + return $controlStructureEndPointer; + } + + if (!in_array($tokens[$nextPointer]['code'], [T_CATCH, T_FINALLY], true)) { + return $controlStructureEndPointer; + } + + $controlStructureEndPointer = $tokens[$nextPointer]['scope_closer']; + } while (true); + } + + if (in_array($tokens[$controlStructurePointer]['code'], [T_WHILE, T_FOR, T_FOREACH, T_SWITCH], true)) { + return $tokens[$controlStructurePointer]['scope_closer']; + } + + if (in_array($tokens[$controlStructurePointer]['code'], [T_CASE, T_DEFAULT], true)) { + $switchPointer = TokenHelper::findPrevious($phpcsFile, T_SWITCH, $controlStructurePointer - 1); + + $pointers = TokenHelper::findNextAll( + $phpcsFile, + [T_CASE, T_DEFAULT], + $controlStructurePointer + 1, + $tokens[$switchPointer]['scope_closer'] + ); + + foreach ($pointers as $pointer) { + if (TokenHelper::findPrevious($phpcsFile, T_SWITCH, $pointer - 1) === $switchPointer) { + $pointerBeforeCaseOrDefault = TokenHelper::findPreviousNonWhitespace($phpcsFile, $pointer - 1); + if ( + in_array($tokens[$pointerBeforeCaseOrDefault]['code'], Tokens::$commentTokens, true) + && $tokens[$pointerBeforeCaseOrDefault]['line'] + 1 === $tokens[$pointer]['line'] + ) { + $pointerBeforeCaseOrDefault = TokenHelper::findPreviousExcluding( + $phpcsFile, + T_WHITESPACE, + $pointerBeforeCaseOrDefault - 1 + ); + } + + return $pointerBeforeCaseOrDefault; + } + } + + return TokenHelper::findPreviousNonWhitespace($phpcsFile, $tokens[$switchPointer]['scope_closer'] - 1); + } + + $nextPointer = TokenHelper::findNext( + $phpcsFile, + [T_SEMICOLON, T_ANON_CLASS, T_CLOSURE, T_FN, T_OPEN_SHORT_ARRAY], + $controlStructurePointer + 1 + ); + if ($tokens[$nextPointer]['code'] === T_SEMICOLON) { + return $nextPointer; + } + + $scopeCloserPointer = $tokens[$nextPointer]['code'] === T_OPEN_SHORT_ARRAY + ? $tokens[$nextPointer]['bracket_closer'] + : $tokens[$nextPointer]['scope_closer']; + + if ($tokens[$scopeCloserPointer]['code'] === T_SEMICOLON) { + return $scopeCloserPointer; + } + + $nextPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $scopeCloserPointer + 1); + + $level = $tokens[$controlStructurePointer]['level']; + while ($level !== $tokens[$nextPointer]['level']) { + $nextPointer = (int) TokenHelper::findNext($phpcsFile, T_SEMICOLON, $nextPointer + 1); + } + + return $nextPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractLineCondition.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractLineCondition.php new file mode 100644 index 000000000..613a94da8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AbstractLineCondition.php @@ -0,0 +1,128 @@ + */ + public $checkedControlStructures = [ + self::IF_CONTROL_STRUCTURE, + self::WHILE_CONTROL_STRUCTURE, + self::DO_CONTROL_STRUCTURE, + ]; + + /** + * @return array + */ + public function register(): array + { + $this->checkedControlStructures = SniffSettingsHelper::normalizeArray($this->checkedControlStructures); + + $register = []; + + if (in_array(self::IF_CONTROL_STRUCTURE, $this->checkedControlStructures, true)) { + $register[] = T_IF; + $register[] = T_ELSEIF; + } + + if (in_array(self::WHILE_CONTROL_STRUCTURE, $this->checkedControlStructures, true)) { + $register[] = T_WHILE; + } + + if (in_array(self::DO_CONTROL_STRUCTURE, $this->checkedControlStructures, true)) { + $register[] = T_WHILE; + } + + return $register; + } + + protected function shouldBeSkipped(File $phpcsFile, int $controlStructurePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + if ( + !array_key_exists('parenthesis_opener', $tokens[$controlStructurePointer]) + || $tokens[$controlStructurePointer]['parenthesis_opener'] === null + || !array_key_exists('parenthesis_closer', $tokens[$controlStructurePointer]) + || $tokens[$controlStructurePointer]['parenthesis_closer'] === null + ) { + return true; + } + + if ($tokens[$controlStructurePointer]['code'] === T_WHILE) { + $isPartOfDo = $this->isPartOfDo($phpcsFile, $controlStructurePointer); + + if ($isPartOfDo && !in_array(self::DO_CONTROL_STRUCTURE, $this->checkedControlStructures, true)) { + return true; + } + + if (!$isPartOfDo && !in_array(self::WHILE_CONTROL_STRUCTURE, $this->checkedControlStructures, true)) { + return true; + } + } + + return false; + } + + protected function getControlStructureName(File $phpcsFile, int $controlStructurePointer): string + { + $tokens = $phpcsFile->getTokens(); + + return $tokens[$controlStructurePointer]['code'] === T_WHILE && $this->isPartOfDo($phpcsFile, $controlStructurePointer) + ? 'do-while' + : $tokens[$controlStructurePointer]['content']; + } + + protected function isPartOfDo(File $phpcsFile, int $whilePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisCloserPointer = $tokens[$whilePointer]['parenthesis_closer']; + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective($phpcsFile, $parenthesisCloserPointer + 1); + + return $tokens[$pointerAfterParenthesisCloser]['code'] !== T_OPEN_CURLY_BRACKET; + } + + protected function getLineStart(File $phpcsFile, int $pointer): string + { + $firstPointerOnLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $pointer); + + return IndentationHelper::convertTabsToSpaces($phpcsFile, TokenHelper::getContent($phpcsFile, $firstPointerOnLine, $pointer)); + } + + protected function getCondition(File $phpcsFile, int $parenthesisOpenerPointer, int $parenthesisCloserPointer): string + { + $condition = TokenHelper::getContent($phpcsFile, $parenthesisOpenerPointer + 1, $parenthesisCloserPointer - 1); + + return trim(preg_replace(sprintf('~%s[ \t]*~', $phpcsFile->eolChar), ' ', $condition)); + } + + protected function getLineEnd(File $phpcsFile, int $pointer): string + { + $lastPointerOnLine = TokenHelper::findLastTokenOnLine($phpcsFile, $pointer); + + return rtrim(TokenHelper::getContent($phpcsFile, $pointer, $lastPointerOnLine)); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AssignmentInConditionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AssignmentInConditionSniff.php new file mode 100644 index 000000000..56165449e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AssignmentInConditionSniff.php @@ -0,0 +1,115 @@ + + */ + public function register(): array + { + return [ + T_IF, + T_ELSEIF, + T_DO, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $conditionStartPointer + */ + public function process(File $phpcsFile, $conditionStartPointer): void + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$conditionStartPointer]; + + if ($token['code'] === T_DO) { + $whilePointer = TokenHelper::findNext($phpcsFile, T_WHILE, $token['scope_closer'] + 1); + $whileToken = $tokens[$whilePointer]; + $parenthesisOpener = $whileToken['parenthesis_opener']; + $parenthesisCloser = $whileToken['parenthesis_closer']; + $type = 'do-while'; + } else { + $parenthesisOpener = $token['parenthesis_opener']; + $parenthesisCloser = $token['parenthesis_closer']; + $type = $token['code'] === T_IF ? 'if' : 'elseif'; + } + + if ( + $parenthesisOpener === null + || $parenthesisCloser === null + ) { + return; + } + + $this->processCondition($phpcsFile, $parenthesisOpener, $parenthesisCloser, $type); + } + + private function processCondition(File $phpcsFile, int $parenthesisOpener, int $parenthesisCloser, string $conditionType): void + { + $equalsTokenPointers = TokenHelper::findNextAll($phpcsFile, T_EQUAL, $parenthesisOpener + 1, $parenthesisCloser); + if ($equalsTokenPointers === []) { + return; + } + + if (!$this->ignoreAssignmentsInsideFunctionCalls) { + $this->error($phpcsFile, $conditionType, $equalsTokenPointers[0]); + return; + } + + $tokens = $phpcsFile->getTokens(); + + foreach ($equalsTokenPointers as $equalsTokenPointer) { + $parenthesisStarts = array_keys($tokens[$equalsTokenPointer]['nested_parenthesis']); + + /** @var int $insideParenthesis */ + $insideParenthesis = max($parenthesisStarts); + if ($insideParenthesis === $parenthesisOpener) { + $this->error($phpcsFile, $conditionType, $equalsTokenPointer); + continue; + } + + $functionCall = TokenHelper::findPrevious( + $phpcsFile, + TokenHelper::getOnlyNameTokenCodes(), + $insideParenthesis, + $parenthesisOpener + ); + if ($functionCall !== null) { + continue; + } + + $this->error($phpcsFile, $conditionType, $equalsTokenPointer); + } + } + + private function error(File $phpcsFile, string $conditionType, int $equalsTokenPointer): void + { + $phpcsFile->addError( + sprintf('Assignment in %s condition is not allowed.', $conditionType), + $equalsTokenPointer, + self::CODE_ASSIGNMENT_IN_CONDITION + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/BlockControlStructureSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/BlockControlStructureSpacingSniff.php new file mode 100644 index 000000000..ab7821ab1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/BlockControlStructureSpacingSniff.php @@ -0,0 +1,113 @@ + */ + public $controlStructures = []; + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $controlStructurePointer + */ + public function process(File $phpcsFile, $controlStructurePointer): void + { + $this->linesCountBefore = SniffSettingsHelper::normalizeInteger($this->linesCountBefore); + $this->linesCountBeforeFirst = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirst); + $this->linesCountAfter = SniffSettingsHelper::normalizeInteger($this->linesCountAfter); + $this->linesCountAfterLast = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLast); + + if ($this->isWhilePartOfDo($phpcsFile, $controlStructurePointer)) { + return; + } + + parent::process($phpcsFile, $controlStructurePointer); + } + + /** + * @return list + */ + protected function getSupportedKeywords(): array + { + return [ + self::KEYWORD_IF, + self::KEYWORD_DO, + self::KEYWORD_WHILE, + self::KEYWORD_FOR, + self::KEYWORD_FOREACH, + self::KEYWORD_SWITCH, + self::KEYWORD_TRY, + self::KEYWORD_CASE, + self::KEYWORD_DEFAULT, + ]; + } + + /** + * @return list + */ + protected function getKeywordsToCheck(): array + { + return $this->controlStructures; + } + + protected function getLinesCountBefore(): int + { + return $this->linesCountBefore; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + */ + protected function getLinesCountBeforeFirst(File $phpcsFile, int $controlStructurePointer): int + { + return $this->linesCountBeforeFirst; + } + + protected function getLinesCountAfter(): int + { + return $this->linesCountAfter; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + */ + protected function getLinesCountAfterLast(File $phpcsFile, int $controlStructurePointer, int $controlStructureEndPointer): int + { + return $this->linesCountAfterLast; + } + + private function isWhilePartOfDo(File $phpcsFile, int $controlStructurePointer): bool + { + $tokens = $phpcsFile->getTokens(); + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $controlStructurePointer - 1); + + return + $tokens[$controlStructurePointer]['code'] === T_WHILE + && $tokens[$pointerBefore]['code'] === T_CLOSE_CURLY_BRACKET + && array_key_exists('scope_condition', $tokens[$pointerBefore]) + && $tokens[$tokens[$pointerBefore]['scope_condition']]['code'] === T_DO; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowContinueWithoutIntegerOperandInSwitchSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowContinueWithoutIntegerOperandInSwitchSniff.php new file mode 100644 index 000000000..69bfc566d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowContinueWithoutIntegerOperandInSwitchSniff.php @@ -0,0 +1,63 @@ + + */ + public function register(): array + { + return [ + T_CONTINUE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $continuePointer + */ + public function process(File $phpcsFile, $continuePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $operandPointer = TokenHelper::findNextEffective($phpcsFile, $continuePointer + 1); + + if ($tokens[$operandPointer]['code'] === T_LNUMBER) { + return; + } + + $conditionTokenCode = current(array_reverse($tokens[$continuePointer]['conditions'])); + if ($conditionTokenCode !== T_SWITCH) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Usage of "continue" without integer operand in "switch" is disallowed, use "break" instead.', + $continuePointer, + self::CODE_DISALLOWED_CONTINUE_WITHOUT_INTEGER_OPERAND_IN_SWITCH + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($continuePointer, 'break'); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowEmptySniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowEmptySniff.php new file mode 100644 index 000000000..e7cf97378 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowEmptySniff.php @@ -0,0 +1,33 @@ + + */ + public function register(): array + { + return [ + T_EMPTY, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $emptyPointer + */ + public function process(File $phpcsFile, $emptyPointer): void + { + $phpcsFile->addError('Use of empty() is disallowed.', $emptyPointer, self::CODE_DISALLOWED_EMPTY); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowNullSafeObjectOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowNullSafeObjectOperatorSniff.php new file mode 100644 index 000000000..6a26e4f30 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowNullSafeObjectOperatorSniff.php @@ -0,0 +1,33 @@ + + */ + public function register(): array + { + return [ + T_NULLSAFE_OBJECT_OPERATOR, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $operatorPointer + */ + public function process(File $phpcsFile, $operatorPointer): void + { + $phpcsFile->addError('Operator ?-> is disallowed.', $operatorPointer, self::CODE_DISALLOWED_NULL_SAFE_OBJECT_OPERATOR); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowShortTernaryOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowShortTernaryOperatorSniff.php new file mode 100644 index 000000000..59c1eba76 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowShortTernaryOperatorSniff.php @@ -0,0 +1,72 @@ + + */ + public function register(): array + { + return [ + T_INLINE_THEN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $inlineThenPointer + */ + public function process(File $phpcsFile, $inlineThenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $inlineThenPointer + 1); + + if ($tokens[$nextPointer]['code'] !== T_INLINE_ELSE) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $inlineThenPointer - 1); + + $message = 'Use of short ternary operator is disallowed.'; + + if ($tokens[$previousPointer]['code'] !== T_VARIABLE) { + $phpcsFile->addError($message, $inlineThenPointer, self::CODE_DISALLOWED_SHORT_TERNARY_OPERATOR); + return; + } + + if (!$this->fixable) { + $phpcsFile->addError($message, $inlineThenPointer, self::CODE_DISALLOWED_SHORT_TERNARY_OPERATOR); + return; + } + + $fix = $phpcsFile->addFixableError($message, $inlineThenPointer, self::CODE_DISALLOWED_SHORT_TERNARY_OPERATOR); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($inlineThenPointer, sprintf(' %s ', $tokens[$previousPointer]['content'])); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowTrailingMultiLineTernaryOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowTrailingMultiLineTernaryOperatorSniff.php new file mode 100644 index 000000000..f37763053 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowTrailingMultiLineTernaryOperatorSniff.php @@ -0,0 +1,88 @@ + + */ + public function register(): array + { + return [ + T_INLINE_THEN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $inlineThenPointer + */ + public function process(File $phpcsFile, $inlineThenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $inlineThenPointer + 1); + if ($tokens[$nextPointer]['code'] === T_INLINE_ELSE) { + return; + } + + if ($tokens[$inlineThenPointer]['line'] === $tokens[$nextPointer]['line']) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Ternary operator should be reformatted as leading the line.', + $inlineThenPointer, + self::CODE_TRAILING_MULTI_LINE_TERNARY_OPERATOR_USED + ); + + if (!$fix) { + return; + } + + $inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer); + + $pointerBeforeInlineThen = TokenHelper::findPreviousEffective($phpcsFile, $inlineThenPointer - 1); + $pointerAfterInlineThen = TokenHelper::findNextExcluding($phpcsFile, [T_WHITESPACE], $inlineThenPointer + 1); + $pointerBeforeInlineElse = TokenHelper::findPreviousEffective($phpcsFile, $inlineElsePointer - 1); + $pointerAfterInlineElse = TokenHelper::findNextExcluding($phpcsFile, [T_WHITESPACE], $inlineElsePointer + 1); + + $indentation = IndentationHelper::addIndentation( + IndentationHelper::getIndentation( + $phpcsFile, + TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $inlineThenPointer) + ) + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeInlineThen, $inlineThenPointer); + FixerHelper::removeBetween($phpcsFile, $inlineThenPointer, $pointerAfterInlineThen); + + $phpcsFile->fixer->addContentBefore($inlineThenPointer, $phpcsFile->eolChar . $indentation); + $phpcsFile->fixer->addContentBefore($pointerAfterInlineThen, ' '); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeInlineElse, $inlineElsePointer); + FixerHelper::removeBetween($phpcsFile, $inlineElsePointer, $pointerAfterInlineElse); + + $phpcsFile->fixer->addContentBefore($inlineElsePointer, $phpcsFile->eolChar . $indentation); + $phpcsFile->fixer->addContentBefore($pointerAfterInlineElse, ' '); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowYodaComparisonSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowYodaComparisonSniff.php new file mode 100644 index 000000000..8cdc703e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/DisallowYodaComparisonSniff.php @@ -0,0 +1,88 @@ + (Foo::BAR, BAR) + * > (true, false, null, 1, 1.0, arrays, 'foo') + */ +class DisallowYodaComparisonSniff implements Sniff +{ + + public const CODE_DISALLOWED_YODA_COMPARISON = 'DisallowedYodaComparison'; + + /** + * @return array + */ + public function register(): array + { + return [ + T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL, + T_IS_EQUAL, + T_IS_NOT_EQUAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $comparisonTokenPointer + */ + public function process(File $phpcsFile, $comparisonTokenPointer): void + { + $tokens = $phpcsFile->getTokens(); + $leftSideTokens = YodaHelper::getLeftSideTokens($tokens, $comparisonTokenPointer); + $rightSideTokens = YodaHelper::getRightSideTokens($tokens, $comparisonTokenPointer); + $leftDynamism = YodaHelper::getDynamismForTokens($tokens, $leftSideTokens); + $rightDynamism = YodaHelper::getDynamismForTokens($tokens, $rightSideTokens); + + if ($leftDynamism === null || $rightDynamism === null) { + return; + } + + if ($leftDynamism >= $rightDynamism) { + return; + } + + if ($leftDynamism >= 900 && $rightDynamism >= 900) { + return; + } + + $errorParameters = [ + 'Yoda comparisons are disallowed.', + $comparisonTokenPointer, + self::CODE_DISALLOWED_YODA_COMPARISON, + ]; + + $lastRightSideTokenPointer = array_keys($rightSideTokens)[count($rightSideTokens) - 1]; + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $lastRightSideTokenPointer + 1); + if ($tokens[$nextPointer]['code'] === T_EQUAL) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + if (!$fix) { + return; + } + + YodaHelper::fix($phpcsFile, $leftSideTokens, $rightSideTokens); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/EarlyExitSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/EarlyExitSniff.php new file mode 100644 index 000000000..fd33700a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/EarlyExitSniff.php @@ -0,0 +1,480 @@ + + */ + public function register(): array + { + return [ + T_IF, + T_ELSEIF, + T_ELSE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_IF) { + $this->processIf($phpcsFile, $pointer); + } elseif ($tokens[$pointer]['code'] === T_ELSEIF) { + $this->processElseIf($phpcsFile, $pointer); + } else { + $this->processElse($phpcsFile, $pointer); + } + } + + private function processElse(File $phpcsFile, int $elsePointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('scope_opener', $tokens[$elsePointer])) { + // Else without curly braces is not supported. + return; + } + + try { + $allConditionsPointers = $this->getAllConditionsPointers($phpcsFile, $elsePointer); + } catch (Throwable $e) { + // Else without curly braces is not supported. + return; + } + + if (TokenHelper::findNext( + $phpcsFile, + T_FUNCTION, + $tokens[$elsePointer]['scope_opener'] + 1, + $tokens[$elsePointer]['scope_closer'] + ) !== null) { + return; + } + + $ifPointer = $allConditionsPointers[0]; + $ifEarlyExitPointer = null; + $elseEarlyExitPointer = null; + $previousConditionPointer = null; + $previousConditionEarlyExitPointer = null; + + foreach ($allConditionsPointers as $conditionPointer) { + $conditionEarlyExitPointer = $this->findEarlyExitInScope( + $phpcsFile, + $tokens[$conditionPointer]['scope_opener'], + $tokens[$conditionPointer]['scope_closer'] + ); + + if ($conditionPointer === $elsePointer) { + $elseEarlyExitPointer = $conditionEarlyExitPointer; + continue; + } + + if (count($allConditionsPointers) > 2 && $conditionEarlyExitPointer === null) { + return; + } + + $previousConditionPointer = $conditionPointer; + $previousConditionEarlyExitPointer = $conditionEarlyExitPointer; + + if ($conditionPointer === $ifPointer) { + $ifEarlyExitPointer = $conditionEarlyExitPointer; + continue; + } + } + + if ($ifEarlyExitPointer === null && $elseEarlyExitPointer === null) { + return; + } + + if ($elseEarlyExitPointer !== null && $previousConditionEarlyExitPointer === null) { + $fix = $phpcsFile->addFixableError('Use early exit instead of "else".', $elsePointer, self::CODE_EARLY_EXIT_NOT_USED); + + if (!$fix) { + return; + } + + $ifCodePointers = $this->getScopeCodePointers($phpcsFile, $ifPointer); + $elseCode = $this->getScopeCode($phpcsFile, $elsePointer); + $negativeIfCondition = ConditionHelper::getNegativeCondition( + $phpcsFile, + $tokens[$ifPointer]['parenthesis_opener'], + $tokens[$ifPointer]['parenthesis_closer'] + ); + $afterIfCode = IndentationHelper::fixIndentation( + $phpcsFile, + $ifCodePointers, + IndentationHelper::getIndentation($phpcsFile, $ifPointer) + ); + + $ifContent = sprintf('if %s {%s}%s%s', $negativeIfCondition, $elseCode, $phpcsFile->eolChar, $afterIfCode); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $ifPointer, $tokens[$elsePointer]['scope_closer'], $ifContent); + + $phpcsFile->fixer->endChangeset(); + + return; + } + + $fix = $phpcsFile->addFixableError('Remove useless "else" to reduce code nesting.', $elsePointer, self::CODE_USELESS_ELSE); + + if (!$fix) { + return; + } + + $elseCodePointers = $this->getScopeCodePointers($phpcsFile, $elsePointer); + $afterIfCode = IndentationHelper::fixIndentation( + $phpcsFile, + $elseCodePointers, + IndentationHelper::getIndentation($phpcsFile, $ifPointer) + ); + + $phpcsFile->fixer->beginChangeset(); + + $previousConditionContent = sprintf('%s%s', $phpcsFile->eolChar, $afterIfCode); + + FixerHelper::change( + $phpcsFile, + $tokens[$previousConditionPointer]['scope_closer'] + 1, + $tokens[$elsePointer]['scope_closer'], + $previousConditionContent + ); + + $phpcsFile->fixer->endChangeset(); + } + + private function processElseIf(File $phpcsFile, int $elseIfPointer): void + { + $tokens = $phpcsFile->getTokens(); + + try { + $allConditionsPointers = $this->getAllConditionsPointers($phpcsFile, $elseIfPointer); + } catch (Throwable $e) { + // Elseif without curly braces is not supported. + return; + } + + if (TokenHelper::findNext( + $phpcsFile, + T_FUNCTION, + $tokens[$elseIfPointer]['scope_opener'] + 1, + $tokens[$elseIfPointer]['scope_closer'] + ) !== null) { + return; + } + + foreach ($allConditionsPointers as $conditionPointer) { + $conditionEarlyExitPointer = $this->findEarlyExitInScope( + $phpcsFile, + $tokens[$conditionPointer]['scope_opener'], + $tokens[$conditionPointer]['scope_closer'] + ); + + if ($conditionPointer === $elseIfPointer) { + break; + } + + if ($conditionEarlyExitPointer === null) { + return; + } + } + + $fix = $phpcsFile->addFixableError('Use "if" instead of "elseif".', $elseIfPointer, self::CODE_USELESS_ELSEIF); + + if (!$fix) { + return; + } + + /** @var int $pointerBeforeElseIfPointer */ + $pointerBeforeElseIfPointer = TokenHelper::findPreviousNonWhitespace($phpcsFile, $elseIfPointer - 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeElseIfPointer, $elseIfPointer); + + $phpcsFile->fixer->addNewline($pointerBeforeElseIfPointer); + $phpcsFile->fixer->addNewline($pointerBeforeElseIfPointer); + + $phpcsFile->fixer->replaceToken( + $elseIfPointer, + sprintf('%sif', IndentationHelper::getIndentation($phpcsFile, $allConditionsPointers[0])) + ); + + $phpcsFile->fixer->endChangeset(); + } + + private function processIf(File $phpcsFile, int $ifPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('scope_closer', $tokens[$ifPointer])) { + // If without curly braces is not supported. + return; + } + + $nextPointer = TokenHelper::findNextNonWhitespace($phpcsFile, $tokens[$ifPointer]['scope_closer'] + 1); + if ($nextPointer === null || $tokens[$nextPointer]['code'] !== T_CLOSE_CURLY_BRACKET) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $ifPointer - 1); + if ( + $this->ignoreStandaloneIfInScope + && in_array($tokens[$previousPointer]['code'], [T_OPEN_CURLY_BRACKET, T_COLON], true) + ) { + return; + } + + if ( + $this->ignoreOneLineTrailingIf + && $tokens[$tokens[$ifPointer]['scope_opener']]['line'] + 2 === $tokens[$tokens[$ifPointer]['scope_closer']]['line'] + ) { + return; + } + + if ($this->ignoreTrailingIfWithOneInstruction) { + $pointerBeforeScopeCloser = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$ifPointer]['scope_closer'] - 1); + if ($tokens[$pointerBeforeScopeCloser]['code'] === T_SEMICOLON) { + $ignore = true; + + $searchStartPointer = $tokens[$ifPointer]['scope_opener'] + 1; + + while (true) { + $anotherSemicolonPointer = TokenHelper::findNext( + $phpcsFile, + T_SEMICOLON, + $searchStartPointer, + $pointerBeforeScopeCloser + ); + if ($anotherSemicolonPointer === null) { + break; + } + + if (ScopeHelper::isInSameScope($phpcsFile, $anotherSemicolonPointer, $pointerBeforeScopeCloser)) { + $ignore = false; + break; + } + + $searchStartPointer = $anotherSemicolonPointer + 1; + } + + if ($ignore) { + return; + } + } + } + + $scopePointer = $tokens[$nextPointer]['scope_condition']; + + if (!in_array($tokens[$scopePointer]['code'], [T_FUNCTION, T_CLOSURE, T_WHILE, T_DO, T_FOREACH, T_FOR], true)) { + return; + } + + if ($this->isEarlyExitInScope($phpcsFile, $tokens[$ifPointer]['scope_opener'], $tokens[$ifPointer]['scope_closer'])) { + return; + } + + $fix = $phpcsFile->addFixableError('Use early exit to reduce code nesting.', $ifPointer, self::CODE_EARLY_EXIT_NOT_USED); + if (!$fix) { + return; + } + + $ifCodePointers = $this->getScopeCodePointers($phpcsFile, $ifPointer); + $ifIndentation = IndentationHelper::getIndentation($phpcsFile, $ifPointer); + $earlyExitCode = $this->getEarlyExitCode($tokens[$scopePointer]['code']); + $earlyExitCodeIndentation = IndentationHelper::addIndentation($ifIndentation); + + $negativeIfCondition = ConditionHelper::getNegativeCondition( + $phpcsFile, + $tokens[$ifPointer]['parenthesis_opener'], + $tokens[$ifPointer]['parenthesis_closer'] + ); + $afterIfCode = IndentationHelper::fixIndentation($phpcsFile, $ifCodePointers, $ifIndentation); + + $ifContent = sprintf( + 'if %s {%s%s%s;%s%s}%s%s', + $negativeIfCondition, + $phpcsFile->eolChar, + $earlyExitCodeIndentation, + $earlyExitCode, + $phpcsFile->eolChar, + $ifIndentation, + $phpcsFile->eolChar, + $afterIfCode + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $ifPointer, $tokens[$ifPointer]['scope_closer'], $ifContent); + + $phpcsFile->fixer->endChangeset(); + } + + private function getScopeCode(File $phpcsFile, int $scopePointer): string + { + $tokens = $phpcsFile->getTokens(); + return TokenHelper::getContent($phpcsFile, $tokens[$scopePointer]['scope_opener'] + 1, $tokens[$scopePointer]['scope_closer'] - 1); + } + + /** + * @return list + */ + private function getScopeCodePointers(File $phpcsFile, int $scopePointer): array + { + $tokens = $phpcsFile->getTokens(); + return range($tokens[$scopePointer]['scope_opener'] + 1, $tokens[$scopePointer]['scope_closer'] - 1); + } + + /** + * @param string|int $code + */ + private function getEarlyExitCode($code): string + { + if (in_array($code, [T_WHILE, T_DO, T_FOREACH, T_FOR], true)) { + return 'continue'; + } + + return 'return'; + } + + private function findEarlyExitInScope(File $phpcsFile, int $startPointer, int $endPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $ifPointers = TokenHelper::findNextAll($phpcsFile, T_IF, $startPointer + 1, $endPointer); + foreach ($ifPointers as $ifPointer) { + if ($tokens[$ifPointer]['level'] - 1 !== $tokens[$startPointer]['level']) { + continue; + } + + $conditionPointers = $this->getAllConditionsPointers($phpcsFile, $ifPointer); + foreach ($conditionPointers as $conditionPointer) { + if ($this->findEarlyExitInScope( + $phpcsFile, + $tokens[$conditionPointer]['scope_opener'], + $tokens[$conditionPointer]['scope_closer'] + ) === null) { + return null; + } + } + } + + $lastSemicolonInScopePointer = TokenHelper::findPreviousEffective($phpcsFile, $endPointer - 1, $startPointer); + return $tokens[$lastSemicolonInScopePointer]['code'] === T_SEMICOLON + ? TokenHelper::findPreviousLocal($phpcsFile, TokenHelper::$earlyExitTokenCodes, $lastSemicolonInScopePointer - 1, $startPointer) + : null; + } + + private function isEarlyExitInScope(File $phpcsFile, int $startPointer, int $endPointer): bool + { + return $this->findEarlyExitInScope($phpcsFile, $startPointer, $endPointer) !== null; + } + + /** + * @return list + */ + private function getAllConditionsPointers(File $phpcsFile, int $conditionPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $conditionsPointers = [$conditionPointer]; + + if ( + isset($tokens[$conditionPointer]['scope_opener']) + && $tokens[$tokens[$conditionPointer]['scope_opener']]['code'] === T_COLON + ) { + // Alternative control structure syntax. + throw new Exception(sprintf('"%s" without curly braces is not supported.', $tokens[$conditionPointer]['content'])); + } + + if ($tokens[$conditionPointer]['code'] !== T_IF) { + $currentConditionPointer = $conditionPointer; + do { + $previousConditionCloseParenthesisPointer = TokenHelper::findPreviousEffective($phpcsFile, $currentConditionPointer - 1); + $currentConditionPointer = $tokens[$previousConditionCloseParenthesisPointer]['scope_condition']; + + $conditionsPointers[] = $currentConditionPointer; + } while ($tokens[$currentConditionPointer]['code'] !== T_IF); + } + + if ($tokens[$conditionPointer]['code'] !== T_ELSE) { + if (!array_key_exists('scope_closer', $tokens[$conditionPointer])) { + throw new Exception(sprintf('"%s" without curly braces is not supported.', $tokens[$conditionPointer]['content'])); + } + + $currentConditionPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$conditionPointer]['scope_closer'] + 1); + if ($currentConditionPointer !== null) { + while (in_array($tokens[$currentConditionPointer]['code'], [T_ELSEIF, T_ELSE], true)) { + $conditionsPointers[] = $currentConditionPointer; + + if (!array_key_exists('scope_closer', $tokens[$currentConditionPointer])) { + throw new Exception( + sprintf('"%s" without curly braces is not supported.', $tokens[$currentConditionPointer]['content']) + ); + } + + $currentConditionPointer = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$currentConditionPointer]['scope_closer'] + 1 + ); + } + } + } + + sort($conditionsPointers); + + return $conditionsPointers; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/JumpStatementsSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/JumpStatementsSpacingSniff.php new file mode 100644 index 000000000..334fbbcee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/JumpStatementsSpacingSniff.php @@ -0,0 +1,282 @@ + */ + public $jumpStatements = []; + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $jumpStatementPointer + */ + public function process(File $phpcsFile, $jumpStatementPointer): void + { + $this->linesCountBefore = SniffSettingsHelper::normalizeInteger($this->linesCountBefore); + $this->linesCountBeforeFirst = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirst); + $this->linesCountBeforeWhenFirstInCaseOrDefault = SniffSettingsHelper::normalizeNullableInteger( + $this->linesCountBeforeWhenFirstInCaseOrDefault + ); + $this->linesCountAfter = SniffSettingsHelper::normalizeInteger($this->linesCountAfter); + $this->linesCountAfterLast = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLast); + $this->linesCountAfterWhenLastInCaseOrDefault = SniffSettingsHelper::normalizeNullableInteger( + $this->linesCountAfterWhenLastInCaseOrDefault + ); + $this->linesCountAfterWhenLastInLastCaseOrDefault = SniffSettingsHelper::normalizeNullableInteger( + $this->linesCountAfterWhenLastInLastCaseOrDefault + ); + + if ($this->isOneOfYieldSpecialCases($phpcsFile, $jumpStatementPointer)) { + return; + } + + parent::process($phpcsFile, $jumpStatementPointer); + } + + /** + * @return list + */ + protected function getSupportedKeywords(): array + { + return [ + self::KEYWORD_GOTO, + self::KEYWORD_BREAK, + self::KEYWORD_CONTINUE, + self::KEYWORD_RETURN, + self::KEYWORD_THROW, + self::KEYWORD_YIELD, + self::KEYWORD_YIELD_FROM, + ]; + } + + /** + * @return list + */ + protected function getKeywordsToCheck(): array + { + return $this->jumpStatements; + } + + protected function getLinesCountBefore(): int + { + return $this->linesCountBefore; + } + + protected function getLinesCountBeforeFirst(File $phpcsFile, int $jumpStatementPointer): int + { + if ( + $this->linesCountBeforeWhenFirstInCaseOrDefault !== null + && $this->isFirstInCaseOrDefault($phpcsFile, $jumpStatementPointer) + ) { + return $this->linesCountBeforeWhenFirstInCaseOrDefault; + } + + return $this->linesCountBeforeFirst; + } + + protected function getLinesCountAfter(): int + { + return $this->linesCountAfter; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + */ + protected function getLinesCountAfterLast(File $phpcsFile, int $jumpStatementPointer, int $jumpStatementEndPointer): int + { + if ( + $this->linesCountAfterWhenLastInLastCaseOrDefault !== null + && $this->isLastInLastCaseOrDefault($phpcsFile, $jumpStatementEndPointer) + ) { + return $this->linesCountAfterWhenLastInLastCaseOrDefault; + } + + if ( + $this->linesCountAfterWhenLastInCaseOrDefault !== null + && $this->isLastInCaseOrDefault($phpcsFile, $jumpStatementEndPointer) + ) { + return $this->linesCountAfterWhenLastInCaseOrDefault; + } + + return $this->linesCountAfterLast; + } + + protected function checkLinesBefore(File $phpcsFile, int $jumpStatementPointer): void + { + if ( + $this->allowSingleLineYieldStacking + && $this->isStackedSingleLineYield($phpcsFile, $jumpStatementPointer, true) + ) { + return; + } + + if ($this->isThrowExpression($phpcsFile, $jumpStatementPointer)) { + return; + } + + parent::checkLinesBefore($phpcsFile, $jumpStatementPointer); + } + + protected function checkLinesAfter(File $phpcsFile, int $jumpStatementPointer): void + { + if ( + $this->allowSingleLineYieldStacking + && $this->isStackedSingleLineYield($phpcsFile, $jumpStatementPointer, false) + ) { + return; + } + + if ($this->isThrowExpression($phpcsFile, $jumpStatementPointer)) { + return; + } + + parent::checkLinesAfter($phpcsFile, $jumpStatementPointer); + } + + private function isOneOfYieldSpecialCases(File $phpcsFile, int $jumpStatementPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $jumpStatementToken = $tokens[$jumpStatementPointer]; + if ($jumpStatementToken['code'] !== T_YIELD && $jumpStatementToken['code'] !== T_YIELD_FROM) { + return false; + } + + // check if yield is used inside parentheses (function call, while, ...) + if (array_key_exists('nested_parenthesis', $jumpStatementToken)) { + return true; + } + + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $jumpStatementPointer - 1); + + // check if yield is used in assignment + if (in_array($tokens[$pointerBefore]['code'], Tokens::$assignmentTokens, true)) { + return true; + } + + // check if yield is used in a return statement + return $tokens[$pointerBefore]['code'] === T_RETURN; + } + + private function isStackedSingleLineYield(File $phpcsFile, int $jumpStatementPointer, bool $previous): bool + { + $tokens = $phpcsFile->getTokens(); + $yields = [T_YIELD, T_YIELD_FROM]; + + if (!in_array($tokens[$jumpStatementPointer]['code'], $yields, true)) { + return false; + } + + $adjoiningYieldPointer = $previous + ? TokenHelper::findPrevious($phpcsFile, $yields, $jumpStatementPointer - 1) + : TokenHelper::findNext($phpcsFile, $yields, $jumpStatementPointer + 1); + + return $adjoiningYieldPointer !== null + && abs($tokens[$adjoiningYieldPointer]['line'] - $tokens[$jumpStatementPointer]['line']) === 1; + } + + private function isThrowExpression(File $phpcsFile, int $jumpStatementPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$jumpStatementPointer]['code'] !== T_THROW) { + return false; + } + + $pointerBefore = TokenHelper::findPreviousEffective($phpcsFile, $jumpStatementPointer - 1); + + return !in_array( + $tokens[$pointerBefore]['code'], + [T_SEMICOLON, T_COLON, T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_OPEN_TAG], + true + ); + } + + private function isFirstInCaseOrDefault(File $phpcsFile, int $jumpStatementPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $jumpStatementPointer - 1); + + if ($tokens[$previousPointer]['code'] !== T_COLON) { + return false; + } + + $firstPointerOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $previousPointer); + + return in_array($tokens[$firstPointerOnLine]['code'], [T_CASE, T_DEFAULT], true); + } + + private function isLastInCaseOrDefault(File $phpcsFile, int $jumpStatementEndPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $jumpStatementEndPointer + 1); + + if (in_array($tokens[$nextPointer]['code'], [T_CASE, T_DEFAULT], true)) { + return true; + } + + return $tokens[$nextPointer]['code'] === T_CLOSE_CURLY_BRACKET + && array_key_exists('scope_condition', $tokens[$nextPointer]) + && $tokens[$tokens[$nextPointer]['scope_condition']]['code'] === T_SWITCH; + } + + private function isLastInLastCaseOrDefault(File $phpcsFile, int $jumpStatementEndPointer): bool + { + if (!$this->isLastInCaseOrDefault($phpcsFile, $jumpStatementEndPointer)) { + return false; + } + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $jumpStatementEndPointer + 1); + + return !in_array($phpcsFile->getTokens()[$nextPointer]['code'], [T_CASE, T_DEFAULT], true); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/LanguageConstructWithParenthesesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/LanguageConstructWithParenthesesSniff.php new file mode 100644 index 000000000..b7f4eecf8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/LanguageConstructWithParenthesesSniff.php @@ -0,0 +1,102 @@ + + */ + public function register(): array + { + return [ + T_BREAK, + T_CONTINUE, + T_ECHO, + T_EXIT, + T_INCLUDE, + T_INCLUDE_ONCE, + T_PRINT, + T_REQUIRE, + T_REQUIRE_ONCE, + T_RETURN, + T_THROW, + T_YIELD, + T_YIELD_FROM, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $languageConstructPointer + */ + public function process(File $phpcsFile, $languageConstructPointer): void + { + $tokens = $phpcsFile->getTokens(); + /** @var int $openParenthesisPointer */ + $openParenthesisPointer = TokenHelper::findNextEffective($phpcsFile, $languageConstructPointer + 1); + if ($tokens[$openParenthesisPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $closeParenthesisPointer = $tokens[$openParenthesisPointer]['parenthesis_closer']; + $afterCloseParenthesisPointer = TokenHelper::findNextEffective($phpcsFile, $closeParenthesisPointer + 1); + if (!in_array($tokens[$afterCloseParenthesisPointer]['code'], [T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SHORT_ARRAY], true)) { + return; + } + + $containsContentBetweenParentheses = TokenHelper::findNextEffective( + $phpcsFile, + $openParenthesisPointer + 1, + $closeParenthesisPointer + ) !== null; + if ($tokens[$languageConstructPointer]['code'] === T_EXIT && $containsContentBetweenParentheses) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Usage of language construct "%s" with parentheses is disallowed.', $tokens[$languageConstructPointer]['content']), + $languageConstructPointer, + self::CODE_USED_WITH_PARENTHESES + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($openParenthesisPointer, ''); + if ($tokens[$openParenthesisPointer - 1]['code'] !== T_WHITESPACE && $containsContentBetweenParentheses) { + $phpcsFile->fixer->addContent($openParenthesisPointer, ' '); + } + $phpcsFile->fixer->replaceToken($closeParenthesisPointer, ''); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithParenthesesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithParenthesesSniff.php new file mode 100644 index 000000000..1d0b66782 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithParenthesesSniff.php @@ -0,0 +1,114 @@ + + */ + public function register(): array + { + return [ + T_NEW, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $newPointer + */ + public function process(File $phpcsFile, $newPointer): void + { + $tokens = $phpcsFile->getTokens(); + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $newPointer + 1); + + if ($tokens[$nextPointer]['code'] === T_ATTRIBUTE) { + $nextPointer = AttributeHelper::getAttributeTarget($phpcsFile, $nextPointer); + } + + if ($tokens[$nextPointer]['code'] === T_ANON_CLASS) { + return; + } + + if ($tokens[$nextPointer]['code'] === T_OPEN_PARENTHESIS) { + $nextPointer = $tokens[$nextPointer]['parenthesis_closer']; + } + + $shouldBeOpenParenthesisPointer = $nextPointer + 1; + do { + $shouldBeOpenParenthesisPointer = TokenHelper::findNext( + $phpcsFile, + [ + T_OPEN_PARENTHESIS, + T_SEMICOLON, + T_COMMA, + T_INLINE_THEN, + T_INLINE_ELSE, + T_COALESCE, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_SQUARE_BRACKET, + T_CLOSE_PARENTHESIS, + T_DOUBLE_ARROW, + ], + $shouldBeOpenParenthesisPointer + ); + + if ( + $shouldBeOpenParenthesisPointer === null + || $tokens[$shouldBeOpenParenthesisPointer]['code'] !== T_CLOSE_SQUARE_BRACKET + || $tokens[$shouldBeOpenParenthesisPointer]['bracket_opener'] <= $newPointer + ) { + break; + } + + $shouldBeOpenParenthesisPointer++; + } while (true); + + if ( + $shouldBeOpenParenthesisPointer !== null + && $tokens[$shouldBeOpenParenthesisPointer]['code'] === T_OPEN_PARENTHESIS + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Usage of "new" without parentheses is disallowed.', + $newPointer, + self::CODE_MISSING_PARENTHESES + ); + if (!$fix) { + return; + } + + /** @var int $classNameEndPointer */ + $classNameEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $shouldBeOpenParenthesisPointer - 1); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($classNameEndPointer, '()'); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithoutParenthesesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithoutParenthesesSniff.php new file mode 100644 index 000000000..6ea0cfb54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/NewWithoutParenthesesSniff.php @@ -0,0 +1,106 @@ + + */ + public function register(): array + { + return [ + T_NEW, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $newPointer + */ + public function process(File $phpcsFile, $newPointer): void + { + $tokens = $phpcsFile->getTokens(); + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $newPointer + 1); + + if ($tokens[$nextPointer]['code'] === T_ANON_CLASS) { + return; + } + + $parenthesisOpenerPointer = $nextPointer + 1; + do { + /** @var int $parenthesisOpenerPointer */ + $parenthesisOpenerPointer = TokenHelper::findNext( + $phpcsFile, + [ + T_OPEN_PARENTHESIS, + T_SEMICOLON, + T_COMMA, + T_INLINE_THEN, + T_INLINE_ELSE, + T_COALESCE, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_SQUARE_BRACKET, + T_CLOSE_PARENTHESIS, + T_DOUBLE_ARROW, + ], + $parenthesisOpenerPointer + ); + + if ( + $tokens[$parenthesisOpenerPointer]['code'] !== T_CLOSE_SQUARE_BRACKET + || $tokens[$parenthesisOpenerPointer]['bracket_opener'] <= $newPointer + ) { + break; + } + + $parenthesisOpenerPointer++; + } while (true); + + if ($tokens[$parenthesisOpenerPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $nextPointer = TokenHelper::findNextNonWhitespace($phpcsFile, $parenthesisOpenerPointer + 1); + if ($nextPointer !== $tokens[$parenthesisOpenerPointer]['parenthesis_closer']) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless parentheses in "new".', $newPointer, self::CODE_USELESS_PARENTHESES); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding( + $phpcsFile, + $parenthesisOpenerPointer, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + ); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineConditionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineConditionSniff.php new file mode 100644 index 000000000..62f911dc5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineConditionSniff.php @@ -0,0 +1,188 @@ +minLineLength = SniffSettingsHelper::normalizeInteger($this->minLineLength); + + if ($this->shouldBeSkipped($phpcsFile, $controlStructurePointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = $tokens[$controlStructurePointer]['parenthesis_opener']; + $parenthesisCloserPointer = $tokens[$controlStructurePointer]['parenthesis_closer']; + + $booleanOperatorPointers = TokenHelper::findNextAll( + $phpcsFile, + Tokens::$booleanOperators, + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ); + + if ($booleanOperatorPointers === []) { + return; + } + + $conditionStartPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + $conditionEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisCloserPointer - 1); + + $conditionStartsOnNewLine = $tokens[$parenthesisOpenerPointer]['line'] !== $tokens[$conditionStartPointer]['line']; + $conditionEndsOnNewLine = $tokens[$parenthesisCloserPointer]['line'] !== $tokens[$conditionEndPointer]['line']; + + $lineStart = $this->getLineStart($phpcsFile, $conditionStartsOnNewLine ? $conditionStartPointer - 1 : $parenthesisOpenerPointer); + $lineEnd = $this->getLineEnd($phpcsFile, $conditionEndsOnNewLine ? $conditionEndPointer + 1 : $parenthesisCloserPointer); + + $condition = $this->getCondition($phpcsFile, $parenthesisOpenerPointer, $parenthesisCloserPointer); + + $lineLength = strlen($lineStart . $condition . $lineEnd); + $conditionLinesCount = $tokens[$conditionEndPointer]['line'] - $tokens[$conditionStartPointer]['line'] + 1; + + if (!$this->shouldReportError($lineLength, $conditionLinesCount, count($booleanOperatorPointers))) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Condition of "%s" should be split to more lines so each condition part is on its own line.', + $this->getControlStructureName($phpcsFile, $controlStructurePointer) + ), + $controlStructurePointer, + self::CODE_REQUIRED_MULTI_LINE_CONDITION + ); + + if (!$fix) { + return; + } + + $controlStructureIndentation = IndentationHelper::getIndentation( + $phpcsFile, + $conditionStartsOnNewLine + ? $conditionStartPointer + : TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $parenthesisOpenerPointer) + ); + + $conditionIndentation = $conditionStartsOnNewLine + ? $controlStructureIndentation + : IndentationHelper::addIndentation($controlStructureIndentation); + + $innerConditionLevel = 0; + + $phpcsFile->fixer->beginChangeset(); + + if (!$conditionStartsOnNewLine) { + FixerHelper::removeWhitespaceBefore($phpcsFile, $conditionStartPointer); + $phpcsFile->fixer->addContentBefore($conditionStartPointer, $phpcsFile->eolChar . $conditionIndentation); + } + + for ($i = $conditionStartPointer; $i <= $conditionEndPointer; $i++) { + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $containsBooleanOperator = TokenHelper::findNext( + $phpcsFile, + Tokens::$booleanOperators, + $i + 1, + $tokens[$i]['parenthesis_closer'] + ) !== null; + + $innerConditionLevel++; + + if ($containsBooleanOperator) { + FixerHelper::removeWhitespaceAfter($phpcsFile, $i); + + $phpcsFile->fixer->addContent( + $i, + $phpcsFile->eolChar . IndentationHelper::addIndentation($conditionIndentation, $innerConditionLevel) + ); + + FixerHelper::removeWhitespaceBefore($phpcsFile, $tokens[$i]['parenthesis_closer']); + + $phpcsFile->fixer->addContentBefore( + $tokens[$i]['parenthesis_closer'], + $phpcsFile->eolChar . IndentationHelper::addIndentation($conditionIndentation, $innerConditionLevel - 1) + ); + } + + continue; + } + + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + $innerConditionLevel--; + continue; + } + + if (!in_array($tokens[$i]['code'], Tokens::$booleanOperators, true)) { + continue; + } + + $innerConditionIndentation = $conditionIndentation; + if ($innerConditionLevel > 0) { + $innerConditionIndentation = IndentationHelper::addIndentation($innerConditionIndentation, $innerConditionLevel); + } + + if ($this->booleanOperatorOnPreviousLine) { + $phpcsFile->fixer->addContent($i, $phpcsFile->eolChar . $innerConditionIndentation); + + FixerHelper::removeWhitespaceAfter($phpcsFile, $i); + + continue; + + } + + FixerHelper::removeWhitespaceBefore($phpcsFile, $i); + + $phpcsFile->fixer->addContentBefore($i, $phpcsFile->eolChar . $innerConditionIndentation); + } + + if (!$conditionEndsOnNewLine) { + FixerHelper::removeWhitespaceAfter($phpcsFile, $conditionEndPointer); + $phpcsFile->fixer->addContent($conditionEndPointer, $phpcsFile->eolChar . $controlStructureIndentation); + } + + $phpcsFile->fixer->endChangeset(); + } + + private function shouldReportError(int $lineLength, int $conditionLinesCount, int $booleanOperatorPointersCount): bool + { + if ($conditionLinesCount === 1) { + return $this->minLineLength === 0 || $lineLength >= $this->minLineLength; + } + + return $this->alwaysSplitAllConditionParts + ? $conditionLinesCount < $booleanOperatorPointersCount + 1 + : false; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineTernaryOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineTernaryOperatorSniff.php new file mode 100644 index 000000000..09ae72377 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireMultiLineTernaryOperatorSniff.php @@ -0,0 +1,178 @@ + + */ + public function register(): array + { + return [ + T_INLINE_THEN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $inlineThenPointer + */ + public function process(File $phpcsFile, $inlineThenPointer): void + { + $this->lineLengthLimit = SniffSettingsHelper::normalizeInteger($this->lineLengthLimit); + $this->minExpressionsLength = SniffSettingsHelper::normalizeNullableInteger($this->minExpressionsLength); + + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $inlineThenPointer + 1); + if ($tokens[$nextPointer]['code'] === T_INLINE_ELSE) { + return; + } + + $inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer); + + if ($tokens[$inlineThenPointer]['line'] !== $tokens[$inlineElsePointer]['line']) { + return; + } + + $inlineElseEndPointer = TernaryOperatorHelper::getEndPointer($phpcsFile, $inlineThenPointer, $inlineElsePointer); + $pointerAfterInlineElseEnd = TokenHelper::findNextEffective($phpcsFile, $inlineElseEndPointer + 1); + + if ($pointerAfterInlineElseEnd === null || $tokens[$pointerAfterInlineElseEnd]['code'] !== T_SEMICOLON) { + return; + } + + $endOfLineBeforeInlineThenPointer = $this->getEndOfLineBefore($phpcsFile, $inlineThenPointer); + + $actualLineLength = strlen(TokenHelper::getContent($phpcsFile, $endOfLineBeforeInlineThenPointer + 1, $pointerAfterInlineElseEnd)); + + if ($actualLineLength <= $this->lineLengthLimit) { + return; + } + + $expressionsLength = strlen(TokenHelper::getContent($phpcsFile, $inlineThenPointer + 1, $pointerAfterInlineElseEnd - 1)); + + if ( + $this->minExpressionsLength !== null + && $this->minExpressionsLength >= $expressionsLength + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Ternary operator should be reformatted to more lines.', + $inlineThenPointer, + self::CODE_MULTI_LINE_TERNARY_OPERATOR_NOT_USED + ); + + if (!$fix) { + return; + } + + $indentation = $this->getIndentation($phpcsFile, $endOfLineBeforeInlineThenPointer); + $pointerBeforeInlineThen = TokenHelper::findPreviousEffective($phpcsFile, $inlineThenPointer - 1); + $pointerBeforeInlineElse = TokenHelper::findPreviousEffective($phpcsFile, $inlineElsePointer - 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeInlineThen, $inlineThenPointer); + + $phpcsFile->fixer->addContentBefore($inlineThenPointer, $phpcsFile->eolChar . $indentation); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeInlineElse, $inlineElsePointer); + + $phpcsFile->fixer->addContentBefore($inlineElsePointer, $phpcsFile->eolChar . $indentation); + + $phpcsFile->fixer->endChangeset(); + } + + private function getEndOfLineBefore(File $phpcsFile, int $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $endOfLineBefore = null; + + $startPointer = $pointer - 1; + while (true) { + $possibleEndOfLinePointer = TokenHelper::findPrevious( + $phpcsFile, + array_merge([T_WHITESPACE, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO], TokenHelper::$inlineCommentTokenCodes), + $startPointer + ); + if ( + $tokens[$possibleEndOfLinePointer]['code'] === T_WHITESPACE + && $tokens[$possibleEndOfLinePointer]['content'] === $phpcsFile->eolChar + ) { + $endOfLineBefore = $possibleEndOfLinePointer; + break; + } + + if ( + $tokens[$possibleEndOfLinePointer]['code'] === T_OPEN_TAG + || $tokens[$possibleEndOfLinePointer]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + $endOfLineBefore = $possibleEndOfLinePointer; + break; + } + + if ( + in_array($tokens[$possibleEndOfLinePointer]['code'], TokenHelper::$inlineCommentTokenCodes, true) + && substr($tokens[$possibleEndOfLinePointer]['content'], -1) === $phpcsFile->eolChar + ) { + $endOfLineBefore = $possibleEndOfLinePointer; + break; + } + + $startPointer = $possibleEndOfLinePointer - 1; + } + + /** @var int $endOfLineBefore */ + $endOfLineBefore = $endOfLineBefore; + return $endOfLineBefore; + } + + private function getIndentation(File $phpcsFile, int $endOfLinePointer): string + { + $pointerAfterWhitespace = TokenHelper::findNextNonWhitespace($phpcsFile, $endOfLinePointer + 1); + $actualIndentation = TokenHelper::getContent($phpcsFile, $endOfLinePointer + 1, $pointerAfterWhitespace - 1); + + if (strlen($actualIndentation) !== 0) { + return $actualIndentation . (substr( + $actualIndentation, + -1 + ) === IndentationHelper::TAB_INDENT ? IndentationHelper::TAB_INDENT : IndentationHelper::SPACES_INDENT); + } + + $tabPointer = TokenHelper::findPreviousContent($phpcsFile, T_WHITESPACE, IndentationHelper::TAB_INDENT, $endOfLinePointer - 1); + return $tabPointer !== null ? IndentationHelper::TAB_INDENT : IndentationHelper::SPACES_INDENT; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceEqualOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceEqualOperatorSniff.php new file mode 100644 index 000000000..03823e00f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceEqualOperatorSniff.php @@ -0,0 +1,99 @@ + + */ + public function register(): array + { + return [ + T_EQUAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $equalPointer + */ + public function process(File $phpcsFile, $equalPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 70400); + + if (!$this->enable) { + return; + } + + /** @var int $variableStartPointer */ + $variableStartPointer = TokenHelper::findNextEffective($phpcsFile, $equalPointer + 1); + $variableEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $variableStartPointer); + + if ($variableEndPointer === null) { + return; + } + + $nullCoalescePointer = TokenHelper::findNextEffective($phpcsFile, $variableEndPointer + 1); + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$nullCoalescePointer]['code'] !== T_COALESCE) { + return; + } + + $variableContent = IdentificatorHelper::getContent($phpcsFile, $variableStartPointer, $variableEndPointer); + + /** @var int $beforeEqualEndPointer */ + $beforeEqualEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $equalPointer - 1); + $beforeEqualStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $beforeEqualEndPointer); + + if ($beforeEqualStartPointer === null) { + return; + } + + $beforeEqualVariableContent = IdentificatorHelper::getContent($phpcsFile, $beforeEqualStartPointer, $beforeEqualEndPointer); + + if ($beforeEqualVariableContent !== $variableContent) { + return; + } + + $semicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $equalPointer + 1); + if (TokenHelper::findNext($phpcsFile, Tokens::$operators, $nullCoalescePointer + 1, $semicolonPointer) !== null) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use "??=" operator instead of "=" and "??".', + $equalPointer, + self::CODE_REQUIRED_NULL_COALESCE_EQUAL_OPERATOR + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $equalPointer, $nullCoalescePointer, '??='); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceOperatorSniff.php new file mode 100644 index 000000000..333ac6ab0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullCoalesceOperatorSniff.php @@ -0,0 +1,217 @@ + + */ + public function register(): array + { + return [ + T_ISSET, + T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_ISSET) { + $this->checkIsset($phpcsFile, $pointer); + } else { + $this->checkIdenticalOperator($phpcsFile, $pointer); + } + } + + public function checkIsset(File $phpcsFile, int $issetPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $issetPointer - 1); + if ($tokens[$previousPointer]['code'] === T_BOOLEAN_NOT) { + return; + } + + if (in_array($tokens[$previousPointer]['code'], Tokens::$booleanOperators, true)) { + return; + } + + $openParenthesisPointer = TokenHelper::findNextEffective($phpcsFile, $issetPointer + 1); + $closeParenthesisPointer = $tokens[$openParenthesisPointer]['parenthesis_closer']; + + /** @var int $inlineThenPointer */ + $inlineThenPointer = TokenHelper::findNextEffective($phpcsFile, $closeParenthesisPointer + 1); + if ($tokens[$inlineThenPointer]['code'] !== T_INLINE_THEN) { + return; + } + + $commaPointer = TokenHelper::findNext($phpcsFile, T_COMMA, $openParenthesisPointer + 1, $closeParenthesisPointer); + if ($commaPointer !== null) { + return; + } + + $inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer); + + $variableContent = IdentificatorHelper::getContent($phpcsFile, $openParenthesisPointer + 1, $closeParenthesisPointer - 1); + $thenContent = IdentificatorHelper::getContent($phpcsFile, $inlineThenPointer + 1, $inlineElsePointer - 1); + + if ($variableContent !== $thenContent) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use null coalesce operator instead of ternary operator.', + $inlineThenPointer, + self::CODE_NULL_COALESCE_OPERATOR_NOT_USED + ); + if (!$fix) { + return; + } + + $startPointer = $issetPointer; + if (in_array($tokens[$previousPointer]['code'], Tokens::$castTokens, true)) { + $startPointer = $previousPointer; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $startPointer, $inlineElsePointer, sprintf('%s ??', $variableContent)); + + $phpcsFile->fixer->endChangeset(); + } + + public function checkIdenticalOperator(File $phpcsFile, int $identicalOperator): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $pointerBeforeIdenticalOperator */ + $pointerBeforeIdenticalOperator = TokenHelper::findPreviousEffective($phpcsFile, $identicalOperator - 1); + /** @var int $pointerAfterIdenticalOperator */ + $pointerAfterIdenticalOperator = TokenHelper::findNextEffective($phpcsFile, $identicalOperator + 1); + + if ( + $tokens[$pointerBeforeIdenticalOperator]['code'] !== T_NULL + && $tokens[$pointerAfterIdenticalOperator]['code'] !== T_NULL + ) { + return; + } + + $isYodaCondition = $tokens[$pointerBeforeIdenticalOperator]['code'] === T_NULL; + + $variableEndPointer = $isYodaCondition ? $pointerAfterIdenticalOperator : $pointerBeforeIdenticalOperator; + $tmpPointer = $variableEndPointer; + while ($tokens[$tmpPointer]['code'] === T_CLOSE_PARENTHESIS) { + /** @var int $tmpPointer */ + $tmpPointer = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$tmpPointer]['parenthesis_opener'] - 1); + } + $variableStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $tmpPointer); + + if ($variableStartPointer === null) { + return; + } + + $pointerBeforeCondition = TokenHelper::findPreviousEffective( + $phpcsFile, + ($isYodaCondition ? $pointerBeforeIdenticalOperator : $variableStartPointer) - 1 + ); + + if (in_array($tokens[$pointerBeforeCondition]['code'], Tokens::$booleanOperators, true)) { + return; + } + + /** @var int $inlineThenPointer */ + $inlineThenPointer = TokenHelper::findNextEffective( + $phpcsFile, + ($isYodaCondition ? $variableEndPointer : $pointerAfterIdenticalOperator) + 1 + ); + if ($tokens[$inlineThenPointer]['code'] !== T_INLINE_THEN) { + return; + } + + $inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer); + $inlineElseEndPointer = TernaryOperatorHelper::getEndPointer($phpcsFile, $inlineThenPointer, $inlineElsePointer); + + $pointerAfterInlineElseEnd = TokenHelper::findNextEffective($phpcsFile, $inlineElseEndPointer + 1); + + $variableContent = IdentificatorHelper::getContent($phpcsFile, $variableStartPointer, $variableEndPointer); + + /** @var int $compareToStartPointer */ + $compareToStartPointer = TokenHelper::findNextEffective( + $phpcsFile, + ($tokens[$identicalOperator]['code'] === T_IS_IDENTICAL ? $inlineElsePointer : $inlineThenPointer) + 1 + ); + /** @var int $compareToEndPointer */ + $compareToEndPointer = TokenHelper::findPreviousEffective( + $phpcsFile, + ($tokens[$identicalOperator]['code'] === T_IS_IDENTICAL ? $pointerAfterInlineElseEnd : $inlineElsePointer) - 1 + ); + + $compareToContent = IdentificatorHelper::getContent($phpcsFile, $compareToStartPointer, $compareToEndPointer); + + if ($compareToContent !== $variableContent) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use null coalesce operator instead of ternary operator.', + $inlineThenPointer, + self::CODE_NULL_COALESCE_OPERATOR_NOT_USED + ); + + if (!$fix) { + return; + } + + /** @var int $conditionStart */ + $conditionStart = $isYodaCondition ? $pointerBeforeIdenticalOperator : $variableStartPointer; + $variableContent = trim(TokenHelper::getContent($phpcsFile, $variableStartPointer, $variableEndPointer)); + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->replaceToken($conditionStart, sprintf('%s ??', $variableContent)); + + if ($tokens[$identicalOperator]['code'] === T_IS_IDENTICAL) { + FixerHelper::removeBetweenIncluding($phpcsFile, $conditionStart + 1, $inlineThenPointer); + + $pointerBeforeInlineElse = TokenHelper::findPreviousEffective($phpcsFile, $inlineElsePointer - 1); + + FixerHelper::removeBetweenIncluding($phpcsFile, $pointerBeforeInlineElse + 1, $inlineElseEndPointer); + + } else { + FixerHelper::removeBetweenIncluding($phpcsFile, $conditionStart + 1, $inlineElsePointer); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullSafeObjectOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullSafeObjectOperatorSniff.php new file mode 100644 index 000000000..4dd1f9e94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireNullSafeObjectOperatorSniff.php @@ -0,0 +1,513 @@ +|\?->)~'; + + /** @var bool|null */ + public $enable = null; + + /** + * @return array + */ + public function register(): array + { + return [ + T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $identicalPointer + */ + public function process(File $phpcsFile, $identicalPointer): int + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000); + + if (!$this->enable) { + return $identicalPointer + 1; + } + + $tokens = $phpcsFile->getTokens(); + + [$pointerBeforeIdentical, $pointerAfterIdentical] = $this->getIdenticalData($phpcsFile, $identicalPointer); + + if ($tokens[$pointerBeforeIdentical]['code'] !== T_NULL && $tokens[$pointerAfterIdentical]['code'] !== T_NULL) { + return $identicalPointer + 1; + } + + [$identificatorStartPointer, $identificatorEndPointer, $conditionStartPointer] = $this->getConditionData( + $phpcsFile, + $pointerBeforeIdentical, + $pointerAfterIdentical + ); + + if ($identificatorStartPointer === null || $identificatorEndPointer === null) { + return $identicalPointer + 1; + } + + $isYoda = $tokens[$pointerBeforeIdentical]['code'] === T_NULL; + $identificator = IdentificatorHelper::getContent($phpcsFile, $identificatorStartPointer, $identificatorEndPointer); + + $pointerAfterCondition = TokenHelper::findNextEffective( + $phpcsFile, + ($isYoda ? $identificatorEndPointer : $pointerAfterIdentical) + 1 + ); + + $allowedBooleanCondition = $tokens[$identicalPointer]['code'] === T_IS_NOT_IDENTICAL ? T_BOOLEAN_AND : T_BOOLEAN_OR; + if ($tokens[$pointerAfterCondition]['code'] === $allowedBooleanCondition) { + return $this->checkNextCondition($phpcsFile, $identicalPointer, $conditionStartPointer, $identificator, $pointerAfterCondition); + } + + if ($tokens[$pointerAfterCondition]['code'] === T_INLINE_THEN) { + $this->checkTernaryOperator($phpcsFile, $identicalPointer, $conditionStartPointer, $identificator, $pointerAfterCondition); + return $pointerAfterCondition + 1; + } + + return $identicalPointer + 1; + } + + private function checkTernaryOperator( + File $phpcsFile, + int $identicalPointer, + int $conditionStartPointer, + string $identificator, + int $inlineThenPointer + ): void + { + $tokens = $phpcsFile->getTokens(); + + $ternaryOperatorStartPointer = TernaryOperatorHelper::getStartPointer($phpcsFile, $inlineThenPointer); + + $searchStartPointer = $ternaryOperatorStartPointer; + do { + $booleanOperatorPointer = TokenHelper::findNext($phpcsFile, Tokens::$booleanOperators, $searchStartPointer, $inlineThenPointer); + if ($booleanOperatorPointer === null) { + break; + } + + $identicalPointer = TokenHelper::findNext( + $phpcsFile, + [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL], + $searchStartPointer, + $booleanOperatorPointer + ); + + if ($identicalPointer === null) { + return; + } + + $pointerAfterIdentical = TokenHelper::findNextEffective($phpcsFile, $identicalPointer + 1); + + if ($tokens[$pointerAfterIdentical]['code'] !== T_NULL) { + return; + } + + $searchStartPointer = $booleanOperatorPointer + 1; + + } while (true); + + $pointerBeforeCondition = TokenHelper::findPreviousEffective($phpcsFile, $conditionStartPointer - 1); + if (in_array($tokens[$pointerBeforeCondition]['code'], [T_BOOLEAN_AND, T_BOOLEAN_OR], true)) { + $previousIdenticalPointer = TokenHelper::findPreviousLocal( + $phpcsFile, + [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL], + $pointerBeforeCondition + ); + + if ($previousIdenticalPointer !== null) { + [$pointerBeforePreviousIdentical, $pointerAfterPreviousIdentical] = $this->getIdenticalData( + $phpcsFile, + $previousIdenticalPointer + ); + + [$previousIdentificatorStartPointer, $previousIdentificatorEndPointer] = $this->getConditionData( + $phpcsFile, + $pointerBeforePreviousIdentical, + $pointerAfterPreviousIdentical + ); + + if ($previousIdentificatorStartPointer !== null && $previousIdentificatorEndPointer !== null) { + $previousIdentificator = IdentificatorHelper::getContent( + $phpcsFile, + $previousIdentificatorStartPointer, + $previousIdentificatorEndPointer + ); + + if (!self::areIdentificatorsCompatible($previousIdentificator, $identificator)) { + return; + } + } + } + } + + $defaultInElse = $tokens[$identicalPointer]['code'] === T_IS_NOT_IDENTICAL; + $inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer); + $inlineElseEndPointer = TernaryOperatorHelper::getEndPointer($phpcsFile, $inlineThenPointer, $inlineElsePointer); + + if ($defaultInElse) { + $nextIdentificatorPointers = $this->getNextIdentificator($phpcsFile, $inlineThenPointer); + + if ($nextIdentificatorPointers === null) { + return; + } + + [$nextIdentificatorStartPointer, $nextIdentificatorEndPointer] = $nextIdentificatorPointers; + + $nextIdentificator = IdentificatorHelper::getContent($phpcsFile, $nextIdentificatorStartPointer, $nextIdentificatorEndPointer); + + if (!$this->areIdentificatorsCompatible($identificator, $nextIdentificator)) { + return; + } + + if (TokenHelper::findNextEffective($phpcsFile, $nextIdentificatorEndPointer + 1) !== $inlineElsePointer) { + return; + } + + $identificatorDifference = $this->getIdentificatorDifference( + $phpcsFile, + $identificator, + $nextIdentificatorStartPointer, + $nextIdentificatorEndPointer + ); + + $firstPointerInElse = TokenHelper::findNextEffective($phpcsFile, $inlineElsePointer + 1); + + $defaultContent = TokenHelper::getContent($phpcsFile, $firstPointerInElse, $inlineElseEndPointer); + + $conditionEndPointer = $inlineElseEndPointer; + + } else { + $nullPointer = TokenHelper::findNextEffective($phpcsFile, $inlineThenPointer + 1); + + if ($tokens[$nullPointer]['code'] !== T_NULL) { + return; + } + + if (TokenHelper::findNextEffective($phpcsFile, $nullPointer + 1) !== $inlineElsePointer) { + return; + } + + $nextIdentificatorPointers = $this->getNextIdentificator($phpcsFile, $inlineElsePointer); + + if ($nextIdentificatorPointers === null) { + return; + } + + [$nextIdentificatorStartPointer, $nextIdentificatorEndPointer] = $nextIdentificatorPointers; + + if ($nextIdentificatorEndPointer !== $inlineElseEndPointer) { + return; + } + + $nextIdentificator = IdentificatorHelper::getContent($phpcsFile, $nextIdentificatorStartPointer, $nextIdentificatorEndPointer); + + if (!$this->areIdentificatorsCompatible($identificator, $nextIdentificator)) { + return; + } + + $identificatorDifference = $this->getIdentificatorDifference( + $phpcsFile, + $identificator, + $nextIdentificatorStartPointer, + $nextIdentificatorEndPointer + ); + + $defaultContent = trim(TokenHelper::getContent($phpcsFile, $inlineThenPointer + 1, $inlineElsePointer - 1)); + + $conditionEndPointer = $nextIdentificatorEndPointer; + } + + $fix = $phpcsFile->addFixableError('Operator ?-> is required.', $identicalPointer, self::CODE_REQUIRED_NULL_SAFE_OBJECT_OPERATOR); + + if (!$fix) { + return; + } + + $conditionContent = sprintf('%s?%s', $identificator, $identificatorDifference); + if (strtolower($defaultContent) !== 'null') { + $conditionContent .= sprintf(' ?? %s', $defaultContent); + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $conditionStartPointer, $conditionEndPointer, $conditionContent); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkNextCondition( + File $phpcsFile, + int $identicalPointer, + int $conditionStartPointer, + string $identificator, + int $nextConditionBooleanPointer + ): int + { + $nextIdentificatorPointers = $this->getNextIdentificator($phpcsFile, $nextConditionBooleanPointer); + + if ($nextIdentificatorPointers === null) { + return $nextConditionBooleanPointer; + } + + [$nextIdentificatorStartPointer, $nextIdentificatorEndPointer] = $nextIdentificatorPointers; + + $nextIdentificator = IdentificatorHelper::getContent($phpcsFile, $nextIdentificatorStartPointer, $nextIdentificatorEndPointer); + + if (!$this->areIdentificatorsCompatible($identificator, $nextIdentificator)) { + return $nextIdentificatorEndPointer; + } + + $pointerAfterNexIdentificator = TokenHelper::findNextEffective($phpcsFile, $nextIdentificatorEndPointer + 1); + + $tokens = $phpcsFile->getTokens(); + + if ( + $tokens[$pointerAfterNexIdentificator]['code'] !== $tokens[$identicalPointer]['code'] + && !in_array($tokens[$pointerAfterNexIdentificator]['code'], [T_INLINE_THEN, T_SEMICOLON], true) + ) { + return $pointerAfterNexIdentificator; + } + + if (!in_array($tokens[$pointerAfterNexIdentificator]['code'], [T_IS_IDENTICAL, T_IS_NOT_IDENTICAL], true)) { + return $pointerAfterNexIdentificator; + } + + $pointerAfterIdentical = TokenHelper::findNextEffective($phpcsFile, $pointerAfterNexIdentificator + 1); + if ($tokens[$pointerAfterIdentical]['code'] !== T_NULL) { + return $pointerAfterNexIdentificator; + } + + $identificatorDifference = $this->getIdentificatorDifference( + $phpcsFile, + $identificator, + $nextIdentificatorStartPointer, + $nextIdentificatorEndPointer + ); + + $fix = $phpcsFile->addFixableError('Operator ?-> is required.', $identicalPointer, self::CODE_REQUIRED_NULL_SAFE_OBJECT_OPERATOR); + + if (!$fix) { + return $pointerAfterNexIdentificator; + } + + $isConditionOfTernaryOperator = TernaryOperatorHelper::isConditionOfTernaryOperator($phpcsFile, $identicalPointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change( + $phpcsFile, + $conditionStartPointer, + $nextIdentificatorEndPointer, + sprintf('%s?%s', $identificator, $identificatorDifference) + ); + + $phpcsFile->fixer->endChangeset(); + + if ($isConditionOfTernaryOperator) { + return TokenHelper::findNext($phpcsFile, T_INLINE_THEN, $identicalPointer + 1); + } + + return $pointerAfterNexIdentificator; + } + + /** + * @return array|null + */ + private function getNextIdentificator(File $phpcsFile, int $pointerBefore): ?array + { + /** @var int $nextIdentificatorStartPointer */ + $nextIdentificatorStartPointer = TokenHelper::findNextEffective($phpcsFile, $pointerBefore + 1); + $nextIdentificatorEndPointer = $this->findIdentificatorEnd($phpcsFile, $nextIdentificatorStartPointer); + + if ($nextIdentificatorEndPointer === null) { + return null; + } + + return [$nextIdentificatorStartPointer, $nextIdentificatorEndPointer]; + } + + private function findIdentificatorStart(File $phpcsFile, int $identificatorEndPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$identificatorEndPointer]['code'] === T_CLOSE_PARENTHESIS) { + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective( + $phpcsFile, + $tokens[$identificatorEndPointer]['parenthesis_opener'] - 1 + ); + $identificatorStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $pointerBeforeParenthesisOpener); + } else { + $identificatorStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $identificatorEndPointer); + } + + if ($identificatorStartPointer !== null) { + $pointerBeforeIdentificatorStart = TokenHelper::findPreviousEffective($phpcsFile, $identificatorStartPointer - 1); + + if (in_array( + $tokens[$pointerBeforeIdentificatorStart]['code'], + [T_DOUBLE_COLON, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], + true + )) { + $pointerBeforeOperator = TokenHelper::findPreviousEffective($phpcsFile, $pointerBeforeIdentificatorStart - 1); + return $this->findIdentificatorStart($phpcsFile, $pointerBeforeOperator); + } + } + + return $identificatorStartPointer; + } + + private function findIdentificatorEnd(File $phpcsFile, int $identificatorStartPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $identificatorEndPointer = $tokens[$identificatorStartPointer]['code'] === T_STRING + ? $identificatorStartPointer + : IdentificatorHelper::findEndPointer($phpcsFile, $identificatorStartPointer); + + if ($identificatorEndPointer !== null) { + $pointerAfterIdentificatorEnd = TokenHelper::findNextEffective($phpcsFile, $identificatorEndPointer + 1); + + if ($tokens[$pointerAfterIdentificatorEnd]['code'] === T_OPEN_PARENTHESIS) { + $identificatorEndPointer = $tokens[$pointerAfterIdentificatorEnd]['parenthesis_closer']; + $pointerAfterIdentificatorEnd = TokenHelper::findNextEffective($phpcsFile, $identificatorEndPointer + 1); + } + + if (in_array( + $tokens[$pointerAfterIdentificatorEnd]['code'], + [T_DOUBLE_COLON, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], + true + )) { + $pointerAfterOperator = TokenHelper::findNextEffective($phpcsFile, $pointerAfterIdentificatorEnd + 1); + return $this->findIdentificatorEnd($phpcsFile, $pointerAfterOperator); + } + } + + return $identificatorEndPointer; + } + + private function areIdentificatorsCompatible(string $first, string $second): bool + { + /** @var list $firstParts */ + $firstParts = preg_split(self::OPERATOR_REGEXP, $first, -1, PREG_SPLIT_DELIM_CAPTURE); + /** @var list $secondParts */ + $secondParts = preg_split(self::OPERATOR_REGEXP, $second, -1, PREG_SPLIT_DELIM_CAPTURE); + + $minPartsCount = min(count($firstParts), count($secondParts)); + + for ($i = 0; $i < $minPartsCount; $i++) { + if ($firstParts[$i] === '?->' && $secondParts[$i] === '->') { + continue; + } + + if ($firstParts[$i] !== $secondParts[$i]) { + return false; + } + } + + return array_key_exists($minPartsCount, $secondParts) && $secondParts[$minPartsCount] === '->'; + } + + private function getIdentificatorDifference( + File $phpcsFile, + string $identificator, + int $nextIdentificatorStartPointer, + int $nextIdentificatorEndPointer + ): string + { + $objectOperatorsCountInIdentificator = substr_count($identificator, '->'); + + $tokens = $phpcsFile->getTokens(); + + $objectOperatorsCountInNextIdentificator = 0; + $differencePointer = $nextIdentificatorStartPointer; + for ($i = $nextIdentificatorStartPointer; $i <= $nextIdentificatorEndPointer; $i++) { + if (in_array($tokens[$i]['code'], [T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR], true)) { + $objectOperatorsCountInNextIdentificator++; + } + + if ($objectOperatorsCountInNextIdentificator > $objectOperatorsCountInIdentificator) { + $differencePointer = $i; + break; + } + } + + return TokenHelper::getContent($phpcsFile, $differencePointer, $nextIdentificatorEndPointer); + } + + /** + * @return array{0: int, 1: int} + */ + private function getIdenticalData(File $phpcsFile, int $identicalPointer): array + { + /** @var int $pointerBeforeIdentical */ + $pointerBeforeIdentical = TokenHelper::findPreviousEffective($phpcsFile, $identicalPointer - 1); + /** @var int $pointerAfterIdentical */ + $pointerAfterIdentical = TokenHelper::findNextEffective($phpcsFile, $identicalPointer + 1); + + return [$pointerBeforeIdentical, $pointerAfterIdentical]; + } + + /** + * @return array{0: int|null, 1: int|null, 2: int|null} + */ + private function getConditionData(File $phpcsFile, int $pointerBeforeIdentical, int $pointerAfterIdentical): array + { + $tokens = $phpcsFile->getTokens(); + + $isYoda = $tokens[$pointerBeforeIdentical]['code'] === T_NULL; + + if ($isYoda) { + $identificatorStartPointer = $pointerAfterIdentical; + $identificatorEndPointer = $this->findIdentificatorEnd($phpcsFile, $identificatorStartPointer); + $conditionStartPointer = $pointerBeforeIdentical; + + } else { + $identificatorEndPointer = $pointerBeforeIdentical; + $identificatorStartPointer = $this->findIdentificatorStart($phpcsFile, $identificatorEndPointer); + $conditionStartPointer = $identificatorStartPointer; + } + + return [$identificatorStartPointer, $identificatorEndPointer, $conditionStartPointer]; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireShortTernaryOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireShortTernaryOperatorSniff.php new file mode 100644 index 000000000..6cfe2f9e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireShortTernaryOperatorSniff.php @@ -0,0 +1,87 @@ + + */ + public function register(): array + { + return [ + T_INLINE_THEN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $inlineThenPointer + */ + public function process(File $phpcsFile, $inlineThenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $inlineThenPointer + 1); + + if ($tokens[$nextPointer]['code'] === T_INLINE_ELSE) { + return; + } + + $conditionStartPointer = TernaryOperatorHelper::getStartPointer($phpcsFile, $inlineThenPointer); + $inlineElsePointer = TernaryOperatorHelper::getElsePointer($phpcsFile, $inlineThenPointer); + $inlineElseEndPointer = TernaryOperatorHelper::getEndPointer($phpcsFile, $inlineThenPointer, $inlineElsePointer); + + $thenContent = trim(TokenHelper::getContent($phpcsFile, $inlineThenPointer + 1, $inlineElsePointer - 1)); + $elseContent = trim(TokenHelper::getContent($phpcsFile, $inlineElsePointer + 1, $inlineElseEndPointer)); + + $conditionEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $inlineThenPointer - 1); + + $condition = TokenHelper::getContent($phpcsFile, $conditionStartPointer, $conditionEndPointer); + + if ($tokens[$conditionStartPointer]['code'] === T_BOOLEAN_NOT) { + if ($elseContent !== ltrim($condition, '!')) { + return; + } + } else { + if ($thenContent !== $condition) { + return; + } + } + + $fix = $phpcsFile->addFixableError('Use short ternary operator.', $inlineThenPointer, self::CODE_REQUIRED_SHORT_TERNARY_OPERATOR); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$conditionStartPointer]['code'] === T_BOOLEAN_NOT) { + $phpcsFile->fixer->replaceToken($conditionStartPointer, ''); + + FixerHelper::change($phpcsFile, $inlineThenPointer, $inlineElseEndPointer, sprintf('?: %s', $thenContent)); + + } else { + FixerHelper::removeBetween($phpcsFile, $inlineThenPointer, $inlineElsePointer); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireSingleLineConditionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireSingleLineConditionSniff.php new file mode 100644 index 000000000..d55864da6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireSingleLineConditionSniff.php @@ -0,0 +1,105 @@ +maxLineLength = SniffSettingsHelper::normalizeInteger($this->maxLineLength); + + if ($this->shouldBeSkipped($phpcsFile, $controlStructurePointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = $tokens[$controlStructurePointer]['parenthesis_opener']; + $parenthesisCloserPointer = $tokens[$controlStructurePointer]['parenthesis_closer']; + + if ($tokens[$parenthesisOpenerPointer]['line'] === $tokens[$parenthesisCloserPointer]['line']) { + return; + } + + if (TokenHelper::findNext( + $phpcsFile, + TokenHelper::$inlineCommentTokenCodes, + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) !== null) { + return; + } + + $lineStart = $this->getLineStart($phpcsFile, $parenthesisOpenerPointer); + $condition = $this->getCondition($phpcsFile, $parenthesisOpenerPointer, $parenthesisCloserPointer); + $lineEnd = $this->getLineEnd($phpcsFile, $parenthesisCloserPointer); + + $lineLength = strlen($lineStart . $condition . $lineEnd); + $isSimpleCondition = TokenHelper::findNext( + $phpcsFile, + Tokens::$booleanOperators, + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) === null; + + if (!$this->shouldReportError($lineLength, $isSimpleCondition)) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Condition of "%s" should be placed on a single line.', + $this->getControlStructureName($phpcsFile, $controlStructurePointer) + ), + $controlStructurePointer, + self::CODE_REQUIRED_SINGLE_LINE_CONDITION + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($parenthesisOpenerPointer, $condition); + + FixerHelper::removeBetween($phpcsFile, $parenthesisOpenerPointer, $parenthesisCloserPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function shouldReportError(int $lineLength, bool $isSimpleCondition): bool + { + if ($this->maxLineLength === 0) { + return true; + } + + if ($lineLength <= $this->maxLineLength) { + return true; + } + + return $isSimpleCondition && $this->alwaysForSimpleConditions; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireTernaryOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireTernaryOperatorSniff.php new file mode 100644 index 000000000..f1dc541bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireTernaryOperatorSniff.php @@ -0,0 +1,266 @@ + + */ + public function register(): array + { + return [ + T_IF, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $ifPointer + */ + public function process(File $phpcsFile, $ifPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('scope_closer', $tokens[$ifPointer])) { + // If without curly braces is not supported. + return; + } + + $elsePointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$ifPointer]['scope_closer'] + 1); + if ($elsePointer === null || $tokens[$elsePointer]['code'] !== T_ELSE) { + return; + } + + if (!array_key_exists('scope_closer', $tokens[$elsePointer])) { + // Else without curly braces is not supported. + return; + } + + if ( + !$this->isCompatibleScope($phpcsFile, $tokens[$ifPointer]['scope_opener'], $tokens[$ifPointer]['scope_closer']) + || !$this->isCompatibleScope($phpcsFile, $tokens[$elsePointer]['scope_opener'], $tokens[$elsePointer]['scope_closer']) + ) { + return; + } + + /** @var int $firstPointerInIf */ + $firstPointerInIf = TokenHelper::findNextEffective($phpcsFile, $tokens[$ifPointer]['scope_opener'] + 1); + /** @var int $firstPointerInElse */ + $firstPointerInElse = TokenHelper::findNextEffective($phpcsFile, $tokens[$elsePointer]['scope_opener'] + 1); + + if ($tokens[$firstPointerInIf]['code'] === T_RETURN && $tokens[$firstPointerInElse]['code'] === T_RETURN) { + $this->checkIfWithReturns($phpcsFile, $ifPointer, $elsePointer, $firstPointerInIf, $firstPointerInElse); + return; + } + + $this->checkIfWithAssignments($phpcsFile, $ifPointer, $elsePointer, $firstPointerInIf, $firstPointerInElse); + } + + private function checkIfWithReturns(File $phpcsFile, int $ifPointer, int $elsePointer, int $returnInIf, int $returnInElse): void + { + $ifContainsComment = $this->containsComment($phpcsFile, $ifPointer); + $elseContainsComment = $this->containsComment($phpcsFile, $elsePointer); + $conditionContainsLogicalOperators = $this->containsLogicalOperators($phpcsFile, $ifPointer); + + $errorParameters = [ + 'Use ternary operator.', + $ifPointer, + self::CODE_TERNARY_OPERATOR_NOT_USED, + ]; + + if ($ifContainsComment || $elseContainsComment || $conditionContainsLogicalOperators) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $pointerAfterReturnInIf = TokenHelper::findNextEffective($phpcsFile, $returnInIf + 1); + /** @var int $semicolonAfterReturnInIf */ + $semicolonAfterReturnInIf = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $pointerAfterReturnInIf + 1); + $pointerAfterReturnInElse = TokenHelper::findNextEffective($phpcsFile, $returnInElse + 1); + $semicolonAfterReturnInElse = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $pointerAfterReturnInElse + 1); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($ifPointer, 'return'); + if ($ifPointer + 1 === $tokens[$ifPointer]['parenthesis_opener']) { + $phpcsFile->fixer->addContent($ifPointer, ' '); + } + $phpcsFile->fixer->replaceToken($tokens[$ifPointer]['parenthesis_opener'], ''); + $phpcsFile->fixer->replaceToken($tokens[$ifPointer]['parenthesis_closer'], ' ? '); + + FixerHelper::removeBetween($phpcsFile, $tokens[$ifPointer]['parenthesis_closer'], $pointerAfterReturnInIf); + + FixerHelper::change($phpcsFile, $semicolonAfterReturnInIf, $pointerAfterReturnInElse - 1, ' : '); + + FixerHelper::removeBetweenIncluding($phpcsFile, $semicolonAfterReturnInElse + 1, $tokens[$elsePointer]['scope_closer']); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkIfWithAssignments( + File $phpcsFile, + int $ifPointer, + int $elsePointer, + int $firstPointerInIf, + int $firstPointerInElse + ): void + { + $tokens = $phpcsFile->getTokens(); + + $identificatorEndPointerInIf = IdentificatorHelper::findEndPointer($phpcsFile, $firstPointerInIf); + $identificatorEndPointerInElse = IdentificatorHelper::findEndPointer($phpcsFile, $firstPointerInElse); + + if ($identificatorEndPointerInIf === null || $identificatorEndPointerInElse === null) { + return; + } + + $identificatorInIf = TokenHelper::getContent($phpcsFile, $firstPointerInIf, $identificatorEndPointerInIf); + $identificatorInElse = TokenHelper::getContent($phpcsFile, $firstPointerInElse, $identificatorEndPointerInElse); + + if ($identificatorInIf !== $identificatorInElse) { + return; + } + + $assignmentPointerInIf = TokenHelper::findNextEffective($phpcsFile, $identificatorEndPointerInIf + 1); + $assignmentPointerInElse = TokenHelper::findNextEffective($phpcsFile, $identificatorEndPointerInElse + 1); + + if ( + $tokens[$assignmentPointerInIf]['code'] !== T_EQUAL + || $tokens[$assignmentPointerInElse]['code'] !== T_EQUAL + ) { + return; + } + + $pointerAfterAssignmentInIf = TokenHelper::findNextEffective($phpcsFile, $assignmentPointerInIf + 1); + $pointerAfterAssignmentInElse = TokenHelper::findNextEffective($phpcsFile, $assignmentPointerInElse + 1); + + if ( + $tokens[$pointerAfterAssignmentInIf]['code'] === T_BITWISE_AND || + $tokens[$pointerAfterAssignmentInElse]['code'] === T_BITWISE_AND + ) { + return; + } + + $ifContainsComment = $this->containsComment($phpcsFile, $ifPointer); + $elseContainsComment = $this->containsComment($phpcsFile, $elsePointer); + $conditionContainsLogicalOperators = $this->containsLogicalOperators($phpcsFile, $ifPointer); + + $errorParameters = [ + 'Use ternary operator.', + $ifPointer, + self::CODE_TERNARY_OPERATOR_NOT_USED, + ]; + + if ($ifContainsComment || $elseContainsComment || $conditionContainsLogicalOperators) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + return; + } + + /** @var int $semicolonAfterAssignmentInIf */ + $semicolonAfterAssignmentInIf = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $pointerAfterAssignmentInIf + 1); + $semicolonAfterAssignmentInElse = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $pointerAfterAssignmentInElse + 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $ifPointer, $tokens[$ifPointer]['parenthesis_opener'], sprintf('%s = ', $identificatorInIf)); + + FixerHelper::change($phpcsFile, $tokens[$ifPointer]['parenthesis_closer'], $pointerAfterAssignmentInIf - 1, ' ? '); + + FixerHelper::change($phpcsFile, $semicolonAfterAssignmentInIf, $pointerAfterAssignmentInElse - 1, ' : '); + + FixerHelper::removeBetweenIncluding($phpcsFile, $semicolonAfterAssignmentInElse + 1, $tokens[$elsePointer]['scope_closer']); + + $phpcsFile->fixer->endChangeset(); + } + + private function isCompatibleScope(File $phpcsFile, int $scopeOpenerPointer, int $scopeCloserPointer): bool + { + $semicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $scopeOpenerPointer + 1, $scopeCloserPointer); + if ($semicolonPointer === null) { + return false; + } + + if (TokenHelper::findNext($phpcsFile, T_INLINE_THEN, $scopeOpenerPointer + 1, $semicolonPointer) !== null) { + return false; + } + + if ($this->ignoreMultiLine) { + $firstContentPointer = TokenHelper::findNextEffective($phpcsFile, $scopeOpenerPointer + 1); + if (TokenHelper::findNextContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $firstContentPointer + 1, + $semicolonPointer + ) !== null) { + return false; + } + } + + $pointerAfterSemicolon = TokenHelper::findNextEffective($phpcsFile, $semicolonPointer + 1); + return $pointerAfterSemicolon === $scopeCloserPointer; + } + + private function containsComment(File $phpcsFile, int $scopeOwnerPointer): bool + { + $tokens = $phpcsFile->getTokens(); + return TokenHelper::findNext( + $phpcsFile, + Tokens::$commentTokens, + $tokens[$scopeOwnerPointer]['scope_opener'] + 1, + $tokens[$scopeOwnerPointer]['scope_closer'] + ) !== null; + } + + private function containsLogicalOperators(File $phpcsFile, int $scopeOwnerPointer): bool + { + $tokens = $phpcsFile->getTokens(); + return TokenHelper::findNext( + $phpcsFile, + [T_LOGICAL_AND, T_LOGICAL_OR, T_LOGICAL_XOR], + $tokens[$scopeOwnerPointer]['parenthesis_opener'] + 1, + $tokens[$scopeOwnerPointer]['parenthesis_closer'] + ) !== null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireYodaComparisonSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireYodaComparisonSniff.php new file mode 100644 index 000000000..cc0a31992 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/RequireYodaComparisonSniff.php @@ -0,0 +1,74 @@ + (Foo::BAR, BAR) + * > (true, false, null, 1, 1.0, arrays, 'foo') + */ +class RequireYodaComparisonSniff implements Sniff +{ + + public const CODE_REQUIRED_YODA_COMPARISON = 'RequiredYodaComparison'; + + /** @var bool */ + public $alwaysVariableOnRight = false; + + /** + * @return array + */ + public function register(): array + { + return [ + T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL, + T_IS_EQUAL, + T_IS_NOT_EQUAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $comparisonTokenPointer + */ + public function process(File $phpcsFile, $comparisonTokenPointer): void + { + $tokens = $phpcsFile->getTokens(); + $leftSideTokens = YodaHelper::getLeftSideTokens($tokens, $comparisonTokenPointer); + $rightSideTokens = YodaHelper::getRightSideTokens($tokens, $comparisonTokenPointer); + $leftDynamism = YodaHelper::getDynamismForTokens($tokens, $leftSideTokens); + $rightDynamism = YodaHelper::getDynamismForTokens($tokens, $rightSideTokens); + + if ($leftDynamism === null || $rightDynamism === null) { + return; + } + + if ($leftDynamism <= $rightDynamism) { + return; + } + + if (!$this->alwaysVariableOnRight && $leftDynamism >= 900 && $rightDynamism >= 900) { + return; + } + + $fix = $phpcsFile->addFixableError('Yoda comparison is required.', $comparisonTokenPointer, self::CODE_REQUIRED_YODA_COMPARISON); + if (!$fix || count($leftSideTokens) === 0 || count($rightSideTokens) === 0) { + return; + } + + YodaHelper::fix($phpcsFile, $leftSideTokens, $rightSideTokens); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UnsupportedKeywordException.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UnsupportedKeywordException.php new file mode 100644 index 000000000..9379e0e7f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UnsupportedKeywordException.php @@ -0,0 +1,17 @@ + + */ + public function register(): array + { + return [ + T_IF, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $ifPointer + */ + public function process(File $phpcsFile, $ifPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('scope_closer', $tokens[$ifPointer])) { + // If without curly braces is not supported. + return; + } + + $ifBooleanPointer = $this->findBooleanAfterReturnInScope($phpcsFile, $tokens[$ifPointer]['scope_opener']); + if ($ifBooleanPointer === null) { + return; + } + + $newCondition = static function () use ($phpcsFile, $tokens, $ifBooleanPointer, $ifPointer): string { + return strtolower($tokens[$ifBooleanPointer]['content']) === 'true' + ? TokenHelper::getContent( + $phpcsFile, + $tokens[$ifPointer]['parenthesis_opener'] + 1, + $tokens[$ifPointer]['parenthesis_closer'] - 1 + ) + : ConditionHelper::getNegativeCondition( + $phpcsFile, + $tokens[$ifPointer]['parenthesis_opener'] + 1, + $tokens[$ifPointer]['parenthesis_closer'] - 1 + ); + }; + + $elsePointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$ifPointer]['scope_closer'] + 1); + + $errorParameters = [ + 'Useless condition.', + $ifPointer, + self::CODE_USELESS_IF_CONDITION, + ]; + + if ( + $elsePointer !== null + && $tokens[$elsePointer]['code'] === T_ELSE + ) { + if (!array_key_exists('scope_closer', $tokens[$elsePointer])) { + // Else without curly braces is not supported. + return; + } + + $elseBooleanPointer = $this->findBooleanAfterReturnInScope($phpcsFile, $tokens[$elsePointer]['scope_opener']); + if ($elseBooleanPointer === null) { + return; + } + + if (!$this->isFixable($phpcsFile, $ifPointer, $tokens[$elsePointer]['scope_closer'])) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $ifPointer, $tokens[$elsePointer]['scope_closer'], sprintf('return %s;', $newCondition())); + + $phpcsFile->fixer->endChangeset(); + } else { + $returnPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$ifPointer]['scope_closer'] + 1); + + if ($returnPointer === null) { + return; + } + + if ($tokens[$returnPointer]['code'] !== T_RETURN) { + return; + } + + $semicolonPointer = $this->findSemicolonAfterReturnWithBoolean($phpcsFile, $returnPointer); + if ($semicolonPointer === null) { + return; + } + + if (!$this->isFixable($phpcsFile, $ifPointer, $semicolonPointer)) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $ifPointer, $semicolonPointer, sprintf('return %s;', $newCondition())); + + $phpcsFile->fixer->endChangeset(); + } + } + + private function isFixable(File $phpcsFile, int $ifPointer, int $endPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + if (TokenHelper::findNext($phpcsFile, Tokens::$commentTokens, $ifPointer + 1, $endPointer) !== null) { + return false; + } + + if ($this->assumeAllConditionExpressionsAreAlreadyBoolean) { + return true; + } + + return ConditionHelper::conditionReturnsBoolean( + $phpcsFile, + $tokens[$ifPointer]['parenthesis_opener'] + 1, + $tokens[$ifPointer]['parenthesis_closer'] - 1 + ); + } + + private function findBooleanAfterReturnInScope(File $phpcsFile, int $scopeOpenerPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $returnPointer */ + $returnPointer = TokenHelper::findNextEffective($phpcsFile, $scopeOpenerPointer + 1); + if ($tokens[$returnPointer]['code'] !== T_RETURN) { + return null; + } + + $booleanPointer = $this->findBooleanAfterReturn($phpcsFile, $returnPointer); + if ($booleanPointer === null) { + return null; + } + + $semicolonPointer = TokenHelper::findNextEffective($phpcsFile, $booleanPointer + 1); + if ($tokens[$semicolonPointer]['code'] !== T_SEMICOLON) { + return null; + } + + return $booleanPointer; + } + + private function findBooleanAfterReturn(File $phpcsFile, int $returnPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $booleanPointer = TokenHelper::findNextEffective($phpcsFile, $returnPointer + 1); + if (in_array($tokens[$booleanPointer]['code'], [T_TRUE, T_FALSE], true)) { + return $booleanPointer; + } + + return null; + } + + private function findSemicolonAfterReturnWithBoolean(File $phpcsFile, int $returnPointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $booleanPointer = $this->findBooleanAfterReturn($phpcsFile, $returnPointer); + if ($booleanPointer === null) { + return null; + } + + $semicolonPointer = TokenHelper::findNextEffective($phpcsFile, $booleanPointer + 1); + if ($tokens[$semicolonPointer]['code'] !== T_SEMICOLON) { + return null; + } + + return $semicolonPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessTernaryOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessTernaryOperatorSniff.php new file mode 100644 index 000000000..55f51134a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/UselessTernaryOperatorSniff.php @@ -0,0 +1,105 @@ + + */ + public function register(): array + { + return [ + T_INLINE_THEN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $inlineThenPointer + */ + public function process(File $phpcsFile, $inlineThenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $pointerAfterInlineThen = TokenHelper::findNextEffective($phpcsFile, $inlineThenPointer + 1); + if ($tokens[$pointerAfterInlineThen]['code'] === T_INLINE_ELSE) { + $inlineElsePointer = $pointerAfterInlineThen; + } else { + if (!in_array($tokens[$pointerAfterInlineThen]['code'], [T_TRUE, T_FALSE], true)) { + return; + } + + $inlineElsePointer = TokenHelper::findNextEffective($phpcsFile, $pointerAfterInlineThen + 1); + if ($tokens[$inlineElsePointer]['code'] !== T_INLINE_ELSE) { + return; + } + } + + $pointerAfterInlineElse = TokenHelper::findNextEffective($phpcsFile, $inlineElsePointer + 1); + if (!in_array($tokens[$pointerAfterInlineElse]['code'], [T_TRUE, T_FALSE], true)) { + return; + } + + $conditionStartPointer = TernaryOperatorHelper::getStartPointer($phpcsFile, $inlineThenPointer); + /** @var int $conditionEndPointer */ + $conditionEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $inlineThenPointer - 1); + + $errorParameters = [ + 'Useless ternary operator.', + $inlineThenPointer, + self::CODE_USELESS_TERNARY_OPERATOR, + ]; + + if ( + !$this->assumeAllConditionExpressionsAreAlreadyBoolean + && !ConditionHelper::conditionReturnsBoolean($phpcsFile, $conditionStartPointer, $conditionEndPointer) + ) { + if ($tokens[$pointerAfterInlineThen]['code'] !== T_INLINE_ELSE) { + $phpcsFile->addError(...$errorParameters); + } + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + return; + } + + $inlineElseEndPointer = TernaryOperatorHelper::getEndPointer($phpcsFile, $inlineThenPointer, $inlineElsePointer); + + $pointerAfterTernaryOperator = TokenHelper::findNextEffective($phpcsFile, $inlineElseEndPointer + 1); + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$pointerAfterInlineThen]['code'] === T_FALSE) { + $negativeCondition = ConditionHelper::getNegativeCondition($phpcsFile, $conditionStartPointer, $conditionEndPointer); + + FixerHelper::change($phpcsFile, $conditionStartPointer, $conditionEndPointer, $negativeCondition); + } + + FixerHelper::removeBetween($phpcsFile, $conditionEndPointer, $pointerAfterTernaryOperator); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DeadCatchSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DeadCatchSniff.php new file mode 100644 index 000000000..8a3c29208 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DeadCatchSniff.php @@ -0,0 +1,56 @@ + + */ + public function register(): array + { + return [ + T_CATCH, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $catchPointer + */ + public function process(File $phpcsFile, $catchPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $catchToken = $tokens[$catchPointer]; + $caughtTypes = CatchHelper::findCaughtTypesInCatch($phpcsFile, $catchToken); + + if (!in_array('\\Throwable', $caughtTypes, true)) { + return; + } + + $nextCatchPointer = TokenHelper::findNextEffective($phpcsFile, $catchToken['scope_closer'] + 1); + + while ($nextCatchPointer !== null) { + $nextCatchToken = $tokens[$nextCatchPointer]; + if ($nextCatchToken['code'] !== T_CATCH) { + break; + } + + $phpcsFile->addError('Unreachable catch block.', $nextCatchPointer, self::CODE_CATCH_AFTER_THROWABLE_CATCH); + + $nextCatchPointer = TokenHelper::findNextEffective($phpcsFile, $nextCatchToken['scope_closer'] + 1); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DisallowNonCapturingCatchSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DisallowNonCapturingCatchSniff.php new file mode 100644 index 000000000..fcf40c9de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/DisallowNonCapturingCatchSniff.php @@ -0,0 +1,46 @@ + + */ + public function register(): array + { + return [ + T_CATCH, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $catchPointer + */ + public function process(File $phpcsFile, $catchPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $variablePointer = TokenHelper::findNext( + $phpcsFile, + T_VARIABLE, + $tokens[$catchPointer]['parenthesis_opener'], + $tokens[$catchPointer]['parenthesis_closer'] + ); + + if ($variablePointer === null) { + $phpcsFile->addError('Use of non-capturing catch is disallowed.', $catchPointer, self::CODE_DISALLOWED_NON_CAPTURING_CATCH); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/ReferenceThrowableOnlySniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/ReferenceThrowableOnlySniff.php new file mode 100644 index 000000000..3769e0ae5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/ReferenceThrowableOnlySniff.php @@ -0,0 +1,139 @@ + + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $message = sprintf('Referencing general \%s; use \%s instead.', Exception::class, Throwable::class); + $referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer); + foreach ($referencedNames as $referencedName) { + $resolvedName = NamespaceHelper::resolveClassName( + $phpcsFile, + $referencedName->getNameAsReferencedInFile(), + $referencedName->getStartPointer() + ); + if ($resolvedName !== '\\Exception') { + continue; + } + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $referencedName->getStartPointer() - 1); + if (in_array($tokens[$previousPointer]['code'], [T_EXTENDS, T_NEW, T_INSTANCEOF], true)) { + // Allow \Exception in extends and instantiating it + continue; + } + if ($tokens[$previousPointer]['code'] === T_BITWISE_OR) { + $previousPointer = TokenHelper::findPreviousExcluding( + $phpcsFile, + array_merge(TokenHelper::$ineffectiveTokenCodes, TokenHelper::getNameTokenCodes(), [T_BITWISE_OR]), + $previousPointer - 1 + ); + } + if ($tokens[$previousPointer]['code'] === T_OPEN_PARENTHESIS) { + /** @var int $openParenthesisOpenerPointer */ + $openParenthesisOpenerPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + if ($tokens[$openParenthesisOpenerPointer]['code'] === T_CATCH) { + if ($this->searchForThrowableInNextCatches($phpcsFile, $openParenthesisOpenerPointer)) { + continue; + } + } elseif ( + array_key_exists('parenthesis_owner', $tokens[$previousPointer]) + && $tokens[$tokens[$previousPointer]['parenthesis_owner']]['code'] === T_FUNCTION + && $tokens[$previousPointer]['parenthesis_closer'] > $referencedName->getStartPointer() + && SuppressHelper::isSniffSuppressed( + $phpcsFile, + $openParenthesisOpenerPointer, + sprintf('%s.%s', self::NAME, self::CODE_REFERENCED_GENERAL_EXCEPTION) + ) + ) { + continue; + } + } + + $fix = $phpcsFile->addFixableError( + $message, + $referencedName->getStartPointer(), + self::CODE_REFERENCED_GENERAL_EXCEPTION + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $referencedName->getStartPointer(), $referencedName->getEndPointer(), '\Throwable'); + + $phpcsFile->fixer->endChangeset(); + } + } + + private function searchForThrowableInNextCatches(File $phpcsFile, int $catchPointer): bool + { + $tokens = $phpcsFile->getTokens(); + $nextCatchPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$catchPointer]['scope_closer'] + 1); + + while ($nextCatchPointer !== null) { + $nextCatchToken = $tokens[$nextCatchPointer]; + if ($nextCatchToken['code'] !== T_CATCH) { + break; + } + + $caughtTypes = CatchHelper::findCaughtTypesInCatch($phpcsFile, $nextCatchToken); + if (in_array('\\Throwable', $caughtTypes, true)) { + return true; + } + + $nextCatchPointer = TokenHelper::findNextEffective($phpcsFile, $nextCatchToken['scope_closer'] + 1); + } + + return false; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/RequireNonCapturingCatchSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/RequireNonCapturingCatchSniff.php new file mode 100644 index 000000000..cbe8810b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/RequireNonCapturingCatchSniff.php @@ -0,0 +1,170 @@ + + */ + public function register(): array + { + return [ + T_CATCH, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $catchPointer + */ + public function process(File $phpcsFile, $catchPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $variablePointer = TokenHelper::findNext( + $phpcsFile, + T_VARIABLE, + $tokens[$catchPointer]['parenthesis_opener'], + $tokens[$catchPointer]['parenthesis_closer'] + ); + if ($variablePointer === null) { + return; + } + + $variableName = $tokens[$variablePointer]['content']; + + if ($this->isVariableUsedInCodePart( + $phpcsFile, + $tokens[$catchPointer]['scope_opener'], + $tokens[$catchPointer]['scope_closer'], + $variableName + )) { + return; + } + + $tryEndPointer = CatchHelper::getTryEndPointer($phpcsFile, $catchPointer); + + $possibleFinallyPointer = $tokens[$tryEndPointer]['scope_condition']; + if ( + $tokens[$possibleFinallyPointer]['code'] === T_FINALLY + && $this->isVariableUsedInCodePart( + $phpcsFile, + $tokens[$possibleFinallyPointer]['scope_opener'], + $tokens[$possibleFinallyPointer]['scope_closer'], + $variableName + ) + ) { + return; + } + + $nextScopeEnd = count($tokens) - 1; + + foreach (array_reverse($tokens[$tryEndPointer]['conditions'], true) as $conditionPointer => $conditionCode) { + if (in_array($conditionCode, TokenHelper::$functionTokenCodes, true)) { + $nextScopeEnd = $tokens[$conditionPointer]['scope_closer']; + break; + } + } + + if ($this->isVariableUsedInCodePart($phpcsFile, $tryEndPointer, $nextScopeEnd, $variableName)) { + return; + } + + $fix = $phpcsFile->addFixableError('Non-capturing catch is required.', $catchPointer, self::CODE_NON_CAPTURING_CATCH_REQUIRED); + + if (!$fix) { + return; + } + + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + $fixEndPointer = TokenHelper::findNextContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $variablePointer + 1, + $tokens[$catchPointer]['parenthesis_closer'] + ); + if ($fixEndPointer === null) { + $fixEndPointer = $tokens[$catchPointer]['parenthesis_closer']; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeVariable, $fixEndPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function isVariableUsedInCodePart(File $phpcsFile, int $codeStartPointer, int $codeEndPointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + $firstPointerInCode = $codeStartPointer + 1; + + for ($i = $firstPointerInCode; $i <= $codeEndPointer; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + if (ParameterHelper::isParameter($phpcsFile, $i)) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $firstPointerInCode, $i)) { + continue; + } + + $catchPointer = TokenHelper::findPrevious($phpcsFile, T_CATCH, $i - 1, $firstPointerInCode); + if ($catchPointer === null) { + return true; + } + + if ($tokens[$catchPointer]['parenthesis_closer'] < $i) { + return true; + } + + } elseif ( + in_array($tokens[$i]['code'], [T_DOUBLE_QUOTED_STRING, T_HEREDOC], true) + && VariableHelper::isUsedInScopeInString($phpcsFile, $variableName, $i) + ) { + return true; + } + } + + return false; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FileLengthSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FileLengthSniff.php new file mode 100644 index 000000000..a3e0108ec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FileLengthSniff.php @@ -0,0 +1,63 @@ + + */ + public function register(): array + { + return [T_OPEN_TAG]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->maxLinesLength = SniffSettingsHelper::normalizeInteger($this->maxLinesLength); + $flags = array_keys(array_filter([ + FunctionHelper::LINE_INCLUDE_COMMENT => $this->includeComments, + FunctionHelper::LINE_INCLUDE_WHITESPACE => $this->includeWhitespace, + ])); + $flags = array_reduce($flags, static function ($carry, $flag): int { + return $carry | $flag; + }, 0); + + $length = FunctionHelper::getLineCount($phpcsFile, $pointer, $flags); + + if ($length <= $this->maxLinesLength) { + return; + } + + $errorMessage = sprintf('Your file is too long. Currently using %d lines. Can be up to %d lines.', $length, $this->maxLinesLength); + + $phpcsFile->addError($errorMessage, $pointer, self::CODE_FILE_TOO_LONG); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FilepathNamespaceExtractor.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FilepathNamespaceExtractor.php new file mode 100644 index 000000000..768bb9a1a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/FilepathNamespaceExtractor.php @@ -0,0 +1,88 @@ + */ + private $rootNamespaces; + + /** @var array dir(string) => true(bool) */ + private $skipDirs; + + /** @var list */ + private $extensions; + + /** + * @param array $rootNamespaces directory(string) => namespace + * @param list $skipDirs + * @param list $extensions index(integer) => extension + */ + public function __construct(array $rootNamespaces, array $skipDirs, array $extensions) + { + $this->rootNamespaces = $rootNamespaces; + $this->skipDirs = array_fill_keys($skipDirs, true); + $this->extensions = array_map(static function (string $extension): string { + return strtolower($extension); + }, $extensions); + } + + public function getTypeNameFromProjectPath(string $path): ?string + { + $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION)); + if (!in_array($extension, $this->extensions, true)) { + return null; + } + + /** @var list $pathParts */ + $pathParts = preg_split('~[/\\\]~', $path); + $rootNamespace = null; + while (count($pathParts) > 0) { + array_shift($pathParts); + foreach ($this->rootNamespaces as $directory => $namespace) { + if (!StringHelper::startsWith(implode('/', $pathParts) . '/', $directory . '/')) { + continue; + } + + $directoryPartsCount = count(explode('/', $directory)); + for ($i = 0; $i < $directoryPartsCount; $i++) { + array_shift($pathParts); + } + + $rootNamespace = $namespace; + break 2; + } + } + + if ($rootNamespace === null) { + return null; + } + + array_unshift($pathParts, $rootNamespace); + + $typeName = implode('\\', array_filter($pathParts, function (string $pathPart): bool { + return !isset($this->skipDirs[$pathPart]); + })); + + return substr($typeName, 0, -strlen('.' . $extension)); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/LineLengthSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/LineLengthSniff.php new file mode 100644 index 000000000..accfa5343 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/LineLengthSniff.php @@ -0,0 +1,138 @@ + + */ + public function register(): array + { + return [T_OPEN_TAG]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): int + { + $tokens = $phpcsFile->getTokens(); + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + $this->checkLineLength($phpcsFile, $i); + } + + return $phpcsFile->numTokens + 1; + } + + private function checkLineLength(File $phpcsFile, int $pointer): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['column'] === 1 && $tokens[$pointer]['length'] === 0) { + // Blank line. + return; + } + + $line = $tokens[$pointer]['line']; + $nextLineStartPtr = $pointer; + while (isset($tokens[$nextLineStartPtr]) && $line === $tokens[$nextLineStartPtr]['line']) { + $pointer = $nextLineStartPtr; + $nextLineStartPtr++; + } + + if ($tokens[$pointer]['content'] === $phpcsFile->eolChar) { + $pointer--; + } + + $lineLength = $tokens[$pointer]['column'] + $tokens[$pointer]['length'] - 1; + if ($lineLength <= $this->lineLengthLimit) { + return; + } + + if (in_array($tokens[$pointer]['code'], [T_COMMENT, T_DOC_COMMENT_STRING], true)) { + if ($this->ignoreComments === true) { + return; + } + + // If this is a long comment, check if it can be broken up onto multiple lines. + // Some comments contain unbreakable strings like URLs and so it makes sense + // to ignore the line length in these cases if the URL would be longer than the max + // line length once you indent it to the correct level. + if ($lineLength > $this->lineLengthLimit) { + $oldLength = strlen($tokens[$pointer]['content']); + $newLength = strlen(ltrim($tokens[$pointer]['content'], "/#\t ")); + $indent = $tokens[$pointer]['column'] - 1 + $oldLength - $newLength; + + $nonBreakingLength = $tokens[$pointer]['length']; + + $space = strrpos($tokens[$pointer]['content'], ' '); + if ($space !== false) { + $nonBreakingLength -= $space + 1; + } + + if ($nonBreakingLength + $indent > $this->lineLengthLimit) { + return; + } + } + } + + if ($this->ignoreImports) { + $usePointer = UseStatementHelper::getUseStatementPointer($phpcsFile, $pointer - 1); + if ( + is_int($usePointer) + && $tokens[$usePointer]['line'] === $tokens[$pointer]['line'] + && UseStatementHelper::isImportUse($phpcsFile, $usePointer) + ) { + return; + } + } + + $error = sprintf('Line exceeds maximum limit of %s characters, contains %s characters.', $this->lineLengthLimit, $lineLength); + $phpcsFile->addError($error, $pointer, self::CODE_LINE_TOO_LONG); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/TypeNameMatchesFileNameSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/TypeNameMatchesFileNameSniff.php new file mode 100644 index 000000000..25b369f1c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Files/TypeNameMatchesFileNameSniff.php @@ -0,0 +1,188 @@ + */ + public $rootNamespaces = []; + + /** @var list */ + public $skipDirs = []; + + /** @var list */ + public $ignoredNamespaces = []; + + /** @var list */ + public $extensions = ['php']; + + /** @var array|null */ + private $normalizedRootNamespaces; + + /** @var list|null */ + private $normalizedSkipDirs; + + /** @var list|null */ + private $normalizedIgnoredNamespaces; + + /** @var list|null */ + private $normalizedExtensions; + + /** @var FilepathNamespaceExtractor */ + private $namespaceExtractor; + + /** + * @return array + */ + public function register(): array + { + return TokenHelper::$typeKeywordTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $typePointer + */ + public function process(File $phpcsFile, $typePointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $namePointer */ + $namePointer = TokenHelper::findNext($phpcsFile, T_STRING, $typePointer + 1); + + $typeName = NamespaceHelper::normalizeToCanonicalName(ClassHelper::getFullyQualifiedName($phpcsFile, $typePointer)); + + foreach ($this->getIgnoredNamespaces() as $ignoredNamespace) { + if (!StringHelper::startsWith($typeName, $ignoredNamespace . '\\')) { + continue; + } + + return; + } + + $filename = str_replace('/', DIRECTORY_SEPARATOR, $phpcsFile->getFilename()); + $basePath = str_replace('/', DIRECTORY_SEPARATOR, $phpcsFile->config->basepath ?? ''); + if ($basePath !== '' && StringHelper::startsWith($filename, $basePath)) { + $filename = substr($filename, strlen($basePath)); + } + + $expectedTypeName = $this->getNamespaceExtractor()->getTypeNameFromProjectPath($filename); + if ($typeName === $expectedTypeName) { + return; + } + + $phpcsFile->addError( + sprintf( + '%s name %s does not match filepath %s.', + ucfirst($tokens[$typePointer]['content']), + $typeName, + $phpcsFile->getFilename() + ), + $namePointer, + self::CODE_NO_MATCH_BETWEEN_TYPE_NAME_AND_FILE_NAME + ); + } + + /** + * @return array path(string) => namespace + */ + private function getRootNamespaces(): array + { + if ($this->normalizedRootNamespaces === null) { + /** @var array $normalizedRootNamespaces */ + $normalizedRootNamespaces = SniffSettingsHelper::normalizeAssociativeArray($this->rootNamespaces); + $this->normalizedRootNamespaces = $normalizedRootNamespaces; + uksort($this->normalizedRootNamespaces, static function (string $a, string $b): int { + $aParts = explode('/', str_replace('\\', '/', $a)); + $bParts = explode('/', str_replace('\\', '/', $b)); + + $minPartsCount = min(count($aParts), count($bParts)); + for ($i = 0; $i < $minPartsCount; $i++) { + $comparison = strcasecmp($bParts[$i], $aParts[$i]); + if ($comparison === 0) { + continue; + } + + return $comparison; + } + + return count($bParts) <=> count($aParts); + }); + } + + return $this->normalizedRootNamespaces; + } + + /** + * @return list + */ + private function getSkipDirs(): array + { + if ($this->normalizedSkipDirs === null) { + $this->normalizedSkipDirs = SniffSettingsHelper::normalizeArray($this->skipDirs); + } + + return $this->normalizedSkipDirs; + } + + /** + * @return list + */ + private function getIgnoredNamespaces(): array + { + if ($this->normalizedIgnoredNamespaces === null) { + $this->normalizedIgnoredNamespaces = SniffSettingsHelper::normalizeArray($this->ignoredNamespaces); + } + + return $this->normalizedIgnoredNamespaces; + } + + /** + * @return list + */ + private function getExtensions(): array + { + if ($this->normalizedExtensions === null) { + $this->normalizedExtensions = SniffSettingsHelper::normalizeArray($this->extensions); + } + + return $this->normalizedExtensions; + } + + private function getNamespaceExtractor(): FilepathNamespaceExtractor + { + if ($this->namespaceExtractor === null) { + $this->namespaceExtractor = new FilepathNamespaceExtractor( + $this->getRootNamespaces(), + $this->getSkipDirs(), + $this->getExtensions() + ); + } + + return $this->namespaceExtractor; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/AbstractLineCall.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/AbstractLineCall.php new file mode 100644 index 000000000..72c869974 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/AbstractLineCall.php @@ -0,0 +1,102 @@ + + */ + public function register(): array + { + return array_merge(TokenHelper::getOnlyNameTokenCodes(), [T_SELF, T_STATIC, T_PARENT]); + } + + protected function isCall(File $phpcsFile, int $stringPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + + if ($tokens[$nextPointer]['code'] !== T_OPEN_PARENTHESIS) { + return false; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $stringPointer - 1); + + return $tokens[$previousPointer]['code'] !== T_FUNCTION; + } + + protected function getLineStart(File $phpcsFile, int $pointer): string + { + $firstPointerOnLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $pointer); + + return IndentationHelper::convertTabsToSpaces($phpcsFile, TokenHelper::getContent($phpcsFile, $firstPointerOnLine, $pointer)); + } + + protected function getCall(File $phpcsFile, int $parenthesisOpenerPointer, int $parenthesisCloserPointer): string + { + $tokens = $phpcsFile->getTokens(); + + $pointerBeforeParenthesisCloser = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisCloserPointer - 1); + + $endPointer = $tokens[$pointerBeforeParenthesisCloser]['code'] === T_COMMA + ? $pointerBeforeParenthesisCloser + : $parenthesisCloserPointer; + + $call = ''; + + for ($i = $parenthesisOpenerPointer + 1; $i < $endPointer; $i++) { + if ($tokens[$i]['code'] === T_COMMA) { + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if ($tokens[$nextPointer]['code'] === T_CLOSE_PARENTHESIS) { + $i = $nextPointer - 1; + continue; + } + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + if ($tokens[$i]['content'] === $phpcsFile->eolChar) { + if ($tokens[$i - 1]['code'] === T_COMMA) { + $call .= ' '; + } + + continue; + + } if ($tokens[$i]['column'] === 1) { + // Nothing + continue; + } + } + + $call .= $tokens[$i]['content']; + } + + return trim($call); + } + + protected function getLineEnd(File $phpcsFile, int $pointer): string + { + $firstPointerOnNextLine = TokenHelper::findFirstTokenOnNextLine($phpcsFile, $pointer); + + return rtrim(TokenHelper::getContent($phpcsFile, $pointer, $firstPointerOnNextLine - 1)); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/ArrowFunctionDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/ArrowFunctionDeclarationSniff.php new file mode 100644 index 000000000..e593423ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/ArrowFunctionDeclarationSniff.php @@ -0,0 +1,181 @@ + + */ + public function register(): array + { + return [ + T_FN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $arrowFunctionPointer + */ + public function process(File $phpcsFile, $arrowFunctionPointer): void + { + $this->spacesCountAfterKeyword = SniffSettingsHelper::normalizeInteger($this->spacesCountAfterKeyword); + $this->spacesCountBeforeArrow = SniffSettingsHelper::normalizeInteger($this->spacesCountBeforeArrow); + $this->spacesCountAfterArrow = SniffSettingsHelper::normalizeInteger($this->spacesCountAfterArrow); + + $this->checkSpacesAfterKeyword($phpcsFile, $arrowFunctionPointer); + + $arrowPointer = TokenHelper::findNext($phpcsFile, T_FN_ARROW, $arrowFunctionPointer); + + $this->checkSpacesBeforeArrow($phpcsFile, $arrowPointer); + $this->checkSpacesAfterArrow($phpcsFile, $arrowPointer); + } + + private function checkSpacesAfterKeyword(File $phpcsFile, int $arrowFunctionPointer): void + { + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $arrowFunctionPointer + 1); + + $spaces = TokenHelper::getContent($phpcsFile, $arrowFunctionPointer + 1, $pointerAfter - 1); + + if ($this->allowMultiLine && strpos($spaces, $phpcsFile->eolChar) === 0) { + return; + } + + $actualSpaces = strlen($spaces); + + if ( + $actualSpaces === $this->spacesCountAfterKeyword + && ( + $this->spacesCountAfterKeyword === 0 + || preg_match('~^ +$~', $spaces) === 1 + ) + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + $this->formatErrorMessage('after "fn" keyword', $this->spacesCountAfterKeyword), + $arrowFunctionPointer, + self::CODE_INCORRECT_SPACES_AFTER_KEYWORD + ); + if (!$fix) { + return; + } + + $this->fixSpaces($phpcsFile, $arrowFunctionPointer, $pointerAfter, $this->spacesCountAfterKeyword); + } + + private function checkSpacesBeforeArrow(File $phpcsFile, int $arrowPointer): void + { + $pointerBefore = TokenHelper::findPreviousNonWhitespace($phpcsFile, $arrowPointer - 1); + + $spaces = TokenHelper::getContent($phpcsFile, $pointerBefore + 1, $arrowPointer - 1); + + if ($this->allowMultiLine && strpos($spaces, $phpcsFile->eolChar) === 0) { + return; + } + + $actualSpaces = strlen($spaces); + + if ( + $actualSpaces === $this->spacesCountBeforeArrow + && ( + $this->spacesCountBeforeArrow === 0 + || preg_match('~^ +$~', $spaces) === 1 + ) + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + $this->formatErrorMessage('before =>', $this->spacesCountBeforeArrow), + $arrowPointer, + self::CODE_INCORRECT_SPACES_BEFORE_ARROW + ); + if (!$fix) { + return; + } + + $this->fixSpaces($phpcsFile, $pointerBefore, $arrowPointer, $this->spacesCountBeforeArrow); + } + + private function checkSpacesAfterArrow(File $phpcsFile, int $arrowPointer): void + { + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $arrowPointer + 1); + + $spaces = TokenHelper::getContent($phpcsFile, $arrowPointer + 1, $pointerAfter - 1); + + if ($this->allowMultiLine && strpos($spaces, $phpcsFile->eolChar) === 0) { + return; + } + + $actualSpaces = strlen($spaces); + + if ($actualSpaces === $this->spacesCountAfterArrow && ($this->spacesCountAfterArrow === 0 || preg_match('~^ +$~', $spaces) === 1)) { + return; + } + + $fix = $phpcsFile->addFixableError( + $this->formatErrorMessage('after =>', $this->spacesCountAfterArrow), + $arrowPointer, + self::CODE_INCORRECT_SPACES_AFTER_ARROW + ); + if (!$fix) { + return; + } + + $this->fixSpaces($phpcsFile, $arrowPointer, $pointerAfter, $this->spacesCountAfterArrow); + } + + private function formatErrorMessage(string $suffix, int $requiredSpaces): string + { + return $requiredSpaces === 0 + ? sprintf('There must be no whitespace %s.', $suffix) + : sprintf('There must be exactly %d whitespace%s %s.', $requiredSpaces, $requiredSpaces !== 1 ? 's' : '', $suffix); + } + + private function fixSpaces(File $phpcsFile, int $pointerBefore, int $pointerAfter, int $requiredSpaces): void + { + $phpcsFile->fixer->beginChangeset(); + + if ($requiredSpaces > 0) { + $phpcsFile->fixer->addContent($pointerBefore, str_repeat(' ', $requiredSpaces)); + } + + FixerHelper::removeBetween($phpcsFile, $pointerBefore, $pointerAfter); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowArrowFunctionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowArrowFunctionSniff.php new file mode 100644 index 000000000..31520d076 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowArrowFunctionSniff.php @@ -0,0 +1,33 @@ + + */ + public function register(): array + { + return [ + T_FN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $arrowFunctionPointer + */ + public function process(File $phpcsFile, $arrowFunctionPointer): void + { + $phpcsFile->addError('Use of arrow function is disallowed.', $arrowFunctionPointer, self::CODE_DISALLOWED_ARROW_FUNCTION); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowEmptyFunctionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowEmptyFunctionSniff.php new file mode 100644 index 000000000..704d30f44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowEmptyFunctionSniff.php @@ -0,0 +1,69 @@ + + */ + public function register(): array + { + return [T_FUNCTION]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (FunctionHelper::isAbstract($phpcsFile, $functionPointer)) { + return; + } + + if (FunctionHelper::getName($phpcsFile, $functionPointer) === '__construct') { + $propertyPromotion = TokenHelper::findNext( + $phpcsFile, + Tokens::$scopeModifiers, + $tokens[$functionPointer]['parenthesis_opener'] + 1, + $tokens[$functionPointer]['parenthesis_closer'] + ); + + if ($propertyPromotion !== null) { + return; + } + } + + $firstContent = TokenHelper::findNextExcluding( + $phpcsFile, + T_WHITESPACE, + $tokens[$functionPointer]['scope_opener'] + 1, + $tokens[$functionPointer]['scope_closer'] + ); + + if ($firstContent !== null) { + return; + } + + $phpcsFile->addError( + 'Empty function body must have at least a comment to explain why is empty.', + $functionPointer, + self::CODE_EMPTY_FUNCTION + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowNamedArgumentsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowNamedArgumentsSniff.php new file mode 100644 index 000000000..500f0f40b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowNamedArgumentsSniff.php @@ -0,0 +1,40 @@ + + */ + public function register(): array + { + return [ + T_PARAM_NAME, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $argumentNamePointer + */ + public function process(File $phpcsFile, $argumentNamePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $phpcsFile->addError( + sprintf('Named arguments are disallowed, usage of named argument "%s" found.', $tokens[$argumentNamePointer]['content']), + $argumentNamePointer, + self::CODE_DISALLOWED_NAMED_ARGUMENT + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInCallSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInCallSniff.php new file mode 100644 index 000000000..2914a8415 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInCallSniff.php @@ -0,0 +1,95 @@ + + */ + public function register(): array + { + return [ + T_OPEN_PARENTHESIS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $parenthesisOpenerPointer + */ + public function process(File $phpcsFile, $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (array_key_exists('parenthesis_owner', $tokens[$parenthesisOpenerPointer])) { + return; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if (!in_array( + $tokens[$pointerBeforeParenthesisOpener]['code'], + array_merge( + TokenHelper::getOnlyNameTokenCodes(), + [T_VARIABLE, T_ISSET, T_UNSET, T_CLOSE_PARENTHESIS, T_SELF, T_STATIC, T_PARENT] + ), + true + )) { + return; + } + + $parenthesisCloserPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + $pointerBeforeParenthesisCloser = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisCloserPointer - 1); + + if ($tokens[$pointerBeforeParenthesisCloser]['code'] !== T_COMMA) { + return; + } + + if ($this->onlySingleLine && $tokens[$parenthesisOpenerPointer]['line'] !== $tokens[$parenthesisCloserPointer]['line']) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Trailing comma after the last parameter in function call is disallowed.', + $pointerBeforeParenthesisCloser, + self::CODE_DISALLOWED_TRAILING_COMMA + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($pointerBeforeParenthesisCloser, ''); + + if ($tokens[$pointerBeforeParenthesisCloser]['line'] === $tokens[$parenthesisCloserPointer]['line']) { + FixerHelper::removeBetween($phpcsFile, $pointerBeforeParenthesisCloser, $parenthesisCloserPointer); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInClosureUseSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInClosureUseSniff.php new file mode 100644 index 000000000..ad8e2bc2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInClosureUseSniff.php @@ -0,0 +1,86 @@ + + */ + public function register(): array + { + return [ + T_CLOSURE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisCloserPointer = $tokens[$functionPointer]['parenthesis_closer']; + + $usePointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisCloserPointer + 1); + + if ($tokens[$usePointer]['code'] !== T_USE) { + return; + } + + $useParenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + $useParenthesisCloserPointer = $tokens[$useParenthesisOpenerPointer]['parenthesis_closer']; + + $pointerBeforeUseParenthesisCloser = TokenHelper::findPreviousExcluding( + $phpcsFile, + T_WHITESPACE, + $tokens[$useParenthesisOpenerPointer]['parenthesis_closer'] - 1, + $useParenthesisOpenerPointer + ); + + if ($tokens[$pointerBeforeUseParenthesisCloser]['code'] !== T_COMMA) { + return; + } + + if ($this->onlySingleLine && $tokens[$useParenthesisOpenerPointer]['line'] !== $tokens[$useParenthesisCloserPointer]['line']) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Trailing comma after the last inherited variable in "use" of closure declaration is disallowed.', + $pointerBeforeUseParenthesisCloser, + self::CODE_DISALLOWED_TRAILING_COMMA + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($pointerBeforeUseParenthesisCloser, ''); + + if ($tokens[$pointerBeforeUseParenthesisCloser]['line'] === $tokens[$useParenthesisCloserPointer]['line']) { + FixerHelper::removeBetween($phpcsFile, $pointerBeforeUseParenthesisCloser, $useParenthesisCloserPointer); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInDeclarationSniff.php new file mode 100644 index 000000000..4e3c747bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/DisallowTrailingCommaInDeclarationSniff.php @@ -0,0 +1,74 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = $tokens[$functionPointer]['parenthesis_opener']; + $parenthesisCloserPointer = $tokens[$functionPointer]['parenthesis_closer']; + + $pointerBeforeParenthesisCloser = TokenHelper::findPreviousExcluding( + $phpcsFile, + T_WHITESPACE, + $parenthesisCloserPointer - 1, + $parenthesisOpenerPointer + ); + + if ($tokens[$pointerBeforeParenthesisCloser]['code'] !== T_COMMA) { + return; + } + + if ($this->onlySingleLine && $tokens[$parenthesisOpenerPointer]['line'] !== $tokens[$parenthesisCloserPointer]['line']) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Trailing comma after the last parameter in function declaration is disallowed.', + $pointerBeforeParenthesisCloser, + self::CODE_DISALLOWED_TRAILING_COMMA + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($pointerBeforeParenthesisCloser, ''); + + if ($tokens[$pointerBeforeParenthesisCloser]['line'] === $tokens[$parenthesisCloserPointer]['line']) { + FixerHelper::removeBetween($phpcsFile, $pointerBeforeParenthesisCloser, $parenthesisCloserPointer); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/FunctionLengthSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/FunctionLengthSniff.php new file mode 100644 index 000000000..0c15e81b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/FunctionLengthSniff.php @@ -0,0 +1,68 @@ + + */ + public function register(): array + { + return [T_FUNCTION]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $file, $functionPointer): void + { + $this->maxLinesLength = SniffSettingsHelper::normalizeInteger($this->maxLinesLength); + + $flags = array_keys(array_filter([ + FunctionHelper::LINE_INCLUDE_COMMENT => $this->includeComments, + FunctionHelper::LINE_INCLUDE_WHITESPACE => $this->includeWhitespace, + ])); + $flags = array_reduce($flags, static function ($carry, $flag): int { + return $carry | $flag; + }, 0); + + $length = FunctionHelper::getFunctionLengthInLines($file, $functionPointer, $flags); + + if ($length <= $this->maxLinesLength) { + return; + } + + $errorMessage = sprintf( + 'Your function is too long. Currently using %d lines. Can be up to %d lines.', + $length, + $this->maxLinesLength + ); + + $file->addError($errorMessage, $functionPointer, self::CODE_FUNCTION_LENGTH); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php new file mode 100644 index 000000000..b44272216 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/NamedArgumentSpacingSniff.php @@ -0,0 +1,79 @@ + + */ + public function register(): array + { + return [ + T_PARAM_NAME, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $colonPointer */ + $colonPointer = TokenHelper::findNext($phpcsFile, T_COLON, $pointer + 1); + + $parameterName = $tokens[$pointer]['content']; + + if ($colonPointer !== $pointer + 1) { + $fix = $phpcsFile->addFixableError( + sprintf('There must be no whitespace between named argument "%s" and colon.', $parameterName), + $colonPointer, + self::CODE_WHITESPACE_BEFORE_COLON + ); + if ($fix) { + $phpcsFile->fixer->replaceToken($colonPointer - 1, ''); + } + } + + $whitespacePointer = $colonPointer + 1; + + if ( + $tokens[$whitespacePointer]['code'] === T_WHITESPACE + && $tokens[$whitespacePointer]['content'] === ' ' + ) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('There must be exactly one space after colon in named argument "%s".', $parameterName), + $colonPointer, + self::CODE_NO_WHITESPACE_AFTER_COLON + ); + + if (!$fix) { + return; + } + + if ($tokens[$whitespacePointer]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($whitespacePointer, ' '); + } else { + $phpcsFile->fixer->addContent($colonPointer, ' '); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireArrowFunctionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireArrowFunctionSniff.php new file mode 100644 index 000000000..06e07873e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireArrowFunctionSniff.php @@ -0,0 +1,158 @@ + + */ + public function register(): array + { + return [ + T_CLOSURE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $closurePointer + */ + public function process(File $phpcsFile, $closurePointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 70400); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $returnPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$closurePointer]['scope_opener'] + 1); + if ($tokens[$returnPointer]['code'] !== T_RETURN) { + return; + } + + $usePointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$closurePointer]['parenthesis_closer'] + 1); + if ($tokens[$usePointer]['code'] === T_USE) { + $useOpenParenthesisPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + if (TokenHelper::findNext( + $phpcsFile, + T_BITWISE_AND, + $useOpenParenthesisPointer + 1, + $tokens[$useOpenParenthesisPointer]['parenthesis_closer'] + ) !== null) { + return; + } + } + + if (!$this->allowNested) { + $closureOrArrowFunctionPointer = TokenHelper::findNext( + $phpcsFile, + [T_CLOSURE, T_FN], + $tokens[$closurePointer]['scope_opener'] + 1, + $tokens[$closurePointer]['scope_closer'] + ); + if ($closureOrArrowFunctionPointer !== null) { + return; + } + } + + $fix = $phpcsFile->addFixableError('Use arrow function.', $closurePointer, self::CODE_REQUIRED_ARROW_FUNCTION); + if (!$fix) { + return; + } + + $pointerAfterReturn = TokenHelper::findNextNonWhitespace($phpcsFile, $returnPointer + 1); + $semicolonAfterReturn = $this->findSemicolon($phpcsFile, $returnPointer); + $usePointer = TokenHelper::findNext( + $phpcsFile, + T_USE, + $tokens[$closurePointer]['parenthesis_closer'] + 1, + $tokens[$closurePointer]['scope_opener'] + ); + $nonWhitespacePointerBeforeScopeOpener = TokenHelper::findPreviousExcluding( + $phpcsFile, + T_WHITESPACE, + $tokens[$closurePointer]['scope_opener'] - 1 + ); + + $nonWhitespacePointerAfterUseParenthesisCloser = null; + if ($usePointer !== null) { + $useParenthesiCloserPointer = TokenHelper::findNext($phpcsFile, T_CLOSE_PARENTHESIS, $usePointer + 1); + $nonWhitespacePointerAfterUseParenthesisCloser = TokenHelper::findNextExcluding( + $phpcsFile, + T_WHITESPACE, + $useParenthesiCloserPointer + 1 + ); + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($closurePointer, 'fn'); + + if ($nonWhitespacePointerAfterUseParenthesisCloser !== null) { + FixerHelper::removeBetween( + $phpcsFile, + $tokens[$closurePointer]['parenthesis_closer'], + $nonWhitespacePointerAfterUseParenthesisCloser + ); + } + + FixerHelper::removeBetween($phpcsFile, $nonWhitespacePointerBeforeScopeOpener, $pointerAfterReturn); + + $phpcsFile->fixer->addContent($nonWhitespacePointerBeforeScopeOpener, ' => '); + + FixerHelper::removeBetweenIncluding($phpcsFile, $semicolonAfterReturn, $tokens[$closurePointer]['scope_closer']); + + $phpcsFile->fixer->endChangeset(); + } + + private function findSemicolon(File $phpcsFile, int $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $semicolonPointer = null; + for ($i = $pointer + 1; $i < count($tokens) - 1; $i++) { + if ($tokens[$i]['code'] !== T_SEMICOLON) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $pointer, $i)) { + continue; + } + + $semicolonPointer = $i; + break; + } + + /** @var int $semicolonPointer */ + $semicolonPointer = $semicolonPointer; + return $semicolonPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireMultiLineCallSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireMultiLineCallSniff.php new file mode 100644 index 000000000..693eb175e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireMultiLineCallSniff.php @@ -0,0 +1,243 @@ +minLineLength = SniffSettingsHelper::normalizeInteger($this->minLineLength); + + if (!$this->isCall($phpcsFile, $stringPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + $parenthesisCloserPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + + // No parameters + $effectivePointerAfterParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + if ($effectivePointerAfterParenthesisOpener === $parenthesisCloserPointer) { + return; + } + + $parametersPointers = [TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1)]; + + $level = 0; + $pointers = TokenHelper::findNextAll( + $phpcsFile, + [T_COMMA, T_OPEN_PARENTHESIS, T_CLOSE_PARENTHESIS, T_OPEN_SHORT_ARRAY, T_CLOSE_SHORT_ARRAY], + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ); + foreach ($pointers as $pointer) { + if (in_array($tokens[$pointer]['code'], [T_OPEN_PARENTHESIS, T_OPEN_SHORT_ARRAY], true)) { + $level++; + continue; + } + + if (in_array($tokens[$pointer]['code'], [T_CLOSE_PARENTHESIS, T_CLOSE_SHORT_ARRAY], true)) { + $level--; + continue; + } + + if ($level !== 0) { + continue; + } + + $parameterPointer = TokenHelper::findNextEffective($phpcsFile, $pointer + 1, $parenthesisCloserPointer); + if ($parameterPointer !== null) { + $parametersPointers[] = $parameterPointer; + } + } + + $lines = [ + $tokens[$parenthesisOpenerPointer]['line'], + $tokens[$parenthesisCloserPointer]['line'], + ]; + foreach ($parametersPointers as $parameterPointer) { + $lines[] = $tokens[$parameterPointer]['line']; + } + + // Each parameter on its line + if (count(array_unique($lines)) - 2 >= count($parametersPointers)) { + return; + } + + if ($this->shouldBeSkipped($phpcsFile, $stringPointer, $parenthesisCloserPointer)) { + return; + } + + $lineStart = $this->getLineStart($phpcsFile, $parenthesisOpenerPointer); + + if ($tokens[$parenthesisCloserPointer]['line'] === $tokens[$stringPointer]['line']) { + $call = $this->getCall($phpcsFile, $parenthesisOpenerPointer, $parenthesisCloserPointer); + $lineEnd = $this->getLineEnd($phpcsFile, $parenthesisCloserPointer); + $lineLength = strlen($lineStart . $call . $lineEnd); + } else { + $lineEnd = $this->getLineEnd($phpcsFile, $parenthesisOpenerPointer); + $lineLength = strlen($lineStart . $lineEnd); + } + + $firstNonWhitespaceOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $stringPointer); + $indentation = IndentationHelper::getIndentation($phpcsFile, $firstNonWhitespaceOnLine); + $oneIndentation = IndentationHelper::getOneIndentationLevel($indentation); + + if (!$this->shouldReportError( + $lineLength, + $lineStart, + $lineEnd, + count($parametersPointers), + strlen(IndentationHelper::convertTabsToSpaces($phpcsFile, $oneIndentation)) + )) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $stringPointer - 1); + + $name = ltrim($tokens[$stringPointer]['content'], '\\'); + + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + $error = sprintf('Call of method %s() should be split to more lines.', $name); + } elseif ($tokens[$previousPointer]['code'] === T_NEW) { + $error = 'Constructor call should be split to more lines.'; + } else { + $error = sprintf('Call of function %s() should be split to more lines.', $name); + } + + $fix = $phpcsFile->addFixableError($error, $stringPointer, self::CODE_REQUIRED_MULTI_LINE_CALL); + + if (!$fix) { + return; + } + + $parametersIndentation = IndentationHelper::addIndentation($indentation); + + $phpcsFile->fixer->beginChangeset(); + + for ($i = $parenthesisOpenerPointer + 1; $i < $parenthesisCloserPointer; $i++) { + if (in_array($i, $parametersPointers, true)) { + FixerHelper::removeWhitespaceBefore($phpcsFile, $i); + $phpcsFile->fixer->addContentBefore($i, $phpcsFile->eolChar . $parametersIndentation); + } elseif ($tokens[$i]['content'] === $phpcsFile->eolChar) { + $phpcsFile->fixer->addContent($i, $oneIndentation); + } else { + // Create conflict so inner calls are fixed in next loop + $phpcsFile->fixer->replaceToken($i, $tokens[$i]['content']); + } + } + + $phpcsFile->fixer->addContentBefore($parenthesisCloserPointer, $phpcsFile->eolChar . $indentation); + + $phpcsFile->fixer->endChangeset(); + } + + private function shouldBeSkipped(File $phpcsFile, int $stringPointer, int $parenthesisCloserPointer): bool + { + $tokens = $phpcsFile->getTokens(); + $nameTokenCodes = TokenHelper::getOnlyNameTokenCodes(); + + $searchStartPointer = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $stringPointer); + while (true) { + $stringPointerBefore = TokenHelper::findNext($phpcsFile, $nameTokenCodes, $searchStartPointer, $stringPointer); + + if ($stringPointerBefore === null) { + break; + } + + $pointerAfterStringPointerBefore = TokenHelper::findNextEffective($phpcsFile, $stringPointerBefore + 1); + if ( + $tokens[$pointerAfterStringPointerBefore]['code'] === T_OPEN_PARENTHESIS + && $tokens[$pointerAfterStringPointerBefore]['parenthesis_closer'] > $stringPointer + ) { + return true; + } + + $searchStartPointer = $stringPointerBefore + 1; + } + + $lastPointerOnLine = TokenHelper::findLastTokenOnLine($phpcsFile, $parenthesisCloserPointer); + $searchStartPointer = $parenthesisCloserPointer + 1; + while (true) { + $stringPointerAfter = TokenHelper::findNext($phpcsFile, $nameTokenCodes, $searchStartPointer, $lastPointerOnLine + 1); + + if ($stringPointerAfter === null) { + break; + } + + $pointerAfterStringPointerAfter = TokenHelper::findNextEffective($phpcsFile, $stringPointerAfter + 1); + if ( + $pointerAfterStringPointerAfter !== null + && $tokens[$pointerAfterStringPointerAfter]['code'] === T_OPEN_PARENTHESIS + && $tokens[$tokens[$pointerAfterStringPointerAfter]['parenthesis_closer']]['line'] === $tokens[$stringPointer]['line'] + && $tokens[$pointerAfterStringPointerAfter]['parenthesis_closer'] !== TokenHelper::findNextEffective( + $phpcsFile, + $pointerAfterStringPointerAfter + 1 + ) + ) { + return true; + } + + $searchStartPointer = $stringPointerAfter + 1; + } + + return false; + } + + private function shouldReportError( + int $lineLength, + string $lineStart, + string $lineEnd, + int $parametersCount, + int $indentationLength + ): bool + { + if ($this->minLineLength === 0) { + return true; + } + + if ($lineLength < $this->minLineLength) { + return false; + } + + if ($parametersCount > 1) { + return true; + } + + return strlen(trim($lineStart) . trim($lineEnd)) > $indentationLength; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireSingleLineCallSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireSingleLineCallSniff.php new file mode 100644 index 000000000..6e1bd4cb1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireSingleLineCallSniff.php @@ -0,0 +1,200 @@ +maxLineLength = SniffSettingsHelper::normalizeInteger($this->maxLineLength); + + if (!$this->isCall($phpcsFile, $stringPointer)) { + return; + } + + if ($this->shouldBeSkipped($phpcsFile, $stringPointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + $parenthesisCloserPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + + if ($tokens[$parenthesisOpenerPointer]['line'] === $tokens[$parenthesisCloserPointer]['line']) { + return; + } + + if (TokenHelper::findNext( + $phpcsFile, + array_merge(TokenHelper::$inlineCommentTokenCodes, Tokens::$heredocTokens), + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) !== null) { + return; + } + + for ($i = $parenthesisOpenerPointer + 1; $i < $parenthesisCloserPointer; $i++) { + if ($tokens[$i]['code'] !== T_CONSTANT_ENCAPSED_STRING && $tokens[$i]['code'] !== T_DOUBLE_QUOTED_STRING) { + continue; + } + + if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { + return; + } + } + + if ($this->ignoreWithComplexParameter) { + if ( + TokenHelper::findNext( + $phpcsFile, + [T_CLOSURE, T_FN, T_OPEN_SHORT_ARRAY], + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) !== null + ) { + return; + } + + // Contains inner call + $callSearchStartPointer = $parenthesisOpenerPointer + 1; + $nameTokenCodes = TokenHelper::getOnlyNameTokenCodes(); + while (true) { + $innerStringPointer = TokenHelper::findNext( + $phpcsFile, + $nameTokenCodes, + $callSearchStartPointer, + $parenthesisCloserPointer + ); + if ($innerStringPointer === null) { + break; + } + + $pointerAfterInnerString = TokenHelper::findNextEffective($phpcsFile, $innerStringPointer + 1); + if ( + $pointerAfterInnerString !== null + && $tokens[$pointerAfterInnerString]['code'] === T_OPEN_PARENTHESIS + ) { + return; + } + + $callSearchStartPointer = $innerStringPointer + 1; + } + } + + $lineStart = $this->getLineStart($phpcsFile, $parenthesisOpenerPointer); + $call = $this->getCall($phpcsFile, $parenthesisOpenerPointer, $parenthesisCloserPointer); + $lineEnd = $this->getLineEnd($phpcsFile, $parenthesisCloserPointer); + + $lineLength = strlen($lineStart . $call . $lineEnd); + + if (!$this->shouldReportError($lineLength)) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $stringPointer - 1); + + $name = ltrim($tokens[$stringPointer]['content'], '\\'); + + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + $error = sprintf('Call of method %s() should be placed on a single line.', $name); + } elseif ($tokens[$previousPointer]['code'] === T_NEW) { + $error = 'Constructor call should be placed on a single line.'; + } else { + $error = sprintf('Call of function %s() should be placed on a single line.', $name); + } + + $fix = $phpcsFile->addFixableError($error, $stringPointer, self::CODE_REQUIRED_SINGLE_LINE_CALL); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($parenthesisOpenerPointer, $call); + + FixerHelper::removeBetween($phpcsFile, $parenthesisOpenerPointer, $parenthesisCloserPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function shouldBeSkipped(File $phpcsFile, int $stringPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + foreach (array_reverse(TokenHelper::findNextAll($phpcsFile, [T_OPEN_PARENTHESIS, T_FUNCTION], 0, $stringPointer)) as $pointer) { + if ($tokens[$pointer]['code'] === T_FUNCTION) { + if (array_key_exists('scope_closer', $tokens[$pointer]) && $tokens[$pointer]['scope_closer'] > $stringPointer) { + return false; + } + + continue; + } + + if ($tokens[$pointer]['parenthesis_closer'] < $stringPointer) { + continue; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + if ( + $pointerBeforeParenthesisOpener === null + || $tokens[$pointerBeforeParenthesisOpener]['code'] !== T_STRING + ) { + continue; + } + + return true; + } + + return false; + } + + private function shouldReportError(int $lineLength): bool + { + if ($this->maxLineLength === 0) { + return true; + } + + return $lineLength <= $this->maxLineLength; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInCallSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInCallSniff.php new file mode 100644 index 000000000..774801102 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInCallSniff.php @@ -0,0 +1,104 @@ + + */ + public function register(): array + { + return [ + T_OPEN_PARENTHESIS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $parenthesisOpenerPointer + */ + public function process(File $phpcsFile, $parenthesisOpenerPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 70300); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if (array_key_exists('parenthesis_owner', $tokens[$parenthesisOpenerPointer])) { + return; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if (!in_array( + $tokens[$pointerBeforeParenthesisOpener]['code'], + array_merge( + TokenHelper::getOnlyNameTokenCodes(), + [T_VARIABLE, T_ISSET, T_UNSET, T_CLOSE_PARENTHESIS, T_SELF, T_STATIC, T_PARENT] + ), + true + )) { + return; + } + + $parenthesisCloserPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + + if ($tokens[$parenthesisOpenerPointer]['line'] === $tokens[$parenthesisCloserPointer]['line']) { + return; + } + + $pointerBeforeParenthesisCloser = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisCloserPointer - 1); + if ($pointerBeforeParenthesisCloser === $parenthesisOpenerPointer) { + return; + } + + if ($tokens[$parenthesisCloserPointer]['line'] === $tokens[$pointerBeforeParenthesisCloser]['line']) { + return; + } + + if ($tokens[$pointerBeforeParenthesisCloser]['code'] === T_COMMA) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Multi-line function calls must have a trailing comma after the last parameter.', + $pointerBeforeParenthesisCloser, + self::CODE_MISSING_TRAILING_COMMA + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($pointerBeforeParenthesisCloser, ','); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInClosureUseSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInClosureUseSniff.php new file mode 100644 index 000000000..e50a8e3b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInClosureUseSniff.php @@ -0,0 +1,85 @@ + + */ + public function register(): array + { + return [T_CLOSURE]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisCloserPointer = $tokens[$functionPointer]['parenthesis_closer']; + + $usePointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisCloserPointer + 1); + + if ($tokens[$usePointer]['code'] !== T_USE) { + return; + } + + $useParenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + $useParenthesisCloserPointer = $tokens[$useParenthesisOpenerPointer]['parenthesis_closer']; + + if ($tokens[$useParenthesisOpenerPointer]['line'] === $tokens[$useParenthesisCloserPointer]['line']) { + return; + } + + $pointerBeforeUseParenthesisCloser = TokenHelper::findPreviousExcluding( + $phpcsFile, + T_WHITESPACE, + $useParenthesisCloserPointer - 1, + $useParenthesisOpenerPointer + ); + + if ($tokens[$pointerBeforeUseParenthesisCloser]['code'] === T_COMMA) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Multi-line "use" of closure declaration must have a trailing comma after the last inherited variable.', + $pointerBeforeUseParenthesisCloser, + self::CODE_MISSING_TRAILING_COMMA + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($pointerBeforeUseParenthesisCloser, ','); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInDeclarationSniff.php new file mode 100644 index 000000000..aab66c58e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/RequireTrailingCommaInDeclarationSniff.php @@ -0,0 +1,77 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = $tokens[$functionPointer]['parenthesis_opener']; + $parenthesisCloserPointer = $tokens[$functionPointer]['parenthesis_closer']; + + if ($tokens[$parenthesisOpenerPointer]['line'] === $tokens[$parenthesisCloserPointer]['line']) { + return; + } + + $pointerBeforeParenthesisCloser = TokenHelper::findPreviousEffective( + $phpcsFile, + $parenthesisCloserPointer - 1, + $parenthesisOpenerPointer + ); + + if ($pointerBeforeParenthesisCloser === $parenthesisOpenerPointer) { + return; + } + + if ($tokens[$pointerBeforeParenthesisCloser]['code'] === T_COMMA) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Multi-line function declaration must have a trailing comma after the last parameter.', + $pointerBeforeParenthesisCloser, + self::CODE_MISSING_TRAILING_COMMA + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($pointerBeforeParenthesisCloser, ','); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StaticClosureSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StaticClosureSniff.php new file mode 100644 index 000000000..5e2053cc9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StaticClosureSniff.php @@ -0,0 +1,103 @@ + + */ + public function register(): array + { + return [ + T_CLOSURE, + T_FN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $closurePointer + */ + public function process(File $phpcsFile, $closurePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $closurePointer - 1); + if ($tokens[$previousPointer]['code'] === T_STATIC) { + return; + } + + if ($tokens[$previousPointer]['code'] === T_OPEN_PARENTHESIS) { + $pointerBeforeParenthesis = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + if ( + $tokens[$pointerBeforeParenthesis]['code'] === T_STRING + && $tokens[$pointerBeforeParenthesis]['content'] === 'bind' + ) { + return; + } + } + + $closureScopeOpenerPointer = $tokens[$closurePointer]['scope_opener']; + $closureScopeCloserPointer = $tokens[$closurePointer]['scope_closer']; + + $thisPointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + '$this', + $closureScopeOpenerPointer + 1, + $closureScopeCloserPointer + ); + if ($thisPointer !== null) { + return; + } + + $stringPointers = TokenHelper::findNextAll( + $phpcsFile, + T_DOUBLE_QUOTED_STRING, + $closureScopeOpenerPointer + 1, + $closureScopeCloserPointer + ); + foreach ($stringPointers as $stringPointer) { + if (VariableHelper::isUsedInScopeInString($phpcsFile, '$this', $stringPointer)) { + return; + } + } + + $parentPointer = TokenHelper::findNext($phpcsFile, T_PARENT, $closureScopeOpenerPointer + 1, $closureScopeCloserPointer); + if ($parentPointer !== null) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Closure not using "$this" should be declared static.', + $closurePointer, + self::CODE_CLOSURE_NOT_STATIC + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($closurePointer, 'static '); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StrictCallSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StrictCallSniff.php new file mode 100644 index 000000000..a012fb4a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/StrictCallSniff.php @@ -0,0 +1,127 @@ + 3, + 'array_search' => 3, + 'base64_decode' => 2, + 'array_keys' => 3, + ]; + + /** + * @return array + */ + public function register(): array + { + return TokenHelper::getOnlyNameTokenCodes(); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stringPointer + */ + public function process(File $phpcsFile, $stringPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + if ($tokens[$parenthesisOpenerPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + $parenthesisCloserPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + + $functionName = ltrim(strtolower($tokens[$stringPointer]['content']), '\\'); + + if (!array_key_exists($functionName, self::FUNCTIONS)) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $stringPointer - 1); + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_FUNCTION], true)) { + return; + } + + $commaPointers = []; + for ($i = $parenthesisOpenerPointer + 1; $i < $parenthesisCloserPointer; $i++) { + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_COMMA) { + $commaPointers[] = $i; + } + } + + $commaPointersCount = count($commaPointers); + + $parametersCount = $commaPointersCount + 1; + $lastCommaPointer = $commaPointersCount > 0 ? $commaPointers[$commaPointersCount - 1] : null; + $hasTrailingComma = false; + + if ( + $lastCommaPointer !== null + && TokenHelper::findNextEffective($phpcsFile, $lastCommaPointer + 1, $parenthesisCloserPointer) === null + ) { + $hasTrailingComma = true; + $parametersCount--; + } + + if ($parametersCount === self::FUNCTIONS[$functionName]) { + + $strictParameterValue = TokenHelper::getContent( + $phpcsFile, + $commaPointers[self::FUNCTIONS[$functionName] - 2] + 1, + ($hasTrailingComma ? $lastCommaPointer : $parenthesisCloserPointer) - 1 + ); + + if (strtolower(trim($strictParameterValue)) !== 'false') { + return; + } + + $phpcsFile->addError( + sprintf('Strict parameter should be set to true in %s() call.', $functionName), + $stringPointer, + self::CODE_NON_STRICT_COMPARISON + ); + + } elseif ($parametersCount === self::FUNCTIONS[$functionName] - 1) { + $phpcsFile->addError( + sprintf('Strict parameter missing in %s() call.', $functionName), + $stringPointer, + self::CODE_STRICT_PARAMETER_MISSING + ); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedInheritedVariablePassedToClosureSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedInheritedVariablePassedToClosureSniff.php new file mode 100644 index 000000000..3fe2e7e20 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedInheritedVariablePassedToClosureSniff.php @@ -0,0 +1,150 @@ + + */ + public function register(): array + { + return [ + T_USE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $usePointer + */ + public function process(File $phpcsFile, $usePointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $parenthesisOpenerPointer */ + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + if ($tokens[$parenthesisOpenerPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + /** @var int $closurePointer */ + $closurePointer = TokenHelper::findPrevious($phpcsFile, T_CLOSURE, $usePointer - 1); + + $currentPointer = $parenthesisOpenerPointer + 1; + do { + $variablePointer = TokenHelper::findNext( + $phpcsFile, + T_VARIABLE, + $currentPointer, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + ); + if ($variablePointer === null) { + break; + } + + $this->checkVariableUsage( + $phpcsFile, + $usePointer, + $parenthesisOpenerPointer, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'], + $variablePointer, + $closurePointer + ); + + $currentPointer = $variablePointer + 1; + } while (true); + } + + private function checkVariableUsage( + File $phpcsFile, + int $usePointer, + int $useParenthesisOpenerPointer, + int $useParenthesisCloserPointer, + int $variablePointer, + int $scopeOwnerPointer + ): void + { + $tokens = $phpcsFile->getTokens(); + + if (VariableHelper::isUsedInScope($phpcsFile, $scopeOwnerPointer, $variablePointer)) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Unused inherited variable %s passed to closure.', $tokens[$variablePointer]['content']), + $variablePointer, + self::CODE_UNUSED_INHERITED_VARIABLE + ); + + if (!$fix) { + return; + } + + $fixStartPointer = $variablePointer; + do { + if ($tokens[$fixStartPointer - 1]['code'] === T_OPEN_PARENTHESIS) { + break; + } + + $fixStartPointer--; + + if ($tokens[$fixStartPointer]['code'] === T_COMMA) { + break; + } + } while (true); + + $fixEndPointer = $variablePointer; + do { + if ($tokens[$fixEndPointer + 1]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + + if ($tokens[$fixEndPointer + 1]['code'] === T_COMMA && $tokens[$fixStartPointer]['code'] === T_COMMA) { + break; + } + + if (in_array($tokens[$fixEndPointer + 1]['code'], [T_VARIABLE, T_BITWISE_AND], true)) { + break; + } + + $fixEndPointer++; + } while (true); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $fixStartPointer, $fixEndPointer); + + $emptyUse = true; + for ($i = $useParenthesisOpenerPointer + 1; $i < $useParenthesisCloserPointer; $i++) { + if ($phpcsFile->fixer->getTokenContent($i) !== '') { + $emptyUse = false; + break; + } + } + if ($emptyUse) { + FixerHelper::removeBetweenIncluding($phpcsFile, $usePointer, $useParenthesisCloserPointer); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedParameterSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedParameterSniff.php new file mode 100644 index 000000000..857f7b30b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UnusedParameterSniff.php @@ -0,0 +1,107 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + if (FunctionHelper::isAbstract($phpcsFile, $functionPointer)) { + return; + } + + $isSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $this->getSniffName(self::CODE_UNUSED_PARAMETER)); + $suppressUseless = true; + + $tokens = $phpcsFile->getTokens(); + + $currentPointer = $tokens[$functionPointer]['parenthesis_opener'] + 1; + while (true) { + $parameterPointer = TokenHelper::findNext( + $phpcsFile, + T_VARIABLE, + $currentPointer, + $tokens[$functionPointer]['parenthesis_closer'] + ); + if ($parameterPointer === null) { + break; + } + + $previousPointer = TokenHelper::findPrevious( + $phpcsFile, + array_merge([T_COMMA], Tokens::$scopeModifiers), + $parameterPointer - 1, + $tokens[$functionPointer]['parenthesis_opener'] + ); + + if ($previousPointer !== null && in_array($tokens[$previousPointer]['code'], Tokens::$scopeModifiers, true)) { + $currentPointer = $parameterPointer + 1; + continue; + } + + if (VariableHelper::isUsedInScope($phpcsFile, $functionPointer, $parameterPointer)) { + $currentPointer = $parameterPointer + 1; + continue; + } + + if (!$isSuppressed) { + $phpcsFile->addError( + sprintf('Unused parameter %s.', $tokens[$parameterPointer]['content']), + $parameterPointer, + self::CODE_UNUSED_PARAMETER + ); + } else { + $suppressUseless = false; + } + + $currentPointer = $parameterPointer + 1; + } + + if (!$isSuppressed || !$suppressUseless) { + return; + } + + $phpcsFile->addError( + sprintf('Useless %s %s', SuppressHelper::ANNOTATION, self::NAME), + $functionPointer, + self::CODE_USELESS_SUPPRESS + ); + } + + private function getSniffName(string $sniffName): string + { + return sprintf('%s.%s', self::NAME, $sniffName); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UselessParameterDefaultValueSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UselessParameterDefaultValueSniff.php new file mode 100644 index 000000000..2a9d613dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Functions/UselessParameterDefaultValueSniff.php @@ -0,0 +1,88 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $parameters = $phpcsFile->getMethodParameters($functionPointer); + $parametersCount = count($parameters); + + if ($parametersCount === 0) { + return; + } + + for ($i = 0; $i < $parametersCount; $i++) { + $parameter = $parameters[$i]; + + if (!array_key_exists('default', $parameter)) { + continue; + } + + $defaultValue = strtolower($parameter['default']); + if ($defaultValue === 'null' && !$parameter['nullable_type']) { + continue; + } + + for ($j = $i + 1; $j < $parametersCount; $j++) { + $nextParameter = $parameters[$j]; + + if (array_key_exists('default', $nextParameter)) { + continue; + } + + if ($nextParameter['variable_length']) { + break; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Useless default value of parameter %s.', $parameter['name']), + $parameter['token'], + self::CODE_USELESS_PARAMETER_DEFAULT_VALUE + ); + + if (!$fix) { + continue; + } + + $commaPointer = TokenHelper::findPrevious($phpcsFile, T_COMMA, $parameters[$i + 1]['token'] - 1); + /** @var int $parameterPointer */ + $parameterPointer = $parameter['token']; + + $phpcsFile->fixer->beginChangeset(); + for ($k = $parameterPointer + 1; $k < $commaPointer; $k++) { + $phpcsFile->fixer->replaceToken($k, ''); + } + $phpcsFile->fixer->endChangeset(); + + break; + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AbstractFullyQualifiedGlobalReference.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AbstractFullyQualifiedGlobalReference.php new file mode 100644 index 000000000..5e91e0e63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AbstractFullyQualifiedGlobalReference.php @@ -0,0 +1,172 @@ + */ + public $exclude = []; + + /** @var list */ + public $include = []; + + /** @var list|null */ + private $normalizedExclude; + + /** @var list|null */ + private $normalizedInclude; + + abstract protected function getNotFullyQualifiedMessage(): string; + + abstract protected function isCaseSensitive(): bool; + + abstract protected function isValidType(ReferencedName $name): bool; + + /** + * @return array + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + if (TokenHelper::findNext($phpcsFile, T_OPEN_USE_GROUP, $openTagPointer) !== null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $namespacePointers = NamespaceHelper::getAllNamespacesPointers($phpcsFile); + $referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer); + $include = array_flip($this->getNormalizedInclude()); + $exclude = array_flip($this->getNormalizedExclude()); + + foreach ($referencedNames as $referencedName) { + $name = $referencedName->getNameAsReferencedInFile(); + $namePointer = $referencedName->getStartPointer(); + + if (!$this->isValidType($referencedName)) { + continue; + } + + if (NamespaceHelper::isFullyQualifiedName($name)) { + continue; + } + + if (NamespaceHelper::hasNamespace($name)) { + continue; + } + + if ($namespacePointers === []) { + continue; + } + + $canonicalName = $this->isCaseSensitive() ? $name : strtolower($name); + + $useStatements = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $namePointer); + + if (array_key_exists(UseStatement::getUniqueId($referencedName->getType(), $canonicalName), $useStatements)) { + $fullyQualifiedName = NamespaceHelper::resolveName($phpcsFile, $name, $referencedName->getType(), $namePointer); + if (NamespaceHelper::hasNamespace($fullyQualifiedName)) { + continue; + } + } + + if ($include !== [] && !array_key_exists($canonicalName, $include)) { + continue; + } + + if (array_key_exists($canonicalName, $exclude)) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf($this->getNotFullyQualifiedMessage(), $tokens[$namePointer]['content']), + $namePointer, + self::CODE_NON_FULLY_QUALIFIED + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore($namePointer, NamespaceHelper::NAMESPACE_SEPARATOR); + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * @return list + */ + protected function getNormalizedInclude(): array + { + if ($this->normalizedInclude === null) { + $this->normalizedInclude = $this->normalizeNames($this->include); + } + return $this->normalizedInclude; + } + + /** + * @return list + */ + private function getNormalizedExclude(): array + { + if ($this->normalizedExclude === null) { + $this->normalizedExclude = $this->normalizeNames($this->exclude); + } + return $this->normalizedExclude; + } + + /** + * @param list $names + * @return list + */ + private function normalizeNames(array $names): array + { + $names = SniffSettingsHelper::normalizeArray($names); + + if (!$this->isCaseSensitive()) { + $names = array_map(static function (string $name): string { + return strtolower($name); + }, $names); + } + + return $names; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php new file mode 100644 index 000000000..6e5b3a0d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/AlphabeticallySortedUsesSniff.php @@ -0,0 +1,240 @@ + + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + // If there are any 'use group' statements then we cannot sort and fix the file. + $groupUsePointer = TokenHelper::findNext($phpcsFile, T_OPEN_USE_GROUP, $openTagPointer); + if ($groupUsePointer !== null) { + return; + } + + $fileUseStatements = UseStatementHelper::getFileUseStatements($phpcsFile); + foreach ($fileUseStatements as $useStatements) { + $lastUse = null; + foreach ($useStatements as $useStatement) { + if ($lastUse === null) { + $lastUse = $useStatement; + } else { + $order = $this->compareUseStatements($useStatement, $lastUse); + if ($order < 0) { + // The use statements are not ordered correctly. Go through all statements and if any are multi-part then + // we report the problem but cannot fix it, because this would lose the secondary parts of the statement. + $fixable = true; + $tokens = $phpcsFile->getTokens(); + foreach ($useStatements as $statement) { + $nextBreaker = TokenHelper::findNext($phpcsFile, [T_SEMICOLON, T_COMMA], $statement->getPointer()); + + if ($tokens[$nextBreaker]['code'] === T_COMMA) { + $fixable = false; + break; + } + } + + $errorParameters = [ + sprintf( + 'Use statements should be sorted alphabetically. The first wrong one is %s.', + $useStatement->getFullyQualifiedTypeName() + ), + $useStatement->getPointer(), + self::CODE_INCORRECT_ORDER, + ]; + + if (!$fixable) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + if ($fix) { + $this->fixAlphabeticalOrder($phpcsFile, $useStatements); + } + + return; + } + + $lastUse = $useStatement; + } + } + } + } + + /** + * @param array $useStatements + */ + private function fixAlphabeticalOrder(File $phpcsFile, array $useStatements): void + { + /** @var UseStatement $firstUseStatement */ + $firstUseStatement = reset($useStatements); + /** @var UseStatement $lastUseStatement */ + $lastUseStatement = end($useStatements); + $lastSemicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $lastUseStatement->getPointer()); + + $firstPointer = $firstUseStatement->getPointer(); + + $tokens = $phpcsFile->getTokens(); + + $commentsBefore = []; + foreach ($useStatements as $useStatement) { + $pointerBeforeUseStatement = TokenHelper::findPreviousNonWhitespace($phpcsFile, $useStatement->getPointer() - 1); + + if (!in_array($tokens[$pointerBeforeUseStatement]['code'], Tokens::$commentTokens, true)) { + continue; + } + + $commentAndWhitespace = TokenHelper::getContent($phpcsFile, $pointerBeforeUseStatement, $useStatement->getPointer() - 1); + if (StringHelper::endsWith($commentAndWhitespace, $phpcsFile->eolChar . $phpcsFile->eolChar)) { + continue; + } + + $commentStartPointer = in_array($tokens[$pointerBeforeUseStatement]['code'], TokenHelper::$inlineCommentTokenCodes, true) + ? CommentHelper::getMultilineCommentStartPointer($phpcsFile, $pointerBeforeUseStatement) + : $tokens[$pointerBeforeUseStatement]['comment_opener']; + + $commentsBefore[$useStatement->getPointer()] = TokenHelper::getContent( + $phpcsFile, + $commentStartPointer, + $pointerBeforeUseStatement + ); + + if ($firstPointer === $useStatement->getPointer()) { + $firstPointer = $commentStartPointer; + } + } + + uasort($useStatements, function (UseStatement $a, UseStatement $b): int { + return $this->compareUseStatements($a, $b); + }); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $firstPointer, $lastSemicolonPointer); + + $phpcsFile->fixer->addContent( + $firstPointer, + implode($phpcsFile->eolChar, array_map(static function (UseStatement $useStatement) use ($phpcsFile, $commentsBefore): string { + $unqualifiedName = NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($useStatement->getFullyQualifiedTypeName()); + + $useTypeName = UseStatement::getTypeName($useStatement->getType()); + $useTypeFormatted = $useTypeName !== null ? sprintf('%s ', $useTypeName) : ''; + + $commentBefore = ''; + if (array_key_exists($useStatement->getPointer(), $commentsBefore)) { + $commentBefore = $commentsBefore[$useStatement->getPointer()]; + if (!StringHelper::endsWith($commentBefore, $phpcsFile->eolChar)) { + $commentBefore .= $phpcsFile->eolChar; + } + } + + if ($unqualifiedName === $useStatement->getNameAsReferencedInFile()) { + return sprintf('%suse %s%s;', $commentBefore, $useTypeFormatted, $useStatement->getFullyQualifiedTypeName()); + } + + return sprintf( + '%suse %s%s as %s;', + $commentBefore, + $useTypeFormatted, + $useStatement->getFullyQualifiedTypeName(), + $useStatement->getNameAsReferencedInFile() + ); + }, $useStatements)) + ); + $phpcsFile->fixer->endChangeset(); + } + + private function compareUseStatements(UseStatement $a, UseStatement $b): int + { + if (!$a->hasSameType($b)) { + $order = [ + UseStatement::TYPE_CLASS => 1, + UseStatement::TYPE_FUNCTION => $this->psr12Compatible ? 2 : 3, + UseStatement::TYPE_CONSTANT => $this->psr12Compatible ? 3 : 2, + ]; + + return $order[$a->getType()] <=> $order[$b->getType()]; + } + + $aNameParts = explode(NamespaceHelper::NAMESPACE_SEPARATOR, $a->getFullyQualifiedTypeName()); + $bNameParts = explode(NamespaceHelper::NAMESPACE_SEPARATOR, $b->getFullyQualifiedTypeName()); + + $minPartsCount = min(count($aNameParts), count($bNameParts)); + for ($i = 0; $i < $minPartsCount; $i++) { + $comparison = $this->compare($aNameParts[$i], $bNameParts[$i]); + if ($comparison === 0) { + continue; + } + + return $comparison; + } + + return count($aNameParts) <=> count($bNameParts); + } + + private function compare(string $a, string $b): int + { + if ($this->caseSensitive) { + return strcmp($a, $b); + } + + return strcasecmp($a, $b); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/DisallowGroupUseSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/DisallowGroupUseSniff.php new file mode 100644 index 000000000..35aecfa4d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/DisallowGroupUseSniff.php @@ -0,0 +1,37 @@ + + */ + public function register(): array + { + return [ + T_OPEN_USE_GROUP, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $usePointer + */ + public function process(File $phpcsFile, $usePointer): void + { + $phpcsFile->addError( + 'Group use declaration is disallowed, use single use for every import.', + $usePointer, + self::CODE_DISALLOWED_GROUP_USE + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedClassNameInAnnotationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedClassNameInAnnotationSniff.php new file mode 100644 index 000000000..17f25b0a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedClassNameInAnnotationSniff.php @@ -0,0 +1,173 @@ + */ + public $ignoredAnnotationNames = []; + + /** + * @return array + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + $this->ignoredAnnotationNames = SniffSettingsHelper::normalizeArray($this->ignoredAnnotationNames); + + foreach ($annotations as $annotation) { + /** @var list $identifierTypeNodes */ + $identifierTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), IdentifierTypeNode::class); + + $annotationName = $annotation->getName(); + + foreach ($identifierTypeNodes as $typeHintNode) { + $typeHint = $typeHintNode->name; + + $lowercasedTypeHint = strtolower($typeHint); + if ( + TypeHintHelper::isSimpleTypeHint($lowercasedTypeHint) + || TypeHintHelper::isSimpleUnofficialTypeHints($lowercasedTypeHint) + || !TypeHelper::isTypeName($typeHint) + || TypeHintHelper::isTypeDefinedInAnnotation($phpcsFile, $docCommentOpenPointer, $typeHint) + ) { + continue; + } + + if (in_array($annotationName, $this->ignoredAnnotationNames, true)) { + continue; + } + + $fullyQualifiedTypeHint = TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $docCommentOpenPointer, $typeHint); + if ($fullyQualifiedTypeHint === $typeHint) { + continue; + } + + $fix = $phpcsFile->addFixableError(sprintf( + 'Class name %s in %s should be referenced via a fully qualified name.', + $fullyQualifiedTypeHint, + $annotationName + ), $annotation->getStartPointer(), self::CODE_NON_FULLY_QUALIFIED_CLASS_NAME); + + if (!$fix) { + continue; + } + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + $fixedDocComment = AnnotationHelper::fixAnnotation( + $parsedDocComment, + $annotation, + $typeHintNode, + new IdentifierTypeNode($fullyQualifiedTypeHint) + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change( + $phpcsFile, + $parsedDocComment->getOpenPointer(), + $parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + $phpcsFile->fixer->endChangeset(); + } + + /** @var list $constantFetchNodes */ + $constantFetchNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), ConstFetchNode::class); + + foreach ($constantFetchNodes as $constantFetchNode) { + $isClassConstant = $constantFetchNode->className !== ''; + + $typeHint = $isClassConstant + ? $constantFetchNode->className + : $constantFetchNode->name; + + if ($typeHint === 'self') { + continue; + } + + $fullyQualifiedTypeHint = $isClassConstant + ? NamespaceHelper::resolveClassName($phpcsFile, $typeHint, $docCommentOpenPointer) + : NamespaceHelper::resolveName($phpcsFile, $typeHint, ReferencedName::TYPE_CONSTANT, $docCommentOpenPointer); + + if ($fullyQualifiedTypeHint === $typeHint) { + continue; + } + + $fix = $phpcsFile->addFixableError(sprintf( + '%s name %s in %s should be referenced via a fully qualified name.', + $isClassConstant ? 'Class' : 'Constant', + $fullyQualifiedTypeHint, + $annotationName + ), $annotation->getStartPointer(), self::CODE_NON_FULLY_QUALIFIED_CLASS_NAME); + + if (!$fix) { + continue; + } + + $fixedConstantFetchNode = PhpDocParserHelper::cloneNode($constantFetchNode); + if ($isClassConstant) { + $fixedConstantFetchNode->className = $fullyQualifiedTypeHint; + } else { + $fixedConstantFetchNode->name = $fullyQualifiedTypeHint; + } + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + $fixedDocComment = AnnotationHelper::fixAnnotation( + $parsedDocComment, + $annotation, + $constantFetchNode, + $fixedConstantFetchNode + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change( + $phpcsFile, + $parsedDocComment->getOpenPointer(), + $parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + $phpcsFile->fixer->endChangeset(); + + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedExceptionsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedExceptionsSniff.php new file mode 100644 index 000000000..8d410cbd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedExceptionsSniff.php @@ -0,0 +1,162 @@ + */ + public $specialExceptionNames = []; + + /** @var list */ + public $ignoredNames = []; + + /** @var list|null */ + private $normalizedSpecialExceptionNames; + + /** @var list|null */ + private $normalizedIgnoredNames; + + /** + * @return array + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $namespacePointers = array_reverse(NamespaceHelper::getAllNamespacesPointers($phpcsFile)); + + $referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer); + foreach ($referencedNames as $referencedName) { + $pointer = $referencedName->getStartPointer(); + $name = $referencedName->getNameAsReferencedInFile(); + $uniqueId = UseStatement::getUniqueId($referencedName->getType(), $name); + $useStatements = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $pointer); + + if ( + isset($useStatements[$uniqueId]) + && $referencedName->hasSameUseStatementType($useStatements[$uniqueId]) + ) { + $useStatement = $useStatements[$uniqueId]; + if ( + in_array($useStatement->getFullyQualifiedTypeName(), $this->getIgnoredNames(), true) + || ( + !StringHelper::endsWith($useStatement->getFullyQualifiedTypeName(), 'Exception') + && $useStatement->getFullyQualifiedTypeName() !== Throwable::class + && (!StringHelper::endsWith($useStatement->getFullyQualifiedTypeName(), 'Error') || NamespaceHelper::hasNamespace( + $useStatement->getFullyQualifiedTypeName() + )) + && !in_array($useStatement->getFullyQualifiedTypeName(), $this->getSpecialExceptionNames(), true) + ) + ) { + continue; + } + } else { + $fileNamespacePointer = null; + if ($namespacePointers !== []) { + foreach ($namespacePointers as $namespacePointer) { + if ($namespacePointer < $pointer) { + $fileNamespacePointer = $namespacePointer; + break; + } + } + } + + $fileNamespace = $fileNamespacePointer !== null + ? NamespaceHelper::getName($phpcsFile, $fileNamespacePointer) + : null; + $canonicalName = $name; + if (!NamespaceHelper::isFullyQualifiedName($name) && $fileNamespace !== null) { + $canonicalName = sprintf('%s%s%s', $fileNamespace, NamespaceHelper::NAMESPACE_SEPARATOR, $name); + } + if ( + in_array($canonicalName, $this->getIgnoredNames(), true) + || ( + !StringHelper::endsWith($name, 'Exception') + && $name !== Throwable::class + && (!StringHelper::endsWith($canonicalName, 'Error') || NamespaceHelper::hasNamespace($canonicalName)) + && !in_array($canonicalName, $this->getSpecialExceptionNames(), true) + ) + ) { + continue; + } + } + + if (NamespaceHelper::isFullyQualifiedName($name)) { + continue; + } + + $fix = $phpcsFile->addFixableError(sprintf( + 'Exception %s should be referenced via a fully qualified name.', + $name + ), $pointer, self::CODE_NON_FULLY_QUALIFIED_EXCEPTION); + if (!$fix) { + continue; + } + + $fullyQualifiedName = NamespaceHelper::resolveClassName($phpcsFile, $name, $pointer); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $referencedName->getStartPointer(), $referencedName->getEndPointer(), $fullyQualifiedName); + + $phpcsFile->fixer->endChangeset(); + } + } + + /** + * @return list + */ + private function getSpecialExceptionNames(): array + { + if ($this->normalizedSpecialExceptionNames === null) { + $this->normalizedSpecialExceptionNames = SniffSettingsHelper::normalizeArray($this->specialExceptionNames); + } + + return $this->normalizedSpecialExceptionNames; + } + + /** + * @return list + */ + private function getIgnoredNames(): array + { + if ($this->normalizedIgnoredNames === null) { + $this->normalizedIgnoredNames = SniffSettingsHelper::normalizeArray($this->ignoredNames); + } + + return $this->normalizedIgnoredNames; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalConstantsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalConstantsSniff.php new file mode 100644 index 000000000..f45597ef7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalConstantsSniff.php @@ -0,0 +1,26 @@ +isConstant(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalFunctionsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalFunctionsSniff.php new file mode 100644 index 000000000..30741a3b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/FullyQualifiedGlobalFunctionsSniff.php @@ -0,0 +1,45 @@ + + */ + protected function getNormalizedInclude(): array + { + $include = parent::getNormalizedInclude(); + + if ($this->includeSpecialFunctions) { + $include = array_merge($include, FunctionHelper::SPECIAL_FUNCTIONS); + } + + return $include; + } + + protected function getNotFullyQualifiedMessage(): string + { + return 'Function %s() should be referenced via a fully qualified name.'; + } + + protected function isCaseSensitive(): bool + { + return false; + } + + protected function isValidType(ReferencedName $name): bool + { + return $name->isFunction(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/MultipleUsesPerLineSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/MultipleUsesPerLineSniff.php new file mode 100644 index 000000000..38ed1031d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/MultipleUsesPerLineSniff.php @@ -0,0 +1,48 @@ + + */ + public function register(): array + { + return [ + T_USE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $usePointer + */ + public function process(File $phpcsFile, $usePointer): void + { + if (!UseStatementHelper::isImportUse($phpcsFile, $usePointer)) { + return; + } + + $endPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $usePointer + 1); + $commaPointer = TokenHelper::findNext($phpcsFile, T_COMMA, $usePointer + 1, $endPointer); + + if ($commaPointer === null) { + return; + } + + $phpcsFile->addError('Multiple used types per use statement are forbidden.', $commaPointer, self::CODE_MULTIPLE_USES_PER_LINE); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceDeclarationSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceDeclarationSniff.php new file mode 100644 index 000000000..028a63e2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceDeclarationSniff.php @@ -0,0 +1,147 @@ + + */ + public function register(): array + { + return [ + T_NAMESPACE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $namespacePointer + */ + public function process(File $phpcsFile, $namespacePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $pointerAfterNamespace = TokenHelper::findNextEffective($phpcsFile, $namespacePointer + 1); + if ($tokens[$pointerAfterNamespace]['code'] === T_NS_SEPARATOR) { + return; + } + + $this->checkWhitespaceAfterNamespace($phpcsFile, $namespacePointer); + $this->checkDisallowedContentBetweenNamespaceNameAndSemicolon($phpcsFile, $namespacePointer); + $this->checkDisallowedBracketedSyntax($phpcsFile, $namespacePointer); + } + + private function checkWhitespaceAfterNamespace(File $phpcsFile, int $namespacePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $whitespacePointer = $namespacePointer + 1; + + if ($tokens[$whitespacePointer]['code'] !== T_WHITESPACE) { + $phpcsFile->addError( + 'Expected one space after namespace statement.', + $namespacePointer, + self::CODE_INVALID_WHITESPACE_AFTER_NAMESPACE + ); + return; + } + + if ($tokens[$whitespacePointer]['content'] === ' ') { + return; + } + + $errorMessage = $tokens[$whitespacePointer]['content'][0] === "\t" + ? 'Expected one space after namespace statement, found tab.' + : sprintf('Expected one space after namespace statement, found %d.', strlen($tokens[$whitespacePointer]['content'])); + + $fix = $phpcsFile->addFixableError($errorMessage, $namespacePointer, self::CODE_INVALID_WHITESPACE_AFTER_NAMESPACE); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($whitespacePointer, ' '); + $phpcsFile->fixer->endChangeset(); + } + + private function checkDisallowedContentBetweenNamespaceNameAndSemicolon(File $phpcsFile, int $namespacePointer): void + { + if (array_key_exists('scope_opener', $phpcsFile->getTokens()[$namespacePointer])) { + return; + } + + $namespaceNameStartPointer = TokenHelper::findNextEffective($phpcsFile, $namespacePointer + 1); + $namespaceNameEndPointer = TokenHelper::findNextExcluding( + $phpcsFile, + TokenHelper::getNameTokenCodes(), + $namespaceNameStartPointer + 1 + ) - 1; + + /** @var int $namespaceSemicolonPointer */ + $namespaceSemicolonPointer = TokenHelper::findNextLocal($phpcsFile, T_SEMICOLON, $namespaceNameEndPointer + 1); + + if ($namespaceNameEndPointer + 1 === $namespaceSemicolonPointer) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Disallowed content between namespace name and semicolon.', + $namespacePointer, + self::CODE_DISALLOWED_CONTENT_BETWEEN_NAMESPACE_NAME_AND_SEMICOLON + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $namespaceNameEndPointer, $namespaceSemicolonPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkDisallowedBracketedSyntax(File $phpcsFile, int $namespacePointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('scope_opener', $tokens[$namespacePointer])) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Bracketed syntax for namespaces is disallowed.', + $namespacePointer, + self::CODE_DISALLOWED_BRACKETED_SYNTAX + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($tokens[$namespacePointer]['scope_opener'], ';'); + $phpcsFile->fixer->replaceToken($tokens[$namespacePointer]['scope_closer'], ''); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceSpacingSniff.php new file mode 100644 index 000000000..14229a039 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/NamespaceSpacingSniff.php @@ -0,0 +1,164 @@ + + */ + public function register(): array + { + return [ + T_NAMESPACE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $namespacePointer + */ + public function process(File $phpcsFile, $namespacePointer): void + { + $this->linesCountBeforeNamespace = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeNamespace); + $this->linesCountAfterNamespace = SniffSettingsHelper::normalizeInteger($this->linesCountAfterNamespace); + + $this->checkLinesBeforeNamespace($phpcsFile, $namespacePointer); + $this->checkLinesAfterNamespace($phpcsFile, $namespacePointer); + } + + private function checkLinesBeforeNamespace(File $phpcsFile, int $namespacePointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $pointerBeforeNamespace */ + $pointerBeforeNamespace = TokenHelper::findPreviousNonWhitespace($phpcsFile, $namespacePointer - 1); + + $whitespaceBeforeNamespace = ''; + + $isInlineCommentBefore = (bool) preg_match('~^(?://|#)(.*)~', $tokens[$pointerBeforeNamespace]['content']); + + if ($tokens[$pointerBeforeNamespace]['code'] === T_OPEN_TAG) { + $whitespaceBeforeNamespace .= substr($tokens[$pointerBeforeNamespace]['content'], strlen('eolChar; + } + + if ($pointerBeforeNamespace + 1 !== $namespacePointer) { + $whitespaceBeforeNamespace .= TokenHelper::getContent($phpcsFile, $pointerBeforeNamespace + 1, $namespacePointer - 1); + } + + $actualLinesCountBeforeNamespace = substr_count($whitespaceBeforeNamespace, $phpcsFile->eolChar) - 1; + + if ($actualLinesCountBeforeNamespace === $this->linesCountBeforeNamespace) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s before namespace statement, found %d.', + $this->linesCountBeforeNamespace, + $this->linesCountBeforeNamespace === 1 ? '' : 's', + $actualLinesCountBeforeNamespace + ), + $namespacePointer, + self::CODE_INCORRECT_LINES_COUNT_BEFORE_NAMESPACE + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$pointerBeforeNamespace]['code'] === T_OPEN_TAG) { + $phpcsFile->fixer->replaceToken($pointerBeforeNamespace, 'fixer->replaceToken( + $pointerBeforeNamespace, + rtrim($tokens[$pointerBeforeNamespace]['content'], $phpcsFile->eolChar) + ); + } + + FixerHelper::removeBetween($phpcsFile, $pointerBeforeNamespace, $namespacePointer); + + for ($i = 0; $i <= $this->linesCountBeforeNamespace; $i++) { + $phpcsFile->fixer->addNewline($pointerBeforeNamespace); + } + $phpcsFile->fixer->endChangeset(); + } + + private function checkLinesAfterNamespace(File $phpcsFile, int $namespacePointer): void + { + if (array_key_exists('scope_opener', $phpcsFile->getTokens()[$namespacePointer])) { + return; + } + + /** @var int $namespaceSemicolonPointer */ + $namespaceSemicolonPointer = TokenHelper::findNextLocal($phpcsFile, T_SEMICOLON, $namespacePointer + 1); + + $pointerAfterWhitespaceEnd = TokenHelper::findNextNonWhitespace($phpcsFile, $namespaceSemicolonPointer + 1); + if ($pointerAfterWhitespaceEnd === null) { + return; + } + + $whitespaceAfterNamespace = TokenHelper::getContent($phpcsFile, $namespaceSemicolonPointer + 1, $pointerAfterWhitespaceEnd - 1); + + $actualLinesCountAfterNamespace = substr_count($whitespaceAfterNamespace, $phpcsFile->eolChar) - 1; + + if ($actualLinesCountAfterNamespace === $this->linesCountAfterNamespace) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s after namespace statement, found %d.', + $this->linesCountAfterNamespace, + $this->linesCountAfterNamespace === 1 ? '' : 's', + $actualLinesCountAfterNamespace + ), + $namespacePointer, + self::CODE_INCORRECT_LINES_COUNT_AFTER_NAMESPACE + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $namespaceSemicolonPointer, $pointerAfterWhitespaceEnd); + + for ($i = 0; $i <= $this->linesCountAfterNamespace; $i++) { + $phpcsFile->fixer->addNewline($namespaceSemicolonPointer); + } + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php new file mode 100644 index 000000000..224afd5e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php @@ -0,0 +1,779 @@ + */ + public $specialExceptionNames = []; + + /** @var list */ + public $ignoredNames = []; + + /** @var bool */ + public $allowPartialUses = true; + + /** + * If empty, all namespaces are required to be used + * + * @var list + */ + public $namespacesRequiredToUse = []; + + /** @var bool */ + public $allowFullyQualifiedNameForCollidingClasses = false; + + /** @var bool */ + public $allowFullyQualifiedNameForCollidingFunctions = false; + + /** @var bool */ + public $allowFullyQualifiedNameForCollidingConstants = false; + + /** @var list|null */ + private $normalizedSpecialExceptionNames; + + /** @var list|null */ + private $normalizedIgnoredNames; + + /** @var list|null */ + private $normalizedNamespacesRequiredToUse; + + /** + * @return array + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $references = $this->getReferences($phpcsFile, $openTagPointer); + + $definedClassesIndex = []; + foreach (ClassHelper::getAllNames($phpcsFile) as $definedClassPointer => $definedClassName) { + $definedClassesIndex[strtolower($definedClassName)] = NamespaceHelper::resolveClassName( + $phpcsFile, + $definedClassName, + $definedClassPointer + ); + } + $definedFunctionsIndex = array_flip(array_map(static function (string $functionName): string { + return strtolower($functionName); + }, FunctionHelper::getAllFunctionNames($phpcsFile))); + $definedConstantsIndex = array_flip(ConstantHelper::getAllNames($phpcsFile)); + + $classReferencesIndex = []; + $classReferences = array_filter($references, static function (stdClass $reference): bool { + return $reference->source === self::SOURCE_CODE && $reference->isClass; + }); + + foreach ($classReferences as $classReference) { + $classReferencesIndex[strtolower($classReference->name)] = NamespaceHelper::resolveName( + $phpcsFile, + $classReference->name, + $classReference->type, + $classReference->startPointer + ); + } + + $namespacePointers = NamespaceHelper::getAllNamespacesPointers($phpcsFile); + + $referenceErrors = []; + + foreach ($references as $reference) { + $useStatements = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $reference->startPointer); + + $name = $reference->name; + /** @var int $startPointer */ + $startPointer = $reference->startPointer; + $canonicalName = NamespaceHelper::normalizeToCanonicalName($name); + $unqualifiedName = NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($name); + + if (in_array(strtolower($unqualifiedName), ['true', 'false', 'null'], true)) { + continue; + } + + $collidingUseStatementUniqueId = UseStatement::getUniqueId($reference->type, $unqualifiedName); + + $isPartialUse = false; + foreach ($useStatements as $useStatement) { + $useStatementName = $useStatement->getAlias() ?? $useStatement->getNameAsReferencedInFile(); + if (strpos($name, $useStatementName . '\\') === 0) { + $isPartialUse = true; + break; + } + } + + $isFullyQualified = NamespaceHelper::isFullyQualifiedName($name) + || ($namespacePointers === [] && NamespaceHelper::hasNamespace($name) && !$isPartialUse); + + $isGlobalFallback = !$isFullyQualified + && !NamespaceHelper::hasNamespace($name) + && $namespacePointers !== [] + && !array_key_exists(UseStatement::getUniqueId($reference->type, $name), $useStatements); + + $isGlobalFunctionFallback = false; + if ($reference->isFunction && $isGlobalFallback) { + $isGlobalFunctionFallback = !array_key_exists(strtolower($reference->name), $definedFunctionsIndex) && function_exists( + $reference->name + ); + } + $isGlobalConstantFallback = false; + if ($reference->isConstant && $isGlobalFallback) { + $isGlobalConstantFallback = !array_key_exists($reference->name, $definedConstantsIndex) && defined($reference->name); + } + + if ($isFullyQualified) { + if ($reference->isClass && $this->allowFullyQualifiedNameForCollidingClasses) { + $lowerCasedUnqualifiedClassName = strtolower($unqualifiedName); + if ( + array_key_exists($lowerCasedUnqualifiedClassName, $definedClassesIndex) + && $canonicalName !== NamespaceHelper::normalizeToCanonicalName( + $definedClassesIndex[$lowerCasedUnqualifiedClassName] + ) + ) { + continue; + } + + if ( + array_key_exists($lowerCasedUnqualifiedClassName, $classReferencesIndex) + && $name !== $classReferencesIndex[$lowerCasedUnqualifiedClassName] + ) { + continue; + } + + if ( + array_key_exists($collidingUseStatementUniqueId, $useStatements) + && $canonicalName !== NamespaceHelper::normalizeToCanonicalName( + $useStatements[$collidingUseStatementUniqueId]->getFullyQualifiedTypeName() + ) + ) { + continue; + } + } elseif ($reference->isFunction && $this->allowFullyQualifiedNameForCollidingFunctions) { + $lowerCasedUnqualifiedFunctionName = strtolower($unqualifiedName); + if (array_key_exists($lowerCasedUnqualifiedFunctionName, $definedFunctionsIndex)) { + continue; + } + + if ( + array_key_exists($collidingUseStatementUniqueId, $useStatements) + && $canonicalName !== NamespaceHelper::normalizeToCanonicalName( + $useStatements[$collidingUseStatementUniqueId]->getFullyQualifiedTypeName() + ) + ) { + continue; + } + } elseif ($reference->isConstant && $this->allowFullyQualifiedNameForCollidingConstants) { + if (array_key_exists($unqualifiedName, $definedConstantsIndex)) { + continue; + } + + if ( + array_key_exists($collidingUseStatementUniqueId, $useStatements) + && $canonicalName !== NamespaceHelper::normalizeToCanonicalName( + $useStatements[$collidingUseStatementUniqueId]->getFullyQualifiedTypeName() + ) + ) { + continue; + } + } + } + + if ($isFullyQualified || $isGlobalFunctionFallback || $isGlobalConstantFallback) { + if ($isFullyQualified && !$this->isRequiredToBeUsed($name)) { + continue; + } + + $isExceptionByName = StringHelper::endsWith($name, 'Exception') + || $name === '\Throwable' + || (StringHelper::endsWith($name, 'Error') && !NamespaceHelper::hasNamespace($name)) + || in_array($canonicalName, $this->getSpecialExceptionNames(), true); + $inIgnoredNames = in_array($canonicalName, $this->getIgnoredNames(), true); + + if ($isExceptionByName && !$inIgnoredNames && $this->allowFullyQualifiedExceptions) { + continue; + } + + if ( + $isFullyQualified + && !NamespaceHelper::hasNamespace($name) + && $namespacePointers === [] + ) { + $label = sprintf( + $reference->isConstant ? 'Constant %s' : ($reference->isFunction ? 'Function %s()' : 'Class %s'), + $name + ); + + $fix = $phpcsFile->addFixableError(sprintf( + '%s should not be referenced via a fully qualified name, but via an unqualified name without the leading \\, because the file does not have a namespace and the type cannot be put in a use statement.', + $label + ), $startPointer, self::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME_WITHOUT_NAMESPACE); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + if ($reference->source === self::SOURCE_ANNOTATION) { + $fixedDocComment = AnnotationHelper::fixAnnotation( + $reference->parsedDocComment, + $reference->annotation, + $reference->nameNode, + new IdentifierTypeNode(substr($reference->name, 1)) + ); + + FixerHelper::change( + $phpcsFile, + $reference->parsedDocComment->getOpenPointer(), + $reference->parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + } elseif ($reference->source === self::SOURCE_ANNOTATION_CONSTANT_FETCH) { + $fixedDocComment = AnnotationHelper::fixAnnotation( + $reference->parsedDocComment, + $reference->annotation, + $reference->constantFetchNode, + new ConstFetchNode(substr($reference->name, 1), $reference->constantFetchNode->name) + ); + + FixerHelper::change( + $phpcsFile, + $reference->parsedDocComment->getOpenPointer(), + $reference->parsedDocComment->getClosePointer(), + $fixedDocComment + ); + } else { + $phpcsFile->fixer->replaceToken($startPointer, substr($tokens[$startPointer]['content'], 1)); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $shouldBeUsed = NamespaceHelper::hasNamespace($name); + if (!$shouldBeUsed) { + if ($reference->isFunction) { + $shouldBeUsed = $isFullyQualified + ? !$this->allowFullyQualifiedGlobalFunctions + : !$this->allowFallbackGlobalFunctions; + } elseif ($reference->isConstant) { + $shouldBeUsed = $isFullyQualified + ? !$this->allowFullyQualifiedGlobalConstants + : !$this->allowFallbackGlobalConstants; + } else { + $shouldBeUsed = !$this->allowFullyQualifiedGlobalClasses; + } + } + + if (!$shouldBeUsed) { + continue; + } + + $referenceErrors[] = (object) [ + 'reference' => $reference, + 'canonicalName' => $canonicalName, + 'isGlobalConstantFallback' => $isGlobalConstantFallback, + 'isGlobalFunctionFallback' => $isGlobalFunctionFallback, + ]; + } + } elseif (!$this->allowPartialUses) { + if (NamespaceHelper::isQualifiedName($name)) { + $phpcsFile->addError(sprintf( + 'Partial use statements are not allowed, but referencing %s found.', + $name + ), $startPointer, self::CODE_PARTIAL_USE); + } + } + } + + if (count($referenceErrors) === 0) { + return; + } + + $alreadyAddedUses = [ + UseStatement::TYPE_CLASS => [], + UseStatement::TYPE_FUNCTION => [], + UseStatement::TYPE_CONSTANT => [], + ]; + + $phpcsFile->fixer->beginChangeset(); + + foreach ($referenceErrors as $referenceData) { + $reference = $referenceData->reference; + /** @var int $startPointer */ + $startPointer = $reference->startPointer; + $canonicalName = $referenceData->canonicalName; + $nameToReference = NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($reference->name); + $canonicalNameToReference = $reference->isConstant ? $nameToReference : strtolower($nameToReference); + $isGlobalConstantFallback = $referenceData->isGlobalConstantFallback; + $isGlobalFunctionFallback = $referenceData->isGlobalFunctionFallback; + + $useStatements = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $reference->startPointer); + + $canBeFixed = array_reduce( + $alreadyAddedUses[$reference->type], + static function (bool $carry, string $use) use ($canonicalName): bool { + $useLastName = strtolower(NamespaceHelper::getLastNamePart($use)); + $canonicalLastName = strtolower(NamespaceHelper::getLastNamePart($canonicalName)); + return $useLastName === $canonicalLastName ? false : $carry; + }, + true + ); + + if ( + ( + $reference->isClass + && array_key_exists($canonicalNameToReference, $definedClassesIndex) + && $canonicalName !== NamespaceHelper::normalizeToCanonicalName($definedClassesIndex[$canonicalNameToReference]) + ) + || ( + $reference->isClass + && array_key_exists($canonicalNameToReference, $classReferencesIndex) + && $canonicalName !== NamespaceHelper::normalizeToCanonicalName($classReferencesIndex[$canonicalNameToReference]) + ) + || ($reference->isFunction && array_key_exists($canonicalNameToReference, $definedFunctionsIndex)) + || ($reference->isConstant && array_key_exists($canonicalNameToReference, $definedConstantsIndex)) + ) { + $canBeFixed = false; + } + + foreach ($useStatements as $useStatement) { + if ($useStatement->getType() !== $reference->type) { + continue; + } + + if ($useStatement->getFullyQualifiedTypeName() === $canonicalName) { + continue; + } + + if ($useStatement->getCanonicalNameAsReferencedInFile() !== $canonicalNameToReference) { + continue; + } + + $canBeFixed = false; + break; + } + + $label = sprintf( + $reference->isConstant + ? 'Constant %s' + : ($reference->isFunction ? 'Function %s()' : 'Class %s'), + $reference->name + ); + $errorCode = $isGlobalConstantFallback || $isGlobalFunctionFallback + ? self::CODE_REFERENCE_VIA_FALLBACK_GLOBAL_NAME + : self::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME; + $errorMessage = $isGlobalConstantFallback || $isGlobalFunctionFallback + ? sprintf('%s should not be referenced via a fallback global name, but via a use statement.', $label) + : sprintf('%s should not be referenced via a fully qualified name, but via a use statement.', $label); + + if (!$canBeFixed) { + $phpcsFile->addError($errorMessage, $startPointer, $errorCode); + continue; + } + + $fix = $phpcsFile->addFixableError($errorMessage, $startPointer, $errorCode); + + if (!$fix) { + continue; + } + + $addUse = !in_array($canonicalName, $alreadyAddedUses[$reference->type], true); + + if ( + $reference->isClass + && array_key_exists($canonicalNameToReference, $definedClassesIndex) + ) { + $addUse = false; + } + + foreach ($useStatements as $useStatement) { + if ( + $useStatement->getType() !== $reference->type + || $useStatement->getFullyQualifiedTypeName() !== $canonicalName + ) { + continue; + } + + $nameToReference = $useStatement->getNameAsReferencedInFile(); + $addUse = false; + // Lock the use statement, so it is not modified by other sniffs + $phpcsFile->fixer->replaceToken( + $useStatement->getPointer(), + $phpcsFile->fixer->getTokenContent($useStatement->getPointer()) + ); + break; + } + + if ($addUse) { + $useStatementPlacePointer = $this->getUseStatementPlacePointer($phpcsFile, $openTagPointer, $useStatements); + $useTypeName = UseStatement::getTypeName($reference->type); + $useTypeFormatted = $useTypeName !== null ? sprintf('%s ', $useTypeName) : ''; + + $phpcsFile->fixer->addNewline($useStatementPlacePointer); + $phpcsFile->fixer->addContent($useStatementPlacePointer, sprintf('use %s%s;', $useTypeFormatted, $canonicalName)); + + $alreadyAddedUses[$reference->type][] = $canonicalName; + } + + if ($reference->source === self::SOURCE_ANNOTATION) { + $fixedDocComment = AnnotationHelper::fixAnnotation( + $reference->parsedDocComment, + $reference->annotation, + $reference->nameNode, + new IdentifierTypeNode($nameToReference) + ); + + FixerHelper::change( + $phpcsFile, + $reference->parsedDocComment->getOpenPointer(), + $reference->parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + } elseif ($reference->source === self::SOURCE_ANNOTATION_CONSTANT_FETCH) { + $fixedDocComment = AnnotationHelper::fixAnnotation( + $reference->parsedDocComment, + $reference->annotation, + $reference->constantFetchNode, + new ConstFetchNode($nameToReference, $reference->constantFetchNode->name) + ); + + FixerHelper::change( + $phpcsFile, + $reference->parsedDocComment->getOpenPointer(), + $reference->parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + } elseif ($reference->source === self::SOURCE_ATTRIBUTE) { + $attributeContent = TokenHelper::getContent($phpcsFile, $startPointer, $reference->endPointer); + $fixedAttributeContent = preg_replace( + '~(?<=\W)' . preg_quote($reference->name, '~') . '(?=\W)~', + $nameToReference, + $attributeContent + ); + FixerHelper::change($phpcsFile, $startPointer, $reference->endPointer, $fixedAttributeContent); + } else { + FixerHelper::change($phpcsFile, $startPointer, $reference->endPointer, $nameToReference); + } + } + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @return list + */ + private function getSpecialExceptionNames(): array + { + if ($this->normalizedSpecialExceptionNames === null) { + $this->normalizedSpecialExceptionNames = SniffSettingsHelper::normalizeArray($this->specialExceptionNames); + } + + return $this->normalizedSpecialExceptionNames; + } + + /** + * @return list + */ + private function getIgnoredNames(): array + { + if ($this->normalizedIgnoredNames === null) { + $this->normalizedIgnoredNames = SniffSettingsHelper::normalizeArray($this->ignoredNames); + } + + return $this->normalizedIgnoredNames; + } + + /** + * @return list + */ + private function getNamespacesRequiredToUse(): array + { + if ($this->normalizedNamespacesRequiredToUse === null) { + $this->normalizedNamespacesRequiredToUse = SniffSettingsHelper::normalizeArray($this->namespacesRequiredToUse); + } + + return $this->normalizedNamespacesRequiredToUse; + } + + /** + * @param array $useStatements + */ + private function getUseStatementPlacePointer(File $phpcsFile, int $openTagPointer, array $useStatements): int + { + if (count($useStatements) !== 0) { + $lastUseStatement = array_values($useStatements)[count($useStatements) - 1]; + /** @var int $useStatementPlacePointer */ + $useStatementPlacePointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $lastUseStatement->getPointer() + 1); + return $useStatementPlacePointer; + } + + $namespacePointer = TokenHelper::findNext($phpcsFile, T_NAMESPACE, $openTagPointer + 1); + if ($namespacePointer !== null) { + /** @var int $useStatementPlacePointer */ + $useStatementPlacePointer = TokenHelper::findNext($phpcsFile, [T_SEMICOLON, T_OPEN_CURLY_BRACKET], $namespacePointer + 1); + return $useStatementPlacePointer; + } + + $tokens = $phpcsFile->getTokens(); + + $useStatementPlacePointer = $openTagPointer; + + $nonWhitespacePointerAfterOpenTag = TokenHelper::findNextNonWhitespace($phpcsFile, $openTagPointer + 1); + if (in_array($tokens[$nonWhitespacePointerAfterOpenTag]['code'], Tokens::$commentTokens, true)) { + $commentEndPointer = CommentHelper::getCommentEndPointer($phpcsFile, $nonWhitespacePointerAfterOpenTag); + + if (StringHelper::endsWith($tokens[$commentEndPointer]['content'], $phpcsFile->eolChar)) { + $useStatementPlacePointer = $commentEndPointer; + } else { + $newLineAfterComment = $commentEndPointer + 1; + + if (array_key_exists($newLineAfterComment, $tokens) && $tokens[$newLineAfterComment]['content'] === $phpcsFile->eolChar) { + $pointerAfterCommentEnd = TokenHelper::findNextNonWhitespace($phpcsFile, $newLineAfterComment + 1); + + if (TokenHelper::findNextContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $newLineAfterComment + 1, + $pointerAfterCommentEnd + ) !== null) { + $useStatementPlacePointer = $commentEndPointer; + } + } + } + } + + $pointerAfter = TokenHelper::findNextEffective($phpcsFile, $useStatementPlacePointer + 1); + if ($tokens[$pointerAfter]['code'] === T_DECLARE) { + return TokenHelper::findNext($phpcsFile, T_SEMICOLON, $pointerAfter + 1); + } + + return $useStatementPlacePointer; + } + + private function isRequiredToBeUsed(string $name): bool + { + if ($this->namespacesRequiredToUse === null || $this->namespacesRequiredToUse === []) { + return true; + } + + foreach ($this->getNamespacesRequiredToUse() as $namespace) { + if (!NamespaceHelper::isTypeInNamespace($name, $namespace)) { + continue; + } + + return true; + } + + return false; + } + + /** + * @return list + */ + private function getReferences(File $phpcsFile, int $openTagPointer): array + { + $tokens = $phpcsFile->getTokens(); + + $references = []; + foreach (ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer) as $referencedName) { + $reference = new stdClass(); + $reference->source = self::SOURCE_CODE; + $reference->name = $referencedName->getNameAsReferencedInFile(); + $reference->type = $referencedName->getType(); + $reference->startPointer = $referencedName->getStartPointer(); + $reference->endPointer = $referencedName->getEndPointer(); + $reference->isClass = $referencedName->isClass(); + $reference->isConstant = $referencedName->isConstant(); + $reference->isFunction = $referencedName->isFunction(); + + $references[] = $reference; + } + + foreach (ReferencedNameHelper::getAllReferencedNamesInAttributes($phpcsFile, $openTagPointer) as $referencedName) { + $reference = new stdClass(); + $reference->source = self::SOURCE_ATTRIBUTE; + $reference->name = $referencedName->getNameAsReferencedInFile(); + $reference->type = $referencedName->getType(); + $reference->startPointer = $referencedName->getStartPointer(); + $reference->endPointer = $referencedName->getEndPointer(); + $reference->isClass = $referencedName->isClass(); + $reference->isConstant = $referencedName->isConstant(); + $reference->isFunction = $referencedName->isFunction(); + + $references[] = $reference; + } + + if (!$this->searchAnnotations) { + return $references; + } + + $searchAnnotationsPointer = $openTagPointer + 1; + while (true) { + $docCommentOpenPointer = TokenHelper::findNext($phpcsFile, T_DOC_COMMENT_OPEN_TAG, $searchAnnotationsPointer); + if ($docCommentOpenPointer === null) { + break; + } + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + if ($parsedDocComment !== null) { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach ($annotations as $annotation) { + /** @var list $identifierTypeNodes */ + $identifierTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), IdentifierTypeNode::class); + + foreach ($identifierTypeNodes as $typeHintNode) { + $typeHint = $typeHintNode->name; + + $lowercasedTypeHint = strtolower($typeHint); + if ( + TypeHintHelper::isSimpleTypeHint($lowercasedTypeHint) + || TypeHintHelper::isSimpleUnofficialTypeHints($lowercasedTypeHint) + || !TypeHelper::isTypeName($typeHint) + ) { + continue; + } + + $reference = new stdClass(); + $reference->source = self::SOURCE_ANNOTATION; + $reference->parsedDocComment = $parsedDocComment; + $reference->annotation = $annotation; + $reference->nameNode = $typeHintNode; + $reference->name = $typeHint; + $reference->type = ReferencedName::TYPE_CLASS; + $reference->startPointer = $annotation->getStartPointer(); + $reference->endPointer = null; + $reference->isClass = true; + $reference->isConstant = false; + $reference->isFunction = false; + + $references[] = $reference; + } + + /** @var list $constantFetchNodes */ + $constantFetchNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), ConstFetchNode::class); + + foreach ($constantFetchNodes as $constantFetchNode) { + $reference = new stdClass(); + $reference->source = self::SOURCE_ANNOTATION_CONSTANT_FETCH; + $reference->parsedDocComment = $parsedDocComment; + $reference->annotation = $annotation; + $reference->constantFetchNode = $constantFetchNode; + $reference->name = $constantFetchNode->className; + $reference->type = ReferencedName::TYPE_CLASS; + $reference->startPointer = $annotation->getStartPointer(); + $reference->endPointer = null; + $reference->isClass = true; + $reference->isConstant = false; + $reference->isFunction = false; + + $references[] = $reference; + } + } + } + + $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1; + } + + return $references; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/RequireOneNamespaceInFileSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/RequireOneNamespaceInFileSniff.php new file mode 100644 index 000000000..8b9730242 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/RequireOneNamespaceInFileSniff.php @@ -0,0 +1,58 @@ + + */ + public function register(): array + { + return [ + T_NAMESPACE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $namespacePointer + */ + public function process(File $phpcsFile, $namespacePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $pointerAfterNamespace = TokenHelper::findNextEffective($phpcsFile, $namespacePointer + 1); + if ($tokens[$pointerAfterNamespace]['code'] === T_NS_SEPARATOR) { + return; + } + + $previousNamespacePointer = $namespacePointer; + do { + $previousNamespacePointer = TokenHelper::findPrevious($phpcsFile, T_NAMESPACE, $previousNamespacePointer - 1); + if ($previousNamespacePointer === null) { + return; + } + + $pointerAfterPreviousNamespace = TokenHelper::findNextEffective($phpcsFile, $previousNamespacePointer + 1); + if ($tokens[$pointerAfterPreviousNamespace]['code'] === T_NS_SEPARATOR) { + continue; + } + + break; + + } while (true); + + $phpcsFile->addError('Only one namespace in a file is allowed.', $namespacePointer, self::CODE_MORE_NAMESPACES_IN_FILE); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php new file mode 100644 index 000000000..9dfb68f40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php @@ -0,0 +1,294 @@ + */ + public $ignoredAnnotationNames = []; + + /** @var list */ + public $ignoredAnnotations = []; + + /** @var list|null */ + private $normalizedIgnoredAnnotationNames; + + /** @var list|null */ + private $normalizedIgnoredAnnotations; + + /** + * @return array + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $startPointer = TokenHelper::findPrevious($phpcsFile, T_NAMESPACE, $openTagPointer - 1) ?? $openTagPointer; + + $fileUnusedNames = UseStatementHelper::getFileUseStatements($phpcsFile); + $referencedNamesInCode = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $startPointer); + $referencedNamesInAttributes = ReferencedNameHelper::getAllReferencedNamesInAttributes($phpcsFile, $startPointer); + + $pointersBeforeUseStatements = array_reverse(NamespaceHelper::getAllNamespacesPointers($phpcsFile)); + + $allUsedNames = []; + + foreach ([$referencedNamesInCode, $referencedNamesInAttributes] as $referencedNames) { + foreach ($referencedNames as $referencedName) { + $pointer = $referencedName->getStartPointer(); + + $pointerBeforeUseStatements = $this->firstPointerBefore($pointer, $pointersBeforeUseStatements, $startPointer); + + $name = $referencedName->getNameAsReferencedInFile(); + $nameParts = NamespaceHelper::getNameParts($name); + $nameAsReferencedInFile = $nameParts[0]; + $nameReferencedWithoutSubNamespace = count($nameParts) === 1; + $uniqueId = $nameReferencedWithoutSubNamespace + ? UseStatement::getUniqueId($referencedName->getType(), $nameAsReferencedInFile) + : UseStatement::getUniqueId(ReferencedName::TYPE_CLASS, $nameAsReferencedInFile); + if ( + NamespaceHelper::isFullyQualifiedName($name) + || !array_key_exists($pointerBeforeUseStatements, $fileUnusedNames) + || !array_key_exists($uniqueId, $fileUnusedNames[$pointerBeforeUseStatements]) + ) { + continue; + } + + $allUsedNames[$pointerBeforeUseStatements][$uniqueId] = true; + } + } + + if ($this->searchAnnotations) { + $tokens = $phpcsFile->getTokens(); + $searchAnnotationsPointer = $startPointer + 1; + while (true) { + $docCommentOpenPointer = TokenHelper::findNext($phpcsFile, T_DOC_COMMENT_OPEN_TAG, $searchAnnotationsPointer); + if ($docCommentOpenPointer === null) { + break; + } + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + if ($annotations === []) { + $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1; + continue; + } + + $pointerBeforeUseStatements = $this->firstPointerBefore( + $docCommentOpenPointer - 1, + $pointersBeforeUseStatements, + $startPointer + ); + + if (!array_key_exists($pointerBeforeUseStatements, $fileUnusedNames)) { + $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1; + continue; + } + + foreach ($fileUnusedNames[$pointerBeforeUseStatements] as $useStatement) { + if (!$useStatement->isClass()) { + continue; + } + + $nameAsReferencedInFile = $useStatement->getNameAsReferencedInFile(); + $uniqueId = UseStatement::getUniqueId($useStatement->getType(), $nameAsReferencedInFile); + + foreach ($annotations as $annotation) { + if (in_array($annotation->getName(), $this->getIgnoredAnnotations(), true)) { + continue; + } + + if ($annotation->isInvalid()) { + continue; + } + + $contentsToCheck = []; + + if ($annotation->getValue() instanceof GenericTagValueNode) { + $contentsToCheck[] = $annotation->getName(); + $contentsToCheck[] = $annotation->getValue()->value; + } else { + /** @var list $identifierTypeNodes */ + $identifierTypeNodes = AnnotationHelper::getAnnotationNodesByType( + $annotation->getNode(), + IdentifierTypeNode::class + ); + /** @var list $doctrineAnnotations */ + $doctrineAnnotations = AnnotationHelper::getAnnotationNodesByType( + $annotation->getNode(), + DoctrineAnnotation::class + ); + /** @var list $constFetchNodes */ + $constFetchNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), ConstFetchNode::class); + + $contentsToCheck = array_filter(array_merge( + $contentsToCheck, + array_map(static function (IdentifierTypeNode $identifierTypeNode): ?string { + if ( + TypeHintHelper::isSimpleTypeHint($identifierTypeNode->name) + || TypeHintHelper::isSimpleUnofficialTypeHints($identifierTypeNode->name) + || !TypeHelper::isTypeName($identifierTypeNode->name) + ) { + return null; + } + + return $identifierTypeNode->name; + }, $identifierTypeNodes), + array_map(function (DoctrineAnnotation $doctrineAnnotation): ?string { + if (in_array($doctrineAnnotation->name, $this->getIgnoredAnnotationNames(), true)) { + return null; + } + + return $doctrineAnnotation->name; + }, $doctrineAnnotations), + array_map(static function (ConstFetchNode $constFetchNode): string { + return $constFetchNode->className; + }, $constFetchNodes) + )); + } + + foreach ($contentsToCheck as $contentToCheck) { + if (preg_match( + '~(?<=^|[^a-z\\\\])(' . preg_quote($nameAsReferencedInFile, '~') . ')(?=\\s|::|\\\\|\||\[|$)~im', + $contentToCheck + ) === 0) { + continue; + } + + $allUsedNames[$pointerBeforeUseStatements][$uniqueId] = true; + } + } + } + + $searchAnnotationsPointer = $tokens[$docCommentOpenPointer]['comment_closer'] + 1; + } + } + + foreach ($fileUnusedNames as $pointerBeforeUnusedNames => $unusedNames) { + $usedNames = $allUsedNames[$pointerBeforeUnusedNames] ?? []; + foreach (array_diff_key($unusedNames, $usedNames) as $unusedUse) { + $fullName = $unusedUse->getFullyQualifiedTypeName(); + if ( + $unusedUse->getNameAsReferencedInFile() !== $fullName + && $unusedUse->getNameAsReferencedInFile() !== NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($fullName) + ) { + $fullName .= sprintf(' (as %s)', $unusedUse->getNameAsReferencedInFile()); + } + $fix = $phpcsFile->addFixableError(sprintf( + 'Type %s is not used in this file.', + $fullName + ), $unusedUse->getPointer(), self::CODE_UNUSED_USE); + if (!$fix) { + continue; + } + + $endPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $unusedUse->getPointer()) + 1; + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $unusedUse->getPointer(), $endPointer); + + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** + * @return list + */ + private function getIgnoredAnnotationNames(): array + { + if ($this->normalizedIgnoredAnnotationNames === null) { + $this->normalizedIgnoredAnnotationNames = array_merge( + SniffSettingsHelper::normalizeArray($this->ignoredAnnotationNames), + [ + '@param', + '@throws', + '@property', + '@method', + ] + ); + } + + return $this->normalizedIgnoredAnnotationNames; + } + + /** + * @return list + */ + private function getIgnoredAnnotations(): array + { + if ($this->normalizedIgnoredAnnotations === null) { + $this->normalizedIgnoredAnnotations = SniffSettingsHelper::normalizeArray($this->ignoredAnnotations); + } + + return $this->normalizedIgnoredAnnotations; + } + + /** + * @param list $pointersBeforeUseStatements + */ + private function firstPointerBefore(int $pointer, array $pointersBeforeUseStatements, int $startPointer): int + { + foreach ($pointersBeforeUseStatements as $pointerBeforeUseStatements) { + if ($pointerBeforeUseStatements < $pointer) { + return $pointerBeforeUseStatements; + } + } + + return $startPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php new file mode 100644 index 000000000..631386273 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php @@ -0,0 +1,74 @@ + + */ + public function register(): array + { + return [ + T_USE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $usePointer + */ + public function process(File $phpcsFile, $usePointer): void + { + if (!UseStatementHelper::isImportUse($phpcsFile, $usePointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + /** @var int $nextTokenPointer */ + $nextTokenPointer = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + + if ( + in_array($tokens[$nextTokenPointer]['code'], TokenHelper::getOnlyNameTokenCodes(), true) + && ( + $tokens[$nextTokenPointer]['content'] === 'function' + || $tokens[$nextTokenPointer]['content'] === 'const' + ) + ) { + /** @var int $nextTokenPointer */ + $nextTokenPointer = TokenHelper::findNextEffective($phpcsFile, $nextTokenPointer + 1); + } + + if (!NamespaceHelper::isFullyQualifiedPointer($phpcsFile, $nextTokenPointer)) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use statement cannot start with a backslash.', + $nextTokenPointer, + self::CODE_STARTS_WITH_BACKSLASH + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($nextTokenPointer, ltrim($tokens[$nextTokenPointer]['content'], '\\')); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseFromSameNamespaceSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseFromSameNamespaceSniff.php new file mode 100644 index 000000000..224876a2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseFromSameNamespaceSniff.php @@ -0,0 +1,90 @@ + + */ + public function register(): array + { + return [ + T_USE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $usePointer + */ + public function process(File $phpcsFile, $usePointer): void + { + if (!UseStatementHelper::isImportUse($phpcsFile, $usePointer)) { + return; + } + + $namespaceName = NamespaceHelper::findCurrentNamespaceName($phpcsFile, $usePointer); + if ($namespaceName === null) { + $namespaceName = ''; + } + + $usedTypeName = UseStatementHelper::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer); + if (!StringHelper::startsWith($usedTypeName, $namespaceName)) { + return; + } + + $asPointer = $this->findAsPointer($phpcsFile, $usePointer); + if ($asPointer !== null) { + return; + } + + $usedTypeNameRest = substr($usedTypeName, strlen($namespaceName)); + if (!NamespaceHelper::isFullyQualifiedName($usedTypeNameRest) && $namespaceName !== '') { + return; + } + + if (NamespaceHelper::hasNamespace($usedTypeNameRest)) { + return; + } + + $fix = $phpcsFile->addFixableError(sprintf( + 'Use %s is from the same namespace – that is prohibited.', + $usedTypeName + ), $usePointer, self::CODE_USE_FROM_SAME_NAMESPACE); + if (!$fix) { + return; + } + + $endPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $usePointer) + 1; + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $usePointer, $endPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function findAsPointer(File $phpcsFile, int $startPointer): ?int + { + return TokenHelper::findNextLocal($phpcsFile, T_AS, $startPointer); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseOnlyWhitelistedNamespacesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseOnlyWhitelistedNamespacesSniff.php new file mode 100644 index 000000000..dbdb4710d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseOnlyWhitelistedNamespacesSniff.php @@ -0,0 +1,78 @@ + */ + public $namespacesRequiredToUse = []; + + /** @var list|null */ + private $normalizedNamespacesRequiredToUse; + + /** + * @return array + */ + public function register(): array + { + return [ + T_USE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $usePointer + */ + public function process(File $phpcsFile, $usePointer): void + { + if (!UseStatementHelper::isImportUse($phpcsFile, $usePointer)) { + return; + } + + $className = UseStatementHelper::getFullyQualifiedTypeNameFromUse($phpcsFile, $usePointer); + if ($this->allowUseFromRootNamespace && !NamespaceHelper::isQualifiedName($className)) { + return; + } + + foreach ($this->getNamespacesRequiredToUse() as $namespace) { + if (!NamespaceHelper::isTypeInNamespace($className, $namespace)) { + continue; + } + + return; + } + + $phpcsFile->addError(sprintf( + 'Type %s should not be used, but referenced via a fully qualified name.', + $className + ), $usePointer, self::CODE_NON_FULLY_QUALIFIED); + } + + /** + * @return list + */ + private function getNamespacesRequiredToUse(): array + { + if ($this->normalizedNamespacesRequiredToUse === null) { + $this->normalizedNamespacesRequiredToUse = SniffSettingsHelper::normalizeArray($this->namespacesRequiredToUse); + } + + return $this->normalizedNamespacesRequiredToUse; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseSpacingSniff.php new file mode 100644 index 000000000..ca0808a47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseSpacingSniff.php @@ -0,0 +1,343 @@ + + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + $this->linesCountBeforeFirstUse = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeFirstUse); + $this->linesCountBetweenUseTypes = SniffSettingsHelper::normalizeInteger($this->linesCountBetweenUseTypes); + $this->linesCountAfterLastUse = SniffSettingsHelper::normalizeInteger($this->linesCountAfterLastUse); + + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $fileUseStatements = UseStatementHelper::getFileUseStatements($phpcsFile); + + if (count($fileUseStatements) === 0) { + return; + } + + foreach ($fileUseStatements as $useStatementsByName) { + $useStatements = array_values($useStatementsByName); + + $this->checkLinesBeforeFirstUse($phpcsFile, $useStatements[0]); + $this->checkLinesAfterLastUse($phpcsFile, $useStatements[count($useStatements) - 1]); + $this->checkLinesBetweenSameTypesOfUse($phpcsFile, $useStatements); + $this->checkLinesBetweenDifferentTypesOfUse($phpcsFile, $useStatements); + } + } + + private function checkLinesBeforeFirstUse(File $phpcsFile, UseStatement $firstUse): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $pointerBeforeFirstUse */ + $pointerBeforeFirstUse = TokenHelper::findPreviousNonWhitespace($phpcsFile, $firstUse->getPointer() - 1); + $useStartPointer = $firstUse->getPointer(); + + if ( + in_array($tokens[$pointerBeforeFirstUse]['code'], Tokens::$commentTokens, true) + && $tokens[$pointerBeforeFirstUse]['line'] + 1 === $tokens[$useStartPointer]['line'] + ) { + $useStartPointer = array_key_exists('comment_opener', $tokens[$pointerBeforeFirstUse]) + ? $tokens[$pointerBeforeFirstUse]['comment_opener'] + : CommentHelper::getMultilineCommentStartPointer($phpcsFile, $pointerBeforeFirstUse); + /** @var int $pointerBeforeFirstUse */ + $pointerBeforeFirstUse = TokenHelper::findPreviousNonWhitespace($phpcsFile, $useStartPointer - 1); + } + + $actualLinesCountBeforeFirstUse = $tokens[$useStartPointer]['line'] - $tokens[$pointerBeforeFirstUse]['line'] - 1; + + if ($actualLinesCountBeforeFirstUse === $this->linesCountBeforeFirstUse) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s before first use statement, found %d.', + $this->linesCountBeforeFirstUse, + $this->linesCountBeforeFirstUse === 1 ? '' : 's', + $actualLinesCountBeforeFirstUse + ), + $firstUse->getPointer(), + self::CODE_INCORRECT_LINES_COUNT_BEFORE_FIRST_USE + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$pointerBeforeFirstUse]['code'] === T_OPEN_TAG) { + $phpcsFile->fixer->replaceToken($pointerBeforeFirstUse, 'linesCountBeforeFirstUse; $i++) { + $phpcsFile->fixer->addNewline($pointerBeforeFirstUse); + } + $phpcsFile->fixer->endChangeset(); + } + + private function checkLinesAfterLastUse(File $phpcsFile, UseStatement $lastUse): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $useEndPointer */ + $useEndPointer = TokenHelper::findNextLocal($phpcsFile, T_SEMICOLON, $lastUse->getPointer() + 1); + + $pointerAfterWhitespaceEnd = TokenHelper::findNextNonWhitespace($phpcsFile, $useEndPointer + 1); + if ($pointerAfterWhitespaceEnd === null) { + return; + } + + if ( + in_array($tokens[$pointerAfterWhitespaceEnd]['code'], Tokens::$commentTokens, true) + && $tokens[$pointerAfterWhitespaceEnd]['code'] !== T_DOC_COMMENT_OPEN_TAG + && ( + $tokens[$useEndPointer]['line'] === $tokens[$pointerAfterWhitespaceEnd]['line'] + || $tokens[$useEndPointer]['line'] + 1 === $tokens[$pointerAfterWhitespaceEnd]['line'] + ) + ) { + $useEndPointer = CommentHelper::getMultilineCommentEndPointer($phpcsFile, $pointerAfterWhitespaceEnd); + /** @var int $pointerAfterWhitespaceEnd */ + $pointerAfterWhitespaceEnd = TokenHelper::findNextNonWhitespace($phpcsFile, $useEndPointer + 1); + } + + $actualLinesCountAfterLastUse = $tokens[$pointerAfterWhitespaceEnd]['line'] - $tokens[$useEndPointer]['line'] - 1; + + if ($actualLinesCountAfterLastUse === $this->linesCountAfterLastUse) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s after last use statement, found %d.', + $this->linesCountAfterLastUse, + $this->linesCountAfterLastUse === 1 ? '' : 's', + $actualLinesCountAfterLastUse + ), + $lastUse->getPointer(), + self::CODE_INCORRECT_LINES_COUNT_AFTER_LAST_USE + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $useEndPointer, $pointerAfterWhitespaceEnd); + + $linesToAdd = $this->linesCountAfterLastUse; + if (CommentHelper::isLineComment($phpcsFile, $useEndPointer)) { + $linesToAdd--; + } + + for ($i = 0; $i <= $linesToAdd; $i++) { + $phpcsFile->fixer->addNewline($useEndPointer); + } + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $useStatements + */ + private function checkLinesBetweenSameTypesOfUse(File $phpcsFile, array $useStatements): void + { + if (count($useStatements) === 1) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $requiredLinesCountBetweenUses = 0; + + $previousUse = null; + foreach ($useStatements as $use) { + if ($previousUse === null) { + $previousUse = $use; + continue; + } + + if (!$use->hasSameType($previousUse)) { + $previousUse = null; + continue; + } + + /** @var int $pointerBeforeUse */ + $pointerBeforeUse = TokenHelper::findPreviousNonWhitespace($phpcsFile, $use->getPointer() - 1); + $useStartPointer = $use->getPointer(); + + if ( + in_array($tokens[$pointerBeforeUse]['code'], Tokens::$commentTokens, true) + && TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $pointerBeforeUse) === $pointerBeforeUse + && $tokens[$pointerBeforeUse]['line'] + 1 === $tokens[$useStartPointer]['line'] + ) { + $useStartPointer = array_key_exists('comment_opener', $tokens[$pointerBeforeUse]) + ? $tokens[$pointerBeforeUse]['comment_opener'] + : CommentHelper::getMultilineCommentStartPointer($phpcsFile, $pointerBeforeUse); + } + + $actualLinesCountAfterPreviousUse = $tokens[$useStartPointer]['line'] - $tokens[$previousUse->getPointer()]['line'] - 1; + + if ($actualLinesCountAfterPreviousUse === $requiredLinesCountBetweenUses) { + $previousUse = $use; + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected 0 lines between same types of use statement, found %d.', + $actualLinesCountAfterPreviousUse + ), + $use->getPointer(), + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_SAME_TYPES_OF_USE + ); + + if (!$fix) { + $previousUse = $use; + continue; + } + + /** @var int $previousUseSemicolonPointer */ + $previousUseSemicolonPointer = TokenHelper::findNextLocal($phpcsFile, T_SEMICOLON, $previousUse->getPointer() + 1); + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetween($phpcsFile, $previousUseSemicolonPointer, $useStartPointer); + $phpcsFile->fixer->addNewline($previousUseSemicolonPointer); + $phpcsFile->fixer->endChangeset(); + + $previousUse = $use; + } + } + + /** + * @param list $useStatements + */ + private function checkLinesBetweenDifferentTypesOfUse(File $phpcsFile, array $useStatements): void + { + if (count($useStatements) === 1) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $previousUse = null; + foreach ($useStatements as $use) { + if ($previousUse === null) { + $previousUse = $use; + continue; + } + + if ($use->hasSameType($previousUse)) { + $previousUse = $use; + continue; + } + + /** @var int $pointerBeforeUse */ + $pointerBeforeUse = TokenHelper::findPreviousNonWhitespace($phpcsFile, $use->getPointer() - 1); + $useStartPointer = $use->getPointer(); + + if ( + in_array($tokens[$pointerBeforeUse]['code'], Tokens::$commentTokens, true) + && TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $pointerBeforeUse) === $pointerBeforeUse + && $tokens[$pointerBeforeUse]['line'] + 1 === $tokens[$useStartPointer]['line'] + ) { + $useStartPointer = array_key_exists('comment_opener', $tokens[$pointerBeforeUse]) + ? $tokens[$pointerBeforeUse]['comment_opener'] + : CommentHelper::getMultilineCommentStartPointer($phpcsFile, $pointerBeforeUse); + } + + $actualLinesCountAfterPreviousUse = $tokens[$useStartPointer]['line'] - $tokens[$previousUse->getPointer()]['line'] - 1; + + if ($actualLinesCountAfterPreviousUse === $this->linesCountBetweenUseTypes) { + $previousUse = $use; + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s between different types of use statement, found %d.', + $this->linesCountBetweenUseTypes, + $this->linesCountBetweenUseTypes === 1 ? '' : 's', + $actualLinesCountAfterPreviousUse + ), + $use->getPointer(), + self::CODE_INCORRECT_LINES_COUNT_BETWEEN_DIFFERENT_TYPES_OF_USE + ); + + if (!$fix) { + $previousUse = $use; + continue; + } + + /** @var int $previousUseSemicolonPointer */ + $previousUseSemicolonPointer = TokenHelper::findNextLocal($phpcsFile, T_SEMICOLON, $previousUse->getPointer() + 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $previousUseSemicolonPointer, $useStartPointer); + + for ($i = 0; $i <= $this->linesCountBetweenUseTypes; $i++) { + $phpcsFile->fixer->addNewline($previousUseSemicolonPointer); + } + $phpcsFile->fixer->endChangeset(); + + $previousUse = $use; + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UselessAliasSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UselessAliasSniff.php new file mode 100644 index 000000000..140e3342e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UselessAliasSniff.php @@ -0,0 +1,82 @@ + + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $fileUseStatements = UseStatementHelper::getFileUseStatements($phpcsFile); + + if (count($fileUseStatements) === 0) { + return; + } + + foreach ($fileUseStatements as $useStatements) { + foreach ($useStatements as $useStatement) { + if ($useStatement->getAlias() === null) { + continue; + } + + $unqualifiedName = NamespaceHelper::getUnqualifiedNameFromFullyQualifiedName($useStatement->getFullyQualifiedTypeName()); + if ($unqualifiedName !== $useStatement->getAlias()) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Useless alias "%s" for use of "%s".', $useStatement->getAlias(), $useStatement->getFullyQualifiedTypeName()), + $useStatement->getPointer(), + self::CODE_USELESS_ALIAS + ); + + if (!$fix) { + continue; + } + + $asPointer = TokenHelper::findNext($phpcsFile, T_AS, $useStatement->getPointer() + 1); + $nameEndPointer = TokenHelper::findPrevious($phpcsFile, TokenHelper::getOnlyNameTokenCodes(), $asPointer - 1); + $useSemicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $asPointer + 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $nameEndPointer, $useSemicolonPointer); + + $phpcsFile->fixer->endChangeset(); + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/DisallowNumericLiteralSeparatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/DisallowNumericLiteralSeparatorSniff.php new file mode 100644 index 000000000..76c0493bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/DisallowNumericLiteralSeparatorSniff.php @@ -0,0 +1,55 @@ + + */ + public function register(): array + { + return [ + T_LNUMBER, + T_DNUMBER, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $numberPointer + */ + public function process(File $phpcsFile, $numberPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (strpos($tokens[$numberPointer]['content'], '_') === false) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Use of numeric literal separator is disallowed.', + $numberPointer, + self::CODE_DISALLOWED_NUMERIC_LITERAL_SEPARATOR + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($numberPointer, str_replace('_', '', $tokens[$numberPointer]['content'])); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/RequireNumericLiteralSeparatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/RequireNumericLiteralSeparatorSniff.php new file mode 100644 index 000000000..92df96ea6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Numbers/RequireNumericLiteralSeparatorSniff.php @@ -0,0 +1,82 @@ + + */ + public function register(): array + { + return [ + T_LNUMBER, + T_DNUMBER, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $numberPointer + */ + public function process(File $phpcsFile, $numberPointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 70400); + $this->minDigitsBeforeDecimalPoint = SniffSettingsHelper::normalizeInteger($this->minDigitsBeforeDecimalPoint); + $this->minDigitsAfterDecimalPoint = SniffSettingsHelper::normalizeInteger($this->minDigitsAfterDecimalPoint); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $number = $tokens[$numberPointer]['content']; + + if (strpos($tokens[$numberPointer]['content'], '_') !== false) { + return; + } + + if ( + $this->ignoreOctalNumbers + && preg_match('~^0[0-7]+$~', $number) === 1 + ) { + return; + } + + $regexp = '~(?:^\\d{' . $this->minDigitsBeforeDecimalPoint . '}|\.\\d{' . $this->minDigitsAfterDecimalPoint . '})~'; + + if (preg_match($regexp, $number) === 0) { + return; + } + + $phpcsFile->addError( + 'Use of numeric literal separator is required.', + $numberPointer, + self::CODE_REQUIRED_NUMERIC_LITERAL_SEPARATOR + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowEqualOperatorsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowEqualOperatorsSniff.php new file mode 100644 index 000000000..11acc895a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowEqualOperatorsSniff.php @@ -0,0 +1,60 @@ + + */ + public function register(): array + { + return [ + T_IS_EQUAL, + T_IS_NOT_EQUAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $operatorPointer + */ + public function process(File $phpcsFile, $operatorPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$operatorPointer]['code'] === T_IS_EQUAL) { + $fix = $phpcsFile->addFixableError( + 'Operator == is disallowed, use === instead.', + $operatorPointer, + self::CODE_DISALLOWED_EQUAL_OPERATOR + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($operatorPointer, '==='); + $phpcsFile->fixer->endChangeset(); + } + } else { + $fix = $phpcsFile->addFixableError(sprintf( + 'Operator %s is disallowed, use !== instead.', + $tokens[$operatorPointer]['content'] + ), $operatorPointer, self::CODE_DISALLOWED_NOT_EQUAL_OPERATOR); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($operatorPointer, '!=='); + $phpcsFile->fixer->endChangeset(); + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowIncrementAndDecrementOperatorsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowIncrementAndDecrementOperatorsSniff.php new file mode 100644 index 000000000..3d9d53966 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/DisallowIncrementAndDecrementOperatorsSniff.php @@ -0,0 +1,65 @@ + + */ + public function register(): array + { + return [ + T_DEC, + T_INC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $operatorPointer + */ + public function process(File $phpcsFile, $operatorPointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $operatorPointer + 1); + $afterVariableEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $nextPointer); + $isPostOperator = $afterVariableEndPointer === null; + + if ($tokens[$operatorPointer]['code'] === T_INC) { + if ($isPostOperator) { + $code = self::CODE_DISALLOWED_POST_INCREMENT_OPERATOR; + $message = 'Use of post-increment operator is disallowed.'; + } else { + $code = self::CODE_DISALLOWED_PRE_INCREMENT_OPERATOR; + $message = 'Use of pre-increment operator is disallowed.'; + } + } else { + if ($isPostOperator) { + $code = self::CODE_DISALLOWED_POST_DECREMENT_OPERATOR; + $message = 'Use of post-decrement operator is disallowed.'; + } else { + $code = self::CODE_DISALLOWED_PRE_DECREMENT_OPERATOR; + $message = 'Use of pre-decrement operator is disallowed.'; + } + } + + $phpcsFile->addError($message, $operatorPointer, $code); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/NegationOperatorSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/NegationOperatorSpacingSniff.php new file mode 100644 index 000000000..3da9174b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/NegationOperatorSpacingSniff.php @@ -0,0 +1,125 @@ + + */ + public function register(): array + { + return [T_MINUS]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->spacesCount = SniffSettingsHelper::normalizeInteger($this->spacesCount); + + $tokens = $phpcsFile->getTokens(); + + $previousEffective = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + + $possibleOperandTypes = array_merge( + TokenHelper::getOnlyNameTokenCodes(), + [ + T_CONSTANT_ENCAPSED_STRING, + T_CLASS_C, + T_CLOSE_PARENTHESIS, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_SQUARE_BRACKET, + T_DIR, + T_DNUMBER, + T_ENCAPSED_AND_WHITESPACE, + T_FILE, + T_FUNC_C, + T_LINE, + T_LNUMBER, + T_METHOD_C, + T_NS_C, + T_NUM_STRING, + T_TRAIT_C, + T_VARIABLE, + ] + ); + + if (in_array($tokens[$previousEffective]['code'], $possibleOperandTypes, true)) { + return; + } + + $possibleVariableStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $previousEffective); + if ($possibleVariableStartPointer !== null) { + return; + } + + $whitespacePointer = $pointer + 1; + + $numberOfSpaces = $tokens[$whitespacePointer]['code'] !== T_WHITESPACE ? 0 : strlen($tokens[$whitespacePointer]['content']); + if ($numberOfSpaces === $this->spacesCount) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected exactly %d space after "%s", %d found.', + $this->spacesCount, + $tokens[$pointer]['content'], + $numberOfSpaces + ), + $pointer, + self::CODE_INVALID_SPACE_AFTER_MINUS + ); + + if (!$fix) { + return; + } + + if ($this->spacesCount > $numberOfSpaces) { + $phpcsFile->fixer->addContent($pointer, ' '); + + return; + } + + $phpcsFile->fixer->replaceToken($whitespacePointer, ''); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireCombinedAssignmentOperatorSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireCombinedAssignmentOperatorSniff.php new file mode 100644 index 000000000..7a3406b34 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireCombinedAssignmentOperatorSniff.php @@ -0,0 +1,149 @@ + + */ + public function register(): array + { + return [ + T_EQUAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $equalPointer + */ + public function process(File $phpcsFile, $equalPointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $variableStartPointer */ + $variableStartPointer = TokenHelper::findNextEffective($phpcsFile, $equalPointer + 1); + $variableEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $variableStartPointer); + + if ($variableEndPointer === null) { + return; + } + + $operatorPointer = TokenHelper::findNextEffective($phpcsFile, $variableEndPointer + 1); + + $operators = [ + T_BITWISE_AND => '&=', + T_BITWISE_OR => '|=', + T_STRING_CONCAT => '.=', + T_DIVIDE => '/=', + T_MINUS => '-=', + T_POW => '**=', + T_MODULUS => '%=', + T_MULTIPLY => '*=', + T_PLUS => '+=', + T_SL => '<<=', + T_SR => '>>=', + T_BITWISE_XOR => '^=', + ]; + + if (!array_key_exists($tokens[$operatorPointer]['code'], $operators)) { + return; + } + + $isFixable = true; + + if ($tokens[$variableEndPointer]['code'] === T_CLOSE_SQUARE_BRACKET) { + $pointerAfterOperator = TokenHelper::findNextEffective($phpcsFile, $operatorPointer + 1); + if (in_array( + $tokens[$pointerAfterOperator]['code'], + [T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING, T_START_HEREDOC, T_START_NOWDOC], + true + )) { + return; + } + + $isFixable = in_array($tokens[$pointerAfterOperator]['code'], [T_LNUMBER, T_DNUMBER], true); + } + + $variableContent = IdentificatorHelper::getContent($phpcsFile, $variableStartPointer, $variableEndPointer); + + /** @var int $beforeEqualEndPointer */ + $beforeEqualEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $equalPointer - 1); + $beforeEqualStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $beforeEqualEndPointer); + + if ($beforeEqualStartPointer === null) { + return; + } + + $beforeEqualVariableContent = IdentificatorHelper::getContent($phpcsFile, $beforeEqualStartPointer, $beforeEqualEndPointer); + + if ($beforeEqualVariableContent !== $variableContent) { + return; + } + + $semicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $equalPointer + 1); + if (TokenHelper::findNext($phpcsFile, Tokens::$operators, $operatorPointer + 1, $semicolonPointer) !== null) { + return; + } + + $errorMessage = sprintf( + 'Use "%s" operator instead of "=" and "%s".', + $operators[$tokens[$operatorPointer]['code']], + $tokens[$operatorPointer]['content'] + ); + + if (!$isFixable) { + $phpcsFile->addError($errorMessage, $equalPointer, self::CODE_REQUIRED_COMBINED_ASSIGNMENT_OPERATOR); + + return; + } + + $fix = $phpcsFile->addFixableError($errorMessage, $equalPointer, self::CODE_REQUIRED_COMBINED_ASSIGNMENT_OPERATOR); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $equalPointer, $operatorPointer, $operators[$tokens[$operatorPointer]['code']]); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireOnlyStandaloneIncrementAndDecrementOperatorsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireOnlyStandaloneIncrementAndDecrementOperatorsSniff.php new file mode 100644 index 000000000..9b66a3c28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/RequireOnlyStandaloneIncrementAndDecrementOperatorsSniff.php @@ -0,0 +1,118 @@ + + */ + public function register(): array + { + return [ + T_DEC, + T_INC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $operatorPointer + */ + public function process(File $phpcsFile, $operatorPointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $nextPointer */ + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $operatorPointer + 1); + + $afterVariableEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $nextPointer); + $isPostOperator = $afterVariableEndPointer === null; + + if ($isPostOperator) { + /** @var int $beforeVariableEndPointer */ + $beforeVariableEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $operatorPointer - 1); + /** @var int $instructionStartPointer */ + $instructionStartPointer = IdentificatorHelper::findStartPointer($phpcsFile, $beforeVariableEndPointer); + $instructionEndPointer = $operatorPointer; + } else { + $instructionStartPointer = $operatorPointer; + /** @var int $instructionEndPointer */ + $instructionEndPointer = $afterVariableEndPointer; + } + + if ($this->isStandalone($phpcsFile, $instructionStartPointer, $instructionEndPointer)) { + return; + } + + if ($tokens[$operatorPointer]['code'] === T_INC) { + if ($isPostOperator) { + $code = self::CODE_POST_INCREMENT_OPERATOR_NOT_USED_STANDALONE; + $message = 'Post-increment operator should be used only as single instruction.'; + } else { + $code = self::CODE_PRE_INCREMENT_OPERATOR_NOT_USED_STANDALONE; + $message = 'Pre-increment operator should be used only as single instruction.'; + } + } else { + if ($isPostOperator) { + $code = self::CODE_POST_DECREMENT_OPERATOR_NOT_USED_STANDALONE; + $message = 'Post-decrement operator should be used only as single instruction.'; + } else { + $code = self::CODE_PRE_DECREMENT_OPERATOR_NOT_USED_STANDALONE; + $message = 'Pre-decrement operator should be used only as single instruction.'; + } + } + + $phpcsFile->addError($message, $operatorPointer, $code); + } + + private function isStandalone(File $phpcsFile, int $instructionStartPointer, int $instructionEndPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $pointerBeforeInstructionStart = TokenHelper::findPreviousEffective($phpcsFile, $instructionStartPointer - 1); + if (!in_array( + $tokens[$pointerBeforeInstructionStart]['code'], + [T_SEMICOLON, T_COLON, T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET, T_OPEN_TAG], + true + )) { + return false; + } + + $pointerAfterInstructionEnd = TokenHelper::findNextEffective($phpcsFile, $instructionEndPointer + 1); + if ($tokens[$pointerAfterInstructionEnd]['code'] === T_SEMICOLON) { + return true; + } + + if ($tokens[$pointerAfterInstructionEnd]['code'] === T_CLOSE_PARENTHESIS) { + return array_key_exists('parenthesis_owner', $tokens[$pointerAfterInstructionEnd]) + && in_array($tokens[$tokens[$pointerAfterInstructionEnd]['parenthesis_owner']]['code'], [T_FOR, T_WHILE], true); + } + + return false; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/SpreadOperatorSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/SpreadOperatorSpacingSniff.php new file mode 100644 index 000000000..27548e711 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Operators/SpreadOperatorSpacingSniff.php @@ -0,0 +1,71 @@ + + */ + public function register(): array + { + return [ + T_ELLIPSIS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $spreadOperatorPointer + */ + public function process(File $phpcsFile, $spreadOperatorPointer): void + { + $this->spacesCountAfterOperator = SniffSettingsHelper::normalizeInteger($this->spacesCountAfterOperator); + + $pointerAfterWhitespace = TokenHelper::findNextNonWhitespace($phpcsFile, $spreadOperatorPointer + 1); + + $whitespace = TokenHelper::getContent($phpcsFile, $spreadOperatorPointer + 1, $pointerAfterWhitespace - 1); + + if ($this->spacesCountAfterOperator === strlen($whitespace)) { + return; + } + + $errorMessage = $this->spacesCountAfterOperator === 0 + ? 'There must be no whitespace after spread operator.' + : sprintf( + 'There must be exactly %d whitespace%s after spread operator.', + $this->spacesCountAfterOperator, + $this->spacesCountAfterOperator !== 1 ? 's' : '' + ); + + $fix = $phpcsFile->addFixableError($errorMessage, $spreadOperatorPointer, self::CODE_INCORRECT_SPACES_AFTER_OPERATOR); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($spreadOperatorPointer, str_repeat(' ', $this->spacesCountAfterOperator)); + FixerHelper::removeBetween($phpcsFile, $spreadOperatorPointer, $pointerAfterWhitespace); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowDirectMagicInvokeCallSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowDirectMagicInvokeCallSniff.php new file mode 100644 index 000000000..f6db2f3ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowDirectMagicInvokeCallSniff.php @@ -0,0 +1,67 @@ + + */ + public function register(): array + { + return [ + T_STRING, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stringPointer + */ + public function process(File $phpcsFile, $stringPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + if ($tokens[$parenthesisOpenerPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (strtolower($tokens[$stringPointer]['content']) !== '__invoke') { + return; + } + + $objectOperator = TokenHelper::findPreviousEffective($phpcsFile, $stringPointer - 1); + if ($tokens[$objectOperator]['code'] !== T_OBJECT_OPERATOR) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Direct call of __invoke() is disallowed.', + $stringPointer, + self::CODE_DISALLOWED_DIRECT_MAGIC_INVOKE_CALL + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $objectOperator, $parenthesisOpenerPointer - 1); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowReferenceSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowReferenceSniff.php new file mode 100644 index 000000000..31340396f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/DisallowReferenceSniff.php @@ -0,0 +1,99 @@ + + */ + public function register(): array + { + return [ + T_BITWISE_AND, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $referencePointer + */ + public function process(File $phpcsFile, $referencePointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $referencePointer - 1); + if (in_array($tokens[$previousPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + $phpcsFile->addError('Returning reference is disallowed.', $referencePointer, self::CODE_DISALLOWED_RETURNING_REFERENCE); + return; + } + + $previousParenthesisOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_PARENTHESIS, $referencePointer - 1); + if ( + $previousParenthesisOpenerPointer !== null + && $tokens[$previousParenthesisOpenerPointer]['parenthesis_closer'] > $referencePointer + ) { + if (array_key_exists('parenthesis_owner', $tokens[$previousParenthesisOpenerPointer])) { + $parenthesisOwnerPointer = $tokens[$previousParenthesisOpenerPointer]['parenthesis_owner']; + if (in_array($tokens[$parenthesisOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + $phpcsFile->addError( + 'Passing by reference is disallowed.', + $referencePointer, + self::CODE_DISALLOWED_PASSING_BY_REFERENCE + ); + return; + } + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $previousParenthesisOpenerPointer - 1); + if ( + $pointerBeforeParenthesisOpener !== null + && $tokens[$pointerBeforeParenthesisOpener]['code'] === T_USE + ) { + $phpcsFile->addError( + 'Inheriting variable by reference is disallowed.', + $referencePointer, + self::CODE_DISALLOWED_INHERITING_VARIABLE_BY_REFERENCE + ); + return; + } + } + + /** @var int $variableStartPointer */ + $variableStartPointer = TokenHelper::findNextEffective($phpcsFile, $referencePointer + 1); + $variableEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $variableStartPointer); + + if ($variableEndPointer === null) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $referencePointer - 1); + if (!in_array($tokens[$previousPointer]['code'], [T_EQUAL, T_DOUBLE_ARROW, T_OPEN_SHORT_ARRAY, T_COMMA, T_AS], true)) { + return; + } + + $phpcsFile->addError('Assigning by reference is disallowed.', $referencePointer, self::CODE_DISALLOWED_ASSIGNING_BY_REFERENCE); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ForbiddenClassesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ForbiddenClassesSniff.php new file mode 100644 index 000000000..165840ed7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ForbiddenClassesSniff.php @@ -0,0 +1,272 @@ + */ + public $forbiddenClasses = []; + + /** @var array */ + public $forbiddenExtends = []; + + /** @var array */ + public $forbiddenInterfaces = []; + + /** @var array */ + public $forbiddenTraits = []; + + /** @var list */ + private static $keywordReferences = ['self', 'parent', 'static']; + + /** + * @return array + */ + public function register(): array + { + $searchTokens = []; + + if (count($this->forbiddenClasses) > 0) { + $this->forbiddenClasses = self::normalizeInputOption($this->forbiddenClasses); + $searchTokens[] = T_NEW; + $searchTokens[] = T_DOUBLE_COLON; + } + + if (count($this->forbiddenExtends) > 0) { + $this->forbiddenExtends = self::normalizeInputOption($this->forbiddenExtends); + $searchTokens[] = T_EXTENDS; + } + + if (count($this->forbiddenInterfaces) > 0) { + $this->forbiddenInterfaces = self::normalizeInputOption($this->forbiddenInterfaces); + $searchTokens[] = T_IMPLEMENTS; + } + + if (count($this->forbiddenTraits) > 0) { + $this->forbiddenTraits = self::normalizeInputOption($this->forbiddenTraits); + $searchTokens[] = T_USE; + } + + return $searchTokens; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $tokenPointer + */ + public function process(File $phpcsFile, $tokenPointer): void + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$tokenPointer]; + $nameTokens = array_merge(TokenHelper::getNameTokenCodes(), TokenHelper::$ineffectiveTokenCodes); + + if ( + $token['code'] === T_IMPLEMENTS + || ( + $token['code'] === T_USE + && UseStatementHelper::isTraitUse($phpcsFile, $tokenPointer) + ) + ) { + $endTokenPointer = TokenHelper::findNext( + $phpcsFile, + [T_SEMICOLON, T_OPEN_CURLY_BRACKET], + $tokenPointer + ); + $references = $this->getAllReferences($phpcsFile, $tokenPointer, $endTokenPointer); + + if ($token['code'] === T_IMPLEMENTS) { + $this->checkReferences($phpcsFile, $tokenPointer, $references, $this->forbiddenInterfaces); + } else { + // Fixer does not work when traits contains aliases + $this->checkReferences( + $phpcsFile, + $tokenPointer, + $references, + $this->forbiddenTraits, + $tokens[$endTokenPointer]['code'] !== T_OPEN_CURLY_BRACKET + ); + } + } elseif (in_array($token['code'], [T_NEW, T_EXTENDS], true)) { + $endTokenPointer = TokenHelper::findNextExcluding($phpcsFile, $nameTokens, $tokenPointer + 1); + $references = $this->getAllReferences($phpcsFile, $tokenPointer, $endTokenPointer); + + $this->checkReferences( + $phpcsFile, + $tokenPointer, + $references, + $token['code'] === T_NEW ? $this->forbiddenClasses : $this->forbiddenExtends + ); + } elseif ($token['code'] === T_DOUBLE_COLON && !$this->isTraitsConflictResolutionToken($token)) { + $startTokenPointer = TokenHelper::findPreviousExcluding($phpcsFile, $nameTokens, $tokenPointer - 1); + $references = $this->getAllReferences($phpcsFile, $startTokenPointer, $tokenPointer); + + $this->checkReferences($phpcsFile, $tokenPointer, $references, $this->forbiddenClasses); + } + } + + /** + * @param list $references + * @param array $forbiddenNames + */ + private function checkReferences( + File $phpcsFile, + int $tokenPointer, + array $references, + array $forbiddenNames, + bool $isFixable = true + ): void + { + $token = $phpcsFile->getTokens()[$tokenPointer]; + $details = [ + T_NEW => ['class', self::CODE_FORBIDDEN_CLASS], + T_DOUBLE_COLON => ['class', self::CODE_FORBIDDEN_CLASS], + T_EXTENDS => ['as a parent class', self::CODE_FORBIDDEN_PARENT_CLASS], + T_IMPLEMENTS => ['interface', self::CODE_FORBIDDEN_INTERFACE], + T_USE => ['trait', self::CODE_FORBIDDEN_TRAIT], + ]; + + foreach ($references as $reference) { + if (!array_key_exists($reference['fullyQualifiedName'], $forbiddenNames)) { + continue; + } + + $alternative = $forbiddenNames[$reference['fullyQualifiedName']]; + [$nameType, $code] = $details[$token['code']]; + + if ($alternative === null) { + $phpcsFile->addError( + sprintf('Usage of %s %s is forbidden.', $reference['fullyQualifiedName'], $nameType), + $reference['startPointer'], + $code + ); + } elseif (!$isFixable) { + $phpcsFile->addError( + sprintf( + 'Usage of %s %s is forbidden, use %s instead.', + $reference['fullyQualifiedName'], + $nameType, + $alternative + ), + $reference['startPointer'], + $code + ); + } else { + $fix = $phpcsFile->addFixableError( + sprintf( + 'Usage of %s %s is forbidden, use %s instead.', + $reference['fullyQualifiedName'], + $nameType, + $alternative + ), + $reference['startPointer'], + $code + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $reference['startPointer'], $reference['endPointer'], $alternative); + + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** + * @param array|int|string> $token + */ + private function isTraitsConflictResolutionToken(array $token): bool + { + return is_array($token['conditions']) && array_pop($token['conditions']) === T_USE; + } + + /** + * @return list + */ + private function getAllReferences(File $phpcsFile, int $startPointer, int $endPointer): array + { + // Always ignore first token + $startPointer++; + $references = []; + + while ($startPointer < $endPointer) { + $nextComma = TokenHelper::findNext($phpcsFile, [T_COMMA], $startPointer + 1); + $nextSeparator = min($endPointer, $nextComma ?? PHP_INT_MAX); + $reference = ReferencedNameHelper::getReferenceName($phpcsFile, $startPointer, $nextSeparator - 1); + + if ( + strlen($reference) !== 0 + && !in_array(strtolower($reference), self::$keywordReferences, true) + ) { + $references[] = [ + 'fullyQualifiedName' => NamespaceHelper::resolveClassName($phpcsFile, $reference, $startPointer), + 'startPointer' => TokenHelper::findNextEffective($phpcsFile, $startPointer, $endPointer), + 'endPointer' => TokenHelper::findPreviousEffective($phpcsFile, $nextSeparator - 1, $startPointer), + ]; + } + + $startPointer = $nextSeparator + 1; + } + + return $references; + } + + /** + * @param array $option + * @return array + */ + private static function normalizeInputOption(array $option): array + { + $forbiddenClasses = []; + foreach ($option as $forbiddenClass => $alternative) { + $forbiddenClasses[self::normalizeClassName($forbiddenClass)] = self::normalizeClassName($alternative); + } + + return $forbiddenClasses; + } + + private static function normalizeClassName(?string $typeName): ?string + { + if ($typeName === null || strlen($typeName) === 0 || strtolower($typeName) === 'null') { + return null; + } + + return NamespaceHelper::getFullyQualifiedTypeName($typeName); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/OptimizedFunctionsWithoutUnpackingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/OptimizedFunctionsWithoutUnpackingSniff.php new file mode 100644 index 000000000..cc304bbbe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/OptimizedFunctionsWithoutUnpackingSniff.php @@ -0,0 +1,114 @@ + + */ + public function register(): array + { + return TokenHelper::getOnlyNameTokenCodes(); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $previousTokenPointer = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + $openBracketPointer = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + $tokens = $phpcsFile->getTokens(); + + if ($openBracketPointer === null || $tokens[$openBracketPointer]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (in_array($tokens[$previousTokenPointer]['code'], [T_FUNCTION, T_NEW, T_OBJECT_OPERATOR], true)) { + return; + } + /** @var int $tokenBeforeInvocationPointer */ + $tokenBeforeInvocationPointer = TokenHelper::findPreviousExcluding($phpcsFile, TokenHelper::getNameTokenCodes(), $pointer); + $invokedName = TokenHelper::getContent($phpcsFile, $tokenBeforeInvocationPointer + 1, $pointer); + $useName = sprintf('function %s', $invokedName); + + $uses = UseStatementHelper::getUseStatementsForPointer($phpcsFile, $pointer); + if ($invokedName[0] === '\\') { + $invokedName = substr($invokedName, 1); + } elseif (array_key_exists($useName, $uses) && $uses[$useName]->isFunction()) { + $invokedName = $uses[$useName]->getFullyQualifiedTypeName(); + } elseif (NamespaceHelper::findCurrentNamespaceName($phpcsFile, $pointer) !== null) { + return; + } + + if (!in_array($invokedName, FunctionHelper::SPECIAL_FUNCTIONS, true)) { + return; + } + + $closeBracketPointer = $tokens[$openBracketPointer]['parenthesis_closer']; + + if (TokenHelper::findNextEffective($phpcsFile, $openBracketPointer + 1, $closeBracketPointer + 1) === $closeBracketPointer) { + return; + } + + $pointerBeforeCloseBracket = TokenHelper::findPreviousEffective($phpcsFile, $closeBracketPointer - 1); + + $startPointer = $tokens[$pointerBeforeCloseBracket]['code'] === T_COMMA ? $pointerBeforeCloseBracket : $closeBracketPointer; + do { + $lastArgumentSeparatorPointer = TokenHelper::findPrevious($phpcsFile, [T_COMMA], $startPointer - 1, $openBracketPointer); + $startPointer = $lastArgumentSeparatorPointer; + } while ( + $lastArgumentSeparatorPointer !== null + && $tokens[$lastArgumentSeparatorPointer]['level'] !== $tokens[$openBracketPointer]['level'] + ); + + if ($lastArgumentSeparatorPointer === null) { + $lastArgumentSeparatorPointer = $openBracketPointer; + } + + /** @var int $nextTokenAfterSeparatorPointer */ + $nextTokenAfterSeparatorPointer = TokenHelper::findNextEffective( + $phpcsFile, + $lastArgumentSeparatorPointer + 1, + $closeBracketPointer + ); + + if ($tokens[$nextTokenAfterSeparatorPointer]['code'] !== T_ELLIPSIS) { + return; + } + + if (TokenHelper::findNextEffective($phpcsFile, $nextTokenAfterSeparatorPointer + 1) === $closeBracketPointer) { + // First class callables + return; + } + + $phpcsFile->addError( + sprintf('Function %s is specialized by PHP and should not use argument unpacking.', $invokedName), + $nextTokenAfterSeparatorPointer, + self::CODE_UNPACKING_USED + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ReferenceSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ReferenceSpacingSniff.php new file mode 100644 index 000000000..a3478c9b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ReferenceSpacingSniff.php @@ -0,0 +1,131 @@ + + */ + public function register(): array + { + return [ + T_BITWISE_AND, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $referencePointer + */ + public function process(File $phpcsFile, $referencePointer): void + { + $this->spacesCountAfterReference = SniffSettingsHelper::normalizeInteger($this->spacesCountAfterReference); + + if (!$this->isReference($phpcsFile, $referencePointer)) { + return; + } + + $pointerAfterWhitespace = TokenHelper::findNextNonWhitespace($phpcsFile, $referencePointer + 1); + + $whitespace = TokenHelper::getContent($phpcsFile, $referencePointer + 1, $pointerAfterWhitespace - 1); + + $actualSpacesCount = strlen($whitespace); + + if ($this->spacesCountAfterReference === $actualSpacesCount) { + return; + } + + $errorMessage = $this->spacesCountAfterReference === 0 + ? 'There must be no whitespace after reference.' + : sprintf( + 'There must be exactly %d whitespace%s after reference.', + $this->spacesCountAfterReference, + $this->spacesCountAfterReference !== 1 ? 's' : '' + ); + + $fix = $phpcsFile->addFixableError($errorMessage, $referencePointer, self::CODE_INCORRECT_SPACES_AFTER_REFERENCE); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->addContent($referencePointer, str_repeat(' ', $this->spacesCountAfterReference)); + + FixerHelper::removeBetween($phpcsFile, $referencePointer, $pointerAfterWhitespace); + + $phpcsFile->fixer->endChangeset(); + } + + private function isReference(File $phpcsFile, int $referencePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $referencePointer - 1); + if (in_array($tokens[$previousPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + return true; + } + + $previousParenthesisOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_PARENTHESIS, $referencePointer - 1); + if ( + $previousParenthesisOpenerPointer !== null + && $tokens[$previousParenthesisOpenerPointer]['parenthesis_closer'] > $referencePointer + ) { + if (array_key_exists('parenthesis_owner', $tokens[$previousParenthesisOpenerPointer])) { + $parenthesisOwnerPointer = $tokens[$previousParenthesisOpenerPointer]['parenthesis_owner']; + if (in_array($tokens[$parenthesisOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + return true; + } + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $previousParenthesisOpenerPointer - 1); + if ( + $pointerBeforeParenthesisOpener !== null + && $tokens[$pointerBeforeParenthesisOpener]['code'] === T_USE + ) { + return true; + } + } + + /** @var int $variableStartPointer */ + $variableStartPointer = TokenHelper::findNextEffective($phpcsFile, $referencePointer + 1); + $variableEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $variableStartPointer); + + if ($variableEndPointer === null) { + return false; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $referencePointer - 1); + + return in_array($tokens[$previousPointer]['code'], [T_EQUAL, T_DOUBLE_ARROW, T_OPEN_SHORT_ARRAY, T_COMMA, T_AS], true); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireExplicitAssertionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireExplicitAssertionSniff.php new file mode 100644 index 000000000..49466b11d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireExplicitAssertionSniff.php @@ -0,0 +1,472 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $tokenCodes = [T_VARIABLE, T_FOREACH, T_WHILE, T_LIST, T_OPEN_SHORT_ARRAY]; + $commentClosePointer = $tokens[$docCommentOpenPointer]['comment_closer']; + + $codePointer = TokenHelper::findFirstNonWhitespaceOnNextLine($phpcsFile, $commentClosePointer); + + if ($codePointer === null || !in_array($tokens[$codePointer]['code'], $tokenCodes, true)) { + $firstPointerOnPreviousLine = TokenHelper::findFirstNonWhitespaceOnPreviousLine($phpcsFile, $docCommentOpenPointer); + if ( + $firstPointerOnPreviousLine === null + || !in_array($tokens[$firstPointerOnPreviousLine]['code'], $tokenCodes, true) + ) { + return; + } + + $codePointer = $firstPointerOnPreviousLine; + } + + /** @var list> $variableAnnotations */ + $variableAnnotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer, '@var'); + if (count($variableAnnotations) === 0) { + return; + } + + foreach (array_reverse($variableAnnotations) as $variableAnnotation) { + if ($variableAnnotation->isInvalid()) { + continue; + } + + $variableName = $variableAnnotation->getValue()->variableName; + + if ($variableName === '') { + continue; + } + + $variableAnnotationType = $variableAnnotation->getValue()->type; + + if ( + $variableAnnotationType instanceof UnionTypeNode + || $variableAnnotationType instanceof IntersectionTypeNode + ) { + foreach ($variableAnnotationType->types as $typeNode) { + if (!$this->isValidTypeNode($typeNode)) { + continue 2; + } + } + } elseif (!$this->isValidTypeNode($variableAnnotationType)) { + continue; + } + + /** @var IdentifierTypeNode|ThisTypeNode|UnionTypeNode|GenericTypeNode $variableAnnotationType */ + $variableAnnotationType = $variableAnnotationType; + + $assertion = $this->createAssert($variableName, $variableAnnotationType); + + if ($assertion === null) { + continue; + } + + if ($tokens[$codePointer]['code'] === T_VARIABLE) { + $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $codePointer + 1); + if ($tokens[$pointerAfterVariable]['code'] !== T_EQUAL) { + continue; + } + + if ($variableName !== $tokens[$codePointer]['content']) { + continue; + } + + $pointerToAddAssertion = $this->getNextSemicolonInSameScope($phpcsFile, $codePointer, $codePointer + 1); + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenPointer); + + } elseif ($tokens[$codePointer]['code'] === T_LIST) { + $listParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $codePointer + 1); + + $variablePointerInList = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $listParenthesisOpener + 1, + $tokens[$listParenthesisOpener]['parenthesis_closer'] + ); + if ($variablePointerInList === null) { + continue; + } + + $pointerToAddAssertion = $this->getNextSemicolonInSameScope($phpcsFile, $codePointer, $codePointer + 1); + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenPointer); + + } elseif ($tokens[$codePointer]['code'] === T_OPEN_SHORT_ARRAY) { + $pointerAfterList = TokenHelper::findNextEffective($phpcsFile, $tokens[$codePointer]['bracket_closer'] + 1); + if ($tokens[$pointerAfterList]['code'] !== T_EQUAL) { + continue; + } + + $variablePointerInList = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $codePointer + 1, + $tokens[$codePointer]['bracket_closer'] + ); + if ($variablePointerInList === null) { + continue; + } + + $pointerToAddAssertion = $this->getNextSemicolonInSameScope( + $phpcsFile, + $codePointer, + $tokens[$codePointer]['bracket_closer'] + 1 + ); + $indentation = IndentationHelper::getIndentation($phpcsFile, $docCommentOpenPointer); + + } else { + if ($tokens[$codePointer]['code'] === T_WHILE) { + $variablePointerInWhile = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $tokens[$codePointer]['parenthesis_opener'] + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + if ($variablePointerInWhile === null) { + continue; + } + + $pointerAfterVariableInWhile = TokenHelper::findNextEffective($phpcsFile, $variablePointerInWhile + 1); + if ($tokens[$pointerAfterVariableInWhile]['code'] !== T_EQUAL) { + continue; + } + } else { + $asPointer = TokenHelper::findNext( + $phpcsFile, + T_AS, + $tokens[$codePointer]['parenthesis_opener'] + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + $variablePointerInForeach = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $asPointer + 1, + $tokens[$codePointer]['parenthesis_closer'] + ); + if ($variablePointerInForeach === null) { + continue; + } + } + + $pointerToAddAssertion = $tokens[$codePointer]['scope_opener']; + $indentation = IndentationHelper::addIndentation(IndentationHelper::getIndentation($phpcsFile, $codePointer)); + } + + $fix = $phpcsFile->addFixableError( + 'Use assertion instead of inline documentation comment.', + $variableAnnotation->getStartPointer(), + self::CODE_REQUIRED_EXPLICIT_ASSERTION + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $variableAnnotation->getStartPointer(), $variableAnnotation->getEndPointer()); + + $docCommentUseful = false; + $docCommentClosePointer = $tokens[$docCommentOpenPointer]['comment_closer']; + for ($i = $docCommentOpenPointer + 1; $i < $docCommentClosePointer; $i++) { + $tokenContent = trim($phpcsFile->fixer->getTokenContent($i)); + if ($tokenContent === '' || $tokenContent === '*') { + continue; + } + + $docCommentUseful = true; + break; + } + + $pointerBeforeDocComment = TokenHelper::findPreviousContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $docCommentOpenPointer - 1 + ); + $pointerAfterDocComment = TokenHelper::findNextContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $docCommentClosePointer + 1 + ); + + if (!$docCommentUseful) { + FixerHelper::removeBetweenIncluding($phpcsFile, $pointerBeforeDocComment + 1, $pointerAfterDocComment); + } + + if ( + $pointerToAddAssertion < $docCommentClosePointer + && array_key_exists($pointerAfterDocComment + 1, $tokens) + ) { + $phpcsFile->fixer->addContentBefore($pointerAfterDocComment + 1, $indentation . $assertion . $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addContent($pointerToAddAssertion, $phpcsFile->eolChar . $indentation . $assertion); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + private function isValidTypeNode(TypeNode $typeNode): bool + { + if ($typeNode instanceof ThisTypeNode) { + return true; + } + + if ($typeNode instanceof IdentifierTypeNode) { + return true; + } + + if ( + $this->enableIntegerRanges + && $typeNode instanceof GenericTypeNode + && $typeNode->type->name === 'int' + && count($typeNode->genericTypes) === 2 + ) { + foreach ($typeNode->genericTypes as $genericType) { + $isValid = ($genericType instanceof IdentifierTypeNode && in_array($genericType->name, ['min', 'max'], true)) + || ($genericType instanceof ConstTypeNode && $genericType->constExpr instanceof ConstExprIntegerNode); + + if (!$isValid) { + return false; + } + } + + return true; + } + + return false; + } + + private function getNextSemicolonInSameScope(File $phpcsFile, int $scopePointer, int $searchAt): int + { + $semicolonPointer = null; + + do { + $semicolonPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $searchAt); + + if (ScopeHelper::isInSameScope($phpcsFile, $scopePointer, $semicolonPointer)) { + break; + } + + $searchAt = $semicolonPointer + 1; + + } while (true); + + return $semicolonPointer; + } + + /** + * @param IdentifierTypeNode|ThisTypeNode|UnionTypeNode|IntersectionTypeNode|GenericTypeNode $typeNode + */ + private function createAssert(string $variableName, TypeNode $typeNode): ?string + { + $conditions = []; + + if ( + $typeNode instanceof IdentifierTypeNode + || $typeNode instanceof ThisTypeNode + || $typeNode instanceof GenericTypeNode + ) { + $conditions = $this->createConditions($variableName, $typeNode); + + return $conditions !== [] ? sprintf('\assert(%s);', implode(' || ', $conditions)) : null; + } + + /** @var IdentifierTypeNode|ThisTypeNode|GenericTypeNode $innerTypeNode */ + foreach ($typeNode->types as $innerTypeNode) { + $innerTypeConditions = $this->createConditions($variableName, $innerTypeNode); + + if ($innerTypeConditions === []) { + return null; + } + + $conditions = array_merge($conditions, $innerTypeConditions); + } + + $operator = $typeNode instanceof IntersectionTypeNode ? '&&' : '||'; + + $formattedConditions = []; + + foreach (array_unique($conditions) as $condition) { + $formattedConditions[] = $operator === '||' && strpos($condition, '&&') !== false ? sprintf('(%s)', $condition) : $condition; + } + + return sprintf('\assert(%s);', implode(sprintf(' %s ', $operator), $formattedConditions)); + } + + /** + * @param IdentifierTypeNode|ThisTypeNode|GenericTypeNode $typeNode + * @return list + */ + private function createConditions(string $variableName, TypeNode $typeNode): array + { + if ($typeNode instanceof GenericTypeNode) { + $conditions = [sprintf('\is_int(%s)', $variableName)]; + + if ($typeNode->genericTypes[0] instanceof ConstTypeNode) { + $conditions[] = sprintf('%s >= %s', $variableName, (string) $typeNode->genericTypes[0]); + } + + if ($typeNode->genericTypes[1] instanceof ConstTypeNode) { + $conditions[] = sprintf('%s <= %s', $variableName, (string) $typeNode->genericTypes[1]); + } + + return [implode(' && ', $conditions)]; + } + + if ($typeNode instanceof ThisTypeNode) { + return [sprintf('%s instanceof $this', $variableName)]; + } + + if ($typeNode->name === 'self') { + return [sprintf('%s instanceof %s', $variableName, $typeNode->name)]; + } + + if ($typeNode->name === 'static') { + return [sprintf('%s instanceof static', $variableName)]; + } + + if (in_array($typeNode->name, ['true', 'false', 'null'], true)) { + return [sprintf('%s === %s', $variableName, $typeNode->name)]; + } + + if ( + $typeNode->name === 'mixed' + || TypeHintHelper::isVoidTypeHint($typeNode->name) + || TypeHintHelper::isNeverTypeHint($typeNode->name) + ) { + return []; + } + + if (TypeHintHelper::isSimpleTypeHint($typeNode->name)) { + return [sprintf('\is_%s(%s)', TypeHintHelper::convertLongSimpleTypeHintToShort($typeNode->name), $variableName)]; + } + + if (in_array($typeNode->name, ['resource', 'object'], true)) { + return [sprintf('\is_%s(%s)', $typeNode->name, $variableName)]; + } + + if ($typeNode->name === 'numeric') { + return [ + sprintf('\is_int(%s)', $variableName), + sprintf('\is_float(%s)', $variableName), + ]; + } + + if ($typeNode->name === 'scalar') { + return [ + sprintf('\is_int(%s)', $variableName), + sprintf('\is_float(%s)', $variableName), + sprintf('\is_bool(%s)', $variableName), + sprintf('\is_string(%s)', $variableName), + ]; + } + + if ($this->enableIntegerRanges) { + if ($typeNode->name === 'positive-int') { + return [sprintf('\is_int(%1$s) && %1$s > 0', $variableName)]; + } + + if ($typeNode->name === 'negative-int') { + return [sprintf('\is_int(%1$s) && %1$s < 0', $variableName)]; + } + } + + if ( + $this->enableAdvancedStringTypes + && in_array($typeNode->name, ['non-empty-string', 'non-falsy-string', 'callable-string', 'numeric-string'], true) + ) { + $conditions = [sprintf('\is_string(%s)', $variableName)]; + + if ($typeNode->name === 'non-empty-string') { + $conditions[] = sprintf("%s !== ''", $variableName); + } elseif ($typeNode->name === 'non-falsy-string') { + $conditions[] = sprintf('(bool) %s === true', $variableName); + } elseif ($typeNode->name === 'callable-string') { + $conditions[] = sprintf('\is_callable(%s)', $variableName); + } else { + $conditions[] = sprintf('\is_numeric(%s)', $variableName); + } + + return [implode(' && ', $conditions)]; + } + + if (TypeHintHelper::isSimpleUnofficialTypeHints($typeNode->name)) { + return []; + } + + return [sprintf('%s instanceof %s', $variableName, $typeNode->name)]; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireNowdocSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireNowdocSniff.php new file mode 100644 index 000000000..88e6f2365 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/RequireNowdocSniff.php @@ -0,0 +1,74 @@ + + */ + public function register(): array + { + return [ + T_START_HEREDOC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $heredocStartPointer + */ + public function process(File $phpcsFile, $heredocStartPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $heredocEndPointer = TokenHelper::findNext($phpcsFile, T_END_HEREDOC, $heredocStartPointer + 1); + + $heredocContentPointers = []; + for ($i = $heredocStartPointer + 1; $i < $heredocEndPointer; $i++) { + if ($tokens[$i]['code'] === T_HEREDOC) { + if (preg_match('~^([^\\\\$]|\\\\[^nrtvef0-7xu])*$~', $tokens[$i]['content']) === 0) { + return; + } + + $heredocContentPointers[] = $i; + } + } + + $fix = $phpcsFile->addFixableError('Use nowdoc syntax instead of heredoc.', $heredocStartPointer, self::CODE_REQUIRED_NOWDOC); + if (!$fix) { + return; + } + + $nowdocStart = preg_replace('~^<<<"?(\w+)"?~', '<<<\'$1\'', $tokens[$heredocStartPointer]['content']); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($heredocStartPointer, $nowdocStart); + + foreach ($heredocContentPointers as $heredocContentPointer) { + $heredocContent = $tokens[$heredocContentPointer]['content']; + $nowdocContent = preg_replace( + '~\\\\(\\\\[nrtvef]|\$|\\\\|\\\\[0-7]{1,3}|\\\\x[0-9A-Fa-f]{1,2}|\\\\u\{[0-9A-Fa-f]+\})~', + '$1', + $heredocContent + ); + + $phpcsFile->fixer->replaceToken($heredocContentPointer, $nowdocContent); + } + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ShortListSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ShortListSniff.php new file mode 100644 index 000000000..493261b5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/ShortListSniff.php @@ -0,0 +1,50 @@ + + */ + public function register(): array + { + return [T_LIST]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $fix = $phpcsFile->addFixableError('list(...) is forbidden, use [...] instead.', $pointer, self::CODE_LONG_LIST_USED); + + if (!$fix) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + /** @var int $startPointer */ + $startPointer = TokenHelper::findNext($phpcsFile, [T_OPEN_PARENTHESIS], $pointer + 1); + $endPointer = $tokens[$startPointer]['parenthesis_closer']; + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $pointer, $startPointer - 1); + $phpcsFile->fixer->replaceToken($startPointer, '['); + $phpcsFile->fixer->replaceToken($endPointer, ']'); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/TypeCastSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/TypeCastSniff.php new file mode 100644 index 000000000..a5b17bd12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/TypeCastSniff.php @@ -0,0 +1,119 @@ + null, + 'boolean' => 'bool', + 'double' => 'float', + 'integer' => 'int', + 'real' => 'float', + 'unset' => null, + ]; + + /** + * @return array + */ + public function register(): array + { + return [ + T_STRING_CAST, + T_BOOL_CAST, + T_DOUBLE_CAST, + T_INT_CAST, + T_UNSET_CAST, + T_BINARY_CAST, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $tokens = $phpcsFile->getTokens(); + $cast = $tokens[$pointer]['content']; + + preg_match('~^\(\s*(\S+)\s*\)\z~i', $cast, $matches); + + if (!array_key_exists(1, $matches)) { + return; + } + + $castName = $matches[1]; + $castNameLower = strtolower($castName); + + if (!array_key_exists($castNameLower, self::INVALID_CASTS)) { + return; + } + + if ($castNameLower === 'unset') { + $phpcsFile->addError( + sprintf('Cast "%s" is forbidden, use "unset(...)" or assign "null" instead.', $cast), + $pointer, + self::CODE_FORBIDDEN_CAST_USED + ); + + return; + } + + if ($castNameLower === 'binary') { + $fix = $phpcsFile->addFixableError( + sprintf('"Cast "%s" is forbidden and has no effect.', $cast), + $pointer, + self::CODE_FORBIDDEN_CAST_USED + ); + + if (!$fix) { + return; + } + + $end = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $pointer, $end - 1); + + $phpcsFile->fixer->endChangeset(); + + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Cast "%s" is forbidden, use "(%s)" instead.', $cast, self::INVALID_CASTS[$castNameLower]), + $pointer, + self::CODE_INVALID_CAST_USED + ); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($pointer, '(' . self::INVALID_CASTS[$castNameLower] . ')'); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessParenthesesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessParenthesesSniff.php new file mode 100644 index 000000000..17c78a06b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessParenthesesSniff.php @@ -0,0 +1,579 @@ + 1, + T_MULTIPLY => 2, + T_DIVIDE => 2, + T_MODULUS => 3, + T_PLUS => 4, + T_MINUS => 4, + T_STRING_CONCAT => 5, + ]; + + /** @var bool */ + public $ignoreComplexTernaryConditions = false; + + /** + * @return array + */ + public function register(): array + { + return [ + T_OPEN_PARENTHESIS, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $parenthesisOpenerPointer + */ + public function process(File $phpcsFile, $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (array_key_exists('parenthesis_owner', $tokens[$parenthesisOpenerPointer])) { + return; + } + + if (!array_key_exists('parenthesis_closer', $tokens[$parenthesisOpenerPointer])) { + return; + } + + /** @var int $pointerBeforeParenthesisOpener */ + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if (in_array($tokens[$pointerBeforeParenthesisOpener]['code'], array_merge( + TokenHelper::getNameTokenCodes(), + [ + T_VARIABLE, + T_ISSET, + T_UNSET, + T_EMPTY, + T_CLOSURE, + T_FN, + T_USE, + T_ANON_CLASS, + T_NEW, + T_SELF, + T_STATIC, + T_PARENT, + T_EXIT, + T_CLOSE_PARENTHESIS, + T_EVAL, + T_LIST, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_INT_CAST, + T_DOUBLE_CAST, + T_STRING_CAST, + T_ARRAY_CAST, + T_OBJECT_CAST, + T_BOOL_CAST, + T_UNSET_CAST, + T_MATCH, + ] + ), true) + ) { + return; + } + + /** @var int $pointerAfterParenthesisOpener */ + $pointerAfterParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + if (in_array( + $tokens[$pointerAfterParenthesisOpener]['code'], + [T_NEW, T_CLONE, T_YIELD, T_YIELD_FROM, T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE, T_ARRAY_CAST], + true + )) { + return; + } + + if (TokenHelper::findNext( + $phpcsFile, + T_EQUAL, + $parenthesisOpenerPointer + 1, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + ) !== null) { + return; + } + + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + 1 + ); + if ( + $pointerAfterParenthesisCloser !== null + && $tokens[$pointerAfterParenthesisCloser]['code'] === T_OPEN_PARENTHESIS + ) { + return; + } + + if (IdentificatorHelper::findStartPointer($phpcsFile, $pointerBeforeParenthesisOpener) !== null) { + return; + } + + $this->checkParenthesesAroundConditionInTernaryOperator($phpcsFile, $parenthesisOpenerPointer); + $this->checkParenthesesAroundCaseInSwitch($phpcsFile, $parenthesisOpenerPointer); + $this->checkParenthesesAroundVariableOrFunctionCall($phpcsFile, $parenthesisOpenerPointer); + $this->checkParenthesesAroundString($phpcsFile, $parenthesisOpenerPointer); + $this->checkParenthesesAroundOperators($phpcsFile, $parenthesisOpenerPointer); + } + + private function checkParenthesesAroundConditionInTernaryOperator(File $phpcsFile, int $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisCloserPointer = $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + + $ternaryOperatorPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisCloserPointer + 1); + if ($tokens[$ternaryOperatorPointer]['code'] !== T_INLINE_THEN) { + return; + } + + if (TokenHelper::findNext( + $phpcsFile, + [T_LOGICAL_AND, T_LOGICAL_OR, T_LOGICAL_XOR], + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) !== null) { + return; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if ($tokens[$pointerBeforeParenthesisOpener]['code'] === T_BOOLEAN_NOT) { + return; + } + + if (in_array($tokens[$pointerBeforeParenthesisOpener]['code'], Tokens::$comparisonTokens, true)) { + return; + } + + if (in_array($tokens[$pointerBeforeParenthesisOpener]['code'], Tokens::$booleanOperators, true)) { + return; + } + + if ($this->ignoreComplexTernaryConditions) { + if (TokenHelper::findNext( + $phpcsFile, + Tokens::$booleanOperators, + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) !== null) { + return; + } + + if (TokenHelper::findNextContent( + $phpcsFile, + T_WHITESPACE, + $phpcsFile->eolChar, + $parenthesisOpenerPointer + 1, + $parenthesisCloserPointer + ) !== null) { + return; + } + } + + $contentStartPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + $contentEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisCloserPointer - 1); + + for ($i = $contentStartPointer; $i <= $contentEndPointer; $i++) { + if ($tokens[$i]['code'] === T_INLINE_THEN) { + return; + } + } + + $fix = $phpcsFile->addFixableError('Useless parentheses.', $parenthesisOpenerPointer, self::CODE_USELESS_PARENTHESES); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $parenthesisOpenerPointer, $contentStartPointer - 1); + FixerHelper::removeBetweenIncluding($phpcsFile, $contentEndPointer + 1, $parenthesisCloserPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkParenthesesAroundCaseInSwitch(File $phpcsFile, int $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if ($tokens[$pointerBeforeParenthesisOpener]['code'] !== T_CASE) { + return; + } + + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + 1 + ); + if ($tokens[$pointerAfterParenthesisCloser]['code'] !== T_COLON) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless parentheses.', $parenthesisOpenerPointer, self::CODE_USELESS_PARENTHESES); + + if (!$fix) { + return; + } + + $contentStartPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + $contentEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] - 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $parenthesisOpenerPointer, $contentStartPointer - 1); + FixerHelper::removeBetweenIncluding($phpcsFile, $contentEndPointer + 1, $tokens[$parenthesisOpenerPointer]['parenthesis_closer']); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkParenthesesAroundVariableOrFunctionCall(File $phpcsFile, int $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $operatorsPointers = TokenHelper::findNextAll( + $phpcsFile, + self::OPERATORS, + $parenthesisOpenerPointer + 1, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + ); + if ($operatorsPointers !== []) { + return; + } + + $casePointer = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if ($tokens[$casePointer]['code'] === T_CASE) { + return; + } + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if (in_array($tokens[$pointerBeforeParenthesisOpener]['code'], Tokens::$booleanOperators, true)) { + return; + } + + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + 1 + ); + if (in_array($tokens[$pointerAfterParenthesisCloser]['code'], [T_INLINE_THEN, T_OPEN_PARENTHESIS, T_SR], true)) { + return; + } + + /** @var int $contentStartPointer */ + $contentStartPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + + if ($tokens[$contentStartPointer]['code'] === T_CONSTANT_ENCAPSED_STRING) { + return; + } + + $notBooleanNotOperatorPointer = $contentStartPointer; + + if ($tokens[$contentStartPointer]['code'] === T_BOOLEAN_NOT) { + /** @var int $notBooleanNotOperatorPointer */ + $notBooleanNotOperatorPointer = TokenHelper::findNextEffective($phpcsFile, $contentStartPointer + 1); + } + + if (in_array( + $tokens[$notBooleanNotOperatorPointer]['code'], + array_merge([T_SELF, T_STATIC, T_PARENT, T_VARIABLE, T_DOLLAR], TokenHelper::getNameTokenCodes()), + true + )) { + $contentEndPointer = IdentificatorHelper::findEndPointer($phpcsFile, $notBooleanNotOperatorPointer); + + if ( + $contentEndPointer === null + && in_array($tokens[$notBooleanNotOperatorPointer]['code'], TokenHelper::getNameTokenCodes(), true) + ) { + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $contentStartPointer + 1); + if ($tokens[$nextPointer]['code'] === T_OPEN_PARENTHESIS) { + $contentEndPointer = $contentStartPointer; + } + } + + do { + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $contentEndPointer + 1); + if ($tokens[$nextPointer]['code'] !== T_OPEN_PARENTHESIS) { + break; + } + + $contentEndPointer = $tokens[$nextPointer]['parenthesis_closer']; + } while (true); + } else { + $nextPointer = TokenHelper::findNext($phpcsFile, T_OPEN_PARENTHESIS, $notBooleanNotOperatorPointer + 1); + if ($nextPointer === null || !isset($tokens[$nextPointer]['parenthesis_closer'])) { + return; + } + + $contentEndPointer = $tokens[$nextPointer]['parenthesis_closer']; + } + + $pointerAfterContent = TokenHelper::findNextEffective($phpcsFile, $contentEndPointer + 1); + + if ($pointerAfterContent !== $tokens[$parenthesisOpenerPointer]['parenthesis_closer']) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless parentheses.', $parenthesisOpenerPointer, self::CODE_USELESS_PARENTHESES); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $parenthesisOpenerPointer, $contentStartPointer - 1); + FixerHelper::removeBetweenIncluding($phpcsFile, $contentEndPointer + 1, $tokens[$parenthesisOpenerPointer]['parenthesis_closer']); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkParenthesesAroundString(File $phpcsFile, int $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $stringPointer */ + $stringPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + + if ($tokens[$stringPointer]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + $pointerAfterString = TokenHelper::findNextEffective($phpcsFile, $stringPointer + 1); + if ($pointerAfterString !== $tokens[$parenthesisOpenerPointer]['parenthesis_closer']) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless parentheses.', $parenthesisOpenerPointer, self::CODE_USELESS_PARENTHESES); + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $parenthesisOpenerPointer, $stringPointer - 1); + FixerHelper::removeBetweenIncluding($phpcsFile, $stringPointer + 1, $tokens[$parenthesisOpenerPointer]['parenthesis_closer']); + + $phpcsFile->fixer->endChangeset(); + } + + private function checkParenthesesAroundOperators(File $phpcsFile, int $parenthesisOpenerPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + $pointerAfterParenthesisCloser = TokenHelper::findNextEffective( + $phpcsFile, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + 1 + ); + + if ($tokens[$pointerBeforeParenthesisOpener]['code'] === T_MINUS) { + $pointerBeforeMinus = TokenHelper::findPreviousEffective($phpcsFile, $pointerBeforeParenthesisOpener - 1); + if (!in_array($tokens[$pointerBeforeMinus]['code'], [T_DNUMBER, T_LNUMBER], true)) { + return; + } + } + + if ( + in_array($tokens[$pointerBeforeParenthesisOpener]['code'], Tokens::$booleanOperators, true) + || in_array($tokens[$pointerAfterParenthesisCloser]['code'], Tokens::$booleanOperators, true) + ) { + return; + } + + $operatorsPointers = []; + $actualStartPointer = $parenthesisOpenerPointer + 1; + while (true) { + $pointer = TokenHelper::findNext( + $phpcsFile, + array_merge( + self::OPERATORS, + [T_OPEN_PARENTHESIS, T_INLINE_THEN, T_COALESCE, T_BITWISE_AND, T_BITWISE_OR, T_BITWISE_XOR], + Tokens::$comparisonTokens + ), + $actualStartPointer, + $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] + ); + + if ($pointer === null) { + break; + } + + if (in_array($tokens[$pointer]['code'], [T_INLINE_THEN, T_COALESCE, T_BITWISE_AND, T_BITWISE_OR, T_BITWISE_XOR], true)) { + return; + } + + if (in_array($tokens[$pointer]['code'], Tokens::$comparisonTokens, true)) { + return; + } + + if ($tokens[$pointer]['code'] === T_OPEN_PARENTHESIS) { + $actualStartPointer = $tokens[$pointer]['parenthesis_closer'] + 1; + continue; + } + + $operatorsPointers[] = $pointer; + $actualStartPointer = $pointer + 1; + } + + if (count($operatorsPointers) === 0) { + return; + } + + if ( + $tokens[$pointerBeforeParenthesisOpener]['code'] !== T_EQUAL + || $tokens[$pointerAfterParenthesisCloser]['code'] !== T_SEMICOLON + ) { + $operatorsGroups = array_map(static function (int $operatorPointer) use ($tokens): int { + return self::OPERATOR_GROUPS[$tokens[$operatorPointer]['code']]; + }, $operatorsPointers); + + if (count($operatorsGroups) > 1) { + return; + } + } + + $firstOperatorPointer = $operatorsPointers[0]; + if (in_array($tokens[$pointerBeforeParenthesisOpener]['code'], self::OPERATORS, true)) { + if (self::OPERATOR_GROUPS[$tokens[$firstOperatorPointer]['code']] !== self::OPERATOR_GROUPS[$tokens[$pointerBeforeParenthesisOpener]['code']]) { + return; + } + + if ( + $tokens[$pointerBeforeParenthesisOpener]['code'] === T_MINUS + && in_array($tokens[$firstOperatorPointer]['code'], [T_PLUS, T_MINUS], true) + ) { + return; + } + + if ( + $tokens[$pointerBeforeParenthesisOpener]['code'] === T_DIVIDE + && in_array($tokens[$firstOperatorPointer]['code'], [T_DIVIDE, T_MULTIPLY], true) + ) { + return; + } + + if ( + $tokens[$pointerBeforeParenthesisOpener]['code'] === T_MODULUS + && $tokens[$firstOperatorPointer]['code'] === T_MODULUS + ) { + return; + } + } + + $lastOperatorPointer = $operatorsPointers[count($operatorsPointers) - 1]; + if ( + in_array($tokens[$pointerAfterParenthesisCloser]['code'], self::OPERATORS, true) + && self::OPERATOR_GROUPS[$tokens[$lastOperatorPointer]['code']] !== self::OPERATOR_GROUPS[$tokens[$pointerAfterParenthesisCloser]['code']] + ) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless parentheses.', $parenthesisOpenerPointer, self::CODE_USELESS_PARENTHESES); + + if (!$fix) { + return; + } + + $contentStartPointer = TokenHelper::findNextEffective($phpcsFile, $parenthesisOpenerPointer + 1); + $contentEndPointer = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$parenthesisOpenerPointer]['parenthesis_closer'] - 1); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $parenthesisOpenerPointer, $contentStartPointer - 1); + FixerHelper::removeBetweenIncluding($phpcsFile, $contentEndPointer + 1, $tokens[$parenthesisOpenerPointer]['parenthesis_closer']); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessSemicolonSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessSemicolonSniff.php new file mode 100644 index 000000000..09bba5155 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/PHP/UselessSemicolonSniff.php @@ -0,0 +1,160 @@ + + */ + public function register(): array + { + return [ + T_SEMICOLON, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $semicolonPointer + */ + public function process(File $phpcsFile, $semicolonPointer): void + { + $this->checkMultipleSemicolons($phpcsFile, $semicolonPointer); + $this->checkSemicolonAtTheBeginningOfScope($phpcsFile, $semicolonPointer); + $this->checkSemicolonAfterScope($phpcsFile, $semicolonPointer); + } + + private function checkMultipleSemicolons(File $phpcsFile, int $semicolonPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1); + if ($tokens[$previousPointer]['code'] !== T_SEMICOLON) { + return; + } + + $possibleEndScopePointer = TokenHelper::findNextLocal($phpcsFile, T_CLOSE_PARENTHESIS, $semicolonPointer + 1); + if ( + $possibleEndScopePointer !== null + && $tokens[$possibleEndScopePointer]['parenthesis_opener'] < $semicolonPointer + && array_key_exists('parenthesis_owner', $tokens[$possibleEndScopePointer]) + && $tokens[$tokens[$possibleEndScopePointer]['parenthesis_owner']]['code'] === T_FOR + ) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless semicolon.', $semicolonPointer, self::CODE_USELESS_SEMICOLON); + + if (!$fix) { + return; + } + + $this->removeUselessSemicolon($phpcsFile, $semicolonPointer); + } + + private function checkSemicolonAtTheBeginningOfScope(File $phpcsFile, int $semicolonPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1); + if (!in_array($tokens[$previousPointer]['code'], [T_OPEN_TAG, T_OPEN_CURLY_BRACKET], true)) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless semicolon.', $semicolonPointer, self::CODE_USELESS_SEMICOLON); + + if (!$fix) { + return; + } + + $this->removeUselessSemicolon($phpcsFile, $semicolonPointer); + } + + private function checkSemicolonAfterScope(File $phpcsFile, int $semicolonPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $semicolonPointer - 1); + if ($tokens[$previousPointer]['code'] !== T_CLOSE_CURLY_BRACKET) { + return; + } + + if (!array_key_exists('scope_condition', $tokens[$previousPointer])) { + return; + } + + $scopeOpenerPointer = $tokens[$previousPointer]['scope_condition']; + if (in_array($tokens[$scopeOpenerPointer]['code'], [T_CLOSURE, T_FN, T_ANON_CLASS, T_MATCH], true)) { + return; + } + + $fix = $phpcsFile->addFixableError('Useless semicolon.', $semicolonPointer, self::CODE_USELESS_SEMICOLON); + + if (!$fix) { + return; + } + + $this->removeUselessSemicolon($phpcsFile, $semicolonPointer); + } + + private function removeUselessSemicolon(File $phpcsFile, int $semicolonPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $fixStartPointer = $semicolonPointer; + do { + if ($tokens[$fixStartPointer - 1]['code'] !== T_WHITESPACE) { + break; + } + + $fixStartPointer--; + + if ($tokens[$fixStartPointer]['content'] === $phpcsFile->eolChar) { + break; + } + } while (true); + + $fixEndPointer = $semicolonPointer; + while ($fixEndPointer < count($tokens) - 1) { + if ($tokens[$fixEndPointer + 1]['code'] !== T_WHITESPACE) { + break; + } + + if ($tokens[$fixEndPointer + 1]['content'] === $phpcsFile->eolChar) { + break; + } + + $fixEndPointer++; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetweenIncluding($phpcsFile, $fixStartPointer, $fixEndPointer); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Strings/DisallowVariableParsingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Strings/DisallowVariableParsingSniff.php new file mode 100644 index 000000000..45a8c4048 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Strings/DisallowVariableParsingSniff.php @@ -0,0 +1,154 @@ + + */ + public function register(): array + { + return [ + T_DOUBLE_QUOTED_STRING, + T_HEREDOC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $stringPointer + */ + public function process(File $phpcsFile, $stringPointer): void + { + if (!$this->disallowDollarCurlySyntax && !$this->disallowCurlyDollarSyntax && !$this->disallowSimpleSyntax) { + throw new UnexpectedValueException('No option is set.'); + } + + $tokens = $phpcsFile->getTokens(); + $tokenContent = $tokens[$stringPointer]['content']; + + if (strpos($tokenContent, '$') === false) { + return; + } + + $stringTokens = $tokens[$stringPointer]['code'] === T_HEREDOC + ? token_get_all('disallowDollarCurlySyntax && $this->getTokenContent($stringToken) === '${') { + $usedVariable = $stringToken[1]; + + for ($j = $i + 1; $j < count($stringTokens); $j++) { + $usedVariable .= $this->getTokenContent($stringTokens[$j]); + + if ($this->getTokenContent($stringTokens[$j]) === '}') { + $phpcsFile->addError( + sprintf( + 'Using variable syntax "${...}" inside string is disallowed as syntax "${...}" is deprecated as of PHP 8.2, found "%s".', + $usedVariable + ), + $stringPointer, + self::CODE_DISALLOWED_DOLLAR_CURLY_SYNTAX + ); + + break; + } + } + } elseif ($stringToken[0] === T_VARIABLE) { + if ($this->disallowCurlyDollarSyntax && $this->getTokenContent($stringTokens[$i - 1]) === '{') { + $usedVariable = $stringToken[1]; + + for ($j = $i + 1; $j < count($stringTokens); $j++) { + $stringTokenContent = $this->getTokenContent($stringTokens[$j]); + if ($stringTokenContent === '}') { + break; + } + + $usedVariable .= $stringTokenContent; + } + + $phpcsFile->addError( + sprintf( + 'Using variable syntax "{$...}" inside string is disallowed, found "{%s}".', + $usedVariable + ), + $stringPointer, + self::CODE_DISALLOWED_CURLY_DOLLAR_SYNTAX + ); + } elseif ($this->disallowSimpleSyntax) { + $error = true; + + for ($j = $i - 1; $j >= 0; $j--) { + $stringTokenContent = $this->getTokenContent($stringTokens[$j]); + + if (in_array($stringTokenContent, ['{', '${'], true)) { + $error = false; + break; + } + + if ($stringTokenContent === '}') { + break; + } + } + + if ($error) { + $phpcsFile->addError( + sprintf( + 'Using variable syntax "$..." inside string is disallowed, found "%s".', + $this->getTokenContent($stringToken) + ), + $stringPointer, + self::CODE_DISALLOWED_SIMPLE_SYNTAX + ); + } + } + } + } + } + + /** + * @param array{0: int, 1: string}|string $token + */ + private function getTokenContent($token): string + { + return is_array($token) ? $token[1] : $token; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TestCase.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TestCase.php new file mode 100644 index 000000000..b418c788b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TestCase.php @@ -0,0 +1,236 @@ +> $sniffProperties + * @param list $codesToCheck + * @param list $cliArgs + */ + protected static function checkFile(string $filePath, array $sniffProperties = [], array $codesToCheck = [], array $cliArgs = []): File + { + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + $codeSniffer = new Runner(); + $codeSniffer->config = new Config(array_merge(['-s'], $cliArgs)); + $codeSniffer->init(); + + if (count($sniffProperties) > 0) { + /** @phpstan-ignore-next-line */ + if (version_compare(Config::VERSION, '3.8.0', '>=')) { + foreach ($sniffProperties as $name => $value) { + $sniffProperties[$name] = [ + 'value' => $value, + 'scope' => 'sniff', + ]; + } + } + + $codeSniffer->ruleset->ruleset[self::getSniffName()]['properties'] = $sniffProperties; + } + + $sniffClassName = static::getSniffClassName(); + /** @var Sniff $sniff */ + $sniff = new $sniffClassName(); + + $codeSniffer->ruleset->sniffs = [$sniffClassName => $sniff]; + + if (count($codesToCheck) > 0) { + foreach (self::getSniffClassReflection()->getConstants() as $constantName => $constantValue) { + if (strpos($constantName, 'CODE_') !== 0 || in_array($constantValue, $codesToCheck, true)) { + continue; + } + + $codeSniffer->ruleset->ruleset[sprintf('%s.%s', self::getSniffName(), $constantValue)]['severity'] = 0; + } + } + + $codeSniffer->ruleset->populateTokenListeners(); + + $file = new LocalFile($filePath, $codeSniffer->ruleset, $codeSniffer->config); + $file->process(); + + return $file; + } + + protected static function assertNoSniffErrorInFile(File $phpcsFile): void + { + $errors = $phpcsFile->getErrors(); + self::assertEmpty($errors, sprintf('No errors expected, but %d errors found.', count($errors))); + } + + protected static function assertNoSniffWarningInFile(File $phpcsFile): void + { + $warnings = $phpcsFile->getWarnings(); + self::assertEmpty($warnings, sprintf('No warnings expected, but %d warnings found.', count($warnings))); + } + + protected static function assertSniffError(File $phpcsFile, int $line, string $code, ?string $message = null): void + { + $errors = $phpcsFile->getErrors(); + self::assertTrue(isset($errors[$line]), sprintf('Expected error on line %s, but none found.', $line)); + + $sniffCode = sprintf('%s.%s', self::getSniffName(), $code); + + self::assertTrue( + self::hasError($errors[$line], $sniffCode, $message), + sprintf( + 'Expected error %s%s, but none found on line %d.%sErrors found on line %d:%s%s%s', + $sniffCode, + $message !== null + ? sprintf(' with message "%s"', $message) + : '', + $line, + PHP_EOL . PHP_EOL, + $line, + PHP_EOL, + self::getFormattedErrors($errors[$line]), + PHP_EOL + ) + ); + } + + protected static function assertSniffWarning(File $phpcsFile, int $line, string $code, ?string $message = null): void + { + $errors = $phpcsFile->getWarnings(); + self::assertTrue(isset($errors[$line]), sprintf('Expected warning on line %s, but none found.', $line)); + + $sniffCode = sprintf('%s.%s', self::getSniffName(), $code); + + self::assertTrue( + self::hasError($errors[$line], $sniffCode, $message), + sprintf( + 'Expected warning %s%s, but none found on line %d.%sWarnings found on line %d:%s%s%s', + $sniffCode, + $message !== null + ? sprintf(' with message "%s"', $message) + : '', + $line, + PHP_EOL . PHP_EOL, + $line, + PHP_EOL, + self::getFormattedErrors($errors[$line]), + PHP_EOL + ) + ); + } + + protected static function assertNoSniffError(File $phpcsFile, int $line): void + { + $errors = $phpcsFile->getErrors(); + self::assertFalse( + isset($errors[$line]), + sprintf( + 'Expected no error on line %s, but found:%s%s%s', + $line, + PHP_EOL . PHP_EOL, + isset($errors[$line]) ? self::getFormattedErrors($errors[$line]) : '', + PHP_EOL + ) + ); + } + + protected static function assertAllFixedInFile(File $phpcsFile): void + { + $phpcsFile->disableCaching(); + $phpcsFile->fixer->fixFile(); + self::assertStringEqualsFile(preg_replace('~(\\.php)$~', '.fixed\\1', $phpcsFile->getFilename()), $phpcsFile->fixer->getContents()); + } + + /** + * @return class-string + */ + protected static function getSniffClassName(): string + { + /** @var class-string $sniffClassName */ + $sniffClassName = substr(static::class, 0, -strlen('Test')); + + return $sniffClassName; + } + + protected static function getSniffName(): string + { + return Common::getSniffCode(static::getSniffClassName()); + } + + private static function getSniffClassReflection(): ReflectionClass + { + static $reflections = []; + + $className = static::getSniffClassName(); + + return $reflections[$className] ?? $reflections[$className] = new ReflectionClass($className); + } + + /** + * @param list> $errorsOnLine + */ + private static function hasError(array $errorsOnLine, string $sniffCode, ?string $message): bool + { + $hasError = false; + + foreach ($errorsOnLine as $errorsOnPosition) { + foreach ($errorsOnPosition as $error) { + /** @var string $errorSource */ + $errorSource = $error['source']; + /** @var string $errorMessage */ + $errorMessage = $error['message']; + + if ( + $errorSource === $sniffCode + && ( + $message === null + || strpos($errorMessage, $message) !== false + ) + ) { + $hasError = true; + break; + } + } + } + + return $hasError; + } + + /** + * @param list> $errors + */ + private static function getFormattedErrors(array $errors): string + { + return implode(PHP_EOL, array_map(static function (array $errors): string { + return implode(PHP_EOL, array_map(static function (array $error): string { + return sprintf("\t%s: %s", $error['source'], $error['message']); + }, $errors)); + }, $errors)); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DeclareStrictTypesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DeclareStrictTypesSniff.php new file mode 100644 index 000000000..998798182 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DeclareStrictTypesSniff.php @@ -0,0 +1,262 @@ + + */ + public function register(): array + { + return [ + T_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $openTagPointer + */ + public function process(File $phpcsFile, $openTagPointer): void + { + $this->linesCountBeforeDeclare = SniffSettingsHelper::normalizeInteger($this->linesCountBeforeDeclare); + $this->linesCountAfterDeclare = SniffSettingsHelper::normalizeInteger($this->linesCountAfterDeclare); + $this->spacesCountAroundEqualsSign = SniffSettingsHelper::normalizeInteger($this->spacesCountAroundEqualsSign); + + if (TokenHelper::findPrevious($phpcsFile, T_OPEN_TAG, $openTagPointer - 1) !== null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $declarePointer = TokenHelper::findNextEffective($phpcsFile, $openTagPointer + 1); + + if ($declarePointer === null || $tokens[$declarePointer]['code'] !== T_DECLARE) { + $fix = $phpcsFile->addFixableError( + sprintf('Missing declare(%s).', $this->getStrictTypeDeclaration()), + $openTagPointer, + self::CODE_DECLARE_STRICT_TYPES_MISSING + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( + $openTagPointer, + sprintf('declare(%s);%s', $this->getStrictTypeDeclaration(), $phpcsFile->eolChar) + ); + $phpcsFile->fixer->endChangeset(); + } + return; + } + + $strictTypesPointer = null; + for ($i = $tokens[$declarePointer]['parenthesis_opener'] + 1; $i < $tokens[$declarePointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_STRING || $tokens[$i]['content'] !== 'strict_types') { + continue; + } + + $strictTypesPointer = $i; + break; + } + + if ($strictTypesPointer === null) { + $fix = $phpcsFile->addFixableError( + sprintf('Missing declare(%s).', $this->getStrictTypeDeclaration()), + $declarePointer, + self::CODE_DECLARE_STRICT_TYPES_MISSING + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore( + $tokens[$declarePointer]['parenthesis_closer'], + ', ' . $this->getStrictTypeDeclaration() + ); + $phpcsFile->fixer->endChangeset(); + } + return; + } + + /** @var int $numberPointer */ + $numberPointer = TokenHelper::findNext($phpcsFile, T_LNUMBER, $strictTypesPointer + 1); + if ($tokens[$numberPointer]['content'] !== '1') { + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %s, found %s.', + $this->getStrictTypeDeclaration(), + TokenHelper::getContent($phpcsFile, $strictTypesPointer, $numberPointer) + ), + $declarePointer, + self::CODE_DECLARE_STRICT_TYPES_MISSING + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($numberPointer, '1'); + $phpcsFile->fixer->endChangeset(); + } + return; + } + + $strictTypesContent = TokenHelper::getContent($phpcsFile, $strictTypesPointer, $numberPointer); + $format = sprintf('strict_types%1$s=%1$s1', str_repeat(' ', $this->spacesCountAroundEqualsSign)); + if ($strictTypesContent !== $format) { + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %s, found %s.', + $format, + $strictTypesContent + ), + $strictTypesPointer, + self::CODE_INCORRECT_STRICT_TYPES_FORMAT + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $strictTypesPointer, $numberPointer, $format); + + $phpcsFile->fixer->endChangeset(); + } + } + + $pointerBeforeDeclare = TokenHelper::findPreviousNonWhitespace($phpcsFile, $declarePointer - 1); + + $whitespaceBefore = ''; + if ($pointerBeforeDeclare === $openTagPointer) { + $whitespaceBefore .= substr($tokens[$openTagPointer]['content'], strlen('declareOnFirstLine) { + if ($whitespaceBefore !== ' ') { + $fix = $phpcsFile->addFixableError( + 'There must be a single space between the PHP open tag and declare statement.', + $declarePointer, + self::CODE_INCORRECT_WHITESPACE_BEFORE_DECLARE + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $openTagPointer, $declarePointer - 1, 'fixer->endChangeset(); + } + } + } else { + $declareOnFirstLine = $tokens[$declarePointer]['line'] === $tokens[$openTagPointer]['line']; + $linesCountBefore = $declareOnFirstLine ? 0 : substr_count($whitespaceBefore, $phpcsFile->eolChar) - 1; + if ($declareOnFirstLine || $linesCountBefore !== $this->linesCountBeforeDeclare) { + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s before declare statement, found %d.', + $this->linesCountBeforeDeclare, + $this->linesCountBeforeDeclare === 1 ? '' : 's', + $linesCountBefore + ), + $declarePointer, + self::CODE_INCORRECT_WHITESPACE_BEFORE_DECLARE + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + + if ($pointerBeforeDeclare === $openTagPointer) { + $phpcsFile->fixer->replaceToken($openTagPointer, 'linesCountBeforeDeclare; $i++) { + $phpcsFile->fixer->addNewline($pointerBeforeDeclare); + } + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** @var int $declareSemicolonPointer */ + $declareSemicolonPointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$declarePointer]['parenthesis_closer'] + 1); + $pointerAfterWhitespaceEnd = TokenHelper::findNextNonWhitespace($phpcsFile, $declareSemicolonPointer + 1); + if ($pointerAfterWhitespaceEnd === null) { + return; + } + + $whitespaceAfter = TokenHelper::getContent($phpcsFile, $declareSemicolonPointer + 1, $pointerAfterWhitespaceEnd - 1); + + $newLinesAfter = substr_count($whitespaceAfter, $phpcsFile->eolChar); + $linesCountAfter = $newLinesAfter > 0 ? $newLinesAfter - 1 : 0; + + if ($linesCountAfter === $this->linesCountAfterDeclare) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Expected %d line%s after declare statement, found %d.', + $this->linesCountAfterDeclare, + $this->linesCountAfterDeclare === 1 ? '' : 's', + $linesCountAfter + ), + $declarePointer, + self::CODE_INCORRECT_WHITESPACE_AFTER_DECLARE + ); + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::removeBetween($phpcsFile, $declareSemicolonPointer, $pointerAfterWhitespaceEnd); + + for ($i = 0; $i <= $this->linesCountAfterDeclare; $i++) { + $phpcsFile->fixer->addNewline($declareSemicolonPointer); + } + + $phpcsFile->fixer->endChangeset(); + } + + protected function getStrictTypeDeclaration(): string + { + return sprintf( + 'strict_types%s=%s1', + str_repeat(' ', $this->spacesCountAroundEqualsSign), + str_repeat(' ', $this->spacesCountAroundEqualsSign) + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowArrayTypeHintSyntaxSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowArrayTypeHintSyntaxSniff.php new file mode 100644 index 000000000..bc8bc6262 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowArrayTypeHintSyntaxSniff.php @@ -0,0 +1,307 @@ + */ + public $traversableTypeHints = []; + + /** @var array|null */ + private $normalizedTraversableTypeHints; + + /** + * @return array + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach ($annotations as $annotation) { + $arrayTypeNodes = $this->getArrayTypeNodes($annotation->getValue()); + + foreach ($arrayTypeNodes as $arrayTypeNode) { + $fix = $phpcsFile->addFixableError( + sprintf( + 'Usage of array type hint syntax in "%s" is disallowed, use generic type hint syntax instead.', + AnnotationTypeHelper::print($arrayTypeNode) + ), + $annotation->getStartPointer(), + self::CODE_DISALLOWED_ARRAY_TYPE_HINT_SYNTAX + ); + + if (!$fix) { + continue; + } + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + /** @var list $unionTypeNodes */ + $unionTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), UnionTypeNode::class); + + $unionTypeNode = $this->findUnionTypeThatContainsArrayType($arrayTypeNode, $unionTypeNodes); + + if ($unionTypeNode !== null) { + $genericIdentifier = $this->findGenericIdentifier( + $phpcsFile, + $docCommentOpenPointer, + $unionTypeNode, + $annotation->getValue() + ); + if ($genericIdentifier !== null) { + $genericTypeNode = new GenericTypeNode( + new IdentifierTypeNode($genericIdentifier), + [$this->fixArrayNode($arrayTypeNode->type)] + ); + $fixedDocComment = AnnotationHelper::fixAnnotation( + $parsedDocComment, + $annotation, + $unionTypeNode, + $genericTypeNode + ); + } else { + $genericTypeNode = new GenericTypeNode( + new IdentifierTypeNode('array'), + [$this->fixArrayNode($arrayTypeNode->type)] + ); + $fixedDocComment = AnnotationHelper::fixAnnotation( + $parsedDocComment, + $annotation, + $arrayTypeNode, + $genericTypeNode + ); + } + } else { + $genericIdentifier = $this->findGenericIdentifier( + $phpcsFile, + $docCommentOpenPointer, + $arrayTypeNode, + $annotation->getValue() + ) ?? 'array'; + + $genericTypeNode = new GenericTypeNode( + new IdentifierTypeNode($genericIdentifier), + [$this->fixArrayNode($arrayTypeNode->type)] + ); + $fixedDocComment = AnnotationHelper::fixAnnotation($parsedDocComment, $annotation, $arrayTypeNode, $genericTypeNode); + } + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change( + $phpcsFile, + $parsedDocComment->getOpenPointer(), + $parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + $phpcsFile->fixer->endChangeset(); + } + } + } + + /** + * @return list + */ + public function getArrayTypeNodes(Node $node): array + { + static $visitor; + static $traverser; + + if ($visitor === null) { + $visitor = new class extends AbstractNodeVisitor { + + /** @var list */ + private $nodes = []; + + /** + * @return Node|list|NodeTraverser::*|null + */ + public function enterNode(Node $node) + { + if ($node instanceof ArrayTypeNode) { + $this->nodes[] = $node; + + if ($node->type instanceof ArrayTypeNode) { + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + } + } + + return null; + } + + public function cleanNodes(): void + { + $this->nodes = []; + } + + /** + * @return list + */ + public function getNodes(): array + { + return $this->nodes; + } + + }; + } + + if ($traverser === null) { + $traverser = new NodeTraverser([$visitor]); + } + + $visitor->cleanNodes(); + + $traverser->traverse([$node]); + + return $visitor->getNodes(); + } + + private function fixArrayNode(TypeNode $node): TypeNode + { + if (!$node instanceof ArrayTypeNode) { + return $node; + } + + return new GenericTypeNode(new IdentifierTypeNode('array'), [$this->fixArrayNode($node->type)]); + } + + /** + * @param list $unionTypeNodes + */ + private function findUnionTypeThatContainsArrayType(ArrayTypeNode $arrayTypeNode, array $unionTypeNodes): ?UnionTypeNode + { + foreach ($unionTypeNodes as $unionTypeNode) { + if (in_array($arrayTypeNode, $unionTypeNode->types, true)) { + return $unionTypeNode; + } + } + + return null; + } + + private function findGenericIdentifier( + File $phpcsFile, + int $docCommentOpenPointer, + TypeNode $typeNode, + PhpDocTagValueNode $annotationValue + ): ?string + { + if (!$typeNode instanceof UnionTypeNode) { + if (!$annotationValue instanceof ParamTagValueNode && !$annotationValue instanceof ReturnTagValueNode) { + return null; + } + + $functionPointer = TokenHelper::findNext($phpcsFile, TokenHelper::$functionTokenCodes, $docCommentOpenPointer + 1); + + if ($functionPointer === null || $phpcsFile->getTokens()[$functionPointer]['code'] !== T_FUNCTION) { + return null; + } + + if ($annotationValue instanceof ParamTagValueNode) { + $parameterTypeHints = FunctionHelper::getParametersTypeHints($phpcsFile, $functionPointer); + return array_key_exists( + $annotationValue->parameterName, + $parameterTypeHints + ) && $parameterTypeHints[$annotationValue->parameterName] !== null + ? $parameterTypeHints[$annotationValue->parameterName]->getTypeHint() + : null; + } + + $returnType = FunctionHelper::findReturnTypeHint($phpcsFile, $functionPointer); + return $returnType !== null ? $returnType->getTypeHint() : null; + } + + if (count($typeNode->types) !== 2) { + return null; + } + + if ( + $typeNode->types[0] instanceof ArrayTypeNode + && $typeNode->types[1] instanceof IdentifierTypeNode + && $this->isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $docCommentOpenPointer, $typeNode->types[1]->name) + ) + ) { + return $typeNode->types[1]->name; + } + + if ( + $typeNode->types[1] instanceof ArrayTypeNode + && $typeNode->types[0] instanceof IdentifierTypeNode + && $this->isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $docCommentOpenPointer, $typeNode->types[0]->name) + ) + ) { + return $typeNode->types[0]->name; + } + + return null; + } + + private function isTraversableType(string $type): bool + { + return TypeHintHelper::isSimpleIterableTypeHint($type) || array_key_exists($type, $this->getNormalizedTraversableTypeHints()); + } + + /** + * @return array + */ + private function getNormalizedTraversableTypeHints(): array + { + if ($this->normalizedTraversableTypeHints === null) { + $this->normalizedTraversableTypeHints = array_flip(array_map(static function (string $typeHint): string { + return NamespaceHelper::isFullyQualifiedName($typeHint) + ? $typeHint + : sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $typeHint); + }, SniffSettingsHelper::normalizeArray($this->traversableTypeHints))); + } + return $this->normalizedTraversableTypeHints; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowMixedTypeHintSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowMixedTypeHintSniff.php new file mode 100644 index 000000000..2c29985ed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowMixedTypeHintSniff.php @@ -0,0 +1,72 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + if (SuppressHelper::isSniffSuppressed( + $phpcsFile, + $docCommentOpenPointer, + $this->getSniffName(self::CODE_DISALLOWED_MIXED_TYPE_HINT) + )) { + return; + } + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach ($annotations as $annotation) { + /** @var list $identifierTypeNodes */ + $identifierTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), IdentifierTypeNode::class); + + foreach ($identifierTypeNodes as $typeHintNode) { + $typeHint = $typeHintNode->name; + + if (strtolower($typeHint) !== 'mixed') { + continue; + } + + $phpcsFile->addError( + 'Usage of "mixed" type hint is disallowed.', + $annotation->getStartPointer(), + self::CODE_DISALLOWED_MIXED_TYPE_HINT + ); + } + } + } + + private function getSniffName(string $sniffName): string + { + return sprintf('%s.%s', self::NAME, $sniffName); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/LongTypeHintsSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/LongTypeHintsSniff.php new file mode 100644 index 000000000..8bc9c2f2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/LongTypeHintsSniff.php @@ -0,0 +1,92 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach ($annotations as $annotation) { + /** @var list $identifierTypeNodes */ + $identifierTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), IdentifierTypeNode::class); + + foreach ($identifierTypeNodes as $typeHintNode) { + $typeHint = $typeHintNode->name; + + $lowercasedTypeHint = strtolower($typeHint); + + $shortTypeHint = null; + if ($lowercasedTypeHint === 'integer') { + $shortTypeHint = 'int'; + } elseif ($lowercasedTypeHint === 'boolean') { + $shortTypeHint = 'bool'; + } + + if ($shortTypeHint === null) { + continue; + } + + $fix = $phpcsFile->addFixableError(sprintf( + 'Expected "%s" but found "%s" in %s annotation.', + $shortTypeHint, + $typeHint, + $annotation->getName() + ), $annotation->getStartPointer(), self::CODE_USED_LONG_TYPE_HINT); + + if (!$fix) { + continue; + } + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + $fixedDocComment = AnnotationHelper::fixAnnotation( + $parsedDocComment, + $annotation, + $typeHintNode, + new IdentifierTypeNode($shortTypeHint) + ); + + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change( + $phpcsFile, + $parsedDocComment->getOpenPointer(), + $parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + $phpcsFile->fixer->endChangeset(); + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullTypeHintOnLastPositionSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullTypeHintOnLastPositionSniff.php new file mode 100644 index 000000000..eb7a3a439 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullTypeHintOnLastPositionSniff.php @@ -0,0 +1,109 @@ + + */ + public function register(): array + { + return [ + T_DOC_COMMENT_OPEN_TAG, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $docCommentOpenPointer + */ + public function process(File $phpcsFile, $docCommentOpenPointer): void + { + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach ($annotations as $annotation) { + /** @var list $unionTypeNodes */ + $unionTypeNodes = AnnotationHelper::getAnnotationNodesByType($annotation->getNode(), UnionTypeNode::class); + + foreach ($unionTypeNodes as $unionTypeNode) { + $nullTypeNode = null; + $nullPosition = 0; + $position = 0; + foreach ($unionTypeNode->types as $typeNode) { + if ($typeNode instanceof IdentifierTypeNode && strtolower($typeNode->name) === 'null') { + $nullTypeNode = $typeNode; + $nullPosition = $position; + break; + } + + $position++; + } + + if ($nullTypeNode === null) { + continue; + } + + if ($nullPosition === count($unionTypeNode->types) - 1) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Null type hint should be on last position in "%s".', AnnotationTypeHelper::print($unionTypeNode)), + $annotation->getStartPointer(), + self::CODE_NULL_TYPE_HINT_NOT_ON_LAST_POSITION + ); + + if (!$fix) { + continue; + } + + $fixedTypeNodes = []; + foreach ($unionTypeNode->types as $typeNode) { + if ($typeNode === $nullTypeNode) { + continue; + } + + $fixedTypeNodes[] = $typeNode; + } + $fixedTypeNodes[] = $nullTypeNode; + + $fixedUnionTypeNode = PhpDocParserHelper::cloneNode($unionTypeNode); + $fixedUnionTypeNode->types = $fixedTypeNodes; + + $phpcsFile->fixer->beginChangeset(); + + $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer); + + $fixedDocComment = AnnotationHelper::fixAnnotation($parsedDocComment, $annotation, $unionTypeNode, $fixedUnionTypeNode); + + FixerHelper::change( + $phpcsFile, + $parsedDocComment->getOpenPointer(), + $parsedDocComment->getClosePointer(), + $fixedDocComment + ); + + $phpcsFile->fixer->endChangeset(); + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullableTypeForNullDefaultValueSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullableTypeForNullDefaultValueSniff.php new file mode 100644 index 000000000..9d97cb1ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullableTypeForNullDefaultValueSniff.php @@ -0,0 +1,125 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + if (SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, self::NAME)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $startPointer = $tokens[$functionPointer]['parenthesis_opener'] + 1; + $endPointer = $tokens[$functionPointer]['parenthesis_closer']; + + $typeHintTokenCodes = TokenHelper::getOnlyTypeHintTokenCodes(); + + for ($i = $startPointer; $i < $endPointer; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + $parameterName = $tokens[$i]['content']; + + $afterVariablePointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if ($tokens[$afterVariablePointer]['code'] !== T_EQUAL) { + continue; + } + + $afterEqualsPointer = TokenHelper::findNextEffective($phpcsFile, $afterVariablePointer + 1); + if ($tokens[$afterEqualsPointer]['code'] !== T_NULL) { + continue; + } + + $ignoreTokensToFindTypeHint = array_merge(TokenHelper::$ineffectiveTokenCodes, [T_BITWISE_AND, T_ELLIPSIS]); + $typeHintEndPointer = TokenHelper::findPreviousExcluding($phpcsFile, $ignoreTokensToFindTypeHint, $i - 1, $startPointer); + + if ( + $typeHintEndPointer === null + || !in_array($tokens[$typeHintEndPointer]['code'], $typeHintTokenCodes, true) + ) { + continue; + } + + $typeHintStartPointer = TypeHintHelper::getStartPointer($phpcsFile, $typeHintEndPointer); + + $typeHint = TokenHelper::getContent($phpcsFile, $typeHintStartPointer, $typeHintEndPointer); + + if (strtolower($typeHint) === 'mixed') { + continue; + } + + $nullableSymbolPointer = TokenHelper::findPreviousEffective( + $phpcsFile, + $typeHintStartPointer - 1, + $tokens[$functionPointer]['parenthesis_opener'] + ); + + if ($nullableSymbolPointer !== null && $tokens[$nullableSymbolPointer]['code'] === T_NULLABLE) { + continue; + } + + if (preg_match('~(?:^|(?:\|\s*))null(?:(?:\s*\|)|$)~i', $typeHint) === 1) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Parameter %s has null default value, but is not marked as nullable.', $parameterName), + $i, + self::CODE_NULLABILITY_TYPE_MISSING + ); + + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + + if (substr_count($typeHint, '|') > 0) { + $phpcsFile->fixer->addContent($typeHintEndPointer, '|null'); + } else { + $phpcsFile->fixer->addContentBefore($typeHintStartPointer, '?'); + } + + $phpcsFile->fixer->endChangeset(); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSniff.php new file mode 100644 index 000000000..fa71a58fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSniff.php @@ -0,0 +1,688 @@ + */ + public $traversableTypeHints = []; + + /** @var array|null */ + private $normalizedTraversableTypeHints; + + /** + * @return array + */ + public function register(): array + { + return [ + T_FUNCTION, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $this->enableObjectTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableObjectTypeHint, 70200); + $this->enableMixedTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableMixedTypeHint, 80000); + $this->enableUnionTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableUnionTypeHint, 80000); + $this->enableIntersectionTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableIntersectionTypeHint, 80100); + $this->enableStandaloneNullTrueFalseTypeHints = SniffSettingsHelper::isEnabledByPhpVersion( + $this->enableStandaloneNullTrueFalseTypeHints, + 80200 + ); + + if (SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, self::NAME)) { + return; + } + + if (DocCommentHelper::hasInheritdocAnnotation($phpcsFile, $functionPointer)) { + return; + } + + $parametersTypeHints = FunctionHelper::getParametersTypeHints($phpcsFile, $functionPointer); + $parametersAnnotations = FunctionHelper::getValidParametersAnnotations($phpcsFile, $functionPointer); + $prefixedParametersAnnotations = FunctionHelper::getValidPrefixedParametersAnnotations($phpcsFile, $functionPointer); + + $this->checkTypeHints($phpcsFile, $functionPointer, $parametersTypeHints, $parametersAnnotations, $prefixedParametersAnnotations); + $this->checkTraversableTypeHintSpecification( + $phpcsFile, + $functionPointer, + $parametersTypeHints, + $parametersAnnotations, + $prefixedParametersAnnotations + ); + $this->checkUselessAnnotations($phpcsFile, $functionPointer, $parametersTypeHints, $parametersAnnotations); + } + + /** + * @param array $parametersTypeHints + * @param array|Annotation|Annotation> $parametersAnnotations + * @param array|Annotation> $prefixedParametersAnnotations + */ + private function checkTypeHints( + File $phpcsFile, + int $functionPointer, + array $parametersTypeHints, + array $parametersAnnotations, + array $prefixedParametersAnnotations + ): void + { + $suppressNameAnyTypeHint = self::getSniffName(self::CODE_MISSING_ANY_TYPE_HINT); + $isSuppressedAnyTypeHint = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressNameAnyTypeHint); + + $suppressNameNativeTypeHint = $this->getSniffName(self::CODE_MISSING_NATIVE_TYPE_HINT); + $isSuppressedNativeTypeHint = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressNameNativeTypeHint); + + $suppressedErrors = 0; + + $parametersWithoutTypeHint = array_keys( + array_filter($parametersTypeHints, static function (?TypeHint $parameterTypeHint = null): bool { + return $parameterTypeHint === null; + }) + ); + + $tokens = $phpcsFile->getTokens(); + + $isConstructor = FunctionHelper::isMethod($phpcsFile, $functionPointer) + && strtolower(FunctionHelper::getName($phpcsFile, $functionPointer)) === '__construct'; + + foreach ($parametersWithoutTypeHint as $parameterName) { + $isPropertyPromotion = false; + + if ($isConstructor) { + $parameterPointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $parameterName, + $tokens[$functionPointer]['parenthesis_opener'], + $tokens[$functionPointer]['parenthesis_closer'] + ); + + $pointerBeforeParameter = TokenHelper::findPrevious($phpcsFile, [T_COMMA, T_OPEN_PARENTHESIS], $parameterPointer - 1); + + $visibilityPointer = TokenHelper::findNextEffective($phpcsFile, $pointerBeforeParameter + 1); + + $isPropertyPromotion = in_array($tokens[$visibilityPointer]['code'], Tokens::$scopeModifiers, true); + } + + if ( + !array_key_exists($parameterName, $parametersAnnotations) + || $parametersAnnotations[$parameterName]->getValue() instanceof TypelessParamTagValueNode + ) { + if (array_key_exists($parameterName, $prefixedParametersAnnotations)) { + continue; + } + + if ($isSuppressedAnyTypeHint) { + $suppressedErrors++; + continue; + } + + $phpcsFile->addError( + sprintf( + '%s %s() does not have parameter type hint nor @param annotation for its parameter %s.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + $parameterName + ), + $functionPointer, + self::CODE_MISSING_ANY_TYPE_HINT + ); + + continue; + } + + $parameterTypeNode = $parametersAnnotations[$parameterName]->getValue()->type; + + if ( + $parameterTypeNode instanceof IdentifierTypeNode + && strtolower($parameterTypeNode->name) === 'null' + && !$this->enableStandaloneNullTrueFalseTypeHints + ) { + continue; + } + + $originalParameterTypeNode = $parameterTypeNode; + if ($parameterTypeNode instanceof NullableTypeNode) { + $parameterTypeNode = $parameterTypeNode->type; + } + + $canTryUnionTypeHint = $this->enableUnionTypeHint && $parameterTypeNode instanceof UnionTypeNode; + + $typeHints = []; + $traversableTypeHints = []; + $nullableParameterTypeHint = false; + + if (AnnotationTypeHelper::containsOneType($parameterTypeNode)) { + /** @var ArrayTypeNode|ArrayShapeNode|ObjectShapeNode|IdentifierTypeNode|ThisTypeNode|GenericTypeNode|CallableTypeNode|ConstTypeNode $parameterTypeNode */ + $parameterTypeNode = $parameterTypeNode; + $typeHints[] = AnnotationTypeHelper::getTypeHintFromOneType( + $parameterTypeNode, + false, + $this->enableStandaloneNullTrueFalseTypeHints + ); + + } elseif ( + $parameterTypeNode instanceof UnionTypeNode + || $parameterTypeNode instanceof IntersectionTypeNode + ) { + $traversableTypeHints = []; + foreach ($parameterTypeNode->types as $typeNode) { + if (!AnnotationTypeHelper::containsOneType($typeNode)) { + continue 2; + } + + /** @var ArrayTypeNode|ArrayShapeNode|ObjectShapeNode|IdentifierTypeNode|ThisTypeNode|GenericTypeNode|CallableTypeNode|ConstTypeNode $typeNode */ + $typeNode = $typeNode; + + $typeHint = AnnotationTypeHelper::getTypeHintFromOneType($typeNode, $canTryUnionTypeHint); + + if (strtolower($typeHint) === 'null') { + $nullableParameterTypeHint = true; + continue; + } + + $isTraversable = TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $functionPointer, $typeHint), + $this->getTraversableTypeHints() + ); + + if ( + !$typeNode instanceof ArrayTypeNode + && !$typeNode instanceof ArrayShapeNode + && $isTraversable + ) { + $traversableTypeHints[] = $typeHint; + } + + $typeHints[] = $typeHint; + } + + $traversableTypeHints = array_values(array_unique($traversableTypeHints)); + if (count($traversableTypeHints) > 1 && !$canTryUnionTypeHint) { + continue; + } + } + + $typeHints = array_values(array_unique($typeHints)); + + if (count($traversableTypeHints) > 0) { + /** @var UnionTypeNode|IntersectionTypeNode $parameterTypeNode */ + $parameterTypeNode = $parameterTypeNode; + + $itemsSpecificationTypeHint = AnnotationTypeHelper::getItemsSpecificationTypeFromType($parameterTypeNode); + if ($itemsSpecificationTypeHint !== null) { + $typeHints = AnnotationTypeHelper::getTraversableTypeHintsFromType( + $parameterTypeNode, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints(), + $canTryUnionTypeHint + ); + } + } + + if (count($typeHints) === 0) { + continue; + } + + $typeHintsWithConvertedUnion = []; + foreach ($typeHints as $typeHint) { + if ($this->enableUnionTypeHint && TypeHintHelper::isUnofficialUnionTypeHint($typeHint)) { + $canTryUnionTypeHint = true; + $typeHintsWithConvertedUnion = array_merge( + $typeHintsWithConvertedUnion, + TypeHintHelper::convertUnofficialUnionTypeHintToOfficialTypeHints($typeHint) + ); + } else { + $typeHintsWithConvertedUnion[] = $typeHint; + } + } + $typeHintsWithConvertedUnion = array_unique($typeHintsWithConvertedUnion); + + if ( + count($typeHintsWithConvertedUnion) > 1 + && ( + ($parameterTypeNode instanceof UnionTypeNode && !$canTryUnionTypeHint) + || ($parameterTypeNode instanceof IntersectionTypeNode && !$this->enableIntersectionTypeHint) + ) + ) { + continue; + } + + foreach ($typeHintsWithConvertedUnion as $typeHintNo => $typeHint) { + if ($canTryUnionTypeHint && $typeHint === 'false') { + continue; + } + + if ($isPropertyPromotion && $typeHint === 'callable') { + continue 2; + } + + if (!TypeHintHelper::isValidTypeHint( + $typeHint, + $this->enableObjectTypeHint, + false, + $this->enableMixedTypeHint, + $this->enableStandaloneNullTrueFalseTypeHints + )) { + continue 2; + } + + if (TypeHintHelper::isTypeDefinedInAnnotation($phpcsFile, $functionPointer, $typeHint)) { + continue 2; + } + + $typeHintsWithConvertedUnion[$typeHintNo] = TypeHintHelper::convertLongSimpleTypeHintToShort($typeHint); + } + + if ($originalParameterTypeNode instanceof NullableTypeNode) { + $nullableParameterTypeHint = true; + } + + if ($isSuppressedNativeTypeHint) { + $suppressedErrors++; + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + '%s %s() does not have native type hint for its parameter %s but it should be possible to add it based on @param annotation "%s".', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + $parameterName, + AnnotationTypeHelper::print($parameterTypeNode) + ), + $functionPointer, + self::CODE_MISSING_NATIVE_TYPE_HINT + ); + if (!$fix) { + continue; + } + + if (in_array('mixed', $typeHintsWithConvertedUnion, true)) { + $parameterTypeHint = 'mixed'; + } elseif ($originalParameterTypeNode instanceof IntersectionTypeNode) { + $parameterTypeHint = implode('&', $typeHintsWithConvertedUnion); + } else { + $parameterTypeHint = implode('|', $typeHintsWithConvertedUnion); + if ($nullableParameterTypeHint) { + if (count($typeHintsWithConvertedUnion) > 1) { + $parameterTypeHint .= '|null'; + } else { + $parameterTypeHint = '?' . $parameterTypeHint; + } + } + } + + $tokens = $phpcsFile->getTokens(); + /** @var int $parameterPointer */ + $parameterPointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $parameterName, + $tokens[$functionPointer]['parenthesis_opener'], + $tokens[$functionPointer]['parenthesis_closer'] + ); + + $beforeParameterPointer = $parameterPointer; + do { + $previousPointer = TokenHelper::findPreviousEffective( + $phpcsFile, + $beforeParameterPointer - 1, + $tokens[$functionPointer]['parenthesis_opener'] + 1 + ); + if ( + $previousPointer === null + || !in_array($tokens[$previousPointer]['code'], [T_BITWISE_AND, T_ELLIPSIS], true) + ) { + break; + } + + /** @var int $beforeParameterPointer */ + $beforeParameterPointer = $previousPointer; + } while (true); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore( + $beforeParameterPointer, + sprintf('%s ', $parameterTypeHint) + ); + $phpcsFile->fixer->endChangeset(); + } + + if ($suppressedErrors > 0) { + return; + } + + if ($isSuppressedAnyTypeHint) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $suppressNameAnyTypeHint); + } + + if ($isSuppressedNativeTypeHint) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $suppressNameNativeTypeHint); + } + } + + /** + * @param array $parametersTypeHints + * @param array|Annotation|Annotation> $parametersAnnotations + * @param array|Annotation> $prefixedParametersAnnotations + */ + private function checkTraversableTypeHintSpecification( + File $phpcsFile, + int $functionPointer, + array $parametersTypeHints, + array $parametersAnnotations, + array $prefixedParametersAnnotations + ): void + { + $suppressName = self::getSniffName(self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION); + $isSniffSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressName); + $suppressUseless = true; + + foreach ($parametersTypeHints as $parameterName => $parameterTypeHint) { + if (array_key_exists($parameterName, $prefixedParametersAnnotations)) { + continue; + } + + $hasTraversableTypeHint = false; + if ( + $parameterTypeHint !== null + && TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $functionPointer, $parameterTypeHint->getTypeHint()), + $this->getTraversableTypeHints() + ) + ) { + $hasTraversableTypeHint = true; + } elseif ( + array_key_exists($parameterName, $parametersAnnotations) + && !$parametersAnnotations[$parameterName]->getValue() instanceof TypelessParamTagValueNode + && AnnotationTypeHelper::containsTraversableType( + $parametersAnnotations[$parameterName]->getValue()->type, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints() + ) + ) { + $hasTraversableTypeHint = true; + } + + if ($hasTraversableTypeHint && !array_key_exists($parameterName, $parametersAnnotations)) { + $suppressUseless = false; + + if (!$isSniffSuppressed) { + $phpcsFile->addError( + sprintf( + '%s %s() does not have @param annotation for its traversable parameter %s.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + $parameterName + ), + $functionPointer, + self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION + ); + } + + continue; + } + + if (!array_key_exists($parameterName, $parametersAnnotations)) { + continue; + } + + if ($parametersAnnotations[$parameterName]->getValue() instanceof TypelessParamTagValueNode) { + continue; + } + + $parameterTypeNode = $parametersAnnotations[$parameterName]->getValue()->type; + + if ( + ( + !$hasTraversableTypeHint + && !AnnotationTypeHelper::containsTraversableType( + $parameterTypeNode, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints() + ) + ) + || AnnotationTypeHelper::containsItemsSpecificationForTraversable( + $parameterTypeNode, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints() + ) + ) { + continue; + } + + $suppressUseless = false; + + if ($isSniffSuppressed) { + continue; + } + + $phpcsFile->addError( + sprintf( + '@param annotation of %s %s() does not specify type hint for items of its traversable parameter %s.', + lcfirst(FunctionHelper::getTypeLabel($phpcsFile, $functionPointer)), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + $parameterName + ), + $parametersAnnotations[$parameterName]->getStartPointer(), + self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION + ); + } + + if ($isSniffSuppressed && $suppressUseless) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $suppressName); + } + } + + /** + * @param array $parametersTypeHints + * @param array $parametersAnnotations + */ + private function checkUselessAnnotations( + File $phpcsFile, + int $functionPointer, + array $parametersTypeHints, + array $parametersAnnotations + ): void + { + $suppressName = self::getSniffName(self::CODE_USELESS_ANNOTATION); + $isSniffSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressName); + $suppressUseless = true; + + foreach ($parametersTypeHints as $parameterName => $parameterTypeHint) { + if (!array_key_exists($parameterName, $parametersAnnotations)) { + continue; + } + + $parameterAnnotation = $parametersAnnotations[$parameterName]; + + if ($parameterAnnotation->getValue() instanceof TypelessParamTagValueNode) { + continue; + } + + if (!AnnotationHelper::isAnnotationUseless( + $phpcsFile, + $functionPointer, + $parameterTypeHint, + $parameterAnnotation, + $this->getTraversableTypeHints(), + $this->enableUnionTypeHint, + $this->enableIntersectionTypeHint, + $this->enableStandaloneNullTrueFalseTypeHints + )) { + continue; + } + + $suppressUseless = false; + + if ($isSniffSuppressed) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + '%s %s() has useless @param annotation for parameter %s.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + $parameterName + ), + $parameterAnnotation->getStartPointer(), + self::CODE_USELESS_ANNOTATION + ); + if (!$fix) { + continue; + } + + $docCommentOpenPointer = $parameterAnnotation->getValue() instanceof VarTagValueNode + ? TokenHelper::findPrevious($phpcsFile, T_DOC_COMMENT_OPEN_TAG, $parameterAnnotation->getStartPointer() - 1) + : DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $functionPointer); + + $starPointer = TokenHelper::findPrevious( + $phpcsFile, + T_DOC_COMMENT_STAR, + $parameterAnnotation->getStartPointer() - 1, + $docCommentOpenPointer + ); + + $changeStart = $starPointer ?? $parameterAnnotation->getStartPointer(); + /** @var int $changeEnd */ + $changeEnd = TokenHelper::findNext( + $phpcsFile, + [T_DOC_COMMENT_CLOSE_TAG, T_DOC_COMMENT_STAR], + $parameterAnnotation->getEndPointer() + ) - 1; + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $changeStart, $changeEnd); + $phpcsFile->fixer->endChangeset(); + } + + if ($isSniffSuppressed && $suppressUseless) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $suppressName); + } + } + + private function reportUselessSuppress(File $phpcsFile, int $pointer, string $suppressName): void + { + $fix = $phpcsFile->addFixableError( + sprintf('Useless %s %s', SuppressHelper::ANNOTATION, $suppressName), + $pointer, + self::CODE_USELESS_SUPPRESS + ); + + if ($fix) { + SuppressHelper::removeSuppressAnnotation($phpcsFile, $pointer, $suppressName); + } + } + + private function getSniffName(string $sniffName): string + { + return sprintf('%s.%s', self::NAME, $sniffName); + } + + /** + * @return list + */ + private function getTraversableTypeHints(): array + { + if ($this->normalizedTraversableTypeHints === null) { + $this->normalizedTraversableTypeHints = array_map(static function (string $typeHint): string { + return NamespaceHelper::isFullyQualifiedName($typeHint) + ? $typeHint + : sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $typeHint); + }, SniffSettingsHelper::normalizeArray($this->traversableTypeHints)); + } + return $this->normalizedTraversableTypeHints; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSpacingSniff.php new file mode 100644 index 000000000..69beededb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ParameterTypeHintSpacingSniff.php @@ -0,0 +1,154 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $parametersStartPointer = $tokens[$functionPointer]['parenthesis_opener'] + 1; + $parametersEndPointer = $tokens[$functionPointer]['parenthesis_closer'] - 1; + + $typeHintTokenCodes = TokenHelper::getTypeHintTokenCodes(); + + for ($i = $parametersStartPointer; $i <= $parametersEndPointer; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + $parameterPointer = $i; + $parameterName = $tokens[$parameterPointer]['content']; + + $parameterStartPointer = TokenHelper::findPrevious($phpcsFile, T_COMMA, $parameterPointer - 1, $parametersStartPointer); + if ($parameterStartPointer === null) { + $parameterStartPointer = $parametersStartPointer; + } + + $parameterEndPointer = TokenHelper::findNext($phpcsFile, T_COMMA, $parameterPointer + 1, $parametersEndPointer + 1); + if ($parameterEndPointer === null) { + $parameterEndPointer = $parametersEndPointer; + } + + $attributeCloserPointer = TokenHelper::findPrevious($phpcsFile, T_ATTRIBUTE_END, $parameterPointer - 1, $parameterStartPointer); + + $typeHintEndPointer = TokenHelper::findPrevious( + $phpcsFile, + $typeHintTokenCodes, + $parameterPointer - 1, + $attributeCloserPointer ?? $parameterStartPointer + ); + if ($typeHintEndPointer === null) { + continue; + } + + $typeHintStartPointer = TypeHintHelper::getStartPointer($phpcsFile, $typeHintEndPointer); + + $nextTokenNames = [ + T_VARIABLE => sprintf('parameter %s', $parameterName), + T_BITWISE_AND => sprintf('reference sign of parameter %s', $parameterName), + T_ELLIPSIS => sprintf('varadic parameter %s', $parameterName), + ]; + $nextTokenPointer = TokenHelper::findNext( + $phpcsFile, + array_keys($nextTokenNames), + $typeHintEndPointer + 1, + $parameterEndPointer + 1 + ); + + if ($tokens[$typeHintEndPointer + 1]['code'] !== T_WHITESPACE) { + $fix = $phpcsFile->addFixableError( + sprintf( + 'There must be exactly one space between parameter type hint and %s.', + $nextTokenNames[$tokens[$nextTokenPointer]['code']] + ), + $typeHintEndPointer, + self::CODE_NO_SPACE_BETWEEN_TYPE_HINT_AND_PARAMETER + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($typeHintEndPointer, ' '); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$typeHintEndPointer + 1]['content'] !== ' ') { + $fix = $phpcsFile->addFixableError( + sprintf( + 'There must be exactly one space between parameter type hint and %s.', + $nextTokenNames[$tokens[$nextTokenPointer]['code']] + ), + $typeHintEndPointer, + self::CODE_MULTIPLE_SPACES_BETWEEN_TYPE_HINT_AND_PARAMETER + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($typeHintEndPointer + 1, ' '); + $phpcsFile->fixer->endChangeset(); + } + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $typeHintStartPointer - 1, $parameterStartPointer); + $nullabilitySymbolPointer = $previousPointer !== null && $tokens[$previousPointer]['code'] === T_NULLABLE + ? $previousPointer + : null; + + if ($nullabilitySymbolPointer === null) { + continue; + } + + if ($nullabilitySymbolPointer + 1 === $typeHintStartPointer) { + continue; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'There must be no whitespace between parameter type hint nullability symbol and parameter type hint of parameter %s.', + $parameterName + ), + $typeHintStartPointer, + self::CODE_WHITESPACE_AFTER_NULLABILITY_SYMBOL + ); + if (!$fix) { + continue; + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($nullabilitySymbolPointer + 1, ''); + $phpcsFile->fixer->endChangeset(); + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/PropertyTypeHintSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/PropertyTypeHintSniff.php new file mode 100644 index 000000000..82a100fdd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/PropertyTypeHintSniff.php @@ -0,0 +1,692 @@ + */ + public $traversableTypeHints = []; + + /** @var array|null */ + private $normalizedTraversableTypeHints; + + /** + * @return array + */ + public function register(): array + { + return [ + T_VAR, + T_PUBLIC, + T_PROTECTED, + T_PRIVATE, + T_STATIC, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->enableNativeTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableNativeTypeHint, 70400); + $this->enableMixedTypeHint = $this->enableNativeTypeHint + ? SniffSettingsHelper::isEnabledByPhpVersion($this->enableMixedTypeHint, 80000) + : false; + $this->enableUnionTypeHint = $this->enableNativeTypeHint + ? SniffSettingsHelper::isEnabledByPhpVersion($this->enableUnionTypeHint, 80000) + : false; + $this->enableIntersectionTypeHint = $this->enableNativeTypeHint + ? SniffSettingsHelper::isEnabledByPhpVersion($this->enableIntersectionTypeHint, 80100) + : false; + $this->enableStandaloneNullTrueFalseTypeHints = $this->enableNativeTypeHint + ? SniffSettingsHelper::isEnabledByPhpVersion($this->enableStandaloneNullTrueFalseTypeHints, 80200) + : false; + + $tokens = $phpcsFile->getTokens(); + + $asPointer = TokenHelper::findPreviousEffective($phpcsFile, $pointer - 1); + if ($tokens[$asPointer]['code'] === T_AS) { + return; + } + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + if (in_array($tokens[$nextPointer]['code'], [T_VAR, T_PUBLIC, T_PROTECTED, T_PRIVATE, T_READONLY, T_STATIC], true)) { + // We don't want to report the same property twice + return; + } + + $propertyPointer = TokenHelper::findNext($phpcsFile, [T_FUNCTION, T_CONST, T_VARIABLE], $pointer + 1); + + if ($propertyPointer === null || $tokens[$propertyPointer]['code'] !== T_VARIABLE) { + return; + } + + if (!PropertyHelper::isProperty($phpcsFile, $propertyPointer)) { + return; + } + + if (SuppressHelper::isSniffSuppressed($phpcsFile, $propertyPointer, self::NAME)) { + return; + } + + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $propertyPointer); + if ($docCommentOpenPointer !== null) { + if (DocCommentHelper::hasInheritdocAnnotation($phpcsFile, $docCommentOpenPointer)) { + return; + } + + $varAnnotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer, '@var'); + $prefixedPropertyAnnotations = $this->getValidPrefixedAnnotations($phpcsFile, $docCommentOpenPointer); + + $propertyAnnotation = count($varAnnotations) > 0 ? current($varAnnotations) : null; + } else { + $propertyAnnotation = null; + $prefixedPropertyAnnotations = []; + } + + $propertyTypeHint = PropertyHelper::findTypeHint($phpcsFile, $propertyPointer); + + $this->checkTypeHint($phpcsFile, $propertyPointer, $propertyTypeHint, $propertyAnnotation, $prefixedPropertyAnnotations); + $this->checkTraversableTypeHintSpecification( + $phpcsFile, + $propertyPointer, + $propertyTypeHint, + $propertyAnnotation, + $prefixedPropertyAnnotations + ); + $this->checkUselessAnnotation($phpcsFile, $propertyPointer, $propertyTypeHint, $propertyAnnotation); + } + + /** + * @param Annotation|null $propertyAnnotation + * @param list> $prefixedPropertyAnnotations + */ + private function checkTypeHint( + File $phpcsFile, + int $propertyPointer, + ?TypeHint $propertyTypeHint, + ?Annotation $propertyAnnotation, + array $prefixedPropertyAnnotations + ): void + { + $suppressNameAnyTypeHint = $this->getSniffName(self::CODE_MISSING_ANY_TYPE_HINT); + $isSuppressedAnyTypeHint = SuppressHelper::isSniffSuppressed($phpcsFile, $propertyPointer, $suppressNameAnyTypeHint); + + $suppressNameNativeTypeHint = $this->getSniffName(self::CODE_MISSING_NATIVE_TYPE_HINT); + $isSuppressedNativeTypeHint = SuppressHelper::isSniffSuppressed($phpcsFile, $propertyPointer, $suppressNameNativeTypeHint); + + if ($propertyTypeHint !== null) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedAnyTypeHint, $suppressNameAnyTypeHint); + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + if (!$this->hasAnnotation($propertyAnnotation)) { + if (count($prefixedPropertyAnnotations) !== 0) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedAnyTypeHint, $suppressNameAnyTypeHint); + return; + } + + if (!$isSuppressedAnyTypeHint) { + $phpcsFile->addError( + sprintf( + $this->enableNativeTypeHint + ? 'Property %s does not have native type hint nor @var annotation for its value.' + : 'Property %s does not have @var annotation for its value.', + PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer) + ), + $propertyPointer, + self::CODE_MISSING_ANY_TYPE_HINT + ); + } + + return; + } + + if (!$this->enableNativeTypeHint) { + return; + } + + $typeNode = $propertyAnnotation->getValue()->type; + $originalTypeNode = $typeNode; + if ($typeNode instanceof NullableTypeNode) { + $typeNode = $typeNode->type; + } + + $canTryUnionTypeHint = $this->enableUnionTypeHint && $typeNode instanceof UnionTypeNode; + + $typeHints = []; + $traversableTypeHints = []; + $nullableTypeHint = false; + + if (AnnotationTypeHelper::containsOneType($typeNode)) { + /** @var ArrayTypeNode|ArrayShapeNode|ObjectShapeNode|IdentifierTypeNode|ThisTypeNode|GenericTypeNode|CallableTypeNode $typeNode */ + $typeNode = $typeNode; + $typeHints[] = AnnotationTypeHelper::getTypeHintFromOneType($typeNode, false, $this->enableStandaloneNullTrueFalseTypeHints); + + } elseif ($typeNode instanceof UnionTypeNode || $typeNode instanceof IntersectionTypeNode) { + $traversableTypeHints = []; + foreach ($typeNode->types as $innerTypeNode) { + if (!AnnotationTypeHelper::containsOneType($innerTypeNode)) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + /** @var ArrayTypeNode|ArrayShapeNode|ObjectShapeNode|IdentifierTypeNode|ThisTypeNode|GenericTypeNode|CallableTypeNode $innerTypeNode */ + $innerTypeNode = $innerTypeNode; + + $typeHint = AnnotationTypeHelper::getTypeHintFromOneType($innerTypeNode, $canTryUnionTypeHint); + + if (strtolower($typeHint) === 'null') { + $nullableTypeHint = true; + continue; + } + + $isTraversable = TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $propertyPointer, $typeHint), + $this->getTraversableTypeHints() + ); + + if ( + !$innerTypeNode instanceof ArrayTypeNode + && !$innerTypeNode instanceof ArrayShapeNode + && $isTraversable + ) { + $traversableTypeHints[] = $typeHint; + } + + $typeHints[] = $typeHint; + } + + $traversableTypeHints = array_values(array_unique($traversableTypeHints)); + if (count($traversableTypeHints) > 1 && !$canTryUnionTypeHint) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + } + + $typeHints = array_values(array_unique($typeHints)); + + if (count($traversableTypeHints) > 0) { + /** @var UnionTypeNode|IntersectionTypeNode $typeNode */ + $typeNode = $typeNode; + + $itemsSpecificationTypeHint = AnnotationTypeHelper::getItemsSpecificationTypeFromType($typeNode); + if ($itemsSpecificationTypeHint !== null) { + $typeHints = AnnotationTypeHelper::getTraversableTypeHintsFromType( + $typeNode, + $phpcsFile, + $propertyPointer, + $this->getTraversableTypeHints(), + $this->enableUnionTypeHint + ); + } + } + + if (count($typeHints) === 0) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + $typeHintsWithConvertedUnion = []; + foreach ($typeHints as $typeHint) { + if ($this->enableUnionTypeHint && TypeHintHelper::isUnofficialUnionTypeHint($typeHint)) { + $canTryUnionTypeHint = true; + $typeHintsWithConvertedUnion = array_merge( + $typeHintsWithConvertedUnion, + TypeHintHelper::convertUnofficialUnionTypeHintToOfficialTypeHints($typeHint) + ); + } else { + $typeHintsWithConvertedUnion[] = $typeHint; + } + } + $typeHintsWithConvertedUnion = array_unique($typeHintsWithConvertedUnion); + + if ( + count($typeHintsWithConvertedUnion) > 1 + && ( + ($typeNode instanceof UnionTypeNode && !$canTryUnionTypeHint) + || ($typeNode instanceof IntersectionTypeNode && !$this->enableIntersectionTypeHint) + ) + ) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + foreach ($typeHintsWithConvertedUnion as $typeHintNo => $typeHint) { + if ($typeHint === 'callable') { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + if ($canTryUnionTypeHint && $typeHint === 'false') { + continue; + } + + if (!TypeHintHelper::isValidTypeHint( + $typeHint, + true, + false, + $this->enableMixedTypeHint, + $this->enableStandaloneNullTrueFalseTypeHints + )) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + if (TypeHintHelper::isTypeDefinedInAnnotation($phpcsFile, $propertyPointer, $typeHint)) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + $typeHintsWithConvertedUnion[$typeHintNo] = TypeHintHelper::convertLongSimpleTypeHintToShort($typeHint); + } + + if ($originalTypeNode instanceof NullableTypeNode) { + $nullableTypeHint = true; + } + + if ($isSuppressedNativeTypeHint) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Property %s does not have native type hint for its value but it should be possible to add it based on @var annotation "%s".', + PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer), + AnnotationTypeHelper::print($typeNode) + ), + $propertyPointer, + self::CODE_MISSING_NATIVE_TYPE_HINT + ); + if (!$fix) { + return; + } + + if (in_array('mixed', $typeHintsWithConvertedUnion, true)) { + $propertyTypeHint = 'mixed'; + } elseif ($originalTypeNode instanceof IntersectionTypeNode) { + $propertyTypeHint = implode('&', $typeHintsWithConvertedUnion); + } else { + $propertyTypeHint = implode('|', $typeHintsWithConvertedUnion); + if ($nullableTypeHint) { + if (count($typeHintsWithConvertedUnion) > 1) { + $propertyTypeHint .= '|null'; + } else { + $propertyTypeHint = '?' . $propertyTypeHint; + } + } + } + + $propertyStartPointer = TokenHelper::findPrevious( + $phpcsFile, + [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_VAR, T_STATIC, T_READONLY], + $propertyPointer - 1 + ); + + $tokens = $phpcsFile->getTokens(); + + $pointerAfterProperty = null; + if ($nullableTypeHint) { + $pointerAfterProperty = TokenHelper::findNextEffective($phpcsFile, $propertyPointer + 1); + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($propertyStartPointer, sprintf(' %s', $propertyTypeHint)); + + if ( + $pointerAfterProperty !== null + && in_array($tokens[$pointerAfterProperty]['code'], [T_SEMICOLON, T_COMMA], true) + ) { + $phpcsFile->fixer->addContent($propertyPointer, ' = null'); + } + + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param Annotation|null $propertyAnnotation + * @param list> $prefixedPropertyAnnotations + */ + private function checkTraversableTypeHintSpecification( + File $phpcsFile, + int $propertyPointer, + ?TypeHint $propertyTypeHint, + ?Annotation $propertyAnnotation, + array $prefixedPropertyAnnotations + ): void + { + $suppressName = $this->getSniffName(self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION); + $isSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $propertyPointer, $suppressName); + + $hasTraversableTypeHint = $this->hasTraversableTypeHint($phpcsFile, $propertyPointer, $propertyTypeHint, $propertyAnnotation); + $hasAnnotation = $this->hasAnnotation($propertyAnnotation); + + if (!$hasAnnotation) { + if ($hasTraversableTypeHint) { + if (count($prefixedPropertyAnnotations) !== 0) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressed, $suppressName); + return; + } + + if (!$isSuppressed) { + $phpcsFile->addError( + sprintf( + '@var annotation of property %s does not specify type hint for its items.', + PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer) + ), + $propertyPointer, + self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION + ); + } + } + + return; + } + + $typeNode = $propertyAnnotation->getValue()->type; + + if ( + !$hasTraversableTypeHint + && !AnnotationTypeHelper::containsTraversableType($typeNode, $phpcsFile, $propertyPointer, $this->getTraversableTypeHints()) + ) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressed, $suppressName); + return; + } + + if (AnnotationTypeHelper::containsItemsSpecificationForTraversable( + $typeNode, + $phpcsFile, + $propertyPointer, + $this->getTraversableTypeHints() + )) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressed, $suppressName); + return; + } + + if ($isSuppressed) { + return; + } + + $phpcsFile->addError( + sprintf( + '@var annotation of property %s does not specify type hint for its items.', + PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer) + ), + $propertyAnnotation->getStartPointer(), + self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION + ); + } + + private function checkUselessAnnotation( + File $phpcsFile, + int $propertyPointer, + ?TypeHint $propertyTypeHint, + ?Annotation $propertyAnnotation + ): void + { + if ($propertyAnnotation === null) { + return; + } + + $suppressName = self::getSniffName(self::CODE_USELESS_ANNOTATION); + $isSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $propertyPointer, $suppressName); + + if (!AnnotationHelper::isAnnotationUseless( + $phpcsFile, + $propertyPointer, + $propertyTypeHint, + $propertyAnnotation, + $this->getTraversableTypeHints(), + $this->enableUnionTypeHint, + $this->enableIntersectionTypeHint, + $this->enableStandaloneNullTrueFalseTypeHints + )) { + $this->reportUselessSuppress($phpcsFile, $propertyPointer, $isSuppressed, $suppressName); + return; + } + + if ($isSuppressed) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + 'Property %s has useless @var annotation.', + PropertyHelper::getFullyQualifiedName($phpcsFile, $propertyPointer) + ), + $propertyAnnotation->getStartPointer(), + self::CODE_USELESS_ANNOTATION + ); + + if (!$fix) { + return; + } + + if ($this->isDocCommentUseless($phpcsFile, $propertyPointer)) { + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $propertyPointer); + $docCommentClosePointer = $phpcsFile->getTokens()[$docCommentOpenPointer]['comment_closer']; + + $changeStart = $docCommentOpenPointer; + /** @var int $changeEnd */ + $changeEnd = TokenHelper::findNextEffective($phpcsFile, $docCommentClosePointer + 1) - 1; + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $changeStart, $changeEnd); + $phpcsFile->fixer->endChangeset(); + + return; + } + + /** @var int $changeStart */ + $changeStart = TokenHelper::findPrevious($phpcsFile, T_DOC_COMMENT_STAR, $propertyAnnotation->getStartPointer() - 1); + + /** @var int $changeEnd */ + $changeEnd = TokenHelper::findNext( + $phpcsFile, + [T_DOC_COMMENT_CLOSE_TAG, T_DOC_COMMENT_STAR], + $propertyAnnotation->getEndPointer() + 1 + ) - 1; + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $changeStart, $changeEnd); + $phpcsFile->fixer->endChangeset(); + } + + private function isDocCommentUseless(File $phpcsFile, int $propertyPointer): bool + { + if (DocCommentHelper::hasDocCommentDescription($phpcsFile, $propertyPointer)) { + return false; + } + + foreach (AnnotationHelper::getAnnotations($phpcsFile, $propertyPointer) as $annotation) { + if ($annotation->getName() !== '@var') { + return false; + } + } + + return true; + } + + private function reportUselessSuppress(File $phpcsFile, int $pointer, bool $isSuppressed, string $suppressName): void + { + if (!$isSuppressed) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Useless %s %s', SuppressHelper::ANNOTATION, $suppressName), + $pointer, + self::CODE_USELESS_SUPPRESS + ); + + if ($fix) { + SuppressHelper::removeSuppressAnnotation($phpcsFile, $pointer, $suppressName); + } + } + + private function getSniffName(string $sniffName): string + { + return sprintf('%s.%s', self::NAME, $sniffName); + } + + /** + * @return list + */ + private function getTraversableTypeHints(): array + { + if ($this->normalizedTraversableTypeHints === null) { + $this->normalizedTraversableTypeHints = array_map(static function (string $typeHint): string { + return NamespaceHelper::isFullyQualifiedName($typeHint) + ? $typeHint + : sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $typeHint); + }, SniffSettingsHelper::normalizeArray($this->traversableTypeHints)); + } + return $this->normalizedTraversableTypeHints; + } + + private function hasAnnotation(?Annotation $propertyAnnotation): bool + { + return $propertyAnnotation !== null && $propertyAnnotation->getValue() instanceof VarTagValueNode; + } + + /** + * @param Annotation|null $propertyAnnotation + */ + private function hasTraversableTypeHint( + File $phpcsFile, + int $propertyPointer, + ?TypeHint $propertyTypeHint, + ?Annotation $propertyAnnotation + ): bool + { + if ( + $propertyTypeHint !== null + && TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint( + $phpcsFile, + $propertyPointer, + $propertyTypeHint->getTypeHintWithoutNullabilitySymbol() + ), + $this->getTraversableTypeHints() + ) + ) { + return true; + } + + return + $this->hasAnnotation($propertyAnnotation) + && AnnotationTypeHelper::containsTraversableType( + $propertyAnnotation->getValue()->type, + $phpcsFile, + $propertyPointer, + $this->getTraversableTypeHints() + ); + } + + /** + * @return list> + */ + private function getValidPrefixedAnnotations(File $phpcsFile, int $docCommentOpenPointer): array + { + $varAnnotations = []; + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $docCommentOpenPointer); + + foreach (AnnotationHelper::STATIC_ANALYSIS_PREFIXES as $prefix) { + foreach ($annotations as $annotation) { + if ($annotation->isInvalid()) { + continue; + } + + if ($annotation->getName() === sprintf('@%s-var', $prefix)) { + $varAnnotations[] = $annotation; + } + } + } + + return $varAnnotations; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSniff.php new file mode 100644 index 000000000..594dc77f7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSniff.php @@ -0,0 +1,732 @@ + */ + public $traversableTypeHints = []; + + /** @var array|null */ + private $normalizedTraversableTypeHints; + + /** + * @return array + */ + public function register(): array + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->enableObjectTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableObjectTypeHint, 70200); + $this->enableStaticTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableStaticTypeHint, 80000); + $this->enableMixedTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableMixedTypeHint, 80000); + $this->enableUnionTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableUnionTypeHint, 80000); + $this->enableIntersectionTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableIntersectionTypeHint, 80100); + $this->enableNeverTypeHint = SniffSettingsHelper::isEnabledByPhpVersion($this->enableNeverTypeHint, 80100); + $this->enableStandaloneNullTrueFalseTypeHints = SniffSettingsHelper::isEnabledByPhpVersion( + $this->enableStandaloneNullTrueFalseTypeHints, + 80200 + ); + + if (SuppressHelper::isSniffSuppressed($phpcsFile, $pointer, self::NAME)) { + return; + } + + if (DocCommentHelper::hasInheritdocAnnotation($phpcsFile, $pointer)) { + return; + } + + $token = $phpcsFile->getTokens()[$pointer]; + + if ($token['code'] === T_FUNCTION) { + $returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $pointer); + $returnAnnotation = FunctionHelper::findReturnAnnotation($phpcsFile, $pointer); + $prefixedReturnAnnotations = FunctionHelper::getValidPrefixedReturnAnnotations($phpcsFile, $pointer); + + $this->checkFunctionTypeHint($phpcsFile, $pointer, $returnTypeHint, $returnAnnotation, $prefixedReturnAnnotations); + $this->checkFunctionTraversableTypeHintSpecification( + $phpcsFile, + $pointer, + $returnTypeHint, + $returnAnnotation, + $prefixedReturnAnnotations + ); + $this->checkFunctionUselessAnnotation($phpcsFile, $pointer, $returnTypeHint, $returnAnnotation); + } elseif ($token['code'] === T_CLOSURE) { + $this->checkClosureTypeHint($phpcsFile, $pointer); + } + } + + /** + * @param list $prefixedReturnAnnotations + */ + private function checkFunctionTypeHint( + File $phpcsFile, + int $functionPointer, + ?TypeHint $returnTypeHint, + ?Annotation $returnAnnotation, + array $prefixedReturnAnnotations + ): void + { + $suppressNameAnyTypeHint = $this->getSniffName(self::CODE_MISSING_ANY_TYPE_HINT); + $isSuppressedAnyTypeHint = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressNameAnyTypeHint); + + $suppressNameNativeTypeHint = $this->getSniffName(self::CODE_MISSING_NATIVE_TYPE_HINT); + $isSuppressedNativeTypeHint = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressNameNativeTypeHint); + + $hasReturnAnnotation = $this->hasReturnAnnotation($returnAnnotation); + $returnTypeNode = $this->getReturnTypeNode($returnAnnotation); + $isAnnotationReturnTypeNever = $returnTypeNode instanceof IdentifierTypeNode + && TypeHintHelper::isNeverTypeHint(strtolower($returnTypeNode->name)); + + if ($returnTypeHint !== null) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedAnyTypeHint, $suppressNameAnyTypeHint); + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + + if ($this->enableNeverTypeHint && $returnTypeHint->getTypeHint() === 'void' && $isAnnotationReturnTypeNever) { + $fix = $phpcsFile->addFixableError( + sprintf( + '%s %s() has return type hint "void" but it should be possible to add "never" based on @return annotation "%s".', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + AnnotationTypeHelper::print($returnTypeNode) + ), + $functionPointer, + self::CODE_LESS_SPECIFIC_NATIVE_TYPE_HINT + ); + + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($returnTypeHint->getStartPointer(), 'never'); + $phpcsFile->fixer->endChangeset(); + } + } + + return; + } + + $methodsWithoutVoidSupport = ['__construct' => true, '__destruct' => true, '__clone' => true]; + + if (array_key_exists(FunctionHelper::getName($phpcsFile, $functionPointer), $methodsWithoutVoidSupport)) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedAnyTypeHint, $suppressNameAnyTypeHint); + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + $isAnnotationReturnTypeVoidOrNever = $returnTypeNode instanceof IdentifierTypeNode + && ( + TypeHintHelper::isVoidTypeHint(strtolower($returnTypeNode->name)) + || $isAnnotationReturnTypeNever + ); + + $isAbstract = FunctionHelper::isAbstract($phpcsFile, $functionPointer); + $returnsValue = $isAbstract + ? ($hasReturnAnnotation && !$isAnnotationReturnTypeVoidOrNever) + : FunctionHelper::returnsValue($phpcsFile, $functionPointer); + + if ($returnsValue && !$hasReturnAnnotation) { + if (count($prefixedReturnAnnotations) !== 0) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedAnyTypeHint, $suppressNameAnyTypeHint); + return; + } + + if (!$isSuppressedAnyTypeHint) { + $phpcsFile->addError( + sprintf( + '%s %s() does not have return type hint nor @return annotation for its return value.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer) + ), + $functionPointer, + self::CODE_MISSING_ANY_TYPE_HINT + ); + } + + return; + } + + if ( + !$returnsValue + && ( + !$hasReturnAnnotation + || $isAnnotationReturnTypeVoidOrNever + ) + ) { + if (!$isSuppressedNativeTypeHint) { + $message = !$hasReturnAnnotation + ? sprintf( + '%s %s() does not have void return type hint.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer) + ) + : sprintf( + '%s %s() does not have native return type hint for its return value but it should be possible to add it based on @return annotation "%s".', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + AnnotationTypeHelper::print($returnTypeNode) + ); + + $fix = $phpcsFile->addFixableError($message, $functionPointer, self::getSniffName(self::CODE_MISSING_NATIVE_TYPE_HINT)); + + if ($fix) { + $fixedReturnType = $this->enableNeverTypeHint && $isAnnotationReturnTypeNever + ? 'never' + : 'void'; + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( + $phpcsFile->getTokens()[$functionPointer]['parenthesis_closer'], + sprintf(': %s', $fixedReturnType) + ); + $phpcsFile->fixer->endChangeset(); + } + } + + return; + } + + if (!$isSuppressedNativeTypeHint && $returnsValue && $isAnnotationReturnTypeVoidOrNever) { + $message = sprintf( + '%s %s() does not have native return type hint for its return value but it should be possible to add it based on @return annotation "%s".', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + AnnotationTypeHelper::print($returnTypeNode) + ); + + $phpcsFile->addError($message, $functionPointer, self::getSniffName(self::CODE_MISSING_NATIVE_TYPE_HINT)); + return; + } + + $canTryUnionTypeHint = $this->enableUnionTypeHint && $returnTypeNode instanceof UnionTypeNode; + + $typeHints = []; + $traversableTypeHints = []; + $nullableReturnTypeHint = false; + + $originalReturnTypeNode = $returnTypeNode; + if ($returnTypeNode instanceof NullableTypeNode) { + $returnTypeNode = $returnTypeNode->type; + } + + if (AnnotationTypeHelper::containsOneType($returnTypeNode)) { + /** @var ArrayTypeNode|ArrayShapeNode|ObjectShapeNode|IdentifierTypeNode|ThisTypeNode|GenericTypeNode|CallableTypeNode $returnTypeNode */ + $returnTypeNode = $returnTypeNode; + $typeHints[] = AnnotationTypeHelper::getTypeHintFromOneType( + $returnTypeNode, + false, + $this->enableStandaloneNullTrueFalseTypeHints + ); + + } elseif ($returnTypeNode instanceof UnionTypeNode || $returnTypeNode instanceof IntersectionTypeNode) { + $traversableTypeHints = []; + foreach ($returnTypeNode->types as $typeNode) { + if (!AnnotationTypeHelper::containsOneType($typeNode)) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + /** @var ArrayTypeNode|ArrayShapeNode|ObjectShapeNode|IdentifierTypeNode|ThisTypeNode|GenericTypeNode|CallableTypeNode $typeNode */ + $typeNode = $typeNode; + + $typeHint = AnnotationTypeHelper::getTypeHintFromOneType($typeNode, $canTryUnionTypeHint); + + if (strtolower($typeHint) === 'null') { + $nullableReturnTypeHint = true; + continue; + } + + $isTraversable = TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $functionPointer, $typeHint), + $this->getTraversableTypeHints() + ); + + if ( + !$typeNode instanceof ArrayTypeNode + && !$typeNode instanceof ArrayShapeNode + && $isTraversable + ) { + $traversableTypeHints[] = $typeHint; + } + + $typeHints[] = $typeHint; + } + + $traversableTypeHints = array_values(array_unique($traversableTypeHints)); + if (count($traversableTypeHints) > 1 && !$canTryUnionTypeHint) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + } + + $typeHints = array_values(array_unique($typeHints)); + + if (count($traversableTypeHints) > 0) { + /** @var UnionTypeNode|IntersectionTypeNode $returnTypeNode */ + $returnTypeNode = $returnTypeNode; + + $itemsSpecificationTypeHint = AnnotationTypeHelper::getItemsSpecificationTypeFromType($returnTypeNode); + if ($itemsSpecificationTypeHint !== null) { + $typeHints = AnnotationTypeHelper::getTraversableTypeHintsFromType( + $returnTypeNode, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints(), + $canTryUnionTypeHint + ); + } + } + + if (count($typeHints) === 0) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + $typeHintsWithConvertedUnion = []; + foreach ($typeHints as $typeHint) { + if ($this->enableUnionTypeHint && TypeHintHelper::isUnofficialUnionTypeHint($typeHint)) { + $canTryUnionTypeHint = true; + $typeHintsWithConvertedUnion = array_merge( + $typeHintsWithConvertedUnion, + TypeHintHelper::convertUnofficialUnionTypeHintToOfficialTypeHints($typeHint) + ); + } else { + $typeHintsWithConvertedUnion[] = $typeHint; + } + } + $typeHintsWithConvertedUnion = array_unique($typeHintsWithConvertedUnion); + + if ( + count($typeHintsWithConvertedUnion) > 1 + && ( + ($returnTypeNode instanceof UnionTypeNode && !$canTryUnionTypeHint) + || ($returnTypeNode instanceof IntersectionTypeNode && !$this->enableIntersectionTypeHint) + ) + ) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + foreach ($typeHintsWithConvertedUnion as $typeHintNo => $typeHint) { + if ($canTryUnionTypeHint && $typeHint === 'false') { + continue; + } + + if (!TypeHintHelper::isValidTypeHint( + $typeHint, + $this->enableObjectTypeHint, + $this->enableStaticTypeHint, + $this->enableMixedTypeHint, + $this->enableStandaloneNullTrueFalseTypeHints + )) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + if (TypeHintHelper::isTypeDefinedInAnnotation($phpcsFile, $functionPointer, $typeHint)) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressedNativeTypeHint, $suppressNameNativeTypeHint); + return; + } + + $typeHintsWithConvertedUnion[$typeHintNo] = TypeHintHelper::isVoidTypeHint($typeHint) + ? 'null' + : TypeHintHelper::convertLongSimpleTypeHintToShort($typeHint); + } + + if ($originalReturnTypeNode instanceof NullableTypeNode) { + $nullableReturnTypeHint = true; + } + + if ($isSuppressedNativeTypeHint) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + '%s %s() does not have native return type hint for its return value but it should be possible to add it based on @return annotation "%s".', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer), + AnnotationTypeHelper::print($returnTypeNode) + ), + $functionPointer, + self::CODE_MISSING_NATIVE_TYPE_HINT + ); + if (!$fix) { + return; + } + + if (in_array('mixed', $typeHintsWithConvertedUnion, true)) { + $returnTypeHint = 'mixed'; + } elseif ($originalReturnTypeNode instanceof IntersectionTypeNode) { + $returnTypeHint = implode('&', $typeHintsWithConvertedUnion); + } else { + $returnTypeHint = implode('|', $typeHintsWithConvertedUnion); + if ($nullableReturnTypeHint) { + if (count($typeHintsWithConvertedUnion) > 1) { + $returnTypeHint .= '|null'; + } else { + $returnTypeHint = '?' . $returnTypeHint; + } + } + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( + $phpcsFile->getTokens()[$functionPointer]['parenthesis_closer'], + sprintf(': %s', $returnTypeHint) + ); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param list $prefixedReturnAnnotations + */ + private function checkFunctionTraversableTypeHintSpecification( + File $phpcsFile, + int $functionPointer, + ?TypeHint $returnTypeHint, + ?Annotation $returnAnnotation, + array $prefixedReturnAnnotations + ): void + { + $suppressName = $this->getSniffName(self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION); + $isSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressName); + + $hasTraversableTypeHint = $this->hasTraversableTypeHint($phpcsFile, $functionPointer, $returnTypeHint, $returnAnnotation); + $hasReturnAnnotation = $this->hasReturnAnnotation($returnAnnotation); + + if (!$hasReturnAnnotation) { + if ($hasTraversableTypeHint) { + if (count($prefixedReturnAnnotations) !== 0) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressed, $suppressName); + return; + } + + if (!$isSuppressed) { + $phpcsFile->addError( + sprintf( + '%s %s() does not have @return annotation for its traversable return value.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer) + ), + $functionPointer, + self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION + ); + } + } + + return; + } + + $returnTypeNode = $this->getReturnTypeNode($returnAnnotation); + + if ( + !$hasTraversableTypeHint + && !AnnotationTypeHelper::containsTraversableType( + $returnTypeNode, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints() + ) + ) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressed, $suppressName); + return; + } + + if (AnnotationTypeHelper::containsItemsSpecificationForTraversable( + $returnTypeNode, + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints() + )) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressed, $suppressName); + return; + } + + if ($isSuppressed) { + return; + } + + /** @var Annotation $returnAnnotation */ + $returnAnnotation = $returnAnnotation; + + $phpcsFile->addError( + sprintf( + '@return annotation of %s %s() does not specify type hint for items of its traversable return value.', + lcfirst(FunctionHelper::getTypeLabel($phpcsFile, $functionPointer)), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer) + ), + $returnAnnotation->getStartPointer(), + self::CODE_MISSING_TRAVERSABLE_TYPE_HINT_SPECIFICATION + ); + } + + private function checkFunctionUselessAnnotation( + File $phpcsFile, + int $functionPointer, + ?TypeHint $returnTypeHint, + ?Annotation $returnAnnotation + ): void + { + if ($returnAnnotation === null) { + return; + } + + $suppressName = self::getSniffName(self::CODE_USELESS_ANNOTATION); + $isSuppressed = SuppressHelper::isSniffSuppressed($phpcsFile, $functionPointer, $suppressName); + + if (!AnnotationHelper::isAnnotationUseless( + $phpcsFile, + $functionPointer, + $returnTypeHint, + $returnAnnotation, + $this->getTraversableTypeHints(), + $this->enableUnionTypeHint, + $this->enableIntersectionTypeHint, + $this->enableStandaloneNullTrueFalseTypeHints + )) { + $this->reportUselessSuppress($phpcsFile, $functionPointer, $isSuppressed, $suppressName); + return; + } + + if ($isSuppressed) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf( + '%s %s() has useless @return annotation.', + FunctionHelper::getTypeLabel($phpcsFile, $functionPointer), + FunctionHelper::getFullyQualifiedName($phpcsFile, $functionPointer) + ), + $returnAnnotation->getStartPointer(), + self::CODE_USELESS_ANNOTATION + ); + + if (!$fix) { + return; + } + + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $functionPointer); + $starPointer = TokenHelper::findPrevious( + $phpcsFile, + T_DOC_COMMENT_STAR, + $returnAnnotation->getStartPointer() - 1, + $docCommentOpenPointer + ); + + $changeStart = $starPointer ?? $returnAnnotation->getStartPointer(); + + /** @var int $changeEnd */ + $changeEnd = TokenHelper::findNext( + $phpcsFile, + [T_DOC_COMMENT_CLOSE_TAG, T_DOC_COMMENT_STAR], + $returnAnnotation->getEndPointer() + 1 + ) - 1; + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $changeStart, $changeEnd); + $phpcsFile->fixer->endChangeset(); + } + + private function checkClosureTypeHint(File $phpcsFile, int $closurePointer): void + { + $returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $closurePointer); + $returnsValue = FunctionHelper::returnsValue($phpcsFile, $closurePointer); + + if ($returnsValue || $returnTypeHint !== null) { + return; + } + + $fix = $phpcsFile->addFixableError( + 'Closure does not have void return type hint.', + $closurePointer, + self::CODE_MISSING_NATIVE_TYPE_HINT + ); + + if (!$fix) { + return; + } + + $tokens = $phpcsFile->getTokens(); + /** @var int $position */ + $position = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$closurePointer]['scope_opener'] - 1, $closurePointer); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($position, ': void'); + $phpcsFile->fixer->endChangeset(); + } + + /** + * @param Annotation|null $returnAnnotation + */ + private function getReturnTypeNode(?Annotation $returnAnnotation): ?TypeNode + { + if ($this->hasReturnAnnotation($returnAnnotation)) { + return $returnAnnotation->getValue()->type; + } + + return null; + } + + private function hasTraversableTypeHint( + File $phpcsFile, + int $functionPointer, + ?TypeHint $returnTypeHint, + ?Annotation $returnAnnotation + ): bool + { + if ( + $returnTypeHint !== null + && TypeHintHelper::isTraversableType( + TypeHintHelper::getFullyQualifiedTypeHint( + $phpcsFile, + $functionPointer, + $returnTypeHint->getTypeHintWithoutNullabilitySymbol() + ), + $this->getTraversableTypeHints() + ) + ) { + return true; + } + + return + $this->hasReturnAnnotation($returnAnnotation) + && AnnotationTypeHelper::containsTraversableType( + $this->getReturnTypeNode($returnAnnotation), + $phpcsFile, + $functionPointer, + $this->getTraversableTypeHints() + ); + } + + private function hasReturnAnnotation(?Annotation $returnAnnotation): bool + { + return $returnAnnotation !== null && !$returnAnnotation->isInvalid(); + } + + private function reportUselessSuppress(File $phpcsFile, int $pointer, bool $isSuppressed, string $suppressName): void + { + if (!$isSuppressed) { + return; + } + + $fix = $phpcsFile->addFixableError( + sprintf('Useless %s %s', SuppressHelper::ANNOTATION, $suppressName), + $pointer, + self::CODE_USELESS_SUPPRESS + ); + + if ($fix) { + SuppressHelper::removeSuppressAnnotation($phpcsFile, $pointer, $suppressName); + } + } + + private function getSniffName(string $sniffName): string + { + return sprintf('%s.%s', self::NAME, $sniffName); + } + + /** + * @return array + */ + private function getTraversableTypeHints(): array + { + if ($this->normalizedTraversableTypeHints === null) { + $this->normalizedTraversableTypeHints = array_map(static function (string $typeHint): string { + return NamespaceHelper::isFullyQualifiedName($typeHint) + ? $typeHint + : sprintf('%s%s', NamespaceHelper::NAMESPACE_SEPARATOR, $typeHint); + }, SniffSettingsHelper::normalizeArray($this->traversableTypeHints)); + } + return $this->normalizedTraversableTypeHints; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSpacingSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSpacingSniff.php new file mode 100644 index 000000000..a2dda3496 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSpacingSniff.php @@ -0,0 +1,172 @@ + + */ + public function register(): array + { + return TokenHelper::$functionTokenCodes; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $functionPointer + */ + public function process(File $phpcsFile, $functionPointer): void + { + $this->spacesCountBeforeColon = SniffSettingsHelper::normalizeInteger($this->spacesCountBeforeColon); + + $typeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $functionPointer); + + if ($typeHint === null) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $typeHintStartPointer = $typeHint->getStartPointer(); + + /** @var int $colonPointer */ + $colonPointer = TokenHelper::findPreviousEffective($phpcsFile, $typeHintStartPointer - 1); + + if ($tokens[$typeHintStartPointer]['code'] !== T_NULLABLE) { + if ($tokens[$colonPointer + 1]['code'] !== T_WHITESPACE) { + $fix = $phpcsFile->addFixableError( + 'There must be exactly one space between return type hint colon and return type hint.', + $typeHintStartPointer, + self::CODE_NO_SPACE_BETWEEN_COLON_AND_TYPE_HINT + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($colonPointer, ' '); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$colonPointer + 1]['content'] !== ' ') { + $fix = $phpcsFile->addFixableError( + 'There must be exactly one space between return type hint colon and return type hint.', + $typeHintStartPointer, + self::CODE_MULTIPLE_SPACES_BETWEEN_COLON_AND_TYPE_HINT + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($colonPointer + 1, ' '); + $phpcsFile->fixer->endChangeset(); + } + } + } else { + if ($tokens[$colonPointer + 1]['code'] !== T_WHITESPACE) { + $fix = $phpcsFile->addFixableError( + 'There must be exactly one space between return type hint colon and return type hint nullability symbol.', + $typeHintStartPointer, + self::CODE_NO_SPACE_BETWEEN_COLON_AND_NULLABILITY_SYMBOL + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($colonPointer, ' '); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$colonPointer + 1]['content'] !== ' ') { + $fix = $phpcsFile->addFixableError( + 'There must be exactly one space between return type hint colon and return type hint nullability symbol.', + $typeHintStartPointer, + self::CODE_MULTIPLE_SPACES_BETWEEN_COLON_AND_NULLABILITY_SYMBOL + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($colonPointer + 1, ' '); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[$typeHintStartPointer + 1]['code'] === T_WHITESPACE) { + $fix = $phpcsFile->addFixableError( + 'There must be no whitespace between return type hint nullability symbol and return type hint.', + $typeHintStartPointer, + self::CODE_WHITESPACE_AFTER_NULLABILITY_SYMBOL + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($typeHintStartPointer + 1, ''); + $phpcsFile->fixer->endChangeset(); + } + } + } + + $expectedSpaces = str_repeat(' ', $this->spacesCountBeforeColon); + + if ( + $tokens[$colonPointer - 1]['code'] !== T_CLOSE_PARENTHESIS + && $tokens[$colonPointer - 1]['content'] !== $expectedSpaces + ) { + $fix = $this->spacesCountBeforeColon === 0 + ? $phpcsFile->addFixableError( + 'There must be no whitespace between closing parenthesis and return type colon.', + $typeHintStartPointer, + self::CODE_WHITESPACE_BEFORE_COLON + ) + : $phpcsFile->addFixableError( + sprintf( + 'There must be exactly %d whitespace%s between closing parenthesis and return type colon.', + $this->spacesCountBeforeColon, + $this->spacesCountBeforeColon !== 1 ? 's' : '' + ), + $typeHintStartPointer, + self::CODE_INCORRECT_SPACES_BEFORE_COLON + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($colonPointer - 1, $expectedSpaces); + $phpcsFile->fixer->endChangeset(); + } + } elseif ($tokens[$colonPointer - 1]['code'] === T_CLOSE_PARENTHESIS && $this->spacesCountBeforeColon !== 0) { + $fix = $phpcsFile->addFixableError( + sprintf( + 'There must be exactly %d whitespace%s between closing parenthesis and return type colon.', + $this->spacesCountBeforeColon, + $this->spacesCountBeforeColon !== 1 ? 's' : '' + ), + $typeHintStartPointer, + self::CODE_INCORRECT_SPACES_BEFORE_COLON + ); + if ($fix) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($colonPointer - 1, $expectedSpaces); + $phpcsFile->fixer->endChangeset(); + } + } + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UnionTypeHintFormatSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UnionTypeHintFormatSniff.php new file mode 100644 index 000000000..2e189487b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UnionTypeHintFormatSniff.php @@ -0,0 +1,248 @@ + + */ + public function register(): array + { + return array_merge( + [T_VARIABLE], + TokenHelper::$functionTokenCodes + ); + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $this->enable = SniffSettingsHelper::isEnabledByPhpVersion($this->enable, 80000); + + if (!$this->enable) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$pointer]['code'] === T_VARIABLE) { + if (!PropertyHelper::isProperty($phpcsFile, $pointer)) { + return; + } + + $propertyTypeHint = PropertyHelper::findTypeHint($phpcsFile, $pointer); + if ($propertyTypeHint !== null) { + $this->checkTypeHint($phpcsFile, $propertyTypeHint); + } + + return; + } + + $returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $pointer); + if ($returnTypeHint !== null) { + $this->checkTypeHint($phpcsFile, $returnTypeHint); + } + + foreach (FunctionHelper::getParametersTypeHints($phpcsFile, $pointer) as $parameterTypeHint) { + if ($parameterTypeHint !== null) { + $this->checkTypeHint($phpcsFile, $parameterTypeHint); + } + } + } + + private function checkTypeHint(File $phpcsFile, TypeHint $typeHint): void + { + $tokens = $phpcsFile->getTokens(); + + $typeHintsCount = substr_count($typeHint->getTypeHint(), '|') + 1; + + if ($typeHintsCount > 1) { + if ($this->withSpaces === self::NO) { + $whitespacePointer = TokenHelper::findNext( + $phpcsFile, + T_WHITESPACE, + $typeHint->getStartPointer() + 1, + $typeHint->getEndPointer() + ); + if ($whitespacePointer !== null) { + $originalTypeHint = TokenHelper::getContent($phpcsFile, $typeHint->getStartPointer(), $typeHint->getEndPointer()); + $fix = $phpcsFile->addFixableError( + sprintf('Spaces in type hint "%s" are disallowed.', $originalTypeHint), + $typeHint->getStartPointer(), + self::CODE_DISALLOWED_WHITESPACE + ); + if ($fix) { + $this->fixTypeHint($phpcsFile, $typeHint, $typeHint->getTypeHint()); + } + } + } elseif ($this->withSpaces === self::YES) { + $error = false; + foreach (TokenHelper::findNextAll( + $phpcsFile, + [T_TYPE_UNION], + $typeHint->getStartPointer(), + $typeHint->getEndPointer() + ) as $unionSeparator) { + if ($tokens[$unionSeparator - 1]['content'] !== ' ') { + $error = true; + break; + } + if ($tokens[$unionSeparator + 1]['content'] !== ' ') { + $error = true; + break; + } + } + + if ($error) { + $originalTypeHint = TokenHelper::getContent($phpcsFile, $typeHint->getStartPointer(), $typeHint->getEndPointer()); + $fix = $phpcsFile->addFixableError( + sprintf('One space required before and after each "|" in type hint "%s".', $originalTypeHint), + $typeHint->getStartPointer(), + self::CODE_REQUIRED_WHITESPACE + ); + if ($fix) { + $fixedTypeHint = implode(' | ', explode('|', $typeHint->getTypeHint())); + $this->fixTypeHint($phpcsFile, $typeHint, $fixedTypeHint); + } + } + } + } + + if (!$typeHint->isNullable()) { + return; + } + + $hasShortNullable = strpos($typeHint->getTypeHint(), '?') === 0; + + if ($this->shortNullable === self::YES && $typeHintsCount === 2 && !$hasShortNullable) { + $fix = $phpcsFile->addFixableError( + sprintf('Short nullable type hint in "%s" is required.', $typeHint->getTypeHint()), + $typeHint->getStartPointer(), + self::CODE_REQUIRED_SHORT_NULLABLE + ); + if ($fix) { + $typeHintWithoutNull = self::getTypeHintContentWithoutNull($phpcsFile, $typeHint); + $this->fixTypeHint($phpcsFile, $typeHint, '?' . $typeHintWithoutNull); + } + } elseif ($this->shortNullable === self::NO && $hasShortNullable) { + $fix = $phpcsFile->addFixableError( + sprintf('Usage of short nullable type hint in "%s" is disallowed.', $typeHint->getTypeHint()), + $typeHint->getStartPointer(), + self::CODE_DISALLOWED_SHORT_NULLABLE + ); + if ($fix) { + $this->fixTypeHint($phpcsFile, $typeHint, substr($typeHint->getTypeHint(), 1) . '|null'); + } + } + + if ($hasShortNullable || ($this->shortNullable === self::YES && $typeHintsCount === 2)) { + return; + } + + if ($this->nullPosition === self::FIRST && strtolower($tokens[$typeHint->getStartPointer()]['content']) !== 'null') { + $fix = $phpcsFile->addFixableError( + sprintf('Null type hint should be on first position in "%s".', $typeHint->getTypeHint()), + $typeHint->getStartPointer(), + self::CODE_NULL_TYPE_HINT_NOT_ON_FIRST_POSITION + ); + if ($fix) { + $this->fixTypeHint($phpcsFile, $typeHint, 'null|' . self::getTypeHintContentWithoutNull($phpcsFile, $typeHint)); + } + } elseif ($this->nullPosition === self::LAST && strtolower($tokens[$typeHint->getEndPointer()]['content']) !== 'null') { + $fix = $phpcsFile->addFixableError( + sprintf('Null type hint should be on last position in "%s".', $typeHint->getTypeHint()), + $typeHint->getStartPointer(), + self::CODE_NULL_TYPE_HINT_NOT_ON_LAST_POSITION + ); + if ($fix) { + $this->fixTypeHint($phpcsFile, $typeHint, self::getTypeHintContentWithoutNull($phpcsFile, $typeHint) . '|null'); + } + } + } + + private function getTypeHintContentWithoutNull(File $phpcsFile, TypeHint $typeHint): string + { + $tokens = $phpcsFile->getTokens(); + + if (strtolower($tokens[$typeHint->getEndPointer()]['content']) === 'null') { + $previousTypeHintPointer = TokenHelper::findPrevious( + $phpcsFile, + TokenHelper::getOnlyTypeHintTokenCodes(), + $typeHint->getEndPointer() - 1 + ); + return TokenHelper::getContent($phpcsFile, $typeHint->getStartPointer(), $previousTypeHintPointer); + } + + $content = ''; + + for ($i = $typeHint->getStartPointer(); $i <= $typeHint->getEndPointer(); $i++) { + if (strtolower($tokens[$i]['content']) === 'null') { + $i = TokenHelper::findNext($phpcsFile, TokenHelper::getOnlyTypeHintTokenCodes(), $i + 1); + } + + $content .= $tokens[$i]['content']; + } + + return $content; + } + + private function fixTypeHint(File $phpcsFile, TypeHint $typeHint, string $fixedTypeHint): void + { + $phpcsFile->fixer->beginChangeset(); + + FixerHelper::change($phpcsFile, $typeHint->getStartPointer(), $typeHint->getEndPointer(), $fixedTypeHint); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UselessConstantTypeHintSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UselessConstantTypeHintSniff.php new file mode 100644 index 000000000..b061adc60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/UselessConstantTypeHintSniff.php @@ -0,0 +1,85 @@ + + */ + public function register(): array + { + return [ + T_CONST, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $constantPointer + */ + public function process(File $phpcsFile, $constantPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $constantPointer); + if ($docCommentOpenPointer === null) { + return; + } + + $annotations = AnnotationHelper::getAnnotations($phpcsFile, $constantPointer, '@var'); + + if ($annotations === []) { + return; + } + + $uselessDocComment = !DocCommentHelper::hasDocCommentDescription($phpcsFile, $constantPointer) && count($annotations) === 1; + if ($uselessDocComment) { + $fix = $phpcsFile->addFixableError('Useless documentation comment.', $docCommentOpenPointer, self::CODE_USELESS_DOC_COMMENT); + + /** @var int $fixerStart */ + $fixerStart = TokenHelper::findLastTokenOnPreviousLine($phpcsFile, $docCommentOpenPointer); + $fixerEnd = $tokens[$docCommentOpenPointer]['comment_closer']; + } else { + $annotation = $annotations[0]; + + $fix = $phpcsFile->addFixableError( + 'Useless @var annotation.', + $annotation->getStartPointer(), + self::CODE_USELESS_VAR_ANNOTATION + ); + + /** @var int $fixerStart */ + $fixerStart = TokenHelper::findPreviousContent( + $phpcsFile, + T_DOC_COMMENT_WHITESPACE, + $phpcsFile->eolChar, + $annotation->getStartPointer() - 1 + ); + $fixerEnd = $annotation->getEndPointer(); + } + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + FixerHelper::removeBetweenIncluding($phpcsFile, $fixerStart, $fixerEnd); + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowSuperGlobalVariableSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowSuperGlobalVariableSniff.php new file mode 100644 index 000000000..716f749c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowSuperGlobalVariableSniff.php @@ -0,0 +1,52 @@ + + */ + public function register(): array + { + return [ + T_VARIABLE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $variablePointer + */ + public function process(File $phpcsFile, $variablePointer): void + { + $tokens = $phpcsFile->getTokens(); + + if (!in_array($tokens[$variablePointer]['content'], self::SUPER_GLOBALS, true)) { + return; + } + + $phpcsFile->addError('Use of super global variable is disallowed.', $variablePointer, self::CODE_DISALLOWED_SUPER_GLOBAL_VARIABLE); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowVariableVariableSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowVariableVariableSniff.php new file mode 100644 index 000000000..ecd92b524 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DisallowVariableVariableSniff.php @@ -0,0 +1,35 @@ + + */ + public function register(): array + { + return [ + T_DOLLAR, + T_DOLLAR_OPEN_CURLY_BRACES, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $pointer + */ + public function process(File $phpcsFile, $pointer): void + { + $phpcsFile->addError('Use of variable variable is disallowed.', $pointer, self::CODE_DISALLOWED_VARIABLE_VARIABLE); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DuplicateAssignmentToVariableSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DuplicateAssignmentToVariableSniff.php new file mode 100644 index 000000000..2e73d89ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/DuplicateAssignmentToVariableSniff.php @@ -0,0 +1,70 @@ + + */ + public function register(): array + { + return [ + T_EQUAL, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $assignmentPointer + */ + public function process(File $phpcsFile, $assignmentPointer): void + { + $tokens = $phpcsFile->getTokens(); + + $variablePointer = TokenHelper::findPreviousEffective($phpcsFile, $assignmentPointer - 1); + if ($tokens[$variablePointer]['code'] !== T_VARIABLE) { + return; + } + + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + if (in_array($tokens[$pointerBeforeVariable]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + return; + } + + /** @var int $secondVariablePointer */ + $secondVariablePointer = TokenHelper::findNextEffective($phpcsFile, $assignmentPointer + 1); + if ($tokens[$secondVariablePointer]['code'] !== T_VARIABLE) { + return; + } + + if ($tokens[$variablePointer]['content'] !== $tokens[$secondVariablePointer]['content']) { + return; + } + + $pointerAfterSecondVariable = TokenHelper::findNextEffective($phpcsFile, $secondVariablePointer + 1); + if ($tokens[$pointerAfterSecondVariable]['code'] !== T_EQUAL) { + return; + } + + $phpcsFile->addError( + sprintf('Duplicate assignment to variable %s.', $tokens[$secondVariablePointer]['content']), + $secondVariablePointer, + self::CODE_DUPLICATE_ASSIGNMENT + ); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UnusedVariableSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UnusedVariableSniff.php new file mode 100644 index 000000000..20a5daae5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UnusedVariableSniff.php @@ -0,0 +1,709 @@ + + */ + public function register(): array + { + return [ + T_VARIABLE, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $variablePointer + */ + public function process(File $phpcsFile, $variablePointer): void + { + if (!$this->isAssignment($phpcsFile, $variablePointer)) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $variableName = $tokens[$variablePointer]['content']; + + if (in_array($variableName, [ + '$this', + '$GLOBALS', + '$_SERVER', + '$_GET', + '$_POST', + '$_FILES', + '$_COOKIE', + '$_SESSION', + '$_REQUEST', + '$_ENV', + ], true)) { + return; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + + if (in_array($tokens[$previousPointer]['code'], [T_OBJECT_OPERATOR, T_DOUBLE_COLON], true)) { + // Property + return; + } + + if (in_array($tokens[$previousPointer]['code'], Tokens::$castTokens, true)) { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } + + if (in_array($tokens[$previousPointer]['code'], [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_MUL_EQUAL, + T_DIV_EQUAL, + T_POW_EQUAL, + T_MOD_EQUAL, + T_AND_EQUAL, + T_OR_EQUAL, + T_XOR_EQUAL, + T_SL_EQUAL, + T_SR_EQUAL, + T_CONCAT_EQUAL, + T_YIELD, + ], true)) { + return; + } + + if ($this->isUsedAsParameter($phpcsFile, $variablePointer)) { + return; + } + + if ($this->isUsedInForLoopCondition($phpcsFile, $variablePointer, $variableName)) { + return; + } + + if ($this->isDefinedInDoConditionAndUsedInLoop($phpcsFile, $variablePointer, $variableName)) { + return; + } + + if ($this->isUsedInLoopCycle($phpcsFile, $variablePointer, $variableName)) { + return; + } + + if ($this->isUsedAsKeyOrValueInArray($phpcsFile, $variablePointer)) { + return; + } + + if ($this->isValueInForeachAndErrorIsIgnored($phpcsFile, $variablePointer)) { + return; + } + + $scopeOwnerPointer = ScopeHelper::getRootPointer($phpcsFile, $variablePointer - 1); + foreach (array_reverse($tokens[$variablePointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) { + $scopeOwnerPointer = $conditionPointer; + break; + } + } + + if (in_array($tokens[$scopeOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) { + if ($this->isStaticOrGlobalVariable($phpcsFile, $scopeOwnerPointer, $variableName)) { + return; + } + + if ($this->isParameterPassedByReference($phpcsFile, $scopeOwnerPointer, $variableName)) { + return; + } + + if ( + $tokens[$scopeOwnerPointer]['code'] === T_CLOSURE + && $this->isInheritedVariablePassedByReference($phpcsFile, $scopeOwnerPointer, $variableName) + ) { + return; + } + } + + if ($this->isReference($phpcsFile, $scopeOwnerPointer, $variablePointer)) { + return; + } + + if (VariableHelper::isUsedInScopeAfterPointer($phpcsFile, $scopeOwnerPointer, $variablePointer, $variablePointer + 1)) { + return; + } + + if ($this->isPartOfStatementAndWithIncrementOrDecrementOperator($phpcsFile, $variablePointer)) { + return; + } + + $phpcsFile->addError( + sprintf('Unused variable %s.', $variableName), + $variablePointer, + self::CODE_UNUSED_VARIABLE + ); + } + + private function isAssignment(File $phpcsFile, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); + if (in_array($tokens[$nextPointer]['code'], [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_MUL_EQUAL, + T_DIV_EQUAL, + T_POW_EQUAL, + T_MOD_EQUAL, + T_AND_EQUAL, + T_OR_EQUAL, + T_XOR_EQUAL, + T_SL_EQUAL, + T_SR_EQUAL, + T_CONCAT_EQUAL, + ], true)) { + if ($tokens[$nextPointer]['code'] === T_EQUAL) { + if (PropertyHelper::isProperty($phpcsFile, $variablePointer)) { + return false; + } + + if (ParameterHelper::isParameter($phpcsFile, $variablePointer)) { + return false; + } + } + + return true; + } + + $actualPointer = $variablePointer; + do { + $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $actualPointer); + $parenthesisOwnerPointer = $this->findOwnerOfNestedParentheses($phpcsFile, $actualPointer); + + $actualPointer = $parenthesisOpenerPointer; + } while ($parenthesisOwnerPointer === null && isset($tokens[$actualPointer]['nested_parenthesis'])); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + + if ( + in_array($tokens[$nextPointer]['code'], [T_INC, T_DEC], true) + || in_array($tokens[$previousPointer]['code'], [T_INC, T_DEC], true) + ) { + if ($parenthesisOwnerPointer === null) { + return true; + } + + return !in_array($tokens[$parenthesisOwnerPointer]['code'], [T_FOR, T_WHILE, T_IF, T_ELSEIF], true); + } + + if ($parenthesisOwnerPointer !== null && $tokens[$parenthesisOwnerPointer]['code'] === T_FOREACH) { + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + return in_array($tokens[$pointerBeforeVariable]['code'], [T_AS, T_DOUBLE_ARROW], true); + } + + if ($parenthesisOpenerPointer !== null) { + $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1); + if ($tokens[$pointerBeforeParenthesisOpener]['code'] === T_LIST) { + return true; + } + } + + $possibleShortListCloserPointer = TokenHelper::findNextExcluding( + $phpcsFile, + array_merge(TokenHelper::$ineffectiveTokenCodes, [T_VARIABLE, T_COMMA]), + $variablePointer + 1 + ); + if ($tokens[$possibleShortListCloserPointer]['code'] === T_CLOSE_SHORT_ARRAY) { + return $tokens[TokenHelper::findNextEffective($phpcsFile, $possibleShortListCloserPointer + 1)]['code'] === T_EQUAL; + } + + return false; + } + + private function isUsedAsParameter(File $phpcsFile, int $variablePointer): bool + { + $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $variablePointer); + if ($parenthesisOpenerPointer === null) { + return false; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $parenthesisOpenerPointer, $variablePointer)) { + return false; + } + + return $phpcsFile->getTokens()[TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1)]['code'] === T_STRING; + } + + private function isUsedInForLoopCondition(File $phpcsFile, int $variablePointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $variablePointer); + if ($parenthesisOpenerPointer === null) { + return false; + } + + $parenthesisOwnerPointer = $this->findOwnerOfNestedParentheses($phpcsFile, $variablePointer); + if ($parenthesisOwnerPointer === null) { + return false; + } + + if ($tokens[$parenthesisOwnerPointer]['code'] !== T_FOR) { + return false; + } + + for ($i = $parenthesisOpenerPointer + 1; $i < $tokens[$parenthesisOwnerPointer]['parenthesis_closer']; $i++) { + if ($i === $variablePointer) { + continue; + } + + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + return true; + } + + return false; + } + + private function isDefinedInDoConditionAndUsedInLoop(File $phpcsFile, int $variablePointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpener = TokenHelper::findPrevious($phpcsFile, T_OPEN_PARENTHESIS, $variablePointer - 1); + if ($parenthesisOpener === null || $tokens[$parenthesisOpener]['parenthesis_closer'] < $variablePointer) { + return false; + } + + $whilePointer = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpener - 1); + if ($tokens[$whilePointer]['code'] !== T_WHILE) { + return false; + } + + $loopCloserPointer = TokenHelper::findPreviousEffective($phpcsFile, $whilePointer - 1); + if ($tokens[$loopCloserPointer]['code'] !== T_CLOSE_CURLY_BRACKET) { + return false; + } + + $doPointer = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$loopCloserPointer]['bracket_opener'] - 1); + if ($tokens[$doPointer]['code'] !== T_DO) { + return false; + } + + return TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $tokens[$loopCloserPointer]['bracket_opener'] + 1, + $loopCloserPointer + ) !== null; + } + + private function isUsedInLoopCycle(File $phpcsFile, int $variablePointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + $loopPointer = null; + foreach (array_reverse($tokens[$variablePointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) { + break; + } + + if (!in_array($conditionTokenCode, [T_FOREACH, T_FOR, T_DO, T_WHILE], true)) { + continue; + } + + $loopPointer = $conditionPointer; + + $loopConditionPointer = $conditionTokenCode === T_DO + ? TokenHelper::findNextEffective($phpcsFile, $tokens[$loopPointer]['scope_closer'] + 1) + : $loopPointer; + + $variableUsedInLoopConditionPointer = TokenHelper::findNextContent( + $phpcsFile, + T_VARIABLE, + $variableName, + $tokens[$loopConditionPointer]['parenthesis_opener'] + 1, + $tokens[$loopConditionPointer]['parenthesis_closer'] + ); + if ( + $variableUsedInLoopConditionPointer === null + || $variableUsedInLoopConditionPointer === $variablePointer + ) { + continue; + } + + if ($conditionTokenCode !== T_FOREACH) { + return true; + } + + $pointerBeforeVariableUsedInLoopCondition = TokenHelper::findPreviousEffective( + $phpcsFile, + $variableUsedInLoopConditionPointer - 1 + ); + if ($tokens[$pointerBeforeVariableUsedInLoopCondition]['code'] === T_BITWISE_AND) { + return true; + } + } + + if ($loopPointer === null) { + return false; + } + + for ($i = $tokens[$loopPointer]['scope_opener'] + 1; $i < $tokens[$loopPointer]['scope_closer']; $i++) { + if ( + in_array($tokens[$i]['code'], [T_DOUBLE_QUOTED_STRING, T_HEREDOC], true) + && VariableHelper::isUsedInScopeInString($phpcsFile, $variableName, $i) + ) { + return true; + } + + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + if (!$this->isAssignment($phpcsFile, $i)) { + return true; + } + + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if (!in_array($tokens[$nextPointer]['code'], [ + T_INC, + T_DEC, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_MUL_EQUAL, + T_DIV_EQUAL, + T_POW_EQUAL, + T_MOD_EQUAL, + T_AND_EQUAL, + T_OR_EQUAL, + T_XOR_EQUAL, + T_SL_EQUAL, + T_SR_EQUAL, + T_CONCAT_EQUAL, + ], true)) { + continue; + } + + $parenthesisOwnerPointer = $this->findNestedParenthesisWithOwner($phpcsFile, $i); + if ( + $parenthesisOwnerPointer !== null + && in_array($tokens[$parenthesisOwnerPointer]['code'], [T_IF, T_ELSEIF], true) + ) { + return true; + } + } + + return false; + } + + private function isUsedAsKeyOrValueInArray(File $phpcsFile, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $squareBracketOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_SQUARE_BRACKET, $variablePointer - 1); + if ( + $squareBracketOpenerPointer !== null + && $tokens[$squareBracketOpenerPointer]['bracket_closer'] > $variablePointer + ) { + return true; + } + + $arrayOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_SHORT_ARRAY, $variablePointer - 1); + if ($arrayOpenerPointer === null) { + return false; + } + + $arrayCloserPointer = $tokens[$arrayOpenerPointer]['bracket_closer']; + if ($arrayCloserPointer < $variablePointer) { + return false; + } + + $pointerAfterArrayCloser = TokenHelper::findNextEffective($phpcsFile, $arrayCloserPointer + 1); + if ($tokens[$pointerAfterArrayCloser]['code'] === T_EQUAL) { + return false; + } + + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + + if (in_array($tokens[$pointerBeforeVariable]['code'], [T_INC, T_DEC], true)) { + $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $pointerBeforeVariable - 1); + } + + return in_array($tokens[$pointerBeforeVariable]['code'], [T_OPEN_SHORT_ARRAY, T_COMMA, T_DOUBLE_ARROW], true); + } + + private function isValueInForeachAndErrorIsIgnored(File $phpcsFile, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOwnerPointer = $this->findNestedParenthesisWithOwner($phpcsFile, $variablePointer); + $isInForeach = $parenthesisOwnerPointer !== null && $tokens[$parenthesisOwnerPointer]['code'] === T_FOREACH; + + if (!$isInForeach) { + return false; + } + + $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); + if ($pointerAfterVariable !== null && $tokens[$pointerAfterVariable]['code'] === T_DOUBLE_ARROW) { + return false; + } + + return $this->ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach; + } + + private function isStaticOrGlobalVariable(File $phpcsFile, int $functionPointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + for ($i = $tokens[$functionPointer]['scope_opener'] + 1; $i < $tokens[$functionPointer]['scope_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + $pointerBeforeParameter = TokenHelper::findPreviousEffective($phpcsFile, $i - 1); + if (in_array($tokens[$pointerBeforeParameter]['code'], [T_STATIC, T_GLOBAL], true)) { + return true; + } + } + + return false; + } + + private function isParameterPassedByReference(File $phpcsFile, int $functionPointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + $pointerBeforeParameter = TokenHelper::findPreviousEffective($phpcsFile, $i - 1); + if ($tokens[$pointerBeforeParameter]['code'] === T_BITWISE_AND) { + return true; + } + } + + return false; + } + + private function isInheritedVariablePassedByReference(File $phpcsFile, int $functionPointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + $usePointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$functionPointer]['parenthesis_closer'] + 1); + if ($tokens[$usePointer]['code'] !== T_USE) { + return false; + } + + $useParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1); + for ($i = $useParenthesisOpener + 1; $i < $tokens[$useParenthesisOpener]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + $pointerBeforeInheritedVariable = TokenHelper::findPreviousEffective($phpcsFile, $i - 1); + if ($tokens[$pointerBeforeInheritedVariable]['code'] === T_BITWISE_AND) { + return true; + } + } + + return false; + } + + private function isReference(File $phpcsFile, int $scopeOwnerPointer, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $scopeOpenerPointer = $tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG + ? $scopeOwnerPointer + : $tokens[$scopeOwnerPointer]['scope_opener']; + + for ($i = $scopeOpenerPointer + 1; $i < $variablePointer; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + if ($tokens[$i]['content'] !== $tokens[$variablePointer]['content']) { + continue; + } + + $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1); + if ($tokens[$assignmentPointer]['code'] !== T_EQUAL) { + continue; + } + + $referencePointer = TokenHelper::findNextEffective($phpcsFile, $assignmentPointer + 1); + if ($tokens[$referencePointer]['code'] === T_BITWISE_AND) { + return true; + } + } + + return false; + } + + private function isPartOfStatementAndWithIncrementOrDecrementOperator(File $phpcsFile, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1); + $nextPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); + + if (in_array($tokens[$previousPointer]['code'], [T_DEC, T_INC], true)) { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } elseif ($nextPointer !== null && in_array($tokens[$nextPointer]['code'], [T_DEC, T_INC], true)) { + // Nothing + } else { + return false; + } + + if ($tokens[$previousPointer]['code'] === T_OPEN_PARENTHESIS) { + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1); + } + + return in_array( + $tokens[$previousPointer]['code'], + array_merge( + [T_STRING_CONCAT, T_ECHO, T_RETURN, T_EXIT, T_PRINT, T_COMMA, T_EMPTY, T_EVAL, T_YIELD], + Tokens::$operators, + Tokens::$assignmentTokens, + Tokens::$booleanOperators, + Tokens::$castTokens + ), + true + ); + } + + private function findNestedParenthesisWithOwner(File $phpcsFile, int $pointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('nested_parenthesis', $tokens[$pointer])) { + return null; + } + + foreach (array_reverse(array_keys($tokens[$pointer]['nested_parenthesis'])) as $nestedParenthesisOpener) { + if (array_key_exists('parenthesis_owner', $tokens[$nestedParenthesisOpener])) { + return $tokens[$nestedParenthesisOpener]['parenthesis_owner']; + } + } + + return null; + } + + private function findOpenerOfNestedParentheses(File $phpcsFile, int $pointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + if (!array_key_exists('nested_parenthesis', $tokens[$pointer])) { + return null; + } + + return array_reverse(array_keys($tokens[$pointer]['nested_parenthesis']))[0]; + } + + private function findOwnerOfNestedParentheses(File $phpcsFile, int $pointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $pointer); + + if ($parenthesisOpenerPointer === null) { + return null; + } + + return array_key_exists('parenthesis_owner', $tokens[$parenthesisOpenerPointer]) + ? $tokens[$parenthesisOpenerPointer]['parenthesis_owner'] + : null; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UselessVariableSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UselessVariableSniff.php new file mode 100644 index 000000000..38cce8371 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UselessVariableSniff.php @@ -0,0 +1,417 @@ + + */ + public function register(): array + { + return [ + T_RETURN, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $returnPointer + */ + public function process(File $phpcsFile, $returnPointer): void + { + $tokens = $phpcsFile->getTokens(); + + /** @var int $variablePointer */ + $variablePointer = TokenHelper::findNextEffective($phpcsFile, $returnPointer + 1); + if ($tokens[$variablePointer]['code'] !== T_VARIABLE) { + return; + } + + $returnSemicolonPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); + if ($tokens[$returnSemicolonPointer]['code'] !== T_SEMICOLON) { + return; + } + + $variableName = $tokens[$variablePointer]['content']; + + $functionPointer = $this->findFunctionPointer($phpcsFile, $variablePointer); + + if ($functionPointer !== null) { + if ($this->isReturnedByReference($phpcsFile, $functionPointer)) { + return; + } + + if ($this->isStaticVariable($phpcsFile, $functionPointer, $variablePointer, $variableName)) { + return; + } + + if ($this->isFunctionParameter($phpcsFile, $functionPointer, $variableName)) { + return; + } + } + + $previousVariablePointer = $this->findPreviousVariablePointer($phpcsFile, $returnPointer, $variableName); + if ($previousVariablePointer === null) { + return; + } + + if (!$this->isAssignmentToVariable($phpcsFile, $previousVariablePointer)) { + return; + } + + if ($this->isAssignedInControlStructure($phpcsFile, $previousVariablePointer)) { + return; + } + + if ($this->isAssignedInFunctionCall($phpcsFile, $previousVariablePointer)) { + return; + } + + if ($this->hasVariableVarAnnotation($phpcsFile, $previousVariablePointer)) { + return; + } + + if ($this->hasAnotherAssignmentBefore($phpcsFile, $previousVariablePointer, $variableName)) { + return; + } + + if (!$this->areBothPointersNearby($phpcsFile, $previousVariablePointer, $returnPointer)) { + return; + } + + $errorParameters = [ + sprintf('Useless variable %s.', $variableName), + $previousVariablePointer, + self::CODE_USELESS_VARIABLE, + ]; + + $pointerBeforePreviousVariable = TokenHelper::findPreviousEffective($phpcsFile, $previousVariablePointer - 1); + + if ( + !in_array($tokens[$pointerBeforePreviousVariable]['code'], [T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_CLOSE_CURLY_BRACKET], true) + && TokenHelper::findNextEffective($phpcsFile, $returnSemicolonPointer + 1) !== null + ) { + $phpcsFile->addError(...$errorParameters); + return; + } + + $fix = $phpcsFile->addFixableError(...$errorParameters); + + if (!$fix) { + return; + } + + /** @var int $assignmentPointer */ + $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $previousVariablePointer + 1); + + $assignmentFixerMapping = [ + T_PLUS_EQUAL => '+', + T_MINUS_EQUAL => '-', + T_MUL_EQUAL => '*', + T_DIV_EQUAL => '/', + T_POW_EQUAL => '**', + T_MOD_EQUAL => '%', + T_AND_EQUAL => '&', + T_OR_EQUAL => '|', + T_XOR_EQUAL => '^', + T_SL_EQUAL => '<<', + T_SR_EQUAL => '>>', + T_CONCAT_EQUAL => '.', + ]; + + $previousVariableSemicolonPointer = $this->findSemicolon($phpcsFile, $previousVariablePointer); + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$assignmentPointer]['code'] === T_EQUAL) { + FixerHelper::change($phpcsFile, $previousVariablePointer, $assignmentPointer, 'return'); + } else { + $phpcsFile->fixer->addContentBefore($previousVariablePointer, 'return '); + $phpcsFile->fixer->replaceToken($assignmentPointer, $assignmentFixerMapping[$tokens[$assignmentPointer]['code']]); + } + + FixerHelper::removeBetweenIncluding($phpcsFile, $previousVariableSemicolonPointer + 1, $returnSemicolonPointer); + + $phpcsFile->fixer->endChangeset(); + } + + private function findPreviousVariablePointer(File $phpcsFile, int $pointer, string $variableName): ?int + { + $tokens = $phpcsFile->getTokens(); + + for ($i = $pointer - 1; $i >= 0; $i--) { + if ( + in_array($tokens[$i]['code'], TokenHelper::$functionTokenCodes, true) + && ScopeHelper::isInSameScope($phpcsFile, $tokens[$i]['scope_opener'] + 1, $pointer) + ) { + return null; + } + + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $i - 1); + if ($tokens[$previousPointer]['code'] === T_DOUBLE_COLON) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $i, $pointer)) { + continue; + } + + return $i; + } + + return null; + } + + private function isAssignedInControlStructure(File $phpcsFile, int $pointer): bool + { + $controlStructure = TokenHelper::findPrevious($phpcsFile, [ + T_WHILE, + T_FOR, + T_FOREACH, + T_SWITCH, + T_IF, + T_ELSEIF, + ], $pointer - 1); + + if ($controlStructure === null) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + + return $tokens[$controlStructure]['parenthesis_opener'] < $pointer && $pointer < $tokens[$controlStructure]['parenthesis_closer']; + } + + private function isAssignedInFunctionCall(File $phpcsFile, int $pointer): bool + { + $possibleFunctionNamePointer = TokenHelper::findPrevious($phpcsFile, T_STRING, $pointer - 1); + + if ($possibleFunctionNamePointer === null) { + return false; + } + + $tokens = $phpcsFile->getTokens(); + + $parenthesisOpenerPointer = TokenHelper::findNextEffective($phpcsFile, $possibleFunctionNamePointer + 1); + if ($tokens[$parenthesisOpenerPointer]['code'] !== T_OPEN_PARENTHESIS) { + return false; + } + + return $parenthesisOpenerPointer < $pointer && $pointer < $tokens[$parenthesisOpenerPointer]['parenthesis_closer']; + } + + private function isAssignmentToVariable(File $phpcsFile, int $pointer): bool + { + $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $pointer + 1); + return in_array($phpcsFile->getTokens()[$assignmentPointer]['code'], [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_MUL_EQUAL, + T_DIV_EQUAL, + T_POW_EQUAL, + T_MOD_EQUAL, + T_AND_EQUAL, + T_OR_EQUAL, + T_XOR_EQUAL, + T_SL_EQUAL, + T_SR_EQUAL, + T_CONCAT_EQUAL, + ], true); + } + + private function findFunctionPointer(File $phpcsFile, int $pointer): ?int + { + $tokens = $phpcsFile->getTokens(); + + foreach (array_reverse($tokens[$pointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) { + if (in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) { + return $conditionPointer; + } + } + + return null; + } + + private function isStaticVariable(File $phpcsFile, int $functionPointer, int $variablePointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + for ($i = $tokens[$functionPointer]['scope_opener'] + 1; $i < $variablePointer; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + $pointerBeforeParameter = TokenHelper::findPreviousEffective($phpcsFile, $i - 1); + if ($tokens[$pointerBeforeParameter]['code'] === T_STATIC) { + return true; + } + } + + return false; + } + + private function isFunctionParameter(File $phpcsFile, int $functionPointer, string $variableName): bool + { + $tokens = $phpcsFile->getTokens(); + + for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE) { + continue; + } + if ($tokens[$i]['content'] !== $variableName) { + continue; + } + + return true; + } + + return false; + } + + private function isReturnedByReference(File $phpcsFile, int $functionPointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $referencePointer = TokenHelper::findNextEffective($phpcsFile, $functionPointer + 1); + return $tokens[$referencePointer]['code'] === T_BITWISE_AND; + } + + private function hasVariableVarAnnotation(File $phpcsFile, int $variablePointer): bool + { + $tokens = $phpcsFile->getTokens(); + + $pointerBeforeVariable = TokenHelper::findPreviousNonWhitespace($phpcsFile, $variablePointer - 1); + if ($tokens[$pointerBeforeVariable]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return false; + } + + $docCommentContent = TokenHelper::getContent($phpcsFile, $tokens[$pointerBeforeVariable]['comment_opener'], $pointerBeforeVariable); + return preg_match( + '~@(?:(?:phpstan|psalm)-)?var\\s+.+\\s+' . preg_quote($tokens[$variablePointer]['content'], '~') . '(?:\\s|$)~', + $docCommentContent + ) !== 0; + } + + private function hasAnotherAssignmentBefore(File $phpcsFile, int $variablePointer, string $variableName): bool + { + $previousVariablePointer = $this->findPreviousVariablePointer($phpcsFile, $variablePointer, $variableName); + if ($previousVariablePointer === null) { + return false; + } + + if (!$this->isAssignmentToVariable($phpcsFile, $previousVariablePointer)) { + return false; + } + + return $this->areBothVariablesNearby($phpcsFile, $previousVariablePointer, $variablePointer); + } + + private function areBothPointersNearby(File $phpcsFile, int $firstPointer, int $secondPointer): bool + { + $firstVariableSemicolonPointer = $this->findSemicolon($phpcsFile, $firstPointer); + $pointerAfterFirstVariableSemicolon = TokenHelper::findNextEffective($phpcsFile, $firstVariableSemicolonPointer + 1); + + return $pointerAfterFirstVariableSemicolon === $secondPointer; + } + + private function areBothVariablesNearby(File $phpcsFile, int $firstVariablePointer, int $secondVariablePointer): bool + { + if ($this->areBothPointersNearby($phpcsFile, $firstVariablePointer, $secondVariablePointer)) { + return true; + } + + $tokens = $phpcsFile->getTokens(); + + $lastConditionPointer = array_reverse(array_keys($tokens[$firstVariablePointer]['conditions']))[0]; + $lastConditionScopeCloserPointer = $tokens[$lastConditionPointer]['scope_closer']; + if ($tokens[$lastConditionPointer]['code'] === T_DO) { + $lastConditionScopeCloserPointer = TokenHelper::findNext($phpcsFile, T_SEMICOLON, $lastConditionScopeCloserPointer + 1); + } + + return TokenHelper::findNextEffective($phpcsFile, $lastConditionScopeCloserPointer + 1) === $secondVariablePointer; + } + + private function findSemicolon(File $phpcsFile, int $pointer): int + { + $tokens = $phpcsFile->getTokens(); + + $semicolonPointer = null; + for ($i = $pointer + 1; $i < count($tokens) - 1; $i++) { + if ($tokens[$i]['code'] !== T_SEMICOLON) { + continue; + } + + if (!ScopeHelper::isInSameScope($phpcsFile, $pointer, $i)) { + continue; + } + + $semicolonPointer = $i; + break; + } + + /** @var int $semicolonPointer */ + $semicolonPointer = $semicolonPointer; + return $semicolonPointer; + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Whitespaces/DuplicateSpacesSniff.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Whitespaces/DuplicateSpacesSniff.php new file mode 100644 index 000000000..8dbecc506 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Whitespaces/DuplicateSpacesSniff.php @@ -0,0 +1,175 @@ + + */ + public function register(): array + { + return [ + T_WHITESPACE, + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STRING, + ]; + } + + /** + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint + * @param int $whitespacePointer + */ + public function process(File $phpcsFile, $whitespacePointer): void + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$whitespacePointer]['column'] === 1) { + return; + } + + $content = $tokens[$whitespacePointer]['content']; + + if ($content === $phpcsFile->eolChar) { + return; + } + + if ($tokens[$whitespacePointer]['code'] === T_WHITESPACE) { + if ($this->ignoreSpacesBeforeAssignment) { + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $whitespacePointer + 1); + if ( + $pointerAfter !== null + && in_array($tokens[$pointerAfter]['code'], Tokens::$assignmentTokens, true) + ) { + return; + } + } + + if ($this->ignoreSpacesInParameters) { + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $whitespacePointer + 1); + if ( + $pointerAfter !== null + && $tokens[$pointerAfter]['code'] === T_VARIABLE + && ParameterHelper::isParameter($phpcsFile, $pointerAfter) + ) { + return; + } + } + + if ($this->ignoreSpacesInMatch) { + $pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $whitespacePointer + 1); + if ( + $pointerAfter !== null + && $tokens[$pointerAfter]['code'] === T_MATCH_ARROW + ) { + return; + } + } + } else { + if ($this->ignoreSpacesInComment) { + return; + } + + if ( + $tokens[$whitespacePointer - 1]['code'] === T_DOC_COMMENT_STAR + && $tokens[$whitespacePointer + 1]['code'] === T_DOC_COMMENT_STRING + ) { + return; + } + + if ($this->ignoreSpacesInAnnotation) { + $pointerBefore = TokenHelper::findPrevious($phpcsFile, [T_DOC_COMMENT_OPEN_TAG, T_DOC_COMMENT_TAG], $whitespacePointer - 1); + if ( + $pointerBefore !== null + && $tokens[$pointerBefore]['code'] === T_DOC_COMMENT_TAG + && $tokens[$whitespacePointer + 1]['code'] !== T_DOC_COMMENT_CLOSE_TAG + ) { + return; + } + } + } + + $matchResult = preg_match_all('~ {2,}~', $content, $matches, PREG_OFFSET_CAPTURE); + if ($matchResult === false || $matchResult === 0) { + return; + } + + $tabWidth = $phpcsFile->config->tabWidth; + + $fix = false; + foreach ($matches[0] as [$match, $offset]) { + $firstPointerOnLine = TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $whitespacePointer - 1); + $indentation = IndentationHelper::getIndentation($phpcsFile, $firstPointerOnLine); + $indentationWithoutTabs = str_replace( + IndentationHelper::TAB_INDENT, + $tabWidth === 0 ? IndentationHelper::SPACES_INDENT : str_repeat(' ', $tabWidth), + $indentation + ); + + $position = $tokens[$whitespacePointer]['column'] + $offset - strlen($indentation) + strlen($indentationWithoutTabs); + + $fixable = $phpcsFile->addFixableError( + sprintf('Duplicate spaces at position %d.', $position), + $whitespacePointer, + self::CODE_DUPLICATE_SPACES + ); + + if ($fixable) { + $fix = true; + } + } + + if (!$fix) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->replaceToken($whitespacePointer, preg_replace('~ {2,}~', ' ', $content)); + + $phpcsFile->fixer->endChangeset(); + } + +} diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml new file mode 100644 index 000000000..185a529e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/SlevomatCodingStandard/ruleset.xml @@ -0,0 +1,4 @@ + + + ./../autoload-bootstrap.php + diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/autoload-bootstrap.php b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/autoload-bootstrap.php new file mode 100644 index 000000000..0a480f1cc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/autoload-bootstrap.php @@ -0,0 +1,11 @@ + + + + + + + + + + +``` + +#### SlevomatCodingStandard.Attributes.DisallowAttributesJoining 🔧 + +Requires that only one attribute can be placed inside `#[]` (no comma-separated list). In case of more attributes applied, they are split into individual `#[]` blocks. + +#### SlevomatCodingStandard.Attributes.DisallowMultipleAttributesPerLine 🔧 + +Disallows multiple attributes of some target on same line. +This sniff treats multiple attributes declared inside one `#[]` as a single attribute. See `DisallowAttributesJoining` to modify this behavior. + +#### SlevomatCodingStandard.Attributes.RequireAttributeAfterDocComment 🔧 + +Requires that attributes are always after documentation comment. + diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/classes.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/classes.md new file mode 100644 index 000000000..5bbed250b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/classes.md @@ -0,0 +1,284 @@ +## Classes + +#### SlevomatCodingStandard.Classes.BackedEnumTypeSpacing 🔧 + +* Checks number of spaces before `:` and before type. + +Sniff provides the following settings: + +* `spacesCountBeforeColon`: the number of spaces before `:`. +* `spacesCountBeforeType`: the number of spaces before type. + +#### SlevomatCodingStandard.Classes.ClassLength + +Disallows long classes. This sniff provides the following settings: + +* `includeComments`: should comments be included in the count (default value is false). +* `includeWhitespace`: should empty lines be included in the count (default value is false). +* `maxLinesLength`: specifies max allowed function lines length (default value is 250). + +#### SlevomatCodingStandard.Classes.ClassConstantVisibility 🔧 + +In PHP 7.1+ it's possible to declare [visibility of class constants](https://wiki.php.net/rfc/class_const_visibility). In a similar vein to optional declaration of visibility for properties and methods which is actually required in sane coding standards, this sniff also requires declaring visibility for all class constants. + +Sniff provides the following settings: + +* `fixable`: the sniff is not fixable by default because we think it's better to decide about each constant one by one, however you can enable fixability with this option. + +```php +const FOO = 1; // visibility missing! +public const BAR = 2; // correct +``` + +#### SlevomatCodingStandard.Classes.ClassMemberSpacing 🔧 + +Sniff checks lines count between different class members, e.g. between last property and first method. + +Sniff provides the following settings: + +* `linesCountBetweenMembers`: lines count between different class members + +#### SlevomatCodingStandard.Classes.ClassStructure 🔧 + +Checks that class/trait/interface members are in the correct order. + +Sniff provides the following settings: + +* `groups`: order of groups. Use multiple groups in one `` to not differentiate among them. You can use specific groups or shortcuts. + +**List of supported groups**: +uses, +enum cases, +public constants, protected constants, private constants, +public properties, public static properties, protected properties, protected static properties, private properties, private static properties, +constructor, static constructors, destructor, magic methods, +public methods, protected methods, private methods, +public final methods, public static final methods, protected final methods, protected static final methods, +public abstract methods, public static abstract methods, protected abstract methods, protected static abstract methods, +public static methods, protected static methods, private static methods, +private methods + +**List of supported shortcuts**: +constants, properties, static properties, methods, all public methods, all protected methods, all private methods, static methods, final methods, abstract methods + +```xml + + + + + + + + + + + + + + + + + + + + + + +``` + +#### SlevomatCodingStandard.Classes.ConstantSpacing 🔧 + +Checks that there is a certain number of blank lines between constants. + +Sniff provides the following settings: + +* `minLinesCountBeforeWithComment`: minimum number of lines before constant with a documentation comment or attribute +* `maxLinesCountBeforeWithComment`: maximum number of lines before constant with a documentation comment or attribute +* `minLinesCountBeforeWithoutComment`: minimum number of lines before constant without a documentation comment or attribute +* `maxLinesCountBeforeWithoutComment`: maximum number of lines before constant without a documentation comment or attribute + +#### SlevomatCodingStandard.Classes.DisallowConstructorPropertyPromotion + +Disallows usage of constructor property promotion. + +#### SlevomatCodingStandard.Classes.DisallowLateStaticBindingForConstants 🔧 + +Disallows late static binding for constants. + +#### SlevomatCodingStandard.Classes.DisallowMultiConstantDefinition 🔧 + +Disallows multi constant definition. + +#### SlevomatCodingStandard.Classes.DisallowMultiPropertyDefinition 🔧 + +Disallows multi property definition. + +#### SlevomatCodingStandard.Classes.DisallowMultiPropertyDefinition 🔧 + +Disallows multi property definition. + +#### SlevomatCodingStandard.Classes.DisallowStringExpressionPropertyFetch 🔧 + +Disallows string expression property fetch `$object->{'foo'}` when the property name is compatible with identifier access. + +#### SlevomatCodingStandard.Classes.EmptyLinesAroundClassBraces 🔧 + +Enforces one configurable number of lines after opening class/interface/trait brace and one empty line before the closing brace. + +Sniff provides the following settings: + +* `linesCountAfterOpeningBrace`: allows to configure the number of lines after opening brace. +* `linesCountBeforeClosingBrace`: allows to configure the number of lines before closing brace. + +#### SlevomatCodingStandard.Classes.EnumCaseSpacing 🔧 + +Checks that there is a certain number of blank lines between enum cases. + +Sniff provides the following settings: + +* `minLinesCountBeforeWithComment`: minimum number of lines before enum case with a documentation comment or attribute +* `maxLinesCountBeforeWithComment`: maximum number of lines before enum case with a documentation comment or attribute +* `minLinesCountBeforeWithoutComment`: minimum number of lines before enum case without a documentation comment or attribute +* `maxLinesCountBeforeWithoutComment`: maximum number of lines before enum case without a documentation comment or attribute + +#### SlevomatCodingStandard.Classes.ForbiddenPublicProperty + +Disallows using public properties. + +This sniff provides the following setting: + +* `checkPromoted`: will check promoted properties too. + +#### SlevomatCodingStandard.Classes.MethodSpacing 🔧 + +Checks that there is a certain number of blank lines between methods. + +Sniff provides the following settings: + +* `minLinesCount`: minimum number of blank lines +* `maxLinesCount`: maximum number of blank lines + +#### SlevomatCodingStandard.Classes.ModernClassNameReference 🔧 + +Reports use of `__CLASS__`, `get_parent_class()`, `get_called_class()`, `get_class()` and `get_class($this)`. +Class names should be referenced via `::class` constant when possible. + +Sniff provides the following settings: + +* `enableOnObjects`: Enable `::class` on all objects. It's on by default if you're on PHP 8.0+ + +#### SlevomatCodingStandard.Classes.ParentCallSpacing 🔧 + +Enforces configurable number of lines around parent method call. + +Sniff provides the following settings: + +* `linesCountBefore`: allows to configure the number of lines before parent call. +* `linesCountBeforeFirst`: allows to configure the number of lines before first parent call. +* `linesCountAfter`: allows to configure the number of lines after parent call. +* `linesCountAfterLast`: allows to configure the number of lines after last parent call. + +#### SlevomatCodingStandard.Classes.PropertyDeclaration 🔧 + +* Checks that there's a single space between a typehint and a property name: `Foo $foo` +* Checks that there's no whitespace between a nullability symbol and a typehint: `?Foo` +* Checks that there's a single space before nullability symbol or a typehint: `private ?Foo` or `private Foo` +* Checks order of modifiers + +Sniff provides the following settings: + +* `modifiersOrder`: allows to configure order of modifiers. +* `checkPromoted`: will check promoted properties too. +* `enableMultipleSpacesBetweenModifiersCheck`: checks multiple spaces between modifiers. + +#### SlevomatCodingStandard.Classes.PropertySpacing 🔧 + +Checks that there is a certain number of blank lines between properties. + +Sniff provides the following settings: + +* `minLinesCountBeforeWithComment`: minimum number of lines before property with a documentation comment or attribute +* `maxLinesCountBeforeWithComment`: maximum number of lines before property with a documentation comment or attribute +* `minLinesCountBeforeWithoutComment`: minimum number of lines before property without a documentation comment or attribute +* `maxLinesCountBeforeWithoutComment`: maximum number of lines before property without a documentation comment or attribute + +#### SlevomatCodingStandard.Classes.RequireAbstractOrFinal 🔧 + +Requires the class to be declared either as abstract or as final. + +#### SlevomatCodingStandard.Classes.RequireConstructorPropertyPromotion 🔧 + +Requires use of constructor property promotion. + +This sniff provides the following setting: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher. + +#### SlevomatCodingStandard.Classes.RequireMultiLineMethodSignature 🔧 + +Enforces method signature to be split to more lines so each parameter is on its own line. + +Sniff provides the following settings: + +* `minLineLength`: specifies min line length to enforce signature to be split. Use 0 value to enforce for all methods, regardless of length. +* `minParametersCount`: specifies min parameters count to enforce signature to be split. + +* `includedMethodPatterns`: allows to configure which methods are included in sniff detection. This is an array of regular expressions (PCRE) with delimiters. You should not use this with `excludedMethodPatterns`, as it will not work properly. + +* `excludedMethodPatterns`: allows to configure which methods are excluded from sniff detection. This is an array of regular expressions (PCRE) with delimiters. You should not use this with `includedMethodPatterns`, as it will not work properly. + +#### SlevomatCodingStandard.Classes.RequireSelfReference 🔧 + +Requires `self` for local reference. + +#### SlevomatCodingStandard.Classes.RequireSingleLineMethodSignature 🔧 + +Enforces method signature to be on a single line. + +Sniff provides the following settings: + +* `maxLineLength`: specifies max allowed line length. If signature fit on it, it's enforced. Use 0 value to enforce for all methods, regardless of length. + +* `includedMethodPatterns`: allows to configure which methods are included in sniff detection. This is an array of regular expressions (PCRE) with delimiters. You should not use this with `excludedMethodPatterns`, as it will not work properly. + +* `excludedMethodPatterns`: allows to configure which methods are excluded from sniff detection. This is an array of regular expressions (PCRE) with delimiters. You should not use this with `includedMethodPatterns`, as it will not work properly. + +#### SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming + +Reports use of superfluous prefix or suffix "Abstract" for abstract classes. + +#### SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming + +Reports use of superfluous prefix or suffix "Interface" for interfaces. + +#### SlevomatCodingStandard.Classes.SuperfluousExceptionNaming + +Reports use of superfluous suffix "Exception" for exceptions. + +#### SlevomatCodingStandard.Classes.SuperfluousErrorNaming + +Reports use of superfluous suffix "Error" for errors. + +#### SlevomatCodingStandard.Classes.SuperfluousTraitNaming + +Reports use of superfluous suffix "Trait" for traits. + +#### SlevomatCodingStandard.Classes.TraitUseDeclaration 🔧 + +Prohibits multiple traits separated by commas in one `use` statement. + +#### SlevomatCodingStandard.Classes.TraitUseSpacing 🔧 + +Enforces configurable number of lines before first `use`, after last `use` and between two `use` statements. + +Sniff provides the following settings: + +* `linesCountBeforeFirstUse`: allows to configure the number of lines before first `use`. +* `linesCountBeforeFirstUseWhenFirstInClass`: allows to configure the number of lines before first `use` when the `use` is the first statement in the class. +* `linesCountBetweenUses`: allows to configure the number of lines between two `use` statements. +* `linesCountAfterLastUse`: allows to configure the number of lines after last `use`. +* `linesCountAfterLastUseWhenLastInClass`: allows to configure the number of lines after last `use` when the `use` is the last statement in the class. + +#### SlevomatCodingStandard.Classes.UselessLateStaticBinding 🔧 + +Reports useless late static binding. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/commenting.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/commenting.md new file mode 100644 index 000000000..0c4862765 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/commenting.md @@ -0,0 +1,118 @@ +## Commenting + +#### SlevomatCodingStandard.Commenting.AnnotationName 🔧 + +Reports incorrect annotation name. It reports standard annotation names used by phpDocumentor, PHPUnit, PHPStan and Psalm by default. +Unknown annotation names are ignored. + +Sniff provides the following settings: + +* `annotations`: allows to configure which annotations are checked and how. + +#### SlevomatCodingStandard.Commenting.DeprecatedAnnotationDeclaration + +Reports `@deprecated` annotations without description. + +#### SlevomatCodingStandard.Commenting.DisallowCommentAfterCode 🔧 + +Sniff disallows comments after code at the same line. + +#### SlevomatCodingStandard.Commenting.ForbiddenAnnotations 🔧 + +Reports forbidden annotations. No annotations are forbidden by default, the configuration is completely up to the user. It's recommended to forbid obsolete and inappropriate annotations like: + +* `@author`, `@created`, `@version`: we have version control systems. +* `@package`: we have namespaces. +* `@copyright`, `@license`: it's not necessary to repeat licensing information in each file. +* `@throws`: it's not possible to enforce this annotation and the information can become outdated. + +Sniff provides the following settings: + +* `forbiddenAnnotations`: allows to configure which annotations are forbidden to be used. + +#### SlevomatCodingStandard.Commenting.ForbiddenComments 🔧 + +Reports forbidden comments in descriptions. Nothing is forbidden by default, the configuration is completely up to the user. It's recommended to forbid generated or inappropriate messages like: + +* `Constructor.` +* `Created by PhpStorm.` + +Sniff provides the following settings: + +* `forbiddenCommentPatterns`: allows to configure which comments are forbidden to be used. This is an array of regular expressions (PCRE) with delimiters. + +#### SlevomatCodingStandard.Commenting.DocCommentSpacing 🔧 + +Enforces configurable number of lines before first content (description or annotation), after last content (description or annotation), +between description and annotations, between two different annotation types (eg. between `@param` and `@return`). + +Sniff provides the following settings: + +* `linesCountBeforeFirstContent`: allows to configure the number of lines before first content (description or annotation). +* `linesCountBetweenDescriptionAndAnnotations`: allows to configure the number of lines between description and annotations. +* `linesCountBetweenDifferentAnnotationsTypes`: allows to configure the number of lines between two different annotation types. +* `linesCountBetweenAnnotationsGroups`: allows to configure the number of lines between annotation groups. +* `linesCountAfterLastContent`: allows to configure the number of lines after last content (description or annotation). +* `annotationsGroups`: allows to configure order of annotation groups and even order of annotations in every group. Supports prefixes, eg. `@ORM\`. + +```xml + + + + + + + + +``` + +If `annotationsGroups` is set, `linesCountBetweenDifferentAnnotationsTypes` is ignored and `linesCountBetweenAnnotationsGroups` is applied. +If `annotationsGroups` is not set, `linesCountBetweenAnnotationsGroups` is ignored and `linesCountBetweenDifferentAnnotationsTypes` is applied. + +Annotations not in any group are placed to automatically created last group. + +#### SlevomatCodingStandard.Commenting.EmptyComment 🔧 + +Reports empty comments. + +#### SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration 🔧 + +Reports invalid inline phpDocs with `@var`. + +Sniff provides the following settings: + +* `allowDocCommentAboveReturn`: Allows documentation comments without variable name above `return` statement. +* `allowAboveNonAssignment`: Allows documentation comments above non-assignment if the line contains the right variable name. + +#### SlevomatCodingStandard.Commenting.RequireOneLinePropertyDocComment 🔧 + +Requires property comments with single-line content to be written as one-liners. + +#### SlevomatCodingStandard.Commenting.RequireOneLineDocComment 🔧 + +Sniff requires comments with single-line content to be written as one-liners. + +#### SlevomatCodingStandard.Commenting.DisallowOneLinePropertyDocComment 🔧 + +Sniff requires comments with single-line content to be written as multi-liners. + +#### SlevomatCodingStandard.Commenting.UselessFunctionDocComment 🔧 + +* Checks for useless doc comments. If the native method declaration contains everything and the phpDoc does not add anything useful, it's reported as useless and can optionally be automatically removed with `phpcbf`. +* Some phpDocs might still be useful even if they do not add any typehint information. They can contain textual descriptions of code elements and also some meaningful annotations like `@expectException` or `@dataProvider`. + +Sniff provides the following settings: + +* `traversableTypeHints`: enforces which typehints must have specified contained type. E.g. if you set this to `\Doctrine\Common\Collections\Collection`, then `\Doctrine\Common\Collections\Collection` must always be supplied with the contained type: `\Doctrine\Common\Collections\Collection|Foo[]`. + +This sniff can cause an error if you're overriding or implementing a parent method which does not have typehints. In such cases add `@phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint` annotation to the method to have this sniff skip it. + +#### SlevomatCodingStandard.Commenting.UselessInheritDocComment 🔧 + +Reports documentation comments containing only `{@inheritDoc}` annotation because inheritance is automatic, and it's not needed to use a special annotation for it. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/complexity.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/complexity.md new file mode 100644 index 000000000..f77bfcfca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/complexity.md @@ -0,0 +1,10 @@ +## Complexity + +#### SlevomatCodingStandard.Complexity.Cognitive + +Enforces maximum [cognitive complexity](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) for functions. + +Sniff provides the following setting: + +* `warningThreshold`: defaults to 6 +* `errorThreshold` : defaults to 6 diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/control-structures.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/control-structures.md new file mode 100644 index 000000000..760aaa586 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/control-structures.md @@ -0,0 +1,258 @@ +## Control structures + +#### SlevomatCodingStandard.ControlStructures.AssignmentInCondition + +Disallows assignments in `if`, `elseif` and `do-while` loop conditions: + +```php +if ($file = findFile($path)) { + +} +``` + +Assignment in `while` loop condition is specifically allowed because it's commonly used. + +This is a great addition to already existing `SlevomatCodingStandard.ControlStructures.DisallowYodaComparison` because it prevents the danger of assigning something by mistake instead of using a comparison operator like `===`. + +Sniff provides the following settings: +* `ignoreAssignmentsInsideFunctionCalls`: ignores assignment inside function calls, like this: + +```php +if (in_array(1, $haystack, $strict = true)) { + +} +``` + +#### SlevomatCodingStandard.ControlStructures.BlockControlStructureSpacing 🔧 + +Enforces configurable number of lines around block control structures (if, foreach, ...). + +Sniff provides the following settings: + +* `linesCountBefore`: allows to configure the number of lines before control structure. +* `linesCountBeforeFirst`: allows to configure the number of lines before first control structure. +* `linesCountAfter`: allows to configure the number of lines after control structure. +* `linesCountAfterLast`: allows to configure the number of lines after last control structure. +* `controlStructures`: allows to narrow the list of checked control structures. + +For example, with the following setting, only `if` and `switch` keywords are checked. + +```xml + + + + + + + + +``` + +#### SlevomatCodingStandard.ControlStructures.EarlyExit 🔧 + +Requires use of early exit. + +Sniff provides the following settings: + +* `ignoreStandaloneIfInScope`: ignores `if` that is standalone in scope, like this: + +```php +foreach ($values as $value) { + if ($value) { + doSomething(); + } +} +``` + +* `ignoreOneLineTrailingIf`: ignores `if` that has one line content and is on the last position in scope, like this: + +```php +foreach ($values as $value) { + $value .= 'whatever'; + + if ($value) { + doSomething(); + } +} +``` + +* `ignoreTrailingIfWithOneInstruction`: ignores `if` that has only one instruction and is on the last position in scope, like this: + +```php +foreach ($values as $value) { + $value .= 'whatever'; + + if ($value) { + doSomething(function () { + // Anything + }); + } +} +``` + +#### SlevomatCodingStandard.ControlStructures.DisallowContinueWithoutIntegerOperandInSwitch 🔧 + +Disallows use of `continue` without integer operand in `switch` because it emits a warning in PHP 7.3 and higher. + +#### SlevomatCodingStandard.ControlStructures.DisallowEmpty + +Disallows use of `empty()`. + +#### SlevomatCodingStandard.ControlStructures.DisallowNullSafeObjectOperator + +Disallows using `?->` operator. + +#### SlevomatCodingStandard.ControlStructures.DisallowShortTernaryOperator 🔧 + +Disallows short ternary operator `?:`. + +Sniff provides the following settings: + +* `fixable`: the sniff is fixable by default, however in strict code it makes sense to forbid this weakly typed form of ternary altogether, you can disable fixability with this option. + +#### SlevomatCodingStandard.ControlStructures.DisallowTrailingMultiLineTernaryOperator 🔧 + +Ternary operator has to be reformatted when the operator is not leading the line. + +```php +# wrong +$t = $someCondition ? + $thenThis : + $otherwiseThis; + +# correct +$t = $someCondition + ? $thenThis + : $otherwiseThis; +``` + +#### SlevomatCodingStandard.ControlStructures.JumpStatementsSpacing 🔧 + +Enforces configurable number of lines around jump statements (continue, return, ...). + +Sniff provides the following settings: + +* `allowSingleLineYieldStacking`: whether or not to allow multiple yield/yield from statements in a row without blank lines. +* `linesCountBefore`: allows to configure the number of lines before jump statement. +* `linesCountBeforeFirst`: allows to configure the number of lines before first jump statement. +* `linesCountBeforeWhenFirstInCaseOrDefault`: allows to configure the number of lines before jump statement that is first in `case` or `default` +* `linesCountAfter`: allows to configure the number of lines after jump statement. +* `linesCountAfterLast`: allows to configure the number of lines after last jump statement. +* `linesCountAfterWhenLastInCaseOrDefault`: allows to configure the number of lines after jump statement that is last in `case` or `default` +* `linesCountAfterWhenLastInLastCaseOrDefault`: allows to configure the number of lines after jump statement that is last in last `case` or `default` +* `jumpStatements`: allows to narrow the list of checked jump statements. + +For example, with the following setting, only `continue` and `break` keywords are checked. + +```xml + + + + + + + + +``` + +#### SlevomatCodingStandard.ControlStructures.LanguageConstructWithParentheses 🔧 + +`LanguageConstructWithParenthesesSniff` checks and fixes language construct used with parentheses. + +#### SlevomatCodingStandard.ControlStructures.NewWithParentheses 🔧 + +Requires `new` with parentheses. + +#### SlevomatCodingStandard.ControlStructures.NewWithoutParentheses 🔧 + +Reports `new` with useless parentheses. + +#### SlevomatCodingStandard.ControlStructures.RequireMultiLineCondition 🔧 + +Enforces conditions of `if`, `elseif`, `while` and `do-while` with one or more boolean operators to be split to more lines +so each condition part is on its own line. + +Sniff provides the following settings: + +* `minLineLength`: specifies minimum line length to enforce condition to be split. Use 0 value to enforce for all conditions, regardless of length. +* `booleanOperatorOnPreviousLine`: boolean operator is placed at the end of previous line when fixing. +* `alwaysSplitAllConditionParts`: require all condition parts to be on its own line - it reports error even if condition is already multi-line but there are some condition parts on the same line. + +#### SlevomatCodingStandard.ControlStructures.RequireMultiLineTernaryOperator 🔧 + +Ternary operator has to be reformatted to more lines when the line length exceeds the given limit. + +Sniff provides the following settings: + +* `lineLengthLimit` (defaults to `0`) +* `minExpressionsLength` (defaults to `null`): when the expressions after `?` are shorter than this length, the ternary operator does not have to be reformatted. + +#### SlevomatCodingStandard.ControlStructures.RequireNullCoalesceEqualOperator 🔧 + +Requires use of null coalesce equal operator when possible. + +This sniff provides the following setting: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 7.4 or higher. + +#### SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator 🔧 + +Requires use of null coalesce operator when possible. + +#### SlevomatCodingStandard.ControlStructures.RequireNullSafeObjectOperator 🔧 + +Requires using `?->` operator. + +Sniff provides the following settings: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher. + +#### SlevomatCodingStandard.ControlStructures.RequireSingleLineCondition 🔧 + +Enforces conditions of `if`, `elseif`, `while` and `do-while` to be on a single line. + +Sniff provides the following settings: + +* `maxLineLength`: specifies max allowed line length. If condition (and the rest of the line) would fit on it, it's enforced. Use 0 value to enforce for all conditions, regardless of length. +* `alwaysForSimpleConditions`: allows to enforce single line for all simple conditions (i.e no `&&`, `||` or `xor`), regardless of length. + +#### SlevomatCodingStandard.ControlStructures.RequireShortTernaryOperator 🔧 + +Requires short ternary operator `?:` when possible. + +#### SlevomatCodingStandard.ControlStructures.RequireTernaryOperator 🔧 + +Requires ternary operator when possible. + +Sniff provides the following settings: + +* `ignoreMultiLine` (defaults to `false`): ignores multi-line statements. + +#### SlevomatCodingStandard.ControlStructures.DisallowYodaComparison 🔧 +#### SlevomatCodingStandard.ControlStructures.RequireYodaComparison 🔧 + +[Yoda conditions](https://en.wikipedia.org/wiki/Yoda_conditions) decrease code comprehensibility and readability by switching operands around comparison operators forcing the reader to read the code in an unnatural way. + +Sniff provides the following settings: + +* `alwaysVariableOnRight` (defaults to `false`): moves variables always to right. + +`DisallowYodaComparison` looks for and fixes such comparisons not only in `if` statements but in the whole code. + +However, if you prefer Yoda conditions, you can use `RequireYodaComparison`. + +#### SlevomatCodingStandard.ControlStructures.UselessIfConditionWithReturn 🔧 + +Reports useless conditions where both branches return `true` or `false`. + +Sniff provides the following settings: + +* `assumeAllConditionExpressionsAreAlreadyBoolean` (defaults to `false`). + +#### SlevomatCodingStandard.ControlStructures.UselessTernaryOperator 🔧 + +Reports useless ternary operator where both branches return `true` or `false`. + +Sniff provides the following settings: + +* `assumeAllConditionExpressionsAreAlreadyBoolean` (defaults to `false`). diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/exceptions.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/exceptions.md new file mode 100644 index 000000000..bc675f25e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/exceptions.md @@ -0,0 +1,31 @@ +## Exceptions + +#### SlevomatCodingStandard.Exceptions.DeadCatch + +This sniff finds unreachable catch blocks: + +```php +try { + doStuff(); +} catch (\Throwable $e) { + log($e); +} catch (\InvalidArgumentException $e) { + // unreachable! +} +``` + +#### SlevomatCodingStandard.Exceptions.DisallowNonCapturingCatch + +This sniff forbids use of non-capturing catch introduced in PHP 8.0 [PHP RFC: non-capturing catches](https://wiki.php.net/rfc/non-capturing_catches). + +#### SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly 🔧🚧 + +In PHP 7.0, a [`Throwable` interface was added](https://wiki.php.net/rfc/throwable-interface) that allows catching and handling errors in more cases than `Exception` previously allowed. So, if the catch statement contained `Exception` on PHP 5.x, it means it should probably be rewritten to reference `Throwable` on PHP 7.x. This sniff enforces that. + +#### SlevomatCodingStandard.Exceptions.RequireNonCapturingCatch 🔧 + +Sniff provides the following settings: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher. + +It requires non-capturing catch when the variable with exception is not used. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/files.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/files.md new file mode 100644 index 000000000..096c65bc0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/files.md @@ -0,0 +1,59 @@ +## Files + +#### SlevomatCodingStandard.Files.FileLength + +Disallows long files. This sniff provides the following settings: + +* `includeComments`: should comments be included in the count (default value is false). +* `includeWhitespace`: should empty lines be included in the count (default value is false). +* `maxLinesLength`: specifies max allowed function lines length (default value is 250). + +#### SlevomatCodingStandard.Files.LineLength + +Enforces maximum length of a single line of code. + +Sniff provides the following settings: + +* `lineLengthLimit`: actual limit of the line length +* `ignoreComments`: whether to ignore line length of comments +* `ignoreImports`: whether to ignore line length of import (use) statements + +#### SlevomatCodingStandard.Files.TypeNameMatchesFileName + +For projects not following the [PSR-0](http://www.php-fig.org/psr/psr-0/) or [PSR-4](http://www.php-fig.org/psr/psr-4/) autoloading standards, this sniff checks whether a namespace and a name of a class/interface/trait follows agreed-on way to organize code into directories and files. + +Other than enforcing that the type name must match the name of the file it's contained in, this sniff is very configurable. Consider the following sample configuration: + +```xml + + + + + + + + + + + + + + + + + + + + + + + + +``` + +Sniff provides the following settings: + +* `rootNamespaces` property expects configuration similar to PSR-4 - project directories mapped to certain namespaces. +* `skipDirs` are not taken into consideration when comparing a path to a namespace. For example, with the above settings, file at path `app/services/Product/Product.php` is expected to contain `Slevomat\Product\Product`, not `Slevomat\services\Product\Product`. +* `extensions`: allow different file extensions. Default is `php`. +* `ignoredNamespaces`: sniff is not performed on these namespaces. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/functions.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/functions.md new file mode 100644 index 000000000..2766552c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/functions.md @@ -0,0 +1,136 @@ +## Functions + +#### SlevomatCodingStandard.Functions.ArrowFunctionDeclaration 🔧 + +Checks `fn` declaration. + +Sniff provides the following settings: + +* `spacesCountAfterKeyword`: the number of spaces after `fn`. +* `spacesCountBeforeArrow`: the number of spaces before `=>`. +* `spacesCountAfterArrow`: the number of spaces after `=>`. +* `allowMultiLine`: allows multi-line declaration. + +#### SlevomatCodingStandard.Functions.DisallowArrowFunction + +Disallows arrow functions. + +#### SlevomatCodingStandard.Functions.DisallowEmptyFunction + +Reports empty functions body and requires at least a comment inside. + +#### SlevomatCodingStandard.Functions.FunctionLength + +Disallows long functions. This sniff provides the following setting: + +* `includeComments`: should comments be included in the count (default value is false). +* `includeWhitespace`: should empty lines be included in the count (default value is false). +* `maxLinesLength`: specifies max allowed function lines length (default value is 20). + +#### SlevomatCodingStandard.Functions.RequireArrowFunction 🔧 + +Requires arrow functions. + +Sniff provides the following settings: + +* `allowNested` (defaults to `true`) +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 7.4 or higher. + +#### SlevomatCodingStandard.Functions.RequireMultiLineCall 🔧 + +Enforces function call to be split to more lines so each parameter is on its own line. + +Sniff provides the following settings: + +* `minLineLength`: specifies min line length to enforce call to be split. Use 0 value to enforce for all calls, regardless of length. + +#### SlevomatCodingStandard.Functions.RequireSingleLineCall 🔧 + +Enforces function call to be on a single line. + +Sniff provides the following settings: + +* `maxLineLength`: specifies max allowed line length. If call would fit on it, it's enforced. Use 0 value to enforce for all calls, regardless of length. +* `ignoreWithComplexParameter` (defaults to `true`): ignores calls with arrays, closures, arrow functions and nested calls. + +#### SlevomatCodingStandard.Functions.DisallowNamedArguments + +This sniff disallows usage of named arguments. + +#### SlevomatCodingStandard.Functions.NamedArgumentSpacing 🔧 + +Checks spacing in named argument. + +#### SlevomatCodingStandard.Functions.DisallowTrailingCommaInCall 🔧 + +This sniff disallows trailing commas in multi-line calls. + +This sniff provides the following setting: + +* `onlySingleLine`: to enable checks only for single-line calls. + +#### SlevomatCodingStandard.Functions.RequireTrailingCommaInCall 🔧 + +Commas after the last parameter in function or method call make adding a new parameter easier and result in a cleaner versioning diff. + +This sniff enforces trailing commas in multi-line calls. + +This sniff provides the following setting: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 7.3 or higher. + +#### SlevomatCodingStandard.Functions.DisallowTrailingCommaInClosureUse 🔧 + +This sniff disallows trailing commas in multi-line `use` of closure declaration. + +This sniff provides the following setting: + +* `onlySingleLine`: to enable checks only for single-line `use` declarations. + +#### SlevomatCodingStandard.Functions.RequireTrailingCommaInClosureUse 🔧 + +Commas after the last inherited variable in multi-line `use` of closure declaration make adding a new variable easier and result in a cleaner versioning diff. + +This sniff enforces trailing commas in multi-line declarations. + +This sniff provides the following setting: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher. + +#### SlevomatCodingStandard.Functions.DisallowTrailingCommaInDeclaration 🔧 + +This sniff disallows trailing commas in multi-line declarations. + +This sniff provides the following setting: + +* `onlySingleLine`: to enable checks only for single-line declarations. + +#### SlevomatCodingStandard.Functions.RequireTrailingCommaInDeclaration 🔧 + +Commas after the last parameter in function or method declaration make adding a new parameter easier and result in a cleaner versioning diff. + +This sniff enforces trailing commas in multi-line declarations. + +This sniff provides the following setting: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher. + +#### SlevomatCodingStandard.Functions.StaticClosure 🔧 + +Reports closures not using `$this` that are not declared `static`. + +#### SlevomatCodingStandard.Functions.StrictCall + +Some functions have `$strict` parameter. This sniff reports calls to these functions without the parameter or with `$strict = false`. + +#### SlevomatCodingStandard.Functions.UnusedInheritedVariablePassedToClosure 🔧 + +Looks for unused inherited variables passed to closure via `use`. + +#### SlevomatCodingStandard.Functions.UnusedParameter 🚧 + +Looks for unused parameters. + +#### SlevomatCodingStandard.Functions.UselessParameterDefaultValue 🚧 + +Looks for useless parameter default value. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/namespaces.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/namespaces.md new file mode 100644 index 000000000..3c5d6cd69 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/namespaces.md @@ -0,0 +1,186 @@ +## Namespaces + +#### SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses 🔧 + +Sniff checks whether `use` declarations at the top of a file are alphabetically sorted. Follows natural sorting and takes edge cases with special symbols into consideration. The following code snippet is an example of correctly sorted uses: + +```php +use LogableTrait; +use LogAware; +use LogFactory; +use LoggerInterface; +use LogLevel; +use LogStandard; +``` + +Sniff provides the following settings: + + +* `psr12Compatible` (defaults to `true`): sets the required order to `classes`, `functions` and `constants`. `false` sets the required order to `classes`, `constants` and `functions`. +* `caseSensitive`: compare namespaces case sensitively, which makes this order correct: + +```php +use LogAware; +use LogFactory; +use LogLevel; +use LogStandard; +use LogableTrait; +use LoggerInterface; +``` + +#### SlevomatCodingStandard.Namespaces.DisallowGroupUse + +[Group use declarations](https://wiki.php.net/rfc/group_use_declarations) are ugly, make diffs ugly and this sniff prohibits them. + +#### SlevomatCodingStandard.Namespaces.FullyQualifiedExceptions 🔧 + +This sniff reduces confusion in the following code snippet: + +```php +try { + $this->foo(); +} catch (Exception $e) { + // Is this the general exception all exceptions must extend from? Or Exception from the current namespace? +} +``` + +All references to types named `Exception` or ending with `Exception` must be referenced via a fully qualified name: + +```php +try { + $this->foo(); +} catch (\FooCurrentNamespace\Exception $e) { + +} catch (\Exception $e) { + +} +``` + +Sniff provides the following settings: + +* Exceptions with different names can be configured in `specialExceptionNames` property. +* If your codebase uses classes that look like exceptions (because they have `Exception` or `Error` suffixes) but aren't, you can add them to `ignoredNames` property and the sniff won't enforce them to be fully qualified. Classes with `Error` suffix have to be added to ignored only if they are in the root namespace (like `LibXMLError`). + +#### SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalConstants 🔧 + +All references to global constants must be referenced via a fully qualified name. + +Sniff provides the following settings: + +* `include`: list of global constants that must be referenced via FQN. If not set all constants are considered. +* `exclude`: list of global constants that are allowed not to be referenced via FQN. + +#### SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions 🔧 + +All references to global functions must be referenced via a fully qualified name. + +Sniff provides the following settings: + +* `include`: list of global functions that must be referenced via FQN. If not set all functions are considered. +* `includeSpecialFunctions`: include complete list of PHP internal functions that could be optimized when referenced via FQN. +* `exclude`: list of global functions that are allowed not to be referenced via FQN. + +#### SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameInAnnotation 🔧 + +Enforces fully qualified names of classes and interfaces in phpDocs - in annotations. This results in unambiguous phpDocs. + +Sniff provides the following settings: + +* `ignoredAnnotationNames`: case-sensitive list of annotation names that the sniff should ignore. Useful for custom annotation names like `@apiParam` + +#### SlevomatCodingStandard.Namespaces.MultipleUsesPerLine + +Prohibits multiple uses separated by commas: + +```php +use Foo, Bar; +``` + +#### SlevomatCodingStandard.Namespaces.NamespaceDeclaration 🔧 + +Enforces one space after `namespace`, disallows content between namespace name and semicolon and disallows use of bracketed syntax. + +#### SlevomatCodingStandard.Namespaces.NamespaceSpacing 🔧 + +Enforces configurable number of lines before and after `namespace`. + +Sniff provides the following settings: + +* `linesCountBeforeNamespace`: allows to configure the number of lines before `namespace`. +* `linesCountAfterNamespace`: allows to configure the number of lines after `namespace`. + +#### SlevomatCodingStandard.Namespaces.RequireOneNamespaceInFile + +Requires only one namespace in a file. + +#### SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly 🔧 + +Sniff provides the following settings: + +* `searchAnnotations` (defaults to `false`): enables searching for mentions in annotations. +* `namespacesRequiredToUse`: if not set, all namespaces are required to be used. When set, only mentioned namespaces are required to be used. Useful in tandem with UseOnlyWhitelistedNamespaces sniff. +* `allowFullyQualifiedExceptions`, `specialExceptionNames` & `ignoredNames`: allows fully qualified exceptions. Useful in tandem with FullyQualifiedExceptions sniff. +* `allowFullyQualifiedNameForCollidingClasses`: allow fully qualified name for a class with a colliding use statement. +* `allowFullyQualifiedNameForCollidingFunctions`: allow fully qualified name for a function with a colliding use statement. +* `allowFullyQualifiedNameForCollidingConstants`: allow fully qualified name for a constant with a colliding use statement. +* `allowFullyQualifiedGlobalClasses`: allows using fully qualified classes from global space (i.e. `\DateTimeImmutable`). +* `allowFullyQualifiedGlobalFunctions`: allows using fully qualified functions from global space (i.e. `\phpversion()`). +* `allowFullyQualifiedGlobalConstants`: allows using fully qualified constants from global space (i.e. `\PHP_VERSION`). +* `allowFallbackGlobalFunctions`: allows using global functions via fallback name without `use` (i.e. `phpversion()`). +* `allowFallbackGlobalConstants`: allows using global constants via fallback name without `use` (i.e. `PHP_VERSION`). +* `allowPartialUses`: allows using and referencing whole namespaces. + +#### SlevomatCodingStandard.Namespaces.UseFromSameNamespace 🔧 + +Sniff prohibits uses from the same namespace: + +```php +namespace Foo; + +use Foo\Bar; +``` + +#### SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash 🔧 + +Disallows leading backslash in use statement: + +```php +use \Foo\Bar; +``` + +#### SlevomatCodingStandard.Namespaces.UseSpacing 🔧 + +Enforces configurable number of lines before first `use`, after last `use` and between two different types of `use` (eg. between `use function` and `use const`). Also enforces zero number of lines between same types of `use`. + +Sniff provides the following settings: + +* `linesCountBeforeFirstUse`: allows to configure the number of lines before first `use`. +* `linesCountBetweenUseTypes`: allows to configure the number of lines between two different types of `use`. +* `linesCountAfterLastUse`: allows to configure the number of lines after last `use`. + +#### SlevomatCodingStandard.Namespaces.UseOnlyWhitelistedNamespaces + +Sniff disallows uses of other than configured namespaces. + +Sniff provides the following settings: + +* `namespacesRequiredToUse`: namespaces in this array are the only ones allowed to be used. E.g. root project namespace. +* `allowUseFromRootNamespace`: also allow using top-level namespace: + +```php +use DateTimeImmutable; +``` + +#### SlevomatCodingStandard.Namespaces.UselessAlias 🔧 + +Looks for `use` alias that is same as unqualified name. + +#### SlevomatCodingStandard.Namespaces.UnusedUses 🔧 + +Looks for unused imports from other namespaces. + +Sniff provides the following settings: + +* `searchAnnotations` (defaults to `false`): enables searching for class names in annotations. +* `ignoredAnnotationNames`: case-sensitive list of annotation names that the sniff should ignore (only the name is ignored, annotation content is still searched). Useful for name collisions like `@testCase` annotation and `TestCase` class. +* `ignoredAnnotations`: case-sensitive list of annotation names that the sniff ignore completely (both name and content are ignored). Useful for name collisions like `@group Cache` annotation and `Cache` class. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/numbers.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/numbers.md new file mode 100644 index 000000000..8df99a236 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/numbers.md @@ -0,0 +1,16 @@ +## Numbers + +#### SlevomatCodingStandard.Numbers.DisallowNumericLiteralSeparator 🔧 + +Disallows numeric literal separators. + +#### SlevomatCodingStandard.Numbers.RequireNumericLiteralSeparator + +Requires use of numeric literal separators. + +This sniff provides the following setting: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 7.4 or higher. +* `minDigitsBeforeDecimalPoint`: the minimum digits before decimal point to require separator. +* `minDigitsAfterDecimalPoint`: the minimum digits after decimal point to require separator. +* `ignoreOctalNumbers`: to ignore octal numbers. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/operators.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/operators.md new file mode 100644 index 000000000..0fcd6e4d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/operators.md @@ -0,0 +1,33 @@ +## Operators + +#### SlevomatCodingStandard.Operators.DisallowEqualOperators 🔧 + +Disallows using loose `==` and `!=` comparison operators. Use `===` and `!==` instead, they are much more secure and predictable. + +#### SlevomatCodingStandard.Operators.DisallowIncrementAndDecrementOperators + +Disallows using `++` and `--` operators. + +#### SlevomatCodingStandard.Operators.NegationOperatorSpacing 🔧 + +Checks if there is the same number of spaces after negation operator as expected. + +Sniff provides the following settings: + +* `spacesCount`: the number of spaces expected after the negation operator + +#### SlevomatCodingStandard.Operators.RequireCombinedAssignmentOperator 🔧 + +Requires using combined assignment operators, eg `+=`, `.=` etc. + +#### SlevomatCodingStandard.Operators.RequireOnlyStandaloneIncrementAndDecrementOperators + +Reports `++` and `--` operators not used standalone. + +#### SlevomatCodingStandard.Operators.SpreadOperatorSpacing 🔧 + +Enforces configurable number of spaces after the `...` operator. + +Sniff provides the following settings: + +* `spacesCountAfterOperator`: the number of spaces after the `...` operator. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/php.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/php.md new file mode 100644 index 000000000..e174028cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/php.md @@ -0,0 +1,80 @@ +## PHP + +#### SlevomatCodingStandard.PHP.DisallowDirectMagicInvokeCall 🔧 + +Disallows direct call of `__invoke()`. + +#### SlevomatCodingStandard.PHP.DisallowReference + +Sniff disallows usage of references. + +#### SlevomatCodingStandard.PHP.ForbiddenClasses 🔧 + +Reports usage of forbidden classes, interfaces, parent classes and traits. And provide the following settings: + +* `forbiddenClasses`: forbids creating instances with `new` keyword or accessing with `::` operator +* `forbiddenExtends`: forbids extending with `extends` keyword +* `forbiddenInterfaces`: forbids usage in `implements` section +* `forbiddenTraits`: forbids imports with `use` keyword + +Optionally can be passed as an alternative for auto fixes. See `phpcs.xml` file example: + +```xml + + + + + + + + + + +``` + +#### SlevomatCodingStandard.PHP.ReferenceSpacing 🔧 + +Enforces configurable number of spaces after reference. + +Sniff provides the following settings: + +* `spacesCountAfterReference`: the number of spaces after `&`. + +#### SlevomatCodingStandard.PHP.RequireExplicitAssertion 🔧 + +Requires assertion via `assert` instead of inline documentation comments. + +Sniff provides the following settings: + +* `enableIntegerRanges` (defaults to `false`): enables support for `positive-int`, `negative-int` and `int<0, 100>`. +* `enableAdvancedStringTypes` (defaults to `false`): enables support for `callable-string`, `numeric-string` and `non-empty-string`. + +#### SlevomatCodingStandard.PHP.RequireNowdoc 🔧 + +Requires nowdoc syntax instead of heredoc when possible. + +#### SlevomatCodingStandard.PHP.OptimizedFunctionsWithoutUnpacking + +PHP optimizes some internal functions into special opcodes on VM level. Such optimization results in much faster execution compared to calling standard functions. This only works when these functions are not invoked with argument unpacking (`...`). + +The list of these functions varies across PHP versions, but is the same as functions that must be referenced by their global name (either by `\ ` prefix or using `use function`), not a fallback name inside namespaced code. + +#### SlevomatCodingStandard.PHP.ShortList 🔧 + +Enforces using short form of list syntax, `[...]` instead of `list(...)`. + +#### SlevomatCodingStandard.PHP.TypeCast 🔧 + +Enforces using shorthand cast operators, forbids use of unset and binary cast operators: `(bool)` instead of `(boolean)`, `(int)` instead of `(integer)`, `(float)` instead of `(double)` or `(real)`. `(binary)` and `(unset)` are forbidden. + +#### SlevomatCodingStandard.PHP.UselessParentheses 🔧 + +Looks for useless parentheses. + +Sniff provides the following settings: + +* `ignoreComplexTernaryConditions` (defaults to `false`): ignores complex ternary conditions - condition must contain `&&`, `||` etc. or end of line. + +#### SlevomatCodingStandard.PHP.UselessSemicolon 🔧 + +Looks for useless semicolons. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/strings.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/strings.md new file mode 100644 index 000000000..17fcc7cc4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/strings.md @@ -0,0 +1,11 @@ +## Strings + +#### SlevomatCodingStandard.Strings.DisallowVariableParsing + +Disallows variable parsing inside strings. + +Sniff provides the following settings: + +* `disallowDollarCurlySyntax`: disallows usage of `${...}`, enabled by default. +* `disallowCurlyDollarSyntax`: disallows usage of `{$...}`, disabled by default. +* `disallowSimpleSyntax`: disallows usage of `$...`, disabled by default. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/type-hints.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/type-hints.md new file mode 100644 index 000000000..f52e2b1d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/type-hints.md @@ -0,0 +1,130 @@ +## Type hints + +#### SlevomatCodingStandard.TypeHints.DeclareStrictTypes 🔧 + +Enforces having `declare(strict_types = 1)` at the top of each PHP file. Allows configuring how many newlines should be between the ``, `array>`). + +Sniff provides the following settings: + +* `traversableTypeHints`: helps fixer detect traversable type hints so `\Traversable|int[]` can be converted to `\Traversable`. + +#### SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint + +Disallows usage of "mixed" type hint in phpDocs. + +#### SlevomatCodingStandard.TypeHints.LongTypeHints 🔧 + +Enforces using shorthand scalar typehint variants in phpDocs: `int` instead of `integer` and `bool` instead of `boolean`. This is for consistency with native scalar typehints which also allow shorthand variants only. + +#### SlevomatCodingStandard.TypeHints.NullTypeHintOnLastPosition 🔧 + +Enforces `null` type hint on last position in annotations. + +#### SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue 🔧🚧 + +Checks whether the nullablity `?` symbol is present before each nullable and optional parameter (which are marked as `= null`): + +```php +function foo( + int $foo = null, // ? missing + ?int $bar = null // correct +) { + +} +``` + +#### SlevomatCodingStandard.TypeHints.ParameterTypeHint 🔧🚧 + +* Checks for missing parameter typehints in case they can be declared natively. If the phpDoc contains something that can be written as a native PHP 7.0+ typehint, this sniff reports that. +* Checks for useless `@param` annotations. If the native method declaration contains everything and the phpDoc does not add anything useful, it's reported as useless and can optionally be automatically removed with `phpcbf`. +* Forces to specify what's in traversable types like `array`, `iterable` and `\Traversable`. + +Sniff provides the following settings: + +* `enableObjectTypeHint`: enforces to transform `@param object` into native `object` typehint. It's on by default if you're on PHP 7.2+ +* `enableMixedTypeHint`: enforces to transform `@param mixed` into native `mixed` typehint. It's on by default if you're on PHP 8.0+ +* `enableUnionTypeHint`: enforces to transform `@param string|int` into native `string|int` typehint. It's on by default if you're on PHP 8.0+ +* `enableIntersectionTypeHint`: enforces to transform `@param Foo&Bar` into native `Foo&Bar` typehint. It's on by default if you're on PHP 8.1+ +* `enableStandaloneNullTrueFalseTypeHints`: enforces to transform `@param true`, `@param false` or `@param null` into native typehints. It's on by default if you're on PHP 8.2+ +* `traversableTypeHints`: enforces which typehints must have specified contained type. E.g. if you set this to `\Doctrine\Common\Collections\Collection`, then `\Doctrine\Common\Collections\Collection` must always be supplied with the contained type: `\Doctrine\Common\Collections\Collection|Foo[]`. + +This sniff can cause an error if you're overriding or implementing a parent method which does not have typehints. In such cases add `@phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint` annotation to the method to have this sniff skip it. + +#### SlevomatCodingStandard.TypeHints.ParameterTypeHintSpacing 🔧 + +* Checks that there's a single space between a typehint and a parameter name: `Foo $foo` +* Checks that there's no whitespace between a nullability symbol and a typehint: `?Foo` + +#### SlevomatCodingStandard.TypeHints.PropertyTypeHint 🔧🚧 + +* Checks for missing property typehints in case they can be declared natively. If the phpDoc contains something that can be written as a native PHP 7.4+ typehint, this sniff reports that. +* Checks for useless `@var` annotations. If the native method declaration contains everything and the phpDoc does not add anything useful, it's reported as useless and can optionally be automatically removed with `phpcbf`. +* Forces to specify what's in traversable types like `array`, `iterable` and `\Traversable`. + +Sniff provides the following settings: + +* `enableNativeTypeHint`: enforces to transform `@var int` into native `int` typehint. It's on by default if you're on PHP 7.4+ +* `enableMixedTypeHint`: enforces to transform `@var mixed` into native `mixed` typehint. It's on by default if you're on PHP 8.0+. It can be enabled only when `enableNativeTypeHint` is enabled too. +* `enableUnionTypeHint`: enforces to transform `@var string|int` into native `string|int` typehint. It's on by default if you're on PHP 8.0+. It can be enabled only when `enableNativeTypeHint` is enabled too. +* `enableIntersectionTypeHint`: enforces to transform `@var Foo&Bar` into native `Foo&Bar` typehint. It's on by default if you're on PHP 8.1+. It can be enabled only when `enableNativeTypeHint` is enabled too. +* `enableStandaloneNullTrueFalseTypeHints`: enforces to transform `@var true`, `@var false` or `@var null` into native typehints. It's on by default if you're on PHP 8.2+. It can be enabled only when `enableNativeTypeHint` is enabled too. +* `traversableTypeHints`: enforces which typehints must have specified contained type. E.g. if you set this to `\Doctrine\Common\Collections\Collection`, then `\Doctrine\Common\Collections\Collection` must always be supplied with the contained type: `\Doctrine\Common\Collections\Collection|Foo[]`. + +This sniff can cause an error if you're overriding parent property which does not have typehints. In such cases add `@phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint` annotation to the property to have this sniff skip it. + +#### SlevomatCodingStandard.TypeHints.ReturnTypeHint 🔧🚧 + +* Checks for missing return typehints in case they can be declared natively. If the phpDoc contains something that can be written as a native PHP 7.0+ typehint, this sniff reports that. +* Checks for useless `@return` annotations. If the native method declaration contains everything and the phpDoc does not add anything useful, it's reported as useless and can optionally be automatically removed with `phpcbf`. +* Forces to specify what's in traversable types like `array`, `iterable` and `\Traversable`. + +Sniff provides the following settings: + +* `enableObjectTypeHint`: enforces to transform `@return object` into native `object` typehint. It's on by default if you're on PHP 7.2+ +* `enableStaticTypeHint`: enforces to transform `@return static` into native `static` typehint. It's on by default if you're on PHP 8.0+ +* `enableMixedTypeHint`: enforces to transform `@return mixed` into native `mixed` typehint. It's on by default if you're on PHP 8.0+ +* `enableUnionTypeHint`: enforces to transform `@return string|int` into native `string|int` typehint. It's on by default if you're on PHP 8.0+. +* `enableIntersectionTypeHint`: enforces to transform `@return Foo&Bar` into native `Foo&Bar` typehint. It's on by default if you're on PHP 8.1+. +* `enableNeverTypeHint`: enforces to transform `@return never` into native `never` typehint. It's on by default if you're on PHP 8.1+. +* `enableStandaloneNullTrueFalseTypeHints`: enforces to transform `@return true`, `@return false` or `@return null` into native typehints. It's on by default if you're on PHP 8.2+. +* `traversableTypeHints`: enforces which typehints must have specified contained type. E.g. if you set this to `\Doctrine\Common\Collections\Collection`, then `\Doctrine\Common\Collections\Collection` must always be supplied with the contained type: `\Doctrine\Common\Collections\Collection|Foo[]`. + +This sniff can cause an error if you're overriding or implementing a parent method which does not have typehints. In such cases add `@phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint` annotation to the method to have this sniff skip it. + +#### SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing 🔧 + +Enforces consistent formatting of return typehints, like this: + +```php +function foo(): ?int +``` + +Sniff provides the following settings: + +* `spacesCountBeforeColon`: the number of spaces expected between closing brace and colon. + +#### SlevomatCodingStandard.TypeHints.UnionTypeHintFormat 🔧 + +Checks format of union type hints. + +Sniff provides the following settings: + +* `enable`: either to enable or not this sniff. By default, it is enabled for PHP versions 8.0 or higher. +* `withSpaces`: `yes` requires spaces around `|`, `no` requires no space around `|`. None is set by default so both are enabled. +* `shortNullable`: `yes` requires usage of `?` for nullable type hint, `no` disallows it. None is set by default so both are enabled. +* `nullPosition`: `first` requires `null` on first position in the type hint, `last` requires last position. None is set by default so `null` can be everywhere. + +#### SlevomatCodingStandard.TypeHints.UselessConstantTypeHint 🔧 + +Reports useless `@var` annotation (or whole documentation comment) for constants because the type of constant is always clear. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/variables.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/variables.md new file mode 100644 index 000000000..c1f6c292e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/variables.md @@ -0,0 +1,31 @@ +## Variables + +#### SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable + +Disallows use of super global variables. + +#### SlevomatCodingStandard.Variables.DisallowVariableVariable + +Disallows use of variable variables. + +#### SlevomatCodingStandard.Variables.DuplicateAssignmentToVariable + +Looks for duplicate assignments to a variable. + +#### SlevomatCodingStandard.Variables.UnusedVariable + +Looks for unused variables. + +Sniff provides the following settings: + +* `ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach` (defaults to `false`): ignore unused `$value` in foreach when only `$key` is used + +```php +foreach ($values as $key => $value) { + echo $key; +} +``` + +#### SlevomatCodingStandard.Variables.UselessVariable 🔧 + +Looks for useless variables. diff --git a/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/whitespaces.md b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/whitespaces.md new file mode 100644 index 000000000..4f3a92f57 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/slevomat/coding-standard/doc/whitespaces.md @@ -0,0 +1,13 @@ +## Whitespaces + +#### SlevomatCodingStandard.Whitespaces.DuplicateSpaces 🔧 + +Checks duplicate spaces anywhere because there aren't sniffs for every part of code to check formatting. + +Sniff provides the following settings: + +* `ignoreSpacesBeforeAssignment`: to allow multiple spaces to align assignments. +* `ignoreSpacesInAnnotation`: to allow multiple spaces to align annotations. +* `ignoreSpacesInComment`: to allow multiple spaces to align content of the comment. +* `ignoreSpacesInParameters`: to allow multiple spaces to align parameters. +* `ignoreSpacesInMatch`: to allow multiple spaces to align `match` expressions. diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CHANGELOG.md b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CHANGELOG.md new file mode 100644 index 000000000..5a4ba6aed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CHANGELOG.md @@ -0,0 +1,7501 @@ +# Changelog + +The file documents changes to the PHP_CodeSniffer project. + +## [Unreleased] + +_Nothing yet._ + +## [3.11.1] - 2024-11-16 + +### Changed +- Output from the `--generator=...` feature will respect the OS-expected EOL char in more places. [#671] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Bartosz DziewoÅ„ski][@MatmaRex] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#674] : Generic.WhiteSpace.HereNowdocIdentifierSpacing broken XML documentation + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Fixed bug [#675] : InvalidArgumentException when a ruleset includes a sniff by file name and the included sniff does not comply with the PHPCS naming conventions. + - Notwithstanding this fix, it is strongly recommended to ensure custom sniff classes comply with the PHPCS naming conventions. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. + +[#671]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/671 +[#674]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/674 +[#675]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/675 + +## [3.11.0] - 2024-11-12 + +### Added +- Runtime support for PHP 8.4. All known PHP 8.4 deprecation notices have been fixed. + - Syntax support for new PHP 8.4 features will follow in a future release. + - If you find any PHP 8.4 deprecation notices which were missed, please report them. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches. +- Tokenizer support for PHP 8.3 "yield from" expressions with a comment between the keywords. [#529], [#647] + - Sniffs explicitly handling T_YIELD_FROM tokens may need updating. The PR description contains example code for use by sniff developers. + - Additionally, the following sniff has been updated to support "yield from" expressions with comments: + - Generic.WhiteSpace.LanguageConstructSpacing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- New `Generic.WhiteSpace.HereNowdocIdentifierSpacing` sniff. [#586], [#637] + - Forbid whitespace between the `<<<` and the identifier string in heredoc/nowdoc start tokens. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- New `Generic.Strings.UnnecessaryHeredoc` sniff. [#633] + - Warns about heredocs without interpolation or expressions in the body text and can auto-fix these to nowdocs. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Documentation for the following sniffs: + - Generic.Arrays.ArrayIndent + - Squiz.PHP.Heredoc + - Thanks to [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for the patches. + +### Changed +- The Common::getSniffCode() method will now throw an InvalidArgumentException exception if an invalid `$sniffClass` is passed. [#524], [#625] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Documentation generated using the `--generator=...` feature will now always be presented in natural order based on the sniff name(s). [#668] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Minor improvements to the display of runtime information. [#658] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Squiz.Commenting.PostStatementComment: trailing annotations in PHP files will now be reported under a separate, non-auto-fixable error code `AnnotationFound`. [#560], [#627] + - This prevents (tooling related) annotations from taking on a different meaning when moved by the fixer. + - The separate error code also allows for selectively excluding it to prevent the sniff from triggering on trailing annotations, while still forbidding other trailing comments. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Squiz.ControlStructures.ForEachLoopDeclaration: the `SpacingAfterOpen` error code has been replaced by the `SpaceAfterOpen` error code. The latter is a pre-existing code. The former appears to have been a typo. [#582] + - Thanks to [Dan Wallis][@fredden] for the patch. +- The following sniff(s) have received efficiency improvements: + - Generic.Classes.DuplicateClassName + - Generic.NamingConventions.ConstructorName + - Thanks to [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for the patches. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#3808][sq-3808] : Generic.WhiteSpace.ScopeIndent would throw false positive for tab indented multi-token yield from expression. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#630] : The tokenizer could inadvertently transform "normal" parentheses to DNF parentheses, when a function call was preceded by a switch-case / alternative syntax control structure colon. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#645] : On PHP 5.4, if yield was used as the declaration name for a function declared to return by reference, the function name would incorrectly be tokenized as T_YIELD instead of T_STRING. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#647] : Tokenizer not applying tab replacement in single token "yield from" keywords. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#647] : Generic.WhiteSpace.DisallowSpaceIndent did not flag space indentation in multi-line yield from. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#647] : Generic.WhiteSpace.DisallowTabIndent did not flag tabs inside yield from. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#652] : Generic.NamingConventions.ConstructorName: false positives for PHP-4 style calls to PHP-4 style parent constructor when a method with the same name as the parent class was called on another class. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#652] : Generic.NamingConventions.ConstructorName: false negatives for PHP-4 style calls to parent constructor for function calls with whitespace and comments in unconventional places. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#653] : Generic.Classes.DuplicateClassName : the sniff did not skip namespace keywords used as operators, which could lead to false positives. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#653] : Generic.Classes.DuplicateClassName : sniff going into an infinite loop during live coding. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#653] : Generic.Classes.DuplicateClassName : false positives/negatives when a namespace declaration contained whitespace or comments in unconventional places. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#653] : Generic.Classes.DuplicateClassName : namespace for a file going in/out of PHP was not remembered/applied correctly. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-3808]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3808 +[#524]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/524 +[#529]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/529 +[#560]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/560 +[#582]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/582 +[#586]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/586 +[#625]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/625 +[#627]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/627 +[#630]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/630 +[#633]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/633 +[#637]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/637 +[#645]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/645 +[#647]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/647 +[#652]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/652 +[#653]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/653 +[#658]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/658 +[#668]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/668 + +## [3.10.3] - 2024-09-18 + +### Changed +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#553] : Squiz.Classes.SelfMemberReference: false negative(s) when namespace operator was encountered between the namespace declaration and the OO declaration. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#579] : AbstractPatternSniff: potential PHP notice during live coding. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#580] : Squiz.Formatting.OperatorBracket: potential PHP notice during live coding. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#581] : PSR12.ControlStructures.ControlStructureSpacing: prevent fixer conflict by correctly handling multiple empty newlines before the first condition in a multi-line control structure. + - Thanks to [Dan Wallis][@fredden] for the patch. +- Fixed bug [#585] : Tokenizer not applying tab replacement in heredoc/nowdoc openers. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#588] : Squiz.PHP.EmbeddedPhp false positive when checking spaces after a PHP short open tag. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#597] : Generic.PHP.LowerCaseKeyword did not flag nor fix non-lowercase anonymous class keywords. + - Thanks to [Marek Å típek][@maryo] for the patch. +- Fixed bug [#598] : Squiz.PHP.DisallowMultipleAssignments: false positive on assignments to variable property on object stored in array. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#608] : Squiz.Functions.MultiLineFunctionDeclaration did not take (parameter) attributes into account when checking for one parameter per line. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Other +- The provenance of PHAR files associated with a release can now be verified via [GitHub Artifact Attestations][ghattest] using the [GitHub CLI tool][ghcli] with the following command: `gh attestation verify [phpcs|phpcbf].phar -o PHPCSStandards`. [#574] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. + +[#553]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/553 +[#574]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/574 +[#579]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/579 +[#580]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/580 +[#581]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/581 +[#585]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/585 +[#588]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/588 +[#597]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/597 +[#598]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/598 +[#608]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/608 + +[ghcli]: https://cli.github.com/ +[ghattest]: https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds + +## [3.10.2] - 2024-07-22 + +### Changed +- The following sniff(s) have received efficiency improvements: + - Generic.Functions.FunctionCallArgumentSpacing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- The array format of the information passed to the `Reports::generateFileReport()` method is now documented in the Reports interface. [#523] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Bill Ruddock][@biinari], [Dan Wallis][@fredden], [Klaus Purer][@klausi], [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#513] : Generic.Functions.FunctionCallArgumentSpacing did not ignore the body of a match expressions passed as a function argument, which could lead to false positives. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#533] : Generic.WhiteSpace.DisallowTabIndent: tab indentation for heredoc/nowdoc closers will no longer be auto-fixed to prevent parse errors. The issue will still be reported. + - The error code for heredoc/nowdoc indentation using tabs has been made more specific - `TabsUsedHeredocCloser` - to allow for selectively excluding the indentation check for heredoc/nowdoc closers. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#534] : Generic.WhiteSpace.DisallowSpaceIndent did not report on space indentation for PHP 7.3 flexible heredoc/nowdoc closers. + - Closers using space indentation will be reported with a dedicated error code: `SpacesUsedHeredocCloser`. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#537] : Squiz.PHP.DisallowMultipleAssignments false positive for list assignments at the start of a new PHP block after an embedded PHP statement. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#551] : Squiz.PHP.DisallowMultipleAssignments prevent false positive for function parameters during live coding. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#554] : Generic.CodeAnalysis.UselessOverridingMethod edge case false negative when the call to the parent method would end on a PHP close tag. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#555] : Squiz.Classes.SelfMemberReference edge case false negative when the namespace declaration would end on a PHP close tag. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[#513]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/513 +[#523]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/523 +[#533]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/533 +[#534]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/534 +[#537]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/537 +[#551]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/551 +[#554]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/554 +[#555]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/555 + +## [3.10.1] - 2024-05-22 + +### Added +- Documentation for the following sniffs: + - Generic.Commenting.DocComment + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. + +### Changed +- The following have received efficiency improvements: + - Type handling in the PHP Tokenizer + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#110], [#437], [#475] : `File::findStartOfStatement()`: the start of statement/expression determination for tokens in parentheses/short array brackets/others scopes, nested within match expressions, was incorrect in most cases. + The trickle down effect of the bug fixes made to the `File::findStartOfStatement()` method, is that the Generic.WhiteSpace.ScopeIndent and the PEAR.WhiteSpace.ScopeIndent sniffs should now be able to correctly determine and fix the indent for match expressions containing nested expressions. + These fixes also fix an issue with the `Squiz.Arrays.ArrayDeclaration` sniff and possibly other, unreported bugs. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#504] : The tokenizer could inadvertently mistake the last parameter in a function call using named arguments for a DNF type. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#508] : Tokenizer/PHP: extra hardening against handling parse errors in the type handling layer. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[#110]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/110 +[#437]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/437 +[#475]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/475 +[#504]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/504 +[#508]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/508 + +## [3.10.0] - 2024-05-20 + +### Added +- Tokenizer support for PHP 8.2 Disjunctive Normal Form (DNF) types. [#3731][sq-3731], [#387], [#461] + - Includes new `T_TYPE_OPEN_PARENTHESIS` and `T_TYPE_CLOSE_PARENTHESIS` tokens to represent the parentheses in DNF types. + - These new tokens, like other parentheses, will have the `parenthesis_opener` and `parenthesis_closer` token array indexes set and the tokens between them will have the `nested_parenthesis` index. + - The `File::getMethodProperties()`, `File::getMethodParameters()` and `File::getMemberProperties()` methods now all support DNF types. [#471], [#472], [#473] + - Additionally, the following sniff has been updated to support DNF types: + - Generic.PHP.LowerCaseType [#478] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches. +- Documentation for the following sniffs: + - Squiz.WhiteSpace.FunctionClosingBraceSpace + - Thanks to [Przemek Hernik][@przemekhernik] for the patch. + +### Changed +- The help screens have received a face-lift for improved usability and readability. [#447] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch and thanks to [Colin Stewart][@costdev], [Gary Jones][@GaryJones] and [@mbomb007] for reviewing. +- The Squiz.Commenting.ClosingDeclarationComment sniff will now also examine and flag closing comments for traits. [#442] + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- The following sniff(s) have efficiency improvements: + - Generic.Arrays.ArrayIndent + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- The autoloader will now always return a boolean value indicating whether it has loaded a class or not. [#479] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Dan Wallis][@fredden], [Danny van der Sluijs][@DannyvdSluijs], [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#466] : Generic.Functions.CallTimePassByReference was not flagging call-time pass-by-reference in class instantiations using the self/parent/static keywords. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#494] : edge case bug in tokenization of an empty block comment. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#494] : edge case bug in tokenization of an empty single-line DocBlock. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#499] : Generic.ControlStructures.InlineControlStructure now handles statements with a comment between `else` and `if` correctly. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. + +[sq-3731]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3731 +[#387]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/387 +[#442]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/442 +[#447]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/447 +[#461]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/461 +[#466]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/466 +[#471]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/471 +[#472]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/472 +[#473]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/473 +[#478]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/478 +[#479]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/479 +[#494]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/494 +[#499]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/499 + +## [3.9.2] - 2024-04-24 + +### Changed +- The Generic.ControlStructures.DisallowYodaConditions sniff no longer listens for the null coalesce operator. [#458] + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Dan Wallis][@fredden], [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#381] : Squiz.Commenting.ClosingDeclarationComment could throw the wrong error when the close brace being examined is at the very end of a file. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#385] : Generic.CodeAnalysis.JumbledIncrementer improved handling of parse errors/live coding. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#394] : Generic.Functions.CallTimePassByReference was not flagging call-time pass-by-reference in anonymous class instantiations + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#420] : PEAR.Functions.FunctionDeclaration could run into a blocking PHP notice while fixing code containing a parse error. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#421] : File::getMethodProperties() small performance improvement & more defensive coding. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#423] : PEAR.WhiteSpace.ScopeClosingBrace would have a fixer conflict with itself when a close tag was preceded by non-empty inline HTML. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#424] : PSR2.Classes.ClassDeclaration using namespace relative interface names in the extends/implements part of a class declaration would lead to a fixer conflict. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#427] : Squiz.Operators.OperatorSpacing would have a fixer conflict with itself when an operator was preceeded by a new line and the previous line ended in a comment. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#430] : Squiz.ControlStructures.ForLoopDeclaration: fixed potential undefined array index notice + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#431] : PSR2.Classes.ClassDeclaration will no longer try to auto-fix multi-line interface implements statements if these are interlaced with comments on their own line. This prevents a potential fixer conflict. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#453] : Arrow function tokenization was broken when the return type was a stand-alone `true` or `false`; or contained `true` or `false` as part of a union type. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Other +- [ESLint 9.0] has been released and changes the supported configuration file format. + The (deprecated) `Generic.Debug.ESLint` sniff only supports the "old" configuration file formats and when using the sniff to run ESLint, the `ESLINT_USE_FLAT_CONFIG=false` environment variable will need to be set when using ESLint >= 9.0. + For more information, see [#436]. + + +[ESLint 9.0]: https://eslint.org/blog/2024/04/eslint-v9.0.0-released/#flat-config-is-now-the-default-and-has-some-changes + +[#381]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/381 +[#385]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/385 +[#394]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/394 +[#420]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/420 +[#421]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/421 +[#423]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/423 +[#424]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/424 +[#427]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/427 +[#430]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/430 +[#431]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/431 +[#436]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/436 +[#453]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/453 +[#458]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/458 + +## [3.9.1] - 2024-03-31 + +### Added +- Documentation for the following sniffs: + - Generic.PHP.RequireStrictTypes + - Squiz.WhiteSpace.MemberVarSpacing + - Squiz.WhiteSpace.ScopeClosingBrace + - Squiz.WhiteSpace.SuperfluousWhitespace + - Thanks to [Jay McPartland][@jonmcp] and [Rodrigo Primo][@rodrigoprimo] for the patches. + +### Changed +- The following sniffs have received performance related improvements: + - Generic.CodeAnalysis.UselessOverridingMethod + - Generic.Files.ByteOrderMark + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patches. +- Performance improvement for the "Diff" report. Should be most notable for Windows users. [#355] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- The test suite has received some performance improvements. Should be most notable contributors using Windows. [#351] + - External standards with sniff tests using the PHP_CodeSniffer native test framework will also benefit from these changes. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch. +- Various housekeeping, including improvements to the tests and documentation. + - Thanks to [Jay McPartland][@jonmcp], [João Pedro Oliveira][@jpoliveira08], [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions. + +### Fixed +- Fixed bug [#289] : Squiz.WhiteSpace.OperatorSpacing and PSR12.Operators.OperatorSpacing : improved fixer conflict protection by more strenuously avoiding handling operators in declare statements. + - Thanks to [Dan Wallis][@fredden] for the patch. +- Fixed bug [#366] : Generic.CodeAnalysis.UselessOverridingMethod : prevent false negative when the declared method name and the called method name do not use the same case. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch. +- Fixed bug [#368] : Squiz.Arrays.ArrayDeclaration fixer did not handle static closures correctly when moving array items to their own line. + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch. +- Fixed bug [#404] : Test framework : fixed PHP 8.4 deprecation notice. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[#289]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/289 +[#351]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/351 +[#355]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/355 +[#366]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/366 +[#368]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/368 +[#404]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/404 + +## [3.9.0] - 2024-02-16 + +### Added +- Tokenizer support for PHP 8.3 typed class constants. [#321] + - Additionally, the following sniffs have been updated to support typed class constants: + - Generic.NamingConventions.UpperCaseConstantName [#332] + - Generic.PHP.LowerCaseConstant [#330] + - Generic.PHP.LowerCaseType [#331] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches +- Tokenizer support for PHP 8.3 readonly anonymous classes. [#309] + - Additionally, the following sniffs have been updated to support readonly anonymous classes: + - PSR12.Classes.ClassInstantiation [#324] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches +- New `PHP_CodeSniffer\Sniffs\DeprecatedSniff` interface to allow for marking a sniff as deprecated. [#281] + - If a ruleset uses deprecated sniffs, deprecation notices will be shown to the end-user before the scan starts. + When running in `-q` (quiet) mode, the deprecation notices will be hidden. + - Deprecated sniffs will still run and using them will have no impact on the exit code for a scan. + - In ruleset "explain"-mode (`-e`) an asterix `*` will show next to deprecated sniffs. + - Sniff maintainers are advised to read through the PR description for full details on how to use this feature for their own (deprecated) sniffs. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- New `Generic.CodeAnalysis.RequireExplicitBooleanOperatorPrecedence` sniff. [#197] + - Forbid mixing different binary boolean operators within a single expression without making precedence clear using parentheses + - Thanks to [Tim Düsterhus][@TimWolla] for the contribution +- Squiz.PHP.EmbeddedPhp : the sniff will now also examine the formatting of embedded PHP statements using short open echo tags. [#27] + - Includes a new `ShortOpenEchoNoSemicolon` errorcode to allow for selectively ignoring missing semicolons in single line embedded PHP snippets within short open echo tags. + - The other error codes are the same and do not distinguish between what type of open tag was used. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Documentation for the following sniffs: + - Generic.WhiteSpace.IncrementDecrementSpacing + - PSR12.ControlStructures.ControlStructureSpacing + - PSR12.Files.ImportStatement + - PSR12.Functions.ReturnTypeDeclaration + - PSR12.Properties.ConstantVisibility + - Thanks to [Denis Žoljom][@dingo-d] and [Rodrigo Primo][@rodrigoprimo] for the patches + +### Changed +- The Performance report can now also be used for a `phpcbf` run. [#308] + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Sniff tests which extend the PHPCS native `AbstractSniffUnitTest` class will now show a (non-build-breaking) warning when test case files contain fixable errors/warnings, but there is no corresponding `.fixed` file available in the test suite to verify the fixes against. [#336] + - The warning is only displayed on PHPUnit 7.3.0 and higher. + - The warning will be elevated to a test failure in PHPCS 4.0. + - Thanks to [Dan Wallis][@fredden] for the patch +- The following sniffs have received performance related improvements: + - Squiz.PHP.EmbeddedPhp + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Various housekeeping, including improvements to the tests and documentation + - Thanks to [Dan Wallis][@fredden], [Joachim Noreiko][@joachim-n], [Remi Collet][@remicollet], [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions + +### Deprecated +- Support for scanning JavaScript and CSS files. See [#2448][sq-2448]. + - This also means that all sniffs which are only aimed at JavaScript or CSS files are now deprecated. + - The Javascript and CSS Tokenizers, all Javascript and CSS specific sniffs, and support for JS and CSS in select sniffs which support multiple file types, will be removed in version 4.0.0. +- The abstract `PHP_CodeSniffer\Filters\ExactMatch::getBlacklist()` and `PHP_CodeSniffer\Filters\ExactMatch::getWhitelist()` methods are deprecated and will be removed in the 4.0 release. See [#198]. + - In version 4.0, these methods will be replaced with abstract `ExactMatch::getDisallowedFiles()` and `ExactMatch::getAllowedFiles()` methods + - To make Filters extending `ExactMatch` cross-version compatible with both PHP_CodeSniffer 3.9.0+ as well as 4.0+, implement the new `getDisallowedFiles()` and `getAllowedFiles()` methods. + - When both the `getDisallowedFiles()` and `getAllowedFiles()` methods as well as the `getBlacklist()` and `getWhitelist()` are available, the new methods will take precedence over the old methods. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The MySource standard and all sniffs in it. See [#2471][sq-2471]. + - The MySource standard and all sniffs in it will be removed in version 4.0.0. +- The `Zend.Debug.CodeAnalyzer` sniff. See [#277]. + - This sniff will be removed in version 4.0.0. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed bug [#127] : Squiz.Commenting.FunctionComment : The `MissingParamType` error code will now be used instead of `MissingParamName` when a parameter name is provided, but not its type. Additionally, invalid type hint suggestions will no longer be provided in these cases. + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#196] : Squiz.PHP.EmbeddedPhp : fixer will no longer leave behind trailing whitespace when moving code to another line. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#196] : Squiz.PHP.EmbeddedPhp : will now determine the needed indent with higher precision in multiple situations. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#196] : Squiz.PHP.EmbeddedPhp : fixer will no longer insert a stray new line when the closer of a multi-line embedded PHP block and the opener of the next multi-line embedded PHP block would be on the same line. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#235] : Generic.CodeAnalysis.ForLoopWithTestFunctionCall : prevent a potential PHP 8.3 deprecation notice during live coding + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch +- Fixed bug [#288] : Generic.WhiteSpace.IncrementDecrementSpacing : error message for post-in/decrement will now correctly inform about new lines found before the operator. + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch +- Fixed bug [#296] : Generic.WhiteSpace.ArbitraryParenthesesSpacing : false positive for non-arbitrary parentheses when these follow the scope closer of a `switch` `case`. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#307] : PSR2.Classes.ClassDeclaration : space between a modifier keyword and the `class` keyword was not checked when the space included a new line or comment. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#325] : Squiz.Operators.IncrementDecrementUsage : the sniff was underreporting when there was (no) whitespace and/or comments in unexpected places. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#335] : PSR12.Files.DeclareStatement : bow out in a certain parse error situation to prevent incorrect auto-fixes from being made. + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#340] : Squiz.Commenting.ClosingDeclarationComment : no longer adds a stray newline when adding a missing comment. + - Thanks to [Dan Wallis][@fredden] for the patch + +### Other +- A "Community cc list" has been introduced to ping maintainers of external standards and integrators for input regarding change proposals for PHP_CodeSniffer which may impact them. [#227] + - For anyone who missed the discussion about this and is interested to be on this list, please feel invited to submit a PR to add yourself. + The list is located in the `.github` folder. + +[sq-2448]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2448 +[sq-2471]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2471 +[#27]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/27 +[#127]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/127 +[#196]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/196 +[#197]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/197 +[#198]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/198 +[#227]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/227 +[#235]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/235 +[#277]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/277 +[#281]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/281 +[#288]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/288 +[#296]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/296 +[#307]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/307 +[#308]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/308 +[#309]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/309 +[#321]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/321 +[#324]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/324 +[#325]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/325 +[#330]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/330 +[#331]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/331 +[#332]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/332 +[#335]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/335 +[#336]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/336 +[#340]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/340 + +## [3.8.1] - 2024-01-11 + +### Added +- Documentation has been added for the following sniffs: + - Generic.CodeAnalysis.EmptyPHPStatement + - Generic.Formatting.SpaceBeforeCast + - Generic.PHP.Syntax + - Generic.WhiteSpace.LanguageConstructSpacing + - PSR12.Classes.ClosingBrace + - PSR12.Classes.OpeningBraceSpace + - PSR12.ControlStructures.BooleanOperatorPlacement + - PSR12.Files.OpenTag + - Thanks to [Rodrigo Primo][@rodrigoprimo] and [Denis Žoljom][@dingo-d] for the patches + +### Changed +- GitHub releases will now always only contain unversioned release assets (PHARS + asc files) (same as it previously was in the squizlabs repo). See [#205] for context. + - Thanks to [Shivam Mathur][@shivammathur] for opening a discussion about this +- Various housekeeping, includes improvements to the tests and documentation + - Thanks to [Dan Wallis][@fredden], [Lucas Hoffmann][@lucc], [Rodrigo Primo][@rodrigoprimo] and [Juliette Reinders Folmer][@jrfnl] for their contributions + +### Fixed +- Fixed bug [#124] : Report Full : avoid unnecessarily wrapping lines when `-s` is used + - Thanks to [Brad Jorsch][@anomiex] for the patch +- Fixed bug [#124] : Report Full : fix incorrect bolding of pipes when `-s` is used and messages wraps + - Thanks to [Brad Jorsch][@anomiex] for the patch +- Fixed bug [#150] : Squiz.WhiteSpace.KeywordSpacing : prevent a PHP notice when run during live coding + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#154] : Report Full : delimiter line calculation could go wonky on wide screens when a report contains multi-line messages + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#178] : Squiz.Commenting.VariableComment : docblocks were incorrectly being flagged as missing when a property declaration used PHP native union/intersection type declarations + - Thanks to [Ferdinand Kuhl][@fcool] for the patch +- Fixed bug [#211] : Squiz.Commenting.VariableComment : docblocks were incorrectly being flagged as missing when a property declaration used PHP 8.2+ stand-alone `true`/`false`/`null` type declarations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#211] : Squiz.Commenting.VariableComment : docblocks were incorrectly being flagged as missing when a property declaration used PHP native `parent`, `self` or a namespace relative class name type declaration + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#226] : Generic.CodeAnalysis.ForLoopShouldBeWhileLoop : prevent a potential PHP 8.3 deprecation notice during live coding + - Thanks to [Rodrigo Primo][@rodrigoprimo] for the patch + +[#124]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/124 +[#150]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/150 +[#154]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/154 +[#178]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/178 +[#205]: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/205 +[#211]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/211 +[#226]: https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/226 + +## [3.8.0] - 2023-12-08 + +[Squizlabs/PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) is dead. Long live [PHPCSStandards/PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer)! + +### Breaking Changes +- The `squizlabs/PHP_CodeSniffer` repository has been abandoned. The `PHPCSStandards/PHP_CodeSniffer` repository will serve as the continuation of the project. For more information about this change, please read the [announcement](https://github.com/squizlabs/PHP_CodeSniffer/issues/3932). + - Installation of PHP_CodeSniffer via PEAR is no longer supported. + - Users will need to switch to another installation method. + - Note: this does not affect the PEAR sniffs. + - For Composer users, nothing changes. + - **_In contrast to earlier information, the `squizlabs/php_codesniffer` package now points to the new repository and everything will continue to work as before._** + - PHIVE users may need to clear the PHIVE URL cache. + - PHIVE users who don't use the package alias, but refer to the package URL, will need to update the URL from `https://squizlabs.github.io/PHP_CodeSniffer/phars/` to `https://phars.phpcodesniffer.com/phars/`. + - Users who download the PHAR files using curl or wget, will need to update the download URL from `https://squizlabs.github.io/PHP_CodeSniffer/[phpcs|phpcbf].phar` or `https://github.com/squizlabs/PHP_CodeSniffer/releases/latest/download/[phpcs|phpcbf].phar` to `https://phars.phpcodesniffer.com/[phpcs|phpcbf].phar`. + - For users who install PHP_CodeSniffer via the [Setup-PHP](https://github.com/shivammathur/setup-php/) action runner for GitHub Actions, nothing changes. + - Users using a git clone will need to update the clone address from `git@github.com:squizlabs/PHP_CodeSniffer.git` to `git@github.com:PHPCSStandards/PHP_CodeSniffer.git`. + - Contributors will need to fork the new repo and add both the new fork as well as the new repo as remotes to their local git copy of PHP_CodeSniffer. + - Users who have (valid) open issues or pull requests in the `squizlabs/PHP_CodeSniffer` repository are invited to resubmit these to the `PHPCSStandards/PHP_CodeSniffer` repository. + +### Added +- Runtime support for PHP 8.3. All known PHP 8.3 deprecation notices have been fixed + - Syntax support for new PHP 8.3 features will follow in a future release + - If you find any PHP 8.3 deprecation notices which were missed, please report them + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches +- Added support for PHP 8.2 readonly classes to File::getClassProperties() through a new is_readonly array index in the return value + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for PHP 8.2 readonly classes to a number of sniffs + - Generic.CodeAnalysis.UnnecessaryFinalModifier + - PEAR.Commenting.ClassComment + - PEAR.Commenting.FileComment + - PSR1.Files.SideEffects + - PSR2.Classes.ClassDeclaration + - PSR12.Files.FileHeader + - Squiz.Classes.ClassDeclaration + - Squiz.Classes.LowercaseClassKeywords + - Squiz.Commenting.ClassComment + - Squiz.Commenting.DocCommentAlignment + - Squiz.Commenting.FileComment + - Squiz.Commenting.InlineComment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for PHP 8.2 `true` as a stand-alone type declaration + - The `File::getMethodProperties()`, `File::getMethodParameters()` and `File::getMemberProperties()` methods now all support the `true` type + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for PHP 8.2 `true` as a stand-alone type to a number of sniffs + - Generic.PHP.LowerCaseType + - PSr12.Functions.NullableTypeDeclaration + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added a Performance report to allow for finding "slow" sniffs + - To run this report, run PHPCS with --report=Performance. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.RequireStrictTypes : new warning for when there is a declare statement, but the strict_types directive is set to 0 + - The warning can be turned off by excluding the `Generic.PHP.RequireStrictTypes.Disabled` error code + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.FunctionComment : new `ParamNameUnexpectedAmpersandPrefix` error for parameters annotated as passed by reference while the parameter is not passed by reference + - Thanks to [Dan Wallis][@fredden] for the patch +- Documentation has been added for the following sniffs: + - PSR2.Files.ClosingTag + - PSR2.Methods.FunctionCallSignature + - PSR2.Methods.FunctionClosingBrace + - Thanks to [Atsushi Okui][@blue32a] for the patch +- Support for PHPUnit 8 and 9 to the test suite + - Test suites for external standards which run via the PHPCS native test suite can now run on PHPUnit 4-9 (was 4-7) + - If any of these tests use the PHPUnit `setUp()`/`tearDown()` methods or overload the `setUp()` in the `AbstractSniffUnitTest` test case, they will need to be adjusted. See the [PR details for further information](https://github.com/PHPCSStandards/PHP_CodeSniffer/pull/59/commits/bc302dd977877a22c5e60d42a2f6b7d9e9192dab) + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Changed +- Changes have been made to the way PHPCS handles invalid sniff properties being set in a custom ruleset + - Fixes PHP 8.2 deprecation notices for properties set in a (custom) ruleset for complete standards/complete sniff categories + - Invalid sniff properties set for individual sniffs will now result in an error and halt the execution of PHPCS + - A descriptive error message is provided to allow users to fix their ruleset + - Sniff properties set for complete standards/complete sniff categories will now only be set on sniffs which explicitly support the property + - The property will be silently ignored for those sniffs which do not support the property + - Invalid sniff properties set for sniffs via inline annotations will result in an informative `Internal.PropertyDoesNotExist` errror on line 1 of the scanned file, but will not halt the execution of PHPCS + - For sniff developers, it is strongly recommended for sniffs to explicitly declare any user-adjustable public properties + - If dynamic properties need to be supported for a sniff, either declare the magic __set()/__get()/__isset()/__unset() methods on the sniff or let the sniff extend stdClass + - Note: The `#[\AllowDynamicProperties]` attribute will have no effect for properties which are being set in rulesets + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The third parameter for the Ruleset::setSniffProperty() method has been changed to expect an array + - Sniff developers/integrators of PHPCS may need to make some small adjustments to allow for this change + - Existing code will continue to work but will throw a deprecation error + - The backwards compatiblity layer will be removed in PHPCS 4.0 + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- When using `auto` report width (the default) a value of 80 columns will be used if the width cannot be determined + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Sniff error messages are now more informative to help bugs get reported to the correct project + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.CodeAnalysis.UnusedFunctionParameter will now ignore magic methods for which the signature is defined by PHP + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Functions.OpeningFunctionBraceBsdAllman will now check the brace indent before the opening brace for empty functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Functions.OpeningFunctionBraceKernighanRitchie will now check the spacing before the opening brace for empty functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.WhiteSpace.IncrementDecrementSpacing now detects more spacing issues + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PSR2.Classes.PropertyDeclaration now enforces that the readonly modifier comes after the visibility modifier + - PSR2 and PSR12 do not have documented rules for this as they pre-date the readonly modifier + - PSR-PER has been used to confirm the order of this keyword so it can be applied to PSR2 and PSR12 correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.Commenting.FunctionComment + Squiz.Commenting.FunctionComment: the SpacingAfter error can now be auto-fixed + - Thanks to [Dan Wallis][@fredden] for the patch +- Squiz.PHP.InnerFunctions sniff no longer reports on OO methods for OO structures declared within a function or closure + - Thanks to [@Daimona] for the patch +- Squiz.PHP.NonExecutableCode will now also flag redundant return statements just before a closure close brace + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Runtime performance improvement for PHPCS CLI users. The improvement should be most noticeable for users on Windows. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The following sniffs have received performance related improvements: + - Generic.PHP.LowerCaseConstant + - Generic.PHP.LowerCaseType + - PSR12.Files.OpenTag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches +- The -e (explain) command will now list sniffs in natural order + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Tests using the PHPCS native test framework with multiple test case files will now run the test case files in numeric order. + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The following sniffs have received minor message readability improvements: + - Generic.Arrays.ArrayIndent + - Generic.Formatting.SpaceAfterCast + - Generic.Formatting.SpaceAfterNot + - Generic.WhiteSpace.SpreadOperatorSpacingAfter + - Squiz.Arrays.ArrayDeclaration + - Squiz.Commenting.DocCommentAlignment + - Squiz.ControlStructures.ControlSignature + - Thanks to [Danny van der Sluijs][@DannyvdSluijs] and [Juliette Reinders Folmer][@jrfnl] for the patches +- Improved README syntax highlighting + - Thanks to [Benjamin Loison][@Benjamin-Loison] for the patch +- Various documentation improvements + - Thanks to [Andrew Dawes][@AndrewDawes], [Danny van der Sluijs][@DannyvdSluijs] and [Juliette Reinders Folmer][@jrfnl] for the patches + +### Removed +- Removed support for installation via PEAR + - Use composer or the PHAR files instead + +### Fixed +- Fixed bug [#2857][sq-2857] : Squiz/NonExecutableCode: prevent false positives when exit is used in a ternary expression or as default with null coalesce + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3386][sq-3386] : PSR1/SideEffects : improved recognition of disable/enable annotations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3557][sq-3557] : Squiz.Arrays.ArrayDeclaration will now ignore PHP 7.4 array unpacking when determining whether an array is associative + - Thanks to [Volker Dusch][@edorian] for the patch +- Fixed bug [#3592][sq-3592] : Squiz/NonExecutableCode: prevent false positives when a PHP 8.0+ inline throw expression is encountered + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3715][sq-3715] : Generic/UnusedFunctionParameter: fixed incorrect errorcode for closures/arrow functions nested within extended classes/classes which implement + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3717][sq-3717] : Squiz.Commenting.FunctionComment: fixed false positive for `InvalidNoReturn` when type is never + - Thanks to [Choraimy Kroonstuiver][@axlon] for the patch +- Fixed bug [#3720][sq-3720] : Generic/RequireStrictTypes : will now bow out silently in case of parse errors/live coding instead of throwing false positives/false negatives + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3720][sq-3720] : Generic/RequireStrictTypes : did not handle multi-directive declare statements + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3722][sq-3722] : Potential "Uninitialized string offset 1" in octal notation backfill + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3736][sq-3736] : PEAR/FunctionDeclaration: prevent fixer removing the close brace (and creating a parse error) when there is no space between the open brace and close brace of a function + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3739][sq-3739] : PEAR/FunctionDeclaration: prevent fixer conflict, and potentially creating a parse error, for unconventionally formatted return types + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3770][sq-3770] : Squiz/NonExecutableCode: prevent false positives for switching between PHP and HTML + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#3773][sq-3773] : Tokenizer/PHP: tokenization of the readonly keyword when used in combination with PHP 8.2 disjunctive normal types + - Thanks to [Dan Wallis][@fredden] and [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3776][sq-3776] : Generic/JSHint: error when JSHint is not available + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#3777][sq-3777] : Squiz/NonExecutableCode: slew of bug fixes, mostly related to modern PHP + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3778][sq-3778] : Squiz/LowercasePHPFunctions: bug fix for class names in attributes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3779][sq-3779] : Generic/ForbiddenFunctions: bug fix for class names in attributes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3785][sq-3785] : Squiz.Commenting.FunctionComment: potential "Uninitialized string offset 0" when a type contains a duplicate pipe symbol + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#3787][sq-3787] : `PEAR/Squiz/[MultiLine]FunctionDeclaration`: allow for PHP 8.1 new in initializers + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3789][sq-3789] : Incorrect tokenization for ternary operator with `match` inside of it + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3790][sq-3790] : PSR12/AnonClassDeclaration: prevent fixer creating parse error when there was no space before the open brace + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3797][sq-3797] : Tokenizer/PHP: more context sensitive keyword fixes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3801][sq-3801] : File::getMethodParameters(): allow for readonly promoted properties without visibility + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3805][sq-3805] : Generic/FunctionCallArgumentSpacing: prevent fixer conflict over PHP 7.3+ trailing comma's in function calls + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3806][sq-3806] : Squiz.PHP.InnerFunctions sniff now correctly reports inner functions declared within a closure + - Thanks to [@Daimona] for the patch +- Fixed bug [#3809][sq-3809] : GitBlame report was broken when passing a basepath + - Thanks to [Chris][@datengraben] for the patch +- Fixed bug [#3813][sq-3813] : Squiz.Commenting.FunctionComment: false positive for parameter name mismatch on parameters annotated as passed by reference + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#3833][sq-3833] : Generic.PHP.LowerCaseType: fixed potential undefined array index notice + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3846][sq-3846] : PSR2.Classes.ClassDeclaration.CloseBraceAfterBody : fixer will no longer remove indentation on the close brace line + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3854][sq-3854] : Fatal error when using Gitblame report in combination with `--basepath` and running from project subdirectory + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3856][sq-3856] : PSR12.Traits.UseDeclaration was using the wrong error code - SpacingAfterAs - for spacing issues after the `use` keyword + - These will now be reported using the SpacingAfterUse error code + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3856][sq-3856] : PSR12.Traits.UseDeclaration did not check spacing after `use` keyword for multi-line trait use statements + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3867][sq-3867] : Tokenizer/PHP: union type and intersection type operators were not correctly tokenized for static properties without explicit visibility + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3877][sq-3877] : Filter names can be case-sensitive. The -h help text will now display the correct case for the available filters + - Thanks to [@simonsan] for the patch +- Fixed bug [#3893][sq-3893] : Generic/DocComment : the SpacingAfterTagGroup fixer could accidentally remove ignore annotations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3898][sq-3898] : Squiz/NonExecutableCode : the sniff could get confused over comments in unexpected places + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3904][sq-3904] : Squiz/FunctionSpacing : prevent potential fixer conflict + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3906][sq-3906] : Tokenizer/CSS: bug fix related to the unsupported slash comment syntax + - Thanks to [Dan Wallis][@fredden] for the patch +- Fixed bug [#3913][sq-3913] : Config did not always correctly store unknown "long" arguments in the `$unknown` property + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +Thanks go to [Dan Wallis][@fredden] and [Danny van der Sluijs][@DannyvdSluijs] for reviewing quite a few of the PRs for this release. +Additionally, thanks to [Alexander Turek][@derrabus] for consulting on the repo change over. + +[sq-2857]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2857 +[sq-3386]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3386 +[sq-3557]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3557 +[sq-3592]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3592 +[sq-3715]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3715 +[sq-3717]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3717 +[sq-3720]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3720 +[sq-3722]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3722 +[sq-3736]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3736 +[sq-3739]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3739 +[sq-3770]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3770 +[sq-3773]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3773 +[sq-3776]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3776 +[sq-3777]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3777 +[sq-3778]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3778 +[sq-3779]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3779 +[sq-3785]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3785 +[sq-3787]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3787 +[sq-3789]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3789 +[sq-3790]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3790 +[sq-3797]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3797 +[sq-3801]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3801 +[sq-3805]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3805 +[sq-3806]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3806 +[sq-3809]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3809 +[sq-3813]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3813 +[sq-3833]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3833 +[sq-3846]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3846 +[sq-3854]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3854 +[sq-3856]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3856 +[sq-3867]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3867 +[sq-3877]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3877 +[sq-3893]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3893 +[sq-3898]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3898 +[sq-3904]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3904 +[sq-3906]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3906 +[sq-3913]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3913 + +## [3.7.2] - 2023-02-23 + +### Changed +- Newer versions of Composer will now suggest installing PHPCS using require-dev instead of require + - Thanks to [Gary Jones][@GaryJones] for the patch +- A custom Out Of Memory error will now be shown if PHPCS or PHPCBF run out of memory during a run + - Error message provides actionable information about how to fix the problem and ensures the error is not silent + - Thanks to [Juliette Reinders Folmer][@jrfnl] and [Alain Schlesser][@schlessera] for the patch +- Generic.PHP.LowerCaseType sniff now correctly examines types inside arrow functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Formatting.OperatorBracket no longer reports false positives in match() structures + +### Fixed +- Fixed bug [#3616][sq-3616] : Squiz.PHP.DisallowComparisonAssignment false positive for PHP 8 match expression + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3618][sq-3618] : Generic.WhiteSpace.ArbitraryParenthesesSpacing false positive for return new parent() + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3632][sq-3632] : Short list not tokenized correctly in control structures without braces + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3639][sq-3639] : Tokenizer not applying tab replacement to heredoc/nowdoc closers + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3640][sq-3640] : Generic.WhiteSpace.DisallowTabIndent not reporting errors for PHP 7.3 flexible heredoc/nowdoc syntax + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3645][sq-3645] : PHPCS can show 0 exit code when running in parallel even if child process has fatal error + - Thanks to [Alex Panshin][@enl] for the patch +- Fixed bug [#3653][sq-3653] : False positives for match() in OperatorSpacingSniff + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#3666][sq-3666] : PEAR.Functions.FunctionCallSignature incorrect indent fix when checking mixed HTML/PHP files +- Fixed bug [#3668][sq-3668] : PSR12.Classes.ClassInstantiation.MissingParentheses false positive when instantiating parent classes + - Similar issues also fixed in Generic.Functions.FunctionCallArgumentSpacing and Squiz.Formatting.OperatorBracket + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3672][sq-3672] : Incorrect ScopeIndent.IncorrectExact report for match inside array literal +- Fixed bug [#3694][sq-3694] : Generic.WhiteSpace.SpreadOperatorSpacingAfter does not ignore spread operator in PHP 8.1 first class callables + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-3616]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3616 +[sq-3618]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3618 +[sq-3632]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3632 +[sq-3639]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3639 +[sq-3640]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3640 +[sq-3645]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3645 +[sq-3653]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3653 +[sq-3666]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3666 +[sq-3668]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3668 +[sq-3672]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3672 +[sq-3694]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3694 + +## [3.7.1] - 2022-06-18 + +### Fixed +- Fixed bug [#3609][sq-3609] : Methods/constants with name empty/isset/unset are always reported as error + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-3609]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3609 + +## [3.7.0] - 2022-06-13 + +### Added +- Added support for PHP 8.1 explicit octal notation + - This new syntax has been backfilled for PHP versions less than 8.1 + - Thanks to [Mark Baker][@MarkBaker] for the patch + - Thanks to [Juliette Reinders Folmer][@jrfnl] for additional fixes +- Added support for PHP 8.1 enums + - This new syntax has been backfilled for PHP versions less than 8.1 + - Includes a new T_ENUM_CASE token to represent the case statements inside an enum + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch + - Thanks to [Juliette Reinders Folmer][@jrfnl] for additional core and sniff support +- Added support for the PHP 8.1 readonly token + - Tokenizing of the readonly keyword has been backfilled for PHP versions less than 8.1 + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Added support for PHP 8.1 intersection types + - Includes a new T_TYPE_INTERSECTION token to represent the ampersand character inside intersection types + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch + +### Changed +- File::getMethodParameters now supports the new PHP 8.1 readonly token + - When constructor property promotion is used, a new property_readonly array index is included in the return value + - This is a boolean value indicating if the property is readonly + - If the readonly token is detected, a new readonly_token array index is included in the return value + - This contains the token index of the readonly keyword + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Support for new PHP 8.1 readonly keyword has been added to the following sniffs: + - Generic.PHP.LowerCaseKeyword + - PSR2.Classes.PropertyDeclaration + - Squiz.Commenting.BlockComment + - Squiz.Commenting.DocCommentAlignment + - Squiz.Commenting.VariableComment + - Squiz.WhiteSpace.ScopeKeywordSpacing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patches +- The parallel feature is now more efficient and runs faster in some situations due to improved process management + - Thanks to [Sergei Morozov][@morozov] for the patch +- The list of installed coding standards now has consistent ordering across all platforms + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.UpperCaseConstant and Generic.PHP.LowerCaseConstant now ignore type declarations + - These sniffs now only report errors for true/false/null when used as values + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.LowerCaseType now supports the PHP 8.1 never type + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch + +### Fixed +- Fixed bug [#3502][sq-3502] : A match statement within an array produces Squiz.Arrays.ArrayDeclaration.NoKeySpecified +- Fixed bug [#3503][sq-3503] : Squiz.Commenting.FunctionComment.ThrowsNoFullStop false positive when one line @throw +- Fixed bug [#3505][sq-3505] : The nullsafe operator is not counted in Generic.Metrics.CyclomaticComplexity + - Thanks to [Mark Baker][@MarkBaker] for the patch +- Fixed bug [#3526][sq-3526] : PSR12.Properties.ConstantVisibility false positive when using public final const syntax + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3530][sq-3530] : Line indented incorrectly false positive when using match-expression inside switch case +- Fixed bug [#3534][sq-3534] : Name of typed enum tokenized as T_GOTO_LABEL + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3546][sq-3546] : Tokenizer/PHP: bug fix - parent/static keywords in class instantiations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3550][sq-3550] : False positive from PSR2.ControlStructures.SwitchDeclaration.TerminatingComment when using trailing comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3575][sq-3575] : Squiz.Scope.MethodScope misses visibility keyword on previous line + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3604][sq-3604] : Tokenizer/PHP: bug fix for double quoted strings using ${ + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-3502]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3502 +[sq-3503]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3503 +[sq-3505]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3505 +[sq-3526]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3526 +[sq-3530]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3530 +[sq-3534]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3534 +[sq-3546]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3546 +[sq-3550]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3550 +[sq-3575]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3575 +[sq-3604]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3604 + +## [3.6.2] - 2021-12-13 + +### Changed +- Processing large code bases that use tab indenting inside comments and strings will now be faster + - Thanks to [Thiemo Kreuz][@thiemowmde] for the patch + +### Fixed +- Fixed bug [#3388][sq-3388] : phpcs does not work when run from WSL drives + - Thanks to [Juliette Reinders Folmer][@jrfnl] and [Graham Wharton][@gwharton] for the patch +- Fixed bug [#3422][sq-3422] : Squiz.WhiteSpace.ScopeClosingBrace fixer removes HTML content when fixing closing brace alignment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3437][sq-3437] : PSR12 does not forbid blank lines at the start of the class body + - Added new PSR12.Classes.OpeningBraceSpace sniff to enforce this +- Fixed bug [#3440][sq-3440] : Squiz.WhiteSpace.MemberVarSpacing false positives when attributes used without docblock + - Thanks to [Vadim Borodavko][@javer] for the patch +- Fixed bug [#3448][sq-3448] : PHP 8.1 deprecation notice while generating running time value + - Thanks to [Juliette Reinders Folmer][@jrfnl] and [Andy Postnikov][@andypost] for the patch +- Fixed bug [#3456][sq-3456] : PSR12.Classes.ClassInstantiation.MissingParentheses false positive using attributes on anonymous class + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3460][sq-3460] : Generic.Formatting.MultipleStatementAlignment false positive on closure with parameters + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3468][sq-3468] : do/while loops are double-counted in Generic.Metrics.CyclomaticComplexity + - Thanks to [Mark Baker][@MarkBaker] for the patch +- Fixed bug [#3469][sq-3469] : Ternary Operator and Null Coalescing Operator are not counted in Generic.Metrics.CyclomaticComplexity + - Thanks to [Mark Baker][@MarkBaker] for the patch +- Fixed bug [#3472][sq-3472] : PHP 8 match() expression is not counted in Generic.Metrics.CyclomaticComplexity + - Thanks to [Mark Baker][@MarkBaker] for the patch + +[sq-3388]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3388 +[sq-3422]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3422 +[sq-3437]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3437 +[sq-3440]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3440 +[sq-3448]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3448 +[sq-3456]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3456 +[sq-3460]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3460 +[sq-3468]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3468 +[sq-3469]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3469 +[sq-3472]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3472 + +## [3.6.1] - 2021-10-11 + +### Changed +- PHPCS annotations can now be specified using hash-style comments + - Previously, only slash-style and block-style comments could be used to do things like disable errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The new PHP 8.1 tokenization for ampersands has been reverted to use the existing PHP_CodeSniffer method + - The PHP 8.1 tokens T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG and T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG are unused + - Ampersands continue to be tokenized as T_BITWISE_AND for all PHP versions + - Thanks to [Juliette Reinders Folmer][@jrfnl] and [Anna Filina][@afilina] for the patch +- File::getMethodParameters() no longer incorrectly returns argument attributes in the type hint array index + - A new has_attributes array index is available and set to TRUE if the argument has attributes defined + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed an issue where some sniffs would not run on PHP files that only used the short echo tag + - The following sniffs were affected: + - Generic.Files.ExecutableFile + - Generic.Files.LowercasedFilename + - Generic.Files.LineEndings + - Generic.Files.EndFileNewline + - Generic.Files.EndFileNoNewline + - Generic.PHP.ClosingPHPTag + - Generic.PHP.Syntax + - Generic.VersionControl.GitMergeConflict + - Generic.WhiteSpace.DisallowSpaceIndent + - Generic.WhiteSpace.DisallowTabIndent + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.BlockComment now correctly applies rules for block comments after a short echo tag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Generic.NamingConventions.ConstructorName no longer throws deprecation notices on PHP 8.1 + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed false positives when using attributes in the following sniffs: + - PEAR.Commenting.FunctionComment + - Squiz.Commenting.InlineComment + - Squiz.Commenting.BlockComment + - Squiz.Commenting.VariableComment + - Squiz.WhiteSpace.MemberVarSpacing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3294][sq-3294] : Bug in attribute tokenization when content contains PHP end token or attribute closer on new line + - Thanks to [Alessandro Chitolina][@alekitto] for the patch + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the tests +- Fixed bug [#3296][sq-3296] : PSR2.ControlStructures.SwitchDeclaration takes phpcs:ignore as content of case body +- Fixed bug [#3297][sq-3297] : PSR2.ControlStructures.SwitchDeclaration.TerminatingComment does not handle try/finally blocks + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3302][sq-3302] : PHP 8.0 | Tokenizer/PHP: bugfix for union types using namespace operator + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3303][sq-3303] : findStartOfStatement() doesn't work with T_OPEN_TAG_WITH_ECHO +- Fixed bug [#3316][sq-3316] : Arrow function not tokenized correctly when using null in union type +- Fixed bug [#3317][sq-3317] : Problem with how phpcs handles ignored files when running in parallel + - Thanks to [Emil Andersson][@emil-nasso] for the patch +- Fixed bug [#3324][sq-3324] : PHPCS hangs processing some nested arrow functions inside a function call +- Fixed bug [#3326][sq-3326] : Generic.Formatting.MultipleStatementAlignment error with const DEFAULT + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3333][sq-3333] : Squiz.Objects.ObjectInstantiation: null coalesce operators are not recognized as assignment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3340][sq-3340] : Ensure interface and trait names are always tokenized as T_STRING + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3342][sq-3342] : PSR12/Squiz/PEAR standards all error on promoted properties with docblocks + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3345][sq-3345] : IF statement with no braces and double catch turned into syntax error by auto-fixer + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3352][sq-3352] : PSR2.ControlStructures.SwitchDeclaration can remove comments on the same line as the case statement while fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3357][sq-3357] : Generic.Functions.OpeningFunctionBraceBsdAllman removes return type when additional lines are present + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3362][sq-3362] : Generic.WhiteSpace.ScopeIndent false positive for arrow functions inside arrays +- Fixed bug [#3384][sq-3384] : Squiz.Commenting.FileComment.SpacingAfterComment false positive on empty file +- Fixed bug [#3394][sq-3394] : Fix PHP 8.1 auto_detect_line_endings deprecation notice +- Fixed bug [#3400][sq-3400] : PHP 8.1: prevent deprecation notices about missing return types + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3424][sq-3424] : PHPCS fails when using PHP 8 Constructor property promotion with attributes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3425][sq-3425] : PHP 8.1 | Runner::processChildProcs(): fix passing null to non-nullable bug + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3445][sq-3445] : Nullable parameter after attribute incorrectly tokenized as ternary operator + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-3294]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3294 +[sq-3296]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3296 +[sq-3297]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3297 +[sq-3302]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3302 +[sq-3303]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3303 +[sq-3316]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3316 +[sq-3317]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3317 +[sq-3324]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3324 +[sq-3326]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3326 +[sq-3333]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3333 +[sq-3340]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3340 +[sq-3342]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3342 +[sq-3345]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3345 +[sq-3352]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3352 +[sq-3357]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3357 +[sq-3362]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3362 +[sq-3384]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3384 +[sq-3394]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3394 +[sq-3400]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3400 +[sq-3424]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3424 +[sq-3425]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3425 +[sq-3445]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3445 + +## [3.6.0] - 2021-04-09 + +### Added +- Added support for PHP 8.0 union types + - A new T_TYPE_UNION token is available to represent the pipe character + - File::getMethodParameters(), getMethodProperties(), and getMemberProperties() will now return union types + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for PHP 8.0 named function call arguments + - A new T_PARAM_NAME token is available to represent the label with the name of the function argument in it + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for PHP 8.0 attributes + - The PHP-supplied T_ATTRIBUTE token marks the start of an attribute + - A new T_ATTRIBUTE_END token is available to mark the end of an attribute + - New attribute_owner and attribute_closer indexes are available in the tokens array for all tokens inside an attribute + - Tokenizing of attributes has been backfilled for older PHP versions + - The following sniffs have been updated to support attributes: + - PEAR.Commenting.ClassComment + - PEAR.Commenting.FileComment + - PSR1.Files.SideEffects + - PSR12.Files.FileHeader + - Squiz.Commenting.ClassComment + - Squiz.Commenting.FileComment + - Squiz.WhiteSpace.FunctionSpacing + - Thanks to [Vadim Borodavko][@javer] for the patch + - Thanks to [Alessandro Chitolina][@alekitto] for the patch +- Added support for PHP 8.0 dereferencing of text strings with interpolated variables + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for PHP 8.0 match expressions + - Match expressions are now tokenized with parenthesis and scope openers and closers + - Sniffs can listen for the T_MATCH token to process match expressions + - Note that the case and default statements inside match expressions do not have scopes set + - A new T_MATCH_ARROW token is available to represent the arrows in match expressions + - A new T_MATCH_DEFAULT token is available to represent the default keyword in match expressions + - All tokenizing of match expressions has been backfilled for older PHP versions + - The following sniffs have been updated to support match expressions: + - Generic.CodeAnalysis.AssignmentInCondition + - Generic.CodeAnalysis.EmptyPHPStatement + - Thanks to [Vadim Borodavko][@javer] for the patch + - Generic.CodeAnalysis.EmptyStatement + - Generic.PHP.LowerCaseKeyword + - PEAR.ControlStructures.ControlSignature + - PSR12.ControlStructures.BooleanOperatorPlacement + - Squiz.Commenting.LongConditionClosingComment + - Squiz.Commenting.PostStatementComment + - Squiz.ControlStructures.LowercaseDeclaration + - Squiz.ControlStructures.ControlSignature + - Squiz.Formatting.OperatorBracket + - Squiz.PHP.DisallowMultipleAssignments + - Squiz.Objects.ObjectInstantiation + - Squiz.WhiteSpace.ControlStructureSpacing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added Generic.NamingConventions.AbstractClassNamePrefix to enforce that class names are prefixed with "Abstract" + - Thanks to [Anna Borzenko][@annechko] for the contribution +- Added Generic.NamingConventions.InterfaceNameSuffix to enforce that interface names are suffixed with "Interface" + - Thanks to [Anna Borzenko][@annechko] for the contribution +- Added Generic.NamingConventions.TraitNameSuffix to enforce that trait names are suffixed with "Trait" + - Thanks to [Anna Borzenko][@annechko] for the contribution + +### Changed +- The value of the T_FN_ARROW token has changed from "T_FN_ARROW" to "PHPCS_T_FN_ARROW" to avoid package conflicts + - This will have no impact on custom sniffs unless they are specifically looking at the value of the T_FN_ARROW constant + - If sniffs are just using constant to find arrow functions, they will continue to work without modification + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- File::findStartOfStatement() now works correctly when passed the last token in a statement +- File::getMethodParameters() now supports PHP 8.0 constructor property promotion + - Returned method params now include a "property_visibility" and "visibility_token" index if property promotion is detected + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- File::getMethodProperties() now includes a "return_type_end_token" index in the return value + - This indicates the last token in the return type, which is helpful when checking union types + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Include patterns are now ignored when processing STDIN + - Previously, checks using include patterns were excluded when processing STDIN when no file path was provided via --stdin-path + - Now, all include and exclude rules are ignored when no file path is provided, allowing all checks to run + - If you want include and exclude rules enforced when checking STDIN, use --stdin-path to set the file path + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Spaces are now correctly escaped in the paths to external on Windows + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.CodeAnalysis.UnusedFunctionParameter can now be configured to ignore variable usage for specific type hints + - This allows you to suppress warnings for some variables that are not required, but leave warnings for others + - Set the ignoreTypeHints array property to a list of type hints to ignore + - Thanks to [Petr Bugyík][@o5] for the patch +- Generic.Formatting.MultipleStatementAlignment can now align statements at the start of the assignment token + - Previously, the sniff enforced that the values were aligned, even if this meant the assignment tokens were not + - Now, the sniff can enforce that the assignment tokens are aligned, even if this means the values are not + - Set the "alignAtEnd" sniff property to "false" to align the assignment tokens + - The default remains at "true", so the assigned values are aligned + - Thanks to [John P. Bloch][@johnpbloch] for the patch +- Generic.PHP.LowerCaseType now supports checking of typed properties + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.LowerCaseType now supports checking of union types + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.Commenting.FunctionComment and Squiz.Commenting.FunctionComment sniffs can now ignore private and protected methods + - Set the "minimumVisibility" sniff property to "protected" to ignore private methods + - Set the "minimumVisibility" sniff property to "public" to ignore both private and protected methods + - The default remains at "private", so all methods are checked + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- PEAR.Commenting.FunctionComment and Squiz.Commenting.FunctionComment sniffs can now ignore return tags in any method + - Previously, only `__construct()` and `__destruct()` were ignored + - Set the list of method names to ignore in the "specialMethods" sniff property + - The default remains at "__construct" and "__destruct" only + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- PSR2.ControlStructures.SwitchDeclaration now supports nested switch statements where every branch terminates + - Previously, if a CASE only contained a SWITCH and no direct terminating statement, a fall-through error was displayed + - Now, the error is suppressed if every branch of the SWITCH has a terminating statement + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- The PSR2.Methods.FunctionCallSignature.SpaceBeforeCloseBracket error message is now reported on the closing parenthesis token + - Previously, the error was being reported on the function keyword, leading to confusing line numbers in the error report +- Squiz.Commenting.FunctionComment is now able to ignore function comments that are only inheritdoc statements + - Set the skipIfInheritdoc sniff property to "true" to skip checking function comments if the content is only {@inhertidoc} + - The default remains at "false", so these comments will continue to report errors + - Thanks to [Jess Myrbo][@xjm] for the patch +- Squiz.Commenting.FunctionComment now supports the PHP 8 mixed type + - Thanks to [Vadim Borodavko][@javer] for the patch +- Squiz.PHP.NonExecutableCode now has improved handling of syntax errors + - Thanks to [Thiemo Kreuz][@thiemowmde] for the patch +- Squiz.WhiteSpace.ScopeKeywordSpacing now checks spacing when using PHP 8.0 constructor property promotion + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed an issue that could occur when checking files on network drives, such as with WSL2 on Windows 10 + - This works around a long-standing PHP bug with is_readable() + - Thanks to [Michael S][@codebymikey] for the patch +- Fixed a number of false positives in the Squiz.PHP.DisallowMultipleAssignments sniff + - Sniff no longer errors for default value assignments in arrow functions + - Sniff no longer errors for assignments on first line of closure + - Sniff no longer errors for assignments after a goto label + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#2913][sq-2913] : Generic.WhiteSpace.ScopeIndent false positive when opening and closing tag on same line inside conditional +- Fixed bug [#2992][sq-2992] : Enabling caching using a ruleset produces invalid cache files when using --sniffs and --exclude CLI args +- Fixed bug [#3003][sq-3003] : Squiz.Formatting.OperatorBracket autofix incorrect when assignment used with null coalescing operator +- Fixed bug [#3145][sq-3145] : Autoloading of sniff fails when multiple classes declared in same file +- Fixed bug [#3157][sq-3157] : PSR2.ControlStructures.SwitchDeclaration.BreakIndent false positive when case keyword is not indented +- Fixed bug [#3163][sq-3163] : Undefined index error with pre-commit hook using husky on PHP 7.4 + - Thanks to [Ismo Vuorinen][@ivuorinen] for the patch +- Fixed bug [#3165][sq-3165] : Squiz.PHP.DisallowComparisonAssignment false positive when comparison inside closure +- Fixed bug [#3167][sq-3167] : Generic.WhiteSpace.ScopeIndent false positive when using PHP 8.0 constructor property promotion +- Fixed bug [#3170][sq-3170] : Squiz.WhiteSpace.OperatorSpacing false positive when using negation with string concat + - This also fixes the same issue in the PSR12.Operators.OperatorSpacing sniff +- Fixed bug [#3177][sq-3177] : Incorrect tokenization of GOTO statements in mixed PHP/HTML files + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3184][sq-3184] : PSR2.Namespace.NamespaceDeclaration false positive on namespace operator + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3188][sq-3188] : Squiz.WhiteSpace.ScopeKeywordSpacing false positive for static return type + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3192][sq-3192] : findStartOfStatement doesn't work correctly inside switch + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- Fixed bug [#3195][sq-3195] : Generic.WhiteSpace.ScopeIndent confusing message when combination of tabs and spaces found +- Fixed bug [#3197][sq-3197] : Squiz.NamingConventions.ValidVariableName does not use correct error code for all member vars +- Fixed bug [#3219][sq-3219] : Generic.Formatting.MultipleStatementAlignment false positive for empty anonymous classes and closures +- Fixed bug [#3258][sq-3258] : Squiz.Formatting.OperatorBracket duplicate error messages for unary minus + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3273][sq-3273] : Squiz.Functions.FunctionDeclarationArgumentSpacing reports line break as 0 spaces between parenthesis +- Fixed bug [#3277][sq-3277] : Nullable static return typehint causes whitespace error +- Fixed bug [#3284][sq-3284] : Unused parameter false positive when using array index in arrow function + +[sq-2913]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2913 +[sq-2992]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2992 +[sq-3003]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3003 +[sq-3145]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3145 +[sq-3157]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3157 +[sq-3163]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3163 +[sq-3165]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3165 +[sq-3167]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3167 +[sq-3170]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3170 +[sq-3177]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3177 +[sq-3184]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3184 +[sq-3188]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3188 +[sq-3192]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3192 +[sq-3195]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3195 +[sq-3197]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3197 +[sq-3219]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3219 +[sq-3258]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3258 +[sq-3273]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3273 +[sq-3277]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3277 +[sq-3284]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3284 + +## [3.5.8] - 2020-10-23 + +### Removed +- Reverted a change to the way include/exclude patterns are processed for STDIN content + - This change is not backwards compatible and will be re-introduced in version 3.6.0 + +## [3.5.7] - 2020-10-23 + +### Added +- The PHP 8.0 T_NULLSAFE_OBJECT_OPERATOR token has been made available for older versions + - Existing sniffs that check for T_OBJECT_OPERATOR have been modified to apply the same rules for the nullsafe object operator + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The new method of PHP 8.0 tokenizing for namespaced names has been reverted to the pre 8.0 method + - This maintains backwards compatible for existing sniffs on PHP 8.0 + - This change will be removed in PHPCS 4.0 as the PHP 8.0 tokenizing method will be backported for pre 8.0 versions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for changes to the way PHP 8.0 tokenizes hash comments + - The existing PHP 5-7 behaviour has been replicated for version 8, so no sniff changes are required + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Running the unit tests now includes warnings in the found and fixable error code counts + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PSR12.Functions.NullableTypeDeclaration now supports the PHP8 static return type + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Changed +- The autoloader has been changed to fix sniff class name detection issues that may occur when running on PHP 7.4+ + - Thanks to [Eloy Lafuente][@stronk7] for the patch +- PSR12.ControlStructures.BooleanOperatorPlacement.FoundMixed error message is now more accurate when using the allowOnly setting + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch + +### Fixed +- Fixed Squiz.Formatting.OperatorBracket false positive when exiting with a negative number +- Fixed Squiz.PHP.DisallowComparisonAssignment false positive for methods called on an object +- Fixed bug [#2882][sq-2882] : Generic.Arrays.ArrayIndent can request close brace indent to be less than the statement indent level +- Fixed bug [#2883][sq-2883] : Generic.WhiteSpace.ScopeIndent.Incorrect issue after NOWDOC +- Fixed bug [#2975][sq-2975] : Undefined offset in PSR12.Functions.ReturnTypeDeclaration when checking function return type inside ternary +- Fixed bug [#2988][sq-2988] : Undefined offset in Squiz.Strings.ConcatenationSpacing during live coding + - Thanks to [Thiemo Kreuz][@thiemowmde] for the patch +- Fixed bug [#2989][sq-2989] : Incorrect auto-fixing in Generic.ControlStructures.InlineControlStructure during live coding + - Thanks to [Thiemo Kreuz][@thiemowmde] for the patch +- Fixed bug [#3007][sq-3007] : Directory exclude pattern improperly excludes directories with names that start the same + - Thanks to [Steve Talbot][@SteveTalbot] for the patch +- Fixed bug [#3043][sq-3043] : Squiz.WhiteSpace.OperatorSpacing false positive for negation in arrow function + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3049][sq-3049] : Incorrect error with arrow function and parameter passed as reference + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3053][sq-3053] : PSR2 incorrect fix when multiple use statements on same line do not have whitespace between them +- Fixed bug [#3058][sq-3058] : Progress gets unaligned when 100% happens at the end of the available dots +- Fixed bug [#3059][sq-3059] : Squiz.Arrays.ArrayDeclaration false positive when using type casting + - Thanks to [Sergei Morozov][@morozov] for the patch +- Fixed bug [#3060][sq-3060] : Squiz.Arrays.ArrayDeclaration false positive for static functions + - Thanks to [Sergei Morozov][@morozov] for the patch +- Fixed bug [#3065][sq-3065] : Should not fix Squiz.Arrays.ArrayDeclaration.SpaceBeforeComma if comment between element and comma + - Thanks to [Sergei Morozov][@morozov] for the patch +- Fixed bug [#3066][sq-3066] : No support for namespace operator used in type declarations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3075][sq-3075] : PSR12.ControlStructures.BooleanOperatorPlacement false positive when operator is the only content on line +- Fixed bug [#3099][sq-3099] : Squiz.WhiteSpace.OperatorSpacing false positive when exiting with negative number + - Thanks to [Sergei Morozov][@morozov] for the patch +- Fixed bug [#3102][sq-3102] : PSR12.Squiz.OperatorSpacing false positive for default values of arrow functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#3124][sq-3124] : PSR-12 not reporting error for empty lines with only whitespace +- Fixed bug [#3135][sq-3135] : Ignore annotations are broken on PHP 8.0 + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-2882]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2882 +[sq-2883]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2883 +[sq-2975]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2975 +[sq-2988]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2988 +[sq-2989]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2989 +[sq-3007]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3007 +[sq-3043]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3043 +[sq-3049]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3049 +[sq-3053]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3053 +[sq-3058]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3058 +[sq-3059]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3059 +[sq-3060]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3060 +[sq-3065]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3065 +[sq-3066]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3066 +[sq-3075]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3075 +[sq-3099]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3099 +[sq-3102]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3102 +[sq-3124]: https://github.com/squizlabs/PHP_CodeSniffer/issues/3124 +[sq-3135]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3135 + +## [3.5.6] - 2020-08-10 + +### Added +- Added support for PHP 8.0 magic constant dereferencing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added support for changes to the way PHP 8.0 tokenizes comments + - The existing PHP 5-7 behaviour has been replicated for version 8, so no sniff changes are required + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- `File::getMethodProperties()` now detects the PHP 8.0 static return type + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The PHP 8.0 static return type is now supported for arrow functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Changed +- The cache is no longer used if the list of loaded PHP extensions changes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- `Generic.NamingConventions.CamelCapsFunctionName` no longer reports `__serialize` and `__unserialize` as invalid names + - Thanks to [Filip Å ][@filips123] for the patch +- `PEAR.NamingConventions.ValidFunctionName` no longer reports `__serialize` and `__unserialize` as invalid names + - Thanks to [Filip Å ][@filips123] for the patch +- `Squiz.Scope.StaticThisUsage` now detects usage of `$this` inside closures and arrow functions + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch + +### Fixed +- Fixed bug [#2877][sq-2877] : PEAR.Functions.FunctionCallSignature false positive for array of functions + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- Fixed bug [#2888][sq-2888] : PSR12.Files.FileHeader blank line error with multiple namespaces in one file +- Fixed bug [#2926][sq-2926] : phpcs hangs when using arrow functions that return heredoc +- Fixed bug [#2943][sq-2943] : Redundant semicolon added to a file when fixing PSR2.Files.ClosingTag.NotAllowed +- Fixed bug [#2967][sq-2967] : Markdown generator does not output headings correctly + - Thanks to [Petr Bugyík][@o5] for the patch +- Fixed bug [#2977][sq-2977] : File::isReference() does not detect return by reference for closures + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2994][sq-2994] : Generic.Formatting.DisallowMultipleStatements false positive for FOR loop with no body +- Fixed bug [#3033][sq-3033] : Error generated during tokenizing of goto statements on PHP 8 + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-2877]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2877 +[sq-2888]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2888 +[sq-2926]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2926 +[sq-2943]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2943 +[sq-2967]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2967 +[sq-2977]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2977 +[sq-2994]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2994 +[sq-3033]: https://github.com/squizlabs/PHP_CodeSniffer/pull/3033 + +## [3.5.5] - 2020-04-17 + +### Changed +- The T_FN backfill now works more reliably so T_FN tokens only ever represent real arrow functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed an issue where including sniffs using paths containing multiple dots would silently fail +- Generic.CodeAnalysis.EmptyPHPStatement now detects empty statements at the start of control structures + +### Fixed +- Error wording in PEAR.Functions.FunctionCallSignature now always uses "parenthesis" instead of sometimes using "bracket" + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- Fixed bug [#2787][sq-2787] : Squiz.PHP.DisallowMultipleAssignments not ignoring typed property declarations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2810][sq-2810] : PHPCBF fails to fix file with empty statement at start on control structure +- Fixed bug [#2812][sq-2812] : Squiz.Arrays.ArrayDeclaration not detecting some arrays with multiple arguments on the same line + - Thanks to [Jakub Chábek][@grongor] for the patch +- Fixed bug [#2826][sq-2826] : Generic.WhiteSpace.ArbitraryParenthesesSpacing doesn't detect issues for statements directly after a control structure + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- Fixed bug [#2848][sq-2848] : PSR12.Files.FileHeader false positive for file with mixed PHP and HTML and no file header +- Fixed bug [#2849][sq-2849] : Generic.WhiteSpace.ScopeIndent false positive with arrow function inside array +- Fixed bug [#2850][sq-2850] : Generic.PHP.LowerCaseKeyword complains __HALT_COMPILER is uppercase +- Fixed bug [#2853][sq-2853] : Undefined variable error when using Info report + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2865][sq-2865] : Double arrow tokenized as T_STRING when placed after function named "fn" +- Fixed bug [#2867][sq-2867] : Incorrect scope matching when arrow function used inside IF condition +- Fixed bug [#2868][sq-2868] : phpcs:ignore annotation doesn't work inside a docblock +- Fixed bug [#2878][sq-2878] : PSR12.Files.FileHeader conflicts with Generic.Files.LineEndings +- Fixed bug [#2895][sq-2895] : PSR2.Methods.FunctionCallSignature.MultipleArguments false positive with arrow function argument + +[sq-2787]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2787 +[sq-2810]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2810 +[sq-2812]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2812 +[sq-2826]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2826 +[sq-2848]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2848 +[sq-2849]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2849 +[sq-2850]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2850 +[sq-2853]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2853 +[sq-2865]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2865 +[sq-2867]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2867 +[sq-2868]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2868 +[sq-2878]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2878 +[sq-2895]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2895 + +## [3.5.4] - 2020-01-31 + +### Changed +- The PHP 7.4 numeric separator backfill now works correctly for more float formats + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The PHP 7.4 numeric separator backfill is no longer run on PHP version 7.4.0 or greater +- File::getCondition() now accepts a 3rd argument that allows for the closest matching token to be returned + - By default, it continues to return the first matched token found from the top of the file +- Fixed detection of array return types for arrow functions +- Added Generic.PHP.DisallowRequestSuperglobal to ban the use of the $_REQUEST superglobal + - Thanks to [Jeantwan Teuma][@Morerice] for the contribution +- Generic.ControlStructures.InlineControlStructure no longer shows errors for WHILE and FOR statements without a body + - Previously it required these to have curly braces, but there were no statements to enclose in them + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PSR12.ControlStructures.BooleanOperatorPlacement can now be configured to enforce a specific operator position + - By default, the sniff ensures that operators are all at the beginning or end of lines, but not a mix of both + - Set the allowOnly property to "first" to enforce all boolean operators to be at the start of a line + - Set the allowOnly property to "last" to enforce all boolean operators to be at the end of a line + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- PSR12.Files.ImportStatement now auto-fixes import statements by removing the leading slash + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Squiz.ControlStructures.ForLoopDeclaration now has a setting to ignore newline characters + - Default remains FALSE, so newlines are not allowed within FOR definitions + - Override the "ignoreNewlines" setting in a ruleset.xml file to change +- Squiz.PHP.InnerFunctions now handles multiple nested anon classes correctly + +### Fixed +- Fixed bug [#2497][sq-2497] : Sniff properties not set when referencing a sniff using relative paths or non-native slashes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2657][sq-2657] : Squiz.WhiteSpace.FunctionSpacing can remove spaces between comment and first/last method during auto-fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2688][sq-2688] : Case statements not tokenized correctly when switch is contained within ternary +- Fixed bug [#2698][sq-2698] : PHPCS throws errors determining auto report width when shell_exec is disabled + - Thanks to [Matthew Peveler][@MasterOdin] for the patch +- Fixed bug [#2730][sq-2730] : PSR12.ControlStructures.ControlStructureSpacing does not ignore comments between conditions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2732][sq-2732] : PSR12.Files.FileHeader misidentifies file header in mixed content file +- Fixed bug [#2745][sq-2745] : AbstractArraySniff wrong indices when mixed coalesce and ternary values + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#2748][sq-2748] : Wrong end of statement for fn closures + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#2751][sq-2751] : Autoload relative paths first to avoid confusion with files from the global include path + - Thanks to [Klaus Purer][@klausi] for the patch +- Fixed bug [#2763][sq-2763] : PSR12 standard reports errors for multi-line FOR definitions +- Fixed bug [#2768][sq-2768] : Generic.Files.LineLength false positive for non-breakable strings at exactly the soft limit + - Thanks to [Alex Miles][@ghostal] for the patch +- Fixed bug [#2773][sq-2773] : PSR2.Methods.FunctionCallSignature false positive when arrow function has array return type +- Fixed bug [#2790][sq-2790] : PSR12.Traits.UseDeclaration ignores block comments + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- Fixed bug [#2791][sq-2791] : PSR12.Functions.NullableTypeDeclaration false positive when ternary operator used with instanceof + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2802][sq-2802] : Can't specify a report file path using the tilde shortcut +- Fixed bug [#2804][sq-2804] : PHP4-style typed properties not tokenized correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2805][sq-2805] : Undefined Offset notice during live coding of arrow functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2843][sq-2843] : Tokenizer does not support alternative syntax for declare statements + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-2497]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2497 +[sq-2657]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2657 +[sq-2688]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2688 +[sq-2698]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2698 +[sq-2730]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2730 +[sq-2732]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2732 +[sq-2745]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2745 +[sq-2748]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2748 +[sq-2751]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2751 +[sq-2763]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2763 +[sq-2768]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2768 +[sq-2773]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2773 +[sq-2790]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2790 +[sq-2791]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2791 +[sq-2802]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2802 +[sq-2804]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2804 +[sq-2805]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2805 +[sq-2843]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2843 + +## [3.5.3] - 2019-12-04 + +### Changed +- The PHP 7.4 T_FN token has been made available for older versions + - T_FN represents the fn string used for arrow functions + - The double arrow becomes the scope opener, and uses a new T_FN_ARROW token type + - The token after the statement (normally a semicolon) becomes the scope closer + - The token is also associated with the opening and closing parenthesis of the statement + - Any functions named "fn" will have a T_FN token for the function name, but have no scope information + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the help with this change +- PHP 7.4 numeric separators are now tokenized in the same way when using older PHP versions + - Previously, a number like 1_000 would tokenize as T_LNUMBER (1), T_STRING (_000) + - Now, the number tokenizes as T_LNUMBER (1_000) + - Sniff developers should consider how numbers with underscores impact their custom sniffs +- The PHPCS file cache now takes file permissions into account + - The cache is now invalidated for a file when its permissions are changed +- File::getMethodParameters() now supports arrow functions +- File::getMethodProperties() now supports arrow functions +- Added Fixer::changeCodeBlockIndent() to change the indent of a code block while auto-fixing + - Can be used to either increase or decrease the indent + - Useful when moving the start position of something like a closure, where you want the content to also move +- Added Generic.Files.ExecutableFile sniff + - Ensures that files are not executable + - Thanks to [Matthew Peveler][@MasterOdin] for the contribution +- Generic.CodeAnalysis.EmptyPhpStatement now reports unnecessary semicolons after control structure closing braces + - Thanks to [Vincent Langlet][@VincentLanglet] for the patch +- Generic.PHP.LowerCaseKeyword now enforces that the "fn" keyword is lowercase + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Generic.WhiteSpace.ScopeIndent now supports static arrow functions +- PEAR.Functions.FunctionCallSignature now adjusts the indent of function argument contents during auto-fixing + - Previously, only the first line of an argument was changed, leading to inconsistent indents + - This change also applies to PSR2.Methods.FunctionCallSignature +- PSR2.ControlStructures.ControlStructureSpacing now checks whitespace before the closing parenthesis of multi-line control structures + - Previously, it incorrectly applied the whitespace check for single-line definitions only +- PSR12.Functions.ReturnTypeDeclaration now checks the return type of arrow functions + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- PSR12.Traits.UseDeclaration now ensures all trait import statements are grouped together + - Previously, the trait import section of the class ended when the first non-import statement was found + - Checking now continues throughout the class to ensure all statements are grouped together + - This also ensures that empty lines are not requested after an import statement that isn't the last one +- Squiz.Functions.LowercaseFunctionKeywords now enforces that the "fn" keyword is lowercase + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch + +### Fixed +- Fixed bug [#2586][sq-2586] : Generic.WhiteSpace.ScopeIndent false positives when indenting open tags at a non tab-stop +- Fixed bug [#2638][sq-2638] : Squiz.CSS.DuplicateClassDefinitionSniff sees comments as part of the class name + - Thanks to [Raphael Horber][@rhorber] for the patch +- Fixed bug [#2640][sq-2640] : Squiz.WhiteSpace.OperatorSpacing false positives for some negation operators + - Thanks to [Jakub Chábek][@grongor] and [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2674][sq-2674] : Squiz.Functions.FunctionDeclarationArgumentSpacing prints wrong argument name in error message +- Fixed bug [#2676][sq-2676] : PSR12.Files.FileHeader locks up when file ends with multiple inline comments +- Fixed bug [#2678][sq-2678] : PSR12.Classes.AnonClassDeclaration incorrectly enforcing that closing brace be on a line by itself +- Fixed bug [#2685][sq-2685] : File::getMethodParameters() setting typeHintEndToken for vars with no type hint + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2694][sq-2694] : AbstractArraySniff produces invalid indices when using ternary operator + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#2702][sq-2702] : Generic.WhiteSpace.ScopeIndent false positive when using ternary operator with short arrays + +[sq-2586]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2586 +[sq-2638]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2638 +[sq-2640]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2640 +[sq-2674]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2674 +[sq-2676]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2676 +[sq-2678]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2678 +[sq-2685]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2685 +[sq-2694]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2694 +[sq-2702]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2702 + +## [3.5.2] - 2019-10-28 + +### Changed +- Generic.ControlStructures.DisallowYodaConditions now returns less false positives + - False positives were being returned for array comparisons, or when performing some function calls +- Squiz.WhiteSpace.SemicolonSpacing.Incorrect error message now escapes newlines and tabs + - Provides a clearer error message as whitespace is now visible + - Also allows for better output for report types such as CSV and XML +- The error message for PSR12.Files.FileHeader.SpacingAfterBlock has been made clearer + - It now uses the wording from the published PSR-12 standard to indicate that blocks must be separated by a blank line + - Thanks to [Craig Duncan][@duncan3dc] for the patch + +### Fixed +- Fixed bug [#2654][sq-2654] : Incorrect indentation for arguments of multiline function calls +- Fixed bug [#2656][sq-2656] : Squiz.WhiteSpace.MemberVarSpacing removes comments before first member var during auto fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2663][sq-2663] : Generic.NamingConventions.ConstructorName complains about old constructor in interfaces +- Fixed bug [#2664][sq-2664] : PSR12.Files.OpenTag incorrectly identifies PHP file with only an opening tag +- Fixed bug [#2665][sq-2665] : PSR12.Files.ImportStatement should not apply to traits +- Fixed bug [#2673][sq-2673] : PSR12.Traits.UseDeclaration does not allow comments or blank lines between use statements + +[sq-2654]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2654 +[sq-2656]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2656 +[sq-2663]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2663 +[sq-2664]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2664 +[sq-2665]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2665 +[sq-2673]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2673 + +## [3.5.1] - 2019-10-17 + +### Changed +- Very very verbose diff report output has slightly changed to improve readability + - Output is printed when running PHPCS with the --report=diff and -vvv command line arguments + - Fully qualified class names have been replaced with sniff codes + - Tokens being changed now display the line number they are on +- PSR2, PSR12, and PEAR standards now correctly check for blank lines at the start of function calls + - This check has been missing from these standards, but has now been implemented + - When using the PEAR standard, the error code is PEAR.Functions.FunctionCallSignature.FirstArgumentPosition + - When using PSR2 or PSR12, the error code is PSR2.Methods.FunctionCallSignature.FirstArgumentPosition +- PSR12.ControlStructures.BooleanOperatorPlacement no longer complains when multiple expressions appear on the same line + - Previously, boolean operators were enforced to appear at the start or end of lines only + - Boolean operators can now appear in the middle of the line +- PSR12.Files.FileHeader no longer ignores comments preceding a use, namespace, or declare statement +- PSR12.Files.FileHeader now allows a hashbang line at the top of the file + +### Fixed +- Fixed bug [#2506][sq-2506] : PSR2 standard can't auto fix multi-line function call inside a string concat statement +- Fixed bug [#2530][sq-2530] : PEAR.Commenting.FunctionComment does not support intersection types in comments +- Fixed bug [#2615][sq-2615] : Constant visibility false positive on non-class constants +- Fixed bug [#2616][sq-2616] : PSR12.Files.FileHeader false positive when file only contains docblock +- Fixed bug [#2619][sq-2619] : PSR12.Files.FileHeader locks up when inline comment is the last content in a file +- Fixed bug [#2621][sq-2621] : PSR12.Classes.AnonClassDeclaration.CloseBraceSameLine false positive for anon class passed as function argument + - Thanks to [Martins Sipenko][@martinssipenko] for the patch +- Fixed bug [#2623][sq-2623] : PSR12.ControlStructures.ControlStructureSpacing not ignoring indentation inside multi-line string arguments +- Fixed bug [#2624][sq-2624] : PSR12.Traits.UseDeclaration doesnt apply the correct indent during auto fixing +- Fixed bug [#2626][sq-2626] : PSR12.Files.FileHeader detects @var annotations as file docblocks +- Fixed bug [#2628][sq-2628] : PSR12.Traits.UseDeclaration does not allow comments above a USE declaration +- Fixed bug [#2632][sq-2632] : Incorrect indentation of lines starting with "static" inside closures +- Fixed bug [#2641][sq-2641] : PSR12.Functions.NullableTypeDeclaration false positive when using new static() + +[sq-2506]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2506 +[sq-2530]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2530 +[sq-2615]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2615 +[sq-2616]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2616 +[sq-2619]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2619 +[sq-2621]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2621 +[sq-2623]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2623 +[sq-2624]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2624 +[sq-2626]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2626 +[sq-2628]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2628 +[sq-2632]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2632 +[sq-2641]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2641 + +## [3.5.0] - 2019-09-27 + +### Changed +- The included PSR12 standard is now complete and ready to use + - Check your code using PSR-12 by running PHPCS with --standard=PSR12 +- Added support for PHP 7.4 typed properties + - The nullable operator is now tokenized as T_NULLABLE inside property types, as it is elsewhere + - To get the type of a member var, use the File::getMemberProperties() method, which now contains a "type" array index + - This contains the type of the member var, or a blank string if not specified + - If the type is nullable, the return type will contain the leading ? + - If a type is specified, the position of the first token in the type will be set in a "type_token" array index + - If a type is specified, the position of the last token in the type will be set in a "type_end_token" array index + - If the type is nullable, a "nullable_type" array index will also be set to TRUE + - If the type contains namespace information, it will be cleaned of whitespace and comments in the return value +- The PSR1 standard now correctly bans alternate PHP tags + - Previously, it only banned short open tags and not the pre-7.0 alternate tags +- Added support for only checking files that have been locally staged in a git repo + - Use --filter=gitstaged to check these files + - You still need to give PHPCS a list of files or directories in which to apply the filter + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- JSON reports now end with a newline character +- The phpcs.xsd schema now validates phpcs-only and phpcbf-only attributes correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The tokenizer now correctly identifies inline control structures in more cases +- All helper methods inside the File class now throw RuntimeException instead of TokenizerException + - Some tokenizer methods were also throwing RuntimeException but now correctly throw TokenizerException + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The File::getMethodParameters() method now returns more information, and supports closure USE groups + - If a type hint is specified, the position of the last token in the hint will be set in a "type_hint_end_token" array index + - If a default is specified, the position of the first token in the default value will be set in a "default_token" array index + - If a default is specified, the position of the equals sign will be set in a "default_equal_token" array index + - If the param is not the last, the position of the comma will be set in a "comma_token" array index + - If the param is passed by reference, the position of the reference operator will be set in a "reference_token" array index + - If the param is variable length, the position of the variadic operator will be set in a "variadic_token" array index +- The T_LIST token and it's opening and closing parentheses now contain references to each other in the tokens array + - Uses the same parenthesis_opener/closer/owner indexes as other tokens + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The T_ANON_CLASS token and it's opening and closing parentheses now contain references to each other in the tokens array + - Uses the same parenthesis_opener/closer/owner indexes as other tokens + - Only applicable if the anon class is passing arguments to the constructor + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The PHP 7.4 T_BAD_CHARACTER token has been made available for older versions + - Allows you to safely look for this token, but it will not appear unless checking with PHP 7.4+ +- Metrics are now available for Squiz.WhiteSpace.FunctionSpacing + - Use the "info" report to see blank lines before/after functions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Metrics are now available for Squiz.WhiteSpace.MemberVarSpacing + - Use the "info" report to see blank lines before member vars + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added Generic.ControlStructures.DisallowYodaConditions sniff + - Ban the use of Yoda conditions + - Thanks to [Mponos George][@gmponos] for the contribution +- Added Generic.PHP.RequireStrictTypes sniff + - Enforce the use of a strict types declaration in PHP files +- Added Generic.WhiteSpace.SpreadOperatorSpacingAfter sniff + - Checks whitespace between the spread operator and the variable/function call it applies to + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added PSR12.Classes.AnonClassDeclaration sniff + - Enforces the formatting of anonymous classes +- Added PSR12.Classes.ClosingBrace sniff + - Enforces that closing braces of classes/interfaces/traits/functions are not followed by a comment or statement +- Added PSR12.ControlStructures.BooleanOperatorPlacement sniff + - Enforces that boolean operators between conditions are consistently at the start or end of the line +- Added PSR12.ControlStructures.ControlStructureSpacing sniff + - Enforces that spacing and indents are correct inside control structure parenthesis +- Added PSR12.Files.DeclareStatement sniff + - Enforces the formatting of declare statements within a file +- Added PSR12.Files.FileHeader sniff + - Enforces the order and formatting of file header blocks +- Added PSR12.Files.ImportStatement sniff + - Enforces the formatting of import statements within a file +- Added PSR12.Files.OpenTag sniff + - Enforces that the open tag is on a line by itself when used at the start of a PHP-only file +- Added PSR12.Functions.ReturnTypeDeclaration sniff + - Enforces the formatting of return type declarations in functions and closures +- Added PSR12.Properties.ConstantVisibility sniff + - Enforces that constants must have their visibility defined + - Uses a warning instead of an error due to this conditionally requiring the project to support PHP 7.1+ +- Added PSR12.Traits.UseDeclaration sniff + - Enforces the formatting of trait import statements within a class +- Generic.Files.LineLength ignoreComments property now ignores comments at the end of a line + - Previously, this property was incorrectly causing the sniff to ignore any line that ended with a comment + - Now, the trailing comment is not included in the line length, but the rest of the line is still checked +- Generic.Files.LineLength now only ignores unwrappable comments when the comment is on a line by itself + - Previously, a short unwrappable comment at the end of the line would have the sniff ignore the entire line +- Generic.Functions.FunctionCallArgumentSpacing no longer checks spacing around assignment operators inside function calls + - Use the Squiz.WhiteSpace.OperatorSpacing sniff to enforce spacing around assignment operators + - Note that this sniff checks spacing around all assignment operators, not just inside function calls + - The Generic.Functions.FunctionCallArgumentSpacing.NoSpaceBeforeEquals error has been removed + - Use Squiz.WhiteSpace.OperatorSpacing.NoSpaceBefore instead + - The Generic.Functions.FunctionCallArgumentSpacing.NoSpaceAfterEquals error has been removed + - Use Squiz.WhiteSpace.OperatorSpacing.NoSpaceAfter instead + - This also changes the PEAR/PSR2/PSR12 standards so they no longer check assignment operators inside function calls + - They were previously checking these operators when they should not have + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.WhiteSpace.ScopeIndent no longer performs exact indents checking for chained method calls + - Other sniffs can be used to enforce chained method call indent rules + - Thanks to [Pieter Frenssen][@pfrenssen] for the patch +- PEAR.WhiteSpace.ObjectOperatorIndent now supports multi-level chained statements + - When enabled, chained calls must be indented 1 level more or less than the previous line + - Set the new "multilevel" setting to TRUE in a ruleset.xml file to enable this behaviour + - Thanks to [Marcos Passos][@marcospassos] for the patch +- PSR2.ControlStructures.ControlStructureSpacing now allows whitespace after the opening parenthesis if followed by a comment + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- PSR2.Classes.PropertyDeclaration now enforces a single space after a property type keyword + - The PSR2 standard itself excludes this new check as it is not defined in the written standard + - Using the PSR12 standard will enforce this check +- Squiz.Commenting.BlockComment no longer requires blank line before comment if it's the first content after the PHP open tag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Functions.FunctionDeclarationArgumentSpacing now has more accurate error messages + - This includes renaming the SpaceAfterDefault error code to SpaceAfterEquals, which reflects the real error +- Squiz.Functions.FunctionDeclarationArgumentSpacing now checks for no space after a reference operator + - If you don't want this new behaviour, exclude the SpacingAfterReference error message in a ruleset.xml file +- Squiz.Functions.FunctionDeclarationArgumentSpacing now checks for no space after a variadic operator + - If you don't want this new behaviour, exclude the SpacingAfterVariadic error message in a ruleset.xml file +- Squiz.Functions.MultiLineFunctionDeclaration now has improved fixing for the FirstParamSpacing and UseFirstParamSpacing errors +- Squiz.Operators.IncrementDecrementUsage now suggests pre-increment of variables instead of post-increment + - This change does not enforce pre-increment over post-increment; only the suggestion has changed + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.DisallowMultipleAssignments now has a second error code for when assignments are found inside control structure conditions + - The new error code is Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure + - All other multiple assignment cases use the existing error code Squiz.PHP.DisallowMultipleAssignments.Found + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.FunctionSpacing now applies beforeFirst and afterLast spacing rules to nested functions + - Previously, these rules only applied to the first and last function in a class, interface, or trait + - These rules now apply to functions nested in any statement block, including other functions and conditions +- Squiz.WhiteSpace.OperatorSpacing now has improved handling of parse errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.OperatorSpacing now checks spacing around the instanceof operator + - Thanks to [Jakub Chábek][@grongor] for the patch +- Squiz.WhiteSpace.OperatorSpacing can now enforce a single space before assignment operators + - Previously, the sniff this spacing as multiple assignment operators are sometimes aligned + - Now, you can set the ignoreSpacingBeforeAssignments sniff property to FALSE to enable checking + - Default remains TRUE, so spacing before assignments is not checked by default + - Thanks to [Jakub Chábek][@grongor] for the patch + +### Fixed +- Fixed bug [#2391][sq-2391] : Sniff-specific ignore rules inside rulesets are filtering out too many files + - Thanks to [Juliette Reinders Folmer][@jrfnl] and [Willington Vega][@wvega] for the patch +- Fixed bug [#2478][sq-2478] : FunctionCommentThrowTag.WrongNumber when exception is thrown once but built conditionally +- Fixed bug [#2479][sq-2479] : Generic.WhiteSpace.ScopeIndent error when using array destructing with exact indent checking +- Fixed bug [#2498][sq-2498] : Squiz.Arrays.ArrayDeclaration.MultiLineNotAllowed autofix breaks heredoc +- Fixed bug [#2502][sq-2502] : Generic.WhiteSpace.ScopeIndent false positives with nested switch indentation and case fall-through +- Fixed bug [#2504][sq-2504] : Generic.WhiteSpace.ScopeIndent false positives with nested arrays and nowdoc string +- Fixed bug [#2511][sq-2511] : PSR2 standard not checking if closing paren of single-line function declaration is on new line +- Fixed bug [#2512][sq-2512] : Squiz.PHP.NonExecutableCode does not support alternate SWITCH control structure + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2522][sq-2522] : Text generator throws error when code sample line is too long + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2526][sq-2526] : XML report format has bad syntax on Windows + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2529][sq-2529] : Generic.Formatting.MultipleStatementAlignment wrong error for assign in string concat +- Fixed bug [#2534][sq-2534] : Unresolvable installed_paths can lead to open_basedir errors + - Thanks to [Oliver Nowak][@ndm2] for the patch +- Fixed bug [#2541][sq-2541] : Text doc generator does not allow for multi-line rule explanations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2549][sq-2549] : Searching for a phpcs.xml file can throw warnings due to open_basedir restrictions + - Thanks to [Matthew Peveler][@MasterOdin] for the patch +- Fixed bug [#2558][sq-2558] : PHP 7.4 throwing offset syntax with curly braces is deprecated message + - Thanks to [Matthew Peveler][@MasterOdin] for the patch +- Fixed bug [#2561][sq-2561] : PHP 7.4 compatibility fix / implode argument order + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2562][sq-2562] : Inline WHILE triggers SpaceBeforeSemicolon incorrectly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2565][sq-2565] : Generic.ControlStructures.InlineControlStructure confused by mixed short/long tags + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2566][sq-2566] : Author tag email validation doesn't support all TLDs + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2575][sq-2575] : Custom error messages don't have data replaced when cache is enabled +- Fixed bug [#2601][sq-2601] : Squiz.WhiteSpace.FunctionSpacing incorrect fix when spacing is 0 +- Fixed bug [#2608][sq-2608] : PSR2 throws errors for use statements when multiple namespaces are defined in a file + +[sq-2391]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2391 +[sq-2478]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2478 +[sq-2479]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2479 +[sq-2498]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2498 +[sq-2502]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2502 +[sq-2504]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2504 +[sq-2511]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2511 +[sq-2512]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2512 +[sq-2522]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2522 +[sq-2526]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2526 +[sq-2529]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2529 +[sq-2534]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2534 +[sq-2541]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2541 +[sq-2549]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2549 +[sq-2558]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2558 +[sq-2561]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2561 +[sq-2562]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2562 +[sq-2565]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2565 +[sq-2566]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2566 +[sq-2575]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2575 +[sq-2601]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2601 +[sq-2608]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2608 + +## [3.4.2] - 2019-04-11 + +### Changed +- Squiz.Arrays.ArrayDeclaration now has improved handling of syntax errors + +### Fixed +- Fixed an issue where the PCRE JIT on PHP 7.3 caused PHPCS to die when using the parallel option + - PHPCS now disables the PCRE JIT before running +- Fixed bug [#2368][sq-2368] : MySource.PHP.AjaxNullComparison throws error when first function has no doc comment +- Fixed bug [#2414][sq-2414] : Indention false positive in switch/case/if combination +- Fixed bug [#2423][sq-2423] : Squiz.Formatting.OperatorBracket.MissingBrackets error with static +- Fixed bug [#2450][sq-2450] : Indentation false positive when closure containing nested IF conditions used as function argument +- Fixed bug [#2452][sq-2452] : LowercasePHPFunctions sniff failing on "new \File()" +- Fixed bug [#2453][sq-2453] : Squiz.CSS.SemicolonSpacingSniff false positive when style name proceeded by an asterisk + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2464][sq-2464] : Fixer conflict between Generic.WhiteSpace.ScopeIndent and Squiz.WhiteSpace.ScopeClosingBrace when class indented 1 space +- Fixed bug [#2465][sq-2465] : Excluding a sniff by path is not working +- Fixed bug [#2467][sq-2467] : PHP open/close tags inside CSS files are replaced with internal PHPCS token strings when auto fixing + +[sq-2368]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2368 +[sq-2414]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2414 +[sq-2423]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2423 +[sq-2450]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2450 +[sq-2452]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2452 +[sq-2453]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2453 +[sq-2464]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2464 +[sq-2465]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2465 +[sq-2467]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2467 + +## [3.4.1] - 2019-03-19 + +### Changed +- The PEAR installable version of PHPCS was missing some files, which have been re-included in this release + - The code report was not previously available for PEAR installs + - The Generic.Formatting.SpaceBeforeCast sniff was not previously available for PEAR installs + - The Generic.WhiteSpace.LanguageConstructSpacing sniff was not previously available for PEAR installs + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PHPCS will now refuse to run if any of the required PHP extensions are not loaded + - Previously, PHPCS only relied on requirements being checked by PEAR and Composer + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Ruleset XML parsing errors are now displayed in a readable format so they are easier to correct + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The PSR2 standard no longer throws duplicate errors for spacing around FOR loop parentheses + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- T_PHPCS_SET tokens now contain sniffCode, sniffProperty, and sniffPropertyValue indexes + - Sniffs can use this information instead of having to parse the token content manually +- Added more guard code for syntax errors to various CSS sniffs + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Commenting.DocComment error messages now contain the name of the comment tag that caused the error + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.ControlStructures.InlineControlStructure now handles syntax errors correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Debug.JSHint now longer requires rhino and can be run directly from the npm install + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Files.LineEndings no longer adds superfluous new line at the end of JS and CSS files + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Formatting.DisallowMultipleStatements no longer tries to fix lines containing phpcs:ignore statements + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Functions.FunctionCallArgumentSpacing now has improved performance and anonymous class support + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.WhiteSpace.ScopeIndent now respects changes to the "exact" property using phpcs:set mid-way through a file + - This allows you to change the "exact" rule for only some parts of a file +- Generic.WhiteSpace.ScopeIndent now disables exact indent checking inside all arrays + - Previously, this was only done when using long array syntax, but it now works for short array syntax as well +- PEAR.Classes.ClassDeclaration now has improved handling of PHPCS annotations and tab indents +- PSR12.Classes.ClassInstantiation has changed its error code from MissingParenthesis to MissingParentheses +- PSR12.Keywords.ShortFormTypeKeywords now ignores all spacing inside type casts during both checking and fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Classes.LowercaseClassKeywords now examines the class keyword for anonymous classes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.ControlStructures.ControlSignature now has improved handling of parse errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.PostStatementComment fixer no longer adds a blank line at the start of a JS file that begins with a comment + - Fixes a conflict between this sniff and the Squiz.WhiteSpace.SuperfluousWhitespace sniff + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.PostStatementComment now ignores comments inside control structure conditions, such as FOR loops + - Fixes a conflict between this sniff and the Squiz.ControlStructures.ForLoopDeclaration sniff + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.FunctionCommentThrowTag now has improved support for unknown exception types and namespaces + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.ControlStructures.ForLoopDeclaration has improved whitespace, closure, and empty expression support + - The SpacingAfterSecondNoThird error code has been removed as part of these fixes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.CSS.ClassDefinitionOpeningBraceSpace now handles comments and indentation correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.CSS.ClassDefinitionClosingBrace now handles comments, indentation, and multiple statements on the same line correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.CSS.Opacity now handles comments correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.CSS.SemicolonSpacing now handles comments and syntax errors correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.NamingConventions.ValidVariableName now supports variables inside anonymous classes correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.LowercasePHPFunctions now handles use statements, namespaces, and comments correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.FunctionSpacing now fixes function spacing correctly when a function is the first content in a file + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.SuperfluousWhitespace no longer throws errors for spacing between functions and properties in anon classes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Zend.Files.ClosingTag no longer adds a semicolon during fixing of a file that only contains a comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Zend.NamingConventions.ValidVariableName now supports variables inside anonymous classes correctly + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed bug [#2298][sq-2298] : PSR2.Classes.ClassDeclaration allows extended class on new line + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#2337][sq-2337] : Generic.WhiteSpace.ScopeIndent incorrect error when multi-line function call starts on same line as open tag +- Fixed bug [#2348][sq-2348] : Cache not invalidated when changing a ruleset included by another +- Fixed bug [#2376][sq-2376] : Using __halt_compiler() breaks Generic.PHP.ForbiddenFunctions unless it's last in the function list + - Thanks to [Sijun Zhu][@Billz95] for the patch +- Fixed bug [#2393][sq-2393] : The gitmodified filter will infinitely loop when encountering deleted file paths + - Thanks to [Lucas Manzke][@lmanzke] for the patch +- Fixed bug [#2396][sq-2396] : Generic.WhiteSpace.ScopeIndent incorrect error when multi-line IF condition mixed with HTML +- Fixed bug [#2431][sq-2431] : Use function/const not tokenized as T_STRING when preceded by comment + +[sq-2298]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2298 +[sq-2337]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2337 +[sq-2348]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2348 +[sq-2376]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2376 +[sq-2393]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2393 +[sq-2396]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2396 +[sq-2431]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2431 + +## [3.4.0] - 2018-12-20 + +### Deprecated +- The Generic.Formatting.NoSpaceAfterCast sniff has been deprecated and will be removed in version 4 + - The functionality of this sniff is now available in the Generic.Formatting.SpaceAfterCast sniff + - Include the Generic.Formatting.SpaceAfterCast sniff and set the "spacing" property to "0" + - As soon as possible, replace all instances of the old sniff code with the new sniff code and property setting + - The existing sniff will continue to work until version 4 has been released + +### Changed +- Rule include patterns in a ruleset.xml file are now evaluated as OR instead of AND + - Previously, a file had to match every include pattern and no exclude patterns to be included + - Now, a file must match at least one include pattern and no exclude patterns to be included + - This is a bug fix as include patterns are already documented to work this way +- New token T_BITWISE_NOT added for the bitwise not operator + - This token was previously tokenized as T_NONE + - Any sniffs specifically looking for T_NONE tokens with a tilde as the contents must now also look for T_BITWISE_NOT + - Sniffs can continue looking for T_NONE as well as T_BITWISE_NOT to support older PHP_CodeSniffer versions +- All types of binary casting are now tokenized as T_BINARY_CAST + - Previously, the 'b' in 'b"some string with $var"' would be a T_BINARY_CAST, but only when the string contained a var + - This change ensures the 'b' is always tokenized as T_BINARY_CAST + - This change also converts '(binary)' from T_STRING_CAST to T_BINARY_CAST + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the help with this patch +- Array properties set inside a ruleset.xml file can now extend a previous value instead of always overwriting it + - e.g., if you include a ruleset that defines forbidden functions, can you now add to that list instead of having to redefine it + - To use this feature, add extends="true" to the property tag + - e.g., property name="forbiddenFunctionNames" type="array" extend="true" + - Thanks to [Michael Moravec][@Majkl578] for the patch +- If $XDG_CACHE_HOME is set and points to a valid directory, it will be used for caching instead of the system temp directory +- PHPCBF now disables parallel running if you are passing content on STDIN + - Stops an error from being shown after the fixed output is printed +- The progress report now shows files with tokenizer errors as skipped (S) instead of a warning (W) + - The tokenizer error is still displayed in reports as normal + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The Squiz standard now ensures there is no space between an increment/decrement operator and its variable +- The File::getMethodProperties() method now includes a has_body array index in the return value + - FALSE if the method has no body (as with abstract and interface methods) or TRUE otherwise + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- The File::getTokensAsString() method now throws an exception if the $start param is invalid + - If the $length param is invalid, an empty string will be returned + - Stops an infinite loop when the function is passed invalid data + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added new Generic.CodeAnalysis.EmptyPHPStatement sniff + - Warns when it finds empty PHP open/close tag combinations or superfluous semicolons + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added new Generic.Formatting.SpaceBeforeCast sniff + - Ensures there is exactly 1 space before a type cast, unless the cast statement is indented or multi-line + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added new Generic.VersionControl.GitMergeConflict sniff + - Detects merge conflict artifacts left in files + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added Generic.WhiteSpace.IncrementDecrementSpacing sniff + - Ensures there is no space between the operator and the variable it applies to + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added PSR12.Functions.NullableTypeDeclaration sniff + - Ensures there is no space after the question mark in a nullable type declaration + - Thanks to [Timo Schinkel][@timoschinkel] for the contribution +- A number of sniffs have improved support for methods in anonymous classes + - These sniffs would often throw the same error twice for functions in nested classes + - Error messages have also been changed to be less confusing + - The full list of affected sniffs is: + - Generic.NamingConventions.CamelCapsFunctionName + - PEAR.NamingConventions.ValidFunctionName + - PSR1.Methods.CamelCapsMethodName + - PSR2.Methods.MethodDeclaration + - Squiz.Scope.MethodScope + - Squiz.Scope.StaticThisUsage + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.CodeAnalysis.UnusedFunctionParameter now only skips functions with empty bodies when the class implements an interface + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.CodeAnalysis.UnusedFunctionParameter now has additional error codes to indicate where unused params were found + - The new error code prefixes are: + - FoundInExtendedClass: when the class extends another + - FoundInImplementedInterface: when the class implements an interface + - Found: used in all other cases, including closures + - The new error code suffixes are: + - BeforeLastUsed: the unused param was positioned before the last used param in the function signature + - AfterLastUsed: the unused param was positioned after the last used param in the function signature + - This makes the new error code list for this sniff: + - Found + - FoundBeforeLastUsed + - FoundAfterLastUsed + - FoundInExtendedClass + - FoundInExtendedClassBeforeLastUsed + - FoundInExtendedClassAfterLastUsed + - FoundInImplementedInterface + - FoundInImplementedInterfaceBeforeLastUsed + - FoundInImplementedInterfaceAfterLastUsed + - These errors code make it easier for specific cases to be ignored or promoted using a ruleset.xml file + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Generic.Classes.DuplicateClassName now inspects traits for duplicate names as well as classes and interfaces + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Generic.Files.InlineHTML now ignores a BOM at the start of the file + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Generic.PHP.CharacterBeforePHPOpeningTag now ignores a BOM at the start of the file + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Generic.Formatting.SpaceAfterCast now has a setting to specify how many spaces are required after a type cast + - Default remains 1 + - Override the "spacing" setting in a ruleset.xml file to change + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Formatting.SpaceAfterCast now has a setting to ignore newline characters after a type cast + - Default remains FALSE, so newlines are not allowed + - Override the "ignoreNewlines" setting in a ruleset.xml file to change + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Formatting.SpaceAfterNot now has a setting to specify how many spaces are required after a NOT operator + - Default remains 1 + - Override the "spacing" setting in a ruleset.xml file to change + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Formatting.SpaceAfterNot now has a setting to ignore newline characters after the NOT operator + - Default remains FALSE, so newlines are not allowed + - Override the "ignoreNewlines" setting in a ruleset.xml file to change + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.Functions.FunctionDeclaration now checks spacing before the opening parenthesis of functions with no body + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- PEAR.Functions.FunctionDeclaration now enforces no space before the semicolon in functions with no body + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- PSR2.Classes.PropertyDeclaration now checks the order of property modifier keywords + - This is a rule that is documented in PSR-2 but was not enforced by the included PSR2 standard until now + - This sniff is also able to fix the order of the modifier keywords if they are incorrect + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PSR2.Methods.MethodDeclaration now checks method declarations inside traits + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Squiz.Commenting.InlineComment now has better detection of comment block boundaries +- Squiz.Classes.ClassFileName now checks that a trait name matches the filename + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Squiz.Classes.SelfMemberReference now supports scoped declarations and anonymous classes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Classes.SelfMemberReference now fixes multiple errors at once, increasing fixer performance + - Thanks to [Gabriel Ostrolucký][@ostrolucky] for the patch +- Squiz.Functions.LowercaseFunctionKeywords now checks abstract and final prefixes, and auto-fixes errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Objects.ObjectMemberComma.Missing has been renamed to Squiz.Objects.ObjectMemberComma.Found + - The error is thrown when the comma is found but not required, so the error code was incorrect + - If you are referencing the old error code in a ruleset XML file, please use the new code instead + - If you wish to maintain backwards compatibility, you can provide rules for both the old and new codes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.ObjectOperatorSpacing is now more tolerant of parse errors +- Squiz.WhiteSpace.ObjectOperatorSpacing now fixes errors more efficiently + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed bug [#2109][sq-2109] : Generic.Functions.CallTimePassByReference false positive for bitwise and used in function argument +- Fixed bug [#2165][sq-2165] : Conflict between Squiz.Arrays.ArrayDeclaration and ScopeIndent sniffs when heredoc used in array +- Fixed bug [#2167][sq-2167] : Generic.WhiteSpace.ScopeIndent shows invalid error when scope opener indented inside inline HTML +- Fixed bug [#2178][sq-2178] : Generic.NamingConventions.ConstructorName matches methods in anon classes with same name as containing class + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2190][sq-2190] : PEAR.Functions.FunctionCallSignature incorrect error when encountering trailing PHPCS annotation + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2194][sq-2194] : Generic.Whitespace.LanguageConstructSpacing should not be checking namespace operators + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2202][sq-2202] : Squiz.WhiteSpace.OperatorSpacing throws error for negative index when using curly braces for string access + - Same issue fixed in Squiz.Formatting.OperatorBracket + - Thanks to [Andreas Buchenrieder][@anbuc] for the patch +- Fixed bug [#2210][sq-2210] : Generic.NamingConventions.CamelCapsFunctionName not ignoring SoapClient __getCookies() method + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2211][sq-2211] : PSR2.Methods.MethodDeclaration gets confused over comments between modifier keywords + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2212][sq-2212] : FUNCTION and CONST in use groups being tokenized as T_FUNCTION and T_CONST + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Fixed bug [#2214][sq-2214] : File::getMemberProperties() is recognizing method params as properties + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2236][sq-2236] : Memory info measurement unit is Mb but probably should be MB +- Fixed bug [#2246][sq-2246] : CSS tokenizer does not tokenize class names correctly when they contain the string NEW + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2278][sq-2278] : Squiz.Operators.ComparisonOperatorUsage false positive when inline IF contained in parentheses + - Thanks to [Arnout Boks][@aboks] for the patch +- Fixed bug [#2284][sq-2284] : Squiz.Functions.FunctionDeclarationArgumentSpacing removing type hint during fixing + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#2297][sq-2297] : Anonymous class not tokenized correctly when used as argument to another anon class + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch + +[sq-2109]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2109 +[sq-2165]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2165 +[sq-2167]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2167 +[sq-2178]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2178 +[sq-2190]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2190 +[sq-2194]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2194 +[sq-2202]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2202 +[sq-2210]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2210 +[sq-2211]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2211 +[sq-2212]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2212 +[sq-2214]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2214 +[sq-2236]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2236 +[sq-2246]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2246 +[sq-2278]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2278 +[sq-2284]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2284 +[sq-2297]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2297 + +## [2.9.2] - 2018-11-08 + +### Changed +- PHPCS should now run under PHP 7.3 without deprecation warnings + - Thanks to [Nick Wilde][@NickDickinsonWilde] for the patch + +### Fixed +- Fixed bug [#1496][sq-1496] : Squiz.Strings.DoubleQuoteUsage not unescaping dollar sign when fixing + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#1549][sq-1549] : Squiz.PHP.EmbeddedPhp fixer conflict with // comment before PHP close tag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1890][sq-1890] : Incorrect Squiz.WhiteSpace.ControlStructureSpacing.NoLineAfterClose error between catch and finally statements + +## [3.3.2] - 2018-09-24 + +### Changed +- Fixed a problem where the report cache was not being cleared when the sniffs inside a standard were updated +- The info report (--report=info) now has improved formatting for metrics that span multiple lines + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The unit test runner now skips .bak files when looking for test cases + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The Squiz standard now ensures underscores are not used to indicate visibility of private members vars and methods + - Previously, this standard enforced the use of underscores +- Generic.PHP.NoSilencedErrors error messages now contain a code snippet to show the context of the error + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Arrays.ArrayDeclaration no longer reports errors for a comma on a line new after a here/nowdoc + - Also stops a parse error being generated when auto-fixing + - The SpaceBeforeComma error message has been changed to only have one data value instead of two +- Squiz.Commenting.FunctionComment no longer errors when trying to fix indents of multi-line param comments +- Squiz.Formatting.OperatorBracket now correctly fixes statements that contain strings +- Squiz.PHP.CommentedOutCode now ignores more @-style annotations and includes better comment block detection + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed a problem where referencing a relative file path in a ruleset XML file could add unnecessary sniff exclusions + - This didn't actually exclude anything, but caused verbose output to list strange exclusion rules +- Fixed bug [#2110][sq-2110] : Squiz.WhiteSpace.FunctionSpacing is removing indents from the start of functions when fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2115][sq-2115] : Squiz.Commenting.VariableComment not checking var types when the @var line contains a comment +- Fixed bug [#2120][sq-2120] : Tokenizer fails to match T_INLINE_ELSE when used after function call containing closure +- Fixed bug [#2121][sq-2121] : Squiz.PHP.DisallowMultipleAssignments false positive in while loop conditions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2127][sq-2127] : File::findExtendedClassName() doesn't support nested classes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2138][sq-2138] : Tokenizer detects wrong token for PHP ::class feature with spaces +- Fixed bug [#2143][sq-2143] : PSR2.Namespaces.UseDeclaration does not properly fix "use function" and "use const" statements + - Thanks to [Chris Wilkinson][@thewilkybarkid] for the patch +- Fixed bug [#2144][sq-2144] : Squiz.Arrays.ArrayDeclaration does incorrect align calculation in array with cyrillic keys +- Fixed bug [#2146][sq-2146] : Zend.Files.ClosingTag removes closing tag from end of file without inserting a semicolon +- Fixed bug [#2151][sq-2151] : XML schema not updated with the new array property syntax + +[sq-2110]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2110 +[sq-2115]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2115 +[sq-2120]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2120 +[sq-2121]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2121 +[sq-2127]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2127 +[sq-2138]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2138 +[sq-2143]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2143 +[sq-2144]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2144 +[sq-2146]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2146 +[sq-2151]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2151 + +## [3.3.1] - 2018-07-27 + +### Removed +- Support for HHVM has been dropped due to recent unfixed bugs and HHVM refocus on Hack only + - Thanks to [Walt Sorensen][@photodude] and [Juliette Reinders Folmer][@jrfnl] for helping to remove all HHVM exceptions from the core + +### Changed +- The full report (the default report) now has improved word wrapping for multi-line messages and sniff codes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The summary report now sorts files based on their directory location instead of just a basic string sort + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The source report now orders error codes by name when they have the same number of errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The junit report no longer generates validation errors with the Jenkins xUnit plugin + - Thanks to [Nikolay Geo][@nicholascus] for the patch +- Generic.Commenting.DocComment no longer generates the SpacingBeforeTags error if tags are the first content in the docblock + - The sniff will still generate a MissingShort error if there is no short comment + - This allows the MissingShort error to be suppressed in a ruleset to make short descriptions optional +- Generic.Functions.FunctionCallArgumentSpacing now properly fixes multi-line function calls with leading commas + - Previously, newlines between function arguments would be removed + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.Syntax will now use PHP_BINARY instead of trying to discover the executable path + - This ensures that the sniff will always syntax check files using the PHP version that PHPCS is running under + - Setting the `php_path` config var will still override this value as normal + - Thanks to [Willem Stuursma-Ruwen][@willemstuursma] for the patch +- PSR2.Namespaces.UseDeclaration now supports commas at the end of group use declarations + - Also improves checking and fixing for use statements containing parse errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Arrays.ArrayDeclaration no longer removes the array opening brace while fixing + - This could occur when the opening brace was on a new line and the first array key directly followed + - This change also stops the KeyNotAligned error message being incorrectly reported in these cases +- Squiz.Arrays.ArrayDeclaration no longer tries to change multi-line arrays to single line when they contain comments + - Fixes a conflict between this sniff and some indentation sniffs +- Squiz.Classes.ClassDeclaration no longer enforces spacing rules when a class is followed by a function + - Fixes a conflict between this sniff and the Squiz.WhiteSpace.FunctionSpacing sniff +- The Squiz.Classes.ValidClassName.NotCamelCaps message now references PascalCase instead of CamelCase + - The "CamelCase class name" metric produced by the sniff has been changed to "PascalCase class name" + - This reflects the fact that the class name check is actually a Pascal Case check and not really Camel Case + - Thanks to [Tom H Anderson][@TomHAnderson] for the patch +- Squiz.Commenting.InlineComment no longer enforces spacing rules when an inline comment is followed by a docblock + - Fixes a conflict between this sniff and the Squiz.WhiteSpace.FunctionSpacing sniff +- Squiz.WhiteSpace.OperatorSpacing no longer tries to fix operator spacing if the next content is a comment on a new line + - Fixes a conflict between this sniff and the Squiz.Commenting.PostStatementComment sniff + - Also stops PHPCS annotations from being moved to a different line, potentially changing their meaning + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.FunctionSpacing no longer checks spacing of functions at the top of an embedded PHP block + - Fixes a conflict between this sniff and the Squiz.PHP.EmbeddedPHP sniff + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.MemberVarSpacing no longer checks spacing before member vars that come directly after methods + - Fixes a conflict between this sniff and the Squiz.WhiteSpace.FunctionSpacing sniff +- Squiz.WhiteSpace.SuperfluousWhitespace now recognizes unicode whitespace at the start and end of a file + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed bug [#2029][sq-2029] : Squiz.Scope.MemberVarScope throws fatal error when a property is found in an interface + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2047][sq-2047] : PSR12.Classes.ClassInstantiation false positive when instantiating class from array index +- Fixed bug [#2048][sq-2048] : GenericFormatting.MultipleStatementAlignment false positive when assigning values inside an array +- Fixed bug [#2053][sq-2053] : PSR12.Classes.ClassInstantiation incorrectly fix when using member vars and some variable formats +- Fixed bug [#2065][sq-2065] : Generic.ControlStructures.InlineControlStructure fixing fails when inline control structure contains closure +- Fixed bug [#2072][sq-2072] : Squiz.Arrays.ArrayDeclaration throws NoComma error when array value is a shorthand IF statement +- Fixed bug [#2082][sq-2082] : File with "defined() or define()" syntax triggers PSR1.Files.SideEffects.FoundWithSymbols +- Fixed bug [#2095][sq-2095] : PSR2.Namespaces.NamespaceDeclaration does not handle namespaces defined over multiple lines + +[sq-2029]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2029 +[sq-2047]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2047 +[sq-2048]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2048 +[sq-2053]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2053 +[sq-2065]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2065 +[sq-2072]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2072 +[sq-2082]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2082 +[sq-2095]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2095 + +## [3.3.0] - 2018-06-07 + +### Deprecated +- The Squiz.WhiteSpace.LanguageConstructSpacing sniff has been deprecated and will be removed in version 4 + - The sniff has been moved to the Generic standard, with a new code of Generic.WhiteSpace.LanguageConstructSpacing + - As soon as possible, replace all instances of the old sniff code with the new sniff code in your ruleset.xml files + - The existing Squiz sniff will continue to work until version 4 has been released + - The new Generic sniff now also checks many more language constructs to enforce additional spacing rules + - Thanks to [Mponos George][@gmponos] for the contribution +- The current method for setting array properties in ruleset files has been deprecated and will be removed in version 4 + - Currently, setting an array value uses the string syntax "print=>echo,create_function=>null" + - Now, individual array elements are specified using a new "element" tag with "key" and "value" attributes + - For example, element key="print" value="echo" + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- The T_ARRAY_HINT token has been deprecated and will be removed in version 4 + - The token was used to ensure array type hints were not tokenized as T_ARRAY, but no other type hints were given a special token + - Array type hints now use the standard T_STRING token instead + - Sniffs referencing this token type will continue to run without error until version 4, but will not find any T_ARRAY_HINT tokens +- The T_RETURN_TYPE token has been deprecated and will be removed in version 4 + - The token was used to ensure array/self/parent/callable return types were tokenized consistently + - For namespaced return types, only the last part of the string (the class name) was tokenized as T_RETURN_TYPE + - This was not consistent and so return types are now left using their original token types so they are not skipped by sniffs + - The exception are array return types, which are tokenized as T_STRING instead of T_ARRAY, as they are for type hints + - Sniffs referencing this token type will continue to run without error until version 4, but will not find any T_RETUTN_TYPE tokens + - To get the return type of a function, use the File::getMethodProperties() method, which now contains a "return_type" array index + - This contains the return type of the function or closer, or a blank string if not specified + - If the return type is nullable, the return type will contain the leading ? + - A nullable_return_type array index in the return value will also be set to true + - If the return type contains namespace information, it will be cleaned of whitespace and comments + - To access the original return value string, use the main tokens array + +### Added +- This release contains an incomplete version of the PSR-12 coding standard + - Errors found using this standard should be valid, but it will miss a lot of violations until it is complete + - If you'd like to test and help, you can use the standard by running PHPCS with --standard=PSR12 + +### Changed +- Config values set using --runtime-set now override any config values set in rulesets or the CodeSniffer.conf file +- You can now apply include-pattern rules to individual message codes in a ruleset like you can with exclude-pattern rules + - Previously, include-pattern rules only applied to entire sniffs + - If a message code has both include and exclude patterns, the exclude patterns will be ignored +- Using PHPCS annotations to selectively re-enable sniffs is now more flexible + - Previously, you could only re-enable a sniff/category/standard using the exact same code that was disabled + - Now, you can disable a standard and only re-enable a specific category or sniff + - Or, you can disable a specific sniff and have it re-enable when you re-enable the category or standard +- The value of array sniff properties can now be set using phpcs:set annotations + - e.g., phpcs:set Standard.Category.SniffName property[] key=>value,key2=>value2 + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- PHPCS annotations now remain as T_PHPCS_* tokens instead of reverting to comment tokens when --ignore-annotations is used + - This stops sniffs (especially commenting sniffs) from generating a large number of false errors when ignoring + - Any custom sniffs that are using the T_PHPCS_* tokens to detect annotations may need to be changed to ignore them + - Check $phpcsFile->config->annotations to see if annotations are enabled and ignore when false +- You can now use fully or partially qualified class names for custom reports instead of absolute file paths + - To support this, you must specify an autoload file in your ruleset.xml file and use it to register an autoloader + - Your autoloader will need to load your custom report class when requested + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The JSON report format now does escaping in error source codes as well as error messages + - Thanks to [Martin Vasel][@marvasDE] for the patch +- Invalid installed_paths values are now ignored instead of causing a fatal error +- Improved testability of custom rulesets by allowing the installed standards to be overridden + - Thanks to [Timo Schinkel][@timoschinkel] for the patch +- The key used for caching PHPCS runs now includes all set config values + - This fixes a problem where changing config values (e.g., via --runtime-set) used an incorrect cache file +- The "Function opening brace placement" metric has been separated into function and closure metrics in the info report + - Closures are no longer included in the "Function opening brace placement" metric + - A new "Closure opening brace placement" metric now shows information for closures +- Multi-line T_YIELD_FROM statements are now replicated properly for older PHP versions +- The PSR2 standard no longer produces 2 error messages when the AS keyword in a foreach loop is not lowercase +- Specifying a path to a non-existent dir when using the `--report-[reportType]=/path/to/report` CLI option no longer throws an exception + - This now prints a readable error message, as it does when using `--report-file` +- The File::getMethodParamaters() method now includes a type_hint_token array index in the return value + - Provides the position in the token stack of the first token in the type hint +- The File::getMethodProperties() method now includes a return_type_token array index in the return value + - Provides the position in the token stack of the first token in the return type +- The File::getTokensAsString() method can now optionally return original (non tab-replaced) content + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Removed Squiz.PHP.DisallowObEndFlush from the Squiz standard + - If you use this sniff and want to continue banning ob_end_flush(), use Generic.PHP.ForbiddenFunctions instead + - You will need to set the forbiddenFunctions property in your ruleset.xml file +- Removed Squiz.PHP.ForbiddenFunctions from the Squiz standard + - Replaced by using the forbiddenFunctions property of Generic.PHP.ForbiddenFunctions in the Squiz ruleset.xml + - Functionality of the Squiz standard remains the same, but the error codes are now different + - Previously, Squiz.PHP.ForbiddenFunctions.Found and Squiz.PHP.ForbiddenFunctions.FoundWithAlternative + - Now, Generic.PHP.ForbiddenFunctions.Found and Generic.PHP.ForbiddenFunctions.FoundWithAlternative +- Added new Generic.PHP.LowerCaseType sniff + - Ensures PHP types used for type hints, return types, and type casting are lowercase + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added new Generic.WhiteSpace.ArbitraryParenthesesSpacing sniff + - Generates an error for whitespace inside parenthesis that don't belong to a function call/declaration or control structure + - Generates a warning for any empty parenthesis found + - Allows the required spacing to be set using the spacing sniff property (default is 0) + - Allows newlines to be used by setting the ignoreNewlines sniff property (default is false) + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added new PSR12.Classes.ClassInstantiation sniff + - Ensures parenthesis are used when instantiating a new class +- Added new PSR12.Keywords.ShortFormTypeKeywords sniff + - Ensures the short form of PHP types is used when type casting +- Added new PSR12.Namespaces.CompundNamespaceDepth sniff + - Ensures compound namespace use statements have a max depth of 2 levels + - The max depth can be changed by setting the 'maxDepth' sniff property in a ruleset.xml file +- Added new PSR12.Operators.OperatorSpacing sniff + - Ensures operators are preceded and followed by at least 1 space +- Improved core support for grouped property declarations + - Also improves support in Squiz.WhiteSpace.ScopeKeywordSpacing and Squiz.WhiteSpace.MemberVarSpacing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Commenting.DocComment now produces a NonParamGroup error when tags are mixed in with the @param tag group + - It would previously throw either a NonParamGroup or ParamGroup error depending on the order of tags + - This change allows the NonParamGroup error to be suppressed in a ruleset to allow the @param group to contain other tags + - Thanks to [Phil Davis][@phil-davis] for the patch +- Generic.Commenting.DocComment now continues checks param tags even if the doc comment short description is missing + - This change allows the MissingShort error to be suppressed in a ruleset without all other errors being suppressed as well + - Thanks to [Phil Davis][@phil-davis] for the patch +- Generic.CodeAnalysis.AssignmentInCondition now reports a different error code for assignments found in WHILE conditions + - The return value of a function call is often assigned in a WHILE condition, so this change makes it easier to exclude these cases + - The new code for this error message is Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition + - The error code for all other cases remains as Generic.CodeAnalysis.AssignmentInCondition.Found + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Functions.OpeningFunctionBraceBsdAllman now longer leaves trailing whitespace when moving the opening brace during fixing + - Also applies to fixes made by PEAR.Functions.FunctionDeclaration and Squiz.Functions.MultiLineFunctionDeclaration +- Generic.WhiteSpace.ScopeIndent now does a better job of fixing the indent of multi-line comments +- Generic.WhiteSpace.ScopeIndent now does a better job of fixing the indent of PHP open and close tags +- PEAR.Commenting.FunctionComment now report a different error code for param comment lines with too much padding + - Previously, any lines of a param comment that don't start at the exact comment position got the same error code + - Now, only comment lines with too little padding use ParamCommentAlignment as they are clearly mistakes + - Comment lines with too much padding may be using precision alignment as now use ParamCommentAlignmentExceeded + - This allows for excessive padding to be excluded from a ruleset while continuing to enforce a minimum padding +- PEAR.WhiteSpace.ObjectOperatorIndent now checks the indent of more chained operators + - Previously, it only checked chains beginning with a variable + - Now, it checks chains beginning with function calls, static class names, etc +- Squiz.Arrays.ArrayDeclaration now continues checking array formatting even if the key indent is not correct + - Allows for using different array indent rules while still checking/fixing double arrow and value alignment +- Squiz.Commenting.BlockComment has improved support for tab-indented comments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.BlockComment auto fixing no longer breaks when two block comments follow each other + - Also stopped single-line block comments from being auto fixed when they are embedded in other code + - Also fixed as issue found when PHPCS annotations were used inside a block comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.BlockComment.LastLineIndent is now able to be fixed with phpcbf + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.BlockComment now aligns star-prefixed lines under the opening tag while fixing, instead of indenting them + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.FunctionComment.IncorrectTypeHint message no longer contains cut-off suggested type hints +- Squiz.Commenting.InlineComment now uses a new error code for inline comments at the end of a function + - Previously, all inline comments followed by a blank line threw a Squiz.Commenting.InlineComment.SpacingAfter error + - Now, inline comments at the end of a function will instead throw Squiz.Commenting.InlineComment.SpacingAfterAtFunctionEnd + - If you previously excluded SpacingAfter, add an exclusion for SpacingAfterAtFunctionEnd to your ruleset as well + - If you previously only included SpacingAfter, consider including SpacingAfterAtFunctionEnd as well + - The Squiz standard now excludes SpacingAfterAtFunctionEnd as the blank line is checked elsewhere + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.ControlStructures.ControlSignature now errors when a comment follows the closing brace of an earlier body + - Applies to catch, finally, else, elseif, and do/while structures + - The included PSR2 standard now enforces this rule + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Formatting.OperatorBracket.MissingBrackets message has been changed to remove the word "arithmetic" + - The sniff checks more than just arithmetic operators, so the message is now clearer +- Sniffs.Operators.ComparisonOperatorUsage now detects more cases of implicit true comparisons + - It could previously be confused by comparisons used as function arguments +- Squiz.PHP.CommentedOutCode now ignores simple @-style annotation comments so they are not flagged as commented out code + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.CommentedOutCode now ignores a greater number of short comments so they are not flagged as commented out code + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.DisallowComparisonAssignment no longer errors when using the null coalescing operator + - Given this operator is used almost exclusively to assign values, it didn't make sense to generate an error +- Squiz.WhiteSpacing.FunctionSpacing now has a property to specify how many blank lines should be before the first class method + - Only applies when a method is the first code block in a class (i.e., there are no member vars before it) + - Override the 'spacingBeforeFirst' property in a ruleset.xml file to change + - If not set, the sniff will use whatever value is set for the existing 'spacing' property +- Squiz.WhiteSpacing.FunctionSpacing now has a property to specify how many blank lines should be after the last class method + - Only applies when a method is the last code block in a class (i.e., there are no member vars after it) + - Override the 'spacingAfterLast' property in a ruleset.xml file to change + - If not set, the sniff will use whatever value is set for the existing 'spacing' property + +### Fixed +- Fixed bug [#1863][sq-1863] : File::findEndOfStatement() not working when passed a scope opener +- Fixed bug [#1876][sq-1876] : PSR2.Namespaces.UseDeclaration not giving error for use statements before the namespace declaration + - Adds a new PSR2.Namespaces.UseDeclaration.UseBeforeNamespace error message +- Fixed bug [#1881][sq-1881] : Generic.Arrays.ArrayIndent is indenting sub-arrays incorrectly when comma not used after the last value +- Fixed bug [#1882][sq-1882] : Conditional with missing braces confused by indirect variables +- Fixed bug [#1915][sq-1915] : JS tokenizer fails to tokenize regular expression proceeded by boolean not operator +- Fixed bug [#1920][sq-1920] : Directory exclude pattern improperly excludes files with names that start the same + - Thanks to [Jeff Puckett][@jpuck] for the patch +- Fixed bug [#1922][sq-1922] : Equal sign alignment check broken when list syntax used before assignment operator +- Fixed bug [#1925][sq-1925] : Generic.Formatting.MultipleStatementAlignment skipping assignments within closures +- Fixed bug [#1931][sq-1931] : Generic opening brace placement sniffs do not correctly support function return types +- Fixed bug [#1932][sq-1932] : Generic.ControlStructures.InlineControlStructure fixer moves new PHPCS annotations +- Fixed bug [#1938][sq-1938] : Generic opening brace placement sniffs incorrectly move PHPCS annotations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1939][sq-1939] : phpcs:set annotations do not cause the line they are on to be ignored + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1949][sq-1949] : Squiz.PHP.DisallowMultipleAssignments false positive when using namespaces with static assignments +- Fixed bug [#1959][sq-1959] : SquizMultiLineFunctionDeclaration error when param has trailing comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1963][sq-1963] : Squiz.Scope.MemberVarScope does not work for multiline member declaration + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1971][sq-1971] : Short array list syntax not correctly tokenized if short array is the first content in a file +- Fixed bug [#1979][sq-1979] : Tokenizer does not change heredoc to nowdoc token if the start tag contains spaces +- Fixed bug [#1982][sq-1982] : Squiz.Arrays.ArrayDeclaration fixer sometimes puts a comma in front of the last array value +- Fixed bug [#1993][sq-1993] : PSR1/PSR2 not reporting or fixing short open tags +- Fixed bug [#1996][sq-1996] : Custom report paths don't work on case-sensitive filesystems +- Fixed bug [#2006][sq-2006] : Squiz.Functions.FunctionDeclarationArgumentSpacing fixer removes comment between parens when no args + - The SpacingAfterOpenHint error message has been removed + - It is replaced by the existing SpacingAfterOpen message + - The error message format for the SpacingAfterOpen and SpacingBeforeClose messages has been changed + - These used to contain 3 pieces of data, but now only contain 2 + - If you have customised the error messages of this sniff, please review your ruleset after upgrading +- Fixed bug [#2018][sq-2018] : Generic.Formatting.MultipleStatementAlignment does see PHP close tag as end of statement block + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#2027][sq-2027] : PEAR.NamingConventions.ValidFunctionName error when function name includes double underscore + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-1863]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1863 +[sq-1876]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1876 +[sq-1881]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1881 +[sq-1882]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1882 +[sq-1915]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1915 +[sq-1920]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1920 +[sq-1922]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1922 +[sq-1925]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1925 +[sq-1931]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1931 +[sq-1932]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1932 +[sq-1938]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1938 +[sq-1939]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1939 +[sq-1949]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1949 +[sq-1959]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1959 +[sq-1963]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1963 +[sq-1971]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1971 +[sq-1979]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1979 +[sq-1982]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1982 +[sq-1993]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1993 +[sq-1996]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1996 +[sq-2006]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2006 +[sq-2018]: https://github.com/squizlabs/PHP_CodeSniffer/pull/2018 +[sq-2027]: https://github.com/squizlabs/PHP_CodeSniffer/issues/2027 + +## [3.2.3] - 2018-02-21 + +### Changed +- The new phpcs: comment syntax can now be prefixed with an at symbol ( @phpcs: ) + - This restores the behaviour of the previous syntax where these comments are ignored by doc generators +- The current PHP version ID is now used to generate cache files + - This ensures that only cache files generated by the current PHP version are selected + - This change fixes caching issues when using sniffs that produce errors based on the current PHP version +- A new Tokens::$phpcsCommentTokens array is now available for sniff developers to detect phpcs: comment syntax + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The PEAR.Commenting.FunctionComment.Missing error message now includes the name of the function + - Thanks to [Yorman Arias][@cixtor] for the patch +- The PEAR.Commenting.ClassComment.Missing and Squiz.Commenting.ClassComment.Missing error messages now include the name of the class + - Thanks to [Yorman Arias][@cixtor] for the patch +- PEAR.Functions.FunctionCallSignature now only forces alignment at a specific tab stop while fixing + - It was enforcing this during checking, but this meant invalid errors if the OpeningIndent message was being muted + - This fixes incorrect errors when using the PSR2 standard with some code blocks +- Generic.Files.LineLength now ignores lines that only contain phpcs: annotation comments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Formatting.MultipleStatementAlignment now skips over arrays containing comments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.Syntax now forces display_errors to ON when linting + - Thanks to [Raúl Arellano][@raul338] for the patch +- PSR2.Namespaces.UseDeclaration has improved syntax error handling and closure detection + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.CommentedOutCode now has improved comment block detection for improved accuracy + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.NonExecutableCode could fatal error while fixing file with syntax error +- Squiz.PHP.NonExecutableCode now detects unreachable code after a goto statement + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.LanguageConstructSpacing has improved syntax error handling while fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Improved phpcs: annotation syntax handling for a number of sniffs + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Improved auto-fixing of files with incomplete comment blocks for various commenting sniffs + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed test suite compatibility with PHPUnit 7 +- Fixed bug [#1793][sq-1793] : PSR2 forcing exact indent for function call opening statements +- Fixed bug [#1803][sq-1803] : Squiz.WhiteSpace.ScopeKeywordSpacing removes member var name while fixing if no space after scope keyword +- Fixed bug [#1817][sq-1817] : Blank line not enforced after control structure if comment on same line as closing brace +- Fixed bug [#1827][sq-1827] : A phpcs:enable comment is not tokenized correctly if it is outside a phpcs:disable block + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1828][sq-1828] : Squiz.WhiteSpace.SuperfluousWhiteSpace ignoreBlankLines property ignores whitespace after single line comments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1840][sq-1840] : When a comment has too many asterisks, phpcbf gives FAILED TO FIX error +- Fixed bug [#1867][sq-1867] : Can't use phpcs:ignore where the next line is HTML +- Fixed bug [#1870][sq-1870] : Invalid warning in multiple assignments alignment with closure or anon class +- Fixed bug [#1890][sq-1890] : Incorrect Squiz.WhiteSpace.ControlStructureSpacing.NoLineAfterClose error between catch and finally statements +- Fixed bug [#1891][sq-1891] : Comment on last USE statement causes false positive for PSR2.Namespaces.UseDeclaration.SpaceAfterLastUse + - Thanks to [Matt Coleman][@iammattcoleman], [Daniel Hensby][@dhensby], and [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1901][sq-1901] : Fixed PHPCS annotations in multi-line tab-indented comments + not ignoring whole line for phpcs:set + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-1793]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1793 +[sq-1803]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1803 +[sq-1817]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1817 +[sq-1827]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1827 +[sq-1828]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1828 +[sq-1840]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1840 +[sq-1867]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1867 +[sq-1870]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1870 +[sq-1890]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1890 +[sq-1891]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1891 +[sq-1901]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1901 + +## [3.2.2] - 2017-12-20 + +### Changed +- Disabled STDIN detection on Windows + - This fixes a problem with IDE plugins (e.g., PHPStorm) hanging on Windows + +## [3.2.1] - 2017-12-18 + +### Changed +- Empty diffs are no longer followed by a newline character (request [#1781][sq-1781]) +- Generic.Functions.OpeningFunctionBraceKernighanRitchie no longer complains when the open brace is followed by a close tag + - This makes the sniff more useful when used in templates + - Thanks to [Joseph Zidell][@josephzidell] for the patch + +### Fixed +- Fixed problems with some scripts and plugins waiting for STDIN + - This was a notable problem with IDE plugins (e.g., PHPStorm) and build systems +- Fixed bug [#1782][sq-1782] : Incorrect detection of operator in ternary + anonymous function + +[sq-1781]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1781 +[sq-1782]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1782 + +## [3.2.0] - 2017-12-13 + +### Deprecated +- This release deprecates the @codingStandards comment syntax used for sending commands to PHP_CodeSniffer + - The existing syntax will continue to work in all version 3 releases, but will be removed in version 4 + - The comment formats have been replaced by a shorter syntax: + - @codingStandardsIgnoreFile becomes phpcs:ignoreFile + - @codingStandardsIgnoreStart becomes phpcs:disable + - @codingStandardsIgnoreEnd becomes phpcs:enable + - @codingStandardsIgnoreLine becomes phpcs:ignore + - @codingStandardsChangeSetting becomes phpcs:set + - The new syntax allows for additional developer comments to be added after a -- separator + - This is useful for describing why a code block is being ignored, or why a setting is being changed + - E.g., phpcs:disable -- This code block must be left as-is. + - Comments using the new syntax are assigned new comment token types to allow them to be detected: + - phpcs:ignoreFile has the token T_PHPCS_IGNORE_FILE + - phpcs:disable has the token T_PHPCS_DISABLE + - phpcs:enable has the token T_PHPCS_ENABLE + - phpcs:ignore has the token T_PHPCS_IGNORE + - phpcs:set has the token T_PHPCS_SET + +### Changed +- The phpcs:disable and phpcs:ignore comments can now selectively ignore specific sniffs (request [#604][sq-604]) + - E.g., phpcs:disable Generic.Commenting.Todo.Found for a specific message + - E.g., phpcs:disable Generic.Commenting.Todo for a whole sniff + - E.g., phpcs:disable Generic.Commenting for a whole category of sniffs + - E.g., phpcs:disable Generic for a whole standard + - Multiple sniff codes can be specified by comma separating them + - E.g., phpcs:disable Generic.Commenting.Todo,PSR1.Files +- @codingStandardsIgnoreLine comments now only ignore the following line if they are on a line by themselves + - If they are at the end of an existing line, they will only ignore the line they are on + - Stops some lines from accidentally being ignored + - Same rule applies for the new phpcs:ignore comment syntax +- PSR1.Files.SideEffects now respects the new phpcs:disable comment syntax + - The sniff will no longer check any code that is between phpcs:disable and phpcs:enable comments + - The sniff does not support phpcs:ignore; you must wrap code structures with disable/enable comments + - Previously, there was no way to have this sniff ignore parts of a file +- Fixed a problem where PHPCS would sometimes hang waiting for STDIN, or read incomplete versions of large files + - Thanks to [Arne Jørgensen][@arnested] for the patch +- Array properties specified in ruleset files now have their keys and values trimmed + - This saves having to do this in individual sniffs and stops errors introduced by whitespace in rulesets + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added phpcs.xsd to allow validation of ruleset XML files + - Thanks to [Renaat De Muynck][@renaatdemuynck] for the contribution +- File paths specified using --stdin-path can now point to fake file locations (request [#1488][sq-1488]) + - Previously, STDIN files using fake file paths were excluded from checking +- Setting an empty basepath (--basepath=) on the CLI will now clear a basepath set directly in a ruleset + - Thanks to [Xaver Loppenstedt][@xalopp] for the patch +- Ignore patterns are now checked on symlink target paths instead of symlink source paths + - Restores previous behaviour of this feature +- Metrics were being double counted when multiple sniffs were recording the same metric +- Added support for bash process substitution + - Thanks to [Scott Dutton][@exussum12] for the contribution +- Files included in the cache file code hash are now sorted to aid in cache file reuse across servers +- Windows BAT files can now be used outside a PEAR install + - You must have the path to PHP set in your PATH environment variable + - Thanks to [Joris Debonnet][@JorisDebonnet] for the patch +- The JS unsigned right shift assignment operator is now properly classified as an assignment operator + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The AbstractVariableSniff abstract sniff now supports anonymous classes and nested functions + - Also fixes an issue with Squiz.Scope.MemberVarScope where member vars of anonymous classes were not being checked +- Added AbstractArraySniff to make it easier to create sniffs that check array formatting + - Allows for checking of single and multi line arrays easily + - Provides a parsed structure of the array including positions of keys, values, and double arrows +- Added Generic.Arrays.ArrayIndent to enforce a single tab stop indent for array keys in multi-line arrays + - Also ensures the close brace is on a new line and indented to the same level as the original statement + - Allows for the indent size to be set using an "indent" property of the sniff +- Added Generic.PHP.DiscourageGoto to warn about the use of the GOTO language construct + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Generic.Debug.ClosureLinter was not running the gjslint command + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Generic.WhiteSpace.DisallowSpaceIndent now fixes space indents in multi-line block comments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.WhiteSpace.DisallowSpaceIndent now fixes mixed space/tab indents more accurately + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.WhiteSpace.DisallowTabIndent now fixes tab indents in multi-line block comments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.Functions.FunctionDeclaration no longer errors when a function declaration is the first content in a JS file + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.Functions.FunctionCallSignature now requires the function name to be indented to an exact tab stop + - If the function name is not the start of the statement, the opening statement must be indented correctly instead + - Added a new fixable error code PEAR.Functions.FunctionCallSignature.OpeningIndent for this error +- Squiz.Functions.FunctionDeclarationArgumentSpacing is no longer confused about comments in function declarations + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.PHP.NonExecutableCode error messages now indicate which line the code block ending is on + - Makes it easier to identify where the code block exited or returned + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.FunctionComment now supports nullable type hints +- Squiz.Commenting.FunctionCommentThrowTag no longer assigns throw tags inside anon classes to the enclosing function +- Squiz.WhiteSpace.SemicolonSpacing now ignores semicolons used for empty statements inside FOR conditions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.ControlStructures.ControlSignature now allows configuring the number of spaces before the colon in alternative syntax + - Override the 'requiredSpacesBeforeColon' setting in a ruleset.xml file to change + - Default remains at 1 + - Thanks to [Nikola Kovacs][@nkovacs] for the patch +- The Squiz standard now ensures array keys are indented 4 spaces from the main statement + - Previously, this standard aligned keys 1 space from the start of the array keyword +- The Squiz standard now ensures array end braces are aligned with the main statement + - Previously, this standard aligned the close brace with the start of the array keyword +- The standard for PHP_CodeSniffer itself now enforces short array syntax +- The standard for PHP_CodeSniffer itself now uses the Generic.Arrays/ArrayIndent sniff rules +- Improved fixer conflicts and syntax error handling for a number of sniffs + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed bug [#1462][sq-1462] : Error processing cyrillic strings in Tokenizer +- Fixed bug [#1573][sq-1573] : Squiz.WhiteSpace.LanguageConstructSpacing does not properly check for tabs and newlines + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#1590][sq-1590] : InlineControlStructure CBF issue while adding braces to an if that's returning a nested function +- Fixed bug [#1718][sq-1718] : Unclosed strings at EOF sometimes tokenized as T_WHITESPACE by the JS tokenizer +- Fixed bug [#1731][sq-1731] : Directory exclusions do not work as expected when a single file name is passed to phpcs +- Fixed bug [#1737][sq-1737] : Squiz.CSS.EmptyStyleDefinition sees comment as style definition and fails to report error +- Fixed bug [#1746][sq-1746] : Very large reports can sometimes become garbled when using the parallel option +- Fixed bug [#1747][sq-1747] : Squiz.Scope.StaticThisUsage incorrectly looking inside closures +- Fixed bug [#1757][sq-1757] : Unknown type hint "object" in Squiz.Commenting.FunctionComment +- Fixed bug [#1758][sq-1758] : PHPCS gets stuck creating file list when processing circular symlinks +- Fixed bug [#1761][sq-1761] : Generic.WhiteSpace.ScopeIndent error on multi-line function call with static closure argument +- Fixed bug [#1762][sq-1762] : `Generic.WhiteSpace.Disallow[Space/Tab]Indent` not inspecting content before open tag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1769][sq-1769] : Custom "define" function triggers a warning about declaring new symbols +- Fixed bug [#1776][sq-1776] : Squiz.Scope.StaticThisUsage incorrectly looking inside anon classes +- Fixed bug [#1777][sq-1777] : Generic.WhiteSpace.ScopeIndent incorrect indent errors when self called function proceeded by comment + +[sq-604]: https://github.com/squizlabs/PHP_CodeSniffer/issues/604 +[sq-1462]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1462 +[sq-1488]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1488 +[sq-1573]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1573 +[sq-1590]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1590 +[sq-1718]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1718 +[sq-1731]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1731 +[sq-1737]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1737 +[sq-1746]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1746 +[sq-1747]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1747 +[sq-1757]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1757 +[sq-1758]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1758 +[sq-1761]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1761 +[sq-1762]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1762 +[sq-1769]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1769 +[sq-1776]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1776 +[sq-1777]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1777 + +## [3.1.1] - 2017-10-17 + +### Changed +- Restored preference of non-dist files over dist files for phpcs.xml and phpcs.xml.dist + - The order that the files are searched is now: .phpcs.xml, phpcs.xml, .phpcs.xml.dist, phpcs.xml.dist + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Progress output now correctly shows skipped files +- Progress output now shows 100% when the file list has finished processing (request [#1697][sq-1697]) +- Stopped some IDEs complaining about testing class aliases + - Thanks to [Vytautas Stankus][@svycka] for the patch +- Squiz.Commenting.InlineComment incorrectly identified comment blocks in some cases, muting some errors + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +### Fixed +- Fixed bug [#1512][sq-1512] : PEAR.Functions.FunctionCallSignature enforces spaces when no arguments if required spaces is not 0 +- Fixed bug [#1522][sq-1522] : Squiz Arrays.ArrayDeclaration and Strings.ConcatenationSpacing fixers causing parse errors with here/nowdocs +- Fixed bug [#1570][sq-1570] : Squiz.Arrays.ArrayDeclaration fixer removes comments between array keyword and open parentheses +- Fixed bug [#1604][sq-1604] : File::isReference has problems with some bitwise operators and class property references + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1645][sq-1645] : Squiz.Commenting.InlineComment will fail to fix comments at the end of the file + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1656][sq-1656] : Using the --sniffs argument has a problem with case sensitivity +- Fixed bug [#1657][sq-1657] : Uninitialized string offset: 0 when sniffing CSS +- Fixed bug [#1669][sq-1669] : Temporary expression proceeded by curly brace is detected as function call +- Fixed bug [#1681][sq-1681] : Huge arrays are super slow to scan with Squiz.Arrays.ArrayDeclaration sniff +- Fixed bug [#1694][sq-1694] : Squiz.Arrays.ArrayBracketSpacing is removing some comments during fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1702][sq-1702] : Generic.WhiteSpaceDisallowSpaceIndent fixer bug when line only contains superfluous whitespace + +[sq-1512]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1512 +[sq-1522]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1522 +[sq-1570]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1570 +[sq-1604]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1604 +[sq-1645]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1645 +[sq-1656]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1656 +[sq-1657]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1657 +[sq-1669]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1669 +[sq-1681]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1681 +[sq-1694]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1694 +[sq-1697]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1697 +[sq-1702]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1702 + +## [3.1.0] - 2017-09-20 + +### Changed +- This release includes a change to support newer versions of PHPUnit (versions 4, 5, and 6 are now supported) + - The custom PHP_CodeSniffer test runner now requires a bootstrap file + - Developers with custom standards using the PHP_CodeSniffer test runner will need to do one of the following: + - run your unit tests from the PHP_CodeSniffer root dir so the bootstrap file is included + - specify the PHP_CodeSniffer bootstrap file on the command line: `phpunit --bootstrap=/path/to/phpcs/tests/bootstrap.php` + - require the PHP_CodeSniffer bootstrap file from your own bootstrap file + - If you don't run PHP_CodeSniffer unit tests, this change will not affect you + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- A phpcs.xml or phpcs.xml.dist file now takes precedence over the default_standard config setting + - Thanks to [Björn Fischer][@Fischer-Bjoern] for the patch +- Both phpcs.xml and phpcs.xml.dist files can now be prefixed with a dot (request [#1566][sq-1566]) + - The order that the files are searched is: .phpcs.xml, .phpcs.xml.dist, phpcs.xml, phpcs.xml.dist +- The autoloader will now search for files during unit tests runs from the same locations as during normal phpcs runs + - Allows for easier unit testing of custom standards that use helper classes or custom namespaces +- Include patterns for sniffs now use OR logic instead of AND logic + - Previously, a file had to be in each of the include patterns to be processed by a sniff + - Now, a file has to only be in at least one of the patterns + - This change reflects the original intention of the feature +- PHPCS will now follow symlinks under the list of checked directories + - This previously only worked if you specified the path to a symlink on the command line +- Output from --config-show, --config-set, and --config-delete now includes the path to the loaded config file +- PHPCS now cleanly exits if its config file is not readable + - Previously, a combination of PHP notices and PHPCS errors would be generated +- Comment tokens that start with /** are now always tokenized as docblocks + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- The PHP-supplied T_YIELD and T_YIELD_FROM token have been replicated for older PHP versions + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Added new Generic.CodeAnalysis.AssignmentInCondition sniff to warn about variable assignments inside conditions + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the contribution +- Added Generic.Files.OneObjectStructurePerFile sniff to ensure there is a single class/interface/trait per file + - Thanks to [Mponos George][@gmponos] for the contribution +- Function call sniffs now check variable function names and self/static object creation + - Specific sniffs are Generic.Functions.FunctionCallArgumentSpacing, PEAR.Functions.FunctionCallSignature, and PSR2.Methods.FunctionCallSignature + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Generic.Files.LineLength can now be configured to ignore all comment lines, no matter their length + - Set the ignoreComments property to TRUE (default is FALSE) in your ruleset.xml file to enable this + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.LowerCaseKeyword now checks self, parent, yield, yield from, and closure (function) keywords + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- PEAR.Functions.FunctionDeclaration now removes a blank line if it creates one by moving the curly brace during fixing +- Squiz.Commenting.FunctionCommentThrowTag now supports PHP 7.1 multi catch exceptions +- Squiz.Formatting.OperatorBracket no longer throws errors for PHP 7.1 multi catch exceptions +- Squiz.Commenting.LongConditionClosingComment now supports finally statements +- Squiz.Formatting.OperatorBracket now correctly fixes pipe separated flags +- Squiz.Formatting.OperatorBracket now correctly fixes statements containing short array syntax +- Squiz.PHP.EmbeddedPhp now properly fixes cases where the only content in an embedded PHP block is a comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.ControlStructureSpacing now ignores comments when checking blank lines at the top of control structures +- Squiz.WhiteSpace.ObjectOperatorSpacing now detects and fixes spaces around double colons + - Thanks to [Julius Å mataviÄius][@bondas83] for the patch +- Squiz.WhiteSpace.MemberVarSpacing can now be configured to check any number of blank lines between member vars + - Set the spacing property (default is 1) in your ruleset.xml file to set the spacing +- Squiz.WhiteSpace.MemberVarSpacing can now be configured to check a different number of blank lines before the first member var + - Set the spacingBeforeFirst property (default is 1) in your ruleset.xml file to set the spacing +- Added a new PHP_CodeSniffer\Util\Tokens::$ooScopeTokens static member var for quickly checking object scope + - Includes T_CLASS, T_ANON_CLASS, T_INTERFACE, and T_TRAIT + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PHP_CodeSniffer\Files\File::findExtendedClassName() now supports extended interfaces + - Thanks to [Martin Hujer][@mhujer] for the patch + +### Fixed +- Fixed bug [#1550][sq-1550] : Squiz.Commenting.FunctionComment false positive when function contains closure +- Fixed bug [#1577][sq-1577] : Generic.InlineControlStructureSniff breaks with a comment between body and condition in do while loops +- Fixed bug [#1581][sq-1581] : Sniffs not loaded when one-standard directories are being registered in installed_paths +- Fixed bug [#1591][sq-1591] : Autoloader failing to load arbitrary files when installed_paths only set via a custom ruleset +- Fixed bug [#1605][sq-1605] : Squiz.WhiteSpace.OperatorSpacing false positive on unary minus after comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1615][sq-1615] : Uncaught RuntimeException when phpcbf fails to fix files +- Fixed bug [#1637][sq-1637] : Generic.WhiteSpaceScopeIndent closure argument indenting incorrect with multi-line strings +- Fixed bug [#1638][sq-1638] : Squiz.WhiteSpace.ScopeClosingBrace closure argument indenting incorrect with multi-line strings +- Fixed bug [#1640][sq-1640] : Squiz.Strings.DoubleQuoteUsage replaces tabs with spaces when fixing + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-1550]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1550 +[sq-1566]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1566 +[sq-1577]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1577 +[sq-1581]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1581 +[sq-1591]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1591 +[sq-1605]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1605 +[sq-1615]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1615 +[sq-1637]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1637 +[sq-1638]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1638 +[sq-1640]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1640 + +## [3.0.2] - 2017-07-18 + +### Changed +- The code report now gracefully handles tokenizer exceptions +- The phpcs and phpcbf scripts are now the only places that exit() in the code + - This allows for easier usage of core PHPCS functions from external scripts + - If you are calling Runner::runPHPCS() or Runner::runPHPCBF() directly, you will get back the full range of exit codes + - If not, catch the new DeepExitException to get the error message ($e->getMessage()) and exit code ($e->getCode()); +- NOWDOC tokens are now considered conditions, just as HEREDOC tokens are + - This makes it easier to find the start and end of a NOWDOC from any token within it + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Custom autoloaders are now only included once in case multiple standards are using the same one + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Improved tokenizing of fallthrough CASE and DEFAULT statements that share a closing statement and use curly braces +- Improved the error message when Squiz.ControlStructures.ControlSignature detects a newline after the closing parenthesis + +### Fixed +- Fixed a problem where the source report was not printing the correct number of errors found +- Fixed a problem where the --cache=/path/to/cachefile CLI argument was not working +- Fixed bug [#1465][sq-1465] : Generic.WhiteSpace.ScopeIndent reports incorrect errors when indenting double arrows in short arrays +- Fixed bug [#1478][sq-1478] : Indentation in fallthrough CASE that contains a closure +- Fixed bug [#1497][sq-1497] : Fatal error if composer prepend-autoloader is set to false + - Thanks to [Kunal Mehta][@legoktm] for the patch +- Fixed bug [#1503][sq-1503] : Alternative control structure syntax not always recognized as scoped +- Fixed bug [#1523][sq-1523] : Fatal error when using the --suffix argument + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1526][sq-1526] : Use of basepath setting can stop PHPCBF being able to write fixed files +- Fixed bug [#1530][sq-1530] : Generic.WhiteSpace.ScopeIndent can increase indent too much for lines within code blocks +- Fixed bug [#1547][sq-1547] : Wrong token type for backslash in use function + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#1549][sq-1549] : Squiz.PHP.EmbeddedPhp fixer conflict with // comment before PHP close tag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1560][sq-1560] : Squiz.Commenting.FunctionComment fatal error when fixing additional param comment lines that have no indent + +[sq-1465]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1465 +[sq-1478]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1478 +[sq-1497]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1497 +[sq-1503]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1503 +[sq-1523]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1523 +[sq-1526]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1526 +[sq-1530]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1530 +[sq-1547]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1547 +[sq-1549]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1549 +[sq-1560]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1560 + +## [3.0.1] - 2017-06-14 + +### Security +- This release contains a fix for a security advisory related to the improper handling of a shell command + - A properly crafted filename would allow for arbitrary code execution when using the --filter=gitmodified command line option + - All version 3 users are encouraged to upgrade to this version, especially if you are checking 3rd-party code + - e.g., you run PHPCS over libraries that you did not write + - e.g., you provide a web service that runs PHPCS over user-uploaded files or 3rd-party repositories + - e.g., you allow external tool paths to be set by user-defined values + - If you are unable to upgrade but you check 3rd-party code, ensure you are not using the Git modified filter + - This advisory does not affect PHP_CodeSniffer version 2. + - Thanks to [Sergei Morozov][@morozov] for the report and patch + +### Changed +- Arguments on the command line now override or merge with those specified in a ruleset.xml file in all cases +- PHPCS now stops looking for a phpcs.xml file as soon as one is found, favoring the closest one to the current dir +- Added missing help text for the --stdin-path CLI option to --help +- Re-added missing help text for the --file-list and --bootstrap CLI options to --help +- Runner::runPHPCS() and Runner::runPHPCBF() now return an exit code instead of exiting directly (request [#1484][sq-1484]) +- The Squiz standard now enforces short array syntax by default +- The autoloader is now working correctly with classes created with class_alias() +- The autoloader will now search for files inside all directories in the installed_paths config var + - This allows autoloading of files inside included custom coding standards without manually requiring them +- You can now specify a namespace for a custom coding standard, used by the autoloader to load non-sniff helper files + - Also used by the autoloader to help other standards directly include sniffs for your standard + - Set the value to the namespace prefix you are using for sniff files (everything up to \Sniffs\) + - e.g., if your namespace format is MyProject\CS\Standard\Sniffs\Category set the namespace to MyProject\CS\Standard + - If omitted, the namespace is assumed to be the same as the directory name containing the ruleset.xml file + - The namespace is set in the ruleset tag of the ruleset.xml file + - e.g., ruleset name="My Coding Standard" namespace="MyProject\CS\Standard" +- Rulesets can now specify custom autoloaders using the new autoload tag + - Autoloaders are included while the ruleset is being processed and before any custom sniffs are included + - Allows for very custom autoloading of helper classes well before the boostrap files are included +- The PEAR standard now includes Squiz.Commenting.DocCommentAlignment + - It previously broke comments onto multiple lines, but didn't align them + +### Fixed +- Fixed a problem where excluding a message from a custom standard's own sniff would exclude the whole sniff + - This caused some PSR2 errors to be under-reported +- Fixed bug [#1442][sq-1442] : T_NULLABLE detection not working for nullable parameters and return type hints in some cases +- Fixed bug [#1447][sq-1447] : Running the unit tests with a PHPUnit config file breaks the test suite + - Unknown arguments were not being handled correctly, but are now stored in $config->unknown +- Fixed bug [#1449][sq-1449] : Generic.Classes.OpeningBraceSameLine doesn't detect comment before opening brace + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1450][sq-1450] : Coding standard located under an installed_path with the same directory name throws an error + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1451][sq-1451] : Sniff exclusions/restrictions don't work with custom sniffs unless they use the PHP_CodeSniffer NS +- Fixed bug [#1454][sq-1454] : Squiz.WhiteSpace.OperatorSpacing is not checking spacing on either side of a short ternary operator + - Thanks to [Mponos George][@gmponos] for the patch +- Fixed bug [#1495][sq-1495] : Setting an invalid installed path breaks all commands +- Fixed bug [#1496][sq-1496] : Squiz.Strings.DoubleQuoteUsage not unescaping dollar sign when fixing + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#1501][sq-1501] : Interactive mode is broken +- Fixed bug [#1504][sq-1504] : PSR2.Namespaces.UseDeclaration hangs fixing use statement with no trailing code + +[sq-1447]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1447 +[sq-1449]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1449 +[sq-1450]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1450 +[sq-1451]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1451 +[sq-1454]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1454 +[sq-1484]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1484 +[sq-1495]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1495 +[sq-1496]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1496 +[sq-1501]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1501 +[sq-1504]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1504 + +## [2.9.1] - 2017-05-22 + +### Fixed +- Fixed bug [#1442][sq-1442] : T_NULLABLE detection not working for nullable parameters and return type hints in some cases +- Fixed bug [#1448][sq-1448] : Generic.Classes.OpeningBraceSameLine doesn't detect comment before opening brace + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch + +[sq-1442]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1442 +[sq-1448]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1448 + +## [3.0.0] - 2017-05-04 + +### Changed +- Added an --ignore-annotations command line argument to ignore all @codingStandards annotations in code comments (request [#811][sq-811]) +- This allows you to force errors to be shown that would otherwise be ignored by code comments + - Also stop files being able to change sniff properties midway through processing +- An error is now reported if no sniffs were registered to be run (request [#1129][sq-1129]) +- The autoloader will now search for files inside the directory of any loaded coding standard + - This allows autoloading of any file inside a custom coding standard without manually requiring them + - Ensure your namespace begins with your coding standard's directory name and follows PSR-4 + - e.g., StandardName\Sniffs\CategoryName\AbstractHelper or StandardName\Helpers\StringSniffHelper +- Fixed an error where STDIN was sometimes not checked when using the --parallel CLI option +- The is_closure index has been removed from the return value of File::getMethodProperties() + - This value was always false because T_FUNCTION tokens are never closures + - Closures have a token type of T_CLOSURE +- The File::isAnonymousFunction() method has been removed + - This function always returned false because it only accepted T_FUNCTION tokens, which are never closures + - Closures have a token type of T_CLOSURE +- Includes all changes from the 2.9.0 release + +### Fixed +- Fixed bug [#834][sq-834] : PSR2.ControlStructures.SwitchDeclaration does not handle if branches with returns + - Thanks to [Fabian Wiget][@fabacino] for the patch + +[sq-811]: https://github.com/squizlabs/PHP_CodeSniffer/issues/811 +[sq-834]: https://github.com/squizlabs/PHP_CodeSniffer/issues/834 +[sq-1129]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1129 + +## [3.0.0RC4] - 2017-03-02 + +### Security +- This release contains a fix for a security advisory related to the improper handling of shell commands + - Uses of shell_exec() and exec() were not escaping filenames and configuration settings in most cases + - A properly crafted filename or configuration option would allow for arbitrary code execution when using some features + - All users are encouraged to upgrade to this version, especially if you are checking 3rd-party code + - e.g., you run PHPCS over libraries that you did not write + - e.g., you provide a web service that runs PHPCS over user-uploaded files or 3rd-party repositories + - e.g., you allow external tool paths to be set by user-defined values + - If you are unable to upgrade but you check 3rd-party code, ensure you are not using the following features: + - The diff report + - The notify-send report + - The Generic.PHP.Syntax sniff + - The Generic.Debug.CSSLint sniff + - The Generic.Debug.ClosureLinter sniff + - The Generic.Debug.JSHint sniff + - The Squiz.Debug.JSLint sniff + - The Squiz.Debug.JavaScriptLint sniff + - The Zend.Debug.CodeAnalyzer sniff + - Thanks to [Klaus Purer][@klausi] for the report + +### Changed +- The indent property of PEAR.Classes.ClassDeclaration has been removed + - Instead of calculating the indent of the brace, it just ensures the brace is aligned with the class keyword + - Other sniffs can be used to ensure the class itself is indented correctly +- Invalid exclude rules inside a ruleset.xml file are now ignored instead of potentially causing out of memory errors + - Using the -vv command line argument now also shows the invalid exclude rule as XML +- Includes all changes from the 2.8.1 release + +### Fixed +- Fixed bug [#1333][sq-1333] : The new autoloader breaks some frameworks with custom autoloaders +- Fixed bug [#1334][sq-1334] : Undefined offset when explaining standard with custom sniffs + +[sq-1333]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1333 +[sq-1334]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1334 + +## [3.0.0RC3] - 2017-02-02 + +### Changed +- Added support for ES6 class declarations + - Previously, these class were tokenized as JS objects but are now tokenized as normal T_CLASS structures +- Added support for ES6 method declarations, where the "function" keyword is not used + - Previously, these methods were tokenized as JS objects (fixes bug [#1251][sq-1251]) + - The name of the ES6 method is now assigned the T_FUNCTION keyword and treated like a normal function + - Custom sniffs that support JS and listen for T_FUNCTION tokens can't assume the token represents the word "function" + - Check the contents of the token first, or use $phpcsFile->getDeclarationName($stackPtr) if you just want its name + - There is no change for custom sniffs that only check PHP code +- PHPCBF exit codes have been changed so they are now more useful (request [#1270][sq-1270]) + - Exit code 0 is now used to indicate that no fixable errors were found, and so nothing was fixed + - Exit code 1 is now used to indicate that all fixable errors were fixed correctly + - Exit code 2 is now used to indicate that PHPCBF failed to fix some of the fixable errors it found + - Exit code 3 is now used for general script execution errors +- Added PEAR.Commenting.FileComment.ParamCommentAlignment to check alignment of multi-line param comments +- Includes all changes from the 2.8.0 release + +### Fixed +- Fixed an issue where excluding a file using a @codingStandardsIgnoreFile comment would produce errors + - For PHPCS, it would show empty files being processed + - For PHPCBF, it would produce a PHP error +- Fixed bug [#1233][sq-1233] : Can't set config data inside ruleset.xml file +- Fixed bug [#1241][sq-1241] : CodeSniffer.conf not working with 3.x PHAR file + +[sq-1233]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1233 +[sq-1241]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1241 +[sq-1251]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1251 +[sq-1270]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1270 + +## [3.0.0RC2] - 2016-11-30 + +### Changed +- Made the Runner class easier to use with wrapper scripts +- Full usage information is no longer printed when a usage error is encountered (request [#1186][sq-1186]) + - Makes it a lot easier to find and read the error message that was printed +- Includes all changes from the 2.7.1 release + +### Fixed +- Fixed an undefined var name error that could be produced while running PHPCBF +- Fixed bug [#1167][sq-1167] : 3.0.0RC1 PHAR does not work with PEAR standard +- Fixed bug [#1208][sq-1208] : Excluding files doesn't work when using STDIN with a filename specified + +[sq-1167]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1167 +[sq-1186]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1186 +[sq-1208]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1208 + +## [3.0.0RC1] - 2016-09-02 + +### Changed +- Progress output now shows E and W in green when a file has fixable errors or warnings + - Only supported if colors are enabled +- PHPCBF no longer produces verbose output by default (request [#699][sq-699]) + - Use the -v command line argument to show verbose fixing output + - Use the -q command line argument to disable verbose information if enabled by default +- PHPBF now prints a summary report after fixing files + - Report shows files that were fixed, how many errors were fixed, and how many remain +- PHPCBF now supports the -p command line argument to print progress information + - Prints a green F for files where fixes occurred + - Prints a red E for files that could not be fixed due to an error + - Use the -q command line argument to disable progress information if enabled by default +- Running unit tests using --verbose no longer throws errors +- Includes all changes from the 2.7.0 release + +### Fixed +- Fixed shell error appearing on some systems when trying to find executable paths + +[sq-699]: https://github.com/squizlabs/PHP_CodeSniffer/issues/699 + +## [3.0.0a1] - 2016-07-20 + +### Changed +- Min PHP version increased from 5.1.2 to 5.4.0 +- Added optional caching of results between runs (request [#530][sq-530]) + - Enable the cache by using the --cache command line argument + - If you want the cache file written somewhere specific, use --cache=/path/to/cacheFile + - Use the command "phpcs --config-set cache true" to turn caching on by default + - Use the --no-cache command line argument to disable caching if it is being turned on automatically +- Add support for checking file in parallel (request [#421][sq-421]) + - Tell PHPCS how many files to check at once using the --parallel command line argument + - To check 100 files at once, using --parallel=100 + - To disable parallel checking if it is being turned on automatically, use --parallel=1 + - Requires PHP to be compiled with the PCNTL package +- The default encoding has been changed from iso-8859-1 to utf-8 (request [#760][sq-760]) + - The --encoding command line argument still works, but you no longer have to set it to process files as utf-8 + - If encoding is being set to utf-8 in a ruleset or on the CLI, it can be safely removed + - If the iconv PHP extension is not installed, standard non-multibyte aware functions will be used +- Added a new "code" report type to show a code snippet for each error (request [#419][sq-419]) + - The line containing the error is printed, along with 2 lines above and below it to show context + - The location of the errors is underlined in the code snippet if you also use --colors + - Use --report=code to generate this report +- Added support for custom filtering of the file list + - Developers can write their own filter classes to perform custom filtering of the list before the run starts + - Use the command line arg `--filter=/path/to/filter.php` to specify a filter to use + - Extend \PHP_CodeSniffer\Filters\Filter to also support the core PHPCS extension and path filtering + - Extend \PHP_CodeSniffer\Filters\ExactMatch to get the core filtering and the ability to use blacklists and whitelists + - The included \PHP_CodeSniffer\Filters\GitModified filter is a good example of an ExactMatch filter +- Added support for only checking files that have been locally modified or added in a git repo + - Use --filter=gitmodified to check these files + - You still need to give PHPCS a list of files or directories in which to check +- Added automatic discovery of executable paths (request [#571][sq-571]) + - Thanks to [Sergei Morozov][@morozov] for the patch +- You must now pass "-" on the command line to have PHPCS wait for STDIN + - E.g., phpcs --standard=PSR2 - + - You can still pipe content via STDIN as normal as PHPCS will see this and process it + - But without the "-", PHPCS will throw an error if no content or files are passed to it +- All PHP errors generated by sniffs are caught, re-thrown as exceptions, and reported in the standard error reports + - This should stop bugs inside sniffs causing infinite loops + - Also stops invalid reports being produced as errors don't print to the screen directly +- Sniff codes are no longer optional + - If a sniff throws an error or a warning, it must specify an internal code for that message +- The installed_paths config setting can now point directly to a standard + - Previously, it had to always point to the directory in which the standard lives +- Multiple reports can now be specified using the --report command line argument + - Report types are separated by commas + - E.g., --report=full,summary,info + - Previously, you had to use one argument for each report such as --report=full --report=summary --report=info +- You can now set the severity, message type, and exclude patterns for an entire sniff, category, or standard + - Previously, this was only available for a single message +- You can now include a single sniff code in a ruleset instead of having to include an entire sniff + - Including a sniff code will automatically exclude all other messages from that sniff + - If the sniff is already included by an imported standard, set the sniff severity to 0 and include the specific message you want +- PHPCBF no longer uses patch + - Files are now always overwritten + - The --no-patch option has been removed +- Added a --basepath option to strip a directory from the front of file paths in output (request [#470][sq-470]) + - The basepath is absolute or relative to the current directory + - E.g., to output paths relative to current dir in reports, use --basepath=. +- Ignore rules are now checked when using STDIN (request [#733][sq-733]) +- Added an include-pattern tag to rulesets to include a sniff for specific files and folders only (request [#656][sq-656]) + - This is the exact opposite of the exclude-pattern tag + - This option is only usable within sniffs, not globally like exclude-patterns are +- Added a new -m option to stop error messages from being recorded, which saves a lot of memory + - PHPCBF always uses this setting to reduce memory as it never outputs error messages + - Setting the $recordErrors member var inside custom report classes is no longer supported (use -m instead) +- Exit code 2 is now used to indicate fixable errors were found (request [#930][sq-930]) + - Exit code 3 is now used for general script execution errors + - Exit code 1 is used to indicate that coding standard errors were found, but none are fixable + - Exit code 0 is unchanged and continues to mean no coding standard errors found + +### Removed +- The included PHPCS standard has been removed + - All rules are now found inside the phpcs.xml.dist file + - Running "phpcs" without any arguments from a git clone will use this ruleset +- The included SVN pre-commit hook has been removed + - Hooks for version control systems will no longer be maintained within the PHPCS project + +[sq-419]: https://github.com/squizlabs/PHP_CodeSniffer/issues/419 +[sq-421]: https://github.com/squizlabs/PHP_CodeSniffer/issues/421 +[sq-470]: https://github.com/squizlabs/PHP_CodeSniffer/issues/470 +[sq-530]: https://github.com/squizlabs/PHP_CodeSniffer/issues/530 +[sq-571]: https://github.com/squizlabs/PHP_CodeSniffer/pull/571 +[sq-656]: https://github.com/squizlabs/PHP_CodeSniffer/issues/656 +[sq-733]: https://github.com/squizlabs/PHP_CodeSniffer/issues/733 +[sq-760]: https://github.com/squizlabs/PHP_CodeSniffer/issues/760 +[sq-930]: https://github.com/squizlabs/PHP_CodeSniffer/issues/930 + +## [2.9.0] - 2017-05-04 + +### Changed +- Added Generic.Debug.ESLint sniff to run ESLint over JS files and report errors + - Set eslint path using: phpcs --config-set eslint_path /path/to/eslint + - Thanks to [Ryan McCue][@rmccue] for the contribution +- T_POW is now properly considered an arithmetic operator, and will be checked as such + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- T_SPACESHIP and T_COALESCE are now properly considered comparison operators, and will be checked as such + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHP.DisallowShortOpenTag now warns about possible short open tags even when short_open_tag is set to OFF + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.WhiteSpace.DisallowTabIndent now finds and fixes improper use of spaces anywhere inside the line indent + - Previously, only the first part of the indent was used to determine the indent type + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.Commenting.ClassComment now supports checking of traits as well as classes and interfaces + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.FunctionCommentThrowTag now supports re-throwing exceptions (request [#946][sq-946]) + - Thanks to [Samuel Levy][@samlev] for the patch +- Squiz.PHP.DisallowMultipleAssignments now ignores PHP4-style member var assignments + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.FunctionSpacing now ignores spacing above functions when they are preceded by inline comments + - Stops conflicts between this sniff and comment spacing sniffs +- Squiz.WhiteSpace.OperatorSpacing no longer checks the equal sign in declare statements + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added missing error codes for a couple of sniffs so they can now be customised as normal + +### Fixed +- Fixed bug [#1266][sq-1266] : PEAR.WhiteSpace.ScopeClosingBrace can throw an error while fixing mixed PHP/HTML +- Fixed bug [#1364][sq-1364] : Yield From values are not recognised as returned values in Squiz FunctionComment sniff +- Fixed bug [#1373][sq-1373] : Error in tab expansion results in white-space of incorrect size + - Thanks to [Mark Clements][@MarkMaldaba] for the patch +- Fixed bug [#1381][sq-1381] : Tokenizer: dereferencing incorrectly identified as short array +- Fixed bug [#1387][sq-1387] : Squiz.ControlStructures.ControlSignature does not handle alt syntax when checking space after closing brace +- Fixed bug [#1392][sq-1392] : Scope indent calculated incorrectly when using array destructuring +- Fixed bug [#1394][sq-1394] : integer type hints appearing as TypeHintMissing instead of ScalarTypeHintMissing + - PHP 7 type hints were also being shown when run under PHP 5 in some cases +- Fixed bug [#1405][sq-1405] : Squiz.WhiteSpace.ScopeClosingBrace fails to fix closing brace within indented PHP tags +- Fixed bug [#1421][sq-1421] : Ternaries used in constant scalar expression for param default misidentified by tokenizer +- Fixed bug [#1431][sq-1431] : PHPCBF can't fix short open tags when they are not followed by a space + - Thanks to [Gonçalo Queirós][@ghunti] for the patch +- Fixed bug [#1432][sq-1432] : PHPCBF can make invalid fixes to inline JS control structures that make use of JS objects + +[sq-946]: https://github.com/squizlabs/PHP_CodeSniffer/pull/946 +[sq-1266]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1266 +[sq-1364]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1364 +[sq-1373]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1373 +[sq-1381]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1381 +[sq-1387]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1387 +[sq-1392]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1392 +[sq-1394]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1394 +[sq-1405]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1405 +[sq-1421]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1421 +[sq-1431]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1431 +[sq-1432]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1432 + +## [2.8.1] - 2017-03-02 + +### Security +- This release contains a fix for a security advisory related to the improper handling of shell commands + - Uses of shell_exec() and exec() were not escaping filenames and configuration settings in most cases + - A properly crafted filename or configuration option would allow for arbitrary code execution when using some features + - All users are encouraged to upgrade to this version, especially if you are checking 3rd-party code + - e.g., you run PHPCS over libraries that you did not write + - e.g., you provide a web service that runs PHPCS over user-uploaded files or 3rd-party repositories + - e.g., you allow external tool paths to be set by user-defined values + - If you are unable to upgrade but you check 3rd-party code, ensure you are not using the following features: + - The diff report + - The notify-send report + - The Generic.PHP.Syntax sniff + - The Generic.Debug.CSSLint sniff + - The Generic.Debug.ClosureLinter sniff + - The Generic.Debug.JSHint sniff + - The Squiz.Debug.JSLint sniff + - The Squiz.Debug.JavaScriptLint sniff + - The Zend.Debug.CodeAnalyzer sniff + - Thanks to [Klaus Purer][@klausi] for the report + +### Changed +- The PHP-supplied T_COALESCE_EQUAL token has been replicated for PHP versions before 7.2 +- PEAR.Functions.FunctionDeclaration now reports an error for blank lines found inside a function declaration +- PEAR.Functions.FunctionDeclaration no longer reports indent errors for blank lines in a function declaration +- Squiz.Functions.MultiLineFunctionDeclaration no longer reports errors for blank lines in a function declaration + - It would previously report that only one argument is allowed per line +- Squiz.Commenting.FunctionComment now corrects multi-line param comment padding more accurately +- Squiz.Commenting.FunctionComment now properly fixes pipe-separated param types +- Squiz.Commenting.FunctionComment now works correctly when function return types also contain a comment + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.ControlStructures.InlineIfDeclaration now supports the elvis operator + - As this is not a real PHP operator, it enforces no spaces between ? and : when the THEN statement is empty +- Squiz.ControlStructures.InlineIfDeclaration is now able to fix the spacing errors it reports + +### Fixed +- Fixed bug [#1340][sq-1340] : STDIN file contents not being populated in some cases + - Thanks to [David Biňovec][@david-binda] for the patch +- Fixed bug [#1344][sq-1344] : PEAR.Functions.FunctionCallSignatureSniff throws error for blank comment lines +- Fixed bug [#1347][sq-1347] : PSR2.Methods.FunctionCallSignature strips some comments during fixing + - Thanks to [Algirdas Gurevicius][@uniquexor] for the patch +- Fixed bug [#1349][sq-1349] : Squiz.Strings.DoubleQuoteUsage.NotRequired message is badly formatted when string contains a CR newline char + - Thanks to [Algirdas Gurevicius][@uniquexor] for the patch +- Fixed bug [#1350][sq-1350] : Invalid Squiz.Formatting.OperatorBracket error when using namespaces +- Fixed bug [#1369][sq-1369] : Empty line in multi-line function declaration cause infinite loop + +[sq-1340]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1340 +[sq-1344]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1344 +[sq-1347]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1347 +[sq-1349]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1349 +[sq-1350]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1350 +[sq-1369]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1369 + +## [2.8.0] - 2017-02-02 + +### Changed +- The Internal.NoCodeFound error is no longer generated for content sourced from STDIN + - This should stop some Git hooks generating errors because PHPCS is trying to process the refs passed on STDIN +- Squiz.Commenting.DocCommentAlignment now checks comments on class properties defined using the VAR keyword + - Thanks to [Klaus Purer][@klausi] for the patch +- The getMethodParameters() method now recognises "self" as a valid type hint + - The return array now contains a new "content" index containing the raw content of the param definition + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The getMethodParameters() method now supports nullable types + - The return array now contains a new "nullable_type" index set to true or false for each method param + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The getMethodParameters() method now supports closures + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added more guard code for JS files with syntax errors (request [#1271][sq-1271] and request [#1272][sq-1272]) +- Added more guard code for CSS files with syntax errors (request [#1304][sq-1304]) +- PEAR.Commenting.FunctionComment fixers now correctly handle multi-line param comments +- AbstractVariableSniff now supports anonymous classes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.NamingConventions.ConstructorName and PEAR.NamingConventions.ValidVariable now support anonymous classes +- Generic.NamingConventions.CamelCapsFunctionName and PEAR.NamingConventions.ValidFunctionName now support anonymous classes + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.CodeAnalysis.UnusedFunctionParameter and PEAR.Functions.ValidDefaultValue now support closures + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- PEAR.NamingConventions.ValidClassName and Squiz.Classes.ValidClassName now support traits + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.Functions.FunctionCallArgumentSpacing now supports closures other PHP-provided functions + - Thanks to [Algirdas Gurevicius][@uniquexor] for the patch +- Fixed an error where a nullable type character was detected as an inline then token + - A new T_NULLABLE token has been added to represent the ? nullable type character + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Squiz.WhiteSpace.SemicolonSpacing no longer removes comments while fixing the placement of semicolons + - Thanks to [Algirdas Gurevicius][@uniquexor] for the patch + +### Fixed +- Fixed bug [#1230][sq-1230] : JS tokeniser incorrectly tokenises bitwise shifts as comparison + - Thanks to [Ryan McCue][@rmccue] for the patch +- Fixed bug [#1237][sq-1237] : Uninitialized string offset in PHP Tokenizer on PHP 5.2 +- Fixed bug [#1239][sq-1239] : Warning when static method name is 'default' +- Fixed bug [#1240][sq-1240] : False positive for function names starting with triple underscore + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1245][sq-1245] : SELF is not recognised as T_SELF token in: return new self +- Fixed bug [#1246][sq-1246] : A mix of USE statements with and without braces can cause the tokenizer to mismatch brace tokens + - Thanks to [MichaÅ‚ Bundyra][@michalbundyra] for the patch +- Fixed bug [#1249][sq-1249] : GitBlame report requires a .git directory +- Fixed bug [#1252][sq-1252] : Squiz.Strings.ConcatenationSpacing fix creates syntax error when joining a number to a string +- Fixed bug [#1253][sq-1253] : Generic.ControlStructures.InlineControlStructure fix creates syntax error fixing if-try/catch +- Fixed bug [#1255][sq-1255] : Inconsistent indentation check results when ELSE on new line +- Fixed bug [#1257][sq-1257] : Double dash in CSS class name can lead to "Named colours are forbidden" false positives +- Fixed bug [#1260][sq-1260] : Syntax errors not being shown when error_prepend_string is set + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Fixed bug [#1264][sq-1264] : Array return type hint is sometimes detected as T_ARRAY_HINT instead of T_RETURN_TYPE + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#1265][sq-1265] : ES6 arrow function raises unexpected operator spacing errors +- Fixed bug [#1267][sq-1267] : Fixer incorrectly handles filepaths with repeated dir names + - Thanks to [Sergey Ovchinnikov][@orx0r] for the patch +- Fixed bug [#1276][sq-1276] : Commenting.FunctionComment.InvalidReturnVoid conditional issue with anonymous classes +- Fixed bug [#1277][sq-1277] : Squiz.PHP.DisallowMultipleAssignments.Found error when var assignment is on the same line as an open tag +- Fixed bug [#1284][sq-1284] : Squiz.Arrays.ArrayBracketSpacing.SpaceBeforeBracket false positive match for short list syntax + +[sq-1230]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1230 +[sq-1237]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1237 +[sq-1239]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1239 +[sq-1240]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1240 +[sq-1245]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1245 +[sq-1246]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1246 +[sq-1249]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1249 +[sq-1252]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1252 +[sq-1253]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1253 +[sq-1255]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1255 +[sq-1257]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1257 +[sq-1260]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1260 +[sq-1264]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1264 +[sq-1265]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1265 +[sq-1267]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1267 +[sq-1271]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1271 +[sq-1272]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1272 +[sq-1276]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1276 +[sq-1277]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1277 +[sq-1284]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1284 +[sq-1304]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1304 + +## [2.7.1] - 2016-11-30 + +### Changed +- Squiz.ControlStructures.ControlSignature.SpaceAfterCloseParenthesis fix now removes unnecessary whitespace +- Squiz.Formatting.OperatorBracket no longer errors for negative array indexes used within a function call +- Squiz.PHP.EmbeddedPhp no longer expects a semicolon after statements that are only opening a scope +- Fixed a problem where the content of T_DOC_COMMENT_CLOSE_TAG tokens could sometimes be (boolean) false +- Developers of custom standards with custom test runners can now have their standards ignored by the built-in test runner + - Set the value of an environment variable called PHPCS_IGNORE_TESTS with a comma separated list of your standard names + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- The unit test runner now loads the test sniff outside of the standard's ruleset so that exclude rules do not get applied + - This may have caused problems when testing custom sniffs inside custom standards + - Also makes the unit tests runs a little faster +- The SVN pre-commit hook now works correctly when installed via composer + - Thanks to [Sergey][@sserbin] for the patch + +### Fixed +- Fixed bug [#1135][sq-1135] : PEAR.ControlStructures.MultiLineCondition.CloseBracketNewLine not detected if preceded by multiline function call +- Fixed bug [#1138][sq-1138] : PEAR.ControlStructures.MultiLineCondition.Alignment not detected if closing brace is first token on line +- Fixed bug [#1141][sq-1141] : Sniffs that check EOF newlines don't detect newlines properly when the last token is a doc block +- Fixed bug [#1150][sq-1150] : Squiz.Strings.EchoedStrings does not properly fix bracketed statements +- Fixed bug [#1156][sq-1156] : Generic.Formatting.DisallowMultipleStatements errors when multiple short echo tags are used on the same line + - Thanks to [Nikola Kovacs][@nkovacs] for the patch +- Fixed bug [#1161][sq-1161] : Absolute report path is treated like a relative path if it also exists within the current directory +- Fixed bug [#1170][sq-1170] : Javascript regular expression literal not recognized after comparison operator +- Fixed bug [#1180][sq-1180] : Class constant named FUNCTION is incorrectly tokenized +- Fixed bug [#1181][sq-1181] : Squiz.Operators.IncrementDecrementUsage.NoBrackets false positive when incrementing properties + - Thanks to [Jürgen Henge-Ernst][@hernst42] for the patch +- Fixed bug [#1188][sq-1188] : Generic.WhiteSpace.ScopeIndent issues with inline HTML and multi-line function signatures +- Fixed bug [#1190][sq-1190] : phpcbf on if/else with trailing comment generates erroneous code +- Fixed bug [#1191][sq-1191] : Javascript sniffer fails with function called "Function" +- Fixed bug [#1203][sq-1203] : Inconsistent behavior of PHP_CodeSniffer_File::findEndOfStatement +- Fixed bug [#1218][sq-1218] : CASE conditions using class constants named NAMESPACE/INTERFACE/TRAIT etc are incorrectly tokenized +- Fixed bug [#1221][sq-1221] : Indented function call with multiple closure arguments can cause scope indent error +- Fixed bug [#1224][sq-1224] : PHPCBF fails to fix code with heredoc/nowdoc as first argument to a function + +[sq-1135]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1135 +[sq-1138]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1138 +[sq-1141]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1141 +[sq-1150]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1150 +[sq-1156]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1156 +[sq-1161]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1161 +[sq-1170]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1170 +[sq-1180]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1180 +[sq-1181]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1181 +[sq-1188]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1188 +[sq-1190]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1190 +[sq-1191]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1191 +[sq-1203]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1203 +[sq-1218]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1218 +[sq-1221]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1221 +[sq-1224]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1224 + +## [2.7.0] - 2016-09-02 + +### Changed +- Added --file-list command line argument to allow a list of files and directories to be specified in an external file + - Useful if you have a generated list of files to check that would be too long for the command line + - File and directory paths are listed one per line + - Usage is: phpcs --file-list=/path/to/file-list ... + - Thanks to [Blotzu][@andrei-propertyguru] for the patch +- Values set using @codingStandardsChangeSetting comments can now contain spaces +- Sniff unit tests can now specify a list of test files instead of letting the runner pick them (request [#1078][sq-1078]) + - Useful if a sniff needs to exclude files based on the environment, or is checking filenames + - Override the new getTestFiles() method to specify your own list of test files +- Generic.Functions.OpeningFunctionBraceKernighanRitchie now ignores spacing for function return types + - The sniff code Generic.Functions.OpeningFunctionBraceKernighanRitchie.SpaceAfterBracket has been removed + - Replaced by Generic.Functions.OpeningFunctionBraceKernighanRitchie.SpaceBeforeBrace + - The new error message is slightly clearer as it indicates that a single space is needed before the brace +- Squiz.Commenting.LongConditionClosingComment now allows for the length of a code block to be configured + - Set the lineLimit property (default is 20) in your ruleset.xml file to set the code block length + - When the code block length is reached, the sniff will enforce a closing comment after the closing brace + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.Commenting.LongConditionClosingComment now allows for the end comment format to be configured + - Set the commentFormat property (default is "//end %s") in your ruleset.xml file to set the format + - The placeholder %s will be replaced with the type of condition opener, e.g., "//end foreach" + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Generic.PHPForbiddenFunctions now allows forbidden functions to have mixed case + - Previously, it would only do a strtolower comparison + - Error message now shows what case was found in the code and what the correct case should be + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added Generic.Classes.OpeningBraceSameLine to ensure opening brace of class/interface/trait is on the same line as the declaration + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added Generic.PHP.BacktickOperator to ban the use of the backtick operator for running shell commands + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Added Generic.PHP.DisallowAlternativePHPTags to ban the use of alternate PHP tags + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Squiz.WhiteSpace.LanguageConstructSpacing no longer checks for spaces if parenthesis are being used (request [#1062][sq-1062]) + - Makes this sniff more compatible with those that check parenthesis spacing of function calls +- Squiz.WhiteSpace.ObjectOperatorSpacing now has a setting to ignore newline characters around object operators + - Default remains FALSE, so newlines are not allowed + - Override the "ignoreNewlines" setting in a ruleset.xml file to change + - Thanks to [Alex Howansky][@AlexHowansky] for the patch +- Squiz.Scope.MethodScope now sniffs traits as well as classes and interfaces + - Thanks to [Jesse Donat][@donatj] for the patch +- PHPCBF is now able to fix Squiz.SelfMemberReference.IncorrectCase errors + - Thanks to [Nikola Kovacs][@nkovacs] for the patch +- PHPCBF is now able to fix Squiz.Commenting.VariableComment.IncorrectVarType + - Thanks to [Walt Sorensen][@photodude] for the patch +- PHPCBF is now able to fix Generic.PHP.DisallowShortOpenTag + - Thanks to [Juliette Reinders Folmer][@jrfnl] for the patch +- Improved the formatting of the end brace when auto fixing InlineControlStructure errors (request [#1121][sq-1121]) +- Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine fix no longer leaves blank line after brace (request [#1085][sq-1085]) +- Generic UpperCaseConstantNameSniff now allows lowercase namespaces in constant definitions + - Thanks to [Daniel Schniepp][@dschniepp] for the patch +- Squiz DoubleQuoteUsageSniff is now more tolerant of syntax errors caused by mismatched string tokens +- A few sniffs that produce errors based on the current PHP version can now be told to run using a specific PHP version + - Set the `php_version` config var using `--config-set`, `--runtime-set`, or in a ruleset to specify a specific PHP version + - The format of the PHP version is the same as the `PHP_VERSION_ID` constant (e.g., 50403 for version 5.4.3) + - Supported sniffs are Generic.PHP.DisallowAlternativePHPTags, PSR1.Classes.ClassDeclaration, Squiz.Commenting.FunctionComment + - Thanks to [Finlay Beaton][@ofbeaton] for the patch + +### Fixed +- Fixed bug [#985][sq-985] : Duplicate class definition detection generates false-positives in media queries + - Thanks to [Raphael Horber][@rhorber] for the patch +- Fixed bug [#1014][sq-1014] : Squiz VariableCommentSniff doesn't always detect a missing comment +- Fixed bug [#1066][sq-1066] : Undefined index: quiet in `CLI.php` during unit test run with `-v` command line arg +- Fixed bug [#1072][sq-1072] : Squiz.SelfMemberReference.NotUsed not detected if leading namespace separator is used +- Fixed bug [#1089][sq-1089] : Rulesets cannot be loaded if the path contains urlencoded characters +- Fixed bug [#1091][sq-1091] : PEAR and Squiz FunctionComment sniffs throw errors for some invalid @param line formats +- Fixed bug [#1092][sq-1092] : PEAR.Functions.ValidDefaultValue should not flag type hinted methods with a NULL default argument +- Fixed bug [#1095][sq-1095] : Generic LineEndings sniff replaces tabs with spaces with --tab-width is set +- Fixed bug [#1096][sq-1096] : Squiz FunctionDeclarationArgumentSpacing gives incorrect error/fix when variadic operator is followed by a space +- Fixed bug [#1099][sq-1099] : Group use declarations are incorrectly fixed by the PSR2 standard + - Thanks to [Jason McCreary][@jasonmccreary] for the patch +- Fixed bug [#1101][sq-1101] : Incorrect indent errors when breaking out of PHP inside an IF statement +- Fixed bug [#1102][sq-1102] : Squiz.Formatting.OperatorBracket.MissingBrackets faulty bracketing fix +- Fixed bug [#1109][sq-1109] : Wrong scope indent reported in anonymous class +- Fixed bug [#1112][sq-1112] : File docblock not recognized when require_once follows it +- Fixed bug [#1120][sq-1120] : InlineControlStructureSniff does not handle auto-fixing for control structures that make function calls +- Fixed bug [#1124][sq-1124] : Squiz.Operators.ComparisonOperatorUsage does not detect bracketed conditions for inline IF statements + - Thanks to [Raphael Horber][@rhorber] for the patch + +[sq-985]: https://github.com/squizlabs/PHP_CodeSniffer/issues/985 +[sq-1014]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1014 +[sq-1062]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1062 +[sq-1066]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1066 +[sq-1072]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1072 +[sq-1078]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1078 +[sq-1085]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1085 +[sq-1089]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1089 +[sq-1091]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1091 +[sq-1092]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1092 +[sq-1095]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1095 +[sq-1096]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1096 +[sq-1099]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1099 +[sq-1101]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1101 +[sq-1102]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1102 +[sq-1109]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1109 +[sq-1112]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1112 +[sq-1120]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1120 +[sq-1121]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1121 +[sq-1124]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1124 + +## [2.6.2] - 2016-07-14 + +### Changed +- Added a new --exclude CLI argument to exclude a list of sniffs from checking and fixing (request [#904][sq-904]) + - Accepts the same sniff codes as the --sniffs command line argument, but provides the opposite functionality +- Added a new -q command line argument to disable progress and verbose information from being printed (request [#969][sq-969]) + - Useful if a coding standard hard-codes progress or verbose output but you want PHPCS to be quiet + - Use the command "phpcs --config-set quiet true" to turn quiet mode on by default +- Generic LineLength sniff no longer errors for comments that cannot be broken out onto a new line (request [#766][sq-766]) + - A typical case is a comment that contains a very long URL + - The comment is ignored if putting the URL on an indented new comment line would be longer than the allowed length +- Settings extensions in a ruleset no longer causes PHP notices during unit testing + - Thanks to [Klaus Purer][@klausi] for the patch +- Version control reports now show which errors are fixable if you are showing sources +- Added a new sniff to enforce a single space after a NOT operator (request [#1051][sq-1051]) + - Include in a ruleset using the code Generic.Formatting.SpaceAfterNot +- The Squiz.Commenting.BlockComment sniff now supports tabs for indenting comment lines (request [#1056][sq-1056]) + +### Fixed +- Fixed bug [#790][sq-790] : Incorrect missing @throws error in methods that use closures +- Fixed bug [#908][sq-908] : PSR2 standard is not checking that closing brace is on line following the body +- Fixed bug [#945][sq-945] : Incorrect indent behavior using deep-nested function and arrays +- Fixed bug [#961][sq-961] : Two anonymous functions passed as function/method arguments cause indentation false positive +- Fixed bug [#1005][sq-1005] : Using global composer vendor autoload breaks PHP lowercase built-in function sniff + - Thanks to [Michael Butler][@michaelbutler] for the patch +- Fixed bug [#1007][sq-1007] : Squiz Unreachable code detection is not working properly with a closure inside a case +- Fixed bug [#1023][sq-1023] : PSR2.Classes.ClassDeclaration fails if class extends base class and "implements" is on trailing line +- Fixed bug [#1026][sq-1026] : Arrays in comma delimited class properties cause ScopeIndent to increase indent +- Fixed bug [#1028][sq-1028] : Squiz ArrayDeclaration incorrectly fixes multi-line array where end bracket is not on a new line +- Fixed bug [#1034][sq-1034] : Squiz FunctionDeclarationArgumentSpacing gives incorrect error when first arg is a variadic +- Fixed bug [#1036][sq-1036] : Adjacent assignments aligned analysis statement wrong +- Fixed bug [#1049][sq-1049] : Version control reports can show notices when the report width is very small +- Fixed bug [#21050][pear-21050] : PEAR MultiLineCondition sniff suppresses errors on last condition line + +[sq-766]: https://github.com/squizlabs/PHP_CodeSniffer/issues/766 +[sq-790]: https://github.com/squizlabs/PHP_CodeSniffer/issues/790 +[sq-904]: https://github.com/squizlabs/PHP_CodeSniffer/issues/904 +[sq-908]: https://github.com/squizlabs/PHP_CodeSniffer/issues/908 +[sq-945]: https://github.com/squizlabs/PHP_CodeSniffer/issues/945 +[sq-961]: https://github.com/squizlabs/PHP_CodeSniffer/issues/961 +[sq-969]: https://github.com/squizlabs/PHP_CodeSniffer/issues/969 +[sq-1005]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1005 +[sq-1007]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1007 +[sq-1023]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1023 +[sq-1026]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1026 +[sq-1028]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1028 +[sq-1034]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1034 +[sq-1036]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1036 +[sq-1049]: https://github.com/squizlabs/PHP_CodeSniffer/pull/1049 +[sq-1051]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1051 +[sq-1056]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1056 +[pear-21050]: https://pear.php.net/bugs/bug.php?id=21050 + +## [2.6.1] - 2016-05-31 + +### Changed +- The PHP-supplied T_COALESCE token has been replicated for PHP versions before 7.0 +- Function return types of self, parent and callable are now tokenized as T_RETURN_TYPE + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- The default_standard config setting now allows multiple standards to be listed, like on the command line + - Thanks to [Michael Mayer][@schnittstabil] for the patch +- Installations done via composer now only include the composer autoloader for PHP 5.3.2+ (request [#942][sq-942]) +- Added a rollbackChangeset() method to the Fixer class to purposely rollback the active changeset + +### Fixed +- Fixed bug [#940][sq-940] : Auto-fixing issue encountered with inconsistent use of braces +- Fixed bug [#943][sq-943] : Squiz.PHP.InnerFunctions.NotAllowed reported in anonymous classes +- Fixed bug [#944][sq-944] : PHP warning when running the latest phar +- Fixed bug [#951][sq-951] : InlineIfDeclaration: invalid error produced with UTF-8 string +- Fixed bug [#957][sq-957] : Operator spacing sniff errors when plus is used as part of a number + - Thanks to [Klaus Purer][@klausi] for the patch +- Fixed bug [#959][sq-959] : Call-time pass-by-reference false positive if there is a square bracket before the ampersand + - Thanks to [Konstantin Leboev][@realmfoo] for the patch +- Fixed bug [#962][sq-962] : Null coalescing operator (??) not detected as a token + - Thanks to [Joel Posti][@joelposti] for the patch +- Fixed bug [#973][sq-973] : Anonymous class declaration and PSR1.Files.SideEffects.FoundWithSymbols +- Fixed bug [#974][sq-974] : Error when file ends with "function" +- Fixed bug [#979][sq-979] : Anonymous function with return type hint is not refactored as expected +- Fixed bug [#983][sq-983] : Squiz.WhiteSpace.MemberVarSpacing.AfterComment fails to fix error when comment is not a docblock +- Fixed bug [#1010][sq-1010] : Squiz NonExecutableCode sniff does not detect boolean OR + - Thanks to [Derek Henderson][@2shediac] for the patch +- Fixed bug [#1015][sq-1015] : The Squiz.Commenting.FunctionComment sniff doesn't allow description in @return tag + - Thanks to [Alexander Obuhovich][@aik099] for the patch +- Fixed bug [#1022][sq-1022] : Duplicate spaces after opening bracket error with PSR2 standard +- Fixed bug [#1025][sq-1025] : Syntax error in JS file can cause undefined index for parenthesis_closer + +[sq-940]: https://github.com/squizlabs/PHP_CodeSniffer/issues/940 +[sq-942]: https://github.com/squizlabs/PHP_CodeSniffer/issues/942 +[sq-943]: https://github.com/squizlabs/PHP_CodeSniffer/issues/943 +[sq-944]: https://github.com/squizlabs/PHP_CodeSniffer/issues/944 +[sq-951]: https://github.com/squizlabs/PHP_CodeSniffer/issues/951 +[sq-957]: https://github.com/squizlabs/PHP_CodeSniffer/pull/957 +[sq-959]: https://github.com/squizlabs/PHP_CodeSniffer/issues/959 +[sq-962]: https://github.com/squizlabs/PHP_CodeSniffer/issues/962 +[sq-973]: https://github.com/squizlabs/PHP_CodeSniffer/issues/973 +[sq-974]: https://github.com/squizlabs/PHP_CodeSniffer/issues/974 +[sq-979]: https://github.com/squizlabs/PHP_CodeSniffer/issues/979 +[sq-983]: https://github.com/squizlabs/PHP_CodeSniffer/issues/983 +[sq-1010]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1010 +[sq-1015]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1015 +[sq-1022]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1022 +[sq-1025]: https://github.com/squizlabs/PHP_CodeSniffer/issues/1025 + +## [2.6.0] - 2016-04-04 + +### Changed +- Paths used when setting CLI arguments inside ruleset.xml files are now relative to the ruleset location (request [#847][sq-847]) + - This change only applies to paths within ARG tags, used to set CLI arguments + - Previously, the paths were relative to the directory PHPCS was being run from + - Absolute paths are still allowed and work the same way they always have + - This change allows ruleset.xml files to be more portable +- Content passed via STDIN will now be processed even if files are specified on the command line or in a ruleset +- When passing content via STDIN, you can now specify the file path to use on the command line (request [#934][sq-934]) + - This allows sniffs that check file paths to work correctly + - This is the same functionality provided by the phpcs_input_file line, except it is available on the command line +- Files processed with custom tokenizers will no longer be skipped if they appear minified (request [#877][sq-877]) + - If the custom tokenizer wants minified files skipped, it can set a $skipMinified member var to TRUE + - See the included JS and CSS tokenizers for an example +- Config vars set in ruleset.xml files are now processed earlier, allowing them to be used during sniff registration + - Among other things, this allows the installed_paths config var to be set in ruleset.xml files + - Thanks to [Pieter Frenssen][@pfrenssen] for the patch +- Improved detection of regular expressions in the JS tokenizer +- Generic PHP Syntax sniff now uses PHP_BINARY (if available) to determine the path to PHP if no other path is available + - You can still manually set `php_path` to use a specific binary for testing + - Thanks to [Andrew Berry][@deviantintegral] for the patch +- The PHP-supplied T_POW_EQUAL token has been replicated for PHP versions before 5.6 +- Added support for PHP7 use group declarations (request [#878][sq-878]) + - New tokens T_OPEN_USE_GROUP and T_CLOSE_USE_GROUP are assigned to the open and close curly braces +- Generic ScopeIndent sniff now reports errors for every line that needs the indent changed (request [#903][sq-903]) + - Previously, it ignored lines that were indented correctly in the context of their block + - This change produces more technically accurate error messages, but is much more verbose +- The PSR2 and Squiz standards now allow multi-line default values in function declarations (request [#542][sq-542]) + - Previously, these would automatically make the function a multi-line declaration +- Squiz InlineCommentSniff now allows docblocks on require(_once) and include(_once) statements + - Thanks to [Gary Jones][@GaryJones] for the patch +- Squiz and PEAR Class and File sniffs no longer assume the first comment in a file is always a file comment + - phpDocumentor assigns the comment to the file only if it is not followed by a structural element + - These sniffs now follow this same rule +- Squiz ClassCommentSniff no longer checks for blank lines before class comments + - Removes the error Squiz.Commenting.ClassComment.SpaceBefore +- Renamed Squiz.CSS.Opacity.SpacingAfterPoint to Squiz.CSS.Opacity.DecimalPrecision + - Please update your ruleset if you are referencing this error code directly +- Fixed PHP tokenizer problem that caused an infinite loop when checking a comment with specific content +- Generic Disallow Space and Tab indent sniffs now detect and fix indents inside embedded HTML chunks (request [#882][sq-882]) +- Squiz CSS IndentationSniff no longer assumes the class opening brace is at the end of a line +- Squiz FunctionCommentThrowTagSniff now ignores non-docblock comments +- Squiz ComparisonOperatorUsageSniff now allows conditions like while(true) +- PEAR FunctionCallSignatureSniff (and the Squiz and PSR2 sniffs that use it) now correctly check the first argument + - Further fix for bug [#698][sq-698] + +### Fixed +- Fixed bug [#791][sq-791] : codingStandardsChangeSetting settings not working with namespaces +- Fixed bug [#872][sq-872] : Incorrect detection of blank lines between CSS class names +- Fixed bug [#879][sq-879] : Generic InlineControlStructureSniff can create parse error when case/if/elseif/else have mixed brace and braceless definitions +- Fixed bug [#883][sq-883] : PSR2 is not checking for blank lines at the start and end of control structures +- Fixed bug [#884][sq-884] : Incorrect indentation notice for anonymous classes +- Fixed bug [#887][sq-887] : Using curly braces for a shared CASE/DEFAULT statement can generate an error in PSR2 SwitchDeclaration +- Fixed bug [#889][sq-889] : Closure inside catch/else/elseif causes indentation error +- Fixed bug [#890][sq-890] : Function call inside returned short array value can cause indentation error inside CASE statements +- Fixed bug [#897][sq-897] : Generic.Functions.CallTimePassByReference.NotAllowed false positive when short array syntax +- Fixed bug [#900][sq-900] : Squiz.Functions.FunctionDeclarationArgumentSpacing bug when no space between type hint and argument +- Fixed bug [#902][sq-902] : T_OR_EQUAL and T_POW_EQUAL are not seen as assignment tokens +- Fixed bug [#910][sq-910] : Unrecognized "extends" and indentation on anonymous classes +- Fixed bug [#915][sq-915] : JS Tokenizer generates errors when processing some decimals +- Fixed bug [#928][sq-928] : Endless loop when sniffing a PHP file with a git merge conflict inside a function +- Fixed bug [#937][sq-937] : Shebang can cause PSR1 SideEffects warning + - Thanks to [Clay Loveless][@claylo] for the patch +- Fixed bug [#938][sq-938] : CallTimePassByReferenceSniff ignores functions with return value + +[sq-542]: https://github.com/squizlabs/PHP_CodeSniffer/issues/542 +[sq-791]: https://github.com/squizlabs/PHP_CodeSniffer/issues/791 +[sq-847]: https://github.com/squizlabs/PHP_CodeSniffer/issues/847 +[sq-872]: https://github.com/squizlabs/PHP_CodeSniffer/issues/872 +[sq-877]: https://github.com/squizlabs/PHP_CodeSniffer/issues/877 +[sq-878]: https://github.com/squizlabs/PHP_CodeSniffer/issues/878 +[sq-879]: https://github.com/squizlabs/PHP_CodeSniffer/issues/879 +[sq-882]: https://github.com/squizlabs/PHP_CodeSniffer/issues/882 +[sq-883]: https://github.com/squizlabs/PHP_CodeSniffer/issues/883 +[sq-884]: https://github.com/squizlabs/PHP_CodeSniffer/issues/884 +[sq-887]: https://github.com/squizlabs/PHP_CodeSniffer/issues/887 +[sq-889]: https://github.com/squizlabs/PHP_CodeSniffer/issues/889 +[sq-890]: https://github.com/squizlabs/PHP_CodeSniffer/issues/890 +[sq-897]: https://github.com/squizlabs/PHP_CodeSniffer/issues/897 +[sq-900]: https://github.com/squizlabs/PHP_CodeSniffer/issues/900 +[sq-902]: https://github.com/squizlabs/PHP_CodeSniffer/issues/902 +[sq-903]: https://github.com/squizlabs/PHP_CodeSniffer/issues/903 +[sq-910]: https://github.com/squizlabs/PHP_CodeSniffer/issues/910 +[sq-915]: https://github.com/squizlabs/PHP_CodeSniffer/issues/915 +[sq-928]: https://github.com/squizlabs/PHP_CodeSniffer/issues/928 +[sq-934]: https://github.com/squizlabs/PHP_CodeSniffer/issues/934 +[sq-937]: https://github.com/squizlabs/PHP_CodeSniffer/pull/937 +[sq-938]: https://github.com/squizlabs/PHP_CodeSniffer/issues/938 + +## [2.5.1] - 2016-01-20 + +### Changed +- The PHP-supplied T_SPACESHIP token has been replicated for PHP versions before 7.0 +- T_SPACESHIP is now correctly identified as an operator + - Thanks to [Alexander Obuhovich][@aik099] for the patch +- Generic LowerCaseKeyword now ensures array type hints are lowercase as well + - Thanks to [Mathieu Rochette][@mathroc] for the patch +- Squiz ComparisonOperatorUsageSniff no longer hangs on JS FOR loops that don't use semicolons +- PHP_CodesSniffer now includes the composer `autoload.php` file, if there is one + - Thanks to [Klaus Purer][@klausi] for the patch +- Added error Squiz.Commenting.FunctionComment.ScalarTypeHintMissing for PHP7 only (request [#858][sq-858]) + - These errors were previously reported as Squiz.Commenting.FunctionComment.TypeHintMissing on PHP7 + - Disable this error message in a ruleset.xml file if your code needs to run on both PHP5 and PHP7 +- The PHP 5.6 __debugInfo magic method no longer produces naming convention errors + - Thanks to [Michael Nowack][@syranez] for the patch +- PEAR and Squiz FunctionComment sniffs now support variadic functions (request [#841][sq-841]) + +### Fixed +- Fixed bug [#622][sq-622] : Wrong detection of Squiz.CSS.DuplicateStyleDefinition with media queries +- Fixed bug [#752][sq-752] : The missing exception error is reported in first found DocBlock +- Fixed bug [#794][sq-794] : PSR2 MultiLineFunctionDeclaration forbids comments after opening parenthesis of a multiline call +- Fixed bug [#820][sq-820] : PEAR/PSR2 FunctionCallSignature sniffs suggest wrong indent when there are multiple arguments on a line +- Fixed bug [#822][sq-822] : Ruleset hard-coded file paths are not used if not running from the same directory as the ruleset +- Fixed bug [#825][sq-825] : FunctionCallArgumentSpacing sniff complains about more than one space before comment in multi-line function call +- Fixed bug [#828][sq-828] : Null classname is tokenized as T_NULL instead of T_STRING +- Fixed bug [#829][sq-829] : Short array argument not fixed correctly when multiple function arguments are on the same line +- Fixed bug [#831][sq-831] : PHPCS freezes in an infinite loop under Windows if no standard is passed +- Fixed bug [#832][sq-832] : Tokenizer does not support context sensitive parsing + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#835][sq-835] : PEAR.Functions.FunctionCallSignature broken when closure uses return types +- Fixed bug [#838][sq-838] : CSS indentation fixer changes color codes + - Thanks to [Klaus Purer][@klausi] for the patch +- Fixed bug [#839][sq-839] : "__()" method is marked as not camel caps + - Thanks to [Tim Bezhashvyly][@tim-bezhashvyly] for the patch +- Fixed bug [#852][sq-852] : Generic.Commenting.DocComment not finding errors when long description is omitted +- Fixed bug [#854][sq-854] : Return typehints in interfaces are not reported as T_RETURN_TYPE + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#855][sq-855] : Capital letter detection for multibyte strings doesn't work correctly +- Fixed bug [#857][sq-857] : PSR2.ControlStructure.SwitchDeclaration shouldn't check indent of curly brace closers +- Fixed bug [#859][sq-859] : Switch statement indention issue when returning function call with closure +- Fixed bug [#861][sq-861] : Single-line arrays and function calls can generate incorrect indentation errors +- Fixed bug [#867][sq-867] : Squiz.Strings.DoubleQuoteUsage broken for some escape codes + - Thanks to [Jack Blower][@ElvenSpellmaker] for the help with the fix +- Fixed bug [#21005][pear-21005] : Incorrect indent detection when multiple properties are initialized to arrays +- Fixed bug [#21010][pear-21010] : Incorrect missing colon detection in CSS when first style is not on new line +- Fixed bug [#21011][pear-21011] : Incorrect error message text when newline found after opening brace + +[sq-622]: https://github.com/squizlabs/PHP_CodeSniffer/issues/622 +[sq-752]: https://github.com/squizlabs/PHP_CodeSniffer/issues/752 +[sq-794]: https://github.com/squizlabs/PHP_CodeSniffer/issues/794 +[sq-820]: https://github.com/squizlabs/PHP_CodeSniffer/issues/820 +[sq-822]: https://github.com/squizlabs/PHP_CodeSniffer/issues/822 +[sq-825]: https://github.com/squizlabs/PHP_CodeSniffer/issues/825 +[sq-828]: https://github.com/squizlabs/PHP_CodeSniffer/issues/828 +[sq-829]: https://github.com/squizlabs/PHP_CodeSniffer/issues/829 +[sq-831]: https://github.com/squizlabs/PHP_CodeSniffer/issues/831 +[sq-832]: https://github.com/squizlabs/PHP_CodeSniffer/issues/832 +[sq-835]: https://github.com/squizlabs/PHP_CodeSniffer/issues/835 +[sq-838]: https://github.com/squizlabs/PHP_CodeSniffer/pull/838 +[sq-839]: https://github.com/squizlabs/PHP_CodeSniffer/issues/839 +[sq-841]: https://github.com/squizlabs/PHP_CodeSniffer/issues/841 +[sq-852]: https://github.com/squizlabs/PHP_CodeSniffer/issues/852 +[sq-854]: https://github.com/squizlabs/PHP_CodeSniffer/issues/854 +[sq-855]: https://github.com/squizlabs/PHP_CodeSniffer/pull/855 +[sq-857]: https://github.com/squizlabs/PHP_CodeSniffer/issues/857 +[sq-858]: https://github.com/squizlabs/PHP_CodeSniffer/issues/858 +[sq-859]: https://github.com/squizlabs/PHP_CodeSniffer/issues/859 +[sq-861]: https://github.com/squizlabs/PHP_CodeSniffer/issues/861 +[sq-867]: https://github.com/squizlabs/PHP_CodeSniffer/issues/867 +[pear-21005]: https://pear.php.net/bugs/bug.php?id=21005 +[pear-21010]: https://pear.php.net/bugs/bug.php?id=21010 +[pear-21011]: https://pear.php.net/bugs/bug.php?id=21011 + +## [2.5.0] - 2015-12-11 + +### Changed +- PHPCS will now look for a phpcs.xml file in parent directories as well as the current directory (request [#626][sq-626]) +- PHPCS will now use a phpcs.xml file even if files are specified on the command line + - This file is still only used if no standard is specified on the command line +- Added support for a phpcs.xml.dist file (request [#583][sq-583]) + - If both a phpcs.xml and phpcs.xml.dist file are present, the phpcs.xml file will be used +- Added support for setting PHP ini values in ruleset.xml files (request [#560][sq-560]) + - Setting the value of the new ini tags to name="memory_limit" value="32M" is the same as -d memory_limit=32M +- Added support for one or more bootstrap files to be run before processing begins + - Use the --bootstrap=file,file,file command line argument to include bootstrap files + - Useful if you want to override some of the high-level settings of PHPCS or PHPCBF + - Thanks to [John Maguire][@johnmaguire] for the patch +- Added additional verbose output for CSS tokenizing +- Squiz ComparisonOperatorUsageSniff now checks FOR, WHILE and DO-WHILE statements + - Thanks to [Arnout Boks][@aboks] for the patch + +### Fixed +- Fixed bug [#660][sq-660] : Syntax checks can fail on Windows with PHP5.6 +- Fixed bug [#784][sq-784] : $this->trait is seen as a T_TRAIT token +- Fixed bug [#786][sq-786] : Switch indent issue with short array notation +- Fixed bug [#787][sq-787] : SpacingAfterDefaultBreak confused by multi-line statements +- Fixed bug [#797][sq-797] : Parsing CSS url() value breaks further parsing +- Fixed bug [#805][sq-805] : Squiz.Commenting.FunctionComment.InvalidTypeHint on Scalar types on PHP7 +- Fixed bug [#807][sq-807] : Cannot fix line endings when open PHP tag is not on the first line +- Fixed bug [#808][sq-808] : JS tokenizer incorrectly setting some function and class names to control structure tokens +- Fixed bug [#809][sq-809] : PHPCBF can break a require_once statement with a space before the open parenthesis +- Fixed bug [#813][sq-813] : PEAR FunctionCallSignature checks wrong indent when first token on line is part of a multi-line string + +[sq-560]: https://github.com/squizlabs/PHP_CodeSniffer/issues/560 +[sq-583]: https://github.com/squizlabs/PHP_CodeSniffer/issues/583 +[sq-626]: https://github.com/squizlabs/PHP_CodeSniffer/issues/626 +[sq-660]: https://github.com/squizlabs/PHP_CodeSniffer/pull/660 +[sq-784]: https://github.com/squizlabs/PHP_CodeSniffer/issues/784 +[sq-786]: https://github.com/squizlabs/PHP_CodeSniffer/issues/786 +[sq-787]: https://github.com/squizlabs/PHP_CodeSniffer/issues/787 +[sq-797]: https://github.com/squizlabs/PHP_CodeSniffer/issues/797 +[sq-805]: https://github.com/squizlabs/PHP_CodeSniffer/issues/805 +[sq-807]: https://github.com/squizlabs/PHP_CodeSniffer/issues/807 +[sq-808]: https://github.com/squizlabs/PHP_CodeSniffer/issues/808 +[sq-809]: https://github.com/squizlabs/PHP_CodeSniffer/issues/809 +[sq-813]: https://github.com/squizlabs/PHP_CodeSniffer/issues/813 + +## [2.4.0] - 2015-11-24 + +### Changed +- Added support for PHP 7 anonymous classes + - Anonymous classes are now tokenized as T_ANON_CLASS and ignored by normal class sniffs +- Added support for PHP 7 function return type declarations + - Return types are now tokenized as T_RETURN_TYPE +- Fixed tokenizing of the XOR operator, which was incorrectly identified as a power operator (bug [#765][sq-765]) + - The T_POWER token has been removed and replaced by the T_BITWISE_XOR token + - The PHP-supplied T_POW token has been replicated for PHP versions before 5.6 +- Traits are now tokenized in PHP versions before 5.4 to make testing easier +- Improved regular expression detection in JS files +- PEAR FunctionCallSignatureSniff now properly detects indents in more mixed HTML/PHP code blocks +- Full report now properly indents lines when newlines are found inside error messages +- Generating documentation without specifying a standard now uses the default standard instead + - Thanks to [Ken Guest][@kenguest] for the patch +- Generic InlineControlStructureSniff now supports braceless do/while loops in JS + - Thanks to [Pieter Frenssen][@pfrenssen] for the patch +- Added more guard code for function declarations with syntax errors + - Thanks to Yun Young-jin for the patch +- Added more guard code for foreach declarations with syntax errors + - Thanks to [Johan de Ruijter][@johanderuijter] for the patch +- Added more guard code for class declarations with syntax errors +- Squiz ArrayDeclarationSniff now has guard code for arrays with syntax errors +- Generic InlineControlStructureSniff now correctly fixes ELSEIF statements + +### Fixed +- Fixed bug [#601][sq-601] : Expected type hint int[]; found array in Squiz FunctionCommentSniff + - Thanks to [Scato Eggen][@scato] for the patch +- Fixed bug [#625][sq-625] : Consider working around T_HASHBANG in HHVM 3.5.x and 3.6.x + - Thanks to [Kunal Mehta][@legoktm] for the patch +- Fixed bug [#692][sq-692] : Comment tokenizer can break when using mbstring function overloading +- Fixed bug [#694][sq-694] : Long sniff codes can cause PHP warnings in source report when showing error codes +- Fixed bug [#698][sq-698] : PSR2.Methods.FunctionCallSignature.Indent forces exact indent of ternary operator parameters +- Fixed bug [#704][sq-704] : ScopeIndent can fail when an opening parenthesis is on a line by itself +- Fixed bug [#707][sq-707] : Squiz MethodScopeSniff doesn't handle nested functions +- Fixed bug [#709][sq-709] : Squiz.Sniffs.Whitespace.ScopeClosingBraceSniff marking indented endif in mixed inline HTML blocks +- Fixed bug [#711][sq-711] : Sniffing from STDIN shows Generic.Files.LowercasedFilename.NotFound error +- Fixed bug [#714][sq-714] : Fixes suppression of errors using docblocks + - Thanks to [Andrzej Karmazyn][@akarmazyn] for the patch +- Fixed bug [#716][sq-716] : JSON report is invalid when messages contain newlines or tabs + - Thanks to [Pieter Frenssen][@pfrenssen] for the patch +- Fixed bug [#723][sq-723] : ScopeIndent can fail when multiple array closers are on the same line +- Fixed bug [#730][sq-730] : ScopeIndent can fail when a short array opening square bracket is on a line by itself +- Fixed bug [#732][sq-732] : PHP Notice if @package name is made up of all invalid characters + - Adds new error code PEAR.Commenting.FileComment.InvalidPackageValue +- Fixed bug [#748][sq-748] : Auto fix for Squiz.Commenting.BlockComment.WrongEnd is incorrect + - Thanks to [J.D. Grimes][@JDGrimes] for the patch +- Fixed bug [#753][sq-753] : PSR2 standard shouldn't require space after USE block when next code is a closing tag +- Fixed bug [#768][sq-768] : PEAR FunctionCallSignature sniff forbids comments after opening parenthesis of a multiline call +- Fixed bug [#769][sq-769] : Incorrect detection of variable reference operator when used with short array syntax + - Thanks to [Klaus Purer][@klausi] for the patch +- Fixed bug [#772][sq-772] : Syntax error when using PHPCBF on alternative style foreach loops +- Fixed bug [#773][sq-773] : Syntax error when stripping trailing PHP close tag and previous statement has no semicolon +- Fixed bug [#778][sq-778] : PHPCBF creates invalid PHP for inline FOREACH containing multiple control structures +- Fixed bug [#781][sq-781] : Incorrect checking for PHP7 return types on multi-line function declarations +- Fixed bug [#782][sq-782] : Conditional function declarations cause fixing conflicts in Squiz standard + - Squiz.ControlStructures.ControlSignature no longer enforces a single newline after open brace + - Squiz.WhiteSpace.ControlStructureSpacing can be used to check spacing at the start/end of control structures + +[sq-601]: https://github.com/squizlabs/PHP_CodeSniffer/issues/601 +[sq-625]: https://github.com/squizlabs/PHP_CodeSniffer/issues/625 +[sq-692]: https://github.com/squizlabs/PHP_CodeSniffer/pull/692 +[sq-694]: https://github.com/squizlabs/PHP_CodeSniffer/issues/694 +[sq-698]: https://github.com/squizlabs/PHP_CodeSniffer/issues/698 +[sq-704]: https://github.com/squizlabs/PHP_CodeSniffer/issues/704 +[sq-707]: https://github.com/squizlabs/PHP_CodeSniffer/pull/707 +[sq-709]: https://github.com/squizlabs/PHP_CodeSniffer/issues/709 +[sq-711]: https://github.com/squizlabs/PHP_CodeSniffer/issues/711 +[sq-714]: https://github.com/squizlabs/PHP_CodeSniffer/pull/714 +[sq-716]: https://github.com/squizlabs/PHP_CodeSniffer/pull/716 +[sq-723]: https://github.com/squizlabs/PHP_CodeSniffer/issues/723 +[sq-730]: https://github.com/squizlabs/PHP_CodeSniffer/pull/730 +[sq-732]: https://github.com/squizlabs/PHP_CodeSniffer/pull/732 +[sq-748]: https://github.com/squizlabs/PHP_CodeSniffer/pull/748 +[sq-753]: https://github.com/squizlabs/PHP_CodeSniffer/issues/753 +[sq-765]: https://github.com/squizlabs/PHP_CodeSniffer/issues/765 +[sq-768]: https://github.com/squizlabs/PHP_CodeSniffer/issues/768 +[sq-769]: https://github.com/squizlabs/PHP_CodeSniffer/pull/769 +[sq-772]: https://github.com/squizlabs/PHP_CodeSniffer/issues/772 +[sq-773]: https://github.com/squizlabs/PHP_CodeSniffer/issues/773 +[sq-778]: https://github.com/squizlabs/PHP_CodeSniffer/issues/778 +[sq-781]: https://github.com/squizlabs/PHP_CodeSniffer/issues/781 +[sq-782]: https://github.com/squizlabs/PHP_CodeSniffer/issues/782 + +## [2.3.4] - 2015-09-09 + +### Changed +- JSON report format now includes the fixable status for each error message and the total number of fixable errors +- Added more guard code for function declarations with syntax errors +- Added tokenizer support for the PHP declare construct + - Thanks to [Andy Blyler][@ablyler] for the patch +- Generic UnnecessaryStringConcatSniff can now allow strings concatenated over multiple lines + - Set the allowMultiline property to TRUE (default is FALSE) in your ruleset.xml file to enable this + - By default, concat used only for getting around line length limits still generates an error + - Thanks to [Stefan Lenselink][@stefanlenselink] for the contribution +- Invalid byte sequences no longer throw iconv_strlen() errors (request [#639][sq-639]) + - Thanks to [Willem Stuursma][@willemstuursma] for the patch +- Generic TodoSniff and FixmeSniff are now better at processing strings with invalid characters +- PEAR FunctionCallSignatureSniff now ignores indentation of inline HTML content +- Squiz ControlSignatureSniff now supports control structures with only inline HTML content + +### Fixed +- Fixed bug [#636][sq-636] : Some class names cause CSS tokenizer to hang +- Fixed bug [#638][sq-638] : VCS blame reports output error content from the blame commands for files not under VC +- Fixed bug [#642][sq-642] : Method params incorrectly detected when default value uses short array syntax + - Thanks to [Josh Davis][@joshdavis11] for the patch +- Fixed bug [#644][sq-644] : PEAR ScopeClosingBrace sniff does not work with mixed HTML/PHP +- Fixed bug [#645][sq-645] : FunctionSignature and ScopeIndent sniffs don't detect indents correctly when PHP open tag is not on a line by itself +- Fixed bug [#648][sq-648] : Namespace not tokenized correctly when followed by multiple use statements +- Fixed bug [#654][sq-654] : Comments affect indent check for BSDAllman brace style +- Fixed bug [#658][sq-658] : Squiz.Functions.FunctionDeclarationSpacing error for multi-line declarations with required spaces greater than zero + - Thanks to [J.D. Grimes][@JDGrimes] for the patch +- Fixed bug [#663][sq-663] : No space after class name generates: Class name "" is not in camel caps format +- Fixed bug [#667][sq-667] : Scope indent check can go into infinite loop due to some parse errors +- Fixed bug [#670][sq-670] : Endless loop in PSR1 SideEffects sniffer if no semicolon after last statement + - Thanks to [Thomas Jarosch][@thomasjfox] for the patch +- Fixed bug [#672][sq-672] : Call-time pass-by-reference false positive +- Fixed bug [#683][sq-683] : Comments are incorrectly reported by PSR2.ControlStructures.SwitchDeclaration sniff +- Fixed bug [#687][sq-687] : ScopeIndent does not check indent correctly for method prefixes like public and abstract +- Fixed bug [#689][sq-689] : False error on some comments after class closing brace + +[sq-636]: https://github.com/squizlabs/PHP_CodeSniffer/issues/636 +[sq-638]: https://github.com/squizlabs/PHP_CodeSniffer/issues/638 +[sq-639]: https://github.com/squizlabs/PHP_CodeSniffer/pull/639 +[sq-642]: https://github.com/squizlabs/PHP_CodeSniffer/pull/642 +[sq-644]: https://github.com/squizlabs/PHP_CodeSniffer/issues/644 +[sq-645]: https://github.com/squizlabs/PHP_CodeSniffer/issues/645 +[sq-648]: https://github.com/squizlabs/PHP_CodeSniffer/issues/648 +[sq-654]: https://github.com/squizlabs/PHP_CodeSniffer/issues/654 +[sq-658]: https://github.com/squizlabs/PHP_CodeSniffer/pull/658 +[sq-663]: https://github.com/squizlabs/PHP_CodeSniffer/issues/663 +[sq-667]: https://github.com/squizlabs/PHP_CodeSniffer/issues/667 +[sq-670]: https://github.com/squizlabs/PHP_CodeSniffer/pull/670 +[sq-672]: https://github.com/squizlabs/PHP_CodeSniffer/issues/672 +[sq-683]: https://github.com/squizlabs/PHP_CodeSniffer/issues/683 +[sq-687]: https://github.com/squizlabs/PHP_CodeSniffer/issues/687 +[sq-689]: https://github.com/squizlabs/PHP_CodeSniffer/issues/689 + +## [2.3.3] - 2015-06-24 + +### Changed +- Improved the performance of the CSS tokenizer, especially on very large CSS files (thousands of lines) + - Thanks to [Klaus Purer][@klausi] for the patch +- Defined tokens for lower PHP versions are now phpcs-specific strings instead of ints + - Stops conflict with other projects, like PHP_CodeCoverage +- Added more guard code for syntax errors to various sniffs +- Improved support for older HHVM versions + - Thanks to [Kunal Mehta][@legoktm] for the patch +- Squiz ValidLogicalOperatorsSniff now ignores XOR as type casting is different when using the ^ operator (request [#567][sq-567]) +- Squiz CommentedOutCodeSniff is now better at ignoring URLs inside comments +- Squiz ControlSignatureSniff is now better at checking embedded PHP code +- Squiz ScopeClosingBraceSniff is now better at checking embedded PHP code + +### Fixed +- Fixed bug [#584][sq-584] : Squiz.Arrays.ArrayDeclaration sniff gives incorrect NoComma error for multiline string values +- Fixed bug [#589][sq-589] : PEAR.Functions.FunctionCallSignature sniff not checking all function calls +- Fixed bug [#592][sq-592] : USE statement tokenizing can sometimes result in mismatched scopes +- Fixed bug [#594][sq-594] : Tokenizer issue on closure that returns by reference +- Fixed bug [#595][sq-595] : Colons in CSS selectors within media queries throw false positives + - Thanks to [Klaus Purer][@klausi] for the patch +- Fixed bug [#598][sq-598] : PHPCBF can break function/use closure brace placement +- Fixed bug [#603][sq-603] : Squiz ControlSignatureSniff hard-codes opener type while fixing +- Fixed bug [#605][sq-605] : Auto report-width specified in ruleset.xml ignored +- Fixed bug [#611][sq-611] : Invalid numeric literal on CSS files under PHP7 +- Fixed bug [#612][sq-612] : Multi-file diff generating incorrectly if files do not end with EOL char +- Fixed bug [#615][sq-615] : Squiz OperatorBracketSniff incorrectly reports and fixes operations using self:: +- Fixed bug [#616][sq-616] : Squiz DisallowComparisonAssignmentSniff inconsistent errors with inline IF statements +- Fixed bug [#617][sq-617] : Space after switch keyword in PSR-2 is not being enforced +- Fixed bug [#621][sq-621] : PSR2 SwitchDeclaration sniff doesn't detect, or correctly fix, case body on same line as statement + +[sq-567]: https://github.com/squizlabs/PHP_CodeSniffer/issues/567 +[sq-584]: https://github.com/squizlabs/PHP_CodeSniffer/issues/584 +[sq-589]: https://github.com/squizlabs/PHP_CodeSniffer/issues/589 +[sq-592]: https://github.com/squizlabs/PHP_CodeSniffer/issues/592 +[sq-594]: https://github.com/squizlabs/PHP_CodeSniffer/issues/594 +[sq-595]: https://github.com/squizlabs/PHP_CodeSniffer/pull/595 +[sq-598]: https://github.com/squizlabs/PHP_CodeSniffer/issues/598 +[sq-603]: https://github.com/squizlabs/PHP_CodeSniffer/issues/603 +[sq-605]: https://github.com/squizlabs/PHP_CodeSniffer/issues/605 +[sq-611]: https://github.com/squizlabs/PHP_CodeSniffer/issues/611 +[sq-612]: https://github.com/squizlabs/PHP_CodeSniffer/issues/612 +[sq-615]: https://github.com/squizlabs/PHP_CodeSniffer/issues/615 +[sq-616]: https://github.com/squizlabs/PHP_CodeSniffer/issues/616 +[sq-617]: https://github.com/squizlabs/PHP_CodeSniffer/issues/617 +[sq-621]: https://github.com/squizlabs/PHP_CodeSniffer/issues/621 + +## [2.3.2] - 2015-04-29 + +### Changed +- The error message for PSR2.ControlStructures.SwitchDeclaration.WrongOpenercase is now clearer (request [#579][sq-579]) + +### Fixed +- Fixed bug [#545][sq-545] : Long list of CASE statements can cause tokenizer to reach a depth limit +- Fixed bug [#565][sq-565] : Squiz.WhiteSpace.OperatorSpacing reports negative number in short array + - Thanks to [VaÅ¡ek Purchart][@VasekPurchart] for the patch + - Same fix also applied to Squiz.Formatting.OperatorBracket +- Fixed bug [#569][sq-569] : Generic ScopeIndentSniff throws PHP notices in JS files +- Fixed bug [#570][sq-570] : Phar class fatals in PHP less than 5.3 + +[sq-545]: https://github.com/squizlabs/PHP_CodeSniffer/issues/545 +[sq-565]: https://github.com/squizlabs/PHP_CodeSniffer/pull/565 +[sq-569]: https://github.com/squizlabs/PHP_CodeSniffer/pull/569 +[sq-570]: https://github.com/squizlabs/PHP_CodeSniffer/issues/570 +[sq-579]: https://github.com/squizlabs/PHP_CodeSniffer/issues/579 + +## [2.3.1] - 2015-04-23 + +### Changed +- PHPCS can now exit with 0 even if errors are found + - Set the ignore_errors_on_exit config variable to 1 to set this behaviour + - Use with the ignore_warnings_on_exit config variable to never return a non-zero exit code +- Added Generic DisallowLongArraySyntaxSniff to enforce the use of the PHP short array syntax (request [#483][sq-483]) + - Thanks to [Xaver Loppenstedt][@xalopp] for helping with tests +- Added Generic DisallowShortArraySyntaxSniff to ban the use of the PHP short array syntax (request [#483][sq-483]) + - Thanks to [Xaver Loppenstedt][@xalopp] for helping with tests +- Generic ScopeIndentSniff no longer does exact checking for content inside parenthesis (request [#528][sq-528]) + - Only applies to custom coding standards that set the "exact" flag to TRUE +- Squiz ConcatenationSpacingSniff now has a setting to ignore newline characters around operators (request [#511][sq-511]) + - Default remains FALSE, so newlines are not allowed + - Override the "ignoreNewlines" setting in a ruleset.xml file to change +- Squiz InlineCommentSniff no longer checks the last char of a comment if the first char is not a letter (request [#505][sq-505]) +- The Squiz standard has increased the max padding for statement alignment from 12 to 20 + +### Fixed +- Fixed bug [#479][sq-479] : Yielded values are not recognised as returned values in Squiz FunctionComment sniff +- Fixed bug [#512][sq-512] : Endless loop whilst parsing mixture of control structure styles +- Fixed bug [#515][sq-515] : Spaces in JS block incorrectly flagged as indentation error +- Fixed bug [#523][sq-523] : Generic ScopeIndent errors for IF in FINALLY +- Fixed bug [#527][sq-527] : Closure inside IF statement is not tokenized correctly +- Fixed bug [#529][sq-529] : Squiz.Strings.EchoedStrings gives false positive when echoing using an inline condition +- Fixed bug [#537][sq-537] : Using --config-set is breaking phpcs.phar +- Fixed bug [#543][sq-543] : SWITCH with closure in condition generates inline control structure error +- Fixed bug [#551][sq-551] : Multiple catch blocks not checked in Squiz.ControlStructures.ControlSignature sniff +- Fixed bug [#554][sq-554] : ScopeIndentSniff causes errors when encountering an unmatched parenthesis +- Fixed bug [#558][sq-558] : PHPCBF adds brace for ELSE IF split over multiple lines +- Fixed bug [#564][sq-564] : Generic MultipleStatementAlignment sniff reports incorrect errors for multiple assignments on a single line + +[sq-479]: https://github.com/squizlabs/PHP_CodeSniffer/issues/479 +[sq-483]: https://github.com/squizlabs/PHP_CodeSniffer/issues/483 +[sq-505]: https://github.com/squizlabs/PHP_CodeSniffer/issues/505 +[sq-511]: https://github.com/squizlabs/PHP_CodeSniffer/issues/511 +[sq-512]: https://github.com/squizlabs/PHP_CodeSniffer/issues/512 +[sq-515]: https://github.com/squizlabs/PHP_CodeSniffer/issues/515 +[sq-523]: https://github.com/squizlabs/PHP_CodeSniffer/issues/523 +[sq-527]: https://github.com/squizlabs/PHP_CodeSniffer/issues/527 +[sq-528]: https://github.com/squizlabs/PHP_CodeSniffer/issues/528 +[sq-529]: https://github.com/squizlabs/PHP_CodeSniffer/issues/529 +[sq-537]: https://github.com/squizlabs/PHP_CodeSniffer/issues/537 +[sq-543]: https://github.com/squizlabs/PHP_CodeSniffer/issues/543 +[sq-551]: https://github.com/squizlabs/PHP_CodeSniffer/issues/551 +[sq-554]: https://github.com/squizlabs/PHP_CodeSniffer/issues/554 +[sq-558]: https://github.com/squizlabs/PHP_CodeSniffer/issues/558 +[sq-564]: https://github.com/squizlabs/PHP_CodeSniffer/issues/564 + +## [2.3.0] - 2015-03-04 + +### Changed +- The existence of the main config file is now cached to reduce is_file() calls when it doesn't exist (request [#486][sq-486]) +- Abstract classes inside the Sniffs directory are now ignored even if they are named `[Name]Sniff.php` (request [#476][sq-476]) + - Thanks to [David Vernet][@Decave] for the patch +- PEAR and Squiz FileComment sniffs no longer have @ in their error codes + - e.g., PEAR.Commenting.FileComment.Duplicate@categoryTag becomes PEAR.Commenting.FileComment.DuplicateCategoryTag + - e.g., Squiz.Commenting.FileComment.Missing@categoryTag becomes Squiz.Commenting.FileComment.MissingCategoryTag +- PEAR MultiLineConditionSniff now allows comment lines inside multi-line IF statement conditions + - Thanks to [Klaus Purer][@klausi] for the patch +- Generic ForbiddenFunctionsSniff now supports setting null replacements in ruleset files (request [#263][sq-263]) +- Generic opening function brace sniffs now support checking of closures + - Set the checkClosures property to TRUE (default is FALSE) in your ruleset.xml file to enable this + - Can also set the checkFunctions property to FALSE (default is TRUE) in your ruleset.xml file to only check closures + - Affects OpeningFunctionBraceBsdAllmanSniff and OpeningFunctionBraceKernighanRitchieSniff +- Generic OpeningFunctionBraceKernighanRitchieSniff can now fix all the errors it finds +- Generic OpeningFunctionBraceKernighanRitchieSniff now allows empty functions with braces next to each other +- Generic OpeningFunctionBraceBsdAllmanSniff now allows empty functions with braces next to each other +- Improved auto report width for the "full" report +- Improved conflict detection during auto fixing +- Generic ScopeIndentSniff is no longer confused by empty closures +- Squiz ControlSignatureSniff now always ignores comments (fixes bug [#490][sq-490]) + - Include the Squiz.Commenting.PostStatementComment sniff in your ruleset.xml to ban these comments again +- Squiz OperatorSpacingSniff no longer throws errors for code in the form ($foo || -1 === $bar) +- Fixed errors tokenizing T_ELSEIF tokens on HHVM 3.5 +- Squiz ArrayDeclarationSniff is no longer tricked by comments after array values +- PEAR IncludingFileSniff no longer produces invalid code when removing parenthesis from require/include statements + +### Fixed +- Fixed bug [#415][sq-415] : The @codingStandardsIgnoreStart has no effect during fixing +- Fixed bug [#432][sq-432] : Properties of custom sniffs cannot be configured +- Fixed bug [#453][sq-453] : PSR2 standard does not allow closing tag for mixed PHP/HTML files +- Fixed bug [#457][sq-457] : FunctionCallSignature sniffs do not support here/nowdoc syntax and can cause syntax error when fixing +- Fixed bug [#466][sq-466] : PropertyLabelSpacing JS fixer issue when there is no space after colon +- Fixed bug [#473][sq-473] : Writing a report for an empty folder to existing file includes the existing contents +- Fixed bug [#485][sq-485] : PHP notice in Squiz.Commenting.FunctionComment when checking malformed @throws comment +- Fixed bug [#491][sq-491] : Generic InlineControlStructureSniff can correct with missing semicolon + - Thanks to [Jesse Donat][@donatj] for the patch +- Fixed bug [#492][sq-492] : Use statements don't increase the scope indent +- Fixed bug [#493][sq-493] : PSR1_Sniffs_Methods_CamelCapsMethodNameSniff false positives for some magic method detection + - Thanks to [Andreas Möller][@localheinz] for the patch +- Fixed bug [#496][sq-496] : Closures in PSR2 are not checked for a space after the function keyword +- Fixed bug [#497][sq-497] : Generic InlineControlStructureSniff does not support alternative SWITCH syntax +- Fixed bug [#500][sq-500] : Functions not supported as values in Squiz ArrayDeclaration sniff +- Fixed bug [#501][sq-501] : ScopeClosingBrace and ScopeIndent conflict with closures used as array values + - Generic ScopeIndentSniff may now report fewer errors for closures, but perform the same fixes +- Fixed bug [#502][sq-502] : PSR1 SideEffectsSniff sees declare() statements as side effects + +[sq-415]: https://github.com/squizlabs/PHP_CodeSniffer/issues/415 +[sq-432]: https://github.com/squizlabs/PHP_CodeSniffer/issues/432 +[sq-453]: https://github.com/squizlabs/PHP_CodeSniffer/issues/453 +[sq-457]: https://github.com/squizlabs/PHP_CodeSniffer/issues/457 +[sq-466]: https://github.com/squizlabs/PHP_CodeSniffer/issues/466 +[sq-473]: https://github.com/squizlabs/PHP_CodeSniffer/issues/473 +[sq-476]: https://github.com/squizlabs/PHP_CodeSniffer/issues/476 +[sq-485]: https://github.com/squizlabs/PHP_CodeSniffer/issues/485 +[sq-486]: https://github.com/squizlabs/PHP_CodeSniffer/issues/486 +[sq-490]: https://github.com/squizlabs/PHP_CodeSniffer/issues/490 +[sq-491]: https://github.com/squizlabs/PHP_CodeSniffer/pull/491 +[sq-492]: https://github.com/squizlabs/PHP_CodeSniffer/pull/492 +[sq-493]: https://github.com/squizlabs/PHP_CodeSniffer/pull/493 +[sq-496]: https://github.com/squizlabs/PHP_CodeSniffer/issues/496 +[sq-497]: https://github.com/squizlabs/PHP_CodeSniffer/issues/497 +[sq-500]: https://github.com/squizlabs/PHP_CodeSniffer/issues/500 +[sq-501]: https://github.com/squizlabs/PHP_CodeSniffer/issues/501 +[sq-502]: https://github.com/squizlabs/PHP_CodeSniffer/issues/502 + +## [2.2.0] - 2015-01-22 + +### Changed +- Added (hopefully) tastefully used colors to report and progress output for the phpcs command + - Use the --colors command line argument to use colors in output + - Use the command "phpcs --config-set colors true" to turn colors on by default + - Use the --no-colors command line argument to turn colors off when the config value is set +- Added support for using the full terminal width for report output + - Use the --report-width=auto command line argument to auto-size the reports + - Use the command "phpcs --config-set report_width auto" to use auto-sizing by default +- Reports will now size to fit inside the report width setting instead of always using padding to fill the space +- If no files or standards are specified, PHPCS will now look for a phpcs.xml file in the current directory + - This file has the same format as a standard ruleset.xml file + - The phpcs.xml file should specify (at least) files to process and a standard/sniffs to use + - Useful for running the phpcs and phpcbf commands without any arguments at the top of a repository +- Default file paths can now be specified in a ruleset.xml file using the "file" tag + - File paths are only processed if no files were specified on the command line +- Extensions specified on the CLI are now merged with those set in ruleset.xml files + - Previously, the ruleset.xml file setting replaced the CLI setting completely +- Squiz coding standard now requires lowercase PHP constants (true, false and null) + - Removed Squiz.NamingConventions.ConstantCase sniff as the rule is now consistent across PHP and JS files +- Squiz FunctionOpeningBraceSpaceSniff no longer does additional checks for JS functions + - PHP and JS functions and closures are now treated the same way +- Squiz MultiLineFunctionDeclarationSniff now supports JS files +- Interactive mode no longer breaks if you also specify a report type on the command line +- PEAR InlineCommentSniff now fixes the Perl-style comments that it finds (request [#375][sq-375]) +- PSR2 standard no longer fixes the placement of docblock open tags as comments are excluded from this standard +- PSR2 standard now sets a default tab width of 4 spaces +- Generic DocCommentSniff now only disallows lowercase letters at the start of a long/short comment (request [#377][sq-377]) + - All non-letter characters are now allowed, including markdown special characters and numbers +- Generic DisallowMultipleStatementsSniff now allows multiple open/close tags on the same line (request [#423][sq-423]) +- Generic CharacterBeforePHPOpeningTagSniff now only checks the first PHP tag it finds (request [#423][sq-423]) +- Generic CharacterBeforePHPOpeningTagSniff now allows a shebang line at the start of the file (request [#20481][pear-20481]) +- Generic InlineHTMLUnitTest now allows a shebang line at the start of the file (request [#20481][pear-20481]) +- PEAR ObjectOperatorIndentSniff now only checks object operators at the start of a line +- PEAR FileComment and ClassComment sniffs no longer have @ in their error codes + - E.g., PEAR.Commenting.FileComment.Missing@categoryTag becomes PEAR.Commenting.FileComment.MissingCategoryTag + - Thanks to [Grzegorz Rygielski][@grzr] for the patch +- Squiz ControlStructureSpacingSniff no longer enforces a blank line before CATCH statements +- Squiz FunctionCommentSniff now fixes the return type in the @return tag (request [#392][sq-392]) +- Squiz BlockCommentSniff now only disallows lowercase letters at the start of the comment +- Squiz InlineCommentSniff now only disallows lowercase letters at the start of the comment +- Squiz OperatorSpacingSniff now has a setting to ignore newline characters around operators (request [#348][sq-348]) + - Default remains FALSE, so newlines are not allowed + - Override the "ignoreNewlines" setting in a ruleset.xml file to change +- PSR2 ControlStructureSpacingSniff now checks for, and fixes, newlines after the opening parenthesis +- Added a markdown document generator (--generator=markdown to use) + - Thanks to [Stefano Kowalke][@Konafets] for the contribution + +### Fixed +- Fixed bug [#379][sq-379] : Squiz.Arrays.ArrayDeclaration.NoCommaAfterLast incorrectly detects comments +- Fixed bug [#382][sq-382] : JS tokenizer incorrect for inline conditionally created immediately invoked anon function +- Fixed bug [#383][sq-383] : Squiz.Arrays.ArrayDeclaration.ValueNoNewline incorrectly detects nested arrays +- Fixed bug [#386][sq-386] : Undefined offset in Squiz.FunctionComment sniff when param has no comment +- Fixed bug [#390][sq-390] : Indentation of non-control structures isn't adjusted when containing structure is fixed +- Fixed bug [#400][sq-400] : InlineControlStructureSniff fails to fix when statement has no semicolon +- Fixed bug [#401][sq-401] : PHPCBF no-patch option shows an error when there are no fixable violations in a file +- Fixed bug [#405][sq-405] : The "Squiz.WhiteSpace.FunctionSpacing" sniff removes class "}" during fixing +- Fixed bug [#407][sq-407] : PEAR.ControlStructures.MultiLineCondition doesn't account for comments at the end of lines +- Fixed bug [#410][sq-410] : The "Squiz.WhiteSpace.MemberVarSpacing" not respecting "var" +- Fixed bug [#411][sq-411] : Generic.WhiteSpace.ScopeIndent.Incorrect - false positive with multiple arrays in argument list +- Fixed bug [#412][sq-412] : PSR2 multi-line detection doesn't work for inline IF and string concats +- Fixed bug [#414][sq-414] : Squiz.WhiteSpace.MemberVarSpacing - inconsistent checking of member vars with comment +- Fixed bug [#433][sq-433] : Wrong detection of Squiz.Arrays.ArrayDeclaration.KeyNotAligned when key contains space +- Fixed bug [#434][sq-434] : False positive for spacing around "=>" in inline array within foreach +- Fixed bug [#452][sq-452] : Ruleset exclude-pattern for specific sniff code ignored when using CLI --ignore option +- Fixed bug [#20482][pear-20482] : Scope indent sniff can get into infinite loop when processing a parse error + +[sq-348]: https://github.com/squizlabs/PHP_CodeSniffer/issues/348 +[sq-375]: https://github.com/squizlabs/PHP_CodeSniffer/issues/375 +[sq-377]: https://github.com/squizlabs/PHP_CodeSniffer/issues/377 +[sq-379]: https://github.com/squizlabs/PHP_CodeSniffer/issues/379 +[sq-382]: https://github.com/squizlabs/PHP_CodeSniffer/issues/382 +[sq-383]: https://github.com/squizlabs/PHP_CodeSniffer/issues/383 +[sq-386]: https://github.com/squizlabs/PHP_CodeSniffer/issues/386 +[sq-390]: https://github.com/squizlabs/PHP_CodeSniffer/issues/390 +[sq-392]: https://github.com/squizlabs/PHP_CodeSniffer/issues/392 +[sq-400]: https://github.com/squizlabs/PHP_CodeSniffer/issues/400 +[sq-401]: https://github.com/squizlabs/PHP_CodeSniffer/issues/401 +[sq-405]: https://github.com/squizlabs/PHP_CodeSniffer/issues/405 +[sq-407]: https://github.com/squizlabs/PHP_CodeSniffer/issues/407 +[sq-410]: https://github.com/squizlabs/PHP_CodeSniffer/issues/410 +[sq-411]: https://github.com/squizlabs/PHP_CodeSniffer/issues/411 +[sq-412]: https://github.com/squizlabs/PHP_CodeSniffer/issues/412 +[sq-414]: https://github.com/squizlabs/PHP_CodeSniffer/issues/414 +[sq-423]: https://github.com/squizlabs/PHP_CodeSniffer/issues/423 +[sq-433]: https://github.com/squizlabs/PHP_CodeSniffer/issues/433 +[sq-434]: https://github.com/squizlabs/PHP_CodeSniffer/issues/434 +[sq-452]: https://github.com/squizlabs/PHP_CodeSniffer/issues/452 +[pear-20481]: https://pear.php.net/bugs/bug.php?id=20481 +[pear-20482]: https://pear.php.net/bugs/bug.php?id=20482 + +## [2.1.0] - 2014-12-18 + +### Changed +- Time and memory output is now shown if progress information is also shown (request [#335][sq-335]) +- A tilde can now be used to reference a user's home directory in a path to a standard (request [#353][sq-353]) +- Added PHP_CodeSniffer_File::findStartOfStatement() to find the first non-whitespace token in a statement + - Possible alternative for code using PHP_CodeSniffer_File::findPrevious() with the local flag set +- Added PHP_CodeSniffer_File::findEndOfStatement() to find the last non-whitespace token in a statement + - Possible alternative for code using PHP_CodeSniffer_File::findNext() with the local flag set +- Generic opening function brace sniffs now ensure the opening brace is the last content on the line + - Affects OpeningFunctionBraceBsdAllmanSniff and OpeningFunctionBraceKernighanRitchieSniff + - Also enforced in PEAR FunctionDeclarationSniff and Squiz MultiLineFunctionDeclarationSniff +- Generic DisallowTabIndentSniff now replaces tabs everywhere it finds them, except in strings and here/now docs +- Generic EmptyStatementSniff error codes now contain the type of empty statement detected (request [#314][sq-314]) + - All messages generated by this sniff are now errors (empty CATCH was previously a warning) + - Message code `Generic.CodeAnalysis.EmptyStatement.NotAllowed` has been removed + - Message code `Generic.CodeAnalysis.EmptyStatement.NotAllowedWarning` has been removed + - New message codes have the format `Generic.CodeAnalysis.EmptyStatement.Detected[TYPE]` + - Example code is `Generic.CodeAnalysis.EmptyStatement.DetectedCATCH` + - You can now use a custom ruleset to change messages to warnings and to exclude them +- PEAR and Squiz FunctionCommentSniffs no longer ban `@return` tags for constructors and destructors + - Removed message PEAR.Commenting.FunctionComment.ReturnNotRequired + - Removed message Squiz.Commenting.FunctionComment.ReturnNotRequired + - Change initiated by request [#324][sq-324] and request [#369][sq-369] +- Squiz EmptyStatementSniff has been removed + - Squiz standard now includes Generic EmptyStatementSniff and turns off the empty CATCH error +- Squiz ControlSignatureSniff fixes now retain comments between the closing parenthesis and open brace +- Squiz SuperfluousWhitespaceSniff now checks for extra blank lines inside closures + - Thanks to [Sertan Danis][@sertand] for the patch +- Squiz ArrayDeclarationSniff now skips function calls while checking multi-line arrays + +### Fixed +- Fixed bug [#337][sq-337] : False positive with anonymous functions in Generic_Sniffs_WhiteSpace_ScopeIndentSniff +- Fixed bug [#339][sq-339] : reformatting brace location can result in broken code +- Fixed bug [#342][sq-342] : Nested ternary operators not tokenized correctly +- Fixed bug [#345][sq-345] : Javascript regex not tokenized when inside array +- Fixed bug [#346][sq-346] : PHP path can't be determined in some cases in "phpcs.bat" (on Windows XP) +- Fixed bug [#358][sq-358] : False positives for Generic_Sniffs_WhiteSpace_ScopeIndentSniff +- Fixed bug [#361][sq-361] : Sniff-specific exclude patterns don't work for Windows +- Fixed bug [#364][sq-364] : Don't interpret "use function" as declaration +- Fixed bug [#366][sq-366] : phpcbf with PSR2 errors on control structure alternative syntax +- Fixed bug [#367][sq-367] : Nested Anonymous Functions Causing False Negative +- Fixed bug [#371][sq-371] : Shorthand binary cast causes tokenizer errors + - New token T_BINARY_CAST added for the b"string" cast format (the 'b' is the T_BINARY_CAST token) +- Fixed bug [#372][sq-372] : phpcbf parse problem, wrong brace placement for inline IF +- Fixed bug [#373][sq-373] : Double quote usage fix removing too many double quotes +- Fixed bug [#20196][pear-20196] : 1.5.2 breaks scope_closer position + +[sq-314]: https://github.com/squizlabs/PHP_CodeSniffer/issues/314 +[sq-324]: https://github.com/squizlabs/PHP_CodeSniffer/issues/324 +[sq-335]: https://github.com/squizlabs/PHP_CodeSniffer/issues/335 +[sq-337]: https://github.com/squizlabs/PHP_CodeSniffer/issues/337 +[sq-339]: https://github.com/squizlabs/PHP_CodeSniffer/issues/339 +[sq-342]: https://github.com/squizlabs/PHP_CodeSniffer/issues/342 +[sq-345]: https://github.com/squizlabs/PHP_CodeSniffer/issues/345 +[sq-346]: https://github.com/squizlabs/PHP_CodeSniffer/issues/346 +[sq-353]: https://github.com/squizlabs/PHP_CodeSniffer/issues/353 +[sq-358]: https://github.com/squizlabs/PHP_CodeSniffer/issues/358 +[sq-361]: https://github.com/squizlabs/PHP_CodeSniffer/issues/361 +[sq-364]: https://github.com/squizlabs/PHP_CodeSniffer/pull/364 +[sq-366]: https://github.com/squizlabs/PHP_CodeSniffer/issues/366 +[sq-367]: https://github.com/squizlabs/PHP_CodeSniffer/issues/367 +[sq-369]: https://github.com/squizlabs/PHP_CodeSniffer/issues/369 +[sq-371]: https://github.com/squizlabs/PHP_CodeSniffer/issues/371 +[sq-372]: https://github.com/squizlabs/PHP_CodeSniffer/issues/372 +[sq-373]: https://github.com/squizlabs/PHP_CodeSniffer/issues/373 +[pear-20196]: https://pear.php.net/bugs/bug.php?id=20196 + +## [2.0.0] - 2014-12-05 + +### Changed +- JS tokenizer now sets functions as T_CLOSUREs if the function is anonymous +- JS tokenizer now sets all objects to T_OBJECT + - Object end braces are set to a new token T_CLOSE_OBJECT + - T_OBJECT tokens no longer act like scopes; i.e., they have no condition/opener/closer + - T_PROPERTY tokens no longer act like scopes; i.e., they have no condition/opener/closer + - T_OBJECT tokens have a bracket_closer instead, which can be used to find the ending + - T_CLOSE_OBJECT tokens have a bracket_opener +- Improved regular expression detection in the JS tokenizer +- You can now get PHP_CodeSniffer to ignore a single line by putting @codingStandardsIgnoreLine in a comment + - When the comment is found, the comment line and the following line will be ignored + - Thanks to [Andy Bulford][@abulford] for the contribution +- PHPCBF now prints output when it is changing into directories +- Improved conflict detection during auto fixing +- The -vvv command line argument will now output the current file content for each loop during fixing +- Generic ScopeIndentSniff now checks that open/close PHP tags are aligned to the correct column +- PEAR FunctionCallSignatureSniff now checks indent of closing parenthesis even if it is not on a line by itself +- PEAR FunctionCallSignatureSniff now supports JS files +- PEAR MultiLineConditionSniff now supports JS files +- Squiz DocCommentAlignmentSniff now supports JS files +- Fixed a problem correcting the closing brace line in Squiz ArrayDeclarationSniff +- Fixed a problem auto-fixing the Squiz.WhiteSpace.FunctionClosingBraceSpace.SpacingBeforeNestedClose error +- Squiz EmbeddedPhpSniff no longer reports incorrect alignment of tags when they are not on new lines +- Squiz EmbeddedPhpSniff now aligns open tags correctly when moving them onto a new line +- Improved fixing of arrays with multiple values in Squiz ArrayDeclarationSniff +- Improved detection of function comments in Squiz FunctionCommentSpacingSniff +- Improved fixing of lines after cases statements in Squiz SwitchDeclarationSniff + +### Fixed +- Fixed bug [#311][sq-311] : Suppression of function prototype breaks checking of lines within function +- Fixed bug [#320][sq-320] : Code sniffer indentation issue +- Fixed bug [#333][sq-333] : Nested ternary operators causing problems + +[sq-320]: https://github.com/squizlabs/PHP_CodeSniffer/issues/320 +[sq-333]: https://github.com/squizlabs/PHP_CodeSniffer/issues/333 + +## [1.5.6] - 2014-12-05 + +### Changed +- JS tokenizer now detects xor statements correctly +- The --config-show command now pretty-prints the config values + - Thanks to [Ken Guest][@kenguest] for the patch +- Setting and removing config values now catches exceptions if the config file is not writable + - Thanks to [Ken Guest][@kenguest] for the patch +- Setting and removing config values now prints a message to confirm the action and show old values +- You can now get PHP_CodeSniffer to ignore a single line by putting @codingStandardsIgnoreLine in a comment + - When the comment is found, the comment line and the following line will be ignored + - Thanks to [Andy Bulford][@abulford] for the contribution +- Generic ConstructorNameSniff no longer errors for PHP4 style constructors when __construct() is present + - Thanks to [Thibaud Fabre][@fabre-thibaud] for the patch + +### Fixed +- Fixed bug [#280][sq-280] : The --config-show option generates error when there is no config file +- Fixed bug [#306][sq-306] : File containing only a namespace declaration raises undefined index notice +- Fixed bug [#308][sq-308] : Squiz InlineIfDeclarationSniff fails on ternary operators inside closure +- Fixed bug [#310][sq-310] : Variadics not recognized by tokenizer +- Fixed bug [#311][sq-311] : Suppression of function prototype breaks checking of lines within function + +[sq-311]: https://github.com/squizlabs/PHP_CodeSniffer/issues/311 + +## [2.0.0RC4] - 2014-11-07 + +### Changed +- JS tokenizer now detects xor statements correctly +- Improved detection of properties and objects in the JS tokenizer +- Generic ScopeIndentSniff can now fix indents using tabs instead of spaces + - Set the tabIndent property to TRUE in your ruleset.xml file to enable this + - It is important to also set a tab-width setting, either in the ruleset or on the command line, for accuracy +- Generic ScopeIndentSniff now checks and auto-fixes JS files +- Generic DisallowSpaceIndentSniff is now able to replace space indents with tab indents during fixing +- Support for phpcs-only and phpcbf-only attributes has been added to all ruleset.xml elements + - Allows parts of the ruleset to only apply when using a specific tool + - Useful for doing things like excluding indent fixes but still reporting indent errors +- Unit tests can now set command line arguments during a test run + - Override getCliValues() and pass an array of CLI arguments for each file being tested +- File-wide sniff properties can now be set using T_INLINE_HTML content during unit test runs + - Sniffs that start checking at the open tag can only, normally, have properties set using a ruleset +- Generic ConstructorNameSniff no longer errors for PHP4 style constructors when __construct() is present + - Thanks to [Thibaud Fabre][@fabre-thibaud] for the patch +- Generic DocCommentSniff now checks that the end comment tag is on a new line +- Generic MultipleStatementAlignmentSniff no longer skips assignments for closures +- Squiz DocCommentAlignment sniff now has better checking for single line doc block +- Running unit tests with the -v CLI argument no longer generates PHP errors + +### Fixed +- Fixed bug [#295][sq-295] : ScopeIndentSniff hangs when processing nested closures +- Fixed bug [#298][sq-298] : False positive in ScopeIndentSniff when anonymous functions are used with method chaining +- Fixed bug [#302][sq-302] : Fixing code in Squiz InlineComment sniff can remove some comment text +- Fixed bug [#303][sq-303] : Open and close tag on same line can cause a PHP notice checking scope indent +- Fixed bug [#306][sq-306] : File containing only a namespace declaration raises undefined index notice +- Fixed bug [#307][sq-307] : Conditional breaks in case statements get incorrect indentations +- Fixed bug [#308][sq-308] : Squiz InlineIfDeclarationSniff fails on ternary operators inside closure +- Fixed bug [#310][sq-310] : Variadics not recognized by tokenizer + +[sq-295]: https://github.com/squizlabs/PHP_CodeSniffer/issues/295 +[sq-298]: https://github.com/squizlabs/PHP_CodeSniffer/issues/298 +[sq-302]: https://github.com/squizlabs/PHP_CodeSniffer/issues/302 +[sq-303]: https://github.com/squizlabs/PHP_CodeSniffer/issues/303 +[sq-306]: https://github.com/squizlabs/PHP_CodeSniffer/issues/306 +[sq-307]: https://github.com/squizlabs/PHP_CodeSniffer/issues/307 +[sq-308]: https://github.com/squizlabs/PHP_CodeSniffer/issues/308 +[sq-310]: https://github.com/squizlabs/PHP_CodeSniffer/issues/310 + +## [2.0.0RC3] - 2014-10-16 + +### Changed +- Improved default output for PHPCBF and removed the options to print verbose and progress output +- If a .fixed file is supplied for a unit test file, the auto fixes will be checked against it during testing + - See Generic ScopeIndentUnitTest.inc and ScopeIndentUnitTest.inc.fixed for an example +- Fixer token replacement methods now return TRUE if the change was accepted and FALSE if rejected +- The --config-show command now pretty-prints the config values + - Thanks to [Ken Guest][@kenguest] for the patch +- Setting and removing config values now catches exceptions if the config file is not writable + - Thanks to [Ken Guest][@kenguest] for the patch +- Setting and removing config values now prints a message to confirm the action and show old values +- Generic ScopeIndentSniff has been completely rewritten to improve fixing and embedded PHP detection +- Generic DisallowTabIndent and DisallowSpaceIndent sniffs now detect indents at the start of block comments +- Generic DisallowTabIndent and DisallowSpaceIndent sniffs now detect indents inside multi-line strings +- Generic DisallowTabIndentSniff now replaces tabs inside doc block comments +- Squiz ControlStructureSpacingSniff error codes have been corrected; they were reversed +- Squiz EmbeddedPhpSniff now checks open and close tag indents and fixes some errors +- Squiz FileCommentSniff no longer throws incorrect blank line before comment errors in JS files +- Squiz ClassDeclarationSniff now has better checking for blank lines after a closing brace +- Removed error Squiz.Classes.ClassDeclaration.NoNewlineAfterCloseBrace (request [#285][sq-285]) + - Already handled by Squiz.Classes.ClassDeclaration.CloseBraceSameLine + +### Fixed +- Fixed bug [#280][sq-280] : The --config-show option generates error when there is no config file + +[sq-280]: https://github.com/squizlabs/PHP_CodeSniffer/issues/280 +[sq-285]: https://github.com/squizlabs/PHP_CodeSniffer/issues/285 + +## [2.0.0RC2] - 2014-09-26 + +### Changed +- Minified JS and CSS files are now detected and skipped (fixes bug [#252][sq-252] and bug [#19899][pear-19899]) + - A warning will be added to the file so it can be found in the report and ignored in the future +- Fixed incorrect length of JS object operator tokens +- PHP tokenizer no longer converts class/function names to special tokens types + - Class/function names such as parent and true would become special tokens such as T_PARENT and T_TRUE +- PHPCS can now exit with 0 if only warnings were found (request [#262][sq-262]) + - Set the ignore_warnings_on_exit config variable to 1 to set this behaviour + - Default remains at exiting with 0 only if no errors and no warnings were found + - Also changes return value of PHP_CodeSniffer_Reporting::printReport() +- Rulesets can now set associative array properties + - property `name="[property]" type="array" value="foo=>bar,baz=>qux"` +- Generic ForbiddenFunctionsSniff now has a public property called forbiddenFunctions (request [#263][sq-263]) + - Override the property in a ruleset.xml file to define forbidden functions and their replacements + - A replacement of NULL indicates that no replacement is available + - e.g., value="delete=>unset,print=>echo,create_function=>null" + - Custom sniffs overriding this one will need to change the visibility of their member var +- Improved closure support in Generic ScopeIndentSniff +- Improved indented PHP tag support in Generic ScopeIndentSniff +- Improved fixing of mixed line indents in Generic ScopeIndentSniff +- Added conflict detection to the file fixer + - If 2 sniffs look to be conflicting, one change will be ignored to allow a fix to occur +- Generic CamelCapsFunctionNameSniff now ignores a single leading underscore + - Thanks to [Alex Slobodiskiy][@xt99] for the patch +- Standards can now be located within hidden directories (further fix for bug [#20323][pear-20323]) + - Thanks to [Klaus Purer][@klausi] for the patch +- Sniff ignore patterns now replace Win dir separators like file ignore patterns already did +- Exclude patterns now use backtick delimiters, allowing all special characters to work correctly again + - Thanks to [Jeremy Edgell][@jedgell] for the patch +- Errors converted to warnings in a ruleset (and vice versa) now retain their fixable status + - Thanks to [Alexander Obuhovich][@aik099] for the patch +- Squiz ConcatenationSpacingSniff now has a setting to specify how many spaces there should be around concat operators + - Default remains at 0 + - Override the "spacing" setting in a ruleset.xml file to change +- Added auto-fixes for Squiz InlineCommentSniff +- Generic DocCommentSniff now correctly fixes additional blank lines at the end of a comment +- Squiz OperatorBracketSniff now correctly fixes operations that include arrays +- Zend ClosingTagSniff fix now correctly leaves closing tags when followed by HTML +- Added Generic SyntaxSniff to check for syntax errors in PHP files + - Thanks to [Blaine Schmeisser][@bayleedev] for the contribution +- Added Generic OneTraitPerFileSniff to check that only one trait is defined in each file + - Thanks to [Alexander Obuhovich][@aik099] for the contribution +- Squiz DiscouragedFunctionsSniff now warns about var_dump() +- PEAR ValidFunctionNameSniff no longer throws an error for _() +- Squiz and PEAR FunctionCommentSniffs now support _() +- Generic DisallowTabIndentSniff now checks for, and fixes, mixed indents again +- Generic UpperCaseConstantSniff and LowerCaseConstantSniff now ignore function names + +### Fixed +- Fixed bug [#243][sq-243] : Missing DocBlock not detected +- Fixed bug [#248][sq-248] : FunctionCommentSniff expects ampersand on param name +- Fixed bug [#265][sq-265] : False positives with type hints in ForbiddenFunctionsSniff +- Fixed bug [#20373][pear-20373] : Inline comment sniff tab handling way +- Fixed bug [#20377][pear-20377] : Error when trying to execute phpcs with report=json +- Fixed bug [#20378][pear-20378] : Report appended to existing file if no errors found in run +- Fixed bug [#20381][pear-20381] : Invalid "Comment closer must be on a new line" + - Thanks to [Brad Kent][@bkdotcom] for the patch +- Fixed bug [#20402][pear-20402] : SVN pre-commit hook fails due to unknown argument error + +[sq-243]: https://github.com/squizlabs/PHP_CodeSniffer/issues/243 +[sq-252]: https://github.com/squizlabs/PHP_CodeSniffer/issues/252 +[sq-262]: https://github.com/squizlabs/PHP_CodeSniffer/issues/262 +[sq-263]: https://github.com/squizlabs/PHP_CodeSniffer/issues/263 +[pear-19899]: https://pear.php.net/bugs/bug.php?id=19899 +[pear-20377]: https://pear.php.net/bugs/bug.php?id=20377 +[pear-20402]: https://pear.php.net/bugs/bug.php?id=20402 + +## [1.5.5] - 2014-09-25 + +### Changed +- PHP tokenizer no longer converts class/function names to special tokens types + - Class/function names such as parent and true would become special tokens such as T_PARENT and T_TRUE +- Improved closure support in Generic ScopeIndentSniff +- Improved indented PHP tag support in Generic ScopeIndentSniff +- Generic CamelCapsFunctionNameSniff now ignores a single leading underscore + - Thanks to [Alex Slobodiskiy][@xt99] for the patch +- Standards can now be located within hidden directories (further fix for bug [#20323][pear-20323]) + - Thanks to [Klaus Purer][@klausi] for the patch +- Added Generic SyntaxSniff to check for syntax errors in PHP files + - Thanks to [Blaine Schmeisser][@bayleedev] for the contribution +- Squiz DiscouragedFunctionsSniff now warns about var_dump() +- PEAR ValidFunctionNameSniff no longer throws an error for _() +- Squiz and PEAR FunctionCommentSnif now support _() +- Generic UpperCaseConstantSniff and LowerCaseConstantSniff now ignore function names + +### Fixed +- Fixed bug [#248][sq-248] : FunctionCommentSniff expects ampersand on param name +- Fixed bug [#265][sq-265] : False positives with type hints in ForbiddenFunctionsSniff +- Fixed bug [#20373][pear-20373] : Inline comment sniff tab handling way +- Fixed bug [#20378][pear-20378] : Report appended to existing file if no errors found in run +- Fixed bug [#20381][pear-20381] : Invalid "Comment closer must be on a new line" + - Thanks to [Brad Kent][@bkdotcom] for the patch +- Fixed bug [#20386][pear-20386] : Squiz.Commenting.ClassComment.SpacingBefore thrown if first block comment + +[sq-248]: https://github.com/squizlabs/PHP_CodeSniffer/issues/248 +[sq-265]: https://github.com/squizlabs/PHP_CodeSniffer/pull/265 +[pear-20373]: https://pear.php.net/bugs/bug.php?id=20373 +[pear-20378]: https://pear.php.net/bugs/bug.php?id=20378 +[pear-20381]: https://pear.php.net/bugs/bug.php?id=20381 +[pear-20386]: https://pear.php.net/bugs/bug.php?id=20386 + +## [2.0.0RC1] - 2014-08-06 + +### Changed +- PHPCBF will now fix incorrect newline characters in a file +- PHPCBF now exits cleanly when there are no errors to fix +- Added phpcbf.bat file for Windows +- Verbose option no longer errors when using a phar file with a space in the path +- Fixed a reporting error when using HHVM + - Thanks to [Martins Sipenko][@martinssipenko] for the patch +- addFixableError() and addFixableWarning() now only return true if the fixer is enabled + - Saves checking ($phpcsFile->fixer->enabled === true) before every fix +- Added addErrorOnLine() and addWarningOnLine() to add a non-fixable violation to a line at column 1 + - Useful if you are generating errors using an external tool or parser and only know line numbers + - Thanks to [OndÅ™ej Mirtes][@ondrejmirtes] for the patch +- CSS tokenizer now identifies embedded PHP code using the new T_EMBEDDED_PHP token type + - The entire string of PHP is contained in a single token +- PHP tokenizer contains better detection of short array syntax +- Unit test runner now also test any standards installed under the installed_paths config var +- Exclude patterns now use {} delimiters, allowing the | special character to work correctly again +- The filtering component of the --extensions argument is now ignored again when passing filenames + - Can still be used to specify a custom tokenizer for each extension when passing filenames + - If no tokenizer is specified, default values will be used for common file extensions +- Diff report now produces relative paths on Windows, where possible (further fix for bug [#20234][pear-20234]) +- If a token's content has been modified by the tab-width setting, it will now have an orig_content in the tokens array +- Generic DisallowSpaceIndent and DisallowTabIndent sniffs now check original indent content even when tab-width is set + - Previously, setting --tab-width would force both to check the indent as spaces +- Fixed a problem where PHPCBF could replace tabs with too many spaces when changing indents +- Fixed a problem that could occur with line numbers when using HHVM to check files with Windows newline characters +- Removed use of sys_get_temp_dir() as this is not supported by the min PHP version +- Squiz ArrayDeclarationSniff now supports short array syntax +- Squiz ControlSignatureSniff no longer uses the Abstract Pattern sniff + - If you are extending this sniff, you'll need to rewrite your code + - The rewrite allows this sniff to fix all control structure formatting issues it finds +- The installed_paths config var now accepts relative paths + - The paths are relative to the PHP_CodeSniffer install directory + - Thanks to [Weston Ruter][@westonruter] for the patch +- Generic ScopeIndentSniff now accounts for different open tag indents +- PEAR FunctionDeclarationSniff now ignores short arrays when checking indent + - Thanks to [Daniel Tschinder][@danez] for the patch +- PSR2 FunctionCallSignatureSniff now treats multi-line strings as a single-line argument, like arrays and closures + - Thanks to [Dawid Nowak][@MacDada] for the patch +- PSR2 UseDeclarationSniff now checks for a single space after the USE keyword +- Generic ForbiddenFunctionsSniff now detects calls to functions in the global namespace + - Thanks to [Ole Martin Handeland][@olemartinorg] for the patch +- Generic LowerCaseConstantSniff and UpperCaseConstantSniff now ignore namespaces beginning with TRUE/FALSE/NULL + - Thanks to [Renan Gonçalves][@renan] for the patch +- Squiz InlineCommentSniff no longer requires a blank line after post-statement comments (request [#20299][pear-20299]) +- Squiz SelfMemberReferenceSniff now works correctly with namespaces +- Squiz FunctionCommentSniff is now more relaxed when checking namespaced type hints +- Tab characters are now encoded in abstract pattern error messages + - Thanks to [Blaine Schmeisser][@bayleedev] for the patch +- Invalid sniff codes passed to --sniffs now show a friendly error message (request [#20313][pear-20313]) +- Generic LineLengthSniff now shows a warning if the iconv module is disabled (request [#20314][pear-20314]) +- Source report no longer shows errors if category or sniff names ends in an uppercase error + - Thanks to [Jonathan Marcil][@jmarcil] for the patch + +### Fixed +- Fixed bug [#20261][pear-20261] : phpcbf has an endless fixing loop +- Fixed bug [#20268][pear-20268] : Incorrect documentation titles in PEAR documentation +- Fixed bug [#20296][pear-20296] : new array notion in function comma check fails +- Fixed bug [#20297][pear-20297] : phar does not work when renamed it to phpcs +- Fixed bug [#20307][pear-20307] : PHP_CodeSniffer_Standards_AbstractVariableSniff analyze traits +- Fixed bug [#20308][pear-20308] : Squiz.ValidVariableNameSniff - wrong variable usage +- Fixed bug [#20309][pear-20309] : Use "member variable" term in sniff "processMemberVar" method +- Fixed bug [#20310][pear-20310] : PSR2 does not check for space after function name +- Fixed bug [#20322][pear-20322] : Display rules set to type=error even when suppressing warnings +- Fixed bug [#20323][pear-20323] : PHPCS tries to load sniffs from hidden directories +- Fixed bug [#20346][pear-20346] : Fixer endless loop with Squiz.CSS sniffs +- Fixed bug [#20355][pear-20355] : No sniffs are registered with PHAR on Windows + +[pear-20261]: https://pear.php.net/bugs/bug.php?id=20261 +[pear-20297]: https://pear.php.net/bugs/bug.php?id=20297 +[pear-20346]: https://pear.php.net/bugs/bug.php?id=20346 +[pear-20355]: https://pear.php.net/bugs/bug.php?id=20355 + +## [1.5.4] - 2014-08-06 + +### Changed +- Removed use of sys_get_temp_dir() as this is not supported by the min PHP version +- The installed_paths config var now accepts relative paths + - The paths are relative to the PHP_CodeSniffer install directory + - Thanks to [Weston Ruter][@westonruter] for the patch +- Generic ScopeIndentSniff now accounts for different open tag indents +- PEAR FunctionDeclarationSniff now ignores short arrays when checking indent + - Thanks to [Daniel Tschinder][@danez] for the patch +- PSR2 FunctionCallSignatureSniff now treats multi-line strings as a single-line argument, like arrays and closures + - Thanks to [Dawid Nowak][@MacDada] for the patch +- Generic ForbiddenFunctionsSniff now detects calls to functions in the global namespace + - Thanks to [Ole Martin Handeland][@olemartinorg] for the patch +- Generic LowerCaseConstantSniff and UpperCaseConstantSniff now ignore namespaces beginning with TRUE/FALSE/NULL + - Thanks to [Renan Gonçalves][@renan] for the patch +- Squiz InlineCommentSniff no longer requires a blank line after post-statement comments (request [#20299][pear-20299]) +- Squiz SelfMemberReferenceSniff now works correctly with namespaces +- Tab characters are now encoded in abstract pattern error messages + - Thanks to [Blaine Schmeisser][@bayleedev] for the patch +- Invalid sniff codes passed to --sniffs now show a friendly error message (request [#20313][pear-20313]) +- Generic LineLengthSniff now shows a warning if the iconv module is disabled (request [#20314][pear-20314]) +- Source report no longer shows errors if category or sniff names ends in an uppercase error + - Thanks to [Jonathan Marcil][@jmarcil] for the patch + +### Fixed +- Fixed bug [#20268][pear-20268] : Incorrect documentation titles in PEAR documentation +- Fixed bug [#20296][pear-20296] : new array notion in function comma check fails +- Fixed bug [#20307][pear-20307] : PHP_CodeSniffer_Standards_AbstractVariableSniff analyze traits +- Fixed bug [#20308][pear-20308] : Squiz.ValidVariableNameSniff - wrong variable usage +- Fixed bug [#20309][pear-20309] : Use "member variable" term in sniff "processMemberVar" method +- Fixed bug [#20310][pear-20310] : PSR2 does not check for space after function name +- Fixed bug [#20322][pear-20322] : Display rules set to type=error even when suppressing warnings +- Fixed bug [#20323][pear-20323] : PHPCS tries to load sniffs from hidden directories + +[pear-20268]: https://pear.php.net/bugs/bug.php?id=20268 +[pear-20296]: https://pear.php.net/bugs/bug.php?id=20296 +[pear-20299]: https://pear.php.net/bugs/bug.php?id=20299 +[pear-20307]: https://pear.php.net/bugs/bug.php?id=20307 +[pear-20308]: https://pear.php.net/bugs/bug.php?id=20308 +[pear-20309]: https://pear.php.net/bugs/bug.php?id=20309 +[pear-20310]: https://pear.php.net/bugs/bug.php?id=20310 +[pear-20313]: https://pear.php.net/bugs/bug.php?id=20313 +[pear-20314]: https://pear.php.net/bugs/bug.php?id=20314 +[pear-20322]: https://pear.php.net/bugs/bug.php?id=20322 +[pear-20323]: https://pear.php.net/bugs/bug.php?id=20323 + +## [2.0.0a2] - 2014-05-01 + +### Changed +- Added report type --report=info to show information about the checked code to make building a standard easier + - Checks a number of things, such as what line length you use, and spacing are brackets, but not everything + - Still highly experimental +- Generic LineLengthSniff now shows warnings for long lines referring to licence and VCS information + - It previously ignored these lines, but at the expense of performance +- Generic DisallowTabIndent and DisallowSpaceIndent sniffs no longer error when detecting mixed indent types + - Only the first type of indent found on a line (space or indent) is considered +- Lots of little performance improvements that can add up to a substantial saving over large code bases + - Added a "length" array index to tokens so you don't need to call strlen() of them, or deal with encoding + - Can now use isset() to find tokens inside the PHP_CodeSniffer_Tokens static vars instead of in_array() +- Custom reports can now specify a $recordErrors member var; this previously only worked for built-in reports + - When set to FALSE, error messages will not be recorded and only totals will be returned + - This can save significant memory while processing a large code base +- Removed dependence on PHP_Timer +- PHP tokenizer now supports DEFAULT statements opened with a T_SEMICOLON +- The Squiz and PHPCS standards have increased the max padding for statement alignment from 8 to 12 +- Squiz EchoedStringsSniff now supports statements without a semicolon, such as PHP embedded in HTML +- Squiz DoubleQuoteUsageSniff now properly replaces escaped double quotes when fixing a doubled quoted string +- Improved detection of nested IF statements that use the alternate IF/ENDIF syntax +- PSR1 CamelCapsMethodNameSniff now ignores magic methods + - Thanks to [Eser Ozvataf][@eser] for the patch +- PSR1 SideEffectsSniff now ignores methods named define() +- PSR1 and PEAR ClassDeclarationSniffs now support traits (request [#20208][pear-20208]) +- PSR2 ControlStructureSpacingSniff now allows newlines before/after parentheses + - Thanks to [Maurus Cuelenaere][@mcuelenaere] for the patch +- PSR2 ControlStructureSpacingSniff now checks TRY and CATCH statements +- Squiz SuperfluousWhitespaceSniff now detects whitespace at the end of block comment lines + - Thanks to [Klaus Purer][@klausi] for the patch +- Squiz LowercasePHPFunctionsSniff no longer reports errors for namespaced functions + - Thanks to [Max Galbusera][@maxgalbu] for the patch +- Squiz SwitchDeclarationSniff now allows exit() as a breaking statement for case/default +- Squiz ValidVariableNameSniff and Zend ValidVariableNameSniff now ignore additional PHP reserved vars + - Thanks to Mikuláš DítÄ› and Adrian Crepaz for the patch +- Sniff code Squiz.WhiteSpace.MemberVarSpacing.After changed to Squiz.WhiteSpace.MemberVarSpacing.Incorrect (request [#20241][pear-20241]) + +### Fixed +- Fixed bug [#20200][pear-20200] : Invalid JSON produced with specific error message +- Fixed bug [#20204][pear-20204] : Ruleset exclude checks are case sensitive +- Fixed bug [#20213][pear-20213] : Invalid error, Inline IF must be declared on single line +- Fixed bug [#20225][pear-20225] : array_merge() that takes more than one line generates error +- Fixed bug [#20230][pear-20230] : Squiz ControlStructureSpacing sniff assumes specific condition formatting +- Fixed bug [#20234][pear-20234] : phpcbf patch command absolute paths +- Fixed bug [#20240][pear-20240] : Squiz block comment sniff fails when newline present +- Fixed bug [#20247][pear-20247] : The Squiz.WhiteSpace.ControlStructureSpacing sniff and do-while + - Thanks to [Alexander Obuhovich][@aik099] for the patch +- Fixed bug [#20248][pear-20248] : The Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff sniff and empty scope +- Fixed bug [#20252][pear-20252] : Unitialized string offset when package name starts with underscore + +[pear-20234]: https://pear.php.net/bugs/bug.php?id=20234 + +## [1.5.3] - 2014-05-01 + +### Changed +- Improved detection of nested IF statements that use the alternate IF/ENDIF syntax +- PHP tokenizer now supports DEFAULT statements opened with a T_SEMICOLON +- PSR1 CamelCapsMethodNameSniff now ignores magic methods + - Thanks to [Eser Ozvataf][@eser] for the patch +- PSR1 SideEffectsSniff now ignores methods named define() +- PSR1 and PEAR ClassDeclarationSniffs now support traits (request [#20208][pear-20208]) +- PSR2 ControlStructureSpacingSniff now allows newlines before/after parentheses + - Thanks to [Maurus Cuelenaere][@mcuelenaere] for the patch +- Squiz LowercasePHPFunctionsSniff no longer reports errors for namespaced functions + - Thanks to [Max Galbusera][@maxgalbu] for the patch +- Squiz SwitchDeclarationSniff now allows exit() as a breaking statement for case/default +- Squiz ValidVariableNameSniff and Zend ValidVariableNameSniff now ignore additional PHP reserved vars + - Thanks to Mikuláš DítÄ› and Adrian Crepaz for the patch +- Sniff code Squiz.WhiteSpace.MemberVarSpacing.After changed to Squiz.WhiteSpace.MemberVarSpacing.Incorrect (request [#20241][pear-20241]) + +### Fixed +- Fixed bug [#20200][pear-20200] : Invalid JSON produced with specific error message +- Fixed bug [#20204][pear-20204] : Ruleset exclude checks are case sensitive +- Fixed bug [#20213][pear-20213] : Invalid error, Inline IF must be declared on single line +- Fixed bug [#20225][pear-20225] : array_merge() that takes more than one line generates error +- Fixed bug [#20230][pear-20230] : Squiz ControlStructureSpacing sniff assumes specific condition formatting +- Fixed bug [#20240][pear-20240] : Squiz block comment sniff fails when newline present +- Fixed bug [#20247][pear-20247] : The Squiz.WhiteSpace.ControlStructureSpacing sniff and do-while + - Thanks to [Alexander Obuhovich][@aik099] for the patch +- Fixed bug [#20248][pear-20248] : The Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff sniff and empty scope +- Fixed bug [#20252][pear-20252] : Uninitialized string offset when package name starts with underscore + +[pear-20200]: https://pear.php.net/bugs/bug.php?id=20200 +[pear-20204]: https://pear.php.net/bugs/bug.php?id=20204 +[pear-20208]: https://pear.php.net/bugs/bug.php?id=20208 +[pear-20213]: https://pear.php.net/bugs/bug.php?id=20213 +[pear-20225]: https://pear.php.net/bugs/bug.php?id=20225 +[pear-20230]: https://pear.php.net/bugs/bug.php?id=20230 +[pear-20240]: https://pear.php.net/bugs/bug.php?id=20240 +[pear-20241]: https://pear.php.net/bugs/bug.php?id=20241 +[pear-20247]: https://pear.php.net/bugs/bug.php?id=20247 +[pear-20248]: https://pear.php.net/bugs/bug.php?id=20248 +[pear-20252]: https://pear.php.net/bugs/bug.php?id=20252 + +## [2.0.0a1] - 2014-02-05 + +### Changed +- Added the phpcbf script to automatically fix many errors found by the phpcs script +- Added report type --report=diff to show suggested changes to fix coding standard violations +- The --report argument now allows for custom reports to be used + - Use the full path to your custom report class as the report name +- The --extensions argument is now respected when passing filenames; not just with directories +- The --extensions argument now allows you to specify the tokenizer for each extension + - e.g., `--extensions=module/php,es/js` +- Command line arguments can now be set in ruleset files + - e.g., `arg name="report" value="summary"` (print summary report; same as `--report=summary`) + - e.g., `arg value="sp"` (print source and progress information; same as `-sp`) + - The `-vvv`, `--sniffs`, `--standard` and `-l` command line arguments cannot be set in this way +- Sniff process() methods can now optionally return a token to ignore up to + - If returned, the sniff will not be executed again until the passed token is reached in the file + - Useful if you are looking for tokens like T_OPEN_TAG but only want to process the first one +- Removed the comment parser classes and replaced it with a simple comment tokenizer + - T_DOC_COMMENT tokens are now tokenized into T_DOC_COMMENT_* tokens so they can be used more easily + - This change requires a significant rewrite of sniffs that use the comment parser + - This change requires minor changes to sniffs that listen for T_DOC_COMMENT tokens directly +- Added Generic DocCommentSniff to check generic doc block formatting + - Removed doc block formatting checks from PEAR ClassCommentSniff + - Removed doc block formatting checks from PEAR FileCommentSniff + - Removed doc block formatting checks from PEAR FunctionCommentSniff + - Removed doc block formatting checks from Squiz ClassCommentSniff + - Removed doc block formatting checks from Squiz FileCommentSniff + - Removed doc block formatting checks from Squiz FunctionCommentSniff + - Removed doc block formatting checks from Squiz VariableCommentSniff +- Squiz DocCommentAlignmentSniff has had its error codes changed + - NoSpaceBeforeTag becomes NoSpaceAfterStar + - SpaceBeforeTag becomes SpaceAfterStar + - SpaceBeforeAsterisk becomes SpaceBeforeStar +- Generic MultipleStatementAlignment now aligns assignments within a block so they fit within their max padding setting + - The sniff previously requested the padding as 1 space if max padding was exceeded + - It now aligns the assignment with surrounding assignments if it can + - Removed property ignoreMultiline as multi-line assignments are now handled correctly and should not be ignored +- Squiz FunctionClosingBraceSpaceSniff now requires a blank line before the brace in all cases except function args +- Added error Squiz.Commenting.ClassComment.SpacingAfter to ensure there are no blank lines after a class comment +- Added error Squiz.WhiteSpace.MemberVarSpacing.AfterComment to ensure there are no blank lines after a member var comment + - Fixes have also been corrected to not strip the member var comment or indent under some circumstances + - Thanks to [Mark Scherer][@dereuromark] for help with this fix +- Added error Squiz.Commenting.FunctionCommentThrowTag.Missing to ensure a throw is documented +- Removed error Squiz.Commenting.FunctionCommentThrowTag.WrongType +- Content passed via STDIN can now specify the filename to use so that sniffs can run the correct filename checks + - Ensure the first line of the content is: phpcs_input_file: /path/to/file +- Squiz coding standard now enforces no closing PHP tag at the end of a pure PHP file +- Squiz coding standard now enforces a single newline character at the end of the file +- Squiz ClassDeclarationSniff no longer checks for a PHP ending tag after a class definition +- Squiz ControlStructureSpacingSniff now checks TRY and CATCH statements as well +- Removed MySource ChannelExceptionSniff + +## [1.5.2] - 2014-02-05 + +### Changed +- Improved support for the PHP 5.5. classname::class syntax + - PSR2 SwitchDeclarationSniff no longer throws errors when this syntax is used in CASE conditions +- Improved support for negative checks of instanceOf in Squiz ComparisonOperatorUsageSniff + - Thanks to [Martin Winkel][@storeman] for the patch +- Generic FunctionCallArgumentSpacingSniff now longer complains about space before comma when using here/nowdocs + - Thanks to [Richard van Velzen][@rvanvelzen] for the patch +- Generic LowerCaseConstantSniff and UpperCaseConstantSniff now ignore class constants + - Thanks to [Kristopher Wilson][@mrkrstphr] for the patch +- PEAR FunctionCallSignatureSniff now has settings to specify how many spaces should appear before/after parentheses + - Override the 'requiredSpacesAfterOpen' and 'requiredSpacesBeforeClose' settings in a ruleset.xml file to change + - Default remains at 0 for both + - Thanks to [Astinus Eberhard][@Astinus-Eberhard] for the patch +- PSR2 ControlStructureSpacingSniff now has settings to specify how many spaces should appear before/after parentheses + - Override the 'requiredSpacesAfterOpen' and 'requiredSpacesBeforeClose' settings in a ruleset.xml file to change + - Default remains at 0 for both + - Thanks to [Astinus Eberhard][@Astinus-Eberhard] for the patch +- Squiz ForEachLoopDeclarationSniff now has settings to specify how many spaces should appear before/after parentheses + - Override the 'requiredSpacesAfterOpen' and 'requiredSpacesBeforeClose' settings in a ruleset.xml file to change + - Default remains at 0 for both + - Thanks to [Astinus Eberhard][@Astinus-Eberhard] for the patch +- Squiz ForLoopDeclarationSniff now has settings to specify how many spaces should appear before/after parentheses + - Override the 'requiredSpacesAfterOpen' and 'requiredSpacesBeforeClose' settings in a ruleset.xml file to change + - Default remains at 0 for both + - Thanks to [Astinus Eberhard][@Astinus-Eberhard] for the patch +- Squiz FunctionDeclarationArgumentSpacingSniff now has settings to specify how many spaces should appear before/after parentheses + - Override the 'requiredSpacesAfterOpen' and 'requiredSpacesBeforeClose' settings in a ruleset.xml file to change + - Default remains at 0 for both + - Thanks to [Astinus Eberhard][@Astinus-Eberhard] for the patch +- Removed UnusedFunctionParameter, CyclomaticComplexity and NestingLevel from the Squiz standard +- Generic FixmeSniff and TodoSniff now work correctly with accented characters + +### Fixed +- Fixed bug [#20145][pear-20145] : Custom ruleset preferences directory over installed standard +- Fixed bug [#20147][pear-20147] : phpcs-svn-pre-commit - no more default error report +- Fixed bug [#20151][pear-20151] : Problem handling "if(): ... else: ... endif;" syntax +- Fixed bug [#20190][pear-20190] : Invalid regex in Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff + +[pear-20145]: https://pear.php.net/bugs/bug.php?id=20145 +[pear-20147]: https://pear.php.net/bugs/bug.php?id=20147 +[pear-20151]: https://pear.php.net/bugs/bug.php?id=20151 +[pear-20190]: https://pear.php.net/bugs/bug.php?id=20190 + +## [1.5.1] - 2013-12-12 + +### Changed +- Config values can now be set at runtime using the command line argument `--runtime-set key value` + - Runtime values are the same as config values, but are not written to the main config file + - Thanks to [Wim Godden][@wimg] for the patch +- Config values can now be set in ruleset files + - e.g., config name="zend_ca_path" value="/path/to/ZendCodeAnalyzer" + - Can not be used to set config values that override command line values, such as show_warnings + - Thanks to [Jonathan Marcil][@jmarcil] for helping with the patch +- Added a new installed_paths config value to allow for the setting of directories that contain standards + - By default, standards have to be installed into the CodeSniffer/Standards directory to be considered installed + - New config value allows a list of paths to be set in addition to this internal path + - Installed standards appear when using the -i arg, and can be referenced in rulesets using only their name + - Set paths by running: phpcs --config-set installed_paths /path/one,/path/two,... +- PSR2 ClassDeclarationSniff now allows a list of extended interfaces to be split across multiple lines +- Squiz DoubleQuoteUsageSniff now allows \b in double quoted strings +- Generic ForbiddenFunctionsSniff now ignores object creation + - This is a further fix for bug [#20100][pear-20100] : incorrect Function mysql() has been deprecated report + +### Fixed +- Fixed bug [#20136][pear-20136] : Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff and Traits +- Fixed bug [#20138][pear-20138] : Protected property underscore and camel caps issue (in trait with Zend) + - Thanks to [Gaetan Rousseau][@Naelyth] for the patch +- Fixed bug [#20139][pear-20139] : No report file generated on success + +[pear-20136]: https://pear.php.net/bugs/bug.php?id=20136 +[pear-20138]: https://pear.php.net/bugs/bug.php?id=20138 +[pear-20139]: https://pear.php.net/bugs/bug.php?id=20139 + +## [1.5.0] - 2013-11-28 + +### Changed +- Doc generation is now working again for installed standards + - Includes a fix for limiting the docs to specific sniffs +- Generic ScopeIndentSniff now allows for ignored tokens to be set via ruleset.xml files + - E.g., to ignore comments, override a property using: + - name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT" +- PSR2 standard now ignores comments when checking indentation rules +- Generic UpperCaseConstantNameSniff no longer reports errors where constants are used (request [#20090][pear-20090]) + - It still reports errors where constants are defined +- Individual messages can now be excluded in ruleset.xml files using the exclude tag (request [#20091][pear-20091]) + - Setting message severity to 0 continues to be supported +- Squiz OperatorSpacingSniff no longer throws errors for the ?: short ternary operator + - Thanks to [Antoine Musso][@hashar] for the patch +- Comment parser now supports non-English characters when splitting comment lines into words + - Thanks to [Nik Sun][@CandySunPlus] for the patch +- Exit statements are now recognised as valid closers for CASE and DEFAULT blocks + - Thanks to [Maksim Kochkin][@ksimka] for the patch +- PHP_CodeSniffer_CLI::process() can now be passed an incomplete array of CLI values + - Missing values will be set to the CLI defaults + - Thanks to [Maksim Kochkin][@ksimka] for the patch + +### Fixed +- Fixed bug [#20093][pear-20093] : Bug with ternary operator token +- Fixed bug [#20097][pear-20097] : `CLI.php` throws error in PHP 5.2 +- Fixed bug [#20100][pear-20100] : incorrect Function mysql() has been deprecated report +- Fixed bug [#20119][pear-20119] : PHP warning: invalid argument to str_repeat() in SVN blame report with -s +- Fixed bug [#20123][pear-20123] : PSR2 complains about an empty second statement in for-loop +- Fixed bug [#20131][pear-20131] : PHP errors in svnblame report, if there are files not under version control +- Fixed bug [#20133][pear-20133] : Allow "HG: hg_id" as value for @version tag + +[pear-20090]: https://pear.php.net/bugs/bug.php?id=20090 +[pear-20091]: https://pear.php.net/bugs/bug.php?id=20091 +[pear-20093]: https://pear.php.net/bugs/bug.php?id=20093 + +## [1.4.8] - 2013-11-26 + +### Changed +- Generic ScopeIndentSniff now allows for ignored tokens to be set via ruleset.xml files + - E.g., to ignore comments, override a property using: + - name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT" +- PSR2 standard now ignores comments when checking indentation rules +- Squiz OperatorSpacingSniff no longer throws errors for the ?: short ternary operator + - Thanks to [Antoine Musso][@hashar] for the patch +- Comment parser now supports non-English characters when splitting comment lines into words + - Thanks to [Nik Sun][@CandySunPlus] for the patch +- Exit statements are now recognised as valid closers for CASE and DEFAULT blocks + - Thanks to [Maksim Kochkin][@ksimka] for the patch +- PHP_CodeSniffer_CLI::process() can now be passed an incomplete array of CLI values + - Missing values will be set to the CLI defaults + - Thanks to [Maksim Kochkin][@ksimka] for the patch + +### Fixed +- Fixed bug [#20097][pear-20097] : `CLI.php` throws error in PHP 5.2 +- Fixed bug [#20100][pear-20100] : incorrect Function mysql() has been deprecated report +- Fixed bug [#20119][pear-20119] : PHP warning: invalid argument to str_repeat() in SVN blame report with -s +- Fixed bug [#20123][pear-20123] : PSR2 complains about an empty second statement in for-loop +- Fixed bug [#20131][pear-20131] : PHP errors in svnblame report, if there are files not under version control +- Fixed bug [#20133][pear-20133] : Allow "HG: hg_id" as value for @version tag + +[pear-20097]: https://pear.php.net/bugs/bug.php?id=20097 +[pear-20100]: https://pear.php.net/bugs/bug.php?id=20100 +[pear-20119]: https://pear.php.net/bugs/bug.php?id=20119 +[pear-20123]: https://pear.php.net/bugs/bug.php?id=20123 +[pear-20131]: https://pear.php.net/bugs/bug.php?id=20131 +[pear-20133]: https://pear.php.net/bugs/bug.php?id=20133 + +## [1.5.0RC4] - 2013-09-26 + +### Changed +- You can now restrict violations to individual sniff codes using the --sniffs command line argument + - Previously, this only restricted violations to an entire sniff and not individual messages + - If you have scripts calling PHP_CodeSniffer::process() or creating PHP_CodeSniffer_File objects, you must update your code + - The array of restrictions passed to PHP_CodeSniffer::process() must now be an array of sniff codes instead of class names + - The PHP_CodeSniffer_File::__construct() method now requires an array of restrictions to be passed +- Doc generation is now working again +- Progress information now shows the percentage complete at the end of each line +- Added report type --report=junit to show the error list in a JUnit compatible format + - Thanks to [Oleg Lobach][@bladeofsteel] for the contribution +- Added support for the PHP 5.4 callable type hint +- Fixed problem where some file content could be ignored when checking STDIN +- Version information is now printed when installed via composer or run from a Git clone (request [#20050][pear-20050]) +- Added Squiz DisallowBooleanStatementSniff to ban boolean operators outside of control structure conditions +- The CSS tokenizer is now more reliable when encountering 'list' and 'break' strings +- Coding standard ignore comments can now appear instead doc blocks as well as inline comments + - Thanks to [Stuart Langley][@sjlangley] for the patch +- Generic LineLengthSniff now ignores SVN URL and Head URL comments + - Thanks to [Karl DeBisschop][@kdebisschop] for the patch +- PEAR MultiLineConditionSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- PEAR MultiLineAssignmentSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- PEAR FunctionDeclarationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- Squiz SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- Squiz CSS IndentationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Hugo Fonseca][@fonsecas72] for the patch +- Squiz and MySource File and Function comment sniffs now allow all tags and don't require a particular licence +- Squiz standard now allows lines to be 120 characters long before warning; up from 85 +- Squiz LowercaseStyleDefinitionSniff no longer throws errors for class names in nested style definitions +- Squiz ClassFileNameSniff no longer throws errors when checking STDIN +- Squiz CSS sniffs no longer generate errors for IE filters +- Squiz CSS IndentationSniff no longer sees comments as blank lines +- Squiz LogicalOperatorSpacingSniff now ignores whitespace at the end of a line +- Squiz.Scope.MethodScope.Missing error message now mentions 'visibility' instead of 'scope modifier' + - Thanks to [Renat Akhmedyanov][@r3nat] for the patch +- Added support for the PSR2 multi-line arguments errata +- The PSR2 standard no longer throws errors for additional spacing after a type hint +- PSR UseDeclarationSniff no longer throws errors for USE statements inside TRAITs + +### Fixed +- Fixed cases where code was incorrectly assigned the T_GOTO_LABEL token when used in a complex CASE condition +- Fixed bug [#20026][pear-20026] : Check for multi-line arrays that should be single-line is slightly wrong + - Adds new error message for single-line arrays that end with a comma +- Fixed bug [#20029][pear-20029] : ForbiddenFunction sniff incorrectly recognizes methods in USE clauses +- Fixed bug [#20043][pear-20043] : Mis-interpretation of Foo::class +- Fixed bug [#20044][pear-20044] : PSR1 camelCase check does not ignore leading underscores +- Fixed bug [#20045][pear-20045] : Errors about indentation for closures with multi-line 'use' in functions +- Fixed bug [#20051][pear-20051] : Undefined index: scope_opener / scope_closer + - Thanks to [Anthon Pang][@robocoder] for the patch + +[pear-20051]: https://pear.php.net/bugs/bug.php?id=20051 + +## [1.4.7] - 2013-09-26 + +### Changed +- Added report type --report=junit to show the error list in a JUnit compatible format + - Thanks to [Oleg Lobach][@bladeofsteel] for the contribution +- Added support for the PHP 5.4 callable type hint +- Fixed problem where some file content could be ignored when checking STDIN +- Version information is now printed when installed via composer or run from a Git clone (request [#20050][pear-20050]) +- The CSS tokenizer is now more reliable when encountering 'list' and 'break' strings +- Coding standard ignore comments can now appear instead doc blocks as well as inline comments + - Thanks to [Stuart Langley][@sjlangley] for the patch +- Generic LineLengthSniff now ignores SVN URL and Head URL comments + - Thanks to [Karl DeBisschop][@kdebisschop] for the patch +- PEAR MultiLineConditionSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- PEAR MultiLineAssignmentSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- PEAR FunctionDeclarationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- Squiz SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Szabolcs Sulik][@blerou] for the patch +- Squiz CSS IndentationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the 'indent' setting in a ruleset.xml file to change + - Thanks to [Hugo Fonseca][@fonsecas72] for the patch +- Squiz and MySource File and Function comment sniffs now allow all tags and don't require a particular licence +- Squiz LowercaseStyleDefinitionSniff no longer throws errors for class names in nested style definitions +- Squiz ClassFileNameSniff no longer throws errors when checking STDIN +- Squiz CSS sniffs no longer generate errors for IE filters +- Squiz CSS IndentationSniff no longer sees comments as blank lines +- Squiz LogicalOperatorSpacingSniff now ignores whitespace at the end of a line +- Squiz.Scope.MethodScope.Missing error message now mentions 'visibility' instead of 'scope modifier' + - Thanks to [Renat Akhmedyanov][@r3nat] for the patch +- Added support for the PSR2 multi-line arguments errata +- The PSR2 standard no longer throws errors for additional spacing after a type hint +- PSR UseDeclarationSniff no longer throws errors for USE statements inside TRAITs + +### Fixed +- Fixed bug [#20026][pear-20026] : Check for multi-line arrays that should be single-line is slightly wrong + - Adds new error message for single-line arrays that end with a comma +- Fixed bug [#20029][pear-20029] : ForbiddenFunction sniff incorrectly recognizes methods in USE clauses +- Fixed bug [#20043][pear-20043] : Mis-interpretation of Foo::class +- Fixed bug [#20044][pear-20044] : PSR1 camelCase check does not ignore leading underscores +- Fixed bug [#20045][pear-20045] : Errors about indentation for closures with multi-line 'use' in functions + +[pear-20026]: https://pear.php.net/bugs/bug.php?id=20026 +[pear-20029]: https://pear.php.net/bugs/bug.php?id=20029 +[pear-20043]: https://pear.php.net/bugs/bug.php?id=20043 +[pear-20044]: https://pear.php.net/bugs/bug.php?id=20044 +[pear-20045]: https://pear.php.net/bugs/bug.php?id=20045 +[pear-20050]: https://pear.php.net/bugs/bug.php?id=20050 + +## [1.5.0RC3] - 2013-07-25 + +### Changed +- Added report type --report=json to show the error list and total counts for all checked files + - Thanks to [Jeffrey Fisher][@jeffslofish] for the contribution +- PHP_CodeSniffer::isCamelCaps now allows for acronyms at the start of a string if the strict flag is FALSE + - acronyms are defined as at least 2 uppercase characters in a row + - e.g., the following is now valid camel caps with strict set to FALSE: XMLParser +- The PHP tokenizer now tokenizes goto labels as T_GOTO_LABEL instead of T_STRING followed by T_COLON +- The JS tokenizer now has support for the T_THROW token +- Symlinked directories inside CodeSniffer/Standards and in ruleset.xml files are now supported + - Only available since PHP 5.2.11 and 5.3.1 + - Thanks to [Maik Penz][@goatherd] for the patch +- The JS tokenizer now correctly identifies T_INLINE_ELSE tokens instead of leaving them as T_COLON + - Thanks to [Arnout Boks][@aboks] for the patch +- Explaining a standard (phpcs -e) that uses namespaces now works correctly +- Restricting a check to specific sniffs (phpcs --sniffs=...) now works correctly with namespaced sniffs + - Thanks to [Maik Penz][@goatherd] for the patch +- Docs added for the entire Generic standard, and many sniffs from other standards are now documented as well + - Thanks to [Spencer Rinehart][@nubs] for the contribution +- Clearer error message for when the sniff class name does not match the directory structure +- Generated HTML docs now correctly show the open PHP tag in code comparison blocks +- Added Generic InlineHTMLSniff to ensure a file only contains PHP code +- Added Squiz ShorthandSizeSniff to check that CSS sizes are using shorthand notation only when 1 or 2 values are used +- Added Squiz ForbiddenStylesSniff to ban the use of some deprecated browser-specific styles +- Added Squiz NamedColoursSniff to ban the use of colour names +- PSR2 standard no longer enforces no whitespace between the closing parenthesis of a function call and the semicolon +- PSR2 ClassDeclarationSniff now ignores empty classes when checking the end brace position +- PSR2 SwitchDeclarationSniff no longer reports errors for empty lines between CASE statements +- PEAR ObjectOperatorIndentSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the indent setting in a ruleset.xml file to change + - Thanks to [Andrey Mindubaev][@covex-nn] for the patch +- Squiz FileExtensionSniff now supports traits + - Thanks to [Lucas Green][@mythril] for the patch +- Squiz ArrayDeclarationSniff no longer reports errors for no comma at the end of a line that contains a function call +- Squiz SwitchDeclarationSniff now supports T_CONTINUE and T_THROW as valid case/default breaking statements +- Squiz CommentedOutCodeSniff is now better at ignoring commented out HTML, XML and regular expressions +- Squiz DisallowComparisonAssignmentSniff no longer throws errors for the third expression in a FOR statement +- Squiz ColourDefinitionSniff no longer throws errors for some CSS class names +- Squiz ControlStructureSpacingSniff now supports all types of CASE/DEFAULT breaking statements +- Generic CallTimePassByReferenceSniff now reports errors for functions called using a variable + - Thanks to [Maik Penz][@goatherd] for the patch +- Generic ConstructorNameSniff no longer throws a notice for abstract constructors inside abstract classes + - Thanks to [Spencer Rinehart][@nubs] for the patch +- Squiz ComparisonOperatorUsageSniff now checks inside elseif statements + - Thanks to [Arnout Boks][@aboks] for the patch +- Squiz OperatorSpacingSniff now reports errors for no spacing around inline then and else tokens + - Thanks to [Arnout Boks][@aboks] for the patch + +### Fixed +- Fixed bug [#19811][pear-19811] : Comments not ignored in all cases in AbstractPatternSniff + - Thanks to [Erik Wiffin][@erikwiffin] for the patch +- Fixed bug [#19892][pear-19892] : ELSE with no braces causes incorrect SWITCH break statement indentation error +- Fixed bug [#19897][pear-19897] : Indenting warnings in templates not consistent +- Fixed bug [#19908][pear-19908] : PEAR MultiLineCondition Does Not Apply elseif +- Fixed bug [#19930][pear-19930] : option --report-file generate an empty file +- Fixed bug [#19935][pear-19935] : notify-send reports do not vanish in gnome-shell + - Thanks to [Christian Weiske][@cweiske] for the patch +- Fixed bug [#19944][pear-19944] : docblock squiz sniff "return void" trips over return in lambda function +- Fixed bug [#19953][pear-19953] : PSR2 - Spaces before interface name for abstract class +- Fixed bug [#19956][pear-19956] : phpcs warns for Type Hint missing Resource +- Fixed bug [#19957][pear-19957] : Does not understand trait method aliasing +- Fixed bug [#19968][pear-19968] : Permission denied on excluded directory +- Fixed bug [#19969][pear-19969] : Sniffs with namespace not recognized in reports +- Fixed bug [#19997][pear-19997] : Class names incorrectly detected as constants + +[pear-19930]: https://pear.php.net/bugs/bug.php?id=19930 + +## [1.4.6] - 2013-07-25 + +### Changed +- Added report type --report=json to show the error list and total counts for all checked files + - Thanks to [Jeffrey Fisher][@jeffslofish] for the contribution +- The JS tokenizer now has support for the T_THROW token +- Symlinked directories inside CodeSniffer/Standards and in ruleset.xml files are now supported + - Only available since PHP 5.2.11 and 5.3.1 + - Thanks to [Maik Penz][@goatherd] for the patch +- The JS tokenizer now correctly identifies T_INLINE_ELSE tokens instead of leaving them as T_COLON + - Thanks to [Arnout Boks][@aboks] for the patch +- Explaining a standard (phpcs -e) that uses namespaces now works correctly +- Restricting a check to specific sniffs (phpcs --sniffs=...) now works correctly with namespaced sniffs + - Thanks to [Maik Penz][@goatherd] for the patch +- Docs added for the entire Generic standard, and many sniffs from other standards are now documented as well + - Thanks to [Spencer Rinehart][@nubs] for the contribution +- Clearer error message for when the sniff class name does not match the directory structure +- Generated HTML docs now correctly show the open PHP tag in code comparison blocks +- Added Generic InlineHTMLSniff to ensure a file only contains PHP code +- Added Squiz ShorthandSizeSniff to check that CSS sizes are using shorthand notation only when 1 or 2 values are used +- Added Squiz ForbiddenStylesSniff to ban the use of some deprecated browser-specific styles +- Added Squiz NamedColoursSniff to ban the use of colour names +- PSR2 standard no longer enforces no whitespace between the closing parenthesis of a function call and the semicolon +- PSR2 ClassDeclarationSniff now ignores empty classes when checking the end brace position +- PSR2 SwitchDeclarationSniff no longer reports errors for empty lines between CASE statements +- PEAR ObjectOperatorIndentSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the indent setting in a ruleset.xml file to change + - Thanks to [Andrey Mindubaev][@covex-nn] for the patch +- Squiz FileExtensionSniff now supports traits + - Thanks to [Lucas Green][@mythril] for the patch +- Squiz ArrayDeclarationSniff no longer reports errors for no comma at the end of a line that contains a function call +- Squiz SwitchDeclarationSniff now supports T_CONTINUE and T_THROW as valid case/default breaking statements +- Squiz CommentedOutCodeSniff is now better at ignoring commented out HTML, XML and regular expressions +- Squiz DisallowComparisonAssignmentSniff no longer throws errors for the third expression in a FOR statement +- Squiz ColourDefinitionSniff no longer throws errors for some CSS class names +- Squiz ControlStructureSpacingSniff now supports all types of CASE/DEFAULT breaking statements +- Generic CallTimePassByReferenceSniff now reports errors for functions called using a variable + - Thanks to [Maik Penz][@goatherd] for the patch +- Generic ConstructorNameSniff no longer throws a notice for abstract constructors inside abstract classes + - Thanks to [Spencer Rinehart][@nubs] for the patch +- Squiz ComparisonOperatorUsageSniff now checks inside elseif statements + - Thanks to [Arnout Boks][@aboks] for the patch +- Squiz OperatorSpacingSniff now reports errors for no spacing around inline then and else tokens + - Thanks to [Arnout Boks][@aboks] for the patch + +### Fixed +- Fixed bug [#19811][pear-19811] : Comments not ignored in all cases in AbstractPatternSniff + - Thanks to [Erik Wiffin][@erikwiffin] for the patch +- Fixed bug [#19892][pear-19892] : ELSE with no braces causes incorrect SWITCH break statement indentation error +- Fixed bug [#19897][pear-19897] : Indenting warnings in templates not consistent +- Fixed bug [#19908][pear-19908] : PEAR MultiLineCondition Does Not Apply elseif +- Fixed bug [#19913][pear-19913] : Running phpcs in interactive mode causes warnings + - Thanks to [Harald Franndorfer][pear-gemineye] for the patch +- Fixed bug [#19935][pear-19935] : notify-send reports do not vanish in gnome-shell + - Thanks to [Christian Weiske][@cweiske] for the patch +- Fixed bug [#19944][pear-19944] : docblock squiz sniff "return void" trips over return in lambda function +- Fixed bug [#19953][pear-19953] : PSR2 - Spaces before interface name for abstract class +- Fixed bug [#19956][pear-19956] : phpcs warns for Type Hint missing Resource +- Fixed bug [#19957][pear-19957] : Does not understand trait method aliasing +- Fixed bug [#19968][pear-19968] : Permission denied on excluded directory +- Fixed bug [#19969][pear-19969] : Sniffs with namespace not recognized in reports +- Fixed bug [#19997][pear-19997] : Class names incorrectly detected as constants + +[pear-19811]: https://pear.php.net/bugs/bug.php?id=19811 +[pear-19892]: https://pear.php.net/bugs/bug.php?id=19892 +[pear-19897]: https://pear.php.net/bugs/bug.php?id=19897 +[pear-19908]: https://pear.php.net/bugs/bug.php?id=19908 +[pear-19913]: https://pear.php.net/bugs/bug.php?id=19913 +[pear-19935]: https://pear.php.net/bugs/bug.php?id=19935 +[pear-19944]: https://pear.php.net/bugs/bug.php?id=19944 +[pear-19953]: https://pear.php.net/bugs/bug.php?id=19953 +[pear-19956]: https://pear.php.net/bugs/bug.php?id=19956 +[pear-19957]: https://pear.php.net/bugs/bug.php?id=19957 +[pear-19968]: https://pear.php.net/bugs/bug.php?id=19968 +[pear-19969]: https://pear.php.net/bugs/bug.php?id=19969 +[pear-19997]: https://pear.php.net/bugs/bug.php?id=19997 + +## [1.5.0RC2] - 2013-04-04 + +### Changed +- Ruleset processing has been rewritten to be more predictable + - Provides much better support for relative paths inside ruleset files + - May mean that sniffs that were previously ignored are now being included when importing external rulesets + - Ruleset processing output can be seen by using the -vv command line argument + - Internal sniff registering functions have all changed, so please review custom scripts +- You can now pass multiple coding standards on the command line, comma separated (request [#19144][pear-19144]) + - Works with built-in or custom standards and rulesets, or a mix of both +- You can now exclude directories or whole standards in a ruleset XML file (request [#19731][pear-19731]) + - e.g., exclude "Generic.Commenting" or just "Generic" + - You can also pass in a path to a directory instead, if you know it +- Added Generic LowerCaseKeywordSniff to ensure all PHP keywords are defined in lowercase + - The PSR2 and Squiz standards now use this sniff +- Added Generic SAPIUsageSniff to ensure the `PHP_SAPI` constant is used instead of `php_sapi_name()` (request [#19863][pear-19863]) +- Squiz FunctionSpacingSniff now has a setting to specify how many lines there should between functions (request [#19843][pear-19843]) + - Default remains at 2 + - Override the "spacing" setting in a ruleset.xml file to change +- Squiz LowercasePHPFunctionSniff no longer throws errors for the limited set of PHP keywords it was checking + - Add a rule for Generic.PHP.LowerCaseKeyword to your ruleset to replicate this functionality +- Added support for the PHP 5.4 T_CALLABLE token so it can be used in lower PHP versions +- Generic EndFileNoNewlineSniff now supports checking of CSS and JS files +- PSR2 SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the indent setting in a ruleset.xml file to change + - Thanks to [Asher Snyder][@asnyder] for the patch +- Generic ScopeIndentSniff now has a setting to specify a list of tokens that should be ignored + - The first token on the line is checked and the whole line is ignored if the token is in the array + - Thanks to [Eloy Lafuente][@stronk7] for the patch +- Squiz LowercaseClassKeywordsSniff now checks for the TRAIT keyword + - Thanks to [Anthon Pang][@robocoder] for the patch +- If you create your own PHP_CodeSniffer object, PHPCS will no longer exit when an unknown argument is found + - This allows you to create wrapper scripts for PHPCS more easily +- PSR2 MethodDeclarationSniff no longer generates a notice for methods named "_" + - Thanks to [Bart S][@zBart] for the patch +- Squiz BlockCommentSniff no longer reports that a blank line between a scope closer and block comment is invalid +- Generic DuplicateClassNameSniff no longer reports an invalid error if multiple PHP open tags exist in a file +- Generic DuplicateClassNameSniff no longer reports duplicate errors if multiple PHP open tags exist in a file + +### Fixed +- Fixed bug [#19819][pear-19819] : Freeze with syntax error in use statement +- Fixed bug [#19820][pear-19820] : Wrong message level in Generic_Sniffs_CodeAnalysis_EmptyStatementSniff +- Fixed bug [#19859][pear-19859] : CodeSniffer::setIgnorePatterns API changed +- Fixed bug [#19871][pear-19871] : findExtendedClassName doesn't return FQCN on namespaced classes +- Fixed bug [#19879][pear-19879] : bitwise and operator interpreted as reference by value + +[pear-19144]: https://pear.php.net/bugs/bug.php?id=19144 +[pear-19731]: https://pear.php.net/bugs/bug.php?id=19731 + +## [1.4.5] - 2013-04-04 + +### Changed +- Added Generic LowerCaseKeywordSniff to ensure all PHP keywords are defined in lowercase + - The PSR2 and Squiz standards now use this sniff +- Added Generic SAPIUsageSniff to ensure the `PHP_SAPI` constant is used instead of `php_sapi_name()` (request [#19863][pear-19863]) +- Squiz FunctionSpacingSniff now has a setting to specify how many lines there should between functions (request [#19843][pear-19843]) + - Default remains at 2 + - Override the "spacing" setting in a ruleset.xml file to change +- Squiz LowercasePHPFunctionSniff no longer throws errors for the limited set of PHP keywords it was checking + - Add a rule for Generic.PHP.LowerCaseKeyword to your ruleset to replicate this functionality +- Added support for the PHP 5.4 T_CALLABLE token so it can be used in lower PHP versions +- Generic EndFileNoNewlineSniff now supports checking of CSS and JS files +- PSR2 SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented + - Default remains at 4; override the indent setting in a ruleset.xml file to change + - Thanks to [Asher Snyder][@asnyder] for the patch +- Generic ScopeIndentSniff now has a setting to specify a list of tokens that should be ignored + - The first token on the line is checked and the whole line is ignored if the token is in the array + - Thanks to [Eloy Lafuente][@stronk7] for the patch +- Squiz LowercaseClassKeywordsSniff now checks for the TRAIT keyword + - Thanks to [Anthon Pang][@robocoder] for the patch +- If you create your own PHP_CodeSniffer object, PHPCS will no longer exit when an unknown argument is found + - This allows you to create wrapper scripts for PHPCS more easily +- PSR2 MethodDeclarationSniff no longer generates a notice for methods named "_" + - Thanks to [Bart S][@zBart] for the patch +- Squiz BlockCommentSniff no longer reports that a blank line between a scope closer and block comment is invalid +- Generic DuplicateClassNameSniff no longer reports an invalid error if multiple PHP open tags exist in a file +- Generic DuplicateClassNameSniff no longer reports duplicate errors if multiple PHP open tags exist in a file + +### Fixed +- Fixed bug [#19819][pear-19819] : Freeze with syntax error in use statement +- Fixed bug [#19820][pear-19820] : Wrong message level in Generic_Sniffs_CodeAnalysis_EmptyStatementSniff +- Fixed bug [#19859][pear-19859] : CodeSniffer::setIgnorePatterns API changed +- Fixed bug [#19871][pear-19871] : findExtendedClassName doesn't return FQCN on namespaced classes +- Fixed bug [#19879][pear-19879] : bitwise and operator interpreted as reference by value + +[pear-19819]: https://pear.php.net/bugs/bug.php?id=19819 +[pear-19820]: https://pear.php.net/bugs/bug.php?id=19820 +[pear-19843]: https://pear.php.net/bugs/bug.php?id=19843 +[pear-19859]: https://pear.php.net/bugs/bug.php?id=19859 +[pear-19863]: https://pear.php.net/bugs/bug.php?id=19863 +[pear-19871]: https://pear.php.net/bugs/bug.php?id=19871 +[pear-19879]: https://pear.php.net/bugs/bug.php?id=19879 + +## [1.5.0RC1] - 2013-02-08 + +### Changed +- Reports have been completely rewritten to consume far less memory + - Each report is incrementally written to the file system during a run and then printed out when the run ends + - There is no longer a need to keep the list of errors and warnings in memory during a run +- Multi-file sniff support has been removed because they are too memory intensive + - If you have a custom multi-file sniff, you can convert it into a standard sniff quite easily + - See `CodeSniffer/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php` for an example + +## [1.4.4] - 2013-02-07 + +### Changed +- Ignored lines no longer cause the summary report to show incorrect error and warning counts + - Thanks to [Bert Van Hauwaert][@becoded] for the patch +- Added Generic CSSLintSniff to run CSSLint over a CSS file and report warnings + - Set full command to run CSSLint using phpcs --config-set csslint_path /path/to/csslint + - Thanks to [Roman Levishchenko][@index0h] for the contribution +- Added PSR2 ControlStructureSpacingSniff to ensure there are no spaces before and after parenthesis in control structures + - Fixes bug [#19732][pear-19732] : PSR2: some control structures errors not reported +- Squiz commenting sniffs now support non-English characters when checking for capital letters + - Thanks to [Roman Levishchenko][@index0h] for the patch +- Generic EndFileNewlineSniff now supports JS and CSS files + - Thanks to [Denis Ryabkov][@dryabkov] for the patch +- PSR1 SideEffectsSniff no longer reports constant declarations as side effects +- Notifysend report now supports notify-send versions before 0.7.3 + - Thanks to [Ken Guest][@kenguest] for the patch +- PEAR and Squiz FunctionCommentSniffs no longer report errors for misaligned argument comments when they are blank + - Thanks to [Thomas Peterson][@boonkerz] for the patch +- Squiz FunctionDeclarationArgumentSpacingSniff now works correctly for equalsSpacing values greater than 0 + - Thanks to [Klaus Purer][@klausi] for the patch +- Squiz SuperfluousWhitespaceSniff no longer throws errors for CSS files with no newline at the end +- Squiz SuperfluousWhitespaceSniff now allows a single newline at the end of JS and CSS files + +### Fixed +- Fixed bug [#19755][pear-19755] : Token of T_CLASS type has no scope_opener and scope_closer keys +- Fixed bug [#19759][pear-19759] : Squiz.PHP.NonExecutableCode fails for return function()... +- Fixed bug [#19763][pear-19763] : Use statements for traits not recognised correctly for PSR2 code style +- Fixed bug [#19764][pear-19764] : Instead of for traits throws uppercase constant name errors +- Fixed bug [#19772][pear-19772] : PSR2_Sniffs_Namespaces_UseDeclarationSniff does not properly recognize last use +- Fixed bug [#19775][pear-19775] : False positive in NonExecutableCode sniff when not using curly braces +- Fixed bug [#19782][pear-19782] : Invalid found size functions in loop when using object operator +- Fixed bug [#19799][pear-19799] : config folder is not created automatically +- Fixed bug [#19804][pear-19804] : JS Tokenizer wrong /**/ parsing + +[pear-19732]: https://pear.php.net/bugs/bug.php?id=19732 +[pear-19755]: https://pear.php.net/bugs/bug.php?id=19755 +[pear-19759]: https://pear.php.net/bugs/bug.php?id=19759 +[pear-19763]: https://pear.php.net/bugs/bug.php?id=19763 +[pear-19764]: https://pear.php.net/bugs/bug.php?id=19764 +[pear-19772]: https://pear.php.net/bugs/bug.php?id=19772 +[pear-19775]: https://pear.php.net/bugs/bug.php?id=19775 +[pear-19782]: https://pear.php.net/bugs/bug.php?id=19782 +[pear-19799]: https://pear.php.net/bugs/bug.php?id=19799 +[pear-19804]: https://pear.php.net/bugs/bug.php?id=19804 + +## [1.4.3] - 2012-12-04 + +### Changed +- Added support for the PHP 5.5 T_FINALLY token to detect try/catch/finally statements +- Added empty CodeSniffer.conf to enable config settings for Composer installs +- Added Generic EndFileNoNewlineSniff to ensure there is no newline at the end of a file +- Autoloader can now load PSR-0 compliant classes + - Thanks to [Maik Penz][@goatherd] for the patch +- Squiz NonExecutableCodeSniff no longer throws error for multi-line RETURNs inside CASE statements + - Thanks to [Marc Ypes][@ceeram] for the patch +- Squiz OperatorSpacingSniff no longer reports errors for negative numbers inside inline THEN statements + - Thanks to [Klaus Purer][@klausi] for the patch +- Squiz OperatorSpacingSniff no longer reports errors for the assignment of operations involving negative numbers +- Squiz SelfMemberReferenceSniff can no longer get into an infinite loop when checking a static call with a namespace + - Thanks to [Andy Grunwald][@andygrunwald] for the patch + +### Fixed +- Fixed bug [#19699][pear-19699] : Generic.Files.LineLength giving false positives when tab-width is used +- Fixed bug [#19726][pear-19726] : Wrong number of spaces expected after instanceof static +- Fixed bug [#19727][pear-19727] : PSR2: no error reported when using } elseif { + +[pear-19699]: https://pear.php.net/bugs/bug.php?id=19699 +[pear-19726]: https://pear.php.net/bugs/bug.php?id=19726 +[pear-19727]: https://pear.php.net/bugs/bug.php?id=19727 + +## [1.4.2] - 2012-11-09 + +### Changed +- PHP_CodeSniffer can now be installed using Composer + - Require `squizlabs/php_codesniffer` in your `composer.json` file + - Thanks to [Rob Bast][@alcohol], [Stephen Rees-Carter][@valorin], [Stefano Kowalke][@Konafets] and [Ivan Habunek][@ihabunek] for help with this +- Squiz BlockCommentSniff and InlineCommentSniff no longer report errors for trait block comments +- Squiz SelfMemberReferenceSniff now supports namespaces + - Thanks to [Andy Grunwald][@andygrunwald] for the patch +- Squiz FileCommentSniff now uses tag names inside the error codes for many messages + - This allows you to exclude specific missing, out of order etc., tags +- Squiz SuperfluousWhitespaceSniff now has an option to ignore blank lines + - This will stop errors being reported for lines that contain only whitespace + - Set the ignoreBlankLines property to TRUE in your ruleset.xml file to enable this +- PSR2 no longer reports errors for whitespace at the end of blank lines + +### Fixed +- Fixed gitblame report not working on Windows + - Thanks to [Rogerio Prado de Jesus][@rogeriopradoj] +- Fixed an incorrect error in Squiz OperatorSpacingSniff for default values inside a closure definition +- Fixed bug [#19691][pear-19691] : SubversionPropertiesSniff fails to find missing properties + - Thanks to [Kevin Winahradsky][pear-kwinahradsky] for the patch +- Fixed bug [#19692][pear-19692] : DisallowMultipleAssignments is triggered by a closure +- Fixed bug [#19693][pear-19693] : exclude-patterns no longer work on specific messages +- Fixed bug [#19694][pear-19694] : Squiz.PHP.LowercasePHPFunctions incorrectly matches return by ref functions + +[pear-19691]: https://pear.php.net/bugs/bug.php?id=19691 +[pear-19692]: https://pear.php.net/bugs/bug.php?id=19692 +[pear-19693]: https://pear.php.net/bugs/bug.php?id=19693 +[pear-19694]: https://pear.php.net/bugs/bug.php?id=19694 + +## [1.4.1] - 2012-11-02 + +### Changed +- All ignore patterns have been reverted to being checked against the absolute path of a file + - Patterns can be specified to be relative in a ruleset.xml file, but nowhere else + - e.g., `^tests/*` +- Added support for PHP tokenizing of T_INLINE_ELSE colons, so this token type is now available + - Custom sniffs that rely on looking for T_COLON tokens inside inline if statements must be changed to use the new token + - Fixes bug [#19666][pear-19666] : PSR1.Files.SideEffects throws a notice Undefined index: scope_closer +- Messages can now be changed from errors to warnings (and vice versa) inside ruleset.xml files + - As you would with "message" and "severity", specify a "type" tag under a "rule" tag and set the value to "error" or "warning" +- PHP_CodeSniffer will now generate a warning on files that it detects have mixed line endings + - This warning has the code Internal.LineEndings.Mixed and can be overridden in a ruleset.xml file + - Thanks to [Vit Brunner][@tasuki] for help with this +- Sniffs inside PHP 5.3 namespaces are now supported, along with the existing underscore-style emulated namespaces + - For example: namespace MyStandard\Sniffs\Arrays; class ArrayDeclarationSniff implements \PHP_CodeSniffer_Sniff { ... + - Thanks to [Till Klampaeckel][@till] for the patch +- Generic DuplicateClassNameSniff is no longer a multi-file sniff, so it won't max out your memory + - Multi-file sniff support should be considered deprecated as standard sniffs can now do the same thing +- Added Generic DisallowSpaceIndent to check that files are indented using tabs +- Added Generic OneClassPerFileSniff to check that only one class is defined in each file + - Thanks to [Andy Grunwald][@andygrunwald] for the contribution +- Added Generic OneInterfacePerFileSniff to check that only one interface is defined in each file + - Thanks to [Andy Grunwald][@andygrunwald] for the contribution +- Added Generic LowercasedFilenameSniff to check that filenames are lowercase + - Thanks to [Andy Grunwald][@andygrunwald] for the contribution +- Added Generic ClosingPHPTagSniff to check that each open PHP tag has a corresponding close tag + - Thanks to [Andy Grunwald][@andygrunwald] for the contribution +- Added Generic CharacterBeforePHPOpeningTagSniff to check that the open PHP tag is the first content in a file + - Thanks to [Andy Grunwald][@andygrunwald] for the contribution +- Fixed incorrect errors in Squiz OperatorBracketSniff and OperatorSpacingSniff for negative numbers in CASE statements + - Thanks to [Arnout Boks][@aboks] for the patch +- Generic CamelCapsFunctionNameSniff no longer enforces exact case matching for PHP magic methods +- Generic CamelCapsFunctionNameSniff no longer throws errors for overridden SOAPClient methods prefixed with double underscores + - Thanks to [Dorian Villet][@gnutix] for the patch +- PEAR ValidFunctionNameSniff now supports traits +- PSR1 ClassDeclarationSniff no longer throws an error for non-namespaced code if PHP version is less than 5.3.0 + +### Fixed +- Fixed bug [#19616][pear-19616] : Nested switches cause false error in PSR2 +- Fixed bug [#19629][pear-19629] : PSR2 error for inline comments on multi-line argument lists +- Fixed bug [#19644][pear-19644] : Alternative syntax, e.g. if/endif triggers Inline Control Structure error +- Fixed bug [#19655][pear-19655] : Closures reporting as multi-line when they are not +- Fixed bug [#19675][pear-19675] : Improper indent of nested anonymous function bodies in a call +- Fixed bug [#19685][pear-19685] : PSR2 catch-22 with empty third statement in for loop +- Fixed bug [#19687][pear-19687] : Anonymous functions inside arrays marked as indented incorrectly in PSR2 + +[pear-19616]: https://pear.php.net/bugs/bug.php?id=19616 +[pear-19629]: https://pear.php.net/bugs/bug.php?id=19629 +[pear-19644]: https://pear.php.net/bugs/bug.php?id=19644 +[pear-19655]: https://pear.php.net/bugs/bug.php?id=19655 +[pear-19666]: https://pear.php.net/bugs/bug.php?id=19666 +[pear-19675]: https://pear.php.net/bugs/bug.php?id=19675 +[pear-19685]: https://pear.php.net/bugs/bug.php?id=19685 +[pear-19687]: https://pear.php.net/bugs/bug.php?id=19687 + +## [1.4.0] - 2012-09-26 + +### Changed +- Added PSR1 and PSR2 coding standards that can be used to check your code against these guidelines +- PHP 5.4 short array syntax is now detected and tokens are assigned to the open and close characters + - New tokens are T_OPEN_SHORT_ARRAY and T_CLOSE_SHORT_ARRAY as PHP does not define its own +- Added the ability to explain a coding standard by listing the sniffs that it includes + - The sniff list includes all imported and native sniffs + - Explain a standard by using the `-e` and `--standard=[standard]` command line arguments + - E.g., `phpcs -e --standard=Squiz` + - Thanks to [Ben Selby][@benmatselby] for the idea +- Added report to show results using notify-send + - Use --report=notifysend to generate the report + - Thanks to [Christian Weiske][@cweiske] for the contribution +- The JS tokenizer now recognises RETURN as a valid closer for CASE and DEFAULT inside switch statements +- AbstractPatternSniff now sets the ignoreComments option using a public var rather than through the constructor + - This allows the setting to be overwritten in ruleset.xml files + - Old method remains for backwards compatibility +- Generic LowerCaseConstantSniff and UpperCaseConstantSniff no longer report errors on classes named True, False or Null +- PEAR ValidFunctionNameSniff no longer enforces exact case matching for PHP magic methods +- Squiz SwitchDeclarationSniff now allows RETURN statements to close a CASE or DEFAULT statement +- Squiz BlockCommentSniff now correctly reports an error for blank lines before blocks at the start of a control structure + +### Fixed +- Fixed a PHP notice generated when loading custom array settings from a ruleset.xml file +- Fixed bug [#17908][pear-17908] : CodeSniffer does not recognise optional @params + - Thanks to [Pete Walker][pear-pete] for the patch +- Fixed bug [#19538][pear-19538] : Function indentation code sniffer checks inside short arrays +- Fixed bug [#19565][pear-19565] : Non-Executable Code Sniff Broken for Case Statements with both return and break +- Fixed bug [#19612][pear-19612] : Invalid @package suggestion + +[pear-17908]: https://pear.php.net/bugs/bug.php?id=17908 +[pear-19538]: https://pear.php.net/bugs/bug.php?id=19538 +[pear-19565]: https://pear.php.net/bugs/bug.php?id=19565 +[pear-19612]: https://pear.php.net/bugs/bug.php?id=19612 + +## [1.3.6] - 2012-08-08 + +### Changed +- Memory usage has been dramatically reduced when using the summary report + - Reduced memory is only available when displaying a single summary report to the screen + - PHP_CodeSniffer will not generate any messages in this case, storing only error counts instead + - Impact is most notable with very high error and warning counts +- Significantly improved the performance of Squiz NonExecutableCodeSniff +- Ignore patterns now check the relative path of a file based on the dir being checked + - Allows ignore patterns to become more generic as the path to the code is no longer included when checking + - Thanks to [Kristof Coomans][@kristofser] for the patch +- Sniff settings can now be changed by specifying a special comment format inside a file + - e.g., // @codingStandardsChangeSetting PEAR.Functions.FunctionCallSignature allowMultipleArguments false + - If you change a setting, don't forget to change it back +- Added Generic EndFileNewlineSniff to ensure PHP files end with a newline character +- PEAR FunctionCallSignatureSniff now includes a setting to force one argument per line in multi-line calls + - Set allowMultipleArguments to false +- Squiz standard now enforces one argument per line in multi-line function calls +- Squiz FunctionDeclarationArgumentSpacingSniff now supports closures +- Squiz OperatorSpacingSniff no longer throws an error for negative values inside an inline THEN statement + - Thanks to [Klaus Purer][@klausi] for the patch +- Squiz FunctionCommentSniff now throws an error for not closing a comment with */ + - Thanks to [Klaus Purer][@klausi] for the patch +- Summary report no longer shows two lines of PHP_Timer output when showing sources + +### Fixed +- Fixed undefined variable error in PEAR FunctionCallSignatureSniff for lines with no indent +- Fixed bug [#19502][pear-19502] : Generic.Files.LineEndingsSniff fails if no new-lines in file +- Fixed bug [#19508][pear-19508] : switch+return: Closing brace indented incorrectly +- Fixed bug [#19532][pear-19532] : The PSR-2 standard don't recognize Null in class names +- Fixed bug [#19546][pear-19546] : Error thrown for __call() method in traits + +[pear-19502]: https://pear.php.net/bugs/bug.php?id=19502 +[pear-19508]: https://pear.php.net/bugs/bug.php?id=19508 +[pear-19532]: https://pear.php.net/bugs/bug.php?id=19532 +[pear-19546]: https://pear.php.net/bugs/bug.php?id=19546 + +## [1.3.5] - 2012-07-12 + +### Changed +- Added Generic CamelCapsFunctionNameSniff to just check if function and method names use camel caps + - Does not allow underscore prefixes for private/protected methods + - Defaults to strict checking, where two uppercase characters can not be next to each other + - Strict checking can be disabled in a ruleset.xml file +- Squiz FunctionDeclarationArgumentSpacing now has a setting to specify how many spaces should surround equals signs + - Default remains at 0 + - Override the equalsSpacing setting in a ruleset.xml file to change +- Squiz ClassDeclarationSniff now throws errors for > 1 space before extends/implements class name with ns separator +- Squiz standard now warns about deprecated functions using Generic DeprecatedFunctionsSniff +- PEAR FunctionDeclarationSniff now reports an error for multiple spaces after the FUNCTION keyword and around USE +- PEAR FunctionDeclarationSniff now supports closures +- Squiz MultiLineFunctionDeclarationSniff now supports closures +- Exclude rules written for Unix systems will now work correctly on Windows + - Thanks to [Walter Tamboer][@waltertamboer] for the patch +- The PHP tokenizer now recognises T_RETURN as a valid closer for T_CASE and T_DEFAULT inside switch statements + +### Fixed +- Fixed duplicate message codes in Generic OpeningFunctionBraceKernighanRitchieSniff +- Fixed bug [#18651][pear-18651] : PHPUnit Test cases for custom standards are not working on Windows +- Fixed bug [#19416][pear-19416] : Shorthand arrays cause bracket spacing errors +- Fixed bug [#19421][pear-19421] : phpcs doesn't recognize ${x} as equivalent to $x +- Fixed bug [#19428][pear-19428] : PHPCS Report "hgblame" doesn't support windows paths + - Thanks to [Justin Rovang][@rovangju] for the patch +- Fixed bug [#19448][pear-19448] : Problem with detecting remote standards +- Fixed bug [#19463][pear-19463] : Anonymous functions incorrectly being flagged by NonExecutableCodeSniff +- Fixed bug [#19469][pear-19469] : PHP_CodeSniffer_File::getMemberProperties() sets wrong scope +- Fixed bug [#19471][pear-19471] : phpcs on Windows, when using Zend standard, doesn't catch problems + - Thanks to [Ivan Habunek][@ihabunek] for the patch +- Fixed bug [#19478][pear-19478] : Incorrect indent detection in PEAR standard + - Thanks to [Shane Auckland][@shanethehat] for the patch +- Fixed bug [#19483][pear-19483] : Blame Reports fail with space in directory name + +[pear-18651]: https://pear.php.net/bugs/bug.php?id=18651 +[pear-19416]: https://pear.php.net/bugs/bug.php?id=19416 +[pear-19421]: https://pear.php.net/bugs/bug.php?id=19421 +[pear-19428]: https://pear.php.net/bugs/bug.php?id=19428 +[pear-19448]: https://pear.php.net/bugs/bug.php?id=19448 +[pear-19463]: https://pear.php.net/bugs/bug.php?id=19463 +[pear-19469]: https://pear.php.net/bugs/bug.php?id=19469 +[pear-19471]: https://pear.php.net/bugs/bug.php?id=19471 +[pear-19478]: https://pear.php.net/bugs/bug.php?id=19478 +[pear-19483]: https://pear.php.net/bugs/bug.php?id=19483 + +## [1.3.4] - 2012-05-17 + +### Changed +- Added missing package.xml entries for new Generic FixmeSniff + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Expected indents for PEAR ScopeClosingBraceSniff and FunctionCallSignatureSniff can now be set in ruleset files + - Both sniffs use a variable called "indent" + - Thanks to [Thomas Despoix][pear-tomdesp] for the patch +- Standards designed to be installed in the PHPCS Standards dir will now work outside this dir as well + - In particular, allows the Drupal CS to work without needing to symlink it into the PHPCS install + - Thanks to [Peter Philipp][@das-peter] for the patch +- Rule references for standards, directories and specific sniffs can now be relative in ruleset.xml files + - For example: `ref="../MyStandard/Sniffs/Commenting/DisallowHashCommentsSniff.php"` +- Symlinked standards now work correctly, allowing aliasing of installed standards (request [#19417][pear-19417]) + - Thanks to [Tom Klingenberg][@ktomk] for the patch +- Squiz ObjectInstantiationSniff now allows objects to be returned without assigning them to a variable +- Added Squiz.Commenting.FileComment.MissingShort error message for file comments that only contains tags + - Also stops undefined index errors being generated for these comments +- Debug option -vv now shows tokenizer status for CSS files +- Added support for new gjslint error formats + - Thanks to [Meck][@yesmeck] for the patch +- Generic ScopeIndentSniff now allows comment indents to not be exact even if the exact flag is set + - The start of the comment is still checked for exact indentation as normal +- Fixed an issue in AbstractPatternSniff where comments were not being ignored in some cases +- Fixed an issue in Zend ClosingTagSniff where the closing tag was not always being detected correctly + - Thanks to [Jonathan Robson][@jnrbsn] for the patch +- Fixed an issue in Generic FunctionCallArgumentSpacingSniff where closures could cause incorrect errors +- Fixed an issue in Generic UpperCaseConstantNameSniff where errors were incorrectly reported on goto statements + - Thanks to [Tom Klingenberg][@ktomk] for the patch +- PEAR FileCommentSniff and ClassCommentSniff now support author emails with a single character in the local part + - E.g., `a@me.com` + - Thanks to Denis Shapkin for the patch + +### Fixed +- Fixed bug [#19290][pear-19290] : Generic indent sniffer fails for anonymous functions +- Fixed bug [#19324][pear-19324] : Setting show_warnings configuration option does not work +- Fixed bug [#19354][pear-19354] : Not recognizing references passed to method +- Fixed bug [#19361][pear-19361] : CSS tokenizer generates errors when PHP embedded in CSS file +- Fixed bug [#19374][pear-19374] : HEREDOC/NOWDOC Indentation problems +- Fixed bug [#19381][pear-19381] : traits and indentations in traits are not handled properly +- Fixed bug [#19394][pear-19394] : Notice in NonExecutableCodeSniff +- Fixed bug [#19402][pear-19402] : Syntax error when executing phpcs on Windows with parens in PHP path + - Thanks to [Tom Klingenberg][@ktomk] for the patch +- Fixed bug [#19411][pear-19411] : magic method error on __construct() + - The fix required a rewrite of AbstractScopeSniff, so please test any sniffs that extend this class +- Fixed bug [#19412][pear-19412] : Incorrect error about assigning objects to variables when inside inline IF +- Fixed bug [#19413][pear-19413] : PHP_CodeSniffer thinks I haven't used a parameter when I have +- Fixed bug [#19414][pear-19414] : PHP_CodeSniffer seems to not track variables correctly in heredocs + +[pear-19290]: https://pear.php.net/bugs/bug.php?id=19290 +[pear-19324]: https://pear.php.net/bugs/bug.php?id=19324 +[pear-19354]: https://pear.php.net/bugs/bug.php?id=19354 +[pear-19361]: https://pear.php.net/bugs/bug.php?id=19361 +[pear-19374]: https://pear.php.net/bugs/bug.php?id=19374 +[pear-19381]: https://pear.php.net/bugs/bug.php?id=19381 +[pear-19394]: https://pear.php.net/bugs/bug.php?id=19394 +[pear-19402]: https://pear.php.net/bugs/bug.php?id=19402 +[pear-19411]: https://pear.php.net/bugs/bug.php?id=19411 +[pear-19412]: https://pear.php.net/bugs/bug.php?id=19412 +[pear-19413]: https://pear.php.net/bugs/bug.php?id=19413 +[pear-19414]: https://pear.php.net/bugs/bug.php?id=19414 +[pear-19417]: https://pear.php.net/bugs/bug.php?id=19417 + +## [1.3.3] - 2012-02-07 + +### Changed +- Added new Generic FixmeSniff that shows error messages for all FIXME comments left in your code + - Thanks to [Sam Graham][@illusori] for the contribution +- The maxPercentage setting in the Squiz CommentedOutCodeSniff can now be overridden in a ruleset.xml file + - Thanks to [Volker Dusch][@edorian] for the patch +- The Checkstyle and XML reports now use XMLWriter + - Only change in output is that empty file tags are no longer produced for files with no violations + - Thanks to [Sebastian Bergmann][@sebastianbergmann] for the patch +- Added PHP_CodeSniffer_Tokens::$bracketTokens to give sniff writers fast access to open and close bracket tokens +- Fixed an issue in AbstractPatternSniff where EOL tokens were not being correctly checked in some cases +- PHP_CodeSniffer_File::getTokensAsString() now detects incorrect length value (request [#19313][pear-19313]) + +### Fixed +- Fixed bug [#19114][pear-19114] : CodeSniffer checks extension even for single file +- Fixed bug [#19171][pear-19171] : Show sniff codes option is ignored by some report types + - Thanks to [Dominic Scheirlinck][@dominics] for the patch +- Fixed bug [#19188][pear-19188] : Lots of PHP Notices when analyzing the Symfony framework + - First issue was list-style.. lines in CSS files not properly adjusting open/close bracket positions + - Second issue was notices caused by bug [#19137][pear-19137] +- Fixed bug [#19208][pear-19208] : UpperCaseConstantName reports class members + - Was also a problem with LowerCaseConstantName as well +- Fixed bug [#19256][pear-19256] : T_DOC_COMMENT in CSS files breaks ClassDefinitionNameSpacingSniff + - Thanks to [Klaus Purer][@klausi] for the patch +- Fixed bug [#19264][pear-19264] : Squiz.PHP.NonExecutableCode does not handle RETURN in CASE without BREAK +- Fixed bug [#19270][pear-19270] : DuplicateClassName does not handle namespaces correctly +- Fixed bug [#19283][pear-19283] : CSS @media rules cause false positives + - Thanks to [Klaus Purer][@klausi] for the patch + +[pear-19114]: https://pear.php.net/bugs/bug.php?id=19114 +[pear-19137]: https://pear.php.net/bugs/bug.php?id=19137 +[pear-19171]: https://pear.php.net/bugs/bug.php?id=19171 +[pear-19188]: https://pear.php.net/bugs/bug.php?id=19188 +[pear-19208]: https://pear.php.net/bugs/bug.php?id=19208 +[pear-19256]: https://pear.php.net/bugs/bug.php?id=19256 +[pear-19264]: https://pear.php.net/bugs/bug.php?id=19264 +[pear-19270]: https://pear.php.net/bugs/bug.php?id=19270 +[pear-19283]: https://pear.php.net/bugs/bug.php?id=19283 +[pear-19313]: https://pear.php.net/bugs/bug.php?id=19313 + +## [1.3.2] - 2011-12-01 + +### Changed +- Added Generic JSHintSniff to run jshint.js over a JS file and report warnings + - Set jshint path using phpcs --config-set jshint_path /path/to/jshint-rhino.js + - Set rhino path using phpcs --config-set rhino_path /path/to/rhino + - Thanks to Alexander Weiß for the contribution +- Nowdocs are now tokenized using PHP_CodeSniffer specific T_NOWDOC tokens for easier identification +- Generic UpperCaseConstantNameSniff no longer throws errors for namespaces + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Squiz NonExecutableCodeSniff now detects code after thrown exceptions + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Squiz OperatorSpacingSniff now ignores references + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Squiz FunctionCommentSniff now reports a missing function comment if it finds a standard code comment instead +- Squiz FunctionCommentThrownTagSniff no longer reports errors if it can't find a function comment + +### Fixed +- Fixed unit tests not running under Windows + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#18964][pear-18964] : "$stackPtr must be of type T_VARIABLE" on heredocs and nowdocs +- Fixed bug [#18973][pear-18973] : phpcs is looking for variables in a nowdoc +- Fixed bug [#18974][pear-18974] : Blank line causes "Multi-line function call not indented correctly" + - Adds new error message to ban empty lines in multi-line function calls +- Fixed bug [#18975][pear-18975] : "Closing parenthesis must be on a line by itself" also causes indentation error + +[pear-18964]: https://pear.php.net/bugs/bug.php?id=18964 +[pear-18973]: https://pear.php.net/bugs/bug.php?id=18973 +[pear-18974]: https://pear.php.net/bugs/bug.php?id=18974 +[pear-18975]: https://pear.php.net/bugs/bug.php?id=18975 + +## 1.3.1 - 2011-11-03 + +### Changed +- All report file command line arguments now work with relative paths (request [#17240][pear-17240]) +- The extensions command line argument now supports multi-part file extensions (request [#17227][pear-17227]) +- Added report type --report=hgblame to show number of errors/warnings committed by authors in a Mercurial repository + - Has the same functionality as the svnblame report + - Thanks to [Ben Selby][@benmatselby] for the patch +- Added T_BACKTICK token type to make detection of backticks easier (request [#18799][pear-18799]) +- Added pattern matching support to Generic ForbiddenFunctionsSniff + - If you are extending it and overriding register() or addError() you will need to review your sniff +- Namespaces are now recognised as scope openers, although they do not require braces (request [#18043][pear-18043]) +- Added new ByteOrderMarkSniff to Generic standard (request [#18194][pear-18194]) + - Throws an error if a byte order mark is found in any PHP file + - Thanks to [Piotr Karas][pear-ryba] for the contribution +- PHP_Timer output is no longer included in reports when being written to a file (request [#18252][pear-18252]) + - Also now shown for all report types if nothing is being printed to the screen +- Generic DeprecatedFunctionSniff now reports functions as deprecated and not simply forbidden (request [#18288][pear-18288]) +- PHPCS now accepts file contents from STDIN (request [#18447][pear-18447]) + - Example usage: `cat temp.php | phpcs [options]` -OR- `phpcs [options] < temp.php` + - Not every sniff will work correctly due to the lack of a valid file path +- PHP_CodeSniffer_Exception no longer extends PEAR_Exception (request [#18483][pear-18483]) + - PEAR_Exception added a requirement that PEAR had to be installed + - PHP_CodeSniffer is not used as a library, so unlikely to have any impact +- PEAR FileCommentSniff now allows GIT IDs in the version tag (request [#14874][pear-14874]) +- AbstractVariableSniff now supports heredocs + - Also includes some variable detection fixes + - Thanks to [Sam Graham][@illusori] for the patch +- Squiz FileCommentSniff now enforces rule that package names cannot start with the word Squiz +- MySource AssignThisSniff now allows "this" to be assigned to the private var _self +- PEAR ClassDeclaration sniff now supports indentation checks when using the alternate namespace syntax + - PEAR.Classes.ClassDeclaration.SpaceBeforeBrace message now contains 2 variables instead of 1 + - Sniff allows overriding of the default indent level, which is set to 4 + - Fixes bug [#18933][pear-18933] : Alternative namespace declaration syntax confuses scope sniffs + +### Fixed +- Fixed issue in Squiz FileCommentSniff where suggested package name was the same as the incorrect package name +- Fixed some issues with Squiz ArrayDeclarationSniff when using function calls in array values +- Fixed doc generation so it actually works again + - Also now works when being run from an SVN checkout as well as when installed as a PEAR package + - Should fix bug [#18949][pear-18949] : Call to private method from static +- Fixed bug [#18465][pear-18465] : "self::" does not work in lambda functions + - Also corrects conversion of T_FUNCTION tokens to T_CLOSURE, which was not fixing token condition arrays +- Fixed bug [#18543][pear-18543] : CSS Tokenizer deletes too many # +- Fixed bug [#18624][pear-18624] : @throws namespace problem + - Thanks to [Gavin Davies][pear-boxgav] for the patch +- Fixed bug [#18628][pear-18628] : Generic.Files.LineLength gives incorrect results with Windows line-endings +- Fixed bug [#18633][pear-18633] : CSS Tokenizer doesn't replace T_LIST tokens inside some styles +- Fixed bug [#18657][pear-18657] : anonymous functions wrongly indented +- Fixed bug [#18670][pear-18670] : UpperCaseConstantNameSniff fails on dynamic retrieval of class constant +- Fixed bug [#18709][pear-18709] : Code sniffer sniffs file even if it's in --ignore + - Thanks to [Artem Lopata][@biozshock] for the patch +- Fixed bug [#18762][pear-18762] : Incorrect handling of define and constant in UpperCaseConstantNameSniff + - Thanks to [Thomas Baker][pear-bakert] for the patch +- Fixed bug [#18769][pear-18769] : CSS Tokenizer doesn't replace T_BREAK tokens inside some styles +- Fixed bug [#18835][pear-18835] : Unreachable errors of inline returns of closure functions + - Thanks to [Patrick Schmidt][pear-woellchen] for the patch +- Fixed bug [#18839][pear-18839] : Fix miscount of warnings in `AbstractSniffUnitTest.php` + - Thanks to [Sam Graham][@illusori] for the patch +- Fixed bug [#18844][pear-18844] : Generic_Sniffs_CodeAnalysis_UnusedFunctionParameterSniff with empty body + - Thanks to [Dmitri Medvedev][pear-dvino] for the patch +- Fixed bug [#18847][pear-18847] : Running Squiz_Sniffs_Classes_ClassDeclarationSniff results in PHP notice +- Fixed bug [#18868][pear-18868] : jslint+rhino: errors/warnings not detected + - Thanks to [Christian Weiske][@cweiske] for the patch +- Fixed bug [#18879][pear-18879] : phpcs-svn-pre-commit requires escapeshellarg + - Thanks to [Bjorn Katuin][pear-bjorn] for the patch +- Fixed bug [#18951][pear-18951] : weird behaviour with closures and multi-line use () params + +[pear-14874]: https://pear.php.net/bugs/bug.php?id=14874 +[pear-17227]: https://pear.php.net/bugs/bug.php?id=17227 +[pear-17240]: https://pear.php.net/bugs/bug.php?id=17240 +[pear-18043]: https://pear.php.net/bugs/bug.php?id=18043 +[pear-18194]: https://pear.php.net/bugs/bug.php?id=18194 +[pear-18252]: https://pear.php.net/bugs/bug.php?id=18252 +[pear-18288]: https://pear.php.net/bugs/bug.php?id=18288 +[pear-18447]: https://pear.php.net/bugs/bug.php?id=18447 +[pear-18465]: https://pear.php.net/bugs/bug.php?id=18465 +[pear-18483]: https://pear.php.net/bugs/bug.php?id=18483 +[pear-18543]: https://pear.php.net/bugs/bug.php?id=18543 +[pear-18624]: https://pear.php.net/bugs/bug.php?id=18624 +[pear-18628]: https://pear.php.net/bugs/bug.php?id=18628 +[pear-18633]: https://pear.php.net/bugs/bug.php?id=18633 +[pear-18657]: https://pear.php.net/bugs/bug.php?id=18657 +[pear-18670]: https://pear.php.net/bugs/bug.php?id=18670 +[pear-18709]: https://pear.php.net/bugs/bug.php?id=18709 +[pear-18762]: https://pear.php.net/bugs/bug.php?id=18762 +[pear-18769]: https://pear.php.net/bugs/bug.php?id=18769 +[pear-18799]: https://pear.php.net/bugs/bug.php?id=18799 +[pear-18835]: https://pear.php.net/bugs/bug.php?id=18835 +[pear-18839]: https://pear.php.net/bugs/bug.php?id=18839 +[pear-18844]: https://pear.php.net/bugs/bug.php?id=18844 +[pear-18847]: https://pear.php.net/bugs/bug.php?id=18847 +[pear-18868]: https://pear.php.net/bugs/bug.php?id=18868 +[pear-18879]: https://pear.php.net/bugs/bug.php?id=18879 +[pear-18933]: https://pear.php.net/bugs/bug.php?id=18933 +[pear-18949]: https://pear.php.net/bugs/bug.php?id=18949 +[pear-18951]: https://pear.php.net/bugs/bug.php?id=18951 + +## 1.3.0 - 2011-03-17 + +### Changed +- Add a new token T_CLOSURE that replaces T_FUNCTION if the function keyword is anonymous +- Many Squiz sniffs no longer report errors when checking closures; they are now ignored +- Fixed some error messages in PEAR MultiLineConditionSniff that were not using placeholders for message data +- AbstractVariableSniff now correctly finds variable names wrapped with curly braces inside double quoted strings +- PEAR FunctionDeclarationSniff now ignores arrays in argument default values when checking multi-line declarations + +### Fixed +- Fixed bug [#18200][pear-18200] : Using custom named ruleset file as standard no longer works +- Fixed bug [#18196][pear-18196] : PEAR MultiLineCondition.SpaceBeforeOpenBrace not consistent with newline chars +- Fixed bug [#18204][pear-18204] : FunctionCommentThrowTag picks wrong exception type when throwing function call +- Fixed bug [#18222][pear-18222] : Add __invoke method to PEAR standard +- Fixed bug [#18235][pear-18235] : Invalid error generation in Squiz.Commenting.FunctionCommentThrowTag +- Fixed bug [#18250][pear-18250] : --standard with relative path skips Standards' "implicit" sniffs +- Fixed bug [#18274][pear-18274] : Multi-line IF and function call indent rules conflict +- Fixed bug [#18282][pear-18282] : Squiz doesn't handle final keyword before function comments + - Thanks to [Dave Perrett][pear-recurser] for the patch +- Fixed bug [#18336][pear-18336] : Function isUnderscoreName gives PHP notices + +[pear-18196]: https://pear.php.net/bugs/bug.php?id=18196 +[pear-18200]: https://pear.php.net/bugs/bug.php?id=18200 +[pear-18204]: https://pear.php.net/bugs/bug.php?id=18204 +[pear-18222]: https://pear.php.net/bugs/bug.php?id=18222 +[pear-18235]: https://pear.php.net/bugs/bug.php?id=18235 +[pear-18250]: https://pear.php.net/bugs/bug.php?id=18250 +[pear-18274]: https://pear.php.net/bugs/bug.php?id=18274 +[pear-18282]: https://pear.php.net/bugs/bug.php?id=18282 +[pear-18336]: https://pear.php.net/bugs/bug.php?id=18336 + +## 1.3.0RC2 - 2011-01-14 + +### Changed +- You can now print multiple reports for each run and print each to the screen or a file (request [#12434][pear-12434]) + - Format is `--report-[report][=file]` (e.g., `--report-xml=out.xml`) + - Printing to screen is done by leaving `[file]` empty (e.g., `--report-xml`) + - Multiple reports can be specified in this way (e.g., `--report-summary --report-xml=out.xml`) + - The standard `--report` and `--report-file` command line arguments are unchanged +- Added `-d` command line argument to set `php.ini` settings while running (request [#17244][pear-17244]) + - Usage is: `phpcs -d memory_limit=32M -d ...` + - Thanks to [Ben Selby][@benmatselby] for the patch +- Added -p command line argument to show progress during a run + - Dot means pass, E means errors found, W means only warnings found and S means skipped file + - Particularly good for runs where you are checking more than 100 files + - Enable by default with --config-set show_progress 1 + - Will not print anything if you are already printing verbose output + - This has caused a big change in the way PHP_CodeSniffer processes files (API changes around processing) +- You can now add exclude rules for individual sniffs or error messages (request [#17903][pear-17903]) + - Only available when using a ruleset.xml file to specify rules + - Uses the same exclude-pattern tags as normal but allows them inside rule tags +- Using the -vvv option will now print a list of sniffs executed for each file and how long they took to process +- Added Generic ClosureLinterSniff to run Google's gjslint over your JS files +- The XML and CSV reports now include the severity of the error (request [#18165][pear-18165]) + - The Severity column in the CSV report has been renamed to Type, and a new Severity column added for this +- Fixed issue with Squiz FunctionCommentSniff reporting incorrect type hint when default value uses namespace + - Thanks to Anti Veeranna for the patch +- Generic FileLengthSniff now uses iconv_strlen to check line length if an encoding is specified (request [#14237][pear-14237]) +- Generic UnnecessaryStringConcatSniff now allows strings to be combined to form a PHP open or close tag +- Squiz SwitchDeclarationSniff no longer reports indentation errors for BREAK statements inside IF conditions +- Interactive mode now always prints the full error report (ignores command line) +- Improved regular expression detection in JavaScript files + - Added new T_TYPEOF token that can be used to target the typeof JS operator + - Fixes bug [#17611][pear-17611] : Regular expression tokens not recognised +- Squiz ScopeIndentSniff removed + - Squiz standard no longer requires additional indents between ob_* methods + - Also removed Squiz OutputBufferingIndentSniff that was checking the same thing +- PHP_CodeSniffer_File::getMemberProperties() performance improved significantly + - Improves performance of Squiz ValidVariableNameSniff significantly +- Squiz OperatorSpacingSniff performance improved significantly +- Squiz NonExecutableCodeSniff performance improved significantly + - Will throw duplicate errors in some cases now, but these should be rare +- MySource IncludeSystemSniff performance improved significantly +- MySource JoinStringsSniff no longer reports an error when using join() on a named JS array +- Warnings are now reported for each file when they cannot be opened instead of stopping the script + - Hide warnings with the -n command line argument + - Can override the warnings using the code Internal.DetectLineEndings + +### Fixed +- Fixed bug [#17693][pear-17693] : issue with pre-commit hook script with filenames that start with v +- Fixed bug [#17860][pear-17860] : isReference function fails with references in array + - Thanks to [Lincoln Maskey][pear-ljmaskey] for the patch +- Fixed bug [#17902][pear-17902] : Cannot run tests when tests are symlinked into tests dir + - Thanks to [Matt Button][@BRMatt] for the patch +- Fixed bug [#17928][pear-17928] : Improve error message for Generic_Sniffs_PHP_UpperCaseConstantSniff + - Thanks to [Stefano Kowalke][@Konafets] for the patch +- Fixed bug [#18039][pear-18039] : JS Tokenizer crash when ] is last character in file +- Fixed bug [#18047][pear-18047] : Incorrect handling of namespace aliases as constants + - Thanks to [Dmitri Medvedev][pear-dvino] for the patch +- Fixed bug [#18072][pear-18072] : Impossible to exclude path from processing when symlinked +- Fixed bug [#18073][pear-18073] : Squiz.PHP.NonExecutableCode fault +- Fixed bug [#18117][pear-18117] : PEAR coding standard: Method constructor not sniffed as a function +- Fixed bug [#18135][pear-18135] : Generic FunctionCallArgumentSpacingSniff reports function declaration errors +- Fixed bug [#18140][pear-18140] : Generic scope indent in exact mode: strange expected/found values for switch +- Fixed bug [#18145][pear-18145] : Sniffs are not loaded for custom ruleset file + - Thanks to [Scott McCammon][pear-mccammos] for the patch +- Fixed bug [#18152][pear-18152] : While and do-while with AbstractPatternSniff +- Fixed bug [#18191][pear-18191] : Squiz.PHP.LowercasePHPFunctions does not work with new Date() +- Fixed bug [#18193][pear-18193] : CodeSniffer doesn't reconize CR (\r) line endings + +[pear-12434]: https://pear.php.net/bugs/bug.php?id=12434 +[pear-14237]: https://pear.php.net/bugs/bug.php?id=14237 +[pear-17244]: https://pear.php.net/bugs/bug.php?id=17244 +[pear-17611]: https://pear.php.net/bugs/bug.php?id=17611 +[pear-17693]: https://pear.php.net/bugs/bug.php?id=17693 +[pear-17860]: https://pear.php.net/bugs/bug.php?id=17860 +[pear-17902]: https://pear.php.net/bugs/bug.php?id=17902 +[pear-17903]: https://pear.php.net/bugs/bug.php?id=17903 +[pear-17928]: https://pear.php.net/bugs/bug.php?id=17928 +[pear-18039]: https://pear.php.net/bugs/bug.php?id=18039 +[pear-18047]: https://pear.php.net/bugs/bug.php?id=18047 +[pear-18072]: https://pear.php.net/bugs/bug.php?id=18072 +[pear-18073]: https://pear.php.net/bugs/bug.php?id=18073 +[pear-18117]: https://pear.php.net/bugs/bug.php?id=18117 +[pear-18135]: https://pear.php.net/bugs/bug.php?id=18135 +[pear-18140]: https://pear.php.net/bugs/bug.php?id=18140 +[pear-18145]: https://pear.php.net/bugs/bug.php?id=18145 +[pear-18152]: https://pear.php.net/bugs/bug.php?id=18152 +[pear-18165]: https://pear.php.net/bugs/bug.php?id=18165 +[pear-18191]: https://pear.php.net/bugs/bug.php?id=18191 +[pear-18193]: https://pear.php.net/bugs/bug.php?id=18193 + +## 1.3.0RC1 - 2010-09-03 + +### Changed +- Added exclude pattern support to ruleset.xml file so you can specify ignore patterns in a standard (request [#17683][pear-17683]) + - Use new exclude-pattern tags to include the ignore rules into your ruleset.xml file + - See CodeSniffer/Standards/PHPCS/ruleset.xml for an example +- Added new --encoding command line argument to specify the encoding of the files being checked + - When set to utf-8, stops the XML-based reports from double-encoding + - When set to something else, helps the XML-based reports encode to utf-8 + - Default value is iso-8859-1 but can be changed with `--config-set encoding [value]` +- The report is no longer printed to screen when using the --report-file command line option (request [#17467][pear-17467]) + - If you want to print it to screen as well, use the -v command line argument +- The SVN and GIT blame reports now also show percentage of reported errors per author (request [#17606][pear-17606]) + - Thanks to [Ben Selby][@benmatselby] for the patch +- Updated the SVN pre-commit hook to work with the new severity levels feature +- Generic SubversionPropertiesSniff now allows properties to have NULL values (request [#17682][pear-17682]) + - A null value indicates that the property should exist but the value should not be checked +- Generic UpperCaseConstantName Sniff now longer complains about the PHPUnit_MAIN_METHOD constant (request [#17798][pear-17798]) +- Squiz FileComment sniff now checks JS files as well as PHP files +- Squiz FunctionCommentSniff now supports namespaces in type hints + +### Fixed +- Fixed a problem in Squiz OutputBufferingIndentSniff where block comments were reported as not indented +- Fixed bug [#17092][pear-17092] : Problems with utf8_encode and htmlspecialchars with non-ascii chars + - Use the new --encoding=utf-8 command line argument if your files are utf-8 encoded +- Fixed bug [#17629][pear-17629] : PHP_CodeSniffer_Tokens::$booleanOperators missing T_LOGICAL_XOR + - Thanks to [Matthew Turland][@elazar] for the patch +- Fixed bug [#17699][pear-17699] : Fatal error generating code coverage with PHPUnit 5.3.0RC1 +- Fixed bug [#17718][pear-17718] : Namespace 'use' statement: used global class name is recognized as constant +- Fixed bug [#17734][pear-17734] : Generic SubversionPropertiesSniff complains on non SVN files +- Fixed bug [#17742][pear-17742] : EmbeddedPhpSniff reacts negatively to file without closing PHP tag +- Fixed bug [#17823][pear-17823] : Notice: Please no longer include `PHPUnit/Framework.php` + +[pear-17092]: https://pear.php.net/bugs/bug.php?id=17092 +[pear-17467]: https://pear.php.net/bugs/bug.php?id=17467 +[pear-17606]: https://pear.php.net/bugs/bug.php?id=17606 +[pear-17629]: https://pear.php.net/bugs/bug.php?id=17629 +[pear-17682]: https://pear.php.net/bugs/bug.php?id=17682 +[pear-17683]: https://pear.php.net/bugs/bug.php?id=17683 +[pear-17699]: https://pear.php.net/bugs/bug.php?id=17699 +[pear-17718]: https://pear.php.net/bugs/bug.php?id=17718 +[pear-17734]: https://pear.php.net/bugs/bug.php?id=17734 +[pear-17742]: https://pear.php.net/bugs/bug.php?id=17742 +[pear-17798]: https://pear.php.net/bugs/bug.php?id=17798 +[pear-17823]: https://pear.php.net/bugs/bug.php?id=17823 + +## 1.3.0a1 - 2010-07-15 + +### Changed +- All `CodingStandard.php` files have been replaced by `ruleset.xml` files + - Custom standards will need to be converted over to this new format to continue working +- You can specify a path to your own custom ruleset.xml file by using the --standard command line arg + - e.g., phpcs --standard=/path/to/my/ruleset.xml +- Added a new report type --report=gitblame to show how many errors and warnings were committed by each author + - Has the same functionality as the svnblame report + - Thanks to [Ben Selby][@benmatselby] for the patch +- A new token type T_DOLLAR has been added to allow you to sniff for variable variables (feature request [#17095][pear-17095]) + - Thanks to [Ian Young][pear-youngian] for the patch +- JS tokenizer now supports T_POWER (^) and T_MOD_EQUAL (%=) tokens (feature request [#17441][pear-17441]) +- If you have PHP_Timer installed, you'll now get a time/memory summary at the end of a script run + - Only happens when printing reports that are designed to be read on the command line +- Added Generic DeprecatedFunctionsSniff to warn about the use of deprecated functions (feature request [#16694][pear-16694]) + - Thanks to [Sebastian Bergmann][@sebastianbergmann] for the patch +- Added Squiz LogicalOperatorSniff to ensure that logical operators are surrounded by single spaces +- Added MySource ChannelExceptionSniff to ensure action files only throw ChannelException +- Added new method getClassProperties() for sniffs to use to determine if a class is abstract and/or final + - Thanks to [Christian Kaps][@akkie] for the patch +- Generic UpperCaseConstantSniff no longer throws errors about namespaces + - Thanks to [Christian Kaps][@akkie] for the patch +- Squiz OperatorBracketSniff now correctly checks value assignments in arrays +- Squiz LongConditionClosingCommentSniff now requires a comment for long CASE statements that use curly braces +- Squiz LongConditionClosingCommentSniff now requires an exact comment match on the brace +- MySource IncludeSystemSniff now ignores DOMDocument usage +- MySource IncludeSystemSniff no longer requires inclusion of systems that are being implemented +- Removed found and expected messages from Squiz ConcatenationSpacingSniff because they were messy and not helpful + +### Fixed +- Fixed a problem where Generic CodeAnalysisSniff could show warnings if checking multi-line strings +- Fixed error messages in Squiz ArrayDeclarationSniff reporting incorrect number of found and expected spaces +- Fixed bug [#17048][pear-17048] : False positive in Squiz_WhiteSpace_ScopeKeywordSpacingSniff +- Fixed bug [#17054][pear-17054] : phpcs more strict than PEAR CS regarding function parameter spacing +- Fixed bug [#17096][pear-17096] : Notice: Undefined index: `scope_condition` in `ScopeClosingBraceSniff.php` + - Moved PEAR.Functions.FunctionCallArgumentSpacing to Generic.Functions.FunctionCallArgumentSpacing +- Fixed bug [#17144][pear-17144] : Deprecated: Function eregi() is deprecated +- Fixed bug [#17236][pear-17236] : PHP Warning due to token_get_all() in DoubleQuoteUsageSniff +- Fixed bug [#17243][pear-17243] : Alternate Switch Syntax causes endless loop of Notices in SwitchDeclaration +- Fixed bug [#17313][pear-17313] : Bug with switch case structure +- Fixed bug [#17331][pear-17331] : Possible parse error: interfaces may not include member vars +- Fixed bug [#17337][pear-17337] : CSS tokenizer fails on quotes urls +- Fixed bug [#17420][pear-17420] : Uncaught exception when comment before function brace +- Fixed bug [#17503][pear-17503] : closures formatting is not supported + +[pear-16694]: https://pear.php.net/bugs/bug.php?id=16694 +[pear-17048]: https://pear.php.net/bugs/bug.php?id=17048 +[pear-17054]: https://pear.php.net/bugs/bug.php?id=17054 +[pear-17095]: https://pear.php.net/bugs/bug.php?id=17095 +[pear-17096]: https://pear.php.net/bugs/bug.php?id=17096 +[pear-17144]: https://pear.php.net/bugs/bug.php?id=17144 +[pear-17236]: https://pear.php.net/bugs/bug.php?id=17236 +[pear-17243]: https://pear.php.net/bugs/bug.php?id=17243 +[pear-17313]: https://pear.php.net/bugs/bug.php?id=17313 +[pear-17331]: https://pear.php.net/bugs/bug.php?id=17331 +[pear-17337]: https://pear.php.net/bugs/bug.php?id=17337 +[pear-17420]: https://pear.php.net/bugs/bug.php?id=17420 +[pear-17441]: https://pear.php.net/bugs/bug.php?id=17441 +[pear-17503]: https://pear.php.net/bugs/bug.php?id=17503 + +## 1.2.2 - 2010-01-27 + +### Changed +- The core PHP_CodeSniffer_File methods now understand the concept of closures (feature request [#16866][pear-16866]) + - Thanks to [Christian Kaps][@akkie] for the sample code +- Sniffs can now specify violation codes for each error and warning they add + - Future versions will allow you to override messages and severities using these codes + - Specifying a code is optional, but will be required if you wish to support overriding +- All reports have been broken into separate classes + - Command line usage and report output remains the same + - Thanks to Gabriele Santini for the patch +- Added an interactive mode that can be enabled using the -a command line argument + - Scans files and stops when it finds a file with errors + - Waits for user input to recheck the file (hopefully you fixed the errors) or skip the file + - Useful for very large code bases where full rechecks take a while +- The reports now show the correct number of errors and warnings found +- The isCamelCaps method now allows numbers in class names +- The JS tokenizer now correctly identifies boolean and bitwise AND and OR tokens +- The JS tokenizer now correctly identifies regular expressions used in conditions +- PEAR ValidFunctionNameSniff now ignores closures +- Squiz standard now uses the PEAR setting of 85 chars for LineLengthSniff +- Squiz ControlStructureSpacingSniff now ensure there are no spaces around parentheses +- Squiz LongConditionClosingCommentSniff now checks for comments at the end of try/catch statements +- Squiz LongConditionClosingCommentSniff now checks validity of comments for short structures if they exist +- Squiz IncrementDecrementUsageSniff now has better checking to ensure it only looks at simple variable assignments +- Squiz PostStatementCommentSniff no longer throws errors for end function comments +- Squiz InlineCommentSniff no longer throws errors for end function comments +- Squiz OperatorBracketSniff now allows simple arithmetic operations in SWITCH conditions +- Squiz ValidFunctionNameSniff now ignores closures +- Squiz MethodScopeSniff now ignores closures +- Squiz ClosingDeclarationCommentSniff now ignores closures +- Squiz GlobalFunctionSniff now ignores closures +- Squiz DisallowComparisonAssignmentSniff now ignores the assigning of arrays +- Squiz DisallowObjectStringIndexSniff now allows indexes that contain dots and reserved words +- Squiz standard now throws nesting level and cyclomatic complexity errors at much higher levels +- Squiz CommentedOutCodeSniff now ignores common comment framing characters +- Squiz ClassCommentSniff now ensures the open comment tag is the only content on the first line +- Squiz FileCommentSniff now ensures the open comment tag is the only content on the first line +- Squiz FunctionCommentSniff now ensures the open comment tag is the only content on the first line +- Squiz VariableCommentSniff now ensures the open comment tag is the only content on the first line +- Squiz NonExecutableCodeSniff now warns about empty return statements that are not required +- Removed ForbiddenStylesSniff from Squiz standard + - It is now in the MySource standard as BrowserSpecificStylesSniff + - New BrowserSpecificStylesSniff ignores files with browser-specific suffixes +- MySource IncludeSystemSniff no longer throws errors when extending the Exception class +- MySource IncludeSystemSniff no longer throws errors for the abstract widget class +- MySource IncludeSystemSniff and UnusedSystemSniff now allow includes inside IF statements +- MySource IncludeSystemSniff no longer throws errors for included widgets inside methods +- MySource GetRequestDataSniff now throws errors for using $_FILES +- MySource CreateWidgetTypeCallbackSniff now allows return statements in nested functions +- MySource DisallowSelfActionsSniff now ignores abstract classes + +### Fixed +- Fixed a problem with the SVN pre-commit hook for PHP versions without vertical whitespace regex support +- Fixed bug [#16740][pear-16740] : False positives for heredoc strings and unused parameter sniff +- Fixed bug [#16794][pear-16794] : ValidLogicalOperatorsSniff doesn't report operators not in lowercase +- Fixed bug [#16804][pear-16804] : Report filename is shortened too much +- Fixed bug [#16821][pear-16821] : Bug in Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#16836][pear-16836] : Notice raised when using semicolon to open case +- Fixed bug [#16855][pear-16855] : Generic standard sniffs incorrectly for define() method +- Fixed bug [#16865][pear-16865] : Two bugs in Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#16902][pear-16902] : Inline If Declaration bug +- Fixed bug [#16960][pear-16960] : False positive for late static binding in Squiz/ScopeKeywordSpacingSniff + - Thanks to [Jakub Tománek][pear-thezero] for the patch +- Fixed bug [#16976][pear-16976] : The phpcs attempts to process symbolic links that don't resolve to files +- Fixed bug [#17017][pear-17017] : Including one file in the files sniffed alters errors reported for another file + +[pear-16740]: https://pear.php.net/bugs/bug.php?id=16740 +[pear-16794]: https://pear.php.net/bugs/bug.php?id=16794 +[pear-16804]: https://pear.php.net/bugs/bug.php?id=16804 +[pear-16821]: https://pear.php.net/bugs/bug.php?id=16821 +[pear-16836]: https://pear.php.net/bugs/bug.php?id=16836 +[pear-16855]: https://pear.php.net/bugs/bug.php?id=16855 +[pear-16865]: https://pear.php.net/bugs/bug.php?id=16865 +[pear-16866]: https://pear.php.net/bugs/bug.php?id=16866 +[pear-16902]: https://pear.php.net/bugs/bug.php?id=16902 +[pear-16960]: https://pear.php.net/bugs/bug.php?id=16960 +[pear-16976]: https://pear.php.net/bugs/bug.php?id=16976 +[pear-17017]: https://pear.php.net/bugs/bug.php?id=17017 + +## 1.2.1 - 2009-11-17 + +### Changed +- Added a new report type --report=svnblame to show how many errors and warnings were committed by each author + - Also shows the percentage of their code that are errors and warnings + - Requires you to have the SVN command in your path + - Make sure SVN is storing usernames and passwords (if required) or you will need to enter them for each file + - You can also use the -s command line argument to see the different types of errors authors are committing + - You can use the -v command line argument to see all authors, even if they have no errors or warnings +- Added a new command line argument --report-width to allow you to set the column width of screen reports + - Reports won't accept values less than 70 or else they get too small + - Can also be set via a config var: phpcs --config-set report_width 100 +- You can now get PHP_CodeSniffer to ignore a whole file by adding @codingStandardsIgnoreFile in the content + - If you put it in the first two lines the file won't even be tokenized, so it will be much quicker +- Reports now print their file lists in alphabetical order +- PEAR FunctionDeclarationSniff now reports error for incorrect closing bracket placement in multi-line definitions +- Added Generic CallTimePassByReferenceSniff to prohibit the passing of variables into functions by reference + - Thanks to Florian Grandel for the contribution +- Added Squiz DisallowComparisonAssignmentSniff to ban the assignment of comparison values to a variable +- Added Squiz DuplicateStyleDefinitionSniff to check for duplicate CSS styles in a single class block +- Squiz ArrayDeclarationSniff no longer checks the case of array indexes because that is not its job +- Squiz PostStatementCommentSniff now allows end comments for class member functions +- Squiz InlineCommentSniff now supports the checking of JS files +- MySource CreateWidgetTypeCallbackSniff now allows the callback to be passed to another function +- MySource CreateWidgetTypeCallbackSniff now correctly ignores callbacks used inside conditions +- Generic MultipleStatementAlignmentSniff now enforces a single space before equals sign if max padding is reached +- Fixed a problem in the JS tokenizer where regular expressions containing \// were not converted correctly +- Fixed a problem tokenizing CSS files where multiple ID targets on a line would look like comments +- Fixed a problem tokenizing CSS files where class names containing a colon looked like style definitions +- Fixed a problem tokenizing CSS files when style statements had empty url() calls +- Fixed a problem tokenizing CSS colours with the letter E in first half of the code +- Squiz ColonSpacingSniff now ensures it is only checking style definitions in CSS files and not class names +- Squiz DisallowComparisonAssignmentSniff no longer reports errors when assigning the return value of a function +- CSS tokenizer now correctly supports multi-line comments +- When only the case of var names differ for function comments, the error now indicates the case is different + +### Fixed +- Fixed an issue with Generic UnnecessaryStringConcatSniff where it incorrectly suggested removing a concat +- Fixed bug [#16530][pear-16530] : ScopeIndentSniff reports false positive +- Fixed bug [#16533][pear-16533] : Duplicate errors and warnings +- Fixed bug [#16563][pear-16563] : Check file extensions problem in phpcs-svn-pre-commit + - Thanks to [Kaijung Chen][pear-et3w503] for the patch +- Fixed bug [#16592][pear-16592] : Object operator indentation incorrect when first operator is on a new line +- Fixed bug [#16641][pear-16641] : Notice output +- Fixed bug [#16682][pear-16682] : Squiz_Sniffs_Strings_DoubleQuoteUsageSniff reports string "\0" as invalid +- Fixed bug [#16683][pear-16683] : Typing error in PHP_CodeSniffer_CommentParser_AbstractParser +- Fixed bug [#16684][pear-16684] : Bug in Squiz_Sniffs_PHP_NonExecutableCodeSniff +- Fixed bug [#16692][pear-16692] : Spaces in paths in Squiz_Sniffs_Debug_JavaScriptLintSniff + - Thanks to [Jaroslav Hanslík][@kukulich] for the patch +- Fixed bug [#16696][pear-16696] : Spelling error in MultiLineConditionSniff +- Fixed bug [#16697][pear-16697] : MultiLineConditionSniff incorrect result with inline IF +- Fixed bug [#16698][pear-16698] : Notice in JavaScript Tokenizer +- Fixed bug [#16736][pear-16736] : Multi-files sniffs aren't processed when FILE is a single directory + - Thanks to [Alexey Shein][pear-conf] for the patch +- Fixed bug [#16792][pear-16792] : Bug in Generic_Sniffs_PHP_ForbiddenFunctionsSniff + +[pear-16530]: https://pear.php.net/bugs/bug.php?id=16530 +[pear-16533]: https://pear.php.net/bugs/bug.php?id=16533 +[pear-16563]: https://pear.php.net/bugs/bug.php?id=16563 +[pear-16592]: https://pear.php.net/bugs/bug.php?id=16592 +[pear-16641]: https://pear.php.net/bugs/bug.php?id=16641 +[pear-16682]: https://pear.php.net/bugs/bug.php?id=16682 +[pear-16683]: https://pear.php.net/bugs/bug.php?id=16683 +[pear-16684]: https://pear.php.net/bugs/bug.php?id=16684 +[pear-16692]: https://pear.php.net/bugs/bug.php?id=16692 +[pear-16696]: https://pear.php.net/bugs/bug.php?id=16696 +[pear-16697]: https://pear.php.net/bugs/bug.php?id=16697 +[pear-16698]: https://pear.php.net/bugs/bug.php?id=16698 +[pear-16736]: https://pear.php.net/bugs/bug.php?id=16736 +[pear-16792]: https://pear.php.net/bugs/bug.php?id=16792 + +## 1.2.0 - 2009-08-17 + +### Changed +- Installed standards are now favoured over custom standards when using the cmd line arg with relative paths +- Unit tests now use a lot less memory while running +- Squiz standard now uses Generic EmptyStatementSniff but throws errors instead of warnings +- Squiz standard now uses Generic UnusedFunctionParameterSniff +- Removed unused ValidArrayIndexNameSniff from the Squiz standard + +### Fixed +- Fixed bug [#16424][pear-16424] : SubversionPropertiesSniff print PHP Warning +- Fixed bug [#16450][pear-16450] : Constant `PHP_CODESNIFFER_VERBOSITY` already defined (unit tests) +- Fixed bug [#16453][pear-16453] : function declaration long line splitted error +- Fixed bug [#16482][pear-16482] : phpcs-svn-pre-commit ignores extensions parameter + +[pear-16424]: https://pear.php.net/bugs/bug.php?id=16424 +[pear-16450]: https://pear.php.net/bugs/bug.php?id=16450 +[pear-16453]: https://pear.php.net/bugs/bug.php?id=16453 +[pear-16482]: https://pear.php.net/bugs/bug.php?id=16482 + +## 1.2.0RC3 - 2009-07-07 + +### Changed +- You can now use @codingStandardsIgnoreStart and @...End comments to suppress messages (feature request [#14002][pear-14002]) +- A warning is now included for files without any code when short_open_tag is set to Off (feature request [#12952][pear-12952]) +- You can now use relative paths to your custom standards with the --standard cmd line arg (feature request [#14967][pear-14967]) +- You can now override magic methods and functions in PEAR ValidFunctionNameSniff (feature request [#15830][pear-15830]) +- MySource IncludeSystemSniff now recognises widget action classes +- MySource IncludeSystemSniff now knows about unit test classes and changes rules accordingly + +[pear-12952]: https://pear.php.net/bugs/bug.php?id=12952 +[pear-14002]: https://pear.php.net/bugs/bug.php?id=14002 +[pear-14967]: https://pear.php.net/bugs/bug.php?id=14967 +[pear-15830]: https://pear.php.net/bugs/bug.php?id=15830 + +## 1.2.0RC2 - 2009-05-25 + +### Changed +- Test suite can now be run using the full path to `AllTests.php` (feature request [#16179][pear-16179]) + +### Fixed +- Fixed bug [#15980][pear-15980] : PHP_CodeSniffer change PHP current directory + - Thanks to [Dolly Aswin Harahap][pear-dollyaswin] for the patch +- Fixed bug [#16001][pear-16001] : Notice triggered +- Fixed bug [#16054][pear-16054] : phpcs-svn-pre-commit not showing any errors +- Fixed bug [#16071][pear-16071] : Fatal error: Uncaught PHP_CodeSniffer_Exception +- Fixed bug [#16170][pear-16170] : Undefined Offset -1 in `MultiLineConditionSniff.php` on line 68 +- Fixed bug [#16175][pear-16175] : Bug in Squiz-IncrementDecrementUsageSniff + +[pear-15980]: https://pear.php.net/bugs/bug.php?id=15980 +[pear-16001]: https://pear.php.net/bugs/bug.php?id=16001 +[pear-16054]: https://pear.php.net/bugs/bug.php?id=16054 +[pear-16071]: https://pear.php.net/bugs/bug.php?id=16071 +[pear-16170]: https://pear.php.net/bugs/bug.php?id=16170 +[pear-16175]: https://pear.php.net/bugs/bug.php?id=16175 +[pear-16179]: https://pear.php.net/bugs/bug.php?id=16179 + +## 1.2.0RC1 - 2009-03-09 + +### Changed +- Reports that are output to a file now include a trailing newline at the end of the file +- Fixed sniff names not shown in -vvv token processing output +- Added Generic SubversionPropertiesSniff to check that specific svn props are set for files + - Thanks to Jack Bates for the contribution +- The PHP version check can now be overridden in classes that extend PEAR FileCommentSniff + - Thanks to [Helgi Þormar Þorbjörnsson][@helgi] for the suggestion +- Added Generic ConstructorNameSniff to check for PHP4 constructor name usage + - Thanks to Leif Wickland for the contribution +- Squiz standard now supports multi-line function and condition sniffs from PEAR standard +- Squiz standard now uses Generic ConstructorNameSniff +- Added MySource GetRequestDataSniff to ensure REQUEST, GET and POST are not accessed directly +- Squiz OperatorBracketSniff now allows square brackets in simple unbracketed operations + +### Fixed +- Fixed the incorrect tokenizing of multi-line block comments in CSS files +- Fixed bug [#15383][pear-15383] : Uncaught PHP_CodeSniffer_Exception +- Fixed bug [#15408][pear-15408] : An unexpected exception has been caught: Undefined offset: 2 +- Fixed bug [#15519][pear-15519] : Uncaught PHP_CodeSniffer_Exception +- Fixed bug [#15624][pear-15624] : Pre-commit hook fails with PHP errors +- Fixed bug [#15661][pear-15661] : Uncaught PHP_CodeSniffer_Exception +- Fixed bug [#15722][pear-15722] : "declare(encoding = 'utf-8');" leads to "Missing file doc comment" +- Fixed bug [#15910][pear-15910] : Object operator indention not calculated correctly + +[pear-15383]: https://pear.php.net/bugs/bug.php?id=15383 +[pear-15408]: https://pear.php.net/bugs/bug.php?id=15408 +[pear-15519]: https://pear.php.net/bugs/bug.php?id=15519 +[pear-15624]: https://pear.php.net/bugs/bug.php?id=15624 +[pear-15661]: https://pear.php.net/bugs/bug.php?id=15661 +[pear-15722]: https://pear.php.net/bugs/bug.php?id=15722 +[pear-15910]: https://pear.php.net/bugs/bug.php?id=15910 + +## 1.2.0a1 - 2008-12-18 + +### Changed +- PHP_CodeSniffer now has a CSS tokenizer for checking CSS files +- Added support for a new multi-file sniff that sniffs all processed files at once +- Added new output format --report=emacs to output errors using the emacs standard compile output format + - Thanks to Len Trigg for the contribution +- Reports can now be written to a file using the --report-file command line argument (feature request [#14953][pear-14953]) + - The report is also written to screen when using this argument +- The CheckStyle, CSV and XML reports now include a source for each error and warning (feature request [#13242][pear-13242]) + - A new report type --report=source can be used to show you the most common errors in your files +- Added new command line argument -s to show error sources in all reports +- Added new command line argument --sniffs to specify a list of sniffs to restrict checking to + - Uses the sniff source codes that are optionally displayed in reports +- Changed the max width of error lines from 80 to 79 chars to stop blank lines in the default windows cmd window +- PHP_CodeSniffer now has a token for an asperand (@ symbol) so sniffs can listen for them + - Thanks to Andy Brockhurst for the patch +- Added Generic DuplicateClassNameSniff that will warn if the same class name is used in multiple files + - Not currently used by any standard; more of a multi-file sniff sample than anything useful +- Added Generic NoSilencedErrorsSniff that warns if PHP errors are being silenced using the @ symbol + - Thanks to Andy Brockhurst for the contribution +- Added Generic UnnecessaryStringConcatSniff that checks for two strings being concatenated +- Added PEAR FunctionDeclarationSniff to enforce the new multi-line function declaration PEAR standard +- Added PEAR MultiLineAssignmentSniff to enforce the correct indentation of multi-line assignments +- Added PEAR MultiLineConditionSniff to enforce the new multi-line condition PEAR standard +- Added PEAR ObjectOperatorIndentSniff to enforce the new chained function call PEAR standard +- Added MySource DisallowSelfActionSniff to ban the use of self::method() calls in Action classes +- Added MySource DebugCodeSniff to ban the use of Debug::method() calls +- Added MySource CreateWidgetTypeCallback sniff to check callback usage in widget type create methods +- Added Squiz DisallowObjectStringIndexSniff that forces object dot notation in JavaScript files + - Thanks to [Sertan Danis][@sertand] for the contribution +- Added Squiz DiscouragedFunctionsSniff to warn when using debug functions +- Added Squiz PropertyLabelSniff to check whitespace around colons in JS property and label declarations +- Added Squiz DuplicatePropertySniff to check for duplicate property names in JS classes +- Added Squiz ColonSpacingSniff to check for spacing around colons in CSS style definitions +- Added Squiz SemicolonSpacingSniff to check for spacing around semicolons in CSS style definitions +- Added Squiz IndentationSniff to check for correct indentation of CSS files +- Added Squiz ColourDefinitionSniff to check that CSS colours are defined in uppercase and using shorthand +- Added Squiz EmptyStyleDefinitionSniff to check for CSS style definitions without content +- Added Squiz EmptyClassDefinitionSniff to check for CSS class definitions without content +- Added Squiz ClassDefinitionOpeningBraceSpaceSniff to check for spaces around opening brace of CSS class definitions +- Added Squiz ClassDefinitionClosingBraceSpaceSniff to check for a single blank line after CSS class definitions +- Added Squiz ClassDefinitionNameSpacingSniff to check for a blank lines inside CSS class definition names +- Added Squiz DisallowMultipleStyleDefinitionsSniff to check for multiple style definitions on a single line +- Added Squiz DuplicateClassDefinitionSniff to check for duplicate CSS class blocks that can be merged +- Added Squiz ForbiddenStylesSniff to check for usage of browser specific styles +- Added Squiz OpacitySniff to check for incorrect opacity values in CSS +- Added Squiz LowercaseStyleDefinitionSniff to check for styles that are not defined in lowercase +- Added Squiz MissingColonSniff to check for style definitions where the colon has been forgotten +- Added Squiz MultiLineFunctionDeclarationSniff to check that multi-line declarations contain one param per line +- Added Squiz JSLintSniff to check for JS errors using the jslint.js script through Rhino + - Set jslint path using phpcs --config-set jslint_path /path/to/jslint.js + - Set rhino path using phpcs --config-set rhino_path /path/to/rhino +- Added Generic TodoSniff that warns about comments that contain the word TODO +- Removed MultipleStatementAlignmentSniff from the PEAR standard as alignment is now optional +- Generic ForbiddenFunctionsSniff now has protected member var to specify if it should use errors or warnings +- Generic MultipleStatementAlignmentSniff now has correct error message if assignment is on a new line +- Generic MultipleStatementAlignmentSniff now has protected member var to allow it to ignore multi-line assignments +- Generic LineEndingsSniff now supports checking of JS files +- Generic LineEndingsSniff now supports checking of CSS files +- Generic DisallowTabIndentSniff now supports checking of CSS files +- Squiz DoubleQuoteUsageSniff now bans the use of variables in double quoted strings in favour of concatenation +- Squiz SuperfluousWhitespaceSniff now supports checking of JS files +- Squiz SuperfluousWhitespaceSniff now supports checking of CSS files +- Squiz DisallowInlineIfSniff now supports checking of JS files +- Squiz SemicolonSpacingSniff now supports checking of JS files +- Squiz PostStatementCommentSniff now supports checking of JS files +- Squiz FunctionOpeningBraceSpacingSniff now supports checking of JS files +- Squiz FunctionClosingBraceSpacingSniff now supports checking of JS files + - Empty JS functions must have their opening and closing braces next to each other +- Squiz ControlStructureSpacingSniff now supports checking of JS files +- Squiz LongConditionClosingCommentSniff now supports checking of JS files +- Squiz OperatorSpacingSniff now supports checking of JS files +- Squiz SwitchDeclarationSniff now supports checking of JS files +- Squiz CommentedOutCodeSniff now supports checking of CSS files +- Squiz DisallowSizeFunctionsInLoopsSniff now supports checking of JS files for the use of object.length +- Squiz DisallowSizeFunctionsInLoopsSniff no longer complains about size functions outside of the FOR condition +- Squiz ControlStructureSpacingSniff now bans blank lines at the end of a control structure +- Squiz ForLoopDeclarationSniff no longer throws errors for JS FOR loops without semicolons +- Squiz MultipleStatementAlignmentSniff no longer throws errors if a statement would take more than 8 spaces to align +- Squiz standard now uses Generic TodoSniff +- Squiz standard now uses Generic UnnecessaryStringConcatSniff +- Squiz standard now uses PEAR MultiLineAssignmentSniff +- Squiz standard now uses PEAR MultiLineConditionSniff +- Zend standard now uses OpeningFunctionBraceBsdAllmanSniff (feature request [#14647][pear-14647]) +- MySource JoinStringsSniff now bans the use of inline array joins and suggests the + operator +- Fixed incorrect errors that can be generated from abstract scope sniffs when moving to a new file +- Core tokenizer now matches orphaned curly braces in the same way as square brackets +- Whitespace tokens at the end of JS files are now added to the token stack +- JavaScript tokenizer now identifies properties and labels as new token types +- JavaScript tokenizer now identifies object definitions as a new token type and matches curly braces for them +- JavaScript tokenizer now identifies DIV_EQUAL and MUL_EQUAL tokens +- Improved regular expression detection in the JavaScript tokenizer +- Improve AbstractPatternSniff support so it can listen for any token type, not just weighted tokens + +### Fixed +- Fixed Squiz DoubleQuoteUsageSniff so it works correctly with short_open_tag=Off +- Fixed bug [#14409][pear-14409] : Output of warnings to log file +- Fixed bug [#14520][pear-14520] : Notice: Undefined offset: 1 in `CodeSniffer/File.php` on line +- Fixed bug [#14637][pear-14637] : Call to processUnknownArguments() misses second parameter $pos + - Thanks to [Peter Buri][pear-burci] for the patch +- Fixed bug [#14889][pear-14889] : Lack of clarity: licence or license +- Fixed bug [#15008][pear-15008] : Nested Parentheses in Control Structure Sniffs +- Fixed bug [#15091][pear-15091] : pre-commit hook attempts to sniff folders + - Thanks to [Bruce Weirdan][pear-weirdan] for the patch +- Fixed bug [#15124][pear-15124] : `AbstractParser.php` uses deprecated `split()` function + - Thanks to [Sebastian Bergmann][@sebastianbergmann] for the patch +- Fixed bug [#15188][pear-15188] : PHPCS vs HEREDOC strings +- Fixed bug [#15231][pear-15231] : Notice: Uninitialized string offset: 0 in `FileCommentSniff.php` on line 555 +- Fixed bug [#15336][pear-15336] : Notice: Undefined offset: 2 in `CodeSniffer/File.php` on line + +[pear-13242]: https://pear.php.net/bugs/bug.php?id=13242 +[pear-14409]: https://pear.php.net/bugs/bug.php?id=14409 +[pear-14520]: https://pear.php.net/bugs/bug.php?id=14520 +[pear-14637]: https://pear.php.net/bugs/bug.php?id=14637 +[pear-14647]: https://pear.php.net/bugs/bug.php?id=14647 +[pear-14889]: https://pear.php.net/bugs/bug.php?id=14889 +[pear-14953]: https://pear.php.net/bugs/bug.php?id=14953 +[pear-15008]: https://pear.php.net/bugs/bug.php?id=15008 +[pear-15091]: https://pear.php.net/bugs/bug.php?id=15091 +[pear-15124]: https://pear.php.net/bugs/bug.php?id=15124 +[pear-15188]: https://pear.php.net/bugs/bug.php?id=15188 +[pear-15231]: https://pear.php.net/bugs/bug.php?id=15231 +[pear-15336]: https://pear.php.net/bugs/bug.php?id=15336 + +## 1.1.0 - 2008-07-14 + +### Changed +- PEAR FileCommentSniff now allows tag orders to be overridden in child classes + - Thanks to Jeff Hodsdon for the patch +- Added Generic DisallowMultipleStatementsSniff to ensure there is only one statement per line +- Squiz standard now uses DisallowMultipleStatementsSniff + +### Fixed +- Fixed error in Zend ValidVariableNameSniff when checking vars in form: $class->{$var} +- Fixed bug [#14077][pear-14077] : Fatal error: Uncaught PHP_CodeSniffer_Exception: $stackPtr is not a class member +- Fixed bug [#14168][pear-14168] : Global Function -> Static Method and __autoload() +- Fixed bug [#14238][pear-14238] : Line length not checked at last line of a file +- Fixed bug [#14249][pear-14249] : wrong detection of scope_opener +- Fixed bug [#14250][pear-14250] : ArrayDeclarationSniff emit warnings at malformed array +- Fixed bug [#14251][pear-14251] : --extensions option doesn't work + +## 1.1.0RC3 - 2008-07-03 + +### Changed +- PEAR FileCommentSniff now allows tag orders to be overridden in child classes + - Thanks to Jeff Hodsdon for the patch +- Added Generic DisallowMultipleStatementsSniff to ensure there is only one statement per line +- Squiz standard now uses DisallowMultipleStatementsSniff + +### Fixed +- Fixed error in Zend ValidVariableNameSniff when checking vars in form: $class->{$var} +- Fixed bug [#14077][pear-14077] : Fatal error: Uncaught PHP_CodeSniffer_Exception: $stackPtr is not a class member +- Fixed bug [#14168][pear-14168] : Global Function -> Static Method and __autoload() +- Fixed bug [#14238][pear-14238] : Line length not checked at last line of a file +- Fixed bug [#14249][pear-14249] : wrong detection of scope_opener +- Fixed bug [#14250][pear-14250] : ArrayDeclarationSniff emit warnings at malformed array +- Fixed bug [#14251][pear-14251] : --extensions option doesn't work + +[pear-14077]: https://pear.php.net/bugs/bug.php?id=14077 +[pear-14168]: https://pear.php.net/bugs/bug.php?id=14168 +[pear-14238]: https://pear.php.net/bugs/bug.php?id=14238 +[pear-14249]: https://pear.php.net/bugs/bug.php?id=14249 +[pear-14250]: https://pear.php.net/bugs/bug.php?id=14250 +[pear-14251]: https://pear.php.net/bugs/bug.php?id=14251 + +## 1.1.0RC2 - 2008-06-13 + +### Changed +- Permission denied errors now stop script execution but still display current errors (feature request [#14076][pear-14076]) +- Added Squiz ValidArrayIndexNameSniff to ensure array indexes do not use camel case +- Squiz ArrayDeclarationSniff now ensures arrays are not declared with camel case index values +- PEAR ValidVariableNameSniff now alerts about a possible parse error for member vars inside an interface + +### Fixed +- Fixed bug [#13921][pear-13921] : js parsing fails for comments on last line of file +- Fixed bug [#13922][pear-13922] : crash in case of malformed (but tokenized) PHP file + - PEAR and Squiz ClassDeclarationSniff now throw warnings for possible parse errors + - Squiz ValidClassNameSniff now throws warning for possible parse errors + - Squiz ClosingDeclarationCommentSniff now throws additional warnings for parse errors + +[pear-13921]: https://pear.php.net/bugs/bug.php?id=13921 +[pear-13922]: https://pear.php.net/bugs/bug.php?id=13922 +[pear-14076]: https://pear.php.net/bugs/bug.php?id=14076 + +## 1.1.0RC1 - 2008-05-13 + +### Changed +- Added support for multiple tokenizers so PHP_CodeSniffer can check more than just PHP files + - PHP_CodeSniffer now has a JS tokenizer for checking JavaScript files + - Sniffs need to be updated to work with additional tokenizers, or new sniffs written for them +- phpcs now exits with status 2 if the tokenizer extension has been disabled (feature request [#13269][pear-13269]) +- Added scripts/phpcs-svn-pre-commit that can be used as an SVN pre-commit hook + - Also reworked the way the phpcs script works to make it easier to wrap it with other functionality + - Thanks to Jack Bates for the contribution +- Fixed error in phpcs error message when a supplied file does not exist +- Fixed a cosmetic error in AbstractPatternSniff where the "found" string was missing some content +- Added sniffs that implement part of the PMD rule catalog to the Generic standard + - Thanks to [Manuel Pichler][@manuelpichler] for the contribution of all these sniffs. +- Squiz FunctionCommentThrowTagSniff no longer throws errors for function that only throw variables +- Generic ScopeIndentSniff now has private member to enforce exact indent matching +- Replaced Squiz DisallowCountInLoopsSniff with Squiz DisallowSizeFunctionsInLoopsSniff + - Thanks to Jan Miczaika for the sniff +- Squiz BlockCommentSniff now checks inline doc block comments +- Squiz InlineCommentSniff now checks inline doc block comments +- Squiz BlockCommentSniff now checks for no blank line before first comment in a function +- Squiz DocCommentAlignmentSniff now ignores inline doc block comments +- Squiz ControlStructureSpacingSniff now ensures no blank lines at the start of control structures +- Squiz ControlStructureSpacingSniff now ensures no blank lines between control structure closing braces +- Squiz IncrementDecrementUsageSniff now ensures inc/dec ops are bracketed in string concats +- Squiz IncrementDecrementUsageSniff now ensures inc/dec ops are not used in arithmetic operations +- Squiz FunctionCommentSniff no longer throws errors if return value is mixed but function returns void somewhere +- Squiz OperatorBracketSniff no allows function call brackets to count as operator brackets +- Squiz DoubleQuoteUsageSniff now supports \x \f and \v (feature request [#13365][pear-13365]) +- Squiz ComparisonOperatorUsageSniff now supports JS files +- Squiz ControlSignatureSniff now supports JS files +- Squiz ForLoopDeclarationSniff now supports JS files +- Squiz OperatorBracketSniff now supports JS files +- Squiz InlineControlStructureSniff now supports JS files +- Generic LowerCaseConstantSniff now supports JS files +- Generic DisallowTabIndentSniff now supports JS files +- Generic MultipleStatementAlignmentSniff now supports JS files +- Added Squiz ObjectMemberCommaSniff to ensure the last member of a JS object is not followed by a comma +- Added Squiz ConstantCaseSniff to ensure the PHP constants are uppercase and JS lowercase +- Added Squiz JavaScriptLintSniff to check JS files with JSL + - Set path using phpcs --config-set jsl_path /path/to/jsl +- Added MySource FirebugConsoleSniff to ban the use of "console" for JS variable and function names +- Added MySource JoinStringsSniff to enforce the use of join() to concatenate JS strings +- Added MySource AssignThisSniff to ensure this is only assigned to a var called self +- Added MySource DisallowNewWidgetSniff to ban manual creation of widget objects +- Removed warning shown in Zend CodeAnalyzerSniff when the ZCA path is not set + +### Fixed +- Fixed error in Squiz ValidVariableNameSniff when checking vars in the form $obj->$var +- Fixed error in Squiz DisallowMultipleAssignmentsSniff when checking vars in the form $obj->$var +- Fixed error in Squiz InlineCommentSniff where comments for class constants were seen as inline +- Fixed error in Squiz BlockCommentSniff where comments for class constants were not ignored +- Fixed error in Squiz OperatorBracketSniff where negative numbers were ignored during comparisons +- Fixed error in Squiz FunctionSpacingSniff where functions after member vars reported incorrect spacing +- Fixed bug [#13062][pear-13062] : Interface comments aren't handled in PEAR standard + - Thanks to [Manuel Pichler][@manuelpichler] for the path +- Fixed bug [#13119][pear-13119] : PHP minimum requirement need to be fix +- Fixed bug [#13156][pear-13156] : Bug in Squiz_Sniffs_PHP_NonExecutableCodeSniff +- Fixed bug [#13158][pear-13158] : Strange behaviour in AbstractPatternSniff +- Fixed bug [#13169][pear-13169] : Undefined variables +- Fixed bug [#13178][pear-13178] : Catch exception in `File.php` +- Fixed bug [#13254][pear-13254] : Notices output in checkstyle report causes XML issues +- Fixed bug [#13446][pear-13446] : crash with src of phpMyAdmin + - Thanks to [Manuel Pichler][@manuelpichler] for the path + +[pear-13062]: https://pear.php.net/bugs/bug.php?id=13062 +[pear-13119]: https://pear.php.net/bugs/bug.php?id=13119 +[pear-13156]: https://pear.php.net/bugs/bug.php?id=13156 +[pear-13158]: https://pear.php.net/bugs/bug.php?id=13158 +[pear-13169]: https://pear.php.net/bugs/bug.php?id=13169 +[pear-13178]: https://pear.php.net/bugs/bug.php?id=13178 +[pear-13254]: https://pear.php.net/bugs/bug.php?id=13254 +[pear-13269]: https://pear.php.net/bugs/bug.php?id=13269 +[pear-13365]: https://pear.php.net/bugs/bug.php?id=13365 +[pear-13446]: https://pear.php.net/bugs/bug.php?id=13446 + +## 1.0.1a1 - 2008-04-21 + +### Changed +- Fixed error in PEAR ValidClassNameSniff when checking class names with double underscores +- Moved Squiz InlineControlStructureSniff into Generic standard +- PEAR standard now throws warnings for inline control structures +- Squiz OutputBufferingIndentSniff now ignores the indentation of inline HTML +- MySource IncludeSystemSniff now ignores usage of ZipArchive +- Removed "function" from error messages for Generic function brace sniffs (feature request [#13820][pear-13820]) +- Generic UpperCaseConstantSniff no longer throws errors for declare(ticks = ...) + - Thanks to Josh Snyder for the patch +- Squiz ClosingDeclarationCommentSniff and AbstractVariableSniff now throw warnings for possible parse errors + +### Fixed +- Fixed bug [#13827][pear-13827] : AbstractVariableSniff throws "undefined index" +- Fixed bug [#13846][pear-13846] : Bug in Squiz.NonExecutableCodeSniff +- Fixed bug [#13849][pear-13849] : infinite loop in PHP_CodeSniffer_File::findNext() + +[pear-13820]: https://pear.php.net/bugs/bug.php?id=13820 +[pear-13827]: https://pear.php.net/bugs/bug.php?id=13827 +[pear-13846]: https://pear.php.net/bugs/bug.php?id=13846 +[pear-13849]: https://pear.php.net/bugs/bug.php?id=13849 + +## 1.0.1 - 2008-02-04 + +### Changed +- Squiz ArrayDeclarationSniff now throws error if the array keyword is followed by a space +- Squiz ArrayDeclarationSniff now throws error for empty multi-line arrays +- Squiz ArrayDeclarationSniff now throws error for multi-line arrays with a single value +- Squiz DocCommentAlignmentSniff now checks for a single space before tags inside docblocks +- Squiz ForbiddenFunctionsSniff now disallows is_null() to force use of (=== NULL) instead +- Squiz VariableCommentSniff now continues throwing errors after the first one is found +- Squiz SuperfluousWhitespaceSniff now throws errors for multiple blank lines inside functions +- MySource IncludedSystemSniff now checks extended class names +- MySource UnusedSystemSniff now checks extended and implemented class names +- MySource IncludedSystemSniff now supports includeWidget() +- MySource UnusedSystemSniff now supports includeWidget() +- Added PEAR ValidVariableNameSniff to check that only private member vars are prefixed with an underscore +- Added Squiz DisallowCountInLoopsSniff to check for the use of count() in FOR and WHILE loop conditions +- Added MySource UnusedSystemSniff to check for included classes that are never used + +### Fixed +- Fixed a problem that caused the parentheses map to sometimes contain incorrect values +- Fixed bug [#12767][pear-12767] : Cant run phpcs from dir with PEAR subdir +- Fixed bug [#12773][pear-12773] : Reserved variables are not detected in strings + - Thanks to [Wilfried Loche][pear-wloche] for the patch +- Fixed bug [#12832][pear-12832] : Tab to space conversion does not work +- Fixed bug [#12888][pear-12888] : extra space indentation = Notice: Uninitialized string offset... +- Fixed bug [#12909][pear-12909] : Default generateDocs function does not work under linux + - Thanks to [Paul Smith][pear-thing2b] for the patch +- Fixed bug [#12957][pear-12957] : PHP 5.3 magic method __callStatic + - Thanks to [Manuel Pichler][@manuelpichler] for the patch + +[pear-12767]: https://pear.php.net/bugs/bug.php?id=12767 +[pear-12773]: https://pear.php.net/bugs/bug.php?id=12773 +[pear-12832]: https://pear.php.net/bugs/bug.php?id=12832 +[pear-12888]: https://pear.php.net/bugs/bug.php?id=12888 +[pear-12909]: https://pear.php.net/bugs/bug.php?id=12909 +[pear-12957]: https://pear.php.net/bugs/bug.php?id=12957 + +## 1.0.0 - 2007-12-21 + +### Changed +- You can now specify the full path to a coding standard on the command line (feature request [#11886][pear-11886]) + - This allows you to use standards that are stored outside of PHP_CodeSniffer's own Standard dir + - You can also specify full paths in the `CodingStandard.php` include and exclude methods + - Classes, dirs and files need to be names as if the standard was part of PHP_CodeSniffer + - Thanks to Dirk Thomas for the doc generator patch and testing +- Modified the scope map to keep checking after 3 lines for some tokens (feature request [#12561][pear-12561]) + - Those tokens that must have an opener (like T_CLASS) now keep looking until EOF + - Other tokens (like T_FUNCTION) still stop after 3 lines for performance +- You can now escape commas in ignore patterns so they can be matched in file names + - Thanks to [Carsten Wiedmann][pear-cwiedmann] for the patch +- Config data is now cached in a global var so the file system is not hit so often + - You can also set config data temporarily for the script if you are using your own external script + - Pass TRUE as the third argument to PHP_CodeSniffer::setConfigData() +- PEAR ClassDeclarationSniff no longer throws errors for multi-line class declarations +- Squiz ClassDeclarationSniff now ensures there is one blank line after a class closing brace +- Squiz ClassDeclarationSniff now throws errors for a missing end PHP tag after the end class tag +- Squiz IncrementDecrementUsageSniff no longer throws errors when -= and += are being used with vars +- Squiz SwitchDeclarationSniff now throws errors for switch statements that do not contain a case statement + - Thanks to [Sertan Danis][@sertand] for the patch +- MySource IncludeSystemSniff no longer throws errors for the Util package + +### Fixed +- Fixed bug [#12621][pear-12621] : "space after AS" check is wrong + - Thanks to [Satoshi Oikawa][pear-renoiv] for the patch +- Fixed bug [#12645][pear-12645] : error message is wrong + - Thanks to [Satoshi Oikawa][pear-renoiv] for the patch +- Fixed bug [#12651][pear-12651] : Increment/Decrement Operators Usage at -1 + +[pear-11886]: https://pear.php.net/bugs/bug.php?id=11886 +[pear-12561]: https://pear.php.net/bugs/bug.php?id=12561 +[pear-12621]: https://pear.php.net/bugs/bug.php?id=12621 +[pear-12645]: https://pear.php.net/bugs/bug.php?id=12645 +[pear-12651]: https://pear.php.net/bugs/bug.php?id=12651 + +## 1.0.0RC3 - 2007-11-30 + +### Changed +- Added new command line argument --tab-width that will convert tabs to spaces before testing + - This allows you to use the existing sniffs that check for spaces even when you use tabs + - Can also be set via a config var: phpcs --config-set tab_width 4 + - A value of zero (the default) tells PHP_CodeSniffer not to replace tabs with spaces +- You can now change the default report format from "full" to something else + - Run: phpcs `--config-set report_format [format]` +- Improved performance by optimising the way the scope map is created during tokenizing +- Added new Squiz DisallowInlineIfSniff to disallow the usage of inline IF statements +- Fixed incorrect errors being thrown for nested switches in Squiz SwitchDeclarationSniff +- PEAR FunctionCommentSniff no longer complains about missing comments for @throws tags +- PEAR FunctionCommentSniff now throws error for missing exception class name for @throws tags +- PHP_CodeSniffer_File::isReference() now correctly returns for functions that return references +- Generic LineLengthSniff no longer warns about @version lines with CVS or SVN id tags +- Generic LineLengthSniff no longer warns about @license lines with long URLs +- Squiz FunctionCommentThrowTagSniff no longer complains about throwing variables +- Squiz ComparisonOperatorUsageSniff no longer throws incorrect errors for inline IF statements +- Squiz DisallowMultipleAssignmentsSniff no longer throws errors for assignments in inline IF statements + +### Fixed +- Fixed bug [#12455][pear-12455] : CodeSniffer treats content inside heredoc as PHP code +- Fixed bug [#12471][pear-12471] : Checkstyle report is broken +- Fixed bug [#12476][pear-12476] : PHP4 destructors are reported as error +- Fixed bug [#12513][pear-12513] : Checkstyle XML messages need to be utf8_encode()d + - Thanks to [Sebastian Bergmann][@sebastianbergmann] for the patch. +- Fixed bug [#12517][pear-12517] : getNewlineAfter() and dos files + +[pear-12455]: https://pear.php.net/bugs/bug.php?id=12455 +[pear-12471]: https://pear.php.net/bugs/bug.php?id=12471 +[pear-12476]: https://pear.php.net/bugs/bug.php?id=12476 +[pear-12513]: https://pear.php.net/bugs/bug.php?id=12513 +[pear-12517]: https://pear.php.net/bugs/bug.php?id=12517 + +## 1.0.0RC2 - 2007-11-14 + +### Changed +- Added a new Checkstyle report format + - Like the current XML format but modified to look like Checkstyle output + - Thanks to [Manuel Pichler][@manuelpichler] for helping get the format correct +- You can now hide warnings by default + - Run: phpcs --config-set show_warnings 0 + - If warnings are hidden by default, use the new -w command line argument to override +- Added new command line argument --config-delete to delete a config value and revert to the default +- Improved overall performance by optimising tokenizing and next/prev methods (feature request [#12421][pear-12421]) + - Thanks to [Christian Weiske][@cweiske] for the patch +- Added FunctionCallSignatureSniff to Squiz standard +- Added @subpackage support to file and class comment sniffs in PEAR standard (feature request [#12382][pear-12382]) + - Thanks to [Carsten Wiedmann][pear-cwiedmann] for the patch +- An error is now displayed if you use a PHP version less than 5.1.0 (feature request [#12380][pear-12380]) + - Thanks to [Carsten Wiedmann][pear-cwiedmann] for the patch +- phpcs now exits with status 2 if it receives invalid input (feature request [#12380][pear-12380]) + - This is distinct from status 1, which indicates errors or warnings were found +- Added new Squiz LanguageConstructSpacingSniff to throw errors for additional whitespace after echo etc. +- Removed Squiz ValidInterfaceNameSniff +- PEAR FunctionCommentSniff no longer complains about unknown tags + +### Fixed +- Fixed incorrect errors about missing function comments in PEAR FunctionCommentSniff +- Fixed incorrect function docblock detection in Squiz FunctionCommentSniff +- Fixed incorrect errors for list() in Squiz DisallowMultipleAssignmentsSniff +- Errors no longer thrown if control structure is followed by a CASE's BREAK in Squiz ControlStructureSpacingSniff +- Fixed bug [#12368][pear-12368] : Autoloader cannot be found due to include_path override + - Thanks to [Richard Quadling][pear-rquadling] for the patch +- Fixed bug [#12378][pear-12378] : equal sign alignments problem with while() + +[pear-12368]: https://pear.php.net/bugs/bug.php?id=12368 +[pear-12378]: https://pear.php.net/bugs/bug.php?id=12378 +[pear-12380]: https://pear.php.net/bugs/bug.php?id=12380 +[pear-12382]: https://pear.php.net/bugs/bug.php?id=12382 +[pear-12421]: https://pear.php.net/bugs/bug.php?id=12421 + +## 1.0.0RC1 - 2007-11-01 + +### Changed +- Main phpcs script can now be run from a CVS checkout without installing the package +- Added a new CSV report format + - Header row indicates what position each element is in + - Always use the header row to determine positions rather than assuming the format, as it may change +- XML and CSV report formats now contain information about which column the error occurred at + - Useful if you want to highlight the token that caused the error in a custom application +- Square bracket tokens now have bracket_opener and bracket_closer set +- Added new Squiz SemicolonSpacingSniff to throw errors if whitespace is found before a semicolon +- Added new Squiz ArrayBracketSpacingSniff to throw errors if whitespace is found around square brackets +- Added new Squiz ObjectOperatorSpacingSniff to throw errors if whitespace is found around object operators +- Added new Squiz DisallowMultipleAssignmentsSniff to throw errors if multiple assignments are on the same line +- Added new Squiz ScopeKeywordSpacingSniff to throw errors if there is not a single space after a scope modifier +- Added new Squiz ObjectInstantiationSniff to throw errors if new objects are not assigned to a variable +- Added new Squiz FunctionDuplicateArgumentSniff to throw errors if argument is declared multiple times in a function +- Added new Squiz FunctionOpeningBraceSpaceSniff to ensure there are no blank lines after a function open brace +- Added new Squiz CommentedOutCodeSniff to warn about comments that looks like they are commented out code blocks +- Added CyclomaticComplexitySniff to Squiz standard +- Added NestingLevelSniff to Squiz standard +- Squiz ForbiddenFunctionsSniff now recommends echo() instead of print() +- Squiz ValidLogicalOperatorsSniff now recommends ^ instead of xor +- Squiz SwitchDeclarationSniff now contains more checks + - A single space is required after the case keyword + - No space is allowed before the colon in a case or default statement + - All switch statements now require a default case + - Default case must contain a break statement + - Empty default case must contain a comment describing why the default is ignored + - Empty case statements are not allowed + - Case and default statements must not be followed by a blank line + - Break statements must be followed by a blank line or the closing brace + - There must be no blank line before a break statement +- Squiz standard is now using the PEAR IncludingFileSniff +- PEAR ClassCommentSniff no longer complains about unknown tags +- PEAR FileCommentSniff no longer complains about unknown tags +- PEAR FileCommentSniff now accepts multiple @copyright tags +- Squiz BlockCommentSniff now checks that comment starts with a capital letter +- Squiz InlineCommentSniff now has better checking to ensure comment starts with a capital letter +- Squiz ClassCommentSniff now checks that short and long comments start with a capital letter +- Squiz FunctionCommentSniff now checks that short, long and param comments start with a capital letter +- Squiz VariableCommentSniff now checks that short and long comments start with a capital letter + +### Fixed +- Fixed error with multi-token array indexes in Squiz ArrayDeclarationSniff +- Fixed error with checking shorthand IF statements without a semicolon in Squiz InlineIfDeclarationSniff +- Fixed error where constants used as default values in function declarations were seen as type hints +- Fixed bug [#12316][pear-12316] : PEAR is no longer the default standard +- Fixed bug [#12321][pear-12321] : wrong detection of missing function docblock + +[pear-12316]: https://pear.php.net/bugs/bug.php?id=12316 +[pear-12321]: https://pear.php.net/bugs/bug.php?id=12321 + +## 0.9.0 - 2007-09-24 + +### Changed +- Added a config system for setting config data across phpcs runs +- You can now change the default coding standard from PEAR to something else + - Run: phpcs `--config-set default_standard [standard]` +- Added new Zend coding standard to check code against the Zend Framework standards + - The complete standard is not yet implemented + - Specify --standard=Zend to use + - Thanks to Johann-Peter Hartmann for the contribution of some sniffs + - Thanks to Holger Kral for the Code Analyzer sniff + +## 0.8.0 - 2007-08-08 + +### Changed +- Added new XML report format; --report=xml (feature request [#11535][pear-11535]) + - Thanks to [Brett Bieber][@saltybeagle] for the patch +- Added new command line argument --ignore to specify a list of files to skip (feature request [#11556][pear-11556]) +- Added PHPCS and MySource coding standards into the core install +- Scope map no longer gets confused by curly braces that act as string offsets +- Removed `CodeSniffer/SniffException.php` as it is no longer used +- Unit tests can now be run directly from a CVS checkout +- Made private vars and functions protected in PHP_CodeSniffer class so this package can be overridden +- Added new Metrics category to Generic coding standard + - Contains Cyclomatic Complexity and Nesting Level sniffs + - Thanks to Johann-Peter Hartmann for the contribution +- Added new Generic DisallowTabIndentSniff to throw errors if tabs are used for indentation (feature request [#11738][pear-11738]) + - PEAR and Squiz standards use this new sniff to throw more specific indentation errors +- Generic MultipleStatementAlignmentSniff has new private var to set a padding size limit (feature request [#11555][pear-11555]) +- Generic MultipleStatementAlignmentSniff can now handle assignments that span multiple lines (feature request [#11561][pear-11561]) +- Generic LineLengthSniff now has a max line length after which errors are thrown instead of warnings + - BC BREAK: Override the protected member var absoluteLineLimit and set it to zero in custom LineLength sniffs + - Thanks to Johann-Peter Hartmann for the contribution +- Comment sniff errors about incorrect tag orders are now more descriptive (feature request [#11693][pear-11693]) + +### Fixed +- Fixed bug [#11473][pear-11473] : Invalid CamelCaps name when numbers used in names + +[pear-11473]: https://pear.php.net/bugs/bug.php?id=11473 +[pear-11535]: https://pear.php.net/bugs/bug.php?id=11535 +[pear-11555]: https://pear.php.net/bugs/bug.php?id=11555 +[pear-11556]: https://pear.php.net/bugs/bug.php?id=11556 +[pear-11561]: https://pear.php.net/bugs/bug.php?id=11561 +[pear-11693]: https://pear.php.net/bugs/bug.php?id=11693 +[pear-11738]: https://pear.php.net/bugs/bug.php?id=11738 + +## 0.7.0 - 2007-07-02 + +### Changed +- BC BREAK: EOL character is now auto-detected and used instead of hard-coded \n + - Pattern sniffs must now specify "EOL" instead of "\n" or "\r\n" to use auto-detection + - Please use $phpcsFile->eolChar to check for newlines instead of hard-coding "\n" or "\r\n" + - Comment parser classes now require you to pass $phpcsFile as an additional argument +- BC BREAK: Included and excluded sniffs now require `.php` extension + - Please update your coding standard classes and add `.php` to all sniff entries + - See `CodeSniffer/Standards/PEAR/PEARCodingStandard.php` for an example +- Fixed error where including a directory of sniffs in a coding standard class did not work +- Coding standard classes can now specify a list of sniffs to exclude as well as include (feature request [#11056][pear-11056]) +- Two uppercase characters can now be placed side-by-side in class names in Squiz ValidClassNameSniff +- SVN tags now allowed in PEAR file doc blocks (feature request [#11038][pear-11038]) + - Thanks to [Torsten Roehr][pear-troehr] for the patch +- Private methods in commenting sniffs and comment parser are now protected (feature request [#11087][pear-11087]) +- Added Generic LineEndingsSniff to check the EOL character of a file +- PEAR standard now only throws one error per file for incorrect line endings (eg. /r/n) +- Command line arg -v now shows number of registered sniffs +- Command line arg -vvv now shows list of registered sniffs +- Squiz ControlStructureSpacingSniff no longer throws errors if the control structure is at the end of the script +- Squiz FunctionCommentSniff now throws error for "return void" if function has return statement +- Squiz FunctionCommentSniff now throws error for functions that return void but specify something else +- Squiz ValidVariableNameSniff now allows multiple uppercase letters in a row +- Squiz ForEachLoopDeclarationSniff now throws error for AS keyword not being lowercase +- Squiz SwitchDeclarationSniff now throws errors for CASE/DEFAULT/BREAK keywords not being lowercase +- Squiz ArrayDeclarationSniff now handles multi-token array values when checking alignment +- Squiz standard now enforces a space after cast tokens +- Generic MultipleStatementAlignmentSniff no longer gets confused by assignments inside FOR conditions +- Generic MultipleStatementAlignmentSniff no longer gets confused by the use of list() +- Added Generic SpaceAfterCastSniff to ensure there is a single space after a cast token +- Added Generic NoSpaceAfterCastSniff to ensure there is no whitespace after a cast token +- Added PEAR ClassDeclarationSniff to ensure the opening brace of a class is on the line after the keyword +- Added Squiz ScopeClosingBraceSniff to ensure closing braces are aligned correctly +- Added Squiz EvalSniff to discourage the use of eval() +- Added Squiz LowercaseDeclarationSniff to ensure all declaration keywords are lowercase +- Added Squiz LowercaseClassKeywordsSniff to ensure all class declaration keywords are lowercase +- Added Squiz LowercaseFunctionKeywordsSniff to ensure all function declaration keywords are lowercase +- Added Squiz LowercasePHPFunctionsSniff to ensure all calls to inbuilt PHP functions are lowercase +- Added Squiz CastSpacingSniff to ensure cast statements don't contain whitespace +- Errors no longer thrown when checking 0 length files with verbosity on + +### Fixed +- Fixed bug [#11105][pear-11105] : getIncludedSniffs() not working anymore + - Thanks to [Blair Robertson][pear-adviva] for the patch +- Fixed bug [#11120][pear-11120] : Uninitialized string offset in `AbstractParser.php` on line 200 + +[pear-11038]: https://pear.php.net/bugs/bug.php?id=11038 +[pear-11056]: https://pear.php.net/bugs/bug.php?id=11056 +[pear-11087]: https://pear.php.net/bugs/bug.php?id=11087 +[pear-11105]: https://pear.php.net/bugs/bug.php?id=11105 +[pear-11120]: https://pear.php.net/bugs/bug.php?id=11120 + +## 0.6.0 - 2007-05-15 + +### Changed +- The number of errors and warnings found is now shown for each file while checking the file if verbosity is enabled +- Now using PHP_EOL instead of hard-coded \n so output looks good on Windows (feature request [#10761][pear-10761]) + - Thanks to [Carsten Wiedmann][pear-cwiedmann] for the patch. +- phpcs now exits with status 0 (no errors) or 1 (errors found) (feature request [#10348][pear-10348]) +- Added new -l command line argument to stop recursion into directories (feature request [#10979][pear-10979]) + +### Fixed +- Fixed variable name error causing incorrect error message in Squiz ValidVariableNameSniff +- Fixed bug [#10757][pear-10757] : Error in ControlSignatureSniff +- Fixed bugs [#10751][pear-10751], [#10777][pear-10777] : Sniffer class paths handled incorrectly in Windows + - Thanks to [Carsten Wiedmann][pear-cwiedmann] for the patch. +- Fixed bug [#10961][pear-10961] : Error "Last parameter comment requires a blank newline after it" thrown +- Fixed bug [#10983][pear-10983] : phpcs outputs notices when checking invalid PHP +- Fixed bug [#10980][pear-10980] : Incorrect warnings for equals sign + +[pear-10348]: https://pear.php.net/bugs/bug.php?id=10348 +[pear-10751]: https://pear.php.net/bugs/bug.php?id=10751 +[pear-10757]: https://pear.php.net/bugs/bug.php?id=10757 +[pear-10761]: https://pear.php.net/bugs/bug.php?id=10761 +[pear-10777]: https://pear.php.net/bugs/bug.php?id=10777 +[pear-10961]: https://pear.php.net/bugs/bug.php?id=10961 +[pear-10979]: https://pear.php.net/bugs/bug.php?id=10979 +[pear-10980]: https://pear.php.net/bugs/bug.php?id=10980 +[pear-10983]: https://pear.php.net/bugs/bug.php?id=10983 + +## 0.5.0 - 2007-04-17 + +### Changed +- BC BREAK: Coding standards now require a class to be added so PHP_CodeSniffer can get information from them + - Please read the end user docs for info about the new class required for all coding standards +- Coding standards can now include sniffs from other standards, or whole standards, without writing new sniff files +- PHP_CodeSniffer_File::isReference() now correctly returns for references in function declarations +- PHP_CodeSniffer_File::isReference() now returns false if you don't pass it a T_BITWISE_AND token +- PHP_CodeSniffer_File now stores the absolute path to the file so sniffs can check file locations correctly +- Fixed undefined index error in AbstractVariableSniff for variables inside an interface function definition +- Added MemberVarSpacingSniff to Squiz standard to enforce one-line spacing between member vars +- Add FunctionCommentThrowTagSniff to Squiz standard to check that @throws tags are correct + +### Fixed +- Fixed problems caused by references and type hints in Squiz FunctionDeclarationArgumentSpacingSniff +- Fixed problems with errors not being thrown for some misaligned @param comments in Squiz FunctionCommentSniff +- Fixed badly spaced comma error being thrown for "extends" class in Squiz ClassDeclarationSniff +- Errors no longer thrown for class method names in Generic ForbiddenFunctionsSniff +- Errors no longer thrown for type hints in front of references in Generic UpperCaseConstantNameSniff +- Errors no longer thrown for correctly indented buffered lines in Squiz ScopeIndexSniff +- Errors no longer thrown for user-defined functions named as forbidden functions in Generic ForbiddenFunctionsSniff +- Errors no longer thrown on __autoload functions in PEAR ValidFunctionNameSniff +- Errors now thrown for __autoload methods in PEAR ValidFunctionNameSniff +- Errors now thrown if constructors or destructors have @return tags in Squiz FunctionCommentSniff +- Errors now thrown if @throws tags don't start with a capital and end with a full stop in Squiz FunctionCommentSniff +- Errors now thrown for invalid @var tag values in Squiz VariableCommentSniff +- Errors now thrown for missing doc comment in Squiz VariableCommentSniff +- Errors now thrown for unspaced operators in FOR loop declarations in Squiz OperatorSpacingSniff +- Errors now thrown for using ob_get_clean/flush functions to end buffers in Squiz OutputBufferingIndentSniff +- Errors now thrown for all missing member variable comments in Squiz VariableCommentSniff + +## 0.4.0 - 2007-02-19 + +### Changed +- Standard name specified with --standard command line argument is no longer case sensitive +- Long error and warning messages are now wrapped to 80 characters in the full error report (thanks Endre Czirbesz) +- Shortened a lot of error and warning messages so they don't take up so much room +- Squiz FunctionCommentSniff now checks that param comments start with a capital letter and end with a full stop +- Squiz FunctionSpacingSniff now reports incorrect lines below function on closing brace, not function keyword +- Squiz FileCommentSniff now checks that there are no blank lines between the open PHP tag and the comment +- PHP_CodeSniffer_File::isReference() now returns correctly when checking refs on right side of => + +### Fixed +- Fixed incorrect error with switch closing brace in Squiz SwitchDeclarationSniff +- Fixed missing error when multiple statements are not aligned correctly with object operators +- Fixed incorrect errors for some PHP special variables in Squiz ValidVariableNameSniff +- Fixed incorrect errors for arrays that only contain other arrays in Squiz ArrayDeclarationSniff +- Fixed bug [#9844][pear-9844] : throw new Exception(\n accidentally reported as error but it ain't + +[pear-9844]: https://pear.php.net/bugs/bug.php?id=9844 + +## 0.3.0 - 2007-01-11 + +### Changed +- Updated package.xml to version 2 +- Specifying coding standard on command line is now optional, even if you have multiple standards installed + - PHP_CodeSniffer uses the PEAR coding standard by default if no standard is specified +- New command line option, --extensions, to specify a comma separated list of file extensions to check +- Converted all unit tests to PHPUnit 3 format +- Added new coding standard, Squiz, that can be used as an alternative to PEAR + - also contains more examples of sniffs + - some may be moved into the Generic coding standard if required +- Added MultipleStatementAlignmentSniff to Generic standard +- Added ScopeIndentSniff to Generic standard +- Added ForbiddenFunctionsSniff to Generic standard +- Added FileCommentSniff to PEAR standard +- Added ClassCommentSniff to PEAR standard +- Added FunctionCommentSniff to PEAR standard +- Change MultipleStatementSniff to MultipleStatementAlignmentSniff in PEAR standard +- Replaced Methods directory with Functions directory in Generic and PEAR standards + - also renamed some of the sniffs in those directories +- Updated file, class and method comments for all files + +### Fixed +- Fixed bug [#9274][pear-9274] : nested_parenthesis element not set for open and close parenthesis tokens +- Fixed bug [#9411][pear-9411] : too few pattern characters cause incorrect error report + +[pear-9411]: https://pear.php.net/bugs/bug.php?id=9411 + +## 0.2.1 - 2006-11-09 + +### Fixed +- Fixed bug [#9274][pear-9274] : nested_parenthesis element not set for open and close parenthesis tokens + +[pear-9274]: https://pear.php.net/bugs/bug.php?id=9274 + +## 0.2.0 - 2006-10-13 + +### Changed +- Added a generic standards package that will contain generic sniffs to be used in specific coding standards + - thanks to Frederic Poeydomenge for the idea +- Changed PEAR standard to use generic sniffs where available +- Added LowerCaseConstantSniff to Generic standard +- Added UpperCaseConstantSniff to Generic standard +- Added DisallowShortOpenTagSniff to Generic standard +- Added LineLengthSniff to Generic standard +- Added UpperCaseConstantNameSniff to Generic standard +- Added OpeningMethodBraceBsdAllmanSniff to Generic standard (contrib by Frederic Poeydomenge) +- Added OpeningMethodBraceKernighanRitchieSniff to Generic standard (contrib by Frederic Poeydomenge) +- Added framework for core PHP_CodeSniffer unit tests +- Added unit test for PHP_CodeSniffer:isCamelCaps method +- ScopeClosingBraceSniff now checks indentation of BREAK statements +- Added new command line arg (-vv) to show developer debug output + +### Fixed +- Fixed some coding standard errors +- Fixed bug [#8834][pear-8834] : Massive memory consumption +- Fixed bug [#8836][pear-8836] : path case issues in package.xml +- Fixed bug [#8843][pear-8843] : confusion on nested switch() +- Fixed bug [#8841][pear-8841] : comments taken as whitespace +- Fixed bug [#8884][pear-8884] : another problem with nested switch() statements + +[pear-8834]: https://pear.php.net/bugs/bug.php?id=8834 +[pear-8836]: https://pear.php.net/bugs/bug.php?id=8836 +[pear-8841]: https://pear.php.net/bugs/bug.php?id=8841 +[pear-8843]: https://pear.php.net/bugs/bug.php?id=8843 +[pear-8884]: https://pear.php.net/bugs/bug.php?id=8884 + +## 0.1.1 - 2006-09-25 + +### Changed +- Added unit tests for all PEAR sniffs +- Exception class now extends from PEAR_Exception + +### Fixed +- Fixed summary report so files without errors but with warnings are not shown when warnings are hidden + +## 0.1.0 - 2006-09-19 + +### Changed +- Reorganised package contents to conform to PEAR standards +- Changed version numbering to conform to PEAR standards +- Removed duplicate `require_once()` of `Exception.php` from `CodeSniffer.php` + +## 0.0.5 - 2006-09-18 + +### Fixed +- Fixed `.bat` file for situation where `php.ini` cannot be found so `include_path` is not set + +## 0.0.4 - 2006-08-28 + +### Changed +- Added .bat file for easier running of PHP_CodeSniffer on Windows +- Sniff that checks method names now works for PHP4 style code where there is no scope keyword +- Sniff that checks method names now works for PHP4 style constructors +- Sniff that checks method names no longer incorrectly reports error with magic methods +- Sniff that checks method names now reports errors with non-magic methods prefixed with __ +- Sniff that checks for constant names no longer incorrectly reports errors with heredoc strings +- Sniff that checks for constant names no longer incorrectly reports errors with created objects +- Sniff that checks indentation no longer incorrectly reports errors with heredoc strings +- Sniff that checks indentation now correctly reports errors with improperly indented multi-line strings +- Sniff that checks function declarations now checks for spaces before and after an equals sign for default values +- Sniff that checks function declarations no longer incorrectly reports errors with multi-line declarations +- Sniff that checks included code no longer incorrectly reports errors when return value is used conditionally +- Sniff that checks opening brace of function no longer incorrectly reports errors with multi-line declarations +- Sniff that checks spacing after commas in function calls no longer reports too many errors for some code +- Sniff that checks control structure declarations now gives more descriptive error message + +## 0.0.3 - 2006-08-22 + +### Changed +- Added sniff to check for invalid class and interface names +- Added sniff to check for invalid function and method names +- Added sniff to warn if line is greater than 85 characters +- Added sniff to check that function calls are in the correct format +- Added command line arg to print current version (--version) + +### Fixed +- Fixed error where comments were not allowed on the same line as a control structure declaration + +## 0.0.2 - 2006-07-25 + +### Changed +- Removed the including of checked files to stop errors caused by parsing them +- Removed the use of reflection so checked files do not have to be included +- Memory usage has been greatly reduced +- Much faster tokenizing and checking times +- Reworked the PEAR coding standard sniffs (much faster now) +- Fix some bugs with the PEAR scope indentation standard +- Better checking for installed coding standards +- Can now accept multiple files and dirs on the command line +- Added an option to list installed coding standards +- Added an option to print a summary report (number of errors and warnings shown for each file) +- Added an option to hide warnings from reports +- Added an option to print verbose output (so you know what is going on) +- Reordered command line args to put switches first (although order is not enforced) +- Switches can now be specified together (e.g. `phpcs -nv`) as well as separately (`phpcs -n -v`) + +## 0.0.1 - 2006-07-19 + +### Added +- Initial preview release + + + +[Unreleased]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/master...HEAD +[3.11.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.11.0...3.11.1 +[3.11.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.10.3...3.11.0 +[3.10.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.10.2...3.10.3 +[3.10.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.10.1...3.10.2 +[3.10.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.10.0...3.10.1 +[3.10.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.9.2...3.10.0 +[3.9.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.9.1...3.9.2 +[3.9.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.9.0...3.9.1 +[3.9.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.8.1...3.9.0 +[3.8.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.8.0...3.8.1 +[3.8.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.7.2...3.8.0 +[3.7.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.7.1...3.7.2 +[3.7.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.7.0...3.7.1 +[3.7.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.6.2...3.7.0 +[3.6.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.6.1...3.6.2 +[3.6.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.6.0...3.6.1 +[3.6.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.8...3.6.0 +[3.5.8]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.7...3.5.8 +[3.5.7]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.6...3.5.7 +[3.5.6]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.5...3.5.6 +[3.5.5]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.4...3.5.5 +[3.5.4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.3...3.5.4 +[3.5.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.2...3.5.3 +[3.5.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.1...3.5.2 +[3.5.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.5.0...3.5.1 +[3.5.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.4.2...3.5.0 +[3.4.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.4.1...3.4.2 +[3.4.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.4.0...3.4.1 +[3.4.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.3.2...3.4.0 +[3.3.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.3.1...3.3.2 +[3.3.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.3.0...3.3.1 +[3.3.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.2.3...3.3.0 +[3.2.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.2.2...3.2.3 +[3.2.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.2.1...3.2.2 +[3.2.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.2.0...3.2.1 +[3.2.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.1.1...3.2.0 +[3.1.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.1.0...3.1.1 +[3.1.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.2...3.1.0 +[3.0.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.0RC4...3.0.0 +[3.0.0RC4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.0RC3...3.0.0RC4 +[3.0.0RC3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.0RC2...3.0.0RC3 +[3.0.0RC2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.0RC1...3.0.0RC2 +[3.0.0RC1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/3.0.0a1...3.0.0RC1 +[3.0.0a1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.9.2...3.0.0a1 +[2.9.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.9.1...2.9.2 +[2.9.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.9.0...2.9.1 +[2.9.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.8.1...2.9.0 +[2.8.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.8.0...2.8.1 +[2.8.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.7.1...2.8.0 +[2.7.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.7.0...2.7.1 +[2.7.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.6.2...2.7.0 +[2.6.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.6.1...2.6.2 +[2.6.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.6.0...2.6.1 +[2.6.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.5.1...2.6.0 +[2.5.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.5.0...2.5.1 +[2.5.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.4.0...2.5.0 +[2.4.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.3.4...2.4.0 +[2.3.4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.3.3...2.3.4 +[2.3.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.3.2...2.3.3 +[2.3.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.3.1...2.3.2 +[2.3.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.3.0...2.3.1 +[2.3.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.2.0...2.3.0 +[2.2.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.1.0...2.2.0 +[2.1.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0...2.1.0 +[2.0.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0RC4...2.0.0 +[2.0.0RC4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0RC3...2.0.0RC4 +[2.0.0RC3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0RC2...2.0.0RC3 +[2.0.0RC2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0RC1...2.0.0RC2 +[2.0.0RC1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0a2...2.0.0RC1 +[2.0.0a2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/2.0.0a1...2.0.0a2 +[2.0.0a1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.6...2.0.0a1 +[1.5.6]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.5...1.5.6 +[1.5.5]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.4...1.5.5 +[1.5.4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.3...1.5.4 +[1.5.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.2...1.5.3 +[1.5.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.1...1.5.2 +[1.5.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.0...1.5.1 +[1.5.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.0RC4...1.5.0 +[1.5.0RC4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.0RC3...1.5.0RC4 +[1.5.0RC3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.0RC2...1.5.0RC3 +[1.5.0RC2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.5.0RC1...1.5.0RC2 +[1.5.0RC1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.8...1.5.0RC1 +[1.4.8]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.7...1.4.8 +[1.4.7]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.6...1.4.7 +[1.4.6]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.5...1.4.6 +[1.4.5]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.4...1.4.5 +[1.4.4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.3...1.4.4 +[1.4.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.2...1.4.3 +[1.4.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.4.0...1.4.1 +[1.4.0]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.3.6...1.4.0 +[1.3.6]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.3.5...1.3.6 +[1.3.5]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.3.4...1.3.5 +[1.3.4]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.3.3...1.3.4 +[1.3.3]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.3.2...1.3.3 +[1.3.2]: https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/1.3.1...1.3.2 + + + +[@2shediac]: https://github.com/2shediac +[@ablyler]: https://github.com/ablyler +[@aboks]: https://github.com/aboks +[@abulford]: https://github.com/abulford +[@afilina]: https://github.com/afilina +[@aik099]: https://github.com/aik099 +[@akarmazyn]: https://github.com/akarmazyn +[@akkie]: https://github.com/akkie +[@alcohol]: https://github.com/alcohol +[@alekitto]: https://github.com/alekitto +[@AlexHowansky]: https://github.com/AlexHowansky +[@anbuc]: https://github.com/anbuc +[@andrei-propertyguru]: https://github.com/andrei-propertyguru +[@AndrewDawes]: https://github.com/AndrewDawes +[@andygrunwald]: https://github.com/andygrunwald +[@andypost]: https://github.com/andypost +[@annechko]: https://github.com/annechko +[@anomiex]: https://github.com/anomiex +[@arnested]: https://github.com/arnested +[@asnyder]: https://github.com/asnyder +[@Astinus-Eberhard]: https://github.com/Astinus-Eberhard +[@axlon]: https://github.com/axlon +[@bayleedev]: https://github.com/bayleedev +[@becoded]: https://github.com/becoded +[@Benjamin-Loison]: https://github.com/Benjamin-Loison +[@benmatselby]: https://github.com/benmatselby +[@biinari]: https://github.com/biinari +[@Billz95]: https://github.com/Billz95 +[@biozshock]: https://github.com/biozshock +[@bkdotcom]: https://github.com/bkdotcom +[@bladeofsteel]: https://github.com/bladeofsteel +[@blerou]: https://github.com/blerou +[@blue32a]: https://github.com/blue32a +[@bondas83]: https://github.com/bondas83 +[@boonkerz]: https://github.com/boonkerz +[@BRMatt]: https://github.com/BRMatt +[@CandySunPlus]: https://github.com/CandySunPlus +[@ceeram]: https://github.com/ceeram +[@cixtor]: https://github.com/cixtor +[@claylo]: https://github.com/claylo +[@codebymikey]: https://github.com/codebymikey +[@costdev]: https://github.com/costdev +[@covex-nn]: https://github.com/covex-nn +[@cweiske]: https://github.com/cweiske +[@Daimona]: https://github.com/Daimona +[@danez]: https://github.com/danez +[@DannyvdSluijs]: https://github.com/DannyvdSluijs +[@das-peter]: https://github.com/das-peter +[@datengraben]: https://github.com/datengraben +[@david-binda]: https://github.com/david-binda +[@Decave]: https://github.com/Decave +[@dereuromark]: https://github.com/dereuromark +[@derrabus]: https://github.com/derrabus +[@deviantintegral]: https://github.com/deviantintegral +[@dhensby]: https://github.com/dhensby +[@dingo-d]: https://github.com/dingo-d +[@dominics]: https://github.com/dominics +[@donatj]: https://github.com/donatj +[@dryabkov]: https://github.com/dryabkov +[@dschniepp]: https://github.com/dschniepp +[@duncan3dc]: https://github.com/duncan3dc +[@edorian]: https://github.com/edorian +[@elazar]: https://github.com/elazar +[@ElvenSpellmaker]: https://github.com/ElvenSpellmaker +[@emil-nasso]: https://github.com/emil-nasso +[@enl]: https://github.com/enl +[@erikwiffin]: https://github.com/erikwiffin +[@eser]: https://github.com/eser +[@exussum12]: https://github.com/exussum12 +[@fabacino]: https://github.com/fabacino +[@fabre-thibaud]: https://github.com/fabre-thibaud +[@fcool]: https://github.com/fcool +[@filips123]: https://github.com/filips123 +[@Fischer-Bjoern]: https://github.com/Fischer-Bjoern +[@fonsecas72]: https://github.com/fonsecas72 +[@fredden]: https://github.com/fredden +[@GaryJones]: https://github.com/GaryJones +[@ghostal]: https://github.com/ghostal +[@ghunti]: https://github.com/ghunti +[@gmponos]: https://github.com/gmponos +[@gnutix]: https://github.com/gnutix +[@goatherd]: https://github.com/goatherd +[@grongor]: https://github.com/grongor +[@grzr]: https://github.com/grzr +[@gwharton]: https://github.com/gwharton +[@hashar]: https://github.com/hashar +[@helgi]: https://github.com/helgi +[@hernst42]: https://github.com/hernst42 +[@iammattcoleman]: https://github.com/iammattcoleman +[@ihabunek]: https://github.com/ihabunek +[@illusori]: https://github.com/illusori +[@index0h]: https://github.com/index0h +[@ivuorinen]: https://github.com/ivuorinen +[@jasonmccreary]: https://github.com/jasonmccreary +[@javer]: https://github.com/javer +[@JDGrimes]: https://github.com/JDGrimes +[@jedgell]: https://github.com/jedgell +[@jeffslofish]: https://github.com/jeffslofish +[@jmarcil]: https://github.com/jmarcil +[@jnrbsn]: https://github.com/jnrbsn +[@joachim-n]: https://github.com/joachim-n +[@joelposti]: https://github.com/joelposti +[@johanderuijter]: https://github.com/johanderuijter +[@johnmaguire]: https://github.com/johnmaguire +[@johnpbloch]: https://github.com/johnpbloch +[@jonmcp]: https://github.com/jonmcp +[@JorisDebonnet]: https://github.com/JorisDebonnet +[@josephzidell]: https://github.com/josephzidell +[@joshdavis11]: https://github.com/joshdavis11 +[@jpoliveira08]: https://github.com/jpoliveira08 +[@jpuck]: https://github.com/jpuck +[@jrfnl]: https://github.com/jrfnl +[@kdebisschop]: https://github.com/kdebisschop +[@kenguest]: https://github.com/kenguest +[@klausi]: https://github.com/klausi +[@Konafets]: https://github.com/Konafets +[@kristofser]: https://github.com/kristofser +[@ksimka]: https://github.com/ksimka +[@ktomk]: https://github.com/ktomk +[@kukulich]: https://github.com/kukulich +[@legoktm]: https://github.com/legoktm +[@lmanzke]: https://github.com/lmanzke +[@localheinz]: https://github.com/localheinz +[@lucc]: https://github.com/lucc +[@MacDada]: https://github.com/MacDada +[@Majkl578]: https://github.com/Majkl578 +[@manuelpichler]: https://github.com/manuelpichler +[@marcospassos]: https://github.com/marcospassos +[@MarkBaker]: https://github.com/MarkBaker +[@MarkMaldaba]: https://github.com/MarkMaldaba +[@martinssipenko]: https://github.com/martinssipenko +[@marvasDE]: https://github.com/marvasDE +[@maryo]: https://github.com/maryo +[@MasterOdin]: https://github.com/MasterOdin +[@mathroc]: https://github.com/mathroc +[@MatmaRex]: https://github.com/MatmaRex +[@maxgalbu]: https://github.com/maxgalbu +[@mcuelenaere]: https://github.com/mcuelenaere +[@mhujer]: https://github.com/mhujer +[@michaelbutler]: https://github.com/michaelbutler +[@michalbundyra]: https://github.com/michalbundyra +[@Morerice]: https://github.com/Morerice +[@mbomb007]: https://github.com/mbomb007 +[@morozov]: https://github.com/morozov +[@mrkrstphr]: https://github.com/mrkrstphr +[@mythril]: https://github.com/mythril +[@Naelyth]: https://github.com/Naelyth +[@ndm2]: https://github.com/ndm2 +[@nicholascus]: https://github.com/nicholascus +[@NickDickinsonWilde]: https://github.com/NickDickinsonWilde +[@nkovacs]: https://github.com/nkovacs +[@nubs]: https://github.com/nubs +[@o5]: https://github.com/o5 +[@ofbeaton]: https://github.com/ofbeaton +[@olemartinorg]: https://github.com/olemartinorg +[@ondrejmirtes]: https://github.com/ondrejmirtes +[@orx0r]: https://github.com/orx0r +[@ostrolucky]: https://github.com/ostrolucky +[@pfrenssen]: https://github.com/pfrenssen +[@phil-davis]: https://github.com/phil-davis +[@photodude]: https://github.com/photodude +[@przemekhernik]: https://github.com/przemekhernik +[@r3nat]: https://github.com/r3nat +[@raul338]: https://github.com/raul338 +[@realmfoo]: https://github.com/realmfoo +[@remicollet]: https://github.com/remicollet +[@renaatdemuynck]: https://github.com/renaatdemuynck +[@renan]: https://github.com/renan +[@rhorber]: https://github.com/rhorber +[@rmccue]: https://github.com/rmccue +[@robocoder]: https://github.com/robocoder +[@rodrigoprimo]: https://github.com/rodrigoprimo +[@rogeriopradoj]: https://github.com/rogeriopradoj +[@rovangju]: https://github.com/rovangju +[@rvanvelzen]: https://github.com/rvanvelzen +[@saltybeagle]: https://github.com/saltybeagle +[@samlev]: https://github.com/samlev +[@scato]: https://github.com/scato +[@schlessera]: https://github.com/schlessera +[@schnittstabil]: https://github.com/schnittstabil +[@sebastianbergmann]: https://github.com/sebastianbergmann +[@sertand]: https://github.com/sertand +[@shanethehat]: https://github.com/shanethehat +[@shivammathur]: https://github.com/shivammathur +[@simonsan]: https://github.com/simonsan +[@sjlangley]: https://github.com/sjlangley +[@sserbin]: https://github.com/sserbin +[@stefanlenselink]: https://github.com/stefanlenselink +[@SteveTalbot]: https://github.com/SteveTalbot +[@storeman]: https://github.com/storeman +[@stronk7]: https://github.com/stronk7 +[@svycka]: https://github.com/svycka +[@syranez]: https://github.com/syranez +[@tasuki]: https://github.com/tasuki +[@tim-bezhashvyly]: https://github.com/tim-bezhashvyly +[@TomHAnderson]: https://github.com/TomHAnderson +[@thewilkybarkid]: https://github.com/thewilkybarkid +[@thiemowmde]: https://github.com/thiemowmde +[@thomasjfox]: https://github.com/thomasjfox +[@till]: https://github.com/till +[@timoschinkel]: https://github.com/timoschinkel +[@TimWolla]: https://github.com/TimWolla +[@uniquexor]: https://github.com/uniquexor +[@valorin]: https://github.com/valorin +[@VasekPurchart]: https://github.com/VasekPurchart +[@VincentLanglet]: https://github.com/VincentLanglet +[@waltertamboer]: https://github.com/waltertamboer +[@westonruter]: https://github.com/westonruter +[@willemstuursma]: https://github.com/willemstuursma +[@wimg]: https://github.com/wimg +[@wvega]: https://github.com/wvega +[@xalopp]: https://github.com/xalopp +[@xjm]: https://github.com/xjm +[@xt99]: https://github.com/xt99 +[@yesmeck]: https://github.com/yesmeck +[@zBart]: https://github.com/zBart +[pear-adviva]: https://pear.php.net/user/adviva +[pear-bakert]: https://pear.php.net/user/bakert +[pear-bjorn]: https://pear.php.net/user/bjorn +[pear-boxgav]: https://pear.php.net/user/boxgav +[pear-burci]: https://pear.php.net/user/burci +[pear-conf]: https://pear.php.net/user/conf +[pear-cwiedmann]: https://pear.php.net/user/cwiedmann +[pear-dollyaswin]: https://pear.php.net/user/dollyaswin +[pear-dvino]: https://pear.php.net/user/dvino +[pear-et3w503]: https://pear.php.net/user/et3w503 +[pear-gemineye]: https://pear.php.net/user/gemineye +[pear-kwinahradsky]: https://pear.php.net/user/kwinahradsky +[pear-ljmaskey]: https://pear.php.net/user/ljmaskey +[pear-mccammos]: https://pear.php.net/user/mccammos +[pear-pete]: https://pear.php.net/user/pete +[pear-recurser]: https://pear.php.net/user/recurser +[pear-renoiv]: https://pear.php.net/user/renoiv +[pear-rquadling]: https://pear.php.net/user/rquadling +[pear-ryba]: https://pear.php.net/user/ryba +[pear-thezero]: https://pear.php.net/user/thezero +[pear-thing2b]: https://pear.php.net/user/thing2b +[pear-tomdesp]: https://pear.php.net/user/tomdesp +[pear-troehr]: https://pear.php.net/user/troehr +[pear-weirdan]: https://pear.php.net/user/weirdan +[pear-wloche]: https://pear.php.net/user/wloche +[pear-woellchen]: https://pear.php.net/user/woellchen +[pear-youngian]: https://pear.php.net/user/youngian + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf new file mode 100644 index 000000000..d0252f3f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf @@ -0,0 +1,5 @@ + '../../slevomat/coding-standard', +); +?> \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist new file mode 100644 index 000000000..f95058faa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist @@ -0,0 +1,9 @@ + 'PSR2', + 'report_format' => 'summary', + 'show_warnings' => '0', + 'show_progress' => '1', + 'report_width' => '120', +); +?> diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/README.md b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/README.md new file mode 100644 index 000000000..9a500edd9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/README.md @@ -0,0 +1,153 @@ +# PHP_CodeSniffer + + + +> [!NOTE] +> This package is the official continuation of the now abandoned [PHP_CodeSniffer package which was created by Squizlabs](https://github.com/squizlabs/PHP_CodeSniffer). + +## About + +PHP_CodeSniffer is a set of two PHP scripts; the main `phpcs` script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second `phpcbf` script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent. + + +## Requirements + +PHP_CodeSniffer requires PHP version 5.4.0 or greater, although individual sniffs may have additional requirements such as external applications and scripts. See the [Configuration Options manual page](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/Configuration-Options) for a list of these requirements. + +If you're using PHP_CodeSniffer as part of a team, or you're running it on a [CI](https://en.wikipedia.org/wiki/Continuous_integration) server, you may want to configure your project's settings [using a configuration file](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/Advanced-Usage#using-a-default-configuration-file). + + +## Installation + +The easiest way to get started with PHP_CodeSniffer is to download the Phar files for each of the commands: +```bash +# Download using curl +curl -OL https://phars.phpcodesniffer.com/phpcs.phar +curl -OL https://phars.phpcodesniffer.com/phpcbf.phar + +# Or download using wget +wget https://phars.phpcodesniffer.com/phpcs.phar +wget https://phars.phpcodesniffer.com/phpcbf.phar + +# Then test the downloaded PHARs +php phpcs.phar -h +php phpcbf.phar -h +``` + +These Phars are signed with the official Release key for PHPCS with the +fingerprint `689D AD77 8FF0 8760 E046 228B A978 2203 05CD 5C32`. + +As of PHP_CodeSniffer 3.10.3, the provenance of PHAR files associated with a release can be verified via [GitHub Artifact Attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) using the [GitHub CLI tool](https://cli.github.com/) with the following command: `gh attestation verify [phpcs|phpcbf].phar -o PHPCSStandards`. + +### Composer +If you use Composer, you can install PHP_CodeSniffer system-wide with the following command: +```bash +composer global require "squizlabs/php_codesniffer=*" +``` +Make sure you have the composer bin dir in your PATH. The default value is `~/.composer/vendor/bin/`, but you can check the value that you need to use by running `composer global config bin-dir --absolute`. + +Or alternatively, include a dependency for `squizlabs/php_codesniffer` in your `composer.json` file. For example: + +```json +{ + "require-dev": { + "squizlabs/php_codesniffer": "^3.0" + } +} +``` + +You will then be able to run PHP_CodeSniffer from the vendor bin directory: +```bash +./vendor/bin/phpcs -h +./vendor/bin/phpcbf -h +``` + +### Phive +If you use Phive, you can install PHP_CodeSniffer as a project tool using the following commands: +```bash +phive install --trust-gpg-keys 689DAD778FF08760E046228BA978220305CD5C32 phpcs +phive install --trust-gpg-keys 689DAD778FF08760E046228BA978220305CD5C32 phpcbf +``` +You will then be able to run PHP_CodeSniffer from the `tools` directory: +```bash +./tools/phpcs -h +./tools/phpcbf -h +``` + +### Git Clone +You can also download the PHP_CodeSniffer source and run the `phpcs` and `phpcbf` commands directly from the Git clone: +```bash +git clone https://github.com/PHPCSStandards/PHP_CodeSniffer.git +cd PHP_CodeSniffer +php bin/phpcs -h +php bin/phpcbf -h +``` + +## Getting Started + +The default coding standard used by PHP_CodeSniffer is the PEAR coding standard. To check a file against the PEAR coding standard, simply specify the file's location: +```bash +phpcs /path/to/code/myfile.php +``` +Or if you wish to check an entire directory you can specify the directory location instead of a file. +```bash +phpcs /path/to/code-directory +``` +If you wish to check your code against the PSR-12 coding standard, use the `--standard` command line argument: +```bash +phpcs --standard=PSR12 /path/to/code-directory +``` + +If PHP_CodeSniffer finds any coding standard errors, a report will be shown after running the command. + +Full usage information and example reports are available on the [usage page](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/Usage). + +## Documentation + +The documentation for PHP_CodeSniffer is available on the [GitHub wiki](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki). + +## Issues + +Bug reports and feature requests can be submitted on the [GitHub Issue Tracker](https://github.com/PHPCSStandards/PHP_CodeSniffer/issues). + +## Contributing + +See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for information. + +## Versioning + +PHP_CodeSniffer uses a `MAJOR.MINOR.PATCH` version number format. + +The `MAJOR` version is incremented when: +- backwards-incompatible changes are made to how the `phpcs` or `phpcbf` commands are used, or +- backwards-incompatible changes are made to the `ruleset.xml` format, or +- backwards-incompatible changes are made to the API used by sniff developers, or +- custom PHP_CodeSniffer token types are removed, or +- existing sniffs are removed from PHP_CodeSniffer entirely + +The `MINOR` version is incremented when: +- new backwards-compatible features are added to the `phpcs` and `phpcbf` commands, or +- backwards-compatible changes are made to the `ruleset.xml` format, or +- backwards-compatible changes are made to the API used by sniff developers, or +- new sniffs are added to an included standard, or +- existing sniffs are removed from an included standard + +> NOTE: Backwards-compatible changes to the API used by sniff developers will allow an existing sniff to continue running without producing fatal errors but may not result in the sniff reporting the same errors as it did previously without changes being required. + +The `PATCH` version is incremented when: +- backwards-compatible bug fixes are made + +> NOTE: As PHP_CodeSniffer exists to report and fix issues, most bugs are the result of coding standard errors being incorrectly reported or coding standard errors not being reported when they should be. This means that the messages produced by PHP_CodeSniffer, and the fixes it makes, are likely to be different between PATCH versions. diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/autoload.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/autoload.php new file mode 100644 index 000000000..6221401e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/autoload.php @@ -0,0 +1,345 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use Composer\Autoload\ClassLoader; +use Exception; + +if (class_exists('PHP_CodeSniffer\Autoload', false) === false) { + class Autoload + { + + /** + * The composer autoloader. + * + * @var \Composer\Autoload\ClassLoader + */ + private static $composerAutoloader = null; + + /** + * A mapping of file names to class names. + * + * @var array + */ + private static $loadedClasses = []; + + /** + * A mapping of class names to file names. + * + * @var array + */ + private static $loadedFiles = []; + + /** + * A list of additional directories to search during autoloading. + * + * This is typically a list of coding standard directories. + * + * @var string[] + */ + private static $searchPaths = []; + + + /** + * Loads a class. + * + * This method only loads classes that exist in the PHP_CodeSniffer namespace. + * All other classes are ignored and loaded by subsequent autoloaders. + * + * @param string $class The name of the class to load. + * + * @return bool + */ + public static function load($class) + { + // Include the composer autoloader if there is one, but re-register it + // so this autoloader runs before the composer one as we need to include + // all files so we can figure out what the class/interface/trait name is. + if (self::$composerAutoloader === null) { + // Make sure we don't try to load any of Composer's classes + // while the autoloader is being setup. + if (strpos($class, 'Composer\\') === 0) { + return false; + } + + if (strpos(__DIR__, 'phar://') !== 0 + && @file_exists(__DIR__.'/../../autoload.php') === true + ) { + self::$composerAutoloader = include __DIR__.'/../../autoload.php'; + if (self::$composerAutoloader instanceof ClassLoader) { + self::$composerAutoloader->unregister(); + self::$composerAutoloader->register(); + } else { + // Something went wrong, so keep going without the autoloader + // although namespaced sniffs might error. + self::$composerAutoloader = false; + } + } else { + self::$composerAutoloader = false; + } + }//end if + + $ds = DIRECTORY_SEPARATOR; + $path = false; + + if (substr($class, 0, 16) === 'PHP_CodeSniffer\\') { + if (substr($class, 0, 22) === 'PHP_CodeSniffer\Tests\\') { + $isInstalled = !is_dir(__DIR__.$ds.'tests'); + if ($isInstalled === false) { + $path = __DIR__.$ds.'tests'; + } else { + $path = '@test_dir@'.$ds.'PHP_CodeSniffer'.$ds.'CodeSniffer'; + } + + $path .= $ds.substr(str_replace('\\', $ds, $class), 22).'.php'; + } else { + $path = __DIR__.$ds.'src'.$ds.substr(str_replace('\\', $ds, $class), 16).'.php'; + } + } + + // See if the composer autoloader knows where the class is. + if ($path === false && self::$composerAutoloader !== false) { + $path = self::$composerAutoloader->findFile($class); + } + + // See if the class is inside one of our alternate search paths. + if ($path === false) { + foreach (self::$searchPaths as $searchPath => $nsPrefix) { + $className = $class; + if ($nsPrefix !== '' && substr($class, 0, strlen($nsPrefix)) === $nsPrefix) { + $className = substr($class, (strlen($nsPrefix) + 1)); + } + + $path = $searchPath.$ds.str_replace('\\', $ds, $className).'.php'; + if (is_file($path) === true) { + break; + } + + $path = false; + } + } + + if ($path !== false && is_file($path) === true) { + self::loadFile($path); + return true; + } + + return false; + + }//end load() + + + /** + * Includes a file and tracks what class or interface was loaded as a result. + * + * @param string $path The path of the file to load. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function loadFile($path) + { + if (strpos(__DIR__, 'phar://') !== 0) { + $path = realpath($path); + if ($path === false) { + return false; + } + } + + if (isset(self::$loadedClasses[$path]) === true) { + return self::$loadedClasses[$path]; + } + + $classesBeforeLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + include $path; + + $classesAfterLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + $className = self::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + + self::$loadedClasses[$path] = $className; + self::$loadedFiles[$className] = $path; + return self::$loadedClasses[$path]; + + }//end loadFile() + + + /** + * Determine which class was loaded based on the before and after lists of loaded classes. + * + * @param array $classesBeforeLoad The classes/interfaces/traits before the file was included. + * @param array $classesAfterLoad The classes/interfaces/traits after the file was included. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function determineLoadedClass($classesBeforeLoad, $classesAfterLoad) + { + $className = null; + + $newClasses = array_diff($classesAfterLoad['classes'], $classesBeforeLoad['classes']); + if (PHP_VERSION_ID < 70400) { + $newClasses = array_reverse($newClasses); + } + + // Since PHP 7.4 get_declared_classes() does not guarantee any order, making + // it impossible to use order to determine which is the parent and which is the child. + // Let's reduce the list of candidates by removing all the classes known to be "parents". + // That way, at the end, only the "main" class just included will remain. + $newClasses = array_reduce( + $newClasses, + function ($remaining, $current) { + return array_diff($remaining, class_parents($current)); + }, + $newClasses + ); + + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + + if ($className === null) { + $newClasses = array_reverse(array_diff($classesAfterLoad['interfaces'], $classesBeforeLoad['interfaces'])); + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + } + + if ($className === null) { + $newClasses = array_reverse(array_diff($classesAfterLoad['traits'], $classesBeforeLoad['traits'])); + foreach ($newClasses as $name) { + if (isset(self::$loadedFiles[$name]) === false) { + $className = $name; + break; + } + } + } + + return $className; + + }//end determineLoadedClass() + + + /** + * Adds a directory to search during autoloading. + * + * @param string $path The path to the directory to search. + * @param string $nsPrefix The namespace prefix used by files under this path. + * + * @return void + */ + public static function addSearchPath($path, $nsPrefix='') + { + self::$searchPaths[$path] = rtrim(trim((string) $nsPrefix), '\\'); + + }//end addSearchPath() + + + /** + * Retrieve the namespaces and paths registered by external standards. + * + * @return array + */ + public static function getSearchPaths() + { + return self::$searchPaths; + + }//end getSearchPaths() + + + /** + * Gets the class name for the given file path. + * + * @param string $path The name of the file. + * + * @throws \Exception If the file path has not been loaded. + * @return string + */ + public static function getLoadedClassName($path) + { + if (isset(self::$loadedClasses[$path]) === false) { + throw new Exception("Cannot get class name for $path; file has not been included"); + } + + return self::$loadedClasses[$path]; + + }//end getLoadedClassName() + + + /** + * Gets the file path for the given class name. + * + * @param string $class The name of the class. + * + * @throws \Exception If the class name has not been loaded. + * @return string + */ + public static function getLoadedFileName($class) + { + if (isset(self::$loadedFiles[$class]) === false) { + throw new Exception("Cannot get file name for $class; class has not been included"); + } + + return self::$loadedFiles[$class]; + + }//end getLoadedFileName() + + + /** + * Gets the mapping of file names to class names. + * + * @return array + */ + public static function getLoadedClasses() + { + return self::$loadedClasses; + + }//end getLoadedClasses() + + + /** + * Gets the mapping of class names to file names. + * + * @return array + */ + public static function getLoadedFiles() + { + return self::$loadedFiles; + + }//end getLoadedFiles() + + + }//end class + + // Register the autoloader before any existing autoloaders to ensure + // it gets a chance to hear about every autoload request, and record + // the file and class name for it. + spl_autoload_register(__NAMESPACE__.'\Autoload::load', true, true); +}//end if diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf new file mode 100644 index 000000000..c804bdf10 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf @@ -0,0 +1,15 @@ +#!/usr/bin/env php + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +require_once __DIR__.'/../autoload.php'; + +$runner = new PHP_CodeSniffer\Runner(); +$exitCode = $runner->runPHPCBF(); +exit($exitCode); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat new file mode 100644 index 000000000..da3b0401a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcbf.bat @@ -0,0 +1,10 @@ +@echo off +REM PHP Code Beautifier and Fixer fixes violations of a defined coding standard. +REM +REM @author Greg Sherwood +REM @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) +REM @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + +set PHPBIN=php + +"%PHPBIN%" "%~dp0\phpcbf" %* diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs new file mode 100644 index 000000000..d098bf878 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs @@ -0,0 +1,15 @@ +#!/usr/bin/env php + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +require_once __DIR__.'/../autoload.php'; + +$runner = new PHP_CodeSniffer\Runner(); +$exitCode = $runner->runPHPCS(); +exit($exitCode); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs.bat b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs.bat new file mode 100644 index 000000000..a95722b4e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/bin/phpcs.bat @@ -0,0 +1,10 @@ +@echo off +REM PHP_CodeSniffer detects violations of a defined coding standard. +REM +REM @author Greg Sherwood +REM @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) +REM @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + +set PHPBIN=php + +"%PHPBIN%" "%~dp0\phpcs" %* diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/composer.json b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/composer.json new file mode 100644 index 000000000..28cdb07b7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/composer.json @@ -0,0 +1,90 @@ +{ + "name": "squizlabs/php_codesniffer", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "license": "BSD-3-Clause", + "type": "library", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy" + }, + "require": { + "php": ">=5.4.0", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "config": { + "lock": false + }, + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "scripts": { + "cs": [ + "@php ./bin/phpcs" + ], + "cbf": [ + "@php ./bin/phpcbf" + ], + "test": [ + "Composer\\Config::disableProcessTimeout", + "@php ./vendor/phpunit/phpunit/phpunit tests/AllTests.php --no-coverage" + ], + "coverage": [ + "Composer\\Config::disableProcessTimeout", + "@php ./vendor/phpunit/phpunit/phpunit tests/AllTests.php -d max_execution_time=0" + ], + "coverage-local": [ + "Composer\\Config::disableProcessTimeout", + "@php ./vendor/phpunit/phpunit/phpunit tests/AllTests.php --coverage-html ./build/coverage-html -d max_execution_time=0" + ], + "build": [ + "Composer\\Config::disableProcessTimeout", + "@php -d phar.readonly=0 -f ./scripts/build-phar.php" + ], + "check-all": [ + "@cs", + "@test" + ] + }, + "scripts-descriptions": { + "cs": "Check for code style violations.", + "cbf": "Fix code style violations.", + "test": "Run the unit tests without code coverage.", + "coverage": "Run the unit tests with code coverage.", + "coverage-local": "Run the unit tests with code coverage and generate an HTML report in a 'build' directory.", + "build": "Create PHAR files for PHPCS and PHPCBF.", + "check-all": "Run all checks (phpcs, tests)." + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/licence.txt b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/licence.txt new file mode 100644 index 000000000..9f95b6771 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/licence.txt @@ -0,0 +1,24 @@ +Copyright (c) 2012, Squiz Pty Ltd (ABN 77 084 670 600) +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 the copyright holder nor the + names of its 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/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/phpcs.xsd b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/phpcs.xsd new file mode 100644 index 000000000..d93dd868c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/phpcs.xsd @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Config.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Config.php new file mode 100644 index 000000000..e954c140e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Config.php @@ -0,0 +1,1661 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use Exception; +use Phar; +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Help; +use PHP_CodeSniffer\Util\Standards; + +/** + * Stores the configuration used to run PHPCS and PHPCBF. + * + * @property string[] $files The files and directories to check. + * @property string[] $standards The standards being used for checking. + * @property int $verbosity How verbose the output should be. + * 0: no unnecessary output + * 1: basic output for files being checked + * 2: ruleset and file parsing output + * 3: sniff execution output + * @property bool $interactive Enable interactive checking mode. + * @property int $parallel Check files in parallel. + * @property bool $cache Enable the use of the file cache. + * @property string $cacheFile Path to the file where the cache data should be written + * @property bool $colors Display colours in output. + * @property bool $explain Explain the coding standards. + * @property bool $local Process local files in directories only (no recursion). + * @property bool $showSources Show sniff source codes in report output. + * @property bool $showProgress Show basic progress information while running. + * @property bool $quiet Quiet mode; disables progress and verbose output. + * @property bool $annotations Process phpcs: annotations. + * @property int $tabWidth How many spaces each tab is worth. + * @property string $encoding The encoding of the files being checked. + * @property string[] $sniffs The sniffs that should be used for checking. + * If empty, all sniffs in the supplied standards will be used. + * @property string[] $exclude The sniffs that should be excluded from checking. + * If empty, all sniffs in the supplied standards will be used. + * @property string[] $ignored Regular expressions used to ignore files and folders during checking. + * @property string $reportFile A file where the report output should be written. + * @property string $generator The documentation generator to use. + * @property string $filter The filter to use for the run. + * @property string[] $bootstrap One of more files to include before the run begins. + * @property int|string $reportWidth The maximum number of columns that reports should use for output. + * Set to "auto" for have this value changed to the width of the terminal. + * @property int $errorSeverity The minimum severity an error must have to be displayed. + * @property int $warningSeverity The minimum severity a warning must have to be displayed. + * @property bool $recordErrors Record the content of error messages as well as error counts. + * @property string $suffix A suffix to add to fixed files. + * @property string $basepath A file system location to strip from the paths of files shown in reports. + * @property bool $stdin Read content from STDIN instead of supplied files. + * @property string $stdinContent Content passed directly to PHPCS on STDIN. + * @property string $stdinPath The path to use for content passed on STDIN. + * @property bool $trackTime Whether or not to track sniff run time. + * + * @property array $extensions File extensions that should be checked, and what tokenizer to use. + * E.g., array('inc' => 'PHP'); + * @property array $reports The reports to use for printing output after the run. + * The format of the array is: + * array( + * 'reportName1' => 'outputFile', + * 'reportName2' => null, + * ); + * If the array value is NULL, the report will be written to the screen. + * + * @property string[] $unknown Any arguments gathered on the command line that are unknown to us. + * E.g., using `phpcs -c` will give array('c'); + */ +class Config +{ + + /** + * The current version. + * + * @var string + */ + const VERSION = '3.11.1'; + + /** + * Package stability; either stable, beta or alpha. + * + * @var string + */ + const STABILITY = 'stable'; + + /** + * Default report width when no report width is provided and 'auto' does not yield a valid width. + * + * @var int + */ + const DEFAULT_REPORT_WIDTH = 80; + + /** + * An array of settings that PHPCS and PHPCBF accept. + * + * This array is not meant to be accessed directly. Instead, use the settings + * as if they are class member vars so the __get() and __set() magic methods + * can be used to validate the values. For example, to set the verbosity level to + * level 2, use $this->verbosity = 2; instead of accessing this property directly. + * + * Each of these settings is described in the class comment property list. + * + * @var array + */ + private $settings = [ + 'files' => null, + 'standards' => null, + 'verbosity' => null, + 'interactive' => null, + 'parallel' => null, + 'cache' => null, + 'cacheFile' => null, + 'colors' => null, + 'explain' => null, + 'local' => null, + 'showSources' => null, + 'showProgress' => null, + 'quiet' => null, + 'annotations' => null, + 'tabWidth' => null, + 'encoding' => null, + 'extensions' => null, + 'sniffs' => null, + 'exclude' => null, + 'ignored' => null, + 'reportFile' => null, + 'generator' => null, + 'filter' => null, + 'bootstrap' => null, + 'reports' => null, + 'basepath' => null, + 'reportWidth' => null, + 'errorSeverity' => null, + 'warningSeverity' => null, + 'recordErrors' => null, + 'suffix' => null, + 'stdin' => null, + 'stdinContent' => null, + 'stdinPath' => null, + 'trackTime' => null, + 'unknown' => null, + ]; + + /** + * Whether or not to kill the process when an unknown command line arg is found. + * + * If FALSE, arguments that are not command line options or file/directory paths + * will be ignored and execution will continue. These values will be stored in + * $this->unknown. + * + * @var boolean + */ + public $dieOnUnknownArg; + + /** + * The current command line arguments we are processing. + * + * @var string[] + */ + private $cliArgs = []; + + /** + * Command line values that the user has supplied directly. + * + * @var array> + */ + private static $overriddenDefaults = []; + + /** + * Config file data that has been loaded for the run. + * + * @var array + */ + private static $configData = null; + + /** + * The full path to the config data file that has been loaded. + * + * @var string + */ + private static $configDataFile = null; + + /** + * Automatically discovered executable utility paths. + * + * @var array + */ + private static $executablePaths = []; + + + /** + * Get the value of an inaccessible property. + * + * @param string $name The name of the property. + * + * @return mixed + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid. + */ + public function __get($name) + { + if (array_key_exists($name, $this->settings) === false) { + throw new RuntimeException("ERROR: unable to get value of property \"$name\""); + } + + // Figure out what the terminal width needs to be for "auto". + if ($name === 'reportWidth' && $this->settings[$name] === 'auto') { + if (function_exists('shell_exec') === true) { + $dimensions = shell_exec('stty size 2>&1'); + if (is_string($dimensions) === true && preg_match('|\d+ (\d+)|', $dimensions, $matches) === 1) { + $this->settings[$name] = (int) $matches[1]; + } + } + + if ($this->settings[$name] === 'auto') { + // If shell_exec wasn't available or didn't yield a usable value, set to the default. + // This will prevent subsequent retrievals of the reportWidth from making another call to stty. + $this->settings[$name] = self::DEFAULT_REPORT_WIDTH; + } + } + + return $this->settings[$name]; + + }//end __get() + + + /** + * Set the value of an inaccessible property. + * + * @param string $name The name of the property. + * @param mixed $value The value of the property. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the setting name is invalid. + */ + public function __set($name, $value) + { + if (array_key_exists($name, $this->settings) === false) { + throw new RuntimeException("Can't __set() $name; setting doesn't exist"); + } + + switch ($name) { + case 'reportWidth' : + if (is_string($value) === true && $value === 'auto') { + // Nothing to do. Leave at 'auto'. + break; + } + + if (is_int($value) === true) { + $value = abs($value); + } else if (is_string($value) === true && preg_match('`^\d+$`', $value) === 1) { + $value = (int) $value; + } else { + $value = self::DEFAULT_REPORT_WIDTH; + } + break; + + case 'standards' : + $cleaned = []; + + // Check if the standard name is valid, or if the case is invalid. + $installedStandards = Standards::getInstalledStandards(); + foreach ($value as $standard) { + foreach ($installedStandards as $validStandard) { + if (strtolower($standard) === strtolower($validStandard)) { + $standard = $validStandard; + break; + } + } + + $cleaned[] = $standard; + } + + $value = $cleaned; + break; + + // Only track time when explicitly needed. + case 'verbosity': + if ($value > 2) { + $this->settings['trackTime'] = true; + } + break; + case 'reports': + $reports = array_change_key_case($value, CASE_LOWER); + if (array_key_exists('performance', $reports) === true) { + $this->settings['trackTime'] = true; + } + break; + + default : + // No validation required. + break; + }//end switch + + $this->settings[$name] = $value; + + }//end __set() + + + /** + * Check if the value of an inaccessible property is set. + * + * @param string $name The name of the property. + * + * @return bool + */ + public function __isset($name) + { + return isset($this->settings[$name]); + + }//end __isset() + + + /** + * Unset the value of an inaccessible property. + * + * @param string $name The name of the property. + * + * @return void + */ + public function __unset($name) + { + $this->settings[$name] = null; + + }//end __unset() + + + /** + * Get the array of all config settings. + * + * @return array + */ + public function getSettings() + { + return $this->settings; + + }//end getSettings() + + + /** + * Set the array of all config settings. + * + * @param array $settings The array of config settings. + * + * @return void + */ + public function setSettings($settings) + { + return $this->settings = $settings; + + }//end setSettings() + + + /** + * Creates a Config object and populates it with command line values. + * + * @param array $cliArgs An array of values gathered from CLI args. + * @param bool $dieOnUnknownArg Whether or not to kill the process when an + * unknown command line arg is found. + * + * @return void + */ + public function __construct(array $cliArgs=[], $dieOnUnknownArg=true) + { + if (defined('PHP_CODESNIFFER_IN_TESTS') === true) { + // Let everything through during testing so that we can + // make use of PHPUnit command line arguments as well. + $this->dieOnUnknownArg = false; + } else { + $this->dieOnUnknownArg = $dieOnUnknownArg; + } + + if (empty($cliArgs) === true) { + $cliArgs = $_SERVER['argv']; + array_shift($cliArgs); + } + + $this->restoreDefaults(); + $this->setCommandLineValues($cliArgs); + + if (isset(self::$overriddenDefaults['standards']) === false) { + // They did not supply a standard to use. + // Look for a default ruleset in the current directory or higher. + $currentDir = getcwd(); + + $defaultFiles = [ + '.phpcs.xml', + 'phpcs.xml', + '.phpcs.xml.dist', + 'phpcs.xml.dist', + ]; + + do { + foreach ($defaultFiles as $defaultFilename) { + $default = $currentDir.DIRECTORY_SEPARATOR.$defaultFilename; + if (is_file($default) === true) { + $this->standards = [$default]; + break(2); + } + } + + $lastDir = $currentDir; + $currentDir = dirname($currentDir); + } while ($currentDir !== '.' && $currentDir !== $lastDir && Common::isReadable($currentDir) === true); + }//end if + + if (defined('STDIN') === false + || stripos(PHP_OS, 'WIN') === 0 + ) { + return; + } + + $handle = fopen('php://stdin', 'r'); + + // Check for content on STDIN. + if ($this->stdin === true + || (Common::isStdinATTY() === false + && feof($handle) === false) + ) { + $readStreams = [$handle]; + $writeSteams = null; + + $fileContents = ''; + while (is_resource($handle) === true && feof($handle) === false) { + // Set a timeout of 200ms. + if (stream_select($readStreams, $writeSteams, $writeSteams, 0, 200000) === 0) { + break; + } + + $fileContents .= fgets($handle); + } + + if (trim($fileContents) !== '') { + $this->stdin = true; + $this->stdinContent = $fileContents; + self::$overriddenDefaults['stdin'] = true; + self::$overriddenDefaults['stdinContent'] = true; + } + }//end if + + fclose($handle); + + }//end __construct() + + + /** + * Set the command line values. + * + * @param array $args An array of command line arguments to set. + * + * @return void + */ + public function setCommandLineValues($args) + { + $this->cliArgs = $args; + $numArgs = count($args); + + for ($i = 0; $i < $numArgs; $i++) { + $arg = $this->cliArgs[$i]; + if ($arg === '') { + continue; + } + + if ($arg[0] === '-') { + if ($arg === '-') { + // Asking to read from STDIN. + $this->stdin = true; + self::$overriddenDefaults['stdin'] = true; + continue; + } + + if ($arg === '--') { + // Empty argument, ignore it. + continue; + } + + if ($arg[1] === '-') { + $this->processLongArgument(substr($arg, 2), $i); + } else { + $switches = str_split($arg); + foreach ($switches as $switch) { + if ($switch === '-') { + continue; + } + + $this->processShortArgument($switch, $i); + } + } + } else { + $this->processUnknownArgument($arg, $i); + }//end if + }//end for + + }//end setCommandLineValues() + + + /** + * Restore default values for all possible command line arguments. + * + * @return void + */ + public function restoreDefaults() + { + $this->files = []; + $this->standards = ['PEAR']; + $this->verbosity = 0; + $this->interactive = false; + $this->cache = false; + $this->cacheFile = null; + $this->colors = false; + $this->explain = false; + $this->local = false; + $this->showSources = false; + $this->showProgress = false; + $this->quiet = false; + $this->annotations = true; + $this->parallel = 1; + $this->tabWidth = 0; + $this->encoding = 'utf-8'; + $this->extensions = [ + 'php' => 'PHP', + 'inc' => 'PHP', + 'js' => 'JS', + 'css' => 'CSS', + ]; + $this->sniffs = []; + $this->exclude = []; + $this->ignored = []; + $this->reportFile = null; + $this->generator = null; + $this->filter = null; + $this->bootstrap = []; + $this->basepath = null; + $this->reports = ['full' => null]; + $this->reportWidth = 'auto'; + $this->errorSeverity = 5; + $this->warningSeverity = 5; + $this->recordErrors = true; + $this->suffix = ''; + $this->stdin = false; + $this->stdinContent = null; + $this->stdinPath = null; + $this->trackTime = false; + $this->unknown = []; + + $standard = self::getConfigData('default_standard'); + if ($standard !== null) { + $this->standards = explode(',', $standard); + } + + $reportFormat = self::getConfigData('report_format'); + if ($reportFormat !== null) { + $this->reports = [$reportFormat => null]; + } + + $tabWidth = self::getConfigData('tab_width'); + if ($tabWidth !== null) { + $this->tabWidth = (int) $tabWidth; + } + + $encoding = self::getConfigData('encoding'); + if ($encoding !== null) { + $this->encoding = strtolower($encoding); + } + + $severity = self::getConfigData('severity'); + if ($severity !== null) { + $this->errorSeverity = (int) $severity; + $this->warningSeverity = (int) $severity; + } + + $severity = self::getConfigData('error_severity'); + if ($severity !== null) { + $this->errorSeverity = (int) $severity; + } + + $severity = self::getConfigData('warning_severity'); + if ($severity !== null) { + $this->warningSeverity = (int) $severity; + } + + $showWarnings = self::getConfigData('show_warnings'); + if ($showWarnings !== null) { + $showWarnings = (bool) $showWarnings; + if ($showWarnings === false) { + $this->warningSeverity = 0; + } + } + + $reportWidth = self::getConfigData('report_width'); + if ($reportWidth !== null) { + $this->reportWidth = $reportWidth; + } + + $showProgress = self::getConfigData('show_progress'); + if ($showProgress !== null) { + $this->showProgress = (bool) $showProgress; + } + + $quiet = self::getConfigData('quiet'); + if ($quiet !== null) { + $this->quiet = (bool) $quiet; + } + + $colors = self::getConfigData('colors'); + if ($colors !== null) { + $this->colors = (bool) $colors; + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + $cache = self::getConfigData('cache'); + if ($cache !== null) { + $this->cache = (bool) $cache; + } + + $parallel = self::getConfigData('parallel'); + if ($parallel !== null) { + $this->parallel = max((int) $parallel, 1); + } + } + + }//end restoreDefaults() + + + /** + * Processes a short (-e) command line argument. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processShortArgument($arg, $pos) + { + switch ($arg) { + case 'h': + case '?': + ob_start(); + $this->printUsage(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'i' : + ob_start(); + Standards::printInstalledStandards(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'v' : + if ($this->quiet === true) { + // Ignore when quiet mode is enabled. + break; + } + + $this->verbosity++; + self::$overriddenDefaults['verbosity'] = true; + break; + case 'l' : + $this->local = true; + self::$overriddenDefaults['local'] = true; + break; + case 's' : + $this->showSources = true; + self::$overriddenDefaults['showSources'] = true; + break; + case 'a' : + $this->interactive = true; + self::$overriddenDefaults['interactive'] = true; + break; + case 'e': + $this->explain = true; + self::$overriddenDefaults['explain'] = true; + break; + case 'p' : + if ($this->quiet === true) { + // Ignore when quiet mode is enabled. + break; + } + + $this->showProgress = true; + self::$overriddenDefaults['showProgress'] = true; + break; + case 'q' : + // Quiet mode disables a few other settings as well. + $this->quiet = true; + $this->showProgress = false; + $this->verbosity = 0; + + self::$overriddenDefaults['quiet'] = true; + break; + case 'm' : + $this->recordErrors = false; + self::$overriddenDefaults['recordErrors'] = true; + break; + case 'd' : + $ini = explode('=', $this->cliArgs[($pos + 1)]); + $this->cliArgs[($pos + 1)] = ''; + if (isset($ini[1]) === true) { + ini_set($ini[0], $ini[1]); + } else { + ini_set($ini[0], true); + } + break; + case 'n' : + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + $this->warningSeverity = 0; + self::$overriddenDefaults['warningSeverity'] = true; + } + break; + case 'w' : + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + $this->warningSeverity = $this->errorSeverity; + self::$overriddenDefaults['warningSeverity'] = true; + } + break; + default: + if ($this->dieOnUnknownArg === false) { + $unknown = $this->unknown; + $unknown[] = $arg; + $this->unknown = $unknown; + } else { + $this->processUnknownArgument('-'.$arg, $pos); + } + }//end switch + + }//end processShortArgument() + + + /** + * Processes a long (--example) command-line argument. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processLongArgument($arg, $pos) + { + switch ($arg) { + case 'help': + ob_start(); + $this->printUsage(); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'version': + $output = 'PHP_CodeSniffer version '.self::VERSION.' ('.self::STABILITY.') '; + $output .= 'by Squiz and PHPCSStandards'.PHP_EOL; + throw new DeepExitException($output, 0); + case 'colors': + if (isset(self::$overriddenDefaults['colors']) === true) { + break; + } + + $this->colors = true; + self::$overriddenDefaults['colors'] = true; + break; + case 'no-colors': + if (isset(self::$overriddenDefaults['colors']) === true) { + break; + } + + $this->colors = false; + self::$overriddenDefaults['colors'] = true; + break; + case 'cache': + if (isset(self::$overriddenDefaults['cache']) === true) { + break; + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + $this->cache = true; + self::$overriddenDefaults['cache'] = true; + } + break; + case 'no-cache': + if (isset(self::$overriddenDefaults['cache']) === true) { + break; + } + + $this->cache = false; + self::$overriddenDefaults['cache'] = true; + break; + case 'ignore-annotations': + if (isset(self::$overriddenDefaults['annotations']) === true) { + break; + } + + $this->annotations = false; + self::$overriddenDefaults['annotations'] = true; + break; + case 'config-set': + if (isset($this->cliArgs[($pos + 1)]) === false + || isset($this->cliArgs[($pos + 2)]) === false + ) { + $error = 'ERROR: Setting a config option requires a name and value'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $key = $this->cliArgs[($pos + 1)]; + $value = $this->cliArgs[($pos + 2)]; + $current = self::getConfigData($key); + + try { + $this->setConfigData($key, $value); + } catch (Exception $e) { + throw new DeepExitException($e->getMessage().PHP_EOL, 3); + } + + $output = 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + + if ($current === null) { + $output .= "Config value \"$key\" added successfully".PHP_EOL; + } else { + $output .= "Config value \"$key\" updated successfully; old value was \"$current\"".PHP_EOL; + } + throw new DeepExitException($output, 0); + case 'config-delete': + if (isset($this->cliArgs[($pos + 1)]) === false) { + $error = 'ERROR: Deleting a config option requires the name of the option'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $output = 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + + $key = $this->cliArgs[($pos + 1)]; + $current = self::getConfigData($key); + if ($current === null) { + $output .= "Config value \"$key\" has not been set".PHP_EOL; + } else { + try { + $this->setConfigData($key, null); + } catch (Exception $e) { + throw new DeepExitException($e->getMessage().PHP_EOL, 3); + } + + $output .= "Config value \"$key\" removed successfully; old value was \"$current\"".PHP_EOL; + } + throw new DeepExitException($output, 0); + case 'config-show': + ob_start(); + $data = self::getAllConfigData(); + echo 'Using config file: '.self::$configDataFile.PHP_EOL.PHP_EOL; + $this->printConfigData($data); + $output = ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($output, 0); + case 'runtime-set': + if (isset($this->cliArgs[($pos + 1)]) === false + || isset($this->cliArgs[($pos + 2)]) === false + ) { + $error = 'ERROR: Setting a runtime config option requires a name and value'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $key = $this->cliArgs[($pos + 1)]; + $value = $this->cliArgs[($pos + 2)]; + $this->cliArgs[($pos + 1)] = ''; + $this->cliArgs[($pos + 2)] = ''; + self::setConfigData($key, $value, true); + if (isset(self::$overriddenDefaults['runtime-set']) === false) { + self::$overriddenDefaults['runtime-set'] = []; + } + + self::$overriddenDefaults['runtime-set'][$key] = true; + break; + default: + if (substr($arg, 0, 7) === 'sniffs=') { + if (isset(self::$overriddenDefaults['sniffs']) === true) { + break; + } + + $sniffs = explode(',', substr($arg, 7)); + foreach ($sniffs as $sniff) { + if (substr_count($sniff, '.') !== 2) { + $error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } + + $this->sniffs = $sniffs; + self::$overriddenDefaults['sniffs'] = true; + } else if (substr($arg, 0, 8) === 'exclude=') { + if (isset(self::$overriddenDefaults['exclude']) === true) { + break; + } + + $sniffs = explode(',', substr($arg, 8)); + foreach ($sniffs as $sniff) { + if (substr_count($sniff, '.') !== 2) { + $error = 'ERROR: The specified sniff code "'.$sniff.'" is invalid'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } + + $this->exclude = $sniffs; + self::$overriddenDefaults['exclude'] = true; + } else if (defined('PHP_CODESNIFFER_IN_TESTS') === false + && substr($arg, 0, 6) === 'cache=' + ) { + if ((isset(self::$overriddenDefaults['cache']) === true + && $this->cache === false) + || isset(self::$overriddenDefaults['cacheFile']) === true + ) { + break; + } + + // Turn caching on. + $this->cache = true; + self::$overriddenDefaults['cache'] = true; + + $this->cacheFile = Common::realpath(substr($arg, 6)); + + // It may not exist and return false instead. + if ($this->cacheFile === false) { + $this->cacheFile = substr($arg, 6); + + $dir = dirname($this->cacheFile); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified cache file path "'.$this->cacheFile.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + if ($dir === '.') { + // Passed cache file is a file in the current directory. + $this->cacheFile = getcwd().'/'.basename($this->cacheFile); + } else { + if ($dir[0] === '/') { + // An absolute path. + $dir = Common::realpath($dir); + } else { + $dir = Common::realpath(getcwd().'/'.$dir); + } + + if ($dir !== false) { + // Cache file path is relative. + $this->cacheFile = $dir.'/'.basename($this->cacheFile); + } + } + }//end if + + self::$overriddenDefaults['cacheFile'] = true; + + if (is_dir($this->cacheFile) === true) { + $error = 'ERROR: The specified cache file path "'.$this->cacheFile.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if (substr($arg, 0, 10) === 'bootstrap=') { + $files = explode(',', substr($arg, 10)); + $bootstrap = []; + foreach ($files as $file) { + $path = Common::realpath($file); + if ($path === false) { + $error = 'ERROR: The specified bootstrap file "'.$file.'" does not exist'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $bootstrap[] = $path; + } + + $this->bootstrap = array_merge($this->bootstrap, $bootstrap); + self::$overriddenDefaults['bootstrap'] = true; + } else if (substr($arg, 0, 10) === 'file-list=') { + $fileList = substr($arg, 10); + $path = Common::realpath($fileList); + if ($path === false) { + $error = 'ERROR: The specified file list "'.$fileList.'" does not exist'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $files = file($path); + foreach ($files as $inputFile) { + $inputFile = trim($inputFile); + + // Skip empty lines. + if ($inputFile === '') { + continue; + } + + $this->processFilePath($inputFile); + } + } else if (substr($arg, 0, 11) === 'stdin-path=') { + if (isset(self::$overriddenDefaults['stdinPath']) === true) { + break; + } + + $this->stdinPath = Common::realpath(substr($arg, 11)); + + // It may not exist and return false instead, so use whatever they gave us. + if ($this->stdinPath === false) { + $this->stdinPath = trim(substr($arg, 11)); + } + + self::$overriddenDefaults['stdinPath'] = true; + } else if (PHP_CODESNIFFER_CBF === false && substr($arg, 0, 12) === 'report-file=') { + if (isset(self::$overriddenDefaults['reportFile']) === true) { + break; + } + + $this->reportFile = Common::realpath(substr($arg, 12)); + + // It may not exist and return false instead. + if ($this->reportFile === false) { + $this->reportFile = substr($arg, 12); + + $dir = Common::realpath(dirname($this->reportFile)); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified report file path "'.$this->reportFile.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $this->reportFile = $dir.'/'.basename($this->reportFile); + }//end if + + self::$overriddenDefaults['reportFile'] = true; + + if (is_dir($this->reportFile) === true) { + $error = 'ERROR: The specified report file path "'.$this->reportFile.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if (substr($arg, 0, 13) === 'report-width=') { + if (isset(self::$overriddenDefaults['reportWidth']) === true) { + break; + } + + $this->reportWidth = substr($arg, 13); + self::$overriddenDefaults['reportWidth'] = true; + } else if (substr($arg, 0, 9) === 'basepath=') { + if (isset(self::$overriddenDefaults['basepath']) === true) { + break; + } + + self::$overriddenDefaults['basepath'] = true; + + if (substr($arg, 9) === '') { + $this->basepath = null; + break; + } + + $this->basepath = Common::realpath(substr($arg, 9)); + + // It may not exist and return false instead. + if ($this->basepath === false) { + $this->basepath = substr($arg, 9); + } + + if (is_dir($this->basepath) === false) { + $error = 'ERROR: The specified basepath "'.$this->basepath.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + } else if ((substr($arg, 0, 7) === 'report=' || substr($arg, 0, 7) === 'report-')) { + $reports = []; + + if ($arg[6] === '-') { + // This is a report with file output. + $split = strpos($arg, '='); + if ($split === false) { + $report = substr($arg, 7); + $output = null; + } else { + $report = substr($arg, 7, ($split - 7)); + $output = substr($arg, ($split + 1)); + if ($output === false) { + $output = null; + } else { + $dir = Common::realpath(dirname($output)); + if (is_dir($dir) === false) { + $error = 'ERROR: The specified '.$report.' report file path "'.$output.'" points to a non-existent directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $output = $dir.'/'.basename($output); + + if (is_dir($output) === true) { + $error = 'ERROR: The specified '.$report.' report file path "'.$output.'" is a directory'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + }//end if + }//end if + + $reports[$report] = $output; + } else { + // This is a single report. + if (isset(self::$overriddenDefaults['reports']) === true) { + break; + } + + $reportNames = explode(',', substr($arg, 7)); + foreach ($reportNames as $report) { + $reports[$report] = null; + } + }//end if + + // Remove the default value so the CLI value overrides it. + if (isset(self::$overriddenDefaults['reports']) === false) { + $this->reports = $reports; + } else { + $this->reports = array_merge($this->reports, $reports); + } + + self::$overriddenDefaults['reports'] = true; + } else if (substr($arg, 0, 7) === 'filter=') { + if (isset(self::$overriddenDefaults['filter']) === true) { + break; + } + + $this->filter = substr($arg, 7); + self::$overriddenDefaults['filter'] = true; + } else if (substr($arg, 0, 9) === 'standard=') { + $standards = trim(substr($arg, 9)); + if ($standards !== '') { + $this->standards = explode(',', $standards); + } + + self::$overriddenDefaults['standards'] = true; + } else if (substr($arg, 0, 11) === 'extensions=') { + if (isset(self::$overriddenDefaults['extensions']) === true) { + break; + } + + $extensions = explode(',', substr($arg, 11)); + $newExtensions = []; + foreach ($extensions as $ext) { + $slash = strpos($ext, '/'); + if ($slash !== false) { + // They specified the tokenizer too. + list($ext, $tokenizer) = explode('/', $ext); + $newExtensions[$ext] = strtoupper($tokenizer); + continue; + } + + if (isset($this->extensions[$ext]) === true) { + $newExtensions[$ext] = $this->extensions[$ext]; + } else { + $newExtensions[$ext] = 'PHP'; + } + } + + $this->extensions = $newExtensions; + self::$overriddenDefaults['extensions'] = true; + } else if (substr($arg, 0, 7) === 'suffix=') { + if (isset(self::$overriddenDefaults['suffix']) === true) { + break; + } + + $this->suffix = substr($arg, 7); + self::$overriddenDefaults['suffix'] = true; + } else if (substr($arg, 0, 9) === 'parallel=') { + if (isset(self::$overriddenDefaults['parallel']) === true) { + break; + } + + $this->parallel = max((int) substr($arg, 9), 1); + self::$overriddenDefaults['parallel'] = true; + } else if (substr($arg, 0, 9) === 'severity=') { + $this->errorSeverity = (int) substr($arg, 9); + $this->warningSeverity = $this->errorSeverity; + if (isset(self::$overriddenDefaults['errorSeverity']) === false) { + self::$overriddenDefaults['errorSeverity'] = true; + } + + if (isset(self::$overriddenDefaults['warningSeverity']) === false) { + self::$overriddenDefaults['warningSeverity'] = true; + } + } else if (substr($arg, 0, 15) === 'error-severity=') { + if (isset(self::$overriddenDefaults['errorSeverity']) === true) { + break; + } + + $this->errorSeverity = (int) substr($arg, 15); + self::$overriddenDefaults['errorSeverity'] = true; + } else if (substr($arg, 0, 17) === 'warning-severity=') { + if (isset(self::$overriddenDefaults['warningSeverity']) === true) { + break; + } + + $this->warningSeverity = (int) substr($arg, 17); + self::$overriddenDefaults['warningSeverity'] = true; + } else if (substr($arg, 0, 7) === 'ignore=') { + if (isset(self::$overriddenDefaults['ignored']) === true) { + break; + } + + // Split the ignore string on commas, unless the comma is escaped + // using 1 or 3 slashes (\, or \\\,). + $patterns = preg_split( + '/(?<=(?ignored = $ignored; + self::$overriddenDefaults['ignored'] = true; + } else if (substr($arg, 0, 10) === 'generator=' + && PHP_CODESNIFFER_CBF === false + ) { + if (isset(self::$overriddenDefaults['generator']) === true) { + break; + } + + $this->generator = substr($arg, 10); + self::$overriddenDefaults['generator'] = true; + } else if (substr($arg, 0, 9) === 'encoding=') { + if (isset(self::$overriddenDefaults['encoding']) === true) { + break; + } + + $this->encoding = strtolower(substr($arg, 9)); + self::$overriddenDefaults['encoding'] = true; + } else if (substr($arg, 0, 10) === 'tab-width=') { + if (isset(self::$overriddenDefaults['tabWidth']) === true) { + break; + } + + $this->tabWidth = (int) substr($arg, 10); + self::$overriddenDefaults['tabWidth'] = true; + } else { + if ($this->dieOnUnknownArg === false) { + $eqPos = strpos($arg, '='); + try { + $unknown = $this->unknown; + + if ($eqPos === false) { + $unknown[$arg] = $arg; + } else { + $value = substr($arg, ($eqPos + 1)); + $arg = substr($arg, 0, $eqPos); + $unknown[$arg] = $value; + } + + $this->unknown = $unknown; + } catch (RuntimeException $e) { + // Value is not valid, so just ignore it. + } + } else { + $this->processUnknownArgument('--'.$arg, $pos); + } + }//end if + break; + }//end switch + + }//end processLongArgument() + + + /** + * Processes an unknown command line argument. + * + * Assumes all unknown arguments are files and folders to check. + * + * @param string $arg The command line argument. + * @param int $pos The position of the argument on the command line. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processUnknownArgument($arg, $pos) + { + // We don't know about any additional switches; just files. + if ($arg[0] === '-') { + if ($this->dieOnUnknownArg === false) { + return; + } + + $error = "ERROR: option \"$arg\" not known".PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + $this->processFilePath($arg); + + }//end processUnknownArgument() + + + /** + * Processes a file path and add it to the file list. + * + * @param string $path The path to the file to add. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processFilePath($path) + { + // If we are processing STDIN, don't record any files to check. + if ($this->stdin === true) { + return; + } + + $file = Common::realpath($path); + if (file_exists($file) === false) { + if ($this->dieOnUnknownArg === false) { + return; + } + + $error = 'ERROR: The file "'.$path.'" does not exist.'.PHP_EOL.PHP_EOL; + $error .= $this->printShortUsage(true); + throw new DeepExitException($error, 3); + } else { + // Can't modify the files array directly because it's not a real + // class member, so need to use this little get/modify/set trick. + $files = $this->files; + $files[] = $file; + $this->files = $files; + self::$overriddenDefaults['files'] = true; + } + + }//end processFilePath() + + + /** + * Prints out the usage information for this script. + * + * @return void + */ + public function printUsage() + { + echo PHP_EOL; + + if (PHP_CODESNIFFER_CBF === true) { + $this->printPHPCBFUsage(); + } else { + $this->printPHPCSUsage(); + } + + echo PHP_EOL; + + }//end printUsage() + + + /** + * Prints out the short usage information for this script. + * + * @param bool $return If TRUE, the usage string is returned + * instead of output to screen. + * + * @return string|void + */ + public function printShortUsage($return=false) + { + if (PHP_CODESNIFFER_CBF === true) { + $usage = 'Run "phpcbf --help" for usage information'; + } else { + $usage = 'Run "phpcs --help" for usage information'; + } + + $usage .= PHP_EOL.PHP_EOL; + + if ($return === true) { + return $usage; + } + + echo $usage; + + }//end printShortUsage() + + + /** + * Prints out the usage information for PHPCS. + * + * @return void + */ + public function printPHPCSUsage() + { + $longOptions = explode(',', Help::DEFAULT_LONG_OPTIONS); + $longOptions[] = 'cache'; + $longOptions[] = 'no-cache'; + $longOptions[] = 'report'; + $longOptions[] = 'report-file'; + $longOptions[] = 'report-report'; + $longOptions[] = 'config-explain'; + $longOptions[] = 'config-set'; + $longOptions[] = 'config-delete'; + $longOptions[] = 'config-show'; + $longOptions[] = 'generator'; + + $shortOptions = Help::DEFAULT_SHORT_OPTIONS.'aems'; + + (new Help($this, $longOptions, $shortOptions))->display(); + + }//end printPHPCSUsage() + + + /** + * Prints out the usage information for PHPCBF. + * + * @return void + */ + public function printPHPCBFUsage() + { + $longOptions = explode(',', Help::DEFAULT_LONG_OPTIONS); + $longOptions[] = 'suffix'; + $shortOptions = Help::DEFAULT_SHORT_OPTIONS; + + (new Help($this, $longOptions, $shortOptions))->display(); + + }//end printPHPCBFUsage() + + + /** + * Get a single config value. + * + * @param string $key The name of the config value. + * + * @return string|null + * @see setConfigData() + * @see getAllConfigData() + */ + public static function getConfigData($key) + { + $phpCodeSnifferConfig = self::getAllConfigData(); + + if ($phpCodeSnifferConfig === null) { + return null; + } + + if (isset($phpCodeSnifferConfig[$key]) === false) { + return null; + } + + return $phpCodeSnifferConfig[$key]; + + }//end getConfigData() + + + /** + * Get the path to an executable utility. + * + * @param string $name The name of the executable utility. + * + * @return string|null + * @see getConfigData() + */ + public static function getExecutablePath($name) + { + $data = self::getConfigData($name.'_path'); + if ($data !== null) { + return $data; + } + + if ($name === "php") { + // For php, we know the executable path. There's no need to look it up. + return PHP_BINARY; + } + + if (array_key_exists($name, self::$executablePaths) === true) { + return self::$executablePaths[$name]; + } + + if (stripos(PHP_OS, 'WIN') === 0) { + $cmd = 'where '.escapeshellarg($name).' 2> nul'; + } else { + $cmd = 'which '.escapeshellarg($name).' 2> /dev/null'; + } + + $result = exec($cmd, $output, $retVal); + if ($retVal !== 0) { + $result = null; + } + + self::$executablePaths[$name] = $result; + return $result; + + }//end getExecutablePath() + + + /** + * Set a single config value. + * + * @param string $key The name of the config value. + * @param string|null $value The value to set. If null, the config + * entry is deleted, reverting it to the + * default value. + * @param boolean $temp Set this config data temporarily for this + * script run. This will not write the config + * data to the config file. + * + * @return bool + * @see getConfigData() + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file can not be written. + */ + public static function setConfigData($key, $value, $temp=false) + { + if (isset(self::$overriddenDefaults['runtime-set']) === true + && isset(self::$overriddenDefaults['runtime-set'][$key]) === true + ) { + return false; + } + + if ($temp === false) { + $path = ''; + if (is_callable('\Phar::running') === true) { + $path = Phar::running(false); + } + + if ($path !== '') { + $configFile = dirname($path).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } else { + $configFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } + + if (is_file($configFile) === true + && is_writable($configFile) === false + ) { + $error = 'ERROR: Config file '.$configFile.' is not writable'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + }//end if + + $phpCodeSnifferConfig = self::getAllConfigData(); + + if ($value === null) { + if (isset($phpCodeSnifferConfig[$key]) === true) { + unset($phpCodeSnifferConfig[$key]); + } + } else { + $phpCodeSnifferConfig[$key] = $value; + } + + if ($temp === false) { + $output = '<'.'?php'."\n".' $phpCodeSnifferConfig = '; + $output .= var_export($phpCodeSnifferConfig, true); + $output .= ";\n?".'>'; + + if (file_put_contents($configFile, $output) === false) { + $error = 'ERROR: Config file '.$configFile.' could not be written'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + self::$configDataFile = $configFile; + } + + self::$configData = $phpCodeSnifferConfig; + + // If the installed paths are being set, make sure all known + // standards paths are added to the autoloader. + if ($key === 'installed_paths') { + $installedStandards = Standards::getInstalledStandardDetails(); + foreach ($installedStandards as $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + } + } + + return true; + + }//end setConfigData() + + + /** + * Get all config data. + * + * @return array + * @see getConfigData() + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the config file could not be read. + */ + public static function getAllConfigData() + { + if (self::$configData !== null) { + return self::$configData; + } + + $path = ''; + if (is_callable('\Phar::running') === true) { + $path = Phar::running(false); + } + + if ($path !== '') { + $configFile = dirname($path).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + } else { + $configFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'CodeSniffer.conf'; + if (is_file($configFile) === false + && strpos('@data_dir@', '@data_dir') === false + ) { + $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf'; + } + } + + if (is_file($configFile) === false) { + self::$configData = []; + return []; + } + + if (Common::isReadable($configFile) === false) { + $error = 'ERROR: Config file '.$configFile.' is not readable'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + include $configFile; + self::$configDataFile = $configFile; + self::$configData = $phpCodeSnifferConfig; + return self::$configData; + + }//end getAllConfigData() + + + /** + * Prints out the gathered config data. + * + * @param array $data The config data to print. + * + * @return void + */ + public function printConfigData($data) + { + $max = 0; + $keys = array_keys($data); + foreach ($keys as $key) { + $len = strlen($key); + if (strlen($key) > $max) { + $max = $len; + } + } + + if ($max === 0) { + return; + } + + $max += 2; + ksort($data); + foreach ($data as $name => $value) { + echo str_pad($name.': ', $max).$value.PHP_EOL; + } + + }//end printConfigData() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php new file mode 100644 index 000000000..6943e033e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/DeepExitException.php @@ -0,0 +1,20 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +use Exception; + +class DeepExitException extends Exception +{ + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php new file mode 100644 index 000000000..25eacd0b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/RuntimeException.php @@ -0,0 +1,17 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +use RuntimeException as PHPRuntimeException; + +class RuntimeException extends PHPRuntimeException +{ + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php new file mode 100644 index 000000000..1cf53d623 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Exceptions/TokenizerException.php @@ -0,0 +1,17 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Exceptions; + +use Exception; + +class TokenizerException extends Exception +{ + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php new file mode 100644 index 000000000..f5dc7cc7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/DummyFile.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; + +class DummyFile extends File +{ + + + /** + * Creates a DummyFile object and sets the content. + * + * @param string $content The content of the file. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($content, Ruleset $ruleset, Config $config) + { + $this->setContent($content); + + // See if a filename was defined in the content. + // This is done by including: phpcs_input_file: [file path] + // as the first line of content. + $path = 'STDIN'; + if ($content !== '') { + if (substr($content, 0, 17) === 'phpcs_input_file:') { + $eolPos = strpos($content, $this->eolChar); + $filename = trim(substr($content, 17, ($eolPos - 17))); + $content = substr($content, ($eolPos + strlen($this->eolChar))); + $path = $filename; + + $this->setContent($content); + } + } + + // The CLI arg overrides anything passed in the content. + if ($config->stdinPath !== null) { + $path = $config->stdinPath; + } + + parent::__construct($path, $ruleset, $config); + + }//end __construct() + + + /** + * Set the error, warning, and fixable counts for the file. + * + * @param int $errorCount The number of errors found. + * @param int $warningCount The number of warnings found. + * @param int $fixableCount The number of fixable errors found. + * @param int $fixedCount The number of errors that were fixed. + * + * @return void + */ + public function setErrorCounts($errorCount, $warningCount, $fixableCount, $fixedCount) + { + $this->errorCount = $errorCount; + $this->warningCount = $warningCount; + $this->fixableCount = $fixableCount; + $this->fixedCount = $fixedCount; + + }//end setErrorCounts() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/File.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/File.php new file mode 100644 index 000000000..29b15c0e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/File.php @@ -0,0 +1,2954 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Fixer; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class File +{ + + /** + * The absolute path to the file associated with this object. + * + * @var string + */ + public $path = ''; + + /** + * The content of the file. + * + * @var string + */ + protected $content = ''; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * If TRUE, the entire file is being ignored. + * + * @var boolean + */ + public $ignored = false; + + /** + * The EOL character this file uses. + * + * @var string + */ + public $eolChar = ''; + + /** + * The Fixer object to control fixing errors. + * + * @var \PHP_CodeSniffer\Fixer + */ + public $fixer = null; + + /** + * The tokenizer being used for this file. + * + * @var \PHP_CodeSniffer\Tokenizers\Tokenizer + */ + public $tokenizer = null; + + /** + * The name of the tokenizer being used for this file. + * + * @var string + */ + public $tokenizerType = 'PHP'; + + /** + * Was the file loaded from cache? + * + * If TRUE, the file was loaded from a local cache. + * If FALSE, the file was tokenized and processed fully. + * + * @var boolean + */ + public $fromCache = false; + + /** + * The number of tokens in this file. + * + * Stored here to save calling count() everywhere. + * + * @var integer + */ + public $numTokens = 0; + + /** + * The tokens stack map. + * + * @var array + */ + protected $tokens = []; + + /** + * The errors raised from sniffs. + * + * @var array + * @see getErrors() + */ + protected $errors = []; + + /** + * The warnings raised from sniffs. + * + * @var array + * @see getWarnings() + */ + protected $warnings = []; + + /** + * The metrics recorded by sniffs. + * + * @var array + * @see getMetrics() + */ + protected $metrics = []; + + /** + * The metrics recorded for each token. + * + * Stops the same metric being recorded for the same token twice. + * + * @var array + * @see getMetrics() + */ + private $metricTokens = []; + + /** + * The total number of errors raised. + * + * @var integer + */ + protected $errorCount = 0; + + /** + * The total number of warnings raised. + * + * @var integer + */ + protected $warningCount = 0; + + /** + * The total number of errors and warnings that can be fixed. + * + * @var integer + */ + protected $fixableCount = 0; + + /** + * The total number of errors and warnings that were fixed. + * + * @var integer + */ + protected $fixedCount = 0; + + /** + * TRUE if errors are being replayed from the cache. + * + * @var boolean + */ + protected $replayingErrors = false; + + /** + * An array of sniffs that are being ignored. + * + * @var array + */ + protected $ignoredListeners = []; + + /** + * An array of message codes that are being ignored. + * + * @var array + */ + protected $ignoredCodes = []; + + /** + * An array of sniffs listening to this file's processing. + * + * @var \PHP_CodeSniffer\Sniffs\Sniff[] + */ + protected $listeners = []; + + /** + * The class name of the sniff currently processing the file. + * + * @var string + */ + protected $activeListener = ''; + + /** + * An array of sniffs being processed and how long they took. + * + * @var array + * @see getListenerTimes() + */ + protected $listenerTimes = []; + + /** + * A cache of often used config settings to improve performance. + * + * Storing them here saves 10k+ calls to __get() in the Config class. + * + * @var array + */ + protected $configCache = []; + + + /** + * Constructs a file. + * + * @param string $path The absolute path to the file to process. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($path, Ruleset $ruleset, Config $config) + { + $this->path = $path; + $this->ruleset = $ruleset; + $this->config = $config; + $this->fixer = new Fixer(); + + $parts = explode('.', $path); + $extension = array_pop($parts); + if (isset($config->extensions[$extension]) === true) { + $this->tokenizerType = $config->extensions[$extension]; + } else { + // Revert to default. + $this->tokenizerType = 'PHP'; + } + + $this->configCache['cache'] = $this->config->cache; + $this->configCache['sniffs'] = array_map('strtolower', $this->config->sniffs); + $this->configCache['exclude'] = array_map('strtolower', $this->config->exclude); + $this->configCache['errorSeverity'] = $this->config->errorSeverity; + $this->configCache['warningSeverity'] = $this->config->warningSeverity; + $this->configCache['recordErrors'] = $this->config->recordErrors; + $this->configCache['trackTime'] = $this->config->trackTime; + $this->configCache['ignorePatterns'] = $this->ruleset->ignorePatterns; + $this->configCache['includePatterns'] = $this->ruleset->includePatterns; + + }//end __construct() + + + /** + * Set the content of the file. + * + * Setting the content also calculates the EOL char being used. + * + * @param string $content The file content. + * + * @return void + */ + public function setContent($content) + { + $this->content = $content; + $this->tokens = []; + + try { + $this->eolChar = Common::detectLineEndings($content); + } catch (RuntimeException $e) { + $this->addWarningOnLine($e->getMessage(), 1, 'Internal.DetectLineEndings'); + return; + } + + }//end setContent() + + + /** + * Reloads the content of the file. + * + * By default, we have no idea where our content comes from, + * so we can't do anything. + * + * @return void + */ + public function reloadContent() + { + + }//end reloadContent() + + + /** + * Disables caching of this file. + * + * @return void + */ + public function disableCaching() + { + $this->configCache['cache'] = false; + + }//end disableCaching() + + + /** + * Starts the stack traversal and tells listeners when tokens are found. + * + * @return void + */ + public function process() + { + if ($this->ignored === true) { + return; + } + + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + + $this->parse(); + + // Check if tokenizer errors cause this file to be ignored. + if ($this->ignored === true) { + return; + } + + $this->fixer->startFile($this); + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t*** START TOKEN PROCESSING ***".PHP_EOL; + } + + $foundCode = false; + $listenerIgnoreTo = []; + $inTests = defined('PHP_CODESNIFFER_IN_TESTS'); + $checkAnnotations = $this->config->annotations; + $annotationErrors = []; + + // Foreach of the listeners that have registered to listen for this + // token, get them to process it. + foreach ($this->tokens as $stackPtr => $token) { + // Check for ignored lines. + if ($checkAnnotations === true + && ($token['code'] === T_COMMENT + || $token['code'] === T_PHPCS_IGNORE_FILE + || $token['code'] === T_PHPCS_SET + || $token['code'] === T_DOC_COMMENT_STRING + || $token['code'] === T_DOC_COMMENT_TAG + || ($inTests === true && $token['code'] === T_INLINE_HTML)) + ) { + $commentText = ltrim($this->tokens[$stackPtr]['content'], " \t/*#"); + $commentTextLower = strtolower($commentText); + if (strpos($commentText, '@codingStandards') !== false) { + if (strpos($commentText, '@codingStandardsIgnoreFile') !== false) { + // Ignoring the whole file, just a little late. + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + return; + } else if (strpos($commentText, '@codingStandardsChangeSetting') !== false) { + $start = strpos($commentText, '@codingStandardsChangeSetting'); + $comment = substr($commentText, ($start + 30)); + $parts = explode(' ', $comment); + if (count($parts) >= 2) { + $sniffParts = explode('.', $parts[0]); + if (count($sniffParts) >= 3) { + // If the sniff code is not known to us, it has not been registered in this run. + // But don't throw an error as it could be there for a different standard to use. + if (isset($this->ruleset->sniffCodes[$parts[0]]) === true) { + $listenerCode = array_shift($parts); + $propertyCode = array_shift($parts); + $settings = [ + 'value' => rtrim(implode(' ', $parts), " */\r\n"), + 'scope' => 'sniff', + ]; + $listenerClass = $this->ruleset->sniffCodes[$listenerCode]; + $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $settings); + } + } + } + }//end if + } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile' + || substr($commentTextLower, 0, 17) === '@phpcs:ignorefile' + ) { + // Ignoring the whole file, just a little late. + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + return; + } else if (substr($commentTextLower, 0, 9) === 'phpcs:set' + || substr($commentTextLower, 0, 10) === '@phpcs:set' + ) { + if (isset($token['sniffCode']) === true) { + $listenerCode = $token['sniffCode']; + if (isset($this->ruleset->sniffCodes[$listenerCode]) === true) { + $propertyCode = $token['sniffProperty']; + $settings = [ + 'value' => $token['sniffPropertyValue'], + 'scope' => 'sniff', + ]; + $listenerClass = $this->ruleset->sniffCodes[$listenerCode]; + try { + $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $settings); + } catch (RuntimeException $e) { + // Non-existant property being set via an inline annotation. + // This is typically a PHPCS test case file, but we can't throw an error on the annotation + // line as it would get ignored. We also don't want this error to block + // the scan of the current file, so collect these and throw later. + $annotationErrors[] = 'Line '.$token['line'].': '.str_replace('Ruleset invalid. ', '', $e->getMessage()); + } + } + } + }//end if + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $type = $token['type']; + $content = Common::prepareForOutput($token['content']); + echo "\t\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + if ($token['code'] !== T_INLINE_HTML) { + $foundCode = true; + } + + if (isset($this->ruleset->tokenListeners[$token['code']]) === false) { + continue; + } + + foreach ($this->ruleset->tokenListeners[$token['code']] as $listenerData) { + if (isset($this->ignoredListeners[$listenerData['class']]) === true + || (isset($listenerIgnoreTo[$listenerData['class']]) === true + && $listenerIgnoreTo[$listenerData['class']] > $stackPtr) + ) { + // This sniff is ignoring past this token, or the whole file. + continue; + } + + // Make sure this sniff supports the tokenizer + // we are currently using. + $class = $listenerData['class']; + + if (isset($listenerData['tokenizers'][$this->tokenizerType]) === false) { + continue; + } + + if (trim($this->path, '\'"') !== 'STDIN') { + // If the file path matches one of our ignore patterns, skip it. + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + foreach ($listenerData['ignore'] as $pattern) { + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $pattern = str_replace('/', '\\\\', $pattern); + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $this->path) === 1) { + $this->ignoredListeners[$class] = true; + continue(2); + } + } + + // If the file path does not match one of our include patterns, skip it. + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + if (empty($listenerData['include']) === false) { + $included = false; + foreach ($listenerData['include'] as $pattern) { + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $pattern = str_replace('/', '\\\\', $pattern); + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $this->path) === 1) { + $included = true; + break; + } + } + + if ($included === false) { + $this->ignoredListeners[$class] = true; + continue; + } + }//end if + }//end if + + $this->activeListener = $class; + + if ($this->configCache['trackTime'] === true) { + $startTime = microtime(true); + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t\t\tProcessing ".$this->activeListener.'... '; + } + + $ignoreTo = $this->ruleset->sniffs[$class]->process($this, $stackPtr); + if ($ignoreTo !== null) { + $listenerIgnoreTo[$this->activeListener] = $ignoreTo; + } + + if ($this->configCache['trackTime'] === true) { + $timeTaken = (microtime(true) - $startTime); + if (isset($this->listenerTimes[$this->activeListener]) === false) { + $this->listenerTimes[$this->activeListener] = 0; + } + + $this->listenerTimes[$this->activeListener] += $timeTaken; + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + $timeTaken = round(($timeTaken), 4); + echo "DONE in $timeTaken seconds".PHP_EOL; + } + + $this->activeListener = ''; + }//end foreach + }//end foreach + + // If short open tags are off but the file being checked uses + // short open tags, the whole content will be inline HTML + // and nothing will be checked. So try and handle this case. + // We don't show this error for STDIN because we can't be sure the content + // actually came directly from the user. It could be something like + // refs from a Git pre-push hook. + if ($foundCode === false && $this->tokenizerType === 'PHP' && $this->path !== 'STDIN') { + $shortTags = (bool) ini_get('short_open_tag'); + if ($shortTags === false) { + $error = 'No PHP code was found in this file and short open tags are not allowed by this install of PHP. This file may be using short open tags but PHP does not allow them.'; + $this->addWarning($error, null, 'Internal.NoCodeFound'); + } + } + + if ($annotationErrors !== []) { + $error = 'Encountered invalid inline phpcs:set annotations. Found:'.PHP_EOL; + $error .= implode(PHP_EOL, $annotationErrors); + + $this->addWarning($error, null, 'Internal.PropertyDoesNotExist'); + } + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "\t*** END TOKEN PROCESSING ***".PHP_EOL; + echo "\t*** START SNIFF PROCESSING REPORT ***".PHP_EOL; + + arsort($this->listenerTimes, SORT_NUMERIC); + foreach ($this->listenerTimes as $listener => $timeTaken) { + echo "\t$listener: ".round(($timeTaken), 4).' secs'.PHP_EOL; + } + + echo "\t*** END SNIFF PROCESSING REPORT ***".PHP_EOL; + } + + $this->fixedCount += $this->fixer->getFixCount(); + + }//end process() + + + /** + * Tokenizes the file and prepares it for the test run. + * + * @return void + */ + public function parse() + { + if (empty($this->tokens) === false) { + // File has already been parsed. + return; + } + + try { + $tokenizerClass = 'PHP_CodeSniffer\Tokenizers\\'.$this->tokenizerType; + $this->tokenizer = new $tokenizerClass($this->content, $this->config, $this->eolChar); + $this->tokens = $this->tokenizer->getTokens(); + } catch (TokenizerException $e) { + $this->ignored = true; + $this->addWarning($e->getMessage(), null, 'Internal.Tokenizer.Exception'); + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo "[$this->tokenizerType => tokenizer error]... "; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + return; + } + + $this->numTokens = count($this->tokens); + + // Check for mixed line endings as these can cause tokenizer errors and we + // should let the user know that the results they get may be incorrect. + // This is done by removing all backslashes, removing the newline char we + // detected, then converting newlines chars into text. If any backslashes + // are left at the end, we have additional newline chars in use. + $contents = str_replace('\\', '', $this->content); + $contents = str_replace($this->eolChar, '', $contents); + $contents = str_replace("\n", '\n', $contents); + $contents = str_replace("\r", '\r', $contents); + if (strpos($contents, '\\') !== false) { + $error = 'File has mixed line endings; this may cause incorrect results'; + $this->addWarningOnLine($error, 1, 'Internal.LineEndings.Mixed'); + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($this->numTokens === 0) { + $numLines = 0; + } else { + $numLines = $this->tokens[($this->numTokens - 1)]['line']; + } + + echo "[$this->tokenizerType => $this->numTokens tokens in $numLines lines]... "; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + }//end parse() + + + /** + * Returns the token stack for this file. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + + }//end getTokens() + + + /** + * Remove vars stored in this file that are no longer required. + * + * @return void + */ + public function cleanUp() + { + $this->listenerTimes = null; + $this->content = null; + $this->tokens = null; + $this->metricTokens = null; + $this->tokenizer = null; + $this->fixer = null; + $this->config = null; + $this->ruleset = null; + + }//end cleanUp() + + + /** + * Records an error against a specific token in the file. + * + * @param string $error The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the error be fixed by the sniff? + * + * @return boolean + */ + public function addError( + $error, + $stackPtr, + $code, + $data=[], + $severity=0, + $fixable=false + ) { + if ($stackPtr === null) { + $line = 1; + $column = 1; + } else { + $line = $this->tokens[$stackPtr]['line']; + $column = $this->tokens[$stackPtr]['column']; + } + + return $this->addMessage(true, $error, $line, $column, $code, $data, $severity, $fixable); + + }//end addError() + + + /** + * Records a warning against a specific token in the file. + * + * @param string $warning The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the warning be fixed by the sniff? + * + * @return boolean + */ + public function addWarning( + $warning, + $stackPtr, + $code, + $data=[], + $severity=0, + $fixable=false + ) { + if ($stackPtr === null) { + $line = 1; + $column = 1; + } else { + $line = $this->tokens[$stackPtr]['line']; + $column = $this->tokens[$stackPtr]['column']; + } + + return $this->addMessage(false, $warning, $line, $column, $code, $data, $severity, $fixable); + + }//end addWarning() + + + /** + * Records an error against a specific line in the file. + * + * @param string $error The error message. + * @param int $line The line on which the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addErrorOnLine( + $error, + $line, + $code, + $data=[], + $severity=0 + ) { + return $this->addMessage(true, $error, $line, 1, $code, $data, $severity, false); + + }//end addErrorOnLine() + + + /** + * Records a warning against a specific line in the file. + * + * @param string $warning The error message. + * @param int $line The line on which the warning occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 will + * will be converted into the default severity level. + * + * @return boolean + */ + public function addWarningOnLine( + $warning, + $line, + $code, + $data=[], + $severity=0 + ) { + return $this->addMessage(false, $warning, $line, 1, $code, $data, $severity, false); + + }//end addWarningOnLine() + + + /** + * Records a fixable error against a specific token in the file. + * + * Returns true if the error was recorded and should be fixed. + * + * @param string $error The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the error message. + * @param int $severity The severity level for this error. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addFixableError( + $error, + $stackPtr, + $code, + $data=[], + $severity=0 + ) { + $recorded = $this->addError($error, $stackPtr, $code, $data, $severity, true); + if ($recorded === true && $this->fixer->enabled === true) { + return true; + } + + return false; + + }//end addFixableError() + + + /** + * Records a fixable warning against a specific token in the file. + * + * Returns true if the warning was recorded and should be fixed. + * + * @param string $warning The error message. + * @param int $stackPtr The stack position where the error occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the warning message. + * @param int $severity The severity level for this warning. A value of 0 + * will be converted into the default severity level. + * + * @return boolean + */ + public function addFixableWarning( + $warning, + $stackPtr, + $code, + $data=[], + $severity=0 + ) { + $recorded = $this->addWarning($warning, $stackPtr, $code, $data, $severity, true); + if ($recorded === true && $this->fixer->enabled === true) { + return true; + } + + return false; + + }//end addFixableWarning() + + + /** + * Adds an error to the error stack. + * + * @param boolean $error Is this an error message? + * @param string $message The text of the message. + * @param int $line The line on which the message occurred. + * @param int $column The column at which the message occurred. + * @param string $code A violation code unique to the sniff message. + * @param array $data Replacements for the message. + * @param int $severity The severity level for this message. A value of 0 + * will be converted into the default severity level. + * @param boolean $fixable Can the problem be fixed by the sniff? + * + * @return boolean + */ + protected function addMessage($error, $message, $line, $column, $code, $data, $severity, $fixable) + { + // Check if this line is ignoring all message codes. + if (isset($this->tokenizer->ignoredLines[$line]['.all']) === true) { + return false; + } + + // Work out which sniff generated the message. + $parts = explode('.', $code); + if ($parts[0] === 'Internal') { + // An internal message. + $listenerCode = ''; + if ($this->activeListener !== '') { + $listenerCode = Common::getSniffCode($this->activeListener); + } + + $sniffCode = $code; + $checkCodes = [$sniffCode]; + } else { + if ($parts[0] !== $code) { + // The full message code has been passed in. + $sniffCode = $code; + $listenerCode = substr($sniffCode, 0, strrpos($sniffCode, '.')); + } else { + $listenerCode = Common::getSniffCode($this->activeListener); + $sniffCode = $listenerCode.'.'.$code; + $parts = explode('.', $sniffCode); + } + + $checkCodes = [ + $sniffCode, + $parts[0].'.'.$parts[1].'.'.$parts[2], + $parts[0].'.'.$parts[1], + $parts[0], + ]; + }//end if + + if (isset($this->tokenizer->ignoredLines[$line]) === true) { + // Check if this line is ignoring this specific message. + $ignored = false; + foreach ($checkCodes as $checkCode) { + if (isset($this->tokenizer->ignoredLines[$line][$checkCode]) === true) { + $ignored = true; + break; + } + } + + // If it is ignored, make sure there is no exception in place. + if ($ignored === true + && isset($this->tokenizer->ignoredLines[$line]['.except']) === true + ) { + foreach ($checkCodes as $checkCode) { + if (isset($this->tokenizer->ignoredLines[$line]['.except'][$checkCode]) === true) { + $ignored = false; + break; + } + } + } + + if ($ignored === true) { + return false; + } + }//end if + + $includeAll = true; + if ($this->configCache['cache'] === false + || $this->configCache['recordErrors'] === false + ) { + $includeAll = false; + } + + // Filter out any messages for sniffs that shouldn't have run + // due to the use of the --sniffs command line argument. + if ($includeAll === false + && ((empty($this->configCache['sniffs']) === false + && in_array(strtolower($listenerCode), $this->configCache['sniffs'], true) === false) + || (empty($this->configCache['exclude']) === false + && in_array(strtolower($listenerCode), $this->configCache['exclude'], true) === true)) + ) { + return false; + } + + // If we know this sniff code is being ignored for this file, return early. + foreach ($checkCodes as $checkCode) { + if (isset($this->ignoredCodes[$checkCode]) === true) { + return false; + } + } + + $oppositeType = 'warning'; + if ($error === false) { + $oppositeType = 'error'; + } + + foreach ($checkCodes as $checkCode) { + // Make sure this message type has not been set to the opposite message type. + if (isset($this->ruleset->ruleset[$checkCode]['type']) === true + && $this->ruleset->ruleset[$checkCode]['type'] === $oppositeType + ) { + $error = !$error; + break; + } + } + + if ($error === true) { + $configSeverity = $this->configCache['errorSeverity']; + $messageCount = &$this->errorCount; + $messages = &$this->errors; + } else { + $configSeverity = $this->configCache['warningSeverity']; + $messageCount = &$this->warningCount; + $messages = &$this->warnings; + } + + if ($includeAll === false && $configSeverity === 0) { + // Don't bother doing any processing as these messages are just going to + // be hidden in the reports anyway. + return false; + } + + if ($severity === 0) { + $severity = 5; + } + + foreach ($checkCodes as $checkCode) { + // Make sure we are interested in this severity level. + if (isset($this->ruleset->ruleset[$checkCode]['severity']) === true) { + $severity = $this->ruleset->ruleset[$checkCode]['severity']; + break; + } + } + + if ($includeAll === false && $configSeverity > $severity) { + return false; + } + + // Make sure we are not ignoring this file. + $included = null; + if (trim($this->path, '\'"') === 'STDIN') { + $included = true; + } else { + foreach ($checkCodes as $checkCode) { + $patterns = null; + + if (isset($this->configCache['includePatterns'][$checkCode]) === true) { + $patterns = $this->configCache['includePatterns'][$checkCode]; + $excluding = false; + } else if (isset($this->configCache['ignorePatterns'][$checkCode]) === true) { + $patterns = $this->configCache['ignorePatterns'][$checkCode]; + $excluding = true; + } + + if ($patterns === null) { + continue; + } + + foreach ($patterns as $pattern => $type) { + // While there is support for a type of each pattern + // (absolute or relative) we don't actually support it here. + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $replacements['/'] = '\\\\'; + } + + $pattern = '`'.strtr($pattern, $replacements).'`i'; + $matched = preg_match($pattern, $this->path); + + if ($matched === 0) { + if ($excluding === false && $included === null) { + // This file path is not being included. + $included = false; + } + + continue; + } + + if ($excluding === true) { + // This file path is being excluded. + $this->ignoredCodes[$checkCode] = true; + return false; + } + + // This file path is being included. + $included = true; + break; + }//end foreach + }//end foreach + }//end if + + if ($included === false) { + // There were include rules set, but this file + // path didn't match any of them. + return false; + } + + $messageCount++; + if ($fixable === true) { + $this->fixableCount++; + } + + if ($this->configCache['recordErrors'] === false + && $includeAll === false + ) { + return true; + } + + // See if there is a custom error message format to use. + // But don't do this if we are replaying errors because replayed + // errors have already used the custom format and have had their + // data replaced. + if ($this->replayingErrors === false + && isset($this->ruleset->ruleset[$sniffCode]['message']) === true + ) { + $message = $this->ruleset->ruleset[$sniffCode]['message']; + } + + if (empty($data) === false) { + $message = vsprintf($message, $data); + } + + if (isset($messages[$line]) === false) { + $messages[$line] = []; + } + + if (isset($messages[$line][$column]) === false) { + $messages[$line][$column] = []; + } + + $messages[$line][$column][] = [ + 'message' => $message, + 'source' => $sniffCode, + 'listener' => $this->activeListener, + 'severity' => $severity, + 'fixable' => $fixable, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1 + && $this->fixer->enabled === true + && $fixable === true + ) { + @ob_end_clean(); + echo "\tE: [Line $line] $message ($sniffCode)".PHP_EOL; + ob_start(); + } + + return true; + + }//end addMessage() + + + /** + * Record a metric about the file being examined. + * + * @param int $stackPtr The stack position where the metric was recorded. + * @param string $metric The name of the metric being recorded. + * @param string $value The value of the metric being recorded. + * + * @return boolean + */ + public function recordMetric($stackPtr, $metric, $value) + { + if (isset($this->metrics[$metric]) === false) { + $this->metrics[$metric] = ['values' => [$value => 1]]; + $this->metricTokens[$metric][$stackPtr] = true; + } else if (isset($this->metricTokens[$metric][$stackPtr]) === false) { + $this->metricTokens[$metric][$stackPtr] = true; + if (isset($this->metrics[$metric]['values'][$value]) === false) { + $this->metrics[$metric]['values'][$value] = 1; + } else { + $this->metrics[$metric]['values'][$value]++; + } + } + + return true; + + }//end recordMetric() + + + /** + * Returns the number of errors raised. + * + * @return int + */ + public function getErrorCount() + { + return $this->errorCount; + + }//end getErrorCount() + + + /** + * Returns the number of warnings raised. + * + * @return int + */ + public function getWarningCount() + { + return $this->warningCount; + + }//end getWarningCount() + + + /** + * Returns the number of fixable errors/warnings raised. + * + * @return int + */ + public function getFixableCount() + { + return $this->fixableCount; + + }//end getFixableCount() + + + /** + * Returns the number of fixed errors/warnings. + * + * @return int + */ + public function getFixedCount() + { + return $this->fixedCount; + + }//end getFixedCount() + + + /** + * Returns the list of ignored lines. + * + * @return array + */ + public function getIgnoredLines() + { + return $this->tokenizer->ignoredLines; + + }//end getIgnoredLines() + + + /** + * Returns the errors raised from processing this file. + * + * @return array + */ + public function getErrors() + { + return $this->errors; + + }//end getErrors() + + + /** + * Returns the warnings raised from processing this file. + * + * @return array + */ + public function getWarnings() + { + return $this->warnings; + + }//end getWarnings() + + + /** + * Returns the metrics found while processing this file. + * + * @return array + */ + public function getMetrics() + { + return $this->metrics; + + }//end getMetrics() + + + /** + * Returns the time taken processing this file for each invoked sniff. + * + * @return array + */ + public function getListenerTimes() + { + return $this->listenerTimes; + + }//end getListenerTimes() + + + /** + * Returns the absolute filename of this file. + * + * @return string + */ + public function getFilename() + { + return $this->path; + + }//end getFilename() + + + /** + * Returns the declaration name for classes, interfaces, traits, enums, and functions. + * + * @param int $stackPtr The position of the declaration token which + * declared the class, interface, trait, or function. + * + * @return string|null The name of the class, interface, trait, or function; + * or NULL if the function or class is anonymous. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified token is not of type + * T_FUNCTION, T_CLASS, T_ANON_CLASS, + * T_CLOSURE, T_TRAIT, T_ENUM, or T_INTERFACE. + */ + public function getDeclarationName($stackPtr) + { + $tokenCode = $this->tokens[$stackPtr]['code']; + + if ($tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + return null; + } + + if ($tokenCode !== T_FUNCTION + && $tokenCode !== T_CLASS + && $tokenCode !== T_INTERFACE + && $tokenCode !== T_TRAIT + && $tokenCode !== T_ENUM + ) { + throw new RuntimeException('Token type "'.$this->tokens[$stackPtr]['type'].'" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM'); + } + + if ($tokenCode === T_FUNCTION + && strtolower($this->tokens[$stackPtr]['content']) !== 'function' + ) { + // This is a function declared without the "function" keyword. + // So this token is the function name. + return $this->tokens[$stackPtr]['content']; + } + + $content = null; + for ($i = $stackPtr; $i < $this->numTokens; $i++) { + if ($this->tokens[$i]['code'] === T_STRING) { + $content = $this->tokens[$i]['content']; + break; + } + } + + return $content; + + }//end getDeclarationName() + + + /** + * Returns the method parameters for the specified function token. + * + * Also supports passing in a USE token for a closure use group. + * + * Each parameter is in the following format: + * + * + * 0 => array( + * 'name' => string, // The variable name. + * 'token' => integer, // The stack pointer to the variable name. + * 'content' => string, // The full content of the variable definition. + * 'has_attributes' => boolean, // Does the parameter have one or more attributes attached ? + * 'pass_by_reference' => boolean, // Is the variable passed by reference? + * 'reference_token' => integer|false, // The stack pointer to the reference operator + * // or FALSE if the param is not passed by reference. + * 'variable_length' => boolean, // Is the param of variable length through use of `...` ? + * 'variadic_token' => integer|false, // The stack pointer to the ... operator + * // or FALSE if the param is not variable length. + * 'type_hint' => string, // The type hint for the variable. + * 'type_hint_token' => integer|false, // The stack pointer to the start of the type hint + * // or FALSE if there is no type hint. + * 'type_hint_end_token' => integer|false, // The stack pointer to the end of the type hint + * // or FALSE if there is no type hint. + * 'nullable_type' => boolean, // TRUE if the type is preceded by the nullability + * // operator. + * 'comma_token' => integer|false, // The stack pointer to the comma after the param + * // or FALSE if this is the last param. + * ) + * + * + * Parameters with default values have additional array indexes of: + * 'default' => string, // The full content of the default value. + * 'default_token' => integer, // The stack pointer to the start of the default value. + * 'default_equal_token' => integer, // The stack pointer to the equals sign. + * + * Parameters declared using PHP 8 constructor property promotion, have these additional array indexes: + * 'property_visibility' => string, // The property visibility as declared. + * 'visibility_token' => integer|false, // The stack pointer to the visibility modifier token + * // or FALSE if the visibility is not explicitly declared. + * 'property_readonly' => boolean, // TRUE if the readonly keyword was found. + * 'readonly_token' => integer, // The stack pointer to the readonly modifier token. + * // This index will only be set if the property is readonly. + * + * @param int $stackPtr The position in the stack of the function token + * to acquire the parameters for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified $stackPtr is not of + * type T_FUNCTION, T_CLOSURE, T_USE, + * or T_FN. + */ + public function getMethodParameters($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_CLOSURE + && $this->tokens[$stackPtr]['code'] !== T_USE + && $this->tokens[$stackPtr]['code'] !== T_FN + ) { + throw new RuntimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_USE or T_FN'); + } + + if ($this->tokens[$stackPtr]['code'] === T_USE) { + $opener = $this->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1)); + if ($opener === false || isset($this->tokens[$opener]['parenthesis_owner']) === true) { + throw new RuntimeException('$stackPtr was not a valid T_USE'); + } + } else { + if (isset($this->tokens[$stackPtr]['parenthesis_opener']) === false) { + // Live coding or syntax error, so no params to find. + return []; + } + + $opener = $this->tokens[$stackPtr]['parenthesis_opener']; + } + + if (isset($this->tokens[$opener]['parenthesis_closer']) === false) { + // Live coding or syntax error, so no params to find. + return []; + } + + $closer = $this->tokens[$opener]['parenthesis_closer']; + + $vars = []; + $currVar = null; + $paramStart = ($opener + 1); + $defaultStart = null; + $equalToken = null; + $paramCount = 0; + $hasAttributes = false; + $passByReference = false; + $referenceToken = false; + $variableLength = false; + $variadicToken = false; + $typeHint = ''; + $typeHintToken = false; + $typeHintEndToken = false; + $nullableType = false; + $visibilityToken = null; + $readonlyToken = null; + + for ($i = $paramStart; $i <= $closer; $i++) { + // Check to see if this token has a parenthesis or bracket opener. If it does + // it's likely to be an array which might have arguments in it. This + // could cause problems in our parsing below, so lets just skip to the + // end of it. + if ($this->tokens[$i]['code'] !== T_TYPE_OPEN_PARENTHESIS + && isset($this->tokens[$i]['parenthesis_opener']) === true + ) { + // Don't do this if it's the close parenthesis for the method. + if ($i !== $this->tokens[$i]['parenthesis_closer']) { + $i = $this->tokens[$i]['parenthesis_closer']; + continue; + } + } + + if (isset($this->tokens[$i]['bracket_opener']) === true) { + if ($i !== $this->tokens[$i]['bracket_closer']) { + $i = $this->tokens[$i]['bracket_closer']; + continue; + } + } + + switch ($this->tokens[$i]['code']) { + case T_ATTRIBUTE: + $hasAttributes = true; + + // Skip to the end of the attribute. + $i = $this->tokens[$i]['attribute_closer']; + break; + case T_BITWISE_AND: + if ($defaultStart === null) { + $passByReference = true; + $referenceToken = $i; + } + break; + case T_VARIABLE: + $currVar = $i; + break; + case T_ELLIPSIS: + $variableLength = true; + $variadicToken = $i; + break; + case T_CALLABLE: + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + break; + case T_SELF: + case T_PARENT: + case T_STATIC: + // Self and parent are valid, static invalid, but was probably intended as type hint. + if (isset($defaultStart) === false) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_STRING: + // This is a string, so it may be a type hint, but it could + // also be a constant used as a default value. + $prevComma = false; + for ($t = $i; $t >= $opener; $t--) { + if ($this->tokens[$t]['code'] === T_COMMA) { + $prevComma = $t; + break; + } + } + + if ($prevComma !== false) { + $nextEquals = false; + for ($t = $prevComma; $t < $i; $t++) { + if ($this->tokens[$t]['code'] === T_EQUAL) { + $nextEquals = $t; + break; + } + } + + if ($nextEquals !== false) { + break; + } + } + + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_NAMESPACE: + case T_NS_SEPARATOR: + case T_TYPE_UNION: + case T_TYPE_INTERSECTION: + case T_TYPE_OPEN_PARENTHESIS: + case T_TYPE_CLOSE_PARENTHESIS: + case T_FALSE: + case T_TRUE: + case T_NULL: + // Part of a type hint or default value. + if ($defaultStart === null) { + if ($typeHintToken === false) { + $typeHintToken = $i; + } + + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_NULLABLE: + if ($defaultStart === null) { + $nullableType = true; + $typeHint .= $this->tokens[$i]['content']; + $typeHintEndToken = $i; + } + break; + case T_PUBLIC: + case T_PROTECTED: + case T_PRIVATE: + if ($defaultStart === null) { + $visibilityToken = $i; + } + break; + case T_READONLY: + if ($defaultStart === null) { + $readonlyToken = $i; + } + break; + case T_CLOSE_PARENTHESIS: + case T_COMMA: + // If it's null, then there must be no parameters for this + // method. + if ($currVar === null) { + continue 2; + } + + $vars[$paramCount] = []; + $vars[$paramCount]['token'] = $currVar; + $vars[$paramCount]['name'] = $this->tokens[$currVar]['content']; + $vars[$paramCount]['content'] = trim($this->getTokensAsString($paramStart, ($i - $paramStart))); + + if ($defaultStart !== null) { + $vars[$paramCount]['default'] = trim($this->getTokensAsString($defaultStart, ($i - $defaultStart))); + $vars[$paramCount]['default_token'] = $defaultStart; + $vars[$paramCount]['default_equal_token'] = $equalToken; + } + + $vars[$paramCount]['has_attributes'] = $hasAttributes; + $vars[$paramCount]['pass_by_reference'] = $passByReference; + $vars[$paramCount]['reference_token'] = $referenceToken; + $vars[$paramCount]['variable_length'] = $variableLength; + $vars[$paramCount]['variadic_token'] = $variadicToken; + $vars[$paramCount]['type_hint'] = $typeHint; + $vars[$paramCount]['type_hint_token'] = $typeHintToken; + $vars[$paramCount]['type_hint_end_token'] = $typeHintEndToken; + $vars[$paramCount]['nullable_type'] = $nullableType; + + if ($visibilityToken !== null || $readonlyToken !== null) { + $vars[$paramCount]['property_visibility'] = 'public'; + $vars[$paramCount]['visibility_token'] = false; + $vars[$paramCount]['property_readonly'] = false; + + if ($visibilityToken !== null) { + $vars[$paramCount]['property_visibility'] = $this->tokens[$visibilityToken]['content']; + $vars[$paramCount]['visibility_token'] = $visibilityToken; + } + + if ($readonlyToken !== null) { + $vars[$paramCount]['property_readonly'] = true; + $vars[$paramCount]['readonly_token'] = $readonlyToken; + } + } + + if ($this->tokens[$i]['code'] === T_COMMA) { + $vars[$paramCount]['comma_token'] = $i; + } else { + $vars[$paramCount]['comma_token'] = false; + } + + // Reset the vars, as we are about to process the next parameter. + $currVar = null; + $paramStart = ($i + 1); + $defaultStart = null; + $equalToken = null; + $hasAttributes = false; + $passByReference = false; + $referenceToken = false; + $variableLength = false; + $variadicToken = false; + $typeHint = ''; + $typeHintToken = false; + $typeHintEndToken = false; + $nullableType = false; + $visibilityToken = null; + $readonlyToken = null; + + $paramCount++; + break; + case T_EQUAL: + $defaultStart = $this->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + $equalToken = $i; + break; + }//end switch + }//end for + + return $vars; + + }//end getMethodParameters() + + + /** + * Returns the visibility and implementation properties of a method. + * + * The format of the return value is: + * + * array( + * 'scope' => string, // Public, private, or protected + * 'scope_specified' => boolean, // TRUE if the scope keyword was found. + * 'return_type' => string, // The return type of the method. + * 'return_type_token' => integer|false, // The stack pointer to the start of the return type + * // or FALSE if there is no return type. + * 'return_type_end_token' => integer|false, // The stack pointer to the end of the return type + * // or FALSE if there is no return type. + * 'nullable_return_type' => boolean, // TRUE if the return type is preceded by the + * // nullability operator. + * 'is_abstract' => boolean, // TRUE if the abstract keyword was found. + * 'is_final' => boolean, // TRUE if the final keyword was found. + * 'is_static' => boolean, // TRUE if the static keyword was found. + * 'has_body' => boolean, // TRUE if the method has a body + * ); + * + * + * @param int $stackPtr The position in the stack of the function token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_FUNCTION, T_CLOSURE, or T_FN token. + */ + public function getMethodProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_CLOSURE + && $this->tokens[$stackPtr]['code'] !== T_FN + ) { + throw new RuntimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_FN'); + } + + if ($this->tokens[$stackPtr]['code'] === T_FUNCTION) { + $valid = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_STATIC => T_STATIC, + T_FINAL => T_FINAL, + T_ABSTRACT => T_ABSTRACT, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + } else { + $valid = [ + T_STATIC => T_STATIC, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + } + + $scope = 'public'; + $scopeSpecified = false; + $isAbstract = false; + $isFinal = false; + $isStatic = false; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_PUBLIC: + $scope = 'public'; + $scopeSpecified = true; + break; + case T_PRIVATE: + $scope = 'private'; + $scopeSpecified = true; + break; + case T_PROTECTED: + $scope = 'protected'; + $scopeSpecified = true; + break; + case T_ABSTRACT: + $isAbstract = true; + break; + case T_FINAL: + $isFinal = true; + break; + case T_STATIC: + $isStatic = true; + break; + }//end switch + }//end for + + $returnType = ''; + $returnTypeToken = false; + $returnTypeEndToken = false; + $nullableReturnType = false; + $hasBody = true; + + if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true) { + $scopeOpener = null; + if (isset($this->tokens[$stackPtr]['scope_opener']) === true) { + $scopeOpener = $this->tokens[$stackPtr]['scope_opener']; + } + + $valid = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + T_FALSE => T_FALSE, + T_TRUE => T_TRUE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + T_TYPE_OPEN_PARENTHESIS => T_TYPE_OPEN_PARENTHESIS, + T_TYPE_CLOSE_PARENTHESIS => T_TYPE_CLOSE_PARENTHESIS, + ]; + + for ($i = $this->tokens[$stackPtr]['parenthesis_closer']; $i < $this->numTokens; $i++) { + if (($scopeOpener === null && $this->tokens[$i]['code'] === T_SEMICOLON) + || ($scopeOpener !== null && $i === $scopeOpener) + ) { + // End of function definition. + break; + } + + if ($this->tokens[$i]['code'] === T_USE) { + // Skip over closure use statements. + for ($j = ($i + 1); $j < $this->numTokens && isset(Tokens::$emptyTokens[$this->tokens[$j]['code']]) === true; $j++); + if ($this->tokens[$j]['code'] === T_OPEN_PARENTHESIS) { + if (isset($this->tokens[$j]['parenthesis_closer']) === false) { + // Live coding/parse error, stop parsing. + break; + } + + $i = $this->tokens[$j]['parenthesis_closer']; + continue; + } + } + + if ($this->tokens[$i]['code'] === T_NULLABLE) { + $nullableReturnType = true; + } + + if (isset($valid[$this->tokens[$i]['code']]) === true) { + if ($returnTypeToken === false) { + $returnTypeToken = $i; + } + + $returnType .= $this->tokens[$i]['content']; + $returnTypeEndToken = $i; + } + }//end for + + if ($this->tokens[$stackPtr]['code'] === T_FN) { + $bodyToken = T_FN_ARROW; + } else { + $bodyToken = T_OPEN_CURLY_BRACKET; + } + + $end = $this->findNext([$bodyToken, T_SEMICOLON], $this->tokens[$stackPtr]['parenthesis_closer']); + $hasBody = $this->tokens[$end]['code'] === $bodyToken; + }//end if + + if ($returnType !== '' && $nullableReturnType === true) { + $returnType = '?'.$returnType; + } + + return [ + 'scope' => $scope, + 'scope_specified' => $scopeSpecified, + 'return_type' => $returnType, + 'return_type_token' => $returnTypeToken, + 'return_type_end_token' => $returnTypeEndToken, + 'nullable_return_type' => $nullableReturnType, + 'is_abstract' => $isAbstract, + 'is_final' => $isFinal, + 'is_static' => $isStatic, + 'has_body' => $hasBody, + ]; + + }//end getMethodProperties() + + + /** + * Returns the visibility and implementation properties of a class member var. + * + * The format of the return value is: + * + * + * array( + * 'scope' => string, // Public, private, or protected. + * 'scope_specified' => boolean, // TRUE if the scope was explicitly specified. + * 'is_static' => boolean, // TRUE if the static keyword was found. + * 'is_readonly' => boolean, // TRUE if the readonly keyword was found. + * 'type' => string, // The type of the var (empty if no type specified). + * 'type_token' => integer|false, // The stack pointer to the start of the type + * // or FALSE if there is no type. + * 'type_end_token' => integer|false, // The stack pointer to the end of the type + * // or FALSE if there is no type. + * 'nullable_type' => boolean, // TRUE if the type is preceded by the nullability + * // operator. + * ); + * + * + * @param int $stackPtr The position in the stack of the T_VARIABLE token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_VARIABLE token, or if the position is not + * a class member variable. + */ + public function getMemberProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_VARIABLE) { + throw new RuntimeException('$stackPtr must be of type T_VARIABLE'); + } + + $conditions = array_keys($this->tokens[$stackPtr]['conditions']); + $ptr = array_pop($conditions); + if (isset($this->tokens[$ptr]) === false + || ($this->tokens[$ptr]['code'] !== T_CLASS + && $this->tokens[$ptr]['code'] !== T_ANON_CLASS + && $this->tokens[$ptr]['code'] !== T_TRAIT) + ) { + if (isset($this->tokens[$ptr]) === true + && ($this->tokens[$ptr]['code'] === T_INTERFACE + || $this->tokens[$ptr]['code'] === T_ENUM) + ) { + // T_VARIABLEs in interfaces/enums can actually be method arguments + // but they won't be seen as being inside the method because there + // are no scope openers and closers for abstract methods. If it is in + // parentheses, we can be pretty sure it is a method argument. + if (isset($this->tokens[$stackPtr]['nested_parenthesis']) === false + || empty($this->tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $error = 'Possible parse error: %ss may not include member vars'; + $code = sprintf('Internal.ParseError.%sHasMemberVar', ucfirst($this->tokens[$ptr]['content'])); + $data = [strtolower($this->tokens[$ptr]['content'])]; + $this->addWarning($error, $stackPtr, $code, $data); + return []; + } + } else { + throw new RuntimeException('$stackPtr is not a class member var'); + } + }//end if + + // Make sure it's not a method parameter. + if (empty($this->tokens[$stackPtr]['nested_parenthesis']) === false) { + $parenthesis = array_keys($this->tokens[$stackPtr]['nested_parenthesis']); + $deepestOpen = array_pop($parenthesis); + if ($deepestOpen > $ptr + && isset($this->tokens[$deepestOpen]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$deepestOpen]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + throw new RuntimeException('$stackPtr is not a class member var'); + } + } + + $valid = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_STATIC => T_STATIC, + T_VAR => T_VAR, + T_READONLY => T_READONLY, + ]; + + $valid += Tokens::$emptyTokens; + + $scope = 'public'; + $scopeSpecified = false; + $isStatic = false; + $isReadonly = false; + + $startOfStatement = $this->findPrevious( + [ + T_SEMICOLON, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + T_ATTRIBUTE_END, + ], + ($stackPtr - 1) + ); + + for ($i = ($startOfStatement + 1); $i < $stackPtr; $i++) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_PUBLIC: + $scope = 'public'; + $scopeSpecified = true; + break; + case T_PRIVATE: + $scope = 'private'; + $scopeSpecified = true; + break; + case T_PROTECTED: + $scope = 'protected'; + $scopeSpecified = true; + break; + case T_STATIC: + $isStatic = true; + break; + case T_READONLY: + $isReadonly = true; + break; + } + }//end for + + $type = ''; + $typeToken = false; + $typeEndToken = false; + $nullableType = false; + + if ($i < $stackPtr) { + // We've found a type. + $valid = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_FALSE => T_FALSE, + T_TRUE => T_TRUE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + T_TYPE_OPEN_PARENTHESIS => T_TYPE_OPEN_PARENTHESIS, + T_TYPE_CLOSE_PARENTHESIS => T_TYPE_CLOSE_PARENTHESIS, + ]; + + for ($i; $i < $stackPtr; $i++) { + if ($this->tokens[$i]['code'] === T_VARIABLE) { + // Hit another variable in a group definition. + break; + } + + if ($this->tokens[$i]['code'] === T_NULLABLE) { + $nullableType = true; + } + + if (isset($valid[$this->tokens[$i]['code']]) === true) { + $typeEndToken = $i; + if ($typeToken === false) { + $typeToken = $i; + } + + $type .= $this->tokens[$i]['content']; + } + } + + if ($type !== '' && $nullableType === true) { + $type = '?'.$type; + } + }//end if + + return [ + 'scope' => $scope, + 'scope_specified' => $scopeSpecified, + 'is_static' => $isStatic, + 'is_readonly' => $isReadonly, + 'type' => $type, + 'type_token' => $typeToken, + 'type_end_token' => $typeEndToken, + 'nullable_type' => $nullableType, + ]; + + }//end getMemberProperties() + + + /** + * Returns the visibility and implementation properties of a class. + * + * The format of the return value is: + * + * array( + * 'is_abstract' => boolean, // TRUE if the abstract keyword was found. + * 'is_final' => boolean, // TRUE if the final keyword was found. + * 'is_readonly' => boolean, // TRUE if the readonly keyword was found. + * ); + * + * + * @param int $stackPtr The position in the stack of the T_CLASS token to + * acquire the properties for. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position is not a + * T_CLASS token. + */ + public function getClassProperties($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_CLASS) { + throw new RuntimeException('$stackPtr must be of type T_CLASS'); + } + + $valid = [ + T_FINAL => T_FINAL, + T_ABSTRACT => T_ABSTRACT, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + ]; + + $isAbstract = false; + $isFinal = false; + $isReadonly = false; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (isset($valid[$this->tokens[$i]['code']]) === false) { + break; + } + + switch ($this->tokens[$i]['code']) { + case T_ABSTRACT: + $isAbstract = true; + break; + + case T_FINAL: + $isFinal = true; + break; + + case T_READONLY: + $isReadonly = true; + break; + } + }//end for + + return [ + 'is_abstract' => $isAbstract, + 'is_final' => $isFinal, + 'is_readonly' => $isReadonly, + ]; + + }//end getClassProperties() + + + /** + * Determine if the passed token is a reference operator. + * + * Returns true if the specified token position represents a reference. + * Returns false if the token represents a bitwise operator. + * + * @param int $stackPtr The position of the T_BITWISE_AND token. + * + * @return boolean + */ + public function isReference($stackPtr) + { + if ($this->tokens[$stackPtr]['code'] !== T_BITWISE_AND) { + return false; + } + + $tokenBefore = $this->findPrevious( + Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($this->tokens[$tokenBefore]['code'] === T_FUNCTION + || $this->tokens[$tokenBefore]['code'] === T_CLOSURE + || $this->tokens[$tokenBefore]['code'] === T_FN + ) { + // Function returns a reference. + return true; + } + + if ($this->tokens[$tokenBefore]['code'] === T_DOUBLE_ARROW) { + // Inside a foreach loop or array assignment, this is a reference. + return true; + } + + if ($this->tokens[$tokenBefore]['code'] === T_AS) { + // Inside a foreach loop, this is a reference. + return true; + } + + if (isset(Tokens::$assignmentTokens[$this->tokens[$tokenBefore]['code']]) === true) { + // This is directly after an assignment. It's a reference. Even if + // it is part of an operation, the other tests will handle it. + return true; + } + + $tokenAfter = $this->findNext( + Tokens::$emptyTokens, + ($stackPtr + 1), + null, + true + ); + + if ($this->tokens[$tokenAfter]['code'] === T_NEW) { + return true; + } + + if (isset($this->tokens[$stackPtr]['nested_parenthesis']) === true) { + $brackets = $this->tokens[$stackPtr]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if (isset($this->tokens[$lastBracket]['parenthesis_owner']) === true) { + $owner = $this->tokens[$this->tokens[$lastBracket]['parenthesis_owner']]; + if ($owner['code'] === T_FUNCTION + || $owner['code'] === T_CLOSURE + || $owner['code'] === T_FN + ) { + $params = $this->getMethodParameters($this->tokens[$lastBracket]['parenthesis_owner']); + foreach ($params as $param) { + if ($param['reference_token'] === $stackPtr) { + // Function parameter declared to be passed by reference. + return true; + } + } + }//end if + } else { + $prev = false; + for ($t = ($this->tokens[$lastBracket]['parenthesis_opener'] - 1); $t >= 0; $t--) { + if ($this->tokens[$t]['code'] !== T_WHITESPACE) { + $prev = $t; + break; + } + } + + if ($prev !== false && $this->tokens[$prev]['code'] === T_USE) { + // Closure use by reference. + return true; + } + }//end if + }//end if + + // Pass by reference in function calls and assign by reference in arrays. + if ($this->tokens[$tokenBefore]['code'] === T_OPEN_PARENTHESIS + || $this->tokens[$tokenBefore]['code'] === T_COMMA + || $this->tokens[$tokenBefore]['code'] === T_OPEN_SHORT_ARRAY + ) { + if ($this->tokens[$tokenAfter]['code'] === T_VARIABLE) { + return true; + } else { + $skip = Tokens::$emptyTokens; + $skip[] = T_NS_SEPARATOR; + $skip[] = T_SELF; + $skip[] = T_PARENT; + $skip[] = T_STATIC; + $skip[] = T_STRING; + $skip[] = T_NAMESPACE; + $skip[] = T_DOUBLE_COLON; + + $nextSignificantAfter = $this->findNext( + $skip, + ($stackPtr + 1), + null, + true + ); + if ($this->tokens[$nextSignificantAfter]['code'] === T_VARIABLE) { + return true; + } + }//end if + }//end if + + return false; + + }//end isReference() + + + /** + * Returns the content of the tokens from the specified start position in + * the token stack for the specified length. + * + * @param int $start The position to start from in the token stack. + * @param int $length The length of tokens to traverse from the start pos. + * @param bool $origContent Whether the original content or the tab replaced + * content should be used. + * + * @return string The token contents. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified position does not exist. + */ + public function getTokensAsString($start, $length, $origContent=false) + { + if (is_int($start) === false || isset($this->tokens[$start]) === false) { + throw new RuntimeException('The $start position for getTokensAsString() must exist in the token stack'); + } + + if (is_int($length) === false || $length <= 0) { + return ''; + } + + $str = ''; + $end = ($start + $length); + if ($end > $this->numTokens) { + $end = $this->numTokens; + } + + for ($i = $start; $i < $end; $i++) { + // If tabs are being converted to spaces by the tokeniser, the + // original content should be used instead of the converted content. + if ($origContent === true && isset($this->tokens[$i]['orig_content']) === true) { + $str .= $this->tokens[$i]['orig_content']; + } else { + $str .= $this->tokens[$i]['content']; + } + } + + return $str; + + }//end getTokensAsString() + + + /** + * Returns the position of the previous specified token(s). + * + * If a value is specified, the previous token of the specified type(s) + * containing the specified value will be returned. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param int|null $end The end position to fail if no token is found. + * if not specified or null, end will default to + * the start of the token stack. + * @param bool $exclude If true, find the previous token that is NOT of + * the types specified in $types. + * @param string|null $value The value that the token(s) must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * @param bool $local If true, tokens outside the current statement + * will not be checked. IE. checking will stop + * at the previous semicolon found. + * + * @return int|false + * @see findNext() + */ + public function findPrevious( + $types, + $start, + $end=null, + $exclude=false, + $value=null, + $local=false + ) { + $types = (array) $types; + + if ($end === null) { + $end = 0; + } + + for ($i = $start; $i >= $end; $i--) { + $found = (bool) $exclude; + foreach ($types as $type) { + if ($this->tokens[$i]['code'] === $type) { + $found = !$exclude; + break; + } + } + + if ($found === true) { + if ($value === null) { + return $i; + } else if ($this->tokens[$i]['content'] === $value) { + return $i; + } + } + + if ($local === true) { + if (isset($this->tokens[$i]['scope_opener']) === true + && $i === $this->tokens[$i]['scope_closer'] + ) { + $i = $this->tokens[$i]['scope_opener']; + } else if (isset($this->tokens[$i]['bracket_opener']) === true + && $i === $this->tokens[$i]['bracket_closer'] + ) { + $i = $this->tokens[$i]['bracket_opener']; + } else if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + $i = $this->tokens[$i]['parenthesis_opener']; + } else if ($this->tokens[$i]['code'] === T_SEMICOLON) { + break; + } + } + }//end for + + return false; + + }//end findPrevious() + + + /** + * Returns the position of the next specified token(s). + * + * If a value is specified, the next token of the specified type(s) + * containing the specified value will be returned. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param int|null $end The end position to fail if no token is found. + * if not specified or null, end will default to + * the end of the token stack. + * @param bool $exclude If true, find the next token that is NOT of + * a type specified in $types. + * @param string|null $value The value that the token(s) must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * @param bool $local If true, tokens outside the current statement + * will not be checked. i.e., checking will stop + * at the next semicolon found. + * + * @return int|false + * @see findPrevious() + */ + public function findNext( + $types, + $start, + $end=null, + $exclude=false, + $value=null, + $local=false + ) { + $types = (array) $types; + + if ($end === null || $end > $this->numTokens) { + $end = $this->numTokens; + } + + for ($i = $start; $i < $end; $i++) { + $found = (bool) $exclude; + foreach ($types as $type) { + if ($this->tokens[$i]['code'] === $type) { + $found = !$exclude; + break; + } + } + + if ($found === true) { + if ($value === null) { + return $i; + } else if ($this->tokens[$i]['content'] === $value) { + return $i; + } + } + + if ($local === true && $this->tokens[$i]['code'] === T_SEMICOLON) { + break; + } + }//end for + + return false; + + }//end findNext() + + + /** + * Returns the position of the first non-whitespace token in a statement. + * + * @param int $start The position to start searching from in the token stack. + * @param int|string|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public function findStartOfStatement($start, $ignore=null) + { + $startTokens = Tokens::$blockOpeners; + $startTokens[T_OPEN_SHORT_ARRAY] = true; + $startTokens[T_OPEN_TAG] = true; + $startTokens[T_OPEN_TAG_WITH_ECHO] = true; + + $endTokens = [ + T_CLOSE_TAG => true, + T_COLON => true, + T_COMMA => true, + T_DOUBLE_ARROW => true, + T_MATCH_ARROW => true, + T_SEMICOLON => true, + ]; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + if (isset($startTokens[$code]) === true) { + unset($startTokens[$code]); + } + + if (isset($endTokens[$code]) === true) { + unset($endTokens[$code]); + } + } + } + + // If the start token is inside the case part of a match expression, + // find the start of the condition. If it's in the statement part, find + // the token that comes after the match arrow. + if (empty($this->tokens[$start]['conditions']) === false) { + $conditions = $this->tokens[$start]['conditions']; + $lastConditionOwner = end($conditions); + $matchExpression = key($conditions); + + if ($lastConditionOwner === T_MATCH + // Check if the $start token is at the same parentheses nesting level as the match token. + && ((empty($this->tokens[$matchExpression]['nested_parenthesis']) === true + && empty($this->tokens[$start]['nested_parenthesis']) === true) + || ((empty($this->tokens[$matchExpression]['nested_parenthesis']) === false + && empty($this->tokens[$start]['nested_parenthesis']) === false) + && $this->tokens[$matchExpression]['nested_parenthesis'] === $this->tokens[$start]['nested_parenthesis'])) + ) { + // Walk back to the previous match arrow (if it exists). + $lastComma = null; + $inNestedExpression = false; + for ($prevMatch = $start; $prevMatch > $this->tokens[$matchExpression]['scope_opener']; $prevMatch--) { + if ($prevMatch !== $start && $this->tokens[$prevMatch]['code'] === T_MATCH_ARROW) { + break; + } + + if ($prevMatch !== $start && $this->tokens[$prevMatch]['code'] === T_COMMA) { + $lastComma = $prevMatch; + continue; + } + + // Skip nested statements. + if (isset($this->tokens[$prevMatch]['bracket_opener']) === true + && $prevMatch === $this->tokens[$prevMatch]['bracket_closer'] + ) { + $prevMatch = $this->tokens[$prevMatch]['bracket_opener']; + continue; + } + + if (isset($this->tokens[$prevMatch]['parenthesis_opener']) === true + && $prevMatch === $this->tokens[$prevMatch]['parenthesis_closer'] + ) { + $prevMatch = $this->tokens[$prevMatch]['parenthesis_opener']; + continue; + } + + // Stop if we're _within_ a nested short array statement, which may contain comma's too. + // No need to deal with parentheses, those are handled above via the `nested_parenthesis` checks. + if (isset($this->tokens[$prevMatch]['bracket_opener']) === true + && $this->tokens[$prevMatch]['bracket_closer'] > $start + ) { + $inNestedExpression = true; + break; + } + }//end for + + if ($inNestedExpression === false) { + // $prevMatch will now either be the scope opener or a match arrow. + // If it is the scope opener, go the first non-empty token after. $start will have been part of the first condition. + if ($prevMatch <= $this->tokens[$matchExpression]['scope_opener']) { + // We're before the arrow in the first case. + $next = $this->findNext(Tokens::$emptyTokens, ($this->tokens[$matchExpression]['scope_opener'] + 1), null, true); + if ($next === false) { + // Shouldn't be possible. + return $start; + } + + return $next; + } + + // Okay, so we found a match arrow. + // If $start was part of the "next" condition, the last comma will be set. + // Otherwise, $start must have been part of a return expression. + if (isset($lastComma) === true && $lastComma > $prevMatch) { + $prevMatch = $lastComma; + } + + // In both cases, go to the first non-empty token after. + $next = $this->findNext(Tokens::$emptyTokens, ($prevMatch + 1), null, true); + if ($next === false) { + // Shouldn't be possible. + return $start; + } + + return $next; + }//end if + }//end if + }//end if + + $lastNotEmpty = $start; + + // If we are starting at a token that ends a scope block, skip to + // the start and continue from there. + // If we are starting at a token that ends a statement, skip this + // token so we find the true start of the statement. + while (isset($endTokens[$this->tokens[$start]['code']]) === true + || (isset($this->tokens[$start]['scope_condition']) === true + && $start === $this->tokens[$start]['scope_closer']) + ) { + if (isset($this->tokens[$start]['scope_condition']) === true) { + $start = $this->tokens[$start]['scope_condition']; + } else { + $start--; + } + } + + for ($i = $start; $i >= 0; $i--) { + if (isset($startTokens[$this->tokens[$i]['code']]) === true + || isset($endTokens[$this->tokens[$i]['code']]) === true + ) { + // Found the end of the previous statement. + return $lastNotEmpty; + } + + if (isset($this->tokens[$i]['scope_opener']) === true + && $i === $this->tokens[$i]['scope_closer'] + && $this->tokens[$i]['code'] !== T_CLOSE_PARENTHESIS + && $this->tokens[$i]['code'] !== T_END_NOWDOC + && $this->tokens[$i]['code'] !== T_END_HEREDOC + && $this->tokens[$i]['code'] !== T_BREAK + && $this->tokens[$i]['code'] !== T_RETURN + && $this->tokens[$i]['code'] !== T_CONTINUE + && $this->tokens[$i]['code'] !== T_THROW + && $this->tokens[$i]['code'] !== T_EXIT + ) { + // Found the end of the previous scope block. + return $lastNotEmpty; + } + + // Skip nested statements. + if (isset($this->tokens[$i]['bracket_opener']) === true + && $i === $this->tokens[$i]['bracket_closer'] + ) { + $i = $this->tokens[$i]['bracket_opener']; + } else if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + $i = $this->tokens[$i]['parenthesis_opener']; + } else if ($this->tokens[$i]['code'] === T_CLOSE_USE_GROUP) { + $start = $this->findPrevious(T_OPEN_USE_GROUP, ($i - 1)); + if ($start !== false) { + $i = $start; + } + }//end if + + if (isset(Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return 0; + + }//end findStartOfStatement() + + + /** + * Returns the position of the last non-whitespace token in a statement. + * + * @param int $start The position to start searching from in the token stack. + * @param int|string|array $ignore Token types that should not be considered stop points. + * + * @return int + */ + public function findEndOfStatement($start, $ignore=null) + { + $endTokens = [ + T_COLON => true, + T_COMMA => true, + T_DOUBLE_ARROW => true, + T_SEMICOLON => true, + T_CLOSE_PARENTHESIS => true, + T_CLOSE_SQUARE_BRACKET => true, + T_CLOSE_CURLY_BRACKET => true, + T_CLOSE_SHORT_ARRAY => true, + T_OPEN_TAG => true, + T_CLOSE_TAG => true, + ]; + + if ($ignore !== null) { + $ignore = (array) $ignore; + foreach ($ignore as $code) { + unset($endTokens[$code]); + } + } + + // If the start token is inside the case part of a match expression, + // advance to the match arrow and continue looking for the + // end of the statement from there so that we skip over commas. + if ($this->tokens[$start]['code'] !== T_MATCH_ARROW) { + $matchExpression = $this->getCondition($start, T_MATCH); + if ($matchExpression !== false) { + $beforeArrow = true; + $prevMatchArrow = $this->findPrevious(T_MATCH_ARROW, ($start - 1), $this->tokens[$matchExpression]['scope_opener']); + if ($prevMatchArrow !== false) { + $prevComma = $this->findNext(T_COMMA, ($prevMatchArrow + 1), $start); + if ($prevComma === false) { + // No comma between this token and the last match arrow, + // so this token exists after the arrow and we can continue + // checking as normal. + $beforeArrow = false; + } + } + + if ($beforeArrow === true) { + $nextMatchArrow = $this->findNext(T_MATCH_ARROW, ($start + 1), $this->tokens[$matchExpression]['scope_closer']); + if ($nextMatchArrow !== false) { + $start = $nextMatchArrow; + } + } + }//end if + }//end if + + $lastNotEmpty = $start; + for ($i = $start; $i < $this->numTokens; $i++) { + if ($i !== $start && isset($endTokens[$this->tokens[$i]['code']]) === true) { + // Found the end of the statement. + if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS + || $this->tokens[$i]['code'] === T_CLOSE_SQUARE_BRACKET + || $this->tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + || $this->tokens[$i]['code'] === T_CLOSE_SHORT_ARRAY + || $this->tokens[$i]['code'] === T_OPEN_TAG + || $this->tokens[$i]['code'] === T_CLOSE_TAG + ) { + return $lastNotEmpty; + } + + return $i; + } + + // Skip nested statements. + if (isset($this->tokens[$i]['scope_closer']) === true + && ($i === $this->tokens[$i]['scope_opener'] + || $i === $this->tokens[$i]['scope_condition']) + ) { + if ($this->tokens[$i]['code'] === T_FN) { + $lastNotEmpty = $this->tokens[$i]['scope_closer']; + $i = ($this->tokens[$i]['scope_closer'] - 1); + continue; + } + + if ($i === $start && isset(Tokens::$scopeOpeners[$this->tokens[$i]['code']]) === true) { + return $this->tokens[$i]['scope_closer']; + } + + $i = $this->tokens[$i]['scope_closer']; + } else if (isset($this->tokens[$i]['bracket_closer']) === true + && $i === $this->tokens[$i]['bracket_opener'] + ) { + $i = $this->tokens[$i]['bracket_closer']; + } else if (isset($this->tokens[$i]['parenthesis_closer']) === true + && $i === $this->tokens[$i]['parenthesis_opener'] + ) { + $i = $this->tokens[$i]['parenthesis_closer']; + } else if ($this->tokens[$i]['code'] === T_OPEN_USE_GROUP) { + $end = $this->findNext(T_CLOSE_USE_GROUP, ($i + 1)); + if ($end !== false) { + $i = $end; + } + }//end if + + if (isset(Tokens::$emptyTokens[$this->tokens[$i]['code']]) === false) { + $lastNotEmpty = $i; + } + }//end for + + return ($this->numTokens - 1); + + }//end findEndOfStatement() + + + /** + * Returns the position of the first token on a line, matching given type. + * + * Returns false if no token can be found. + * + * @param int|string|array $types The type(s) of tokens to search for. + * @param int $start The position to start searching from in the + * token stack. + * @param bool $exclude If true, find the token that is NOT of + * the types specified in $types. + * @param string $value The value that the token must be equal to. + * If value is omitted, tokens with any value will + * be returned. + * + * @return int|false The first token which matches on the line containing the start + * token, between the start of the line and the start token. + * Note: The first token matching might be the start token. + * FALSE when no matching token could be found between the start of + * the line and the start token. + */ + public function findFirstOnLine($types, $start, $exclude=false, $value=null) + { + if (is_array($types) === false) { + $types = [$types]; + } + + $foundToken = false; + + for ($i = $start; $i >= 0; $i--) { + if ($this->tokens[$i]['line'] < $this->tokens[$start]['line']) { + break; + } + + $found = $exclude; + foreach ($types as $type) { + if ($exclude === false) { + if ($this->tokens[$i]['code'] === $type) { + $found = true; + break; + } + } else { + if ($this->tokens[$i]['code'] === $type) { + $found = false; + break; + } + } + } + + if ($found === true) { + if ($value === null) { + $foundToken = $i; + } else if ($this->tokens[$i]['content'] === $value) { + $foundToken = $i; + } + } + }//end for + + return $foundToken; + + }//end findFirstOnLine() + + + /** + * Determine if the passed token has a condition of one of the passed types. + * + * @param int $stackPtr The position of the token we are checking. + * @param int|string|array $types The type(s) of tokens to search for. + * + * @return boolean + */ + public function hasCondition($stackPtr, $types) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + // Make sure the token has conditions. + if (empty($this->tokens[$stackPtr]['conditions']) === true) { + return false; + } + + $types = (array) $types; + $conditions = $this->tokens[$stackPtr]['conditions']; + + foreach ($types as $type) { + if (in_array($type, $conditions, true) === true) { + // We found a token with the required type. + return true; + } + } + + return false; + + }//end hasCondition() + + + /** + * Return the position of the condition for the passed token. + * + * Returns FALSE if the token does not have the condition. + * + * @param int $stackPtr The position of the token we are checking. + * @param int|string $type The type of token to search for. + * @param bool $first If TRUE, will return the matched condition + * furthest away from the passed token. + * If FALSE, will return the matched condition + * closest to the passed token. + * + * @return int|false + */ + public function getCondition($stackPtr, $type, $first=true) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + // Make sure the token has conditions. + if (empty($this->tokens[$stackPtr]['conditions']) === true) { + return false; + } + + $conditions = $this->tokens[$stackPtr]['conditions']; + if ($first === false) { + $conditions = array_reverse($conditions, true); + } + + foreach ($conditions as $token => $condition) { + if ($condition === $type) { + return $token; + } + } + + return false; + + }//end getCondition() + + + /** + * Returns the name of the class that the specified class extends. + * (works for classes, anonymous classes and interfaces) + * + * Returns FALSE on error or if there is no extended class name. + * + * @param int $stackPtr The stack position of the class. + * + * @return string|false + */ + public function findExtendedClassName($stackPtr) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + if ($this->tokens[$stackPtr]['code'] !== T_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ANON_CLASS + && $this->tokens[$stackPtr]['code'] !== T_INTERFACE + ) { + return false; + } + + if (isset($this->tokens[$stackPtr]['scope_opener']) === false) { + return false; + } + + $classOpenerIndex = $this->tokens[$stackPtr]['scope_opener']; + $extendsIndex = $this->findNext(T_EXTENDS, $stackPtr, $classOpenerIndex); + if ($extendsIndex === false) { + return false; + } + + $find = [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + ]; + + $end = $this->findNext($find, ($extendsIndex + 1), ($classOpenerIndex + 1), true); + $name = $this->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } + + return $name; + + }//end findExtendedClassName() + + + /** + * Returns the names of the interfaces that the specified class or enum implements. + * + * Returns FALSE on error or if there are no implemented interface names. + * + * @param int $stackPtr The stack position of the class or enum token. + * + * @return array|false + */ + public function findImplementedInterfaceNames($stackPtr) + { + // Check for the existence of the token. + if (isset($this->tokens[$stackPtr]) === false) { + return false; + } + + if ($this->tokens[$stackPtr]['code'] !== T_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ANON_CLASS + && $this->tokens[$stackPtr]['code'] !== T_ENUM + ) { + return false; + } + + if (isset($this->tokens[$stackPtr]['scope_closer']) === false) { + return false; + } + + $classOpenerIndex = $this->tokens[$stackPtr]['scope_opener']; + $implementsIndex = $this->findNext(T_IMPLEMENTS, $stackPtr, $classOpenerIndex); + if ($implementsIndex === false) { + return false; + } + + $find = [ + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + T_COMMA, + ]; + + $end = $this->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true); + $name = $this->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1)); + $name = trim($name); + + if ($name === '') { + return false; + } else { + $names = explode(',', $name); + $names = array_map('trim', $names); + return $names; + } + + }//end findImplementedInterfaceNames() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php new file mode 100644 index 000000000..ab52e3388 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/FileList.php @@ -0,0 +1,261 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use Countable; +use FilesystemIterator; +use Iterator; +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Util\Common; +use RecursiveArrayIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use ReturnTypeWillChange; + +class FileList implements Iterator, Countable +{ + + /** + * A list of file paths that are included in the list. + * + * @var array + */ + private $files = []; + + /** + * The number of files in the list. + * + * @var integer + */ + private $numFiles = 0; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * An array of patterns to use for skipping files. + * + * @var array + */ + protected $ignorePatterns = []; + + + /** + * Constructs a file list and loads in an array of file paths to process. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @return void + */ + public function __construct(Config $config, Ruleset $ruleset) + { + $this->ruleset = $ruleset; + $this->config = $config; + + $paths = $config->files; + foreach ($paths as $path) { + $isPharFile = Common::isPharFile($path); + if (is_dir($path) === true || $isPharFile === true) { + if ($isPharFile === true) { + $path = 'phar://'.$path; + } + + $filterClass = $this->getFilterClass(); + + $di = new RecursiveDirectoryIterator($path, (RecursiveDirectoryIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS)); + $filter = new $filterClass($di, $path, $config, $ruleset); + $iterator = new RecursiveIteratorIterator($filter); + + foreach ($iterator as $file) { + $this->files[$file->getPathname()] = null; + $this->numFiles++; + } + } else { + $this->addFile($path); + }//end if + }//end foreach + + reset($this->files); + + }//end __construct() + + + /** + * Add a file to the list. + * + * If a file object has already been created, it can be passed here. + * If it is left NULL, it will be created when accessed. + * + * @param string $path The path to the file being added. + * @param \PHP_CodeSniffer\Files\File $file The file being added. + * + * @return void + */ + public function addFile($path, $file=null) + { + // No filtering is done for STDIN when the filename + // has not been specified. + if ($path === 'STDIN') { + $this->files[$path] = $file; + $this->numFiles++; + return; + } + + $filterClass = $this->getFilterClass(); + + $di = new RecursiveArrayIterator([$path]); + $filter = new $filterClass($di, $path, $this->config, $this->ruleset); + $iterator = new RecursiveIteratorIterator($filter); + + foreach ($iterator as $path) { + $this->files[$path] = $file; + $this->numFiles++; + } + + }//end addFile() + + + /** + * Get the class name of the filter being used for the run. + * + * @return string + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the specified filter could not be found. + */ + private function getFilterClass() + { + $filterType = $this->config->filter; + + if ($filterType === null) { + $filterClass = '\PHP_CodeSniffer\Filters\Filter'; + } else { + if (strpos($filterType, '.') !== false) { + // This is a path to a custom filter class. + $filename = realpath($filterType); + if ($filename === false) { + $error = "ERROR: Custom filter \"$filterType\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $filterClass = Autoload::loadFile($filename); + } else { + $filterClass = '\PHP_CodeSniffer\Filters\\'.$filterType; + } + } + + return $filterClass; + + }//end getFilterClass() + + + /** + * Rewind the iterator to the first file. + * + * @return void + */ + #[ReturnTypeWillChange] + public function rewind() + { + reset($this->files); + + }//end rewind() + + + /** + * Get the file that is currently being processed. + * + * @return \PHP_CodeSniffer\Files\File + */ + #[ReturnTypeWillChange] + public function current() + { + $path = key($this->files); + if (isset($this->files[$path]) === false) { + $this->files[$path] = new LocalFile($path, $this->ruleset, $this->config); + } + + return $this->files[$path]; + + }//end current() + + + /** + * Return the file path of the current file being processed. + * + * @return string|null Path name or `null` when the end of the iterator has been reached. + */ + #[ReturnTypeWillChange] + public function key() + { + return key($this->files); + + }//end key() + + + /** + * Move forward to the next file. + * + * @return void + */ + #[ReturnTypeWillChange] + public function next() + { + next($this->files); + + }//end next() + + + /** + * Checks if current position is valid. + * + * @return boolean + */ + #[ReturnTypeWillChange] + public function valid() + { + if (current($this->files) === false) { + return false; + } + + return true; + + }//end valid() + + + /** + * Return the number of files in the list. + * + * @return integer + */ + #[ReturnTypeWillChange] + public function count() + { + return $this->numFiles; + + }//end count() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php new file mode 100644 index 000000000..babfe69c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Files/LocalFile.php @@ -0,0 +1,219 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Files; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Util\Cache; +use PHP_CodeSniffer\Util\Common; + +class LocalFile extends File +{ + + + /** + * Creates a LocalFile object and sets the content. + * + * @param string $path The absolute path to the file. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function __construct($path, Ruleset $ruleset, Config $config) + { + $this->path = trim($path); + if (Common::isReadable($this->path) === false) { + parent::__construct($this->path, $ruleset, $config); + $error = 'Error opening file; file no longer exists or you do not have access to read the file'; + $this->addMessage(true, $error, 1, 1, 'Internal.LocalFile', [], 5, false); + $this->ignored = true; + return; + } + + // Before we go and spend time tokenizing this file, just check + // to see if there is a tag up top to indicate that the whole + // file should be ignored. It must be on one of the first two lines. + if ($config->annotations === true) { + $handle = fopen($this->path, 'r'); + if ($handle !== false) { + $firstContent = fgets($handle); + $firstContent .= fgets($handle); + fclose($handle); + + if (strpos($firstContent, '@codingStandardsIgnoreFile') !== false + || stripos($firstContent, 'phpcs:ignorefile') !== false + ) { + // We are ignoring the whole file. + $this->ignored = true; + return; + } + } + } + + $this->reloadContent(); + + parent::__construct($this->path, $ruleset, $config); + + }//end __construct() + + + /** + * Loads the latest version of the file's content from the file system. + * + * @return void + */ + public function reloadContent() + { + $this->setContent(file_get_contents($this->path)); + + }//end reloadContent() + + + /** + * Processes the file. + * + * @return void + */ + public function process() + { + if ($this->ignored === true) { + return; + } + + if ($this->configCache['cache'] === false) { + parent::process(); + return; + } + + $hash = md5_file($this->path); + $hash .= fileperms($this->path); + $cache = Cache::get($this->path); + if ($cache !== false && $cache['hash'] === $hash) { + // We can't filter metrics, so just load all of them. + $this->metrics = $cache['metrics']; + + if ($this->configCache['recordErrors'] === true) { + // Replay the cached errors and warnings to filter out the ones + // we don't need for this specific run. + $this->configCache['cache'] = false; + $this->replayErrors($cache['errors'], $cache['warnings']); + $this->configCache['cache'] = true; + } else { + $this->errorCount = $cache['errorCount']; + $this->warningCount = $cache['warningCount']; + $this->fixableCount = $cache['fixableCount']; + } + + if (PHP_CODESNIFFER_VERBOSITY > 0 + || (PHP_CODESNIFFER_CBF === true && empty($this->config->files) === false) + ) { + echo "[loaded from cache]... "; + } + + $this->numTokens = $cache['numTokens']; + $this->fromCache = true; + return; + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + + parent::process(); + + $cache = [ + 'hash' => $hash, + 'errors' => $this->errors, + 'warnings' => $this->warnings, + 'metrics' => $this->metrics, + 'errorCount' => $this->errorCount, + 'warningCount' => $this->warningCount, + 'fixableCount' => $this->fixableCount, + 'numTokens' => $this->numTokens, + ]; + + Cache::set($this->path, $cache); + + // During caching, we don't filter out errors in any way, so + // we need to do that manually now by replaying them. + if ($this->configCache['recordErrors'] === true) { + $this->configCache['cache'] = false; + $this->replayErrors($this->errors, $this->warnings); + $this->configCache['cache'] = true; + } + + }//end process() + + + /** + * Clears and replays error and warnings for the file. + * + * Replaying errors and warnings allows for filtering rules to be changed + * and then errors and warnings to be reapplied with the new rules. This is + * particularly useful while caching. + * + * @param array $errors The list of errors to replay. + * @param array $warnings The list of warnings to replay. + * + * @return void + */ + private function replayErrors($errors, $warnings) + { + $this->errors = []; + $this->warnings = []; + $this->errorCount = 0; + $this->warningCount = 0; + $this->fixableCount = 0; + + $this->replayingErrors = true; + + foreach ($errors as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $this->activeListener = $error['listener']; + $this->addMessage( + true, + $error['message'], + $line, + $column, + $error['source'], + [], + $error['severity'], + $error['fixable'] + ); + } + } + } + + foreach ($warnings as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $this->activeListener = $error['listener']; + $this->addMessage( + false, + $error['message'], + $line, + $column, + $error['source'], + [], + $error['severity'], + $error['fixable'] + ); + } + } + } + + $this->replayingErrors = false; + + }//end replayErrors() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php new file mode 100644 index 000000000..89517b838 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/ExactMatch.php @@ -0,0 +1,156 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util\Common; + +abstract class ExactMatch extends Filter +{ + + /** + * A list of files to exclude. + * + * @var array + */ + private $disallowedFiles = null; + + /** + * A list of files to include. + * + * If the allowed files list is empty, only files in the disallowed files list will be excluded. + * + * @var array + */ + private $allowedFiles = null; + + + /** + * Check whether the current element of the iterator is acceptable. + * + * If a file is both disallowed and allowed, it will be deemed unacceptable. + * + * @return bool + */ + public function accept() + { + if (parent::accept() === false) { + return false; + } + + if ($this->disallowedFiles === null) { + $this->disallowedFiles = $this->getDisallowedFiles(); + + // BC-layer. + if ($this->disallowedFiles === null) { + $this->disallowedFiles = $this->getBlacklist(); + } + } + + if ($this->allowedFiles === null) { + $this->allowedFiles = $this->getAllowedFiles(); + + // BC-layer. + if ($this->allowedFiles === null) { + $this->allowedFiles = $this->getWhitelist(); + } + } + + $filePath = Common::realpath($this->current()); + + // If a file is both disallowed and allowed, the disallowed files list takes precedence. + if (isset($this->disallowedFiles[$filePath]) === true) { + return false; + } + + if (empty($this->allowedFiles) === true && empty($this->disallowedFiles) === false) { + // We are only checking the disallowed files list, so everything else should be allowed. + return true; + } + + return isset($this->allowedFiles[$filePath]); + + }//end accept() + + + /** + * Returns an iterator for the current entry. + * + * Ensures that the disallowed files list and the allowed files list are preserved so they don't have + * to be generated each time. + * + * @return \RecursiveIterator + */ + public function getChildren() + { + $children = parent::getChildren(); + $children->disallowedFiles = $this->disallowedFiles; + $children->allowedFiles = $this->allowedFiles; + return $children; + + }//end getChildren() + + + /** + * Get a list of file paths to exclude. + * + * @deprecated 3.9.0 Implement the `getDisallowedFiles()` method instead. + * The `getDisallowedFiles()` method will be made abstract and therefore required + * in v4.0 and this method will be removed. + * If both methods are implemented, the new `getDisallowedFiles()` method will take precedence. + * + * @return array + */ + abstract protected function getBlacklist(); + + + /** + * Get a list of file paths to include. + * + * @deprecated 3.9.0 Implement the `getAllowedFiles()` method instead. + * The `getAllowedFiles()` method will be made abstract and therefore required + * in v4.0 and this method will be removed. + * If both methods are implemented, the new `getAllowedFiles()` method will take precedence. + * + * @return array + */ + abstract protected function getWhitelist(); + + + /** + * Get a list of file paths to exclude. + * + * @since 3.9.0 Replaces the deprecated `getBlacklist()` method. + * + * @return array|null + */ + protected function getDisallowedFiles() + { + return null; + + }//end getDisallowedFiles() + + + /** + * Get a list of file paths to include. + * + * @since 3.9.0 Replaces the deprecated `getWhitelist()` method. + * + * @return array|null + */ + protected function getAllowedFiles() + { + return null; + + }//end getAllowedFiles() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php new file mode 100644 index 000000000..8376d15c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/Filter.php @@ -0,0 +1,288 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use FilesystemIterator; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Util\Common; +use RecursiveDirectoryIterator; +use RecursiveFilterIterator; +use ReturnTypeWillChange; + +class Filter extends RecursiveFilterIterator +{ + + /** + * The top-level path we are filtering. + * + * @var string + */ + protected $basedir = null; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + protected $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset = null; + + /** + * A list of ignore patterns that apply to directories only. + * + * @var array + */ + protected $ignoreDirPatterns = null; + + /** + * A list of ignore patterns that apply to files only. + * + * @var array + */ + protected $ignoreFilePatterns = null; + + /** + * A list of file paths we've already accepted. + * + * Used to ensure we aren't following circular symlinks. + * + * @var array + */ + protected $acceptedPaths = []; + + + /** + * Constructs a filter. + * + * @param \RecursiveIterator $iterator The iterator we are using to get file paths. + * @param string $basedir The top-level path we are filtering. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @return void + */ + public function __construct($iterator, $basedir, Config $config, Ruleset $ruleset) + { + parent::__construct($iterator); + $this->basedir = $basedir; + $this->config = $config; + $this->ruleset = $ruleset; + + }//end __construct() + + + /** + * Check whether the current element of the iterator is acceptable. + * + * Files are checked for allowed extensions and ignore patterns. + * Directories are checked for ignore patterns only. + * + * @return bool + */ + #[ReturnTypeWillChange] + public function accept() + { + $filePath = $this->current(); + $realPath = Common::realpath($filePath); + + if ($realPath !== false) { + // It's a real path somewhere, so record it + // to check for circular symlinks. + if (isset($this->acceptedPaths[$realPath]) === true) { + // We've been here before. + return false; + } + } + + $filePath = $this->current(); + if (is_dir($filePath) === true) { + if ($this->config->local === true) { + return false; + } + } else if ($this->shouldProcessFile($filePath) === false) { + return false; + } + + if ($this->shouldIgnorePath($filePath) === true) { + return false; + } + + $this->acceptedPaths[$realPath] = true; + return true; + + }//end accept() + + + /** + * Returns an iterator for the current entry. + * + * Ensures that the ignore patterns are preserved so they don't have + * to be generated each time. + * + * @return \RecursiveIterator + */ + #[ReturnTypeWillChange] + public function getChildren() + { + $filterClass = get_called_class(); + $children = new $filterClass( + new RecursiveDirectoryIterator($this->current(), (RecursiveDirectoryIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS)), + $this->basedir, + $this->config, + $this->ruleset + ); + + // Set the ignore patterns so we don't have to generate them again. + $children->ignoreDirPatterns = $this->ignoreDirPatterns; + $children->ignoreFilePatterns = $this->ignoreFilePatterns; + $children->acceptedPaths = $this->acceptedPaths; + return $children; + + }//end getChildren() + + + /** + * Checks filtering rules to see if a file should be checked. + * + * Checks both file extension filters and path ignore filters. + * + * @param string $path The path to the file being checked. + * + * @return bool + */ + protected function shouldProcessFile($path) + { + // Check that the file's extension is one we are checking. + // We are strict about checking the extension and we don't + // let files through with no extension or that start with a dot. + $fileName = basename($path); + $fileParts = explode('.', $fileName); + if ($fileParts[0] === $fileName || $fileParts[0] === '') { + return false; + } + + // Checking multi-part file extensions, so need to create a + // complete extension list and make sure one is allowed. + $extensions = []; + array_shift($fileParts); + while (empty($fileParts) === false) { + $extensions[implode('.', $fileParts)] = 1; + array_shift($fileParts); + } + + $matches = array_intersect_key($extensions, $this->config->extensions); + if (empty($matches) === true) { + return false; + } + + return true; + + }//end shouldProcessFile() + + + /** + * Checks filtering rules to see if a path should be ignored. + * + * @param string $path The path to the file or directory being checked. + * + * @return bool + */ + protected function shouldIgnorePath($path) + { + if ($this->ignoreFilePatterns === null) { + $this->ignoreDirPatterns = []; + $this->ignoreFilePatterns = []; + + $ignorePatterns = $this->config->ignored; + $rulesetIgnorePatterns = $this->ruleset->getIgnorePatterns(); + foreach ($rulesetIgnorePatterns as $pattern => $type) { + // Ignore standard/sniff specific exclude rules. + if (is_array($type) === true) { + continue; + } + + $ignorePatterns[$pattern] = $type; + } + + foreach ($ignorePatterns as $pattern => $type) { + // If the ignore pattern ends with /* then it is ignoring an entire directory. + if (substr($pattern, -2) === '/*') { + // Need to check this pattern for dirs as well as individual file paths. + $this->ignoreFilePatterns[$pattern] = $type; + + $pattern = substr($pattern, 0, -2).'(?=/|$)'; + $this->ignoreDirPatterns[$pattern] = $type; + } else { + // This is a file-specific pattern, so only need to check this + // for individual file paths. + $this->ignoreFilePatterns[$pattern] = $type; + } + } + }//end if + + $relativePath = $path; + if (strpos($path, $this->basedir) === 0) { + // The +1 cuts off the directory separator as well. + $relativePath = substr($path, (strlen($this->basedir) + 1)); + } + + if (is_dir($path) === true) { + $ignorePatterns = $this->ignoreDirPatterns; + } else { + $ignorePatterns = $this->ignoreFilePatterns; + } + + foreach ($ignorePatterns as $pattern => $type) { + // Maintains backwards compatibility in case the ignore pattern does + // not have a relative/absolute value. + if (is_int($pattern) === true) { + $pattern = $type; + $type = 'absolute'; + } + + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + // We assume a / directory separator, as do the exclude rules + // most developers write, so we need a special case for any system + // that is different. + if (DIRECTORY_SEPARATOR === '\\') { + $replacements['/'] = '\\\\'; + } + + $pattern = strtr($pattern, $replacements); + + if ($type === 'relative') { + $testPath = $relativePath; + } else { + $testPath = $path; + } + + $pattern = '`'.$pattern.'`i'; + if (preg_match($pattern, $testPath) === 1) { + return true; + } + }//end foreach + + return false; + + }//end shouldIgnorePath() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php new file mode 100644 index 000000000..3337287b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitModified.php @@ -0,0 +1,124 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util\Common; + +class GitModified extends ExactMatch +{ + + + /** + * Get a list of file paths to exclude. + * + * @since 3.9.0 + * + * @return array + */ + protected function getDisallowedFiles() + { + return []; + + }//end getDisallowedFiles() + + + /** + * Get a list of file paths to exclude. + * + * @deprecated 3.9.0 Overload the `getDisallowedFiles()` method instead. + * + * @codeCoverageIgnore + * + * @return array + */ + protected function getBlacklist() + { + return $this->getDisallowedFiles(); + + }//end getBlacklist() + + + /** + * Get a list of file paths to include. + * + * @since 3.9.0 + * + * @return array + */ + protected function getAllowedFiles() + { + $modified = []; + + $cmd = 'git ls-files -o -m --exclude-standard -- '.escapeshellarg($this->basedir); + $output = $this->exec($cmd); + + $basedir = $this->basedir; + if (is_dir($basedir) === false) { + $basedir = dirname($basedir); + } + + foreach ($output as $path) { + $path = Common::realpath($path); + + if ($path === false) { + continue; + } + + do { + $modified[$path] = true; + $path = dirname($path); + } while ($path !== $basedir); + } + + return $modified; + + }//end getAllowedFiles() + + + /** + * Get a list of file paths to include. + * + * @deprecated 3.9.0 Overload the `getAllowedFiles()` method instead. + * + * @codeCoverageIgnore + * + * @return array + */ + protected function getWhitelist() + { + return $this->getAllowedFiles(); + + }//end getWhitelist() + + + /** + * Execute an external command. + * + * {@internal This method is only needed to allow for mocking the return value + * to test the class logic.} + * + * @param string $cmd Command. + * + * @return array + */ + protected function exec($cmd) + { + $output = []; + $lastLine = exec($cmd, $output); + if ($lastLine === false) { + return []; + } + + return $output; + + }//end exec() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php new file mode 100644 index 000000000..7a764314a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Filters/GitStaged.php @@ -0,0 +1,126 @@ + + * @copyright 2018 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Filters; + +use PHP_CodeSniffer\Util\Common; + +class GitStaged extends ExactMatch +{ + + + /** + * Get a list of file paths to exclude. + * + * @since 3.9.0 + * + * @return array + */ + protected function getDisallowedFiles() + { + return []; + + }//end getDisallowedFiles() + + + /** + * Get a list of file paths to exclude. + * + * @deprecated 3.9.0 Overload the `getDisallowedFiles()` method instead. + * + * @codeCoverageIgnore + * + * @return array + */ + protected function getBlacklist() + { + return $this->getDisallowedFiles(); + + }//end getBlacklist() + + + /** + * Get a list of file paths to include. + * + * @since 3.9.0 + * + * @return array + */ + protected function getAllowedFiles() + { + $modified = []; + + $cmd = 'git diff --cached --name-only -- '.escapeshellarg($this->basedir); + $output = $this->exec($cmd); + + $basedir = $this->basedir; + if (is_dir($basedir) === false) { + $basedir = dirname($basedir); + } + + foreach ($output as $path) { + $path = Common::realpath($path); + if ($path === false) { + // Skip deleted files. + continue; + } + + do { + $modified[$path] = true; + $path = dirname($path); + } while ($path !== $basedir); + } + + return $modified; + + }//end getAllowedFiles() + + + /** + * Get a list of file paths to include. + * + * @deprecated 3.9.0 Overload the `getAllowedFiles()` method instead. + * + * @codeCoverageIgnore + * + * @return array + */ + protected function getWhitelist() + { + return $this->getAllowedFiles(); + + }//end getWhitelist() + + + /** + * Execute an external command. + * + * {@internal This method is only needed to allow for mocking the return value + * to test the class logic.} + * + * @param string $cmd Command. + * + * @return array + */ + protected function exec($cmd) + { + $output = []; + $lastLine = exec($cmd, $output); + if ($lastLine === false) { + return []; + } + + return $output; + + }//end exec() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Fixer.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Fixer.php new file mode 100644 index 000000000..b429825f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Fixer.php @@ -0,0 +1,846 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; + +class Fixer +{ + + /** + * Is the fixer enabled and fixing a file? + * + * Sniffs should check this value to ensure they are not + * doing extra processing to prepare for a fix when fixing is + * not required. + * + * @var boolean + */ + public $enabled = false; + + /** + * The number of times we have looped over a file. + * + * @var integer + */ + public $loops = 0; + + /** + * The file being fixed. + * + * @var \PHP_CodeSniffer\Files\File + */ + private $currentFile = null; + + /** + * The list of tokens that make up the file contents. + * + * This is a simplified list which just contains the token content and nothing + * else. This is the array that is updated as fixes are made, not the file's + * token array. Imploding this array will give you the file content back. + * + * @var array + */ + private $tokens = []; + + /** + * A list of tokens that have already been fixed. + * + * We don't allow the same token to be fixed more than once each time + * through a file as this can easily cause conflicts between sniffs. + * + * @var int[] + */ + private $fixedTokens = []; + + /** + * The last value of each fixed token. + * + * If a token is being "fixed" back to its last value, the fix is + * probably conflicting with another. + * + * @var array> + */ + private $oldTokenValues = []; + + /** + * A list of tokens that have been fixed during a changeset. + * + * All changes in changeset must be able to be applied, or else + * the entire changeset is rejected. + * + * @var array + */ + private $changeset = []; + + /** + * Is there an open changeset. + * + * @var boolean + */ + private $inChangeset = false; + + /** + * Is the current fixing loop in conflict? + * + * @var boolean + */ + private $inConflict = false; + + /** + * The number of fixes that have been performed. + * + * @var integer + */ + private $numFixes = 0; + + + /** + * Starts fixing a new file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being fixed. + * + * @return void + */ + public function startFile(File $phpcsFile) + { + $this->currentFile = $phpcsFile; + $this->numFixes = 0; + $this->fixedTokens = []; + + $tokens = $phpcsFile->getTokens(); + $this->tokens = []; + foreach ($tokens as $index => $token) { + if (isset($token['orig_content']) === true) { + $this->tokens[$index] = $token['orig_content']; + } else { + $this->tokens[$index] = $token['content']; + } + } + + }//end startFile() + + + /** + * Attempt to fix the file by processing it until no fixes are made. + * + * @return boolean + */ + public function fixFile() + { + $fixable = $this->currentFile->getFixableCount(); + if ($fixable === 0) { + // Nothing to fix. + return false; + } + + $this->enabled = true; + + $this->loops = 0; + while ($this->loops < 50) { + ob_start(); + + // Only needed once file content has changed. + $contents = $this->getContents(); + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + @ob_end_clean(); + echo '---START FILE CONTENT---'.PHP_EOL; + $lines = explode($this->currentFile->eolChar, $contents); + $max = strlen(count($lines)); + foreach ($lines as $lineNum => $line) { + $lineNum++; + echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL; + } + + echo '--- END FILE CONTENT ---'.PHP_EOL; + ob_start(); + } + + $this->inConflict = false; + $this->currentFile->ruleset->populateTokenListeners(); + $this->currentFile->setContent($contents); + $this->currentFile->process(); + ob_end_clean(); + + $this->loops++; + + if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) { + echo "\r".str_repeat(' ', 80)."\r"; + echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass"; + if ($this->loops > 1) { + echo 'es'; + } + + echo ']... '; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + if ($this->numFixes === 0 && $this->inConflict === false) { + // Nothing left to do. + break; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL; + } + }//end while + + $this->enabled = false; + + if ($this->numFixes > 0) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if (ob_get_level() > 0) { + ob_end_clean(); + } + + echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL; + ob_start(); + } + + return false; + } + + return true; + + }//end fixFile() + + + /** + * Generates a text diff of the original file and the new content. + * + * @param string $filePath Optional file path to diff the file against. + * If not specified, the original version of the + * file will be used. + * @param boolean $colors Print coloured output or not. + * + * @return string + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException When the diff command fails. + */ + public function generateDiff($filePath=null, $colors=true) + { + if ($filePath === null) { + $filePath = $this->currentFile->getFilename(); + } + + $cwd = getcwd().DIRECTORY_SEPARATOR; + if (strpos($filePath, $cwd) === 0) { + $filename = substr($filePath, strlen($cwd)); + } else { + $filename = $filePath; + } + + $contents = $this->getContents(); + + $tempName = tempnam(sys_get_temp_dir(), 'phpcs-fixer'); + $fixedFile = fopen($tempName, 'w'); + fwrite($fixedFile, $contents); + + // We must use something like shell_exec() or proc_open() because whitespace at the end + // of lines is critical to diff files. + // Using proc_open() instead of shell_exec improves performance on Windows significantly, + // while the results are the same (though more code is needed to get the results). + // This is specifically due to proc_open allowing to set the "bypass_shell" option. + $filename = escapeshellarg($filename); + $cmd = "diff -u -L$filename -LPHP_CodeSniffer $filename \"$tempName\""; + + // Stream 0 = STDIN, 1 = STDOUT, 2 = STDERR. + $descriptorspec = [ + 0 => [ + 'pipe', + 'r', + ], + 1 => [ + 'pipe', + 'w', + ], + 2 => [ + 'pipe', + 'w', + ], + ]; + + $options = null; + if (stripos(PHP_OS, 'WIN') === 0) { + $options = ['bypass_shell' => true]; + } + + $process = proc_open($cmd, $descriptorspec, $pipes, $cwd, null, $options); + if (is_resource($process) === false) { + throw new RuntimeException('Could not obtain a resource to execute the diff command.'); + } + + // We don't need these. + fclose($pipes[0]); + fclose($pipes[2]); + + // Stdout will contain the actual diff. + $diff = stream_get_contents($pipes[1]); + fclose($pipes[1]); + + proc_close($process); + + fclose($fixedFile); + if (is_file($tempName) === true) { + unlink($tempName); + } + + if ($diff === false || $diff === '') { + return ''; + } + + if ($colors === false) { + return $diff; + } + + $diffLines = explode(PHP_EOL, $diff); + if (count($diffLines) === 1) { + // Seems to be required for cygwin. + $diffLines = explode("\n", $diff); + } + + $diff = []; + foreach ($diffLines as $line) { + if (isset($line[0]) === true) { + switch ($line[0]) { + case '-': + $diff[] = "\033[31m$line\033[0m"; + break; + case '+': + $diff[] = "\033[32m$line\033[0m"; + break; + default: + $diff[] = $line; + } + } + } + + $diff = implode(PHP_EOL, $diff); + + return $diff; + + }//end generateDiff() + + + /** + * Get a count of fixes that have been performed on the file. + * + * This value is reset every time a new file is started, or an existing + * file is restarted. + * + * @return int + */ + public function getFixCount() + { + return $this->numFixes; + + }//end getFixCount() + + + /** + * Get the current content of the file, as a string. + * + * @return string + */ + public function getContents() + { + $contents = implode($this->tokens); + return $contents; + + }//end getContents() + + + /** + * Get the current fixed content of a token. + * + * This function takes changesets into account so should be used + * instead of directly accessing the token array. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return string + */ + public function getTokenContent($stackPtr) + { + if ($this->inChangeset === true + && isset($this->changeset[$stackPtr]) === true + ) { + return $this->changeset[$stackPtr]; + } else { + return $this->tokens[$stackPtr]; + } + + }//end getTokenContent() + + + /** + * Start recording actions for a changeset. + * + * @return void|false + */ + public function beginChangeset() + { + if ($this->inConflict === true) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === __CLASS__) { + $sniff = 'Fixer'; + } else { + $sniff = Common::getSniffCode($bt[1]['class']); + } + + $line = $bt[0]['line']; + + @ob_end_clean(); + echo "\t=> Changeset started by $sniff:$line".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + $this->inChangeset = true; + + }//end beginChangeset() + + + /** + * Stop recording actions for a changeset, and apply logged changes. + * + * @return boolean + */ + public function endChangeset() + { + if ($this->inConflict === true) { + return false; + } + + $this->inChangeset = false; + + $success = true; + $applied = []; + foreach ($this->changeset as $stackPtr => $content) { + $success = $this->replaceToken($stackPtr, $content); + if ($success === false) { + break; + } else { + $applied[] = $stackPtr; + } + } + + if ($success === false) { + // Rolling back all changes. + foreach ($applied as $stackPtr) { + $this->revertToken($stackPtr); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "\t=> Changeset failed to apply".PHP_EOL; + ob_start(); + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + $fixes = count($this->changeset); + @ob_end_clean(); + echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + return true; + + }//end endChangeset() + + + /** + * Stop recording actions for a changeset, and discard logged changes. + * + * @return void + */ + public function rollbackChangeset() + { + $this->inChangeset = false; + $this->inConflict = false; + + if (empty($this->changeset) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Common::getSniffCode($sniff); + + $numChanges = count($this->changeset); + + @ob_end_clean(); + echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL; + echo "\t=> Changeset rolled back".PHP_EOL; + ob_start(); + } + + $this->changeset = []; + }//end if + + }//end rollbackChangeset() + + + /** + * Replace the entire contents of a token. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The new content of the token. + * + * @return bool If the change was accepted. + */ + public function replaceToken($stackPtr, $content) + { + if ($this->inConflict === true) { + return false; + } + + if ($this->inChangeset === false + && isset($this->fixedTokens[$stackPtr]) === true + ) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\t"; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL; + ob_start(); + } + + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Common::getSniffCode($sniff); + + $tokens = $this->currentFile->getTokens(); + $type = $tokens[$stackPtr]['type']; + $tokenLine = $tokens[$stackPtr]['line']; + $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]); + $newContent = Common::prepareForOutput($content); + if (trim($this->tokens[$stackPtr]) === '' && isset($this->tokens[($stackPtr + 1)]) === true) { + // Add some context for whitespace only changes. + $append = Common::prepareForOutput($this->tokens[($stackPtr + 1)]); + $oldContent .= $append; + $newContent .= $append; + } + }//end if + + if ($this->inChangeset === true) { + $this->changeset[$stackPtr] = $content; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + @ob_end_clean(); + echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + } + + if (isset($this->oldTokenValues[$stackPtr]) === false) { + $this->oldTokenValues[$stackPtr] = [ + 'curr' => $content, + 'prev' => $this->tokens[$stackPtr], + 'loop' => $this->loops, + ]; + } else { + if ($this->oldTokenValues[$stackPtr]['prev'] === $content + && $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\t"; + } + + $loop = $this->oldTokenValues[$stackPtr]['loop']; + + @ob_end_clean(); + echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL; + echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL; + } + + if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) { + $this->inConflict = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "$indent**** ignoring all changes until next loop ****".PHP_EOL; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + ob_start(); + } + + return false; + }//end if + + $this->oldTokenValues[$stackPtr]['prev'] = $this->oldTokenValues[$stackPtr]['curr']; + $this->oldTokenValues[$stackPtr]['curr'] = $content; + $this->oldTokenValues[$stackPtr]['loop'] = $this->loops; + }//end if + + $this->fixedTokens[$stackPtr] = $this->tokens[$stackPtr]; + $this->tokens[$stackPtr] = $content; + $this->numFixes++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\tA: "; + } + + if (ob_get_level() > 0) { + ob_end_clean(); + } + + echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + + }//end replaceToken() + + + /** + * Reverts the previous fix made to a token. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If a change was reverted. + */ + public function revertToken($stackPtr) + { + if (isset($this->fixedTokens[$stackPtr]) === false) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') { + $sniff = $bt[2]['class']; + $line = $bt[1]['line']; + } else { + $sniff = $bt[1]['class']; + $line = $bt[0]['line']; + } + + $sniff = Common::getSniffCode($sniff); + + $tokens = $this->currentFile->getTokens(); + $type = $tokens[$stackPtr]['type']; + $tokenLine = $tokens[$stackPtr]['line']; + $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]); + $newContent = Common::prepareForOutput($this->fixedTokens[$stackPtr]); + if (trim($this->tokens[$stackPtr]) === '' && isset($tokens[($stackPtr + 1)]) === true) { + // Add some context for whitespace only changes. + $append = Common::prepareForOutput($this->tokens[($stackPtr + 1)]); + $oldContent .= $append; + $newContent .= $append; + } + }//end if + + $this->tokens[$stackPtr] = $this->fixedTokens[$stackPtr]; + unset($this->fixedTokens[$stackPtr]); + $this->numFixes--; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $indent = "\t"; + if (empty($this->changeset) === false) { + $indent .= "\tR: "; + } + + @ob_end_clean(); + echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + ob_start(); + } + + return true; + + }//end revertToken() + + + /** + * Replace the content of a token with a part of its current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param int $start The first character to keep. + * @param int $length The number of characters to keep. If NULL, the content of + * the token from $start to the end of the content is kept. + * + * @return bool If the change was accepted. + */ + public function substrToken($stackPtr, $start, $length=null) + { + $current = $this->getTokenContent($stackPtr); + + if ($length === null) { + $newContent = substr($current, $start); + } else { + $newContent = substr($current, $start, $length); + } + + return $this->replaceToken($stackPtr, $newContent); + + }//end substrToken() + + + /** + * Adds a newline to end of a token's content. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If the change was accepted. + */ + public function addNewline($stackPtr) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $current.$this->currentFile->eolChar); + + }//end addNewline() + + + /** + * Adds a newline to the start of a token's content. + * + * @param int $stackPtr The position of the token in the token stack. + * + * @return bool If the change was accepted. + */ + public function addNewlineBefore($stackPtr) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $this->currentFile->eolChar.$current); + + }//end addNewlineBefore() + + + /** + * Adds content to the end of a token's current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The content to add. + * + * @return bool If the change was accepted. + */ + public function addContent($stackPtr, $content) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $current.$content); + + }//end addContent() + + + /** + * Adds content to the start of a token's current content. + * + * @param int $stackPtr The position of the token in the token stack. + * @param string $content The content to add. + * + * @return bool If the change was accepted. + */ + public function addContentBefore($stackPtr, $content) + { + $current = $this->getTokenContent($stackPtr); + return $this->replaceToken($stackPtr, $content.$current); + + }//end addContentBefore() + + + /** + * Adjust the indent of a code block. + * + * @param int $start The position of the token in the token stack + * to start adjusting the indent from. + * @param int $end The position of the token in the token stack + * to end adjusting the indent. + * @param int $change The number of spaces to adjust the indent by + * (positive or negative). + * + * @return void + */ + public function changeCodeBlockIndent($start, $end, $change) + { + $tokens = $this->currentFile->getTokens(); + + $baseIndent = ''; + if ($change > 0) { + $baseIndent = str_repeat(' ', $change); + } + + $useChangeset = false; + if ($this->inChangeset === false) { + $this->beginChangeset(); + $useChangeset = true; + } + + for ($i = $start; $i <= $end; $i++) { + if ($tokens[$i]['column'] !== 1 + || $tokens[($i + 1)]['line'] !== $tokens[$i]['line'] + ) { + continue; + } + + $length = 0; + if ($tokens[$i]['code'] === T_WHITESPACE + || $tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $length = $tokens[$i]['length']; + + $padding = ($length + $change); + if ($padding > 0) { + $padding = str_repeat(' ', $padding); + } else { + $padding = ''; + } + + $newContent = $padding.ltrim($tokens[$i]['content']); + } else { + $newContent = $baseIndent.$tokens[$i]['content']; + } + + $this->replaceToken($i, $newContent); + }//end for + + if ($useChangeset === true) { + $this->endChangeset(); + } + + }//end changeCodeBlockIndent() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php new file mode 100644 index 000000000..873ac3f3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Generator.php @@ -0,0 +1,128 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use DOMDocument; +use DOMNode; +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Ruleset; + +abstract class Generator +{ + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * XML documentation files used to produce the final output. + * + * @var string[] + */ + public $docFiles = []; + + + /** + * Constructs a doc generator. + * + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * + * @see generate() + */ + public function __construct(Ruleset $ruleset) + { + $this->ruleset = $ruleset; + + $find = [ + DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR, + 'Sniff.php', + ]; + $replace = [ + DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR, + 'Standard.xml', + ]; + + foreach ($ruleset->sniffs as $className => $sniffClass) { + $file = Autoload::getLoadedFileName($className); + $docFile = str_replace($find, $replace, $file); + + if (is_file($docFile) === true) { + $this->docFiles[] = $docFile; + } + } + + // Always present the docs in a consistent alphabetical order. + sort($this->docFiles, (SORT_NATURAL | SORT_FLAG_CASE)); + + }//end __construct() + + + /** + * Retrieves the title of the sniff from the DOMNode supplied. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return string + */ + protected function getTitle(DOMNode $doc) + { + return $doc->getAttribute('title'); + + }//end getTitle() + + + /** + * Generates the documentation for a standard. + * + * It's probably wise for doc generators to override this method so they + * have control over how the docs are produced. Otherwise, the processSniff + * method should be overridden to output content for each sniff. + * + * @return void + * @see processSniff() + */ + public function generate() + { + foreach ($this->docFiles as $file) { + $doc = new DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + }//end generate() + + + /** + * Process the documentation for a single sniff. + * + * Doc generators must implement this function to produce output. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + * @see generate() + */ + abstract protected function processSniff(DOMNode $doc); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php new file mode 100644 index 000000000..0fce7c99a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/HTML.php @@ -0,0 +1,284 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use DOMDocument; +use DOMNode; +use PHP_CodeSniffer\Config; + +class HTML extends Generator +{ + + /** + * Stylesheet for the HTML output. + * + * @var string + */ + const STYLESHEET = ''; + + + /** + * Generates the documentation for a standard. + * + * @return void + * @see processSniff() + */ + public function generate() + { + ob_start(); + $this->printHeader(); + $this->printToc(); + + foreach ($this->docFiles as $file) { + $doc = new DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + $this->printFooter(); + + $content = ob_get_contents(); + ob_end_clean(); + + echo $content; + + }//end generate() + + + /** + * Print the header of the HTML page. + * + * @return void + */ + protected function printHeader() + { + $standard = $this->ruleset->name; + echo ''.PHP_EOL; + echo ' '.PHP_EOL; + echo " $standard Coding Standards".PHP_EOL; + echo ' '.str_replace("\n", PHP_EOL, self::STYLESHEET).PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo "

    $standard Coding Standards

    ".PHP_EOL; + + }//end printHeader() + + + /** + * Print the table of contents for the standard. + * + * The TOC is just an unordered list of bookmarks to sniffs on the page. + * + * @return void + */ + protected function printToc() + { + echo '

    Table of Contents

    '.PHP_EOL; + echo '
      '.PHP_EOL; + + foreach ($this->docFiles as $file) { + $doc = new DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $title = $this->getTitle($documentation); + echo '
    • $title
    • ".PHP_EOL; + } + + echo '
    '.PHP_EOL; + + }//end printToc() + + + /** + * Print the footer of the HTML page. + * + * @return void + */ + protected function printFooter() + { + // Turn off errors so we don't get timezone warnings if people + // don't have their timezone set. + $errorLevel = error_reporting(0); + echo '
    '; + echo 'Documentation generated on '.date('r'); + echo ' by PHP_CodeSniffer '.Config::VERSION.''; + echo '
    '.PHP_EOL; + error_reporting($errorLevel); + + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + + }//end printFooter() + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + public function processSniff(DOMNode $doc) + { + $title = $this->getTitle($doc); + echo ' '.PHP_EOL; + echo "

    $title

    ".PHP_EOL; + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(DOMNode $node) + { + $content = trim($node->nodeValue); + $content = htmlspecialchars($content); + + // Use the correct line endings based on the OS. + $content = str_replace("\n", PHP_EOL, $content); + + // Allow em tags only. + $content = str_replace('<em>', '', $content); + $content = str_replace('</em>', '', $content); + + echo "

    $content

    ".PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + $first = trim($codeBlocks->item(0)->nodeValue); + $first = str_replace('', $first); + $first = str_replace(' ', ' ', $first); + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + $second = trim($codeBlocks->item(1)->nodeValue); + $second = str_replace('', $second); + $second = str_replace(' ', ' ', $second); + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo '
    $firstTitle$secondTitle
    $first$second
    '.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php new file mode 100644 index 000000000..de207ec60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Markdown.php @@ -0,0 +1,168 @@ + + * @author Juliette Reinders Folmer + * @copyright 2014 Arroba IT + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use DOMDocument; +use DOMNode; +use PHP_CodeSniffer\Config; + +class Markdown extends Generator +{ + + + /** + * Generates the documentation for a standard. + * + * @return void + * @see processSniff() + */ + public function generate() + { + ob_start(); + $this->printHeader(); + + foreach ($this->docFiles as $file) { + $doc = new DOMDocument(); + $doc->load($file); + $documentation = $doc->getElementsByTagName('documentation')->item(0); + $this->processSniff($documentation); + } + + $this->printFooter(); + $content = ob_get_contents(); + ob_end_clean(); + + echo $content; + + }//end generate() + + + /** + * Print the markdown header. + * + * @return void + */ + protected function printHeader() + { + $standard = $this->ruleset->name; + + echo "# $standard Coding Standard".PHP_EOL; + + }//end printHeader() + + + /** + * Print the markdown footer. + * + * @return void + */ + protected function printFooter() + { + // Turn off errors so we don't get timezone warnings if people + // don't have their timezone set. + error_reporting(0); + echo 'Documentation generated on '.date('r'); + echo ' by [PHP_CodeSniffer '.Config::VERSION.'](https://github.com/PHPCSStandards/PHP_CodeSniffer)'.PHP_EOL; + + }//end printFooter() + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + protected function processSniff(DOMNode $doc) + { + $title = $this->getTitle($doc); + echo PHP_EOL."## $title".PHP_EOL; + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(DOMNode $node) + { + $content = trim($node->nodeValue); + $content = htmlspecialchars($content); + + // Use the correct line endings based on the OS. + $content = str_replace("\n", PHP_EOL, $content); + + $content = str_replace('<em>', '*', $content); + $content = str_replace('</em>', '*', $content); + + echo $content.PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + $first = trim($codeBlocks->item(0)->nodeValue); + $first = str_replace("\n", PHP_EOL.' ', $first); + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + $second = trim($codeBlocks->item(1)->nodeValue); + $second = str_replace("\n", PHP_EOL.' ', $second); + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo " ".PHP_EOL; + echo " ".PHP_EOL; + echo ' '.PHP_EOL; + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo ' '.PHP_EOL; + echo '
    $firstTitle$secondTitle
    '.PHP_EOL.PHP_EOL; + echo " $first".PHP_EOL.PHP_EOL; + echo ''.PHP_EOL.PHP_EOL; + echo " $second".PHP_EOL.PHP_EOL; + echo '
    '.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Text.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Text.php new file mode 100644 index 000000000..ce419ba11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Generators/Text.php @@ -0,0 +1,255 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Generators; + +use DOMNode; + +class Text extends Generator +{ + + + /** + * Process the documentation for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + public function processSniff(DOMNode $doc) + { + $this->printTitle($doc); + + foreach ($doc->childNodes as $node) { + if ($node->nodeName === 'standard') { + $this->printTextBlock($node); + } else if ($node->nodeName === 'code_comparison') { + $this->printCodeComparisonBlock($node); + } + } + + }//end processSniff() + + + /** + * Prints the title area for a single sniff. + * + * @param \DOMNode $doc The DOMNode object for the sniff. + * It represents the "documentation" tag in the XML + * standard file. + * + * @return void + */ + protected function printTitle(DOMNode $doc) + { + $title = $this->getTitle($doc); + $standard = $this->ruleset->name; + + echo PHP_EOL; + echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4)); + echo strtoupper(PHP_EOL."| $standard CODING STANDARD: $title |".PHP_EOL); + echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4)); + echo PHP_EOL.PHP_EOL; + + }//end printTitle() + + + /** + * Print a text block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the text block. + * + * @return void + */ + protected function printTextBlock(DOMNode $node) + { + $text = trim($node->nodeValue); + $text = str_replace('', '*', $text); + $text = str_replace('', '*', $text); + + $nodeLines = explode("\n", $text); + $lines = []; + + foreach ($nodeLines as $currentLine) { + $currentLine = trim($currentLine); + if ($currentLine === '') { + // The text contained a blank line. Respect this. + $lines[] = ''; + continue; + } + + $tempLine = ''; + $words = explode(' ', $currentLine); + + foreach ($words as $word) { + $currentLength = strlen($tempLine.$word); + if ($currentLength < 99) { + $tempLine .= $word.' '; + continue; + } + + if ($currentLength === 99 || $currentLength === 100) { + // We are already at the edge, so we are done. + $lines[] = $tempLine.$word; + $tempLine = ''; + } else { + $lines[] = rtrim($tempLine); + $tempLine = $word.' '; + } + }//end foreach + + if ($tempLine !== '') { + $lines[] = rtrim($tempLine); + } + }//end foreach + + echo implode(PHP_EOL, $lines).PHP_EOL.PHP_EOL; + + }//end printTextBlock() + + + /** + * Print a code comparison block found in a standard. + * + * @param \DOMNode $node The DOMNode object for the code comparison block. + * + * @return void + */ + protected function printCodeComparisonBlock(DOMNode $node) + { + $codeBlocks = $node->getElementsByTagName('code'); + $first = trim($codeBlocks->item(0)->nodeValue); + $firstTitle = $codeBlocks->item(0)->getAttribute('title'); + + $firstTitleLines = []; + $tempTitle = ''; + $words = explode(' ', $firstTitle); + + foreach ($words as $word) { + if (strlen($tempTitle.$word) >= 45) { + if (strlen($tempTitle.$word) === 45) { + // Adding the extra space will push us to the edge + // so we are done. + $firstTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else if (strlen($tempTitle.$word) === 46) { + // We are already at the edge, so we are done. + $firstTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else { + $firstTitleLines[] = $tempTitle; + $tempTitle = $word.' '; + } + } else { + $tempTitle .= $word.' '; + } + }//end foreach + + if ($tempTitle !== '') { + $firstTitleLines[] = $tempTitle; + } + + $first = str_replace('', '', $first); + $first = str_replace('', '', $first); + $firstLines = explode("\n", $first); + + $second = trim($codeBlocks->item(1)->nodeValue); + $secondTitle = $codeBlocks->item(1)->getAttribute('title'); + + $secondTitleLines = []; + $tempTitle = ''; + $words = explode(' ', $secondTitle); + + foreach ($words as $word) { + if (strlen($tempTitle.$word) >= 45) { + if (strlen($tempTitle.$word) === 45) { + // Adding the extra space will push us to the edge + // so we are done. + $secondTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else if (strlen($tempTitle.$word) === 46) { + // We are already at the edge, so we are done. + $secondTitleLines[] = $tempTitle.$word; + $tempTitle = ''; + } else { + $secondTitleLines[] = $tempTitle; + $tempTitle = $word.' '; + } + } else { + $tempTitle .= $word.' '; + } + }//end foreach + + if ($tempTitle !== '') { + $secondTitleLines[] = $tempTitle; + } + + $second = str_replace('', '', $second); + $second = str_replace('', '', $second); + $secondLines = explode("\n", $second); + + $maxCodeLines = max(count($firstLines), count($secondLines)); + $maxTitleLines = max(count($firstTitleLines), count($secondTitleLines)); + + echo str_repeat('-', 41); + echo ' CODE COMPARISON '; + echo str_repeat('-', 42).PHP_EOL; + + for ($i = 0; $i < $maxTitleLines; $i++) { + if (isset($firstTitleLines[$i]) === true) { + $firstLineText = $firstTitleLines[$i]; + } else { + $firstLineText = ''; + } + + if (isset($secondTitleLines[$i]) === true) { + $secondLineText = $secondTitleLines[$i]; + } else { + $secondLineText = ''; + } + + echo '| '; + echo $firstLineText.str_repeat(' ', (46 - strlen($firstLineText))); + echo ' | '; + echo $secondLineText.str_repeat(' ', (47 - strlen($secondLineText))); + echo ' |'.PHP_EOL; + }//end for + + echo str_repeat('-', 100).PHP_EOL; + + for ($i = 0; $i < $maxCodeLines; $i++) { + if (isset($firstLines[$i]) === true) { + $firstLineText = $firstLines[$i]; + } else { + $firstLineText = ''; + } + + if (isset($secondLines[$i]) === true) { + $secondLineText = $secondLines[$i]; + } else { + $secondLineText = ''; + } + + echo '| '; + echo $firstLineText.str_repeat(' ', max(0, (47 - strlen($firstLineText)))); + echo '| '; + echo $secondLineText.str_repeat(' ', max(0, (48 - strlen($secondLineText)))); + echo '|'.PHP_EOL; + }//end for + + echo str_repeat('-', 100).PHP_EOL.PHP_EOL; + + }//end printCodeComparisonBlock() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reporter.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reporter.php new file mode 100644 index 000000000..824031a48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reporter.php @@ -0,0 +1,445 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Reports\Report; +use PHP_CodeSniffer\Util\Common; + +class Reporter +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * Total number of files that contain errors or warnings. + * + * @var integer + */ + public $totalFiles = 0; + + /** + * Total number of errors found during the run. + * + * @var integer + */ + public $totalErrors = 0; + + /** + * Total number of warnings found during the run. + * + * @var integer + */ + public $totalWarnings = 0; + + /** + * Total number of errors/warnings that can be fixed. + * + * @var integer + */ + public $totalFixable = 0; + + /** + * Total number of errors/warnings that were fixed. + * + * @var integer + */ + public $totalFixed = 0; + + /** + * When the PHPCS run started. + * + * @var float + */ + public static $startTime = 0; + + /** + * A cache of report objects. + * + * @var array + */ + private $reports = []; + + /** + * A cache of opened temporary files. + * + * @var array + */ + private $tmpFiles = []; + + + /** + * Initialise the reporter. + * + * All reports specified in the config will be created and their + * output file (or a temp file if none is specified) initialised by + * clearing the current contents. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If a custom report class could not be found. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If a report class is incorrectly set up. + */ + public function __construct(Config $config) + { + $this->config = $config; + + foreach ($config->reports as $type => $output) { + if ($output === null) { + $output = $config->reportFile; + } + + $reportClassName = ''; + if (strpos($type, '.') !== false) { + // This is a path to a custom report class. + $filename = realpath($type); + if ($filename === false) { + $error = "ERROR: Custom report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $reportClassName = Autoload::loadFile($filename); + } else if (class_exists('PHP_CodeSniffer\Reports\\'.ucfirst($type)) === true) { + // PHPCS native report. + $reportClassName = 'PHP_CodeSniffer\Reports\\'.ucfirst($type); + } else if (class_exists($type) === true) { + // FQN of a custom report. + $reportClassName = $type; + } else { + // OK, so not a FQN, try and find the report using the registered namespaces. + $registeredNamespaces = Autoload::getSearchPaths(); + $trimmedType = ltrim($type, '\\'); + + foreach ($registeredNamespaces as $nsPrefix) { + if ($nsPrefix === '') { + continue; + } + + if (class_exists($nsPrefix.'\\'.$trimmedType) === true) { + $reportClassName = $nsPrefix.'\\'.$trimmedType; + break; + } + } + }//end if + + if ($reportClassName === '') { + $error = "ERROR: Class file for report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); + } + + $reportClass = new $reportClassName(); + if (($reportClass instanceof Report) === false) { + throw new RuntimeException('Class "'.$reportClassName.'" must implement the "PHP_CodeSniffer\Report" interface.'); + } + + $this->reports[$type] = [ + 'output' => $output, + 'class' => $reportClass, + ]; + + if ($output === null) { + // Using a temp file. + // This needs to be set in the constructor so that all + // child procs use the same report file when running in parallel. + $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs'); + file_put_contents($this->tmpFiles[$type], ''); + } else { + file_put_contents($output, ''); + } + }//end foreach + + }//end __construct() + + + /** + * Generates and prints final versions of all reports. + * + * Returns TRUE if any of the reports output content to the screen + * or FALSE if all reports were silently printed to a file. + * + * @return bool + */ + public function printReports() + { + $toScreen = false; + foreach ($this->reports as $type => $report) { + if ($report['output'] === null) { + $toScreen = true; + } + + $this->printReport($type); + } + + return $toScreen; + + }//end printReports() + + + /** + * Generates and prints a single final report. + * + * @param string $report The report type to print. + * + * @return void + */ + public function printReport($report) + { + $reportClass = $this->reports[$report]['class']; + $reportFile = $this->reports[$report]['output']; + + if ($reportFile !== null) { + $filename = $reportFile; + $toScreen = false; + } else { + if (isset($this->tmpFiles[$report]) === true) { + $filename = $this->tmpFiles[$report]; + } else { + $filename = null; + } + + $toScreen = true; + } + + $reportCache = ''; + if ($filename !== null) { + $reportCache = file_get_contents($filename); + } + + ob_start(); + $reportClass->generate( + $reportCache, + $this->totalFiles, + $this->totalErrors, + $this->totalWarnings, + $this->totalFixable, + $this->config->showSources, + $this->config->reportWidth, + $this->config->interactive, + $toScreen + ); + $generatedReport = ob_get_contents(); + ob_end_clean(); + + if ($this->config->colors !== true || $reportFile !== null) { + $generatedReport = Common::stripColors($generatedReport); + } + + if ($reportFile !== null) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo $generatedReport; + } + + file_put_contents($reportFile, $generatedReport.PHP_EOL); + } else { + echo $generatedReport; + if ($filename !== null && file_exists($filename) === true) { + unlink($filename); + unset($this->tmpFiles[$report]); + } + } + + }//end printReport() + + + /** + * Caches the result of a single processed file for all reports. + * + * The report content that is generated is appended to the output file + * assigned to each report. This content may be an intermediate report format + * and not reflect the final report output. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed. + * + * @return void + */ + public function cacheFileReport(File $phpcsFile) + { + if (isset($this->config->reports) === false) { + // This happens during unit testing, or any time someone just wants + // the error data and not the printed report. + return; + } + + $reportData = $this->prepareFileReport($phpcsFile); + $errorsShown = false; + + foreach ($this->reports as $type => $report) { + $reportClass = $report['class']; + + ob_start(); + $result = $reportClass->generateFileReport($reportData, $phpcsFile, $this->config->showSources, $this->config->reportWidth); + if ($result === true) { + $errorsShown = true; + } + + $generatedReport = ob_get_contents(); + ob_end_clean(); + + if ($report['output'] === null) { + // Using a temp file. + if (isset($this->tmpFiles[$type]) === false) { + // When running in interactive mode, the reporter prints the full + // report many times, which will unlink the temp file. So we need + // to create a new one if it doesn't exist. + $this->tmpFiles[$type] = tempnam(sys_get_temp_dir(), 'phpcs'); + file_put_contents($this->tmpFiles[$type], ''); + } + + file_put_contents($this->tmpFiles[$type], $generatedReport, (FILE_APPEND | LOCK_EX)); + } else { + file_put_contents($report['output'], $generatedReport, (FILE_APPEND | LOCK_EX)); + }//end if + }//end foreach + + if ($errorsShown === true || PHP_CODESNIFFER_CBF === true) { + $this->totalFiles++; + $this->totalErrors += $reportData['errors']; + $this->totalWarnings += $reportData['warnings']; + + // When PHPCBF is running, we need to use the fixable error values + // after the report has run and fixed what it can. + if (PHP_CODESNIFFER_CBF === true) { + $this->totalFixable += $phpcsFile->getFixableCount(); + $this->totalFixed += $phpcsFile->getFixedCount(); + } else { + $this->totalFixable += $reportData['fixable']; + } + } + + }//end cacheFileReport() + + + /** + * Generate summary information to be used during report generation. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed. + * + * @return array Prepared report data. + * The format of prepared data is as follows: + * ``` + * array( + * 'filename' => string The name of the current file. + * 'errors' => int The number of errors seen in the current file. + * 'warnings' => int The number of warnings seen in the current file. + * 'fixable' => int The number of fixable issues seen in the current file. + * 'messages' => array( + * int => array( + * int => array( + * int => array( + * 'message' => string The error/warning message. + * 'source' => string The full error code for the message. + * 'severity' => int The severity of the message. + * 'fixable' => bool Whether this error/warning is auto-fixable. + * 'type' => string The type of message. Either 'ERROR' or 'WARNING'. + * ) + * ) + * ) + * ) + * ) + * ``` + */ + public function prepareFileReport(File $phpcsFile) + { + $report = [ + 'filename' => Common::stripBasepath($phpcsFile->getFilename(), $this->config->basepath), + 'errors' => $phpcsFile->getErrorCount(), + 'warnings' => $phpcsFile->getWarningCount(), + 'fixable' => $phpcsFile->getFixableCount(), + 'messages' => [], + ]; + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Perfect score! + return $report; + } + + if ($this->config->recordErrors === false) { + $message = 'Errors are not being recorded but this report requires error messages. '; + $message .= 'This report will not show the correct information.'; + $report['messages'][1][1] = [ + [ + 'message' => $message, + 'source' => 'Internal.RecordErrors', + 'severity' => 5, + 'fixable' => false, + 'type' => 'ERROR', + ], + ]; + return $report; + } + + $errors = []; + + // Merge errors and warnings. + foreach ($phpcsFile->getErrors() as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + $newErrors = []; + foreach ($colErrors as $data) { + $newErrors[] = [ + 'message' => $data['message'], + 'source' => $data['source'], + 'severity' => $data['severity'], + 'fixable' => $data['fixable'], + 'type' => 'ERROR', + ]; + } + + $errors[$line][$column] = $newErrors; + } + + ksort($errors[$line]); + }//end foreach + + foreach ($phpcsFile->getWarnings() as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $colWarnings) { + $newWarnings = []; + foreach ($colWarnings as $data) { + $newWarnings[] = [ + 'message' => $data['message'], + 'source' => $data['source'], + 'severity' => $data['severity'], + 'fixable' => $data['fixable'], + 'type' => 'WARNING', + ]; + } + + if (isset($errors[$line]) === false) { + $errors[$line] = []; + } + + if (isset($errors[$line][$column]) === true) { + $errors[$line][$column] = array_merge( + $newWarnings, + $errors[$line][$column] + ); + } else { + $errors[$line][$column] = $newWarnings; + } + }//end foreach + + ksort($errors[$line]); + }//end foreach + + ksort($errors); + $report['messages'] = $errors; + return $report; + + }//end prepareFileReport() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php new file mode 100644 index 000000000..d3b70fab6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Cbf.php @@ -0,0 +1,254 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Cbf implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $errors = $phpcsFile->getFixableCount(); + if ($errors !== 0) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + ob_end_clean(); + $startTime = microtime(true); + echo "\t=> Fixing file: $errors/$errors violations remaining"; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + $fixed = $phpcsFile->fixer->fixFile(); + } + + if ($phpcsFile->config->stdin === true) { + // Replacing STDIN, so output current file to STDOUT + // even if nothing was fixed. Exit here because we + // can't process any more than 1 file in this setup. + $fixedContent = $phpcsFile->fixer->getContents(); + throw new DeepExitException($fixedContent, 1); + } + + if ($errors === 0) { + return false; + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($fixed === false) { + echo 'ERROR'; + } else { + echo 'DONE'; + } + + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo " in {$timeTaken}ms".PHP_EOL; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo " in $timeTaken secs".PHP_EOL; + } + } + + if ($fixed === true) { + // The filename in the report may be truncated due to a basepath setting + // but we are using it for writing here and not display, + // so find the correct path if basepath is in use. + $newFilename = $report['filename'].$phpcsFile->config->suffix; + if ($phpcsFile->config->basepath !== null) { + $newFilename = $phpcsFile->config->basepath.DIRECTORY_SEPARATOR.$newFilename; + } + + $newContent = $phpcsFile->fixer->getContents(); + file_put_contents($newFilename, $newContent); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + if ($newFilename === $report['filename']) { + echo "\t=> File was overwritten".PHP_EOL; + } else { + echo "\t=> Fixed file written to ".basename($newFilename).PHP_EOL; + } + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + ob_start(); + } + + $errorCount = $phpcsFile->getErrorCount(); + $warningCount = $phpcsFile->getWarningCount(); + $fixableCount = $phpcsFile->getFixableCount(); + $fixedCount = ($errors - $fixableCount); + echo $report['filename'].">>$errorCount>>$warningCount>>$fixableCount>>$fixedCount".PHP_EOL; + + return $fixed; + + }//end generateFileReport() + + + /** + * Prints a summary of fixed files. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + echo PHP_EOL.'No fixable errors were found'.PHP_EOL; + return; + } + + $reportFiles = []; + $maxLength = 0; + $totalFixed = 0; + $failures = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $fileLen = strlen($parts[0]); + $reportFiles[$parts[0]] = [ + 'errors' => $parts[1], + 'warnings' => $parts[2], + 'fixable' => $parts[3], + 'fixed' => $parts[4], + 'strlen' => $fileLen, + ]; + + $maxLength = max($maxLength, $fileLen); + + $totalFixed += $parts[4]; + + if ($parts[3] > 0) { + $failures++; + } + } + + $width = min($width, ($maxLength + 21)); + $width = max($width, 70); + + echo PHP_EOL."\033[1m".'PHPCBF RESULT SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'FILE'.str_repeat(' ', ($width - 20)).'FIXED REMAINING'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + foreach ($reportFiles as $file => $data) { + $padding = ($width - 18 - $data['strlen']); + if ($padding < 0) { + $file = '...'.substr($file, (($padding * -1) + 3)); + $padding = 0; + } + + echo $file.str_repeat(' ', $padding).' '; + + if ($data['fixable'] > 0) { + echo "\033[31mFAILED TO FIX\033[0m".PHP_EOL; + continue; + } + + $remaining = ($data['errors'] + $data['warnings']); + + if ($data['fixed'] !== 0) { + echo $data['fixed']; + echo str_repeat(' ', (7 - strlen((string) $data['fixed']))); + } else { + echo '0 '; + } + + if ($remaining !== 0) { + echo $remaining; + } else { + echo '0'; + } + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1mA TOTAL OF $totalFixed ERROR"; + if ($totalFixed !== 1) { + echo 'S'; + } + + $numFiles = count($reportFiles); + echo ' WERE FIXED IN '.$numFiles.' FILE'; + if ($numFiles !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($failures > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF FAILED TO FIX $failures FILE"; + if ($failures !== 1) { + echo 'S'; + } + + echo "\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php new file mode 100644 index 000000000..8640561fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Checkstyle.php @@ -0,0 +1,111 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use XMLWriter; + +class Checkstyle implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new XMLWriter; + $out->openMemory(); + $out->setIndent(true); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $out->startElement('file'); + $out->writeAttribute('name', $report['filename']); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement('error'); + $out->writeAttribute('line', $line); + $out->writeAttribute('column', $column); + $out->writeAttribute('severity', $error['type']); + $out->writeAttribute('message', $error['message']); + $out->writeAttribute('source', $error['source']); + $out->endElement(); + } + } + }//end foreach + + $out->endElement(); + echo $out->flush(); + + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a Checkstyle format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Code.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Code.php new file mode 100644 index 000000000..c97e1681b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Code.php @@ -0,0 +1,365 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use Exception; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Timing; + +class Code implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + // How many lines to show above and below the error line. + $surroundingLines = 2; + + $file = $report['filename']; + $tokens = $phpcsFile->getTokens(); + if (empty($tokens) === true) { + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $startTime = microtime(true); + echo 'CODE report is parsing '.basename($file).' '; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "CODE report is forcing parse of $file".PHP_EOL; + } + + try { + $phpcsFile->parse(); + } catch (Exception $e) { + // This is a second parse, so ignore exceptions. + // They would have been added to the file's error list already. + } + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + echo PHP_EOL; + } + + $tokens = $phpcsFile->getTokens(); + }//end if + + // Create an array that maps lines to the first token on the line. + $lineTokens = []; + $lastLine = 0; + $stackPtr = 0; + foreach ($tokens as $stackPtr => $token) { + if ($token['line'] !== $lastLine) { + if ($lastLine > 0) { + $lineTokens[$lastLine]['end'] = ($stackPtr - 1); + } + + $lastLine++; + $lineTokens[$lastLine] = [ + 'start' => $stackPtr, + 'end' => null, + ]; + } + } + + // Make sure the last token in the file sits on an imaginary + // last line so it is easier to generate code snippets at the + // end of the file. + $lineTokens[$lastLine]['end'] = $stackPtr; + + // Determine the longest code line we will be showing. + $maxSnippetLength = 0; + $eolLen = strlen($phpcsFile->eolChar); + foreach ($report['messages'] as $line => $lineErrors) { + $startLine = max(($line - $surroundingLines), 1); + $endLine = min(($line + $surroundingLines), $lastLine); + + $maxLineNumLength = strlen($endLine); + + for ($i = $startLine; $i <= $endLine; $i++) { + if ($i === 1) { + continue; + } + + $lineLength = ($tokens[($lineTokens[$i]['start'] - 1)]['column'] + $tokens[($lineTokens[$i]['start'] - 1)]['length'] - $eolLen); + $maxSnippetLength = max($lineLength, $maxSnippetLength); + } + } + + $maxSnippetLength += ($maxLineNumLength + 8); + + // Determine the longest error message we will be showing. + $maxErrorLength = 0; + foreach ($report['messages'] as $lineErrors) { + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + $length = strlen($error['message']); + if ($showSources === true) { + $length += (strlen($error['source']) + 3); + } + + $maxErrorLength = max($maxErrorLength, ($length + 1)); + } + } + } + + // The padding that all lines will require that are printing an error message overflow. + if ($report['warnings'] > 0) { + $typeLength = 7; + } else { + $typeLength = 5; + } + + $errorPadding = str_repeat(' ', ($maxLineNumLength + 7)); + $errorPadding .= str_repeat(' ', $typeLength); + $errorPadding .= ' '; + if ($report['fixable'] > 0) { + $errorPadding .= ' '; + } + + $errorPaddingLength = strlen($errorPadding); + + // The maximum amount of space an error message can use. + $maxErrorSpace = ($width - $errorPaddingLength); + if ($showSources === true) { + // Account for the chars used to print colors. + $maxErrorSpace += 8; + } + + // Figure out the max report width we need and can use. + $fileLength = strlen($file); + $maxWidth = max(($fileLength + 6), ($maxErrorLength + $errorPaddingLength)); + $width = max(min($width, $maxWidth), $maxSnippetLength); + if ($width < 70) { + $width = 70; + } + + // Print the file header. + echo PHP_EOL."\033[1mFILE: "; + if ($fileLength <= ($width - 6)) { + echo $file; + } else { + echo '...'.substr($file, ($fileLength - ($width - 6))); + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + echo "\033[1m".'FOUND '.$report['errors'].' ERROR'; + if ($report['errors'] !== 1) { + echo 'S'; + } + + if ($report['warnings'] > 0) { + echo ' AND '.$report['warnings'].' WARNING'; + if ($report['warnings'] !== 1) { + echo 'S'; + } + } + + echo ' AFFECTING '.count($report['messages']).' LINE'; + if (count($report['messages']) !== 1) { + echo 'S'; + } + + echo "\033[0m".PHP_EOL; + + foreach ($report['messages'] as $line => $lineErrors) { + $startLine = max(($line - $surroundingLines), 1); + $endLine = min(($line + $surroundingLines), $lastLine); + + $snippet = ''; + if (isset($lineTokens[$startLine]) === true) { + for ($i = $lineTokens[$startLine]['start']; $i <= $lineTokens[$endLine]['end']; $i++) { + $snippetLine = $tokens[$i]['line']; + if ($lineTokens[$snippetLine]['start'] === $i) { + // Starting a new line. + if ($snippetLine === $line) { + $snippet .= "\033[1m".'>> '; + } else { + $snippet .= ' '; + } + + $snippet .= str_repeat(' ', ($maxLineNumLength - strlen($snippetLine))); + $snippet .= $snippetLine.': '; + if ($snippetLine === $line) { + $snippet .= "\033[0m"; + } + } + + if (isset($tokens[$i]['orig_content']) === true) { + $tokenContent = $tokens[$i]['orig_content']; + } else { + $tokenContent = $tokens[$i]['content']; + } + + if (strpos($tokenContent, "\t") !== false) { + $token = $tokens[$i]; + $token['content'] = $tokenContent; + if (stripos(PHP_OS, 'WIN') === 0) { + $tab = "\000"; + } else { + $tab = "\033[30;1m»\033[0m"; + } + + $phpcsFile->tokenizer->replaceTabsInToken($token, $tab, "\000"); + $tokenContent = $token['content']; + } + + $tokenContent = Common::prepareForOutput($tokenContent, ["\r", "\n", "\t"]); + $tokenContent = str_replace("\000", ' ', $tokenContent); + + $underline = false; + if ($snippetLine === $line && isset($lineErrors[$tokens[$i]['column']]) === true) { + $underline = true; + } + + // Underline invisible characters as well. + if ($underline === true && trim($tokenContent) === '') { + $snippet .= "\033[4m".' '."\033[0m".$tokenContent; + } else { + if ($underline === true) { + $snippet .= "\033[4m"; + } + + $snippet .= $tokenContent; + + if ($underline === true) { + $snippet .= "\033[0m"; + } + } + }//end for + }//end if + + echo str_repeat('-', $width).PHP_EOL; + + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + $padding = ($maxLineNumLength - strlen($line)); + echo 'LINE '.str_repeat(' ', $padding).$line.': '; + + if ($error['type'] === 'ERROR') { + echo "\033[31mERROR\033[0m"; + if ($report['warnings'] > 0) { + echo ' '; + } + } else { + echo "\033[33mWARNING\033[0m"; + } + + echo ' '; + if ($report['fixable'] > 0) { + echo '['; + if ($error['fixable'] === true) { + echo 'x'; + } else { + echo ' '; + } + + echo '] '; + } + + $message = $error['message']; + $message = str_replace("\n", "\n".$errorPadding, $message); + if ($showSources === true) { + $message = "\033[1m".$message."\033[0m".' ('.$error['source'].')'; + } + + $errorMsg = wordwrap( + $message, + $maxErrorSpace, + PHP_EOL.$errorPadding + ); + + echo $errorMsg.PHP_EOL; + }//end foreach + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo rtrim($snippet).PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + if ($report['fixable'] > 0) { + echo "\033[1m".'PHPCBF CAN FIX THE '.$report['fixable'].' MARKED SNIFF VIOLATIONS AUTOMATICALLY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + if ($cachedData === '') { + return; + } + + echo $cachedData; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php new file mode 100644 index 000000000..ed7caca38 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Csv.php @@ -0,0 +1,92 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Csv implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $filename = str_replace('"', '\"', $report['filename']); + $message = str_replace('"', '\"', $error['message']); + $type = strtolower($error['type']); + $source = $error['source']; + $severity = $error['severity']; + $fixable = (int) $error['fixable']; + echo "\"$filename\",$line,$column,$type,\"$message\",$source,$severity,$fixable".PHP_EOL; + } + } + } + + return true; + + }//end generateFileReport() + + + /** + * Generates a csv report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo 'File,Line,Column,Type,Message,Source,Severity,Fixable'.PHP_EOL; + echo $cachedData; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php new file mode 100644 index 000000000..9580b4e97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Diff.php @@ -0,0 +1,131 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Diff implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $errors = $phpcsFile->getFixableCount(); + if ($errors === 0) { + return false; + } + + $phpcsFile->disableCaching(); + $tokens = $phpcsFile->getTokens(); + if (empty($tokens) === true) { + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $startTime = microtime(true); + echo 'DIFF report is parsing '.basename($report['filename']).' '; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo 'DIFF report is forcing parse of '.$report['filename'].PHP_EOL; + } + + $phpcsFile->parse(); + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + echo PHP_EOL; + } + + $phpcsFile->fixer->startFile($phpcsFile); + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + ob_end_clean(); + echo "\t*** START FILE FIXING ***".PHP_EOL; + } + + $fixed = $phpcsFile->fixer->fixFile(); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END FILE FIXING ***".PHP_EOL; + ob_start(); + } + + if ($fixed === false) { + return false; + } + + $diff = $phpcsFile->fixer->generateDiff(); + if ($diff === '') { + // Nothing to print. + return false; + } + + echo $diff.PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo $cachedData; + if ($toScreen === true && $cachedData !== '') { + echo PHP_EOL; + } + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php new file mode 100644 index 000000000..076768a78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Emacs.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Emacs implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $message = $error['message']; + if ($showSources === true) { + $message .= ' ('.$error['source'].')'; + } + + $type = strtolower($error['type']); + echo $report['filename'].':'.$line.':'.$column.': '.$type.' - '.$message.PHP_EOL; + } + } + } + + return true; + + }//end generateFileReport() + + + /** + * Generates an emacs report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo $cachedData; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Full.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Full.php new file mode 100644 index 000000000..9af4efaea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Full.php @@ -0,0 +1,260 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Full implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + // The length of the word ERROR or WARNING; used for padding. + if ($report['warnings'] > 0) { + $typeLength = 7; + } else { + $typeLength = 5; + } + + // Work out the max line number length for formatting. + $maxLineNumLength = max(array_map('strlen', array_keys($report['messages']))); + + // The padding that all lines will require that are + // printing an error message overflow. + $paddingLine2 = str_repeat(' ', ($maxLineNumLength + 1)); + $paddingLine2 .= ' | '; + $paddingLine2 .= str_repeat(' ', $typeLength); + $paddingLine2 .= ' | '; + if ($report['fixable'] > 0) { + $paddingLine2 .= ' '; + } + + $paddingLength = strlen($paddingLine2); + + // Make sure the report width isn't too big. + $maxErrorLength = 0; + foreach ($report['messages'] as $lineErrors) { + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + // Start with the presumption of a single line error message. + $length = strlen($error['message']); + $srcLength = (strlen($error['source']) + 3); + if ($showSources === true) { + $length += $srcLength; + } + + // ... but also handle multi-line messages correctly. + if (strpos($error['message'], "\n") !== false) { + $errorLines = explode("\n", $error['message']); + $length = max(array_map('strlen', $errorLines)); + + if ($showSources === true) { + $lastLine = array_pop($errorLines); + $length = max($length, (strlen($lastLine) + $srcLength)); + } + } + + $maxErrorLength = max($maxErrorLength, ($length + 1)); + }//end foreach + }//end foreach + }//end foreach + + $file = $report['filename']; + $fileLength = strlen($file); + $maxWidth = max(($fileLength + 6), ($maxErrorLength + $paddingLength)); + $width = min($width, $maxWidth); + if ($width < 70) { + $width = 70; + } + + echo PHP_EOL."\033[1mFILE: "; + if ($fileLength <= ($width - 6)) { + echo $file; + } else { + echo '...'.substr($file, ($fileLength - ($width - 6))); + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + echo "\033[1m".'FOUND '.$report['errors'].' ERROR'; + if ($report['errors'] !== 1) { + echo 'S'; + } + + if ($report['warnings'] > 0) { + echo ' AND '.$report['warnings'].' WARNING'; + if ($report['warnings'] !== 1) { + echo 'S'; + } + } + + echo ' AFFECTING '.count($report['messages']).' LINE'; + if (count($report['messages']) !== 1) { + echo 'S'; + } + + echo "\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + // The maximum amount of space an error message can use. + $maxErrorSpace = ($width - $paddingLength - 1); + + $beforeMsg = ''; + $afterMsg = ''; + if ($showSources === true) { + $beforeMsg = "\033[1m"; + $afterMsg = "\033[0m"; + } + + $beforeAfterLength = strlen($beforeMsg.$afterMsg); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + $errorMsg = wordwrap( + $error['message'], + $maxErrorSpace + ); + + // Add the padding _after_ the wordwrap as the message itself may contain line breaks + // and those lines will also need to receive padding. + $errorMsg = str_replace("\n", $afterMsg.PHP_EOL.$paddingLine2.$beforeMsg, $errorMsg); + $errorMsg = $beforeMsg.$errorMsg.$afterMsg; + + if ($showSources === true) { + $lastMsg = $errorMsg; + $startPosLastLine = strrpos($errorMsg, PHP_EOL.$paddingLine2.$beforeMsg); + if ($startPosLastLine !== false) { + // Message is multiline. Grab the text of last line of the message, including the color codes. + $lastMsg = substr($errorMsg, ($startPosLastLine + strlen(PHP_EOL.$paddingLine2))); + } + + // When show sources is used, the message itself will be bolded, so we need to correct the length. + $sourceSuffix = '('.$error['source'].')'; + + $lastMsgPlusSourceLength = strlen($lastMsg); + // Add space + source suffix length. + $lastMsgPlusSourceLength += (1 + strlen($sourceSuffix)); + // Correct for the color codes. + $lastMsgPlusSourceLength -= $beforeAfterLength; + + if ($lastMsgPlusSourceLength > $maxErrorSpace) { + $errorMsg .= PHP_EOL.$paddingLine2.$sourceSuffix; + } else { + $errorMsg .= ' '.$sourceSuffix; + } + }//end if + + // The padding that goes on the front of the line. + $padding = ($maxLineNumLength - strlen($line)); + + echo ' '.str_repeat(' ', $padding).$line.' | '; + if ($error['type'] === 'ERROR') { + echo "\033[31mERROR\033[0m"; + if ($report['warnings'] > 0) { + echo ' '; + } + } else { + echo "\033[33mWARNING\033[0m"; + } + + echo ' | '; + if ($report['fixable'] > 0) { + echo '['; + if ($error['fixable'] === true) { + echo 'x'; + } else { + echo ' '; + } + + echo '] '; + } + + echo $errorMsg.PHP_EOL; + }//end foreach + }//end foreach + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + if ($report['fixable'] > 0) { + echo "\033[1m".'PHPCBF CAN FIX THE '.$report['fixable'].' MARKED SNIFF VIOLATIONS AUTOMATICALLY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + echo PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Prints all errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + if ($cachedData === '') { + return; + } + + echo $cachedData; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php new file mode 100644 index 000000000..3beb34524 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Gitblame.php @@ -0,0 +1,91 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Gitblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'GIT'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + $line = preg_replace('|\s+|', ' ', $line); + preg_match( + '|\(.+[0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]+\)|', + $line, + $blameParts + ); + + if (isset($blameParts[0]) === false) { + return false; + } + + $parts = explode(' ', $blameParts[0]); + + if (count($parts) < 2) { + return false; + } + + $parts = array_slice($parts, 0, (count($parts) - 2)); + $author = preg_replace('|\(|', '', implode(' ', $parts)); + return $author; + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $cwd = getcwd(); + + chdir(dirname($filename)); + $command = 'git blame --date=short "'.basename($filename).'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + chdir($cwd); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php new file mode 100644 index 000000000..2d98c46db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Hgblame.php @@ -0,0 +1,110 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Hgblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'MERCURIAL'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return string|false String or FALSE if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + $line = preg_replace('|\s+|', ' ', $line); + + preg_match( + '|(.+[0-9]{2}:[0-9]{2}:[0-9]{2}\s[0-9]{4}\s.[0-9]{4}:)|', + $line, + $blameParts + ); + + if (isset($blameParts[0]) === false) { + return false; + } + + $parts = explode(' ', $blameParts[0]); + + if (count($parts) < 6) { + return false; + } + + $parts = array_slice($parts, 0, (count($parts) - 6)); + + return trim(preg_replace('|<.+>|', '', implode(' ', $parts))); + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $cwd = getcwd(); + + $fileParts = explode(DIRECTORY_SEPARATOR, $filename); + $found = false; + $location = ''; + while (empty($fileParts) === false) { + array_pop($fileParts); + $location = implode(DIRECTORY_SEPARATOR, $fileParts); + if (is_dir($location.DIRECTORY_SEPARATOR.'.hg') === true) { + $found = true; + break; + } + } + + if ($found === true) { + chdir($location); + } else { + $error = 'ERROR: Could not locate .hg directory '.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $command = 'hg blame -u -d -v "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + chdir($cwd); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Info.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Info.php new file mode 100644 index 000000000..9f1f45aa5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Info.php @@ -0,0 +1,173 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Info implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $metrics = $phpcsFile->getMetrics(); + foreach ($metrics as $metric => $data) { + foreach ($data['values'] as $value => $count) { + echo "$metric>>$value>>$count".PHP_EOL; + } + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the recorded metrics. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $metrics = []; + foreach ($lines as $line) { + $parts = explode('>>', $line); + $metric = $parts[0]; + $value = $parts[1]; + $count = $parts[2]; + if (isset($metrics[$metric]) === false) { + $metrics[$metric] = []; + } + + if (isset($metrics[$metric][$value]) === false) { + $metrics[$metric][$value] = $count; + } else { + $metrics[$metric][$value] += $count; + } + } + + ksort($metrics); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER INFORMATION REPORT'."\033[0m".PHP_EOL; + echo str_repeat('-', 70).PHP_EOL; + + foreach ($metrics as $metric => $values) { + if (count($values) === 1) { + $count = reset($values); + $value = key($values); + + echo "$metric: \033[4m$value\033[0m [$count/$count, 100%]".PHP_EOL; + } else { + $totalCount = 0; + $valueWidth = 0; + foreach ($values as $value => $count) { + $totalCount += $count; + $valueWidth = max($valueWidth, strlen($value)); + } + + // Length of the total string, plus however many + // thousands separators there are. + $countWidth = strlen($totalCount); + $thousandSeparatorCount = floor($countWidth / 3); + $countWidth += $thousandSeparatorCount; + + // Account for 'total' line. + $valueWidth = max(5, $valueWidth); + + echo "$metric:".PHP_EOL; + + ksort($values, SORT_NATURAL); + arsort($values); + + $percentPrefixWidth = 0; + $percentWidth = 6; + foreach ($values as $value => $count) { + $percent = round(($count / $totalCount * 100), 2); + $percentPrefix = ''; + if ($percent === 0.00) { + $percent = 0.01; + $percentPrefix = '<'; + $percentPrefixWidth = 2; + $percentWidth = 4; + } + + printf( + "\t%-{$valueWidth}s => %{$countWidth}s (%{$percentPrefixWidth}s%{$percentWidth}.2f%%)".PHP_EOL, + $value, + number_format($count), + $percentPrefix, + $percent + ); + } + + echo "\t".str_repeat('-', ($valueWidth + $countWidth + 15)).PHP_EOL; + printf( + "\t%-{$valueWidth}s => %{$countWidth}s (100.00%%)".PHP_EOL, + 'total', + number_format($totalCount) + ); + }//end if + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', 70).PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Json.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Json.php new file mode 100644 index 000000000..67c8b5e63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Json.php @@ -0,0 +1,107 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +class Json implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $filename = str_replace('\\', '\\\\', $report['filename']); + $filename = str_replace('"', '\"', $filename); + $filename = str_replace('/', '\/', $filename); + echo '"'.$filename.'":{'; + echo '"errors":'.$report['errors'].',"warnings":'.$report['warnings'].',"messages":['; + + $messages = ''; + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['message'] = str_replace("\n", '\n', $error['message']); + $error['message'] = str_replace("\r", '\r', $error['message']); + $error['message'] = str_replace("\t", '\t', $error['message']); + + $fixable = false; + if ($error['fixable'] === true) { + $fixable = true; + } + + $messagesObject = (object) $error; + $messagesObject->line = $line; + $messagesObject->column = $column; + $messagesObject->fixable = $fixable; + + $messages .= json_encode($messagesObject).","; + } + } + }//end foreach + + echo rtrim($messages, ','); + echo ']},'; + + return true; + + }//end generateFileReport() + + + /** + * Generates a JSON report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo '{"totals":{"errors":'.$totalErrors.',"warnings":'.$totalWarnings.',"fixable":'.$totalFixable.'},"files":{'; + echo rtrim($cachedData, ','); + echo "}}".PHP_EOL; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php new file mode 100644 index 000000000..aaeeb1774 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Junit.php @@ -0,0 +1,133 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use XMLWriter; + +class Junit implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new XMLWriter; + $out->openMemory(); + $out->setIndent(true); + + $out->startElement('testsuite'); + $out->writeAttribute('name', $report['filename']); + $out->writeAttribute('errors', 0); + + if (count($report['messages']) === 0) { + $out->writeAttribute('tests', 1); + $out->writeAttribute('failures', 0); + + $out->startElement('testcase'); + $out->writeAttribute('name', $report['filename']); + $out->endElement(); + } else { + $failures = ($report['errors'] + $report['warnings']); + $out->writeAttribute('tests', $failures); + $out->writeAttribute('failures', $failures); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $out->startElement('testcase'); + $out->writeAttribute('name', $error['source'].' at '.$report['filename']." ($line:$column)"); + + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement('failure'); + $out->writeAttribute('type', $error['type']); + $out->writeAttribute('message', $error['message']); + $out->endElement(); + + $out->endElement(); + } + } + } + }//end if + + $out->endElement(); + echo $out->flush(); + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + // Figure out the total number of tests. + $tests = 0; + $matches = []; + preg_match_all('/tests="([0-9]+)"/', $cachedData, $matches); + if (isset($matches[1]) === true) { + foreach ($matches[1] as $match) { + $tests += $match; + } + } + + $failures = ($totalErrors + $totalWarnings); + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php new file mode 100644 index 000000000..839d99036 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Notifysend.php @@ -0,0 +1,243 @@ + + * @author Greg Sherwood + * @copyright 2012-2014 Christian Weiske + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; + +class Notifysend implements Report +{ + + /** + * Notification timeout in milliseconds. + * + * @var integer + */ + protected $timeout = 3000; + + /** + * Path to notify-send command. + * + * @var string + */ + protected $path = 'notify-send'; + + /** + * Show "ok, all fine" messages. + * + * @var boolean + */ + protected $showOk = true; + + /** + * Version of installed notify-send executable. + * + * @var string + */ + protected $version = null; + + + /** + * Load configuration data. + */ + public function __construct() + { + $path = Config::getExecutablePath('notifysend'); + if ($path !== null) { + $this->path = Common::escapeshellcmd($path); + } + + $timeout = Config::getConfigData('notifysend_timeout'); + if ($timeout !== null) { + $this->timeout = (int) $timeout; + } + + $showOk = Config::getConfigData('notifysend_showok'); + if ($showOk !== null) { + $this->showOk = (bool) $showOk; + } + + $this->version = str_replace( + 'notify-send ', + '', + exec($this->path.' --version') + ); + + }//end __construct() + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + echo $report['filename'].PHP_EOL; + + // We want this file counted in the total number + // of checked files even if it has no errors. + return true; + + }//end generateFileReport() + + + /** + * Generates a summary of errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $checkedFiles = explode(PHP_EOL, trim($cachedData)); + + $msg = $this->generateMessage($checkedFiles, $totalErrors, $totalWarnings); + if ($msg === null) { + if ($this->showOk === true) { + $this->notifyAllFine(); + } + } else { + $this->notifyErrors($msg); + } + + }//end generate() + + + /** + * Generate the error message to show to the user. + * + * @param string[] $checkedFiles The files checked during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * + * @return string|null Error message or NULL if no error/warning found. + */ + protected function generateMessage($checkedFiles, $totalErrors, $totalWarnings) + { + if ($totalErrors === 0 && $totalWarnings === 0) { + // Nothing to print. + return null; + } + + $totalFiles = count($checkedFiles); + + $msg = ''; + if ($totalFiles > 1) { + $msg .= 'Checked '.$totalFiles.' files'.PHP_EOL; + } else { + $msg .= $checkedFiles[0].PHP_EOL; + } + + if ($totalWarnings > 0) { + $msg .= $totalWarnings.' warnings'.PHP_EOL; + } + + if ($totalErrors > 0) { + $msg .= $totalErrors.' errors'.PHP_EOL; + } + + return $msg; + + }//end generateMessage() + + + /** + * Tell the user that all is fine and no error/warning has been found. + * + * @return void + */ + protected function notifyAllFine() + { + $cmd = $this->getBasicCommand(); + $cmd .= ' -i info'; + $cmd .= ' "PHP CodeSniffer: Ok"'; + $cmd .= ' "All fine"'; + exec($cmd); + + }//end notifyAllFine() + + + /** + * Tell the user that errors/warnings have been found. + * + * @param string $msg Message to display. + * + * @return void + */ + protected function notifyErrors($msg) + { + $cmd = $this->getBasicCommand(); + $cmd .= ' -i error'; + $cmd .= ' "PHP CodeSniffer: Error"'; + $cmd .= ' '.escapeshellarg(trim($msg)); + exec($cmd); + + }//end notifyErrors() + + + /** + * Generate and return the basic notify-send command string to execute. + * + * @return string Shell command with common parameters. + */ + protected function getBasicCommand() + { + $cmd = $this->path; + $cmd .= ' --category dev.validate'; + $cmd .= ' -h int:transient:1'; + $cmd .= ' -t '.(int) $this->timeout; + if (version_compare($this->version, '0.7.3', '>=') === true) { + $cmd .= ' -a phpcs'; + } + + return $cmd; + + }//end getBasicCommand() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Performance.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Performance.php new file mode 100644 index 000000000..843698990 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Performance.php @@ -0,0 +1,161 @@ + + * @copyright 2023 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Timing; + +class Performance implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $times = $phpcsFile->getListenerTimes(); + foreach ($times as $sniff => $time) { + echo "$sniff>>$time".PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the sniff performance report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + // First collect the accumulated timings. + $timings = []; + $totalSniffTime = 0; + foreach ($lines as $line) { + $parts = explode('>>', $line); + $sniffClass = $parts[0]; + $time = $parts[1]; + + if (isset($timings[$sniffClass]) === false) { + $timings[$sniffClass] = 0; + } + + $timings[$sniffClass] += $time; + $totalSniffTime += $time; + } + + // Next, tidy up the sniff names and determine max needed column width. + $totalTimes = []; + $maxNameWidth = 0; + foreach ($timings as $sniffClass => $secs) { + $sniffCode = Common::getSniffCode($sniffClass); + $maxNameWidth = max($maxNameWidth, strlen($sniffCode)); + $totalTimes[$sniffCode] = $secs; + } + + // Leading space + up to 12 chars for the number. + $maxTimeWidth = 13; + // Leading space, open parenthesis, up to 5 chars for the number, space + % and close parenthesis. + $maxPercWidth = 10; + // Calculate the maximum width available for the sniff name. + $maxNameWidth = min(($width - $maxTimeWidth - $maxPercWidth), max(($width - $maxTimeWidth - $maxPercWidth), $maxNameWidth)); + + arsort($totalTimes); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER SNIFF PERFORMANCE REPORT'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'SNIFF'.str_repeat(' ', ($width - 31)).'TIME TAKEN (SECS) (%)'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + // Mark sniffs which take more than twice as long as the average processing time per sniff + // in orange and when they take more than three times as long as the average, + // mark them in red. + $avgSniffTime = ($totalSniffTime / count($totalTimes)); + $doubleAvgSniffTime = (2 * $avgSniffTime); + $tripleAvgSniffTime = (3 * $avgSniffTime); + + $format = "%- {$maxNameWidth}.{$maxNameWidth}s % 12.6f (% 5.1f %%)".PHP_EOL; + $formatBold = "\033[1m%- {$maxNameWidth}.{$maxNameWidth}s % 12.6f (% 5.1f %%)\033[0m".PHP_EOL; + $formatWarning = "%- {$maxNameWidth}.{$maxNameWidth}s \033[33m% 12.6f (% 5.1f %%)\033[0m".PHP_EOL; + $formatError = "%- {$maxNameWidth}.{$maxNameWidth}s \033[31m% 12.6f (% 5.1f %%)\033[0m".PHP_EOL; + + foreach ($totalTimes as $sniff => $time) { + $percent = round((($time / $totalSniffTime) * 100), 1); + + if ($time > $tripleAvgSniffTime) { + printf($formatError, $sniff, $time, $percent); + } else if ($time > $doubleAvgSniffTime) { + printf($formatWarning, $sniff, $time, $percent); + } else { + printf($format, $sniff, $time, $percent); + } + } + + echo str_repeat('-', $width).PHP_EOL; + printf($formatBold, 'TOTAL SNIFF PROCESSING TIME', $totalSniffTime, 100); + + $runTime = (Timing::getDuration() / 1000); + $phpcsTime = ($runTime - $totalSniffTime); + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + printf($format, 'Time taken by sniffs', $totalSniffTime, round((($totalSniffTime / $runTime) * 100), 1)); + printf($format, 'Time taken by PHPCS runner', $phpcsTime, round((($phpcsTime / $runTime) * 100), 1)); + + echo str_repeat('-', $width).PHP_EOL; + printf($formatBold, 'TOTAL RUN TIME', $runTime, 100); + echo str_repeat('-', $width).PHP_EOL; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Report.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Report.php new file mode 100644 index 000000000..52d7883b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Report.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; + +interface Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * The format of the `$report` parameter the function receives is as follows: + * ``` + * array( + * 'filename' => string The name of the current file. + * 'errors' => int The number of errors seen in the current file. + * 'warnings' => int The number of warnings seen in the current file. + * 'fixable' => int The number of fixable issues seen in the current file. + * 'messages' => array( + * int => array( + * int => array( + * int => array( + * 'message' => string The error/warning message. + * 'source' => string The full error code for the message. + * 'severity' => int The severity of the message. + * 'fixable' => bool Whether this error/warning is auto-fixable. + * 'type' => string The type of message. Either 'ERROR' or 'WARNING'. + * ) + * ) + * ) + * ) + * ) + * ``` + * + * @param array $report Prepared report data. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80); + + + /** + * Generate the actual report. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ); + + +}//end interface diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Source.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Source.php new file mode 100644 index 000000000..deedb3ebd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Source.php @@ -0,0 +1,337 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Source implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $sources = []; + + foreach ($report['messages'] as $lineErrors) { + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + $src = $error['source']; + if (isset($sources[$src]) === false) { + $sources[$src] = [ + 'fixable' => (int) $error['fixable'], + 'count' => 1, + ]; + } else { + $sources[$src]['count']++; + } + } + } + } + + foreach ($sources as $source => $data) { + echo $source.'>>'.$data['fixable'].'>>'.$data['count'].PHP_EOL; + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the source of all errors and warnings. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $sources = []; + $maxLength = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $source = $parts[0]; + $fixable = (bool) $parts[1]; + $count = $parts[2]; + + if (isset($sources[$source]) === false) { + if ($showSources === true) { + $parts = null; + $sniff = $source; + } else { + $parts = explode('.', $source); + if ($parts[0] === 'Internal') { + $parts[2] = $parts[1]; + $parts[1] = ''; + } + + $parts[1] = $this->makeFriendlyName($parts[1]); + + $sniff = $this->makeFriendlyName($parts[2]); + if (isset($parts[3]) === true) { + $name = $this->makeFriendlyName($parts[3]); + $name[0] = strtolower($name[0]); + $sniff .= ' '.$name; + unset($parts[3]); + } + + $parts[2] = $sniff; + }//end if + + $maxLength = max($maxLength, strlen($sniff)); + + $sources[$source] = [ + 'count' => $count, + 'fixable' => $fixable, + 'parts' => $parts, + ]; + } else { + $sources[$source]['count'] += $count; + }//end if + }//end foreach + + if ($showSources === true) { + $width = min($width, ($maxLength + 11)); + } else { + $width = min($width, ($maxLength + 41)); + } + + $width = max($width, 70); + + // Sort the data based on counts and source code. + $sourceCodes = array_keys($sources); + $counts = []; + foreach ($sources as $source => $data) { + $counts[$source] = $data['count']; + } + + array_multisort($counts, SORT_DESC, $sourceCodes, SORT_ASC, SORT_NATURAL, $sources); + + echo PHP_EOL."\033[1mPHP CODE SNIFFER VIOLATION SOURCE SUMMARY\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL."\033[1m"; + if ($showSources === true) { + if ($totalFixable > 0) { + echo ' SOURCE'.str_repeat(' ', ($width - 15)).'COUNT'.PHP_EOL; + } else { + echo 'SOURCE'.str_repeat(' ', ($width - 11)).'COUNT'.PHP_EOL; + } + } else { + if ($totalFixable > 0) { + echo ' STANDARD CATEGORY SNIFF'.str_repeat(' ', ($width - 44)).'COUNT'.PHP_EOL; + } else { + echo 'STANDARD CATEGORY SNIFF'.str_repeat(' ', ($width - 40)).'COUNT'.PHP_EOL; + } + } + + echo "\033[0m".str_repeat('-', $width).PHP_EOL; + + $fixableSources = 0; + + if ($showSources === true) { + $maxSniffWidth = ($width - 7); + } else { + $maxSniffWidth = ($width - 37); + } + + if ($totalFixable > 0) { + $maxSniffWidth -= 4; + } + + foreach ($sources as $source => $sourceData) { + if ($totalFixable > 0) { + echo '['; + if ($sourceData['fixable'] === true) { + echo 'x'; + $fixableSources++; + } else { + echo ' '; + } + + echo '] '; + } + + if ($showSources === true) { + if (strlen($source) > $maxSniffWidth) { + $source = substr($source, 0, $maxSniffWidth); + } + + echo $source; + if ($totalFixable > 0) { + echo str_repeat(' ', ($width - 9 - strlen($source))); + } else { + echo str_repeat(' ', ($width - 5 - strlen($source))); + } + } else { + $parts = $sourceData['parts']; + + if (strlen($parts[0]) > 8) { + $parts[0] = substr($parts[0], 0, ((strlen($parts[0]) - 8) * -1)); + } + + echo $parts[0].str_repeat(' ', (10 - strlen($parts[0]))); + + $category = $parts[1]; + if (strlen($category) > 18) { + $category = substr($category, 0, ((strlen($category) - 18) * -1)); + } + + echo $category.str_repeat(' ', (20 - strlen($category))); + + $sniff = $parts[2]; + if (strlen($sniff) > $maxSniffWidth) { + $sniff = substr($sniff, 0, $maxSniffWidth); + } + + if ($totalFixable > 0) { + echo $sniff.str_repeat(' ', ($width - 39 - strlen($sniff))); + } else { + echo $sniff.str_repeat(' ', ($width - 35 - strlen($sniff))); + } + }//end if + + echo $sourceData['count'].PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'A TOTAL OF '.($totalErrors + $totalWarnings).' SNIFF VIOLATION'; + if (($totalErrors + $totalWarnings) > 1) { + echo 'S'; + } + + echo ' WERE FOUND IN '.count($sources).' SOURCE'; + if (count($sources) !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + + /** + * Converts a camel caps name into a readable string. + * + * @param string $name The camel caps name to convert. + * + * @return string + */ + public function makeFriendlyName($name) + { + if (trim($name) === '') { + return ''; + } + + $friendlyName = ''; + $length = strlen($name); + + $lastWasUpper = false; + $lastWasNumeric = false; + for ($i = 0; $i < $length; $i++) { + if (is_numeric($name[$i]) === true) { + if ($lastWasNumeric === false) { + $friendlyName .= ' '; + } + + $lastWasUpper = false; + $lastWasNumeric = true; + } else { + $lastWasNumeric = false; + + $char = strtolower($name[$i]); + if ($char === $name[$i]) { + // Lowercase. + $lastWasUpper = false; + } else { + // Uppercase. + if ($lastWasUpper === false) { + $friendlyName .= ' '; + if ($i < ($length - 1)) { + $next = $name[($i + 1)]; + if (strtolower($next) === $next) { + // Next char is lowercase so it is a word boundary. + $name[$i] = strtolower($name[$i]); + } + } + } + + $lastWasUpper = true; + } + }//end if + + $friendlyName .= $name[$i]; + }//end for + + $friendlyName = trim($friendlyName); + $friendlyName[0] = strtoupper($friendlyName[0]); + + return $friendlyName; + + }//end makeFriendlyName() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php new file mode 100644 index 000000000..165ad64b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Summary.php @@ -0,0 +1,184 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +class Summary implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + if (PHP_CODESNIFFER_VERBOSITY === 0 + && $report['errors'] === 0 + && $report['warnings'] === 0 + ) { + // Nothing to print. + return false; + } + + echo $report['filename'].'>>'.$report['errors'].'>>'.$report['warnings'].PHP_EOL; + return true; + + }//end generateFileReport() + + + /** + * Generates a summary of errors and warnings for each file processed. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $reportFiles = []; + $maxLength = 0; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + $fileLen = strlen($parts[0]); + $reportFiles[$parts[0]] = [ + 'errors' => $parts[1], + 'warnings' => $parts[2], + 'strlen' => $fileLen, + ]; + + $maxLength = max($maxLength, $fileLen); + } + + uksort( + $reportFiles, + function ($keyA, $keyB) { + $pathPartsA = explode(DIRECTORY_SEPARATOR, $keyA); + $pathPartsB = explode(DIRECTORY_SEPARATOR, $keyB); + + do { + $partA = array_shift($pathPartsA); + $partB = array_shift($pathPartsB); + } while ($partA === $partB && empty($pathPartsA) === false && empty($pathPartsB) === false); + + if (empty($pathPartsA) === false && empty($pathPartsB) === true) { + return 1; + } else if (empty($pathPartsA) === true && empty($pathPartsB) === false) { + return -1; + } else { + return strcasecmp($partA, $partB); + } + } + ); + + $width = min($width, ($maxLength + 21)); + $width = max($width, 70); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER REPORT SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'FILE'.str_repeat(' ', ($width - 20)).'ERRORS WARNINGS'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + + foreach ($reportFiles as $file => $data) { + $padding = ($width - 18 - $data['strlen']); + if ($padding < 0) { + $file = '...'.substr($file, (($padding * -1) + 3)); + $padding = 0; + } + + echo $file.str_repeat(' ', $padding).' '; + if ($data['errors'] !== 0) { + echo "\033[31m".$data['errors']."\033[0m"; + echo str_repeat(' ', (8 - strlen((string) $data['errors']))); + } else { + echo '0 '; + } + + if ($data['warnings'] !== 0) { + echo "\033[33m".$data['warnings']."\033[0m"; + } else { + echo '0'; + } + + echo PHP_EOL; + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1mA TOTAL OF $totalErrors ERROR"; + if ($totalErrors !== 1) { + echo 'S'; + } + + echo ' AND '.$totalWarnings.' WARNING'; + if ($totalWarnings !== 1) { + echo 'S'; + } + + echo ' WERE FOUND IN '.$totalFiles.' FILE'; + if ($totalFiles !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m"; + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php new file mode 100644 index 000000000..b44e83d62 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Svnblame.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Exceptions\DeepExitException; + +class Svnblame extends VersionControl +{ + + /** + * The name of the report we want in the output + * + * @var string + */ + protected $reportName = 'SVN'; + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + protected function getAuthor($line) + { + $blameParts = []; + preg_match('|\s*([^\s]+)\s+([^\s]+)|', $line, $blameParts); + + if (isset($blameParts[2]) === false) { + return false; + } + + return $blameParts[2]; + + }//end getAuthor() + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + protected function getBlameContent($filename) + { + $command = 'svn blame "'.$filename.'" 2>&1'; + $handle = popen($command, 'r'); + if ($handle === false) { + $error = 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $rawContent = stream_get_contents($handle); + pclose($handle); + + $blames = explode("\n", $rawContent); + + return $blames; + + }//end getBlameContent() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php new file mode 100644 index 000000000..296846c7d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php @@ -0,0 +1,377 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Timing; + +abstract class VersionControl implements Report +{ + + /** + * The name of the report we want in the output. + * + * @var string + */ + protected $reportName = 'VERSION CONTROL'; + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $blames = $this->getBlameContent($phpcsFile->getFilename()); + + $authorCache = []; + $praiseCache = []; + $sourceCache = []; + + foreach ($report['messages'] as $line => $lineErrors) { + $author = 'Unknown'; + if (isset($blames[($line - 1)]) === true) { + $blameAuthor = $this->getAuthor($blames[($line - 1)]); + if ($blameAuthor !== false) { + $author = $blameAuthor; + } + } + + if (isset($authorCache[$author]) === false) { + $authorCache[$author] = 0; + $praiseCache[$author] = [ + 'good' => 0, + 'bad' => 0, + ]; + } + + $praiseCache[$author]['bad']++; + + foreach ($lineErrors as $colErrors) { + foreach ($colErrors as $error) { + $authorCache[$author]++; + + if ($showSources === true) { + $source = $error['source']; + if (isset($sourceCache[$author][$source]) === false) { + $sourceCache[$author][$source] = [ + 'count' => 1, + 'fixable' => $error['fixable'], + ]; + } else { + $sourceCache[$author][$source]['count']++; + } + } + } + } + + unset($blames[($line - 1)]); + }//end foreach + + // Now go through and give the authors some credit for + // all the lines that do not have errors. + foreach ($blames as $line) { + $author = $this->getAuthor($line); + if ($author === false) { + $author = 'Unknown'; + } + + if (isset($authorCache[$author]) === false) { + // This author doesn't have any errors. + if (PHP_CODESNIFFER_VERBOSITY === 0) { + continue; + } + + $authorCache[$author] = 0; + $praiseCache[$author] = [ + 'good' => 0, + 'bad' => 0, + ]; + } + + $praiseCache[$author]['good']++; + }//end foreach + + foreach ($authorCache as $author => $errors) { + echo "AUTHOR>>$author>>$errors".PHP_EOL; + } + + foreach ($praiseCache as $author => $praise) { + echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL; + } + + foreach ($sourceCache as $author => $sources) { + foreach ($sources as $source => $sourceData) { + $count = $sourceData['count']; + $fixable = (int) $sourceData['fixable']; + echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL; + } + } + + return true; + + }//end generateFileReport() + + + /** + * Prints the author of all errors and warnings, as given by "version control blame". + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + $errorsShown = ($totalErrors + $totalWarnings); + if ($errorsShown === 0) { + // Nothing to show. + return; + } + + $lines = explode(PHP_EOL, $cachedData); + array_pop($lines); + + if (empty($lines) === true) { + return; + } + + $authorCache = []; + $praiseCache = []; + $sourceCache = []; + + foreach ($lines as $line) { + $parts = explode('>>', $line); + switch ($parts[0]) { + case 'AUTHOR': + if (isset($authorCache[$parts[1]]) === false) { + $authorCache[$parts[1]] = $parts[2]; + } else { + $authorCache[$parts[1]] += $parts[2]; + } + break; + case 'PRAISE': + if (isset($praiseCache[$parts[1]]) === false) { + $praiseCache[$parts[1]] = [ + 'good' => $parts[2], + 'bad' => $parts[3], + ]; + } else { + $praiseCache[$parts[1]]['good'] += $parts[2]; + $praiseCache[$parts[1]]['bad'] += $parts[3]; + } + break; + case 'SOURCE': + if (isset($praiseCache[$parts[1]]) === false) { + $praiseCache[$parts[1]] = []; + } + + if (isset($sourceCache[$parts[1]][$parts[2]]) === false) { + $sourceCache[$parts[1]][$parts[2]] = [ + 'count' => $parts[3], + 'fixable' => (bool) $parts[4], + ]; + } else { + $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3]; + } + break; + default: + break; + }//end switch + }//end foreach + + // Make sure the report width isn't too big. + $maxLength = 0; + foreach ($authorCache as $author => $count) { + $maxLength = max($maxLength, strlen($author)); + if ($showSources === true && isset($sourceCache[$author]) === true) { + foreach ($sourceCache[$author] as $source => $sourceData) { + if ($source === 'count') { + continue; + } + + $maxLength = max($maxLength, (strlen($source) + 9)); + } + } + } + + $width = min($width, ($maxLength + 30)); + $width = max($width, 70); + arsort($authorCache); + + echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL; + echo str_repeat('-', $width).PHP_EOL."\033[1m"; + if ($showSources === true) { + echo 'AUTHOR SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } else { + echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL; + echo str_repeat('-', $width).PHP_EOL; + } + + echo "\033[0m"; + + if ($showSources === true) { + $maxSniffWidth = ($width - 15); + + if ($totalFixable > 0) { + $maxSniffWidth -= 4; + } + } + + $fixableSources = 0; + + foreach ($authorCache as $author => $count) { + if ($praiseCache[$author]['good'] === 0) { + $percent = 0; + } else { + $total = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']); + $percent = round(($praiseCache[$author]['bad'] / $total * 100), 2); + } + + $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')'; + $authorPercent = '('.$percent.')'; + $line = str_repeat(' ', (6 - strlen($count))).$count; + $line = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line; + $line = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line; + $line = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line; + + if ($showSources === true) { + $line = "\033[1m$line\033[0m"; + } + + echo $line.PHP_EOL; + + if ($showSources === true && isset($sourceCache[$author]) === true) { + $errors = $sourceCache[$author]; + asort($errors); + $errors = array_reverse($errors); + + foreach ($errors as $source => $sourceData) { + if ($source === 'count') { + continue; + } + + $count = $sourceData['count']; + + $srcLength = strlen($source); + if ($srcLength > $maxSniffWidth) { + $source = substr($source, 0, $maxSniffWidth); + } + + $line = str_repeat(' ', (5 - strlen($count))).$count; + + echo ' '; + if ($totalFixable > 0) { + echo '['; + if ($sourceData['fixable'] === true) { + echo 'x'; + $fixableSources++; + } else { + echo ' '; + } + + echo '] '; + } + + echo $source; + if ($totalFixable > 0) { + echo str_repeat(' ', ($width - 18 - strlen($source))); + } else { + echo str_repeat(' ', ($width - 14 - strlen($source))); + } + + echo $line.PHP_EOL; + }//end foreach + }//end if + }//end foreach + + echo str_repeat('-', $width).PHP_EOL; + echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION'; + if ($errorsShown !== 1) { + echo 'S'; + } + + echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR'; + if (count($authorCache) !== 1) { + echo 'S'; + } + + echo "\033[0m"; + + if ($totalFixable > 0) { + if ($showSources === true) { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m"; + } else { + echo PHP_EOL.str_repeat('-', $width).PHP_EOL; + echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m"; + } + } + + echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL; + + if ($toScreen === true && $interactive === false) { + Timing::printRunTime(); + } + + }//end generate() + + + /** + * Extract the author from a blame line. + * + * @param string $line Line to parse. + * + * @return mixed string or false if impossible to recover. + */ + abstract protected function getAuthor($line); + + + /** + * Gets the blame output. + * + * @param string $filename File to blame. + * + * @return array + */ + abstract protected function getBlameContent($filename); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php new file mode 100644 index 000000000..68276d80d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Reports/Xml.php @@ -0,0 +1,128 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Reports; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use XMLWriter; + +class Xml implements Report +{ + + + /** + * Generate a partial report for a single processed file. + * + * Function should return TRUE if it printed or stored data about the file + * and FALSE if it ignored the file. Returning TRUE indicates that the file and + * its data should be counted in the grand totals. + * + * @param array $report Prepared report data. + * See the {@see Report} interface for a detailed specification. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * + * @return bool + */ + public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80) + { + $out = new XMLWriter; + $out->openMemory(); + $out->setIndent(true); + $out->setIndentString(' '); + $out->startDocument('1.0', 'UTF-8'); + + if ($report['errors'] === 0 && $report['warnings'] === 0) { + // Nothing to print. + return false; + } + + $out->startElement('file'); + $out->writeAttribute('name', $report['filename']); + $out->writeAttribute('errors', $report['errors']); + $out->writeAttribute('warnings', $report['warnings']); + $out->writeAttribute('fixable', $report['fixable']); + + foreach ($report['messages'] as $line => $lineErrors) { + foreach ($lineErrors as $column => $colErrors) { + foreach ($colErrors as $error) { + $error['type'] = strtolower($error['type']); + if ($phpcsFile->config->encoding !== 'utf-8') { + $error['message'] = iconv($phpcsFile->config->encoding, 'utf-8', $error['message']); + } + + $out->startElement($error['type']); + $out->writeAttribute('line', $line); + $out->writeAttribute('column', $column); + $out->writeAttribute('source', $error['source']); + $out->writeAttribute('severity', $error['severity']); + $out->writeAttribute('fixable', (int) $error['fixable']); + $out->text($error['message']); + $out->endElement(); + } + } + }//end foreach + + $out->endElement(); + + // Remove the start of the document because we will + // add that manually later. We only have it in here to + // properly set the encoding. + $content = $out->flush(); + if (strpos($content, PHP_EOL) !== false) { + $content = substr($content, (strpos($content, PHP_EOL) + strlen(PHP_EOL))); + } else if (strpos($content, "\n") !== false) { + $content = substr($content, (strpos($content, "\n") + 1)); + } + + echo $content; + + return true; + + }//end generateFileReport() + + + /** + * Prints all violations for processed files, in a proprietary XML format. + * + * @param string $cachedData Any partial report data that was returned from + * generateFileReport during the run. + * @param int $totalFiles Total number of files processed during the run. + * @param int $totalErrors Total number of errors found during the run. + * @param int $totalWarnings Total number of warnings found during the run. + * @param int $totalFixable Total number of problems that can be fixed. + * @param bool $showSources Show sources? + * @param int $width Maximum allowed line width. + * @param bool $interactive Are we running in interactive mode? + * @param bool $toScreen Is the report being printed to screen? + * + * @return void + */ + public function generate( + $cachedData, + $totalFiles, + $totalErrors, + $totalWarnings, + $totalFixable, + $showSources=false, + $width=80, + $interactive=false, + $toScreen=true + ) { + echo ''.PHP_EOL; + echo ''.PHP_EOL; + echo $cachedData; + echo ''.PHP_EOL; + + }//end generate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Ruleset.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Ruleset.php new file mode 100644 index 000000000..baa0f32c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Ruleset.php @@ -0,0 +1,1623 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Sniffs\DeprecatedSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Standards; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use ReflectionClass; +use stdClass; + +class Ruleset +{ + + /** + * The name of the coding standard being used. + * + * If a top-level standard includes other standards, or sniffs + * from other standards, only the name of the top-level standard + * will be stored in here. + * + * If multiple top-level standards are being loaded into + * a single ruleset object, this will store a comma separated list + * of the top-level standard names. + * + * @var string + */ + public $name = ''; + + /** + * A list of file paths for the ruleset files being used. + * + * @var string[] + */ + public $paths = []; + + /** + * A list of regular expressions used to ignore specific sniffs for files and folders. + * + * Is also used to set global exclude patterns. + * The key is the regular expression and the value is the type + * of ignore pattern (absolute or relative). + * + * @var array + */ + public $ignorePatterns = []; + + /** + * A list of regular expressions used to include specific sniffs for files and folders. + * + * The key is the sniff code and the value is an array with + * the key being a regular expression and the value is the type + * of ignore pattern (absolute or relative). + * + * @var array> + */ + public $includePatterns = []; + + /** + * An array of sniff objects that are being used to check files. + * + * The key is the fully qualified name of the sniff class + * and the value is the sniff object. + * + * @var array + */ + public $sniffs = []; + + /** + * A mapping of sniff codes to fully qualified class names. + * + * The key is the sniff code and the value + * is the fully qualified name of the sniff class. + * + * @var array + */ + public $sniffCodes = []; + + /** + * An array of token types and the sniffs that are listening for them. + * + * The key is the token name being listened for and the value + * is the sniff object. + * + * @var array>> + */ + public $tokenListeners = []; + + /** + * An array of rules from the ruleset.xml file. + * + * It may be empty, indicating that the ruleset does not override + * any of the default sniff settings. + * + * @var array + */ + public $ruleset = []; + + /** + * The directories that the processed rulesets are in. + * + * @var string[] + */ + protected $rulesetDirs = []; + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + private $config = null; + + /** + * An array of the names of sniffs which have been marked as deprecated. + * + * The key is the sniff code and the value + * is the fully qualified name of the sniff class. + * + * @var array + */ + private $deprecatedSniffs = []; + + + /** + * Initialise the ruleset that the run will use. + * + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If no sniffs were registered. + */ + public function __construct(Config $config) + { + $this->config = $config; + $restrictions = $config->sniffs; + $exclusions = $config->exclude; + $sniffs = []; + + $standardPaths = []; + foreach ($config->standards as $standard) { + $installed = Standards::getInstalledStandardPath($standard); + if ($installed === null) { + $standard = Common::realpath($standard); + if (is_dir($standard) === true + && is_file(Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml')) === true + ) { + $standard = Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml'); + } + } else { + $standard = $installed; + } + + $standardPaths[] = $standard; + } + + foreach ($standardPaths as $standard) { + $ruleset = @simplexml_load_string(file_get_contents($standard)); + if ($ruleset !== false) { + $standardName = (string) $ruleset['name']; + if ($this->name !== '') { + $this->name .= ', '; + } + + $this->name .= $standardName; + + // Allow autoloading of custom files inside this standard. + if (isset($ruleset['namespace']) === true) { + $namespace = (string) $ruleset['namespace']; + } else { + $namespace = basename(dirname($standard)); + } + + Autoload::addSearchPath(dirname($standard), $namespace); + } + + if (defined('PHP_CODESNIFFER_IN_TESTS') === true && empty($restrictions) === false) { + // In unit tests, only register the sniffs that the test wants and not the entire standard. + try { + foreach ($restrictions as $restriction) { + $sniffs = array_merge($sniffs, $this->expandRulesetReference($restriction, dirname($standard))); + } + } catch (RuntimeException $e) { + // Sniff reference could not be expanded, which probably means this + // is an installed standard. Let the unit test system take care of + // setting the correct sniff for testing. + return; + } + + break; + } + + if (PHP_CODESNIFFER_VERBOSITY === 1) { + echo "Registering sniffs in the $standardName standard... "; + if (count($config->standards) > 1 || PHP_CODESNIFFER_VERBOSITY > 2) { + echo PHP_EOL; + } + } + + $sniffs = array_merge($sniffs, $this->processRuleset($standard)); + }//end foreach + + // Ignore sniff restrictions if caching is on. + if ($config->cache === true) { + $restrictions = []; + $exclusions = []; + } + + $sniffRestrictions = []; + foreach ($restrictions as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $sniffRestrictions[$sniffName] = true; + } + + $sniffExclusions = []; + foreach ($exclusions as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $sniffExclusions[$sniffName] = true; + } + + $this->registerSniffs($sniffs, $sniffRestrictions, $sniffExclusions); + $this->populateTokenListeners(); + + $numSniffs = count($this->sniffs); + if (PHP_CODESNIFFER_VERBOSITY === 1) { + echo "DONE ($numSniffs sniffs registered)".PHP_EOL; + } + + if ($numSniffs === 0) { + throw new RuntimeException('No sniffs were registered'); + } + + }//end __construct() + + + /** + * Prints a report showing the sniffs contained in a standard. + * + * @return void + */ + public function explain() + { + $sniffs = array_keys($this->sniffCodes); + sort($sniffs, (SORT_NATURAL | SORT_FLAG_CASE)); + + $sniffCount = count($sniffs); + + // Add a dummy entry to the end so we loop one last time + // and echo out the collected info about the last standard. + $sniffs[] = ''; + + $summaryLine = PHP_EOL."The $this->name standard contains 1 sniff".PHP_EOL; + if ($sniffCount !== 1) { + $summaryLine = str_replace('1 sniff', "$sniffCount sniffs", $summaryLine); + } + + echo $summaryLine; + + $lastStandard = null; + $lastCount = 0; + $sniffsInStandard = []; + + foreach ($sniffs as $i => $sniff) { + if ($i === $sniffCount) { + $currentStandard = null; + } else { + $currentStandard = substr($sniff, 0, strpos($sniff, '.')); + if ($lastStandard === null) { + $lastStandard = $currentStandard; + } + } + + // Reached the first item in the next standard. + // Echo out the info collected from the previous standard. + if ($currentStandard !== $lastStandard) { + $subTitle = $lastStandard.' ('.$lastCount.' sniff'; + if ($lastCount > 1) { + $subTitle .= 's'; + } + + $subTitle .= ')'; + + echo PHP_EOL.$subTitle.PHP_EOL; + echo str_repeat('-', strlen($subTitle)).PHP_EOL; + echo ' '.implode(PHP_EOL.' ', $sniffsInStandard).PHP_EOL; + + $lastStandard = $currentStandard; + $lastCount = 0; + $sniffsInStandard = []; + + if ($currentStandard === null) { + break; + } + }//end if + + if (isset($this->deprecatedSniffs[$sniff]) === true) { + $sniff .= ' *'; + } + + $sniffsInStandard[] = $sniff; + ++$lastCount; + }//end foreach + + if (count($this->deprecatedSniffs) > 0) { + echo PHP_EOL.'* Sniffs marked with an asterix are deprecated.'.PHP_EOL; + } + + }//end explain() + + + /** + * Checks whether any deprecated sniffs were registered via the ruleset. + * + * @return bool + */ + public function hasSniffDeprecations() + { + return (count($this->deprecatedSniffs) > 0); + + }//end hasSniffDeprecations() + + + /** + * Prints an information block about deprecated sniffs being used. + * + * @return void + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException When the interface implementation is faulty. + */ + public function showSniffDeprecations() + { + if ($this->hasSniffDeprecations() === false) { + return; + } + + // Don't show deprecation notices in quiet mode, in explain mode + // or when the documentation is being shown. + // Documentation and explain will mark a sniff as deprecated natively + // and also call the Ruleset multiple times which would lead to duplicate + // display of the deprecation messages. + if ($this->config->quiet === true + || $this->config->explain === true + || $this->config->generator !== null + ) { + return; + } + + $reportWidth = $this->config->reportWidth; + // Message takes report width minus the leading dash + two spaces, minus a one space gutter at the end. + $maxMessageWidth = ($reportWidth - 4); + $maxActualWidth = 0; + + ksort($this->deprecatedSniffs, (SORT_NATURAL | SORT_FLAG_CASE)); + + $messages = []; + $messageTemplate = 'This sniff has been deprecated since %s and will be removed in %s. %s'; + $errorTemplate = 'The %s::%s() method must return a %sstring, received %s'; + + foreach ($this->deprecatedSniffs as $sniffCode => $className) { + if (isset($this->sniffs[$className]) === false) { + // Should only be possible in test situations, but some extra defensive coding is never a bad thing. + continue; + } + + // Verify the interface was implemented correctly. + // Unfortunately can't be safeguarded via type declarations yet. + $deprecatedSince = $this->sniffs[$className]->getDeprecationVersion(); + if (is_string($deprecatedSince) === false) { + throw new RuntimeException( + sprintf($errorTemplate, $className, 'getDeprecationVersion', 'non-empty ', gettype($deprecatedSince)) + ); + } + + if ($deprecatedSince === '') { + throw new RuntimeException( + sprintf($errorTemplate, $className, 'getDeprecationVersion', 'non-empty ', '""') + ); + } + + $removedIn = $this->sniffs[$className]->getRemovalVersion(); + if (is_string($removedIn) === false) { + throw new RuntimeException( + sprintf($errorTemplate, $className, 'getRemovalVersion', 'non-empty ', gettype($removedIn)) + ); + } + + if ($removedIn === '') { + throw new RuntimeException( + sprintf($errorTemplate, $className, 'getRemovalVersion', 'non-empty ', '""') + ); + } + + $customMessage = $this->sniffs[$className]->getDeprecationMessage(); + if (is_string($customMessage) === false) { + throw new RuntimeException( + sprintf($errorTemplate, $className, 'getDeprecationMessage', '', gettype($customMessage)) + ); + } + + // Truncate the error code if there is not enough report width. + if (strlen($sniffCode) > $maxMessageWidth) { + $sniffCode = substr($sniffCode, 0, ($maxMessageWidth - 3)).'...'; + } + + $message = '- '."\033[36m".$sniffCode."\033[0m".PHP_EOL; + $maxActualWidth = max($maxActualWidth, strlen($sniffCode)); + + // Normalize new line characters in custom message. + $customMessage = preg_replace('`\R`', PHP_EOL, $customMessage); + + $notice = trim(sprintf($messageTemplate, $deprecatedSince, $removedIn, $customMessage)); + $maxActualWidth = max($maxActualWidth, min(strlen($notice), $maxMessageWidth)); + $wrapped = wordwrap($notice, $maxMessageWidth, PHP_EOL); + $message .= ' '.implode(PHP_EOL.' ', explode(PHP_EOL, $wrapped)); + + $messages[] = $message; + }//end foreach + + if (count($messages) === 0) { + return; + } + + $summaryLine = "WARNING: The $this->name standard uses 1 deprecated sniff"; + $sniffCount = count($messages); + if ($sniffCount !== 1) { + $summaryLine = str_replace('1 deprecated sniff', "$sniffCount deprecated sniffs", $summaryLine); + } + + $maxActualWidth = max($maxActualWidth, min(strlen($summaryLine), $maxMessageWidth)); + + $summaryLine = wordwrap($summaryLine, $reportWidth, PHP_EOL); + if ($this->config->colors === true) { + echo "\033[33m".$summaryLine."\033[0m".PHP_EOL; + } else { + echo $summaryLine.PHP_EOL; + } + + $messages = implode(PHP_EOL, $messages); + if ($this->config->colors === false) { + $messages = Common::stripColors($messages); + } + + echo str_repeat('-', min(($maxActualWidth + 4), $reportWidth)).PHP_EOL; + echo $messages; + + $closer = wordwrap('Deprecated sniffs are still run, but will stop working at some point in the future.', $reportWidth, PHP_EOL); + echo PHP_EOL.PHP_EOL.$closer.PHP_EOL.PHP_EOL; + + }//end showSniffDeprecations() + + + /** + * Processes a single ruleset and returns a list of the sniffs it represents. + * + * Rules founds within the ruleset are processed immediately, but sniff classes + * are not registered by this method. + * + * @param string $rulesetPath The path to a ruleset XML file. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return string[] + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException - If the ruleset path is invalid. + * - If a specified autoload file could not be found. + */ + public function processRuleset($rulesetPath, $depth=0) + { + $rulesetPath = Common::realpath($rulesetPath); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo 'Processing ruleset '.Common::stripBasepath($rulesetPath, $this->config->basepath).PHP_EOL; + } + + libxml_use_internal_errors(true); + $ruleset = simplexml_load_string(file_get_contents($rulesetPath)); + if ($ruleset === false) { + $errorMsg = "Ruleset $rulesetPath is not valid".PHP_EOL; + $errors = libxml_get_errors(); + foreach ($errors as $error) { + $errorMsg .= '- On line '.$error->line.', column '.$error->column.': '.$error->message; + } + + libxml_clear_errors(); + throw new RuntimeException($errorMsg); + } + + libxml_use_internal_errors(false); + + $ownSniffs = []; + $includedSniffs = []; + $excludedSniffs = []; + + $this->paths[] = $rulesetPath; + $rulesetDir = dirname($rulesetPath); + $this->rulesetDirs[] = $rulesetDir; + + $sniffDir = $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs'; + if (is_dir($sniffDir) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\tAdding sniff files from ".Common::stripBasepath($sniffDir, $this->config->basepath).' directory'.PHP_EOL; + } + + $ownSniffs = $this->expandSniffDirectory($sniffDir, $depth); + } + + // Include custom autoloaders. + foreach ($ruleset->{'autoload'} as $autoload) { + if ($this->shouldProcessElement($autoload) === false) { + continue; + } + + $autoloadPath = (string) $autoload; + + // Try relative autoload paths first. + $relativePath = Common::realPath(dirname($rulesetPath).DIRECTORY_SEPARATOR.$autoloadPath); + + if ($relativePath !== false && is_file($relativePath) === true) { + $autoloadPath = $relativePath; + } else if (is_file($autoloadPath) === false) { + throw new RuntimeException('The specified autoload file "'.$autoload.'" does not exist'); + } + + include_once $autoloadPath; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> included autoloader $autoloadPath".PHP_EOL; + } + }//end foreach + + // Process custom sniff config settings. + foreach ($ruleset->{'config'} as $config) { + if ($this->shouldProcessElement($config) === false) { + continue; + } + + Config::setConfigData((string) $config['name'], (string) $config['value'], true); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set config value ".(string) $config['name'].': '.(string) $config['value'].PHP_EOL; + } + } + + foreach ($ruleset->rule as $rule) { + if (isset($rule['ref']) === false + || $this->shouldProcessElement($rule) === false + ) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\tProcessing rule \"".$rule['ref'].'"'.PHP_EOL; + } + + $expandedSniffs = $this->expandRulesetReference((string) $rule['ref'], $rulesetDir, $depth); + $newSniffs = array_diff($expandedSniffs, $includedSniffs); + $includedSniffs = array_merge($includedSniffs, $expandedSniffs); + + $parts = explode('.', $rule['ref']); + if (count($parts) === 4 + && $parts[0] !== '' + && $parts[1] !== '' + && $parts[2] !== '' + ) { + $sniffCode = $parts[0].'.'.$parts[1].'.'.$parts[2]; + if (isset($this->ruleset[$sniffCode]['severity']) === true + && $this->ruleset[$sniffCode]['severity'] === 0 + ) { + // This sniff code has already been turned off, but now + // it is being explicitly included again, so turn it back on. + $this->ruleset[(string) $rule['ref']]['severity'] = 5; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* disabling sniff exclusion for specific message code *".PHP_EOL; + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to 5".PHP_EOL; + } + } else if (empty($newSniffs) === false) { + $newSniff = $newSniffs[0]; + if (in_array($newSniff, $ownSniffs, true) === false) { + // Including a sniff that hasn't been included higher up, but + // only including a single message from it. So turn off all messages in + // the sniff, except this one. + $this->ruleset[$sniffCode]['severity'] = 0; + $this->ruleset[(string) $rule['ref']]['severity'] = 5; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\tExcluding sniff \"".$sniffCode.'" except for "'.$parts[3].'"'.PHP_EOL; + } + } + }//end if + }//end if + + if (isset($rule->exclude) === true) { + foreach ($rule->exclude as $exclude) { + if (isset($exclude['name']) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* ignoring empty exclude rule *".PHP_EOL; + echo "\t\t\t=> ".$exclude->asXML().PHP_EOL; + } + + continue; + } + + if ($this->shouldProcessElement($exclude) === false) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\tExcluding rule \"".$exclude['name'].'"'.PHP_EOL; + } + + // Check if a single code is being excluded, which is a shortcut + // for setting the severity of the message to 0. + $parts = explode('.', $exclude['name']); + if (count($parts) === 4) { + $this->ruleset[(string) $exclude['name']]['severity'] = 0; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to 0".PHP_EOL; + } + } else { + $excludedSniffs = array_merge( + $excludedSniffs, + $this->expandRulesetReference((string) $exclude['name'], $rulesetDir, ($depth + 1)) + ); + } + }//end foreach + }//end if + + $this->processRule($rule, $newSniffs, $depth); + }//end foreach + + // Process custom command line arguments. + $cliArgs = []; + foreach ($ruleset->{'arg'} as $arg) { + if ($this->shouldProcessElement($arg) === false) { + continue; + } + + if (isset($arg['name']) === true) { + $argString = '--'.(string) $arg['name']; + if (isset($arg['value']) === true) { + $argString .= '='.(string) $arg['value']; + } + } else { + $argString = '-'.(string) $arg['value']; + } + + $cliArgs[] = $argString; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set command line value $argString".PHP_EOL; + } + }//end foreach + + // Set custom php ini values as CLI args. + foreach ($ruleset->{'ini'} as $arg) { + if ($this->shouldProcessElement($arg) === false) { + continue; + } + + if (isset($arg['name']) === false) { + continue; + } + + $name = (string) $arg['name']; + $argString = $name; + if (isset($arg['value']) === true) { + $value = (string) $arg['value']; + $argString .= "=$value"; + } else { + $value = 'true'; + } + + $cliArgs[] = '-d'; + $cliArgs[] = $argString; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> set PHP ini value $name to $value".PHP_EOL; + } + }//end foreach + + if (empty($this->config->files) === true) { + // Process hard-coded file paths. + foreach ($ruleset->{'file'} as $file) { + $file = (string) $file; + $cliArgs[] = $file; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> added \"$file\" to the file list".PHP_EOL; + } + } + } + + if (empty($cliArgs) === false) { + // Change the directory so all relative paths are worked + // out based on the location of the ruleset instead of + // the location of the user. + $inPhar = Common::isPharFile($rulesetDir); + if ($inPhar === false) { + $currentDir = getcwd(); + chdir($rulesetDir); + } + + $this->config->setCommandLineValues($cliArgs); + + if ($inPhar === false) { + chdir($currentDir); + } + } + + // Process custom ignore pattern rules. + foreach ($ruleset->{'exclude-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->ignorePatterns[(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t=> added global ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL; + } + } + + $includedSniffs = array_unique(array_merge($ownSniffs, $includedSniffs)); + $excludedSniffs = array_unique($excludedSniffs); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $included = count($includedSniffs); + $excluded = count($excludedSniffs); + echo str_repeat("\t", $depth); + echo "=> Ruleset processing complete; included $included sniffs and excluded $excluded".PHP_EOL; + } + + // Merge our own sniff list with our externally included + // sniff list, but filter out any excluded sniffs. + $files = []; + foreach ($includedSniffs as $sniff) { + if (in_array($sniff, $excludedSniffs, true) === true) { + continue; + } else { + $files[] = Common::realpath($sniff); + } + } + + return $files; + + }//end processRuleset() + + + /** + * Expands a directory into a list of sniff files within. + * + * @param string $directory The path to a directory. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return array + */ + private function expandSniffDirectory($directory, $depth=0) + { + $sniffs = []; + + $rdi = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::FOLLOW_SYMLINKS); + $di = new RecursiveIteratorIterator($rdi, 0, RecursiveIteratorIterator::CATCH_GET_CHILD); + + $dirLen = strlen($directory); + + foreach ($di as $file) { + $filename = $file->getFilename(); + + // Skip hidden files. + if (substr($filename, 0, 1) === '.') { + continue; + } + + // We are only interested in PHP and sniff files. + $fileParts = explode('.', $filename); + if (array_pop($fileParts) !== 'php') { + continue; + } + + $basename = basename($filename, '.php'); + if (substr($basename, -5) !== 'Sniff') { + continue; + } + + $path = $file->getPathname(); + + // Skip files in hidden directories within the Sniffs directory of this + // standard. We use the offset with strpos() to allow hidden directories + // before, valid example: + // /home/foo/.composer/vendor/squiz/custom_tool/MyStandard/Sniffs/... + if (strpos($path, DIRECTORY_SEPARATOR.'.', $dirLen) !== false) { + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Common::stripBasepath($path, $this->config->basepath).PHP_EOL; + } + + $sniffs[] = $path; + }//end foreach + + return $sniffs; + + }//end expandSniffDirectory() + + + /** + * Expands a ruleset reference into a list of sniff files. + * + * @param string $ref The reference from the ruleset XML file. + * @param string $rulesetDir The directory of the ruleset XML file, used to + * evaluate relative paths. + * @param int $depth How many nested processing steps we are in. This + * is only used for debug output. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the reference is invalid. + */ + private function expandRulesetReference($ref, $rulesetDir, $depth=0) + { + // Ignore internal sniffs codes as they are used to only + // hide and change internal messages. + if (substr($ref, 0, 9) === 'Internal.') { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* ignoring internal sniff code *".PHP_EOL; + } + + return []; + } + + // As sniffs can't begin with a full stop, assume references in + // this format are relative paths and attempt to convert them + // to absolute paths. If this fails, let the reference run through + // the normal checks and have it fail as normal. + if (substr($ref, 0, 1) === '.') { + $realpath = Common::realpath($rulesetDir.'/'.$ref); + if ($realpath !== false) { + $ref = $realpath; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } + } + + // As sniffs can't begin with a tilde, assume references in + // this format are relative to the user's home directory. + if (substr($ref, 0, 2) === '~/') { + $realpath = Common::realpath($ref); + if ($realpath !== false) { + $ref = $realpath; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } + } + + if (is_file($ref) === true) { + if (substr($ref, -9) === 'Sniff.php') { + // A single external sniff. + $this->rulesetDirs[] = dirname(dirname(dirname($ref))); + return [$ref]; + } + } else { + // See if this is a whole standard being referenced. + $path = Standards::getInstalledStandardPath($ref); + if ($path !== null && Common::isPharFile($path) === true && strpos($path, 'ruleset.xml') === false) { + // If the ruleset exists inside the phar file, use it. + if (file_exists($path.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { + $path .= DIRECTORY_SEPARATOR.'ruleset.xml'; + } else { + $path = null; + } + } + + if ($path !== null) { + $ref = $path; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + } else if (is_dir($ref) === false) { + // Work out the sniff path. + $sepPos = strpos($ref, DIRECTORY_SEPARATOR); + if ($sepPos !== false) { + $stdName = substr($ref, 0, $sepPos); + $path = substr($ref, $sepPos); + } else { + $parts = explode('.', $ref); + $stdName = $parts[0]; + if (count($parts) === 1) { + // A whole standard? + $path = ''; + } else if (count($parts) === 2) { + // A directory of sniffs? + $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1]; + } else { + // A single sniff? + $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1].DIRECTORY_SEPARATOR.$parts[2].'Sniff.php'; + } + } + + $newRef = false; + $stdPath = Standards::getInstalledStandardPath($stdName); + if ($stdPath !== null && $path !== '') { + if (Common::isPharFile($stdPath) === true + && strpos($stdPath, 'ruleset.xml') === false + ) { + // Phar files can only return the directory, + // since ruleset can be omitted if building one standard. + $newRef = Common::realpath($stdPath.$path); + } else { + $newRef = Common::realpath(dirname($stdPath).$path); + } + } + + if ($newRef === false) { + // The sniff is not locally installed, so check if it is being + // referenced as a remote sniff outside the install. We do this + // by looking through all directories where we have found ruleset + // files before, looking for ones for this particular standard, + // and seeing if it is in there. + foreach ($this->rulesetDirs as $dir) { + if (strtolower(basename($dir)) !== strtolower($stdName)) { + continue; + } + + $newRef = Common::realpath($dir.$path); + + if ($newRef !== false) { + $ref = $newRef; + } + } + } else { + $ref = $newRef; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + } + }//end if + }//end if + + if (is_dir($ref) === true) { + if (is_file($ref.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { + // We are referencing an external coding standard. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a standard using directory name; processing *".PHP_EOL; + } + + return $this->processRuleset($ref.DIRECTORY_SEPARATOR.'ruleset.xml', ($depth + 2)); + } else { + // We are referencing a whole directory of sniffs. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a directory of sniffs *".PHP_EOL; + echo str_repeat("\t", $depth); + echo "\t\tAdding sniff files from directory".PHP_EOL; + } + + return $this->expandSniffDirectory($ref, ($depth + 1)); + } + } else { + if (is_file($ref) === false) { + $error = "Referenced sniff \"$ref\" does not exist"; + throw new RuntimeException($error); + } + + if (substr($ref, -9) === 'Sniff.php') { + // A single sniff. + return [$ref]; + } else { + // Assume an external ruleset.xml file. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t* rule is referencing a standard using ruleset path; processing *".PHP_EOL; + } + + return $this->processRuleset($ref, ($depth + 2)); + } + }//end if + + }//end expandRulesetReference() + + + /** + * Processes a rule from a ruleset XML file, overriding built-in defaults. + * + * @param \SimpleXMLElement $rule The rule object from a ruleset XML file. + * @param string[] $newSniffs An array of sniffs that got included by this rule. + * @param int $depth How many nested processing steps we are in. + * This is only used for debug output. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If rule settings are invalid. + */ + private function processRule($rule, $newSniffs, $depth=0) + { + $ref = (string) $rule['ref']; + $todo = [$ref]; + + $parts = explode('.', $ref); + $partsCount = count($parts); + if ($partsCount <= 2 + || $partsCount > count(array_filter($parts)) + || in_array($ref, $newSniffs) === true + ) { + // We are processing a standard, a category of sniffs or a relative path inclusion. + foreach ($newSniffs as $sniffFile) { + $parts = explode(DIRECTORY_SEPARATOR, $sniffFile); + if (count($parts) === 1 && DIRECTORY_SEPARATOR === '\\') { + // Path using forward slashes while running on Windows. + $parts = explode('/', $sniffFile); + } + + $sniffName = array_pop($parts); + $sniffCategory = array_pop($parts); + array_pop($parts); + $sniffStandard = array_pop($parts); + $todo[] = $sniffStandard.'.'.$sniffCategory.'.'.substr($sniffName, 0, -9); + } + } + + foreach ($todo as $code) { + // Custom severity. + if (isset($rule->severity) === true + && $this->shouldProcessElement($rule->severity) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $this->ruleset[$code]['severity'] = (int) $rule->severity; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> severity set to ".(int) $rule->severity; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } + + // Custom message type. + if (isset($rule->type) === true + && $this->shouldProcessElement($rule->type) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $type = strtolower((string) $rule->type); + if ($type !== 'error' && $type !== 'warning') { + throw new RuntimeException("Message type \"$type\" is invalid; must be \"error\" or \"warning\""); + } + + $this->ruleset[$code]['type'] = $type; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> message type set to ".(string) $rule->type; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + }//end if + + // Custom message. + if (isset($rule->message) === true + && $this->shouldProcessElement($rule->message) === true + ) { + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = []; + } + + $this->ruleset[$code]['message'] = (string) $rule->message; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> message set to ".(string) $rule->message; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } + + // Custom properties. + if (isset($rule->properties) === true + && $this->shouldProcessElement($rule->properties) === true + ) { + $propertyScope = 'standard'; + if ($code === $ref || substr($ref, -9) === 'Sniff.php') { + $propertyScope = 'sniff'; + } + + foreach ($rule->properties->property as $prop) { + if ($this->shouldProcessElement($prop) === false) { + continue; + } + + if (isset($this->ruleset[$code]) === false) { + $this->ruleset[$code] = [ + 'properties' => [], + ]; + } else if (isset($this->ruleset[$code]['properties']) === false) { + $this->ruleset[$code]['properties'] = []; + } + + $name = (string) $prop['name']; + if (isset($prop['type']) === true + && (string) $prop['type'] === 'array' + ) { + $values = []; + if (isset($prop['extend']) === true + && (string) $prop['extend'] === 'true' + && isset($this->ruleset[$code]['properties'][$name]['value']) === true + ) { + $values = $this->ruleset[$code]['properties'][$name]['value']; + } + + if (isset($prop->element) === true) { + $printValue = ''; + foreach ($prop->element as $element) { + if ($this->shouldProcessElement($element) === false) { + continue; + } + + $value = (string) $element['value']; + if (isset($element['key']) === true) { + $key = (string) $element['key']; + $values[$key] = $value; + $printValue .= $key.'=>'.$value.','; + } else { + $values[] = $value; + $printValue .= $value.','; + } + } + + $printValue = rtrim($printValue, ','); + } else { + $value = (string) $prop['value']; + $printValue = $value; + foreach (explode(',', $value) as $val) { + list($k, $v) = explode('=>', $val.'=>'); + if ($v !== '') { + $values[trim($k)] = trim($v); + } else { + $values[] = trim($k); + } + } + }//end if + + $this->ruleset[$code]['properties'][$name] = [ + 'value' => $values, + 'scope' => $propertyScope, + ]; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> array property \"$name\" set to \"$printValue\""; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + } else { + $this->ruleset[$code]['properties'][$name] = [ + 'value' => (string) $prop['value'], + 'scope' => $propertyScope, + ]; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> property \"$name\" set to \"".(string) $prop['value'].'"'; + if ($code !== $ref) { + echo " for $code"; + } + + echo PHP_EOL; + } + }//end if + }//end foreach + }//end if + + // Ignore patterns. + foreach ($rule->{'exclude-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($this->ignorePatterns[$code]) === false) { + $this->ignorePatterns[$code] = []; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->ignorePatterns[$code][(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> added rule-specific ".(string) $pattern['type'].' ignore pattern'; + if ($code !== $ref) { + echo " for $code"; + } + + echo ': '.(string) $pattern.PHP_EOL; + } + }//end foreach + + // Include patterns. + foreach ($rule->{'include-pattern'} as $pattern) { + if ($this->shouldProcessElement($pattern) === false) { + continue; + } + + if (isset($this->includePatterns[$code]) === false) { + $this->includePatterns[$code] = []; + } + + if (isset($pattern['type']) === false) { + $pattern['type'] = 'absolute'; + } + + $this->includePatterns[$code][(string) $pattern] = (string) $pattern['type']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "\t\t=> added rule-specific ".(string) $pattern['type'].' include pattern'; + if ($code !== $ref) { + echo " for $code"; + } + + echo ': '.(string) $pattern.PHP_EOL; + } + }//end foreach + }//end foreach + + }//end processRule() + + + /** + * Determine if an element should be processed or ignored. + * + * @param \SimpleXMLElement $element An object from a ruleset XML file. + * + * @return bool + */ + private function shouldProcessElement($element) + { + if (isset($element['phpcbf-only']) === false + && isset($element['phpcs-only']) === false + ) { + // No exceptions are being made. + return true; + } + + if (PHP_CODESNIFFER_CBF === true + && isset($element['phpcbf-only']) === true + && (string) $element['phpcbf-only'] === 'true' + ) { + return true; + } + + if (PHP_CODESNIFFER_CBF === false + && isset($element['phpcs-only']) === true + && (string) $element['phpcs-only'] === 'true' + ) { + return true; + } + + return false; + + }//end shouldProcessElement() + + + /** + * Loads and stores sniffs objects used for sniffing files. + * + * @param array $files Paths to the sniff files to register. + * @param array $restrictions The sniff class names to restrict the allowed + * listeners to. + * @param array $exclusions The sniff class names to exclude from the + * listeners list. + * + * @return void + */ + public function registerSniffs($files, $restrictions, $exclusions) + { + $listeners = []; + + foreach ($files as $file) { + // Work out where the position of /StandardName/Sniffs/... is + // so we can determine what the class will be called. + $sniffPos = strrpos($file, DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR); + if ($sniffPos === false) { + continue; + } + + $slashPos = strrpos(substr($file, 0, $sniffPos), DIRECTORY_SEPARATOR); + if ($slashPos === false) { + continue; + } + + $className = Autoload::loadFile($file); + $compareName = Common::cleanSniffClass($className); + + // If they have specified a list of sniffs to restrict to, check + // to see if this sniff is allowed. + if (empty($restrictions) === false + && isset($restrictions[$compareName]) === false + ) { + continue; + } + + // If they have specified a list of sniffs to exclude, check + // to see if this sniff is allowed. + if (empty($exclusions) === false + && isset($exclusions[$compareName]) === true + ) { + continue; + } + + // Skip abstract classes. + $reflection = new ReflectionClass($className); + if ($reflection->isAbstract() === true) { + continue; + } + + $listeners[$className] = $className; + + if (PHP_CODESNIFFER_VERBOSITY > 2) { + echo "Registered $className".PHP_EOL; + } + }//end foreach + + $this->sniffs = $listeners; + + }//end registerSniffs() + + + /** + * Populates the array of PHP_CodeSniffer_Sniff objects for this file. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If sniff registration fails. + */ + public function populateTokenListeners() + { + // Construct a list of listeners indexed by token being listened for. + $this->tokenListeners = []; + + foreach ($this->sniffs as $sniffClass => $sniffObject) { + $this->sniffs[$sniffClass] = null; + $this->sniffs[$sniffClass] = new $sniffClass(); + + $sniffCode = Common::getSniffCode($sniffClass); + $this->sniffCodes[$sniffCode] = $sniffClass; + + if ($this->sniffs[$sniffClass] instanceof DeprecatedSniff) { + $this->deprecatedSniffs[$sniffCode] = $sniffClass; + } + + // Set custom properties. + if (isset($this->ruleset[$sniffCode]['properties']) === true) { + foreach ($this->ruleset[$sniffCode]['properties'] as $name => $settings) { + $this->setSniffProperty($sniffClass, $name, $settings); + } + } + + $tokenizers = []; + $vars = get_class_vars($sniffClass); + if (isset($vars['supportedTokenizers']) === true) { + foreach ($vars['supportedTokenizers'] as $tokenizer) { + $tokenizers[$tokenizer] = $tokenizer; + } + } else { + $tokenizers = ['PHP' => 'PHP']; + } + + $tokens = $this->sniffs[$sniffClass]->register(); + if (is_array($tokens) === false) { + $msg = "Sniff $sniffClass register() method must return an array"; + throw new RuntimeException($msg); + } + + $ignorePatterns = []; + $patterns = $this->getIgnorePatterns($sniffCode); + foreach ($patterns as $pattern => $type) { + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + $ignorePatterns[] = strtr($pattern, $replacements); + } + + $includePatterns = []; + $patterns = $this->getIncludePatterns($sniffCode); + foreach ($patterns as $pattern => $type) { + $replacements = [ + '\\,' => ',', + '*' => '.*', + ]; + + $includePatterns[] = strtr($pattern, $replacements); + } + + foreach ($tokens as $token) { + if (isset($this->tokenListeners[$token]) === false) { + $this->tokenListeners[$token] = []; + } + + if (isset($this->tokenListeners[$token][$sniffClass]) === false) { + $this->tokenListeners[$token][$sniffClass] = [ + 'class' => $sniffClass, + 'source' => $sniffCode, + 'tokenizers' => $tokenizers, + 'ignore' => $ignorePatterns, + 'include' => $includePatterns, + ]; + } + } + }//end foreach + + }//end populateTokenListeners() + + + /** + * Set a single property for a sniff. + * + * @param string $sniffClass The class name of the sniff. + * @param string $name The name of the property to change. + * @param array $settings Array with the new value of the property and the scope of the property being set. + * + * @return void + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException When attempting to set a non-existent property on a sniff + * which doesn't declare the property or explicitly supports + * dynamic properties. + */ + public function setSniffProperty($sniffClass, $name, $settings) + { + // Setting a property for a sniff we are not using. + if (isset($this->sniffs[$sniffClass]) === false) { + return; + } + + $name = trim($name); + $propertyName = $name; + if (substr($propertyName, -2) === '[]') { + $propertyName = substr($propertyName, 0, -2); + } + + /* + * BC-compatibility layer for $settings using the pre-PHPCS 3.8.0 format. + * + * Prior to PHPCS 3.8.0, `$settings` was expected to only contain the new _value_ + * for the property (which could be an array). + * Since PHPCS 3.8.0, `$settings` is expected to be an array with two keys: 'scope' + * and 'value', where 'scope' indicates whether the property should be set to the given 'value' + * for one individual sniff or for all sniffs in a standard. + * + * This BC-layer is only for integrations with PHPCS which may call this method directly + * and will be removed in PHPCS 4.0.0. + */ + + if (is_array($settings) === false + || isset($settings['scope'], $settings['value']) === false + ) { + // This will be an "old" format value. + $settings = [ + 'value' => $settings, + 'scope' => 'standard', + ]; + + trigger_error( + __FUNCTION__.': the format of the $settings parameter has changed from (mixed) $value to array(\'scope\' => \'sniff|standard\', \'value\' => $value). Please update your integration code. See PR #3629 for more information.', + E_USER_DEPRECATED + ); + } + + $isSettable = false; + $sniffObject = $this->sniffs[$sniffClass]; + if (property_exists($sniffObject, $propertyName) === true + || ($sniffObject instanceof stdClass) === true + || method_exists($sniffObject, '__set') === true + ) { + $isSettable = true; + } + + if ($isSettable === false) { + if ($settings['scope'] === 'sniff') { + $notice = "Ruleset invalid. Property \"$propertyName\" does not exist on sniff "; + $notice .= array_search($sniffClass, $this->sniffCodes, true); + throw new RuntimeException($notice); + } + + return; + } + + $value = $settings['value']; + + if (is_string($value) === true) { + $value = trim($value); + } + + if ($value === '') { + $value = null; + } + + // Special case for booleans. + if ($value === 'true') { + $value = true; + } else if ($value === 'false') { + $value = false; + } else if (substr($name, -2) === '[]') { + $name = $propertyName; + $values = []; + if ($value !== null) { + foreach (explode(',', $value) as $val) { + list($k, $v) = explode('=>', $val.'=>'); + if ($v !== '') { + $values[trim($k)] = trim($v); + } else { + $values[] = trim($k); + } + } + } + + $value = $values; + } + + $sniffObject->$name = $value; + + }//end setSniffProperty() + + + /** + * Gets the array of ignore patterns. + * + * Optionally takes a listener to get ignore patterns specified + * for that sniff only. + * + * @param string $listener The listener to get patterns for. If NULL, all + * patterns are returned. + * + * @return array + */ + public function getIgnorePatterns($listener=null) + { + if ($listener === null) { + return $this->ignorePatterns; + } + + if (isset($this->ignorePatterns[$listener]) === true) { + return $this->ignorePatterns[$listener]; + } + + return []; + + }//end getIgnorePatterns() + + + /** + * Gets the array of include patterns. + * + * Optionally takes a listener to get include patterns specified + * for that sniff only. + * + * @param string $listener The listener to get patterns for. If NULL, all + * patterns are returned. + * + * @return array + */ + public function getIncludePatterns($listener=null) + { + if ($listener === null) { + return $this->includePatterns; + } + + if (isset($this->includePatterns[$listener]) === true) { + return $this->includePatterns[$listener]; + } + + return []; + + }//end getIncludePatterns() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Runner.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Runner.php new file mode 100644 index 000000000..20c2eddf4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Runner.php @@ -0,0 +1,992 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer; + +use Exception; +use InvalidArgumentException; +use PHP_CodeSniffer\Exceptions\DeepExitException; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Files\FileList; +use PHP_CodeSniffer\Util\Cache; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Standards; +use PHP_CodeSniffer\Util\Timing; +use PHP_CodeSniffer\Util\Tokens; + +class Runner +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + public $config = null; + + /** + * The ruleset used for the run. + * + * @var \PHP_CodeSniffer\Ruleset + */ + public $ruleset = null; + + /** + * The reporter used for generating reports after the run. + * + * @var \PHP_CodeSniffer\Reporter + */ + public $reporter = null; + + + /** + * Run the PHPCS script. + * + * @return int + */ + public function runPHPCS() + { + $this->registerOutOfMemoryShutdownMessage('phpcs'); + + try { + Timing::startTiming(); + Runner::checkRequirements(); + + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + + // Creating the Config object populates it with all required settings + // based on the CLI arguments provided to the script and any config + // values the user has set. + $this->config = new Config(); + + // Init the run and load the rulesets to set additional config vars. + $this->init(); + + // Print a list of sniffs in each of the supplied standards. + // We fudge the config here so that each standard is explained in isolation. + if ($this->config->explain === true) { + $standards = $this->config->standards; + foreach ($standards as $standard) { + $this->config->standards = [$standard]; + $ruleset = new Ruleset($this->config); + $ruleset->explain(); + } + + return 0; + } + + // Generate documentation for each of the supplied standards. + if ($this->config->generator !== null) { + $standards = $this->config->standards; + foreach ($standards as $standard) { + $this->config->standards = [$standard]; + $ruleset = new Ruleset($this->config); + $class = 'PHP_CodeSniffer\Generators\\'.$this->config->generator; + $generator = new $class($ruleset); + $generator->generate(); + } + + return 0; + } + + // Other report formats don't really make sense in interactive mode + // so we hard-code the full report here and when outputting. + // We also ensure parallel processing is off because we need to do one file at a time. + if ($this->config->interactive === true) { + $this->config->reports = ['full' => null]; + $this->config->parallel = 1; + $this->config->showProgress = false; + } + + // Disable caching if we are processing STDIN as we can't be 100% + // sure where the file came from or if it will change in the future. + if ($this->config->stdin === true) { + $this->config->cache = false; + } + + $numErrors = $this->run(); + + // Print all the reports for this run. + $toScreen = $this->reporter->printReports(); + + // Only print timer output if no reports were + // printed to the screen so we don't put additional output + // in something like an XML report. If we are printing to screen, + // the report types would have already worked out who should + // print the timer info. + if ($this->config->interactive === false + && ($toScreen === false + || (($this->reporter->totalErrors + $this->reporter->totalWarnings) === 0 && $this->config->showProgress === true)) + ) { + Timing::printRunTime(); + } + } catch (DeepExitException $e) { + echo $e->getMessage(); + return $e->getCode(); + }//end try + + if ($numErrors === 0) { + // No errors found. + return 0; + } else if ($this->reporter->totalFixable === 0) { + // Errors found, but none of them can be fixed by PHPCBF. + return 1; + } else { + // Errors found, and some can be fixed by PHPCBF. + return 2; + } + + }//end runPHPCS() + + + /** + * Run the PHPCBF script. + * + * @return int + */ + public function runPHPCBF() + { + $this->registerOutOfMemoryShutdownMessage('phpcbf'); + + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', true); + } + + try { + Timing::startTiming(); + Runner::checkRequirements(); + + // Creating the Config object populates it with all required settings + // based on the CLI arguments provided to the script and any config + // values the user has set. + $this->config = new Config(); + + // When processing STDIN, we can't output anything to the screen + // or it will end up mixed in with the file output. + if ($this->config->stdin === true) { + $this->config->verbosity = 0; + } + + // Init the run and load the rulesets to set additional config vars. + $this->init(); + + // When processing STDIN, we only process one file at a time and + // we don't process all the way through, so we can't use the parallel + // running system. + if ($this->config->stdin === true) { + $this->config->parallel = 1; + } + + // Override some of the command line settings that might break the fixes. + $this->config->generator = null; + $this->config->explain = false; + $this->config->interactive = false; + $this->config->cache = false; + $this->config->showSources = false; + $this->config->recordErrors = false; + $this->config->reportFile = null; + + // Only use the "Cbf" report, but allow for the Performance report as well. + $originalReports = array_change_key_case($this->config->reports, CASE_LOWER); + $newReports = ['cbf' => null]; + if (array_key_exists('performance', $originalReports) === true) { + $newReports['performance'] = $originalReports['performance']; + } + + $this->config->reports = $newReports; + + // If a standard tries to set command line arguments itself, some + // may be blocked because PHPCBF is running, so stop the script + // dying if any are found. + $this->config->dieOnUnknownArg = false; + + $this->run(); + $this->reporter->printReports(); + + echo PHP_EOL; + Timing::printRunTime(); + } catch (DeepExitException $e) { + echo $e->getMessage(); + return $e->getCode(); + }//end try + + if ($this->reporter->totalFixed === 0) { + // Nothing was fixed by PHPCBF. + if ($this->reporter->totalFixable === 0) { + // Nothing found that could be fixed. + return 0; + } else { + // Something failed to fix. + return 2; + } + } + + if ($this->reporter->totalFixable === 0) { + // PHPCBF fixed all fixable errors. + return 1; + } + + // PHPCBF fixed some fixable errors, but others failed to fix. + return 2; + + }//end runPHPCBF() + + + /** + * Exits if the minimum requirements of PHP_CodeSniffer are not met. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If the requirements are not met. + */ + public function checkRequirements() + { + // Check the PHP version. + if (PHP_VERSION_ID < 50400) { + $error = 'ERROR: PHP_CodeSniffer requires PHP version 5.4.0 or greater.'.PHP_EOL; + throw new DeepExitException($error, 3); + } + + $requiredExtensions = [ + 'tokenizer', + 'xmlwriter', + 'SimpleXML', + ]; + $missingExtensions = []; + + foreach ($requiredExtensions as $extension) { + if (extension_loaded($extension) === false) { + $missingExtensions[] = $extension; + } + } + + if (empty($missingExtensions) === false) { + $last = array_pop($requiredExtensions); + $required = implode(', ', $requiredExtensions); + $required .= ' and '.$last; + + if (count($missingExtensions) === 1) { + $missing = $missingExtensions[0]; + } else { + $last = array_pop($missingExtensions); + $missing = implode(', ', $missingExtensions); + $missing .= ' and '.$last; + } + + $error = 'ERROR: PHP_CodeSniffer requires the %s extensions to be enabled. Please enable %s.'.PHP_EOL; + $error = sprintf($error, $required, $missing); + throw new DeepExitException($error, 3); + } + + }//end checkRequirements() + + + /** + * Init the rulesets and other high-level settings. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException If a referenced standard is not installed. + */ + public function init() + { + if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); + } + + // Ensure this option is enabled or else line endings will not always + // be detected properly for files created on a Mac with the /r line ending. + @ini_set('auto_detect_line_endings', true); + + // Disable the PCRE JIT as this caused issues with parallel running. + ini_set('pcre.jit', false); + + // Check that the standards are valid. + foreach ($this->config->standards as $standard) { + if (Standards::isInstalledStandard($standard) === false) { + // They didn't select a valid coding standard, so help them + // out by letting them know which standards are installed. + $error = 'ERROR: the "'.$standard.'" coding standard is not installed. '; + ob_start(); + Standards::printInstalledStandards(); + $error .= ob_get_contents(); + ob_end_clean(); + throw new DeepExitException($error, 3); + } + } + + // Saves passing the Config object into other objects that only need + // the verbosity flag for debug output. + if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', $this->config->verbosity); + } + + // Create this class so it is autoloaded and sets up a bunch + // of PHP_CodeSniffer-specific token type constants. + new Tokens(); + + // Allow autoloading of custom files inside installed standards. + $installedStandards = Standards::getInstalledStandardDetails(); + foreach ($installedStandards as $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + } + + // The ruleset contains all the information about how the files + // should be checked and/or fixed. + try { + $this->ruleset = new Ruleset($this->config); + + if ($this->ruleset->hasSniffDeprecations() === true) { + $this->ruleset->showSniffDeprecations(); + } + } catch (RuntimeException $e) { + $error = 'ERROR: '.$e->getMessage().PHP_EOL.PHP_EOL; + $error .= $this->config->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + }//end init() + + + /** + * Performs the run. + * + * @return int The number of errors and warnings found. + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + private function run() + { + // The class that manages all reporters for the run. + $this->reporter = new Reporter($this->config); + + // Include bootstrap files. + foreach ($this->config->bootstrap as $bootstrap) { + include $bootstrap; + } + + if ($this->config->stdin === true) { + $fileContents = $this->config->stdinContent; + if ($fileContents === null) { + $handle = fopen('php://stdin', 'r'); + stream_set_blocking($handle, true); + $fileContents = stream_get_contents($handle); + fclose($handle); + } + + $todo = new FileList($this->config, $this->ruleset); + $dummy = new DummyFile($fileContents, $this->ruleset, $this->config); + $todo->addFile($dummy->path, $dummy); + } else { + if (empty($this->config->files) === true) { + $error = 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL; + $error .= $this->config->printShortUsage(true); + throw new DeepExitException($error, 3); + } + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Creating file list... '; + } + + $todo = new FileList($this->config, $this->ruleset); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $numFiles = count($todo); + echo "DONE ($numFiles files in queue)".PHP_EOL; + } + + if ($this->config->cache === true) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Loading cache... '; + } + + Cache::load($this->ruleset, $this->config); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $size = Cache::getSize(); + echo "DONE ($size files in cache)".PHP_EOL; + } + } + }//end if + + // Turn all sniff errors into exceptions. + set_error_handler([$this, 'handleErrors']); + + // If verbosity is too high, turn off parallelism so the + // debug output is clean. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $this->config->parallel = 1; + } + + // If the PCNTL extension isn't installed, we can't fork. + if (function_exists('pcntl_fork') === false) { + $this->config->parallel = 1; + } + + $lastDir = ''; + $numFiles = count($todo); + + if ($this->config->parallel === 1) { + // Running normally. + $numProcessed = 0; + foreach ($todo as $path => $file) { + if ($file->ignored === false) { + $currDir = dirname($path); + if ($lastDir !== $currDir) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + } + + $lastDir = $currDir; + } + + $this->processFile($file); + } else if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Skipping '.basename($file->path).PHP_EOL; + } + + $numProcessed++; + $this->printProgress($file, $numFiles, $numProcessed); + } + } else { + // Batching and forking. + $childProcs = []; + $numPerBatch = ceil($numFiles / $this->config->parallel); + + for ($batch = 0; $batch < $this->config->parallel; $batch++) { + $startAt = ($batch * $numPerBatch); + if ($startAt >= $numFiles) { + break; + } + + $endAt = ($startAt + $numPerBatch); + if ($endAt > $numFiles) { + $endAt = $numFiles; + } + + $childOutFilename = tempnam(sys_get_temp_dir(), 'phpcs-child'); + $pid = pcntl_fork(); + if ($pid === -1) { + throw new RuntimeException('Failed to create child process'); + } else if ($pid !== 0) { + $childProcs[$pid] = $childOutFilename; + } else { + // Move forward to the start of the batch. + $todo->rewind(); + for ($i = 0; $i < $startAt; $i++) { + $todo->next(); + } + + // Reset the reporter to make sure only figures from this + // file batch are recorded. + $this->reporter->totalFiles = 0; + $this->reporter->totalErrors = 0; + $this->reporter->totalWarnings = 0; + $this->reporter->totalFixable = 0; + $this->reporter->totalFixed = 0; + + // Process the files. + $pathsProcessed = []; + ob_start(); + for ($i = $startAt; $i < $endAt; $i++) { + $path = $todo->key(); + $file = $todo->current(); + + if ($file->ignored === true) { + $todo->next(); + continue; + } + + $currDir = dirname($path); + if ($lastDir !== $currDir) { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + } + + $lastDir = $currDir; + } + + $this->processFile($file); + + $pathsProcessed[] = $path; + $todo->next(); + }//end for + + $debugOutput = ob_get_contents(); + ob_end_clean(); + + // Write information about the run to the filesystem + // so it can be picked up by the main process. + $childOutput = [ + 'totalFiles' => $this->reporter->totalFiles, + 'totalErrors' => $this->reporter->totalErrors, + 'totalWarnings' => $this->reporter->totalWarnings, + 'totalFixable' => $this->reporter->totalFixable, + 'totalFixed' => $this->reporter->totalFixed, + ]; + + $output = '<'.'?php'."\n".' $childOutput = '; + $output .= var_export($childOutput, true); + $output .= ";\n\$debugOutput = "; + $output .= var_export($debugOutput, true); + + if ($this->config->cache === true) { + $childCache = []; + foreach ($pathsProcessed as $path) { + $childCache[$path] = Cache::get($path); + } + + $output .= ";\n\$childCache = "; + $output .= var_export($childCache, true); + } + + $output .= ";\n?".'>'; + file_put_contents($childOutFilename, $output); + exit(); + }//end if + }//end for + + $success = $this->processChildProcs($childProcs); + if ($success === false) { + throw new RuntimeException('One or more child processes failed to run'); + } + }//end if + + restore_error_handler(); + + if (PHP_CODESNIFFER_VERBOSITY === 0 + && $this->config->interactive === false + && $this->config->showProgress === true + ) { + echo PHP_EOL.PHP_EOL; + } + + if ($this->config->cache === true) { + Cache::save(); + } + + $ignoreWarnings = Config::getConfigData('ignore_warnings_on_exit'); + $ignoreErrors = Config::getConfigData('ignore_errors_on_exit'); + + $return = ($this->reporter->totalErrors + $this->reporter->totalWarnings); + if ($ignoreErrors !== null) { + $ignoreErrors = (bool) $ignoreErrors; + if ($ignoreErrors === true) { + $return -= $this->reporter->totalErrors; + } + } + + if ($ignoreWarnings !== null) { + $ignoreWarnings = (bool) $ignoreWarnings; + if ($ignoreWarnings === true) { + $return -= $this->reporter->totalWarnings; + } + } + + return $return; + + }//end run() + + + /** + * Converts all PHP errors into exceptions. + * + * This method forces a sniff to stop processing if it is not + * able to handle a specific piece of code, instead of continuing + * and potentially getting into a loop. + * + * @param int $code The level of error raised. + * @param string $message The error message. + * @param string $file The path of the file that raised the error. + * @param int $line The line number the error was raised at. + * + * @return bool + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function handleErrors($code, $message, $file, $line) + { + if ((error_reporting() & $code) === 0) { + // This type of error is being muted. + return true; + } + + throw new RuntimeException("$message in $file on line $line"); + + }//end handleErrors() + + + /** + * Processes a single file, including checking and fixing. + * + * @param \PHP_CodeSniffer\Files\File $file The file to be processed. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\DeepExitException + */ + public function processFile($file) + { + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $startTime = microtime(true); + echo 'Processing '.basename($file->path).' '; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + } + + try { + $file->process(); + + if (PHP_CODESNIFFER_VERBOSITY > 0) { + $timeTaken = ((microtime(true) - $startTime) * 1000); + if ($timeTaken < 1000) { + $timeTaken = round($timeTaken); + echo "DONE in {$timeTaken}ms"; + } else { + $timeTaken = round(($timeTaken / 1000), 2); + echo "DONE in $timeTaken secs"; + } + + if (PHP_CODESNIFFER_CBF === true) { + $errors = $file->getFixableCount(); + echo " ($errors fixable violations)".PHP_EOL; + } else { + $errors = $file->getErrorCount(); + $warnings = $file->getWarningCount(); + echo " ($errors errors, $warnings warnings)".PHP_EOL; + } + } + } catch (Exception $e) { + $error = 'An error occurred during processing; checking has been aborted. The error message was: '.$e->getMessage(); + + // Determine which sniff caused the error. + $sniffStack = null; + $nextStack = null; + foreach ($e->getTrace() as $step) { + if (isset($step['file']) === false) { + continue; + } + + if (empty($sniffStack) === false) { + $nextStack = $step; + break; + } + + if (substr($step['file'], -9) === 'Sniff.php') { + $sniffStack = $step; + continue; + } + } + + if (empty($sniffStack) === false) { + $sniffCode = ''; + try { + if (empty($nextStack) === false + && isset($nextStack['class']) === true + && substr($nextStack['class'], -5) === 'Sniff' + ) { + $sniffCode = 'the '.Common::getSniffCode($nextStack['class']).' sniff'; + } + } catch (InvalidArgumentException $e) { + // Sniff code could not be determined. This may be an abstract sniff class. + } + + if ($sniffCode === '') { + $sniffCode = substr(strrchr(str_replace('\\', '/', $sniffStack['file']), '/'), 1); + } + + $error .= sprintf(PHP_EOL.'The error originated in %s on line %s.', $sniffCode, $sniffStack['line']); + } + + $file->addErrorOnLine($error, 1, 'Internal.Exception'); + }//end try + + $this->reporter->cacheFileReport($file); + + if ($this->config->interactive === true) { + /* + Running interactively. + Print the error report for the current file and then wait for user input. + */ + + // Get current violations and then clear the list to make sure + // we only print violations for a single file each time. + $numErrors = null; + while ($numErrors !== 0) { + $numErrors = ($file->getErrorCount() + $file->getWarningCount()); + if ($numErrors === 0) { + continue; + } + + $this->reporter->printReport('full'); + + echo ' to recheck, [s] to skip or [q] to quit : '; + $input = fgets(STDIN); + $input = trim($input); + + switch ($input) { + case 's': + break(2); + case 'q': + throw new DeepExitException('', 0); + default: + // Repopulate the sniffs because some of them save their state + // and only clear it when the file changes, but we are rechecking + // the same file. + $file->ruleset->populateTokenListeners(); + $file->reloadContent(); + $file->process(); + $this->reporter->cacheFileReport($file); + break; + } + }//end while + }//end if + + // Clean up the file to save (a lot of) memory. + $file->cleanUp(); + + }//end processFile() + + + /** + * Waits for child processes to complete and cleans up after them. + * + * The reporting information returned by each child process is merged + * into the main reporter class. + * + * @param array $childProcs An array of child processes to wait for. + * + * @return bool + */ + private function processChildProcs($childProcs) + { + $numProcessed = 0; + $totalBatches = count($childProcs); + + $success = true; + + while (count($childProcs) > 0) { + $pid = pcntl_waitpid(0, $status); + if ($pid <= 0) { + continue; + } + + $childProcessStatus = pcntl_wexitstatus($status); + if ($childProcessStatus !== 0) { + $success = false; + } + + $out = $childProcs[$pid]; + unset($childProcs[$pid]); + if (file_exists($out) === false) { + continue; + } + + include $out; + unlink($out); + + $numProcessed++; + + if (isset($childOutput) === false) { + // The child process died, so the run has failed. + $file = new DummyFile('', $this->ruleset, $this->config); + $file->setErrorCounts(1, 0, 0, 0); + $this->printProgress($file, $totalBatches, $numProcessed); + $success = false; + continue; + } + + $this->reporter->totalFiles += $childOutput['totalFiles']; + $this->reporter->totalErrors += $childOutput['totalErrors']; + $this->reporter->totalWarnings += $childOutput['totalWarnings']; + $this->reporter->totalFixable += $childOutput['totalFixable']; + $this->reporter->totalFixed += $childOutput['totalFixed']; + + if (isset($debugOutput) === true) { + echo $debugOutput; + } + + if (isset($childCache) === true) { + foreach ($childCache as $path => $cache) { + Cache::set($path, $cache); + } + } + + // Fake a processed file so we can print progress output for the batch. + $file = new DummyFile('', $this->ruleset, $this->config); + $file->setErrorCounts( + $childOutput['totalErrors'], + $childOutput['totalWarnings'], + $childOutput['totalFixable'], + $childOutput['totalFixed'] + ); + $this->printProgress($file, $totalBatches, $numProcessed); + }//end while + + return $success; + + }//end processChildProcs() + + + /** + * Print progress information for a single processed file. + * + * @param \PHP_CodeSniffer\Files\File $file The file that was processed. + * @param int $numFiles The total number of files to process. + * @param int $numProcessed The number of files that have been processed, + * including this one. + * + * @return void + */ + public function printProgress(File $file, $numFiles, $numProcessed) + { + if (PHP_CODESNIFFER_VERBOSITY > 0 + || $this->config->showProgress === false + ) { + return; + } + + // Show progress information. + if ($file->ignored === true) { + echo 'S'; + } else { + $errors = $file->getErrorCount(); + $warnings = $file->getWarningCount(); + $fixable = $file->getFixableCount(); + $fixed = $file->getFixedCount(); + + if (PHP_CODESNIFFER_CBF === true) { + // Files with fixed errors or warnings are F (green). + // Files with unfixable errors or warnings are E (red). + // Files with no errors or warnings are . (black). + if ($fixable > 0) { + if ($this->config->colors === true) { + echo "\033[31m"; + } + + echo 'E'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else if ($fixed > 0) { + if ($this->config->colors === true) { + echo "\033[32m"; + } + + echo 'F'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else { + echo '.'; + }//end if + } else { + // Files with errors are E (red). + // Files with fixable errors are E (green). + // Files with warnings are W (yellow). + // Files with fixable warnings are W (green). + // Files with no errors or warnings are . (black). + if ($errors > 0) { + if ($this->config->colors === true) { + if ($fixable > 0) { + echo "\033[32m"; + } else { + echo "\033[31m"; + } + } + + echo 'E'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else if ($warnings > 0) { + if ($this->config->colors === true) { + if ($fixable > 0) { + echo "\033[32m"; + } else { + echo "\033[33m"; + } + } + + echo 'W'; + + if ($this->config->colors === true) { + echo "\033[0m"; + } + } else { + echo '.'; + }//end if + }//end if + }//end if + + $numPerLine = 60; + if ($numProcessed !== $numFiles && ($numProcessed % $numPerLine) !== 0) { + return; + } + + $percent = round(($numProcessed / $numFiles) * 100); + $padding = (strlen($numFiles) - strlen($numProcessed)); + if ($numProcessed === $numFiles + && $numFiles > $numPerLine + && ($numProcessed % $numPerLine) !== 0 + ) { + $padding += ($numPerLine - ($numFiles - (floor($numFiles / $numPerLine) * $numPerLine))); + } + + echo str_repeat(' ', $padding)." $numProcessed / $numFiles ($percent%)".PHP_EOL; + + }//end printProgress() + + + /** + * Registers a PHP shutdown function to provide a more informative out of memory error. + * + * @param string $command The command which was used to initiate the PHPCS run. + * + * @return void + */ + private function registerOutOfMemoryShutdownMessage($command) + { + // Allocate all needed memory beforehand as much as possible. + $errorMsg = PHP_EOL.'The PHP_CodeSniffer "%1$s" command ran out of memory.'.PHP_EOL; + $errorMsg .= 'Either raise the "memory_limit" of PHP in the php.ini file or raise the memory limit at runtime'.PHP_EOL; + $errorMsg .= 'using `%1$s -d memory_limit=512M` (replace 512M with the desired memory limit).'.PHP_EOL; + $errorMsg = sprintf($errorMsg, $command); + $memoryError = 'Allowed memory size of'; + $errorArray = [ + 'type' => 42, + 'message' => 'Some random dummy string to take up memory and take up some more memory and some more', + 'file' => 'Another random string, which would be a filename this time. Should be relatively long to allow for deeply nested files', + 'line' => 31427, + ]; + + register_shutdown_function( + static function () use ( + $errorMsg, + $memoryError, + $errorArray + ) { + $errorArray = error_get_last(); + if (is_array($errorArray) === true && strpos($errorArray['message'], $memoryError) !== false) { + echo $errorMsg; + } + } + ); + + }//end registerOutOfMemoryShutdownMessage() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php new file mode 100644 index 000000000..95a0a0908 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php @@ -0,0 +1,172 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractArraySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + final public function register() + { + return [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + $arrayStart = $tokens[$stackPtr]['parenthesis_opener']; + if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) { + // Incomplete array. + return; + } + + $arrayEnd = $tokens[$arrayStart]['parenthesis_closer']; + } else { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + $arrayStart = $stackPtr; + $arrayEnd = $tokens[$stackPtr]['bracket_closer']; + } + + $lastContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($arrayEnd - 1), null, true); + if ($tokens[$lastContent]['code'] === T_COMMA) { + // Last array item ends with a comma. + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no'); + } + + $indices = []; + + $current = $arrayStart; + while (($next = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), $arrayEnd, true)) !== false) { + $end = $this->getNext($phpcsFile, $next, $arrayEnd); + + if ($tokens[$end]['code'] === T_DOUBLE_ARROW) { + $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true); + $valueStart = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + + $indices[] = [ + 'index_start' => $next, + 'index_end' => $indexEnd, + 'arrow' => $end, + 'value_start' => $valueStart, + ]; + } else { + $valueStart = $next; + $indices[] = ['value_start' => $valueStart]; + } + + $current = $this->getNext($phpcsFile, $valueStart, $arrayEnd); + } + + if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) { + $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + } else { + $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + } + + }//end process() + + + /** + * Find next separator in array - either: comma or double arrow. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $ptr The position of current token. + * @param int $arrayEnd The token that ends the array definition. + * + * @return int + */ + private function getNext(File $phpcsFile, $ptr, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + + while ($ptr < $arrayEnd) { + if (isset($tokens[$ptr]['scope_closer']) === true) { + $ptr = $tokens[$ptr]['scope_closer']; + } else if (isset($tokens[$ptr]['parenthesis_closer']) === true) { + $ptr = $tokens[$ptr]['parenthesis_closer']; + } else if (isset($tokens[$ptr]['bracket_closer']) === true) { + $ptr = $tokens[$ptr]['bracket_closer']; + } + + if ($tokens[$ptr]['code'] === T_COMMA + || $tokens[$ptr]['code'] === T_DOUBLE_ARROW + ) { + return $ptr; + } + + ++$ptr; + } + + return $ptr; + + }//end getNext() + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + abstract protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + abstract protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php new file mode 100644 index 000000000..d9528dccf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php @@ -0,0 +1,941 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Tokenizers\PHP; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractPatternSniff implements Sniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = false; + + /** + * The current file being checked. + * + * @var string + */ + protected $currFile = ''; + + /** + * The parsed patterns array. + * + * @var array + */ + private $parsedPatterns = []; + + /** + * Tokens that this sniff wishes to process outside of the patterns. + * + * @var int[] + * @see registerSupplementary() + * @see processSupplementary() + */ + private $supplementaryTokens = []; + + /** + * Positions in the stack where errors have occurred. + * + * @var array + */ + private $errorPos = []; + + + /** + * Constructs a AbstractPatternSniff. + * + * @param boolean $ignoreComments If true, comments will be ignored. + */ + public function __construct($ignoreComments=null) + { + // This is here for backwards compatibility. + if ($ignoreComments !== null) { + $this->ignoreComments = $ignoreComments; + } + + $this->supplementaryTokens = $this->registerSupplementary(); + + }//end __construct() + + + /** + * Registers the tokens to listen to. + * + * Classes extending AbstractPatternTest should implement the + * getPatterns() method to register the patterns they wish to test. + * + * @return array + * @see process() + */ + final public function register() + { + $listenTypes = []; + $patterns = $this->getPatterns(); + + foreach ($patterns as $pattern) { + $parsedPattern = $this->parse($pattern); + + // Find a token position in the pattern that we can use + // for a listener token. + $pos = $this->getListenerTokenPos($parsedPattern); + $tokenType = $parsedPattern[$pos]['token']; + $listenTypes[] = $tokenType; + + $patternArray = [ + 'listen_pos' => $pos, + 'pattern' => $parsedPattern, + 'pattern_code' => $pattern, + ]; + + if (isset($this->parsedPatterns[$tokenType]) === false) { + $this->parsedPatterns[$tokenType] = []; + } + + $this->parsedPatterns[$tokenType][] = $patternArray; + }//end foreach + + return array_unique(array_merge($listenTypes, $this->supplementaryTokens)); + + }//end register() + + + /** + * Returns the token types that the specified pattern is checking for. + * + * Returned array is in the format: + * + * array( + * T_WHITESPACE => 0, // 0 is the position where the T_WHITESPACE token + * // should occur in the pattern. + * ); + * + * + * @param array $pattern The parsed pattern to find the acquire the token + * types from. + * + * @return array + */ + private function getPatternTokenTypes($pattern) + { + $tokenTypes = []; + foreach ($pattern as $pos => $patternInfo) { + if ($patternInfo['type'] === 'token') { + if (isset($tokenTypes[$patternInfo['token']]) === false) { + $tokenTypes[$patternInfo['token']] = $pos; + } + } + } + + return $tokenTypes; + + }//end getPatternTokenTypes() + + + /** + * Returns the position in the pattern that this test should register as + * a listener for the pattern. + * + * @param array $pattern The pattern to acquire the listener for. + * + * @return int The position in the pattern that this test should register + * as the listener. + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If we could not determine a token to listen for. + */ + private function getListenerTokenPos($pattern) + { + $tokenTypes = $this->getPatternTokenTypes($pattern); + $tokenCodes = array_keys($tokenTypes); + $token = Tokens::getHighestWeightedToken($tokenCodes); + + // If we could not get a token. + if ($token === false) { + $error = 'Could not determine a token to listen for'; + throw new RuntimeException($error); + } + + return $tokenTypes[$token]; + + }//end getListenerTokenPos() + + + /** + * Processes the test. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ + final public function process(File $phpcsFile, $stackPtr) + { + $file = $phpcsFile->getFilename(); + if ($this->currFile !== $file) { + // We have changed files, so clean up. + $this->errorPos = []; + $this->currFile = $file; + } + + $tokens = $phpcsFile->getTokens(); + + if (in_array($tokens[$stackPtr]['code'], $this->supplementaryTokens, true) === true) { + $this->processSupplementary($phpcsFile, $stackPtr); + } + + $type = $tokens[$stackPtr]['code']; + + // If the type is not set, then it must have been a token registered + // with registerSupplementary(). + if (isset($this->parsedPatterns[$type]) === false) { + return; + } + + $allErrors = []; + + // Loop over each pattern that is listening to the current token type + // that we are processing. + foreach ($this->parsedPatterns[$type] as $patternInfo) { + // If processPattern returns false, then the pattern that we are + // checking the code with must not be designed to check that code. + $errors = $this->processPattern($patternInfo, $phpcsFile, $stackPtr); + if ($errors === false) { + // The pattern didn't match. + continue; + } else if (empty($errors) === true) { + // The pattern matched, but there were no errors. + break; + } + + foreach ($errors as $stackPtr => $error) { + if (isset($this->errorPos[$stackPtr]) === false) { + $this->errorPos[$stackPtr] = true; + $allErrors[$stackPtr] = $error; + } + } + } + + foreach ($allErrors as $stackPtr => $error) { + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + + /** + * Processes the pattern and verifies the code at $stackPtr. + * + * @param array $patternInfo Information about the pattern used + * for checking, which includes are + * parsed token representation of the + * pattern. + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack where + * the listening token type was found. + * + * @return array|false + */ + protected function processPattern($patternInfo, File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $pattern = $patternInfo['pattern']; + $patternCode = $patternInfo['pattern_code']; + $errors = []; + $found = ''; + + $ignoreTokens = [T_WHITESPACE => T_WHITESPACE]; + if ($this->ignoreComments === true) { + $ignoreTokens += Tokens::$commentTokens; + } + + $origStackPtr = $stackPtr; + $hasError = false; + + if ($patternInfo['listen_pos'] > 0) { + $stackPtr--; + + for ($i = ($patternInfo['listen_pos'] - 1); $i >= 0; $i--) { + if ($pattern[$i]['type'] === 'token') { + if ($pattern[$i]['token'] === T_WHITESPACE) { + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + $found = $tokens[$stackPtr]['content'].$found; + } + + // Only check the size of the whitespace if this is not + // the first token. We don't care about the size of + // leading whitespace, just that there is some. + if ($i !== 0) { + if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) { + $hasError = true; + } + } + } else { + // Check to see if this important token is the same as the + // previous important token in the pattern. If it is not, + // then the pattern cannot be for this piece of code. + $prev = $phpcsFile->findPrevious( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($prev === false + || $tokens[$prev]['code'] !== $pattern[$i]['token'] + ) { + return false; + } + + // If we skipped past some whitespace tokens, then add them + // to the found string. + $tokenContent = $phpcsFile->getTokensAsString( + ($prev + 1), + ($stackPtr - $prev - 1) + ); + + $found = $tokens[$prev]['content'].$tokenContent.$found; + + if (isset($pattern[($i - 1)]) === true + && $pattern[($i - 1)]['type'] === 'skip' + ) { + $stackPtr = $prev; + } else { + $stackPtr = ($prev - 1); + } + }//end if + } else if ($pattern[$i]['type'] === 'skip') { + // Skip to next piece of relevant code. + if ($pattern[$i]['to'] === 'parenthesis_closer') { + $to = 'parenthesis_opener'; + } else { + $to = 'scope_opener'; + } + + // Find the previous opener. + $next = $phpcsFile->findPrevious( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next === false || isset($tokens[$next][$to]) === false) { + // If there was not opener, then we must be + // using the wrong pattern. + return false; + } + + if ($to === 'parenthesis_opener') { + $found = '{'.$found; + } else { + $found = '('.$found; + } + + $found = '...'.$found; + + // Skip to the opening token. + $stackPtr = ($tokens[$next][$to] - 1); + } else if ($pattern[$i]['type'] === 'string') { + $found = 'abc'; + } else if ($pattern[$i]['type'] === 'newline') { + if ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true + ) { + $startComment = $phpcsFile->findPrevious( + Tokens::$commentTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$startComment]['line'] !== $tokens[($startComment + 1)]['line']) { + $startComment++; + } + + $tokenContent = $phpcsFile->getTokensAsString( + $startComment, + ($stackPtr - $startComment + 1) + ); + + $found = $tokenContent.$found; + $stackPtr = ($startComment - 1); + } + + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) { + $found = $tokens[$stackPtr]['content'].$found; + + // This may just be an indent that comes after a newline + // so check the token before to make sure. If it is a newline, we + // can ignore the error here. + if (($tokens[($stackPtr - 1)]['content'] !== $phpcsFile->eolChar) + && ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[($stackPtr - 1)]['code']]) === false) + ) { + $hasError = true; + } else { + $stackPtr--; + } + } else { + $found = 'EOL'.$found; + } + } else { + $found = $tokens[$stackPtr]['content'].$found; + $hasError = true; + }//end if + + if ($hasError === false && $pattern[($i - 1)]['type'] !== 'newline') { + // Make sure they only have 1 newline. + $prev = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) { + $hasError = true; + } + } + }//end if + }//end for + }//end if + + $stackPtr = $origStackPtr; + $lastAddedStackPtr = null; + $patternLen = count($pattern); + + if (($stackPtr + $patternLen - $patternInfo['listen_pos']) > $phpcsFile->numTokens) { + // Pattern can never match as there are not enough tokens left in the file. + return false; + } + + for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) { + if (isset($tokens[$stackPtr]) === false) { + break; + } + + if ($pattern[$i]['type'] === 'token') { + if ($pattern[$i]['token'] === T_WHITESPACE) { + if ($this->ignoreComments === true) { + // If we are ignoring comments, check to see if this current + // token is a comment. If so skip it. + if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) { + continue; + } + + // If the next token is a comment, the we need to skip the + // current token as we should allow a space before a + // comment for readability. + if (isset($tokens[($stackPtr + 1)]) === true + && isset(Tokens::$commentTokens[$tokens[($stackPtr + 1)]['code']]) === true + ) { + continue; + } + } + + $tokenContent = ''; + if ($tokens[$stackPtr]['code'] === T_WHITESPACE) { + if (isset($pattern[($i + 1)]) === false) { + // This is the last token in the pattern, so just compare + // the next token of content. + $tokenContent = $tokens[$stackPtr]['content']; + } else { + // Get all the whitespace to the next token. + $next = $phpcsFile->findNext( + Tokens::$emptyTokens, + $stackPtr, + null, + true + ); + + $tokenContent = $phpcsFile->getTokensAsString( + $stackPtr, + ($next - $stackPtr) + ); + + $lastAddedStackPtr = $stackPtr; + $stackPtr = $next; + }//end if + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $tokenContent; + } + } else { + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $tokens[$stackPtr]['content']; + $lastAddedStackPtr = $stackPtr; + } + }//end if + + if (isset($pattern[($i + 1)]) === true + && $pattern[($i + 1)]['type'] === 'skip' + ) { + // The next token is a skip token, so we just need to make + // sure the whitespace we found has *at least* the + // whitespace required. + if (strpos($tokenContent, $pattern[$i]['value']) !== 0) { + $hasError = true; + } + } else { + if ($tokenContent !== $pattern[$i]['value']) { + $hasError = true; + } + } + } else { + // Check to see if this important token is the same as the + // next important token in the pattern. If it is not, then + // the pattern cannot be for this piece of code. + $next = $phpcsFile->findNext( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next === false + || $tokens[$next]['code'] !== $pattern[$i]['token'] + ) { + // The next important token did not match the pattern. + return false; + } + + if ($lastAddedStackPtr !== null) { + if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) + && isset($tokens[$next]['scope_condition']) === true + && $tokens[$next]['scope_condition'] > $lastAddedStackPtr + ) { + // This is a brace, but the owner of it is after the current + // token, which means it does not belong to any token in + // our pattern. This means the pattern is not for us. + return false; + } + + if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS + || $tokens[$next]['code'] === T_CLOSE_PARENTHESIS) + && isset($tokens[$next]['parenthesis_owner']) === true + && $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr + ) { + // This is a bracket, but the owner of it is after the current + // token, which means it does not belong to any token in + // our pattern. This means the pattern is not for us. + return false; + } + }//end if + + // If we skipped past some whitespace tokens, then add them + // to the found string. + if (($next - $stackPtr) > 0) { + $hasComment = false; + for ($j = $stackPtr; $j < $next; $j++) { + $found .= $tokens[$j]['content']; + if (isset(Tokens::$commentTokens[$tokens[$j]['code']]) === true) { + $hasComment = true; + } + } + + // If we are not ignoring comments, this additional + // whitespace or comment is not allowed. If we are + // ignoring comments, there needs to be at least one + // comment for this to be allowed. + if ($this->ignoreComments === false + || ($this->ignoreComments === true + && $hasComment === false) + ) { + $hasError = true; + } + + // Even when ignoring comments, we are not allowed to include + // newlines without the pattern specifying them, so + // everything should be on the same line. + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $hasError = true; + } + }//end if + + if ($next !== $lastAddedStackPtr) { + $found .= $tokens[$next]['content']; + $lastAddedStackPtr = $next; + } + + if (isset($pattern[($i + 1)]) === true + && $pattern[($i + 1)]['type'] === 'skip' + ) { + $stackPtr = $next; + } else { + $stackPtr = ($next + 1); + } + }//end if + } else if ($pattern[$i]['type'] === 'skip') { + if ($pattern[$i]['to'] === 'unknown') { + $next = $phpcsFile->findNext( + $pattern[($i + 1)]['token'], + $stackPtr + ); + + if ($next === false) { + // Couldn't find the next token, so we must + // be using the wrong pattern. + return false; + } + + $found .= '...'; + $stackPtr = $next; + } else { + // Find the previous opener. + $next = $phpcsFile->findPrevious( + Tokens::$blockOpeners, + $stackPtr + ); + + if ($next === false + || isset($tokens[$next][$pattern[$i]['to']]) === false + ) { + // If there was not opener, then we must + // be using the wrong pattern. + return false; + } + + $found .= '...'; + if ($pattern[$i]['to'] === 'parenthesis_closer') { + $found .= ')'; + } else { + $found .= '}'; + } + + // Skip to the closing token. + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + }//end if + } else if ($pattern[$i]['type'] === 'string') { + if ($tokens[$stackPtr]['code'] !== T_STRING) { + $hasError = true; + } + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= 'abc'; + $lastAddedStackPtr = $stackPtr; + } + + $stackPtr++; + } else if ($pattern[$i]['type'] === 'newline') { + // Find the next token that contains a newline character. + $newline = 0; + for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) { + if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) { + $newline = $j; + break; + } + } + + if ($newline === 0) { + // We didn't find a newline character in the rest of the file. + $next = ($phpcsFile->numTokens - 1); + $hasError = true; + } else { + if ($this->ignoreComments === false) { + // The newline character cannot be part of a comment. + if (isset(Tokens::$commentTokens[$tokens[$newline]['code']]) === true) { + $hasError = true; + } + } + + if ($newline === $stackPtr) { + $next = ($stackPtr + 1); + } else { + // Check that there were no significant tokens that we + // skipped over to find our newline character. + $next = $phpcsFile->findNext( + $ignoreTokens, + $stackPtr, + null, + true + ); + + if ($next < $newline) { + // We skipped a non-ignored token. + $hasError = true; + } else { + $next = ($newline + 1); + } + } + }//end if + + if ($stackPtr !== $lastAddedStackPtr) { + $found .= $phpcsFile->getTokensAsString( + $stackPtr, + ($next - $stackPtr) + ); + + $lastAddedStackPtr = ($next - 1); + } + + $stackPtr = $next; + }//end if + }//end for + + if ($hasError === true) { + $error = $this->prepareError($found, $patternCode); + $errors[$origStackPtr] = $error; + } + + return $errors; + + }//end processPattern() + + + /** + * Prepares an error for the specified patternCode. + * + * @param string $found The actual found string in the code. + * @param string $patternCode The expected pattern code. + * + * @return string The error message. + */ + protected function prepareError($found, $patternCode) + { + $found = str_replace("\r\n", '\n', $found); + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\n', $found); + $found = str_replace("\t", '\t', $found); + $found = str_replace('EOL', '\n', $found); + $expected = str_replace('EOL', '\n', $patternCode); + + $error = "Expected \"$expected\"; found \"$found\""; + + return $error; + + }//end prepareError() + + + /** + * Returns the patterns that should be checked. + * + * @return string[] + */ + abstract protected function getPatterns(); + + + /** + * Registers any supplementary tokens that this test might wish to process. + * + * A sniff may wish to register supplementary tests when it wishes to group + * an arbitrary validation that cannot be performed using a pattern, with + * other pattern tests. + * + * @return int[] + * @see processSupplementary() + */ + protected function registerSupplementary() + { + return []; + + }//end registerSupplementary() + + + /** + * Processes any tokens registered with registerSupplementary(). + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where to + * process the skip. + * @param int $stackPtr The position in the tokens stack to + * process. + * + * @return void + * @see registerSupplementary() + */ + protected function processSupplementary(File $phpcsFile, $stackPtr) + { + + }//end processSupplementary() + + + /** + * Parses a pattern string into an array of pattern steps. + * + * @param string $pattern The pattern to parse. + * + * @return array The parsed pattern array. + * @see createSkipPattern() + * @see createTokenPattern() + */ + private function parse($pattern) + { + $patterns = []; + $length = strlen($pattern); + $lastToken = 0; + $firstToken = 0; + + for ($i = 0; $i < $length; $i++) { + $specialPattern = false; + $isLastChar = ($i === ($length - 1)); + $oldFirstToken = $firstToken; + + if (substr($pattern, $i, 3) === '...') { + // It's a skip pattern. The skip pattern requires the + // content of the token in the "from" position and the token + // to skip to. + $specialPattern = $this->createSkipPattern($pattern, ($i - 1)); + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + + if ($specialPattern['to'] !== 'unknown') { + $firstToken++; + } + } else if (substr($pattern, $i, 3) === 'abc') { + $specialPattern = ['type' => 'string']; + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + } else if (substr($pattern, $i, 3) === 'EOL') { + $specialPattern = ['type' => 'newline']; + $lastToken = ($i - $firstToken); + $firstToken = ($i + 3); + $i += 2; + }//end if + + if ($specialPattern !== false || $isLastChar === true) { + // If we are at the end of the string, don't worry about a limit. + if ($isLastChar === true) { + // Get the string from the end of the last skip pattern, if any, + // to the end of the pattern string. + $str = substr($pattern, $oldFirstToken); + } else { + // Get the string from the end of the last special pattern, + // if any, to the start of this special pattern. + if ($lastToken === 0) { + // Note that if the last special token was zero characters ago, + // there will be nothing to process so we can skip this bit. + // This happens if you have something like: EOL... in your pattern. + $str = ''; + } else { + $str = substr($pattern, $oldFirstToken, $lastToken); + } + } + + if ($str !== '') { + $tokenPatterns = $this->createTokenPattern($str); + foreach ($tokenPatterns as $tokenPattern) { + $patterns[] = $tokenPattern; + } + } + + // Make sure we don't skip the last token. + if ($isLastChar === false && $i === ($length - 1)) { + $i--; + } + }//end if + + // Add the skip pattern *after* we have processed + // all the tokens from the end of the last skip pattern + // to the start of this skip pattern. + if ($specialPattern !== false) { + $patterns[] = $specialPattern; + } + }//end for + + return $patterns; + + }//end parse() + + + /** + * Creates a skip pattern. + * + * @param string $pattern The pattern being parsed. + * @param int $from The token position that the skip pattern starts from. + * + * @return array The pattern step. + * @see createTokenPattern() + * @see parse() + */ + private function createSkipPattern($pattern, $from) + { + $skip = ['type' => 'skip']; + + $nestedParenthesis = 0; + $nestedBraces = 0; + for ($start = $from; $start >= 0; $start--) { + switch ($pattern[$start]) { + case '(': + if ($nestedParenthesis === 0) { + $skip['to'] = 'parenthesis_closer'; + } + + $nestedParenthesis--; + break; + case '{': + if ($nestedBraces === 0) { + $skip['to'] = 'scope_closer'; + } + + $nestedBraces--; + break; + case '}': + $nestedBraces++; + break; + case ')': + $nestedParenthesis++; + break; + }//end switch + + if (isset($skip['to']) === true) { + break; + } + }//end for + + if (isset($skip['to']) === false) { + $skip['to'] = 'unknown'; + } + + return $skip; + + }//end createSkipPattern() + + + /** + * Creates a token pattern. + * + * @param string $str The tokens string that the pattern should match. + * + * @return array The pattern step. + * @see createSkipPattern() + * @see parse() + */ + private function createTokenPattern($str) + { + // Don't add a space after the closing php tag as it will add a new + // whitespace token. + $tokenizer = new PHP('', null); + + // Remove the getTokens(); + $tokens = array_slice($tokens, 1, (count($tokens) - 2)); + + $patterns = []; + foreach ($tokens as $patternInfo) { + $patterns[] = [ + 'type' => 'token', + 'token' => $patternInfo['code'], + 'value' => $patternInfo['content'], + ]; + } + + return $patterns; + + }//end createTokenPattern() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php new file mode 100644 index 000000000..d2b6979d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php @@ -0,0 +1,189 @@ + + * class ClassScopeTest extends PHP_CodeSniffer_Standards_AbstractScopeSniff + * { + * public function __construct() + * { + * parent::__construct(array(T_CLASS), array(T_FUNCTION)); + * } + * + * protected function processTokenWithinScope(\PHP_CodeSniffer\Files\File $phpcsFile, $stackPtr, $currScope) + * { + * $className = $phpcsFile->getDeclarationName($currScope); + * echo 'encountered a method within class '.$className; + * } + * } + * + * + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; + +abstract class AbstractScopeSniff implements Sniff +{ + + /** + * The token types that this test wishes to listen to within the scope. + * + * @var array + */ + private $tokens = []; + + /** + * The type of scope opener tokens that this test wishes to listen to. + * + * @var array + */ + private $scopeTokens = []; + + /** + * True if this test should fire on tokens outside of the scope. + * + * @var boolean + */ + private $listenOutside = false; + + + /** + * Constructs a new AbstractScopeTest. + * + * @param array $scopeTokens The type of scope the test wishes to listen to. + * @param array $tokens The tokens that the test wishes to listen to + * within the scope. + * @param boolean $listenOutside If true this test will also alert the + * extending class when a token is found outside + * the scope, by calling the + * processTokenOutsideScope method. + * + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified tokens arrays are empty + * or invalid. + */ + public function __construct( + array $scopeTokens, + array $tokens, + $listenOutside=false + ) { + if (empty($scopeTokens) === true) { + $error = 'The scope tokens list cannot be empty'; + throw new RuntimeException($error); + } + + if (empty($tokens) === true) { + $error = 'The tokens list cannot be empty'; + throw new RuntimeException($error); + } + + $invalidScopeTokens = array_intersect($scopeTokens, $tokens); + if (empty($invalidScopeTokens) === false) { + $invalid = implode(', ', $invalidScopeTokens); + $error = "Scope tokens [$invalid] can't be in the tokens array"; + throw new RuntimeException($error); + } + + $this->listenOutside = $listenOutside; + $this->scopeTokens = array_flip($scopeTokens); + $this->tokens = $tokens; + + }//end __construct() + + + /** + * The method that is called to register the tokens this test wishes to + * listen to. + * + * DO NOT OVERRIDE THIS METHOD. Use the constructor of this class to register + * for the desired tokens and scope. + * + * @return array + * @see __constructor() + */ + final public function register() + { + return $this->tokens; + + }//end register() + + + /** + * Processes the tokens that this test is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + * @see processTokenWithinScope() + */ + final public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $foundScope = false; + $skipTokens = []; + foreach ($tokens[$stackPtr]['conditions'] as $scope => $code) { + if (isset($this->scopeTokens[$code]) === true) { + $skipTokens[] = $this->processTokenWithinScope($phpcsFile, $stackPtr, $scope); + $foundScope = true; + } + } + + if ($this->listenOutside === true && $foundScope === false) { + $skipTokens[] = $this->processTokenOutsideScope($phpcsFile, $stackPtr); + } + + if (empty($skipTokens) === false) { + return min($skipTokens); + } + + }//end process() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * @param int $currScope The position in the tokens array that + * opened the scope that this test is + * listening for. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + abstract protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope); + + + /** + * Processes a token that is found outside the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + abstract protected function processTokenOutsideScope(File $phpcsFile, $stackPtr); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php new file mode 100644 index 000000000..34a3b43aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractVariableSniff.php @@ -0,0 +1,230 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +abstract class AbstractVariableSniff extends AbstractScopeSniff +{ + + /** + * List of PHP Reserved variables. + * + * Used by various naming convention sniffs. + * + * @var array + */ + protected $phpReservedVars = [ + '_SERVER' => true, + '_GET' => true, + '_POST' => true, + '_REQUEST' => true, + '_SESSION' => true, + '_ENV' => true, + '_COOKIE' => true, + '_FILES' => true, + 'GLOBALS' => true, + 'http_response_header' => true, + 'HTTP_RAW_POST_DATA' => true, + 'php_errormsg' => true, + ]; + + + /** + * Constructs an AbstractVariableTest. + */ + public function __construct() + { + $scopes = Tokens::$ooScopeTokens; + + $listen = [ + T_VARIABLE, + T_DOUBLE_QUOTED_STRING, + T_HEREDOC, + ]; + + parent::__construct($scopes, $listen, true); + + }//end __construct() + + + /** + * Processes the token in the specified PHP_CodeSniffer\Files\File. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + final protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING + || $tokens[$stackPtr]['code'] === T_HEREDOC + ) { + // Check to see if this string has a variable in it. + $pattern = '|(?processVariableInString($phpcsFile, $stackPtr); + } + + return; + } + + // If this token is nested inside a function at a deeper + // level than the current OO scope that was found, it's a normal + // variable and not a member var. + $conditions = array_reverse($tokens[$stackPtr]['conditions'], true); + $inFunction = false; + foreach ($conditions as $scope => $code) { + if (isset(Tokens::$ooScopeTokens[$code]) === true) { + break; + } + + if ($code === T_FUNCTION || $code === T_CLOSURE) { + $inFunction = true; + } + } + + if ($scope !== $currScope) { + // We found a closer scope to this token, so ignore + // this particular time through the sniff. We will process + // this token when this closer scope is found to avoid + // duplicate checks. + return; + } + + // Just make sure this isn't a variable in a function declaration. + if ($inFunction === false && isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === false) { + // Check if this is a USE statement for a closure. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true); + if ($tokens[$prev]['code'] === T_USE) { + $inFunction = true; + break; + } + + continue; + } + + $owner = $tokens[$opener]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FUNCTION + || $tokens[$owner]['code'] === T_CLOSURE + ) { + $inFunction = true; + break; + } + } + }//end if + + if ($inFunction === true) { + return $this->processVariable($phpcsFile, $stackPtr); + } else { + return $this->processMemberVar($phpcsFile, $stackPtr); + } + + }//end processTokenWithinScope() + + + /** + * Processes the token outside the scope in the file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + final protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + // These variables are not member vars. + if ($tokens[$stackPtr]['code'] === T_VARIABLE) { + return $this->processVariable($phpcsFile, $stackPtr); + } else if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING + || $tokens[$stackPtr]['code'] === T_HEREDOC + ) { + // Check to see if this string has a variable in it. + $pattern = '|(?processVariableInString($phpcsFile, $stackPtr); + } + } + + }//end processTokenOutsideScope() + + + /** + * Called to process class member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + abstract protected function processMemberVar(File $phpcsFile, $stackPtr); + + + /** + * Called to process normal member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + abstract protected function processVariable(File $phpcsFile, $stackPtr); + + + /** + * Called to process variables found in double quoted strings or heredocs. + * + * Note that there may be more than one variable in the string, which will + * result only in one call for the string or one call per line for heredocs. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this + * token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + abstract protected function processVariableInString(File $phpcsFile, $stackPtr); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/DeprecatedSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/DeprecatedSniff.php new file mode 100644 index 000000000..4f4d9fc02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/DeprecatedSniff.php @@ -0,0 +1,63 @@ + + * @copyright 2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +interface DeprecatedSniff +{ + + + /** + * Provide the version number in which the sniff was deprecated. + * + * Recommended format for PHPCS native sniffs: "v3.3.0". + * Recommended format for external sniffs: "StandardName v3.3.0". + * + * @return string + */ + public function getDeprecationVersion(); + + + /** + * Provide the version number in which the sniff will be removed. + * + * Recommended format for PHPCS native sniffs: "v3.3.0". + * Recommended format for external sniffs: "StandardName v3.3.0". + * + * If the removal version is not yet known, it is recommended to set + * this to: "a future version". + * + * @return string + */ + public function getRemovalVersion(); + + + /** + * Optionally provide an arbitrary custom message to display with the deprecation. + * + * Typically intended to allow for displaying information about what to + * replace the deprecated sniff with. + * Example: "Use the Stnd.Cat.SniffName sniff instead." + * Multi-line messages (containing new line characters) are supported. + * + * An empty string can be returned if there is no replacement/no need + * for a custom message. + * + * @return string + */ + public function getDeprecationMessage(); + + +}//end interface diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php new file mode 100644 index 000000000..e0f7cfe9c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Sniffs/Sniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Sniffs; + +use PHP_CodeSniffer\Files\File; + +interface Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * An example return value for a sniff that wants to listen for whitespace + * and any comments would be: + * + * + * return array( + * T_WHITESPACE, + * T_DOC_COMMENT, + * T_COMMENT, + * ); + * + * + * @return array + * @see Tokens.php + */ + public function register(); + + + /** + * Called when one of the token types that this sniff is listening for + * is found. + * + * The stackPtr variable indicates where in the stack the token was found. + * A sniff can acquire information about this token, along with all the other + * tokens within the stack by first acquiring the token stack: + * + * + * $tokens = $phpcsFile->getTokens(); + * echo 'Encountered a '.$tokens[$stackPtr]['type'].' token'; + * echo 'token information: '; + * print_r($tokens[$stackPtr]); + * + * + * If the sniff discovers an anomaly in the code, they can raise an error + * by calling addError() on the \PHP_CodeSniffer\Files\File object, specifying an error + * message and the position of the offending token: + * + * + * $phpcsFile->addError('Encountered an error', $stackPtr); + * + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token was found. + * @param int $stackPtr The position in the PHP_CodeSniffer + * file's token stack where the token + * was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + public function process(File $phpcsFile, $stackPtr); + + +}//end interface diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/ArrayIndentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/ArrayIndentStandard.xml new file mode 100644 index 000000000..0312a70f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/ArrayIndentStandard.xml @@ -0,0 +1,107 @@ + + + + + + + [ + 1, + 2, +]; + +if ($condition) { + $a = + [ + 1, + 2, + ]; +} + + ]]> + + + [ + 1, + 2, + ]; +} + ]]> + + + + + + + + 1, + 2, + 3, +); + ]]> + + + 1, + 2, + 3, +); + ]]> + + + + + + + + +]; + ]]> + + + ]; + ]]> + + + + + + + + ); + ]]> + + + ); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml new file mode 100644 index 000000000..21b0d27d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowLongArraySyntaxStandard.xml @@ -0,0 +1,23 @@ + + + + + + + [ + 'foo' => 'bar', +]; + ]]> + + + array( + 'foo' => 'bar', +); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml new file mode 100644 index 000000000..f24767ca5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Arrays/DisallowShortArraySyntaxStandard.xml @@ -0,0 +1,23 @@ + + + + + + + array( + 'foo' => 'bar', +); + ]]> + + + [ + 'foo' => 'bar', +]; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml new file mode 100644 index 000000000..4b0ec96d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml @@ -0,0 +1,27 @@ + + + + + + + Foo +{ +} + ]]> + + + Foo +{ +} + +class Foo +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml new file mode 100644 index 000000000..6fa08be7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Classes/OpeningBraceSameLineStandard.xml @@ -0,0 +1,36 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + + + { +} + ]]> + + + // Start of class. +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml new file mode 100644 index 000000000..9961ea054 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/AssignmentInConditionStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $test === 'abc') { + // Code. +} + ]]> + + + $test = 'abc') { + // Code. +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyPHPStatementStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyPHPStatementStandard.xml new file mode 100644 index 000000000..6b96c825a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyPHPStatementStandard.xml @@ -0,0 +1,44 @@ + + + + + + + echo 'Hello World'; ?> +'Hello World'; ?> + ]]> + + + ; ?> + ?> + ]]> + + + + + + + + ; +if (true) { + echo 'Hello World'; +} + ]]> + + + ;;; +if (true) { + echo 'Hello World'; +}; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml new file mode 100644 index 000000000..c400d75e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + // do nothing +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml new file mode 100644 index 000000000..06f0b7a5b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $i = 0; $i < 10; $i++) { + echo "{$i}\n"; +} + ]]> + + + ;$test;) { + $test = doSomething(); +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml new file mode 100644 index 000000000..f40d94bb1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml @@ -0,0 +1,24 @@ + + + + + + + $end = count($foo); +for ($i = 0; $i < $end; $i++) { + echo $foo[$i]."\n"; +} + ]]> + + + count($foo); $i++) { + echo $foo[$i]."\n"; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml new file mode 100644 index 000000000..50f078288 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $i++) { + for ($j = 0; $j < 10; $j++) { + } +} + ]]> + + + $i++) { + for ($j = 0; $j < 10; $i++) { + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceStandard.xml new file mode 100644 index 000000000..006dbff44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceStandard.xml @@ -0,0 +1,44 @@ + + + + + + + ($one && $two) || $three; +$result2 = $one && ($two || $three); +$result3 = ($one && !$two) xor $three; +$result4 = $one && (!$two xor $three); + +if ( + ($result && !$result3) + || (!$result && $result3) +) {} + ]]> + + + $one && $two || $three; + +$result3 = $one && !$two xor $three; + + +if ( + $result && !$result3 + || !$result && $result3 +) {} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml new file mode 100644 index 000000000..b2eaabe79 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $test) { + $var = 1; +} + ]]> + + + true) { + $var = 1; +} + ]]> + + + + + $test) { + $var = 1; +} + ]]> + + + false) { + $var = 1; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml new file mode 100644 index 000000000..893674077 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xml @@ -0,0 +1,29 @@ + + + + + + + + + + final function bar() + { + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml new file mode 100644 index 000000000..181dff4ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $a + $b + $c; +} + ]]> + + + $a + $b; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml new file mode 100644 index 000000000..ba8bd7e42 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml @@ -0,0 +1,32 @@ + + + + + + + $this->doSomethingElse(); + } +} + ]]> + + + parent::bar(); + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/DocCommentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/DocCommentStandard.xml new file mode 100644 index 000000000..bbeb4f69a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/DocCommentStandard.xml @@ -0,0 +1,269 @@ + + + + + + + + + + Some content. + */ + ]]> + + + + */ + ]]> + + + + + + + + /** + * Short description. + */ + ]]> + + + /** Short description. */ + ]]> + + + + + + + + Short description. + */ + ]]> + + + @return int + */ + +/** + * + * Short description. + */ + ]]> + + + + + + + + Short description. + * + * Long description. + */ + ]]> + + + short description. + * + * long description. + */ + ]]> + + + + + + + + * + * Long description. + * + * @param int $foo + */ + ]]> + + + * + * + + * Long description. + * @param int $foo + */ + ]]> + + + + + + + + * @param int $foo + * @param string $bar + */ + ]]> + + + * + * @param string $bar + */ + ]]> + + + + + + + + * @param int $foo + * + * @since 3.4.8 + * @deprecated 6.0.0 + */ + ]]> + + + * @param int $foo + * @since 3.4.8 + * @deprecated 6.0.0 + */ + ]]> + + + + + + + + 0.5.0 + * @deprecated 1.0.0 + */ + ]]> + + + 0.5.0 + * @deprecated 1.0.0 + */ + ]]> + + + + + + + + @param string $foo + * + * @return void + */ + ]]> + + + @param string $bar + */ + ]]> + + + + + + + + + */ + ]]> + + + * + */ + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml new file mode 100644 index 000000000..174c6b0a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/FixmeStandard.xml @@ -0,0 +1,25 @@ + + + + + + + Handle strange case +if ($test) { + $var = 1; +} + ]]> + + + FIXME: This needs to be fixed! +if ($test) { + $var = 1; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml new file mode 100644 index 000000000..c9c4fc061 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Commenting/TodoStandard.xml @@ -0,0 +1,25 @@ + + + + + + + Handle strange case +if ($test) { + $var = 1; +} + ]]> + + + TODO: This needs to be fixed! +if ($test) { + $var = 1; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml new file mode 100644 index 000000000..651cc70d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/DisallowYodaConditionsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + { + $var = 1; +} + ]]> + + + { + $var = 1; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml new file mode 100644 index 000000000..06ae14b76 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml @@ -0,0 +1,22 @@ + + + + + + + { + $var = 1; +} + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml new file mode 100644 index 000000000..b57a97068 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/CSSLintStandard.xml @@ -0,0 +1,19 @@ + + + + + + + %; } + ]]> + + + %; } + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml new file mode 100644 index 000000000..9df9aec48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ]; + ]]> + + + ,]; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml new file mode 100644 index 000000000..7525e9e6b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Debug/JSHintStandard.xml @@ -0,0 +1,19 @@ + + + + + + + var foo = 5; + ]]> + + + foo = 5; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml new file mode 100644 index 000000000..88591f925 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml new file mode 100644 index 000000000..aa757edc6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml new file mode 100644 index 000000000..227d5621a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml new file mode 100644 index 000000000..6114f24c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/ExecutableFileStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml new file mode 100644 index 000000000..3c137a9a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/InlineHTMLStandard.xml @@ -0,0 +1,24 @@ + + + + + + + + + + some string here + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml new file mode 100644 index 000000000..4554d0f38 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineEndingsStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml new file mode 100644 index 000000000..31342e3c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LineLengthStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml new file mode 100644 index 000000000..a1be34cb0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml new file mode 100644 index 000000000..7b5857633 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + class Foo +{ +} + ]]> + + + class Foo +{ +} + +class Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml new file mode 100644 index 000000000..de975319a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + interface Foo +{ +} + ]]> + + + interface Foo +{ +} + +interface Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml new file mode 100644 index 000000000..4d957e701 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneObjectStructurePerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + trait Foo +{ +} + ]]> + + + trait Foo +{ +} + +class Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml new file mode 100644 index 000000000..58a6482f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Files/OneTraitPerFileStandard.xml @@ -0,0 +1,29 @@ + + + + + + + trait Foo +{ +} + ]]> + + + trait Foo +{ +} + +trait Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml new file mode 100644 index 000000000..f0d4490c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml new file mode 100644 index 000000000..09df3b7cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml @@ -0,0 +1,56 @@ + + + + + + + = (1 + 2); +$veryLongVarName = 'string'; +$var = foo($bar, $baz); + ]]> + + + = (1 + 2); +$veryLongVarName = 'string'; +$var = foo($bar, $baz); + ]]> + + + + + + + + += 1; +$veryLongVarName = 1; + ]]> + + + += 1; +$veryLongVarName = 1; + ]]> + + + + + = 1; +$veryLongVarName -= 1; + ]]> + + + = 1; +$veryLongVarName -= 1; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml new file mode 100644 index 000000000..80b932d27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + 1; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml new file mode 100644 index 000000000..0563bb261 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml @@ -0,0 +1,19 @@ + + + + + + + 1; + ]]> + + + 1; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml new file mode 100644 index 000000000..aea863695 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceAfterNotStandard.xml @@ -0,0 +1,22 @@ + + + + + + + $someVar || ! $x instanceOf stdClass) {}; + ]]> + + + $someVar || !$x instanceOf stdClass) {}; + +if (! $someVar || ! + $x instanceOf stdClass) {}; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceBeforeCastStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceBeforeCastStandard.xml new file mode 100644 index 000000000..09fbc189f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Formatting/SpaceBeforeCastStandard.xml @@ -0,0 +1,21 @@ + + + + + + + (int) $string; +$c = $a . (string) $b; + ]]> + + + (int) $string; +$c = $a . (string) $b; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml new file mode 100644 index 000000000..738998d43 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml @@ -0,0 +1,31 @@ + + + + + + + &$bar) +{ + $bar++; +} + +$baz = 1; +foo($baz); + ]]> + + + &$baz); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml new file mode 100644 index 000000000..9809844d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $baz) +{ +} + ]]> + + + $baz) +{ +} + ]]> + + + + + = true) +{ +} + ]]> + + + =true) +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml new file mode 100644 index 000000000..76314c508 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml @@ -0,0 +1,24 @@ + + + + + + + { + ... +} + ]]> + + + { + ... +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml new file mode 100644 index 000000000..acd65e08b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml @@ -0,0 +1,24 @@ + + + + + + + { + ... +} + ]]> + + + { + ... +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml new file mode 100644 index 000000000..a928e7db1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml new file mode 100644 index 000000000..f66cd92c9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml new file mode 100644 index 000000000..e9e61ddd6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/AbstractClassNamePrefixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + AbstractBar +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml new file mode 100644 index 000000000..f5345b712 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + doSomething() +{ +} + ]]> + + + do_something() +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml new file mode 100644 index 000000000..9dfc175ff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + __construct() + { + } +} + ]]> + + + Foo() + { + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml new file mode 100644 index 000000000..bf1a70769 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/InterfaceNameSuffixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + BarInterface +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml new file mode 100644 index 000000000..fb5f2e670 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/TraitNameSuffixStandard.xml @@ -0,0 +1,23 @@ + + + + + + + BarTrait +{ +} + ]]> + + + Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml new file mode 100644 index 000000000..22c2f6b12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + FOO_CONSTANT', 'foo'); + +class FooClass +{ + const FOO_CONSTANT = 'foo'; +} + ]]> + + + Foo_Constant', 'foo'); + +class FooClass +{ + const foo_constant = 'foo'; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml new file mode 100644 index 000000000..4ebd67704 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/BacktickOperatorStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml new file mode 100644 index 000000000..494a5d738 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + + + + Beginning content + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml new file mode 100644 index 000000000..f0c8e5298 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + +echo 'Foo'; +?> + ]]> + + + +echo 'Foo'; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml new file mode 100644 index 000000000..33b803a75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + explode('a', $bar); + ]]> + + + split('a', $bar); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml new file mode 100644 index 000000000..bdfd5dc16 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowAlternativePHPTagsStandard.xml @@ -0,0 +1,7 @@ + + + to delimit PHP code, do not use the ASP <% %> style tags nor the tags. This is the most portable way to include PHP code on differing operating systems and setups. + ]]> + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml new file mode 100644 index 000000000..519d7f5c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowRequestSuperglobalStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml new file mode 100644 index 000000000..8086ea271 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml @@ -0,0 +1,7 @@ + + + to delimit PHP code, not the shorthand. This is the most portable way to include PHP code on differing operating systems and setups. + ]]> + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml new file mode 100644 index 000000000..83bceef40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/DiscourageGotoStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml new file mode 100644 index 000000000..c0f18b557 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + count($bar); + ]]> + + + sizeof($bar); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml new file mode 100644 index 000000000..d4aac8093 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xml @@ -0,0 +1,23 @@ + + + true, false and null constants must always be lowercase. + ]]> + + + + false || $var === null) { + $var = true; +} + ]]> + + + FALSE || $var === NULL) { + $var = TRUE; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml new file mode 100644 index 000000000..965742d94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml @@ -0,0 +1,19 @@ + + + + + + + array(); + ]]> + + + Array(); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml new file mode 100644 index 000000000..f38df3af5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/LowerCaseTypeStandard.xml @@ -0,0 +1,38 @@ + + + + + + + + + + Int $foo) : STRING { +} + ]]> + + + + + + + + + + + (BOOL) $isValid; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml new file mode 100644 index 000000000..df6988794 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + isset($foo) && $foo) { + echo "Hello\n"; +} + ]]> + + + @$foo) { + echo "Hello\n"; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/RequireStrictTypesStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/RequireStrictTypesStandard.xml new file mode 100644 index 000000000..dc7243069 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/RequireStrictTypesStandard.xml @@ -0,0 +1,38 @@ + + + + + + + strict_types=1); + +declare(encoding='UTF-8', strict_types=0); + ]]> + + + ); + ]]> + + + + + + + + 1); + ]]> + + + 0); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml new file mode 100644 index 000000000..989827ed9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml @@ -0,0 +1,23 @@ + + + + + + + PHP_SAPI === 'cli') { + echo "Hello, CLI user."; +} + ]]> + + + php_sapi_name() === 'cli') { + echo "Hello, CLI user."; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SyntaxStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SyntaxStandard.xml new file mode 100644 index 000000000..1c2457df0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/SyntaxStandard.xml @@ -0,0 +1,21 @@ + + + + + + + echo "Hello!"; +$array = [1, 2, 3]; + ]]> + + + // Missing semicolon. +$array = [1, 2, 3; // Missing closing bracket. + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml new file mode 100644 index 000000000..2cc1df2f4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xml @@ -0,0 +1,23 @@ + + + true, false and null constants must always be uppercase. + ]]> + + + + FALSE || $var === NULL) { + $var = TRUE; +} + ]]> + + + false || $var === null) { + $var = true; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryHeredocStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryHeredocStandard.xml new file mode 100644 index 000000000..e0ca14f47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryHeredocStandard.xml @@ -0,0 +1,39 @@ + + + + + + + <<<'EOD' +some text +EOD; + ]]> + + + << +some text +EOD; + ]]> + + + + + <<<"EOD" +some $text +EOD; + ]]> + + + <<<"EOD" +some text +EOD; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml new file mode 100644 index 000000000..a4c9887b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml new file mode 100644 index 000000000..c38ae4c44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml new file mode 100644 index 000000000..d65c93a8c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ArbitraryParenthesesSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml new file mode 100644 index 000000000..2e399b34b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml new file mode 100644 index 000000000..7013ffd90 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/HereNowdocIdentifierSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/HereNowdocIdentifierSpacingStandard.xml new file mode 100644 index 000000000..66759bf5b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/HereNowdocIdentifierSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + << +some text +EOD; + ]]> + + + <<< END +some text +END; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/IncrementDecrementSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/IncrementDecrementSpacingStandard.xml new file mode 100644 index 000000000..92532fc68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/IncrementDecrementSpacingStandard.xml @@ -0,0 +1,26 @@ + + + + + + + $i; +--$i['key']['id']; +ClassName::$prop++; +$obj->prop--; + ]]> + + + $i; +-- $i['key']['id']; +ClassName::$prop ++; +$obj->prop +--; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml new file mode 100644 index 000000000..a9cd5a65c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml @@ -0,0 +1,44 @@ + + + + + + + 'Hello, World!'; +throw new Exception(); +return $newLine; + ]]> + + + 'Hello, World!'; +throw new Exception(); +return +$newLine; + ]]> + + + + + + + + from [1, 2, 3]; + ]]> + + + from [1, 2, 3]; +yield from [1, 2, 3]; +yield +from [1, 2, 3]; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml new file mode 100644 index 000000000..bdd36d498 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $var = 1; +} + ]]> + + + $var = 1; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml new file mode 100644 index 000000000..558bebfac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Docs/WhiteSpace/SpreadOperatorSpacingAfterStandard.xml @@ -0,0 +1,34 @@ + + + + + + + &...$spread) { + bar(...$spread); + + bar( + [...$foo], + ...array_values($keyedArray) + ); +} + ]]> + + + ... $spread) { + bar(... + $spread + ); + + bar( + [... $foo ],.../*@*/array_values($keyed) + ); +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php new file mode 100644 index 000000000..b6e3d37d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/ArrayIndentSniff.php @@ -0,0 +1,193 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; +use PHP_CodeSniffer\Util\Tokens; + +class ArrayIndentSniff extends AbstractArraySniff +{ + + /** + * The number of spaces each array key should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $tokens = $phpcsFile->getTokens(); + + // Determine how far indented the entire array declaration should be. + $ignore = Tokens::$emptyTokens; + $ignore[] = T_DOUBLE_ARROW; + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $start = $phpcsFile->findStartOfStatement($prev); + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $start, true); + $baseIndent = ($tokens[$first]['column'] - 1); + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $startIndent = ($tokens[$first]['column'] - 1); + + // If the open brace is not indented to at least to the level of the start + // of the statement, the sniff will conflict with other sniffs trying to + // check indent levels because it's not valid. But we don't enforce exactly + // how far indented it should be. + if ($startIndent < $baseIndent) { + $pluralizeSpace = 's'; + if ($baseIndent === 1) { + $pluralizeSpace = ''; + } + + $error = 'Array open brace not indented correctly; expected at least %s space%s but found %s'; + $data = [ + $baseIndent, + $pluralizeSpace, + $startIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OpenBraceIncorrect', $data); + if ($fix === true) { + $padding = str_repeat(' ', $baseIndent); + if ($startIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + } + + return; + }//end if + + $expectedIndent = ($startIndent + $this->indent); + + foreach ($indices as $index) { + if (isset($index['index_start']) === true) { + $start = $index['index_start']; + } else { + $start = $index['value_start']; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$start]['line']) { + // This index isn't the only content on the line + // so we can't check indent rules. + continue; + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $start, true); + + $foundIndent = ($tokens[$first]['column'] - 1); + if ($foundIndent === $expectedIndent) { + continue; + } + + $pluralizeSpace = 's'; + if ($expectedIndent === 1) { + $pluralizeSpace = ''; + } + + $error = 'Array key not indented correctly; expected %s space%s but found %s'; + $data = [ + $expectedIndent, + $pluralizeSpace, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $first, 'KeyIncorrect', $data); + if ($fix === false) { + continue; + } + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + }//end foreach + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$arrayEnd]['line']) { + $error = 'Closing brace of array declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotNewLine'); + if ($fix === true) { + $padding = $phpcsFile->eolChar.str_repeat(' ', $startIndent); + $phpcsFile->fixer->addContentBefore($arrayEnd, $padding); + } + + return; + } + + // The close brace must be indented one stop less. + $foundIndent = ($tokens[$arrayEnd]['column'] - 1); + if ($foundIndent === $startIndent) { + return; + } + + $pluralizeSpace = 's'; + if ($startIndent === 1) { + $pluralizeSpace = ''; + } + + $error = 'Array close brace not indented correctly; expected %s space%s but found %s'; + $data = [ + $startIndent, + $pluralizeSpace, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceIncorrect', $data); + if ($fix === false) { + return; + } + + $padding = str_repeat(' ', $startIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($arrayEnd, $padding); + } else { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), $padding); + } + + }//end processMultiLineArray() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php new file mode 100644 index 000000000..6854945ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowLongArraySyntaxSniff.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowLongArraySyntaxSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ARRAY]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + $error = 'Short array syntax must be used to define arrays'; + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) { + // Live coding/parse error, just show the error, don't try and fix it. + $phpcsFile->addError($error, $stackPtr, 'Found'); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + + if ($fix === true) { + $opener = $tokens[$stackPtr]['parenthesis_opener']; + $closer = $tokens[$stackPtr]['parenthesis_closer']; + + $phpcsFile->fixer->beginChangeset(); + + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $phpcsFile->fixer->replaceToken($opener, '['); + $phpcsFile->fixer->replaceToken($closer, ']'); + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php new file mode 100644 index 000000000..f98277116 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Arrays/DisallowShortArraySyntaxSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowShortArraySyntaxSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_SHORT_ARRAY]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + + $error = 'Short array syntax is not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $opener = $tokens[$stackPtr]['bracket_opener']; + $closer = $tokens[$stackPtr]['bracket_closer']; + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($opener, 'array('); + $phpcsFile->fixer->replaceToken($closer, ')'); + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php new file mode 100644 index 000000000..ca1ed0999 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php @@ -0,0 +1,126 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DuplicateClassNameSniff implements Sniff +{ + + /** + * List of classes that have been found during checking. + * + * @var array + */ + protected $foundClasses = []; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $namespace = ''; + $findTokens = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_NAMESPACE, + ]; + + $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1)); + while ($stackPtr !== false) { + // Keep track of what namespace we are in. + if ($tokens[$stackPtr]['code'] === T_NAMESPACE) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== false + // Ignore namespace keyword used as operator. + && $tokens[$nextNonEmpty]['code'] !== T_NS_SEPARATOR + ) { + $namespace = ''; + for ($i = $nextNonEmpty; $i < $phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if ($tokens[$i]['code'] !== T_STRING && $tokens[$i]['code'] !== T_NS_SEPARATOR) { + break; + } + + $namespace .= $tokens[$i]['content']; + } + + $stackPtr = $i; + } + } else { + $name = $phpcsFile->getDeclarationName($stackPtr); + if (empty($name) === false) { + if ($namespace !== '') { + $name = $namespace.'\\'.$name; + } + + $compareName = strtolower($name); + if (isset($this->foundClasses[$compareName]) === true) { + $type = strtolower($tokens[$stackPtr]['content']); + $file = $this->foundClasses[$compareName]['file']; + $line = $this->foundClasses[$compareName]['line']; + $error = 'Duplicate %s name "%s" found; first defined in %s on line %s'; + $data = [ + $type, + $name, + $file, + $line, + ]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } else { + $this->foundClasses[$compareName] = [ + 'file' => $phpcsFile->getFilename(), + 'line' => $tokens[$stackPtr]['line'], + ]; + } + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $stackPtr = $tokens[$stackPtr]['scope_closer']; + } + }//end if + + $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1)); + }//end while + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php new file mode 100644 index 000000000..40291ea47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Classes/OpeningBraceSameLineSniff.php @@ -0,0 +1,124 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OpeningBraceSameLineSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $scopeIdentifier = $phpcsFile->findNext(T_STRING, ($stackPtr + 1)); + $errorData = [strtolower($tokens[$stackPtr]['content']).' '.$tokens[$scopeIdentifier]['content']]; + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData); + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + + // Is the brace on the same line as the class/interface/trait declaration ? + $lastClassLineToken = $phpcsFile->findPrevious(T_WHITESPACE, ($openingBrace - 1), $stackPtr, true); + $lastClassLine = $tokens[$lastClassLineToken]['line']; + $braceLine = $tokens[$openingBrace]['line']; + $lineDifference = ($braceLine - $lastClassLine); + + if ($lineDifference > 0) { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'new line'); + $error = 'Opening brace should be on the same line as the declaration for %s'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnNewLine', $errorData); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($lastClassLineToken, ' {'); + $phpcsFile->fixer->replaceToken($openingBrace, ''); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'same line'); + } + + // Is the opening brace the last thing on the line ? + $next = $phpcsFile->findNext(T_WHITESPACE, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + if ($next === $tokens[$stackPtr]['scope_closer']) { + // Ignore empty classes. + return; + } + + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference > 0) { + return; + } + + // Is there precisely one space before the opening brace ? + if ($tokens[($openingBrace - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($openingBrace - 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($openingBrace - 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space before opening brace; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + if ($length === 0 || $length === '\t') { + $phpcsFile->fixer->addContentBefore($openingBrace, ' '); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php new file mode 100644 index 000000000..fecd16a75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/AssignmentInConditionSniff.php @@ -0,0 +1,171 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class AssignmentInConditionSniff implements Sniff +{ + + /** + * Assignment tokens to trigger on. + * + * Set in the register() method. + * + * @var array + */ + protected $assignmentTokens = []; + + /** + * The tokens that indicate the start of a condition. + * + * @var array + */ + protected $conditionStartTokens = []; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + $this->assignmentTokens = Tokens::$assignmentTokens; + unset($this->assignmentTokens[T_DOUBLE_ARROW]); + + $starters = Tokens::$booleanOperators; + $starters[T_SEMICOLON] = T_SEMICOLON; + $starters[T_OPEN_PARENTHESIS] = T_OPEN_PARENTHESIS; + + $this->conditionStartTokens = $starters; + + return [ + T_IF, + T_ELSEIF, + T_FOR, + T_SWITCH, + T_CASE, + T_WHILE, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Find the condition opener/closer. + if ($token['code'] === T_FOR) { + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($token['parenthesis_opener'] + 1), ($token['parenthesis_closer'])); + if ($semicolon === false) { + return; + } + + $opener = $semicolon; + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($opener + 1), ($token['parenthesis_closer'])); + if ($semicolon === false) { + return; + } + + $closer = $semicolon; + unset($semicolon); + } else if ($token['code'] === T_CASE) { + if (isset($token['scope_opener']) === false) { + return; + } + + $opener = $stackPtr; + $closer = $token['scope_opener']; + } else { + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $opener = $token['parenthesis_opener']; + $closer = $token['parenthesis_closer']; + }//end if + + $startPos = $opener; + + do { + $hasAssignment = $phpcsFile->findNext($this->assignmentTokens, ($startPos + 1), $closer); + if ($hasAssignment === false) { + return; + } + + // Examine whether the left side is a variable. + $hasVariable = false; + $conditionStart = $startPos; + $altConditionStart = $phpcsFile->findPrevious($this->conditionStartTokens, ($hasAssignment - 1), $startPos); + if ($altConditionStart !== false) { + $conditionStart = $altConditionStart; + } + + for ($i = $hasAssignment; $i > $conditionStart; $i--) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // If this is a variable or array, we've seen all we need to see. + if ($tokens[$i]['code'] === T_VARIABLE || $tokens[$i]['code'] === T_CLOSE_SQUARE_BRACKET) { + $hasVariable = true; + break; + } + + // If this is a function call or something, we are OK. + if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + } + + if ($hasVariable === true) { + $errorCode = 'Found'; + if ($token['code'] === T_WHILE) { + $errorCode = 'FoundInWhileCondition'; + } + + $phpcsFile->addWarning( + 'Variable assignment found within a condition. Did you mean to do a comparison ?', + $hasAssignment, + $errorCode + ); + } + + $startPos = $hasAssignment; + } while ($startPos < $closer); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php new file mode 100644 index 000000000..4ecf63037 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyPHPStatementSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyPHPStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_SEMICOLON, + T_CLOSE_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + switch ($tokens[$stackPtr]['type']) { + // Detect `something();;`. + case 'T_SEMICOLON': + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if ($prevNonEmpty === false) { + return; + } + + if ($tokens[$prevNonEmpty]['code'] !== T_SEMICOLON + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG_WITH_ECHO + ) { + if (isset($tokens[$prevNonEmpty]['scope_condition']) === false) { + return; + } + + if ($tokens[$prevNonEmpty]['scope_opener'] !== $prevNonEmpty + && $tokens[$prevNonEmpty]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + return; + } + + $scopeOwner = $tokens[$tokens[$prevNonEmpty]['scope_condition']]['code']; + if ($scopeOwner === T_CLOSURE || $scopeOwner === T_ANON_CLASS || $scopeOwner === T_MATCH) { + return; + } + + // Else, it's something like `if (foo) {};` and the semicolon is not needed. + } + + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + $lastCloser = array_pop($nested); + if (isset($tokens[$lastCloser]['parenthesis_owner']) === true + && $tokens[$tokens[$lastCloser]['parenthesis_owner']]['code'] === T_FOR + ) { + // Empty for() condition. + return; + } + } + + $fix = $phpcsFile->addFixableWarning( + 'Empty PHP statement detected: superfluous semicolon.', + $stackPtr, + 'SemicolonWithoutCodeDetected' + ); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$prevNonEmpty]['code'] === T_OPEN_TAG + || $tokens[$prevNonEmpty]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + // Check for superfluous whitespace after the semicolon which will be + // removed as the `fixer->replaceToken(($stackPtr + 1), $replacement); + } + } + + for ($i = $stackPtr; $i > $prevNonEmpty; $i--) { + if ($tokens[$i]['code'] !== T_SEMICOLON + && $tokens[$i]['code'] !== T_WHITESPACE + ) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + break; + + // Detect ``. + case 'T_CLOSE_TAG': + $prevNonEmpty = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($prevNonEmpty === false + || ($tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG + && $tokens[$prevNonEmpty]['code'] !== T_OPEN_TAG_WITH_ECHO) + ) { + return; + } + + $fix = $phpcsFile->addFixableWarning( + 'Empty PHP open/close tag combination detected.', + $prevNonEmpty, + 'EmptyPHPOpenCloseTagsDetected' + ); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = $prevNonEmpty; $i <= $stackPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + break; + + default: + // Deliberately left empty. + break; + }//end switch + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php new file mode 100644 index 000000000..ded042a9a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php @@ -0,0 +1,97 @@ + + * stmt { + * // foo + * } + * stmt (conditions) { + * // foo + * } + * + * + * @author Manuel Pichler + * @author Greg Sherwood + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyStatementSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_TRY, + T_CATCH, + T_FINALLY, + T_DO, + T_ELSE, + T_ELSEIF, + T_FOR, + T_FOREACH, + T_IF, + T_SWITCH, + T_WHILE, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip statements without a body. + if (isset($token['scope_opener']) === false) { + return; + } + + $next = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($token['scope_opener'] + 1), + ($token['scope_closer'] - 1), + true + ); + + if ($next !== false) { + return; + } + + // Get token identifier. + $name = strtoupper($token['content']); + $error = 'Empty %s statement detected'; + $phpcsFile->addError($error, $stackPtr, 'Detected'.ucfirst(strtolower($name)), [$name]); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php new file mode 100644 index 000000000..726b32c55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php @@ -0,0 +1,91 @@ + + * class Foo + * { + * public function bar($x) + * { + * for (;true;) true; // No Init or Update part, may as well be: while (true) + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopShouldBeWhileLoopSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip invalid statement. + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $parts = [ + 0, + 0, + 0, + ]; + $index = 0; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$index; + } else if (isset(Tokens::$emptyTokens[$code]) === false) { + ++$parts[$index]; + } + } + + if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) { + $error = 'This FOR loop can be simplified to a WHILE loop'; + $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php new file mode 100644 index 000000000..0374a8f75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php @@ -0,0 +1,101 @@ + + * class Foo + * { + * public function bar($x) + * { + * $a = array(1, 2, 3, 4); + * for ($i = 0; $i < count($a); $i++) { + * $a[$i] *= $i; + * } + * } + * } + * + * + * @author Greg Sherwood + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopWithTestFunctionCallSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip invalid statement. + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $position = 0; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$position; + } + + if ($position < 1) { + continue; + } else if ($position > 1) { + break; + } else if ($code !== T_VARIABLE && $code !== T_STRING) { + continue; + } + + // Find next non empty token, if it is a open parenthesis we have a + // function call. + $index = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) { + $error = 'Avoid function calls in a FOR loop test part'; + $phpcsFile->addWarning($error, $stackPtr, 'NotAllowed'); + break; + } + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php new file mode 100644 index 000000000..8174d6653 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php @@ -0,0 +1,134 @@ + + * class Foo + * { + * public function bar($x) + * { + * for ($i = 0; $i < 10; $i++) + * { + * for ($k = 0; $k < 20; $i++) + * { + * echo 'Hello'; + * } + * } + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class JumbledIncrementerSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip for-loop without body. + if (isset($token['scope_opener']) === false) { + return; + } + + // Find incrementers for outer loop. + $outer = $this->findIncrementers($tokens, $token); + + // Skip if empty. + if (count($outer) === 0) { + return; + } + + // Find nested for loops. + $start = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $start <= $end; ++$start) { + if ($tokens[$start]['code'] !== T_FOR) { + continue; + } + + $inner = $this->findIncrementers($tokens, $tokens[$start]); + $diff = array_intersect($outer, $inner); + + if (count($diff) !== 0) { + $error = 'Loop incrementer (%s) jumbling with inner loop'; + $data = [implode(', ', $diff)]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + } + + }//end process() + + + /** + * Get all used variables in the incrementer part of a for statement. + * + * @param array $tokens Array with all code sniffer tokens. + * @param array $token Current for loop token. + * + * @return string[] List of all found incrementer variables. + */ + protected function findIncrementers(array $tokens, array $token) + { + // Skip invalid statement. + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return []; + } + + $start = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $incrementers = []; + $semicolons = 0; + for ($next = $start; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + if ($code === T_SEMICOLON) { + ++$semicolons; + } else if ($semicolons === 2 && $code === T_VARIABLE) { + $incrementers[] = $tokens[$next]['content']; + } + } + + return $incrementers; + + }//end findIncrementers() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceSniff.php new file mode 100644 index 000000000..41922efc6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/RequireExplicitBooleanOperatorPrecedenceSniff.php @@ -0,0 +1,112 @@ + + * $one = false; + * $two = false; + * $three = true; + * + * $result = $one && $two || $three; + * $result3 = $one && !$two xor $three; + * + * + * {@internal The unary `!` operator is not handled, because its high precedence matches its visuals of + * applying only to the sub-expression right next to it, making it unlikely that someone would + * misinterpret its precedence. Requiring parentheses around it would reduce the readability of + * expressions due to the additional characters, especially if multiple subexpressions / variables + * need to be negated.} + * + * Sister-sniff to the `Squiz.ControlStructures.InlineIfDeclaration` and + * `Squiz.Formatting.OperatorBracket.MissingBrackets` sniffs. + * + * @author Tim Duesterhus + * @copyright 2021-2023 WoltLab GmbH. + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class RequireExplicitBooleanOperatorPrecedenceSniff implements Sniff +{ + + /** + * Array of tokens this test searches for to find either a boolean + * operator or the start of the current (sub-)expression. Used for + * performance optimization purposes. + * + * @var array + */ + private $searchTargets = []; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $this->searchTargets = Tokens::$booleanOperators; + $this->searchTargets[T_INLINE_THEN] = T_INLINE_THEN; + $this->searchTargets[T_INLINE_ELSE] = T_INLINE_ELSE; + + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $start = $phpcsFile->findStartOfStatement($stackPtr); + + $previous = $phpcsFile->findPrevious( + $this->searchTargets, + ($stackPtr - 1), + $start, + false, + null, + true + ); + + if ($previous === false) { + // No token found. + return; + } + + if ($tokens[$previous]['code'] === $tokens[$stackPtr]['code']) { + // Identical operator found. + return; + } + + if (in_array($tokens[$previous]['code'], [T_INLINE_THEN, T_INLINE_ELSE], true) === true) { + // Beginning of the expression found for the ternary conditional operator. + return; + } + + // We found a mismatching operator, thus we must report the error. + $error = 'Mixing different binary boolean operators within an expression'; + $error .= ' without using parentheses to clarify precedence is not allowed.'; + $phpcsFile->addError($error, $stackPtr, 'MissingParentheses'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php new file mode 100644 index 000000000..db71a9676 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php @@ -0,0 +1,93 @@ +true or false + * + * + * class Foo + * { + * public function close() + * { + * if (true) + * { + * // ... + * } + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnconditionalIfStatementSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip if statement without body. + if (isset($token['parenthesis_opener'], $token['parenthesis_closer']) === false) { + return; + } + + $next = ++$token['parenthesis_opener']; + $end = --$token['parenthesis_closer']; + + $goodCondition = false; + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } else if ($code !== T_TRUE && $code !== T_FALSE) { + $goodCondition = true; + } + } + + if ($goodCondition === false) { + $error = 'Avoid IF statements that are always true or false'; + $phpcsFile->addWarning($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php new file mode 100644 index 000000000..2f4faa891 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php @@ -0,0 +1,88 @@ + + * final class Foo + * { + * public final function bar() + * { + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class UnnecessaryFinalModifierSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip for statements without body. + if (isset($token['scope_opener']) === false) { + return; + } + + if ($phpcsFile->getClassProperties($stackPtr)['is_final'] === false) { + // This class is not final so we don't need to check it. + return; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $next <= $end; ++$next) { + if ($tokens[$next]['code'] === T_FINAL) { + $error = 'Unnecessary FINAL modifier in FINAL class'; + $phpcsFile->addWarning($error, $next, 'Found'); + } + + // Skip over the contents of functions as those can't contain the `final` keyword anyway. + if ($tokens[$next]['code'] === T_FUNCTION + && isset($tokens[$next]['scope_closer']) === true + ) { + $next = $tokens[$next]['scope_closer']; + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php new file mode 100644 index 000000000..e076b83dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php @@ -0,0 +1,307 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UnusedFunctionParameterSniff implements Sniff +{ + + /** + * The list of class type hints which will be ignored. + * + * @var array + */ + public $ignoreTypeHints = []; + + /** + * A list of all PHP magic methods with fixed method signatures. + * + * Note: `__construct()` and `__invoke()` are excluded on purpose + * as their method signature is not fixed. + * + * @var array + */ + private $magicMethods = [ + '__destruct' => true, + '__call' => true, + '__callstatic' => true, + '__get' => true, + '__set' => true, + '__isset' => true, + '__unset' => true, + '__sleep' => true, + '__wakeup' => true, + '__serialize' => true, + '__unserialize' => true, + '__tostring' => true, + '__set_state' => true, + '__clone' => true, + '__debuginfo' => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip broken function declarations. + if (isset($token['scope_opener']) === false || isset($token['parenthesis_opener']) === false) { + return; + } + + $errorCode = 'Found'; + $implements = false; + + if ($token['code'] === T_FUNCTION) { + $classPtr = $phpcsFile->getCondition($stackPtr, T_CLASS); + if ($classPtr !== false) { + // Check for magic methods and ignore these as the method signature cannot be changed. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if (empty($methodName) === false) { + $methodNameLc = strtolower($methodName); + if (isset($this->magicMethods[$methodNameLc]) === true) { + return; + } + } + + // Check for extends/implements and adjust the error code when found. + $implements = $phpcsFile->findImplementedInterfaceNames($classPtr); + $extends = $phpcsFile->findExtendedClassName($classPtr); + if ($extends !== false) { + $errorCode .= 'InExtendedClass'; + } else if ($implements !== false) { + $errorCode .= 'InImplementedInterface'; + } + } + }//end if + + $params = []; + $methodParams = $phpcsFile->getMethodParameters($stackPtr); + + // Skip when no parameters found. + $methodParamsCount = count($methodParams); + if ($methodParamsCount === 0) { + return; + } + + foreach ($methodParams as $param) { + if (isset($param['property_visibility']) === true) { + // Ignore constructor property promotion. + continue; + } + + $params[$param['name']] = $stackPtr; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + // Check the end token for arrow functions as + // they can end at a content token due to not having + // a clearly defined closing token. + if ($token['code'] === T_FN) { + ++$end; + } + + $foundContent = false; + $validTokens = [ + T_HEREDOC => T_HEREDOC, + T_NOWDOC => T_NOWDOC, + T_END_HEREDOC => T_END_HEREDOC, + T_END_NOWDOC => T_END_NOWDOC, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + $validTokens += Tokens::$emptyTokens; + + for (; $next <= $end; ++$next) { + $token = $tokens[$next]; + $code = $token['code']; + + // Ignorable tokens. + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } + + if ($foundContent === false) { + // A throw statement as the first content indicates an interface method. + if ($code === T_THROW && $implements !== false) { + return; + } + + // A return statement as the first content indicates an interface method. + if ($code === T_RETURN) { + $firstNonEmptyTokenAfterReturn = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($tokens[$firstNonEmptyTokenAfterReturn]['code'] === T_SEMICOLON && $implements !== false) { + return; + } + + $secondNonEmptyTokenAfterReturn = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($firstNonEmptyTokenAfterReturn + 1), + null, + true + ); + + if ($secondNonEmptyTokenAfterReturn !== false + && $tokens[$secondNonEmptyTokenAfterReturn]['code'] === T_SEMICOLON + && $implements !== false + ) { + // There is a return . + return; + } + }//end if + }//end if + + $foundContent = true; + + if ($code === T_VARIABLE && isset($params[$token['content']]) === true) { + unset($params[$token['content']]); + } else if ($code === T_DOLLAR) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_CURLY_BRACKET) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_STRING) { + $varContent = '$'.$tokens[$nextToken]['content']; + if (isset($params[$varContent]) === true) { + unset($params[$varContent]); + } + } + } + } else if ($code === T_DOUBLE_QUOTED_STRING + || $code === T_START_HEREDOC + || $code === T_START_NOWDOC + ) { + // Tokenize strings that can contain variables. + // Make sure the string is re-joined if it occurs over multiple lines. + $content = $token['content']; + for ($i = ($next + 1); $i <= $end; $i++) { + if (isset($validTokens[$tokens[$i]['code']]) === true) { + $content .= $tokens[$i]['content']; + $next++; + } else { + break; + } + } + + $stringTokens = token_get_all(sprintf('', $content)); + foreach ($stringTokens as $stringPtr => $stringToken) { + if (is_array($stringToken) === false) { + continue; + } + + $varContent = ''; + if ($stringToken[0] === T_DOLLAR_OPEN_CURLY_BRACES) { + $varContent = '$'.$stringTokens[($stringPtr + 1)][1]; + } else if ($stringToken[0] === T_VARIABLE) { + $varContent = $stringToken[1]; + } + + if ($varContent !== '' && isset($params[$varContent]) === true) { + unset($params[$varContent]); + } + } + }//end if + }//end for + + if ($foundContent === true && count($params) > 0) { + $error = 'The method parameter %s is never used'; + + // If there is only one parameter and it is unused, no need for additional errorcode toggling logic. + if ($methodParamsCount === 1) { + foreach ($params as $paramName => $position) { + if (in_array($methodParams[0]['type_hint'], $this->ignoreTypeHints, true) === true) { + continue; + } + + $data = [$paramName]; + $phpcsFile->addWarning($error, $position, $errorCode, $data); + } + + return; + } + + $foundLastUsed = false; + $lastIndex = ($methodParamsCount - 1); + $errorInfo = []; + for ($i = $lastIndex; $i >= 0; --$i) { + if ($foundLastUsed !== false) { + if (isset($params[$methodParams[$i]['name']]) === true) { + $errorInfo[$methodParams[$i]['name']] = [ + 'position' => $params[$methodParams[$i]['name']], + 'errorcode' => $errorCode.'BeforeLastUsed', + 'typehint' => $methodParams[$i]['type_hint'], + ]; + } + } else { + if (isset($params[$methodParams[$i]['name']]) === false) { + $foundLastUsed = true; + } else { + $errorInfo[$methodParams[$i]['name']] = [ + 'position' => $params[$methodParams[$i]['name']], + 'errorcode' => $errorCode.'AfterLastUsed', + 'typehint' => $methodParams[$i]['type_hint'], + ]; + } + } + }//end for + + if (count($errorInfo) > 0) { + $errorInfo = array_reverse($errorInfo); + foreach ($errorInfo as $paramName => $info) { + if (in_array($info['typehint'], $this->ignoreTypeHints, true) === true) { + continue; + } + + $data = [$paramName]; + $phpcsFile->addWarning($error, $info['position'], $info['errorcode'], $data); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php new file mode 100644 index 000000000..5163da71c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php @@ -0,0 +1,184 @@ + + * class FooBar { + * public function __construct($a, $b) { + * parent::__construct($a, $b); + * } + * } + * + * + * @author Manuel Pichler + * @copyright 2007-2014 Manuel Pichler. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UselessOverridingMethodSniff implements Sniff +{ + + /** + * Object-Oriented scopes in which a call to parent::method() can exist. + * + * @var array Keys are the token constants, value is irrelevant. + */ + private $validOOScopes = [ + T_CLASS => true, + T_ANON_CLASS => true, + T_TRAIT => true, + ]; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[$stackPtr]; + + // Skip function without body. + if (isset($token['scope_opener'], $token['scope_closer']) === false) { + return; + } + + $conditions = $token['conditions']; + $lastCondition = end($conditions); + + // Skip functions that are not a method part of a class, anon class or trait. + if (isset($this->validOOScopes[$lastCondition]) === false) { + return; + } + + // Get function name. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + + // Get all parameters from method signature. + $signature = []; + foreach ($phpcsFile->getMethodParameters($stackPtr) as $param) { + $signature[] = $param['name']; + } + + $next = ++$token['scope_opener']; + $end = --$token['scope_closer']; + + for (; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + + if (isset(Tokens::$emptyTokens[$code]) === true) { + continue; + } else if ($code === T_RETURN) { + continue; + } + + break; + } + + // Any token except 'parent' indicates correct code. + if ($tokens[$next]['code'] !== T_PARENT) { + return; + } + + // Find next non empty token index, should be double colon. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code. + if ($tokens[$next]['code'] !== T_DOUBLE_COLON) { + return; + } + + // Find next non empty token index, should be the name of the method being called. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code or other method. + if (strcasecmp($tokens[$next]['content'], $methodName) !== 0) { + return; + } + + // Find next non empty token index, should be the open parenthesis. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + + // Skip for invalid code. + if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS || isset($tokens[$next]['parenthesis_closer']) === false) { + return; + } + + $parameters = ['']; + $parenthesisCount = 1; + for (++$next; $next < $phpcsFile->numTokens; ++$next) { + $code = $tokens[$next]['code']; + + if ($code === T_OPEN_PARENTHESIS) { + ++$parenthesisCount; + } else if ($code === T_CLOSE_PARENTHESIS) { + --$parenthesisCount; + } else if ($parenthesisCount === 1 && $code === T_COMMA) { + $parameters[] = ''; + } else if (isset(Tokens::$emptyTokens[$code]) === false) { + $parameters[(count($parameters) - 1)] .= $tokens[$next]['content']; + } + + if ($parenthesisCount === 0) { + break; + } + }//end for + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($tokens[$next]['code'] !== T_SEMICOLON && $tokens[$next]['code'] !== T_CLOSE_TAG) { + return; + } + + // This list deliberately does not include the `T_OPEN_TAG_WITH_ECHO` as that token implicitly is an echo statement, i.e. content. + $nonContent = Tokens::$emptyTokens; + $nonContent[T_OPEN_TAG] = T_OPEN_TAG; + $nonContent[T_CLOSE_TAG] = T_CLOSE_TAG; + + // Check rest of the scope. + for (++$next; $next <= $end; ++$next) { + $code = $tokens[$next]['code']; + // Skip for any other content. + if (isset($nonContent[$code]) === false) { + return; + } + } + + $parameters = array_map('trim', $parameters); + $parameters = array_filter($parameters); + + if (count($parameters) === count($signature) && $parameters === $signature) { + $phpcsFile->addWarning('Possible useless method overriding detected', $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php new file mode 100644 index 000000000..f34ffc2b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/DocCommentSniff.php @@ -0,0 +1,357 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DocCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOC_COMMENT_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['comment_closer']) === false + || ($tokens[$tokens[$stackPtr]['comment_closer']]['content'] === '' + && $tokens[$stackPtr]['comment_closer'] === ($phpcsFile->numTokens - 1)) + ) { + // Don't process an unfinished comment during live coding. + return; + } + + $commentStart = $stackPtr; + $commentEnd = $tokens[$stackPtr]['comment_closer']; + + $empty = [ + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + + $short = $phpcsFile->findNext($empty, ($stackPtr + 1), $commentEnd, true); + if ($short === false) { + // No content at all. + $error = 'Doc comment is empty'; + $phpcsFile->addError($error, $stackPtr, 'Empty'); + return; + } + + // The first line of the comment should just be the /** code. + if ($tokens[$short]['line'] === $tokens[$stackPtr]['line']) { + $error = 'The open comment tag must be the only content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + $phpcsFile->fixer->addContentBefore($short, '* '); + $phpcsFile->fixer->endChangeset(); + } + } + + // The last line of the comment should just be the */ code. + $prev = $phpcsFile->findPrevious($empty, ($commentEnd - 1), $stackPtr, true); + if ($tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $error = 'The close comment tag must be the only content on the line'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($commentEnd); + } + } + + // Check for additional blank lines at the end of the comment. + if ($tokens[$prev]['line'] < ($tokens[$commentEnd]['line'] - 1)) { + $error = 'Additional blank lines found at end of doc comment'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $commentEnd; $i++) { + if ($tokens[($i + 1)]['line'] === $tokens[$commentEnd]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Check for a comment description. + if ($tokens[$short]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Missing short description in doc comment'; + $phpcsFile->addError($error, $stackPtr, 'MissingShort'); + } else { + // No extra newline before short description. + if ($tokens[$short]['line'] !== ($tokens[$stackPtr]['line'] + 1)) { + $error = 'Doc comment short description must be on the first line'; + $fix = $phpcsFile->addFixableError($error, $short, 'SpacingBeforeShort'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i < $short; $i++) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } else if ($tokens[$i]['line'] === $tokens[$short]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Account for the fact that a short description might cover + // multiple lines. + $shortContent = $tokens[$short]['content']; + $shortEnd = $short; + for ($i = ($short + 1); $i < $commentEnd; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$i]['line'] === ($tokens[$shortEnd]['line'] + 1)) { + $shortContent .= $tokens[$i]['content']; + $shortEnd = $i; + } else { + break; + } + } + } + + if (preg_match('/^\p{Ll}/u', $shortContent) === 1) { + $error = 'Doc comment short description must start with a capital letter'; + $phpcsFile->addError($error, $short, 'ShortNotCapital'); + } + + $long = $phpcsFile->findNext($empty, ($shortEnd + 1), ($commentEnd - 1), true); + if ($long !== false && $tokens[$long]['code'] === T_DOC_COMMENT_STRING) { + if ($tokens[$long]['line'] !== ($tokens[$shortEnd]['line'] + 2)) { + $error = 'There must be exactly one blank line between descriptions in a doc comment'; + $fix = $phpcsFile->addFixableError($error, $long, 'SpacingBetween'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($shortEnd + 1); $i < $long; $i++) { + if ($tokens[$i]['line'] === $tokens[$shortEnd]['line']) { + continue; + } else if ($tokens[$i]['line'] === ($tokens[$long]['line'] - 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if (preg_match('/^\p{Ll}/u', $tokens[$long]['content']) === 1) { + $error = 'Doc comment long description must start with a capital letter'; + $phpcsFile->addError($error, $long, 'LongNotCapital'); + } + }//end if + }//end if + + if (empty($tokens[$commentStart]['comment_tags']) === true) { + // No tags in the comment. + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + $prev = $phpcsFile->findPrevious($empty, ($firstTag - 1), $stackPtr, true); + if ($tokens[$firstTag]['line'] !== ($tokens[$prev]['line'] + 2) + && $tokens[$prev]['code'] !== T_DOC_COMMENT_OPEN_TAG + ) { + $error = 'There must be exactly one blank line before the tags in a doc comment'; + $fix = $phpcsFile->addFixableError($error, $firstTag, 'SpacingBeforeTags'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $firstTag; $i++) { + if ($tokens[$i]['line'] === $tokens[$firstTag]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $indent = str_repeat(' ', $tokens[$stackPtr]['column']); + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + // Break out the tags into groups and check alignment within each. + // A tag group is one where there are no blank lines between tags. + // The param tag group is special as it requires all @param tags to be inside. + $tagGroups = []; + $groupid = 0; + $paramGroupid = null; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($pos > 0) { + $prev = $phpcsFile->findPrevious( + T_DOC_COMMENT_STRING, + ($tag - 1), + $tokens[$commentStart]['comment_tags'][($pos - 1)] + ); + + if ($prev === false) { + $prev = $tokens[$commentStart]['comment_tags'][($pos - 1)]; + } + + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) { + $groupid++; + } + } + + if ($tokens[$tag]['content'] === '@param') { + if ($paramGroupid !== null + && $paramGroupid !== $groupid + ) { + $error = 'Parameter tags must be grouped together in a doc comment'; + $phpcsFile->addError($error, $tag, 'ParamGroup'); + } + + if ($paramGroupid === null) { + $paramGroupid = $groupid; + } + }//end if + + $tagGroups[$groupid][] = $tag; + }//end foreach + + foreach ($tagGroups as $groupid => $group) { + $maxLength = 0; + $paddings = []; + foreach ($group as $pos => $tag) { + if ($paramGroupid === $groupid + && $tokens[$tag]['content'] !== '@param' + ) { + $error = 'Tag %s cannot be grouped with parameter tags in a doc comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addError($error, $tag, 'NonParamGroup', $data); + } + + $tagLength = $tokens[$tag]['length']; + if ($tagLength > $maxLength) { + $maxLength = $tagLength; + } + + // Check for a value. No value means no padding needed. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string !== false && $tokens[$string]['line'] === $tokens[$tag]['line']) { + $paddings[$tag] = $tokens[($tag + 1)]['length']; + } + } + + // Check that there was single blank line after the tag block + // but account for multi-line tag comments. + $find = Tokens::$phpcsCommentTokens; + $find[T_DOC_COMMENT_TAG] = T_DOC_COMMENT_TAG; + + $lastTag = $group[$pos]; + $next = $phpcsFile->findNext($find, ($lastTag + 3), $commentEnd); + if ($next !== false) { + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_TAG, T_DOC_COMMENT_STRING], ($next - 1), $commentStart); + if ($tokens[$next]['line'] !== ($tokens[$prev]['line'] + 2)) { + $error = 'There must be a single blank line after a tag group'; + $fix = $phpcsFile->addFixableError($error, $lastTag, 'SpacingAfterTagGroup'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $indent = str_repeat(' ', $tokens[$stackPtr]['column']); + $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + // Now check paddings. + foreach ($paddings as $tag => $padding) { + $required = ($maxLength - $tokens[$tag]['length'] + 1); + + if ($padding !== $required) { + $error = 'Tag value for %s tag indented incorrectly; expected %s spaces but found %s'; + $data = [ + $tokens[$tag]['content'], + $required, + $padding, + ]; + + $fix = $phpcsFile->addFixableError($error, ($tag + 1), 'TagValueIndent', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($tag + 1), str_repeat(' ', $required)); + } + } + } + }//end foreach + + // If there is a param group, it needs to be first. + if ($paramGroupid !== null && $paramGroupid !== 0) { + $error = 'Parameter tags must be defined first in a doc comment'; + $phpcsFile->addError($error, $tagGroups[$paramGroupid][0], 'ParamNotFirst'); + } + + $foundTags = []; + foreach ($tokens[$stackPtr]['comment_tags'] as $pos => $tag) { + $tagName = $tokens[$tag]['content']; + if (isset($foundTags[$tagName]) === true) { + $lastTag = $tokens[$stackPtr]['comment_tags'][($pos - 1)]; + if ($tokens[$lastTag]['content'] !== $tagName) { + $error = 'Tags must be grouped together in a doc comment'; + $phpcsFile->addError($error, $tag, 'TagsNotGrouped'); + } + + continue; + } + + $foundTags[$tagName] = true; + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php new file mode 100644 index 000000000..b78a6595e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/FixmeSniff.php @@ -0,0 +1,78 @@ + + * @author Sam Graham + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FixmeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array_diff(Tokens::$commentTokens, Tokens::$phpcsCommentTokens); + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $matches = []; + preg_match('/(?:\A|[^\p{L}]+)fixme([^\p{L}]+(.*)|\Z)/ui', $content, $matches); + if (empty($matches) === false) { + // Clear whitespace and some common characters not required at + // the end of a fixme message to make the error more informative. + $type = 'CommentFound'; + $fixmeMessage = trim($matches[1]); + $fixmeMessage = trim($fixmeMessage, '-:[](). '); + $error = 'Comment refers to a FIXME task'; + $data = [$fixmeMessage]; + if ($fixmeMessage !== '') { + $type = 'TaskFound'; + $error .= ' "%s"'; + } + + $phpcsFile->addError($error, $stackPtr, $type, $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php new file mode 100644 index 000000000..d24111cbd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Commenting/TodoSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class TodoSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array_diff(Tokens::$commentTokens, Tokens::$phpcsCommentTokens); + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $matches = []; + preg_match('/(?:\A|[^\p{L}]+)todo([^\p{L}]+(.*)|\Z)/ui', $content, $matches); + if (empty($matches) === false) { + // Clear whitespace and some common characters not required at + // the end of a to-do message to make the warning more informative. + $type = 'CommentFound'; + $todoMessage = trim($matches[1]); + $todoMessage = trim($todoMessage, '-:[](). '); + $error = 'Comment refers to a TODO task'; + $data = [$todoMessage]; + if ($todoMessage !== '') { + $type = 'TaskFound'; + $error .= ' "%s"'; + } + + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php new file mode 100644 index 000000000..666b1916e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php @@ -0,0 +1,185 @@ + + * @author Mark Scherer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowYodaConditionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$comparisonTokens; + unset($tokens[T_COALESCE]); + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $previousIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + $relevantTokens = [ + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_TRUE, + T_FALSE, + T_NULL, + T_LNUMBER, + T_DNUMBER, + T_CONSTANT_ENCAPSED_STRING, + ]; + + if (in_array($tokens[$previousIndex]['code'], $relevantTokens, true) === false) { + return; + } + + if ($tokens[$previousIndex]['code'] === T_CLOSE_SHORT_ARRAY) { + $previousIndex = $tokens[$previousIndex]['bracket_opener']; + if ($this->isArrayStatic($phpcsFile, $previousIndex) === false) { + return; + } + } + + $prevIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), null, true); + + if (in_array($tokens[$prevIndex]['code'], Tokens::$arithmeticTokens, true) === true) { + return; + } + + if ($tokens[$prevIndex]['code'] === T_STRING_CONCAT) { + return; + } + + // Is it a parenthesis. + if ($tokens[$previousIndex]['code'] === T_CLOSE_PARENTHESIS) { + $beforeOpeningParenthesisIndex = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokens[$previousIndex]['parenthesis_opener'] - 1), + null, + true + ); + + if ($beforeOpeningParenthesisIndex === false || $tokens[$beforeOpeningParenthesisIndex]['code'] !== T_ARRAY) { + if ($tokens[$beforeOpeningParenthesisIndex]['code'] === T_STRING) { + return; + } + + // If it is not an array check what is inside. + $found = $phpcsFile->findPrevious( + T_VARIABLE, + ($previousIndex - 1), + $tokens[$previousIndex]['parenthesis_opener'] + ); + + // If a variable exists, it is not Yoda. + if ($found !== false) { + return; + } + + // If there is nothing inside the parenthesis, it is not a Yoda condition. + $opener = $tokens[$previousIndex]['parenthesis_opener']; + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), ($opener + 1), true); + if ($prev === false) { + return; + } + } else if ($tokens[$beforeOpeningParenthesisIndex]['code'] === T_ARRAY + && $this->isArrayStatic($phpcsFile, $beforeOpeningParenthesisIndex) === false + ) { + return; + }//end if + }//end if + + $phpcsFile->addError( + 'Usage of Yoda conditions is not allowed; switch the expression order', + $stackPtr, + 'Found' + ); + + }//end process() + + + /** + * Determines if an array is a static definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $arrayToken The position of the array token. + * + * @return bool + */ + public function isArrayStatic(File $phpcsFile, $arrayToken) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$arrayToken]['code'] === T_OPEN_SHORT_ARRAY) { + $start = $arrayToken; + $end = $tokens[$arrayToken]['bracket_closer']; + } else if ($tokens[$arrayToken]['code'] === T_ARRAY) { + $start = $tokens[$arrayToken]['parenthesis_opener']; + $end = $tokens[$arrayToken]['parenthesis_closer']; + } else { + // Shouldn't be possible but may happen if external sniffs are using this method. + return true; // @codeCoverageIgnore + } + + $staticTokens = Tokens::$emptyTokens; + $staticTokens += Tokens::$textStringTokens; + $staticTokens += Tokens::$assignmentTokens; + $staticTokens += Tokens::$equalityTokens; + $staticTokens += Tokens::$comparisonTokens; + $staticTokens += Tokens::$arithmeticTokens; + $staticTokens += Tokens::$operators; + $staticTokens += Tokens::$booleanOperators; + $staticTokens += Tokens::$castTokens; + $staticTokens += Tokens::$bracketTokens; + $staticTokens += [ + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_COMMA => T_COMMA, + T_TRUE => T_TRUE, + T_FALSE => T_FALSE, + ]; + + for ($i = ($start + 1); $i < $end; $i++) { + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + if (isset($staticTokens[$tokens[$i]['code']]) === false) { + return false; + } + } + + return true; + + }//end isArrayStatic() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php new file mode 100644 index 000000000..ff1738328 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php @@ -0,0 +1,366 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InlineControlStructureSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSE, + T_ELSEIF, + T_FOREACH, + T_WHILE, + T_DO, + T_SWITCH, + T_FOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no'); + return; + } + + // Ignore the ELSE in ELSE IF. We'll process the IF part later. + if ($tokens[$stackPtr]['code'] === T_ELSE) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_IF) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_WHILE || $tokens[$stackPtr]['code'] === T_FOR) { + // This could be from a DO WHILE, which doesn't have an opening brace or a while/for without body. + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $afterParensCloser = $phpcsFile->findNext(Tokens::$emptyTokens, ($tokens[$stackPtr]['parenthesis_closer'] + 1), null, true); + if ($afterParensCloser === false) { + // Live coding. + return; + } + + if ($tokens[$afterParensCloser]['code'] === T_SEMICOLON) { + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'no'); + return; + } + } + }//end if + + if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false + && $tokens[$stackPtr]['code'] !== T_ELSE + ) { + if ($tokens[$stackPtr]['code'] !== T_DO) { + // Live coding or parse error. + return; + } + + $nextWhile = $phpcsFile->findNext(T_WHILE, ($stackPtr + 1)); + if ($nextWhile !== false + && isset($tokens[$nextWhile]['parenthesis_opener'], $tokens[$nextWhile]['parenthesis_closer']) === false + ) { + // Live coding or parse error. + return; + } + + unset($nextWhile); + } + + $start = $stackPtr; + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $start = $tokens[$stackPtr]['parenthesis_closer']; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($start + 1), null, true); + if ($nextNonEmpty === false) { + // Live coding or parse error. + return; + } + + if ($tokens[$nextNonEmpty]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$nextNonEmpty]['code'] === T_COLON + ) { + // T_CLOSE_CURLY_BRACKET missing, or alternative control structure with + // T_END... missing. Either live coding, parse error or end + // tag in short open tags and scan run with short_open_tag=Off. + // Bow out completely as any further detection will be unreliable + // and create incorrect fixes or cause fixer conflicts. + return $phpcsFile->numTokens; + } + + unset($nextNonEmpty, $start); + + // This is a control structure without an opening brace, + // so it is an inline statement. + if ($this->error === true) { + $fix = $phpcsFile->addFixableError('Inline control structures are not allowed', $stackPtr, 'NotAllowed'); + } else { + $fix = $phpcsFile->addFixableWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged'); + } + + $phpcsFile->recordMetric($stackPtr, 'Control structure defined inline', 'yes'); + + // Stop here if we are not fixing the error. + if ($fix !== true) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $closer = $tokens[$stackPtr]['parenthesis_closer']; + } else { + $closer = $stackPtr; + } + + if ($tokens[($closer + 1)]['code'] === T_WHITESPACE + || $tokens[($closer + 1)]['code'] === T_SEMICOLON + ) { + $phpcsFile->fixer->addContent($closer, ' {'); + } else { + $phpcsFile->fixer->addContent($closer, ' { '); + } + + $fixableScopeOpeners = $this->register(); + + $lastNonEmpty = $closer; + for ($end = ($closer + 1); $end < $phpcsFile->numTokens; $end++) { + if ($tokens[$end]['code'] === T_SEMICOLON) { + break; + } + + if ($tokens[$end]['code'] === T_CLOSE_TAG) { + $end = $lastNonEmpty; + break; + } + + if (in_array($tokens[$end]['code'], $fixableScopeOpeners, true) === true + && isset($tokens[$end]['scope_opener']) === false + ) { + // The best way to fix nested inline scopes is middle-out. + // So skip this one. It will be detected and fixed on a future loop. + $phpcsFile->fixer->rollbackChangeset(); + return; + } + + if (isset($tokens[$end]['scope_opener']) === true) { + $type = $tokens[$end]['code']; + $end = $tokens[$end]['scope_closer']; + if ($type === T_DO + || $type === T_IF || $type === T_ELSEIF + || $type === T_TRY || $type === T_CATCH || $type === T_FINALLY + ) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next === false) { + break; + } + + $nextType = $tokens[$next]['code']; + + // Let additional conditions loop and find their ending. + if (($type === T_IF + || $type === T_ELSEIF) + && ($nextType === T_ELSEIF + || $nextType === T_ELSE) + ) { + continue; + } + + // Account for TRY... CATCH/FINALLY statements. + if (($type === T_TRY + || $type === T_CATCH + || $type === T_FINALLY) + && ($nextType === T_CATCH + || $nextType === T_FINALLY) + ) { + continue; + } + + // Account for DO... WHILE conditions. + if ($type === T_DO && $nextType === T_WHILE) { + $end = $phpcsFile->findNext(T_SEMICOLON, ($next + 1)); + } + } else if ($type === T_CLOSURE) { + // There should be a semicolon after the closing brace. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_SEMICOLON) { + $end = $next; + } + }//end if + + if ($tokens[$end]['code'] !== T_END_HEREDOC + && $tokens[$end]['code'] !== T_END_NOWDOC + ) { + break; + } + }//end if + + if (isset($tokens[$end]['parenthesis_closer']) === true) { + $end = $tokens[$end]['parenthesis_closer']; + $lastNonEmpty = $end; + continue; + } + + if ($tokens[$end]['code'] !== T_WHITESPACE) { + $lastNonEmpty = $end; + } + }//end for + + if ($end === $phpcsFile->numTokens) { + $end = $lastNonEmpty; + } + + $nextContent = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Looks for completely empty statements. + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), ($end + 1), true); + } else { + $next = ($end + 1); + $endLine = $end; + } + + if ($next !== $end) { + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] + ) { + break; + } + } + + if (isset(Tokens::$commentTokens[$tokens[$endLine]['code']]) === false + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || isset(Tokens::$commentTokens[$tokens[($endLine - 1)]['code']]) === false) + ) { + $endLine = $end; + } + } + + if ($endLine !== $end) { + $endToken = $endLine; + $addedContent = ''; + } else { + $endToken = $end; + $addedContent = $phpcsFile->eolChar; + + if ($tokens[$end]['code'] !== T_SEMICOLON + && $tokens[$end]['code'] !== T_CLOSE_CURLY_BRACKET + ) { + $phpcsFile->fixer->addContent($end, '; '); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($endToken + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_ELSE + || $tokens[$next]['code'] === T_ELSEIF) + ) { + $phpcsFile->fixer->addContentBefore($next, '} '); + } else { + $indent = ''; + for ($first = $stackPtr; $first > 0; $first--) { + if ($tokens[$first]['column'] === 1) { + break; + } + } + + if ($tokens[$first]['code'] === T_WHITESPACE) { + $indent = $tokens[$first]['content']; + } else if ($tokens[$first]['code'] === T_INLINE_HTML + || $tokens[$first]['code'] === T_OPEN_TAG + ) { + $addedContent = ''; + } + + $addedContent .= $indent.'}'; + if ($next !== false && $tokens[$endToken]['code'] === T_COMMENT) { + $addedContent .= $phpcsFile->eolChar; + } + + $phpcsFile->fixer->addContent($endToken, $addedContent); + }//end if + } else { + if ($nextContent === false || $tokens[$nextContent]['line'] !== $tokens[$end]['line']) { + // Account for a comment on the end of the line. + for ($endLine = $end; $endLine < $phpcsFile->numTokens; $endLine++) { + if (isset($tokens[($endLine + 1)]) === false + || $tokens[$endLine]['line'] !== $tokens[($endLine + 1)]['line'] + ) { + break; + } + } + + if ($tokens[$endLine]['code'] !== T_COMMENT + && ($tokens[$endLine]['code'] !== T_WHITESPACE + || $tokens[($endLine - 1)]['code'] !== T_COMMENT) + ) { + $endLine = $end; + } + } + + if ($endLine !== $end) { + $phpcsFile->fixer->replaceToken($end, ''); + $phpcsFile->fixer->addNewlineBefore($endLine); + $phpcsFile->fixer->addContent($endLine, '}'); + } else { + $phpcsFile->fixer->replaceToken($end, '}'); + } + }//end if + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php new file mode 100644 index 000000000..6df4c1ffb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/CSSLintSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2013-2014 Roman Levishchenko + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class CSSLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $csslintPath = Config::getExecutablePath('csslint'); + if ($csslintPath === null) { + return $phpcsFile->numTokens; + } + + $fileName = $phpcsFile->getFilename(); + + $cmd = Common::escapeshellcmd($csslintPath).' '.escapeshellarg($fileName).' 2>&1'; + exec($cmd, $output, $retval); + + if (is_array($output) === false) { + return $phpcsFile->numTokens; + } + + $count = count($output); + + for ($i = 0; $i < $count; $i++) { + $matches = []; + $numMatches = preg_match( + '/(error|warning) at line (\d+)/', + $output[$i], + $matches + ); + + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches[2]; + $message = 'csslint says: '.$output[($i + 1)]; + // First line is message with error line and error code. + // Second is error message. + // Third is wrong line in file. + // Fourth is empty line. + $i += 4; + + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + }//end for + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php new file mode 100644 index 000000000..637bf41ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php @@ -0,0 +1,119 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ClosureLinterSniff implements Sniff +{ + + /** + * A list of error codes that should show errors. + * + * All other error codes will show warnings. + * + * @var array + */ + public $errorCodes = []; + + /** + * A list of error codes to ignore. + * + * @var array + */ + public $ignoreCodes = []; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jslint.js could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $lintPath = Config::getExecutablePath('gjslint'); + if ($lintPath === null) { + return $phpcsFile->numTokens; + } + + $fileName = $phpcsFile->getFilename(); + + $lintPath = Common::escapeshellcmd($lintPath); + $cmd = $lintPath.' --nosummary --notime --unix_mode '.escapeshellarg($fileName); + exec($cmd, $output, $retval); + + if (is_array($output) === false) { + return $phpcsFile->numTokens; + } + + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match('/^(.*):([0-9]+):\(.*?([0-9]+)\)(.*)$/', $finding, $matches); + if ($numMatches === 0) { + continue; + } + + // Skip error codes we are ignoring. + $code = $matches[3]; + if (in_array($code, $this->ignoreCodes) === true) { + continue; + } + + $line = (int) $matches[2]; + $error = trim($matches[4]); + + $message = 'gjslint says: (%s) %s'; + $data = [ + $code, + $error, + ]; + if (in_array($code, $this->errorCodes) === true) { + $phpcsFile->addErrorOnLine($message, $line, 'ExternalToolError', $data); + } else { + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool', $data); + } + }//end foreach + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php new file mode 100644 index 000000000..1c6b0e3f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/ESLintSniff.php @@ -0,0 +1,115 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ESLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + /** + * ESLint configuration file path. + * + * @var string|null Path to eslintrc. Null to autodetect. + */ + public $configFile = null; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jshint.js could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $eslintPath = Config::getExecutablePath('eslint'); + if ($eslintPath === null) { + return $phpcsFile->numTokens; + } + + $filename = $phpcsFile->getFilename(); + + $configFile = $this->configFile; + if (empty($configFile) === true) { + // Attempt to autodetect. + $candidates = glob('.eslintrc{.js,.yaml,.yml,.json}', GLOB_BRACE); + if (empty($candidates) === false) { + $configFile = $candidates[0]; + } + } + + $eslintOptions = ['--format json']; + if (empty($configFile) === false) { + $eslintOptions[] = '--config '.escapeshellarg($configFile); + } + + $cmd = Common::escapeshellcmd(escapeshellarg($eslintPath).' '.implode(' ', $eslintOptions).' '.escapeshellarg($filename)); + + // Execute! + exec($cmd, $stdout, $code); + + if ($code <= 0) { + // No errors, continue. + return $phpcsFile->numTokens; + } + + $data = json_decode(implode("\n", $stdout)); + if (json_last_error() !== JSON_ERROR_NONE) { + // Ignore any errors. + return $phpcsFile->numTokens; + } + + // Data is a list of files, but we only pass a single one. + $messages = $data[0]->messages; + foreach ($messages as $error) { + $message = 'eslint says: '.$error->message; + if (empty($error->fatal) === false || $error->severity === 2) { + $phpcsFile->addErrorOnLine($message, $error->line, 'ExternalTool'); + } else { + $phpcsFile->addWarningOnLine($message, $error->line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php new file mode 100644 index 000000000..ae8264ebb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Debug/JSHintSniff.php @@ -0,0 +1,97 @@ + + * @author Alexander Wei§ + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JSHintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jshint.js could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $rhinoPath = Config::getExecutablePath('rhino'); + $jshintPath = Config::getExecutablePath('jshint'); + if ($jshintPath === null) { + return $phpcsFile->numTokens; + } + + $fileName = $phpcsFile->getFilename(); + $jshintPath = Common::escapeshellcmd($jshintPath); + + if ($rhinoPath !== null) { + $rhinoPath = Common::escapeshellcmd($rhinoPath); + $cmd = "$rhinoPath \"$jshintPath\" ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + $regex = '`^(?P.+)\(.+:(?P[0-9]+).*:[0-9]+\)$`'; + } else { + $cmd = "$jshintPath ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + $regex = '`^(.+?): line (?P[0-9]+), col [0-9]+, (?P.+)$`'; + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match($regex, $finding, $matches); + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches['line']; + $message = 'jshint says: '.trim($matches['error']); + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php new file mode 100644 index 000000000..5a1fde6f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php @@ -0,0 +1,82 @@ + + * @author Greg Sherwood + * @copyright 2010-2014 mediaSELF Sp. z o.o. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ByteOrderMarkSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_HTML]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // The BOM will be the very first token in the file. + if ($stackPtr !== 0) { + return $phpcsFile->numTokens; + } + + $tokens = $phpcsFile->getTokens(); + + foreach ($this->bomDefinitions as $bomName => $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[$stackPtr]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex) { + $errorData = [$bomName]; + $error = 'File contains %s byte order mark, which may corrupt your application'; + $phpcsFile->addError($error, $stackPtr, 'Found', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'yes'); + return $phpcsFile->numTokens; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Using byte order mark', 'no'); + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php new file mode 100644 index 000000000..71bcabbb7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php @@ -0,0 +1,84 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNewlineSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $stackPtr = ($phpcsFile->numTokens - 1); + + if ($tokens[$stackPtr]['content'] === '') { + $stackPtr--; + } + + $eolCharLen = strlen($phpcsFile->eolChar); + $lastChars = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1)); + if ($lastChars !== $phpcsFile->eolChar) { + $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'no'); + + $error = 'File must end with a newline character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotFound'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($stackPtr); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Newline at EOF', 'yes'); + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php new file mode 100644 index 000000000..3f7660756 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNoNewlineSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $stackPtr = ($phpcsFile->numTokens - 1); + + if ($tokens[$stackPtr]['content'] === '') { + --$stackPtr; + } + + $eolCharLen = strlen($phpcsFile->eolChar); + $lastChars = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1)); + if ($lastChars === $phpcsFile->eolChar) { + $error = 'File must not end with a newline character'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = $stackPtr; $i > 0; $i--) { + $newContent = rtrim($tokens[$i]['content'], $phpcsFile->eolChar); + $phpcsFile->fixer->replaceToken($i, $newContent); + + if ($newContent !== '') { + break; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php new file mode 100644 index 000000000..8f597dfdf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/ExecutableFileSniff.php @@ -0,0 +1,62 @@ + + * @copyright 2019 Matthew Peveler + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ExecutableFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $filename = $phpcsFile->getFilename(); + + if ($filename !== 'STDIN') { + $perms = fileperms($phpcsFile->getFilename()); + if (($perms & 0x0040) !== 0 || ($perms & 0x0008) !== 0 || ($perms & 0x0001) !== 0) { + $error = 'A PHP file should not be executable; found file permissions set to %s'; + $data = [substr(sprintf('%o', $perms), -4)]; + $phpcsFile->addError($error, 0, 'Executable', $data); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php new file mode 100644 index 000000000..d90b89301 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineHTMLSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_HTML]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int|void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + foreach ($this->bomDefinitions as $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[0]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex && strlen($tokens[0]['content']) === $bomByteLength) { + return; + } + } + + // Ignore shebang lines. + $tokens = $phpcsFile->getTokens(); + if (substr($tokens[$stackPtr]['content'], 0, 2) === '#!') { + return; + } + + $error = 'PHP files must only contain PHP code'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php new file mode 100644 index 000000000..1814b5555 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineEndingsSniff.php @@ -0,0 +1,148 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LineEndingsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + /** + * The valid EOL character. + * + * @var string + */ + public $eolChar = '\n'; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $found = $phpcsFile->eolChar; + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\r', $found); + + $phpcsFile->recordMetric($stackPtr, 'EOL char', $found); + + if ($found === $this->eolChar) { + // Ignore the rest of the file. + return $phpcsFile->numTokens; + } + + // Check for single line files without an EOL. This is a very special + // case and the EOL char is set to \n when this happens. + if ($found === '\n') { + $tokens = $phpcsFile->getTokens(); + $lastToken = ($phpcsFile->numTokens - 1); + if ($tokens[$lastToken]['line'] === 1 + && $tokens[$lastToken]['content'] !== "\n" + ) { + return $phpcsFile->numTokens; + } + } + + $error = 'End of line character is invalid; expected "%s" but found "%s"'; + $expected = $this->eolChar; + $expected = str_replace("\n", '\n', $expected); + $expected = str_replace("\r", '\r', $expected); + $data = [ + $expected, + $found, + ]; + + // Errors are always reported on line 1, no matter where the first PHP tag is. + $fix = $phpcsFile->addFixableError($error, 0, 'InvalidEOLChar', $data); + + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + switch ($this->eolChar) { + case '\n': + $eolChar = "\n"; + break; + case '\r': + $eolChar = "\r"; + break; + case '\r\n': + $eolChar = "\r\n"; + break; + default: + $eolChar = $this->eolChar; + break; + } + + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if (isset($tokens[($i + 1)]) === true + && $tokens[($i + 1)]['line'] <= $tokens[$i]['line'] + ) { + continue; + } + + // Token is the last on a line. + if (isset($tokens[$i]['orig_content']) === true) { + $tokenContent = $tokens[$i]['orig_content']; + } else { + $tokenContent = $tokens[$i]['content']; + } + + if ($tokenContent === '') { + // Special case for JS/CSS close tag. + continue; + } + + $newContent = rtrim($tokenContent, "\r\n"); + $newContent .= $eolChar; + if ($tokenContent !== $newContent) { + $phpcsFile->fixer->replaceToken($i, $newContent); + } + }//end for + }//end if + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php new file mode 100644 index 000000000..a65baf76b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LineLengthSniff.php @@ -0,0 +1,201 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LineLengthSniff implements Sniff +{ + + /** + * The limit that the length of a line should not exceed. + * + * @var integer + */ + public $lineLimit = 80; + + /** + * The limit that the length of a line must not exceed. + * + * Set to zero (0) to disable. + * + * @var integer + */ + public $absoluteLineLimit = 100; + + /** + * Whether or not to ignore trailing comments. + * + * This has the effect of also ignoring all lines + * that only contain comments. + * + * @var boolean + */ + public $ignoreComments = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + for ($i = 1; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['column'] === 1) { + $this->checkLineLength($phpcsFile, $tokens, $i); + } + } + + $this->checkLineLength($phpcsFile, $tokens, $i); + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + + /** + * Checks if a line is too long. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tokens The token stack. + * @param int $stackPtr The first token on the next line. + * + * @return void + */ + protected function checkLineLength($phpcsFile, $tokens, $stackPtr) + { + // The passed token is the first on the line. + $stackPtr--; + + if ($tokens[$stackPtr]['column'] === 1 + && $tokens[$stackPtr]['length'] === 0 + ) { + // Blank line. + return; + } + + if ($tokens[$stackPtr]['column'] !== 1 + && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar + ) { + $stackPtr--; + } + + $onlyComment = false; + if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) { + $prevNonWhiteSpace = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['line'] !== $tokens[$prevNonWhiteSpace]['line']) { + $onlyComment = true; + } + } + + if ($onlyComment === true + && isset(Tokens::$phpcsCommentTokens[$tokens[$stackPtr]['code']]) === true + ) { + // Ignore PHPCS annotation comments that are on a line by themselves. + return; + } + + $lineLength = ($tokens[$stackPtr]['column'] + $tokens[$stackPtr]['length'] - 1); + + if ($this->ignoreComments === true + && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true + ) { + // Trailing comments are being ignored in line length calculations. + if ($onlyComment === true) { + // The comment is the only thing on the line, so no need to check length. + return; + } + + $lineLength -= $tokens[$stackPtr]['length']; + } + + // Record metrics for common line length groupings. + if ($lineLength <= 80) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '80 or less'); + } else if ($lineLength <= 120) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '81-120'); + } else if ($lineLength <= 150) { + $phpcsFile->recordMetric($stackPtr, 'Line length', '121-150'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Line length', '151 or more'); + } + + if ($onlyComment === true) { + // If this is a long comment, check if it can be broken up onto multiple lines. + // Some comments contain unbreakable strings like URLs and so it makes sense + // to ignore the line length in these cases if the URL would be longer than the max + // line length once you indent it to the correct level. + if ($lineLength > $this->lineLimit) { + $oldLength = strlen($tokens[$stackPtr]['content']); + $newLength = strlen(ltrim($tokens[$stackPtr]['content'], "/#\t ")); + $indent = (($tokens[$stackPtr]['column'] - 1) + ($oldLength - $newLength)); + + $nonBreakingLength = $tokens[$stackPtr]['length']; + + $space = strrpos($tokens[$stackPtr]['content'], ' '); + if ($space !== false) { + $nonBreakingLength -= ($space + 1); + } + + if (($nonBreakingLength + $indent) > $this->lineLimit) { + return; + } + } + }//end if + + if ($this->absoluteLineLimit > 0 + && $lineLength > $this->absoluteLineLimit + ) { + $data = [ + $this->absoluteLineLimit, + $lineLength, + ]; + + $error = 'Line exceeds maximum limit of %s characters; contains %s characters'; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($lineLength > $this->lineLimit) { + $data = [ + $this->lineLimit, + $lineLength, + ]; + + $warning = 'Line exceeds %s characters; contains %s characters'; + $phpcsFile->addWarning($warning, $stackPtr, 'TooLong', $data); + } + + }//end checkLineLength() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php new file mode 100644 index 000000000..1773cb8a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php @@ -0,0 +1,70 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercasedFilenameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $filename = $phpcsFile->getFilename(); + if ($filename === 'STDIN') { + return $phpcsFile->numTokens; + } + + $filename = basename($filename); + $lowercaseFilename = strtolower($filename); + if ($filename !== $lowercaseFilename) { + $data = [ + $filename, + $lowercaseFilename, + ]; + $error = 'Filename "%s" doesn\'t match the expected filename "%s"'; + $phpcsFile->addError($error, $stackPtr, 'NotFound', $data); + $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Lowercase filename', 'yes'); + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php new file mode 100644 index 000000000..e328e7443 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneClassPerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one class is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php new file mode 100644 index 000000000..34211f2f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneInterfacePerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INTERFACE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextInterface = $phpcsFile->findNext($this->register(), $start); + if ($nextInterface !== false) { + $error = 'Only one interface is allowed in a file'; + $phpcsFile->addError($error, $nextInterface, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php new file mode 100644 index 000000000..459c5d1aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneObjectStructurePerFileSniff.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneObjectStructurePerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one object structure is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php new file mode 100644 index 000000000..309383fcd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Files/OneTraitPerFileSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2010-2014 Alexander Obuhovich + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OneTraitPerFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_TRAIT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $start = ($tokens[$stackPtr]['scope_closer'] + 1); + } + + $nextClass = $phpcsFile->findNext($this->register(), $start); + if ($nextClass !== false) { + $error = 'Only one trait is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleFound'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php new file mode 100644 index 000000000..750fdabc5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowMultipleStatementsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SEMICOLON]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $fixable = true; + $prev = $stackPtr; + + do { + $prev = $phpcsFile->findPrevious([T_SEMICOLON, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_PHPCS_IGNORE], ($prev - 1)); + if ($prev === false + || $tokens[$prev]['code'] === T_OPEN_TAG + || $tokens[$prev]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no'); + return; + } + + if ($tokens[$prev]['code'] === T_PHPCS_IGNORE) { + $fixable = false; + } + } while ($tokens[$prev]['code'] === T_PHPCS_IGNORE); + + // Ignore multiple statements in a FOR condition. + foreach ([$stackPtr, $prev] as $checkToken) { + if (isset($tokens[$checkToken]['nested_parenthesis']) === true) { + foreach ($tokens[$checkToken]['nested_parenthesis'] as $bracket) { + if (isset($tokens[$bracket]['parenthesis_owner']) === false) { + // Probably a closure sitting inside a function call. + continue; + } + + $owner = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FOR) { + return; + } + } + } + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'yes'); + + $error = 'Each PHP statement must be on a line by itself'; + $code = 'SameLine'; + if ($fixable === false) { + $phpcsFile->addError($error, $stackPtr, $code); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $code); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($prev); + if ($tokens[($prev + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($prev + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no'); + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php new file mode 100644 index 000000000..8916659a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php @@ -0,0 +1,426 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultipleStatementAlignmentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = false; + + /** + * The maximum amount of padding before the alignment is ignored. + * + * If the amount of padding required to align this assignment with the + * surrounding assignments exceeds this number, the assignment will be + * ignored and no errors or warnings will be thrown. + * + * @var integer + */ + public $maxPadding = 1000; + + /** + * Controls which side of the assignment token is used for alignment. + * + * @var boolean + */ + public $alignAtEnd = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$assignmentTokens; + unset($tokens[T_DOUBLE_ARROW]); + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $lastAssign = $this->checkAlignment($phpcsFile, $stackPtr); + return ($lastAssign + 1); + + }//end process() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $end The token where checking should end. + * If NULL, the entire file will be checked. + * + * @return int + */ + public function checkAlignment($phpcsFile, $stackPtr, $end=null) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore assignments used in a condition, like an IF or FOR or closure param defaults. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + // If the parenthesis is on the same line as the assignment, + // then it should be ignored as it is specifically being grouped. + $parens = $tokens[$stackPtr]['nested_parenthesis']; + $lastParen = array_pop($parens); + if ($tokens[$lastParen]['line'] === $tokens[$stackPtr]['line']) { + return $stackPtr; + } + + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $start => $end) { + if (isset($tokens[$start]['parenthesis_owner']) === true) { + return $stackPtr; + } + } + } + + $assignments = []; + $prevAssign = null; + $lastLine = $tokens[$stackPtr]['line']; + $maxPadding = null; + $stopped = null; + $lastCode = $stackPtr; + $lastSemi = null; + $arrayEnd = null; + + if ($end === null) { + $end = $phpcsFile->numTokens; + } + + $find = Tokens::$assignmentTokens; + unset($find[T_DOUBLE_ARROW]); + + $scopes = Tokens::$scopeOpeners; + unset($scopes[T_CLOSURE]); + unset($scopes[T_ANON_CLASS]); + unset($scopes[T_OBJECT]); + + for ($assign = $stackPtr; $assign < $end; $assign++) { + if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // Statement is in a different context, so the block is over. + break; + } + + if (isset($tokens[$assign]['scope_opener']) === true + && $tokens[$assign]['level'] === $tokens[$stackPtr]['level'] + ) { + if (isset($scopes[$tokens[$assign]['code']]) === true) { + // This type of scope indicates that the assignment block is over. + break; + } + + // Skip over the scope block because it is seen as part of the assignment block, + // but also process any assignment blocks that are inside as well. + $nextAssign = $phpcsFile->findNext($find, ($assign + 1), ($tokens[$assign]['scope_closer'] - 1)); + if ($nextAssign !== false) { + $assign = $this->checkAlignment($phpcsFile, $nextAssign); + } else { + $assign = $tokens[$assign]['scope_closer']; + } + + $lastCode = $assign; + continue; + } + + if ($assign === $arrayEnd) { + $arrayEnd = null; + } + + if (isset($find[$tokens[$assign]['code']]) === false) { + // A blank line indicates that the assignment block has ended. + if (isset(Tokens::$emptyTokens[$tokens[$assign]['code']]) === false + && ($tokens[$assign]['line'] - $tokens[$lastCode]['line']) > 1 + && $tokens[$assign]['level'] === $tokens[$stackPtr]['level'] + && $arrayEnd === null + ) { + break; + } + + if ($tokens[$assign]['code'] === T_CLOSE_TAG) { + // Breaking out of PHP ends the assignment block. + break; + } + + if ($tokens[$assign]['code'] === T_OPEN_SHORT_ARRAY + && isset($tokens[$assign]['bracket_closer']) === true + ) { + $arrayEnd = $tokens[$assign]['bracket_closer']; + } + + if ($tokens[$assign]['code'] === T_ARRAY + && isset($tokens[$assign]['parenthesis_opener']) === true + && isset($tokens[$tokens[$assign]['parenthesis_opener']]['parenthesis_closer']) === true + ) { + $arrayEnd = $tokens[$tokens[$assign]['parenthesis_opener']]['parenthesis_closer']; + } + + if (isset(Tokens::$emptyTokens[$tokens[$assign]['code']]) === false) { + $lastCode = $assign; + + if ($tokens[$assign]['code'] === T_SEMICOLON) { + if ($tokens[$assign]['conditions'] === $tokens[$stackPtr]['conditions']) { + if ($lastSemi !== null && $prevAssign !== null && $lastSemi > $prevAssign) { + // This statement did not have an assignment operator in it. + break; + } else { + $lastSemi = $assign; + } + } else if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // Statement is in a different context, so the block is over. + break; + } + } + }//end if + + continue; + } else if ($assign !== $stackPtr && $tokens[$assign]['line'] === $lastLine) { + // Skip multiple assignments on the same line. We only need to + // try and align the first assignment. + continue; + }//end if + + if ($assign !== $stackPtr) { + if ($tokens[$assign]['level'] > $tokens[$stackPtr]['level']) { + // Has to be nested inside the same conditions as the first assignment. + // We've gone one level down, so process this new block. + $assign = $this->checkAlignment($phpcsFile, $assign); + $lastCode = $assign; + continue; + } else if ($tokens[$assign]['level'] < $tokens[$stackPtr]['level']) { + // We've gone one level up, so the block we are processing is done. + break; + } else if ($arrayEnd !== null) { + // Assignments inside arrays are not part of + // the original block, so process this new block. + $assign = ($this->checkAlignment($phpcsFile, $assign, $arrayEnd) - 1); + $arrayEnd = null; + $lastCode = $assign; + continue; + } + + // Make sure it is not assigned inside a condition (eg. IF, FOR). + if (isset($tokens[$assign]['nested_parenthesis']) === true) { + // If the parenthesis is on the same line as the assignment, + // then it should be ignored as it is specifically being grouped. + $parens = $tokens[$assign]['nested_parenthesis']; + $lastParen = array_pop($parens); + if ($tokens[$lastParen]['line'] === $tokens[$assign]['line']) { + break; + } + + foreach ($tokens[$assign]['nested_parenthesis'] as $start => $end) { + if (isset($tokens[$start]['parenthesis_owner']) === true) { + break(2); + } + } + } + }//end if + + $var = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($assign - 1), + null, + true + ); + + // Make sure we wouldn't break our max padding length if we + // aligned with this statement, or they wouldn't break the max + // padding length if they aligned with us. + $varEnd = $tokens[($var + 1)]['column']; + $assignLen = $tokens[$assign]['length']; + if ($this->alignAtEnd !== true) { + $assignLen = 1; + } + + if ($assign !== $stackPtr) { + if ($prevAssign === null) { + // Processing an inner block but no assignments found. + break; + } + + if (($varEnd + 1) > $assignments[$prevAssign]['assign_col']) { + $padding = 1; + $assignColumn = ($varEnd + 1); + } else { + $padding = ($assignments[$prevAssign]['assign_col'] - $varEnd + $assignments[$prevAssign]['assign_len'] - $assignLen); + if ($padding <= 0) { + $padding = 1; + } + + if ($padding > $this->maxPadding) { + $stopped = $assign; + break; + } + + $assignColumn = ($varEnd + $padding); + }//end if + + if (($assignColumn + $assignLen) > ($assignments[$maxPadding]['assign_col'] + $assignments[$maxPadding]['assign_len'])) { + $newPadding = ($varEnd - $assignments[$maxPadding]['var_end'] + $assignLen - $assignments[$maxPadding]['assign_len'] + 1); + if ($newPadding > $this->maxPadding) { + $stopped = $assign; + break; + } else { + // New alignment settings for previous assignments. + foreach ($assignments as $i => $data) { + if ($i === $assign) { + break; + } + + $newPadding = ($varEnd - $data['var_end'] + $assignLen - $data['assign_len'] + 1); + $assignments[$i]['expected'] = $newPadding; + $assignments[$i]['assign_col'] = ($data['var_end'] + $newPadding); + } + + $padding = 1; + $assignColumn = ($varEnd + 1); + } + } else if ($padding > $assignments[$maxPadding]['expected']) { + $maxPadding = $assign; + }//end if + } else { + $padding = 1; + $assignColumn = ($varEnd + 1); + $maxPadding = $assign; + }//end if + + $found = 0; + if ($tokens[($var + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($var + 1)]['length']; + if ($found === 0) { + // This means a newline was found. + $found = 1; + } + } + + $assignments[$assign] = [ + 'var_end' => $varEnd, + 'assign_len' => $assignLen, + 'assign_col' => $assignColumn, + 'expected' => $padding, + 'found' => $found, + ]; + + $lastLine = $tokens[$assign]['line']; + $prevAssign = $assign; + }//end for + + if (empty($assignments) === true) { + return $stackPtr; + } + + $numAssignments = count($assignments); + + $errorGenerated = false; + foreach ($assignments as $assignment => $data) { + if ($data['found'] === $data['expected']) { + continue; + } + + $expectedText = $data['expected'].' space'; + if ($data['expected'] !== 1) { + $expectedText .= 's'; + } + + if ($data['found'] === null) { + $foundText = 'a new line'; + } else { + $foundText = $data['found'].' space'; + if ($data['found'] !== 1) { + $foundText .= 's'; + } + } + + if ($numAssignments === 1) { + $type = 'Incorrect'; + $error = 'Equals sign not aligned correctly; expected %s but found %s'; + } else { + $type = 'NotSame'; + $error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s'; + } + + $errorData = [ + $expectedText, + $foundText, + ]; + + if ($this->error === true) { + $fix = $phpcsFile->addFixableError($error, $assignment, $type, $errorData); + } else { + $fix = $phpcsFile->addFixableWarning($error, $assignment, $type.'Warning', $errorData); + } + + $errorGenerated = true; + + if ($fix === true && $data['found'] !== null) { + $newContent = str_repeat(' ', $data['expected']); + if ($data['found'] === 0) { + $phpcsFile->fixer->addContentBefore($assignment, $newContent); + } else { + $phpcsFile->fixer->replaceToken(($assignment - 1), $newContent); + } + } + }//end foreach + + if ($numAssignments > 1) { + if ($errorGenerated === true) { + $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Adjacent assignments aligned', 'yes'); + } + } + + if ($stopped !== null) { + return $this->checkAlignment($phpcsFile, $stopped); + } else { + return $assign; + } + + }//end checkAlignment() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php new file mode 100644 index 000000000..f7644df03 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.4.0 Use the Generic.Formatting.SpaceAfterCast sniff with + * the $spacing property set to 0 instead. + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NoSpaceAfterCastSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + return; + } + + $error = 'A cast statement must not be followed by a space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFound'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php new file mode 100644 index 000000000..d831ea7d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php @@ -0,0 +1,161 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceAfterCastSniff implements Sniff +{ + + /** + * The number of spaces desired after a cast token. + * + * @var integer + */ + public $spacing = 1; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $this->spacing = (int) $this->spacing; + $pluralizeSpace = 's'; + if ($this->spacing === 1) { + $pluralizeSpace = ''; + } + + if ($tokens[$stackPtr]['code'] === T_BINARY_CAST + && $tokens[$stackPtr]['content'] === 'b' + ) { + // You can't replace a space after this type of binary casting. + return; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($this->ignoreNewlines === true + && $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line'] + ) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 'newline'); + return; + } + + if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0); + return; + } + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== $nextNonWhitespace) { + $error = 'Expected %s space%s after cast statement; comment found'; + $data = [ + $this->spacing, + $pluralizeSpace, + ]; + $phpcsFile->addError($error, $stackPtr, 'CommentFound', $data); + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $tokens[($stackPtr + 1)]['length']); + } else { + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', 0); + } + + return; + } + + $found = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $found = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after cast statement', $found); + + if ($found === $this->spacing) { + return; + } + + $error = 'Expected %s space%s after cast statement; %s found'; + $data = [ + $this->spacing, + $pluralizeSpace, + $found, + ]; + + $errorCode = 'TooMuchSpace'; + if ($this->spacing !== 0) { + if ($found === 0) { + $errorCode = 'NoSpace'; + } else if ($found !== 'newline' && $found < $this->spacing) { + $errorCode = 'TooLittleSpace'; + } + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $start = ($stackPtr + 1); + + if ($this->spacing > 0) { + $phpcsFile->fixer->replaceToken($start, $padding); + ++$start; + } + + for ($i = $start; $i < $nextNonWhitespace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php new file mode 100644 index 000000000..a1a6d0936 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceAfterNotSniff.php @@ -0,0 +1,143 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceAfterNotSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces desired after the NOT operator. + * + * @var integer + */ + public $spacing = 1; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_BOOLEAN_NOT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $this->spacing = (int) $this->spacing; + $pluralizeSpace = 's'; + if ($this->spacing === 1) { + $pluralizeSpace = ''; + } + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($this->ignoreNewlines === true + && $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line'] + ) { + return; + } + + if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) { + return; + } + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonEmpty !== $nextNonWhitespace) { + $error = 'Expected %s space%s after NOT operator; comment found'; + $data = [ + $this->spacing, + $pluralizeSpace, + ]; + $phpcsFile->addError($error, $stackPtr, 'CommentFound', $data); + return; + } + + $found = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $found = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + } + + if ($found === $this->spacing) { + return; + } + + $error = 'Expected %s space%s after NOT operator; %s found'; + $data = [ + $this->spacing, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $start = ($stackPtr + 1); + + if ($this->spacing > 0) { + $phpcsFile->fixer->replaceToken($start, $padding); + ++$start; + } + + for ($i = $start; $i < $nextNonWhitespace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php new file mode 100644 index 000000000..96082e3fe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Formatting/SpaceBeforeCastSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SpaceBeforeCastSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['column'] === 1) { + return; + } + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'A cast statement must be preceded by a single space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpace'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before cast statement', 0); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before cast statement', $tokens[($stackPtr - 1)]['length']); + + if ($tokens[($stackPtr - 1)]['column'] !== 1 && $tokens[($stackPtr - 1)]['length'] !== 1) { + $error = 'A cast statement must be preceded by a single space'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpace'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php new file mode 100644 index 000000000..76c4a6306 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2009-2014 Florian Grandel + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CallTimePassByReferenceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_VARIABLE, + T_ANON_CLASS, + T_PARENT, + T_SELF, + T_STATIC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $findTokens = Tokens::$emptyTokens; + $findTokens[] = T_BITWISE_AND; + + $prev = $phpcsFile->findPrevious($findTokens, ($stackPtr - 1), null, true); + + // Skip tokens that are the names of functions + // within their definitions. For example: function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $prevCode = $tokens[$prev]['code']; + if ($prevCode === T_FUNCTION) { + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it cant really be a *call*. + $functionName = $stackPtr; + $openBracket = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($functionName + 1), + null, + true + ); + + if ($openBracket === false || $tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + return; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $nextSeparator = $openBracket; + $find = [ + T_VARIABLE, + T_OPEN_SHORT_ARRAY, + ]; + + while (($nextSeparator = $phpcsFile->findNext($find, ($nextSeparator + 1), $closeBracket)) !== false) { + if ($tokens[$nextSeparator]['code'] === T_OPEN_SHORT_ARRAY) { + $nextSeparator = $tokens[$nextSeparator]['bracket_closer']; + continue; + } + + // Make sure the variable belongs directly to this function call + // and is not inside a nested function call or array. + $brackets = $tokens[$nextSeparator]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if ($lastBracket !== $closeBracket) { + continue; + } + + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($nextSeparator - 1), + null, + true + ); + + if ($tokens[$tokenBefore]['code'] === T_BITWISE_AND) { + if ($phpcsFile->isReference($tokenBefore) === false) { + continue; + } + + // We also want to ignore references used in assignment + // operations passed as function arguments, but isReference() + // sees them as valid references (which they are). + $tokenBefore = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($tokenBefore - 1), + null, + true + ); + + if (isset(Tokens::$assignmentTokens[$tokens[$tokenBefore]['code']]) === true) { + continue; + } + + // T_BITWISE_AND represents a pass-by-reference. + $error = 'Call-time pass-by-reference calls are prohibited'; + $phpcsFile->addError($error, $tokenBefore, 'NotAllowed'); + }//end if + }//end while + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php new file mode 100644 index 000000000..bf93c5533 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php @@ -0,0 +1,197 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallArgumentSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return[ + T_STRING, + T_ISSET, + T_UNSET, + T_SELF, + T_STATIC, + T_PARENT, + T_VARIABLE, + T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip tokens that are the names of functions or classes + // within their definitions. For example: + // function myFunction... + // "myFunction" is T_STRING but we should skip because it is not a + // function or method *call*. + $functionName = $stackPtr; + $ignoreTokens = Tokens::$emptyTokens; + $ignoreTokens[] = T_BITWISE_AND; + $functionKeyword = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true); + if ($tokens[$functionKeyword]['code'] === T_FUNCTION || $tokens[$functionKeyword]['code'] === T_CLASS) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$stackPtr]['scope_condition']) === true + ) { + // Not a function call. + return; + } + + // If the next non-whitespace token after the function or method call + // is not an opening parenthesis then it can't really be a *call*. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($functionName + 1), null, true); + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + return; + } + + $this->checkSpacing($phpcsFile, $stackPtr, $openBracket); + + }//end process() + + + /** + * Checks the spacing around commas. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * + * @return void + */ + public function checkSpacing(File $phpcsFile, $stackPtr, $openBracket) + { + $tokens = $phpcsFile->getTokens(); + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $nextSeparator = $openBracket; + + $find = [ + T_COMMA, + T_CLOSURE, + T_FN, + T_ANON_CLASS, + T_OPEN_SHORT_ARRAY, + T_MATCH, + ]; + + while (($nextSeparator = $phpcsFile->findNext($find, ($nextSeparator + 1), $closeBracket)) !== false) { + if ($tokens[$nextSeparator]['code'] === T_CLOSURE + || $tokens[$nextSeparator]['code'] === T_ANON_CLASS + || $tokens[$nextSeparator]['code'] === T_MATCH + ) { + // Skip closures, anon class declarations and match control structures. + $nextSeparator = $tokens[$nextSeparator]['scope_closer']; + continue; + } else if ($tokens[$nextSeparator]['code'] === T_FN) { + // Skip arrow functions, but don't skip the arrow function closer as it is likely to + // be the comma separating it from the next function call argument (or the parenthesis closer). + $nextSeparator = ($tokens[$nextSeparator]['scope_closer'] - 1); + continue; + } else if ($tokens[$nextSeparator]['code'] === T_OPEN_SHORT_ARRAY) { + // Skips arrays using short notation. + $nextSeparator = $tokens[$nextSeparator]['bracket_closer']; + continue; + } + + // Make sure the comma or variable belongs directly to this function call, + // and is not inside a nested function call or array. + $brackets = $tokens[$nextSeparator]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if ($lastBracket !== $closeBracket) { + continue; + } + + if ($tokens[$nextSeparator]['code'] === T_COMMA) { + if ($tokens[($nextSeparator - 1)]['code'] === T_WHITESPACE) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextSeparator - 2), null, true); + if (isset(Tokens::$heredocTokens[$tokens[$prev]['code']]) === false) { + $error = 'Space found before comma in argument list'; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'SpaceBeforeComma'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[$prev]['line'] !== $tokens[$nextSeparator]['line']) { + $phpcsFile->fixer->addContent($prev, ','); + $phpcsFile->fixer->replaceToken($nextSeparator, ''); + } else { + $phpcsFile->fixer->replaceToken(($nextSeparator - 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[($nextSeparator + 1)]['code'] !== T_WHITESPACE) { + // Ignore trailing comma's after last argument as that's outside the scope of this sniff. + if (($nextSeparator + 1) !== $closeBracket) { + $error = 'No space found after comma in argument list'; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'NoSpaceAfterComma'); + if ($fix === true) { + $phpcsFile->fixer->addContent($nextSeparator, ' '); + } + } + } else { + // If there is a newline in the space, then they must be formatting + // each argument on a newline, which is valid, so ignore it. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextSeparator + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$nextSeparator]['line']) { + $space = $tokens[($nextSeparator + 1)]['length']; + if ($space > 1) { + $error = 'Expected 1 space after comma in argument list; %s found'; + $data = [$space]; + $fix = $phpcsFile->addFixableError($error, $nextSeparator, 'TooMuchSpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextSeparator + 1), ' '); + } + } + } + }//end if + }//end if + }//end while + + }//end checkSpacing() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php new file mode 100644 index 000000000..be96f5858 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php @@ -0,0 +1,225 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningFunctionBraceBsdAllmanSniff implements Sniff +{ + + /** + * Should this sniff check function braces? + * + * @var boolean + */ + public $checkFunctions = true; + + /** + * Should this sniff check closure braces? + * + * @var boolean + */ + public $checkClosures = false; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if (($tokens[$stackPtr]['code'] === T_FUNCTION + && (bool) $this->checkFunctions === false) + || ($tokens[$stackPtr]['code'] === T_CLOSURE + && (bool) $this->checkClosures === false) + ) { + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + } + + // Find the end of the function declaration. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + + $functionLine = $tokens[$prev]['line']; + $braceLine = $tokens[$openingBrace]['line']; + + $lineDifference = ($braceLine - $functionLine); + + $metricType = 'Function'; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $metricType = 'Closure'; + } + + if ($lineDifference === 0) { + $error = 'Opening brace should be on a new line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnSameLine'); + if ($fix === true) { + $hasTrailingAnnotation = false; + for ($nextLine = ($openingBrace + 1); $nextLine < $phpcsFile->numTokens; $nextLine++) { + if ($tokens[$openingBrace]['line'] !== $tokens[$nextLine]['line']) { + break; + } + + if (isset(Tokens::$phpcsCommentTokens[$tokens[$nextLine]['code']]) === true) { + $hasTrailingAnnotation = true; + } + } + + $phpcsFile->fixer->beginChangeset(); + $indent = $phpcsFile->findFirstOnLine([], $openingBrace); + + if ($hasTrailingAnnotation === false || $nextLine === false) { + if ($tokens[$indent]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addContentBefore($openingBrace, $tokens[$indent]['content']); + } + + if ($tokens[($openingBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ''); + } + + $phpcsFile->fixer->addNewlineBefore($openingBrace); + } else { + $phpcsFile->fixer->replaceToken($openingBrace, ''); + $phpcsFile->fixer->addNewlineBefore($nextLine); + $phpcsFile->fixer->addContentBefore($nextLine, '{'); + + if ($tokens[$indent]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addContentBefore($nextLine, $tokens[$indent]['content']); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'same line'); + } else if ($lineDifference > 1) { + $error = 'Opening brace should be on the line after the declaration; found %s blank line(s)'; + $data = [($lineDifference - 1)]; + + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($openingBrace - 1), $closeBracket, true); + if ($prevNonWs !== $prev) { + // There must be a comment between the end of the function declaration and the open brace. + // Report, but don't fix. + $phpcsFile->addError($error, $openingBrace, 'BraceSpacing', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceSpacing', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $openingBrace; $i > $prev; $i--) { + if ($tokens[$i]['line'] === $tokens[$openingBrace]['line']) { + if ($tokens[$i]['column'] === 1) { + $phpcsFile->fixer->addNewLineBefore($i); + } + + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $ignore = Tokens::$phpcsCommentTokens; + $ignore[] = T_WHITESPACE; + $next = $phpcsFile->findNext($ignore, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + // Only throw this error when this is not an empty function. + if ($next !== $tokens[$stackPtr]['scope_closer']) { + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference !== 1) { + return; + } + + // We need to actually find the first piece of content on this line, + // as if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + + // The opening brace is on the correct line, now it needs to be + // checked to be correctly indented. + $startColumn = $tokens[$lineStart]['column']; + $braceIndent = $tokens[$openingBrace]['column']; + + if ($braceIndent !== $startColumn) { + $expected = ($startColumn - 1); + $found = ($braceIndent - 1); + + $error = 'Opening brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceIndent', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expected); + if ($found === 0) { + $phpcsFile->fixer->addContentBefore($openingBrace, $indent); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), $indent); + } + } + }//end if + + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'new line'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php new file mode 100644 index 000000000..ca259854e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php @@ -0,0 +1,182 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningFunctionBraceKernighanRitchieSniff implements Sniff +{ + + /** + * Should this sniff check function braces? + * + * @var boolean + */ + public $checkFunctions = true; + + /** + * Should this sniff check closure braces? + * + * @var boolean + */ + public $checkClosures = false; + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + if (($tokens[$stackPtr]['code'] === T_FUNCTION + && (bool) $this->checkFunctions === false) + || ($tokens[$stackPtr]['code'] === T_CLOSURE + && (bool) $this->checkClosures === false) + ) { + return; + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + } + + // Find the end of the function declaration. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + + $functionLine = $tokens[$prev]['line']; + $braceLine = $tokens[$openingBrace]['line']; + + $lineDifference = ($braceLine - $functionLine); + + $metricType = 'Function'; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $metricType = 'Closure'; + } + + if ($lineDifference > 0) { + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'new line'); + $error = 'Opening brace should be on the same line as the declaration'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'BraceOnNewLine'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $closeBracket, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prev, ' {'); + $phpcsFile->fixer->replaceToken($openingBrace, ''); + if ($tokens[($openingBrace + 1)]['code'] === T_WHITESPACE + && $tokens[($openingBrace + 2)]['line'] > $tokens[$openingBrace]['line'] + ) { + // Brace is followed by a new line, so remove it to ensure we don't + // leave behind a blank line at the top of the block. + $phpcsFile->fixer->replaceToken(($openingBrace + 1), ''); + + if ($tokens[($openingBrace - 1)]['code'] === T_WHITESPACE + && $tokens[($openingBrace - 1)]['line'] === $tokens[$openingBrace]['line'] + && $tokens[($openingBrace - 2)]['line'] < $tokens[$openingBrace]['line'] + ) { + // Brace is preceded by indent, so remove it to ensure we don't + // leave behind more indent than is required for the first line. + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ''); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $phpcsFile->recordMetric($stackPtr, "$metricType opening brace placement", 'same line'); + }//end if + + $ignore = Tokens::$phpcsCommentTokens; + $ignore[] = T_WHITESPACE; + $next = $phpcsFile->findNext($ignore, ($openingBrace + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openingBrace]['line']) { + // Only throw this error when this is not an empty function. + if ($next !== $tokens[$stackPtr]['scope_closer'] + && $tokens[$next]['code'] !== T_CLOSE_TAG + ) { + $error = 'Opening brace must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'ContentAfterBrace'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($openingBrace); + } + } + } + + // Only continue checking if the opening brace looks good. + if ($lineDifference > 0) { + return; + } + + // We are looking for tabs, even if they have been replaced, because + // we enforce a space here. + if (isset($tokens[($openingBrace - 1)]['orig_content']) === true) { + $spacing = $tokens[($openingBrace - 1)]['orig_content']; + } else { + $spacing = $tokens[($openingBrace - 1)]['content']; + } + + if ($tokens[($openingBrace - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($spacing === "\t") { + $length = '\t'; + } else { + $length = strlen($spacing); + } + + if ($length !== 1) { + $error = 'Expected 1 space before opening brace; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $openingBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + if ($length === 0 || $length === '\t') { + $phpcsFile->fixer->addContentBefore($openingBrace, ' '); + } else { + $phpcsFile->fixer->replaceToken(($openingBrace - 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php new file mode 100644 index 000000000..8cba81daf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php @@ -0,0 +1,117 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Mayflower GmbH + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CyclomaticComplexitySniff implements Sniff +{ + + /** + * A complexity higher than this value will throw a warning. + * + * @var integer + */ + public $complexity = 10; + + /** + * A complexity higher than this value will throw an error. + * + * @var integer + */ + public $absoluteComplexity = 20; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore abstract methods. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // Detect start and end of this function definition. + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + + // Predicate nodes for PHP. + $find = [ + T_CASE => true, + T_DEFAULT => true, + T_CATCH => true, + T_IF => true, + T_FOR => true, + T_FOREACH => true, + T_WHILE => true, + T_ELSEIF => true, + T_INLINE_THEN => true, + T_COALESCE => true, + T_COALESCE_EQUAL => true, + T_MATCH_ARROW => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + ]; + + $complexity = 1; + + // Iterate from start to end and count predicate nodes. + for ($i = ($start + 1); $i < $end; $i++) { + if (isset($find[$tokens[$i]['code']]) === true) { + $complexity++; + } + } + + if ($complexity > $this->absoluteComplexity) { + $error = 'Function\'s cyclomatic complexity (%s) exceeds allowed maximum of %s'; + $data = [ + $complexity, + $this->absoluteComplexity, + ]; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($complexity > $this->complexity) { + $warning = 'Function\'s cyclomatic complexity (%s) exceeds %s; consider refactoring the function'; + $data = [ + $complexity, + $this->complexity, + ]; + $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php new file mode 100644 index 000000000..3c086c7fe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php @@ -0,0 +1,100 @@ + + * @author Greg Sherwood + * @copyright 2007-2014 Mayflower GmbH + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NestingLevelSniff implements Sniff +{ + + /** + * A nesting level higher than this value will throw a warning. + * + * @var integer + */ + public $nestingLevel = 5; + + /** + * A nesting level higher than this value will throw an error. + * + * @var integer + */ + public $absoluteNestingLevel = 10; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore abstract methods. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // Detect start and end of this function definition. + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + + $nestingLevel = 0; + + // Find the maximum nesting level of any token in the function. + for ($i = ($start + 1); $i < $end; $i++) { + $level = $tokens[$i]['level']; + if ($nestingLevel < $level) { + $nestingLevel = $level; + } + } + + // We subtract the nesting level of the function itself. + $nestingLevel = ($nestingLevel - $tokens[$stackPtr]['level'] - 1); + + if ($nestingLevel > $this->absoluteNestingLevel) { + $error = 'Function\'s nesting level (%s) exceeds allowed maximum of %s'; + $data = [ + $nestingLevel, + $this->absoluteNestingLevel, + ]; + $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); + } else if ($nestingLevel > $this->nestingLevel) { + $warning = 'Function\'s nesting level (%s) exceeds %s; consider refactoring the function'; + $data = [ + $nestingLevel, + $this->nestingLevel, + ]; + $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php new file mode 100644 index 000000000..44c16390e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/AbstractClassNamePrefixSniff.php @@ -0,0 +1,60 @@ + + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class AbstractClassNamePrefixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($phpcsFile->getClassProperties($stackPtr)['is_abstract'] === false) { + // This class is not abstract so we don't need to check it. + return; + } + + $className = $phpcsFile->getDeclarationName($stackPtr); + if ($className === null) { + // Live coding or parse error. + return; + } + + $prefix = substr($className, 0, 8); + if (strtolower($prefix) !== 'abstract') { + $phpcsFile->addError('Abstract class names must be prefixed with "Abstract"; found "%s"', $stackPtr, 'Missing', [$className]); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php new file mode 100644 index 000000000..d596f1744 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php @@ -0,0 +1,222 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class CamelCapsFunctionNameSniff extends AbstractScopeSniff +{ + + /** + * A list of all PHP magic methods. + * + * @var array + */ + protected $magicMethods = [ + 'construct' => true, + 'destruct' => true, + 'call' => true, + 'callstatic' => true, + 'get' => true, + 'set' => true, + 'isset' => true, + 'unset' => true, + 'sleep' => true, + 'wakeup' => true, + 'serialize' => true, + 'unserialize' => true, + 'tostring' => true, + 'invoke' => true, + 'set_state' => true, + 'clone' => true, + 'debuginfo' => true, + ]; + + /** + * A list of all PHP non-magic methods starting with a double underscore. + * + * These come from PHP modules such as SOAPClient. + * + * @var array + */ + protected $methodsDoubleUnderscore = [ + 'dorequest' => true, + 'getcookies' => true, + 'getfunctions' => true, + 'getlastrequest' => true, + 'getlastrequestheaders' => true, + 'getlastresponse' => true, + 'getlastresponseheaders' => true, + 'gettypes' => true, + 'setcookie' => true, + 'setlocation' => true, + 'setsoapheaders' => true, + 'soapcall' => true, + ]; + + /** + * A list of all PHP magic functions. + * + * @var array + */ + protected $magicFunctions = ['autoload' => true]; + + /** + * If TRUE, the string must not have two capital letters next to each other. + * + * @var boolean + */ + public $strict = true; + + + /** + * Constructs a Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Live coding or parse error. Bow out. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + + $methodNameLc = strtolower($methodName); + $classNameLc = strtolower($className); + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = substr($methodNameLc, 2); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); + } + + // PHP4 constructors are allowed to break our rules. + if ($methodNameLc === $classNameLc) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodNameLc === '_'.$classNameLc) { + return; + } + + // Ignore leading underscores in the method name. + $methodName = ltrim($methodName, '_'); + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if (Common::isCamelCaps($methodName, false, true, $this->strict) === false) { + if ($methodProps['scope_specified'] === true) { + $error = '%s method name "%s" is not in camel caps format'; + $data = [ + ucfirst($methodProps['scope']), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); + } else { + $error = 'Method name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Live coding or parse error. Bow out. + return; + } + + $errorData = [$functionName]; + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === true) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData); + } + + // Ignore leading underscores in the method name. + $functionName = ltrim($functionName, '_'); + + if (Common::isCamelCaps($functionName, false, true, $this->strict) === false) { + $error = 'Function name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase function name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php new file mode 100644 index 000000000..48e7659e3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php @@ -0,0 +1,178 @@ + + * @author Leif Wickland + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConstructorNameSniff extends AbstractScopeSniff +{ + + /** + * The name of the class we are currently checking. + * + * @var string + */ + private $currentClass = ''; + + /** + * A list of functions in the current class. + * + * @var string[] + */ + private $functionList = []; + + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() + { + parent::__construct([T_CLASS, T_ANON_CLASS], [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes this test when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (empty($className) === false) { + // Not an anonymous class. + $className = strtolower($className); + } + + if ($className !== $this->currentClass) { + $this->loadFunctionNamesInScope($phpcsFile, $currScope); + $this->currentClass = $className; + } + + $methodName = strtolower($phpcsFile->getDeclarationName($stackPtr)); + + if ($methodName === $className) { + if (in_array('__construct', $this->functionList, true) === false) { + $error = 'PHP4 style constructors are not allowed; use "__construct()" instead'; + $phpcsFile->addError($error, $stackPtr, 'OldStyle'); + } + } else if ($methodName !== '__construct') { + // Not a constructor. + return; + } + + // Stop if the constructor doesn't have a body, like when it is abstract. + if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $parentClassName = $phpcsFile->findExtendedClassName($currScope); + if ($parentClassName === false) { + return; + } + + $parentClassNameLc = strtolower($parentClassName); + + $endFunctionIndex = $tokens[$stackPtr]['scope_closer']; + $startIndex = $tokens[$stackPtr]['scope_opener']; + while (($doubleColonIndex = $phpcsFile->findNext(T_DOUBLE_COLON, ($startIndex + 1), $endFunctionIndex)) !== false) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($doubleColonIndex + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] !== T_STRING + || strtolower($tokens[$nextNonEmpty]['content']) !== $parentClassNameLc + ) { + $startIndex = $nextNonEmpty; + continue; + } + + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($doubleColonIndex - 1), null, true); + if ($tokens[$prevNonEmpty]['code'] === T_PARENT + || $tokens[$prevNonEmpty]['code'] === T_SELF + || $tokens[$prevNonEmpty]['code'] === T_STATIC + || ($tokens[$prevNonEmpty]['code'] === T_STRING + && strtolower($tokens[$prevNonEmpty]['content']) === $parentClassNameLc) + ) { + $error = 'PHP4 style calls to parent constructors are not allowed; use "parent::__construct()" instead'; + $phpcsFile->addError($error, $nextNonEmpty, 'OldStyleCall'); + } + + $startIndex = $nextNonEmpty; + }//end while + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + + /** + * Extracts all the function names found in the given scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + protected function loadFunctionNamesInScope(File $phpcsFile, $currScope) + { + $this->functionList = []; + $tokens = $phpcsFile->getTokens(); + + for ($i = ($tokens[$currScope]['scope_opener'] + 1); $i < $tokens[$currScope]['scope_closer']; $i++) { + if ($tokens[$i]['code'] !== T_FUNCTION) { + continue; + } + + $this->functionList[] = trim(strtolower($phpcsFile->getDeclarationName($i))); + + if (isset($tokens[$i]['scope_closer']) !== false) { + // Skip past nested functions and such. + $i = $tokens[$i]['scope_closer']; + } + } + + }//end loadFunctionNamesInScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php new file mode 100644 index 000000000..6dfad6b40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/InterfaceNameSuffixSniff.php @@ -0,0 +1,55 @@ + + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InterfaceNameSuffixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INTERFACE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $interfaceName = $phpcsFile->getDeclarationName($stackPtr); + if ($interfaceName === null) { + // Live coding or parse error. Bow out. + return; + } + + $suffix = substr($interfaceName, -9); + if (strtolower($suffix) !== 'interface') { + $phpcsFile->addError('Interface names must be suffixed with "Interface"; found "%s"', $stackPtr, 'Missing', [$interfaceName]); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php new file mode 100644 index 000000000..79a77557d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/TraitNameSuffixSniff.php @@ -0,0 +1,55 @@ + + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class TraitNameSuffixSniff implements Sniff +{ + + + /** + * Registers the tokens that this sniff wants to listen for. + * + * @return array + */ + public function register() + { + return [T_TRAIT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $traitName = $phpcsFile->getDeclarationName($stackPtr); + if ($traitName === null) { + // Live coding or parse error. Bow out. + return; + } + + $suffix = substr($traitName, -5); + if (strtolower($suffix) !== 'trait') { + $phpcsFile->addError('Trait names must be suffixed with "Trait"; found "%s"', $stackPtr, 'Missing', [$traitName]); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php new file mode 100644 index 000000000..f62cfe94b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php @@ -0,0 +1,149 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UpperCaseConstantNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_CONST, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_CONST) { + // This is a constant declared with the "const" keyword. + // This may be an OO constant, in which case it could be typed, so we need to + // jump over a potential type to get to the name. + $assignmentOperator = $phpcsFile->findNext([T_EQUAL, T_SEMICOLON], ($stackPtr + 1)); + if ($assignmentOperator === false || $tokens[$assignmentOperator]['code'] !== T_EQUAL) { + // Parse error/live coding. Nothing to do. Rest of loop is moot. + return; + } + + $constant = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($assignmentOperator - 1), ($stackPtr + 1), true); + if ($constant === false) { + return; + } + + $constName = $tokens[$constant]['content']; + + if (strtoupper($constName) !== $constName) { + if (strtolower($constName) === $constName) { + $phpcsFile->recordMetric($constant, 'Constant name case', 'lower'); + } else { + $phpcsFile->recordMetric($constant, 'Constant name case', 'mixed'); + } + + $error = 'Class constants must be uppercase; expected %s but found %s'; + $data = [ + strtoupper($constName), + $constName, + ]; + $phpcsFile->addError($error, $constant, 'ClassConstantNotUpperCase', $data); + } else { + $phpcsFile->recordMetric($constant, 'Constant name case', 'upper'); + } + + return; + }//end if + + // Only interested in define statements now. + if (strtolower($tokens[$stackPtr]['content']) !== 'define') { + return; + } + + // Make sure this is not a method call. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_DOUBLE_COLON + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + return; + } + + // If the next non-whitespace token after this token + // is not an opening parenthesis then it is not a function call. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($openBracket === false) { + return; + } + + // The next non-whitespace token must be the constant name. + $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + $constName = $tokens[$constPtr]['content']; + + // Check for constants like self::CONSTANT. + $prefix = ''; + $splitPos = strpos($constName, '::'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 2)); + $constName = substr($constName, ($splitPos + 2)); + } + + // Strip namespace from constant like /foo/bar/CONSTANT. + $splitPos = strrpos($constName, '\\'); + if ($splitPos !== false) { + $prefix = substr($constName, 0, ($splitPos + 1)); + $constName = substr($constName, ($splitPos + 1)); + } + + if (strtoupper($constName) !== $constName) { + if (strtolower($constName) === $constName) { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'lower'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'mixed'); + } + + $error = 'Constants must be uppercase; expected %s but found %s'; + $data = [ + $prefix.strtoupper($constName), + $prefix.$constName, + ]; + $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data); + } else { + $phpcsFile->recordMetric($stackPtr, 'Constant name case', 'upper'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php new file mode 100644 index 000000000..f3c56b588 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/BacktickOperatorSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class BacktickOperatorSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_BACKTICK]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of the backtick operator is forbidden'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php new file mode 100644 index 000000000..61ff4f2f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php @@ -0,0 +1,86 @@ + + * @copyright 2010-2014 Andy Grunwald + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CharacterBeforePHPOpeningTagSniff implements Sniff +{ + + /** + * List of supported BOM definitions. + * + * Use encoding names as keys and hex BOM representations as values. + * + * @var array + */ + protected $bomDefinitions = [ + 'UTF-8' => 'efbbbf', + 'UTF-16 (BE)' => 'feff', + 'UTF-16 (LE)' => 'fffe', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $expected = 0; + if ($stackPtr > 0) { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + foreach ($this->bomDefinitions as $expectedBomHex) { + $bomByteLength = (strlen($expectedBomHex) / 2); + $htmlBomHex = bin2hex(substr($tokens[0]['content'], 0, $bomByteLength)); + if ($htmlBomHex === $expectedBomHex) { + $expected++; + break; + } + } + + // Allow a shebang line. + if (substr($tokens[0]['content'], 0, 2) === '#!') { + $expected++; + } + } + + if ($stackPtr !== $expected) { + $error = 'The opening PHP tag must be the first content in the file'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + // Skip the rest of the file so we don't pick up additional + // open tags, typically embedded in HTML. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php new file mode 100644 index 000000000..23dd2b6b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php @@ -0,0 +1,54 @@ + + * @copyright 2010-2014 Stefano Kowalke + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingPHPTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closeTag === false) { + $error = 'The PHP open tag does not have a corresponding PHP close tag'; + $phpcsFile->addError($error, $stackPtr, 'NotFound'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php new file mode 100644 index 000000000..44efd53af --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php @@ -0,0 +1,75 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use ReflectionFunction; + +class DeprecatedFunctionsSniff extends ForbiddenFunctionsSniff +{ + + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array + */ + public $forbiddenFunctions = []; + + + /** + * Constructor. + * + * Uses the Reflection API to get a list of deprecated functions. + */ + public function __construct() + { + $functions = get_defined_functions(); + + foreach ($functions['internal'] as $functionName) { + $function = new ReflectionFunction($functionName); + + if ($function->isDeprecated() === true) { + $this->forbiddenFunctions[$functionName] = null; + } + } + + }//end __construct() + + + /** + * Generates the error or warning for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden function + * in the token array. + * @param string $function The name of the forbidden function. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError($phpcsFile, $stackPtr, $function, $pattern=null) + { + $data = [$function]; + $error = 'Function %s() has been deprecated'; + $type = 'Deprecated'; + + if ($this->error === true) { + $phpcsFile->addError($error, $stackPtr, $type, $data); + } else { + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + + }//end addError() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php new file mode 100644 index 000000000..a2cf1b931 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Sniffs/PHP/DisallowAlternativePHPTagsSniff.php @@ -0,0 +1,253 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowAlternativePHPTagsSniff implements Sniff +{ + + /** + * Whether ASP tags are enabled or not. + * + * @var boolean + */ + private $aspTags = false; + + /** + * The current PHP version. + * + * @var integer|string|null + */ + private $phpVersion = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + if ($this->phpVersion === null) { + $this->phpVersion = Config::getConfigData('php_version'); + if ($this->phpVersion === null) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + if ($this->phpVersion < 70000) { + $this->aspTags = (bool) ini_get('asp_tags'); + } + + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + T_INLINE_HTML, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $openTag = $tokens[$stackPtr]; + $content = $openTag['content']; + + if (trim($content) === '') { + return; + } + + if ($openTag['code'] === T_OPEN_TAG) { + if ($content === '<%') { + $error = 'ASP style opening tag used; expected "findClosingTag($phpcsFile, $tokens, $stackPtr, '%>'); + $errorCode = 'ASPOpenTagFound'; + } else if (strpos($content, ''); + $errorCode = 'ScriptOpenTagFound'; + } + + if (isset($error, $closer, $errorCode) === true) { + $data = [$content]; + + if ($closer === false) { + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + $this->addChangeset($phpcsFile, $tokens, $stackPtr, $closer); + } + } + } + + return; + }//end if + + if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO && $content === '<%=') { + $error = 'ASP style opening tag used with echo; expected "findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $snippet = $this->getSnippet($tokens[$nextVar]['content']); + $data = [ + $snippet, + $content, + $snippet, + ]; + + $closer = $this->findClosingTag($phpcsFile, $tokens, $stackPtr, '%>'); + + if ($closer === false) { + $phpcsFile->addError($error, $stackPtr, 'ASPShortOpenTagFound', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ASPShortOpenTagFound', $data); + if ($fix === true) { + $this->addChangeset($phpcsFile, $tokens, $stackPtr, $closer, true); + } + } + + return; + }//end if + + // Account for incorrect script open tags. + if ($openTag['code'] === T_INLINE_HTML + && preg_match('`( + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed new file mode 100644 index 000000000..2a695c896 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.1.inc.fixed @@ -0,0 +1,14 @@ +
    + +Some content here. + + + + +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc new file mode 100644 index 000000000..cd5a6620c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc @@ -0,0 +1,6 @@ +
    +<% echo $var; %> +

    Some text <% echo $var; %> and some more text

    +<%= $var . ' and some more text to make sure the snippet works'; %> +

    Some text <%= $var %> and some more text

    +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed new file mode 100644 index 000000000..6eafb422e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.2.inc.fixed @@ -0,0 +1,6 @@ +
    + +

    Some text and some more text

    + +

    Some text and some more text

    +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc new file mode 100644 index 000000000..ba86345a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.3.inc @@ -0,0 +1,7 @@ + +
    +<% echo $var; %> +

    Some text <% echo $var; %> and some more text

    +<%= $var . ' and some more text to make sure the snippet works'; %> +

    Some text <%= $var %> and some more text

    +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php new file mode 100644 index 000000000..8dd6deb97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php @@ -0,0 +1,110 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowAlternativePHPTags sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowAlternativePHPTagsSniff + */ +final class DisallowAlternativePHPTagsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of all test files to check. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = [$testFileBase.'1.inc']; + + $aspTags = false; + if (PHP_VERSION_ID < 70000) { + $aspTags = (bool) ini_get('asp_tags'); + } + + if ($aspTags === true) { + $testFiles[] = $testFileBase.'2.inc'; + } else { + $testFiles[] = $testFileBase.'3.inc'; + } + + return $testFiles; + + }//end getTestFiles() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowAlternativePHPTagsUnitTest.1.inc': + return [ + 4 => 1, + 7 => 1, + 8 => 1, + 11 => 1, + ]; + case 'DisallowAlternativePHPTagsUnitTest.2.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 5 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'DisallowAlternativePHPTagsUnitTest.3.inc') { + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + ]; + } + + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc new file mode 100644 index 000000000..974e45c05 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.inc @@ -0,0 +1,16 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php new file mode 100644 index 000000000..15510a691 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowRequestSuperglobalUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowRequestSuperglobal sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowRequestSuperglobalSniff + */ +final class DisallowRequestSuperglobalUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 2 => 1, + 12 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc new file mode 100644 index 000000000..040e62dcb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc @@ -0,0 +1,11 @@ +
    + +Some content here. + + +Some content Some more content + + +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed new file mode 100644 index 000000000..1ea281a41 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.1.inc.fixed @@ -0,0 +1,11 @@ +
    + +Some content here. + + +Some content Some more content + + +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc new file mode 100644 index 000000000..85617ded6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc @@ -0,0 +1,8 @@ +
    + +Some content Some more content + + +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed new file mode 100644 index 000000000..afe5d8f2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.2.inc.fixed @@ -0,0 +1,8 @@ +
    + +Some content Some more content + + +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc new file mode 100644 index 000000000..6c4f83d56 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.3.inc @@ -0,0 +1,20 @@ +// Test warning for when short_open_tag is off. + +Some content Some more content + +// Test multi-line. +Some content Some more content + +// Make sure skipping works. +Some content Some more content + +// Test snippet clipping with a line that has more than 40 characters after the PHP open tag. +Some content Some longer content to trigger snippet clipping + +// Only recognize closing tag after opener. +// The test below must be the last test in the file because there must be no PHP close tag after it. +Some?> content + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowShortOpenTag sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowShortOpenTagSniff + */ +final class DisallowShortOpenTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of all test files to check. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = [$testFileBase.'1.inc']; + + $option = (bool) ini_get('short_open_tag'); + if ($option === true) { + $testFiles[] = $testFileBase.'2.inc'; + } else { + $testFiles[] = $testFileBase.'3.inc'; + $testFiles[] = $testFileBase.'4.inc'; + } + + return $testFiles; + + }//end getTestFiles() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowShortOpenTagUnitTest.1.inc': + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 10 => 1, + ]; + case 'DisallowShortOpenTagUnitTest.2.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 7 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'DisallowShortOpenTagUnitTest.1.inc': + return []; + case 'DisallowShortOpenTagUnitTest.3.inc': + return [ + 3 => 1, + 6 => 1, + 11 => 1, + 16 => 1, + ]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc new file mode 100644 index 000000000..f564215b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/DiscourageGotoUnitTest.inc @@ -0,0 +1,18 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DiscourageGoto sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DiscourageGotoSniff + */ +final class DiscourageGotoUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 3 => 1, + 6 => 1, + 11 => 1, + 16 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc new file mode 100644 index 000000000..060da6128 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.inc @@ -0,0 +1,60 @@ +sizeof($array); +$size = $class->count($array); +$class->delete($filepath); +$class->unset($filepath); + +function delete() {} +function unset() {} +function sizeof() {} +function count() {} + +trait DelProvider { + public function delete() { + //irrelevant + } +} + +class LeftSideTest { + use DelProvider { + delete as protected unsetter; + } +} + +class RightSideTest { + use DelProvider { + delete as delete; + } +} + +class RightSideVisTest { + use DelProvider { + delete as protected delete; + DelProvider::delete insteadof delete; + } +} + +namespace Something\sizeof; +$var = new Sizeof(); +class SizeOf implements Something {} + +function mymodule_form_callback(SizeOf $sizeof) { +} + +$size = $class?->sizeof($array); + +#[SizeOf(10)] +function doSomething() {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php new file mode 100644 index 000000000..cb0931312 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ForbiddenFunctions sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff + */ +final class ForbiddenFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 2 => 1, + 4 => 1, + 6 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc new file mode 100644 index 000000000..396cf6a4a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc @@ -0,0 +1,153 @@ +NULL = 7; + +use Zend\Log\Writer\NULL as NullWriter; +new \Zend\Log\Writer\NULL(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?FALSE:true; +$x = $f? FALSE:true; + +class MyClass +{ + // Spice things up a little. + const TRUE = false; +} + +var_dump(MyClass::TRUE); + +function tRUE() {} + +$input->getFilterChain()->attachByName('Null', ['type' => Null::TYPE_STRING]); + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = FALSE; + + public int|FALSE $int = FALSE; + public Type|NULL $int = new MyObj(NULL); + + private function typed(int|FALSE $param = NULL, Type|NULL $obj = new MyObj(FALSE)) : string|FALSE|NULL + { + if (TRUE === FALSE) { + return NULL; + } + } +} + +$cl = function (int|FALSE $param = NULL, Type|NULL $obj = new MyObj(FALSE)) : string|FALSE|NULL {}; + +// Adding some extra tests to safeguard that function declarations which don't create scope are handled correctly. +interface InterfaceMethodsWithReturnTypeNoScopeOpener { + private function typed($param = TRUE) : string|FALSE|NULL; +} + +abstract class ClassMethodsWithReturnTypeNoScopeOpener { + abstract public function typed($param = FALSE) : TRUE; +} + +// Additional tests to safeguard improved property type skip logic. +readonly class Properties { + use SomeTrait { + sayHello as private myPrivateHello; + } + + public Type|FALSE|NULL $propertyA = array( + 'itemA' => TRUE, + 'itemB' => FALSE, + 'itemC' => NULL, + ), $propertyB = FALSE; + + protected \FullyQualified&Partially\Qualified&namespace\Relative $propertyC; + var ?TRUE $propertyD; + static array|callable|FALSE|self|parent $propertyE = TRUE; + private + // phpcs:ignore Stnd.Cat.Sniff -- for reasons. + TRUE /*comment*/ + $propertyF = TRUE; + + public function __construct( + public FALSE|NULL $promotedPropA, + readonly callable|TRUE $promotedPropB, + ) { + static $var; + echo static::class; + static::foo(); + $var = $var instanceof static; + $obj = new static(); + } + + public static function foo(): static|self|FALSE { + $callable = static function() {}; + } +} + +// PHP 8.3 introduces typed constants. +class TypedConstants { + const MyClass|NULL|TRUE|FALSE MYCONST = FALSE; +} + +// Global constants can not be typed. +const MYCONST = TRUE; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc.fixed new file mode 100644 index 000000000..96b1c78de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.1.inc.fixed @@ -0,0 +1,153 @@ +NULL = 7; + +use Zend\Log\Writer\NULL as NullWriter; +new \Zend\Log\Writer\NULL(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?false:true; +$x = $f? false:true; + +class MyClass +{ + // Spice things up a little. + const TRUE = false; +} + +var_dump(MyClass::TRUE); + +function tRUE() {} + +$input->getFilterChain()->attachByName('Null', ['type' => Null::TYPE_STRING]); + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = false; + + public int|FALSE $int = false; + public Type|NULL $int = new MyObj(null); + + private function typed(int|FALSE $param = null, Type|NULL $obj = new MyObj(false)) : string|FALSE|NULL + { + if (true === false) { + return null; + } + } +} + +$cl = function (int|FALSE $param = null, Type|NULL $obj = new MyObj(false)) : string|FALSE|NULL {}; + +// Adding some extra tests to safeguard that function declarations which don't create scope are handled correctly. +interface InterfaceMethodsWithReturnTypeNoScopeOpener { + private function typed($param = true) : string|FALSE|NULL; +} + +abstract class ClassMethodsWithReturnTypeNoScopeOpener { + abstract public function typed($param = false) : TRUE; +} + +// Additional tests to safeguard improved property type skip logic. +readonly class Properties { + use SomeTrait { + sayHello as private myPrivateHello; + } + + public Type|FALSE|NULL $propertyA = array( + 'itemA' => true, + 'itemB' => false, + 'itemC' => null, + ), $propertyB = false; + + protected \FullyQualified&Partially\Qualified&namespace\Relative $propertyC; + var ?TRUE $propertyD; + static array|callable|FALSE|self|parent $propertyE = true; + private + // phpcs:ignore Stnd.Cat.Sniff -- for reasons. + TRUE /*comment*/ + $propertyF = true; + + public function __construct( + public FALSE|NULL $promotedPropA, + readonly callable|TRUE $promotedPropB, + ) { + static $var; + echo static::class; + static::foo(); + $var = $var instanceof static; + $obj = new static(); + } + + public static function foo(): static|self|FALSE { + $callable = static function() {}; + } +} + +// PHP 8.3 introduces typed constants. +class TypedConstants { + const MyClass|NULL|TRUE|FALSE MYCONST = false; +} + +// Global constants can not be typed. +const MYCONST = true; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.2.inc new file mode 100644 index 000000000..c61a0a50f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.2.inc @@ -0,0 +1,4 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowerCaseConstant sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseConstantSniff + */ +final class LowerCaseConstantUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'LowerCaseConstantUnitTest.1.inc': + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 23 => 1, + 26 => 1, + 31 => 1, + 32 => 1, + 39 => 1, + 42 => 1, + 47 => 1, + 48 => 1, + 70 => 1, + 71 => 1, + 87 => 1, + 89 => 1, + 90 => 1, + 92 => 2, + 94 => 2, + 95 => 1, + 100 => 2, + 104 => 1, + 108 => 1, + 118 => 1, + 119 => 1, + 120 => 1, + 121 => 1, + 125 => 1, + 129 => 1, + 149 => 1, + 153 => 1, + ]; + + case 'LowerCaseConstantUnitTest.js': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 7 => 1, + 8 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc new file mode 100644 index 000000000..10d3ed693 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc @@ -0,0 +1,64 @@ + $x; +$r = Match ($x) { + 1 => 1, + 2 => 2, + DEFAULT, => 3, +}; + +class Reading { + Public READOnly int $var; +} + +EnuM ENUM: string +{ + Case HEARTS; +} + +new Class {}; +new clasS extends stdClass {}; +new class {}; + +if (isset($a) && !empty($a)) { unset($a); } +if (ISSET($a) && !Empty($a)) { UnSeT($a); } +eval('foo'); +eVaL('foo'); + +$c = function() { + Yield /*comment*/ From fun(); + YIELD + /*comment*/ + FROM fun(); +} + +__HALT_COMPILER(); // An exception due to phar support. +function diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed new file mode 100644 index 000000000..547f72fca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc.fixed @@ -0,0 +1,64 @@ + $x; +$r = match ($x) { + 1 => 1, + 2 => 2, + default, => 3, +}; + +class Reading { + public readonly int $var; +} + +enum ENUM: string +{ + case HEARTS; +} + +new class {}; +new class extends stdClass {}; +new class {}; + +if (isset($a) && !empty($a)) { unset($a); } +if (isset($a) && !empty($a)) { unset($a); } +eval('foo'); +eval('foo'); + +$c = function() { + yield /*comment*/ from fun(); + yield + /*comment*/ + from fun(); +} + +__HALT_COMPILER(); // An exception due to phar support. +function diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php new file mode 100644 index 000000000..31bfad6df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowerCaseKeyword sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseKeywordSniff + */ +final class LowerCaseKeywordUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 3, + 11 => 4, + 12 => 1, + 13 => 3, + 14 => 7, + 15 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 25 => 1, + 28 => 1, + 31 => 1, + 32 => 1, + 35 => 1, + 39 => 2, + 42 => 1, + 44 => 1, + 47 => 1, + 48 => 1, + 52 => 3, + 54 => 1, + 57 => 2, + 58 => 1, + 60 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc new file mode 100644 index 000000000..fb5b1fd5a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc @@ -0,0 +1,145 @@ + $a * $b; +$arrow = fn (Int $a, String $b, BOOL $c, Array $d, Foo\Bar $e) : Float => $a * $b; + +$cl = function (False $a, TRUE $b, Null $c): ?True {}; + +class TypedClassConstants +{ + const UNTYPED = null; + const FLOAT = 'Reserved keyword as name is valid and should not be changed'; + const OBJECT = 'Reserved keyword as name is valid and should not be changed'; + + const ClassName FIRST = null; + public const Int SECOND = 0; + private const ?BOOL THIRD = false; + public const Self FOURTH = null; +} +interface TypedInterfaceConstants +{ + protected const PaRenT FIRST = null; + private const ARRAY SECOND = []; + public const Float THIRD = 2.5; + final const ?STRING FOURTH = 'fourth'; +} +trait TypedTraitConstants { + const IterablE FIRST = null; + const Object SECOND = null; + const Mixed THIRD = 'third'; +} +enum TypedEnumConstants { + public const Iterable|FALSE|NULL FIRST = null; + protected const SELF|Parent /* comment */ |\Fully\Qualified\ClassName|UnQualifiedClass SECOND = null; + private const ClassName|/*comment*/Float|STRING|False THIRD = 'third'; + public const sTRing | aRRaY | FaLSe FOURTH = 'fourth'; +} + +class DNFTypes { + const (Parent&Something)|Float CONST_NAME = 1.5; + + public readonly TRUE|(\A&B) $prop; + + function DNFParamTypes ( + null|(\Package\ClassName&\Package\Other_Class)|INT $DNFinMiddle, + (\Package\ClassName&\Package\Other_Class)|ARRAY $parensAtStart, + False|(\Package\ClassName&\Package\Other_Class) $parentAtEnd, + ) {} + + function DNFReturnTypes ($var): object|(Self&\Package\Other_Class)|sTRINg|false {} +} + +// Intentional error, should be ignored by the sniff. +interface PropertiesNotAllowed { + public $notAllowed; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc.fixed new file mode 100644 index 000000000..10be06b0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.inc.fixed @@ -0,0 +1,145 @@ + $a * $b; +$arrow = fn (int $a, string $b, bool $c, array $d, Foo\Bar $e) : float => $a * $b; + +$cl = function (false $a, true $b, null $c): ?true {}; + +class TypedClassConstants +{ + const UNTYPED = null; + const FLOAT = 'Reserved keyword as name is valid and should not be changed'; + const OBJECT = 'Reserved keyword as name is valid and should not be changed'; + + const ClassName FIRST = null; + public const int SECOND = 0; + private const ?bool THIRD = false; + public const self FOURTH = null; +} +interface TypedInterfaceConstants +{ + protected const parent FIRST = null; + private const array SECOND = []; + public const float THIRD = 2.5; + final const ?string FOURTH = 'fourth'; +} +trait TypedTraitConstants { + const iterable FIRST = null; + const object SECOND = null; + const mixed THIRD = 'third'; +} +enum TypedEnumConstants { + public const iterable|false|null FIRST = null; + protected const self|parent /* comment */ |\Fully\Qualified\ClassName|UnQualifiedClass SECOND = null; + private const ClassName|/*comment*/float|string|false THIRD = 'third'; + public const string | array | false FOURTH = 'fourth'; +} + +class DNFTypes { + const (parent&Something)|float CONST_NAME = 1.5; + + public readonly true|(\A&B) $prop; + + function DNFParamTypes ( + null|(\Package\ClassName&\Package\Other_Class)|int $DNFinMiddle, + (\Package\ClassName&\Package\Other_Class)|array $parensAtStart, + false|(\Package\ClassName&\Package\Other_Class) $parentAtEnd, + ) {} + + function DNFReturnTypes ($var): object|(self&\Package\Other_Class)|string|false {} +} + +// Intentional error, should be ignored by the sniff. +interface PropertiesNotAllowed { + public $notAllowed; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.php new file mode 100644 index 000000000..262193285 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/LowerCaseTypeUnitTest.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowerCaseType sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseTypeSniff + */ +final class LowerCaseTypeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 21 => 4, + 22 => 3, + 23 => 3, + 25 => 1, + 26 => 2, + 27 => 2, + 32 => 4, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 43 => 2, + 44 => 1, + 46 => 1, + 49 => 1, + 51 => 2, + 53 => 1, + 55 => 2, + 60 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 71 => 3, + 72 => 2, + 73 => 3, + 74 => 3, + 78 => 3, + 82 => 2, + 85 => 1, + 94 => 5, + 96 => 4, + 105 => 1, + 106 => 1, + 107 => 1, + 111 => 1, + 112 => 1, + 113 => 1, + 114 => 1, + 117 => 1, + 118 => 1, + 119 => 1, + 122 => 3, + 123 => 2, + 124 => 3, + 125 => 3, + 129 => 2, + 131 => 1, + 134 => 1, + 135 => 1, + 136 => 1, + 139 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + // Warning from getMemberProperties() about parse error. + return [144 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc new file mode 100644 index 000000000..98159b472 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.inc @@ -0,0 +1,16 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the NoSilencedErrors sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\NoSilencedErrorsSniff + */ +final class NoSilencedErrorsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [13 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 5 => 1, + 10 => 1, + 16 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc new file mode 100644 index 000000000..387cec240 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/RequireStrictTypesUnitTest.1.inc @@ -0,0 +1,8 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the RequireStrictType sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\RequireStrictTypesSniff + */ +final class RequireStrictTypesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'RequireStrictTypesUnitTest.2.inc': + case 'RequireStrictTypesUnitTest.5.inc': + case 'RequireStrictTypesUnitTest.6.inc': + case 'RequireStrictTypesUnitTest.10.inc': + return [1 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'RequireStrictTypesUnitTest.11.inc': + case 'RequireStrictTypesUnitTest.12.inc': + case 'RequireStrictTypesUnitTest.14.inc': + case 'RequireStrictTypesUnitTest.15.inc': + return [3 => 1]; + + default: + return []; + } + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc new file mode 100644 index 000000000..f0f350f37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.inc @@ -0,0 +1,5 @@ +php_sapi_name() === true) {} +if ($object?->php_sapi_name() === true) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php new file mode 100644 index 000000000..9ee274b6f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SAPIUsage sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\SAPIUsageSniff + */ +final class SAPIUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [2 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc new file mode 100644 index 000000000..4f0d9d84e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.1.inc @@ -0,0 +1,4 @@ + +
    text
    + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php new file mode 100644 index 000000000..58433eb1d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/SyntaxUnitTest.php @@ -0,0 +1,63 @@ + + * @author Blaine Schmeisser + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the Syntax sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\SyntaxSniff + */ +final class SyntaxUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SyntaxUnitTest.1.inc': + case 'SyntaxUnitTest.2.inc': + return [3 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc new file mode 100644 index 000000000..30c6d2980 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc @@ -0,0 +1,98 @@ +null = 7; + +use Zend\Log\Writer\Null as NullWriter; +new \Zend\Log\Writer\Null(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?false:TRUE; +$x = $f? false:TRUE; + +class MyClass +{ + // Spice things up a little. + const true = FALSE; +} + +var_dump(MyClass::true); + +function true() {} + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = false; + + public int|false $int = false; + public Type|null $int = new MyObj(null); + + private function typed(int|false $param = null, Type|null $obj = new MyObj(false)) : string|false|null + { + if (true === false) { + return null; + } + } +} + +$cl = function (int|false $param = null, Type|null $obj = new MyObj(false)) : string|false|null {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed new file mode 100644 index 000000000..7705198c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc.fixed @@ -0,0 +1,98 @@ +null = 7; + +use Zend\Log\Writer\Null as NullWriter; +new \Zend\Log\Writer\Null(); + +namespace False; + +class True extends Null implements False {} + +use True\Something; +use Something\True; +class MyClass +{ + public function myFunction() + { + $var = array('foo' => new True()); + } +} + +$x = $f?FALSE:TRUE; +$x = $f? FALSE:TRUE; + +class MyClass +{ + // Spice things up a little. + const true = FALSE; +} + +var_dump(MyClass::true); + +function true() {} + +// Issue #3332 - ignore type declarations, but not default values. +class TypedThings { + const MYCONST = FALSE; + + public int|false $int = FALSE; + public Type|null $int = new MyObj(NULL); + + private function typed(int|false $param = NULL, Type|null $obj = new MyObj(FALSE)) : string|false|null + { + if (TRUE === FALSE) { + return NULL; + } + } +} + +$cl = function (int|false $param = NULL, Type|null $obj = new MyObj(FALSE)) : string|false|null {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php new file mode 100644 index 000000000..481c4ab1c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the UpperCaseConstant sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\UpperCaseConstantSniff + */ +final class UpperCaseConstantUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 23 => 1, + 26 => 1, + 31 => 1, + 32 => 1, + 39 => 1, + 42 => 1, + 47 => 1, + 48 => 1, + 70 => 1, + 71 => 1, + 85 => 1, + 87 => 1, + 88 => 1, + 90 => 2, + 92 => 2, + 93 => 1, + 98 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc new file mode 100644 index 000000000..abaad16d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryHeredocUnitTest.1.inc @@ -0,0 +1,108 @@ +bar} +END; + +$heredoc = <<< "END" +some ${beers::softdrink} +END; + +$heredoc = <<< END +{${$object->getName()}} text +END; + +$heredoc = <<<"END" +some {${getName()}} +END; + +$heredoc = <<baz()()} +END; + +$heredoc = <<values[3]->name} text +END; + +$heredoc = <<<"END" +some ${$bar} +END; + +$heredoc = <<bar} text +END; + +$heredoc = <<<"END" +${foo["${bar}"]} text +END; + +$heredoc = <<{${'a'}}} text +END; + +$heredoc = <<{$baz[1]}} +END; + +$heredoc = <<john's wife greeted $people->robert. +END; + +$heredoc = <<bar} +END; + +$heredoc = <<< "END" +some ${beers::softdrink} +END; + +$heredoc = <<< END +{${$object->getName()}} text +END; + +$heredoc = <<<"END" +some {${getName()}} +END; + +$heredoc = <<baz()()} +END; + +$heredoc = <<values[3]->name} text +END; + +$heredoc = <<<"END" +some ${$bar} +END; + +$heredoc = <<bar} text +END; + +$heredoc = <<<"END" +${foo["${bar}"]} text +END; + +$heredoc = <<{${'a'}}} text +END; + +$heredoc = <<{$baz[1]}} +END; + +$heredoc = <<john's wife greeted $people->robert. +END; + +$heredoc = <<bar} + END; + +$heredoc = <<< "END" + some ${beers::softdrink} + END; + +$heredoc = <<< END + {${$object->getName()}} text + END; + +$heredoc = <<<"END" + some {${getName()}} + END; + +$heredoc = <<baz()()} + END; + +$heredoc = <<values[3]->name} text + END; + +$heredoc = <<<"END" + some ${$bar} + END; + +$heredoc = <<bar} text + END; + +$heredoc = <<<"END" + ${foo["${bar}"]} text + END; + +$heredoc = <<{${'a'}}} text + END; + +$heredoc = <<{$baz[1]}} + END; + +$heredoc = <<john's wife greeted $people->robert. + END; + +$heredoc = <<bar} + END; + +$heredoc = <<< "END" + some ${beers::softdrink} + END; + +$heredoc = <<< END + {${$object->getName()}} text + END; + +$heredoc = <<<"END" + some {${getName()}} + END; + +$heredoc = <<baz()()} + END; + +$heredoc = <<values[3]->name} text + END; + +$heredoc = <<<"END" + some ${$bar} + END; + +$heredoc = <<bar} text + END; + +$heredoc = <<<"END" + ${foo["${bar}"]} text + END; + +$heredoc = <<{${'a'}}} text + END; + +$heredoc = <<{$baz[1]}} + END; + +$heredoc = <<john's wife greeted $people->robert. + END; + +$heredoc = << + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the UnnecessaryHeredoc sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\Strings\UnnecessaryHeredocSniff + */ +final class UnnecessaryHeredocUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + $warnings = [ + 100 => 1, + 104 => 1, + ]; + + switch ($testFile) { + case 'UnnecessaryHeredocUnitTest.1.inc': + return $warnings; + + case 'UnnecessaryHeredocUnitTest.2.inc': + if (PHP_VERSION_ID >= 70300) { + return $warnings; + } + + // PHP 7.2 or lower: PHP version which doesn't support flexible heredocs/nowdocs yet. + return []; + + default: + return []; + } + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.1.inc new file mode 100644 index 000000000..d2ac790d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.1.inc @@ -0,0 +1,34 @@ +'; +$code = '<'.'?php '; + +$string = 'This is a really long string. ' + . 'It is being used for errors. ' + . 'The message is not translated.'; + +$shouldBail = 1 + 1; + +$shouldNotTrigger = 'My' . /* comment */ 'string'; +$shouldNotTrigger = 'My' /* comment */ . 'string'; + +// phpcs:set Generic.Strings.UnnecessaryStringConcat allowMultiline true +$string = 'Multiline strings are allowed ' + . 'when setting is enabled.'; +// phpcs:set Generic.Strings.UnnecessaryStringConcat allowMultiline false + +// phpcs:set Generic.Strings.UnnecessaryStringConcat error false +$throwWarning = 'My' . 'string'; +// phpcs:set Generic.Strings.UnnecessaryStringConcat error true diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.2.inc new file mode 100644 index 000000000..6a5fcba9a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.2.inc @@ -0,0 +1,7 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the UnnecessaryStringConcat sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\Strings\UnnecessaryStringConcatSniff + */ +final class UnnecessaryStringConcatUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'UnnecessaryStringConcatUnitTest.1.inc': + return [ + 2 => 1, + 6 => 1, + 9 => 1, + 12 => 1, + 19 => 1, + 20 => 1, + ]; + + case 'UnnecessaryStringConcatUnitTest.js': + return [ + 1 => 1, + 8 => 1, + 11 => 1, + 14 => 1, + 15 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'UnnecessaryStringConcatUnitTest.1.inc': + return [ + 33 => 1, + ]; + + default: + return []; + } + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css new file mode 100644 index 000000000..de84a948e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.css @@ -0,0 +1,35 @@ +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ + +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; +<<<<<<< HEAD + line-height: -25px; +======= + line-height: -20px; +>>>>>>> ref/heads/feature-branch + cursor: pointer; + -moz-user-select: none; +} + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries, subsequent boundaries will still + * be detected correctly. + */ + +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc new file mode 100644 index 000000000..470c3b8f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.1.inc @@ -0,0 +1,61 @@ +> -1); +var_dump( +1 +<< +-1 +); + +$string = +<< 'a' +<<<<<<< HEAD + 'b' => 'b' +======= + 'c' => 'c' +>>>>>>> master + ); + } + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +/* + * Testing detecting subsequent merge conflicts. + * +<<<<<<< HEAD + * @var string $bar + */ +public function foo($bar){ } + +/** +============ +The above is not the boundary, the below is. +======= + * @var string $bar +>>>>>>> f19f8a5... Commit message +*/ + +// Test that stray boundaries, i.e. an opener without closer and such, are detected. +<<<<<<< HEAD +$a = 1; +======= diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css new file mode 100644 index 000000000..6caa78d02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.css @@ -0,0 +1,32 @@ +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict started in a comment, ending in a CSS block. + */ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; +======= + * which should be detected. + **/ +.SettingsTabPaneWidgetType-tab-start { + line-height: -25px; +>>>>>>> ref/heads/feature-branch + cursor: pointer; + -moz-user-select: none; +} + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries, subsequent boundaries will still + * be detected correctly. + */ + +/* + * This is a CSS comment. +<<<<<<< HEAD + * This is a merge conflict... +======= + * which should be detected. +>>>>>>> ref/heads/feature-branch + */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc new file mode 100644 index 000000000..809b17d6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.2.inc @@ -0,0 +1,31 @@ +>>>>>> master + */ + +/* + * Testing detecting merge conflicts using different comment styles. + * +<<<<<<< HEAD + * @var string $bar + */ +public function foo($bar){ } + +/* +======= + * @var string $bar +>>>>>>> master +*/ + +// Comment +<<<<<<< HEAD +// Second comment line. NOTE: The above opener breaks the tokenizer. +======= +// New second comment line +>>>>>>> master +// Third comment line diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc new file mode 100644 index 000000000..ce709412b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.3.inc @@ -0,0 +1,43 @@ + +
    +<<<<<<< HEAD +

    Testing a merge conflict.

    +======= +

    Another text string.

    +>>>>>>> ref/heads/feature-branch +
    + + +
    +<<<<<<< HEAD +

    +======= +

    +>>>>>>> ref/heads/feature-branch +
    + +>>>>>> master + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ +?> + +
    +<<<<<<< HEAD +

    Testing a merge conflict.

    +======= +

    Another text string.

    +>>>>>>> ref/heads/feature-branch +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc new file mode 100644 index 000000000..99c0b9971 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.4.inc @@ -0,0 +1,71 @@ +>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +// Heredoc with a merge conflict starter, the closer is outside the heredoc. +$string = +<<>>>>>> ref/heads/other-branchname + +// Merge conflict starter outside with a closer inside of the heredoc. +// This breaks the tokenizer. +<<<<<<< HEAD +$string = +<<>>>>>> ref/heads/other-branchname +EOD; + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = +<<>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +$string = +<<>>>>>> ref/heads/other-branchname diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc new file mode 100644 index 000000000..7d55f6df4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.5.inc @@ -0,0 +1,34 @@ +>>>>>> ref/heads/other-branchname +And now they are. +EOD; + +// Break the tokenizer. +<<<<<<< HEAD + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = +<<<'EOD' +can be problematic. +<<<<<<< HEAD +were previously not detected. +======= +should also be detected. +>>>>>>> ref/heads/other-branchname +And now they are. +EOD; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc new file mode 100644 index 000000000..aaea32450 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.6.inc @@ -0,0 +1,34 @@ +>>>>>> ref/heads/other-branchname + And now they are. + EOD; + +// Break the tokenizer. +>>>>>>> master + +/* + * The above tests are based on "normal" tokens. + * The below test checks that once the tokenizer breaks down because of + * unexpected merge conflict boundaries - i.e. after the first merge conflict + * opener in non-comment, non-heredoc/nowdoc, non-inline HTML code -, subsequent + * merge conflict boundaries will still be detected correctly. + */ + +$string = + <<<"EOD" + Merge conflicts in PHP 7.3 indented heredocs +<<<<<<< HEAD + can be problematic. +======= + should also be detected. +>>>>>>> ref/heads/other-branchname + And now they are. + EOD; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc new file mode 100644 index 000000000..85cae1fdc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.7.inc @@ -0,0 +1,19 @@ + +
    +<<<<<<< HEAD +

    Testing a merge conflict.

    +======= +

    Another text string.

    +>>>>>>> ref/heads/feature-branch +
    + + +
    +<<<<<<< HEAD +

    +======= +

    +>>>>>>> ref/heads/feature-branch +
    + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js new file mode 100644 index 000000000..cd7bc760f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.js @@ -0,0 +1,33 @@ + +result = x?y:z; +result = x ? y : z; + +<<<<<<< HEAD +if (something === true +======= +if (something === false +>>>>>>> develop + ^ somethingElse === true +) { +<<<<<<< HEAD + return true; +======= + return false; +>>>>>>> develop +} + +y = 1 + + 2 + - 3; + +/* +<<<<<<< HEAD + * @var string $bar + */ +if (something === true + +/** +======= + * @var string $foo +>>>>>>> master + */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php new file mode 100644 index 000000000..bc9663849 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/GitMergeConflictUnitTest.php @@ -0,0 +1,175 @@ + + * @copyright 2017 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\VersionControl; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the GitMergeConflict sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\GitMergeConflictSniff + */ +final class GitMergeConflictUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'GitMergeConflictUnitTest.1.inc': + return [ + 26 => 1, + 28 => 1, + 30 => 1, + 45 => 1, + 53 => 1, + 55 => 1, + 59 => 1, + 61 => 1, + ]; + + case 'GitMergeConflictUnitTest.2.inc': + return [ + 4 => 1, + 6 => 1, + 8 => 1, + 14 => 1, + 20 => 1, + 22 => 1, + 26 => 1, + 28 => 1, + 30 => 1, + ]; + + case 'GitMergeConflictUnitTest.3.inc': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 22 => 1, + 24 => 1, + 26 => 1, + 38 => 1, + 40 => 1, + 42 => 1, + ]; + + case 'GitMergeConflictUnitTest.4.inc': + return [ + 6 => 1, + 8 => 1, + 10 => 1, + 18 => 1, + 22 => 1, + 25 => 1, + 29 => 1, + 34 => 1, + 39 => 1, + 53 => 1, + 55 => 1, + 57 => 1, + 64 => 1, + 68 => 1, + 71 => 1, + ]; + case 'GitMergeConflictUnitTest.5.inc': + case 'GitMergeConflictUnitTest.6.inc': + return [ + 6 => 1, + 8 => 1, + 10 => 1, + 15 => 1, + 28 => 1, + 30 => 1, + 32 => 1, + ]; + + case 'GitMergeConflictUnitTest.7.inc': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + ]; + + case 'GitMergeConflictUnitTest.1.css': + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 30 => 1, + 32 => 1, + 34 => 1, + ]; + + case 'GitMergeConflictUnitTest.2.css': + return [ + 3 => 1, + 8 => 1, + 13 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + ]; + + case 'GitMergeConflictUnitTest.js': + return [ + 5 => 1, + 7 => 1, + 9 => 1, + 12 => 1, + 14 => 1, + 16 => 1, + 24 => 1, + 30 => 1, + 32 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc new file mode 100644 index 000000000..e4110dee1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/VersionControl/SubversionPropertiesUnitTest.inc @@ -0,0 +1,3 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\VersionControl; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SubversionProperties sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\SubversionPropertiesSniff + */ +final class SubversionPropertiesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return bool + */ + protected function shouldSkipTest() + { + // This sniff cannot be tested as no SVN version control directory is available. + return true; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc new file mode 100644 index 000000000..4ce050840 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc @@ -0,0 +1,192 @@ +{$var}( $foo,$bar ); + +$bar(function( $a, $b ) { + return function( $c, $d ) use ( $a, $b ) { + echo $a, $b, $c, $d; + }; +})( 'a','b' )( 'c','d' ); + +$closure( $foo,$bar ); +$var = $closure() + $closure( $foo,$bar ) + self::$closure( $foo,$bar ); + +class Test { + public static function baz( $foo, $bar ) { + $a = new self( $foo,$bar ); + $b = new static( $foo,$bar ); + } +} + +/* + * Test warning for empty parentheses. + */ +$a = 4 + (); // Warning. +$a = 4 + ( ); // Warning. +$a = 4 + (/* Not empty */); + +/* + * Test the actual sniff. + */ +if ((null !== $extra) && ($row->extra !== $extra)) {} + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} // Bad x 4. + +if (( null !== $extra // Bad x 1. + && is_int($extra)) + && ( $row->extra !== $extra // Bad x 1. + || $something ) // Bad x 1. +) {} + +if (( null !== $extra ) // Bad x 2. + && ( $row->extra !== $extra ) // Bad x 2. +) {} + +$a = (null !== $extra); +$a = ( null !== $extra ); // Bad x 2. + +$sx = $vert ? ($w - 1) : 0; + +$this->is_overloaded = ( ( ini_get("mbstring.func_overload") & 2 ) != 0 ) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} + +$directory = ('/' == $file[ strlen($file)-1 ]); + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ((null !== $extra) && ($row->extra !== $extra)) {} // Bad x 4. + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} + +if (( null !== $extra // Bad x 1. + && is_int($extra)) // Bad x 1. + && ( $row->extra !== $extra + || $something ) // Bad x 1. +) {} + +if ((null !== $extra) // Bad x 2. + && ($row->extra !== $extra) // Bad x 2. +) {} + +$a = (null !== $extra); // Bad x 2. +$a = ( null !== $extra ); + +$sx = $vert ? ($w - 1) : 0; // Bad x 2. + +$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); // Bad x 4. + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} // Bad x 2. + +$directory = ('/' == $file[ strlen($file)-1 ]); // Bad x 2. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +/* + * Test handling of ignoreNewlines. + */ +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} // Bad x 4, 1 x line 123, 2 x line 125, 1 x line 127. + + +$a = ( + null !== $extra +); // Bad x 2, 1 x line 131, 1 x line 133. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} // Bad x 4, 1 x line 137, 2 x line 139, 1 x line 141. + +$a = ( + null !== $extra +); // Bad x 2, 1 x line 144, 1 x line 146. +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines true +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} + +$a = ( + null !== $extra +); +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines false + +if (true) {} ( 1+2) === 3 ? $a = 1 : $a = 2; +class A {} ( 1+2) === 3 ? $a = 1 : $a = 2; +function foo() {} ( 1+2) === 3 ? $a = 1 : $a = 2; + +// Issue #3618. +class NonArbitraryParenthesesWithKeywords { + public static function baz( $foo, $bar ) { + $a = new self(); + $b = new parent(); + $c = new static(); + + // self/static are already tested above, round line 45. + $d = new parent( $foo,$bar ); + } +} + +// Test that the match expression does not trigger the sniff. +$b = match ( $a ) { + 1 => true, +}; + +// Parentheses after die/exit in a switch case should be ignored. +switch ( $type ) { + case A: + exit( 1 ); + case B: + die(); + default: + break; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc.fixed new file mode 100644 index 000000000..a00228081 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.1.inc.fixed @@ -0,0 +1,180 @@ +{$var}( $foo,$bar ); + +$bar(function( $a, $b ) { + return function( $c, $d ) use ( $a, $b ) { + echo $a, $b, $c, $d; + }; +})( 'a','b' )( 'c','d' ); + +$closure( $foo,$bar ); +$var = $closure() + $closure( $foo,$bar ) + self::$closure( $foo,$bar ); + +class Test { + public static function baz( $foo, $bar ) { + $a = new self( $foo,$bar ); + $b = new static( $foo,$bar ); + } +} + +/* + * Test warning for empty parentheses. + */ +$a = 4 + (); // Warning. +$a = 4 + ( ); // Warning. +$a = 4 + (/* Not empty */); + +/* + * Test the actual sniff. + */ +if ((null !== $extra) && ($row->extra !== $extra)) {} + +if ((null !== $extra) && ($row->extra !== $extra)) {} // Bad x 4. + +if ((null !== $extra // Bad x 1. + && is_int($extra)) + && ($row->extra !== $extra // Bad x 1. + || $something) // Bad x 1. +) {} + +if ((null !== $extra) // Bad x 2. + && ($row->extra !== $extra) // Bad x 2. +) {} + +$a = (null !== $extra); +$a = (null !== $extra); // Bad x 2. + +$sx = $vert ? ($w - 1) : 0; + +$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ($operation->axis & 1) != 0, ($operation->axis & 2) != 0 ); + +if ( $success && ('nothumb' == $target || 'all' == $target) ) {} + +$directory = ('/' == $file[ strlen($file)-1 ]); + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if (( null !== $extra ) && ( $row->extra !== $extra )) {} // Bad x 4. + +if (( null !== $extra ) && ( $row->extra !== $extra )) {} + +if (( null !== $extra // Bad x 1. + && is_int($extra) ) // Bad x 1. + && ( $row->extra !== $extra + || $something ) // Bad x 1. +) {} + +if (( null !== $extra ) // Bad x 2. + && ( $row->extra !== $extra ) // Bad x 2. +) {} + +$a = ( null !== $extra ); // Bad x 2. +$a = ( null !== $extra ); + +$sx = $vert ? ( $w - 1 ) : 0; // Bad x 2. + +$this->is_overloaded = ( ( ini_get("mbstring.func_overload") & 2 ) != 0 ) && function_exists('mb_substr'); // Bad x 4. + +$image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 ); // Bad x 4. + +if ( $success && ( 'nothumb' == $target || 'all' == $target ) ) {} // Bad x 2. + +$directory = ( '/' == $file[ strlen($file)-1 ] ); // Bad x 2. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +/* + * Test handling of ignoreNewlines. + */ +if ( + (null !== $extra) && ($row->extra !== $extra) +) {} // Bad x 4, 1 x line 123, 2 x line 125, 1 x line 127. + + +$a = (null !== $extra); // Bad x 2, 1 x line 131, 1 x line 133. + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 1 +if ( + ( null !== $extra ) && ( $row->extra !== $extra ) +) {} // Bad x 4, 1 x line 137, 2 x line 139, 1 x line 141. + +$a = ( null !== $extra ); // Bad x 2, 1 x line 144, 1 x line 146. +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing spacing 0 + +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines true +if ( + ( + null !== $extra + ) && ( + $row->extra !== $extra + ) +) {} + +$a = ( + null !== $extra +); +// phpcs:set Generic.WhiteSpace.ArbitraryParenthesesSpacing ignoreNewlines false + +if (true) {} (1+2) === 3 ? $a = 1 : $a = 2; +class A {} (1+2) === 3 ? $a = 1 : $a = 2; +function foo() {} (1+2) === 3 ? $a = 1 : $a = 2; + +// Issue #3618. +class NonArbitraryParenthesesWithKeywords { + public static function baz( $foo, $bar ) { + $a = new self(); + $b = new parent(); + $c = new static(); + + // self/static are already tested above, round line 45. + $d = new parent( $foo,$bar ); + } +} + +// Test that the match expression does not trigger the sniff. +$b = match ( $a ) { + 1 => true, +}; + +// Parentheses after die/exit in a switch case should be ignored. +switch ( $type ) { + case A: + exit( 1 ); + case B: + die(); + default: + break; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.2.inc new file mode 100644 index 000000000..3d5bcd0a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ArbitraryParenthesesSpacingUnitTest.2.inc @@ -0,0 +1,4 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ArbitraryParenthesesSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ArbitraryParenthesesSpacingSniff + */ +final class ArbitraryParenthesesSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ArbitraryParenthesesSpacingUnitTest.1.inc': + return [ + 64 => 4, + 66 => 1, + 68 => 1, + 69 => 1, + 72 => 2, + 73 => 2, + 77 => 2, + 81 => 4, + 90 => 4, + 94 => 1, + 95 => 1, + 97 => 1, + 100 => 2, + 101 => 2, + 104 => 2, + 107 => 2, + 109 => 4, + 111 => 4, + 113 => 2, + 115 => 2, + 123 => 1, + 125 => 2, + 127 => 1, + 131 => 1, + 133 => 1, + 137 => 1, + 139 => 2, + 141 => 1, + 144 => 1, + 146 => 1, + 163 => 1, + 164 => 1, + 165 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'ArbitraryParenthesesSpacingUnitTest.1.inc': + return [ + 55 => 1, + 56 => 1, + ]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc new file mode 100644 index 000000000..b19a58d87 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.1.inc @@ -0,0 +1,125 @@ +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + +"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; + return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>"; +// Doc comments are indent with tabs and one space +//[tab]/** +//[tab][space]* + /** + * CVS revision for HTTP headers. + * + * @var string + * @access private + */ + /** + * + */ + +$str = 'hello + there'; + +/** + * This PHP DocBlock should be fine, even though there is a single space at the beginning. + * + * @var int $x + */ +$x = 1; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowSpaceIndent sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\DisallowSpaceIndentSniff + */ +final class DisallowSpaceIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'DisallowSpaceIndentUnitTest.2.inc') { + return; + } + + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowSpaceIndentUnitTest.1.inc': + case 'DisallowSpaceIndentUnitTest.2.inc': + return [ + 5 => 1, + 9 => 1, + 15 => 1, + 22 => 1, + 24 => 1, + 30 => 1, + 35 => 1, + 50 => 1, + 55 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 73 => 1, + 77 => 1, + 81 => 1, + 104 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 108 => 1, + 110 => 1, + 111 => 1, + 112 => 1, + 114 => 1, + 115 => 1, + 117 => 1, + 118 => 1, + 123 => 1, + ]; + + case 'DisallowSpaceIndentUnitTest.3.inc': + return [ + 2 => 1, + 5 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + ]; + + case 'DisallowSpaceIndentUnitTest.4.inc': + if (PHP_VERSION_ID >= 70300) { + return [ + 7 => 1, + 13 => 1, + ]; + } + + // PHP 7.2 or lower: PHP version which doesn't support flexible heredocs/nowdocs yet. + return []; + + case 'DisallowSpaceIndentUnitTest.js': + return [3 => 1]; + + case 'DisallowSpaceIndentUnitTest.css': + return [2 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc new file mode 100644 index 000000000..74fa50511 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.1.inc @@ -0,0 +1,102 @@ + 'Czech republic', + 'România' => 'Romania', + 'Magyarország' => 'Hungary', +); + +$var = "$hello $there"; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + 'Czech republic', + 'România' => 'Romania', + 'Magyarország' => 'Hungary', +); + +$var = "$hello $there"; + +?> + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + + + Foo + + +
    +
    +
    +
    +
    +
    + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowTabIndent sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\DisallowTabIndentSniff + */ +final class DisallowTabIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowTabIndentUnitTest.1.inc': + return [ + 5 => 2, + 9 => 1, + 15 => 1, + 20 => 2, + 21 => 1, + 22 => 2, + 23 => 1, + 24 => 2, + 31 => 1, + 32 => 2, + 33 => 2, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 48 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 85 => 1, + 86 => 1, + 87 => 1, + 89 => 1, + 90 => 1, + 92 => 1, + 93 => 1, + 97 => 1, + 100 => 1, + ]; + + case 'DisallowTabIndentUnitTest.2.inc': + return [ + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 19 => 1, + ]; + + case 'DisallowTabIndentUnitTest.3.inc': + if (PHP_VERSION_ID >= 70300) { + return [ + 7 => 1, + 13 => 1, + ]; + } + + // PHP 7.2 or lower: PHP version which doesn't support flexible heredocs/nowdocs yet. + return []; + + case 'DisallowTabIndentUnitTest.js': + return [ + 3 => 1, + 5 => 1, + 6 => 1, + ]; + + case 'DisallowTabIndentUnitTest.css': + return [ + 1 => 1, + 2 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/HereNowdocIdentifierSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/HereNowdocIdentifierSpacingUnitTest.inc new file mode 100644 index 000000000..0121118a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/HereNowdocIdentifierSpacingUnitTest.inc @@ -0,0 +1,25 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the HereNowdocIdentifierSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\HereNowdocIdentifierSpacingSniff + */ +final class HereNowdocIdentifierSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc new file mode 100644 index 000000000..535053b0d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc @@ -0,0 +1,43 @@ +prop++; +$obj->prop ++; +$obj?->prop ++; + +$obj->obj->prop++; +$obj->obj->prop ++; +$obj?->obj->prop ++; + +$obj->prop['key']++; +$obj->prop['key'] ++; + +--ClassName::$prop; +-- ClassName::$prop; + +getObject()->count +++; +getObject()->count++; +++ getObject()->count; +++getObject()->count; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..c30332b25 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.inc.fixed @@ -0,0 +1,41 @@ +prop++; +$obj->prop++; +$obj?->prop++; + +$obj->obj->prop++; +$obj->obj->prop++; +$obj?->obj->prop++; + +$obj->prop['key']++; +$obj->prop['key']++; + +--ClassName::$prop; +--ClassName::$prop; + +getObject()->count++; +getObject()->count++; +++getObject()->count; +++getObject()->count; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js new file mode 100644 index 000000000..b7b1c2f26 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js @@ -0,0 +1,17 @@ +var i; + +i = 10; +--i; +-- i; +-- /*comment*/ i; +++i; +++ + i; +++/*comment*/i; + +i--; +i --; +i /*comment*/ --; +i++; +i ++; +i /*comment*/ ++; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js.fixed new file mode 100644 index 000000000..5d8b33a0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.js.fixed @@ -0,0 +1,16 @@ +var i; + +i = 10; +--i; +--i; +-- /*comment*/ i; +++i; +++i; +++/*comment*/i; + +i--; +i--; +i /*comment*/ --; +i++; +i++; +i /*comment*/ ++; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.php new file mode 100644 index 000000000..91e349338 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/IncrementDecrementSpacingUnitTest.php @@ -0,0 +1,86 @@ + + * @copyright 2018 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the IncrementDecrementSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\IncrementDecrementSpacingSniff + */ +final class IncrementDecrementSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + $errors = [ + 5 => 1, + 6 => 1, + 8 => 1, + 10 => 1, + 13 => 1, + 14 => 1, + 16 => 1, + 17 => 1, + ]; + + switch ($testFile) { + case 'IncrementDecrementSpacingUnitTest.inc': + $errors[21] = 1; + $errors[23] = 1; + $errors[26] = 1; + $errors[27] = 1; + $errors[30] = 1; + $errors[31] = 1; + $errors[34] = 1; + $errors[37] = 1; + $errors[40] = 1; + $errors[42] = 1; + + return $errors; + + case 'IncrementDecrementSpacingUnitTest.js': + return $errors; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.1.inc new file mode 100644 index 000000000..8d4acfe0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.1.inc @@ -0,0 +1,100 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LanguageConstructSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\LanguageConstructSpacingSniff + */ +final class LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'LanguageConstructSpacingUnitTest.1.inc': + return [ + 3 => 1, + 5 => 1, + 8 => 1, + 10 => 1, + 13 => 1, + 15 => 1, + 18 => 1, + 20 => 1, + 23 => 1, + 25 => 1, + 28 => 1, + 30 => 1, + 33 => 1, + 36 => 1, + 39 => 1, + 40 => 1, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 48 => 1, + 52 => 1, + 55 => 1, + 56 => 1, + 57 => 2, + 60 => 1, + 63 => 1, + 65 => 1, + 73 => 1, + 75 => 1, + 77 => 1, + 81 => 1, + 83 => 1, + 85 => 1, + 86 => 1, + 90 => 1, + 94 => 1, + 95 => 1, + 98 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc new file mode 100644 index 000000000..74c5c0728 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc @@ -0,0 +1,1659 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false + +hello(); + } + + function hello() + { + echo 'hello'; +}//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): +if ($bar) $foo = 1; +elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { +if (false) { +echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( +'some long description', function () { + }); +} + +switch ( $a ) { +case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'b': + $b = 3; +?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, +false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => +$value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +foo(function ($foo) { + return [ + match ($foo) { + } + ]; +}); + +// Issue #110. +echo match (1) { + 0 => match (2) { + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, + 1 => match (2) { + 1 => match (3) { + 3 => 3, + default => -1, + }, + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, +}; + +// Issue #437. +match (true) { + default => [ + 'unrelated' => '', + 'example' => array_filter( + array_map( + function () { + return null; + }, + [] + ) + ) + ] +}; + +// Issue squizlabs/PHP_CodeSniffer#3808 +function test() { + yield + from [ 3, 4 ]; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed new file mode 100644 index 000000000..414ea6f7f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.inc.fixed @@ -0,0 +1,1659 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false + +hello(); + } + + function hello() + { + echo 'hello'; + }//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { + if (false) { + echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( + 'some long description', function () { + }); +} + +switch ( $a ) { + case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'b': + $b = 3; + ?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => + $value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +foo(function ($foo) { + return [ + match ($foo) { + } + ]; +}); + +// Issue #110. +echo match (1) { + 0 => match (2) { + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, + 1 => match (2) { + 1 => match (3) { + 3 => 3, + default => -1, + }, + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, +}; + +// Issue #437. +match (true) { + default => [ + 'unrelated' => '', + 'example' => array_filter( + array_map( + function () { + return null; + }, + [] + ) + ) + ] +}; + +// Issue squizlabs/PHP_CodeSniffer#3808 +function test() { + yield + from [ 3, 4 ]; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js new file mode 100644 index 000000000..2195bfb9b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js @@ -0,0 +1,239 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +var script = document.createElement('script'); +script.onload = function() +{ + clearTimeout(t); + script456.onload = null; + script.onreadystatechange = null; + callback.call(this); + +}; + +this.callbacks[type] = { + namespaces: {}, +others: [] +}; + +blah = function() +{ + print something; + + } + +test(blah, function() { + print something; +}); + +var test = [{x: 10}]; +var test = [{ + x: 10, + y: { + b14h: 12, + 'b14h': 12 + }, + z: 23 +}]; + +Viper.prototype = { + + _removeEvents: function(elem) + { + if (!elem) { + elem = this.element; + } + + ViperUtil.removeEvent(elem, '.' + this.getEventNamespace()); + + } + +}; + +this.init = function(data) { + if (_pageListWdgt) { + GUI.getWidget('changedPagesList').addItemClickedCallback( + function(itemid, target) { + draftChangeTypeClicked( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + } + ); + } + ); + }//end if + +}; + +a( + function() { + var _a = function() { + b = false; + + }; + true + } +); + +(function() { + a = function() { + a(function() { + if (true) { + a = true; + } + }); + + a( + function() { + if (true) { + if (true) { + a = true; + } + } + } + ); + + a( + function() { + if (true) { + a = true; + } + } + ); + + }; + +})(); + +a.prototype = { + + a: function() + { + var currentSize = null; + ViperUtil.addEvent( + header, + 'safedblclick', + function() {}, + ); + + if (topContent) { + ViperUtil.addClass(topContent, 'Viper-popup-top'); + main.appendChild(topContent); + } + + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + } + +}; + +a.prototype = { + + a: function() + { + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + + var mouseUpAction = function() {}; + var preventMouseUp = false; + var self = this; + if (clickAction) { + } + } + +}; + +a.prototype = { + + a: function() + { + var a = function() { + var a = 'foo'; + }; + + if (true) { + } + + }, + + b: function() + { + ViperUtil.addEvent( + function() { + if (fullScreen !== true) { + currentSize = { + }; + + showfullScreen(); + } + } + ); + + }, + + c: function() + { + this.a( + { + a: function() { + form.onsubmit = function() { + return false; + }; + + var a = true; + } + } + ); + + } + +}; + +a.prototype = { + init: function() + {}, + + _b: function() + { + } + +}; + +for (var i = 0; i < 10; i++) { + var foo = {foo:{'a':'b', + 'c':'d'}}; +} + +class TestOk +{ + destroy() + { + setTimeout(a, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +class TestBad +{ + destroy() + { + setTimeout(function () { + return; + }, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +( function( $ ) { + foo(function( value ) { + value.bind( function( newval ) { + $( '#bar' ).html( newval ); + } ); + } )( jQuery ); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed new file mode 100644 index 000000000..d4bf409bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.1.js.fixed @@ -0,0 +1,239 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent false +var script = document.createElement('script'); +script.onload = function() +{ + clearTimeout(t); + script456.onload = null; + script.onreadystatechange = null; + callback.call(this); + +}; + +this.callbacks[type] = { + namespaces: {}, + others: [] +}; + +blah = function() +{ + print something; + +} + +test(blah, function() { + print something; +}); + +var test = [{x: 10}]; +var test = [{ + x: 10, + y: { + b14h: 12, + 'b14h': 12 + }, + z: 23 +}]; + +Viper.prototype = { + + _removeEvents: function(elem) + { + if (!elem) { + elem = this.element; + } + + ViperUtil.removeEvent(elem, '.' + this.getEventNamespace()); + + } + +}; + +this.init = function(data) { + if (_pageListWdgt) { + GUI.getWidget('changedPagesList').addItemClickedCallback( + function(itemid, target) { + draftChangeTypeClicked( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + } + ); + } + ); + }//end if + +}; + +a( + function() { + var _a = function() { + b = false; + + }; + true + } +); + +(function() { + a = function() { + a(function() { + if (true) { + a = true; + } + }); + + a( + function() { + if (true) { + if (true) { + a = true; + } + } + } + ); + + a( + function() { + if (true) { + a = true; + } + } + ); + + }; + +})(); + +a.prototype = { + + a: function() + { + var currentSize = null; + ViperUtil.addEvent( + header, + 'safedblclick', + function() {}, + ); + + if (topContent) { + ViperUtil.addClass(topContent, 'Viper-popup-top'); + main.appendChild(topContent); + } + + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + } + +}; + +a.prototype = { + + a: function() + { + ViperUtil.addClass(midContent, 'Viper-popup-content'); + main.appendChild(midContent); + + var mouseUpAction = function() {}; + var preventMouseUp = false; + var self = this; + if (clickAction) { + } + } + +}; + +a.prototype = { + + a: function() + { + var a = function() { + var a = 'foo'; + }; + + if (true) { + } + + }, + + b: function() + { + ViperUtil.addEvent( + function() { + if (fullScreen !== true) { + currentSize = { + }; + + showfullScreen(); + } + } + ); + + }, + + c: function() + { + this.a( + { + a: function() { + form.onsubmit = function() { + return false; + }; + + var a = true; + } + } + ); + + } + +}; + +a.prototype = { + init: function() + {}, + + _b: function() + { + } + +}; + +for (var i = 0; i < 10; i++) { + var foo = {foo:{'a':'b', + 'c':'d'}}; +} + +class TestOk +{ + destroy() + { + setTimeout(a, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +class TestBad +{ + destroy() + { + setTimeout(function () { + return; + }, 1000); + + if (typeof self.callbackOnClose === "function") { + self.callbackOnClose(); + } + } +} + +( function( $ ) { + foo(function( value ) { + value.bind( function( newval ) { + $( '#bar' ).html( newval ); + } ); + } )( jQuery ); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc new file mode 100644 index 000000000..c30e5b8dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc @@ -0,0 +1,1659 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent true + +hello(); + } + + function hello() + { + echo 'hello'; +}//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +	$safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): +if ($bar) $foo = 1; +elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { +if (false) { +echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( +'some long description', function () { + }); +} + +switch ( $a ) { +case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + +case 'b': + $b = 3; +?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, +false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => +$value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +foo(function ($foo) { + return [ + match ($foo) { + } + ]; +}); + +// Issue #110. +echo match (1) { + 0 => match (2) { + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, + 1 => match (2) { + 1 => match (3) { + 3 => 3, + default => -1, + }, + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, +}; + +// Issue #437. +match (true) { + default => [ + 'unrelated' => '', + 'example' => array_filter( + array_map( + function () { + return null; + }, + [] + ) + ) + ] +}; + +// Issue squizlabs/PHP_CodeSniffer#3808 +function test() { + yield + from [ 3, 4 ]; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed new file mode 100644 index 000000000..4660f7588 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.2.inc.fixed @@ -0,0 +1,1659 @@ +phpcs:set Generic.WhiteSpace.ScopeIndent tabIndent true + +hello(); + } + + function hello() + { + echo 'hello'; + }//end hello() + + function hello2() + { + if (TRUE) { + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; + } + + while (TRUE) { + echo 'hello'; + } + + do { + echo 'hello'; + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +	$safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* This is a T_COMMENT + * + * + * + */ + + /** This is a T_DOC_COMMENT + */ + + /* + This T_COMMENT has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + + + + doSomething( + function () { + echo 123; + } + ); + } +} + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +some_function( + function() { + $a = 403; + if ($a === 404) { + $a = 403; + } + } +); + +$myFunction = function() { + $a = 403; + if ($a === 404) { + $a = 403; + } +}; + +class Whatever +{ + protected $_protectedArray = array( + 'normalString' => 'That email address is already in use!', + 'offendingString' => <<<'STRING' +Each line of this string is always said to be at column 0, + no matter how many spaces are placed + at the beginning of each line +and the ending STRING on the next line is reported as having to be indented. +STRING + ); +} + +class MyClass +{ + public static function myFunction() + { + if (empty($keywords) === FALSE) { + $keywords = 'foo'; + $existing = 'foo'; + } + + return $keywords; + + }//end myFunction() + +}//end class + +$var = call_user_func( + $new_var = function () use (&$a) { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + } +); + +class AnonymousFn +{ + public function getAnonFn() + { + return array( + 'functions' => Array( + 'function1' => function ($a, $b, $c) { + $a = $b + $c; + $b = $c / 2; + return Array($a, $b, $c); + }, + ), + ); + } +} +?> + +
    + +
    +
    + +
    +
    + +
    + + "") { + $test = true; + } else { + $test = true; + } + } + ?> + + + +
    +
    +
    + +
    +
    +
    + + +

    some text

    + function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } +]; + +if ($foo) { + foreach ($bar as $baz) { + if ($baz) { + ?> +
    +
    +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + 1) { + echo '1'; + } + ?> +
    + +<?= CHtml::encode($this->pageTitle); ?> + +expects($this->at(2)) + ->with($this->callback( + function ($subject) + { + } + ) + ); + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +echo $string->append('foo') + ->appaend('bar') + ->appaend('baz') + ->outputUsing( + function () + { + } + ); + +echo PHP_EOL; + +switch ($arg) { + case 1: + break; + case 2: + if ($arg2 == 'foo') { + } + case 3: + default: + echo 'default'; +} + +if ($tokens[$stackPtr]['content']{0} === '#') { +} else if ($tokens[$stackPtr]['content']{0} === '/' + && $tokens[$stackPtr]['content']{1} === '/' +) { +} + +$var = call_user_func( + function() { + if ($foo) { + $new_var = function() { + if ($a > 0) { + return $a++; + } else { + return $a--; + } + }; + } + } +); + +a( + function() { + $a = function() { + $b = false; + }; + true; + } +); + +$var = [ + [ + '1' => + function () { + return true; + }, + ], + [ + '1' => + function () { + return true; + }, + '2' => true, + ] +]; + +if ($foo) { + ?> +

    + self::_replaceKeywords($failingComment, $result), + 'screenshot' => Test::getScreenshotPath( + $projectid, + $result['class_name'], + ), + ); + +} + +$this->mockedDatabase + ->with( + $this->callback( + function () { + return; + } + ) + ); + +$this->subject->recordLogin(); + +function a() +{ + if (true) { + static::$a[$b] = + static::where($c) + ->where($c) + ->where( + function ($d) { + $d->whereNull(); + $d->orWhere(); + } + ) + ->first(); + + if (static::$a[$b] === null) { + static::$a[$b] = new static( + array( + 'a' => $a->id, + 'a' => $a->id, + ) + ); + } + } + + return static::$a[$b]; +} + +$foo->load( + array( + 'bar' => function ($baz) { + $baz->call(); + } + ) +); + +hello(); + +$foo = array_unique( + array_map( + function ($entry) { + return $entry * 2; + }, + array() + ) +); +bar($foo); + +class PHP_CodeSniffer_Tokenizers_JS +{ + + public $scopeOpeners = array( + T_CASE => array( + 'end' => array( + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + ), + 'strict' => true, + ), + ); +} + +echo $string-> + append('foo')-> + appaend('bar')-> + appaend('baz')-> + outputUsing( + function () + { + } + ); + +$str = 'the items I want to show are: ' . + implode( + ', ', + array('a', 'b', 'c') + ); + +echo $str; + +$str = 'foo' + . '1' + . '2'; + +echo $str; + +bar([ + 'foo' => foo(function () { + return 'foo'; + }) +]); + +$domains = array_unique( + array_map( + function ($url) { + $urlObject = new \Purl\Url($url); + return $urlObject->registerableDomain; + }, + $sites + ) +); + +return $domains; + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +if ($foo): + if ($bar) $foo = 1; + elseif ($baz) $foo = 2; +endif; + +$this + ->method(array( + 'foo' => 'bar', + ), 'arg', array( + 'foo' => 'bar', + )); + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +class Foo +{ + use Bar { + myMethod as renamedMethod; + } +} + +foo(); + +array( + 'key1' => function ($bar) { + return $bar; + }, + 'key2' => function ($foo) { + return $foo; + }, +); + +?> + + 1, + ]; +$c = 2; + +class foo +{ + public function get() + { + $foo = ['b' => 'c', + 'd' => [ + ['e' => 'f'] + ]]; + echo '42'; + + $foo = array('b' => 'c', + 'd' => array( + array('e' => 'f') + )); + echo '42'; + } +} + +switch ($foo) { + case 1: + return array(); + case 2: + return ''; + case 3: + return $function(); + case 4: + return $functionCall($param[0]); + case 5: + return array() + array(); // Array Merge + case 6: + // String connect + return $functionReturningString('') . $functionReturningString(array()); + case 7: + return functionCall( + $withMultiLineParam[0], + array(), + $functionReturningString( + $withMultiLineParam[1] + ) + ); + case 8: + return $param[0][0]; +} + +class Test { + + public + $foo + ,$bar + ,$baz = [ ] + ; + + public function wtfindent() { + } +} + +switch ($x) { + case 1: + return [1]; + default: + return [2]; +} + +switch ($foo) { + case self::FOO: + return $this->bar($gfoo, function ($id) { + return FOO::bar($id); + }, $values); + case self::BAR: + $values = $this->bar($foo, $values); + break; +} + +$var = array( + 'long description' => + array(0, 'something'), + 'another long description' => + array(1, "something else") +); + +$services = array( + 'service 1' => + Mockery::mock('class 1') + ->shouldReceive('setFilter')->once() + ->shouldReceive('getNbResults')->atLeast()->once() + ->shouldReceive('getSlice')->once()->andReturn(array()) + ->getMock(), + 'service 2' => + Mockery::mock('class 2') + ->shouldReceive('__invoke')->once() + ->getMock() +); + +class Foo +{ + public function setUp() + { + $this->foo = new class { + public $name = 'Some value'; + }; + } +} + +try { + foo(); +} catch (\Exception $e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +if ($foo) { + foo(); +} else if ($e) { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} else { + $foo = function() { + return 'foo'; + }; + + if (true) { + } +} + +switch ($parameter) { + case null: + return [ + 'foo' => in_array( + 'foo', + [] + ), + ]; + + default: + return []; +} + +class SomeClass +{ + public function someFunc() + { + a(function () { + echo "a"; + })->b(function () { + echo "b"; + }); + + if (true) { + echo "c"; + } + echo "d"; + } +} + +$params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + +$framework = api::read_framework($params['id']); +self::validate_context($framework->get_context()); +$output = $PAGE->get_renderer('tool_lp'); + +class Test123 +{ + protected static + $prop1 = [ + 'testA' => 123, + ], + $prop2 = [ + 'testB' => 456, + ]; + + protected static + $prop3 = array( + 'testA' => 123, + ), + $prop4 = array( + 'testB' => 456, + ); + + protected static $prop5; +} + +$foo = foo( + function () { + $foo->debug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +if (somethingIsTrue()) { + ?> +
    + +
    + bar(foo(function () { + }), foo(function () { + })); + +echo 'foo'; + +class Test { + + public function a() { + ?>adebug( + $a, + $b + ); + + if ($a) { + $b = $a; + } + } +); + +function test() +{ + $array = []; + foreach ($array as $data) { + [ + 'key1' => $var1, + 'key2' => $var2, + ] = $data; + foreach ($var1 as $method) { + echo $method . $var2; + } + } +} + +switch ($a) { + case 0: + $a = function () { + }; + case 1: + break; +} + +class Test +{ + public function __construct() + { + if (false) { + echo 0; + } + } +} + +return [ + 'veryLongKeySoIWantToMakeALineBreak' + => 'veryLonValueSoIWantToMakeALineBreak', + + 'someOtherKey' => [ + 'someValue' + ], + + 'arrayWithArraysInThere' => [ + ['Value1', 'Value1'] + ], +]; + +switch ($sContext) { + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +array_map( + static function ( $item ) { + echo $item; + }, + $some_array +); + +/** + * Comment. + */ +$a(function () use ($app) { + echo 'hi'; +})(); + +$app->run(); + +function foo() +{ + $foo('some + long description', function () { + }); + + $foo('some + long + description', function () { + }); + + $foo( + 'some long description', function () { + }); +} + +switch ( $a ) { + case 'a': + $b = 2; + /** + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'aa': + $b = 2; + /* + * A comment. + */ + apply_filter( 'something', $b ); + break; + + case 'b': + $b = 3; + ?> + + + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + [ + ], + 'b' => <<<'FOO' +foo; +FOO + ], + $a, +]; + +$query = Model::query() + ->when($a, function () { + static $b = ''; + }); + +$result = array_map( + static fn(int $number) : int => $number + 1, + $numbers +); + +$a = $a === true ? [ + 'a' => 1, + ] : [ + 'a' => 100, +]; + +return [ + Url::make('View Song', fn($song) => $song->url()) + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +echo $string?->append('foo') + ?->outputUsing(); + +// phpcs:set Generic.WhiteSpace.ScopeIndent exact true +echo $string?->append('foo') + ?->outputUsing(); +// phpcs:set Generic.WhiteSpace.ScopeIndent exact false + +if (true) { + ?> null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ($value) { + '' => null, + false => false, + 1, 2, 3 => true, + default => $value, +}; + +$value = match ( + $value + ) { + '' => null, + false + => false, + 1, + 2, + 3 => true, + default => + $value, +}; + +function toString(): string +{ + return sprintf( + '%s', + match ($type) { + 'foo' => 'bar', + }, + ); +} + +$list = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + }, + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + $list2 = [ + 'fn' => function ($a) { + if ($a === true) { + echo 'hi'; + } + } + ]; + } + } +]; + +$foo = match ($type) { + 'a' => [ + 'aa' => 'DESC', + 'ab' => 'DESC', + ], + 'b' => [ + 'ba' => 'DESC', + 'bb' => 'DESC', + ], + default => [ + 'da' => 'DESC', + ], +}; + +$a = [ + 'a' => [ + 'a' => fn () => foo() + ], + 'a' => [ + 'a' => 'a', + ] +]; + +switch ($foo) { + case 'a': + $foo = match ($foo) { + 'bar' => 'custom_1', + default => 'a' + }; + return $foo; + case 'b': + return match ($foo) { + 'bar' => 'custom_1', + default => 'b' + }; + default: + return 'default'; +} + +foo(function ($foo) { + return [ + match ($foo) { + } + ]; +}); + +// Issue #110. +echo match (1) { + 0 => match (2) { + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, + 1 => match (2) { + 1 => match (3) { + 3 => 3, + default => -1, + }, + 2 => match (3) { + 3 => 3, + default => -1, + }, + }, +}; + +// Issue #437. +match (true) { + default => [ + 'unrelated' => '', + 'example' => array_filter( + array_map( + function () { + return null; + }, + [] + ) + ) + ] +}; + +// Issue squizlabs/PHP_CodeSniffer#3808 +function test() { + yield + from [ 3, 4 ]; +} + +/* ADD NEW TESTS ABOVE THIS LINE AND MAKE SURE THAT THE 1 (space-based) AND 2 (tab-based) FILES ARE IN SYNC! */ +?> + + + + + + + <<<'INTRO' + lorem ipsum + INTRO, + 'em' => [ + [ + '', + ], + ], + 'abc' => [ + 'a' => 'wop wop', + 'b' => 'ola ola.', + ], +]; + +echo "" diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc new file mode 100644 index 000000000..dd095617c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc @@ -0,0 +1,34 @@ + $enabled, + 'compression' => $compression, + ] = $options; +} + +$this->foo() + ->bar() + ->baz(); + +// Issue squizlabs/PHP_CodeSniffer#3808 +function test() { + yield + from [ 3, 4 ]; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed new file mode 100644 index 000000000..aaa0b1c81 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.3.inc.fixed @@ -0,0 +1,34 @@ + $enabled, + 'compression' => $compression, + ] = $options; +} + +$this->foo() + ->bar() + ->baz(); + +// Issue squizlabs/PHP_CodeSniffer#3808 +function test() { + yield + from [ 3, 4 ]; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc new file mode 100644 index 000000000..e58dc4de7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.4.inc @@ -0,0 +1,6 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ScopeIndent sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ScopeIndentSniff + */ +final class ScopeIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + // Tab width setting is only needed for the tabbed file. + if ($testFile === 'ScopeIndentUnitTest.2.inc') { + $config->tabWidth = 4; + } else { + $config->tabWidth = 0; + } + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile === 'ScopeIndentUnitTest.1.js') { + return [ + 6 => 1, + 14 => 1, + 21 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 39 => 1, + 42 => 1, + 59 => 1, + 60 => 1, + 75 => 1, + 120 => 1, + 121 => 1, + 122 => 1, + 123 => 1, + 141 => 1, + 142 => 1, + 155 => 1, + 156 => 1, + 168 => 1, + 184 => 1, + ]; + }//end if + + if ($testFile === 'ScopeIndentUnitTest.3.inc') { + return [ + 6 => 1, + 7 => 1, + 10 => 1, + 33 => 1, + ]; + } + + if ($testFile === 'ScopeIndentUnitTest.4.inc') { + return []; + } + + return [ + 7 => 1, + 10 => 1, + 13 => 1, + 17 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 58 => 1, + 123 => 1, + 224 => 1, + 225 => 1, + 279 => 1, + 280 => 1, + 281 => 1, + 282 => 1, + 283 => 1, + 284 => 1, + 285 => 1, + 286 => 1, + 336 => 1, + 349 => 1, + 380 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 389 => 1, + 390 => 1, + 397 => 1, + 419 => 1, + 420 => 1, + 465 => 1, + 467 => 1, + 472 => 1, + 473 => 1, + 474 => 1, + 496 => 1, + 498 => 1, + 500 => 1, + 524 => 1, + 526 => 1, + 544 => 1, + 545 => 1, + 546 => 1, + 639 => 1, + 660 => 1, + 662 => 1, + 802 => 1, + 803 => 1, + 823 => 1, + 858 => 1, + 879 => 1, + 1163 => 1, + 1197 => 1, + 1198 => 1, + 1259 => 1, + 1264 => 1, + 1265 => 1, + 1266 => 1, + 1269 => 1, + 1272 => 1, + 1273 => 1, + 1274 => 1, + 1275 => 1, + 1276 => 1, + 1277 => 1, + 1280 => 1, + 1281 => 1, + 1282 => 1, + 1284 => 1, + 1285 => 1, + 1288 => 1, + 1289 => 1, + 1290 => 1, + 1292 => 1, + 1293 => 1, + 1310 => 1, + 1312 => 1, + 1327 => 1, + 1328 => 1, + 1329 => 1, + 1330 => 1, + 1331 => 1, + 1332 => 1, + 1335 => 1, + 1340 => 1, + 1342 => 1, + 1345 => 1, + 1488 => 1, + 1489 => 1, + 1500 => 1, + 1503 => 1, + 1518 => 1, + 1520 => 1, + 1527 => 1, + 1529 => 1, + 1530 => 1, + 1631 => 1, + 1632 => 1, + 1633 => 1, + 1634 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.1.inc new file mode 100644 index 000000000..6c86ac0b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/Tests/WhiteSpace/SpreadOperatorSpacingAfterUnitTest.1.inc @@ -0,0 +1,78 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Generic\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SpreadOperatorSpacingAfter sniff. + * + * @covers \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\SpreadOperatorSpacingAfterSniff + */ +final class SpreadOperatorSpacingAfterUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SpreadOperatorSpacingAfterUnitTest.1.inc': + return [ + 12 => 1, + 13 => 1, + 20 => 2, + 40 => 1, + 41 => 1, + 46 => 2, + 60 => 1, + 61 => 1, + 66 => 2, + 78 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml new file mode 100644 index 000000000..728426e6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Generic/ruleset.xml @@ -0,0 +1,4 @@ + + + A collection of generic sniffs. This standard is not designed to be used to check code. + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php new file mode 100644 index 000000000..904769e12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\CSS; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class BrowserSpecificStylesSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of specific stylesheet suffixes we allow. + * + * These stylesheets contain browser specific styles + * so this sniff ignore them files in the form: + * *_moz.css and *_ie7.css etc. + * + * @var array + */ + protected $specificStylesheets = [ + 'moz' => true, + 'ie' => true, + 'ie7' => true, + 'ie8' => true, + 'webkit' => true, + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Ignore files with browser-specific suffixes. + $filename = $phpcsFile->getFilename(); + $breakChar = strrpos($filename, '_'); + if ($breakChar !== false && substr($filename, -4) === '.css') { + $specific = substr($filename, ($breakChar + 1), -4); + if (isset($this->specificStylesheets[$specific]) === true) { + return; + } + } + + $tokens = $phpcsFile->getTokens(); + $content = $tokens[$stackPtr]['content']; + + if ($content[0] === '-') { + $error = 'Browser-specific styles are not allowed'; + $phpcsFile->addError($error, $stackPtr, 'ForbiddenStyle'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php new file mode 100644 index 000000000..91004a84d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php @@ -0,0 +1,127 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowSelfActionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We are not interested in abstract classes. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($prev !== false && $tokens[$prev]['code'] === T_ABSTRACT) { + return; + } + + // We are only interested in Action classes. + $classNameToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $className = $tokens[$classNameToken]['content']; + if (substr($className, -7) !== 'Actions') { + return; + } + + $foundFunctions = []; + $foundCalls = []; + + // Find all static method calls in the form self::method() in the class. + $classEnd = $tokens[$stackPtr]['scope_closer']; + for ($i = ($classNameToken + 1); $i < $classEnd; $i++) { + if ($tokens[$i]['code'] !== T_DOUBLE_COLON) { + if ($tokens[$i]['code'] === T_FUNCTION) { + // Cache the function information. + $funcName = $phpcsFile->findNext(T_STRING, ($i + 1)); + $funcScope = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($i - 1)); + + $foundFunctions[$tokens[$funcName]['content']] = strtolower($tokens[$funcScope]['content']); + } + + continue; + } + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($tokens[$prevToken]['content'] !== 'self' + && $tokens[$prevToken]['content'] !== 'static' + ) { + continue; + } + + $funcNameToken = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$funcNameToken]['code'] === T_VARIABLE) { + // We are only interested in function calls. + continue; + } + + $funcName = $tokens[$funcNameToken]['content']; + + // We've found the function, now we need to find it and see if it is + // public, private or protected. If it starts with an underscore we + // can assume it is private. + if ($funcName[0] === '_') { + continue; + } + + $foundCalls[$i] = [ + 'name' => $funcName, + 'type' => strtolower($tokens[$prevToken]['content']), + ]; + }//end for + + $errorClassName = substr($className, 0, -7); + + foreach ($foundCalls as $token => $funcData) { + if (isset($foundFunctions[$funcData['name']]) === false) { + // Function was not in this class, might have come from the parent. + // Either way, we can't really check this. + continue; + } else if ($foundFunctions[$funcData['name']] === 'public') { + $type = $funcData['type']; + $error = "Static calls to public methods in Action classes must not use the $type keyword; use %s::%s() instead"; + $data = [ + $errorClassName, + $funcName, + ]; + $phpcsFile->addError($error, $token, 'Found'.ucfirst($funcData['type']), $data); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php new file mode 100644 index 000000000..83bb5ff31 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php @@ -0,0 +1,100 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class IncludeOwnSystemSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $fileName = $phpcsFile->getFilename(); + $matches = []; + if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|i', $fileName, $matches) === 0) { + // Not an actions file. + return; + } + + $ownClass = $matches[2]; + $tokens = $phpcsFile->getTokens(); + + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 2), null, false, true); + $typeName = trim($tokens[$typeName]['content'], " '"); + switch (strtolower($tokens[($stackPtr + 1)]['content'])) { + case 'includesystem' : + $included = strtolower($typeName); + break; + case 'includeasset' : + $included = strtolower($typeName).'assettype'; + break; + case 'includewidget' : + $included = strtolower($typeName).'widgettype'; + break; + default: + return; + } + + if ($included === strtolower($ownClass)) { + $error = "You do not need to include \"%s\" from within the system's own actions file"; + $data = [$ownClass]; + $phpcsFile->addError($error, $stackPtr, 'NotRequired', $data); + } + + }//end process() + + + /** + * Determines the included class name from given token. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param array $tokens The array of file tokens. + * @param int $stackPtr The position in the tokens array of the + * potentially included class. + * + * @return bool + */ + protected function getIncludedClassFromToken( + $phpcsFile, + array $tokens, + $stackPtr + ) { + + return false; + + }//end getIncludedClassFromToken() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php new file mode 100644 index 000000000..063dab4a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php @@ -0,0 +1,316 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class IncludeSystemSniff extends AbstractScopeSniff +{ + + /** + * A list of classes that don't need to be included. + * + * @var array + */ + private $ignore = [ + 'self' => true, + 'static' => true, + 'parent' => true, + 'channels' => true, + 'basesystem' => true, + 'dal' => true, + 'init' => true, + 'pdo' => true, + 'util' => true, + 'ziparchive' => true, + 'phpunit_framework_assert' => true, + 'abstractmysourceunittest' => true, + 'abstractdatacleanunittest' => true, + 'exception' => true, + 'abstractwidgetwidgettype' => true, + 'domdocument' => true, + ]; + + + /** + * Constructs an AbstractScopeSniff. + */ + public function __construct() + { + parent::__construct([T_FUNCTION], [T_DOUBLE_COLON, T_EXTENDS], true); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param integer $stackPtr The position where the token was found. + * @param integer $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine the name of the class that the static function + // is being called on. + $classNameToken = $phpcsFile->findPrevious( + T_WHITESPACE, + ($stackPtr - 1), + null, + true + ); + + // Don't process class names represented by variables as this can be + // an inexact science. + if ($tokens[$classNameToken]['code'] === T_VARIABLE) { + return; + } + + $className = $tokens[$classNameToken]['content']; + if (isset($this->ignore[strtolower($className)]) === true) { + return; + } + + $includedClasses = []; + + $fileName = strtolower($phpcsFile->getFilename()); + $matches = []; + if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) { + // This is an actions file, which means we don't + // have to include the system in which it exists. + $includedClasses[$matches[2]] = true; + + // Or a system it implements. + $class = $phpcsFile->getCondition($stackPtr, T_CLASS); + $implements = $phpcsFile->findNext(T_IMPLEMENTS, $class, ($class + 10)); + if ($implements !== false) { + $implementsClass = $phpcsFile->findNext(T_STRING, $implements); + $implementsClassName = strtolower($tokens[$implementsClass]['content']); + if (substr($implementsClassName, -7) === 'actions') { + $includedClasses[substr($implementsClassName, 0, -7)] = true; + } + } + } + + // Go searching for includeSystem and includeAsset calls within this + // function, or the inclusion of .inc files, which + // would be library files. + for ($i = ($currScope + 1); $i < $stackPtr; $i++) { + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + // Special case for Widgets cause they are, well, special. + } else if (strtolower($tokens[$i]['content']) === 'includewidget') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + $includedClasses[strtolower($typeName).'widgettype'] = true; + } + } + + // Now go searching for includeSystem, includeAsset or require/include + // calls outside our scope. If we are in a class, look outside the + // class. If we are not, look outside the function. + $condPtr = $currScope; + if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) { + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) { + if ($condType === T_CLASS) { + break; + } + } + } + + for ($i = 0; $i < $condPtr; $i++) { + // Skip other scopes. + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + } + } + + // If we are in a testing class, we might have also included + // some systems and classes in our setUp() method. + $setupFunction = null; + if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) { + foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) { + if ($condType === T_CLASS) { + // Is this is a testing class? + $name = $phpcsFile->findNext(T_STRING, $condPtr); + $name = $tokens[$name]['content']; + if (substr($name, -8) === 'UnitTest') { + // Look for a method called setUp(). + $end = $tokens[$condPtr]['scope_closer']; + $function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end); + while ($function !== false) { + $name = $phpcsFile->findNext(T_STRING, $function); + if ($tokens[$name]['content'] === 'setUp') { + $setupFunction = $function; + break; + } + + $function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end); + } + } + } + }//end foreach + }//end if + + if ($setupFunction !== null) { + $start = ($tokens[$setupFunction]['scope_opener'] + 1); + $end = $tokens[$setupFunction]['scope_closer']; + for ($i = $start; $i < $end; $i++) { + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + } + } + }//end if + + if (isset($includedClasses[strtolower($className)]) === false) { + $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token within the scope that this test is listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * this token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_EXTENDS) { + // Find the class name. + $classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1)); + $className = $tokens[$classNameToken]['content']; + } else { + // Determine the name of the class that the static function + // is being called on. But don't process class names represented by + // variables as this can be an inexact science. + $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$classNameToken]['code'] === T_VARIABLE) { + return; + } + + $className = $tokens[$classNameToken]['content']; + } + + // Some systems are always available. + if (isset($this->ignore[strtolower($className)]) === true) { + return; + } + + $includedClasses = []; + + $fileName = strtolower($phpcsFile->getFilename()); + $matches = []; + if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) { + // This is an actions file, which means we don't + // have to include the system in which it exists + // We know the system from the path. + $includedClasses[$matches[1]] = true; + } + + // Go searching for includeSystem, includeAsset or require/include + // calls outside our scope. + for ($i = 0; $i < $stackPtr; $i++) { + // Skip classes and functions as will we never get + // into their scopes when including this file, although + // we have a chance of getting into IF, WHILE etc. + if (($tokens[$i]['code'] === T_CLASS + || $tokens[$i]['code'] === T_INTERFACE + || $tokens[$i]['code'] === T_FUNCTION) + && isset($tokens[$i]['scope_closer']) === true + ) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i); + if ($name !== false) { + $includedClasses[$name] = true; + // Special case for Widgets cause they are, well, special. + } else if (strtolower($tokens[$i]['content']) === 'includewidget') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + $includedClasses[strtolower($typeName).'widgettype'] = true; + } + }//end for + + if (isset($includedClasses[strtolower($className)]) === false) { + if ($tokens[$stackPtr]['code'] === T_EXTENDS) { + $error = 'Class extends non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedExtends', $data); + } else { + $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once'; + $data = [$className]; + $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data); + } + } + + }//end processTokenOutsideScope() + + + /** + * Determines the included class name from given token. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param array $tokens The array of file tokens. + * @param int $stackPtr The position in the tokens array of the + * potentially included class. + * + * @return string|false + */ + protected function getIncludedClassFromToken(File $phpcsFile, array $tokens, $stackPtr) + { + if (strtolower($tokens[$stackPtr]['content']) === 'includesystem') { + $systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $systemName = trim($tokens[$systemName]['content'], " '"); + return strtolower($systemName); + } else if (strtolower($tokens[$stackPtr]['content']) === 'includeasset') { + $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $typeName = trim($tokens[$typeName]['content'], " '"); + return strtolower($typeName).'assettype'; + } else if (isset(Tokens::$includeTokens[$tokens[$stackPtr]['code']]) === true) { + $filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1)); + $filePath = $tokens[$filePath]['content']; + $filePath = trim($filePath, " '"); + $filePath = basename($filePath, '.inc'); + return strtolower($filePath); + } + + return false; + + }//end getIncludedClassFromToken() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php new file mode 100644 index 000000000..0f20f70b9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php @@ -0,0 +1,143 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Channels; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class UnusedSystemSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check if this is a call to includeSystem, includeAsset or includeWidget. + $methodName = strtolower($tokens[($stackPtr + 1)]['content']); + if ($methodName === 'includesystem' + || $methodName === 'includeasset' + || $methodName === 'includewidget' + ) { + $systemName = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 3), null, true); + if ($systemName === false || $tokens[$systemName]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + // Must be using a variable instead of a specific system name. + // We can't accurately check that. + return; + } + + $systemName = trim($tokens[$systemName]['content'], " '"); + } else { + return; + } + + if ($methodName === 'includeasset') { + $systemName .= 'assettype'; + } else if ($methodName === 'includewidget') { + $systemName .= 'widgettype'; + } + + $systemName = strtolower($systemName); + + // Now check if this system is used anywhere in this scope. + $level = $tokens[$stackPtr]['level']; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['level'] < $level) { + // We have gone out of scope. + // If the original include was inside an IF statement that + // is checking if the system exists, check the outer scope + // as well. + if ($tokens[$stackPtr]['level'] === $level) { + // We are still in the base level, so this is the first + // time we have got here. + $conditions = array_keys($tokens[$stackPtr]['conditions']); + if (empty($conditions) === false) { + $cond = array_pop($conditions); + if ($tokens[$cond]['code'] === T_IF) { + $i = $tokens[$cond]['scope_closer']; + $level--; + continue; + } + } + } + + break; + }//end if + + if ($tokens[$i]['code'] !== T_DOUBLE_COLON + && $tokens[$i]['code'] !== T_EXTENDS + && $tokens[$i]['code'] !== T_IMPLEMENTS + ) { + continue; + } + + switch ($tokens[$i]['code']) { + case T_DOUBLE_COLON: + $usedName = strtolower($tokens[($i - 1)]['content']); + if ($usedName === $systemName) { + // The included system was used, so it is fine. + return; + } + break; + case T_EXTENDS: + $classNameToken = $phpcsFile->findNext(T_STRING, ($i + 1)); + $className = strtolower($tokens[$classNameToken]['content']); + if ($className === $systemName) { + // The included system was used, so it is fine. + return; + } + break; + case T_IMPLEMENTS: + $endImplements = $phpcsFile->findNext([T_EXTENDS, T_OPEN_CURLY_BRACKET], ($i + 1)); + for ($x = ($i + 1); $x < $endImplements; $x++) { + if ($tokens[$x]['code'] === T_STRING) { + $className = strtolower($tokens[$x]['content']); + if ($className === $systemName) { + // The included system was used, so it is fine. + return; + } + } + } + break; + }//end switch + }//end for + + // If we get to here, the system was not use. + $error = 'Included system "%s" is never used'; + $data = [$systemName]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 000000000..da00c903f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Commenting; + +use PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FunctionCommentSniff as SquizFunctionCommentSniff; +use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Files\File; + +class FunctionCommentSniff extends SquizFunctionCommentSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + parent::process($phpcsFile, $stackPtr); + + $tokens = $phpcsFile->getTokens(); + $find = Tokens::$methodPrefixes; + $find[] = T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + $hasApiTag = false; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@api') { + if ($hasApiTag === true) { + // We've come across an API tag already, which means + // we were not the first tag in the API list. + $error = 'The @api tag must come first in the @api tag list in a function comment'; + $phpcsFile->addError($error, $tag, 'ApiNotFirst'); + } + + $hasApiTag = true; + + // There needs to be a blank line before the @api tag. + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], ($tag - 1)); + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 2)) { + $error = 'There must be one blank line before the @api tag in a function comment'; + $phpcsFile->addError($error, $tag, 'ApiSpacing'); + } + } else if (substr($tokens[$tag]['content'], 0, 5) === '@api-') { + $hasApiTag = true; + + $prev = $phpcsFile->findPrevious([T_DOC_COMMENT_STRING, T_DOC_COMMENT_TAG], ($tag - 1)); + if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) { + $error = 'There must be no blank line before the @%s tag in a function comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addError($error, $tag, 'ApiTagSpacing', $data); + } + }//end if + }//end foreach + + if ($hasApiTag === true && substr($tokens[$tag]['content'], 0, 4) !== '@api') { + // API tags must be the last tags in a function comment. + $error = 'The @api tags must be the last tags in a function comment'; + $phpcsFile->addError($error, $commentEnd, 'ApiNotLast'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php new file mode 100644 index 000000000..d40e064e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class DebugCodeSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOUBLE_COLON]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if (strtolower($tokens[$className]['content']) === 'debug') { + $method = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $error = 'Call to debug function Debug::%s() must be removed'; + $data = [$tokens[$method]['content']]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php new file mode 100644 index 000000000..1f56a0e28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class FirebugConsoleSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_STRING, + T_PROPERTY, + T_LABEL, + T_OBJECT, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (strtolower($tokens[$stackPtr]['content']) === 'console') { + $error = 'Variables, functions and labels must not be named "console"; name may conflict with Firebug internal variable'; + $phpcsFile->addError($error, $stackPtr, 'ConflictFound'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php new file mode 100644 index 000000000..97732872c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/AssignThisSniff.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class AssignThisSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_THIS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore this.something and other uses of "this" that are not + // direct assignments. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] !== T_SEMICOLON) { + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + return; + } + } + + // Something must be assigned to "this". + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_EQUAL) { + return; + } + + // A variable needs to be assigned to "this". + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true); + if ($tokens[$prev]['code'] !== T_STRING) { + return; + } + + // We can only assign "this" to a var called "self". + if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') { + $error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"'; + $phpcsFile->addError($error, $prev, 'NotSelf'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php new file mode 100644 index 000000000..5d8dc9968 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php @@ -0,0 +1,220 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class CreateWidgetTypeCallbackSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OBJECT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findPrevious(T_STRING, ($stackPtr - 1)); + if (substr(strtolower($tokens[$className]['content']), -10) !== 'widgettype') { + return; + } + + // Search for a create method. + $create = $phpcsFile->findNext(T_PROPERTY, $stackPtr, $tokens[$stackPtr]['bracket_closer'], null, 'create'); + if ($create === false) { + return; + } + + $function = $phpcsFile->findNext([T_WHITESPACE, T_COLON], ($create + 1), null, true); + if ($tokens[$function]['code'] !== T_FUNCTION + && $tokens[$function]['code'] !== T_CLOSURE + ) { + return; + } + + $start = ($tokens[$function]['scope_opener'] + 1); + $end = ($tokens[$function]['scope_closer'] - 1); + + // Check that the first argument is called "callback". + $arg = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$function]['parenthesis_opener'] + 1), null, true); + if ($tokens[$arg]['content'] !== 'callback') { + $error = 'The first argument of the create() method of a widget type must be called "callback"'; + $phpcsFile->addError($error, $arg, 'FirstArgNotCallback'); + } + + /* + Look for return statements within the function. They cannot return + anything and must be preceded by the callback.call() line. The + callback itself must contain "self" or "this" as the first argument + and there needs to be a call to the callback function somewhere + in the create method. All calls to the callback function must be + followed by a return statement or the end of the method. + */ + + $foundCallback = false; + $passedCallback = false; + $nestedFunction = null; + for ($i = $start; $i <= $end; $i++) { + // Keep track of nested functions. + if ($nestedFunction !== null) { + if ($i === $nestedFunction) { + $nestedFunction = null; + continue; + } + } else if (($tokens[$i]['code'] === T_FUNCTION + || $tokens[$i]['code'] === T_CLOSURE) + && isset($tokens[$i]['scope_closer']) === true + ) { + $nestedFunction = $tokens[$i]['scope_closer']; + continue; + } + + if ($nestedFunction === null && $tokens[$i]['code'] === T_RETURN) { + // Make sure return statements are not returning anything. + if ($tokens[($i + 1)]['code'] !== T_SEMICOLON) { + $error = 'The create() method of a widget type must not return a value'; + $phpcsFile->addError($error, $i, 'ReturnValue'); + } + + continue; + } else if ($tokens[$i]['code'] !== T_STRING + || $tokens[$i]['content'] !== 'callback' + ) { + continue; + } + + // If this is the form "callback.call(" then it is a call + // to the callback function. + if ($tokens[($i + 1)]['code'] !== T_OBJECT_OPERATOR + || $tokens[($i + 2)]['content'] !== 'call' + || $tokens[($i + 3)]['code'] !== T_OPEN_PARENTHESIS + ) { + // One last chance; this might be the callback function + // being passed to another function, like this + // "this.init(something, callback, something)". + if (isset($tokens[$i]['nested_parenthesis']) === false) { + continue; + } + + // Just make sure those brackets don't belong to anyone, + // like an IF or FOR statement. + foreach ($tokens[$i]['nested_parenthesis'] as $bracket) { + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + continue(2); + } + } + + // Note that we use this endBracket down further when checking + // for a RETURN statement. + $nestedParens = $tokens[$i]['nested_parenthesis']; + $endBracket = end($nestedParens); + $bracket = key($nestedParens); + + $prev = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($bracket - 1), + null, + true + ); + + if ($tokens[$prev]['code'] !== T_STRING) { + // This is not a function passing the callback. + continue; + } + + $passedCallback = true; + }//end if + + $foundCallback = true; + + if ($passedCallback === false) { + // The first argument must be "this" or "self". + $arg = $phpcsFile->findNext(T_WHITESPACE, ($i + 4), null, true); + if ($tokens[$arg]['content'] !== 'this' + && $tokens[$arg]['content'] !== 'self' + ) { + $error = 'The first argument passed to the callback function must be "this" or "self"'; + $phpcsFile->addError($error, $arg, 'FirstArgNotSelf'); + } + } + + // Now it must be followed by a return statement or the end of the function. + if ($passedCallback === false) { + $endBracket = $tokens[($i + 3)]['parenthesis_closer']; + } + + for ($next = $endBracket; $next <= $end; $next++) { + // Skip whitespace so we find the next content after the call. + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true) { + continue; + } + + // Skip closing braces like END IF because it is not executable code. + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + continue; + } + + // We don't care about anything on the current line, like a + // semicolon. It doesn't matter if there are other statements on the + // line because another sniff will check for those. + if ($tokens[$next]['line'] === $tokens[$endBracket]['line']) { + continue; + } + + break; + } + + if ($next !== $tokens[$function]['scope_closer'] + && $tokens[$next]['code'] !== T_RETURN + ) { + $error = 'The call to the callback function must be followed by a return statement if it is not the last statement in the create() method'; + $phpcsFile->addError($error, $i, 'NoReturn'); + } + }//end for + + if ($foundCallback === false) { + $error = 'The create() method of a widget type must call the callback function'; + $phpcsFile->addError($error, $create, 'CallbackNotCalled'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php new file mode 100644 index 000000000..693a03714 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Objects; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class DisallowNewWidgetSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$className]['code'] !== T_STRING) { + return; + } + + if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') { + $widgetType = substr($tokens[$className]['content'], 0, -10); + $error = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead'; + $data = [$widgetType]; + $phpcsFile->addError($error, $stackPtr, 'Found', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php new file mode 100644 index 000000000..06c251271 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class AjaxNullComparisonSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure it is an API function. We know this by the doc comment. + $commentEnd = $phpcsFile->findPrevious(T_DOC_COMMENT_CLOSE_TAG, $stackPtr); + $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT_OPEN_TAG, ($commentEnd - 1)); + // If function doesn't contain any doc comments - skip it. + if ($commentEnd === false || $commentStart === false) { + return; + } + + $comment = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart)); + if (strpos($comment, '* @api') === false) { + return; + } + + // Find all the vars passed in as we are only interested in comparisons + // to NULL for these specific variables. + $foundVars = []; + $open = $tokens[$stackPtr]['parenthesis_opener']; + $close = $tokens[$stackPtr]['parenthesis_closer']; + for ($i = ($open + 1); $i < $close; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + $foundVars[$tokens[$i]['content']] = true; + } + } + + if (empty($foundVars) === true) { + return; + } + + $start = $tokens[$stackPtr]['scope_opener']; + $end = $tokens[$stackPtr]['scope_closer']; + for ($i = ($start + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] !== T_VARIABLE + || isset($foundVars[$tokens[$i]['content']]) === false + ) { + continue; + } + + $operator = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$operator]['code'] !== T_IS_IDENTICAL + && $tokens[$operator]['code'] !== T_IS_NOT_IDENTICAL + ) { + continue; + } + + $nullValue = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), null, true); + if ($tokens[$nullValue]['code'] !== T_NULL) { + continue; + } + + $error = 'Values submitted via Ajax requests should not be compared directly to NULL; use empty() instead'; + $phpcsFile->addWarning($error, $nullValue, 'Found'); + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php new file mode 100644 index 000000000..6684691f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class EvalObjectFactorySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EVAL]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + /* + We need to find all strings that will be in the eval + to determine if the "new" keyword is being used. + */ + + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1)); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $strings = []; + $vars = []; + + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $strings[$i] = $tokens[$i]['content']; + } else if ($tokens[$i]['code'] === T_VARIABLE) { + $vars[$i] = $tokens[$i]['content']; + } + } + + /* + We now have some variables that we need to expand into + the strings that were assigned to them, if any. + */ + + foreach ($vars as $varPtr => $varName) { + while (($prev = $phpcsFile->findPrevious(T_VARIABLE, ($varPtr - 1))) !== false) { + // Make sure this is an assignment of the variable. That means + // it will be the first thing on the line. + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true); + if ($tokens[$prevContent]['line'] === $tokens[$prev]['line']) { + $varPtr = $prevContent; + continue; + } + + if ($tokens[$prev]['content'] !== $varName) { + // This variable has a different name. + $varPtr = $prevContent; + continue; + } + + // We found one. + break; + }//end while + + if ($prev !== false) { + // Find all strings on the line. + $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prev + 1)); + for ($i = ($prev + 1); $i < $lineEnd; $i++) { + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true) { + $strings[$i] = $tokens[$i]['content']; + } + } + } + }//end foreach + + foreach ($strings as $string) { + // If the string has "new" in it, it is not allowed. + // We don't bother checking if the word "new" is printed to screen + // because that is unlikely to happen. We assume the use + // of "new" is for object instantiation. + if (strstr($string, ' new ') !== false) { + $error = 'Do not use eval() to create objects dynamically; use reflection instead'; + $phpcsFile->addWarning($error, $stackPtr, 'Found'); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php new file mode 100644 index 000000000..a07677968 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php @@ -0,0 +1,108 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class GetRequestDataSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_VARIABLE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $varName = $tokens[$stackPtr]['content']; + if ($varName !== '$_REQUEST' + && $varName !== '$_GET' + && $varName !== '$_POST' + && $varName !== '$_FILES' + ) { + return; + } + + // The only place these super globals can be accessed directly is + // in the getRequestData() method of the Security class. + $inClass = false; + foreach ($tokens[$stackPtr]['conditions'] as $i => $type) { + if ($tokens[$i]['code'] === T_CLASS) { + $className = $phpcsFile->findNext(T_STRING, $i); + $className = $tokens[$className]['content']; + if (strtolower($className) === 'security') { + $inClass = true; + } else { + // We don't have nested classes. + break; + } + } else if ($inClass === true && $tokens[$i]['code'] === T_FUNCTION) { + $funcName = $phpcsFile->findNext(T_STRING, $i); + $funcName = $tokens[$funcName]['content']; + if (strtolower($funcName) === 'getrequestdata') { + // This is valid. + return; + } else { + // We don't have nested functions. + break; + } + }//end if + }//end foreach + + // If we get to here, the super global was used incorrectly. + // First find out how it is being used. + $globalName = strtolower(substr($varName, 2)); + $usedVar = ''; + + $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$openBracket]['code'] === T_OPEN_SQUARE_BRACKET) { + $closeBracket = $tokens[$openBracket]['bracket_closer']; + $usedVar = $phpcsFile->getTokensAsString(($openBracket + 1), ($closeBracket - $openBracket - 1)); + } + + $type = 'SuperglobalAccessed'; + $error = 'The %s super global must not be accessed directly; use Security::getRequestData('; + $data = [$varName]; + if ($usedVar !== '') { + $type .= 'WithVar'; + $error .= '%s, \'%s\''; + $data[] = $usedVar; + $data[] = $globalName; + } + + $error .= ') instead'; + $phpcsFile->addError($error, $stackPtr, $type, $data); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php new file mode 100644 index 000000000..697e91dc7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\PHP; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; + +class ReturnFunctionValueSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_RETURN]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $functionName = $phpcsFile->findNext(T_STRING, ($stackPtr + 1), null, false, null, true); + + while ($functionName !== false) { + // Check if this is really a function. + $bracket = $phpcsFile->findNext(T_WHITESPACE, ($functionName + 1), null, true); + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + $functionName = $phpcsFile->findNext(T_STRING, ($functionName + 1), null, false, null, true); + continue; + } + + $error = 'The result of a function call should be assigned to a variable before being returned'; + $phpcsFile->addWarning($error, $stackPtr, 'NotAssigned'); + break; + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php new file mode 100644 index 000000000..ee527b41b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\MySource\Sniffs\Strings; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Tokens; + +class JoinStringsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'] !== 'join') { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_SQUARE_BRACKET) { + $opener = $tokens[$prev]['bracket_opener']; + if ($tokens[($opener - 1)]['code'] !== T_STRING) { + // This means the array is declared inline, like x = [a,b,c].join() + // and not elsewhere, like x = y[a].join() + // The first is not allowed while the second is. + $error = 'Joining strings using inline arrays is not allowed; use the + operator instead'; + $phpcsFile->addError($error, $stackPtr, 'ArrayNotAllowed'); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css new file mode 100644 index 000000000..339ee1544 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css @@ -0,0 +1,13 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + line-height: -25px; + cursor: pointer; + -moz-user-select: none; +} + +.AssetLineageWidgetType-item { + float: left; + list-style: none; + height: 22px; + cursor: pointer; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php new file mode 100644 index 000000000..7f10457c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the BrowserSpecificStyles sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\CSS\BrowserSpecificStylesSniff + */ +final class BrowserSpecificStylesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [5 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc new file mode 100644 index 000000000..95fd04b79 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc @@ -0,0 +1,51 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php new file mode 100644 index 000000000..30a62d136 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowSelfActions sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Channels\DisallowSelfActionsSniff + */ +final class DisallowSelfActionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 28 => 1, + 29 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc new file mode 100644 index 000000000..ccb0273e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.inc @@ -0,0 +1,112 @@ +fetch(PDO::FETCH_NUM) +BaseSystem::getDataDir(); +Util::getArrayIndex(array(), ''); + + +Channels::includeSystem('Widget'); +Widget::includeWidget('AbstractContainer'); +class MyWidget extends AbstractContainerWidgetType {} +class MyOtherWidget extends BookWidgetType {} + +$zip = new ZipArchive(); +$res = $zip->open($path, ZipArchive::CREATE); + +class AssetListingUnitTest extends AbstractMySourceUnitTest +{ + function setUp() { + parent::setUp(); + Channels::includeSystem('MySystem2'); + include_once 'Libs/FileSystem.inc'; + } + + function two() { + $siteid = MySystem2::getCurrentSiteId(); + $parserFiles = FileSystem::listDirectory(); + } + + function three() { + $siteid = MySystem3::getCurrentSiteId(); + $parserFiles = FileSystem::listDirectory(); + } +} + +if (Channels::systemExists('Log') === TRUE) { + Channels::includeSystem('Log'); +} else { + return; +} + +Log::addProjectLog('metadata.field.update', $msg); + +function two() { + Widget::includeWidget('CacheAdminScreen'); + $barChart = CacheAdminScreenWidgetType::constructBarchart($data); +} + +$adjustDialog->setOrientation(AbstractWidgetWidgetType::CENTER); + +$className = 'SquizPerspective'.ucfirst($property['type']).'PropertyType'; +Channels::includeSystem($className); +$className::setValue($assetid, $propertyid, $perspectives, $value, (array) $property['settings']); +?> diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php new file mode 100644 index 000000000..635054d3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the IncludeSystem sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Channels\IncludeSystemSniff + */ +final class IncludeSystemUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 14 => 1, + 24 => 1, + 27 => 1, + 28 => 1, + 31 => 1, + 36 => 1, + 41 => 1, + 61 => 1, + 70 => 1, + 89 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc new file mode 100644 index 000000000..c7bd4738f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc @@ -0,0 +1,67 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php new file mode 100644 index 000000000..05359a482 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Channels; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the UnusedSystem sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Channels\UnusedSystemSniff + */ +final class UnusedSystemUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 8 => 1, + 24 => 1, + 34 => 1, + 54 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 000000000..19d5c5d4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,101 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 000000000..07c62a956 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionComment sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Commenting\FunctionCommentSniff + */ +final class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 28 => 1, + 36 => 1, + 37 => 2, + 49 => 1, + 58 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc new file mode 100644 index 000000000..349016101 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc @@ -0,0 +1,4 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php new file mode 100644 index 000000000..1f85b23e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/DebugCodeUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DebugCode sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Debug\DebugCodeSniff + */ +final class DebugCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js new file mode 100644 index 000000000..d5e3df571 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js @@ -0,0 +1,8 @@ +console.info(); +console.warn(); +console.test(); +con.sole(); +var console = { + console: 'string'; +}; +function console() {} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php new file mode 100644 index 000000000..8b9d60435 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FirebugConsole sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Debug\FirebugConsoleSniff + */ +final class FirebugConsoleUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile !== 'FirebugConsoleUnitTest.js') { + return []; + } + + return [ + 1 => 1, + 2 => 1, + 3 => 1, + 5 => 1, + 6 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js new file mode 100644 index 000000000..747a10084 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.js @@ -0,0 +1,20 @@ +var self = this; +buttonWidget.addClickEvent(function() { + self.addDynamicSouce(); +}); + +var x = self; +var y = this; + +var test = ''; +if (true) { + test = this +} + +var itemid = this.items[i].getAttribute('itemid'); + +for (var x = this; y < 10; y++) { + var x = this + 1; +} + +var _self = this; \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php new file mode 100644 index 000000000..7e44a8578 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/AssignThisUnitTest.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the AssignThis sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Objects\AssignThisSniff + */ +final class AssignThisUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile !== 'AssignThisUnitTest.js') { + return []; + } + + return [ + 7 => 1, + 11 => 1, + 16 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js new file mode 100644 index 000000000..22822d321 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js @@ -0,0 +1,186 @@ +SampleWidgetType.prototype = { + + create: function(callback) + { + if (x === 1) { + return; + } + + if (y === 1) { + callback.call(this); + // A comment here to explain the return is okay. + return; + } + + if (a === 1) { + // Cant return value even after calling callback. + callback.call(this); + return something; + } + + if (a === 1) { + // Need to pass self or this to callback function. + callback.call(a); + } + + callback.call(self); + + var self = this; + this.createChildren(null, function() { + callback.call(self, div); + }); + + // Never good to return a value. + return something; + + callback.call(self); + } + +}; + +AnotherSampleWidgetType.prototype = { + + create: function(input) + { + return; + } + + getSomething: function(input) + { + return 1; + } + +}; + + +NoCreateWidgetType.prototype = { + + getSomething: function(input) + { + return; + } + +}; + + +SomeRandom.prototype = { + + create: function(input) + { + return; + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (a === 1) { + // This is ok because it is the last statement, + // even though it is conditional. + callback.call(self); + } + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + var something = callback; + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + // Also valid because we are passing the callback to + // someone else to call. + if (y === 1) { + this.something(callback); + return; + } + + this.init(callback); + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + // Also valid because we are passing the callback to + // someone else to call. + if (y === 1) { + this.something(callback); + } + + this.init(callback); + + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (a === 1) { + // This is ok because it is the last statement, + // even though it is conditional. + this.something(callback); + } + + } + +}; + + +SampleWidgetType.prototype = { + + create: function(callback) + { + if (dfx.isFn(callback) === true) { + callback.call(this, cont); + return; + } + } + +}; + + +SampleWidgetType.prototype = { + + create: function(callback) + { + dfx.foreach(items, function(item) { + return true; + }); + + if (dfx.isFn(callback) === true) { + callback.call(this); + } + } + +}; + +SampleWidgetType.prototype = { + + create: function(callback) + { + var self = this; + this.createChildren(null, function() { + callback.call(self, div); + return; + }); + } + +}; \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php new file mode 100644 index 000000000..5c9ca8e51 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the CreateWidgetTypeCallback sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Objects\CreateWidgetTypeCallbackSniff + */ +final class CreateWidgetTypeCallbackUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 18 => 1, + 23 => 2, + 26 => 1, + 30 => 1, + 34 => 1, + 43 => 2, + 91 => 1, + 123 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc new file mode 100644 index 000000000..acf9baf7e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php new file mode 100644 index 000000000..049356048 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowNewWidget sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Objects\DisallowNewWidgetSniff + */ +final class DisallowNewWidgetUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [4 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc new file mode 100644 index 000000000..337914a85 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc @@ -0,0 +1,182 @@ +getMessage()); + }//end try + + if ($something === NULL) { + if ($bar !== NULL) { + } + } + + return $issueid; + +}//end addIssue() + +/** + * Adds a new issue. + * + * Returns the new issue id. + * + * @param string $title Title of the new issue. + * @param string $description The description of the issue. + * @param string $reporter Asset id of the reporter. + * @param integer $projectid Id of the project that the issue belongs to. + * @param array $tags Array of tags. + * @param string $status The status of the issue. + * @param string $assignedTo The asset id of the user that the issue is + * assigned to. + * @param string $reportedDate If set then this date will be used instead of the + * current date and time. + * @param integer $reportedMilestone Reported milestone. + * + * @return integer + * @throws ChannelException If there is an error. + * + */ +public static function addIssue( + $title, + $description, + $reporter=NULL, + $projectid=NULL, + array $tags=array(), + $status=NULL, + $assignedTo=NULL, + $reportedDate=NULL, + $reportedMilestone=NULL +) { + // Get current projectid if not specified. + if ($projectid === NULL) { + Channels::includeSystem('Project'); + $projectid = Project::getCurrentProjectId(); + Channels::modifyBasket('project', $projectid); + } + +}//end addIssue() diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php new file mode 100644 index 000000000..fa39de07e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the AjaxNullComparison sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\PHP\AjaxNullComparisonSniff + */ +final class AjaxNullComparisonUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 41 => 1, + 53 => 1, + 64 => 1, + 77 => 1, + 92 => 1, + 122 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc new file mode 100644 index 000000000..992a7dc19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc @@ -0,0 +1,26 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php new file mode 100644 index 000000000..e98ee2857 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EvalObjectFactory sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\PHP\EvalObjectFactorySniff + */ +final class EvalObjectFactoryUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + 21 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc new file mode 100644 index 000000000..7999763f2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.inc @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php new file mode 100644 index 000000000..f079325b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the GetRequestData sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\PHP\GetRequestDataSniff + */ +final class GetRequestDataUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 8 => 1, + 21 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc new file mode 100644 index 000000000..f9148a782 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc @@ -0,0 +1,9 @@ +myFunction(); +return $obj->variable; +return MyClass::VARIABLE; +return $variable; +return ($var + 1); +?> \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php new file mode 100644 index 000000000..ce8604610 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ReturnFunctionValue sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\PHP\ReturnFunctionValueSniff + */ +final class ReturnFunctionValueUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js new file mode 100644 index 000000000..46d90cf9f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js @@ -0,0 +1,18 @@ +one = (1 + 2); +two = (one + 2); +two = (one + one); +three = ('1' + 2); + +four = ['1', two].join(); +four = ['1', two].join(''); +four = ['1', [one, two].join(',')].join(' '); +four = ['1', [one, two].join()].join(' '); +four = ['1', [one, two].join()].join(); + +five = 'string' + ['1', [one, two].join()].join() + 'string'; + +six = myArray.join(' '); +six = [arrayOne, arrayTwo].join(); + +// This is fine because the array is not created inline. +var x = 'x' + test[x].join('p') + 't'; \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php new file mode 100644 index 000000000..b33922330 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\MySource\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the JoinStrings sniff. + * + * @covers PHP_CodeSniffer\Standards\MySource\Sniffs\Strings\JoinStringsSniff + */ +final class JoinStringsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile !== 'JoinStringsUnitTest.js') { + return []; + } + + return [ + 6 => 1, + 7 => 1, + 8 => 2, + 9 => 2, + 10 => 2, + 12 => 2, + 15 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml new file mode 100644 index 000000000..92407957a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/MySource/ruleset.xml @@ -0,0 +1,18 @@ + + + The MySource coding standard builds on the Squiz coding standard. Currently used for MySource Mini development. + + */Tests/* + */Oven/* + */data/* + */jquery.js + */jquery.*.js + */viper/* + DALConf.inc + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 000000000..b5d53fdf0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,22 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml new file mode 100644 index 000000000..fe8162000 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml @@ -0,0 +1,177 @@ + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + + + /** + * The Foo class. + */ +class Foo +{ +} + ]]> + + + /** + * The Foo class. + */ + +class Foo +{ +} + ]]> + + + + + The Foo class. + */ +class Foo +{ +} + ]]> + + + The Foo class. + */ +class Foo +{ +} + ]]> + + + + + + * A helper for the Bar class. + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + * + * A helper for the Bar class. + * + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + + + * @see Bar + */ +class Foo +{ +} + ]]> + + + + * + * @see Bar + */ +class Foo +{ +} + ]]> + + + + + Release: 1.0 + */ +class Foo +{ +} + ]]> + + + 1.0 + */ +class Foo +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml new file mode 100644 index 000000000..190670f75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml @@ -0,0 +1,293 @@ + + + + + + + /** + * Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + ]]> + + + + + Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * Short description here. + * + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * + * PHP version 5 + * + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + + + @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + @category Foo + * @category Bar + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + PHP version 5 + * + * @category Foo + * @package Foo_Helpers + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + + + + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + @package Foo_Helpers + * @category Foo + * @author Marty McFly + * @copyright 2013-2014 Foo Inc. + * @license MIT License + * @link http://example.com + */ + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml new file mode 100644 index 000000000..621649f24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml @@ -0,0 +1,230 @@ + + + + + + + /** + * Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + + + Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + * Short description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + * Long description here. + * + * @return void + */ + function foo() + { + } + ]]> + + + + * + * Long description here. + * + * + * @return void + */ + function foo() + { + } + ]]> + + + + + + * @return void + */ + function foo() + { + } + ]]> + + + + * + * @return void + */ + function foo() + { + } + ]]> + + + + + FooException + */ + function foo() + { + } + ]]> + + + @throws + */ + function foo() + { + } + ]]> + + + + + @return void + */ + function foo() + { + } + ]]> + + + + + + + + $foo Foo parameter + * @param string $bar Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + $qux Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + + + $foo Foo parameter + * @param string $bar Bar parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + $bar Bar parameter + * @param string $foo Foo parameter + * @return void + */ + function foo($foo, $bar) + { + } + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml new file mode 100644 index 000000000..53056e2a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml @@ -0,0 +1,19 @@ + + + + + + + // A comment. + ]]> + + + # A comment. + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml new file mode 100644 index 000000000..ce430fb12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml @@ -0,0 +1,36 @@ + + + + + + + ($foo) { +} + ]]> + + + ($foo){ +} + ]]> + + + + + { +} + ]]> + + + { +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml new file mode 100644 index 000000000..96d451dc4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml @@ -0,0 +1,60 @@ + + + + + + + && $bar +) { +} + ]]> + + + && $bar +) { +} + ]]> + + + + + && $bar +) { +} + ]]> + + + && + $bar +) { +} + ]]> + + + + + ) { +} + ]]> + + + ) { +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml new file mode 100644 index 000000000..912fa5e0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/IncludingFileStandard.xml @@ -0,0 +1,24 @@ + + + require_once. Anywhere you are conditionally including a class file (for example, factory methods), use include_once. Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with require_once will not be included again by include_once. + ]]> + + + include_once and require_once are statements, not functions. Parentheses should not surround the subject filename. + ]]> + + + + + + + ('PHP/CodeSniffer.php'); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml new file mode 100644 index 000000000..e4911ef3b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Files/LineLengthStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml new file mode 100644 index 000000000..e825c5533 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml @@ -0,0 +1,35 @@ + + + + + + + = $bar; + ]]> + + + = + $bar; + ]]> + + + + + = $bar; + ]]> + + + = $bar; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml new file mode 100644 index 000000000..2f539c9b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + ( $bar, $baz, $quux ) ; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml new file mode 100644 index 000000000..ced9ae2e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml @@ -0,0 +1,41 @@ + + + + + + + () use ($bar) { +}; + ]]> + + + ()use($bar){ +}; + ]]> + + + + + $bar, + $baz +) { +}; + ]]> + + + $bar, +$baz) +{ +}; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml new file mode 100644 index 000000000..ef9bc3262 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $persistent = false) +{ + ... +} + ]]> + + + $persistent = false, $dsn) +{ + ... +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml new file mode 100644 index 000000000..052fb2bab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml new file mode 100644 index 000000000..5dcff71a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml new file mode 100644 index 000000000..1f8e6d2b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + publicVar; + protected $protectedVar; + private $_privateVar; +} + ]]> + + + _publicVar; + protected $_protectedVar; + private $privateVar; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml new file mode 100644 index 000000000..9dee905db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml @@ -0,0 +1,39 @@ + + + + + + + ->bar() + ->baz(); + ]]> + + + -> + bar()-> + baz(); + ]]> + + + + + ->bar() + ->baz(); + ]]> + + + ->bar() +->baz(); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml new file mode 100644 index 000000000..c8d6e2748 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + } + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml new file mode 100644 index 000000000..fafa07ace --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml @@ -0,0 +1,29 @@ + + + + + + + if ($test) { + $var = 1; + } +} + ]]> + + + if ($test) { +$var = 1; +} +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..893dc9a8d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,150 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $errorData = [strtolower($tokens[$stackPtr]['content'])]; + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData); + return; + } + + $curlyBrace = $tokens[$stackPtr]['scope_opener']; + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBrace - 1), $stackPtr, true); + $classLine = $tokens[$lastContent]['line']; + $braceLine = $tokens[$curlyBrace]['line']; + if ($braceLine === $classLine) { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'same line'); + $error = 'Opening brace of a %s must be on the line after the definition'; + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceNewLine', $errorData); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($curlyBrace - 1), ''); + } + + $phpcsFile->fixer->addNewlineBefore($curlyBrace); + $phpcsFile->fixer->endChangeset(); + } + + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'Class opening brace placement', 'new line'); + + if ($braceLine > ($classLine + 1)) { + $error = 'Opening brace of a %s must be on the line following the %s declaration; found %s line(s)'; + $data = [ + $tokens[$stackPtr]['content'], + $tokens[$stackPtr]['content'], + ($braceLine - $classLine - 1), + ]; + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceWrongLine', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($curlyBrace - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] === ($tokens[$curlyBrace]['line'] + 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + }//end if + + if ($tokens[($curlyBrace + 1)]['content'] !== $phpcsFile->eolChar) { + $error = 'Opening %s brace must be on a line by itself'; + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($curlyBrace + 1), null, true); + if ($tokens[$nextNonWhitespace]['code'] === T_PHPCS_IGNORE) { + // Don't auto-fix if the next thing is a PHPCS ignore annotation. + $phpcsFile->addError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData); + } else { + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData); + if ($fix === true) { + $phpcsFile->fixer->addNewline($curlyBrace); + } + } + } + + if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($curlyBrace - 1)]['content']; + if ($prevContent === $phpcsFile->eolChar) { + $spaces = 0; + } else { + $spaces = $tokens[($curlyBrace - 1)]['length']; + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $expected = ($tokens[$first]['column'] - 1); + if ($spaces !== $expected) { + $error = 'Expected %s spaces before opening brace; %s found'; + $data = [ + $expected, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $curlyBrace, 'SpaceBeforeBrace', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expected); + if ($spaces === 0) { + $phpcsFile->fixer->addContentBefore($curlyBrace, $indent); + } else { + $phpcsFile->fixer->replaceToken(($curlyBrace - 1), $indent); + } + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 000000000..8fa6bfba7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,122 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; + +class ClassCommentSniff extends FileCommentSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $type = strtolower($tokens[$stackPtr]['content']); + $errorData = [$type]; + + $find = [ + T_ABSTRACT => T_ABSTRACT, + T_FINAL => T_FINAL, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + ]; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $errorData[] = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError('Missing doc comment for %s %s', $stackPtr, 'Missing', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes'); + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a %s comment', $stackPtr, 'WrongStyle', $errorData); + return; + } + + // Check each tag. + $this->processTags($phpcsFile, $stackPtr, $tokens[$commentEnd]['comment_opener']); + + }//end process() + + + /** + * Process the version tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processVersion($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if ((strstr($content, 'Release:') === false)) { + $error = 'Invalid version "%s" in doc comment; consider "Release: " instead'; + $data = [$content]; + $phpcsFile->addWarning($error, $tag, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 000000000..c47466a0d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,583 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class FileCommentSniff implements Sniff +{ + + /** + * Tags in correct order and related info. + * + * @var array + */ + protected $tags = [ + '@category' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@package' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@subpackage' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@author' => [ + 'required' => true, + 'allow_multiple' => true, + ], + '@copyright' => [ + 'required' => false, + 'allow_multiple' => true, + ], + '@license' => [ + 'required' => true, + 'allow_multiple' => false, + ], + '@version' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@link' => [ + 'required' => true, + 'allow_multiple' => true, + ], + '@see' => [ + 'required' => false, + 'allow_multiple' => true, + ], + '@since' => [ + 'required' => false, + 'allow_multiple' => false, + ], + '@deprecated' => [ + 'required' => false, + 'allow_multiple' => false, + ], + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the next non whitespace token. + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + // Allow declare() statements at the top of the file. + if ($tokens[$commentStart]['code'] === T_DECLARE) { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($commentStart + 1)); + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), null, true); + } + + // Ignore vim header. + if ($tokens[$commentStart]['code'] === T_COMMENT) { + if (strstr($tokens[$commentStart]['content'], 'vim:') !== false) { + $commentStart = $phpcsFile->findNext( + T_WHITESPACE, + ($commentStart + 1), + null, + true + ); + } + } + + $errorToken = ($stackPtr + 1); + if (isset($tokens[$errorToken]) === false) { + $errorToken--; + } + + if ($tokens[$commentStart]['code'] === T_CLOSE_TAG) { + // We are only interested if this is the first open tag. + return $phpcsFile->numTokens; + } else if ($tokens[$commentStart]['code'] === T_COMMENT) { + $error = 'You must use "/**" style comments for a file comment'; + $phpcsFile->addError($error, $errorToken, 'WrongStyle'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + return $phpcsFile->numTokens; + } else if ($commentStart === false + || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG + ) { + $phpcsFile->addError('Missing file doc comment', $errorToken, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return $phpcsFile->numTokens; + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + for ($nextToken = ($commentEnd + 1); $nextToken < $phpcsFile->numTokens; $nextToken++) { + if ($tokens[$nextToken]['code'] === T_WHITESPACE) { + continue; + } + + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE + && isset($tokens[$nextToken]['attribute_closer']) === true + ) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } + + if ($nextToken === $phpcsFile->numTokens) { + $nextToken--; + } + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_READONLY, + T_CONST, + T_PROPERTY, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return $phpcsFile->numTokens; + } + + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + + // Check the PHP Version, which should be in some text before the first tag. + $found = false; + for ($i = ($commentStart + 1); $i < $commentEnd; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG) { + break; + } else if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING + && strstr(strtolower($tokens[$i]['content']), 'php version') !== false + ) { + $found = true; + break; + } + } + + if ($found === false) { + $error = 'PHP version not specified'; + $phpcsFile->addWarning($error, $commentEnd, 'MissingVersion'); + } + + // Check each tag. + $this->processTags($phpcsFile, $stackPtr, $commentStart); + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + + /** + * Processes each required or optional tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart Position in the stack where the comment started. + * + * @return void + */ + protected function processTags($phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if (get_class($this) === 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff') { + $docBlock = 'file'; + } else { + $docBlock = 'class'; + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + $foundTags = []; + $tagTokens = []; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $name = $tokens[$tag]['content']; + if (isset($this->tags[$name]) === false) { + continue; + } + + if ($this->tags[$name]['allow_multiple'] === false && isset($tagTokens[$name]) === true) { + $error = 'Only one %s tag is allowed in a %s comment'; + $data = [ + $name, + $docBlock, + ]; + $phpcsFile->addError($error, $tag, 'Duplicate'.ucfirst(substr($name, 1)).'Tag', $data); + } + + $foundTags[] = $name; + $tagTokens[$name][] = $tag; + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in %s comment'; + $data = [ + $name, + $docBlock, + ]; + $phpcsFile->addError($error, $tag, 'Empty'.ucfirst(substr($name, 1)).'Tag', $data); + continue; + } + }//end foreach + + // Check if the tags are in the correct position. + $pos = 0; + foreach ($this->tags as $tag => $tagData) { + if (isset($tagTokens[$tag]) === false) { + if ($tagData['required'] === true) { + $error = 'Missing %s tag in %s comment'; + $data = [ + $tag, + $docBlock, + ]; + $phpcsFile->addError($error, $commentEnd, 'Missing'.ucfirst(substr($tag, 1)).'Tag', $data); + } + + continue; + } else { + $method = 'process'.substr($tag, 1); + if (method_exists($this, $method) === true) { + // Process each tag if a method is defined. + call_user_func([$this, $method], $phpcsFile, $tagTokens[$tag]); + } + } + + if (isset($foundTags[$pos]) === false) { + break; + } + + if ($foundTags[$pos] !== $tag) { + $error = 'The tag in position %s should be the %s tag'; + $data = [ + ($pos + 1), + $tag, + ]; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)).'TagOrder', $data); + } + + // Account for multiple tags. + $pos++; + while (isset($foundTags[$pos]) === true && $foundTags[$pos] === $tag) { + $pos++; + } + }//end foreach + + }//end processTags() + + + /** + * Process the category tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processCategory($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) !== true) { + $newContent = str_replace(' ', '_', $content); + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = ucfirst($firstBit).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= ucfirst($bit).'_'; + } + } + + $error = 'Category name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidCategory', $data); + } + }//end foreach + + }//end processCategory() + + + /** + * Process the package tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processPackage($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) === true) { + continue; + } + + $newContent = str_replace(' ', '_', $content); + $newContent = trim($newContent, '_'); + $newContent = preg_replace('/[^A-Za-z_]/', '', $newContent); + + if ($newContent === '') { + $error = 'Package name "%s" is not valid'; + $data = [$content]; + $phpcsFile->addError($error, $tag, 'InvalidPackageValue', $data); + } else { + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $error = 'Package name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidPackage', $data); + }//end if + }//end foreach + + }//end processPackage() + + + /** + * Process the subpackage tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processSubpackage($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (Common::isUnderscoreName($content) === true) { + continue; + } + + $newContent = str_replace(' ', '_', $content); + $nameBits = explode('_', $newContent); + $firstBit = array_shift($nameBits); + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $error = 'Subpackage name "%s" is not valid; consider "%s" instead'; + $validName = trim($newName, '_'); + $data = [ + $content, + $validName, + ]; + $phpcsFile->addError($error, $tag, 'InvalidSubpackage', $data); + }//end foreach + + }//end processSubpackage() + + + /** + * Process the author tag(s) that this header comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processAuthor($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $local = '\da-zA-Z-_+'; + // Dot character cannot be the first or last character in the local-part. + $localMiddle = $local.'.\w'; + if (preg_match('/^([^<]*)\s+<(['.$local.'](['.$localMiddle.']*['.$local.'])*@[\da-zA-Z][-.\w]*[\da-zA-Z]\.[a-zA-Z]{2,})>$/', $content) === 0) { + $error = 'Content of the @author tag must be in the form "Display Name "'; + $phpcsFile->addError($error, $tag, 'InvalidAuthors'); + } + } + + }//end processAuthor() + + + /** + * Process the copyright tags. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processCopyright($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $matches = []; + if (preg_match('/^([0-9]{4})((.{1})([0-9]{4}))? (.+)$/', $content, $matches) !== 0) { + // Check earliest-latest year order. + if ($matches[3] !== '' && $matches[3] !== null) { + if ($matches[3] !== '-') { + $error = 'A hyphen must be used between the earliest and latest year'; + $phpcsFile->addError($error, $tag, 'CopyrightHyphen'); + } + + if ($matches[4] !== '' && $matches[4] !== null && $matches[4] < $matches[1]) { + $error = "Invalid year span \"$matches[1]$matches[3]$matches[4]\" found; consider \"$matches[4]-$matches[1]\" instead"; + $phpcsFile->addWarning($error, $tag, 'InvalidCopyright'); + } + } + } else { + $error = '@copyright tag must contain a year and the name of the copyright holder'; + $phpcsFile->addError($error, $tag, 'IncompleteCopyright'); + } + }//end foreach + + }//end processCopyright() + + + /** + * Process the license tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processLicense($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + $matches = []; + preg_match('/^([^\s]+)\s+(.*)/', $content, $matches); + if (count($matches) !== 3) { + $error = '@license tag must contain a URL and a license name'; + $phpcsFile->addError($error, $tag, 'IncompleteLicense'); + } + } + + }//end processLicense() + + + /** + * Process the version tag. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $tags The tokens for these tags. + * + * @return void + */ + protected function processVersion($phpcsFile, array $tags) + { + $tokens = $phpcsFile->getTokens(); + foreach ($tags as $tag) { + if ($tokens[($tag + 2)]['code'] !== T_DOC_COMMENT_STRING) { + // No content. + continue; + } + + $content = $tokens[($tag + 2)]['content']; + if (strstr($content, 'CVS:') === false + && strstr($content, 'SVN:') === false + && strstr($content, 'GIT:') === false + && strstr($content, 'HG:') === false + ) { + $error = 'Invalid version "%s" in file comment; consider "CVS: " or "SVN: " or "GIT: " or "HG: " instead'; + $data = [$content]; + $phpcsFile->addWarning($error, $tag, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 000000000..ee242cf6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,539 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCommentSniff implements Sniff +{ + + /** + * Disable the check for functions with a lower visibility than the value given. + * + * Allowed values are public, protected, and private. + * + * @var string + */ + public $minimumVisibility = 'private'; + + /** + * Array of methods which do not require a return type. + * + * @var array + */ + public $specialMethods = [ + '__construct', + '__destruct', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $scopeModifier = $phpcsFile->getMethodProperties($stackPtr)['scope']; + if (($scopeModifier === 'protected' + && $this->minimumVisibility === 'public') + || ($scopeModifier === 'private' + && ($this->minimumVisibility === 'public' || $this->minimumVisibility === 'protected')) + ) { + return; + } + + $tokens = $phpcsFile->getTokens(); + $ignore = Tokens::$methodPrefixes; + $ignore[T_WHITESPACE] = T_WHITESPACE; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + // Inline comments might just be closing comments for + // control structures or functions instead of function comments + // using the wrong comment type. If there is other code on the line, + // assume they relate to that code. + $prev = $phpcsFile->findPrevious($ignore, ($commentEnd - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) { + $commentEnd = $prev; + } + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $function = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError( + 'Missing doc comment for function %s()', + $stackPtr, + 'Missing', + [$function] + ); + $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no'); + return; + } else { + $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes'); + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle'); + return; + } + + if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + for ($i = ($commentEnd + 1); $i < $stackPtr; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'There must be no blank lines after the function comment'; + $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + while ($i < $stackPtr + && $tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $phpcsFile->fixer->replaceToken($i++, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + break; + } + }//end for + }//end if + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } + } + + $this->processReturn($phpcsFile, $stackPtr, $commentStart); + $this->processThrows($phpcsFile, $stackPtr, $commentStart); + $this->processParams($phpcsFile, $stackPtr, $commentStart); + + }//end process() + + + /** + * Process the return comment of this function comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = in_array($methodName, $this->specialMethods, true); + + $return = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } + } else { + if ($isSpecialMethod === true) { + return; + } + + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + } + + if ($exception === null) { + $error = 'Exception type missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentEnd = 0; + $commentTokens = []; + + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/((?:(?![$.]|&(?=\$)).)*)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + if (empty($matches) === false) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + $commentEnd = $i; + $commentTokens[] = $i; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + }//end if + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'comment_end' => $commentEnd, + 'comment_tokens' => $commentTokens, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so add + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + if (trim($param['type']) !== '') { + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + 1); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix === true) { + $commentToken = ($param['tag'] + 2); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + + $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']); + + $padding = str_repeat(' ', ($tokens[$star]['column'] - 1)); + $padding .= '* '; + $padding .= str_repeat(' ', $spaceLength); + + $content .= wordwrap( + $param['comment'], + $wrapLength, + $phpcsFile->eolChar.$padding + ); + + $phpcsFile->fixer->replaceToken($commentToken, $content); + for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + }//end if + }//end if + }//end if + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + if ($realName !== $param['var']) { + $code = 'ParamNameNoMatch'; + $data = [ + $param['var'], + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($param['var']) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } else if (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the param name. + $spaces = ($maxVar - strlen($param['var']) + 1); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix === true) { + $commentToken = ($param['tag'] + 2); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + + $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']); + + $padding = str_repeat(' ', ($tokens[$star]['column'] - 1)); + $padding .= '* '; + $padding .= str_repeat(' ', $spaceLength); + + $content .= wordwrap( + $param['comment'], + $wrapLength, + $phpcsFile->eolChar.$padding + ); + + $phpcsFile->fixer->replaceToken($commentToken, $content); + for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + }//end if + }//end if + + // Check the alignment of multi-line param comments. + if ($param['tag'] !== $param['comment_end']) { + $wrapLength = ($tokens[($param['tag'] + 2)]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var'])); + + $startColumn = ($tokens[($param['tag'] + 2)]['column'] + $tokens[($param['tag'] + 2)]['length'] - $wrapLength); + + $star = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']); + $expected = ($startColumn - $tokens[$star]['column'] - 1); + + foreach ($param['comment_tokens'] as $commentToken) { + if ($tokens[$commentToken]['column'] === $startColumn) { + continue; + } + + $found = 0; + if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $found = $tokens[($commentToken - 1)]['length']; + } + + $error = 'Parameter comment not aligned correctly; expected %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + + if ($found < $expected) { + $code = 'ParamCommentAlignment'; + } else { + $code = 'ParamCommentAlignmentExceeded'; + } + + $fix = $phpcsFile->addFixableError($error, $commentToken, $code, $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($commentToken - 1), $padding); + } else { + $phpcsFile->fixer->addContentBefore($commentToken, $padding); + } + } + }//end foreach + }//end if + }//end foreach + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php new file mode 100644 index 000000000..71c11808d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'][0] === '#') { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '# ...'); + + $error = 'Perl-style comments are not allowed. Use "// Comment."'; + $error .= ' or "/* comment */" instead.'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle'); + if ($fix === true) { + $newComment = ltrim($tokens[$stackPtr]['content'], '# '); + $newComment = '// '.$newComment; + $phpcsFile->fixer->replaceToken($stackPtr, $newComment); + } + } else if ($tokens[$stackPtr]['content'][0] === '/' + && $tokens[$stackPtr]['content'][1] === '/' + ) { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '// ...'); + } else if ($tokens[$stackPtr]['content'][0] === '/' + && $tokens[$stackPtr]['content'][1] === '*' + ) { + $phpcsFile->recordMetric($stackPtr, 'Inline comment style', '/* ... */'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100644 index 000000000..4ca5451b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Sniffs\AbstractPatternSniff; + +class ControlSignatureSniff extends AbstractPatternSniff +{ + + /** + * If true, comments will be ignored if they are found in the code. + * + * @var boolean + */ + public $ignoreComments = true; + + + /** + * Returns the patterns that this test wishes to verify. + * + * @return string[] + */ + protected function getPatterns() + { + return [ + 'do {EOL...} while (...);EOL', + 'while (...) {EOL', + 'for (...) {EOL', + 'if (...) {EOL', + 'foreach (...) {EOL', + '} else if (...) {EOL', + '} elseif (...) {EOL', + '} else {EOL', + 'do {EOL', + 'match (...) {EOL', + ]; + + }//end getPatterns() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php new file mode 100644 index 000000000..08752edaa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php @@ -0,0 +1,283 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultiLineConditionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + $spaceAfterOpen = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($openBracket + 1)]['content'], $phpcsFile->eolChar) !== false) { + $spaceAfterOpen = 'newline'; + } else { + $spaceAfterOpen = $tokens[($openBracket + 1)]['length']; + } + } + + if ($spaceAfterOpen !== 0) { + $error = 'First condition of a multi-line IF statement must directly follow the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, ($openBracket + 1), 'SpacingAfterOpenBrace'); + if ($fix === true) { + if ($spaceAfterOpen === 'newline') { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + } + + // We need to work out how far indented the if statement + // itself is, so we can work out how far to indent conditions. + $statementIndent = 0; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + $i++; + break; + } + } + + if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) { + $statementIndent = $tokens[$i]['length']; + } + + // Each line between the parenthesis should be indented 4 spaces + // and start with an operator, unless the line is inside a + // function call, in which case it is ignored. + $prevLine = $tokens[$openBracket]['line']; + for ($i = ($openBracket + 1); $i <= $closeBracket; $i++) { + if ($i === $closeBracket && $tokens[$openBracket]['line'] !== $tokens[$i]['line']) { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + // Closing bracket is on the same line as a condition. + $error = 'Closing parenthesis of a multi-line IF statement must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketNewLine'); + if ($fix === true) { + // Account for a comment at the end of the line. + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] !== T_COMMENT + && isset(Tokens::$phpcsCommentTokens[$tokens[$next]['code']]) === false + ) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } else { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($closeBracket, ''); + $phpcsFile->fixer->addContentBefore($next, ')'); + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + + if ($tokens[$i]['line'] !== $prevLine) { + if ($tokens[$i]['line'] === $tokens[$closeBracket]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, $i, null, true); + if ($next !== $closeBracket) { + $expectedIndent = ($statementIndent + $this->indent); + } else { + // Closing brace needs to be indented to the same level + // as the statement. + $expectedIndent = $statementIndent; + }//end if + } else { + $expectedIndent = ($statementIndent + $this->indent); + }//end if + + if ($tokens[$i]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true + ) { + $prevLine = $tokens[$i]['line']; + continue; + } + + // We changed lines, so this should be a whitespace indent token. + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundIndent = 0; + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($expectedIndent !== $foundIndent) { + $error = 'Multi-line IF statement not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Alignment', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $spaces); + } else { + $phpcsFile->fixer->replaceToken($i, $spaces); + } + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $i, null, true); + if ($next !== $closeBracket && $tokens[$next]['line'] === $tokens[$i]['line']) { + if (isset(Tokens::$booleanOperators[$tokens[$next]['code']]) === false) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $openBracket, true); + $fixable = true; + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === false + && $phpcsFile->findNext(T_WHITESPACE, ($prev + 1), $next, true) !== false + ) { + // Condition spread over multi-lines interspersed with comments. + $fixable = false; + } + + $error = 'Each line in a multi-line IF statement must begin with a boolean operator'; + if ($fixable === false) { + $phpcsFile->addError($error, $next, 'StartWithBoolean'); + } else { + $fix = $phpcsFile->addFixableError($error, $next, 'StartWithBoolean'); + if ($fix === true) { + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->addContentBefore($next, $tokens[$prev]['content'].' '); + $phpcsFile->fixer->endChangeset(); + } else { + for ($x = ($prev + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + } + } + } + }//end if + }//end if + + $prevLine = $tokens[$i]['line']; + }//end if + + if ($tokens[$i]['code'] === T_STRING) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + // This is a function call, so skip to the end as they + // have their own indentation rules. + $i = $tokens[$next]['parenthesis_closer']; + $prevLine = $tokens[$i]['line']; + continue; + } + } + }//end for + + // From here on, we are checking the spacing of the opening and closing + // braces. If this IF statement does not use braces, we end here. + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // The opening brace needs to be one space away from the closing parenthesis. + $openBrace = $tokens[$stackPtr]['scope_opener']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), $openBrace, true); + if ($next !== false) { + // Probably comments in between tokens, so don't check. + return; + } + + if ($tokens[$openBrace]['line'] > $tokens[$closeBracket]['line']) { + $length = -1; + } else if ($openBrace === ($closeBracket + 1)) { + $length = 0; + } else if ($openBrace === ($closeBracket + 2) + && $tokens[($closeBracket + 1)]['code'] === T_WHITESPACE + ) { + $length = $tokens[($closeBracket + 1)]['length']; + } else { + // Confused, so don't check. + $length = 1; + } + + if ($length === 1) { + return; + } + + $data = [$length]; + $code = 'SpaceBeforeOpenBrace'; + + $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement; found '; + if ($length === -1) { + $error .= 'newline'; + $code = 'NewlineBeforeOpenBrace'; + } else { + $error .= '%s spaces'; + } + + $fix = $phpcsFile->addFixableError($error, ($closeBracket + 1), $code, $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContent($closeBracket, ' '); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket + 1), ' '); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php new file mode 100644 index 000000000..e0ed0fb1b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php @@ -0,0 +1,136 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IncludingFileSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_INCLUDE_ONCE, + T_REQUIRE_ONCE, + T_REQUIRE, + T_INCLUDE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS) { + $error = '"%s" is a statement not a function; no parentheses are required'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BracketsNotRequired', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($tokens[$nextToken]['parenthesis_closer'], ''); + if ($tokens[($nextToken - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($nextToken, ' '); + } else { + $phpcsFile->fixer->replaceToken($nextToken, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if (count($tokens[$stackPtr]['conditions']) !== 0) { + $inCondition = true; + } else { + $inCondition = false; + } + + // Check to see if this including statement is within the parenthesis + // of a condition. If that's the case then we need to process it as being + // within a condition, as they are checking the return value. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $left => $right) { + if (isset($tokens[$left]['parenthesis_owner']) === true) { + $inCondition = true; + } + } + } + + // Check to see if they are assigning the return value of this + // including call. If they are then they are probably checking it, so + // it's conditional. + $previous = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset(Tokens::$assignmentTokens[$tokens[$previous]['code']]) === true) { + // The have assigned the return value to it, so its conditional. + $inCondition = true; + } + + $tokenCode = $tokens[$stackPtr]['code']; + if ($inCondition === true) { + // We are inside a conditional statement. We need an include_once. + if ($tokenCode === T_REQUIRE_ONCE) { + $error = 'File is being conditionally included; '; + $error .= 'use "include_once" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseIncludeOnce'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'include_once'); + } + } else if ($tokenCode === T_REQUIRE) { + $error = 'File is being conditionally included; '; + $error .= 'use "include" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseInclude'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'include'); + } + } + } else { + // We are unconditionally including, we need a require_once. + if ($tokenCode === T_INCLUDE_ONCE) { + $error = 'File is being unconditionally included; '; + $error .= 'use "require_once" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseRequireOnce'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'require_once'); + } + } else if ($tokenCode === T_INCLUDE) { + $error = 'File is being unconditionally included; '; + $error .= 'use "require" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseRequire'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'require'); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php new file mode 100644 index 000000000..0f18710df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php @@ -0,0 +1,106 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class MultiLineAssignmentSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Equal sign can't be the last thing on the line. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + // Bad assignment. + return; + } + + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Multi-line assignments must have the equal sign on the second line'; + $phpcsFile->addError($error, $stackPtr, 'EqualSignLine'); + return; + } + + // Make sure it is the first thing on the line, otherwise we ignore it. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), false, true); + if ($prev === false) { + // Bad assignment. + return; + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + return; + } + + // Find the required indent based on the ident of the previous line. + $assignmentIndent = 0; + $prevLine = $tokens[$prev]['line']; + for ($i = ($prev - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $prevLine) { + $i++; + break; + } + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + $assignmentIndent = $tokens[$i]['length']; + } + + // Find the actual indent. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1)); + + $expectedIndent = ($assignmentIndent + $this->indent); + $foundIndent = $tokens[$prev]['length']; + if ($foundIndent !== $expectedIndent) { + $error = 'Multi-line assignment not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + $phpcsFile->addError($error, $stackPtr, 'Indent', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php new file mode 100644 index 000000000..772ab6b8c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php @@ -0,0 +1,634 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallSignatureSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * If TRUE, multiple arguments can be defined per line in a multi-line call. + * + * @var boolean + */ + public $allowMultipleArguments = true; + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$functionNameTokens; + + $tokens[] = T_VARIABLE; + $tokens[] = T_CLOSE_CURLY_BRACKET; + $tokens[] = T_CLOSE_SQUARE_BRACKET; + $tokens[] = T_CLOSE_PARENTHESIS; + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$stackPtr]['scope_condition']) === true + ) { + // Not a function call. + return; + } + + // Find the next non-empty token. + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) { + // Not a function call. + return; + } + + if (isset($tokens[$openBracket]['parenthesis_closer']) === false) { + // Not a function call. + return; + } + + // Find the previous non-empty token. + $search = Tokens::$emptyTokens; + $search[] = T_BITWISE_AND; + $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true); + if ($tokens[$previous]['code'] === T_FUNCTION) { + // It's a function definition, not a function call. + return; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + if (($stackPtr + 1) !== $openBracket) { + // Checking this: $value = my_function[*](...). + $error = 'Space before opening parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $openBracket; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Modify the bracket as well to ensure a conflict if the bracket + // has been changed in some way by another sniff. + $phpcsFile->fixer->replaceToken($openBracket, '('); + $phpcsFile->fixer->endChangeset(); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + if (isset(Tokens::$emptyTokens[$tokens[($closeBracket + 1)]['code']]) === true) { + $error = 'Space after closing parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpaceAfterCloseBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closeBracket + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Modify the bracket as well to ensure a conflict if the bracket + // has been changed in some way by another sniff. + $phpcsFile->fixer->replaceToken($closeBracket, ')'); + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Check if this is a single line or multi-line function call. + if ($this->isMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens); + } else { + $this->processSingleLineCall($phpcsFile, $stackPtr, $openBracket, $tokens); + } + + }//end process() + + + /** + * Determine if this is a multi-line function call. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + return true; + } + + return false; + + }//end isMultiLineCall() + + + /** + * Processes single-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closer = $tokens[$openBracket]['parenthesis_closer']; + if ($openBracket === ($closer - 1)) { + return; + } + + // If the function call has no arguments or comments, enforce 0 spaces. + $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closer, true); + if ($next === false) { + $requiredSpacesAfterOpen = 0; + $requiredSpacesBeforeClose = 0; + } else { + $requiredSpacesAfterOpen = $this->requiredSpacesAfterOpen; + $requiredSpacesBeforeClose = $this->requiredSpacesBeforeClose; + } + + if ($requiredSpacesAfterOpen === 0 && $tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + // Checking this: $value = my_function([*]...). + $error = 'Space after opening parenthesis of function call prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } else if ($requiredSpacesAfterOpen > 0) { + $spaceAfterOpen = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening parenthesis; %s found'; + $data = [ + $requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), $padding); + } + } + } + }//end if + + // Checking this: $value = my_function(...[*]). + $spaceBeforeClose = 0; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), $openBracket, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Need a newline after these tokens, so ignore this rule. + return; + } + + if ($tokens[$prev]['line'] !== $tokens[$closer]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closer - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closer - 1)]['length']; + } + + if ($spaceBeforeClose !== $requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing parenthesis; %s found'; + $data = [ + $requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeCloseBracket', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredSpacesBeforeClose); + + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closer, $padding); + } else if ($spaceBeforeClose === 'newline') { + $phpcsFile->fixer->beginChangeset(); + + $closingContent = ')'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $closingContent .= ';'; + for ($i = ($closer + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // We want to jump over any whitespace or inline comment and + // move the closing parenthesis after any other token. + $prev = ($closer - 1); + while (isset(Tokens::$emptyTokens[$tokens[$prev]['code']]) === true) { + if (($tokens[$prev]['code'] === T_COMMENT) + && (strpos($tokens[$prev]['content'], '*/') !== false) + ) { + break; + } + + $prev--; + } + + $phpcsFile->fixer->addContent($prev, $padding.$closingContent); + + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), null, true); + for ($i = ($prevNonWhitespace + 1); $i <= $closer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($closer - 1), $padding); + }//end if + }//end if + }//end if + + }//end processSingleLineCall() + + + /** + * Processes multi-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + // We need to work out how far indented the function + // call itself is, so we can work out how far to + // indent the arguments. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + if ($first !== false + && $tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($first - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING + ) { + // We are in a multi-line string, so find the start and use + // the indent from there. + $prev = $phpcsFile->findPrevious(T_CONSTANT_ENCAPSED_STRING, ($first - 2), null, true); + $first = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $prev, true); + if ($first === false) { + $first = ($prev + 1); + } + } + + $foundFunctionIndent = 0; + if ($first !== false) { + if ($tokens[$first]['code'] === T_INLINE_HTML + || ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($first - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING) + ) { + $trimmed = ltrim($tokens[$first]['content']); + if ($trimmed === '') { + $foundFunctionIndent = strlen($tokens[$first]['content']); + } else { + $foundFunctionIndent = (strlen($tokens[$first]['content']) - strlen($trimmed)); + } + } else { + $foundFunctionIndent = ($tokens[$first]['column'] - 1); + } + } + + // Make sure the function indent is divisible by the indent size. + // We round down here because this accounts for times when the + // surrounding code is indented a little too far in, and not correctly + // at a tab stop. Without this, the function will be indented a further + // $indent spaces to the right. + $functionIndent = (int) (floor($foundFunctionIndent / $this->indent) * $this->indent); + $adjustment = 0; + + if ($foundFunctionIndent !== $functionIndent) { + $error = 'Opening statement of multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $functionIndent, + $foundFunctionIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'OpeningIndent', $data); + if ($fix === true) { + // Set adjustment for use later to determine whether argument indentation is correct when fixing. + $adjustment = ($functionIndent - $foundFunctionIndent); + + $padding = str_repeat(' ', $functionIndent); + if ($foundFunctionIndent === 0) { + $phpcsFile->fixer->addContentBefore($first, $padding); + } else if ($tokens[$first]['code'] === T_INLINE_HTML) { + $newContent = $padding.ltrim($tokens[$first]['content']); + $phpcsFile->fixer->replaceToken($first, $newContent); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), $padding); + } + } + }//end if + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $error = 'Opening parenthesis of a multi-line function call must be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->addContent( + $openBracket, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + } + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) { + $error = 'Closing parenthesis of a multi-line function call must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore( + $closeBracket, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + } + } + + // Each line between the parenthesis should be indented n spaces. + $lastLine = ($tokens[$openBracket]['line'] - 1); + $argStart = null; + $argEnd = null; + + // Start processing at the first argument. + $i = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); + + if ($tokens[$i]['line'] > ($tokens[$openBracket]['line'] + 1)) { + $error = 'The first argument in a multi-line function call must be on the line after the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, $i, 'FirstArgumentPosition'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($openBracket + 1); $x < $i; $x++) { + if ($tokens[$x]['line'] === $tokens[$openBracket]['line']) { + continue; + } + + if ($tokens[$x]['line'] === $tokens[$i]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $i = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + + if ($tokens[($i - 1)]['code'] === T_WHITESPACE + && $tokens[($i - 1)]['line'] === $tokens[$i]['line'] + ) { + // Make sure we check the indent. + $i--; + } + + for ($i; $i < $closeBracket; $i++) { + if ($i > $argStart && $i < $argEnd) { + $inArg = true; + } else { + $inArg = false; + } + + if ($tokens[$i]['line'] !== $lastLine) { + $lastLine = $tokens[$i]['line']; + + // Ignore heredoc indentation. + if (isset(Tokens::$heredocTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore multi-line string indentation. + if (isset(Tokens::$stringTokens[$tokens[$i]['code']]) === true + && $tokens[$i]['code'] === $tokens[($i - 1)]['code'] + ) { + continue; + } + + // Ignore inline HTML. + if ($tokens[$i]['code'] === T_INLINE_HTML) { + continue; + } + + if ($tokens[$i]['line'] !== $tokens[$openBracket]['line']) { + // We changed lines, so this should be a whitespace indent token, but first make + // sure it isn't a blank line because we don't need to check indent unless there + // is actually some code to indent. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closeBracket + 1), true); + if ($tokens[$nextCode]['line'] !== $lastLine) { + if ($inArg === false) { + $error = 'Empty lines are not allowed in multi-line function calls'; + $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + continue; + } + } else { + $nextCode = $i; + } + + if ($tokens[$nextCode]['line'] === $tokens[$closeBracket]['line']) { + // Closing brace needs to be indented to the same level + // as the function call. + $inArg = false; + $expectedIndent = ($foundFunctionIndent + $adjustment); + } else { + $expectedIndent = ($foundFunctionIndent + $this->indent + $adjustment); + } + + if ($tokens[$i]['code'] !== T_WHITESPACE + && $tokens[$i]['code'] !== T_DOC_COMMENT_WHITESPACE + ) { + // Just check if it is a multi-line block comment. If so, we can + // calculate the indent from the whitespace before the content. + if ($tokens[$i]['code'] === T_COMMENT + && $tokens[($i - 1)]['code'] === T_COMMENT + ) { + $trimmedLength = strlen(ltrim($tokens[$i]['content'])); + if ($trimmedLength === 0) { + // This is a blank comment line, so indenting it is + // pointless. + continue; + } + + $foundIndent = (strlen($tokens[$i]['content']) - $trimmedLength); + } else { + $foundIndent = 0; + } + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($foundIndent < $expectedIndent + || ($inArg === false + && $expectedIndent !== $foundIndent) + ) { + $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $padding = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $padding); + if (isset($tokens[$i]['scope_opener']) === true) { + $phpcsFile->fixer->changeCodeBlockIndent($i, $tokens[$i]['scope_closer'], $expectedIndent); + } + } else { + if ($tokens[$i]['code'] === T_COMMENT) { + $comment = $padding.ltrim($tokens[$i]['content']); + $phpcsFile->fixer->replaceToken($i, $comment); + } else { + $phpcsFile->fixer->replaceToken($i, $padding); + } + + if (isset($tokens[($i + 1)]['scope_opener']) === true) { + $phpcsFile->fixer->changeCodeBlockIndent(($i + 1), $tokens[($i + 1)]['scope_closer'], ($expectedIndent - $foundIndent)); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + } else { + $nextCode = $i; + }//end if + + if ($inArg === false) { + $argStart = $nextCode; + $argEnd = $phpcsFile->findEndOfStatement($nextCode, [T_COLON]); + } + }//end if + + // If we are within an argument we should be ignoring commas + // as these are not signalling the end of an argument. + if ($inArg === false && $tokens[$i]['code'] === T_COMMA) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closeBracket, true); + if ($next === false) { + continue; + } + + if ($this->allowMultipleArguments === false) { + // Comma has to be the last token on the line. + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + $error = 'Only one argument is allowed per line in a multi-line function call'; + $fix = $phpcsFile->addFixableError($error, $next, 'MultipleArguments'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($next - 1); $x > $i; $x--) { + if ($tokens[$x]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore( + $next, + $phpcsFile->eolChar.str_repeat(' ', ($foundFunctionIndent + $this->indent)) + ); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + $argStart = $next; + $argEnd = $phpcsFile->findEndOfStatement($next, [T_COLON]); + }//end if + }//end for + + }//end processMultiLineCall() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php new file mode 100644 index 000000000..1d0745b98 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php @@ -0,0 +1,549 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\OpeningFunctionBraceBsdAllmanSniff; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\OpeningFunctionBraceKernighanRitchieSniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionDeclarationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + if (strtolower($tokens[$stackPtr]['content']) === 'function') { + // Must be one space after the FUNCTION keyword. + if ($tokens[($stackPtr + 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($stackPtr + 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 1) { + $error = 'Expected 1 space after FUNCTION keyword; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterFunction', $data); + if ($fix === true) { + if ($spaces === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + }//end if + + // Must be no space before the opening parenthesis. For closures, this is + // enforced by the previous check because there is no content between the keywords + // and the opening parenthesis. + // Unfinished closures are tokenized as T_FUNCTION however, and can be excluded + // by checking for the scope_opener. + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($tokens[$stackPtr]['code'] === T_FUNCTION + && (isset($tokens[$stackPtr]['scope_opener']) === true || $methodProps['has_body'] === false) + ) { + if ($tokens[($openBracket - 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($openBracket - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($openBracket - 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 0) { + $error = 'Expected 0 spaces before opening parenthesis; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpaceBeforeOpenParen', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket - 1), ''); + } + } + + // Must be no space before semicolon in abstract/interface methods. + if ($methodProps['has_body'] === false) { + $end = $phpcsFile->findNext(T_SEMICOLON, $closeBracket); + if ($end !== false) { + if ($tokens[($end - 1)]['content'] === $phpcsFile->eolChar) { + $spaces = 'newline'; + } else if ($tokens[($end - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($end - 1)]['length']; + } else { + $spaces = 0; + } + + if ($spaces !== 0) { + $error = 'Expected 0 spaces before semicolon; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $end, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($end - 1), ''); + } + } + } + }//end if + }//end if + + // Must be one space before and after USE keyword for closures. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + if ($tokens[($use + 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($use + 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($use + 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space after USE keyword; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $use, 'SpaceAfterUse', $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContent($use, ' '); + } else { + $phpcsFile->fixer->replaceToken(($use + 1), ' '); + } + } + } + + if ($tokens[($use - 1)]['code'] !== T_WHITESPACE) { + $length = 0; + } else if ($tokens[($use - 1)]['content'] === "\t") { + $length = '\t'; + } else { + $length = $tokens[($use - 1)]['length']; + } + + if ($length !== 1) { + $error = 'Expected 1 space before USE keyword; found %s'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $use, 'SpaceBeforeUse', $data); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContentBefore($use, ' '); + } else { + $phpcsFile->fixer->replaceToken(($use - 1), ' '); + } + } + } + }//end if + }//end if + + if ($this->isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens); + } else { + $this->processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens); + } + + }//end process() + + + /** + * Determine if this is a multi-line function declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) + { + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + return true; + } + + // Closures may use the USE keyword and so be multi-line in this way. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + // If the opening and closing parenthesis of the use statement + // are also on the same line, this is a single line declaration. + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $close = $tokens[$open]['parenthesis_closer']; + if ($tokens[$open]['line'] !== $tokens[$close]['line']) { + return true; + } + } + } + + return false; + + }//end isMultiLineDeclaration() + + + /** + * Processes single-line declarations. + * + * Just uses the Generic BSD-Allman brace sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $sniff = new OpeningFunctionBraceKernighanRitchieSniff(); + } else { + $sniff = new OpeningFunctionBraceBsdAllmanSniff(); + } + + $sniff->checkClosures = true; + $sniff->process($phpcsFile, $stackPtr); + + }//end processSingleLineDeclaration() + + + /** + * Processes multi-line declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + $this->processArgumentList($phpcsFile, $stackPtr, $this->indent); + + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$open]['parenthesis_closer']; + } + } + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + // The opening brace needs to be on the same line as the closing parenthesis. + // There should only be one space between the closing parenthesis - or the end of the + // return type - and the opening brace. + $opener = $tokens[$stackPtr]['scope_opener']; + if ($tokens[$opener]['line'] !== $tokens[$closeBracket]['line']) { + $error = 'The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line'; + $code = 'NewlineBeforeOpenBrace'; + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), $closeBracket, true); + if ($tokens[$prev]['line'] === $tokens[$opener]['line']) { + // End of the return type is not on the same line as the close parenthesis. + $phpcsFile->addError($error, $opener, $code); + } else { + $fix = $phpcsFile->addFixableError($error, $opener, $code); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prev, ' {'); + + // If the opener is on a line by itself, removing it will create + // an empty line, so remove the entire line instead. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $closeBracket, true); + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + + if ($tokens[$prev]['line'] < $tokens[$opener]['line'] + && $tokens[$next]['line'] > $tokens[$opener]['line'] + ) { + // Clear the whole line. + for ($i = ($prev + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else { + // Just remove the opener. + $phpcsFile->fixer->replaceToken($opener, ''); + if ($tokens[$next]['line'] === $tokens[$opener]['line'] + && ($opener + 1) !== $next + ) { + $phpcsFile->fixer->replaceToken(($opener + 1), ''); + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + return; + }//end if + }//end if + + $prev = $tokens[($opener - 1)]; + if ($prev['code'] !== T_WHITESPACE) { + $length = 0; + } else { + $length = strlen($prev['content']); + } + + if ($length !== 1) { + $error = 'There must be a single space between the closing parenthesis/return type and the opening brace of a multi-line function declaration; found %s spaces'; + $fix = $phpcsFile->addFixableError($error, ($opener - 1), 'SpaceBeforeOpenBrace', [$length]); + if ($fix === true) { + if ($length === 0) { + $phpcsFile->fixer->addContentBefore($opener, ' '); + } else { + $phpcsFile->fixer->replaceToken(($opener - 1), ' '); + } + } + } + + }//end processMultiLineDeclaration() + + + /** + * Processes multi-line argument list declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $indent The number of spaces code should be indented. + * @param string $type The type of the token the brackets + * belong to. + * + * @return void + */ + public function processArgumentList($phpcsFile, $stackPtr, $indent, $type='function') + { + $tokens = $phpcsFile->getTokens(); + + // We need to work out how far indented the function + // declaration itself is, so we can work out how far to + // indent parameters. + $functionIndent = 0; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) { + break; + } + } + + // Move $i back to the line the function is or to 0. + $i++; + + if ($tokens[$i]['code'] === T_WHITESPACE) { + $functionIndent = $tokens[$i]['length']; + } + + // The closing parenthesis must be on a new line, even + // when checking abstract function definitions. + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + $prev = $phpcsFile->findPrevious( + T_WHITESPACE, + ($closeBracket - 1), + null, + true + ); + + if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line'] + && $tokens[$prev]['line'] === $tokens[$closeBracket]['line'] + ) { + $error = 'The closing parenthesis of a multi-line '.$type.' declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } + } + + // If this is a closure and is using a USE statement, the closing + // parenthesis we need to look at from now on is the closing parenthesis + // of the USE statement. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + $closeBracket = $tokens[$open]['parenthesis_closer']; + + $prev = $phpcsFile->findPrevious( + T_WHITESPACE, + ($closeBracket - 1), + null, + true + ); + + if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line'] + && $tokens[$prev]['line'] === $tokens[$closeBracket]['line'] + ) { + $error = 'The closing parenthesis of a multi-line use declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'UseCloseBracketLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBracket); + } + } + }//end if + }//end if + + // Each line between the parenthesis should be indented 4 spaces. + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $lastLine = $tokens[$openBracket]['line']; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if ($tokens[$i]['line'] !== $lastLine) { + if ($i === $tokens[$stackPtr]['parenthesis_closer'] + || ($tokens[$i]['code'] === T_WHITESPACE + && (($i + 1) === $closeBracket + || ($i + 1) === $tokens[$stackPtr]['parenthesis_closer'])) + ) { + // Closing braces need to be indented to the same level + // as the function. + $expectedIndent = $functionIndent; + } else { + $expectedIndent = ($functionIndent + $indent); + } + + // We changed lines, so this should be a whitespace indent token. + $foundIndent = 0; + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'Blank lines are not allowed in a multi-line '.$type.' declaration'; + $fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // This is an empty line, so don't check the indent. + continue; + } else if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundIndent = $tokens[$i]['length']; + } else if ($tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE) { + $foundIndent = $tokens[$i]['length']; + ++$expectedIndent; + } + + if ($expectedIndent !== $foundIndent) { + $error = 'Multi-line '.$type.' declaration not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Indent', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $spaces); + } else { + $phpcsFile->fixer->replaceToken($i, $spaces); + } + } + } + + $lastLine = $tokens[$i]['line']; + }//end if + + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) === true + ) { + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prevNonEmpty]['code'] !== T_USE) { + // Since PHP 8.1, a default value can contain a class instantiation. + // Skip over these "function calls" as they have their own indentation rules. + $i = $tokens[$i]['parenthesis_closer']; + $lastLine = $tokens[$i]['line']; + continue; + } + } + + if ($tokens[$i]['code'] === T_ARRAY || $tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + // Skip arrays as they have their own indentation rules. + if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) { + $i = $tokens[$i]['bracket_closer']; + } else { + $i = $tokens[$i]['parenthesis_closer']; + } + + $lastLine = $tokens[$i]['line']; + continue; + } + + if ($tokens[$i]['code'] === T_ATTRIBUTE) { + // Skip attributes as they have their own indentation rules. + $i = $tokens[$i]['attribute_closer']; + $lastLine = $tokens[$i]['line']; + continue; + } + }//end for + + }//end processArgumentList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php new file mode 100644 index 000000000..9952daa44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidDefaultValueSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Flag for when we have found a default in our arg list. + // If there is a value without a default after this, it is an error. + $defaultFound = false; + + $params = $phpcsFile->getMethodParameters($stackPtr); + foreach ($params as $param) { + if ($param['variable_length'] === true) { + continue; + } + + if (array_key_exists('default', $param) === true) { + $defaultFound = true; + // Check if the arg is type hinted and using NULL for the default. + // This does not make the argument optional - it just allows NULL + // to be passed in. + if ($param['type_hint'] !== '' && strtolower($param['default']) === 'null') { + $defaultFound = false; + } + + continue; + } + + if ($defaultFound === true) { + $error = 'Arguments with default values must be at the end of the argument list'; + $phpcsFile->addError($error, $param['token'], 'NotAtEnd'); + return; + } + }//end foreach + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php new file mode 100644 index 000000000..c2ed80ac6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidClassNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $className = $phpcsFile->findNext(T_STRING, $stackPtr); + $name = trim($tokens[$className]['content']); + $errorData = [ucfirst($tokens[$stackPtr]['content'])]; + + // Make sure the first letter is a capital. + if (preg_match('|^[A-Z]|', $name) === 0) { + $error = '%s name must begin with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'StartWithCapital', $errorData); + } + + // Check that each new word starts with a capital as well, but don't + // check the first word, as it is checked above. + $validName = true; + $nameBits = explode('_', $name); + $firstBit = array_shift($nameBits); + foreach ($nameBits as $bit) { + if ($bit === '' || $bit[0] !== strtoupper($bit[0])) { + $validName = false; + break; + } + } + + if ($validName === false) { + // Strip underscores because they cause the suggested name + // to be incorrect. + $nameBits = explode('_', trim($name, '_')); + $firstBit = array_shift($nameBits); + if ($firstBit === '') { + $error = '%s name is not valid'; + $phpcsFile->addError($error, $stackPtr, 'Invalid', $errorData); + } else { + $newName = strtoupper($firstBit[0]).substr($firstBit, 1).'_'; + foreach ($nameBits as $bit) { + if ($bit !== '') { + $newName .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + } + + $newName = rtrim($newName, '_'); + $error = '%s name is not valid; consider %s instead'; + $data = $errorData; + $data[] = $newName; + $phpcsFile->addError($error, $stackPtr, 'Invalid', $data); + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 000000000..b1521aa68 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,284 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidFunctionNameSniff extends AbstractScopeSniff +{ + + /** + * A list of all PHP magic methods. + * + * @var array + */ + protected $magicMethods = [ + 'construct' => true, + 'destruct' => true, + 'call' => true, + 'callstatic' => true, + 'get' => true, + 'set' => true, + 'isset' => true, + 'unset' => true, + 'sleep' => true, + 'wakeup' => true, + 'serialize' => true, + 'unserialize' => true, + 'tostring' => true, + 'invoke' => true, + 'set_state' => true, + 'clone' => true, + 'debuginfo' => true, + ]; + + /** + * A list of all PHP magic functions. + * + * @var array + */ + protected $magicFunctions = ['autoload' => true]; + + + /** + * Constructs a PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION], true); + + }//end __construct() + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + + $methodNameLc = strtolower($methodName); + $classNameLc = strtolower($className); + + // Is this a magic method. i.e., is prefixed with "__" ? + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = substr($methodNameLc, 2); + if (isset($this->magicMethods[$magicPart]) === true) { + return; + } + + $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData); + } + + // PHP4 constructors are allowed to break our rules. + if ($methodNameLc === $classNameLc) { + return; + } + + // PHP4 destructors are allowed to break our rules. + if ($methodNameLc === '_'.$classNameLc) { + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + $scope = $methodProps['scope']; + $scopeSpecified = $methodProps['scope_specified']; + + if ($methodProps['scope'] === 'private') { + $isPublic = false; + } else { + $isPublic = true; + } + + // If it's a private method, it must have an underscore on the front. + if ($isPublic === false) { + if ($methodName[0] !== '_') { + $error = 'Private method name "%s" must be prefixed with an underscore'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'yes'); + } + } + + // If it's not a private method, it must not have an underscore on the front. + if ($isPublic === true && $scopeSpecified === true && $methodName[0] === '_') { + $error = '%s method name "%s" must not be prefixed with an underscore'; + $data = [ + ucfirst($scope), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); + } + + $testMethodName = ltrim($methodName, '_'); + + if (Common::isCamelCaps($testMethodName, false, true, false) === false) { + if ($scopeSpecified === true) { + $error = '%s method name "%s" is not in camel caps format'; + $data = [ + ucfirst($scope), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data); + } else { + $error = 'Method name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + // Ignore closures. + return; + } + + if (ltrim($functionName, '_') === '') { + // Ignore special functions. + return; + } + + $errorData = [$functionName]; + + // Is this a magic function. i.e., it is prefixed with "__". + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $magicPart = strtolower(substr($functionName, 2)); + if (isset($this->magicFunctions[$magicPart]) === true) { + return; + } + + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData); + } + + // Function names can be in two parts; the package name and + // the function name. + $packagePart = ''; + $underscorePos = strrpos($functionName, '_'); + if ($underscorePos === false) { + $camelCapsPart = $functionName; + } else { + $packagePart = substr($functionName, 0, $underscorePos); + $camelCapsPart = substr($functionName, ($underscorePos + 1)); + + // We don't care about _'s on the front. + $packagePart = ltrim($packagePart, '_'); + } + + // If it has a package part, make sure the first letter is a capital. + if ($packagePart !== '') { + if ($functionName[0] === '_') { + $error = 'Function name "%s" is invalid; only private methods should be prefixed with an underscore'; + $phpcsFile->addError($error, $stackPtr, 'FunctionUnderscore', $errorData); + } + + if ($functionName[0] !== strtoupper($functionName[0])) { + $error = 'Function name "%s" is prefixed with a package name but does not begin with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'FunctionNoCapital', $errorData); + } + } + + // If it doesn't have a camel caps part, it's not valid. + if (trim($camelCapsPart) === '') { + $error = 'Function name "%s" is not valid; name appears incomplete'; + $phpcsFile->addError($error, $stackPtr, 'FunctionInvalid', $errorData); + return; + } + + $validName = true; + $newPackagePart = $packagePart; + $newCamelCapsPart = $camelCapsPart; + + // Every function must have a camel caps part, so check that first. + if (Common::isCamelCaps($camelCapsPart, false, true, false) === false) { + $validName = false; + $newCamelCapsPart = strtolower($camelCapsPart[0]).substr($camelCapsPart, 1); + } + + if ($packagePart !== '') { + // Check that each new word starts with a capital. + $nameBits = explode('_', $packagePart); + $nameBits = array_filter($nameBits); + foreach ($nameBits as $bit) { + if ($bit[0] !== strtoupper($bit[0])) { + $newPackagePart = ''; + foreach ($nameBits as $bit) { + $newPackagePart .= strtoupper($bit[0]).substr($bit, 1).'_'; + } + + $validName = false; + break; + } + } + } + + if ($validName === false) { + if ($newPackagePart === '') { + $newName = $newCamelCapsPart; + } else { + $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart; + } + + $error = 'Function name "%s" is invalid; consider "%s" instead'; + $data = $errorData; + $data[] = $newName; + $phpcsFile->addError($error, $stackPtr, 'FunctionNameInvalid', $data); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..48674b1e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + return; + } + + $memberName = ltrim($tokens[$stackPtr]['content'], '$'); + $scope = $memberProps['scope']; + $scopeSpecified = $memberProps['scope_specified']; + + if ($memberProps['scope'] === 'private') { + $isPublic = false; + } else { + $isPublic = true; + } + + // If it's a private member, it must have an underscore on the front. + if ($isPublic === false && $memberName[0] !== '_') { + $error = 'Private member variable "%s" must be prefixed with an underscore'; + $data = [$memberName]; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); + return; + } + + // If it's not a private member, it must not have an underscore on the front. + if ($isPublic === true && $scopeSpecified === true && $memberName[0] === '_') { + $error = '%s member variable "%s" must not be prefixed with an underscore'; + $data = [ + ucfirst($scope), + $memberName, + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data); + return; + } + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php new file mode 100644 index 000000000..9c64c328a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php @@ -0,0 +1,204 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ObjectOperatorIndentSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * Indicates whether multilevel indenting is allowed. + * + * @var boolean + */ + public $multilevel = false; + + /** + * Tokens to listen for. + * + * @var array + */ + private $targets = [ + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return $this->targets; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is the first object operator in a chain of them. + $start = $phpcsFile->findStartOfStatement($stackPtr); + $prev = $phpcsFile->findPrevious($this->targets, ($stackPtr - 1), $start); + if ($prev !== false) { + return; + } + + // Make sure this is a chained call. + $end = $phpcsFile->findEndOfStatement($stackPtr); + $next = $phpcsFile->findNext($this->targets, ($stackPtr + 1), $end); + if ($next === false) { + // Not a chained call. + return; + } + + // Determine correct indent. + for ($i = ($start - 1); $i >= 0; $i--) { + if ($tokens[$i]['line'] !== $tokens[$start]['line']) { + $i++; + break; + } + } + + $baseIndent = 0; + if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) { + $baseIndent = $tokens[$i]['length']; + } + + $baseIndent += $this->indent; + + // Determine the scope of the original object operator. + $origBrackets = null; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $origBrackets = $tokens[$stackPtr]['nested_parenthesis']; + } + + $origConditions = null; + if (isset($tokens[$stackPtr]['conditions']) === true) { + $origConditions = $tokens[$stackPtr]['conditions']; + } + + // Check indentation of each object operator in the chain. + // If the first object operator is on a different line than + // the variable, make sure we check its indentation too. + if ($tokens[$stackPtr]['line'] > $tokens[$start]['line']) { + $next = $stackPtr; + } + + $previousIndent = $baseIndent; + + while ($next !== false) { + // Make sure it is in the same scope, otherwise don't check indent. + $brackets = null; + if (isset($tokens[$next]['nested_parenthesis']) === true) { + $brackets = $tokens[$next]['nested_parenthesis']; + } + + $conditions = null; + if (isset($tokens[$next]['conditions']) === true) { + $conditions = $tokens[$next]['conditions']; + } + + if ($origBrackets === $brackets && $origConditions === $conditions) { + // Make sure it starts a line, otherwise don't check indent. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), $stackPtr, true); + $indent = $tokens[($next - 1)]; + if ($tokens[$prev]['line'] !== $tokens[$next]['line'] + && $indent['code'] === T_WHITESPACE + ) { + if ($indent['line'] === $tokens[$next]['line']) { + $foundIndent = strlen($indent['content']); + } else { + $foundIndent = 0; + } + + $minIndent = $previousIndent; + $maxIndent = $previousIndent; + $expectedIndent = $previousIndent; + + if ($this->multilevel === true) { + $minIndent = max(($previousIndent - $this->indent), $baseIndent); + $maxIndent = ($previousIndent + $this->indent); + $expectedIndent = min(max($foundIndent, $minIndent), $maxIndent); + } + + if ($foundIndent < $minIndent || $foundIndent > $maxIndent) { + $error = 'Object operator not indented correctly; expected %s spaces but found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $next, 'Incorrect', $data); + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($next, $spaces); + } else { + $phpcsFile->fixer->replaceToken(($next - 1), $spaces); + } + } + } + + $previousIndent = $expectedIndent; + }//end if + + // It cant be the last thing on the line either. + $content = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($tokens[$content]['line'] !== $tokens[$next]['line']) { + $error = 'Object operator must be at the start of the line, not the end'; + $fix = $phpcsFile->addFixableError($error, $next, 'StartOfLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($next + 1); $x < $content; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewlineBefore($next); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + $next = $phpcsFile->findNext( + $this->targets, + ($next + 1), + null, + false, + null, + true + ); + }//end while + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php new file mode 100644 index 000000000..cb8e46d52 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @@ -0,0 +1,182 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeClosingBraceSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$scopeOpeners; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + // If the scope closer doesn't think it belongs to this scope opener + // then the opener is sharing its closer with other tokens. We only + // want to process the closer once, so skip this one. + if (isset($tokens[$scopeEnd]['scope_condition']) === false + || $tokens[$scopeEnd]['scope_condition'] !== $stackPtr + ) { + return; + } + + // We need to actually find the first piece of content on this line, + // because if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = ($stackPtr - 1); + for ($lineStart; $lineStart > 0; $lineStart--) { + if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + + $lineStart++; + + $startColumn = 1; + if ($tokens[$lineStart]['code'] === T_WHITESPACE) { + $startColumn = $tokens[($lineStart + 1)]['column']; + } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) { + $trimmed = ltrim($tokens[$lineStart]['content']); + if ($trimmed === '') { + $startColumn = $tokens[($lineStart + 1)]['column']; + } else { + $startColumn = (strlen($tokens[$lineStart]['content']) - strlen($trimmed)); + } + } + + // Check that the closing brace is on it's own line. + for ($lastContent = ($scopeEnd - 1); $lastContent > $scopeStart; $lastContent--) { + if ($tokens[$lastContent]['code'] === T_WHITESPACE || $tokens[$lastContent]['code'] === T_OPEN_TAG) { + continue; + } + + if ($tokens[$lastContent]['code'] === T_INLINE_HTML + && ltrim($tokens[$lastContent]['content']) === '' + ) { + continue; + } + + break; + } + + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) { + $error = 'Closing brace must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Line'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($scopeEnd); + } + + return; + } + + // Check now that the closing brace is lined up correctly. + $lineStart = ($scopeEnd - 1); + for ($lineStart; $lineStart > 0; $lineStart--) { + if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) { + break; + } + } + + $lineStart++; + + $braceIndent = 0; + if ($tokens[$lineStart]['code'] === T_WHITESPACE) { + $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1); + } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) { + $trimmed = ltrim($tokens[$lineStart]['content']); + if ($trimmed === '') { + $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1); + } else { + $braceIndent = (strlen($tokens[$lineStart]['content']) - strlen($trimmed) - 1); + } + } + + $fix = false; + if ($tokens[$stackPtr]['code'] === T_CASE + || $tokens[$stackPtr]['code'] === T_DEFAULT + ) { + // BREAK statements should be indented n spaces from the + // CASE or DEFAULT statement. + $expectedIndent = ($startColumn + $this->indent - 1); + if ($braceIndent !== $expectedIndent) { + $error = 'Case breaking statement indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $braceIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'BreakIndent', $data); + } + } else { + $expectedIndent = max(0, ($startColumn - 1)); + if ($braceIndent !== $expectedIndent) { + $error = 'Closing brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $braceIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data); + } + }//end if + + if ($fix === true) { + $spaces = str_repeat(' ', $expectedIndent); + if ($braceIndent === 0) { + $phpcsFile->fixer->addContentBefore($lineStart, $spaces); + } else { + $phpcsFile->fixer->replaceToken($lineStart, ltrim($tokens[$lineStart]['content'])); + $phpcsFile->fixer->addContentBefore($lineStart, $spaces); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php new file mode 100644 index 000000000..e95dc8bda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -0,0 +1,24 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ScopeIndentSniff as GenericScopeIndentSniff; + +class ScopeIndentSniff extends GenericScopeIndentSniff +{ + + /** + * Any scope openers that should not cause an indent. + * + * @var int[] + */ + protected $nonIndentingScopes = [T_SWITCH]; + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc new file mode 100644 index 000000000..6942944b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc @@ -0,0 +1,114 @@ +setLogger(new class {}); + +var_dump(new class(10) extends SomeClass implements SomeInterface { + private $num; + + public function __construct($num) + { + $this->num = $num; + } + + use SomeTrait; +}); + +class IncorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration /* Comment */ { +} + +class CorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration +/* Comment */ +{ +} + +// Don't move phpcs:ignore comments. +class PHPCSIgnoreAnnotationAfterOpeningBrace +{ // phpcs:ignore Standard.Cat.Sniff -- for reasons. +} + +// Moving any of the other trailing phpcs: comments is ok. +class PHPCSAnnotationAfterOpeningBrace +{ // phpcs:disable Standard.Cat.Sniff -- for reasons. +} + +if (!class_exists('ClassOpeningBraceShouldBeIndented')) { + abstract class ClassOpeningBraceShouldBeIndented +{ +} +} + +if (!class_exists('ClassOpeningBraceTooMuchIndentation')) { + final class ClassOpeningBraceTooMuchIndentation + { + } +} + +enum IncorrectBracePlacement {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed new file mode 100644 index 000000000..26688b152 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,125 @@ +setLogger(new class {}); + +var_dump(new class(10) extends SomeClass implements SomeInterface { + private $num; + + public function __construct($num) + { + $this->num = $num; + } + + use SomeTrait; +}); + +class IncorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration /* Comment */ +{ +} + +class CorrectClassDeclarationWithCommentAtEnd extends correctClassDeclaration +/* Comment */ +{ +} + +// Don't move phpcs:ignore comments. +class PHPCSIgnoreAnnotationAfterOpeningBrace +{ // phpcs:ignore Standard.Cat.Sniff -- for reasons. +} + +// Moving any of the other trailing phpcs: comments is ok. +class PHPCSAnnotationAfterOpeningBrace +{ + // phpcs:disable Standard.Cat.Sniff -- for reasons. +} + +if (!class_exists('ClassOpeningBraceShouldBeIndented')) { + abstract class ClassOpeningBraceShouldBeIndented + { +} +} + +if (!class_exists('ClassOpeningBraceTooMuchIndentation')) { + final class ClassOpeningBraceTooMuchIndentation + { + } +} + +enum IncorrectBracePlacement +{ +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc new file mode 100644 index 000000000..ac71fc9f2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.2.inc @@ -0,0 +1,11 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDeclarationSniff + */ +final class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'ClassDeclarationUnitTest.1.inc') { + return; + } + + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClassDeclarationUnitTest.1.inc': + return [ + 21 => 1, + 22 => 1, + 23 => 1, + 27 => 1, + 33 => 1, + 38 => 1, + 49 => 1, + 84 => 1, + 94 => 1, + 99 => 1, + 104 => 1, + 110 => 1, + 114 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'ClassDeclarationUnitTest.2.inc') { + return [11 => 1]; + } + + return[]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc new file mode 100644 index 000000000..bd7d06180 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc @@ -0,0 +1,163 @@ + + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version Release: 1.0 + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Extra_Description_Newlines +{ + +}//end class + + +/** + * Sample class comment + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @version + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class Missing_Newlines_Before_Tags +{ + +}//end class + + +/** + * Simple class comment + * + * @category _wrong_category + * @package PHP_CodeSniffer + * @package ADDITIONAL PACKAGE TAG + * @subpackage SUBPACKAGE TAG + * @author Original Author + * @author Greg Sherwood gsherwood@squiz.net + * @author Mr T + * @author + * @copyright 1997~1994 The PHP Group + * @license http://www.php.net/license/3_0.txt + * @version INVALID VERSION CONTENT + * @see + * @see + * @link sdfsdf + * @see Net_Sample::Net_Sample() + * @see Net_Other + * @deprecated asd + * @unknown Unknown tag + * @since Class available since Release 1.2.0 + */ +class Checking_Tags +{ + class Sub_Class { + + }//end class + + +}//end class + + +/** + * + * + */ +class Empty_Class_Doc +{ + +}//end class + + +/** + * + * + */ +interface Empty_Interface_Doc +{ + +}//end interface + + +/** + * + * + */ +trait Empty_Trait_Doc +{ + +}//end trait + + +/** + * + * + */ +enum Empty_Enum_Doc +{ + +}//end enum + + +/** + * Sample class comment + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +#[Authenticate('admin_logged_in')] +class TodoController extends AbstractController implements MustBeLoggedInInterface +{ +} + +/** + * Docblock + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +abstract readonly class AbstractReadonlyWithDocblock {} + +/* + * Docblock + */ +readonly class ReadonlyWrongStyle {} + +readonly final class ReadonlyFinalWithoutDocblock {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php new file mode 100644 index 000000000..d60c0fe83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.php @@ -0,0 +1,78 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\ClassCommentSniff + */ +final class ClassCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 15 => 1, + 51 => 1, + 63 => 1, + 65 => 2, + 66 => 1, + 68 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 74 => 2, + 75 => 1, + 76 => 1, + 77 => 1, + 85 => 1, + 96 => 5, + 106 => 5, + 116 => 5, + 126 => 5, + 161 => 1, + 163 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 71 => 1, + 73 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc new file mode 100644 index 000000000..0b18fa38a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.1.inc @@ -0,0 +1,53 @@ + +* @author Greg Sherwood gsherwood@squiz.net +* @author Mr T +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1997~1994 The PHP Group +* @license http://www.php.net/license/3_0.txt +* @see +* @see +* @version INVALID VERSION CONTENT +* @see Net_Sample::Net_Sample() +* @see Net_Other +* @deprecated asd +* @since Class available since Release 1.2.0 +* @summary An unknown summary tag +* @package '' +* @subpackage !! +* @author Code AUthor +*/ +require_once '/some/path.php'; +?> + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc new file mode 100644 index 000000000..8845eb190 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.2.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FileComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff + */ +final class FileCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + return [ + 21 => 1, + 23 => 2, + 24 => 1, + 26 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 2, + 33 => 1, + 34 => 1, + 35 => 1, + 40 => 2, + 41 => 2, + 43 => 1, + ]; + + case 'FileCommentUnitTest.2.inc': + case 'FileCommentUnitTest.3.inc': + case 'FileCommentUnitTest.4.inc': + return [1 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + return [ + 29 => 1, + 30 => 1, + 34 => 1, + 43 => 1, + ]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 000000000..a20ba3a72 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,512 @@ + line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function foo(&$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Gettext. + * + */ +function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Complete a step. + * + * @param string $status Status of step to complete. + * @param array $array Array. + * @param string $note Optional note. + * + * @return void + */ +function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { + echo 'foo'; +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + +/** + * Completely invalid format, but should not cause PHP notices. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Processes the test. + * + * @param PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * Processes the test. + * + * @param int $phpcsFile The PHP_CodeSniffer + * file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * @param (Foo&Bar)|null $a Comment. + * @param string $b Comment. + * + * @return void + */ +public function setTranslator($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility protected +private function setTranslator2($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility public +protected function setTranslator3($a, &$b): void +{ + $this->translator = $translator; +} + +private function setTranslator4($a, &$b): void +{ + $this->translator = $translator; +} + +class Bar { + /** + * The PHP5 constructor + * + * @return + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] __construct,__destruct + +class Something implements JsonSerializable { + /** + * Single attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function jsonSerialize() {} + + /** + * Multiple attributes. + * + * @return Something + */ + #[AttributeA] + #[AttributeB] + public function methodName() {} + + /** + * Blank line between docblock and attribute. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + public function blankLineDetectionA() {} + + /** + * Blank line between attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + + public function blankLineDetectionB() {} + + /** + * Blank line between both docblock and attribute and attribute and function declaration. + * + * @return mixed + */ + + #[ReturnTypeWillChange] + + public function blankLineDetectionC() {} +} + +class SpacingAfter { + /** + * There are multiple blank lines between this comment and the next function. + * + * @return void + */ + + + + + + + + + public function multipleBlankLines() {} + + /** + * There are multiple blank lines, and some "empty" lines with only + * spaces/tabs between this comment and the next function. + * + * @return void + */ + + + + + + + + + + public function multipleLinesSomeEmpty() {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed new file mode 100644 index 000000000..fc6d4f7e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc.fixed @@ -0,0 +1,491 @@ + line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function foo(&$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Gettext. + * + */ +function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Complete a step. + * + * @param string $status Status of step to complete. + * @param array $array Array. + * @param string $note Optional note. + * + * @return void + */ +function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { + echo 'foo'; +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +function myFunction(string $name1, string ...$name2) { +} + +/** + * Completely invalid format, but should not cause PHP notices. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Processes the test. + * + * @param PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * Processes the test. + * + * @param int $phpcsFile The PHP_CodeSniffer + * file where the + * token occurred. + * @param int $stackPtr The position in the tokens stack + * where the listening token type + * was found. + * + * @return void + * @see register() + */ +function process(File $phpcsFile, $stackPtr) +{ + +}//end process() + +/** + * @param (Foo&Bar)|null $a Comment. + * @param string $b Comment. + * + * @return void + */ +public function setTranslator($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility protected +private function setTranslator2($a, &$b): void +{ + $this->translator = $translator; +} + +// phpcs:set PEAR.Commenting.FunctionComment minimumVisibility public +protected function setTranslator3($a, &$b): void +{ + $this->translator = $translator; +} + +private function setTranslator4($a, &$b): void +{ + $this->translator = $translator; +} + +class Bar { + /** + * The PHP5 constructor + * + * @return + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set PEAR.Commenting.FunctionComment specialMethods[] __construct,__destruct + +class Something implements JsonSerializable { + /** + * Single attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function jsonSerialize() {} + + /** + * Multiple attributes. + * + * @return Something + */ + #[AttributeA] + #[AttributeB] + public function methodName() {} + + /** + * Blank line between docblock and attribute. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function blankLineDetectionA() {} + + /** + * Blank line between attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function blankLineDetectionB() {} + + /** + * Blank line between both docblock and attribute and attribute and function declaration. + * + * @return mixed + */ + #[ReturnTypeWillChange] + public function blankLineDetectionC() {} +} + +class SpacingAfter { + /** + * There are multiple blank lines between this comment and the next function. + * + * @return void + */ + public function multipleBlankLines() {} + + /** + * There are multiple blank lines, and some "empty" lines with only + * spaces/tabs between this comment and the next function. + * + * @return void + */ + public function multipleLinesSomeEmpty() {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 000000000..62863be62 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff + */ +final class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 28 => 1, + 76 => 1, + 87 => 1, + 103 => 1, + 109 => 1, + 112 => 1, + 122 => 1, + 123 => 2, + 124 => 2, + 125 => 1, + 126 => 1, + 137 => 1, + 138 => 1, + 139 => 1, + 152 => 1, + 155 => 1, + 165 => 1, + 172 => 1, + 183 => 1, + 190 => 2, + 206 => 1, + 234 => 1, + 272 => 1, + 313 => 1, + 317 => 1, + 327 => 1, + 329 => 1, + 332 => 1, + 344 => 1, + 343 => 1, + 345 => 1, + 346 => 1, + 360 => 1, + 361 => 1, + 363 => 1, + 364 => 1, + 406 => 1, + 417 => 1, + 455 => 1, + 464 => 1, + 473 => 1, + 485 => 1, + 501 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc new file mode 100644 index 000000000..187228c2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.inc @@ -0,0 +1,29 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the InlineComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\InlineCommentSniff + */ +final class InlineCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 15 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc new file mode 100644 index 000000000..cc9903aa1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc @@ -0,0 +1,165 @@ + 0); + +do +{ + echo $i; +} while ($i > 0); + +do +{ + echo $i; +} +while ($i > 0); + +do { echo $i; } while ($i > 0); + +do{ + echo $i; +}while($i > 0); + + +// while +while ($i < 1) { + echo $i; +} + +while($i < 1){ + echo $i; +} + +while ($i < 1) { echo $i; } + + +// for +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for($i = 1; $i < 1; $i++){ + echo $i; +} + +for ($i = 1; $i < 1; $i++) { echo $i; } + + +// foreach +foreach ($items as $item) { + echo $item; +} + +foreach($items as $item){ + echo $item; +} + +foreach ($items as $item) { echo $item; } + + +// if +if ($i == 0) { + $i = 1; +} + +if($i == 0){ + $i = 1; +} + +if ($i == 0) { $i = 1; } + + +// else +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + + +// else +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + + +// else if +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} elseif ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else if($i == 2){ + $i = 0; +} + +if ($i == 0) { + $i = 1; +}elseif($i == 2){ + $i = 0; +} + +if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; } +if ($i == 0) { $i = 1; } elseif ($i == 2) { $i = 0; } + +if ($i == 0) { // this is ok because comments are allowed + $i = 1; +} + +if ($i == 0) {// this is ok because comments are allowed + $i = 1; +} + +if ($i == 0) { /* this is ok because comments are allowed*/ + $i = 1; +} + +if ($i == 0) +{ // this is not ok + $i = 1; +} + +if ($i == 0) /* this is ok */ { +} + +if ($i == 0) { +} +else { +} + +// match +$r = match ($x) { + 1 => 1, +}; + +$r = match( $x ){ 1 => 1 }; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php new file mode 100644 index 000000000..b387a93e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ControlSignature sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures\ControlSignatureSniff + */ +final class ControlSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 14 => 1, + 20 => 1, + 22 => 1, + 32 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 56 => 1, + 60 => 1, + 68 => 1, + 72 => 1, + 84 => 1, + 88 => 2, + 100 => 1, + 104 => 2, + 122 => 2, + 128 => 1, + 132 => 3, + 133 => 2, + 147 => 1, + 157 => 1, + 165 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc new file mode 100644 index 000000000..a7a3c69d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc @@ -0,0 +1,251 @@ + +

    some text

    +errorCode() == 401 || // comment + $IPP->errorCode() == 3200) /* long comment + here + */ +{ + return false; +} + +if ($IPP->errorCode() == 401 || // comment + $IPP->errorCode() == 3200) // long comment here +{ + return false; +} + +if ($IPP->errorCode() == 401 + // Comment explaining the next condition here. + || $IPP->errorCode() == 3200 +) { + return false; +} + +function bar() { + if ($a + && $b +) { + return false; + } +} + +if ($a + && foo( + 'a', + 'b' + )) { + return false; +} + +?> + + + + + +errorCode() == 401 || // phpcs:ignore Standard.Category.Sniff -- for reasons. + $IPP->errorCode() == 3200) /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +{ + return false; +} + +if ($IPP->errorCode() == 401 || // phpcs:disable Standard.Category.Sniff -- for reasons. + $IPP->errorCode() == 3200) // phpcs:enable +{ + return false; +} + +if ($IPP->errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 +) { + return false; +} + + if ($IPP->errorCode() == 401 || + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + $IPP->errorCode() == 3200 + ) { + return false; + } + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // A comment. + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + === 'someverylongexpectedoutput' +) { + return false; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed new file mode 100644 index 000000000..7d56c4618 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc.fixed @@ -0,0 +1,247 @@ + +

    some text

    +errorCode() == 401 // comment + || $IPP->errorCode() == 3200 /* long comment + here + */ +) { + return false; +} + +if ($IPP->errorCode() == 401 // comment + || $IPP->errorCode() == 3200 // long comment here +) { + return false; +} + +if ($IPP->errorCode() == 401 + // Comment explaining the next condition here. + || $IPP->errorCode() == 3200 +) { + return false; +} + +function bar() { + if ($a + && $b + ) { + return false; + } +} + +if ($a + && foo( + 'a', + 'b' + ) +) { + return false; +} + +?> + + + + + +errorCode() == 401 // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +) { + return false; +} + +if ($IPP->errorCode() == 401 // phpcs:disable Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 // phpcs:enable +) { + return false; +} + +if ($IPP->errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || $IPP->errorCode() == 3200 +) { + return false; +} + + if ($IPP->errorCode() == 401 + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + || $IPP->errorCode() == 3200 + ) { + return false; + } + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // A comment. + === 'someverylongexpectedoutput' +) { + return false; +} + +if ($IPP->errorCode() == 401 + || $IPP->errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + === 'someverylongexpectedoutput' +) { + return false; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js new file mode 100644 index 000000000..064d7ff7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js @@ -0,0 +1,251 @@ +if (blah(param)) { + +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if ((condition1 || condition2) && condition3 && condition4 && condition5) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ( + (condition1 || condition2) + && condition3 +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 && + condition4 +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if (($condition1 + || $condition2) +) { +} + +if ((condition1 + || condition2) + ) { +} + +if ( + ( + condition1 + || condition2 + ) + && condition3 +) { +} + + +if ( condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if ( + condition1 + || condition2 && + condition3 +) { +} + +if (condition1 + || condition2 +|| condition3) { +} + +if (condition1 + || condition2 || condition3 +){ +} + +if (condition1) + console.info('bar'); + +if (condition1 + || condition2 +|| condition3) + console.info('bar'); + + +if (condition1 + || condition2 || condition3 +) + console.info('bar'); + +if (!a(post) + && (!a(context.header) + ^ a(context.header, 'Content-Type')) +) { +// ... +} + +if (foo) +{ + console.info('bar'); +} + +// Should be no errors even though lines are +// not exactly aligned together. Multi-line function +// call takes precedence. +if (array_key_exists(key, value) + && foo.bar.baz( + key, value2 + ) +) { +} + +if (true) { + foo = true; +}; + +if (foo == 401 || // comment + bar == 3200) /* long comment + here + */ +{ + return false; +} + +if (foo == 401 || // comment + bar == 3200) // long comment here +{ + return false; +} + +if (IPP.errorCode() == 401 + // Comment explaining the next condition here. + || IPP.errorCode() == 3200 +) { + return false; +} + +function bar() { + if (a + && b +) { + return false; + } +} + +if (a + && foo( + 'a', + 'b' + )) { + return false; +} + + + + + + + + + + + + + +if (foo == 401 || // phpcs:ignore Standard.Category.Sniff -- for reasons. + bar == 3200) /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +{ + return false; +} + +if (foo == 401 || // phpcs:disable Standard.Category.Sniff -- for reasons. + bar == 3200) // phpcs:enable +{ + return false; +} + +if (IPP.errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || IPP.errorCode() == 3200 +) { + return false; +} + + if (foo == 401 || + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + bar == 3200 + ) { + return false; + } + +if (IPP.errorCode() == 401 + || IPP.errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if (foo == 401 + || bar + == 'someverylongexpectedoutput' +) { + return false; +} + +if (IPP.errorCode() == 401 + || bar + // A comment. + == 'someverylongexpectedoutput' +) { + return false; +} + +if (foo == 401 + || IPP.errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + == 'someverylongexpectedoutput' +) { + return false; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed new file mode 100644 index 000000000..cfde75d74 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.js.fixed @@ -0,0 +1,247 @@ +if (blah(param)) { + +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if ((condition1 || condition2) && condition3 && condition4 && condition5) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ((condition1 || condition2) + && condition3 +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 +) { +} + +if ((condition1 + || condition2) + && condition3 + && condition4 + && condition5 +) { +} + +if (($condition1 + || $condition2) +) { +} + +if ((condition1 + || condition2) +) { +} + +if ((condition1 + || condition2) + && condition3 +) { +} + + +if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} else if (condition1 + || condition2 + && condition3 +) { +} + +if (condition1 + || condition2 + || condition3 +) { +} + +if (condition1 + || condition2 || condition3 +) { +} + +if (condition1) + console.info('bar'); + +if (condition1 + || condition2 + || condition3 +) + console.info('bar'); + + +if (condition1 + || condition2 || condition3 +) + console.info('bar'); + +if (!a(post) + && (!a(context.header) + ^ a(context.header, 'Content-Type')) +) { +// ... +} + +if (foo) { + console.info('bar'); +} + +// Should be no errors even though lines are +// not exactly aligned together. Multi-line function +// call takes precedence. +if (array_key_exists(key, value) + && foo.bar.baz( + key, value2 + ) +) { +} + +if (true) { + foo = true; +}; + +if (foo == 401 // comment + || bar == 3200 /* long comment + here + */ +) { + return false; +} + +if (foo == 401 // comment + || bar == 3200 // long comment here +) { + return false; +} + +if (IPP.errorCode() == 401 + // Comment explaining the next condition here. + || IPP.errorCode() == 3200 +) { + return false; +} + +function bar() { + if (a + && b + ) { + return false; + } +} + +if (a + && foo( + 'a', + 'b' + ) +) { + return false; +} + + + + + + + + + + + + + +if (foo == 401 // phpcs:ignore Standard.Category.Sniff -- for reasons. + || bar == 3200 /* + phpcs:ignore Standard.Category.Sniff -- for reasons. + */ +) { + return false; +} + +if (foo == 401 // phpcs:disable Standard.Category.Sniff -- for reasons. + || bar == 3200 // phpcs:enable +) { + return false; +} + +if (IPP.errorCode() == 401 + // phpcs:ignore Standard.Category.Sniff -- for reasons. + || IPP.errorCode() == 3200 +) { + return false; +} + + if (foo == 401 + /* + * phpcs:disable Standard.Category.Sniff -- for reasons. + */ + || bar == 3200 + ) { + return false; + } + +if (IPP.errorCode() == 401 + || IPP.errorCode() == 3200 + // phpcs:ignore Standard.Category.Sniff -- for reasons. +) { + return false; +} + +if (foo == 401 + || bar == 'someverylongexpectedoutput' +) { + return false; +} + +if (IPP.errorCode() == 401 + || bar + // A comment. + == 'someverylongexpectedoutput' +) { + return false; +} + +if (foo == 401 + || IPP.errorCode() + // phpcs:ignore Standard.Category.Sniff -- for reasons. + == 'someverylongexpectedoutput' +) { + return false; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php new file mode 100644 index 000000000..263906d18 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.php @@ -0,0 +1,96 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MultiLineCondition sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\ControlStructures\MultiLineConditionSniff + */ +final class MultiLineConditionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + $errors = [ + 21 => 1, + 22 => 1, + 35 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 49 => 1, + 54 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 67 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + 90 => 1, + 96 => 2, + 101 => 1, + 109 => 2, + 125 => 1, + 145 => 2, + 153 => 2, + 168 => 1, + 177 => 1, + 194 => 2, + 202 => 2, + 215 => 1, + 218 => 2, + 232 => 2, + 239 => 1, + 240 => 2, + 248 => 2, + ]; + + if ($testFile === 'MultiLineConditionUnitTest.inc') { + $errors[183] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc new file mode 100644 index 000000000..dadfe9234 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Files/IncludingFileUnitTest.inc @@ -0,0 +1,99 @@ + +
    +Some content goes here.
    +
    +
    + +
    +    Some content goes here.
    +    
    +    
    + +
    +Some content goes here.
    +
    +
    + +
    +    Some content goes here.
    +    
    +    
    + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the IncludingFile sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Files\IncludingFileSniff + */ +final class IncludingFileUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 11 => 1, + 12 => 1, + 16 => 1, + 17 => 1, + 33 => 1, + 34 => 1, + 47 => 1, + 48 => 1, + 64 => 1, + 65 => 1, + 73 => 1, + 74 => 1, + 85 => 1, + 86 => 1, + 98 => 1, + 99 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc new file mode 100644 index 000000000..fc6aea006 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc @@ -0,0 +1,22 @@ +additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = + $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); + +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] + = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax')); +$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = 'boo'; + +$var='string'; + +function getInstalledStandards( + $includeGeneric=false, + $standardsDir='' +) { +} +?> diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php new file mode 100644 index 000000000..1be3296c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Formatting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MultiLineAssignment sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Formatting\MultiLineAssignmentSniff + */ +final class MultiLineAssignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 6 => 1, + 8 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc new file mode 100644 index 000000000..fddd3cba1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc @@ -0,0 +1,576 @@ +getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +$var = myFunction( +$foo, +$bar +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +fputs( + STDOUT, + "Examples: + $ {$app} , --all + $ {$app} --all", $something +); + +$array = array(); +array_map( + function($x) + { + return trim($x, $y); + }, $foo, + $array +); + +$bar = new stdClass( + 4, /* thanks */ 5, /* PSR-2 */ 6 +); + +function doSomething() +{ + return $this->getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +doError( + 404, // status code + 'Not Found', // error name + 'Check your id' // fix +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +// Don't report errors for closing braces. Leave that to other sniffs. +foo( + [ + 'this', + 'is', + 'an', + 'array' + ], +[ + 'this', + 'is', + 'an', + 'array' + ], + array( + 'this', + 'is', +'an', +'array' + ), + array( + 'this', + 'is', + 'an', + 'array' + ), + function($x) + { + echo 'wee'; + + return trim($x); + } +); + +function foo() +{ + myFunction( + 'string'. + // comment + // comment + 'string'. + /* comment + * comment + */ + 'string' + ); +} + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test($arg, $arg2); +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test(); +test( ); +test( ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +?> + + + +
  • + log(// ... + 'error', + sprintf( + 'Message: %s', + isset($e->getData()['object']['evidence_details']) + ? $e->getData()['object']['evidence_details']['due_by'] + : '' + ), + array($e->getData()['object']) +); + +?> +
    + $class + ] + ); ?> +
    + + function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +array_filter( + [1, 2], + function ($i) : bool { + return $i === 0; + } +); + +foo(array( + 'callback' => function () { + $foo = 'foo'; + return; + }, +)); + +foo( + $a, + /* + $c, + + $d, + */ + $e +); + +test( + 1,2,3,4 + ); + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a','b', 'c' + ); + } +} + +$x = $var('y', +'x'); + +$obj->{$x}(1, + 2); + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)('c', + 'd'); + +class Foo +{ + public function bar($a, $b) + { + if (!$a || !$b) { + return; + } + + (new stdClass())->a = $a; + } +} + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})('a','b')('c','d'); + +function foo() +{ + Bar( + function () { + } + ); +} + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 7 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 9 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +printf( + '', + $obj->getName(), // Trailing comment. + $obj->getID(), // phpcs:ignore Standard.Category.SniffName -- for reasons. + $option +); + +// Handling of PHP 7.3 trailing comma's. +functionCall($args, $foo,); +functionCall( + $args, $foo, +); +functionCall( + $args, + $foo, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +$this->foo( + + ['a','b'], + true + +); + +$this->foo( + + // Comment + ['a','b'], + true + +); + +function m() +{ + $t = ' + ' . (empty(true) ? ' + ' . f( + '1', + '2', + ) . ' + ' : ''); +} + +class C +{ + + public function m() + { + $a = []; + $t = + "SELECT * FROM t +WHERE f IN(" . implode( + ",", + $a + ) . ")"; + } +} + +$notices = array( + 'index' => sprintf( + translation_function('a text string with %s placeholder'), + 'replacement' + ), +); + +$componentType = $this->componentTypeRepository->findByType($this->identifier) ?: + $this->componentTypeFactory->createForType( + $this->identifier, + $this->className, + true, + $this->isPrototypal + ); + +return [ + 'export-path' => 'exports/database/' + . env( + 'APP_CUSTOMER', + 'not-configured' + ) + . '/' . env( + 'APP_IDENTIFIER', + 'not-configured' + ), +]; + +$methods .= + str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate + ) + . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + +$rangeValues['min'] = + $this->adjustLowerThreshold( + $this->normalizeRatingForFilter($rangeValues['min']) + ); + +$salesOrderThresholdTransfer->fromArray($salesOrderThresholdEntity->toArray(), true) + ->setSalesOrderThresholdValue( + $this->mapSalesOrderThresholdValueTransfer($salesOrderThresholdTransfer, $salesOrderThresholdEntity) + )->setCurrency( + (new CurrencyTransfer())->fromArray($salesOrderThresholdEntity->getCurrency()->toArray(), true) + )->setStore( + (new StoreTransfer())->fromArray($salesOrderThresholdEntity->getStore()->toArray(), true) + ); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + )); + +$a = ['a' => function ($b) { return $b; }]; +$a['a']( 1 ); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +?> +
    +

    +
    +
    +

    +
    + +content +

    + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed new file mode 100644 index 000000000..1c5252307 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc.fixed @@ -0,0 +1,591 @@ +getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +$var = myFunction( + $foo, + $bar +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +fputs( + STDOUT, + "Examples: + $ {$app} , --all + $ {$app} --all", + $something +); + +$array = array(); +array_map( + function($x) + { + return trim($x, $y); + }, + $foo, + $array +); + +$bar = new stdClass( + 4, /* thanks */ + 5, /* PSR-2 */ + 6 +); + +function doSomething() +{ + return $this->getFoo() + ->doBar( + $this->getX() // no comma here + ->doY() // this is still the first method argument + ->doZ() // this is still the first method argument + ); +} + +doError( + 404, // status code + 'Not Found', // error name + 'Check your id' // fix +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +// Don't report errors for closing braces. Leave that to other sniffs. +foo( + [ + 'this', + 'is', + 'an', + 'array' + ], + [ + 'this', + 'is', + 'an', + 'array' + ], + array( + 'this', + 'is', + 'an', + 'array' + ), + array( + 'this', + 'is', + 'an', + 'array' + ), + function($x) + { + echo 'wee'; + + return trim($x); + } +); + +function foo() +{ + myFunction( + 'string'. + // comment + // comment + 'string'. + /* comment + * comment + */ + 'string' + ); +} + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test( $arg, $arg2 ); +test(); +test(); +test(); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +?> + + + +
  • + log(// ... + 'error', + sprintf( + 'Message: %s', + isset($e->getData()['object']['evidence_details']) + ? $e->getData()['object']['evidence_details']['due_by'] + : '' + ), + array($e->getData()['object']) +); + +?> +
    + $class + ] + ); ?> +
    + + function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +array_filter( + [1, 2], + function ($i) : bool { + return $i === 0; + } +); + +foo( + array( + 'callback' => function () { + $foo = 'foo'; + return; + }, + ) +); + +foo( + $a, + /* + $c, + + $d, + */ + $e +); + +test( + 1,2,3,4 +); + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a','b', 'c' + ); + } +} + +$x = $var( + 'y', + 'x' +); + +$obj->{$x}( + 1, + 2 +); + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)( + 'c', + 'd' +); + +class Foo +{ + public function bar($a, $b) + { + if (!$a || !$b) { + return; + } + + (new stdClass())->a = $a; + } +} + +return (function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})('a','b')('c','d'); + +function foo() +{ + Bar( + function () { + } + ); +} + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 7 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +$deprecated_functions = [ + 'the_category_ID' + => function_call( // 9 spaces, not 8. This is the problem line. + $a, + $b + ), +]; + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false + +printf( + '', + $obj->getName(), // Trailing comment. + $obj->getID(), // phpcs:ignore Standard.Category.SniffName -- for reasons. + $option +); + +// Handling of PHP 7.3 trailing comma's. +functionCall($args, $foo,); +functionCall( + $args, + $foo, +); +functionCall( + $args, + $foo, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +$this->foo( + ['a','b'], + true +); + +$this->foo( + // Comment + ['a','b'], + true +); + +function m() +{ + $t = ' + ' . (empty(true) ? ' + ' . f( + '1', + '2', + ) . ' + ' : ''); +} + +class C +{ + + public function m() + { + $a = []; + $t = + "SELECT * FROM t +WHERE f IN(" . implode( + ",", + $a + ) . ")"; + } +} + +$notices = array( + 'index' => sprintf( + translation_function('a text string with %s placeholder'), + 'replacement' + ), +); + +$componentType = $this->componentTypeRepository->findByType($this->identifier) ?: + $this->componentTypeFactory->createForType( + $this->identifier, + $this->className, + true, + $this->isPrototypal + ); + +return [ + 'export-path' => 'exports/database/' + . env( + 'APP_CUSTOMER', + 'not-configured' + ) + . '/' . env( + 'APP_IDENTIFIER', + 'not-configured' + ), +]; + +$methods .= + str_replace( + array_keys($replacements), + array_values($replacements), + $methodTemplate + ) + . PHP_EOL . PHP_EOL . str_repeat(' ', 4); + +$rangeValues['min'] = + $this->adjustLowerThreshold( + $this->normalizeRatingForFilter($rangeValues['min']) + ); + +$salesOrderThresholdTransfer->fromArray($salesOrderThresholdEntity->toArray(), true) + ->setSalesOrderThresholdValue( + $this->mapSalesOrderThresholdValueTransfer($salesOrderThresholdTransfer, $salesOrderThresholdEntity) + )->setCurrency( + (new CurrencyTransfer())->fromArray($salesOrderThresholdEntity->getCurrency()->toArray(), true) + )->setStore( + (new StoreTransfer())->fromArray($salesOrderThresholdEntity->getStore()->toArray(), true) + ); + +return trim( + preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + ) +); + +$a = ['a' => function ($b) { return $b; }]; +$a['a'](1); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( + 1, + 12, + ), value: true, +); + +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments false +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); +// phpcs:set PEAR.Functions.FunctionCallSignature allowMultipleArguments true + +?> +
    +

    +
    +
    +

    +
    + +content +

    + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js new file mode 100644 index 000000000..5e77e57a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js @@ -0,0 +1,80 @@ +test( +); +test(); +test(arg, arg2); +test (); +test( ); +test() ; +test( arg); +test( arg ); +test ( arg ); + +if (foo(arg) === true) { + +} + +var something = get(arg1, arg2); +var something = get(arg1, arg2) ; +var something = get(arg1, arg2) ; + +make_foo(string/*the string*/, true/*test*/); +make_foo(string/*the string*/, true/*test*/ ); +make_foo(string /*the string*/, true /*test*/); +make_foo(/*the string*/string, /*test*/true); +make_foo( /*the string*/string, /*test*/true); + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test(arg, arg2); +test( arg, arg2 ); +test( arg, arg2 ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +this.init = function(data) { + a.b('').a(function(itemid, target) { + b( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + }, + '', + function() { + var _showAspectItems = function(itemid) { + a.a(a.c(''), ''); + a.b(a.c('-' + itemid), ''); + }; + a.foo(function(itemid, target) { + _foo(itemid); + }); + } + ); + }); +}; + +a.prototype = { + + a: function() + { + this.addItem( + { + /** + * @return void + */ + a: function() + { + + }, + /** + * @return void + */ + a: function() + { + + }, + } + ); + } +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed new file mode 100644 index 000000000..7855ac677 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.js.fixed @@ -0,0 +1,84 @@ +test( +); +test(); +test(arg, arg2); +test(); +test(); +test(); +test(arg); +test(arg); +test(arg); + +if (foo(arg) === true) { + +} + +var something = get(arg1, arg2); +var something = get(arg1, arg2); +var something = get(arg1, arg2); + +make_foo(string/*the string*/, true/*test*/); +make_foo(string/*the string*/, true/*test*/); +make_foo(string /*the string*/, true /*test*/); +make_foo(/*the string*/string, /*test*/true); +make_foo(/*the string*/string, /*test*/true); + +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 1 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 1 +test( arg, arg2 ); +test( arg, arg2 ); +test( arg, arg2 ); +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesAfterOpen 0 +// phpcs:set PEAR.Functions.FunctionCallSignature requiredSpacesBeforeClose 0 + +this.init = function(data) { + a.b('').a( + function(itemid, target) { + b( + itemid, + target, + { + reviewData: _reviewData, + pageid: itemid + }, + '', + function() { + var _showAspectItems = function(itemid) { + a.a(a.c(''), ''); + a.b(a.c('-' + itemid), ''); + }; + a.foo( + function(itemid, target) { + _foo(itemid); + } + ); + } + ); + } + ); +}; + +a.prototype = { + + a: function() + { + this.addItem( + { + /** + * @return void + */ + a: function() + { + + }, + /** + * @return void + */ + a: function() + { + + }, + } + ); + } +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php new file mode 100644 index 000000000..5884bd8f7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionCallSignature sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionCallSignatureSniff + */ +final class FunctionCallSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile === 'FunctionCallSignatureUnitTest.js') { + return [ + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 9 => 2, + 10 => 3, + 17 => 1, + 18 => 1, + 21 => 1, + 24 => 1, + 28 => 2, + 30 => 2, + 35 => 1, + 49 => 1, + 51 => 1, + 54 => 1, + 70 => 1, + 71 => 1, + ]; + }//end if + + return [ + 5 => 1, + 6 => 2, + 7 => 1, + 8 => 1, + 9 => 2, + 10 => 3, + 17 => 1, + 18 => 1, + 31 => 1, + 34 => 1, + 43 => 2, + 57 => 1, + 59 => 1, + 63 => 1, + 64 => 1, + 82 => 1, + 93 => 1, + 100 => 1, + 106 => 2, + 119 => 1, + 120 => 1, + 129 => 1, + 137 => 1, + 142 => 2, + 171 => 1, + 180 => 1, + 181 => 1, + 194 => 1, + 213 => 2, + 215 => 2, + 217 => 2, + 218 => 2, + 277 => 1, + 278 => 1, + 303 => 1, + 308 => 1, + 321 => 1, + 322 => 1, + 329 => 1, + 330 => 1, + 337 => 1, + 342 => 1, + 343 => 1, + 345 => 1, + 346 => 2, + 353 => 1, + 354 => 1, + 355 => 2, + 377 => 1, + 378 => 1, + 379 => 1, + 380 => 1, + 385 => 1, + 386 => 1, + 387 => 1, + 388 => 1, + 393 => 1, + 394 => 1, + 395 => 1, + 396 => 1, + 411 => 1, + 422 => 1, + 424 => 1, + 429 => 1, + 432 => 1, + 440 => 1, + 441 => 1, + 442 => 1, + 464 => 1, + 510 => 1, + 513 => 1, + 514 => 1, + 523 => 1, + 524 => 3, + 527 => 2, + 539 => 1, + 540 => 1, + 546 => 1, + 547 => 1, + 548 => 1, + 559 => 1, + 567 => 1, + 568 => 1, + 573 => 1, + 574 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.1.inc new file mode 100644 index 000000000..6ba3bd9f6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.1.inc @@ -0,0 +1,490 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionDeclarationSniff + */ +final class FunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionDeclarationUnitTest.1.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 17 => 1, + 44 => 1, + 52 => 1, + 61 => 2, + 98 => 1, + 110 => 2, + 120 => 3, + 121 => 1, + 140 => 1, + 145 => 1, + 161 => 2, + 162 => 2, + 164 => 2, + 167 => 2, + 171 => 1, + 173 => 1, + 201 => 1, + 206 => 1, + 208 => 1, + 216 => 1, + 223 => 1, + 230 => 1, + 237 => 1, + 243 => 1, + 247 => 1, + 251 => 2, + 253 => 2, + 257 => 2, + 259 => 1, + 263 => 1, + 265 => 1, + 269 => 1, + 273 => 1, + 277 => 1, + 278 => 1, + 283 => 1, + 287 => 2, + 289 => 2, + 293 => 2, + 295 => 1, + 299 => 1, + 301 => 1, + 305 => 1, + 309 => 1, + 313 => 1, + 314 => 1, + 350 => 1, + 351 => 1, + 352 => 1, + 353 => 1, + 361 => 1, + 362 => 1, + 363 => 1, + 364 => 1, + 365 => 1, + 366 => 1, + 367 => 1, + 368 => 1, + 369 => 1, + 370 => 1, + 371 => 1, + 402 => 1, + 406 => 1, + 475 => 1, + 483 => 1, + 490 => 2, + ]; + + case 'FunctionDeclarationUnitTest.js': + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 17 => 1, + 41 => 1, + 48 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.1.inc new file mode 100644 index 000000000..2503f599d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.1.inc @@ -0,0 +1,116 @@ + $a[] = $b; + +class OnlyConstructorPropertyPromotion { + public function __construct( + public string $name = '', + protected $bar + ) {} +} + +class ConstructorPropertyPromotionMixedWithNormalParams { + public function __construct( + public string $name = '', + ?int $optionalParam = 0, + mixed $requiredParam, + ) {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.2.inc new file mode 100644 index 000000000..3cfece7a1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.2.inc @@ -0,0 +1,7 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidDefaultValue sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\ValidDefaultValueSniff + */ +final class ValidDefaultValueUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ValidDefaultValueUnitTest.1.inc': + return [ + 29 => 1, + 34 => 1, + 39 => 1, + 71 => 1, + 76 => 1, + 81 => 1, + 91 => 1, + 99 => 1, + 101 => 1, + 106 => 1, + 114 => 1, + ]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc new file mode 100644 index 000000000..053a4fee2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidClassName sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidClassNameSniff + */ +final class ValidClassNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 7 => 2, + 9 => 1, + 19 => 1, + 24 => 1, + 26 => 2, + 28 => 1, + 38 => 1, + 40 => 2, + 42 => 2, + 44 => 1, + 46 => 1, + 50 => 1, + 52 => 2, + 54 => 1, + 64 => 1, + 66 => 2, + 68 => 1, + 72 => 1, + 74 => 2, + 76 => 1, + 86 => 1, + 88 => 2, + 90 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc new file mode 100644 index 000000000..18b1a4817 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -0,0 +1,243 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidFunctionName sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff + */ +final class ValidFunctionNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 2, + 18 => 2, + 19 => 2, + 20 => 2, + 24 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 2, + 31 => 2, + 32 => 2, + 33 => 2, + 35 => 1, + 36 => 1, + 37 => 2, + 38 => 2, + 39 => 2, + 40 => 2, + 43 => 1, + 44 => 1, + 45 => 1, + 46 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 73 => 2, + 74 => 2, + 75 => 2, + 76 => 2, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 86 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + 95 => 1, + 96 => 1, + 97 => 1, + 98 => 1, + 99 => 1, + 100 => 1, + 101 => 2, + 102 => 2, + 103 => 2, + 104 => 2, + 123 => 1, + 125 => 1, + 126 => 2, + 129 => 1, + 130 => 1, + 131 => 1, + 132 => 1, + 133 => 1, + 134 => 1, + 135 => 1, + 136 => 1, + 137 => 1, + 138 => 1, + 139 => 1, + 140 => 3, + 141 => 1, + 143 => 1, + 144 => 1, + 145 => 3, + 147 => 2, + 148 => 1, + 149 => 1, + 181 => 1, + 201 => 1, + 203 => 1, + 204 => 2, + 207 => 2, + 212 => 1, + 213 => 1, + 214 => 1, + 235 => 1, + 236 => 2, + 239 => 1, + 242 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 000000000..3c03da3fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,101 @@ +def["POP_{$cc}_A"]}' + and POP_{$cc}_B = +'{$this->def["POP_{$cc}_B"]}')"; + } +} + +class mpgResponse{ + var $term_id; + var $currentTag; + function characterHandler($parser,$data){ + switch($this->currentTag) + { + case "term_id": { + $this->term_id=$data; + break; + } + } + }//end characterHandler +}//end class mpgResponse + +class foo +{ + const bar = <<setLogger( + new class { + private $varName = 'hello'; + private $_varName = 'hello'; +}); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 000000000..c98af3bc5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidVariableName sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidVariableNameSniff + */ +final class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 17 => 1, + 22 => 1, + 92 => 1, + 93 => 1, + 94 => 1, + 99 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc new file mode 100644 index 000000000..b1b09d932 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc @@ -0,0 +1,142 @@ +someFunction("some", "parameter") +->someOtherFunc(23, 42)-> + someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ->andAThirdFunction(); + + $someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +func( + $bar->foo() +) + ->bar(); + +func( + $bar->foo() +) + ->bar( + $bar->foo() + ->bar() + ->func() + ); + +$object + ->setBar($foo) + ->setFoo($bar); + +if ($bar) { + $object + ->setBar($foo) + ->setFoo($bar); +} + +$response -> CompletedTrackDetails -> TrackDetails -> Events; +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$response + -> CompletedTrackDetails +-> TrackDetails + -> Events; + +$var = get_object( + $foo->something() + ->query() +)->two() + ->three(); + +$foo->one( + $foo + ->two() +); + +get_object()->one() + ->two() + ->three(); + +someclass::one() + ->two() + ->three(); + +(new someclass())->one() + ->two() + ->three(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true + +$someObject + ->startSomething() + ->someOtherFunc(23, 42) +->endSomething() +->doSomething(23, 42) +->endEverything(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() +->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") +->someOtherFunc(23, 42)?-> + someOtherFunc2($one, $two) + +->someOtherFunc3(23, 42) + ?->andAThirdFunction(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") +->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + +->someOtherFunc3(23, 42) + ?->andAThirdFunction(); +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$someObject + ->startSomething(paramName: $value) + ->someOtherFunc(nameA: 23, nameB: 42) +->endSomething($value, name: $value) +->endEverything(); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed new file mode 100644 index 000000000..5d5b77bef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc.fixed @@ -0,0 +1,142 @@ +someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ->andAThirdFunction(); + + $someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42); + +$someObject->someFunction("some", "parameter") + ->someOtherFunc(23, 42); + +func( + $bar->foo() +) + ->bar(); + +func( + $bar->foo() +) + ->bar( + $bar->foo() + ->bar() + ->func() + ); + +$object + ->setBar($foo) + ->setFoo($bar); + +if ($bar) { + $object + ->setBar($foo) + ->setFoo($bar); +} + +$response -> CompletedTrackDetails -> TrackDetails -> Events; +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$response + -> CompletedTrackDetails + -> TrackDetails + -> Events; + +$var = get_object( + $foo->something() + ->query() +)->two() + ->three(); + +$foo->one( + $foo + ->two() +); + +get_object()->one() + ->two() + ->three(); + +someclass::one() + ->two() + ->three(); + +(new someclass())->one() + ->two() + ->three(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true + +$someObject + ->startSomething() + ->someOtherFunc(23, 42) + ->endSomething() + ->doSomething(23, 42) + ->endEverything(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +$rootNode + ->one() + ->two() + ->three() + ->four() + ->five(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ?->andAThirdFunction(); + +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel true +$object + ?->setBar($foo) + ?->setFoo($bar); + +$someObject?->someFunction("some", "parameter") + ->someOtherFunc(23, 42) + ?->someOtherFunc2($one, $two) + + ->someOtherFunc3(23, 42) + ?->andAThirdFunction(); +// phpcs:set PEAR.WhiteSpace.ObjectOperatorIndent multilevel false + +$someObject + ->startSomething(paramName: $value) + ->someOtherFunc(nameA: 23, nameB: 42) + ->endSomething($value, name: $value) + ->endEverything(); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php new file mode 100644 index 000000000..9beb77fea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ObjectOperatorIndent sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace\ObjectOperatorIndentSniff + */ +final class ObjectOperatorIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 2, + 6 => 1, + 15 => 1, + 27 => 1, + 37 => 1, + 38 => 1, + 48 => 1, + 49 => 1, + 50 => 1, + 65 => 1, + 69 => 1, + 73 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 95 => 1, + 103 => 1, + 119 => 2, + 122 => 1, + 131 => 1, + 134 => 1, + 140 => 1, + 141 => 1, + 142 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc new file mode 100644 index 000000000..a97aca760 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc @@ -0,0 +1,170 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +switch ($foo) { +case 1: + switch ($bar) { + default: + if ($something) { + echo $string{1}; + } else if ($else) { + switch ($else) { + case 1: + // Do something. + break; + default: + // Do something. + break; + } + } + } +break; +case 2: + // Do something; + break; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + default: + return 'Unknown'; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + return 'Processing.'; + default: + return 'Unknown'; +} + +switch($i) { +case 1: {} +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + exit; + default: + exit; +} + +if ($foo): + if ($bar): + $foo = 1; + elseif ($baz): + $foo = 2; + endif; +endif; + +if ($foo): +elseif ($baz): $foo = 2; +endif; + +?> +
      + +
    • + +
    +
      + +
    • + +
    +
      + +
    • + +
    + +getSummaryCount(); ?> +
    class="empty"> + + 'a', 2 => 'b' }; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' + }; + +enum Enum +{ +} + +enum Suits {} + +enum Cards +{ + } + +?> + + +
    +
    {$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +switch ($foo) { +case 1: + switch ($bar) { + default: + if ($something) { + echo $string{1}; + } else if ($else) { + switch ($else) { + case 1: + // Do something. + break; + default: + // Do something. + break; + } + } + } + break; +case 2: + // Do something; + break; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + default: + return 'Unknown'; +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + return 'Processing.'; + default: + return 'Unknown'; +} + +switch($i) { +case 1: { + } +} + +switch ($httpResponseCode) { + case 100: + case 101: + case 102: + exit; + default: + exit; +} + +if ($foo): + if ($bar): + $foo = 1; + elseif ($baz): + $foo = 2; + endif; +endif; + +if ($foo): +elseif ($baz): $foo = 2; +endif; + +?> +
      + +
    • + +
    +
      + +
    • + +
    +
      + +
    • + +
    + +getSummaryCount(); ?> +
    class="empty"> + + 'a', 2 => 'b' +}; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' +}; + +enum Enum +{ +} + +enum Suits { +} + +enum Cards +{ +} + +?> + + +
    +
    + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ScopeClosingBrace sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace\ScopeClosingBraceSniff + */ +final class ScopeClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 13 => 1, + 24 => 1, + 30 => 1, + 61 => 1, + 65 => 1, + 85 => 1, + 89 => 1, + 98 => 1, + 122 => 1, + 127 => 1, + 135 => 1, + 141 => 1, + 146 => 1, + 149 => 1, + 154 => 1, + 160 => 1, + 164 => 1, + 170 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc new file mode 100644 index 000000000..b122a1476 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc @@ -0,0 +1,314 @@ +hello(); // error here + } + + function hello() // error here + { // no error here as brackets can be put anywhere in the pear standard + echo 'hello'; + } + + function hello2() + { + if (TRUE) { // error here + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; // error here + } + + while (TRUE) { + echo 'hello'; // error here + } + + do { // error here + echo 'hello'; // error here + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* + * + * + * + */ + + /** + */ + + /* + This comment has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = <<hello(); // error here + } + + function hello() // error here + { // no error here as brackets can be put anywhere in the pear standard + echo 'hello'; + } + + function hello2() + { + if (TRUE) { // error here + echo 'hello'; // no error here as its more than 4 spaces. + } else { + echo 'bye'; // error here + } + + while (TRUE) { + echo 'hello'; // error here + } + + do { // error here + echo 'hello'; // error here + } while (TRUE); + } + + function hello3() + { + switch ($hello) { + case 'hello': + break; + } + } + +} + +?> +
    +
    +
    +validate()) {
    +    $safe = $form->getSubmitValues();
    +}
    +?>
    +
    +open(); // error here + } + + public function open() + { + // Some inline stuff that shouldn't error + if (TRUE) echo 'hello'; + foreach ($tokens as $token) echo $token; + } + + /** + * This is a comment 1. + * This is a comment 2. + * This is a comment 3. + * This is a comment 4. + */ + public function close() + { + // All ok. + if (TRUE) { + if (TRUE) { + } else if (FALSE) { + foreach ($tokens as $token) { + switch ($token) { + case '1': + case '2': + if (true) { + if (false) { + if (false) { + if (false) { + echo 'hello'; + } + } + } + } + break; + case '5': + break; + } + do { + while (true) { + foreach ($tokens as $token) { + for ($i = 0; $i < $token; $i++) { + echo 'hello'; + } + } + } + } while (true); + } + } + } + } + + /* + This is another c style comment 1. + This is another c style comment 2. + This is another c style comment 3. + This is another c style comment 4. + This is another c style comment 5. + */ + + /* + * + * + * + */ + + /** + */ + + /* + This comment has a newline in it. + + */ + + public function read() + { + echo 'hello'; + + // no errors below. + $array = array( + 'this', + 'that' => array( + 'hello', + 'hello again' => array( + 'hello', + ), + ), + ); + } +} + +abstract class Test3 +{ + public function parse() + { + + foreach ($t as $ndx => $token) { + if (is_array($token)) { + echo 'here'; + } else { + $ts[] = array("token" => $token, "value" => ''); + + $last = count($ts) - 1; + + switch ($token) { + case '(': + + if ($last >= 3 && + $ts[0]['token'] != T_CLASS && + $ts[$last - 2]['token'] == T_OBJECT_OPERATOR && + $ts[$last - 3]['token'] == T_VARIABLE ) { + + + if (true) { + echo 'hello'; + } + } + array_push($braces, $token); + break; + } + } + } + } +} + +function test() +{ + $o = << + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PEAR\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ScopeIndent sniff. + * + * @covers \PHP_CodeSniffer\Standards\PEAR\Sniffs\WhiteSpace\ScopeIndentSniff + */ +final class ScopeIndentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 10 => 1, + 17 => 1, + 20 => 1, + 24 => 1, + 25 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 58 => 1, + 123 => 1, + 224 => 1, + 225 => 1, + 279 => 1, + 284 => 1, + 311 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml new file mode 100644 index 000000000..1bf94ca54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PEAR/ruleset.xml @@ -0,0 +1,41 @@ + + + The PEAR coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 000000000..eaae99b22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,48 @@ + + + + + + + class Bar { +} + ]]> + + + class Bar { +} + +class Baz { +} + ]]> + + + + + namespace Foo; + +class Bar { +} + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml new file mode 100644 index 000000000..3bb83470f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Files/SideEffectsStandard.xml @@ -0,0 +1,27 @@ + + + + + + + + + + echo "Class Foo loaded." + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml new file mode 100644 index 000000000..66df4e1ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Docs/Methods/CamelCapsMethodNameStandard.xml @@ -0,0 +1,29 @@ + + + + + + + doBar() + { + } +} + ]]> + + + do_bar() + { + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..e3f626b3c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param integer $stackPtr The position of the current token in + * the token stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $errorData = [strtolower($tokens[$stackPtr]['content'])]; + + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], ($tokens[$stackPtr]['scope_closer'] + 1)); + if ($nextClass !== false) { + $error = 'Each %s must be in a file by itself'; + $phpcsFile->addError($error, $nextClass, 'MultipleClasses', $errorData); + $phpcsFile->recordMetric($stackPtr, 'One class per file', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'One class per file', 'yes'); + } + + $namespace = $phpcsFile->findNext([T_NAMESPACE, T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], 0); + if ($tokens[$namespace]['code'] !== T_NAMESPACE) { + $error = 'Each %s must be in a namespace of at least one level (a top-level vendor name)'; + $phpcsFile->addError($error, $stackPtr, 'MissingNamespace', $errorData); + $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Class defined in namespace', 'yes'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php new file mode 100644 index 000000000..68a18d8c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php @@ -0,0 +1,303 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SideEffectsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the token stack. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $result = $this->searchForConflict($phpcsFile, 0, ($phpcsFile->numTokens - 1), $tokens); + + if ($result['symbol'] !== null && $result['effect'] !== null) { + $error = 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line %s and the first side effect is on line %s.'; + $data = [ + $tokens[$result['symbol']]['line'], + $tokens[$result['effect']]['line'], + ]; + $phpcsFile->addWarning($error, 0, 'FoundWithSymbols', $data); + $phpcsFile->recordMetric($stackPtr, 'Declarations and side effects mixed', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Declarations and side effects mixed', 'no'); + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + + /** + * Searches for symbol declarations and side effects. + * + * Returns the positions of both the first symbol declared and the first + * side effect in the file. A NULL value for either indicates nothing was + * found. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $start The token to start searching from. + * @param int $end The token to search to. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return array + */ + private function searchForConflict($phpcsFile, $start, $end, $tokens) + { + $symbols = [ + T_CLASS => T_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + T_FUNCTION => T_FUNCTION, + ]; + + $conditions = [ + T_IF => T_IF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ]; + + $checkAnnotations = $phpcsFile->config->annotations; + + $firstSymbol = null; + $firstEffect = null; + for ($i = $start; $i <= $end; $i++) { + // Respect phpcs:disable comments. + if ($checkAnnotations === true + && $tokens[$i]['code'] === T_PHPCS_DISABLE + && (empty($tokens[$i]['sniffCodes']) === true + || isset($tokens[$i]['sniffCodes']['PSR1']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects']) === true + || isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects.FoundWithSymbols']) === true) + ) { + do { + $i = $phpcsFile->findNext(T_PHPCS_ENABLE, ($i + 1)); + } while ($i !== false + && empty($tokens[$i]['sniffCodes']) === false + && isset($tokens[$i]['sniffCodes']['PSR1']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects']) === false + && isset($tokens[$i]['sniffCodes']['PSR1.Files.SideEffects.FoundWithSymbols']) === false); + + if ($i === false) { + // The entire rest of the file is disabled, + // so return what we have so far. + break; + } + + continue; + } + + // Ignore whitespace and comments. + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore PHP tags. + if ($tokens[$i]['code'] === T_OPEN_TAG + || $tokens[$i]['code'] === T_CLOSE_TAG + ) { + continue; + } + + // Ignore shebang. + if (substr($tokens[$i]['content'], 0, 2) === '#!') { + continue; + } + + // Ignore logical operators. + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true) { + continue; + } + + // Ignore entire namespace, declare, const and use statements. + if ($tokens[$i]['code'] === T_NAMESPACE + || $tokens[$i]['code'] === T_USE + || $tokens[$i]['code'] === T_DECLARE + || $tokens[$i]['code'] === T_CONST + ) { + if (isset($tokens[$i]['scope_opener']) === true) { + $i = $tokens[$i]['scope_closer']; + if ($tokens[$i]['code'] === T_ENDDECLARE) { + $semicolon = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($semicolon !== false && $tokens[$semicolon]['code'] === T_SEMICOLON) { + $i = $semicolon; + } + } + } else { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1)); + if ($semicolon !== false) { + $i = $semicolon; + } + } + + continue; + } + + // Ignore function/class prefixes. + if (isset(Tokens::$methodPrefixes[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_READONLY + ) { + continue; + } + + // Ignore anon classes. + if ($tokens[$i]['code'] === T_ANON_CLASS) { + $i = $tokens[$i]['scope_closer']; + continue; + } + + // Ignore attributes. + if ($tokens[$i]['code'] === T_ATTRIBUTE + && isset($tokens[$i]['attribute_closer']) === true + ) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + // Detect and skip over symbols. + if (isset($symbols[$tokens[$i]['code']]) === true + && isset($tokens[$i]['scope_closer']) === true + ) { + if ($firstSymbol === null) { + $firstSymbol = $i; + } + + $i = $tokens[$i]['scope_closer']; + continue; + } else if ($tokens[$i]['code'] === T_STRING + && strtolower($tokens[$i]['content']) === 'define' + ) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_NULLSAFE_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_DOUBLE_COLON + && $tokens[$prev]['code'] !== T_FUNCTION + ) { + if ($firstSymbol === null) { + $firstSymbol = $i; + } + + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1)); + if ($semicolon !== false) { + $i = $semicolon; + } + + continue; + } + }//end if + + // Special case for defined() as it can be used to see + // if a constant (a symbol) should be defined or not and + // doesn't need to use a full conditional block. + if ($tokens[$i]['code'] === T_STRING + && strtolower($tokens[$i]['content']) === 'defined' + ) { + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($openBracket !== false + && $tokens[$openBracket]['code'] === T_OPEN_PARENTHESIS + && isset($tokens[$openBracket]['parenthesis_closer']) === true + ) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), null, true); + if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_NULLSAFE_OBJECT_OPERATOR + && $tokens[$prev]['code'] !== T_DOUBLE_COLON + && $tokens[$prev]['code'] !== T_FUNCTION + ) { + $i = $tokens[$openBracket]['parenthesis_closer']; + continue; + } + } + }//end if + + // Conditional statements are allowed in symbol files as long as the + // contents is only a symbol definition. So don't count these as effects + // in this case. + if (isset($conditions[$tokens[$i]['code']]) === true) { + if (isset($tokens[$i]['scope_opener']) === false) { + // Probably an "else if", so just ignore. + continue; + } + + $result = $this->searchForConflict( + $phpcsFile, + ($tokens[$i]['scope_opener'] + 1), + ($tokens[$i]['scope_closer'] - 1), + $tokens + ); + + if ($result['symbol'] !== null) { + if ($firstSymbol === null) { + $firstSymbol = $result['symbol']; + } + + if ($result['effect'] !== null) { + // Found a conflict. + $firstEffect = $result['effect']; + break; + } + } + + if ($firstEffect === null) { + $firstEffect = $result['effect']; + } + + $i = $tokens[$i]['scope_closer']; + continue; + }//end if + + if ($firstEffect === null) { + $firstEffect = $i; + } + + if ($firstSymbol !== null) { + // We have a conflict we have to report, so no point continuing. + break; + } + }//end for + + return [ + 'symbol' => $firstSymbol, + 'effect' => $firstEffect, + ]; + + }//end searchForConflict() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php new file mode 100644 index 000000000..0cf1022f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff as GenericCamelCapsFunctionNameSniff; +use PHP_CodeSniffer\Util\Common; + +class CamelCapsMethodNameSniff extends GenericCamelCapsFunctionNameSniff +{ + + + /** + * Processes the tokens within the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * @param int $currScope The position of the current scope. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + // Ignore magic methods. + if (preg_match('|^__[^_]|', $methodName) !== 0) { + $magicPart = strtolower(substr($methodName, 2)); + if (isset($this->magicMethods[$magicPart]) === true + || isset($this->methodsDoubleUnderscore[$magicPart]) === true + ) { + return; + } + } + + $testName = ltrim($methodName, '_'); + if ($testName !== '' && Common::isCamelCaps($testName, false, true, false) === false) { + $error = 'Method name "%s" is not in camel caps format'; + $className = $phpcsFile->getDeclarationName($currScope); + if (isset($className) === false) { + $className = '[Anonymous Class]'; + } + + $errorData = [$className.'::'.$methodName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'CamelCase method name', 'yes'); + } + + }//end processTokenWithinScope() + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc new file mode 100644 index 000000000..58cb85e39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.1.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff + */ +final class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile === 'ClassDeclarationUnitTest.2.inc') { + return []; + } + + return [ + 2 => 1, + 3 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc new file mode 100644 index 000000000..b7e1dc9a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc @@ -0,0 +1,87 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc new file mode 100644 index 000000000..63f256d4e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.10.inc @@ -0,0 +1,8 @@ +define("MAXSIZE", 100); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc new file mode 100644 index 000000000..9499885b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.14.inc @@ -0,0 +1,2 @@ +define("MAXSIZE", 100); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc new file mode 100644 index 000000000..0500d10e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.15.inc @@ -0,0 +1,2 @@ +defined('MINSIZE') or define("MAXSIZE", 100); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc new file mode 100644 index 000000000..588ece584 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.16.inc @@ -0,0 +1,2 @@ +defined('MINSIZE') or define("MAXSIZE", 100); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.17.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.17.inc new file mode 100644 index 000000000..ec81bfeda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.17.inc @@ -0,0 +1,8 @@ +define(); +echo $object -> define(); +Foo::define(); + +$c = new class extends Something{ + + public function someMethod() + { + // ... + } + +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc new file mode 100644 index 000000000..d4ae77eed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inc @@ -0,0 +1,6 @@ + +'; +} + +printHead(); +?> + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc new file mode 100644 index 000000000..7265c6377 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.5.inc @@ -0,0 +1,2 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc new file mode 100644 index 000000000..e02fed4b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Files/SideEffectsUnitTest.6.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SideEffects sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff + */ +final class SideEffectsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Set CLI values before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + if ($testFile === 'SideEffectsUnitTest.12.inc') { + $config->annotations = false; + } + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'SideEffectsUnitTest.3.inc': + case 'SideEffectsUnitTest.4.inc': + case 'SideEffectsUnitTest.5.inc': + case 'SideEffectsUnitTest.10.inc': + case 'SideEffectsUnitTest.12.inc': + case 'SideEffectsUnitTest.15.inc': + case 'SideEffectsUnitTest.16.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc new file mode 100644 index 000000000..7381517f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR1\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the CamelCapsMethodName sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff + */ +final class CamelCapsMethodNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 17 => 1, + 21 => 1, + 25 => 1, + 26 => 1, + 77 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml new file mode 100644 index 000000000..65cbe20e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR1/ruleset.xml @@ -0,0 +1,47 @@ + + + The PSR1 coding standard. + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml new file mode 100644 index 000000000..ae24611d0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClassInstantiationStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClosingBraceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClosingBraceStandard.xml new file mode 100644 index 000000000..b59d734fe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/ClosingBraceStandard.xml @@ -0,0 +1,35 @@ + + + + + + + + +function bar() +{ + // Function content. +} + ]]> + + + echo 'Hello!'; + +function bar() +{ + // Function content. +} //end bar() + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/OpeningBraceSpaceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/OpeningBraceSpaceStandard.xml new file mode 100644 index 000000000..818bbe83a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Classes/OpeningBraceSpaceStandard.xml @@ -0,0 +1,32 @@ + + + + + + + + public function bar() + { + // Method content. + } +} + ]]> + + + + public function bar() + { + // Method content. + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/BooleanOperatorPlacementStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/BooleanOperatorPlacementStandard.xml new file mode 100644 index 000000000..805e15c66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/BooleanOperatorPlacementStandard.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/ControlStructureSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/ControlStructureSpacingStandard.xml new file mode 100644 index 000000000..db4fe8028 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/ControlStructures/ControlStructureSpacingStandard.xml @@ -0,0 +1,124 @@ + + + + + + + ($expr) { +} + ]]> + + + ( $expr) { +} + ]]> + + + + + ($expr) { +} + ]]> + + + ) { +} + ]]> + + + + + + + + $expr1 + && $expr2 +) { +} + ]]> + + + ($expr1 + && $expr2 +) { +} + ]]> + + + + + $expr1 + && $expr2 +) { +} + ]]> + + + $expr1 + && $expr2 + && $expr3 +) { +} + ]]> + + + + + + + + ) { +} + ]]> + + + && $expr2) { +} + ]]> + + + + + ) { +} + ]]> + + + ) { +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/ImportStatementStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/ImportStatementStandard.xml new file mode 100644 index 000000000..66b58de0c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/ImportStatementStandard.xml @@ -0,0 +1,33 @@ + + + + + + + + + + \Vendor\Package\ClassA as A; + +class FooBar extends A +{ + // Class content. +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/OpenTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/OpenTagStandard.xml new file mode 100644 index 000000000..20db18b21 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Files/OpenTagStandard.xml @@ -0,0 +1,40 @@ + + + + + + + + +echo 'hi'; + ]]> + + + echo 'hi'; + ]]> + + + + + + + + + + + ]]> + + + + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml new file mode 100644 index 000000000..95904c9a8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/NullableTypeDeclarationStandard.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/ReturnTypeDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/ReturnTypeDeclarationStandard.xml new file mode 100644 index 000000000..000459c33 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Functions/ReturnTypeDeclarationStandard.xml @@ -0,0 +1,41 @@ + + + + + + + string { + // Closure body. +}; + ]]> + + + string { + // Closure body. +}; + ]]> + + + + + : string { + // Function body. +}; + ]]> + + + : string { + // Function body. +}; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml new file mode 100644 index 000000000..9bb5a8a55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Keywords/ShortFormTypeKeywordsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + (boolean) $isValid; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml new file mode 100644 index 000000000..b74e8b429 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Namespaces/CompoundNamespaceDepthStandard.xml @@ -0,0 +1,28 @@ + + + + + + + + + + SubnamespaceOne\AnotherNamespace\ClassA, + SubnamespaceOne\ClassB, + ClassZ, +}; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml new file mode 100644 index 000000000..981b1d97a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Operators/OperatorSpacingStandard.xml @@ -0,0 +1,27 @@ + + + + + + + $b) { + $variable = $foo ? 'foo' : 'bar'; +} + ]]> + + + $b) { + $variable=$foo?'foo':'bar'; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Properties/ConstantVisibilityStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Properties/ConstantVisibilityStandard.xml new file mode 100644 index 000000000..da9b60a40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Docs/Properties/ConstantVisibilityStandard.xml @@ -0,0 +1,27 @@ + + + + + + + private const BAR = 'bar'; +} + ]]> + + + const BAR = 'bar'; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php new file mode 100644 index 000000000..552bfea46 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/AnonClassDeclarationSniff.php @@ -0,0 +1,246 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\FunctionCallArgumentSpacingSniff; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff; +use PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\MultiLineFunctionDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class AnonClassDeclarationSniff extends ClassDeclarationSniff +{ + + /** + * The PSR2 MultiLineFunctionDeclarations sniff. + * + * @var \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\MultiLineFunctionDeclarationSniff + */ + private $multiLineSniff = null; + + /** + * The Generic FunctionCallArgumentSpacing sniff. + * + * @var \PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\FunctionCallArgumentSpacingSniff + */ + private $functionCallSniff = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ANON_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $this->multiLineSniff = new MultiLineFunctionDeclarationSniff(); + $this->functionCallSniff = new FunctionCallArgumentSpacingSniff(); + + $this->processOpen($phpcsFile, $stackPtr); + $this->processClose($phpcsFile, $stackPtr); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) { + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + if ($this->multiLineSniff->isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) === true) { + $this->processMultiLineArgumentList($phpcsFile, $stackPtr); + } else { + $this->processSingleLineArgumentList($phpcsFile, $stackPtr); + } + + $this->functionCallSniff->checkSpacing($phpcsFile, $stackPtr, $openBracket); + } + + $opener = $tokens[$stackPtr]['scope_opener']; + if ($tokens[$opener]['line'] === $tokens[$stackPtr]['line']) { + return; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $stackPtr, true); + + $implements = $phpcsFile->findPrevious(T_IMPLEMENTS, ($opener - 1), $stackPtr); + if ($implements !== false + && $tokens[$opener]['line'] !== $tokens[$implements]['line'] + && $tokens[$opener]['line'] === $tokens[$prev]['line'] + ) { + // Opening brace must be on a new line as implements list wraps. + $error = 'Opening brace must be on the line after the last implemented interface'; + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceSameLine'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $indent = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[($prev + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($prev + 1), ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->addContentBefore($opener, $indent); + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[$opener]['line'] > ($tokens[$prev]['line'] + 1)) { + // Opening brace is on a new line, so there must be no blank line before it. + $error = 'Opening brace must not be preceded by a blank line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($prev + 1); $x < $opener; $x++) { + if ($tokens[$x]['line'] === $tokens[$prev]['line']) { + // Maintain existing newline. + continue; + } + + if ($tokens[$x]['line'] === $tokens[$opener]['line']) { + // Maintain existing indent. + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end process() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processSingleLineArgumentList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + if ($openBracket === ($closeBracket - 1)) { + return; + } + + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $error = 'Space after opening parenthesis of single-line argument list prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpenBracket'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + + $spaceBeforeClose = 0; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), $openBracket, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Need a newline after these tokens, so ignore this rule. + return; + } + + if ($tokens[$prev]['line'] !== $tokens[$closeBracket]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closeBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closeBracket - 1)]['length']; + } + + if ($spaceBeforeClose !== 0) { + $error = 'Space before closing parenthesis of single-line argument list prohibited'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeCloseBracket'); + if ($fix === true) { + if ($spaceBeforeClose === 'newline') { + $phpcsFile->fixer->beginChangeset(); + + $closingContent = ')'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $closingContent .= ';'; + for ($i = ($closeBracket + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + // We want to jump over any whitespace or inline comment and + // move the closing parenthesis after any other token. + $prev = ($closeBracket - 1); + while (isset(Tokens::$emptyTokens[$tokens[$prev]['code']]) === true) { + if (($tokens[$prev]['code'] === T_COMMENT) + && (strpos($tokens[$prev]['content'], '*/') !== false) + ) { + break; + } + + $prev--; + } + + $phpcsFile->fixer->addContent($prev, $closingContent); + + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + for ($i = ($prevNonWhitespace + 1); $i <= $closeBracket; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket - 1), ''); + }//end if + }//end if + }//end if + + }//end processSingleLineArgumentList() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processMultiLineArgumentList(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + + $this->multiLineSniff->processBracket($phpcsFile, $openBracket, $tokens, 'argument'); + $this->multiLineSniff->processArgumentList($phpcsFile, $stackPtr, $this->indent, 'argument'); + + }//end processMultiLineArgumentList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php new file mode 100644 index 000000000..048cb60cc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClassInstantiationSniff.php @@ -0,0 +1,112 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassInstantiationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the class name. + $allowed = [ + T_STRING => T_STRING, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_PARENT => T_PARENT, + T_VARIABLE => T_VARIABLE, + T_DOLLAR => T_DOLLAR, + T_OBJECT_OPERATOR => T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR => T_NULLSAFE_OBJECT_OPERATOR, + T_DOUBLE_COLON => T_DOUBLE_COLON, + ]; + + $allowed += Tokens::$emptyTokens; + + $classNameEnd = null; + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + if (isset($allowed[$tokens[$i]['code']]) === true) { + continue; + } + + // Bow out when this is an anonymous class. + // Anonymous classes are the only situation which would allow for an attribute + // or for the readonly keyword between "new" and the class "name". + if ($tokens[$i]['code'] === T_ATTRIBUTE + || $tokens[$i]['code'] === T_READONLY + || $tokens[$i]['code'] === T_ANON_CLASS + ) { + return; + } + + if ($tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + ) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + $classNameEnd = $i; + break; + }//end for + + if ($classNameEnd === null) { + return; + } + + if ($tokens[$classNameEnd]['code'] === T_OPEN_PARENTHESIS) { + // Using parenthesis. + return; + } + + if ($classNameEnd === $stackPtr) { + // Failed to find the class name. + return; + } + + $error = 'Parentheses must be used when instantiating a new class'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingParentheses'); + if ($fix === true) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($classNameEnd - 1), null, true); + $phpcsFile->fixer->addContent($prev, '()'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php new file mode 100644 index 000000000..82f215f6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/ClosingBraceSniff.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $closer = $tokens[$stackPtr]['scope_closer']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($closer + 1), null, true); + if ($next === false + || $tokens[$next]['line'] !== $tokens[$closer]['line'] + ) { + return; + } + + $error = 'Closing brace must not be followed by any comment or statement on the same line'; + $phpcsFile->addError($error, $closer, 'StatementAfter'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php new file mode 100644 index 000000000..261f7022d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Classes/OpeningBraceSpaceSniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpeningBraceSpaceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$ooScopeTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $opener = $tokens[$stackPtr]['scope_opener']; + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + if ($next === false + || $tokens[$next]['line'] <= ($tokens[$opener]['line'] + 1) + ) { + return; + } + + $error = 'Opening brace must not be followed by a blank line'; + $fix = $phpcsFile->addFixableError($error, $opener, 'Found'); + if ($fix === false) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php new file mode 100644 index 000000000..dabb3187b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php @@ -0,0 +1,229 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class BooleanOperatorPlacementSniff implements Sniff +{ + + /** + * Used to restrict the placement of the boolean operator. + * + * Allowed value are "first" or "last". + * + * @var string|null + */ + public $allowOnly = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_SWITCH, + T_ELSEIF, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) { + // Conditions are all on the same line. + return; + } + + $find = [ + T_BOOLEAN_AND, + T_BOOLEAN_OR, + ]; + + if ($this->allowOnly === 'first' || $this->allowOnly === 'last') { + $position = $this->allowOnly; + } else { + $position = null; + } + + $operator = $parenOpener; + $error = false; + $operators = []; + + do { + $operator = $phpcsFile->findNext($find, ($operator + 1), $parenCloser); + if ($operator === false) { + break; + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); + if ($prev === false) { + // Parse error. + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + if ($next === false) { + // Parse error. + return; + } + + $firstOnLine = false; + $lastOnLine = false; + + if ($tokens[$prev]['line'] < $tokens[$operator]['line']) { + // The boolean operator is the first content on the line. + $firstOnLine = true; + } + + if ($tokens[$next]['line'] > $tokens[$operator]['line']) { + // The boolean operator is the last content on the line. + $lastOnLine = true; + } + + if ($firstOnLine === true && $lastOnLine === true) { + // The operator is the only content on the line. + // Don't record it because we can't determine + // placement information from looking at it. + continue; + } + + $operators[] = $operator; + + if ($firstOnLine === false && $lastOnLine === false) { + // It's in the middle of content, so we can't determine + // placement information from looking at it, but we may + // still need to process it. + continue; + } + + if ($firstOnLine === true) { + if ($position === null) { + $position = 'first'; + } + + if ($position !== 'first') { + $error = true; + } + } else { + if ($position === null) { + $position = 'last'; + } + + if ($position !== 'last') { + $error = true; + } + } + } while ($operator !== false); + + if ($error === false) { + return; + } + + switch ($this->allowOnly) { + case 'first': + $error = 'Boolean operators between conditions must be at the beginning of the line'; + break; + case 'last': + $error = 'Boolean operators between conditions must be at the end of the line'; + break; + default: + $error = 'Boolean operators between conditions must be at the beginning or end of the line, but not both'; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundMixed'); + if ($fix === false) { + return; + } + + $phpcsFile->fixer->beginChangeset(); + foreach ($operators as $operator) { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + + if ($position === 'last') { + if ($tokens[$next]['line'] === $tokens[$operator]['line']) { + if ($tokens[$prev]['line'] === $tokens[$operator]['line']) { + // Move the content after the operator to the next line. + if ($tokens[($operator + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator + 1), ''); + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $operator, true); + $padding = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->addContent($operator, $phpcsFile->eolChar.$padding); + } else { + // Move the operator to the end of the previous line. + if ($tokens[($operator + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator + 1), ''); + } + + $phpcsFile->fixer->addContent($prev, ' '.$tokens[$operator]['content']); + $phpcsFile->fixer->replaceToken($operator, ''); + } + }//end if + } else { + if ($tokens[$prev]['line'] === $tokens[$operator]['line']) { + if ($tokens[$next]['line'] === $tokens[$operator]['line']) { + // Move the operator, and the rest of the expression, to the next line. + if ($tokens[($operator - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator - 1), ''); + } + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $operator, true); + $padding = str_repeat(' ', ($tokens[$first]['column'] - 1)); + $phpcsFile->fixer->addContentBefore($operator, $phpcsFile->eolChar.$padding); + } else { + // Move the operator to the start of the next line. + if ($tokens[($operator - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($operator - 1), ''); + } + + $phpcsFile->fixer->addContentBefore($next, $tokens[$operator]['content'].' '); + $phpcsFile->fixer->replaceToken($operator, ''); + } + }//end if + }//end if + }//end foreach + + $phpcsFile->fixer->endChangeset(); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..56c4192ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/ControlStructures/ControlStructureSpacingSniff.php @@ -0,0 +1,219 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ControlStructureSpacingSniff as PSR2ControlStructureSpacing; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + /** + * Instance of the PSR2 ControlStructureSpacingSniff sniff. + * + * @var \PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ControlStructureSpacingSniff + */ + private $psr2ControlStructureSpacing; + + + /** + * Constructor. + */ + public function __construct() + { + $this->psr2ControlStructureSpacing = new PSR2ControlStructureSpacing(); + + }//end __construct() + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_ELSEIF, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']) { + // Conditions are all on the same line, so follow PSR2. + return $this->psr2ControlStructureSpacing->process($phpcsFile, $stackPtr); + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($parenOpener + 1), $parenCloser, true); + if ($next === false) { + // No conditions; parse error. + return; + } + + // Check the first expression. + if ($tokens[$next]['line'] !== ($tokens[$parenOpener]['line'] + 1)) { + $error = 'The first expression of a multi-line control structure must be on the line after the opening parenthesis'; + $fix = $phpcsFile->addFixableError($error, $next, 'FirstExpressionLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[$next]['line'] > ($tokens[$parenOpener]['line'] + 1)) { + for ($i = ($parenOpener + 1); $i < $next; $i++) { + if ($tokens[$next]['line'] === $tokens[$i]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + $phpcsFile->fixer->addNewline($parenOpener); + $phpcsFile->fixer->endChangeset(); + } + } + + // Check the indent of each line. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $requiredIndent = ($tokens[$first]['column'] + $this->indent - 1); + for ($i = $parenOpener; $i < $parenCloser; $i++) { + if ($tokens[$i]['column'] !== 1 + || $tokens[($i + 1)]['line'] > $tokens[$i]['line'] + || isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true + ) { + continue; + } + + if (($i + 1) === $parenCloser) { + break; + } + + // Leave indentation inside multi-line strings. + if (isset(Tokens::$textStringTokens[$tokens[$i]['code']]) === true + || isset(Tokens::$heredocTokens[$tokens[$i]['code']]) === true + ) { + continue; + } + + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundIndent = 0; + } else { + $foundIndent = $tokens[$i]['length']; + } + + if ($foundIndent < $requiredIndent) { + $error = 'Each line in a multi-line control structure must be indented at least once; expected at least %s spaces, but found %s'; + $data = [ + $requiredIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'LineIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $padding); + } else { + $phpcsFile->fixer->replaceToken($i, $padding); + } + } + } + }//end for + + // Check the closing parenthesis. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($parenCloser - 1), $parenOpener, true); + if ($tokens[$parenCloser]['line'] !== ($tokens[$prev]['line'] + 1)) { + $error = 'The closing parenthesis of a multi-line control structure must be on the line after the last expression'; + $fix = $phpcsFile->addFixableError($error, $parenCloser, 'CloseParenthesisLine'); + if ($fix === true) { + if ($tokens[$parenCloser]['line'] === $tokens[$prev]['line']) { + $phpcsFile->fixer->addNewlineBefore($parenCloser); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $parenCloser; $i++) { + // Maintain existing newline. + if ($tokens[$i]['line'] === $tokens[$prev]['line']) { + continue; + } + + // Maintain existing indent. + if ($tokens[$i]['line'] === $tokens[$parenCloser]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[$parenCloser]['line'] !== $tokens[$prev]['line']) { + $requiredIndent = ($tokens[$first]['column'] - 1); + $foundIndent = ($tokens[$parenCloser]['column'] - 1); + if ($foundIndent !== $requiredIndent) { + $error = 'The closing parenthesis of a multi-line control structure must be indented to the same level as start of the control structure; expected %s spaces but found %s'; + $data = [ + $requiredIndent, + $foundIndent, + ]; + $fix = $phpcsFile->addFixableError($error, $parenCloser, 'CloseParenthesisIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $requiredIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($parenCloser, $padding); + } else { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), $padding); + } + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php new file mode 100644 index 000000000..d9615f9a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/DeclareStatementSniff.php @@ -0,0 +1,262 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DeclareStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DECLARE]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // Allow a byte-order mark. + $tokens = $phpcsFile->getTokens(); + + // There should be no space between declare keyword and opening parenthesis. + $parenthesis = ($stackPtr + 1); + if ($tokens[($stackPtr + 1)]['type'] !== 'T_OPEN_PARENTHESIS') { + $parenthesis = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + $error = 'Expected no space between declare keyword and opening parenthesis in a declare statement'; + + if ($tokens[$parenthesis]['type'] === 'T_OPEN_PARENTHESIS') { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceFoundAfterDeclare'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } else { + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundAfterDeclare'); + $parenthesis = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($parenthesis + 1)); + } + } + + // There should be no space between open parenthesis and the directive. + $string = $phpcsFile->findNext(T_WHITESPACE, ($parenthesis + 1), null, true); + if ($parenthesis !== false) { + if ($tokens[($parenthesis + 1)]['type'] !== 'T_STRING') { + $error = 'Expected no space between opening parenthesis and directive in a declare statement'; + + if ($tokens[$string]['type'] === 'T_STRING') { + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundBeforeDirective'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ''); + } + } else { + $phpcsFile->addError($error, $string, 'SpaceFoundBeforeDirective'); + $string = $phpcsFile->findNext(T_STRING, ($string + 1)); + } + } + } + + // There should be no space between directive and the equal sign. + $equals = $phpcsFile->findNext(T_WHITESPACE, ($string + 1), null, true); + if ($string !== false) { + // The directive must be in lowercase. + if ($tokens[$string]['content'] !== strtolower($tokens[$string]['content'])) { + $error = 'The directive of a declare statement must be in lowercase'; + $fix = $phpcsFile->addFixableError($error, $string, 'DirectiveNotLowercase'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($string, strtolower($tokens[$string]['content'])); + } + } + + if ($tokens[($string + 1)]['type'] !== 'T_EQUAL') { + $error = 'Expected no space between directive and the equals sign in a declare statement'; + + if ($tokens[$equals]['type'] === 'T_EQUAL') { + $fix = $phpcsFile->addFixableError($error, $equals, 'SpaceFoundAfterDirective'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($string + 1), ''); + } + } else { + $phpcsFile->addError($error, $equals, 'SpaceFoundAfterDirective'); + $equals = $phpcsFile->findNext(T_EQUAL, ($equals + 1)); + } + } + }//end if + + // There should be no space between equal sign and directive value. + $value = $phpcsFile->findNext(T_WHITESPACE, ($equals + 1), null, true); + + if ($value === false) { + // Live coding / parse error. + return; + } + + if ($equals !== false) { + if ($tokens[($equals + 1)]['type'] !== 'T_LNUMBER') { + $error = 'Expected no space between equal sign and the directive value in a declare statement'; + + if ($tokens[$value]['type'] === 'T_LNUMBER') { + $fix = $phpcsFile->addFixableError($error, $value, 'SpaceFoundBeforeDirectiveValue'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($equals + 1), ''); + } + } else { + $phpcsFile->addError($error, $value, 'SpaceFoundBeforeDirectiveValue'); + $value = $phpcsFile->findNext(T_LNUMBER, ($value + 1)); + } + } + } + + $parenthesis = $phpcsFile->findNext(T_WHITESPACE, ($value + 1), null, true); + if ($value !== false) { + if ($tokens[($value + 1)]['type'] !== 'T_CLOSE_PARENTHESIS') { + $error = 'Expected no space between the directive value and closing parenthesis in a declare statement'; + + if ($tokens[$parenthesis]['type'] === 'T_CLOSE_PARENTHESIS') { + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundAfterDirectiveValue'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($value + 1), ''); + } + } else { + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundAfterDirectiveValue'); + $parenthesis = $phpcsFile->findNext(T_CLOSE_PARENTHESIS, ($parenthesis + 1)); + } + } + } + + // Check for semicolon. + $curlyBracket = false; + if ($tokens[($parenthesis + 1)]['type'] !== 'T_SEMICOLON') { + $token = $phpcsFile->findNext(T_WHITESPACE, ($parenthesis + 1), null, true); + + if ($tokens[$token]['type'] === 'T_OPEN_CURLY_BRACKET') { + // Block declaration. + $curlyBracket = $token; + } else if ($tokens[$token]['type'] === 'T_SEMICOLON') { + $error = 'Expected no space between the closing parenthesis and the semicolon in a declare statement'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'SpaceFoundBeforeSemicolon'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ''); + } + } else if ($tokens[$token]['type'] === 'T_CLOSE_TAG') { + if ($tokens[($parenthesis)]['line'] !== $tokens[$token]['line']) { + // Close tag must be on the same line.. + $error = 'The close tag must be on the same line as the declare statement'; + $fix = $phpcsFile->addFixableError($error, $parenthesis, 'CloseTagOnNewLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenthesis + 1), ' '); + } + } + } else { + $error = 'Expected no space between the closing parenthesis and the semicolon in a declare statement'; + $phpcsFile->addError($error, $parenthesis, 'SpaceFoundBeforeSemicolon'); + + // See if there is a semicolon or curly bracket after this token. + $token = $phpcsFile->findNext([T_WHITESPACE, T_COMMENT], ($token + 1), null, true); + if ($tokens[$token]['type'] === 'T_OPEN_CURLY_BRACKET') { + $curlyBracket = $token; + } + }//end if + }//end if + + if ($curlyBracket !== false) { + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBracket - 1), null, true); + $error = 'Expected one space between closing parenthesis and opening curly bracket in a declare statement'; + + // The opening curly bracket must on the same line with a single space between closing bracket. + if ($tokens[$prevToken]['type'] !== 'T_CLOSE_PARENTHESIS') { + $phpcsFile->addError($error, $curlyBracket, 'ExtraSpaceFoundAfterBracket'); + } else if ($phpcsFile->getTokensAsString(($prevToken + 1), ($curlyBracket - $prevToken - 1)) !== ' ') { + $fix = $phpcsFile->addFixableError($error, $curlyBracket, 'ExtraSpaceFoundAfterBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($prevToken + 1), ' '); + $nextToken = ($prevToken + 2); + while ($nextToken !== $curlyBracket) { + $phpcsFile->fixer->replaceToken($nextToken, ''); + $nextToken++; + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $closeCurlyBracket = $tokens[$curlyBracket]['bracket_closer']; + + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($closeCurlyBracket - 1), null, true); + $nextToken = $phpcsFile->findNext([T_WHITESPACE, T_COMMENT], ($closeCurlyBracket + 1), null, true); + $line = $tokens[$closeCurlyBracket]['line']; + + // The closing curly bracket must be on a new line. + if ($tokens[$prevToken]['line'] === $line || $tokens[$nextToken]['line'] === $line) { + if ($tokens[$prevToken]['line'] === $line) { + $error = 'The closing curly bracket of a declare statement must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $prevToken, 'CurlyBracketNotOnNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($prevToken); + } + } + }//end if + + // Closing curly bracket must align with the declare keyword. + if ($tokens[$stackPtr]['column'] !== $tokens[$closeCurlyBracket]['column']) { + $error = 'The closing curly bracket of a declare statements must be aligned with the declare keyword'; + + $fix = $phpcsFile->addFixableError($error, $closeCurlyBracket, 'CloseBracketNotAligned'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closeCurlyBracket - 1), str_repeat(' ', ($tokens[$stackPtr]['column'] - 1))); + } + } + + // The open curly bracket must be the last code on the line. + $token = $phpcsFile->findNext(Tokens::$emptyTokens, ($curlyBracket + 1), null, true); + if ($tokens[$curlyBracket]['line'] === $tokens[$token]['line']) { + $error = 'The open curly bracket of a declare statement must be the last code on the line'; + $fix = $phpcsFile->addFixableError($error, $token, 'CodeFoundAfterCurlyBracket'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($token - 1), null, true); + + for ($i = ($prevToken + 1); $i < $token; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewLineBefore($token); + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php new file mode 100644 index 000000000..f06357d43 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/FileHeaderSniff.php @@ -0,0 +1,429 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FileHeaderSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return int|void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $possibleHeaders = []; + + $searchFor = Tokens::$ooScopeTokens; + $searchFor[T_OPEN_TAG] = T_OPEN_TAG; + + $openTag = $stackPtr; + do { + $headerLines = $this->getHeaderLines($phpcsFile, $openTag); + if (empty($headerLines) === true && $openTag === $stackPtr) { + // No content in the file. + return; + } + + $possibleHeaders[$openTag] = $headerLines; + if (count($headerLines) > 1) { + break; + } + + $next = $phpcsFile->findNext($searchFor, ($openTag + 1)); + if (isset(Tokens::$ooScopeTokens[$tokens[$next]['code']]) === true) { + // Once we find an OO token, the file content has + // definitely started. + break; + } + + $openTag = $next; + } while ($openTag !== false); + + if ($openTag === false) { + // We never found a proper file header. + // If the file has multiple PHP open tags, we know + // that it must be a mix of PHP and HTML (or similar) + // so the header rules do not apply. + if (count($possibleHeaders) > 1) { + return $phpcsFile->numTokens; + } + + // There is only one possible header. + // If it is the first content in the file, it technically + // serves as the file header, and the open tag needs to + // have a newline after it. Otherwise, ignore it. + if ($stackPtr > 0) { + return $phpcsFile->numTokens; + } + + $openTag = $stackPtr; + } else if (count($possibleHeaders) > 1) { + // There are other PHP blocks before the file header. + $error = 'The file header must be the first content in the file'; + $phpcsFile->addError($error, $openTag, 'HeaderPosition'); + } else { + // The first possible header was the file header block, + // so make sure it is the first content in the file. + if ($openTag !== 0) { + // Allow for hashbang lines. + $hashbang = false; + if ($tokens[($openTag - 1)]['code'] === T_INLINE_HTML) { + $content = trim($tokens[($openTag - 1)]['content']); + if (substr($content, 0, 2) === '#!') { + $hashbang = true; + } + } + + if ($hashbang === false) { + $error = 'The file header must be the first content in the file'; + $phpcsFile->addError($error, $openTag, 'HeaderPosition'); + } + } + }//end if + + $this->processHeaderLines($phpcsFile, $possibleHeaders[$openTag]); + + return $phpcsFile->numTokens; + + }//end process() + + + /** + * Gather information about the statements inside a possible file header. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return array + */ + public function getHeaderLines(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + return []; + } + + $headerLines = []; + $headerLines[] = [ + 'type' => 'tag', + 'start' => $stackPtr, + 'end' => $stackPtr, + ]; + + $foundDocblock = false; + + $commentOpeners = Tokens::$scopeOpeners; + unset($commentOpeners[T_NAMESPACE]); + unset($commentOpeners[T_DECLARE]); + unset($commentOpeners[T_USE]); + unset($commentOpeners[T_IF]); + unset($commentOpeners[T_WHILE]); + unset($commentOpeners[T_FOR]); + unset($commentOpeners[T_FOREACH]); + unset($commentOpeners[T_DO]); + unset($commentOpeners[T_TRY]); + + do { + switch ($tokens[$next]['code']) { + case T_DOC_COMMENT_OPEN_TAG: + if ($foundDocblock === true) { + // Found a second docblock, so start of code. + break(2); + } + + // Make sure this is not a code-level docblock. + $end = $tokens[$next]['comment_closer']; + for ($docToken = ($end + 1); $docToken < $phpcsFile->numTokens; $docToken++) { + if (isset(Tokens::$emptyTokens[$tokens[$docToken]['code']]) === true) { + continue; + } + + if ($tokens[$docToken]['code'] === T_ATTRIBUTE + && isset($tokens[$docToken]['attribute_closer']) === true + ) { + $docToken = $tokens[$docToken]['attribute_closer']; + continue; + } + + break; + } + + if ($docToken === $phpcsFile->numTokens) { + $docToken--; + } + + if (isset($commentOpeners[$tokens[$docToken]['code']]) === false + && isset(Tokens::$methodPrefixes[$tokens[$docToken]['code']]) === false + && $tokens[$docToken]['code'] !== T_READONLY + ) { + // Check for an @var annotation. + $annotation = false; + for ($i = $next; $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG + && strtolower($tokens[$i]['content']) === '@var' + ) { + $annotation = true; + break; + } + } + + if ($annotation === false) { + $foundDocblock = true; + $headerLines[] = [ + 'type' => 'docblock', + 'start' => $next, + 'end' => $end, + ]; + } + }//end if + + $next = $end; + break; + case T_DECLARE: + case T_NAMESPACE: + if (isset($tokens[$next]['scope_opener']) === true) { + // If this statement is using bracketed syntax, it doesn't + // apply to the entire files and so is not part of header. + // The header has now ended and the main code block begins. + break(2); + } + + $end = $phpcsFile->findEndOfStatement($next); + + $headerLines[] = [ + 'type' => substr(strtolower($tokens[$next]['type']), 2), + 'start' => $next, + 'end' => $end, + ]; + + $next = $end; + break; + case T_USE: + $type = 'use'; + $useType = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($useType !== false && $tokens[$useType]['code'] === T_STRING) { + $content = strtolower($tokens[$useType]['content']); + if ($content === 'function' || $content === 'const') { + $type .= ' '.$content; + } + } + + $end = $phpcsFile->findEndOfStatement($next); + + $headerLines[] = [ + 'type' => $type, + 'start' => $next, + 'end' => $end, + ]; + + $next = $end; + break; + default: + // Skip comments as PSR-12 doesn't say if these are allowed or not. + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true) { + $next = $phpcsFile->findNext(Tokens::$commentTokens, ($next + 1), null, true); + if ($next === false) { + // We reached the end of the file. + break(2); + } + + $next--; + break; + } + + // We found the start of the main code block. + break(2); + }//end switch + + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + } while ($next !== false); + + return $headerLines; + + }//end getHeaderLines() + + + /** + * Check the spacing and grouping of the statements inside each header block. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $headerLines Header information, as sourced + * from getHeaderLines(). + * + * @return void + */ + public function processHeaderLines(File $phpcsFile, $headerLines) + { + $tokens = $phpcsFile->getTokens(); + + $found = []; + + foreach ($headerLines as $i => $line) { + if (isset($headerLines[($i + 1)]) === false + || $headerLines[($i + 1)]['type'] !== $line['type'] + ) { + // We're at the end of the current header block. + // Make sure there is a single blank line after + // this block. + $next = $phpcsFile->findNext(T_WHITESPACE, ($line['end'] + 1), null, true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$line['end']]['line'] + 2)) { + $error = 'Header blocks must be separated by a single blank line'; + $fix = $phpcsFile->addFixableError($error, $line['end'], 'SpacingAfterBlock'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$line['end']]['line']) { + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($tokens[$next]['line'] === ($tokens[$line['end']]['line'] + 1)) { + $phpcsFile->fixer->addNewline($line['end']); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($line['end'] + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === ($tokens[$line['end']]['line'] + 2)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + // Make sure we haven't seen this next block before. + if (isset($headerLines[($i + 1)]) === true + && isset($found[$headerLines[($i + 1)]['type']]) === true + ) { + $error = 'Similar statements must be grouped together inside header blocks; '; + $error .= 'the first "%s" statement was found on line %s'; + $data = [ + $headerLines[($i + 1)]['type'], + $tokens[$found[$headerLines[($i + 1)]['type']]['start']]['line'], + ]; + $phpcsFile->addError($error, $headerLines[($i + 1)]['start'], 'IncorrectGrouping', $data); + } + } else if ($headerLines[($i + 1)]['type'] === $line['type']) { + // Still in the same block, so make sure there is no + // blank line after this statement. + $next = $phpcsFile->findNext(T_WHITESPACE, ($line['end'] + 1), null, true); + if ($tokens[$next]['line'] > ($tokens[$line['end']]['line'] + 1)) { + $error = 'Header blocks must not contain blank lines'; + $fix = $phpcsFile->addFixableError($error, $line['end'], 'SpacingInsideBlock'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($line['end'] + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$line['end']]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + if (isset($found[$line['type']]) === false) { + $found[$line['type']] = $line; + } + }//end foreach + + /* + Next, check that the order of the header blocks + is correct: + Opening php tag. + File-level docblock. + One or more declare statements. + The namespace declaration of the file. + One or more class-based use import statements. + One or more function-based use import statements. + One or more constant-based use import statements. + */ + + $blockOrder = [ + 'tag' => 'opening PHP tag', + 'docblock' => 'file-level docblock', + 'declare' => 'declare statements', + 'namespace' => 'namespace declaration', + 'use' => 'class-based use imports', + 'use function' => 'function-based use imports', + 'use const' => 'constant-based use imports', + ]; + + foreach (array_keys($found) as $type) { + if ($type === 'tag') { + // The opening tag is always in the correct spot. + continue; + } + + do { + $orderedType = next($blockOrder); + } while ($orderedType !== false && key($blockOrder) !== $type); + + if ($orderedType === false) { + // We didn't find the block type in the rest of the + // ordered array, so it is out of place. + // Error and reset the array to the correct position + // so we can check the next block. + reset($blockOrder); + $prevValidType = 'tag'; + do { + $orderedType = next($blockOrder); + if (isset($found[key($blockOrder)]) === true + && key($blockOrder) !== $type + ) { + $prevValidType = key($blockOrder); + } + } while ($orderedType !== false && key($blockOrder) !== $type); + + $error = 'The %s must follow the %s in the file header'; + $data = [ + $blockOrder[$type], + $blockOrder[$prevValidType], + ]; + $phpcsFile->addError($error, $found[$type]['start'], 'IncorrectOrder', $data); + }//end if + }//end foreach + + }//end processHeaderLines() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php new file mode 100644 index 000000000..65198e861 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/ImportStatementSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ImportStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is not a closure USE group. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return; + } + + if ($phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens) === true) { + // This rule only applies to import statements. + return; + } + + if ($tokens[$next]['code'] === T_STRING + && (strtolower($tokens[$next]['content']) === 'function' + || strtolower($tokens[$next]['content']) === 'const') + ) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + } + + if ($tokens[$next]['code'] !== T_NS_SEPARATOR) { + return; + } + + $error = 'Import statements must not begin with a leading backslash'; + $fix = $phpcsFile->addFixableError($error, $next, 'LeadingSlash'); + + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php new file mode 100644 index 000000000..d0ac5d363 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Files/OpenTagSniff.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class OpenTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current + * token in the stack. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($stackPtr !== 0) { + // This rule only applies if the open tag is on the first line of the file. + return $phpcsFile->numTokens; + } + + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === false) { + // Empty file. + return $phpcsFile->numTokens; + } + + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + // Tag is on a line by itself. + return $phpcsFile->numTokens; + } + + $next = $phpcsFile->findNext(T_INLINE_HTML, 0); + if ($next !== false) { + // This rule only applies to PHP-only files. + return $phpcsFile->numTokens; + } + + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAlone'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($stackPtr); + } + + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php new file mode 100644 index 000000000..4314194d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/NullableTypeDeclarationSniff.php @@ -0,0 +1,94 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NullableTypeDeclarationSniff implements Sniff +{ + + /** + * An array of valid tokens after `T_NULLABLE` occurrences. + * + * @var array + */ + private $validTokens = [ + T_STRING => true, + T_NS_SEPARATOR => true, + T_CALLABLE => true, + T_SELF => true, + T_PARENT => true, + T_STATIC => true, + T_NULL => true, + T_FALSE => true, + T_TRUE => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NULLABLE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $nextNonEmptyPtr = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($nextNonEmptyPtr === false) { + // Parse error or live coding. + return; + } + + $tokens = $phpcsFile->getTokens(); + $nextNonEmptyCode = $tokens[$nextNonEmptyPtr]['code']; + $validTokenFound = isset($this->validTokens[$nextNonEmptyCode]); + + if ($validTokenFound === true && $nextNonEmptyPtr === ($stackPtr + 1)) { + // Valid structure. + return; + } + + $error = 'There must not be a space between the question mark and the type in nullable type declarations'; + + if ($validTokenFound === true) { + // No other tokens then whitespace tokens found; fixable. + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WhitespaceFound'); + if ($fix === true) { + for ($i = ($stackPtr + 1); $i < $nextNonEmptyPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + return; + } + + // Non-whitespace tokens found; trigger error but don't fix. + $phpcsFile->addError($error, $stackPtr, 'UnexpectedCharactersFound'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php new file mode 100644 index 000000000..cf1afc560 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php @@ -0,0 +1,110 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ReturnTypeDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $methodProperties = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProperties['return_type'] === '') { + return; + } + + $returnType = $methodProperties['return_type_token']; + if ($methodProperties['nullable_return_type'] === true) { + $returnType = $phpcsFile->findPrevious(T_NULLABLE, ($returnType - 1)); + } + + if ($tokens[($returnType - 1)]['code'] !== T_WHITESPACE + || $tokens[($returnType - 1)]['content'] !== ' ' + || $tokens[($returnType - 2)]['code'] !== T_COLON + ) { + $error = 'There must be a single space between the colon and type in a return type declaration'; + if ($tokens[($returnType - 1)]['code'] === T_WHITESPACE + && $tokens[($returnType - 2)]['code'] === T_COLON + ) { + $fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($returnType - 1), ' '); + } + } else if ($tokens[($returnType - 1)]['code'] === T_COLON) { + $fix = $phpcsFile->addFixableError($error, $returnType, 'SpaceBeforeReturnType'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($returnType, ' '); + } + } else { + $phpcsFile->addError($error, $returnType, 'SpaceBeforeReturnType'); + } + } + + $colon = $phpcsFile->findPrevious(T_COLON, $returnType); + if ($tokens[($colon - 1)]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'There must not be a space before the colon in a return type declaration'; + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($colon - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { + $fix = $phpcsFile->addFixableError($error, $colon, 'SpaceBeforeColon'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($prev + 1); $x < $colon; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $colon, 'SpaceBeforeColon'); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php new file mode 100644 index 000000000..65d39eb91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Keywords/ShortFormTypeKeywordsSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Keywords; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ShortFormTypeKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_BOOL_CAST, + T_INT_CAST, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $typecast = str_replace(' ', '', $tokens[$stackPtr]['content']); + $typecast = str_replace("\t", '', $typecast); + $typecast = trim($typecast, '()'); + $typecastLc = strtolower($typecast); + + if (($tokens[$stackPtr]['code'] === T_BOOL_CAST + && $typecastLc === 'bool') + || ($tokens[$stackPtr]['code'] === T_INT_CAST + && $typecastLc === 'int') + ) { + return; + } + + $error = 'Short form type keywords must be used. Found: %s'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'LongFound', $data); + if ($fix === true) { + if ($tokens[$stackPtr]['code'] === T_BOOL_CAST) { + $replacement = str_replace($typecast, 'bool', $tokens[$stackPtr]['content']); + } else { + $replacement = str_replace($typecast, 'int', $tokens[$stackPtr]['content']); + } + + $phpcsFile->fixer->replaceToken($stackPtr, $replacement); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php new file mode 100644 index 000000000..34e7f461a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Namespaces/CompoundNamespaceDepthSniff.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class CompoundNamespaceDepthSniff implements Sniff +{ + + /** + * The max depth for compound namespaces. + * + * @var integer + */ + public $maxDepth = 2; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_USE_GROUP]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->maxDepth = (int) $this->maxDepth; + + $tokens = $phpcsFile->getTokens(); + + $end = $phpcsFile->findNext(T_CLOSE_USE_GROUP, ($stackPtr + 1)); + if ($end === false) { + return; + } + + $depth = 1; + for ($i = ($stackPtr + 1); $i <= $end; $i++) { + if ($tokens[$i]['code'] === T_NS_SEPARATOR) { + $depth++; + continue; + } + + if ($i === $end || $tokens[$i]['code'] === T_COMMA) { + // End of a namespace. + if ($depth > $this->maxDepth) { + $error = 'Compound namespaces cannot have a depth more than %s'; + $data = [$this->maxDepth]; + $phpcsFile->addError($error, $i, 'TooDeep', $data); + } + + $depth = 1; + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php new file mode 100644 index 000000000..41628ce3a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Operators/OperatorSpacingSniff.php @@ -0,0 +1,128 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\OperatorSpacingSniff as SquizOperatorSpacingSniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorSpacingSniff extends SquizOperatorSpacingSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + parent::register(); + + $targets = Tokens::$comparisonTokens; + $targets += Tokens::$operators; + $targets += Tokens::$assignmentTokens; + $targets += Tokens::$booleanOperators; + $targets[] = T_INLINE_THEN; + $targets[] = T_INLINE_ELSE; + $targets[] = T_STRING_CONCAT; + $targets[] = T_INSTANCEOF; + + // Also register the contexts we want to specifically skip over. + $targets[] = T_DECLARE; + + return $targets; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip over declare statements as those should be handled by different sniffs. + if ($tokens[$stackPtr]['code'] === T_DECLARE) { + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) { + // Parse error / live coding. + return $phpcsFile->numTokens; + } + + return $tokens[$stackPtr]['parenthesis_closer']; + } + + if ($this->isOperator($phpcsFile, $stackPtr) === false) { + return; + } + + $operator = $tokens[$stackPtr]['content']; + + $checkBefore = true; + $checkAfter = true; + + // Skip short ternary. + if ($tokens[($stackPtr)]['code'] === T_INLINE_ELSE + && $tokens[($stackPtr - 1)]['code'] === T_INLINE_THEN + ) { + $checkBefore = false; + } + + // Skip operator with comment on previous line. + if ($tokens[($stackPtr - 1)]['code'] === T_COMMENT + && $tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] + ) { + $checkBefore = false; + } + + if (isset($tokens[($stackPtr + 1)]) === true) { + // Skip short ternary. + if ($tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[($stackPtr + 1)]['code'] === T_INLINE_ELSE + ) { + $checkAfter = false; + } + } else { + // Skip partial files. + $checkAfter = false; + } + + if ($checkBefore === true && $tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected at least 1 space before "%s"; 0 found'; + $data = [$operator]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } + + if ($checkAfter === true && $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected at least 1 space after "%s"; 0 found'; + $data = [$operator]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php new file mode 100644 index 000000000..8bcf0d568 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Properties/ConstantVisibilitySniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Properties; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConstantVisibilitySniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CONST]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this is a class constant. + if ($phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens) === false) { + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_FINAL; + + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + if (isset(Tokens::$scopeModifiers[$tokens[$prev]['code']]) === true) { + return; + } + + $error = 'Visibility must be declared on all constants if your project supports PHP 7.1 or later'; + $phpcsFile->addWarning($error, $stackPtr, 'NotFound'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php new file mode 100644 index 000000000..70e99d764 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Sniffs/Traits/UseDeclarationSniff.php @@ -0,0 +1,700 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Sniffs\Traits; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Needs to be a use statement directly inside a class. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + if (isset(Tokens::$ooScopeTokens[current($conditions)]) === false) { + return; + } + + $ooToken = key($conditions); + $opener = $tokens[$ooToken]['scope_opener']; + + // Figure out where all the use statements are. + $useTokens = [$stackPtr]; + for ($i = ($stackPtr + 1); $i < $tokens[$ooToken]['scope_closer']; $i++) { + if ($tokens[$i]['code'] === T_USE) { + $useTokens[] = $i; + } + + if (isset($tokens[$i]['scope_closer']) === true) { + $i = $tokens[$i]['scope_closer']; + } + } + + $numUseTokens = count($useTokens); + foreach ($useTokens as $usePos => $useToken) { + if ($usePos === 0) { + /* + This is the first use statement. + */ + + // The first non-comment line must be the use line. + $lastValidContent = $useToken; + for ($i = ($useToken - 1); $i > $opener; $i--) { + if ($tokens[$i]['code'] === T_WHITESPACE + && ($tokens[($i - 1)]['line'] === $tokens[$i]['line'] + || $tokens[($i + 1)]['line'] === $tokens[$i]['line']) + ) { + continue; + } + + if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past the comment. + $i = $tokens[$i]['comment_opener']; + } + + $lastValidContent = $i; + + continue; + } + + break; + }//end for + + if ($tokens[$lastValidContent]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'The first trait import statement must be declared on the first non-comment line after the %s opening brace'; + $data = [strtolower($tokens[$ooToken]['content'])]; + + // Figure out if we can fix this error. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($useToken - 1), ($opener - 1), true); + if ($tokens[$prev]['line'] === $tokens[$opener]['line']) { + $fix = $phpcsFile->addFixableError($error, $useToken, 'UseAfterBrace', $data); + if ($fix === true) { + // We know that the USE statements is the first non-comment content + // in the class, so we just need to remove blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($useToken - 1); $i > $opener; $i--) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + break; + } + + if ($tokens[$i]['line'] === $tokens[$useToken]['line']) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[($i - 1)]['line'] !== $tokens[$i]['line'] + && $tokens[($i + 1)]['line'] !== $tokens[$i]['line'] + ) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (isset(Tokens::$commentTokens[$tokens[$i]['code']]) === true) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past the comment. + $i = $tokens[$i]['comment_opener']; + } + + $lastValidContent = $i; + } + }//end for + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + $phpcsFile->addError($error, $useToken, 'UseAfterBrace', $data); + }//end if + }//end if + } else { + // Make sure this use statement is not on the same line as the previous one. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($useToken - 1), null, true); + if ($prev !== false && $tokens[$prev]['line'] === $tokens[$useToken]['line']) { + $error = 'Each imported trait must be on its own line'; + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($useToken - 1), null, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $useToken, 'SpacingBeforeImport'); + } else { + $fix = $phpcsFile->addFixableError($error, $useToken, 'SpacingBeforeImport'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($useToken - 1); $x > $prev; $x--) { + if ($tokens[$x]['line'] === $tokens[$useToken]['line'] + ) { + // Preserve indent. + continue; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($prev); + if ($tokens[$prev]['line'] === $tokens[$useToken]['line']) { + if ($tokens[($useToken - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($useToken - 1), ''); + } + + $padding = str_repeat(' ', ($tokens[$useTokens[0]]['column'] - 1)); + $phpcsFile->fixer->addContent($prev, $padding); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + $error = 'Expected 1 space after USE in trait import statement; %s found'; + if ($tokens[($useToken + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $useToken, 'SpaceAfterUse', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($useToken, ' '); + } + } else if ($tokens[($useToken + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($useToken + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$useToken]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($useToken + 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $useToken, 'SpaceAfterUse', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($useToken + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($useToken, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($useToken + 1), ' '); + } + } + }//end if + + // Check the formatting of the statement. + if (isset($tokens[$useToken]['scope_opener']) === true) { + $this->processUseGroup($phpcsFile, $useToken); + $end = $tokens[$useToken]['scope_closer']; + } else { + $this->processUseStatement($phpcsFile, $useToken); + $end = $phpcsFile->findNext(T_SEMICOLON, ($useToken + 1)); + if ($end === false) { + // Syntax error. + return; + } + } + + if ($usePos === ($numUseTokens - 1)) { + /* + This is the last use statement. + */ + + $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true); + if ($next === $tokens[$ooToken]['scope_closer']) { + // Last content in the class. + $closer = $tokens[$ooToken]['scope_closer']; + if ($tokens[$closer]['line'] > ($tokens[$end]['line'] + 1)) { + $error = 'There must be no blank line after the last trait import statement at the bottom of a %s'; + $data = [strtolower($tokens[$ooToken]['content'])]; + $fix = $phpcsFile->addFixableError($error, $end, 'BlankLineAfterLastUse', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($end + 1); $i < $closer; $i++) { + if ($tokens[$i]['line'] === $tokens[$end]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$closer]['line']) { + // Don't remove indents. + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else if ($tokens[$next]['code'] !== T_USE) { + // Comments are allowed on the same line as the use statement, so make sure + // we don't error for those. + for ($next = ($end + 1); $next < $tokens[$ooToken]['scope_closer']; $next++) { + if ($tokens[$next]['code'] === T_WHITESPACE) { + continue; + } + + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$end]['line'] + ) { + continue; + } + + break; + } + + if ($tokens[$next]['line'] <= ($tokens[$end]['line'] + 1)) { + $error = 'There must be a blank line following the last trait import statement'; + $fix = $phpcsFile->addFixableError($error, $end, 'NoBlankLineAfterUse'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$useToken]['line']) { + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else { + for ($i = ($next - 1); $i > $end; $i--) { + if ($tokens[$i]['line'] !== $tokens[$next]['line']) { + break; + } + } + + $phpcsFile->fixer->addNewlineBefore(($i + 1)); + } + } + } + }//end if + } else { + // Ensure use statements are grouped. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($next !== $useTokens[($usePos + 1)]) { + $error = 'Imported traits must be grouped together'; + $phpcsFile->addError($error, $useTokens[($usePos + 1)], 'NotGrouped'); + } + }//end if + }//end foreach + + return $tokens[$ooToken]['scope_closer']; + + }//end process() + + + /** + * Processes a group use statement. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processUseGroup(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $opener = $tokens[$stackPtr]['scope_opener']; + $closer = $tokens[$stackPtr]['scope_closer']; + + if ($tokens[$opener]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'The opening brace of a trait import statement must be on the same line as the USE keyword'; + // Figure out if we can fix this error. + $canFix = true; + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + && $tokens[$i]['code'] !== T_WHITESPACE + ) { + $canFix = false; + break; + } + } + + if ($canFix === true) { + $fix = $phpcsFile->addFixableError($error, $opener, 'OpenBraceNewLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['line'] !== $tokens[($i + 1)]['line']) { + // Everything should have a single space around it. + $phpcsFile->fixer->replaceToken($i, ' '); + } + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError($error, $opener, 'OpenBraceNewLine'); + } + }//end if + + $error = 'Expected 1 space before opening brace in trait import statement; %s found'; + if ($tokens[($opener - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceBeforeOpeningBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($opener, ' '); + } + } else if ($tokens[($opener - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), null, true); + if ($tokens[$prev]['line'] !== $tokens[$opener]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($opener - 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceBeforeOpeningBrace', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($opener - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($opener, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($opener - 1), ' '); + } + } + }//end if + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($opener + 1), ($closer - 1), true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'First trait conflict resolution statement must be on the line after the opening brace'; + $nextNonWs = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), ($closer - 1), true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $opener, 'SpaceAfterOpeningBrace'); + } else { + $fix = $phpcsFile->addFixableError($error, $opener, 'SpaceAfterOpeningBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($opener + 1); $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + // Preserve indent. + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($opener); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + for ($i = ($stackPtr + 1); $i < $opener; $i++) { + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + if ($tokens[($i - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected no space before comma in trait import statement; %s found'; + $data = [$tokens[($i - 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i - 1), ''); + } + } + + $error = 'Expected 1 space after comma in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $opener, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterComma', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + }//end if + }//end for + + for ($i = ($opener + 1); $i < $closer; $i++) { + if ($tokens[$i]['code'] === T_INSTEADOF) { + $error = 'Expected 1 space before INSTEADOF in trait import statement; %s found'; + if ($tokens[($i - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeInsteadof', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($i, ' '); + } + } else if ($tokens[($i - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), $opener, true); + if ($tokens[$prev]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i - 1)]['length']; + } + + $data = [$found]; + + $prevNonWs = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $opener, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $i, 'SpaceBeforeInsteadof', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeInsteadof', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), ' '); + } + } + } + }//end if + + $error = 'Expected 1 space after INSTEADOF in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterInsteadof', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $closer, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closer, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'SpaceAfterInsteadof', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterInsteadof', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + } + }//end if + }//end if + + if ($tokens[$i]['code'] === T_AS) { + $error = 'Expected 1 space before AS in trait import statement; %s found'; + if ($tokens[($i - 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($i, ' '); + } + } else if ($tokens[($i - 1)]['content'] !== ' ') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), $opener, true); + if ($tokens[$prev]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i - 1)]['length']; + } + + $data = [$found]; + + $prevNonWs = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($i - 1), $opener, true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $i, 'SpaceBeforeAs', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i - 1); $x > $prev; $x--) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContentBefore($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), ' '); + } + } + } + }//end if + + $error = 'Expected 1 space after AS in trait import statement; %s found'; + if ($tokens[($i + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $closer, true); + if ($tokens[$next]['line'] !== $tokens[$i]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($i + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), $closer, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'SpaceAfterAs', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterAs', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($i + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($i, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + } + }//end if + }//end if + + if ($tokens[$i]['code'] === T_SEMICOLON) { + if ($tokens[($i - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected no space before semicolon in trait import statement; %s found'; + $data = [$tokens[($i - 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i - 1), ''); + } + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), ($closer - 1), true); + if ($next !== false && $tokens[$next]['line'] === $tokens[$i]['line']) { + $error = 'Each trait conflict resolution statement must be on a line by itself'; + $nextNonWs = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closer - 1), true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $i, 'ConflictSameLine'); + } else { + $fix = $phpcsFile->addFixableError($error, $i, 'ConflictSameLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($tokens[($i + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($i + 1), ''); + } + + $phpcsFile->fixer->addNewline($i); + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end for + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closer - 1), ($opener + 1), true); + if ($prev !== false && $tokens[$prev]['line'] !== ($tokens[$closer]['line'] - 1)) { + $error = 'Closing brace must be on the line after the last trait conflict resolution statement'; + $prevNonWs = $phpcsFile->findPrevious(T_WHITESPACE, ($closer - 1), ($opener + 1), true); + if ($prevNonWs !== $prev) { + $phpcsFile->addError($error, $closer, 'SpaceBeforeClosingBrace'); + } else { + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeClosingBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($closer - 1); $x > $prev; $x--) { + if ($tokens[$x]['line'] === $tokens[$closer]['line']) { + // Preserve indent. + continue; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processUseGroup() + + + /** + * Processes a single use statement. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processUseStatement(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $next = $phpcsFile->findNext([T_COMMA, T_SEMICOLON], ($stackPtr + 1)); + if ($next !== false && $tokens[$next]['code'] === T_COMMA) { + $error = 'Each imported trait must have its own "use" import statement'; + $fix = $phpcsFile->addFixableError($error, $next, 'MultipleImport'); + if ($fix === true) { + $padding = str_repeat(' ', ($tokens[$stackPtr]['column'] - 1)); + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar.$padding.'use '); + } + } + + }//end processUseStatement() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc new file mode 100644 index 000000000..386b12c22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc @@ -0,0 +1,96 @@ +bar( + new class implements Bar { + // ... + }, +); + +foo(new class { +}); + +// Issue #3790: OpenBraceSameLine fixer should not remove open brace. +$instance = new class() extends SomeClass implements + SomeInterface{ + public function __construct() {} +}; + +// PHP 8.3 readonly anonymous classes. +$anon = new readonly class {}; +$anon = new readonly class {}; +$anon = new readonly + class {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..28b38f708 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.inc.fixed @@ -0,0 +1,98 @@ +bar( + new class implements Bar { + // ... + }, +); + +foo(new class { +}); + +// Issue #3790: OpenBraceSameLine fixer should not remove open brace. +$instance = new class () extends SomeClass implements + SomeInterface +{ + public function __construct() {} +}; + +// PHP 8.3 readonly anonymous classes. +$anon = new readonly class {}; +$anon = new readonly class {}; +$anon = new readonly class {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php new file mode 100644 index 000000000..240352704 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/AnonClassDeclarationUnitTest.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the AnonClassDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes\AnonClassDeclarationSniff + */ +final class AnonClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 28 => 3, + 30 => 1, + 31 => 4, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 3, + 39 => 1, + 40 => 1, + 43 => 3, + 44 => 4, + 45 => 1, + 48 => 1, + 52 => 3, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 2, + 63 => 1, + 75 => 1, + 87 => 1, + 88 => 1, + 94 => 1, + 96 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc new file mode 100644 index 000000000..264116779 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc @@ -0,0 +1,51 @@ +bar(); +echo (new Foo)->bar(); +echo (new Foo((new Bar)->getBaz()))->bar(); +$foo = (new Foo)::$bar; + +echo (new Foo((new Bar//comment +)->getBaz(new Baz /* comment */)))->bar(); + +$foo = new $bar['a'](); +$foo = new $bar['a']['b'](); +$foo = new $bar['a'][$baz['a']['b']]['b'](); +$foo = new $bar['a'] [$baz['a']/* comment */ ['b']]['b']; + +$a = new self::$transport[$cap_string]; +$renderer = new $this->inline_diff_renderer; +$a = new ${$varHoldingClassName}; + +$class = new $obj?->classname(); +$class = new $obj?->classname; +$class = new ${$obj?->classname}; + +// Issue 3456. +// Anon classes should be skipped, even when there is an attribute between the new and the class keywords. +$anonWithAttribute = new #[SomeAttribute('summary')] class { + public const SOME_STUFF = 'foo'; +}; + +$foo = new parent(); +$foo = new parent; + +// PHP 8.3: safeguard that the sniff ignores anonymous classes, even when declared as readonly. +$anon = new readonly class {}; +$anon = new #[MyAttribute] readonly class {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed new file mode 100644 index 000000000..1e580f45d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.inc.fixed @@ -0,0 +1,51 @@ +bar(); +echo (new Foo())->bar(); +echo (new Foo((new Bar())->getBaz()))->bar(); +$foo = (new Foo())::$bar; + +echo (new Foo((new Bar()//comment +)->getBaz(new Baz() /* comment */)))->bar(); + +$foo = new $bar['a'](); +$foo = new $bar['a']['b'](); +$foo = new $bar['a'][$baz['a']['b']]['b'](); +$foo = new $bar['a'] [$baz['a']/* comment */ ['b']]['b'](); + +$a = new self::$transport[$cap_string](); +$renderer = new $this->inline_diff_renderer(); +$a = new ${$varHoldingClassName}(); + +$class = new $obj?->classname(); +$class = new $obj?->classname(); +$class = new ${$obj?->classname}(); + +// Issue 3456. +// Anon classes should be skipped, even when there is an attribute between the new and the class keywords. +$anonWithAttribute = new #[SomeAttribute('summary')] class { + public const SOME_STUFF = 'foo'; +}; + +$foo = new parent(); +$foo = new parent(); + +// PHP 8.3: safeguard that the sniff ignores anonymous classes, even when declared as readonly. +$anon = new readonly class {}; +$anon = new #[MyAttribute] readonly class {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php new file mode 100644 index 000000000..103569211 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClassInstantiationUnitTest.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassInstantiation sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes\ClassInstantiationSniff + */ +final class ClassInstantiationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 9 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 24 => 1, + 25 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 37 => 1, + 38 => 1, + 47 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc new file mode 100644 index 000000000..2562d26c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.inc @@ -0,0 +1,52 @@ +bar( + $arg1, + function ($arg2) use ($var1) { + // body + }, + $arg3 +); + +$instance = new class extends \Foo implements \HandleableInterface { + // Class content +}; + +$app->get('/hello/{name}', function ($name) use ($app) { + return 'Hello ' . $app->escape($name); +}); + +enum Foo4 +{ + +}//end diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php new file mode 100644 index 000000000..196de8f5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/ClosingBraceUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClosingBrace sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes\ClosingBraceSniff + */ +final class ClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 14 => 1, + 19 => 1, + 24 => 1, + 31 => 1, + 52 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc new file mode 100644 index 000000000..2c41bde99 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Classes/OpeningBraceSpaceUnitTest.inc @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the OpeningBraceSpace sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Classes\OpeningBraceSpaceSniff + */ +final class OpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 18 => 1, + 24 => 1, + 34 => 1, + 41 => 1, + 55 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc new file mode 100644 index 000000000..4bc2eceba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc @@ -0,0 +1,131 @@ + 0 && $n < 10) + || ($n > 10 && $n < 20) + || ($n > 20 && $n < 30) +) { + return $n; +} + +if ( + ( + $expr1 + && $expr2 + && $expr3 + && $expr4 + && $expr5 + && $expr6 + ) + || ($n > 100 && $n < 200) + || ($n > 200 && $n < 300) +) { + return $n; +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly first +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 || $expr4) && + $expr5 +) { + // elseif body +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly last +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 || $expr4) && + $expr5 +) { + // elseif body +} + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} + +// Reset to default. +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly + +match ( + $expr1 + && $expr2 && + $expr3 +) { + // structure body +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed new file mode 100644 index 000000000..5f4d223e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed @@ -0,0 +1,141 @@ + 0 && $n < 10) + || ($n > 10 && $n < 20) + || ($n > 20 && $n < 30) +) { + return $n; +} + +if ( + ( + $expr1 + && $expr2 + && $expr3 + && $expr4 + && $expr5 + && $expr6 + ) + || ($n > 100 && $n < 200) + || ($n > 200 && $n < 300) +) { + return $n; +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly first +if ( + $expr1 + && $expr2 + && ($expr3 + || $expr4) + && $expr5 +) { + // if body +} elseif ( + $expr1 + && ($expr3 + || $expr4) + && $expr5 +) { + // elseif body +} elseif ( + $expr1 + && ($expr3 + || $expr4) + && $expr5 +) { + // elseif body +} + +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly last +if ( + $expr1 && + $expr2 && + ($expr3 || + $expr4) && + $expr5 +) { + // if body +} elseif ( + $expr1 && + ($expr3 || + $expr4) && + $expr5 +) { + // elseif body +} elseif ( + $expr1 && + ($expr3 || + $expr4) && + $expr5 +) { + // elseif body +} + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} + +// Reset to default. +// phpcs:set PSR12.ControlStructures.BooleanOperatorPlacement allowOnly + +match ( + $expr1 + && $expr2 + && $expr3 +) { + // structure body +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php new file mode 100644 index 000000000..957ea546d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the BooleanOperatorPlacement sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures\BooleanOperatorPlacementSniff + */ +final class BooleanOperatorPlacementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 16 => 1, + 28 => 1, + 34 => 1, + 75 => 1, + 81 => 1, + 90 => 1, + 98 => 1, + 104 => 1, + 125 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc new file mode 100644 index 000000000..f37069699 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,133 @@ + $foo + /* + * A multi-line comment. + */ + && $foo === true + ) { + break; + } + +match ( + $expr1 && + $expr2 && + $expr3 + ) { + // structure body +}; + +match ($expr1 && +$expr2 && + $expr3) { + // structure body +}; + +// Ensure the sniff handles too many newlines (not just too few). +for ( + + + $i = 0; + $i < 10; + $i++ + + +) {} + +// Ensure the sniff does not remove indentation whitespace when comments are involved. +for ( + + + // comment. + $i = 0; + $i < 10; + $i++ +) {} + +// The sniff treats a comment (ie non-whitespace) as content, but only at the +// start / end of the control structure. So the inner-whitespace here is +// intentionally ignored by this sniff. Additionally, the comment is not indented +// by this sniff when fixing. +for (// comment. + + + $i = 0; + $i < 10; + $i++ +) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..d6c3f48c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,131 @@ + $foo + /* + * A multi-line comment. + */ + && $foo === true + ) { + break; + } + +match ( + $expr1 && + $expr2 && + $expr3 +) { + // structure body +}; + +match ( + $expr1 && + $expr2 && + $expr3 +) { + // structure body +}; + +// Ensure the sniff handles too many newlines (not just too few). +for ( + $i = 0; + $i < 10; + $i++ +) {} + +// Ensure the sniff does not remove indentation whitespace when comments are involved. +for ( + // comment. + $i = 0; + $i < 10; + $i++ +) {} + +// The sniff treats a comment (ie non-whitespace) as content, but only at the +// start / end of the control structure. So the inner-whitespace here is +// intentionally ignored by this sniff. Additionally, the comment is not indented +// by this sniff when fixing. +for ( +// comment. + + + $i = 0; + $i < 10; + $i++ +) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php new file mode 100644 index 000000000..3763b5d3c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/ControlStructures/ControlStructureSpacingUnitTest.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ControlStructureSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\ControlStructures\ControlStructureSpacingSniff + */ +final class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 2, + 16 => 1, + 17 => 1, + 18 => 1, + 22 => 1, + 23 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 48 => 2, + 58 => 1, + 59 => 1, + 92 => 1, + 96 => 1, + 97 => 1, + 98 => 2, + 106 => 1, + 111 => 1, + 117 => 1, + 127 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.1.inc new file mode 100644 index 000000000..f21daaff4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/DeclareStatementUnitTest.1.inc @@ -0,0 +1,50 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DeclareStatement sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Files\DeclareStatementSniff + */ +final class DeclareStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DeclareStatementUnitTest.1.inc': + return [ + 2 => 1, + 3 => 1, + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 9 => 2, + 10 => 1, + 11 => 3, + 12 => 2, + 13 => 1, + 14 => 2, + 16 => 3, + 19 => 3, + 22 => 1, + 24 => 1, + 26 => 3, + 28 => 3, + 34 => 2, + 43 => 1, + 46 => 1, + 47 => 1, + 49 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc new file mode 100644 index 000000000..1298ed71b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.1.inc @@ -0,0 +1,29 @@ + + +

    + + + +

    + + + + +

    Demo

    + + +
  • My page
  • +
  • Write
  • +
  • Sign out
  • + +
  • Sign in
  • + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc new file mode 100644 index 000000000..11102beb6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.15.inc @@ -0,0 +1,5 @@ + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc new file mode 100644 index 000000000..5c3df1f37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/FileHeaderUnitTest.16.inc @@ -0,0 +1,13 @@ + + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FileHeader sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Files\FileHeaderSniff + */ +final class FileHeaderUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileHeaderUnitTest.2.inc': + return [ + 1 => 1, + 6 => 1, + 7 => 1, + 18 => 1, + 20 => 1, + 24 => 1, + ]; + case 'FileHeaderUnitTest.3.inc': + return [ + 9 => 1, + 18 => 1, + ]; + case 'FileHeaderUnitTest.4.inc': + return [ + 1 => 1, + 2 => 1, + 3 => 1, + 7 => 1, + ]; + case 'FileHeaderUnitTest.5.inc': + return [4 => 1]; + case 'FileHeaderUnitTest.7.inc': + case 'FileHeaderUnitTest.10.inc': + case 'FileHeaderUnitTest.11.inc': + return [1 => 1]; + case 'FileHeaderUnitTest.12.inc': + return [4 => 2]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc new file mode 100644 index 000000000..6d024eaa9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/ImportStatementUnitTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ImportStatement sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Files\ImportStatementSniff + */ +final class ImportStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 7 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc new file mode 100644 index 000000000..0dbdf010a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.1.inc @@ -0,0 +1,3 @@ + +hi diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc new file mode 100644 index 000000000..09be8fbe6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Files/OpenTagUnitTest.4.inc @@ -0,0 +1,2 @@ + + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the OpenTag sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Files\OpenTagSniff + */ +final class OpenTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'OpenTagUnitTest.2.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc new file mode 100644 index 000000000..056d74c3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/NullableTypeDeclarationUnitTest.inc @@ -0,0 +1,95 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the NullableWhitespace sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions\NullableTypeDeclarationSniff + */ +final class NullableTypeDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 23 => 1, + 24 => 1, + 25 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 43 => 2, + 48 => 1, + 50 => 1, + 51 => 1, + 53 => 1, + 57 => 2, + 58 => 2, + 59 => 2, + 87 => 1, + 90 => 1, + 91 => 1, + 95 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc new file mode 100644 index 000000000..59ab1aa78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc @@ -0,0 +1,66 @@ + $arg; + +return (!$a ? [ new class { public function b(): c {} } ] : []); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..cd79f7816 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.inc.fixed @@ -0,0 +1,62 @@ + $arg; + +return (!$a ? [ new class { public function b(): c {} } ] : []); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php new file mode 100644 index 000000000..d2962e8d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Functions/ReturnTypeDeclarationUnitTest.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2018 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ReturnTypeDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions\ReturnTypeDeclarationSniff + */ +final class ReturnTypeDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + protected function getErrorList() + { + return [ + 27 => 1, + 28 => 1, + 35 => 2, + 41 => 2, + 48 => 2, + 52 => 1, + 55 => 1, + 56 => 1, + 59 => 1, + 60 => 1, + 62 => 1, + 64 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + protected function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc new file mode 100644 index 000000000..6ce930d94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Keywords/ShortFormTypeKeywordsUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Keywords; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ShortFormTypeKeywords sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Keywords\ShortFormTypeKeywordsSniff + */ +final class ShortFormTypeKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 13 => 1, + 14 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc new file mode 100644 index 000000000..3336fc2dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Namespaces/CompoundNamespaceDepthUnitTest.inc @@ -0,0 +1,31 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the CompoundNamespaceDepth sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Namespaces\CompoundNamespaceDepthSniff + */ +final class CompoundNamespaceDepthUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 18 => 1, + 21 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc new file mode 100644 index 000000000..14cf8e9df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc @@ -0,0 +1,79 @@ + $b) { + $variable =$foo ? 'foo' :'bar'; + $variable.='text'.'text'; +} + +$foo+= $a&$b; +$foo = $a|$b; +$foo =$a^$b; +$foo = ~$a; +$foo *=$a<<$b; +$foo = $a>>$b; + +function foo(&$a,& $b) {} + +$foo = $a and$b; +$foo = $a or $b; +$foo = $a xor$b; +$foo = !$a; +$foo = $a&&$b; +$foo = $a||$b; + +$foo = $a instanceof Foo; +$foo = $a instanceof$b; + +$foo .= 'hi' + .= 'there'; + +$foo .= 'hi' +.= 'there'; + +$foo .= 'hi' // comment +.= 'there'; + +$foo/*comment*/=/*comment*/$a/*comment*/and/*comment*/$b; + +$foo .=//comment +'string' .=/*comment*/ +'string'; + +$foo = $foo ?: 'bar'; +$foo = $foo?:'bar'; + +try { +} catch (ExceptionType1|ExceptionType2 $e) { +} + +if (strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') {} + +$oldConstructorPos = +1; +return -$content; + +function name($a = -1) {} + +$a =& $ref; +$a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +function issue3267(string|int ...$values) {} + +function setDefault(#[ImportValue( + constraints: [ + [ + Assert\Type::class, + ['type' => 'bool'], + ], + ] + )] ?bool $value = null): void + { + // Do something + } + +declare(strict_types=1); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc.fixed new file mode 100644 index 000000000..0f52f1cf7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.1.inc.fixed @@ -0,0 +1,79 @@ + $b) { + $variable = $foo ? 'foo' : 'bar'; + $variable .= 'text' . 'text'; +} + +$foo += $a & $b; +$foo = $a | $b; +$foo = $a ^ $b; +$foo = ~$a; +$foo *= $a << $b; +$foo = $a >> $b; + +function foo(&$a,& $b) {} + +$foo = $a and $b; +$foo = $a or $b; +$foo = $a xor $b; +$foo = !$a; +$foo = $a && $b; +$foo = $a || $b; + +$foo = $a instanceof Foo; +$foo = $a instanceof $b; + +$foo .= 'hi' + .= 'there'; + +$foo .= 'hi' +.= 'there'; + +$foo .= 'hi' // comment +.= 'there'; + +$foo/*comment*/ = /*comment*/$a/*comment*/ and /*comment*/$b; + +$foo .= //comment +'string' .= /*comment*/ +'string'; + +$foo = $foo ?: 'bar'; +$foo = $foo ?: 'bar'; + +try { +} catch (ExceptionType1 | ExceptionType2 $e) { +} + +if (strpos($tokenContent, 'b"') === 0 && substr($tokenContent, -1) === '"') {} + +$oldConstructorPos = +1; +return -$content; + +function name($a = -1) {} + +$a =& $ref; +$a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +function issue3267(string|int ...$values) {} + +function setDefault(#[ImportValue( + constraints: [ + [ + Assert\Type::class, + ['type' => 'bool'], + ], + ] + )] ?bool $value = null): void + { + // Do something + } + +declare(strict_types=1); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.2.inc new file mode 100644 index 000000000..3a0dbac3e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.2.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the OperatorSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators\OperatorSpacingSniff + */ +final class OperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'OperatorSpacingUnitTest.1.inc': + return [ + 2 => 1, + 3 => 2, + 4 => 1, + 5 => 2, + 6 => 4, + 9 => 3, + 10 => 2, + 11 => 3, + 13 => 3, + 14 => 2, + 18 => 1, + 20 => 1, + 22 => 2, + 23 => 2, + 26 => 1, + 37 => 4, + 39 => 1, + 40 => 1, + 44 => 2, + 47 => 2, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc new file mode 100644 index 000000000..84ea24b2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Properties/ConstantVisibilityUnitTest.inc @@ -0,0 +1,22 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Properties; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ConstantVisibility sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Properties\ConstantVisibilitySniff + */ +final class ConstantVisibilityUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + 21 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc new file mode 100644 index 000000000..152121cf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/Tests/Traits/UseDeclarationUnitTest.inc @@ -0,0 +1,221 @@ + + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR12\Tests\Traits; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the UseDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR12\Sniffs\Traits\UseDeclarationSniff + */ +final class UseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 15 => 1, + 29 => 2, + 30 => 1, + 42 => 1, + 57 => 4, + 59 => 3, + 61 => 1, + 63 => 5, + 65 => 1, + 71 => 1, + 73 => 2, + 76 => 1, + 86 => 2, + 103 => 1, + 112 => 1, + 122 => 1, + 132 => 1, + 157 => 1, + 165 => 1, + 170 => 1, + 208 => 1, + 219 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml new file mode 100644 index 000000000..2f9ae0a47 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR12/ruleset.xml @@ -0,0 +1,348 @@ + + + The PSR-12 coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + Method name "%s" must not be prefixed with an underscore to indicate visibility + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml new file mode 100644 index 000000000..4e56bc04a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml @@ -0,0 +1,23 @@ + + + + + + + class Foo +{ +} + ]]> + + + class Foo +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml new file mode 100644 index 000000000..042c0c6cd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml @@ -0,0 +1,81 @@ + + + + + + + bar; +} + ]]> + + + _bar; +} + ]]> + + + + + private $bar; +} + ]]> + + + var $bar; +} + ]]> + + + + + + + + $bar, $baz; +} + ]]> + + + + + static $bar; + private $baz; +} + ]]> + + + static protected $bar; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml new file mode 100644 index 000000000..dcbe98f5e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + $foo) { + $var = 1; +} + ]]> + + + $foo ) { + $var = 1; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml new file mode 100644 index 000000000..a22dd1796 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xml @@ -0,0 +1,27 @@ + + + + + + + elseif ($bar) { + $var = 2; +} + ]]> + + + else if ($bar) { + $var = 2; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml new file mode 100644 index 000000000..1d6d053df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml @@ -0,0 +1,104 @@ + + + + + + + case 'bar': + break; +} + ]]> + + + case 'bar': + break; +} + ]]> + + + + + 'bar': + break; +} + ]]> + + + 'bar': + break; +} + ]]> + + + + + : + break; + default: + break; +} + ]]> + + + : + break; + default : + break; +} + ]]> + + + + + break; +} + ]]> + + + break; +} + ]]> + + + + + // no break + default: + break; +} + ]]> + + + : + break; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/ClosingTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/ClosingTagStandard.xml new file mode 100644 index 000000000..60d5e7fba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/ClosingTagStandard.xml @@ -0,0 +1,23 @@ + + + + + + + + ]]> + + + ?> + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml new file mode 100644 index 000000000..d6d3aad16 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionCallSignatureStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionCallSignatureStandard.xml new file mode 100644 index 000000000..257bcab0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionCallSignatureStandard.xml @@ -0,0 +1,107 @@ + + + + + + + ($bar, $baz); + ]]> + + + ( $bar, $baz ); + ]]> + + + + + $bar, + $baz +); + ]]> + + + $bar, + $baz +); + ]]> + + + + + ); + ]]> + + + ); + ]]> + + + + + $bar, + $baz +); + ]]> + + + $bar, + $baz +); + ]]> + + + + + $baz +); + ]]> + + + $baz +); + ]]> + + + + + + + + + $baz +); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionClosingBraceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionClosingBraceStandard.xml new file mode 100644 index 000000000..3b1b6555e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/FunctionClosingBraceStandard.xml @@ -0,0 +1,26 @@ + + + + + + + } + ]]> + + + +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml new file mode 100644 index 000000000..91ff8c2cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml @@ -0,0 +1,51 @@ + + + + + + + bar() + { + } +} + ]]> + + + _bar() + { + } +} + ]]> + + + + + final public static function bar() + { + } +} + ]]> + + + static public final function bar() + { + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml new file mode 100644 index 000000000..1f4d389aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml @@ -0,0 +1,22 @@ + + + + + + + +use \Baz; + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml new file mode 100644 index 000000000..4082603ca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml @@ -0,0 +1,57 @@ + + + + + + + + + + \Foo, \Bar; + ]]> + + + + + + + + + + + + + +class Baz +{ +} + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..887c552ed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,540 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDeclarationSniff as PEARClassDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDeclarationSniff extends PEARClassDeclarationSniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // We want all the errors from the PEAR standard, plus some of our own. + parent::process($phpcsFile, $stackPtr); + + // Just in case. + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + return; + } + + $this->processOpen($phpcsFile, $stackPtr); + $this->processClose($phpcsFile, $stackPtr); + + }//end process() + + + /** + * Processes the opening section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processOpen(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $stackPtrType = strtolower($tokens[$stackPtr]['content']); + + // Check alignment of the keyword and braces. + $classModifiers = [ + T_ABSTRACT => T_ABSTRACT, + T_FINAL => T_FINAL, + T_READONLY => T_READONLY, + ]; + + $prevNonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + if (isset($classModifiers[$tokens[$prevNonEmpty]['code']]) === true) { + $spaces = 0; + $errorCode = 'SpaceBeforeKeyword'; + if ($tokens[$prevNonEmpty]['line'] !== $tokens[$stackPtr]['line']) { + $spaces = 'newline'; + $errorCode = 'NewlineBeforeKeyword'; + } else if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $spaces = $tokens[($stackPtr - 1)]['length']; + } + + if ($spaces !== 1) { + $error = 'Expected 1 space between %s and %s keywords; %s found'; + $data = [ + strtolower($tokens[$prevNonEmpty]['content']), + $stackPtrType, + $spaces, + ]; + + if ($prevNonSpace !== $prevNonEmpty) { + // Comment found between modifier and class keyword. Do not auto-fix. + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + if ($spaces === 0) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + for ($i = ($stackPtr - 2); $i > $prevNonSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ' '); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end if + + // We'll need the indent of the class/interface declaration for later. + $classIndent = 0; + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } + + // We changed lines. + if ($tokens[($i + 1)]['code'] === T_WHITESPACE) { + $classIndent = $tokens[($i + 1)]['length']; + } + + break; + } + + $className = null; + $checkSpacing = true; + + if ($tokens[$stackPtr]['code'] !== T_ANON_CLASS) { + $className = $phpcsFile->findNext(T_STRING, $stackPtr); + } else { + // Ignore the spacing check if this is a simple anon class. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next === $tokens[$stackPtr]['scope_opener'] + && $tokens[$next]['line'] > $tokens[$stackPtr]['line'] + ) { + $checkSpacing = false; + } + } + + if ($checkSpacing === true) { + // Spacing of the keyword. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $gap = 0; + } else if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $gap = 'newline'; + } else { + $gap = $tokens[($stackPtr + 1)]['length']; + } + + if ($gap !== 1) { + $error = 'Expected 1 space after %s keyword; %s found'; + $data = [ + $stackPtrType, + $gap, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword', $data); + if ($fix === true) { + if ($gap === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + }//end if + + // Check after the class/interface name. + if ($className !== null + && $tokens[($className + 2)]['line'] === $tokens[$className]['line'] + ) { + $gap = $tokens[($className + 1)]['content']; + if (strlen($gap) !== 1) { + $found = strlen($gap); + $error = 'Expected 1 space after %s name; %s found'; + $data = [ + $stackPtrType, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceAfterName', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($className + 1), ' '); + } + } + } + + $openingBrace = $tokens[$stackPtr]['scope_opener']; + + // Check positions of the extends and implements keywords. + $compareToken = $stackPtr; + $compareType = 'name'; + if ($tokens[$stackPtr]['code'] === T_ANON_CLASS) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) { + $compareToken = $tokens[$stackPtr]['parenthesis_closer']; + $compareType = 'closing parenthesis'; + } else { + $compareType = 'keyword'; + } + } + + foreach (['extends', 'implements'] as $keywordType) { + $keyword = $phpcsFile->findNext(constant('T_'.strtoupper($keywordType)), ($compareToken + 1), $openingBrace); + if ($keyword !== false) { + if ($tokens[$keyword]['line'] !== $tokens[$compareToken]['line']) { + $error = 'The '.$keywordType.' keyword must be on the same line as the %s '.$compareType; + $data = [$stackPtrType]; + $fix = $phpcsFile->addFixableError($error, $keyword, ucfirst($keywordType).'Line', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $comments = []; + + for ($i = ($compareToken + 1); $i < $keyword; ++$i) { + if ($tokens[$i]['code'] === T_COMMENT) { + $comments[] = trim($tokens[$i]['content']); + } + + if ($tokens[$i]['code'] === T_WHITESPACE + || $tokens[$i]['code'] === T_COMMENT + ) { + $phpcsFile->fixer->replaceToken($i, ' '); + } + } + + $phpcsFile->fixer->addContent($compareToken, ' '); + if (empty($comments) === false) { + $i = $keyword; + while ($tokens[($i + 1)]['line'] === $tokens[$keyword]['line']) { + ++$i; + } + + $phpcsFile->fixer->addContentBefore($i, ' '.implode(' ', $comments)); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + } else { + // Check the whitespace before. Whitespace after is checked + // later by looking at the whitespace before the first class name + // in the list. + $gap = $tokens[($keyword - 1)]['length']; + if ($gap !== 1) { + $error = 'Expected 1 space before '.$keywordType.' keyword; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, $keyword, 'SpaceBefore'.ucfirst($keywordType), $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($keyword - 1), ' '); + } + } + }//end if + }//end if + }//end foreach + + // Check each of the extends/implements class names. If the extends/implements + // keyword is the last content on the line, it means we need to check for + // the multi-line format, so we do not include the class names + // from the extends/implements list in the following check. + // Note that classes can only extend one other class, so they can't use a + // multi-line extends format, whereas an interface can extend multiple + // other interfaces, and so uses a multi-line extends format. + if ($tokens[$stackPtr]['code'] === T_INTERFACE) { + $keywordTokenType = T_EXTENDS; + } else { + $keywordTokenType = T_IMPLEMENTS; + } + + $implements = $phpcsFile->findNext($keywordTokenType, ($stackPtr + 1), $openingBrace); + $multiLineImplements = false; + if ($implements !== false) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($openingBrace - 1), $implements, true); + if ($tokens[$prev]['line'] !== $tokens[$implements]['line']) { + $multiLineImplements = true; + } + } + + $find = [ + T_STRING, + $keywordTokenType, + ]; + + if ($className !== null) { + $start = $className; + } else if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) { + $start = $tokens[$stackPtr]['parenthesis_closer']; + } else { + $start = $stackPtr; + } + + $classNames = []; + $nextClass = $phpcsFile->findNext($find, ($start + 2), ($openingBrace - 1)); + while ($nextClass !== false) { + $classNames[] = $nextClass; + $nextClass = $phpcsFile->findNext($find, ($nextClass + 1), ($openingBrace - 1)); + } + + $classCount = count($classNames); + $checkingImplements = false; + $implementsToken = null; + foreach ($classNames as $n => $className) { + if ($tokens[$className]['code'] === $keywordTokenType) { + $checkingImplements = true; + $implementsToken = $className; + + continue; + } + + if ($checkingImplements === true + && $multiLineImplements === true + && ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR + || ($tokens[($className - 2)]['code'] !== T_STRING + && $tokens[($className - 2)]['code'] !== T_NAMESPACE)) + ) { + $prev = $phpcsFile->findPrevious( + [ + T_NS_SEPARATOR, + T_WHITESPACE, + ], + ($className - 1), + $implements, + true + ); + + if ($prev === $implementsToken && $tokens[$className]['line'] !== ($tokens[$prev]['line'] + 1)) { + if ($keywordTokenType === T_EXTENDS) { + $error = 'The first item in a multi-line extends list must be on the line following the extends keyword'; + $fix = $phpcsFile->addFixableError($error, $className, 'FirstExtendsInterfaceSameLine'); + } else { + $error = 'The first item in a multi-line implements list must be on the line following the implements keyword'; + $fix = $phpcsFile->addFixableError($error, $className, 'FirstInterfaceSameLine'); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $className; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } else if ((isset(Tokens::$commentTokens[$tokens[$prev]['code']]) === false + && $tokens[$prev]['line'] !== ($tokens[$className]['line'] - 1)) + || $tokens[$prev]['line'] === $tokens[$className]['line'] + ) { + if ($keywordTokenType === T_EXTENDS) { + $error = 'Only one interface may be specified per line in a multi-line extends declaration'; + $fix = $phpcsFile->addFixableError($error, $className, 'ExtendsInterfaceSameLine'); + } else { + $error = 'Only one interface may be specified per line in a multi-line implements declaration'; + $fix = $phpcsFile->addFixableError($error, $className, 'InterfaceSameLine'); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $className; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + } + } else { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($className - 1), $implements); + if ($tokens[$prev]['line'] !== $tokens[$className]['line']) { + $found = 0; + } else { + $found = $tokens[$prev]['length']; + } + + $expected = ($classIndent + $this->indent); + if ($found !== $expected) { + $error = 'Expected %s spaces before interface name; %s found'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $className, 'InterfaceWrongIndent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($found === 0) { + $phpcsFile->fixer->addContent($prev, $padding); + } else { + $phpcsFile->fixer->replaceToken($prev, $padding); + } + } + } + }//end if + } else if ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR + || ($tokens[($className - 2)]['code'] !== T_STRING + && $tokens[($className - 2)]['code'] !== T_NAMESPACE) + ) { + // Not part of a longer fully qualified or namespace relative class name. + if ($tokens[($className - 1)]['code'] === T_COMMA + || ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR + && $tokens[($className - 2)]['code'] === T_COMMA) + ) { + $error = 'Expected 1 space before "%s"; 0 found'; + $data = [$tokens[$className]['content']]; + $fix = $phpcsFile->addFixableError($error, ($nextComma + 1), 'NoSpaceBeforeName', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore(($nextComma + 1), ' '); + } + } else { + if ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR) { + $prev = ($className - 2); + } else { + $prev = ($className - 1); + } + + $last = $phpcsFile->findPrevious(T_WHITESPACE, $prev, null, true); + $content = $phpcsFile->getTokensAsString(($last + 1), ($prev - $last)); + if ($content !== ' ') { + $found = strlen($content); + + $error = 'Expected 1 space before "%s"; %s found'; + $data = [ + $tokens[$className]['content'], + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceBeforeName', $data); + if ($fix === true) { + if ($tokens[$prev]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($prev, ' '); + while ($tokens[--$prev]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($prev, ' '); + } + + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->addContent($prev, ' '); + } + } + }//end if + }//end if + }//end if + + if ($checkingImplements === true + && $tokens[($className + 1)]['code'] !== T_NS_SEPARATOR + && $tokens[($className + 1)]['code'] !== T_COMMA + ) { + if ($n !== ($classCount - 1)) { + // This is not the last class name, and the comma + // is not where we expect it to be. + if ($tokens[($className + 2)]['code'] !== $keywordTokenType) { + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $tokens[$className]['content'], + $tokens[($className + 1)]['length'], + ]; + + $fix = $phpcsFile->addFixableError($error, $className, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($className + 1), ''); + } + } + } + + $nextComma = $phpcsFile->findNext(T_COMMA, $className); + } else { + $nextComma = ($className + 1); + }//end if + }//end foreach + + }//end processOpen() + + + /** + * Processes the closing section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check that the closing brace comes right after the code body. + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + if ($prevContent !== $tokens[$stackPtr]['scope_opener'] + && $tokens[$prevContent]['line'] !== ($tokens[$closeBrace]['line'] - 1) + ) { + $error = 'The closing brace for the %s must go on the next line after the body'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'CloseBraceAfterBody', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $tokens[$i]['line'] !== $tokens[$closeBrace]['line']; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (strpos($tokens[$prevContent]['content'], $phpcsFile->eolChar) === false) { + $phpcsFile->fixer->addNewline($prevContent); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + if ($tokens[$stackPtr]['code'] !== T_ANON_CLASS) { + // Check the closing brace is on it's own line, but allow + // for comments like "//end class". + $ignoreTokens = Tokens::$phpcsCommentTokens; + $ignoreTokens[] = T_WHITESPACE; + $ignoreTokens[] = T_COMMENT; + $ignoreTokens[] = T_SEMICOLON; + $nextContent = $phpcsFile->findNext($ignoreTokens, ($closeBrace + 1), null, true); + if ($tokens[$nextContent]['line'] === $tokens[$closeBrace]['line']) { + $type = strtolower($tokens[$stackPtr]['content']); + $error = 'Closing %s brace must be on a line by itself'; + $data = [$type]; + $phpcsFile->addError($error, $closeBrace, 'CloseBraceSameLine', $data); + } + } + + }//end processClose() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php new file mode 100644 index 000000000..29d7023ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php @@ -0,0 +1,226 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes; + +use Exception; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Tokens; + +class PropertyDeclarationSniff extends AbstractVariableSniff +{ + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'][1] === '_') { + $error = 'Property name "%s" should not be prefixed with an underscore to indicate visibility'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); + } + + // Detect multiple properties defined at the same time. Throw an error + // for this, but also only process the first property in the list so we don't + // repeat errors. + $find = Tokens::$scopeModifiers; + $find[] = T_VARIABLE; + $find[] = T_VAR; + $find[] = T_READONLY; + $find[] = T_SEMICOLON; + $find[] = T_OPEN_CURLY_BRACKET; + + $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1)); + if ($tokens[$prev]['code'] === T_VARIABLE) { + return; + } + + if ($tokens[$prev]['code'] === T_VAR) { + $error = 'The var keyword must not be used to declare a property'; + $phpcsFile->addError($error, $stackPtr, 'VarUsed'); + } + + $next = $phpcsFile->findNext([T_VARIABLE, T_SEMICOLON], ($stackPtr + 1)); + if ($next !== false && $tokens[$next]['code'] === T_VARIABLE) { + $error = 'There must not be more than one property declared per statement'; + $phpcsFile->addError($error, $stackPtr, 'Multiple'); + } + + try { + $propertyInfo = $phpcsFile->getMemberProperties($stackPtr); + if (empty($propertyInfo) === true) { + return; + } + } catch (Exception $e) { + // Turns out not to be a property after all. + return; + } + + if ($propertyInfo['type'] !== '') { + $typeToken = $propertyInfo['type_end_token']; + $error = 'There must be 1 space after the property type declaration; %s found'; + if ($tokens[($typeToken + 1)]['code'] !== T_WHITESPACE) { + $data = ['0']; + $fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($typeToken, ' '); + } + } else if ($tokens[($typeToken + 1)]['content'] !== ' ') { + $next = $phpcsFile->findNext(T_WHITESPACE, ($typeToken + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$typeToken]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($typeToken + 1)]['length']; + } + + $data = [$found]; + + $nextNonWs = $phpcsFile->findNext(Tokens::$emptyTokens, ($typeToken + 1), null, true); + if ($nextNonWs !== $next) { + $phpcsFile->addError($error, $typeToken, 'SpacingAfterType', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $typeToken, 'SpacingAfterType', $data); + if ($fix === true) { + if ($found === 'newline') { + $phpcsFile->fixer->beginChangeset(); + for ($x = ($typeToken + 1); $x < $next; $x++) { + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addContent($typeToken, ' '); + $phpcsFile->fixer->endChangeset(); + } else { + $phpcsFile->fixer->replaceToken(($typeToken + 1), ' '); + } + } + } + }//end if + }//end if + + if ($propertyInfo['scope_specified'] === false) { + $error = 'Visibility must be declared on property "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data); + } + + /* + * Note: per PSR-PER section 4.6, the order should be: + * - Inheritance modifier: `abstract` or `final`. + * - Visibility modifier: `public`, `protected`, or `private`. + * - Scope modifier: `static`. + * - Mutation modifier: `readonly`. + * - Type declaration. + * - Name. + * + * Ref: https://www.php-fig.org/per/coding-style/#46-modifier-keywords + * + * At this time (PHP 8.2), inheritance modifiers cannot be applied to properties and + * the `static` and `readonly` modifiers are mutually exclusive and cannot be used together. + * + * Based on that, the below modifier keyword order checks are sufficient (for now). + */ + + if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_static'] === true) { + $scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1)); + $staticPtr = $phpcsFile->findPrevious(T_STATIC, ($stackPtr - 1)); + if ($scopePtr > $staticPtr) { + $error = 'The static declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'StaticBeforeVisibility'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($scopePtr + 1); $scopePtr < $stackPtr; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($scopePtr, ''); + $phpcsFile->fixer->addContentBefore($staticPtr, $propertyInfo['scope'].' '); + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_readonly'] === true) { + $scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1)); + $readonlyPtr = $phpcsFile->findPrevious(T_READONLY, ($stackPtr - 1)); + if ($scopePtr > $readonlyPtr) { + $error = 'The readonly declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ReadonlyBeforeVisibility'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($scopePtr + 1); $scopePtr < $stackPtr; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($scopePtr, ''); + $phpcsFile->fixer->addContentBefore($readonlyPtr, $propertyInfo['scope'].' '); + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..d855dbd63 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php @@ -0,0 +1,141 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_ELSEIF, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + ) { + return; + } + + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($parenOpener + 1), null, true); + if (in_array($tokens[$nextContent]['code'], Tokens::$commentTokens, true) === false) { + $spaceAfterOpen = 0; + if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($parenOpener + 1)]['content'], $phpcsFile->eolChar) !== false) { + $spaceAfterOpen = 'newline'; + } else { + $spaceAfterOpen = $tokens[($parenOpener + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $spaceAfterOpen); + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($parenOpener, $padding); + } else if ($spaceAfterOpen === 'newline') { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), ''); + } else { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), $padding); + } + } + } + }//end if + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($parenCloser - 1), $parenOpener, true); + if ($tokens[$prev]['line'] === $tokens[$parenCloser]['line']) { + $spaceBeforeClose = 0; + if ($tokens[($parenCloser - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = strlen(ltrim($tokens[($parenCloser - 1)]['content'], $phpcsFile->eolChar)); + } + + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $spaceBeforeClose); + + if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($parenCloser, $padding); + } else { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), $padding); + } + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100644 index 000000000..7f5e97c18 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ElseIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ELSE, + T_ELSEIF, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ELSEIF) { + $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'elseif'); + return; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_IF) { + $phpcsFile->recordMetric($stackPtr, 'Use of ELSE IF or ELSEIF', 'else if'); + $error = 'Usage of ELSE IF is discouraged; use ELSEIF instead'; + $fix = $phpcsFile->addFixableWarning($error, $stackPtr, 'NotAllowed'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, 'elseif'); + for ($i = ($stackPtr + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php new file mode 100644 index 000000000..4b3b5ad2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php @@ -0,0 +1,396 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SwitchDeclarationSniff implements Sniff +{ + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SWITCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We can't process SWITCH statements unless we know where they start and end. + if (isset($tokens[$stackPtr]['scope_opener']) === false + || isset($tokens[$stackPtr]['scope_closer']) === false + ) { + return; + } + + $switch = $tokens[$stackPtr]; + $nextCase = $stackPtr; + $caseAlignment = ($switch['column'] + $this->indent); + + while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $switch['scope_closer'])) !== false) { + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $type = 'default'; + } else { + $type = 'case'; + } + + if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) { + $expected = strtolower($tokens[$nextCase]['content']); + $error = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $tokens[$nextCase]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'NotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($nextCase, $expected); + } + } + + if ($type === 'case' + && ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE + || $tokens[($nextCase + 1)]['content'] !== ' ') + ) { + $error = 'CASE keyword must be followed by a single space'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase'); + if ($fix === true) { + if ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent($nextCase, ' '); + } else { + $phpcsFile->fixer->replaceToken(($nextCase + 1), ' '); + } + } + } + + $opener = $tokens[$nextCase]['scope_opener']; + $nextCloser = $tokens[$nextCase]['scope_closer']; + if ($tokens[$opener]['code'] === T_COLON) { + if ($tokens[($opener - 1)]['code'] === T_WHITESPACE) { + $error = 'There must be no space before the colon in a '.strtoupper($type).' statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon'.strtoupper($type)); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($opener - 1), ''); + } + } + + for ($next = ($opener + 1); $next < $nextCloser; $next++) { + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === false + || (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] !== $tokens[$opener]['line']) + ) { + break; + } + } + + if ($tokens[$next]['line'] !== ($tokens[$opener]['line'] + 1)) { + $error = 'The '.strtoupper($type).' body must start on the line following the statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'BodyOnNextLine'.strtoupper($type)); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $padding = str_repeat(' ', ($caseAlignment + $this->indent - 1)); + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$padding); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$opener]['line']) { + // Ignore trailing comments. + continue; + } + + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + if ($tokens[$nextCloser]['scope_condition'] === $nextCase) { + // Only need to check some things once, even if the + // closer is shared between multiple case statements, or even + // the default case. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCloser - 1), $nextCase, true); + if ($tokens[$prev]['line'] === $tokens[$nextCloser]['line']) { + $error = 'Terminating statement must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakNotNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewLine($prev); + $phpcsFile->fixer->replaceToken($nextCloser, trim($tokens[$nextCloser]['content'])); + } + } else { + $diff = ($tokens[$nextCase]['column'] + $this->indent - $tokens[$nextCloser]['column']); + if ($diff !== 0) { + $error = 'Terminating statement must be indented to the same level as the CASE body'; + $fix = $phpcsFile->addFixableError($error, $nextCloser, 'BreakIndent'); + if ($fix === true) { + if ($diff > 0) { + $phpcsFile->fixer->addContentBefore($nextCloser, str_repeat(' ', $diff)); + } else { + $phpcsFile->fixer->substrToken(($nextCloser - 1), 0, $diff); + } + } + } + }//end if + }//end if + } else { + $error = strtoupper($type).' statements must be defined using a colon'; + $phpcsFile->addError($error, $nextCase, 'WrongOpener'.$type); + }//end if + + // We only want cases from here on in. + if ($type !== 'case') { + continue; + } + + $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), $nextCloser, true); + + if ($tokens[$nextCode]['code'] !== T_CASE && $tokens[$nextCode]['code'] !== T_DEFAULT) { + // This case statement has content. If the next case or default comes + // before the closer, it means we don't have an obvious terminating + // statement and need to make some more effort to find one. If we + // don't, we do need a comment. + $nextCode = $this->findNextCase($phpcsFile, ($opener + 1), $nextCloser); + if ($nextCode !== false) { + $prevCode = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCode - 1), $nextCase, true); + if (isset(Tokens::$commentTokens[$tokens[$prevCode]['code']]) === false + && $this->findNestedTerminator($phpcsFile, ($opener + 1), $nextCode) === false + ) { + $error = 'There must be a comment when fall-through is intentional in a non-empty case body'; + $phpcsFile->addError($error, $nextCase, 'TerminatingComment'); + } + } + } + }//end while + + }//end process() + + + /** + * Find the next CASE or DEFAULT statement from a point in the file. + * + * Note that nested switches are ignored. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position to start looking at. + * @param int $end The position to stop looking at. + * + * @return int|false + */ + private function findNextCase($phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + while (($stackPtr = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], $stackPtr, $end)) !== false) { + // Skip nested SWITCH statements; they are handled on their own. + if ($tokens[$stackPtr]['code'] === T_SWITCH) { + $stackPtr = $tokens[$stackPtr]['scope_closer']; + continue; + } + + break; + } + + return $stackPtr; + + }//end findNextCase() + + + /** + * Returns the position of the nested terminating statement. + * + * Returns false if no terminating statement was found. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position to start looking at. + * @param int $end The position to stop looking at. + * + * @return int|bool + */ + private function findNestedTerminator($phpcsFile, $stackPtr, $end) + { + $tokens = $phpcsFile->getTokens(); + + $lastToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($end - 1), $stackPtr, true); + if ($lastToken === false) { + return false; + } + + if ($tokens[$lastToken]['code'] === T_CLOSE_CURLY_BRACKET) { + // We found a closing curly bracket and want to check if its block + // belongs to a SWITCH, IF, ELSEIF or ELSE, TRY, CATCH OR FINALLY clause. + // If yes, we continue searching for a terminating statement within that + // block. Note that we have to make sure that every block of + // the entire if/else/switch statement has a terminating statement. + // For a try/catch/finally statement, either the finally block has + // to have a terminating statement or every try/catch block has to have one. + $currentCloser = $lastToken; + $hasElseBlock = false; + $hasCatchWithoutTerminator = false; + do { + $scopeOpener = $tokens[$currentCloser]['scope_opener']; + $scopeCloser = $tokens[$currentCloser]['scope_closer']; + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($scopeOpener - 1), $stackPtr, true); + if ($prevToken === false) { + return false; + } + + // SWITCH, IF, ELSEIF, CATCH clauses possess a condition we have to account for. + if ($tokens[$prevToken]['code'] === T_CLOSE_PARENTHESIS) { + $prevToken = $tokens[$prevToken]['parenthesis_owner']; + } + + if ($tokens[$prevToken]['code'] === T_IF) { + // If we have not encountered an ELSE clause by now, we cannot + // be sure that the whole statement terminates in every case. + if ($hasElseBlock === false) { + return false; + } + + return $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + } else if ($tokens[$prevToken]['code'] === T_ELSEIF + || $tokens[$prevToken]['code'] === T_ELSE + ) { + // If we find a terminating statement within this block, + // we continue with the previous ELSEIF or IF clause. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator === false) { + return false; + } + + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + if ($tokens[$prevToken]['code'] === T_ELSE) { + $hasElseBlock = true; + } + } else if ($tokens[$prevToken]['code'] === T_FINALLY) { + // If we find a terminating statement within this block, + // the whole try/catch/finally statement is covered. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator !== false) { + return $hasTerminator; + } + + // Otherwise, we continue with the previous TRY or CATCH clause. + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + } else if ($tokens[$prevToken]['code'] === T_TRY) { + // If we've seen CATCH blocks without terminator statement and + // have not seen a FINALLY *with* a terminator statement, we + // don't even need to bother checking the TRY. + if ($hasCatchWithoutTerminator === true) { + return false; + } + + return $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + } else if ($tokens[$prevToken]['code'] === T_CATCH) { + // Keep track of seen catch statements without terminating statement, + // but don't bow out yet as there may still be a FINALLY clause + // with a terminating statement before the CATCH. + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($scopeOpener + 1), $scopeCloser); + if ($hasTerminator === false) { + $hasCatchWithoutTerminator = true; + } + + $currentCloser = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), $stackPtr, true); + } else if ($tokens[$prevToken]['code'] === T_SWITCH) { + $hasDefaultBlock = false; + $endOfSwitch = $tokens[$prevToken]['scope_closer']; + $nextCase = $prevToken; + + // We look for a terminating statement within every blocks. + while (($nextCase = $this->findNextCase($phpcsFile, ($nextCase + 1), $endOfSwitch)) !== false) { + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $hasDefaultBlock = true; + } + + $opener = $tokens[$nextCase]['scope_opener']; + + $nextCode = $phpcsFile->findNext(Tokens::$emptyTokens, ($opener + 1), $endOfSwitch, true); + if ($tokens[$nextCode]['code'] === T_CASE || $tokens[$nextCode]['code'] === T_DEFAULT) { + // This case statement has no content, so skip it. + continue; + } + + $endOfCase = $this->findNextCase($phpcsFile, ($opener + 1), $endOfSwitch); + if ($endOfCase === false) { + $endOfCase = $endOfSwitch; + } + + $hasTerminator = $this->findNestedTerminator($phpcsFile, ($opener + 1), $endOfCase); + if ($hasTerminator === false) { + return false; + } + }//end while + + // If we have not encountered a DEFAULT block by now, we cannot + // be sure that the whole statement terminates in every case. + if ($hasDefaultBlock === false) { + return false; + } + + return $hasTerminator; + } else { + return false; + }//end if + } while ($currentCloser !== false && $tokens[$currentCloser]['code'] === T_CLOSE_CURLY_BRACKET); + + return true; + } else if ($tokens[$lastToken]['code'] === T_SEMICOLON) { + // We found the last statement of the CASE. Now we want to + // check whether it is a terminating one. + $terminators = [ + T_RETURN => T_RETURN, + T_BREAK => T_BREAK, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ]; + + $terminator = $phpcsFile->findStartOfStatement(($lastToken - 1)); + if (isset($terminators[$tokens[$terminator]['code']]) === true) { + return $terminator; + } + }//end if + + return false; + + }//end findNestedTerminator() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php new file mode 100644 index 000000000..1cb637447 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/ClosingTagSniff.php @@ -0,0 +1,89 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClosingTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Make sure this file only contains PHP code. + for ($i = 0; $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['code'] === T_INLINE_HTML + && trim($tokens[$i]['content']) !== '' + ) { + return $phpcsFile->numTokens; + } + } + + // Find the last non-empty token. + for ($last = ($phpcsFile->numTokens - 1); $last > 0; $last--) { + if (trim($tokens[$last]['content']) !== '') { + break; + } + } + + if ($tokens[$last]['code'] === T_CLOSE_TAG) { + $error = 'A closing tag is not permitted at the end of a PHP file'; + $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($last - 1), null, true); + if ($tokens[$prev]['code'] !== T_SEMICOLON + && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET + && $tokens[$prev]['code'] !== T_OPEN_TAG + ) { + $phpcsFile->fixer->addContent($prev, ';'); + } + + $phpcsFile->fixer->endChangeset(); + } + + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at end of PHP-only file', 'no'); + }//end if + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php new file mode 100644 index 000000000..5b2d2817b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EndFileNewlineSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($phpcsFile->findNext(T_INLINE_HTML, ($stackPtr + 1)) !== false) { + return $phpcsFile->numTokens; + } + + // Skip to the end of the file. + $tokens = $phpcsFile->getTokens(); + $lastToken = ($phpcsFile->numTokens - 1); + + if ($tokens[$lastToken]['content'] === '') { + $lastToken--; + } + + // Hard-coding the expected \n in this sniff as it is PSR-2 specific and + // PSR-2 enforces the use of unix style newlines. + if (substr($tokens[$lastToken]['content'], -1) !== "\n") { + $error = 'Expected 1 newline at end of file; 0 found'; + $fix = $phpcsFile->addFixableError($error, $lastToken, 'NoneFound'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($lastToken); + } + + $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', '0'); + return $phpcsFile->numTokens; + } + + // Go looking for the last non-empty line. + $lastLine = $tokens[$lastToken]['line']; + if ($tokens[$lastToken]['code'] === T_WHITESPACE + || $tokens[$lastToken]['code'] === T_DOC_COMMENT_WHITESPACE + ) { + $lastCode = $phpcsFile->findPrevious([T_WHITESPACE, T_DOC_COMMENT_WHITESPACE], ($lastToken - 1), null, true); + } else { + $lastCode = $lastToken; + } + + $lastCodeLine = $tokens[$lastCode]['line']; + $blankLines = ($lastLine - $lastCodeLine + 1); + $phpcsFile->recordMetric($stackPtr, 'Number of newlines at EOF', $blankLines); + + if ($blankLines > 1) { + $error = 'Expected 1 blank line at end of file; %s found'; + $data = [$blankLines]; + $fix = $phpcsFile->addFixableError($error, $lastCode, 'TooMany', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($lastCode, rtrim($tokens[$lastCode]['content'])); + for ($i = ($lastCode + 1); $i < $lastToken; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($lastToken, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } + + // Skip the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php new file mode 100644 index 000000000..cee18cacd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionCallSignatureSniff as PEARFunctionCallSignatureSniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCallSignatureSniff extends PEARFunctionCallSignatureSniff +{ + + /** + * If TRUE, multiple arguments can be defined per line in a multi-line call. + * + * @var boolean + */ + public $allowMultipleArguments = false; + + + /** + * Processes single-line calls. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens) + { + // If the first argument is on a new line, this is a multi-line + // function call, even if there is only one argument. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + return true; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $end = $phpcsFile->findEndOfStatement(($openBracket + 1), [T_COLON]); + while ($tokens[$end]['code'] === T_COMMA) { + // If the next bit of code is not on the same line, this is a + // multi-line function call. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next === false) { + return false; + } + + if ($tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + $end = $phpcsFile->findEndOfStatement($next, [T_COLON]); + } + + // We've reached the last argument, so see if the next content + // (should be the close bracket) is also on the same line. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + return false; + + }//end isMultiLineCall() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php new file mode 100644 index 000000000..c4f1a6f4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/FunctionClosingBraceSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + $found = ($tokens[$closeBrace]['line'] - $tokens[$prevContent]['line'] - 1); + + if ($found < 0) { + // Brace isn't on a new line, so not handled by us. + return; + } + + if ($found === 0) { + // All is good. + return; + } + + $error = 'Function closing brace must go on the next line following the body; found %s blank lines before brace'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeClose', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + if ($tokens[$i]['line'] === $tokens[$prevContent]['line']) { + continue; + } + + // Don't remove any indentation before the brace. + if ($tokens[$i]['line'] === $tokens[$closeBrace]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php new file mode 100644 index 000000000..6500d0468 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php @@ -0,0 +1,162 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MethodDeclarationSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + if ($methodName[0] === '_' && isset($methodName[1]) === true && $methodName[1] !== '_') { + $error = 'Method name "%s" should not be prefixed with an underscore to indicate visibility'; + $data = [$methodName]; + $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data); + } + + $visibility = 0; + $static = 0; + $abstract = 0; + $final = 0; + + $find = (Tokens::$methodPrefixes + Tokens::$emptyTokens); + $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + + $prefix = $stackPtr; + while (($prefix = $phpcsFile->findPrevious(Tokens::$methodPrefixes, ($prefix - 1), $prev)) !== false) { + switch ($tokens[$prefix]['code']) { + case T_STATIC: + $static = $prefix; + break; + case T_ABSTRACT: + $abstract = $prefix; + break; + case T_FINAL: + $final = $prefix; + break; + default: + $visibility = $prefix; + break; + } + } + + $fixes = []; + + if ($visibility !== 0 && $final > $visibility) { + $error = 'The final declaration must precede the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $final, 'FinalAfterVisibility'); + if ($fix === true) { + $fixes[$final] = ''; + $fixes[($final + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] = 'final '.$fixes[$visibility]; + } else { + $fixes[$visibility] = 'final '.$tokens[$visibility]['content']; + } + } + } + + if ($visibility !== 0 && $abstract > $visibility) { + $error = 'The abstract declaration must precede the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $abstract, 'AbstractAfterVisibility'); + if ($fix === true) { + $fixes[$abstract] = ''; + $fixes[($abstract + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] = 'abstract '.$fixes[$visibility]; + } else { + $fixes[$visibility] = 'abstract '.$tokens[$visibility]['content']; + } + } + } + + if ($static !== 0 && $static < $visibility) { + $error = 'The static declaration must come after the visibility declaration'; + $fix = $phpcsFile->addFixableError($error, $static, 'StaticBeforeVisibility'); + if ($fix === true) { + $fixes[$static] = ''; + $fixes[($static + 1)] = ''; + if (isset($fixes[$visibility]) === true) { + $fixes[$visibility] .= ' static'; + } else { + $fixes[$visibility] = $tokens[$visibility]['content'].' static'; + } + } + } + + // Batch all the fixes together to reduce the possibility of conflicts. + if (empty($fixes) === false) { + $phpcsFile->fixer->beginChangeset(); + foreach ($fixes as $stackPtr => $content) { + $phpcsFile->fixer->replaceToken($stackPtr, $content); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php new file mode 100644 index 000000000..7b1dad199 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php @@ -0,0 +1,100 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NamespaceDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_NAMESPACE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_NS_SEPARATOR) { + // Namespace keyword as operator. Not a declaration. + return; + } + + $end = $phpcsFile->findEndOfStatement($stackPtr); + for ($i = ($end + 1); $i < ($phpcsFile->numTokens - 1); $i++) { + if ($tokens[$i]['line'] === $tokens[$end]['line']) { + continue; + } + + break; + } + + // The $i var now points to the first token on the line after the + // namespace declaration, which must be a blank line. + $next = $phpcsFile->findNext(T_WHITESPACE, $i, $phpcsFile->numTokens, true); + if ($next === false) { + return; + } + + $diff = ($tokens[$next]['line'] - $tokens[$i]['line']); + if ($diff === 1) { + return; + } + + if ($diff < 0) { + $diff = 0; + } + + $error = 'There must be one blank line after the namespace declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'BlankLineAfter'); + + if ($fix === true) { + if ($diff === 0) { + $phpcsFile->fixer->addNewlineBefore($i); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($x = $i; $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($x, ''); + } + + $phpcsFile->fixer->addNewline($i); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php new file mode 100644 index 000000000..39c69c8b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php @@ -0,0 +1,297 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class UseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_USE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->shouldIgnoreUse($phpcsFile, $stackPtr) === true) { + return; + } + + $tokens = $phpcsFile->getTokens(); + + // One space after the use keyword. + if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + $error = 'There must be a single space after the USE keyword'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterUse'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + + // Only one USE declaration allowed per statement. + $next = $phpcsFile->findNext([T_COMMA, T_SEMICOLON, T_OPEN_USE_GROUP, T_CLOSE_TAG], ($stackPtr + 1)); + if ($next !== false + && $tokens[$next]['code'] !== T_SEMICOLON + && $tokens[$next]['code'] !== T_CLOSE_TAG + ) { + $error = 'There must be one USE keyword per declaration'; + + if ($tokens[$next]['code'] === T_COMMA) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MultipleDeclarations'); + if ($fix === true) { + switch ($tokens[($stackPtr + 2)]['content']) { + case 'const': + $baseUse = 'use const'; + break; + case 'function': + $baseUse = 'use function'; + break; + default: + $baseUse = 'use'; + } + + if ($tokens[($next + 1)]['code'] !== T_WHITESPACE) { + $baseUse .= ' '; + } + + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar.$baseUse); + } + } else { + $closingCurly = $phpcsFile->findNext(T_CLOSE_USE_GROUP, ($next + 1)); + if ($closingCurly === false) { + // Parse error or live coding. Not auto-fixable. + $phpcsFile->addError($error, $stackPtr, 'MultipleDeclarations'); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MultipleDeclarations'); + if ($fix === true) { + $baseUse = rtrim($phpcsFile->getTokensAsString($stackPtr, ($next - $stackPtr))); + $lastNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingCurly - 1), null, true); + + $phpcsFile->fixer->beginChangeset(); + + // Remove base use statement. + for ($i = $stackPtr; $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + if (preg_match('`^[\r\n]+$`', $tokens[($next + 1)]['content']) === 1) { + $phpcsFile->fixer->replaceToken(($next + 1), ''); + } + + // Convert grouped use statements into full use statements. + do { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + if ($next === false) { + // Group use statement with trailing comma after last item. + break; + } + + $nonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($next - 1), null, true); + for ($i = ($nonWhitespace + 1); $i < $next; $i++) { + if (preg_match('`^[\r\n]+$`', $tokens[$i]['content']) === 1) { + // Preserve new lines. + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + if ($tokens[$next]['content'] === 'const' || $tokens[$next]['content'] === 'function') { + $phpcsFile->fixer->addContentBefore($next, 'use '); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + $phpcsFile->fixer->addContentBefore($next, str_replace('use ', '', $baseUse)); + } else { + $phpcsFile->fixer->addContentBefore($next, $baseUse); + } + + $next = $phpcsFile->findNext(T_COMMA, ($next + 1), $closingCurly); + if ($next !== false) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), $closingCurly, true); + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['line'] === $tokens[$next]['line']) { + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($nextNonEmpty - 1), $next, true); + if ($prevNonWhitespace === $next) { + $phpcsFile->fixer->replaceToken($next, ';'.$phpcsFile->eolChar); + } else { + $phpcsFile->fixer->replaceToken($next, ';'); + $phpcsFile->fixer->addNewline($prevNonWhitespace); + } + } else { + // Last item with trailing comma or next item already on new line. + $phpcsFile->fixer->replaceToken($next, ';'); + } + } else { + // Last item without trailing comma. + $phpcsFile->fixer->addContent($lastNonWhitespace, ';'); + } + } while ($next !== false); + + // Remove closing curly, semicolon and any whitespace between last child and closing curly. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($closingCurly + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_SEMICOLON) { + // Parse error, forgotten semicolon. + $next = $closingCurly; + } + + for ($i = ($lastNonWhitespace + 1); $i <= $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Make sure this USE comes after the first namespace declaration. + $prev = $phpcsFile->findPrevious(T_NAMESPACE, ($stackPtr - 1)); + if ($prev === false) { + $next = $phpcsFile->findNext(T_NAMESPACE, ($stackPtr + 1)); + if ($next !== false) { + $error = 'USE declarations must go after the namespace declaration'; + $phpcsFile->addError($error, $stackPtr, 'UseBeforeNamespace'); + } + } + + // Only interested in the last USE statement from here onwards. + $nextUse = $phpcsFile->findNext(T_USE, ($stackPtr + 1)); + while ($this->shouldIgnoreUse($phpcsFile, $nextUse) === true) { + $nextUse = $phpcsFile->findNext(T_USE, ($nextUse + 1)); + if ($nextUse === false) { + break; + } + } + + if ($nextUse !== false) { + return; + } + + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_USE_GROUP, T_CLOSE_TAG], ($stackPtr + 1)); + if ($end === false) { + return; + } + + if ($tokens[$end]['code'] === T_CLOSE_USE_GROUP) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $end = $nextNonEmpty; + } + } + + // Find either the start of the next line or the beginning of the next statement, + // whichever comes first. + for ($end = ++$end; $end < $phpcsFile->numTokens; $end++) { + if (isset(Tokens::$emptyTokens[$tokens[$end]['code']]) === false) { + break; + } + + if ($tokens[$end]['column'] === 1) { + // Reached the next line. + break; + } + } + + --$end; + + if (($tokens[$end]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$end]['code']]) === true) + && substr($tokens[$end]['content'], 0, 2) === '/*' + && substr($tokens[$end]['content'], -2) !== '*/' + ) { + // Multi-line block comments are not allowed as trailing comment after a use statement. + --$end; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true); + + if ($next === false || $tokens[$next]['code'] === T_CLOSE_TAG) { + return; + } + + $diff = ($tokens[$next]['line'] - $tokens[$end]['line'] - 1); + if ($diff !== 1) { + if ($diff < 0) { + $diff = 0; + } + + $error = 'There must be one blank line after the last USE statement; %s found;'; + $data = [$diff]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterLastUse', $data); + if ($fix === true) { + if ($diff === 0) { + $phpcsFile->fixer->addNewline($end); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($end + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($end); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end process() + + + /** + * Check if this use statement is part of the namespace block. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return bool + */ + private function shouldIgnoreUse($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore USE keywords inside closures and during live coding. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + return true; + } + + // Ignore USE keywords for traits. + if ($phpcsFile->hasCondition($stackPtr, [T_CLASS, T_TRAIT, T_ENUM]) === true) { + return true; + } + + return false; + + }//end shouldIgnoreUse() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc new file mode 100644 index 000000000..1df40d514 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc @@ -0,0 +1,346 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +class A extends B + implements C +{ +} + +class C2 +{ + +} // phpcs:ignore Standard.Category.Sniff + +interface I1 extends + Foo +{ +} + +interface I2 extends + Bar +{ +} + +interface I3 extends + Foo, + Bar +{ +} + +class C1 extends + Foo +{ +} + +class C2 extends + Bar +{ +} + +class C3 extends Foo implements + Bar +{ +} + +class C4 extends Foo implements + Bar +{ +} + +class C5 extends Foo implements + Bar, + Baz +{ +} + +class C6 extends \Foo\Bar implements + \Baz\Bar +{ +} + +interface I4 extends + \Baz + \Bar +{ +} + +interface I5 extends /* comment */ + \Foo\Bar +{ +} + +interface I6 extends // comment + \Foo\Bar +{ +} + +class C7 extends // comment + \Foo\Bar implements \Baz\Bar +{ +} + +class +C8 +{ +} + +foo(new class { +}); + +readonly +class Test +{ +} + +readonly class Test +{ +} + +if (!class_exists('IndentedDeclaration')) { + class IndentedDeclaration + { + function foo() {} + + + } +} + +// Space between modifier and class keyword would not be flagged nor fixed if newline + indentation. +final + class FinalClassWithIndentation + { + } + +readonly + class ReadonlyClassWithIndentation + { + } + +// And would also not be flagged if there was a comment between (not auto-fixable). +final/*comment*/class FinalClassWithComment +{ +} +abstract /*comment*/ class AbstractClassWithComment +{ +} + +readonly + // comment + class ReadonlyClassWithComment + { + } + +// Safeguard against fixer conflict when there are namespace relative interface names in extends. +interface FooBar extends namespace\BarFoo +{ +} + +// Safeguard against fixer conflict when there are namespace relative interface names in a multi-line implements. +class BarFoo implements + namespace\BarFoo +{ +} + +// Safeguard that the sniff ignores comments between interface names in a multiline implements. +class ClassWithMultiLineImplementsAndIgnoreAnnotation implements + SomeInterface, + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + + \AnotherInterface +{ +} + +class ClassWithMultiLineImplementsAndComment implements + SomeInterface, + // Comment. + +AnotherInterface +{ +} + +class ClassWithMultiLineImplementsAndCommentOnSameLineAsInterfaceName implements + SomeInterface, + /* Comment. */ AnotherInterface +{ +} + +// Verify the `CloseBraceSameLine` error code is thrown when expected. +class ClassBraceNotOnLineByItselfError +{ + public $prop; +} $foo = new ClassBraceNotOnLineByItselfError; + +interface ClassBraceNotOnLineByItselfTrailingCommentIsAllowed +{ + public function myMethod(); +} //end interface -- this comment is allowed. + +trait ClassBraceNotOnLineByItselfTrailingAnnotationIsAllowed +{ +} // phpcs:ignore Stnd.Cat.Sniff -- this comment is also allowed. + +// Issue squizlabs/PHP_CodeSniffer#2621 - fix was superseded by fix for #2678. +$foo->bar( + new class implements Bar { + // ... + }, +); + +enum BraceNotOnLineByItselfCloseTagError +{ +} ?> + +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +class A extends B implements C +{ +} + +class C2 +{ + +} // phpcs:ignore Standard.Category.Sniff + +interface I1 extends + Foo +{ +} + +interface I2 extends + Bar +{ +} + +interface I3 extends + Foo, + Bar +{ +} + +class C1 extends Foo +{ +} + +class C2 extends Bar +{ +} + +class C3 extends Foo implements + Bar +{ +} + +class C4 extends Foo implements + Bar +{ +} + +class C5 extends Foo implements + Bar, + Baz +{ +} + +class C6 extends \Foo\Bar implements + \Baz\Bar +{ +} + +interface I4 extends + \Baz\Bar +{ +} + +interface I5 extends /* comment */ + \Foo\Bar +{ +} + +interface I6 extends // comment + \Foo\Bar +{ +} + +class C7 extends \Foo\Bar implements \Baz\Bar // comment +{ +} + +class C8 +{ +} + +foo(new class { +}); + +readonly class Test +{ +} + +readonly class Test +{ +} + +if (!class_exists('IndentedDeclaration')) { + class IndentedDeclaration + { + function foo() {} + } +} + +// Space between modifier and class keyword would not be flagged nor fixed if newline + indentation. +final class FinalClassWithIndentation +{ + } + +readonly class ReadonlyClassWithIndentation +{ + } + +// And would also not be flagged if there was a comment between (not auto-fixable). +final/*comment*/class FinalClassWithComment +{ +} +abstract /*comment*/ class AbstractClassWithComment +{ +} + +readonly + // comment + class ReadonlyClassWithComment + { + } + +// Safeguard against fixer conflict when there are namespace relative interface names in extends. +interface FooBar extends namespace\BarFoo +{ +} + +// Safeguard against fixer conflict when there are namespace relative interface names in a multi-line implements. +class BarFoo implements + namespace\BarFoo +{ +} + +// Safeguard that the sniff ignores comments between interface names in a multiline implements. +class ClassWithMultiLineImplementsAndIgnoreAnnotation implements + SomeInterface, + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + + \AnotherInterface +{ +} + +class ClassWithMultiLineImplementsAndComment implements + SomeInterface, + // Comment. + + AnotherInterface +{ +} + +class ClassWithMultiLineImplementsAndCommentOnSameLineAsInterfaceName implements + SomeInterface, + /* Comment. */ + AnotherInterface +{ +} + +// Verify the `CloseBraceSameLine` error code is thrown when expected. +class ClassBraceNotOnLineByItselfError +{ + public $prop; +} $foo = new ClassBraceNotOnLineByItselfError; + +interface ClassBraceNotOnLineByItselfTrailingCommentIsAllowed +{ + public function myMethod(); +} //end interface -- this comment is allowed. + +trait ClassBraceNotOnLineByItselfTrailingAnnotationIsAllowed +{ +} // phpcs:ignore Stnd.Cat.Sniff -- this comment is also allowed. + +// Issue squizlabs/PHP_CodeSniffer#2621 - fix was superseded by fix for #2678. +$foo->bar( + new class implements Bar { + // ... + }, +); + +enum BraceNotOnLineByItselfCloseTagError +{ +} ?> + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff + */ +final class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 7 => 3, + 12 => 1, + 13 => 1, + 17 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 1, + 25 => 1, + 27 => 2, + 34 => 1, + 35 => 2, + 44 => 1, + 45 => 1, + 63 => 1, + 95 => 1, + 116 => 1, + 118 => 1, + 119 => 1, + 124 => 1, + 130 => 2, + 131 => 1, + 158 => 1, + 168 => 1, + 178 => 1, + 179 => 1, + 184 => 1, + 189 => 1, + 194 => 1, + 204 => 1, + 205 => 1, + 210 => 1, + 215 => 2, + 216 => 1, + 231 => 2, + 235 => 1, + 244 => 1, + 248 => 1, + 258 => 1, + 263 => 1, + 268 => 1, + 273 => 1, + 276 => 1, + 282 => 1, + 310 => 1, + 316 => 1, + 324 => 1, + 344 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc new file mode 100644 index 000000000..3e086c6f2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the PropertyDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\PropertyDeclarationSniff + */ +final class PropertyDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 9 => 2, + 10 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 23 => 1, + 38 => 1, + 41 => 1, + 42 => 1, + 50 => 2, + 51 => 1, + 55 => 1, + 56 => 1, + 61 => 1, + 62 => 1, + 68 => 1, + 69 => 1, + 71 => 1, + 72 => 1, + 76 => 1, + 80 => 1, + 82 => 1, + 84 => 1, + 86 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 13 => 1, + 14 => 1, + 15 => 1, + 53 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc new file mode 100644 index 000000000..542ab3cf2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,81 @@ + $that) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 + +$binary = b"binary string"; + +if ($expr1 + && $expr2 ) { +} + +if ($expr1 + && $expr2 /* comment */ ) { +} + +if ($expr1 + && $expr2 + /* comment */ ) { +} + +$r = match ($x) {}; +$r = match ( $x ) {}; + +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 1 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 1 +$r = match ($x) {}; +$r = match ( $x ) {}; +$r = match ( $x ) {}; +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..a29534bee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,80 @@ + $that ) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 + +$binary = b"binary string"; + +if ($expr1 + && $expr2) { +} + +if ($expr1 + && $expr2 /* comment */) { +} + +if ($expr1 + && $expr2 + /* comment */) { +} + +$r = match ($x) {}; +$r = match ($x) {}; + +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 1 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 1 +$r = match ( $x ) {}; +$r = match ( $x ) {}; +$r = match ( $x ) {}; +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesAfterOpen 0 +// phpcs:set PSR2.ControlStructures.ControlStructureSpacing requiredSpacesBeforeClose 0 diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php new file mode 100644 index 000000000..a8ab73e1a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ControlStructureSpacingSniff + */ +final class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 14 => 2, + 26 => 2, + 27 => 2, + 31 => 1, + 51 => 2, + 53 => 2, + 60 => 1, + 64 => 1, + 69 => 1, + 73 => 2, + 77 => 2, + 79 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc new file mode 100644 index 000000000..778659c82 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..4a7bfdc27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc.fixed @@ -0,0 +1,17 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php new file mode 100644 index 000000000..79d46542f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ElseIfDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ElseIfDeclarationSniff + */ +final class ElseIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 4 => 1, + 12 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc new file mode 100644 index 000000000..2ca60a93e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc @@ -0,0 +1,598 @@ + 0) { + return 0; + } else { + return 1; + } + case 2: + return 2; +} + +// ERROR: No else clause +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } + case 2: + return 2; +} + +// OK: No fall-through present +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } +} + +// ERROR: No else clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } else { + break; + } + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause +switch ($foo) { + case 1: + if ($bar > 0) { + $offset = 0; + } else { + break; + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + continue; + } else { + if ($foo > $bar) { + $offset = 0; + } else { + break; + } + } + case 2: + return 2; +} + +switch ($sContext) +{ + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +$foo = $foo ? + function () { + switch ($a) { + case 'a': + break; + } + } : + null; + +switch ($foo) { +case Foo::INTERFACE: + echo '1'; + return self::INTERFACE; +case Foo::TRAIT: +case Foo::ARRAY: + echo '1'; + return self::VALUE; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + return 3; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + default: + $a = 1; + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + throw new \Exception(); + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + // phpcs:ignore + case 2: + return 1; + case 3: + return 2; +} + +// Issue 3352. +switch ( $test ) { + case 2: // comment followed by empty line + + break; + + case 3: /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments. */ + + + + break; + + case 4: /** inline docblock */ + + + + break; + + case 5: /* checking how it handles */ /* two trailing comments */ + + break; + + case 6: + // Comment as first content of the body. + + break; + + case 7: + /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments at start of body. */ + + break; + + case 8: + /** inline docblock */ + + break; +} + +// Handle comments correctly. +switch ($foo) { + case 1: + if ($bar > 0) { + doSomething(); + } + // Comment + else { + return 1; + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + if ($bar > 0) /*comment*/ { + return doSomething(); + } + else { + return 1; + } + case 2: + return 2; +} + +// Issue #3297. +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + doSomething(); + } finally { + return true; + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) /*comment*/ { + return true; + } + // Comment + catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } finally { + return true; + } catch (AnotherException $e) { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + return false; + } finally { + doSomething(); + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no finally. Any exception still uncaught will terminate the case anyhow, so we're good. +switch ( $a ) { + case 1: + try { + return false; + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no catch +switch ( $a ) { + case 1: + try { + return true; + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// All okay, try-catch nested in if. +switch ( $a ) { + case 1: + if ($a) { + try { + return true; // Comment. + } catch (MyException $e) { + throw new Exception($e->getMessage()); + } + } else { + return true; + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. Try does not have a terminating statement. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } catch (Exception $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Issue 3550 - comment after terminating statement. +switch (rand()) { + case 1: + if (rand() === 1) { + break; + } else { + break; // comment + } + default: + break; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..bbc8b7c48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc.fixed @@ -0,0 +1,593 @@ + 0) { + return 0; + } else { + return 1; + } + case 2: + return 2; +} + +// ERROR: No else clause +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } + case 2: + return 2; +} + +// OK: No fall-through present +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } elseif ($bar < 0) { + return 1; + } +} + +// ERROR: No else clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + if ($bar > 0) { + return 0; + } else { + if ($foo > $bar) { + continue; + } else { + break; + } + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause +switch ($foo) { + case 1: + if ($bar > 0) { + $offset = 0; + } else { + break; + } + case 2: + return 2; +} + +// ERROR: Non-termination IF clause (nested) +switch ($foo) { + case 1: + if ($bar > 0) { + continue; + } else { + if ($foo > $bar) { + $offset = 0; + } else { + break; + } + } + case 2: + return 2; +} + +switch ($sContext) +{ + case 'SOMETHING': + case 'CONSTANT': + do_something(); + break; + case 'GLOBAL': + case 'GLOBAL1': + do_something(); + // Fall through + default: + { + do_something(); + } +} + +$foo = $foo ? + function () { + switch ($a) { + case 'a': + break; + } + } : + null; + +switch ($foo) { +case Foo::INTERFACE: + echo '1'; + return self::INTERFACE; +case Foo::TRAIT: +case Foo::ARRAY: + echo '1'; + return self::VALUE; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + return 3; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + } + case 2: + return 2; +} + +// KO: Not every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return; + default: + $a = 1; + } + case 2: + return 2; +} + +// OK: Every clause terminates +switch ($foo) { + case 1: + switch ($bar) { + case 1: + return 1; + default: + throw new \Exception(); + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + // phpcs:ignore + case 2: + return 1; + case 3: + return 2; +} + +// Issue 3352. +switch ( $test ) { + case 2: // comment followed by empty line + break; + + case 3: /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments. */ + break; + + case 4: /** inline docblock */ + break; + + case 5: /* checking how it handles */ /* two trailing comments */ + break; + + case 6: + // Comment as first content of the body. + + break; + + case 7: + /* phpcs:ignore Stnd.Cat.SniffName -- Verify correct handling of ignore comments at start of body. */ + + break; + + case 8: + /** inline docblock */ + + break; +} + +// Handle comments correctly. +switch ($foo) { + case 1: + if ($bar > 0) { + doSomething(); + } + // Comment + else { + return 1; + } + case 2: + return 2; +} + +switch ($foo) { + case 1: + if ($bar > 0) /*comment*/ { + return doSomething(); + } + else { + return 1; + } + case 2: + return 2; +} + +// Issue #3297. +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + doSomething(); + } finally { + return true; + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) /*comment*/ { + return true; + } + // Comment + catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - finally will always be executed, so all branches are covered by the `return` in finally. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + doSomething(); + } catch (Exception $e) { + doSomething(); + } finally { + return true; + } catch (AnotherException $e) { + doSomething(); + } + default: + $other = $code; + break; +} + +// Okay - all - non-finally - branches have a terminating statement. +// Non-standard structure order. +switch ( $a ) { + case 1: + try { + return false; + } finally { + doSomething(); + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no finally. Any exception still uncaught will terminate the case anyhow, so we're good. +switch ( $a ) { + case 1: + try { + return false; + } catch (MyException $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// All okay, no catch +switch ( $a ) { + case 1: + try { + return true; + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// All okay, try-catch nested in if. +switch ( $a ) { + case 1: + if ($a) { + try { + return true; // Comment. + } catch (MyException $e) { + throw new Exception($e->getMessage()); + } + } else { + return true; + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } + case 2: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } finally { + doSomething(); + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. Try does not have a terminating statement. +switch ( $a ) { + case 1: + try { + doSomething(); + } finally { + doSomething(); + } catch (Exception $e) { + return true; + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Missing fall-through comment. One of the catches does not have a terminating statement. +switch ( $a ) { + case 1: + try { + return false; + } catch (Exception $e) { + doSomething(); + } catch (AnotherException $e) { + return true; + } + default: + $other = $code; + break; +} + +// Issue 3550 - comment after terminating statement. +switch (rand()) { + case 1: + if (rand() === 1) { + break; + } else { + break; // comment + } + default: + break; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php new file mode 100644 index 000000000..a292503dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php @@ -0,0 +1,86 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SwitchDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\SwitchDeclarationSniff + */ +final class SwitchDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 10 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + 20 => 1, + 23 => 1, + 29 => 1, + 33 => 1, + 37 => 2, + 108 => 2, + 109 => 1, + 111 => 1, + 113 => 2, + 114 => 1, + 128 => 1, + 141 => 1, + 172 => 1, + 194 => 1, + 224 => 1, + 236 => 1, + 260 => 1, + 300 => 1, + 311 => 1, + 346 => 1, + 350 => 1, + 356 => 1, + 362 => 1, + 384 => 1, + 528 => 1, + 541 => 1, + 558 => 1, + 575 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc new file mode 100644 index 000000000..738e70e9b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc @@ -0,0 +1,12 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed new file mode 100644 index 000000000..f70b9ebad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.1.inc.fixed @@ -0,0 +1,12 @@ + + +
    + +
    \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc new file mode 100644 index 000000000..d6a861750 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.3.inc @@ -0,0 +1,7 @@ + + +A: +B: +C: \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc new file mode 100644 index 000000000..dd103cde3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc @@ -0,0 +1 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed new file mode 100644 index 000000000..1058f1f37 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.4.inc.fixed @@ -0,0 +1 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed new file mode 100644 index 000000000..93d55fbdc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.5.inc.fixed @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed new file mode 100644 index 000000000..534574d44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.6.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed new file mode 100644 index 000000000..68e7d8ce0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/ClosingTagUnitTest.7.inc.fixed @@ -0,0 +1,5 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClosingTag sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\ClosingTagSniff + */ +final class ClosingTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingTagUnitTest.1.inc': + return [11 => 1]; + + case 'ClosingTagUnitTest.4.inc': + case 'ClosingTagUnitTest.5.inc': + return [1 => 1]; + + case 'ClosingTagUnitTest.6.inc': + case 'ClosingTagUnitTest.7.inc': + return [5 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc new file mode 100644 index 000000000..ca2a7493a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed new file mode 100644 index 000000000..d3c19feeb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.12.inc.fixed @@ -0,0 +1 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc new file mode 100644 index 000000000..fa2f476a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.13.inc @@ -0,0 +1,5 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc new file mode 100644 index 000000000..1254e4a55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc @@ -0,0 +1,2 @@ + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc new file mode 100644 index 000000000..c3a59b672 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc @@ -0,0 +1,6 @@ + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EndFileNewline sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\EndFileNewlineSniff + */ +final class EndFileNewlineUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'EndFileNewlineUnitTest.1.inc': + case 'EndFileNewlineUnitTest.3.inc': + case 'EndFileNewlineUnitTest.6.inc': + case 'EndFileNewlineUnitTest.7.inc': + case 'EndFileNewlineUnitTest.9.inc': + case 'EndFileNewlineUnitTest.10.inc': + return [2 => 1]; + case 'EndFileNewlineUnitTest.11.inc': + case 'EndFileNewlineUnitTest.12.inc': + case 'EndFileNewlineUnitTest.13.inc': + return [1 => 1]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc new file mode 100644 index 000000000..1ca477d05 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc @@ -0,0 +1,267 @@ +get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}, array( + '1', + '2', + '3', +)); + +// error +somefunction2($foo, $bar, [ + // ... + ], +$baz); + +// ok +somefunction3(// ... + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction4(' + this should not + give an error + because it\'s actually + one line call + with multi-line string +'); + +// ok +somefunction5("hey, +multi-line string with some +extra args", $foo, 12); + +// error +somefunction6(' + but args in a new line + are not ok… + ', + $foo +); + +$this->setFoo(true + ? 1 + : 2, false, array( + 'value', + 'more')); + +$this->setFoo('some' + . 'long' + . 'text', 'string'); + +foo(bar(), $a); +foo();bar(); + +foo( + true +); + +myFunction(<< function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, function ($x) { + return $x; + } +); + +$this->listeners[] = $events->getSharedManager()->attach( + 'Zend\Mvc\Application', MvcEvent::EVENT_DISPATCH, [$this, 'selectLayout'], 100 +); + +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 1 +foo('Testing + multiline text' + ); + +foo('Testing + multiline text: ' // . $text + ); + +foo('Testing + multiline text: ' /* . $text */ + ); + +foo('Testing + multiline text: ' /* . $text */ + // . $other_text + ); + +foo('Testing + multiline text: ' /* + . $text +// . $text2 + */ + ); +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 0 + +foo('Testing + multiline text' +); + +foo('Testing + multiline text' + ); + +foo('Testing + multiline text' // hello +); + +foo('Testing + multiline text' /* hello */ +); + +foo('Testing + multiline text' + // hello +); + +foo('Testing + multiline text' + /* hello */ +); + +$var = foo('Testing + multiline' + // hi + ) + foo('Testing + multiline' + // hi + ) +; + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a', 'b', 'c' + ); + } +} + +$x = $var('y', + 'x'); + +$obj->{$x}(1, +2); + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a','b' +)('c', + 'd'); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search + )); + +return trim(preg_replace_callback( +// sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) +// /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ +sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), +function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; +}, +$search +)); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); + +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments true +array_fill_keys( + keys: range( 1, + 12, + ), value: true, +); +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed new file mode 100644 index 000000000..dc383ed2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.inc.fixed @@ -0,0 +1,283 @@ +get('/hello/{name}', function ($name) use ($app) { + return 'Hello '.$app->escape($name); +}, array( + '1', + '2', + '3', +)); + +// error +somefunction2( + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction3(// ... + $foo, + $bar, + [ + // ... + ], + $baz +); + +// ok +somefunction4(' + this should not + give an error + because it\'s actually + one line call + with multi-line string +'); + +// ok +somefunction5("hey, +multi-line string with some +extra args", $foo, 12); + +// error +somefunction6( + ' + but args in a new line + are not ok… + ', + $foo +); + +$this->setFoo(true + ? 1 + : 2, false, array( + 'value', + 'more')); + +$this->setFoo('some' + . 'long' + . 'text', 'string'); + +foo(bar(), $a); +foo();bar(); + +foo( + true +); + +myFunction(<< function ($x) { + return true; + }, + 'baz' => false + ) +); +$qux = array_filter( + $quux, + function ($x) { + return $x; + } +); + +$this->listeners[] = $events->getSharedManager()->attach( + 'Zend\Mvc\Application', + MvcEvent::EVENT_DISPATCH, + [$this, 'selectLayout'], + 100 +); + +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 1 +foo('Testing + multiline text' ); + +foo('Testing + multiline text: ' ); // . $text + + +foo('Testing + multiline text: ' /* . $text */ ); + +foo('Testing + multiline text: ' /* . $text */ ); + // . $other_text + + +foo('Testing + multiline text: ' /* + . $text +// . $text2 + */ ); +// phpcs:set PSR2.Methods.FunctionCallSignature requiredSpacesBeforeClose 0 + +foo('Testing + multiline text'); + +foo('Testing + multiline text'); + +foo('Testing + multiline text'); // hello + + +foo('Testing + multiline text' /* hello */); + +foo('Testing + multiline text'); + // hello + + +foo('Testing + multiline text' + /* hello */); + +$var = foo('Testing + multiline') + // hi + + foo('Testing + multiline'); + // hi + + +class Test +{ + public function getInstance() + { + return new static( + 'arg', + 'foo' + ); + } + + public function getSelf() + { + return new self( + 'a', + 'b', + 'c' + ); + } +} + +$x = $var( + 'y', + 'x' +); + +$obj->{$x}( + 1, + 2 +); + +(function ($a, $b) { + return function ($c, $d) use ($a, $b) { + echo $a, $b, $c, $d; + }; +})( + 'a', + 'b' +)( + 'c', + 'd' +); + +return trim(preg_replace_callback( + // sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) + // /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search +)); + +return trim(preg_replace_callback( +// sprintf replaces IGNORED_CHARS multiple times: for %s as well as %1$s (argument numbering) +// /[%s]*([^%1$s]+)/ results in /[IGNORED_CHARS]*([^IGNORED_CHARS]+)/ + sprintf('/[%s]*([^%1$s]+)/', self::IGNORED_CHARS), + function (array $term) use ($mode): string { + // query pieces have to bigger than one char, otherwise they are too expensive for the search + if (mb_strlen($term[1], 'UTF-8') > 1) { + // in boolean search mode '' (empty) means OR, '-' means NOT + return sprintf('%s%s ', $mode === 'AND' ? '+' : '', self::extractUmlauts($term[1])); + } + + return ''; + }, + $search +)); + +// PHP 8.0 named parameters. +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +array_fill_keys( + keys: range( + 1, + 12, + ), + value: true, +); + +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments true +array_fill_keys( + keys: range( + 1, + 12, + ), value: true, +); +// phpcs:set PSR2.Methods.FunctionCallSignature allowMultipleArguments false diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php new file mode 100644 index 000000000..52cda1746 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php @@ -0,0 +1,99 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionCallSignature sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionCallSignatureSniff + */ +final class FunctionCallSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 18 => 3, + 21 => 1, + 48 => 1, + 87 => 1, + 90 => 1, + 91 => 1, + 103 => 1, + 111 => 1, + 117 => 4, + 123 => 1, + 127 => 1, + 131 => 1, + 136 => 1, + 143 => 1, + 148 => 1, + 152 => 1, + 156 => 1, + 160 => 1, + 165 => 1, + 170 => 1, + 175 => 1, + 178 => 2, + 186 => 1, + 187 => 1, + 194 => 3, + 199 => 1, + 200 => 2, + 202 => 1, + 203 => 1, + 210 => 2, + 211 => 1, + 212 => 2, + 217 => 1, + 218 => 1, + 227 => 1, + 228 => 1, + 233 => 1, + 234 => 1, + 242 => 1, + 243 => 1, + 256 => 1, + 257 => 1, + 258 => 1, + 263 => 1, + 264 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc new file mode 100644 index 000000000..7bf667e6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/FunctionClosingBraceUnitTest.inc @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionClosingBrace sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionClosingBraceSniff + */ +final class FunctionClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 16 => 1, + 23 => 1, + 40 => 1, + 47 => 1, + 63 => 1, + 70 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc new file mode 100644 index 000000000..096b44bc8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Methods; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MethodDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff + */ +final class MethodDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 11 => 1, + 13 => 1, + 15 => 3, + 24 => 1, + 34 => 1, + 36 => 1, + 38 => 1, + 40 => 3, + 50 => 1, + 52 => 1, + 54 => 1, + 56 => 3, + 63 => 2, + 73 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 5 => 1, + 21 => 1, + 30 => 1, + 46 => 1, + 63 => 1, + 70 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc new file mode 100644 index 000000000..703393396 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the NamespaceDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces\NamespaceDeclarationSniff + */ +final class NamespaceDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 9 => 1, + 17 => 1, + 19 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc new file mode 100644 index 000000000..977a7fb22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.inc @@ -0,0 +1,40 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed new file mode 100644 index 000000000..6579613b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc.fixed @@ -0,0 +1,27 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc new file mode 100644 index 000000000..8b290950b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc @@ -0,0 +1,16 @@ + +

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc new file mode 100644 index 000000000..1fdaccd38 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.5.inc @@ -0,0 +1,47 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc new file mode 100644 index 000000000..dee568699 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.7.inc @@ -0,0 +1 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\PSR2\Tests\Namespaces; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the UseDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces\UseDeclarationSniff + */ +final class UseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'UseDeclarationUnitTest.2.inc': + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 16 => 1, + ]; + case 'UseDeclarationUnitTest.3.inc': + return [ + 4 => 1, + 6 => 1, + ]; + case 'UseDeclarationUnitTest.5.inc': + return [ + 5 => 1, + 6 => 1, + 8 => 1, + 14 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 21 => 1, + 28 => 1, + 30 => 1, + 35 => 1, + ]; + case 'UseDeclarationUnitTest.10.inc': + case 'UseDeclarationUnitTest.11.inc': + case 'UseDeclarationUnitTest.12.inc': + case 'UseDeclarationUnitTest.13.inc': + case 'UseDeclarationUnitTest.14.inc': + case 'UseDeclarationUnitTest.16.inc': + case 'UseDeclarationUnitTest.17.inc': + return [2 => 1]; + case 'UseDeclarationUnitTest.15.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 1, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml new file mode 100644 index 000000000..ba5bd4e0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/PSR2/ruleset.xml @@ -0,0 +1,218 @@ + + + The PSR-2 coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + 0 + + + 0 + + + + + + + 0 + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml new file mode 100644 index 000000000..d91fec901 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ['bar']; + ]]> + + + [ 'bar' ]; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml new file mode 100644 index 000000000..568fac305 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml @@ -0,0 +1,117 @@ + + + + + + array keyword must be lowercase. + ]]> + + + + + + + + + + + array keyword. + ]]> + + + + 'value1', + 'key2' => 'value2', + ); + ]]> + + + 'value1', + 'key2' => 'value2', + ); + ]]> + + + + array keyword. The closing parenthesis must be aligned with the start of the array keyword. + ]]> + + + + 'key1' => 'value1', + 'key2' => 'value2', + ); + ]]> + + + 'key1' => 'value1', + 'key2' => 'value2', +); + ]]> + + + + + + + + => 'ValueTen', + 'keyTwenty' => 'ValueTwenty', + ); + ]]> + + + => 'ValueTen', + 'keyTwenty' => 'ValueTwenty', + ); + ]]> + + + + + + + + 'value1', + 'key2' => 'value2', + 'key3' => 'value3', + ); + ]]> + + + 'value1', + 'key2' => 'value2', + 'key3' => 'value3' + ); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml new file mode 100644 index 000000000..610edf62f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml @@ -0,0 +1,23 @@ + + + + + + + final class Foo extends Bar +{ +} + ]]> + + + Final Class Foo Extends Bar +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml new file mode 100644 index 000000000..4f982fa4e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml @@ -0,0 +1,63 @@ + + + + + + + self::foo(); + ]]> + + + SELF::foo(); + ]]> + + + + + ::foo(); + ]]> + + + :: foo(); + ]]> + + + + + self::bar(); + } +} + ]]> + + + Foo +{ + public static function bar() + { + } + + public static function baz() + { + Foo::bar(); + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml new file mode 100644 index 000000000..17fed42cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xml @@ -0,0 +1,39 @@ + + + + + + + * @see foo() + */ + ]]> + + + * @see foo() +*/ + ]]> + + + + + @see foo() + */ + ]]> + + + @see foo() + */ + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml new file mode 100644 index 000000000..e3638a49c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml @@ -0,0 +1,32 @@ + + + + + + + @throws Exception all the time + * @return void + */ +function foo() +{ + throw new Exception('Danger!'); +} + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml new file mode 100644 index 000000000..42fa6f439 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml @@ -0,0 +1,39 @@ + + + + + + + $foo as $bar => $baz) { + echo $baz; +} + ]]> + + + $foo as $bar=>$baz ) { + echo $baz; +} + ]]> + + + + + as $bar => $baz) { + echo $baz; +} + ]]> + + + AS $bar => $baz) { + echo $baz; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml new file mode 100644 index 000000000..37caaded0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xml @@ -0,0 +1,55 @@ + + + + + + + $i = 0; $i < 10; $i++) { + echo $i; +} + ]]> + + + $i = 0; $i < 10; $i++ ) { + echo $i; +} + ]]> + + + + + ; $i < 10; $i++) { + echo $i; +} + ]]> + + + ; $i < 10 ; $i++) { + echo $i; +} + ]]> + + + + + $i < 10; $i++) { + echo $i; +} + ]]> + + + $i < 10;$i++) { + echo $i; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml new file mode 100644 index 000000000..d281400be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml @@ -0,0 +1,23 @@ + + + + + + + if ($foo) { + $bar = true; +} + ]]> + + + IF ($foo) { + $bar = true; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml new file mode 100644 index 000000000..fb2ef443c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml @@ -0,0 +1,25 @@ + + + + + + + function foo() +{ + return true; +} + ]]> + + + FUNCTION foo() +{ + return true; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/PHP/HeredocStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/PHP/HeredocStandard.xml new file mode 100644 index 000000000..b2a63be39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/PHP/HeredocStandard.xml @@ -0,0 +1,32 @@ + + + + + + + +some text + + + + <<; + +echo <<<'EOD' +some text +EOD; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml new file mode 100644 index 000000000..0145657d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xml @@ -0,0 +1,31 @@ + + + + + + + static function bar() + { + return self::$staticMember; + } +} + ]]> + + + static function bar() + { + return $this->$staticMember; + } +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml new file mode 100644 index 000000000..2bc536ebb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml @@ -0,0 +1,19 @@ + + + + + + + "Hello"; + ]]> + + + ("Hello"); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml new file mode 100644 index 000000000..9529b1fda --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + int)'42'; + ]]> + + + int )'42'; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionClosingBraceSpaceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionClosingBraceSpaceStandard.xml new file mode 100644 index 000000000..ccbdfa214 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionClosingBraceSpaceStandard.xml @@ -0,0 +1,73 @@ + + + + + + + { + +} +]]> + + + {} +]]> + + + + + + + + + { + } + +} +]]> + + + {} + +} +]]> + + + + + + + + + { + } + +} +]]> + + + { + + } + +} +]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml new file mode 100644 index 000000000..28fa712f8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml @@ -0,0 +1,41 @@ + + + + + + + { +} + ]]> + + + { +} + ]]> + + + + + return 42; +} + ]]> + + + + return 42; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml new file mode 100644 index 000000000..85838ec32 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + "hi"; + ]]> + + + "hi"; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/MemberVarSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/MemberVarSpacingStandard.xml new file mode 100644 index 000000000..a551af8a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/MemberVarSpacingStandard.xml @@ -0,0 +1,91 @@ + + + + + + + + + protected $var1 = 'value'; +} + ]]> + + + + protected $var1 = 'value'; +} + ]]> + + + + + + + + + + public $var2 = 'value2'; + + public $var3 = 'value3'; +} + ]]> + + + + + + public $var2 = 'value2'; + public $var3 = 'value3'; +} + ]]> + + + + + + + + + public $actions = array(); +}; + ]]> + + + + + public $actions = array(); +}; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml new file mode 100644 index 000000000..44edc7b5d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml @@ -0,0 +1,19 @@ + + + ) should not have any space around it. + ]]> + + + + ->bar(); + ]]> + + + -> bar(); + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeClosingBraceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeClosingBraceStandard.xml new file mode 100644 index 000000000..3284df973 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeClosingBraceStandard.xml @@ -0,0 +1,59 @@ + + + + + + + } + +if (!class_exists('Foo')) { + class Foo { + } +} + + + some output + ?> + ]]> + + + } + +if (!class_exists('Foo')) { + class Foo { +} + } + + + some output + ?> + ]]> + + + + + + + + } + ]]> + + + } + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml new file mode 100644 index 000000000..f226a128b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml @@ -0,0 +1,23 @@ + + + + + + + static function foo() +{ +} + ]]> + + + static function foo() +{ +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml new file mode 100644 index 000000000..bb9bf8f0c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml @@ -0,0 +1,19 @@ + + + + + + + ; + ]]> + + + ; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SuperfluousWhitespaceStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SuperfluousWhitespaceStandard.xml new file mode 100644 index 000000000..b4ad03d0b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Docs/WhiteSpace/SuperfluousWhitespaceStandard.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + + echo 'code here'; +} + ]]> + + + + + + + + + + ]]> + + + + + + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php new file mode 100644 index 000000000..b6bb31de6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php @@ -0,0 +1,95 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ArrayBracketSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET + && isset($tokens[$stackPtr]['bracket_closer']) === false) + || ($tokens[$stackPtr]['code'] === T_CLOSE_SQUARE_BRACKET + && isset($tokens[$stackPtr]['bracket_opener']) === false) + ) { + // Bow out for parse error/during live coding. + return; + } + + // Square brackets can not have a space before them. + $prevType = $tokens[($stackPtr - 1)]['code']; + if ($prevType === T_WHITESPACE) { + $nonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 2), null, true); + $expected = $tokens[$nonSpace]['content'].$tokens[$stackPtr]['content']; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).$tokens[$stackPtr]['content']; + $error = 'Space found before square bracket; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeBracket', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + + // Open square brackets can't ever have spaces after them. + if ($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET) { + $nextType = $tokens[($stackPtr + 1)]['code']; + if ($nextType === T_WHITESPACE) { + $nonSpace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 2), null, true); + $expected = $tokens[$stackPtr]['content'].$tokens[$nonSpace]['content']; + $found = $phpcsFile->getTokensAsString($stackPtr, ($nonSpace - $stackPtr + 1)); + $error = 'Space found after square bracket; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterBracket', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php new file mode 100644 index 000000000..89cd7bd57 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php @@ -0,0 +1,942 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ArrayDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ARRAY, + T_OPEN_SHORT_ARRAY, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no'); + + // Array keyword should be lower case. + if ($tokens[$stackPtr]['content'] !== strtolower($tokens[$stackPtr]['content'])) { + if ($tokens[$stackPtr]['content'] === strtoupper($tokens[$stackPtr]['content'])) { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'upper'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'mixed'); + } + + $error = 'Array keyword should be lower case; expected "array" but found "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotLowerCase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'array'); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'lower'); + } + + $arrayStart = $tokens[$stackPtr]['parenthesis_opener']; + if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) { + return; + } + + $arrayEnd = $tokens[$arrayStart]['parenthesis_closer']; + + if ($arrayStart !== ($stackPtr + 1)) { + $error = 'There must be no space between the "array" keyword and the opening parenthesis'; + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $arrayStart, true); + if (isset(Tokens::$commentTokens[$tokens[$next]['code']]) === true) { + // We don't have anywhere to put the comment, so don't attempt to fix it. + $phpcsFile->addError($error, $stackPtr, 'SpaceAfterKeyword'); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $arrayStart; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes'); + $arrayStart = $stackPtr; + $arrayEnd = $tokens[$stackPtr]['bracket_closer']; + }//end if + + // Check for empty arrays. + $content = $phpcsFile->findNext(T_WHITESPACE, ($arrayStart + 1), ($arrayEnd + 1), true); + if ($content === $arrayEnd) { + // Empty array, but if the brackets aren't together, there's a problem. + if (($arrayEnd - $arrayStart) !== 1) { + $error = 'Empty array declaration must have no space between the parentheses'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceInEmptyArray'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + // We can return here because there is nothing else to check. All code + // below can assume that the array is not empty. + return; + } + + if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) { + $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd); + } else { + $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd); + } + + }//end process() + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + + // Check if there are multiple values. If so, then it has to be multiple lines + // unless it is contained inside a function call or condition. + $valueCount = 0; + $commas = []; + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + // Skip bracketed statements, like function calls. + if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_COMMA) { + // Before counting this comma, make sure we are not + // at the end of the array. + $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $arrayEnd, true); + if ($next !== false) { + $valueCount++; + $commas[] = $i; + } else { + // There is a comma at the end of a single line array. + $error = 'Comma not allowed after last value in single-line array declaration'; + $fix = $phpcsFile->addFixableError($error, $i, 'CommaAfterLast'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + }//end for + + // Now check each of the double arrows (if any). + $nextArrow = $arrayStart; + while (($nextArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, ($nextArrow + 1), $arrayEnd)) !== false) { + if ($tokens[($nextArrow - 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($nextArrow - 1)]['content']; + $error = 'Expected 1 space between "%s" and double arrow; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceBeforeDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($nextArrow, ' '); + } + } else { + $spaceLength = $tokens[($nextArrow - 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($nextArrow - 2)]['content']; + $error = 'Expected 1 space between "%s" and double arrow; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceBeforeDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextArrow - 1), ' '); + } + } + }//end if + + if ($tokens[($nextArrow + 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($nextArrow + 1)]['content']; + $error = 'Expected 1 space between double arrow and "%s"; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceAfterDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($nextArrow, ' '); + } + } else { + $spaceLength = $tokens[($nextArrow + 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($nextArrow + 2)]['content']; + $error = 'Expected 1 space between double arrow and "%s"; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceAfterDoubleArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextArrow + 1), ' '); + } + } + }//end if + }//end while + + if ($valueCount > 0) { + $nestedParenthesis = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + $nestedParenthesis = array_pop($nested); + } + + if ($nestedParenthesis === false + || $tokens[$nestedParenthesis]['line'] !== $tokens[$stackPtr]['line'] + ) { + $error = 'Array with multiple values cannot be declared on a single line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLineNotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($arrayStart); + + if ($tokens[($arrayEnd - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($arrayEnd); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + // We have a multiple value array that is inside a condition or + // function. Check its spacing is correct. + foreach ($commas as $comma) { + if ($tokens[($comma + 1)]['code'] !== T_WHITESPACE) { + $content = $tokens[($comma + 1)]['content']; + $error = 'Expected 1 space between comma and "%s"; 0 found'; + $data = [$content]; + $fix = $phpcsFile->addFixableError($error, $comma, 'NoSpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($comma, ' '); + } + } else { + $spaceLength = $tokens[($comma + 1)]['length']; + if ($spaceLength !== 1) { + $content = $tokens[($comma + 2)]['content']; + $error = 'Expected 1 space between comma and "%s"; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceAfterComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($comma + 1), ' '); + } + } + }//end if + + if ($tokens[($comma - 1)]['code'] === T_WHITESPACE) { + $content = $tokens[($comma - 2)]['content']; + $spaceLength = $tokens[($comma - 1)]['length']; + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($comma - 1), ''); + } + } + }//end foreach + }//end if + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd) + { + $tokens = $phpcsFile->getTokens(); + $keywordStart = $tokens[$stackPtr]['column']; + + // Check the closing bracket is on a new line. + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), $arrayStart, true); + if ($tokens[$lastContent]['line'] === $tokens[$arrayEnd]['line']) { + $error = 'Closing parenthesis of array declaration must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNewLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($arrayEnd); + } + } else if ($tokens[$arrayEnd]['column'] !== $keywordStart) { + // Check the closing bracket is lined up under the "a" in array. + $expected = ($keywordStart - 1); + $found = ($tokens[$arrayEnd]['column'] - 1); + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + $error = 'Closing parenthesis not aligned correctly; expected %s space%s but found %s'; + $data = [ + $expected, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($arrayEnd - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($arrayEnd - 1), str_repeat(' ', $expected)); + } + } + }//end if + + $keyUsed = false; + $singleUsed = false; + $indices = []; + $maxLength = 0; + + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + $lastToken = $tokens[$stackPtr]['parenthesis_opener']; + } else { + $lastToken = $stackPtr; + } + + // Find all the double arrows that reside in this scope. + for ($nextToken = ($stackPtr + 1); $nextToken < $arrayEnd; $nextToken++) { + // Skip bracketed statements, like function calls. + if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS + && (isset($tokens[$nextToken]['parenthesis_owner']) === false + || $tokens[$nextToken]['parenthesis_owner'] !== $stackPtr) + ) { + $nextToken = $tokens[$nextToken]['parenthesis_closer']; + continue; + } + + if ($tokens[$nextToken]['code'] === T_ARRAY + || $tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY + || $tokens[$nextToken]['code'] === T_CLOSURE + || $tokens[$nextToken]['code'] === T_FN + || $tokens[$nextToken]['code'] === T_MATCH + ) { + // Let subsequent calls of this test handle nested arrays. + if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) { + $indices[] = ['value' => $nextToken]; + $lastToken = $nextToken; + } + + if ($tokens[$nextToken]['code'] === T_ARRAY) { + $nextToken = $tokens[$tokens[$nextToken]['parenthesis_opener']]['parenthesis_closer']; + } else if ($tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY) { + $nextToken = $tokens[$nextToken]['bracket_closer']; + } else { + // T_CLOSURE. + $nextToken = $tokens[$nextToken]['scope_closer']; + } + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_COMMA) { + $nextToken--; + } else { + $lastToken = $nextToken; + } + + continue; + }//end if + + if ($tokens[$nextToken]['code'] !== T_DOUBLE_ARROW && $tokens[$nextToken]['code'] !== T_COMMA) { + continue; + } + + $currentEntry = []; + + if ($tokens[$nextToken]['code'] === T_COMMA) { + $stackPtrCount = 0; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']); + } + + $commaCount = 0; + if (isset($tokens[$nextToken]['nested_parenthesis']) === true) { + $commaCount = count($tokens[$nextToken]['nested_parenthesis']); + if ($tokens[$stackPtr]['code'] === T_ARRAY) { + // Remove parenthesis that are used to define the array. + $commaCount--; + } + } + + if ($commaCount > $stackPtrCount) { + // This comma is inside more parenthesis than the ARRAY keyword, + // then there it is actually a comma used to separate arguments + // in a function call. + continue; + } + + if ($keyUsed === true && $tokens[$lastToken]['code'] === T_COMMA) { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($lastToken + 1), null, true); + // Allow for PHP 7.4+ array unpacking within an array declaration. + if ($tokens[$nextToken]['code'] !== T_ELLIPSIS) { + $error = 'No key specified for array entry; first entry specifies key'; + $phpcsFile->addError($error, $nextToken, 'NoKeySpecified'); + return; + } + } + + if ($keyUsed === false) { + if ($tokens[($nextToken - 1)]['code'] === T_WHITESPACE) { + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextToken - 1), null, true); + if (($tokens[$prev]['code'] !== T_END_HEREDOC + && $tokens[$prev]['code'] !== T_END_NOWDOC) + || $tokens[($nextToken - 1)]['line'] === $tokens[$nextToken]['line'] + ) { + if ($tokens[($nextToken - 1)]['content'] === $phpcsFile->eolChar) { + $spaceLength = 'newline'; + } else { + $spaceLength = $tokens[($nextToken - 1)]['length']; + } + + $error = 'Expected 0 spaces before comma; %s found'; + $data = [$spaceLength]; + + // The error is only fixable if there is only whitespace between the tokens. + if ($prev === $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), null, true)) { + $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextToken - 1), ''); + } + } else { + $phpcsFile->addError($error, $nextToken, 'SpaceBeforeComma', $data); + } + } + }//end if + + $valueContent = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($lastToken + 1), + $nextToken, + true + ); + + $indices[] = ['value' => $valueContent]; + $usesArrayUnpacking = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($nextToken - 2), + null, + true + ); + if ($tokens[$usesArrayUnpacking]['code'] !== T_ELLIPSIS) { + // Don't decide if an array is key => value indexed or not when PHP 7.4+ array unpacking is used. + $singleUsed = true; + } + }//end if + + $lastToken = $nextToken; + continue; + }//end if + + if ($tokens[$nextToken]['code'] === T_DOUBLE_ARROW) { + if ($singleUsed === true) { + $error = 'Key specified for array entry; first entry has no key'; + $phpcsFile->addError($error, $nextToken, 'KeySpecified'); + return; + } + + $currentEntry['arrow'] = $nextToken; + $keyUsed = true; + + // Find the start of index that uses this double arrow. + $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), $arrayStart, true); + $indexStart = $phpcsFile->findStartOfStatement($indexEnd); + + if ($indexStart === $indexEnd) { + $currentEntry['index'] = $indexEnd; + $currentEntry['index_content'] = $tokens[$indexEnd]['content']; + $currentEntry['index_length'] = $tokens[$indexEnd]['length']; + } else { + $currentEntry['index'] = $indexStart; + $currentEntry['index_content'] = ''; + $currentEntry['index_length'] = 0; + for ($i = $indexStart; $i <= $indexEnd; $i++) { + $currentEntry['index_content'] .= $tokens[$i]['content']; + $currentEntry['index_length'] += $tokens[$i]['length']; + } + } + + if ($maxLength < $currentEntry['index_length']) { + $maxLength = $currentEntry['index_length']; + } + + // Find the value of this index. + $nextContent = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($nextToken + 1), + $arrayEnd, + true + ); + + $currentEntry['value'] = $nextContent; + $indices[] = $currentEntry; + $lastToken = $nextToken; + }//end if + }//end for + + // Check for multi-line arrays that should be single-line. + $singleValue = false; + + if (empty($indices) === true) { + $singleValue = true; + } else if (count($indices) === 1 && $tokens[$lastToken]['code'] === T_COMMA) { + // There may be another array value without a comma. + $exclude = Tokens::$emptyTokens; + $exclude[] = T_COMMA; + $nextContent = $phpcsFile->findNext($exclude, ($indices[0]['value'] + 1), $arrayEnd, true); + if ($nextContent === false) { + $singleValue = true; + } + } + + if ($singleValue === true) { + // Before we complain, make sure the single value isn't a here/nowdoc. + $next = $phpcsFile->findNext(Tokens::$heredocTokens, ($arrayStart + 1), ($arrayEnd - 1)); + if ($next === false) { + // Array cannot be empty, so this is a multi-line array with + // a single value. It should be defined on single line. + $error = 'Multi-line array contains a single value; use single-line array instead'; + $errorCode = 'MultiLineNotAllowed'; + + $find = Tokens::$phpcsCommentTokens; + $find[] = T_COMMENT; + $comment = $phpcsFile->findNext($find, ($arrayStart + 1), $arrayEnd); + if ($comment === false) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode); + } else { + $fix = false; + $phpcsFile->addError($error, $stackPtr, $errorCode); + } + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + for ($i = ($arrayEnd - 1); $i > $arrayStart; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + }//end if + + /* + This section checks for arrays that don't specify keys. + + Arrays such as: + array( + 'aaa', + 'bbb', + 'd', + ); + */ + + if ($keyUsed === false && empty($indices) === false) { + $count = count($indices); + $lastIndex = $indices[($count - 1)]['value']; + + $trailingContent = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($arrayEnd - 1), + $lastIndex, + true + ); + + if ($tokens[$trailingContent]['code'] !== T_COMMA) { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no'); + $error = 'Comma required after last value in array declaration'; + $fix = $phpcsFile->addFixableError($error, $trailingContent, 'NoCommaAfterLast'); + if ($fix === true) { + $phpcsFile->fixer->addContent($trailingContent, ','); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes'); + } + + foreach ($indices as $valuePosition => $value) { + if (empty($value['value']) === true) { + // Array was malformed and we couldn't figure out + // the array value correctly, so we have to ignore it. + // Other parts of this sniff will correct the error. + continue; + } + + $valuePointer = $value['value']; + + $ignoreTokens = [ + T_WHITESPACE => T_WHITESPACE, + T_COMMA => T_COMMA, + ]; + $ignoreTokens += Tokens::$castTokens; + + if ($tokens[$valuePointer]['code'] === T_CLOSURE + || $tokens[$valuePointer]['code'] === T_FN + ) { + // Check if the closure is static, if it is, override the value pointer as indices before skip static. + $staticPointer = $phpcsFile->findPrevious($ignoreTokens, ($valuePointer - 1), ($arrayStart + 1), true); + if ($staticPointer !== false && $tokens[$staticPointer]['code'] === T_STATIC) { + $valuePointer = $staticPointer; + } + } + + $previous = $phpcsFile->findPrevious($ignoreTokens, ($valuePointer - 1), ($arrayStart + 1), true); + if ($previous === false) { + $previous = $stackPtr; + } + + $previousIsWhitespace = $tokens[($valuePointer - 1)]['code'] === T_WHITESPACE; + if ($tokens[$previous]['line'] === $tokens[$valuePointer]['line']) { + $error = 'Each value in a multi-line array must be on a new line'; + if ($valuePosition === 0) { + $error = 'The first value in a multi-value array must be on a new line'; + } + + $fix = $phpcsFile->addFixableError($error, $valuePointer, 'ValueNoNewline'); + if ($fix === true) { + if ($previousIsWhitespace === true) { + $phpcsFile->fixer->replaceToken(($valuePointer - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($valuePointer); + } + } + } else if ($previousIsWhitespace === true) { + $expected = $keywordStart; + + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $valuePointer, true); + $found = ($tokens[$first]['column'] - 1); + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + if ($found !== $expected) { + $error = 'Array value not aligned correctly; expected %s space%s but found %s'; + $data = [ + $expected, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $first, 'ValueNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($first - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($first - 1), str_repeat(' ', $expected)); + } + } + } + }//end if + }//end foreach + }//end if + + /* + Below the actual indentation of the array is checked. + Errors will be thrown when a key is not aligned, when + a double arrow is not aligned, and when a value is not + aligned correctly. + If an error is found in one of the above areas, then errors + are not reported for the rest of the line to avoid reporting + spaces and columns incorrectly. Often fixing the first + problem will fix the other 2 anyway. + + For example: + + $a = array( + 'index' => '2', + ); + + or + + $a = [ + 'index' => '2', + ]; + + In this array, the double arrow is indented too far, but this + will also cause an error in the value's alignment. If the arrow were + to be moved back one space however, then both errors would be fixed. + */ + + $indicesStart = ($keywordStart + 1); + foreach ($indices as $valuePosition => $index) { + $valuePointer = $index['value']; + if ($valuePointer === false) { + // Syntax error or live coding. + continue; + } + + if (isset($index['index']) === false) { + // Array value only. + continue; + } + + $indexPointer = $index['index']; + $indexLine = $tokens[$indexPointer]['line']; + + $previous = $phpcsFile->findPrevious([T_WHITESPACE, T_COMMA], ($indexPointer - 1), ($arrayStart + 1), true); + if ($previous === false) { + $previous = $stackPtr; + } + + if ($tokens[$previous]['line'] === $indexLine) { + $error = 'Each index in a multi-line array must be on a new line'; + if ($valuePosition === 0) { + $error = 'The first index in a multi-value array must be on a new line'; + } + + $fix = $phpcsFile->addFixableError($error, $indexPointer, 'IndexNoNewline'); + if ($fix === true) { + if ($tokens[($indexPointer - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($indexPointer - 1), $phpcsFile->eolChar); + } else { + $phpcsFile->fixer->addNewlineBefore($indexPointer); + } + } + + continue; + } + + if ($tokens[$indexPointer]['column'] !== $indicesStart && ($indexPointer - 1) !== $arrayStart) { + $expected = ($indicesStart - 1); + $found = ($tokens[$indexPointer]['column'] - 1); + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + $error = 'Array key not aligned correctly; expected %s space%s but found %s'; + $data = [ + $expected, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $indexPointer, 'KeyNotAligned', $data); + if ($fix === true) { + if ($found === 0 || $tokens[($indexPointer - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent(($indexPointer - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($indexPointer - 1), str_repeat(' ', $expected)); + } + } + }//end if + + $arrowStart = ($tokens[$indexPointer]['column'] + $maxLength + 1); + if ($tokens[$index['arrow']]['column'] !== $arrowStart) { + $expected = ($arrowStart - ($index['index_length'] + $tokens[$indexPointer]['column'])); + $found = ($tokens[$index['arrow']]['column'] - ($index['index_length'] + $tokens[$indexPointer]['column'])); + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + $error = 'Array double arrow not aligned correctly; expected %s space%s but found %s'; + $data = [ + $expected, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'DoubleArrowNotAligned', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent(($index['arrow'] - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($index['arrow'] - 1), str_repeat(' ', $expected)); + } + } + + continue; + }//end if + + $valueStart = ($arrowStart + 3); + if ($tokens[$valuePointer]['column'] !== $valueStart) { + $expected = ($valueStart - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column'])); + $found = ($tokens[$valuePointer]['column'] - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column'])); + if ($found < 0) { + $found = 'newline'; + } + + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + $error = 'Array value not aligned correctly; expected %s space%s but found %s'; + $data = [ + $expected, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'ValueNotAligned', $data); + if ($fix === true) { + if ($found === 'newline') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($valuePointer - 1), null, true); + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $valuePointer; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken(($valuePointer - 1), str_repeat(' ', $expected)); + $phpcsFile->fixer->endChangeset(); + } else if ($found === 0) { + $phpcsFile->fixer->addContent(($valuePointer - 1), str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($valuePointer - 1), str_repeat(' ', $expected)); + } + } + }//end if + + // Check each line ends in a comma. + $valueStart = $valuePointer; + $nextComma = false; + + $end = $phpcsFile->findEndOfStatement($valueStart); + if ($end === false) { + $valueEnd = $valueStart; + } else if ($tokens[$end]['code'] === T_COMMA) { + $valueEnd = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($end - 1), $valueStart, true); + $nextComma = $end; + } else { + $valueEnd = $end; + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $arrayEnd, true); + if ($next !== false && $tokens[$next]['code'] === T_COMMA) { + $nextComma = $next; + } + } + + $valueLine = $tokens[$valueEnd]['line']; + if ($tokens[$valueEnd]['code'] === T_END_HEREDOC || $tokens[$valueEnd]['code'] === T_END_NOWDOC) { + $valueLine++; + } + + if ($nextComma === false || ($tokens[$nextComma]['line'] !== $valueLine)) { + $error = 'Each line in an array declaration must end in a comma'; + $fix = $phpcsFile->addFixableError($error, $valuePointer, 'NoComma'); + + if ($fix === true) { + // Find the end of the line and put a comma there. + for ($i = ($valuePointer + 1); $i <= $arrayEnd; $i++) { + if ($tokens[$i]['line'] > $valueLine) { + break; + } + } + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore(($i - 1), ','); + if ($nextComma !== false) { + $phpcsFile->fixer->replaceToken($nextComma, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + // Check that there is no space before the comma. + if ($nextComma !== false && $tokens[($nextComma - 1)]['code'] === T_WHITESPACE) { + // Here/nowdoc closing tags must have the comma on the next line. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextComma - 1), null, true); + if ($tokens[$prev]['code'] !== T_END_HEREDOC && $tokens[$prev]['code'] !== T_END_NOWDOC) { + $content = $tokens[($nextComma - 2)]['content']; + $spaceLength = $tokens[($nextComma - 1)]['length']; + $error = 'Expected 0 spaces between "%s" and comma; %s found'; + $data = [ + $content, + $spaceLength, + ]; + + $fix = $phpcsFile->addFixableError($error, $nextComma, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($nextComma - 1), ''); + } + } + } + }//end foreach + + }//end processMultiLineArray() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php new file mode 100644 index 000000000..384a8f2b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php @@ -0,0 +1,136 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionClosingBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_CLOSE_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $stackPtr; + while (true) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true); + if ($next === false) { + return; + } + + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$stackPtr]['line'] + ) { + // Trailing comment. + continue; + } + + break; + } + + if ($tokens[$next]['code'] !== T_CLOSE_TAG) { + $found = (($tokens[$next]['line'] - $tokens[$stackPtr]['line']) - 1); + if ($found !== 1) { + $error = 'Expected one blank line after closing brace of class definition; %s found'; + $data = [max(0, $found)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterClose', $data); + + if ($fix === true) { + $firstOnLine = $next; + while ($tokens[$firstOnLine]['column'] !== 1) { + --$firstOnLine; + } + + if ($found < 0) { + // Next statement on same line as the closing brace. + $phpcsFile->fixer->addContentBefore($next, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($found === 0) { + // Next statement on next line, no blank line. + $phpcsFile->fixer->addContentBefore($firstOnLine, $phpcsFile->eolChar); + } else { + // Too many blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($firstOnLine - 1); $i > $stackPtr; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($firstOnLine, $phpcsFile->eolChar.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + // Ignore nested style definitions from here on. The spacing before the closing brace + // (a single blank line) will be enforced by the above check, which ensures there is a + // blank line after the last nested class. + $found = $phpcsFile->findPrevious( + T_CLOSE_CURLY_BRACKET, + ($stackPtr - 1), + $tokens[$stackPtr]['bracket_opener'] + ); + + if ($found !== false) { + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($prev === false) { + return; + } + + if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Closing brace of class definition must be on new line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($stackPtr); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php new file mode 100644 index 000000000..796bbbaa1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php @@ -0,0 +1,113 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionNameSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Do not check nested style definitions as, for example, in @media style rules. + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); + if ($nested !== false) { + return; + } + + // Find the first blank line before this opening brace, unless we get + // to another style definition, comment or the start of the file. + $endTokens = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_OPEN_TAG => T_OPEN_TAG, + ]; + $endTokens += Tokens::$commentTokens; + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + $foundContent = false; + $currentLine = $tokens[$prev]['line']; + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if (isset($endTokens[$tokens[$i]['code']]) === true) { + break; + } + + if ($tokens[$i]['line'] === $currentLine) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + $foundContent = true; + } + + continue; + } + + // We changed lines. + if ($foundContent === false) { + // Before we throw an error, make sure we are not looking + // at a gap before the style definition. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, $i, null, true); + if ($prev !== false + && isset($endTokens[$tokens[$prev]['code']]) === false + ) { + $error = 'Blank lines are not allowed between class names'; + $phpcsFile->addError($error, ($i + 1), 'BlankLinesFound'); + } + + break; + } + + $foundContent = false; + $currentLine = $tokens[$i]['line']; + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php new file mode 100644 index 000000000..7750fa1de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php @@ -0,0 +1,178 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDefinitionOpeningBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($prevNonWhitespace !== false) { + $length = 0; + if ($tokens[$stackPtr]['line'] !== $tokens[$prevNonWhitespace]['line']) { + $length = 'newline'; + } else if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($stackPtr - 1)]['content'], "\t") !== false) { + $length = 'tab'; + } else { + $length = $tokens[($stackPtr - 1)]['length']; + } + } + + if ($length === 0) { + $error = 'Expected 1 space before opening brace of class definition; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoneBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } else if ($length !== 1) { + $error = 'Expected 1 space before opening brace of class definition; %s found'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr - 1); $i > $prevNonWhitespace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + if ($tokens[$nextNonEmpty]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening brace should be the last content on the line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBefore'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($stackPtr); + + // Remove potentially left over trailing whitespace. + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Check for nested class definitions. + $found = $phpcsFile->findNext( + T_OPEN_CURLY_BRACKET, + ($stackPtr + 1), + $tokens[$stackPtr]['bracket_closer'] + ); + + if ($found === false) { + // Not nested. + return; + } + + $lastOnLine = $stackPtr; + for ($lastOnLine; $lastOnLine < $tokens[$stackPtr]['bracket_closer']; $lastOnLine++) { + if ($tokens[$lastOnLine]['line'] !== $tokens[($lastOnLine + 1)]['line']) { + break; + } + } + + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($lastOnLine + 1), null, true); + if ($nextNonWhiteSpace === false) { + return; + } + + $foundLines = ($tokens[$nextNonWhiteSpace]['line'] - $tokens[$stackPtr]['line'] - 1); + if ($foundLines !== 1) { + $error = 'Expected 1 blank line after opening brace of nesting class definition; %s found'; + $data = [max(0, $foundLines)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AfterNesting', $data); + + if ($fix === true) { + $firstOnNextLine = $nextNonWhiteSpace; + while ($tokens[$firstOnNextLine]['column'] !== 1) { + --$firstOnNextLine; + } + + if ($found < 0) { + // First statement on same line as the opening brace. + $phpcsFile->fixer->addContentBefore($nextNonWhiteSpace, $phpcsFile->eolChar.$phpcsFile->eolChar); + } else if ($found === 0) { + // Next statement on next line, no blank line. + $phpcsFile->fixer->addNewlineBefore($firstOnNextLine); + } else { + // Too many blank lines. + $phpcsFile->fixer->beginChangeset(); + for ($i = ($firstOnNextLine - 1); $i > $stackPtr; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContentBefore($firstOnNextLine, $phpcsFile->eolChar.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php new file mode 100644 index 000000000..6459e035c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php @@ -0,0 +1,109 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ColonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_COLON]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] !== T_STYLE) { + // The colon is not part of a style definition. + return; + } + + if ($tokens[$prev]['content'] === 'progid') { + // Special case for IE filters. + return; + } + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $error = 'There must be no space before a colon in a style definition'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['code'] === T_STYLE) { + // Empty style definition, ignore it. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after colon in style definition; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoneAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else { + $content = $tokens[($stackPtr + 1)]['content']; + if (strpos($content, $phpcsFile->eolChar) === false) { + $length = strlen($content); + if ($length !== 1) { + $error = 'Expected 1 space after colon in style definition; %s found'; + $data = [$length]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } else { + $error = 'Expected 1 space after colon in style definition; newline found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'AfterNewline'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php new file mode 100644 index 000000000..5114a0cb0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ColourDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_COLOUR]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $colour = $tokens[$stackPtr]['content']; + + $expected = strtoupper($colour); + if ($colour !== $expected) { + $error = 'CSS colours must be defined in uppercase; expected %s but found %s'; + $data = [ + $expected, + $colour, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotUpper', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + // Now check if shorthand can be used. + if (strlen($colour) !== 7) { + return; + } + + if ($colour[1] === $colour[2] && $colour[3] === $colour[4] && $colour[5] === $colour[6]) { + $expected = '#'.$colour[1].$colour[3].$colour[5]; + $error = 'CSS colours must use shorthand if available; expected %s but found %s'; + $data = [ + $expected, + $colour, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Shorthand', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php new file mode 100644 index 000000000..72448a30b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowMultipleStyleDefinitionsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var string[] + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(T_STYLE, ($stackPtr + 1)); + if ($next === false) { + return; + } + + if ($tokens[$next]['content'] === 'progid') { + // Special case for IE filters. + return; + } + + if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Each style definition must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $next, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($next); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php new file mode 100644 index 000000000..82a974c8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php @@ -0,0 +1,118 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DuplicateClassDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Find the content of each class definition name. + $classNames = []; + $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1)); + if ($next === false) { + // No class definitions in the file. + return; + } + + // Save the class names in a "scope", + // to prevent false positives with @media blocks. + $scope = 'main'; + + $find = [ + T_CLOSE_CURLY_BRACKET, + T_OPEN_CURLY_BRACKET, + T_OPEN_TAG, + ]; + + while ($next !== false) { + $prev = $phpcsFile->findPrevious($find, ($next - 1)); + + // Check if an inner block was closed. + $beforePrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($beforePrev !== false + && $tokens[$beforePrev]['code'] === T_CLOSE_CURLY_BRACKET + ) { + $scope = 'main'; + } + + // Create a sorted name for the class so we can compare classes + // even when the individual names are all over the place. + $name = ''; + for ($i = ($prev + 1); $i < $next; $i++) { + $name .= $tokens[$i]['content']; + } + + $name = trim($name); + $name = str_replace("\n", ' ', $name); + $name = preg_replace('|[\s]+|', ' ', $name); + $name = preg_replace('|\s*/\*.*\*/\s*|', '', $name); + $name = str_replace(', ', ',', $name); + + $names = explode(',', $name); + sort($names); + $name = implode(',', $names); + + if ($name[0] === '@') { + // Media block has its own "scope". + $scope = $name; + } else if (isset($classNames[$scope][$name]) === true) { + $first = $classNames[$scope][$name]; + $error = 'Duplicate class definition found; first defined on line %s'; + $data = [$tokens[$first]['line']]; + $phpcsFile->addError($error, $next, 'Found', $data); + } else { + $classNames[$scope][$name] = $next; + } + + $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($next + 1)); + }//end while + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php new file mode 100644 index 000000000..e9221470e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicateStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + // Find the content of each style definition name. + $styleNames = []; + + $next = $stackPtr; + $end = $tokens[$stackPtr]['bracket_closer']; + + do { + $next = $phpcsFile->findNext([T_STYLE, T_OPEN_CURLY_BRACKET], ($next + 1), $end); + if ($next === false) { + // Class definition is empty. + break; + } + + if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) { + $next = $tokens[$next]['bracket_closer']; + continue; + } + + $name = $tokens[$next]['content']; + if (isset($styleNames[$name]) === true) { + $first = $styleNames[$name]; + $error = 'Duplicate style definition found; first defined on line %s'; + $data = [$tokens[$first]['line']]; + $phpcsFile->addError($error, $next, 'Found', $data); + } else { + $styleNames[$name] = $next; + } + } while ($next !== false); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php new file mode 100644 index 000000000..b7671d3e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyClassDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($next === false || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + $error = 'Class definition is empty'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php new file mode 100644 index 000000000..cc3007f2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmptyStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_COLON; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Style definition is empty'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php new file mode 100644 index 000000000..982f46970 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php @@ -0,0 +1,179 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ForbiddenStylesSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of forbidden styles with their alternatives. + * + * The value is NULL if no alternative exists. i.e., the + * style should just not be used. + * + * @var array + */ + protected $forbiddenStyles = [ + '-moz-border-radius' => 'border-radius', + '-webkit-border-radius' => 'border-radius', + '-moz-border-radius-topleft' => 'border-top-left-radius', + '-moz-border-radius-topright' => 'border-top-right-radius', + '-moz-border-radius-bottomright' => 'border-bottom-right-radius', + '-moz-border-radius-bottomleft' => 'border-bottom-left-radius', + '-moz-box-shadow' => 'box-shadow', + '-webkit-box-shadow' => 'box-shadow', + ]; + + /** + * A cache of forbidden style names, for faster lookups. + * + * @var string[] + */ + protected $forbiddenStyleNames = []; + + /** + * If true, forbidden styles will be considered regular expressions. + * + * @var boolean + */ + protected $patternMatch = false; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = true; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $this->forbiddenStyleNames = array_keys($this->forbiddenStyles); + + if ($this->patternMatch === true) { + foreach ($this->forbiddenStyleNames as $i => $name) { + $this->forbiddenStyleNames[$i] = '/'.$name.'/i'; + } + } + + return [T_STYLE]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $style = strtolower($tokens[$stackPtr]['content']); + $pattern = null; + + if ($this->patternMatch === true) { + $count = 0; + $pattern = preg_replace( + $this->forbiddenStyleNames, + $this->forbiddenStyleNames, + $style, + 1, + $count + ); + + if ($count === 0) { + return; + } + + // Remove the pattern delimiters and modifier. + $pattern = substr($pattern, 1, -2); + } else { + if (in_array($style, $this->forbiddenStyleNames, true) === false) { + return; + } + }//end if + + $this->addError($phpcsFile, $stackPtr, $style, $pattern); + + }//end process() + + + /** + * Generates the error or warning for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden style + * in the token array. + * @param string $style The name of the forbidden style. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError($phpcsFile, $stackPtr, $style, $pattern=null) + { + $data = [$style]; + $error = 'The use of style %s is '; + if ($this->error === true) { + $type = 'Found'; + $error .= 'forbidden'; + } else { + $type = 'Discouraged'; + $error .= 'discouraged'; + } + + if ($pattern === null) { + $pattern = $style; + } + + if ($this->forbiddenStyles[$pattern] !== null) { + $data[] = $this->forbiddenStyles[$pattern]; + if ($this->error === true) { + $fix = $phpcsFile->addFixableError($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); + } else { + $fix = $phpcsFile->addFixableWarning($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); + } + + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $this->forbiddenStyles[$pattern]); + } + } else { + if ($this->error === true) { + $phpcsFile->addError($error, $stackPtr, $type, $data); + } else { + $phpcsFile->addWarning($error, $stackPtr, $type, $data); + } + } + + }//end addError() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php new file mode 100644 index 000000000..56406ccb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/IndentationSniff.php @@ -0,0 +1,152 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IndentationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $numTokens = (count($tokens) - 2); + $indentLevel = 0; + $nestingLevel = 0; + for ($i = 1; $i < $numTokens; $i++) { + if ($tokens[$i]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true + ) { + // Don't check the indent of comments. + continue; + } + + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + $indentLevel++; + + if (isset($tokens[$i]['bracket_closer']) === false) { + // Syntax error or live coding. + // Anything after this would receive incorrect fixes, so bow out. + return; + } + + // Check for nested class definitions. + $found = $phpcsFile->findNext( + T_OPEN_CURLY_BRACKET, + ($i + 1), + $tokens[$i]['bracket_closer'] + ); + + if ($found !== false) { + $nestingLevel = $indentLevel; + } + } + + if (($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$i]['line'] !== $tokens[($i - 1)]['line']) + || ($tokens[($i + 1)]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$i]['line'] === $tokens[($i + 1)]['line']) + ) { + $indentLevel--; + if ($indentLevel === 0) { + $nestingLevel = 0; + } + } + + if ($tokens[$i]['column'] !== 1 + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + || $tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + ) { + continue; + } + + // We started a new line, so check indent. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $content = str_replace($phpcsFile->eolChar, '', $tokens[$i]['content']); + $foundIndent = strlen($content); + } else { + $foundIndent = 0; + } + + $expectedIndent = ($indentLevel * $this->indent); + if ($expectedIndent > 0 + && strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false + ) { + if ($nestingLevel !== $indentLevel) { + $error = 'Blank lines are not allowed in class definitions'; + $fix = $phpcsFile->addFixableError($error, $i, 'BlankLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else if ($foundIndent !== $expectedIndent) { + $error = 'Line indented incorrectly; expected %s spaces, found %s'; + $data = [ + $expectedIndent, + $foundIndent, + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'Incorrect', $data); + if ($fix === true) { + $indent = str_repeat(' ', $expectedIndent); + if ($foundIndent === 0) { + $phpcsFile->fixer->addContentBefore($i, $indent); + } else { + $phpcsFile->fixer->replaceToken($i, $indent); + } + } + }//end if + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php new file mode 100644 index 000000000..c8393c51c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php @@ -0,0 +1,99 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercaseStyleDefinitionSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $start = ($stackPtr + 1); + $end = ($tokens[$stackPtr]['bracket_closer'] - 1); + $inStyle = null; + + for ($i = $start; $i <= $end; $i++) { + // Skip nested definitions as they are checked individually. + if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if ($tokens[$i]['code'] === T_STYLE) { + $inStyle = $tokens[$i]['content']; + } + + if ($tokens[$i]['code'] === T_SEMICOLON) { + $inStyle = null; + } + + if ($inStyle === 'progid') { + // Special case for IE filters. + continue; + } + + if ($tokens[$i]['code'] === T_STYLE + || ($inStyle !== null + && $tokens[$i]['code'] === T_STRING) + ) { + $expected = strtolower($tokens[$i]['content']); + if ($expected !== $tokens[$i]['content']) { + $error = 'Style definitions must be lowercase; expected %s but found %s'; + $data = [ + $expected, + $tokens[$i]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $i, 'FoundUpper', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($i, $expected); + } + } + } + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php new file mode 100644 index 000000000..83f2a6c82 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php @@ -0,0 +1,93 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class MissingColonSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['bracket_closer']) === false) { + // Syntax error or live coding, bow out. + return; + } + + $lastLine = $tokens[$stackPtr]['line']; + $end = $tokens[$stackPtr]['bracket_closer']; + + // Do not check nested style definitions as, for example, in @media style rules. + $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $end); + if ($nested !== false) { + return; + } + + $foundColon = false; + $foundString = false; + for ($i = ($stackPtr + 1); $i <= $end; $i++) { + if ($tokens[$i]['line'] !== $lastLine) { + // We changed lines. + if ($foundColon === false && $foundString !== false) { + // We didn't find a colon on the previous line. + $error = 'No style definition found on line; check for missing colon'; + $phpcsFile->addError($error, $foundString, 'Found'); + } + + $foundColon = false; + $foundString = false; + $lastLine = $tokens[$i]['line']; + } + + if ($tokens[$i]['code'] === T_STRING) { + $foundString = $i; + } else if ($tokens[$i]['code'] === T_COLON) { + $foundColon = $i; + } + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php new file mode 100644 index 000000000..586b4730a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php @@ -0,0 +1,95 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class NamedColoursSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of named colours. + * + * This is the list of standard colours defined in the CSS specification. + * + * @var array + */ + protected $colourNames = [ + 'aqua' => 'aqua', + 'black' => 'black', + 'blue' => 'blue', + 'fuchsia' => 'fuchsia', + 'gray' => 'gray', + 'green' => 'green', + 'lime' => 'lime', + 'maroon' => 'maroon', + 'navy' => 'navy', + 'olive' => 'olive', + 'orange' => 'orange', + 'purple' => 'purple', + 'red' => 'red', + 'silver' => 'silver', + 'teal' => 'teal', + 'white' => 'white', + 'yellow' => 'yellow', + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr - 1)]['code'] === T_HASH + || $tokens[($stackPtr - 1)]['code'] === T_STRING_CONCAT + ) { + // Class name. + return; + } + + if (isset($this->colourNames[strtolower($tokens[$stackPtr]['content'])]) === true) { + $error = 'Named colours are forbidden; use hex, rgb, or rgba values instead'; + $phpcsFile->addError($error, $stackPtr, 'Forbidden'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php new file mode 100644 index 000000000..0c1c553a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/OpacitySniff.php @@ -0,0 +1,103 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OpacitySniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['content'] !== 'opacity') { + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_COLON; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + + if ($next === false + || ($tokens[$next]['code'] !== T_DNUMBER + && $tokens[$next]['code'] !== T_LNUMBER) + ) { + return; + } + + $value = $tokens[$next]['content']; + if ($tokens[$next]['code'] === T_LNUMBER) { + if ($value !== '0' && $value !== '1') { + $error = 'Opacity values must be between 0 and 1'; + $phpcsFile->addError($error, $next, 'Invalid'); + } + } else { + if (strlen($value) > 3) { + $error = 'Opacity values must have a single value after the decimal point'; + $phpcsFile->addError($error, $next, 'DecimalPrecision'); + } else if ($value === '0.0' || $value === '1.0') { + $error = 'Opacity value does not require decimal point; use %s instead'; + $data = [$value[0]]; + $fix = $phpcsFile->addFixableError($error, $next, 'PointNotRequired', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, $value[0]); + } + } else if ($value[0] === '.') { + $error = 'Opacity values must not start with a decimal point; use 0%s instead'; + $data = [$value]; + $fix = $phpcsFile->addFixableError($error, $next, 'StartWithPoint', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($next, '0'.$value); + } + } else if ($value[0] !== '0') { + $error = 'Opacity values must be between 0 and 1'; + $phpcsFile->addError($error, $next, 'Invalid'); + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php new file mode 100644 index 000000000..9030468b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SemicolonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextStatement = $phpcsFile->findNext([T_STYLE, T_CLOSE_CURLY_BRACKET], ($stackPtr + 1)); + if ($nextStatement === false) { + return; + } + + $ignore = Tokens::$emptyTokens; + if ($tokens[$nextStatement]['code'] === T_STYLE) { + // Allow for star-prefix hack. + $ignore[] = T_MULTIPLY; + } + + $endOfThisStatement = $phpcsFile->findPrevious($ignore, ($nextStatement - 1), null, true); + if ($tokens[$endOfThisStatement]['code'] !== T_SEMICOLON) { + $error = 'Style definitions must end with a semicolon'; + $phpcsFile->addError($error, $endOfThisStatement, 'NotAtEnd'); + return; + } + + if ($tokens[($endOfThisStatement - 1)]['code'] !== T_WHITESPACE) { + return; + } + + // There is a semicolon, so now find the last token in the statement. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($endOfThisStatement - 1), null, true); + $found = $tokens[($endOfThisStatement - 1)]['length']; + if ($tokens[$prevNonEmpty]['line'] !== $tokens[$endOfThisStatement]['line']) { + $found = 'newline'; + } + + $error = 'Expected 0 spaces before semicolon in style definition; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $prevNonEmpty, 'SpaceFound', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent($prevNonEmpty, ';'); + $phpcsFile->fixer->replaceToken($endOfThisStatement, ''); + + for ($i = ($endOfThisStatement - 1); $i > $prevNonEmpty; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php new file mode 100644 index 000000000..76e7330c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php @@ -0,0 +1,183 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ShorthandSizeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['CSS']; + + /** + * A list of styles that we shouldn't check. + * + * These have values that looks like sizes, but are not. + * + * @var array + */ + protected $excludeStyles = [ + 'background-position' => 'background-position', + 'box-shadow' => 'box-shadow', + 'transform-origin' => 'transform-origin', + '-webkit-transform-origin' => '-webkit-transform-origin', + '-ms-transform-origin' => '-ms-transform-origin', + ]; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_STYLE]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Some styles look like shorthand but are not actually a set of 4 sizes. + $style = strtolower($tokens[$stackPtr]['content']); + if (isset($this->excludeStyles[$style]) === true) { + return; + } + + $end = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1)); + if ($end === false) { + // Live coding or parse error. + return; + } + + // Get the whole style content. + $origContent = $phpcsFile->getTokensAsString(($stackPtr + 1), ($end - $stackPtr - 1)); + $origContent = trim($origContent, ':'); + $origContent = trim($origContent); + + // Account for a !important annotation. + $content = $origContent; + if (substr($content, -10) === '!important') { + $content = substr($content, 0, -10); + $content = trim($content); + } + + // Check if this style value is a set of numbers with optional prefixes. + $content = preg_replace('/\s+/', ' ', $content); + $values = []; + $num = preg_match_all( + '/(?:[0-9]+)(?:[a-zA-Z]{2}\s+|%\s+|\s+)/', + $content.' ', + $values, + PREG_SET_ORDER + ); + + // Only interested in styles that have multiple sizes defined. + if ($num < 2) { + return; + } + + // Rebuild the content we matched to ensure we got everything. + $matched = ''; + foreach ($values as $value) { + $matched .= $value[0]; + } + + if ($content !== trim($matched)) { + return; + } + + if ($num === 3) { + $expected = trim($content.' '.$values[1][0]); + $error = 'Shorthand syntax not allowed here; use %s instead'; + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if (substr($origContent, -10) === '!important') { + $expected .= ' !important'; + } + + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 2), null, true); + $phpcsFile->fixer->replaceToken($next, $expected); + for ($next++; $next < $end; $next++) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + }//end if + + if ($num === 2) { + if ($values[0][0] !== $values[1][0]) { + // Both values are different, so it is already shorthand. + return; + } + } else if ($values[0][0] !== $values[2][0] || $values[1][0] !== $values[3][0]) { + // Can't shorthand this. + return; + } + + if ($values[0][0] === $values[1][0]) { + // All values are the same. + $expected = trim($values[0][0]); + } else { + $expected = trim($values[0][0]).' '.trim($values[1][0]); + } + + $error = 'Size definitions must use shorthand if available; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotUsed', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if (substr($origContent, -10) === '!important') { + $expected .= ' !important'; + } + + $next = $phpcsFile->findNext(T_COLON, ($stackPtr + 1)); + $phpcsFile->fixer->addContent($next, ' '.$expected); + for ($next++; $next < $end; $next++) { + $phpcsFile->fixer->replaceToken($next, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php new file mode 100644 index 000000000..3f5e1fbc7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php @@ -0,0 +1,207 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff as PSR2ClassDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClassDeclarationSniff extends PSR2ClassDeclarationSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + // We want all the errors from the PSR2 standard, plus some of our own. + parent::process($phpcsFile, $stackPtr); + + // Check that this is the only class or interface in the file. + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE], ($stackPtr + 1)); + if ($nextClass !== false) { + // We have another, so an error is thrown. + $error = 'Only one interface or class is allowed in a file'; + $phpcsFile->addError($error, $nextClass, 'MultipleClasses'); + } + + }//end process() + + + /** + * Processes the opening section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processOpen(File $phpcsFile, $stackPtr) + { + parent::processOpen($phpcsFile, $stackPtr); + + $tokens = $phpcsFile->getTokens(); + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($stackPtr - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + + if ($tokens[($stackPtr - 2)]['code'] !== T_ABSTRACT + && $tokens[($stackPtr - 2)]['code'] !== T_FINAL + && $tokens[($stackPtr - 2)]['code'] !== T_READONLY + ) { + if ($spaces !== 0) { + $type = strtolower($tokens[$stackPtr]['content']); + $error = 'Expected 0 spaces before %s keyword; %s found'; + $data = [ + $type, + $spaces, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeKeyword', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + } + } + }//end if + }//end if + + }//end processOpen() + + + /** + * Processes the closing section of a class declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processClose(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + + // Check that the closing brace has one blank line after it. + for ($nextContent = ($closeBrace + 1); $nextContent < $phpcsFile->numTokens; $nextContent++) { + // Ignore comments on the same line as the brace. + if ($tokens[$nextContent]['line'] === $tokens[$closeBrace]['line'] + && ($tokens[$nextContent]['code'] === T_WHITESPACE + || $tokens[$nextContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$nextContent]['code']]) === true) + ) { + continue; + } + + if ($tokens[$nextContent]['code'] !== T_WHITESPACE) { + break; + } + } + + if ($nextContent === $phpcsFile->numTokens) { + // Ignore the line check as this is the very end of the file. + $difference = 1; + } else { + $difference = ($tokens[$nextContent]['line'] - $tokens[$closeBrace]['line'] - 1); + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), $stackPtr, true); + + if ($difference === -1 + || $tokens[$lastContent]['line'] === $tokens[$closeBrace]['line'] + ) { + $error = 'Closing %s brace must be on a line by itself'; + $data = [$tokens[$stackPtr]['content']]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'CloseBraceSameLine', $data); + if ($fix === true) { + if ($difference === -1) { + $phpcsFile->fixer->addNewlineBefore($nextContent); + } + + if ($tokens[$lastContent]['line'] === $tokens[$closeBrace]['line']) { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } + } else if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) { + $prevContent = $tokens[($closeBrace - 1)]['content']; + if ($prevContent !== $phpcsFile->eolChar) { + $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar)); + $spaces = strlen($blankSpace); + if ($spaces !== 0) { + if ($tokens[($closeBrace - 1)]['line'] !== $tokens[$closeBrace]['line']) { + $error = 'Expected 0 spaces before closing brace; newline found'; + $phpcsFile->addError($error, $closeBrace, 'NewLineBeforeCloseBrace'); + } else { + $error = 'Expected 0 spaces before closing brace; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closeBrace - 1), ''); + } + } + } + } + }//end if + + if ($difference !== -1 && $difference !== 1) { + if ($tokens[$nextContent]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$nextContent]['comment_closer'] + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_FUNCTION) { + return; + } + } + + $error = 'Closing brace of a %s must be followed by a single blank line; found %s'; + $data = [ + $tokens[$stackPtr]['content'], + $difference, + ]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'NewlinesAfterCloseBrace', $data); + if ($fix === true) { + if ($difference === 0) { + $first = $phpcsFile->findFirstOnLine([], $nextContent, true); + $phpcsFile->fixer->addNewlineBefore($first); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closeBrace + 1); $i < $nextContent; $i++) { + if ($tokens[$i]['line'] <= ($tokens[$closeBrace]['line'] + 1)) { + continue; + } else if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processClose() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php new file mode 100644 index 000000000..fc3ec0473 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php @@ -0,0 +1,70 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassFileNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $fullPath = basename($phpcsFile->getFilename()); + $fileName = substr($fullPath, 0, strrpos($fullPath, '.')); + if ($fileName === '') { + // No filename probably means STDIN, so we can't do this check. + return; + } + + $tokens = $phpcsFile->getTokens(); + $decName = $phpcsFile->findNext(T_STRING, $stackPtr); + + if ($tokens[$decName]['content'] !== $fileName) { + $error = '%s name doesn\'t match filename; expected "%s %s"'; + $data = [ + ucfirst($tokens[$stackPtr]['content']), + $tokens[$stackPtr]['content'], + $fileName, + ]; + $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php new file mode 100644 index 000000000..12d8a2456 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php @@ -0,0 +1,84 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DuplicatePropertySniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OBJECT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $properties = []; + $wantedTokens = [ + T_PROPERTY, + T_OBJECT, + ]; + + $next = $phpcsFile->findNext($wantedTokens, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']); + while ($next !== false && $next < $tokens[$stackPtr]['bracket_closer']) { + if ($tokens[$next]['code'] === T_OBJECT) { + // Skip nested objects. + $next = $tokens[$next]['bracket_closer']; + } else { + $propName = $tokens[$next]['content']; + if (isset($properties[$propName]) === true) { + $error = 'Duplicate property definition found for "%s"; previously defined on line %s'; + $data = [ + $propName, + $tokens[$properties[$propName]]['line'], + ]; + $phpcsFile->addError($error, $next, 'Found', $data); + } + + $properties[$propName] = $next; + }//end if + + $next = $phpcsFile->findNext($wantedTokens, ($next + 1), $tokens[$stackPtr]['bracket_closer']); + }//end while + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php new file mode 100644 index 000000000..b9d71db00 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercaseClassKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $targets = Tokens::$ooScopeTokens; + $targets[] = T_EXTENDS; + $targets[] = T_IMPLEMENTS; + $targets[] = T_ABSTRACT; + $targets[] = T_FINAL; + $targets[] = T_READONLY; + $targets[] = T_VAR; + $targets[] = T_CONST; + + return $targets; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php new file mode 100644 index 000000000..8ee4de45a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php @@ -0,0 +1,248 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class SelfMemberReferenceSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Classes_SelfMemberReferenceSniff. + */ + public function __construct() + { + parent::__construct([T_CLASS], [T_DOUBLE_COLON]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a double colon which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + $conditions = array_reverse($conditions, true); + foreach ($conditions as $conditionToken => $tokenCode) { + if ($tokenCode === T_CLASS || $tokenCode === T_ANON_CLASS || $tokenCode === T_CLOSURE) { + break; + } + } + + if ($conditionToken !== $currScope) { + return; + } + + $calledClassName = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($calledClassName === false) { + // Parse error. + return; + } + + if ($tokens[$calledClassName]['code'] === T_SELF) { + if ($tokens[$calledClassName]['content'] !== 'self') { + $error = 'Must use "self::" for local static member reference; found "%s::"'; + $data = [$tokens[$calledClassName]['content']]; + $fix = $phpcsFile->addFixableError($error, $calledClassName, 'IncorrectCase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($calledClassName, 'self'); + } + + return; + } + } else if ($tokens[$calledClassName]['code'] === T_STRING) { + // If the class is called with a namespace prefix, build fully qualified + // namespace calls for both current scope class and requested class. + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($calledClassName - 1), null, true); + if ($prevNonEmpty !== false && $tokens[$prevNonEmpty]['code'] === T_NS_SEPARATOR) { + $declarationName = $this->getDeclarationNameWithNamespace($tokens, $calledClassName); + $declarationName = ltrim($declarationName, '\\'); + $fullQualifiedClassName = $this->getNamespaceOfScope($phpcsFile, $currScope); + if ($fullQualifiedClassName === '\\') { + $fullQualifiedClassName = ''; + } else { + $fullQualifiedClassName .= '\\'; + } + + $fullQualifiedClassName .= $phpcsFile->getDeclarationName($currScope); + } else { + $declarationName = $phpcsFile->getDeclarationName($currScope); + $fullQualifiedClassName = $tokens[$calledClassName]['content']; + } + + if ($declarationName === $fullQualifiedClassName) { + // Class name is the same as the current class, which is not allowed. + $error = 'Must use "self::" for local static member reference'; + $fix = $phpcsFile->addFixableError($error, $calledClassName, 'NotUsed'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $currentPointer = ($stackPtr - 1); + while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR + || $tokens[$currentPointer]['code'] === T_STRING + || isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true + ) { + if (isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true) { + --$currentPointer; + continue; + } + + $phpcsFile->fixer->replaceToken($currentPointer, ''); + --$currentPointer; + } + + $phpcsFile->fixer->replaceToken($stackPtr, 'self::'); + $phpcsFile->fixer->endChangeset(); + + // Fix potential whitespace issues in the next loop. + return; + }//end if + }//end if + }//end if + + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr - 1)]['length']; + $error = 'Expected 0 spaces before double colon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, ($stackPtr - 1), 'SpaceBefore', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr - 1); $tokens[$i]['code'] === T_WHITESPACE; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $found = $tokens[($stackPtr + 1)]['length']; + $error = 'Expected 0 spaces after double colon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, ($stackPtr - 1), 'SpaceAfter', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr + 1); $tokens[$i]['code'] === T_WHITESPACE; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + + /** + * Returns the declaration names for classes/interfaces/functions with a namespace. + * + * @param array $tokens Token stack for this file. + * @param int $stackPtr The position where the namespace building will start. + * + * @return string + */ + protected function getDeclarationNameWithNamespace(array $tokens, $stackPtr) + { + $nameParts = []; + $currentPointer = $stackPtr; + while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR + || $tokens[$currentPointer]['code'] === T_STRING + || isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true + ) { + if (isset(Tokens::$emptyTokens[$tokens[$currentPointer]['code']]) === true) { + --$currentPointer; + continue; + } + + $nameParts[] = $tokens[$currentPointer]['content']; + --$currentPointer; + } + + $nameParts = array_reverse($nameParts); + return implode('', $nameParts); + + }//end getDeclarationNameWithNamespace() + + + /** + * Returns the namespace declaration of a file. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the search for the + * namespace declaration will start. + * + * @return string + */ + protected function getNamespaceOfScope(File $phpcsFile, $stackPtr) + { + $namespace = '\\'; + $tokens = $phpcsFile->getTokens(); + + while (($namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr)) !== false) { + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($namespaceDeclaration + 1), null, true); + if ($tokens[$nextNonEmpty]['code'] === T_NS_SEPARATOR) { + // Namespace operator. Ignore. + $stackPtr = ($namespaceDeclaration - 1); + continue; + } + + $endOfNamespaceDeclaration = $phpcsFile->findNext([T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_CLOSE_TAG], $namespaceDeclaration); + $namespace = $this->getDeclarationNameWithNamespace( + $phpcsFile->getTokens(), + ($endOfNamespaceDeclaration - 1) + ); + break; + } + + return $namespace; + + }//end getNamespaceOfScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php new file mode 100644 index 000000000..a8975353f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class ValidClassNameSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being processed. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); + return; + } + + // Determine the name of the class or interface. Note that we cannot + // simply look for the first T_STRING because a class name + // starting with the number will be multiple tokens. + $opener = $tokens[$stackPtr]['scope_opener']; + $nameStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $opener, true); + $nameEnd = $phpcsFile->findNext([T_WHITESPACE, T_COLON], $nameStart, $opener); + if ($nameEnd === false) { + $name = $tokens[$nameStart]['content']; + } else { + $name = trim($phpcsFile->getTokensAsString($nameStart, ($nameEnd - $nameStart))); + } + + // Check for PascalCase format. + $valid = Common::isCamelCaps($name, true, true, false); + if ($valid === false) { + $type = ucfirst($tokens[$stackPtr]['content']); + $error = '%s name "%s" is not in PascalCase format'; + $data = [ + $type, + $name, + ]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + $phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'no'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PascalCase class name', 'yes'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php new file mode 100644 index 000000000..9a565123b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php @@ -0,0 +1,401 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class BlockCommentSniff implements Sniff +{ + + /** + * The --tab-width CLI value that is being used. + * + * @var integer + */ + private $tabWidth = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + if ($this->tabWidth === null) { + if (isset($phpcsFile->config->tabWidth) === false || $phpcsFile->config->tabWidth === 0) { + // We have no idea how wide tabs are, so assume 4 spaces for fixing. + $this->tabWidth = 4; + } else { + $this->tabWidth = $phpcsFile->config->tabWidth; + } + } + + $tokens = $phpcsFile->getTokens(); + + // If it's an inline comment, return. + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '/*') { + return; + } + + // If this is a function/class/interface doc block comment, skip it. + // We are only interested in inline doc block comments. + if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_FUNCTION => true, + T_PUBLIC => true, + T_PRIVATE => true, + T_FINAL => true, + T_PROTECTED => true, + T_STATIC => true, + T_ABSTRACT => true, + T_CONST => true, + T_VAR => true, + T_READONLY => true, + ]; + if (isset($ignore[$tokens[$nextToken]['code']]) === true) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] === T_OPEN_TAG) { + return; + } + + $error = 'Block comments must be started with /*'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStart'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, '/*'); + } + + $end = $tokens[$stackPtr]['comment_closer']; + if ($tokens[$end]['content'] !== '*/') { + $error = 'Block comments must be ended with */'; + $fix = $phpcsFile->addFixableError($error, $end, 'WrongEnd'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($end, '*/'); + } + } + + return; + }//end if + + $commentLines = [$stackPtr]; + $nextComment = $stackPtr; + $lastLine = $tokens[$stackPtr]['line']; + $commentString = $tokens[$stackPtr]['content']; + + // Construct the comment into an array. + while (($nextComment = $phpcsFile->findNext(T_WHITESPACE, ($nextComment + 1), null, true)) !== false) { + if ($tokens[$nextComment]['code'] !== $tokens[$stackPtr]['code'] + && isset(Tokens::$phpcsCommentTokens[$tokens[$nextComment]['code']]) === false + ) { + // Found the next bit of code. + break; + } + + if (($tokens[$nextComment]['line'] - 1) !== $lastLine) { + // Not part of the block. + break; + } + + $lastLine = $tokens[$nextComment]['line']; + $commentLines[] = $nextComment; + $commentString .= $tokens[$nextComment]['content']; + if ($tokens[$nextComment]['code'] === T_DOC_COMMENT_CLOSE_TAG + || substr($tokens[$nextComment]['content'], -2) === '*/' + ) { + break; + } + }//end while + + $commentText = str_replace($phpcsFile->eolChar, '', $commentString); + $commentText = trim($commentText, "/* \t"); + if ($commentText === '') { + $error = 'Empty block comment not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + $lastToken = array_pop($commentLines); + for ($i = ($stackPtr + 1); $i <= $lastToken; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + return; + } + + if (count($commentLines) === 1) { + $error = 'Single line block comment not allowed; use inline ("// text") comment instead'; + + // Only fix comments when they are the last token on a line. + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLine'); + if ($fix === true) { + $comment = '// '.$commentText.$phpcsFile->eolChar; + $phpcsFile->fixer->replaceToken($stackPtr, $comment); + } + } else { + $phpcsFile->addError($error, $stackPtr, 'SingleLine'); + } + + return; + } + + $content = trim($tokens[$stackPtr]['content']); + if ($content !== '/*' && $content !== '/**') { + $error = 'Block comment text must start on a new line'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoNewLine'); + if ($fix === true) { + $indent = ''; + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + if (isset($tokens[($stackPtr - 1)]['orig_content']) === true) { + $indent = $tokens[($stackPtr - 1)]['orig_content']; + } else { + $indent = $tokens[($stackPtr - 1)]['content']; + } + } + + $comment = preg_replace( + '/^(\s*\/\*\*?)/', + '$1'.$phpcsFile->eolChar.$indent, + $tokens[$stackPtr]['content'], + 1 + ); + $phpcsFile->fixer->replaceToken($stackPtr, $comment); + } + + return; + }//end if + + $starColumn = $tokens[$stackPtr]['column']; + $hasStars = false; + + // Make sure first line isn't blank. + if (trim($tokens[$commentLines[1]]['content']) === '') { + $error = 'Empty line not allowed at start of comment'; + $fix = $phpcsFile->addFixableError($error, $commentLines[1], 'HasEmptyLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($commentLines[1], ''); + } + } else { + // Check indentation of first line. + $content = $tokens[$commentLines[1]]['content']; + $commentText = ltrim($content); + $leadingSpace = (strlen($content) - strlen($commentText)); + + $expected = ($starColumn + 3); + if ($commentText[0] === '*') { + $expected = $starColumn; + $hasStars = true; + } + + if ($leadingSpace !== $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'First line of comment not aligned correctly; expected %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $commentLines[1], 'FirstLineIndent', $data); + if ($fix === true) { + if (isset($tokens[$commentLines[1]]['orig_content']) === true + && $tokens[$commentLines[1]]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($commentLines[1], $padding.$commentText); + } + }//end if + + if (preg_match('/^\p{Ll}/u', $commentText) === 1) { + $error = 'Block comments must start with a capital letter'; + $phpcsFile->addError($error, $commentLines[1], 'NoCapital'); + } + }//end if + + // Check that each line of the comment is indented past the star. + foreach ($commentLines as $line) { + // First and last lines (comment opener and closer) are handled separately. + if ($line === $commentLines[(count($commentLines) - 1)] || $line === $commentLines[0]) { + continue; + } + + // First comment line was handled above. + if ($line === $commentLines[1]) { + continue; + } + + // If it's empty, continue. + if (trim($tokens[$line]['content']) === '') { + continue; + } + + $commentText = ltrim($tokens[$line]['content']); + $leadingSpace = (strlen($tokens[$line]['content']) - strlen($commentText)); + + $expected = ($starColumn + 3); + if ($commentText[0] === '*') { + $expected = $starColumn; + $hasStars = true; + } + + if ($leadingSpace < $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'Comment line indented incorrectly; expected at least %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $line, 'LineIndent', $data); + if ($fix === true) { + if (isset($tokens[$line]['orig_content']) === true + && $tokens[$line]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($line, $padding.$commentText); + } + }//end if + }//end foreach + + // Finally, test the last line is correct. + $lastIndex = (count($commentLines) - 1); + $content = $tokens[$commentLines[$lastIndex]]['content']; + $commentText = ltrim($content); + if ($commentText !== '*/' && $commentText !== '**/') { + $error = 'Comment closer must be on a new line'; + $phpcsFile->addError($error, $commentLines[$lastIndex], 'CloserSameLine'); + } else { + $leadingSpace = (strlen($content) - strlen($commentText)); + + $expected = ($starColumn - 1); + if ($hasStars === true) { + $expected = $starColumn; + } + + if ($leadingSpace !== $expected) { + $expectedTxt = $expected.' space'; + if ($expected !== 1) { + $expectedTxt .= 's'; + } + + $data = [ + $expectedTxt, + $leadingSpace, + ]; + + $error = 'Last line of comment aligned incorrectly; expected %s but found %s'; + $fix = $phpcsFile->addFixableError($error, $commentLines[$lastIndex], 'LastLineIndent', $data); + if ($fix === true) { + if (isset($tokens[$line]['orig_content']) === true + && $tokens[$line]['orig_content'][0] === "\t" + ) { + // Line is indented using tabs. + $padding = str_repeat("\t", floor($expected / $this->tabWidth)); + $padding .= str_repeat(' ', ($expected % $this->tabWidth)); + } else { + $padding = str_repeat(' ', $expected); + } + + $phpcsFile->fixer->replaceToken($commentLines[$lastIndex], $padding.$commentText); + } + }//end if + }//end if + + // Check that the lines before and after this comment are blank. + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ((isset($tokens[$contentBefore]['scope_closer']) === true + && $tokens[$contentBefore]['scope_opener'] === $contentBefore) + || $tokens[$contentBefore]['code'] === T_OPEN_TAG + || $tokens[$contentBefore]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) !== 1) { + $error = 'Empty line not required before block comment'; + $phpcsFile->addError($error, $stackPtr, 'HasEmptyLineBefore'); + } + } else { + if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) < 2) { + $error = 'Empty line required before block comment'; + $phpcsFile->addError($error, $stackPtr, 'NoEmptyLineBefore'); + } + } + + $commentCloser = $commentLines[$lastIndex]; + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($commentCloser + 1), null, true); + if ($contentAfter !== false && ($tokens[$contentAfter]['line'] - $tokens[$commentCloser]['line']) < 2) { + $error = 'Empty line required after block comment'; + $phpcsFile->addError($error, $commentCloser, 'NoEmptyLineAfter'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 000000000..60d553fc2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,109 @@ + + *
  • A class doc comment exists.
  • + *
  • The comment uses the correct docblock style.
  • + *
  • There are no blank lines after the class comment.
  • + *
  • No tags are used in the docblock.
  • + * + * + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClassCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLASS]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $find = [ + T_ABSTRACT => T_ABSTRACT, + T_FINAL => T_FINAL, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + ]; + + $previousContent = null; + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($previousContent === null) { + $previousContent = $commentEnd; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT + ) { + $class = $phpcsFile->getDeclarationName($stackPtr); + $phpcsFile->addError('Missing doc comment for class %s', $stackPtr, 'Missing', [$class]); + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes'); + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle'); + return; + } + + if ($tokens[$previousContent]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + $error = 'There must be no blank lines after the class comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfter'); + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $error = '%s tag is not allowed in class comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php new file mode 100644 index 000000000..44bd4388d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php @@ -0,0 +1,130 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ClosingDeclarationCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CLASS, + T_ENUM, + T_FUNCTION, + T_INTERFACE, + T_TRAIT, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens.. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_FUNCTION) { + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + + // Abstract methods do not require a closing comment. + if ($methodProps['is_abstract'] === true) { + return; + } + + // If this function is in an interface then we don't require + // a closing comment. + if ($phpcsFile->hasCondition($stackPtr, T_INTERFACE) === true) { + return; + } + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + $error = 'Possible parse error: non-abstract method defined as abstract'; + $phpcsFile->addWarning($error, $stackPtr, 'Abstract'); + return; + } + + $decName = $phpcsFile->getDeclarationName($stackPtr); + $comment = '//end '.$decName.'()'; + } else if ($tokens[$stackPtr]['code'] === T_CLASS) { + $comment = '//end class'; + } else if ($tokens[$stackPtr]['code'] === T_INTERFACE) { + $comment = '//end interface'; + } else if ($tokens[$stackPtr]['code'] === T_TRAIT) { + $comment = '//end trait'; + } else { + $comment = '//end enum'; + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + $error = 'Possible parse error: %s missing opening or closing brace'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data); + return; + } + + $closingBracket = $tokens[$stackPtr]['scope_closer']; + + $data = [$comment]; + if (isset($tokens[($closingBracket + 1)]) === false || $tokens[($closingBracket + 1)]['code'] !== T_COMMENT) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($closingBracket + 1), null, true); + if ($next !== false && rtrim($tokens[$next]['content']) === $comment) { + // The comment isn't really missing; it is just in the wrong place. + $fix = $phpcsFile->addFixableError('Expected %s directly after closing brace', $closingBracket, 'Misplaced', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Just in case, because indentation fixes can add indents onto + // these comments and cause us to be unable to fix them. + $phpcsFile->fixer->replaceToken($next, $comment.$phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + } else { + $fix = $phpcsFile->addFixableError('Expected %s', $closingBracket, 'Missing', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($closingBracket, '}'.$comment); + } + } + + return; + }//end if + + if (rtrim($tokens[($closingBracket + 1)]['content']) !== $comment) { + $fix = $phpcsFile->addFixableError('Expected %s', $closingBracket, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closingBracket + 1), $comment.$phpcsFile->eolChar); + } + + return; + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php new file mode 100644 index 000000000..453ff89c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php @@ -0,0 +1,167 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DocCommentAlignmentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_DOC_COMMENT_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We are only interested in function/class/interface doc block comments. + $ignore = Tokens::$emptyTokens; + if ($phpcsFile->tokenizerType === 'JS') { + $ignore[] = T_EQUAL; + $ignore[] = T_STRING; + $ignore[] = T_OBJECT_OPERATOR; + } + + $nextToken = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + $ignore = [ + T_CLASS => true, + T_INTERFACE => true, + T_ENUM => true, + T_ENUM_CASE => true, + T_FUNCTION => true, + T_PUBLIC => true, + T_PRIVATE => true, + T_PROTECTED => true, + T_STATIC => true, + T_ABSTRACT => true, + T_PROPERTY => true, + T_OBJECT => true, + T_PROTOTYPE => true, + T_VAR => true, + T_READONLY => true, + ]; + + if ($nextToken === false || isset($ignore[$tokens[$nextToken]['code']]) === false) { + // Could be a file comment. + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prevToken]['code'] !== T_OPEN_TAG) { + return; + } + } + + // There must be one space after each star (unless it is an empty comment line) + // and all the stars must be aligned correctly. + $requiredColumn = ($tokens[$stackPtr]['column'] + 1); + $endComment = $tokens[$stackPtr]['comment_closer']; + for ($i = ($stackPtr + 1); $i <= $endComment; $i++) { + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STAR + && $tokens[$i]['code'] !== T_DOC_COMMENT_CLOSE_TAG + ) { + continue; + } + + if ($tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + if (trim($tokens[$i]['content']) === '') { + // Don't process an unfinished docblock close tag during live coding. + continue; + } + + // Can't process the close tag if it is not the first thing on the line. + $prev = $phpcsFile->findPrevious(T_DOC_COMMENT_WHITESPACE, ($i - 1), $stackPtr, true); + if ($tokens[$prev]['line'] === $tokens[$i]['line']) { + continue; + } + } + + if ($tokens[$i]['column'] !== $requiredColumn) { + $pluralizeSpace = 's'; + if (($requiredColumn - 1) === 1) { + $pluralizeSpace = ''; + } + + $error = 'Expected %s space%s before asterisk; %s found'; + $data = [ + ($requiredColumn - 1), + $pluralizeSpace, + ($tokens[$i]['column'] - 1), + ]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceBeforeStar', $data); + if ($fix === true) { + $padding = str_repeat(' ', ($requiredColumn - 1)); + if ($tokens[$i]['column'] === 1) { + $phpcsFile->fixer->addContentBefore($i, $padding); + } else { + $phpcsFile->fixer->replaceToken(($i - 1), $padding); + } + } + }//end if + + if ($tokens[$i]['code'] !== T_DOC_COMMENT_STAR) { + continue; + } + + if ($tokens[($i + 2)]['line'] !== $tokens[$i]['line']) { + // Line is empty. + continue; + } + + if ($tokens[($i + 1)]['code'] !== T_DOC_COMMENT_WHITESPACE) { + $error = 'Expected 1 space after asterisk; 0 found'; + $fix = $phpcsFile->addFixableError($error, $i, 'NoSpaceAfterStar'); + if ($fix === true) { + $phpcsFile->fixer->addContent($i, ' '); + } + } else if ($tokens[($i + 2)]['code'] === T_DOC_COMMENT_TAG + && $tokens[($i + 1)]['content'] !== ' ' + ) { + $error = 'Expected 1 space after asterisk; %s found'; + $data = [$tokens[($i + 1)]['length']]; + $fix = $phpcsFile->addFixableError($error, $i, 'SpaceAfterStar', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($i + 1), ' '); + } + } + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php new file mode 100644 index 000000000..301537fe7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php @@ -0,0 +1,55 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EmptyCatchCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CATCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($scopeStart + 1), $tokens[$stackPtr]['scope_closer'], true); + + if ($firstContent === false) { + $error = 'Empty CATCH statement must have a comment to explain why the exception is not handled'; + $phpcsFile->addError($error, $scopeStart, 'Missing'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 000000000..cfff91fc6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,228 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FileCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + + if ($tokens[$commentStart]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a file comment', $commentStart, 'WrongStyle'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + return $phpcsFile->numTokens; + } else if ($commentStart === false || $tokens[$commentStart]['code'] !== T_DOC_COMMENT_OPEN_TAG) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return $phpcsFile->numTokens; + } + + if (isset($tokens[$commentStart]['comment_closer']) === false + || ($tokens[$tokens[$commentStart]['comment_closer']]['content'] === '' + && $tokens[$commentStart]['comment_closer'] === ($phpcsFile->numTokens - 1)) + ) { + // Don't process an unfinished file comment during live coding. + return $phpcsFile->numTokens; + } + + $commentEnd = $tokens[$commentStart]['comment_closer']; + + for ($nextToken = ($commentEnd + 1); $nextToken < $phpcsFile->numTokens; $nextToken++) { + if ($tokens[$nextToken]['code'] === T_WHITESPACE) { + continue; + } + + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE + && isset($tokens[$nextToken]['attribute_closer']) === true + ) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } + + if ($nextToken === $phpcsFile->numTokens) { + $nextToken--; + } + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_READONLY, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + $phpcsFile->addError('Missing file doc comment', $stackPtr, 'Missing'); + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'no'); + return $phpcsFile->numTokens; + } + + $phpcsFile->recordMetric($stackPtr, 'File has doc comment', 'yes'); + + // No blank line between the open tag and the file comment. + if ($tokens[$commentStart]['line'] > ($tokens[$stackPtr]['line'] + 1)) { + $error = 'There must be no blank lines before the file comment'; + $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen'); + } + + // Exactly one blank line after the file comment. + $next = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), null, true); + if ($next !== false && $tokens[$next]['line'] !== ($tokens[$commentEnd]['line'] + 2)) { + $error = 'There must be exactly one blank line after the file comment'; + $phpcsFile->addError($error, $commentEnd, 'SpacingAfterComment'); + } + + // Required tags in correct order. + $required = [ + '@package' => true, + '@subpackage' => true, + '@author' => true, + '@copyright' => true, + ]; + + $foundTags = []; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + $name = $tokens[$tag]['content']; + $isRequired = isset($required[$name]); + + if ($isRequired === true && in_array($name, $foundTags, true) === true) { + $error = 'Only one %s tag is allowed in a file comment'; + $data = [$name]; + $phpcsFile->addError($error, $tag, 'Duplicate'.ucfirst(substr($name, 1)).'Tag', $data); + } + + $foundTags[] = $name; + + if ($isRequired === false) { + continue; + } + + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for %s tag in file comment'; + $data = [$name]; + $phpcsFile->addError($error, $tag, 'Empty'.ucfirst(substr($name, 1)).'Tag', $data); + continue; + } + + if ($name === '@author') { + if ($tokens[$string]['content'] !== 'Squiz Pty Ltd ') { + $error = 'Expected "Squiz Pty Ltd " for author tag'; + $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectAuthor'); + if ($fix === true) { + $expected = 'Squiz Pty Ltd '; + $phpcsFile->fixer->replaceToken($string, $expected); + } + } + } else if ($name === '@copyright') { + if (preg_match('/^([0-9]{4})(-[0-9]{4})? (Squiz Pty Ltd \(ABN 77 084 670 600\))$/', $tokens[$string]['content']) === 0) { + $error = 'Expected "xxxx-xxxx Squiz Pty Ltd (ABN 77 084 670 600)" for copyright declaration'; + $fix = $phpcsFile->addFixableError($error, $tag, 'IncorrectCopyright'); + if ($fix === true) { + $matches = []; + preg_match('/^(([0-9]{4})(-[0-9]{4})?)?.*$/', $tokens[$string]['content'], $matches); + if (isset($matches[1]) === false) { + $matches[1] = date('Y'); + } + + $expected = $matches[1].' Squiz Pty Ltd (ABN 77 084 670 600)'; + $phpcsFile->fixer->replaceToken($string, $expected); + } + } + }//end if + }//end foreach + + // Check if the tags are in the correct position. + $pos = 0; + foreach ($required as $tag => $true) { + if (in_array($tag, $foundTags, true) === false) { + $error = 'Missing %s tag in file comment'; + $data = [$tag]; + $phpcsFile->addError($error, $commentEnd, 'Missing'.ucfirst(substr($tag, 1)).'Tag', $data); + } + + if (isset($foundTags[$pos]) === false) { + break; + } + + if ($foundTags[$pos] !== $tag) { + $error = 'The tag in position %s should be the %s tag'; + $data = [ + ($pos + 1), + $tag, + ]; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_tags'][$pos], ucfirst(substr($tag, 1)).'TagOrder', $data); + } + + $pos++; + }//end foreach + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php new file mode 100644 index 000000000..b0b7cafb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php @@ -0,0 +1,800 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FunctionCommentSniff as PEARFunctionCommentSniff; +use PHP_CodeSniffer\Util\Common; + +class FunctionCommentSniff extends PEARFunctionCommentSniff +{ + + /** + * Whether to skip inheritdoc comments. + * + * @var boolean + */ + public $skipIfInheritdoc = false; + + /** + * The current PHP version. + * + * @var integer|string|null + */ + private $phpVersion = null; + + + /** + * Process the return comment of this function comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processReturn(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + $return = null; + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@return') { + if ($return !== null) { + $error = 'Only 1 @return tag is allowed in a function comment'; + $phpcsFile->addError($error, $tag, 'DuplicateReturn'); + return; + } + + $return = $tag; + } + } + + // Skip constructor and destructor. + $methodName = $phpcsFile->getDeclarationName($stackPtr); + $isSpecialMethod = in_array($methodName, $this->specialMethods, true); + + if ($return !== null) { + $content = $tokens[($return + 2)]['content']; + if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { + $error = 'Return type missing for @return tag in function comment'; + $phpcsFile->addError($error, $return, 'MissingReturnType'); + } else { + // Support both a return type and a description. + preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $content, $returnParts); + if (isset($returnParts[1]) === false) { + return; + } + + $returnType = $returnParts[1]; + + // Check return type (can be multiple, separated by '|'). + $typeNames = explode('|', $returnType); + $suggestedNames = []; + foreach ($typeNames as $typeName) { + $suggestedName = Common::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames, true) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($returnType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for function return type'; + $data = [ + $suggestedType, + $returnType, + ]; + $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); + if ($fix === true) { + $replacement = $suggestedType; + if (empty($returnParts[2]) === false) { + $replacement .= $returnParts[2]; + } + + $phpcsFile->fixer->replaceToken(($return + 2), $replacement); + unset($replacement); + } + } + + // If the return type is void, make sure there is + // no return statement in the function. + if ($returnType === 'void') { + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken !== $endToken) { + // If the function is not returning anything, just + // exiting, then there is no problem. + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { + $error = 'Function return type is void, but function contains return statement'; + $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); + } + } + }//end if + } else if ($returnType !== 'mixed' + && $returnType !== 'never' + && in_array('void', $typeNames, true) === false + ) { + // If return type is not void, never, or mixed, there needs to be a + // return statement somewhere in the function that returns something. + if (isset($tokens[$stackPtr]['scope_closer']) === true) { + $endToken = $tokens[$stackPtr]['scope_closer']; + for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { + if ($tokens[$returnToken]['code'] === T_CLOSURE + || $tokens[$returnToken]['code'] === T_ANON_CLASS + ) { + $returnToken = $tokens[$returnToken]['scope_closer']; + continue; + } + + if ($tokens[$returnToken]['code'] === T_RETURN + || $tokens[$returnToken]['code'] === T_YIELD + || $tokens[$returnToken]['code'] === T_YIELD_FROM + ) { + break; + } + } + + if ($returnToken === $endToken) { + $error = 'Function return type is not void, but function has no return statement'; + $phpcsFile->addError($error, $return, 'InvalidNoReturn'); + } else { + $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); + if ($tokens[$semicolon]['code'] === T_SEMICOLON) { + $error = 'Function return type is not void, but function is returning void here'; + $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); + } + } + }//end if + }//end if + }//end if + } else { + if ($isSpecialMethod === true) { + return; + } + + $error = 'Missing @return tag in function comment'; + $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); + }//end if + + }//end processReturn() + + + /** + * Process any throw tags that this function comment has. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + $exception = null; + $comment = null; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); + $exception = $matches[1]; + if (isset($matches[2]) === true && trim($matches[2]) !== '') { + $comment = $matches[2]; + } + } + + if ($exception === null) { + $error = 'Exception type and comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'InvalidThrows'); + } else if ($comment === null) { + $error = 'Comment missing for @throws tag in function comment'; + $phpcsFile->addError($error, $tag, 'EmptyThrows'); + } else { + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $comment .= ' '.$tokens[$i]['content']; + } + } + + $comment = trim($comment); + + // Starts with a capital letter and ends with a fullstop. + $firstChar = $comment[0]; + if (strtoupper($firstChar) !== $firstChar) { + $error = '@throws tag comment must start with a capital letter'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); + } + + $lastChar = substr($comment, -1); + if ($lastChar !== '.') { + $error = '@throws tag comment must end with a full stop'; + $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop'); + } + }//end if + }//end foreach + + }//end processThrows() + + + /** + * Process the function parameter comments. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return void + */ + protected function processParams(File $phpcsFile, $stackPtr, $commentStart) + { + if ($this->phpVersion === null) { + $this->phpVersion = Config::getConfigData('php_version'); + if ($this->phpVersion === null) { + $this->phpVersion = PHP_VERSION_ID; + } + } + + $tokens = $phpcsFile->getTokens(); + + if ($this->skipIfInheritdoc === true) { + if ($this->checkInheritdoc($phpcsFile, $stackPtr, $commentStart) === true) { + return; + } + } + + $params = []; + $maxType = 0; + $maxVar = 0; + foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { + if ($tokens[$tag]['content'] !== '@param') { + continue; + } + + $type = ''; + $typeSpace = 0; + $var = ''; + $varSpace = 0; + $comment = ''; + $commentLines = []; + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $matches = []; + preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + + if (empty($matches) === false) { + $typeLen = strlen($matches[1]); + $type = trim($matches[1]); + $typeSpace = ($typeLen - strlen($type)); + $typeLen = strlen($type); + if ($typeLen > $maxType) { + $maxType = $typeLen; + } + } + + if (isset($matches[2]) === true) { + $var = $matches[2]; + $varLen = strlen($var); + if ($varLen > $maxVar) { + $maxVar = $varLen; + } + + if (isset($matches[4]) === true) { + $varSpace = strlen($matches[3]); + $comment = $matches[4]; + $commentLines[] = [ + 'comment' => $comment, + 'token' => ($tag + 2), + 'indent' => $varSpace, + ]; + + // Any strings until the next tag belong to this comment. + if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { + $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; + } else { + $end = $tokens[$commentStart]['comment_closer']; + } + + for ($i = ($tag + 3); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { + $indent = 0; + if ($tokens[($i - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { + $indent = $tokens[($i - 1)]['length']; + } + + $comment .= ' '.$tokens[$i]['content']; + $commentLines[] = [ + 'comment' => $tokens[$i]['content'], + 'token' => $i, + 'indent' => $indent, + ]; + } + } + } else { + $error = 'Missing parameter comment'; + $phpcsFile->addError($error, $tag, 'MissingParamComment'); + $commentLines[] = ['comment' => '']; + }//end if + } else if ($tokens[($tag + 2)]['content'][0] === '$') { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + } else { + $error = 'Missing parameter name'; + $phpcsFile->addError($error, $tag, 'MissingParamName'); + }//end if + } else { + $error = 'Missing parameter type'; + $phpcsFile->addError($error, $tag, 'MissingParamType'); + }//end if + + $params[] = [ + 'tag' => $tag, + 'type' => $type, + 'var' => $var, + 'comment' => $comment, + 'commentLines' => $commentLines, + 'type_space' => $typeSpace, + 'var_space' => $varSpace, + ]; + }//end foreach + + $realParams = $phpcsFile->getMethodParameters($stackPtr); + $foundParams = []; + + // We want to use ... for all variable length arguments, so added + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + + foreach ($params as $pos => $param) { + // If the type is empty, the whole line is empty. + if ($param['type'] === '') { + continue; + } + + // Check the param type value. + $typeNames = explode('|', $param['type']); + $suggestedTypeNames = []; + + foreach ($typeNames as $typeName) { + if ($typeName === '') { + continue; + } + + // Strip nullable operator. + if ($typeName[0] === '?') { + $typeName = substr($typeName, 1); + } + + $suggestedName = Common::suggestType($typeName); + $suggestedTypeNames[] = $suggestedName; + + if (count($typeNames) > 1) { + continue; + } + + // Check type hint for array and custom type. + $suggestedTypeHint = ''; + if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { + $suggestedTypeHint = 'array'; + } else if (strpos($suggestedName, 'callable') !== false) { + $suggestedTypeHint = 'callable'; + } else if (strpos($suggestedName, 'callback') !== false) { + $suggestedTypeHint = 'callable'; + } else if (in_array($suggestedName, Common::$allowedTypes, true) === false) { + $suggestedTypeHint = $suggestedName; + } + + if ($this->phpVersion >= 70000) { + if ($suggestedName === 'string') { + $suggestedTypeHint = 'string'; + } else if ($suggestedName === 'int' || $suggestedName === 'integer') { + $suggestedTypeHint = 'int'; + } else if ($suggestedName === 'float') { + $suggestedTypeHint = 'float'; + } else if ($suggestedName === 'bool' || $suggestedName === 'boolean') { + $suggestedTypeHint = 'bool'; + } + } + + if ($this->phpVersion >= 70200) { + if ($suggestedName === 'object') { + $suggestedTypeHint = 'object'; + } + } + + if ($this->phpVersion >= 80000) { + if ($suggestedName === 'mixed') { + $suggestedTypeHint = 'mixed'; + } + } + + if ($suggestedTypeHint !== '' && isset($realParams[$pos]) === true && $param['var'] !== '') { + $typeHint = $realParams[$pos]['type_hint']; + + // Remove namespace prefixes when comparing. + $compareTypeHint = substr($suggestedTypeHint, (strlen($typeHint) * -1)); + + if ($typeHint === '') { + $error = 'Type hint "%s" missing for %s'; + $data = [ + $suggestedTypeHint, + $param['var'], + ]; + + $errorCode = 'TypeHintMissing'; + if ($suggestedTypeHint === 'string' + || $suggestedTypeHint === 'int' + || $suggestedTypeHint === 'float' + || $suggestedTypeHint === 'bool' + ) { + $errorCode = 'Scalar'.$errorCode; + } + + $phpcsFile->addError($error, $stackPtr, $errorCode, $data); + } else if ($typeHint !== $compareTypeHint && $typeHint !== '?'.$compareTypeHint) { + $error = 'Expected type hint "%s"; found "%s" for %s'; + $data = [ + $suggestedTypeHint, + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); + }//end if + } else if ($suggestedTypeHint === '' && isset($realParams[$pos]) === true) { + $typeHint = $realParams[$pos]['type_hint']; + if ($typeHint !== '') { + $error = 'Unknown type hint "%s" found for %s'; + $data = [ + $typeHint, + $param['var'], + ]; + $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); + } + }//end if + }//end foreach + + $suggestedType = implode('|', $suggestedTypeNames); + if ($param['type'] !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for parameter type'; + $data = [ + $suggestedType, + $param['type'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $suggestedType; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + if (isset($param['commentLines'][0]) === true) { + $content .= $param['commentLines'][0]['comment']; + } + + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = (strlen($param['type']) - strlen($suggestedType)); + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + if ($param['var'] === '') { + continue; + } + + $foundParams[] = $param['var']; + + // Check number of spaces after the type. + $this->checkSpacingAfterParamType($phpcsFile, $param, $maxType); + + // Make sure the param name is correct. + if (isset($realParams[$pos]) === true) { + $realName = $realParams[$pos]['name']; + $paramVarName = $param['var']; + + if ($param['var'][0] === '&') { + // Even when passed by reference, the variable name in $realParams does not have + // a leading '&'. This sniff will accept both '&$var' and '$var' in these cases. + $paramVarName = substr($param['var'], 1); + + // This makes sure that the 'MissingParamTag' check won't throw a false positive. + $foundParams[(count($foundParams) - 1)] = $paramVarName; + + if ($realParams[$pos]['pass_by_reference'] !== true && $realName === $paramVarName) { + // Don't complain about this unless the param name is otherwise correct. + $error = 'Doc comment for parameter %s is prefixed with "&" but parameter is not passed by reference'; + $code = 'ParamNameUnexpectedAmpersandPrefix'; + $data = [$paramVarName]; + + // We're not offering an auto-fix here because we can't tell if the docblock + // is wrong, or the parameter should be passed by reference. + $phpcsFile->addError($error, $param['tag'], $code, $data); + } + } + + if ($realName !== $paramVarName) { + $code = 'ParamNameNoMatch'; + $data = [ + $paramVarName, + $realName, + ]; + + $error = 'Doc comment for parameter %s does not match '; + if (strtolower($paramVarName) === strtolower($realName)) { + $error .= 'case of '; + $code = 'ParamNameNoCaseMatch'; + } + + $error .= 'actual variable name %s'; + + $phpcsFile->addError($error, $param['tag'], $code, $data); + }//end if + } else if (substr($param['var'], -4) !== ',...') { + // We must have an extra parameter comment. + $error = 'Superfluous parameter comment'; + $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); + }//end if + + if ($param['comment'] === '') { + continue; + } + + // Check number of spaces after the var name. + $this->checkSpacingAfterParamName($phpcsFile, $param, $maxVar); + + // Param comments must start with a capital letter and end with a full stop. + if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { + $error = 'Parameter comment must start with a capital letter'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital'); + } + + $lastChar = substr($param['comment'], -1); + if ($lastChar !== '.') { + $error = 'Parameter comment must end with a full stop'; + $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop'); + } + }//end foreach + + $realNames = []; + foreach ($realParams as $realParam) { + $realNames[] = $realParam['name']; + } + + // Report missing comments. + $diff = array_diff($realNames, $foundParams); + foreach ($diff as $neededParam) { + $error = 'Doc comment for parameter "%s" missing'; + $data = [$neededParam]; + $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); + } + + }//end processParams() + + + /** + * Check the spacing after the type of a parameter. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxType The maxlength of the longest parameter type. + * @param int $spacing The number of spaces to add after the type. + * + * @return void + */ + protected function checkSpacingAfterParamType(File $phpcsFile, $param, $maxType, $spacing=1) + { + // Check number of spaces after the type. + $spaces = ($maxType - strlen($param['type']) + $spacing); + if ($param['type_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter type; %s found'; + $data = [ + $spaces, + $param['type_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $spaces); + $content .= $param['var']; + $content .= str_repeat(' ', $param['var_space']); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + $diff = ($param['type_space'] - $spaces); + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + }//end checkSpacingAfterParamType() + + + /** + * Check the spacing after the name of a parameter. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param array $param The parameter to be checked. + * @param int $maxVar The maxlength of the longest parameter name. + * @param int $spacing The number of spaces to add after the type. + * + * @return void + */ + protected function checkSpacingAfterParamName(File $phpcsFile, $param, $maxVar, $spacing=1) + { + // Check number of spaces after the var name. + $spaces = ($maxVar - strlen($param['var']) + $spacing); + if ($param['var_space'] !== $spaces) { + $error = 'Expected %s spaces after parameter name; %s found'; + $data = [ + $spaces, + $param['var_space'], + ]; + + $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + + $content = $param['type']; + $content .= str_repeat(' ', $param['type_space']); + $content .= $param['var']; + $content .= str_repeat(' ', $spaces); + $content .= $param['commentLines'][0]['comment']; + $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); + + // Fix up the indent of additional comment lines. + foreach ($param['commentLines'] as $lineNum => $line) { + if ($lineNum === 0 + || $param['commentLines'][$lineNum]['indent'] === 0 + ) { + continue; + } + + $diff = ($param['var_space'] - $spaces); + $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); + if ($newIndent <= 0) { + continue; + } + + $phpcsFile->fixer->replaceToken( + ($param['commentLines'][$lineNum]['token'] - 1), + str_repeat(' ', $newIndent) + ); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + }//end checkSpacingAfterParamName() + + + /** + * Determines whether the whole comment is an inheritdoc comment. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $commentStart The position in the stack where the comment started. + * + * @return boolean TRUE if the docblock contains only {@inheritdoc} (case-insensitive). + */ + protected function checkInheritdoc(File $phpcsFile, $stackPtr, $commentStart) + { + $tokens = $phpcsFile->getTokens(); + + $allowedTokens = [ + T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_STAR, + ]; + for ($i = $commentStart; $i <= $tokens[$commentStart]['comment_closer']; $i++) { + if (in_array($tokens[$i]['code'], $allowedTokens) === false) { + $trimmedContent = strtolower(trim($tokens[$i]['content'])); + + if ($trimmedContent === '{@inheritdoc}') { + return true; + } else { + return false; + } + } + } + + return false; + + }//end checkInheritdoc() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php new file mode 100644 index 000000000..4fb332cf4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php @@ -0,0 +1,233 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionCommentThrowTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Abstract or incomplete. + return; + } + + $find = Tokens::$methodPrefixes; + $find[] = T_WHITESPACE; + + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) { + // Function doesn't have a doc comment or is using the wrong type of comment. + return; + } + + $stackPtrEnd = $tokens[$stackPtr]['scope_closer']; + + // Find all the exception type tokens within the current scope. + $thrownExceptions = []; + $currPos = $stackPtr; + $foundThrows = false; + $unknownCount = 0; + do { + $currPos = $phpcsFile->findNext([T_THROW, T_ANON_CLASS, T_CLOSURE], ($currPos + 1), $stackPtrEnd); + if ($currPos === false) { + break; + } + + if ($tokens[$currPos]['code'] !== T_THROW) { + $currPos = $tokens[$currPos]['scope_closer']; + continue; + } + + $foundThrows = true; + + /* + If we can't find a NEW, we are probably throwing + a variable or calling a method. + + If we're throwing a variable, and it's the same variable as the + exception container from the nearest 'catch' block, we take that exception + as it is likely to be a re-throw. + + If we can't find a matching catch block, or the variable name + is different, it's probably a different variable, so we ignore it, + but they still need to provide at least one @throws tag, even through we + don't know the exception class. + */ + + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($currPos + 1), null, true); + if ($tokens[$nextToken]['code'] === T_NEW + || $tokens[$nextToken]['code'] === T_NS_SEPARATOR + || $tokens[$nextToken]['code'] === T_STRING + ) { + if ($tokens[$nextToken]['code'] === T_NEW) { + $currException = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + $currPos, + $stackPtrEnd, + false, + null, + true + ); + } else { + $currException = $nextToken; + } + + if ($currException !== false) { + $endException = $phpcsFile->findNext( + [ + T_NS_SEPARATOR, + T_STRING, + ], + ($currException + 1), + $stackPtrEnd, + true, + null, + true + ); + + if ($endException === false) { + $thrownExceptions[] = $tokens[$currException]['content']; + } else { + $thrownExceptions[] = $phpcsFile->getTokensAsString($currException, ($endException - $currException)); + } + }//end if + } else if ($tokens[$nextToken]['code'] === T_VARIABLE) { + // Find the nearest catch block in this scope and, if the caught var + // matches our re-thrown var, use the exception types being caught as + // exception types that are being thrown as well. + $catch = $phpcsFile->findPrevious( + T_CATCH, + $currPos, + $tokens[$stackPtr]['scope_opener'], + false, + null, + false + ); + + if ($catch !== false) { + $thrownVar = $phpcsFile->findPrevious( + T_VARIABLE, + ($tokens[$catch]['parenthesis_closer'] - 1), + $tokens[$catch]['parenthesis_opener'] + ); + + if ($tokens[$thrownVar]['content'] === $tokens[$nextToken]['content']) { + $exceptions = explode('|', $phpcsFile->getTokensAsString(($tokens[$catch]['parenthesis_opener'] + 1), ($thrownVar - $tokens[$catch]['parenthesis_opener'] - 1))); + foreach ($exceptions as $exception) { + $thrownExceptions[] = trim($exception); + } + } + } + } else { + ++$unknownCount; + }//end if + } while ($currPos < $stackPtrEnd && $currPos !== false); + + if ($foundThrows === false) { + return; + } + + // Only need one @throws tag for each type of exception thrown. + $thrownExceptions = array_unique($thrownExceptions); + + $throwTags = []; + $commentStart = $tokens[$commentEnd]['comment_opener']; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] !== '@throws') { + continue; + } + + if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { + $exception = $tokens[($tag + 2)]['content']; + $space = strpos($exception, ' '); + if ($space !== false) { + $exception = substr($exception, 0, $space); + } + + $throwTags[$exception] = true; + } + } + + if (empty($throwTags) === true) { + $error = 'Missing @throws tag in function comment'; + $phpcsFile->addError($error, $commentEnd, 'Missing'); + return; + } else if (empty($thrownExceptions) === true) { + // If token count is zero, it means that only variables are being + // thrown, so we need at least one @throws tag (checked above). + // Nothing more to do. + return; + } + + // Make sure @throws tag count matches thrown count. + $thrownCount = (count($thrownExceptions) + $unknownCount); + $tagCount = count($throwTags); + if ($thrownCount !== $tagCount) { + $error = 'Expected %s @throws tag(s) in function comment; %s found'; + $data = [ + $thrownCount, + $tagCount, + ]; + $phpcsFile->addError($error, $commentEnd, 'WrongNumber', $data); + return; + } + + foreach ($thrownExceptions as $throw) { + if (isset($throwTags[$throw]) === true) { + continue; + } + + foreach ($throwTags as $tag => $ignore) { + if (strrpos($tag, $throw) === (strlen($tag) - strlen($throw))) { + continue 2; + } + } + + $error = 'Missing @throws tag for "%s" exception'; + $data = [$throw]; + $phpcsFile->addError($error, $commentEnd, 'Missing', $data); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php new file mode 100644 index 000000000..3c1ead70a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php @@ -0,0 +1,349 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InlineCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_OPEN_TAG, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void|int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is a function/class/interface doc block comment, skip it. + // We are only interested in inline doc block comments, which are + // not allowed. + if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_READONLY, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + ]; + + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + return; + } + + if ($phpcsFile->tokenizerType === 'JS') { + // We allow block comments if a function or object + // is being assigned to a variable. + $ignore = Tokens::$emptyTokens; + $ignore[] = T_EQUAL; + $ignore[] = T_STRING; + $ignore[] = T_OBJECT_OPERATOR; + $nextToken = $phpcsFile->findNext($ignore, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_FUNCTION + || $tokens[$nextToken]['code'] === T_CLOSURE + || $tokens[$nextToken]['code'] === T_OBJECT + || $tokens[$nextToken]['code'] === T_PROTOTYPE + ) { + return; + } + } + + $prevToken = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($stackPtr - 1), + null, + true + ); + + if ($tokens[$prevToken]['code'] === T_OPEN_TAG) { + return; + } + + if ($tokens[$stackPtr]['content'] === '/**') { + $error = 'Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead'; + $phpcsFile->addError($error, $stackPtr, 'DocBlock'); + } + }//end if + + if ($tokens[$stackPtr]['content'][0] === '#') { + $error = 'Perl-style comments are not allowed; use "// Comment" instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStyle'); + if ($fix === true) { + $comment = ltrim($tokens[$stackPtr]['content'], "# \t"); + $phpcsFile->fixer->replaceToken($stackPtr, "// $comment"); + } + } + + // We don't want end of block comments. Check if the last token before the + // comment is a closing curly brace. + $previousContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$previousContent]['line'] === $tokens[$stackPtr]['line']) { + if ($tokens[$previousContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + + // Special case for JS files. + if ($tokens[$previousContent]['code'] === T_COMMA + || $tokens[$previousContent]['code'] === T_SEMICOLON + ) { + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($previousContent - 1), null, true); + if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + } + + // Only want inline comments. + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { + return; + } + + $commentTokens = [$stackPtr]; + + $nextComment = $stackPtr; + $lastComment = $stackPtr; + while (($nextComment = $phpcsFile->findNext(T_COMMENT, ($nextComment + 1), null, false)) !== false) { + if ($tokens[$nextComment]['line'] !== ($tokens[$lastComment]['line'] + 1)) { + break; + } + + // Only want inline comments. + if (substr($tokens[$nextComment]['content'], 0, 2) !== '//') { + break; + } + + // There is a comment on the very next line. If there is + // no code between the comments, they are part of the same + // comment block. + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($nextComment - 1), $lastComment, true); + if ($prevNonWhitespace !== $lastComment) { + break; + } + + $commentTokens[] = $nextComment; + $lastComment = $nextComment; + }//end while + + $commentText = ''; + foreach ($commentTokens as $lastCommentToken) { + $comment = rtrim($tokens[$lastCommentToken]['content']); + + if (trim(substr($comment, 2)) === '') { + continue; + } + + $spaceCount = 0; + $tabFound = false; + + $commentLength = strlen($comment); + for ($i = 2; $i < $commentLength; $i++) { + if ($comment[$i] === "\t") { + $tabFound = true; + break; + } + + if ($comment[$i] !== ' ') { + break; + } + + $spaceCount++; + } + + $fix = false; + if ($tabFound === true) { + $error = 'Tab found before comment text; expected "// %s" but found "%s"'; + $data = [ + ltrim(substr($comment, 2)), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'TabBefore', $data); + } else if ($spaceCount === 0) { + $error = 'No space found before comment text; expected "// %s" but found "%s"'; + $data = [ + substr($comment, 2), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'NoSpaceBefore', $data); + } else if ($spaceCount > 1) { + $error = 'Expected 1 space before comment text but found %s; use block comment if you need indentation'; + $data = [ + $spaceCount, + substr($comment, (2 + $spaceCount)), + $comment, + ]; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, 'SpacingBefore', $data); + }//end if + + if ($fix === true) { + $newComment = '// '.ltrim($tokens[$lastCommentToken]['content'], "/\t "); + $phpcsFile->fixer->replaceToken($lastCommentToken, $newComment); + } + + $commentText .= trim(substr($tokens[$lastCommentToken]['content'], 2)); + }//end foreach + + if ($commentText === '') { + $error = 'Blank comments are not allowed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, ''); + } + + return ($lastCommentToken + 1); + } + + if (preg_match('/^\p{Ll}/u', $commentText) === 1) { + $error = 'Inline comments must start with a capital letter'; + $phpcsFile->addError($error, $stackPtr, 'NotCapital'); + } + + // Only check the end of comment character if the start of the comment + // is a letter, indicating that the comment is just standard text. + if (preg_match('/^\p{L}/u', $commentText) === 1) { + $commentCloser = $commentText[(strlen($commentText) - 1)]; + $acceptedClosers = [ + 'full-stops' => '.', + 'exclamation marks' => '!', + 'or question marks' => '?', + ]; + + if (in_array($commentCloser, $acceptedClosers, true) === false) { + $error = 'Inline comments must end in %s'; + $ender = ''; + foreach ($acceptedClosers as $closerName => $symbol) { + $ender .= ' '.$closerName.','; + } + + $ender = trim($ender, ' ,'); + $data = [$ender]; + $phpcsFile->addError($error, $lastCommentToken, 'InvalidEndChar', $data); + } + } + + // Finally, the line below the last comment cannot be empty if this inline + // comment is on a line by itself. + if ($tokens[$previousContent]['line'] < $tokens[$stackPtr]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($lastCommentToken + 1), null, true); + if ($next === false) { + // Ignore if the comment is the last non-whitespace token in a file. + return ($lastCommentToken + 1); + } + + if ($tokens[$next]['code'] === T_DOC_COMMENT_OPEN_TAG) { + // If this inline comment is followed by a docblock, + // ignore spacing as docblock/function etc spacing rules + // are likely to conflict with our rules. + return ($lastCommentToken + 1); + } + + $errorCode = 'SpacingAfter'; + + if (isset($tokens[$stackPtr]['conditions']) === true) { + $conditions = $tokens[$stackPtr]['conditions']; + $type = end($conditions); + $conditionPtr = key($conditions); + + if (($type === T_FUNCTION || $type === T_CLOSURE) + && $tokens[$conditionPtr]['scope_closer'] === $next + ) { + $errorCode = 'SpacingAfterAtFunctionEnd'; + } + } + + for ($i = ($lastCommentToken + 1); $i < $phpcsFile->numTokens; $i++) { + if ($tokens[$i]['line'] === ($tokens[$lastCommentToken]['line'] + 1)) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + return ($lastCommentToken + 1); + } + } else if ($tokens[$i]['line'] > ($tokens[$lastCommentToken]['line'] + 1)) { + break; + } + } + + $error = 'There must be no blank line following an inline comment'; + $fix = $phpcsFile->addFixableError($error, $lastCommentToken, $errorCode); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($lastCommentToken + 1); $i < $next; $i++) { + if ($tokens[$i]['line'] === $tokens[$next]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + return ($lastCommentToken + 1); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php new file mode 100644 index 000000000..7c06e4294 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php @@ -0,0 +1,218 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LongConditionClosingCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The openers that we are interested in. + * + * @var integer[] + */ + private static $openers = [ + T_SWITCH, + T_IF, + T_FOR, + T_FOREACH, + T_WHILE, + T_TRY, + T_CASE, + T_MATCH, + ]; + + /** + * The length that a code block must be before + * requiring a closing comment. + * + * @var integer + */ + public $lineLimit = 20; + + /** + * The format the end comment should be in. + * + * The placeholder %s will be replaced with the type of condition opener. + * + * @var string + */ + public $commentFormat = '//end %s'; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_CLOSE_CURLY_BRACKET]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_condition']) === false) { + // No scope condition. It is a function closer. + return; + } + + $startCondition = $tokens[$tokens[$stackPtr]['scope_condition']]; + $startBrace = $tokens[$tokens[$stackPtr]['scope_opener']]; + $endBrace = $tokens[$stackPtr]; + + // We are only interested in some code blocks. + if (in_array($startCondition['code'], self::$openers, true) === false) { + return; + } + + if ($startCondition['code'] === T_IF) { + // If this is actually an ELSE IF, skip it as the brace + // will be checked by the original IF. + $else = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$stackPtr]['scope_condition'] - 1), null, true); + if ($tokens[$else]['code'] === T_ELSE) { + return; + } + + // IF statements that have an ELSE block need to use + // "end if" rather than "end else" or "end elseif". + do { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ELSE || $tokens[$nextToken]['code'] === T_ELSEIF) { + // Check for ELSE IF (2 tokens) as opposed to ELSEIF (1 token). + if ($tokens[$nextToken]['code'] === T_ELSE + && isset($tokens[$nextToken]['scope_closer']) === false + ) { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] !== T_IF + || isset($tokens[$nextToken]['scope_closer']) === false + ) { + // Not an ELSE IF or is an inline ELSE IF. + break; + } + } + + if (isset($tokens[$nextToken]['scope_closer']) === false) { + // There isn't going to be anywhere to print the "end if" comment + // because there is no closer. + return; + } + + // The end brace becomes the ELSE's end brace. + $stackPtr = $tokens[$nextToken]['scope_closer']; + $endBrace = $tokens[$stackPtr]; + } else { + break; + }//end if + } while (isset($tokens[$nextToken]['scope_closer']) === true); + }//end if + + if ($startCondition['code'] === T_TRY) { + // TRY statements need to check until the end of all CATCH statements. + do { + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$nextToken]['code'] === T_CATCH + || $tokens[$nextToken]['code'] === T_FINALLY + ) { + // The end brace becomes the CATCH end brace. + $stackPtr = $tokens[$nextToken]['scope_closer']; + $endBrace = $tokens[$stackPtr]; + } else { + break; + } + } while (isset($tokens[$nextToken]['scope_closer']) === true); + } + + if ($startCondition['code'] === T_MATCH) { + // Move the stackPtr to after the semicolon/comma if there is one. + $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextToken !== false + && ($tokens[$nextToken]['code'] === T_SEMICOLON + || $tokens[$nextToken]['code'] === T_COMMA) + ) { + $stackPtr = $nextToken; + } + } + + $lineDifference = ($endBrace['line'] - $startBrace['line']); + + $expected = sprintf($this->commentFormat, $startCondition['content']); + $comment = $phpcsFile->findNext([T_COMMENT], $stackPtr, null, false); + + if (($comment === false) || ($tokens[$comment]['line'] !== $endBrace['line'])) { + if ($lineDifference >= $this->lineLimit) { + $error = 'End comment for long condition not found; expected "%s"'; + $data = [$expected]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Missing', $data); + + if ($fix === true) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($next !== false && $tokens[$next]['line'] === $tokens[$stackPtr]['line']) { + $expected .= $phpcsFile->eolChar; + } + + $phpcsFile->fixer->addContent($stackPtr, $expected); + } + } + + return; + } + + if (($comment - $stackPtr) !== 1) { + $error = 'Space found before closing comment; expected "%s"'; + $data = [$expected]; + $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data); + } + + if (trim($tokens[$comment]['content']) !== $expected) { + $found = trim($tokens[$comment]['content']); + $error = 'Incorrect closing comment; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Invalid', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($comment, $expected.$phpcsFile->eolChar); + } + + return; + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php new file mode 100644 index 000000000..82b934a79 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php @@ -0,0 +1,129 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class PostStatementCommentSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * Exceptions to the rule. + * + * If post statement comments are found within the condition + * parenthesis of these structures, leave them alone. + * + * @var array + */ + private $controlStructureExceptions = [ + T_IF => true, + T_ELSEIF => true, + T_SWITCH => true, + T_WHILE => true, + T_FOR => true, + T_FOREACH => true, + T_MATCH => true, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') { + return; + } + + $commentLine = $tokens[$stackPtr]['line']; + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + + if ($lastContent === false + || $tokens[$lastContent]['line'] !== $commentLine + || $tokens[$stackPtr]['column'] === 1 + ) { + return; + } + + if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + + // Special case for JS files and PHP closures. + if ($tokens[$lastContent]['code'] === T_COMMA + || $tokens[$lastContent]['code'] === T_SEMICOLON + ) { + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($lastContent - 1), null, true); + if ($lastContent === false || $tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) { + return; + } + } + + // Special case for (trailing) comments within multi-line control structures. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + foreach ($nestedParens as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) === true + && isset($this->controlStructureExceptions[$tokens[$tokens[$open]['parenthesis_owner']]['code']]) === true + ) { + return; + } + } + } + + if ($phpcsFile->tokenizerType === 'PHP' + && preg_match('|^//[ \t]*@[^\s]+|', $tokens[$stackPtr]['content']) === 1 + ) { + $error = 'Annotations may not appear after statements'; + $phpcsFile->addError($error, $stackPtr, 'AnnotationFound'); + return; + } + + $error = 'Comments may not appear after statements'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($stackPtr); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php new file mode 100644 index 000000000..61ccbf7a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php @@ -0,0 +1,201 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; + +class VariableCommentSniff extends AbstractVariableSniff +{ + + + /** + * Called to process class member vars. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $ignore = [ + T_PUBLIC => T_PUBLIC, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_VAR => T_VAR, + T_STATIC => T_STATIC, + T_READONLY => T_READONLY, + T_WHITESPACE => T_WHITESPACE, + T_STRING => T_STRING, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_NAMESPACE => T_NAMESPACE, + T_NULLABLE => T_NULLABLE, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + T_NULL => T_NULL, + T_TRUE => T_TRUE, + T_FALSE => T_FALSE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + ]; + + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($ignore[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } + + if ($commentEnd === false + || ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG + && $tokens[$commentEnd]['code'] !== T_COMMENT) + ) { + $phpcsFile->addError('Missing member variable doc comment', $stackPtr, 'Missing'); + return; + } + + if ($tokens[$commentEnd]['code'] === T_COMMENT) { + $phpcsFile->addError('You must use "/**" style comments for a member variable comment', $stackPtr, 'WrongStyle'); + return; + } + + $commentStart = $tokens[$commentEnd]['comment_opener']; + + $foundVar = null; + foreach ($tokens[$commentStart]['comment_tags'] as $tag) { + if ($tokens[$tag]['content'] === '@var') { + if ($foundVar !== null) { + $error = 'Only one @var tag is allowed in a member variable comment'; + $phpcsFile->addError($error, $tag, 'DuplicateVar'); + } else { + $foundVar = $tag; + } + } else if ($tokens[$tag]['content'] === '@see') { + // Make sure the tag isn't empty. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) { + $error = 'Content missing for @see tag in member variable comment'; + $phpcsFile->addError($error, $tag, 'EmptySees'); + } + } else { + $error = '%s tag is not allowed in member variable comment'; + $data = [$tokens[$tag]['content']]; + $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data); + }//end if + }//end foreach + + // The @var tag is the only one we require. + if ($foundVar === null) { + $error = 'Missing @var tag in member variable comment'; + $phpcsFile->addError($error, $commentEnd, 'MissingVar'); + return; + } + + $firstTag = $tokens[$commentStart]['comment_tags'][0]; + if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') { + $error = 'The @var tag must be the first tag in a member variable comment'; + $phpcsFile->addError($error, $foundVar, 'VarOrder'); + } + + // Make sure the tag isn't empty and has the correct padding. + $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd); + if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) { + $error = 'Content missing for @var tag in member variable comment'; + $phpcsFile->addError($error, $foundVar, 'EmptyVar'); + return; + } + + // Support both a var type and a description. + preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $tokens[($foundVar + 2)]['content'], $varParts); + if (isset($varParts[1]) === false) { + return; + } + + $varType = $varParts[1]; + + // Check var type (can be multiple, separated by '|'). + $typeNames = explode('|', $varType); + $suggestedNames = []; + foreach ($typeNames as $typeName) { + $suggestedName = Common::suggestType($typeName); + if (in_array($suggestedName, $suggestedNames, true) === false) { + $suggestedNames[] = $suggestedName; + } + } + + $suggestedType = implode('|', $suggestedNames); + if ($varType !== $suggestedType) { + $error = 'Expected "%s" but found "%s" for @var tag in member variable comment'; + $data = [ + $suggestedType, + $varType, + ]; + $fix = $phpcsFile->addFixableError($error, $foundVar, 'IncorrectVarType', $data); + if ($fix === true) { + $replacement = $suggestedType; + if (empty($varParts[2]) === false) { + $replacement .= $varParts[2]; + } + + $phpcsFile->fixer->replaceToken(($foundVar + 2), $replacement); + unset($replacement); + } + } + + }//end processMemberVar() + + + /** + * Called to process a normal variable. + * + * Not required for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + + }//end processVariable() + + + /** + * Called to process variables found in double quoted strings. + * + * Not required for this sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found. + * @param int $stackPtr The position where the double quoted + * string was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php new file mode 100644 index 000000000..06fd3edcc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php @@ -0,0 +1,337 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlSignatureSniff implements Sniff +{ + + /** + * How many spaces should precede the colon if using alternative syntax. + * + * @var integer + */ + public $requiredSpacesBeforeColon = 1; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_TRY, + T_CATCH, + T_FINALLY, + T_DO, + T_WHILE, + T_FOR, + T_IF, + T_FOREACH, + T_ELSE, + T_ELSEIF, + T_SWITCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($nextNonEmpty === false) { + return; + } + + $isAlternative = false; + if (isset($tokens[$stackPtr]['scope_opener']) === true + && $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON + ) { + $isAlternative = true; + } + + // Single space after the keyword. + $expected = 1; + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false && $isAlternative === true) { + // Catching cases like: + // if (condition) : ... else: ... endif + // where there is no condition. + $expected = (int) $this->requiredSpacesBeforeColon; + } + + $found = 1; + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $found = 0; + } else if ($tokens[($stackPtr + 1)]['content'] !== ' ') { + if (strpos($tokens[($stackPtr + 1)]['content'], $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + } + + if ($found !== $expected) { + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + $error = 'Expected %s space%s after %s keyword; %s found'; + $data = [ + $expected, + $pluralizeSpace, + strtoupper($tokens[$stackPtr]['content']), + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $expected)); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), str_repeat(' ', $expected)); + } + } + }//end if + + // Single space after closing parenthesis. + if (isset($tokens[$stackPtr]['parenthesis_closer']) === true + && isset($tokens[$stackPtr]['scope_opener']) === true + ) { + $expected = 1; + if ($isAlternative === true) { + $expected = (int) $this->requiredSpacesBeforeColon; + } + + $closer = $tokens[$stackPtr]['parenthesis_closer']; + $opener = $tokens[$stackPtr]['scope_opener']; + $content = $phpcsFile->getTokensAsString(($closer + 1), ($opener - $closer - 1)); + + if (trim($content) === '') { + if (strpos($content, $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = strlen($content); + } + } else { + $found = '"'.str_replace($phpcsFile->eolChar, '\n', $content).'"'; + } + + if ($found !== $expected) { + $pluralizeSpace = 's'; + if ($expected === 1) { + $pluralizeSpace = ''; + } + + $error = 'Expected %s space%s after closing parenthesis; found %s'; + $data = [ + $expected, + $pluralizeSpace, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceAfterCloseParenthesis', $data); + if ($fix === true) { + $padding = str_repeat(' ', $expected); + if ($closer === ($opener - 1)) { + $phpcsFile->fixer->addContent($closer, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + if (trim($content) === '') { + $phpcsFile->fixer->addContent($closer, $padding); + if ($found !== 0) { + for ($i = ($closer + 1); $i < $opener; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } else { + $phpcsFile->fixer->addContent($closer, $padding.$tokens[$opener]['content']); + $phpcsFile->fixer->replaceToken($opener, ''); + + if ($tokens[$opener]['line'] !== $tokens[$closer]['line']) { + $next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$opener]['line']) { + for ($i = ($opener + 1); $i < $next; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + } + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + }//end if + + // Single newline after opening brace. + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $opener = $tokens[$stackPtr]['scope_opener']; + for ($next = ($opener + 1); $next < $phpcsFile->numTokens; $next++) { + $code = $tokens[$next]['code']; + + if ($code === T_WHITESPACE + || ($code === T_INLINE_HTML + && trim($tokens[$next]['content']) === '') + ) { + continue; + } + + // Skip all empty tokens on the same line as the opener. + if ($tokens[$next]['line'] === $tokens[$opener]['line'] + && (isset(Tokens::$emptyTokens[$code]) === true + || $code === T_CLOSE_TAG) + ) { + continue; + } + + // We found the first bit of a code, or a comment on the + // following line. + break; + }//end for + + if ($tokens[$next]['line'] === $tokens[$opener]['line']) { + $error = 'Newline required after opening brace'; + $fix = $phpcsFile->addFixableError($error, $opener, 'NewlineAfterOpenBrace'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($opener + 1); $i < $next; $i++) { + if (trim($tokens[$i]['content']) !== '') { + break; + } + + // Remove whitespace. + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addContent($opener, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else if ($tokens[$stackPtr]['code'] === T_WHILE) { + // Zero spaces after parenthesis closer, but only if followed by a semicolon. + $closer = $tokens[$stackPtr]['parenthesis_closer']; + $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($closer + 1), null, true); + if ($nextNonEmpty !== false && $tokens[$nextNonEmpty]['code'] === T_SEMICOLON) { + $found = 0; + if ($tokens[($closer + 1)]['code'] === T_WHITESPACE) { + if (strpos($tokens[($closer + 1)]['content'], $phpcsFile->eolChar) !== false) { + $found = 'newline'; + } else { + $found = $tokens[($closer + 1)]['length']; + } + } + + if ($found !== 0) { + $error = 'Expected 0 spaces before semicolon; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceBeforeSemicolon', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closer + 1), ''); + } + } + } + }//end if + + // Only want to check multi-keyword structures from here on. + if ($tokens[$stackPtr]['code'] === T_WHILE) { + if (isset($tokens[$stackPtr]['scope_closer']) !== false) { + return; + } + + $closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($closer === false + || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET + || $tokens[$tokens[$closer]['scope_condition']]['code'] !== T_DO + ) { + return; + } + } else if ($tokens[$stackPtr]['code'] === T_ELSE + || $tokens[$stackPtr]['code'] === T_ELSEIF + || $tokens[$stackPtr]['code'] === T_CATCH + || $tokens[$stackPtr]['code'] === T_FINALLY + ) { + if (isset($tokens[$stackPtr]['scope_opener']) === true + && $tokens[$tokens[$stackPtr]['scope_opener']]['code'] === T_COLON + ) { + // Special case for alternate syntax, where this token is actually + // the closer for the previous block, so there is no spacing to check. + return; + } + + $closer = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($closer === false || $tokens[$closer]['code'] !== T_CLOSE_CURLY_BRACKET) { + return; + } + } else { + return; + }//end if + + // Single space after closing brace. + $found = 1; + if ($tokens[($closer + 1)]['code'] !== T_WHITESPACE) { + $found = 0; + } else if ($tokens[$closer]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else if ($tokens[($closer + 1)]['content'] !== ' ') { + $found = $tokens[($closer + 1)]['length']; + } + + if ($found !== 1) { + $error = 'Expected 1 space after closing brace; %s found'; + $data = [$found]; + + if ($phpcsFile->findNext(Tokens::$commentTokens, ($closer + 1), $stackPtr) !== false) { + // Comment found between closing brace and keyword, don't auto-fix. + $phpcsFile->addError($error, $closer, 'SpaceAfterCloseBrace', $data); + return; + } + + $fix = $phpcsFile->addFixableError($error, $closer, 'SpaceAfterCloseBrace', $data); + if ($fix === true) { + if ($found === 0) { + $phpcsFile->fixer->addContent($closer, ' '); + } else { + $phpcsFile->fixer->replaceToken(($closer + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php new file mode 100644 index 000000000..3cdb901d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ElseIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ELSEIF]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Usage of ELSEIF not allowed; use ELSE IF instead'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, 'else if'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php new file mode 100644 index 000000000..456886b36 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php @@ -0,0 +1,236 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ForEachLoopDeclarationSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOREACH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); + if ($openingBracket === false) { + $error = 'Possible parse error: FOREACH has no opening parenthesis'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingOpenParenthesis'); + return; + } + + if (isset($tokens[$openingBracket]['parenthesis_closer']) === false) { + $error = 'Possible parse error: FOREACH has no closing parenthesis'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingCloseParenthesis'); + return; + } + + $closingBracket = $tokens[$openingBracket]['parenthesis_closer']; + + if ($this->requiredSpacesAfterOpen === 0 && $tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $error = 'Space found after opening bracket of FOREACH loop'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openingBracket + 1), ''); + } + } else if ($this->requiredSpacesAfterOpen > 0) { + $spaceAfterOpen = 0; + if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openingBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openingBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openingBracket + 1), $padding); + } + } + } + }//end if + + if ($this->requiredSpacesBeforeClose === 0 && $tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $error = 'Space found before closing bracket of FOREACH loop'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($closingBracket - 1), ''); + } + } else if ($this->requiredSpacesBeforeClose > 0) { + $spaceBeforeClose = 0; + if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closingBracket - 1)]['length']; + } + + if ($spaceBeforeClose !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closingBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($closingBracket - 1), $padding); + } + } + } + }//end if + + $asToken = $phpcsFile->findNext(T_AS, $openingBracket); + if ($asToken === false) { + $error = 'Possible parse error: FOREACH has no AS statement'; + $phpcsFile->addWarning($error, $stackPtr, 'MissingAs'); + return; + } + + $content = $tokens[$asToken]['content']; + if ($content !== strtolower($content)) { + $expected = strtolower($content); + $error = 'AS keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $asToken, 'AsNotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($asToken, $expected); + } + } + + $doubleArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, $asToken, $closingBracket); + + if ($doubleArrow !== false) { + if ($tokens[($doubleArrow - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "=>"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeArrow'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($doubleArrow, ' '); + } + } else { + if ($tokens[($doubleArrow - 1)]['length'] !== 1) { + $spaces = $tokens[($doubleArrow - 1)]['length']; + $error = 'Expected 1 space before "=>"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($doubleArrow - 1), ' '); + } + } + } + + if ($tokens[($doubleArrow + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "=>"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterArrow'); + if ($fix === true) { + $phpcsFile->fixer->addContent($doubleArrow, ' '); + } + } else { + if ($tokens[($doubleArrow + 1)]['length'] !== 1) { + $spaces = $tokens[($doubleArrow + 1)]['length']; + $error = 'Expected 1 space after "=>"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterArrow', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($doubleArrow + 1), ' '); + } + } + } + }//end if + + if ($tokens[($asToken - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "as"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAs'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($asToken, ' '); + } + } else { + if ($tokens[($asToken - 1)]['length'] !== 1) { + $spaces = $tokens[($asToken - 1)]['length']; + $error = 'Expected 1 space before "as"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAs', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($asToken - 1), ' '); + } + } + } + + if ($tokens[($asToken + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "as"; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAs'); + if ($fix === true) { + $phpcsFile->fixer->addContent($asToken, ' '); + } + } else { + if ($tokens[($asToken + 1)]['length'] !== 1) { + $spaces = $tokens[($asToken + 1)]['length']; + $error = 'Expected 1 space after "as"; %s found'; + $data = [$spaces]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAs', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($asToken + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php new file mode 100644 index 000000000..38313e166 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php @@ -0,0 +1,316 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ForLoopDeclarationSniff implements Sniff +{ + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FOR]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + $tokens = $phpcsFile->getTokens(); + + $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr); + if ($openingBracket === false || isset($tokens[$openingBracket]['parenthesis_closer']) === false) { + $error = 'Possible parse error: no opening/closing parenthesis for FOR keyword'; + $phpcsFile->addWarning($error, $stackPtr, 'NoOpenBracket'); + return; + } + + $closingBracket = $tokens[$openingBracket]['parenthesis_closer']; + + if ($this->requiredSpacesAfterOpen === 0 + && $tokens[($openingBracket + 1)]['code'] === T_WHITESPACE + ) { + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($openingBracket + 1), $closingBracket, true); + if ($this->ignoreNewlines === false + || $tokens[$nextNonWhiteSpace]['line'] === $tokens[$openingBracket]['line'] + ) { + $error = 'Whitespace found after opening bracket of FOR loop'; + $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($openingBracket + 1); $i < $closingBracket; $i++) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($this->requiredSpacesAfterOpen > 0) { + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($openingBracket + 1), $closingBracket, true); + $spaceAfterOpen = 0; + if ($tokens[$openingBracket]['line'] !== $tokens[$nextNonWhiteSpace]['line']) { + $spaceAfterOpen = 'newline'; + } else if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) { + $spaceAfterOpen = $tokens[($openingBracket + 1)]['length']; + } + + if ($spaceAfterOpen !== $this->requiredSpacesAfterOpen + && ($this->ignoreNewlines === false + || $spaceAfterOpen !== 'newline') + ) { + $error = 'Expected %s spaces after opening bracket; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $spaceAfterOpen, + ]; + $fix = $phpcsFile->addFixableError($error, $openingBracket, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($spaceAfterOpen === 0) { + $phpcsFile->fixer->addContent($openingBracket, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($openingBracket + 1), $padding); + for ($i = ($openingBracket + 2); $i < $nextNonWhiteSpace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingBracket - 1), $openingBracket, true); + $beforeClosefixable = true; + if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line'] + && isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true + ) { + $beforeClosefixable = false; + } + + if ($this->requiredSpacesBeforeClose === 0 + && $tokens[($closingBracket - 1)]['code'] === T_WHITESPACE + && ($this->ignoreNewlines === false + || $tokens[$prevNonWhiteSpace]['line'] === $tokens[$closingBracket]['line']) + ) { + $error = 'Whitespace found before closing bracket of FOR loop'; + + if ($beforeClosefixable === false) { + $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose'); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket - 1); $i > $openingBracket; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } else if ($this->requiredSpacesBeforeClose > 0) { + $spaceBeforeClose = 0; + if ($tokens[$closingBracket]['line'] !== $tokens[$prevNonWhiteSpace]['line']) { + $spaceBeforeClose = 'newline'; + } else if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) { + $spaceBeforeClose = $tokens[($closingBracket - 1)]['length']; + } + + if ($this->requiredSpacesBeforeClose !== $spaceBeforeClose + && ($this->ignoreNewlines === false + || $spaceBeforeClose !== 'newline') + ) { + $error = 'Expected %s spaces before closing bracket; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $spaceBeforeClose, + ]; + + if ($beforeClosefixable === false) { + $phpcsFile->addError($error, $closingBracket, 'SpacingBeforeClose', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'SpacingBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($spaceBeforeClose === 0) { + $phpcsFile->fixer->addContentBefore($closingBracket, $padding); + } else { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($closingBracket - 1), $padding); + for ($i = ($closingBracket - 2); $i > $prevNonWhiteSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + }//end if + }//end if + + /* + * Check whitespace around each of the semicolon tokens. + */ + + $semicolonCount = 0; + $semicolon = $openingBracket; + $targetNestinglevel = 0; + if (isset($tokens[$openingBracket]['conditions']) === true) { + $targetNestinglevel = count($tokens[$openingBracket]['conditions']); + } + + do { + $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($semicolon + 1), $closingBracket); + if ($semicolon === false) { + break; + } + + if (isset($tokens[$semicolon]['conditions']) === true + && count($tokens[$semicolon]['conditions']) > $targetNestinglevel + ) { + // Semicolon doesn't belong to the for(). + continue; + } + + ++$semicolonCount; + + $humanReadableCount = 'first'; + if ($semicolonCount !== 1) { + $humanReadableCount = 'second'; + } + + $humanReadableCode = ucfirst($humanReadableCount); + $data = [$humanReadableCount]; + + // Only examine the space before the first semicolon if the first expression is not empty. + // If it *is* empty, leave it up to the `SpacingAfterOpen` logic. + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($semicolon - 1), $openingBracket, true); + if ($semicolonCount !== 1 || $prevNonWhiteSpace !== $openingBracket) { + if ($tokens[($semicolon - 1)]['code'] === T_WHITESPACE) { + $error = 'Whitespace found before %s semicolon of FOR loop'; + $errorCode = 'SpacingBefore'.$humanReadableCode; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($semicolon - 1); $i > $prevNonWhiteSpace; $i--) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + } + + // Only examine the space after the second semicolon if the last expression is not empty. + // If it *is* empty, leave it up to the `SpacingBeforeClose` logic. + $nextNonWhiteSpace = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), ($closingBracket + 1), true); + if ($semicolonCount !== 2 || $nextNonWhiteSpace !== $closingBracket) { + if ($tokens[($semicolon + 1)]['code'] !== T_WHITESPACE + && $tokens[($semicolon + 1)]['code'] !== T_SEMICOLON + ) { + $error = 'Expected 1 space after %s semicolon of FOR loop; 0 found'; + $errorCode = 'NoSpaceAfter'.$humanReadableCode; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($semicolon, ' '); + } + } else if ($tokens[($semicolon + 1)]['code'] === T_WHITESPACE + && $tokens[$nextNonWhiteSpace]['code'] !== T_SEMICOLON + ) { + $spaces = $tokens[($semicolon + 1)]['length']; + if ($tokens[$semicolon]['line'] !== $tokens[$nextNonWhiteSpace]['line']) { + $spaces = 'newline'; + } + + if ($spaces !== 1 + && ($this->ignoreNewlines === false + || $spaces !== 'newline') + ) { + $error = 'Expected 1 space after %s semicolon of FOR loop; %s found'; + $errorCode = 'SpacingAfter'.$humanReadableCode; + $data[] = $spaces; + $fix = $phpcsFile->addFixableError($error, $semicolon, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($semicolon + 1), ' '); + for ($i = ($semicolon + 2); $i < $nextNonWhiteSpace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + } while ($semicolonCount < 2); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php new file mode 100644 index 000000000..ff39c847f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php @@ -0,0 +1,155 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class InlineIfDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_THEN]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = null; + $closeBracket = null; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parens = $tokens[$stackPtr]['nested_parenthesis']; + $openBracket = array_pop($parens); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + } + + // Find the beginning of the statement. If we don't find a + // semicolon (end of statement) or comma (end of array value) + // then assume the content before the closing parenthesis is the end. + $else = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1)); + $statementEnd = $phpcsFile->findNext([T_SEMICOLON, T_COMMA], ($else + 1), $closeBracket); + if ($statementEnd === false) { + $statementEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true); + } + + // Make sure it's all on the same line. + if ($tokens[$statementEnd]['line'] !== $tokens[$stackPtr]['line']) { + $error = 'Inline shorthand IF statement must be declared on a single line'; + $phpcsFile->addError($error, $stackPtr, 'NotSingleLine'); + return; + } + + // Make sure there are spaces around the question mark. + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$contentBefore]['code'] !== T_CLOSE_PARENTHESIS) { + $error = 'Inline shorthand IF statement requires brackets around comparison'; + $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); + } + + $spaceBefore = ($tokens[$stackPtr]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); + if ($spaceBefore !== 1) { + $error = 'Inline shorthand IF statement requires 1 space before THEN; %s found'; + $data = [$spaceBefore]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeThen', $data); + if ($fix === true) { + if ($spaceBefore === 0) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } + + // If there is no content between the ? and the : operators, then they are + // trying to replicate an elvis operator, even though PHP doesn't have one. + // In this case, we want no spaces between the two operators so ?: looks like + // an operator itself. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_INLINE_ELSE) { + $inlineElse = $next; + if ($inlineElse !== ($stackPtr + 1)) { + $error = 'Inline shorthand IF statement without THEN statement requires 0 spaces between THEN and ELSE'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ElvisSpacing'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + } else { + $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$stackPtr]['column'] + 1)); + if ($spaceAfter !== 1) { + $error = 'Inline shorthand IF statement requires 1 space after THEN; %s found'; + $data = [$spaceAfter]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterThen', $data); + if ($fix === true) { + if ($spaceAfter === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + + // Make sure the ELSE has the correct spacing. + $inlineElse = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1), $statementEnd, false); + $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($inlineElse - 1), null, true); + $spaceBefore = ($tokens[$inlineElse]['column'] - ($tokens[$contentBefore]['column'] + $tokens[$contentBefore]['length'])); + if ($spaceBefore !== 1) { + $error = 'Inline shorthand IF statement requires 1 space before ELSE; %s found'; + $data = [$spaceBefore]; + $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingBeforeElse', $data); + if ($fix === true) { + if ($spaceBefore === 0) { + $phpcsFile->fixer->addContentBefore($inlineElse, ' '); + } else { + $phpcsFile->fixer->replaceToken(($inlineElse - 1), ' '); + } + } + } + }//end if + + $contentAfter = $phpcsFile->findNext(T_WHITESPACE, ($inlineElse + 1), null, true); + $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$inlineElse]['column'] + 1)); + if ($spaceAfter !== 1) { + $error = 'Inline shorthand IF statement requires 1 space after ELSE; %s found'; + $data = [$spaceAfter]; + $fix = $phpcsFile->addFixableError($error, $inlineElse, 'SpacingAfterElse', $data); + if ($fix === true) { + if ($spaceAfter === 0) { + $phpcsFile->fixer->addContent($inlineElse, ' '); + } else { + $phpcsFile->fixer->replaceToken(($inlineElse + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php new file mode 100644 index 000000000..068563c03 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class LowercaseDeclarationSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSE, + T_ELSEIF, + T_FOREACH, + T_FOR, + T_DO, + T_SWITCH, + T_WHILE, + T_TRY, + T_CATCH, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php new file mode 100644 index 000000000..be46aed55 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php @@ -0,0 +1,304 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SwitchDeclarationSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * The number of spaces code should be indented. + * + * @var integer + */ + public $indent = 4; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SWITCH]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // We can't process SWITCH statements unless we know where they start and end. + if (isset($tokens[$stackPtr]['scope_opener']) === false + || isset($tokens[$stackPtr]['scope_closer']) === false + ) { + return; + } + + $switch = $tokens[$stackPtr]; + $nextCase = $stackPtr; + $caseAlignment = ($switch['column'] + $this->indent); + $caseCount = 0; + $foundDefault = false; + + while (($nextCase = $phpcsFile->findNext([T_CASE, T_DEFAULT, T_SWITCH], ($nextCase + 1), $switch['scope_closer'])) !== false) { + // Skip nested SWITCH statements; they are handled on their own. + if ($tokens[$nextCase]['code'] === T_SWITCH) { + $nextCase = $tokens[$nextCase]['scope_closer']; + continue; + } + + if ($tokens[$nextCase]['code'] === T_DEFAULT) { + $type = 'Default'; + $foundDefault = true; + } else { + $type = 'Case'; + $caseCount++; + } + + if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) { + $expected = strtolower($tokens[$nextCase]['content']); + $error = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + $expected, + $tokens[$nextCase]['content'], + ]; + + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'NotLower', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($nextCase, $expected); + } + } + + if ($tokens[$nextCase]['column'] !== $caseAlignment) { + $error = strtoupper($type).' keyword must be indented '.$this->indent.' spaces from SWITCH keyword'; + $fix = $phpcsFile->addFixableError($error, $nextCase, $type.'Indent'); + + if ($fix === true) { + $padding = str_repeat(' ', ($caseAlignment - 1)); + if ($tokens[$nextCase]['column'] === 1 + || $tokens[($nextCase - 1)]['code'] !== T_WHITESPACE + ) { + $phpcsFile->fixer->addContentBefore($nextCase, $padding); + } else { + $phpcsFile->fixer->replaceToken(($nextCase - 1), $padding); + } + } + } + + if ($type === 'Case' + && ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE' + || $tokens[($nextCase + 1)]['content'] !== ' ') + ) { + $error = 'CASE keyword must be followed by a single space'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpacingAfterCase'); + if ($fix === true) { + if ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE') { + $phpcsFile->fixer->addContent($nextCase, ' '); + } else { + $phpcsFile->fixer->replaceToken(($nextCase + 1), ' '); + } + } + } + + if (isset($tokens[$nextCase]['scope_opener']) === false) { + $error = 'Possible parse error: CASE missing opening colon'; + $phpcsFile->addWarning($error, $nextCase, 'MissingColon'); + continue; + } + + $opener = $tokens[$nextCase]['scope_opener']; + if ($tokens[($opener - 1)]['type'] === 'T_WHITESPACE') { + $error = 'There must be no space before the colon in a '.strtoupper($type).' statement'; + $fix = $phpcsFile->addFixableError($error, $nextCase, 'SpaceBeforeColon'.$type); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($opener - 1), ''); + } + } + + $nextBreak = $tokens[$nextCase]['scope_closer']; + if ($tokens[$nextBreak]['code'] === T_BREAK + || $tokens[$nextBreak]['code'] === T_RETURN + || $tokens[$nextBreak]['code'] === T_CONTINUE + || $tokens[$nextBreak]['code'] === T_THROW + || $tokens[$nextBreak]['code'] === T_EXIT + ) { + if ($tokens[$nextBreak]['scope_condition'] === $nextCase) { + // Only need to check a couple of things once, even if the + // break is shared between multiple case statements, or even + // the default case. + if ($tokens[$nextBreak]['column'] !== $caseAlignment) { + $error = 'Case breaking statement must be indented '.$this->indent.' spaces from SWITCH keyword'; + $fix = $phpcsFile->addFixableError($error, $nextBreak, 'BreakIndent'); + + if ($fix === true) { + $padding = str_repeat(' ', ($caseAlignment - 1)); + if ($tokens[$nextBreak]['column'] === 1 + || $tokens[($nextBreak - 1)]['code'] !== T_WHITESPACE + ) { + $phpcsFile->fixer->addContentBefore($nextBreak, $padding); + } else { + $phpcsFile->fixer->replaceToken(($nextBreak - 1), $padding); + } + } + } + + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($nextBreak - 1), $stackPtr, true); + if ($tokens[$prev]['line'] !== ($tokens[$nextBreak]['line'] - 1)) { + $error = 'Blank lines are not allowed before case breaking statements'; + $phpcsFile->addError($error, $nextBreak, 'SpacingBeforeBreak'); + } + + $nextLine = $tokens[$tokens[$stackPtr]['scope_closer']]['line']; + $semicolon = $phpcsFile->findEndOfStatement($nextBreak); + for ($i = ($semicolon + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $nextLine = $tokens[$i]['line']; + break; + } + } + + if ($type === 'Case') { + // Ensure the BREAK statement is followed by + // a single blank line, or the end switch brace. + if ($nextLine !== ($tokens[$semicolon]['line'] + 2) && $i !== $tokens[$stackPtr]['scope_closer']) { + $error = 'Case breaking statements must be followed by a single blank line'; + $fix = $phpcsFile->addFixableError($error, $nextBreak, 'SpacingAfterBreak'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($semicolon + 1); $i <= $tokens[$stackPtr]['scope_closer']; $i++) { + if ($tokens[$i]['line'] === $nextLine) { + $phpcsFile->fixer->addNewlineBefore($i); + break; + } + + if ($tokens[$i]['line'] === $tokens[$semicolon]['line']) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + } else { + // Ensure the BREAK statement is not followed by a blank line. + if ($nextLine !== ($tokens[$semicolon]['line'] + 1)) { + $error = 'Blank lines are not allowed after the DEFAULT case\'s breaking statement'; + $phpcsFile->addError($error, $nextBreak, 'SpacingAfterDefaultBreak'); + } + }//end if + + $caseLine = $tokens[$nextCase]['line']; + $nextLine = $tokens[$nextBreak]['line']; + for ($i = ($opener + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $nextLine = $tokens[$i]['line']; + break; + } + } + + if ($nextLine !== ($caseLine + 1)) { + $error = 'Blank lines are not allowed after '.strtoupper($type).' statements'; + $phpcsFile->addError($error, $nextCase, 'SpacingAfter'.$type); + } + }//end if + + if ($tokens[$nextBreak]['code'] === T_BREAK) { + if ($type === 'Case') { + // Ensure empty CASE statements are not allowed. + // They must have some code content in them. A comment is not enough. + // But count RETURN statements as valid content if they also + // happen to close the CASE statement. + $foundContent = false; + for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['code'] === T_CASE) { + $i = $tokens[$i]['scope_opener']; + continue; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + $foundContent = true; + break; + } + } + + if ($foundContent === false) { + $error = 'Empty CASE statements are not allowed'; + $phpcsFile->addError($error, $nextCase, 'EmptyCase'); + } + } else { + // Ensure empty DEFAULT statements are not allowed. + // They must (at least) have a comment describing why + // the default case is being ignored. + $foundContent = false; + for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) { + if ($tokens[$i]['type'] !== 'T_WHITESPACE') { + $foundContent = true; + break; + } + } + + if ($foundContent === false) { + $error = 'Comment required for empty DEFAULT case'; + $phpcsFile->addError($error, $nextCase, 'EmptyDefault'); + } + }//end if + }//end if + } else if ($type === 'Default') { + $error = 'DEFAULT case must have a breaking statement'; + $phpcsFile->addError($error, $nextCase, 'DefaultNoBreak'); + }//end if + }//end while + + if ($foundDefault === false) { + $error = 'All SWITCH statements must contain a DEFAULT case'; + $phpcsFile->addError($error, $stackPtr, 'MissingDefault'); + } + + if ($tokens[$switch['scope_closer']]['column'] !== $switch['column']) { + $error = 'Closing brace of SWITCH statement must be aligned with SWITCH keyword'; + $phpcsFile->addError($error, $switch['scope_closer'], 'CloseBraceAlign'); + } + + if ($caseCount === 0) { + $error = 'SWITCH statements must contain at least one CASE statement'; + $phpcsFile->addError($error, $stackPtr, 'MissingCase'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php new file mode 100644 index 000000000..652391f11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JSLintSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JSLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If jslint.js could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $rhinoPath = Config::getExecutablePath('rhino'); + $jslintPath = Config::getExecutablePath('jslint'); + if ($rhinoPath === null || $jslintPath === null) { + return $phpcsFile->numTokens; + } + + $fileName = $phpcsFile->getFilename(); + + $rhinoPath = Common::escapeshellcmd($rhinoPath); + $jslintPath = Common::escapeshellcmd($jslintPath); + + $cmd = "$rhinoPath \"$jslintPath\" ".escapeshellarg($fileName); + exec($cmd, $output, $retval); + + if (is_array($output) === true) { + foreach ($output as $finding) { + $matches = []; + $numMatches = preg_match('/Lint at line ([0-9]+).*:(.*)$/', $finding, $matches); + if ($numMatches === 0) { + continue; + } + + $line = (int) $matches[1]; + $message = 'jslint says: '.trim($matches[2]); + $phpcsFile->addWarningOnLine($message, $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php new file mode 100644 index 000000000..031b2e39a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Common; + +class JavaScriptLintSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If Javascript Lint ran into trouble. + */ + public function process(File $phpcsFile, $stackPtr) + { + $jslPath = Config::getExecutablePath('jsl'); + if ($jslPath === null) { + return $phpcsFile->numTokens; + } + + $fileName = $phpcsFile->getFilename(); + + $cmd = '"'.Common::escapeshellcmd($jslPath).'" -nologo -nofilelisting -nocontext -nosummary -output-format __LINE__:__ERROR__ -process '.escapeshellarg($fileName); + $msg = exec($cmd, $output, $retval); + + // Variable $exitCode is the last line of $output if no error occurs, on + // error it is numeric. Try to handle various error conditions and + // provide useful error reporting. + if ($retval === 2 || $retval === 4) { + if (is_array($output) === true) { + $msg = implode('\n', $output); + } + + throw new RuntimeException("Failed invoking JavaScript Lint, retval was [$retval], output was [$msg]"); + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + $split = strpos($finding, ':'); + $line = substr($finding, 0, $split); + $message = substr($finding, ($split + 1)); + $phpcsFile->addWarningOnLine(trim($message), $line, 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php new file mode 100644 index 000000000..aceecffd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php @@ -0,0 +1,68 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FileExtensionSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $fileName = $phpcsFile->getFilename(); + $extension = substr($fileName, strrpos($fileName, '.')); + $nextClass = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM], $stackPtr); + + if ($nextClass !== false) { + $phpcsFile->recordMetric($stackPtr, 'File extension for class files', $extension); + if ($extension === '.php') { + $error = '%s found in ".php" file; use ".inc" extension instead'; + $data = [ucfirst($tokens[$nextClass]['content'])]; + $phpcsFile->addError($error, $stackPtr, 'ClassFound', $data); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'File extension for non-class files', $extension); + if ($extension === '.inc') { + $error = 'No interface or class found in ".inc" file; use ".php" extension instead'; + $phpcsFile->addError($error, $stackPtr, 'NoClass'); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php new file mode 100644 index 000000000..44429012a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php @@ -0,0 +1,402 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Formatting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorBracketSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$operators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$stackPtr]['code'] === T_PLUS) { + // JavaScript uses the plus operator for string concatenation as well + // so we cannot accurately determine if it is a string concat or addition. + // So just ignore it. + return; + } + + // If the & is a reference, then we don't want to check for brackets. + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr) === true) { + return; + } + + // There is one instance where brackets aren't needed, which involves + // the minus sign being used to assign a negative number to a variable. + if ($tokens[$stackPtr]['code'] === T_MINUS) { + // Check to see if we are trying to return -n. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_RETURN) { + return; + } + + $number = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$number]['code'] === T_LNUMBER || $tokens[$number]['code'] === T_DNUMBER) { + $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($previous !== false) { + $isAssignment = isset(Tokens::$assignmentTokens[$tokens[$previous]['code']]); + $isEquality = isset(Tokens::$equalityTokens[$tokens[$previous]['code']]); + $isComparison = isset(Tokens::$comparisonTokens[$tokens[$previous]['code']]); + $isUnary = isset(Tokens::$operators[$tokens[$previous]['code']]); + if ($isAssignment === true || $isEquality === true || $isComparison === true || $isUnary === true) { + // This is a negative assignment or comparison. + // We need to check that the minus and the number are + // adjacent. + if (($number - $stackPtr) !== 1) { + $error = 'No space allowed between minus sign and number'; + $phpcsFile->addError($error, $stackPtr, 'SpacingAfterMinus'); + } + + return; + } + } + } + }//end if + + $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true, null, true); + if ($previousToken !== false) { + // A list of tokens that indicate that the token is not + // part of an arithmetic operation. + $invalidTokens = [ + T_COMMA => true, + T_COLON => true, + T_OPEN_PARENTHESIS => true, + T_OPEN_SQUARE_BRACKET => true, + T_OPEN_CURLY_BRACKET => true, + T_OPEN_SHORT_ARRAY => true, + T_CASE => true, + T_EXIT => true, + T_MATCH_ARROW => true, + ]; + + if (isset($invalidTokens[$tokens[$previousToken]['code']]) === true) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_OR + && isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $brackets = $tokens[$stackPtr]['nested_parenthesis']; + $lastBracket = array_pop($brackets); + if (isset($tokens[$lastBracket]['parenthesis_owner']) === true + && $tokens[$tokens[$lastBracket]['parenthesis_owner']]['code'] === T_CATCH + ) { + // This is a pipe character inside a catch statement, so it is acting + // as an exception type separator and not an arithmetic operation. + return; + } + } + + // Tokens that are allowed inside a bracketed operation. + $allowed = [ + T_VARIABLE, + T_LNUMBER, + T_DNUMBER, + T_STRING, + T_WHITESPACE, + T_NS_SEPARATOR, + T_THIS, + T_SELF, + T_STATIC, + T_PARENT, + T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + T_MODULUS, + T_NONE, + T_BITWISE_NOT, + ]; + + $allowed += Tokens::$operators; + + $lastBracket = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true); + foreach ($parenthesis as $bracket => $endBracket) { + $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($bracket - 1), null, true); + $prevCode = $tokens[$prevToken]['code']; + + if ($prevCode === T_ISSET) { + // This operation is inside an isset() call, but has + // no bracket of it's own. + break; + } + + if ($prevCode === T_STRING || $prevCode === T_SWITCH || $prevCode === T_MATCH) { + // We allow simple operations to not be bracketed. + // For example, ceil($one / $two). + for ($prev = ($stackPtr - 1); $prev > $bracket; $prev--) { + if (in_array($tokens[$prev]['code'], $allowed, true) === true) { + continue; + } + + if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) { + $prev = $tokens[$prev]['parenthesis_opener']; + } else { + break; + } + } + + if ($prev !== $bracket) { + break; + } + + for ($next = ($stackPtr + 1); $next < $endBracket; $next++) { + if (in_array($tokens[$next]['code'], $allowed, true) === true) { + continue; + } + + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + $next = $tokens[$next]['parenthesis_closer']; + } else { + break; + } + } + + if ($next !== $endBracket) { + break; + } + }//end if + + if (in_array($prevCode, Tokens::$scopeOpeners, true) === true) { + // This operation is inside a control structure like FOREACH + // or IF, but has no bracket of it's own. + // The only control structures allowed to do this are SWITCH and MATCH. + if ($prevCode !== T_SWITCH && $prevCode !== T_MATCH) { + break; + } + } + + if ($prevCode === T_OPEN_PARENTHESIS) { + // These are two open parenthesis in a row. If the current + // one doesn't enclose the operator, go to the previous one. + if ($endBracket < $stackPtr) { + continue; + } + } + + $lastBracket = $bracket; + break; + }//end foreach + }//end if + + if ($lastBracket === false) { + // It is not in a bracketed statement at all. + $this->addMissingBracketsError($phpcsFile, $stackPtr); + return; + } else if ($tokens[$lastBracket]['parenthesis_closer'] < $stackPtr) { + // There are a set of brackets in front of it that don't include it. + $this->addMissingBracketsError($phpcsFile, $stackPtr); + return; + } else { + // We are enclosed in a set of bracket, so the last thing to + // check is that we are not also enclosed in square brackets + // like this: ($array[$index + 1]), which is invalid. + $brackets = [ + T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET, + ]; + + $squareBracket = $phpcsFile->findPrevious($brackets, ($stackPtr - 1), $lastBracket); + if ($squareBracket !== false && $tokens[$squareBracket]['code'] === T_OPEN_SQUARE_BRACKET) { + $closeSquareBracket = $phpcsFile->findNext($brackets, ($stackPtr + 1)); + if ($closeSquareBracket !== false && $tokens[$closeSquareBracket]['code'] === T_CLOSE_SQUARE_BRACKET) { + $this->addMissingBracketsError($phpcsFile, $stackPtr); + } + } + + return; + }//end if + + $lastAssignment = $phpcsFile->findPrevious(Tokens::$assignmentTokens, $stackPtr, null, false, null, true); + if ($lastAssignment !== false && $lastAssignment > $lastBracket) { + $this->addMissingBracketsError($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Add and fix the missing brackets error. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function addMissingBracketsError($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $allowed = [ + T_VARIABLE => true, + T_LNUMBER => true, + T_DNUMBER => true, + T_STRING => true, + T_CONSTANT_ENCAPSED_STRING => true, + T_DOUBLE_QUOTED_STRING => true, + T_WHITESPACE => true, + T_NS_SEPARATOR => true, + T_THIS => true, + T_SELF => true, + T_STATIC => true, + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_DOUBLE_COLON => true, + T_MODULUS => true, + T_ISSET => true, + T_ARRAY => true, + T_NONE => true, + T_BITWISE_NOT => true, + ]; + + // Find the first token in the expression. + for ($before = ($stackPtr - 1); $before > 0; $before--) { + // Special case for plus operators because we can't tell if they are used + // for addition or string contact. So assume string concat to be safe. + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$before]['code'] === T_PLUS) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$before]['code']]) === true + || isset(Tokens::$operators[$tokens[$before]['code']]) === true + || isset(Tokens::$castTokens[$tokens[$before]['code']]) === true + || isset($allowed[$tokens[$before]['code']]) === true + ) { + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_PARENTHESIS) { + $before = $tokens[$before]['parenthesis_opener']; + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_SQUARE_BRACKET) { + $before = $tokens[$before]['bracket_opener']; + continue; + } + + if ($tokens[$before]['code'] === T_CLOSE_SHORT_ARRAY) { + $before = $tokens[$before]['bracket_opener']; + continue; + } + + break; + }//end for + + $before = $phpcsFile->findNext(Tokens::$emptyTokens, ($before + 1), null, true); + + // A few extra tokens are allowed to be on the right side of the expression. + $allowed[T_EQUAL] = true; + $allowed[T_NEW] = true; + + // Find the last token in the expression. + for ($after = ($stackPtr + 1); $after < $phpcsFile->numTokens; $after++) { + // Special case for plus operators because we can't tell if they are used + // for addition or string concat. So assume string concat to be safe. + if ($phpcsFile->tokenizerType === 'JS' && $tokens[$after]['code'] === T_PLUS) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$after]['code']]) === true + || isset(Tokens::$operators[$tokens[$after]['code']]) === true + || isset(Tokens::$castTokens[$tokens[$after]['code']]) === true + || isset($allowed[$tokens[$after]['code']]) === true + ) { + continue; + } + + if ($tokens[$after]['code'] === T_OPEN_PARENTHESIS) { + if (isset($tokens[$after]['parenthesis_closer']) === false) { + // Live coding/parse error. Ignore. + return; + } + + $after = $tokens[$after]['parenthesis_closer']; + continue; + } + + if (($tokens[$after]['code'] === T_OPEN_SQUARE_BRACKET + || $tokens[$after]['code'] === T_OPEN_SHORT_ARRAY) + ) { + if (isset($tokens[$after]['bracket_closer']) === false) { + // Live coding/parse error. Ignore. + return; + } + + $after = $tokens[$after]['bracket_closer']; + continue; + } + + break; + }//end for + + $after = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($after - 1), null, true); + + $error = 'Operation must be bracketed'; + if ($before === $after || $before === $stackPtr || $after === $stackPtr) { + $phpcsFile->addError($error, $stackPtr, 'MissingBrackets'); + return; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'MissingBrackets'); + if ($fix === true) { + // Can only fix this error if both tokens are available for fixing. + // Adding one bracket without the other will create parse errors. + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($before, '('.$tokens[$before]['content']); + $phpcsFile->fixer->replaceToken($after, $tokens[$after]['content'].')'); + $phpcsFile->fixer->endChangeset(); + } + + }//end addMissingBracketsError() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php new file mode 100644 index 000000000..7357a507e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php @@ -0,0 +1,398 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionDeclarationArgumentSpacingSniff implements Sniff +{ + + /** + * How many spaces should surround the equals signs. + * + * @var integer + */ + public $equalsSpacing = 0; + + /** + * How many spaces should follow the opening bracket. + * + * @var integer + */ + public $requiredSpacesAfterOpen = 0; + + /** + * How many spaces should precede the closing bracket. + * + * @var integer + */ + public $requiredSpacesBeforeClose = 0; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + T_FN, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false + || isset($tokens[$stackPtr]['parenthesis_closer']) === false + || $tokens[$stackPtr]['parenthesis_opener'] === null + || $tokens[$stackPtr]['parenthesis_closer'] === null + ) { + return; + } + + $this->equalsSpacing = (int) $this->equalsSpacing; + $this->requiredSpacesAfterOpen = (int) $this->requiredSpacesAfterOpen; + $this->requiredSpacesBeforeClose = (int) $this->requiredSpacesBeforeClose; + + $this->processBracket($phpcsFile, $tokens[$stackPtr]['parenthesis_opener']); + + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null); + $this->processBracket($phpcsFile, $openBracket); + } + } + + }//end process() + + + /** + * Processes the contents of a single set of brackets. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $openBracket The position of the open bracket + * in the stack. + * + * @return void + */ + public function processBracket($phpcsFile, $openBracket) + { + $tokens = $phpcsFile->getTokens(); + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + $multiLine = ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']); + + if (isset($tokens[$openBracket]['parenthesis_owner']) === true) { + $stackPtr = $tokens[$openBracket]['parenthesis_owner']; + } else { + $stackPtr = $phpcsFile->findPrevious(T_USE, ($openBracket - 1)); + } + + $params = $phpcsFile->getMethodParameters($stackPtr); + + if (empty($params) === true) { + // Check spacing around parenthesis. + $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closeBracket, true); + if ($next === false) { + if (($closeBracket - $openBracket) !== 1) { + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($openBracket + 1)]['length']; + } + + $error = 'Expected 0 spaces between parenthesis of function declaration; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingBetween', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($openBracket + 1), ''); + } + } + + // No params, so we don't check normal spacing rules. + return; + } + }//end if + + foreach ($params as $paramNumber => $param) { + if ($param['pass_by_reference'] === true) { + $refToken = $param['reference_token']; + + $gap = 0; + if ($tokens[($refToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($refToken + 1)]['length']; + } + + if ($gap !== 0) { + $error = 'Expected 0 spaces after reference operator for argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $refToken, 'SpacingAfterReference', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($refToken + 1), ''); + } + } + }//end if + + if ($param['variable_length'] === true) { + $variadicToken = $param['variadic_token']; + + $gap = 0; + if ($tokens[($variadicToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($variadicToken + 1)]['length']; + } + + if ($gap !== 0) { + $error = 'Expected 0 spaces after variadic operator for argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $variadicToken, 'SpacingAfterVariadic', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($variadicToken + 1), ''); + } + } + }//end if + + if (isset($param['default_equal_token']) === true) { + $equalToken = $param['default_equal_token']; + + $spacesBefore = 0; + if (($equalToken - $param['token']) > 1) { + $spacesBefore = $tokens[($param['token'] + 1)]['length']; + } + + if ($spacesBefore !== $this->equalsSpacing) { + $error = 'Incorrect spacing between argument "%s" and equals sign; expected '.$this->equalsSpacing.' but found %s'; + $data = [ + $param['name'], + $spacesBefore, + ]; + + $fix = $phpcsFile->addFixableError($error, $equalToken, 'SpaceBeforeEquals', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->equalsSpacing); + if ($spacesBefore === 0) { + $phpcsFile->fixer->addContentBefore($equalToken, $padding); + } else { + $phpcsFile->fixer->replaceToken(($equalToken - 1), $padding); + } + } + }//end if + + $spacesAfter = 0; + if ($tokens[($equalToken + 1)]['code'] === T_WHITESPACE) { + $spacesAfter = $tokens[($equalToken + 1)]['length']; + } + + if ($spacesAfter !== $this->equalsSpacing) { + $error = 'Incorrect spacing between default value and equals sign for argument "%s"; expected '.$this->equalsSpacing.' but found %s'; + $data = [ + $param['name'], + $spacesAfter, + ]; + + $fix = $phpcsFile->addFixableError($error, $equalToken, 'SpaceAfterEquals', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->equalsSpacing); + if ($spacesAfter === 0) { + $phpcsFile->fixer->addContent($equalToken, $padding); + } else { + $phpcsFile->fixer->replaceToken(($equalToken + 1), $padding); + } + } + }//end if + }//end if + + if ($param['type_hint_token'] !== false) { + $typeHintToken = $param['type_hint_end_token']; + + $gap = 0; + if ($tokens[($typeHintToken + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($typeHintToken + 1)]['length']; + } + + if ($gap !== 1) { + $error = 'Expected 1 space between type hint and argument "%s"; %s found'; + $data = [ + $param['name'], + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $typeHintToken, 'SpacingAfterHint', $data); + if ($fix === true) { + if ($gap === 0) { + $phpcsFile->fixer->addContent($typeHintToken, ' '); + } else { + $phpcsFile->fixer->replaceToken(($typeHintToken + 1), ' '); + } + } + } + }//end if + + $commaToken = false; + if ($paramNumber > 0 && $params[($paramNumber - 1)]['comma_token'] !== false) { + $commaToken = $params[($paramNumber - 1)]['comma_token']; + } + + if ($commaToken !== false) { + if ($tokens[($commaToken - 1)]['code'] === T_WHITESPACE) { + $error = 'Expected 0 spaces between argument "%s" and comma; %s found'; + $data = [ + $params[($paramNumber - 1)]['name'], + $tokens[($commaToken - 1)]['length'], + ]; + + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpaceBeforeComma', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken - 1), ''); + } + } + + // Don't check spacing after the comma if it is the last content on the line. + $checkComma = true; + if ($multiLine === true) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($commaToken + 1), $closeBracket, true); + if ($tokens[$next]['line'] !== $tokens[$commaToken]['line']) { + $checkComma = false; + } + } + + if ($checkComma === true) { + if ($param['type_hint_token'] === false) { + $spacesAfter = 0; + if ($tokens[($commaToken + 1)]['code'] === T_WHITESPACE) { + $spacesAfter = $tokens[($commaToken + 1)]['length']; + } + + if ($spacesAfter === 0) { + $error = 'Expected 1 space between comma and argument "%s"; 0 found'; + $data = [$param['name']]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'NoSpaceBeforeArg', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($commaToken, ' '); + } + } else if ($spacesAfter !== 1) { + $error = 'Expected 1 space between comma and argument "%s"; %s found'; + $data = [ + $param['name'], + $spacesAfter, + ]; + + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpacingBeforeArg', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken + 1), ' '); + } + }//end if + } else { + $hint = $phpcsFile->getTokensAsString($param['type_hint_token'], (($param['type_hint_end_token'] - $param['type_hint_token']) + 1)); + if ($param['nullable_type'] === true) { + $hint = '?'.$hint; + } + + if ($tokens[($commaToken + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space between comma and type hint "%s"; 0 found'; + $data = [$hint]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'NoSpaceBeforeHint', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($commaToken, ' '); + } + } else { + $gap = $tokens[($commaToken + 1)]['length']; + if ($gap !== 1) { + $error = 'Expected 1 space between comma and type hint "%s"; %s found'; + $data = [ + $hint, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $commaToken, 'SpacingBeforeHint', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($commaToken + 1), ' '); + } + } + }//end if + }//end if + }//end if + }//end if + }//end foreach + + // Only check spacing around parenthesis for single line definitions. + if ($multiLine === true) { + return; + } + + $gap = 0; + if ($tokens[($closeBracket - 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($closeBracket - 1)]['length']; + } + + if ($gap !== $this->requiredSpacesBeforeClose) { + $error = 'Expected %s spaces before closing parenthesis; %s found'; + $data = [ + $this->requiredSpacesBeforeClose, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $closeBracket, 'SpacingBeforeClose', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesBeforeClose); + if ($gap === 0) { + $phpcsFile->fixer->addContentBefore($closeBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($closeBracket - 1), $padding); + } + } + } + + $gap = 0; + if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($openBracket + 1)]['length']; + } + + if ($gap !== $this->requiredSpacesAfterOpen) { + $error = 'Expected %s spaces after opening parenthesis; %s found'; + $data = [ + $this->requiredSpacesAfterOpen, + $gap, + ]; + $fix = $phpcsFile->addFixableError($error, $openBracket, 'SpacingAfterOpen', $data); + if ($fix === true) { + $padding = str_repeat(' ', $this->requiredSpacesAfterOpen); + if ($gap === 0) { + $phpcsFile->fixer->addContent($openBracket, $padding); + } else { + $phpcsFile->fixer->replaceToken(($openBracket + 1), $padding); + } + } + } + + }//end processBracket() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php new file mode 100644 index 000000000..fdb391c28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php @@ -0,0 +1,34 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Sniffs\AbstractPatternSniff; + +class FunctionDeclarationSniff extends AbstractPatternSniff +{ + + + /** + * Returns an array of patterns to check are correct. + * + * @return array + */ + protected function getPatterns() + { + return [ + 'function abc(...);', + 'function abc(...)', + 'abstract function abc(...);', + ]; + + }//end getPatterns() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php new file mode 100644 index 000000000..5eafbfdbb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionDuplicateArgumentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $foundVariables = []; + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + if ($tokens[$i]['code'] === T_VARIABLE) { + $variable = $tokens[$i]['content']; + if (in_array($variable, $foundVariables, true) === true) { + $error = 'Variable "%s" appears more than once in function declaration'; + $data = [$variable]; + $phpcsFile->addError($error, $i, 'Found', $data); + } else { + $foundVariables[] = $variable; + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php new file mode 100644 index 000000000..af3d902ec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class GlobalFunctionSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (empty($tokens[$stackPtr]['conditions']) === true) { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + return; + } + + // Special exception for __autoload as it needs to be global. + if ($functionName !== '__autoload') { + $error = 'Consider putting global function "%s" in a static class'; + $data = [$functionName]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php new file mode 100644 index 000000000..401b840c5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercaseFunctionKeywordsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $tokens = Tokens::$methodPrefixes; + $tokens[] = T_FUNCTION; + $tokens[] = T_CLOSURE; + $tokens[] = T_FN; + + return $tokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content !== $contentLc) { + $error = '%s keyword must be lowercase; expected "%s" but found "%s"'; + $data = [ + strtoupper($content), + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php new file mode 100644 index 000000000..e88d5c9a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php @@ -0,0 +1,262 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions; + +use PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionDeclarationSniff as PEARFunctionDeclarationSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MultiLineFunctionDeclarationSniff extends PEARFunctionDeclarationSniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Determine if this is a multi-line function declaration. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $openBracket The position of the opening bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return bool + */ + public function isMultiLineDeclaration($phpcsFile, $stackPtr, $openBracket, $tokens) + { + $bracketsToCheck = [$stackPtr => $openBracket]; + + // Closures may use the USE keyword and so be multi-line in this way. + if ($tokens[$stackPtr]['code'] === T_CLOSURE) { + $use = $phpcsFile->findNext(T_USE, ($tokens[$openBracket]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use !== false) { + $open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1)); + if ($open !== false) { + $bracketsToCheck[$use] = $open; + } + } + } + + foreach ($bracketsToCheck as $stackPtr => $openBracket) { + // If the first argument is on a new line, this is a multi-line + // function declaration, even if there is only one argument. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) { + return true; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + $end = $phpcsFile->findEndOfStatement($openBracket + 1); + while ($tokens[$end]['code'] === T_COMMA) { + // If the next bit of code is not on the same line, this is a + // multi-line function declaration. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next === false) { + continue(2); + } + + if ($tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + + $end = $phpcsFile->findEndOfStatement($next); + } + + // We've reached the last argument, so see if the next content + // (should be the close bracket) is also on the same line. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), $closeBracket, true); + if ($next !== false && $tokens[$next]['line'] !== $tokens[$end]['line']) { + return true; + } + }//end foreach + + return false; + + }//end isMultiLineDeclaration() + + + /** + * Processes single-line declarations. + * + * Just uses the Generic BSD-Allman brace sniff. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + // We do everything the parent sniff does, and a bit more because we + // define multi-line declarations a bit differently. + parent::processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens); + + $openingBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closingBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $prevNonWhiteSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($closingBracket - 1), $openingBracket, true); + if ($tokens[$prevNonWhiteSpace]['line'] !== $tokens[$closingBracket]['line']) { + $error = 'There must not be a newline before the closing parenthesis of a single-line function declaration'; + + if (isset(Tokens::$emptyTokens[$tokens[$prevNonWhiteSpace]['code']]) === true) { + $phpcsFile->addError($error, $closingBracket, 'CloseBracketNewLine'); + } else { + $fix = $phpcsFile->addFixableError($error, $closingBracket, 'CloseBracketNewLine'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($closingBracket - 1); $i > $openingBracket; $i--) { + if ($tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + + }//end processSingleLineDeclaration() + + + /** + * Processes multi-line declarations. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * + * @return void + */ + public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens) + { + // We do everything the parent sniff does, and a bit more. + parent::processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens); + + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $this->processBracket($phpcsFile, $openBracket, $tokens, 'function'); + + if ($tokens[$stackPtr]['code'] !== T_CLOSURE) { + return; + } + + $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']); + if ($use === false) { + return; + } + + $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null); + $this->processBracket($phpcsFile, $openBracket, $tokens, 'use'); + + }//end processMultiLineDeclaration() + + + /** + * Processes the contents of a single set of brackets. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $openBracket The position of the open bracket + * in the stack passed in $tokens. + * @param array $tokens The stack of tokens that make up + * the file. + * @param string $type The type of the token the brackets + * belong to (function or use). + * + * @return void + */ + public function processBracket($phpcsFile, $openBracket, $tokens, $type='function') + { + $errorPrefix = ''; + if ($type === 'use') { + $errorPrefix = 'Use'; + } + + $closeBracket = $tokens[$openBracket]['parenthesis_closer']; + + // The open bracket should be the last thing on the line. + if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($openBracket + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $error = 'The first parameter of a multi-line '.$type.' declaration must be on the line after the opening bracket'; + $fix = $phpcsFile->addFixableError($error, $next, $errorPrefix.'FirstParamSpacing'); + if ($fix === true) { + if ($tokens[$next]['line'] === $tokens[$openBracket]['line']) { + $phpcsFile->fixer->addNewline($openBracket); + } else { + $phpcsFile->fixer->beginChangeset(); + for ($x = $openBracket; $x < $next; $x++) { + if ($tokens[$x]['line'] === $tokens[$openBracket]['line']) { + continue; + } + + if ($tokens[$x]['line'] === $tokens[$next]['line']) { + break; + } + } + + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + // Each line between the brackets should contain a single parameter. + for ($i = ($openBracket + 1); $i < $closeBracket; $i++) { + // Skip brackets, like arrays, as they can contain commas. + if (isset($tokens[$i]['bracket_closer']) === true) { + $i = $tokens[$i]['bracket_closer']; + continue; + } + + if (isset($tokens[$i]['parenthesis_closer']) === true) { + $i = $tokens[$i]['parenthesis_closer']; + continue; + } + + if (isset($tokens[$i]['attribute_closer']) === true) { + $i = $tokens[$i]['attribute_closer']; + continue; + } + + if ($tokens[$i]['code'] !== T_COMMA) { + continue; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + if ($tokens[$next]['line'] === $tokens[$i]['line']) { + $error = 'Multi-line '.$type.' declarations must define one parameter per line'; + $fix = $phpcsFile->addFixableError($error, $next, $errorPrefix.'OneParamPerLine'); + if ($fix === true) { + $phpcsFile->fixer->addNewline($i); + } + } + }//end for + + }//end processBracket() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php new file mode 100644 index 000000000..2450ba7fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff as PEARValidFunctionNameSniff; +use PHP_CodeSniffer\Util\Common; + +class ValidFunctionNameSniff extends PEARValidFunctionNameSniff +{ + + + /** + * Processes the tokens outside the scope. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being processed. + * @param int $stackPtr The position where this token was + * found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + $functionName = $phpcsFile->getDeclarationName($stackPtr); + if ($functionName === null) { + return; + } + + $errorData = [$functionName]; + + // Does this function claim to be magical? + if (preg_match('|^__[^_]|', $functionName) !== 0) { + $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore'; + $phpcsFile->addError($error, $stackPtr, 'DoubleUnderscore', $errorData); + + $functionName = ltrim($functionName, '_'); + } + + if (Common::isCamelCaps($functionName, false, true, false) === false) { + $error = 'Function name "%s" is not in camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData); + } + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..79f9c4b23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,190 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + return; + } + + $objOperator = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR + || $tokens[$objOperator]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Check to see if we are using a variable from an object. + $var = $phpcsFile->findNext([T_WHITESPACE], ($objOperator + 1), null, true); + if ($tokens[$var]['code'] === T_STRING) { + $bracket = $phpcsFile->findNext([T_WHITESPACE], ($var + 1), null, true); + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + $objVarName = $tokens[$var]['content']; + + // There is no way for us to know if the var is public or + // private, so we have to ignore a leading underscore if there is + // one and just check the main part of the variable name. + $originalVarName = $objVarName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $var, 'MemberNotCamelCaps', $data); + } + }//end if + }//end if + }//end if + + $objOperator = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $objVarName = $varName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $data); + } + + return; + } + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $inClass = $phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + if ($inClass === true) { + $varName = substr($varName, 1); + } + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } + + }//end processVariable() + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + // Couldn't get any info about this variable, which + // generally means it is invalid or possibly has a parse + // error. Any errors will be reported by the core, so + // we can ignore it. + return; + } + + $public = ($memberProps['scope'] !== 'private'); + $errorData = [$varName]; + + if ($public === true) { + if (substr($varName, 0, 1) === '_') { + $error = '%s member variable "%s" must not contain a leading underscore'; + $data = [ + ucfirst($memberProps['scope']), + $errorData[0], + ]; + $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); + } + } else { + if (substr($varName, 0, 1) !== '_') { + $error = 'Private member variable "%s" must contain a leading underscore'; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData); + } + } + + // Remove a potential underscore prefix for testing CamelCaps. + $varName = ltrim($varName, '_'); + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $errorData); + } + + }//end processMemberVar() + + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match_all('|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + continue; + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'StringNotCamelCaps', $data); + } + } + } + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php new file mode 100644 index 000000000..b619924e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowObjectStringIndexSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_SQUARE_BRACKET]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check if the next non whitespace token is a string. + $index = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$index]['code'] !== T_CONSTANT_ENCAPSED_STRING) { + return; + } + + // Make sure it is the only thing in the square brackets. + $next = $phpcsFile->findNext(T_WHITESPACE, ($index + 1), null, true); + if ($tokens[$next]['code'] !== T_CLOSE_SQUARE_BRACKET) { + return; + } + + // Allow indexes that have dots in them because we can't write + // them in dot notation. + $content = trim($tokens[$index]['content'], '"\' '); + if (strpos($content, '.') !== false) { + return; + } + + // Also ignore reserved words. + if ($content === 'super') { + return; + } + + // Token before the opening square bracket cannot be a var name. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_STRING) { + $error = 'Object indexes must be written in dot notation'; + $phpcsFile->addError($error, $prev, 'Found'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php new file mode 100644 index 000000000..d408a07cc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php @@ -0,0 +1,85 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ObjectInstantiationSniff implements Sniff +{ + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [T_NEW]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $allowedTokens = Tokens::$emptyTokens; + $allowedTokens[] = T_BITWISE_AND; + + $prev = $phpcsFile->findPrevious($allowedTokens, ($stackPtr - 1), null, true); + + $allowedTokens = [ + T_EQUAL => T_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_FN_ARROW => T_FN_ARROW, + T_MATCH_ARROW => T_MATCH_ARROW, + T_THROW => T_THROW, + T_RETURN => T_RETURN, + ]; + + if (isset($allowedTokens[$tokens[$prev]['code']]) === true) { + return; + } + + $ternaryLikeTokens = [ + T_COALESCE => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + // For ternary like tokens, walk a little further back to see if it is preceded by + // one of the allowed tokens (within the same statement). + if (isset($ternaryLikeTokens[$tokens[$prev]['code']]) === true) { + $hasAllowedBefore = $phpcsFile->findPrevious($allowedTokens, ($prev - 1), null, false, null, true); + if ($hasAllowedBefore !== false) { + return; + } + } + + $error = 'New objects must be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'NotAssigned'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php new file mode 100644 index 000000000..dbbc1b842 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php @@ -0,0 +1,66 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ObjectMemberCommaSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [T_CLOSE_OBJECT]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_COMMA) { + $error = 'Last member of object must not be followed by a comma'; + $fix = $phpcsFile->addFixableError($error, $prev, 'Found'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($prev, ''); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php new file mode 100644 index 000000000..e9b41d691 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php @@ -0,0 +1,235 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ComparisonOperatorUsageSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * A list of valid comparison operators. + * + * @var array + */ + private static $validOps = [ + T_IS_IDENTICAL => true, + T_IS_NOT_IDENTICAL => true, + T_LESS_THAN => true, + T_GREATER_THAN => true, + T_IS_GREATER_OR_EQUAL => true, + T_IS_SMALLER_OR_EQUAL => true, + T_INSTANCEOF => true, + ]; + + /** + * A list of invalid operators with their alternatives. + * + * @var array> + */ + private static $invalidOps = [ + 'PHP' => [ + T_IS_EQUAL => '===', + T_IS_NOT_EQUAL => '!==', + T_BOOLEAN_NOT => '=== FALSE', + ], + 'JS' => [ + T_IS_EQUAL => '===', + T_IS_NOT_EQUAL => '!==', + ], + ]; + + + /** + * Registers the token types that this sniff wishes to listen to. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_ELSEIF, + T_INLINE_THEN, + T_WHILE, + T_FOR, + ]; + + }//end register() + + + /** + * Process the tokens that this sniff is listening for. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where the token + * was found. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenizer = $phpcsFile->tokenizerType; + + if ($tokens[$stackPtr]['code'] === T_INLINE_THEN) { + $end = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$end]['code'] !== T_CLOSE_PARENTHESIS) { + // This inline IF statement does not have its condition + // bracketed, so we need to guess where it starts. + for ($i = ($end - 1); $i >= 0; $i--) { + if ($tokens[$i]['code'] === T_SEMICOLON) { + // Stop here as we assume it is the end + // of the previous statement. + break; + } else if ($tokens[$i]['code'] === T_OPEN_TAG) { + // Stop here as this is the start of the file. + break; + } else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET) { + // Stop if this is the closing brace of + // a code block. + if (isset($tokens[$i]['scope_opener']) === true) { + break; + } + } else if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) { + // Stop if this is the opening brace of + // a code block. + if (isset($tokens[$i]['scope_closer']) === true) { + break; + } + } else if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + // Stop if this is the start of a pair of + // parentheses that surrounds the inline + // IF statement. + if (isset($tokens[$i]['parenthesis_closer']) === true + && $tokens[$i]['parenthesis_closer'] >= $stackPtr + ) { + break; + } + }//end if + }//end for + + $start = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true); + } else { + if (isset($tokens[$end]['parenthesis_opener']) === false) { + return; + } + + $start = $tokens[$end]['parenthesis_opener']; + }//end if + } else if ($tokens[$stackPtr]['code'] === T_FOR) { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $openingBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closingBracket = $tokens[$stackPtr]['parenthesis_closer']; + + $start = $phpcsFile->findNext(T_SEMICOLON, $openingBracket, $closingBracket); + $end = $phpcsFile->findNext(T_SEMICOLON, ($start + 1), $closingBracket); + if ($start === false || $end === false) { + return; + } + } else { + if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) { + return; + } + + $start = $tokens[$stackPtr]['parenthesis_opener']; + $end = $tokens[$stackPtr]['parenthesis_closer']; + }//end if + + $requiredOps = 0; + $foundOps = 0; + $foundBooleans = 0; + + $lastNonEmpty = $start; + + for ($i = $start; $i <= $end; $i++) { + $type = $tokens[$i]['code']; + if (isset(self::$invalidOps[$tokenizer][$type]) === true) { + $error = 'Operator %s prohibited; use %s instead'; + $data = [ + $tokens[$i]['content'], + self::$invalidOps[$tokenizer][$type], + ]; + $phpcsFile->addError($error, $i, 'NotAllowed', $data); + $foundOps++; + } else if (isset(self::$validOps[$type]) === true) { + $foundOps++; + } + + if ($type === T_OPEN_PARENTHESIS + && isset($tokens[$i]['parenthesis_closer']) === true + && isset(Tokens::$functionNameTokens[$tokens[$lastNonEmpty]['code']]) === true + ) { + $i = $tokens[$i]['parenthesis_closer']; + $lastNonEmpty = $i; + continue; + } + + if ($tokens[$i]['code'] === T_TRUE || $tokens[$i]['code'] === T_FALSE) { + $foundBooleans++; + } + + if ($phpcsFile->tokenizerType !== 'JS' + && ($tokens[$i]['code'] === T_BOOLEAN_AND + || $tokens[$i]['code'] === T_BOOLEAN_OR) + ) { + $requiredOps++; + + // When the instanceof operator is used with another operator + // like ===, you can get more ops than are required. + if ($foundOps > $requiredOps) { + $foundOps = $requiredOps; + } + + // If we get to here and we have not found the right number of + // comparison operators, then we must have had an implicit + // true operation i.e., if ($a) instead of the required + // if ($a === true), so let's add an error. + if ($requiredOps !== $foundOps) { + $error = 'Implicit true comparisons prohibited; use === TRUE instead'; + $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue'); + $foundOps++; + } + } + + if (isset(Tokens::$emptyTokens[$type]) === false) { + $lastNonEmpty = $i; + } + }//end for + + $requiredOps++; + + if ($phpcsFile->tokenizerType !== 'JS' + && $foundOps < $requiredOps + && ($requiredOps !== $foundBooleans) + ) { + $error = 'Implicit true comparisons prohibited; use === TRUE instead'; + $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue'); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php new file mode 100644 index 000000000..a39e44e12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php @@ -0,0 +1,231 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class IncrementDecrementUsageSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_INC, + T_DEC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_INC || $tokens[$stackPtr]['code'] === T_DEC) { + $this->processIncDec($phpcsFile, $stackPtr); + } else { + $this->processAssignment($phpcsFile, $stackPtr); + } + + }//end process() + + + /** + * Checks to ensure increment and decrement operators are not confusing. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processIncDec($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Work out where the variable is so we know where to + // start looking for other operators. + if ($tokens[($stackPtr - 1)]['code'] === T_VARIABLE + || ($tokens[($stackPtr - 1)]['code'] === T_STRING + && ($tokens[($stackPtr - 2)]['code'] === T_OBJECT_OPERATOR + || $tokens[($stackPtr - 2)]['code'] === T_NULLSAFE_OBJECT_OPERATOR)) + ) { + $start = ($stackPtr + 1); + } else { + $start = ($stackPtr + 2); + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true); + if ($next === false) { + return; + } + + if (isset(Tokens::$arithmeticTokens[$tokens[$next]['code']]) === true) { + $error = 'Increment and decrement operators cannot be used in an arithmetic operation'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + return; + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 3), null, true); + if ($prev === false) { + return; + } + + // Check if this is in a string concat. + if ($tokens[$next]['code'] === T_STRING_CONCAT || $tokens[$prev]['code'] === T_STRING_CONCAT) { + $error = 'Increment and decrement operators must be bracketed when used in string concatenation'; + $phpcsFile->addError($error, $stackPtr, 'NoBrackets'); + } + + }//end processIncDec() + + + /** + * Checks to ensure increment and decrement operators are used. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + protected function processAssignment($phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $assignedVar = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + // Not an assignment, return. + if ($tokens[$assignedVar]['code'] !== T_VARIABLE) { + return; + } + + $statementEnd = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SQUARE_BRACKET, T_CLOSE_CURLY_BRACKET], $stackPtr); + + // If there is anything other than variables, numbers, spaces or operators we need to return. + $find = Tokens::$emptyTokens; + $find[] = T_LNUMBER; + $find[] = T_VARIABLE; + $find[] = T_PLUS; + $find[] = T_MINUS; + $find[] = T_OPEN_PARENTHESIS; + + $noiseTokens = $phpcsFile->findNext($find, ($stackPtr + 1), $statementEnd, true); + if ($noiseTokens !== false) { + return; + } + + // If we are already using += or -=, we need to ignore + // the statement if a variable is being used. + if ($tokens[$stackPtr]['code'] !== T_EQUAL) { + $nextVar = $phpcsFile->findNext(T_VARIABLE, ($stackPtr + 1), $statementEnd); + if ($nextVar !== false) { + return; + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + $nextVar = $stackPtr; + $previousVariable = $stackPtr; + $variableCount = 0; + while (($nextVar = $phpcsFile->findNext(T_VARIABLE, ($nextVar + 1), $statementEnd)) !== false) { + $previousVariable = $nextVar; + $variableCount++; + } + + if ($variableCount !== 1) { + return; + } + + $nextVar = $previousVariable; + if ($tokens[$nextVar]['content'] !== $tokens[$assignedVar]['content']) { + return; + } + } + + // We have only one variable, and it's the same as what is being assigned, + // so we need to check what is being added or subtracted. + $nextNumber = $stackPtr; + $previousNumber = $stackPtr; + $numberCount = 0; + while (($nextNumber = $phpcsFile->findNext([T_LNUMBER], ($nextNumber + 1), $statementEnd, false)) !== false) { + $previousNumber = $nextNumber; + $numberCount++; + } + + if ($numberCount !== 1) { + return; + } + + $nextNumber = $previousNumber; + if ($tokens[$nextNumber]['content'] === '1') { + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + $opToken = $phpcsFile->findNext([T_PLUS, T_MINUS], ($nextVar + 1), $statementEnd); + if ($opToken === false) { + // Operator was before the variable, like: + // $var = 1 + $var; + // So we ignore it. + return; + } + + $operator = $tokens[$opToken]['content']; + } else { + $operator = substr($tokens[$stackPtr]['content'], 0, 1); + } + + // If we are adding or subtracting negative value, the operator + // needs to be reversed. + if ($tokens[$stackPtr]['code'] !== T_EQUAL) { + $negative = $phpcsFile->findPrevious(T_MINUS, ($nextNumber - 1), $stackPtr); + if ($negative !== false) { + if ($operator === '+') { + $operator = '-'; + } else { + $operator = '+'; + } + } + } + + $expected = $operator.$operator.$tokens[$assignedVar]['content']; + $found = $phpcsFile->getTokensAsString($assignedVar, ($statementEnd - $assignedVar + 1)); + + if ($operator === '+') { + $error = 'Increment'; + } else { + $error = 'Decrement'; + } + + $error .= " operators should be used where possible; found \"$found\" but expected \"$expected\""; + $phpcsFile->addError($error, $stackPtr, 'Found'); + }//end if + + }//end processAssignment() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php new file mode 100644 index 000000000..720e4724a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ValidLogicalOperatorsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_LOGICAL_AND, + T_LOGICAL_OR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $replacements = [ + 'and' => '&&', + 'or' => '||', + ]; + + $operator = strtolower($tokens[$stackPtr]['content']); + if (isset($replacements[$operator]) === false) { + return; + } + + $error = 'Logical operator "%s" is prohibited; use "%s" instead'; + $data = [ + $operator, + $replacements[$operator], + ]; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php new file mode 100644 index 000000000..c8e1a4030 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php @@ -0,0 +1,283 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CommentedOutCodeSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'CSS', + ]; + + /** + * If a comment is more than $maxPercentage% code, a warning will be shown. + * + * @var integer + */ + public $maxPercentage = 35; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_COMMENT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int|void Integer stack pointer to skip forward or void to continue + * normal file processing. + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore comments at the end of code blocks. + if (substr($tokens[$stackPtr]['content'], 0, 6) === '//end ') { + return; + } + + $content = ''; + $lastLineSeen = $tokens[$stackPtr]['line']; + $commentStyle = 'line'; + if (strpos($tokens[$stackPtr]['content'], '/*') === 0) { + $commentStyle = 'block'; + } + + $lastCommentBlockToken = $stackPtr; + for ($i = $stackPtr; $i < $phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) { + break; + } + + if ($tokens[$i]['code'] === T_WHITESPACE) { + continue; + } + + if (isset(Tokens::$phpcsCommentTokens[$tokens[$i]['code']]) === true) { + $lastLineSeen = $tokens[$i]['line']; + continue; + } + + if ($commentStyle === 'line' + && ($lastLineSeen + 1) <= $tokens[$i]['line'] + && strpos($tokens[$i]['content'], '/*') === 0 + ) { + // First non-whitespace token on a new line is start of a different style comment. + break; + } + + if ($commentStyle === 'line' + && ($lastLineSeen + 1) < $tokens[$i]['line'] + ) { + // Blank line breaks a '//' style comment block. + break; + } + + /* + Trim as much off the comment as possible so we don't + have additional whitespace tokens or comment tokens + */ + + $tokenContent = trim($tokens[$i]['content']); + $break = false; + + if ($commentStyle === 'line') { + if (substr($tokenContent, 0, 2) === '//') { + $tokenContent = substr($tokenContent, 2); + } + + if (substr($tokenContent, 0, 1) === '#') { + $tokenContent = substr($tokenContent, 1); + } + } else { + if (substr($tokenContent, 0, 3) === '/**') { + $tokenContent = substr($tokenContent, 3); + } + + if (substr($tokenContent, 0, 2) === '/*') { + $tokenContent = substr($tokenContent, 2); + } + + if (substr($tokenContent, -2) === '*/') { + $tokenContent = substr($tokenContent, 0, -2); + $break = true; + } + + if (substr($tokenContent, 0, 1) === '*') { + $tokenContent = substr($tokenContent, 1); + } + }//end if + + $content .= $tokenContent.$phpcsFile->eolChar; + $lastLineSeen = $tokens[$i]['line']; + + $lastCommentBlockToken = $i; + + if ($break === true) { + // Closer of a block comment found. + break; + } + }//end for + + // Ignore typical warning suppression annotations from other tools. + if (preg_match('`^\s*@[A-Za-z()\._-]+\s*$`', $content) === 1) { + return ($lastCommentBlockToken + 1); + } + + // Quite a few comments use multiple dashes, equals signs etc + // to frame comments and licence headers. + $content = preg_replace('/[-=#*]{2,}/', '-', $content); + + // Random numbers sitting inside the content can throw parse errors + // for invalid literals in PHP7+, so strip those. + $content = preg_replace('/\d+/', '', $content); + + $content = trim($content); + + if ($content === '') { + return ($lastCommentBlockToken + 1); + } + + if ($phpcsFile->tokenizerType === 'PHP') { + $content = ''; + } + + // Because we are not really parsing code, the tokenizer can throw all sorts + // of errors that don't mean anything, so ignore them. + $oldErrors = ini_get('error_reporting'); + ini_set('error_reporting', 0); + try { + $tokenizerClass = get_class($phpcsFile->tokenizer); + $tokenizer = new $tokenizerClass($content, $phpcsFile->config, $phpcsFile->eolChar); + $stringTokens = $tokenizer->getTokens(); + } catch (TokenizerException $e) { + // We couldn't check the comment, so ignore it. + ini_set('error_reporting', $oldErrors); + return ($lastCommentBlockToken + 1); + } + + ini_set('error_reporting', $oldErrors); + + $numTokens = count($stringTokens); + + /* + We know what the first two and last two tokens should be + (because we put them there) so ignore this comment if those + tokens were not parsed correctly. It obviously means this is not + valid code. + */ + + // First token is always the opening tag. + if ($stringTokens[0]['code'] !== T_OPEN_TAG) { + return ($lastCommentBlockToken + 1); + } else { + array_shift($stringTokens); + --$numTokens; + } + + // Last token is always the closing tag, unless something went wrong. + if (isset($stringTokens[($numTokens - 1)]) === false + || $stringTokens[($numTokens - 1)]['code'] !== T_CLOSE_TAG + ) { + return ($lastCommentBlockToken + 1); + } else { + array_pop($stringTokens); + --$numTokens; + } + + // Second last token is always whitespace or a comment, depending + // on the code inside the comment. + if ($phpcsFile->tokenizerType === 'PHP') { + if (isset(Tokens::$emptyTokens[$stringTokens[($numTokens - 1)]['code']]) === false) { + return ($lastCommentBlockToken + 1); + } + + if ($stringTokens[($numTokens - 1)]['code'] === T_WHITESPACE) { + array_pop($stringTokens); + --$numTokens; + } + } + + $emptyTokens = [ + T_WHITESPACE => true, + T_STRING => true, + T_STRING_CONCAT => true, + T_ENCAPSED_AND_WHITESPACE => true, + T_NONE => true, + T_COMMENT => true, + ]; + $emptyTokens += Tokens::$phpcsCommentTokens; + + $numCode = 0; + $numNonWhitespace = 0; + + for ($i = 0; $i < $numTokens; $i++) { + // Do not count comments. + if (isset($emptyTokens[$stringTokens[$i]['code']]) === false + // Commented out HTML/XML and other docs contain a lot of these + // characters, so it is best to not use them directly. + && isset(Tokens::$comparisonTokens[$stringTokens[$i]['code']]) === false + && isset(Tokens::$arithmeticTokens[$stringTokens[$i]['code']]) === false + && $stringTokens[$i]['code'] !== T_GOTO_LABEL + ) { + // Looks like code. + $numCode++; + } + + if ($stringTokens[$i]['code'] !== T_WHITESPACE) { + ++$numNonWhitespace; + } + } + + // Ignore comments with only two or less non-whitespace tokens. + // Sample size too small for a reliably determination. + if ($numNonWhitespace <= 2) { + return ($lastCommentBlockToken + 1); + } + + $percentCode = ceil((($numCode / $numTokens) * 100)); + if ($percentCode > $this->maxPercentage) { + // Just in case. + $percentCode = min(100, $percentCode); + + $error = 'This comment is %s%% valid code; is this commented out code?'; + $data = [$percentCode]; + $phpcsFile->addWarning($error, $stackPtr, 'Found', $data); + } + + return ($lastCommentBlockToken + 1); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php new file mode 100644 index 000000000..24dc1370d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowBooleanStatementSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + foreach ($tokens[$stackPtr]['nested_parenthesis'] as $open => $close) { + if (isset($tokens[$open]['parenthesis_owner']) === true) { + // Any owner means we are not just a simple statement. + return; + } + } + } + + $error = 'Boolean operators are not allowed outside of control structure conditions'; + $phpcsFile->addError($error, $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php new file mode 100644 index 000000000..57dabbf12 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php @@ -0,0 +1,112 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowComparisonAssignmentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore default value assignments in function definitions. + $function = $phpcsFile->findPrevious(T_FUNCTION, ($stackPtr - 1), null, false, null, true); + if ($function !== false) { + $opener = $tokens[$function]['parenthesis_opener']; + $closer = $tokens[$function]['parenthesis_closer']; + if ($opener < $stackPtr && $closer > $stackPtr) { + return; + } + } + + // Ignore values in array definitions or match structures. + $nextNonEmpty = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($stackPtr + 1), + null, + true + ); + + if ($nextNonEmpty !== false + && ($tokens[$nextNonEmpty]['code'] === T_ARRAY + || $tokens[$nextNonEmpty]['code'] === T_MATCH) + ) { + return; + } + + // Ignore function calls. + $ignore = [ + T_NULLSAFE_OBJECT_OPERATOR, + T_OBJECT_OPERATOR, + T_STRING, + T_VARIABLE, + T_WHITESPACE, + ]; + + $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_CLOSURE + || ($tokens[$next]['code'] === T_OPEN_PARENTHESIS + && $tokens[($next - 1)]['code'] === T_STRING) + ) { + // Code will look like: $var = myFunction( + // and will be ignored. + return; + } + + $endStatement = $phpcsFile->findEndOfStatement($stackPtr); + for ($i = ($stackPtr + 1); $i < $endStatement; $i++) { + if ((isset(Tokens::$comparisonTokens[$tokens[$i]['code']]) === true + && $tokens[$i]['code'] !== T_COALESCE) + || $tokens[$i]['code'] === T_INLINE_THEN + ) { + $error = 'The value of a comparison must not be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'AssignedComparison'); + break; + } + + if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_BOOLEAN_NOT + ) { + $error = 'The value of a boolean operation must not be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'AssignedBool'); + break; + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php new file mode 100644 index 000000000..f2620c7d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowInlineIfSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_INLINE_THEN]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $phpcsFile->addError('Inline IF statements are not allowed', $stackPtr, 'Found'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php new file mode 100644 index 000000000..2a953b462 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php @@ -0,0 +1,196 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class DisallowMultipleAssignmentsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EQUAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Ignore default value assignments in function definitions. + $function = $phpcsFile->findPrevious([T_FUNCTION, T_CLOSURE, T_FN], ($stackPtr - 1), null, false, null, true); + if ($function !== false) { + if (isset($tokens[$function]['parenthesis_closer']) === false) { + // Live coding/parse error. Bow out. + return; + } + + $opener = $tokens[$function]['parenthesis_opener']; + $closer = $tokens[$function]['parenthesis_closer']; + if ($opener < $stackPtr && $closer > $stackPtr) { + return; + } + } + + // Ignore assignments in WHILE loop conditions. + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nested = $tokens[$stackPtr]['nested_parenthesis']; + foreach ($nested as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === true + && $tokens[$tokens[$opener]['parenthesis_owner']]['code'] === T_WHILE + ) { + return; + } + } + } + + // Ignore member var definitions. + if (empty($tokens[$stackPtr]['conditions']) === false) { + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if (isset(Tokens::$ooScopeTokens[$tokens[$deepestScope]['code']]) === true) { + return; + } + } + + /* + The general rule is: + Find an equal sign and go backwards along the line. If you hit an + end bracket, skip to the opening bracket. When you find a variable, + stop. That variable must be the first non-empty token on the line + or in the statement. If not, throw an error. + */ + + for ($varToken = ($stackPtr - 1); $varToken >= 0; $varToken--) { + if (in_array($tokens[$varToken]['code'], [T_SEMICOLON, T_OPEN_CURLY_BRACKET, T_CLOSE_TAG], true) === true) { + // We've reached the previous statement, so we didn't find a variable. + return; + } + + // Skip brackets. + if (isset($tokens[$varToken]['parenthesis_opener']) === true && $tokens[$varToken]['parenthesis_opener'] < $varToken) { + $varToken = $tokens[$varToken]['parenthesis_opener']; + continue; + } + + if (isset($tokens[$varToken]['bracket_opener']) === true) { + $varToken = $tokens[$varToken]['bracket_opener']; + continue; + } + + if ($tokens[$varToken]['code'] === T_VARIABLE) { + $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($varToken - 1), null, true); + if ($tokens[$prevNonEmpty]['code'] === T_OBJECT_OPERATOR) { + // Dynamic property access, the real "start" variable still needs to be found. + $varToken = $prevNonEmpty; + continue; + } + + // We found our variable. + break; + } + }//end for + + if ($varToken <= 0) { + // Didn't find a variable. + return; + } + + $start = $phpcsFile->findStartOfStatement($varToken); + + $allowed = Tokens::$emptyTokens; + + $allowed[T_STRING] = T_STRING; + $allowed[T_NS_SEPARATOR] = T_NS_SEPARATOR; + $allowed[T_DOUBLE_COLON] = T_DOUBLE_COLON; + $allowed[T_ASPERAND] = T_ASPERAND; + $allowed[T_DOLLAR] = T_DOLLAR; + $allowed[T_SELF] = T_SELF; + $allowed[T_PARENT] = T_PARENT; + $allowed[T_STATIC] = T_STATIC; + + $varToken = $phpcsFile->findPrevious($allowed, ($varToken - 1), null, true); + + if ($varToken < $start + && $tokens[$varToken]['code'] !== T_OPEN_PARENTHESIS + && $tokens[$varToken]['code'] !== T_OPEN_SQUARE_BRACKET + ) { + $varToken = $start; + } + + // Ignore the first part of FOR loops as we are allowed to + // assign variables there even though the variable is not the + // first thing on the line. + if ($tokens[$varToken]['code'] === T_OPEN_PARENTHESIS && isset($tokens[$varToken]['parenthesis_owner']) === true) { + $owner = $tokens[$varToken]['parenthesis_owner']; + if ($tokens[$owner]['code'] === T_FOR) { + return; + } + } + + if ($tokens[$varToken]['code'] === T_VARIABLE + || $tokens[$varToken]['code'] === T_OPEN_TAG + || $tokens[$varToken]['code'] === T_GOTO_LABEL + || $tokens[$varToken]['code'] === T_INLINE_THEN + || $tokens[$varToken]['code'] === T_INLINE_ELSE + || $tokens[$varToken]['code'] === T_SEMICOLON + || $tokens[$varToken]['code'] === T_CLOSE_PARENTHESIS + || isset($allowed[$tokens[$varToken]['code']]) === true + ) { + return; + } + + $error = 'Assignments must be the first block of code on a line'; + $errorCode = 'Found'; + + if (isset($nested) === true) { + $controlStructures = [ + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + T_SWITCH => T_SWITCH, + T_CASE => T_CASE, + T_FOR => T_FOR, + T_MATCH => T_MATCH, + ]; + foreach ($nested as $opener => $closer) { + if (isset($tokens[$opener]['parenthesis_owner']) === true + && isset($controlStructures[$tokens[$tokens[$opener]['parenthesis_owner']]['code']]) === true + ) { + $errorCode .= 'InControlStructure'; + break; + } + } + } + + $phpcsFile->addError($error, $stackPtr, $errorCode); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php new file mode 100644 index 000000000..5d71c3ec6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DisallowSizeFunctionsInLoopsSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * An array of functions we don't want in the condition of loops. + * + * @var array + */ + protected $forbiddenFunctions = [ + 'PHP' => [ + 'sizeof' => true, + 'strlen' => true, + 'count' => true, + ], + 'JS' => ['length' => true], + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_WHILE, + T_FOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $tokenizer = $phpcsFile->tokenizerType; + $openBracket = $tokens[$stackPtr]['parenthesis_opener']; + $closeBracket = $tokens[$stackPtr]['parenthesis_closer']; + + if ($tokens[$stackPtr]['code'] === T_FOR) { + // We only want to check the condition in FOR loops. + $start = $phpcsFile->findNext(T_SEMICOLON, ($openBracket + 1)); + $end = $phpcsFile->findPrevious(T_SEMICOLON, ($closeBracket - 1)); + } else { + $start = $openBracket; + $end = $closeBracket; + } + + for ($i = ($start + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] === T_STRING + && isset($this->forbiddenFunctions[$tokenizer][$tokens[$i]['content']]) === true + ) { + $functionName = $tokens[$i]['content']; + if ($tokenizer === 'JS') { + // Needs to be in the form object.function to be valid. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true); + if ($prev === false || $tokens[$prev]['code'] !== T_OBJECT_OPERATOR) { + continue; + } + + $functionName = 'object.'.$functionName; + } else { + // Make sure it isn't a member var. + if ($tokens[($i - 1)]['code'] === T_OBJECT_OPERATOR + || $tokens[($i - 1)]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + continue; + } + + $functionName .= '()'; + } + + $error = 'The use of %s inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead'; + $data = [$functionName]; + $phpcsFile->addError($error, $i, 'Found', $data); + }//end if + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php new file mode 100644 index 000000000..56fce551d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php @@ -0,0 +1,38 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\ForbiddenFunctionsSniff as GenericForbiddenFunctionsSniff; + +class DiscouragedFunctionsSniff extends GenericForbiddenFunctionsSniff +{ + + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array + */ + public $forbiddenFunctions = [ + 'error_log' => null, + 'print_r' => null, + 'var_dump' => null, + ]; + + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var boolean + */ + public $error = false; + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php new file mode 100644 index 000000000..63a1cdd09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php @@ -0,0 +1,516 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EmbeddedPhpSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If the close php tag is on the same line as the opening + // then we have an inline embedded PHP block. + $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr); + if ($closeTag === false || $tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) { + $this->validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closeTag); + } else { + $this->validateInlineEmbeddedPhp($phpcsFile, $stackPtr, $closeTag); + } + + }//end process() + + + /** + * Validates embedded PHP that exists on multiple lines. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int|false $closingTag The position of the PHP close tag in the + * stack passed in $tokens. + * + * @return void + */ + private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closingTag) + { + $tokens = $phpcsFile->getTokens(); + + $prevTag = $phpcsFile->findPrevious($this->register(), ($stackPtr - 1)); + if ($prevTag === false) { + // This is the first open tag. + return; + } + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($firstContent === false) { + // Unclosed PHP open tag at the end of a file. Nothing to do. + return; + } + + if ($closingTag !== false) { + $firstContentAfterBlock = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), $phpcsFile->numTokens, true); + if ($firstContentAfterBlock === false) { + // Final closing tag. It will be handled elsewhere. + return; + } + + // We have an opening and a closing tag, that lie within other content. + if ($firstContent === $closingTag) { + $this->reportEmptyTagSet($phpcsFile, $stackPtr, $closingTag); + return; + } + }//end if + + if ($tokens[$firstContent]['line'] === $tokens[$stackPtr]['line']) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr, true); + $padding = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($stackPtr, rtrim($tokens[$stackPtr]['content'])); + $phpcsFile->fixer->addNewline($stackPtr); + $phpcsFile->fixer->addContent($stackPtr, str_repeat(' ', $padding)); + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + // Check the indent of the first line, except if it is a scope closer. + if (isset($tokens[$firstContent]['scope_closer']) === false + || $tokens[$firstContent]['scope_closer'] !== $firstContent + ) { + // Check for a blank line at the top. + if ($tokens[$firstContent]['line'] > ($tokens[$stackPtr]['line'] + 1)) { + // Find a token on the blank line to throw the error on. + $i = $stackPtr; + do { + $i++; + } while ($tokens[$i]['line'] !== ($tokens[$stackPtr]['line'] + 1)); + + $error = 'Blank line found at start of embedded PHP content'; + $fix = $phpcsFile->addFixableError($error, $i, 'SpacingBefore'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $firstContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$firstContent]['line'] + || $tokens[$i]['line'] === $tokens[$stackPtr]['line'] + ) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + $indent = 0; + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr); + if ($first === false) { + $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + if ($first !== false) { + $indent = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } + } else { + $indent = ($tokens[($first + 1)]['column'] - 1); + } + + $contentColumn = ($tokens[$firstContent]['column'] - 1); + if ($contentColumn !== $indent) { + $error = 'First line of embedded PHP code must be indented %s spaces; %s found'; + $data = [ + $indent, + $contentColumn, + ]; + $fix = $phpcsFile->addFixableError($error, $firstContent, 'Indent', $data); + if ($fix === true) { + $padding = str_repeat(' ', $indent); + if ($contentColumn === 0) { + $phpcsFile->fixer->addContentBefore($firstContent, $padding); + } else { + $phpcsFile->fixer->replaceToken(($firstContent - 1), $padding); + } + } + } + }//end if + }//end if + + $lastContentBeforeBlock = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$lastContentBeforeBlock]['line'] === $tokens[$stackPtr]['line'] + && trim($tokens[$lastContentBeforeBlock]['content']) !== '' + ) { + $error = 'Opening PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContentBeforeOpen'); + if ($fix === true) { + $padding = 0; + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $stackPtr); + if ($first === false) { + $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr); + if ($first !== false) { + $padding = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } + } else { + $padding = ($tokens[($first + 1)]['column'] - 1); + } + + $phpcsFile->fixer->addContentBefore($stackPtr, $phpcsFile->eolChar.str_repeat(' ', $padding)); + } + } else { + // Find the first token on the first non-empty line we find. + for ($first = ($lastContentBeforeBlock - 1); $first > 0; $first--) { + if ($tokens[$first]['line'] === $tokens[$stackPtr]['line']) { + continue; + } else if (trim($tokens[$first]['content']) !== '') { + $first = $phpcsFile->findFirstOnLine([], $first, true); + if ($tokens[$first]['code'] === T_COMMENT + && $tokens[$first]['content'] !== ltrim($tokens[$first]['content']) + ) { + // This is a subsequent line in a star-slash comment containing leading indent. + // We'll need the first line of the comment to correctly determine the indent. + continue; + } + + break; + } + } + + $expected = 0; + if ($tokens[$first]['code'] === T_INLINE_HTML + && trim($tokens[$first]['content']) !== '' + ) { + $expected = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content']))); + } else if ($tokens[$first]['code'] === T_WHITESPACE) { + $expected = ($tokens[($first + 1)]['column'] - 1); + } + + $expected += 4; + $found = ($tokens[$stackPtr]['column'] - 1); + if ($found > $expected) { + $error = 'Opening PHP tag indent incorrect; expected no more than %s spaces but found %s'; + $data = [ + $expected, + $found, + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'OpenTagIndent', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), str_repeat(' ', $expected)); + } + } + }//end if + + if ($closingTag === false) { + return; + } + + $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closingTag - 1), ($stackPtr + 1), true); + $firstContentAfterBlock = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), null, true); + + if ($tokens[$lastContent]['line'] === $tokens[$closingTag]['line']) { + $error = 'Closing PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closingTag, 'ContentBeforeEnd'); + if ($fix === true) { + // Calculate the indent for the close tag. + // If the close tag is on the same line as the first content, re-use the indent + // calculated for the first content line to prevent the indent being based on an + // "old" indent, not the _new_ (fixed) indent. + if ($tokens[$firstContent]['line'] === $tokens[$lastContent]['line'] + && isset($indent) === true + ) { + $closerIndent = $indent; + } else { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closingTag, true); + + while ($tokens[$first]['code'] === T_COMMENT + && $tokens[$first]['content'] !== ltrim($tokens[$first]['content']) + ) { + // This is a subsequent line in a star-slash comment containing leading indent. + // We'll need the first line of the comment to correctly determine the indent. + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, ($first - 1), true); + } + + $closerIndent = ($tokens[$first]['column'] - 1); + } + + $phpcsFile->fixer->beginChangeset(); + + if ($tokens[($closingTag - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($closingTag - 1), ''); + } + + $phpcsFile->fixer->addContentBefore($closingTag, str_repeat(' ', $closerIndent)); + $phpcsFile->fixer->addNewlineBefore($closingTag); + $phpcsFile->fixer->endChangeset(); + }//end if + } else if ($firstContentAfterBlock !== false + && $tokens[$firstContentAfterBlock]['line'] === $tokens[$closingTag]['line'] + ) { + $error = 'Closing PHP tag must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $closingTag, 'ContentAfterEnd'); + if ($fix === true) { + $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $closingTag, true); + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addNewline($closingTag); + $phpcsFile->fixer->addContent($closingTag, str_repeat(' ', ($tokens[$first]['column'] - 1))); + + if ($tokens[$firstContentAfterBlock]['code'] === T_INLINE_HTML) { + $trimmedHtmlContent = ltrim($tokens[$firstContentAfterBlock]['content']); + if ($trimmedHtmlContent === '') { + // HTML token contains only whitespace and the next token after is PHP, not HTML, so remove the whitespace. + $phpcsFile->fixer->replaceToken($firstContentAfterBlock, ''); + } else { + // The HTML token has content, so remove leading whitespace in favour of the indent. + $phpcsFile->fixer->replaceToken($firstContentAfterBlock, $trimmedHtmlContent); + } + } + + if ($tokens[$firstContentAfterBlock]['code'] === T_OPEN_TAG + || $tokens[$firstContentAfterBlock]['code'] === T_OPEN_TAG_WITH_ECHO + ) { + // Next token is a PHP open tag which will also have thrown an error. + // Prevent both fixers running in the same loop by making sure the token is "touched" during this loop. + // This prevents a stray new line being added between the close and open tags. + $phpcsFile->fixer->replaceToken($firstContentAfterBlock, $tokens[$firstContentAfterBlock]['content']); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + $next = $phpcsFile->findNext($this->register(), ($closingTag + 1)); + if ($next === false) { + return; + } + + // Check for a blank line at the bottom. + if ((isset($tokens[$lastContent]['scope_closer']) === false + || $tokens[$lastContent]['scope_closer'] !== $lastContent) + && $tokens[$lastContent]['line'] < ($tokens[$closingTag]['line'] - 1) + ) { + // Find a token on the blank line to throw the error on. + $i = $closingTag; + do { + $i--; + } while ($tokens[$i]['line'] !== ($tokens[$closingTag]['line'] - 1)); + + $error = 'Blank line found at end of embedded PHP content'; + $fix = $phpcsFile->addFixableError($error, $i, 'SpacingAfter'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($lastContent + 1); $i < $closingTag; $i++) { + if ($tokens[$i]['line'] === $tokens[$lastContent]['line'] + || $tokens[$i]['line'] === $tokens[$closingTag]['line'] + ) { + continue; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + }//end if + + }//end validateMultilineEmbeddedPhp() + + + /** + * Validates embedded PHP that exists on one line. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $closeTag The position of the PHP close tag in the + * stack passed in $tokens. + * + * @return void + */ + private function validateInlineEmbeddedPhp($phpcsFile, $stackPtr, $closeTag) + { + $tokens = $phpcsFile->getTokens(); + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $closeTag, true); + + if ($firstContent === false) { + $this->reportEmptyTagSet($phpcsFile, $stackPtr, $closeTag); + return; + } + + // Check that there is one, and only one space at the start of the statement. + $leadingSpace = 0; + $isLongOpenTag = false; + if ($tokens[$stackPtr]['code'] === T_OPEN_TAG + && stripos($tokens[$stackPtr]['content'], 'addFixableError($error, $stackPtr, 'SpacingAfterOpen', $data); + if ($fix === true) { + if ($isLongOpenTag === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + // Short open tag with too much whitespace. + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } else { + // Short open tag without whitespace. + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } + } + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($closeTag - 1), $stackPtr, true); + if ($prev !== $stackPtr) { + if ((isset($tokens[$prev]['scope_opener']) === false + || $tokens[$prev]['scope_opener'] !== $prev) + && (isset($tokens[$prev]['scope_closer']) === false + || $tokens[$prev]['scope_closer'] !== $prev) + && $tokens[$prev]['code'] !== T_SEMICOLON + ) { + $error = 'Inline PHP statement must end with a semicolon'; + $code = 'NoSemicolon'; + if ($tokens[$stackPtr]['code'] === T_OPEN_TAG_WITH_ECHO) { + $code = 'ShortOpenEchoNoSemicolon'; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $code); + if ($fix === true) { + $phpcsFile->fixer->addContent($prev, ';'); + } + } else if ($tokens[$prev]['code'] === T_SEMICOLON) { + $statementCount = 1; + for ($i = ($stackPtr + 1); $i < $prev; $i++) { + if ($tokens[$i]['code'] === T_SEMICOLON) { + $statementCount++; + } + } + + if ($statementCount > 1) { + $error = 'Inline PHP statement must contain a single statement; %s found'; + $data = [$statementCount]; + $phpcsFile->addError($error, $stackPtr, 'MultipleStatements', $data); + } + }//end if + }//end if + + $trailingSpace = 0; + if ($tokens[($closeTag - 1)]['code'] === T_WHITESPACE) { + $trailingSpace = $tokens[($closeTag - 1)]['length']; + } else if (($tokens[($closeTag - 1)]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[($closeTag - 1)]['code']]) === true) + && substr($tokens[($closeTag - 1)]['content'], -1) === ' ' + ) { + $trailingSpace = (strlen($tokens[($closeTag - 1)]['content']) - strlen(rtrim($tokens[($closeTag - 1)]['content']))); + } + + if ($trailingSpace !== 1) { + $error = 'Expected 1 space before closing PHP tag; %s found'; + $data = [$trailingSpace]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeClose', $data); + if ($fix === true) { + if ($trailingSpace === 0) { + $phpcsFile->fixer->addContentBefore($closeTag, ' '); + } else if ($tokens[($closeTag - 1)]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[($closeTag - 1)]['code']]) === true + ) { + $phpcsFile->fixer->replaceToken(($closeTag - 1), rtrim($tokens[($closeTag - 1)]['content']).' '); + } else { + $phpcsFile->fixer->replaceToken(($closeTag - 1), ' '); + } + } + } + + }//end validateInlineEmbeddedPhp() + + + /** + * Report and fix an set of empty PHP tags. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $closeTag The position of the PHP close tag in the + * stack passed in $tokens. + * + * @return void + */ + private function reportEmptyTagSet(File $phpcsFile, $stackPtr, $closeTag) + { + $tokens = $phpcsFile->getTokens(); + $error = 'Empty embedded PHP tag found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $stackPtr; $i <= $closeTag; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + // Prevent leaving indentation whitespace behind when the empty tag set is the only thing on the affected lines. + if (isset($tokens[($closeTag + 1)]) === true + && $tokens[($closeTag + 1)]['line'] !== $tokens[$closeTag]['line'] + && $tokens[($stackPtr - 1)]['code'] === T_INLINE_HTML + && $tokens[($stackPtr - 1)]['line'] === $tokens[$stackPtr]['line'] + && $tokens[($stackPtr - 1)]['column'] === 1 + && trim($tokens[($stackPtr - 1)]['content']) === '' + ) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + } + + }//end reportEmptyTagSet() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php new file mode 100644 index 000000000..102bd7c3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/EvalSniff.php @@ -0,0 +1,48 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class EvalSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_EVAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of eval() is discouraged'; + $phpcsFile->addWarning($error, $stackPtr, 'Discouraged'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php new file mode 100644 index 000000000..fec3ec821 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class GlobalKeywordSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_GLOBAL]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $nextVar = $tokens[$phpcsFile->findNext([T_VARIABLE], $stackPtr)]; + $varName = str_replace('$', '', $nextVar['content']); + $error = 'Use of the "global" keyword is forbidden; use "$GLOBALS[\'%s\']" instead'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php new file mode 100644 index 000000000..a3ab8e5a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/HeredocSniff.php @@ -0,0 +1,51 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class HeredocSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_START_HEREDOC, + T_START_NOWDOC, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $error = 'Use of heredoc and nowdoc syntax ("<<<") is not allowed; use standard strings or inline HTML instead'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php new file mode 100644 index 000000000..1bc369a2a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php @@ -0,0 +1,76 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class InnerFunctionsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['conditions']) === false) { + return; + } + + $conditions = $tokens[$stackPtr]['conditions']; + $reversedConditions = array_reverse($conditions, true); + + $outerFuncToken = null; + foreach ($reversedConditions as $condToken => $condition) { + if ($condition === T_FUNCTION || $condition === T_CLOSURE) { + $outerFuncToken = $condToken; + break; + } + + if (array_key_exists($condition, Tokens::$ooScopeTokens) === true) { + // Ignore methods in OOP structures defined within functions. + return; + } + } + + if ($outerFuncToken === null) { + // Not a nested function. + return; + } + + $error = 'The use of inner functions is forbidden'; + $phpcsFile->addError($error, $stackPtr, 'NotAllowed'); + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php new file mode 100644 index 000000000..0b671d629 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php @@ -0,0 +1,167 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LowercasePHPFunctionsSniff implements Sniff +{ + + /** + * String -> int hash map of all php built in function names + * + * @var array + */ + private $builtInFunctions; + + + /** + * Construct the LowercasePHPFunctionSniff + */ + public function __construct() + { + + $allFunctions = get_defined_functions(); + $this->builtInFunctions = array_flip($allFunctions['internal']); + + }//end __construct() + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $contentLc = strtolower($content); + if ($content === $contentLc) { + return; + } + + // Make sure it is an inbuilt PHP function. + // PHP_CodeSniffer can possibly include user defined functions + // through the use of vendor/autoload.php. + if (isset($this->builtInFunctions[$contentLc]) === false) { + return; + } + + // Make sure this is a function call or a use statement. + if (empty($tokens[$stackPtr]['nested_attributes']) === false) { + // Class instantiation in attribute, not function call. + return; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false) { + // Not a function call. + return; + } + + $ignore = Tokens::$emptyTokens; + $ignore[] = T_BITWISE_AND; + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + $prevPrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + + if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) { + // Is this a use statement importing a PHP native function ? + if ($tokens[$next]['code'] !== T_NS_SEPARATOR + && $tokens[$prev]['code'] === T_STRING + && $tokens[$prev]['content'] === 'function' + && $prevPrev !== false + && $tokens[$prevPrev]['code'] === T_USE + ) { + $error = 'Use statements for PHP native functions must be lowercase; expected "%s" but found "%s"'; + $data = [ + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseStatementUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + } + + // No open parenthesis; not a "use function" statement nor a function call. + return; + }//end if + + if ($tokens[$prev]['code'] === T_FUNCTION) { + // Function declaration, not a function call. + return; + } + + if ($tokens[$prev]['code'] === T_NS_SEPARATOR) { + if ($prevPrev !== false + && ($tokens[$prevPrev]['code'] === T_STRING + || $tokens[$prevPrev]['code'] === T_NAMESPACE + || $tokens[$prevPrev]['code'] === T_NEW) + ) { + // Namespaced class/function, not an inbuilt function. + // Could potentially give false negatives for non-namespaced files + // when namespace\functionName() is encountered. + return; + } + } + + if ($tokens[$prev]['code'] === T_NEW) { + // Object creation, not an inbuilt function. + return; + } + + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Not an inbuilt function. + return; + } + + if ($tokens[$prev]['code'] === T_DOUBLE_COLON) { + // Not an inbuilt function. + return; + } + + $error = 'Calls to PHP native functions must be lowercase; expected "%s" but found "%s"'; + $data = [ + $contentLc, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'CallUppercase', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $contentLc); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php new file mode 100644 index 000000000..4c0d6bcb7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php @@ -0,0 +1,303 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class NonExecutableCodeSniff implements Sniff +{ + + /** + * Tokens for terminating expressions, which can be used inline. + * + * This is in contrast to terminating statements, which cannot be used inline + * and would result in a parse error (which is not the concern of this sniff). + * + * `throw` can be used as an expression since PHP 8.0. + * {@link https://wiki.php.net/rfc/throw_expression} + * + * @var array + */ + private $expressionTokens = [ + T_EXIT => T_EXIT, + T_THROW => T_THROW, + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_BREAK, + T_CONTINUE, + T_RETURN, + T_THROW, + T_EXIT, + T_GOTO, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + + // Tokens which can be used in inline expressions need special handling. + if (isset($this->expressionTokens[$tokens[$stackPtr]['code']]) === true) { + // If this token is preceded by a logical operator, it only relates to one line + // and should be ignored. For example: fopen() or die(). + // Note: There is one exception: throw expressions can not be used with xor. + if (isset(Tokens::$booleanOperators[$tokens[$prev]['code']]) === true + && ($tokens[$stackPtr]['code'] === T_THROW && $tokens[$prev]['code'] === T_LOGICAL_XOR) === false + ) { + return; + } + + // Expressions are allowed in the `else` clause of ternaries. + if ($tokens[$prev]['code'] === T_INLINE_THEN || $tokens[$prev]['code'] === T_INLINE_ELSE) { + return; + } + + // Expressions are allowed with PHP 7.0+ null coalesce and PHP 7.4+ null coalesce equals. + if ($tokens[$prev]['code'] === T_COALESCE || $tokens[$prev]['code'] === T_COALESCE_EQUAL) { + return; + } + + // Expressions are allowed in arrow functions. + if ($tokens[$prev]['code'] === T_FN_ARROW) { + return; + } + }//end if + + // This token may be part of an inline condition. + // If we find a closing parenthesis that belongs to a condition, + // or an "else", we should ignore this token. + if ($tokens[$prev]['code'] === T_ELSE + || (isset($tokens[$prev]['parenthesis_owner']) === true + && ($tokens[$tokens[$prev]['parenthesis_owner']]['code'] === T_IF + || $tokens[$tokens[$prev]['parenthesis_owner']]['code'] === T_ELSEIF)) + ) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_RETURN) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_SEMICOLON) { + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true); + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + // If this is the closing brace of a function + // then this return statement doesn't return anything + // and is not required anyway. + $owner = $tokens[$next]['scope_condition']; + if ($tokens[$owner]['code'] === T_FUNCTION + || $tokens[$owner]['code'] === T_CLOSURE + ) { + $warning = 'Empty return statement not required here'; + $phpcsFile->addWarning($warning, $stackPtr, 'ReturnNotRequired'); + return; + } + } + } + } + + if (isset($tokens[$stackPtr]['scope_opener']) === true) { + $owner = $tokens[$stackPtr]['scope_condition']; + if ($tokens[$owner]['code'] === T_CASE || $tokens[$owner]['code'] === T_DEFAULT) { + // This token closes the scope of a CASE or DEFAULT statement + // so any code between this statement and the next CASE, DEFAULT or + // end of SWITCH token will not be executable. + $end = $phpcsFile->findEndOfStatement($stackPtr); + $next = $phpcsFile->findNext( + [ + T_CASE, + T_DEFAULT, + T_CLOSE_CURLY_BRACKET, + T_ENDSWITCH, + ], + ($end + 1) + ); + + if ($next !== false) { + $lastLine = $tokens[$end]['line']; + for ($i = ($stackPtr + 1); $i < $next; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $line = $tokens[$i]['line']; + if ($line > $lastLine) { + $type = substr($tokens[$stackPtr]['type'], 2); + $warning = 'Code after the %s statement on line %s cannot be executed'; + $data = [ + $type, + $tokens[$stackPtr]['line'], + ]; + $phpcsFile->addWarning($warning, $i, 'Unreachable', $data); + $lastLine = $line; + } + } + }//end if + + // That's all we have to check for these types of statements. + return; + }//end if + }//end if + + $ourConditions = array_keys($tokens[$stackPtr]['conditions']); + + if (empty($ourConditions) === false) { + $condition = array_pop($ourConditions); + + if (isset($tokens[$condition]['scope_closer']) === false) { + return; + } + + // Special case for BREAK statements sitting directly inside SWITCH + // statements. If we get to this point, we know the BREAK is not being + // used to close a CASE statement, so it is most likely non-executable + // code itself (as is the case when you put return; break; at the end of + // a case). So we need to ignore this token. + if ($tokens[$condition]['code'] === T_SWITCH + && $tokens[$stackPtr]['code'] === T_BREAK + ) { + return; + } + + $closer = $tokens[$condition]['scope_closer']; + + // If the closer for our condition is shared with other openers, + // we will need to throw errors from this token to the next + // shared opener (if there is one), not to the scope closer. + $nextOpener = null; + for ($i = ($stackPtr + 1); $i < $closer; $i++) { + if (isset($tokens[$i]['scope_closer']) === true) { + if ($tokens[$i]['scope_closer'] === $closer) { + // We found an opener that shares the same + // closing token as us. + $nextOpener = $i; + break; + } + } + }//end for + + if ($nextOpener === null) { + $end = $closer; + } else { + $end = ($nextOpener - 1); + } + } else { + // This token is in the global scope. + if ($tokens[$stackPtr]['code'] === T_BREAK) { + return; + } + + // Throw an error for all lines until the end of the file. + $end = ($phpcsFile->numTokens - 1); + }//end if + + // Find the semicolon or closing PHP tag that ends this statement, + // skipping nested statements like FOR loops and closures. + for ($start = ($stackPtr + 1); $start < $phpcsFile->numTokens; $start++) { + if ($start === $end) { + break; + } + + if (isset($tokens[$start]['parenthesis_closer']) === true + && $tokens[$start]['code'] === T_OPEN_PARENTHESIS + ) { + $start = $tokens[$start]['parenthesis_closer']; + continue; + } + + if (isset($tokens[$start]['bracket_closer']) === true + && $tokens[$start]['code'] === T_OPEN_CURLY_BRACKET + ) { + $start = $tokens[$start]['bracket_closer']; + continue; + } + + if ($tokens[$start]['code'] === T_SEMICOLON || $tokens[$start]['code'] === T_CLOSE_TAG) { + break; + } + }//end for + + if (isset($tokens[$start]) === false) { + return; + } + + $lastLine = $tokens[$start]['line']; + for ($i = ($start + 1); $i < $end; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true + || isset(Tokens::$bracketTokens[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_SEMICOLON + ) { + continue; + } + + // Skip whole functions and classes/interfaces because they are not + // technically executed code, but rather declarations that may be used. + if (isset(Tokens::$ooScopeTokens[$tokens[$i]['code']]) === true + || $tokens[$i]['code'] === T_FUNCTION + || $tokens[$i]['code'] === T_CLOSURE + ) { + if (isset($tokens[$i]['scope_closer']) === false) { + // Parse error/Live coding. + return; + } + + $i = $tokens[$i]['scope_closer']; + continue; + } + + // Skip HTML whitespace. + if ($tokens[$i]['code'] === T_INLINE_HTML && trim($tokens[$i]['content']) === '') { + continue; + } + + // Skip PHP re-open tag (eg, after inline HTML). + if ($tokens[$i]['code'] === T_OPEN_TAG) { + continue; + } + + $line = $tokens[$i]['line']; + if ($line > $lastLine) { + $type = substr($tokens[$stackPtr]['type'], 2); + $warning = 'Code after the %s statement on line %s cannot be executed'; + $data = [ + $type, + $tokens[$stackPtr]['line'], + ]; + $phpcsFile->addWarning($warning, $i, 'Unreachable', $data); + $lastLine = $line; + } + }//end for + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php new file mode 100644 index 000000000..3d1c83f01 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; + +class MemberVarScopeSniff extends AbstractVariableSniff +{ + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $properties = $phpcsFile->getMemberProperties($stackPtr); + + if ($properties === [] || $properties['scope_specified'] !== false) { + return; + } + + $error = 'Scope modifier not specified for member variable "%s"'; + $data = [$tokens[$stackPtr]['content']]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php new file mode 100644 index 000000000..39ed5b0dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php @@ -0,0 +1,83 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MethodScopeSniff extends AbstractScopeSniff +{ + + + /** + * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff. + */ + public function __construct() + { + parent::__construct(Tokens::$ooScopeTokens, [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * @param int $currScope The current scope opener token. + * + * @return void + */ + protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + $methodName = $phpcsFile->getDeclarationName($stackPtr); + if ($methodName === null) { + // Ignore closures. + return; + } + + $properties = $phpcsFile->getMethodProperties($stackPtr); + if ($properties['scope_specified'] === false) { + $error = 'Visibility must be declared on method "%s"'; + $data = [$methodName]; + $phpcsFile->addError($error, $stackPtr, 'Missing', $data); + } + + }//end processTokenWithinScope() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php new file mode 100644 index 000000000..aab5bdb7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php @@ -0,0 +1,128 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractScopeSniff; +use PHP_CodeSniffer\Util\Tokens; + +class StaticThisUsageSniff extends AbstractScopeSniff +{ + + + /** + * Constructs the test with the tokens it wishes to listen for. + */ + public function __construct() + { + parent::__construct([T_CLASS, T_TRAIT, T_ENUM, T_ANON_CLASS], [T_FUNCTION]); + + }//end __construct() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * @param int $currScope A pointer to the start of the scope. + * + * @return void + */ + public function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope) + { + $tokens = $phpcsFile->getTokens(); + + // Determine if this is a function which needs to be examined. + $conditions = $tokens[$stackPtr]['conditions']; + end($conditions); + $deepestScope = key($conditions); + if ($deepestScope !== $currScope) { + return; + } + + // Ignore abstract functions. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($next === false || $tokens[$next]['code'] !== T_STRING) { + // Not a function declaration, or incomplete. + return; + } + + $methodProps = $phpcsFile->getMethodProperties($stackPtr); + if ($methodProps['is_static'] === false) { + return; + } + + $next = $stackPtr; + $end = $tokens[$stackPtr]['scope_closer']; + + $this->checkThisUsage($phpcsFile, $next, $end); + + }//end processTokenWithinScope() + + + /** + * Check for $this variable usage between $next and $end tokens. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned. + * @param int $next The position of the next token to check. + * @param int $end The position of the last token to check. + * + * @return void + */ + private function checkThisUsage(File $phpcsFile, $next, $end) + { + $tokens = $phpcsFile->getTokens(); + + do { + $next = $phpcsFile->findNext([T_VARIABLE, T_ANON_CLASS], ($next + 1), $end); + if ($next === false) { + continue; + } + + if ($tokens[$next]['code'] === T_ANON_CLASS) { + $this->checkThisUsage($phpcsFile, $next, $tokens[$next]['scope_opener']); + $next = $tokens[$next]['scope_closer']; + continue; + } + + if ($tokens[$next]['content'] !== '$this') { + continue; + } + + $error = 'Usage of "$this" in static methods will cause runtime errors'; + $phpcsFile->addError($error, $next, 'Found'); + } while ($next !== false); + + }//end checkThisUsage() + + + /** + * Processes a token that is found within the scope that this test is + * listening to. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position in the stack where this + * token was found. + * + * @return void + */ + protected function processTokenOutsideScope(File $phpcsFile, $stackPtr) + { + + }//end processTokenOutsideScope() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php new file mode 100644 index 000000000..66c324548 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ConcatenationSpacingSniff implements Sniff +{ + + /** + * The number of spaces before and after a string concat. + * + * @var integer + */ + public $spacing = 0; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_STRING_CONCAT]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if (isset($tokens[($stackPtr + 2)]) === false) { + // Syntax error or live coding, bow out. + return; + } + + $ignoreBefore = false; + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($tokens[$prev]['code'] === T_END_HEREDOC || $tokens[$prev]['code'] === T_END_NOWDOC) { + // Spacing before must be preserved due to the here/nowdoc closing tag. + $ignoreBefore = true; + } + + $this->spacing = (int) $this->spacing; + + if ($ignoreBefore === false) { + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $before = 0; + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $before = 'newline'; + } else { + $before = $tokens[($stackPtr - 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before string concat', $before); + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $after = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $after = 'newline'; + } else { + $after = $tokens[($stackPtr + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after string concat', $after); + + if (($ignoreBefore === true + || $before === $this->spacing + || ($before === 'newline' + && $this->ignoreNewlines === true)) + && ($after === $this->spacing + || ($after === 'newline' + && $this->ignoreNewlines === true)) + ) { + return; + } + + if ($this->spacing === 0) { + $message = 'Concat operator must not be surrounded by spaces'; + $data = []; + } else { + if ($this->spacing > 1) { + $message = 'Concat operator must be surrounded by %s spaces'; + } else { + $message = 'Concat operator must be surrounded by a single space'; + } + + $data = [$this->spacing]; + } + + $fix = $phpcsFile->addFixableError($message, $stackPtr, 'PaddingFound', $data); + + if ($fix === true) { + $padding = str_repeat(' ', $this->spacing); + if ($ignoreBefore === false && ($before !== 'newline' || $this->ignoreNewlines === false)) { + if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr - 1), $padding); + if ($this->spacing === 0 + && ($tokens[($stackPtr - 2)]['code'] === T_LNUMBER + || $tokens[($stackPtr - 2)]['code'] === T_DNUMBER) + ) { + $phpcsFile->fixer->replaceToken(($stackPtr - 2), '('.$tokens[($stackPtr - 2)]['content'].')'); + } + + $phpcsFile->fixer->endChangeset(); + } else if ($this->spacing > 0) { + $phpcsFile->fixer->addContent(($stackPtr - 1), $padding); + } + } + + if ($after !== 'newline' || $this->ignoreNewlines === false) { + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken(($stackPtr + 1), $padding); + if ($this->spacing === 0 + && ($tokens[($stackPtr + 2)]['code'] === T_LNUMBER + || $tokens[($stackPtr + 2)]['code'] === T_DNUMBER) + ) { + $phpcsFile->fixer->replaceToken(($stackPtr + 2), '('.$tokens[($stackPtr + 2)]['content'].')'); + } + + $phpcsFile->fixer->endChangeset(); + } else if ($this->spacing > 0) { + $phpcsFile->fixer->addContent($stackPtr, $padding); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php new file mode 100644 index 000000000..fb3b626f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php @@ -0,0 +1,144 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class DoubleQuoteUsageSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If tabs are being converted to spaces by the tokeniser, the + // original content should be used instead of the converted content. + if (isset($tokens[$stackPtr]['orig_content']) === true) { + $workingString = $tokens[$stackPtr]['orig_content']; + } else { + $workingString = $tokens[$stackPtr]['content']; + } + + $lastStringToken = $stackPtr; + + $i = ($stackPtr + 1); + if (isset($tokens[$i]) === true) { + while ($i < $phpcsFile->numTokens + && $tokens[$i]['code'] === $tokens[$stackPtr]['code'] + ) { + if (isset($tokens[$i]['orig_content']) === true) { + $workingString .= $tokens[$i]['orig_content']; + } else { + $workingString .= $tokens[$i]['content']; + } + + $lastStringToken = $i; + $i++; + } + } + + $skipTo = ($lastStringToken + 1); + + // Check if it's a double quoted string. + if ($workingString[0] !== '"' || substr($workingString, -1) !== '"') { + return $skipTo; + } + + // The use of variables in double quoted strings is not allowed. + if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING) { + $stringTokens = token_get_all('addError($error, $stackPtr, 'ContainsVar', $data); + } + } + + return $skipTo; + }//end if + + $allowedChars = [ + '\0', + '\1', + '\2', + '\3', + '\4', + '\5', + '\6', + '\7', + '\n', + '\r', + '\f', + '\t', + '\v', + '\x', + '\b', + '\e', + '\u', + '\'', + ]; + + foreach ($allowedChars as $testChar) { + if (strpos($workingString, $testChar) !== false) { + return $skipTo; + } + } + + $error = 'String %s does not require double quotes; use single quotes instead'; + $data = [str_replace(["\r", "\n"], ['\r', '\n'], $workingString)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotRequired', $data); + + if ($fix === true) { + $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, ''); + $lastStringToken--; + } + + $phpcsFile->fixer->endChangeset(); + } + + return $skipTo; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php new file mode 100644 index 000000000..ec516a99a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class EchoedStringsSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_ECHO]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + // If the first non-whitespace token is not an opening parenthesis, then we are not concerned. + if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + $end = $phpcsFile->findNext([T_SEMICOLON, T_CLOSE_TAG], $stackPtr, null, false); + + // If the token before the semicolon is not a closing parenthesis, then we are not concerned. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true); + if ($tokens[$prev]['code'] !== T_CLOSE_PARENTHESIS) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + // If the parenthesis don't match, then we are not concerned. + if ($tokens[$firstContent]['parenthesis_closer'] !== $prev) { + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'no'); + return; + } + + $phpcsFile->recordMetric($stackPtr, 'Brackets around echoed strings', 'yes'); + + if (($phpcsFile->findNext(Tokens::$operators, $stackPtr, $end, false)) === false) { + // There are no arithmetic operators in this. + $error = 'Echoed strings should not be bracketed'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'HasBracket'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($firstContent, ''); + if ($tokens[($firstContent - 1)]['code'] !== T_WHITESPACE) { + $phpcsFile->fixer->addContent(($firstContent - 1), ' '); + } + + $phpcsFile->fixer->replaceToken($prev, ''); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php new file mode 100644 index 000000000..2ae782cef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class CastSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$castTokens; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $content = $tokens[$stackPtr]['content']; + $expected = str_replace(' ', '', $content); + $expected = str_replace("\t", '', $expected); + + if ($content !== $expected) { + $error = 'Cast statements must not contain whitespace; expected "%s" but found "%s"'; + $data = [ + $expected, + $content, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'ContainsWhiteSpace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $expected); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php new file mode 100644 index 000000000..eb6e5b2ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -0,0 +1,359 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ControlStructureSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_DO, + T_ELSE, + T_ELSEIF, + T_TRY, + T_CATCH, + T_FINALLY, + T_MATCH, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['parenthesis_opener']) === true + && isset($tokens[$stackPtr]['parenthesis_closer']) === true + ) { + $parenOpener = $tokens[$stackPtr]['parenthesis_opener']; + $parenCloser = $tokens[$stackPtr]['parenthesis_closer']; + if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) { + $gap = $tokens[($parenOpener + 1)]['length']; + + if ($gap === 0) { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 'newline'); + $gap = 'newline'; + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', $gap); + } + + $error = 'Expected 0 spaces after opening bracket; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenOpener + 1), ''); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces after control structure open parenthesis', 0); + } + + if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line'] + && $tokens[($parenCloser - 1)]['code'] === T_WHITESPACE + ) { + $gap = $tokens[($parenCloser - 1)]['length']; + $error = 'Expected 0 spaces before closing bracket; %s found'; + $data = [$gap]; + $fix = $phpcsFile->addFixableError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($parenCloser - 1), ''); + } + + if ($gap === 0) { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 'newline'); + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', $gap); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Spaces before control structure close parenthesis', 0); + } + }//end if + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + $scopeOpener = $tokens[$stackPtr]['scope_opener']; + $scopeCloser = $tokens[$stackPtr]['scope_closer']; + + for ($firstContent = ($scopeOpener + 1); $firstContent < $phpcsFile->numTokens; $firstContent++) { + $code = $tokens[$firstContent]['code']; + + if ($code === T_WHITESPACE + || ($code === T_INLINE_HTML + && trim($tokens[$firstContent]['content']) === '') + ) { + continue; + } + + // Skip all empty tokens on the same line as the opener. + if ($tokens[$firstContent]['line'] === $tokens[$scopeOpener]['line'] + && (isset(Tokens::$emptyTokens[$code]) === true + || $code === T_CLOSE_TAG) + ) { + continue; + } + + break; + } + + // We ignore spacing for some structures that tend to have their own rules. + $ignore = [ + T_FUNCTION => true, + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_DOC_COMMENT_OPEN_TAG => true, + ]; + + if (isset($ignore[$tokens[$firstContent]['code']]) === false + && $tokens[$firstContent]['line'] >= ($tokens[$scopeOpener]['line'] + 2) + ) { + $gap = ($tokens[$firstContent]['line'] - $tokens[$scopeOpener]['line'] - 1); + $phpcsFile->recordMetric($stackPtr, 'Blank lines at start of control structure', $gap); + + $error = 'Blank line found at start of control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'SpacingAfterOpen'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($scopeOpener + 1); + while ($tokens[$i]['line'] !== $tokens[$firstContent]['line']) { + // Start removing content from the line after the opener. + if ($tokens[$i]['line'] !== $tokens[$scopeOpener]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $i++; + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Blank lines at start of control structure', 0); + }//end if + + if ($firstContent !== $scopeCloser) { + $lastContent = $phpcsFile->findPrevious( + T_WHITESPACE, + ($scopeCloser - 1), + null, + true + ); + + $lastNonEmptyContent = $phpcsFile->findPrevious( + Tokens::$emptyTokens, + ($scopeCloser - 1), + null, + true + ); + + $checkToken = $lastContent; + if (isset($tokens[$lastNonEmptyContent]['scope_condition']) === true) { + $checkToken = $tokens[$lastNonEmptyContent]['scope_condition']; + } + + if (isset($ignore[$tokens[$checkToken]['code']]) === false + && $tokens[$lastContent]['line'] <= ($tokens[$scopeCloser]['line'] - 2) + ) { + $errorToken = $scopeCloser; + for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] < $tokens[$scopeCloser]['line']) { + $errorToken = $i; + break; + } + } + + $gap = ($tokens[$scopeCloser]['line'] - $tokens[$lastContent]['line'] - 1); + $phpcsFile->recordMetric($stackPtr, 'Blank lines at end of control structure', $gap); + + $error = 'Blank line found at end of control structure'; + $fix = $phpcsFile->addFixableError($error, $errorToken, 'SpacingBeforeClose'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { + if ($tokens[$i]['line'] === $tokens[$scopeCloser]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$lastContent]['line']) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->recordMetric($stackPtr, 'Blank lines at end of control structure', 0); + }//end if + }//end if + + if ($tokens[$stackPtr]['code'] === T_MATCH) { + // Move the scope closer to the semicolon/comma. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($scopeCloser + 1), null, true); + if ($next !== false + && ($tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['code'] === T_COMMA) + ) { + $scopeCloser = $next; + } + } + + $trailingContent = $phpcsFile->findNext( + T_WHITESPACE, + ($scopeCloser + 1), + null, + true + ); + + if ($tokens[$trailingContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$trailingContent]['code']]) === true + ) { + // Special exception for code where the comment about + // an ELSE or ELSEIF is written between the control structures. + $nextCode = $phpcsFile->findNext( + Tokens::$emptyTokens, + ($scopeCloser + 1), + null, + true + ); + + if ($tokens[$nextCode]['code'] === T_ELSE + || $tokens[$nextCode]['code'] === T_ELSEIF + || $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + ) { + $trailingContent = $nextCode; + } + }//end if + + if ($tokens[$trailingContent]['code'] === T_ELSE) { + if ($tokens[$stackPtr]['code'] === T_IF) { + // IF with ELSE. + return; + } + } + + if ($tokens[$trailingContent]['code'] === T_WHILE + && $tokens[$stackPtr]['code'] === T_DO + ) { + // DO with WHILE. + return; + } + + if ($tokens[$trailingContent]['code'] === T_CLOSE_TAG) { + // At the end of the script or embedded code. + return; + } + + if (isset($tokens[$trailingContent]['scope_condition']) === true + && $tokens[$trailingContent]['scope_condition'] !== $trailingContent + && isset($tokens[$trailingContent]['scope_opener']) === true + && $tokens[$trailingContent]['scope_opener'] !== $trailingContent + ) { + // Another control structure's closing brace. + $owner = $tokens[$trailingContent]['scope_condition']; + if ($tokens[$owner]['code'] === T_FUNCTION) { + // The next content is the closing brace of a function + // so normal function rules apply and we can ignore it. + return; + } + + if ($tokens[$owner]['code'] === T_CLOSURE + && ($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true) + ) { + return; + } + + if ($tokens[$trailingContent]['line'] !== ($tokens[$scopeCloser]['line'] + 1)) { + $error = 'Blank line found after control structure'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'LineAfterClose'); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($scopeCloser + 1); + while ($tokens[$i]['line'] !== $tokens[$trailingContent]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + $i++; + } + + $phpcsFile->fixer->addNewline($scopeCloser); + $phpcsFile->fixer->endChangeset(); + } + } + } 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'; + $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'NoLineAfterClose'); + if ($fix === true) { + $trailingContent = $phpcsFile->findNext( + T_WHITESPACE, + ($scopeCloser + 1), + null, + true + ); + + if (($tokens[$trailingContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$trailingContent]['code']]) === true) + && $tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line'] + ) { + $phpcsFile->fixer->addNewline($trailingContent); + } else { + $phpcsFile->fixer->addNewline($scopeCloser); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php new file mode 100644 index 000000000..54b9ca927 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php @@ -0,0 +1,164 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionClosingBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Probably an interface method. + return; + } + + $closeBrace = $tokens[$stackPtr]['scope_closer']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true); + + // Special case for empty JS functions. + if ($phpcsFile->tokenizerType === 'JS' && $prevContent === $tokens[$stackPtr]['scope_opener']) { + // In this case, the opening and closing brace must be + // right next to each other. + if ($tokens[$stackPtr]['scope_closer'] !== ($tokens[$stackPtr]['scope_opener'] + 1)) { + $error = 'The opening and closing braces of empty functions must be directly next to each other; e.g., function () {}'; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBetween'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $closeBrace; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } + + return; + } + + $nestedFunction = false; + if ($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true + || isset($tokens[$stackPtr]['nested_parenthesis']) === true + ) { + $nestedFunction = true; + } + + $braceLine = $tokens[$closeBrace]['line']; + $prevLine = $tokens[$prevContent]['line']; + $found = ($braceLine - $prevLine - 1); + + if ($nestedFunction === true) { + if ($found < 0) { + $error = 'Closing brace of nested function must be on a new line'; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'ContentBeforeClose'); + if ($fix === true) { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } else if ($found > 0) { + $error = 'Expected 0 blank lines before closing brace of nested function; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeNestedClose', $data); + + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $changeMade = false; + for ($i = ($prevContent + 1); $i < $closeBrace; $i++) { + // Try and maintain indentation. + if ($tokens[$i]['line'] === ($braceLine - 1)) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + $changeMade = true; + } + + // Special case for when the last content contains the newline + // token as well, like with a comment. + if ($changeMade === false) { + $phpcsFile->fixer->replaceToken(($prevContent + 1), ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + } else { + if ($found !== 1) { + if ($found < 0) { + $found = 0; + } + + $error = 'Expected 1 blank line before closing function brace; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $closeBrace, 'SpacingBeforeClose', $data); + + if ($fix === true) { + if ($found > 1) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prevContent + 1); $i < ($closeBrace - 1); $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken($i, $phpcsFile->eolChar); + $phpcsFile->fixer->endChangeset(); + } else { + // Try and maintain indentation. + if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->addNewlineBefore($closeBrace - 1); + } else { + $phpcsFile->fixer->addNewlineBefore($closeBrace); + } + } + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php new file mode 100644 index 000000000..3eff4e0ff --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php @@ -0,0 +1,98 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class FunctionOpeningBraceSpaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_FUNCTION, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[$stackPtr]['scope_opener']) === false) { + // Probably an interface or abstract method. + return; + } + + $openBrace = $tokens[$stackPtr]['scope_opener']; + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($openBrace + 1), null, true); + + if ($nextContent === $tokens[$stackPtr]['scope_closer']) { + // The next bit of content is the closing brace, so this + // is an empty function and should have a blank line + // between the opening and closing braces. + return; + } + + $braceLine = $tokens[$openBrace]['line']; + $nextLine = $tokens[$nextContent]['line']; + + $found = ($nextLine - $braceLine - 1); + if ($found > 0) { + $error = 'Expected 0 blank lines after opening function brace; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $openBrace, 'SpacingAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($openBrace + 1); $i < $nextContent; $i++) { + if ($tokens[$i]['line'] === $nextLine) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->addNewline($openBrace); + $phpcsFile->fixer->endChangeset(); + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php new file mode 100644 index 000000000..01cbd647f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php @@ -0,0 +1,366 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class FunctionSpacingSniff implements Sniff +{ + + /** + * The number of blank lines between functions. + * + * @var integer + */ + public $spacing = 2; + + /** + * The number of blank lines before the first function in a class. + * + * @var integer + */ + public $spacingBeforeFirst = 2; + + /** + * The number of blank lines after the last function in a class. + * + * @var integer + */ + public $spacingAfterLast = 2; + + /** + * Original properties as set in a custom ruleset (if any). + * + * @var array|null + */ + private $rulesetProperties = null; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_FUNCTION]; + + }//end register() + + + /** + * Processes this sniff when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $previousNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if ($previousNonEmpty !== false + && $tokens[$previousNonEmpty]['code'] === T_OPEN_TAG + && $tokens[$previousNonEmpty]['line'] !== 1 + ) { + // Ignore functions at the start of an embedded PHP block. + return; + } + + // If the ruleset has only overridden the spacing property, use + // that value for all spacing rules. + if ($this->rulesetProperties === null) { + $this->rulesetProperties = []; + if (isset($phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']) === true + && isset($phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']['properties']) === true + ) { + $this->rulesetProperties = $phpcsFile->ruleset->ruleset['Squiz.WhiteSpace.FunctionSpacing']['properties']; + if (isset($this->rulesetProperties['spacing']) === true) { + if (isset($this->rulesetProperties['spacingBeforeFirst']) === false) { + $this->spacingBeforeFirst = $this->spacing; + } + + if (isset($this->rulesetProperties['spacingAfterLast']) === false) { + $this->spacingAfterLast = $this->spacing; + } + } + } + } + + $this->spacing = (int) $this->spacing; + $this->spacingBeforeFirst = (int) $this->spacingBeforeFirst; + $this->spacingAfterLast = (int) $this->spacingAfterLast; + + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + // Must be an interface method, so the closer is the semicolon. + $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr); + } else { + $closer = $tokens[$stackPtr]['scope_closer']; + } + + $isFirst = false; + $isLast = false; + + $ignore = ([T_WHITESPACE => T_WHITESPACE] + Tokens::$methodPrefixes); + + $prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true); + + while ($tokens[$prev]['code'] === T_ATTRIBUTE_END) { + // Skip past function attributes. + $prev = $phpcsFile->findPrevious($ignore, ($tokens[$prev]['attribute_opener'] - 1), null, true); + } + + if ($tokens[$prev]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + // Skip past function docblocks. + $prev = $phpcsFile->findPrevious($ignore, ($tokens[$prev]['comment_opener'] - 1), null, true); + } + + if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET) { + $isFirst = true; + } + + $next = $phpcsFile->findNext($ignore, ($closer + 1), null, true); + if (isset(Tokens::$emptyTokens[$tokens[$next]['code']]) === true + && $tokens[$next]['line'] === $tokens[$closer]['line'] + ) { + // Skip past "end" comments. + $next = $phpcsFile->findNext($ignore, ($next + 1), null, true); + } + + if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) { + $isLast = true; + } + + /* + Check the number of blank lines + after the function. + */ + + // Allow for comments on the same line as the closer. + for ($nextLineToken = ($closer + 1); $nextLineToken < $phpcsFile->numTokens; $nextLineToken++) { + if ($tokens[$nextLineToken]['line'] !== $tokens[$closer]['line']) { + break; + } + } + + $requiredSpacing = $this->spacing; + $errorCode = 'After'; + if ($isLast === true) { + $requiredSpacing = $this->spacingAfterLast; + $errorCode = 'AfterLast'; + } + + $foundLines = 0; + if ($nextLineToken === ($phpcsFile->numTokens - 1)) { + // We are at the end of the file. + // Don't check spacing after the function because this + // should be done by an EOF sniff. + $foundLines = $requiredSpacing; + } else { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, $nextLineToken, null, true); + if ($nextContent === false) { + // We are at the end of the file. + // Don't check spacing after the function because this + // should be done by an EOF sniff. + $foundLines = $requiredSpacing; + } else { + $foundLines = ($tokens[$nextContent]['line'] - $tokens[$nextLineToken]['line']); + } + } + + if ($isLast === true) { + $phpcsFile->recordMetric($stackPtr, 'Function spacing after last', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Function spacing after', $foundLines); + } + + if ($foundLines !== $requiredSpacing) { + $error = 'Expected %s blank line'; + if ($requiredSpacing !== 1) { + $error .= 's'; + } + + $error .= ' after function; %s found'; + $data = [ + $requiredSpacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($error, $closer, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = $nextLineToken; $i <= $nextContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + $phpcsFile->fixer->addContentBefore($i, str_repeat($phpcsFile->eolChar, $requiredSpacing)); + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + + /* + Check the number of blank lines + before the function. + */ + + $prevLineToken = null; + for ($i = $stackPtr; $i >= 0; $i--) { + if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) { + continue; + } + + $prevLineToken = $i; + break; + } + + if ($prevLineToken === null) { + // Never found the previous line, which means + // there are 0 blank lines before the function. + $foundLines = 0; + $prevContent = 0; + $prevLineToken = 0; + } else { + $currentLine = $tokens[$stackPtr]['line']; + + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, $prevLineToken, null, true); + + if ($tokens[$prevContent]['code'] === T_COMMENT + || isset(Tokens::$phpcsCommentTokens[$tokens[$prevContent]['code']]) === true + ) { + // Ignore comments as they can have different spacing rules, and this + // isn't a proper function comment anyway. + return; + } + + while ($tokens[$prevContent]['code'] === T_ATTRIBUTE_END + && $tokens[$prevContent]['line'] === ($currentLine - 1) + ) { + // Account for function attributes. + $currentLine = $tokens[$tokens[$prevContent]['attribute_opener']]['line']; + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$prevContent]['attribute_opener'] - 1), null, true); + } + + if ($tokens[$prevContent]['code'] === T_DOC_COMMENT_CLOSE_TAG + && $tokens[$prevContent]['line'] === ($currentLine - 1) + ) { + // Account for function comments. + $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$prevContent]['comment_opener'] - 1), null, true); + } + + // Before we throw an error, check that we are not throwing an error + // for another function. We don't want to error for no blank lines after + // the previous function and no blank lines before this one as well. + $stopAt = 0; + if (isset($tokens[$prevLineToken]['conditions']) === true) { + $conditions = $tokens[$prevLineToken]['conditions']; + $conditions = array_keys($conditions); + $stopAt = array_pop($conditions); + } + + $prevLineToken = $prevContent; + $prevLine = ($tokens[$prevContent]['line'] - 1); + $i = ($stackPtr - 1); + $foundLines = 0; + + while ($currentLine !== $prevLine && $currentLine > 1 && $i > $stopAt) { + if ($tokens[$i]['code'] === T_FUNCTION) { + // Found another interface or abstract function. + return; + } + + if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET + && $tokens[$tokens[$i]['scope_condition']]['code'] === T_FUNCTION + ) { + // Found a previous function. + return; + } + + $currentLine = $tokens[$i]['line']; + if ($currentLine === $prevLine) { + break; + } + + if ($tokens[($i - 1)]['line'] < $currentLine && $tokens[($i + 1)]['line'] > $currentLine) { + // This token is on a line by itself. If it is whitespace, the line is empty. + if ($tokens[$i]['code'] === T_WHITESPACE) { + $foundLines++; + } + } + + $i--; + }//end while + }//end if + + $requiredSpacing = $this->spacing; + $errorCode = 'Before'; + if ($isFirst === true) { + $requiredSpacing = $this->spacingBeforeFirst; + $errorCode = 'BeforeFirst'; + + $phpcsFile->recordMetric($stackPtr, 'Function spacing before first', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Function spacing before', $foundLines); + } + + if ($foundLines !== $requiredSpacing) { + $error = 'Expected %s blank line'; + if ($requiredSpacing !== 1) { + $error .= 's'; + } + + $error .= ' before function; %s found'; + $data = [ + $requiredSpacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data); + if ($fix === true) { + $nextSpace = $phpcsFile->findNext(T_WHITESPACE, ($prevContent + 1), $stackPtr); + if ($nextSpace === false) { + $nextSpace = ($stackPtr - 1); + } + + if ($foundLines < $requiredSpacing) { + $padding = str_repeat($phpcsFile->eolChar, ($requiredSpacing - $foundLines)); + $phpcsFile->fixer->addContent($prevLineToken, $padding); + } else { + $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($nextSpace + 1), null, true); + $phpcsFile->fixer->beginChangeset(); + for ($i = $nextSpace; $i < $nextContent; $i++) { + if ($tokens[$i]['line'] === $tokens[$prevContent]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$nextContent]['line']) { + $phpcsFile->fixer->addContentBefore($i, str_repeat($phpcsFile->eolChar, $requiredSpacing)); + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php new file mode 100644 index 000000000..c4faf158b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.3.0 Use the Generic.WhiteSpace.LanguageConstructSpacing sniff instead. + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util; + +class LanguageConstructSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_ECHO, + T_PRINT, + T_RETURN, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_NEW, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr + 1)]) === false) { + // Skip if there is no next token. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] === T_SEMICOLON) { + // No content for this language construct. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) { + $content = $tokens[($stackPtr + 1)]['content']; + if ($content !== ' ') { + $error = 'Language constructs must be followed by a single space; expected 1 space but found "%s"'; + $data = [Util\Common::prepareForOutput($content)]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'IncorrectSingle', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } else if ($tokens[($stackPtr + 1)]['code'] !== T_OPEN_PARENTHESIS) { + $error = 'Language constructs must be followed by a single space; expected "%s" but found "%s"'; + $data = [ + $tokens[$stackPtr]['content'].' '.$tokens[($stackPtr + 1)]['content'], + $tokens[$stackPtr]['content'].$tokens[($stackPtr + 1)]['content'], + ]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php new file mode 100644 index 000000000..d0f4c80c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php @@ -0,0 +1,102 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class LogicalOperatorSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$booleanOperators; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Check there is one space before the operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before logical operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + } else { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$prev]['line'] + && $tokens[($stackPtr - 1)]['length'] !== 1 + ) { + $found = $tokens[($stackPtr - 1)]['length']; + $error = 'Expected 1 space before logical operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpaceBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + } + + // Check there is one space after the operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after logical operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + } else { + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$stackPtr]['line'] === $tokens[$next]['line'] + && $tokens[($stackPtr + 1)]['length'] !== 1 + ) { + $found = $tokens[($stackPtr + 1)]['length']; + $error = 'Expected 1 space after logical operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'TooMuchSpaceAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php new file mode 100644 index 000000000..773d25d4f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php @@ -0,0 +1,252 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Tokens; + +class MemberVarSpacingSniff extends AbstractVariableSniff +{ + + /** + * The number of blank lines between member vars. + * + * @var integer + */ + public $spacing = 1; + + /** + * The number of blank lines before the first member var. + * + * @var integer + */ + public $spacingBeforeFirst = 1; + + + /** + * Processes the function tokens within the class. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $validPrefixes = Tokens::$methodPrefixes; + $validPrefixes[] = T_VAR; + + $startOfStatement = $phpcsFile->findPrevious($validPrefixes, ($stackPtr - 1), null, false, null, true); + if ($startOfStatement === false) { + return; + } + + $endOfStatement = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1), null, false, null, true); + + $ignore = $validPrefixes; + $ignore[T_WHITESPACE] = T_WHITESPACE; + + $start = $startOfStatement; + for ($prev = ($startOfStatement - 1); $prev >= 0; $prev--) { + if (isset($ignore[$tokens[$prev]['code']]) === true) { + continue; + } + + if ($tokens[$prev]['code'] === T_ATTRIBUTE_END + && isset($tokens[$prev]['attribute_opener']) === true + ) { + $prev = $tokens[$prev]['attribute_opener']; + $start = $prev; + continue; + } + + break; + } + + if (isset(Tokens::$commentTokens[$tokens[$prev]['code']]) === true) { + // Assume the comment belongs to the member var if it is on a line by itself. + $prevContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true); + if ($tokens[$prevContent]['line'] !== $tokens[$prev]['line']) { + // Check the spacing, but then skip it. + $foundLines = ($tokens[$startOfStatement]['line'] - $tokens[$prev]['line'] - 1); + if ($foundLines > 0) { + for ($i = ($prev + 1); $i < $startOfStatement; $i++) { + if ($tokens[$i]['column'] !== 1) { + continue; + } + + if ($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line'] + ) { + $error = 'Expected 0 blank lines after member var comment; %s found'; + $data = [$foundLines]; + $fix = $phpcsFile->addFixableError($error, $prev, 'AfterComment', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + // Inline comments have the newline included in the content but + // docblocks do not. + if ($tokens[$prev]['code'] === T_COMMENT) { + $phpcsFile->fixer->replaceToken($prev, rtrim($tokens[$prev]['content'])); + } + + for ($i = ($prev + 1); $i <= $startOfStatement; $i++) { + if ($tokens[$i]['line'] === $tokens[$startOfStatement]['line']) { + break; + } + + // Remove the newline after the docblock, and any entirely + // empty lines before the member var. + if (($tokens[$i]['code'] === T_WHITESPACE + && $tokens[$i]['line'] === $tokens[$prev]['line']) + || ($tokens[$i]['column'] === 1 + && $tokens[$i]['line'] !== $tokens[($i + 1)]['line']) + ) { + $phpcsFile->fixer->replaceToken($i, ''); + } + } + + $phpcsFile->fixer->addNewline($prev); + $phpcsFile->fixer->endChangeset(); + }//end if + + break; + }//end if + }//end for + }//end if + + $start = $prev; + }//end if + }//end if + + // There needs to be n blank lines before the var, not counting comments. + if ($start === $startOfStatement) { + // No comment found. + $first = $phpcsFile->findFirstOnLine(Tokens::$emptyTokens, $start, true); + if ($first === false) { + $first = $start; + } + } else if ($tokens[$start]['code'] === T_DOC_COMMENT_CLOSE_TAG) { + $first = $tokens[$start]['comment_opener']; + } else { + $first = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($start - 1), null, true); + $first = $phpcsFile->findNext(array_merge(Tokens::$commentTokens, [T_ATTRIBUTE]), ($first + 1)); + } + + // Determine if this is the first member var. + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($first - 1), null, true); + if ($tokens[$prev]['code'] === T_CLOSE_CURLY_BRACKET + && isset($tokens[$prev]['scope_condition']) === true + && $tokens[$tokens[$prev]['scope_condition']]['code'] === T_FUNCTION + ) { + return; + } + + if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET + && isset(Tokens::$ooScopeTokens[$tokens[$tokens[$prev]['scope_condition']]['code']]) === true + ) { + $errorMsg = 'Expected %s blank line(s) before first member var; %s found'; + $errorCode = 'FirstIncorrect'; + $spacing = (int) $this->spacingBeforeFirst; + } else { + $errorMsg = 'Expected %s blank line(s) before member var; %s found'; + $errorCode = 'Incorrect'; + $spacing = (int) $this->spacing; + } + + $foundLines = ($tokens[$first]['line'] - $tokens[$prev]['line'] - 1); + + if ($errorCode === 'FirstIncorrect') { + $phpcsFile->recordMetric($stackPtr, 'Member var spacing before first', $foundLines); + } else { + $phpcsFile->recordMetric($stackPtr, 'Member var spacing before', $foundLines); + } + + if ($foundLines === $spacing) { + if ($endOfStatement !== false) { + return $endOfStatement; + } + + return; + } + + $data = [ + $spacing, + $foundLines, + ]; + + $fix = $phpcsFile->addFixableError($errorMsg, $startOfStatement, $errorCode, $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = ($prev + 1); $i < $first; $i++) { + if ($tokens[$i]['line'] === $tokens[$prev]['line']) { + continue; + } + + if ($tokens[$i]['line'] === $tokens[$first]['line']) { + for ($x = 1; $x <= $spacing; $x++) { + $phpcsFile->fixer->addNewlineBefore($i); + } + + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + }//end if + + if ($endOfStatement !== false) { + return $endOfStatement; + } + + }//end processMemberVar() + + + /** + * Processes normal variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariable() + + + /** + * Processes variables in double quoted strings. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. + * @param int $stackPtr The position where the token was found. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + /* + We don't care about normal variables. + */ + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php new file mode 100644 index 000000000..1c27be7a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php @@ -0,0 +1,167 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class ObjectOperatorSpacingSniff implements Sniff +{ + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OBJECT_OPERATOR, + T_DOUBLE_COLON, + T_NULLSAFE_OBJECT_OPERATOR, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $before = 0; + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $before = 'newline'; + } else { + $before = $tokens[($stackPtr - 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing before object operator', $before); + $this->checkSpacingBeforeOperator($phpcsFile, $stackPtr, $before); + + if (isset($tokens[($stackPtr + 1)]) === false + || isset($tokens[($stackPtr + 2)]) === false + ) { + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $after = 0; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $after = 'newline'; + } else { + $after = $tokens[($stackPtr + 1)]['length']; + } + } + + $phpcsFile->recordMetric($stackPtr, 'Spacing after object operator', $after); + $this->checkSpacingAfterOperator($phpcsFile, $stackPtr, $after); + + }//end process() + + + /** + * Check the spacing before the operator. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param mixed $before The number of spaces found before the + * operator or the string 'newline'. + * + * @return boolean true if there was no error, false otherwise. + */ + protected function checkSpacingBeforeOperator(File $phpcsFile, $stackPtr, $before) + { + if ($before !== 0 + && ($before !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Space found before object operator'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $curPos = ($stackPtr - 1); + + $phpcsFile->fixer->beginChangeset(); + while ($tokens[$curPos]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($curPos, ''); + --$curPos; + } + + $phpcsFile->fixer->endChangeset(); + } + + return false; + } + + return true; + + }//end checkSpacingBeforeOperator() + + + /** + * Check the spacing after the operator. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param mixed $after The number of spaces found after the + * operator or the string 'newline'. + * + * @return boolean true if there was no error, false otherwise. + */ + protected function checkSpacingAfterOperator(File $phpcsFile, $stackPtr, $after) + { + if ($after !== 0 + && ($after !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Space found after object operator'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After'); + if ($fix === true) { + $tokens = $phpcsFile->getTokens(); + $curPos = ($stackPtr + 1); + + $phpcsFile->fixer->beginChangeset(); + while ($tokens[$curPos]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($curPos, ''); + ++$curPos; + } + + $phpcsFile->fixer->endChangeset(); + } + + return false; + } + + return true; + + }//end checkSpacingAfterOperator() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php new file mode 100644 index 000000000..2a87978a0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -0,0 +1,409 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class OperatorSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + /** + * Allow newlines instead of spaces. + * + * @var boolean + */ + public $ignoreNewlines = false; + + /** + * Don't check spacing for assignment operators. + * + * This allows multiple assignment statements to be aligned. + * + * @var boolean + */ + public $ignoreSpacingBeforeAssignments = true; + + /** + * A list of tokens that aren't considered as operands. + * + * @var string[] + */ + private $nonOperandTokens = []; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + /* + First we setup an array of all the tokens that can come before + a T_MINUS or T_PLUS token to indicate that the token is not being + used as an operator. + */ + + // Trying to operate on a negative value; eg. ($var * -1). + $this->nonOperandTokens = Tokens::$operators; + + // Trying to compare a negative value; eg. ($var === -1). + $this->nonOperandTokens += Tokens::$comparisonTokens; + + // Trying to compare a negative value; eg. ($var || -1 === $b). + $this->nonOperandTokens += Tokens::$booleanOperators; + + // Trying to assign a negative value; eg. ($var = -1). + $this->nonOperandTokens += Tokens::$assignmentTokens; + + // Returning/printing a negative value; eg. (return -1). + $this->nonOperandTokens += [ + T_RETURN => T_RETURN, + T_ECHO => T_ECHO, + T_EXIT => T_EXIT, + T_PRINT => T_PRINT, + T_YIELD => T_YIELD, + T_FN_ARROW => T_FN_ARROW, + T_MATCH_ARROW => T_MATCH_ARROW, + ]; + + // Trying to use a negative value; eg. myFunction($var, -2). + $this->nonOperandTokens += [ + T_CASE => T_CASE, + T_COLON => T_COLON, + T_COMMA => T_COMMA, + T_INLINE_ELSE => T_INLINE_ELSE, + T_INLINE_THEN => T_INLINE_THEN, + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_STRING_CONCAT => T_STRING_CONCAT, + ]; + + // Casting a negative value; eg. (array) -$a. + $this->nonOperandTokens += Tokens::$castTokens; + + /* + These are the tokens the sniff is looking for. + */ + + $targets = Tokens::$comparisonTokens; + $targets += Tokens::$operators; + $targets += Tokens::$assignmentTokens; + $targets[] = T_INLINE_THEN; + $targets[] = T_INLINE_ELSE; + $targets[] = T_INSTANCEOF; + + // Also register the contexts we want to specifically skip over. + $targets[] = T_DECLARE; + + return $targets; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return void|int Optionally returns a stack pointer. The sniff will not be + * called again on the current file until the returned stack + * pointer is reached. Return `$phpcsFile->numTokens` to skip + * the rest of the file. + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // Skip over declare statements as those should be handled by different sniffs. + if ($tokens[$stackPtr]['code'] === T_DECLARE) { + if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) { + // Parse error / live coding. + return $phpcsFile->numTokens; + } + + return $tokens[$stackPtr]['parenthesis_closer']; + } + + if ($this->isOperator($phpcsFile, $stackPtr) === false) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // Check there is one space before the & operator. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space before "&" operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBeforeAmp'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); + } else { + if ($tokens[($stackPtr - 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr - 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space before "&" operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBeforeAmp', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + } + } + }//end if + + $hasNext = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($hasNext === false) { + // Live coding/parse error at end of file. + return; + } + + // Check there is one space after the & operator. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $error = 'Expected 1 space after "&" operator; 0 found'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterAmp'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space after "&" operator; %s found'; + $data = [$found]; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfterAmp', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + + return; + }//end if + + $operator = $tokens[$stackPtr]['content']; + + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE + && (($tokens[($stackPtr - 1)]['code'] === T_INLINE_THEN + && $tokens[($stackPtr)]['code'] === T_INLINE_ELSE) === false) + ) { + $error = "Expected 1 space before \"$operator\"; 0 found"; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore'); + if ($fix === true) { + $phpcsFile->fixer->addContentBefore($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', 0); + } else if (isset(Tokens::$assignmentTokens[$tokens[$stackPtr]['code']]) === false + || $this->ignoreSpacingBeforeAssignments === false + ) { + // Throw an error for assignments only if enabled using the sniff property + // because other standards allow multiple spaces to align assignments. + $prevNonWhitespace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + if ($tokens[$prevNonWhitespace]['line'] !== $tokens[$stackPtr]['line']) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr - 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space before operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space before "%s"; %s found'; + $data = [ + $operator, + $found, + ]; + + if (isset(Tokens::$commentTokens[$tokens[$prevNonWhitespace]['code']]) === true) { + // Throw a non-fixable error if the token on the previous line is a comment token, + // as in that case it's not for the sniff to decide where the comment should be moved to + // and it would get us into unfixable situations as the new line char is included + // in the contents of the comment token. + $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + if ($found === 'newline') { + $i = ($stackPtr - 2); + while ($tokens[$i]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken($i, ''); + $i--; + } + } + + $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + }//end if + + $hasNext = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($hasNext === false) { + // Live coding/parse error at end of file. + return; + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + // Skip short ternary such as: "$foo = $bar ?: true;". + if (($tokens[$stackPtr]['code'] === T_INLINE_THEN + && $tokens[($stackPtr + 1)]['code'] === T_INLINE_ELSE) + ) { + return; + } + + $error = "Expected 1 space after \"$operator\"; 0 found"; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter'); + if ($fix === true) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', 0); + } else { + if (isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line'] + ) { + $found = 'newline'; + } else { + $found = $tokens[($stackPtr + 1)]['length']; + } + + $phpcsFile->recordMetric($stackPtr, 'Space after operator', $found); + if ($found !== 1 + && ($found !== 'newline' || $this->ignoreNewlines === false) + ) { + $error = 'Expected 1 space after "%s"; %s found'; + $data = [ + $operator, + $found, + ]; + + $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($nextNonWhitespace !== false + && isset(Tokens::$commentTokens[$tokens[$nextNonWhitespace]['code']]) === true + && $found === 'newline' + ) { + // Don't auto-fix when it's a comment or PHPCS annotation on a new line as + // it causes fixer conflicts and can cause the meaning of annotations to change. + $phpcsFile->addError($error, $stackPtr, 'SpacingAfter', $data); + } else { + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfter', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + } + } + }//end if + }//end if + + }//end process() + + + /** + * Checks if an operator is actually a different type of token in the current context. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the operator in + * the stack. + * + * @return boolean + */ + protected function isOperator(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_DECLARE) { + return false; + } + + // Skip default values in function declarations. + // Skip declare statements. + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']); + $bracket = array_pop($parenthesis); + if (isset($tokens[$bracket]['parenthesis_owner']) === true) { + $function = $tokens[$bracket]['parenthesis_owner']; + if ($tokens[$function]['code'] === T_FUNCTION + || $tokens[$function]['code'] === T_CLOSURE + || $tokens[$function]['code'] === T_FN + ) { + return false; + } + } + } + } + + if ($tokens[$stackPtr]['code'] === T_EQUAL) { + // Skip for '=&' case. + if (isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)]['code'] === T_BITWISE_AND + ) { + return false; + } + } + + if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { + // If it's not a reference, then we expect one space either side of the + // bitwise operator. + if ($phpcsFile->isReference($stackPtr) === true) { + return false; + } + } + + if ($tokens[$stackPtr]['code'] === T_MINUS || $tokens[$stackPtr]['code'] === T_PLUS) { + // Check minus spacing, but make sure we aren't just assigning + // a minus value or returning one. + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + if (isset($this->nonOperandTokens[$tokens[$prev]['code']]) === true) { + return false; + } + }//end if + + return true; + + }//end isOperator() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php new file mode 100644 index 000000000..ec8218fef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class PropertyLabelSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = ['JS']; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_PROPERTY, + T_LABEL, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $colon = $phpcsFile->findNext(T_COLON, ($stackPtr + 1)); + + if ($colon !== ($stackPtr + 1)) { + $error = 'There must be no space before the colon in a property/label declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Before'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ''); + } + } + + if ($tokens[($colon + 1)]['code'] !== T_WHITESPACE || $tokens[($colon + 1)]['content'] !== ' ') { + $error = 'There must be a single space after the colon in a property/label declaration'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'After'); + if ($fix === true) { + if ($tokens[($colon + 1)]['code'] === T_WHITESPACE) { + $phpcsFile->fixer->replaceToken(($colon + 1), ' '); + } else { + $phpcsFile->fixer->addContent($colon, ' '); + } + } + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php new file mode 100644 index 000000000..852759e58 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeClosingBraceSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return Tokens::$scopeOpeners; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + // If this is an inline condition (ie. there is no scope opener), then + // return, as this is not a new scope. + if (isset($tokens[$stackPtr]['scope_closer']) === false) { + return; + } + + // We need to actually find the first piece of content on this line, + // as if this is a method with tokens before it (public, static etc) + // or an if with an else before it, then we need to start the scope + // checking from there, rather than the current token. + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $stackPtr, true); + while ($tokens[$lineStart]['code'] === T_CONSTANT_ENCAPSED_STRING + && $tokens[($lineStart - 1)]['code'] === T_CONSTANT_ENCAPSED_STRING + ) { + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], ($lineStart - 1), true); + } + + $startColumn = $tokens[$lineStart]['column']; + $scopeStart = $tokens[$stackPtr]['scope_opener']; + $scopeEnd = $tokens[$stackPtr]['scope_closer']; + + // Check that the closing brace is on it's own line. + $lastContent = $phpcsFile->findPrevious([T_INLINE_HTML, T_WHITESPACE, T_OPEN_TAG], ($scopeEnd - 1), $scopeStart, true); + for ($lineStart = $scopeEnd; $tokens[$lineStart]['column'] > 1; $lineStart--); + + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line'] + || ($tokens[$lineStart]['code'] === T_INLINE_HTML + && trim($tokens[$lineStart]['content']) !== '') + ) { + $error = 'Closing brace must be on a line by itself'; + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'ContentBefore'); + if ($fix === true) { + if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) { + $phpcsFile->fixer->addNewlineBefore($scopeEnd); + } else { + $phpcsFile->fixer->addNewlineBefore(($lineStart + 1)); + } + } + + return; + } + + // Check now that the closing brace is lined up correctly. + $lineStart = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $scopeEnd, true); + $braceIndent = $tokens[$lineStart]['column']; + if ($tokens[$stackPtr]['code'] !== T_DEFAULT + && $tokens[$stackPtr]['code'] !== T_CASE + && $braceIndent !== $startColumn + ) { + $error = 'Closing brace indented incorrectly; expected %s spaces, found %s'; + $data = [ + ($startColumn - 1), + ($braceIndent - 1), + ]; + + $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data); + if ($fix === true) { + $diff = ($startColumn - $braceIndent); + if ($diff > 0) { + $phpcsFile->fixer->addContentBefore($lineStart, str_repeat(' ', $diff)); + } else { + $phpcsFile->fixer->substrToken(($lineStart - 1), 0, $diff); + } + } + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php new file mode 100644 index 000000000..65cc13f91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php @@ -0,0 +1,172 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ScopeKeywordSpacingSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + $register = Tokens::$scopeModifiers; + $register[] = T_STATIC; + $register[] = T_READONLY; + return $register; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (isset($tokens[($stackPtr + 1)]) === false) { + return; + } + + $prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + + if ($tokens[$stackPtr]['code'] === T_STATIC) { + if (($nextToken === false || $tokens[$nextToken]['code'] === T_DOUBLE_COLON) + || $tokens[$prevToken]['code'] === T_NEW + ) { + // Late static binding, e.g., static:: OR new static() usage or live coding. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_TYPE_UNION + ) { + // Not a scope keyword, but a union return type. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_NULLABLE + ) { + // Not a scope keyword, but a return type. + return; + } + + if ($prevToken !== false + && $tokens[$prevToken]['code'] === T_COLON + ) { + $prevPrevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevToken - 1), null, true); + if ($prevPrevToken !== false + && $tokens[$prevPrevToken]['code'] === T_CLOSE_PARENTHESIS + ) { + // Not a scope keyword, but a return type. + return; + } + } + }//end if + + if ($tokens[$prevToken]['code'] === T_AS) { + // Trait visibility change, e.g., "use HelloWorld { sayHello as private; }". + return; + } + + $isInFunctionDeclaration = false; + if (empty($tokens[$stackPtr]['nested_parenthesis']) === false) { + // Check if this is PHP 8.0 constructor property promotion. + // In that case, we can't have multi-property definitions. + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + $lastCloseParens = end($nestedParens); + if (isset($tokens[$lastCloseParens]['parenthesis_owner']) === true + && $tokens[$tokens[$lastCloseParens]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $isInFunctionDeclaration = true; + } + } + + if ($nextToken !== false + && $tokens[$nextToken]['code'] === T_VARIABLE + && $isInFunctionDeclaration === false + ) { + $endOfStatement = $phpcsFile->findNext(T_SEMICOLON, ($nextToken + 1)); + if ($endOfStatement === false) { + // Live coding. + return; + } + + $multiProperty = $phpcsFile->findNext(T_VARIABLE, ($nextToken + 1), $endOfStatement); + if ($multiProperty !== false + && $tokens[$stackPtr]['line'] !== $tokens[$nextToken]['line'] + && $tokens[$nextToken]['line'] !== $tokens[$endOfStatement]['line'] + ) { + // Allow for multiple properties definitions to each be on their own line. + return; + } + } + + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + $spacing = 0; + } else if (isset($tokens[($stackPtr + 2)]) === false) { + // Parse error/live coding. Bow out. + return; + } else { + if ($tokens[($stackPtr + 2)]['line'] !== $tokens[$stackPtr]['line']) { + $spacing = 'newline'; + } else { + $spacing = $tokens[($stackPtr + 1)]['length']; + } + } + + if ($spacing !== 1) { + $error = 'Scope keyword "%s" must be followed by a single space; found %s'; + $data = [ + $tokens[$stackPtr]['content'], + $spacing, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + if ($spacing === 0) { + $phpcsFile->fixer->addContent($stackPtr, ' '); + } else { + $phpcsFile->fixer->beginChangeset(); + + for ($i = ($stackPtr + 2); $i < $phpcsFile->numTokens; $i++) { + if (isset($tokens[$i]) === false || $tokens[$i]['code'] !== T_WHITESPACE) { + break; + } + + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); + $phpcsFile->fixer->endChangeset(); + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php new file mode 100644 index 000000000..dbf719d20 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php @@ -0,0 +1,116 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class SemicolonSpacingSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + ]; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_SEMICOLON]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + $prevType = $tokens[($stackPtr - 1)]['code']; + if (isset(Tokens::$emptyTokens[$prevType]) === false) { + return; + } + + $nonSpace = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 2), null, true); + + // Detect whether this is a semicolon for a condition in a `for()` control structure. + $forCondition = false; + if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { + $nestedParens = $tokens[$stackPtr]['nested_parenthesis']; + $closeParenthesis = end($nestedParens); + + if (isset($tokens[$closeParenthesis]['parenthesis_owner']) === true) { + $owner = $tokens[$closeParenthesis]['parenthesis_owner']; + + if ($tokens[$owner]['code'] === T_FOR) { + $forCondition = true; + $nonSpace = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 2), null, true); + } + } + } + + if ($tokens[$nonSpace]['code'] === T_SEMICOLON + || ($forCondition === true && $nonSpace === $tokens[$owner]['parenthesis_opener']) + || (isset($tokens[$nonSpace]['scope_opener']) === true + && $tokens[$nonSpace]['scope_opener'] === $nonSpace) + ) { + // Empty statement. + return; + } + + $expected = $tokens[$nonSpace]['content'].';'; + $found = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).';'; + $found = str_replace("\n", '\n', $found); + $found = str_replace("\r", '\r', $found); + $found = str_replace("\t", '\t', $found); + $error = 'Space found before semicolon; expected "%s" but found "%s"'; + $data = [ + $expected, + $found, + ]; + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = ($stackPtr - 1); + while (($tokens[$i]['code'] === T_WHITESPACE) && ($i > $nonSpace)) { + $phpcsFile->fixer->replaceToken($i, ''); + $i--; + } + + $phpcsFile->fixer->addContent($nonSpace, ';'); + $phpcsFile->fixer->replaceToken($stackPtr, ''); + + $phpcsFile->fixer->endChangeset(); + } + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php new file mode 100644 index 000000000..f13baba9f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php @@ -0,0 +1,265 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; + +class SuperfluousWhitespaceSniff implements Sniff +{ + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = [ + 'PHP', + 'JS', + 'CSS', + ]; + + /** + * If TRUE, whitespace rules are not checked for blank lines. + * + * Blank lines are those that contain only whitespace. + * + * @var boolean + */ + public $ignoreBlankLines = false; + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [ + T_OPEN_TAG, + T_OPEN_TAG_WITH_ECHO, + T_CLOSE_TAG, + T_WHITESPACE, + T_COMMENT, + T_DOC_COMMENT_WHITESPACE, + T_CLOSURE, + ]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if ($tokens[$stackPtr]['code'] === T_OPEN_TAG) { + /* + Check for start of file whitespace. + */ + + if ($phpcsFile->tokenizerType !== 'PHP') { + // The first token is always the open tag inserted when tokenized + // and the second token is always the first piece of content in + // the file. If the second token is whitespace, there was + // whitespace at the start of the file. + if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { + return; + } + + if ($phpcsFile->fixer->enabled === true) { + $stackPtr = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + } + } else { + // If it's the first token, then there is no space. + if ($stackPtr === 0) { + return; + } + + $beforeOpen = ''; + + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + // If we find something that isn't inline html then there is something previous in the file. + if ($tokens[$i]['type'] !== 'T_INLINE_HTML') { + return; + } + + $beforeOpen .= $tokens[$i]['content']; + } + + // If we have ended up with inline html make sure it isn't just whitespace. + if (preg_match('`^[\pZ\s]+$`u', $beforeOpen) !== 1) { + return; + } + }//end if + + $fix = $phpcsFile->addFixableError('Additional whitespace found at start of file', $stackPtr, 'StartFile'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + for ($i = 0; $i < $stackPtr; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) { + /* + Check for end of file whitespace. + */ + + if ($phpcsFile->tokenizerType === 'PHP') { + if (isset($tokens[($stackPtr + 1)]) === false) { + // The close PHP token is the last in the file. + return; + } + + $afterClose = ''; + + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + // If we find something that isn't inline HTML then there + // is more to the file. + if ($tokens[$i]['type'] !== 'T_INLINE_HTML') { + return; + } + + $afterClose .= $tokens[$i]['content']; + } + + // If we have ended up with inline html make sure it isn't just whitespace. + if (preg_match('`^[\pZ\s]+$`u', $afterClose) !== 1) { + return; + } + } else { + // The last token is always the close tag inserted when tokenized + // and the second last token is always the last piece of content in + // the file. If the second last token is whitespace, there was + // whitespace at the end of the file. + $stackPtr--; + + // The pointer is now looking at the last content in the file and + // not the fake PHP end tag the tokenizer inserted. + if ($tokens[$stackPtr]['code'] !== T_WHITESPACE) { + return; + } + + // Allow a single newline at the end of the last line in the file. + if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE + && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar + ) { + return; + } + }//end if + + $fix = $phpcsFile->addFixableError('Additional whitespace found at end of file', $stackPtr, 'EndFile'); + if ($fix === true) { + if ($phpcsFile->tokenizerType !== 'PHP') { + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); + $stackPtr = ($prev + 1); + } + + $phpcsFile->fixer->beginChangeset(); + for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) { + $phpcsFile->fixer->replaceToken($i, ''); + } + + $phpcsFile->fixer->endChangeset(); + } + } else { + /* + Check for end of line whitespace. + */ + + // Ignore whitespace that is not at the end of a line. + if (isset($tokens[($stackPtr + 1)]['line']) === true + && $tokens[($stackPtr + 1)]['line'] === $tokens[$stackPtr]['line'] + ) { + return; + } + + // Ignore blank lines if required. + if ($this->ignoreBlankLines === true + && $tokens[$stackPtr]['code'] === T_WHITESPACE + && $tokens[($stackPtr - 1)]['line'] !== $tokens[$stackPtr]['line'] + ) { + return; + } + + $tokenContent = rtrim($tokens[$stackPtr]['content'], $phpcsFile->eolChar); + if (empty($tokenContent) === false) { + if ($tokenContent !== rtrim($tokenContent)) { + $fix = $phpcsFile->addFixableError('Whitespace found at end of line', $stackPtr, 'EndLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, rtrim($tokenContent).$phpcsFile->eolChar); + } + } + } else if ($tokens[($stackPtr - 1)]['content'] !== rtrim($tokens[($stackPtr - 1)]['content']) + && $tokens[($stackPtr - 1)]['line'] === $tokens[$stackPtr]['line'] + ) { + $fix = $phpcsFile->addFixableError('Whitespace found at end of line', ($stackPtr - 1), 'EndLine'); + if ($fix === true) { + $phpcsFile->fixer->replaceToken(($stackPtr - 1), rtrim($tokens[($stackPtr - 1)]['content'])); + } + } + + /* + Check for multiple blank lines in a function. + */ + + if (($phpcsFile->hasCondition($stackPtr, [T_FUNCTION, T_CLOSURE]) === true) + && $tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] + && $tokens[($stackPtr - 2)]['line'] === $tokens[($stackPtr - 1)]['line'] + ) { + // Properties and functions in nested classes have their own rules for spacing. + $conditions = $tokens[$stackPtr]['conditions']; + $deepestScope = end($conditions); + if ($deepestScope === T_ANON_CLASS) { + return; + } + + // This is an empty line and the line before this one is not + // empty, so this could be the start of a multiple empty + // line block. + $next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr, null, true); + $lines = ($tokens[$next]['line'] - $tokens[$stackPtr]['line']); + if ($lines > 1) { + $error = 'Functions must not contain multiple empty lines in a row; found %s empty lines'; + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'EmptyLines', [$lines]); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $i = $stackPtr; + while ($tokens[$i]['line'] !== $tokens[$next]['line']) { + $phpcsFile->fixer->replaceToken($i, ''); + $i++; + } + + $phpcsFile->fixer->addNewlineBefore($i); + $phpcsFile->fixer->endChangeset(); + } + } + }//end if + }//end if + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc new file mode 100644 index 000000000..8ffc868a3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc @@ -0,0 +1,31 @@ + 'bar', + 'bar' => 'foo', +]; + +if ($foo) {} +[$a, $b] = $c; + +echo foo()[ 1 ]; + +echo $this->addedCustomFunctions['nonce']; +echo $this->deprecated_functions[ $function_name ]['version']; + +echo [ 1,2,3 ][0]; +echo [ 1,2,3 ][ 0 ]; +echo 'PHP'[ 0 ]; + +$array = []; +$var = $var[$var[$var]]]; // Syntax error +$var = $var[$var[$var]; // Syntax error + +$myArray[ /* key start */'key'] = $value; +$myArray[ /* key start */'key'/* key end */ ] = $value; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..41d664092 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.inc.fixed @@ -0,0 +1,31 @@ + 'bar', + 'bar' => 'foo', +]; + +if ($foo) {} +[$a, $b] = $c; + +echo foo()[1]; + +echo $this->addedCustomFunctions['nonce']; +echo $this->deprecated_functions[$function_name]['version']; + +echo [ 1,2,3 ][0]; +echo [ 1,2,3 ][0]; +echo 'PHP'[0]; + +$array = []; +$var = $var[$var[$var]]]; // Syntax error +$var = $var[$var[$var]; // Syntax error + +$myArray[/* key start */'key'] = $value; +$myArray[/* key start */'key'/* key end */] = $value; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php new file mode 100644 index 000000000..0e687b800 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Arrays; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ArrayBracketSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays\ArrayBracketSpacingSniff + */ +final class ArrayBracketSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 3, + 7 => 3, + 17 => 2, + 20 => 2, + 23 => 2, + 24 => 2, + 30 => 1, + 31 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc new file mode 100644 index 000000000..cdbfff6c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc @@ -0,0 +1,549 @@ + 1, + ); +} + +class TestClass +{ + public $good = array( + 'width' => '', + 'height' => '', + ); + + private $_bad = Array( + 'width' => '', + 'height' => '' + ); + + + public function test() + { + $truck = array( + 'width' => '', + 'height' => '', + ); + + $plane = Array( + 'width' => '', + 'height' => '', + ); + + $car = array( + 'width' => '', + 'height' => '', + ); + + $bus = array( + 'width' => '', + 'height' => '' + ); + + $train = array ( + TRUE, + FALSE, + 'aaa' + ); + + $inline = array('aaa', 'bbb', 'ccc'); + $inline = array('aaa'); + $inline = Array('aaa'); + + $bigone = array( + 'name' => 'bigone', + 'children' => Array( + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => Array( + 'child' => 'aaa', + ), + ), + 'short_name' => 'big' + ); + } + +}//end class + +$value = array ( ); +$value = array( ); +$value = array('1'=>$one, '2' => $two, '3'=> $three, '4' =>$four); +$value = array('1'=>$one); + +if (in_array('1', array('1','2','3')) === TRUE) { + $value = in_array('1', array('1' , '2', '3','4')); +} + +$value = array( + '1'=> TRUE, + FALSE, + '3' => 'aaa',); + +$value = array( + '1'=> TRUE, + FALSE, + ); + +$value = array( + TRUE, + '1' => FALSE, + ); + +$value = array(1, + 2 , + 3 , + ); + +$value = array(1 => $one, + 2 => $two , + 3 => $three , + ); + +$value = array( + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2 + ) + ); + +// Space in second arg. +$args = array( + '"'.$this->id.'"', + (int) $hasSessions, + ); + +// No errors. +$paths = array( + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ); + +$x = array( + ); + +$x = array('test' + ); +$x = array('test', + ); +$x = array('name' => 'test', + ); + +$x = array( + $x, + ); + +$func = array( + $x, + 'get'.$x.'Replacement' + ); + +$array = array( + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ); + +$array = array( + 'input_one', + 'inputTwo', + 'input_3', + ); + +// Malformed +$foo = array(1 +, 2); + +$listItems[$aliasPath] = array('itemContent' => implode('
    ', $aliases)); + +$listItems[$aliasPath] = array( + 'itemContent' => implode('
    ', $aliases) + ); + +$x = array + ( + $x, + $y, + ); + +$x = array +( + $x, + $y, + ); + +$x = array( + + $x, + $y, + ); + +$test = array( + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ); + +$c = array('a' => 1,); + +function b() +{ + $a = array( + 'a' => a('a'), + + ); + +} + +$foo = Array('[',']',':',"\n","\r"); +$bar = Array('[',']',':',' ',' '); + +function foo() +{ + return array($a, $b->screen); +} + +$array = array( + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => array( + new \Zend\Validator\InArray(array('haystack' => array_keys($aSubjects))), + ), + ); + +$var = array( + 'ViewHelper', + array('Foo'), + 'Errors', + ); + +$data = array( + 'first', + 'second', + 'third', + // Add more here + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$data = array( + 'first', + 'second' + //'third', + ); + +$foo = array( + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ); + +$foo = array( + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ); + +$weightings = array( + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ); + +foreach (array( + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ) as $key => $value) { +} + +$ids = array( + '1', // Foo. + '13', // Bar. + ); + +array( + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + } +); + +array( + 'key1' => array( + '1', + '2', + ) +); + +$var = array( + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ); + +function test() : array +{ + return []; +} + +$fields = array( + 'id' => array('type' => 'INT'), + 'value' => array('type' => 'VARCHAR')); + +get_current_screen()->add_help_tab( array( + 'id' => << false); + +$x = array( + 'xxxx' => array('aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false), +); + +$foo = array + ('foo' => array + ('bar1' => 1 + ,'bar2' => 1 + ,'bar3' => 1 + ,'bar4' => 1 + ,'bar5' => 1 + ) + ); + +$foo = array( + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ); + +$foo = foo( + array( + // comment + ) +); + +$foo = array( + << lorem( + 1 + ), 2 => 2, +); + +$foo = array( + 'тип' => 'авто', + 'цвет' => 'Ñиний', + ); + +$paths = array( + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'Ñиний', + ); + +$foo = array(<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ); + +$array = array( + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ); + +$foo = array( + $this->fn => 'value', + $foo->fn => 'value', + ); + +array($a, $b, +$c); + +array('a' => $a, 'b' => $b, +'c' => $c); + +array( + static function() { + return null; + }, + (array) array(), + (bool) array(), + (double) array(), + (int) array(), + (object) array(), + (string) array(), + (unset) array(), +); + +array( + 'foo', + 'bar' + // This is a non-fixable error. + , +); + +yield array( + static fn () : string => '', +); + +yield array( + static fn () : string => '', + ); + +$foo = array( + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ); + +// Intentional syntax error. +$a = array( + 'a' => + ); + +// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered. +$x = array( + ...$a, + 'foo' => 'bar', + ); + +$x = array( + 'foo' => 'bar', + ...$a, + ); + +$x = array( + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + ); + +$x = array( + ...$a, + 'foo' => 'bar', // OK. + 'bar', // NoKeySpecified Error (based on second entry). + ); + +$x = array( + ...$a, + 'bar', // OK. + 'foo' => 'bar', // KeySpecified Error (based on second entry). + ); + +$x = array( + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + 'bar', // NoKeySpecified Error (based on first entry). + ); + +$x = array( + 'bar', + ...$a, + 'bar', + 'baz' => 'bar', // KeySpecified (based on first entry). + ); + + $x = + array( + 'a', + 'b', + ); + +$x = array( + 1, static fn (float $item): float => match ($item) { + 2.0 => 3.0, + default => $item + }, + ); + +$x = array( + 1, static::helloWorld(), $class instanceof static, + 2, + ); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed new file mode 100644 index 000000000..6f8fe216a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,588 @@ + 1); +} + +class TestClass +{ + public $good = array( + 'width' => '', + 'height' => '', + ); + + private $_bad = array( + 'width' => '', + 'height' => '', + ); + + + public function test() + { + $truck = array( + 'width' => '', + 'height' => '', + ); + + $plane = array( + 'width' => '', + 'height' => '', + ); + + $car = array( + 'width' => '', + 'height' => '', + ); + + $bus = array( + 'width' => '', + 'height' => '', + ); + + $train = array( + TRUE, + FALSE, + 'aaa', + ); + + $inline = array( + 'aaa', + 'bbb', + 'ccc', + ); + $inline = array('aaa'); + $inline = array('aaa'); + + $bigone = array( + 'name' => 'bigone', + 'children' => array( + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => array('child' => 'aaa'), + ), + 'short_name' => 'big', + ); + } + +}//end class + +$value = array(); +$value = array(); +$value = array( + '1' => $one, + '2' => $two, + '3' => $three, + '4' => $four, + ); +$value = array('1' => $one); + +if (in_array('1', array('1', '2', '3')) === TRUE) { + $value = in_array('1', array('1', '2', '3', '4')); +} + +$value = array( + '1'=> TRUE, + FALSE, + '3' => 'aaa', + ); + +$value = array( + '1'=> TRUE, + FALSE, + ); + +$value = array( + TRUE, + '1' => FALSE, + ); + +$value = array( + 1, + 2, + 3, + ); + +$value = array( + 1 => $one, + 2 => $two, + 3 => $three, + ); + +$value = array( + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +$expected = array( + array( + '1' => 1, + '1' => 2, + ), + ); + +// Space in second arg. +$args = array( + '"'.$this->id.'"', + (int) $hasSessions, + ); + +// No errors. +$paths = array( + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ); + +$x = array(); + +$x = array('test'); +$x = array('test'); +$x = array('name' => 'test'); + +$x = array($x); + +$func = array( + $x, + 'get'.$x.'Replacement', + ); + +$array = array( + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ); + +$array = array( + 'input_one', + 'inputTwo', + 'input_3', + ); + +// Malformed +$foo = array( + 1, + 2, + ); + +$listItems[$aliasPath] = array('itemContent' => implode('
    ', $aliases)); + +$listItems[$aliasPath] = array( + 'itemContent' => implode('
    ', $aliases), + ); + +$x = array( + $x, + $y, + ); + +$x = array( + $x, + $y, + ); + +$x = array( + + $x, + $y, + ); + +$test = array( + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ); + +$c = array('a' => 1); + +function b() +{ + $a = array( + 'a' => a('a'), + + ); + +} + +$foo = array( + '[', + ']', + ':', + "\n", + "\r", + ); +$bar = array( + '[', + ']', + ':', + ' ', + ' ', + ); + +function foo() +{ + return array( + $a, + $b->screen, + ); +} + +$array = array( + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => array( + new \Zend\Validator\InArray(array('haystack' => array_keys($aSubjects))), + ), + ); + +$var = array( + 'ViewHelper', + array('Foo'), + 'Errors', + ); + +$data = array( + 'first', + 'second', + 'third', + // Add more here + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$data = array( + 'first', + 'second', + //'third', + ); + +$foo = array( + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ); + +$foo = array( + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ); + +$weightings = array( + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ); + +foreach (array( + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ) as $key => $value) { +} + +$ids = array( + '1', // Foo. + '13', // Bar. + ); + +array( + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + }, +); + +array( + 'key1' => array( + '1', + '2', + ), +); + +$var = array( + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ); + +function test() : array +{ + return []; +} + +$fields = array( + 'id' => array('type' => 'INT'), + 'value' => array('type' => 'VARCHAR'), + ); + +get_current_screen()->add_help_tab( array( + 'id' => << false); + +$x = array( + 'xxxx' => array( + 'aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false, + ), + ); + +$foo = array( + 'foo' => array( + 'bar1' => 1, + 'bar2' => 1, + 'bar3' => 1, + 'bar4' => 1, + 'bar5' => 1, + ), + ); + +$foo = array( + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ); + +$foo = foo( + array( + // comment + ) +); + +$foo = array( + << lorem( + 1 + ), + 2 => 2, +); + +$foo = array( + 'тип' => 'авто', + 'цвет' => 'Ñиний', + ); + +$paths = array( + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'Ñиний', + ); + +$foo = array(<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ); + +$array = array( + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ); + +$foo = array( + $this->fn => 'value', + $foo->fn => 'value', + ); + +array( + $a, + $b, + $c, +); + +array( + 'a' => $a, + 'b' => $b, + 'c' => $c, +); + +array( + static function() { + return null; + }, + (array) array(), + (bool) array(), + (double) array(), + (int) array(), + (object) array(), + (string) array(), + (unset) array(), +); + +array( + 'foo', + 'bar' + // This is a non-fixable error. + , +); + +yield array( + static fn () : string => '', + ); + +yield array( + static fn () : string => '', + ); + +$foo = array( + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ); + +// Intentional syntax error. +$a = array( + 'a' => + ); + +// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered. +$x = array( + ...$a, + 'foo' => 'bar', + ); + +$x = array( + 'foo' => 'bar', + ...$a, + ); + +$x = array( + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + ); + +$x = array( + ...$a, + 'foo' => 'bar', // OK. + 'bar', // NoKeySpecified Error (based on second entry). + ); + +$x = array( + ...$a, + 'bar', // OK. + 'foo' => 'bar', // KeySpecified Error (based on second entry). + ); + +$x = array( + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + 'bar', // NoKeySpecified Error (based on first entry). + ); + +$x = array( + 'bar', + ...$a, + 'bar', + 'baz' => 'bar', // KeySpecified (based on first entry). + ); + + $x = + array( + 'a', + 'b', + ); + +$x = array( + 1, + static fn (float $item): float => match ($item) { + 2.0 => 3.0, + default => $item + }, + ); + +$x = array( + 1, + static::helloWorld(), + $class instanceof static, + 2, + ); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc new file mode 100644 index 000000000..90b026f02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc @@ -0,0 +1,538 @@ + 1, + ]; +} + +class TestClass +{ + public $good = [ + 'width' => '', + 'height' => '', + ]; + + private $_bad = [ + 'width' => '', + 'height' => '' + ]; + + + public function test() + { + $truck = [ + 'width' => '', + 'height' => '', + ]; + + $plane = [ + 'width' => '', + 'height' => '', + ]; + + $car = [ + 'width' => '', + 'height' => '', + ]; + + $bus = [ + 'width' => '', + 'height' => '' + ]; + + $train = [ + TRUE, + FALSE, + 'aaa' + ]; + + $inline = ['aaa', 'bbb', 'ccc']; + $inline = ['aaa']; + $inline = ['aaa']; + + $bigone = [ + 'name' => 'bigone', + 'children' => [ + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => [ + 'child' => 'aaa', + ], + ], + 'short_name' => 'big' + ]; + } + +}//end class + +$value = [ ]; +$value = [ ]; +$value = ['1'=>$one, '2' => $two, '3'=> $three, '4' =>$four]; +$value = ['1'=>$one]; + +if (in_array('1', ['1','2','3']) === TRUE) { + $value = in_array('1', ['1' , '2', '3','4']); +} + +$value = [ + '1'=> TRUE, + FALSE, + '3' => 'aaa',]; + +$value = [ + '1'=> TRUE, + FALSE, + ]; + +$value = [ + TRUE, + '1' => FALSE, + ]; + +$value = [1, + 2 , + 3 , + ]; + +$value = [1 => $one, + 2 => $two , + 3 => $three , + ]; + +$value = [ + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2 + ] + ]; + +// Space in second arg. +$args = [ + '"'.$this->id.'"', + (int) $hasSessions, + ]; + +// No errors. +$paths = [ + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ]; + +$x = [ + ]; + +$x = ['test' + ]; +$x = ['test', + ]; +$x = ['name' => 'test', + ]; + +$x = [ + $x, + ]; + +$func = [ + $x, + 'get'.$x.'Replacement' + ]; + +$array = [ + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ]; + +$array = [ + 'input_one', + 'inputTwo', + 'input_3', + ]; + +// Malformed +$foo = [1 +, 2]; + +$listItems[$aliasPath] = ['itemContent' => implode('
    ', $aliases)]; + +$listItems[$aliasPath] = [ + 'itemContent' => implode('
    ', $aliases) + ]; + +$x = + [ + $x, + $y, + ]; + +$x = +[ + $x, + $y, + ]; + +$x = [ + + $x, + $y, + ]; + +$test = [ + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ]; + +$c = ['a' => 1,]; +$c->{$var}[ ] = 2; + +$foo = ['[',']',':',"\n","\r"]; +$bar = ['[',']',':',' ',' ']; + +function foo() +{ + return [$a, $b->screen]; +} + +$array = [ + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => [ + new \Zend\Validator\InArray(['haystack' => array_keys($aSubjects)]), + ], + ]; + +$var = [ + 'ViewHelper', + ['Foo'], + 'Errors', + ]; + +$data = [ + 'first', + 'second', + 'third', + // Add more here + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$data = [ + 'first', + 'second' + //'third', + ]; + +$foo = [ + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ]; + +$foo = [ + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ]; + +$weightings = [ + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ]; + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} + +$ids = [ + '1', // Foo. + '13', // Bar. + ]; + +[ + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + } +]; + +[ + 'key1' => [ + '1', + '2', + ] +]; + +$var = [ + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ]; + +function test() : array +{ + return []; +} + +$fields = [ + 'id' => ['type' => 'INT'], + 'value' => ['type' => 'VARCHAR']]; + +get_current_screen()->add_help_tab( [ + 'id' => << false]; + +$x = [ + 'xxxx' => ['aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false], +]; + +$foo = ['foo' => ['bar1' => 1 + ,'bar2' => 1 + ,'bar3' => 1 + ,'bar4' => 1 + ,'bar5' => 1 + ] + ]; + +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], ['notverified', 'unverified'], true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ]; + + +$foo = foo( + [ + // comment + ] +); + +$foo = [ + << lorem( + 1 + ), 2 => 2, +]; + +$foo = [ + 'тип' => 'авто', + 'цвет' => 'Ñиний', + ]; + +$paths = [ + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'Ñиний', + ]; + +$foo = [<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ]; + +$array = [ + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ]; + +$foo = [ + $this->fn => 'value', + $foo->fn => 'value', + ]; + +[$a, $b, +$c]; + +['a' => $a, 'b' => $b, +'c' => $c]; + +[ + static function() { + return null; + }, + (array) [], + (bool) [], + (double) [], + (int) [], + (object) [], + (string) [], + (unset) [], +]; + +[ + 'foo', + 'bar' + // This is a non-fixable error. + , +]; + +yield [ + static fn () : string => '', +]; + +yield [ + static fn () : string => '', + ]; + +$foo = [ + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ]; + +// Intentional syntax error. +$a = [ + 'a' => + ]; + +// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered. +$x = [ + ...$a, + 'foo' => 'bar', + ]; + +$x = [ + 'foo' => 'bar', + ...$a, + ]; + +$x = [ + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + ]; + +$x = [ + ...$a, + 'foo' => 'bar', // OK. + 'bar', // NoKeySpecified Error (based on second entry). + ]; + +$x = [ + ...$a, + 'bar', // OK. + 'foo' => 'bar', // KeySpecified Error (based on second entry). + ]; + +$x = [ + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + 'bar', // NoKeySpecified Error (based on first entry). + ]; + +$x = [ + 'bar', + ...$a, + 'bar', + 'baz' => 'bar', // KeySpecified (based on first entry). + ]; + + $x = + [ + 'a', + 'b', + ]; + +$x = [ + 1, static fn (float $item): float => match ($item) { + 2.0 => 3.0, + default => $item + }, + ]; + +$x = [ + 1, static::helloWorld(), $class instanceof static, + 2, + ]; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed new file mode 100644 index 000000000..533be16a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.2.inc.fixed @@ -0,0 +1,575 @@ + 1]; +} + +class TestClass +{ + public $good = [ + 'width' => '', + 'height' => '', + ]; + + private $_bad = [ + 'width' => '', + 'height' => '', + ]; + + + public function test() + { + $truck = [ + 'width' => '', + 'height' => '', + ]; + + $plane = [ + 'width' => '', + 'height' => '', + ]; + + $car = [ + 'width' => '', + 'height' => '', + ]; + + $bus = [ + 'width' => '', + 'height' => '', + ]; + + $train = [ + TRUE, + FALSE, + 'aaa', + ]; + + $inline = [ + 'aaa', + 'bbb', + 'ccc', + ]; + $inline = ['aaa']; + $inline = ['aaa']; + + $bigone = [ + 'name' => 'bigone', + 'children' => [ + '1a' => 'child', + '11b' => 'child', + '111c' => 'child', + 'children' => ['child' => 'aaa'], + ], + 'short_name' => 'big', + ]; + } + +}//end class + +$value = []; +$value = []; +$value = [ + '1' => $one, + '2' => $two, + '3' => $three, + '4' => $four, + ]; +$value = ['1' => $one]; + +if (in_array('1', ['1', '2', '3']) === TRUE) { + $value = in_array('1', ['1', '2', '3', '4']); +} + +$value = [ + '1'=> TRUE, + FALSE, + '3' => 'aaa', + ]; + +$value = [ + '1'=> TRUE, + FALSE, + ]; + +$value = [ + TRUE, + '1' => FALSE, + ]; + +$value = [ + 1, + 2, + 3, + ]; + +$value = [ + 1 => $one, + 2 => $two, + 3 => $three, + ]; + +$value = [ + 'tag' => $tag, + 'space' => $this->_getIndentation($tag, $tagElement), + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +$expected = [ + [ + '1' => 1, + '1' => 2, + ], + ]; + +// Space in second arg. +$args = [ + '"'.$this->id.'"', + (int) $hasSessions, + ]; + +// No errors. +$paths = [ + Init::ROOT_DIR.'/Systems' => 'Systems', + Init::ROOT_DIR.'/Installer' => 'Systems', + ]; + +$x = []; + +$x = ['test']; +$x = ['test']; +$x = ['name' => 'test']; + +$x = [$x]; + +$func = [ + $x, + 'get'.$x.'Replacement', + ]; + +$array = [ + 'input_one' => 'one', + 'inputTwo' => 'two', + 'input_3' => 3, + ]; + +$array = [ + 'input_one', + 'inputTwo', + 'input_3', + ]; + +// Malformed +$foo = [ + 1, + 2, + ]; + +$listItems[$aliasPath] = ['itemContent' => implode('
    ', $aliases)]; + +$listItems[$aliasPath] = [ + 'itemContent' => implode('
    ', $aliases), + ]; + +$x = + [ + $x, + $y, + ]; + +$x = +[ + $x, + $y, +]; + +$x = [ + + $x, + $y, + ]; + +$test = [ + 'test' => TestFunction::blah( + $value1, + $value2 + ), + ]; + +$c = ['a' => 1]; +$c->{$var}[ ] = 2; + +$foo = [ + '[', + ']', + ':', + "\n", + "\r", + ]; +$bar = [ + '[', + ']', + ':', + ' ', + ' ', + ]; + +function foo() +{ + return [ + $a, + $b->screen, + ]; +} + +$array = [ + 'name' => 'contactSubject', + 'required' => TRUE, + 'validators' => [ + new \Zend\Validator\InArray(['haystack' => array_keys($aSubjects)]), + ], + ]; + +$var = [ + 'ViewHelper', + ['Foo'], + 'Errors', + ]; + +$data = [ + 'first', + 'second', + 'third', + // Add more here + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$data = [ + 'first', + 'second', + //'third', + ]; + +$foo = [ + $this->getViewName() . '.id' => 'value', + $this->getViewName() . '.title' => 'value', + ]; + +$foo = [ + $this->getViewName() . '.id', + $this->getViewName() . '.title', + ]; + +$weightings = [ + T_CLOSURE => 100, + + /* + Conditions. + */ + + T_WHILE => 50, + + /* + Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + + T_BOOLEAN_AND => 5, + + /* + Equality. + */ + + T_IS_GREATER_OR_EQUAL => 5, + ]; + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} + +$ids = [ + '1', // Foo. + '13', // Bar. + ]; + +[ + 'key1' => function($bar) { + return $bar; + }, + 'key2' => function($foo) { + return $foo; + }, + 'key3' => function($bar) { + return $bar; + }, +]; + +[ + 'key1' => [ + '1', + '2', + ], +]; + +$var = [ + 'tab_template' => ' +
  • %s
  • ', + 'panel_template' => ' +
    + %s +
    ', + ]; + +function test() : array +{ + return []; +} + +$fields = [ + 'id' => ['type' => 'INT'], + 'value' => ['type' => 'VARCHAR'], + ]; + +get_current_screen()->add_help_tab( [ + 'id' => << false]; + +$x = [ + 'xxxx' => [ + 'aaaaaaaaaa' => 'ccccccccccc', + 'bbbbbbbb' => false, + ], + ]; + +$foo = [ + 'foo' => [ + 'bar1' => 1, + 'bar2' => 1, + 'bar3' => 1, + 'bar4' => 1, + 'bar5' => 1, + ], + ]; + +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], ['notverified', 'unverified'], true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), + ]; + + +$foo = foo( + [ + // comment + ] +); + +$foo = [ + << lorem( + 1 + ), + 2 => 2, +]; + +$foo = [ + 'тип' => 'авто', + 'цвет' => 'Ñиний', + ]; + +$paths = [ + Init::ROOT_DIR.'/тип' => 'авто', + Init::ROOT_DIR.'/цвет' => 'Ñиний', + ]; + +$foo = [<< fn() => return 1, + 'bb' => fn() => return 2, + 'ccc' => ( true ) ? + fn() => return 1 : + fn() => return 2, + ]; + +$array = [ + 1 => '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', + ]; + +$foo = [ + $this->fn => 'value', + $foo->fn => 'value', + ]; + +[ + $a, + $b, + $c, +]; + +[ + 'a' => $a, + 'b' => $b, + 'c' => $c, +]; + +[ + static function() { + return null; + }, + (array) [], + (bool) [], + (double) [], + (int) [], + (object) [], + (string) [], + (unset) [], +]; + +[ + 'foo', + 'bar' + // This is a non-fixable error. + , +]; + +yield [ + static fn () : string => '', + ]; + +yield [ + static fn () : string => '', + ]; + +$foo = [ + 'foo' => match ($anything) { + 'foo' => 'bar', + default => null, + }, + ]; + +// Intentional syntax error. +$a = [ + 'a' => + ]; + +// Safeguard correct errors for key/no key when PHP 7.4+ array unpacking is encountered. +$x = [ + ...$a, + 'foo' => 'bar', + ]; + +$x = [ + 'foo' => 'bar', + ...$a, + ]; + +$x = [ + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + ]; + +$x = [ + ...$a, + 'foo' => 'bar', // OK. + 'bar', // NoKeySpecified Error (based on second entry). + ]; + +$x = [ + ...$a, + 'bar', // OK. + 'foo' => 'bar', // KeySpecified Error (based on second entry). + ]; + +$x = [ + 'foo' => 'bar', + ...$a, + 'baz' => 'bar', + 'bar', // NoKeySpecified Error (based on first entry). + ]; + +$x = [ + 'bar', + ...$a, + 'bar', + 'baz' => 'bar', // KeySpecified (based on first entry). + ]; + + $x = + [ + 'a', + 'b', + ]; + +$x = [ + 1, + static fn (float $item): float => match ($item) { + 2.0 => 3.0, + default => $item + }, + ]; + +$x = [ + 1, + static::helloWorld(), + $class instanceof static, + 2, + ]; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php new file mode 100644 index 000000000..b34044b2d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php @@ -0,0 +1,255 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Arrays; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ArrayDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Arrays\ArrayDeclarationSniff + */ +final class ArrayDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ArrayDeclarationUnitTest.1.inc': + return [ + 2 => 1, + 8 => 2, + 10 => 2, + 22 => 1, + 23 => 2, + 24 => 2, + 25 => 1, + 31 => 2, + 35 => 1, + 36 => 2, + 41 => 1, + 46 => 1, + 47 => 1, + 50 => 1, + 51 => 1, + 53 => 1, + 56 => 1, + 58 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 3, + 70 => 1, + 76 => 2, + 77 => 1, + 78 => 7, + 79 => 2, + 81 => 2, + 82 => 4, + 87 => 1, + 88 => 1, + 92 => 1, + 97 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 125 => 1, + 126 => 1, + 141 => 1, + 144 => 1, + 146 => 1, + 148 => 1, + 151 => 1, + 157 => 1, + 173 => 1, + 174 => 3, + 179 => 1, + 182 => 1, + 188 => 1, + 207 => 1, + 212 => 2, + 214 => 1, + 218 => 2, + 219 => 2, + 223 => 1, + 255 => 1, + 294 => 1, + 295 => 1, + 296 => 1, + 311 => 1, + 317 => 1, + 339 => 2, + 348 => 2, + 352 => 2, + 355 => 3, + 358 => 3, + 359 => 2, + 360 => 1, + 362 => 1, + 363 => 2, + 364 => 1, + 365 => 2, + 366 => 2, + 367 => 2, + 368 => 2, + 369 => 1, + 370 => 1, + 383 => 1, + 394 => 1, + 400 => 1, + 406 => 1, + 441 => 1, + 444 => 2, + 445 => 2, + 447 => 2, + 448 => 3, + 467 => 1, + 471 => 1, + 472 => 1, + 510 => 1, + 516 => 1, + 523 => 1, + 530 => 1, + 537 => 1, + 540 => 1, + 547 => 2, + ]; + case 'ArrayDeclarationUnitTest.2.inc': + return [ + 2 => 1, + 10 => 1, + 23 => 2, + 24 => 2, + 25 => 1, + 31 => 2, + 36 => 2, + 41 => 1, + 46 => 1, + 47 => 1, + 51 => 1, + 53 => 1, + 56 => 1, + 61 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 2, + 70 => 1, + 76 => 1, + 77 => 1, + 78 => 7, + 79 => 2, + 81 => 2, + 82 => 4, + 87 => 1, + 88 => 1, + 92 => 1, + 97 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + 125 => 1, + 126 => 1, + 141 => 1, + 144 => 1, + 146 => 1, + 148 => 1, + 151 => 1, + 157 => 1, + 173 => 1, + 174 => 3, + 179 => 1, + 190 => 1, + 191 => 1, + 192 => 1, + 207 => 1, + 210 => 1, + 211 => 1, + 215 => 1, + 247 => 1, + 286 => 1, + 287 => 1, + 288 => 1, + 303 => 1, + 309 => 1, + 331 => 2, + 345 => 3, + 348 => 3, + 349 => 2, + 350 => 1, + 352 => 2, + 353 => 2, + 354 => 2, + 355 => 2, + 356 => 2, + 357 => 1, + 358 => 1, + 372 => 1, + 383 => 1, + 389 => 1, + 395 => 1, + 430 => 1, + 433 => 2, + 434 => 2, + 436 => 2, + 437 => 3, + 456 => 1, + 460 => 1, + 461 => 1, + 499 => 1, + 505 => 1, + 512 => 1, + 519 => 1, + 526 => 1, + 529 => 1, + 536 => 2, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css new file mode 100644 index 000000000..39abce232 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css @@ -0,0 +1,81 @@ +.my-style { +} + + +.my-style { +} + +/* Comment */ + +.my-style { +} + + +/* Comment */ + +.my-style { + float: left; + +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +/*.AssetLineageWidgetType-item2 .selected, +.AssetLineageWidgetType-item .selected { +}*/ + +.AssetLineageWidgetType-item.selected { +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } +} + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + .no-blank-line-after { + } + .no-blank-line-after-second-def { + } .my-style { + } + + .no-blank-line-and-trailing-comment { + } /* end long class */ + .too-many-blank-lines-and-trailing-comment-extra-whitespace-after-brace { + } /* end long class */ + + + + .has-blank-line-and-trailing-comment { + } /* end long class */ + + .no-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + .too-many-blank-lines-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + + + .has-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%;}} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed new file mode 100644 index 000000000..ca77e83b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css.fixed @@ -0,0 +1,85 @@ +.my-style { +} + +.my-style { +} + +/* Comment */ + +.my-style { +} + +/* Comment */ + +.my-style { + float: left; + +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +/*.AssetLineageWidgetType-item2 .selected, +.AssetLineageWidgetType-item .selected { +}*/ + +.AssetLineageWidgetType-item.selected { +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after { +} + +@media screen and (max-device-width: 769px) { + .no-blank-line-after { + } + + .no-blank-line-after-second-def { + } + +.my-style { + } + + .no-blank-line-and-trailing-comment { + } /* end long class */ + + .too-many-blank-lines-and-trailing-comment-extra-whitespace-after-brace { + } /* end long class */ + + .has-blank-line-and-trailing-comment { + } /* end long class */ + + .no-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + .too-many-blank-lines-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + + .has-blank-line-and-annotation { + } /* phpcs:ignore Standard.Cat.SniffName -- for reasons */ + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; +} + +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php new file mode 100644 index 000000000..c9770cc16 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDefinitionClosingBraceSpace sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ClassDefinitionClosingBraceSpaceSniff + */ +final class ClassDefinitionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 11 => 1, + 44 => 1, + 47 => 1, + 51 => 1, + 53 => 1, + 57 => 1, + 59 => 1, + 67 => 1, + 69 => 1, + 81 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css new file mode 100644 index 000000000..6496cb839 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css @@ -0,0 +1,66 @@ +.AssetListingEditWidgetType-BottomPanel select, +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, + +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, +/*.AssetListingEditWidgetType-BottomPanel ul,*/ +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +.AssetListingEditWidgetType-BottomPanel select, + +.AssetListingEditWidgetType-BottomPanel ul, +#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew { + float: left; +} + +#SuperUsersSystemConfigScreen-table { + display: block; + left: 50%; + margin-left: -500px; + margin-top: 180px; + position: relative; + width: 1000px; +} + +/** + * More styles below here. + */ + +td.TableWidgetType-header.TableWidgetType-header-lastLogin, +td.TableWidgetType-header.TableWidgetType-header-remove, +td.TableWidgetType-header.TableWidgetType-header-email, +td.TableWidgetType-header.TableWidgetType-header-userName { + background: url(images/ScreenImages/table_header_bg.png) repeat-x; + border-top: 1px solid #D4D4D4; + color: #787878; + height: 33px; + padding-left: 12px; + width: 150px; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +.foo +{ + border: none; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php new file mode 100644 index 000000000..5320047c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDefinitionNameSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ClassDefinitionNameSpacingSniff + */ +final class ClassDefinitionNameSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 19 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css new file mode 100644 index 000000000..98c8fa563 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css @@ -0,0 +1,108 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title{ + float: left; +} +.HelpWidgetType-new-bug-title { + + float: left; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after {} + +.single-line {float: left;} + +#opening-brace-on-different-line + + +{ + color: #FFFFFF; +} + +#opening-brace-on-different-line-and-inline-style + + +{color: #FFFFFF;} + +@media screen and (max-device-width: 769px) { .everything-on-one-line { float: left; } } + +/* Document handling of comments in various places */ +.no-space-before-opening-with-comment /* comment*/{ + float: left; +} + +.space-before-opening-with-comment-on-next-line +/* comment*/ { + float: left; +} + +#opening-brace-on-different-line-with-comment-between +/*comment*/ +{ + padding: 0; +} + +.single-line-with-comment { /* comment*/ float: left; } + +.multi-line-with-trailing-comment { /* comment*/ + float: left; +} + + +@media screen and (max-device-width: 769px) { + /*comment*/ + .comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .blank-line-and-comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + + + /* phpcs:ignore Standard.Category.Sniffname -- for reasons */ + .blank-line-and-annotation-after-nesting-class-opening { + } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed new file mode 100644 index 000000000..b3f48a5ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css.fixed @@ -0,0 +1,106 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + + float: left; +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + +} + +.GUITextBox.container:after { +} + +.single-line { +float: left;} + +#opening-brace-on-different-line { + color: #FFFFFF; +} + +#opening-brace-on-different-line-and-inline-style { +color: #FFFFFF;} + +@media screen and (max-device-width: 769px) { + +.everything-on-one-line { +float: left; } } + +/* Document handling of comments in various places */ +.no-space-before-opening-with-comment /* comment*/ { + float: left; +} + +.space-before-opening-with-comment-on-next-line +/* comment*/ { + float: left; +} + +#opening-brace-on-different-line-with-comment-between +/*comment*/ { + padding: 0; +} + +.single-line-with-comment { +/* comment*/ float: left; } + +.multi-line-with-trailing-comment { /* comment*/ + float: left; +} + + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /*comment*/ + .blank-line-and-comment-line-after-nesting-class-opening { + } +} + +@media screen and (max-device-width: 769px) { + + /* phpcs:ignore Standard.Category.Sniffname -- for reasons */ + .blank-line-and-annotation-after-nesting-class-opening { + } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php new file mode 100644 index 000000000..3d5f37bb6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php @@ -0,0 +1,69 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDefinitionOpeningBraceSpace sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ClassDefinitionOpeningBraceSpaceSniff + */ +final class ClassDefinitionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 7 => 1, + 10 => 1, + 26 => 1, + 33 => 1, + 43 => 1, + 45 => 1, + 50 => 1, + 57 => 2, + 59 => 2, + 62 => 1, + 73 => 1, + 77 => 1, + 84 => 1, + 97 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css new file mode 100644 index 000000000..391bc85ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css @@ -0,0 +1,42 @@ +body { +font-family: Arial, Helvetica, sans-serif; +margin : 40px 0 0 0; +padding : 0; +background: #8FB7DB url(diag_lines_bg.gif) top left; +margin-top: +10px; +margin-bottom: +0px; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited { + text-decoration: none; + color: #444; +} + +/* checking embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; + margin:0px; + padding-left:10px; + margin-bottom:px; + margin-top: px; + line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Empty style defs. */ +.p { + margin:; + margin-right: + margin-left: 10px; + float:/* Some comment. */ ; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed new file mode 100644 index 000000000..e68bddce6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.css.fixed @@ -0,0 +1,40 @@ +body { +font-family: Arial, Helvetica, sans-serif; +margin: 40px 0 0 0; +padding: 0; +background: #8FB7DB url(diag_lines_bg.gif) top left; +margin-top: 10px; +margin-bottom: 0px; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited { + text-decoration: none; + color: #444; +} + +/* checking embedded PHP */ +li { + background: url(/images//bullet.gif) left px no-repeat; + margin: 0px; + padding-left: 10px; + margin-bottom: px; + margin-top: px; + line-height: 13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Empty style defs. */ +.p { + margin:; + margin-right: + margin-left: 10px; + float: /* Some comment. */ ; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php new file mode 100644 index 000000000..222bbe4e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ColonSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ColonSpacingSniff + */ +final class ColonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 2, + 5 => 1, + 6 => 1, + 8 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + 41 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css new file mode 100644 index 000000000..2dfd22adb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css @@ -0,0 +1,16 @@ +#title-bar-bottom-right { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #08f7db url(diag_lines_bg.gif) top left; + + /* The sniff only deals with HEX colours. */ + color: DarkSlateGray; + background-color: rgb(255, 0, 0); + background-color: rgba(0, 0, 255, 0.3); + background-color: hsl(120, 100%, 50%); +} + +#add-new-comment { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed new file mode 100644 index 000000000..039209dd5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css.fixed @@ -0,0 +1,16 @@ +#title-bar-bottom-right { + background-color: #333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #F0F; + background: #08F7DB url(diag_lines_bg.gif) top left; + + /* The sniff only deals with HEX colours. */ + color: DarkSlateGray; + background-color: rgb(255, 0, 0); + background-color: rgba(0, 0, 255, 0.3); + background-color: hsl(120, 100%, 50%); +} + +#add-new-comment { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php new file mode 100644 index 000000000..44a2d64f7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ColourDefinition sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ColourDefinitionSniff + */ +final class ColourDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 5 => 1, + 6 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css new file mode 100644 index 000000000..4c11beaa8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css @@ -0,0 +1,17 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + height: 100%;float: left; + line-height: -25px; + cursor: pointer; margin: 10px; float: right; +} + +/* testing embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; margin:0px; padding-left:10px; margin-bottom:px; line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Document handling of comments and annotations. */ +div#annotations {-webkit-tap-highlight-color:transparent;/* phpcs:disable Standard.Cat.SniffName */-webkit-touch-callout:none;/*phpcs:enable*/-webkit-user-select:none;} + +div#comments {height:100%;/*comment*/width:100%;} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed new file mode 100644 index 000000000..93a7815e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.css.fixed @@ -0,0 +1,27 @@ +.SettingsTabPaneWidgetType-tab-mid { + background: transparent url(tab_inact_mid.png) repeat-x; + height: 100%; +float: left; + line-height: -25px; + cursor: pointer; +margin: 10px; +float: right; +} + +/* testing embedded PHP */ +li { + background:url(/images//bullet.gif) left px no-repeat; +margin:0px; +padding-left:10px; +margin-bottom:px; +line-height:13px; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); +} + +/* Document handling of comments and annotations. */ +div#annotations {-webkit-tap-highlight-color:transparent;/* phpcs:disable Standard.Cat.SniffName */ +-webkit-touch-callout:none;/*phpcs:enable*/ +-webkit-user-select:none;} + +div#comments {height:100%;/*comment*/ +width:100%;} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php new file mode 100644 index 000000000..18abf1a5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowMultipleStyleDefinitions sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\DisallowMultipleStyleDefinitionsSniff + */ +final class DisallowMultipleStyleDefinitionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 2, + 10 => 4, + 15 => 2, + 17 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css new file mode 100644 index 000000000..8ac95012a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css @@ -0,0 +1,103 @@ +.AssetLineageWidgetType-item { + color: #FFF; +} + +.AssetLineageWidgetType-title { + color: #CCC; +} + +.AssetLineageWidgetType-item { + color: #CCC; +} + +.AssetLineageWidgetType-item .selected { +} + +.AssetLineageWidgetType-item.selected { +} + +#Blah .AssetLineageWidgetType-item { +} + +#X.selected, +.AssetLineageWidgetType-item { +} + +.MyClass, .YourClass { +} + +.YourClass, .MyClass { +} + +.YourClass, .MyClass, .OurClass { +} + + +.ClassAtTopOfMediaBlock { +} + +@media print { + .ClassAtTopOfMediaBlock { + } + + .ClassInMultipleMediaBlocks { + } +} + +.ClassNotAtTopOfMediaBlock { +} + +@media handheld { + .SameClassInMediaBlock { + } + + .ClassNotAtTopOfMediaBlock { + } + + .SameClassInMediaBlock { + } +} + +@media braille { + .PlaceholderClass { + } + + .ClassNotAtTopOfMediaBlock { + } + + .ClassInMultipleMediaBlocks { + } +} + +.foo /* any comment */ +{ color: red; } + +/* print comment */ +@media print { + /* comment1 */ + td { + } + + /* comment2 */ + img { + } + + /* comment3 */ + td { + } +} + +@media handheld /* handheld comment */ +{ + td /* comment1 */ + { + } + + img /* comment2 */ + { + } + + td /* comment3 */ + { + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php new file mode 100644 index 000000000..70bc5b105 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DuplicateClassDefinition sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\DuplicateClassDefinitionSniff + */ +final class DuplicateClassDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 29 => 1, + 57 => 1, + 86 => 1, + 101 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css new file mode 100644 index 000000000..c9c849f61 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css @@ -0,0 +1,27 @@ +.ViperSubToolbar-wrapper { + height: 34px; + left: 0; + position: fixed; + top: 60px; + z-index: 997; + left: 50%; +} + +.expandable { + -moz-transition-property: margin-left, margin-right; + -moz-transition-duration: 0.2s; + -moz-transition-timing-function: ease; + -webkit-transition-property: margin-left, margin-right; + -webkit-transition-duration: 0.2s; + -webkit-transition-timing-function: ease; + z-index: 2; +} + +@media only screen and (max-width: 480px) { + header nav.meta a { display: none; } + header nav.meta a.search { display: block; } +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php new file mode 100644 index 000000000..f7e9e95f0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DuplicateStyleDefinition sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\DuplicateStyleDefinitionSniff + */ +final class DuplicateStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [7 => 1]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css new file mode 100644 index 000000000..801dcda11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css @@ -0,0 +1,15 @@ +.HelpWidgetType-new-bug-title {} +.HelpWidgetType-new-bug-title { +} +.HelpWidgetType-new-bug-title { + +} +.HelpWidgetType-new-bug-title { + +} +.HelpWidgetType-new-bug-title { + /* Nothing to see here */ +} +.HelpWidgetType-new-bug-title { + float: left; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php new file mode 100644 index 000000000..b75873002 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EmptyClassDefinition sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\EmptyClassDefinitionSniff + */ +final class EmptyClassDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 1 => 1, + 2 => 1, + 4 => 1, + 7 => 1, + 10 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css new file mode 100644 index 000000000..24910b714 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.css @@ -0,0 +1,11 @@ +#MetadataAdminScreen-addField-fieldType { + margin-left: 10px; + margin-right: + float: ; +} + +#MetadataAdminScreen-addField-fieldType li { + margin-right: /* @todo */ + margin-left: 10px; + float: /* Some comment. */ ; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php new file mode 100644 index 000000000..55ec5331e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EmptyStyleDefinition sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\EmptyStyleDefinitionSniff + */ +final class EmptyStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 8 => 1, + 10 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css new file mode 100644 index 000000000..dbd548705 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css @@ -0,0 +1,18 @@ +#add-new-comment { + -moz-border-radius: 1px; + -webkit-border-radius: 1px; + border-radius: 1px; + + -moz-border-radius-topleft: 1px; + -moz-border-radius-topright: 1px; + -moz-border-radius-bottomright: 1px; + -moz-border-radius-bottomleft: 1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + + -moz-box-shadow: 1px; + -webkit-box-shadow: 1px; + box-shadow: 1px; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed new file mode 100644 index 000000000..a8ea27048 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css.fixed @@ -0,0 +1,18 @@ +#add-new-comment { + border-radius: 1px; + border-radius: 1px; + border-radius: 1px; + + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + border-top-left-radius: 1px; + border-top-right-radius: 1px; + border-bottom-right-radius: 1px; + border-bottom-left-radius: 1px; + + box-shadow: 1px; + box-shadow: 1px; + box-shadow: 1px; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php new file mode 100644 index 000000000..f5cdae436 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php @@ -0,0 +1,62 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ForbiddenStyles sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ForbiddenStylesSniff + */ +final class ForbiddenStylesUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 15 => 1, + 16 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css new file mode 100644 index 000000000..216f00ee5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css @@ -0,0 +1,79 @@ +body { + + font-family: Arial, Helvetica, sans-serif; + margin: 40px 0 0 0; +padding: 0; + background: #8FB7DB url(diag_lines_bg.gif) top left; + +} + +td { + margin: 40px; + + padding: 20px; +} + +/* +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left { + background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat; +} +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right { + background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat; +} +*/ + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + + header #logo img { + min-width: 100%; + } + +} + +td { + margin: 40px; + + padding: 20px; + + +} + +.GUIFileUpload { +/* opacity: 0.25; */ +} + +.foo +{ + border: none; +} + +.mortgage-calculator h2 { + background: #072237; + color: #fff; + font-weight: normal; + height: 50px; + line-height: 50px; + padding: 0 0 0 30px; + } + +.WhitelistCommentIndentationShouldBeIgnored { +/* phpcs:disable Standard.Category.Sniff -- for reasons. */ +} + +/* syntax error */ +--------------------------------------------- */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed new file mode 100644 index 000000000..1fd128a5e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.1.css.fixed @@ -0,0 +1,73 @@ +body { + font-family: Arial, Helvetica, sans-serif; + margin: 40px 0 0 0; + padding: 0; + background: #8FB7DB url(diag_lines_bg.gif) top left; +} + +td { + margin: 40px; + padding: 20px; +} + +/* +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left { + background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat; +} +#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right { + background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat; +} +*/ + +.GUITextBox.container:after {} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + padding: 20px; + margin: 40px; + } +} + +@media screen and (max-device-width: 769px) { + + header #logo img { + max-width: 100%; + } + + header #logo img { + min-width: 100%; + } + +} + +td { + margin: 40px; + padding: 20px; +} + +.GUIFileUpload { +/* opacity: 0.25; */ +} + +.foo +{ + border: none; +} + +.mortgage-calculator h2 { + background: #072237; + color: #fff; + font-weight: normal; + height: 50px; + line-height: 50px; + padding: 0 0 0 30px; +} + +.WhitelistCommentIndentationShouldBeIgnored { +/* phpcs:disable Standard.Category.Sniff -- for reasons. */ +} + +/* syntax error */ +--------------------------------------------- */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css new file mode 100644 index 000000000..48b22f6d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.2.css @@ -0,0 +1,3 @@ +/* Live coding. Has to be the last (only) test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php new file mode 100644 index 000000000..fe79ffb3e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/IndentationUnitTest.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the Indentation sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\IndentationSniff + */ +final class IndentationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'IndentationUnitTest.1.css': + return [ + 2 => 1, + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 12 => 1, + 30 => 1, + 32 => 1, + 50 => 1, + 52 => 1, + 53 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css new file mode 100644 index 000000000..d0f2982fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css @@ -0,0 +1,14 @@ +.SettingsTabPaneWidgetType-tab-mid { + font-family: Arial; + Font-Family: arial; + background-color: #DA9393; + BACKGROUND-IMAGE: URL(Warning_Close.png); +} + +@media screen and (max-device-width: 769px) { + + .SettingsTabPaneWidgetType-tab-mid { + Font-Family: arial; + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363); + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php new file mode 100644 index 000000000..c47455a14 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowercaseStyleDefinition sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\LowercaseStyleDefinitionSniff + */ +final class LowercaseStyleDefinitionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 3 => 1, + 5 => 2, + 11 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css new file mode 100644 index 000000000..6c947e5b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css @@ -0,0 +1,21 @@ +.my-style { + margin-right 15px; + float: left; + margin-left 15px; + margin-top: 15px; + margin-bottom 15px; +} + +@media screen and (max-device-width: 769px) { + header #logo img { + max-width: 100%; + margin-bottom 15px; + } +} + +#foo { background-color: #FF0000; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php new file mode 100644 index 000000000..29e39848b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/MissingColonUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MissingColon sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\MissingColonSniff + */ +final class MissingColonUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 6 => 1, + 12 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css new file mode 100644 index 000000000..05637a602 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css @@ -0,0 +1,25 @@ +#red { + background-color: red; +} + +.red { + border-bottom: 1px dotted black; + border-top: 1px dotted gray; +} + +#red.yellow { + background: yellow url(diag_lines_bg.gif) top left; + text-shadow: 0 1px 0 white; +} + +.something--white { + border: 0; +} + +.something--------------white { + border: 0; +} + +.-white { + border: 0; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php new file mode 100644 index 000000000..90744d358 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php @@ -0,0 +1,59 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the NamedColours sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\NamedColoursSniff + */ +final class NamedColoursUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 6 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css new file mode 100644 index 000000000..c656c78ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css @@ -0,0 +1,35 @@ +.my-style { + opacity: 0; + opacity: 0.0; + opacity: 1; + opacity: 1.0; + opacity: 1.5; + opacity: .5; + opacity: 0.5; + opacity: 2; + opacity: -1; + opacity: 0.55; +} + +div { + font-size: 1.2em; + background: linear-gradient(to bottom, #00F, #0F0) repeat scroll 50% 50% #EEE; + min-width: 250px; + max-width: 100%; + padding-bottom: 50px; + box-shadow: 2px -3px 3px rgba(100, 100, 100, 0.33); + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 1px solid #000; + border-bottom: 1px dotted #000; + background: url(../1/2/3/4-5-6_7_100x100.png) repeat scroll 50% 50% #EEE; + opacity: -1; +} + +.my-commented-style { + opacity: /*comment*/ 0; + opacity: /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + 0.0; + opacity: /*comment*/ 1.0; + opacity: /*comment*/ .5; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed new file mode 100644 index 000000000..257e41a78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.css.fixed @@ -0,0 +1,35 @@ +.my-style { + opacity: 0; + opacity: 0; + opacity: 1; + opacity: 1; + opacity: 1.5; + opacity: 0.5; + opacity: 0.5; + opacity: 2; + opacity: -1; + opacity: 0.55; +} + +div { + font-size: 1.2em; + background: linear-gradient(to bottom, #00F, #0F0) repeat scroll 50% 50% #EEE; + min-width: 250px; + max-width: 100%; + padding-bottom: 50px; + box-shadow: 2px -3px 3px rgba(100, 100, 100, 0.33); + border-left: 1px solid #000; + border-right: 1px solid #000; + border-top: 1px solid #000; + border-bottom: 1px dotted #000; + background: url(../1/2/3/4-5-6_7_100x100.png) repeat scroll 50% 50% #EEE; + opacity: -1; +} + +.my-commented-style { + opacity: /*comment*/ 0; + opacity: /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + 0; + opacity: /*comment*/ 1; + opacity: /*comment*/ 0.5; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php new file mode 100644 index 000000000..d323477b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/OpacityUnitTest.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the Opacity sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\OpacitySniff + */ +final class OpacityUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 26 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css new file mode 100644 index 000000000..3ccb162e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css @@ -0,0 +1,61 @@ +.HelpWidgetType-new-bug-title { + width: 308px + float: left; +} + +#MetadataAdminScreen-addField-add { + float: left ; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.HelpWidgetType-list { + list-style-image: url(); +} + +@media (min-width: 320px) and (max-width: 961px) { + .tooltipsrt:hover span.tltp, + .tooltipstp:hover span.tltp { + visibility: hidden; + } +} + +#single-line-multi-statement-no-semicolon { + padding: 0 border: 20; +} + +#multi-line-style-no-semicolon { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20 + margin: + 0px /* top */ + 10px /* right + left */ +} + +#multi-line-style-whitespace { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ ; + border: + 20 ; + margin: + 10px /* top */ + 0px /* right + left */ + + + ; +} + +.allow-for-star-hack { + cursor: pointer; + *cursor: hand; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed new file mode 100644 index 000000000..7efef5882 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css.fixed @@ -0,0 +1,58 @@ +.HelpWidgetType-new-bug-title { + width: 308px + float: left; +} + +#MetadataAdminScreen-addField-add { + float: left; +} + +.TableWidgetType .recover:hover { + background-color: #FFF; +} + +#clearCache-settings:rootNodes-list_0 { + border-top: none; +} + +.HelpWidgetType-list { + list-style-image: url(); +} + +@media (min-width: 320px) and (max-width: 961px) { + .tooltipsrt:hover span.tltp, + .tooltipstp:hover span.tltp { + visibility: hidden; + } +} + +#single-line-multi-statement-no-semicolon { + padding: 0 border: 20; +} + +#multi-line-style-no-semicolon { + padding: 0 /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20 + margin: + 0px /* top */ + 10px /* right + left */ +} + +#multi-line-style-whitespace { + padding: 0; /* phpcs:ignore Standard.Cat.Sniff -- for reasons */ + border: + 20; + margin: + 10px /* top */ + 0px; /* right + left */ +} + +.allow-for-star-hack { + cursor: pointer; + *cursor: hand; +} + +/* Live coding. Has to be the last test in the file. */ +.intentional-parse-error { + float: left diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php new file mode 100644 index 000000000..ab2c839be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SemicolonSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\SemicolonSpacingSniff + */ +final class SemicolonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 7 => 1, + 30 => 1, + 34 => 1, + 36 => 1, + 39 => 1, + 43 => 1, + 45 => 1, + 48 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css new file mode 100644 index 000000000..c3d07ef5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css @@ -0,0 +1,41 @@ +#add-new-comment { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #8fb7db url(diag_lines_bg.gif) top left; + tab-size: 1; + margin: 8px 8px 8px 8px; + margin: 8px 8px; + margin: 0 0 0 0; + margin: 0 8px 0 8px; + margin: 8px 4px 8px 4px; + margin: 8px 4% 8px 4%; + margin: 6px 2px 9px 2px; + margin: 6px 2px 9px; + border-radius: 2px 2px 2px 2px !important; + border-width: 2px 2px 2px 2px; + border-width: 1px 2px 2px 4px; + margin: 97px auto 0 auto; + text-shadow: 0 1px 0 #fff; + border-width: + 2px + 4px + 2px + 4px; + + /* These are style names excluded from this rule. */ + background-position: 0 0; + box-shadow: 2px 2px 2px 2px; + transform-origin: 0 110% 0; + + /* Sizes with comments between them will be ignored for the purposes of this sniff. */ + margin: 8px /*top*/ 8px /*right*/ 8px /*bottom*/ 8px /*left*/; + + /* Same with PHPCS annotations. */ + border-width: + 2px /* phpcs:ignore Standard.Category.SniffName -- for reasons */ + 4px + 2px /* phpcs:disable Standard.Category.SniffName -- for reasons */ + 4px; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css.fixed new file mode 100644 index 000000000..36297dd60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.1.css.fixed @@ -0,0 +1,37 @@ +#add-new-comment { + background-color: #333333; + padding: 10px; + border-bottom: 1px dotted #F0F0F0; + border-top: 1px dotted #FF00FF; + background: #8fb7db url(diag_lines_bg.gif) top left; + tab-size: 1; + margin: 8px; + margin: 8px; + margin: 0; + margin: 0 8px; + margin: 8px 4px; + margin: 8px 4%; + margin: 6px 2px 9px 2px; + margin: 6px 2px 9px 2px; + border-radius: 2px !important; + border-width: 2px; + border-width: 1px 2px 2px 4px; + margin: 97px auto 0 auto; + text-shadow: 0 1px 0 #fff; + border-width: 2px 4px; + + /* These are style names excluded from this rule. */ + background-position: 0 0; + box-shadow: 2px 2px 2px 2px; + transform-origin: 0 110% 0; + + /* Sizes with comments between them will be ignored for the purposes of this sniff. */ + margin: 8px /*top*/ 8px /*right*/ 8px /*bottom*/ 8px /*left*/; + + /* Same with PHPCS annotations. */ + border-width: + 2px /* phpcs:ignore Standard.Category.SniffName -- for reasons */ + 4px + 2px /* phpcs:disable Standard.Category.SniffName -- for reasons */ + 4px; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.2.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.2.css new file mode 100644 index 000000000..2a91cf71a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.2.css @@ -0,0 +1,3 @@ +/* Intentional parse error. Live coding resilience. */ +#live-coding { + margin: 8px 8px 8px 8px diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php new file mode 100644 index 000000000..7394b77c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\CSS; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ShorthandSize sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\CSS\ShorthandSizeSniff + */ +final class ShorthandSizeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ShorthandSizeUnitTest.1.css': + return [ + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 21 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc new file mode 100644 index 000000000..2af42d372 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc @@ -0,0 +1,130 @@ + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ClassDeclarationSniff + */ +final class ClassDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 6 => 1, + 10 => 1, + 15 => 2, + 18 => 1, + 22 => 4, + 23 => 4, + 24 => 4, + 27 => 2, + 30 => 2, + 34 => 1, + 35 => 1, + 39 => 1, + 42 => 1, + 45 => 1, + 48 => 1, + 50 => 2, + 51 => 1, + 55 => 1, + 59 => 4, + 63 => 1, + 65 => 1, + 69 => 3, + 74 => 2, + 77 => 1, + 80 => 1, + 85 => 3, + 89 => 1, + 92 => 1, + 97 => 1, + 108 => 1, + 114 => 1, + 116 => 1, + 118 => 1, + 121 => 1, + 124 => 2, + 128 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc new file mode 100644 index 000000000..8b5a5aa70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc @@ -0,0 +1,45 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php new file mode 100644 index 000000000..7a01e9c09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassFileName sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ClassFileNameSniff + */ +final class ClassFileNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js new file mode 100644 index 000000000..04126f86a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js @@ -0,0 +1,45 @@ +var x = { + abc: 1, + zyz: 2, + abc: 5, + mno: { + abc: 4 + }, + abc: 5 + + this.request({ + action: 'getSubmissions' + }); + + this.request({ + action: 'deleteSubmission' + }); +} + + +LinkingEditScreenWidgetType.prototype = { + + _addDeleteButtonEvent: function(parentid) + { + var params = { + screen: 'LinkingEditScreenWidget', + assetid: self.assetid, + parentid: parentid, + assetid: parentid, + op: 'deleteLink' + }; + + }, + + saveDesignEdit: function() + { + var params = { + screen: [this.id, 'Widget'].join(''), + assetid: this.assetid, + changes: dfx.jsonEncode(this.currnetLinksWdgt.getChanges()), + op: 'saveLinkEdit' + }; + + } + +}; \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php new file mode 100644 index 000000000..567a89cc2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DuplicateProperty sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\DuplicatePropertySniff + */ +final class DuplicatePropertyUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 8 => 1, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc new file mode 100644 index 000000000..da47fa179 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc @@ -0,0 +1,16 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowercaseClassKeywords sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\LowercaseClassKeywordsSniff + */ +final class LowercaseClassKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 2 => 3, + 3 => 3, + 4 => 1, + 5 => 1, + 6 => 2, + 8 => 1, + 10 => 1, + 11 => 1, + 14 => 1, + 16 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc new file mode 100644 index 000000000..4f1781386 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc @@ -0,0 +1,199 @@ +testResults; + + + // Correct call to self. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = parent::selfMemberReferenceUnitTestFunction(); + + // Incorrect case. + $testResults[] = Self::selfMemberReferenceUnitTestFunction(); + $testResults[] = SELF::selfMemberReferenceUnitTestFunction(); + $testResults[] = SelfMemberReferenceUnitTestExample::selfMemberReferenceUnitTestFunction(); + + + // Incorrect spacing. + $testResults[] = self ::selfMemberReferenceUnitTestFunction(); + $testResults[] = self:: selfMemberReferenceUnitTestFunction(); + $testResults[] = self :: selfMemberReferenceUnitTestFunction(); + + // Remove ALL the newlines + $testResults[] = self + + + + + :: + + + + + selfMemberReferenceUnitTestFunction(); + + } + + + function selfMemberReferenceUnitTestFunction() + { + $this->testCount = $this->testCount + 1; + return $this->testCount; + + } + + +} + + +class MyClass { + + public static function test($value) { + echo "$value\n"; + } + + public static function walk() { + $callback = function($value, $key) { + // This is valid because you can't use self:: in a closure. + MyClass::test($value); + }; + + $array = array(1,2,3); + array_walk($array, $callback); + } +} + +MyClass::walk(); + +class Controller +{ + public function Action() + { + Doctrine\Common\Util\Debug::dump(); + } +} + +class Foo +{ + public static function bar() + { + \Foo::baz(); + } +} + +namespace TYPO3\CMS\Reports; + +class Status { + const NOTICE = -2; + const INFO = -1; + const OK = 0; + const WARNING = 1; + const ERROR = 2; +} + +namespace TYPO3\CMS\Reports\Report\Status; + +class Status implements \TYPO3\CMS\Reports\ReportInterface { + public function getHighestSeverity(array $statusCollection) { + $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE; + } +} + +namespace Foo; + +class Bar { + + function myFunction() + { + \Foo\Whatever::something(); + \Foo\Bar::something(); + } +} + +namespace Foo\Bar; + +class Baz { + + function myFunction() + { + \Foo\Bar\Whatever::something(); + \Foo\Bar\Baz::something(); + } +} + +class Nested_Anon_Class { + public function getAnonymousClass() { + // Spacing/comments should not cause false negatives for the NotUsed error. + Nested_Anon_Class :: $prop; + Nested_Anon_Class + /* some comment */ + + :: + + // phpcs:ignore Standard.Category.SniffName -- for reasons. + Bar(); + + // Anonymous class is a different scope. + return new class() { + public function nested_function() { + Nested_Anon_Class::$prop; + Nested_Anon_Class::BAR; + } + }; + } +} + +// Test dealing with scoped namespaces. +namespace Foo\Baz { + class BarFoo { + public function foo() { + echo Foo\Baz\BarFoo::$prop; + } + } +} + +// Prevent false negative when namespace has whitespace/comments. +namespace Foo /*comment*/ \ Bah { + class BarFoo { + public function foo() { + echo Foo \ /*comment*/ Bah\BarFoo::$prop; + } + } +} + +namespace EndsIn\CloseTag ?> +testResults; + + + // Correct call to self. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = parent::selfMemberReferenceUnitTestFunction(); + + // Incorrect case. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + + // Incorrect spacing. + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + // Remove ALL the newlines + $testResults[] = self::selfMemberReferenceUnitTestFunction(); + + } + + + function selfMemberReferenceUnitTestFunction() + { + $this->testCount = $this->testCount + 1; + return $this->testCount; + + } + + +} + + +class MyClass { + + public static function test($value) { + echo "$value\n"; + } + + public static function walk() { + $callback = function($value, $key) { + // This is valid because you can't use self:: in a closure. + MyClass::test($value); + }; + + $array = array(1,2,3); + array_walk($array, $callback); + } +} + +MyClass::walk(); + +class Controller +{ + public function Action() + { + Doctrine\Common\Util\Debug::dump(); + } +} + +class Foo +{ + public static function bar() + { + self::baz(); + } +} + +namespace TYPO3\CMS\Reports; + +class Status { + const NOTICE = -2; + const INFO = -1; + const OK = 0; + const WARNING = 1; + const ERROR = 2; +} + +namespace TYPO3\CMS\Reports\Report\Status; + +class Status implements \TYPO3\CMS\Reports\ReportInterface { + public function getHighestSeverity(array $statusCollection) { + $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE; + } +} + +namespace Foo; + +class Bar { + + function myFunction() + { + \Foo\Whatever::something(); + self::something(); + } +} + +namespace Foo\Bar; + +class Baz { + + function myFunction() + { + \Foo\Bar\Whatever::something(); + self::something(); + } +} + +class Nested_Anon_Class { + public function getAnonymousClass() { + // Spacing/comments should not cause false negatives for the NotUsed error. + self::$prop; + + /* some comment */ + + self::// phpcs:ignore Standard.Category.SniffName -- for reasons. + Bar(); + + // Anonymous class is a different scope. + return new class() { + public function nested_function() { + Nested_Anon_Class::$prop; + Nested_Anon_Class::BAR; + } + }; + } +} + +// Test dealing with scoped namespaces. +namespace Foo\Baz { + class BarFoo { + public function foo() { + echo self::$prop; + } + } +} + +// Prevent false negative when namespace has whitespace/comments. +namespace Foo /*comment*/ \ Bah { + class BarFoo { + public function foo() { + echo /*comment*/ self::$prop; + } + } +} + +namespace EndsIn\CloseTag ?> + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SelfMemberReference sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\SelfMemberReferenceSniff + */ +final class SelfMemberReferenceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 24 => 1, + 25 => 1, + 26 => 1, + 30 => 1, + 31 => 1, + 32 => 2, + 40 => 2, + 92 => 1, + 121 => 1, + 132 => 1, + 139 => 3, + 140 => 1, + 143 => 2, + 162 => 1, + 171 => 1, + 183 => 1, + 197 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc new file mode 100644 index 000000000..3fe39435b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc @@ -0,0 +1,191 @@ +anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +// Valid interface name. +interface ValidCamelCaseClass extends MyClass {} + + +// Incorrect usage of camel case. +interface invalidCamelCaseClass extends MyClass {} +interface Invalid_Camel_Case_Class_With_Underscores implements MyClass {} + + +// All lowercase. +interface invalidlowercaseclass extends MyClass {} +interface invalid_lowercase_class_with_underscores extends MyClass {} + + +// All uppercase. +interface VALIDUPPERCASECLASS extends MyClass {} +interface INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {} + + +// Mix camel case with uppercase. +interface ValidCamelCaseClassWithUPPERCASE extends MyClass {} + + +// Usage of numeric characters. +interface ValidCamelCaseClassWith1Number extends MyClass {} +interface ValidCamelCaseClassWith12345Numbers extends MyClass {} +interface 5InvalidCamelCaseClassStartingWithNumber extends MyClass {} +interface ValidCamelCaseClassEndingWithNumber5 extends MyClass {} +interface 12345 extends MyClass {} + +interface Testing{} + +interface Base +{ + protected $anonymous; + + public function __construct(); +} + + +// Valid trait name. +trait ValidCamelCaseClass extends MyClass {} + + +// Incorrect usage of camel case. +trait invalidCamelCaseClass extends MyClass {} +trait Invalid_Camel_Case_Class_With_Underscores implements MyClass {} + + +// All lowercase. +trait invalidlowercaseclass extends MyClass {} +trait invalid_lowercase_class_with_underscores extends MyClass {} + + +// All uppercase. +trait VALIDUPPERCASECLASS extends MyClass {} +trait INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {} + + +// Mix camel case with uppercase. +trait ValidCamelCaseClassWithUPPERCASE extends MyClass {} + + +// Usage of numeric characters. +trait ValidCamelCaseClassWith1Number extends MyClass {} +trait ValidCamelCaseClassWith12345Numbers extends MyClass {} +trait 5InvalidCamelCaseClassStartingWithNumber extends MyClass {} +trait ValidCamelCaseClassEndingWithNumber5 extends MyClass {} +trait 12345 extends MyClass {} + +trait Testing{} + +trait Base +{ + protected $anonymous; + + public function __construct() + { + $this->anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +// Valid enum name. +enum ValidCamelCaseClass: string {} + + +// Incorrect usage of camel case. +enum invalidCamelCaseClass {} +enum Invalid_Camel_Case_Class_With_Underscores {} + + +// All lowercase. +enum invalidlowercaseclass: INT {} +enum invalid_lowercase_class_with_underscores {} + + +// All uppercase. +enum VALIDUPPERCASECLASS: int {} +enum INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES {} + + +// Mix camel case with uppercase. +enum ValidCamelCaseClassWithUPPERCASE : string {} + + +// Usage of numeric characters. +enum ValidCamelCaseClassWith1Number {} +enum ValidCamelCaseClassWith12345Numbers : string {} +enum ValidCamelCaseClassEndingWithNumber5 {} + +enum Testing{} + +enum Base +{ + public function __construct() + { + $this->anonymous = new class extends ArrayObject + { + public function __construct() + { + parent::__construct(['a' => 1, 'b' => 2]); + } + }; + } +} + +if ( class_exists( Test :: class ) ) {} +if ( class_exists( Test2 ::class ) ) {} + +$foo = new class( + new class implements Countable { + } +) extends DateTime { +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php new file mode 100644 index 000000000..8e505a418 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Classes; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidClassName sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff + */ +final class ValidClassNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 10 => 1, + 14 => 1, + 15 => 1, + 20 => 1, + 30 => 1, + 32 => 1, + 57 => 1, + 58 => 1, + 62 => 1, + 63 => 1, + 68 => 1, + 78 => 1, + 80 => 1, + 97 => 1, + 98 => 1, + 102 => 1, + 103 => 1, + 108 => 1, + 118 => 1, + 120 => 1, + 145 => 1, + 146 => 1, + 150 => 1, + 151 => 1, + 156 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc new file mode 100644 index 000000000..7cd04a211 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc @@ -0,0 +1,309 @@ + + + + + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the BlockComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\BlockCommentSniff + */ +final class BlockCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the test run. + * + * @return void + */ + public function setCliValues($testFile, $config) + { + $config->tabWidth = 4; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 3 => 1, + 8 => 1, + 20 => 1, + 24 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 40 => 1, + 45 => 1, + 49 => 1, + 51 => 1, + 53 => 1, + 57 => 1, + 60 => 1, + 61 => 1, + 63 => 1, + 65 => 1, + 68 => 1, + 70 => 1, + 72 => 1, + 75 => 1, + 84 => 1, + 87 => 1, + 89 => 1, + 92 => 1, + 111 => 1, + 159 => 1, + 181 => 1, + 188 => 1, + 208 => 1, + 214 => 1, + 226 => 1, + 227 => 1, + 232 => 1, + 233 => 1, + 256 => 1, + 271 => 1, + 273 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc new file mode 100644 index 000000000..8de3d0a70 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc @@ -0,0 +1,145 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClassComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\ClassCommentSniff + */ +final class ClassCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 15 => 1, + 31 => 1, + 54 => 1, + 143 => 1, + 145 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 29 => 1, + 30 => 1, + 50 => 1, + 66 => 1, + 67 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc new file mode 100644 index 000000000..560370bfb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc @@ -0,0 +1,124 @@ + $a; + +trait TestTrait { +}//end trait + +trait TestTrait { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc.fixed new file mode 100644 index 000000000..8c6901452 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.1.inc.fixed @@ -0,0 +1,117 @@ + $a; + +trait TestTrait { +}//end trait + +trait TestTrait { +}//end trait diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.2.inc new file mode 100644 index 000000000..25913dd8f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.2.inc @@ -0,0 +1,7 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClosingDeclarationComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\ClosingDeclarationCommentSniff + */ +final class ClosingDeclarationCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the test file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingDeclarationCommentUnitTest.1.inc': + return [ + 13 => 1, + 17 => 1, + 31 => 1, + 41 => 1, + 59 => 1, + 63 => 1, + 67 => 1, + 79 => 1, + 83 => 1, + 89 => 1, + 92 => 1, + 98 => 1, + 101 => 1, + 106 => 1, + 110 => 1, + 124 => 1, + ]; + + case 'ClosingDeclarationCommentUnitTest.4.inc': + return [8 => 1]; + + case 'ClosingDeclarationCommentUnitTest.5.inc': + return [11 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the test file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'ClosingDeclarationCommentUnitTest.1.inc': + return [71 => 1]; + + case 'ClosingDeclarationCommentUnitTest.2.inc': + case 'ClosingDeclarationCommentUnitTest.3.inc': + return [7 => 1]; + + default: + return []; + } + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc new file mode 100644 index 000000000..d95acd2ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc @@ -0,0 +1,103 @@ + line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +class MyClass2 +{ + /** + * Some info about the variable here. + */ + var $x; +} + +abstract class MyClass +{ + /** +* Property comment + */ + readonly public string $prop; +} + +/** + * Some info about the enum here + * +*/ +enum Suits: string +{ + /** + * Some info about the case here. + */ + case HEARTS; +} + +/** ************************************************************************ + * Example with no errors. + **************************************************************************/ +function example() {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed new file mode 100644 index 000000000..ea6488a02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.inc.fixed @@ -0,0 +1,103 @@ + line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +class MyClass2 +{ + /** + * Some info about the variable here. + */ + var $x; +} + +abstract class MyClass +{ + /** + * Property comment + */ + readonly public string $prop; +} + +/** + * Some info about the enum here + * + */ +enum Suits: string +{ + /** + * Some info about the case here. + */ + case HEARTS; +} + +/** ************************************************************************ + * Example with no errors. + **************************************************************************/ +function example() {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js new file mode 100644 index 000000000..6e1a87812 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js @@ -0,0 +1,76 @@ + +/** +* Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + *@return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + *Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * +*/ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +function myFunction() +{ + console.info('hi'); + /** + Comment here. + */ +} + +/** + * Creates a map of tokens => line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +$.extend(Datepicker.prototype, { + _widgetDatepicker: function() { + }, + /* Action for selecting a new month/year. */ +}); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed new file mode 100644 index 000000000..9edb4ccc6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.js.fixed @@ -0,0 +1,76 @@ + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** + * Some info about the class here + * + */ +foo.prototype = { + + /** + * Some info about the function here. + * + * @return void + */ + bar: function() {} +} + +/** @var Database $mockedDatabase */ +/** @var Container $mockedContainer */ + +function myFunction() +{ + console.info('hi'); + /** + Comment here. + */ +} + +/** + * Creates a map of tokens => line numbers for each token. + * + * Long description with some points: + * - one + * - two + * - three + * + * @param array &$tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to + * process this file. + * @param string $eolChar The EOL character to use for splitting strings. + * + * @return void + */ +function myFunction() {} + +$.extend(Datepicker.prototype, { + _widgetDatepicker: function() { + }, + /* Action for selecting a new month/year. */ +}); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php new file mode 100644 index 000000000..a1ab9c327 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php @@ -0,0 +1,81 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DocCommentAlignment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\DocCommentAlignmentSniff + */ +final class DocCommentAlignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + $errors = [ + 3 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 19 => 1, + 23 => 2, + 24 => 1, + 25 => 2, + 26 => 1, + 32 => 1, + 33 => 1, + 38 => 1, + 39 => 1, + ]; + + if ($testFile === 'DocCommentAlignmentUnitTest.inc') { + $errors[75] = 1; + $errors[83] = 1; + $errors[84] = 1; + $errors[90] = 1; + $errors[91] = 1; + $errors[95] = 1; + $errors[96] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc new file mode 100644 index 000000000..cde6e462f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inc @@ -0,0 +1,55 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php new file mode 100644 index 000000000..06c308e01 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EmptyCatchComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\EmptyCatchCommentSniff + */ +final class EmptyCatchCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 13 => 1, + 33 => 1, + 49 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc new file mode 100644 index 000000000..1db2861b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc @@ -0,0 +1,43 @@ + +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1994-1997 The PHP Group +* @copyright The PHP Group +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +?> + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed new file mode 100644 index 000000000..f584c5527 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.inc.fixed @@ -0,0 +1,43 @@ + +* @author +* @copyright 1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 1994-1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 2024 Squiz Pty Ltd (ABN 77 084 670 600) +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +?> + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js new file mode 100644 index 000000000..57d8d37a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js @@ -0,0 +1,40 @@ + + + + +/** +* +* 0Multi-line short description without full stop +* +* +* asdasd +* long description for file (if any) +* asdasdadada +* +* PHP versio +* +* LICENSE: This source file is subject to version 3.0 of the PHP license +* that is available through the world-wide-web at the following URI: +* http://www.php.net/license/3_0.txt. If you did not receive a copy of +* the PHP License and are unable to obtain it through the web, please +* send a note to license@php.net so we can mail you a copy immediately. +* @package SquizCMS +* @package ADDITIONAL PACKAGE TAG +* @subpkg not_camelcased +* @author Antônio Carlos Venâncio Júnior +* @author +* @copyright 1997~1994 The PHP Group +* @copyright 1994-1997 The PHP Group +* @copyright The PHP Group +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +/** +* This bit here is not qualified as file comment +* +* as it is not the first comment in the file +* +*/ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed new file mode 100644 index 000000000..c7f54ffdf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.1.js.fixed @@ -0,0 +1,40 @@ + + + + +/** +* +* 0Multi-line short description without full stop +* +* +* asdasd +* long description for file (if any) +* asdasdadada +* +* PHP versio +* +* LICENSE: This source file is subject to version 3.0 of the PHP license +* that is available through the world-wide-web at the following URI: +* http://www.php.net/license/3_0.txt. If you did not receive a copy of +* the PHP License and are unable to obtain it through the web, please +* send a note to license@php.net so we can mail you a copy immediately. +* @package SquizCMS +* @package ADDITIONAL PACKAGE TAG +* @subpkg not_camelcased +* @author Squiz Pty Ltd +* @author +* @copyright 1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 1994-1997 Squiz Pty Ltd (ABN 77 084 670 600) +* @copyright 2024 Squiz Pty Ltd (ABN 77 084 670 600) +* @license http://www.php.net/license/3_0.txt +* @summary An unknown summary tag +* +*/ + + +/** +* This bit here is not qualified as file comment +* +* as it is not the first comment in the file +* +*/ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.10.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.10.inc new file mode 100644 index 000000000..1f82abfea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.10.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +readonly class Foo { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc new file mode 100644 index 000000000..520d34975 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.inc @@ -0,0 +1,11 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +echo 'hi'; \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js new file mode 100644 index 000000000..4bb4d50d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.2.js @@ -0,0 +1,10 @@ +/** + * File comment. + * + * @package Package + * @subpackage Subpackage + * @author Squiz Pty Ltd + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +print 'hi'; \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc new file mode 100644 index 000000000..b47603f20 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.3.inc @@ -0,0 +1,9 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + * diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc new file mode 100644 index 000000000..2fdeeba1f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.4.inc @@ -0,0 +1,3 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +class Foo { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc new file mode 100644 index 000000000..7074dac23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.7.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ +#[Attribute] +class Foo { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc new file mode 100644 index 000000000..5ef90f2ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.8.inc @@ -0,0 +1,9 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc new file mode 100644 index 000000000..f6c9d9968 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.9.inc @@ -0,0 +1,12 @@ + + * @copyright 2010-2014 Squiz Pty Ltd (ABN 77 084 670 600) + */ + +enum Foo { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php new file mode 100644 index 000000000..d5816bff4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php @@ -0,0 +1,82 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FileComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FileCommentSniff + */ +final class FileCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileCommentUnitTest.1.inc': + case 'FileCommentUnitTest.1.js': + return [ + 1 => 1, + 22 => 2, + 23 => 1, + 24 => 2, + 25 => 2, + 26 => 1, + 27 => 2, + 28 => 2, + 32 => 2, + ]; + + case 'FileCommentUnitTest.4.inc': + case 'FileCommentUnitTest.6.inc': + case 'FileCommentUnitTest.7.inc': + case 'FileCommentUnitTest.9.inc': + case 'FileCommentUnitTest.10.inc': + return [1 => 1]; + + case 'FileCommentUnitTest.5.inc': + return [2 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc new file mode 100644 index 000000000..7e94bb265 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.inc @@ -0,0 +1,511 @@ +callSomeFunction(); + + }//end okFunction() + + + /** + * Comment inside function. + * + * @throws Exception + */ + function okFunction() + { + /** + * @var FooClass + */ + $foo = FooFactory::factory(); + throw new Exception; + + }//end okFunction + + /** + * Needs at throws tag for rethrown exception, + * even though we have one throws tag. + * + * @throws PHP_Exception1 + */ + public function notOkVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end notOkVariableRethrown() + + /** + * Needs at throws tag for rethrown exception, + * even though we have one throws tag. + * + * @throws PHP_Exception1 + */ + public function notOkVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception1 | PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end notOkVariableRethrown() + + /** + * Has correct throws tags for all exceptions + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function okVariableRethrown() + { + throw new PHP_Exception1('Error'); + + try { + // Do something. + } catch (PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end okVariableRethrown() + + /** + * Has correct throws tags for all exceptions + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function okVariableMultiRethrown() + { + try { + // Do something. + } catch (PHP_Exception1 | PHP_Exception2 $e) { + logError(); + throw $e; + } + + }//end okVariableMultiRethrown() +}//end class + +class NamespacedException { + /** + * @throws \Exception + */ + public function foo() { + throw new \Exception(); + } + + /** + * @throws \Foo\Bar\FooBarException + */ + public function fooBar2() { + throw new \Foo\Bar\FooBarException(); + } + + /** + * @throws FooBarException + */ + public function fooBar2() { + throw new \Foo\Bar\FooBarException(); + } +} + +class Foo { + /** + * Comment + */ + public function foo() { + }//end foo() + + public function bar() { + throw new Exception(); + } + + /** + * Returns information for a test. + * + * This info includes parameters, their valid values. + * + * @param integer $projectid Id of the project. + * + * @return array + * @throws ChannelException If the project is invalid. + */ + public static function getTestInfo($projectid=NULL) + { + try { + DAL::beginTransaction(); + DAL::commit(); + } catch (DALException $e) { + DAL::rollBack(); + throw new ChannelException($e); + } + } +} + +class Test +{ + /** + * Folder name. + * + * @var string + */ + protected $folderName; + + protected function setUp() + { + parent::setUp(); + + if ( !strlen($this->folderName) ) { + throw new \RuntimeException('The $this->folderName must be specified before proceeding.'); + } + } + + /* + * + */ + protected function foo() + { + } + + /** + * @return Closure + */ + public function getStuff() + { + return function () { + throw new RuntimeException("bam!"); + }; + } +} + +/** + * Class comment. + */ +class A +{ + /** + * Function B. + */ + public function b() + { + return new class { + public function c() + { + throw new \Exception(); + } + } + } +} + +/** + * Class comment. + */ +class A +{ + /** + * Function B. + */ + public function b() + { + return new class { + /** + * Tag and token number mismatch. + * + * @throws PHP_Exception1 + * @throws PHP_Exception2 + */ + public function oneLessThrowsTagNeeded() + { + throw new PHP_Exception1('Error'); + + }//end oneLessThrowsTagNeeded() + } + } +} + +abstract class SomeClass { + /** + * Comment here. + */ + abstract public function getGroups(); +} + +class SomeClass { + /** + * Validates something. + * + * @param string $method The set method parameter. + * + * @return string The validated method. + * + * @throws Prefix_Invalid_Argument_Exception The invalid argument exception. + * @throws InvalidArgumentException The invalid argument exception. + */ + protected function validate_something( $something ) { + if ( ! Prefix_Validator::is_string( $something ) ) { + throw Prefix_Invalid_Argument_Exception::invalid_string_parameter( $something, 'something' ); + } + + if ( ! in_array( $something, $this->valid_http_something, true ) ) { + throw new InvalidArgumentException( sprintf( '%s is not a valid HTTP something', $something ) ); + } + + return $something; + } + + /** + * Comment + * + * @throws Exception1 Comment. + * @throws Exception2 Comment. + * @throws Exception3 Comment. + */ + public function foo() { + switch ($foo) { + case 1: + throw Exception1::a(); + case 2: + throw Exception1::b(); + case 3: + throw Exception1::c(); + case 4: + throw Exception2::a(); + case 5: + throw Exception2::b(); + default: + throw new Exception3; + + } + } +} + +namespace Test\Admin { + class NameSpacedClass { + /** + * @throws \ExceptionFromGlobalNamespace + */ + public function ExceptionInGlobalNamespace() { + throw new \ExceptionFromGlobalNamespace(); + } + + /** + * @throws ExceptionFromSameNamespace + */ + public function ExceptionInSameNamespace() { + throw new ExceptionFromSameNamespace(); + } + + /** + * @throws \Test\Admin\ExceptionFromSameNamespace + */ + public function ExceptionInSameNamespaceToo() { + throw new ExceptionFromSameNamespace(); + } + + /** + * @throws \Different\NameSpaceName\ExceptionFromDifferentNamespace + */ + public function ExceptionInSameNamespaceToo() { + throw new \Different\NameSpaceName\ExceptionFromDifferentNamespace(); + } + } +} + +namespace { + class GlobalNameSpaceClass { + /** + * @throws SomeGlobalException + */ + public function ThrowGlobalException() { + throw new SomeGlobalException(); + } + + /** + * @throws \SomeGlobalException + */ + public function ThrowGlobalExceptionToo() { + throw new SomeGlobalException(); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php new file mode 100644 index 000000000..178b85a26 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionCommentThrowTag sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FunctionCommentThrowTagSniff + */ +final class FunctionCommentThrowTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 9 => 1, + 21 => 1, + 35 => 1, + 47 => 1, + 61 => 2, + 106 => 1, + 123 => 1, + 200 => 1, + 219 => 1, + 287 => 1, + 397 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc new file mode 100644 index 000000000..4fcbb6dbe --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc @@ -0,0 +1,1160 @@ +MyClass) + */ +public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7) +{ + +}//end caseSensitive() + + +/** + * More type hint check for custom type and array. + * + * @param array $a1 Comment here. + * @param array $a2 Comment here. + * @param MyClass $a3 Comment here. + * @param MyClass $a4 Comment here. + * + * @return array(int => MyClass) + */ +public function typeHint(MyClass $a1, $a2, myclass $a3, $a4) +{ + return (3 => 'myclass obj'); + +}//end typeHint() + + +/** + * Mixed variable type separated by a '|'. + * + * @param array|string $a1 Comment here. + * @param mixed $a2 Comment here. + * @param string|array $a3 Comment here. + * @param MyClass|int $a4 Comment here. + * + * @return bool + */ +public function mixedType($a1, $a2, $a3, $a4) +{ + return true; + +}//end mixedType() + + +/** + * Array type. + * + * @param array(MyClass) $a1 OK. + * @param array() $a2 Invalid type. + * @param array( $a3 Typo. + * @param array(int) $a4 Use 'array(integer)' instead. + * @param array(int => integer) $a5 Use 'array(integer => integer)' instead. + * @param array(integer => bool) $a6 Use 'array(integer => boolean)' instead. + * @param aRRay $a7 Use 'array' instead. + * @param string $a8 String with unknown type hint. + * + * @return int + */ +public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8) +{ + return 1; + +}//end mixedArrayType() + + +/** + */ +function empty1() +{ +}//end empty1() + + +/** + * + */ +function empty2() +{ +}//end empty2() + + +/** + * + * + * + */ +function empty3() +{ +}//end empty3 + + +/** + * @return boolean + */ +public function missingShortDescriptionInFunctionComment() +{ + return true; + +}//end missingShortDescriptionInFunctionComment() + + +class Another_Class +{ + + /** + * Destructor should not include a return tag. + * + * @return void + */ + function __destruct() + { + return; + } + + /** + * Constructor should not include a return tag. + * + * @return void + */ + function __construct() + { + return; + } + +}//end class + + +/** + * Comment param alignment test. + * + * @param string $varrr1 Comment1.. + * @param string $vr2 Comment2. + * @param string $var3 Comment3.. + * + * @return void + */ +public static function paramAlign($varrr1, $vr2, $var3) +{ + +}//end paramAlign() + + +/** + * Comment. + * + * @param string $id Comment. + * @param array $design Comment. + * + * @return void + */ +public static function paint($id, array $design) +{ + +}//end paint() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @since 4.0.0 + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + return; + } + + return 'blah'; + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + + return 'blah'; + +}//end myFunction() + +/** + * Test function. + * + * @param string $arg1 An argument + * + * @access public + * @return bool + */ + +echo $blah; + +function myFunction($arg1) {} + +class MyClass() { + /** + * An abstract function. + * + * @return string[] + */ + abstract final protected function myFunction(); +} + +/** + * Comment. + * + * @param mixed $test An argument. + * + * @return mixed + */ +function test($test) +{ + if ($test === TRUE) { + return; + } + + return $test; + +}//end test() + + +/** Comment. + * + * @return mixed + * + */ +function test() +{ + +}//end test() + +/** + * Comment. + * + * @param \other\ns\item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\ns\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +// Closures should be ignored. +preg_replace_callback( + '~-([a-z])~', + function ($match) { + return strtoupper($match[1]); + }, + 'hello-world' +); + +$callback = function ($bar) use ($foo) + { + $bar += $foo; + }; + +/** + * Comment should end with '*', not '**' before the slash. + **/ +function test123() { + +} + +/** + * Cant use resource for type hint. + * + * @param resource $test An argument. + * + * @return mixed + */ +function test($test) +{ + return $test; + +}//end test() + +/** + * Variable number of args. + * + * @param string $a1 Comment here. + * @param string $a2 Comment here. + * @param string $a2,... Comment here. + * + * @return boolean + */ +public function variableArgs($a1, $a2) +{ + return true; + +}//end variableArgs() + +/** + * Contains closure. + * + * @return void + */ +public function containsClosure() +{ + function ($e) { + return new Event($e); + }, + +}//end containsClosure() + +/** + * 这是一æ¡æµ‹è¯•è¯„论. + * + * @return void + */ +public function test() +{ + +}//end variableArgs() + +/** + * Uses callable. + * + * @param callable $cb Test parameter. + * + * @return void + */ +public function usesCallable(callable $cb) { + $cb(); +}//end usesCallable() + +/** + * Creates a map of tokens => line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character + * to use for splitting strings. + * + * @return void + * @throws Exception If something really bad + * happens while doing foo. + */ +public function foo(array &$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Some description. + * + * @param \Vendor\Package\SomeClass $someclass Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass2 Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass3 Some class. + * + * @return void + */ +public function foo(SomeClass $someclass, \OtherVendor\Package\SomeClass2 $someclass2, SomeClass3 $someclass3) +{ +} + +/** + * Gettext. + * + * @return string + */ +public function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Test + * + * @return void + * @throws E + */ +function myFunction() {} + +/** + * Yield test + * + * @return integer + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Yield test + * + * @return void + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Using "array" as a type hint should satisfy a specified array parameter type. + * + * @param MyClass[] $values An array of MyClass objects. + * + * @return void + */ +public function specifiedArray(array $values) { + +}// end specifiedArray() + +/** + * Using "callable" as a type hint should satisfy a "callback" parameter type. + * + * @param callback $cb A callback. + * + * @return void + */ +public function callableCallback(callable $cb) { + +}// end callableCallback() + +/** + * PHP7 type hints. + * + * @param string $name1 Comment. + * @param integer $name2 Comment. + * @param float $name3 Comment. + * @param boolean $name4 Comment. + * + * @return void + */ +public function myFunction (string $name1, int $name2, float $name3, bool $name4) { +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + +/** + * Return description function + correct type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + incorrect type. + * + * @return int This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + no return. + * + * @return void This is a description. + */ +public function myFunction() { +} + +/** + * Return description function + mixed return. + * + * @return mixed This is a description. + */ +public function myFunction() { +} + +/** + * Function comment. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Do something. + * + * @return void + */ +public function someFunc(): void +{ + $class = new class + { + /** + * Do something. + * + * @return string + */ + public function getString(): string + { + return 'some string'; + } + }; +} + +/** + * Return description function + mixed return types. + * + * @return bool|int This is a description. + */ +function returnTypeWithDescriptionA() +{ + return 5; + +}//end returnTypeWithDescriptionA() + + +/** + * Return description function + mixed return types. + * + * @return real|bool This is a description. + */ +function returnTypeWithDescriptionB() +{ + return 5; + +}//end returnTypeWithDescriptionB() + + +/** + * Return description function + lots of different mixed return types. + * + * @return int|object|string[]|real|double|float|bool|array(int=>MyClass)|callable And here we have a description + */ +function returnTypeWithDescriptionC() +{ + return 5; + +}//end returnTypeWithDescriptionC() + + +/** + * Return description function + lots of different mixed return types. + * + * @return array(int=>bool)|\OtherVendor\Package\SomeClass2|MyClass[]|void And here we have a description + */ +function returnTypeWithDescriptionD() +{ + +}//end returnTypeWithDescriptionD() + +/** + * Yield from test + * + * @return int[] + */ +function yieldFromTest() +{ + yield from foo(); +} + +/** + * Audio + * + * Generates an audio element to embed sounds + * + * @param mixed $src Either a source string or + * an array of sources. + * @param mixed $unsupportedMessage The message to display + * if the media tag is not supported by the browser. + * @param mixed $attributes HTML attributes. + * @return string + */ +function audio( + $src, + $unsupportedMessage = '', + $attributes = '', +) +{ + return 'test'; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithClosure() +{ + function () { + return; + }; + + return []; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithAnonymousClass() +{ + new class { + /** + * @return void + */ + public function test() { + return; + } + }; + + return []; +} + +/** + * @return void + */ +function returnVoidWithClosure() +{ + function () { + return 1; + }; +} + +/** + * @return void + */ +function returnVoidWithAnonymousClass() +{ + new class { + /** + * @return integer + */ + public function test() + { + return 1; + } + }; +} + +class TestReturnVoid +{ + /** + * @return void + */ + public function test() + { + function () { + return 4; + }; + } +} + +/** + * Comment here. + * + * @param integer $a This is A. + * @param ?array $b This is B. + * + * @return void + */ +public static function foo(?int $a, ?array $b) {} + +/** + * Comment here. + * + * @param object $a This is A. + * @param object $b This is B. + * + * @return void + */ +public function foo(object $a, ?object $b) {} + +/** + * Prepares given PHP class method for later code building. + * + * @param integer $foo Comment. + * - Additional comment. + * + * @return void + */ +function foo($foo) {} + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +// phpcs:set Squiz.Commenting.FunctionComment skipIfInheritdoc true + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +/** + * Foo. + * + * @param mixed $a Comment. + * + * @return mixed + */ +public function foo(mixed $a): mixed {} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] __construct,__destruct + +/** + * @return void + * @throws Exception If any other error occurs. */ +function throwCommentOneLine() {} + +/** + * When two adjacent pipe symbols are used (by mistake), the sniff should not throw a PHP Fatal error + * + * @param stdClass||null $object While invalid, this should not throw a PHP Fatal error. + * @return void + */ +function doublePipeFatalError(?stdClass $object) {} + +/** + * Test for passing variables by reference + * + * This sniff treats the '&' as optional for parameters passed by reference, but + * forbidden for parameters which are not passed by reference. + * + * Because mismatches may be in either direction, we cannot auto-fix these. + * + * @param string $foo A string passed in by reference. + * @param string &$bar A string passed in by reference. + * @param string $baz A string NOT passed in by reference. + * @param string &$qux A string NOT passed in by reference. + * @param string &$case1 A string passed in by reference with a case mismatch. + * @param string &$CASE2 A string NOT passed in by reference, also with a case mismatch. + * + * @return void + */ +public function variablesPassedByReference(&$foo, &$bar, $baz, $qux, &$CASE1, $case2) +{ + return; +} + +/** + * Test for param tag containing ref, but param in declaration not being by ref. + * + * @param string &$foo This should be flagged as (only) ParamNameUnexpectedAmpersandPrefix. + * @param string &$bar This should be flagged as (only) ParamNameNoMatch. + * @param string &$baz This should be flagged as (only) ParamNameNoCaseMatch. + * + * @return void + */ +function passedByRefMismatch($foo, $bra, $BAZ) { + return; +} + +/** + * Test variable case + * + * @param string $foo This parameter is lowercase. + * @param string $BAR This parameter is UPPERCASE. + * @param string $BazQux This parameter is TitleCase. + * @param string $corgeGrault This parameter is camelCase. + * @param string $GARPLY This parameter should be in lowercase. + * @param string $waldo This parameter should be in TitleCase. + * @param string $freD This parameter should be in UPPERCASE. + * @param string $PLUGH This parameter should be in TitleCase. + * + * @return void + */ +public function variableCaseTest( + $foo, + $BAR, + $BazQux, + $corgeGrault, + $garply, + $Waldo, + $FRED, + $PluGh +) { + return; +} + +/** + * Test variable order mismatch + * + * @param string $foo This is the third parameter. + * @param string $bar This is the first parameter. + * @param string $baz This is the second parameter. + * + * @return void + */ +public function variableOrderMismatch($bar, $baz, $foo) { + return; +} + +/** + * @return never + */ +function foo() {} + +/** + * @param $noTypeNoComment + * @return void + */ +function paramVariation1($noTypeNoComment): void {} + +/** + * @param $noTypeWithComment This parameter has no type specified. + * @return void + */ +function paramVariation2($noTypeWithComment): void {} + +/** + * @param integer $hasTypeNoComment + * @return void + */ +function paramVariation3($hasTypeNoComment): void {} + +/** + * @param integer $hasTypehasComment This parameter has type. + * @return void + */ +function paramVariation4($hasTypehasComment): void {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed new file mode 100644 index 000000000..817630b5b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc.fixed @@ -0,0 +1,1160 @@ + MyClass) + */ +public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7) +{ + +}//end caseSensitive() + + +/** + * More type hint check for custom type and array. + * + * @param array $a1 Comment here. + * @param array $a2 Comment here. + * @param MyClass $a3 Comment here. + * @param MyClass $a4 Comment here. + * + * @return array(integer => MyClass) + */ +public function typeHint(MyClass $a1, $a2, myclass $a3, $a4) +{ + return (3 => 'myclass obj'); + +}//end typeHint() + + +/** + * Mixed variable type separated by a '|'. + * + * @param array|string $a1 Comment here. + * @param mixed $a2 Comment here. + * @param string|array $a3 Comment here. + * @param MyClass|integer $a4 Comment here. + * + * @return boolean + */ +public function mixedType($a1, $a2, $a3, $a4) +{ + return true; + +}//end mixedType() + + +/** + * Array type. + * + * @param array(MyClass) $a1 OK. + * @param array $a2 Invalid type. + * @param array $a3 Typo. + * @param array(integer) $a4 Use 'array(integer)' instead. + * @param array(integer => integer) $a5 Use 'array(integer => integer)' instead. + * @param array(integer => boolean) $a6 Use 'array(integer => boolean)' instead. + * @param array $a7 Use 'array' instead. + * @param string $a8 String with unknown type hint. + * + * @return integer + */ +public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8) +{ + return 1; + +}//end mixedArrayType() + + +/** + */ +function empty1() +{ +}//end empty1() + + +/** + * + */ +function empty2() +{ +}//end empty2() + + +/** + * + * + * + */ +function empty3() +{ +}//end empty3 + + +/** + * @return boolean + */ +public function missingShortDescriptionInFunctionComment() +{ + return true; + +}//end missingShortDescriptionInFunctionComment() + + +class Another_Class +{ + + /** + * Destructor should not include a return tag. + * + * @return void + */ + function __destruct() + { + return; + } + + /** + * Constructor should not include a return tag. + * + * @return void + */ + function __construct() + { + return; + } + +}//end class + + +/** + * Comment param alignment test. + * + * @param string $varrr1 Comment1.. + * @param string $vr2 Comment2. + * @param string $var3 Comment3.. + * + * @return void + */ +public static function paramAlign($varrr1, $vr2, $var3) +{ + +}//end paramAlign() + + +/** + * Comment. + * + * @param string $id Comment. + * @param array $design Comment. + * + * @return void + */ +public static function paint($id, array $design) +{ + +}//end paint() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @since 4.0.0 + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + return; + } + + return 'blah'; + +}//end myFunction() + + +/** + * Adds specified class name to class attribute of this widget. + * + * @return string + */ +public function myFunction() +{ + if ($condition === FALSE) { + echo 'hi'; + } + + return 'blah'; + +}//end myFunction() + +/** + * Test function. + * + * @param string $arg1 An argument + * + * @access public + * @return bool + */ + +echo $blah; + +function myFunction($arg1) {} + +class MyClass() { + /** + * An abstract function. + * + * @return string[] + */ + abstract final protected function myFunction(); +} + +/** + * Comment. + * + * @param mixed $test An argument. + * + * @return mixed + */ +function test($test) +{ + if ($test === TRUE) { + return; + } + + return $test; + +}//end test() + + +/** Comment. + * + * @return mixed + * + */ +function test() +{ + +}//end test() + +/** + * Comment. + * + * @param \other\ns\item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param item $test An argument. + * + * @return mixed + */ +function test(\other\ns\item $test) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\ns\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +/** + * Comment. + * + * @param \first\item $test An argument. + * + * @return mixed + */ +function test(\first\ns\item $test = \second\ns::CONSTANT) +{ + return $test; + +}//end test() + +// Closures should be ignored. +preg_replace_callback( + '~-([a-z])~', + function ($match) { + return strtoupper($match[1]); + }, + 'hello-world' +); + +$callback = function ($bar) use ($foo) + { + $bar += $foo; + }; + +/** + * Comment should end with '*', not '**' before the slash. + **/ +function test123() { + +} + +/** + * Cant use resource for type hint. + * + * @param resource $test An argument. + * + * @return mixed + */ +function test($test) +{ + return $test; + +}//end test() + +/** + * Variable number of args. + * + * @param string $a1 Comment here. + * @param string $a2 Comment here. + * @param string $a2,... Comment here. + * + * @return boolean + */ +public function variableArgs($a1, $a2) +{ + return true; + +}//end variableArgs() + +/** + * Contains closure. + * + * @return void + */ +public function containsClosure() +{ + function ($e) { + return new Event($e); + }, + +}//end containsClosure() + +/** + * 这是一æ¡æµ‹è¯•è¯„论. + * + * @return void + */ +public function test() +{ + +}//end variableArgs() + +/** + * Uses callable. + * + * @param callable $cb Test parameter. + * + * @return void + */ +public function usesCallable(callable $cb) { + $cb(); +}//end usesCallable() + +/** + * Creates a map of tokens => line numbers for each token. + * + * @param array $tokens The array of tokens to process. + * @param object $tokenizer The tokenizer being used to process this file. + * @param string $eolChar The EOL character + * to use for splitting strings. + * + * @return void + * @throws Exception If something really bad + * happens while doing foo. + */ +public function foo(array &$tokens, $tokenizer, $eolChar) +{ + +}//end foo() + +/** + * Some description. + * + * @param \Vendor\Package\SomeClass $someclass Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass2 Some class. + * @param \OtherVendor\Package\SomeClass2 $someclass3 Some class. + * + * @return void + */ +public function foo(SomeClass $someclass, \OtherVendor\Package\SomeClass2 $someclass2, SomeClass3 $someclass3) +{ +} + +/** + * Gettext. + * + * @return string + */ +public function _() { + return $foo; +} + +class Baz { + /** + * The PHP5 constructor + * + * No return tag + */ + public function __construct() { + + } +} + +/** + * Test + * + * @return void + * @throws E + */ +function myFunction() {} + +/** + * Yield test + * + * @return integer + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Yield test + * + * @return void + */ +function yieldTest() +{ + for ($i = 0; $i < 5; $i++) { + yield $i; + } +} + +/** + * Using "array" as a type hint should satisfy a specified array parameter type. + * + * @param MyClass[] $values An array of MyClass objects. + * + * @return void + */ +public function specifiedArray(array $values) { + +}// end specifiedArray() + +/** + * Using "callable" as a type hint should satisfy a "callback" parameter type. + * + * @param callback $cb A callback. + * + * @return void + */ +public function callableCallback(callable $cb) { + +}// end callableCallback() + +/** + * PHP7 type hints. + * + * @param string $name1 Comment. + * @param integer $name2 Comment. + * @param float $name3 Comment. + * @param boolean $name4 Comment. + * + * @return void + */ +public function myFunction (string $name1, int $name2, float $name3, bool $name4) { +} + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + +/** + * Return description function + correct type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + incorrect type. + * + * @return integer This is a description. + */ +public function myFunction() { + return 5; +} + +/** + * Return description function + no return. + * + * @return void This is a description. + */ +public function myFunction() { +} + +/** + * Return description function + mixed return. + * + * @return mixed This is a description. + */ +public function myFunction() { +} + +/** + * Function comment. + * + * @param $bar + * Comment here. + * @param ... + * Additional arguments here. + * + * @return + * Return value + * + */ +function foo($bar) { +} + +/** + * Do something. + * + * @return void + */ +public function someFunc(): void +{ + $class = new class + { + /** + * Do something. + * + * @return string + */ + public function getString(): string + { + return 'some string'; + } + }; +} + +/** + * Return description function + mixed return types. + * + * @return boolean|integer This is a description. + */ +function returnTypeWithDescriptionA() +{ + return 5; + +}//end returnTypeWithDescriptionA() + + +/** + * Return description function + mixed return types. + * + * @return float|boolean This is a description. + */ +function returnTypeWithDescriptionB() +{ + return 5; + +}//end returnTypeWithDescriptionB() + + +/** + * Return description function + lots of different mixed return types. + * + * @return integer|object|string[]|float|boolean|array(integer => MyClass)|callable And here we have a description + */ +function returnTypeWithDescriptionC() +{ + return 5; + +}//end returnTypeWithDescriptionC() + + +/** + * Return description function + lots of different mixed return types. + * + * @return array(integer => boolean)|\OtherVendor\Package\SomeClass2|MyClass[]|void And here we have a description + */ +function returnTypeWithDescriptionD() +{ + +}//end returnTypeWithDescriptionD() + +/** + * Yield from test + * + * @return int[] + */ +function yieldFromTest() +{ + yield from foo(); +} + +/** + * Audio + * + * Generates an audio element to embed sounds + * + * @param mixed $src Either a source string or + * an array of sources. + * @param mixed $unsupportedMessage The message to display + * if the media tag is not supported by the browser. + * @param mixed $attributes HTML attributes. + * @return string + */ +function audio( + $src, + $unsupportedMessage = '', + $attributes = '', +) +{ + return 'test'; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithClosure() +{ + function () { + return; + }; + + return []; +} + +/** + * Test function + * + * @return array + */ +function returnArrayWithAnonymousClass() +{ + new class { + /** + * @return void + */ + public function test() { + return; + } + }; + + return []; +} + +/** + * @return void + */ +function returnVoidWithClosure() +{ + function () { + return 1; + }; +} + +/** + * @return void + */ +function returnVoidWithAnonymousClass() +{ + new class { + /** + * @return integer + */ + public function test() + { + return 1; + } + }; +} + +class TestReturnVoid +{ + /** + * @return void + */ + public function test() + { + function () { + return 4; + }; + } +} + +/** + * Comment here. + * + * @param integer $a This is A. + * @param array $b This is B. + * + * @return void + */ +public static function foo(?int $a, ?array $b) {} + +/** + * Comment here. + * + * @param object $a This is A. + * @param object $b This is B. + * + * @return void + */ +public function foo(object $a, ?object $b) {} + +/** + * Prepares given PHP class method for later code building. + * + * @param integer $foo Comment. + * - Additional comment. + * + * @return void + */ +function foo($foo) {} + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +// phpcs:set Squiz.Commenting.FunctionComment skipIfInheritdoc true + +/** + * {@inheritDoc} + */ +public function foo($a, $b) {} + +/** + * Foo. + * + * @param mixed $a Comment. + * + * @return mixed + */ +public function foo(mixed $a): mixed {} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] +class Bar { + /** + * The PHP5 constructor + */ + public function __construct() { + + } +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] ignored +/** + * Should be ok + */ +public function ignored() { + +} + +// phpcs:set Squiz.Commenting.FunctionComment specialMethods[] __construct,__destruct + +/** + * @return void + * @throws Exception If any other error occurs. */ +function throwCommentOneLine() {} + +/** + * When two adjacent pipe symbols are used (by mistake), the sniff should not throw a PHP Fatal error + * + * @param stdClass|null $object While invalid, this should not throw a PHP Fatal error. + * @return void + */ +function doublePipeFatalError(?stdClass $object) {} + +/** + * Test for passing variables by reference + * + * This sniff treats the '&' as optional for parameters passed by reference, but + * forbidden for parameters which are not passed by reference. + * + * Because mismatches may be in either direction, we cannot auto-fix these. + * + * @param string $foo A string passed in by reference. + * @param string &$bar A string passed in by reference. + * @param string $baz A string NOT passed in by reference. + * @param string &$qux A string NOT passed in by reference. + * @param string &$case1 A string passed in by reference with a case mismatch. + * @param string &$CASE2 A string NOT passed in by reference, also with a case mismatch. + * + * @return void + */ +public function variablesPassedByReference(&$foo, &$bar, $baz, $qux, &$CASE1, $case2) +{ + return; +} + +/** + * Test for param tag containing ref, but param in declaration not being by ref. + * + * @param string &$foo This should be flagged as (only) ParamNameUnexpectedAmpersandPrefix. + * @param string &$bar This should be flagged as (only) ParamNameNoMatch. + * @param string &$baz This should be flagged as (only) ParamNameNoCaseMatch. + * + * @return void + */ +function passedByRefMismatch($foo, $bra, $BAZ) { + return; +} + +/** + * Test variable case + * + * @param string $foo This parameter is lowercase. + * @param string $BAR This parameter is UPPERCASE. + * @param string $BazQux This parameter is TitleCase. + * @param string $corgeGrault This parameter is camelCase. + * @param string $GARPLY This parameter should be in lowercase. + * @param string $waldo This parameter should be in TitleCase. + * @param string $freD This parameter should be in UPPERCASE. + * @param string $PLUGH This parameter should be in TitleCase. + * + * @return void + */ +public function variableCaseTest( + $foo, + $BAR, + $BazQux, + $corgeGrault, + $garply, + $Waldo, + $FRED, + $PluGh +) { + return; +} + +/** + * Test variable order mismatch + * + * @param string $foo This is the third parameter. + * @param string $bar This is the first parameter. + * @param string $baz This is the second parameter. + * + * @return void + */ +public function variableOrderMismatch($bar, $baz, $foo) { + return; +} + +/** + * @return never + */ +function foo() {} + +/** + * @param $noTypeNoComment + * @return void + */ +function paramVariation1($noTypeNoComment): void {} + +/** + * @param $noTypeWithComment This parameter has no type specified. + * @return void + */ +function paramVariation2($noTypeWithComment): void {} + +/** + * @param integer $hasTypeNoComment + * @return void + */ +function paramVariation3($hasTypeNoComment): void {} + +/** + * @param integer $hasTypehasComment This parameter has type. + * @return void + */ +function paramVariation4($hasTypehasComment): void {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php new file mode 100644 index 000000000..036bdc622 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php @@ -0,0 +1,208 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\FunctionCommentSniff + */ +final class FunctionCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 5 => 1, + 10 => 3, + 12 => 2, + 13 => 2, + 14 => 1, + 15 => 1, + 28 => 1, + 43 => 1, + 76 => 1, + 87 => 1, + 103 => 1, + 109 => 1, + 112 => 1, + 122 => 1, + 123 => 3, + 124 => 2, + 125 => 1, + 126 => 1, + 137 => 4, + 138 => 4, + 139 => 4, + 143 => 2, + 155 => 1, + 159 => 1, + 166 => 1, + 173 => 1, + 183 => 1, + 190 => 2, + 193 => 2, + 196 => 1, + 199 => 2, + 210 => 1, + 211 => 1, + 222 => 1, + 223 => 1, + 224 => 1, + 225 => 1, + 226 => 1, + 227 => 1, + 230 => 2, + 232 => 2, + 246 => 1, + 248 => 4, + 261 => 1, + 263 => 1, + 276 => 1, + 277 => 1, + 278 => 1, + 279 => 1, + 280 => 1, + 281 => 1, + 284 => 1, + 286 => 7, + 294 => 1, + 302 => 1, + 312 => 1, + 358 => 1, + 359 => 2, + 372 => 1, + 373 => 1, + 387 => 1, + 407 => 1, + 441 => 1, + 500 => 1, + 526 => 1, + 548 => 1, + 641 => 1, + 669 => 1, + 688 => 1, + 744 => 1, + 748 => 1, + 767 => 1, + 789 => 1, + 792 => 1, + 794 => 1, + 797 => 1, + 828 => 1, + 840 => 1, + 852 => 1, + 864 => 1, + 886 => 1, + 888 => 1, + 890 => 1, + 978 => 1, + 997 => 1, + 1004 => 2, + 1006 => 1, + 1029 => 1, + 1053 => 1, + 1058 => 2, + 1069 => 1, + 1070 => 1, + 1071 => 1, + 1080 => 2, + 1083 => 1, + 1084 => 1, + 1085 => 1, + 1093 => 4, + 1100 => 1, + 1101 => 1, + 1102 => 1, + 1103 => 1, + 1123 => 1, + 1124 => 1, + 1125 => 1, + 1138 => 1, + 1139 => 1, + 1144 => 1, + 1145 => 1, + 1151 => 1, + ]; + + // Scalar type hints only work from PHP 7 onwards. + if (PHP_VERSION_ID >= 70000) { + $errors[17] = 3; + $errors[128] = 1; + $errors[143] = 3; + $errors[161] = 2; + $errors[201] = 1; + $errors[232] = 7; + $errors[363] = 3; + $errors[377] = 1; + $errors[575] = 2; + $errors[627] = 1; + $errors[1002] = 1; + $errors[1075] = 6; + $errors[1089] = 3; + $errors[1107] = 8; + $errors[1129] = 3; + $errors[1154] = 1; + $errors[1160] = 1; + } else { + $errors[729] = 4; + $errors[740] = 2; + $errors[752] = 2; + $errors[982] = 1; + }//end if + + // Object type hints only work from PHP 7.2 onwards. + if (PHP_VERSION_ID >= 70200) { + $errors[627] = 2; + } else { + $errors[992] = 2; + } + + // Mixed type hints only work from PHP 8.0 onwards. + if (PHP_VERSION_ID >= 80000) { + $errors[265] = 1; + $errors[459] = 1; + $errors[893] = 3; + } else { + $errors[1023] = 1; + } + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc new file mode 100644 index 000000000..024876842 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc @@ -0,0 +1,196 @@ + One +// -> One.One +// -> Two + +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + +/** + * Comment should be ignored in PHP 5.4. + * + */ +trait MyTrait { + +} + +$foo = 'foo'; // Var set to foo. + +echo $foo; + +// Comment here. +echo $foo; + +/** + * Comments about the include + */ +include_once($blah); + +// some comment without capital or full stop +echo $foo; // An unrelated comment. + +// An unrelated comment. +echo $foo; // some comment without capital or full stop + +class Foo +{ + // This is fine. + + /** + * Spacing is ignored above. + */ + function bar(){} +} + +if ($foo) { +}//end if +// Another comment here. +$foo++; + +if ($foo) { +}//end if +// another comment here. +$foo++; + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} + +/** + * Comment should be ignored. + * + */ +enum MyEnum { + +} + +/** + * Comment should be ignored. + * + */ +readonly class MyClass +{ + /** + * Comment should be ignored. + * + */ + readonly $property = 10; +} + +/* + * N.B.: The below test line must be the last test in the file. + * Testing that a new line after an inline comment when it's the last non-whitespace + * token in a file, does *not* throw an error as this would conflict with the common + * "new line required at end of file" rule. + */ + +// For this test line having an empty line below it, is fine. diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed new file mode 100644 index 000000000..949a9ff94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc.fixed @@ -0,0 +1,189 @@ + One +// -> One.One +// -> Two +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + +/** + * Comment should be ignored in PHP 5.4. + * + */ +trait MyTrait { + +} + +$foo = 'foo'; // Var set to foo. + +echo $foo; + +// Comment here. +echo $foo; + +/** + * Comments about the include + */ +include_once($blah); + +// some comment without capital or full stop +echo $foo; // An unrelated comment. + +// An unrelated comment. +echo $foo; // some comment without capital or full stop + +class Foo +{ + // This is fine. + + /** + * Spacing is ignored above. + */ + function bar(){} +} + +if ($foo) { +}//end if +// Another comment here. +$foo++; + +if ($foo) { +}//end if +// another comment here. +$foo++; + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} + +/** + * Comment should be ignored. + * + */ +enum MyEnum { + +} + +/** + * Comment should be ignored. + * + */ +readonly class MyClass +{ + /** + * Comment should be ignored. + * + */ + readonly $property = 10; +} + +/* + * N.B.: The below test line must be the last test in the file. + * Testing that a new line after an inline comment when it's the last non-whitespace + * token in a file, does *not* throw an error as this would conflict with the common + * "new line required at end of file" rule. + */ + +// For this test line having an empty line below it, is fine. diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js new file mode 100644 index 000000000..6b1093e6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js @@ -0,0 +1,129 @@ +// Some content here. +var code = 'hello'; + +// This comment contains # multiple +// hash signs (#). +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +function testFunction() +{ + // Callback methods which are added by external objects. + this.callbacks = {}; + +}//end testFunction() + +/** + * This is the first line of a class comment. + * This is the second line. + */ +myClass.prototype = { + + /** + * This is the first line of a method comment. + * This is the second line. + */ + load: function(url, callback) + { + // Some code here. + + } +}; + +// some code goes here! + +/* + A longer comment goes here. + It spans multiple lines!! + Or does it? +*/ + +// 0This is a simple multi-line +// comment! +code = 'hello'; + +//This is not valid. +code = 'hello'; + +// Neither is this! +code = 'hello'; + +// +code = 'hello'; + +/** Neither is this! **/ +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +var myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myClass.myFunction = function() { +} + +dfx.getIframeDocument = function(iframe) +{ + return doc; + +};//end dfx.getIframeDocument() + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +// Here is some inline example code: +// -> One +// -> One.One +// -> Two + +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + + +var foo = 'foo'; // Var set to foo. + +console.info(foo); + +// Comment here. +console.info(foo); + +//** +* invalid comment +*/ + +// some comment without capital or full stop +console.log(foo); // An unrelated comment. + +// An unrelated comment. +console.log(foo); // some comment without capital or full stop diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed new file mode 100644 index 000000000..20e5041e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js.fixed @@ -0,0 +1,125 @@ +// Some content here. +var code = 'hello'; + +// This comment contains # multiple +// hash signs (#). +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +function testFunction() +{ + // Callback methods which are added by external objects. + this.callbacks = {}; + +}//end testFunction() + +/** + * This is the first line of a class comment. + * This is the second line. + */ +myClass.prototype = { + + /** + * This is the first line of a method comment. + * This is the second line. + */ + load: function(url, callback) + { + // Some code here. + } +}; + +// some code goes here! +/* + A longer comment goes here. + It spans multiple lines!! + Or does it? +*/ + +// 0This is a simple multi-line +// comment! +code = 'hello'; + +// This is not valid. +code = 'hello'; + +// Neither is this! +code = 'hello'; + +code = 'hello'; + +/** Neither is this! **/ +code = 'hello'; + +/** + * This is the first line of a function comment. + * This is the second line. + */ +var myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myFunction = function() { +} + +/** + * This is the first line of a function comment. + * This is the second line. + */ +myClass.myFunction = function() { +} + +dfx.getIframeDocument = function(iframe) +{ + return doc; + +};//end dfx.getIframeDocument() + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +// Here is some inline example code: +// -> One +// -> One.One +// -> Two +/* + Here is some inline example code: + -> One + -> One.One + -> Two +*/ + + +var foo = 'foo'; // Var set to foo. + +console.info(foo); + +// Comment here. +console.info(foo); + +// ** +* invalid comment +*/ + +// some comment without capital or full stop +console.log(foo); // An unrelated comment. + +// An unrelated comment. +console.log(foo); // some comment without capital or full stop diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php new file mode 100644 index 000000000..c559c5ae6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php @@ -0,0 +1,96 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the InlineComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\InlineCommentSniff + */ +final class InlineCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'InlineCommentUnitTest.inc': + $errors = [ + 17 => 1, + 27 => 1, + 28 => 1, + 32 => 2, + 36 => 1, + 44 => 2, + 58 => 1, + 61 => 1, + 64 => 1, + 67 => 1, + 95 => 1, + 96 => 1, + 97 => 3, + 118 => 1, + 126 => 2, + 130 => 2, + 149 => 1, + ]; + + return $errors; + case 'InlineCommentUnitTest.js': + return [ + 31 => 1, + 36 => 2, + 48 => 1, + 51 => 1, + 54 => 1, + 57 => 1, + 102 => 1, + 103 => 1, + 104 => 3, + 118 => 1, + 121 => 1, + 125 => 2, + 129 => 2, + ]; + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc new file mode 100644 index 000000000..d6c4cf6c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc @@ -0,0 +1,1033 @@ + match ($foo) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 + }, +]; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed new file mode 100644 index 000000000..176cfe248 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.fixed @@ -0,0 +1,1033 @@ + match ($foo) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 + },//end match +]; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js new file mode 100644 index 000000000..c0cf2821d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js @@ -0,0 +1,444 @@ +function long_function() +{ + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + } +} + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + for (val =1; val < 20; val++) { + // Short for. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + while (something) { + // Short while. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} //end if + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} else { + // Short ELSE +} //end if + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +if (true) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else if (condition) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +if (something) { + // Line 1 + // Line 2 +} else if (somethingElse) { + // Line 1 + // Line 2 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} + +switch (something) { + case '1': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '2': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '3': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '4': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '5': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; +} + +// Wrong comment +if (condition) { + condition = true; +}//end foreach diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed new file mode 100644 index 000000000..231b51c5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js.fixed @@ -0,0 +1,444 @@ +function long_function() +{ + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if + + if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } + } else { + // Short ELSE + }//end if +} + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + for (val =1; val < 20; val++) { + // Short for. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + while (something) { + // Short while. + } + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} //end if + +if (longFunction) { + // This is a long + // IF statement + // that does + // not have + // an ELSE + // block on it + variable = 'hello'; + + if (variable === 'hello') { + // This is a short + // IF statement + } + + if (variable === 'hello') { + // This is a short + // IF statement + } else { + // This is a short ELSE + // statement + } +} else { + // Short ELSE +} //end if + +for (variable=1; variable < 20; variable++) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end for + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} //end while + +while (variable < 20) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end while + +if (true) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else if (condition) { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +if (something) { + // Line 1 + // Line 2 +} else if (somethingElse) { + // Line 1 + // Line 2 +} else { + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + // Line 6 + // Line 7 + // Line 8 + // Line 9 + // Line 10 + // Line 11 + // Line 12 + // Line 13 + // Line 14 + // Line 15 + // Line 16 + // Line 17 + // Line 18 + // Line 19 + // Line 20 +}//end if + +switch (something) { + case '1': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '2': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '3': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '4': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; + case '5': + // Line 1 + // Line 2 + // Line 3 + // Line 4 + // Line 5 + break; +}//end switch + +// Wrong comment +if (condition) { + condition = true; +}//end if diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php new file mode 100644 index 000000000..e2a0f7b00 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LongConditionClosingComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\LongConditionClosingCommentSniff + */ +final class LongConditionClosingCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'LongConditionClosingCommentUnitTest.inc': + return [ + 49 => 1, + 99 => 1, + 146 => 1, + 192 => 1, + 215 => 1, + 238 => 1, + 261 => 1, + 286 => 1, + 309 => 1, + 332 => 1, + 355 => 1, + 378 => 1, + 493 => 1, + 531 => 1, + 536 => 1, + 540 => 1, + 562 => 1, + 601 => 1, + 629 => 1, + 663 => 1, + 765 => 1, + 798 => 1, + 811 => 1, + 897 => 1, + 931 => 1, + 962 => 1, + 985 => 2, + 1008 => 1, + 1032 => 1, + ]; + + case 'LongConditionClosingCommentUnitTest.js': + return [ + 47 => 1, + 97 => 1, + 144 => 1, + 190 => 1, + 213 => 1, + 238 => 1, + 261 => 1, + 284 => 1, + 307 => 1, + 401 => 1, + 439 => 1, + 444 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js new file mode 100644 index 000000000..6de642107 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js @@ -0,0 +1,36 @@ +function test(id, buttons) // cool function +{ + alert('hello'); + alert('hello again'); // And again. + // Valid comment. + +}//end test() + +var good = true; // Indeed. + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +dfx.getIframeDocument = function(iframe) +{ + + return doc; + +};//end dfx.getIframeDocument() + +// Verify that multi-line control structure with comments and annotations are left alone. +if (condition // comment + && anotherCondition) { + condition = true; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed new file mode 100644 index 000000000..1953760da --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.1.js.fixed @@ -0,0 +1,39 @@ +function test(id, buttons) +// cool function +{ + alert('hello'); + alert('hello again'); +// And again. + // Valid comment. + +}//end test() + +var good = true; +// Indeed. + +mig.Gallery.prototype = { + + init: function(cb) + { + + },//end init() + + imageClicked: function(id) + { + + }//end imageClicked() + +}; + +dfx.getIframeDocument = function(iframe) +{ + + return doc; + +};//end dfx.getIframeDocument() + +// Verify that multi-line control structure with comments and annotations are left alone. +if (condition // comment + && anotherCondition) { + condition = true; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js new file mode 100644 index 000000000..88d0e7d44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.2.js @@ -0,0 +1,2 @@ +// Comment as first thing in a JS file. +var i = 100; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc new file mode 100644 index 000000000..3374c4760 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc @@ -0,0 +1,64 @@ + function($b) { + }, // comment. + 'key' => 'value', // phpcs:ignore Standard.Category.SniffName -- for reasons. + 'key' => 'value', // comment. +]; + +// Verify that multi-line control structure with comments and annotations are left alone. +for ( + $i = 0; /* Start */ + $i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + $i++ // comment + +) {} + +if ( $condition === true // comment + && $anotherCondition === false +) {} + +$match = match($foo // comment + && $bar +) { + 1 => 1, // comment +}; + +// Issue #560: Annotations should be reported separately and be non-auto-fixable as their meaning may change when moved. +$a = 1; //@codeCoverageIgnore +$b = 2; // @phpstan-ignore variable.undefined +$c = 3; // @phpstan-ignore variable.undefined +$d = 4; // @tabInsteadOfSpace + +// Comments that include `@`, but are not recognized as annotations by this sniff. +$a = 1; // @ = add tag. +$b = 2; // Some comment. // @username diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed new file mode 100644 index 000000000..bd6b171b0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc.fixed @@ -0,0 +1,71 @@ + function($b) { + }, // comment. + 'key' => 'value', // phpcs:ignore Standard.Category.SniffName -- for reasons. + 'key' => 'value', +// comment. +]; + +// Verify that multi-line control structure with comments and annotations are left alone. +for ( + $i = 0; /* Start */ + $i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + $i++ // comment + +) {} + +if ( $condition === true // comment + && $anotherCondition === false +) {} + +$match = match($foo // comment + && $bar +) { + 1 => 1, +// comment +}; + +// Issue #560: Annotations should be reported separately and be non-auto-fixable as their meaning may change when moved. +$a = 1; //@codeCoverageIgnore +$b = 2; // @phpstan-ignore variable.undefined +$c = 3; // @phpstan-ignore variable.undefined +$d = 4; // @tabInsteadOfSpace + +// Comments that include `@`, but are not recognized as annotations by this sniff. +$a = 1; +// @ = add tag. +$b = 2; +// Some comment. // @username diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php new file mode 100644 index 000000000..ba3b1c722 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the PostStatementComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\PostStatementCommentSniff + */ +final class PostStatementCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'PostStatementCommentUnitTest.inc': + return [ + 6 => 1, + 10 => 1, + 18 => 1, + 35 => 1, + 53 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 63 => 1, + 64 => 1, + ]; + + case 'PostStatementCommentUnitTest.1.js': + return [ + 1 => 1, + 4 => 1, + 9 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc new file mode 100644 index 000000000..54ef5d2d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc @@ -0,0 +1,456 @@ + $content) { + echo $content; + } + + return $var1; + + }//end checkVariable() + + + /** + * + * + */ + $emptyVarDoc = ''; + + /** + * Var type checking (int v.s. integer). + * + * @var int + */ + private $_varSimpleTypeCheck; + + + /** + * Var type checking (array(int => string) v.s. array(int => string)). + * + * @var array(int => string) + */ + private $_varArrayTypeCheck; + + + /** + * Boolean @var tag Capitalized + * + * @var Boolean + */ + public $CapBoolTag = true; + + + /** + * Boolean @var tag Capitalized + * + * @var BOOLEAN + */ + public $CapBoolTag2 = true; + + + /** + * Double @var tag Capitalized + * + * @var Double + */ + public $CapDoubleTag = 1; + + + /** + * Double @var tag Capitalized + * + * @var DOUBLE + */ + public $CapDoubleTag2 = 1; + + + /** + * Real @var tag Capitalized + * + * @var Real + */ + public $CapRealTag = 1; + + + /** + * Real @var tag Capitalized + * + * @var REAL + */ + public $CapRealTag2 = 1; + + + /** + * Float @var tag Capitalized + * + * @var Float + */ + public $CapFloatTag = 1; + + + /** + * Float @var tag Capitalized + * + * @var FLOAT + */ + public $CapFloatTag2 = 1; + + + /** + * Int @var tag Capitalized + * + * @var Int + */ + public $CapIntTag = 1; + + + /** + * Int @var tag Capitalized + * + * @var INT + */ + public $CapIntTag2 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var Integer + */ + public $CapIntTag3 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var INTEGER + */ + public $CapIntTag4 = 1; + + + /** + * Array @var tag Capitalized + * + * @var Array + */ + public $CapVarTag = []; + + + /** + * Array @var tag All Caps + * + * @var ARRAY + */ + public $CapVarTag2 = []; + + + /** + * Array @var tag Capitalized + * + * @var Array() + */ + public $CapVarTag3 = []; + + + /** + * Array @var tag All Caps + * + * @var ARRAY() + */ + public $CapVarTag4 = []; + + + /** + * Var type checking (STRING v.s. string). + * + * @var STRING + */ + private $_varCaseTypeCheck; + + + /** + * @var integer + */ + private $_varWithNoShortComment; + + protected $noComment2 = ''; + + + /** + * @var int Var type checking (int v.s. integer) with single-line comment. + */ + private $_varSimpleTypeCheckSingleLine; + + +}//end class + + +/** + * VariableCommentUnitTest2. + * + * Long description goes here. + * + */ +class VariableCommentUnitTest2 +{ + + public $hello; + + /** Comment starts here. + * + * @var string + * + */ + private $_varCaseTypeCheck; + + /** + * 这是一æ¡æµ‹è¯•è¯„论. + * + * @var string + */ + public $foo; + +}//end class + + +/* + * Class comment + */ +class Foo +{ + + protected $bar; + + /** + * Short description of the member variable. + * + * @var array + */ + public static array $variableName = array(); + +} + +class Foo +{ + + /** + * Short description of the member variable. + * + * @var array + */ + public array $variableName = array(); + + + // Not "/**" style comment. + // + // @var string + private ?Folder\ClassName $_incorrectCommentStyle = null; + + + var int $noComment = 1; + } + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; +} + +class ReadOnlyProps +{ + /** + * Short description of the member variable. + * + * @var array + */ + public readonly array $variableName = array(); + + /** + * Short description of the member variable. + * + * @var + */ + readonly protected ?int $variableName = 10; + + private readonly string $variable; +} + +class UnionTypes +{ + /** + * @var array|boolean + */ + private array|bool $variableName = array(); +} + +class IntersectionTypes +{ + /** + * @var \Iterator|\Countable + */ + private \Iterator&\Countable $variableName; +} + +class StandaloneNullTrueFalseTypes +{ + /** + * @var null + */ + public null $variableName = null; + + /** + * @var true + */ + protected true $variableName = true; + + /** + * @var false + */ + private false $variableName = false; +} + +class MoreMissingButSupportedTypes +{ + /** + * @var parent + */ + public parent $variableName; + + /** + * @var self + */ + protected self $variableName; + + /** + * @var SomeClass + */ + private namespace\SomeClass $variableName; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed new file mode 100644 index 000000000..a292b6de1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc.fixed @@ -0,0 +1,456 @@ + $content) { + echo $content; + } + + return $var1; + + }//end checkVariable() + + + /** + * + * + */ + $emptyVarDoc = ''; + + /** + * Var type checking (int v.s. integer). + * + * @var integer + */ + private $_varSimpleTypeCheck; + + + /** + * Var type checking (array(int => string) v.s. array(int => string)). + * + * @var array(integer => string) + */ + private $_varArrayTypeCheck; + + + /** + * Boolean @var tag Capitalized + * + * @var boolean + */ + public $CapBoolTag = true; + + + /** + * Boolean @var tag Capitalized + * + * @var boolean + */ + public $CapBoolTag2 = true; + + + /** + * Double @var tag Capitalized + * + * @var float + */ + public $CapDoubleTag = 1; + + + /** + * Double @var tag Capitalized + * + * @var float + */ + public $CapDoubleTag2 = 1; + + + /** + * Real @var tag Capitalized + * + * @var float + */ + public $CapRealTag = 1; + + + /** + * Real @var tag Capitalized + * + * @var float + */ + public $CapRealTag2 = 1; + + + /** + * Float @var tag Capitalized + * + * @var float + */ + public $CapFloatTag = 1; + + + /** + * Float @var tag Capitalized + * + * @var float + */ + public $CapFloatTag2 = 1; + + + /** + * Int @var tag Capitalized + * + * @var integer + */ + public $CapIntTag = 1; + + + /** + * Int @var tag Capitalized + * + * @var integer + */ + public $CapIntTag2 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var integer + */ + public $CapIntTag3 = 1; + + + /** + * Integer @var tag Capitalized + * + * @var integer + */ + public $CapIntTag4 = 1; + + + /** + * Array @var tag Capitalized + * + * @var array + */ + public $CapVarTag = []; + + + /** + * Array @var tag All Caps + * + * @var array + */ + public $CapVarTag2 = []; + + + /** + * Array @var tag Capitalized + * + * @var array + */ + public $CapVarTag3 = []; + + + /** + * Array @var tag All Caps + * + * @var array + */ + public $CapVarTag4 = []; + + + /** + * Var type checking (STRING v.s. string). + * + * @var string + */ + private $_varCaseTypeCheck; + + + /** + * @var integer + */ + private $_varWithNoShortComment; + + protected $noComment2 = ''; + + + /** + * @var integer Var type checking (int v.s. integer) with single-line comment. + */ + private $_varSimpleTypeCheckSingleLine; + + +}//end class + + +/** + * VariableCommentUnitTest2. + * + * Long description goes here. + * + */ +class VariableCommentUnitTest2 +{ + + public $hello; + + /** Comment starts here. + * + * @var string + * + */ + private $_varCaseTypeCheck; + + /** + * 这是一æ¡æµ‹è¯•è¯„论. + * + * @var string + */ + public $foo; + +}//end class + + +/* + * Class comment + */ +class Foo +{ + + protected $bar; + + /** + * Short description of the member variable. + * + * @var array + */ + public static array $variableName = array(); + +} + +class Foo +{ + + /** + * Short description of the member variable. + * + * @var array + */ + public array $variableName = array(); + + + // Not "/**" style comment. + // + // @var string + private ?Folder\ClassName $_incorrectCommentStyle = null; + + + var int $noComment = 1; + } + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; +} + +class ReadOnlyProps +{ + /** + * Short description of the member variable. + * + * @var array + */ + public readonly array $variableName = array(); + + /** + * Short description of the member variable. + * + * @var + */ + readonly protected ?int $variableName = 10; + + private readonly string $variable; +} + +class UnionTypes +{ + /** + * @var array|boolean + */ + private array|bool $variableName = array(); +} + +class IntersectionTypes +{ + /** + * @var \Iterator|\Countable + */ + private \Iterator&\Countable $variableName; +} + +class StandaloneNullTrueFalseTypes +{ + /** + * @var null + */ + public null $variableName = null; + + /** + * @var true + */ + protected true $variableName = true; + + /** + * @var false + */ + private false $variableName = false; +} + +class MoreMissingButSupportedTypes +{ + /** + * @var parent + */ + public parent $variableName; + + /** + * @var self + */ + protected self $variableName; + + /** + * @var SomeClass + */ + private namespace\SomeClass $variableName; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php new file mode 100644 index 000000000..965e3c031 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php @@ -0,0 +1,88 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Commenting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the VariableComment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\VariableCommentSniff + */ +final class VariableCommentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 21 => 1, + 24 => 1, + 56 => 1, + 64 => 1, + 73 => 1, + 84 => 1, + 130 => 1, + 136 => 1, + 144 => 1, + 152 => 1, + 160 => 1, + 168 => 1, + 176 => 1, + 184 => 1, + 192 => 1, + 200 => 1, + 208 => 1, + 216 => 1, + 224 => 1, + 232 => 1, + 240 => 1, + 248 => 1, + 256 => 1, + 264 => 1, + 272 => 1, + 280 => 1, + 290 => 1, + 294 => 1, + 311 => 1, + 336 => 1, + 361 => 1, + 364 => 1, + 399 => 1, + 403 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [93 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc new file mode 100644 index 000000000..de0235cdd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc @@ -0,0 +1,320 @@ + 0); + +do +{ + echo $i; +} while ($i > 0); + +do +{ + echo $i; +} +while ($i > 0); + +do { echo $i; } while ($i > 0); + +do{ + echo $i; +}while($i > 0); + +while ($i < 1) { + echo $i; +} + +while($i < 1){ + echo $i; +} + +while ($i < 1) { echo $i; } + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for($i = 1; $i < 1; $i++){ + echo $i; +} + +for ($i = 1; $i < 1; $i++) { echo $i; } + +if ($i == 0) { + $i = 1; +} + +if($i == 0){ + $i = 1; +} + +if ($i == 0) { $i = 1; } + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else{ + $i = 0; +} + +if ($i == 0) { $i = 1; } else { $i = 0; } + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +}else if($i == 2){ + $i = 0; +} + +if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; } + +if ($i == 0) { // comments are allowed + $i = 1; +} + +if ($i == 0) {// comments are allowed + $i = 1; +} + +if ($i == 0) { /* comments are allowed*/ + $i = 1; +} + +if ($i == 0) +{ // this is ok + $i = 1; +} + +if ($i == 0) /* this is ok */ { +} + +try { + $code = 'this'; +} catch (Exception $e) { + // Caught! +} + +try { $code = 'this'; } catch (Exception $e) { + // Caught! +} + +do { echo $i; +} while ($i > 0); + +if ($i === 0) { + + $i = 1 +} + +if ($a) { + +} +elseif ($b) { +} + +foreach ($items as $item) { + echo $item; +} + +foreach($items as $item){ + echo $item; +} + +if ($a && $b) // && $c) +{ +} + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +try { + // try body +} +catch (FirstExceptionType $e) { + // catch body +} +catch (OtherExceptionType $e) { + // catch body +} + +switch($foo) { + + case 'bar': + break; + +} + +if ($foo) : +endif; + +?> + +getRow()): ?> +

    + + + +
    + +
    + + + + + + + hello + + + + hello + + + + +getRow()) : ?> +

    + + + + + + + + hello + + + + hello + + 1, +}; + +$r = match($x){1 => 1}; + +// phpcs:set Squiz.ControlStructures.ControlSignature requiredSpacesBeforeColon 2 +if ($a == 5): + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +// Reset property. +// phpcs:set Squiz.ControlStructures.ControlSignature requiredSpacesBeforeColon 1 diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc.fixed new file mode 100644 index 000000000..03e6bf2c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.1.inc.fixed @@ -0,0 +1,324 @@ + 0); + +do { + echo $i; +} while ($i > 0); + +do { + echo $i; +} while ($i > 0); + +do { +echo $i; } while ($i > 0); + +do { + echo $i; +} while ($i > 0); + +while ($i < 1) { + echo $i; +} + +while ($i < 1) { + echo $i; +} + +while ($i < 1) { +echo $i; } + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for ($i = 1; $i < 1; $i++) { + echo $i; +} + +for ($i = 1; $i < 1; $i++) { +echo $i; } + +if ($i == 0) { + $i = 1; +} + +if ($i == 0) { + $i = 1; +} + +if ($i == 0) { +$i = 1; } + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} else { + $i = 0; +} + +if ($i == 0) { +$i = 1; } else { +$i = 0; } + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { + $i = 1; +} else if ($i == 2) { + $i = 0; +} + +if ($i == 0) { +$i = 1; } else if ($i == 2) { +$i = 0; } + +if ($i == 0) { // comments are allowed + $i = 1; +} + +if ($i == 0) {// comments are allowed + $i = 1; +} + +if ($i == 0) { /* comments are allowed*/ + $i = 1; +} + +if ($i == 0) { // this is ok + $i = 1; +} + +if ($i == 0) { /* this is ok */ +} + +try { + $code = 'this'; +} catch (Exception $e) { + // Caught! +} + +try { +$code = 'this'; } catch (Exception $e) { + // Caught! +} + +do { +echo $i; +} while ($i > 0); + +if ($i === 0) { + + $i = 1 +} + +if ($a) { + +} elseif ($b) { +} + +foreach ($items as $item) { + echo $item; +} + +foreach ($items as $item) { + echo $item; +} + +if ($a && $b) { // && $c) +} + +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +try { + // try body +} catch (FirstExceptionType $e) { + // catch body +} catch (OtherExceptionType $e) { + // catch body +} + +switch ($foo) { + + case 'bar': + break; + +} + +if ($foo) : +endif; + +?> + +getRow()) : ?> +

    + + + +
    + +
    + + + + + + + hello + + + + hello + + + + +getRow()): ?> +

    + + + + + + + + hello + + + + hello + + 1, +}; + +$r = match ($x) { +1 => 1}; + +// phpcs:set Squiz.ControlStructures.ControlSignature requiredSpacesBeforeColon 2 +if ($a == 5) : + echo "a equals 5"; + echo "..."; +elseif ($a == 6) : + echo "a equals 6"; + echo "!!!"; +else : + echo "a is neither 5 nor 6"; +endif; + +// Reset property. +// phpcs:set Squiz.ControlStructures.ControlSignature requiredSpacesBeforeColon 1 diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.2.inc new file mode 100644 index 000000000..ef99b1a22 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.2.inc @@ -0,0 +1,5 @@ + 0); + +do +{ + i = 0; +} while (i > 0); + +do +{ + i = 0; +} +while (i > 0); + +do { i = 0; } while (i > 0); + +do{ + i = 0; +}while(i > 0); + +while (i < 1) { + i = 0; +} + +while(i < 1){ + i = 0; +} + +while (i < 1) { i = 0; } + +for (i = 1; i < 1; i++) { + i = 0; +} + +for(i = 1; i < 1; i++){ + i = 0; +} + +for (i = 1; i < 1; i++) { i = 0; } + +if (i == 0) { + i = 1; +} + +if(i == 0){ + i = 1; +} + +if (i == 0) { i = 1; } + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { + i = 1; +}else{ + i = 0; +} + +if (i == 0) { i = 1; } else { i = 0; } + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { + i = 1; +}else if(i == 2){ + i = 0; +} + +if (i == 0) { i = 1; } else if (i == 2) { i = 0; } + +if (i == 0) { // comments are allowed + i = 1; +} + +if (i == 0) {// comments are allowed + i = 1; +} + +if (i == 0) { /* comments are allowed*/ + i = 1; +} + +if (i == 0) +{ // this is ok + i = 1; +} + +if (i == 0) /* this is ok */ { +} + +try { + code = 'this'; +} catch (e) { + // Caught! +} + +try { code = 'this'; } catch (e) { + // Caught! +} + +do { i = 0; +} while (i > 0); + +if (i === 0) { + + i = 1 +} + +if (window.jQuery)(function($) { + $.fn.reset = function() { + return this.each(function() { + try { + this.reset(); + } catch (e) { + } + }); + }; +})(jQuery); + +if ($("#myid").rotationDegrees()=='90') + $('.modal').css({'transform': 'rotate(90deg)'}); + +if ($("#myid").rotationDegrees()=='90') + $foo = {'transform': 'rotate(90deg)'}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed new file mode 100644 index 000000000..e3ed6de74 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js.fixed @@ -0,0 +1,141 @@ + +i = 0; +do { + i = 0; +} while (i > 0); + +do { + i = 0; +} while (i > 0); + +do { + i = 0; +} while (i > 0); + +do { +i = 0; } while (i > 0); + +do { + i = 0; +} while (i > 0); + +while (i < 1) { + i = 0; +} + +while (i < 1) { + i = 0; +} + +while (i < 1) { +i = 0; } + +for (i = 1; i < 1; i++) { + i = 0; +} + +for (i = 1; i < 1; i++) { + i = 0; +} + +for (i = 1; i < 1; i++) { +i = 0; } + +if (i == 0) { + i = 1; +} + +if (i == 0) { + i = 1; +} + +if (i == 0) { +i = 1; } + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { + i = 1; +} else { + i = 0; +} + +if (i == 0) { +i = 1; } else { +i = 0; } + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { + i = 1; +} else if (i == 2) { + i = 0; +} + +if (i == 0) { +i = 1; } else if (i == 2) { +i = 0; } + +if (i == 0) { // comments are allowed + i = 1; +} + +if (i == 0) {// comments are allowed + i = 1; +} + +if (i == 0) { /* comments are allowed*/ + i = 1; +} + +if (i == 0) { // this is ok + i = 1; +} + +if (i == 0) { /* this is ok */ +} + +try { + code = 'this'; +} catch (e) { + // Caught! +} + +try { +code = 'this'; } catch (e) { + // Caught! +} + +do { +i = 0; +} while (i > 0); + +if (i === 0) { + + i = 1 +} + +if (window.jQuery)(function($) { + $.fn.reset = function() { + return this.each(function() { + try { + this.reset(); + } catch (e) { + } + }); + }; +})(jQuery); + +if ($("#myid").rotationDegrees()=='90') + $('.modal').css({'transform': 'rotate(90deg)'}); + +if ($("#myid").rotationDegrees()=='90') + $foo = {'transform': 'rotate(90deg)'}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php new file mode 100644 index 000000000..f6db4b19a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php @@ -0,0 +1,115 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ControlSignature sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ControlSignatureSniff + */ +final class ControlSignatureUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + $errors = [ + 7 => 1, + 12 => 1, + 15 => 1, + 18 => 1, + 20 => 1, + 22 => 2, + 28 => 2, + 32 => 1, + 38 => 2, + 42 => 1, + 48 => 2, + 52 => 1, + 62 => 2, + 66 => 2, + 76 => 4, + 80 => 2, + 94 => 1, + 99 => 1, + 108 => 1, + 112 => 1, + ]; + + switch ($testFile) { + case 'ControlSignatureUnitTest.1.inc': + $errors[122] = 1; + $errors[130] = 2; + $errors[134] = 1; + $errors[150] = 1; + $errors[153] = 1; + $errors[158] = 1; + $errors[165] = 1; + $errors[170] = 2; + $errors[185] = 1; + $errors[190] = 2; + $errors[191] = 2; + $errors[195] = 1; + $errors[227] = 1; + $errors[234] = 1; + $errors[239] = 2; + $errors[243] = 2; + $errors[244] = 2; + $errors[248] = 1; + $errors[259] = 1; + $errors[262] = 1; + $errors[267] = 1; + $errors[269] = 1; + $errors[276] = 1; + $errors[279] = 1; + $errors[283] = 1; + $errors[306] = 3; + $errors[309] = 1; + $errors[315] = 1; + return $errors; + + case 'ControlSignatureUnitTest.js': + return $errors; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc new file mode 100644 index 000000000..91d0a23c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc @@ -0,0 +1,14 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ElseIfDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ElseIfDeclarationSniff + */ +final class ElseIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc new file mode 100644 index 000000000..4709923ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc @@ -0,0 +1,36 @@ + $that) { +} + +// Invalid. +foreach ( $something as $blah => $that ) { +} + +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach (${something}AS$blah=>$that) { +} + +// The works. +foreach ( $something aS $blah => $that ) { +} + +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 1 +foreach ($something as $blah => $that) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 0 + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..b0de6ebcb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.inc.fixed @@ -0,0 +1,36 @@ + $that) { +} + +// Invalid. +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach ($something as $blah => $that) { +} + +foreach (${something} as $blah => $that) { +} + +// The works. +foreach ($something as $blah => $that) { +} + +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 1 +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +foreach ( $something as $blah => $that ) {} +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForEachLoopDeclaration requiredSpacesBeforeClose 0 + +foreach ([ + 'foo' => 'bar', + 'foobaz' => 'bazzy', + ] as $key => $value) { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php new file mode 100644 index 000000000..5e70703ed --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php @@ -0,0 +1,61 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ForEachLoopDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ForEachLoopDeclarationSniff + */ +final class ForEachLoopDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 2, + 11 => 2, + 14 => 2, + 17 => 5, + 21 => 7, + 26 => 2, + 28 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc new file mode 100644 index 000000000..d10bd9800 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc @@ -0,0 +1,126 @@ +i ; }; $i < function() { return $this->max; }; $i++) {} +for ($i = function() { return $this->i; }; $i < function() { return $this->max; } ; $i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines true +for ( + $i = 0; + $i < 5; + $i++ +) { + // body here +} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines false diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc.fixed new file mode 100644 index 000000000..85214c03e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.inc.fixed @@ -0,0 +1,92 @@ +i ; }; $i < function() { return $this->max; }; $i++) {} +for ($i = function() { return $this->i; }; $i < function() { return $this->max; }; $i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines true +for ( + $i = 0; + $i < 5; + $i++ +) { + // body here +} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration ignoreNewlines false diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js new file mode 100644 index 000000000..94e1f7484 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js @@ -0,0 +1,122 @@ +// Valid. +for (var i = 0; i < 10; i++) { +} + +// Invalid. +for ( i = 0; i < 10; i++ ) { +} + +for (i = 0; i < 10; i++) { +} + +for (var i = 0 ; i < 10 ; i++) { +} + +for (i = 0;i < 10;i++) { +} + +// The works. +for ( var i = 0 ; i < 10 ; i++ ) { +} + +this.formats = {}; +dfx.inherits('ContentFormat', 'Widget'); + +for (var widgetid in this.loadedContents) { + if (dfx.isset(widget) === true) { + widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);}); + } +} + +for (var i = 0; i < 10;) { +} +for (var i = 0; i < 10; ) { +} + +for (var i = 0; ; i++) { +} +for (var i = 0;; i++) { +} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for (var i = 0; i < 10; i++) {} +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +for ( ; i < 10; i++) {} +for (; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} +for (; i < 10; i++ ) {} + +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10;) {} +for ( i = 0; i < 10; ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test handling of comments and inline annotations. +for ( /*phpcs:enable*/ i = 0 /*start*/ ; /*end*/i < 10/*comment*/; i++ /*comment*/ ) {} + +// Test multi-line FOR control structure. +for ( + i = 0; + i < 10; + i++ +) {} + +// Test multi-line FOR control structure with comments and annotations. +for ( + i = 0; /* Start */ + i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + i++ // comment + +) {} + +// Test fixing each error in one go. Note: lines 84 + 88 contain trailing whitespace on purpose. +for ( + + + i = 0 + + ; + + i < 10 + + ; + + i++ + + +) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( + + + + i = 0 + + ; + + i < 10 + + ; + + i++ + + +) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test with semicolon not belonging to for. +for (i = function() {self.widgetLoaded(widget.id) ; }; i < function() {self.widgetLoaded(widget.id);}; i++) {} +for (i = function() {self.widgetLoaded(widget.id);}; i < function() {self.widgetLoaded(widget.id);} ; i++) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js.fixed new file mode 100644 index 000000000..fbf9b6098 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.1.js.fixed @@ -0,0 +1,88 @@ +// Valid. +for (var i = 0; i < 10; i++) { +} + +// Invalid. +for (i = 0; i < 10; i++) { +} + +for (i = 0; i < 10; i++) { +} + +for (var i = 0; i < 10; i++) { +} + +for (i = 0; i < 10; i++) { +} + +// The works. +for (var i = 0; i < 10; i++) { +} + +this.formats = {}; +dfx.inherits('ContentFormat', 'Widget'); + +for (var widgetid in this.loadedContents) { + if (dfx.isset(widget) === true) { + widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);}); + } +} + +for (var i = 0; i < 10;) { +} +for (var i = 0; i < 10;) { +} + +for (var i = 0;; i++) { +} +for (var i = 0;; i++) { +} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +for ( var i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +for (; i < 10; i++) {} +for (; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} +for ( ; i < 10; i++ ) {} + +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10; ) {} +for ( i = 0; i < 10; ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test handling of comments and inline annotations. +for (/*phpcs:enable*/ i = 0 /*start*/; /*end*/i < 10/*comment*/; i++ /*comment*/) {} + +// Test multi-line FOR control structure. +for (i = 0; i < 10; i++) {} + +// Test multi-line FOR control structure with comments and annotations. +for (i = 0; /* Start */ + i < 10; /* phpcs:ignore Standard.Category.SniffName -- for reasons. */ + i++ // comment + +) {} + +// Test fixing each error in one go. Note: lines 84 + 88 contain trailing whitespace on purpose. +for (i = 0; i < 10; i++) {} + +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 1 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 1 +for ( i = 0; i < 10; i++ ) {} +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesAfterOpen 0 +// phpcs:set Squiz.ControlStructures.ForLoopDeclaration requiredSpacesBeforeClose 0 + +// Test with semicolon not belonging to for. +for (i = function() {self.widgetLoaded(widget.id) ; }; i < function() {self.widgetLoaded(widget.id);}; i++) {} +for (i = function() {self.widgetLoaded(widget.id);}; i < function() {self.widgetLoaded(widget.id);}; i++) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.2.inc new file mode 100644 index 000000000..a327ccedd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.2.inc @@ -0,0 +1,6 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ForLoopDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ForLoopDeclarationSniff + */ +final class ForLoopDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ForLoopDeclarationUnitTest.1.inc': + return [ + 8 => 2, + 11 => 2, + 14 => 2, + 17 => 2, + 21 => 6, + 27 => 1, + 30 => 1, + 37 => 2, + 39 => 2, + 43 => 1, + 49 => 1, + 50 => 1, + 53 => 1, + 54 => 1, + 59 => 4, + 62 => 1, + 63 => 1, + 64 => 1, + 66 => 1, + 69 => 1, + 74 => 1, + 77 => 1, + 82 => 2, + 86 => 2, + 91 => 1, + 95 => 1, + 101 => 2, + 105 => 2, + 110 => 1, + 116 => 2, + ]; + + case 'ForLoopDeclarationUnitTest.1.js': + return [ + 6 => 2, + 9 => 2, + 12 => 2, + 15 => 2, + 19 => 6, + 33 => 1, + 36 => 1, + 43 => 2, + 45 => 2, + 49 => 1, + 55 => 1, + 56 => 1, + 59 => 1, + 60 => 1, + 65 => 4, + 68 => 1, + 69 => 1, + 70 => 1, + 72 => 1, + 75 => 1, + 80 => 1, + 83 => 1, + 88 => 2, + 92 => 2, + 97 => 1, + 101 => 1, + 107 => 2, + 111 => 2, + 116 => 1, + 122 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'ForLoopDeclarationUnitTest.2.inc': + case 'ForLoopDeclarationUnitTest.3.inc': + return [6 => 1]; + + case 'ForLoopDeclarationUnitTest.2.js': + return [2 => 1]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc new file mode 100644 index 000000000..f54ed8af0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc @@ -0,0 +1,48 @@ +id.'"', + '"'.$this->stepInfo['title'].'"', + '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"', + '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"', + '"'.$this->stepInfo['title'].'"', + ); + +echo (TRUE)?'Hello':'Bye'; + +$array = array( + 'one' => ($test == 1) ? true : false, + 'two' => (($test == 1) ? true : false), + 'three' => (($test == 1) ? true : false) +); +$var = ($test == 1) ? true : false; +$var = (myFunc(1,2,3) == 1) ? true : false; + +set('config', function() { + $foo = ($bar === "on") ? "1" : "2"; +}); + +$config = function() { + $foo = ($bar === "on") ? "1" : "2"; +}; + +rand(0, 1) ? 'ěšÄřžýáí' : NULL; + +$c = ($argv[1]) ? : ""; +$filepath = realpath($argv[1]) ?: $argv[1]; +$c = ($argv[1]) ? /* comment */ : ""; +$c = ($argv[1]) ? +: ""; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed new file mode 100644 index 000000000..f7aa1d67c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc.fixed @@ -0,0 +1,48 @@ +id.'"', + '"'.$this->stepInfo['title'].'"', + '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"', + '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"', + '"'.$this->stepInfo['title'].'"', + ); + +echo (TRUE) ? 'Hello' : 'Bye'; + +$array = array( + 'one' => ($test == 1) ? true : false, + 'two' => (($test == 1) ? true : false), + 'three' => (($test == 1) ? true : false) +); +$var = ($test == 1) ? true : false; +$var = (myFunc(1,2,3) == 1) ? true : false; + +set('config', function() { + $foo = ($bar === "on") ? "1" : "2"; +}); + +$config = function() { + $foo = ($bar === "on") ? "1" : "2"; +}; + +rand(0, 1) ? 'ěšÄřžýáí' : NULL; + +$c = ($argv[1]) ?: ""; +$filepath = realpath($argv[1]) ?: $argv[1]; +$c = ($argv[1]) ? /* comment */ : ""; +$c = ($argv[1]) ? +: ""; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php new file mode 100644 index 000000000..dc4738e0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the InlineIfDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\InlineIfDeclarationSniff + */ +final class InlineIfDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getCliValues($testFile) + { + return ['--encoding=utf-8']; + + }//end getCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 1, + 13 => 1, + 20 => 1, + 24 => 4, + 44 => 1, + 47 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc new file mode 100644 index 000000000..1acf3eac4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc @@ -0,0 +1,24 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowercaseDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\LowercaseDeclarationSniff + */ +final class LowercaseDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 7 => 1, + 9 => 1, + 10 => 1, + 12 => 1, + 14 => 1, + 15 => 1, + 16 => 1, + 20 => 1, + 21 => 1, + 24 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc new file mode 100644 index 000000000..cf397607b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc @@ -0,0 +1,333 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\ControlStructures; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SwitchDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\SwitchDeclarationSniff + */ +final class SwitchDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SwitchDeclarationUnitTest.inc': + return [ + 27 => 1, + 29 => 1, + 34 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 52 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 62 => 1, + 79 => 1, + 85 => 2, + 88 => 2, + 89 => 2, + 92 => 1, + 95 => 3, + 99 => 1, + 116 => 1, + 122 => 1, + 127 => 2, + 134 => 2, + 135 => 1, + 138 => 1, + 143 => 1, + 144 => 1, + 147 => 1, + 165 => 1, + 172 => 1, + 176 => 2, + 180 => 1, + 192 => 2, + 196 => 1, + 223 => 1, + 266 => 1, + 282 => 1, + 284 => 2, + 322 => 1, + 323 => 1, + 327 => 1, + 329 => 1, + 330 => 1, + ]; + + case 'SwitchDeclarationUnitTest.js': + return [ + 27 => 1, + 29 => 1, + 34 => 1, + 36 => 1, + 44 => 1, + 48 => 1, + 52 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 62 => 1, + 79 => 1, + 85 => 2, + 88 => 2, + 89 => 2, + 92 => 1, + 95 => 3, + 99 => 1, + 116 => 1, + 122 => 1, + 127 => 2, + 134 => 2, + 135 => 1, + 138 => 1, + 143 => 1, + 144 => 1, + 147 => 1, + 165 => 1, + 172 => 1, + 176 => 2, + 180 => 1, + 192 => 2, + 196 => 1, + 223 => 1, + 266 => 1, + 282 => 1, + 284 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + if ($testFile === 'SwitchDeclarationUnitTest.js') { + return [273 => 1]; + } + + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js new file mode 100644 index 000000000..797e0eea2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.js @@ -0,0 +1,2 @@ +alert('hi') +alert('hi'); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php new file mode 100644 index 000000000..c4b14dc2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JSLintUnitTest.php @@ -0,0 +1,74 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +/** + * Unit test class for the JSLint sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug\JSLintSniff + */ +final class JSLintUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return bool + */ + protected function shouldSkipTest() + { + $jslPath = Config::getExecutablePath('jslint'); + if ($jslPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 1 => 2, + 2 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js new file mode 100644 index 000000000..797e0eea2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js @@ -0,0 +1,2 @@ +alert('hi') +alert('hi'); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php new file mode 100644 index 000000000..96a68d7c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +/** + * Unit test class for the JavaScriptLint sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Debug\JavaScriptLintSniff + */ +final class JavaScriptLintUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return bool + */ + protected function shouldSkipTest() + { + $jslPath = Config::getExecutablePath('jsl'); + if ($jslPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc new file mode 100644 index 000000000..3279edb54 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc new file mode 100644 index 000000000..05be63306 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc new file mode 100644 index 000000000..ec1b02390 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc new file mode 100644 index 000000000..ed0456463 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc new file mode 100644 index 000000000..d777aff6b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.5.inc @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php new file mode 100644 index 000000000..065922547 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Files/FileExtensionUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FileExtension sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Files\FileExtensionSniff + */ +final class FileExtensionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FileExtensionUnitTest.1.inc': + return [1 => 1]; + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc new file mode 100644 index 000000000..8e6289638 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc @@ -0,0 +1,203 @@ +words[$wordPos-1]) || $this->words[$wordPos-1] !== ' ') { +} else if ($this->tokens[$pos + 1] === "\n") { +} + +if ($pos === count($this->tokens) - 1) { + $file = '...'.substr($file, (($padding * -1) + 3)); +} + +if (substr($basename, -5) !== 'Sniff') { + $i = ($this->_tokens[$i]['parenthesis_closer'] + 1); +} + +$pos = $this->_getShortCommentEndPos(); +if ($pos === -1) { + $stackPtr = ($tokens[$next][$to] - 1); + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + $var = (($var1 + $var2) + $var3 + $var4) +} + +$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); +$commentEnd = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1); +$expected .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content']; + +if (($tokens[$nextToken - 1]['code']) !== T_WHITESPACE) { + $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart); +} + +while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, $nextSpace + 1, $nextBreak)) !== false) { +} + +foreach ($attributes as $id => &$attribute) { +} + +class MyClass +{ + + + public function &myFunction(array &$one, array &$two) + { + + }//end myFunction() + + +}//end class + +if ($index < -1) $index = 0; +if ($index < - 1) $index = 0; + +$three = ceil($one / $two); +$three = ceil(($one / $two) / $four); +$three = ceil($one / ($two / $four)); + +$four = -0.25; + +$three = ceil($one[1] / $two); + +switch ($number % 10) { + case -1: + $suffix = 'st'; + break; +} + +$expectedPermission = array( + 'granted' => 4, + 'denied' => 1, + 'cascade' => TRUE, + 'blockergranted' => 2, + 'blockerdenied' => - 3, + 'effective' => TRUE, + ); + +$value = (int) isset($blah) + 2; +$value = (int) isset($blah) + (int) isset($foo) + (int) isset($bar); + +doSomething(getValue($var, 2)) - $y; + +$codeFiles = array($global => $codeFiles[$global]) + $codeFiles; + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$cntPages = ceil(count($items) / self::ON_PAGE); + +error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); +error_reporting(E_ALL & ~E_NOTICE | ~E_WARNING); +$results = $stmt->fetchAll(\PDO::FETCH_ASSOC | \PDO::FETCH_GROUP | \PDO::FETCH_UNIQUE); +$di = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS); +foo(1 + 2 + 3); + +if (empty($foo[-1]) === true) { + $foo[-1] = 'foo'; +} + +try { +} catch (AException | BException $e) { +} + +$var = $foo['blah'] + []; + +$a = 2 * ${x} - ${minus}; + +$foo = $bar ?? $baz ?? ''; + +$foo = $myString{-1}; + +$value = (binary) $blah + b"binary $foo"; + +$test = (1 * static::TEST); +$test = myfunc(1 * static::TEST); + +$errorPos = $params[$x]?->getLine() + $commentStart; + +$foo = $this->gmail ?? $this->gmail = new Google_Service_Gmail($this->google); + +exit -1; + +$expr = match ($number - 10) { + -1 => 0, +}; + +$expr = match ($number % 10) { + 1 => 2 * $num, +}; + +$expr = match (true) { + $num * 100 > 500 => 'expression in key', +}; + +// PHP 8.0 named parameters. +if ($pos === count(value: $this->tokens) - 1) { + $file = '...'.substr(string: $file, offset: $padding * -1 + 3); +} + +match ($a) { + 'a' => -1, + 'b', 'c', 'd' => -2, + default => -3, +}; + +$cntPages = ceil(count($items) / parent::ON_PAGE); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc.fixed new file mode 100644 index 000000000..9fa0216cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.1.inc.fixed @@ -0,0 +1,203 @@ +words[($wordPos-1)]) || $this->words[($wordPos-1)] !== ' ') { +} else if ($this->tokens[($pos + 1)] === "\n") { +} + +if ($pos === (count($this->tokens) - 1)) { + $file = '...'.substr($file, (($padding * -1) + 3)); +} + +if (substr($basename, -5) !== 'Sniff') { + $i = ($this->_tokens[$i]['parenthesis_closer'] + 1); +} + +$pos = $this->_getShortCommentEndPos(); +if ($pos === -1) { + $stackPtr = ($tokens[$next][$to] - 1); + $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1); + $var = (($var1 + $var2) + $var3 + $var4) +} + +$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); +$commentEnd = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1); +$expected .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content']; + +if (($tokens[($nextToken - 1)]['code']) !== T_WHITESPACE) { + $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart); +} + +while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, ($nextSpace + 1), $nextBreak)) !== false) { +} + +foreach ($attributes as $id => &$attribute) { +} + +class MyClass +{ + + + public function &myFunction(array &$one, array &$two) + { + + }//end myFunction() + + +}//end class + +if ($index < -1) $index = 0; +if ($index < - 1) $index = 0; + +$three = ceil($one / $two); +$three = ceil(($one / $two) / $four); +$three = ceil($one / ($two / $four)); + +$four = -0.25; + +$three = ceil($one[1] / $two); + +switch ($number % 10) { + case -1: + $suffix = 'st'; + break; +} + +$expectedPermission = array( + 'granted' => 4, + 'denied' => 1, + 'cascade' => TRUE, + 'blockergranted' => 2, + 'blockerdenied' => - 3, + 'effective' => TRUE, + ); + +$value = ((int) isset($blah) + 2); +$value = ((int) isset($blah) + (int) isset($foo) + (int) isset($bar)); + +(doSomething(getValue($var, 2)) - $y); + +$codeFiles = (array($global => $codeFiles[$global]) + $codeFiles); + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$cntPages = ceil(count($items) / self::ON_PAGE); + +error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING); +error_reporting(E_ALL & ~E_NOTICE | ~E_WARNING); +$results = $stmt->fetchAll(\PDO::FETCH_ASSOC | \PDO::FETCH_GROUP | \PDO::FETCH_UNIQUE); +$di = new \RecursiveDirectoryIterator($path, (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)); +foo(1 + 2 + 3); + +if (empty($foo[-1]) === true) { + $foo[-1] = 'foo'; +} + +try { +} catch (AException | BException $e) { +} + +$var = ($foo['blah'] + []); + +$a = 2 * ${x} - ${minus}; + +$foo = ($bar ?? $baz ?? ''); + +$foo = $myString{-1}; + +$value = ((binary) $blah + b"binary $foo"); + +$test = (1 * static::TEST); +$test = myfunc(1 * static::TEST); + +$errorPos = ($params[$x]?->getLine() + $commentStart); + +$foo = ($this->gmail ?? $this->gmail = new Google_Service_Gmail($this->google)); + +exit -1; + +$expr = match ($number - 10) { + -1 => 0, +}; + +$expr = match ($number % 10) { + 1 => (2 * $num), +}; + +$expr = match (true) { + ($num * 100) > 500 => 'expression in key', +}; + +// PHP 8.0 named parameters. +if ($pos === (count(value: $this->tokens) - 1)) { + $file = '...'.substr(string: $file, offset: ($padding * -1 + 3)); +} + +match ($a) { + 'a' => -1, + 'b', 'c', 'd' => -2, + default => -3, +}; + +$cntPages = ceil(count($items) / parent::ON_PAGE); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.2.inc new file mode 100644 index 000000000..1284f121f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.2.inc @@ -0,0 +1,7 @@ +\s]+))?)+\s*|\s*)\/?>/gim); + +var options = { + minVal: -1, + maxVal: -1 +}; + +stepWidth = Math.round(this.width / 5); + +date.setMonth(d[2] - 1); + +switch (number % 10) { + case -1: + suffix = 'st'; + break; +} + +var pathSplit = ipt.value.split(/\/|\\/); + +if (pairs[i].search(/=/) !== -1) { +} + +if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) { +} + +if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) { +} + +if (!value || /^\s*$/.test(value)) { + return true; +} + +parseInt(dfx.attr(selectors[idx], 'elemOffsetTop'), 10) - scrollCoords.y + 'px' + +if (something === true + ^ somethingElse === true +) { + return false; +} + +if (true === /^\d*\.?\d*$/.test(input)) return true; + +if ( ! /^(?:a|select)$/i.test( element.tagName ) ) return true; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed new file mode 100644 index 000000000..04e35d977 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js.fixed @@ -0,0 +1,118 @@ +value = (one + two); +value = one + two; + +value = (one - two); +value = (one - two); + +value = (one * two); +value = (one * two); + +value = (one / two); +value = (one / two); + +value = (one % two); +value = (one % two); + +value = (one + two + three); +value = one + two + three; +value = (one + (two + three)); +value = one + (two + three); + +value++; +value--; +value = -1; +value = - 1; + +value = (1 + 2); +value = 1 + 2; + +value = (1 - 2); +value = (1 - 2); + +value = (1 * 2); +value = (1 * 2); + +value = (1 / 2); +value = (1 / 2); + +value = (1 % 2); +value = (1 % 2); + +value = (1 + 2 + 3); +value = 1 + 2 + 3; +value = (1 + (2 + 3)); +value = 1 + (2 + 3); + +value = one + 2 + (3 - (four * five * (6 + 7))) + nine + 2; +value = myFunction(tokens[(stackPtr - 1)]); + +for (i = 1 + 2; i < 4 + 5; i++) { +} + +function myFunction() +{ + value = (one + 1) + (two + 2) + (myFunction() + 2); + value = myFunction() + 2; + value = (myFunction(mvar) + myFunction2(mvar)); + return -1; +} + +params['mode'] = id.replace(/WidgetType/, ''); + +if (index < -1) index = 0; +if (index < - 1) index = 0; + +var classN = prvId.replace(/\./g, '-'); + +three = myFunction(one / two); +three = myFunction((one / two) / four); +three = myFunction(one / (two / four)); + +four = -0.25; + +id = id.replace(/row\/:/gi, ''); +return /MSIE/.test(navigator.userAgent); + +var re = new RegExp(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gim); + +var options = { + minVal: -1, + maxVal: -1 +}; + +stepWidth = Math.round(this.width / 5); + +date.setMonth(d[2] - 1); + +switch (number % 10) { + case -1: + suffix = 'st'; + break; +} + +var pathSplit = ipt.value.split(/\/|\\/); + +if (pairs[i].search(/=/) !== -1) { +} + +if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) { +} + +if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) { +} + +if (!value || /^\s*$/.test(value)) { + return true; +} + +(parseInt(dfx.attr(selectors[idx], 'elemOffsetTop'), 10) - scrollCoords.y) + 'px' + +if (something === true + ^ somethingElse === true +) { + return false; +} + +if (true === /^\d*\.?\d*$/.test(input)) return true; + +if ( ! /^(?:a|select)$/i.test( element.tagName ) ) return true; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php new file mode 100644 index 000000000..aac432757 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php @@ -0,0 +1,121 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Formatting; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the OperatorBracket sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Formatting\OperatorBracketSniff + */ +final class OperatorBracketUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'OperatorBracketUnitTest.1.inc': + return [ + 3 => 1, + 6 => 1, + 9 => 1, + 12 => 1, + 15 => 1, + 18 => 2, + 20 => 1, + 25 => 1, + 28 => 1, + 31 => 1, + 34 => 1, + 37 => 1, + 40 => 1, + 43 => 2, + 45 => 1, + 47 => 5, + 48 => 1, + 50 => 2, + 55 => 2, + 56 => 1, + 63 => 2, + 64 => 1, + 67 => 1, + 86 => 1, + 90 => 1, + 109 => 1, + 130 => 1, + 134 => 1, + 135 => 2, + 137 => 1, + 139 => 1, + 150 => 1, + 161 => 1, + 163 => 2, + 165 => 2, + 169 => 1, + 174 => 1, + 176 => 1, + 185 => 1, + 189 => 1, + 193 => 1, + 194 => 2, + ]; + + case 'OperatorBracketUnitTest.js': + return [ + 5 => 1, + 8 => 1, + 11 => 1, + 14 => 1, + 24 => 1, + 30 => 1, + 33 => 1, + 36 => 1, + 39 => 1, + 46 => 1, + 47 => 1, + 63 => 1, + 108 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc new file mode 100644 index 000000000..33564e2e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc @@ -0,0 +1,111 @@ + $a($b); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..68fb1c1c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc.fixed @@ -0,0 +1,111 @@ + $a($b); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php new file mode 100644 index 000000000..62ccfef2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.php @@ -0,0 +1,91 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionDeclarationArgumentSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\FunctionDeclarationArgumentSpacingSniff + */ +final class FunctionDeclarationArgumentSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 2, + 7 => 2, + 8 => 2, + 9 => 2, + 11 => 2, + 13 => 7, + 14 => 2, + 15 => 2, + 16 => 4, + 18 => 2, + 35 => 2, + 36 => 2, + 44 => 2, + 45 => 1, + 46 => 1, + 51 => 2, + 53 => 2, + 55 => 1, + 56 => 1, + 58 => 1, + 73 => 7, + 76 => 1, + 77 => 1, + 81 => 1, + 89 => 2, + 92 => 1, + 93 => 1, + 94 => 1, + 95 => 1, + 99 => 11, + 100 => 2, + 101 => 2, + 102 => 2, + 106 => 1, + 107 => 2, + 111 => 3, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.1.inc new file mode 100644 index 000000000..0cde1138c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.1.inc @@ -0,0 +1,75 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\FunctionDeclarationSniff + */ +final class FunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionDeclarationUnitTest.1.inc': + return [ + 55 => 1, + 68 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc new file mode 100644 index 000000000..27102d057 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php new file mode 100644 index 000000000..f29f80900 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionDuplicateArgument sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\FunctionDuplicateArgumentSniff + */ +final class FunctionDuplicateArgumentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 2, + 5 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc new file mode 100644 index 000000000..b7b7f205c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc @@ -0,0 +1,17 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php new file mode 100644 index 000000000..1a0779156 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php @@ -0,0 +1,53 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the GlobalFunction sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\GlobalFunctionSniff + */ +final class GlobalFunctionUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc new file mode 100644 index 000000000..4e8683362 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc @@ -0,0 +1,28 @@ + $x; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed new file mode 100644 index 000000000..48c997774 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc.fixed @@ -0,0 +1,28 @@ + $x; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php new file mode 100644 index 000000000..c91c3008c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php @@ -0,0 +1,63 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowercaseFunctionKeywords sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\LowercaseFunctionKeywordsSniff + */ +final class LowercaseFunctionKeywordsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 16 => 1, + 17 => 1, + 20 => 1, + 21 => 1, + 22 => 1, + 23 => 1, + 24 => 3, + 25 => 4, + 28 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc new file mode 100644 index 000000000..e9f019eb5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc @@ -0,0 +1,356 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Functions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MultiLineFunctionDeclaration sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\MultiLineFunctionDeclarationSniff + */ +final class MultiLineFunctionDeclarationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile === 'MultiLineFunctionDeclarationUnitTest.inc') { + $errors = [ + 2 => 1, + 3 => 1, + 4 => 2, + 5 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 36 => 1, + 43 => 2, + 48 => 1, + 81 => 1, + 82 => 2, + 88 => 1, + 102 => 2, + 137 => 1, + 141 => 2, + 142 => 1, + 158 => 1, + 160 => 1, + 182 => 2, + 186 => 2, + 190 => 2, + 194 => 1, + 195 => 1, + 233 => 1, + 234 => 1, + 235 => 1, + 236 => 1, + 244 => 1, + 245 => 1, + 246 => 1, + 247 => 1, + 248 => 1, + 249 => 1, + 250 => 1, + 251 => 1, + 252 => 1, + 253 => 1, + 254 => 1, + 318 => 1, + 323 => 1, + ]; + } else { + $errors = [ + 2 => 1, + 3 => 1, + 4 => 2, + 5 => 1, + 7 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 16 => 1, + 26 => 1, + 36 => 1, + 43 => 2, + 48 => 1, + 65 => 1, + ]; + }//end if + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc new file mode 100644 index 000000000..aacef347b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -0,0 +1,27 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php new file mode 100644 index 000000000..7b9692e7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidFunctionName sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions\ValidFunctionNameSniff + */ +final class ValidFunctionNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + 12 => 1, + 13 => 1, + 14 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 000000000..87c3bdf2e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,157 @@ +varName2; +echo $this->var_name2; +echo $this->varname2; +echo $this->_varName2; +echo $object->varName2; +echo $object->var_name2; +echo $object_name->varname2; +echo $object_name->_varName2; + +echo $this->myFunction($one, $two); +echo $object->myFunction($one_two); + +$error = "format is \$GLOBALS['$varName']"; + +echo $_SESSION['var_name']; +echo $_FILES['var_name']; +echo $_ENV['var_name']; +echo $_COOKIE['var_name']; + +$XML = 'hello'; +$myXML = 'hello'; +$XMLParser = 'hello'; +$xmlParser = 'hello'; + +echo "{$_SERVER['HOSTNAME']} $var_name"; + +// Need to be the last thing in this test file. +$obj->$classVar = $prefix.'-'.$type; + +class foo +{ + const bar = <<varName; +echo $obj?->var_name; +echo $obj?->varname; +echo $obj?->_varName; + +enum SomeEnum +{ + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 000000000..d8d8695c6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,93 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidVariableName sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions\ValidVariableNameSniff + */ +final class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + $errors = [ + 3 => 1, + 5 => 1, + 10 => 1, + 12 => 1, + 15 => 1, + 17 => 1, + 20 => 1, + 22 => 1, + 25 => 1, + 27 => 1, + 31 => 1, + 33 => 1, + 36 => 1, + 37 => 1, + 39 => 1, + 42 => 1, + 44 => 1, + 53 => 1, + 58 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 67 => 1, + 81 => 1, + 106 => 1, + 107 => 2, + 108 => 1, + 111 => 1, + 112 => 1, + 113 => 1, + 114 => 1, + 123 => 1, + 138 => 1, + 141 => 1, + 146 => 1, + 152 => 1, + 155 => 1, + ]; + + return $errors; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js new file mode 100644 index 000000000..1c61fbfbb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js @@ -0,0 +1,37 @@ +function test(id) +{ + + this.id = id; + +} +/**/ +test.prototype = { + init: function() + { + var x = {}; + x.name = 'test'; + x['phone'] = 123124324; + var t = ['test', 'this'].join(''); + var y = ['test'].join(''); + var a = x[0]; + var z = x[x['name']]; + var p = x[x.name]; + } + +}; + +function test() { + this.errors['step_' + step] = errors; + this.errors['test'] = x; + this.errors['test' + 10] = x; + this.errors['test' + y] = x; + this.errors['test' + 'blah'] = x; + this.errors[y] = x; + this.errors[y + z] = x; + this.permissions['workflow.cancel'] = x; +} + +if (child.prototype) { + above.prototype['constructor'] = parent; + child.prototype['super'] = new above(); +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php new file mode 100644 index 000000000..36880a9a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowObjectStringIndex sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects\DisallowObjectStringIndexSniff + */ +final class DisallowObjectStringIndexUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + if ($testFile !== 'DisallowObjectStringIndexUnitTest.js') { + return []; + } + + return [ + 13 => 1, + 17 => 1, + 25 => 1, + 35 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc new file mode 100644 index 000000000..b6df38c9d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc @@ -0,0 +1,49 @@ + new MyClass()); +$object->myFunction(new MyClass()); + +throw new MyException($msg); + +function foo() { return new MyClass(); } + +$doodad = $x ? new Foo : new Bar; + +function returnFn() { + $fn = fn($x) => new MyClass(); +} + +function returnMatch() { + $match = match($x) { + 0 => new MyClass() + } +} + +// Issue 3333. +$time2 ??= new \DateTime(); +$time3 = $time1 ?? new \DateTime(); +$time3 = $time1 ?? $time2 ?? new \DateTime(); + +function_call($time1 ?? new \DateTime()); +$return = function_call($time1 ?? new \DateTime()); // False negative depending on interpretation of the sniff. + +function returnViaTernary() { + return ($y == false ) ? ($x === true ? new Foo : new Bar) : new FooBar; +} + +function nonAssignmentTernary() { + if (($x ? new Foo() : new Bar) instanceof FooBar) { + // Do something. + } +} + +// Test for tokenizer issue #3789. +$a = $b !== null + ? match ($c) { + default => 5, + } + : new Foo; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php new file mode 100644 index 000000000..bfd4bef29 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ObjectInstantiation sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects\ObjectInstantiationSniff + */ +final class ObjectInstantiationUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 8 => 1, + 31 => 1, + 39 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js new file mode 100644 index 000000000..28bf85ade --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js @@ -0,0 +1,47 @@ +this.request({ action: 'getTypeFormatContents', }); + +addTypeFormatButton.addClickEvent(function() { + self.addNewTypeFormat(); +}); + +var x = {}; + +var y = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var z = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + }, +}; + +var x = function() { + console.info(2); +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + }, +}; + +AssetListingEditWidgetType.prototype = { + // phpcs: disable Standard.Cat.SniffName -- testing annotation between closing brace and comma + init: function(data, assetid, editables) + { + }, + // phpcs:enable +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed new file mode 100644 index 000000000..df548c741 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js.fixed @@ -0,0 +1,47 @@ +this.request({ action: 'getTypeFormatContents' }); + +addTypeFormatButton.addClickEvent(function() { + self.addNewTypeFormat(); +}); + +var x = {}; + +var y = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var z = { + VarOne : 'If you ask me, thats if you ask', + VarTwo : ['Alonzo played you', 'for a fool', 'esse'], + VarThree: function(arg) { + console.info(1); + } +}; + +var x = function() { + console.info(2); +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + init: function(data, assetid, editables) + { + } +}; + +AssetListingEditWidgetType.prototype = { + // phpcs: disable Standard.Cat.SniffName -- testing annotation between closing brace and comma + init: function(data, assetid, editables) + { + } + // phpcs:enable +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php new file mode 100644 index 000000000..0ac826f3a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Objects; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ObjectMemberComma sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Objects\ObjectMemberCommaSniff + */ +final class ObjectMemberCommaUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 1 => 1, + 22 => 1, + 38 => 1, + 45 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc new file mode 100644 index 000000000..8522438dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.inc @@ -0,0 +1,138 @@ + + 0)) { +} + +myFunction($var1 === true ? "" : "foobar"); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js new file mode 100644 index 000000000..048223ba1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.js @@ -0,0 +1,71 @@ +if (value === TRUE) { +} else if (value === FALSE) { +} + +if (value == TRUE) { +} else if (value == FALSE) { +} + +if (value) { +} else if (!value) { +} + +if (value.isSomething === TRUE) { +} else if (myFunction(value) === FALSE) { +} + +if (value.isSomething == TRUE) { +} else if (myFunction(value) == FALSE) { +} + +if (value.isSomething) { +} else if (!myFunction(value)) { +} + +if (value === TRUE || other === FALSE) { +} + +if (value == TRUE || other == FALSE) { +} + +if (value || !other) { +} + +if (one === TRUE || two === TRUE || three === FALSE || four === TRUE) { +} + +if (one || two || !three || four) { +} + +while (one == true) { +} + +while (one === true) { +} + +do { +} while (one == true); + +do { +} while (one === true); + +for (one = 10; one != 0; one--) { +} + +for (one = 10; one !== 0; one--) { +} + +for (type in types) { +} + +variable = (variable2 === true) ? variable1 : "foobar"; + +variable = (variable2 == true) ? variable1 : "foobar"; + +variable = (variable2 === false) ? variable1 : "foobar"; + +variable = (variable2 == false) ? variable1 : "foobar"; + +variable = (variable2 === 0) ? variable1 : "foobar"; + +variable = (variable2 == 0) ? variable1 : "foobar"; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php new file mode 100644 index 000000000..1189725bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php @@ -0,0 +1,105 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ComparisonOperatorUsage sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators\ComparisonOperatorUsageSniff + */ +final class ComparisonOperatorUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ComparisonOperatorUsageUnitTest.inc': + return [ + 6 => 1, + 7 => 1, + 10 => 1, + 11 => 1, + 18 => 1, + 19 => 1, + 22 => 1, + 23 => 1, + 29 => 2, + 32 => 2, + 38 => 4, + 47 => 2, + 69 => 1, + 72 => 1, + 75 => 1, + 78 => 1, + 80 => 1, + 82 => 1, + 83 => 1, + 89 => 1, + 92 => 1, + 100 => 1, + 106 => 1, + 112 => 1, + 123 => 1, + 127 => 1, + 131 => 1, + 135 => 1, + ]; + + case 'ComparisonOperatorUsageUnitTest.js': + return [ + 5 => 1, + 6 => 1, + 17 => 1, + 18 => 1, + 28 => 2, + 40 => 1, + 47 => 1, + 52 => 1, + 63 => 1, + 67 => 1, + 71 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc new file mode 100644 index 000000000..266695970 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc @@ -0,0 +1,56 @@ +i++).$id; +$id = $obj?->i++.$id; +$id = $obj?->i++*10; + +$var+=1; +$var-=1; + +$var=$var+1; +$var=$var-1; + +$var /*comment*/ +=1; +$var + // phpcs:ignore Something + -=1; + +$var += /*comment*/ 1; +$var = ( $var /*comment*/ - 1 /*comment*/); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php new file mode 100644 index 000000000..e27e196b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the IncrementDecrementUsage sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators\IncrementDecrementUsageSniff + */ +final class IncrementDecrementUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 6 => 1, + 12 => 1, + 16 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + 41 => 1, + 42 => 1, + 44 => 1, + 45 => 1, + 47 => 1, + 48 => 1, + 50 => 1, + 53 => 1, + 55 => 1, + 56 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc new file mode 100644 index 000000000..328ccc5d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc @@ -0,0 +1,28 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php new file mode 100644 index 000000000..d7ce889e3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Operators; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidLogicalOperators sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Operators\ValidLogicalOperatorsSniff + */ +final class ValidLogicalOperatorsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 11 => 1, + 17 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css new file mode 100644 index 000000000..94cc8f27c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css @@ -0,0 +1,23 @@ +/* CSS Document */ + +body { +font-family: Arial, Helvetica, sans-serif; +margin : 40px 0 0 0; +padding : 0; +/*background: #8FB7DB url(login_glow_bg.jpg) no-repeat 30% 0;*/ +background: #8FB7DB url(diag_lines_bg.gif) top left; +} + +#login-container { + margin-left: -225px; + margin-top: -161px; + position:absolute; + top :50%; + /*left :50%;*/ + width:450px; +} + +#cacheConfig-dayLabel, #cacheConfig-hourLabel, #cacheConfig-minuteLabel { + float: left; + padding-right: 8px; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc new file mode 100644 index 000000000..121240a94 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.inc @@ -0,0 +1,158 @@ + + * + * Title + * Contents + * + * ... + * + * + * + * + * @return void + */ + +/* + [^\'"] +*/ + +// http://www.google.com + +// Base config function. + +// function () + +// T_STRING is not a function call or not listed in _getFunctionListWithCallableArgument(). + + // function myFunction( $param ) + // { + // do_something(); + // }//end myFunction() + // + +/* +function myFunction( $param ) +{ + // phpcs:disable Standard.Category.Sniff -- for reasons. + if ( preg_match( '`[abc]`', $param ) > 0 ) { + do_something(); + } + // phpcs:enable Standard.Category.Sniff -- for reasons. + +}//end myFunction() +*/ + + /* + * function myFunction( $param ) // @phpcs:ignore Standard.Category.Sniff -- for reasons. + * { + * + * }//end myFunction() + */ + + /* + * function myFunction( $param ) + * { + * // phpcs:disable Standard.Category.Sniff -- for reasons. + * if ( preg_match( '`[abc]`', $param ) > 0 ) { + * do_something(); + * } + * // phpcs:enable Standard.Category.Sniff -- for reasons. + * + * }//end myFunction() + */ + + // function myFunction( $param ) + // { + // phpcs:disable Standard.Category.Sniff -- for reasons. + // do_something(); + // phpcs:enable Standard.Category.Sniff -- for reasons. + // }//end myFunction() + // + +echo 'something'; // @codeCoverageIgnore +echo 'something'; // @codeCoverageIgnoreStart +echo 'something'; // @SuppressWarnings(PHPMD.UnusedLocalVariable) + +// Ok! + +/* Go! */ + +// ISO-639-3 + + // But override with a different text if any. + /* + $id = intval( str_replace( 'hook_name', '', $order_method['method_id'] ) ); + if ( ! empty( $id ) ) { + $info_text = get_post_meta( $location_id, 'meta_name' ); + + if ( ! empty( $info_text ) ) { + $text = $info_text; + } + + } + */ + // function() { $a = $b; }; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php new file mode 100644 index 000000000..99d8f01ac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the CommentedOutCode sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\CommentedOutCodeSniff + */ +final class CommentedOutCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'CommentedOutCodeUnitTest.inc': + return [ + 6 => 1, + 8 => 1, + 15 => 1, + 19 => 1, + 87 => 1, + 91 => 1, + 97 => 1, + 109 => 1, + 116 => 1, + 128 => 1, + 147 => 1, + 158 => 1, + ]; + + case 'CommentedOutCodeUnitTest.css': + return [ + 7 => 1, + 16 => 1, + ]; + + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc new file mode 100644 index 000000000..4701c23e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inc @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php new file mode 100644 index 000000000..8c3afa4de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowBooleanStatement sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowBooleanStatementSniff + */ +final class DisallowBooleanStatementUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 8 => 1, + 13 => 1, + 15 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc new file mode 100644 index 000000000..a07047b19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc @@ -0,0 +1,83 @@ +nextSibling; $node; $node = $node->nextSibling) { + if ($node->nodeType !== XML_ELEMENT_NODE) { + continue; + } + + for ($node = $fields->nextSibling; $node; $node = $node->nextSibling) { + if ($node->nodeType !== XML_ELEMENT_NODE) { + continue; + } + } +} + +$a = $b ? $c : $d; +$a = $b === true ? $c : $d; + +$this->_args = $this->_getArgs(($_SERVER['argv'] ?? [])); +$args = ($_SERVER['argv'] ?? []); + +$a = [ + 'a' => ($foo) ? $foo : $bar, +]; + +$a = [ + 'a' => ($foo) ? fn() => return 1 : fn() => return 2, +]; + +$var = $foo->something(!$var); +$var = $foo?->something(!$var); + +$callback = function ($value) { + if ($value > 10) { + return false; + } +}; + +function issue3616() { + $food = 'cake'; + + $returnValue = match (true) { + $food === 'apple' => 'This food is an apple', + $food === 'bar' => 'This food is a bar', + $food === 'cake' => 'This food is a cake', + }; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php new file mode 100644 index 000000000..9c0f7e336 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowComparisonAssignment sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowComparisonAssignmentSniff + */ +final class DisallowComparisonAssignmentUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 10 => 1, + 52 => 1, + 53 => 1, + 58 => 1, + 62 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc new file mode 100644 index 000000000..f57e07109 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc @@ -0,0 +1,18 @@ + $x; + +$b = fn ($b) => $b ? true : false; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js new file mode 100644 index 000000000..56387c06f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js @@ -0,0 +1,2 @@ +x = (x?a:x); +id = id.replace(/row\/:/gi, ''); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php new file mode 100644 index 000000000..14f79c87e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowObEndFlush sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowInlineIfSniff + */ +final class DisallowInlineIfUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowInlineIfUnitTest.inc': + return [ + 8 => 1, + 18 => 1, + ]; + + case 'DisallowInlineIfUnitTest.js': + return [1 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.1.inc new file mode 100644 index 000000000..960f907de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.1.inc @@ -0,0 +1,150 @@ +fetch(PDO::FETCH_NUM)) { + $result[$row[0]] = array(); + $result[$row[0]][] = $current; + + self::$_inTransaction = TRUE; + parent::$_inTransaction = TRUE; + static::$_inTransaction = TRUE; + $$varName = $varValue; + } + +}//end getVar() + +class myClass +{ + private static $_dbh = NULL; + public $dbh = NULL; + protected $dbh = NULL; + var $dbh = NULL; // Old PHP4 compatible code. +} + +A::$a = 'b'; +\A::$a = 'c'; +\A\B\C::$d = 'd'; +B\C::$d = 'e'; + +@$a = 1; + +$a = []; +foreach ($a as $b) + $c = 'd'; + +$var = $var2; +list ($a, $b) = explode(',', $c); +$var1 ? $var2 = 0 : $var2 = 1; + +$obj->$classVar = $prefix.'-'.$type; + +$closureWithDefaultParamter = function(array $testArray=array()) {}; +?> + + + 10, + false => 0 + }, +]; + +$arrow_function = fn ($a = null) => $a; + +function ($html) { + $regEx = '/regexp/'; + + return preg_replace_callback($regEx, function ($matches) { + [$all] = $matches; + return $all; + }, $html); +}; + + +function () { + $a = false; + + some_label: + + $b = getB(); +}; + +?> + + +// Issue PHPCSStandards/PHP_CodeSniffer#537. + + + + + + + + + + + + +field = $result; +$filtered_results->$field = $result; +$filtered_results->$row->field = $result; +$filtered_results->$row->$field = $result; + +$filtered_results[ $i ]->field = $result; +$filtered_results[ $i ]->$field = $result; +$filtered_results[ $i ]->$row->field = $result; +$filtered_results[ $i ]->$row->$field = $result; +$filtered_results[ $i ]->$row[0]->field = $result; +$filtered_results[ $i ]->$row[$j]->$field = $result; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.2.inc new file mode 100644 index 000000000..3befd507a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.2.inc @@ -0,0 +1,7 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowMultipleAssignments sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowMultipleAssignmentsSniff + */ +final class DisallowMultipleAssignmentsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the test file to process. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowMultipleAssignmentsUnitTest.1.inc': + return [ + 4 => 1, + 5 => 2, + 7 => 1, + 9 => 1, + 12 => 1, + 14 => 1, + 15 => 1, + 79 => 1, + 85 => 1, + ]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc new file mode 100644 index 000000000..56802e37a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc @@ -0,0 +1,58 @@ +children); $i++) { +} + + + +for ($i = 0; $i < sizeof($array); $i++) { +} + +$num = sizeof($array); + +while ($i < sizeof($array)) { +} + +do { +} while ($i < sizeof($array)); + +for ($i = 0; $i < sizeof($this->children); $i++) { +} + + + + +for ($i = 0; $i < strlen($string); $i++) { +} + +$num = strlen($string); + +while ($i < strlen($string)) { +} + +do { +} while ($i < strlen($string)); + +for ($i = 0; $i < strlen($this->string); $i++) { +} + +for ($i = sizeof($array); $i > 0; $i--) { +} + +do { + echo $a->count; + $a->count--; +} while($a->count); + +for ($i = 0; $i < $a->count; $i++) {} +for ($i = 0; $i < $a?->count; $i++) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js new file mode 100644 index 000000000..8f7f7b94f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js @@ -0,0 +1,13 @@ +for (var i = 0; i < permissions.length; i++) { + // Code here. +} + +var permLen = permissions.length; +for (var length = 0; i < permLen; i++) { + // Code here. +} + +var myArray = [1, 2, 3, 4]; +for (var i = myArray.length; i >= 0; i--) { + var x = i; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php new file mode 100644 index 000000000..3f923ad6b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php @@ -0,0 +1,77 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DisallowSizeFunctionsInLoops sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowSizeFunctionsInLoopsSniff + */ +final class DisallowSizeFunctionsInLoopsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'DisallowSizeFunctionsInLoopsUnitTest.inc': + return [ + 2 => 1, + 7 => 1, + 11 => 1, + 13 => 1, + 18 => 1, + 23 => 1, + 27 => 1, + 29 => 1, + 35 => 1, + 40 => 1, + 44 => 1, + 46 => 1, + ]; + + case 'DisallowSizeFunctionsInLoopsUnitTest.js': + return [1 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc new file mode 100644 index 000000000..3c875d098 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc @@ -0,0 +1,7 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DiscouragedFunctions sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DiscouragedFunctionsSniff + */ +final class DiscouragedFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 3 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc new file mode 100644 index 000000000..015468357 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.1.inc @@ -0,0 +1,275 @@ + + + +<?php echo $title ?> + + + + + hello + + + + + + + + + + + + + + + + + + + + + +section as $section) { + ?> + + + + + + section as $section) { + ?> +
    + + + + + + + + +?> + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + +<?php echo $title; ?> + + + + + hello + + + + + + + + + + + + + + + + + + + +section as $section) { + ?> +
    + + + + + section as $section) { + ?> +
    + + + + + + + + + + + + +?> + + + + + + + + + + + + + + + + + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.15.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.15.inc new file mode 100644 index 000000000..d8f051277 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.15.inc @@ -0,0 +1,9 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.16.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.16.inc new file mode 100644 index 000000000..754c241b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.16.inc @@ -0,0 +1,8 @@ + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.17.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.17.inc new file mode 100644 index 000000000..71de17bfb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.17.inc @@ -0,0 +1,8 @@ + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc new file mode 100644 index 000000000..3d61d4859 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc @@ -0,0 +1,15 @@ + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc.fixed new file mode 100644 index 000000000..8c906d40c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.18.inc.fixed @@ -0,0 +1,13 @@ + + +
    + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc new file mode 100644 index 000000000..34db64d60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc @@ -0,0 +1,17 @@ + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc.fixed new file mode 100644 index 000000000..b1738db57 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.19.inc.fixed @@ -0,0 +1,15 @@ + + +
    + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc new file mode 100644 index 000000000..755fd355b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc @@ -0,0 +1,7 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc.fixed new file mode 100644 index 000000000..e9073da91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.2.inc.fixed @@ -0,0 +1,7 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc new file mode 100644 index 000000000..28cdbdaf7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc @@ -0,0 +1,15 @@ + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc.fixed new file mode 100644 index 000000000..fcc24a278 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.20.inc.fixed @@ -0,0 +1,16 @@ + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc new file mode 100644 index 000000000..1da67a2ea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc @@ -0,0 +1,15 @@ + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc.fixed new file mode 100644 index 000000000..d7487b507 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.21.inc.fixed @@ -0,0 +1,16 @@ + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.22.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.22.inc new file mode 100644 index 000000000..5196a3b45 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.22.inc @@ -0,0 +1,30 @@ +
    Inline HTML with indent to demonstrate the bug in the indent calculation.
    + + + + + + + + +Inline HTML with indent to demonstrate the bug in the indent calculation.
    + + + + + + + + + + + +
    + + +
    +

    Some more content after the last PHP tag block.

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.24.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.24.inc new file mode 100644 index 000000000..dc1749c33 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.24.inc @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + +<?= $title ?> + + + + + hello + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +// Safeguard fixing when there is no whitespace between the close tag and the contents. + + + + + + + + + +<?= $title; ?> + + + + + hello + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Safeguard fixing when there is no whitespace between the close tag and the contents. + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.4.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.4.inc.fixed new file mode 100644 index 000000000..b7985cc50 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.4.inc.fixed @@ -0,0 +1,7 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.5.inc new file mode 100644 index 000000000..f4d8d8a0c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.5.inc @@ -0,0 +1,48 @@ + + + + + + + +
    + + + + + + + +
    + + + + + + + + + + + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EmbeddedPhp sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\EmbeddedPhpSniff + */ +final class EmbeddedPhpUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'EmbeddedPhpUnitTest.1.inc': + return [ + 7 => 1, + 12 => 1, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 3, + 24 => 1, + 26 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 34 => 1, + 36 => 1, + 40 => 1, + 41 => 1, + 44 => 1, + 45 => 1, + 49 => 1, + 59 => 1, + 63 => 1, + 93 => 1, + 94 => 2, + 100 => 1, + 102 => 1, + 112 => 1, + 113 => 1, + 116 => 1, + 117 => 1, + 120 => 1, + 121 => 1, + 128 => 1, + 129 => 1, + 132 => 1, + 134 => 1, + 136 => 1, + 138 => 1, + 142 => 1, + 145 => 1, + 151 => 1, + 158 => 1, + 165 => 1, + 169 => 1, + 175 => 1, + 176 => 2, + 178 => 1, + 179 => 1, + 180 => 2, + 181 => 1, + 189 => 1, + 212 => 1, + 214 => 2, + 219 => 1, + 223 => 1, + 225 => 1, + 226 => 1, + 227 => 2, + 228 => 1, + 235 => 1, + 241 => 1, + 248 => 1, + 253 => 1, + 258 => 1, + 263 => 1, + 264 => 1, + 270 => 1, + ]; + + case 'EmbeddedPhpUnitTest.2.inc': + case 'EmbeddedPhpUnitTest.4.inc': + return [ + 5 => 2, + 6 => 2, + 7 => 2, + ]; + + case 'EmbeddedPhpUnitTest.3.inc': + return [ + 10 => 1, + 15 => 1, + 21 => 1, + 22 => 2, + 23 => 1, + 24 => 1, + 25 => 3, + 28 => 1, + 29 => 1, + 30 => 1, + 33 => 1, + 35 => 1, + 39 => 1, + 40 => 1, + 43 => 1, + 44 => 1, + 48 => 1, + 53 => 1, + 55 => 1, + 61 => 1, + 62 => 1, + 65 => 2, + 66 => 2, + 69 => 1, + 70 => 1, + 75 => 1, + 82 => 1, + 89 => 1, + 93 => 1, + 98 => 2, + 99 => 1, + 103 => 2, + 105 => 1, + 111 => 1, + 112 => 2, + 114 => 1, + 115 => 1, + 116 => 2, + 117 => 1, + ]; + + case 'EmbeddedPhpUnitTest.5.inc': + return [ + 16 => 1, + 18 => 1, + 25 => 1, + 26 => 1, + 29 => 1, + 31 => 1, + 33 => 1, + 35 => 1, + 39 => 1, + 42 => 1, + ]; + + case 'EmbeddedPhpUnitTest.12.inc': + case 'EmbeddedPhpUnitTest.13.inc': + return [ + 10 => 1, + 12 => 1, + ]; + + case 'EmbeddedPhpUnitTest.18.inc': + return [11 => 1]; + + case 'EmbeddedPhpUnitTest.19.inc': + return [13 => 1]; + + case 'EmbeddedPhpUnitTest.20.inc': + case 'EmbeddedPhpUnitTest.21.inc': + return [12 => 2]; + + case 'EmbeddedPhpUnitTest.22.inc': + return [ + 14 => 1, + 22 => 2, + ]; + + case 'EmbeddedPhpUnitTest.24.inc': + $shortOpenTagDirective = (bool) ini_get('short_open_tag'); + if ($shortOpenTagDirective === true) { + return [ + 18 => 1, + 20 => 1, + ]; + } + return []; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc new file mode 100644 index 000000000..ee4c73e5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.inc @@ -0,0 +1,5 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php new file mode 100644 index 000000000..db0af7f04 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/EvalUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the Eval sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\EvalSniff + */ +final class EvalUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 2 => 1, + 4 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc new file mode 100644 index 000000000..4b2a21094 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc @@ -0,0 +1,13 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php new file mode 100644 index 000000000..c0c79baa6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php @@ -0,0 +1,56 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the GlobalKeyword sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\GlobalKeywordSniff + */ +final class GlobalKeywordUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 8 => 1, + 9 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.1.inc new file mode 100644 index 000000000..d1863c076 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.1.inc @@ -0,0 +1,12 @@ +foo. +Now, I am printing some {$foo->bar[1]}. +This should not print a capital 'A': \x41 +EOT; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.2.inc new file mode 100644 index 000000000..eb0062f08 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.2.inc @@ -0,0 +1,17 @@ + 'a' +<<<<<<< HEAD + 'b' => 'b' +======= + 'c' => 'c' +>>>>>>> master + ); + } diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php new file mode 100644 index 000000000..5d78d8938 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/HeredocUnitTest.php @@ -0,0 +1,64 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the Heredoc sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\HeredocSniff + */ +final class HeredocUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'HeredocUnitTest.1.inc': + return [ + 2 => 1, + 8 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc new file mode 100644 index 000000000..d16c7f2eb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the InnerFunctions sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\InnerFunctionsSniff + */ +final class InnerFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 46 => 1, + 55 => 1, + 83 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc new file mode 100644 index 000000000..702b13de0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc @@ -0,0 +1,50 @@ +Count(); +$count = $object::Count(); +$count = $object->count(); +$count = $object::count(); +class MyClass { + public function Count() {} +} + +function &Sort() { + +} + +$connection = new Db\Adapter\Pdo\Mysql($config); + +namespace Strtolower\Silly; + +use function strToUpper as somethingElse; +use function MyClass\WordsToUpper as UCWords; // Intentional redeclared function error. +use function strToUpper\NotTheFunction; + +class ArrayUnique {} + +$sillyComments = strToLower /*comment*/ ($string); + +$callToGlobalFunction = \STR_REPEAT($a, 2); +$callToGlobalFunction = \ /*comment*/ str_Repeat($a, 2); + +$callToNamespacedFunction = MyNamespace /* phpcs:ignore Standard */ \STR_REPEAT($a, 2); +$callToNamespacedFunction = namespace\STR_REPEAT($a, 2); // Could potentially be false negative. + +$filePath = new \File($path); + +$count = $object?->Count(); + +class AttributesShouldBeIgnored +{ + #[Putenv('FOO', 'foo')] + public function foo(): void + {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed new file mode 100644 index 000000000..281425c59 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.inc.fixed @@ -0,0 +1,50 @@ +Count(); +$count = $object::Count(); +$count = $object->count(); +$count = $object::count(); +class MyClass { + public function Count() {} +} + +function &Sort() { + +} + +$connection = new Db\Adapter\Pdo\Mysql($config); + +namespace Strtolower\Silly; + +use function strtoupper as somethingElse; +use function MyClass\WordsToUpper as UCWords; // Intentional redeclared function error. +use function strToUpper\NotTheFunction; + +class ArrayUnique {} + +$sillyComments = strtolower /*comment*/ ($string); + +$callToGlobalFunction = \str_repeat($a, 2); +$callToGlobalFunction = \ /*comment*/ str_repeat($a, 2); + +$callToNamespacedFunction = MyNamespace /* phpcs:ignore Standard */ \STR_REPEAT($a, 2); +$callToNamespacedFunction = namespace\STR_REPEAT($a, 2); // Could potentially be false negative. + +$filePath = new \File($path); + +$count = $object?->Count(); + +class AttributesShouldBeIgnored +{ + #[Putenv('FOO', 'foo')] + public function foo(): void + {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php new file mode 100644 index 000000000..5feb363f6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LowercasePHPFunctions sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\LowercasePHPFunctionsSniff + */ +final class LowercasePHPFunctionsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 27 => 1, + 33 => 1, + 35 => 1, + 36 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc new file mode 100644 index 000000000..4b1d1ca65 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.1.inc @@ -0,0 +1,420 @@ +{$action . 'JsonAction'}(); +} + +switch (true) { + case 1: + return foo( + function () { + $foo = $bar; // when this is removed it works ok + return false; // from here on it reports unreachable + } + ); +} + +for($i=0,$j=50; $i<100; $i++) { + while($j--) { + if($j==17) { + goto end; + echo 'unreachable'; + } + } +} + +switch ($var) { + case '1': + goto end; + echo 'hi'; + + case '2': + case '3': + if ($something === true) { + goto end; + echo 'hi'; + } + break; + default: + goto end; + + if ($something === true) { + goto end; + echo 'hi'; + } +} + +end: +echo 'j hit 17'; + +// Issue 2512. +class TestAlternativeControlStructures { + + public function alternative_switch_in_function( $var ) { + + switch ( $var ) : + case 'value1': + do_something(); + break; + + default: + case 'value2': + do_something_else(); + break; + endswitch; + } + + public function various_alternative_control_structures() { + $_while = 1; + + for ( $a = 0; $a++ < 1; ) : + foreach ( [ 1 ] as $b ) : + while ( $_while-- ) : + if ( 1 ) : + switch ( 1 ) : + default: + echo 'yay, we made it!'; + break; + endswitch; + endif; + endwhile; + endforeach; + endfor; + } +} + +$var_after_class_in_global_space = 1; +do_something_else(); + +// These are parse errors, but that's not the concern of the sniff. +function parseError1() { + defined('FOO') or return 'foo'; + echo 'unreachable'; +} + +function parseError2() { + defined('FOO') || continue; + echo 'unreachable'; +} + +// All logical operators are allowed with inline expressions (but this was not correctly handled by the sniff). +function exitExpressionsWithLogicalOperators() { + $condition = false; + $condition || exit(); + $condition or die(); + + $condition = true; + $condition && die(); + $condition and exit; + + $condition xor die(); + + echo 'still executable as exit, in all of the above cases, is used as part of an expression'; +} + +// Inline expressions are allowed in ternaries. +function exitExpressionsInTernary() { + $value = $myValue ? $myValue : exit(); + $value = $myValue ?: exit(); + $value = $var == 'foo' ? 'bar' : die( 'world' ); + + $value = (!$myValue ) ? exit() : $myValue; + $value = $var != 'foo' ? die( 'world' ) : 'bar'; + + echo 'still executable'; +} + +// Inline expressions are allowed with null coalesce and null coalesce equals. +function exitExpressionsWithNullCoalesce() { + $value = $nullableValue ?? exit(); + $value ??= die(); + echo 'still executable'; +} + +// Inline expressions are allowed in arrow functions. +function exitExpressionsInArrowFunction() { + $callable = fn() => die(); + echo 'still executable'; +} + +// PHP 8.0+: throw expressions which don't stop execution. +function nonStoppingThrowExpressions() { + $callable = fn() => throw new Exception(); + + $value = $myValue ? 'something' : throw new Exception(); + $value = $myValue ?: throw new Exception(); + $value = $myValue ? throw new Exception() : 'something'; + + $value = $nullableValue ?? throw new Exception(); + $value ??= throw new Exception(); + + $condition && throw new Exception(); + $condition || throw new Exception(); + $condition and throw new Exception(); + $condition or throw new Exception(); + + echo 'still executable as throw, in all of the above cases, is used as part of an expression'; + + throw new Exception(); + echo 'non-executable'; +} + +// PHP 8.0+: throw expressions which do stop execution. +function executionStoppingThrowExpressionsA() { + $condition xor throw new Exception(); + echo 'non-executable'; +} + +function executionStoppingThrowExpressionsB() { + throw $userIsAuthorized ? new ForbiddenException() : new UnauthorizedException(); + echo 'non-executable'; +} + +function executionStoppingThrowExpressionsC() { + throw $condition1 && $condition2 ? new Exception1() : new Exception2(); + echo 'non-executable'; +} + +function executionStoppingThrowExpressionsD() { + throw $exception ??= new Exception(); + echo 'non-executable'; +} + +function executionStoppingThrowExpressionsE() { + throw $maybeNullException ?? new Exception(); + echo 'non-executable'; +} + +function returnNotRequiredIgnoreCommentsA() +{ + if ($something === TRUE) { + return /*comment*/; + } + + echo 'foo'; + return /*comment*/; +} + +function returnNotRequiredIgnoreCommentsB() +{ + echo 'foo'; + return; + /*comment*/ +} + +$closure = function () +{ + echo 'foo'; + return; // This return should be flagged as not required. +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc new file mode 100644 index 000000000..9b7a22bcc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.2.inc @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
    non-executable
    + + + + + + + + +
    non-executable
    + + + + + + + + +
    non-executable
    + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.4.inc new file mode 100644 index 000000000..189466b4d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.4.inc @@ -0,0 +1,6 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\PHP; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the NonExecutableCode sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\NonExecutableCodeSniff + */ +final class NonExecutableCodeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getWarningList($testFile='') + { + switch ($testFile) { + case 'NonExecutableCodeUnitTest.1.inc': + return [ + 5 => 1, + 11 => 1, + 17 => 1, + 18 => 1, + 19 => 2, + 28 => 1, + 32 => 1, + 33 => 2, + 34 => 2, + 42 => 1, + 45 => 1, + 54 => 1, + 58 => 1, + 73 => 1, + 83 => 1, + 95 => 1, + 105 => 1, + 123 => 1, + 147 => 1, + 150 => 1, + 153 => 1, + 166 => 1, + 180 => 1, + 232 => 1, + 240 => 1, + 246 => 1, + 252 => 1, + 253 => 1, + 254 => 2, + 303 => 1, + 308 => 1, + 370 => 1, + 376 => 1, + 381 => 1, + 386 => 1, + 391 => 1, + 396 => 1, + 406 => 1, + 412 => 1, + 419 => 1, + ]; + + case 'NonExecutableCodeUnitTest.2.inc': + return [ + 7 => 1, + 8 => 1, + 9 => 1, + 10 => 2, + 14 => 1, + 54 => 2, + 65 => 2, + 69 => 2, + 70 => 2, + 71 => 2, + ]; + + case 'NonExecutableCodeUnitTest.3.inc': + return [ + 27 => 1, + 36 => 1, + 45 => 1, + 54 => 1, + 62 => 1, + ]; + default: + return []; + }//end switch + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc new file mode 100644 index 000000000..6df12cca4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc @@ -0,0 +1,72 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MemberVarScope sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope\MemberVarScopeSniff + */ +final class MemberVarScopeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 25 => 1, + 29 => 1, + 33 => 1, + 39 => 1, + 41 => 1, + 66 => 2, + 67 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + // Warning from getMemberProperties() about parse error. + return [71 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc new file mode 100644 index 000000000..3cc617d75 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.inc @@ -0,0 +1,57 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MethodScope sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope\MethodScopeSniff + */ +final class MethodScopeUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 6 => 1, + 30 => 1, + 39 => 1, + 46 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc new file mode 100644 index 000000000..dd6530e80 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc @@ -0,0 +1,127 @@ +func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + public static function /* */ func1() + { + return $this->setValue($result); + } + + public static function + func1() + { + return $this->setValue($result); + } + + public function func1() + { + $value = 'hello'; + $newValue = array($this->func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + function func1() + { + $value = 'hello'; + $newValue = array($this->func2()); + $result = $this->getValue($value); + return $this->setValue($result); + } + + public static function func1() { + return function() { + echo $this->name; + }; + } + + private static function func1(array $data) + { + return new class() + { + private $data; + + public function __construct(array $data) + { + $this->data = $data; + } + }; + } + + public function getAnonymousClass() { + return new class() { + public static function something() { + $this->doSomething(); + } + }; + } +} + +trait MyTrait { + public static function myFunc() { + $this->doSomething(); + } +} + +$b = new class() +{ + public static function myFunc() { + $this->doSomething(); + } + + public static function other() { + return fn () => $this->name; + } + + public static function anonClassUseThis() { + return new class($this) { + public function __construct($class) { + } + }; + } + + public static function anonClassAnotherThis() { + return new class() { + public function __construct() { + $this->id = 1; + } + }; + } + + public static function anonClassNestedUseThis() { + return new class(new class($this) {}) { + }; + } + + public static function anonClassNestedAnotherThis() { + return new class(new class() { + public function __construct() { + $this->id = 1; + } + }) { + }; + } + + public static function thisMustBeLowercase() { + $This = 'hey'; + + return $This; + } +} + +enum MyEnum { + private function notStatic () { + $this->doSomething(); + } + + public static function myFunc() { + $this->doSomething(); + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php new file mode 100644 index 000000000..543b56973 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Scope; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the StaticThisUsage sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope\StaticThisUsageSniff + */ +final class StaticThisUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 7 => 1, + 8 => 1, + 9 => 1, + 14 => 1, + 20 => 1, + 41 => 1, + 61 => 1, + 69 => 1, + 76 => 1, + 80 => 1, + 84 => 1, + 99 => 1, + 125 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc new file mode 100644 index 000000000..3bf4186e0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc @@ -0,0 +1,49 @@ +add_help_tab( array( +'id' => <<', +) ); + +// phpcs:set Squiz.Strings.ConcatenationSpacing spacing 1 + +$string = 'Hello'.$there.'. How are'.$you.$going. "today $okay"; +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello'.$there; +$string = 'Hello'. $there; +$string = 'Hello' .$there; + +// phpcs:set Squiz.Strings.ConcatenationSpacing ignoreNewlines true +$y = '1' + . '2' + . '3'; + +$y = '1' . + '2' . + '3'; + +$y = '1' +. '2' +. '3'; + +$y = '1' + .'2'. + '3' + . '4'; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..b45f1a43a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc.fixed @@ -0,0 +1,47 @@ +add_help_tab( array( +'id' => <<', +) ); + +// phpcs:set Squiz.Strings.ConcatenationSpacing spacing 1 + +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay"; +$string = 'Hello' . $there; +$string = 'Hello' . $there; +$string = 'Hello' . $there; + +// phpcs:set Squiz.Strings.ConcatenationSpacing ignoreNewlines true +$y = '1' + . '2' + . '3'; + +$y = '1' . + '2' . + '3'; + +$y = '1' +. '2' +. '3'; + +$y = '1' + . '2' . + '3' + . '4'; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php new file mode 100644 index 000000000..e59da3c6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ConcatenationSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\ConcatenationSpacingSniff + */ +final class ConcatenationSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 5, + 5 => 1, + 6 => 1, + 9 => 1, + 10 => 1, + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 16 => 5, + 22 => 1, + 27 => 5, + 29 => 1, + 30 => 1, + 31 => 1, + 47 => 2, + 49 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc new file mode 100644 index 000000000..c8cc63836 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc @@ -0,0 +1,37 @@ +"; +$string = "Value: $var[test]"; +$string = "\0"; +$string = "\$var"; + +$x = "bar = '$z', +baz = '" . $a . "'...$x"; + +$string = "Hello +there"; +$string = 'Hello +there'; + +$string = "\123 \234"."\u123"."\e"; + +echo "window.location = \"".$url."\";\n"; +echo "" + +$string = "Hello + there"; + +function test() { + echo "It Worked'; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed new file mode 100644 index 000000000..97309194e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc.fixed @@ -0,0 +1,37 @@ +"; +$string = "Value: $var[test]"; +$string = "\0"; +$string = '$var'; + +$x = "bar = '$z', +baz = '" . $a . "'...$x"; + +$string = 'Hello +there'; +$string = 'Hello +there'; + +$string = "\123 \234"."\u123"."\e"; + +echo 'window.location = "'.$url."\";\n"; +echo '' + +$string = 'Hello + there'; + +function test() { + echo "It Worked'; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php new file mode 100644 index 000000000..df50beee1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.php @@ -0,0 +1,67 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the DoubleQuoteUsage sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\DoubleQuoteUsageSniff + */ +final class DoubleQuoteUsageUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 5 => 1, + 6 => 1, + 8 => 2, + 14 => 1, + 15 => 1, + 17 => 1, + 19 => 1, + 20 => 1, + 22 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc new file mode 100644 index 000000000..9e0391dad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc @@ -0,0 +1,13 @@ +returndate == 0) ? 'Not returned' : date('d/m/Y', $loan_device->returndate); +?> +

    +

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed new file mode 100644 index 000000000..37c7d24c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.inc.fixed @@ -0,0 +1,13 @@ +returndate == 0) ? 'Not returned' : date('d/m/Y', $loan_device->returndate); +?> +

    +

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php new file mode 100644 index 000000000..dd8ead06a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\Strings; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the EchoedStrings sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\EchoedStringsSniff + */ +final class EchoedStringsUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 9 => 1, + 13 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc new file mode 100644 index 000000000..fa65112fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.inc @@ -0,0 +1,9 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the CastSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\CastSpacingSniff + */ +final class CastSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 9 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc new file mode 100644 index 000000000..70abae434 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc @@ -0,0 +1,269 @@ + +
    + + + +
    + children as $child) { + // There should be no error after this + // foreach, because it is followed by a + // close PHP tag. + } + ?> +
    +children as $child) { + echo $child; + +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +foreach ( $blah as $var ) { + if ( $blah ) { + } +} + +if ( + $defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +$moo = 'blar'; +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; + + default: + $moo = 'moo'; + break; +} + +do { +} +while (true); + +try { + // Something +} catch (Exception $e) { + // Something +} + +try { + + // Something + +} catch (Exception $e) { + + // Something + +} + +if ($one) { +} +elseif ($two) { +} +// else if something +else if ($three) { +} // else do something +else { +} + +if ($one) { + +} + +do { + echo 'hi'; +} while ( $blah ); + +if ($one) { +} +// No blank line here. +if ($two) { +} + +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + + return $moo; +} + +try { + // Something +} +catch (Exception $e) { + // Something +} +finally { + // Something +} + +if ($foo) { + + + /** + * Comment + */ + function foo() { + // Code here + } + + + /** + * Comment + */ + class bar() { + + }//end class + + +} + +if (true) { // some comment goes here + + echo 'foo'; +} + +if (true) { echo 'foo'; + + echo 'foo'; +} + +if ($true) { + echo 'hi 2'; +}//end if +echo 'hi'; + +if ($true) { + echo 'hi 2'; +} // phpcs:enable Standard.Category.Sniff -- for reasons. +echo 'hi'; + +?> + + + + + + + 1, + 2 => 2, + +}; +echo $expr; + +if($true) { + + enum SomeEnum {} + +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..c64de25e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc.fixed @@ -0,0 +1,261 @@ + + + + + +
    + children as $child) { + // There should be no error after this + // foreach, because it is followed by a + // close PHP tag. + } + ?> +
    +children as $child) { + echo $child; +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +foreach ($blah as $var) { + if ($blah) { + } +} + +if ($defaultPageDesign === 0 + && $defaultCascade === TRUE + && $defaultChildDesign === 0 +) { + $settingsUpdated = FALSE; +} + +$moo = 'blar'; +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; + + default: + $moo = 'moo'; + break; +} + +do { +} +while (true); + +try { + // Something +} catch (Exception $e) { + // Something +} + +try { + // Something +} catch (Exception $e) { + // Something +} + +if ($one) { +} +elseif ($two) { +} +// else if something +else if ($three) { +} // else do something +else { +} + +if ($one) { +} + +do { + echo 'hi'; +} while ($blah); + +if ($one) { +} + +// No blank line here. +if ($two) { +} + +switch ($moo) +{ + case 'blar': + if ($moo === 'blar2') { + $moo = 'blar' + } + return $moo; +} + +try { + // Something +} +catch (Exception $e) { + // Something +} +finally { + // Something +} + +if ($foo) { + + + /** + * Comment + */ + function foo() { + // Code here + } + + + /** + * Comment + */ + class bar() { + + }//end class + + +} + +if (true) { // some comment goes here + echo 'foo'; +} + +if (true) { echo 'foo'; + + echo 'foo'; +} + +if ($true) { + echo 'hi 2'; +}//end if + +echo 'hi'; + +if ($true) { + echo 'hi 2'; +} // phpcs:enable Standard.Category.Sniff -- for reasons. + +echo 'hi'; + +?> + + + + + + 1, + 2 => 2, +}; + +echo $expr; + +if($true) { + + enum SomeEnum {} + +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js new file mode 100644 index 000000000..1c889a1c0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js @@ -0,0 +1,93 @@ + +if (something) { +} +for (i = 0; i < 10; i++) { +} + +while (true) { + for (i = 0; i < 10; i++) { + } + if (something) { + } + + do { + } while (true); + +} + +if (one) { +} else (two) { +} else if (three) { +} +if (one) { +} else (two) { +} else if (three) { +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // There are no spaces before break. + } + break; +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // Code here. + } +} + +for (i = 0; i < 10; i++) { + if (blah) { + } + break; +} + +while (true) { + for (i = 0; i < 10; i++) { + + if (something) { + } + + } + + do { + + alert(i); + } while (true); +} + +for ( i = 0; i < 10; i++ ) { + if ( blah ) { + } +} + +var x = { + a: function () { + if (blah) { + } + + }, +}; + +if (one) { +} +// else if something +else if (two) { +} // else do something +else { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed new file mode 100644 index 000000000..bb979bc8e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js.fixed @@ -0,0 +1,93 @@ + +if (something) { +} + +for (i = 0; i < 10; i++) { +} + +while (true) { + for (i = 0; i < 10; i++) { + } + + if (something) { + } + + do { + } while (true); +} + +if (one) { +} else (two) { +} else if (three) { +} + +if (one) { +} else (two) { +} else if (three) { +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // There are no spaces before break. + } + break; +} + +switch (blah) { + case 'one': + if (blah) { + // There are no spaces before break. + } + break; + + default: + if (blah) { + // Code here. + } +} + +for (i = 0; i < 10; i++) { + if (blah) { + } + + break; +} + +while (true) { + for (i = 0; i < 10; i++) { + if (something) { + } + } + + do { + alert(i); + } while (true); +} + +for (i = 0; i < 10; i++) { + if (blah) { + } +} + +var x = { + a: function () { + if (blah) { + } + + }, +}; + +if (one) { +} +// else if something +else if (two) { +} // else do something +else { +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php new file mode 100644 index 000000000..c5567cb72 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php @@ -0,0 +1,107 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ControlStructureSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ControlStructureSpacingSniff + */ +final class ControlStructureSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ControlStructureSpacingUnitTest.inc': + return [ + 3 => 1, + 5 => 1, + 8 => 1, + 15 => 1, + 23 => 1, + 74 => 1, + 79 => 1, + 82 => 1, + 83 => 1, + 87 => 1, + 103 => 1, + 113 => 2, + 114 => 2, + 118 => 1, + 150 => 1, + 153 => 1, + 154 => 1, + 157 => 1, + 170 => 1, + 176 => 2, + 179 => 1, + 189 => 1, + 225 => 1, + 237 => 1, + 242 => 1, + 246 => 1, + 248 => 1, + 257 => 3, + 261 => 1, + 262 => 1, + ]; + + case 'ControlStructureSpacingUnitTest.js': + return [ + 3 => 1, + 9 => 1, + 15 => 1, + 21 => 1, + 56 => 1, + 61 => 1, + 64 => 1, + 65 => 1, + 68 => 1, + 74 => 2, + 75 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc new file mode 100644 index 000000000..e831e257d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.inc @@ -0,0 +1,39 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionClosingBraceSpace sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\FunctionClosingBraceSpaceSniff + */ +final class FunctionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionClosingBraceSpaceUnitTest.inc': + return [ + 10 => 1, + 21 => 1, + 28 => 1, + 29 => 1, + 31 => 1, + 39 => 1, + ]; + + case 'FunctionClosingBraceSpaceUnitTest.js': + return [ + 13 => 1, + 25 => 1, + 32 => 1, + 53 => 1, + 59 => 1, + 67 => 1, + 84 => 1, + 128 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc new file mode 100644 index 000000000..fe2c903b1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc @@ -0,0 +1,54 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionOpeningBraceSpace sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\FunctionOpeningBraceSpaceSniff + */ +final class FunctionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionOpeningBraceSpaceUnitTest.inc': + return [ + 10 => 1, + 25 => 1, + 49 => 1, + ]; + + case 'FunctionOpeningBraceSpaceUnitTest.js': + return [ + 11 => 1, + 31 => 1, + 38 => 1, + 88 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc new file mode 100644 index 000000000..b03a0ed82 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc @@ -0,0 +1,584 @@ +setLogger(new class { + public function a(){} + private function b(){} + protected function c(){} +}); + +?> + +setLogger(new class { + + public function a(){} + + private function b(){} + + protected function c(){} + +}); + +?> + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the FunctionSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\FunctionSpacingSniff + */ +final class FunctionSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'FunctionSpacingUnitTest.1.inc': + return [ + 26 => 1, + 35 => 1, + 44 => 1, + 51 => 1, + 55 => 1, + 61 => 1, + 64 => 1, + 66 => 1, + 81 => 1, + 100 => 1, + 111 => 1, + 113 => 1, + 119 => 2, + 141 => 1, + 160 => 1, + 173 => 2, + 190 => 1, + 224 => 2, + 281 => 1, + 282 => 1, + 295 => 1, + 297 => 1, + 303 => 1, + 327 => 1, + 329 => 1, + 338 => 1, + 344 => 1, + 345 => 1, + 354 => 2, + 355 => 1, + 356 => 1, + 360 => 2, + 361 => 1, + 362 => 1, + 385 => 1, + 399 => 1, + 411 => 2, + 418 => 2, + 426 => 2, + 432 => 1, + 437 => 1, + 438 => 1, + 442 => 2, + 444 => 1, + 449 => 1, + 458 => 2, + 459 => 1, + 460 => 1, + 465 => 2, + 466 => 1, + 467 => 1, + 471 => 1, + 473 => 2, + 475 => 1, + 478 => 2, + 479 => 1, + 483 => 2, + 495 => 1, + 529 => 1, + 539 => 1, + 547 => 2, + 551 => 1, + 553 => 1, + 560 => 1, + 566 => 1, + 580 => 2, + 583 => 3, + ]; + + case 'FunctionSpacingUnitTest.2.inc': + return [2 => 1]; + + case 'FunctionSpacingUnitTest.3.inc': + return [7 => 1]; + + case 'FunctionSpacingUnitTest.5.inc': + return [5 => 1]; + + case 'FunctionSpacingUnitTest.6.inc': + return [10 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc new file mode 100644 index 000000000..e8f2edad3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc @@ -0,0 +1,43 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LanguageConstructSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\LanguageConstructSpacingSniff + */ +final class LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 7 => 1, + 11 => 1, + 15 => 1, + 19 => 1, + 23 => 1, + 27 => 1, + 31 => 1, + 34 => 1, + 35 => 1, + 39 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc new file mode 100644 index 000000000..c2f4ec7db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc @@ -0,0 +1,19 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the LogicalOperatorSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\LogicalOperatorSpacingSniff + */ +final class LogicalOperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 2, + 5 => 3, + 6 => 3, + 15 => 1, + 17 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc new file mode 100644 index 000000000..12b55176c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc @@ -0,0 +1,374 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; +} + +// Make sure the determination of whether a property is the first property or not is done correctly. +class ClassUsingSimpleTraits +{ + use HelloWorld; + + + /* comment */ + public $firstVar = array( 'a', 'b' ); + protected $secondVar = true; +} + +class ClassUsingComplexTraits +{ + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } + + + + public $firstVar = array( 'a', 'b' ); + + + /* comment */ + protected $secondVar = true; +} + +class Foo +{ + + + private function foo() + { + } + + + /* no error here because after function */ + private $bar = false; +} + +class CommentedOutCodeAtStartOfClass { + + /** + * Description. + * + * @var bool + */ + //public $commented_out_property = true; + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class CommentedOutCodeAtStartOfClassNoBlankLine { + + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class HasAttributes +{ + /** + * Short description of the member variable. + * + * @var array + */ + + #[ORM\Id]#[ORM\Column("integer")] + + private $id; + + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; + + #[SingleAttribute] + protected $propertySingle; + + #[FirstAttribute] + #[SecondAttribute] + protected $propertyDouble; + #[ThirdAttribute] + protected $propertyWithoutSpacing; +} + +enum SomeEnum +{ + // Enum cannot have properties + + case ONE = 'one'; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..d683eaadf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc.fixed @@ -0,0 +1,359 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; +} + +// Make sure the determination of whether a property is the first property or not is done correctly. +class ClassUsingSimpleTraits +{ + use HelloWorld; + + /* comment */ + public $firstVar = array( 'a', 'b' ); + + protected $secondVar = true; +} + +class ClassUsingComplexTraits +{ + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } + + public $firstVar = array( 'a', 'b' ); + + /* comment */ + protected $secondVar = true; +} + +class Foo +{ + + + private function foo() + { + } + + + /* no error here because after function */ + private $bar = false; +} + +class CommentedOutCodeAtStartOfClass { + + /** + * Description. + * + * @var bool + */ + //public $commented_out_property = true; + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class CommentedOutCodeAtStartOfClassNoBlankLine { + + // phpcs:disable Stnd.Cat.Sniff -- For reasons. + + /** + * Description. + * + * @var bool + */ + public $property = true; +} + +class HasAttributes +{ + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\Id]#[ORM\Column("integer")] + private $id; + + /** + * Short description of the member variable. + * + * @var array + */ + #[ORM\GeneratedValue] + #[ORM\Column(ORM\Column::T_INTEGER)] + protected $height; + + #[SingleAttribute] + protected $propertySingle; + + #[FirstAttribute] + #[SecondAttribute] + protected $propertyDouble; + + #[ThirdAttribute] + protected $propertyWithoutSpacing; +} + +enum SomeEnum +{ + // Enum cannot have properties + + case ONE = 'one'; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php new file mode 100644 index 000000000..548ee3baa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php @@ -0,0 +1,90 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the MemberVarSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\MemberVarSpacingSniff + */ +final class MemberVarSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 4 => 1, + 7 => 1, + 20 => 1, + 30 => 1, + 35 => 1, + 44 => 1, + 50 => 1, + 73 => 1, + 86 => 1, + 106 => 1, + 115 => 1, + 150 => 1, + 160 => 1, + 165 => 1, + 177 => 1, + 186 => 1, + 200 => 1, + 209 => 1, + 211 => 1, + 224 => 1, + 229 => 1, + 241 => 1, + 246 => 1, + 252 => 1, + 254 => 1, + 261 => 1, + 275 => 1, + 276 => 1, + 288 => 1, + 292 => 1, + 333 => 1, + 342 => 1, + 346 => 1, + 353 => 1, + 357 => 1, + 366 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc new file mode 100644 index 000000000..67f8ee144 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc @@ -0,0 +1,52 @@ +testThis(); +$this-> testThis(); +$this -> testThis(); +$this-> /* comment here */testThis(); +$this/* comment here */ -> testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +$this->testThis(); +$this-> testThis(); +$this -> testThis(); +$this->/* comment here */testThis(); +$this/* comment here */ -> testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +thisObject::testThis(); +thisObject:: testThis(); +thisObject :: testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */ :: testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +thisObject::testThis(); +thisObject:: testThis(); +thisObject :: testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */ :: testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +$this?->testThis(); +$this?-> testThis(); +$this ?-> testThis(); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..730b8e4a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc.fixed @@ -0,0 +1,48 @@ +testThis(); +$this->testThis(); +$this->testThis(); +$this->/* comment here */testThis(); +$this/* comment here */->testThis(); +$this->testThis(); +$this->testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +$this->testThis(); +$this->testThis(); +$this->testThis(); +$this->/* comment here */testThis(); +$this/* comment here */->testThis(); +$this + ->testThis(); +$this-> + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +thisObject::testThis(); +thisObject::testThis(); +thisObject::testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */::testThis(); +thisObject::testThis(); +thisObject::testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines true + +thisObject::testThis(); +thisObject::testThis(); +thisObject::testThis(); +thisObject::/* comment here */testThis(); +thisObject/* comment here */::testThis(); +thisObject + ::testThis(); +thisObject:: + testThis(); + +// phpcs:set Squiz.WhiteSpace.ObjectOperatorSpacing ignoreNewlines false + +$this?->testThis(); +$this?->testThis(); +$this?->testThis(); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php new file mode 100644 index 000000000..c1ef24a42 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php @@ -0,0 +1,73 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ObjectOperatorSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ObjectOperatorSpacingSniff + */ +final class ObjectOperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 4 => 2, + 5 => 1, + 6 => 2, + 8 => 1, + 9 => 1, + 15 => 1, + 16 => 2, + 18 => 2, + 27 => 1, + 28 => 2, + 30 => 2, + 32 => 1, + 33 => 1, + 39 => 1, + 40 => 2, + 42 => 2, + 51 => 1, + 52 => 2, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc new file mode 100644 index 000000000..29acf308a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc @@ -0,0 +1,510 @@ + $j && $k< $l && $m>= $n && $o<= $p && $q<> $r; + +$a ==$b && $c !=$d && $e ===$f && $g !==$h; +$i >$j && $k <$l && $m >=$n && $o <=$p && $q <>$r; + +function myFunction($variable=0, $var2='string') {} + +if (index > -1) { +} + +array_walk_recursive($array, function(&$item) use (&$something) { +}); + +$var = saveFile(&$model, &$foo); + +// This is all valid. +$boo = -$foo; +function foo($boo = -1) {} +$foo = array('boo' => -1); +$x = $test ? -1 : 1; +$y = $test ? 1 : -1; +$z = $test ?: false; + +$closureWithDefaultParameter = function (array $testArray=array()) {}; + +switch ($foo) { + case -1: + break; +} + +$y = 1 * -1; +$y = -1 * 1; +$y = -1 * $var; +$y = 10 / -2; +$y = -10 / 2; +$y = (-10 / 2); +$y = (-10 / $var); +$y = 10 + -2; +$y = -10 + 2; + +$a = $x?$y:$z; +$a = $x ? $y : $z; + +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == $b) { +} + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$y = array(&$x); +$y = [&$x]; +$y = array(&$a, &$b, &$c); +$y = [&$a, &$b, &$c]; +$y = array(&$a => 1, 2 => &$b, &$c); +$y = [&$a => 1, 2 => &$b, &$c]; + +if ($a <=> $b) { +} + +if ($a <=>$b) { +} + +$a |= $b; +$a **= $b; +$a ??= $b; + +$a = +1; + +function bar($boo = +1) {} + +$username = $_GET['user']??'nobody'; + +function foo(string $bar, array $baz, ?MyClass $object) : MyClass {} + +declare(strict_types=1); + +function foo($c = ((BAR)?10:100)) {} + +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; + +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; + +function foo(string $a = '', ?string $b = ''): ?string {} + +// Issue #1605. +$text = preg_replace_callback( + self::CHAR_REFS_REGEX, + [ 'Sanitizer', 'decodeCharReferencesCallback' ], + $text, /* limit */ -1, $count ); + +if (true || /* test */ -1 == $b) {} +$y = 10 + /* test */ -2; + +// Issue #1604. +Hooks::run( 'ParserOptionsRegister', [ + &self::$defaults, + &self::$inCacheKey, + &self::$lazyOptions, +] ); + +$x = $foo ? function (): int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) + // comment + : int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) use /* comment */ ($bar): int { + return 1; +} : $bar; + +$x = !$foo ? $bar : function (): int { + return 1; +}; + +$a = + // Comment. + [ + 'a', + 'b', + ]; + +$a = +// phpcs:ignore Standard.Category.Sniff -- for reasons. +[ + 'a', + 'b', +]; + +$foo = is_array($bar) ? array_map( + function () {}, + $bar + ) : $bar; + +function bar(): array {} + +if ($line{-1} === ':') { + $line = substr($line, 0, -1); +} + +$a = $a instanceof $b; +$a = $a instanceof $b; +$a = ($a)instanceof$b; + +fn&($x) => $x; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +$a = 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments true +yield -1; +echo -1; +$a = -1; +func(-1); +$a = [-1]; +return -1; +print -1; +$a &= -1; +switch ($a) { + case -1: +} +$a = $a ?? -1; +$a .= -1; +$a /= -1; +$a = [1 => -1]; +$a = $a == -1; +$a = $a >= -1; +$a = $a === -1; +$a = $a != -1; +$a = $a !== -1; +$a = $a <= -1; +$a = $a <=> -1; +$a = $a and -1; +$a = $a or -1; +$a = $a xor -1; +$a -= -1; +$a %= -1; +$a *= -1; +$a |= -1; +$a += -1; +$a = $a ** -1; +$a **= -1; +$a = $a << -1; +$a <<= -1; +$a = $a >> -1; +$a >>= -1; +$a = (string) -1; +$a = (array) -1; +$a = (bool) -1; +$a = (object) -1; +$a = (unset) -1; +$a = (float) -1; +$a = (int) -1; +$a ^= -1; +$a = [$a, -1]; +$a = $a[-1]; +$a = $a ? -1 : -1; + +yield - 1; +echo - 1; +$a = - 1; +func(- 1); +$a = [- 1]; +return - 1; +print - 1; +$a &= - 1; +switch ($a) { + case - 1: +} +$a = $a ?? - 1; +$a .= - 1; +$a /= - 1; +$a = [1 => - 1]; +$a = $a == - 1; +$a = $a >= - 1; +$a = $a === - 1; +$a = $a != - 1; +$a = $a !== - 1; +$a = $a <= - 1; +$a = $a <=> - 1; +$a = $a and - 1; +$a = $a or - 1; +$a = $a xor - 1; +$a -= - 1; +$a %= - 1; +$a *= - 1; +$a |= - 1; +$a += - 1; +$a = $a ** - 1; +$a **= - 1; +$a = $a << - 1; +$a <<= - 1; +$a = $a >> - 1; +$a >>= - 1; +$a = (string) - 1; +$a = (array) - 1; +$a = (bool) - 1; +$a = (object) - 1; +$a = (unset) - 1; +$a = (float) - 1; +$a = (int) - 1; +$a ^= - 1; +$a = [$a, - 1]; +$a = $a[- 1]; +$a = $a ? - 1 : - 1; + + +yield -$b; +echo -$b; +$a = -$b; +func(-$b); +$a = [-$b]; +return -$b; +print -$b; +$a &= -$b; +switch ($a) { + case -$b: +} +$a = $a ?? -$b; +$a .= -$b; +$a /= -$b; +$a = [1 => -$b]; +$a = $a == -$b; +$a = $a >= -$b; +$a = $a === -$b; +$a = $a != -$b; +$a = $a !== -$b; +$a = $a <= -$b; +$a = $a <=> -$b; +$a = $a and -$b; +$a = $a or -$b; +$a = $a xor -$b; +$a -= -$b; +$a %= -$b; +$a *= -$b; +$a |= -$b; +$a += -$b; +$a = $a ** -$b; +$a **= -$b; +$a = $a << -$b; +$a <<= -$b; +$a = $a >> -$b; +$a >>= -$b; +$a = (string) -$b; +$a = (array) -$b; +$a = (bool) -$b; +$a = (object) -$b; +$a = (unset) -$b; +$a = (float) -$b; +$a = (int) -$b; +$a ^= -$b; +$a = [$a, -$b]; +$a = $a[-$b]; +$a = $a ? -$b : -$b; + +yield - $b; +echo - $b; +$a = - $b; +func(- $b); +$a = [- $b]; +return - $b; +print - $b; +$a &= - $b; +switch ($a) { + case - $b: +} +$a = $a ?? - $b; +$a .= - $b; +$a /= - $b; +$a = [1 => - $b]; +$a = $a == - $b; +$a = $a >= - $b; +$a = $a === - $b; +$a = $a != - $b; +$a = $a !== - $b; +$a = $a <= - $b; +$a = $a <=> - $b; +$a = $a and - $b; +$a = $a or - $b; +$a = $a xor - $b; +$a -= - $b; +$a %= - $b; +$a *= - $b; +$a |= - $b; +$a += - $b; +$a = $a ** - $b; +$a **= - $b; +$a = $a << - $b; +$a <<= - $b; +$a = $a >> - $b; +$a >>= - $b; +$a = (string) - $b; +$a = (array) - $b; +$a = (bool) - $b; +$a = (object) - $b; +$a = (unset) - $b; +$a = (float) - $b; +$a = (int) - $b; +$a ^= - $b; +$a = [$a, - $b]; +$a = $a[- $b]; +$a = $a ? - $b : - $b; + +exit -1; + +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +$a = 'a '.-MY_CONSTANT; +$a = 'a '.-$b; +$a = 'a '.- MY_CONSTANT; +$a = 'a '.- $b; + +match ($a) { + 'a' => -1, + 'b', 'c', 'd' => -2, + default => -3, +}; + +$foo = $var + ? 10 + : true; + +// Safeguard that a non-fixable error is thrown when there is a new line before the operator, +// but the last non-whitespace token before the operator is a comment token. +$foo = $var // Comment + ? false /* Comment */ + : true; + +$foo = $var // phpcs: ignore Stnd.Cat.Sniff -- for reasons. + + + ? $something /** + * Don't ask, but someone might have a docblock between the lines. It's valid PHP after all. + */ + + + : true; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$foo = $var // Comment + ? false // Comment + : true; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed new file mode 100644 index 000000000..5c94e3658 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed @@ -0,0 +1,502 @@ + $j && $k < $l && $m >= $n && $o <= $p && $q <> $r; + +$a == $b && $c != $d && $e === $f && $g !== $h; +$i > $j && $k < $l && $m >= $n && $o <= $p && $q <> $r; + +function myFunction($variable=0, $var2='string') {} + +if (index > -1) { +} + +array_walk_recursive($array, function(&$item) use (&$something) { +}); + +$var = saveFile(&$model, &$foo); + +// This is all valid. +$boo = -$foo; +function foo($boo = -1) {} +$foo = array('boo' => -1); +$x = $test ? -1 : 1; +$y = $test ? 1 : -1; +$z = $test ?: false; + +$closureWithDefaultParameter = function (array $testArray=array()) {}; + +switch ($foo) { + case -1: + break; +} + +$y = 1 * -1; +$y = -1 * 1; +$y = -1 * $var; +$y = 10 / -2; +$y = -10 / 2; +$y = (-10 / 2); +$y = (-10 / $var); +$y = 10 + -2; +$y = -10 + 2; + +$a = $x ? $y : $z; +$a = $x ? $y : $z; + +$y = 1 + 2 - 3; + +$y = 1 + 2 - 3; + +$y = 1 + 2 - 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$y = 1 + + 2 + - 3; + +$y = 1 + + 2 - + 3; + +$y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == $b) { +} + +$var = array(-1); +$var = [-1]; +$var = [0, -1, -2]; + +$y = array(&$x); +$y = [&$x]; +$y = array(&$a, &$b, &$c); +$y = [&$a, &$b, &$c]; +$y = array(&$a => 1, 2 => &$b, &$c); +$y = [&$a => 1, 2 => &$b, &$c]; + +if ($a <=> $b) { +} + +if ($a <=> $b) { +} + +$a |= $b; +$a **= $b; +$a ??= $b; + +$a = +1; + +function bar($boo = +1) {} + +$username = $_GET['user'] ?? 'nobody'; + +function foo(string $bar, array $baz, ?MyClass $object) : MyClass {} + +declare(strict_types=1); + +function foo($c = ((BAR) ? 10 : 100)) {} + +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; +$res = $a ?: $b; + +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; +$res = $a ? : $b; + +function foo(string $a = '', ?string $b = ''): ?string {} + +// Issue #1605. +$text = preg_replace_callback( + self::CHAR_REFS_REGEX, + [ 'Sanitizer', 'decodeCharReferencesCallback' ], + $text, /* limit */ -1, $count ); + +if (true || /* test */ -1 == $b) {} +$y = 10 + /* test */ -2; + +// Issue #1604. +Hooks::run( 'ParserOptionsRegister', [ + &self::$defaults, + &self::$inCacheKey, + &self::$lazyOptions, +] ); + +$x = $foo ? function (): int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) + // comment + : int { + return 1; +} : $bar; + +$x = $foo ? function ($foo) use /* comment */ ($bar): int { + return 1; +} : $bar; + +$x = !$foo ? $bar : function (): int { + return 1; +}; + +$a = + // Comment. + [ + 'a', + 'b', + ]; + +$a = +// phpcs:ignore Standard.Category.Sniff -- for reasons. +[ + 'a', + 'b', +]; + +$foo = is_array($bar) ? array_map( + function () {}, + $bar + ) : $bar; + +function bar(): array {} + +if ($line{-1} === ':') { + $line = substr($line, 0, -1); +} + +$a = $a instanceof $b; +$a = $a instanceof $b; +$a = ($a) instanceof $b; + +fn&($x) => $x; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +$a = 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments true +yield -1; +echo -1; +$a = -1; +func(-1); +$a = [-1]; +return -1; +print -1; +$a &= -1; +switch ($a) { + case -1: +} +$a = $a ?? -1; +$a .= -1; +$a /= -1; +$a = [1 => -1]; +$a = $a == -1; +$a = $a >= -1; +$a = $a === -1; +$a = $a != -1; +$a = $a !== -1; +$a = $a <= -1; +$a = $a <=> -1; +$a = $a and -1; +$a = $a or -1; +$a = $a xor -1; +$a -= -1; +$a %= -1; +$a *= -1; +$a |= -1; +$a += -1; +$a = $a ** -1; +$a **= -1; +$a = $a << -1; +$a <<= -1; +$a = $a >> -1; +$a >>= -1; +$a = (string) -1; +$a = (array) -1; +$a = (bool) -1; +$a = (object) -1; +$a = (unset) -1; +$a = (float) -1; +$a = (int) -1; +$a ^= -1; +$a = [$a, -1]; +$a = $a[-1]; +$a = $a ? -1 : -1; + +yield - 1; +echo - 1; +$a = - 1; +func(- 1); +$a = [- 1]; +return - 1; +print - 1; +$a &= - 1; +switch ($a) { + case - 1: +} +$a = $a ?? - 1; +$a .= - 1; +$a /= - 1; +$a = [1 => - 1]; +$a = $a == - 1; +$a = $a >= - 1; +$a = $a === - 1; +$a = $a != - 1; +$a = $a !== - 1; +$a = $a <= - 1; +$a = $a <=> - 1; +$a = $a and - 1; +$a = $a or - 1; +$a = $a xor - 1; +$a -= - 1; +$a %= - 1; +$a *= - 1; +$a |= - 1; +$a += - 1; +$a = $a ** - 1; +$a **= - 1; +$a = $a << - 1; +$a <<= - 1; +$a = $a >> - 1; +$a >>= - 1; +$a = (string) - 1; +$a = (array) - 1; +$a = (bool) - 1; +$a = (object) - 1; +$a = (unset) - 1; +$a = (float) - 1; +$a = (int) - 1; +$a ^= - 1; +$a = [$a, - 1]; +$a = $a[- 1]; +$a = $a ? - 1 : - 1; + + +yield -$b; +echo -$b; +$a = -$b; +func(-$b); +$a = [-$b]; +return -$b; +print -$b; +$a &= -$b; +switch ($a) { + case -$b: +} +$a = $a ?? -$b; +$a .= -$b; +$a /= -$b; +$a = [1 => -$b]; +$a = $a == -$b; +$a = $a >= -$b; +$a = $a === -$b; +$a = $a != -$b; +$a = $a !== -$b; +$a = $a <= -$b; +$a = $a <=> -$b; +$a = $a and -$b; +$a = $a or -$b; +$a = $a xor -$b; +$a -= -$b; +$a %= -$b; +$a *= -$b; +$a |= -$b; +$a += -$b; +$a = $a ** -$b; +$a **= -$b; +$a = $a << -$b; +$a <<= -$b; +$a = $a >> -$b; +$a >>= -$b; +$a = (string) -$b; +$a = (array) -$b; +$a = (bool) -$b; +$a = (object) -$b; +$a = (unset) -$b; +$a = (float) -$b; +$a = (int) -$b; +$a ^= -$b; +$a = [$a, -$b]; +$a = $a[-$b]; +$a = $a ? -$b : -$b; + +yield - $b; +echo - $b; +$a = - $b; +func(- $b); +$a = [- $b]; +return - $b; +print - $b; +$a &= - $b; +switch ($a) { + case - $b: +} +$a = $a ?? - $b; +$a .= - $b; +$a /= - $b; +$a = [1 => - $b]; +$a = $a == - $b; +$a = $a >= - $b; +$a = $a === - $b; +$a = $a != - $b; +$a = $a !== - $b; +$a = $a <= - $b; +$a = $a <=> - $b; +$a = $a and - $b; +$a = $a or - $b; +$a = $a xor - $b; +$a -= - $b; +$a %= - $b; +$a *= - $b; +$a |= - $b; +$a += - $b; +$a = $a ** - $b; +$a **= - $b; +$a = $a << - $b; +$a <<= - $b; +$a = $a >> - $b; +$a >>= - $b; +$a = (string) - $b; +$a = (array) - $b; +$a = (bool) - $b; +$a = (object) - $b; +$a = (unset) - $b; +$a = (float) - $b; +$a = (int) - $b; +$a ^= - $b; +$a = [$a, - $b]; +$a = $a[- $b]; +$a = $a ? - $b : - $b; + +exit -1; + +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + +$a = 'a '.-MY_CONSTANT; +$a = 'a '.-$b; +$a = 'a '.- MY_CONSTANT; +$a = 'a '.- $b; + +match ($a) { + 'a' => -1, + 'b', 'c', 'd' => -2, + default => -3, +}; + +$foo = $var ? 10 : true; + +// Safeguard that a non-fixable error is thrown when there is a new line before the operator, +// but the last non-whitespace token before the operator is a comment token. +$foo = $var // Comment + ? false /* Comment */ + : true; + +$foo = $var // phpcs: ignore Stnd.Cat.Sniff -- for reasons. + + + ? $something /** + * Don't ask, but someone might have a docblock between the lines. It's valid PHP after all. + */ + + + : true; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +$foo = $var // Comment + ? false // Comment + : true; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.2.inc new file mode 100644 index 000000000..3a0dbac3e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.2.inc @@ -0,0 +1,3 @@ +> y; +x >>= y; +x = x >>> y; +x >>>= y; + +var foo = bar.map(baz=> baz.length); + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +a = 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments true diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed new file mode 100644 index 000000000..47c89302b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed @@ -0,0 +1,98 @@ + + +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; +result = 1 + 2; + +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; +result = 1 - 2; + +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; +result = 1 * 2; + +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; +result = 1 / 2; + +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = 1 % 2; +result = '100%'; + +result += 4; +result += 4; +result -= 4; +result -= 4; +result /= 4; +result /= 4; +result *= 4; +result *= 4; + +$.localScroll({offset: {top: -32}}); + +switch (result) { + case -1: + break; +} + +result = x ? y : z; +result = x ? y : z; + +if (something === true + ^ somethingElse === true +) { + return false; +} + +y = 1 + 2 - 3; + +y = 1 + 2 - 3; + +y = 1 + 2 - 3; + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines true +y = 1 + + 2 + - 3; + +y = 1 + + 2 - + 3; + +y = 1 ++ 2 +- 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreNewlines false + +if (true || -1 == b) { +} + +x = x << y; +x <<= y; +x = x >> y; +x >>= y; +x = x >>> y; +x >>>= y; + +var foo = bar.map(baz => baz.length); + +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments false +a = 3; +// phpcs:set Squiz.WhiteSpace.OperatorSpacing ignoreSpacingBeforeAssignments true diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php new file mode 100644 index 000000000..e34a2ec4a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php @@ -0,0 +1,180 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the OperatorSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\OperatorSpacingSniff + */ +final class OperatorSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'OperatorSpacingUnitTest.1.inc': + return [ + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 8 => 2, + 11 => 1, + 12 => 2, + 13 => 1, + 14 => 1, + 15 => 2, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 2, + 25 => 1, + 26 => 2, + 27 => 1, + 28 => 1, + 29 => 2, + 32 => 1, + 33 => 2, + 34 => 1, + 35 => 1, + 36 => 2, + 40 => 2, + 42 => 2, + 44 => 2, + 45 => 1, + 46 => 2, + 53 => 4, + 54 => 3, + 59 => 10, + 64 => 1, + 77 => 4, + 78 => 1, + 79 => 1, + 80 => 2, + 81 => 1, + 84 => 6, + 85 => 6, + 87 => 4, + 88 => 5, + 90 => 4, + 91 => 5, + 128 => 4, + 132 => 1, + 133 => 1, + 135 => 1, + 136 => 1, + 140 => 1, + 141 => 1, + 174 => 1, + 177 => 1, + 178 => 1, + 179 => 1, + 185 => 2, + 191 => 4, + 194 => 1, + 195 => 1, + 196 => 2, + 199 => 1, + 200 => 1, + 201 => 2, + 239 => 1, + 246 => 1, + 265 => 2, + 266 => 2, + 271 => 2, + 487 => 1, + 488 => 1, + 493 => 1, + 494 => 1, + 499 => 1, + 504 => 1, + ]; + + case 'OperatorSpacingUnitTest.js': + return [ + 4 => 1, + 5 => 2, + 6 => 1, + 7 => 1, + 8 => 2, + 11 => 1, + 12 => 2, + 13 => 1, + 14 => 1, + 15 => 2, + 18 => 1, + 19 => 2, + 20 => 1, + 21 => 1, + 22 => 2, + 25 => 1, + 26 => 2, + 27 => 1, + 28 => 1, + 29 => 2, + 32 => 1, + 33 => 2, + 34 => 1, + 35 => 1, + 36 => 2, + 40 => 2, + 42 => 2, + 44 => 2, + 45 => 1, + 46 => 2, + 55 => 4, + 65 => 1, + 66 => 1, + 68 => 1, + 69 => 1, + 73 => 1, + 74 => 1, + 100 => 1, + 103 => 2, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js new file mode 100644 index 000000000..15890b96a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js @@ -0,0 +1,40 @@ +var x = { + b: 'x', + xasd: x, + abc:x, + a: function () { + alert('thats right'); + x = (x?a:x); + }, + casdasd : 123123, + omgwtfbbq: { + a: 1, + b: 2 + } +}; + +id = id.replace(/row\/:/gi, ''); + +outer_loop: +for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break outer_loop; + } +} +alert('hi'); + +even_number: if ((i % 2) == 0) { + if (i == 12) + break even_number; +} + +switch (blah) { + case dfx.DOM_VK_LEFT: + this.caretLeft(shiftKey); + break; + default: + if (blah) { + } + break; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed new file mode 100644 index 000000000..f332878e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js.fixed @@ -0,0 +1,39 @@ +var x = { + b: 'x', + xasd: x, + abc: x, + a: function () { + alert('thats right'); + x = (x?a:x); + }, + casdasd: 123123, + omgwtfbbq: { + a: 1, + b: 2 + } +}; + +id = id.replace(/row\/:/gi, ''); + +outer_loop: for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break outer_loop; + } +} +alert('hi'); + +even_number: if ((i % 2) == 0) { + if (i == 12) + break even_number; +} + +switch (blah) { + case dfx.DOM_VK_LEFT: + this.caretLeft(shiftKey); + break; + default: + if (blah) { + } + break; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php new file mode 100644 index 000000000..5c20b0010 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php @@ -0,0 +1,60 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the PropertyLabel sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\PropertyLabelSpacingSniff + */ +final class PropertyLabelSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 2 => 1, + 4 => 1, + 9 => 2, + 10 => 1, + 12 => 1, + 18 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc new file mode 100644 index 000000000..ecae5c6d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc @@ -0,0 +1,134 @@ +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content']{0} === '#') +) { +} + +switch ($blah) { + case 'one': + echo 'one'; + break; + default: + echo 'another'; +} + +?> + +getRow()): ?> +

    + + + +
    + +

    o hai!

    + +
    + + + + + + + + + + + + $x + $y; + +$match = match ($test) { 1 => 'a', 2 => 'b' }; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' + }; + +?> + +
    + +
    + +{$property} =& new $class_name($this->db_index); + $this->modules[$module] =& $this->{$property}; +} + +foreach ($elements as $element) { + if ($something) { + // Do IF. + } else if ($somethingElse) { + // Do ELSE. + } +} + +if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content']{0} === '#') +) { +} + +switch ($blah) { + case 'one': + echo 'one'; + break; + default: + echo 'another'; +} + +?> + +getRow()): ?> +

    + + + +
    + +

    o hai!

    + +
    + + + + + + + + + + + + $x + $y; + +$match = match ($test) { 1 => 'a', 2 => 'b' +}; + +$match = match ($test) { + 1 => 'a', + 2 => 'b' +}; + +?> + +
    + +
    + + + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ScopeClosingBrace sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ScopeClosingBraceSniff + */ +final class ScopeClosingBraceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 11 => 1, + 13 => 1, + 24 => 1, + 80 => 1, + 102 => 1, + 111 => 1, + 116 => 1, + 122 => 1, + 130 => 1, + 134 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc new file mode 100644 index 000000000..1d3ccebc9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc @@ -0,0 +1,149 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; + + // Intentionally missing a semicolon for testing. + public + $varS, + $varT +} + +// Issue #3188 - static as return type. +public static function fCreate($attributes = []): static +{ + return static::factory()->create($attributes); +} + +public static function fCreate($attributes = []): ?static +{ + return static::factory()->create($attributes); +} + +// Also account for static used within union types. +public function staticLast($attributes = []): object|static {} +public function staticMiddle(): string|static|object {} +public function staticFirst(): static|object {} + +// Ensure that static as a scope keyword when preceeded by a colon which is not for a type declaration is still handled. +$callback = $cond ? get_fn_name() : static function ($a) { return $a * 10; }; + +class TypedProperties { + public + int $var; + + protected string $stringA, $stringB; + + private bool + $boolA, + $boolB; +} + +// PHP 8.0 constructor property promotion. +class ConstructorPropertyPromotionTest { + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + $normalParam, + ) {} +} + +class ConstructorPropertyPromotionWithTypesTest { + public function __construct(protected float|int $x, public?string &$y = 'test', private mixed $z) {} +} + +// PHP 8.1 readonly keywords. +class ReadonlyTest { + public readonly int $publicReadonlyProperty; + + protected readonly int $protectedReadonlyProperty; + + readonly protected int $protectedReadonlyProperty; + + readonly private int $privateReadonlyProperty; + + public function __construct(readonly protected float|int $x, public readonly?string &$y = 'test') {} +} + +// PHP 8.2 readonly classes. +readonly class ReadonlyClassTest {} +readonly class ReadonlyClassTest {} + +// PHP 8.3 readonly anonymous classes. +$anon = new readonly class {}; +$anon = new readonly class {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc.fixed new file mode 100644 index 000000000..d4e8a39e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.1.inc.fixed @@ -0,0 +1,143 @@ + 'a', 'b' => 'b' ), + $varQ = 'string', + $varR = 123; + + // Intentionally missing a semicolon for testing. + public + $varS, + $varT +} + +// Issue #3188 - static as return type. +public static function fCreate($attributes = []): static +{ + return static::factory()->create($attributes); +} + +public static function fCreate($attributes = []): ?static +{ + return static::factory()->create($attributes); +} + +// Also account for static used within union types. +public function staticLast($attributes = []): object|static {} +public function staticMiddle(): string|static|object {} +public function staticFirst(): static|object {} + +// Ensure that static as a scope keyword when preceeded by a colon which is not for a type declaration is still handled. +$callback = $cond ? get_fn_name() : static function ($a) { return $a * 10; }; + +class TypedProperties { + public int $var; + + protected string $stringA, $stringB; + + private bool + $boolA, + $boolB; +} + +// PHP 8.0 constructor property promotion. +class ConstructorPropertyPromotionTest { + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + $normalParam, + ) {} +} + +class ConstructorPropertyPromotionWithTypesTest { + public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {} +} + +// PHP 8.1 readonly keywords. +class ReadonlyTest { + public readonly int $publicReadonlyProperty; + + protected readonly int $protectedReadonlyProperty; + + readonly protected int $protectedReadonlyProperty; + + readonly private int $privateReadonlyProperty; + + public function __construct(readonly protected float|int $x, public readonly ?string &$y = 'test') {} +} + +// PHP 8.2 readonly classes. +readonly class ReadonlyClassTest {} +readonly class ReadonlyClassTest {} + +// PHP 8.3 readonly anonymous classes. +$anon = new readonly class {}; +$anon = new readonly class {}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.2.inc new file mode 100644 index 000000000..45cfb5343 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.2.inc @@ -0,0 +1,6 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ScopeKeywordSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ScopeKeywordSpacingSniff + */ +final class ScopeKeywordSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ScopeKeywordSpacingUnitTest.1.inc': + return [ + 7 => 2, + 8 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + 17 => 2, + 26 => 1, + 28 => 1, + 29 => 1, + 64 => 1, + 67 => 1, + 71 => 1, + 103 => 1, + 106 => 1, + 111 => 1, + 119 => 1, + 121 => 1, + 127 => 2, + 134 => 2, + 138 => 2, + 140 => 3, + 145 => 1, + 149 => 1, + ]; + + case 'ScopeKeywordSpacingUnitTest.3.inc': + return [6 => 1]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc new file mode 100644 index 000000000..60f87e5bc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc @@ -0,0 +1,42 @@ +testThis(); +$test = $this->testThis() ; +$test = $this->testThis() ; +for ($var = 1 ; $var < 10 ; $var++) { + echo $var ; +} +$test = $this->testThis() /* comment here */; +$test = $this->testThis() /* comment here */ ; + +$hello ='foo'; +; + +$sum = $a /* + $b */; +$sum = $a // + $b +; +$sum = $a /* + $b + + $c */ ; + +/* + * Test that the sniff does *not* throw incorrect errors for semicolons in + * "empty" parts of a `for` control structure. + */ +for ($i = 1; ; $i++) {} +for ( ; $ptr >= 0; $ptr-- ) {} +for ( ; ; ) {} + +// But it should when the semicolon in a `for` follows a comment (but shouldn't move the semicolon). +for ( /* Deliberately left empty. */ ; $ptr >= 0; $ptr-- ) {} +for ( $i = 1 ; /* Deliberately left empty. */ ; $i++ ) {} + +switch ($foo) { + case 'foo': + ; + break + ; +} + +// This is an empty statement and should be ignored. +if ($foo) { +; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed new file mode 100644 index 000000000..b4dc0f13e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc.fixed @@ -0,0 +1,41 @@ +testThis(); +$test = $this->testThis(); +$test = $this->testThis(); +for ($var = 1; $var < 10; $var++) { + echo $var; +} +$test = $this->testThis(); /* comment here */ +$test = $this->testThis(); /* comment here */ + +$hello ='foo'; +; + +$sum = $a; /* + $b */ +$sum = $a; // + $b + +$sum = $a; /* + $b + + $c */ + +/* + * Test that the sniff does *not* throw incorrect errors for semicolons in + * "empty" parts of a `for` control structure. + */ +for ($i = 1; ; $i++) {} +for ( ; $ptr >= 0; $ptr-- ) {} +for ( ; ; ) {} + +// But it should when the semicolon in a `for` follows a comment (but shouldn't move the semicolon). +for ( /* Deliberately left empty. */; $ptr >= 0; $ptr-- ) {} +for ( $i = 1; /* Deliberately left empty. */; $i++ ) {} + +switch ($foo) { + case 'foo': + ; + break; +} + +// This is an empty statement and should be ignored. +if ($foo) { +; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js new file mode 100644 index 000000000..3aafd6da9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js @@ -0,0 +1,25 @@ +var x = { + a: function () { + alert('thats right') ; + x = (x?a:x) ; + }, +} ; + +id = id.replace(/row\/:;/gi, ''); + +for (i=0 ; i<3 ; i++) { + for (j=0; j<5 ; j++) { + if (j==x) + break ; + } +} +alert('hi'); +; + +var sum = a /* + b */; + +var sum = a // +b +; + +var sum = a /* +b + + c */ ; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed new file mode 100644 index 000000000..a547144de --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js.fixed @@ -0,0 +1,25 @@ +var x = { + a: function () { + alert('thats right'); + x = (x?a:x); + }, +}; + +id = id.replace(/row\/:;/gi, ''); + +for (i=0; i<3; i++) { + for (j=0; j<5; j++) { + if (j==x) + break; + } +} +alert('hi'); +; + +var sum = a; /* + b */ + +var sum = a; // +b + + +var sum = a; /* +b + + c */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php new file mode 100644 index 000000000..218666dc0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.php @@ -0,0 +1,87 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SemicolonSpacing sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\SemicolonSpacingSniff + */ +final class SemicolonSpacingUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SemicolonSpacingUnitTest.inc': + return [ + 3 => 1, + 4 => 1, + 5 => 2, + 6 => 1, + 8 => 1, + 9 => 1, + 14 => 1, + 16 => 1, + 18 => 1, + 29 => 1, + 30 => 2, + 36 => 1, + ]; + + case 'SemicolonSpacingUnitTest.js': + return [ + 3 => 1, + 4 => 1, + 6 => 1, + 10 => 2, + 11 => 1, + 13 => 1, + 19 => 1, + 22 => 1, + 25 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css new file mode 100644 index 000000000..e3f3f0291 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css @@ -0,0 +1,32 @@ + +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} + +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */ +.HelpWidgetType-new-bug-title{ + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */ + +// /** +// * This text is in two types of comment: each line is commented out +// * individually, and the whole block is in what looks like a +// * docblock-comment. This sniff should ignore all this text as there +// * is no superfluous white-space here. +// */ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed new file mode 100644 index 000000000..11be21d5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css.fixed @@ -0,0 +1,30 @@ +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} +.HelpWidgetType-new-bug-title { + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} + +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */ +.HelpWidgetType-new-bug-title{ + float: left; +} + +.HelpWidgetType-new-bug-title{ + float: left; +} +/* phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */ + +// /** +// * This text is in two types of comment: each line is commented out +// * individually, and the whole block is in what looks like a +// * docblock-comment. This sniff should ignore all this text as there +// * is no superfluous white-space here. +// */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc new file mode 100644 index 000000000..f9dca29a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc @@ -0,0 +1,74 @@ + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed new file mode 100644 index 000000000..1d764ebfa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.inc.fixed @@ -0,0 +1,68 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js new file mode 100644 index 000000000..be542e776 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js @@ -0,0 +1,56 @@ + +alert('hi'); +alert('hello'); + +if (something) { + +} + + +function myFunction() +{ + alert('code here'); + + alert('code here'); + + + // Hello. + + /* + HI + */ + + +} + +function myFunction2() +{ + alert('code here'); + + + alert('code here'); + +} + +MyFunction = function() +{ + alert('code here'); + + + alert('code here'); + +}; + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed new file mode 100644 index 000000000..960111a5e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js.fixed @@ -0,0 +1,50 @@ +alert('hi'); +alert('hello'); + +if (something) { + +} + + +function myFunction() +{ + alert('code here'); + + alert('code here'); + + // Hello. + + /* + HI + */ + +} + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +MyFunction = function() +{ + alert('code here'); + + alert('code here'); + +}; + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true + +function myFunction2() +{ + alert('code here'); + + alert('code here'); + +} + +// phpcs:set Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css new file mode 100644 index 000000000..2025eeb19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed new file mode 100644 index 000000000..2025eeb19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css.fixed @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc new file mode 100644 index 000000000..a6e2b8ad7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc @@ -0,0 +1,9 @@ + + +

    + +

    + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed new file mode 100644 index 000000000..78c452511 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.inc.fixed @@ -0,0 +1,7 @@ + +

    + +

    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js new file mode 100644 index 000000000..7b0c8eacd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js @@ -0,0 +1 @@ +alert('hi'); \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed new file mode 100644 index 000000000..7b0c8eacd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js.fixed @@ -0,0 +1 @@ +alert('hi'); \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css new file mode 100644 index 000000000..9f794a082 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed new file mode 100644 index 000000000..2025eeb19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css.fixed @@ -0,0 +1,3 @@ +.HelpWidgetType-new-bug-title { + float: left; +} \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc new file mode 100644 index 000000000..661ebdafd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed new file mode 100644 index 000000000..0cb97480e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.inc.fixed @@ -0,0 +1,5 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js new file mode 100644 index 000000000..70f67193a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js @@ -0,0 +1 @@ +alert('hi'); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed new file mode 100644 index 000000000..70f67193a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js.fixed @@ -0,0 +1 @@ +alert('hi'); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc new file mode 100644 index 000000000..96860ffb0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed new file mode 100644 index 000000000..b26b5b2c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.4.inc.fixed @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc new file mode 100644 index 000000000..4d6f06bcf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc @@ -0,0 +1,5 @@ +   +  \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed new file mode 100644 index 000000000..8ec5f30d4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.5.inc.fixed @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php new file mode 100644 index 000000000..4f7c7cdbc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.php @@ -0,0 +1,117 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Squiz\Tests\WhiteSpace; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the SuperfluousWhitespace sniff. + * + * @covers \PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\SuperfluousWhitespaceSniff + */ +final class SuperfluousWhitespaceUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'SuperfluousWhitespaceUnitTest.1.inc': + return [ + 2 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + 16 => 1, + 23 => 1, + 28 => 1, + 33 => 1, + 49 => 1, + 62 => 1, + 65 => 1, + 73 => 1, + ]; + + case 'SuperfluousWhitespaceUnitTest.2.inc': + return [ + 2 => 1, + 8 => 1, + ]; + + case 'SuperfluousWhitespaceUnitTest.3.inc': + return [ + 6 => 1, + 10 => 1, + ]; + + case 'SuperfluousWhitespaceUnitTest.4.inc': + case 'SuperfluousWhitespaceUnitTest.5.inc': + return [ + 1 => 1, + 4 => 1, + ]; + + case 'SuperfluousWhitespaceUnitTest.1.js': + return [ + 1 => 1, + 3 => 1, + 4 => 1, + 5 => 1, + 6 => 1, + 15 => 1, + 22 => 1, + 29 => 1, + 38 => 1, + 56 => 1, + ]; + + case 'SuperfluousWhitespaceUnitTest.1.css': + return [ + 1 => 1, + 8 => 1, + 9 => 1, + 11 => 1, + 32 => 1, + ]; + + default: + return []; + }//end switch + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml new file mode 100644 index 000000000..87ab4c3e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Squiz/ruleset.xml @@ -0,0 +1,132 @@ + + + The Squiz coding standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + %2$s + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + + + + + + 0 + + + error + + + + + 0 + + + error + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml new file mode 100644 index 000000000..c462b4f8b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml @@ -0,0 +1,25 @@ + + + + + + + $bar + $baz; +} + ]]> + + + $bar + 2; +} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml new file mode 100644 index 000000000..f1dca3c67 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/Files/ClosingTagStandard.xml @@ -0,0 +1,22 @@ + + + + + + + + + + ?> + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml new file mode 100644 index 000000000..5bcde4b84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml @@ -0,0 +1,37 @@ + + + + + + + $testNumber = 1; + ]]> + + + $Test_Number = 1; + ]]> + + + + + _bar; +} + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php new file mode 100644 index 000000000..454f665a7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php @@ -0,0 +1,100 @@ + + * @author Greg Sherwood + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + * + * @deprecated 3.9.0 + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\Debug; + +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Common; + +class CodeAnalyzerSniff implements Sniff +{ + + + /** + * Returns the token types that this sniff is interested in. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes the tokens that this sniff is interested in. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where the token was found. + * @param int $stackPtr The position in the stack where + * the token was found. + * + * @return int + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If ZendCodeAnalyzer could not be run. + */ + public function process(File $phpcsFile, $stackPtr) + { + $analyzerPath = Config::getExecutablePath('zend_ca'); + if ($analyzerPath === null) { + return $phpcsFile->numTokens; + } + + $fileName = $phpcsFile->getFilename(); + + // In the command, 2>&1 is important because the code analyzer sends its + // findings to stderr. $output normally contains only stdout, so using 2>&1 + // will pipe even stderr to stdout. + $cmd = Common::escapeshellcmd($analyzerPath).' '.escapeshellarg($fileName).' 2>&1'; + + // There is the possibility to pass "--ide" as an option to the analyzer. + // This would result in an output format which would be easier to parse. + // The problem here is that no cleartext error messages are returned; only + // error-code-labels. So for a start we go for cleartext output. + $exitCode = exec($cmd, $output, $retval); + + // Variable $exitCode is the last line of $output if no error occurs, on + // error it is numeric. Try to handle various error conditions and + // provide useful error reporting. + if (is_numeric($exitCode) === true && $exitCode > 0) { + if (is_array($output) === true) { + $msg = implode('\n', $output); + } + + throw new RuntimeException("Failed invoking ZendCodeAnalyzer, exitcode was [$exitCode], retval was [$retval], output was [$msg]"); + } + + if (is_array($output) === true) { + foreach ($output as $finding) { + // The first two lines of analyzer output contain + // something like this: + // > Zend Code Analyzer 1.2.2 + // > Analyzing ... + // So skip these... + $res = preg_match("/^.+\(line ([0-9]+)\):(.+)$/", $finding, $regs); + if (empty($regs) === true || $res === false) { + continue; + } + + $phpcsFile->addWarningOnLine(trim($regs[2]), $regs[1], 'ExternalTool'); + } + } + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php new file mode 100644 index 000000000..7b547bfd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/Files/ClosingTagSniff.php @@ -0,0 +1,79 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\Files; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +class ClosingTagSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return [T_OPEN_TAG]; + + }//end register() + + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in + * the stack passed in $tokens. + * + * @return int + */ + public function process(File $phpcsFile, $stackPtr) + { + // Find the last non-empty token. + $tokens = $phpcsFile->getTokens(); + for ($last = ($phpcsFile->numTokens - 1); $last > 0; $last--) { + if (trim($tokens[$last]['content']) !== '') { + break; + } + } + + if ($tokens[$last]['code'] === T_CLOSE_TAG) { + $error = 'A closing tag is not permitted at the end of a PHP file'; + $fix = $phpcsFile->addFixableError($error, $last, 'NotAllowed'); + if ($fix === true) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken($last, $phpcsFile->eolChar); + $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($last - 1), null, true); + if ($tokens[$prev]['code'] !== T_SEMICOLON + && $tokens[$prev]['code'] !== T_CLOSE_CURLY_BRACKET + && $tokens[$prev]['code'] !== T_OPEN_TAG + ) { + $phpcsFile->fixer->addContent($prev, ';'); + } + + $phpcsFile->fixer->endChangeset(); + } + + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'yes'); + } else { + $phpcsFile->recordMetric($stackPtr, 'PHP closing tag at EOF', 'no'); + }//end if + + // Ignore the rest of the file. + return $phpcsFile->numTokens; + + }//end process() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php new file mode 100644 index 000000000..41b194810 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php @@ -0,0 +1,196 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\AbstractVariableSniff; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class ValidVariableNameSniff extends AbstractVariableSniff +{ + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processVariable(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + return; + } + + $objOperator = $phpcsFile->findNext([T_WHITESPACE], ($stackPtr + 1), null, true); + if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR + || $tokens[$objOperator]['code'] === T_NULLSAFE_OBJECT_OPERATOR + ) { + // Check to see if we are using a variable from an object. + $var = $phpcsFile->findNext([T_WHITESPACE], ($objOperator + 1), null, true); + if ($tokens[$var]['code'] === T_STRING) { + // Either a var name or a function call, so check for bracket. + $bracket = $phpcsFile->findNext([T_WHITESPACE], ($var + 1), null, true); + + if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) { + $objVarName = $tokens[$var]['content']; + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $objVarName; + if (substr($objVarName, 0, 1) === '_') { + $objVarName = substr($objVarName, 1); + } + + if (Common::isCamelCaps($objVarName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $var, 'NotCamelCaps', $data); + } else if (preg_match('|\d|', $objVarName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$originalVarName]; + $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data); + } + }//end if + }//end if + }//end if + + // There is no way for us to know if the var is public or private, + // so we have to ignore a leading underscore if there is one and just + // check the main part of the variable name. + $originalVarName = $varName; + if (substr($varName, 0, 1) === '_') { + $objOperator = $phpcsFile->findPrevious([T_WHITESPACE], ($stackPtr - 1), null, true); + if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) { + // The variable lives within a class, and is referenced like + // this: MyClass::$_variable, so we don't know its scope. + $inClass = true; + } else { + $inClass = $phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + } + + if ($inClass === true) { + $varName = substr($varName, 1); + } + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$originalVarName]; + $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$originalVarName]; + $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data); + } + + }//end processVariable() + + + /** + * Processes class member variables. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + protected function processMemberVar(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + $varName = ltrim($tokens[$stackPtr]['content'], '$'); + $memberProps = $phpcsFile->getMemberProperties($stackPtr); + if (empty($memberProps) === true) { + // Exception encountered. + return; + } + + $public = ($memberProps['scope'] === 'public'); + + if ($public === true) { + if (substr($varName, 0, 1) === '_') { + $error = 'Public member variable "%s" must not contain a leading underscore'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data); + } + } else { + if (substr($varName, 0, 1) !== '_') { + $scope = ucfirst($memberProps['scope']); + $error = '%s member variable "%s" must contain a leading underscore'; + $data = [ + $scope, + $varName, + ]; + $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data); + } + } + + // Remove a potential underscore prefix for testing CamelCaps. + $varName = ltrim($varName, '_'); + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Member variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'MemberVarNotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Member variable "%s" contains numbers but this is discouraged'; + $data = [$varName]; + $phpcsFile->addWarning($warning, $stackPtr, 'MemberVarContainsNumbers', $data); + } + + }//end processMemberVar() + + + /** + * Processes the variable found within a double quoted string. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the double quoted + * string. + * + * @return void + */ + protected function processVariableInString(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + + if (preg_match_all('|[^\\\]\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) { + foreach ($matches[1] as $varName) { + // If it's a php reserved var, then its ok. + if (isset($this->phpReservedVars[$varName]) === true) { + continue; + } + + if (Common::isCamelCaps($varName, false, true, false) === false) { + $error = 'Variable "%s" is not in valid camel caps format'; + $data = [$varName]; + $phpcsFile->addError($error, $stackPtr, 'StringVarNotCamelCaps', $data); + } else if (preg_match('|\d|', $varName) === 1) { + $warning = 'Variable "%s" contains numbers but this is discouraged'; + $data = [$varName]; + $phpcsFile->addWarning($warning, $stackPtr, 'StringVarContainsNumbers', $data); + } + }//end foreach + }//end if + + }//end processVariableInString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc new file mode 100644 index 000000000..c8d0499dd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.inc @@ -0,0 +1,6 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php new file mode 100644 index 000000000..82781a7d6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php @@ -0,0 +1,71 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\Debug; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; +use PHP_CodeSniffer\Config; + +/** + * Unit test class for the CodeAnalyzer sniff. + * + * @covers \PHP_CodeSniffer\Standards\Zend\Sniffs\Debug\CodeAnalyzerSniff + */ +final class CodeAnalyzerUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Should this test be skipped for some reason. + * + * @return bool + */ + protected function shouldSkipTest() + { + $analyzerPath = Config::getExecutablePath('zend_ca'); + if ($analyzerPath === null) { + return true; + } + + return false; + + }//end shouldSkipTest() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return []; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [2 => 1]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc new file mode 100644 index 000000000..7e7089dc3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc @@ -0,0 +1,12 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed new file mode 100644 index 000000000..caf3b38eb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.1.inc.fixed @@ -0,0 +1,12 @@ + + +

    + +
    diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc new file mode 100644 index 000000000..63df04d5f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc @@ -0,0 +1 @@ +add('arg'))?> diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed new file mode 100644 index 000000000..b4c462198 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.3.inc.fixed @@ -0,0 +1 @@ +add('arg')); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc new file mode 100644 index 000000000..539365dad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc @@ -0,0 +1 @@ +add('arg')) /* comment */ ?> diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed new file mode 100644 index 000000000..4cc31a510 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.4.inc.fixed @@ -0,0 +1 @@ +add('arg')); /* comment */ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc new file mode 100644 index 000000000..09e484407 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc @@ -0,0 +1 @@ +add('arg')); } ?> diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed new file mode 100644 index 000000000..9ff112a4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.5.inc.fixed @@ -0,0 +1 @@ +add('arg')); } diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc new file mode 100644 index 000000000..48de7e035 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed new file mode 100644 index 000000000..796727a8f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.6.inc.fixed @@ -0,0 +1,3 @@ + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed new file mode 100644 index 000000000..dc84e23ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/Files/ClosingTagUnitTest.7.inc.fixed @@ -0,0 +1 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\Files; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ClosingTag sniff. + * + * @covers \PHP_CodeSniffer\Standards\Zend\Sniffs\Files\ClosingTagSniff + */ +final class ClosingTagUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + public function getErrorList($testFile='') + { + switch ($testFile) { + case 'ClosingTagUnitTest.1.inc': + return [11 => 1]; + + case 'ClosingTagUnitTest.3.inc': + case 'ClosingTagUnitTest.4.inc': + case 'ClosingTagUnitTest.5.inc': + case 'ClosingTagUnitTest.7.inc': + return [1 => 1]; + + case 'ClosingTagUnitTest.6.inc': + return [3 => 1]; + + default: + return []; + } + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc new file mode 100644 index 000000000..3325e1152 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -0,0 +1,131 @@ +varName; +echo $this->var_name; +echo $this->varname; +echo $this->_varName; +echo $this->varName2; +echo $object->varName; +echo $object->var_name; +echo $object->varName2; +echo $object_name->varname; +echo $object_name->_varName; +echo $object_name->varName2; + +echo $this->myFunction($one, $two); +echo $object->myFunction($one_two, $var2); + +$error = "format is \$GLOBALS['$varName']"; +$error = "format is \$GLOBALS['$varName2']"; + +echo $_SESSION['var_name']; +echo $_FILES['var_name']; +echo $_ENV['var_name']; +echo $_COOKIE['var_name']; +echo $_COOKIE['var_name2']; + +$XML = 'hello'; +$myXML = 'hello'; +$XMLParser = 'hello'; +$xmlParser = 'hello'; +$xmlParser2 = 'hello'; + +echo "{$_SERVER['HOSTNAME']} $var_name"; + +$someObject->{$name}; +$someObject->my_function($var_name); + +var_dump($http_response_header); +var_dump($HTTP_RAW_POST_DATA); +var_dump($php_errormsg); + +interface Base +{ + protected $anonymous; + + public function __construct(); +} + +$anonClass = new class() { + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +}; + +echo $obj?->varName; +echo $obj?->var_name; +echo $obj?->varName; + +enum SomeEnum +{ + public function foo($foo, $_foo, $foo_bar) { + $bar = 1; + $_bar = 2; + $bar_foo = 3; + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php new file mode 100644 index 000000000..c66a2a42c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -0,0 +1,102 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Standards\Zend\Tests\NamingConventions; + +use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest; + +/** + * Unit test class for the ValidVariableName sniff. + * + * @covers \PHP_CodeSniffer\Standards\Zend\Sniffs\NamingConventions\ValidVariableNameSniff + */ +final class ValidVariableNameUnitTest extends AbstractSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + public function getErrorList() + { + return [ + 3 => 1, + 5 => 1, + 11 => 1, + 13 => 1, + 17 => 1, + 19 => 1, + 23 => 1, + 25 => 1, + 29 => 1, + 31 => 1, + 36 => 1, + 38 => 1, + 42 => 1, + 44 => 1, + 48 => 1, + 50 => 1, + 61 => 1, + 67 => 1, + 72 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + 79 => 1, + 96 => 1, + 99 => 1, + 113 => 1, + 116 => 1, + 121 => 1, + 126 => 1, + 129 => 1, + ]; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + public function getWarningList() + { + return [ + 6 => 1, + 14 => 1, + 20 => 1, + 26 => 1, + 32 => 1, + 39 => 1, + 45 => 1, + 51 => 1, + 64 => 1, + 70 => 1, + 73 => 1, + 76 => 1, + 79 => 1, + 82 => 1, + 94 => 1, + // Warning from getMemberProperties() about parse error. + 107 => 1, + ]; + + }//end getWarningList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml new file mode 100644 index 000000000..d10b10395 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Standards/Zend/ruleset.xml @@ -0,0 +1,32 @@ + + + A coding standard based on an early Zend Framework coding standard. Note that this standard is out of date. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php new file mode 100644 index 000000000..36631ddc3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/CSS.php @@ -0,0 +1,541 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +class CSS extends PHP +{ + + + /** + * Initialise the tokenizer. + * + * Pre-checks the content to see if it looks minified. + * + * @param string $content The content to tokenize. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, Config $config, $eolChar='\n') + { + if ($this->isMinifiedContent($content, $eolChar) === true) { + throw new TokenizerException('File appears to be minified and cannot be processed'); + } + + parent::__construct($content, $config, $eolChar); + + }//end __construct() + + + /** + * Creates an array of tokens when given some CSS code. + * + * Uses the PHP tokenizer to do all the tricky work + * + * @param string $string The string to tokenize. + * + * @return array + */ + public function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START CSS TOKENIZING 1ST PASS ***".PHP_EOL; + } + + // If the content doesn't have an EOL char on the end, add one so + // the open and close tags we add are parsed correctly. + $eolAdded = false; + if (substr($string, (strlen($this->eolChar) * -1)) !== $this->eolChar) { + $string .= $this->eolChar; + $eolAdded = true; + } + + $string = str_replace('', '^PHPCS_CSS_T_CLOSE_TAG^', $string); + $tokens = parent::tokenize(''); + + $finalTokens = []; + $finalTokens[0] = [ + 'code' => T_OPEN_TAG, + 'type' => 'T_OPEN_TAG', + 'content' => '', + ]; + + $newStackPtr = 1; + $numTokens = count($tokens); + $multiLineComment = false; + for ($stackPtr = 1; $stackPtr < $numTokens; $stackPtr++) { + $token = $tokens[$stackPtr]; + + // CSS files don't have lists, breaks etc, so convert these to + // standard strings early so they can be converted into T_STYLE + // tokens and joined with other strings if needed. + if ($token['code'] === T_BREAK + || $token['code'] === T_LIST + || $token['code'] === T_DEFAULT + || $token['code'] === T_SWITCH + || $token['code'] === T_FOR + || $token['code'] === T_FOREACH + || $token['code'] === T_WHILE + || $token['code'] === T_DEC + || $token['code'] === T_NEW + ) { + $token['type'] = 'T_STRING'; + $token['code'] = T_STRING; + } + + $token['content'] = str_replace('^PHPCS_CSS_T_OPEN_TAG^', '', $token['content']); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + if ($token['code'] === T_BITWISE_XOR + && $tokens[($stackPtr + 1)]['content'] === 'PHPCS_CSS_T_OPEN_TAG' + ) { + $content = ''; + $stackPtr += 2; + break; + } else { + $content .= $tokens[$stackPtr]['content']; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> Found embedded PHP code: "; + $cleanContent = Util\Common::prepareForOutput($content); + echo $cleanContent.PHP_EOL; + } + + $finalTokens[$newStackPtr] = [ + 'type' => 'T_EMBEDDED_PHP', + 'code' => T_EMBEDDED_PHP, + 'content' => $content, + ]; + + $newStackPtr++; + continue; + }//end if + + if ($token['code'] === T_GOTO_LABEL) { + // Convert these back to T_STRING followed by T_COLON so we can + // more easily process style definitions. + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => substr($token['content'], 0, -1), + ]; + $newStackPtr++; + $finalTokens[$newStackPtr] = [ + 'type' => 'T_COLON', + 'code' => T_COLON, + 'content' => ':', + ]; + $newStackPtr++; + continue; + } + + if ($token['code'] === T_FUNCTION) { + // There are no functions in CSS, so convert this to a string. + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => $token['content'], + ]; + + $newStackPtr++; + continue; + } + + if ($token['code'] === T_COMMENT + && substr($token['content'], 0, 2) === '/*' + ) { + // Multi-line comment. Record it so we can ignore other + // comment tags until we get out of this one. + $multiLineComment = true; + } + + if ($token['code'] === T_COMMENT + && $multiLineComment === false + && (substr($token['content'], 0, 2) === '//' + || $token['content'][0] === '#') + ) { + $content = ltrim($token['content'], '#/'); + + // Guard against PHP7+ syntax errors by stripping + // leading zeros so the content doesn't look like an invalid int. + $leadingZero = false; + if ($content[0] === '0') { + $content = '1'.$content; + $leadingZero = true; + } + + $commentTokens = parent::tokenize(''); + + // The first and last tokens are the open/close tags. + array_shift($commentTokens); + $closeTag = array_pop($commentTokens); + + while ($closeTag['content'] !== '?'.'>') { + $closeTag = array_pop($commentTokens); + } + + if ($leadingZero === true) { + $commentTokens[0]['content'] = substr($commentTokens[0]['content'], 1); + $content = substr($content, 1); + } + + if ($token['content'][0] === '#') { + // The # character is not a comment in CSS files, so + // determine what it means in this context. + $firstContent = $commentTokens[0]['content']; + + // If the first content is just a number, it is probably a + // colour like 8FB7DB, which PHP splits into 8 and FB7DB. + if (($commentTokens[0]['code'] === T_LNUMBER + || $commentTokens[0]['code'] === T_DNUMBER) + && $commentTokens[1]['code'] === T_STRING + ) { + $firstContent .= $commentTokens[1]['content']; + array_shift($commentTokens); + } + + // If the first content looks like a colour and not a class + // definition, join the tokens together. + if (preg_match('/^[ABCDEF0-9]+$/i', $firstContent) === 1 + && $commentTokens[1]['content'] !== '-' + ) { + array_shift($commentTokens); + // Work out what we trimmed off above and remember to re-add it. + $trimmed = substr($token['content'], 0, (strlen($token['content']) - strlen($content))); + $finalTokens[$newStackPtr] = [ + 'type' => 'T_COLOUR', + 'code' => T_COLOUR, + 'content' => $trimmed.$firstContent, + ]; + } else { + $finalTokens[$newStackPtr] = [ + 'type' => 'T_HASH', + 'code' => T_HASH, + 'content' => '#', + ]; + } + } else { + $finalTokens[$newStackPtr] = [ + 'type' => 'T_STRING', + 'code' => T_STRING, + 'content' => '//', + ]; + }//end if + + $newStackPtr++; + + array_splice($tokens, $stackPtr, 1, $commentTokens); + $numTokens = count($tokens); + $stackPtr--; + continue; + }//end if + + if ($token['code'] === T_COMMENT + && substr($token['content'], -2) === '*/' + ) { + // Multi-line comment is done. + $multiLineComment = false; + } + + $finalTokens[$newStackPtr] = $token; + $newStackPtr++; + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END CSS TOKENIZING 1ST PASS ***".PHP_EOL; + echo "\t*** START CSS TOKENIZING 2ND PASS ***".PHP_EOL; + } + + // A flag to indicate if we are inside a style definition, + // which is defined using curly braces. + $inStyleDef = false; + + // A flag to indicate if an At-rule like "@media" is used, which will result + // in nested curly brackets. + $asperandStart = false; + + $numTokens = count($finalTokens); + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + $token = $finalTokens[$stackPtr]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $token['type']; + $content = Util\Common::prepareForOutput($token['content']); + echo "\tProcess token $stackPtr: $type => $content".PHP_EOL; + } + + switch ($token['code']) { + case T_OPEN_CURLY_BRACKET: + // Opening curly brackets for an At-rule do not start a style + // definition. We also reset the asperand flag here because the next + // opening curly bracket could be indeed the start of a style + // definition. + if ($asperandStart === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inStyleDef === true) { + echo "\t\t* style definition closed *".PHP_EOL; + } + + if ($asperandStart === true) { + echo "\t\t* at-rule definition closed *".PHP_EOL; + } + } + + $inStyleDef = false; + $asperandStart = false; + } else { + $inStyleDef = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* style definition opened *".PHP_EOL; + } + } + break; + case T_CLOSE_CURLY_BRACKET: + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inStyleDef === true) { + echo "\t\t* style definition closed *".PHP_EOL; + } + + if ($asperandStart === true) { + echo "\t\t* at-rule definition closed *".PHP_EOL; + } + } + + $inStyleDef = false; + $asperandStart = false; + break; + case T_MINUS: + // Minus signs are often used instead of spaces inside + // class names, IDs and styles. + if ($finalTokens[($stackPtr + 1)]['code'] === T_STRING) { + if ($finalTokens[($stackPtr - 1)]['code'] === T_STRING) { + $newContent = $finalTokens[($stackPtr - 1)]['content'].'-'.$finalTokens[($stackPtr + 1)]['content']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL; + $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + $new = Util\Common::prepareForOutput($newContent); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + unset($finalTokens[($stackPtr - 1)]); + } else { + $newContent = '-'.$finalTokens[($stackPtr + 1)]['content']; + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + } + } else if ($finalTokens[($stackPtr + 1)]['code'] === T_LNUMBER) { + // They can also be used to provide negative numbers. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is part of a negative number; adding content to next token and ignoring *".PHP_EOL; + $content = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$content\" to \"-$content\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = '-'.$finalTokens[($stackPtr + 1)]['content']; + unset($finalTokens[$stackPtr]); + }//end if + break; + case T_COLON: + // Only interested in colons that are defining styles. + if ($inStyleDef === false) { + break; + } + + for ($x = ($stackPtr - 1); $x >= 0; $x--) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) { + break; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $finalTokens[$x]['type']; + echo "\t\t=> token $x changed from $type to T_STYLE".PHP_EOL; + } + + $finalTokens[$x]['type'] = 'T_STYLE'; + $finalTokens[$x]['code'] = T_STYLE; + break; + case T_STRING: + if (strtolower($token['content']) === 'url') { + // Find the next content. + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$x]['code']]) === false) { + break; + } + } + + // Needs to be in the format "url(" for it to be a URL. + if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) { + continue 2; + } + + // Make sure the content isn't empty. + for ($y = ($x + 1); $y < $numTokens; $y++) { + if (isset(Util\Tokens::$emptyTokens[$finalTokens[$y]['code']]) === false) { + break; + } + } + + if ($finalTokens[$y]['code'] === T_CLOSE_PARENTHESIS) { + continue 2; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= $y; $i++) { + $type = $finalTokens[$i]['type']; + $content = Util\Common::prepareForOutput($finalTokens[$i]['content']); + echo "\tProcess token $i: $type => $content".PHP_EOL; + } + + echo "\t\t* token starts a URL *".PHP_EOL; + } + + // Join all the content together inside the url() statement. + $newContent = ''; + for ($i = ($x + 2); $i < $numTokens; $i++) { + if ($finalTokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + break; + } + + $newContent .= $finalTokens[$i]['content']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($finalTokens[$i]['content']); + echo "\t\t=> token $i added to URL string and ignored: $content".PHP_EOL; + } + + unset($finalTokens[$i]); + } + + $stackPtr = $i; + + // If the content inside the "url()" is in double quotes + // there will only be one token and so we don't have to do + // anything except change its type. If it is not empty, + // we need to do some token merging. + $finalTokens[($x + 1)]['type'] = 'T_URL'; + $finalTokens[($x + 1)]['code'] = T_URL; + + if ($newContent !== '') { + $finalTokens[($x + 1)]['content'] .= $newContent; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($finalTokens[($x + 1)]['content']); + echo "\t\t=> token content changed to: $content".PHP_EOL; + } + } + } else if ($finalTokens[$stackPtr]['content'][0] === '-' + && $finalTokens[($stackPtr + 1)]['code'] === T_STRING + ) { + if (isset($finalTokens[($stackPtr - 1)]) === true + && $finalTokens[($stackPtr - 1)]['code'] === T_STRING + ) { + $newContent = $finalTokens[($stackPtr - 1)]['content'].$finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is a string joiner; ignoring this and previous token".PHP_EOL; + $old = Util\Common::prepareForOutput($finalTokens[($stackPtr + 1)]['content']); + $new = Util\Common::prepareForOutput($newContent); + echo "\t\t=> token ".($stackPtr + 1)." content changed from \"$old\" to \"$new\"".PHP_EOL; + } + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + unset($finalTokens[($stackPtr - 1)]); + } else { + $newContent = $finalTokens[$stackPtr]['content'].$finalTokens[($stackPtr + 1)]['content']; + + $finalTokens[($stackPtr + 1)]['content'] = $newContent; + unset($finalTokens[$stackPtr]); + } + }//end if + break; + case T_ASPERAND: + $asperandStart = true; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* at-rule definition opened *".PHP_EOL; + } + break; + default: + // Nothing special to be done with this token. + break; + }//end switch + }//end for + + // Reset the array keys to avoid gaps. + $finalTokens = array_values($finalTokens); + $numTokens = count($finalTokens); + + // Blank out the content of the end tag. + $finalTokens[($numTokens - 1)]['content'] = ''; + + if ($eolAdded === true) { + // Strip off the extra EOL char we added for tokenizing. + $finalTokens[($numTokens - 2)]['content'] = substr( + $finalTokens[($numTokens - 2)]['content'], + 0, + (strlen($this->eolChar) * -1) + ); + + if ($finalTokens[($numTokens - 2)]['content'] === '') { + unset($finalTokens[($numTokens - 2)]); + $finalTokens = array_values($finalTokens); + $numTokens = count($finalTokens); + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END CSS TOKENIZING 2ND PASS ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Performs additional processing after main tokenizing. + * + * @return void + */ + public function processAdditional() + { + /* + We override this method because we don't want the PHP version to + run during CSS processing because it is wasted processing time. + */ + + }//end processAdditional() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php new file mode 100644 index 000000000..b7c6e3745 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php @@ -0,0 +1,283 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Util\Common; + +class Comment +{ + + + /** + * Creates an array of tokens when given some PHP code. + * + * Starts by using token_get_all() but does a lot of extra processing + * to insert information about the context of the token. + * + * @param string $string The string to tokenize. + * @param string $eolChar The EOL character to use for splitting strings. + * @param int $stackPtr The position of the first token in the file. + * + * @return array>> + */ + public function tokenizeString($string, $eolChar, $stackPtr) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL; + } + + $tokens = []; + $numChars = strlen($string); + + /* + Doc block comments start with /*, but typically contain an + extra star when they are used for function and class comments. + */ + + $char = ($numChars - strlen(ltrim($string, '/*'))); + $lastChars = substr($string, -2); + if ($char === $numChars && $lastChars === '*/') { + // Edge case: docblock without whitespace or contents. + $openTag = substr($string, 0, -2); + $string = $lastChars; + } else { + $openTag = substr($string, 0, $char); + $string = ltrim($string, '/*'); + } + + $tokens[$stackPtr] = [ + 'content' => $openTag, + 'code' => T_DOC_COMMENT_OPEN_TAG, + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'comment_tags' => [], + ]; + + $openPtr = $stackPtr; + $stackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Common::prepareForOutput($openTag); + echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL; + } + + /* + Strip off the close tag so it doesn't interfere with any + of our comment line processing. The token will be added to the + stack just before we return it. + */ + + $closeTag = [ + 'content' => substr($string, strlen(rtrim($string, '/*'))), + 'code' => T_DOC_COMMENT_CLOSE_TAG, + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'comment_opener' => $openPtr, + ]; + + if ($closeTag['content'] === false) { + // In PHP < 8.0 substr() can return `false` instead of always returning a string. + $closeTag['content'] = ''; + } + + $string = rtrim($string, '/*'); + + /* + Process each line of the comment. + */ + + $lines = explode($eolChar, $string); + $numLines = count($lines); + foreach ($lines as $lineNum => $string) { + if ($lineNum !== ($numLines - 1)) { + $string .= $eolChar; + } + + $char = 0; + $numChars = strlen($string); + + // We've started a new line, so process the indent. + $space = $this->collectWhitespace($string, $char, $numChars); + if ($space !== null) { + $tokens[$stackPtr] = $space; + $stackPtr++; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Common::prepareForOutput($space['content']); + echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL; + } + + $char += strlen($space['content']); + if ($char === $numChars) { + break; + } + } + + if ($string === '') { + continue; + } + + if ($lineNum > 0 && $string[$char] === '*') { + // This is a function or class doc block line. + $char++; + $tokens[$stackPtr] = [ + 'content' => '*', + 'code' => T_DOC_COMMENT_STAR, + 'type' => 'T_DOC_COMMENT_STAR', + ]; + + $stackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL; + } + } + + // Now we are ready to process the actual content of the line. + $lineTokens = $this->processLine($string, $eolChar, $char, $numChars); + foreach ($lineTokens as $lineToken) { + $tokens[$stackPtr] = $lineToken; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Common::prepareForOutput($lineToken['content']); + $type = $lineToken['type']; + echo "\t\tCreate comment token: $type => $content".PHP_EOL; + } + + if ($lineToken['code'] === T_DOC_COMMENT_TAG) { + $tokens[$openPtr]['comment_tags'][] = $stackPtr; + } + + $stackPtr++; + } + }//end foreach + + $tokens[$stackPtr] = $closeTag; + $tokens[$openPtr]['comment_closer'] = $stackPtr; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Common::prepareForOutput($closeTag['content']); + echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL; + } + + return $tokens; + + }//end tokenizeString() + + + /** + * Process a single line of a comment. + * + * @param string $string The comment string being tokenized. + * @param string $eolChar The EOL character to use for splitting strings. + * @param int $start The position in the string to start processing. + * @param int $end The position in the string to end processing. + * + * @return array> + */ + private function processLine($string, $eolChar, $start, $end) + { + $tokens = []; + + // Collect content padding. + $space = $this->collectWhitespace($string, $start, $end); + if ($space !== null) { + $tokens[] = $space; + $start += strlen($space['content']); + } + + if (isset($string[$start]) === false) { + return $tokens; + } + + if ($string[$start] === '@') { + // The content up until the first whitespace is the tag name. + $matches = []; + preg_match('/@[^\s]+/', $string, $matches, 0, $start); + if (isset($matches[0]) === true + && substr(strtolower($matches[0]), 0, 7) !== '@phpcs:' + ) { + $tagName = $matches[0]; + $start += strlen($tagName); + $tokens[] = [ + 'content' => $tagName, + 'code' => T_DOC_COMMENT_TAG, + 'type' => 'T_DOC_COMMENT_TAG', + ]; + + // Then there will be some whitespace. + $space = $this->collectWhitespace($string, $start, $end); + if ($space !== null) { + $tokens[] = $space; + $start += strlen($space['content']); + } + } + }//end if + + // Process the rest of the line. + $eol = strpos($string, $eolChar, $start); + if ($eol === false) { + $eol = $end; + } + + if ($eol > $start) { + $tokens[] = [ + 'content' => substr($string, $start, ($eol - $start)), + 'code' => T_DOC_COMMENT_STRING, + 'type' => 'T_DOC_COMMENT_STRING', + ]; + } + + if ($eol !== $end) { + $tokens[] = [ + 'content' => substr($string, $eol, strlen($eolChar)), + 'code' => T_DOC_COMMENT_WHITESPACE, + 'type' => 'T_DOC_COMMENT_WHITESPACE', + ]; + } + + return $tokens; + + }//end processLine() + + + /** + * Collect consecutive whitespace into a single token. + * + * @param string $string The comment string being tokenized. + * @param int $start The position in the string to start processing. + * @param int $end The position in the string to end processing. + * + * @return array|null + */ + private function collectWhitespace($string, $start, $end) + { + $space = ''; + for ($start; $start < $end; $start++) { + if ($string[$start] !== ' ' && $string[$start] !== "\t") { + break; + } + + $space .= $string[$start]; + } + + if ($space === '') { + return null; + } + + return [ + 'content' => $space, + 'code' => T_DOC_COMMENT_WHITESPACE, + 'type' => 'T_DOC_COMMENT_WHITESPACE', + ]; + + }//end collectWhitespace() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php new file mode 100644 index 000000000..c7249fcd9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/JS.php @@ -0,0 +1,1256 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util; + +class JS extends Tokenizer +{ + + /** + * A list of tokens that are allowed to open a scope. + * + * This array also contains information about what kind of token the scope + * opener uses to open and close the scope, if the token strictly requires + * an opener, if the token can share a scope closer, and who it can be shared + * with. An example of a token that shares a scope closer is a CASE scope. + * + * @var array + */ + public $scopeOpeners = [ + T_IF => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_TRY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ELSE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_FOR => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_CLASS => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FUNCTION => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_WHILE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DO => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_SWITCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CASE => [ + 'start' => [T_COLON => T_COLON], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_DEFAULT => T_DEFAULT, + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_DEFAULT => [ + 'start' => [T_COLON => T_COLON], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + ]; + + /** + * A list of tokens that end the scope. + * + * This array is just a unique collection of the end tokens + * from the _scopeOpeners array. The data is duplicated here to + * save time during parsing of the file. + * + * @var array + */ + public $endScopeTokens = [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_BREAK => T_BREAK, + ]; + + /** + * A list of special JS tokens and their types. + * + * @var array + */ + protected $tokenValues = [ + 'class' => 'T_CLASS', + 'function' => 'T_FUNCTION', + 'prototype' => 'T_PROTOTYPE', + 'try' => 'T_TRY', + 'catch' => 'T_CATCH', + 'return' => 'T_RETURN', + 'throw' => 'T_THROW', + 'break' => 'T_BREAK', + 'switch' => 'T_SWITCH', + 'continue' => 'T_CONTINUE', + 'if' => 'T_IF', + 'else' => 'T_ELSE', + 'do' => 'T_DO', + 'while' => 'T_WHILE', + 'for' => 'T_FOR', + 'var' => 'T_VAR', + 'case' => 'T_CASE', + 'default' => 'T_DEFAULT', + 'true' => 'T_TRUE', + 'false' => 'T_FALSE', + 'null' => 'T_NULL', + 'this' => 'T_THIS', + 'typeof' => 'T_TYPEOF', + '(' => 'T_OPEN_PARENTHESIS', + ')' => 'T_CLOSE_PARENTHESIS', + '{' => 'T_OPEN_CURLY_BRACKET', + '}' => 'T_CLOSE_CURLY_BRACKET', + '[' => 'T_OPEN_SQUARE_BRACKET', + ']' => 'T_CLOSE_SQUARE_BRACKET', + '?' => 'T_INLINE_THEN', + '.' => 'T_OBJECT_OPERATOR', + '+' => 'T_PLUS', + '-' => 'T_MINUS', + '*' => 'T_MULTIPLY', + '%' => 'T_MODULUS', + '/' => 'T_DIVIDE', + '^' => 'T_LOGICAL_XOR', + ',' => 'T_COMMA', + ';' => 'T_SEMICOLON', + ':' => 'T_COLON', + '<' => 'T_LESS_THAN', + '>' => 'T_GREATER_THAN', + '<<' => 'T_SL', + '>>' => 'T_SR', + '>>>' => 'T_ZSR', + '<<=' => 'T_SL_EQUAL', + '>>=' => 'T_SR_EQUAL', + '>>>=' => 'T_ZSR_EQUAL', + '<=' => 'T_IS_SMALLER_OR_EQUAL', + '>=' => 'T_IS_GREATER_OR_EQUAL', + '=>' => 'T_DOUBLE_ARROW', + '!' => 'T_BOOLEAN_NOT', + '||' => 'T_BOOLEAN_OR', + '&&' => 'T_BOOLEAN_AND', + '|' => 'T_BITWISE_OR', + '&' => 'T_BITWISE_AND', + '!=' => 'T_IS_NOT_EQUAL', + '!==' => 'T_IS_NOT_IDENTICAL', + '=' => 'T_EQUAL', + '==' => 'T_IS_EQUAL', + '===' => 'T_IS_IDENTICAL', + '-=' => 'T_MINUS_EQUAL', + '+=' => 'T_PLUS_EQUAL', + '*=' => 'T_MUL_EQUAL', + '/=' => 'T_DIV_EQUAL', + '%=' => 'T_MOD_EQUAL', + '++' => 'T_INC', + '--' => 'T_DEC', + '//' => 'T_COMMENT', + '/*' => 'T_COMMENT', + '/**' => 'T_DOC_COMMENT', + '*/' => 'T_COMMENT', + ]; + + /** + * A list string delimiters. + * + * @var array + */ + protected $stringTokens = [ + '\'' => '\'', + '"' => '"', + ]; + + /** + * A list tokens that start and end comments. + * + * @var array + */ + protected $commentTokens = [ + '//' => null, + '/*' => '*/', + '/**' => '*/', + ]; + + + /** + * Initialise the tokenizer. + * + * Pre-checks the content to see if it looks minified. + * + * @param string $content The content to tokenize. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, Config $config, $eolChar='\n') + { + if ($this->isMinifiedContent($content, $eolChar) === true) { + throw new TokenizerException('File appears to be minified and cannot be processed'); + } + + parent::__construct($content, $config, $eolChar); + + }//end __construct() + + + /** + * Creates an array of tokens when given some JS code. + * + * @param string $string The string to tokenize. + * + * @return array + */ + public function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START JS TOKENIZING ***".PHP_EOL; + } + + $maxTokenLength = 0; + foreach ($this->tokenValues as $token => $values) { + if (strlen($token) > $maxTokenLength) { + $maxTokenLength = strlen($token); + } + } + + $tokens = []; + $inString = ''; + $stringChar = null; + $inComment = ''; + $buffer = ''; + $preStringBuffer = ''; + $cleanBuffer = false; + + $commentTokenizer = new Comment(); + + $tokens[] = [ + 'code' => T_OPEN_TAG, + 'type' => 'T_OPEN_TAG', + 'content' => '', + ]; + + // Convert newlines to single characters for ease of + // processing. We will change them back later. + $string = str_replace($this->eolChar, "\n", $string); + + $chars = str_split($string); + $numChars = count($chars); + for ($i = 0; $i < $numChars; $i++) { + $char = $chars[$i]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($char); + $bufferContent = Util\Common::prepareForOutput($buffer); + + if ($inString !== '') { + echo "\t"; + } + + if ($inComment !== '') { + echo "\t"; + } + + echo "\tProcess char $i => $content (buffer: $bufferContent)".PHP_EOL; + }//end if + + if ($inString === '' && $inComment === '' && $buffer !== '') { + // If the buffer only has whitespace and we are about to + // add a character, store the whitespace first. + if (trim($char) !== '' && trim($buffer) === '') { + $tokens[] = [ + 'code' => T_WHITESPACE, + 'type' => 'T_WHITESPACE', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL; + } + + $buffer = ''; + } + + // If the buffer is not whitespace and we are about to + // add a whitespace character, store the content first. + if ($inString === '' + && $inComment === '' + && trim($char) === '' + && trim($buffer) !== '' + ) { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + } + }//end if + + // Process strings. + if ($inComment === '' && isset($this->stringTokens[$char]) === true) { + if ($inString === $char) { + // This could be the end of the string, but make sure it + // is not escaped first. + $escapes = 0; + for ($x = ($i - 1); $x >= 0; $x--) { + if ($chars[$x] !== '\\') { + break; + } + + $escapes++; + } + + if ($escapes === 0 || ($escapes % 2) === 0) { + // There is an even number escape chars, + // so this is not escaped, it is the end of the string. + $tokens[] = [ + 'code' => T_CONSTANT_ENCAPSED_STRING, + 'type' => 'T_CONSTANT_ENCAPSED_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer).$char, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* found end of string *".PHP_EOL; + $content = Util\Common::prepareForOutput($buffer.$char); + echo "\t=> Added token T_CONSTANT_ENCAPSED_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + $preStringBuffer = ''; + $inString = ''; + $stringChar = null; + continue; + }//end if + } else if ($inString === '') { + $inString = $char; + $stringChar = $i; + $preStringBuffer = $buffer; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* looking for string closer *".PHP_EOL; + } + }//end if + }//end if + + if ($inString !== '' && $char === "\n") { + // Unless this newline character is escaped, the string did not + // end before the end of the line, which means it probably + // wasn't a string at all (maybe a regex). + if ($chars[($i - 1)] !== '\\') { + $i = $stringChar; + $buffer = $preStringBuffer; + $preStringBuffer = ''; + $inString = ''; + $stringChar = null; + $char = $chars[$i]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* found newline before end of string, bailing *".PHP_EOL; + } + } + } + + $buffer .= $char; + + // We don't look for special tokens inside strings, + // so if we are in a string, we can continue here now + // that the current char is in the buffer. + if ($inString !== '') { + continue; + } + + // Special case for T_DIVIDE which can actually be + // the start of a regular expression. + if ($buffer === $char && $char === '/' && $chars[($i + 1)] !== '*') { + $regex = $this->getRegexToken($i, $string, $chars, $tokens); + if ($regex !== null) { + $tokens[] = [ + 'code' => T_REGULAR_EXPRESSION, + 'type' => 'T_REGULAR_EXPRESSION', + 'content' => $regex['content'], + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($regex['content']); + echo "\t=> Added token T_REGULAR_EXPRESSION ($content)".PHP_EOL; + } + + $i = $regex['end']; + $buffer = ''; + $cleanBuffer = false; + continue; + }//end if + }//end if + + // Check for known tokens, but ignore tokens found that are not at + // the end of a string, like FOR and this.FORmat. + if (isset($this->tokenValues[strtolower($buffer)]) === true + && (preg_match('|[a-zA-z0-9_]|', $char) === 0 + || isset($chars[($i + 1)]) === false + || preg_match('|[a-zA-z0-9_]|', $chars[($i + 1)]) === 0) + ) { + $matchedToken = false; + $lookAheadLength = ($maxTokenLength - strlen($buffer)); + + if ($lookAheadLength > 0) { + // The buffer contains a token type, but we need + // to look ahead at the next chars to see if this is + // actually part of a larger token. For example, + // FOR and FOREACH. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* buffer possibly contains token, looking ahead $lookAheadLength chars *".PHP_EOL; + } + + $charBuffer = $buffer; + for ($x = 1; $x <= $lookAheadLength; $x++) { + if (isset($chars[($i + $x)]) === false) { + break; + } + + $charBuffer .= $chars[($i + $x)]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($charBuffer); + echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL; + } + + if (isset($this->tokenValues[strtolower($charBuffer)]) === true) { + // We've found something larger that matches + // so we can ignore this char. Except for 1 very specific + // case where a comment like /**/ needs to tokenize as + // T_COMMENT and not T_DOC_COMMENT. + $oldType = $this->tokenValues[strtolower($buffer)]; + $newType = $this->tokenValues[strtolower($charBuffer)]; + if ($oldType === 'T_COMMENT' + && $newType === 'T_DOC_COMMENT' + && $chars[($i + $x + 1)] === '/' + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead ignored T_DOC_COMMENT, continuing *".PHP_EOL; + } + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead found more specific token ($newType), ignoring $i *".PHP_EOL; + } + + $matchedToken = true; + break; + } + }//end if + }//end for + }//end if + + if ($matchedToken === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1 && $lookAheadLength > 0) { + echo "\t\t* look ahead found nothing *".PHP_EOL; + } + + $value = $this->tokenValues[strtolower($buffer)]; + + if ($value === 'T_FUNCTION' && $buffer !== 'function') { + // The function keyword needs to be all lowercase or else + // it is just a function called "Function". + $value = 'T_STRING'; + } + + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $buffer, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + + $cleanBuffer = true; + }//end if + } else if (isset($this->tokenValues[strtolower($char)]) === true) { + // No matter what token we end up using, we don't + // need the content in the buffer any more because we have + // found a valid token. + $newContent = substr(str_replace("\n", $this->eolChar, $buffer), 0, -1); + if ($newContent !== '') { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $newContent, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput(substr($buffer, 0, -1)); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* char is token, looking ahead ".($maxTokenLength - 1).' chars *'.PHP_EOL; + } + + // The char is a token type, but we need to look ahead at the + // next chars to see if this is actually part of a larger token. + // For example, = and ===. + $charBuffer = $char; + $matchedToken = false; + for ($x = 1; $x <= $maxTokenLength; $x++) { + if (isset($chars[($i + $x)]) === false) { + break; + } + + $charBuffer .= $chars[($i + $x)]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($charBuffer); + echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL; + } + + if (isset($this->tokenValues[strtolower($charBuffer)]) === true) { + // We've found something larger that matches + // so we can ignore this char. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokenValues[strtolower($charBuffer)]; + echo "\t\t* look ahead found more specific token ($type), ignoring $i *".PHP_EOL; + } + + $matchedToken = true; + break; + } + }//end for + + if ($matchedToken === false) { + $value = $this->tokenValues[strtolower($char)]; + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $char, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* look ahead found nothing *".PHP_EOL; + $content = Util\Common::prepareForOutput($char); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + + $cleanBuffer = true; + } else { + $buffer = $char; + }//end if + }//end if + + // Keep track of content inside comments. + if ($inComment === '' + && array_key_exists($buffer, $this->commentTokens) === true + ) { + // This is not really a comment if the content + // looks like \// (i.e., it is escaped). + if (isset($chars[($i - 2)]) === true && $chars[($i - 2)] === '\\') { + $lastToken = array_pop($tokens); + $lastContent = $lastToken['content']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $value = $this->tokenValues[strtolower($lastContent)]; + $content = Util\Common::prepareForOutput($lastContent); + echo "\t=> Removed token $value ($content)".PHP_EOL; + } + + $lastChars = str_split($lastContent); + $lastNumChars = count($lastChars); + for ($x = 0; $x < $lastNumChars; $x++) { + $lastChar = $lastChars[$x]; + $value = $this->tokenValues[strtolower($lastChar)]; + $tokens[] = [ + 'code' => constant($value), + 'type' => $value, + 'content' => $lastChar, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($lastChar); + echo "\t=> Added token $value ($content)".PHP_EOL; + } + } + } else { + // We have started a comment. + $inComment = $buffer; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* looking for end of comment *".PHP_EOL; + } + }//end if + } else if ($inComment !== '') { + if ($this->commentTokens[$inComment] === null) { + // Comment ends at the next newline. + if (strpos($buffer, "\n") !== false) { + $inComment = ''; + } + } else { + if ($this->commentTokens[$inComment] === $buffer) { + $inComment = ''; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($inComment === '') { + echo "\t\t* found end of comment *".PHP_EOL; + } + } + + if ($inComment === '' && $cleanBuffer === false) { + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + + $buffer = ''; + } + }//end if + + if ($cleanBuffer === true) { + $buffer = ''; + $cleanBuffer = false; + } + }//end for + + if (empty($buffer) === false) { + if ($inString !== '') { + // The string did not end before the end of the file, + // which means there was probably a syntax error somewhere. + $tokens[] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_STRING ($content)".PHP_EOL; + } + } else { + // Buffer contains whitespace from the end of the file. + $tokens[] = [ + 'code' => T_WHITESPACE, + 'type' => 'T_WHITESPACE', + 'content' => str_replace("\n", $this->eolChar, $buffer), + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $content = Util\Common::prepareForOutput($buffer); + echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL; + } + }//end if + }//end if + + $tokens[] = [ + 'code' => T_CLOSE_TAG, + 'type' => 'T_CLOSE_TAG', + 'content' => '', + ]; + + /* + Now that we have done some basic tokenizing, we need to + modify the tokens to join some together and split some apart + so they match what the PHP tokenizer does. + */ + + $finalTokens = []; + $newStackPtr = 0; + $numTokens = count($tokens); + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + $token = $tokens[$stackPtr]; + + /* + Look for comments and join the tokens together. + */ + + if ($token['code'] === T_COMMENT || $token['code'] === T_DOC_COMMENT) { + $newContent = ''; + $tokenContent = $token['content']; + + $endContent = null; + if (isset($this->commentTokens[$tokenContent]) === true) { + $endContent = $this->commentTokens[$tokenContent]; + } + + while ($tokenContent !== $endContent) { + if ($endContent === null + && strpos($tokenContent, $this->eolChar) !== false + ) { + // A null end token means the comment ends at the end of + // the line so we look for newlines and split the token. + $tokens[$stackPtr]['content'] = substr( + $tokenContent, + (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar)) + ); + + $tokenContent = substr( + $tokenContent, + 0, + (strpos($tokenContent, $this->eolChar) + strlen($this->eolChar)) + ); + + // If the substr failed, skip the token as the content + // will now be blank. + if ($tokens[$stackPtr]['content'] !== false + && $tokens[$stackPtr]['content'] !== '' + ) { + $stackPtr--; + } + + break; + }//end if + + $stackPtr++; + $newContent .= $tokenContent; + if (isset($tokens[$stackPtr]) === false) { + break; + } + + $tokenContent = $tokens[$stackPtr]['content']; + }//end while + + if ($token['code'] === T_DOC_COMMENT) { + $commentTokens = $commentTokenizer->tokenizeString($newContent.$tokenContent, $this->eolChar, $newStackPtr); + foreach ($commentTokens as $commentToken) { + $finalTokens[$newStackPtr] = $commentToken; + $newStackPtr++; + } + + continue; + } else { + // Save the new content in the current token so + // the code below can chop it up on newlines. + $token['content'] = $newContent.$tokenContent; + } + }//end if + + /* + If this token has newlines in its content, split each line up + and create a new token for each line. We do this so it's easier + to ascertain where errors occur on a line. + Note that $token[1] is the token's content. + */ + + if (strpos($token['content'], $this->eolChar) !== false) { + $tokenLines = explode($this->eolChar, $token['content']); + $numLines = count($tokenLines); + + for ($i = 0; $i < $numLines; $i++) { + $newToken = ['content' => $tokenLines[$i]]; + if ($i === ($numLines - 1)) { + if ($tokenLines[$i] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $newToken['type'] = $token['type']; + $newToken['code'] = $token['code']; + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + } else { + $finalTokens[$newStackPtr] = $token; + $newStackPtr++; + }//end if + + // Convert numbers, including decimals. + if ($token['code'] === T_STRING + || $token['code'] === T_OBJECT_OPERATOR + ) { + $newContent = ''; + $oldStackPtr = $stackPtr; + while (preg_match('|^[0-9\.]+$|', $tokens[$stackPtr]['content']) !== 0) { + $newContent .= $tokens[$stackPtr]['content']; + $stackPtr++; + } + + if ($newContent !== '' && $newContent !== '.') { + $finalTokens[($newStackPtr - 1)]['content'] = $newContent; + if (ctype_digit($newContent) === true) { + $finalTokens[($newStackPtr - 1)]['code'] = constant('T_LNUMBER'); + $finalTokens[($newStackPtr - 1)]['type'] = 'T_LNUMBER'; + } else { + $finalTokens[($newStackPtr - 1)]['code'] = constant('T_DNUMBER'); + $finalTokens[($newStackPtr - 1)]['type'] = 'T_DNUMBER'; + } + + $stackPtr--; + continue; + } else { + $stackPtr = $oldStackPtr; + } + }//end if + + // Convert the token after an object operator into a string, in most cases. + if ($token['code'] === T_OBJECT_OPERATOR) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (isset(Util\Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if ($tokens[$i]['code'] !== T_PROTOTYPE + && $tokens[$i]['code'] !== T_LNUMBER + && $tokens[$i]['code'] !== T_DNUMBER + ) { + $tokens[$i]['code'] = T_STRING; + $tokens[$i]['type'] = 'T_STRING'; + } + + break; + } + } + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END TOKENIZING ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Tokenizes a regular expression if one is found. + * + * If a regular expression is not found, NULL is returned. + * + * @param int $char The index of the possible regex start character. + * @param string $string The complete content of the string being tokenized. + * @param array $chars An array of characters being tokenized. + * @param array $tokens The current array of tokens found in the string. + * + * @return array|null + */ + public function getRegexToken($char, $string, $chars, $tokens) + { + $beforeTokens = [ + T_EQUAL => true, + T_IS_NOT_EQUAL => true, + T_IS_IDENTICAL => true, + T_IS_NOT_IDENTICAL => true, + T_OPEN_PARENTHESIS => true, + T_OPEN_SQUARE_BRACKET => true, + T_RETURN => true, + T_BOOLEAN_OR => true, + T_BOOLEAN_AND => true, + T_BOOLEAN_NOT => true, + T_BITWISE_OR => true, + T_BITWISE_AND => true, + T_COMMA => true, + T_COLON => true, + T_TYPEOF => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + $afterTokens = [ + ',' => true, + ')' => true, + ']' => true, + ';' => true, + ' ' => true, + '.' => true, + ':' => true, + $this->eolChar => true, + ]; + + // Find the last non-whitespace token that was added + // to the tokens array. + $numTokens = count($tokens); + for ($prev = ($numTokens - 1); $prev >= 0; $prev--) { + if (isset(Util\Tokens::$emptyTokens[$tokens[$prev]['code']]) === false) { + break; + } + } + + if (isset($beforeTokens[$tokens[$prev]['code']]) === false) { + return null; + } + + // This is probably a regular expression, so look for the end of it. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* token possibly starts a regular expression *".PHP_EOL; + } + + $numChars = count($chars); + for ($next = ($char + 1); $next < $numChars; $next++) { + if ($chars[$next] === '/') { + // Just make sure this is not escaped first. + if ($chars[($next - 1)] !== '\\') { + // In the simple form: /.../ so we found the end. + break; + } else if ($chars[($next - 2)] === '\\') { + // In the form: /...\\/ so we found the end. + break; + } + } else { + $possibleEolChar = substr($string, $next, strlen($this->eolChar)); + if ($possibleEolChar === $this->eolChar) { + // This is the last token on the line and regular + // expressions need to be defined on a single line, + // so this is not a regular expression. + break; + } + } + } + + if ($chars[$next] !== '/') { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* could not find end of regular expression *".PHP_EOL; + } + + return null; + } + + while (preg_match('|[a-zA-Z]|', $chars[($next + 1)]) !== 0) { + // The token directly after the end of the regex can + // be modifiers like global and case insensitive + // (.e.g, /pattern/gi). + $next++; + } + + $regexEnd = $next; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* found end of regular expression at token $regexEnd *".PHP_EOL; + } + + for ($next += 1; $next < $numChars; $next++) { + if ($chars[$next] !== ' ') { + break; + } else { + $possibleEolChar = substr($string, $next, strlen($this->eolChar)); + if ($possibleEolChar === $this->eolChar) { + // This is the last token on the line. + break; + } + } + } + + if (isset($afterTokens[$chars[$next]]) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* tokens after regular expression do not look correct *".PHP_EOL; + } + + return null; + } + + // This is a regular expression, so join all the tokens together. + $content = ''; + for ($x = $char; $x <= $regexEnd; $x++) { + $content .= $chars[$x]; + } + + $token = [ + 'start' => $char, + 'end' => $regexEnd, + 'content' => $content, + ]; + + return $token; + + }//end getRegexToken() + + + /** + * Performs additional processing after main tokenizing. + * + * This additional processing looks for properties, closures, labels and objects. + * + * @return void + */ + public function processAdditional() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START ADDITIONAL JS PROCESSING ***".PHP_EOL; + } + + $numTokens = count($this->tokens); + $classStack = []; + + for ($i = 0; $i < $numTokens; $i++) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $content = Util\Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", count($classStack)); + echo "\tProcess token $i: $type => $content".PHP_EOL; + } + + // Looking for functions that are actually closures. + if ($this->tokens[$i]['code'] === T_FUNCTION && isset($this->tokens[$i]['scope_opener']) === true) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$i]['code'] = T_CLOSURE; + $this->tokens[$i]['type'] = 'T_CLOSURE'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo str_repeat("\t", count($classStack)); + echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE *".PHP_EOL; + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_CLOSURE; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + && isset($this->tokens[$i]['scope_condition']) === false + && isset($this->tokens[$i]['bracket_closer']) === true + ) { + $condition = $this->tokens[$i]['conditions']; + $condition = end($condition); + if ($condition === T_CLASS) { + // Possibly an ES6 method. To be classified as one, the previous + // non-empty tokens need to be a set of parenthesis, and then a string + // (the method name). + for ($parenCloser = ($i - 1); $parenCloser > 0; $parenCloser--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$parenCloser]['code']]) === false) { + break; + } + } + + if ($this->tokens[$parenCloser]['code'] === T_CLOSE_PARENTHESIS) { + $parenOpener = $this->tokens[$parenCloser]['parenthesis_opener']; + for ($name = ($parenOpener - 1); $name > 0; $name--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$name]['code']]) === false) { + break; + } + } + + if ($this->tokens[$name]['code'] === T_STRING) { + // We found a method name. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$name]['line']; + echo str_repeat("\t", count($classStack)); + echo "\t* token $name on line $line changed from T_STRING to T_FUNCTION *".PHP_EOL; + } + + $closer = $this->tokens[$i]['bracket_closer']; + + $this->tokens[$name]['code'] = T_FUNCTION; + $this->tokens[$name]['type'] = 'T_FUNCTION'; + + foreach ([$name, $i, $closer] as $token) { + $this->tokens[$token]['scope_condition'] = $name; + $this->tokens[$token]['scope_opener'] = $i; + $this->tokens[$token]['scope_closer'] = $closer; + $this->tokens[$token]['parenthesis_opener'] = $parenOpener; + $this->tokens[$token]['parenthesis_closer'] = $parenCloser; + $this->tokens[$token]['parenthesis_owner'] = $name; + } + + $this->tokens[$parenOpener]['parenthesis_owner'] = $name; + $this->tokens[$parenCloser]['parenthesis_owner'] = $name; + + for ($x = ($i + 1); $x < $closer; $x++) { + $this->tokens[$x]['conditions'][$name] = T_FUNCTION; + ksort($this->tokens[$x]['conditions'], SORT_NUMERIC); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* added T_FUNCTION condition to $x ($type) *".PHP_EOL; + } + } + + continue; + }//end if + }//end if + }//end if + + $classStack[] = $i; + + $closer = $this->tokens[$i]['bracket_closer']; + $this->tokens[$i]['code'] = T_OBJECT; + $this->tokens[$i]['type'] = 'T_OBJECT'; + $this->tokens[$closer]['code'] = T_CLOSE_OBJECT; + $this->tokens[$closer]['type'] = 'T_CLOSE_OBJECT'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $i converted from T_OPEN_CURLY_BRACKET to T_OBJECT *".PHP_EOL; + echo str_repeat("\t", count($classStack)); + echo "\t* token $closer converted from T_CLOSE_CURLY_BRACKET to T_CLOSE_OBJECT *".PHP_EOL; + } + + for ($x = ($i + 1); $x < $closer; $x++) { + $this->tokens[$x]['conditions'][$i] = T_OBJECT; + ksort($this->tokens[$x]['conditions'], SORT_NUMERIC); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo str_repeat("\t", count($classStack)); + echo "\t\t* added T_OBJECT condition to $x ($type) *".PHP_EOL; + } + } + } else if ($this->tokens[$i]['code'] === T_CLOSE_OBJECT) { + array_pop($classStack); + } else if ($this->tokens[$i]['code'] === T_COLON) { + // If it is a scope opener, it belongs to a + // DEFAULT or CASE statement. + if (isset($this->tokens[$i]['scope_condition']) === true) { + continue; + } + + // Make sure this is not part of an inline IF statement. + for ($x = ($i - 1); $x >= 0; $x--) { + if ($this->tokens[$x]['code'] === T_INLINE_THEN) { + $this->tokens[$i]['code'] = T_INLINE_ELSE; + $this->tokens[$i]['type'] = 'T_INLINE_ELSE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $i converted from T_COLON to T_INLINE_THEN *".PHP_EOL; + } + + continue(2); + } else if ($this->tokens[$x]['line'] < $this->tokens[$i]['line']) { + break; + } + } + + // The string to the left of the colon is either a property or label. + for ($label = ($i - 1); $label >= 0; $label--) { + if (isset(Util\Tokens::$emptyTokens[$this->tokens[$label]['code']]) === false) { + break; + } + } + + if ($this->tokens[$label]['code'] !== T_STRING + && $this->tokens[$label]['code'] !== T_CONSTANT_ENCAPSED_STRING + ) { + continue; + } + + if (empty($classStack) === false) { + $this->tokens[$label]['code'] = T_PROPERTY; + $this->tokens[$label]['type'] = 'T_PROPERTY'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $label converted from T_STRING to T_PROPERTY *".PHP_EOL; + } + } else { + $this->tokens[$label]['code'] = T_LABEL; + $this->tokens[$label]['type'] = 'T_LABEL'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($classStack)); + echo "\t* token $label converted from T_STRING to T_LABEL *".PHP_EOL; + } + }//end if + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END ADDITIONAL JS PROCESSING ***".PHP_EOL; + } + + }//end processAdditional() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php new file mode 100644 index 000000000..9c6c11e4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/PHP.php @@ -0,0 +1,4002 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +class PHP extends Tokenizer +{ + + /** + * A list of tokens that are allowed to open a scope. + * + * This array also contains information about what kind of token the scope + * opener uses to open and close the scope, if the token strictly requires + * an opener, if the token can share a scope closer, and who it can be shared + * with. An example of a token that shares a scope closer is a CASE scope. + * + * @var array + */ + public $scopeOpeners = [ + T_IF => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + ], + T_TRY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FINALLY => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ELSE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + ], + ], + T_ELSEIF => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + ], + 'strict' => false, + 'shared' => false, + 'with' => [ + T_IF => T_IF, + T_ELSE => T_ELSE, + ], + ], + T_FOR => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDFOR => T_ENDFOR, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_FOREACH => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDFOREACH => T_ENDFOREACH, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_INTERFACE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_FUNCTION => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CLASS => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_TRAIT => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_ENUM => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_USE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DECLARE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDDECLARE => T_ENDDECLARE, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_NAMESPACE => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_WHILE => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDWHILE => T_ENDWHILE, + ], + 'strict' => false, + 'shared' => false, + 'with' => [], + ], + T_DO => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_SWITCH => [ + 'start' => [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_COLON => T_COLON, + ], + 'end' => [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDSWITCH => T_ENDSWITCH, + ], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_CASE => [ + 'start' => [ + T_COLON => T_COLON, + T_SEMICOLON => T_SEMICOLON, + ], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_DEFAULT => T_DEFAULT, + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_DEFAULT => [ + 'start' => [ + T_COLON => T_COLON, + T_SEMICOLON => T_SEMICOLON, + ], + 'end' => [ + T_BREAK => T_BREAK, + T_RETURN => T_RETURN, + T_CONTINUE => T_CONTINUE, + T_THROW => T_THROW, + T_EXIT => T_EXIT, + ], + 'strict' => true, + 'shared' => true, + 'with' => [ + T_CASE => T_CASE, + T_SWITCH => T_SWITCH, + ], + ], + T_MATCH => [ + 'start' => [T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET], + 'end' => [T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_START_HEREDOC => [ + 'start' => [T_START_HEREDOC => T_START_HEREDOC], + 'end' => [T_END_HEREDOC => T_END_HEREDOC], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + T_START_NOWDOC => [ + 'start' => [T_START_NOWDOC => T_START_NOWDOC], + 'end' => [T_END_NOWDOC => T_END_NOWDOC], + 'strict' => true, + 'shared' => false, + 'with' => [], + ], + ]; + + /** + * A list of tokens that end the scope. + * + * This array is just a unique collection of the end tokens + * from the scopeOpeners array. The data is duplicated here to + * save time during parsing of the file. + * + * @var array + */ + public $endScopeTokens = [ + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_ENDIF => T_ENDIF, + T_ENDFOR => T_ENDFOR, + T_ENDFOREACH => T_ENDFOREACH, + T_ENDWHILE => T_ENDWHILE, + T_ENDSWITCH => T_ENDSWITCH, + T_ENDDECLARE => T_ENDDECLARE, + T_BREAK => T_BREAK, + T_END_HEREDOC => T_END_HEREDOC, + T_END_NOWDOC => T_END_NOWDOC, + ]; + + /** + * Known lengths of tokens. + * + * @var array + */ + public $knownLengths = [ + T_ABSTRACT => 8, + T_AND_EQUAL => 2, + T_ARRAY => 5, + T_AS => 2, + T_BOOLEAN_AND => 2, + T_BOOLEAN_OR => 2, + T_BREAK => 5, + T_CALLABLE => 8, + T_CASE => 4, + T_CATCH => 5, + T_CLASS => 5, + T_CLASS_C => 9, + T_CLONE => 5, + T_CONCAT_EQUAL => 2, + T_CONST => 5, + T_CONTINUE => 8, + T_CURLY_OPEN => 2, + T_DEC => 2, + T_DECLARE => 7, + T_DEFAULT => 7, + T_DIR => 7, + T_DIV_EQUAL => 2, + T_DO => 2, + T_DOLLAR_OPEN_CURLY_BRACES => 2, + T_DOUBLE_ARROW => 2, + T_DOUBLE_COLON => 2, + T_ECHO => 4, + T_ELLIPSIS => 3, + T_ELSE => 4, + T_ELSEIF => 6, + T_EMPTY => 5, + T_ENDDECLARE => 10, + T_ENDFOR => 6, + T_ENDFOREACH => 10, + T_ENDIF => 5, + T_ENDSWITCH => 9, + T_ENDWHILE => 8, + T_ENUM => 4, + T_ENUM_CASE => 4, + T_EVAL => 4, + T_EXTENDS => 7, + T_FILE => 8, + T_FINAL => 5, + T_FINALLY => 7, + T_FN => 2, + T_FOR => 3, + T_FOREACH => 7, + T_FUNCTION => 8, + T_FUNC_C => 12, + T_GLOBAL => 6, + T_GOTO => 4, + T_HALT_COMPILER => 15, + T_IF => 2, + T_IMPLEMENTS => 10, + T_INC => 2, + T_INCLUDE => 7, + T_INCLUDE_ONCE => 12, + T_INSTANCEOF => 10, + T_INSTEADOF => 9, + T_INTERFACE => 9, + T_ISSET => 5, + T_IS_EQUAL => 2, + T_IS_GREATER_OR_EQUAL => 2, + T_IS_IDENTICAL => 3, + T_IS_NOT_EQUAL => 2, + T_IS_NOT_IDENTICAL => 3, + T_IS_SMALLER_OR_EQUAL => 2, + T_LINE => 8, + T_LIST => 4, + T_LOGICAL_AND => 3, + T_LOGICAL_OR => 2, + T_LOGICAL_XOR => 3, + T_MATCH => 5, + T_MATCH_ARROW => 2, + T_MATCH_DEFAULT => 7, + T_METHOD_C => 10, + T_MINUS_EQUAL => 2, + T_POW_EQUAL => 3, + T_MOD_EQUAL => 2, + T_MUL_EQUAL => 2, + T_NAMESPACE => 9, + T_NS_C => 13, + T_NS_SEPARATOR => 1, + T_NEW => 3, + T_NULLSAFE_OBJECT_OPERATOR => 3, + T_OBJECT_OPERATOR => 2, + T_OPEN_TAG_WITH_ECHO => 3, + T_OR_EQUAL => 2, + T_PLUS_EQUAL => 2, + T_PRINT => 5, + T_PRIVATE => 7, + T_PUBLIC => 6, + T_PROTECTED => 9, + T_READONLY => 8, + T_REQUIRE => 7, + T_REQUIRE_ONCE => 12, + T_RETURN => 6, + T_STATIC => 6, + T_SWITCH => 6, + T_THROW => 5, + T_TRAIT => 5, + T_TRAIT_C => 9, + T_TRY => 3, + T_UNSET => 5, + T_USE => 3, + T_VAR => 3, + T_WHILE => 5, + T_XOR_EQUAL => 2, + T_YIELD => 5, + T_OPEN_CURLY_BRACKET => 1, + T_CLOSE_CURLY_BRACKET => 1, + T_OPEN_SQUARE_BRACKET => 1, + T_CLOSE_SQUARE_BRACKET => 1, + T_OPEN_PARENTHESIS => 1, + T_CLOSE_PARENTHESIS => 1, + T_COLON => 1, + T_STRING_CONCAT => 1, + T_INLINE_THEN => 1, + T_INLINE_ELSE => 1, + T_NULLABLE => 1, + T_NULL => 4, + T_FALSE => 5, + T_TRUE => 4, + T_SEMICOLON => 1, + T_EQUAL => 1, + T_MULTIPLY => 1, + T_DIVIDE => 1, + T_PLUS => 1, + T_MINUS => 1, + T_MODULUS => 1, + T_POW => 2, + T_SPACESHIP => 3, + T_COALESCE => 2, + T_COALESCE_EQUAL => 3, + T_BITWISE_AND => 1, + T_BITWISE_OR => 1, + T_BITWISE_XOR => 1, + T_SL => 2, + T_SR => 2, + T_SL_EQUAL => 3, + T_SR_EQUAL => 3, + T_GREATER_THAN => 1, + T_LESS_THAN => 1, + T_BOOLEAN_NOT => 1, + T_SELF => 4, + T_PARENT => 6, + T_COMMA => 1, + T_THIS => 4, + T_CLOSURE => 8, + T_BACKTICK => 1, + T_OPEN_SHORT_ARRAY => 1, + T_CLOSE_SHORT_ARRAY => 1, + T_TYPE_UNION => 1, + T_TYPE_INTERSECTION => 1, + T_TYPE_OPEN_PARENTHESIS => 1, + T_TYPE_CLOSE_PARENTHESIS => 1, + ]; + + /** + * Contexts in which keywords should always be tokenized as T_STRING. + * + * @var array + */ + protected $tstringContexts = [ + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_FUNCTION => true, + T_CLASS => true, + T_INTERFACE => true, + T_TRAIT => true, + T_ENUM => true, + T_ENUM_CASE => true, + T_EXTENDS => true, + T_IMPLEMENTS => true, + T_ATTRIBUTE => true, + T_NEW => true, + T_CONST => true, + T_NS_SEPARATOR => true, + T_USE => true, + T_NAMESPACE => true, + T_PAAMAYIM_NEKUDOTAYIM => true, + ]; + + /** + * A cache of different token types, resolved into arrays. + * + * @var array + * @see standardiseToken() + */ + private static $resolveTokenCache = []; + + + /** + * Creates an array of tokens when given some PHP code. + * + * Starts by using token_get_all() but does a lot of extra processing + * to insert information about the context of the token. + * + * @param string $string The string to tokenize. + * + * @return array + */ + protected function tokenize($string) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START PHP TOKENIZING ***".PHP_EOL; + $isWin = false; + if (stripos(PHP_OS, 'WIN') === 0) { + $isWin = true; + } + } + + $tokens = @token_get_all($string); + $finalTokens = []; + + $newStackPtr = 0; + $numTokens = count($tokens); + $lastNotEmptyToken = 0; + + $insideInlineIf = []; + $insideUseGroup = false; + $insideConstDeclaration = false; + + $commentTokenizer = new Comment(); + + for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) { + // Special case for tokens we have needed to blank out. + if ($tokens[$stackPtr] === null) { + continue; + } + + $token = (array) $tokens[$stackPtr]; + $tokenIsArray = isset($token[1]); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($tokenIsArray === true) { + $type = Tokens::tokenName($token[0]); + $content = Common::prepareForOutput($token[1]); + } else { + $newToken = self::resolveSimpleToken($token[0]); + $type = $newToken['type']; + $content = Common::prepareForOutput($token[0]); + } + + echo "\tProcess token "; + if ($tokenIsArray === true) { + echo "[$stackPtr]"; + } else { + echo " $stackPtr "; + } + + echo ": $type => $content"; + }//end if + + if ($newStackPtr > 0 + && isset(Tokens::$emptyTokens[$finalTokens[($newStackPtr - 1)]['code']]) === false + ) { + $lastNotEmptyToken = ($newStackPtr - 1); + } + + /* + If we are using \r\n newline characters, the \r and \n are sometimes + split over two tokens. This normally occurs after comments. We need + to merge these two characters together so that our line endings are + consistent for all lines. + */ + + if ($tokenIsArray === true && substr($token[1], -1) === "\r") { + if (isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][1][0] === "\n" + ) { + $token[1] .= "\n"; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + if ($isWin === true) { + echo '\n'; + } else { + echo "\033[30;1m\\n\033[0m"; + } + } + + if ($tokens[($stackPtr + 1)][1] === "\n") { + // This token's content has been merged into the previous, + // so we can skip it. + $tokens[($stackPtr + 1)] = ''; + } else { + $tokens[($stackPtr + 1)][1] = substr($tokens[($stackPtr + 1)][1], 1); + } + } + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL; + } + + /* + Before PHP 5.5, the yield keyword was tokenized as + T_STRING. So look for and change this token in + earlier versions. + */ + + if (PHP_VERSION_ID < 50500 + && $tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'yield' + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + // Could still be a context sensitive keyword or "yield from" and potentially multi-line, + // so adjust the token stack in place. + $token[0] = T_YIELD; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_YIELD".PHP_EOL; + } + } + + /* + Tokenize context sensitive keyword as string when it should be string. + */ + + if ($tokenIsArray === true + && isset(Tokens::$contextSensitiveKeywords[$token[0]]) === true + && (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + || $finalTokens[$lastNotEmptyToken]['content'] === '&' + || $insideConstDeclaration === true) + ) { + if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true) { + $preserveKeyword = false; + + // `new class`, and `new static` should be preserved. + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && ($token[0] === T_CLASS + || $token[0] === T_STATIC) + ) { + $preserveKeyword = true; + } + + // `new readonly class` should be preserved. + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && strtolower($token[1]) === 'readonly' + ) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (is_array($tokens[$i]) === true && $tokens[$i][0] === T_CLASS) { + $preserveKeyword = true; + } + } + + // `new class extends` `new class implements` should be preserved + if (($token[0] === T_EXTENDS || $token[0] === T_IMPLEMENTS) + && $finalTokens[$lastNotEmptyToken]['code'] === T_CLASS + ) { + $preserveKeyword = true; + } + + // `namespace\` should be preserved + if ($token[0] === T_NAMESPACE) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false) { + break; + } + + if (isset(Tokens::$emptyTokens[$tokens[$i][0]]) === true) { + continue; + } + + if ($tokens[$i][0] === T_NS_SEPARATOR) { + $preserveKeyword = true; + } + + break; + } + } + }//end if + + // Types in typed constants should not be touched, but the constant name should be. + if ((isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + && $finalTokens[$lastNotEmptyToken]['code'] === T_CONST) + || $insideConstDeclaration === true + ) { + $preserveKeyword = true; + + // Find the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true + && isset(Tokens::$emptyTokens[$tokens[$i][0]]) === true + ) { + continue; + } + + break; + } + + if ($tokens[$i] === '=' || $tokens[$i] === ';') { + $preserveKeyword = false; + $insideConstDeclaration = false; + } + }//end if + + if ($finalTokens[$lastNotEmptyToken]['content'] === '&') { + $preserveKeyword = true; + + for ($i = ($lastNotEmptyToken - 1); $i >= 0; $i--) { + if (isset(Tokens::$emptyTokens[$finalTokens[$i]['code']]) === true) { + continue; + } + + if ($finalTokens[$i]['code'] === T_FUNCTION) { + $preserveKeyword = false; + } + + break; + } + } + + if ($preserveKeyword === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Tokens::tokenName($token[0]); + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $token[1], + ]; + + $newStackPtr++; + continue; + } + }//end if + + /* + Mark the start of a constant declaration to allow for handling keyword to T_STRING + convertion for constant names using reserved keywords. + */ + + if ($tokenIsArray === true && $token[0] === T_CONST) { + $insideConstDeclaration = true; + } + + /* + Close an open "inside constant declaration" marker when no keyword conversion was needed. + */ + + if ($insideConstDeclaration === true + && $tokenIsArray === false + && ($token[0] === '=' || $token[0] === ';') + ) { + $insideConstDeclaration = false; + } + + /* + Special case for `static` used as a function name, i.e. `static()`. + + Note: this may incorrectly change the static keyword directly before a DNF property type. + If so, this will be caught and corrected for in the additional processing. + */ + + if ($tokenIsArray === true + && $token[0] === T_STATIC + && $finalTokens[$lastNotEmptyToken]['code'] !== T_NEW + ) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true + && isset(Tokens::$emptyTokens[$tokens[$i][0]]) === true + ) { + continue; + } + + if ($tokens[$i][0] === '(') { + $finalTokens[$newStackPtr] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $token[1], + ]; + + $newStackPtr++; + continue 2; + } + + break; + } + }//end if + + /* + Parse doc blocks into something that can be easily iterated over. + */ + + if ($tokenIsArray === true + && ($token[0] === T_DOC_COMMENT + || ($token[0] === T_COMMENT && strpos($token[1], '/**') === 0 && $token[1] !== '/**/')) + ) { + $commentTokens = $commentTokenizer->tokenizeString($token[1], $this->eolChar, $newStackPtr); + foreach ($commentTokens as $commentToken) { + $finalTokens[$newStackPtr] = $commentToken; + $newStackPtr++; + } + + continue; + } + + /* + PHP 8 tokenizes a new line after a slash and hash comment to the next whitespace token. + */ + + if (PHP_VERSION_ID >= 80000 + && $tokenIsArray === true + && ($token[0] === T_COMMENT && (strpos($token[1], '//') === 0 || strpos($token[1], '#') === 0)) + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + ) { + $nextToken = $tokens[($stackPtr + 1)]; + + // If the next token is a single new line, merge it into the comment token + // and set to it up to be skipped. + if ($nextToken[1] === "\n" || $nextToken[1] === "\r\n" || $nextToken[1] === "\n\r") { + $token[1] .= $nextToken[1]; + $tokens[($stackPtr + 1)] = null; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* merged newline after comment into comment token $stackPtr".PHP_EOL; + } + } else { + // This may be a whitespace token consisting of multiple new lines. + if (strpos($nextToken[1], "\r\n") === 0) { + $token[1] .= "\r\n"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 2); + } else if (strpos($nextToken[1], "\n\r") === 0) { + $token[1] .= "\n\r"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 2); + } else if (strpos($nextToken[1], "\n") === 0) { + $token[1] .= "\n"; + $tokens[($stackPtr + 1)][1] = substr($nextToken[1], 1); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* stripped first newline after comment and added it to comment token $stackPtr".PHP_EOL; + } + }//end if + }//end if + + /* + For Explicit Octal Notation prior to PHP 8.1 we need to combine the + T_LNUMBER and T_STRING token values into a single token value, and + then ignore the T_STRING token. + */ + + if (PHP_VERSION_ID < 80100 + && $tokenIsArray === true && $token[1] === '0' + && (isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_STRING + && isset($tokens[($stackPtr + 1)][1][0], $tokens[($stackPtr + 1)][1][1]) === true + && strtolower($tokens[($stackPtr + 1)][1][0]) === 'o' + && $tokens[($stackPtr + 1)][1][1] !== '_') + && preg_match('`^(o[0-7]+(?:_[0-7]+)?)([0-9_]*)$`i', $tokens[($stackPtr + 1)][1], $matches) === 1 + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_LNUMBER, + 'type' => 'T_LNUMBER', + 'content' => $token[1] .= $matches[1], + ]; + $newStackPtr++; + + if (isset($matches[2]) === true && $matches[2] !== '') { + $type = 'T_LNUMBER'; + if ($matches[2][0] === '_') { + $type = 'T_STRING'; + } + + $finalTokens[$newStackPtr] = [ + 'code' => constant($type), + 'type' => $type, + 'content' => $matches[2], + ]; + $newStackPtr++; + } + + $stackPtr++; + continue; + }//end if + + /* + PHP 8.1 introduced two dedicated tokens for the & character. + Retokenizing both of these to T_BITWISE_AND, which is the + token PHPCS already tokenized them as. + */ + + if ($tokenIsArray === true + && ($token[0] === T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG + || $token[0] === T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG) + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BITWISE_AND, + 'type' => 'T_BITWISE_AND', + 'content' => $token[1], + ]; + $newStackPtr++; + continue; + } + + /* + If this is a double quoted string, PHP will tokenize the whole + thing which causes problems with the scope map when braces are + within the string. So we need to merge the tokens together to + provide a single string. + */ + + if ($tokenIsArray === false && ($token[0] === '"' || $token[0] === 'b"')) { + // Binary casts need a special token. + if ($token[0] === 'b"') { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => 'b', + ]; + $newStackPtr++; + } + + $tokenContent = '"'; + $nestedVars = []; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + $subToken = (array) $tokens[$i]; + $subTokenIsArray = isset($subToken[1]); + + if ($subTokenIsArray === true) { + $tokenContent .= $subToken[1]; + if (($subToken[1] === '{' + || $subToken[1] === '${') + && $subToken[0] !== T_ENCAPSED_AND_WHITESPACE + ) { + $nestedVars[] = $i; + } + } else { + $tokenContent .= $subToken[0]; + if ($subToken[0] === '}') { + array_pop($nestedVars); + } + } + + if ($subTokenIsArray === false + && $subToken[0] === '"' + && empty($nestedVars) === true + ) { + // We found the other end of the double quoted string. + break; + } + }//end for + + $stackPtr = $i; + + // Convert each line within the double quoted string to a + // new token, so it conforms with other multiple line tokens. + $tokenLines = explode($this->eolChar, $tokenContent); + $numLines = count($tokenLines); + $newToken = []; + + for ($j = 0; $j < $numLines; $j++) { + $newToken['content'] = $tokenLines[$j]; + if ($j === ($numLines - 1)) { + if ($tokenLines[$j] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $newToken['code'] = T_DOUBLE_QUOTED_STRING; + $newToken['type'] = 'T_DOUBLE_QUOTED_STRING'; + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + + // Continue, as we're done with this token. + continue; + }//end if + + /* + Detect binary casting and assign the casts their own token. + */ + + if ($tokenIsArray === true + && $token[0] === T_CONSTANT_ENCAPSED_STRING + && (substr($token[1], 0, 2) === 'b"' + || substr($token[1], 0, 2) === "b'") + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => 'b', + ]; + $newStackPtr++; + $token[1] = substr($token[1], 1); + } + + if ($tokenIsArray === true + && $token[0] === T_STRING_CAST + && preg_match('`^\(\s*binary\s*\)$`i', $token[1]) === 1 + ) { + $finalTokens[$newStackPtr] = [ + 'code' => T_BINARY_CAST, + 'type' => 'T_BINARY_CAST', + 'content' => $token[1], + ]; + $newStackPtr++; + continue; + } + + /* + If this is a heredoc, PHP will tokenize the whole + thing which causes problems when heredocs don't + contain real PHP code, which is almost never. + We want to leave the start and end heredoc tokens + alone though. + */ + + if ($tokenIsArray === true && $token[0] === T_START_HEREDOC) { + // Add the start heredoc token to the final array. + $finalTokens[$newStackPtr] = self::standardiseToken($token); + + // Check if this is actually a nowdoc and use a different token + // to help the sniffs. + $nowdoc = false; + if (strpos($token[1], "'") !== false) { + $finalTokens[$newStackPtr]['code'] = T_START_NOWDOC; + $finalTokens[$newStackPtr]['type'] = 'T_START_NOWDOC'; + $nowdoc = true; + } + + $tokenContent = ''; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + $subTokenIsArray = is_array($tokens[$i]); + if ($subTokenIsArray === true + && $tokens[$i][0] === T_END_HEREDOC + ) { + // We found the other end of the heredoc. + break; + } + + if ($subTokenIsArray === true) { + $tokenContent .= $tokens[$i][1]; + } else { + $tokenContent .= $tokens[$i]; + } + } + + if ($i === $numTokens) { + // We got to the end of the file and never + // found the closing token, so this probably wasn't + // a heredoc. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $finalTokens[$newStackPtr]['type']; + echo "\t\t* failed to find the end of the here/nowdoc".PHP_EOL; + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr]['code'] = T_STRING; + $finalTokens[$newStackPtr]['type'] = 'T_STRING'; + $newStackPtr++; + continue; + } + + $stackPtr = $i; + $newStackPtr++; + + // Convert each line within the heredoc to a + // new token, so it conforms with other multiple line tokens. + $tokenLines = explode($this->eolChar, $tokenContent); + $numLines = count($tokenLines); + $newToken = []; + + for ($j = 0; $j < $numLines; $j++) { + $newToken['content'] = $tokenLines[$j]; + if ($j === ($numLines - 1)) { + if ($tokenLines[$j] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + if ($nowdoc === true) { + $newToken['code'] = T_NOWDOC; + $newToken['type'] = 'T_NOWDOC'; + } else { + $newToken['code'] = T_HEREDOC; + $newToken['type'] = 'T_HEREDOC'; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + }//end for + + // Add the end heredoc token to the final array. + $finalTokens[$newStackPtr] = self::standardiseToken($tokens[$stackPtr]); + + if ($nowdoc === true) { + $finalTokens[$newStackPtr]['code'] = T_END_NOWDOC; + $finalTokens[$newStackPtr]['type'] = 'T_END_NOWDOC'; + } + + $newStackPtr++; + + // Continue, as we're done with this token. + continue; + }//end if + + /* + Enum keyword for PHP < 8.1 + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'enum' + ) { + // Get the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (isset($tokens[$i]) === true + && is_array($tokens[$i]) === true + && $tokens[$i][0] === T_STRING + ) { + // Modify $tokens directly so we can use it later when converting enum "case". + $tokens[$stackPtr][0] = T_ENUM; + + $newToken = []; + $newToken['code'] = T_ENUM; + $newToken['type'] = 'T_ENUM'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_ENUM".PHP_EOL; + } + + $newStackPtr++; + continue; + } + }//end if + + /* + Convert enum "case" to T_ENUM_CASE + */ + + if ($tokenIsArray === true + && $token[0] === T_CASE + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + $isEnumCase = false; + $scope = 1; + + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if ($tokens[$i] === '}') { + $scope++; + continue; + } + + if ($tokens[$i] === '{') { + $scope--; + continue; + } + + if (is_array($tokens[$i]) === false) { + continue; + } + + if ($scope !== 0) { + continue; + } + + if ($tokens[$i][0] === T_SWITCH) { + break; + } + + if ($tokens[$i][0] === T_ENUM || $tokens[$i][0] === T_ENUM_CASE) { + $isEnumCase = true; + break; + } + }//end for + + if ($isEnumCase === true) { + // Modify $tokens directly so we can use it as optimisation for other enum "case". + $tokens[$stackPtr][0] = T_ENUM_CASE; + + $newToken = []; + $newToken['code'] = T_ENUM_CASE; + $newToken['type'] = 'T_ENUM_CASE'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_CASE to T_ENUM_CASE".PHP_EOL; + } + + $newStackPtr++; + continue; + } + }//end if + + /* + As of PHP 8.0 fully qualified, partially qualified and namespace relative + identifier names are tokenized differently. + This "undoes" the new tokenization so the tokenization will be the same in + in PHP 5, 7 and 8. + */ + + if (PHP_VERSION_ID >= 80000 + && $tokenIsArray === true + && ($token[0] === T_NAME_QUALIFIED + || $token[0] === T_NAME_FULLY_QUALIFIED + || $token[0] === T_NAME_RELATIVE) + ) { + $name = $token[1]; + + if ($token[0] === T_NAME_FULLY_QUALIFIED) { + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $name = ltrim($name, '\\'); + } + + if ($token[0] === T_NAME_RELATIVE) { + $newToken = []; + $newToken['code'] = T_NAMESPACE; + $newToken['type'] = 'T_NAMESPACE'; + $newToken['content'] = substr($name, 0, 9); + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + $name = substr($name, 10); + } + + $parts = explode('\\', $name); + $partCount = count($parts); + $lastPart = ($partCount - 1); + + foreach ($parts as $i => $part) { + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $part; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + + if ($i !== $lastPart) { + $newToken = []; + $newToken['code'] = T_NS_SEPARATOR; + $newToken['type'] = 'T_NS_SEPARATOR'; + $newToken['content'] = '\\'; + $finalTokens[$newStackPtr] = $newToken; + ++$newStackPtr; + } + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Tokens::tokenName($token[0]); + $content = Common::prepareForOutput($token[1]); + echo "\t\t* token $stackPtr split into individual tokens; was: $type => $content".PHP_EOL; + } + + continue; + }//end if + + /* + PHP 8.0 Attributes + */ + + if (PHP_VERSION_ID < 80000 + && $token[0] === T_COMMENT + && strpos($token[1], '#[') === 0 + ) { + $subTokens = $this->parsePhpAttribute($tokens, $stackPtr); + if ($subTokens !== null) { + array_splice($tokens, $stackPtr, 1, $subTokens); + $numTokens = count($tokens); + + $tokenIsArray = true; + $token = $tokens[$stackPtr]; + } else { + $token[0] = T_ATTRIBUTE; + } + } + + if ($tokenIsArray === true + && $token[0] === T_ATTRIBUTE + ) { + // Go looking for the close bracket. + $bracketCloser = $this->findCloser($tokens, ($stackPtr + 1), ['[', '#['], ']'); + + $newToken = []; + $newToken['code'] = T_ATTRIBUTE; + $newToken['type'] = 'T_ATTRIBUTE'; + $newToken['content'] = '#['; + $finalTokens[$newStackPtr] = $newToken; + + $tokens[$bracketCloser] = []; + $tokens[$bracketCloser][0] = T_ATTRIBUTE_END; + $tokens[$bracketCloser][1] = ']'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $bracketCloser changed from T_CLOSE_SQUARE_BRACKET to T_ATTRIBUTE_END".PHP_EOL; + } + + $newStackPtr++; + continue; + }//end if + + /* + Tokenize the parameter labels for PHP 8.0 named parameters as a special T_PARAM_NAME + token and ensures that the colon after it is always T_COLON. + */ + + if ($tokenIsArray === true + && ($token[0] === T_STRING + || preg_match('`^[a-zA-Z_\x80-\xff]`', $token[1]) === 1) + ) { + // Get the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if (isset($tokens[$i]) === true + && is_array($tokens[$i]) === false + && $tokens[$i] === ':' + ) { + // Get the previous non-empty token. + for ($j = ($stackPtr - 1); $j > 0; $j--) { + if (is_array($tokens[$j]) === false + || isset(Tokens::$emptyTokens[$tokens[$j][0]]) === false + ) { + break; + } + } + + if (is_array($tokens[$j]) === false + && ($tokens[$j] === '(' + || $tokens[$j] === ',') + ) { + $newToken = []; + $newToken['code'] = T_PARAM_NAME; + $newToken['type'] = 'T_PARAM_NAME'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + + // Modify the original token stack so that future checks, like + // determining T_COLON vs T_INLINE_ELSE can handle this correctly. + $tokens[$stackPtr][0] = T_PARAM_NAME; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Tokens::tokenName($token[0]); + echo "\t\t* token $stackPtr changed from $type to T_PARAM_NAME".PHP_EOL; + } + + continue; + } + }//end if + }//end if + + /* + "readonly" keyword for PHP < 8.1 + */ + + if ($tokenIsArray === true + && strtolower($token[1]) === 'readonly' + && (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + || $finalTokens[$lastNotEmptyToken]['code'] === T_NEW) + ) { + // Get the next non-whitespace token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + $isReadonlyKeyword = false; + + if (isset($tokens[$i]) === false + || $tokens[$i] !== '(' + ) { + $isReadonlyKeyword = true; + } else if ($tokens[$i] === '(') { + /* + * Skip over tokens which can be used in type declarations. + * At this point, the only token types which need to be taken into consideration + * as potential type declarations are identifier names, T_ARRAY, T_CALLABLE and T_NS_SEPARATOR + * and the union/intersection/dnf parentheses. + */ + + $foundDNFParens = 1; + $foundDNFPipe = 0; + + for (++$i; $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if (isset(Tokens::$emptyTokens[$tokenType]) === true) { + continue; + } + + if ($tokenType === '|') { + ++$foundDNFPipe; + continue; + } + + if ($tokenType === ')') { + ++$foundDNFParens; + continue; + } + + if ($tokenType === '(') { + ++$foundDNFParens; + continue; + } + + if ($tokenType === T_STRING + || $tokenType === T_NAME_FULLY_QUALIFIED + || $tokenType === T_NAME_RELATIVE + || $tokenType === T_NAME_QUALIFIED + || $tokenType === T_ARRAY + || $tokenType === T_NAMESPACE + || $tokenType === T_NS_SEPARATOR + || $tokenType === T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG // PHP 8.0+. + || $tokenType === '&' // PHP < 8.0. + ) { + continue; + } + + // Reached the next token after. + if (($foundDNFParens % 2) === 0 + && $foundDNFPipe >= 1 + && ($tokenType === T_VARIABLE + || $tokenType === T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG) + ) { + $isReadonlyKeyword = true; + } + + break; + }//end for + }//end if + + if ($isReadonlyKeyword === true) { + $finalTokens[$newStackPtr] = [ + 'code' => T_READONLY, + 'type' => 'T_READONLY', + 'content' => $token[1], + ]; + $newStackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1 && $type !== T_READONLY) { + echo "\t\t* token $stackPtr changed from $type to T_READONLY".PHP_EOL; + } + } else { + $finalTokens[$newStackPtr] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $token[1], + ]; + $newStackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1 && $type !== T_STRING) { + echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + } + }//end if + + continue; + }//end if + + /* + Before PHP 7.0, "yield from" was tokenized as + T_YIELD, T_WHITESPACE and T_STRING. So look for + and change this token in earlier versions. + */ + + if (PHP_VERSION_ID < 70000 + && $tokenIsArray === true + && $token[0] === T_YIELD + && isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)][0] === T_WHITESPACE + && strpos($tokens[($stackPtr + 1)][1], $this->eolChar) === false + && $tokens[($stackPtr + 2)][0] === T_STRING + && strtolower($tokens[($stackPtr + 2)][1]) === 'from' + ) { + // Single-line "yield from" with only whitespace between. + $finalTokens[$newStackPtr] = [ + 'code' => T_YIELD_FROM, + 'type' => 'T_YIELD_FROM', + 'content' => $token[1].$tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1], + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + for ($i = ($stackPtr + 1); $i <= ($stackPtr + 2); $i++) { + $type = Tokens::tokenName($tokens[$i][0]); + $content = Common::prepareForOutput($tokens[$i][1]); + echo "\t\t* token $i merged into T_YIELD_FROM; was: $type => $content".PHP_EOL; + } + } + + $newStackPtr++; + $stackPtr += 2; + + continue; + } else if (PHP_VERSION_ID < 80300 + && $tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'from' + && $finalTokens[$lastNotEmptyToken]['code'] === T_YIELD + ) { + /* + Before PHP 8.3, if there was a comment between the "yield" and "from" keywords, + it was tokenized as T_YIELD, T_WHITESPACE, T_COMMENT... and T_STRING. + We want to keep the tokenization of the tokens between, but need to change the + `T_YIELD` and `T_STRING` (from) keywords to `T_YIELD_FROM. + */ + + $finalTokens[$lastNotEmptyToken]['code'] = T_YIELD_FROM; + $finalTokens[$lastNotEmptyToken]['type'] = 'T_YIELD_FROM'; + + $finalTokens[$newStackPtr] = [ + 'code' => T_YIELD_FROM, + 'type' => 'T_YIELD_FROM', + 'content' => $token[1], + ]; + $newStackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $lastNotEmptyToken (new stack) changed into T_YIELD_FROM; was: T_YIELD".PHP_EOL; + echo "\t\t* token $stackPtr changed into T_YIELD_FROM; was: T_STRING".PHP_EOL; + } + + continue; + } else if (PHP_VERSION_ID >= 70000 + && $tokenIsArray === true + && $token[0] === T_YIELD_FROM + && strpos($token[1], $this->eolChar) !== false + && preg_match('`^yield\s+from$`i', $token[1]) === 1 + ) { + /* + In PHP 7.0+, a multi-line "yield from" (without comment) tokenizes as a single + T_YIELD_FROM token, but we want to split it and tokenize the whitespace + separately for consistency. + */ + + $finalTokens[$newStackPtr] = [ + 'code' => T_YIELD_FROM, + 'type' => 'T_YIELD_FROM', + 'content' => substr($token[1], 0, 5), + ]; + $newStackPtr++; + + $tokenLines = explode($this->eolChar, substr($token[1], 5, -4)); + $numLines = count($tokenLines); + $newToken = [ + 'type' => 'T_WHITESPACE', + 'code' => T_WHITESPACE, + 'content' => '', + ]; + + foreach ($tokenLines as $i => $line) { + $newToken['content'] = $line; + if ($i === ($numLines - 1)) { + if ($line === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + + $finalTokens[$newStackPtr] = [ + 'code' => T_YIELD_FROM, + 'type' => 'T_YIELD_FROM', + 'content' => substr($token[1], -4), + ]; + $newStackPtr++; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr split into 'yield', one or more whitespace tokens and 'from'".PHP_EOL; + } + + continue; + } else if (PHP_VERSION_ID >= 80300 + && $tokenIsArray === true + && $token[0] === T_YIELD_FROM + && preg_match('`^yield[ \t]+from$`i', $token[1]) !== 1 + && stripos($token[1], 'yield') === 0 + ) { + /* + Since PHP 8.3, "yield from" allows for comments and will + swallow the comment in the `T_YIELD_FROM` token. + We need to split this up to allow for sniffs handling comments. + */ + + $finalTokens[$newStackPtr] = [ + 'code' => T_YIELD_FROM, + 'type' => 'T_YIELD_FROM', + 'content' => substr($token[1], 0, 5), + ]; + $newStackPtr++; + + $yieldFromSubtokens = @token_get_all(" T_YIELD_FROM, + 1 => substr($token[1], -4), + ]; + + // Inject the new tokens into the token stack. + array_splice($tokens, ($stackPtr + 1), 0, $yieldFromSubtokens); + $numTokens = count($tokens); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr split into parts (yield from with comment)".PHP_EOL; + } + + unset($yieldFromSubtokens); + continue; + }//end if + + /* + Before PHP 5.6, the ... operator was tokenized as three + T_STRING_CONCAT tokens in a row. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '.' + && isset($tokens[($stackPtr + 1)]) === true + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 1)] === '.' + && $tokens[($stackPtr + 2)] === '.' + ) { + $newToken = []; + $newToken['code'] = T_ELLIPSIS; + $newToken['type'] = 'T_ELLIPSIS'; + $newToken['content'] = '...'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr += 2; + continue; + } + + /* + Before PHP 5.6, the ** operator was tokenized as two + T_MULTIPLY tokens in a row. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '*' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)] === '*' + ) { + $newToken = []; + $newToken['code'] = T_POW; + $newToken['type'] = 'T_POW'; + $newToken['content'] = '**'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 5.6, the **= operator was tokenized as + T_MULTIPLY followed by T_MUL_EQUAL. So look for and combine + these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '*' + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][1] === '*=' + ) { + $newToken = []; + $newToken['code'] = T_POW_EQUAL; + $newToken['type'] = 'T_POW_EQUAL'; + $newToken['content'] = '**='; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 7, the ??= operator was tokenized as + T_INLINE_THEN, T_INLINE_THEN, T_EQUAL. + Between PHP 7.0 and 7.3, the ??= operator was tokenized as + T_COALESCE, T_EQUAL. + So look for and combine these tokens in earlier versions. + */ + + if (($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '?' + && isset($tokens[($stackPtr + 2)]) === true + && $tokens[($stackPtr + 2)][0] === '=') + || ($tokenIsArray === true + && $token[0] === T_COALESCE + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '=') + ) { + $newToken = []; + $newToken['code'] = T_COALESCE_EQUAL; + $newToken['type'] = 'T_COALESCE_EQUAL'; + $newToken['content'] = '??='; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + + if ($tokenIsArray === false) { + // Pre PHP 7. + $stackPtr++; + } + + continue; + } + + /* + Before PHP 7, the ?? operator was tokenized as + T_INLINE_THEN followed by T_INLINE_THEN. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '?' + ) { + $newToken = []; + $newToken['code'] = T_COALESCE; + $newToken['type'] = 'T_COALESCE'; + $newToken['content'] = '??'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 8, the ?-> operator was tokenized as + T_INLINE_THEN followed by T_OBJECT_OPERATOR. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === false + && $token[0] === '?' + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_OBJECT_OPERATOR + ) { + $newToken = []; + $newToken['code'] = T_NULLSAFE_OBJECT_OPERATOR; + $newToken['type'] = 'T_NULLSAFE_OBJECT_OPERATOR'; + $newToken['content'] = '?->'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + Before PHP 7.4, underscores inside T_LNUMBER and T_DNUMBER + tokens split the token with a T_STRING. So look for + and change these tokens in earlier versions. + */ + + if (PHP_VERSION_ID < 70400 + && ($tokenIsArray === true + && ($token[0] === T_LNUMBER + || $token[0] === T_DNUMBER) + && isset($tokens[($stackPtr + 1)]) === true + && is_array($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === T_STRING + && $tokens[($stackPtr + 1)][1][0] === '_') + ) { + $newContent = $token[1]; + $newType = $token[0]; + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false) { + break; + } + + if ($tokens[$i][0] === T_LNUMBER + || $tokens[$i][0] === T_DNUMBER + ) { + $newContent .= $tokens[$i][1]; + continue; + } + + if ($tokens[$i][0] === T_STRING + && $tokens[$i][1][0] === '_' + && ((strpos($newContent, '0x') === 0 + && preg_match('`^((? PHP_INT_MAX) + || (stripos($newContent, '0b') === 0 && bindec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (stripos($newContent, '0o') === 0 && octdec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (stripos($newContent, '0x') !== 0 + && (stripos($newContent, 'e') !== false || strpos($newContent, '.') !== false)) + || (strpos($newContent, '0') === 0 && stripos($newContent, '0x') !== 0 + && stripos($newContent, '0b') !== 0 && octdec(str_replace('_', '', $newContent)) > PHP_INT_MAX) + || (strpos($newContent, '0') !== 0 && str_replace('_', '', $newContent) > PHP_INT_MAX)) + ) { + $newType = T_DNUMBER; + } + + $newToken = []; + $newToken['code'] = $newType; + $newToken['type'] = Tokens::tokenName($newType); + $newToken['content'] = $newContent; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr = ($i - 1); + continue; + }//end if + + /* + Backfill the T_MATCH token for PHP versions < 8.0 and + do initial correction for non-match expression T_MATCH tokens + to T_STRING for PHP >= 8.0. + A final check for non-match expression T_MATCH tokens is done + in PHP::processAdditional(). + */ + + if ($tokenIsArray === true + && (($token[0] === T_STRING + && strtolower($token[1]) === 'match') + || $token[0] === T_MATCH) + ) { + $isMatch = false; + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (isset($tokens[$x][0], Tokens::$emptyTokens[$tokens[$x][0]]) === true) { + continue; + } + + if ($tokens[$x] !== '(') { + // This is not a match expression. + break; + } + + if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true) { + // Also not a match expression. + break; + } + + $isMatch = true; + break; + }//end for + + if ($isMatch === true && $token[0] === T_STRING) { + $newToken = []; + $newToken['code'] = T_MATCH; + $newToken['type'] = 'T_MATCH'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_MATCH".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + } else if ($isMatch === false && $token[0] === T_MATCH) { + // PHP 8.0, match keyword, but not a match expression. + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_MATCH to T_STRING".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Retokenize the T_DEFAULT in match control structures as T_MATCH_DEFAULT + to prevent scope being set and the scope for switch default statements + breaking. + */ + + if ($tokenIsArray === true + && $token[0] === T_DEFAULT + && isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === false + ) { + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if ($tokens[$x] === ',') { + // Skip over potential trailing comma (supported in PHP). + continue; + } + + if (is_array($tokens[$x]) === false + || isset(Tokens::$emptyTokens[$tokens[$x][0]]) === false + ) { + // Non-empty, non-comma content. + break; + } + } + + if (isset($tokens[$x]) === true + && is_array($tokens[$x]) === true + && $tokens[$x][0] === T_DOUBLE_ARROW + ) { + // Modify the original token stack for the double arrow so that + // future checks can disregard the double arrow token more easily. + // For match expression "case" statements, this is handled + // in PHP::processAdditional(). + $tokens[$x][0] = T_MATCH_ARROW; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + } + + $newToken = []; + $newToken['code'] = T_MATCH_DEFAULT; + $newToken['type'] = 'T_MATCH_DEFAULT'; + $newToken['content'] = $token[1]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + }//end if + + /* + Convert ? to T_NULLABLE OR T_INLINE_THEN + */ + + if ($tokenIsArray === false && $token[0] === '?') { + $newToken = []; + $newToken['content'] = '?'; + + // For typed constants, we only need to check the token before the ? to be sure. + if ($finalTokens[$lastNotEmptyToken]['code'] === T_CONST) { + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + } + + /* + * Check if the next non-empty token is one of the tokens which can be used + * in type declarations. If not, it's definitely a ternary. + * At this point, the only token types which need to be taken into consideration + * as potential type declarations are identifier names, T_ARRAY, T_CALLABLE and T_NS_SEPARATOR. + */ + + $lastRelevantNonEmpty = null; + + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if (isset(Tokens::$emptyTokens[$tokenType]) === true) { + continue; + } + + if ($tokenType === T_STRING + || $tokenType === T_NAME_FULLY_QUALIFIED + || $tokenType === T_NAME_RELATIVE + || $tokenType === T_NAME_QUALIFIED + || $tokenType === T_ARRAY + || $tokenType === T_NAMESPACE + || $tokenType === T_NS_SEPARATOR + ) { + $lastRelevantNonEmpty = $tokenType; + continue; + } + + if (($tokenType !== T_CALLABLE + && isset($lastRelevantNonEmpty) === false) + || ($lastRelevantNonEmpty === T_ARRAY + && $tokenType === '(') + || (($lastRelevantNonEmpty === T_STRING + || $lastRelevantNonEmpty === T_NAME_FULLY_QUALIFIED + || $lastRelevantNonEmpty === T_NAME_RELATIVE + || $lastRelevantNonEmpty === T_NAME_QUALIFIED) + && ($tokenType === T_DOUBLE_COLON + || $tokenType === '(' + || $tokenType === ':')) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + } + + $newToken['code'] = T_INLINE_THEN; + $newToken['type'] = 'T_INLINE_THEN'; + + $insideInlineIf[] = $stackPtr; + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue 2; + } + + break; + }//end for + + /* + * This can still be a nullable type or a ternary. + * Do additional checking. + */ + + $prevNonEmpty = null; + $lastSeenNonEmpty = null; + + for ($i = ($stackPtr - 1); $i >= 0; $i--) { + if (is_array($tokens[$i]) === true) { + $tokenType = $tokens[$i][0]; + } else { + $tokenType = $tokens[$i]; + } + + if ($tokenType === T_STATIC + && ($lastSeenNonEmpty === T_DOUBLE_COLON + || $lastSeenNonEmpty === '(') + ) { + $lastSeenNonEmpty = $tokenType; + continue; + } + + if ($prevNonEmpty === null + && isset(Tokens::$emptyTokens[$tokenType]) === false + ) { + // Found the previous non-empty token. + if ($tokenType === ':' || $tokenType === ',' || $tokenType === T_ATTRIBUTE_END) { + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + break; + } + + $prevNonEmpty = $tokenType; + } + + if ($tokenType === T_FUNCTION + || $tokenType === T_FN + || isset(Tokens::$methodPrefixes[$tokenType]) === true + || $tokenType === T_VAR + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + } + + $newToken['code'] = T_NULLABLE; + $newToken['type'] = 'T_NULLABLE'; + break; + } else if (in_array($tokenType, [T_DOUBLE_ARROW, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, '=', '{', ';'], true) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + } + + $newToken['code'] = T_INLINE_THEN; + $newToken['type'] = 'T_INLINE_THEN'; + + $insideInlineIf[] = $stackPtr; + break; + } + + if (isset(Tokens::$emptyTokens[$tokenType]) === false) { + $lastSeenNonEmpty = $tokenType; + } + }//end for + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + continue; + }//end if + + /* + Tokens after a double colon may look like scope openers, + such as when writing code like Foo::NAMESPACE, but they are + only ever variables or strings. + */ + + if ($stackPtr > 1 + && (is_array($tokens[($stackPtr - 1)]) === true + && $tokens[($stackPtr - 1)][0] === T_PAAMAYIM_NEKUDOTAYIM) + && $tokenIsArray === true + && $token[0] !== T_STRING + && $token[0] !== T_VARIABLE + && $token[0] !== T_DOLLAR + && isset(Tokens::$emptyTokens[$token[0]]) === false + ) { + $newToken = []; + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + $newToken['content'] = $token[1]; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + continue; + } + + /* + Backfill the T_FN token for PHP versions < 7.4. + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && strtolower($token[1]) === 'fn' + ) { + // Modify the original token stack so that + // future checks (like looking for T_NULLABLE) can + // detect the T_FN token more easily. + $tokens[$stackPtr][0] = T_FN; + $token[0] = T_FN; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_FN".PHP_EOL; + } + } + + /* + This is a special condition for T_ARRAY tokens used for + function return types. We want to keep the parenthesis map clean, + so let's tag these tokens as T_STRING. + */ + + if ($tokenIsArray === true + && ($token[0] === T_FUNCTION + || $token[0] === T_FN) + && $finalTokens[$lastNotEmptyToken]['code'] !== T_USE + ) { + // Go looking for the colon to start the return type hint. + // Start by finding the closing parenthesis of the function. + $parenthesisStack = []; + $parenthesisCloser = false; + for ($x = ($stackPtr + 1); $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false && $tokens[$x] === '(') { + $parenthesisStack[] = $x; + } else if (is_array($tokens[$x]) === false && $tokens[$x] === ')') { + array_pop($parenthesisStack); + if (empty($parenthesisStack) === true) { + $parenthesisCloser = $x; + break; + } + } + } + + if ($parenthesisCloser !== false) { + for ($x = ($parenthesisCloser + 1); $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false + || isset(Tokens::$emptyTokens[$tokens[$x][0]]) === false + ) { + // Non-empty content. + if (is_array($tokens[$x]) === true && $tokens[$x][0] === T_USE) { + // Found a use statements, so search ahead for the closing parenthesis. + for ($x += 1; $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === false && $tokens[$x] === ')') { + continue(2); + } + } + } + + break; + } + } + + if (isset($tokens[$x]) === true + && is_array($tokens[$x]) === false + && $tokens[$x] === ':' + ) { + // Find the start of the return type. + for ($x += 1; $x < $numTokens; $x++) { + if (is_array($tokens[$x]) === true + && isset(Tokens::$emptyTokens[$tokens[$x][0]]) === true + ) { + // Whitespace or comments before the return type. + continue; + } + + if (is_array($tokens[$x]) === false && $tokens[$x] === '?') { + // Found a nullable operator, so skip it. + // But also convert the token to save the tokenizer + // a bit of time later on. + $tokens[$x] = [ + T_NULLABLE, + '?', + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from ? to T_NULLABLE".PHP_EOL; + } + + continue; + } + + break; + }//end for + }//end if + }//end if + }//end if + + /* + Before PHP 7, the <=> operator was tokenized as + T_IS_SMALLER_OR_EQUAL followed by T_GREATER_THAN. + So look for and combine these tokens in earlier versions. + */ + + if ($tokenIsArray === true + && $token[0] === T_IS_SMALLER_OR_EQUAL + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)][0] === '>' + ) { + $newToken = []; + $newToken['code'] = T_SPACESHIP; + $newToken['type'] = 'T_SPACESHIP'; + $newToken['content'] = '<=>'; + $finalTokens[$newStackPtr] = $newToken; + + $newStackPtr++; + $stackPtr++; + continue; + } + + /* + PHP doesn't assign a token to goto labels, so we have to. + These are just string tokens with a single colon after them. Double + colons are already tokenized and so don't interfere with this check. + But we do have to account for CASE statements, that look just like + goto labels. + */ + + if ($tokenIsArray === true + && $token[0] === T_STRING + && isset($tokens[($stackPtr + 1)]) === true + && $tokens[($stackPtr + 1)] === ':' + && (is_array($tokens[($stackPtr - 1)]) === false + || $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM) + ) { + $stopTokens = [ + T_CASE => true, + T_SEMICOLON => true, + T_OPEN_TAG => true, + T_OPEN_CURLY_BRACKET => true, + T_INLINE_THEN => true, + T_ENUM => true, + ]; + + for ($x = ($newStackPtr - 1); $x > 0; $x--) { + if (isset($stopTokens[$finalTokens[$x]['code']]) === true) { + break; + } + } + + if ($finalTokens[$x]['code'] !== T_CASE + && $finalTokens[$x]['code'] !== T_INLINE_THEN + && $finalTokens[$x]['code'] !== T_ENUM + ) { + $finalTokens[$newStackPtr] = [ + 'content' => $token[1].':', + 'code' => T_GOTO_LABEL, + 'type' => 'T_GOTO_LABEL', + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $stackPtr changed from T_STRING to T_GOTO_LABEL".PHP_EOL; + echo "\t\t* skipping T_COLON token ".($stackPtr + 1).PHP_EOL; + } + + $newStackPtr++; + $stackPtr++; + continue; + } + }//end if + + /* + If this token has newlines in its content, split each line up + and create a new token for each line. We do this so it's easier + to ascertain where errors occur on a line. + Note that $token[1] is the token's content. + */ + + if ($tokenIsArray === true && strpos($token[1], $this->eolChar) !== false) { + $tokenLines = explode($this->eolChar, $token[1]); + $numLines = count($tokenLines); + $newToken = [ + 'type' => Tokens::tokenName($token[0]), + 'code' => $token[0], + 'content' => '', + ]; + + for ($i = 0; $i < $numLines; $i++) { + $newToken['content'] = $tokenLines[$i]; + if ($i === ($numLines - 1)) { + if ($tokenLines[$i] === '') { + break; + } + } else { + $newToken['content'] .= $this->eolChar; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + } + } else { + // Some T_STRING tokens should remain that way due to their context. + if ($tokenIsArray === true && $token[0] === T_STRING) { + $preserveTstring = false; + + // True/false/parent/self/static in typed constants should be fixed to their own token, + // but the constant name should not be. + if ((isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + && $finalTokens[$lastNotEmptyToken]['code'] === T_CONST) + || $insideConstDeclaration === true + ) { + // Find the next non-empty token. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true + && isset(Tokens::$emptyTokens[$tokens[$i][0]]) === true + ) { + continue; + } + + break; + } + + if ($tokens[$i] === '=') { + $preserveTstring = true; + $insideConstDeclaration = false; + } + } else if (isset($this->tstringContexts[$finalTokens[$lastNotEmptyToken]['code']]) === true + && $finalTokens[$lastNotEmptyToken]['code'] !== T_CONST + ) { + $preserveTstring = true; + + // Special case for syntax like: return new self/new parent + // where self/parent should not be a string. + $tokenContentLower = strtolower($token[1]); + if ($finalTokens[$lastNotEmptyToken]['code'] === T_NEW + && ($tokenContentLower === 'self' || $tokenContentLower === 'parent') + ) { + $preserveTstring = false; + } + } else if ($finalTokens[$lastNotEmptyToken]['content'] === '&') { + // Function names for functions declared to return by reference. + for ($i = ($lastNotEmptyToken - 1); $i >= 0; $i--) { + if (isset(Tokens::$emptyTokens[$finalTokens[$i]['code']]) === true) { + continue; + } + + if ($finalTokens[$i]['code'] === T_FUNCTION) { + $preserveTstring = true; + } + + break; + } + } else { + // Keywords with special PHPCS token when used as a function call. + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === true + && isset(Tokens::$emptyTokens[$tokens[$i][0]]) === true + ) { + continue; + } + + if ($tokens[$i][0] === '(') { + $preserveTstring = true; + } + + break; + } + }//end if + + if ($preserveTstring === true) { + $finalTokens[$newStackPtr] = [ + 'code' => T_STRING, + 'type' => 'T_STRING', + 'content' => $token[1], + ]; + + $newStackPtr++; + continue; + } + }//end if + + $newToken = null; + if ($tokenIsArray === false) { + if (isset(self::$resolveTokenCache[$token[0]]) === true) { + $newToken = self::$resolveTokenCache[$token[0]]; + } + } else { + $cacheKey = null; + if ($token[0] === T_STRING) { + $cacheKey = strtolower($token[1]); + } else if ($token[0] !== T_CURLY_OPEN) { + $cacheKey = $token[0]; + } + + if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) { + $newToken = self::$resolveTokenCache[$cacheKey]; + $newToken['content'] = $token[1]; + } + } + + if ($newToken === null) { + $newToken = self::standardiseToken($token); + } + + // Convert colons that are actually the ELSE component of an + // inline IF statement. + if (empty($insideInlineIf) === false && $newToken['code'] === T_COLON) { + $isInlineIf = true; + + // Make sure this isn't a named parameter label. + // Get the previous non-empty token. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || isset(Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + break; + } + } + + if ($tokens[$i][0] === T_PARAM_NAME) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is parameter label, not T_INLINE_ELSE".PHP_EOL; + } + } + + if ($isInlineIf === true) { + // Make sure this isn't a return type separator. + for ($i = ($stackPtr - 1); $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || ($tokens[$i][0] !== T_DOC_COMMENT + && $tokens[$i][0] !== T_COMMENT + && $tokens[$i][0] !== T_WHITESPACE) + ) { + break; + } + } + + if ($tokens[$i] === ')') { + $parenCount = 1; + for ($i--; $i > 0; $i--) { + if ($tokens[$i] === '(') { + $parenCount--; + if ($parenCount === 0) { + break; + } + } else if ($tokens[$i] === ')') { + $parenCount++; + } + } + + // We've found the open parenthesis, so if the previous + // non-empty token is FUNCTION or USE, this is a return type. + // Note that we need to skip T_STRING tokens here as these + // can be function names. + for ($i--; $i > 0; $i--) { + if (is_array($tokens[$i]) === false + || ($tokens[$i][0] !== T_DOC_COMMENT + && $tokens[$i][0] !== T_COMMENT + && $tokens[$i][0] !== T_WHITESPACE + && $tokens[$i][0] !== T_STRING) + ) { + break; + } + } + + if ($tokens[$i][0] === T_FUNCTION || $tokens[$i][0] === T_FN || $tokens[$i][0] === T_USE) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is return type, not T_INLINE_ELSE".PHP_EOL; + } + } + }//end if + }//end if + + // Check to see if this is a CASE or DEFAULT opener. + if ($isInlineIf === true) { + $inlineIfToken = $insideInlineIf[(count($insideInlineIf) - 1)]; + for ($i = $stackPtr; $i > $inlineIfToken; $i--) { + if (is_array($tokens[$i]) === true + && ($tokens[$i][0] === T_CASE + || $tokens[$i][0] === T_DEFAULT) + ) { + $isInlineIf = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token is T_CASE or T_DEFAULT opener, not T_INLINE_ELSE".PHP_EOL; + } + + break; + } + + if (is_array($tokens[$i]) === false + && ($tokens[$i] === ';' + || $tokens[$i] === '{' + || $tokens[$i] === '}') + ) { + break; + } + }//end for + }//end if + + if ($isInlineIf === true) { + array_pop($insideInlineIf); + $newToken['code'] = T_INLINE_ELSE; + $newToken['type'] = 'T_INLINE_ELSE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token changed from T_COLON to T_INLINE_ELSE".PHP_EOL; + } + } + }//end if + + // This is a special condition for T_ARRAY tokens used for anything else + // but array declarations, like type hinting function arguments as + // being arrays. + // We want to keep the parenthesis map clean, so let's tag these tokens as + // T_STRING. + if ($newToken['code'] === T_ARRAY) { + for ($i = ($stackPtr + 1); $i < $numTokens; $i++) { + if (is_array($tokens[$i]) === false + || isset(Tokens::$emptyTokens[$tokens[$i][0]]) === false + ) { + // Non-empty content. + break; + } + } + + if ($i !== $numTokens && $tokens[$i] !== '(') { + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + } + } + + // This is a special case when checking PHP 5.5+ code in PHP < 5.5 + // where "finally" should be T_FINALLY instead of T_STRING. + if ($newToken['code'] === T_STRING + && strtolower($newToken['content']) === 'finally' + && $finalTokens[$lastNotEmptyToken]['code'] === T_CLOSE_CURLY_BRACKET + ) { + $newToken['code'] = T_FINALLY; + $newToken['type'] = 'T_FINALLY'; + } + + // This is a special case for PHP 5.6 use function and use const + // where "function" and "const" should be T_STRING instead of T_FUNCTION + // and T_CONST. + if (($newToken['code'] === T_FUNCTION + || $newToken['code'] === T_CONST) + && ($finalTokens[$lastNotEmptyToken]['code'] === T_USE || $insideUseGroup === true) + ) { + $newToken['code'] = T_STRING; + $newToken['type'] = 'T_STRING'; + } + + // This is a special case for use groups in PHP 7+ where leaving + // the curly braces as their normal tokens would confuse + // the scope map and sniffs. + if ($newToken['code'] === T_OPEN_CURLY_BRACKET + && $finalTokens[$lastNotEmptyToken]['code'] === T_NS_SEPARATOR + ) { + $newToken['code'] = T_OPEN_USE_GROUP; + $newToken['type'] = 'T_OPEN_USE_GROUP'; + $insideUseGroup = true; + } + + if ($insideUseGroup === true && $newToken['code'] === T_CLOSE_CURLY_BRACKET) { + $newToken['code'] = T_CLOSE_USE_GROUP; + $newToken['type'] = 'T_CLOSE_USE_GROUP'; + $insideUseGroup = false; + } + + $finalTokens[$newStackPtr] = $newToken; + $newStackPtr++; + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END PHP TOKENIZING ***".PHP_EOL; + } + + return $finalTokens; + + }//end tokenize() + + + /** + * Performs additional processing after main tokenizing. + * + * This additional processing checks for CASE statements that are using curly + * braces for scope openers and closers. It also turns some T_FUNCTION tokens + * into T_CLOSURE when they are not standard function definitions. It also + * detects short array syntax and converts those square brackets into new tokens. + * It also corrects some usage of the static and class keywords. It also + * assigns tokens to function return types. + * + * @return void + */ + protected function processAdditional() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL; + } + + $this->createAttributesNestingMap(); + + $numTokens = count($this->tokens); + $lastSeenTypeToken = $numTokens; + + for ($i = ($numTokens - 1); $i >= 0; $i--) { + // Check for any unset scope conditions due to alternate IF/ENDIF syntax. + if (isset($this->tokens[$i]['scope_opener']) === true + && isset($this->tokens[$i]['scope_condition']) === false + ) { + $this->tokens[$i]['scope_condition'] = $this->tokens[$this->tokens[$i]['scope_opener']]['scope_condition']; + } + + if ($this->tokens[$i]['code'] === T_FUNCTION) { + /* + Detect functions that are actually closures and + assign them a different token. + */ + + if (isset($this->tokens[$i]['scope_opener']) === true) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false + && $this->tokens[$x]['code'] !== T_BITWISE_AND + ) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$i]['code'] = T_CLOSURE; + $this->tokens[$i]['type'] = 'T_CLOSURE'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL; + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_CLOSURE; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_CLASS && isset($this->tokens[$i]['scope_opener']) === true) { + /* + Detect anonymous classes and assign them a different token. + */ + + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + || $this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET + || $this->tokens[$x]['code'] === T_EXTENDS + || $this->tokens[$x]['code'] === T_IMPLEMENTS + ) { + $this->tokens[$i]['code'] = T_ANON_CLASS; + $this->tokens[$i]['type'] = 'T_ANON_CLASS'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL; + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + && isset($this->tokens[$x]['parenthesis_closer']) === true + ) { + $closer = $this->tokens[$x]['parenthesis_closer']; + + $this->tokens[$i]['parenthesis_opener'] = $x; + $this->tokens[$i]['parenthesis_closer'] = $closer; + $this->tokens[$i]['parenthesis_owner'] = $i; + $this->tokens[$x]['parenthesis_owner'] = $i; + $this->tokens[$closer]['parenthesis_owner'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t\t* added parenthesis keys to T_ANON_CLASS token $i on line $line".PHP_EOL; + } + } + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($this->tokens[$x]['conditions'][$i]) === false) { + continue; + } + + $this->tokens[$x]['conditions'][$i] = T_ANON_CLASS; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + } + } + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_FN && isset($this->tokens[($i + 1)]) === true) { + // Possible arrow function. + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false + && $this->tokens[$x]['code'] !== T_BITWISE_AND + ) { + // Non-whitespace content. + break; + } + } + + if (isset($this->tokens[$x]) === true && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $ignore = Tokens::$emptyTokens; + $ignore += [ + T_ARRAY => T_ARRAY, + T_CALLABLE => T_CALLABLE, + T_COLON => T_COLON, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + T_NULL => T_NULL, + T_TRUE => T_TRUE, + T_FALSE => T_FALSE, + T_NULLABLE => T_NULLABLE, + T_PARENT => T_PARENT, + T_SELF => T_SELF, + T_STATIC => T_STATIC, + T_STRING => T_STRING, + T_TYPE_UNION => T_TYPE_UNION, + T_TYPE_INTERSECTION => T_TYPE_INTERSECTION, + T_TYPE_OPEN_PARENTHESIS => T_TYPE_OPEN_PARENTHESIS, + T_TYPE_CLOSE_PARENTHESIS => T_TYPE_CLOSE_PARENTHESIS, + ]; + + $closer = $this->tokens[$x]['parenthesis_closer']; + for ($arrow = ($closer + 1); $arrow < $numTokens; $arrow++) { + if (isset($ignore[$this->tokens[$arrow]['code']]) === false) { + break; + } + } + + if ($this->tokens[$arrow]['code'] === T_DOUBLE_ARROW) { + $endTokens = [ + T_COLON => true, + T_COMMA => true, + T_SEMICOLON => true, + T_CLOSE_PARENTHESIS => true, + T_CLOSE_SQUARE_BRACKET => true, + T_CLOSE_CURLY_BRACKET => true, + T_CLOSE_SHORT_ARRAY => true, + T_OPEN_TAG => true, + T_CLOSE_TAG => true, + ]; + + $inTernary = false; + $lastEndToken = null; + + for ($scopeCloser = ($arrow + 1); $scopeCloser < $numTokens; $scopeCloser++) { + // Arrow function closer should never be shared with the closer of a match + // control structure. + if (isset($this->tokens[$scopeCloser]['scope_closer'], $this->tokens[$scopeCloser]['scope_condition']) === true + && $scopeCloser === $this->tokens[$scopeCloser]['scope_closer'] + && $this->tokens[$this->tokens[$scopeCloser]['scope_condition']]['code'] === T_MATCH + ) { + if ($arrow < $this->tokens[$scopeCloser]['scope_condition']) { + // Match in return value of arrow function. Move on to the next token. + continue; + } + + // Arrow function as return value for the last match case without trailing comma. + if ($lastEndToken !== null) { + $scopeCloser = $lastEndToken; + break; + } + + for ($lastNonEmpty = ($scopeCloser - 1); $lastNonEmpty > $arrow; $lastNonEmpty--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$lastNonEmpty]['code']]) === false) { + $scopeCloser = $lastNonEmpty; + break 2; + } + } + } + + if (isset($endTokens[$this->tokens[$scopeCloser]['code']]) === true) { + if ($lastEndToken !== null + && ((isset($this->tokens[$scopeCloser]['parenthesis_opener']) === true + && $this->tokens[$scopeCloser]['parenthesis_opener'] < $arrow) + || (isset($this->tokens[$scopeCloser]['bracket_opener']) === true + && $this->tokens[$scopeCloser]['bracket_opener'] < $arrow)) + ) { + for ($lastNonEmpty = ($scopeCloser - 1); $lastNonEmpty > $arrow; $lastNonEmpty--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$lastNonEmpty]['code']]) === false) { + $scopeCloser = $lastNonEmpty; + break; + } + } + } + + break; + } + + if ($inTernary === false + && isset($this->tokens[$scopeCloser]['scope_closer'], $this->tokens[$scopeCloser]['scope_condition']) === true + && $scopeCloser === $this->tokens[$scopeCloser]['scope_closer'] + && $this->tokens[$this->tokens[$scopeCloser]['scope_condition']]['code'] === T_FN + ) { + // Found a nested arrow function that already has the closer set and is in + // the same scope as us, so we can use its closer. + break; + } + + if (isset($this->tokens[$scopeCloser]['scope_closer']) === true + && $this->tokens[$scopeCloser]['code'] !== T_INLINE_ELSE + && $this->tokens[$scopeCloser]['code'] !== T_END_HEREDOC + && $this->tokens[$scopeCloser]['code'] !== T_END_NOWDOC + ) { + // We minus 1 here in case the closer can be shared with us. + $scopeCloser = ($this->tokens[$scopeCloser]['scope_closer'] - 1); + continue; + } + + if (isset($this->tokens[$scopeCloser]['parenthesis_closer']) === true) { + $scopeCloser = $this->tokens[$scopeCloser]['parenthesis_closer']; + $lastEndToken = $scopeCloser; + continue; + } + + if (isset($this->tokens[$scopeCloser]['bracket_closer']) === true) { + $scopeCloser = $this->tokens[$scopeCloser]['bracket_closer']; + $lastEndToken = $scopeCloser; + continue; + } + + if ($this->tokens[$scopeCloser]['code'] === T_INLINE_THEN) { + $inTernary = true; + continue; + } + + if ($this->tokens[$scopeCloser]['code'] === T_INLINE_ELSE) { + if ($inTernary === false) { + break; + } + + $inTernary = false; + continue; + } + }//end for + + if ($scopeCloser !== $numTokens) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t=> token $i on line $line processed as arrow function".PHP_EOL; + echo "\t\t* scope opener set to $arrow *".PHP_EOL; + echo "\t\t* scope closer set to $scopeCloser *".PHP_EOL; + echo "\t\t* parenthesis opener set to $x *".PHP_EOL; + echo "\t\t* parenthesis closer set to $closer *".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_FN; + $this->tokens[$i]['type'] = 'T_FN'; + $this->tokens[$i]['scope_condition'] = $i; + $this->tokens[$i]['scope_opener'] = $arrow; + $this->tokens[$i]['scope_closer'] = $scopeCloser; + $this->tokens[$i]['parenthesis_owner'] = $i; + $this->tokens[$i]['parenthesis_opener'] = $x; + $this->tokens[$i]['parenthesis_closer'] = $closer; + + $this->tokens[$arrow]['code'] = T_FN_ARROW; + $this->tokens[$arrow]['type'] = 'T_FN_ARROW'; + + $this->tokens[$arrow]['scope_condition'] = $i; + $this->tokens[$arrow]['scope_opener'] = $arrow; + $this->tokens[$arrow]['scope_closer'] = $scopeCloser; + $this->tokens[$scopeCloser]['scope_condition'] = $i; + $this->tokens[$scopeCloser]['scope_opener'] = $arrow; + $this->tokens[$scopeCloser]['scope_closer'] = $scopeCloser; + + $opener = $this->tokens[$i]['parenthesis_opener']; + $closer = $this->tokens[$i]['parenthesis_closer']; + $this->tokens[$opener]['parenthesis_owner'] = $i; + $this->tokens[$closer]['parenthesis_owner'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$arrow]['line']; + echo "\t\t* token $arrow on line $line changed from T_DOUBLE_ARROW to T_FN_ARROW".PHP_EOL; + } + }//end if + }//end if + }//end if + + // If after all that, the extra tokens are not set, this is not an arrow function. + if (isset($this->tokens[$i]['scope_closer']) === false) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t=> token $i on line $line is not an arrow function".PHP_EOL; + echo "\t\t* token changed from T_FN to T_STRING".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + } + } else if ($this->tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) { + if (isset($this->tokens[$i]['bracket_closer']) === false) { + continue; + } + + // Unless there is a variable or a bracket before this token, + // it is the start of an array being defined using the short syntax. + $isShortArray = false; + $allowed = [ + T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + T_VARIABLE => T_VARIABLE, + T_OBJECT_OPERATOR => T_OBJECT_OPERATOR, + T_NULLSAFE_OBJECT_OPERATOR => T_NULLSAFE_OBJECT_OPERATOR, + T_STRING => T_STRING, + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + $allowed += Tokens::$magicConstants; + + for ($x = ($i - 1); $x >= 0; $x--) { + // If we hit a scope opener, the statement has ended + // without finding anything, so it's probably an array + // using PHP 7.1 short list syntax. + if (isset($this->tokens[$x]['scope_opener']) === true) { + $isShortArray = true; + break; + } + + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Allow for control structures without braces. + if (($this->tokens[$x]['code'] === T_CLOSE_PARENTHESIS + && isset($this->tokens[$x]['parenthesis_owner']) === true + && isset(Tokens::$scopeOpeners[$this->tokens[$this->tokens[$x]['parenthesis_owner']]['code']]) === true) + || isset($allowed[$this->tokens[$x]['code']]) === false + ) { + $isShortArray = true; + } + + break; + } + }//end for + + if ($isShortArray === true) { + $this->tokens[$i]['code'] = T_OPEN_SHORT_ARRAY; + $this->tokens[$i]['type'] = 'T_OPEN_SHORT_ARRAY'; + + $closer = $this->tokens[$i]['bracket_closer']; + $this->tokens[$closer]['code'] = T_CLOSE_SHORT_ARRAY; + $this->tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY'; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL; + $line = $this->tokens[$closer]['line']; + echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_MATCH) { + if (isset($this->tokens[$i]['scope_opener'], $this->tokens[$i]['scope_closer']) === false) { + // Not a match expression after all. + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $i changed from T_MATCH to T_STRING".PHP_EOL; + } + + if (isset($this->tokens[$i]['parenthesis_opener'], $this->tokens[$i]['parenthesis_closer']) === true) { + $opener = $this->tokens[$i]['parenthesis_opener']; + $closer = $this->tokens[$i]['parenthesis_closer']; + unset( + $this->tokens[$opener]['parenthesis_owner'], + $this->tokens[$closer]['parenthesis_owner'] + ); + unset( + $this->tokens[$i]['parenthesis_opener'], + $this->tokens[$i]['parenthesis_closer'], + $this->tokens[$i]['parenthesis_owner'] + ); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* cleaned parenthesis of token $i *".PHP_EOL; + } + } + } else { + // Retokenize the double arrows for match expression cases to `T_MATCH_ARROW`. + $searchFor = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + ]; + $searchFor += Tokens::$scopeOpeners; + + for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { + if (isset($searchFor[$this->tokens[$x]['code']]) === false) { + continue; + } + + if (isset($this->tokens[$x]['scope_closer']) === true) { + $x = $this->tokens[$x]['scope_closer']; + continue; + } + + if (isset($this->tokens[$x]['parenthesis_closer']) === true) { + $x = $this->tokens[$x]['parenthesis_closer']; + continue; + } + + if (isset($this->tokens[$x]['bracket_closer']) === true) { + $x = $this->tokens[$x]['bracket_closer']; + continue; + } + + // This must be a double arrow, but make sure anyhow. + if ($this->tokens[$x]['code'] === T_DOUBLE_ARROW) { + $this->tokens[$x]['code'] = T_MATCH_ARROW; + $this->tokens[$x]['type'] = 'T_MATCH_ARROW'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + } + } + }//end for + }//end if + + continue; + } else if ($this->tokens[$i]['code'] === T_BITWISE_OR + || $this->tokens[$i]['code'] === T_BITWISE_AND + || $this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS + ) { + if ($lastSeenTypeToken < $i) { + // We've already examined this code to check if it is a type declaration and concluded it wasn't. + // No need to do it again. + continue; + } + + /* + Convert "|" to T_TYPE_UNION or leave as T_BITWISE_OR. + Convert "&" to T_TYPE_INTERSECTION or leave as T_BITWISE_AND. + Convert "(" and ")" to T_TYPE_(OPEN|CLOSE)_PARENTHESIS or leave as T_(OPEN|CLOSE)_PARENTHESIS. + + All type related tokens will be converted in one go as soon as this section is hit. + */ + + $allowed = [ + T_STRING => T_STRING, + T_CALLABLE => T_CALLABLE, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + T_FALSE => T_FALSE, + T_TRUE => T_TRUE, + T_NULL => T_NULL, + T_NAMESPACE => T_NAMESPACE, + T_NS_SEPARATOR => T_NS_SEPARATOR, + ]; + + $suspectedType = null; + $typeTokenCountAfter = 0; + + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + if (isset($allowed[$this->tokens[$x]['code']]) === true) { + ++$typeTokenCountAfter; + continue; + } + + if (($typeTokenCountAfter > 0 + || ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS + && isset($this->tokens[$i]['parenthesis_owner']) === false)) + && ($this->tokens[$x]['code'] === T_BITWISE_AND + || $this->tokens[$x]['code'] === T_ELLIPSIS) + ) { + // Skip past reference and variadic indicators for parameter types. + continue; + } + + if ($this->tokens[$x]['code'] === T_VARIABLE) { + // Parameter/Property defaults can not contain variables, so this could be a type. + $suspectedType = 'property or parameter'; + break; + } + + if ($this->tokens[$x]['code'] === T_DOUBLE_ARROW) { + // Possible arrow function. + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_SEMICOLON) { + // Possible abstract method or interface method. + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_OPEN_CURLY_BRACKET + && isset($this->tokens[$x]['scope_condition']) === true + && $this->tokens[$this->tokens[$x]['scope_condition']]['code'] === T_FUNCTION + ) { + $suspectedType = 'return'; + break; + } + + if ($this->tokens[$x]['code'] === T_EQUAL) { + // Possible constant declaration, the `T_STRING` name will have been skipped over already. + $suspectedType = 'constant'; + break; + } + + break; + }//end for + + if (($typeTokenCountAfter === 0 + && ($this->tokens[$i]['code'] !== T_CLOSE_PARENTHESIS + || isset($this->tokens[$i]['parenthesis_owner']) === true)) + || isset($suspectedType) === false + ) { + // Definitely not a union, intersection or DNF type, move on. + continue; + } + + if ($suspectedType === 'property or parameter') { + unset($allowed[T_STATIC]); + } + + $typeTokenCountBefore = 0; + $typeOperators = [$i]; + $parenthesesCount = 0; + $confirmed = false; + $maybeNullable = null; + + if ($this->tokens[$i]['code'] === T_OPEN_PARENTHESIS || $this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + ++$parenthesesCount; + } + + for ($x = ($i - 1); $x >= 0; $x--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + if ($suspectedType === 'property or parameter' + && $this->tokens[$x]['code'] === T_STRING + && strtolower($this->tokens[$x]['content']) === 'static' + ) { + // Static keyword followed directly by an open parenthesis for a DNF type. + // This token should be T_STATIC and was incorrectly identified as a function call before. + $this->tokens[$x]['code'] = T_STATIC; + $this->tokens[$x]['type'] = 'T_STATIC'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed back from T_STRING to T_STATIC".PHP_EOL; + } + } + + if ($suspectedType === 'property or parameter' + && $this->tokens[$x]['code'] === T_OPEN_PARENTHESIS + ) { + // We need to prevent the open parenthesis for a function/fn declaration from being retokenized + // to T_TYPE_OPEN_PARENTHESIS if this is the first parameter in the declaration. + if (isset($this->tokens[$x]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$x]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $confirmed = true; + break; + } else { + // This may still be an arrow function which hasn't been handled yet. + for ($y = ($x - 1); $y > 0; $y--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$y]['code']]) === false + && $this->tokens[$y]['code'] !== T_BITWISE_AND + ) { + // Non-whitespace content. + break; + } + } + + if ($this->tokens[$y]['code'] === T_FN) { + $confirmed = true; + break; + } + } + }//end if + + if (isset($allowed[$this->tokens[$x]['code']]) === true) { + ++$typeTokenCountBefore; + continue; + } + + // Union, intersection and DNF types can't use the nullable operator, but be tolerant to parse errors. + if (($typeTokenCountBefore > 0 + || ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS && isset($this->tokens[$x]['parenthesis_owner']) === false)) + && ($this->tokens[$x]['code'] === T_NULLABLE + || $this->tokens[$x]['code'] === T_INLINE_THEN) + ) { + if ($this->tokens[$x]['code'] === T_INLINE_THEN) { + $maybeNullable = $x; + } + + continue; + } + + if ($this->tokens[$x]['code'] === T_BITWISE_OR || $this->tokens[$x]['code'] === T_BITWISE_AND) { + $typeOperators[] = $x; + continue; + } + + if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS || $this->tokens[$x]['code'] === T_CLOSE_PARENTHESIS) { + ++$parenthesesCount; + $typeOperators[] = $x; + continue; + } + + if ($suspectedType === 'return' && $this->tokens[$x]['code'] === T_COLON) { + // Make sure this is the colon for a return type. + for ($y = ($x - 1); $y > 0; $y--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$y]['code']]) === false) { + break; + } + } + + if ($this->tokens[$y]['code'] !== T_CLOSE_PARENTHESIS) { + // Definitely not a union, intersection or DNF return type, move on. + continue 2; + } + + if (isset($this->tokens[$y]['parenthesis_owner']) === true) { + if ($this->tokens[$this->tokens[$y]['parenthesis_owner']]['code'] === T_FUNCTION + || $this->tokens[$this->tokens[$y]['parenthesis_owner']]['code'] === T_CLOSURE + || $this->tokens[$this->tokens[$y]['parenthesis_owner']]['code'] === T_FN + ) { + $confirmed = true; + } + + break; + } + + // Arrow functions may not have the parenthesis_owner set correctly yet. + // Closure use tokens won't be parentheses owners until PHPCS 4.0. + if (isset($this->tokens[$y]['parenthesis_opener']) === true) { + for ($z = ($this->tokens[$y]['parenthesis_opener'] - 1); $z > 0; $z--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$z]['code']]) === false) { + break; + } + } + + if ($this->tokens[$z]['code'] === T_FN || $this->tokens[$z]['code'] === T_USE) { + $confirmed = true; + } + } + + break; + }//end if + + if ($suspectedType === 'constant' && $this->tokens[$x]['code'] === T_CONST) { + $confirmed = true; + break; + } + + if ($suspectedType === 'property or parameter' + && (isset(Tokens::$scopeModifiers[$this->tokens[$x]['code']]) === true + || $this->tokens[$x]['code'] === T_VAR + || $this->tokens[$x]['code'] === T_STATIC + || $this->tokens[$x]['code'] === T_READONLY) + ) { + // This will also confirm constructor property promotion parameters, but that's fine. + $confirmed = true; + } + + break; + }//end for + + // Remember the last token we examined as part of the (non-)"type declaration". + $lastSeenTypeToken = $x; + + if ($confirmed === false + && $suspectedType === 'property or parameter' + && isset($this->tokens[$i]['nested_parenthesis']) === true + ) { + $parens = $this->tokens[$i]['nested_parenthesis']; + $last = end($parens); + + if (isset($this->tokens[$last]['parenthesis_owner']) === true + && $this->tokens[$this->tokens[$last]['parenthesis_owner']]['code'] === T_FUNCTION + ) { + $confirmed = true; + } else { + // No parenthesis owner set, this may be an arrow function which has not yet + // had additional processing done. + if (isset($this->tokens[$last]['parenthesis_opener']) === true) { + for ($x = ($this->tokens[$last]['parenthesis_opener'] - 1); $x >= 0; $x--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } + + break; + } + + if ($this->tokens[$x]['code'] === T_FN) { + for (--$x; $x >= 0; $x--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true + || $this->tokens[$x]['code'] === T_BITWISE_AND + ) { + continue; + } + + break; + } + + if ($this->tokens[$x]['code'] !== T_FUNCTION) { + $confirmed = true; + } + } + }//end if + }//end if + + unset($parens, $last); + }//end if + + if ($confirmed === false || ($parenthesesCount % 2) !== 0) { + // Not a (valid) union, intersection or DNF type after all, move on. + continue; + } + + foreach ($typeOperators as $x) { + if ($this->tokens[$x]['code'] === T_BITWISE_OR) { + $this->tokens[$x]['code'] = T_TYPE_UNION; + $this->tokens[$x]['type'] = 'T_TYPE_UNION'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_BITWISE_OR to T_TYPE_UNION".PHP_EOL; + } + } else if ($this->tokens[$x]['code'] === T_BITWISE_AND) { + $this->tokens[$x]['code'] = T_TYPE_INTERSECTION; + $this->tokens[$x]['type'] = 'T_TYPE_INTERSECTION'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_BITWISE_AND to T_TYPE_INTERSECTION".PHP_EOL; + } + } else if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { + $this->tokens[$x]['code'] = T_TYPE_OPEN_PARENTHESIS; + $this->tokens[$x]['type'] = 'T_TYPE_OPEN_PARENTHESIS'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_OPEN_PARENTHESIS to T_TYPE_OPEN_PARENTHESIS".PHP_EOL; + } + } else if ($this->tokens[$x]['code'] === T_CLOSE_PARENTHESIS) { + $this->tokens[$x]['code'] = T_TYPE_CLOSE_PARENTHESIS; + $this->tokens[$x]['type'] = 'T_TYPE_CLOSE_PARENTHESIS'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$x]['line']; + echo "\t* token $x on line $line changed from T_CLOSE_PARENTHESIS to T_TYPE_CLOSE_PARENTHESIS".PHP_EOL; + } + }//end if + }//end foreach + + if (isset($maybeNullable) === true) { + $this->tokens[$maybeNullable]['code'] = T_NULLABLE; + $this->tokens[$maybeNullable]['type'] = 'T_NULLABLE'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$maybeNullable]['line']; + echo "\t* token $maybeNullable on line $line changed from T_INLINE_THEN to T_NULLABLE".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_STATIC) { + for ($x = ($i - 1); $x > 0; $x--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + break; + } + } + + if ($this->tokens[$x]['code'] === T_INSTANCEOF) { + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL; + } + } + + continue; + } else if ($this->tokens[$i]['code'] === T_TRUE + || $this->tokens[$i]['code'] === T_FALSE + || $this->tokens[$i]['code'] === T_NULL + ) { + for ($x = ($i + 1); $x < $numTokens; $x++) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Non-whitespace content. + break; + } + } + + if ($x !== $numTokens + && isset($this->tstringContexts[$this->tokens[$x]['code']]) === true + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + $type = $this->tokens[$i]['type']; + echo "\t* token $i on line $line changed from $type to T_STRING".PHP_EOL; + } + + $this->tokens[$i]['code'] = T_STRING; + $this->tokens[$i]['type'] = 'T_STRING'; + } + }//end if + + if (($this->tokens[$i]['code'] !== T_CASE + && $this->tokens[$i]['code'] !== T_DEFAULT) + || isset($this->tokens[$i]['scope_opener']) === false + ) { + // Only interested in CASE and DEFAULT statements from here on in. + continue; + } + + $scopeOpener = $this->tokens[$i]['scope_opener']; + $scopeCloser = $this->tokens[$i]['scope_closer']; + + // If the first char after the opener is a curly brace + // and that brace has been ignored, it is actually + // opening this case statement and the opener and closer are + // probably set incorrectly. + for ($x = ($scopeOpener + 1); $x < $numTokens; $x++) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === false) { + // Non-whitespace content. + break; + } + } + + if ($this->tokens[$x]['code'] === T_CASE || $this->tokens[$x]['code'] === T_DEFAULT) { + // Special case for multiple CASE statements that share the same + // closer. Because we are going backwards through the file, this next + // CASE statement is already fixed, so just use its closer and don't + // worry about fixing anything. + $newCloser = $this->tokens[$x]['scope_closer']; + $this->tokens[$i]['scope_closer'] = $newCloser; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + $line = $this->tokens[$i]['line']; + echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + + continue; + } + + if ($this->tokens[$x]['code'] !== T_OPEN_CURLY_BRACKET + || isset($this->tokens[$x]['scope_condition']) === true + ) { + // Not a CASE/DEFAULT with a curly brace opener. + continue; + } + + // The closer for this CASE/DEFAULT should be the closing curly brace and + // not whatever it already is. The opener needs to be the opening curly + // brace so everything matches up. + $newCloser = $this->tokens[$x]['bracket_closer']; + foreach ([$i, $x, $newCloser] as $index) { + $this->tokens[$index]['scope_condition'] = $i; + $this->tokens[$index]['scope_opener'] = $x; + $this->tokens[$index]['scope_closer'] = $newCloser; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$i]['line']; + $tokenType = $this->tokens[$i]['type']; + + $oldType = $this->tokens[$scopeOpener]['type']; + $newType = $this->tokens[$x]['type']; + echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL; + + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + + if ($this->tokens[$scopeOpener]['scope_condition'] === $i) { + unset($this->tokens[$scopeOpener]['scope_condition']); + unset($this->tokens[$scopeOpener]['scope_opener']); + unset($this->tokens[$scopeOpener]['scope_closer']); + } + + if ($this->tokens[$scopeCloser]['scope_condition'] === $i) { + unset($this->tokens[$scopeCloser]['scope_condition']); + unset($this->tokens[$scopeCloser]['scope_opener']); + unset($this->tokens[$scopeCloser]['scope_closer']); + } else { + // We were using a shared closer. All tokens that were + // sharing this closer with us, except for the scope condition + // and it's opener, need to now point to the new closer. + $condition = $this->tokens[$scopeCloser]['scope_condition']; + $start = ($this->tokens[$condition]['scope_opener'] + 1); + for ($y = $start; $y < $scopeCloser; $y++) { + if (isset($this->tokens[$y]['scope_closer']) === true + && $this->tokens[$y]['scope_closer'] === $scopeCloser + ) { + $this->tokens[$y]['scope_closer'] = $newCloser; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $line = $this->tokens[$y]['line']; + $tokenType = $this->tokens[$y]['type']; + $oldType = $this->tokens[$scopeCloser]['type']; + $newType = $this->tokens[$newCloser]['type']; + echo "\t\t* token $y ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + } + } + } + }//end if + + unset($this->tokens[$x]['bracket_opener']); + unset($this->tokens[$x]['bracket_closer']); + unset($this->tokens[$newCloser]['bracket_opener']); + unset($this->tokens[$newCloser]['bracket_closer']); + $this->tokens[$scopeCloser]['conditions'][] = $i; + + // Now fix up all the tokens that think they are + // inside the CASE/DEFAULT statement when they are really outside. + for ($x = $newCloser; $x < $scopeCloser; $x++) { + foreach ($this->tokens[$x]['conditions'] as $num => $oldCond) { + if ($oldCond === $this->tokens[$i]['code']) { + $oldConditions = $this->tokens[$x]['conditions']; + unset($this->tokens[$x]['conditions'][$num]); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + echo "\t\t* cleaned $x ($type) *".PHP_EOL; + echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL; + } + + break; + }//end if + }//end foreach + }//end for + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL; + } + + }//end processAdditional() + + + /** + * Takes a token produced from token_get_all() and produces a + * more uniform token. + * + * @param string|array $token The token to convert. + * + * @return array The new token. + */ + public static function standardiseToken($token) + { + if (isset($token[1]) === false) { + if (isset(self::$resolveTokenCache[$token[0]]) === true) { + return self::$resolveTokenCache[$token[0]]; + } + } else { + $cacheKey = null; + if ($token[0] === T_STRING) { + $cacheKey = strtolower($token[1]); + } else if ($token[0] !== T_CURLY_OPEN) { + $cacheKey = $token[0]; + } + + if ($cacheKey !== null && isset(self::$resolveTokenCache[$cacheKey]) === true) { + $newToken = self::$resolveTokenCache[$cacheKey]; + $newToken['content'] = $token[1]; + return $newToken; + } + } + + if (isset($token[1]) === false) { + return self::resolveSimpleToken($token[0]); + } + + if ($token[0] === T_STRING) { + switch ($cacheKey) { + case 'false': + $newToken['type'] = 'T_FALSE'; + break; + case 'true': + $newToken['type'] = 'T_TRUE'; + break; + case 'null': + $newToken['type'] = 'T_NULL'; + break; + case 'self': + $newToken['type'] = 'T_SELF'; + break; + case 'parent': + $newToken['type'] = 'T_PARENT'; + break; + default: + $newToken['type'] = 'T_STRING'; + break; + } + + $newToken['code'] = constant($newToken['type']); + + self::$resolveTokenCache[$cacheKey] = $newToken; + } else if ($token[0] === T_CURLY_OPEN) { + $newToken = [ + 'code' => T_OPEN_CURLY_BRACKET, + 'type' => 'T_OPEN_CURLY_BRACKET', + ]; + } else { + $newToken = [ + 'code' => $token[0], + 'type' => Tokens::tokenName($token[0]), + ]; + + self::$resolveTokenCache[$token[0]] = $newToken; + }//end if + + $newToken['content'] = $token[1]; + return $newToken; + + }//end standardiseToken() + + + /** + * Converts simple tokens into a format that conforms to complex tokens + * produced by token_get_all(). + * + * Simple tokens are tokens that are not in array form when produced from + * token_get_all(). + * + * @param string $token The simple token to convert. + * + * @return array The new token in array format. + */ + public static function resolveSimpleToken($token) + { + $newToken = []; + + switch ($token) { + case '{': + $newToken['type'] = 'T_OPEN_CURLY_BRACKET'; + break; + case '}': + $newToken['type'] = 'T_CLOSE_CURLY_BRACKET'; + break; + case '[': + $newToken['type'] = 'T_OPEN_SQUARE_BRACKET'; + break; + case ']': + $newToken['type'] = 'T_CLOSE_SQUARE_BRACKET'; + break; + case '(': + $newToken['type'] = 'T_OPEN_PARENTHESIS'; + break; + case ')': + $newToken['type'] = 'T_CLOSE_PARENTHESIS'; + break; + case ':': + $newToken['type'] = 'T_COLON'; + break; + case '.': + $newToken['type'] = 'T_STRING_CONCAT'; + break; + case ';': + $newToken['type'] = 'T_SEMICOLON'; + break; + case '=': + $newToken['type'] = 'T_EQUAL'; + break; + case '*': + $newToken['type'] = 'T_MULTIPLY'; + break; + case '/': + $newToken['type'] = 'T_DIVIDE'; + break; + case '+': + $newToken['type'] = 'T_PLUS'; + break; + case '-': + $newToken['type'] = 'T_MINUS'; + break; + case '%': + $newToken['type'] = 'T_MODULUS'; + break; + case '^': + $newToken['type'] = 'T_BITWISE_XOR'; + break; + case '&': + $newToken['type'] = 'T_BITWISE_AND'; + break; + case '|': + $newToken['type'] = 'T_BITWISE_OR'; + break; + case '~': + $newToken['type'] = 'T_BITWISE_NOT'; + break; + case '<': + $newToken['type'] = 'T_LESS_THAN'; + break; + case '>': + $newToken['type'] = 'T_GREATER_THAN'; + break; + case '!': + $newToken['type'] = 'T_BOOLEAN_NOT'; + break; + case ',': + $newToken['type'] = 'T_COMMA'; + break; + case '@': + $newToken['type'] = 'T_ASPERAND'; + break; + case '$': + $newToken['type'] = 'T_DOLLAR'; + break; + case '`': + $newToken['type'] = 'T_BACKTICK'; + break; + default: + $newToken['type'] = 'T_NONE'; + break; + }//end switch + + $newToken['code'] = constant($newToken['type']); + $newToken['content'] = $token; + + self::$resolveTokenCache[$token] = $newToken; + return $newToken; + + }//end resolveSimpleToken() + + + /** + * Finds a "closer" token (closing parenthesis or square bracket for example) + * Handle parenthesis balancing while searching for closing token + * + * @param array $tokens The list of tokens to iterate searching the closing token (as returned by token_get_all). + * @param int $start The starting position. + * @param string|string[] $openerTokens The opening character. + * @param string $closerChar The closing character. + * + * @return int|null The position of the closing token, if found. NULL otherwise. + */ + private function findCloser(array &$tokens, $start, $openerTokens, $closerChar) + { + $numTokens = count($tokens); + $stack = [0]; + $closer = null; + $openerTokens = (array) $openerTokens; + + for ($x = $start; $x < $numTokens; $x++) { + if (in_array($tokens[$x], $openerTokens, true) === true + || (is_array($tokens[$x]) === true && in_array($tokens[$x][1], $openerTokens, true) === true) + ) { + $stack[] = $x; + } else if ($tokens[$x] === $closerChar) { + array_pop($stack); + if (empty($stack) === true) { + $closer = $x; + break; + } + } + } + + return $closer; + + }//end findCloser() + + + /** + * PHP 8 attributes parser for PHP < 8 + * Handles single-line and multiline attributes. + * + * @param array $tokens The original array of tokens (as returned by token_get_all). + * @param int $stackPtr The current position in token array. + * + * @return array|null The array of parsed attribute tokens + */ + private function parsePhpAttribute(array &$tokens, $stackPtr) + { + + $token = $tokens[$stackPtr]; + + $commentBody = substr($token[1], 2); + $subTokens = @token_get_all(' $subToken) { + if (is_array($subToken) === true + && $subToken[0] === T_COMMENT + && strpos($subToken[1], '#[') === 0 + ) { + $reparsed = $this->parsePhpAttribute($subTokens, $i); + if ($reparsed !== null) { + array_splice($subTokens, $i, 1, $reparsed); + } else { + $subToken[0] = T_ATTRIBUTE; + } + } + } + + array_splice($subTokens, 0, 1, [[T_ATTRIBUTE, '#[']]); + + // Go looking for the close bracket. + $bracketCloser = $this->findCloser($subTokens, 1, '[', ']'); + if (PHP_VERSION_ID < 80000 && $bracketCloser === null) { + foreach (array_slice($tokens, ($stackPtr + 1)) as $token) { + if (is_array($token) === true) { + $commentBody .= $token[1]; + } else { + $commentBody .= $token; + } + } + + $subTokens = @token_get_all('findCloser($subTokens, 1, '[', ']'); + if ($bracketCloser !== null) { + array_splice($tokens, ($stackPtr + 1), count($tokens), array_slice($subTokens, ($bracketCloser + 1))); + $subTokens = array_slice($subTokens, 0, ($bracketCloser + 1)); + } + } + + if ($bracketCloser === null) { + return null; + } + + return $subTokens; + + }//end parsePhpAttribute() + + + /** + * Creates a map for the attributes tokens that surround other tokens. + * + * @return void + */ + private function createAttributesNestingMap() + { + $map = []; + for ($i = 0; $i < $this->numTokens; $i++) { + if (isset($this->tokens[$i]['attribute_opener']) === true + && $i === $this->tokens[$i]['attribute_opener'] + ) { + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + + if (isset($this->tokens[$i]['attribute_closer']) === true) { + $map[$this->tokens[$i]['attribute_opener']] + = $this->tokens[$i]['attribute_closer']; + } + } else if (isset($this->tokens[$i]['attribute_closer']) === true + && $i === $this->tokens[$i]['attribute_closer'] + ) { + array_pop($map); + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + } else { + if (empty($map) === false) { + $this->tokens[$i]['nested_attributes'] = $map; + } + }//end if + }//end for + + }//end createAttributesNestingMap() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php new file mode 100644 index 000000000..8c90cd7c1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Tokenizers/Tokenizer.php @@ -0,0 +1,1738 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tokenizers; + +use PHP_CodeSniffer\Exceptions\TokenizerException; +use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Tokens; + +abstract class Tokenizer +{ + + /** + * The config data for the run. + * + * @var \PHP_CodeSniffer\Config + */ + protected $config = null; + + /** + * The EOL char used in the content. + * + * @var string + */ + protected $eolChar = ''; + + /** + * A token-based representation of the content. + * + * @var array + */ + protected $tokens = []; + + /** + * The number of tokens in the tokens array. + * + * @var integer + */ + protected $numTokens = 0; + + /** + * A list of tokens that are allowed to open a scope. + * + * @var array + */ + public $scopeOpeners = []; + + /** + * A list of tokens that end the scope. + * + * @var array + */ + public $endScopeTokens = []; + + /** + * Known lengths of tokens. + * + * @var array + */ + public $knownLengths = []; + + /** + * A list of lines being ignored due to error suppression comments. + * + * @var array + */ + public $ignoredLines = []; + + + /** + * Initialise and run the tokenizer. + * + * @param string $content The content to tokenize. + * @param \PHP_CodeSniffer\Config | null $config The config data for the run. + * @param string $eolChar The EOL char used in the content. + * + * @return void + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the file appears to be minified. + */ + public function __construct($content, $config, $eolChar='\n') + { + $this->eolChar = $eolChar; + + $this->config = $config; + $this->tokens = $this->tokenize($content); + + if ($config === null) { + return; + } + + $this->createPositionMap(); + $this->createTokenMap(); + $this->createParenthesisNestingMap(); + $this->createScopeMap(); + $this->createLevelMap(); + + // Allow the tokenizer to do additional processing if required. + $this->processAdditional(); + + }//end __construct() + + + /** + * Checks the content to see if it looks minified. + * + * @param string $content The content to tokenize. + * @param string $eolChar The EOL char used in the content. + * + * @return boolean + */ + protected function isMinifiedContent($content, $eolChar='\n') + { + // Minified files often have a very large number of characters per line + // and cause issues when tokenizing. + $numChars = strlen($content); + $numLines = (substr_count($content, $eolChar) + 1); + $average = ($numChars / $numLines); + if ($average > 100) { + return true; + } + + return false; + + }//end isMinifiedContent() + + + /** + * Gets the array of tokens. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + + }//end getTokens() + + + /** + * Creates an array of tokens when given some content. + * + * @param string $string The string to tokenize. + * + * @return array + */ + abstract protected function tokenize($string); + + + /** + * Performs additional processing after main tokenizing. + * + * @return void + */ + abstract protected function processAdditional(); + + + /** + * Sets token position information. + * + * Can also convert tabs into spaces. Each tab can represent between + * 1 and $width spaces, so this cannot be a straight string replace. + * + * @return void + */ + private function createPositionMap() + { + $currColumn = 1; + $lineNumber = 1; + $eolLen = strlen($this->eolChar); + $ignoring = null; + $inTests = defined('PHP_CODESNIFFER_IN_TESTS'); + + $checkEncoding = false; + if (function_exists('iconv_strlen') === true) { + $checkEncoding = true; + } + + $checkAnnotations = $this->config->annotations; + $encoding = $this->config->encoding; + $tabWidth = $this->config->tabWidth; + + $tokensWithTabs = [ + T_WHITESPACE => true, + T_COMMENT => true, + T_DOC_COMMENT => true, + T_DOC_COMMENT_WHITESPACE => true, + T_DOC_COMMENT_STRING => true, + T_CONSTANT_ENCAPSED_STRING => true, + T_DOUBLE_QUOTED_STRING => true, + T_START_HEREDOC => true, + T_START_NOWDOC => true, + T_HEREDOC => true, + T_NOWDOC => true, + T_END_HEREDOC => true, + T_END_NOWDOC => true, + T_INLINE_HTML => true, + T_YIELD_FROM => true, + ]; + + $this->numTokens = count($this->tokens); + for ($i = 0; $i < $this->numTokens; $i++) { + $this->tokens[$i]['line'] = $lineNumber; + $this->tokens[$i]['column'] = $currColumn; + + if (isset($this->knownLengths[$this->tokens[$i]['code']]) === true) { + // There are no tabs in the tokens we know the length of. + $length = $this->knownLengths[$this->tokens[$i]['code']]; + $currColumn += $length; + } else if ($tabWidth === 0 + || isset($tokensWithTabs[$this->tokens[$i]['code']]) === false + || strpos($this->tokens[$i]['content'], "\t") === false + ) { + // There are no tabs in this content, or we aren't replacing them. + if ($checkEncoding === true) { + // Not using the default encoding, so take a bit more care. + $oldLevel = error_reporting(); + error_reporting(0); + $length = iconv_strlen($this->tokens[$i]['content'], $encoding); + error_reporting($oldLevel); + + if ($length === false) { + // String contained invalid characters, so revert to default. + $length = strlen($this->tokens[$i]['content']); + } + } else { + $length = strlen($this->tokens[$i]['content']); + } + + $currColumn += $length; + } else { + $this->replaceTabsInToken($this->tokens[$i]); + $length = $this->tokens[$i]['length']; + $currColumn += $length; + }//end if + + $this->tokens[$i]['length'] = $length; + + if (isset($this->knownLengths[$this->tokens[$i]['code']]) === false + && strpos($this->tokens[$i]['content'], $this->eolChar) !== false + ) { + $lineNumber++; + $currColumn = 1; + + // Newline chars are not counted in the token length. + $this->tokens[$i]['length'] -= $eolLen; + } + + if ($this->tokens[$i]['code'] === T_COMMENT + || $this->tokens[$i]['code'] === T_DOC_COMMENT_STRING + || $this->tokens[$i]['code'] === T_DOC_COMMENT_TAG + || ($inTests === true && $this->tokens[$i]['code'] === T_INLINE_HTML) + ) { + $commentText = ltrim($this->tokens[$i]['content'], " \t/*#"); + $commentText = rtrim($commentText, " */\t\r\n"); + $commentTextLower = strtolower($commentText); + if (strpos($commentText, '@codingStandards') !== false) { + // If this comment is the only thing on the line, it tells us + // to ignore the following line. If the line contains other content + // then we are just ignoring this one single line. + $ownLine = false; + if ($i > 0) { + for ($prev = ($i - 1); $prev >= 0; $prev--) { + if ($this->tokens[$prev]['code'] === T_WHITESPACE) { + continue; + } + + break; + } + + if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) { + $ownLine = true; + } + } + + if ($ignoring === null + && strpos($commentText, '@codingStandardsIgnoreStart') !== false + ) { + $ignoring = ['.all' => true]; + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + } else if ($ignoring !== null + && strpos($commentText, '@codingStandardsIgnoreEnd') !== false + ) { + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } else { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $ignoring = null; + } else if ($ignoring === null + && strpos($commentText, '@codingStandardsIgnoreLine') !== false + ) { + $ignoring = ['.all' => true]; + if ($ownLine === true) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoring; + } else { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $ignoring = null; + }//end if + } else if (substr($commentTextLower, 0, 6) === 'phpcs:' + || substr($commentTextLower, 0, 7) === '@phpcs:' + ) { + // If the @phpcs: syntax is being used, strip the @ to make + // comparisons easier. + if ($commentText[0] === '@') { + $commentText = substr($commentText, 1); + $commentTextLower = strtolower($commentText); + } + + // If there is a comment on the end, strip it off. + $commentStart = strpos($commentTextLower, ' --'); + if ($commentStart !== false) { + $commentText = substr($commentText, 0, $commentStart); + $commentTextLower = strtolower($commentText); + } + + // If this comment is the only thing on the line, it tells us + // to ignore the following line. If the line contains other content + // then we are just ignoring this one single line. + $lineHasOtherContent = false; + $lineHasOtherTokens = false; + if ($i > 0) { + for ($prev = ($i - 1); $prev > 0; $prev--) { + if ($this->tokens[$prev]['line'] !== $this->tokens[$i]['line']) { + // Changed lines. + break; + } + + if ($this->tokens[$prev]['code'] === T_WHITESPACE + || $this->tokens[$prev]['code'] === T_DOC_COMMENT_WHITESPACE + || ($this->tokens[$prev]['code'] === T_INLINE_HTML + && trim($this->tokens[$prev]['content']) === '') + ) { + continue; + } + + $lineHasOtherTokens = true; + + if ($this->tokens[$prev]['code'] === T_OPEN_TAG + || $this->tokens[$prev]['code'] === T_DOC_COMMENT_STAR + ) { + continue; + } + + $lineHasOtherContent = true; + break; + }//end for + + $changedLines = false; + for ($next = $i; $next < $this->numTokens; $next++) { + if ($changedLines === true) { + // Changed lines. + break; + } + + if (isset($this->knownLengths[$this->tokens[$next]['code']]) === false + && strpos($this->tokens[$next]['content'], $this->eolChar) !== false + ) { + // Last token on the current line. + $changedLines = true; + } + + if ($next === $i) { + continue; + } + + if ($this->tokens[$next]['code'] === T_WHITESPACE + || $this->tokens[$next]['code'] === T_DOC_COMMENT_WHITESPACE + || ($this->tokens[$next]['code'] === T_INLINE_HTML + && trim($this->tokens[$next]['content']) === '') + ) { + continue; + } + + $lineHasOtherTokens = true; + + if ($this->tokens[$next]['code'] === T_CLOSE_TAG) { + continue; + } + + $lineHasOtherContent = true; + break; + }//end for + }//end if + + if (substr($commentTextLower, 0, 9) === 'phpcs:set') { + // Ignore standards for complete lines that change sniff settings. + if ($lineHasOtherTokens === false) { + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } + + // Need to maintain case here, to get the correct sniff code. + $parts = explode(' ', substr($commentText, 10)); + if (count($parts) >= 2) { + $sniffParts = explode('.', $parts[0]); + if (count($sniffParts) >= 3) { + $this->tokens[$i]['sniffCode'] = array_shift($parts); + $this->tokens[$i]['sniffProperty'] = array_shift($parts); + $this->tokens[$i]['sniffPropertyValue'] = rtrim(implode(' ', $parts), " */\r\n"); + } + } + + $this->tokens[$i]['code'] = T_PHPCS_SET; + $this->tokens[$i]['type'] = 'T_PHPCS_SET'; + } else if (substr($commentTextLower, 0, 16) === 'phpcs:ignorefile') { + // The whole file will be ignored, but at least set the correct token. + $this->tokens[$i]['code'] = T_PHPCS_IGNORE_FILE; + $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE_FILE'; + } else if (substr($commentTextLower, 0, 13) === 'phpcs:disable') { + if ($lineHasOtherContent === false) { + // Completely ignore the comment line. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } + + if ($ignoring === null) { + $ignoring = []; + } + + $disabledSniffs = []; + + $additionalText = substr($commentText, 14); + if (empty($additionalText) === true) { + $ignoring = ['.all' => true]; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $sniffCode = trim($sniffCode); + $disabledSniffs[$sniffCode] = true; + $ignoring[$sniffCode] = true; + + // This newly disabled sniff might be disabling an existing + // enabled exception that we are tracking. + if (isset($ignoring['.except']) === true) { + foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring['.except'][$ignoredSniffCode]); + } + } + + if (empty($ignoring['.except']) === true) { + unset($ignoring['.except']); + } + } + }//end foreach + }//end if + + $this->tokens[$i]['code'] = T_PHPCS_DISABLE; + $this->tokens[$i]['type'] = 'T_PHPCS_DISABLE'; + $this->tokens[$i]['sniffCodes'] = $disabledSniffs; + } else if (substr($commentTextLower, 0, 12) === 'phpcs:enable') { + if ($ignoring !== null) { + $enabledSniffs = []; + + $additionalText = substr($commentText, 13); + if (empty($additionalText) === true) { + $ignoring = null; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $sniffCode = trim($sniffCode); + $enabledSniffs[$sniffCode] = true; + + // This new enabled sniff might remove previously disabled + // sniffs if it is actually a standard or category of sniffs. + foreach (array_keys($ignoring) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring[$ignoredSniffCode]); + } + } + + // This new enabled sniff might be able to clear up + // previously enabled sniffs if it is actually a standard or + // category of sniffs. + if (isset($ignoring['.except']) === true) { + foreach (array_keys($ignoring['.except']) as $ignoredSniffCode) { + if ($ignoredSniffCode === $sniffCode + || strpos($ignoredSniffCode, $sniffCode.'.') === 0 + ) { + unset($ignoring['.except'][$ignoredSniffCode]); + } + } + } + }//end foreach + + if (empty($ignoring) === true) { + $ignoring = null; + } else { + if (isset($ignoring['.except']) === true) { + $ignoring['.except'] += $enabledSniffs; + } else { + $ignoring['.except'] = $enabledSniffs; + } + } + }//end if + + if ($lineHasOtherContent === false) { + // Completely ignore the comment line. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + } else { + // The comment is on the same line as the code it is ignoring, + // so respect the new ignore rules. + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + + $this->tokens[$i]['sniffCodes'] = $enabledSniffs; + }//end if + + $this->tokens[$i]['code'] = T_PHPCS_ENABLE; + $this->tokens[$i]['type'] = 'T_PHPCS_ENABLE'; + } else if (substr($commentTextLower, 0, 12) === 'phpcs:ignore') { + $ignoreRules = []; + + $additionalText = substr($commentText, 13); + if (empty($additionalText) === true) { + $ignoreRules = ['.all' => true]; + } else { + $parts = explode(',', $additionalText); + foreach ($parts as $sniffCode) { + $ignoreRules[trim($sniffCode)] = true; + } + } + + $this->tokens[$i]['code'] = T_PHPCS_IGNORE; + $this->tokens[$i]['type'] = 'T_PHPCS_IGNORE'; + $this->tokens[$i]['sniffCodes'] = $ignoreRules; + + if ($ignoring !== null) { + $ignoreRules += $ignoring; + } + + if ($lineHasOtherContent === false) { + // Completely ignore the comment line, and set the following + // line to include the ignore rules we've set. + $this->ignoredLines[$this->tokens[$i]['line']] = ['.all' => true]; + $this->ignoredLines[($this->tokens[$i]['line'] + 1)] = $ignoreRules; + } else { + // The comment is on the same line as the code it is ignoring, + // so respect the ignore rules it set. + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoreRules; + } + }//end if + }//end if + }//end if + + if ($ignoring !== null && isset($this->ignoredLines[$this->tokens[$i]['line']]) === false) { + $this->ignoredLines[$this->tokens[$i]['line']] = $ignoring; + } + }//end for + + // If annotations are being ignored, we clear out all the ignore rules + // but leave the annotations tokenized as normal. + if ($checkAnnotations === false) { + $this->ignoredLines = []; + } + + }//end createPositionMap() + + + /** + * Replaces tabs in original token content with spaces. + * + * Each tab can represent between 1 and $config->tabWidth spaces, + * so this cannot be a straight string replace. The original content + * is placed into an orig_content index and the new token length is also + * set in the length index. + * + * @param array $token The token to replace tabs inside. + * @param string $prefix The character to use to represent the start of a tab. + * @param string $padding The character to use to represent the end of a tab. + * @param int $tabWidth The number of spaces each tab represents. + * + * @return void + */ + public function replaceTabsInToken(&$token, $prefix=' ', $padding=' ', $tabWidth=null) + { + $checkEncoding = false; + if (function_exists('iconv_strlen') === true) { + $checkEncoding = true; + } + + $currColumn = $token['column']; + if ($tabWidth === null) { + $tabWidth = $this->config->tabWidth; + if ($tabWidth === 0) { + $tabWidth = 1; + } + } + + if (rtrim($token['content'], "\t") === '') { + // String only contains tabs, so we can shortcut the process. + $numTabs = strlen($token['content']); + + $firstTabSize = ($tabWidth - (($currColumn - 1) % $tabWidth)); + $length = ($firstTabSize + ($tabWidth * ($numTabs - 1))); + $newContent = $prefix.str_repeat($padding, ($length - 1)); + } else { + // We need to determine the length of each tab. + $tabs = explode("\t", $token['content']); + + $numTabs = (count($tabs) - 1); + $tabNum = 0; + $newContent = ''; + $length = 0; + + foreach ($tabs as $content) { + if ($content !== '') { + $newContent .= $content; + if ($checkEncoding === true) { + // Not using ASCII encoding, so take a bit more care. + $oldLevel = error_reporting(); + error_reporting(0); + $contentLength = iconv_strlen($content, $this->config->encoding); + error_reporting($oldLevel); + if ($contentLength === false) { + // String contained invalid characters, so revert to default. + $contentLength = strlen($content); + } + } else { + $contentLength = strlen($content); + } + + $currColumn += $contentLength; + $length += $contentLength; + } + + // The last piece of content does not have a tab after it. + if ($tabNum === $numTabs) { + break; + } + + // Process the tab that comes after the content. + $tabNum++; + + // Move the pointer to the next tab stop. + $pad = ($tabWidth - ($currColumn + $tabWidth - 1) % $tabWidth); + $currColumn += $pad; + $length += $pad; + $newContent .= $prefix.str_repeat($padding, ($pad - 1)); + }//end foreach + }//end if + + $token['orig_content'] = $token['content']; + $token['content'] = $newContent; + $token['length'] = $length; + + }//end replaceTabsInToken() + + + /** + * Creates a map of brackets positions. + * + * @return void + */ + private function createTokenMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START TOKEN MAP ***".PHP_EOL; + } + + $squareOpeners = []; + $curlyOpeners = []; + $this->numTokens = count($this->tokens); + + $openers = []; + $openOwner = null; + + for ($i = 0; $i < $this->numTokens; $i++) { + /* + Parenthesis mapping. + */ + + if (isset(Tokens::$parenthesisOpeners[$this->tokens[$i]['code']]) === true) { + $this->tokens[$i]['parenthesis_opener'] = null; + $this->tokens[$i]['parenthesis_closer'] = null; + $this->tokens[$i]['parenthesis_owner'] = $i; + $openOwner = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found parenthesis owner at $i".PHP_EOL; + } + } else if ($this->tokens[$i]['code'] === T_OPEN_PARENTHESIS) { + $openers[] = $i; + $this->tokens[$i]['parenthesis_opener'] = $i; + if ($openOwner !== null) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found parenthesis opener at $i for $openOwner".PHP_EOL; + } + + $this->tokens[$openOwner]['parenthesis_opener'] = $i; + $this->tokens[$i]['parenthesis_owner'] = $openOwner; + $openOwner = null; + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found unowned parenthesis opener at $i".PHP_EOL; + } + } else if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { + // Did we set an owner for this set of parenthesis? + $numOpeners = count($openers); + if ($numOpeners !== 0) { + $opener = array_pop($openers); + if (isset($this->tokens[$opener]['parenthesis_owner']) === true) { + $owner = $this->tokens[$opener]['parenthesis_owner']; + + $this->tokens[$owner]['parenthesis_closer'] = $i; + $this->tokens[$i]['parenthesis_owner'] = $owner; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found parenthesis closer at $i for $owner".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found unowned parenthesis closer at $i for $opener".PHP_EOL; + } + + $this->tokens[$i]['parenthesis_opener'] = $opener; + $this->tokens[$i]['parenthesis_closer'] = $i; + $this->tokens[$opener]['parenthesis_closer'] = $i; + }//end if + } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE) { + $openers[] = $i; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($openers)); + echo "=> Found attribute opener at $i".PHP_EOL; + } + + $this->tokens[$i]['attribute_opener'] = $i; + $this->tokens[$i]['attribute_closer'] = null; + } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE_END) { + $numOpeners = count($openers); + if ($numOpeners !== 0) { + $opener = array_pop($openers); + if (isset($this->tokens[$opener]['attribute_opener']) === true) { + $this->tokens[$opener]['attribute_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found attribute closer at $i for $opener".PHP_EOL; + } + + for ($x = ($opener + 1); $x <= $i; ++$x) { + if (isset($this->tokens[$x]['attribute_closer']) === true) { + continue; + } + + $this->tokens[$x]['attribute_opener'] = $opener; + $this->tokens[$x]['attribute_closer'] = $i; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", (count($openers) + 1)); + echo "=> Found unowned attribute closer at $i for $opener".PHP_EOL; + } + }//end if + }//end if + + /* + Bracket mapping. + */ + + switch ($this->tokens[$i]['code']) { + case T_OPEN_SQUARE_BRACKET: + $squareOpeners[] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "=> Found square bracket opener at $i".PHP_EOL; + } + break; + case T_OPEN_CURLY_BRACKET: + if (isset($this->tokens[$i]['scope_closer']) === false) { + $curlyOpeners[] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "=> Found curly bracket opener at $i".PHP_EOL; + } + } + break; + case T_CLOSE_SQUARE_BRACKET: + if (empty($squareOpeners) === false) { + $opener = array_pop($squareOpeners); + $this->tokens[$i]['bracket_opener'] = $opener; + $this->tokens[$i]['bracket_closer'] = $i; + $this->tokens[$opener]['bracket_opener'] = $opener; + $this->tokens[$opener]['bracket_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "\t=> Found square bracket closer at $i for $opener".PHP_EOL; + } + } + break; + case T_CLOSE_CURLY_BRACKET: + if (empty($curlyOpeners) === false + && isset($this->tokens[$i]['scope_opener']) === false + ) { + $opener = array_pop($curlyOpeners); + $this->tokens[$i]['bracket_opener'] = $opener; + $this->tokens[$i]['bracket_closer'] = $i; + $this->tokens[$opener]['bracket_opener'] = $opener; + $this->tokens[$opener]['bracket_closer'] = $i; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", count($squareOpeners)); + echo str_repeat("\t", count($curlyOpeners)); + echo "\t=> Found curly bracket closer at $i for $opener".PHP_EOL; + } + } + break; + default: + continue 2; + }//end switch + }//end for + + // Cleanup for any openers that we didn't find closers for. + // This typically means there was a syntax error breaking things. + foreach ($openers as $opener) { + unset($this->tokens[$opener]['parenthesis_opener']); + unset($this->tokens[$opener]['parenthesis_owner']); + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END TOKEN MAP ***".PHP_EOL; + } + + }//end createTokenMap() + + + /** + * Creates a map for the parenthesis tokens that surround other tokens. + * + * @return void + */ + private function createParenthesisNestingMap() + { + $map = []; + for ($i = 0; $i < $this->numTokens; $i++) { + if (isset($this->tokens[$i]['parenthesis_opener']) === true + && $i === $this->tokens[$i]['parenthesis_opener'] + ) { + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + + if (isset($this->tokens[$i]['parenthesis_closer']) === true) { + $map[$this->tokens[$i]['parenthesis_opener']] + = $this->tokens[$i]['parenthesis_closer']; + } + } else if (isset($this->tokens[$i]['parenthesis_closer']) === true + && $i === $this->tokens[$i]['parenthesis_closer'] + ) { + array_pop($map); + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + } else { + if (empty($map) === false) { + $this->tokens[$i]['nested_parenthesis'] = $map; + } + }//end if + }//end for + + }//end createParenthesisNestingMap() + + + /** + * Creates a scope map of tokens that open scopes. + * + * @return void + * @see recurseScopeMap() + */ + private function createScopeMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START SCOPE MAP ***".PHP_EOL; + } + + for ($i = 0; $i < $this->numTokens; $i++) { + // Check to see if the current token starts a new scope. + if (isset($this->scopeOpeners[$this->tokens[$i]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $content = Common::prepareForOutput($this->tokens[$i]['content']); + echo "\tStart scope map at $i:$type => $content".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_condition']) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* already processed, skipping *".PHP_EOL; + } + + continue; + } + + $i = $this->recurseScopeMap($i); + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END SCOPE MAP ***".PHP_EOL; + } + + }//end createScopeMap() + + + /** + * Recurses though the scope openers to build a scope map. + * + * @param int $stackPtr The position in the stack of the token that + * opened the scope (eg. an IF token or FOR token). + * @param int $depth How many scope levels down we are. + * @param int $ignore How many curly braces we are ignoring. + * + * @return int The position in the stack that closed the scope. + * @throws \PHP_CodeSniffer\Exceptions\TokenizerException If the nesting level gets too deep. + */ + private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "=> Begin scope map recursion at token $stackPtr with depth $depth".PHP_EOL; + } + + $opener = null; + $currType = $this->tokens[$stackPtr]['code']; + $startLine = $this->tokens[$stackPtr]['line']; + + // We will need this to restore the value if we end up + // returning a token ID that causes our calling function to go back + // over already ignored braces. + $originalIgnore = $ignore; + + // If the start token for this scope opener is the same as + // the scope token, we have already found our opener. + if (isset($this->scopeOpeners[$currType]['start'][$currType]) === true) { + $opener = $stackPtr; + } + + for ($i = ($stackPtr + 1); $i < $this->numTokens; $i++) { + $tokenType = $this->tokens[$i]['code']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $line = $this->tokens[$i]['line']; + $content = Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", $depth); + echo "Process token $i on line $line ["; + if ($opener !== null) { + echo "opener:$opener;"; + } + + if ($ignore > 0) { + echo "ignore=$ignore;"; + } + + echo "]: $type => $content".PHP_EOL; + }//end if + + // Very special case for IF statements in PHP that can be defined without + // scope tokens. E.g., if (1) 1; 1 ? (1 ? 1 : 1) : 1; + // If an IF statement below this one has an opener but no + // keyword, the opener will be incorrectly assigned to this IF statement. + // The same case also applies to USE statements, which don't have to have + // openers, so a following USE statement can cause an incorrect brace match. + if (($currType === T_IF || $currType === T_ELSE || $currType === T_USE) + && $opener === null + && ($this->tokens[$i]['code'] === T_SEMICOLON + || $this->tokens[$i]['code'] === T_CLOSE_TAG) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + if ($this->tokens[$i]['code'] === T_SEMICOLON) { + $closerType = 'semicolon'; + } else { + $closerType = 'close tag'; + } + + echo "=> Found $closerType before scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return $i; + } + + // Special case for PHP control structures that have no braces. + // If we find a curly brace closer before we find the opener, + // we're not going to find an opener. That closer probably belongs to + // a control structure higher up. + if ($opener === null + && $ignore === 0 + && $tokenType === T_CLOSE_CURLY_BRACKET + && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found curly brace closer before scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return ($i - 1); + } + + if ($opener !== null + && (isset($this->tokens[$i]['scope_opener']) === false + || $this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) + && isset($this->scopeOpeners[$currType]['end'][$tokenType]) === true + ) { + if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) { + // The last opening bracket must have been for a string + // offset or alike, so let's ignore it. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + continue; + } else if ($this->tokens[$opener]['code'] === T_OPEN_CURLY_BRACKET + && $tokenType !== T_CLOSE_CURLY_BRACKET + ) { + // The opener is a curly bracket so the closer must be a curly bracket as well. + // We ignore this closer to handle cases such as T_ELSE or T_ELSEIF being considered + // a closer of T_IF when it should not. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Ignoring non-curly scope closer for $stackPtr:$type".PHP_EOL; + } + } else { + $scopeCloser = $i; + $todo = [ + $stackPtr, + $opener, + ]; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + $closerType = $this->tokens[$scopeCloser]['type']; + echo str_repeat("\t", $depth); + echo "=> Found scope closer ($scopeCloser:$closerType) for $stackPtr:$type".PHP_EOL; + } + + $validCloser = true; + if (($this->tokens[$stackPtr]['code'] === T_IF || $this->tokens[$stackPtr]['code'] === T_ELSEIF) + && ($tokenType === T_ELSE || $tokenType === T_ELSEIF) + ) { + // To be a closer, this token must have an opener. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer needs to be tested *".PHP_EOL; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + + if (isset($this->tokens[$scopeCloser]['scope_opener']) === false) { + $validCloser = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer is not valid (no opener found) *".PHP_EOL; + } + } else if ($this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['code'] !== $this->tokens[$opener]['code']) { + $validCloser = false; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + $type = $this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['type']; + $openerType = $this->tokens[$opener]['type']; + echo "* closer is not valid (mismatched opener type; $type != $openerType) *".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo "* closer was valid *".PHP_EOL; + } + } else { + // The closer was not processed, so we need to + // complete that token as well. + $todo[] = $scopeCloser; + }//end if + + if ($validCloser === true) { + foreach ($todo as $token) { + $this->tokens[$token]['scope_condition'] = $stackPtr; + $this->tokens[$token]['scope_opener'] = $opener; + $this->tokens[$token]['scope_closer'] = $scopeCloser; + } + + if ($this->scopeOpeners[$this->tokens[$stackPtr]['code']]['shared'] === true) { + // As we are going back to where we started originally, restore + // the ignore value back to its original value. + $ignore = $originalIgnore; + return $opener; + } else if ($scopeCloser === $i + && isset($this->scopeOpeners[$tokenType]) === true + ) { + // Unset scope_condition here or else the token will appear to have + // already been processed, and it will be skipped. Normally we want that, + // but in this case, the token is both a closer and an opener, so + // it needs to act like an opener. This is also why we return the + // token before this one; so the closer has a chance to be processed + // a second time, but as an opener. + unset($this->tokens[$scopeCloser]['scope_condition']); + return ($i - 1); + } else { + return $i; + } + } else { + continue; + }//end if + }//end if + }//end if + + // Is this an opening condition ? + if (isset($this->scopeOpeners[$tokenType]) === true) { + if ($opener === null) { + if ($tokenType === T_USE) { + // PHP use keywords are special because they can be + // used as blocks but also inline in function definitions. + // So if we find them nested inside another opener, just skip them. + continue; + } + + if ($tokenType === T_NAMESPACE) { + // PHP namespace keywords are special because they can be + // used as blocks but also inline as operators. + // So if we find them nested inside another opener, just skip them. + continue; + } + + if ($tokenType === T_FUNCTION + && $this->tokens[$stackPtr]['code'] !== T_FUNCTION + ) { + // Probably a closure, so process it manually. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found function before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_closer']) === true) { + // We've already processed this closure. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + $i = $this->tokens[$i]['scope_closer']; + continue; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + continue; + }//end if + + if ($tokenType === T_CLASS) { + // Probably an anonymous class inside another anonymous class, + // so process it manually. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found class before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + } + + if (isset($this->tokens[$i]['scope_closer']) === true) { + // We've already processed this anon class. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + $i = $this->tokens[$i]['scope_closer']; + continue; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + continue; + }//end if + + // Found another opening condition but still haven't + // found our opener, so we are never going to find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found new opening condition before scope opener for $stackPtr:$type, "; + } + + if (($this->tokens[$stackPtr]['code'] === T_IF + || $this->tokens[$stackPtr]['code'] === T_ELSEIF + || $this->tokens[$stackPtr]['code'] === T_ELSE) + && ($this->tokens[$i]['code'] === T_ELSE + || $this->tokens[$i]['code'] === T_ELSEIF) + ) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "continuing".PHP_EOL; + } + + return ($i - 1); + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "backtracking".PHP_EOL; + } + + return $stackPtr; + } + }//end if + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* token is an opening condition *'.PHP_EOL; + } + + $isShared = ($this->scopeOpeners[$tokenType]['shared'] === true); + + if (isset($this->tokens[$i]['scope_condition']) === true) { + // We've been here before. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* already processed, skipping *'.PHP_EOL; + } + + if ($isShared === false + && isset($this->tokens[$i]['scope_closer']) === true + ) { + $i = $this->tokens[$i]['scope_closer']; + } + + continue; + } else if ($currType === $tokenType + && $isShared === false + && $opener === null + ) { + // We haven't yet found our opener, but we have found another + // scope opener which is the same type as us, and we don't + // share openers, so we will never find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* it was another token\'s opener, bailing *'.PHP_EOL; + } + + return $stackPtr; + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* searching for opener *'.PHP_EOL; + } + + if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { + $oldIgnore = $ignore; + $ignore = 0; + } + + // PHP has a max nesting level for functions. Stop before we hit that limit + // because too many loops means we've run into trouble anyway. + if ($depth > 50) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* reached maximum nesting level; aborting *'.PHP_EOL; + } + + throw new TokenizerException('Maximum nesting level reached; file could not be processed'); + } + + $oldDepth = $depth; + if ($isShared === true + && isset($this->scopeOpeners[$tokenType]['with'][$currType]) === true + ) { + // Don't allow the depth to increment because this is + // possibly not a true nesting if we are sharing our closer. + // This can happen, for example, when a SWITCH has a large + // number of CASE statements with the same shared BREAK. + $depth--; + } + + $i = self::recurseScopeMap($i, ($depth + 1), $ignore); + $depth = $oldDepth; + + if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { + $ignore = $oldIgnore; + } + }//end if + }//end if + + if (isset($this->scopeOpeners[$currType]['start'][$tokenType]) === true + && $opener === null + ) { + if ($tokenType === T_OPEN_CURLY_BRACKET) { + if (isset($this->tokens[$stackPtr]['parenthesis_closer']) === true + && $i < $this->tokens[$stackPtr]['parenthesis_closer'] + ) { + // We found a curly brace inside the condition of the + // current scope opener, so it must be a string offset. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace inside condition *'.PHP_EOL; + } + + $ignore++; + } else { + // Make sure this is actually an opener and not a + // string offset (e.g., $var{0}). + for ($x = ($i - 1); $x > 0; $x--) { + if (isset(Tokens::$emptyTokens[$this->tokens[$x]['code']]) === true) { + continue; + } else { + // If the first non-whitespace/comment token looks like this + // brace is a string offset, or this brace is mid-way through + // a new statement, it isn't a scope opener. + $disallowed = Tokens::$assignmentTokens; + $disallowed += [ + T_DOLLAR => true, + T_VARIABLE => true, + T_OBJECT_OPERATOR => true, + T_NULLSAFE_OBJECT_OPERATOR => true, + T_COMMA => true, + T_OPEN_PARENTHESIS => true, + ]; + + if (isset($disallowed[$this->tokens[$x]['code']]) === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace *'.PHP_EOL; + } + + $ignore++; + } + + break; + }//end if + }//end for + }//end if + }//end if + + if ($ignore === 0 || $tokenType !== T_OPEN_CURLY_BRACKET) { + $openerNested = isset($this->tokens[$i]['nested_parenthesis']); + $ownerNested = isset($this->tokens[$stackPtr]['nested_parenthesis']); + + if (($openerNested === true && $ownerNested === false) + || ($openerNested === false && $ownerNested === true) + || ($openerNested === true + && $this->tokens[$i]['nested_parenthesis'] !== $this->tokens[$stackPtr]['nested_parenthesis']) + ) { + // We found the a token that looks like the opener, but it's nested differently. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + echo str_repeat("\t", $depth); + echo "* ignoring possible opener $i:$type as nested parenthesis don't match *".PHP_EOL; + } + } else { + // We found the opening scope token for $currType. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + } + + $opener = $i; + } + }//end if + } else if ($tokenType === T_SEMICOLON + && $opener === null + && (isset($this->tokens[$stackPtr]['parenthesis_closer']) === false + || $i > $this->tokens[$stackPtr]['parenthesis_closer']) + ) { + // Found the end of a statement but still haven't + // found our opener, so we are never going to find one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found end of statement before scope opener for $stackPtr:$type, continuing".PHP_EOL; + } + + return ($i - 1); + } else if ($tokenType === T_OPEN_PARENTHESIS) { + if (isset($this->tokens[$i]['parenthesis_owner']) === true) { + $owner = $this->tokens[$i]['parenthesis_owner']; + if (isset(Tokens::$scopeOpeners[$this->tokens[$owner]['code']]) === true + && isset($this->tokens[$i]['parenthesis_closer']) === true + ) { + // If we get into here, then we opened a parenthesis for + // a scope (eg. an if or else if) so we need to update the + // start of the line so that when we check to see + // if the closing parenthesis is more than n lines away from + // the statement, we check from the closing parenthesis. + $startLine = $this->tokens[$this->tokens[$i]['parenthesis_closer']]['line']; + } + } + } else if ($tokenType === T_OPEN_CURLY_BRACKET && $opener !== null) { + // We opened something that we don't have a scope opener for. + // Examples of this are curly brackets for string offsets etc. + // We want to ignore this so that we don't have an invalid scope + // map. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* ignoring curly brace *'.PHP_EOL; + } + + $ignore++; + } else if ($tokenType === T_CLOSE_CURLY_BRACKET && $ignore > 0) { + // We found the end token for the opener we were ignoring. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + } else if ($opener === null + && isset($this->scopeOpeners[$currType]) === true + ) { + // If we still haven't found the opener after 30 lines, + // we're not going to find it, unless we know it requires + // an opener (in which case we better keep looking) or the last + // token was empty (in which case we'll just confirm there is + // more code in this file and not just a big comment). + if ($this->tokens[$i]['line'] >= ($startLine + 30) + && isset(Tokens::$emptyTokens[$this->tokens[($i - 1)]['code']]) === false + ) { + if ($this->scopeOpeners[$currType]['strict'] === true) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + $lines = ($this->tokens[$i]['line'] - $startLine); + echo str_repeat("\t", $depth); + echo "=> Still looking for $stackPtr:$type scope opener after $lines lines".PHP_EOL; + } + } else { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL; + } + + return $stackPtr; + } + } + } else if ($opener !== null + && $tokenType !== T_BREAK + && isset($this->endScopeTokens[$tokenType]) === true + ) { + if (isset($this->tokens[$i]['scope_condition']) === false) { + if ($ignore > 0) { + // We found the end token for the opener we were ignoring. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", $depth); + echo '* finished ignoring curly brace *'.PHP_EOL; + } + + $ignore--; + } else { + // We found a token that closes the scope but it doesn't + // have a condition, so it belongs to another token and + // our token doesn't have a closer, so pretend this is + // the closer. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", $depth); + echo "=> Found (unexpected) scope closer for $stackPtr:$type".PHP_EOL; + } + + foreach ([$stackPtr, $opener] as $token) { + $this->tokens[$token]['scope_condition'] = $stackPtr; + $this->tokens[$token]['scope_opener'] = $opener; + $this->tokens[$token]['scope_closer'] = $i; + } + + return ($i - 1); + }//end if + }//end if + }//end if + }//end for + + return $stackPtr; + + }//end recurseScopeMap() + + + /** + * Constructs the level map. + * + * The level map adds a 'level' index to each token which indicates the + * depth that a token within a set of scope blocks. It also adds a + * 'conditions' index which is an array of the scope conditions that opened + * each of the scopes - position 0 being the first scope opener. + * + * @return void + */ + private function createLevelMap() + { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** START LEVEL MAP ***".PHP_EOL; + } + + $this->numTokens = count($this->tokens); + $level = 0; + $conditions = []; + $lastOpener = null; + $openers = []; + + for ($i = 0; $i < $this->numTokens; $i++) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$i]['type']; + $line = $this->tokens[$i]['line']; + $len = $this->tokens[$i]['length']; + $col = $this->tokens[$i]['column']; + + $content = Common::prepareForOutput($this->tokens[$i]['content']); + + echo str_repeat("\t", ($level + 1)); + echo "Process token $i on line $line [col:$col;len:$len;lvl:$level;"; + if (empty($conditions) !== true) { + $conditionString = 'conds;'; + foreach ($conditions as $condition) { + $conditionString .= Tokens::tokenName($condition).','; + } + + echo rtrim($conditionString, ',').';'; + } + + echo "]: $type => $content".PHP_EOL; + }//end if + + $this->tokens[$i]['level'] = $level; + $this->tokens[$i]['conditions'] = $conditions; + + if (isset($this->tokens[$i]['scope_condition']) === true) { + // Check to see if this token opened the scope. + if ($this->tokens[$i]['scope_opener'] === $i) { + $stackPtr = $this->tokens[$i]['scope_condition']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", ($level + 1)); + echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + } + + $stackPtr = $this->tokens[$i]['scope_condition']; + + // If we find a scope opener that has a shared closer, + // then we need to go back over the condition map that we + // just created and fix ourselves as we just added some + // conditions where there was none. This happens for T_CASE + // statements that are using the same break statement. + if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $this->tokens[$i]['scope_closer']) { + // This opener shares its closer with the previous opener, + // but we still need to check if the two openers share their + // closer with each other directly (like CASE and DEFAULT) + // or if they are just sharing because one doesn't have a + // closer (like CASE with no BREAK using a SWITCHes closer). + $thisType = $this->tokens[$this->tokens[$i]['scope_condition']]['code']; + $opener = $this->tokens[$lastOpener]['scope_condition']; + + $isShared = isset($this->scopeOpeners[$thisType]['with'][$this->tokens[$opener]['code']]); + + reset($this->scopeOpeners[$thisType]['end']); + reset($this->scopeOpeners[$this->tokens[$opener]['code']]['end']); + $sameEnd = (current($this->scopeOpeners[$thisType]['end']) === current($this->scopeOpeners[$this->tokens[$opener]['code']]['end'])); + + if ($isShared === true && $sameEnd === true) { + $badToken = $opener; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$badToken]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* shared closer, cleaning up $badToken:$type *".PHP_EOL; + } + + for ($x = $this->tokens[$i]['scope_condition']; $x <= $i; $x++) { + $oldConditions = $this->tokens[$x]['conditions']; + $oldLevel = $this->tokens[$x]['level']; + $this->tokens[$x]['level']--; + unset($this->tokens[$x]['conditions'][$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + $newLevel = $this->tokens[$x]['level']; + echo str_repeat("\t", ($level + 1)); + echo "* cleaned $x:$type *".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + }//end if + }//end for + + unset($conditions[$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$badToken]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* token $badToken:$type removed from conditions array *".PHP_EOL; + } + + unset($openers[$lastOpener]); + + $level--; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 2)); + echo '* level decreased *'.PHP_EOL; + } + }//end if + }//end if + + $level++; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 1)); + echo '* level increased *'.PHP_EOL; + } + + $conditions[$stackPtr] = $this->tokens[$stackPtr]['code']; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$stackPtr]['type']; + echo str_repeat("\t", ($level + 1)); + echo "* token $stackPtr:$type added to conditions array *".PHP_EOL; + } + + $lastOpener = $this->tokens[$i]['scope_opener']; + if ($lastOpener !== null) { + $openers[$lastOpener] = $lastOpener; + } + } else if ($lastOpener !== null && $this->tokens[$lastOpener]['scope_closer'] === $i) { + foreach (array_reverse($openers) as $opener) { + if ($this->tokens[$opener]['scope_closer'] === $i) { + $oldOpener = array_pop($openers); + if (empty($openers) === false) { + $lastOpener = array_pop($openers); + $openers[$lastOpener] = $lastOpener; + } else { + $lastOpener = null; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$oldOpener]['type']; + echo str_repeat("\t", ($level + 1)); + echo "=> Found scope closer for $oldOpener:$type".PHP_EOL; + } + + $oldCondition = array_pop($conditions); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 1)); + echo '* token '.Tokens::tokenName($oldCondition).' removed from conditions array *'.PHP_EOL; + } + + // Make sure this closer actually belongs to us. + // Either the condition also has to think this is the + // closer, or it has to allow sharing with us. + $condition = $this->tokens[$this->tokens[$i]['scope_condition']]['code']; + if ($condition !== $oldCondition) { + if (isset($this->scopeOpeners[$oldCondition]['with'][$condition]) === false) { + $badToken = $this->tokens[$oldOpener]['scope_condition']; + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = Tokens::tokenName($oldCondition); + echo str_repeat("\t", ($level + 1)); + echo "* scope closer was bad, cleaning up $badToken:$type *".PHP_EOL; + } + + for ($x = ($oldOpener + 1); $x <= $i; $x++) { + $oldConditions = $this->tokens[$x]['conditions']; + $oldLevel = $this->tokens[$x]['level']; + $this->tokens[$x]['level']--; + unset($this->tokens[$x]['conditions'][$badToken]); + if (PHP_CODESNIFFER_VERBOSITY > 1) { + $type = $this->tokens[$x]['type']; + $oldConds = ''; + foreach ($oldConditions as $condition) { + $oldConds .= Tokens::tokenName($condition).','; + } + + $oldConds = rtrim($oldConds, ','); + + $newConds = ''; + foreach ($this->tokens[$x]['conditions'] as $condition) { + $newConds .= Tokens::tokenName($condition).','; + } + + $newConds = rtrim($newConds, ','); + + $newLevel = $this->tokens[$x]['level']; + echo str_repeat("\t", ($level + 1)); + echo "* cleaned $x:$type *".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; + echo str_repeat("\t", ($level + 2)); + echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + }//end if + }//end for + }//end if + }//end if + + $level--; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo str_repeat("\t", ($level + 2)); + echo '* level decreased *'.PHP_EOL; + } + + $this->tokens[$i]['level'] = $level; + $this->tokens[$i]['conditions'] = $conditions; + }//end if + }//end foreach + }//end if + }//end if + }//end for + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t*** END LEVEL MAP ***".PHP_EOL; + } + + }//end createLevelMap() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Cache.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Cache.php new file mode 100644 index 000000000..408de96e7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Cache.php @@ -0,0 +1,355 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use FilesystemIterator; +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Ruleset; +use RecursiveCallbackFilterIterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; + +class Cache +{ + + /** + * The filesystem location of the cache file. + * + * @var string + */ + private static $path = ''; + + /** + * The cached data. + * + * @var array + */ + private static $cache = []; + + + /** + * Loads existing cache data for the run, if any. + * + * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public static function load(Ruleset $ruleset, Config $config) + { + // Look at every loaded sniff class so far and use their file contents + // to generate a hash for the code used during the run. + // At this point, the loaded class list contains the core PHPCS code + // and all sniffs that have been loaded as part of the run. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo PHP_EOL."\tGenerating loaded file list for code hash".PHP_EOL; + } + + $codeHashFiles = []; + + $classes = array_keys(Autoload::getLoadedClasses()); + sort($classes); + + $installDir = dirname(__DIR__); + $installDirLen = strlen($installDir); + $standardDir = $installDir.DIRECTORY_SEPARATOR.'Standards'; + $standardDirLen = strlen($standardDir); + foreach ($classes as $file) { + if (substr($file, 0, $standardDirLen) !== $standardDir) { + if (substr($file, 0, $installDirLen) === $installDir) { + // We are only interested in sniffs here. + continue; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> external file: $file".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> internal sniff: $file".PHP_EOL; + } + + $codeHashFiles[] = $file; + } + + // Add the content of the used rulesets to the hash so that sniff setting + // changes in the ruleset invalidate the cache. + $rulesets = $ruleset->paths; + sort($rulesets); + foreach ($rulesets as $file) { + if (substr($file, 0, $standardDirLen) !== $standardDir) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> external ruleset: $file".PHP_EOL; + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> internal ruleset: $file".PHP_EOL; + } + + $codeHashFiles[] = $file; + } + + // Go through the core PHPCS code and add those files to the file + // hash. This ensures that core PHPCS changes will also invalidate the cache. + // Note that we ignore sniffs here, and any files that don't affect + // the outcome of the run. + $di = new RecursiveDirectoryIterator( + $installDir, + (FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS) + ); + $filter = new RecursiveCallbackFilterIterator( + $di, + function ($file, $key, $iterator) { + // Skip non-php files. + $filename = $file->getFilename(); + if ($file->isFile() === true && substr($filename, -4) !== '.php') { + return false; + } + + $filePath = Common::realpath($key); + if ($filePath === false) { + return false; + } + + if ($iterator->hasChildren() === true + && ($filename === 'Standards' + || $filename === 'Exceptions' + || $filename === 'Reports' + || $filename === 'Generators') + ) { + return false; + } + + return true; + } + ); + + $iterator = new RecursiveIteratorIterator($filter); + foreach ($iterator as $file) { + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> core file: $file".PHP_EOL; + } + + $codeHashFiles[] = $file->getPathname(); + } + + $codeHash = ''; + sort($codeHashFiles); + foreach ($codeHashFiles as $file) { + $codeHash .= md5_file($file); + } + + $codeHash = md5($codeHash); + + // Along with the code hash, use various settings that can affect + // the results of a run to create a new hash. This hash will be used + // in the cache file name. + $rulesetHash = md5(var_export($ruleset->ignorePatterns, true).var_export($ruleset->includePatterns, true)); + $phpExtensionsHash = md5(var_export(get_loaded_extensions(), true)); + $configData = [ + 'phpVersion' => PHP_VERSION_ID, + 'phpExtensions' => $phpExtensionsHash, + 'tabWidth' => $config->tabWidth, + 'encoding' => $config->encoding, + 'recordErrors' => $config->recordErrors, + 'annotations' => $config->annotations, + 'configData' => Config::getAllConfigData(), + 'codeHash' => $codeHash, + 'rulesetHash' => $rulesetHash, + ]; + + $configString = var_export($configData, true); + $cacheHash = substr(sha1($configString), 0, 12); + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\tGenerating cache key data".PHP_EOL; + foreach ($configData as $key => $value) { + if (is_array($value) === true) { + echo "\t\t=> $key:".PHP_EOL; + foreach ($value as $subKey => $subValue) { + echo "\t\t\t=> $subKey: $subValue".PHP_EOL; + } + + continue; + } + + if ($value === true || $value === false) { + $value = (int) $value; + } + + echo "\t\t=> $key: $value".PHP_EOL; + } + + echo "\t\t=> cacheHash: $cacheHash".PHP_EOL; + }//end if + + if ($config->cacheFile !== null) { + $cacheFile = $config->cacheFile; + } else { + // Determine the common paths for all files being checked. + // We can use this to locate an existing cache file, or to + // determine where to create a new one. + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\tChecking possible cache file paths".PHP_EOL; + } + + $paths = []; + foreach ($config->files as $file) { + $file = Common::realpath($file); + while ($file !== DIRECTORY_SEPARATOR) { + if (isset($paths[$file]) === false) { + $paths[$file] = 1; + } else { + $paths[$file]++; + } + + $lastFile = $file; + $file = dirname($file); + if ($file === $lastFile) { + // Just in case something went wrong, + // we don't want to end up in an infinite loop. + break; + } + } + } + + ksort($paths); + $paths = array_reverse($paths); + + $numFiles = count($config->files); + + $cacheFile = null; + $cacheDir = getenv('XDG_CACHE_HOME'); + if ($cacheDir === false || is_dir($cacheDir) === false) { + $cacheDir = sys_get_temp_dir(); + } + + foreach ($paths as $file => $count) { + if ($count !== $numFiles) { + unset($paths[$file]); + continue; + } + + $fileHash = substr(sha1($file), 0, 12); + $testFile = $cacheDir.DIRECTORY_SEPARATOR."phpcs.$fileHash.$cacheHash.cache"; + if ($cacheFile === null) { + // This will be our default location if we can't find + // an existing file. + $cacheFile = $testFile; + } + + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t\t=> $testFile".PHP_EOL; + echo "\t\t\t * based on shared location: $file *".PHP_EOL; + } + + if (file_exists($testFile) === true) { + $cacheFile = $testFile; + break; + } + }//end foreach + + if ($cacheFile === null) { + // Unlikely, but just in case $paths is empty for some reason. + $cacheFile = $cacheDir.DIRECTORY_SEPARATOR."phpcs.$cacheHash.cache"; + } + }//end if + + self::$path = $cacheFile; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t=> Using cache file: ".self::$path.PHP_EOL; + } + + if (file_exists(self::$path) === true) { + self::$cache = json_decode(file_get_contents(self::$path), true); + + // Verify the contents of the cache file. + if (self::$cache['config'] !== $configData) { + self::$cache = []; + if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* cache was invalid and has been cleared *".PHP_EOL; + } + } + } else if (PHP_CODESNIFFER_VERBOSITY > 1) { + echo "\t* cache file does not exist *".PHP_EOL; + } + + self::$cache['config'] = $configData; + + }//end load() + + + /** + * Saves the current cache to the filesystem. + * + * @return void + */ + public static function save() + { + file_put_contents(self::$path, json_encode(self::$cache)); + + }//end save() + + + /** + * Retrieves a single entry from the cache. + * + * @param string $key The key of the data to get. If NULL, + * everything in the cache is returned. + * + * @return mixed + */ + public static function get($key=null) + { + if ($key === null) { + return self::$cache; + } + + if (isset(self::$cache[$key]) === true) { + return self::$cache[$key]; + } + + return false; + + }//end get() + + + /** + * Retrieves a single entry from the cache. + * + * @param string $key The key of the data to set. If NULL, + * sets the entire cache. + * @param mixed $value The value to set. + * + * @return void + */ + public static function set($key, $value) + { + if ($key === null) { + self::$cache = $value; + } else { + self::$cache[$key] = $value; + } + + }//end set() + + + /** + * Retrieves the number of cache entries. + * + * @return int + */ + public static function getSize() + { + return (count(self::$cache) - 1); + + }//end getSize() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Common.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Common.php new file mode 100644 index 000000000..cb6965f62 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Common.php @@ -0,0 +1,605 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use InvalidArgumentException; +use Phar; + +class Common +{ + + /** + * An array of variable types for param/var we will check. + * + * @var string[] + */ + public static $allowedTypes = [ + 'array', + 'boolean', + 'float', + 'integer', + 'mixed', + 'object', + 'string', + 'resource', + 'callable', + ]; + + + /** + * Return TRUE if the path is a PHAR file. + * + * @param string $path The path to use. + * + * @return bool + */ + public static function isPharFile($path) + { + if (strpos($path, 'phar://') === 0) { + return true; + } + + return false; + + }//end isPharFile() + + + /** + * Checks if a file is readable. + * + * Addresses PHP bug related to reading files from network drives on Windows. + * e.g. when using WSL2. + * + * @param string $path The path to the file. + * + * @return boolean + */ + public static function isReadable($path) + { + if (@is_readable($path) === true) { + return true; + } + + if (@file_exists($path) === true && @is_file($path) === true) { + $f = @fopen($path, 'rb'); + if (fclose($f) === true) { + return true; + } + } + + return false; + + }//end isReadable() + + + /** + * CodeSniffer alternative for realpath. + * + * Allows for PHAR support. + * + * @param string $path The path to use. + * + * @return string|false + */ + public static function realpath($path) + { + // Support the path replacement of ~ with the user's home directory. + if (substr($path, 0, 2) === '~/') { + $homeDir = getenv('HOME'); + if ($homeDir !== false) { + $path = $homeDir.substr($path, 1); + } + } + + // Check for process substitution. + if (strpos($path, '/dev/fd') === 0) { + return str_replace('/dev/fd', 'php://fd', $path); + } + + // No extra work needed if this is not a phar file. + if (self::isPharFile($path) === false) { + return realpath($path); + } + + // Before trying to break down the file path, + // check if it exists first because it will mostly not + // change after running the below code. + if (file_exists($path) === true) { + return $path; + } + + $phar = Phar::running(false); + $extra = str_replace('phar://'.$phar, '', $path); + $path = realpath($phar); + if ($path === false) { + return false; + } + + $path = 'phar://'.$path.$extra; + if (file_exists($path) === true) { + return $path; + } + + return false; + + }//end realpath() + + + /** + * Removes a base path from the front of a file path. + * + * @param string $path The path of the file. + * @param string $basepath The base path to remove. This should not end + * with a directory separator. + * + * @return string + */ + public static function stripBasepath($path, $basepath) + { + if (empty($basepath) === true) { + return $path; + } + + $basepathLen = strlen($basepath); + if (substr($path, 0, $basepathLen) === $basepath) { + $path = substr($path, $basepathLen); + } + + $path = ltrim($path, DIRECTORY_SEPARATOR); + if ($path === '') { + $path = '.'; + } + + return $path; + + }//end stripBasepath() + + + /** + * Detects the EOL character being used in a string. + * + * @param string $contents The contents to check. + * + * @return string + */ + public static function detectLineEndings($contents) + { + if (preg_match("/\r\n?|\n/", $contents, $matches) !== 1) { + // Assume there are no newlines. + $eolChar = "\n"; + } else { + $eolChar = $matches[0]; + } + + return $eolChar; + + }//end detectLineEndings() + + + /** + * Check if STDIN is a TTY. + * + * @return boolean + */ + public static function isStdinATTY() + { + // The check is slow (especially calling `tty`) so we static + // cache the result. + static $isTTY = null; + + if ($isTTY !== null) { + return $isTTY; + } + + if (defined('STDIN') === false) { + return false; + } + + // If PHP has the POSIX extensions we will use them. + if (function_exists('posix_isatty') === true) { + $isTTY = (posix_isatty(STDIN) === true); + return $isTTY; + } + + // Next try is detecting whether we have `tty` installed and use that. + if (defined('PHP_WINDOWS_VERSION_PLATFORM') === true) { + $devnull = 'NUL'; + $which = 'where'; + } else { + $devnull = '/dev/null'; + $which = 'which'; + } + + $tty = trim(shell_exec("$which tty 2> $devnull")); + if (empty($tty) === false) { + exec("tty -s 2> $devnull", $output, $returnValue); + $isTTY = ($returnValue === 0); + return $isTTY; + } + + // Finally we will use fstat. The solution borrowed from + // https://stackoverflow.com/questions/11327367/detect-if-a-php-script-is-being-run-interactively-or-not + // This doesn't work on Mingw/Cygwin/... using Mintty but they + // have `tty` installed. + $type = [ + 'S_IFMT' => 0170000, + 'S_IFIFO' => 0010000, + ]; + + $stat = fstat(STDIN); + $mode = ($stat['mode'] & $type['S_IFMT']); + $isTTY = ($mode !== $type['S_IFIFO']); + + return $isTTY; + + }//end isStdinATTY() + + + /** + * Escape a path to a system command. + * + * @param string $cmd The path to the system command. + * + * @return string + */ + public static function escapeshellcmd($cmd) + { + $cmd = escapeshellcmd($cmd); + + if (stripos(PHP_OS, 'WIN') === 0) { + // Spaces are not escaped by escapeshellcmd on Windows, but need to be + // for the command to be able to execute. + $cmd = preg_replace('`(? 0) { + return false; + } + + if ($strict === true) { + // Check that there are not two capital letters next to each other. + $length = strlen($string); + $lastCharWasCaps = $classFormat; + + for ($i = 1; $i < $length; $i++) { + $ascii = ord($string[$i]); + if ($ascii >= 48 && $ascii <= 57) { + // The character is a number, so it can't be a capital. + $isCaps = false; + } else { + if (strtoupper($string[$i]) === $string[$i]) { + $isCaps = true; + } else { + $isCaps = false; + } + } + + if ($isCaps === true && $lastCharWasCaps === true) { + return false; + } + + $lastCharWasCaps = $isCaps; + } + }//end if + + return true; + + }//end isCamelCaps() + + + /** + * Returns true if the specified string is in the underscore caps format. + * + * @param string $string The string to verify. + * + * @return boolean + */ + public static function isUnderscoreName($string) + { + // If there is whitespace in the name, it can't be valid. + if (strpos($string, ' ') !== false) { + return false; + } + + $validName = true; + $nameBits = explode('_', $string); + + if (preg_match('|^[A-Z]|', $string) === 0) { + // Name does not begin with a capital letter. + $validName = false; + } else { + foreach ($nameBits as $bit) { + if ($bit === '') { + continue; + } + + if ($bit[0] !== strtoupper($bit[0])) { + $validName = false; + break; + } + } + } + + return $validName; + + }//end isUnderscoreName() + + + /** + * Returns a valid variable type for param/var tags. + * + * If type is not one of the standard types, it must be a custom type. + * Returns the correct type name suggestion if type name is invalid. + * + * @param string $varType The variable type to process. + * + * @return string + */ + public static function suggestType($varType) + { + if ($varType === '') { + return ''; + } + + if (in_array($varType, self::$allowedTypes, true) === true) { + return $varType; + } else { + $lowerVarType = strtolower($varType); + switch ($lowerVarType) { + case 'bool': + case 'boolean': + return 'boolean'; + case 'double': + case 'real': + case 'float': + return 'float'; + case 'int': + case 'integer': + return 'integer'; + case 'array()': + case 'array': + return 'array'; + }//end switch + + if (strpos($lowerVarType, 'array(') !== false) { + // Valid array declaration: + // array, array(type), array(type1 => type2). + $matches = []; + $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i'; + if (preg_match($pattern, $varType, $matches) !== 0) { + $type1 = ''; + if (isset($matches[1]) === true) { + $type1 = $matches[1]; + } + + $type2 = ''; + if (isset($matches[3]) === true) { + $type2 = $matches[3]; + } + + $type1 = self::suggestType($type1); + $type2 = self::suggestType($type2); + if ($type2 !== '') { + $type2 = ' => '.$type2; + } + + return "array($type1$type2)"; + } else { + return 'array'; + }//end if + } else if (in_array($lowerVarType, self::$allowedTypes, true) === true) { + // A valid type, but not lower cased. + return $lowerVarType; + } else { + // Must be a custom type name. + return $varType; + }//end if + }//end if + + }//end suggestType() + + + /** + * Given a sniff class name, returns the code for the sniff. + * + * @param string $sniffClass The fully qualified sniff class name. + * + * @return string + * + * @throws \InvalidArgumentException When $sniffClass is not a non-empty string. + * @throws \InvalidArgumentException When $sniffClass is not a FQN for a sniff(test) class. + */ + public static function getSniffCode($sniffClass) + { + if (is_string($sniffClass) === false || $sniffClass === '') { + throw new InvalidArgumentException('The $sniffClass parameter must be a non-empty string'); + } + + $parts = explode('\\', $sniffClass); + $partsCount = count($parts); + $sniff = $parts[($partsCount - 1)]; + + if (substr($sniff, -5) === 'Sniff') { + // Sniff class name. + $sniff = substr($sniff, 0, -5); + } else if (substr($sniff, -8) === 'UnitTest') { + // Unit test class name. + $sniff = substr($sniff, 0, -8); + } else { + throw new InvalidArgumentException( + 'The $sniffClass parameter was not passed a fully qualified sniff(test) class name. Received: '.$sniffClass + ); + } + + $standard = ''; + if (isset($parts[($partsCount - 4)]) === true) { + $standard = $parts[($partsCount - 4)]; + } + + $category = ''; + if (isset($parts[($partsCount - 2)]) === true) { + $category = $parts[($partsCount - 2)]; + } + + return $standard.'.'.$category.'.'.$sniff; + + }//end getSniffCode() + + + /** + * Removes project-specific information from a sniff class name. + * + * @param string $sniffClass The fully qualified sniff class name. + * + * @return string + */ + public static function cleanSniffClass($sniffClass) + { + $newName = strtolower($sniffClass); + + $sniffPos = strrpos($newName, '\sniffs\\'); + if ($sniffPos === false) { + // Nothing we can do as it isn't in a known format. + return $newName; + } + + $end = (strlen($newName) - $sniffPos + 1); + $start = strrpos($newName, '\\', ($end * -1)); + + if ($start === false) { + // Nothing needs to be cleaned. + return $newName; + } + + $newName = substr($newName, ($start + 1)); + return $newName; + + }//end cleanSniffClass() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Help.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Help.php new file mode 100644 index 000000000..5a686a97a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Help.php @@ -0,0 +1,625 @@ + + * @copyright 2024 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use InvalidArgumentException; +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Util\Common; + +final class Help +{ + + + /** + * Short options which are available for both the `phpcs` as well as the `phpcbf` command. + * + * @var string + */ + const DEFAULT_SHORT_OPTIONS = '-hilnpqvw'; + + /** + * Long options which are available for both the `phpcs` as well as the `phpcbf` command. + * + * {@internal This should be a constant array, but those aren't supported until PHP 5.6.} + * + * @var string Comma-separated list of the option names. + */ + const DEFAULT_LONG_OPTIONS = 'basepath,bootstrap,colors,encoding,error-severity,exclude,extensions,file,file-list,filter,ignore,ignore-annotations,no-colors,parallel,php-ini,report-width,runtime-set,severity,sniffs,standard,stdin-path,tab-width,version,vv,vvv,warning-severity'; + + /** + * Minimum screen width. + * + * The help info needs room to display, so this is the minimum acceptable width. + * + * @var integer + */ + const MIN_WIDTH = 60; + + /** + * Indent option lines. + * + * @var string + */ + const INDENT = ' '; + + /** + * Gutter spacing for between the option argument info and the option description. + * + * @var string + */ + const GUTTER = ' '; + + /** + * The current PHPCS Configuration. + * + * @var \PHP_CodeSniffer\Config + */ + private $config; + + /** + * The options which should be shown for this help screen. + * + * @var array + */ + private $requestedOptions = []; + + /** + * Active options per category (after filtering). + * + * @var array>> + */ + private $activeOptions = []; + + /** + * Width of the indent for option lines. + * + * @var integer + */ + private $indentWidth = 0; + + /** + * Width of the gutter spacing. + * + * @var integer + */ + private $gutterWidth = 0; + + /** + * Width of longest option argument info entry. + * + * @var integer + */ + private $maxOptionNameLength = 0; + + + /** + * Constructor. + * + * @param \PHP_CodeSniffer\Config $config Configuration object. + * @param array $longOptions The long options which should be shown. + * @param string $shortOptions The short options which should be shown. + * + * @throws \InvalidArgumentException When $shortOptions is not a string. + */ + public function __construct(Config $config, array $longOptions, $shortOptions='') + { + if (is_string($shortOptions) === false) { + throw new InvalidArgumentException('The $shortOptions parameter must be a string'); + } + + $this->config = $config; + $this->requestedOptions = array_merge($longOptions, str_split($shortOptions)); + + $this->filterOptions(); + + $this->indentWidth = strlen(self::INDENT); + $this->gutterWidth = strlen(self::GUTTER); + + $this->setMaxOptionNameLength(); + + }//end __construct() + + + /** + * Display the help info. + * + * @return void + */ + public function display() + { + $this->printUsage(); + $this->printCategories(); + + }//end display() + + + /** + * Filter the available options based on the requested options. + * + * @return void + */ + private function filterOptions() + { + $filteredOptions = $this->getAllOptions(); + + foreach ($filteredOptions as $category => $options) { + // Initial state set to "true" to prevent a spacer at the start of an array. + $lastWasSpacer = true; + $spacerCount = 0; + + foreach ($options as $name => $option) { + if ($lastWasSpacer !== true && strpos($name, 'blank-line') === 0) { + ++$spacerCount; + $lastWasSpacer = true; + continue; + } + + if (in_array($name, $this->requestedOptions, true) === false) { + unset($filteredOptions[$category][$name]); + continue; + } + + $lastWasSpacer = false; + } + + // Make sure the final array doesn't contain a spacer at the end. + if (empty($filteredOptions[$category]) === false) { + end($filteredOptions[$category]); + $key = key($filteredOptions[$category]); + if (strpos($key, 'blank-line') === 0) { + unset($filteredOptions[$category][$key]); + --$spacerCount; + } + } + + // Remove categories now left empty. + if (empty($filteredOptions[$category]) === true || count($filteredOptions[$category]) === $spacerCount) { + unset($filteredOptions[$category]); + } + }//end foreach + + $this->activeOptions = $filteredOptions; + + }//end filterOptions() + + + /** + * Determine the length of the longest option argument and store it. + * + * @return void + */ + private function setMaxOptionNameLength() + { + $lengths = []; + foreach ($this->activeOptions as $category => $options) { + foreach ($options as $option) { + if (isset($option['argument']) === false) { + continue; + } + + $lengths[] = strlen($option['argument']); + } + } + + if (empty($lengths) === false) { + $this->maxOptionNameLength = max($lengths); + } + + }//end setMaxOptionNameLength() + + + /** + * Get the maximum width which can be used to display the help info. + * + * Independently of user preference/auto-determined width of the current screen, + * a minimum width is needed to display information, so don't allow this to get too low. + * + * @return int + */ + private function getMaxWidth() + { + return max(self::MIN_WIDTH, $this->config->reportWidth); + + }//end getMaxWidth() + + + /** + * Get the maximum width for the text in the option description column. + * + * @return int + */ + private function getDescriptionColumnWidth() + { + return ($this->getMaxWidth() - $this->maxOptionNameLength - $this->indentWidth - $this->gutterWidth); + + }//end getDescriptionColumnWidth() + + + /** + * Get the length of the indentation needed for follow up lines when the description does not fit on one line. + * + * @return int + */ + private function getDescriptionFollowupLineIndentLength() + { + return ($this->maxOptionNameLength + $this->indentWidth + $this->gutterWidth); + + }//end getDescriptionFollowupLineIndentLength() + + + /** + * Print basic usage information to the screen. + * + * @return void + */ + private function printUsage() + { + $command = 'phpcs'; + if (defined('PHP_CODESNIFFER_CBF') === true && PHP_CODESNIFFER_CBF === true) { + $command = 'phpcbf'; // @codeCoverageIgnore + } + + $this->printCategoryHeader('Usage'); + + echo self::INDENT.$command.' [options] '.PHP_EOL; + + }//end printUsage() + + + /** + * Print details of all the requested options to the screen, sorted by category. + * + * @return void + */ + private function printCategories() + { + foreach ($this->activeOptions as $category => $options) { + $this->printCategoryHeader($category); + $this->printCategoryOptions($options); + } + + }//end printCategories() + + + /** + * Print a category header. + * + * @param string $header The header text. + * + * @return void + */ + private function printCategoryHeader($header) + { + $header .= ':'; + if ($this->config->colors === true) { + $header = "\033[33m{$header}\033[0m"; + } + + echo PHP_EOL.$header.PHP_EOL; + + }//end printCategoryHeader() + + + /** + * Print the options for a category. + * + * @param array> $options The options to display. + * + * @return void + */ + private function printCategoryOptions(array $options) + { + $maxDescriptionWidth = $this->getDescriptionColumnWidth(); + $maxTextWidth = ($this->getMaxWidth() - $this->indentWidth); + $secondLineIndent = str_repeat(' ', $this->getDescriptionFollowupLineIndentLength()); + + $output = ''; + foreach ($options as $option) { + if (isset($option['spacer']) === true) { + $output .= PHP_EOL; + } + + if (isset($option['text']) === true) { + $text = wordwrap($option['text'], $maxTextWidth, "\n"); + $output .= self::INDENT.implode(PHP_EOL.self::INDENT, explode("\n", $text)).PHP_EOL; + } + + if (isset($option['argument'], $option['description']) === true) { + $argument = str_pad($option['argument'], $this->maxOptionNameLength); + $argument = $this->colorizeVariableInput($argument); + $output .= self::INDENT."\033[32m{$argument}\033[0m"; + $output .= self::GUTTER; + + $description = wordwrap($option['description'], $maxDescriptionWidth, "\n"); + $output .= implode(PHP_EOL.$secondLineIndent, explode("\n", $description)).PHP_EOL; + } + } + + if ($this->config->colors === false) { + $output = Common::stripColors($output); + } + + echo $output; + + }//end printCategoryOptions() + + + /** + * Colorize "variable" input in the option argument info. + * + * For the purposes of this method, "variable" input is text between <> brackets. + * The regex allows for multiple tags and nested tags. + * + * @param string $text The text to process. + * + * @return string + */ + private function colorizeVariableInput($text) + { + return preg_replace('`(<(?:(?>[^<>]+)|(?R))*>)`', "\033[36m".'$1'."\033[32m", $text); + + }//end colorizeVariableInput() + + + /** + * Retrieve the help details for all supported CLI arguments per category. + * + * @return array>> + */ + private function getAllOptions() + { + $options = []; + + // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- Readability is more important. + $options['Scan targets'] = [ + 'file' => [ + 'argument' => '', + 'description' => 'One or more files and/or directories to check, space separated.', + ], + '-' => [ + 'argument' => '-', + 'description' => 'Check STDIN instead of local files and directories.', + ], + 'stdin-path' => [ + 'argument' => '--stdin-path=', + 'description' => 'If processing STDIN, the file path that STDIN will be processed as.', + ], + 'file-list' => [ + 'argument' => '--file-list=', + 'description' => 'Check the files and/or directories which are defined in the file to which the path is provided (one per line).', + ], + 'filter' => [ + 'argument' => '--filter=', + 'description' => 'Check based on a predefined file filter. Use either the "GitModified" or "GitStaged" filter, or specify the path to a custom filter class.', + ], + 'ignore' => [ + 'argument' => '--ignore=', + 'description' => 'Ignore files based on a comma-separated list of patterns matching files and/or directories.', + ], + 'extensions' => [ + 'argument' => '--extensions=', + 'description' => 'Check files with the specified file extensions (comma-separated list). Defaults to php,inc/php,js,css.'."\n" + .'The type of the file can be specified using: ext/type; e.g. module/php,es/js.', + ], + 'l' => [ + 'argument' => '-l', + 'description' => 'Check local directory only, no recursion.', + ], + ]; + + $options['Rule Selection Options'] = [ + 'standard' => [ + 'argument' => '--standard=', + 'description' => 'The name of, or the path to, the coding standard to use. Can be a comma-separated list specifying multiple standards. If no standard is specified, PHP_CodeSniffer will look for a [.]phpcs.xml[.dist] custom ruleset file in the current directory and those above it.', + ], + 'sniffs' => [ + 'argument' => '--sniffs=', + 'description' => 'A comma-separated list of sniff codes to limit the scan to. All sniffs must be part of the standard in use.', + ], + 'exclude' => [ + 'argument' => '--exclude=', + 'description' => 'A comma-separated list of sniff codes to exclude from the scan. All sniffs must be part of the standard in use.', + ], + 'blank-line' => ['spacer' => ''], + + 'i' => [ + 'argument' => '-i', + 'description' => 'Show a list of installed coding standards.', + ], + 'e' => [ + 'argument' => '-e', + 'description' => 'Explain a standard by showing the names of all the sniffs it includes.', + ], + 'generator' => [ + 'argument' => '--generator=', + 'description' => 'Show documentation for a standard. Use either the "HTML", "Markdown" or "Text" generator.', + ], + ]; + + $options['Run Options'] = [ + 'a' => [ + 'argument' => '-a', + 'description' => 'Run in interactive mode, pausing after each file.', + ], + 'bootstrap' => [ + 'argument' => '--bootstrap=', + 'description' => 'Run the specified file(s) before processing begins. A list of files can be provided, separated by commas.', + ], + 'cache' => [ + 'argument' => '--cache[=]', + 'description' => 'Cache results between runs. Optionally, can be provided to use a specific file for caching. Otherwise, a temporary file is used.', + ], + 'no-cache' => [ + 'argument' => '--no-cache', + 'description' => 'Do not cache results between runs (default).', + ], + 'parallel' => [ + 'argument' => '--parallel=', + 'description' => 'The number of files to be checked simultaneously. Defaults to 1 (no parallel processing).'."\n" + .'If enabled, this option only takes effect if the PHP PCNTL (Process Control) extension is available.', + ], + 'suffix' => [ + 'argument' => '--suffix=', + 'description' => 'Write modified files to a filename using this suffix ("diff" and "patch" are not used in this mode).', + ], + 'blank-line' => ['spacer' => ''], + + 'php-ini' => [ + 'argument' => '-d ', + 'description' => 'Set the [key] php.ini value to [value] or set to [true] if value is omitted.'."\n" + .'Note: only php.ini settings which can be changed at runtime are supported.', + ], + ]; + + $options['Reporting Options'] = [ + 'report' => [ + 'argument' => '--report=', + 'description' => 'Print either the "full", "xml", "checkstyle", "csv", "json", "junit", "emacs", "source", "summary", "diff", "svnblame", "gitblame", "hgblame", "notifysend" or "performance" report or specify the path to a custom report class. By default, the "full" report is displayed.', + ], + 'report-file' => [ + 'argument' => '--report-file=', + 'description' => 'Write the report to the specified file path.', + ], + 'report-report' => [ + 'argument' => '--report-=', + 'description' => 'Write the report specified in to the specified file path.', + ], + 'report-width' => [ + 'argument' => '--report-width=', + 'description' => 'How many columns wide screen reports should be. Set to "auto" to use current screen width, where supported.', + ], + 'basepath' => [ + 'argument' => '--basepath=', + 'description' => 'Strip a path from the front of file paths inside reports.', + ], + 'blank-line-1' => ['spacer' => ''], + + 'w' => [ + 'argument' => '-w', + 'description' => 'Include both warnings and errors (default).', + ], + 'n' => [ + 'argument' => '-n', + 'description' => 'Do not include warnings. Shortcut for "--warning-severity=0".', + ], + 'severity' => [ + 'argument' => '--severity=', + 'description' => 'The minimum severity required to display an error or warning. Defaults to 5.', + ], + 'error-severity' => [ + 'argument' => '--error-severity=', + 'description' => 'The minimum severity required to display an error. Defaults to 5.', + ], + 'warning-severity' => [ + 'argument' => '--warning-severity=', + 'description' => 'The minimum severity required to display a warning. Defaults to 5.', + ], + 'blank-line-2' => ['spacer' => ''], + + 's' => [ + 'argument' => '-s', + 'description' => 'Show sniff error codes in all reports.', + ], + 'ignore-annotations' => [ + 'argument' => '--ignore-annotations', + 'description' => 'Ignore all "phpcs:..." annotations in code comments.', + ], + 'colors' => [ + 'argument' => '--colors', + 'description' => 'Use colors in screen output.', + ], + 'no-colors' => [ + 'argument' => '--no-colors', + 'description' => 'Do not use colors in screen output (default).', + ], + 'p' => [ + 'argument' => '-p', + 'description' => 'Show progress of the run.', + ], + 'q' => [ + 'argument' => '-q', + 'description' => 'Quiet mode; disables progress and verbose output.', + ], + 'm' => [ + 'argument' => '-m', + 'description' => 'Stop error messages from being recorded. This saves a lot of memory but stops many reports from being used.', + ], + ]; + + $options['Configuration Options'] = [ + 'encoding' => [ + 'argument' => '--encoding=', + 'description' => 'The encoding of the files being checked. Defaults to "utf-8".', + ], + 'tab-width' => [ + 'argument' => '--tab-width=', + 'description' => 'The number of spaces each tab represents.', + ], + 'blank-line' => ['spacer' => ''], + + 'config-explain' => [ + 'text' => 'Default values for a selection of options can be stored in a user-specific CodeSniffer.conf configuration file.'."\n" + .'This applies to the following options: "default_standard", "report_format", "tab_width", "encoding", "severity", "error_severity", "warning_severity", "show_warnings", "report_width", "show_progress", "quiet", "colors", "cache", "parallel".', + ], + 'config-show' => [ + 'argument' => '--config-show', + 'description' => 'Show the configuration options which are currently stored in the applicable CodeSniffer.conf file.', + ], + 'config-set' => [ + 'argument' => '--config-set ', + 'description' => 'Save a configuration option to the CodeSniffer.conf file.', + ], + 'config-delete' => [ + 'argument' => '--config-delete ', + 'description' => 'Delete a configuration option from the CodeSniffer.conf file.', + ], + 'runtime-set' => [ + 'argument' => '--runtime-set ', + 'description' => 'Set a configuration option to be applied to the current scan run only.', + ], + ]; + + $options['Miscellaneous Options'] = [ + 'h' => [ + 'argument' => '-h, -?, --help', + 'description' => 'Print this help message.', + ], + 'version' => [ + 'argument' => '--version', + 'description' => 'Print version information.', + ], + 'v' => [ + 'argument' => '-v', + 'description' => 'Verbose output: Print processed files.', + ], + 'vv' => [ + 'argument' => '-vv', + 'description' => 'Verbose output: Print ruleset and token output.', + ], + 'vvv' => [ + 'argument' => '-vvv', + 'description' => 'Verbose output: Print sniff processing information.', + ], + ]; + // phpcs:enable + + return $options; + + }//end getAllOptions() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Standards.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Standards.php new file mode 100644 index 000000000..f7217a72e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Standards.php @@ -0,0 +1,340 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +use DirectoryIterator; +use PHP_CodeSniffer\Config; + +class Standards +{ + + + /** + * Get a list of paths where standards are installed. + * + * Unresolvable relative paths will be excluded from the results. + * + * @return array + */ + public static function getInstalledStandardPaths() + { + $ds = DIRECTORY_SEPARATOR; + + $installedPaths = [dirname(dirname(__DIR__)).$ds.'src'.$ds.'Standards']; + $configPaths = Config::getConfigData('installed_paths'); + if ($configPaths !== null) { + $installedPaths = array_merge($installedPaths, explode(',', $configPaths)); + } + + $resolvedInstalledPaths = []; + foreach ($installedPaths as $installedPath) { + if (substr($installedPath, 0, 1) === '.') { + $installedPath = Common::realPath(__DIR__.$ds.'..'.$ds.'..'.$ds.$installedPath); + if ($installedPath === false) { + continue; + } + } + + $resolvedInstalledPaths[] = $installedPath; + } + + return $resolvedInstalledPaths; + + }//end getInstalledStandardPaths() + + + /** + * Get the details of all coding standards installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a Sniffs subdirectory. + * + * The details returned for each standard are: + * - path: the path to the coding standard's main directory + * - name: the name of the coding standard, as sourced from the ruleset.xml file + * - namespace: the namespace used by the coding standard, as sourced from the ruleset.xml file + * + * If you only need the paths to the installed standards, + * use getInstalledStandardPaths() instead as it performs less work to + * retrieve coding standard names. + * + * @param boolean $includeGeneric If true, the special "Generic" + * coding standard will be included + * if installed. + * @param string $standardsDir A specific directory to look for standards + * in. If not specified, PHP_CodeSniffer will + * look in its default locations. + * + * @return array + * @see getInstalledStandardPaths() + */ + public static function getInstalledStandardDetails( + $includeGeneric=false, + $standardsDir='' + ) { + $rulesets = []; + + if ($standardsDir === '') { + $installedPaths = self::getInstalledStandardPaths(); + } else { + $installedPaths = [$standardsDir]; + } + + foreach ($installedPaths as $standardsDir) { + // Check if the installed dir is actually a standard itself. + $csFile = $standardsDir.'/ruleset.xml'; + if (is_file($csFile) === true) { + $rulesets[] = $csFile; + continue; + } + + if (is_dir($standardsDir) === false) { + continue; + } + + $di = new DirectoryIterator($standardsDir); + foreach ($di as $file) { + if ($file->isDir() === true && $file->isDot() === false) { + $filename = $file->getFilename(); + + // Ignore the special "Generic" standard. + if ($includeGeneric === false && $filename === 'Generic') { + continue; + } + + // Valid coding standard dirs include a ruleset. + $csFile = $file->getPathname().'/ruleset.xml'; + if (is_file($csFile) === true) { + $rulesets[] = $csFile; + } + } + } + }//end foreach + + $installedStandards = []; + + foreach ($rulesets as $rulesetPath) { + $ruleset = @simplexml_load_string(file_get_contents($rulesetPath)); + if ($ruleset === false) { + continue; + } + + $standardName = (string) $ruleset['name']; + $dirname = basename(dirname($rulesetPath)); + + if (isset($ruleset['namespace']) === true) { + $namespace = (string) $ruleset['namespace']; + } else { + $namespace = $dirname; + } + + $installedStandards[$dirname] = [ + 'path' => dirname($rulesetPath), + 'name' => $standardName, + 'namespace' => $namespace, + ]; + }//end foreach + + return $installedStandards; + + }//end getInstalledStandardDetails() + + + /** + * Get a list of all coding standards installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a Sniffs subdirectory. + * + * @param boolean $includeGeneric If true, the special "Generic" + * coding standard will be included + * if installed. + * @param string $standardsDir A specific directory to look for standards + * in. If not specified, PHP_CodeSniffer will + * look in its default locations. + * + * @return array + * @see isInstalledStandard() + */ + public static function getInstalledStandards( + $includeGeneric=false, + $standardsDir='' + ) { + $installedStandards = []; + + if ($standardsDir === '') { + $installedPaths = self::getInstalledStandardPaths(); + } else { + $installedPaths = [$standardsDir]; + } + + foreach ($installedPaths as $standardsDir) { + // Check if the installed dir is actually a standard itself. + $csFile = $standardsDir.'/ruleset.xml'; + if (is_file($csFile) === true) { + $basename = basename($standardsDir); + $installedStandards[$basename] = $basename; + continue; + } + + if (is_dir($standardsDir) === false) { + // Doesn't exist. + continue; + } + + $di = new DirectoryIterator($standardsDir); + $standardsInDir = []; + foreach ($di as $file) { + if ($file->isDir() === true && $file->isDot() === false) { + $filename = $file->getFilename(); + + // Ignore the special "Generic" standard. + if ($includeGeneric === false && $filename === 'Generic') { + continue; + } + + // Valid coding standard dirs include a ruleset. + $csFile = $file->getPathname().'/ruleset.xml'; + if (is_file($csFile) === true) { + $standardsInDir[$filename] = $filename; + } + } + } + + natsort($standardsInDir); + $installedStandards += $standardsInDir; + }//end foreach + + return $installedStandards; + + }//end getInstalledStandards() + + + /** + * Determine if a standard is installed. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a ruleset.xml file. + * + * @param string $standard The name of the coding standard. + * + * @return boolean + * @see getInstalledStandards() + */ + public static function isInstalledStandard($standard) + { + $path = self::getInstalledStandardPath($standard); + if ($path !== null && strpos($path, 'ruleset.xml') !== false) { + return true; + } else { + // This could be a custom standard, installed outside our + // standards directory. + $standard = Common::realPath($standard); + if ($standard === false) { + return false; + } + + // Might be an actual ruleset file itUtil. + // If it has an XML extension, let's at least try it. + if (is_file($standard) === true + && (substr(strtolower($standard), -4) === '.xml' + || substr(strtolower($standard), -9) === '.xml.dist') + ) { + return true; + } + + // If it is a directory with a ruleset.xml file in it, + // it is a standard. + $ruleset = rtrim($standard, ' /\\').DIRECTORY_SEPARATOR.'ruleset.xml'; + if (is_file($ruleset) === true) { + return true; + } + }//end if + + return false; + + }//end isInstalledStandard() + + + /** + * Return the path of an installed coding standard. + * + * Coding standards are directories located in the + * CodeSniffer/Standards directory. Valid coding standards + * include a ruleset.xml file. + * + * @param string $standard The name of the coding standard. + * + * @return string|null + */ + public static function getInstalledStandardPath($standard) + { + if (strpos($standard, '.') !== false) { + return null; + } + + $installedPaths = self::getInstalledStandardPaths(); + foreach ($installedPaths as $installedPath) { + $standardPath = $installedPath.DIRECTORY_SEPARATOR.$standard; + if (file_exists($standardPath) === false) { + if (basename($installedPath) !== $standard) { + continue; + } + + $standardPath = $installedPath; + } + + $path = Common::realpath($standardPath.DIRECTORY_SEPARATOR.'ruleset.xml'); + + if ($path !== false && is_file($path) === true) { + return $path; + } else if (Common::isPharFile($standardPath) === true) { + $path = Common::realpath($standardPath); + if ($path !== false) { + return $path; + } + } + }//end foreach + + return null; + + }//end getInstalledStandardPath() + + + /** + * Prints out a list of installed coding standards. + * + * @return void + */ + public static function printInstalledStandards() + { + $installedStandards = self::getInstalledStandards(); + $numStandards = count($installedStandards); + + if ($numStandards === 0) { + echo 'No coding standards are installed.'.PHP_EOL; + } else { + $lastStandard = array_pop($installedStandards); + if ($numStandards === 1) { + echo "The only coding standard installed is $lastStandard".PHP_EOL; + } else { + $standardList = implode(', ', $installedStandards); + $standardList .= ' and '.$lastStandard; + echo 'The installed coding standards are '.$standardList.PHP_EOL; + } + } + + }//end printInstalledStandards() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Timing.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Timing.php new file mode 100644 index 000000000..95f6810b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Timing.php @@ -0,0 +1,133 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +class Timing +{ + + /** + * Number of milliseconds in a minute. + * + * @var int + */ + const MINUTE_IN_MS = 60000; + + /** + * Number of milliseconds in a second. + * + * @var int + */ + const SECOND_IN_MS = 1000; + + /** + * The start time of the run in microseconds. + * + * @var float + */ + private static $startTime; + + /** + * Used to make sure we only print the run time once per run. + * + * @var boolean + */ + private static $printed = false; + + + /** + * Start recording time for the run. + * + * @return void + */ + public static function startTiming() + { + + self::$startTime = microtime(true); + + }//end startTiming() + + + /** + * Get the duration of the run up to "now". + * + * @return float Duration in milliseconds. + */ + public static function getDuration() + { + if (self::$startTime === null) { + // Timing was never started. + return 0; + } + + return ((microtime(true) - self::$startTime) * 1000); + + }//end getDuration() + + + /** + * Convert a duration in milliseconds to a human readable duration string. + * + * @param float $duration Duration in milliseconds. + * + * @return string + */ + public static function getHumanReadableDuration($duration) + { + $timeString = ''; + if ($duration >= self::MINUTE_IN_MS) { + $mins = floor($duration / self::MINUTE_IN_MS); + $secs = round((fmod($duration, self::MINUTE_IN_MS) / self::SECOND_IN_MS), 2); + $timeString = $mins.' mins'; + if ($secs >= 0.01) { + $timeString .= ", $secs secs"; + } + } else if ($duration >= self::SECOND_IN_MS) { + $timeString = round(($duration / self::SECOND_IN_MS), 2).' secs'; + } else { + $timeString = round($duration).'ms'; + } + + return $timeString; + + }//end getHumanReadableDuration() + + + /** + * Print information about the run. + * + * @param boolean $force If TRUE, prints the output even if it has + * already been printed during the run. + * + * @return void + */ + public static function printRunTime($force=false) + { + if ($force === false && self::$printed === true) { + // A double call. + return; + } + + if (self::$startTime === null) { + // Timing was never started. + return; + } + + $duration = self::getDuration(); + $duration = self::getHumanReadableDuration($duration); + + $mem = round((memory_get_peak_usage(true) / (1024 * 1024)), 2).'MB'; + echo "Time: $duration; Memory: $mem".PHP_EOL.PHP_EOL; + + self::$printed = true; + + }//end printRunTime() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php new file mode 100644 index 000000000..5554cc9aa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/src/Util/Tokens.php @@ -0,0 +1,814 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util; + +define('T_NONE', 'PHPCS_T_NONE'); +define('T_OPEN_CURLY_BRACKET', 'PHPCS_T_OPEN_CURLY_BRACKET'); +define('T_CLOSE_CURLY_BRACKET', 'PHPCS_T_CLOSE_CURLY_BRACKET'); +define('T_OPEN_SQUARE_BRACKET', 'PHPCS_T_OPEN_SQUARE_BRACKET'); +define('T_CLOSE_SQUARE_BRACKET', 'PHPCS_T_CLOSE_SQUARE_BRACKET'); +define('T_OPEN_PARENTHESIS', 'PHPCS_T_OPEN_PARENTHESIS'); +define('T_CLOSE_PARENTHESIS', 'PHPCS_T_CLOSE_PARENTHESIS'); +define('T_COLON', 'PHPCS_T_COLON'); +define('T_NULLABLE', 'PHPCS_T_NULLABLE'); +define('T_STRING_CONCAT', 'PHPCS_T_STRING_CONCAT'); +define('T_INLINE_THEN', 'PHPCS_T_INLINE_THEN'); +define('T_INLINE_ELSE', 'PHPCS_T_INLINE_ELSE'); +define('T_NULL', 'PHPCS_T_NULL'); +define('T_FALSE', 'PHPCS_T_FALSE'); +define('T_TRUE', 'PHPCS_T_TRUE'); +define('T_SEMICOLON', 'PHPCS_T_SEMICOLON'); +define('T_EQUAL', 'PHPCS_T_EQUAL'); +define('T_MULTIPLY', 'PHPCS_T_MULTIPLY'); +define('T_DIVIDE', 'PHPCS_T_DIVIDE'); +define('T_PLUS', 'PHPCS_T_PLUS'); +define('T_MINUS', 'PHPCS_T_MINUS'); +define('T_MODULUS', 'PHPCS_T_MODULUS'); +define('T_BITWISE_AND', 'PHPCS_T_BITWISE_AND'); +define('T_BITWISE_OR', 'PHPCS_T_BITWISE_OR'); +define('T_BITWISE_XOR', 'PHPCS_T_BITWISE_XOR'); +define('T_BITWISE_NOT', 'PHPCS_T_BITWISE_NOT'); +define('T_ARRAY_HINT', 'PHPCS_T_ARRAY_HINT'); +define('T_GREATER_THAN', 'PHPCS_T_GREATER_THAN'); +define('T_LESS_THAN', 'PHPCS_T_LESS_THAN'); +define('T_BOOLEAN_NOT', 'PHPCS_T_BOOLEAN_NOT'); +define('T_SELF', 'PHPCS_T_SELF'); +define('T_PARENT', 'PHPCS_T_PARENT'); +define('T_DOUBLE_QUOTED_STRING', 'PHPCS_T_DOUBLE_QUOTED_STRING'); +define('T_COMMA', 'PHPCS_T_COMMA'); +define('T_HEREDOC', 'PHPCS_T_HEREDOC'); +define('T_PROTOTYPE', 'PHPCS_T_PROTOTYPE'); +define('T_THIS', 'PHPCS_T_THIS'); +define('T_REGULAR_EXPRESSION', 'PHPCS_T_REGULAR_EXPRESSION'); +define('T_PROPERTY', 'PHPCS_T_PROPERTY'); +define('T_LABEL', 'PHPCS_T_LABEL'); +define('T_OBJECT', 'PHPCS_T_OBJECT'); +define('T_CLOSE_OBJECT', 'PHPCS_T_CLOSE_OBJECT'); +define('T_COLOUR', 'PHPCS_T_COLOUR'); +define('T_HASH', 'PHPCS_T_HASH'); +define('T_URL', 'PHPCS_T_URL'); +define('T_STYLE', 'PHPCS_T_STYLE'); +define('T_ASPERAND', 'PHPCS_T_ASPERAND'); +define('T_DOLLAR', 'PHPCS_T_DOLLAR'); +define('T_TYPEOF', 'PHPCS_T_TYPEOF'); +define('T_CLOSURE', 'PHPCS_T_CLOSURE'); +define('T_ANON_CLASS', 'PHPCS_T_ANON_CLASS'); +define('T_BACKTICK', 'PHPCS_T_BACKTICK'); +define('T_START_NOWDOC', 'PHPCS_T_START_NOWDOC'); +define('T_NOWDOC', 'PHPCS_T_NOWDOC'); +define('T_END_NOWDOC', 'PHPCS_T_END_NOWDOC'); +define('T_OPEN_SHORT_ARRAY', 'PHPCS_T_OPEN_SHORT_ARRAY'); +define('T_CLOSE_SHORT_ARRAY', 'PHPCS_T_CLOSE_SHORT_ARRAY'); +define('T_GOTO_LABEL', 'PHPCS_T_GOTO_LABEL'); +define('T_BINARY_CAST', 'PHPCS_T_BINARY_CAST'); +define('T_EMBEDDED_PHP', 'PHPCS_T_EMBEDDED_PHP'); +define('T_RETURN_TYPE', 'PHPCS_T_RETURN_TYPE'); +define('T_OPEN_USE_GROUP', 'PHPCS_T_OPEN_USE_GROUP'); +define('T_CLOSE_USE_GROUP', 'PHPCS_T_CLOSE_USE_GROUP'); +define('T_ZSR', 'PHPCS_T_ZSR'); +define('T_ZSR_EQUAL', 'PHPCS_T_ZSR_EQUAL'); +define('T_FN_ARROW', 'PHPCS_T_FN_ARROW'); +define('T_TYPE_UNION', 'PHPCS_T_TYPE_UNION'); +define('T_PARAM_NAME', 'PHPCS_T_PARAM_NAME'); +define('T_MATCH_ARROW', 'PHPCS_T_MATCH_ARROW'); +define('T_MATCH_DEFAULT', 'PHPCS_T_MATCH_DEFAULT'); +define('T_ATTRIBUTE_END', 'PHPCS_T_ATTRIBUTE_END'); +define('T_ENUM_CASE', 'PHPCS_T_ENUM_CASE'); +define('T_TYPE_INTERSECTION', 'PHPCS_T_TYPE_INTERSECTION'); +define('T_TYPE_OPEN_PARENTHESIS', 'PHPCS_T_TYPE_OPEN_PARENTHESIS'); +define('T_TYPE_CLOSE_PARENTHESIS', 'PHPCS_T_TYPE_CLOSE_PARENTHESIS'); + +// Some PHP 5.5 tokens, replicated for lower versions. +if (defined('T_FINALLY') === false) { + define('T_FINALLY', 'PHPCS_T_FINALLY'); +} + +if (defined('T_YIELD') === false) { + define('T_YIELD', 'PHPCS_T_YIELD'); +} + +// Some PHP 5.6 tokens, replicated for lower versions. +if (defined('T_ELLIPSIS') === false) { + define('T_ELLIPSIS', 'PHPCS_T_ELLIPSIS'); +} + +if (defined('T_POW') === false) { + define('T_POW', 'PHPCS_T_POW'); +} + +if (defined('T_POW_EQUAL') === false) { + define('T_POW_EQUAL', 'PHPCS_T_POW_EQUAL'); +} + +// Some PHP 7 tokens, replicated for lower versions. +if (defined('T_SPACESHIP') === false) { + define('T_SPACESHIP', 'PHPCS_T_SPACESHIP'); +} + +if (defined('T_COALESCE') === false) { + define('T_COALESCE', 'PHPCS_T_COALESCE'); +} + +if (defined('T_COALESCE_EQUAL') === false) { + define('T_COALESCE_EQUAL', 'PHPCS_T_COALESCE_EQUAL'); +} + +if (defined('T_YIELD_FROM') === false) { + define('T_YIELD_FROM', 'PHPCS_T_YIELD_FROM'); +} + +// Some PHP 7.4 tokens, replicated for lower versions. +if (defined('T_BAD_CHARACTER') === false) { + define('T_BAD_CHARACTER', 'PHPCS_T_BAD_CHARACTER'); +} + +if (defined('T_FN') === false) { + define('T_FN', 'PHPCS_T_FN'); +} + +// Some PHP 8.0 tokens, replicated for lower versions. +if (defined('T_NULLSAFE_OBJECT_OPERATOR') === false) { + define('T_NULLSAFE_OBJECT_OPERATOR', 'PHPCS_T_NULLSAFE_OBJECT_OPERATOR'); +} + +if (defined('T_NAME_QUALIFIED') === false) { + define('T_NAME_QUALIFIED', 'PHPCS_T_NAME_QUALIFIED'); +} + +if (defined('T_NAME_FULLY_QUALIFIED') === false) { + define('T_NAME_FULLY_QUALIFIED', 'PHPCS_T_NAME_FULLY_QUALIFIED'); +} + +if (defined('T_NAME_RELATIVE') === false) { + define('T_NAME_RELATIVE', 'PHPCS_T_NAME_RELATIVE'); +} + +if (defined('T_MATCH') === false) { + define('T_MATCH', 'PHPCS_T_MATCH'); +} + +if (defined('T_ATTRIBUTE') === false) { + define('T_ATTRIBUTE', 'PHPCS_T_ATTRIBUTE'); +} + +// Some PHP 8.1 tokens, replicated for lower versions. +if (defined('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG') === false) { + define('T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG', 'PHPCS_T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG'); +} + +if (defined('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG') === false) { + define('T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG', 'PHPCS_T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG'); +} + +if (defined('T_READONLY') === false) { + define('T_READONLY', 'PHPCS_T_READONLY'); +} + +if (defined('T_ENUM') === false) { + define('T_ENUM', 'PHPCS_T_ENUM'); +} + +// Tokens used for parsing doc blocks. +define('T_DOC_COMMENT_STAR', 'PHPCS_T_DOC_COMMENT_STAR'); +define('T_DOC_COMMENT_WHITESPACE', 'PHPCS_T_DOC_COMMENT_WHITESPACE'); +define('T_DOC_COMMENT_TAG', 'PHPCS_T_DOC_COMMENT_TAG'); +define('T_DOC_COMMENT_OPEN_TAG', 'PHPCS_T_DOC_COMMENT_OPEN_TAG'); +define('T_DOC_COMMENT_CLOSE_TAG', 'PHPCS_T_DOC_COMMENT_CLOSE_TAG'); +define('T_DOC_COMMENT_STRING', 'PHPCS_T_DOC_COMMENT_STRING'); + +// Tokens used for PHPCS instruction comments. +define('T_PHPCS_ENABLE', 'PHPCS_T_PHPCS_ENABLE'); +define('T_PHPCS_DISABLE', 'PHPCS_T_PHPCS_DISABLE'); +define('T_PHPCS_SET', 'PHPCS_T_PHPCS_SET'); +define('T_PHPCS_IGNORE', 'PHPCS_T_PHPCS_IGNORE'); +define('T_PHPCS_IGNORE_FILE', 'PHPCS_T_PHPCS_IGNORE_FILE'); + +final class Tokens +{ + + /** + * The token weightings. + * + * @var array + */ + public static $weightings = [ + T_CLASS => 1000, + T_INTERFACE => 1000, + T_TRAIT => 1000, + T_ENUM => 1000, + T_NAMESPACE => 1000, + T_FUNCTION => 100, + T_CLOSURE => 100, + + /* + * Conditions. + */ + + T_WHILE => 50, + T_FOR => 50, + T_FOREACH => 50, + T_IF => 50, + T_ELSE => 50, + T_ELSEIF => 50, + T_DO => 50, + T_TRY => 50, + T_CATCH => 50, + T_FINALLY => 50, + T_SWITCH => 50, + T_MATCH => 50, + + T_SELF => 25, + T_PARENT => 25, + + /* + * Operators and arithmetic. + */ + + T_BITWISE_AND => 8, + T_BITWISE_OR => 8, + T_BITWISE_XOR => 8, + + T_MULTIPLY => 5, + T_DIVIDE => 5, + T_PLUS => 5, + T_MINUS => 5, + T_MODULUS => 5, + T_POW => 5, + T_SPACESHIP => 5, + T_COALESCE => 5, + T_COALESCE_EQUAL => 5, + + T_SL => 5, + T_SR => 5, + T_SL_EQUAL => 5, + T_SR_EQUAL => 5, + + T_EQUAL => 5, + T_AND_EQUAL => 5, + T_CONCAT_EQUAL => 5, + T_DIV_EQUAL => 5, + T_MINUS_EQUAL => 5, + T_MOD_EQUAL => 5, + T_MUL_EQUAL => 5, + T_OR_EQUAL => 5, + T_PLUS_EQUAL => 5, + T_XOR_EQUAL => 5, + + T_BOOLEAN_AND => 5, + T_BOOLEAN_OR => 5, + + /* + * Equality. + */ + + T_IS_EQUAL => 5, + T_IS_NOT_EQUAL => 5, + T_IS_IDENTICAL => 5, + T_IS_NOT_IDENTICAL => 5, + T_IS_SMALLER_OR_EQUAL => 5, + T_IS_GREATER_OR_EQUAL => 5, + ]; + + /** + * Tokens that represent assignments. + * + * @var array + */ + public static $assignmentTokens = [ + T_EQUAL => T_EQUAL, + T_AND_EQUAL => T_AND_EQUAL, + T_OR_EQUAL => T_OR_EQUAL, + T_CONCAT_EQUAL => T_CONCAT_EQUAL, + T_DIV_EQUAL => T_DIV_EQUAL, + T_MINUS_EQUAL => T_MINUS_EQUAL, + T_POW_EQUAL => T_POW_EQUAL, + T_MOD_EQUAL => T_MOD_EQUAL, + T_MUL_EQUAL => T_MUL_EQUAL, + T_PLUS_EQUAL => T_PLUS_EQUAL, + T_XOR_EQUAL => T_XOR_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_SL_EQUAL => T_SL_EQUAL, + T_SR_EQUAL => T_SR_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_ZSR_EQUAL => T_ZSR_EQUAL, + ]; + + /** + * Tokens that represent equality comparisons. + * + * @var array + */ + public static $equalityTokens = [ + T_IS_EQUAL => T_IS_EQUAL, + T_IS_NOT_EQUAL => T_IS_NOT_EQUAL, + T_IS_IDENTICAL => T_IS_IDENTICAL, + T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL, + T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL, + T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL, + ]; + + /** + * Tokens that represent comparison operator. + * + * @var array + */ + public static $comparisonTokens = [ + T_IS_EQUAL => T_IS_EQUAL, + T_IS_IDENTICAL => T_IS_IDENTICAL, + T_IS_NOT_EQUAL => T_IS_NOT_EQUAL, + T_IS_NOT_IDENTICAL => T_IS_NOT_IDENTICAL, + T_LESS_THAN => T_LESS_THAN, + T_GREATER_THAN => T_GREATER_THAN, + T_IS_SMALLER_OR_EQUAL => T_IS_SMALLER_OR_EQUAL, + T_IS_GREATER_OR_EQUAL => T_IS_GREATER_OR_EQUAL, + T_SPACESHIP => T_SPACESHIP, + T_COALESCE => T_COALESCE, + ]; + + /** + * Tokens that represent arithmetic operators. + * + * @var array + */ + public static $arithmeticTokens = [ + T_PLUS => T_PLUS, + T_MINUS => T_MINUS, + T_MULTIPLY => T_MULTIPLY, + T_DIVIDE => T_DIVIDE, + T_MODULUS => T_MODULUS, + T_POW => T_POW, + ]; + + /** + * Tokens that perform operations. + * + * @var array + */ + public static $operators = [ + T_MINUS => T_MINUS, + T_PLUS => T_PLUS, + T_MULTIPLY => T_MULTIPLY, + T_DIVIDE => T_DIVIDE, + T_MODULUS => T_MODULUS, + T_POW => T_POW, + T_SPACESHIP => T_SPACESHIP, + T_COALESCE => T_COALESCE, + T_BITWISE_AND => T_BITWISE_AND, + T_BITWISE_OR => T_BITWISE_OR, + T_BITWISE_XOR => T_BITWISE_XOR, + T_SL => T_SL, + T_SR => T_SR, + ]; + + /** + * Tokens that perform boolean operations. + * + * @var array + */ + public static $booleanOperators = [ + T_BOOLEAN_AND => T_BOOLEAN_AND, + T_BOOLEAN_OR => T_BOOLEAN_OR, + T_LOGICAL_AND => T_LOGICAL_AND, + T_LOGICAL_OR => T_LOGICAL_OR, + T_LOGICAL_XOR => T_LOGICAL_XOR, + ]; + + /** + * Tokens that represent casting. + * + * @var array + */ + public static $castTokens = [ + T_INT_CAST => T_INT_CAST, + T_STRING_CAST => T_STRING_CAST, + T_DOUBLE_CAST => T_DOUBLE_CAST, + T_ARRAY_CAST => T_ARRAY_CAST, + T_BOOL_CAST => T_BOOL_CAST, + T_OBJECT_CAST => T_OBJECT_CAST, + T_UNSET_CAST => T_UNSET_CAST, + T_BINARY_CAST => T_BINARY_CAST, + ]; + + /** + * Token types that open parenthesis. + * + * @var array + */ + public static $parenthesisOpeners = [ + T_ARRAY => T_ARRAY, + T_LIST => T_LIST, + T_FUNCTION => T_FUNCTION, + T_CLOSURE => T_CLOSURE, + T_ANON_CLASS => T_ANON_CLASS, + T_WHILE => T_WHILE, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_SWITCH => T_SWITCH, + T_IF => T_IF, + T_ELSEIF => T_ELSEIF, + T_CATCH => T_CATCH, + T_DECLARE => T_DECLARE, + T_MATCH => T_MATCH, + ]; + + /** + * Tokens that are allowed to open scopes. + * + * @var array + */ + public static $scopeOpeners = [ + T_CLASS => T_CLASS, + T_ANON_CLASS => T_ANON_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + T_NAMESPACE => T_NAMESPACE, + T_FUNCTION => T_FUNCTION, + T_CLOSURE => T_CLOSURE, + T_IF => T_IF, + T_SWITCH => T_SWITCH, + T_CASE => T_CASE, + T_DECLARE => T_DECLARE, + T_DEFAULT => T_DEFAULT, + T_WHILE => T_WHILE, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_DO => T_DO, + T_TRY => T_TRY, + T_CATCH => T_CATCH, + T_FINALLY => T_FINALLY, + T_PROPERTY => T_PROPERTY, + T_OBJECT => T_OBJECT, + T_USE => T_USE, + T_MATCH => T_MATCH, + ]; + + /** + * Tokens that represent scope modifiers. + * + * @var array + */ + public static $scopeModifiers = [ + T_PRIVATE => T_PRIVATE, + T_PUBLIC => T_PUBLIC, + T_PROTECTED => T_PROTECTED, + ]; + + /** + * Tokens that can prefix a method name + * + * @var array + */ + public static $methodPrefixes = [ + T_PRIVATE => T_PRIVATE, + T_PUBLIC => T_PUBLIC, + T_PROTECTED => T_PROTECTED, + T_ABSTRACT => T_ABSTRACT, + T_STATIC => T_STATIC, + T_FINAL => T_FINAL, + ]; + + /** + * Tokens that open code blocks. + * + * @var array + */ + public static $blockOpeners = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_OBJECT => T_OBJECT, + ]; + + /** + * Tokens that don't represent code. + * + * @var array + */ + public static $emptyTokens = [ + T_WHITESPACE => T_WHITESPACE, + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR, + T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG, + T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING, + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that are comments. + * + * @var array + */ + public static $commentTokens = [ + T_COMMENT => T_COMMENT, + T_DOC_COMMENT => T_DOC_COMMENT, + T_DOC_COMMENT_STAR => T_DOC_COMMENT_STAR, + T_DOC_COMMENT_WHITESPACE => T_DOC_COMMENT_WHITESPACE, + T_DOC_COMMENT_TAG => T_DOC_COMMENT_TAG, + T_DOC_COMMENT_OPEN_TAG => T_DOC_COMMENT_OPEN_TAG, + T_DOC_COMMENT_CLOSE_TAG => T_DOC_COMMENT_CLOSE_TAG, + T_DOC_COMMENT_STRING => T_DOC_COMMENT_STRING, + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that are comments containing PHPCS instructions. + * + * @var array + */ + public static $phpcsCommentTokens = [ + T_PHPCS_ENABLE => T_PHPCS_ENABLE, + T_PHPCS_DISABLE => T_PHPCS_DISABLE, + T_PHPCS_SET => T_PHPCS_SET, + T_PHPCS_IGNORE => T_PHPCS_IGNORE, + T_PHPCS_IGNORE_FILE => T_PHPCS_IGNORE_FILE, + ]; + + /** + * Tokens that represent strings. + * + * Note that T_STRINGS are NOT represented in this list. + * + * @var array + */ + public static $stringTokens = [ + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + ]; + + /** + * Tokens that represent text strings. + * + * @var array + */ + public static $textStringTokens = [ + T_CONSTANT_ENCAPSED_STRING => T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING => T_DOUBLE_QUOTED_STRING, + T_INLINE_HTML => T_INLINE_HTML, + T_HEREDOC => T_HEREDOC, + T_NOWDOC => T_NOWDOC, + ]; + + /** + * Tokens that represent brackets and parenthesis. + * + * @var array + */ + public static $bracketTokens = [ + T_OPEN_CURLY_BRACKET => T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET => T_CLOSE_CURLY_BRACKET, + T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, + T_CLOSE_SQUARE_BRACKET => T_CLOSE_SQUARE_BRACKET, + T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS => T_CLOSE_PARENTHESIS, + ]; + + /** + * Tokens that include files. + * + * @var array + */ + public static $includeTokens = [ + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_REQUIRE => T_REQUIRE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_INCLUDE => T_INCLUDE, + ]; + + /** + * Tokens that make up a heredoc string. + * + * @var array + */ + public static $heredocTokens = [ + T_START_HEREDOC => T_START_HEREDOC, + T_END_HEREDOC => T_END_HEREDOC, + T_HEREDOC => T_HEREDOC, + T_START_NOWDOC => T_START_NOWDOC, + T_END_NOWDOC => T_END_NOWDOC, + T_NOWDOC => T_NOWDOC, + ]; + + /** + * Tokens that represent the names of called functions. + * + * Mostly, these are just strings. But PHP tokenizes some language + * constructs and functions using their own tokens. + * + * @var array + */ + public static $functionNameTokens = [ + T_STRING => T_STRING, + T_EVAL => T_EVAL, + T_EXIT => T_EXIT, + T_INCLUDE => T_INCLUDE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_REQUIRE => T_REQUIRE, + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_ISSET => T_ISSET, + T_UNSET => T_UNSET, + T_EMPTY => T_EMPTY, + T_SELF => T_SELF, + T_PARENT => T_PARENT, + T_STATIC => T_STATIC, + ]; + + /** + * Tokens that open class and object scopes. + * + * @var array + */ + public static $ooScopeTokens = [ + T_CLASS => T_CLASS, + T_ANON_CLASS => T_ANON_CLASS, + T_INTERFACE => T_INTERFACE, + T_TRAIT => T_TRAIT, + T_ENUM => T_ENUM, + ]; + + /** + * Tokens representing PHP magic constants. + * + * @var array => + * + * @link https://www.php.net/language.constants.predefined PHP Manual on magic constants + */ + public static $magicConstants = [ + T_CLASS_C => T_CLASS_C, + T_DIR => T_DIR, + T_FILE => T_FILE, + T_FUNC_C => T_FUNC_C, + T_LINE => T_LINE, + T_METHOD_C => T_METHOD_C, + T_NS_C => T_NS_C, + T_TRAIT_C => T_TRAIT_C, + ]; + + /** + * Tokens representing context sensitive keywords in PHP. + * + * @var array + * + * https://wiki.php.net/rfc/context_sensitive_lexer + */ + public static $contextSensitiveKeywords = [ + T_ABSTRACT => T_ABSTRACT, + T_ARRAY => T_ARRAY, + T_AS => T_AS, + T_BREAK => T_BREAK, + T_CALLABLE => T_CALLABLE, + T_CASE => T_CASE, + T_CATCH => T_CATCH, + T_CLASS => T_CLASS, + T_CLONE => T_CLONE, + T_CONST => T_CONST, + T_CONTINUE => T_CONTINUE, + T_DECLARE => T_DECLARE, + T_DEFAULT => T_DEFAULT, + T_DO => T_DO, + T_ECHO => T_ECHO, + T_ELSE => T_ELSE, + T_ELSEIF => T_ELSEIF, + T_EMPTY => T_EMPTY, + T_ENDDECLARE => T_ENDDECLARE, + T_ENDFOR => T_ENDFOR, + T_ENDFOREACH => T_ENDFOREACH, + T_ENDIF => T_ENDIF, + T_ENDSWITCH => T_ENDSWITCH, + T_ENDWHILE => T_ENDWHILE, + T_ENUM => T_ENUM, + T_EVAL => T_EVAL, + T_EXIT => T_EXIT, + T_EXTENDS => T_EXTENDS, + T_FINAL => T_FINAL, + T_FINALLY => T_FINALLY, + T_FN => T_FN, + T_FOR => T_FOR, + T_FOREACH => T_FOREACH, + T_FUNCTION => T_FUNCTION, + T_GLOBAL => T_GLOBAL, + T_GOTO => T_GOTO, + T_IF => T_IF, + T_IMPLEMENTS => T_IMPLEMENTS, + T_INCLUDE => T_INCLUDE, + T_INCLUDE_ONCE => T_INCLUDE_ONCE, + T_INSTANCEOF => T_INSTANCEOF, + T_INSTEADOF => T_INSTEADOF, + T_INTERFACE => T_INTERFACE, + T_ISSET => T_ISSET, + T_LIST => T_LIST, + T_LOGICAL_AND => T_LOGICAL_AND, + T_LOGICAL_OR => T_LOGICAL_OR, + T_LOGICAL_XOR => T_LOGICAL_XOR, + T_MATCH => T_MATCH, + T_NAMESPACE => T_NAMESPACE, + T_NEW => T_NEW, + T_PRINT => T_PRINT, + T_PRIVATE => T_PRIVATE, + T_PROTECTED => T_PROTECTED, + T_PUBLIC => T_PUBLIC, + T_READONLY => T_READONLY, + T_REQUIRE => T_REQUIRE, + T_REQUIRE_ONCE => T_REQUIRE_ONCE, + T_RETURN => T_RETURN, + T_STATIC => T_STATIC, + T_SWITCH => T_SWITCH, + T_THROW => T_THROW, + T_TRAIT => T_TRAIT, + T_TRY => T_TRY, + T_UNSET => T_UNSET, + T_USE => T_USE, + T_VAR => T_VAR, + T_WHILE => T_WHILE, + T_YIELD => T_YIELD, + T_YIELD_FROM => T_YIELD_FROM, + ]; + + + /** + * Given a token, returns the name of the token. + * + * If passed an integer, the token name is sourced from PHP's token_name() + * function. If passed a string, it is assumed to be a PHPCS-supplied token + * that begins with PHPCS_T_, so the name is sourced from the token value itself. + * + * @param int|string $token The token to get the name for. + * + * @return string + */ + public static function tokenName($token) + { + if (is_string($token) === false) { + // PHP-supplied token name. + return token_name($token); + } + + return substr($token, 6); + + }//end tokenName() + + + /** + * Returns the highest weighted token type. + * + * Tokens are weighted by their approximate frequency of appearance in code + * - the less frequently they appear in the code, the higher the weighting. + * For example T_CLASS tokens appear very infrequently in a file, and + * therefore have a high weighting. + * + * If there are no weightings for any of the specified tokens, the first token + * seen in the passed array will be returned. + * + * @param array $tokens The token types to get the highest weighted + * type for. + * + * @return int The highest weighted token. + * On equal "weight", returns the first token of that particular weight. + */ + public static function getHighestWeightedToken(array $tokens) + { + $highest = -1; + $highestType = false; + + $weights = self::$weightings; + + foreach ($tokens as $token) { + if (isset($weights[$token]) === true) { + $weight = $weights[$token]; + } else { + $weight = 0; + } + + if ($weight > $highest) { + $highest = $weight; + $highestType = $token; + } + } + + return $highestType; + + }//end getHighestWeightedToken() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/AllTests.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/AllTests.php new file mode 100644 index 000000000..4fa41d9d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/AllTests.php @@ -0,0 +1,58 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +require_once 'Core/AllTests.php'; +require_once 'Standards/AllSniffs.php'; + +// PHPUnit 7 made the TestSuite run() method incompatible with +// older PHPUnit versions due to return type hints, so maintain +// two different suite objects. +$phpunit7 = false; +if (class_exists('\PHPUnit\Runner\Version') === true) { + $version = \PHPUnit\Runner\Version::id(); + if (version_compare($version, '7.0', '>=') === true) { + $phpunit7 = true; + } +} + +if ($phpunit7 === true) { + include_once 'TestSuite7.php'; +} else { + include_once 'TestSuite.php'; +} + +class PHP_CodeSniffer_AllTests +{ + + + /** + * Add all PHP_CodeSniffer test suites into a single test suite. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'] = []; + $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'] = []; + + // Use a special PHP_CodeSniffer test suite so that we can + // unset our autoload function after the run. + $suite = new TestSuite('PHP CodeSniffer'); + + $suite->addTest(Core\AllTests::suite()); + $suite->addTest(Standards\AllSniffs::suite()); + + return $suite; + + }//end suite() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/ConfigDouble.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/ConfigDouble.php new file mode 100644 index 000000000..62caaba8d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/ConfigDouble.php @@ -0,0 +1,212 @@ + + * @copyright 2024 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHP_CodeSniffer\Config; +use ReflectionProperty; + +final class ConfigDouble extends Config +{ + + /** + * Whether or not the setting of a standard should be skipped. + * + * @var boolean + */ + private $skipSettingStandard = false; + + + /** + * Creates a clean Config object and populates it with command line values. + * + * @param array $cliArgs An array of values gathered from CLI args. + * @param bool $skipSettingStandard Whether to skip setting a standard to prevent + * the Config class trying to auto-discover a ruleset file. + * Should only be set to `true` for tests which actually test + * the ruleset auto-discovery. + * Note: there is no need to set this to `true` when a standard + * is being passed via the `$cliArgs`. Those settings will always + * respected. + * Defaults to `false`. Will result in the standard being set + * to "PSR1" if not provided via `$cliArgs`. + * @param bool $skipSettingReportWidth Whether to skip setting a report-width to prevent + * the Config class trying to auto-discover the screen width. + * Should only be set to `true` for tests which actually test + * the screen width auto-discovery. + * Note: there is no need to set this to `true` when a report-width + * is being passed via the `$cliArgs`. Those settings will always + * respected. + * Defaults to `false`. Will result in the reportWidth being set + * to "80" if not provided via `$cliArgs`. + * + * @return void + */ + public function __construct(array $cliArgs=[], $skipSettingStandard=false, $skipSettingReportWidth=false) + { + $this->skipSettingStandard = $skipSettingStandard; + + $this->resetSelectProperties(); + $this->preventReadingCodeSnifferConfFile(); + + parent::__construct($cliArgs); + + if ($skipSettingReportWidth !== true) { + $this->preventAutoDiscoveryScreenWidth(); + } + + }//end __construct() + + + /** + * Ensures the static properties in the Config class are reset to their default values + * when the ConfigDouble is no longer used. + * + * @return void + */ + public function __destruct() + { + $this->setStaticConfigProperty('overriddenDefaults', []); + $this->setStaticConfigProperty('executablePaths', []); + $this->setStaticConfigProperty('configData', null); + $this->setStaticConfigProperty('configDataFile', null); + + }//end __destruct() + + + /** + * Sets the command line values and optionally prevents a file system search for a custom ruleset. + * + * @param array $args An array of command line arguments to set. + * + * @return void + */ + public function setCommandLineValues($args) + { + parent::setCommandLineValues($args); + + if ($this->skipSettingStandard !== true) { + $this->preventSearchingForRuleset(); + } + + }//end setCommandLineValues() + + + /** + * Reset a few properties on the Config class to their default values. + * + * @return void + */ + private function resetSelectProperties() + { + $this->setStaticConfigProperty('overriddenDefaults', []); + $this->setStaticConfigProperty('executablePaths', []); + + }//end resetSelectProperties() + + + /** + * Prevent the values in a potentially available user-specific `CodeSniffer.conf` file + * from influencing the tests. + * + * This also prevents some file system calls which can influence the test runtime. + * + * @return void + */ + private function preventReadingCodeSnifferConfFile() + { + $this->setStaticConfigProperty('configData', []); + $this->setStaticConfigProperty('configDataFile', ''); + + }//end preventReadingCodeSnifferConfFile() + + + /** + * Prevent searching for a custom ruleset by setting a standard, but only if the test + * being run doesn't set a standard itself. + * + * This also prevents some file system calls which can influence the test runtime. + * + * The standard being set is the smallest one available so the ruleset initialization + * will be the fastest possible. + * + * @return void + */ + private function preventSearchingForRuleset() + { + $overriddenDefaults = $this->getStaticConfigProperty('overriddenDefaults'); + if (isset($overriddenDefaults['standards']) === false) { + $this->standards = ['PSR1']; + $overriddenDefaults['standards'] = true; + } + + self::setStaticConfigProperty('overriddenDefaults', $overriddenDefaults); + + }//end preventSearchingForRuleset() + + + /** + * Prevent a call to stty to figure out the screen width, but only if the test being run + * doesn't set a report width itself. + * + * @return void + */ + private function preventAutoDiscoveryScreenWidth() + { + $settings = $this->getSettings(); + if ($settings['reportWidth'] === 'auto') { + $this->reportWidth = self::DEFAULT_REPORT_WIDTH; + } + + }//end preventAutoDiscoveryScreenWidth() + + + /** + * Helper function to retrieve the value of a private static property on the Config class. + * + * @param string $name The name of the property to retrieve. + * + * @return mixed + */ + private function getStaticConfigProperty($name) + { + $property = new ReflectionProperty('PHP_CodeSniffer\Config', $name); + $property->setAccessible(true); + return $property->getValue(); + + }//end getStaticConfigProperty() + + + /** + * Helper function to set the value of a private static property on the Config class. + * + * @param string $name The name of the property to set. + * @param mixed $value The value to set the property to. + * + * @return void + */ + private function setStaticConfigProperty($name, $value) + { + $property = new ReflectionProperty('PHP_CodeSniffer\Config', $name); + $property->setAccessible(true); + $property->setValue(null, $value); + $property->setAccessible(false); + + }//end setStaticConfigProperty() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php new file mode 100644 index 000000000..3784fb072 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AbstractMethodUnitTest.php @@ -0,0 +1,223 @@ + + * @copyright 2018-2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use Exception; +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +abstract class AbstractMethodUnitTest extends TestCase +{ + + /** + * The file extension of the test case file (without leading dot). + * + * This allows child classes to overrule the default `inc` with, for instance, + * `js` or `css` when applicable. + * + * @var string + */ + protected static $fileExtension = 'inc'; + + /** + * The tab width setting to use when tokenizing the file. + * + * This allows for test case files to use a different tab width than the default. + * + * @var integer + */ + protected static $tabWidth = 4; + + /** + * The \PHP_CodeSniffer\Files\File object containing the parsed contents of the test case file. + * + * @var \PHP_CodeSniffer\Files\File + */ + protected static $phpcsFile; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @beforeClass + * + * @return void + */ + public static function initializeFile() + { + $_SERVER['argv'] = []; + $config = new ConfigDouble(); + // Also set a tab-width to enable testing tab-replaced vs `orig_content`. + $config->tabWidth = static::$tabWidth; + + $ruleset = new Ruleset($config); + + // Default to a file with the same name as the test class. Extension is property based. + $relativeCN = str_replace(__NAMESPACE__, '', get_called_class()); + $relativePath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeCN); + $pathToTestFile = realpath(__DIR__).$relativePath.'.'.static::$fileExtension; + + // Make sure the file gets parsed correctly based on the file type. + $contents = 'phpcs_input_file: '.$pathToTestFile.PHP_EOL; + $contents .= file_get_contents($pathToTestFile); + + self::$phpcsFile = new DummyFile($contents, $ruleset, $config); + self::$phpcsFile->parse(); + + }//end initializeFile() + + + /** + * Clean up after finished test by resetting all static properties on the class to their default values. + * + * Note: This is a PHPUnit cross-version compatible {@see \PHPUnit\Framework\TestCase::tearDownAfterClass()} + * method. + * + * @afterClass + * + * @return void + */ + public static function reset() + { + // Explicitly trigger __destruct() on the ConfigDouble to reset the Config statics. + // The explicit method call prevents potential stray test-local references to the $config object + // preventing the destructor from running the clean up (which without stray references would be + // automagically triggered when `self::$phpcsFile` is reset, but we can't definitively rely on that). + if (isset(self::$phpcsFile) === true) { + self::$phpcsFile->config->__destruct(); + } + + self::$fileExtension = 'inc'; + self::$tabWidth = 4; + self::$phpcsFile = null; + + }//end reset() + + + /** + * Get the token pointer for a target token based on a specific comment found on the line before. + * + * Note: the test delimiter comment MUST start with "/* test" to allow this function to + * distinguish between comments used *in* a test and test delimiters. + * + * @param string $commentString The delimiter comment to look for. + * @param int|string|array $tokenType The type of token(s) to look for. + * @param string $tokenContent Optional. The token content for the target token. + * + * @return int + */ + public function getTargetToken($commentString, $tokenType, $tokenContent=null) + { + return self::getTargetTokenFromFile(self::$phpcsFile, $commentString, $tokenType, $tokenContent); + + }//end getTargetToken() + + + /** + * Get the token pointer for a target token based on a specific comment found on the line before. + * + * Note: the test delimiter comment MUST start with "/* test" to allow this function to + * distinguish between comments used *in* a test and test delimiters. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file to find the token in. + * @param string $commentString The delimiter comment to look for. + * @param int|string|array $tokenType The type of token(s) to look for. + * @param string $tokenContent Optional. The token content for the target token. + * + * @return int + * + * @throws Exception When the test delimiter comment is not found. + * @throws Exception When the test target token is not found. + */ + public static function getTargetTokenFromFile(File $phpcsFile, $commentString, $tokenType, $tokenContent=null) + { + $start = ($phpcsFile->numTokens - 1); + $comment = $phpcsFile->findPrevious( + T_COMMENT, + $start, + null, + false, + $commentString + ); + + if ($comment === false) { + throw new Exception( + sprintf('Failed to find the test marker: %s in test case file %s', $commentString, $phpcsFile->getFilename()) + ); + } + + $tokens = $phpcsFile->getTokens(); + $end = ($start + 1); + + // Limit the token finding to between this and the next delimiter comment. + for ($i = ($comment + 1); $i < $end; $i++) { + if ($tokens[$i]['code'] !== T_COMMENT) { + continue; + } + + if (stripos($tokens[$i]['content'], '/* test') === 0) { + $end = $i; + break; + } + } + + $target = $phpcsFile->findNext( + $tokenType, + ($comment + 1), + $end, + false, + $tokenContent + ); + + if ($target === false) { + $msg = 'Failed to find test target token for comment string: '.$commentString; + if ($tokenContent !== null) { + $msg .= ' with token content: '.$tokenContent; + } + + throw new Exception($msg); + } + + return $target; + + }//end getTargetTokenFromFile() + + + /** + * Helper method to tell PHPUnit to expect a PHPCS RuntimeException in a PHPUnit cross-version + * compatible manner. + * + * @param string $message The expected exception message. + * + * @return void + */ + public function expectRunTimeException($message) + { + $exception = 'PHP_CodeSniffer\Exceptions\RuntimeException'; + + if (method_exists($this, 'expectException') === true) { + // PHPUnit 5+. + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + // PHPUnit 4. + $this->setExpectedException($exception, $message); + } + + }//end expectRunTimeException() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php new file mode 100644 index 000000000..a5465f987 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php @@ -0,0 +1,63 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Tests\FileList; +use PHPUnit\Framework\TestSuite; +use PHPUnit\TextUI\TestRunner; + +class AllTests +{ + + + /** + * Prepare the test runner. + * + * @return void + */ + public static function main() + { + TestRunner::run(self::suite()); + + }//end main() + + + /** + * Add all core unit tests into a test suite. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $suite = new TestSuite('PHP CodeSniffer Core'); + + $testFileIterator = new FileList(__DIR__, '', '`Test\.php$`Di'); + foreach ($testFileIterator->fileIterator as $file) { + if (strpos($file, 'AbstractMethodUnitTest.php') !== false) { + continue; + } + + include_once $file; + + $class = str_replace(__DIR__, '', $file); + $class = str_replace('.php', '', $class); + $class = str_replace('/', '\\', $class); + $class = 'PHP_CodeSniffer\Tests\Core'.$class; + + $suite->addTestSuite($class); + } + + return $suite; + + }//end suite() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php new file mode 100644 index 000000000..ea40a5402 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/DetermineLoadedClassTest.php @@ -0,0 +1,126 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Autoloader; + +use PHP_CodeSniffer\Autoload; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Autoload::determineLoadedClass method. + * + * @covers \PHP_CodeSniffer\Autoload::determineLoadedClass + */ +final class DetermineLoadedClassTest extends TestCase +{ + + + /** + * Load the test files. + * + * @beforeClass + * + * @return void + */ + public static function includeFixture() + { + include __DIR__.'/TestFiles/Sub/C.inc'; + + }//end includeFixture() + + + /** + * Test for when class list is ordered. + * + * @return void + */ + public function testOrdered() + { + $classesBeforeLoad = [ + 'classes' => [], + 'interfaces' => [], + 'traits' => [], + ]; + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + }//end testOrdered() + + + /** + * Test for when class list is out of order. + * + * @return void + */ + public function testUnordered() + { + $classesBeforeLoad = [ + 'classes' => [], + 'interfaces' => [], + 'traits' => [], + ]; + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + $classesAfterLoad = [ + 'classes' => [ + 'PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\A', + 'PHP_CodeSniffer\Tests\Core\Autoloader\C', + 'PHP_CodeSniffer\Tests\Core\Autoloader\B', + ], + 'interfaces' => [], + 'traits' => [], + ]; + + $className = Autoload::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + $this->assertEquals('PHP_CodeSniffer\Tests\Core\Autoloader\Sub\C', $className); + + }//end testUnordered() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc new file mode 100644 index 000000000..c1433718b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Autoloader/TestFiles/A.inc @@ -0,0 +1,3 @@ + + * @copyright 2006-2023 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Config; + +use PHP_CodeSniffer\Config; +use PHPUnit\Framework\TestCase; +use ReflectionProperty; + +/** + * Tests for the \PHP_CodeSniffer\Config reportWidth value. + * + * @covers \PHP_CodeSniffer\Config::__get + */ +final class ReportWidthTest extends TestCase +{ + + + /** + * Set static properties in the Config class to prevent tests influencing each other. + * + * @before + * + * @return void + */ + public static function cleanConfig() + { + // Set to the property's default value to clear out potentially set values from other tests. + self::setStaticProperty('executablePaths', []); + + // Set to a usable value to circumvent Config trying to find a phpcs.xml config file. + self::setStaticProperty('overriddenDefaults', ['standards' => ['PSR1']]); + + // Set to values which prevent the test-runner user's `CodeSniffer.conf` file + // from being read and influencing the tests. + self::setStaticProperty('configData', []); + self::setStaticProperty('configDataFile', ''); + + }//end cleanConfig() + + + /** + * Clean up after each finished test. + * + * @after + * + * @return void + */ + public function resetConfig() + { + $_SERVER['argv'] = []; + + }//end resetConfig() + + + /** + * Reset the static properties in the Config class to their true defaults to prevent this class + * from influencing other tests. + * + * @afterClass + * + * @return void + */ + public static function resetConfigToDefaults() + { + self::setStaticProperty('overriddenDefaults', []); + self::setStaticProperty('executablePaths', []); + self::setStaticProperty('configData', null); + self::setStaticProperty('configDataFile', null); + $_SERVER['argv'] = []; + + }//end resetConfigToDefaults() + + + /** + * Test that report width without overrules will always be set to a non-0 positive integer. + * + * @covers \PHP_CodeSniffer\Config::__set + * @covers \PHP_CodeSniffer\Config::restoreDefaults + * + * @return void + */ + public function testReportWidthDefault() + { + $config = new Config(); + + // Can't test the exact value as "auto" will resolve differently depending on the machine running the tests. + $this->assertTrue(is_int($config->reportWidth), 'Report width is not an integer'); + $this->assertGreaterThan(0, $config->reportWidth, 'Report width is not greater than 0'); + + }//end testReportWidthDefault() + + + /** + * Test that the report width will be set to a non-0 positive integer when not found in the CodeSniffer.conf file. + * + * @covers \PHP_CodeSniffer\Config::__set + * @covers \PHP_CodeSniffer\Config::restoreDefaults + * + * @return void + */ + public function testReportWidthWillBeSetFromAutoWhenNotFoundInConfFile() + { + $phpCodeSnifferConfig = [ + 'default_standard' => 'PSR2', + 'show_warnings' => '0', + ]; + + $this->setStaticProperty('configData', $phpCodeSnifferConfig); + + $config = new Config(); + + // Can't test the exact value as "auto" will resolve differently depending on the machine running the tests. + $this->assertTrue(is_int($config->reportWidth), 'Report width is not an integer'); + $this->assertGreaterThan(0, $config->reportWidth, 'Report width is not greater than 0'); + + }//end testReportWidthWillBeSetFromAutoWhenNotFoundInConfFile() + + + /** + * Test that the report width will be set correctly when found in the CodeSniffer.conf file. + * + * @covers \PHP_CodeSniffer\Config::__set + * @covers \PHP_CodeSniffer\Config::getConfigData + * @covers \PHP_CodeSniffer\Config::restoreDefaults + * + * @return void + */ + public function testReportWidthCanBeSetFromConfFile() + { + $phpCodeSnifferConfig = [ + 'default_standard' => 'PSR2', + 'report_width' => '120', + ]; + + $this->setStaticProperty('configData', $phpCodeSnifferConfig); + + $config = new Config(); + $this->assertSame(120, $config->reportWidth); + + }//end testReportWidthCanBeSetFromConfFile() + + + /** + * Test that the report width will be set correctly when passed as a CLI argument. + * + * @covers \PHP_CodeSniffer\Config::__set + * @covers \PHP_CodeSniffer\Config::processLongArgument + * + * @return void + */ + public function testReportWidthCanBeSetFromCLI() + { + $_SERVER['argv'] = [ + 'phpcs', + '--report-width=100', + ]; + + $config = new Config(); + $this->assertSame(100, $config->reportWidth); + + }//end testReportWidthCanBeSetFromCLI() + + + /** + * Test that the report width will be set correctly when multiple report widths are passed on the CLI. + * + * @covers \PHP_CodeSniffer\Config::__set + * @covers \PHP_CodeSniffer\Config::processLongArgument + * + * @return void + */ + public function testReportWidthWhenSetFromCLIFirstValuePrevails() + { + $_SERVER['argv'] = [ + 'phpcs', + '--report-width=100', + '--report-width=200', + ]; + + $config = new Config(); + $this->assertSame(100, $config->reportWidth); + + }//end testReportWidthWhenSetFromCLIFirstValuePrevails() + + + /** + * Test that a report width passed as a CLI argument will overrule a report width set in a CodeSniffer.conf file. + * + * @covers \PHP_CodeSniffer\Config::__set + * @covers \PHP_CodeSniffer\Config::processLongArgument + * @covers \PHP_CodeSniffer\Config::getConfigData + * + * @return void + */ + public function testReportWidthSetFromCLIOverrulesConfFile() + { + $phpCodeSnifferConfig = [ + 'default_standard' => 'PSR2', + 'report_format' => 'summary', + 'show_warnings' => '0', + 'show_progress' => '1', + 'report_width' => '120', + ]; + + $this->setStaticProperty('configData', $phpCodeSnifferConfig); + + $cliArgs = [ + 'phpcs', + '--report-width=180', + ]; + + $config = new Config($cliArgs); + $this->assertSame(180, $config->reportWidth); + + }//end testReportWidthSetFromCLIOverrulesConfFile() + + + /** + * Test that the report width will be set to a non-0 positive integer when set to "auto". + * + * @covers \PHP_CodeSniffer\Config::__set + * + * @return void + */ + public function testReportWidthInputHandlingForAuto() + { + $config = new Config(); + $config->reportWidth = 'auto'; + + // Can't test the exact value as "auto" will resolve differently depending on the machine running the tests. + $this->assertTrue(is_int($config->reportWidth), 'Report width is not an integer'); + $this->assertGreaterThan(0, $config->reportWidth, 'Report width is not greater than 0'); + + }//end testReportWidthInputHandlingForAuto() + + + /** + * Test that the report width will be set correctly for various types of input. + * + * @param mixed $value Input value received. + * @param int $expected Expected report width. + * + * @dataProvider dataReportWidthInputHandling + * @covers \PHP_CodeSniffer\Config::__set + * + * @return void + */ + public function testReportWidthInputHandling($value, $expected) + { + $config = new Config(); + $config->reportWidth = $value; + + $this->assertSame($expected, $config->reportWidth); + + }//end testReportWidthInputHandling() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataReportWidthInputHandling() + { + return [ + 'No value (empty string)' => [ + 'value' => '', + 'expected' => Config::DEFAULT_REPORT_WIDTH, + ], + 'Value: invalid input type null' => [ + 'value' => null, + 'expected' => Config::DEFAULT_REPORT_WIDTH, + ], + 'Value: invalid input type false' => [ + 'value' => false, + 'expected' => Config::DEFAULT_REPORT_WIDTH, + ], + 'Value: invalid input type float' => [ + 'value' => 100.50, + 'expected' => Config::DEFAULT_REPORT_WIDTH, + ], + 'Value: invalid string value "invalid"' => [ + 'value' => 'invalid', + 'expected' => Config::DEFAULT_REPORT_WIDTH, + ], + 'Value: invalid string value, non-integer string "50.25"' => [ + 'value' => '50.25', + 'expected' => Config::DEFAULT_REPORT_WIDTH, + ], + 'Value: valid numeric string value' => [ + 'value' => '250', + 'expected' => 250, + ], + 'Value: valid int value' => [ + 'value' => 220, + 'expected' => 220, + ], + 'Value: negative int value becomes positive int' => [ + 'value' => -180, + 'expected' => 180, + ], + ]; + + }//end dataReportWidthInputHandling() + + + /** + * Helper function to set a static property on the Config class. + * + * @param string $name The name of the property to set. + * @param mixed $value The value to set the property to. + * + * @return void + */ + public static function setStaticProperty($name, $value) + { + $property = new ReflectionProperty('PHP_CodeSniffer\Config', $name); + $property->setAccessible(true); + $property->setValue(null, $value); + $property->setAccessible(false); + + }//end setStaticProperty() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Config/SniffsExcludeArgsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Config/SniffsExcludeArgsTest.php new file mode 100644 index 000000000..4eedb624e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Config/SniffsExcludeArgsTest.php @@ -0,0 +1,200 @@ + + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Config; + +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Config --sniffs and --exclude arguments. + * + * @covers \PHP_CodeSniffer\Config::processLongArgument + */ +final class SniffsExcludeArgsTest extends TestCase +{ + + + /** + * Ensure that the expected error message is returned for invalid arguments. + * + * @param string $argument 'sniffs' or 'exclude'. + * @param string $value List of sniffs to include / exclude. + * @param string $message Expected error message text. + * + * @return void + * @dataProvider dataInvalidSniffs + */ + public function testInvalid($argument, $value, $message) + { + $exception = 'PHP_CodeSniffer\Exceptions\DeepExitException'; + + if (method_exists($this, 'expectException') === true) { + // PHPUnit 5+. + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + // PHPUnit 4. + $this->setExpectedException($exception, $message); + } + + new ConfigDouble(["--$argument=$value"]); + + }//end testInvalid() + + + /** + * Data provider for testInvalid(). + * + * @see self::testInvalid() + * @return array> + */ + public static function dataInvalidSniffs() + { + $arguments = [ + 'sniffs', + 'exclude', + ]; + $data = []; + + $messageTemplate = 'ERROR: The specified sniff code "%s" is invalid'.PHP_EOL.PHP_EOL; + + foreach ($arguments as $argument) { + // An empty string is not a valid sniff. + $data[$argument.'; empty string'] = [ + 'argument' => $argument, + 'value' => '', + 'message' => sprintf($messageTemplate, ''), + ]; + + // A standard is not a valid sniff. + $data[$argument.'; standard'] = [ + 'argument' => $argument, + 'value' => 'Standard', + 'message' => sprintf($messageTemplate, 'Standard'), + ]; + + // A category is not a valid sniff. + $data[$argument.'; category'] = [ + 'argument' => $argument, + 'value' => 'Standard.Category', + 'message' => sprintf($messageTemplate, 'Standard.Category'), + ]; + + // An error-code is not a valid sniff. + $data[$argument.'; error-code'] = [ + 'argument' => $argument, + 'value' => 'Standard.Category', + 'message' => sprintf($messageTemplate, 'Standard.Category'), + ]; + + // Only the first error is reported. + $data[$argument.'; two errors'] = [ + 'argument' => $argument, + 'value' => 'StandardOne,StandardTwo', + 'message' => sprintf($messageTemplate, 'StandardOne'), + ]; + $data[$argument.'; valid followed by invalid'] = [ + 'argument' => $argument, + 'value' => 'StandardOne.Category.Sniff,StandardTwo.Category', + 'message' => sprintf($messageTemplate, 'StandardTwo.Category'), + ]; + }//end foreach + + return $data; + + }//end dataInvalidSniffs() + + + /** + * Ensure that the valid data does not throw an exception, and the value is stored. + * + * @param string $argument 'sniffs' or 'exclude'. + * @param string $value List of sniffs to include or exclude. + * + * @return void + * @dataProvider dataValidSniffs + */ + public function testValid($argument, $value) + { + $config = new ConfigDouble(["--$argument=$value"]); + + $this->assertSame(explode(',', $value), $config->$argument); + + }//end testValid() + + + /** + * Data provider for testValid(). + * + * @see self::testValid() + * @return array> + */ + public static function dataValidSniffs() + { + $arguments = [ + 'sniffs', + 'exclude', + ]; + $data = []; + + foreach ($arguments as $argument) { + $data[$argument.'; one valid sniff'] = [ + 'argument' => $argument, + 'value' => 'Standard.Category.Sniff', + ]; + $data[$argument.'; two valid sniffs'] = [ + 'argument' => $argument, + 'value' => 'StandardOne.Category.Sniff,StandardTwo.Category.Sniff', + ]; + } + + return $data; + + }//end dataValidSniffs() + + + /** + * Ensure that only the first argument is processed and others are ignored. + * + * @param string $argument 'sniffs' or 'exclude'. + * + * @return void + * @dataProvider dataOnlySetOnce + */ + public function testOnlySetOnce($argument) + { + $config = new ConfigDouble( + [ + "--$argument=StandardOne.Category.Sniff", + "--$argument=StandardTwo.Category.Sniff", + "--$argument=Standard.AnotherCategory.Sniff", + ] + ); + + $this->assertSame(['StandardOne.Category.Sniff'], $config->$argument); + + }//end testOnlySetOnce() + + + /** + * Data provider for testOnlySetOnce(). + * + * @return array> + */ + public static function dataOnlySetOnce() + { + return [ + 'sniffs' => ['sniffs'], + 'exclude' => ['exclude'], + ]; + + }//end dataOnlySetOnce() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/ErrorSuppressionTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/ErrorSuppressionTest.php new file mode 100644 index 000000000..ccd9f479e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/ErrorSuppressionTest.php @@ -0,0 +1,1278 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core; + +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Tests for PHP_CodeSniffer error suppression tags. + * + * @covers PHP_CodeSniffer\Files\File::addMessage + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + */ +final class ErrorSuppressionTest extends TestCase +{ + + + /** + * Test suppressing a single error. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * + * @dataProvider dataSuppressError + * + * @return void + */ + public function testSuppressError($before, $after, $expectedErrors=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressError() + + + /** + * Data provider. + * + * @see testSuppressError() + * + * @return array> + */ + public static function dataSuppressError() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Inline slash comments. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable'.PHP_EOL, + 'after' => '// phpcs:enable', + ], + 'disable/enable: multi-line slash comment, tab indented' => [ + 'before' => "\t".'// For reasons'.PHP_EOL."\t".'// phpcs:disable'.PHP_EOL."\t", + 'after' => "\t".'// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable'.PHP_EOL, + 'after' => '// @phpcs:enable', + ], + 'disable/enable: slash comment, mixed case' => [ + 'before' => '// PHPCS:Disable'.PHP_EOL, + 'after' => '// pHPcs:enabLE', + ], + + // Inline hash comments. + 'disable/enable: hash comment' => [ + 'before' => '# phpcs:disable'.PHP_EOL, + 'after' => '# phpcs:enable', + ], + 'disable/enable: multi-line hash comment, tab indented' => [ + 'before' => "\t".'# For reasons'.PHP_EOL."\t".'# phpcs:disable'.PHP_EOL."\t", + 'after' => "\t".'# phpcs:enable', + ], + 'disable/enable: hash comment, with @' => [ + 'before' => '# @phpcs:disable'.PHP_EOL, + 'after' => '# @phpcs:enable', + ], + 'disable/enable: hash comment, mixed case' => [ + 'before' => '# PHPCS:Disable'.PHP_EOL, + 'after' => '# pHPcs:enabLE', + ], + + // Inline star (block) comments. + 'disable/enable: star comment' => [ + 'before' => '/* phpcs:disable */'.PHP_EOL, + 'after' => '/* phpcs:enable */', + ], + 'disable/enable: multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' phpcs:disable'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' phpcs:enable'.PHP_EOL.' */', + ], + 'disable/enable: multi-line star comment, each line starred' => [ + 'before' => '/*'.PHP_EOL.' * phpcs:disable'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' * phpcs:enable'.PHP_EOL.' */', + ], + 'disable/enable: multi-line star comment, each line starred, tab indented' => [ + 'before' => "\t".'/*'.PHP_EOL."\t".' * phpcs:disable'.PHP_EOL."\t".' */'.PHP_EOL."\t", + 'after' => "\t".'/*'.PHP_EOL.' * phpcs:enable'.PHP_EOL.' */', + ], + + // Docblock comments. + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */'.PHP_EOL, + 'after' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart'.PHP_EOL, + 'after' => '// @codingStandardsIgnoreEnd', + ], + 'old style: star comment' => [ + 'before' => '/* @codingStandardsIgnoreStart */'.PHP_EOL, + 'after' => '/* @codingStandardsIgnoreEnd */', + ], + 'old style: multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' @codingStandardsIgnoreStart'.PHP_EOL.' */'.PHP_EOL, + 'after' => '/*'.PHP_EOL.' @codingStandardsIgnoreEnd'.PHP_EOL.' */', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */'.PHP_EOL, + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressError() + + + /** + * Test suppressing 1 out of 2 errors. + * + * @param string $before Annotation to place before the code. + * @param string $between Annotation to place between the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 1. + * + * @dataProvider dataSuppressSomeErrors + * + * @return void + */ + public function testSuppressSomeErrors($before, $between, $expectedErrors=1) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressSomeErrors() + + + /** + * Data provider. + * + * @see testSuppressSomeErrors() + * + * @return array> + */ + public static function dataSuppressSomeErrors() + { + return [ + 'no suppression' => [ + 'before' => '', + 'between' => '', + 'expectedErrors' => 2, + ], + + // With suppression. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable', + 'between' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable', + 'between' => '// @phpcs:enable', + ], + 'disable/enable: hash comment' => [ + 'before' => '# phpcs:disable', + 'between' => '# phpcs:enable', + ], + 'disable/enable: hash comment, with @' => [ + 'before' => '# @phpcs:disable', + 'between' => '# @phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'between' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'between' => '// @codingStandardsIgnoreEnd', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'between' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressSomeErrors() + + + /** + * Test suppressing a single warning. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataSuppressWarning + * + * @return void + */ + public function testSuppressWarning($before, $after, $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Commenting.Todo']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testSuppressWarning() + + + /** + * Data provider. + * + * @see testSuppressWarning() + * + * @return array> + */ + public static function dataSuppressWarning() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedWarnings' => 1, + ], + + // With suppression. + 'disable/enable: slash comment' => [ + 'before' => '// phpcs:disable', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '// @phpcs:disable', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'after' => '/** phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: slash comment' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'after' => '// @codingStandardsIgnoreEnd', + ], + 'old style: single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressWarning() + + + /** + * Test suppressing a single error using a single line ignore. + * + * @param string $before Annotation to place before the code. + * @param string $after Optional. Annotation to place after the code. + * Defaults to an empty string. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 1. + * + * @dataProvider dataSuppressLine + * + * @return void + */ + public function testSuppressLine($before, $after='', $expectedErrors=1) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressLine() + + + /** + * Data provider. + * + * @see testSuppressLine() + * + * @return array> + */ + public static function dataSuppressLine() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 2, + ], + + // With suppression on line before. + 'ignore: line before, slash comment' => [ + 'before' => '// phpcs:ignore', + ], + 'ignore: line before, slash comment, with @' => [ + 'before' => '// @phpcs:ignore', + ], + 'ignore: line before, hash comment' => [ + 'before' => '# phpcs:ignore', + ], + 'ignore: line before, hash comment, with @' => [ + 'before' => '# @phpcs:ignore', + ], + 'ignore: line before, star comment' => [ + 'before' => '/* phpcs:ignore */', + ], + 'ignore: line before, star comment, with @' => [ + 'before' => '/* @phpcs:ignore */', + ], + + // With suppression as trailing comment on code line. + 'ignore: end of line, slash comment' => [ + 'before' => '', + 'after' => ' // phpcs:ignore', + ], + 'ignore: end of line, slash comment, with @' => [ + 'before' => '', + 'after' => ' // @phpcs:ignore', + ], + 'ignore: end of line, hash comment' => [ + 'before' => '', + 'after' => ' # phpcs:ignore', + ], + 'ignore: end of line, hash comment, with @' => [ + 'before' => '', + 'after' => ' # @phpcs:ignore', + ], + + // Deprecated syntax. + 'old style: line before, slash comment' => [ + 'before' => '// @codingStandardsIgnoreLine', + ], + 'old style: end of line, slash comment' => [ + 'before' => '', + 'after' => ' // @codingStandardsIgnoreLine', + ], + ]; + + }//end dataSuppressLine() + + + /** + * Test suppressing a single error using a single line ignore in the middle of a line. + * + * @return void + */ + public function testSuppressLineMidLine() + { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + + $content = 'process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testSuppressLineMidLine() + + + /** + * Test suppressing a single error using a single line ignore within a docblock. + * + * @return void + */ + public function testSuppressLineWithinDocblock() + { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Files.LineLength']; + + $ruleset = new Ruleset($config); + + // Process with @ suppression on line before inside docblock. + $comment = str_repeat('a ', 50); + $content = <<process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testSuppressLineWithinDocblock() + + + /** + * Test that using a single line ignore does not interfere with other suppressions. + * + * @param string $before Annotation to place before the code. + * @param string $after Annotation to place after the code. + * + * @dataProvider dataNestedSuppressLine + * + * @return void + */ + public function testNestedSuppressLine($before, $after) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.PHP.LowerCaseConstant']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame(0, $file->getErrorCount()); + $this->assertCount(0, $file->getErrors()); + + }//end testNestedSuppressLine() + + + /** + * Data provider. + * + * @see testNestedSuppressLine() + * + * @return array> + */ + public static function dataNestedSuppressLine() + { + return [ + // Process with disable/enable suppression and no single line suppression. + 'disable/enable: slash comment, no single line suppression' => [ + 'before' => '// phpcs:disable', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @, no single line suppression' => [ + 'before' => '// @phpcs:disable', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: hash comment, no single line suppression' => [ + 'before' => '# phpcs:disable', + 'after' => '# phpcs:enable', + ], + 'old style: slash comment, no single line suppression' => [ + 'before' => '// @codingStandardsIgnoreStart', + 'after' => '// @codingStandardsIgnoreEnd', + ], + + // Process with line suppression nested within disable/enable suppression. + 'disable/enable: slash comment, next line nested single line suppression' => [ + 'before' => '// phpcs:disable'.PHP_EOL.'// phpcs:ignore', + 'after' => '// phpcs:enable', + ], + 'disable/enable: slash comment, with @, next line nested single line suppression' => [ + 'before' => '// @phpcs:disable'.PHP_EOL.'// @phpcs:ignore', + 'after' => '// @phpcs:enable', + ], + 'disable/enable: hash comment, next line nested single line suppression' => [ + 'before' => '# @phpcs:disable'.PHP_EOL.'# @phpcs:ignore', + 'after' => '# @phpcs:enable', + ], + 'old style: slash comment, next line nested single line suppression' => [ + 'before' => '// @codingStandardsIgnoreStart'.PHP_EOL.'// @codingStandardsIgnoreLine', + 'after' => '// @codingStandardsIgnoreEnd', + ], + ]; + + }//end dataNestedSuppressLine() + + + /** + * Test suppressing a scope opener. + * + * @param string $before Annotation to place before the scope opener. + * @param string $after Annotation to place after the scope opener. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * + * @dataProvider dataSuppressScope + * + * @return void + */ + public function testSuppressScope($before, $after, $expectedErrors=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['PEAR']; + $config->sniffs = ['PEAR.Functions.FunctionDeclaration']; + + $ruleset = new Ruleset($config); + } + + $content = 'foo(); + } +} +EOD; + $file = new DummyFile($content, $ruleset, $config); + $file->process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + }//end testSuppressScope() + + + /** + * Data provider. + * + * @see testSuppressScope() + * + * @return array> + */ + public static function dataSuppressScope() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedErrors' => 1, + ], + + // Process with suppression. + 'disable/enable: slash comment' => [ + 'before' => '//phpcs:disable', + 'after' => '//phpcs:enable', + ], + 'disable/enable: slash comment, with @' => [ + 'before' => '//@phpcs:disable', + 'after' => '//@phpcs:enable', + ], + 'disable/enable: hash comment' => [ + 'before' => '#phpcs:disable', + 'after' => '#phpcs:enable', + ], + 'disable/enable: single line docblock comment' => [ + 'before' => '/** phpcs:disable */', + 'after' => '/** phpcs:enable */', + ], + 'disable/enable: single line docblock comment, with @' => [ + 'before' => '/** @phpcs:disable */', + 'after' => '/** @phpcs:enable */', + ], + + // Deprecated syntax. + 'old style: start/end, slash comment' => [ + 'before' => '//@codingStandardsIgnoreStart', + 'after' => '//@codingStandardsIgnoreEnd', + ], + 'old style: start/end, single line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreStart */', + 'after' => '/** @codingStandardsIgnoreEnd */', + ], + ]; + + }//end dataSuppressScope() + + + /** + * Test suppressing a whole file. + * + * @param string $before Annotation to place before the code. + * @param string $after Optional. Annotation to place after the code. + * Defaults to an empty string. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataSuppressFile + * + * @return void + */ + public function testSuppressFile($before, $after='', $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = ['Generic.Commenting.Todo']; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testSuppressFile() + + + /** + * Data provider. + * + * @see testSuppressFile() + * + * @return array> + */ + public static function dataSuppressFile() + { + return [ + 'no suppression' => [ + 'before' => '', + 'after' => '', + 'expectedWarnings' => 1, + ], + + // Process with suppression. + 'ignoreFile: start of file, slash comment' => [ + 'before' => '// phpcs:ignoreFile', + ], + 'ignoreFile: start of file, slash comment, with @' => [ + 'before' => '// @phpcs:ignoreFile', + ], + 'ignoreFile: start of file, slash comment, mixed case' => [ + 'before' => '// PHPCS:Ignorefile', + ], + 'ignoreFile: start of file, hash comment' => [ + 'before' => '# phpcs:ignoreFile', + ], + 'ignoreFile: start of file, hash comment, with @' => [ + 'before' => '# @phpcs:ignoreFile', + ], + 'ignoreFile: start of file, single-line star comment' => [ + 'before' => '/* phpcs:ignoreFile */', + ], + 'ignoreFile: start of file, multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' phpcs:ignoreFile'.PHP_EOL.' */', + ], + 'ignoreFile: start of file, single-line docblock comment' => [ + 'before' => '/** phpcs:ignoreFile */', + ], + + // Process late comment. + 'ignoreFile: late comment, slash comment' => [ + 'before' => '', + 'after' => '// phpcs:ignoreFile', + ], + + // Deprecated syntax. + 'old style: start of file, slash comment' => [ + 'before' => '// @codingStandardsIgnoreFile', + ], + 'old style: start of file, single-line star comment' => [ + 'before' => '/* @codingStandardsIgnoreFile */', + ], + 'old style: start of file, multi-line star comment' => [ + 'before' => '/*'.PHP_EOL.' @codingStandardsIgnoreFile'.PHP_EOL.' */', + ], + 'old style: start of file, single-line docblock comment' => [ + 'before' => '/** @codingStandardsIgnoreFile */', + ], + + // Deprecated syntax, late comment. + 'old style: late comment, slash comment' => [ + 'before' => '', + 'after' => '// @codingStandardsIgnoreFile', + ], + ]; + + }//end dataSuppressFile() + + + /** + * Test disabling specific sniffs. + * + * @param string $before Annotation to place before the code. + * @param int $expectedErrors Optional. Number of errors expected. + * Defaults to 0. + * @param int $expectedWarnings Optional. Number of warnings expected. + * Defaults to 0. + * + * @dataProvider dataDisableSelected + * + * @return void + */ + public function testDisableSelected($before, $expectedErrors=0, $expectedWarnings=0) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testDisableSelected() + + + /** + * Data provider. + * + * @see testDisableSelected() + * + * @return array> + */ + public static function dataDisableSelected() + { + return [ + // Single sniff. + 'disable: single sniff' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo', + 'expectedErrors' => 1, + ], + 'disable: single sniff with reason' => [ + 'before' => '# phpcs:disable Generic.Commenting.Todo -- for reasons', + 'expectedErrors' => 1, + ], + 'disable: single sniff, docblock' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + ], + 'disable: single sniff, docblock, with @' => [ + 'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Commenting.Todo'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + ], + + // Multiple sniffs. + 'disable: multiple sniffs in one comment' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant', + ], + 'disable: multiple sniff in multiple comments' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:disable Generic.PHP.LowerCaseConstant', + ], + + // Selectiveness variations. + 'disable: complete category' => [ + 'before' => '// phpcs:disable Generic.Commenting', + 'expectedErrors' => 1, + ], + 'disable: whole standard' => [ + 'before' => '// phpcs:disable Generic', + ], + 'disable: single errorcode' => [ + 'before' => '# @phpcs:disable Generic.Commenting.Todo.TaskFound', + 'expectedErrors' => 1, + ], + 'disable: single errorcode and a category' => [ + 'before' => '// phpcs:disable Generic.PHP.LowerCaseConstant.Found,Generic.Commenting', + ], + + // Wrong category/sniff/code. + 'disable: wrong error code and category' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.PHP.LowerCaseConstant.Upper,Generic.Comments'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: wrong category, docblock' => [ + 'before' => '/**'.PHP_EOL.' * phpcs:disable Generic.Files'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: wrong category, docblock, with @' => [ + 'before' => '/**'.PHP_EOL.' * @phpcs:disable Generic.Files'.PHP_EOL.' */ ', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + ]; + + }//end dataDisableSelected() + + + /** + * Test re-enabling specific sniffs that have been disabled. + * + * @param string $code Code pattern to check. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataEnableSelected + * + * @return void + */ + public function testEnableSelected($code, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testEnableSelected() + + + /** + * Data provider. + * + * @see testEnableSelected() + * + * @return array> + */ + public static function dataEnableSelected() + { + return [ + 'disable/enable: a single sniff' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable/enable: multiple sniffs' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: multiple sniffs; enable: one' => [ + 'code' => ' + # phpcs:disable Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant + $var = FALSE; + //TODO: write some code + # phpcs:enable Generic.Commenting.Todo + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable/enable: complete category' => [ + 'code' => ' + // phpcs:disable Generic.Commenting + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable/enable: whole standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: category from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: a category; enable: the whole standard containing the category' => [ + 'code' => ' + # phpcs:disable Generic.Commenting + $var = FALSE; + //TODO: write some code + # phpcs:enable Generic + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; enable: the category containing the sniff' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: single sniff from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 1, + ], + 'disable: whole standard; enable: single sniff from the standard; disable: that same sniff; enable: everything' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code + // phpcs:disable Generic.Commenting.Todo + //TODO: write some code + // phpcs:enable + //TODO: write some code', + 'expectedErrors' => 0, + 'expectedWarnings' => 2, + ], + 'disable: whole standard; enable: single sniff from the standard; enable: other sniff from the standard' => [ + 'code' => ' + // phpcs:disable Generic + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo + //TODO: write some code + $var = FALSE; + // phpcs:enable Generic.PHP.LowerCaseConstant + //TODO: write some code + $var = FALSE;', + 'expectedErrors' => 1, + 'expectedWarnings' => 2, + ], + ]; + + }//end dataEnableSelected() + + + /** + * Test ignoring specific sniffs. + * + * @param string $before Annotation to place before the code. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataIgnoreSelected + * + * @return void + */ + public function testIgnoreSelected($before, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = <<process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testIgnoreSelected() + + + /** + * Data provider. + * + * @see testIgnoreSelected() + * + * @return array> + */ + public static function dataIgnoreSelected() + { + return [ + 'no suppression' => [ + 'before' => '', + 'expectedErrors' => 2, + 'expectedWarnings' => 2, + ], + + // With suppression. + 'ignore: single sniff' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'ignore: multiple sniffs' => [ + 'before' => '// phpcs:ignore Generic.Commenting.Todo,Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; ignore: single sniff' => [ + 'before' => '// phpcs:disable Generic.Commenting.Todo'.PHP_EOL.'// phpcs:ignore Generic.PHP.LowerCaseConstant', + 'expectedErrors' => 1, + 'expectedWarnings' => 0, + ], + 'ignore: category of sniffs' => [ + 'before' => '# phpcs:ignore Generic.Commenting', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'ignore: whole standard' => [ + 'before' => '// phpcs:ignore Generic', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + ]; + + }//end dataIgnoreSelected() + + + /** + * Test ignoring specific sniffs. + * + * @param string $code Code pattern to check. + * @param int $expectedErrors Number of errors expected. + * @param int $expectedWarnings Number of warnings expected. + * + * @dataProvider dataCommenting + * + * @return void + */ + public function testCommenting($code, $expectedErrors, $expectedWarnings) + { + static $config, $ruleset; + + if (isset($config, $ruleset) === false) { + $config = new ConfigDouble(); + $config->standards = ['Generic']; + $config->sniffs = [ + 'Generic.PHP.LowerCaseConstant', + 'Generic.Commenting.Todo', + ]; + + $ruleset = new Ruleset($config); + } + + $content = 'process(); + + $this->assertSame($expectedErrors, $file->getErrorCount()); + $this->assertCount($expectedErrors, $file->getErrors()); + + $this->assertSame($expectedWarnings, $file->getWarningCount()); + $this->assertCount($expectedWarnings, $file->getWarnings()); + + }//end testCommenting() + + + /** + * Data provider. + * + * @see testCommenting() + * + * @return array> + */ + public static function dataCommenting() + { + return [ + 'ignore: single sniff' => [ + 'code' => ' + // phpcs:ignore Generic.Commenting.Todo -- Because reasons + $var = FALSE; //TODO: write some code + $var = FALSE; //TODO: write some code', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'disable: single sniff; enable: same sniff - test whitespace handling around reason delimiter' => [ + 'code' => ' + // phpcs:disable Generic.Commenting.Todo --Because reasons + $var = FALSE; + //TODO: write some code + // phpcs:enable Generic.Commenting.Todo -- Because reasons + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 1, + ], + 'disable: single sniff, multi-line comment' => [ + 'code' => ' + /* + Disable some checks + phpcs:disable Generic.Commenting.Todo + */ + $var = FALSE; + //TODO: write some code', + 'expectedErrors' => 1, + 'expectedWarnings' => 0, + ], + 'ignore: single sniff, multi-line slash comment' => [ + 'code' => ' + // Turn off a check for the next line of code. + // phpcs:ignore Generic.Commenting.Todo + $var = FALSE; //TODO: write some code + $var = FALSE; //TODO: write some code', + 'expectedErrors' => 2, + 'expectedWarnings' => 1, + ], + 'enable before disable, sniff not in standard' => [ + 'code' => ' + // phpcs:enable Generic.PHP.NoSilencedErrors -- Because reasons + $var = @delete( $filename ); + ', + 'expectedErrors' => 0, + 'expectedWarnings' => 0, + ], + ]; + + }//end dataCommenting() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc new file mode 100644 index 000000000..835167989 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.inc @@ -0,0 +1,105 @@ + fn() => return 1, + 'b' => fn() => return 1, +]; + +/* testStaticArrowFunction */ +static fn ($a) => $a; + +return 0; + +/* testArrowFunctionReturnValue */ +fn(): array => [a($a, $b)]; + +/* testArrowFunctionAsArgument */ +$foo = foo( + fn() => bar() +); + +/* testArrowFunctionWithArrayAsArgument */ +$foo = foo( + fn() => [$row[0], $row[3]] +); + +$match = match ($a) { + /* testMatchCase */ + 1 => 'foo', + /* testMatchDefault */ + default => 'bar' +}; + +$match = match ($a) { + /* testMatchMultipleCase */ + 1, 2, => $a * $b, + /* testMatchDefaultComma */ + default, => 'something' +}; + +match ($pressedKey) { + /* testMatchFunctionCall */ + Key::RETURN_ => save($value, $user) +}; + +$result = match (true) { + /* testMatchFunctionCallArm */ + str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', + str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', + default => 'pl' +}; + +/* testMatchClosure */ +$result = match ($key) { + 1 => function($a, $b) {}, + 2 => function($b, $c) {}, +}; + +/* testMatchArray */ +$result = match ($key) { + 1 => [1,2,3], + 2 => [1 => one(), 2 => two()], +}; + +/* testNestedMatch */ +$result = match ($key) { + 1 => match ($key) { + 1 => 'one', + 2 => 'two', + }, + 2 => match ($key) { + 1 => 'two', + 2 => 'one', + }, +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php new file mode 100644 index 000000000..be8f458ae --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindEndOfStatementTest.php @@ -0,0 +1,457 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::findEndOfStatement method. + * + * @covers \PHP_CodeSniffer\Files\File::findEndOfStatement + */ +final class FindEndOfStatementTest extends AbstractMethodUnitTest +{ + + + /** + * Test that end of statement is NEVER before the "current" token. + * + * @return void + */ + public function testEndIsNeverLessThanCurrentToken() + { + $tokens = self::$phpcsFile->getTokens(); + $errors = []; + + for ($i = 0; $i < self::$phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $end = self::$phpcsFile->findEndOfStatement($i); + + // Collect all the errors. + if ($end < $i) { + $errors[] = sprintf( + 'End of statement for token %1$d (%2$s: %3$s) on line %4$d is %5$d (%6$s), which is less than %1$d', + $i, + $tokens[$i]['type'], + $tokens[$i]['content'], + $tokens[$i]['line'], + $end, + $tokens[$end]['type'] + ); + } + } + + $this->assertSame([], $errors); + + }//end testEndIsNeverLessThanCurrentToken() + + + /** + * Test a simple assignment. + * + * @return void + */ + public function testSimpleAssignment() + { + $start = $this->getTargetToken('/* testSimpleAssignment */', T_VARIABLE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testSimpleAssignment() + + + /** + * Test a direct call to a control structure. + * + * @return void + */ + public function testControlStructure() + { + $start = $this->getTargetToken('/* testControlStructure */', T_WHILE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 6), $found); + + }//end testControlStructure() + + + /** + * Test the assignment of a closure. + * + * @return void + */ + public function testClosureAssignment() + { + $start = $this->getTargetToken('/* testClosureAssignment */', T_VARIABLE, '$a'); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 13), $found); + + }//end testClosureAssignment() + + + /** + * Test using a heredoc in a function argument. + * + * @return void + */ + public function testHeredocFunctionArg() + { + // Find the end of the function. + $start = $this->getTargetToken('/* testHeredocFunctionArg */', T_STRING, 'myFunction'); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 10), $found); + + // Find the end of the heredoc. + $start += 2; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 4), $found); + + // Find the end of the last arg. + $start = ($found + 2); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame($start, $found); + + }//end testHeredocFunctionArg() + + + /** + * Test parts of a switch statement. + * + * @return void + */ + public function testSwitch() + { + // Find the end of the switch. + $start = $this->getTargetToken('/* testSwitch */', T_SWITCH); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 28), $found); + + // Find the end of the case. + $start += 9; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 8), $found); + + // Find the end of default case. + $start += 11; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 6), $found); + + }//end testSwitch() + + + /** + * Test statements that are array values. + * + * @return void + */ + public function testStatementAsArrayValue() + { + // Test short array syntax. + $start = $this->getTargetToken('/* testStatementAsArrayValue */', T_NEW); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 2), $found); + + // Test long array syntax. + $start += 12; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 2), $found); + + // Test same statement outside of array. + $start += 10; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 3), $found); + + }//end testStatementAsArrayValue() + + + /** + * Test a use group. + * + * @return void + */ + public function testUseGroup() + { + $start = $this->getTargetToken('/* testUseGroup */', T_USE); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 23), $found); + + }//end testUseGroup() + + + /** + * Test arrow function as array value. + * + * @return void + */ + public function testArrowFunctionArrayValue() + { + $start = $this->getTargetToken('/* testArrowFunctionArrayValue */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 9), $found); + + }//end testArrowFunctionArrayValue() + + + /** + * Test static arrow function. + * + * @return void + */ + public function testStaticArrowFunction() + { + $static = $this->getTargetToken('/* testStaticArrowFunction */', T_STATIC); + $fn = $this->getTargetToken('/* testStaticArrowFunction */', T_FN); + + $endOfStatementStatic = self::$phpcsFile->findEndOfStatement($static); + $endOfStatementFn = self::$phpcsFile->findEndOfStatement($fn); + + $this->assertSame($endOfStatementFn, $endOfStatementStatic); + + }//end testStaticArrowFunction() + + + /** + * Test arrow function with return value. + * + * @return void + */ + public function testArrowFunctionReturnValue() + { + $start = $this->getTargetToken('/* testArrowFunctionReturnValue */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 18), $found); + + }//end testArrowFunctionReturnValue() + + + /** + * Test arrow function used as a function argument. + * + * @return void + */ + public function testArrowFunctionAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionAsArgument */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 8), $found); + + }//end testArrowFunctionAsArgument() + + + /** + * Test arrow function with arrays used as a function argument. + * + * @return void + */ + public function testArrowFunctionWithArrayAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionWithArrayAsArgument */', T_FN); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 17), $found); + + }//end testArrowFunctionWithArrayAsArgument() + + + /** + * Test simple match expression case. + * + * @return void + */ + public function testMatchCase() + { + $start = $this->getTargetToken('/* testMatchCase */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + $start = $this->getTargetToken('/* testMatchCase */', T_CONSTANT_ENCAPSED_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 1), $found); + + }//end testMatchCase() + + + /** + * Test simple match expression default case. + * + * @return void + */ + public function testMatchDefault() + { + $start = $this->getTargetToken('/* testMatchDefault */', T_MATCH_DEFAULT); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 4), $found); + + $start = $this->getTargetToken('/* testMatchDefault */', T_CONSTANT_ENCAPSED_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefault() + + + /** + * Test multiple comma-separated match expression case values. + * + * @return void + */ + public function testMatchMultipleCase() + { + $start = $this->getTargetToken('/* testMatchMultipleCase */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + $this->assertSame(($start + 13), $found); + + $start += 6; + $found = self::$phpcsFile->findEndOfStatement($start); + $this->assertSame(($start + 7), $found); + + }//end testMatchMultipleCase() + + + /** + * Test match expression default case with trailing comma. + * + * @return void + */ + public function testMatchDefaultComma() + { + $start = $this->getTargetToken('/* testMatchDefaultComma */', T_MATCH_DEFAULT); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testMatchDefaultComma() + + + /** + * Test match expression with function call. + * + * @return void + */ + public function testMatchFunctionCall() + { + $start = $this->getTargetToken('/* testMatchFunctionCall */', T_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 12), $found); + + $start += 8; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 1), $found); + + }//end testMatchFunctionCall() + + + /** + * Test match expression with function call in the arm. + * + * @return void + */ + public function testMatchFunctionCallArm() + { + // Check the first case. + $start = $this->getTargetToken('/* testMatchFunctionCallArm */', T_STRING); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 21), $found); + + // Check the second case. + $start += 24; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 21), $found); + + }//end testMatchFunctionCallArm() + + + /** + * Test match expression with closure. + * + * @return void + */ + public function testMatchClosure() + { + $start = $this->getTargetToken('/* testMatchClosure */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 14), $found); + + $start += 17; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 14), $found); + + }//end testMatchClosure() + + + /** + * Test match expression with array declaration. + * + * @return void + */ + public function testMatchArray() + { + $start = $this->getTargetToken('/* testMatchArray */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 11), $found); + + $start += 14; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 22), $found); + + }//end testMatchArray() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testNestedMatch() + { + $start = $this->getTargetToken('/* testNestedMatch */', T_LNUMBER); + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 30), $found); + + $start += 21; + $found = self::$phpcsFile->findEndOfStatement($start); + + $this->assertSame(($start + 5), $found); + + }//end testNestedMatch() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc new file mode 100644 index 000000000..dae2cd969 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindExtendedClassNameTest.inc @@ -0,0 +1,52 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::findExtendedClassName method. + * + * @covers \PHP_CodeSniffer\Files\File::findExtendedClassName + */ +final class FindExtendedClassNameTest extends AbstractMethodUnitTest +{ + + + /** + * Test getting a `false` result when a non-existent token is passed. + * + * @return void + */ + public function testNonExistentToken() + { + $result = self::$phpcsFile->findExtendedClassName(100000); + $this->assertFalse($result); + + }//end testNonExistentToken() + + + /** + * Test getting a `false` result when a token other than one of the supported tokens is passed. + * + * @return void + */ + public function testNotAClass() + { + $token = $this->getTargetToken('/* testNotAClass */', [T_FUNCTION]); + $result = self::$phpcsFile->findExtendedClassName($token); + $this->assertFalse($result); + + }//end testNotAClass() + + + /** + * Test retrieving the name of the class being extended by another class + * (or interface). + * + * @param string $identifier Comment which precedes the test case. + * @param string|false $expected Expected function output. + * + * @dataProvider dataExtendedClass + * + * @return void + */ + public function testFindExtendedClassName($identifier, $expected) + { + $OOToken = $this->getTargetToken($identifier, [T_CLASS, T_ANON_CLASS, T_INTERFACE]); + $result = self::$phpcsFile->findExtendedClassName($OOToken); + $this->assertSame($expected, $result); + + }//end testFindExtendedClassName() + + + /** + * Data provider for the FindExtendedClassName test. + * + * @see testFindExtendedClassName() + * + * @return array> + */ + public static function dataExtendedClass() + { + return [ + 'class does not extend' => [ + 'identifier' => '/* testNonExtendedClass */', + 'expected' => false, + ], + 'class extends unqualified class' => [ + 'identifier' => '/* testExtendsUnqualifiedClass */', + 'expected' => 'testFECNClass', + ], + 'class extends fully qualified class' => [ + 'identifier' => '/* testExtendsFullyQualifiedClass */', + 'expected' => '\PHP_CodeSniffer\Tests\Core\File\testFECNClass', + ], + 'class extends partially qualified class' => [ + 'identifier' => '/* testExtendsPartiallyQualifiedClass */', + 'expected' => 'Core\File\RelativeClass', + ], + 'interface does not extend' => [ + 'identifier' => '/* testNonExtendedInterface */', + 'expected' => false, + ], + 'interface extends unqualified interface' => [ + 'identifier' => '/* testInterfaceExtendsUnqualifiedInterface */', + 'expected' => 'testFECNInterface', + ], + 'interface extends fully qualified interface' => [ + 'identifier' => '/* testInterfaceExtendsFullyQualifiedInterface */', + 'expected' => '\PHP_CodeSniffer\Tests\Core\File\testFECNInterface', + ], + 'anon class extends unqualified class' => [ + 'identifier' => '/* testExtendedAnonClass */', + 'expected' => 'testFECNExtendedAnonClass', + ], + 'class does not extend but contains anon class which extends' => [ + 'identifier' => '/* testNestedExtendedClass */', + 'expected' => false, + ], + 'anon class extends, nested in non-extended class' => [ + 'identifier' => '/* testNestedExtendedAnonClass */', + 'expected' => 'testFECNAnonClass', + ], + 'class extends and implements' => [ + 'identifier' => '/* testClassThatExtendsAndImplements */', + 'expected' => 'testFECNClass', + ], + 'class implements and extends' => [ + 'identifier' => '/* testClassThatImplementsAndExtends */', + 'expected' => 'testFECNClass', + ], + 'interface extends multiple interfaces (not supported)' => [ + 'identifier' => '/* testInterfaceMultiExtends */', + 'expected' => '\Package\FooInterface', + ], + 'parse error - extends keyword, but no class name' => [ + 'identifier' => '/* testMissingExtendsName */', + 'expected' => false, + ], + 'parse error - live coding - no curly braces' => [ + 'identifier' => '/* testParseError */', + 'expected' => false, + ], + ]; + + }//end dataExtendedClass() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc new file mode 100644 index 000000000..3246efa2c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindImplementedInterfaceNamesTest.inc @@ -0,0 +1,47 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::findImplementedInterfaceNames method. + * + * @covers \PHP_CodeSniffer\Files\File::findImplementedInterfaceNames + */ +final class FindImplementedInterfaceNamesTest extends AbstractMethodUnitTest +{ + + + /** + * Test getting a `false` result when a non-existent token is passed. + * + * @return void + */ + public function testNonExistentToken() + { + $result = self::$phpcsFile->findImplementedInterfaceNames(100000); + $this->assertFalse($result); + + }//end testNonExistentToken() + + + /** + * Test getting a `false` result when a token other than one of the supported tokens is passed. + * + * @return void + */ + public function testNotAClass() + { + $token = $this->getTargetToken('/* testNotAClass */', [T_FUNCTION]); + $result = self::$phpcsFile->findImplementedInterfaceNames($token); + $this->assertFalse($result); + + }//end testNotAClass() + + + /** + * Test retrieving the name(s) of the interfaces being implemented by a class. + * + * @param string $identifier Comment which precedes the test case. + * @param array|false $expected Expected function output. + * + * @dataProvider dataImplementedInterface + * + * @return void + */ + public function testFindImplementedInterfaceNames($identifier, $expected) + { + $OOToken = $this->getTargetToken($identifier, [T_CLASS, T_ANON_CLASS, T_INTERFACE, T_ENUM]); + $result = self::$phpcsFile->findImplementedInterfaceNames($OOToken); + $this->assertSame($expected, $result); + + }//end testFindImplementedInterfaceNames() + + + /** + * Data provider for the FindImplementedInterfaceNames test. + * + * @see testFindImplementedInterfaceNames() + * + * @return array>> + */ + public static function dataImplementedInterface() + { + return [ + 'interface declaration, no implements' => [ + 'identifier' => '/* testPlainInterface */', + 'expected' => false, + ], + 'class does not implement' => [ + 'identifier' => '/* testNonImplementedClass */', + 'expected' => false, + ], + 'class implements single interface, unqualified' => [ + 'identifier' => '/* testClassImplementsSingle */', + 'expected' => [ + 'testFIINInterface', + ], + ], + 'class implements multiple interfaces' => [ + 'identifier' => '/* testClassImplementsMultiple */', + 'expected' => [ + 'testFIINInterface', + 'testFIINInterface2', + ], + ], + 'class implements single interface, fully qualified' => [ + 'identifier' => '/* testImplementsFullyQualified */', + 'expected' => [ + '\PHP_CodeSniffer\Tests\Core\File\testFIINInterface', + ], + ], + 'class implements single interface, partially qualified' => [ + 'identifier' => '/* testImplementsPartiallyQualified */', + 'expected' => [ + 'Core\File\RelativeInterface', + ], + ], + 'class extends and implements' => [ + 'identifier' => '/* testClassThatExtendsAndImplements */', + 'expected' => [ + 'InterfaceA', + '\NameSpaced\Cat\InterfaceB', + ], + ], + 'class implements and extends' => [ + 'identifier' => '/* testClassThatImplementsAndExtends */', + 'expected' => [ + '\InterfaceA', + 'InterfaceB', + ], + ], + 'enum does not implement' => [ + 'identifier' => '/* testBackedEnumWithoutImplements */', + 'expected' => false, + ], + 'enum implements single interface, unqualified' => [ + 'identifier' => '/* testEnumImplementsSingle */', + 'expected' => [ + 'Colorful', + ], + ], + 'enum implements multiple interfaces, unqualified + fully qualified' => [ + 'identifier' => '/* testBackedEnumImplementsMulti */', + 'expected' => [ + 'Colorful', + '\Deck', + ], + ], + 'anon class implements single interface, unqualified' => [ + 'identifier' => '/* testAnonClassImplementsSingle */', + 'expected' => [ + 'testFIINInterface', + ], + ], + 'parse error - implements keyword, but no interface name' => [ + 'identifier' => '/* testMissingImplementsName */', + 'expected' => false, + ], + 'parse error - live coding - no curly braces' => [ + 'identifier' => '/* testParseError */', + 'expected' => false, + ], + ]; + + }//end dataImplementedInterface() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc new file mode 100644 index 000000000..574b98614 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.inc @@ -0,0 +1,200 @@ + $foo + $bar, 'b' => true]; + +/* testUseGroup */ +use Vendor\Package\{ClassA as A, ClassB, ClassC as C}; + +$a = [ + /* testArrowFunctionArrayValue */ + 'a' => fn() => 1, + 'b' => fn() => 1, +]; + +/* testStaticArrowFunction */ +static fn ($a) => $a; + +/* testArrowFunctionReturnValue */ +fn(): array => [a($a, $b)]; + +/* testArrowFunctionAsArgument */ +$foo = foo( + fn() => bar() +); + +/* testArrowFunctionWithArrayAsArgument */ +$foo = foo( + fn() => [$row[0], $row[3]] +); + +$match = match ($a) { + /* testMatchCase */ + 1 => 'foo', + /* testMatchDefault */ + default => 'bar' +}; + +$match = match ($a) { + /* testMatchMultipleCase */ + 1, 2, => $a * $b, + /* testMatchDefaultComma */ + default, => 'something' +}; + +match ($pressedKey) { + /* testMatchFunctionCall */ + Key::RETURN_ => save($value, $user) +}; + +$result = match (true) { + /* testMatchFunctionCallArm */ + str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en', + str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr', + default => 'pl' +}; + +/* testMatchClosure */ +$result = match ($key) { + 1 => function($a, $b) {}, + 2 => function($b, $c) {}, +}; + +/* testMatchArray */ +$result = match ($key) { + 1 => [1,2,3], + 2 => [1 => one($a, $b), 2 => two($b, $c)], + 3 => [], +}; + +/* testNestedMatch */ +$result = match ($key) { + 1 => match ($key) { + 1 => 'one', + 2 => 'two', + }, + 2 => match ($key) { + 1 => 'two', + 2 => 'one', + }, +}; + +return 0; + +/* testOpenTag */ +?> +

    Test

    +', foo(), ''; + +/* testOpenTagWithEcho */ +?> +

    Test

    +', foo(), ''; + +$value = [ + /* testPrecededByArrowFunctionInArray - Expected */ + Url::make('View Song', fn($song) => $song->url()) + /* testPrecededByArrowFunctionInArray */ + ->onlyOnDetail(), + + new Panel('Information', [ + Text::make('Title') + ]), +]; + +switch ($foo) { + /* testCaseStatement */ + case 1: + /* testInsideCaseStatement */ + $var = doSomething(); + /* testInsideCaseBreakStatement */ + break 1; + + case 2: + /* testInsideCaseContinueStatement */ + continue 1; + + case 3: + /* testInsideCaseReturnStatement */ + return false; + + case 4: + /* testInsideCaseExitStatement */ + exit(1); + + case 5: + /* testInsideCaseThrowStatement */ + throw new Exception(); + + /* testDefaultStatement */ + default: + /* testInsideDefaultContinueStatement */ + continue $var; +} + +match ($var) { + true => + /* test437ClosureDeclaration */ + function ($var) { + /* test437EchoNestedWithinClosureWithinMatch */ + echo $var, 'text', PHP_EOL; + }, + default => false +}; + +match ($var) { + /* test437NestedLongArrayWithinMatch */ + 'a' => array( 1, 2.5, $var), + /* test437NestedFunctionCallWithinMatch */ + 'b' => functionCall( 11, $var, 50.50), + /* test437NestedArrowFunctionWithinMatch */ + 'c' => fn($p1, /* test437FnSecondParamWithinMatch */ $p2) => $p1 + $p2, + default => false +}; + +callMe($paramA, match ($var) { + /* test437NestedLongArrayWithinNestedMatch */ + 'a' => array( 1, 2.5, $var), + /* test437NestedFunctionCallWithinNestedMatch */ + 'b' => functionCall( 11, $var, 50.50), + /* test437NestedArrowFunctionWithinNestedMatch */ + 'c' => fn($p1, /* test437FnSecondParamWithinNestedMatch */ $p2) => $p1 + $p2, + default => false +}); + +match ($var) { + /* test437NestedShortArrayWithinMatch */ + 'a' => [ 1, 2.5, $var], + default => false +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php new file mode 100644 index 000000000..bfcbfaf95 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/FindStartOfStatementTest.php @@ -0,0 +1,973 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @copyright 2019-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Tests for the \PHP_CodeSniffer\Files\File:findStartOfStatement method. + * + * @covers \PHP_CodeSniffer\Files\File::findStartOfStatement + */ +final class FindStartOfStatementTest extends AbstractMethodUnitTest +{ + + + /** + * Test that start of statement is NEVER beyond the "current" token. + * + * @return void + */ + public function testStartIsNeverMoreThanCurrentToken() + { + $tokens = self::$phpcsFile->getTokens(); + $errors = []; + + for ($i = 0; $i < self::$phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + $start = self::$phpcsFile->findStartOfStatement($i); + + // Collect all the errors. + if ($start > $i) { + $errors[] = sprintf( + 'Start of statement for token %1$d (%2$s: %3$s) on line %4$d is %5$d (%6$s), which is more than %1$d', + $i, + $tokens[$i]['type'], + $tokens[$i]['content'], + $tokens[$i]['line'], + $start, + $tokens[$start]['type'] + ); + } + } + + $this->assertSame([], $errors); + + }//end testStartIsNeverMoreThanCurrentToken() + + + /** + * Test a simple assignment. + * + * @return void + */ + public function testSimpleAssignment() + { + $start = $this->getTargetToken('/* testSimpleAssignment */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + }//end testSimpleAssignment() + + + /** + * Test a function call. + * + * @return void + */ + public function testFunctionCall() + { + $start = $this->getTargetToken('/* testFunctionCall */', T_CLOSE_PARENTHESIS); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testFunctionCall() + + + /** + * Test a function call. + * + * @return void + */ + public function testFunctionCallArgument() + { + $start = $this->getTargetToken('/* testFunctionCallArgument */', T_VARIABLE, '$b'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testFunctionCallArgument() + + + /** + * Test a direct call to a control structure. + * + * @return void + */ + public function testControlStructure() + { + $start = $this->getTargetToken('/* testControlStructure */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testControlStructure() + + + /** + * Test the assignment of a closure. + * + * @return void + */ + public function testClosureAssignment() + { + $start = $this->getTargetToken('/* testClosureAssignment */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 11), $found); + + }//end testClosureAssignment() + + + /** + * Test using a heredoc in a function argument. + * + * @return void + */ + public function testHeredocFunctionArg() + { + // Find the start of the function. + $start = $this->getTargetToken('/* testHeredocFunctionArg */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + // Find the start of the heredoc. + $start -= 4; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 4), $found); + + // Find the start of the last arg. + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testHeredocFunctionArg() + + + /** + * Test parts of a switch statement. + * + * @return void + */ + public function testSwitch() + { + // Find the start of the switch. + $start = $this->getTargetToken('/* testSwitch */', T_CLOSE_CURLY_BRACKET); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 47), $found); + + // Find the start of default case. + $start -= 5; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + // Find the start of the second case. + $start -= 12; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + // Find the start of the first case. + $start -= 13; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 8), $found); + + // Test inside the first case. + $start--; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testSwitch() + + + /** + * Test statements that are array values. + * + * @return void + */ + public function testStatementAsArrayValue() + { + // Test short array syntax. + $start = $this->getTargetToken('/* testStatementAsArrayValue */', T_STRING, 'Datetime'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + // Test long array syntax. + $start += 12; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + // Test same statement outside of array. + $start++; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 9), $found); + + // Test with an array index. + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 5), $found); + + }//end testStatementAsArrayValue() + + + /** + * Test a use group. + * + * @return void + */ + public function testUseGroup() + { + $start = $this->getTargetToken('/* testUseGroup */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 23), $found); + + }//end testUseGroup() + + + /** + * Test arrow function as array value. + * + * @return void + */ + public function testArrowFunctionArrayValue() + { + $start = $this->getTargetToken('/* testArrowFunctionArrayValue */', T_COMMA); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 7), $found); + + }//end testArrowFunctionArrayValue() + + + /** + * Test static arrow function. + * + * @return void + */ + public function testStaticArrowFunction() + { + $start = $this->getTargetToken('/* testStaticArrowFunction */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 11), $found); + + }//end testStaticArrowFunction() + + + /** + * Test arrow function with return value. + * + * @return void + */ + public function testArrowFunctionReturnValue() + { + $start = $this->getTargetToken('/* testArrowFunctionReturnValue */', T_SEMICOLON); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + }//end testArrowFunctionReturnValue() + + + /** + * Test arrow function used as a function argument. + * + * @return void + */ + public function testArrowFunctionAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionAsArgument */', T_FN); + $start += 8; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 8), $found); + + }//end testArrowFunctionAsArgument() + + + /** + * Test arrow function with arrays used as a function argument. + * + * @return void + */ + public function testArrowFunctionWithArrayAsArgument() + { + $start = $this->getTargetToken('/* testArrowFunctionWithArrayAsArgument */', T_FN); + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 17), $found); + + }//end testArrowFunctionWithArrayAsArgument() + + + /** + * Test simple match expression case. + * + * @return void + */ + public function testMatchCase() + { + $start = $this->getTargetToken('/* testMatchCase */', T_COMMA); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testMatchCase() + + + /** + * Test simple match expression default case. + * + * @return void + */ + public function testMatchDefault() + { + $start = $this->getTargetToken('/* testMatchDefault */', T_CONSTANT_ENCAPSED_STRING, "'bar'"); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefault() + + + /** + * Test multiple comma-separated match expression case values. + * + * @return void + */ + public function testMatchMultipleCase() + { + $start = $this->getTargetToken('/* testMatchMultipleCase */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + $start += 6; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 4), $found); + + }//end testMatchMultipleCase() + + + /** + * Test match expression default case with trailing comma. + * + * @return void + */ + public function testMatchDefaultComma() + { + $start = $this->getTargetToken('/* testMatchDefaultComma */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 3), $found); + + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($start, $found); + + }//end testMatchDefaultComma() + + + /** + * Test match expression with function call. + * + * @return void + */ + public function testMatchFunctionCall() + { + $start = $this->getTargetToken('/* testMatchFunctionCall */', T_CLOSE_PARENTHESIS); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 6), $found); + + }//end testMatchFunctionCall() + + + /** + * Test match expression with function call in the arm. + * + * @return void + */ + public function testMatchFunctionCallArm() + { + // Check the first case. + $start = $this->getTargetToken('/* testMatchFunctionCallArm */', T_MATCH_ARROW); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + // Check the second case. + $start += 24; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 18), $found); + + }//end testMatchFunctionCallArm() + + + /** + * Test match expression with closure. + * + * @return void + */ + public function testMatchClosure() + { + $start = $this->getTargetToken('/* testMatchClosure */', T_LNUMBER); + $start += 14; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + $start += 17; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 10), $found); + + }//end testMatchClosure() + + + /** + * Test match expression with array declaration. + * + * @return void + */ + public function testMatchArray() + { + // Start of first case statement. + $start = $this->getTargetToken('/* testMatchArray */', T_LNUMBER); + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame($start, $found); + + // Comma after first statement. + $start += 11; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame(($start - 7), $found); + + // Start of second case statement. + $start += 3; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame($start, $found); + + // Comma after first statement. + $start += 30; + $found = self::$phpcsFile->findStartOfStatement($start); + $this->assertSame(($start - 26), $found); + + }//end testMatchArray() + + + /** + * Test nested match expressions. + * + * @return void + */ + public function testNestedMatch() + { + $start = $this->getTargetToken('/* testNestedMatch */', T_LNUMBER); + $start += 30; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 26), $found); + + $start -= 4; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + $start -= 3; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 2), $found); + + }//end testNestedMatch() + + + /** + * Test PHP open tag. + * + * @return void + */ + public function testOpenTag() + { + $start = $this->getTargetToken('/* testOpenTag */', T_OPEN_TAG); + $start += 2; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testOpenTag() + + + /** + * Test PHP short open echo tag. + * + * @return void + */ + public function testOpenTagWithEcho() + { + $start = $this->getTargetToken('/* testOpenTagWithEcho */', T_OPEN_TAG_WITH_ECHO); + $start += 3; + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame(($start - 1), $found); + + }//end testOpenTagWithEcho() + + + /** + * Test object call on result of static function call with arrow function as parameter and wrapped within an array. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/2849 + * @link https://github.com/squizlabs/PHP_CodeSniffer/commit/fbf67efc3fc0c2a355f5585d49f4f6fe160ff2f9 + * + * @return void + */ + public function testObjectCallPrecededByArrowFunctionAsFunctionCallParameterInArray() + { + $expected = $this->getTargetToken('/* testPrecededByArrowFunctionInArray - Expected */', T_STRING, 'Url'); + + $start = $this->getTargetToken('/* testPrecededByArrowFunctionInArray */', T_STRING, 'onlyOnDetail'); + $found = self::$phpcsFile->findStartOfStatement($start); + + $this->assertSame($expected, $found); + + }//end testObjectCallPrecededByArrowFunctionAsFunctionCallParameterInArray() + + + /** + * Test finding the start of a statement inside a switch control structure case/default statement. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $targets The token to search for after the test marker. + * @param string|int $expectedTarget Token code of the expected start of statement stack pointer. + * + * @link https://github.com/squizlabs/php_codesniffer/issues/3192 + * @link https://github.com/squizlabs/PHP_CodeSniffer/pull/3186/commits/18a0e54735bb9b3850fec266e5f4c50dacf618ea + * + * @dataProvider dataFindStartInsideSwitchCaseDefaultStatements + * + * @return void + */ + public function testFindStartInsideSwitchCaseDefaultStatements($testMarker, $targets, $expectedTarget) + { + $testToken = $this->getTargetToken($testMarker, $targets); + $expected = $this->getTargetToken($testMarker, $expectedTarget); + + $found = self::$phpcsFile->findStartOfStatement($testToken); + + $this->assertSame($expected, $found); + + }//end testFindStartInsideSwitchCaseDefaultStatements() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataFindStartInsideSwitchCaseDefaultStatements() + { + return [ + 'Case keyword should be start of case statement - case itself' => [ + 'testMarker' => '/* testCaseStatement */', + 'targets' => T_CASE, + 'expectedTarget' => T_CASE, + ], + 'Case keyword should be start of case statement - number (what\'s being compared)' => [ + 'testMarker' => '/* testCaseStatement */', + 'targets' => T_LNUMBER, + 'expectedTarget' => T_CASE, + ], + 'Variable should be start of arbitrary assignment statement - variable itself' => [ + 'testMarker' => '/* testInsideCaseStatement */', + 'targets' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + 'Variable should be start of arbitrary assignment statement - equal sign' => [ + 'testMarker' => '/* testInsideCaseStatement */', + 'targets' => T_EQUAL, + 'expectedTarget' => T_VARIABLE, + ], + 'Variable should be start of arbitrary assignment statement - function call' => [ + 'testMarker' => '/* testInsideCaseStatement */', + 'targets' => T_STRING, + 'expectedTarget' => T_VARIABLE, + ], + 'Break should be start for contents of the break statement - contents' => [ + 'testMarker' => '/* testInsideCaseBreakStatement */', + 'targets' => T_LNUMBER, + 'expectedTarget' => T_BREAK, + ], + 'Continue should be start for contents of the continue statement - contents' => [ + 'testMarker' => '/* testInsideCaseContinueStatement */', + 'targets' => T_LNUMBER, + 'expectedTarget' => T_CONTINUE, + ], + 'Return should be start for contents of the return statement - contents' => [ + 'testMarker' => '/* testInsideCaseReturnStatement */', + 'targets' => T_FALSE, + 'expectedTarget' => T_RETURN, + ], + 'Exit should be start for contents of the exit statement - close parenthesis' => [ + // Note: not sure if this is actually correct - should this be the open parenthesis ? + 'testMarker' => '/* testInsideCaseExitStatement */', + 'targets' => T_CLOSE_PARENTHESIS, + 'expectedTarget' => T_EXIT, + ], + 'Throw should be start for contents of the throw statement - new keyword' => [ + 'testMarker' => '/* testInsideCaseThrowStatement */', + 'targets' => T_NEW, + 'expectedTarget' => T_THROW, + ], + 'Throw should be start for contents of the throw statement - exception name' => [ + 'testMarker' => '/* testInsideCaseThrowStatement */', + 'targets' => T_STRING, + 'expectedTarget' => T_THROW, + ], + 'Throw should be start for contents of the throw statement - close parenthesis' => [ + 'testMarker' => '/* testInsideCaseThrowStatement */', + 'targets' => T_CLOSE_PARENTHESIS, + 'expectedTarget' => T_THROW, + ], + 'Default keyword should be start of default statement - default itself' => [ + 'testMarker' => '/* testDefaultStatement */', + 'targets' => T_DEFAULT, + 'expectedTarget' => T_DEFAULT, + ], + 'Return should be start for contents of the return statement (inside default) - variable' => [ + 'testMarker' => '/* testInsideDefaultContinueStatement */', + 'targets' => T_VARIABLE, + 'expectedTarget' => T_CONTINUE, + ], + ]; + + }//end dataFindStartInsideSwitchCaseDefaultStatements() + + + /** + * Test finding the start of a statement inside a closed scope nested within a match expressions. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $target The token to search for after the test marker. + * @param int|string $expectedTarget Token code of the expected start of statement stack pointer. + * + * @link https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/437 + * + * @dataProvider dataFindStartInsideClosedScopeNestedWithinMatch + * + * @return void + */ + public function testFindStartInsideClosedScopeNestedWithinMatch($testMarker, $target, $expectedTarget) + { + $testToken = $this->getTargetToken($testMarker, $target); + $expected = $this->getTargetToken($testMarker, $expectedTarget); + + $found = self::$phpcsFile->findStartOfStatement($testToken); + + $this->assertSame($expected, $found); + + }//end testFindStartInsideClosedScopeNestedWithinMatch() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataFindStartInsideClosedScopeNestedWithinMatch() + { + return [ + // These were already working correctly. + 'Closure function keyword should be start of closure - closure keyword' => [ + 'testMarker' => '/* test437ClosureDeclaration */', + 'target' => T_CLOSURE, + 'expectedTarget' => T_CLOSURE, + ], + 'Open curly is a statement/expression opener - open curly' => [ + 'testMarker' => '/* test437ClosureDeclaration */', + 'target' => T_OPEN_CURLY_BRACKET, + 'expectedTarget' => T_OPEN_CURLY_BRACKET, + ], + + 'Echo should be start for expression - echo keyword' => [ + 'testMarker' => '/* test437EchoNestedWithinClosureWithinMatch */', + 'target' => T_ECHO, + 'expectedTarget' => T_ECHO, + ], + 'Echo should be start for expression - variable' => [ + 'testMarker' => '/* test437EchoNestedWithinClosureWithinMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_ECHO, + ], + 'Echo should be start for expression - comma' => [ + 'testMarker' => '/* test437EchoNestedWithinClosureWithinMatch */', + 'target' => T_COMMA, + 'expectedTarget' => T_ECHO, + ], + + // These were not working correctly and would previously return the close curly of the match expression. + 'First token after comma in echo expression should be start for expression - text string' => [ + 'testMarker' => '/* test437EchoNestedWithinClosureWithinMatch */', + 'target' => T_CONSTANT_ENCAPSED_STRING, + 'expectedTarget' => T_CONSTANT_ENCAPSED_STRING, + ], + 'First token after comma in echo expression - PHP_EOL constant' => [ + 'testMarker' => '/* test437EchoNestedWithinClosureWithinMatch */', + 'target' => T_STRING, + 'expectedTarget' => T_STRING, + ], + 'First token after comma in echo expression - semicolon' => [ + 'testMarker' => '/* test437EchoNestedWithinClosureWithinMatch */', + 'target' => T_SEMICOLON, + 'expectedTarget' => T_STRING, + ], + ]; + + }//end dataFindStartInsideClosedScopeNestedWithinMatch() + + + /** + * Test finding the start of a statement for a token within a set of parentheses within a match expressions. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $target The token to search for after the test marker. + * @param int|string $expectedTarget Token code of the expected start of statement stack pointer. + * + * @link https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/437 + * + * @dataProvider dataFindStartInsideParenthesesNestedWithinMatch + * + * @return void + */ + public function testFindStartInsideParenthesesNestedWithinMatch($testMarker, $target, $expectedTarget) + { + $testToken = $this->getTargetToken($testMarker, $target); + $expected = $this->getTargetToken($testMarker, $expectedTarget); + + $found = self::$phpcsFile->findStartOfStatement($testToken); + + $this->assertSame($expected, $found); + + }//end testFindStartInsideParenthesesNestedWithinMatch() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataFindStartInsideParenthesesNestedWithinMatch() + { + return [ + 'Array item itself should be start for first array item' => [ + 'testMarker' => '/* test437NestedLongArrayWithinMatch */', + 'target' => T_LNUMBER, + 'expectedTarget' => T_LNUMBER, + ], + 'Array item itself should be start for second array item' => [ + 'testMarker' => '/* test437NestedLongArrayWithinMatch */', + 'target' => T_DNUMBER, + 'expectedTarget' => T_DNUMBER, + ], + 'Array item itself should be start for third array item' => [ + 'testMarker' => '/* test437NestedLongArrayWithinMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + + 'Parameter itself should be start for first param passed to function call' => [ + 'testMarker' => '/* test437NestedFunctionCallWithinMatch */', + 'target' => T_LNUMBER, + 'expectedTarget' => T_LNUMBER, + ], + 'Parameter itself should be start for second param passed to function call' => [ + 'testMarker' => '/* test437NestedFunctionCallWithinMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + 'Parameter itself should be start for third param passed to function call' => [ + 'testMarker' => '/* test437NestedFunctionCallWithinMatch */', + 'target' => T_DNUMBER, + 'expectedTarget' => T_DNUMBER, + ], + + 'Parameter itself should be start for first param declared in arrow function' => [ + 'testMarker' => '/* test437NestedArrowFunctionWithinMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + 'Parameter itself should be start for second param declared in arrow function' => [ + 'testMarker' => '/* test437FnSecondParamWithinMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + ]; + + }//end dataFindStartInsideParenthesesNestedWithinMatch() + + + /** + * Test finding the start of a statement for a token within a set of parentheses within a match expressions, + * which itself is nested within parentheses. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $target The token to search for after the test marker. + * @param int|string $expectedTarget Token code of the expected start of statement stack pointer. + * + * @link https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/437 + * + * @dataProvider dataFindStartInsideParenthesesNestedWithinNestedMatch + * + * @return void + */ + public function testFindStartInsideParenthesesNestedWithinNestedMatch($testMarker, $target, $expectedTarget) + { + $testToken = $this->getTargetToken($testMarker, $target); + $expected = $this->getTargetToken($testMarker, $expectedTarget); + + $found = self::$phpcsFile->findStartOfStatement($testToken); + + $this->assertSame($expected, $found); + + }//end testFindStartInsideParenthesesNestedWithinNestedMatch() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataFindStartInsideParenthesesNestedWithinNestedMatch() + { + return [ + 'Array item itself should be start for first array item' => [ + 'testMarker' => '/* test437NestedLongArrayWithinNestedMatch */', + 'target' => T_LNUMBER, + 'expectedTarget' => T_LNUMBER, + ], + 'Array item itself should be start for second array item' => [ + 'testMarker' => '/* test437NestedLongArrayWithinNestedMatch */', + 'target' => T_DNUMBER, + 'expectedTarget' => T_DNUMBER, + ], + 'Array item itself should be start for third array item' => [ + 'testMarker' => '/* test437NestedLongArrayWithinNestedMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + + 'Parameter itself should be start for first param passed to function call' => [ + 'testMarker' => '/* test437NestedFunctionCallWithinNestedMatch */', + 'target' => T_LNUMBER, + 'expectedTarget' => T_LNUMBER, + ], + 'Parameter itself should be start for second param passed to function call' => [ + 'testMarker' => '/* test437NestedFunctionCallWithinNestedMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + 'Parameter itself should be start for third param passed to function call' => [ + 'testMarker' => '/* test437NestedFunctionCallWithinNestedMatch */', + 'target' => T_DNUMBER, + 'expectedTarget' => T_DNUMBER, + ], + + 'Parameter itself should be start for first param declared in arrow function' => [ + 'testMarker' => '/* test437NestedArrowFunctionWithinNestedMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + 'Parameter itself should be start for second param declared in arrow function' => [ + 'testMarker' => '/* test437FnSecondParamWithinNestedMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + ]; + + }//end dataFindStartInsideParenthesesNestedWithinNestedMatch() + + + /** + * Test finding the start of a statement for a token within a short array within a match expressions. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $target The token to search for after the test marker. + * @param int|string $expectedTarget Token code of the expected start of statement stack pointer. + * + * @link https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/437 + * + * @dataProvider dataFindStartInsideShortArrayNestedWithinMatch + * + * @return void + */ + public function testFindStartInsideShortArrayNestedWithinMatch($testMarker, $target, $expectedTarget) + { + $testToken = $this->getTargetToken($testMarker, $target); + $expected = $this->getTargetToken($testMarker, $expectedTarget); + + $found = self::$phpcsFile->findStartOfStatement($testToken); + + $this->assertSame($expected, $found); + + }//end testFindStartInsideShortArrayNestedWithinMatch() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataFindStartInsideShortArrayNestedWithinMatch() + { + return [ + 'Array item itself should be start for first array item' => [ + 'testMarker' => '/* test437NestedShortArrayWithinMatch */', + 'target' => T_LNUMBER, + 'expectedTarget' => T_LNUMBER, + ], + 'Array item itself should be start for second array item' => [ + 'testMarker' => '/* test437NestedShortArrayWithinMatch */', + 'target' => T_DNUMBER, + 'expectedTarget' => T_DNUMBER, + ], + 'Array item itself should be start for third array item' => [ + 'testMarker' => '/* test437NestedShortArrayWithinMatch */', + 'target' => T_VARIABLE, + 'expectedTarget' => T_VARIABLE, + ], + ]; + + }//end dataFindStartInsideShortArrayNestedWithinMatch() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetClassPropertiesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetClassPropertiesTest.inc new file mode 100644 index 000000000..2490a0965 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetClassPropertiesTest.inc @@ -0,0 +1,58 @@ + + * @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File:getClassProperties method. + * + * @covers \PHP_CodeSniffer\Files\File::getClassProperties + */ +final class GetClassPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test receiving an expected exception when a non class token is passed. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $tokenType The type of token to look for after the marker. + * + * @dataProvider dataNotAClassException + * + * @return void + */ + public function testNotAClassException($testMarker, $tokenType) + { + $this->expectRunTimeException('$stackPtr must be of type T_CLASS'); + + $target = $this->getTargetToken($testMarker, $tokenType); + self::$phpcsFile->getClassProperties($target); + + }//end testNotAClassException() + + + /** + * Data provider. + * + * @see testNotAClassException() For the array format. + * + * @return array> + */ + public static function dataNotAClassException() + { + return [ + 'interface' => [ + 'testMarker' => '/* testNotAClass */', + 'tokenType' => T_INTERFACE, + ], + 'anon-class' => [ + 'testMarker' => '/* testAnonClass */', + 'tokenType' => T_ANON_CLASS, + ], + 'enum' => [ + 'testMarker' => '/* testEnum */', + 'tokenType' => T_ENUM, + ], + ]; + + }//end dataNotAClassException() + + + /** + * Test retrieving the properties for a class declaration. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expected Expected function output. + * + * @dataProvider dataGetClassProperties + * + * @return void + */ + public function testGetClassProperties($testMarker, $expected) + { + $class = $this->getTargetToken($testMarker, T_CLASS); + $result = self::$phpcsFile->getClassProperties($class); + $this->assertSame($expected, $result); + + }//end testGetClassProperties() + + + /** + * Data provider. + * + * @see testGetClassProperties() For the array format. + * + * @return array>> + */ + public static function dataGetClassProperties() + { + return [ + 'no-properties' => [ + 'testMarker' => '/* testClassWithoutProperties */', + 'expected' => [ + 'is_abstract' => false, + 'is_final' => false, + 'is_readonly' => false, + ], + ], + 'abstract' => [ + 'testMarker' => '/* testAbstractClass */', + 'expected' => [ + 'is_abstract' => true, + 'is_final' => false, + 'is_readonly' => false, + ], + ], + 'final' => [ + 'testMarker' => '/* testFinalClass */', + 'expected' => [ + 'is_abstract' => false, + 'is_final' => true, + 'is_readonly' => false, + ], + ], + 'readonly' => [ + 'testMarker' => '/* testReadonlyClass */', + 'expected' => [ + 'is_abstract' => false, + 'is_final' => false, + 'is_readonly' => true, + ], + ], + 'final-readonly' => [ + 'testMarker' => '/* testFinalReadonlyClass */', + 'expected' => [ + 'is_abstract' => false, + 'is_final' => true, + 'is_readonly' => true, + ], + ], + 'readonly-final' => [ + 'testMarker' => '/* testReadonlyFinalClass */', + 'expected' => [ + 'is_abstract' => false, + 'is_final' => true, + 'is_readonly' => true, + ], + ], + 'abstract-readonly' => [ + 'testMarker' => '/* testAbstractReadonlyClass */', + 'expected' => [ + 'is_abstract' => true, + 'is_final' => false, + 'is_readonly' => true, + ], + ], + 'readonly-abstract' => [ + 'testMarker' => '/* testReadonlyAbstractClass */', + 'expected' => [ + 'is_abstract' => true, + 'is_final' => false, + 'is_readonly' => true, + ], + ], + 'comments-and-new-lines' => [ + 'testMarker' => '/* testWithCommentsAndNewLines */', + 'expected' => [ + 'is_abstract' => true, + 'is_final' => false, + 'is_readonly' => false, + ], + ], + 'no-properties-with-docblock' => [ + 'testMarker' => '/* testWithDocblockWithoutProperties */', + 'expected' => [ + 'is_abstract' => false, + 'is_final' => false, + 'is_readonly' => false, + ], + ], + 'abstract-final-parse-error' => [ + 'testMarker' => '/* testParseErrorAbstractFinal */', + 'expected' => [ + 'is_abstract' => true, + 'is_final' => true, + 'is_readonly' => false, + ], + ], + ]; + + }//end dataGetClassProperties() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.inc new file mode 100644 index 000000000..e7684daa9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.inc @@ -0,0 +1,91 @@ + $v) { + + /* condition 11-2: try */ + try { + --$k; + + /* condition 11-3: catch */ + } catch (Exception $e) { + /* testInException */ + echo 'oh darn'; + /* condition 11-4: finally */ + } finally { + return true; + } + } + + $a++; + } + break; + + /* condition 8b: default */ + default: + /* testInDefault */ + $return = 'nada'; + return $return; + } + } + } + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.php new file mode 100644 index 000000000..5df0f5a27 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetConditionTest.php @@ -0,0 +1,494 @@ + + * @copyright 2022-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Tests for the \PHP_CodeSniffer\Files\File:getCondition and \PHP_CodeSniffer\Files\File:hasCondition methods. + * + * @covers \PHP_CodeSniffer\Files\File::getCondition + * @covers \PHP_CodeSniffer\Files\File::hasCondition + */ +final class GetConditionTest extends AbstractMethodUnitTest +{ + + /** + * List of all the test markers with their target token in the test case file. + * + * - The startPoint token is left out as it is tested separately. + * - The key is the type of token to look for after the test marker. + * + * @var array + */ + protected static $testTargets = [ + T_VARIABLE => '/* testSeriouslyNestedMethod */', + T_RETURN => '/* testDeepestNested */', + T_ECHO => '/* testInException */', + T_CONSTANT_ENCAPSED_STRING => '/* testInDefault */', + ]; + + /** + * List of all the condition markers in the test case file. + * + * @var array + */ + protected $conditionMarkers = [ + '/* condition 0: namespace */', + '/* condition 1: if */', + '/* condition 2: function */', + '/* condition 3-1: if */', + '/* condition 3-2: else */', + '/* condition 4: if */', + '/* condition 5: nested class */', + '/* condition 6: class method */', + '/* condition 7: switch */', + '/* condition 8a: case */', + '/* condition 9: while */', + '/* condition 10-1: if */', + '/* condition 11-1: nested anonymous class */', + '/* condition 12: nested anonymous class method */', + '/* condition 13: closure */', + '/* condition 10-2: elseif */', + '/* condition 10-3: foreach */', + '/* condition 11-2: try */', + '/* condition 11-3: catch */', + '/* condition 11-4: finally */', + '/* condition 8b: default */', + ]; + + /** + * Base array with all the scope opening tokens. + * + * This array is merged with expected result arrays for various unit tests + * to make sure all possible conditions are tested. + * + * This array should be kept in sync with the Tokens::$scopeOpeners array. + * This array isn't auto-generated based on the array in Tokens as for these + * tests we want to have access to the token constant names, not just their values. + * + * @var array + */ + protected $conditionDefaults = [ + 'T_CLASS' => false, + 'T_ANON_CLASS' => false, + 'T_INTERFACE' => false, + 'T_TRAIT' => false, + 'T_NAMESPACE' => false, + 'T_FUNCTION' => false, + 'T_CLOSURE' => false, + 'T_IF' => false, + 'T_SWITCH' => false, + 'T_CASE' => false, + 'T_DECLARE' => false, + 'T_DEFAULT' => false, + 'T_WHILE' => false, + 'T_ELSE' => false, + 'T_ELSEIF' => false, + 'T_FOR' => false, + 'T_FOREACH' => false, + 'T_DO' => false, + 'T_TRY' => false, + 'T_CATCH' => false, + 'T_FINALLY' => false, + 'T_PROPERTY' => false, + 'T_OBJECT' => false, + 'T_USE' => false, + ]; + + /** + * Cache for the test token stack pointers. + * + * @var array + */ + protected static $testTokens = []; + + /** + * Cache for the marker token stack pointers. + * + * @var array + */ + protected static $markerTokens = []; + + + /** + * Set up the token position caches for the tests. + * + * Retrieves the test tokens and marker token stack pointer positions + * only once and caches them as they won't change between the tests anyway. + * + * @before + * + * @return void + */ + protected function setUpCaches() + { + if (empty(self::$testTokens) === true) { + foreach (self::$testTargets as $targetToken => $marker) { + self::$testTokens[$marker] = $this->getTargetToken($marker, $targetToken); + } + } + + if (empty(self::$markerTokens) === true) { + foreach ($this->conditionMarkers as $marker) { + self::$markerTokens[$marker] = $this->getTargetToken($marker, Tokens::$scopeOpeners); + } + } + + }//end setUpCaches() + + + /** + * Test passing a non-existent token pointer. + * + * @return void + */ + public function testNonExistentToken() + { + $result = self::$phpcsFile->getCondition(100000, Tokens::$ooScopeTokens); + $this->assertFalse($result); + + $result = self::$phpcsFile->hasCondition(100000, T_IF); + $this->assertFalse($result); + + }//end testNonExistentToken() + + + /** + * Test passing a non conditional token. + * + * @return void + */ + public function testNonConditionalToken() + { + $targetType = T_STRING; + $stackPtr = $this->getTargetToken('/* testStartPoint */', $targetType); + + $result = self::$phpcsFile->getCondition($stackPtr, T_IF); + $this->assertFalse($result); + + $result = self::$phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + $this->assertFalse($result); + + }//end testNonConditionalToken() + + + /** + * Test retrieving a specific condition from a tokens "conditions" array. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedResults Array with the condition token type to search for as key + * and the marker for the expected stack pointer result as a value. + * + * @dataProvider dataGetCondition + * + * @return void + */ + public function testGetCondition($testMarker, $expectedResults) + { + $stackPtr = self::$testTokens[$testMarker]; + + // Add expected results for all test markers not listed in the data provider. + $expectedResults += $this->conditionDefaults; + + foreach ($expectedResults as $conditionType => $expected) { + if (is_string($expected) === true) { + $expected = self::$markerTokens[$expected]; + } + + $result = self::$phpcsFile->getCondition($stackPtr, constant($conditionType)); + $this->assertSame( + $expected, + $result, + "Assertion failed for test marker '{$testMarker}' with condition {$conditionType}" + ); + } + + }//end testGetCondition() + + + /** + * Data provider. + * + * Only the conditions which are expected to be *found* need to be listed here. + * All other potential conditions will automatically also be tested and will expect + * `false` as a result. + * + * @see testGetCondition() For the array format. + * + * @return array>> + */ + public static function dataGetCondition() + { + return [ + 'testSeriouslyNestedMethod' => [ + 'testMarker' => '/* testSeriouslyNestedMethod */', + 'expectedResults' => [ + 'T_CLASS' => '/* condition 5: nested class */', + 'T_NAMESPACE' => '/* condition 0: namespace */', + 'T_FUNCTION' => '/* condition 2: function */', + 'T_IF' => '/* condition 1: if */', + 'T_ELSE' => '/* condition 3-2: else */', + ], + ], + 'testDeepestNested' => [ + 'testMarker' => '/* testDeepestNested */', + 'expectedResults' => [ + 'T_CLASS' => '/* condition 5: nested class */', + 'T_ANON_CLASS' => '/* condition 11-1: nested anonymous class */', + 'T_NAMESPACE' => '/* condition 0: namespace */', + 'T_FUNCTION' => '/* condition 2: function */', + 'T_CLOSURE' => '/* condition 13: closure */', + 'T_IF' => '/* condition 1: if */', + 'T_SWITCH' => '/* condition 7: switch */', + 'T_CASE' => '/* condition 8a: case */', + 'T_WHILE' => '/* condition 9: while */', + 'T_ELSE' => '/* condition 3-2: else */', + ], + ], + 'testInException' => [ + 'testMarker' => '/* testInException */', + 'expectedResults' => [ + 'T_CLASS' => '/* condition 5: nested class */', + 'T_NAMESPACE' => '/* condition 0: namespace */', + 'T_FUNCTION' => '/* condition 2: function */', + 'T_IF' => '/* condition 1: if */', + 'T_SWITCH' => '/* condition 7: switch */', + 'T_CASE' => '/* condition 8a: case */', + 'T_WHILE' => '/* condition 9: while */', + 'T_ELSE' => '/* condition 3-2: else */', + 'T_FOREACH' => '/* condition 10-3: foreach */', + 'T_CATCH' => '/* condition 11-3: catch */', + ], + ], + 'testInDefault' => [ + 'testMarker' => '/* testInDefault */', + 'expectedResults' => [ + 'T_CLASS' => '/* condition 5: nested class */', + 'T_NAMESPACE' => '/* condition 0: namespace */', + 'T_FUNCTION' => '/* condition 2: function */', + 'T_IF' => '/* condition 1: if */', + 'T_SWITCH' => '/* condition 7: switch */', + 'T_DEFAULT' => '/* condition 8b: default */', + 'T_ELSE' => '/* condition 3-2: else */', + ], + ], + ]; + + }//end dataGetCondition() + + + /** + * Test retrieving a specific condition from a tokens "conditions" array. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedResults Array with the condition token type to search for as key + * and the marker for the expected stack pointer result as a value. + * + * @dataProvider dataGetConditionReversed + * + * @return void + */ + public function testGetConditionReversed($testMarker, $expectedResults) + { + $stackPtr = self::$testTokens[$testMarker]; + + // Add expected results for all test markers not listed in the data provider. + $expectedResults += $this->conditionDefaults; + + foreach ($expectedResults as $conditionType => $expected) { + if (is_string($expected) === true) { + $expected = self::$markerTokens[$expected]; + } + + $result = self::$phpcsFile->getCondition($stackPtr, constant($conditionType), false); + $this->assertSame( + $expected, + $result, + "Assertion failed for test marker '{$testMarker}' with condition {$conditionType} (reversed)" + ); + } + + }//end testGetConditionReversed() + + + /** + * Data provider. + * + * Only the conditions which are expected to be *found* need to be listed here. + * All other potential conditions will automatically also be tested and will expect + * `false` as a result. + * + * @see testGetConditionReversed() For the array format. + * + * @return array>> + */ + public static function dataGetConditionReversed() + { + $data = self::dataGetCondition(); + + // Set up the data for the reversed results. + $data['testSeriouslyNestedMethod']['expectedResults']['T_IF'] = '/* condition 4: if */'; + + $data['testDeepestNested']['expectedResults']['T_FUNCTION'] = '/* condition 12: nested anonymous class method */'; + $data['testDeepestNested']['expectedResults']['T_IF'] = '/* condition 10-1: if */'; + + $data['testInException']['expectedResults']['T_FUNCTION'] = '/* condition 6: class method */'; + $data['testInException']['expectedResults']['T_IF'] = '/* condition 4: if */'; + + $data['testInDefault']['expectedResults']['T_FUNCTION'] = '/* condition 6: class method */'; + $data['testInDefault']['expectedResults']['T_IF'] = '/* condition 4: if */'; + + return $data; + + }//end dataGetConditionReversed() + + + /** + * Test whether a token has a condition of a certain type. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array $expectedResults Array with the condition token type to search for as key + * and the expected result as a value. + * + * @dataProvider dataHasCondition + * + * @return void + */ + public function testHasCondition($testMarker, $expectedResults) + { + $stackPtr = self::$testTokens[$testMarker]; + + // Add expected results for all test markers not listed in the data provider. + $expectedResults += $this->conditionDefaults; + + foreach ($expectedResults as $conditionType => $expected) { + $result = self::$phpcsFile->hasCondition($stackPtr, constant($conditionType)); + $this->assertSame( + $expected, + $result, + "Assertion failed for test marker '{$testMarker}' with condition {$conditionType}" + ); + } + + }//end testHasCondition() + + + /** + * Data Provider. + * + * Only list the "true" conditions in the $results array. + * All other potential conditions will automatically also be tested + * and will expect "false" as a result. + * + * @see testHasCondition() For the array format. + * + * @return array>> + */ + public static function dataHasCondition() + { + return [ + 'testSeriouslyNestedMethod' => [ + 'testMarker' => '/* testSeriouslyNestedMethod */', + 'expectedResults' => [ + 'T_CLASS' => true, + 'T_NAMESPACE' => true, + 'T_FUNCTION' => true, + 'T_IF' => true, + 'T_ELSE' => true, + ], + ], + 'testDeepestNested' => [ + 'testMarker' => '/* testDeepestNested */', + 'expectedResults' => [ + 'T_CLASS' => true, + 'T_ANON_CLASS' => true, + 'T_NAMESPACE' => true, + 'T_FUNCTION' => true, + 'T_CLOSURE' => true, + 'T_IF' => true, + 'T_SWITCH' => true, + 'T_CASE' => true, + 'T_WHILE' => true, + 'T_ELSE' => true, + ], + ], + 'testInException' => [ + 'testMarker' => '/* testInException */', + 'expectedResults' => [ + 'T_CLASS' => true, + 'T_NAMESPACE' => true, + 'T_FUNCTION' => true, + 'T_IF' => true, + 'T_SWITCH' => true, + 'T_CASE' => true, + 'T_WHILE' => true, + 'T_ELSE' => true, + 'T_FOREACH' => true, + 'T_CATCH' => true, + ], + ], + 'testInDefault' => [ + 'testMarker' => '/* testInDefault */', + 'expectedResults' => [ + 'T_CLASS' => true, + 'T_NAMESPACE' => true, + 'T_FUNCTION' => true, + 'T_IF' => true, + 'T_SWITCH' => true, + 'T_DEFAULT' => true, + 'T_ELSE' => true, + ], + ], + ]; + + }//end dataHasCondition() + + + /** + * Test whether a token has a condition of a certain type, with multiple allowed possibilities. + * + * @return void + */ + public function testHasConditionMultipleTypes() + { + $stackPtr = self::$testTokens['/* testInException */']; + + $result = self::$phpcsFile->hasCondition($stackPtr, [T_TRY, T_FINALLY]); + $this->assertFalse( + $result, + 'Failed asserting that "testInException" does not have a "try" nor a "finally" condition' + ); + + $result = self::$phpcsFile->hasCondition($stackPtr, [T_TRY, T_CATCH, T_FINALLY]); + $this->assertTrue( + $result, + 'Failed asserting that "testInException" has a "try", "catch" or "finally" condition' + ); + + $stackPtr = self::$testTokens['/* testSeriouslyNestedMethod */']; + + $result = self::$phpcsFile->hasCondition($stackPtr, [T_ANON_CLASS, T_CLOSURE]); + $this->assertFalse( + $result, + 'Failed asserting that "testSeriouslyNestedMethod" does not have an anonymous class nor a closure condition' + ); + + $result = self::$phpcsFile->hasCondition($stackPtr, Tokens::$ooScopeTokens); + $this->assertTrue( + $result, + 'Failed asserting that "testSeriouslyNestedMethod" has an OO Scope token condition' + ); + + }//end testHasConditionMultipleTypes() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.js b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.js new file mode 100644 index 000000000..ee0a76a44 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.js @@ -0,0 +1,23 @@ +/* testInvalidTokenPassed */ +print something; + +var object = +{ + /* testClosure */ + propertyName: function () {} +} + +/* testFunction */ +function functionName() {} + +/* testClass */ +class ClassName +{ + /* testMethod */ + methodName() { + return false; + } +} + +/* testFunctionUnicode */ +function π() {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.php new file mode 100644 index 000000000..af3fe56d2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameJSTest.php @@ -0,0 +1,158 @@ + + * @copyright 2022-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File:getDeclarationName method. + * + * @covers \PHP_CodeSniffer\Files\File::getDeclarationName + */ +final class GetDeclarationNameJSTest extends AbstractMethodUnitTest +{ + + /** + * The file extension of the test case file (without leading dot). + * + * @var string + */ + protected static $fileExtension = 'js'; + + + /** + * Test receiving an expected exception when a non-supported token is passed. + * + * @return void + */ + public function testInvalidTokenPassed() + { + $this->expectRunTimeException('Token type "T_STRING" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM'); + + $target = $this->getTargetToken('/* testInvalidTokenPassed */', T_STRING); + self::$phpcsFile->getDeclarationName($target); + + }//end testInvalidTokenPassed() + + + /** + * Test receiving "null" when passed an anonymous construct or in case of a parse error. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $targetType Token type of the token to get as stackPtr. + * + * @dataProvider dataGetDeclarationNameNull + * + * @return void + */ + public function testGetDeclarationNameNull($testMarker, $targetType) + { + $target = $this->getTargetToken($testMarker, $targetType); + $result = self::$phpcsFile->getDeclarationName($target); + $this->assertNull($result); + + }//end testGetDeclarationNameNull() + + + /** + * Data provider. + * + * @see GetDeclarationNameTest::testGetDeclarationNameNull() + * + * @return array> + */ + public static function dataGetDeclarationNameNull() + { + return [ + 'closure' => [ + 'testMarker' => '/* testClosure */', + 'targetType' => T_CLOSURE, + ], + ]; + + }//end dataGetDeclarationNameNull() + + + /** + * Test retrieving the name of a function or OO structure. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expected Expected function output. + * @param array|null $targetType Token type of the token to get as stackPtr. + * + * @dataProvider dataGetDeclarationName + * + * @return void + */ + public function testGetDeclarationName($testMarker, $expected, $targetType=null) + { + if (isset($targetType) === false) { + $targetType = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + ]; + } + + $target = $this->getTargetToken($testMarker, $targetType); + $result = self::$phpcsFile->getDeclarationName($target); + $this->assertSame($expected, $result); + + }//end testGetDeclarationName() + + + /** + * Data provider. + * + * @see GetDeclarationNameTest::testGetDeclarationName() + * + * @return array>> + */ + public static function dataGetDeclarationName() + { + return [ + 'function' => [ + 'testMarker' => '/* testFunction */', + 'expected' => 'functionName', + ], + 'class' => [ + 'testMarker' => '/* testClass */', + 'expected' => 'ClassName', + 'targetType' => [ + T_CLASS, + T_STRING, + ], + ], + 'function-unicode-name' => [ + 'testMarker' => '/* testFunctionUnicode */', + 'expected' => 'π', + ], + ]; + + }//end dataGetDeclarationName() + + + /** + * Test retrieving the name of JS ES6 class method. + * + * @return void + */ + public function testGetDeclarationNameES6Method() + { + $target = $this->getTargetToken('/* testMethod */', [T_CLASS, T_INTERFACE, T_TRAIT, T_FUNCTION]); + $result = self::$phpcsFile->getDeclarationName($target); + $this->assertSame('methodName', $result); + + }//end testGetDeclarationNameES6Method() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameTest.inc new file mode 100644 index 000000000..14902245b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetDeclarationNameTest.inc @@ -0,0 +1,102 @@ + + * @copyright 2022-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File:getDeclarationName method. + * + * @covers \PHP_CodeSniffer\Files\File::getDeclarationName + */ +final class GetDeclarationNameTest extends AbstractMethodUnitTest +{ + + + /** + * Test receiving an expected exception when a non-supported token is passed. + * + * @return void + */ + public function testInvalidTokenPassed() + { + $this->expectRunTimeException('Token type "T_STRING" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM'); + + $target = $this->getTargetToken('/* testInvalidTokenPassed */', T_STRING); + self::$phpcsFile->getDeclarationName($target); + + }//end testInvalidTokenPassed() + + + /** + * Test receiving "null" when passed an anonymous construct or in case of a parse error. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $targetType Token type of the token to get as stackPtr. + * + * @dataProvider dataGetDeclarationNameNull + * + * @return void + */ + public function testGetDeclarationNameNull($testMarker, $targetType) + { + $target = $this->getTargetToken($testMarker, $targetType); + $result = self::$phpcsFile->getDeclarationName($target); + $this->assertNull($result); + + }//end testGetDeclarationNameNull() + + + /** + * Data provider. + * + * @see testGetDeclarationNameNull() For the array format. + * + * @return array> + */ + public static function dataGetDeclarationNameNull() + { + return [ + 'closure' => [ + 'testMarker' => '/* testClosure */', + 'targetType' => T_CLOSURE, + ], + 'anon-class-with-parentheses' => [ + 'testMarker' => '/* testAnonClassWithParens */', + 'targetType' => T_ANON_CLASS, + ], + 'anon-class-with-parentheses-2' => [ + 'testMarker' => '/* testAnonClassWithParens2 */', + 'targetType' => T_ANON_CLASS, + ], + 'anon-class-without-parentheses' => [ + 'testMarker' => '/* testAnonClassWithoutParens */', + 'targetType' => T_ANON_CLASS, + ], + 'anon-class-extends-without-parentheses' => [ + 'testMarker' => '/* testAnonClassExtendsWithoutParens */', + 'targetType' => T_ANON_CLASS, + ], + 'live-coding' => [ + 'testMarker' => '/* testLiveCoding */', + 'targetType' => T_FUNCTION, + ], + ]; + + }//end dataGetDeclarationNameNull() + + + /** + * Test retrieving the name of a function or OO structure. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expected Expected function output. + * @param int|string|null $targetType Token type of the token to get as stackPtr. + * + * @dataProvider dataGetDeclarationName + * + * @return void + */ + public function testGetDeclarationName($testMarker, $expected, $targetType=null) + { + if (isset($targetType) === false) { + $targetType = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_ENUM, + T_FUNCTION, + ]; + } + + $target = $this->getTargetToken($testMarker, $targetType); + $result = self::$phpcsFile->getDeclarationName($target); + $this->assertSame($expected, $result); + + }//end testGetDeclarationName() + + + /** + * Data provider. + * + * @see testGetDeclarationName() For the array format. + * + * @return array> + */ + public static function dataGetDeclarationName() + { + return [ + 'function' => [ + 'testMarker' => '/* testFunction */', + 'expected' => 'functionName', + ], + 'function-return-by-reference' => [ + 'testMarker' => '/* testFunctionReturnByRef */', + 'expected' => 'functionNameByRef', + ], + 'class' => [ + 'testMarker' => '/* testClass */', + 'expected' => 'ClassName', + ], + 'method' => [ + 'testMarker' => '/* testMethod */', + 'expected' => 'methodName', + ], + 'abstract-method' => [ + 'testMarker' => '/* testAbstractMethod */', + 'expected' => 'abstractMethodName', + ], + 'method-return-by-reference' => [ + 'testMarker' => '/* testMethodReturnByRef */', + 'expected' => 'MethodNameByRef', + ], + 'extended-class' => [ + 'testMarker' => '/* testExtendedClass */', + 'expected' => 'ExtendedClass', + ], + 'interface' => [ + 'testMarker' => '/* testInterface */', + 'expected' => 'InterfaceName', + ], + 'trait' => [ + 'testMarker' => '/* testTrait */', + 'expected' => 'TraitName', + ], + 'function-name-ends-with-number' => [ + 'testMarker' => '/* testFunctionEndingWithNumber */', + 'expected' => 'ValidNameEndingWithNumber5', + ], + 'class-with-numbers-in-name' => [ + 'testMarker' => '/* testClassWithNumber */', + 'expected' => 'ClassWith1Number', + ], + 'interface-with-numbers-in-name' => [ + 'testMarker' => '/* testInterfaceWithNumbers */', + 'expected' => 'InterfaceWith12345Numbers', + ], + 'class-with-comments-and-new-lines' => [ + 'testMarker' => '/* testClassWithCommentsAndNewLines */', + 'expected' => 'ClassWithCommentsAndNewLines', + ], + 'function-named-fn' => [ + 'testMarker' => '/* testFunctionFn */', + 'expected' => 'fn', + ], + 'enum-pure' => [ + 'testMarker' => '/* testPureEnum */', + 'expected' => 'Foo', + ], + 'enum-backed-space-between-name-and-colon' => [ + 'testMarker' => '/* testBackedEnumSpaceBetweenNameAndColon */', + 'expected' => 'Hoo', + ], + 'enum-backed-no-space-between-name-and-colon' => [ + 'testMarker' => '/* testBackedEnumNoSpaceBetweenNameAndColon */', + 'expected' => 'Suit', + ], + 'function-return-by-reference-with-reserved-keyword-each' => [ + 'testMarker' => '/* testFunctionReturnByRefWithReservedKeywordEach */', + 'expected' => 'each', + ], + 'function-return-by-reference-with-reserved-keyword-parent' => [ + 'testMarker' => '/* testFunctionReturnByRefWithReservedKeywordParent */', + 'expected' => 'parent', + ], + 'function-return-by-reference-with-reserved-keyword-self' => [ + 'testMarker' => '/* testFunctionReturnByRefWithReservedKeywordSelf */', + 'expected' => 'self', + ], + 'function-return-by-reference-with-reserved-keyword-static' => [ + 'testMarker' => '/* testFunctionReturnByRefWithReservedKeywordStatic */', + 'expected' => 'static', + ], + ]; + + }//end dataGetDeclarationName() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc new file mode 100644 index 000000000..514662081 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.inc @@ -0,0 +1,356 @@ + 'a', 'b' => 'b' ), + /* testGroupPrivate 3 */ + $varQ = 'string', + /* testGroupPrivate 4 */ + $varR = 123, + /* testGroupPrivate 5 */ + $varS = ONE / self::THREE, + /* testGroupPrivate 6 */ + $varT = [ + 'a' => 'a', + 'b' => 'b' + ], + /* testGroupPrivate 7 */ + $varU = __DIR__ . "/base"; + + + /* testMethodParam */ + public function methodName($param) { + /* testImportedGlobal */ + global $importedGlobal = true; + + /* testLocalVariable */ + $localVariable = true; + } + + /* testPropertyAfterMethod */ + private static $varV = true; + + /* testMessyNullableType */ + public /* comment + */ ? //comment + array $foo = []; + + /* testNamespaceType */ + public \MyNamespace\MyClass $foo; + + /* testNullableNamespaceType 1 */ + private ?ClassName $nullableClassType; + + /* testNullableNamespaceType 2 */ + protected ?Folder\ClassName $nullableClassType2; + + /* testMultilineNamespaceType */ + public \MyNamespace /** comment *\/ comment */ + \MyClass /* comment */ + \Foo $foo; + +} + +interface Base +{ + /* testInterfaceProperty */ + protected $anonymous; +} + +/* testGlobalVariable */ +$globalVariable = true; + +/* testNotAVariable */ +return; + +$a = ( $foo == $bar ? new stdClass() : + new class() { + /* testNestedProperty 1 */ + public $var = true; + + /* testNestedMethodParam 1 */ + public function something($var = false) {} + } +); + +function_call( 'param', new class { + /* testNestedProperty 2 */ + public $year = 2017; + + /* testNestedMethodParam 2 */ + public function __construct( $open, $post_id ) {} +}, 10, 2 ); + +class PHP8Mixed { + /* testPHP8MixedTypeHint */ + public static miXed $mixed; + + /* testPHP8MixedTypeHintNullable */ + // Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. + private ?mixed $nullableMixed; +} + +class NSOperatorInType { + /* testNamespaceOperatorTypeHint */ + public ?namespace\Name $prop; +} + +$anon = class() { + /* testPHP8UnionTypesSimple */ + public int|float $unionTypeSimple; + + /* testPHP8UnionTypesTwoClasses */ + private MyClassA|\Package\MyClassB $unionTypesTwoClasses; + + /* testPHP8UnionTypesAllBaseTypes */ + protected array|bool|int|float|NULL|object|string $unionTypesAllBaseTypes; + + /* testPHP8UnionTypesAllPseudoTypes */ + // Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. + var false|mixed|self|parent|iterable|Resource $unionTypesAllPseudoTypes; + + /* testPHP8UnionTypesIllegalTypes */ + // Intentional fatal error - types which are not allowed for properties, but that's not the concern of the method. + // Note: static is also not allowed as a type, but using static for a property type is not supported by the tokenizer. + public callable|void $unionTypesIllegalTypes; + + /* testPHP8UnionTypesNullable */ + // Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. + public ?int|float $unionTypesNullable; + + /* testPHP8PseudoTypeNull */ + // PHP 8.0 - 8.1: Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. + public null $pseudoTypeNull; + + /* testPHP8PseudoTypeFalse */ + // PHP 8.0 - 8.1: Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. + public false $pseudoTypeFalse; + + /* testPHP8PseudoTypeFalseAndBool */ + // Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. + public bool|FALSE $pseudoTypeFalseAndBool; + + /* testPHP8ObjectAndClass */ + // Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. + public object|ClassName $objectAndClass; + + /* testPHP8PseudoTypeIterableAndArray */ + // Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. + public iterable|array|Traversable $pseudoTypeIterableAndArray; + + /* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ + // Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. + public int |string| /*comment*/ INT $duplicateTypeInUnion; + + /* testPHP81Readonly */ + public readonly int $readonly; + + /* testPHP81ReadonlyWithNullableType */ + public readonly ?array $readonlyWithNullableType; + + /* testPHP81ReadonlyWithUnionType */ + public readonly string|int $readonlyWithUnionType; + + /* testPHP81ReadonlyWithUnionTypeWithNull */ + protected ReadOnly string|null $readonlyWithUnionTypeWithNull; + + /* testPHP81OnlyReadonlyWithUnionType */ + readonly string|int $onlyReadonly; + + /* testPHP81OnlyReadonlyWithUnionTypeMultiple */ + readonly \InterfaceA|\Sub\InterfaceB|false + $onlyReadonly; + + /* testPHP81ReadonlyAndStatic */ + readonly private static ?string $readonlyAndStatic; + + /* testPHP81ReadonlyMixedCase */ + public ReadONLY static $readonlyMixedCase; +}; + +$anon = class { + /* testPHP8PropertySingleAttribute */ + #[PropertyWithAttribute] + public string $foo; + + /* testPHP8PropertyMultipleAttributes */ + #[PropertyWithAttribute(foo: 'bar'), MyAttribute] + protected ?int|float $bar; + + /* testPHP8PropertyMultilineAttribute */ + #[ + PropertyWithAttribute(/* comment */ 'baz') + ] + private mixed $baz; +}; + +enum Suit +{ + /* testEnumProperty */ + protected $anonymous; +} + +enum Direction implements ArrayAccess +{ + case Up; + case Down; + + /* testEnumMethodParamNotProperty */ + public function offsetGet($val) { ... } +} + +$anon = class() { + /* testPHP81IntersectionTypes */ + public Foo&Bar $intersectionType; + + /* testPHP81MoreIntersectionTypes */ + public Foo&Bar&Baz $moreIntersectionTypes; + + /* testPHP81IllegalIntersectionTypes */ + // Intentional fatal error - types which are not allowed for intersection type, but that's not the concern of the method. + public int&string $illegalIntersectionType; + + /* testPHP81NullableIntersectionType */ + // Intentional fatal error - nullability is not allowed with intersection type, but that's not the concern of the method. + public ?Foo&Bar $nullableIntersectionType; +}; + +$anon = class() { + /* testPHP82PseudoTypeTrue */ + public true $pseudoTypeTrue; + + /* testPHP82NullablePseudoTypeTrue */ + static protected ?true $pseudoTypeNullableTrue; + + /* testPHP82PseudoTypeTrueInUnion */ + private int|string|true $pseudoTypeTrueInUnion; + + /* testPHP82PseudoTypeFalseAndTrue */ + // Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method. + readonly true|FALSE $pseudoTypeFalseAndTrue; +}; + +class WhitespaceAndCommentsInTypes { + /* testUnionTypeWithWhitespaceAndComment */ + public int | /*comment*/ string $hasWhitespaceAndComment; + + /* testIntersectionTypeWithWhitespaceAndComment */ + public \Foo /*comment*/ & Bar $hasWhitespaceAndComment; +} + +trait DNFTypes { + /* testPHP82DNFTypeStatic */ + public static (Foo&\Bar)|bool $propA; + + /* testPHP82DNFTypeReadonlyA */ + protected readonly float|(Partially\Qualified&Traversable) $propB; + + /* testPHP82DNFTypeReadonlyB */ + private readonly (namespace\Foo&Bar)|string $propC; + + /* testPHP82DNFTypeIllegalNullable */ + // Intentional fatal error - nullable operator cannot be combined with DNF. + var ?(A&\Pck\B)|bool $propD; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php new file mode 100644 index 000000000..2d5fbe634 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMemberPropertiesTest.php @@ -0,0 +1,1191 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::getMemberProperties method. + * + * @covers \PHP_CodeSniffer\Files\File::getMemberProperties + */ +final class GetMemberPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test the getMemberProperties() method. + * + * @param string $identifier Comment which precedes the test case. + * @param array $expected Expected function output. + * + * @dataProvider dataGetMemberProperties + * + * @return void + */ + public function testGetMemberProperties($identifier, $expected) + { + $variable = $this->getTargetToken($identifier, T_VARIABLE); + $result = self::$phpcsFile->getMemberProperties($variable); + + // Convert offsets to absolute positions in the token stream. + if (isset($expected['type_token']) === true && is_int($expected['type_token']) === true) { + $expected['type_token'] += $variable; + } + + if (isset($expected['type_end_token']) === true && is_int($expected['type_end_token']) === true) { + $expected['type_end_token'] += $variable; + } + + $this->assertSame($expected, $result); + + }//end testGetMemberProperties() + + + /** + * Data provider for the GetMemberProperties test. + * + * Note: the `expected - type_token` and `expected - type_end_token` indexes should + * contain either `false` (no type) or the _offset_ of the type start/end token in + * relation to the `T_VARIABLE` token which is passed to the getMemberProperties() method. + * + * @see testGetMemberProperties() + * + * @return array>> + */ + public static function dataGetMemberProperties() + { + return [ + 'var-modifier' => [ + 'identifier' => '/* testVar */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'var-modifier-and-type' => [ + 'identifier' => '/* testVarType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'public-modifier' => [ + 'identifier' => '/* testPublic */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'public-modifier-and-type' => [ + 'identifier' => '/* testPublicType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'string', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'protected-modifier' => [ + 'identifier' => '/* testProtected */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'protected-modifier-and-type' => [ + 'identifier' => '/* testProtectedType */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'bool', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'private-modifier' => [ + 'identifier' => '/* testPrivate */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'private-modifier-and-type' => [ + 'identifier' => '/* testPrivateType */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'array', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'static-modifier' => [ + 'identifier' => '/* testStatic */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'static-modifier-and-type' => [ + 'identifier' => '/* testStaticType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'static-and-var-modifier' => [ + 'identifier' => '/* testStaticVar */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'var-and-static-modifier' => [ + 'identifier' => '/* testVarStatic */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'public-static-modifiers' => [ + 'identifier' => '/* testPublicStatic */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'protected-static-modifiers' => [ + 'identifier' => '/* testProtectedStatic */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'private-static-modifiers' => [ + 'identifier' => '/* testPrivateStatic */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'no-modifier' => [ + 'identifier' => '/* testNoPrefix */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'public-and-static-modifier-with-docblock' => [ + 'identifier' => '/* testPublicStaticWithDocblock */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'protected-and-static-modifier-with-docblock' => [ + 'identifier' => '/* testProtectedStaticWithDocblock */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'private-and-static-modifier-with-docblock' => [ + 'identifier' => '/* testPrivateStaticWithDocblock */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-simple-type-prop-1' => [ + 'identifier' => '/* testGroupType 1 */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'float', + 'type_token' => -6, + 'type_end_token' => -6, + 'nullable_type' => false, + ], + ], + 'property-group-simple-type-prop-2' => [ + 'identifier' => '/* testGroupType 2 */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'float', + 'type_token' => -13, + 'type_end_token' => -13, + 'nullable_type' => false, + ], + ], + 'property-group-nullable-type-prop-1' => [ + 'identifier' => '/* testGroupNullableType 1 */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'type_token' => -6, + 'type_end_token' => -6, + 'nullable_type' => true, + ], + ], + 'property-group-nullable-type-prop-2' => [ + 'identifier' => '/* testGroupNullableType 2 */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?string', + 'type_token' => -17, + 'type_end_token' => -17, + 'nullable_type' => true, + ], + ], + 'property-group-protected-static-prop-1' => [ + 'identifier' => '/* testGroupProtectedStatic 1 */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-protected-static-prop-2' => [ + 'identifier' => '/* testGroupProtectedStatic 2 */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-protected-static-prop-3' => [ + 'identifier' => '/* testGroupProtectedStatic 3 */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-1' => [ + 'identifier' => '/* testGroupPrivate 1 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-2' => [ + 'identifier' => '/* testGroupPrivate 2 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-3' => [ + 'identifier' => '/* testGroupPrivate 3 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-4' => [ + 'identifier' => '/* testGroupPrivate 4 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-5' => [ + 'identifier' => '/* testGroupPrivate 5 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-6' => [ + 'identifier' => '/* testGroupPrivate 6 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-group-private-prop-7' => [ + 'identifier' => '/* testGroupPrivate 7 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'messy-nullable-type' => [ + 'identifier' => '/* testMessyNullableType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?array', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'fqn-type' => [ + 'identifier' => '/* testNamespaceType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\MyNamespace\MyClass', + 'type_token' => -5, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'nullable-classname-type' => [ + 'identifier' => '/* testNullableNamespaceType 1 */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?ClassName', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'nullable-namespace-relative-class-type' => [ + 'identifier' => '/* testNullableNamespaceType 2 */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?Folder\ClassName', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'multiline-namespaced-type' => [ + 'identifier' => '/* testMultilineNamespaceType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\MyNamespace\MyClass\Foo', + 'type_token' => -18, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'property-after-method' => [ + 'identifier' => '/* testPropertyAfterMethod */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'invalid-property-in-interface' => [ + 'identifier' => '/* testInterfaceProperty */', + 'expected' => [], + ], + 'property-in-nested-class-1' => [ + 'identifier' => '/* testNestedProperty 1 */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'property-in-nested-class-2' => [ + 'identifier' => '/* testNestedProperty 2 */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'php8-mixed-type' => [ + 'identifier' => '/* testPHP8MixedTypeHint */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => 'miXed', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-nullable-mixed-type' => [ + 'identifier' => '/* testPHP8MixedTypeHintNullable */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?mixed', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'namespace-operator-type-declaration' => [ + 'identifier' => '/* testNamespaceOperatorTypeHint */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?namespace\Name', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'php8-union-types-simple' => [ + 'identifier' => '/* testPHP8UnionTypesSimple */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|float', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-two-classes' => [ + 'identifier' => '/* testPHP8UnionTypesTwoClasses */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'MyClassA|\Package\MyClassB', + 'type_token' => -7, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-all-base-types' => [ + 'identifier' => '/* testPHP8UnionTypesAllBaseTypes */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'array|bool|int|float|NULL|object|string', + 'type_token' => -14, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-all-pseudo-types' => [ + 'identifier' => '/* testPHP8UnionTypesAllPseudoTypes */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'false|mixed|self|parent|iterable|Resource', + 'type_token' => -12, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-illegal-types' => [ + 'identifier' => '/* testPHP8UnionTypesIllegalTypes */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + // Missing static, but that's OK as not an allowed syntax. + 'type' => 'callable|void', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-nullable' => [ + 'identifier' => '/* testPHP8UnionTypesNullable */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int|float', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'php8-union-types-pseudo-type-null' => [ + 'identifier' => '/* testPHP8PseudoTypeNull */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'null', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-pseudo-type-false' => [ + 'identifier' => '/* testPHP8PseudoTypeFalse */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'false', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-pseudo-type-false-and-bool' => [ + 'identifier' => '/* testPHP8PseudoTypeFalseAndBool */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'bool|FALSE', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-object-and-class' => [ + 'identifier' => '/* testPHP8ObjectAndClass */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'object|ClassName', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-pseudo-type-iterable-and-array' => [ + 'identifier' => '/* testPHP8PseudoTypeIterableAndArray */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'iterable|array|Traversable', + 'type_token' => -6, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-union-types-duplicate-type-with-whitespace-and-comments' => [ + 'identifier' => '/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|string|INT', + 'type_token' => -10, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-readonly-property' => [ + 'identifier' => '/* testPHP81Readonly */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'int', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-readonly-property-with-nullable-type' => [ + 'identifier' => '/* testPHP81ReadonlyWithNullableType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => '?array', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'php8.1-readonly-property-with-union-type' => [ + 'identifier' => '/* testPHP81ReadonlyWithUnionType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|int', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-readonly-property-with-union-type-with-null' => [ + 'identifier' => '/* testPHP81ReadonlyWithUnionTypeWithNull */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|null', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-readonly-property-with-union-type-no-visibility' => [ + 'identifier' => '/* testPHP81OnlyReadonlyWithUnionType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'string|int', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-readonly-property-with-multi-union-type-no-visibility' => [ + 'identifier' => '/* testPHP81OnlyReadonlyWithUnionTypeMultiple */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => true, + 'type' => '\InterfaceA|\Sub\InterfaceB|false', + 'type_token' => -11, + 'type_end_token' => -3, + 'nullable_type' => false, + ], + ], + 'php8.1-readonly-and-static-property' => [ + 'identifier' => '/* testPHP81ReadonlyAndStatic */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => true, + 'type' => '?string', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'php8.1-readonly-mixed-case-keyword' => [ + 'identifier' => '/* testPHP81ReadonlyMixedCase */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => true, + 'type' => '', + 'type_token' => false, + 'type_end_token' => false, + 'nullable_type' => false, + ], + ], + 'php8-property-with-single-attribute' => [ + 'identifier' => '/* testPHP8PropertySingleAttribute */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'string', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8-property-with-multiple-attributes' => [ + 'identifier' => '/* testPHP8PropertyMultipleAttributes */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?int|float', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'php8-property-with-multiline-attribute' => [ + 'identifier' => '/* testPHP8PropertyMultilineAttribute */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'mixed', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'invalid-property-in-enum' => [ + 'identifier' => '/* testEnumProperty */', + 'expected' => [], + ], + 'php8.1-single-intersection-type' => [ + 'identifier' => '/* testPHP81IntersectionTypes */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'Foo&Bar', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-multi-intersection-type' => [ + 'identifier' => '/* testPHP81MoreIntersectionTypes */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'Foo&Bar&Baz', + 'type_token' => -6, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-illegal-intersection-type' => [ + 'identifier' => '/* testPHP81IllegalIntersectionTypes */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int&string', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-nullable-intersection-type' => [ + 'identifier' => '/* testPHP81NullableIntersectionType */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?Foo&Bar', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + + 'php8.0-union-type-with-whitespace-and-comment' => [ + 'identifier' => '/* testUnionTypeWithWhitespaceAndComment */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|string', + 'type_token' => -8, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.1-intersection-type-with-whitespace-and-comment' => [ + 'identifier' => '/* testIntersectionTypeWithWhitespaceAndComment */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '\Foo&Bar', + 'type_token' => -9, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.2-pseudo-type-true' => [ + 'identifier' => '/* testPHP82PseudoTypeTrue */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'true', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.2-pseudo-type-true-nullable' => [ + 'identifier' => '/* testPHP82NullablePseudoTypeTrue */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '?true', + 'type_token' => -2, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + 'php8.2-pseudo-type-true-in-union' => [ + 'identifier' => '/* testPHP82PseudoTypeTrueInUnion */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => false, + 'type' => 'int|string|true', + 'type_token' => -6, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.2-pseudo-type-invalid-true-false-union' => [ + 'identifier' => '/* testPHP82PseudoTypeFalseAndTrue */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'true|FALSE', + 'type_token' => -4, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + + 'php8.2-dnf-with-static' => [ + 'identifier' => '/* testPHP82DNFTypeStatic */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => true, + 'is_static' => true, + 'is_readonly' => false, + 'type' => '(Foo&\Bar)|bool', + 'type_token' => -9, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.2-dnf-with-readonly-1' => [ + 'identifier' => '/* testPHP82DNFTypeReadonlyA */', + 'expected' => [ + 'scope' => 'protected', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => 'float|(Partially\Qualified&Traversable)', + 'type_token' => -10, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.2-dnf-with-readonly-2' => [ + 'identifier' => '/* testPHP82DNFTypeReadonlyB */', + 'expected' => [ + 'scope' => 'private', + 'scope_specified' => true, + 'is_static' => false, + 'is_readonly' => true, + 'type' => '(namespace\Foo&Bar)|string', + 'type_token' => -10, + 'type_end_token' => -2, + 'nullable_type' => false, + ], + ], + 'php8.2-dnf-with-illegal-nullable' => [ + 'identifier' => '/* testPHP82DNFTypeIllegalNullable */', + 'expected' => [ + 'scope' => 'public', + 'scope_specified' => false, + 'is_static' => false, + 'is_readonly' => false, + 'type' => '?(A&\Pck\B)|bool', + 'type_token' => -11, + 'type_end_token' => -2, + 'nullable_type' => true, + ], + ], + ]; + + }//end dataGetMemberProperties() + + + /** + * Test receiving an expected exception when a non property is passed. + * + * @param string $identifier Comment which precedes the test case. + * + * @dataProvider dataNotClassProperty + * + * @return void + */ + public function testNotClassPropertyException($identifier) + { + $this->expectRunTimeException('$stackPtr is not a class member var'); + + $variable = $this->getTargetToken($identifier, T_VARIABLE); + self::$phpcsFile->getMemberProperties($variable); + + }//end testNotClassPropertyException() + + + /** + * Data provider for the NotClassPropertyException test. + * + * @see testNotClassPropertyException() + * + * @return array> + */ + public static function dataNotClassProperty() + { + return [ + 'method parameter' => ['/* testMethodParam */'], + 'variable import using global keyword' => ['/* testImportedGlobal */'], + 'function local variable' => ['/* testLocalVariable */'], + 'global variable' => ['/* testGlobalVariable */'], + 'method parameter in anon class nested in ternary' => ['/* testNestedMethodParam 1 */'], + 'method parameter in anon class nested in function call' => ['/* testNestedMethodParam 2 */'], + 'method parameter in enum' => ['/* testEnumMethodParamNotProperty */'], + ]; + + }//end dataNotClassProperty() + + + /** + * Test receiving an expected exception when a non variable is passed. + * + * @return void + */ + public function testNotAVariableException() + { + $this->expectRunTimeException('$stackPtr must be of type T_VARIABLE'); + + $next = $this->getTargetToken('/* testNotAVariable */', T_RETURN); + self::$phpcsFile->getMemberProperties($next); + + }//end testNotAVariableException() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError1Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError1Test.inc new file mode 100644 index 000000000..465679eb3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError1Test.inc @@ -0,0 +1,4 @@ + + * @copyright 2019-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::getMethodParameters method. + * + * @covers \PHP_CodeSniffer\Files\File::getMethodParameters + */ +final class GetMethodParametersParseError1Test extends AbstractMethodUnitTest +{ + + + /** + * Test receiving an empty array when encountering a specific parse error. + * + * @return void + */ + public function testParseError() + { + $target = $this->getTargetToken('/* testParseError */', [T_FUNCTION, T_CLOSURE, T_FN]); + $result = self::$phpcsFile->getMethodParameters($target); + + $this->assertSame([], $result); + + }//end testParseError() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError2Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError2Test.inc new file mode 100644 index 000000000..667cb5ed2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersParseError2Test.inc @@ -0,0 +1,4 @@ + + * @copyright 2019-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::getMethodParameters method. + * + * @covers \PHP_CodeSniffer\Files\File::getMethodParameters + */ +final class GetMethodParametersParseError2Test extends AbstractMethodUnitTest +{ + + + /** + * Test receiving an empty array when encountering a specific parse error. + * + * @return void + */ + public function testParseError() + { + $target = $this->getTargetToken('/* testParseError */', [T_FUNCTION, T_CLOSURE, T_FN]); + $result = self::$phpcsFile->getMethodParameters($target); + + $this->assertSame([], $result); + + }//end testParseError() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc new file mode 100644 index 000000000..1f72ccfaa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.inc @@ -0,0 +1,338 @@ + $b; + +/* testArrowFunctionReturnByRef */ +fn&(?string $a) => $b; + +/* testArrayDefaultValues */ +function arrayDefaultValues($var1 = [], $var2 = array(1, 2, 3) ) {} + +/* testConstantDefaultValueSecondParam */ +function constantDefaultValueSecondParam($var1, $var2 = M_PI) {} + +/* testScalarTernaryExpressionInDefault */ +function ternayInDefault( $a = FOO ? 'bar' : 10, ? bool $b ) {} + +/* testVariadicFunction */ +function variadicFunction( int ... $a ) {} + +/* testVariadicByRefFunction */ +function variadicByRefFunction( &...$a ) {} + +/* testVariadicFunctionClassType */ +function variableLengthArgument($unit, DateInterval ...$intervals) {} + +/* testNameSpacedTypeDeclaration */ +function namespacedClassType( \Package\Sub\ClassName $a, ?Sub\AnotherClass $b ) {} + +/* testWithAllTypes */ +class testAllTypes { + function allTypes( + ?ClassName $a, + self $b, + parent $c, + object $d, + ?int $e, + string &$f, + iterable $g, + bool $h = true, + callable $i = 'is_null', + float $j = 1.1, + array ...$k + ) {} +} + +/* testArrowFunctionWithAllTypes */ +$fn = fn( + ?ClassName $a, + self $b, + parent $c, + object $d, + ?int $e, + string &$f, + iterable $g, + bool $h = true, + callable $i = 'is_null', + float $j = 1.1, + array ...$k +) => $something; + +/* testMessyDeclaration */ +function messyDeclaration( + // comment + ?\MyNS /* comment */ + \ SubCat // phpcs:ignore Standard.Cat.Sniff -- for reasons. + \ MyClass $a, + $b /* test */ = /* test */ 'default' /* test*/, + // phpcs:ignore Stnd.Cat.Sniff -- For reasons. + ? /*comment*/ + bool // phpcs:disable Stnd.Cat.Sniff -- For reasons. + & /*test*/ ... /* phpcs:ignore */ $c +) {} + +/* testPHP8MixedTypeHint */ +function mixedTypeHint(mixed &...$var1) {} + +/* testPHP8MixedTypeHintNullable */ +// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. +function mixedTypeHintNullable(?Mixed $var1) {} + +/* testNamespaceOperatorTypeHint */ +function namespaceOperatorTypeHint(?namespace\Name $var1) {} + +/* testPHP8UnionTypesSimple */ +function unionTypeSimple(int|float $number, self|parent &...$obj) {} + +/* testPHP8UnionTypesWithSpreadOperatorAndReference */ +function globalFunctionWithSpreadAndReference(float|null &$paramA, string|int ...$paramB ) {} + +/* testPHP8UnionTypesSimpleWithBitwiseOrInDefault */ +$fn = fn(int|float $var = CONSTANT_A | CONSTANT_B) => $var; + +/* testPHP8UnionTypesTwoClasses */ +function unionTypesTwoClasses(MyClassA|\Package\MyClassB $var) {} + +/* testPHP8UnionTypesAllBaseTypes */ +function unionTypesAllBaseTypes(array|bool|callable|int|float|null|object|string $var) {} + +/* testPHP8UnionTypesAllPseudoTypes */ +// Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. +function unionTypesAllPseudoTypes(false|mixed|self|parent|iterable|Resource $var) {} + +/* testPHP8UnionTypesNullable */ +// Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. +$closure = function (?int|float $number) {}; + +/* testPHP8PseudoTypeNull */ +// PHP 8.0 - 8.1: Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeNull(null $var = null) {} + +/* testPHP8PseudoTypeFalse */ +// PHP 8.0 - 8.1: Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeFalse(false $var = false) {} + +/* testPHP8PseudoTypeFalseAndBool */ +// Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. +function pseudoTypeFalseAndBool(bool|false $var = false) {} + +/* testPHP8ObjectAndClass */ +// Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. +function objectAndClass(object|ClassName $var) {} + +/* testPHP8PseudoTypeIterableAndArray */ +// Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. +function pseudoTypeIterableAndArray(iterable|array|Traversable $var) {} + +/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ +// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. +function duplicateTypeInUnion( int | string /*comment*/ | INT $var) {} + +class ConstructorPropertyPromotionNoTypes { + /* testPHP8ConstructorPropertyPromotionNoTypes */ + public function __construct( + public $x = 0.0, + protected $y = '', + private $z = null, + ) {} +} + +class ConstructorPropertyPromotionWithTypes { + /* testPHP8ConstructorPropertyPromotionWithTypes */ + public function __construct(protected float|int $x, public ?string &$y = 'test', private mixed $z) {} +} + +class ConstructorPropertyPromotionAndNormalParams { + /* testPHP8ConstructorPropertyPromotionAndNormalParam */ + public function __construct(public int $promotedProp, ?int $normalArg) {} +} + +class ConstructorPropertyPromotionWithReadOnly { + /* testPHP81ConstructorPropertyPromotionWithReadOnly */ + public function __construct(public readonly ?int $promotedProp, ReadOnly private string|bool &$promotedToo) {} +} + +class ConstructorPropertyPromotionWithReadOnlyNoTypeDeclaration { + /* testPHP81ConstructorPropertyPromotionWithReadOnlyNoTypeDeclaration */ + // Intentional fatal error. Readonly properties MUST be typed. + public function __construct(public readonly $promotedProp, ReadOnly private &$promotedToo) {} +} + +class ConstructorPropertyPromotionWithOnlyReadOnly { + /* testPHP81ConstructorPropertyPromotionWithOnlyReadOnly */ + public function __construct(readonly Foo&Bar $promotedProp, readonly ?bool $promotedToo,) {} +} + +/* testPHP8ConstructorPropertyPromotionGlobalFunction */ +// Intentional fatal error. Property promotion not allowed in non-constructor, but that's not the concern of this method. +function globalFunction(private $x) {} + +abstract class ConstructorPropertyPromotionAbstractMethod { + /* testPHP8ConstructorPropertyPromotionAbstractMethod */ + // Intentional fatal error. + // 1. Property promotion not allowed in abstract method, but that's not the concern of this method. + // 2. Variadic arguments not allowed in property promotion, but that's not the concern of this method. + // 3. The callable type is not supported for properties, but that's not the concern of this method. + abstract public function __construct(public callable $y, private ...$x); +} + +/* testCommentsInParameter */ +function commentsInParams( + // Leading comment. + ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ 'default value' . /*-*/ 'second part' // Trailing comment. +) {} + +/* testParameterAttributesInFunctionDeclaration */ +class ParametersWithAttributes( + public function __construct( + #[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute, + #[MyAttr([1, 2])] + Type|false + $typedParamSingleAttribute, + #[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute, + #[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes, + #[MyAttribute(array("key" => "value"))] + &...$otherParam, + ) {} +} + +/* testPHP8IntersectionTypes */ +function intersectionTypes(Foo&Bar $obj1, Boo&Bar $obj2) {} + +/* testPHP81IntersectionTypesWithSpreadOperatorAndReference */ +function globalFunctionWithSpreadAndReference(Boo&Bar &$paramA, Foo&Bar ...$paramB) {} + +/* testPHP81MoreIntersectionTypes */ +function moreIntersectionTypes(MyClassA&\Package\MyClassB&\Package\MyClassC $var) {} + +/* testPHP81IllegalIntersectionTypes */ +// Intentional fatal error - simple types are not allowed with intersection types, but that's not the concern of the method. +$closure = function (string&int $numeric_string) {}; + +/* testPHP81NullableIntersectionTypes */ +// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method. +$closure = function (?Foo&Bar $object) {}; + +/* testPHP82PseudoTypeTrue */ +function pseudoTypeTrue(?true $var = true) {} + +/* testPHP82PseudoTypeFalseAndTrue */ +// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method. +function pseudoTypeFalseAndTrue(true|false $var = true) {} + +/* testPHP81NewInInitializers */ +function newInInitializers( + TypeA $new = new TypeA(self::CONST_VALUE), + \Package\TypeB $newToo = new \Package\TypeB(10, 'string'), +) {} + +/* testPHP82DNFTypes */ +function dnfTypes( + #[MyAttribute] + false|(Foo&Bar)|true $obj1, + (\Boo&\Pck\Bar)|(Boo&Baz) $obj2 = new Boo() +) {} + +/* testPHP82DNFTypesWithSpreadOperatorAndReference */ +function dnfInGlobalFunctionWithSpreadAndReference((Countable&MeMe)|iterable &$paramA, true|(Foo&Bar) ...$paramB) {} + +/* testPHP82DNFTypesIllegalNullable */ +// Intentional fatal error - nullable operator cannot be combined with DNF. +$dnf_closure = function (? ( MyClassA & /*comment*/ \Package\MyClassB & \Package\MyClassC ) $var): void {}; + +/* testPHP82DNFTypesInArrow */ +$dnf_arrow = fn((Hi&Ho)|FALSE &...$range): string => $a; + +/* testFunctionCallFnPHPCS353-354 */ +$value = $obj->fn(true); + +/* testClosureNoParams */ +function() {}; + +/* testClosure */ +function( $a = 'test' ) {}; + +/* testClosureUseNoParams */ +function() use() {}; + +/* testClosureUse */ +function() use( $foo, $bar ) {}; + +/* testFunctionParamListWithTrailingComma */ +function trailingComma( + ?string $foo /*comment*/ , + $bar = 0, +) {} + +/* testClosureParamListWithTrailingComma */ +function( + $foo, + $bar, +) {}; + +/* testArrowFunctionParamListWithTrailingComma */ +$fn = fn( ?int $a , ...$b, ) => $b; + +/* testClosureUseWithTrailingComma */ +function() use( + $foo /*comment*/ , + $bar, +) {}; + +/* testArrowFunctionLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$fn = fn diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php new file mode 100644 index 000000000..f8e7b22e2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php @@ -0,0 +1,3182 @@ + + * @author Juliette Reinders Folmer + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @copyright 2019-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::getMethodParameters method. + * + * @covers \PHP_CodeSniffer\Files\File::getMethodParameters + */ +final class GetMethodParametersTest extends AbstractMethodUnitTest +{ + + + /** + * Test receiving an expected exception when a non function/use token is passed. + * + * @param string $commentString The comment which preceeds the test. + * @param int|string|array $targetTokenType The token type to search for after $commentString. + * + * @dataProvider dataUnexpectedTokenException + * + * @return void + */ + public function testUnexpectedTokenException($commentString, $targetTokenType) + { + $this->expectRunTimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_USE or T_FN'); + + $target = $this->getTargetToken($commentString, $targetTokenType); + self::$phpcsFile->getMethodParameters($target); + + }//end testUnexpectedTokenException() + + + /** + * Data Provider. + * + * @see testUnexpectedTokenException() For the array format. + * + * @return array>> + */ + public static function dataUnexpectedTokenException() + { + return [ + 'interface' => [ + 'commentString' => '/* testNotAFunction */', + 'targetTokenType' => T_INTERFACE, + ], + 'function-call-fn-phpcs-3.5.3-3.5.4' => [ + 'commentString' => '/* testFunctionCallFnPHPCS353-354 */', + 'targetTokenType' => [ + T_FN, + T_STRING, + ], + ], + 'fn-live-coding' => [ + 'commentString' => '/* testArrowFunctionLiveCoding */', + 'targetTokenType' => [ + T_FN, + T_STRING, + ], + ], + ]; + + }//end dataUnexpectedTokenException() + + + /** + * Test receiving an expected exception when a non-closure use token is passed. + * + * @param string $identifier The comment which preceeds the test. + * + * @dataProvider dataInvalidUse + * + * @return void + */ + public function testInvalidUse($identifier) + { + $this->expectRunTimeException('$stackPtr was not a valid T_USE'); + + $use = $this->getTargetToken($identifier, [T_USE]); + self::$phpcsFile->getMethodParameters($use); + + }//end testInvalidUse() + + + /** + * Data Provider. + * + * @see testInvalidUse() For the array format. + * + * @return array> + */ + public static function dataInvalidUse() + { + return [ + 'ImportUse' => ['/* testImportUse */'], + 'ImportGroupUse' => ['/* testImportGroupUse */'], + 'TraitUse' => ['/* testTraitUse */'], + ]; + + }//end dataInvalidUse() + + + /** + * Test receiving an empty array when there are no parameters. + * + * @param string $commentString The comment which preceeds the test. + * @param int|string|array $targetTokenType Optional. The token type to search for after $commentString. + * Defaults to the function/closure/arrow tokens. + * + * @dataProvider dataNoParams + * + * @return void + */ + public function testNoParams($commentString, $targetTokenType=[T_FUNCTION, T_CLOSURE, T_FN]) + { + $target = $this->getTargetToken($commentString, $targetTokenType); + $result = self::$phpcsFile->getMethodParameters($target); + + $this->assertSame([], $result); + + }//end testNoParams() + + + /** + * Data Provider. + * + * @see testNoParams() For the array format. + * + * @return array>> + */ + public static function dataNoParams() + { + return [ + 'FunctionNoParams' => [ + 'commentString' => '/* testFunctionNoParams */', + ], + 'ClosureNoParams' => [ + 'commentString' => '/* testClosureNoParams */', + ], + 'ClosureUseNoParams' => [ + 'commentString' => '/* testClosureUseNoParams */', + 'targetTokenType' => T_USE, + ], + ]; + + }//end dataNoParams() + + + /** + * Verify pass-by-reference parsing. + * + * @return void + */ + public function testPassByReference() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 5, + 'name' => '$var', + 'content' => '&$var', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 4, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPassByReference() + + + /** + * Verify array hint parsing. + * + * @return void + */ + public function testArrayHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$var', + 'content' => 'array $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'array', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrayHint() + + + /** + * Verify variable. + * + * @return void + */ + public function testVariable() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$var', + 'content' => '$var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testVariable() + + + /** + * Verify default value parsing with a single function param. + * + * @return void + */ + public function testSingleDefaultValue() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$var1', + 'content' => '$var1=self::CONSTANT', + 'default' => 'self::CONSTANT', + 'default_token' => 6, + 'default_equal_token' => 5, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testSingleDefaultValue() + + + /** + * Verify default value parsing. + * + * @return void + */ + public function testDefaultValues() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$var1', + 'content' => '$var1=1', + 'default' => '1', + 'default_token' => 6, + 'default_equal_token' => 5, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 7, + ]; + $expected[1] = [ + 'token' => 9, + 'name' => '$var2', + 'content' => "\$var2='value'", + 'default' => "'value'", + 'default_token' => 11, + 'default_equal_token' => 10, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testDefaultValues() + + + /** + * Verify type hint parsing. + * + * @return void + */ + public function testTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$var1', + 'content' => 'foo $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'foo', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => 7, + ]; + + $expected[1] = [ + 'token' => 11, + 'name' => '$var2', + 'content' => 'bar $var2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'bar', + 'type_hint_token' => 9, + 'type_hint_end_token' => 9, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testTypeHint() + + + /** + * Verify self type hint parsing. + * + * @return void + */ + public function testSelfTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$var', + 'content' => 'self $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'self', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testSelfTypeHint() + + + /** + * Verify nullable type hint parsing. + * + * @return void + */ + public function testNullableTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 7, + 'name' => '$var1', + 'content' => '?int $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 5, + 'type_hint_end_token' => 5, + 'nullable_type' => true, + 'comma_token' => 8, + ]; + + $expected[1] = [ + 'token' => 14, + 'name' => '$var2', + 'content' => '?\bar $var2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?\bar', + 'type_hint_token' => 11, + 'type_hint_end_token' => 12, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNullableTypeHint() + + + /** + * Verify "bitwise and" in default value !== pass-by-reference. + * + * @return void + */ + public function testBitwiseAndConstantExpressionDefaultValue() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$a', + 'content' => '$a = 10 & 20', + 'default' => '10 & 20', + 'default_token' => 8, + 'default_equal_token' => 6, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBitwiseAndConstantExpressionDefaultValue() + + + /** + * Verify that arrow functions are supported. + * + * @return void + */ + public function testArrowFunction() + { + // Offsets are relative to the T_FN token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$a', + 'content' => 'int $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'int', + 'type_hint_token' => 2, + 'type_hint_end_token' => 2, + 'nullable_type' => false, + 'comma_token' => 5, + ]; + + $expected[1] = [ + 'token' => 8, + 'name' => '$b', + 'content' => '...$b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 7, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunction() + + + /** + * Verify that arrow functions are supported. + * + * @return void + */ + public function testArrowFunctionReturnByRef() + { + // Offsets are relative to the T_FN token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$a', + 'content' => '?string $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?string', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunctionReturnByRef() + + + /** + * Verify default value parsing with array values. + * + * @return void + */ + public function testArrayDefaultValues() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$var1', + 'content' => '$var1 = []', + 'default' => '[]', + 'default_token' => 8, + 'default_equal_token' => 6, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 10, + ]; + $expected[1] = [ + 'token' => 12, + 'name' => '$var2', + 'content' => '$var2 = array(1, 2, 3)', + 'default' => 'array(1, 2, 3)', + 'default_token' => 16, + 'default_equal_token' => 14, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrayDefaultValues() + + + /** + * Verify having a T_STRING constant as a default value for the second parameter. + * + * @return void + */ + public function testConstantDefaultValueSecondParam() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$var1', + 'content' => '$var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 5, + ]; + $expected[1] = [ + 'token' => 7, + 'name' => '$var2', + 'content' => '$var2 = M_PI', + 'default' => 'M_PI', + 'default_token' => 11, + 'default_equal_token' => 9, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testConstantDefaultValueSecondParam() + + + /** + * Verify distinquishing between a nullable type and a ternary within a default expression. + * + * @return void + */ + public function testScalarTernaryExpressionInDefault() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 5, + 'name' => '$a', + 'content' => '$a = FOO ? \'bar\' : 10', + 'default' => 'FOO ? \'bar\' : 10', + 'default_token' => 9, + 'default_equal_token' => 7, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 18, + ]; + $expected[1] = [ + 'token' => 24, + 'name' => '$b', + 'content' => '? bool $b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?bool', + 'type_hint_token' => 22, + 'type_hint_end_token' => 22, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testScalarTernaryExpressionInDefault() + + + /** + * Verify a variadic parameter being recognized correctly. + * + * @return void + */ + public function testVariadicFunction() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 9, + 'name' => '$a', + 'content' => 'int ... $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 7, + 'type_hint' => 'int', + 'type_hint_token' => 5, + 'type_hint_end_token' => 5, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testVariadicFunction() + + + /** + * Verify a variadic parameter passed by reference being recognized correctly. + * + * @return void + */ + public function testVariadicByRefFunction() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 7, + 'name' => '$a', + 'content' => '&...$a', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 5, + 'variable_length' => true, + 'variadic_token' => 6, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testVariadicByRefFunction() + + + /** + * Verify handling of a variadic parameter with a class based type declaration. + * + * @return void + */ + public function testVariadicFunctionClassType() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$unit', + 'content' => '$unit', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 5, + ]; + $expected[1] = [ + 'token' => 10, + 'name' => '$intervals', + 'content' => 'DateInterval ...$intervals', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 9, + 'type_hint' => 'DateInterval', + 'type_hint_token' => 7, + 'type_hint_end_token' => 7, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testVariadicFunctionClassType() + + + /** + * Verify distinquishing between a nullable type and a ternary within a default expression. + * + * @return void + */ + public function testNameSpacedTypeDeclaration() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 12, + 'name' => '$a', + 'content' => '\Package\Sub\ClassName $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '\Package\Sub\ClassName', + 'type_hint_token' => 5, + 'type_hint_end_token' => 10, + 'nullable_type' => false, + 'comma_token' => 13, + ]; + $expected[1] = [ + 'token' => 20, + 'name' => '$b', + 'content' => '?Sub\AnotherClass $b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?Sub\AnotherClass', + 'type_hint_token' => 16, + 'type_hint_end_token' => 18, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNameSpacedTypeDeclaration() + + + /** + * Verify correctly recognizing all type declarations supported by PHP. + * + * @return void + */ + public function testWithAllTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 9, + 'name' => '$a', + 'content' => '?ClassName $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?ClassName', + 'type_hint_token' => 7, + 'type_hint_end_token' => 7, + 'nullable_type' => true, + 'comma_token' => 10, + ]; + $expected[1] = [ + 'token' => 15, + 'name' => '$b', + 'content' => 'self $b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'self', + 'type_hint_token' => 13, + 'type_hint_end_token' => 13, + 'nullable_type' => false, + 'comma_token' => 16, + ]; + $expected[2] = [ + 'token' => 21, + 'name' => '$c', + 'content' => 'parent $c', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'parent', + 'type_hint_token' => 19, + 'type_hint_end_token' => 19, + 'nullable_type' => false, + 'comma_token' => 22, + ]; + $expected[3] = [ + 'token' => 27, + 'name' => '$d', + 'content' => 'object $d', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'object', + 'type_hint_token' => 25, + 'type_hint_end_token' => 25, + 'nullable_type' => false, + 'comma_token' => 28, + ]; + $expected[4] = [ + 'token' => 34, + 'name' => '$e', + 'content' => '?int $e', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 32, + 'type_hint_end_token' => 32, + 'nullable_type' => true, + 'comma_token' => 35, + ]; + $expected[5] = [ + 'token' => 41, + 'name' => '$f', + 'content' => 'string &$f', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 40, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'string', + 'type_hint_token' => 38, + 'type_hint_end_token' => 38, + 'nullable_type' => false, + 'comma_token' => 42, + ]; + $expected[6] = [ + 'token' => 47, + 'name' => '$g', + 'content' => 'iterable $g', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'iterable', + 'type_hint_token' => 45, + 'type_hint_end_token' => 45, + 'nullable_type' => false, + 'comma_token' => 48, + ]; + $expected[7] = [ + 'token' => 53, + 'name' => '$h', + 'content' => 'bool $h = true', + 'default' => 'true', + 'default_token' => 57, + 'default_equal_token' => 55, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'bool', + 'type_hint_token' => 51, + 'type_hint_end_token' => 51, + 'nullable_type' => false, + 'comma_token' => 58, + ]; + $expected[8] = [ + 'token' => 63, + 'name' => '$i', + 'content' => 'callable $i = \'is_null\'', + 'default' => "'is_null'", + 'default_token' => 67, + 'default_equal_token' => 65, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'callable', + 'type_hint_token' => 61, + 'type_hint_end_token' => 61, + 'nullable_type' => false, + 'comma_token' => 68, + ]; + $expected[9] = [ + 'token' => 73, + 'name' => '$j', + 'content' => 'float $j = 1.1', + 'default' => '1.1', + 'default_token' => 77, + 'default_equal_token' => 75, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'float', + 'type_hint_token' => 71, + 'type_hint_end_token' => 71, + 'nullable_type' => false, + 'comma_token' => 78, + ]; + $expected[10] = [ + 'token' => 84, + 'name' => '$k', + 'content' => 'array ...$k', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 83, + 'type_hint' => 'array', + 'type_hint_token' => 81, + 'type_hint_end_token' => 81, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testWithAllTypes() + + + /** + * Verify correctly recognizing all type declarations supported by PHP when used with an arrow function. + * + * @return void + */ + public function testArrowFunctionWithAllTypes() + { + // Offsets are relative to the T_FN token. + $expected = []; + $expected[0] = [ + 'token' => 7, + 'name' => '$a', + 'content' => '?ClassName $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?ClassName', + 'type_hint_token' => 5, + 'type_hint_end_token' => 5, + 'nullable_type' => true, + 'comma_token' => 8, + ]; + $expected[1] = [ + 'token' => 13, + 'name' => '$b', + 'content' => 'self $b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'self', + 'type_hint_token' => 11, + 'type_hint_end_token' => 11, + 'nullable_type' => false, + 'comma_token' => 14, + ]; + $expected[2] = [ + 'token' => 19, + 'name' => '$c', + 'content' => 'parent $c', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'parent', + 'type_hint_token' => 17, + 'type_hint_end_token' => 17, + 'nullable_type' => false, + 'comma_token' => 20, + ]; + $expected[3] = [ + 'token' => 25, + 'name' => '$d', + 'content' => 'object $d', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'object', + 'type_hint_token' => 23, + 'type_hint_end_token' => 23, + 'nullable_type' => false, + 'comma_token' => 26, + ]; + $expected[4] = [ + 'token' => 32, + 'name' => '$e', + 'content' => '?int $e', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 30, + 'type_hint_end_token' => 30, + 'nullable_type' => true, + 'comma_token' => 33, + ]; + $expected[5] = [ + 'token' => 39, + 'name' => '$f', + 'content' => 'string &$f', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 38, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'string', + 'type_hint_token' => 36, + 'type_hint_end_token' => 36, + 'nullable_type' => false, + 'comma_token' => 40, + ]; + $expected[6] = [ + 'token' => 45, + 'name' => '$g', + 'content' => 'iterable $g', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'iterable', + 'type_hint_token' => 43, + 'type_hint_end_token' => 43, + 'nullable_type' => false, + 'comma_token' => 46, + ]; + $expected[7] = [ + 'token' => 51, + 'name' => '$h', + 'content' => 'bool $h = true', + 'default' => 'true', + 'default_token' => 55, + 'default_equal_token' => 53, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'bool', + 'type_hint_token' => 49, + 'type_hint_end_token' => 49, + 'nullable_type' => false, + 'comma_token' => 56, + ]; + $expected[8] = [ + 'token' => 61, + 'name' => '$i', + 'content' => 'callable $i = \'is_null\'', + 'default' => "'is_null'", + 'default_token' => 65, + 'default_equal_token' => 63, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'callable', + 'type_hint_token' => 59, + 'type_hint_end_token' => 59, + 'nullable_type' => false, + 'comma_token' => 66, + ]; + $expected[9] = [ + 'token' => 71, + 'name' => '$j', + 'content' => 'float $j = 1.1', + 'default' => '1.1', + 'default_token' => 75, + 'default_equal_token' => 73, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'float', + 'type_hint_token' => 69, + 'type_hint_end_token' => 69, + 'nullable_type' => false, + 'comma_token' => 76, + ]; + $expected[10] = [ + 'token' => 82, + 'name' => '$k', + 'content' => 'array ...$k', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 81, + 'type_hint' => 'array', + 'type_hint_token' => 79, + 'type_hint_end_token' => 79, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunctionWithAllTypes() + + + /** + * Verify handling of a declaration interlaced with whitespace and comments. + * + * @return void + */ + public function testMessyDeclaration() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 25, + 'name' => '$a', + 'content' => '// comment + ?\MyNS /* comment */ + \ SubCat // phpcs:ignore Standard.Cat.Sniff -- for reasons. + \ MyClass $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?\MyNS\SubCat\MyClass', + 'type_hint_token' => 9, + 'type_hint_end_token' => 23, + 'nullable_type' => true, + 'comma_token' => 26, + ]; + $expected[1] = [ + 'token' => 29, + 'name' => '$b', + 'content' => "\$b /* test */ = /* test */ 'default' /* test*/", + 'default' => "'default' /* test*/", + 'default_token' => 37, + 'default_equal_token' => 33, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 40, + ]; + $expected[2] = [ + 'token' => 62, + 'name' => '$c', + 'content' => '// phpcs:ignore Stnd.Cat.Sniff -- For reasons. + ? /*comment*/ + bool // phpcs:disable Stnd.Cat.Sniff -- For reasons. + & /*test*/ ... /* phpcs:ignore */ $c', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 54, + 'variable_length' => true, + 'variadic_token' => 58, + 'type_hint' => '?bool', + 'type_hint_token' => 50, + 'type_hint_end_token' => 50, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testMessyDeclaration() + + + /** + * Verify recognition of PHP8 mixed type declaration. + * + * @return void + */ + public function testPHP8MixedTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$var1', + 'content' => 'mixed &...$var1', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 6, + 'variable_length' => true, + 'variadic_token' => 7, + 'type_hint' => 'mixed', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHint() + + + /** + * Verify recognition of PHP8 mixed type declaration with nullability. + * + * @return void + */ + public function testPHP8MixedTypeHintNullable() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 7, + 'name' => '$var1', + 'content' => '?Mixed $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?Mixed', + 'type_hint_token' => 5, + 'type_hint_end_token' => 5, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHintNullable() + + + /** + * Verify recognition of type declarations using the namespace operator. + * + * @return void + */ + public function testNamespaceOperatorTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 9, + 'name' => '$var1', + 'content' => '?namespace\Name $var1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?namespace\Name', + 'type_hint_token' => 5, + 'type_hint_end_token' => 7, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNamespaceOperatorTypeHint() + + + /** + * Verify recognition of PHP8 union type declaration. + * + * @return void + */ + public function testPHP8UnionTypesSimple() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$number', + 'content' => 'int|float $number', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'int|float', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => 9, + ]; + $expected[1] = [ + 'token' => 17, + 'name' => '$obj', + 'content' => 'self|parent &...$obj', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 15, + 'variable_length' => true, + 'variadic_token' => 16, + 'type_hint' => 'self|parent', + 'type_hint_token' => 11, + 'type_hint_end_token' => 13, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimple() + + + /** + * Verify recognition of PHP8 union type declaration when the variable has either a spread operator or a reference. + * + * @return void + */ + public function testPHP8UnionTypesWithSpreadOperatorAndReference() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 9, + 'name' => '$paramA', + 'content' => 'float|null &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 8, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'float|null', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => 10, + ]; + $expected[1] = [ + 'token' => 17, + 'name' => '$paramB', + 'content' => 'string|int ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 16, + 'type_hint' => 'string|int', + 'type_hint_token' => 12, + 'type_hint_end_token' => 14, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP8 union type declaration with a bitwise or in the default value. + * + * @return void + */ + public function testPHP8UnionTypesSimpleWithBitwiseOrInDefault() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$var', + 'content' => 'int|float $var = CONSTANT_A | CONSTANT_B', + 'default' => 'CONSTANT_A | CONSTANT_B', + 'default_token' => 10, + 'default_equal_token' => 8, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'int|float', + 'type_hint_token' => 2, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimpleWithBitwiseOrInDefault() + + + /** + * Verify recognition of PHP8 union type declaration with two classes. + * + * @return void + */ + public function testPHP8UnionTypesTwoClasses() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 11, + 'name' => '$var', + 'content' => 'MyClassA|\Package\MyClassB $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'MyClassA|\Package\MyClassB', + 'type_hint_token' => 4, + 'type_hint_end_token' => 9, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesTwoClasses() + + + /** + * Verify recognition of PHP8 union type declaration with all base types. + * + * @return void + */ + public function testPHP8UnionTypesAllBaseTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 20, + 'name' => '$var', + 'content' => 'array|bool|callable|int|float|null|object|string $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'array|bool|callable|int|float|null|object|string', + 'type_hint_token' => 4, + 'type_hint_end_token' => 18, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllBaseTypes() + + + /** + * Verify recognition of PHP8 union type declaration with all pseudo types. + * + * Note: "Resource" is not a type, but seen as a class name. + * + * @return void + */ + public function testPHP8UnionTypesAllPseudoTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 16, + 'name' => '$var', + 'content' => 'false|mixed|self|parent|iterable|Resource $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'false|mixed|self|parent|iterable|Resource', + 'type_hint_token' => 4, + 'type_hint_end_token' => 14, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllPseudoTypes() + + + /** + * Verify recognition of PHP8 union type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP8UnionTypesNullable() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$number', + 'content' => '?int|float $number', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int|float', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesNullable() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type null. + * + * @return void + */ + public function testPHP8PseudoTypeNull() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$var', + 'content' => 'null $var = null', + 'default' => 'null', + 'default_token' => 10, + 'default_equal_token' => 8, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'null', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeNull() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type false. + * + * @return void + */ + public function testPHP8PseudoTypeFalse() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$var', + 'content' => 'false $var = false', + 'default' => 'false', + 'default_token' => 10, + 'default_equal_token' => 8, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'false', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalse() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. + * + * @return void + */ + public function testPHP8PseudoTypeFalseAndBool() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$var', + 'content' => 'bool|false $var = false', + 'default' => 'false', + 'default_token' => 12, + 'default_equal_token' => 10, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'bool|false', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalseAndBool() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. + * + * @return void + */ + public function testPHP8ObjectAndClass() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$var', + 'content' => 'object|ClassName $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'object|ClassName', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ObjectAndClass() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. + * + * @return void + */ + public function testPHP8PseudoTypeIterableAndArray() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 10, + 'name' => '$var', + 'content' => 'iterable|array|Traversable $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'iterable|array|Traversable', + 'type_hint_token' => 4, + 'type_hint_end_token' => 8, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeIterableAndArray() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) duplicate types. + * + * @return void + */ + public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 17, + 'name' => '$var', + 'content' => 'int | string /*comment*/ | INT $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'int|string|INT', + 'type_hint_token' => 5, + 'type_hint_end_token' => 15, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() + + + /** + * Verify recognition of PHP8 constructor property promotion without type declaration, with defaults. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionNoTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$x', + 'content' => 'public $x = 0.0', + 'default' => '0.0', + 'default_token' => 12, + 'default_equal_token' => 10, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'public', + 'visibility_token' => 6, + 'property_readonly' => false, + 'comma_token' => 13, + ]; + $expected[1] = [ + 'token' => 18, + 'name' => '$y', + 'content' => 'protected $y = \'\'', + 'default' => "''", + 'default_token' => 22, + 'default_equal_token' => 20, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'protected', + 'visibility_token' => 16, + 'property_readonly' => false, + 'comma_token' => 23, + ]; + $expected[2] = [ + 'token' => 28, + 'name' => '$z', + 'content' => 'private $z = null', + 'default' => 'null', + 'default_token' => 32, + 'default_equal_token' => 30, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 26, + 'property_readonly' => false, + 'comma_token' => 33, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionNoTypes() + + + /** + * Verify recognition of PHP8 constructor property promotion with type declarations. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionWithTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 10, + 'name' => '$x', + 'content' => 'protected float|int $x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'float|int', + 'type_hint_token' => 6, + 'type_hint_end_token' => 8, + 'nullable_type' => false, + 'property_visibility' => 'protected', + 'visibility_token' => 4, + 'property_readonly' => false, + 'comma_token' => 11, + ]; + $expected[1] = [ + 'token' => 19, + 'name' => '$y', + 'content' => 'public ?string &$y = \'test\'', + 'default' => "'test'", + 'default_token' => 23, + 'default_equal_token' => 21, + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 18, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?string', + 'type_hint_token' => 16, + 'type_hint_end_token' => 16, + 'nullable_type' => true, + 'property_visibility' => 'public', + 'visibility_token' => 13, + 'property_readonly' => false, + 'comma_token' => 24, + ]; + $expected[2] = [ + 'token' => 30, + 'name' => '$z', + 'content' => 'private mixed $z', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'mixed', + 'type_hint_token' => 28, + 'type_hint_end_token' => 28, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 26, + 'property_readonly' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionWithTypes() + + + /** + * Verify recognition of PHP8 constructor with both property promotion as well as normal parameters. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionAndNormalParam() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$promotedProp', + 'content' => 'public int $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'int', + 'type_hint_token' => 6, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'property_visibility' => 'public', + 'visibility_token' => 4, + 'property_readonly' => false, + 'comma_token' => 9, + ]; + $expected[1] = [ + 'token' => 14, + 'name' => '$normalArg', + 'content' => '?int $normalArg', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 12, + 'type_hint_end_token' => 12, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionAndNormalParam() + + + /** + * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly keyword. + * + * @return void + */ + public function testPHP81ConstructorPropertyPromotionWithReadOnly() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 11, + 'name' => '$promotedProp', + 'content' => 'public readonly ?int $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 9, + 'type_hint_end_token' => 9, + 'nullable_type' => true, + 'property_visibility' => 'public', + 'visibility_token' => 4, + 'property_readonly' => true, + 'readonly_token' => 6, + 'comma_token' => 12, + ]; + $expected[1] = [ + 'token' => 23, + 'name' => '$promotedToo', + 'content' => 'ReadOnly private string|bool &$promotedToo', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 22, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'string|bool', + 'type_hint_token' => 18, + 'type_hint_end_token' => 20, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 16, + 'property_readonly' => true, + 'readonly_token' => 14, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81ConstructorPropertyPromotionWithReadOnly() + + + /** + * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly keyword + * without a property type. + * + * @return void + */ + public function testPHP81ConstructorPropertyPromotionWithReadOnlyNoTypeDeclaration() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$promotedProp', + 'content' => 'public readonly $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'public', + 'visibility_token' => 4, + 'property_readonly' => true, + 'readonly_token' => 6, + 'comma_token' => 9, + ]; + $expected[1] = [ + 'token' => 16, + 'name' => '$promotedToo', + 'content' => 'ReadOnly private &$promotedToo', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 15, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 13, + 'property_readonly' => true, + 'readonly_token' => 11, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81ConstructorPropertyPromotionWithReadOnlyNoTypeDeclaration() + + + /** + * Verify recognition of PHP8 constructor with property promotion using PHP 8.1 readonly + * keyword without explicit visibility. + * + * @return void + */ + public function testPHP81ConstructorPropertyPromotionWithOnlyReadOnly() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 10, + 'name' => '$promotedProp', + 'content' => 'readonly Foo&Bar $promotedProp', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'Foo&Bar', + 'type_hint_token' => 6, + 'type_hint_end_token' => 8, + 'nullable_type' => false, + 'property_visibility' => 'public', + 'visibility_token' => false, + 'property_readonly' => true, + 'readonly_token' => 4, + 'comma_token' => 11, + ]; + $expected[1] = [ + 'token' => 18, + 'name' => '$promotedToo', + 'content' => 'readonly ?bool $promotedToo', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?bool', + 'type_hint_token' => 16, + 'type_hint_end_token' => 16, + 'nullable_type' => true, + 'property_visibility' => 'public', + 'visibility_token' => false, + 'property_readonly' => true, + 'readonly_token' => 13, + 'comma_token' => 19, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81ConstructorPropertyPromotionWithOnlyReadOnly() + + + /** + * Verify behaviour when a non-constructor function uses PHP 8 property promotion syntax. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionGlobalFunction() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$x', + 'content' => 'private $x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 4, + 'property_readonly' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionGlobalFunction() + + + /** + * Verify behaviour when an abstract constructor uses PHP 8 property promotion syntax. + * + * @return void + */ + public function testPHP8ConstructorPropertyPromotionAbstractMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$y', + 'content' => 'public callable $y', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'callable', + 'type_hint_token' => 6, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'property_visibility' => 'public', + 'visibility_token' => 4, + 'property_readonly' => false, + 'comma_token' => 9, + ]; + $expected[1] = [ + 'token' => 14, + 'name' => '$x', + 'content' => 'private ...$x', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 13, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 11, + 'property_readonly' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ConstructorPropertyPromotionAbstractMethod() + + + /** + * Verify and document behaviour when there are comments within a parameter declaration. + * + * @return void + */ + public function testCommentsInParameter() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 19, + 'name' => '$param', + 'content' => '// Leading comment. + ?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ \'default value\' . /*-*/ \'second part\' // Trailing comment.', + 'default' => '\'default value\' . /*-*/ \'second part\' // Trailing comment.', + 'default_token' => 27, + 'default_equal_token' => 23, + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 13, + 'variable_length' => true, + 'variadic_token' => 16, + 'type_hint' => '?MyClass', + 'type_hint_token' => 9, + 'type_hint_end_token' => 9, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testCommentsInParameter() + + + /** + * Verify behaviour when parameters have attributes attached. + * + * @return void + */ + public function testParameterAttributesInFunctionDeclaration() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 17, + 'name' => '$constructorPropPromTypedParamSingleAttribute', + 'content' => '#[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'string', + 'type_hint_token' => 15, + 'type_hint_end_token' => 15, + 'nullable_type' => false, + 'property_visibility' => 'private', + 'visibility_token' => 13, + 'property_readonly' => false, + 'comma_token' => 18, + ]; + $expected[1] = [ + 'token' => 39, + 'name' => '$typedParamSingleAttribute', + 'content' => '#[MyAttr([1, 2])] + Type|false + $typedParamSingleAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'Type|false', + 'type_hint_token' => 34, + 'type_hint_end_token' => 36, + 'nullable_type' => false, + 'comma_token' => 40, + ]; + $expected[2] = [ + 'token' => 59, + 'name' => '$nullableTypedParamMultiAttribute', + 'content' => '#[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 57, + 'type_hint_end_token' => 57, + 'nullable_type' => true, + 'comma_token' => 60, + ]; + $expected[3] = [ + 'token' => 74, + 'name' => '$nonTypedParamTwoAttributes', + 'content' => '#[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 75, + ]; + $expected[4] = [ + 'token' => 95, + 'name' => '$otherParam', + 'content' => '#[MyAttribute(array("key" => "value"))] + &...$otherParam', + 'has_attributes' => true, + 'pass_by_reference' => true, + 'reference_token' => 93, + 'variable_length' => true, + 'variadic_token' => 94, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 96, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testParameterAttributesInFunctionDeclaration() + + + /** + * Verify recognition of PHP8.1 intersection type declaration. + * + * @return void + */ + public function testPHP8IntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$obj1', + 'content' => 'Foo&Bar $obj1', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'Foo&Bar', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => 9, + ]; + $expected[1] = [ + 'token' => 15, + 'name' => '$obj2', + 'content' => 'Boo&Bar $obj2', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'Boo&Bar', + 'type_hint_token' => 11, + 'type_hint_end_token' => 13, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8IntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration when the variable + * has either a spread operator or a reference. + * + * @return void + */ + public function testPHP81IntersectionTypesWithSpreadOperatorAndReference() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 9, + 'name' => '$paramA', + 'content' => 'Boo&Bar &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 8, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'Boo&Bar', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => 10, + ]; + $expected[1] = [ + 'token' => 17, + 'name' => '$paramB', + 'content' => 'Foo&Bar ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 16, + 'type_hint' => 'Foo&Bar', + 'type_hint_token' => 12, + 'type_hint_end_token' => 14, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IntersectionTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with more types. + * + * @return void + */ + public function testPHP81MoreIntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 16, + 'name' => '$var', + 'content' => 'MyClassA&\Package\MyClassB&\Package\MyClassC $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', + 'type_hint_token' => 4, + 'type_hint_end_token' => 14, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81MoreIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. + * + * @return void + */ + public function testPHP81IllegalIntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 7, + 'name' => '$numeric_string', + 'content' => 'string&int $numeric_string', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'string&int', + 'type_hint_token' => 3, + 'type_hint_end_token' => 5, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IllegalIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableIntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$object', + 'content' => '?Foo&Bar $object', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?Foo&Bar', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableIntersectionTypes() + + + /** + * Verify recognition of PHP 8.2 stand-alone `true` type. + * + * @return void + */ + public function testPHP82PseudoTypeTrue() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 7, + 'name' => '$var', + 'content' => '?true $var = true', + 'default' => 'true', + 'default_token' => 11, + 'default_equal_token' => 9, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?true', + 'type_hint_token' => 5, + 'type_hint_end_token' => 5, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82PseudoTypeTrue() + + + /** + * Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true. + * + * @return void + */ + public function testPHP82PseudoTypeFalseAndTrue() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$var', + 'content' => 'true|false $var = true', + 'default' => 'true', + 'default_token' => 12, + 'default_equal_token' => 10, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'true|false', + 'type_hint_token' => 4, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82PseudoTypeFalseAndTrue() + + + /** + * Verify behaviour when the default value uses the "new" keyword, as is allowed per PHP 8.1. + * + * @return void + */ + public function testPHP81NewInInitializers() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 8, + 'name' => '$new', + 'content' => 'TypeA $new = new TypeA(self::CONST_VALUE)', + 'default' => 'new TypeA(self::CONST_VALUE)', + 'default_token' => 12, + 'default_equal_token' => 10, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'TypeA', + 'type_hint_token' => 6, + 'type_hint_end_token' => 6, + 'nullable_type' => false, + 'comma_token' => 20, + ]; + $expected[1] = [ + 'token' => 28, + 'name' => '$newToo', + 'content' => '\Package\TypeB $newToo = new \Package\TypeB(10, \'string\')', + 'default' => "new \Package\TypeB(10, 'string')", + 'default_token' => 32, + 'default_equal_token' => 30, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '\Package\TypeB', + 'type_hint_token' => 23, + 'type_hint_end_token' => 26, + 'nullable_type' => false, + 'comma_token' => 44, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NewInInitializers() + + + /** + * Verify recognition of 8.2 DNF parameter type declarations. + * + * @return void + */ + public function testPHP82DNFTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 21, + 'name' => '$obj1', + 'content' => '#[MyAttribute] + false|(Foo&Bar)|true $obj1', + 'has_attributes' => true, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => 'false|(Foo&Bar)|true', + 'type_hint_token' => 11, + 'type_hint_end_token' => 19, + 'nullable_type' => false, + 'comma_token' => 22, + ]; + $expected[1] = [ + 'token' => 41, + 'name' => '$obj2', + 'content' => '(\Boo&\Pck\Bar)|(Boo&Baz) $obj2 = new Boo()', + 'default' => 'new Boo()', + 'default_token' => 45, + 'default_equal_token' => 43, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '(\Boo&\Pck\Bar)|(Boo&Baz)', + 'type_hint_token' => 25, + 'type_hint_end_token' => 39, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypes() + + + /** + * Verify recognition of PHP 8.2 DNF parameter type declarations when the variable + * has either a spread operator or a reference. + * + * @return void + */ + public function testPHP82DNFTypesWithSpreadOperatorAndReference() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 13, + 'name' => '$paramA', + 'content' => '(Countable&MeMe)|iterable &$paramA', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 12, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '(Countable&MeMe)|iterable', + 'type_hint_token' => 4, + 'type_hint_end_token' => 10, + 'nullable_type' => false, + 'comma_token' => 14, + ]; + $expected[1] = [ + 'token' => 25, + 'name' => '$paramB', + 'content' => 'true|(Foo&Bar) ...$paramB', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 24, + 'type_hint' => 'true|(Foo&Bar)', + 'type_hint_token' => 16, + 'type_hint_end_token' => 22, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypesWithSpreadOperatorAndReference() + + + /** + * Verify recognition of PHP 8.2 DNF parameter type declarations using the nullability operator (not allowed). + * + * @return void + */ + public function testPHP82DNFTypesIllegalNullable() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 27, + 'name' => '$var', + 'content' => '? ( MyClassA & /*comment*/ \Package\MyClassB & \Package\MyClassC ) $var', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?(MyClassA&\Package\MyClassB&\Package\MyClassC)', + 'type_hint_token' => 5, + 'type_hint_end_token' => 25, + 'nullable_type' => true, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypesIllegalNullable() + + + /** + * Verify recognition of PHP 8.2 DNF parameter type declarations in an arrow function. + * + * @return void + */ + public function testPHP82DNFTypesInArrow() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 12, + 'name' => '$range', + 'content' => '(Hi&Ho)|FALSE &...$range', + 'has_attributes' => false, + 'pass_by_reference' => true, + 'reference_token' => 10, + 'variable_length' => true, + 'variadic_token' => 11, + 'type_hint' => '(Hi&Ho)|FALSE', + 'type_hint_token' => 2, + 'type_hint_end_token' => 8, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypesInArrow() + + + /** + * Verify handling of a closure. + * + * @return void + */ + public function testClosure() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 3, + 'name' => '$a', + 'content' => '$a = \'test\'', + 'default' => "'test'", + 'default_token' => 7, + 'default_equal_token' => 5, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testClosure() + + + /** + * Verify handling of a closure T_USE token correctly. + * + * @return void + */ + public function testClosureUse() + { + // Offsets are relative to the T_USE token. + $expected = []; + $expected[0] = [ + 'token' => 3, + 'name' => '$foo', + 'content' => '$foo', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 4, + ]; + $expected[1] = [ + 'token' => 6, + 'name' => '$bar', + 'content' => '$bar', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => false, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected, [T_USE]); + + }//end testClosureUse() + + + /** + * Verify function declarations with trailing commas are handled correctly. + * + * @return void + */ + public function testFunctionParamListWithTrailingComma() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 9, + 'name' => '$foo', + 'content' => '?string $foo /*comment*/', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?string', + 'type_hint_token' => 7, + 'type_hint_end_token' => 7, + 'nullable_type' => true, + 'comma_token' => 13, + ]; + $expected[1] = [ + 'token' => 16, + 'name' => '$bar', + 'content' => '$bar = 0', + 'default' => '0', + 'default_token' => 20, + 'default_equal_token' => 18, + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 21, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testFunctionParamListWithTrailingComma() + + + /** + * Verify closure declarations with trailing commas are handled correctly. + * + * @return void + */ + public function testClosureParamListWithTrailingComma() + { + // Offsets are relative to the T_FUNCTION token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$foo', + 'content' => '$foo', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 5, + ]; + $expected[1] = [ + 'token' => 8, + 'name' => '$bar', + 'content' => '$bar', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 9, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testClosureParamListWithTrailingComma() + + + /** + * Verify arrow function declarations with trailing commas are handled correctly. + * + * @return void + */ + public function testArrowFunctionParamListWithTrailingComma() + { + // Offsets are relative to the T_FN token. + $expected = []; + $expected[0] = [ + 'token' => 6, + 'name' => '$a', + 'content' => '?int $a', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '?int', + 'type_hint_token' => 4, + 'type_hint_end_token' => 4, + 'nullable_type' => true, + 'comma_token' => 8, + ]; + $expected[1] = [ + 'token' => 11, + 'name' => '$b', + 'content' => '...$b', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => true, + 'variadic_token' => 10, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 12, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunctionParamListWithTrailingComma() + + + /** + * Verify closure T_USE statements with trailing commas are handled correctly. + * + * @return void + */ + public function testClosureUseWithTrailingComma() + { + // Offsets are relative to the T_USE token. + $expected = []; + $expected[0] = [ + 'token' => 4, + 'name' => '$foo', + 'content' => '$foo /*comment*/', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 8, + ]; + $expected[1] = [ + 'token' => 11, + 'name' => '$bar', + 'content' => '$bar', + 'has_attributes' => false, + 'pass_by_reference' => false, + 'reference_token' => false, + 'variable_length' => false, + 'variadic_token' => false, + 'type_hint' => '', + 'type_hint_token' => false, + 'type_hint_end_token' => false, + 'nullable_type' => false, + 'comma_token' => 12, + ]; + + $this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected, [T_USE]); + + }//end testClosureUseWithTrailingComma() + + + /** + * Test helper. + * + * @param string $commentString The comment which preceeds the test. + * @param array> $expected The expected function output. + * @param int|string|array $targetType Optional. The token type to search for after $marker. + * Defaults to the function/closure/arrow tokens. + * + * @return void + */ + private function getMethodParametersTestHelper($commentString, $expected, $targetType=[T_FUNCTION, T_CLOSURE, T_FN]) + { + $target = $this->getTargetToken($commentString, $targetType); + $found = self::$phpcsFile->getMethodParameters($target); + + // Convert offsets to absolute positions in the token stream. + foreach ($expected as $key => $param) { + $expected[$key]['token'] += $target; + + if (is_int($param['reference_token']) === true) { + $expected[$key]['reference_token'] += $target; + } + + if (is_int($param['variadic_token']) === true) { + $expected[$key]['variadic_token'] += $target; + } + + if (is_int($param['type_hint_token']) === true) { + $expected[$key]['type_hint_token'] += $target; + } + + if (is_int($param['type_hint_end_token']) === true) { + $expected[$key]['type_hint_end_token'] += $target; + } + + if (is_int($param['comma_token']) === true) { + $expected[$key]['comma_token'] += $target; + } + + if (isset($param['default_token']) === true) { + $expected[$key]['default_token'] += $target; + } + + if (isset($param['default_equal_token']) === true) { + $expected[$key]['default_equal_token'] += $target; + } + + if (isset($param['visibility_token']) === true && is_int($param['visibility_token']) === true) { + $expected[$key]['visibility_token'] += $target; + } + + if (isset($param['readonly_token']) === true) { + $expected[$key]['readonly_token'] += $target; + } + }//end foreach + + $this->assertSame($expected, $found); + + }//end getMethodParametersTestHelper() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc new file mode 100644 index 000000000..7f572f66c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.inc @@ -0,0 +1,226 @@ + $number + 1, + $numbers +); + +class ReturnMe { + /* testReturnTypeStatic */ + private function myFunction(): static { + return $this; + } + + /* testReturnTypeNullableStatic */ + function myNullableFunction(): ?static { + return $this; + } +} + +/* testPHP8MixedTypeHint */ +function mixedTypeHint() :mixed {} + +/* testPHP8MixedTypeHintNullable */ +// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method. +function mixedTypeHintNullable(): ?mixed {} + +/* testNamespaceOperatorTypeHint */ +function namespaceOperatorTypeHint() : ?namespace\Name {} + +/* testPHP8UnionTypesSimple */ +function unionTypeSimple($number) : int|float {} + +/* testPHP8UnionTypesTwoClasses */ +$fn = fn($var): MyClassA|\Package\MyClassB => $var; + +/* testPHP8UnionTypesAllBaseTypes */ +function unionTypesAllBaseTypes() : array|bool|callable|int|float|null|Object|string {} + +/* testPHP8UnionTypesAllPseudoTypes */ +// Intentional fatal error - mixing types which cannot be combined, but that's not the concern of the method. +function unionTypesAllPseudoTypes($var) : false|MIXED|self|parent|static|iterable|Resource|void {} + +/* testPHP8UnionTypesNullable */ +// Intentional fatal error - nullability is not allowed with union types, but that's not the concern of the method. +$closure = function () use($a) :?int|float {}; + +/* testPHP8PseudoTypeNull */ +// PHP 8.0 - 8.1: Intentional fatal error - null pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeNull(): null {} + +/* testPHP8PseudoTypeFalse */ +// PHP 8.0 - 8.1: Intentional fatal error - false pseudotype is only allowed in union types, but that's not the concern of the method. +function pseudoTypeFalse(): false {} + +/* testPHP8PseudoTypeFalseAndBool */ +// Intentional fatal error - false pseudotype is not allowed in combination with bool, but that's not the concern of the method. +function pseudoTypeFalseAndBool(): bool|false {} + +/* testPHP8ObjectAndClass */ +// Intentional fatal error - object is not allowed in combination with class name, but that's not the concern of the method. +function objectAndClass(): object|ClassName {} + +/* testPHP8PseudoTypeIterableAndArray */ +// Intentional fatal error - iterable pseudotype is not allowed in combination with array or Traversable, but that's not the concern of the method. +interface FooBar { + public function pseudoTypeIterableAndArray(): iterable|array|Traversable; +} + +/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */ +// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method. +function duplicateTypeInUnion(): int | /*comment*/ string | INT {} + +/* testPHP81NeverType */ +function never(): never {} + +/* testPHP81NullableNeverType */ +// Intentional fatal error - nullability is not allowed with never, but that's not the concern of the method. +function nullableNever(): ?never {} + +/* testPHP8IntersectionTypes */ +function intersectionTypes(): Foo&Bar {} + +/* testPHP81MoreIntersectionTypes */ +function moreIntersectionTypes(): MyClassA&\Package\MyClassB&\Package\MyClassC {} + +/* testPHP81IntersectionArrowFunction */ +$fn = fn($var): MyClassA&\Package\MyClassB => $var; + +/* testPHP81IllegalIntersectionTypes */ +// Intentional fatal error - simple types are not allowed with intersection types, but that's not the concern of the method. +$closure = function (): string&int {}; + +/* testPHP81NullableIntersectionTypes */ +// Intentional fatal error - nullability is not allowed with intersection types, but that's not the concern of the method. +$closure = function (): ?Foo&Bar {}; + +/* testPHP82PseudoTypeTrue */ +function pseudoTypeTrue(): ?true {} + +/* testPHP82PseudoTypeFalseAndTrue */ +// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method. +function pseudoTypeFalseAndTrue(): true|false {} + +/* testPHP82DNFType */ +function hasDNFType() : bool|(Foo&Bar)|string {} + +abstract class AbstractClass { + /* testPHP82DNFTypeAbstractMethod */ + abstract protected function abstractMethodDNFType() : float|(Foo&Bar); +} + +/* testPHP82DNFTypeIllegalNullable */ +// Intentional fatal error - nullable operator cannot be combined with DNF. +function illegalNullableDNF(): ?(A&\Pck\B)|bool {} + +/* testPHP82DNFTypeClosure */ +$closure = function() : object|(namespace\Foo&Countable) {}; + +/* testPHP82DNFTypeFn */ +// Intentional fatal error - void type cannot be combined with DNF. +$arrow = fn() : null|(Partially\Qualified&Traversable)|void => do_something(); + +/* testNotAFunction */ +return true; + +/* testPhpcsIssue1264 */ +function foo() : array { + echo $foo; +} + +/* testArrowFunctionArrayReturnValue */ +$fn = fn(): array => [a($a, $b)]; + +/* testArrowFunctionReturnByRef */ +fn&(?string $a) : ?string => $b; + +/* testFunctionCallFnPHPCS353-354 */ +$value = $obj->fn(true); + +/* testFunctionDeclarationNestedInTernaryPHPCS2975 */ +return (!$a ? [ new class { public function b(): c {} } ] : []); + +/* testClosureWithUseNoReturnType */ +$closure = function () use($a) /*comment*/ {}; + +/* testClosureWithUseNoReturnTypeIllegalUseProp */ +$closure = function () use ($this->prop){}; + +/* testClosureWithUseWithReturnType */ +$closure = function () use /*comment*/ ($a): Type {}; + +/* testClosureWithUseMultiParamWithReturnType */ +$closure = function () use ($a, &$b, $c, $d, $e, $f, $g): ?array {}; + +/* testArrowFunctionLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$fn = fn diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php new file mode 100644 index 000000000..273ff4b28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodPropertiesTest.php @@ -0,0 +1,1562 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::getMethodProperties method. + * + * @covers \PHP_CodeSniffer\Files\File::getMethodProperties + */ +final class GetMethodPropertiesTest extends AbstractMethodUnitTest +{ + + + /** + * Test receiving an expected exception when a non function token is passed. + * + * @param string $commentString The comment which preceeds the test. + * @param string|int|array $targetTokenType The token type to search for after $commentString. + * + * @dataProvider dataNotAFunctionException + * + * @return void + */ + public function testNotAFunctionException($commentString, $targetTokenType) + { + $this->expectRunTimeException('$stackPtr must be of type T_FUNCTION or T_CLOSURE or T_FN'); + + $next = $this->getTargetToken($commentString, $targetTokenType); + self::$phpcsFile->getMethodProperties($next); + + }//end testNotAFunctionException() + + + /** + * Data Provider. + * + * @see testNotAFunctionException() For the array format. + * + * @return array>> + */ + public static function dataNotAFunctionException() + { + return [ + 'return' => [ + 'commentString' => '/* testNotAFunction */', + 'targetTokenType' => T_RETURN, + ], + 'function-call-fn-phpcs-3.5.3-3.5.4' => [ + 'commentString' => '/* testFunctionCallFnPHPCS353-354 */', + 'targetTokenType' => [ + T_FN, + T_STRING, + ], + ], + 'fn-live-coding' => [ + 'commentString' => '/* testArrowFunctionLiveCoding */', + 'targetTokenType' => [ + T_FN, + T_STRING, + ], + ], + ]; + + }//end dataNotAFunctionException() + + + /** + * Test a basic function. + * + * @return void + */ + public function testBasicFunction() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBasicFunction() + + + /** + * Test a function with a return type. + * + * @return void + */ + public function testReturnFunction() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array', + 'return_type_token' => 11, + 'return_type_end_token' => 11, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnFunction() + + + /** + * Test a closure used as a function argument. + * + * @return void + */ + public function testNestedClosure() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNestedClosure() + + + /** + * Test a basic method. + * + * @return void + */ + public function testBasicMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testBasicMethod() + + + /** + * Test a private static method. + * + * @return void + */ + public function testPrivateStaticMethod() + { + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => true, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPrivateStaticMethod() + + + /** + * Test a basic final method. + * + * @return void + */ + public function testFinalMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => true, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testFinalMethod() + + + /** + * Test a protected method with a return type. + * + * @return void + */ + public function testProtectedReturnMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'int', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testProtectedReturnMethod() + + + /** + * Test a public method with a return type. + * + * @return void + */ + public function testPublicReturnMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'array', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPublicReturnMethod() + + + /** + * Test a public method with a nullable return type. + * + * @return void + */ + public function testNullableReturnMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '?array', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNullableReturnMethod() + + + /** + * Test a public method with a nullable return type. + * + * @return void + */ + public function testMessyNullableReturnMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => '?array', + 'return_type_token' => 18, + 'return_type_end_token' => 18, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testMessyNullableReturnMethod() + + + /** + * Test a method with a namespaced return type. + * + * @return void + */ + public function testReturnNamespace() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '\MyNamespace\MyClass', + 'return_type_token' => 7, + 'return_type_end_token' => 10, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnNamespace() + + + /** + * Test a method with a messy namespaces return type. + * + * @return void + */ + public function testReturnMultilineNamespace() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '\MyNamespace\MyClass\Foo', + 'return_type_token' => 7, + 'return_type_end_token' => 23, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnMultilineNamespace() + + + /** + * Test a method with an unqualified named return type. + * + * @return void + */ + public function testReturnUnqualifiedName() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => '?MyClass', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnUnqualifiedName() + + + /** + * Test a method with a partially qualified namespaced return type. + * + * @return void + */ + public function testReturnPartiallyQualifiedName() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'Sub\Level\MyClass', + 'return_type_token' => 7, + 'return_type_end_token' => 11, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnPartiallyQualifiedName() + + + /** + * Test a basic abstract method. + * + * @return void + */ + public function testAbstractMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testAbstractMethod() + + + /** + * Test an abstract method with a return type. + * + * @return void + */ + public function testAbstractReturnMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'bool', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testAbstractReturnMethod() + + + /** + * Test a basic interface method. + * + * @return void + */ + public function testInterfaceMethod() + { + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testInterfaceMethod() + + + /** + * Test a static arrow function. + * + * @return void + */ + public function testArrowFunction() + { + // Offsets are relative to the T_FN token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int', + 'return_type_token' => 9, + 'return_type_end_token' => 9, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => true, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunction() + + + /** + * Test a function with return type "static". + * + * @return void + */ + public function testReturnTypeStatic() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'private', + 'scope_specified' => true, + 'return_type' => 'static', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnTypeStatic() + + + /** + * Test a function with return type "?static". + * + * @return void + */ + public function testReturnTypeNullableStatic() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?static', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testReturnTypeNullableStatic() + + + /** + * Test a function with return type "mixed". + * + * @return void + */ + public function testPHP8MixedTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'mixed', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHint() + + + /** + * Test a function with return type "mixed" and nullability. + * + * @return void + */ + public function testPHP8MixedTypeHintNullable() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?mixed', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8MixedTypeHintNullable() + + + /** + * Test a function with return type using the namespace operator. + * + * @return void + */ + public function testNamespaceOperatorTypeHint() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?namespace\Name', + 'return_type_token' => 9, + 'return_type_end_token' => 11, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testNamespaceOperatorTypeHint() + + + /** + * Verify recognition of PHP8 union type declaration. + * + * @return void + */ + public function testPHP8UnionTypesSimple() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int|float', + 'return_type_token' => 9, + 'return_type_end_token' => 11, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesSimple() + + + /** + * Verify recognition of PHP8 union type declaration with two classes. + * + * @return void + */ + public function testPHP8UnionTypesTwoClasses() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA|\Package\MyClassB', + 'return_type_token' => 6, + 'return_type_end_token' => 11, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesTwoClasses() + + + /** + * Verify recognition of PHP8 union type declaration with all base types. + * + * @return void + */ + public function testPHP8UnionTypesAllBaseTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array|bool|callable|int|float|null|Object|string', + 'return_type_token' => 8, + 'return_type_end_token' => 22, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllBaseTypes() + + + /** + * Verify recognition of PHP8 union type declaration with all pseudo types. + * + * Note: "Resource" is not a type, but seen as a class name. + * + * @return void + */ + public function testPHP8UnionTypesAllPseudoTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'false|MIXED|self|parent|static|iterable|Resource|void', + 'return_type_token' => 9, + 'return_type_end_token' => 23, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesAllPseudoTypes() + + + /** + * Verify recognition of PHP8 union type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP8UnionTypesNullable() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?int|float', + 'return_type_token' => 12, + 'return_type_end_token' => 14, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8UnionTypesNullable() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type null. + * + * @return void + */ + public function testPHP8PseudoTypeNull() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'null', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeNull() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) single type false. + * + * @return void + */ + public function testPHP8PseudoTypeFalse() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'false', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalse() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type false combined with type bool. + * + * @return void + */ + public function testPHP8PseudoTypeFalseAndBool() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'bool|false', + 'return_type_token' => 7, + 'return_type_end_token' => 9, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeFalseAndBool() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type object combined with a class name. + * + * @return void + */ + public function testPHP8ObjectAndClass() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'object|ClassName', + 'return_type_token' => 7, + 'return_type_end_token' => 9, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8ObjectAndClass() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) type iterable combined with array/Traversable. + * + * @return void + */ + public function testPHP8PseudoTypeIterableAndArray() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'iterable|array|Traversable', + 'return_type_token' => 7, + 'return_type_end_token' => 11, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8PseudoTypeIterableAndArray() + + + /** + * Verify recognition of PHP8 type declaration with (illegal) duplicate types. + * + * @return void + */ + public function testPHP8DuplicateTypeInUnionWhitespaceAndComment() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'int|string|INT', + 'return_type_token' => 7, + 'return_type_end_token' => 17, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8DuplicateTypeInUnionWhitespaceAndComment() + + + /** + * Verify recognition of PHP8.1 type "never". + * + * @return void + */ + public function testPHP81NeverType() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'never', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NeverType() + + + /** + * Verify recognition of PHP8.1 type "never" with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableNeverType() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?never', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableNeverType() + + + /** + * Verify recognition of PHP8.1 intersection type declaration. + * + * @return void + */ + public function testPHP8IntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'Foo&Bar', + 'return_type_token' => 7, + 'return_type_end_token' => 9, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP8IntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with more types. + * + * @return void + */ + public function testPHP81MoreIntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA&\Package\MyClassB&\Package\MyClassC', + 'return_type_token' => 7, + 'return_type_end_token' => 17, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81MoreIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration in arrow function. + * + * @return void + */ + public function testPHP81IntersectionArrowFunction() + { + // Offsets are relative to the T_FN token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'MyClassA&\Package\MyClassB', + 'return_type_token' => 6, + 'return_type_end_token' => 11, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IntersectionArrowFunction() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with illegal simple types. + * + * @return void + */ + public function testPHP81IllegalIntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'string&int', + 'return_type_token' => 6, + 'return_type_end_token' => 8, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81IllegalIntersectionTypes() + + + /** + * Verify recognition of PHP8.1 intersection type declaration with (illegal) nullability. + * + * @return void + */ + public function testPHP81NullableIntersectionTypes() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?Foo&Bar', + 'return_type_token' => 7, + 'return_type_end_token' => 9, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP81NullableIntersectionTypes() + + + /** + * Verify recognition of PHP 8.2 stand-alone `true` type. + * + * @return void + */ + public function testPHP82PseudoTypeTrue() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?true', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82PseudoTypeTrue() + + + /** + * Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true. + * + * @return void + */ + public function testPHP82PseudoTypeFalseAndTrue() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'true|false', + 'return_type_token' => 7, + 'return_type_end_token' => 9, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82PseudoTypeFalseAndTrue() + + + /** + * Verify recognition of PHP 8.2 DNF return type declaration. + * + * @return void + */ + public function testPHP82DNFType() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'bool|(Foo&Bar)|string', + 'return_type_token' => 8, + 'return_type_end_token' => 16, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFType() + + + /** + * Verify recognition of PHP 8.2 DNF return type declaration on an abstract method. + * + * @return void + */ + public function testPHP82DNFTypeAbstractMethod() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'protected', + 'scope_specified' => true, + 'return_type' => 'float|(Foo&Bar)', + 'return_type_token' => 8, + 'return_type_end_token' => 14, + 'nullable_return_type' => false, + 'is_abstract' => true, + 'is_final' => false, + 'is_static' => false, + 'has_body' => false, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypeAbstractMethod() + + + /** + * Verify recognition of PHP 8.2 DNF return type declaration with illegal nullability. + * + * @return void + */ + public function testPHP82DNFTypeIllegalNullable() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?(A&\Pck\B)|bool', + 'return_type_token' => 8, + 'return_type_end_token' => 17, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypeIllegalNullable() + + + /** + * Verify recognition of PHP 8.2 DNF return type declaration on a closure. + * + * @return void + */ + public function testPHP82DNFTypeClosure() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'object|(namespace\Foo&Countable)', + 'return_type_token' => 6, + 'return_type_end_token' => 14, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypeClosure() + + + /** + * Verify recognition of PHP 8.2 DNF return type declaration on an arrow function. + * + * @return void + */ + public function testPHP82DNFTypeFn() + { + // Offsets are relative to the T_FN token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'null|(Partially\Qualified&Traversable)|void', + 'return_type_token' => 6, + 'return_type_end_token' => 16, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPHP82DNFTypeFn() + + + /** + * Test for incorrect tokenization of array return type declarations in PHPCS < 2.8.0. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/pull/1264 + * + * @return void + */ + public function testPhpcsIssue1264() + { + // Offsets are relative to the T_FUNCTION token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array', + 'return_type_token' => 8, + 'return_type_end_token' => 8, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testPhpcsIssue1264() + + + /** + * Test handling of incorrect tokenization of array return type declarations for arrow functions + * in a very specific code sample in PHPCS < 3.5.4. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/2773 + * + * @return void + */ + public function testArrowFunctionArrayReturnValue() + { + // Offsets are relative to the T_FN token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'array', + 'return_type_token' => 5, + 'return_type_end_token' => 5, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunctionArrayReturnValue() + + + /** + * Test handling of an arrow function returning by reference. + * + * @return void + */ + public function testArrowFunctionReturnByRef() + { + // Offsets are relative to the T_FN token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?string', + 'return_type_token' => 12, + 'return_type_end_token' => 12, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testArrowFunctionReturnByRef() + + + /** + * Test handling of function declaration nested in a ternary, where the colon for the + * return type was incorrectly tokenized as T_INLINE_ELSE prior to PHPCS 3.5.7. + * + * @return void + */ + public function testFunctionDeclarationNestedInTernaryPHPCS2975() + { + // Offsets are relative to the T_FN token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => true, + 'return_type' => 'c', + 'return_type_token' => 7, + 'return_type_end_token' => 7, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testFunctionDeclarationNestedInTernaryPHPCS2975() + + + /** + * Test handling of closure declarations with a use variable import without a return type declaration. + * + * @return void + */ + public function testClosureWithUseNoReturnType() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testClosureWithUseNoReturnType() + + + /** + * Test handling of closure declarations with an illegal use variable for a property import (not allowed in PHP) + * without a return type declaration. + * + * @return void + */ + public function testClosureWithUseNoReturnTypeIllegalUseProp() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '', + 'return_type_token' => false, + 'return_type_end_token' => false, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testClosureWithUseNoReturnTypeIllegalUseProp() + + + /** + * Test handling of closure declarations with a use variable import with a return type declaration. + * + * @return void + */ + public function testClosureWithUseWithReturnType() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => 'Type', + 'return_type_token' => 14, + 'return_type_end_token' => 14, + 'nullable_return_type' => false, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testClosureWithUseWithReturnType() + + + /** + * Test handling of closure declarations with a use variable import with a return type declaration. + * + * @return void + */ + public function testClosureWithUseMultiParamWithReturnType() + { + // Offsets are relative to the T_CLOSURE token. + $expected = [ + 'scope' => 'public', + 'scope_specified' => false, + 'return_type' => '?array', + 'return_type_token' => 32, + 'return_type_end_token' => 32, + 'nullable_return_type' => true, + 'is_abstract' => false, + 'is_final' => false, + 'is_static' => false, + 'has_body' => true, + ]; + + $this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected); + + }//end testClosureWithUseMultiParamWithReturnType() + + + /** + * Test helper. + * + * @param string $commentString The comment which preceeds the test. + * @param array $expected The expected function output. + * + * @return void + */ + private function getMethodPropertiesTestHelper($commentString, $expected) + { + $function = $this->getTargetToken($commentString, [T_FUNCTION, T_CLOSURE, T_FN]); + $found = self::$phpcsFile->getMethodProperties($function); + + // Convert offsets to absolute positions in the token stream. + if (is_int($expected['return_type_token']) === true) { + $expected['return_type_token'] += $function; + } + + if (is_int($expected['return_type_end_token']) === true) { + $expected['return_type_end_token'] += $function; + } + + $this->assertSame($expected, $found); + + }//end getMethodPropertiesTestHelper() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.inc new file mode 100644 index 000000000..ace5a9bd4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.inc @@ -0,0 +1,25 @@ + 20; +} + +/* testEchoWithTabs */ +echo 'foo', + 'bar' , + 'baz'; + +/* testEndOfFile */ +echo $foo; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.php new file mode 100644 index 000000000..7e7974951 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/GetTokensAsStringTest.php @@ -0,0 +1,334 @@ + + * @copyright 2022-2024 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File:getTokensAsString method. + * + * @covers \PHP_CodeSniffer\Files\File::getTokensAsString + */ +final class GetTokensAsStringTest extends AbstractMethodUnitTest +{ + + + /** + * Test passing a non-existent token pointer. + * + * @return void + */ + public function testNonExistentToken() + { + $this->expectRunTimeException('The $start position for getTokensAsString() must exist in the token stack'); + + self::$phpcsFile->getTokensAsString(100000, 10); + + }//end testNonExistentToken() + + + /** + * Test passing a non integer `$start`, like the result of a failed $phpcsFile->findNext(). + * + * @return void + */ + public function testNonIntegerStart() + { + $this->expectRunTimeException('The $start position for getTokensAsString() must exist in the token stack'); + + self::$phpcsFile->getTokensAsString(false, 10); + + }//end testNonIntegerStart() + + + /** + * Test passing a non integer `$length`. + * + * @return void + */ + public function testNonIntegerLength() + { + $result = self::$phpcsFile->getTokensAsString(10, false); + $this->assertSame('', $result); + + $result = self::$phpcsFile->getTokensAsString(10, 1.5); + $this->assertSame('', $result); + + }//end testNonIntegerLength() + + + /** + * Test passing a zero or negative `$length`. + * + * @return void + */ + public function testLengthEqualToOrLessThanZero() + { + $result = self::$phpcsFile->getTokensAsString(10, -10); + $this->assertSame('', $result); + + $result = self::$phpcsFile->getTokensAsString(10, 0); + $this->assertSame('', $result); + + }//end testLengthEqualToOrLessThanZero() + + + /** + * Test passing a `$length` beyond the end of the file. + * + * @return void + */ + public function testLengthBeyondEndOfFile() + { + $semicolon = $this->getTargetToken('/* testEndOfFile */', T_SEMICOLON); + $result = self::$phpcsFile->getTokensAsString($semicolon, 20); + $this->assertSame( + '; +', + $result + ); + + }//end testLengthBeyondEndOfFile() + + + /** + * Test getting a token set as a string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $startTokenType The type of token(s) to look for for the start of the string. + * @param int $length Token length to get. + * @param string $expected The expected function return value. + * + * @dataProvider dataGetTokensAsString + * + * @return void + */ + public function testGetTokensAsString($testMarker, $startTokenType, $length, $expected) + { + $start = $this->getTargetToken($testMarker, $startTokenType); + $result = self::$phpcsFile->getTokensAsString($start, $length); + $this->assertSame($expected, $result); + + }//end testGetTokensAsString() + + + /** + * Data provider. + * + * @see testGetTokensAsString() For the array format. + * + * @return array> + */ + public static function dataGetTokensAsString() + { + return [ + 'length-0' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 0, + 'expected' => '', + ], + 'length-1' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 1, + 'expected' => '1', + ], + 'length-2' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 2, + 'expected' => '1 ', + ], + 'length-3' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 3, + 'expected' => '1 +', + ], + 'length-4' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 4, + 'expected' => '1 + ', + ], + 'length-5' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 5, + 'expected' => '1 + 2', + ], + 'length-6' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 6, + 'expected' => '1 + 2 ', + ], + 'length-7' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 7, + 'expected' => '1 + 2 +', + ], + 'length-8' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 8, + 'expected' => '1 + 2 + +', + ], + 'length-9' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 9, + 'expected' => '1 + 2 + + ', + ], + 'length-10' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 10, + 'expected' => '1 + 2 + + // Comment. +', + ], + 'length-11' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 11, + 'expected' => '1 + 2 + + // Comment. + ', + ], + 'length-12' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 12, + 'expected' => '1 + 2 + + // Comment. + 3', + ], + 'length-13' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 13, + 'expected' => '1 + 2 + + // Comment. + 3 ', + ], + 'length-14' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 14, + 'expected' => '1 + 2 + + // Comment. + 3 +', + ], + 'length-34' => [ + 'testMarker' => '/* testCalculation */', + 'startTokenType' => T_LNUMBER, + 'length' => 34, + 'expected' => '1 + 2 + + // Comment. + 3 + 4 + + 5 + 6 + 7 > 20;', + ], + 'namespace' => [ + 'testMarker' => '/* testNamespace */', + 'startTokenType' => T_NAMESPACE, + 'length' => 8, + 'expected' => 'namespace Foo\Bar\Baz;', + ], + 'use-with-comments' => [ + 'testMarker' => '/* testUseWithComments */', + 'startTokenType' => T_USE, + 'length' => 17, + 'expected' => 'use Foo /*comment*/ \ Bar + // phpcs:ignore Stnd.Cat.Sniff -- For reasons. + \ Bah;', + ], + 'echo-with-tabs' => [ + 'testMarker' => '/* testEchoWithTabs */', + 'startTokenType' => T_ECHO, + 'length' => 13, + 'expected' => 'echo \'foo\', + \'bar\' , + \'baz\';', + ], + 'end-of-file' => [ + 'testMarker' => '/* testEndOfFile */', + 'startTokenType' => T_ECHO, + 'length' => 4, + 'expected' => 'echo $foo;', + ], + ]; + + }//end dataGetTokensAsString() + + + /** + * Test getting a token set as a string with the original, non tab-replaced content. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $startTokenType The type of token(s) to look for for the start of the string. + * @param int $length Token length to get. + * @param string $expected The expected function return value. + * + * @dataProvider dataGetOrigContent + * + * @return void + */ + public function testGetOrigContent($testMarker, $startTokenType, $length, $expected) + { + $start = $this->getTargetToken($testMarker, $startTokenType); + $result = self::$phpcsFile->getTokensAsString($start, $length, true); + $this->assertSame($expected, $result); + + }//end testGetOrigContent() + + + /** + * Data provider. + * + * @see testGetOrigContent() For the array format. + * + * @return array> + */ + public static function dataGetOrigContent() + { + return [ + 'use-with-comments' => [ + 'testMarker' => '/* testUseWithComments */', + 'startTokenType' => T_USE, + 'length' => 17, + 'expected' => 'use Foo /*comment*/ \ Bar + // phpcs:ignore Stnd.Cat.Sniff -- For reasons. + \ Bah;', + ], + 'echo-with-tabs' => [ + 'testMarker' => '/* testEchoWithTabs */', + 'startTokenType' => T_ECHO, + 'length' => 13, + 'expected' => 'echo \'foo\', + \'bar\' , + \'baz\';', + ], + 'end-of-file' => [ + 'testMarker' => '/* testEndOfFile */', + 'startTokenType' => T_ECHO, + 'length' => 4, + 'expected' => 'echo $foo;', + ], + ]; + + }//end dataGetOrigContent() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc new file mode 100644 index 000000000..05af83905 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.inc @@ -0,0 +1,216 @@ + $first, 'b' => $something & $somethingElse ]; + +/* testBitwiseAndF */ +$a = array( 'a' => $first, 'b' => $something & \MyClass::$somethingElse ); + +/* testBitwiseAndG */ +$a = $something & $somethingElse; + +/* testBitwiseAndH */ +function myFunction($a = 10 & 20) {} + +/* testBitwiseAndI */ +$closure = function ($a = MY_CONSTANT & parent::OTHER_CONSTANT) {}; + +/* testFunctionReturnByReference */ +function &myFunction() {} + +/* testFunctionPassByReferenceA */ +function myFunction( &$a ) {} + +/* testFunctionPassByReferenceB */ +function myFunction( $a, &$b ) {} + +/* testFunctionPassByReferenceC */ +$closure = function ( &$a ) {}; + +/* testFunctionPassByReferenceD */ +$closure = function ( $a, &$b ) {}; + +/* testFunctionPassByReferenceE */ +function myFunction(array &$one) {} + +/* testFunctionPassByReferenceF */ +$closure = function (\MyClass &$one) {}; + +/* testFunctionPassByReferenceG */ +$closure = function ($param, &...$moreParams) {}; + +/* testForeachValueByReference */ +foreach( $array as $key => &$value ) {} + +/* testForeachKeyByReference */ +foreach( $array as &$key => $value ) {} + +/* testArrayValueByReferenceA */ +$a = [ 'a' => &$something ]; + +/* testArrayValueByReferenceB */ +$a = [ 'a' => $something, 'b' => &$somethingElse ]; + +/* testArrayValueByReferenceC */ +$a = [ &$something ]; + +/* testArrayValueByReferenceD */ +$a = [ $something, &$somethingElse ]; + +/* testArrayValueByReferenceE */ +$a = array( 'a' => &$something ); + +/* testArrayValueByReferenceF */ +$a = array( 'a' => $something, 'b' => &$somethingElse ); + +/* testArrayValueByReferenceG */ +$a = array( &$something ); + +/* testArrayValueByReferenceH */ +$a = array( $something, &$somethingElse ); + +/* testAssignByReferenceA */ +$b = &$something; + +/* testAssignByReferenceB */ +$b =& $something; + +/* testAssignByReferenceC */ +$b .= &$something; + +/* testAssignByReferenceD */ +$myValue = &$obj->getValue(); + +/* testAssignByReferenceE */ +$collection = &collector(); + +/* testAssignByReferenceF */ +$collection ??= &collector(); + +/* testShortListAssignByReferenceNoKeyA */ +[ + &$a, + /* testShortListAssignByReferenceNoKeyB */ + &$b, + /* testNestedShortListAssignByReferenceNoKey */ + [$c, &$d] +] = $array; + +/* testLongListAssignByReferenceNoKeyA */ +list($a, &$b, list(/* testLongListAssignByReferenceNoKeyB */ &$c, /* testLongListAssignByReferenceNoKeyC */ &$d)) = $array; + +[ + /* testNestedShortListAssignByReferenceWithKeyA */ + 'a' => [&$a, $b], + /* testNestedShortListAssignByReferenceWithKeyB */ + 'b' => [$c, &$d] +] = $array; + + +/* testLongListAssignByReferenceWithKeyA */ +list(get_key()[1] => &$e) = [1, 2, 3]; + +/* testPassByReferenceA */ +functionCall(&$something, $somethingElse); + +/* testPassByReferenceB */ +functionCall($something, &$somethingElse); + +/* testPassByReferenceC */ +functionCall($something, &$this->somethingElse); + +/* testPassByReferenceD */ +functionCall($something, &self::$somethingElse); + +/* testPassByReferenceE */ +functionCall($something, &parent::$somethingElse); + +/* testPassByReferenceF */ +functionCall($something, &static::$somethingElse); + +/* testPassByReferenceG */ +functionCall($something, &SomeClass::$somethingElse); + +/* testPassByReferenceH */ +functionCall(&\SomeClass::$somethingElse); + +/* testPassByReferenceI */ +functionCall($something, &\SomeNS\SomeClass::$somethingElse); + +/* testPassByReferenceJ */ +functionCall($something, &namespace\SomeClass::$somethingElse); + +/* testPassByReferencePartiallyQualifiedName */ +functionCall($something, &Sub\Level\SomeClass::$somethingElse); + +/* testNewByReferenceA */ +$foobar2 = &new Foobar(); + +/* testNewByReferenceB */ +functionCall( $something , &new Foobar() ); + +/* testUseByReference */ +$closure = function() use (&$var){}; + +/* testUseByReferenceWithCommentFirstParam */ +$closure = function() use /*comment*/ (&$value){}; + +/* testUseByReferenceWithCommentSecondParam */ +$closure = function() use /*comment*/ ($varA, &$varB){}; + +/* testArrowFunctionReturnByReference */ +fn&($x) => $x; + +$closure = function ( + /* testBitwiseAndExactParameterA */ + $a = MY_CONSTANT & parent::OTHER_CONSTANT, + /* testPassByReferenceExactParameterB */ + &$b, + /* testPassByReferenceExactParameterC */ + &...$c, + /* testBitwiseAndExactParameterD */ + $d = E_NOTICE & E_STRICT, +) {}; + +// Issue PHPCS#3049. +/* testArrowFunctionPassByReferenceA */ +$fn = fn(array &$one) => 1; + +/* testArrowFunctionPassByReferenceB */ +$fn = fn($param, &...$moreParams) => 1; + +/* testClosureReturnByReference */ +$closure = function &($param) use ($value) {}; + +/* testBitwiseAndArrowFunctionInDefault */ +$fn = fn( $one = E_NOTICE & E_STRICT) => 1; + +/* testIntersectionIsNotReference */ +function intersect(Foo&Bar $param) {} + +/* testDNFTypeIsNotReference */ +$fn = fn((Foo&\Bar)|null /* testParamPassByReference */ &$param) => $param; + +/* testTokenizerIssue1284PHPCSlt280A */ +if ($foo) {} +[&$a, /* testTokenizerIssue1284PHPCSlt280B */ &$b] = $c; + +/* testTokenizerIssue1284PHPCSlt280C */ +if ($foo) {} +[&$a, $b]; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php new file mode 100644 index 000000000..5b977de7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/File/IsReferenceTest.php @@ -0,0 +1,396 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\File; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Files\File::isReference method. + * + * @covers \PHP_CodeSniffer\Files\File::isReference + */ +final class IsReferenceTest extends AbstractMethodUnitTest +{ + + + /** + * Test that false is returned when a non-"bitwise and" token is passed. + * + * @param string $testMarker Comment which precedes the test case. + * @param array $targetTokens Type of tokens to look for. + * + * @dataProvider dataNotBitwiseAndToken + * + * @return void + */ + public function testNotBitwiseAndToken($testMarker, $targetTokens) + { + $targetTokens[] = T_BITWISE_AND; + + $target = $this->getTargetToken($testMarker, $targetTokens); + $this->assertFalse(self::$phpcsFile->isReference($target)); + + }//end testNotBitwiseAndToken() + + + /** + * Data provider. + * + * @see testNotBitwiseAndToken() + * + * @return array>> + */ + public static function dataNotBitwiseAndToken() + { + return [ + 'Not ampersand token at all' => [ + 'testMarker' => '/* testBitwiseAndA */', + 'targetTokens' => [T_STRING], + ], + 'ampersand in intersection type' => [ + 'testMarker' => '/* testIntersectionIsNotReference */', + 'targetTokens' => [T_TYPE_INTERSECTION], + ], + 'ampersand in DNF type' => [ + 'testMarker' => '/* testDNFTypeIsNotReference */', + 'targetTokens' => [T_TYPE_INTERSECTION], + ], + ]; + + }//end dataNotBitwiseAndToken() + + + /** + * Test correctly identifying whether a "bitwise and" token is a reference or not. + * + * @param string $testMarker Comment which precedes the test case. + * @param bool $expected Expected function output. + * + * @dataProvider dataIsReference + * + * @return void + */ + public function testIsReference($testMarker, $expected) + { + $bitwiseAnd = $this->getTargetToken($testMarker, T_BITWISE_AND); + $result = self::$phpcsFile->isReference($bitwiseAnd); + $this->assertSame($expected, $result); + + }//end testIsReference() + + + /** + * Data provider for the IsReference test. + * + * @see testIsReference() + * + * @return array> + */ + public static function dataIsReference() + { + return [ + 'issue-1971-list-first-in-file' => [ + 'testMarker' => '/* testTokenizerIssue1971PHPCSlt330gt271A */', + 'expected' => true, + ], + 'issue-1971-list-first-in-file-nested' => [ + 'testMarker' => '/* testTokenizerIssue1971PHPCSlt330gt271B */', + 'expected' => true, + ], + 'bitwise and: param in function call' => [ + 'testMarker' => '/* testBitwiseAndA */', + 'expected' => false, + ], + 'bitwise and: in unkeyed short array, first value' => [ + 'testMarker' => '/* testBitwiseAndB */', + 'expected' => false, + ], + 'bitwise and: in unkeyed short array, last value' => [ + 'testMarker' => '/* testBitwiseAndC */', + 'expected' => false, + ], + 'bitwise and: in unkeyed long array, last value' => [ + 'testMarker' => '/* testBitwiseAndD */', + 'expected' => false, + ], + 'bitwise and: in keyed short array, last value' => [ + 'testMarker' => '/* testBitwiseAndE */', + 'expected' => false, + ], + 'bitwise and: in keyed long array, last value' => [ + 'testMarker' => '/* testBitwiseAndF */', + 'expected' => false, + ], + 'bitwise and: in assignment' => [ + 'testMarker' => '/* testBitwiseAndG */', + 'expected' => false, + ], + 'bitwise and: in param default value in function declaration' => [ + 'testMarker' => '/* testBitwiseAndH */', + 'expected' => false, + ], + 'bitwise and: in param default value in closure declaration' => [ + 'testMarker' => '/* testBitwiseAndI */', + 'expected' => false, + ], + 'reference: function declared to return by reference' => [ + 'testMarker' => '/* testFunctionReturnByReference */', + 'expected' => true, + ], + 'reference: only param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceA */', + 'expected' => true, + ], + 'reference: last param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceB */', + 'expected' => true, + ], + 'reference: only param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceC */', + 'expected' => true, + ], + 'reference: last param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceD */', + 'expected' => true, + ], + 'reference: typed param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceE */', + 'expected' => true, + ], + 'reference: typed param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceF */', + 'expected' => true, + ], + 'reference: variadic param in function declaration, pass by reference' => [ + 'testMarker' => '/* testFunctionPassByReferenceG */', + 'expected' => true, + ], + 'reference: foreach value' => [ + 'testMarker' => '/* testForeachValueByReference */', + 'expected' => true, + ], + 'reference: foreach key' => [ + 'testMarker' => '/* testForeachKeyByReference */', + 'expected' => true, + ], + 'reference: keyed short array, first value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceA */', + 'expected' => true, + ], + 'reference: keyed short array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceB */', + 'expected' => true, + ], + 'reference: unkeyed short array, only value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceC */', + 'expected' => true, + ], + 'reference: unkeyed short array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceD */', + 'expected' => true, + ], + 'reference: keyed long array, first value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceE */', + 'expected' => true, + ], + 'reference: keyed long array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceF */', + 'expected' => true, + ], + 'reference: unkeyed long array, only value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceG */', + 'expected' => true, + ], + 'reference: unkeyed long array, last value, value by reference' => [ + 'testMarker' => '/* testArrayValueByReferenceH */', + 'expected' => true, + ], + 'reference: variable, assign by reference' => [ + 'testMarker' => '/* testAssignByReferenceA */', + 'expected' => true, + ], + 'reference: variable, assign by reference, spacing variation' => [ + 'testMarker' => '/* testAssignByReferenceB */', + 'expected' => true, + ], + 'reference: variable, assign by reference, concat assign' => [ + 'testMarker' => '/* testAssignByReferenceC */', + 'expected' => true, + ], + 'reference: property, assign by reference' => [ + 'testMarker' => '/* testAssignByReferenceD */', + 'expected' => true, + ], + 'reference: function return value, assign by reference' => [ + 'testMarker' => '/* testAssignByReferenceE */', + 'expected' => true, + ], + 'reference: function return value, assign by reference, null coalesce assign' => [ + 'testMarker' => '/* testAssignByReferenceF */', + 'expected' => true, + ], + 'reference: unkeyed short list, first var, assign by reference' => [ + 'testMarker' => '/* testShortListAssignByReferenceNoKeyA */', + 'expected' => true, + ], + 'reference: unkeyed short list, second var, assign by reference' => [ + 'testMarker' => '/* testShortListAssignByReferenceNoKeyB */', + 'expected' => true, + ], + 'reference: unkeyed short list, nested var, assign by reference' => [ + 'testMarker' => '/* testNestedShortListAssignByReferenceNoKey */', + 'expected' => true, + ], + 'reference: unkeyed long list, second var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceNoKeyA */', + 'expected' => true, + ], + 'reference: unkeyed long list, first nested var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceNoKeyB */', + 'expected' => true, + ], + 'reference: unkeyed long list, last nested var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceNoKeyC */', + 'expected' => true, + ], + 'reference: keyed short list, first nested var, assign by reference' => [ + 'testMarker' => '/* testNestedShortListAssignByReferenceWithKeyA */', + 'expected' => true, + ], + 'reference: keyed short list, last nested var, assign by reference' => [ + 'testMarker' => '/* testNestedShortListAssignByReferenceWithKeyB */', + 'expected' => true, + ], + 'reference: keyed long list, only var, assign by reference' => [ + 'testMarker' => '/* testLongListAssignByReferenceWithKeyA */', + 'expected' => true, + ], + 'reference: first param in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceA */', + 'expected' => true, + ], + 'reference: last param in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceB */', + 'expected' => true, + ], + 'reference: property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceC */', + 'expected' => true, + ], + 'reference: hierarchical self property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceD */', + 'expected' => true, + ], + 'reference: hierarchical parent property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceE */', + 'expected' => true, + ], + 'reference: hierarchical static property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceF */', + 'expected' => true, + ], + 'reference: static property in function call, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceG */', + 'expected' => true, + ], + 'reference: static property in function call, first with FQN, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceH */', + 'expected' => true, + ], + 'reference: static property in function call, last with FQN, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceI */', + 'expected' => true, + ], + 'reference: static property in function call, last with namespace relative name, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceJ */', + 'expected' => true, + ], + 'reference: static property in function call, last with PQN, pass by reference' => [ + 'testMarker' => '/* testPassByReferencePartiallyQualifiedName */', + 'expected' => true, + ], + 'reference: new by reference' => [ + 'testMarker' => '/* testNewByReferenceA */', + 'expected' => true, + ], + 'reference: new by reference as function call param' => [ + 'testMarker' => '/* testNewByReferenceB */', + 'expected' => true, + ], + 'reference: closure use by reference' => [ + 'testMarker' => '/* testUseByReference */', + 'expected' => true, + ], + 'reference: closure use by reference, first param, with comment' => [ + 'testMarker' => '/* testUseByReferenceWithCommentFirstParam */', + 'expected' => true, + ], + 'reference: closure use by reference, last param, with comment' => [ + 'testMarker' => '/* testUseByReferenceWithCommentSecondParam */', + 'expected' => true, + ], + 'reference: arrow fn declared to return by reference' => [ + 'testMarker' => '/* testArrowFunctionReturnByReference */', + 'expected' => true, + ], + 'bitwise and: first param default value in closure declaration' => [ + 'testMarker' => '/* testBitwiseAndExactParameterA */', + 'expected' => false, + ], + 'reference: param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceExactParameterB */', + 'expected' => true, + ], + 'reference: variadic param in closure declaration, pass by reference' => [ + 'testMarker' => '/* testPassByReferenceExactParameterC */', + 'expected' => true, + ], + 'bitwise and: last param default value in closure declaration' => [ + 'testMarker' => '/* testBitwiseAndExactParameterD */', + 'expected' => false, + ], + 'reference: typed param in arrow fn declaration, pass by reference' => [ + 'testMarker' => '/* testArrowFunctionPassByReferenceA */', + 'expected' => true, + ], + 'reference: variadic param in arrow fn declaration, pass by reference' => [ + 'testMarker' => '/* testArrowFunctionPassByReferenceB */', + 'expected' => true, + ], + 'reference: closure declared to return by reference' => [ + 'testMarker' => '/* testClosureReturnByReference */', + 'expected' => true, + ], + 'bitwise and: param default value in arrow fn declaration' => [ + 'testMarker' => '/* testBitwiseAndArrowFunctionInDefault */', + 'expected' => false, + ], + 'reference: param pass by ref in arrow function' => [ + 'testMarker' => '/* testParamPassByReference */', + 'expected' => true, + ], + 'issue-1284-short-list-directly-after-close-curly-control-structure' => [ + 'testMarker' => '/* testTokenizerIssue1284PHPCSlt280A */', + 'expected' => true, + ], + 'issue-1284-short-list-directly-after-close-curly-control-structure-second-item' => [ + 'testMarker' => '/* testTokenizerIssue1284PHPCSlt280B */', + 'expected' => true, + ], + 'issue-1284-short-array-directly-after-close-curly-control-structure' => [ + 'testMarker' => '/* testTokenizerIssue1284PHPCSlt280C */', + 'expected' => true, + ], + ]; + + }//end dataIsReference() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/AbstractFilterTestCase.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/AbstractFilterTestCase.php new file mode 100644 index 000000000..4277f8c6e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/AbstractFilterTestCase.php @@ -0,0 +1,250 @@ + + * @copyright 2023 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Filters; + +use PHP_CodeSniffer\Filters\Filter; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; +use RecursiveIteratorIterator; + +/** + * Base functionality and utilities for testing Filter classes. + */ +abstract class AbstractFilterTestCase extends TestCase +{ + + /** + * The Config object. + * + * @var \PHP_CodeSniffer\Config + */ + protected static $config; + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected static $ruleset; + + + /** + * Initialize the config and ruleset objects. + * + * @beforeClass + * + * @return void + */ + public static function initializeConfigAndRuleset() + { + self::$config = new ConfigDouble(['--extensions=php,inc/php,js,css']); + self::$ruleset = new Ruleset(self::$config); + + }//end initializeConfigAndRuleset() + + + /** + * Clean up after finished test by resetting all static properties on the Config class to their default values. + * + * Note: This is a PHPUnit cross-version compatible {@see \PHPUnit\Framework\TestCase::tearDownAfterClass()} + * method. + * + * @afterClass + * + * @return void + */ + public static function reset() + { + // Explicitly trigger __destruct() on the ConfigDouble to reset the Config statics. + // The explicit method call prevents potential stray test-local references to the $config object + // preventing the destructor from running the clean up (which without stray references would be + // automagically triggered when `self::$phpcsFile` is reset, but we can't definitively rely on that). + if (isset(self::$config) === true) { + self::$config->__destruct(); + } + + }//end reset() + + + /** + * Helper method to retrieve a mock object for a Filter class. + * + * The `setMethods()` method was silently deprecated in PHPUnit 9 and removed in PHPUnit 10. + * + * Note: direct access to the `getMockBuilder()` method is soft deprecated as of PHPUnit 10, + * and expected to be hard deprecated in PHPUnit 11 and removed in PHPUnit 12. + * Dealing with that is something for a later iteration of the test suite. + * + * @param string $className Fully qualified name of the class under test. + * @param array $constructorArgs Optional. Array of parameters to pass to the class constructor. + * @param array|null $methodsToMock Optional. The methods to mock in the class under test. + * Needed for PHPUnit cross-version support as PHPUnit 4.x does + * not have a `setMethodsExcept()` method yet. + * If not passed, no methods will be replaced. + * + * @return \PHPUnit\Framework\MockObject\MockObject + */ + protected function getMockedClass($className, array $constructorArgs=[], $methodsToMock=null) + { + $mockedObj = $this->getMockBuilder($className); + + if (method_exists($mockedObj, 'onlyMethods') === true) { + // PHPUnit 8+. + if (is_array($methodsToMock) === true) { + return $mockedObj + ->setConstructorArgs($constructorArgs) + ->onlyMethods($methodsToMock) + ->getMock(); + } + + return $mockedObj->getMock() + ->setConstructorArgs($constructorArgs); + } + + // PHPUnit < 8. + return $mockedObj + ->setConstructorArgs($constructorArgs) + ->setMethods($methodsToMock) + ->getMock(); + + }//end getMockedClass() + + + /** + * Retrieve an array of files which were accepted by a filter. + * + * @param \PHP_CodeSniffer\Filters\Filter $filter The Filter object under test. + * + * @return array + */ + protected function getFilteredResultsAsArray(Filter $filter) + { + $iterator = new RecursiveIteratorIterator($filter); + $files = []; + foreach ($iterator as $file) { + $files[] = $file; + } + + return $files; + + }//end getFilteredResultsAsArray() + + + /** + * Retrieve the basedir to use for tests using the `getFakeFileList()` method. + * + * @return string + */ + protected static function getBaseDir() + { + return dirname(dirname(dirname(__DIR__))); + + }//end getBaseDir() + + + /** + * Retrieve a file list containing a range of paths for testing purposes. + * + * This list **must** contain files which exist in this project (well, except for some which don't exist + * purely for testing purposes), as `realpath()` is used in the logic under test and `realpath()` will + * return `false` for any non-existent files, which will automatically filter them out before + * we get to the code under test. + * + * Note this list does not include `.` and `..` as \PHP_CodeSniffer\Files\FileList uses `SKIP_DOTS`. + * + * @return array + */ + protected static function getFakeFileList() + { + $basedir = self::getBaseDir(); + return [ + $basedir.'/.gitignore', + $basedir.'/.yamllint.yml', + $basedir.'/phpcs.xml', + $basedir.'/phpcs.xml.dist', + $basedir.'/autoload.php', + $basedir.'/bin', + $basedir.'/bin/phpcs', + $basedir.'/bin/phpcs.bat', + $basedir.'/scripts', + $basedir.'/scripts/build-phar.php', + $basedir.'/src', + $basedir.'/src/WillNotExist.php', + $basedir.'/src/WillNotExist.bak', + $basedir.'/src/WillNotExist.orig', + $basedir.'/src/Ruleset.php', + $basedir.'/src/Generators', + $basedir.'/src/Generators/Markdown.php', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Generic', + $basedir.'/src/Standards/Generic/Docs', + $basedir.'/src/Standards/Generic/Docs/Classes', + $basedir.'/src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml', + $basedir.'/src/Standards/Generic/Sniffs', + $basedir.'/src/Standards/Generic/Sniffs/Classes', + $basedir.'/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + $basedir.'/src/Standards/Generic/Tests', + $basedir.'/src/Standards/Generic/Tests/Classes', + $basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc', + // Will rarely exist when running the tests. + $basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc.bak', + $basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.2.inc', + $basedir.'/src/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.php', + $basedir.'/src/Standards/Squiz', + $basedir.'/src/Standards/Squiz/Docs', + $basedir.'/src/Standards/Squiz/Docs/WhiteSpace', + $basedir.'/src/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml', + $basedir.'/src/Standards/Squiz/Sniffs', + $basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace', + $basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php', + $basedir.'/src/Standards/Squiz/Tests', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php', + ]; + + }//end getFakeFileList() + + + /** + * Translate Linux paths to Windows paths, when necessary. + * + * These type of tests should be able to run and pass on both *nix as well as Windows + * based dev systems. This method is a helper to allow for this. + * + * @param array $paths A single or multi-dimensional array containing + * file paths. + * + * @return array + */ + protected static function mapPathsToRuntimeOs(array $paths) + { + if (DIRECTORY_SEPARATOR !== '\\') { + return $paths; + } + + foreach ($paths as $key => $value) { + if (is_string($value) === true) { + $paths[$key] = strtr($value, '/', '\\\\'); + } else if (is_array($value) === true) { + $paths[$key] = self::mapPathsToRuntimeOs($value); + } + } + + return $paths; + + }//end mapPathsToRuntimeOs() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php new file mode 100644 index 000000000..8d622061d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.php @@ -0,0 +1,110 @@ + + * @author Juliette Reinders Folmer + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Filters\Filter; + +use PHP_CodeSniffer\Filters\Filter; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHP_CodeSniffer\Tests\Core\Filters\AbstractFilterTestCase; +use RecursiveArrayIterator; + +/** + * Tests for the \PHP_CodeSniffer\Filters\Filter::accept method. + * + * @covers \PHP_CodeSniffer\Filters\Filter + */ +final class AcceptTest extends AbstractFilterTestCase +{ + + + /** + * Initialize the config and ruleset objects based on the `AcceptTest.xml` ruleset file. + * + * @beforeClass + * + * @return void + */ + public static function initializeConfigAndRuleset() + { + $standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + self::$config = new ConfigDouble(["--standard=$standard", '--ignore=*/somethingelse/*']); + self::$ruleset = new Ruleset(self::$config); + + }//end initializeConfigAndRuleset() + + + /** + * Test filtering a file list for excluded paths. + * + * @param array $inputPaths List of file paths to be filtered. + * @param array $expectedOutput Expected filtering result. + * + * @dataProvider dataExcludePatterns + * + * @return void + */ + public function testExcludePatterns($inputPaths, $expectedOutput) + { + $fakeDI = new RecursiveArrayIterator($inputPaths); + $filter = new Filter($fakeDI, '/', self::$config, self::$ruleset); + + $this->assertEquals($expectedOutput, $this->getFilteredResultsAsArray($filter)); + + }//end testExcludePatterns() + + + /** + * Data provider. + * + * @see testExcludePatterns + * + * @return array>> + */ + public static function dataExcludePatterns() + { + $testCases = [ + // Test top-level exclude patterns. + 'Non-sniff specific path based excludes from ruleset and command line are respected and don\'t filter out too much' => [ + 'inputPaths' => [ + '/path/to/src/Main.php', + '/path/to/src/Something/Main.php', + '/path/to/src/Somethingelse/Main.php', + '/path/to/src/SomethingelseEvenLonger/Main.php', + '/path/to/src/Other/Main.php', + ], + 'expectedOutput' => [ + '/path/to/src/Main.php', + '/path/to/src/SomethingelseEvenLonger/Main.php', + ], + ], + + // Test ignoring standard/sniff specific exclude patterns. + 'Filter should not act on standard/sniff specific exclude patterns' => [ + 'inputPaths' => [ + '/path/to/src/generic-project/Main.php', + '/path/to/src/generic/Main.php', + '/path/to/src/anything-generic/Main.php', + ], + 'expectedOutput' => [ + '/path/to/src/generic-project/Main.php', + '/path/to/src/generic/Main.php', + '/path/to/src/anything-generic/Main.php', + ], + ], + ]; + + // Allow these tests to work on Windows as well. + return self::mapPathsToRuntimeOs($testCases); + + }//end dataExcludePatterns() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml new file mode 100644 index 000000000..3d3e1de08 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/Filter/AcceptTest.xml @@ -0,0 +1,16 @@ + + + Ruleset to test the filtering based on exclude patterns. + + + */something/* + + */Other/Main\.php$ + + + + /anything/* + + /YetAnother/Main\.php + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitModifiedTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitModifiedTest.php new file mode 100644 index 000000000..2fe894096 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitModifiedTest.php @@ -0,0 +1,268 @@ + + * @copyright 2023 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Filters; + +use PHP_CodeSniffer\Filters\GitModified; +use PHP_CodeSniffer\Tests\Core\Filters\AbstractFilterTestCase; +use RecursiveArrayIterator; +use ReflectionMethod; + +/** + * Tests for the \PHP_CodeSniffer\Filters\GitModified class. + * + * @covers \PHP_CodeSniffer\Filters\GitModified + */ +final class GitModifiedTest extends AbstractFilterTestCase +{ + + + /** + * Test filtering a file list for excluded paths. + * + * @return void + */ + public function testFileNamePassesAsBasePathWillTranslateToDirname() + { + $rootFile = self::getBaseDir().'/autoload.php'; + + $fakeDI = new RecursiveArrayIterator(self::getFakeFileList()); + $constructorArgs = [ + $fakeDI, + $rootFile, + self::$config, + self::$ruleset, + ]; + $mockObj = $this->getMockedClass('PHP_CodeSniffer\Filters\GitModified', $constructorArgs, ['exec']); + + $mockObj->expects($this->once()) + ->method('exec') + ->willReturn(['autoload.php']); + + $this->assertEquals([$rootFile], $this->getFilteredResultsAsArray($mockObj)); + + }//end testFileNamePassesAsBasePathWillTranslateToDirname() + + + /** + * Test filtering a file list for excluded paths. + * + * @param array $inputPaths List of file paths to be filtered. + * @param array $outputGitModified Simulated "git modified" output. + * @param array $expectedOutput Expected filtering result. + * + * @dataProvider dataAcceptOnlyGitModified + * + * @return void + */ + public function testAcceptOnlyGitModified($inputPaths, $outputGitModified, $expectedOutput) + { + $fakeDI = new RecursiveArrayIterator($inputPaths); + $constructorArgs = [ + $fakeDI, + self::getBaseDir(), + self::$config, + self::$ruleset, + ]; + $mockObj = $this->getMockedClass('PHP_CodeSniffer\Filters\GitModified', $constructorArgs, ['exec']); + + $mockObj->expects($this->once()) + ->method('exec') + ->willReturn($outputGitModified); + + $this->assertEquals($expectedOutput, $this->getFilteredResultsAsArray($mockObj)); + + }//end testAcceptOnlyGitModified() + + + /** + * Data provider. + * + * @see testAcceptOnlyGitModified + * + * @return array>> + */ + public static function dataAcceptOnlyGitModified() + { + $basedir = self::getBaseDir(); + $fakeFileList = self::getFakeFileList(); + + $testCases = [ + 'no files marked as git modified' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [], + 'expectedOutput' => [], + ], + + 'files marked as git modified which don\'t actually exist' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [ + 'src/WillNotExist.php', + 'src/WillNotExist.bak', + 'src/WillNotExist.orig', + ], + 'expectedOutput' => [], + ], + + 'single file marked as git modified - file in root dir' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [ + 'autoload.php', + ], + 'expectedOutput' => [ + $basedir.'/autoload.php', + ], + ], + 'single file marked as git modified - file in sub dir' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [ + 'src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + 'expectedOutput' => [ + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Generic', + $basedir.'/src/Standards/Generic/Sniffs', + $basedir.'/src/Standards/Generic/Sniffs/Classes', + $basedir.'/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + ], + + 'multiple files marked as git modified, none valid for scan' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [ + '.gitignore', + 'phpcs.xml.dist', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed', + ], + 'expectedOutput' => [ + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Squiz', + $basedir.'/src/Standards/Squiz/Tests', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace', + ], + ], + + 'multiple files marked as git modified, only one file valid for scan' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [ + '.gitignore', + 'src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml', + 'src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + 'expectedOutput' => [ + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Generic', + $basedir.'/src/Standards/Generic/Docs', + $basedir.'/src/Standards/Generic/Docs/Classes', + $basedir.'/src/Standards/Generic/Sniffs', + $basedir.'/src/Standards/Generic/Sniffs/Classes', + $basedir.'/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + ], + + 'multiple files marked as git modified, multiple files valid for scan' => [ + 'inputPaths' => $fakeFileList, + 'outputGitModified' => [ + '.yamllint.yml', + 'autoload.php', + 'src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php', + ], + 'expectedOutput' => [ + $basedir.'/autoload.php', + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Squiz', + $basedir.'/src/Standards/Squiz/Sniffs', + $basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace', + $basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php', + $basedir.'/src/Standards/Squiz/Tests', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php', + ], + ], + ]; + + return $testCases; + + }//end dataAcceptOnlyGitModified() + + + /** + * Test filtering a file list for excluded paths. + * + * @param string $cmd Command to run. + * @param array $expected Expected return value. + * + * @dataProvider dataExecAlwaysReturnsArray + * + * @return void + */ + public function testExecAlwaysReturnsArray($cmd, $expected) + { + if (is_dir(__DIR__.'/../../../.git') === false) { + $this->markTestSkipped('Not a git repository'); + } + + $fakeDI = new RecursiveArrayIterator(self::getFakeFileList()); + $filter = new GitModified($fakeDI, '/', self::$config, self::$ruleset); + + $reflMethod = new ReflectionMethod($filter, 'exec'); + $reflMethod->setAccessible(true); + $result = $reflMethod->invoke($filter, $cmd); + + $this->assertSame($expected, $result); + + }//end testExecAlwaysReturnsArray() + + + /** + * Data provider. + * + * @see testExecAlwaysReturnsArray + * + * {@internal Missing: test with a command which yields a `false` return value. + * JRF: I've not managed to find a command which does so, let alone one, which then + * doesn't have side-effects of uncatchable output while running the tests.} + * + * @return array>> + */ + public static function dataExecAlwaysReturnsArray() + { + return [ + 'valid command which won\'t have any output unless files in the bin dir have been modified' => [ + // Largely using the command used in the filter, but only checking the bin dir. + // This should prevent the test unexpectedly failing during local development (in most cases). + 'cmd' => 'git ls-files -o -m --exclude-standard -- '.escapeshellarg(self::getBaseDir().'/bin'), + 'expected' => [], + ], + 'valid command which will have output' => [ + 'cmd' => 'git ls-files --exclude-standard -- '.escapeshellarg(self::getBaseDir().'/bin'), + 'expected' => [ + 'bin/phpcbf', + 'bin/phpcbf.bat', + 'bin/phpcs', + 'bin/phpcs.bat', + ], + ], + ]; + + }//end dataExecAlwaysReturnsArray() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitStagedTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitStagedTest.php new file mode 100644 index 000000000..0da18af9a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Filters/GitStagedTest.php @@ -0,0 +1,268 @@ + + * @copyright 2023 PHPCSStandards Contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Filters; + +use PHP_CodeSniffer\Filters\GitStaged; +use PHP_CodeSniffer\Tests\Core\Filters\AbstractFilterTestCase; +use RecursiveArrayIterator; +use ReflectionMethod; + +/** + * Tests for the \PHP_CodeSniffer\Filters\GitStaged class. + * + * @covers \PHP_CodeSniffer\Filters\GitStaged + */ +final class GitStagedTest extends AbstractFilterTestCase +{ + + + /** + * Test filtering a file list for excluded paths. + * + * @return void + */ + public function testFileNamePassesAsBasePathWillTranslateToDirname() + { + $rootFile = self::getBaseDir().'/autoload.php'; + + $fakeDI = new RecursiveArrayIterator(self::getFakeFileList()); + $constructorArgs = [ + $fakeDI, + $rootFile, + self::$config, + self::$ruleset, + ]; + $mockObj = $this->getMockedClass('PHP_CodeSniffer\Filters\GitStaged', $constructorArgs, ['exec']); + + $mockObj->expects($this->once()) + ->method('exec') + ->willReturn(['autoload.php']); + + $this->assertEquals([$rootFile], $this->getFilteredResultsAsArray($mockObj)); + + }//end testFileNamePassesAsBasePathWillTranslateToDirname() + + + /** + * Test filtering a file list for excluded paths. + * + * @param array $inputPaths List of file paths to be filtered. + * @param array $outputGitStaged Simulated "git staged" output. + * @param array $expectedOutput Expected filtering result. + * + * @dataProvider dataAcceptOnlyGitStaged + * + * @return void + */ + public function testAcceptOnlyGitStaged($inputPaths, $outputGitStaged, $expectedOutput) + { + $fakeDI = new RecursiveArrayIterator($inputPaths); + $constructorArgs = [ + $fakeDI, + self::getBaseDir(), + self::$config, + self::$ruleset, + ]; + $mockObj = $this->getMockedClass('PHP_CodeSniffer\Filters\GitStaged', $constructorArgs, ['exec']); + + $mockObj->expects($this->once()) + ->method('exec') + ->willReturn($outputGitStaged); + + $this->assertEquals($expectedOutput, $this->getFilteredResultsAsArray($mockObj)); + + }//end testAcceptOnlyGitStaged() + + + /** + * Data provider. + * + * @see testAcceptOnlyGitStaged + * + * @return array>> + */ + public static function dataAcceptOnlyGitStaged() + { + $basedir = self::getBaseDir(); + $fakeFileList = self::getFakeFileList(); + + $testCases = [ + 'no files marked as git modified' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [], + 'expectedOutput' => [], + ], + + 'files marked as git modified which don\'t actually exist' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [ + 'src/WillNotExist.php', + 'src/WillNotExist.bak', + 'src/WillNotExist.orig', + ], + 'expectedOutput' => [], + ], + + 'single file marked as git modified - file in root dir' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [ + 'autoload.php', + ], + 'expectedOutput' => [ + $basedir.'/autoload.php', + ], + ], + 'single file marked as git modified - file in sub dir' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [ + 'src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + 'expectedOutput' => [ + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Generic', + $basedir.'/src/Standards/Generic/Sniffs', + $basedir.'/src/Standards/Generic/Sniffs/Classes', + $basedir.'/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + ], + + 'multiple files marked as git modified, none valid for scan' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [ + '.gitignore', + 'phpcs.xml.dist', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed', + ], + 'expectedOutput' => [ + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Squiz', + $basedir.'/src/Standards/Squiz/Tests', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace', + ], + ], + + 'multiple files marked as git modified, only one file valid for scan' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [ + '.gitignore', + 'src/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml', + 'src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + 'expectedOutput' => [ + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Generic', + $basedir.'/src/Standards/Generic/Docs', + $basedir.'/src/Standards/Generic/Docs/Classes', + $basedir.'/src/Standards/Generic/Sniffs', + $basedir.'/src/Standards/Generic/Sniffs/Classes', + $basedir.'/src/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php', + ], + ], + + 'multiple files marked as git modified, multiple files valid for scan' => [ + 'inputPaths' => $fakeFileList, + 'outputGitStaged' => [ + '.yamllint.yml', + 'autoload.php', + 'src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc.fixed', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js.fixed', + 'src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php', + ], + 'expectedOutput' => [ + $basedir.'/autoload.php', + $basedir.'/src', + $basedir.'/src/Standards', + $basedir.'/src/Standards/Squiz', + $basedir.'/src/Standards/Squiz/Sniffs', + $basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace', + $basedir.'/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php', + $basedir.'/src/Standards/Squiz/Tests', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.1.inc', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js', + $basedir.'/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php', + ], + ], + ]; + + return $testCases; + + }//end dataAcceptOnlyGitStaged() + + + /** + * Test filtering a file list for excluded paths. + * + * @param string $cmd Command to run. + * @param array $expected Expected return value. + * + * @dataProvider dataExecAlwaysReturnsArray + * + * @return void + */ + public function testExecAlwaysReturnsArray($cmd, $expected) + { + if (is_dir(__DIR__.'/../../../.git') === false) { + $this->markTestSkipped('Not a git repository'); + } + + $fakeDI = new RecursiveArrayIterator(self::getFakeFileList()); + $filter = new GitStaged($fakeDI, '/', self::$config, self::$ruleset); + + $reflMethod = new ReflectionMethod($filter, 'exec'); + $reflMethod->setAccessible(true); + $result = $reflMethod->invoke($filter, $cmd); + + $this->assertSame($expected, $result); + + }//end testExecAlwaysReturnsArray() + + + /** + * Data provider. + * + * @see testExecAlwaysReturnsArray + * + * {@internal Missing: test with a command which yields a `false` return value. + * JRF: I've not managed to find a command which does so, let alone one, which then + * doesn't have side-effects of uncatchable output while running the tests.} + * + * @return array>> + */ + public static function dataExecAlwaysReturnsArray() + { + return [ + 'valid command which won\'t have any output unless files in the bin dir have been modified & staged' => [ + // Largely using the command used in the filter, but only checking the bin dir. + // This should prevent the test unexpectedly failing during local development (in most cases). + 'cmd' => 'git diff --cached --name-only -- '.escapeshellarg(self::getBaseDir().'/bin'), + 'expected' => [], + ], + 'valid command which will have output' => [ + 'cmd' => 'git ls-files --exclude-standard -- '.escapeshellarg(self::getBaseDir().'/bin'), + 'expected' => [ + 'bin/phpcbf', + 'bin/phpcbf.bat', + 'bin/phpcs', + 'bin/phpcs.bat', + ], + ], + ]; + + }//end dataExecAlwaysReturnsArray() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.diff b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.diff new file mode 100644 index 000000000..b9a217ed2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.diff @@ -0,0 +1,10 @@ +--- tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.inc ++++ PHP_CodeSniffer +@@ -5,7 +5,3 @@ + if ($var) { + echo 'This line is tab indented'; + } +- +- +- +- diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.inc new file mode 100644 index 000000000..2e65b2b50 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Fixer/Fixtures/GenerateDiffTest-BlankLinesAtEnd.inc @@ -0,0 +1,11 @@ + + * @copyright 2024 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Fixer; + +use PHP_CodeSniffer\Files\LocalFile; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Tests for diff generation. + * + * Note: these tests are specifically about the Fixer::generateDiff() method and do not + * test running the fixer itself, nor generating a diff based on a fixer run. + * + * @covers PHP_CodeSniffer\Fixer::generateDiff + * @group Windows + */ +final class GenerateDiffTest extends TestCase +{ + + /** + * A \PHP_CodeSniffer\Files\File object to compare the files against. + * + * @var \PHP_CodeSniffer\Files\LocalFile + */ + private static $phpcsFile; + + + /** + * Initialize an \PHP_CodeSniffer\Files\File object with code. + * + * Things to take note of in the code snippet used for these tests: + * - Line endings are \n. + * - Tab indent. + * - Trailing whitespace. + * + * Also note that the Config object is deliberately created without a `tabWidth` setting to + * prevent doing tab replacement when parsing the file. This is to allow for testing a + * diff with tabs vs spaces (which wouldn't yield a diff if tabs had already been replaced). + * + * @beforeClass + * + * @return void + */ + public static function initializeFile() + { + $config = new ConfigDouble(); + $ruleset = new Ruleset($config); + + self::$phpcsFile = new LocalFile(__DIR__.'/Fixtures/GenerateDiffTest.inc', $ruleset, $config); + self::$phpcsFile->parse(); + self::$phpcsFile->fixer->startFile(self::$phpcsFile); + + }//end initializeFile() + + + /** + * Test generating a diff on the file object itself. + * + * @return void + */ + public function testGenerateDiffNoFile() + { + $diff = self::$phpcsFile->fixer->generateDiff(null, false); + + $this->assertSame('', $diff); + + }//end testGenerateDiffNoFile() + + + /** + * Test generating a diff between a PHPCS File object and a file on disk. + * + * @param string $filePath The path to the file to compare the File object against. + * + * @dataProvider dataGenerateDiff + * + * @return void + */ + public function testGenerateDiff($filePath) + { + $diff = self::$phpcsFile->fixer->generateDiff($filePath, false); + + // Allow for the tests to pass on Windows too. + $diff = str_replace('--- tests\Core\Fixer/', '--- tests/Core/Fixer/', $diff); + + $expectedDiffFile = str_replace('.inc', '.diff', $filePath); + + $this->assertStringEqualsFile($expectedDiffFile, $diff); + + }//end testGenerateDiff() + + + /** + * Data provider. + * + * @see testGenerateDiff() + * + * @return array> + */ + public static function dataGenerateDiff() + { + return [ + 'no difference' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-NoDiff.inc', + ], + 'line removed' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-LineRemoved.inc', + ], + 'line added' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-LineAdded.inc', + ], + 'var name changed' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-VarNameChanged.inc', + ], + 'trailing whitespace removed' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-NoTrailingWhitespace.inc', + ], + 'tab replaced with spaces' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-TabsToSpaces.inc', + ], + 'blank lines at start of file' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-BlankLinesAtStart.inc', + ], + 'whitespace diff at start of file' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-WhiteSpaceAtStart.inc', + ], + 'blank lines at end of file' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-BlankLinesAtEnd.inc', + ], + 'whitespace diff at end of file' => [ + 'filePath' => __DIR__.'/Fixtures/GenerateDiffTest-WhiteSpaceAtEnd.inc', + ], + ]; + + }//end dataGenerateDiff() + + + /** + * Test generating a diff between a PHPCS File object and a file on disk and colourizing the output. + * + * @return void + */ + public function testGenerateDiffColoured() + { + $expected = "\033[31m--- tests/Core/Fixer/Fixtures/GenerateDiffTest-VarNameChanged.inc\033[0m".PHP_EOL; + $expected .= "\033[32m+++ PHP_CodeSniffer\033[0m".PHP_EOL; + $expected .= '@@ -1,7 +1,7 @@'.PHP_EOL; + $expected .= ' fixer->generateDiff($filePath); + + // Allow for the tests to pass on Windows too. + $diff = str_replace('--- tests\Core\Fixer/', '--- tests/Core/Fixer/', $diff); + + $this->assertSame($expected, $diff); + + }//end testGenerateDiffColoured() + + + /** + * Test generating a diff between a PHPCS File object using *nix line endings and a file on disk + * using Windows line endings. + * + * The point of this test is to verify that all lines are marked as having a difference. + * The actual lines endings used in the diff shown to the end-user are not relevant for this + * test. + * As the "diff" command is finicky with what type of line endings are used when the only + * difference on a line is the line ending, the test normalizes the line endings of the + * received diff before testing it. + * + * @return void + */ + public function testGenerateDiffDifferentLineEndings() + { + // By the looks of it, if the only diff between two files is line endings, the + // diff generated by the *nix "diff" command will always contain *nix line endings. + $expected = '--- tests/Core/Fixer/Fixtures/GenerateDiffTest-WindowsLineEndings.inc'."\n"; + $expected .= '+++ PHP_CodeSniffer'."\n"; + $expected .= '@@ -1,7 +1,7 @@'."\n"; + $expected .= '-fixer->generateDiff($filePath, false); + + // Allow for the tests to pass on Windows too. + $diff = str_replace('--- tests\Core\Fixer/', '--- tests/Core/Fixer/', $diff); + + // Normalize line endings of the diff. + $diff = preg_replace('`\R`', "\n", $diff); + + $this->assertSame($expected, $diff); + + }//end testGenerateDiffDifferentLineEndings() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputEmpty.txt b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputEmpty.txt new file mode 100644 index 000000000..e69de29bb diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html new file mode 100644 index 000000000..060de7aa6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.html @@ -0,0 +1,78 @@ + + + GeneratorTest Coding Standards + + + +

    GeneratorTest Coding Standards

    +

    Table of Contents

    +
      +
    +
    + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md new file mode 100644 index 000000000..ece269218 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputNoDocs.md @@ -0,0 +1,2 @@ +# GeneratorTest Coding Standard +Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer) diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html new file mode 100644 index 000000000..772d3861e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.html @@ -0,0 +1,82 @@ + + + GeneratorTest Coding Standards + + + +

    GeneratorTest Coding Standards

    +

    Table of Contents

    + + +

    One Standard Block, No Code

    +

    Documentation contains one standard block and no code comparison.

    +
    + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md new file mode 100644 index 000000000..f8deb0ce2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.md @@ -0,0 +1,5 @@ +# GeneratorTest Coding Standard + +## One Standard Block, No Code +Documentation contains one standard block and no code comparison. +Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer) diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt new file mode 100644 index 000000000..75bbdcb00 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputOneDoc.txt @@ -0,0 +1,7 @@ + +-------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, NO CODE | +-------------------------------------------------------------- + +Documentation contains one standard block and no code comparison. + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html new file mode 100644 index 000000000..db1f3a9a9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.html @@ -0,0 +1,191 @@ + + + GeneratorTest Coding Standards + + + +

    GeneratorTest Coding Standards

    +

    Table of Contents

    + + +

    No Content

    +
    +

    Code Comparison Only, Missing Standard Block

    + + + + + + + + + +
    Valid: Lorem ipsum dolor sit amet.Invalid: Maecenas non rutrum dolor.
    class Code {}class Comparison {}
    +
    +

    One Standard Block, Code Comparison

    +

    Documentation contains one standard block and one code comparison.

    + + + + + + + + + +
    Valid: Lorem ipsum dolor sit amet.Invalid: Maecenas non rutrum dolor.
    class Code {}class Comparison {}
    +
    +

    One Standard Block, No Code

    +

    Documentation contains one standard block and no code comparison.

    +
    +

    One Standard Block, Two Code Comparisons

    +

    Documentation contains one standard block and two code comparisons.

    + + + + + + + + + +
    Valid: Etiam commodo magna at vestibulum blandit.Invalid: Vivamus lacinia ante velit.
    class Code {}class Comparison {}
    + + + + + + + + + +
    Valid: Pellentesque nisi neque.Invalid: Mauris dictum metus quis maximus pharetra.
    $one = 10;$a = 10;
    +
    +

    Two Standard Blocks, No Code

    +

    This is standard block one.

    +

    This is standard block two.

    +
    +

    Two Standard Blocks, One Code Comparison

    +

    This is standard block one.

    + + + + + + + + + +
    Valid: Vestibulum et orci condimentum.Invalid: Donec in nisl ut tortor convallis interdum.
    class Code {}class Comparison {}
    +

    This is standard block two.

    +
    +

    Two Standard Blocks, Three Code Comparisons

    +

    This is standard block one.

    + + + + + + + + + +
    Valid: Vestibulum et orci condimentum.Invalid: Donec in nisl ut tortor convallis interdum.
    class Code {}class Comparison {}
    +

    This is standard block two.

    + + + + + + + + + +
    Valid: Pellentesque nisi neque.Invalid: Mauris dictum metus quis maximus pharetra.
    $one = 10;$a = 10;
    + + + + + + + + + +
    Valid: Quisque sagittis nisi vitae.Invalid: Morbi ac libero vitae lorem.
    echo $foo;print $foo;
    +
    + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md new file mode 100644 index 000000000..d613df295 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.md @@ -0,0 +1,171 @@ +# GeneratorTest Coding Standard + +## No Content + +## Code Comparison Only, Missing Standard Block + + + + + + + + + +
    Valid: Lorem ipsum dolor sit amet.Invalid: Maecenas non rutrum dolor.
    + + class Code {} + + + + class Comparison {} + +
    + +## One Standard Block, Code Comparison +Documentation contains one standard block and one code comparison. + + + + + + + + + +
    Valid: Lorem ipsum dolor sit amet.Invalid: Maecenas non rutrum dolor.
    + + class Code {} + + + + class Comparison {} + +
    + +## One Standard Block, No Code +Documentation contains one standard block and no code comparison. + +## One Standard Block, Two Code Comparisons +Documentation contains one standard block and two code comparisons. + + + + + + + + + +
    Valid: Etiam commodo magna at vestibulum blandit.Invalid: Vivamus lacinia ante velit.
    + + class Code {} + + + + class Comparison {} + +
    + + + + + + + + + +
    Valid: Pellentesque nisi neque.Invalid: Mauris dictum metus quis maximus pharetra.
    + + $one = 10; + + + + $a = 10; + +
    + +## Two Standard Blocks, No Code +This is standard block one. +This is standard block two. + +## Two Standard Blocks, One Code Comparison +This is standard block one. + + + + + + + + + +
    Valid: Vestibulum et orci condimentum.Invalid: Donec in nisl ut tortor convallis interdum.
    + + class Code {} + + + + class Comparison {} + +
    +This is standard block two. + +## Two Standard Blocks, Three Code Comparisons +This is standard block one. + + + + + + + + + +
    Valid: Vestibulum et orci condimentum.Invalid: Donec in nisl ut tortor convallis interdum.
    + + class Code {} + + + + class Comparison {} + +
    +This is standard block two. + + + + + + + + + +
    Valid: Pellentesque nisi neque.Invalid: Mauris dictum metus quis maximus pharetra.
    + + $one = 10; + + + + $a = 10; + +
    + + + + + + + + + +
    Valid: Quisque sagittis nisi vitae.Invalid: Morbi ac libero vitae lorem.
    + + echo $foo; + + + + print $foo; + +
    +Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer) diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt new file mode 100644 index 000000000..dcb404eec --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Expectations/ExpectedOutputStructureDocs.txt @@ -0,0 +1,111 @@ + +--------------------------------------------- +| GENERATORTEST CODING STANDARD: NO CONTENT | +--------------------------------------------- + + +------------------------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: CODE COMPARISON ONLY, MISSING STANDARD BLOCK | +------------------------------------------------------------------------------- + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Lorem ipsum dolor sit amet. | Invalid: Maecenas non rutrum dolor. | +---------------------------------------------------------------------------------------------------- +| class Code {} | class Comparison {} | +---------------------------------------------------------------------------------------------------- + + +---------------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, CODE COMPARISON | +---------------------------------------------------------------------- + +Documentation contains one standard block and one code comparison. + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Lorem ipsum dolor sit amet. | Invalid: Maecenas non rutrum dolor. | +---------------------------------------------------------------------------------------------------- +| class Code {} | class Comparison {} | +---------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, NO CODE | +-------------------------------------------------------------- + +Documentation contains one standard block and no code comparison. + + +--------------------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: ONE STANDARD BLOCK, TWO CODE COMPARISONS | +--------------------------------------------------------------------------- + +Documentation contains one standard block and two code comparisons. + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Etiam commodo magna at vestibulum | Invalid: Vivamus lacinia ante velit. | +| blandit. | | +---------------------------------------------------------------------------------------------------- +| class Code {} | class Comparison {} | +---------------------------------------------------------------------------------------------------- + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Pellentesque nisi neque. | Invalid: Mauris dictum metus quis maximus | +| | pharetra. | +---------------------------------------------------------------------------------------------------- +| $one = 10; | $a = 10; | +---------------------------------------------------------------------------------------------------- + + +--------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: TWO STANDARD BLOCKS, NO CODE | +--------------------------------------------------------------- + +This is standard block one. + +This is standard block two. + + +--------------------------------------------------------------------------- +| GENERATORTEST CODING STANDARD: TWO STANDARD BLOCKS, ONE CODE COMPARISON | +--------------------------------------------------------------------------- + +This is standard block one. + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Vestibulum et orci condimentum. | Invalid: Donec in nisl ut tortor convallis | +| | interdum. | +---------------------------------------------------------------------------------------------------- +| class Code {} | class Comparison {} | +---------------------------------------------------------------------------------------------------- + +This is standard block two. + + +------------------------------------------------------------------------------ +| GENERATORTEST CODING STANDARD: TWO STANDARD BLOCKS, THREE CODE COMPARISONS | +------------------------------------------------------------------------------ + +This is standard block one. + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Vestibulum et orci condimentum. | Invalid: Donec in nisl ut tortor convallis | +| | interdum. | +---------------------------------------------------------------------------------------------------- +| class Code {} | class Comparison {} | +---------------------------------------------------------------------------------------------------- + +This is standard block two. + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Pellentesque nisi neque. | Invalid: Mauris dictum metus quis maximus | +| | pharetra. | +---------------------------------------------------------------------------------------------------- +| $one = 10; | $a = 10; | +---------------------------------------------------------------------------------------------------- + +----------------------------------------- CODE COMPARISON ------------------------------------------ +| Valid: Quisque sagittis nisi vitae. | Invalid: Morbi ac libero vitae lorem. | +---------------------------------------------------------------------------------------------------- +| echo $foo; | print $foo; | +---------------------------------------------------------------------------------------------------- + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/HTMLDouble.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/HTMLDouble.php new file mode 100644 index 000000000..920372408 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/HTMLDouble.php @@ -0,0 +1,40 @@ +'; + echo 'Documentation generated on #REDACTED#'; + echo ' by PHP_CodeSniffer #VERSION#'; + echo '
    '.PHP_EOL; + echo ' '.PHP_EOL; + echo ''.PHP_EOL; + } + + /** + * Print the _real_ footer of the HTML page. + * + * @return void + */ + public function printRealFooter() + { + parent::printFooter(); + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/MarkdownDouble.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/MarkdownDouble.php new file mode 100644 index 000000000..6f51f3ec4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/MarkdownDouble.php @@ -0,0 +1,36 @@ +getTitle($doc), PHP_EOL; + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml new file mode 100644 index 000000000..83afee8e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoContentStandard.xml @@ -0,0 +1,2 @@ + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml new file mode 100644 index 000000000..ca8290f1b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/NoDocumentationElementStandard.xml @@ -0,0 +1,2 @@ + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneCodeComparisonNoStandardStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneCodeComparisonNoStandardStandard.xml new file mode 100644 index 000000000..c2af9098a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneCodeComparisonNoStandardStandard.xml @@ -0,0 +1,14 @@ + + + + class Code {} + ]]> + + + class Comparison {} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml new file mode 100644 index 000000000..c3ce35cd7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockCodeComparisonStandard.xml @@ -0,0 +1,19 @@ + + + + + + + class Code {} + ]]> + + + class Comparison {} + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml new file mode 100644 index 000000000..fc014949e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockNoCodeStandard.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml new file mode 100644 index 000000000..19559e672 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/OneStandardBlockTwoCodeComparisonsStandard.xml @@ -0,0 +1,31 @@ + + + + + + + class Code {} + ]]> + + + class Comparison {} + ]]> + + + + + $one = 10; + ]]> + + + $a = 10; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml new file mode 100644 index 000000000..f5f621ecd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksNoCodeStandard.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml new file mode 100644 index 000000000..a5b3a3216 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksOneCodeComparisonStandard.xml @@ -0,0 +1,24 @@ + + + + + + + Code {} + ]]> + + + Comparison {} + ]]> + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml new file mode 100644 index 000000000..540ac7eaf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Docs/Structure/TwoStandardBlocksThreeCodeComparisonsStandard.xml @@ -0,0 +1,48 @@ + + + + + + + class Code {} + ]]> + + + class Comparison {} + ]]> + + + + + + + + $one = 10; + ]]> + + + $a = 10; + ]]> + + + + + echo $foo; + ]]> + + + print $foo; + ]]> + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php new file mode 100644 index 000000000..1a2546b11 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/Fixtures/StandardWithDocs/Sniffs/DummySniff.php @@ -0,0 +1,25 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/GeneratorTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/GeneratorTest.php new file mode 100644 index 000000000..30536518f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/GeneratorTest.php @@ -0,0 +1,241 @@ + $expected The expected list of found docs. + * + * @dataProvider dataConstructor + * + * @return void + */ + public function testConstructor($standard, array $expected) + { + // Set up the ruleset. + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $generator = new MockGenerator($ruleset); + $this->assertSame($expected, $generator->docFiles); + + }//end testConstructor() + + + /** + * Data provider. + * + * @return array>> + */ + public static function dataConstructor() + { + $pathToDocsInFixture = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'; + $pathToDocsInFixture .= DIRECTORY_SEPARATOR.'StandardWithDocs'; + $pathToDocsInFixture .= DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR; + + return [ + 'Standard without docs' => [ + 'standard' => __DIR__.'/NoDocsTest.xml', + 'expected' => [], + ], + 'Standard with an invalid doc file' => [ + 'standard' => __DIR__.'/NoValidDocsTest.xml', + 'expected' => [ + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'NoDocumentationElementStandard.xml', + ], + ], + 'Standard with one doc file' => [ + 'standard' => __DIR__.'/OneDocTest.xml', + 'expected' => [ + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockNoCodeStandard.xml', + ], + ], + 'Standard with multiple doc files' => [ + 'standard' => __DIR__.'/StructureDocsTest.xml', + 'expected' => [ + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'NoContentStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneCodeComparisonNoStandardStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockCodeComparisonStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockNoCodeStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'OneStandardBlockTwoCodeComparisonsStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'TwoStandardBlocksNoCodeStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'TwoStandardBlocksOneCodeComparisonStandard.xml', + $pathToDocsInFixture.'Structure'.DIRECTORY_SEPARATOR.'TwoStandardBlocksThreeCodeComparisonsStandard.xml', + ], + ], + ]; + + }//end dataConstructor() + + + /** + * Verify that an XML doc which isn't valid documentation yields an Exception to warn devs. + * + * This should not be hidden via defensive coding! + * + * @return void + */ + public function testGeneratingInvalidDocsResultsInException() + { + // Set up the ruleset. + $standard = __DIR__.'/NoValidDocsTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + if (PHP_VERSION_ID >= 80000) { + $exception = 'TypeError'; + $message = 'processSniff(): Argument #1 ($doc) must be of type DOMNode, null given'; + } else if (PHP_VERSION_ID >= 70000) { + $exception = 'TypeError'; + $message = 'processSniff() must be an instance of DOMNode, null given'; + } else { + $exception = 'PHPUnit_Framework_Error'; + $message = 'processSniff() must be an instance of DOMNode, null given'; + } + + if (method_exists($this, 'expectExceptionMessage') === true) { + // PHPUnit 5.2.0+. + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + // Ancient PHPUnit. + $this->setExpectedException($exception, $message); + } + + $generator = new MockGenerator($ruleset); + $generator->generate(); + + }//end testGeneratingInvalidDocsResultsInException() + + + /** + * Verify the wiring for the generate() function. + * + * @param string $standard The standard to use for the test. + * @param string $expected The expected function output. + * + * @dataProvider dataGeneratingDocs + * + * @return void + */ + public function testGeneratingDocs($standard, $expected) + { + // Set up the ruleset. + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $this->expectOutputString($expected); + + $generator = new MockGenerator($ruleset); + $generator->generate(); + + }//end testGeneratingDocs() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataGeneratingDocs() + { + $multidocExpected = []; + $multidocExpected[] = 'No Content'; + $multidocExpected[] = 'Code Comparison Only, Missing Standard Block'; + $multidocExpected[] = 'One Standard Block, Code Comparison'; + $multidocExpected[] = 'One Standard Block, No Code'; + $multidocExpected[] = 'One Standard Block, Two Code Comparisons'; + $multidocExpected[] = 'Two Standard Blocks, No Code'; + $multidocExpected[] = 'Two Standard Blocks, One Code Comparison'; + $multidocExpected[] = 'Two Standard Blocks, Three Code Comparisons'; + $multidocExpected = implode(PHP_EOL, $multidocExpected).PHP_EOL; + + return [ + 'Standard without docs' => [ + 'standard' => __DIR__.'/NoDocsTest.xml', + 'expected' => '', + ], + 'Standard with one doc file' => [ + 'standard' => __DIR__.'/OneDocTest.xml', + 'expected' => 'One Standard Block, No Code'.PHP_EOL, + ], + 'Standard with multiple doc files' => [ + 'standard' => __DIR__.'/StructureDocsTest.xml', + 'expected' => $multidocExpected, + ], + ]; + + }//end dataGeneratingDocs() + + + /** + * Test that the documentation for each standard passed on the command-line is shown separately. + * + * @covers \PHP_CodeSniffer\Runner::runPHPCS + * + * @return void + */ + public function testGeneratorWillShowEachStandardSeparately() + { + $standard = __DIR__.'/OneDocTest.xml'; + $_SERVER['argv'] = [ + 'phpcs', + '--generator=Text', + "--standard=$standard,PSR1", + '--report-width=80', + ]; + + $regex = '`^ + \R* # Optional blank line at the start. + (?: + (?P-+\R) # Line with dashes. + \|[ ]GENERATORTEST[ ]CODING[ ]STANDARD:[ ][^\|]+\|\R # Doc title line with prefix expected for first standard. + (?P>delimiter) # Line with dashes. + .+?\R{2} # Standard description. + ) # Only expect this group once. + (?: + (?P>delimiter) # Line with dashes. + \|[ ]PSR1[ ]CODING[ ]STANDARD:[ ][^\|]+\|\R # Doc title line with prefix expected for second standard. + (?P>delimiter) # Line with dashes. + .+?\R+ # Standard description. + (?: + -+[ ]CODE[ ]COMPARISON[ ]-+\R # Code Comparison starter line with dashes. + (?:.+?(?P>delimiter)\R){2} # Arbitrary text followed by a delimiter line. + )* # Code comparison is optional and can exist multiple times. + \R+ + ){3,} # This complete group should occur at least three times. + `sx'; + + $this->expectOutputRegex($regex); + + $runner = new Runner(); + $runner->runPHPCS(); + + }//end testGeneratorWillShowEachStandardSeparately() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/HTMLTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/HTMLTest.php new file mode 100644 index 000000000..4140937ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/HTMLTest.php @@ -0,0 +1,104 @@ +assertNotFalse($expected, 'Output expectation file could not be found'); + + // Make the test OS independent. + $expected = str_replace("\n", PHP_EOL, $expected); + $this->expectOutputString($expected); + + $generator = new HTMLDouble($ruleset); + $generator->generate(); + + }//end testDocs() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataDocs() + { + return [ + 'Standard without docs' => [ + 'standard' => __DIR__.'/NoDocsTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputNoDocs.html', + ], + 'Standard with one doc file' => [ + 'standard' => __DIR__.'/OneDocTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputOneDoc.html', + ], + 'Standard with multiple doc files' => [ + 'standard' => __DIR__.'/StructureDocsTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputStructureDocs.html', + ], + ]; + + }//end dataDocs() + + + /** + * Test the generated footer. + * + * @return void + */ + public function testFooter() + { + // Set up the ruleset. + $standard = __DIR__.'/OneDocTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $regex = '`^
    '; + $regex .= 'Documentation generated on [A-Z][a-z]{2}, [0-9]{2} [A-Z][a-z]{2} 20[0-9]{2} [0-2][0-9](?::[0-5][0-9]){2} [+-][0-9]{4}'; + $regex .= ' by PHP_CodeSniffer [3-9]\.[0-9]+.[0-9]+'; + $regex .= '
    \R \R\R$`'; + $this->expectOutputRegex($regex); + + $generator = new HTMLDouble($ruleset); + $generator->printRealFooter(); + + }//end testFooter() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/MarkdownTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/MarkdownTest.php new file mode 100644 index 000000000..9a3e54004 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/MarkdownTest.php @@ -0,0 +1,102 @@ +assertNotFalse($expected, 'Output expectation file could not be found'); + + // Make the test OS independent. + $expected = str_replace("\n", PHP_EOL, $expected); + $this->expectOutputString($expected); + + $generator = new MarkdownDouble($ruleset); + $generator->generate(); + + }//end testDocs() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataDocs() + { + return [ + 'Standard without docs' => [ + 'standard' => __DIR__.'/NoDocsTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputNoDocs.md', + ], + 'Standard with one doc file' => [ + 'standard' => __DIR__.'/OneDocTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputOneDoc.md', + ], + 'Standard with multiple doc files' => [ + 'standard' => __DIR__.'/StructureDocsTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputStructureDocs.md', + ], + ]; + + }//end dataDocs() + + + /** + * Test the generated footer. + * + * @return void + */ + public function testFooter() + { + // Set up the ruleset. + $standard = __DIR__.'/OneDocTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $regex = '`^Documentation generated on [A-Z][a-z]{2}, [0-9]{2} [A-Z][a-z]{2} 20[0-9]{2} [0-2][0-9](?::[0-5][0-9]){2} [+-][0-9]{4}'; + $regex .= ' by \[PHP_CodeSniffer [3-9]\.[0-9]+.[0-9]+\]\(https://github\.com/PHPCSStandards/PHP_CodeSniffer\)\R$`'; + $this->expectOutputRegex($regex); + + $generator = new MarkdownDouble($ruleset); + $generator->printRealFooter(); + + }//end testFooter() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoDocsTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoDocsTest.xml new file mode 100644 index 000000000..51df8395c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoDocsTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoValidDocsTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoValidDocsTest.xml new file mode 100644 index 000000000..94dda4e71 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/NoValidDocsTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/OneDocTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/OneDocTest.xml new file mode 100644 index 000000000..83ca4384e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/OneDocTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/StructureDocsTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/StructureDocsTest.xml new file mode 100644 index 000000000..45811bee6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/StructureDocsTest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/TextTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/TextTest.php new file mode 100644 index 000000000..40544557f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Generators/TextTest.php @@ -0,0 +1,80 @@ +assertNotFalse($expected, 'Output expectation file could not be found'); + + // Make the test OS independent. + $expected = str_replace("\n", PHP_EOL, $expected); + $this->expectOutputString($expected); + + $generator = new Text($ruleset); + $generator->generate(); + + }//end testDocs() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataDocs() + { + return [ + 'Standard without docs' => [ + 'standard' => __DIR__.'/NoDocsTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputEmpty.txt', + ], + 'Standard with one doc file' => [ + 'standard' => __DIR__.'/OneDocTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputOneDoc.txt', + ], + 'Standard with multiple doc files' => [ + 'standard' => __DIR__.'/StructureDocsTest.xml', + 'pathToExpected' => __DIR__.'/Expectations/ExpectedOutputStructureDocs.txt', + ], + ]; + + }//end dataDocs() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainCustomRulesetTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainCustomRulesetTest.xml new file mode 100644 index 000000000..cbca4fd51 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainCustomRulesetTest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainSingleSniffTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainSingleSniffTest.xml new file mode 100644 index 000000000..159b7efa8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainSingleSniffTest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainTest.php new file mode 100644 index 000000000..5438c65cf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ExplainTest.php @@ -0,0 +1,258 @@ + + * @copyright 2023 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Runner; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Test the Ruleset::explain() function. + * + * @covers \PHP_CodeSniffer\Ruleset::explain + */ +final class ExplainTest extends TestCase +{ + + + /** + * Test the output of the "explain" command. + * + * @return void + */ + public function testExplain() + { + // Set up the ruleset. + $config = new ConfigDouble(['--standard=PSR1', '-e']); + $ruleset = new Ruleset($config); + + $expected = PHP_EOL; + $expected .= 'The PSR1 standard contains 8 sniffs'.PHP_EOL.PHP_EOL; + $expected .= 'Generic (4 sniffs)'.PHP_EOL; + $expected .= '------------------'.PHP_EOL; + $expected .= ' Generic.Files.ByteOrderMark'.PHP_EOL; + $expected .= ' Generic.NamingConventions.UpperCaseConstantName'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowAlternativePHPTags'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowShortOpenTag'.PHP_EOL.PHP_EOL; + $expected .= 'PSR1 (3 sniffs)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' PSR1.Classes.ClassDeclaration'.PHP_EOL; + $expected .= ' PSR1.Files.SideEffects'.PHP_EOL; + $expected .= ' PSR1.Methods.CamelCapsMethodName'.PHP_EOL.PHP_EOL; + $expected .= 'Squiz (1 sniff)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' Squiz.Classes.ValidClassName'.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->explain(); + + }//end testExplain() + + + /** + * Test the output of the "explain" command is not influenced by a user set report width. + * + * @return void + */ + public function testExplainAlwaysDisplaysCompleteSniffName() + { + // Set up the ruleset. + $config = new ConfigDouble(['--standard=PSR1', '-e', '--report-width=30']); + $ruleset = new Ruleset($config); + + $expected = PHP_EOL; + $expected .= 'The PSR1 standard contains 8 sniffs'.PHP_EOL.PHP_EOL; + $expected .= 'Generic (4 sniffs)'.PHP_EOL; + $expected .= '------------------'.PHP_EOL; + $expected .= ' Generic.Files.ByteOrderMark'.PHP_EOL; + $expected .= ' Generic.NamingConventions.UpperCaseConstantName'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowAlternativePHPTags'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowShortOpenTag'.PHP_EOL.PHP_EOL; + $expected .= 'PSR1 (3 sniffs)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' PSR1.Classes.ClassDeclaration'.PHP_EOL; + $expected .= ' PSR1.Files.SideEffects'.PHP_EOL; + $expected .= ' PSR1.Methods.CamelCapsMethodName'.PHP_EOL.PHP_EOL; + $expected .= 'Squiz (1 sniff)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' Squiz.Classes.ValidClassName'.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->explain(); + + }//end testExplainAlwaysDisplaysCompleteSniffName() + + + /** + * Test the output of the "explain" command when a ruleset only contains a single sniff. + * + * This is mostly about making sure that the summary line uses the correct grammar. + * + * @return void + */ + public function testExplainSingleSniff() + { + // Set up the ruleset. + $standard = __DIR__.'/ExplainSingleSniffTest.xml'; + $config = new ConfigDouble(["--standard=$standard", '-e']); + $ruleset = new Ruleset($config); + + $expected = PHP_EOL; + $expected .= 'The ExplainSingleSniffTest standard contains 1 sniff'.PHP_EOL.PHP_EOL; + $expected .= 'Squiz (1 sniff)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' Squiz.Scope.MethodScope'.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->explain(); + + }//end testExplainSingleSniff() + + + /** + * Test that "explain" works correctly with custom rulesets. + * + * Verifies that: + * - The "standard" name is taken from the custom ruleset. + * - Any and all sniff additions and exclusions in the ruleset are taken into account correctly. + * - That the displayed list will have both the standards as well as the sniff names + * ordered alphabetically. + * + * @return void + */ + public function testExplainCustomRuleset() + { + // Set up the ruleset. + $standard = __DIR__.'/ExplainCustomRulesetTest.xml'; + $config = new ConfigDouble(["--standard=$standard", '-e']); + $ruleset = new Ruleset($config); + + $expected = PHP_EOL; + $expected .= 'The ExplainCustomRulesetTest standard contains 10 sniffs'.PHP_EOL.PHP_EOL; + $expected .= 'Generic (4 sniffs)'.PHP_EOL; + $expected .= '------------------'.PHP_EOL; + $expected .= ' Generic.Files.ByteOrderMark'.PHP_EOL; + $expected .= ' Generic.NamingConventions.UpperCaseConstantName'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowAlternativePHPTags'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowShortOpenTag'.PHP_EOL.PHP_EOL; + $expected .= 'PSR1 (2 sniffs)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' PSR1.Classes.ClassDeclaration'.PHP_EOL; + $expected .= ' PSR1.Methods.CamelCapsMethodName'.PHP_EOL.PHP_EOL; + $expected .= 'PSR12 (2 sniffs)'.PHP_EOL; + $expected .= '----------------'.PHP_EOL; + $expected .= ' PSR12.ControlStructures.BooleanOperatorPlacement'.PHP_EOL; + $expected .= ' PSR12.ControlStructures.ControlStructureSpacing'.PHP_EOL.PHP_EOL; + $expected .= 'Squiz (2 sniffs)'.PHP_EOL; + $expected .= '----------------'.PHP_EOL; + $expected .= ' Squiz.Classes.ValidClassName'.PHP_EOL; + $expected .= ' Squiz.Scope.MethodScope'.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->explain(); + + }//end testExplainCustomRuleset() + + + /** + * Test the output of the "explain" command for a standard containing both deprecated + * and non-deprecated sniffs. + * + * Tests that: + * - Deprecated sniffs are marked with an asterix in the list. + * - A footnote is displayed explaining the asterix. + * - And that the "standard uses # deprecated sniffs" listing is **not** displayed. + * + * @return void + */ + public function testExplainWithDeprecatedSniffs() + { + // Set up the ruleset. + $standard = __DIR__."/ShowSniffDeprecationsTest.xml"; + $config = new ConfigDouble(["--standard=$standard", '-e']); + $ruleset = new Ruleset($config); + + $expected = PHP_EOL; + $expected .= 'The SniffDeprecationTest standard contains 9 sniffs'.PHP_EOL.PHP_EOL; + + $expected .= 'Fixtures (9 sniffs)'.PHP_EOL; + $expected .= '-------------------'.PHP_EOL; + $expected .= ' Fixtures.Deprecated.WithLongReplacement *'.PHP_EOL; + $expected .= ' Fixtures.Deprecated.WithoutReplacement *'.PHP_EOL; + $expected .= ' Fixtures.Deprecated.WithReplacement *'.PHP_EOL; + $expected .= ' Fixtures.Deprecated.WithReplacementContainingLinuxNewlines *'.PHP_EOL; + $expected .= ' Fixtures.Deprecated.WithReplacementContainingNewlines *'.PHP_EOL; + $expected .= ' Fixtures.SetProperty.AllowedAsDeclared'.PHP_EOL; + $expected .= ' Fixtures.SetProperty.AllowedViaMagicMethod'.PHP_EOL; + $expected .= ' Fixtures.SetProperty.AllowedViaStdClass'.PHP_EOL; + $expected .= ' Fixtures.SetProperty.NotAllowedViaAttribute'.PHP_EOL.PHP_EOL; + + $expected .= '* Sniffs marked with an asterix are deprecated.'.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->explain(); + + }//end testExplainWithDeprecatedSniffs() + + + /** + * Test that each standard passed on the command-line is explained separately. + * + * @covers \PHP_CodeSniffer\Runner::runPHPCS + * + * @return void + */ + public function testExplainWillExplainEachStandardSeparately() + { + $standard = __DIR__.'/ExplainSingleSniffTest.xml'; + $_SERVER['argv'] = [ + 'phpcs', + '-e', + "--standard=PSR1,$standard", + '--report-width=80', + ]; + + $expected = PHP_EOL; + $expected .= 'The PSR1 standard contains 8 sniffs'.PHP_EOL.PHP_EOL; + $expected .= 'Generic (4 sniffs)'.PHP_EOL; + $expected .= '------------------'.PHP_EOL; + $expected .= ' Generic.Files.ByteOrderMark'.PHP_EOL; + $expected .= ' Generic.NamingConventions.UpperCaseConstantName'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowAlternativePHPTags'.PHP_EOL; + $expected .= ' Generic.PHP.DisallowShortOpenTag'.PHP_EOL.PHP_EOL; + $expected .= 'PSR1 (3 sniffs)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' PSR1.Classes.ClassDeclaration'.PHP_EOL; + $expected .= ' PSR1.Files.SideEffects'.PHP_EOL; + $expected .= ' PSR1.Methods.CamelCapsMethodName'.PHP_EOL.PHP_EOL; + $expected .= 'Squiz (1 sniff)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' Squiz.Classes.ValidClassName'.PHP_EOL.PHP_EOL; + + $expected .= 'The ExplainSingleSniffTest standard contains 1 sniff'.PHP_EOL.PHP_EOL; + $expected .= 'Squiz (1 sniff)'.PHP_EOL; + $expected .= '---------------'.PHP_EOL; + $expected .= ' Squiz.Scope.MethodScope'.PHP_EOL; + + $this->expectOutputString($expected); + + $runner = new Runner(); + $runner->runPHPCS(); + + }//end testExplainWillExplainEachStandardSeparately() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithLongReplacementSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithLongReplacementSniff.php new file mode 100644 index 000000000..40c23113d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/Deprecated/WithLongReplacementSniff.php @@ -0,0 +1,41 @@ +magic[$name] = $value; + } + + public function __get($name) + { + if (isset($this->magic[$name])) { + return $this->magic[$name]; + } + + return null; + } + + public function register() + { + return [T_WHITESPACE]; + } + + public function process(File $phpcsFile, $stackPtr) + { + // Do something. + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/AllowedViaStdClassSniff.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/AllowedViaStdClassSniff.php new file mode 100644 index 000000000..30418729d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/Fixtures/Sniffs/SetProperty/AllowedViaStdClassSniff.php @@ -0,0 +1,26 @@ + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php new file mode 100644 index 000000000..1955ce2a4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.php @@ -0,0 +1,119 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Ruleset class using a Linux-style absolute path to include a sniff. + * + * @covers \PHP_CodeSniffer\Ruleset + */ +final class RuleInclusionAbsoluteLinuxTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private $contents = ''; + + + /** + * Initialize the config and ruleset objects. + * + * @before + * + * @return void + */ + public function initializeConfigAndRuleset() + { + $this->standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + $repoRootDir = dirname(dirname(dirname(__DIR__))); + + // On-the-fly adjust the ruleset test file to be able to test sniffs included with absolute paths. + $contents = file_get_contents($this->standard); + $this->contents = $contents; + + $newPath = $repoRootDir; + if (DIRECTORY_SEPARATOR === '\\') { + $newPath = str_replace('\\', '/', $repoRootDir); + } + + $adjusted = str_replace('%path_slash_forward%', $newPath, $contents); + + if (file_put_contents($this->standard, $adjusted) === false) { + $this->markTestSkipped('On the fly ruleset adjustment failed'); + } + + // Initialize the config and ruleset objects for the test. + $config = new ConfigDouble(["--standard={$this->standard}"]); + $this->ruleset = new Ruleset($config); + + }//end initializeConfigAndRuleset() + + + /** + * Reset ruleset file. + * + * @after + * + * @return void + */ + public function resetRuleset() + { + file_put_contents($this->standard, $this->contents); + + }//end resetRuleset() + + + /** + * Test that sniffs registed with a Linux absolute path are correctly recognized and that + * properties are correctly set for them. + * + * @return void + */ + public function testLinuxStylePathRuleInclusion() + { + // Test that the sniff is correctly registered. + $this->assertCount(1, $this->ruleset->sniffCodes); + $this->assertArrayHasKey('Generic.Formatting.SpaceAfterNot', $this->ruleset->sniffCodes); + $this->assertSame( + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff', + $this->ruleset->sniffCodes['Generic.Formatting.SpaceAfterNot'] + ); + + // Test that the sniff properties are correctly set. + $this->assertSame( + '10', + $this->ruleset->sniffs['PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff']->spacing + ); + + }//end testLinuxStylePathRuleInclusion() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml new file mode 100644 index 000000000..2978cef9f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteLinuxTest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php new file mode 100644 index 000000000..9dd0370b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.php @@ -0,0 +1,116 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Ruleset class using a Windows-style absolute path to include a sniff. + * + * @covers \PHP_CodeSniffer\Ruleset + * @requires OS ^WIN.*. + * @group Windows + */ +final class RuleInclusionAbsoluteWindowsTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private $contents = ''; + + + /** + * Initialize the config and ruleset objects. + * + * @before + * + * @return void + */ + public function initializeConfigAndRuleset() + { + $this->standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + $repoRootDir = dirname(dirname(dirname(__DIR__))); + + // On-the-fly adjust the ruleset test file to be able to test sniffs included with absolute paths. + $contents = file_get_contents($this->standard); + $this->contents = $contents; + + $adjusted = str_replace('%path_slash_back%', $repoRootDir, $contents); + + if (file_put_contents($this->standard, $adjusted) === false) { + $this->markTestSkipped('On the fly ruleset adjustment failed'); + } + + // Initialize the config and ruleset objects for the test. + $config = new ConfigDouble(["--standard={$this->standard}"]); + $this->ruleset = new Ruleset($config); + + }//end initializeConfigAndRuleset() + + + /** + * Reset ruleset file. + * + * @after + * + * @return void + */ + public function resetRuleset() + { + file_put_contents($this->standard, $this->contents); + + }//end resetRuleset() + + + /** + * Test that sniffs registed with a Windows absolute path are correctly recognized and that + * properties are correctly set for them. + * + * @return void + */ + public function testWindowsStylePathRuleInclusion() + { + // Test that the sniff is correctly registered. + $this->assertCount(1, $this->ruleset->sniffCodes); + $this->assertArrayHasKey('Generic.Formatting.SpaceAfterCast', $this->ruleset->sniffCodes); + $this->assertSame( + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff', + $this->ruleset->sniffCodes['Generic.Formatting.SpaceAfterCast'] + ); + + // Test that the sniff property is correctly set. + $this->assertSame( + '10', + $this->ruleset->sniffs['PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff']->spacing + ); + + }//end testWindowsStylePathRuleInclusion() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml new file mode 100644 index 000000000..e92c68842 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionAbsoluteWindowsTest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml new file mode 100644 index 000000000..d95af20d9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest-include.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php new file mode 100644 index 000000000..3f6a7180d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.php @@ -0,0 +1,486 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; +use ReflectionObject; + +/** + * Tests for the \PHP_CodeSniffer\Ruleset class. + * + * @covers \PHP_CodeSniffer\Ruleset + */ +final class RuleInclusionTest extends TestCase +{ + + /** + * The Ruleset object. + * + * @var \PHP_CodeSniffer\Ruleset + */ + protected static $ruleset; + + /** + * Path to the ruleset file. + * + * @var string + */ + private static $standard = ''; + + /** + * The original content of the ruleset. + * + * @var string + */ + private static $contents = ''; + + + /** + * Initialize the config and ruleset objects based on the `RuleInclusionTest.xml` ruleset file. + * + * @before + * + * @return void + */ + public static function initializeConfigAndRuleset() + { + if (self::$standard === '') { + $standard = __DIR__.'/'.basename(__FILE__, '.php').'.xml'; + self::$standard = $standard; + + // On-the-fly adjust the ruleset test file to be able to test + // sniffs included with relative paths. + $contents = file_get_contents($standard); + self::$contents = $contents; + + $repoRootDir = basename(dirname(dirname(dirname(__DIR__)))); + + $newPath = $repoRootDir; + if (DIRECTORY_SEPARATOR === '\\') { + $newPath = str_replace('\\', '/', $repoRootDir); + } + + $adjusted = str_replace('%path_root_dir%', $newPath, $contents); + + if (file_put_contents($standard, $adjusted) === false) { + self::markTestSkipped('On the fly ruleset adjustment failed'); + } + + $config = new ConfigDouble(["--standard=$standard"]); + self::$ruleset = new Ruleset($config); + }//end if + + }//end initializeConfigAndRuleset() + + + /** + * Reset ruleset file. + * + * @after + * + * @return void + */ + public function resetRuleset() + { + file_put_contents(self::$standard, self::$contents); + + }//end resetRuleset() + + + /** + * Test that sniffs are registered. + * + * @return void + */ + public function testHasSniffCodes() + { + $this->assertCount(49, self::$ruleset->sniffCodes); + + }//end testHasSniffCodes() + + + /** + * Test that sniffs are correctly registered, independently of the syntax used to include the sniff. + * + * @param string $key Expected array key. + * @param string $value Expected array value. + * + * @dataProvider dataRegisteredSniffCodes + * + * @return void + */ + public function testRegisteredSniffCodes($key, $value) + { + $this->assertArrayHasKey($key, self::$ruleset->sniffCodes); + $this->assertSame($value, self::$ruleset->sniffCodes[$key]); + + }//end testRegisteredSniffCodes() + + + /** + * Data provider. + * + * @see self::testRegisteredSniffCodes() + * + * @return array> + */ + public static function dataRegisteredSniffCodes() + { + return [ + [ + 'PSR2.Classes.ClassDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff', + ], + [ + 'PSR2.Classes.PropertyDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\PropertyDeclarationSniff', + ], + [ + 'PSR2.ControlStructures.ControlStructureSpacing', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ControlStructureSpacingSniff', + ], + [ + 'PSR2.ControlStructures.ElseIfDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\ElseIfDeclarationSniff', + ], + [ + 'PSR2.ControlStructures.SwitchDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\SwitchDeclarationSniff', + ], + [ + 'PSR2.Files.ClosingTag', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\ClosingTagSniff', + ], + [ + 'PSR2.Files.EndFileNewline', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\EndFileNewlineSniff', + ], + [ + 'PSR2.Methods.FunctionCallSignature', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionCallSignatureSniff', + ], + [ + 'PSR2.Methods.FunctionClosingBrace', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionClosingBraceSniff', + ], + [ + 'PSR2.Methods.MethodDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff', + ], + [ + 'PSR2.Namespaces.NamespaceDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces\NamespaceDeclarationSniff', + ], + [ + 'PSR2.Namespaces.UseDeclaration', + 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Namespaces\UseDeclarationSniff', + ], + [ + 'PSR1.Classes.ClassDeclaration', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff', + ], + [ + 'PSR1.Files.SideEffects', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Files\SideEffectsSniff', + ], + [ + 'PSR1.Methods.CamelCapsMethodName', + 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff', + ], + [ + 'Generic.PHP.DisallowAlternativePHPTags', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowAlternativePHPTagsSniff', + ], + [ + 'Generic.PHP.DisallowShortOpenTag', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\DisallowShortOpenTagSniff', + ], + [ + 'Generic.Files.ByteOrderMark', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff', + ], + [ + 'Squiz.Classes.ValidClassName', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes\ValidClassNameSniff', + ], + [ + 'Generic.NamingConventions.UpperCaseConstantName', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\UpperCaseConstantNameSniff', + ], + [ + 'Generic.Files.LineEndings', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineEndingsSniff', + ], + [ + 'Generic.Files.LineLength', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff', + ], + [ + 'Squiz.WhiteSpace.SuperfluousWhitespace', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\SuperfluousWhitespaceSniff', + ], + [ + 'Generic.Formatting.DisallowMultipleStatements', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\DisallowMultipleStatementsSniff', + ], + [ + 'Generic.WhiteSpace.ScopeIndent', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ScopeIndentSniff', + ], + [ + 'Generic.WhiteSpace.DisallowTabIndent', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\DisallowTabIndentSniff', + ], + [ + 'Generic.PHP.LowerCaseKeyword', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseKeywordSniff', + ], + [ + 'Generic.PHP.LowerCaseConstant', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\LowerCaseConstantSniff', + ], + [ + 'Squiz.Scope.MethodScope', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Scope\MethodScopeSniff', + ], + [ + 'Squiz.WhiteSpace.ScopeKeywordSpacing', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ScopeKeywordSpacingSniff', + ], + [ + 'Squiz.Functions.FunctionDeclaration', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\FunctionDeclarationSniff', + ], + [ + 'Squiz.Functions.LowercaseFunctionKeywords', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\LowercaseFunctionKeywordsSniff', + ], + [ + 'Squiz.Functions.FunctionDeclarationArgumentSpacing', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\FunctionDeclarationArgumentSpacingSniff', + ], + [ + 'PEAR.Functions.ValidDefaultValue', + 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\ValidDefaultValueSniff', + ], + [ + 'Squiz.Functions.MultiLineFunctionDeclaration', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Functions\MultiLineFunctionDeclarationSniff', + ], + [ + 'Generic.Functions.FunctionCallArgumentSpacing', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Functions\FunctionCallArgumentSpacingSniff', + ], + [ + 'Squiz.ControlStructures.ControlSignature', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ControlSignatureSniff', + ], + [ + 'Squiz.WhiteSpace.ControlStructureSpacing', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ControlStructureSpacingSniff', + ], + [ + 'Squiz.WhiteSpace.ScopeClosingBrace', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\ScopeClosingBraceSniff', + ], + [ + 'Squiz.ControlStructures.ForEachLoopDeclaration', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ForEachLoopDeclarationSniff', + ], + [ + 'Squiz.ControlStructures.ForLoopDeclaration', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\ForLoopDeclarationSniff', + ], + [ + 'Squiz.ControlStructures.LowercaseDeclaration', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\ControlStructures\LowercaseDeclarationSniff', + ], + [ + 'Generic.ControlStructures.InlineControlStructure', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\ControlStructures\InlineControlStructureSniff', + ], + [ + 'PSR12.Operators.OperatorSpacing', + 'PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators\OperatorSpacingSniff', + ], + [ + 'Generic.Arrays.ArrayIndent', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff', + ], + [ + 'Generic.Metrics.CyclomaticComplexity', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff', + ], + [ + 'Squiz.Files.FileExtension', + 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Files\FileExtensionSniff', + ], + [ + 'Generic.NamingConventions.CamelCapsFunctionName', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', + ], + [ + 'Generic.Metrics.NestingLevel', + 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + ], + ]; + + }//end dataRegisteredSniffCodes() + + + /** + * Test that setting properties for standards, categories, sniffs works for all supported rule + * inclusion methods. + * + * @param string $sniffClass The name of the sniff class. + * @param string $propertyName The name of the changed property. + * @param string|int|bool $expectedValue The value expected for the property. + * + * @dataProvider dataSettingProperties + * + * @return void + */ + public function testSettingProperties($sniffClass, $propertyName, $expectedValue) + { + $this->assertArrayHasKey($sniffClass, self::$ruleset->sniffs); + + $hasProperty = (new ReflectionObject(self::$ruleset->sniffs[$sniffClass]))->hasProperty($propertyName); + $errorMsg = sprintf('Property %s does not exist on sniff class %s', $propertyName, $sniffClass); + $this->assertTrue($hasProperty, $errorMsg); + + $actualValue = self::$ruleset->sniffs[$sniffClass]->$propertyName; + $this->assertSame($expectedValue, $actualValue); + + }//end testSettingProperties() + + + /** + * Data provider. + * + * @see self::testSettingProperties() + * + * @return array> + */ + public static function dataSettingProperties() + { + return [ + 'Set property for complete standard: PSR2 ClassDeclaration' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Classes\ClassDeclarationSniff', + 'propertyName' => 'indent', + 'expectedValue' => '20', + ], + 'Set property for complete standard: PSR2 SwitchDeclaration' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR2\Sniffs\ControlStructures\SwitchDeclarationSniff', + 'propertyName' => 'indent', + 'expectedValue' => '20', + ], + 'Set property for complete standard: PSR2 FunctionCallSignature' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionCallSignatureSniff', + 'propertyName' => 'indent', + 'expectedValue' => '20', + ], + 'Set property for complete category: PSR12 OperatorSpacing' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators\OperatorSpacingSniff', + 'propertyName' => 'ignoreSpacingBeforeAssignments', + 'expectedValue' => false, + ], + 'Set property for individual sniff: Generic ArrayIndent' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays\ArrayIndentSniff', + 'propertyName' => 'indent', + 'expectedValue' => '2', + ], + 'Set property for individual sniff using sniff file inclusion: Generic LineLength' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff', + 'propertyName' => 'lineLimit', + 'expectedValue' => '10', + ], + 'Set property for individual sniff using sniff file inclusion: CamelCapsFunctionName' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff', + 'propertyName' => 'strict', + 'expectedValue' => false, + ], + 'Set property for individual sniff via included ruleset: NestingLevel - nestingLevel' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + 'propertyName' => 'nestingLevel', + 'expectedValue' => '2', + ], + 'Set property for all sniffs in an included ruleset: NestingLevel - absoluteNestingLevel' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff', + 'propertyName' => 'absoluteNestingLevel', + 'expectedValue' => true, + ], + + // Testing that setting a property at error code level does *not* work. + 'Set property for error code will not change the sniff property value: CyclomaticComplexity' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff', + 'propertyName' => 'complexity', + 'expectedValue' => 10, + ], + ]; + + }//end dataSettingProperties() + + + /** + * Test that setting properties for standards, categories on sniffs which don't support the property will + * silently ignore the property and not set it. + * + * @param string $sniffClass The name of the sniff class. + * @param string $propertyName The name of the property which should not be set. + * + * @dataProvider dataSettingInvalidPropertiesOnStandardsAndCategoriesSilentlyFails + * + * @return void + */ + public function testSettingInvalidPropertiesOnStandardsAndCategoriesSilentlyFails($sniffClass, $propertyName) + { + $this->assertArrayHasKey($sniffClass, self::$ruleset->sniffs, 'Sniff class '.$sniffClass.' not listed in registered sniffs'); + + $hasProperty = (new ReflectionObject(self::$ruleset->sniffs[$sniffClass]))->hasProperty($propertyName); + $errorMsg = sprintf('Property %s registered for sniff %s which does not support it', $propertyName, $sniffClass); + $this->assertFalse($hasProperty, $errorMsg); + + }//end testSettingInvalidPropertiesOnStandardsAndCategoriesSilentlyFails() + + + /** + * Data provider. + * + * @see self::testSettingInvalidPropertiesOnStandardsAndCategoriesSilentlyFails() + * + * @return arraystring, string>> + */ + public static function dataSettingInvalidPropertiesOnStandardsAndCategoriesSilentlyFails() + { + return [ + 'Set property for complete standard: PSR2 ClassDeclaration' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR1\Sniffs\Classes\ClassDeclarationSniff', + 'propertyName' => 'setforallsniffs', + ], + 'Set property for complete standard: PSR2 FunctionCallSignature' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\FunctionCallSignatureSniff', + 'propertyName' => 'setforallsniffs', + ], + 'Set property for complete category: PSR12 OperatorSpacing' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\PSR12\Sniffs\Operators\OperatorSpacingSniff', + 'propertyName' => 'setforallincategory', + ], + 'Set property for all sniffs in included category directory' => [ + 'sniffClass' => 'PHP_CodeSniffer\Standards\Squiz\Sniffs\Files\FileExtensionSniff', + 'propertyName' => 'setforsquizfilessniffs', + ], + ]; + + }//end dataSettingInvalidPropertiesOnStandardsAndCategoriesSilentlyFails() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml new file mode 100644 index 000000000..6b5c0a970 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/RuleInclusionTest.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedAsDeclaredTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedAsDeclaredTest.xml new file mode 100644 index 000000000..5840d0c36 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedAsDeclaredTest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaMagicMethodTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaMagicMethodTest.xml new file mode 100644 index 000000000..7ff217824 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaMagicMethodTest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaStdClassTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaStdClassTest.xml new file mode 100644 index 000000000..387f419e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAllowedViaStdClassTest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAppliesPropertyToMultipleSniffsInCategoryTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAppliesPropertyToMultipleSniffsInCategoryTest.xml new file mode 100644 index 000000000..7c4ca4fd3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyAppliesPropertyToMultipleSniffsInCategoryTest.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategoryTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategoryTest.xml new file mode 100644 index 000000000..979b48f52 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategoryTest.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml new file mode 100644 index 000000000..48a36a831 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyNotAllowedViaAttributeTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyNotAllowedViaAttributeTest.xml new file mode 100644 index 000000000..7caae3d39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyNotAllowedViaAttributeTest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyThrowsErrorOnInvalidPropertyTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyThrowsErrorOnInvalidPropertyTest.xml new file mode 100644 index 000000000..5dca1a010 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetPropertyThrowsErrorOnInvalidPropertyTest.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetSniffPropertyTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetSniffPropertyTest.php new file mode 100644 index 000000000..36e6f0097 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/SetSniffPropertyTest.php @@ -0,0 +1,402 @@ + + * @copyright 2022 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; +use ReflectionObject; + +/** + * These tests specifically focus on the changes made to work around the PHP 8.2 dynamic properties deprecation. + * + * @covers \PHP_CodeSniffer\Ruleset::setSniffProperty + */ +final class SetSniffPropertyTest extends TestCase +{ + + + /** + * Test that setting a property via the ruleset works in all situations which allow for it. + * + * @param string $name Name of the test. Used for the sniff name, the ruleset file name etc. + * + * @dataProvider dataSniffPropertiesGetSetWhenAllowed + * + * @return void + */ + public function testSniffPropertiesGetSetWhenAllowed($name) + { + $sniffCode = "Fixtures.SetProperty.{$name}"; + $sniffClass = 'Fixtures\Sniffs\SetProperty\\'.$name.'Sniff'; + $properties = [ + 'arbitrarystring' => 'arbitraryvalue', + 'arbitraryarray' => [ + 'mykey' => 'myvalue', + 'otherkey' => 'othervalue', + ], + ]; + + // Set up the ruleset. + $standard = __DIR__."/SetProperty{$name}Test.xml"; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + // Verify that the sniff has been registered. + $this->assertGreaterThan(0, count($ruleset->sniffCodes), 'No sniff codes registered'); + + // Verify that our target sniff has been registered. + $this->assertArrayHasKey($sniffCode, $ruleset->sniffCodes, 'Target sniff not registered'); + $this->assertSame($sniffClass, $ruleset->sniffCodes[$sniffCode], 'Target sniff not registered with the correct class'); + + // Test that the property as declared in the ruleset has been set on the sniff. + $this->assertArrayHasKey($sniffClass, $ruleset->sniffs, 'Sniff class not listed in registered sniffs'); + + $sniffObject = $ruleset->sniffs[$sniffClass]; + foreach ($properties as $name => $expectedValue) { + $this->assertSame($expectedValue, $sniffObject->$name, 'Property value not set to expected value'); + } + + }//end testSniffPropertiesGetSetWhenAllowed() + + + /** + * Data provider. + * + * @see self::testSniffPropertiesGetSetWhenAllowed() + * + * @return array> + */ + public static function dataSniffPropertiesGetSetWhenAllowed() + { + return [ + 'Property allowed as explicitly declared' => ['AllowedAsDeclared'], + 'Property allowed as sniff extends stdClass' => ['AllowedViaStdClass'], + 'Property allowed as sniff has magic __set() method' => ['AllowedViaMagicMethod'], + ]; + + }//end dataSniffPropertiesGetSetWhenAllowed() + + + /** + * Test that setting a property for a category will apply it correctly to those sniffs which support the + * property, but won't apply it to sniffs which don't. + * + * Note: this test intentionally uses the `PEAR.Functions` category as two sniffs in that category + * have a public property with the same name (`indent`) and one sniff doesn't, which makes it a great + * test case for this. + * + * @return void + */ + public function testSetPropertyAppliesPropertyToMultipleSniffsInCategory() + { + $propertyName = 'indent'; + $expectedValue = '10'; + + // Set up the ruleset. + $standard = __DIR__.'/SetPropertyAppliesPropertyToMultipleSniffsInCategoryTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + // Test that the two sniffs which support the property have received the value. + $sniffClass = 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionCallSignatureSniff'; + $this->assertArrayHasKey($sniffClass, $ruleset->sniffs, 'Sniff class '.$sniffClass.' not listed in registered sniffs'); + $sniffObject = $ruleset->sniffs[$sniffClass]; + $this->assertSame($expectedValue, $sniffObject->$propertyName, 'Property value not set to expected value for '.$sniffClass); + + $sniffClass = 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\FunctionDeclarationSniff'; + $this->assertArrayHasKey($sniffClass, $ruleset->sniffs, 'Sniff class '.$sniffClass.' not listed in registered sniffs'); + $sniffObject = $ruleset->sniffs[$sniffClass]; + $this->assertSame($expectedValue, $sniffObject->$propertyName, 'Property value not set to expected value for '.$sniffClass); + + // Test that the property doesn't get set for the one sniff which doesn't support the property. + $sniffClass = 'PHP_CodeSniffer\Standards\PEAR\Sniffs\Functions\ValidDefaultValueSniff'; + $this->assertArrayHasKey($sniffClass, $ruleset->sniffs, 'Sniff class '.$sniffClass.' not listed in registered sniffs'); + + $hasProperty = (new ReflectionObject($ruleset->sniffs[$sniffClass]))->hasProperty($propertyName); + $errorMsg = sprintf('Property %s registered for sniff %s which does not support it', $propertyName, $sniffClass); + $this->assertFalse($hasProperty, $errorMsg); + + }//end testSetPropertyAppliesPropertyToMultipleSniffsInCategory() + + + /** + * Test that attempting to set a non-existent property directly on a sniff will throw an error + * when the sniff does not explicitly declare the property, extends stdClass or has magic methods. + * + * @return void + */ + public function testSetPropertyThrowsErrorOnInvalidProperty() + { + $exceptionClass = 'PHP_CodeSniffer\Exceptions\RuntimeException'; + $exceptionMsg = 'Ruleset invalid. Property "indentation" does not exist on sniff Generic.Arrays.ArrayIndent'; + if (method_exists($this, 'expectException') === true) { + $this->expectException($exceptionClass); + $this->expectExceptionMessage($exceptionMsg); + } else { + // PHPUnit < 5.2.0. + $this->setExpectedException($exceptionClass, $exceptionMsg); + } + + // Set up the ruleset. + $standard = __DIR__.'/SetPropertyThrowsErrorOnInvalidPropertyTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + new Ruleset($config); + + }//end testSetPropertyThrowsErrorOnInvalidProperty() + + + /** + * Test that attempting to set a non-existent property directly on a sniff will throw an error + * when the sniff does not explicitly declare the property, extends stdClass or has magic methods, + * even though the sniff has the PHP 8.2 `#[AllowDynamicProperties]` attribute set. + * + * @return void + */ + public function testSetPropertyThrowsErrorWhenPropertyOnlyAllowedViaAttribute() + { + $exceptionClass = 'PHP_CodeSniffer\Exceptions\RuntimeException'; + $exceptionMsg = 'Ruleset invalid. Property "arbitrarystring" does not exist on sniff Fixtures.SetProperty.NotAllowedViaAttribute'; + if (method_exists($this, 'expectException') === true) { + $this->expectException($exceptionClass); + $this->expectExceptionMessage($exceptionMsg); + } else { + // PHPUnit < 5.2.0. + $this->setExpectedException($exceptionClass, $exceptionMsg); + } + + // Set up the ruleset. + $standard = __DIR__.'/SetPropertyNotAllowedViaAttributeTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + new Ruleset($config); + + }//end testSetPropertyThrowsErrorWhenPropertyOnlyAllowedViaAttribute() + + + /** + * Test that attempting to set a non-existent property on a sniff when the property directive is + * for the whole standard, does not yield an error. + * + * @doesNotPerformAssertions + * + * @return void + */ + public function testSetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandard() + { + // Set up the ruleset. + $standard = __DIR__.'/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandardTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + new Ruleset($config); + + }//end testSetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForStandard() + + + /** + * Test that attempting to set a non-existent property on a sniff when the property directive is + * for a whole category, does not yield an error. + * + * @doesNotPerformAssertions + * + * @return void + */ + public function testSetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategory() + { + // Set up the ruleset. + $standard = __DIR__.'/SetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategoryTest.xml'; + $config = new ConfigDouble(["--standard=$standard"]); + new Ruleset($config); + + }//end testSetPropertyDoesNotThrowErrorOnInvalidPropertyWhenSetForCategory() + + + /** + * Test that setting a property via a direct call to the Ruleset::setSniffProperty() method + * sets the property correctly when using the new $settings array format. + * + * @return void + */ + public function testDirectCallWithNewArrayFormatSetsProperty() + { + $name = 'AllowedAsDeclared'; + $sniffCode = "Fixtures.SetProperty.{$name}"; + $sniffClass = 'Fixtures\Sniffs\SetProperty\\'.$name.'Sniff'; + + // Set up the ruleset. + $standard = __DIR__."/SetProperty{$name}Test.xml"; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $propertyName = 'arbitrarystring'; + $propertyValue = 'new value'; + + $ruleset->setSniffProperty( + $sniffClass, + $propertyName, + [ + 'scope' => 'sniff', + 'value' => $propertyValue, + ] + ); + + // Verify that the sniff has been registered. + $this->assertGreaterThan(0, count($ruleset->sniffCodes), 'No sniff codes registered'); + + // Verify that our target sniff has been registered. + $this->assertArrayHasKey($sniffCode, $ruleset->sniffCodes, 'Target sniff not registered'); + $this->assertSame($sniffClass, $ruleset->sniffCodes[$sniffCode], 'Target sniff not registered with the correct class'); + + // Test that the property as declared in the ruleset has been set on the sniff. + $this->assertArrayHasKey($sniffClass, $ruleset->sniffs, 'Sniff class not listed in registered sniffs'); + + $sniffObject = $ruleset->sniffs[$sniffClass]; + $this->assertSame($propertyValue, $sniffObject->$propertyName, 'Property value not set to expected value'); + + }//end testDirectCallWithNewArrayFormatSetsProperty() + + + /** + * Test that setting a property via a direct call to the Ruleset::setSniffProperty() method + * sets the property correctly when using the old $settings array format. + * + * Tested by silencing the deprecation notice as otherwise the test would fail on the deprecation notice. + * + * @param mixed $propertyValue Value for the property to set. + * + * @dataProvider dataDirectCallWithOldArrayFormatSetsProperty + * + * @return void + */ + public function testDirectCallWithOldArrayFormatSetsProperty($propertyValue) + { + $name = 'AllowedAsDeclared'; + $sniffCode = "Fixtures.SetProperty.{$name}"; + $sniffClass = 'Fixtures\Sniffs\SetProperty\\'.$name.'Sniff'; + + // Set up the ruleset. + $standard = __DIR__."/SetProperty{$name}Test.xml"; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $propertyName = 'arbitrarystring'; + + @$ruleset->setSniffProperty( + $sniffClass, + $propertyName, + $propertyValue + ); + + // Verify that the sniff has been registered. + $this->assertGreaterThan(0, count($ruleset->sniffCodes), 'No sniff codes registered'); + + // Verify that our target sniff has been registered. + $this->assertArrayHasKey($sniffCode, $ruleset->sniffCodes, 'Target sniff not registered'); + $this->assertSame($sniffClass, $ruleset->sniffCodes[$sniffCode], 'Target sniff not registered with the correct class'); + + // Test that the property as declared in the ruleset has been set on the sniff. + $this->assertArrayHasKey($sniffClass, $ruleset->sniffs, 'Sniff class not listed in registered sniffs'); + + $sniffObject = $ruleset->sniffs[$sniffClass]; + $this->assertSame($propertyValue, $sniffObject->$propertyName, 'Property value not set to expected value'); + + }//end testDirectCallWithOldArrayFormatSetsProperty() + + + /** + * Data provider. + * + * @see self::testDirectCallWithOldArrayFormatSetsProperty() + * + * @return array> + */ + public static function dataDirectCallWithOldArrayFormatSetsProperty() + { + return [ + 'Property value is not an array (boolean)' => [ + 'propertyValue' => false, + ], + 'Property value is not an array (string)' => [ + 'propertyValue' => 'a string', + ], + 'Property value is an empty array' => [ + 'propertyValue' => [], + ], + 'Property value is an array without keys' => [ + 'propertyValue' => [ + 'value', + false, + ], + ], + 'Property value is an array without the "scope" or "value" keys' => [ + 'propertyValue' => [ + 'key1' => 'value', + 'key2' => false, + ], + ], + 'Property value is an array without the "scope" key' => [ + 'propertyValue' => [ + 'key1' => 'value', + 'value' => true, + ], + ], + 'Property value is an array without the "value" key' => [ + 'propertyValue' => [ + 'scope' => 'value', + 'key2' => 1234, + ], + ], + ]; + + }//end dataDirectCallWithOldArrayFormatSetsProperty() + + + /** + * Test that setting a property via a direct call to the Ruleset::setSniffProperty() method + * throws a deprecation notice when using the old $settings array format. + * + * Note: as PHPUnit stops as soon as it sees the deprecation notice, the setting of the property + * value is not tested here. + * + * @return void + */ + public function testDirectCallWithOldArrayFormatThrowsDeprecationNotice() + { + $exceptionClass = 'PHPUnit\Framework\Error\Deprecated'; + if (class_exists($exceptionClass) === false) { + $exceptionClass = 'PHPUnit_Framework_Error_Deprecated'; + } + + $exceptionMsg = 'the format of the $settings parameter has changed from (mixed) $value to array(\'scope\' => \'sniff|standard\', \'value\' => $value). Please update your integration code. See PR #3629 for more information.'; + + if (method_exists($this, 'expectException') === true) { + $this->expectException($exceptionClass); + $this->expectExceptionMessage($exceptionMsg); + } else { + // PHPUnit < 5.2.0. + $this->setExpectedException($exceptionClass, $exceptionMsg); + } + + $name = 'AllowedAsDeclared'; + $sniffClass = 'Fixtures\Sniffs\SetProperty\\'.$name.'Sniff'; + + // Set up the ruleset. + $standard = __DIR__."/SetProperty{$name}Test.xml"; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $ruleset->setSniffProperty( + $sniffClass, + 'arbitrarystring', + ['key' => 'value'] + ); + + }//end testDirectCallWithOldArrayFormatThrowsDeprecationNotice() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyDeprecationVersionTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyDeprecationVersionTest.xml new file mode 100644 index 000000000..5e2480bf2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyDeprecationVersionTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyRemovalVersionTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyRemovalVersionTest.xml new file mode 100644 index 000000000..6e667375a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsEmptyRemovalVersionTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationMessageTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationMessageTest.xml new file mode 100644 index 000000000..d32516799 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationMessageTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationVersionTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationVersionTest.xml new file mode 100644 index 000000000..89d83ab52 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidDeprecationVersionTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidRemovalVersionTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidRemovalVersionTest.xml new file mode 100644 index 000000000..c1eb062e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsInvalidRemovalVersionTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsOrderTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsOrderTest.xml new file mode 100644 index 000000000..3ce96ce89 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsOrderTest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsReportWidthTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsReportWidthTest.xml new file mode 100644 index 000000000..9f1cc8515 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsReportWidthTest.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.php new file mode 100644 index 000000000..8e81f96a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.php @@ -0,0 +1,510 @@ + + * @copyright 2024 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Ruleset; + +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Tests PHPCS native handling of sniff deprecations. + * + * @covers \PHP_CodeSniffer\Ruleset::hasSniffDeprecations + * @covers \PHP_CodeSniffer\Ruleset::showSniffDeprecations + */ +final class ShowSniffDeprecationsTest extends TestCase +{ + + + /** + * Test the return value of the hasSniffDeprecations() method. + * + * @param string $standard The standard to use for the test. + * @param bool $expected The expected function return value. + * + * @dataProvider dataHasSniffDeprecations + * + * @return void + */ + public function testHasSniffDeprecations($standard, $expected) + { + $config = new ConfigDouble(['.', "--standard=$standard"]); + $ruleset = new Ruleset($config); + + $this->assertSame($expected, $ruleset->hasSniffDeprecations()); + + }//end testHasSniffDeprecations() + + + /** + * Data provider. + * + * @see testHasSniffDeprecations() + * + * @return array> + */ + public static function dataHasSniffDeprecations() + { + return [ + 'Standard not using deprecated sniffs: PSR1' => [ + 'standard' => 'PSR1', + 'expected' => false, + ], + 'Standard using deprecated sniffs: Test Fixture' => [ + 'standard' => __DIR__.'/ShowSniffDeprecationsTest.xml', + 'expected' => true, + ], + ]; + + }//end dataHasSniffDeprecations() + + + /** + * Test that the listing with deprecated sniffs will not show when specific command-line options are being used. + * + * @param string $standard The standard to use for the test. + * @param array $additionalArgs Optional. Additional arguments to pass. + * + * @dataProvider dataDeprecatedSniffsListDoesNotShow + * + * @return void + */ + public function testDeprecatedSniffsListDoesNotShow($standard, $additionalArgs=[]) + { + $args = $additionalArgs; + $args[] = '.'; + $args[] = "--standard=$standard"; + + $config = new ConfigDouble($args); + $ruleset = new Ruleset($config); + + $this->expectOutputString(''); + + $ruleset->showSniffDeprecations(); + + }//end testDeprecatedSniffsListDoesNotShow() + + + /** + * Data provider. + * + * @see testDeprecatedSniffsListDoesNotShow() + * + * @return array>> + */ + public static function dataDeprecatedSniffsListDoesNotShow() + { + return [ + 'Standard not using deprecated sniffs: PSR1' => [ + 'standard' => 'PSR1', + ], + 'Standard using deprecated sniffs; explain mode' => [ + 'standard' => __DIR__.'/ShowSniffDeprecationsTest.xml', + 'additionalArgs' => ['-e'], + ], + 'Standard using deprecated sniffs; quiet mode' => [ + 'standard' => __DIR__.'/ShowSniffDeprecationsTest.xml', + 'additionalArgs' => ['-q'], + ], + 'Standard using deprecated sniffs; documentation is requested' => [ + 'standard' => __DIR__.'/ShowSniffDeprecationsTest.xml', + 'additionalArgs' => ['--generator=text'], + ], + ]; + + }//end dataDeprecatedSniffsListDoesNotShow() + + + /** + * Test that the listing with deprecated sniffs will not show when using a standard containing deprecated sniffs, + * but only running select non-deprecated sniffs (using `--sniffs=...`). + * + * @return void + */ + public function testDeprecatedSniffsListDoesNotShowWhenSelectedSniffsAreNotDeprecated() + { + $standard = __DIR__.'/ShowSniffDeprecationsTest.xml'; + $config = new ConfigDouble(['.', "--standard=$standard"]); + $ruleset = new Ruleset($config); + + /* + * Apply sniff restrictions. + * For tests we need to manually trigger this if the standard is "installed", like with the fixtures these tests use. + */ + + $restrictions = []; + $sniffs = [ + 'Fixtures.SetProperty.AllowedAsDeclared', + 'Fixtures.SetProperty.AllowedViaStdClass', + ]; + foreach ($sniffs as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $restrictions[strtolower($sniffName)] = true; + } + + $sniffFiles = []; + $allSniffs = $ruleset->sniffCodes; + foreach ($allSniffs as $sniffName) { + $sniffFile = str_replace('\\', DIRECTORY_SEPARATOR, $sniffName); + $sniffFile = __DIR__.DIRECTORY_SEPARATOR.$sniffFile.'.php'; + $sniffFiles[] = $sniffFile; + } + + $ruleset->registerSniffs($allSniffs, $restrictions, []); + $ruleset->populateTokenListeners(); + + $this->expectOutputString(''); + + $ruleset->showSniffDeprecations(); + + }//end testDeprecatedSniffsListDoesNotShowWhenSelectedSniffsAreNotDeprecated() + + + /** + * Test that the listing with deprecated sniffs will not show when using a standard containing deprecated sniffs, + * but all deprecated sniffs have been excluded from the run (using `--exclude=...`). + * + * @return void + */ + public function testDeprecatedSniffsListDoesNotShowWhenAllDeprecatedSniffsAreExcluded() + { + $standard = __DIR__.'/ShowSniffDeprecationsTest.xml'; + $config = new ConfigDouble(['.', "--standard=$standard"]); + $ruleset = new Ruleset($config); + + /* + * Apply sniff restrictions. + * For tests we need to manually trigger this if the standard is "installed", like with the fixtures these tests use. + */ + + $exclusions = []; + $exclude = [ + 'Fixtures.Deprecated.WithLongReplacement', + 'Fixtures.Deprecated.WithoutReplacement', + 'Fixtures.Deprecated.WithReplacement', + 'Fixtures.Deprecated.WithReplacementContainingLinuxNewlines', + 'Fixtures.Deprecated.WithReplacementContainingNewlines', + ]; + foreach ($exclude as $sniffCode) { + $parts = explode('.', strtolower($sniffCode)); + $sniffName = $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff'; + $exclusions[strtolower($sniffName)] = true; + } + + $sniffFiles = []; + $allSniffs = $ruleset->sniffCodes; + foreach ($allSniffs as $sniffName) { + $sniffFile = str_replace('\\', DIRECTORY_SEPARATOR, $sniffName); + $sniffFile = __DIR__.DIRECTORY_SEPARATOR.$sniffFile.'.php'; + $sniffFiles[] = $sniffFile; + } + + $ruleset->registerSniffs($allSniffs, [], $exclusions); + $ruleset->populateTokenListeners(); + + $this->expectOutputString(''); + + $ruleset->showSniffDeprecations(); + + }//end testDeprecatedSniffsListDoesNotShowWhenAllDeprecatedSniffsAreExcluded() + + + /** + * Test deprecated sniffs are listed alphabetically in the deprecated sniffs warning. + * + * This tests a number of different aspects: + * 1. That the summary line uses the correct grammar when there is are multiple deprecated sniffs. + * 2. That there is no trailing whitespace when the sniff does not provide a custom message. + * 3. That custom messages containing new line characters (any type) are handled correctly and + * that those new line characters are converted to the OS supported new line char. + * + * @return void + */ + public function testDeprecatedSniffsWarning() + { + $standard = __DIR__.'/ShowSniffDeprecationsTest.xml'; + $config = new ConfigDouble(["--standard=$standard", '--no-colors']); + $ruleset = new Ruleset($config); + + $expected = 'WARNING: The SniffDeprecationTest standard uses 5 deprecated sniffs'.PHP_EOL; + $expected .= '--------------------------------------------------------------------------------'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithLongReplacement'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= ' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel'.PHP_EOL; + $expected .= ' vestibulum nunc. Sed luctus dolor tortor, eu euismod purus pretium sed.'.PHP_EOL; + $expected .= ' Fusce egestas congue massa semper cursus. Donec quis pretium tellus. In'.PHP_EOL; + $expected .= ' lacinia, augue ut ornare porttitor, diam nunc faucibus purus, et accumsan'.PHP_EOL; + $expected .= ' eros sapien at sem. Sed pulvinar aliquam malesuada. Aliquam erat volutpat.'.PHP_EOL; + $expected .= ' Mauris gravida rutrum lectus at egestas. Fusce tempus elit in tincidunt'.PHP_EOL; + $expected .= ' dictum. Suspendisse dictum egestas sapien, eget ullamcorper metus elementum'.PHP_EOL; + $expected .= ' semper. Vestibulum sem justo, consectetur ac tincidunt et, finibus eget'.PHP_EOL; + $expected .= ' libero.'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithoutReplacement'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.4.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithReplacement'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= ' Use the Stnd.Category.OtherSniff sniff instead.'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithReplacementContainingLinuxNewlines'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= ' Lorem ipsum dolor sit amet, consectetur adipiscing elit.'.PHP_EOL; + $expected .= ' Fusce vel vestibulum nunc. Sed luctus dolor tortor, eu euismod purus pretium'.PHP_EOL; + $expected .= ' sed.'.PHP_EOL; + $expected .= ' Fusce egestas congue massa semper cursus. Donec quis pretium tellus.'.PHP_EOL; + $expected .= ' In lacinia, augue ut ornare porttitor, diam nunc faucibus purus, et accumsan'.PHP_EOL; + $expected .= ' eros sapien at sem.'.PHP_EOL; + $expected .= ' Sed pulvinar aliquam malesuada. Aliquam erat volutpat. Mauris gravida rutrum'.PHP_EOL; + $expected .= ' lectus at egestas.'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithReplacementContainingNewlines'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= ' Lorem ipsum dolor sit amet, consectetur adipiscing elit.'.PHP_EOL; + $expected .= ' Fusce vel vestibulum nunc. Sed luctus dolor tortor, eu euismod purus pretium'.PHP_EOL; + $expected .= ' sed.'.PHP_EOL; + $expected .= ' Fusce egestas congue massa semper cursus. Donec quis pretium tellus.'.PHP_EOL; + $expected .= ' In lacinia, augue ut ornare porttitor, diam nunc faucibus purus, et accumsan'.PHP_EOL; + $expected .= ' eros sapien at sem.'.PHP_EOL; + $expected .= ' Sed pulvinar aliquam malesuada. Aliquam erat volutpat. Mauris gravida rutrum'.PHP_EOL; + $expected .= ' lectus at egestas'.PHP_EOL.PHP_EOL; + $expected .= 'Deprecated sniffs are still run, but will stop working at some point in the'.PHP_EOL; + $expected .= 'future.'.PHP_EOL.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->showSniffDeprecations(); + + }//end testDeprecatedSniffsWarning() + + + /** + * Test deprecated sniffs are listed alphabetically in the deprecated sniffs warning. + * + * This tests the following aspects: + * 1. That the summary line uses the correct grammar when there is a single deprecated sniff. + * 2. That the separator line below the summary maximizes at the longest line length. + * 3. That the word wrapping respects the maximum report width. + * 4. That the sniff name is truncated if it is longer than the max report width. + * + * @param int $reportWidth Report width for the test. + * @param string $expectedOutput Expected output. + * + * @dataProvider dataReportWidthIsRespected + * + * @return void + */ + public function testReportWidthIsRespected($reportWidth, $expectedOutput) + { + // Set up the ruleset. + $standard = __DIR__.'/ShowSniffDeprecationsReportWidthTest.xml'; + $config = new ConfigDouble(['.', "--standard=$standard", "--report-width=$reportWidth", '--no-colors']); + $ruleset = new Ruleset($config); + + $this->expectOutputString($expectedOutput); + + $ruleset->showSniffDeprecations(); + + }//end testReportWidthIsRespected() + + + /** + * Data provider. + * + * @see testReportWidthIsRespected() + * + * @return array> + */ + public static function dataReportWidthIsRespected() + { + $summaryLine = 'WARNING: The SniffDeprecationTest standard uses 1 deprecated sniff'.PHP_EOL; + + // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- Test readability is more important. + return [ + 'Report width small: 40; with truncated sniff name and wrapped header and footer lines' => [ + 'reportWidth' => 40, + 'expectedOutput' => 'WARNING: The SniffDeprecationTest'.PHP_EOL + .'standard uses 1 deprecated sniff'.PHP_EOL + .'----------------------------------------'.PHP_EOL + .'- Fixtures.Deprecated.WithLongRepla...'.PHP_EOL + .' This sniff has been deprecated since'.PHP_EOL + .' v3.8.0 and will be removed in'.PHP_EOL + .' v4.0.0. Lorem ipsum dolor sit amet,'.PHP_EOL + .' consectetur adipiscing elit. Fusce'.PHP_EOL + .' vel vestibulum nunc. Sed luctus'.PHP_EOL + .' dolor tortor, eu euismod purus'.PHP_EOL + .' pretium sed. Fusce egestas congue'.PHP_EOL + .' massa semper cursus. Donec quis'.PHP_EOL + .' pretium tellus. In lacinia, augue ut'.PHP_EOL + .' ornare porttitor, diam nunc faucibus'.PHP_EOL + .' purus, et accumsan eros sapien at'.PHP_EOL + .' sem. Sed pulvinar aliquam malesuada.'.PHP_EOL + .' Aliquam erat volutpat. Mauris'.PHP_EOL + .' gravida rutrum lectus at egestas.'.PHP_EOL + .' Fusce tempus elit in tincidunt'.PHP_EOL + .' dictum. Suspendisse dictum egestas'.PHP_EOL + .' sapien, eget ullamcorper metus'.PHP_EOL + .' elementum semper. Vestibulum sem'.PHP_EOL + .' justo, consectetur ac tincidunt et,'.PHP_EOL + .' finibus eget libero.'.PHP_EOL.PHP_EOL + .'Deprecated sniffs are still run, but'.PHP_EOL + .'will stop working at some point in the'.PHP_EOL + .'future.'.PHP_EOL.PHP_EOL, + ], + 'Report width default: 80' => [ + 'reportWidth' => 80, + 'expectedOutput' => $summaryLine.str_repeat('-', 80).PHP_EOL + .'- Fixtures.Deprecated.WithLongReplacement'.PHP_EOL + .' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0.'.PHP_EOL + .' Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel'.PHP_EOL + .' vestibulum nunc. Sed luctus dolor tortor, eu euismod purus pretium sed.'.PHP_EOL + .' Fusce egestas congue massa semper cursus. Donec quis pretium tellus. In'.PHP_EOL + .' lacinia, augue ut ornare porttitor, diam nunc faucibus purus, et accumsan'.PHP_EOL + .' eros sapien at sem. Sed pulvinar aliquam malesuada. Aliquam erat volutpat.'.PHP_EOL + .' Mauris gravida rutrum lectus at egestas. Fusce tempus elit in tincidunt'.PHP_EOL + .' dictum. Suspendisse dictum egestas sapien, eget ullamcorper metus elementum'.PHP_EOL + .' semper. Vestibulum sem justo, consectetur ac tincidunt et, finibus eget'.PHP_EOL + .' libero.'.PHP_EOL.PHP_EOL + .'Deprecated sniffs are still run, but will stop working at some point in the'.PHP_EOL + .'future.'.PHP_EOL.PHP_EOL, + ], + 'Report width matches longest line: 666; the message should not wrap' => [ + // Length = 4 padding + 75 base line + 587 custom message. + 'reportWidth' => 666, + 'expectedOutput' => $summaryLine.str_repeat('-', 666).PHP_EOL + .'- Fixtures.Deprecated.WithLongReplacement'.PHP_EOL + .' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel vestibulum nunc. Sed luctus dolor tortor, eu euismod purus pretium sed. Fusce egestas congue massa semper cursus. Donec quis pretium tellus. In lacinia, augue ut ornare porttitor, diam nunc faucibus purus, et accumsan eros sapien at sem. Sed pulvinar aliquam malesuada. Aliquam erat volutpat. Mauris gravida rutrum lectus at egestas. Fusce tempus elit in tincidunt dictum. Suspendisse dictum egestas sapien, eget ullamcorper metus elementum semper. Vestibulum sem justo, consectetur ac tincidunt et, finibus eget libero.' + .PHP_EOL.PHP_EOL + .'Deprecated sniffs are still run, but will stop working at some point in the future.'.PHP_EOL.PHP_EOL, + ], + 'Report width wide: 1000; delimiter line length should match longest line' => [ + 'reportWidth' => 1000, + 'expectedOutput' => $summaryLine.str_repeat('-', 666).PHP_EOL + .'- Fixtures.Deprecated.WithLongReplacement'.PHP_EOL + .' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vel vestibulum nunc. Sed luctus dolor tortor, eu euismod purus pretium sed. Fusce egestas congue massa semper cursus. Donec quis pretium tellus. In lacinia, augue ut ornare porttitor, diam nunc faucibus purus, et accumsan eros sapien at sem. Sed pulvinar aliquam malesuada. Aliquam erat volutpat. Mauris gravida rutrum lectus at egestas. Fusce tempus elit in tincidunt dictum. Suspendisse dictum egestas sapien, eget ullamcorper metus elementum semper. Vestibulum sem justo, consectetur ac tincidunt et, finibus eget libero.' + .PHP_EOL.PHP_EOL + .'Deprecated sniffs are still run, but will stop working at some point in the future.'.PHP_EOL.PHP_EOL, + ], + ]; + // phpcs:enable + + }//end dataReportWidthIsRespected() + + + /** + * Test deprecated sniffs are listed alphabetically in the deprecated sniffs warning. + * + * Additionally, this test verifies that deprecated sniffs are still registered to run. + * + * @return void + */ + public function testDeprecatedSniffsAreListedAlphabetically() + { + // Set up the ruleset. + $standard = __DIR__.'/ShowSniffDeprecationsOrderTest.xml'; + $config = new ConfigDouble(["--standard=$standard", '--no-colors']); + $ruleset = new Ruleset($config); + + $expected = 'WARNING: The SniffDeprecationTest standard uses 2 deprecated sniffs'.PHP_EOL; + $expected .= '--------------------------------------------------------------------------------'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithoutReplacement'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.4.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= '- Fixtures.Deprecated.WithReplacement'.PHP_EOL; + $expected .= ' This sniff has been deprecated since v3.8.0 and will be removed in v4.0.0.'.PHP_EOL; + $expected .= ' Use the Stnd.Category.OtherSniff sniff instead.'.PHP_EOL.PHP_EOL; + $expected .= 'Deprecated sniffs are still run, but will stop working at some point in the'.PHP_EOL; + $expected .= 'future.'.PHP_EOL.PHP_EOL; + + $this->expectOutputString($expected); + + $ruleset->showSniffDeprecations(); + + // Verify that the sniffs have been registered to run. + $this->assertCount(2, $ruleset->sniffCodes, 'Incorrect number of sniff codes registered'); + $this->assertArrayHasKey( + 'Fixtures.Deprecated.WithoutReplacement', + $ruleset->sniffCodes, + 'WithoutReplacement sniff not registered' + ); + $this->assertArrayHasKey( + 'Fixtures.Deprecated.WithReplacement', + $ruleset->sniffCodes, + 'WithReplacement sniff not registered' + ); + + }//end testDeprecatedSniffsAreListedAlphabetically() + + + /** + * Test that an exception is thrown when any of the interface required methods does not + * comply with the return type/value requirements. + * + * @param string $standard The standard to use for the test. + * @param string $exceptionMessage The contents of the expected exception message. + * + * @dataProvider dataExceptionIsThrownOnIncorrectlyImplementedInterface + * + * @return void + */ + public function testExceptionIsThrownOnIncorrectlyImplementedInterface($standard, $exceptionMessage) + { + $exception = 'PHP_CodeSniffer\Exceptions\RuntimeException'; + if (method_exists($this, 'expectException') === true) { + // PHPUnit 5+. + $this->expectException($exception); + $this->expectExceptionMessage($exceptionMessage); + } else { + // PHPUnit 4. + $this->setExpectedException($exception, $exceptionMessage); + } + + // Set up the ruleset. + $standard = __DIR__.'/'.$standard; + $config = new ConfigDouble(["--standard=$standard"]); + $ruleset = new Ruleset($config); + + $ruleset->showSniffDeprecations(); + + }//end testExceptionIsThrownOnIncorrectlyImplementedInterface() + + + /** + * Data provider. + * + * @see testExceptionIsThrownOnIncorrectlyImplementedInterface() + * + * @return array> + */ + public static function dataExceptionIsThrownOnIncorrectlyImplementedInterface() + { + return [ + 'getDeprecationVersion() does not return a string' => [ + 'standard' => 'ShowSniffDeprecationsInvalidDeprecationVersionTest.xml', + 'exceptionMessage' => 'The Fixtures\Sniffs\DeprecatedInvalid\InvalidDeprecationVersionSniff::getDeprecationVersion() method must return a non-empty string, received double', + ], + 'getRemovalVersion() does not return a string' => [ + 'standard' => 'ShowSniffDeprecationsInvalidRemovalVersionTest.xml', + 'exceptionMessage' => 'The Fixtures\Sniffs\DeprecatedInvalid\InvalidRemovalVersionSniff::getRemovalVersion() method must return a non-empty string, received array', + ], + 'getDeprecationMessage() does not return a string' => [ + 'standard' => 'ShowSniffDeprecationsInvalidDeprecationMessageTest.xml', + 'exceptionMessage' => 'The Fixtures\Sniffs\DeprecatedInvalid\InvalidDeprecationMessageSniff::getDeprecationMessage() method must return a string, received object', + ], + 'getDeprecationVersion() returns an empty string' => [ + 'standard' => 'ShowSniffDeprecationsEmptyDeprecationVersionTest.xml', + 'exceptionMessage' => 'The Fixtures\Sniffs\DeprecatedInvalid\EmptyDeprecationVersionSniff::getDeprecationVersion() method must return a non-empty string, received ""', + ], + 'getRemovalVersion() returns an empty string' => [ + 'standard' => 'ShowSniffDeprecationsEmptyRemovalVersionTest.xml', + 'exceptionMessage' => 'The Fixtures\Sniffs\DeprecatedInvalid\EmptyRemovalVersionSniff::getRemovalVersion() method must return a non-empty string, received ""', + ], + ]; + + }//end dataExceptionIsThrownOnIncorrectlyImplementedInterface() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml new file mode 100644 index 000000000..4c1dec220 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Ruleset/ShowSniffDeprecationsTest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc new file mode 100644 index 000000000..488229589 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.inc @@ -0,0 +1,51 @@ +1,'2'=>2,'3'=>3]; + +/* testMissingKeys */ +$foo = ['1'=>1,2,'3'=>3]; + +/* testMultiTokenKeys */ +$paths = array( + Init::ROOT_DIR.'/a' => 'a', + Init::ROOT_DIR.'/b' => 'b', +); + +/* testMissingKeysCoalesceTernary */ +return [ + $a => static function () { return [1,2,3]; }, + $b ?? $c, + $d ? [$e] : [$f], +]; + +/* testTernaryValues */ +$foo = [ + '1' => $row['status'] === 'rejected' + ? self::REJECTED_CODE + : self::VERIFIED_CODE, + '2' => in_array($row['status'], array('notverified', 'unverified'), true) + ? self::STATUS_PENDING + : self::STATUS_VERIFIED, + '3' => strtotime($row['date']), +]; + +/* testHeredocValues */ +$foo = array( + << '1', + 2 => fn ($x) => yield 'a' => $x, + 3 => '3', +); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php new file mode 100644 index 000000000..f074d9500 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTest.php @@ -0,0 +1,297 @@ + + * @copyright 2006-2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Sniffs; + +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; + +/** + * Tests for the \PHP_CodeSniffer\Sniffs\AbstractArraySniff. + * + * @covers \PHP_CodeSniffer\Sniffs\AbstractArraySniff + */ +final class AbstractArraySniffTest extends AbstractMethodUnitTest +{ + + /** + * The sniff objects we are testing. + * + * This extends the \PHP_CodeSniffer\Sniffs\AbstractArraySniff class to make the + * internal workings of the sniff observable. + * + * @var \PHP_CodeSniffer\Sniffs\AbstractArraySniffTestable + */ + protected static $sniff; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @beforeClass + * + * @return void + */ + public static function initializeFile() + { + self::$sniff = new AbstractArraySniffTestable(); + parent::initializeFile(); + + }//end initializeFile() + + + /** + * Test an array of simple values only. + * + * @return void + */ + public function testSimpleValues() + { + $token = $this->getTargetToken('/* testSimpleValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => ['value_start' => ($token + 1)], + 1 => ['value_start' => ($token + 3)], + 2 => ['value_start' => ($token + 5)], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testSimpleValues() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testSimpleKeyValues() + { + $token = $this->getTargetToken('/* testSimpleKeyValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 1), + 'index_end' => ($token + 1), + 'arrow' => ($token + 2), + 'value_start' => ($token + 3), + ], + 1 => [ + 'index_start' => ($token + 5), + 'index_end' => ($token + 5), + 'arrow' => ($token + 6), + 'value_start' => ($token + 7), + ], + 2 => [ + 'index_start' => ($token + 9), + 'index_end' => ($token + 9), + 'arrow' => ($token + 10), + 'value_start' => ($token + 11), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testSimpleKeyValues() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testMissingKeys() + { + $token = $this->getTargetToken('/* testMissingKeys */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 1), + 'index_end' => ($token + 1), + 'arrow' => ($token + 2), + 'value_start' => ($token + 3), + ], + 1 => [ + 'value_start' => ($token + 5), + ], + 2 => [ + 'index_start' => ($token + 7), + 'index_end' => ($token + 7), + 'arrow' => ($token + 8), + 'value_start' => ($token + 9), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMissingKeys() + + + /** + * Test an array with keys that span multiple tokens. + * + * @return void + */ + public function testMultiTokenKeys() + { + $token = $this->getTargetToken('/* testMultiTokenKeys */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 4), + 'index_end' => ($token + 8), + 'arrow' => ($token + 10), + 'value_start' => ($token + 12), + ], + 1 => [ + 'index_start' => ($token + 16), + 'index_end' => ($token + 20), + 'arrow' => ($token + 22), + 'value_start' => ($token + 24), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMultiTokenKeys() + + + /** + * Test an array of simple keys and values. + * + * @return void + */ + public function testMissingKeysCoalesceTernary() + { + $token = $this->getTargetToken('/* testMissingKeysCoalesceTernary */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 3), + 'index_end' => ($token + 3), + 'arrow' => ($token + 5), + 'value_start' => ($token + 7), + ], + 1 => [ + 'value_start' => ($token + 31), + ], + 2 => [ + 'value_start' => ($token + 39), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testMissingKeysCoalesceTernary() + + + /** + * Test an array of ternary values. + * + * @return void + */ + public function testTernaryValues() + { + $token = $this->getTargetToken('/* testTernaryValues */', T_OPEN_SHORT_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 3), + 'index_end' => ($token + 3), + 'arrow' => ($token + 5), + 'value_start' => ($token + 7), + ], + 1 => [ + 'index_start' => ($token + 32), + 'index_end' => ($token + 32), + 'arrow' => ($token + 34), + 'value_start' => ($token + 36), + ], + 2 => [ + 'index_start' => ($token + 72), + 'index_end' => ($token + 72), + 'arrow' => ($token + 74), + 'value_start' => ($token + 76), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testTernaryValues() + + + /** + * Test an array of heredocs. + * + * @return void + */ + public function testHeredocValues() + { + $token = $this->getTargetToken('/* testHeredocValues */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'value_start' => ($token + 4), + ], + 1 => [ + 'value_start' => ($token + 10), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testHeredocValues() + + + /** + * Test an array of with an arrow function as a value. + * + * @return void + */ + public function testArrowFunctionValue() + { + $token = $this->getTargetToken('/* testArrowFunctionValue */', T_ARRAY); + self::$sniff->process(self::$phpcsFile, $token); + + $expected = [ + 0 => [ + 'index_start' => ($token + 4), + 'index_end' => ($token + 4), + 'arrow' => ($token + 6), + 'value_start' => ($token + 8), + ], + 1 => [ + 'index_start' => ($token + 12), + 'index_end' => ($token + 12), + 'arrow' => ($token + 14), + 'value_start' => ($token + 16), + ], + 2 => [ + 'index_start' => ($token + 34), + 'index_end' => ($token + 34), + 'arrow' => ($token + 36), + 'value_start' => ($token + 38), + ], + ]; + + $this->assertSame($expected, self::$sniff->indicies); + + }//end testArrowFunctionValue() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php new file mode 100644 index 000000000..751b01a8b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Sniffs/AbstractArraySniffTestable.php @@ -0,0 +1,65 @@ + + * @copyright 2006-2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Sniffs; + +use PHP_CodeSniffer\Sniffs\AbstractArraySniff; + +class AbstractArraySniffTestable extends AbstractArraySniff +{ + + /** + * The array indicies that were found during processing. + * + * @var array + */ + public $indicies = []; + + + /** + * Processes a single-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $this->indicies = $indices; + + }//end processSingleLineArray() + + + /** + * Processes a multi-line array definition. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param int $arrayStart The token that starts the array definition. + * @param int $arrayEnd The token that ends the array definition. + * @param array $indices An array of token positions for the array keys, + * double arrows, and values. + * + * @return void + */ + public function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices) + { + $this->indicies = $indices; + + }//end processMultiLineArray() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/AbstractTokenizerTestCase.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/AbstractTokenizerTestCase.php new file mode 100644 index 000000000..a7c1a6b09 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/AbstractTokenizerTestCase.php @@ -0,0 +1,126 @@ + + * @copyright 2018-2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers; + +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest; +use PHPUnit\Framework\TestCase; +use ReflectionProperty; + +abstract class AbstractTokenizerTestCase extends TestCase +{ + + /** + * The file extension of the test case file (without leading dot). + * + * This allows child classes to overrule the default `inc` with, for instance, + * `js` or `css` when applicable. + * + * @var string + */ + protected $fileExtension = 'inc'; + + /** + * The tab width setting to use when tokenizing the file. + * + * This allows for test case files to use a different tab width than the default. + * + * @var integer + */ + protected $tabWidth = 4; + + /** + * The \PHP_CodeSniffer\Files\File object containing the parsed contents of the test case file. + * + * @var \PHP_CodeSniffer\Files\File + */ + protected $phpcsFile; + + + /** + * Initialize & tokenize \PHP_CodeSniffer\Files\File with code from the test case file. + * + * The test case file for a unit test class has to be in the same directory + * directory and use the same file name as the test class, using the .inc extension. + * + * @before + * + * @return void + */ + protected function initializeFile() + { + if (isset($this->phpcsFile) === false) { + $_SERVER['argv'] = []; + $config = new ConfigDouble(); + + // Also set a tab-width to enable testing tab-replaced vs `orig_content`. + $config->tabWidth = $this->tabWidth; + + $ruleset = new Ruleset($config); + + // Default to a file with the same name as the test class. Extension is property based. + $relativeCN = str_replace(__NAMESPACE__, '', get_called_class()); + $relativePath = str_replace('\\', DIRECTORY_SEPARATOR, $relativeCN); + $pathToTestFile = realpath(__DIR__).$relativePath.'.'.$this->fileExtension; + + // Make sure the file gets parsed correctly based on the file type. + $contents = 'phpcs_input_file: '.$pathToTestFile.PHP_EOL; + $contents .= file_get_contents($pathToTestFile); + + $this->phpcsFile = new DummyFile($contents, $ruleset, $config); + $this->phpcsFile->parse(); + }//end if + + }//end initializeFile() + + + /** + * Get the token pointer for a target token based on a specific comment found on the line before. + * + * Note: the test delimiter comment MUST start with "/* test" to allow this function to + * distinguish between comments used *in* a test and test delimiters. + * + * @param string $commentString The delimiter comment to look for. + * @param int|string|array $tokenType The type of token(s) to look for. + * @param string $tokenContent Optional. The token content for the target token. + * + * @return int + */ + protected function getTargetToken($commentString, $tokenType, $tokenContent=null) + { + return AbstractMethodUnitTest::getTargetTokenFromFile($this->phpcsFile, $commentString, $tokenType, $tokenContent); + + }//end getTargetToken() + + + /** + * Clear the static "resolved tokens" cache property on the Tokenizer\PHP class. + * + * This method should be used selectively by tests to ensure the code under test is actually hit + * by the test testing the code. + * + * @return void + */ + public static function clearResolvedTokensCache() + { + $property = new ReflectionProperty('PHP_CodeSniffer\Tokenizers\PHP', 'resolveTokenCache'); + $property->setAccessible(true); + $property->setValue(null, []); + $property->setAccessible(false); + + }//end clearResolvedTokensCache() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/CommentTestCase.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/CommentTestCase.php new file mode 100644 index 000000000..625029db1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/CommentTestCase.php @@ -0,0 +1,117 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Base class for testing DocBlock comment tokenization. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +abstract class CommentTestCase extends AbstractTokenizerTestCase +{ + + + /** + * Test whether the docblock opener and closer have the expected extra keys. + * + * @param string $marker The comment prefacing the target token. + * @param int $closerOffset The offset of the closer from the opener. + * @param array $expectedTags The expected tags offsets array. + * + * @dataProvider dataDocblockOpenerCloser + * + * @return void + */ + public function testDocblockOpenerCloser($marker, $closerOffset, $expectedTags) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($marker, [T_DOC_COMMENT_OPEN_TAG]); + + $opener = $tokens[$target]; + + $this->assertArrayHasKey('comment_closer', $opener, 'Comment opener: comment_closer index is not set'); + $this->assertArrayHasKey('comment_tags', $opener, 'Comment opener: comment_tags index is not set'); + + $expectedCloser = ($target + $closerOffset); + $this->assertSame($expectedCloser, $opener['comment_closer'], 'Comment opener: comment_closer not set to the expected stack pointer'); + + // Update the tags expectations. + foreach ($expectedTags as $i => $ptr) { + $expectedTags[$i] += $target; + } + + $this->assertSame($expectedTags, $opener['comment_tags'], 'Comment opener: recorded tags do not match expected tags'); + + $closer = $tokens[$opener['comment_closer']]; + + $this->assertArrayHasKey('comment_opener', $closer, 'Comment closer: comment_opener index is not set'); + $this->assertSame($target, $closer['comment_opener'], 'Comment closer: comment_opener not set to the expected stack pointer'); + + }//end testDocblockOpenerCloser() + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + abstract public static function dataDocblockOpenerCloser(); + + + /** + * Test helper. Check a token sequence complies with an expected token sequence. + * + * @param int $startPtr The position in the file to start checking from. + * @param array> $expectedSequence The consecutive token constants and their contents to expect. + * + * @return void + */ + protected function checkTokenSequence($startPtr, array $expectedSequence) + { + $tokens = $this->phpcsFile->getTokens(); + + $sequenceKey = 0; + $sequenceCount = count($expectedSequence); + + for ($i = $startPtr; $sequenceKey < $sequenceCount; $i++, $sequenceKey++) { + $currentItem = $expectedSequence[$sequenceKey]; + $expectedCode = key($currentItem); + $expectedType = Tokens::tokenName($expectedCode); + $expectedContent = current($currentItem); + $errorMsgSuffix = PHP_EOL.'(StackPtr: '.$i.' | Position in sequence: '.$sequenceKey.' | Expected: '.$expectedType.')'; + + $this->assertSame( + $expectedCode, + $tokens[$i]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$i]['code']).', not '.$expectedType.' (code)'.$errorMsgSuffix + ); + + $this->assertSame( + $expectedType, + $tokens[$i]['type'], + 'Token tokenized as '.$tokens[$i]['type'].', not '.$expectedType.' (type)'.$errorMsgSuffix + ); + + $this->assertSame( + $expectedContent, + $tokens[$i]['content'], + 'Token content did not match expectations'.$errorMsgSuffix + ); + }//end for + + }//end checkTokenSequence() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding1Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding1Test.inc new file mode 100644 index 000000000..a43c7d9b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding1Test.inc @@ -0,0 +1,6 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that unclosed docblocks during live coding are handled correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class LiveCoding1Test extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'live coding: unclosed docblock, no blank line at end of file' => [ + 'marker' => '/* testLiveCoding */', + 'closerOffset' => 8, + 'expectedTags' => [], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify tokenization of the DocBlock. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testLiveCoding() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Unclosed docblock, live coding.... with no blank line at end of file.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testLiveCoding() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding2Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding2Test.inc new file mode 100644 index 000000000..b113645b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding2Test.inc @@ -0,0 +1,5 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that unclosed docblocks during live coding are handled correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class LiveCoding2Test extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'live coding: unclosed docblock with blank line at end of file' => [ + 'marker' => '/* testLiveCoding */', + 'closerOffset' => 7, + 'expectedTags' => [], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify tokenization of the DocBlock. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testLiveCoding() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Unclosed docblock, live coding.... with a blank line at end of file.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_CLOSE_TAG => ''], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testLiveCoding() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding3Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding3Test.inc new file mode 100644 index 000000000..9b81a434d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding3Test.inc @@ -0,0 +1,4 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that unclosed docblocks during live coding are handled correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class LiveCoding3Test extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'live coding: unclosed docblock, no contents, no blank line at end of file' => [ + 'marker' => '/* testLiveCoding */', + 'closerOffset' => 1, + 'expectedTags' => [], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify tokenization of the DocBlock. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testLiveCoding() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_CLOSE_TAG => ''], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testLiveCoding() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding4Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding4Test.inc new file mode 100644 index 000000000..1561e7156 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/LiveCoding4Test.inc @@ -0,0 +1,7 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that unclosed docblocks during live coding are handled correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class LiveCoding4Test extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'live coding: unclosed docblock, trailing whitespace on last line, no blank line at end of file' => [ + 'marker' => '/* testLiveCoding */', + 'closerOffset' => 15, + 'expectedTags' => [], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify tokenization of the DocBlock. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testLiveCoding() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'The last line of this test must have trailing whitespace.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'So, be careful when saving this file!'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => ''], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testLiveCoding() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/MultiLineDocBlockTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/MultiLineDocBlockTest.inc new file mode 100644 index 000000000..f33afcd6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/MultiLineDocBlockTest.inc @@ -0,0 +1,81 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that multiline docblocks are tokenized correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class MultiLineDocBlockTest extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'Multi line docblock: no contents' => [ + 'marker' => '/* testEmptyDocblock */', + 'closerOffset' => 3, + 'expectedTags' => [], + ], + 'Multi line docblock: variety of text and tags' => [ + 'marker' => '/* testMultilineDocblock */', + 'closerOffset' => 95, + // phpcs:ignore Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed + 'expectedTags' => [21, 29, 36, 46, 56, 63, 73, 80, 90], + ], + 'Multi line docblock: no leading stars' => [ + 'marker' => '/* testMultilineDocblockNoStars */', + 'closerOffset' => 32, + // phpcs:ignore Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed + 'expectedTags' => [10, 16, 21, 27], + ], + 'Multi line docblock: indented' => [ + 'marker' => '/* testMultilineDocblockIndented */', + 'closerOffset' => 60, + // phpcs:ignore Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed + 'expectedTags' => [21, 28, 38, 45, 55], + ], + 'Multi line docblock: opener not on own line' => [ + 'marker' => '/* testMultilineDocblockOpenerNotOnOwnLine */', + 'closerOffset' => 10, + 'expectedTags' => [], + ], + 'Multi line docblock: closer not on own line' => [ + 'marker' => '/* testMultilineDocblockCloserNotOnOwnLine */', + 'closerOffset' => 11, + 'expectedTags' => [], + ], + 'Multi line docblock: stars not aligned' => [ + 'marker' => '/* testMultilineDocblockStarsNotAligned */', + 'closerOffset' => 26, + 'expectedTags' => [], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify tokenization of an empty, multi-line DocBlock. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testEmptyDocblock() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testEmptyDocblock() + + + /** + * Verify tokenization of a multi-line DocBlock containing all possible tokens. + * + * @return void + */ + public function testMultilineDocblock() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'This is a multi-line docblock.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'With blank lines, stars, tags, and tag descriptions.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tagWithoutDescription'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@since'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '10.3'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@deprecated'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '11.5'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@requires'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'PHP 7.1 -- PHPUnit tag.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tag-with-dashes-is-suppported'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Description.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tag_with_underscores'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Description.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@param'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'string $p1 Description 1.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@param'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'int|false $p2 Description 2.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@return'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'void'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultilineDocblock() + + + /** + * Verify tokenization of a multi-line DocBlock with extra starts for the opener/closer and no stars on the lines between. + * + * @return void + */ + public function testMultilineDocblockNoStars() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/****'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'This is a multi-line docblock, but the lines are not marked with stars.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Then again, the opener and closer have an abundance of stars.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@since'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '10.3'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@param'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'string $p1 Description 1.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@param'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'int|false $p2 Description 2.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@return'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'void'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '**/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultilineDocblockNoStars() + + + /** + * Verify tokenization of a multi-line, indented DocBlock. + * + * @return void + */ + public function testMultilineDocblockIndented() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'This is a multi-line indented docblock.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'With blank lines, stars, tags, and tag descriptions.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@since'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '10.3'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@deprecated'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '11.5'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@param'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'string $p1 Description 1.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@param'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'int|false $p2 Description 2.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@return'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'void'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultilineDocblockIndented() + + + /** + * Verify tokenization of a multi-line DocBlock, where the opener is not on its own line. + * + * @return void + */ + public function testMultilineDocblockOpenerNotOnOwnLine() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Start of description'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'description continued.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultilineDocblockOpenerNotOnOwnLine() + + + /** + * Verify tokenization of a multi-line DocBlock, where the closer is not on its own line. + * + * @return void + */ + public function testMultilineDocblockCloserNotOnOwnLine() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Start of description'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'description continued. '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultilineDocblockCloserNotOnOwnLine() + + + /** + * Verify tokenization of a multi-line DocBlock with inconsistent indentation. + * + * @return void + */ + public function testMultilineDocblockStarsNotAligned() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Start of description.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Line below this is missing a star.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Text'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Star indented.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Closer indented.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultilineDocblockStarsNotAligned() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/PhpcsAnnotationsInDocBlockTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/PhpcsAnnotationsInDocBlockTest.inc new file mode 100644 index 000000000..d74f68d24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/PhpcsAnnotationsInDocBlockTest.inc @@ -0,0 +1,116 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that PHPCS native annotations in docblocks are tokenized correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class PhpcsAnnotationsInDocBlockTest extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'Single-line: @phpcs:ignoreFile annotation' => [ + 'marker' => '/* testSingleLineDocIgnoreFileAnnotation */', + 'closerOffset' => 3, + 'expectedTags' => [], + ], + 'Single-line: @phpcs:ignore annotation' => [ + 'marker' => '/* testSingleLineDocIgnoreAnnotation */', + 'closerOffset' => 3, + 'expectedTags' => [], + ], + 'Single-line: @phpcs:disable annotation' => [ + 'marker' => '/* testSingleLineDocDisableAnnotation */', + 'closerOffset' => 3, + 'expectedTags' => [], + ], + 'Single-line: @phpcs:enable annotation; no whitespace' => [ + 'marker' => '/* testSingleLineDocEnableAnnotationNoWhitespace */', + 'closerOffset' => 2, + 'expectedTags' => [], + ], + + 'Multi-line: @phpcs:ignoreFile at the start' => [ + 'marker' => '/* testMultiLineDocIgnoreFileAnnotationAtStart */', + 'closerOffset' => 13, + 'expectedTags' => [], + ], + 'Multi-line: @phpcs:ignore at the start' => [ + 'marker' => '/* testMultiLineDocIgnoreAnnotationAtStart */', + 'closerOffset' => 13, + 'expectedTags' => [10], + ], + 'Multi-line: @phpcs:disable at the start' => [ + 'marker' => '/* testMultiLineDocDisableAnnotationAtStart */', + 'closerOffset' => 13, + 'expectedTags' => [], + ], + 'Multi-line: @phpcs:enable at the start' => [ + 'marker' => '/* testMultiLineDocEnableAnnotationAtStart */', + 'closerOffset' => 18, + 'expectedTags' => [13], + ], + + 'Multi-line: @phpcs:ignoreFile in the middle' => [ + 'marker' => '/* testMultiLineDocIgnoreFileAnnotationInMiddle */', + 'closerOffset' => 21, + 'expectedTags' => [], + ], + 'Multi-line: @phpcs:ignore in the middle' => [ + 'marker' => '/* testMultiLineDocIgnoreAnnotationInMiddle */', + 'closerOffset' => 23, + 'expectedTags' => [5], + ], + 'Multi-line: @phpcs:disable in the middle' => [ + 'marker' => '/* testMultiLineDocDisableAnnotationInMiddle */', + 'closerOffset' => 26, + 'expectedTags' => [21], + ], + 'Multi-line: @phpcs:enable in the middle' => [ + 'marker' => '/* testMultiLineDocEnableAnnotationInMiddle */', + 'closerOffset' => 24, + 'expectedTags' => [21], + ], + + 'Multi-line: @phpcs:ignoreFile at the end' => [ + 'marker' => '/* testMultiLineDocIgnoreFileAnnotationAtEnd */', + 'closerOffset' => 16, + 'expectedTags' => [5], + ], + 'Multi-line: @phpcs:ignore at the end' => [ + 'marker' => '/* testMultiLineDocIgnoreAnnotationAtEnd */', + 'closerOffset' => 16, + 'expectedTags' => [], + ], + 'Multi-line: @phpcs:disable at the end' => [ + 'marker' => '/* testMultiLineDocDisableAnnotationAtEnd */', + 'closerOffset' => 18, + 'expectedTags' => [5], + ], + 'Multi-line: @phpcs:enable at the end' => [ + 'marker' => '/* testMultiLineDocEnableAnnotationAtEnd */', + 'closerOffset' => 16, + 'expectedTags' => [], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignoreFile annotation. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testSingleLineDocIgnoreFileAnnotation() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE_FILE => '@phpcs:ignoreFile '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocIgnoreFileAnnotation() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignore annotation. + * + * @return void + */ + public function testSingleLineDocIgnoreAnnotation() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE => '@phpcs:ignore Stnd.Cat.SniffName -- With reason '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocIgnoreAnnotation() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS disable annotation. + * + * @return void + */ + public function testSingleLineDocDisableAnnotation() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_DISABLE => '@phpcs:disable Stnd.Cat.SniffName,Stnd.Other '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocDisableAnnotation() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS enable annotation. + * + * @return void + */ + public function testSingleLineDocEnableAnnotationNoWhitespace() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_PHPCS_ENABLE => '@phpcs:enable Stnd.Cat.SniffName'], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocEnableAnnotationNoWhitespace() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignoreFile annotation at the start. + * + * @return void + */ + public function testMultiLineDocIgnoreFileAnnotationAtStart() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE_FILE => '@phpcs:ignoreFile'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Something.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocIgnoreFileAnnotationAtStart() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignore annotation at the start. + * + * @return void + */ + public function testMultiLineDocIgnoreAnnotationAtStart() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE => '@phpcs:ignore Stnd.Cat.SniffName'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tag'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocIgnoreAnnotationAtStart() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS disable annotation at the start. + * + * @return void + */ + public function testMultiLineDocDisableAnnotationAtStart() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_DISABLE => '@phpcs:disable Stnd.Cat.SniffName -- Ensure PHPCS annotations are also retokenized correctly.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Something.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocDisableAnnotationAtStart() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS enable annotation at the start. + * + * @return void + */ + public function testMultiLineDocEnableAnnotationAtStart() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_ENABLE => '@phpcs:enable Stnd.Cat,Stnd.Other'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tag'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'With description.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocEnableAnnotationAtStart() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignoreFile annotation in the middle. + * + * @return void + */ + public function testMultiLineDocIgnoreFileAnnotationInMiddle() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Check tokenization of PHPCS annotations within docblocks.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE_FILE => '@phpcs:ignoreFile'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Something.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocIgnoreFileAnnotationInMiddle() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignore annotation in the middle. + * + * @return void + */ + public function testMultiLineDocIgnoreAnnotationInMiddle() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tagBefore'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'With Description'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE => '@phpcs:ignore Stnd.Cat.SniffName'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Something.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocIgnoreAnnotationInMiddle() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS disable annotation in the middle. + * + * @return void + */ + public function testMultiLineDocDisableAnnotationInMiddle() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Check tokenization of PHPCS annotations within docblocks.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_DISABLE => '@phpcs:disable Stnd.Cat.SniffName -- Ensure PHPCS annotations are also retokenized correctly.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tagAfter'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'With Description'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocDisableAnnotationInMiddle() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS enable annotation in the middle. + * + * @return void + */ + public function testMultiLineDocEnableAnnotationInMiddle() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Check tokenization of PHPCS annotations within docblocks.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_ENABLE => '@phpcs:enable Stnd.Cat,Stnd.Other'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tagAfter'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocEnableAnnotationInMiddle() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignoreFile annotation at the end. + * + * @return void + */ + public function testMultiLineDocIgnoreFileAnnotationAtEnd() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tagBefore'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE_FILE => '@phpcs:ignoreFile'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocIgnoreFileAnnotationAtEnd() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS ignore annotation at the end. + * + * @return void + */ + public function testMultiLineDocIgnoreAnnotationAtEnd() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Check tokenization of PHPCS annotations within docblocks.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_IGNORE => '@phpcs:ignore Stnd.Cat.SniffName'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocIgnoreAnnotationAtEnd() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS disable annotation at the end. + * + * @return void + */ + public function testMultiLineDocDisableAnnotationAtEnd() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@tagBefore'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'With Description.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_DISABLE => '@phpcs:disable Stnd.Cat.SniffName -- Ensure PHPCS annotations are also retokenized correctly.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocDisableAnnotationAtEnd() + + + /** + * Verify tokenization of a single line DocBlock containing a PHPCS enable annotation at the end. + * + * @return void + */ + public function testMultiLineDocEnableAnnotationAtEnd() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Check tokenization of PHPCS annotations within docblocks.'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STAR => '*'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_PHPCS_ENABLE => '@phpcs:enable Stnd.Cat,Stnd.Other'], + [T_DOC_COMMENT_WHITESPACE => "\n"], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testMultiLineDocEnableAnnotationAtEnd() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/SingleLineDocBlockTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/SingleLineDocBlockTest.inc new file mode 100644 index 000000000..88b05ea43 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Comment/SingleLineDocBlockTest.inc @@ -0,0 +1,26 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Comment; + +/** + * Tests that single line docblocks are tokenized correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\Comment + */ +final class SingleLineDocBlockTest extends CommentTestCase +{ + + + /** + * Data provider. + * + * @see testDocblockOpenerCloser() + * + * @return array>> + */ + public static function dataDocblockOpenerCloser() + { + return [ + 'Single line docblock: empty, no whitespace' => [ + 'marker' => '/* testEmptyDocblockNoWhiteSpace */', + 'closerOffset' => 1, + 'expectedTags' => [], + ], + 'Single line docblock: only whitespace' => [ + 'marker' => '/* testEmptyDocblockWithWhiteSpace */', + 'closerOffset' => 2, + 'expectedTags' => [], + ], + 'Single line docblock: just text' => [ + 'marker' => '/* testSingleLineDocblockNoTag */', + 'closerOffset' => 3, + 'expectedTags' => [], + ], + 'Single line docblock: @var type before name' => [ + 'marker' => '/* testSingleLineDocblockWithTag1 */', + 'closerOffset' => 5, + 'expectedTags' => [2], + ], + 'Single line docblock: @var name before type' => [ + 'marker' => '/* testSingleLineDocblockWithTag2 */', + 'closerOffset' => 5, + 'expectedTags' => [2], + ], + 'Single line docblock: @see with description' => [ + 'marker' => '/* testSingleLineDocblockWithTag3 */', + 'closerOffset' => 5, + 'expectedTags' => [2], + ], + ]; + + }//end dataDocblockOpenerCloser() + + + /** + * Verify an empty block comment is tokenized as T_COMMENT, not as a docblock. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testEmptyBlockCommentNoWhiteSpace() + { + $expectedSequence = [ + [T_COMMENT => '/**/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', [T_COMMENT, T_DOC_COMMENT_OPEN_TAG]); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testEmptyBlockCommentNoWhiteSpace() + + + /** + * Verify tokenization of an empty, single line DocBlock without whitespace between the opener and closer. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testEmptyDocblockNoWhiteSpace() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testEmptyDocblockNoWhiteSpace() + + + /** + * Verify tokenization of an empty, single line DocBlock. + * + * @return void + */ + public function testEmptyDocblockWithWhiteSpace() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testEmptyDocblockWithWhiteSpace() + + + /** + * Verify tokenization of a single line DocBlock. + * + * @return void + */ + public function testSingleLineDocblockNoTag() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Just some text '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocblockNoTag() + + + /** + * Verify tokenization of a single line DocBlock with a tag. + * + * @return void + */ + public function testSingleLineDocblockWithTag1() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@var'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '\SomeClass[] $var '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocblockWithTag1() + + + /** + * Verify tokenization of a single line DocBlock with a tag. + * + * @return void + */ + public function testSingleLineDocblockWithTag2() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@var'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => '$var \SomeClass[] '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocblockWithTag2() + + + /** + * Verify tokenization of a single line DocBlock with a tag. + * + * @return void + */ + public function testSingleLineDocblockWithTag3() + { + $expectedSequence = [ + [T_DOC_COMMENT_OPEN_TAG => '/**'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_TAG => '@see'], + [T_DOC_COMMENT_WHITESPACE => ' '], + [T_DOC_COMMENT_STRING => 'Something::Else '], + [T_DOC_COMMENT_CLOSE_TAG => '*/'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_DOC_COMMENT_OPEN_TAG); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testSingleLineDocblockWithTag3() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AnonClassParenthesisOwnerTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AnonClassParenthesisOwnerTest.inc new file mode 100644 index 000000000..3ee1afd0d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AnonClassParenthesisOwnerTest.inc @@ -0,0 +1,29 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class AnonClassParenthesisOwnerTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that anonymous class tokens without parenthesis do not get assigned a parenthesis owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassNoParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassNoParentheses($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS); + $this->assertFalse(array_key_exists('parenthesis_owner', $tokens[$anonClass])); + $this->assertFalse(array_key_exists('parenthesis_opener', $tokens[$anonClass])); + $this->assertFalse(array_key_exists('parenthesis_closer', $tokens[$anonClass])); + + }//end testAnonClassNoParentheses() + + + /** + * Test that the next open/close parenthesis after an anonymous class without parenthesis + * do not get assigned the anonymous class as a parenthesis owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassNoParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassNoParenthesesNextOpenClose($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $function = $this->getTargetToken($testMarker, T_FUNCTION); + + $opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener])); + $this->assertSame($function, $tokens[$opener]['parenthesis_owner']); + + $closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer])); + $this->assertSame($function, $tokens[$closer]['parenthesis_owner']); + + }//end testAnonClassNoParenthesesNextOpenClose() + + + /** + * Data provider. + * + * @see testAnonClassNoParentheses() + * @see testAnonClassNoParenthesesNextOpenClose() + * + * @return array> + */ + public static function dataAnonClassNoParentheses() + { + return [ + 'plain' => [ + 'testMarker' => '/* testNoParentheses */', + ], + 'readonly' => [ + 'testMarker' => '/* testReadonlyNoParentheses */', + ], + 'declaration contains comments and extra whitespace' => [ + 'testMarker' => '/* testNoParenthesesAndEmptyTokens */', + ], + ]; + + }//end dataAnonClassNoParentheses() + + + /** + * Test that anonymous class tokens with parenthesis get assigned a parenthesis owner, + * opener and closer; and that the opener/closer get the anonymous class assigned as owner. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataAnonClassWithParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testAnonClassWithParentheses($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $anonClass = $this->getTargetToken($testMarker, T_ANON_CLASS); + $opener = $this->getTargetToken($testMarker, T_OPEN_PARENTHESIS); + $closer = $this->getTargetToken($testMarker, T_CLOSE_PARENTHESIS); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$anonClass])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$anonClass])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$anonClass])); + $this->assertSame($anonClass, $tokens[$anonClass]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$anonClass]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$anonClass]['parenthesis_closer']); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$opener])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$opener])); + $this->assertSame($anonClass, $tokens[$opener]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$opener]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$opener]['parenthesis_closer']); + + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer])); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$closer])); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$closer])); + $this->assertSame($anonClass, $tokens[$closer]['parenthesis_owner']); + $this->assertSame($opener, $tokens[$closer]['parenthesis_opener']); + $this->assertSame($closer, $tokens[$closer]['parenthesis_closer']); + + }//end testAnonClassWithParentheses() + + + /** + * Data provider. + * + * @see testAnonClassWithParentheses() + * + * @return array> + */ + public static function dataAnonClassWithParentheses() + { + return [ + 'plain' => [ + 'testMarker' => '/* testWithParentheses */', + ], + 'readonly' => [ + 'testMarker' => '/* testReadonlyWithParentheses */', + ], + 'declaration contains comments and extra whitespace' => [ + 'testMarker' => '/* testWithParenthesesAndEmptyTokens */', + ], + ]; + + }//end dataAnonClassWithParentheses() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.inc new file mode 100644 index 000000000..6d8adfcba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.inc @@ -0,0 +1,58 @@ + 10); + +/* testArrayWithComment */ +$var = Array /*comment*/ (1 => 10); + +/* testNestingArray */ +$var = array( + /* testNestedArray */ + array( + 'key' => 'value', + + /* testClosureReturnType */ + 'closure' => function($a) use($global) : Array {}, + ), +); + +/* testFunctionDeclarationParamType */ +function typedParam(array $a) {} + +/* testFunctionDeclarationReturnType */ +function returnType($a) : int|array|null {} + +class Bar { + /* testClassConst */ + const ARRAY = []; + + /* testClassMethod */ + public function array() {} + + /* testOOConstType */ + const array /* testTypedOOConstName */ ARRAY = /* testOOConstDefault */ array(); + + /* testOOPropertyType */ + protected array $property; +} + +class DNFTypes { + /* testOOConstDNFType */ + const (A&B)|array|(C&D) NAME = []; + + /* testOOPropertyDNFType */ + protected (A&B)|ARRAY|null $property; + + /* testFunctionDeclarationParamDNFType */ + public function name(null|array|(A&B) $param) { + /* testClosureDeclarationParamDNFType */ + $cl = function ( array|(A&B) $param) {}; + + /* testArrowDeclarationReturnDNFType */ + $arrow = fn($a): (A&B)|Array => new $a; + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.php new file mode 100644 index 000000000..e19c2ffbf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ArrayKeywordTest.php @@ -0,0 +1,200 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class ArrayKeywordTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the array keyword is correctly tokenized as `T_ARRAY`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testArrayKeyword($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (code)'); + $this->assertSame('T_ARRAY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (type)'); + + }//end testArrayKeyword() + + + /** + * Data provider. + * + * @see testArrayKeyword() + * + * @return array> + */ + public static function dataArrayKeyword() + { + return [ + 'empty array' => [ + 'testMarker' => '/* testEmptyArray */', + ], + 'array with space before parenthesis' => [ + 'testMarker' => '/* testArrayWithSpace */', + ], + 'array with comment before parenthesis' => [ + 'testMarker' => '/* testArrayWithComment */', + 'testContent' => 'Array', + ], + 'nested: outer array' => [ + 'testMarker' => '/* testNestingArray */', + ], + 'nested: inner array' => [ + 'testMarker' => '/* testNestedArray */', + ], + 'OO constant default value' => [ + 'testMarker' => '/* testOOConstDefault */', + ], + ]; + + }//end dataArrayKeyword() + + + /** + * Test that the array keyword when used in a type declaration is correctly tokenized as `T_STRING`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayType + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testArrayType($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testArrayType() + + + /** + * Data provider. + * + * @see testArrayType() + * + * @return array> + */ + public static function dataArrayType() + { + return [ + 'closure return type' => [ + 'testMarker' => '/* testClosureReturnType */', + 'testContent' => 'Array', + ], + 'function param type' => [ + 'testMarker' => '/* testFunctionDeclarationParamType */', + ], + 'function union return type' => [ + 'testMarker' => '/* testFunctionDeclarationReturnType */', + ], + 'OO constant type' => [ + 'testMarker' => '/* testOOConstType */', + ], + 'OO property type' => [ + 'testMarker' => '/* testOOPropertyType */', + ], + + 'OO constant DNF type' => [ + 'testMarker' => '/* testOOConstDNFType */', + ], + 'OO property DNF type' => [ + 'testMarker' => '/* testOOPropertyDNFType */', + 'testContent' => 'ARRAY', + ], + 'function param DNF type' => [ + 'testMarker' => '/* testFunctionDeclarationParamDNFType */', + ], + 'closure param DNF type' => [ + 'testMarker' => '/* testClosureDeclarationParamDNFType */', + ], + 'arrow return DNF type' => [ + 'testMarker' => '/* testArrowDeclarationReturnDNFType */', + 'testContent' => 'Array', + ], + ]; + + }//end dataArrayType() + + + /** + * Verify that the retokenization of `T_ARRAY` tokens to `T_STRING` is handled correctly + * for tokens with the contents 'array' which aren't in actual fact the array keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotArrayKeyword($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testNotArrayKeyword() + + + /** + * Data provider. + * + * @see testNotArrayKeyword() + * + * @return array> + */ + public static function dataNotArrayKeyword() + { + return [ + 'class-constant-name' => [ + 'testMarker' => '/* testClassConst */', + 'testContent' => 'ARRAY', + ], + 'class-method-name' => [ + 'testMarker' => '/* testClassMethod */', + ], + 'class-constant-name-after-type' => [ + 'testMarker' => '/* testTypedOOConstName */', + 'testContent' => 'ARRAY', + ], + ]; + + }//end dataNotArrayKeyword() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.inc new file mode 100644 index 000000000..e539adf8a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.inc @@ -0,0 +1,90 @@ + 'foobar'])] +function attribute_with_params_on_function_test() {} + +/* testAttributeWithShortClosureParameter */ +#[AttributeWithParams(static fn ($value) => ! $value)] +function attribute_with_short_closure_param_test() {} + +/* testTwoAttributeOnTheSameLine */ +#[CustomAttribute] #[AttributeWithParams('foo')] +function two_attribute_on_same_line_test() {} + +/* testAttributeAndCommentOnTheSameLine */ +#[CustomAttribute] // This is a comment +function attribute_and_line_comment_on_same_line_test() {} + +/* testAttributeGrouping */ +#[CustomAttribute, AttributeWithParams('foo'), AttributeWithParams('foo', bar: ['bar' => 'foobar'])] +function attribute_grouping_test() {} + +/* testAttributeMultiline */ +#[ + CustomAttribute, + AttributeWithParams('foo'), + AttributeWithParams('foo', bar: ['bar' => 'foobar']) +] +function attribute_multiline_test() {} + +/* testAttributeMultilineWithComment */ +#[ + CustomAttribute, // comment + AttributeWithParams(/* another comment */ 'foo'), + AttributeWithParams('foo', bar: ['bar' => 'foobar']) +] +function attribute_multiline_with_comment_test() {} + +/* testSingleAttributeOnParameter */ +function single_attribute_on_parameter_test(#[ParamAttribute] int $param) {} + +/* testMultipleAttributesOnParameter */ +function multiple_attributes_on_parameter_test(#[ParamAttribute, AttributeWithParams(/* another comment */ 'foo')] int $param) {} + +/* testFqcnAttribute */ +#[Boo\QualifiedName, \Foo\FullyQualifiedName('foo')] +function fqcn_attrebute_test() {} + +/* testNestedAttributes */ +#[Boo\QualifiedName(fn (#[AttributeOne('boo')] $value) => (string) $value)] +function nested_attributes_test() {} + +/* testMultilineAttributesOnParameter */ +function multiline_attributes_on_parameter_test(#[ + AttributeWithParams( + 'foo' + ) + ] int $param) {} + +/* testAttributeContainingTextLookingLikeCloseTag */ +#[DeprecationReason('reason: ')] +function attribute_containing_text_looking_like_close_tag() {} + +/* testAttributeContainingMultilineTextLookingLikeCloseTag */ +#[DeprecationReason( + 'reason: ' +)] +function attribute_containing_mulitline_text_looking_like_close_tag() {} + +/* testInvalidAttribute */ +#[ThisIsNotAnAttribute +function invalid_attribute_test() {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.php new file mode 100644 index 000000000..43952b628 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/AttributesTest.php @@ -0,0 +1,704 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class AttributesTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that attributes are parsed correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $length The number of tokens between opener and closer. + * @param array $tokenCodes The codes of tokens inside the attributes. + * + * @dataProvider dataAttribute + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttribute($testMarker, $length, $tokenCodes) + { + $tokens = $this->phpcsFile->getTokens(); + + $attribute = $this->getTargetToken($testMarker, T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + $length), $closer); + + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $map = array_map( + function ($token) use ($attribute, $length) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), ($length - 1)) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testAttribute() + + + /** + * Data provider. + * + * @see testAttribute() + * + * @return array>> + */ + public static function dataAttribute() + { + return [ + 'class attribute' => [ + 'testMarker' => '/* testAttribute */', + 'length' => 2, + 'tokenCodes' => [ + T_STRING + ], + ], + 'class attribute with param' => [ + 'testMarker' => '/* testAttributeWithParams */', + 'length' => 7, + 'tokenCodes' => [ + T_STRING, + T_OPEN_PARENTHESIS, + T_STRING, + T_DOUBLE_COLON, + T_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + 'class attribute with named param' => [ + 'testMarker' => '/* testAttributeWithNamedParam */', + 'length' => 10, + 'tokenCodes' => [ + T_STRING, + T_OPEN_PARENTHESIS, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_STRING, + T_DOUBLE_COLON, + T_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + 'function attribute' => [ + 'testMarker' => '/* testAttributeOnFunction */', + 'length' => 2, + 'tokenCodes' => [ + T_STRING + ], + ], + 'function attribute with params' => [ + 'testMarker' => '/* testAttributeOnFunctionWithParams */', + 'length' => 17, + 'tokenCodes' => [ + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + ], + ], + 'function attribute with arrow function as param' => [ + 'testMarker' => '/* testAttributeWithShortClosureParameter */', + 'length' => 17, + 'tokenCodes' => [ + T_STRING, + T_OPEN_PARENTHESIS, + T_STATIC, + T_WHITESPACE, + T_FN, + T_WHITESPACE, + T_OPEN_PARENTHESIS, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_FN_ARROW, + T_WHITESPACE, + T_BOOLEAN_NOT, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + ], + ], + 'function attribute; multiple comma separated classes' => [ + 'testMarker' => '/* testAttributeGrouping */', + 'length' => 26, + 'tokenCodes' => [ + T_STRING, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + ], + ], + 'function attribute; multiple comma separated classes, one per line' => [ + 'testMarker' => '/* testAttributeMultiline */', + 'length' => 31, + 'tokenCodes' => [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + ], + ], + 'function attribute; multiple comma separated classes, one per line, with comments' => [ + 'testMarker' => '/* testAttributeMultilineWithComment */', + 'length' => 34, + 'tokenCodes' => [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_COMMENT, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_COMMENT, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_COMMA, + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_COMMA, + T_WHITESPACE, + T_PARAM_NAME, + T_COLON, + T_WHITESPACE, + T_OPEN_SHORT_ARRAY, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_DOUBLE_ARROW, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_SHORT_ARRAY, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + ], + ], + 'function attribute; using partially qualified and fully qualified class names' => [ + 'testMarker' => '/* testFqcnAttribute */', + 'length' => 13, + 'tokenCodes' => [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_COMMA, + T_WHITESPACE, + T_NS_SEPARATOR, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + ]; + + }//end dataAttribute() + + + /** + * Test that multiple attributes on the same line are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testTwoAttributesOnTheSameLine() + { + $tokens = $this->phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testTwoAttributeOnTheSameLine */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_ATTRIBUTE, $tokens[($closer + 2)]['code']); + $this->assertArrayHasKey('attribute_closer', $tokens[($closer + 2)]); + + }//end testTwoAttributesOnTheSameLine() + + + /** + * Test that attribute followed by a line comment is parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttributeAndLineComment() + { + $tokens = $this->phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testAttributeAndCommentOnTheSameLine */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_COMMENT, $tokens[($closer + 2)]['code']); + + }//end testAttributeAndLineComment() + + + /** + * Test that attributes on function declaration parameters are parsed correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $position The token position (starting from T_FUNCTION) of T_ATTRIBUTE token. + * @param int $length The number of tokens between opener and closer. + * @param array $tokenCodes The codes of tokens inside the attributes. + * + * @dataProvider dataAttributeOnParameters + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testAttributeOnParameters($testMarker, $position, $length, array $tokenCodes) + { + $tokens = $this->phpcsFile->getTokens(); + + $function = $this->getTargetToken($testMarker, T_FUNCTION); + $attribute = ($function + $position); + + $this->assertSame(T_ATTRIBUTE, $tokens[$attribute]['code']); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $this->assertSame(($attribute + $length), $tokens[$attribute]['attribute_closer']); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(T_WHITESPACE, $tokens[($closer + 1)]['code']); + $this->assertSame(T_STRING, $tokens[($closer + 2)]['code']); + $this->assertSame('int', $tokens[($closer + 2)]['content']); + + $this->assertSame(T_VARIABLE, $tokens[($closer + 4)]['code']); + $this->assertSame('$param', $tokens[($closer + 4)]['content']); + + $map = array_map( + function ($token) use ($attribute, $length) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), ($length - 1)) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testAttributeOnParameters() + + + /** + * Data provider. + * + * @see testAttributeOnParameters() + * + * @return array>> + */ + public static function dataAttributeOnParameters() + { + return [ + 'parameter attribute; single, inline' => [ + 'testMarker' => '/* testSingleAttributeOnParameter */', + 'position' => 4, + 'length' => 2, + 'tokenCodes' => [ + T_STRING + ], + ], + 'parameter attribute; multiple comma separated, inline' => [ + 'testMarker' => '/* testMultipleAttributesOnParameter */', + 'position' => 4, + 'length' => 10, + 'tokenCodes' => [ + T_STRING, + T_COMMA, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_COMMENT, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + ], + ], + 'parameter attribute; single, multiline' => [ + 'testMarker' => '/* testMultilineAttributesOnParameter */', + 'position' => 4, + 'length' => 13, + 'tokenCodes' => [ + T_WHITESPACE, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_WHITESPACE, + T_WHITESPACE, + T_CONSTANT_ENCAPSED_STRING, + T_WHITESPACE, + T_WHITESPACE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_WHITESPACE, + ], + ], + ]; + + }//end dataAttributeOnParameters() + + + /** + * Test that an attribute containing text which looks like a PHP close tag is tokenized correctly. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $length The number of tokens between opener and closer. + * @param array> $expectedTokensAttribute The codes of tokens inside the attributes. + * @param array $expectedTokensAfter The codes of tokens after the attributes. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @dataProvider dataAttributeOnTextLookingLikeCloseTag + * + * @return void + */ + public function testAttributeContainingTextLookingLikeCloseTag($testMarker, $length, array $expectedTokensAttribute, array $expectedTokensAfter) + { + $tokens = $this->phpcsFile->getTokens(); + + $attribute = $this->getTargetToken($testMarker, T_ATTRIBUTE); + + $this->assertSame('T_ATTRIBUTE', $tokens[$attribute]['type']); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + $length), $closer); + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + $this->assertSame('T_ATTRIBUTE_END', $tokens[$closer]['type']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $i = ($attribute + 1); + foreach ($expectedTokensAttribute as $item) { + list($expectedType, $expectedContents) = $item; + $this->assertSame($expectedType, $tokens[$i]['type']); + $this->assertSame($expectedContents, $tokens[$i]['content']); + $this->assertArrayHasKey('attribute_opener', $tokens[$i]); + $this->assertArrayHasKey('attribute_closer', $tokens[$i]); + ++$i; + } + + $i = ($closer + 1); + foreach ($expectedTokensAfter as $expectedCode) { + $this->assertSame($expectedCode, $tokens[$i]['code']); + ++$i; + } + + }//end testAttributeContainingTextLookingLikeCloseTag() + + + /** + * Data provider. + * + * @see dataAttributeOnTextLookingLikeCloseTag() + * + * @return array>|array>> + */ + public static function dataAttributeOnTextLookingLikeCloseTag() + { + return [ + 'function attribute; string param with "?>"' => [ + 'testMarker' => '/* testAttributeContainingTextLookingLikeCloseTag */', + 'length' => 5, + 'expectedTokensAttribute' => [ + [ + 'T_STRING', + 'DeprecationReason', + ], + [ + 'T_OPEN_PARENTHESIS', + '(', + ], + [ + 'T_CONSTANT_ENCAPSED_STRING', + "'reason: '", + ], + [ + 'T_CLOSE_PARENTHESIS', + ')', + ], + [ + 'T_ATTRIBUTE_END', + ']', + ], + ], + 'expectedTokensAfter' => [ + T_WHITESPACE, + T_FUNCTION, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + ], + 'function attribute; string param with "?>"; multiline' => [ + 'testMarker' => '/* testAttributeContainingMultilineTextLookingLikeCloseTag */', + 'length' => 8, + 'expectedTokensAttribute' => [ + [ + 'T_STRING', + 'DeprecationReason', + ], + [ + 'T_OPEN_PARENTHESIS', + '(', + ], + [ + 'T_WHITESPACE', + "\n", + ], + [ + 'T_WHITESPACE', + " ", + ], + [ + 'T_CONSTANT_ENCAPSED_STRING', + "'reason: '", + ], + [ + 'T_WHITESPACE', + "\n", + ], + [ + 'T_CLOSE_PARENTHESIS', + ')', + ], + [ + 'T_ATTRIBUTE_END', + ']', + ], + ], + 'expectedTokensAfter' => [ + T_WHITESPACE, + T_FUNCTION, + T_WHITESPACE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ], + ], + ]; + + }//end dataAttributeOnTextLookingLikeCloseTag() + + + /** + * Test that invalid attribute (or comment starting with #[ and without ]) are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * + * @return void + */ + public function testInvalidAttribute() + { + $tokens = $this->phpcsFile->getTokens(); + + $attribute = $this->getTargetToken('/* testInvalidAttribute */', T_ATTRIBUTE); + + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + $this->assertNull($tokens[$attribute]['attribute_closer']); + + }//end testInvalidAttribute() + + + /** + * Test that nested attributes are parsed correctly. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::findCloser + * @covers PHP_CodeSniffer\Tokenizers\PHP::parsePhpAttribute + * @covers PHP_CodeSniffer\Tokenizers\PHP::createAttributesNestingMap + * + * @return void + */ + public function testNestedAttributes() + { + $tokens = $this->phpcsFile->getTokens(); + $tokenCodes = [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_OPEN_PARENTHESIS, + T_FN, + T_WHITESPACE, + T_OPEN_PARENTHESIS, + T_ATTRIBUTE, + T_STRING, + T_OPEN_PARENTHESIS, + T_CONSTANT_ENCAPSED_STRING, + T_CLOSE_PARENTHESIS, + T_ATTRIBUTE_END, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_WHITESPACE, + T_FN_ARROW, + T_WHITESPACE, + T_STRING_CAST, + T_WHITESPACE, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + ]; + + $attribute = $this->getTargetToken('/* testNestedAttributes */', T_ATTRIBUTE); + $this->assertArrayHasKey('attribute_closer', $tokens[$attribute]); + + $closer = $tokens[$attribute]['attribute_closer']; + $this->assertSame(($attribute + 24), $closer); + + $this->assertSame(T_ATTRIBUTE_END, $tokens[$closer]['code']); + + $this->assertSame($tokens[$attribute]['attribute_opener'], $tokens[$closer]['attribute_opener']); + $this->assertSame($tokens[$attribute]['attribute_closer'], $tokens[$closer]['attribute_closer']); + + $this->assertArrayNotHasKey('nested_attributes', $tokens[$attribute]); + $this->assertArrayHasKey('nested_attributes', $tokens[($attribute + 8)]); + $this->assertSame([$attribute => ($attribute + 24)], $tokens[($attribute + 8)]['nested_attributes']); + + $test = function (array $tokens, $length, $nestedMap) use ($attribute) { + foreach ($tokens as $token) { + $this->assertArrayHasKey('attribute_closer', $token); + $this->assertSame(($attribute + $length), $token['attribute_closer']); + $this->assertSame($nestedMap, $token['nested_attributes']); + } + }; + + $test(array_slice($tokens, ($attribute + 1), 7), 24, [$attribute => $attribute + 24]); + $test(array_slice($tokens, ($attribute + 8), 1), 8 + 5, [$attribute => $attribute + 24]); + + // Length here is 8 (nested attribute offset) + 5 (real length). + $test( + array_slice($tokens, ($attribute + 9), 4), + 8 + 5, + [ + $attribute => $attribute + 24, + $attribute + 8 => $attribute + 13, + ] + ); + + $test(array_slice($tokens, ($attribute + 13), 1), 8 + 5, [$attribute => $attribute + 24]); + $test(array_slice($tokens, ($attribute + 14), 10), 24, [$attribute => $attribute + 24]); + + $map = array_map( + static function ($token) { + return $token['code']; + }, + array_slice($tokens, ($attribute + 1), 23) + ); + + $this->assertSame($tokenCodes, $map); + + }//end testNestedAttributes() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.inc new file mode 100644 index 000000000..16624ecce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.inc @@ -0,0 +1,91 @@ +enum = 'foo'; + } +} + +/* testEnumUsedAsFunctionName */ +function enum() +{ +} + +/* testDeclarationContainingComment */ +enum /* comment */ Name +{ + case SOME_CASE; +} + +/* testEnumUsedAsNamespaceName */ +namespace Enum; +/* testEnumUsedAsPartOfNamespaceName */ +namespace My\Enum\Collection; +/* testEnumUsedInObjectInitialization */ +$obj = new Enum; +/* testEnumAsFunctionCall */ +$var = enum($a, $b); +/* testEnumAsFunctionCallWithNamespace */ +var = namespace\enum(); +/* testClassConstantFetchWithEnumAsClassName */ +echo Enum::CONSTANT; +/* testClassConstantFetchWithEnumAsConstantName */ +echo ClassName::ENUM; + +/* testParseErrorMissingName */ +enum { + case SOME_CASE; +} + +/* testParseErrorLiveCoding */ +// This must be the last test in the file. +enum diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.php new file mode 100644 index 000000000..9b313ca69 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillEnumTest.php @@ -0,0 +1,226 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class BackfillEnumTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the "enum" keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * @param int $openerOffset Offset to find expected scope opener. + * @param int $closerOffset Offset to find expected scope closer. + * + * @dataProvider dataEnums + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testEnums($testMarker, $testContent, $openerOffset, $closerOffset) + { + $tokens = $this->phpcsFile->getTokens(); + $enum = $this->getTargetToken($testMarker, [T_ENUM, T_STRING], $testContent); + $tokenArray = $tokens[$enum]; + + $this->assertSame(T_ENUM, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM (code)'); + $this->assertSame('T_ENUM', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM (type)'); + + $this->assertArrayHasKey('scope_condition', $tokenArray); + $this->assertArrayHasKey('scope_opener', $tokenArray); + $this->assertArrayHasKey('scope_closer', $tokenArray); + + $this->assertSame($enum, $tokenArray['scope_condition']); + + $scopeOpener = $tokenArray['scope_opener']; + $scopeCloser = $tokenArray['scope_closer']; + + $expectedScopeOpener = ($enum + $openerOffset); + $expectedScopeCloser = ($enum + $closerOffset); + + $this->assertSame($expectedScopeOpener, $scopeOpener); + $this->assertArrayHasKey('scope_condition', $tokens[$scopeOpener]); + $this->assertArrayHasKey('scope_opener', $tokens[$scopeOpener]); + $this->assertArrayHasKey('scope_closer', $tokens[$scopeOpener]); + $this->assertSame($enum, $tokens[$scopeOpener]['scope_condition']); + $this->assertSame($scopeOpener, $tokens[$scopeOpener]['scope_opener']); + $this->assertSame($scopeCloser, $tokens[$scopeOpener]['scope_closer']); + + $this->assertSame($expectedScopeCloser, $scopeCloser); + $this->assertArrayHasKey('scope_condition', $tokens[$scopeCloser]); + $this->assertArrayHasKey('scope_opener', $tokens[$scopeCloser]); + $this->assertArrayHasKey('scope_closer', $tokens[$scopeCloser]); + $this->assertSame($enum, $tokens[$scopeCloser]['scope_condition']); + $this->assertSame($scopeOpener, $tokens[$scopeCloser]['scope_opener']); + $this->assertSame($scopeCloser, $tokens[$scopeCloser]['scope_closer']); + + }//end testEnums() + + + /** + * Data provider. + * + * @see testEnums() + * + * @return array> + */ + public static function dataEnums() + { + return [ + 'enum - pure' => [ + 'testMarker' => '/* testPureEnum */', + 'testContent' => 'enum', + 'openerOffset' => 4, + 'closerOffset' => 12, + ], + 'enum - backed int' => [ + 'testMarker' => '/* testBackedIntEnum */', + 'testContent' => 'enum', + 'openerOffset' => 7, + 'closerOffset' => 29, + ], + 'enum - backed string' => [ + 'testMarker' => '/* testBackedStringEnum */', + 'testContent' => 'enum', + 'openerOffset' => 8, + 'closerOffset' => 30, + ], + 'enum - backed int + implements' => [ + 'testMarker' => '/* testComplexEnum */', + 'testContent' => 'enum', + 'openerOffset' => 11, + 'closerOffset' => 72, + ], + 'enum keyword when "enum" is the name for the construct (yes, this is allowed)' => [ + 'testMarker' => '/* testEnumWithEnumAsClassName */', + 'testContent' => 'enum', + 'openerOffset' => 6, + 'closerOffset' => 7, + ], + 'enum - keyword is case insensitive' => [ + 'testMarker' => '/* testEnumIsCaseInsensitive */', + 'testContent' => 'EnUm', + 'openerOffset' => 4, + 'closerOffset' => 5, + ], + 'enum - declaration containing comment' => [ + 'testMarker' => '/* testDeclarationContainingComment */', + 'testContent' => 'enum', + 'openerOffset' => 6, + 'closerOffset' => 14, + ], + ]; + + }//end dataEnums() + + + /** + * Test that "enum" when not used as the keyword is still tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotEnums + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotEnums($testMarker, $testContent) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_ENUM, T_STRING], $testContent); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testNotEnums() + + + /** + * Data provider. + * + * @see testNotEnums() + * + * @return array> + */ + public static function dataNotEnums() + { + return [ + 'not enum - construct named enum' => [ + 'testMarker' => '/* testEnumAsClassNameAfterEnumKeyword */', + 'testContent' => 'Enum', + ], + 'not enum - class named enum' => [ + 'testMarker' => '/* testEnumUsedAsClassName */', + 'testContent' => 'Enum', + ], + 'not enum - class constant named enum' => [ + 'testMarker' => '/* testEnumUsedAsClassConstantName */', + 'testContent' => 'ENUM', + ], + 'not enum - method named enum' => [ + 'testMarker' => '/* testEnumUsedAsMethodName */', + 'testContent' => 'enum', + ], + 'not enum - class property named enum' => [ + 'testMarker' => '/* testEnumUsedAsPropertyName */', + 'testContent' => 'enum', + ], + 'not enum - global function named enum' => [ + 'testMarker' => '/* testEnumUsedAsFunctionName */', + 'testContent' => 'enum', + ], + 'not enum - namespace named enum' => [ + 'testMarker' => '/* testEnumUsedAsNamespaceName */', + 'testContent' => 'Enum', + ], + 'not enum - part of namespace named enum' => [ + 'testMarker' => '/* testEnumUsedAsPartOfNamespaceName */', + 'testContent' => 'Enum', + ], + 'not enum - class instantiation for class enum' => [ + 'testMarker' => '/* testEnumUsedInObjectInitialization */', + 'testContent' => 'Enum', + ], + 'not enum - function call' => [ + 'testMarker' => '/* testEnumAsFunctionCall */', + 'testContent' => 'enum', + ], + 'not enum - namespace relative function call' => [ + 'testMarker' => '/* testEnumAsFunctionCallWithNamespace */', + 'testContent' => 'enum', + ], + 'not enum - class constant fetch with enum as class name' => [ + 'testMarker' => '/* testClassConstantFetchWithEnumAsClassName */', + 'testContent' => 'Enum', + ], + 'not enum - class constant fetch with enum as constant name' => [ + 'testMarker' => '/* testClassConstantFetchWithEnumAsConstantName */', + 'testContent' => 'ENUM', + ], + 'parse error, not enum - enum declaration without name' => [ + 'testMarker' => '/* testParseErrorMissingName */', + 'testContent' => 'enum', + ], + 'parse error, not enum - enum declaration with curlies' => [ + 'testMarker' => '/* testParseErrorLiveCoding */', + 'testContent' => 'enum', + ], + ]; + + }//end dataNotEnums() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillExplicitOctalNotationTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillExplicitOctalNotationTest.inc new file mode 100644 index 000000000..eb907ed39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillExplicitOctalNotationTest.inc @@ -0,0 +1,31 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class BackfillExplicitOctalNotationTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that explicitly-defined octal values are tokenized as a single number and not as a number and a string. + * + * @param string $marker The comment which prefaces the target token in the test file. + * @param string $value The expected content of the token. + * @param int|string $nextToken The expected next token. + * @param string $nextContent The expected content of the next token. + * + * @dataProvider dataExplicitOctalNotation + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testExplicitOctalNotation($marker, $value, $nextToken, $nextContent) + { + $tokens = $this->phpcsFile->getTokens(); + + $number = $this->getTargetToken($marker, [T_LNUMBER]); + + $this->assertSame($value, $tokens[$number]['content'], 'Content of integer token does not match expectation'); + + $this->assertSame($nextToken, $tokens[($number + 1)]['code'], 'Next token is not the expected type, but '.$tokens[($number + 1)]['type']); + $this->assertSame($nextContent, $tokens[($number + 1)]['content'], 'Next token did not have the expected contents'); + + }//end testExplicitOctalNotation() + + + /** + * Data provider. + * + * @see testExplicitOctalNotation() + * + * @return array> + */ + public static function dataExplicitOctalNotation() + { + return [ + 'Explicit octal' => [ + 'marker' => '/* testExplicitOctal */', + 'value' => '0o137041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + 'Explicit octal - capitalized O' => [ + 'marker' => '/* testExplicitOctalCapitalised */', + 'value' => '0O137041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + 'Explicit octal - with numeric literal separator' => [ + 'marker' => '/* testExplicitOctalWithNumericSeparator */', + 'value' => '0o137_041', + 'nextToken' => T_SEMICOLON, + 'nextContent' => ';', + ], + 'Invalid explicit octal - numeric literal separator directly after "0o"' => [ + 'marker' => '/* testInvalid1 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o_137', + ], + 'Invalid explicit octal - numeric literal separator directly after "0O" (capitalized O)' => [ + 'marker' => '/* testInvalid2 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'O_41', + ], + 'Invalid explicit octal - number out of octal range' => [ + 'marker' => '/* testInvalid3 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o91', + ], + 'Invalid explicit octal - part of the number out of octal range' => [ + 'marker' => '/* testInvalid4 */', + 'value' => '0O2', + 'nextToken' => T_LNUMBER, + 'nextContent' => '82', + ], + 'Invalid explicit octal - part of the number out of octal range with numeric literal separator after' => [ + 'marker' => '/* testInvalid5 */', + 'value' => '0o2', + 'nextToken' => T_LNUMBER, + 'nextContent' => '8_2', + ], + 'Invalid explicit octal - part of the number out of octal range with numeric literal separator before' => [ + 'marker' => '/* testInvalid6 */', + 'value' => '0o2', + 'nextToken' => T_STRING, + 'nextContent' => '_82', + ], + 'Invalid explicit octal - explicit notation without number' => [ + 'marker' => '/* testInvalid7 */', + 'value' => '0', + 'nextToken' => T_STRING, + 'nextContent' => 'o', + ], + ]; + + }//end dataExplicitOctalNotation() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.inc new file mode 100644 index 000000000..cbb7b63bf --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.inc @@ -0,0 +1,228 @@ + $x + $y; + +/* testMixedCase */ +$fn1 = Fn($x) => $x + $y; + +/* testWhitespace */ +$fn1 = fn ($x) => $x + $y; + +/* testComment */ +$fn1 = fn /* comment here */ ($x) => $x + $y; + +/* testHeredoc */ +$fn1 = fn() => << /* testNestedInner */ fn($y) => $x * $y + $z; + +/* testNestedSharedCloserOuter */ +$foo = foo(fn() => /* testNestedSharedCloserInner */ fn() => bar() === true); + +/* testFunctionCall */ +$extended = fn($c) => $callable($factory($c), $c); + +/* testChainedFunctionCall */ +$result = Collection::from([1, 2]) + ->map(fn($v) => $v * 2) + ->reduce(/* testFunctionArgument */ fn($tmp, $v) => $tmp + $v, 0); + +/* testClosure */ +$extended = fn($c) => $callable(function() { + for ($x = 1; $x < 10; $x++) { + echo $x; + } + + echo 'done'; +}, $c); + +/* testArrayIndex */ +$found = in_array_cb($needle, $haystack, fn($array, $needle) => $array[2] === $needle); + +$result = array_map( + /* testReturnType */ + static fn(int $number) : int => $number + 1, + $numbers +); + +/* testReference */ +fn&($x) => $x; + +/* testGrouped */ +(fn($x) => $x) + $y; + +/* testArrayValue */ +$a = [ + 'a' => fn() => return 1, +]; + +/* testArrayValueNoTrailingComma */ +$a = [ + 'a' => fn() => foo() +]; + +/* testYield */ +$a = fn($x) => yield 'k' => $x; + +/* testNullableNamespace */ +$a = fn(?\DateTime $x) : ?\DateTime => $x; + +/* testNamespaceOperatorInTypes */ +$fn = fn(namespace\Foo $a) : ?namespace\Foo => $a; + +/* testSelfReturnType */ +fn(self $a) : self => $a; + +/* testParentReturnType */ +fn(parent $a) : parent => $a; + +/* testCallableReturnType */ +fn(callable $a) : callable => $a; + +/* testArrayReturnType */ +fn(array $a) : array => $a; + +/* testStaticReturnType */ +fn(array $a) : static => $a; + +/* testFalseReturnType */ +fn(array $a) : false => $a; + +/* testTrueReturnType */ +fn(array $a) : True => $a; + +/* testNullReturnType */ +fn(array $a) : null => $a; + +/* testUnionParamType */ +$arrowWithUnionParam = fn(int|float $param) : SomeClass => new SomeClass($param); + +/* testUnionReturnType */ +$arrowWithUnionReturn = fn($param) : int|float => $param | 10; + +/* testUnionReturnTypeWithTrue */ +$arrowWithUnionReturn = fn($param) : int|true => $param | 10; + +/* testUnionReturnTypeWithFalse */ +$arrowWithUnionReturn = fn($param) : string|FALSE => $param | 10; + +/* testIntersectionParamType */ +$arrowWithUnionParam = fn(Traversable&Countable $param) : int => (new SomeClass($param))->getValue(); + +/* testIntersectionReturnType */ +$arrowWithUnionReturn = fn($param) : \MyFoo&SomeInterface => new SomeClass($param); + +/* testDNFParamType */ +$arrowWithUnionParam = fn((Traversable&Countable)|null $param) : SomeClass => new SomeClass($param) ?? null; + +/* testDNFReturnType */ +$arrowWithUnionReturn = fn($param) : false|(\MyFoo&SomeInterface) => new \MyFoo($param) ?? false; + +/* testDNFParamTypeWithReturnByRef */ +$arrowWithParamReturnByRef = fn &((A&B)|null $param) => $param * 10; + +/* testTernary */ +$fn = fn($a) => $a ? /* testTernaryThen */ fn() : string => 'a' : /* testTernaryElse */ fn() : string => 'b'; + +/* testTernaryWithTypes */ +$fn = fn(int|null $a) : array|null => $a ? null : []; + +function matchInArrow($x) { + /* testWithMatchValue */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + }; +} + +function matchInArrowAndMore($x) { + /* testWithMatchValueAndMore */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + } . 'suffix'; +} + +function arrowFunctionInMatchWithTrailingComma($x) { + return match ($x) { + /* testInMatchNotLastValue */ + 1 => fn($y) => callMe($y), + /* testInMatchLastValueWithTrailingComma */ + default => fn($y) => callThem($y), + }; +} + +function arrowFunctionInMatchNoTrailingComma1($x) { + return match ($x) { + 1 => fn($y) => callMe($y), + /* testInMatchLastValueNoTrailingComma1 */ + default => fn($y) => callThem($y) + }; +} + +function arrowFunctionInMatchNoTrailingComma2($x) { + return match ($x) { + /* testInMatchLastValueNoTrailingComma2 */ + default => fn($y) => 5 * $y + }; +} + +/* testConstantDeclaration */ +const FN = 'a'; + +/* testConstantDeclarationLower */ +const fn = 'a'; + +class Foo { + /* testStaticMethodName */ + public static function fn($param) { + /* testNestedInMethod */ + $fn = fn($c) => $callable($factory($c), $c); + } + + public function foo() { + /* testPropertyAssignment */ + $this->fn = 'a'; + } +} + +$anon = new class() { + /* testAnonClassMethodName */ + protected function fN($param) { + } +} + +/* testNonArrowStaticMethodCall */ +$a = Foo::fn($param); + +/* testNonArrowConstantAccess */ +$a = MyClass::FN; + +/* testNonArrowConstantAccessMixed */ +$a = MyClass::Fn; + +/* testNonArrowObjectMethodCall */ +$a = $obj->fn($param); + +/* testNonArrowObjectMethodCallUpper */ +$a = $obj->FN($param); + +/* testNonArrowNamespacedFunctionCall */ +$a = MyNS\Sub\Fn($param); + +/* testNonArrowNamespaceOperatorFunctionCall */ +$a = namespace\fn($param); + +/* testNonArrowFunctionNameWithUnionTypes */ +function fn(int|float $param) : string|null {} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$fn = fn diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.php new file mode 100644 index 000000000..f4ef2f206 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillFnTokenTest.php @@ -0,0 +1,967 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class BackfillFnTokenTest extends AbstractTokenizerTestCase +{ + + + /** + * Test simple arrow functions. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataSimple + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSimple($testMarker) + { + $token = $this->getTargetToken($testMarker, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 12); + + }//end testSimple() + + + /** + * Data provider. + * + * @see testSimple() + * + * @return array> + */ + public static function dataSimple() + { + return [ + 'standard' => [ + 'testMarker' => '/* testStandard */', + ], + 'mixed case' => [ + 'testMarker' => '/* testMixedCase */', + ], + ]; + + }//end dataSimple() + + + /** + * Test whitespace inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWhitespace() + { + $token = $this->getTargetToken('/* testWhitespace */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 6, 13); + + }//end testWhitespace() + + + /** + * Test comments inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testComment() + { + $token = $this->getTargetToken('/* testComment */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 15); + + }//end testComment() + + + /** + * Test heredocs inside arrow function definitions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testHeredoc() + { + $token = $this->getTargetToken('/* testHeredoc */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 9); + + }//end testHeredoc() + + + /** + * Test nested arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedOuter() + { + $token = $this->getTargetToken('/* testNestedOuter */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 25); + + }//end testNestedOuter() + + + /** + * Test nested arrow functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedInner() + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testNestedInner */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 5); + $expectedScopeCloser = ($token + 16); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 4), $tokens[$closer]['scope_opener'], 'Closer scope opener is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer is not the semicolon token'); + + }//end testNestedInner() + + + /** + * Test nested arrow functions with a shared closer. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedSharedCloser() + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testNestedSharedCloserOuter */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 20); + + $token = $this->getTargetToken('/* testNestedSharedCloserInner */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 4); + $expectedScopeCloser = ($token + 12); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for "inner" arrow function is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for "inner" arrow function is not the TRUE token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for "inner" arrow function is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for "inner" arrow function is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 4), $tokens[$closer]['scope_opener'], 'Closer scope opener for "inner" arrow function is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for "inner" arrow function is not the TRUE token'); + + }//end testNestedSharedCloser() + + + /** + * Test arrow functions that call functions. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFunctionCall() + { + $token = $this->getTargetToken('/* testFunctionCall */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 17); + + }//end testFunctionCall() + + + /** + * Test arrow functions that are included in chained calls. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testChainedFunctionCall() + { + $token = $this->getTargetToken('/* testChainedFunctionCall */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 12, 'bracket'); + + }//end testChainedFunctionCall() + + + /** + * Test arrow functions that are used as function arguments. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFunctionArgument() + { + $token = $this->getTargetToken('/* testFunctionArgument */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 15, 'comma'); + + }//end testFunctionArgument() + + + /** + * Test arrow functions that use closures. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testClosure() + { + $token = $this->getTargetToken('/* testClosure */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 60, 'comma'); + + }//end testClosure() + + + /** + * Test arrow functions using an array index. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayIndex() + { + $token = $this->getTargetToken('/* testArrayIndex */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 8, 17, 'comma'); + + }//end testArrayIndex() + + + /** + * Test arrow functions with a return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReturnType() + { + $token = $this->getTargetToken('/* testReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18, 'comma'); + + }//end testReturnType() + + + /** + * Test arrow functions that return a reference. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReference() + { + $token = $this->getTargetToken('/* testReference */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 6, 9); + + }//end testReference() + + + /** + * Test arrow functions that are grouped by parenthesis. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testGrouped() + { + $token = $this->getTargetToken('/* testGrouped */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 8); + + }//end testGrouped() + + + /** + * Test arrow functions that are used as array values. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayValue() + { + $token = $this->getTargetToken('/* testArrayValue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 9, 'comma'); + + }//end testArrayValue() + + + /** + * Test arrow functions that are used as array values with no trailing comma. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testArrayValueNoTrailingComma() + { + $token = $this->getTargetToken('/* testArrayValueNoTrailingComma */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 4, 8, 'closing parenthesis'); + + }//end testArrayValueNoTrailingComma() + + + /** + * Test arrow functions that use the yield keyword. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testYield() + { + $token = $this->getTargetToken('/* testYield */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 14); + + }//end testYield() + + + /** + * Test arrow functions that use nullable namespace types. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNullableNamespace() + { + $token = $this->getTargetToken('/* testNullableNamespace */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 18); + + }//end testNullableNamespace() + + + /** + * Test arrow functions that use the namespace operator in the return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNamespaceOperatorInTypes() + { + $token = $this->getTargetToken('/* testNamespaceOperatorInTypes */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 16, 19); + + }//end testNamespaceOperatorInTypes() + + + /** + * Test arrow functions that use keyword return types. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataKeywordReturnTypes + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testKeywordReturnTypes($testMarker) + { + $token = $this->getTargetToken($testMarker, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 14); + + }//end testKeywordReturnTypes() + + + /** + * Data provider. + * + * @see testKeywordReturnTypes() + * + * @return array> + */ + public static function dataKeywordReturnTypes() + { + return [ + 'self' => [ + 'testMarker' => '/* testSelfReturnType */', + ], + 'parent' => [ + 'testMarker' => '/* testParentReturnType */', + ], + 'callable' => [ + 'testMarker' => '/* testCallableReturnType */', + ], + 'array' => [ + 'testMarker' => '/* testArrayReturnType */', + ], + 'static' => [ + 'testMarker' => '/* testStaticReturnType */', + ], + 'false' => [ + 'testMarker' => '/* testFalseReturnType */', + ], + 'true' => [ + 'testMarker' => '/* testTrueReturnType */', + ], + 'null' => [ + 'testMarker' => '/* testNullReturnType */', + ], + ]; + + }//end dataKeywordReturnTypes() + + + /** + * Test arrow function with a union parameter type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionParamType() + { + $token = $this->getTargetToken('/* testUnionParamType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 13, 21); + + }//end testUnionParamType() + + + /** + * Test arrow function with a union return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionReturnType() + { + $token = $this->getTargetToken('/* testUnionReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18); + + }//end testUnionReturnType() + + + /** + * Test arrow function with a union return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionReturnTypeWithTrue() + { + $token = $this->getTargetToken('/* testUnionReturnTypeWithTrue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18); + + }//end testUnionReturnTypeWithTrue() + + + /** + * Test arrow function with a union return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testUnionReturnTypeWithFalse() + { + $token = $this->getTargetToken('/* testUnionReturnTypeWithFalse */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 11, 18); + + }//end testUnionReturnTypeWithFalse() + + + /** + * Test arrow function with an intersection parameter type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testIntersectionParamType() + { + $token = $this->getTargetToken('/* testIntersectionParamType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 13, 27); + + }//end testIntersectionParamType() + + + /** + * Test arrow function with an intersection return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testIntersectionReturnType() + { + $token = $this->getTargetToken('/* testIntersectionReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 12, 20); + + }//end testIntersectionReturnType() + + + /** + * Test arrow function with a DNF parameter type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testDNFParamType() + { + $token = $this->getTargetToken('/* testDNFParamType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 17, 29); + + }//end testDNFParamType() + + + /** + * Test arrow function with a DNF return type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testDNFReturnType() + { + $token = $this->getTargetToken('/* testDNFReturnType */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 16, 29); + + }//end testDNFReturnType() + + + /** + * Test arrow function which returns by reference with a DNF parameter type. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testDNFParamTypeWithReturnByRef() + { + $token = $this->getTargetToken('/* testDNFParamTypeWithReturnByRef */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 22); + + }//end testDNFParamTypeWithReturnByRef() + + + /** + * Test arrow functions used in ternary operators. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTernary() + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testTernary */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 40); + + $token = $this->getTargetToken('/* testTernaryThen */', T_FN); + $this->backfillHelper($token); + + $expectedScopeOpener = ($token + 8); + $expectedScopeCloser = ($token + 12); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for THEN is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for THEN is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'Closer scope opener for THEN is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for THEN is not the semicolon token'); + + $token = $this->getTargetToken('/* testTernaryElse */', T_FN); + $this->backfillHelper($token, true); + + $expectedScopeOpener = ($token + 8); + $expectedScopeCloser = ($token + 11); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener for ELSE is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer for ELSE is not the semicolon token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener for ELSE is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer for ELSE is not the semicolon token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame(($token - 24), $tokens[$closer]['scope_opener'], 'Closer scope opener for ELSE is not the arrow token of the "outer" arrow function (shared scope closer)'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer for ELSE is not the semicolon token'); + + }//end testTernary() + + + /** + * Test typed arrow functions used in ternary operators. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTernaryWithTypes() + { + $token = $this->getTargetToken('/* testTernaryWithTypes */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 15, 27); + + }//end testTernaryWithTypes() + + + /** + * Test arrow function returning a match control structure. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWithMatchValue() + { + $token = $this->getTargetToken('/* testWithMatchValue */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 44); + + }//end testWithMatchValue() + + + /** + * Test arrow function returning a match control structure with something behind it. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testWithMatchValueAndMore() + { + $token = $this->getTargetToken('/* testWithMatchValueAndMore */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 48); + + }//end testWithMatchValueAndMore() + + + /** + * Test match control structure returning arrow functions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param string $expectedCloserType The type of token expected for the scope closer. + * @param string $expectedCloserFriendlyName A friendly name for the type of token expected for the scope closer + * to be used in the error message for failing tests. + * + * @dataProvider dataInMatchValue + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testInMatchValue($testMarker, $openerOffset, $closerOffset, $expectedCloserType, $expectedCloserFriendlyName) + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, $openerOffset, $closerOffset, $expectedCloserFriendlyName); + + $this->assertSame($expectedCloserType, $tokens[($token + $closerOffset)]['type'], 'Mismatched scope closer type'); + + }//end testInMatchValue() + + + /** + * Data provider. + * + * @see testInMatchValue() + * + * @return array> + */ + public static function dataInMatchValue() + { + return [ + 'not_last_value' => [ + 'testMarker' => '/* testInMatchNotLastValue */', + 'openerOffset' => 5, + 'closerOffset' => 11, + 'expectedCloserType' => 'T_COMMA', + 'expectedCloserFriendlyName' => 'comma', + ], + 'last_value_with_trailing_comma' => [ + 'testMarker' => '/* testInMatchLastValueWithTrailingComma */', + 'openerOffset' => 5, + 'closerOffset' => 11, + 'expectedCloserType' => 'T_COMMA', + 'expectedCloserFriendlyName' => 'comma', + ], + 'last_value_without_trailing_comma_1' => [ + 'testMarker' => '/* testInMatchLastValueNoTrailingComma1 */', + 'openerOffset' => 5, + 'closerOffset' => 10, + 'expectedCloserType' => 'T_CLOSE_PARENTHESIS', + 'expectedCloserFriendlyName' => 'close parenthesis', + ], + 'last_value_without_trailing_comma_2' => [ + 'testMarker' => '/* testInMatchLastValueNoTrailingComma2 */', + 'openerOffset' => 5, + 'closerOffset' => 11, + 'expectedCloserType' => 'T_VARIABLE', + 'expectedCloserFriendlyName' => '$y variable', + ], + ]; + + }//end dataInMatchValue() + + + /** + * Test arrow function nested within a method declaration. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNestedInMethod() + { + $token = $this->getTargetToken('/* testNestedInMethod */', T_FN); + $this->backfillHelper($token); + $this->scopePositionTestHelper($token, 5, 17); + + }//end testNestedInMethod() + + + /** + * Verify that "fn" keywords which are not arrow functions get tokenized as T_STRING and don't + * have the extra token array indexes. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotAnArrowFunction + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotAnArrowFunction($testMarker, $testContent='fn') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_FN], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotAnArrowFunction() + + + /** + * Data provider. + * + * @see testNotAnArrowFunction() + * + * @return array> + */ + public static function dataNotAnArrowFunction() + { + return [ + 'name of a function, context: declaration' => [ + 'testMarker' => '/* testFunctionName */', + ], + 'name of a constant, context: declaration using "const" keyword - uppercase' => [ + 'testMarker' => '/* testConstantDeclaration */', + 'testContent' => 'FN', + ], + 'name of a constant, context: declaration using "const" keyword - lowercase' => [ + 'testMarker' => '/* testConstantDeclarationLower */', + 'testContent' => 'fn', + ], + 'name of a (static) method, context: declaration' => [ + 'testMarker' => '/* testStaticMethodName */', + ], + 'name of a property, context: property access' => [ + 'testMarker' => '/* testPropertyAssignment */', + ], + 'name of a method, context: declaration in an anon class - mixed case' => [ + 'testMarker' => '/* testAnonClassMethodName */', + 'testContent' => 'fN', + ], + 'name of a method, context: static method call' => [ + 'testMarker' => '/* testNonArrowStaticMethodCall */', + ], + 'name of a constant, context: constant access - uppercase' => [ + 'testMarker' => '/* testNonArrowConstantAccess */', + 'testContent' => 'FN', + ], + 'name of a constant, context: constant access - mixed case' => [ + 'testMarker' => '/* testNonArrowConstantAccessMixed */', + 'testContent' => 'Fn', + ], + 'name of a method, context: method call on object - lowercase' => [ + 'testMarker' => '/* testNonArrowObjectMethodCall */', + ], + 'name of a method, context: method call on object - uppercase' => [ + 'testMarker' => '/* testNonArrowObjectMethodCallUpper */', + 'testContent' => 'FN', + ], + 'name of a (namespaced) function, context: partially qualified function call' => [ + 'testMarker' => '/* testNonArrowNamespacedFunctionCall */', + 'testContent' => 'Fn', + ], + 'name of a (namespaced) function, context: namespace relative function call' => [ + 'testMarker' => '/* testNonArrowNamespaceOperatorFunctionCall */', + ], + 'name of a function, context: declaration with union types for param and return' => [ + 'testMarker' => '/* testNonArrowFunctionNameWithUnionTypes */', + ], + 'unknown - live coding/parse error' => [ + 'testMarker' => '/* testLiveCoding */', + ], + ]; + + }//end dataNotAnArrowFunction() + + + /** + * Helper function to check that all token keys are correctly set for T_FN tokens. + * + * @param int $token The T_FN token to check. + * @param bool $skipScopeCloserCheck Whether to skip the scope closer check. + * This should be set to "true" when testing nested arrow functions, + * where the "inner" arrow function shares a scope closer with the + * "outer" arrow function, as the 'scope_condition' for the scope closer + * of the "inner" arrow function will point to the "outer" arrow function. + * + * @return void + */ + private function backfillHelper($token, $skipScopeCloserCheck=false) + { + $tokens = $this->phpcsFile->getTokens(); + + $this->assertTrue(array_key_exists('scope_condition', $tokens[$token]), 'Scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$token]), 'Scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$token]), 'Scope closer is not set'); + $this->assertSame($tokens[$token]['scope_condition'], $token, 'Scope condition is not the T_FN token'); + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$token]), 'Parenthesis owner is not set'); + $this->assertTrue(array_key_exists('parenthesis_opener', $tokens[$token]), 'Parenthesis opener is not set'); + $this->assertTrue(array_key_exists('parenthesis_closer', $tokens[$token]), 'Parenthesis closer is not set'); + $this->assertSame($tokens[$token]['parenthesis_owner'], $token, 'Parenthesis owner is not the T_FN token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertTrue(array_key_exists('scope_condition', $tokens[$opener]), 'Opener scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$opener]), 'Opener scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$opener]), 'Opener scope closer is not set'); + $this->assertSame($tokens[$opener]['scope_condition'], $token, 'Opener scope condition is not the T_FN token'); + $this->assertSame(T_FN_ARROW, $tokens[$opener]['code'], 'Arrow scope opener not tokenized as T_FN_ARROW (code)'); + $this->assertSame('T_FN_ARROW', $tokens[$opener]['type'], 'Arrow scope opener not tokenized as T_FN_ARROW (type)'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertTrue(array_key_exists('scope_condition', $tokens[$closer]), 'Closer scope condition is not set'); + $this->assertTrue(array_key_exists('scope_opener', $tokens[$closer]), 'Closer scope opener is not set'); + $this->assertTrue(array_key_exists('scope_closer', $tokens[$closer]), 'Closer scope closer is not set'); + if ($skipScopeCloserCheck === false) { + $this->assertSame($tokens[$closer]['scope_condition'], $token, 'Closer scope condition is not the T_FN token'); + } + + $opener = $tokens[$token]['parenthesis_opener']; + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$opener]), 'Opening parenthesis owner is not set'); + $this->assertSame($tokens[$opener]['parenthesis_owner'], $token, 'Opening parenthesis owner is not the T_FN token'); + + $closer = $tokens[$token]['parenthesis_closer']; + $this->assertTrue(array_key_exists('parenthesis_owner', $tokens[$closer]), 'Closing parenthesis owner is not set'); + $this->assertSame($tokens[$closer]['parenthesis_owner'], $token, 'Closing parenthesis owner is not the T_FN token'); + + }//end backfillHelper() + + + /** + * Helper function to check that the scope opener/closer positions are correctly set for T_FN tokens. + * + * @param int $token The T_FN token to check. + * @param int $openerOffset The expected offset of the scope opener in relation to + * the fn keyword. + * @param int $closerOffset The expected offset of the scope closer in relation to + * the fn keyword. + * @param string $expectedCloserType Optional. The type of token expected for the scope closer. + * + * @return void + */ + private function scopePositionTestHelper($token, $openerOffset, $closerOffset, $expectedCloserType='semicolon') + { + $tokens = $this->phpcsFile->getTokens(); + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertSame($expectedScopeOpener, $tokens[$token]['scope_opener'], 'Scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$token]['scope_closer'], 'Scope closer is not the '.$expectedCloserType.' token'); + + $opener = $tokens[$token]['scope_opener']; + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'Opener scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'Opener scope closer is not the '.$expectedCloserType.' token'); + + $closer = $tokens[$token]['scope_closer']; + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'Closer scope opener is not the arrow token'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'Closer scope closer is not the '.$expectedCloserType.' token'); + + }//end scopePositionTestHelper() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.inc new file mode 100644 index 000000000..095a4d7df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.inc @@ -0,0 +1,319 @@ + 'Zero', + 1 => 'One', + 2 => 'Two', + }; +} + +function matchNoTrailingComma($bool) { + /* testMatchNoTrailingComma */ + echo match ($bool) { + true => "true\n", + false => "false\n" + }; +} + +function matchWithDefault($i) { + /* testMatchWithDefault */ + return match ($i) { + 1 => 1, + 2 => 2, + default => 'default', + }; +} + +function matchExpressionInCondition($i) { + /* testMatchExpressionInCondition */ + return match (true) { + $i >= 50 => '50+', + $i >= 40 => '40-50', + $i >= 30 => '30-40', + $i >= 20 => '20-30', + $i >= 10 => '10-20', + default => '0-10', + }; +} + +function matchMultiCase($day) { + /* testMatchMultiCase */ + return match ($day) { + 1, 7 => false, + 2, 3, 4, 5, 6 => true, + }; +} + +function matchMultiCaseTrailingCommaInCase($bool) { + /* testMatchMultiCaseTrailingCommaInCase */ + echo match ($bool) { + false, + 0, + => "false\n", + true, + 1, + => "true\n", + default, + => "not bool\n", + }; +} + +assert((function () { + /* testMatchInClosureNotLowercase */ + Match ('foo') { + 'foo', 'bar' => false, + 'baz' => 'a', + default => 'b', + }; +})()); + +function matchInArrowFunction($x) { + /* testMatchInArrowFunction */ + $fn = fn($x) => match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', + }; +} + +function arrowFunctionInMatchNoTrailingComma($x) { + /* testArrowFunctionInMatchNoTrailingComma */ + return match ($x) { + 1 => fn($y) => callMe($y), + default => fn($y) => callThem($y) + }; +} + +/* testMatchInFunctionCallParamNotLowercase */ +var_dump(MATCH ( 'foo' ) { + 'foo' => dump_and_return('foo'), + 'bar' => dump_and_return('bar'), +}); + +/* testMatchInMethodCallParam */ +Test::usesValue(match(true) { true => $i }); + +/* testMatchDiscardResult */ +match (1) { + 1 => print "Executed\n", +}; + +/* testMatchWithDuplicateConditionsWithComments */ +echo match /*comment*/ ( $value /*comment*/ ) { + // Comment. + 2, 1 => '2, 1', + 1 => 1, + 3 => 3, + 4 => 4, + 5 => 5, +}; + +/* testNestedMatchOuter */ +$x = match ($y) { + /* testNestedMatchInner */ + default => match ($z) { 1 => 1 }, +}; + +/* testMatchInTernaryCondition */ +$x = match ($test) { 1 => 'a', 2 => 'b' } ? + /* testMatchInTernaryThen */ match ($test) { 1 => 'a', 2 => 'b' } : + /* testMatchInTernaryElse */ match ($notTest) { 3 => 'a', 4 => 'b' }; + +/* testMatchInArrayValue */ +$array = array( + match ($test) { 1 => 'a', 2 => 'b' }, +); + +/* testMatchInArrayKey */ +$array = [ + match ($test) { 1 => 'a', 2 => 'b' } => 'dynamic keys, woho!', +]; + +/* testMatchreturningArray */ +$matcher = match ($x) { + 0 => array( 0 => 1, 'a' => 2, 'b' => 3 ), + 1 => [1, 2, 3], + 2 => array( 1, [1, 2, 3], 2, 3), + 3 => [ 0 => 1, 'a' => array(1, 2, 3), 'b' => 2, 3], +}; + +/* testSwitchContainingMatch */ +switch ($something) { + /* testMatchWithDefaultNestedInSwitchCase1 */ + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + default => 'default', + }; + continue 2; + + /* testMatchWithDefaultNestedInSwitchCase2 */ + case 'bar' ; + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + default => 'default', + }; + + /* testMatchWithDefaultNestedInSwitchDefault */ + default: + echo 'something', match ($i) { + 1 => 1, + default => 'default', + }; + break; +} + +/* testMatchContainingSwitch */ +$x = match ($y) { + 5, 8 => function($z) { + /* testSwitchNestedInMatch1 */ + switch($z) { + case 'a': + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $i = callMe($a, $b); + return 'default1'; + } + }, + default => function($z) { + /* testSwitchNestedInMatch2 */ + switch($z) { + case 'a'; + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default; + $var = [1, 2, 3]; + return 'default2'; + } + } +}; + +/* testMatchNoCases */ +// Intentional fatal error. +$x = match (true) {}; + +/* testMatchMultiDefault */ +// Intentional fatal error. +echo match (1) { + default => 'foo', + 1 => 'bar', + 2 => 'baz', + default => 'qux', +}; + +/* testNoMatchStaticMethodCall */ +$a = Foo::match($param); + +/* testNoMatchClassConstantAccess */ +$a = MyClass::MATCH; + +/* testNoMatchClassConstantArrayAccessMixedCase */ +$a = MyClass::Match[$a]; + +/* testNoMatchMethodCall */ +$a = $obj->match($param); + +/* testNoMatchMethodCallUpper */ +$a = $obj??->MATCH()->chain($param); + +/* testNoMatchPropertyAccess */ +$a = $obj->match; + +/* testNoMatchNamespacedFunctionCall */ +// Intentional fatal error. +$a = MyNS\Sub\match($param); + +/* testNoMatchNamespaceOperatorFunctionCall */ +// Intentional fatal error. +$a = namespace\match($param); + +interface MatchInterface { + /* testNoMatchInterfaceMethodDeclaration */ + public static function match($param); +} + +class MatchClass { + /* testNoMatchClassConstantDeclarationLower */ + const match = 'a'; + + /* testNoMatchClassMethodDeclaration */ + public static function match($param) { + /* testNoMatchPropertyAssignment */ + $this->match = 'a'; + } +} + +/* testNoMatchClassInstantiation */ +$obj = new Match(); + +$anon = new class() { + /* testNoMatchAnonClassMethodDeclaration */ + protected function maTCH($param) { + } +}; + +/* testNoMatchClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Match {} + +/* testNoMatchInterfaceDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +interface Match {} + +/* testNoMatchTraitDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +trait Match {} + +/* testNoMatchConstantDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +const MATCH = '1'; + +/* testNoMatchFunctionDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +function match() {} + +/* testNoMatchNamespaceDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +namespace Match {} + +/* testNoMatchExtendedClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Foo extends Match {} + +/* testNoMatchImplementedClassDeclaration */ +// Intentional fatal error. Match is now a reserved keyword. +class Bar implements Match {} + +/* testNoMatchInUseStatement */ +// Intentional fatal error in PHP < 8. Match is now a reserved keyword. +use Match\me; + +function brokenMatchNoCurlies($x) { + /* testNoMatchMissingCurlies */ + // Intentional fatal error. New control structure is not supported without curly braces. + return match ($x) + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + ; +} + +function brokenMatchAlternativeSyntax($x) { + /* testNoMatchAlternativeSyntax */ + // Intentional fatal error. Alternative syntax is not supported. + return match ($x) : + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + endmatch; +} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +echo match diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.php new file mode 100644 index 000000000..ca6d27b3d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillMatchTokenTest.php @@ -0,0 +1,555 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class BackfillMatchTokenTest extends AbstractTokenizerTestCase +{ + + + /** + * Test tokenization of match expressions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchExpression + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMatchExpression($testMarker, $openerOffset, $closerOffset, $testContent='match') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_MATCH], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH (code)'); + $this->assertSame('T_MATCH', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH (type)'); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + $this->parenthesisTestHelper($token); + + }//end testMatchExpression() + + + /** + * Data provider. + * + * @see testMatchExpression() + * + * @return array> + */ + public static function dataMatchExpression() + { + return [ + 'simple_match' => [ + 'testMarker' => '/* testMatchSimple */', + 'openerOffset' => 6, + 'closerOffset' => 33, + ], + 'no_trailing_comma' => [ + 'testMarker' => '/* testMatchNoTrailingComma */', + 'openerOffset' => 6, + 'closerOffset' => 24, + ], + 'with_default_case' => [ + 'testMarker' => '/* testMatchWithDefault */', + 'openerOffset' => 6, + 'closerOffset' => 33, + ], + 'expression_in_condition' => [ + 'testMarker' => '/* testMatchExpressionInCondition */', + 'openerOffset' => 6, + 'closerOffset' => 77, + ], + 'multicase' => [ + 'testMarker' => '/* testMatchMultiCase */', + 'openerOffset' => 6, + 'closerOffset' => 40, + ], + 'multicase_trailing_comma_in_case' => [ + 'testMarker' => '/* testMatchMultiCaseTrailingCommaInCase */', + 'openerOffset' => 6, + 'closerOffset' => 47, + ], + 'in_closure_not_lowercase' => [ + 'testMarker' => '/* testMatchInClosureNotLowercase */', + 'openerOffset' => 6, + 'closerOffset' => 36, + 'testContent' => 'Match', + ], + 'in_arrow_function' => [ + 'testMarker' => '/* testMatchInArrowFunction */', + 'openerOffset' => 5, + 'closerOffset' => 36, + ], + 'arrow_function_in_match_no_trailing_comma' => [ + 'testMarker' => '/* testArrowFunctionInMatchNoTrailingComma */', + 'openerOffset' => 6, + 'closerOffset' => 44, + ], + 'in_function_call_param_not_lowercase' => [ + 'testMarker' => '/* testMatchInFunctionCallParamNotLowercase */', + 'openerOffset' => 8, + 'closerOffset' => 32, + 'testContent' => 'MATCH', + ], + 'in_method_call_param' => [ + 'testMarker' => '/* testMatchInMethodCallParam */', + 'openerOffset' => 5, + 'closerOffset' => 13, + ], + 'discard_result' => [ + 'testMarker' => '/* testMatchDiscardResult */', + 'openerOffset' => 6, + 'closerOffset' => 18, + ], + 'duplicate_conditions_and_comments' => [ + 'testMarker' => '/* testMatchWithDuplicateConditionsWithComments */', + 'openerOffset' => 12, + 'closerOffset' => 59, + ], + 'nested_match_outer' => [ + 'testMarker' => '/* testNestedMatchOuter */', + 'openerOffset' => 6, + 'closerOffset' => 33, + ], + 'nested_match_inner' => [ + 'testMarker' => '/* testNestedMatchInner */', + 'openerOffset' => 6, + 'closerOffset' => 14, + ], + 'ternary_condition' => [ + 'testMarker' => '/* testMatchInTernaryCondition */', + 'openerOffset' => 6, + 'closerOffset' => 21, + ], + 'ternary_then' => [ + 'testMarker' => '/* testMatchInTernaryThen */', + 'openerOffset' => 6, + 'closerOffset' => 21, + ], + 'ternary_else' => [ + 'testMarker' => '/* testMatchInTernaryElse */', + 'openerOffset' => 6, + 'closerOffset' => 21, + ], + 'array_value' => [ + 'testMarker' => '/* testMatchInArrayValue */', + 'openerOffset' => 6, + 'closerOffset' => 21, + ], + 'array_key' => [ + 'testMarker' => '/* testMatchInArrayKey */', + 'openerOffset' => 6, + 'closerOffset' => 21, + ], + 'returning_array' => [ + 'testMarker' => '/* testMatchreturningArray */', + 'openerOffset' => 6, + 'closerOffset' => 125, + ], + 'nested_in_switch_case_1' => [ + 'testMarker' => '/* testMatchWithDefaultNestedInSwitchCase1 */', + 'openerOffset' => 6, + 'closerOffset' => 25, + ], + 'nested_in_switch_case_2' => [ + 'testMarker' => '/* testMatchWithDefaultNestedInSwitchCase2 */', + 'openerOffset' => 6, + 'closerOffset' => 25, + ], + 'nested_in_switch_default' => [ + 'testMarker' => '/* testMatchWithDefaultNestedInSwitchDefault */', + 'openerOffset' => 6, + 'closerOffset' => 25, + ], + 'match_with_nested_switch' => [ + 'testMarker' => '/* testMatchContainingSwitch */', + 'openerOffset' => 6, + 'closerOffset' => 180, + ], + 'no_cases' => [ + 'testMarker' => '/* testMatchNoCases */', + 'openerOffset' => 6, + 'closerOffset' => 7, + ], + 'multi_default' => [ + 'testMarker' => '/* testMatchMultiDefault */', + 'openerOffset' => 6, + 'closerOffset' => 40, + ], + ]; + + }//end dataMatchExpression() + + + /** + * Verify that "match" keywords which are not match control structures get tokenized as T_STRING + * and don't have the extra token array indexes. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotAMatchStructure + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotAMatchStructure($testMarker, $testContent='match') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_STRING, T_MATCH], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + $next = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($token + 1), null, true); + if ($next !== false && $tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set for opener after'); + } + + }//end testNotAMatchStructure() + + + /** + * Data provider. + * + * @see testNotAMatchStructure() + * + * @return array> + */ + public static function dataNotAMatchStructure() + { + return [ + 'static_method_call' => [ + 'testMarker' => '/* testNoMatchStaticMethodCall */', + ], + 'class_constant_access' => [ + 'testMarker' => '/* testNoMatchClassConstantAccess */', + 'testContent' => 'MATCH', + ], + 'class_constant_array_access' => [ + 'testMarker' => '/* testNoMatchClassConstantArrayAccessMixedCase */', + 'testContent' => 'Match', + ], + 'method_call' => [ + 'testMarker' => '/* testNoMatchMethodCall */', + ], + 'method_call_uppercase' => [ + 'testMarker' => '/* testNoMatchMethodCallUpper */', + 'testContent' => 'MATCH', + ], + 'property_access' => [ + 'testMarker' => '/* testNoMatchPropertyAccess */', + ], + 'namespaced_function_call' => [ + 'testMarker' => '/* testNoMatchNamespacedFunctionCall */', + ], + 'namespace_operator_function_call' => [ + 'testMarker' => '/* testNoMatchNamespaceOperatorFunctionCall */', + ], + 'interface_method_declaration' => [ + 'testMarker' => '/* testNoMatchInterfaceMethodDeclaration */', + ], + 'class_constant_declaration' => [ + 'testMarker' => '/* testNoMatchClassConstantDeclarationLower */', + ], + 'class_method_declaration' => [ + 'testMarker' => '/* testNoMatchClassMethodDeclaration */', + ], + 'property_assigment' => [ + 'testMarker' => '/* testNoMatchPropertyAssignment */', + ], + 'class_instantiation' => [ + 'testMarker' => '/* testNoMatchClassInstantiation */', + 'testContent' => 'Match', + ], + 'anon_class_method_declaration' => [ + 'testMarker' => '/* testNoMatchAnonClassMethodDeclaration */', + 'testContent' => 'maTCH', + ], + 'class_declaration' => [ + 'testMarker' => '/* testNoMatchClassDeclaration */', + 'testContent' => 'Match', + ], + 'interface_declaration' => [ + 'testMarker' => '/* testNoMatchInterfaceDeclaration */', + 'testContent' => 'Match', + ], + 'trait_declaration' => [ + 'testMarker' => '/* testNoMatchTraitDeclaration */', + 'testContent' => 'Match', + ], + 'constant_declaration' => [ + 'testMarker' => '/* testNoMatchConstantDeclaration */', + 'testContent' => 'MATCH', + ], + 'function_declaration' => [ + 'testMarker' => '/* testNoMatchFunctionDeclaration */', + ], + 'namespace_declaration' => [ + 'testMarker' => '/* testNoMatchNamespaceDeclaration */', + 'testContent' => 'Match', + ], + 'class_extends_declaration' => [ + 'testMarker' => '/* testNoMatchExtendedClassDeclaration */', + 'testContent' => 'Match', + ], + 'class_implements_declaration' => [ + 'testMarker' => '/* testNoMatchImplementedClassDeclaration */', + 'testContent' => 'Match', + ], + 'use_statement' => [ + 'testMarker' => '/* testNoMatchInUseStatement */', + 'testContent' => 'Match', + ], + 'unsupported_inline_control_structure' => [ + 'testMarker' => '/* testNoMatchMissingCurlies */', + ], + 'unsupported_alternative_syntax' => [ + 'testMarker' => '/* testNoMatchAlternativeSyntax */', + ], + 'live_coding' => [ + 'testMarker' => '/* testLiveCoding */', + ], + ]; + + }//end dataNotAMatchStructure() + + + /** + * Verify that the tokenization of switch structures is not affected by the backfill. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * + * @dataProvider dataSwitchExpression + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSwitchExpression($testMarker, $openerOffset, $closerOffset) + { + $token = $this->getTargetToken($testMarker, T_SWITCH); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + $this->parenthesisTestHelper($token); + + }//end testSwitchExpression() + + + /** + * Data provider. + * + * @see testSwitchExpression() + * + * @return array> + */ + public static function dataSwitchExpression() + { + return [ + 'switch_containing_match' => [ + 'testMarker' => '/* testSwitchContainingMatch */', + 'openerOffset' => 6, + 'closerOffset' => 174, + ], + 'match_containing_switch_1' => [ + 'testMarker' => '/* testSwitchNestedInMatch1 */', + 'openerOffset' => 5, + 'closerOffset' => 63, + ], + 'match_containing_switch_2' => [ + 'testMarker' => '/* testSwitchNestedInMatch2 */', + 'openerOffset' => 5, + 'closerOffset' => 63, + ], + ]; + + }//end dataSwitchExpression() + + + /** + * Verify that the tokenization of a switch case/default structure containing a match structure + * or contained *in* a match structure is not affected by the backfill. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * + * @dataProvider dataSwitchCaseVersusMatch + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSwitchCaseVersusMatch($testMarker, $openerOffset, $closerOffset) + { + $token = $this->getTargetToken($testMarker, [T_CASE, T_DEFAULT]); + + $this->scopeTestHelper($token, $openerOffset, $closerOffset); + + }//end testSwitchCaseVersusMatch() + + + /** + * Data provider. + * + * @see testSwitchCaseVersusMatch() + * + * @return array> + */ + public static function dataSwitchCaseVersusMatch() + { + return [ + 'switch_with_nested_match_case_1' => [ + 'testMarker' => '/* testMatchWithDefaultNestedInSwitchCase1 */', + 'openerOffset' => 3, + 'closerOffset' => 55, + ], + 'switch_with_nested_match_case_2' => [ + 'testMarker' => '/* testMatchWithDefaultNestedInSwitchCase2 */', + 'openerOffset' => 4, + 'closerOffset' => 21, + ], + 'switch_with_nested_match_default_case' => [ + 'testMarker' => '/* testMatchWithDefaultNestedInSwitchDefault */', + 'openerOffset' => 1, + 'closerOffset' => 38, + ], + 'match_with_nested_switch_case' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchCase */', + 'openerOffset' => 1, + 'closerOffset' => 18, + ], + 'match_with_nested_switch_default_case' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchDefault */', + 'openerOffset' => 1, + 'closerOffset' => 20, + ], + ]; + + }//end dataSwitchCaseVersusMatch() + + + /** + * Helper function to verify that all scope related array indexes for a control structure + * are set correctly. + * + * @param string $token The control structure token to check. + * @param int $openerOffset The expected offset of the scope opener in relation to + * the control structure token. + * @param int $closerOffset The expected offset of the scope closer in relation to + * the control structure token. + * @param bool $skipScopeCloserCheck Whether to skip the scope closer check. + * This should be set to "true" when testing nested arrow functions, + * where the "inner" arrow function shares a scope closer with the + * "outer" arrow function, as the 'scope_condition' for the scope closer + * of the "inner" arrow function will point to the "outer" arrow function. + * + * @return void + */ + private function scopeTestHelper($token, $openerOffset, $closerOffset, $skipScopeCloserCheck=false) + { + $tokens = $this->phpcsFile->getTokens(); + $tokenArray = $tokens[$token]; + $tokenType = $tokenArray['type']; + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame($token, $tokenArray['scope_condition'], 'Scope condition is not the '.$tokenType.' token'); + $this->assertSame($expectedScopeOpener, $tokenArray['scope_opener'], 'Scope opener of the '.$tokenType.' token incorrect'); + $this->assertSame($expectedScopeCloser, $tokenArray['scope_closer'], 'Scope closer of the '.$tokenType.' token incorrect'); + + $opener = $tokenArray['scope_opener']; + $this->assertArrayHasKey('scope_condition', $tokens[$opener], 'Opener scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Opener scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Opener scope closer is not set'); + $this->assertSame($token, $tokens[$opener]['scope_condition'], 'Opener scope condition is not the '.$tokenType.' token'); + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], $tokenType.' opener scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], $tokenType.' opener scope closer token incorrect'); + + $closer = $tokenArray['scope_closer']; + $this->assertArrayHasKey('scope_condition', $tokens[$closer], 'Closer scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Closer scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Closer scope closer is not set'); + if ($skipScopeCloserCheck === false) { + $this->assertSame($token, $tokens[$closer]['scope_condition'], 'Closer scope condition is not the '.$tokenType.' token'); + } + + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], $tokenType.' closer scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], $tokenType.' closer scope closer token incorrect'); + + if (($opener + 1) !== $closer) { + for ($i = ($opener + 1); $i < $closer; $i++) { + $this->assertArrayHasKey( + $token, + $tokens[$i]['conditions'], + $tokenType.' condition not added for token belonging to the '.$tokenType.' structure' + ); + } + } + + }//end scopeTestHelper() + + + /** + * Helper function to verify that all parenthesis related array indexes for a control structure + * token are set correctly. + * + * @param int $token The position of the control structure token. + * + * @return void + */ + private function parenthesisTestHelper($token) + { + $tokens = $this->phpcsFile->getTokens(); + $tokenArray = $tokens[$token]; + $tokenType = $tokenArray['type']; + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + $this->assertSame($token, $tokenArray['parenthesis_owner'], 'Parenthesis owner is not the '.$tokenType.' token'); + + $opener = $tokenArray['parenthesis_opener']; + $this->assertArrayHasKey('parenthesis_owner', $tokens[$opener], 'Opening parenthesis owner is not set'); + $this->assertSame($token, $tokens[$opener]['parenthesis_owner'], 'Opening parenthesis owner is not the '.$tokenType.' token'); + + $closer = $tokenArray['parenthesis_closer']; + $this->assertArrayHasKey('parenthesis_owner', $tokens[$closer], 'Closing parenthesis owner is not set'); + $this->assertSame($token, $tokens[$closer]['parenthesis_owner'], 'Closing parenthesis owner is not the '.$tokenType.' token'); + + }//end parenthesisTestHelper() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillNumericSeparatorTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillNumericSeparatorTest.inc new file mode 100644 index 000000000..d8559705c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillNumericSeparatorTest.inc @@ -0,0 +1,94 @@ + + * @copyright 2019 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class BackfillNumericSeparatorTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that numbers using numeric separators are tokenized correctly. + * + * @param string $marker The comment which prefaces the target token in the test file. + * @param string $type The expected token type. + * @param string $value The expected token content. + * + * @dataProvider dataTestBackfill + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testBackfill($marker, $type, $value) + { + $tokens = $this->phpcsFile->getTokens(); + $number = $this->getTargetToken($marker, [T_LNUMBER, T_DNUMBER]); + $tokenArray = $tokens[$number]; + + $this->assertSame(constant($type), $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not '.$type.' (code)'); + $this->assertSame($type, $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not '.$type.' (type)'); + $this->assertSame($value, $tokenArray['content']); + + }//end testBackfill() + + + /** + * Data provider. + * + * @see testBackfill() + * + * @return array> + */ + public static function dataTestBackfill() + { + $testHexType = 'T_LNUMBER'; + if (PHP_INT_MAX < 0xCAFEF00D) { + $testHexType = 'T_DNUMBER'; + } + + $testHexMultipleType = 'T_LNUMBER'; + if (PHP_INT_MAX < 0x42726F776E) { + $testHexMultipleType = 'T_DNUMBER'; + } + + $testIntMoreThanMaxType = 'T_LNUMBER'; + if (PHP_INT_MAX < 10223372036854775807) { + $testIntMoreThanMaxType = 'T_DNUMBER'; + } + + return [ + 'decimal integer' => [ + 'marker' => '/* testSimpleLNumber */', + 'type' => 'T_LNUMBER', + 'value' => '1_000_000_000', + ], + 'float' => [ + 'marker' => '/* testSimpleDNumber */', + 'type' => 'T_DNUMBER', + 'value' => '107_925_284.88', + ], + 'float, scientific notation, negative exponent with sigh' => [ + 'marker' => '/* testFloat */', + 'type' => 'T_DNUMBER', + 'value' => '6.674_083e-11', + ], + 'float, scientific notation, positive exponent with sign' => [ + 'marker' => '/* testFloat2 */', + 'type' => 'T_DNUMBER', + 'value' => '6.674_083e+11', + ], + 'float, scientific notation, positive exponent without sign' => [ + 'marker' => '/* testFloat3 */', + 'type' => 'T_DNUMBER', + 'value' => '1_2.3_4e1_23', + ], + 'hexidecimal integer/float' => [ + 'marker' => '/* testHex */', + 'type' => $testHexType, + 'value' => '0xCAFE_F00D', + ], + 'hexidecimal integer/float with multiple underscores' => [ + 'marker' => '/* testHexMultiple */', + 'type' => $testHexMultipleType, + 'value' => '0x42_72_6F_77_6E', + ], + 'hexidecimal integer' => [ + 'marker' => '/* testHexInt */', + 'type' => 'T_LNUMBER', + 'value' => '0x42_72_6F', + ], + 'binary integer' => [ + 'marker' => '/* testBinary */', + 'type' => 'T_LNUMBER', + 'value' => '0b0101_1111', + ], + 'octal integer' => [ + 'marker' => '/* testOctal */', + 'type' => 'T_LNUMBER', + 'value' => '0137_041', + ], + 'octal integer using explicit octal notation' => [ + 'marker' => '/* testExplicitOctal */', + 'type' => 'T_LNUMBER', + 'value' => '0o137_041', + ], + 'octal integer using explicit octal notation with capital O' => [ + 'marker' => '/* testExplicitOctalCapitalised */', + 'type' => 'T_LNUMBER', + 'value' => '0O137_041', + ], + 'integer more than PHP_INT_MAX becomes a float' => [ + 'marker' => '/* testIntMoreThanMax */', + 'type' => $testIntMoreThanMaxType, + 'value' => '10_223_372_036_854_775_807', + ], + ]; + + }//end dataTestBackfill() + + + /** + * Test that numbers using numeric separators which are considered parse errors and/or + * which aren't relevant to the backfill, do not incorrectly trigger the backfill anyway. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array> $expectedTokens The token type and content of the expected token sequence. + * + * @dataProvider dataNoBackfill + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNoBackfill($testMarker, $expectedTokens) + { + $tokens = $this->phpcsFile->getTokens(); + $number = $this->getTargetToken($testMarker, [T_LNUMBER, T_DNUMBER]); + + foreach ($expectedTokens as $key => $expectedToken) { + $i = ($number + $key); + $this->assertSame( + $expectedToken['code'], + $tokens[$i]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$i]['code']).', not '.Tokens::tokenName($expectedToken['code']) + ); + $this->assertSame($expectedToken['content'], $tokens[$i]['content']); + } + + }//end testNoBackfill() + + + /** + * Data provider. + * + * @see testBackfill() + * + * @return array>>> + */ + public static function dataNoBackfill() + { + return [ + 'invalid: trailing underscore' => [ + 'testMarker' => '/* testInvalid1 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '100', + ], + [ + 'code' => T_STRING, + 'content' => '_', + ], + ], + ], + 'invalid: two consecutive underscores' => [ + 'testMarker' => '/* testInvalid2 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '__1', + ], + ], + ], + 'invalid: underscore directly before decimal point' => [ + 'testMarker' => '/* testInvalid3 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '_', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.0', + ], + ], + ], + 'invalid: underscore directly after decimal point' => [ + 'testMarker' => '/* testInvalid4 */', + 'expectedTokens' => [ + [ + 'code' => T_DNUMBER, + 'content' => '1.', + ], + [ + 'code' => T_STRING, + 'content' => '_0', + ], + ], + ], + 'invalid: hex int - underscore directly after x' => [ + 'testMarker' => '/* testInvalid5 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'x_123', + ], + ], + ], + 'invalid: binary int - underscore directly after b' => [ + 'testMarker' => '/* testInvalid6 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'b_101', + ], + ], + ], + 'invalid: scientific float - underscore directly before e' => [ + 'testMarker' => '/* testInvalid7 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => '_e2', + ], + ], + ], + 'invalid: scientific float - underscore directly after e' => [ + 'testMarker' => '/* testInvalid8 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '1', + ], + [ + 'code' => T_STRING, + 'content' => 'e_2', + ], + ], + ], + 'invalid: space between parts of the number' => [ + 'testMarker' => '/* testInvalid9 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '107_925_284', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.88', + ], + ], + ], + 'invalid: comment within the number' => [ + 'testMarker' => '/* testInvalid10 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '107_925_284', + ], + [ + 'code' => T_COMMENT, + 'content' => '/*comment*/', + ], + [ + 'code' => T_DNUMBER, + 'content' => '.88', + ], + ], + ], + 'invalid: explicit octal int - underscore directly after o' => [ + 'testMarker' => '/* testInvalid11 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'o_137', + ], + ], + ], + 'invalid: explicit octal int - underscore directly after capital O' => [ + 'testMarker' => '/* testInvalid12 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '0', + ], + [ + 'code' => T_STRING, + 'content' => 'O_41', + ], + ], + ], + 'calculations should be untouched - int - int' => [ + 'testMarker' => '/* testCalc1 */', + 'expectedTokens' => [ + [ + 'code' => T_LNUMBER, + 'content' => '667_083', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_MINUS, + 'content' => '-', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_LNUMBER, + 'content' => '11', + ], + ], + ], + 'calculations should be untouched - scientific float + int' => [ + 'testMarker' => '/* test Calc2 */', + 'expectedTokens' => [ + [ + 'code' => T_DNUMBER, + 'content' => '6.674_08e3', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_PLUS, + 'content' => '+', + ], + [ + 'code' => T_WHITESPACE, + 'content' => ' ', + ], + [ + 'code' => T_LNUMBER, + 'content' => '11', + ], + ], + ], + ]; + + }//end dataNoBackfill() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.inc new file mode 100644 index 000000000..eb36e3870 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.inc @@ -0,0 +1,156 @@ +readonly = 'foo'; + + /* testReadonlyPropertyInTernaryOperator */ + $isReadonly = $this->readonly ? true : false; + } +} + +/* testReadonlyUsedAsFunctionName */ +function readonly() {} + +/* testReadonlyUsedAsFunctionNameWithReturnByRef */ +function &readonly() {} + +/* testReadonlyUsedAsNamespaceName */ +namespace Readonly; +/* testReadonlyUsedAsPartOfNamespaceName */ +namespace My\Readonly\Collection; +/* testReadonlyAsFunctionCall */ +$var = readonly($a, $b); +/* testReadonlyAsNamespacedFunctionCall */ +$var = My\NS\readonly($a, $b); +/* testReadonlyAsNamespaceRelativeFunctionCall */ +$var = namespace\ReadOnly($a, $b); +/* testReadonlyAsMethodCall */ +$var = $obj->readonly($a, $b); +/* testReadonlyAsNullsafeMethodCall */ +$var = $obj?->readOnly($a, $b); +/* testReadonlyAsStaticMethodCallWithSpace */ +$var = ClassName::readonly ($a, $b); +/* testClassConstantFetchWithReadonlyAsConstantName */ +echo ClassName::READONLY; + +/* testReadonlyUsedAsFunctionCallWithSpaceBetweenKeywordAndParens */ +$var = readonly /* comment */ (); + +// These test cases are inspired by +// https://github.com/php/php-src/commit/08b75395838b4b42a41e3c70684fa6c6b113eee0 +class ReadonlyWithDisjunctiveNormalForm +{ + /* testReadonlyPropertyDNFTypeUnqualified */ + readonly (B&C)|A $h; + + /* testReadonlyPropertyDNFTypeFullyQualified */ + public readonly (\Fully\Qualified\B&\Full\C)|\Foo\Bar $j; + + /* testReadonlyPropertyDNFTypePartiallyQualified */ + protected readonly (Partially\Qualified&C)|A $l; + + /* testReadonlyPropertyDNFTypeRelativeName */ + private readonly (namespace\Relative&C)|A $n; + + /* testReadonlyPropertyDNFTypeMultipleSets */ + private readonly (A&C)|(B&C)|(C&D) $m; + + /* testReadonlyPropertyDNFTypeWithArray */ + private readonly (B & C)|array $o; + + /* testReadonlyPropertyDNFTypeWithSpacesAndComments */ + private readonly ( B & C /*something*/) | A $q; + + public function __construct( + /* testReadonlyConstructorPropertyPromotionWithDNF */ + private readonly (B&C)|A $b1, + /* testReadonlyConstructorPropertyPromotionWithDNFAndReference */ + readonly (B&C)|A &$b2, + ) {} + + /* testReadonlyUsedAsMethodNameWithDNFParam */ + public function readonly (A&B $param): void {} +} + +/* testReadonlyAnonClassWithParens */ +$anon = new readonly class() {}; + +/* testReadonlyAnonClassWithoutParens */ +$anon = new Readonly class {}; + +/* testReadonlyAnonClassWithCommentsAndWhitespace */ +$anon = new +// comment +READONLY +// phpcs:ignore Stnd.Cat.Sniff +class {}; + +/* testParseErrorLiveCoding */ +// This must be the last test in the file. +readonly diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.php new file mode 100644 index 000000000..89dc3e19d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BackfillReadonlyTest.php @@ -0,0 +1,271 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class BackfillReadonlyTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the "readonly" keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent Optional. The token content to look for. + * Defaults to lowercase "readonly". + * + * @dataProvider dataReadonly + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testReadonly($testMarker, $testContent='readonly') + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_READONLY, T_STRING], $testContent); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_READONLY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_READONLY (code)'); + $this->assertSame('T_READONLY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_READONLY (type)'); + + }//end testReadonly() + + + /** + * Data provider. + * + * @see testReadonly() + * + * @return array> + */ + public static function dataReadonly() + { + return [ + 'property declaration, no visibility' => [ + 'testMarker' => '/* testReadonlyProperty */', + ], + 'property declaration, var keyword before' => [ + 'testMarker' => '/* testVarReadonlyProperty */', + ], + 'property declaration, var keyword after' => [ + 'testMarker' => '/* testReadonlyVarProperty */', + ], + 'property declaration, static before' => [ + 'testMarker' => '/* testStaticReadonlyProperty */', + ], + 'property declaration, static after' => [ + 'testMarker' => '/* testReadonlyStaticProperty */', + ], + 'constant declaration, with visibility' => [ + 'testMarker' => '/* testConstReadonlyProperty */', + ], + 'property declaration, missing type' => [ + 'testMarker' => '/* testReadonlyPropertyWithoutType */', + ], + 'property declaration, public before' => [ + 'testMarker' => '/* testPublicReadonlyProperty */', + ], + 'property declaration, protected before' => [ + 'testMarker' => '/* testProtectedReadonlyProperty */', + ], + 'property declaration, private before' => [ + 'testMarker' => '/* testPrivateReadonlyProperty */', + ], + 'property declaration, public after' => [ + 'testMarker' => '/* testPublicReadonlyPropertyWithReadonlyFirst */', + ], + 'property declaration, protected after' => [ + 'testMarker' => '/* testProtectedReadonlyPropertyWithReadonlyFirst */', + ], + 'property declaration, private after' => [ + 'testMarker' => '/* testPrivateReadonlyPropertyWithReadonlyFirst */', + ], + 'property declaration, private before, comments in declaration' => [ + 'testMarker' => '/* testReadonlyWithCommentsInDeclaration */', + ], + 'property declaration, private before, nullable type' => [ + 'testMarker' => '/* testReadonlyWithNullableProperty */', + ], + 'property declaration, private before, union type, null first' => [ + 'testMarker' => '/* testReadonlyNullablePropertyWithUnionTypeHintAndNullFirst */', + ], + 'property declaration, private before, union type, null last' => [ + 'testMarker' => '/* testReadonlyNullablePropertyWithUnionTypeHintAndNullLast */', + ], + 'property declaration, private before, array type' => [ + 'testMarker' => '/* testReadonlyPropertyWithArrayTypeHint */', + ], + 'property declaration, private before, self type' => [ + 'testMarker' => '/* testReadonlyPropertyWithSelfTypeHint */', + ], + 'property declaration, private before, parent type' => [ + 'testMarker' => '/* testReadonlyPropertyWithParentTypeHint */', + ], + 'property declaration, private before, FQN type' => [ + 'testMarker' => '/* testReadonlyPropertyWithFullyQualifiedTypeHint */', + ], + 'property declaration, public before, mixed case' => [ + 'testMarker' => '/* testReadonlyIsCaseInsensitive */', + 'testContent' => 'ReAdOnLy', + ], + 'property declaration, constructor property promotion' => [ + 'testMarker' => '/* testReadonlyConstructorPropertyPromotion */', + ], + 'property declaration, constructor property promotion with reference, mixed case' => [ + 'testMarker' => '/* testReadonlyConstructorPropertyPromotionWithReference */', + 'testContent' => 'ReadOnly', + ], + 'property declaration, in anonymous class' => [ + 'testMarker' => '/* testReadonlyPropertyInAnonymousClass */', + ], + 'property declaration, no visibility, DNF type, unqualified' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypeUnqualified */', + ], + 'property declaration, public before, DNF type, fully qualified' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypeFullyQualified */', + ], + 'property declaration, protected before, DNF type, partially qualified' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypePartiallyQualified */', + ], + 'property declaration, private before, DNF type, namespace relative name' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypeRelativeName */', + ], + 'property declaration, private before, DNF type, multiple sets' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypeMultipleSets */', + ], + 'property declaration, private before, DNF type, union with array' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypeWithArray */', + ], + 'property declaration, private before, DNF type, with spaces and comment' => [ + 'testMarker' => '/* testReadonlyPropertyDNFTypeWithSpacesAndComments */', + ], + 'property declaration, constructor property promotion, DNF type' => [ + 'testMarker' => '/* testReadonlyConstructorPropertyPromotionWithDNF */', + ], + 'property declaration, constructor property promotion, DNF type and reference' => [ + 'testMarker' => '/* testReadonlyConstructorPropertyPromotionWithDNFAndReference */', + ], + 'anon class declaration, with parentheses' => [ + 'testMarker' => '/* testReadonlyAnonClassWithParens */', + ], + 'anon class declaration, without parentheses' => [ + 'testMarker' => '/* testReadonlyAnonClassWithoutParens */', + 'testContent' => 'Readonly', + ], + 'anon class declaration, with comments and whitespace' => [ + 'testMarker' => '/* testReadonlyAnonClassWithCommentsAndWhitespace */', + 'testContent' => 'READONLY', + ], + 'live coding / parse error' => [ + 'testMarker' => '/* testParseErrorLiveCoding */', + ], + ]; + + }//end dataReadonly() + + + /** + * Test that "readonly" when not used as the keyword is still tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $testContent Optional. The token content to look for. + * Defaults to lowercase "readonly". + * + * @dataProvider dataNotReadonly + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotReadonly($testMarker, $testContent='readonly') + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_READONLY, T_STRING], $testContent); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testNotReadonly() + + + /** + * Data provider. + * + * @see testNotReadonly() + * + * @return array> + */ + public static function dataNotReadonly() + { + return [ + 'name of a constant, context: declaration using "const" keyword, uppercase' => [ + 'testMarker' => '/* testReadonlyUsedAsClassConstantName */', + 'testContent' => 'READONLY', + ], + 'name of a method, context: declaration' => [ + 'testMarker' => '/* testReadonlyUsedAsMethodName */', + ], + 'name of a property, context: property access' => [ + 'testMarker' => '/* testReadonlyUsedAsPropertyName */', + ], + 'name of a property, context: property access in ternary' => [ + 'testMarker' => '/* testReadonlyPropertyInTernaryOperator */', + ], + 'name of a function, context: declaration' => [ + 'testMarker' => '/* testReadonlyUsedAsFunctionName */', + ], + 'name of a function, context: declaration with return by ref' => [ + 'testMarker' => '/* testReadonlyUsedAsFunctionNameWithReturnByRef */', + ], + 'name of namespace, context: declaration, mixed case' => [ + 'testMarker' => '/* testReadonlyUsedAsNamespaceName */', + 'testContent' => 'Readonly', + ], + 'partial name of namespace, context: declaration, mixed case' => [ + 'testMarker' => '/* testReadonlyUsedAsPartOfNamespaceName */', + 'testContent' => 'Readonly', + ], + 'name of a function, context: call' => [ + 'testMarker' => '/* testReadonlyAsFunctionCall */', + ], + 'name of a namespaced function, context: partially qualified call' => [ + 'testMarker' => '/* testReadonlyAsNamespacedFunctionCall */', + ], + 'name of a function, context: namespace relative call, mixed case' => [ + 'testMarker' => '/* testReadonlyAsNamespaceRelativeFunctionCall */', + 'testContent' => 'ReadOnly', + ], + 'name of a method, context: method call on object' => [ + 'testMarker' => '/* testReadonlyAsMethodCall */', + ], + 'name of a method, context: nullsafe method call on object' => [ + 'testMarker' => '/* testReadonlyAsNullsafeMethodCall */', + 'testContent' => 'readOnly', + ], + 'name of a method, context: static method call with space after' => [ + 'testMarker' => '/* testReadonlyAsStaticMethodCallWithSpace */', + ], + 'name of a constant, context: constant access - uppercase' => [ + 'testMarker' => '/* testClassConstantFetchWithReadonlyAsConstantName */', + 'testContent' => 'READONLY', + ], + 'name of a function, context: call with space and comment between keyword and parens' => [ + 'testMarker' => '/* testReadonlyUsedAsFunctionCallWithSpaceBetweenKeywordAndParens */', + ], + 'name of a method, context: declaration with DNF parameter' => [ + 'testMarker' => '/* testReadonlyUsedAsMethodNameWithDNFParam */', + ], + ]; + + }//end dataNotReadonly() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.inc new file mode 100644 index 000000000..54ff50822 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.inc @@ -0,0 +1,183 @@ + $param | $int; + +/* testTypeUnionArrowReturnType */ +$arrowWithReturnType = fn ($param) : int|null => $param * 10; + +/* testBitwiseOrInArrayKey */ +$array = array( + A | B => /* testBitwiseOrInArrayValue */ B | C +); + +/* testBitwiseOrInShortArrayKey */ +$array = [ + A | B => /* testBitwiseOrInShortArrayValue */ B | C +]; + +/* testBitwiseOrTryCatch */ +try { +} catch ( ExceptionA | ExceptionB $e ) { +} + +/* testBitwiseOrNonArrowFnFunctionCall */ +$obj->fn($something | $else); + +/* testTypeUnionNonArrowFunctionDeclaration */ +function &fn(int|false $something) {} + +/* testTypeUnionPHP82TrueFirst */ +function trueTypeParam(true|null $param) {} + +/* testTypeUnionPHP82TrueMiddle */ +function trueTypeReturn($param): array|true|null {} + +/* testTypeUnionPHP82TrueLast */ +$closure = function ($param): array|true {} + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +return function( type| diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.php new file mode 100644 index 000000000..3c9fa50a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/BitwiseOrTest.php @@ -0,0 +1,160 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class BitwiseOrTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that non-union type bitwise or tokens are still tokenized as bitwise or. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataBitwiseOr + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBitwiseOr($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_BITWISE_OR, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_BITWISE_OR (code)'); + $this->assertSame('T_BITWISE_OR', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_BITWISE_OR (type)'); + + }//end testBitwiseOr() + + + /** + * Data provider. + * + * @see testBitwiseOr() + * + * @return array> + */ + public static function dataBitwiseOr() + { + return [ + 'in simple assignment 1' => ['/* testBitwiseOr1 */'], + 'in simple assignment 2' => ['/* testBitwiseOr2 */'], + 'in OO constant default value' => ['/* testBitwiseOrOOConstDefaultValue */'], + 'in property default value' => ['/* testBitwiseOrPropertyDefaultValue */'], + 'in method parameter default value' => ['/* testBitwiseOrParamDefaultValue */'], + 'in return statement' => ['/* testBitwiseOr3 */'], + 'in closure parameter default value' => ['/* testBitwiseOrClosureParamDefault */'], + 'in OO constant default value DNF-like' => ['/* testBitwiseOrOOConstDefaultValueDNF */'], + 'in property default value DNF-like' => ['/* testBitwiseOrPropertyDefaultValueDNF */'], + 'in method parameter default value DNF-like' => ['/* testBitwiseOrParamDefaultValueDNF */'], + 'in arrow function parameter default value' => ['/* testBitwiseOrArrowParamDefault */'], + 'in arrow function return expression' => ['/* testBitwiseOrArrowExpression */'], + 'in long array key' => ['/* testBitwiseOrInArrayKey */'], + 'in long array value' => ['/* testBitwiseOrInArrayValue */'], + 'in short array key' => ['/* testBitwiseOrInShortArrayKey */'], + 'in short array value' => ['/* testBitwiseOrInShortArrayValue */'], + 'in catch condition' => ['/* testBitwiseOrTryCatch */'], + 'in parameter in function call' => ['/* testBitwiseOrNonArrowFnFunctionCall */'], + 'live coding / undetermined' => ['/* testLiveCoding */'], + ]; + + }//end dataBitwiseOr() + + + /** + * Test that bitwise or tokens when used as part of a union type are tokenized as `T_TYPE_UNION`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataTypeUnion + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypeUnion($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_TYPE_UNION, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_TYPE_UNION (code)'); + $this->assertSame('T_TYPE_UNION', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_TYPE_UNION (type)'); + + }//end testTypeUnion() + + + /** + * Data provider. + * + * @see testTypeUnion() + * + * @return array> + */ + public static function dataTypeUnion() + { + return [ + 'type for OO constant' => ['/* testTypeUnionOOConstSimple */'], + 'type for OO constant, reversed modifier order' => ['/* testTypeUnionOOConstReverseModifierOrder */'], + 'type for OO constant, first of multi-union' => ['/* testTypeUnionOOConstMulti1 */'], + 'type for OO constant, middle of multi-union + comments' => ['/* testTypeUnionOOConstMulti2 */'], + 'type for OO constant, last of multi-union' => ['/* testTypeUnionOOConstMulti3 */'], + 'type for OO constant, using namespace relative names' => ['/* testTypeUnionOOConstNamespaceRelative */'], + 'type for OO constant, using partially qualified names' => ['/* testTypeUnionOOConstPartiallyQualified */'], + 'type for OO constant, using fully qualified names' => ['/* testTypeUnionOOConstFullyQualified */'], + 'type for static property' => ['/* testTypeUnionPropertySimple */'], + 'type for static property, reversed modifier order' => ['/* testTypeUnionPropertyReverseModifierOrder */'], + 'type for property, first of multi-union' => ['/* testTypeUnionPropertyMulti1 */'], + 'type for property, middle of multi-union, also comments' => ['/* testTypeUnionPropertyMulti2 */'], + 'type for property, last of multi-union' => ['/* testTypeUnionPropertyMulti3 */'], + 'type for property using namespace relative names' => ['/* testTypeUnionPropertyNamespaceRelative */'], + 'type for property using partially qualified names' => ['/* testTypeUnionPropertyPartiallyQualified */'], + 'type for property using fully qualified names' => ['/* testTypeUnionPropertyFullyQualified */'], + 'type for readonly property' => ['/* testTypeUnionPropertyWithReadOnlyKeyword */'], + 'type for static readonly property' => ['/* testTypeUnionPropertyWithStaticAndReadOnlyKeywords */'], + 'type for readonly property using var keyword' => ['/* testTypeUnionPropertyWithVarAndReadOnlyKeywords */'], + 'type for readonly property, reversed modifier order' => ['/* testTypeUnionPropertyWithReadOnlyKeywordFirst */'], + 'type for readonly property, no visibility' => ['/* testTypeUnionPropertyWithOnlyReadOnlyKeyword */'], + 'type for static property, no visibility' => ['/* testTypeUnionPropertyWithOnlyStaticKeyword */'], + 'type for method parameter' => ['/* testTypeUnionParam1 */'], + 'type for method parameter, first in multi-union' => ['/* testTypeUnionParam2 */'], + 'type for method parameter, last in multi-union' => ['/* testTypeUnionParam3 */'], + 'type for method parameter with namespace relative names' => ['/* testTypeUnionParamNamespaceRelative */'], + 'type for method parameter with partially qualified names' => ['/* testTypeUnionParamPartiallyQualified */'], + 'type for method parameter with fully qualified names' => ['/* testTypeUnionParamFullyQualified */'], + 'type for property in constructor property promotion' => ['/* testTypeUnionConstructorPropertyPromotion */'], + 'return type for method' => ['/* testTypeUnionReturnType */'], + 'return type for method, first of multi-union' => ['/* testTypeUnionAbstractMethodReturnType1 */'], + 'return type for method, last of multi-union' => ['/* testTypeUnionAbstractMethodReturnType2 */'], + 'return type for method with namespace relative names' => ['/* testTypeUnionReturnTypeNamespaceRelative */'], + 'return type for method with partially qualified names' => ['/* testTypeUnionReturnPartiallyQualified */'], + 'return type for method with fully qualified names' => ['/* testTypeUnionReturnFullyQualified */'], + 'type for function parameter with reference' => ['/* testTypeUnionWithReference */'], + 'type for function parameter with spread operator' => ['/* testTypeUnionWithSpreadOperator */'], + 'DNF type for OO constant, union before DNF' => ['/* testTypeUnionConstantTypeUnionBeforeDNF */'], + 'DNF type for property, union after DNF' => ['/* testTypeUnionPropertyTypeUnionAfterDNF */'], + 'DNF type for function param, union before and after DNF' => ['/* testTypeUnionParamUnionBeforeAndAfterDNF */'], + 'DNF type for function return, union after DNF with null' => ['/* testTypeUnionReturnTypeUnionAfterDNF */'], + 'type for closure parameter with illegal nullable' => ['/* testTypeUnionClosureParamIllegalNullable */'], + 'return type for closure' => ['/* testTypeUnionClosureReturn */'], + 'type for arrow function parameter' => ['/* testTypeUnionArrowParam */'], + 'return type for arrow function' => ['/* testTypeUnionArrowReturnType */'], + 'type for function parameter, return by ref' => ['/* testTypeUnionNonArrowFunctionDeclaration */'], + 'type for function param with true type first' => ['/* testTypeUnionPHP82TrueFirst */'], + 'type for function param with true type middle' => ['/* testTypeUnionPHP82TrueMiddle */'], + 'type for function param with true type last' => ['/* testTypeUnionPHP82TrueLast */'], + ]; + + }//end dataTypeUnion() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.inc new file mode 100644 index 000000000..2825f26e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.inc @@ -0,0 +1,244 @@ + 'a', + 2 => 'b', + /* testMatchDefaultIsKeyword */ default => 'default', +}; + +$closure = /* testFnIsKeyword */ fn () => 'string'; + +function () { + /* testYieldIsKeyword */ yield $f; + /* testYieldFromIsKeyword */ yield from someFunction(); +}; + +/* testDeclareIsKeyword */ declare(ticks=1): +/* testEndDeclareIsKeyword */ enddeclare; + +if (true /* testAndIsKeyword */ and false /* testOrIsKeyword */ or null /* testXorIsKeyword */ xor 0) { + +} + +$anonymousClass = new /* testAnonymousClassIsKeyword */ class {}; +$anonymousClass2 = new class /* testExtendsInAnonymousClassIsKeyword */ extends SomeParent {}; +$anonymousClass3 = new class /* testImplementsInAnonymousClassIsKeyword */ implements SomeInterface {}; + +$instantiated = new /* testClassInstantiationStaticIsKeyword */ static($param); + +class Foo extends /* testNamespaceInNameIsKeyword */ namespace\Exception +{} + +function /* testKeywordAfterFunctionShouldBeString */ eval() {} +function /* testKeywordAfterFunctionByRefShouldBeString */ &switch() {} + +function /* testKeywordStaticAfterFunctionByRefShouldBeString */ &static() {} + +/* testKeywordAsFunctionCallNameShouldBeStringStatic */ static(); +$obj-> /* testKeywordAsMethodCallNameShouldBeStringStatic */ static(); + +$function = /* testStaticIsKeywordBeforeClosure */ static function(/* testStaticIsKeywordWhenParamType */ static $param) {}; +$arrow = /* testStaticIsKeywordBeforeArrow */ static fn(): /* testStaticIsKeywordWhenReturnType */ static => 10; + +/* testKeywordAsFunctionCallNameShouldBeStringStaticDNFLookaLike */ +$obj->static((CONST_A&CONST_B)|CONST_C | $var); + +class DNF { + public /* testStaticIsKeywordPropertyModifierBeforeDNF */ static (DN&F)|null $dnfProp; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.php new file mode 100644 index 000000000..103e5ec91 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ContextSensitiveKeywordsTest.php @@ -0,0 +1,548 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class ContextSensitiveKeywordsTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that context sensitive keyword is tokenized as string when it should be string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataStrings + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testStrings($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, (Tokens::$contextSensitiveKeywords + [T_STRING])); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testStrings() + + + /** + * Data provider. + * + * @see testStrings() + * + * @return array> + */ + public static function dataStrings() + { + return [ + 'constant declaration: abstract' => ['/* testAbstract */'], + 'constant declaration: array' => ['/* testArray */'], + 'constant declaration: as' => ['/* testAs */'], + 'constant declaration: break' => ['/* testBreak */'], + 'constant declaration: callable' => ['/* testCallable */'], + 'constant declaration: case' => ['/* testCase */'], + 'constant declaration: catch' => ['/* testCatch */'], + 'constant declaration: class' => ['/* testClass */'], + 'constant declaration: clone' => ['/* testClone */'], + 'constant declaration: const' => ['/* testConst */'], + 'constant declaration: continue' => ['/* testContinue */'], + 'constant declaration: declare' => ['/* testDeclare */'], + 'constant declaration: default' => ['/* testDefault */'], + 'constant declaration: do' => ['/* testDo */'], + 'constant declaration: echo' => ['/* testEcho */'], + 'constant declaration: else' => ['/* testElse */'], + 'constant declaration: elseif' => ['/* testElseIf */'], + 'constant declaration: empty' => ['/* testEmpty */'], + 'constant declaration: enddeclare' => ['/* testEndDeclare */'], + 'constant declaration: endfor' => ['/* testEndFor */'], + 'constant declaration: endforeach' => ['/* testEndForeach */'], + 'constant declaration: endif' => ['/* testEndIf */'], + 'constant declaration: endswitch' => ['/* testEndSwitch */'], + 'constant declaration: endwhile' => ['/* testEndWhile */'], + 'constant declaration: enum' => ['/* testEnum */'], + 'constant declaration: eval' => ['/* testEval */'], + 'constant declaration: exit' => ['/* testExit */'], + 'constant declaration: extends' => ['/* testExtends */'], + 'constant declaration: final' => ['/* testFinal */'], + 'constant declaration: finally' => ['/* testFinally */'], + 'constant declaration: fn' => ['/* testFn */'], + 'constant declaration: for' => ['/* testFor */'], + 'constant declaration: foreach' => ['/* testForeach */'], + 'constant declaration: function' => ['/* testFunction */'], + 'constant declaration: global' => ['/* testGlobal */'], + 'constant declaration: goto' => ['/* testGoto */'], + 'constant declaration: if' => ['/* testIf */'], + 'constant declaration: implements' => ['/* testImplements */'], + 'constant declaration: include' => ['/* testInclude */'], + 'constant declaration: include_once' => ['/* testIncludeOnce */'], + 'constant declaration: instanceof' => ['/* testInstanceOf */'], + 'constant declaration: insteadof' => ['/* testInsteadOf */'], + 'constant declaration: interface' => ['/* testInterface */'], + 'constant declaration: isset' => ['/* testIsset */'], + 'constant declaration: list' => ['/* testList */'], + 'constant declaration: match' => ['/* testMatch */'], + 'constant declaration: namespace' => ['/* testNamespace */'], + 'constant declaration: new' => ['/* testNew */'], + 'constant declaration: print' => ['/* testPrint */'], + 'constant declaration: private' => ['/* testPrivate */'], + 'constant declaration: protected' => ['/* testProtected */'], + 'constant declaration: public' => ['/* testPublic */'], + 'constant declaration: readonly' => ['/* testReadonly */'], + 'constant declaration: require' => ['/* testRequire */'], + 'constant declaration: require_once' => ['/* testRequireOnce */'], + 'constant declaration: return' => ['/* testReturn */'], + 'constant declaration: static' => ['/* testStatic */'], + 'constant declaration: switch' => ['/* testSwitch */'], + 'constant declaration: throws' => ['/* testThrows */'], + 'constant declaration: trait' => ['/* testTrait */'], + 'constant declaration: try' => ['/* testTry */'], + 'constant declaration: unset' => ['/* testUnset */'], + 'constant declaration: use' => ['/* testUse */'], + 'constant declaration: var' => ['/* testVar */'], + 'constant declaration: while' => ['/* testWhile */'], + 'constant declaration: yield' => ['/* testYield */'], + 'constant declaration: yield_from' => ['/* testYieldFrom */'], + 'constant declaration: and' => ['/* testAnd */'], + 'constant declaration: or' => ['/* testOr */'], + 'constant declaration: xor' => ['/* testXor */'], + + 'constant declaration: array in type' => ['/* testArrayIsTstringInConstType */'], + 'constant declaration: array, name after type' => ['/* testArrayNameForTypedConstant */'], + 'constant declaration: static, name after type' => ['/* testStaticIsNameForTypedConstant */'], + 'constant declaration: private, name after type' => ['/* testPrivateNameForUnionTypedConstant */'], + 'constant declaration: final, name after type' => ['/* testFinalNameForIntersectionTypedConstant */'], + + 'namespace declaration: class' => ['/* testKeywordAfterNamespaceShouldBeString */'], + 'namespace declaration (partial): my' => ['/* testNamespaceNameIsString1 */'], + 'namespace declaration (partial): class' => ['/* testNamespaceNameIsString2 */'], + 'namespace declaration (partial): foreach' => ['/* testNamespaceNameIsString3 */'], + + 'function declaration: eval' => ['/* testKeywordAfterFunctionShouldBeString */'], + 'function declaration with return by ref: switch' => ['/* testKeywordAfterFunctionByRefShouldBeString */'], + 'function declaration with return by ref: static' => ['/* testKeywordStaticAfterFunctionByRefShouldBeString */'], + + 'function call: static' => ['/* testKeywordAsFunctionCallNameShouldBeStringStatic */'], + 'method call: static' => ['/* testKeywordAsMethodCallNameShouldBeStringStatic */'], + 'method call: static with dnf look a like param' => ['/* testKeywordAsFunctionCallNameShouldBeStringStaticDNFLookaLike */'], + ]; + + }//end dataStrings() + + + /** + * Test that context sensitive keyword is tokenized as keyword when it should be keyword. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedTokenType The expected token type. + * + * @dataProvider dataKeywords + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testKeywords($testMarker, $expectedTokenType) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, (Tokens::$contextSensitiveKeywords + [T_ANON_CLASS, T_MATCH_DEFAULT, T_STRING])); + $tokenArray = $tokens[$target]; + + $this->assertSame( + constant($expectedTokenType), + $tokenArray['code'], + 'Token tokenized as '.$tokenArray['type'].', not '.$expectedTokenType.' (code)' + ); + $this->assertSame( + $expectedTokenType, + $tokenArray['type'], + 'Token tokenized as '.$tokenArray['type'].', not '.$expectedTokenType.' (type)' + ); + + }//end testKeywords() + + + /** + * Data provider. + * + * @see testKeywords() + * + * @return array + */ + public static function dataKeywords() + { + return [ + 'namespace: declaration' => [ + 'testMarker' => '/* testNamespaceIsKeyword */', + 'expectedTokenType' => 'T_NAMESPACE', + ], + 'array: default value in const decl' => [ + 'testMarker' => '/* testArrayIsKeywordInConstDefault */', + 'expectedTokenType' => 'T_ARRAY', + ], + 'static: type in constant declaration' => [ + 'testMarker' => '/* testStaticIsKeywordAsConstType */', + 'expectedTokenType' => 'T_STATIC', + ], + 'static: value in constant declaration' => [ + 'testMarker' => '/* testStaticIsKeywordAsConstDefault */', + 'expectedTokenType' => 'T_STATIC', + ], + + 'abstract: class declaration' => [ + 'testMarker' => '/* testAbstractIsKeyword */', + 'expectedTokenType' => 'T_ABSTRACT', + ], + 'class: declaration' => [ + 'testMarker' => '/* testClassIsKeyword */', + 'expectedTokenType' => 'T_CLASS', + ], + 'extends: in class declaration' => [ + 'testMarker' => '/* testExtendsIsKeyword */', + 'expectedTokenType' => 'T_EXTENDS', + ], + 'implements: in class declaration' => [ + 'testMarker' => '/* testImplementsIsKeyword */', + 'expectedTokenType' => 'T_IMPLEMENTS', + ], + 'use: in trait import' => [ + 'testMarker' => '/* testUseIsKeyword */', + 'expectedTokenType' => 'T_USE', + ], + 'insteadof: in trait import' => [ + 'testMarker' => '/* testInsteadOfIsKeyword */', + 'expectedTokenType' => 'T_INSTEADOF', + ], + 'as: in trait import' => [ + 'testMarker' => '/* testAsIsKeyword */', + 'expectedTokenType' => 'T_AS', + ], + 'const: declaration' => [ + 'testMarker' => '/* testConstIsKeyword */', + 'expectedTokenType' => 'T_CONST', + ], + 'private: property declaration' => [ + 'testMarker' => '/* testPrivateIsKeyword */', + 'expectedTokenType' => 'T_PRIVATE', + ], + 'protected: property declaration' => [ + 'testMarker' => '/* testProtectedIsKeyword */', + 'expectedTokenType' => 'T_PROTECTED', + ], + 'public: property declaration' => [ + 'testMarker' => '/* testPublicIsKeyword */', + 'expectedTokenType' => 'T_PUBLIC', + ], + 'var: property declaration' => [ + 'testMarker' => '/* testVarIsKeyword */', + 'expectedTokenType' => 'T_VAR', + ], + 'static: property declaration' => [ + 'testMarker' => '/* testStaticIsKeyword */', + 'expectedTokenType' => 'T_STATIC', + ], + 'readonly: property declaration' => [ + 'testMarker' => '/* testReadonlyIsKeywordForProperty */', + 'expectedTokenType' => 'T_READONLY', + ], + 'final: function declaration' => [ + 'testMarker' => '/* testFinalIsKeyword */', + 'expectedTokenType' => 'T_FINAL', + ], + 'function: declaration' => [ + 'testMarker' => '/* testFunctionIsKeyword */', + 'expectedTokenType' => 'T_FUNCTION', + ], + 'callable: param type declaration' => [ + 'testMarker' => '/* testCallableIsKeyword */', + 'expectedTokenType' => 'T_CALLABLE', + ], + 'readonly: anon class declaration' => [ + 'testMarker' => '/* testReadonlyIsKeywordForAnonClass */', + 'expectedTokenType' => 'T_READONLY', + ], + 'return: statement' => [ + 'testMarker' => '/* testReturnIsKeyword */', + 'expectedTokenType' => 'T_RETURN', + ], + + 'interface: declaration' => [ + 'testMarker' => '/* testInterfaceIsKeyword */', + 'expectedTokenType' => 'T_INTERFACE', + ], + 'trait: declaration' => [ + 'testMarker' => '/* testTraitIsKeyword */', + 'expectedTokenType' => 'T_TRAIT', + ], + 'enum: declaration' => [ + 'testMarker' => '/* testEnumIsKeyword */', + 'expectedTokenType' => 'T_ENUM', + ], + + 'new: named instantiation' => [ + 'testMarker' => '/* testNewIsKeyword */', + 'expectedTokenType' => 'T_NEW', + ], + 'instanceof: comparison' => [ + 'testMarker' => '/* testInstanceOfIsKeyword */', + 'expectedTokenType' => 'T_INSTANCEOF', + ], + 'clone' => [ + 'testMarker' => '/* testCloneIsKeyword */', + 'expectedTokenType' => 'T_CLONE', + ], + + 'if' => [ + 'testMarker' => '/* testIfIsKeyword */', + 'expectedTokenType' => 'T_IF', + ], + 'empty' => [ + 'testMarker' => '/* testEmptyIsKeyword */', + 'expectedTokenType' => 'T_EMPTY', + ], + 'elseif' => [ + 'testMarker' => '/* testElseIfIsKeyword */', + 'expectedTokenType' => 'T_ELSEIF', + ], + 'else' => [ + 'testMarker' => '/* testElseIsKeyword */', + 'expectedTokenType' => 'T_ELSE', + ], + 'endif' => [ + 'testMarker' => '/* testEndIfIsKeyword */', + 'expectedTokenType' => 'T_ENDIF', + ], + + 'for' => [ + 'testMarker' => '/* testForIsKeyword */', + 'expectedTokenType' => 'T_FOR', + ], + 'endfor' => [ + 'testMarker' => '/* testEndForIsKeyword */', + 'expectedTokenType' => 'T_ENDFOR', + ], + + 'foreach' => [ + 'testMarker' => '/* testForeachIsKeyword */', + 'expectedTokenType' => 'T_FOREACH', + ], + 'endforeach' => [ + 'testMarker' => '/* testEndForeachIsKeyword */', + 'expectedTokenType' => 'T_ENDFOREACH', + ], + + 'switch' => [ + 'testMarker' => '/* testSwitchIsKeyword */', + 'expectedTokenType' => 'T_SWITCH', + ], + 'case: in switch' => [ + 'testMarker' => '/* testCaseIsKeyword */', + 'expectedTokenType' => 'T_CASE', + ], + 'default: in switch' => [ + 'testMarker' => '/* testDefaultIsKeyword */', + 'expectedTokenType' => 'T_DEFAULT', + ], + 'endswitch' => [ + 'testMarker' => '/* testEndSwitchIsKeyword */', + 'expectedTokenType' => 'T_ENDSWITCH', + ], + 'break: in switch' => [ + 'testMarker' => '/* testBreakIsKeyword */', + 'expectedTokenType' => 'T_BREAK', + ], + 'continue: in switch' => [ + 'testMarker' => '/* testContinueIsKeyword */', + 'expectedTokenType' => 'T_CONTINUE', + ], + + 'do' => [ + 'testMarker' => '/* testDoIsKeyword */', + 'expectedTokenType' => 'T_DO', + ], + 'while' => [ + 'testMarker' => '/* testWhileIsKeyword */', + 'expectedTokenType' => 'T_WHILE', + ], + 'endwhile' => [ + 'testMarker' => '/* testEndWhileIsKeyword */', + 'expectedTokenType' => 'T_ENDWHILE', + ], + + 'try' => [ + 'testMarker' => '/* testTryIsKeyword */', + 'expectedTokenType' => 'T_TRY', + ], + 'throw: statement' => [ + 'testMarker' => '/* testThrowIsKeyword */', + 'expectedTokenType' => 'T_THROW', + ], + 'catch' => [ + 'testMarker' => '/* testCatchIsKeyword */', + 'expectedTokenType' => 'T_CATCH', + ], + 'finally' => [ + 'testMarker' => '/* testFinallyIsKeyword */', + 'expectedTokenType' => 'T_FINALLY', + ], + + 'global' => [ + 'testMarker' => '/* testGlobalIsKeyword */', + 'expectedTokenType' => 'T_GLOBAL', + ], + 'echo' => [ + 'testMarker' => '/* testEchoIsKeyword */', + 'expectedTokenType' => 'T_ECHO', + ], + 'print: statement' => [ + 'testMarker' => '/* testPrintIsKeyword */', + 'expectedTokenType' => 'T_PRINT', + ], + 'die: statement' => [ + 'testMarker' => '/* testDieIsKeyword */', + 'expectedTokenType' => 'T_EXIT', + ], + 'eval' => [ + 'testMarker' => '/* testEvalIsKeyword */', + 'expectedTokenType' => 'T_EVAL', + ], + 'exit: statement' => [ + 'testMarker' => '/* testExitIsKeyword */', + 'expectedTokenType' => 'T_EXIT', + ], + 'isset' => [ + 'testMarker' => '/* testIssetIsKeyword */', + 'expectedTokenType' => 'T_ISSET', + ], + 'unset' => [ + 'testMarker' => '/* testUnsetIsKeyword */', + 'expectedTokenType' => 'T_UNSET', + ], + + 'include' => [ + 'testMarker' => '/* testIncludeIsKeyword */', + 'expectedTokenType' => 'T_INCLUDE', + ], + 'include_once' => [ + 'testMarker' => '/* testIncludeOnceIsKeyword */', + 'expectedTokenType' => 'T_INCLUDE_ONCE', + ], + 'require' => [ + 'testMarker' => '/* testRequireIsKeyword */', + 'expectedTokenType' => 'T_REQUIRE', + ], + 'require_once' => [ + 'testMarker' => '/* testRequireOnceIsKeyword */', + 'expectedTokenType' => 'T_REQUIRE_ONCE', + ], + + 'list' => [ + 'testMarker' => '/* testListIsKeyword */', + 'expectedTokenType' => 'T_LIST', + ], + 'goto' => [ + 'testMarker' => '/* testGotoIsKeyword */', + 'expectedTokenType' => 'T_GOTO', + ], + 'match' => [ + 'testMarker' => '/* testMatchIsKeyword */', + 'expectedTokenType' => 'T_MATCH', + ], + 'default: in match expression' => [ + 'testMarker' => '/* testMatchDefaultIsKeyword */', + 'expectedTokenType' => 'T_MATCH_DEFAULT', + ], + 'fn' => [ + 'testMarker' => '/* testFnIsKeyword */', + 'expectedTokenType' => 'T_FN', + ], + + 'yield' => [ + 'testMarker' => '/* testYieldIsKeyword */', + 'expectedTokenType' => 'T_YIELD', + ], + 'yield from' => [ + 'testMarker' => '/* testYieldFromIsKeyword */', + 'expectedTokenType' => 'T_YIELD_FROM', + ], + + 'declare' => [ + 'testMarker' => '/* testDeclareIsKeyword */', + 'expectedTokenType' => 'T_DECLARE', + ], + 'enddeclare' => [ + 'testMarker' => '/* testEndDeclareIsKeyword */', + 'expectedTokenType' => 'T_ENDDECLARE', + ], + + 'and: in if' => [ + 'testMarker' => '/* testAndIsKeyword */', + 'expectedTokenType' => 'T_LOGICAL_AND', + ], + 'or: in if' => [ + 'testMarker' => '/* testOrIsKeyword */', + 'expectedTokenType' => 'T_LOGICAL_OR', + ], + 'xor: in if' => [ + 'testMarker' => '/* testXorIsKeyword */', + 'expectedTokenType' => 'T_LOGICAL_XOR', + ], + + 'class: anon class declaration' => [ + 'testMarker' => '/* testAnonymousClassIsKeyword */', + 'expectedTokenType' => 'T_ANON_CLASS', + ], + 'extends: anon class declaration' => [ + 'testMarker' => '/* testExtendsInAnonymousClassIsKeyword */', + 'expectedTokenType' => 'T_EXTENDS', + ], + 'implements: anon class declaration' => [ + 'testMarker' => '/* testImplementsInAnonymousClassIsKeyword */', + 'expectedTokenType' => 'T_IMPLEMENTS', + ], + 'static: class instantiation' => [ + 'testMarker' => '/* testClassInstantiationStaticIsKeyword */', + 'expectedTokenType' => 'T_STATIC', + ], + 'namespace: operator' => [ + 'testMarker' => '/* testNamespaceInNameIsKeyword */', + 'expectedTokenType' => 'T_NAMESPACE', + ], + + 'static: closure declaration' => [ + 'testMarker' => '/* testStaticIsKeywordBeforeClosure */', + 'expectedTokenType' => 'T_STATIC', + ], + 'static: parameter type (illegal)' => [ + 'testMarker' => '/* testStaticIsKeywordWhenParamType */', + 'expectedTokenType' => 'T_STATIC', + ], + 'static: arrow function declaration' => [ + 'testMarker' => '/* testStaticIsKeywordBeforeArrow */', + 'expectedTokenType' => 'T_STATIC', + ], + 'static: return type for arrow function' => [ + 'testMarker' => '/* testStaticIsKeywordWhenReturnType */', + 'expectedTokenType' => 'T_STATIC', + ], + 'static: property modifier before DNF' => [ + 'testMarker' => '/* testStaticIsKeywordPropertyModifierBeforeDNF */', + 'expectedTokenType' => 'T_STATIC', + ], + ]; + + }//end dataKeywords() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError1Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError1Test.inc new file mode 100644 index 000000000..a6cf511c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError1Test.inc @@ -0,0 +1,17 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class DNFTypesParseError1Test extends AbstractTokenizerTestCase +{ + + + /** + * Document handling for a DNF type / parse error where the last significant type specific token is an open parenthesis. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataBrokenDNFTypeCantEndOnOpenParenthesis + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBrokenDNFTypeCantEndOnOpenParenthesis($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS], '('); + $token = $tokens[$openPtr]; + + // Verify that the open parenthesis is tokenized as a normal parenthesis. + $this->assertSame(T_OPEN_PARENTHESIS, $token['code'], 'Token tokenized as '.$token['type'].', not T_OPEN_PARENTHESIS (code)'); + $this->assertSame('T_OPEN_PARENTHESIS', $token['type'], 'Token tokenized as '.$token['type'].', not T_OPEN_PARENTHESIS (type)'); + + // Verify that the type union is still tokenized as T_BITWISE_OR as the type declaration + // is not recognized as a valid type declaration. + $unionPtr = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION], '|'); + $token = $tokens[$unionPtr]; + + $this->assertSame(T_BITWISE_OR, $token['code'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (code)'); + $this->assertSame('T_BITWISE_OR', $token['type'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (type)'); + + }//end testBrokenDNFTypeCantEndOnOpenParenthesis() + + + /** + * Data provider. + * + * @see testBrokenDNFTypeCantEndOnOpenParenthesis() + * + * @return array> + */ + public static function dataBrokenDNFTypeCantEndOnOpenParenthesis() + { + return [ + 'OO const type' => ['/* testBrokenConstDNFTypeEndOnOpenParenthesis */'], + 'OO property type' => ['/* testBrokenPropertyDNFTypeEndOnOpenParenthesis */'], + 'Parameter type' => ['/* testBrokenParamDNFTypeEndOnOpenParenthesis */'], + 'Return type' => ['/* testBrokenReturnDNFTypeEndOnOpenParenthesis */'], + ]; + + }//end dataBrokenDNFTypeCantEndOnOpenParenthesis() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError2Test.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError2Test.inc new file mode 100644 index 000000000..792975828 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesParseError2Test.inc @@ -0,0 +1,48 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class DNFTypesParseError2Test extends AbstractTokenizerTestCase +{ + + + /** + * Document handling for a DNF type / parse error where the type declaration contains an unmatched parenthesis. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataBrokenDNFTypeParensShouldAlwaysBeAPairMissingCloseParens + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBrokenDNFTypeParensShouldAlwaysBeAPairMissingCloseParens($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + // Verify that the type union is still tokenized as T_BITWISE_OR as the type declaration + // is not recognized as a valid type declaration. + $unionPtr = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION], '|'); + $token = $tokens[$unionPtr]; + + $this->assertSame(T_BITWISE_OR, $token['code'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (code)'); + $this->assertSame('T_BITWISE_OR', $token['type'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (type)'); + + // Verify that the unmatched open parenthesis is tokenized as a normal parenthesis. + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS], '('); + $token = $tokens[$openPtr]; + + $this->assertSame(T_OPEN_PARENTHESIS, $token['code'], 'Token tokenized as '.$token['type'].', not T_OPEN_PARENTHESIS (code)'); + $this->assertSame('T_OPEN_PARENTHESIS', $token['type'], 'Token tokenized as '.$token['type'].', not T_OPEN_PARENTHESIS (type)'); + + // Verify that the type intersection is still tokenized as T_BITWISE_AND as the type declaration + // is not recognized as a valid type declaration. + $intersectPtr = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION], '&'); + $token = $tokens[$intersectPtr]; + + $this->assertSame(T_BITWISE_AND, $token['code'], 'Token tokenized as '.$token['type'].', not T_BITWISE_AND (code)'); + $this->assertSame('T_BITWISE_AND', $token['type'], 'Token tokenized as '.$token['type'].', not T_BITWISE_AND (type)'); + + }//end testBrokenDNFTypeParensShouldAlwaysBeAPairMissingCloseParens() + + + /** + * Data provider. + * + * @see testBrokenDNFTypeParensShouldAlwaysBeAPairMissingCloseParens() + * + * @return array> + */ + public static function dataBrokenDNFTypeParensShouldAlwaysBeAPairMissingCloseParens() + { + return [ + 'OO const type' => ['/* testBrokenConstDNFTypeParensMissingClose */'], + 'OO property type' => ['/* testBrokenPropertyDNFTypeParensMissingClose */'], + 'Parameter type' => ['/* testBrokenParamDNFTypeParensMissingClose */'], + 'Return type' => ['/* testBrokenReturnDNFTypeParensMissingClose */'], + ]; + + }//end dataBrokenDNFTypeParensShouldAlwaysBeAPairMissingCloseParens() + + + /** + * Document handling for a DNF type / parse error where the type declaration contains an unmatched parenthesis. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataBrokenDNFTypeParensShouldAlwaysBeAPairMissingOpenParens + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBrokenDNFTypeParensShouldAlwaysBeAPairMissingOpenParens($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + // Verify that the type union is still tokenized as T_BITWISE_OR as the type declaration + // is not recognized as a valid type declaration. + $unionPtr = $this->getTargetToken($testMarker, [T_BITWISE_OR, T_TYPE_UNION], '|'); + $token = $tokens[$unionPtr]; + + $this->assertSame(T_BITWISE_OR, $token['code'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (code)'); + $this->assertSame('T_BITWISE_OR', $token['type'], 'Token tokenized as '.$token['type'].', not T_BITWISE_OR (type)'); + + // Verify that the unmatched open parenthesis is tokenized as a normal parenthesis. + $closePtr = $this->getTargetToken($testMarker, [T_CLOSE_PARENTHESIS, T_TYPE_CLOSE_PARENTHESIS], ')'); + $token = $tokens[$closePtr]; + + $this->assertSame(T_CLOSE_PARENTHESIS, $token['code'], 'Token tokenized as '.$token['type'].', not T_CLOSE_PARENTHESIS (code)'); + $this->assertSame('T_CLOSE_PARENTHESIS', $token['type'], 'Token tokenized as '.$token['type'].', not T_CLOSE_PARENTHESIS (type)'); + + // Verify that the type intersection is still tokenized as T_BITWISE_AND as the type declaration + // is not recognized as a valid type declaration. + $intersectPtr = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION], '&'); + $token = $tokens[$intersectPtr]; + + $this->assertSame(T_BITWISE_AND, $token['code'], 'Token tokenized as '.$token['type'].', not T_BITWISE_AND (code)'); + $this->assertSame('T_BITWISE_AND', $token['type'], 'Token tokenized as '.$token['type'].', not T_BITWISE_AND (type)'); + + }//end testBrokenDNFTypeParensShouldAlwaysBeAPairMissingOpenParens() + + + /** + * Data provider. + * + * @see testBrokenDNFTypeParensShouldAlwaysBeAPairMissingOpenParens() + * + * @return array> + */ + public static function dataBrokenDNFTypeParensShouldAlwaysBeAPairMissingOpenParens() + { + return [ + 'OO const type' => ['/* testBrokenConstDNFTypeParensMissingOpen */'], + 'OO property type' => ['/* testBrokenPropertyDNFTypeParensMissingOpen */'], + 'Parameter type' => ['/* testBrokenParamDNFTypeParensMissingOpen */'], + 'Return type' => ['/* testBrokenReturnDNFTypeParensMissingOpen */'], + ]; + + }//end dataBrokenDNFTypeParensShouldAlwaysBeAPairMissingOpenParens() + + + /** + * Document handling for a DNF type / parse error where the type declaration contains an unmatched parenthesis, + * but also contains a set of matched parentheses. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataBrokenDNFTypeParensShouldAlwaysBeAPairMatchedAndUnmatched + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBrokenDNFTypeParensShouldAlwaysBeAPairMatchedAndUnmatched($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $startPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS], '('); + + for ($i = $startPtr; $i < $this->phpcsFile->numTokens; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + continue; + } + + if ($tokens[$i]['code'] === T_EQUAL + || $tokens[$i]['code'] === T_VARIABLE + || $tokens[$i]['code'] === T_OPEN_CURLY_BRACKET + ) { + // Reached the end of the type. + break; + } + + $errorPrefix = 'Token tokenized as '.$tokens[$i]['type']; + + // Verify that type tokens have not been retokenized to `T_TYPE_*` tokens for broken type declarations. + switch ($tokens[$i]['content']) { + case '|': + $this->assertSame(T_BITWISE_OR, $tokens[$i]['code'], $errorPrefix.', not T_BITWISE_OR (code)'); + $this->assertSame('T_BITWISE_OR', $tokens[$i]['type'], $errorPrefix.', not T_BITWISE_OR (type)'); + break; + + case '&': + $this->assertSame(T_BITWISE_AND, $tokens[$i]['code'], $errorPrefix.', not T_BITWISE_AND (code)'); + $this->assertSame('T_BITWISE_AND', $tokens[$i]['type'], $errorPrefix.', not T_BITWISE_AND (type)'); + break; + + case '(': + // Verify that the open parenthesis is tokenized as a normal parenthesis. + $this->assertSame(T_OPEN_PARENTHESIS, $tokens[$i]['code'], $errorPrefix.', not T_OPEN_PARENTHESIS (code)'); + $this->assertSame('T_OPEN_PARENTHESIS', $tokens[$i]['type'], $errorPrefix.', not T_OPEN_PARENTHESIS (type)'); + break; + + case ')': + $this->assertSame(T_CLOSE_PARENTHESIS, $tokens[$i]['code'], $errorPrefix.', not T_CLOSE_PARENTHESIS (code)'); + $this->assertSame('T_CLOSE_PARENTHESIS', $tokens[$i]['type'], $errorPrefix.', not T_CLOSE_PARENTHESIS (type)'); + break; + + default: + break; + }//end switch + }//end for + + }//end testBrokenDNFTypeParensShouldAlwaysBeAPairMatchedAndUnmatched() + + + /** + * Data provider. + * + * @see testBrokenDNFTypeParensShouldAlwaysBeAPairMatchedAndUnmatched() + * + * @return array> + */ + public static function dataBrokenDNFTypeParensShouldAlwaysBeAPairMatchedAndUnmatched() + { + return [ + 'OO const type - missing one close parenthesis' => ['/* testBrokenConstDNFTypeParensMissingOneClose */'], + 'OO property type - missing one open parenthesis' => ['/* testBrokenPropertyDNFTypeParensMissingOneOpen */'], + 'Parameter type - missing one close parenthesis' => ['/* testBrokenParamDNFTypeParensMissingOneClose */'], + 'Return type - missing one open parenthesis' => ['/* testBrokenReturnDNFTypeParensMissingOneOpen */'], + ]; + + }//end dataBrokenDNFTypeParensShouldAlwaysBeAPairMatchedAndUnmatched() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.inc new file mode 100644 index 000000000..5043ab7db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.inc @@ -0,0 +1,224 @@ + 10 ) {} + +/* testParensOwnerFor */ +for ($i =0; $i < /* testParensNoOwnerInForCondition */ ( CONST_A & CONST_B ); $i++ ); + +/* testParensOwnerMatch */ +$match = match(CONST_A & CONST_B) { + default => $a, +}; + +/* testParensOwnerArray */ +$array = array ( + 'text', + \CONST_A & \Fully\Qualified\CONST_B, + /* testParensNoOwnerFunctionCallWithAmpersandInCallable */ + do_something($a, /* testParensOwnerArrowFn */ fn($b) => $a & $b, $c), +); + +/* testParensOwnerListWithRefVars */ +list(&$a, &$b) = $array; + +/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */ +$obj->static((CONST_A&CONST_B)|CONST_C | $var); + +/* testParensNoOwnerFunctionCallWithDNFLookALikeNamedParamPlain */ +callMe(label: false); + +/* testParensNoOwnerFunctionCallWithDNFLookALikeNamedParamUnion */ +callMe(label: CONST_A | CONST_B); + +/* testParensNoOwnerFunctionCallWithDNFLookALikeNamedParamIntersect */ +callMe(label: CONST_A & CONST_B); + +/* testSwitchControlStructureCondition */ +switch (CONST_A | CONST_B) { + /* testFunctionCallInSwitchCaseCondition */ + case get_bool(): + /* testFunctionCallInSwitchCaseBody */ + \Name\functionInSwitch(); + break; + + default: + /* testFunctionCallInSwitchDefaultBody */ + functionInSwitch(); + break; +} + +/* testIfAlternativeSyntaxCondition */ +if (true): + /* testFunctionCallInIfBody */ + \B\call(); +/* testElseIfAlternativeSyntaxCondition */ +elseif (10): + /* testFunctionCallInElseIfBody */ + C\call(); +endif; + +gotolabel: + /* testFunctionCallInGotoBody */ + \doSomething(); + + +/* + * DNF parentheses. + */ + +abstract class DNFTypes { + /* testDNFTypeOOConstUnqualifiedClasses */ + public const (A&B)|D UNQUALIFIED = new Foo; + + /* testDNFTypeOOConstReverseModifierOrder */ + protected final const int|(Foo&Bar)|float MODIFIERS_REVERSED /* testParensNoOwnerOOConstDefaultValue */ = (E_WARNING & E_NOTICE) | E_DEPRECATED; + + const + /* testDNFTypeOOConstMulti1 */ + (A&B) | + /* testDNFTypeOOConstMulti2 */ + (C&D) | // phpcs:ignore Stnd.Cat.Sniff + /* testDNFTypeOOConstMulti3 */ + (Y&D) + | null MULTI_DNF = null; + + /* testDNFTypeOOConstNamespaceRelative */ + final protected const (namespace\Sub\NameA&namespace\Sub\NameB)|namespace\Sub\NameC NAMESPACE_RELATIVE = new namespace\Sub\NameB; + + /* testDNFTypeOOConstPartiallyQualified */ + const Partially\Qualified\NameC|(Partially\Qualified\NameA&Partially\Qualified\NameB) PARTIALLY_QUALIFIED = new Partially\Qualified\NameA; + + /* testDNFTypeOOConstFullyQualified */ + const (\Fully\Qualified\NameA&\Fully\Qualified\NameB)|\Fully\Qualified\NameC FULLY_QUALIFIED = new \Fully\Qualified\NameB(); + + /* testDNFTypePropertyUnqualifiedClasses */ + public static (Foo&Bar)|array $obj; + + /* testDNFTypePropertyReverseModifierOrder */ + static protected string|(A&B)|int $dnf /* testParensNoOwnerPropertyDefaultValue1 */ = ( E_WARNING & E_NOTICE ) | /* testParensNoOwnerPropertyDefaultValue2 */ (E_ALL & E_DEPRECATED); + + private + /* testDNFTypePropertyMultiNamespaceRelative */ + (namespace\Sub\NameA&namespace\Sub\NameB) | + /* testDNFTypePropertyMultiPartiallyQualified */ + (Partially\Qualified\NameA&Partially\Qualified\NameB) | // phpcs:ignore Stnd.Cat.Sniff + false + /* testDNFTypePropertyMultiFullyQualified */ + | (\Fully\Qualified\NameA&\Fully\Qualified\NameB) $multiDnf; + + /* testDNFTypePropertyWithReadOnlyKeyword1 */ + protected readonly (A&B) | /* testDNFTypePropertyWithReadOnlyKeyword2 */ (C&D) $readonly; + + /* testDNFTypePropertyWithStaticAndReadOnlyKeywords */ + static readonly (A&B&C)|array $staticReadonly; + + /* testDNFTypePropertyWithOnlyStaticKeyword */ + static (A&B&C)|true $onlyStaticModified; + + public function paramTypes( + /* testDNFTypeParam1WithAttribute */ + #[MyAttribute] + (\Foo&Bar)|int|float $paramA /* testParensNoOwnerParamDefaultValue */ = SOMETHING | (CONSTANT_A & CONSTANT_B), + + /* testDNFTypeParam2 */ + (Foo&\Bar) /* testDNFTypeParam3 */ |(Baz&Fop) &...$paramB, + ) { + /* testParensNoOwnerInReturnValue1 */ + return ( + /* testParensNoOwnerInReturnValue2 */ + ($a1 & $b1) | + /* testParensNoOwnerInReturnValue3 */ + ($a2 & $b2) + ) + $c; + } + + public function identifierNames( + /* testDNFTypeParamNamespaceRelative */ + (namespace\Sub\NameA&namespace\Sub\NameB)|false $paramA, + /* testDNFTypeParamPartiallyQualified */ + Partially\Qualified\NameC|(Partially\Qualified\NameA&Partially\Qualified\NameB) $paramB, + /* testDNFTypeParamFullyQualified */ + name|(\Fully\Qualified\NameA&\Fully\Qualified\NameB) $paramC, + ) {} + + public function __construct( + /* testDNFTypeConstructorPropertyPromotion1 */ + public (A&B)| /* testDNFTypeConstructorPropertyPromotion2 */ (A&D) $property + ) {} + + public function returnType()/* testDNFTypeReturnType1 */ : A|(B&D)|/* testDNFTypeReturnType2 */(B&W)|null {} + + abstract public function abstractMethod(): /* testDNFTypeAbstractMethodReturnType1 */ (X&Y) /* testDNFTypeAbstractMethodReturnType2 */ |(W&Z); + + public function identifierNamesReturnRelative( + ) : /* testDNFTypeReturnTypeNamespaceRelative */ (namespace\Sub\NameA&namespace\Sub\NameB)|namespace\Sub\NameC {} + + public function identifierNamesReturnPQ( + ) : /* testDNFTypeReturnPartiallyQualified */Partially\Qualified\NameA|(Partially\Qualified\NameB&Partially\Qualified\NameC) {} + + // Illegal type: segments which are strict subsets of others are disallowed, but that's not the concern of the tokenizer. + public function identifierNamesReturnFQ( + ) /* testDNFTypeReturnFullyQualified */ : (\Fully\Qualified\NameA&\Fully\Qualified\NameB)|\Fully\Qualified\NameB {} +} + +function globalFunctionWithSpreadAndReference( + /* testDNFTypeWithReference */ + float|(B&A) &$paramA, + /* testDNFTypeWithSpreadOperator */ + string|(B&D) ...$paramB +) {} + + +$closureWithParamType = function ( /* testDNFTypeClosureParamIllegalNullable */ ?(A&B)|bool $string) {}; + +/* testParensOwnerClosureAmpersandInDefaultValue */ +$closureWithReturnType = function ($string = NONSENSE & FAKE) /* testDNFTypeClosureReturn */ : (\Package\MyA&PackageB)|null {}; + +$closureWithUseAndReturnType = function ($foo) use ($a) /* testDNFTypeClosureWithUseReturn */ : null|(Foo&\Bar)|false {}; + +/* testParensOwnerArrowDNFUsedWithin */ +$arrowWithParamType = fn ( + /* testDNFTypeArrowParam */ + int|(A&B&C)|array $param, + /* testParensNoOwnerAmpersandInDefaultValue */ ?int $int = (CONSTA & CONSTB )| CONST_C +) + /* testParensNoOwnerInArrowReturnExpression */ + => ($param & $foo ) | $int; + +$arrowWithReturnType = fn ($param) : /* testDNFTypeArrowReturnType */ int|(A&B) => $param * 10; + +$arrowWithParamReturnByRef = fn &( + /* testDNFTypeArrowParamWithReturnByRef */ + (A&B)|null $param +) => $param * 10; + +function InvalidSyntaxes( + /* testDNFTypeParamIllegalUnnecessaryParens */ + (A&B) $parensNotNeeded, + + /* testDNFTypeParamIllegalIntersectUnionReversed */ + A&(B|D) $onlyIntersectAllowedWithinParensAndUnionOutside, + + /* testDNFTypeParamIllegalNestedParens */ + A|(B&(D|W)|null) $nestedParensNotAllowed, +) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.php new file mode 100644 index 000000000..75e1b1dbd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DNFTypesTest.php @@ -0,0 +1,481 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class DNFTypesTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that parentheses when **not** used in a type declaration are correctly tokenized. + * + * @param string $testMarker The comment prefacing the target token. + * @param bool $skipCheckInside Optional. Skip checking correct token type inside the parentheses. + * Use judiciously for combined normal + DNF tests only. + * + * @dataProvider dataNormalParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNormalParentheses($testMarker, $skipCheckInside=false) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS]); + $opener = $tokens[$openPtr]; + + $this->assertSame('(', $opener['content'], 'Content of type open parenthesis is not "("'); + $this->assertSame(T_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_OPEN_PARENTHESIS (code)'); + $this->assertSame('T_OPEN_PARENTHESIS', $opener['type'], 'Token tokenized as '.$opener['type'].', not T_OPEN_PARENTHESIS (type)'); + + $closePtr = $opener['parenthesis_closer']; + $closer = $tokens[$closePtr]; + + $this->assertSame(')', $closer['content'], 'Content of type close parenthesis is not ")"'); + $this->assertSame(T_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_CLOSE_PARENTHESIS (code)'); + $this->assertSame('T_CLOSE_PARENTHESIS', $closer['type'], 'Token tokenized as '.$closer['type'].', not T_CLOSE_PARENTHESIS (type)'); + + if ($skipCheckInside === false) { + for ($i = ($openPtr + 1); $i < $closePtr; $i++) { + // If there are ampersands, make sure these are tokenized as bitwise and. + if ($tokens[$i]['content'] === '&') { + $this->assertSame(T_BITWISE_AND, $tokens[$i]['code'], 'Token tokenized as '.$tokens[$i]['type'].', not T_BITWISE_AND (code)'); + $this->assertSame('T_BITWISE_AND', $tokens[$i]['type'], 'Token tokenized as '.$tokens[$i]['type'].', not T_BITWISE_AND (type)'); + } + + // If there are pipes, make sure these are tokenized as bitwise or. + if ($tokens[$i]['content'] === '|') { + $this->assertSame(T_BITWISE_OR, $tokens[$i]['code'], 'Token tokenized as '.$tokens[$i]['type'].', not T_BITWISE_OR (code)'); + $this->assertSame('T_BITWISE_OR', $tokens[$i]['type'], 'Token tokenized as '.$tokens[$i]['type'].', not T_BITWISE_OR (type)'); + } + } + } + + $before = $this->phpcsFile->findPrevious(Tokens::$emptyTokens, ($openPtr - 1), null, true); + if ($before !== false && $tokens[$before]['content'] === '|') { + $this->assertSame( + T_BITWISE_OR, + $tokens[$before]['code'], + 'Token before tokenized as '.$tokens[$before]['type'].', not T_BITWISE_OR (code)' + ); + $this->assertSame( + 'T_BITWISE_OR', + $tokens[$before]['type'], + 'Token before tokenized as '.$tokens[$before]['type'].', not T_BITWISE_OR (type)' + ); + } + + $after = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($closePtr + 1), null, true); + if ($after !== false && $tokens[$after]['content'] === '|') { + $this->assertSame( + T_BITWISE_OR, + $tokens[$after]['code'], + 'Token after tokenized as '.$tokens[$after]['type'].', not T_BITWISE_OR (code)' + ); + $this->assertSame( + 'T_BITWISE_OR', + $tokens[$after]['type'], + 'Token after tokenized as '.$tokens[$after]['type'].', not T_BITWISE_OR (type)' + ); + } + + }//end testNormalParentheses() + + + /** + * Data provider. + * + * @see testNormalParentheses() + * + * @return array> + */ + public static function dataNormalParentheses() + { + // "Owner" offsets are relative to the open parenthesis. + return [ + 'parens without owner' => [ + 'testMarker' => '/* testParensNoOwner */', + ], + 'parens without owner in ternary then' => [ + 'testMarker' => '/* testParensNoOwnerInTernary */', + ], + 'parens without owner in short ternary' => [ + 'testMarker' => '/* testParensNoOwnerInShortTernary */', + ], + 'parens with owner: function; & in default value' => [ + 'testMarker' => '/* testParensOwnerFunctionAmpersandInDefaultValue */', + ], + 'parens with owner: closure; param declared by & ref' => [ + 'testMarker' => '/* testParensOwnerClosureAmpersandParamRef */', + ], + 'parens with owner: if' => [ + 'testMarker' => '/* testParensOwnerIf */', + ], + 'parens without owner in if condition' => [ + 'testMarker' => '/* testParensNoOwnerInIfCondition */', + ], + 'parens with owner: for' => [ + 'testMarker' => '/* testParensOwnerFor */', + ], + 'parens without owner in for condition' => [ + 'testMarker' => '/* testParensNoOwnerInForCondition */', + ], + 'parens with owner: match' => [ + 'testMarker' => '/* testParensOwnerMatch */', + ], + 'parens with owner: array' => [ + 'testMarker' => '/* testParensOwnerArray */', + ], + 'parens without owner in array; function call with & in callable' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallWithAmpersandInCallable */', + ], + 'parens with owner: fn; & in return value' => [ + 'testMarker' => '/* testParensOwnerArrowFn */', + ], + 'parens with owner: list with reference vars' => [ + 'testMarker' => '/* testParensOwnerListWithRefVars */', + ], + 'parens without owner, function call with DNF look-a-like param' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */', + ], + 'parens without owner, function call, named param' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallWithDNFLookALikeNamedParamPlain */', + ], + 'parens without owner, function call, named param + bitwise or' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallWithDNFLookALikeNamedParamUnion */', + ], + 'parens without owner, function call, named param + bitwise and' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallWithDNFLookALikeNamedParamIntersect */', + ], + + 'parens without owner in OO const default value' => [ + 'testMarker' => '/* testParensNoOwnerOOConstDefaultValue */', + ], + 'parens without owner in property default 1' => [ + 'testMarker' => '/* testParensNoOwnerPropertyDefaultValue1 */', + ], + 'parens without owner in property default 2' => [ + 'testMarker' => '/* testParensNoOwnerPropertyDefaultValue2 */', + ], + 'parens without owner in param default value' => [ + 'testMarker' => '/* testParensNoOwnerParamDefaultValue */', + ], + 'parens without owner in return statement 1' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue1 */', + ], + 'parens without owner in return statement 2' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue2 */', + ], + 'parens without owner in return statement 3' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue3 */', + ], + 'parens with owner: closure; & in default value' => [ + 'testMarker' => '/* testParensOwnerClosureAmpersandInDefaultValue */', + ], + 'parens with owner: fn; dnf used within' => [ + 'testMarker' => '/* testParensOwnerArrowDNFUsedWithin */', + 'skipCheckInside' => true, + ], + 'parens without owner: default value for param in arrow function' => [ + 'testMarker' => '/* testParensNoOwnerAmpersandInDefaultValue */', + ], + 'parens without owner in arrow function return expression' => [ + 'testMarker' => '/* testParensNoOwnerInArrowReturnExpression */', + ], + 'parens with owner: switch condition' => [ + 'testMarker' => '/* testSwitchControlStructureCondition */', + ], + 'parens without owner in switch-case condition' => [ + 'testMarker' => '/* testFunctionCallInSwitchCaseCondition */', + ], + 'parens without owner in switch-case body' => [ + 'testMarker' => '/* testFunctionCallInSwitchCaseBody */', + ], + 'parens without owner in switch-default body' => [ + 'testMarker' => '/* testFunctionCallInSwitchDefaultBody */', + ], + 'parens with owner: if condition, alternative syntax' => [ + 'testMarker' => '/* testIfAlternativeSyntaxCondition */', + ], + 'parens without owner in if body, alternative syntax' => [ + 'testMarker' => '/* testFunctionCallInIfBody */', + ], + 'parens with owner: elseif condition, alternative syntax' => [ + 'testMarker' => '/* testElseIfAlternativeSyntaxCondition */', + ], + 'parens without owner in elseif body, alternative syntax' => [ + 'testMarker' => '/* testFunctionCallInElseIfBody */', + ], + 'parens without owner in goto body' => [ + 'testMarker' => '/* testFunctionCallInGotoBody */', + ], + ]; + + }//end dataNormalParentheses() + + + /** + * Test that parentheses when used in a DNF type declaration are correctly tokenized. + * + * Includes verifying that: + * - the tokens between the parentheses all have a "nested_parenthesis" key. + * - all ampersands between the parentheses are tokenized as T_TYPE_INTERSECTION. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataDNFTypeParentheses + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testDNFTypeParentheses($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS]); + $opener = $tokens[$openPtr]; + + $this->assertSame('(', $opener['content'], 'Content of type open parenthesis is not "("'); + $this->assertSame(T_TYPE_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_TYPE_OPEN_PARENTHESIS (code)'); + $this->assertSame('T_TYPE_OPEN_PARENTHESIS', $opener['type'], 'Token tokenized as '.$opener['type'].', not T_TYPE_OPEN_PARENTHESIS (type)'); + + $closePtr = $opener['parenthesis_closer']; + $closer = $tokens[$closePtr]; + + $this->assertSame(')', $closer['content'], 'Content of type close parenthesis is not ")"'); + $this->assertSame(T_TYPE_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_TYPE_CLOSE_PARENTHESIS (code)'); + $this->assertSame('T_TYPE_CLOSE_PARENTHESIS', $closer['type'], 'Token tokenized as '.$closer['type'].', not T_TYPE_CLOSE_PARENTHESIS (type)'); + + $intersectionCount = 0; + for ($i = ($openPtr + 1); $i < $closePtr; $i++) { + if ($tokens[$i]['content'] === '&') { + $this->assertSame( + T_TYPE_INTERSECTION, + $tokens[$i]['code'], + 'Token tokenized as '.$tokens[$i]['type'].', not T_TYPE_INTERSECTION (code)' + ); + $this->assertSame( + 'T_TYPE_INTERSECTION', + $tokens[$i]['type'], + 'Token tokenized as '.$tokens[$i]['type'].', not T_TYPE_INTERSECTION (type)' + ); + ++$intersectionCount; + } + + // Not valid, but that's irrelevant for the tokenization. + if ($tokens[$i]['content'] === '|') { + $this->assertSame(T_TYPE_UNION, $tokens[$i]['code'], 'Token tokenized as '.$tokens[$i]['type'].', not T_TYPE_UNION (code)'); + $this->assertSame('T_TYPE_UNION', $tokens[$i]['type'], 'Token tokenized as '.$tokens[$i]['type'].', not T_TYPE_UNION (type)'); + + // For the purposes of this test, presume it was intended as an intersection. + ++$intersectionCount; + } + }//end for + + $this->assertGreaterThanOrEqual(1, $intersectionCount, 'Did not find an intersection "&" between the DNF type parentheses'); + + $before = $this->phpcsFile->findPrevious(Tokens::$emptyTokens, ($openPtr - 1), null, true); + if ($before !== false && $tokens[$before]['content'] === '|') { + $this->assertSame( + T_TYPE_UNION, + $tokens[$before]['code'], + 'Token before tokenized as '.$tokens[$before]['type'].', not T_TYPE_UNION (code)' + ); + $this->assertSame( + 'T_TYPE_UNION', + $tokens[$before]['type'], + 'Token before tokenized as '.$tokens[$before]['type'].', not T_TYPE_UNION (type)' + ); + } + + // Invalid, but that's not relevant for the tokenization. + if ($before !== false && $tokens[$before]['content'] === '?') { + $this->assertSame( + T_NULLABLE, + $tokens[$before]['code'], + 'Token before tokenized as '.$tokens[$before]['type'].', not T_NULLABLE (code)' + ); + $this->assertSame( + 'T_NULLABLE', + $tokens[$before]['type'], + 'Token before tokenized as '.$tokens[$before]['type'].', not T_NULLABLE (type)' + ); + } + + $after = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($closePtr + 1), null, true); + if ($after !== false && $tokens[$after]['content'] === '|') { + $this->assertSame( + T_TYPE_UNION, + $tokens[$after]['code'], + 'Token after tokenized as '.$tokens[$after]['type'].', not T_TYPE_UNION (code)' + ); + $this->assertSame( + 'T_TYPE_UNION', + $tokens[$after]['type'], + 'Token after tokenized as '.$tokens[$after]['type'].', not T_TYPE_UNION (type)' + ); + } + + }//end testDNFTypeParentheses() + + + /** + * Data provider. + * + * @see testDNFTypeParentheses() + * + * @return array> + */ + public static function dataDNFTypeParentheses() + { + return [ + 'OO const type: unqualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstUnqualifiedClasses */', + ], + 'OO const type: modifiers in reverse order' => [ + 'testMarker' => '/* testDNFTypeOOConstReverseModifierOrder */', + ], + 'OO const type: multi-dnf part 1' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti1 */', + ], + 'OO const type: multi-dnf part 2' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti2 */', + ], + 'OO const type: multi-dnf part 3' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti3 */', + ], + 'OO const type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeOOConstNamespaceRelative */', + ], + 'OO const type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstPartiallyQualified */', + ], + 'OO const type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstFullyQualified */', + ], + + 'OO property type: unqualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyUnqualifiedClasses */', + ], + 'OO property type: modifiers in reverse order' => [ + 'testMarker' => '/* testDNFTypePropertyReverseModifierOrder */', + ], + 'OO property type: multi-dnf namespace relative classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiNamespaceRelative */', + ], + 'OO property type: multi-dnf partially qualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiPartiallyQualified */', + ], + 'OO property type: multi-dnf fully qualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiFullyQualified */', + ], + + 'OO property type: multi-dnf with readonly keyword 1' => [ + 'testMarker' => '/* testDNFTypePropertyWithReadOnlyKeyword1 */', + ], + 'OO property type: multi-dnf with readonly keyword 2' => [ + 'testMarker' => '/* testDNFTypePropertyWithReadOnlyKeyword2 */', + ], + 'OO property type: with static and readonly keywords' => [ + 'testMarker' => '/* testDNFTypePropertyWithStaticAndReadOnlyKeywords */', + ], + 'OO property type: with only static keyword' => [ + 'testMarker' => '/* testDNFTypePropertyWithOnlyStaticKeyword */', + ], + 'OO method param type: first param' => [ + 'testMarker' => '/* testDNFTypeParam1WithAttribute */', + ], + 'OO method param type: second param, first DNF' => [ + 'testMarker' => '/* testDNFTypeParam2 */', + ], + 'OO method param type: second param, second DNF' => [ + 'testMarker' => '/* testDNFTypeParam3 */', + ], + 'OO method param type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeParamNamespaceRelative */', + ], + 'OO method param type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeParamPartiallyQualified */', + ], + 'OO method param type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeParamFullyQualified */', + ], + 'Constructor property promotion with multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeConstructorPropertyPromotion1 */', + ], + 'Constructor property promotion with multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeConstructorPropertyPromotion2 */', + ], + 'OO method return type: multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeReturnType1 */', + ], + 'OO method return type: multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeReturnType2 */', + ], + 'OO abstract method return type: multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeAbstractMethodReturnType1 */', + ], + 'OO abstract method return type: multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeAbstractMethodReturnType2 */', + ], + 'OO method return type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeReturnTypeNamespaceRelative */', + ], + 'OO method return type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeReturnPartiallyQualified */', + ], + 'OO method return type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeReturnFullyQualified */', + ], + 'function param type: with reference' => [ + 'testMarker' => '/* testDNFTypeWithReference */', + ], + 'function param type: with spread' => [ + 'testMarker' => '/* testDNFTypeWithSpreadOperator */', + ], + 'closure param type: with illegal nullable' => [ + 'testMarker' => '/* testDNFTypeClosureParamIllegalNullable */', + ], + 'closure return type' => [ + 'testMarker' => '/* testDNFTypeClosureReturn */', + ], + 'closure with use return type' => [ + 'testMarker' => '/* testDNFTypeClosureWithUseReturn */', + ], + + 'arrow function param type' => [ + 'testMarker' => '/* testDNFTypeArrowParam */', + ], + 'arrow function return type' => [ + 'testMarker' => '/* testDNFTypeArrowReturnType */', + ], + 'arrow function param type with return by ref' => [ + 'testMarker' => '/* testDNFTypeArrowParamWithReturnByRef */', + ], + + 'illegal syntax: unnecessary parentheses (no union)' => [ + 'testMarker' => '/* testDNFTypeParamIllegalUnnecessaryParens */', + ], + 'illegal syntax: union within parentheses, intersect outside' => [ + 'testMarker' => '/* testDNFTypeParamIllegalIntersectUnionReversed */', + ], + 'illegal syntax: nested parentheses' => [ + 'testMarker' => '/* testDNFTypeParamIllegalNestedParens */', + ], + ]; + + }//end dataDNFTypeParentheses() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.inc new file mode 100644 index 000000000..648149d2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.inc @@ -0,0 +1,203 @@ + 1, + 2 => 2, + /* testSimpleMatchDefault */ + default => 'default', + }; +} + +function switchWithDefault($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefault */ + default: + return 'default'; + } +} + +function switchWithDefaultAndCurlies($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefaultWithCurlies */ + default: { + return 'default'; + } + } +} + +function matchWithDefaultInSwitch() { + switch ($something) { + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase1 */ + default => 'default', + }; + continue; + + case 'bar' : + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase2 */ + default => 'default', + }; + + /* testSwitchDefault */ + default; + echo 'something', match ($i) { + 1, => 1, + /* testMatchDefaultNestedInSwitchDefault */ + default, => 'default', + }; + break; + } +} + +function switchWithDefaultInMatch() { + $x = match ($y) { + 5, 8 => function($z) { + switch($z) { + case 'a'; + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $var = [1, 2, 3]; + return 'default1'; + } + }, + /* testMatchDefault */ + default => function($z) { + switch($z) { + case 'a': + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default: + $i = callMe($a, $b); + return 'default2'; + } + } + }; +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testClassConstantAsShortArrayKey */ + SomeClass::DEFAULT => 1, + /* testClassPropertyAsShortArrayKey */ + SomeClass->DEFAULT => 1, + /* testNamespacedConstantAsShortArrayKey */ + // Intentional parse error PHP < 8.0. Reserved keyword used as namespaced constant. + SomeNamespace\DEFAULT => 1, + /* testFQNGlobalConstantAsShortArrayKey */ + // Intentional parse error in PHP < 8.0. Reserved keyword used as global constant. + \DEFAULT => 1, + ]; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testClassConstantAsLongArrayKey */ + SomeClass::DEFAULT => 1, + ); +} + +function yieldWithConstantKey() { + /* testClassConstantAsYieldKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKey */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ), + }, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKey */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ], + }, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testClassConstantAsLongArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInLongArray */ + DEFAULT => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testClassConstantAsShortArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInShortArray */ + DEFAULT => 'foo' + }, + ]; +} + +function switchWithConstantNonDefault($i) { + switch ($i) { + /* testClassConstantInSwitchCase */ + case SomeClass::DEFAULT: + return 1; + + /* testClassPropertyInSwitchCase */ + case SomeClass->DEFAULT: + return 2; + + /* testNamespacedConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as constant. + case SomeNamespace\DEFAULT: + return 2; + + /* testNamespaceRelativeConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as global constant. + case namespace\DEFAULT: + return 2; + } +} + +class Foo { + /* testClassConstant */ + const DEFAULT = 'foo'; + + /* testMethodDeclaration */ + public function default() {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.php new file mode 100644 index 000000000..c398aa6cb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DefaultKeywordTest.php @@ -0,0 +1,255 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class DefaultKeywordTest extends AbstractTokenizerTestCase +{ + + + /** + * Test the retokenization of the `default` keyword for match structure to `T_MATCH_DEFAULT`. + * + * Note: Cases and default structures within a match structure do *NOT* get case/default scope + * conditions, in contrast to case and default structures in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchDefault + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMatchDefault($testMarker, $testContent='default') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)'); + $this->assertSame('T_MATCH_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (type)'); + + }//end testMatchDefault() + + + /** + * Data provider. + * + * @see testMatchDefault() + * + * @return array> + */ + public static function dataMatchDefault() + { + return [ + 'simple_match_default' => [ + 'testMarker' => '/* testSimpleMatchDefault */', + ], + 'match_default_in_switch_case_1' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchCase1 */', + ], + 'match_default_in_switch_case_2' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchCase2 */', + ], + 'match_default_in_switch_default' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchDefault */', + ], + 'match_default_containing_switch' => [ + 'testMarker' => '/* testMatchDefault */', + ], + + 'match_default_with_nested_long_array_and_default_key' => [ + 'testMarker' => '/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_long_array_and_default_key_2' => [ + 'testMarker' => '/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key' => [ + 'testMarker' => '/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key_2' => [ + 'testMarker' => '/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */', + 'testContent' => 'DEFAULT', + ], + 'match_default_in_long_array' => [ + 'testMarker' => '/* testMatchDefaultNestedInLongArray */', + 'testContent' => 'DEFAULT', + ], + 'match_default_in_short_array' => [ + 'testMarker' => '/* testMatchDefaultNestedInShortArray */', + 'testContent' => 'DEFAULT', + ], + ]; + + }//end dataMatchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_DEFAULT` tokens in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataSwitchDefault + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testSwitchDefault($testMarker, $testContent='default') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (code)'); + $this->assertSame('T_DEFAULT', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (type)'); + + }//end testSwitchDefault() + + + /** + * Data provider. + * + * @see testSwitchDefault() + * + * @return array> + */ + public static function dataSwitchDefault() + { + return [ + 'simple_switch_default' => [ + 'testMarker' => '/* testSimpleSwitchDefault */', + ], + 'simple_switch_default_with_curlies' => [ + 'testMarker' => '/* testSimpleSwitchDefaultWithCurlies */', + ], + 'switch_default_toplevel' => [ + 'testMarker' => '/* testSwitchDefault */', + ], + 'switch_default_nested_in_match_case' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchCase */', + ], + 'switch_default_nested_in_match_default' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchDefault */', + ], + ]; + + }//end dataSwitchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_STRING` tokens with the contents 'default' which aren't in + * actual fact the default keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotDefaultKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testNotDefaultKeyword() + + + /** + * Data provider. + * + * @see testNotDefaultKeyword() + * + * @return array> + */ + public static function dataNotDefaultKeyword() + { + return [ + 'class-constant-as-short-array-key' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKey */', + ], + 'class-property-as-short-array-key' => [ + 'testMarker' => '/* testClassPropertyAsShortArrayKey */', + ], + 'namespaced-constant-as-short-array-key' => [ + 'testMarker' => '/* testNamespacedConstantAsShortArrayKey */', + ], + 'fqn-global-constant-as-short-array-key' => [ + 'testMarker' => '/* testFQNGlobalConstantAsShortArrayKey */', + ], + 'class-constant-as-long-array-key' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKey */', + ], + 'class-constant-as-yield-key' => [ + 'testMarker' => '/* testClassConstantAsYieldKey */', + ], + + 'class-constant-as-long-array-key-nested-in-match' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyNestedInMatch */', + ], + 'class-constant-as-long-array-key-nested-in-match-2' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */', + ], + 'class-constant-as-short-array-key-nested-in-match' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyNestedInMatch */', + ], + 'class-constant-as-short-array-key-nested-in-match-2' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */', + ], + 'class-constant-as-long-array-key-with-nested-match' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyWithNestedMatch */', + ], + 'class-constant-as-short-array-key-with-nested-match' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyWithNestedMatch */', + ], + + 'class-constant-in-switch-case' => [ + 'testMarker' => '/* testClassConstantInSwitchCase */', + ], + 'class-property-in-switch-case' => [ + 'testMarker' => '/* testClassPropertyInSwitchCase */', + ], + 'namespaced-constant-in-switch-case' => [ + 'testMarker' => '/* testNamespacedConstantInSwitchCase */', + ], + 'namespace-relative-constant-in-switch-case' => [ + 'testMarker' => '/* testNamespaceRelativeConstantInSwitchCase */', + ], + + 'class-constant-declaration' => [ + 'testMarker' => '/* testClassConstant */', + ], + 'class-method-declaration' => [ + 'testMarker' => '/* testMethodDeclaration */', + 'testContent' => 'default', + ], + ]; + + }//end dataNotDefaultKeyword() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.inc new file mode 100644 index 000000000..b67b06601 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.inc @@ -0,0 +1,281 @@ + 'Zero', + ); +} + +function simpleShortArray($x) { + return [ + /* testShortArrayArrowSimple */ + 0 => 'Zero', + ]; +} + +function simpleLongList($x) { + list( + /* testLongListArrowSimple */ + 0 => $a, + ) = $x; +} + +function simpleShortList($x) { + [ + /* testShortListArrowSimple */ + 0 => $a, + ] = $x; +} + +function simpleYield($x) { + $i = 0; + foreach (explode("\n", $x) as $line) { + /* testYieldArrowSimple */ + yield ++$i => $line; + } +} + +function simpleForeach($x) { + /* testForeachArrowSimple */ + foreach ($x as $k => $value) {} +} + +function simpleMatch($x) { + return match ($x) { + /* testMatchArrowSimpleSingleCase */ + 0 => 'Zero', + /* testMatchArrowSimpleMultiCase */ + 2, 4, 6 => 'Zero', + /* testMatchArrowSimpleSingleCaseWithTrailingComma */ + 1, => 'Zero', + /* testMatchArrowSimpleMultiCaseWithTrailingComma */ + 3, 5, => 'Zero', + }; +} + +function simpleArrowFunction($y) { + /* testFnArrowSimple */ + return fn ($y) => callMe($y); +} + +function matchNestedInMatch() { + $x = match ($y) { + /* testMatchArrowNestedMatchOuter */ + default, => match ($z) { + /* testMatchArrowNestedMatchInner */ + 1 => 1 + }, + }; +} + +function matchNestedInLongArrayValue() { + $array = array( + /* testLongArrayArrowWithNestedMatchValue1 */ + 'a' => match ($test) { + /* testMatchArrowInLongArrayValue1 */ + 1 => 'a', + /* testMatchArrowInLongArrayValue2 */ + 2 => 'b' + }, + /* testLongArrayArrowWithNestedMatchValue2 */ + $i => match ($test) { + /* testMatchArrowInLongArrayValue3 */ + 1 => 'a', + }, + ); +} + +function matchNestedInShortArrayValue() { + $array = [ + /* testShortArrayArrowWithNestedMatchValue1 */ + 'a' => match ($test) { + /* testMatchArrowInShortArrayValue1 */ + 1 => 'a', + /* testMatchArrowInShortArrayValue2 */ + 2 => 'b' + }, + /* testShortArrayArrowWithNestedMatchValue2 */ + $i => match ($test) { + /* testMatchArrowInShortArrayValue3 */ + 1 => 'a', + }, + ]; +} + +function matchNestedInLongArrayKey() { + $array = array( + match ($test) { /* testMatchArrowInLongArrayKey1 */ 1 => 'a', /* testMatchArrowInLongArrayKey2 */ 2 => 'b' } + /* testLongArrayArrowWithMatchKey */ + => 'dynamic keys, woho!', + ); +} + +function matchNestedInShortArrayKey() { + $array = [ + match ($test) { /* testMatchArrowInShortArrayKey1 */ 1 => 'a', /* testMatchArrowInShortArrayKey2 */ 2 => 'b' } + /* testShortArrayArrowWithMatchKey */ + => 'dynamic keys, woho!', + ]; +} + +function arraysNestedInMatch() { + $matcher = match ($x) { + /* testMatchArrowWithLongArrayBodyWithKeys */ + 0 => array( + /* testLongArrayArrowInMatchBody1 */ + 0 => 1, + /* testLongArrayArrowInMatchBody2 */ + 'a' => 2, + /* testLongArrayArrowInMatchBody3 */ + 'b' => 3 + ), + /* testMatchArrowWithShortArrayBodyWithoutKeys */ + 1 => [1, 2, 3], + /* testMatchArrowWithLongArrayBodyWithoutKeys */ + 2 => array( 1, [1, 2, 3], 2, 3), + /* testMatchArrowWithShortArrayBodyWithKeys */ + 3 => [ + /* testShortArrayArrowInMatchBody1 */ + 0 => 1, + /* testShortArrayArrowInMatchBody2 */ + 'a' => array(1, 2, 3), + /* testShortArrayArrowInMatchBody3 */ + 'b' => 2, + 3 + ], + /* testShortArrayArrowinMatchCase1 */ + [4 => 'a', /* testShortArrayArrowinMatchCase2 */ 5 => 6] + /* testMatchArrowWithShortArrayWithKeysAsCase */ + => 'match with array as case value', + /* testShortArrayArrowinMatchCase3 */ + [4 => 'a'], /* testLongArrayArrowinMatchCase4 */ array(5 => 6), + /* testMatchArrowWithMultipleArraysWithKeysAsCase */ + => 'match with multiple arrays as case value', + }; +} + +function matchNestedInArrowFunction($x) { + /* testFnArrowWithMatchInValue */ + $fn = fn($x) => match(true) { + /* testMatchArrowInFnBody1 */ + 1, 2, 3, 4, 5 => 'foo', + /* testMatchArrowInFnBody2 */ + default => 'bar', + }; +} + +function arrowFunctionsNestedInMatch($x) { + return match ($x) { + /* testMatchArrowWithFnBody1 */ + 1 => /* testFnArrowInMatchBody1 */ fn($y) => callMe($y), + /* testMatchArrowWithFnBody2 */ + default => /* testFnArrowInMatchBody2 */ fn($y) => callThem($y) + }; +} + +function matchShortArrayMismash() { + $array = [ + match ($test) { + /* testMatchArrowInComplexShortArrayKey1 */ + 1 => [ /* testShortArrayArrowInComplexMatchValueinShortArrayKey */ 1 => 'a'], + /* testMatchArrowInComplexShortArrayKey2 */ + 2 => 'b' + /* testShortArrayArrowInComplexMatchArrayMismash */ + } => match ($test) { + /* testMatchArrowInComplexShortArrayValue1 */ + 1 => [ /* testShortArrayArrowInComplexMatchValueinShortArrayValue */ 1 => 'a'], + /* testMatchArrowInComplexShortArrayValue2 */ + 2 => /* testFnArrowInComplexMatchValueInShortArrayValue */ fn($y) => callMe($y) + }, + ]; +} + + +function longListInMatch($x, $y) { + return match($x) { + /* testMatchArrowWithLongListBody */ + 1 => list('a' => $a, /* testLongListArrowInMatchBody */ 'b' => $b, 'c' => list('d' => $c)) = $y, + /* testLongListArrowInMatchCase */ + list('a' => $a, 'b' => $b) = $y /* testMatchArrowWithLongListInCase */ => 'something' + }; +} + +function shortListInMatch($x, $y) { + return match($x) { + /* testMatchArrowWithShortListBody */ + 1 => ['a' => $a, 'b' => $b, 'c' => /* testShortListArrowInMatchBody */ ['d' => $c]] = $y, + /* testShortListArrowInMatchCase */ + ['a' => $a, 'b' => $b] = $y /* testMatchArrowWithShortListInCase */ => 'something' + }; +} + +function matchInLongList() { + /* testMatchArrowInLongListKey */ + list(match($x) {1 => 1, 2 => 2} /* testLongListArrowWithMatchInKey */ => $a) = $array; +} + +function matchInShortList() { + /* testMatchArrowInShortListKey */ + [match($x) {1 => 1, 2 => 2} /* testShortListArrowWithMatchInKey */ => $a] = $array; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testLongArrayArrowWithClassConstantKey */ + SomeClass::DEFAULT => 1, + ); +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testShortArrayArrowWithClassConstantKey */ + SomeClass::DEFAULT => 1, + ]; +} + +function yieldWithConstantKey() { + /* testYieldArrowWithClassConstantKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchArrowWithNestedLongArrayWithClassConstantKey */ + default => array( + /* testLongArrayArrowWithClassConstantKeyNestedInMatch */ + SomeClass::DEFAULT => 1, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchArrowWithNestedShortArrayWithClassConstantKey */ + default => [ + /* testShortArrayArrowWithClassConstantKeyNestedInMatch */ + SomeClass::DEFAULT => 1, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testLongArrayArrowWithClassConstantKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchArrowNestedInLongArrayWithClassConstantKey */ + default => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testShortArrayArrowWithClassConstantKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchArrowNestedInShortArrayWithClassConstantKey */ + default => 'foo' + }, + ]; +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.php new file mode 100644 index 000000000..5258d9c16 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleArrowTest.php @@ -0,0 +1,237 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class DoubleArrowTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that "normal" double arrows are correctly tokenized as `T_DOUBLE_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataDoubleArrow + * @coversNothing + * + * @return void + */ + public function testDoubleArrow($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_DOUBLE_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DOUBLE_ARROW (code)'); + $this->assertSame('T_DOUBLE_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_DOUBLE_ARROW (type)'); + + }//end testDoubleArrow() + + + /** + * Data provider. + * + * @see testDoubleArrow() + * + * @return array> + */ + public static function dataDoubleArrow() + { + return [ + 'simple_long_array' => ['/* testLongArrayArrowSimple */'], + 'simple_short_array' => ['/* testShortArrayArrowSimple */'], + 'simple_long_list' => ['/* testLongListArrowSimple */'], + 'simple_short_list' => ['/* testShortListArrowSimple */'], + 'simple_yield' => ['/* testYieldArrowSimple */'], + 'simple_foreach' => ['/* testForeachArrowSimple */'], + + 'long_array_with_match_value_1' => ['/* testLongArrayArrowWithNestedMatchValue1 */'], + 'long_array_with_match_value_2' => ['/* testLongArrayArrowWithNestedMatchValue2 */'], + 'short_array_with_match_value_1' => ['/* testShortArrayArrowWithNestedMatchValue1 */'], + 'short_array_with_match_value_2' => ['/* testShortArrayArrowWithNestedMatchValue2 */'], + + 'long_array_with_match_key' => ['/* testLongArrayArrowWithMatchKey */'], + 'short_array_with_match_key' => ['/* testShortArrayArrowWithMatchKey */'], + + 'long_array_in_match_body_1' => ['/* testLongArrayArrowInMatchBody1 */'], + 'long_array_in_match_body_2' => ['/* testLongArrayArrowInMatchBody2 */'], + 'long_array_in_match_body_3' => ['/* testLongArrayArrowInMatchBody3 */'], + 'short_array_in_match_body_1' => ['/* testShortArrayArrowInMatchBody1 */'], + 'short_array_in_match_body_2' => ['/* testShortArrayArrowInMatchBody2 */'], + 'short_array_in_match_body_3' => ['/* testShortArrayArrowInMatchBody3 */'], + + 'short_array_in_match_case_1' => ['/* testShortArrayArrowinMatchCase1 */'], + 'short_array_in_match_case_2' => ['/* testShortArrayArrowinMatchCase2 */'], + 'short_array_in_match_case_3' => ['/* testShortArrayArrowinMatchCase3 */'], + 'long_array_in_match_case_4' => ['/* testLongArrayArrowinMatchCase4 */'], + + 'in_complex_short_array_key_match_value' => ['/* testShortArrayArrowInComplexMatchValueinShortArrayKey */'], + 'in_complex_short_array_toplevel' => ['/* testShortArrayArrowInComplexMatchArrayMismash */'], + 'in_complex_short_array_value_match_value' => ['/* testShortArrayArrowInComplexMatchValueinShortArrayValue */'], + + 'long_list_in_match_body' => ['/* testLongListArrowInMatchBody */'], + 'long_list_in_match_case' => ['/* testLongListArrowInMatchCase */'], + 'short_list_in_match_body' => ['/* testShortListArrowInMatchBody */'], + 'short_list_in_match_case' => ['/* testShortListArrowInMatchCase */'], + 'long_list_with_match_in_key' => ['/* testLongListArrowWithMatchInKey */'], + 'short_list_with_match_in_key' => ['/* testShortListArrowWithMatchInKey */'], + + 'long_array_with_constant_default_in_key' => ['/* testLongArrayArrowWithClassConstantKey */'], + 'short_array_with_constant_default_in_key' => ['/* testShortArrayArrowWithClassConstantKey */'], + 'yield_with_constant_default_in_key' => ['/* testYieldArrowWithClassConstantKey */'], + + 'long_array_with_default_in_key_in_match' => ['/* testLongArrayArrowWithClassConstantKeyNestedInMatch */'], + 'short_array_with_default_in_key_in_match' => ['/* testShortArrayArrowWithClassConstantKeyNestedInMatch */'], + 'long_array_with_default_in_key_with_match' => ['/* testLongArrayArrowWithClassConstantKeyWithNestedMatch */'], + 'short_array_with_default_in_key_with_match' => ['/* testShortArrayArrowWithClassConstantKeyWithNestedMatch */'], + ]; + + }//end dataDoubleArrow() + + + /** + * Test that double arrows in match expressions which are the demarkation between a case and the return value + * are correctly tokenized as `T_MATCH_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataMatchArrow + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testMatchArrow($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_MATCH_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_ARROW (code)'); + $this->assertSame('T_MATCH_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_ARROW (type)'); + + }//end testMatchArrow() + + + /** + * Data provider. + * + * @see testMatchArrow() + * + * @return array> + */ + public static function dataMatchArrow() + { + return [ + 'single_case' => ['/* testMatchArrowSimpleSingleCase */'], + 'multi_case' => ['/* testMatchArrowSimpleMultiCase */'], + 'single_case_with_trailing_comma' => ['/* testMatchArrowSimpleSingleCaseWithTrailingComma */'], + 'multi_case_with_trailing_comma' => ['/* testMatchArrowSimpleMultiCaseWithTrailingComma */'], + 'match_nested_outer' => ['/* testMatchArrowNestedMatchOuter */'], + 'match_nested_inner' => ['/* testMatchArrowNestedMatchInner */'], + + 'in_long_array_value_1' => ['/* testMatchArrowInLongArrayValue1 */'], + 'in_long_array_value_2' => ['/* testMatchArrowInLongArrayValue2 */'], + 'in_long_array_value_3' => ['/* testMatchArrowInLongArrayValue3 */'], + 'in_short_array_value_1' => ['/* testMatchArrowInShortArrayValue1 */'], + 'in_short_array_value_2' => ['/* testMatchArrowInShortArrayValue2 */'], + 'in_short_array_value_3' => ['/* testMatchArrowInShortArrayValue3 */'], + + 'in_long_array_key_1' => ['/* testMatchArrowInLongArrayKey1 */'], + 'in_long_array_key_2' => ['/* testMatchArrowInLongArrayKey2 */'], + 'in_short_array_key_1' => ['/* testMatchArrowInShortArrayKey1 */'], + 'in_short_array_key_2' => ['/* testMatchArrowInShortArrayKey2 */'], + + 'with_long_array_value_with_keys' => ['/* testMatchArrowWithLongArrayBodyWithKeys */'], + 'with_short_array_value_without_keys' => ['/* testMatchArrowWithShortArrayBodyWithoutKeys */'], + 'with_long_array_value_without_keys' => ['/* testMatchArrowWithLongArrayBodyWithoutKeys */'], + 'with_short_array_value_with_keys' => ['/* testMatchArrowWithShortArrayBodyWithKeys */'], + + 'with_short_array_with_keys_as_case' => ['/* testMatchArrowWithShortArrayWithKeysAsCase */'], + 'with_multiple_arrays_with_keys_as_case' => ['/* testMatchArrowWithMultipleArraysWithKeysAsCase */'], + + 'in_fn_body_case' => ['/* testMatchArrowInFnBody1 */'], + 'in_fn_body_default' => ['/* testMatchArrowInFnBody2 */'], + 'with_fn_body_case' => ['/* testMatchArrowWithFnBody1 */'], + 'with_fn_body_default' => ['/* testMatchArrowWithFnBody2 */'], + + 'in_complex_short_array_key_1' => ['/* testMatchArrowInComplexShortArrayKey1 */'], + 'in_complex_short_array_key_2' => ['/* testMatchArrowInComplexShortArrayKey2 */'], + 'in_complex_short_array_value_1' => ['/* testMatchArrowInComplexShortArrayValue1 */'], + 'in_complex_short_array_value_2' => ['/* testMatchArrowInComplexShortArrayValue2 */'], + + 'with_long_list_in_body' => ['/* testMatchArrowWithLongListBody */'], + 'with_long_list_in_case' => ['/* testMatchArrowWithLongListInCase */'], + 'with_short_list_in_body' => ['/* testMatchArrowWithShortListBody */'], + 'with_short_list_in_case' => ['/* testMatchArrowWithShortListInCase */'], + 'in_long_list_key' => ['/* testMatchArrowInLongListKey */'], + 'in_short_list_key' => ['/* testMatchArrowInShortListKey */'], + + 'with_long_array_value_with_default_key' => ['/* testMatchArrowWithNestedLongArrayWithClassConstantKey */'], + 'with_short_array_value_with_default_key' => ['/* testMatchArrowWithNestedShortArrayWithClassConstantKey */'], + 'in_long_array_value_with_default_key' => ['/* testMatchArrowNestedInLongArrayWithClassConstantKey */'], + 'in_short_array_value_with_default_key' => ['/* testMatchArrowNestedInShortArrayWithClassConstantKey */'], + ]; + + }//end dataMatchArrow() + + + /** + * Test that double arrows used as the scope opener for an arrow function + * are correctly tokenized as `T_FN_ARROW`. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataFnArrow + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testFnArrow($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_DOUBLE_ARROW, T_MATCH_ARROW, T_FN_ARROW]); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_FN_ARROW, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_FN_ARROW (code)'); + $this->assertSame('T_FN_ARROW', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_FN_ARROW (type)'); + + }//end testFnArrow() + + + /** + * Data provider. + * + * @see testFnArrow() + * + * @return array> + */ + public static function dataFnArrow() + { + return [ + 'simple_fn' => ['/* testFnArrowSimple */'], + + 'with_match_as_value' => ['/* testFnArrowWithMatchInValue */'], + 'in_match_value_case' => ['/* testFnArrowInMatchBody1 */'], + 'in_match_value_default' => ['/* testFnArrowInMatchBody2 */'], + + 'in_complex_match_value_in_short_array' => ['/* testFnArrowInComplexMatchValueInShortArrayValue */'], + ]; + + }//end dataFnArrow() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.inc new file mode 100644 index 000000000..62535b1e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.inc @@ -0,0 +1,52 @@ +bar"; +/* testProperty2 */ +"{$foo->bar}"; + +/* testMethod1 */ +"{$foo->bar()}"; + +/* testClosure1 */ +"{$foo()}"; + +/* testChain1 */ +"{$foo['bar']->baz()()}"; + +/* testVariableVar1 */ +"${$bar}"; +/* testVariableVar2 */ +"${(foo)}"; +/* testVariableVar3 */ +"${foo->bar}"; + +/* testNested1 */ +"${foo["${bar}"]}"; +/* testNested2 */ +"${foo["${bar['baz']}"]}"; +/* testNested3 */ +"${foo->{$baz}}"; +/* testNested4 */ +"${foo->{${'a'}}}"; +/* testNested5 */ +"${foo->{"${'a'}"}}"; + +/* testParseError */ +"${foo["${bar diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.php new file mode 100644 index 000000000..aa0817a46 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/DoubleQuotedStringTest.php @@ -0,0 +1,144 @@ + + * @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class DoubleQuotedStringTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that double quoted strings contain the complete string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent The expected content of the double quoted string. + * + * @dataProvider dataDoubleQuotedString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testDoubleQuotedString($testMarker, $expectedContent) + { + $tokens = $this->phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, T_DOUBLE_QUOTED_STRING); + $this->assertSame($expectedContent, $tokens[$target]['content']); + + }//end testDoubleQuotedString() + + + /** + * Data provider. + * + * Type reference: + * 1. Directly embedded variables. + * 2. Braces outside the variable. + * 3. Braces after the dollar sign. + * 4. Variable variables and expressions. + * + * @link https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation + * + * @see testDoubleQuotedString() + * + * @return array> + */ + public static function dataDoubleQuotedString() + { + return [ + 'Type 1: simple variable' => [ + 'testMarker' => '/* testSimple1 */', + 'expectedContent' => '"$foo"', + ], + 'Type 2: simple variable' => [ + 'testMarker' => '/* testSimple2 */', + 'expectedContent' => '"{$foo}"', + ], + 'Type 3: simple variable' => [ + 'testMarker' => '/* testSimple3 */', + 'expectedContent' => '"${foo}"', + ], + 'Type 1: array offset' => [ + 'testMarker' => '/* testDIM1 */', + 'expectedContent' => '"$foo[bar]"', + ], + 'Type 2: array offset' => [ + 'testMarker' => '/* testDIM2 */', + 'expectedContent' => '"{$foo[\'bar\']}"', + ], + 'Type 3: array offset' => [ + 'testMarker' => '/* testDIM3 */', + 'expectedContent' => '"${foo[\'bar\']}"', + ], + 'Type 1: object property' => [ + 'testMarker' => '/* testProperty1 */', + 'expectedContent' => '"$foo->bar"', + ], + 'Type 2: object property' => [ + 'testMarker' => '/* testProperty2 */', + 'expectedContent' => '"{$foo->bar}"', + ], + 'Type 2: object method call' => [ + 'testMarker' => '/* testMethod1 */', + 'expectedContent' => '"{$foo->bar()}"', + ], + 'Type 2: closure function call' => [ + 'testMarker' => '/* testClosure1 */', + 'expectedContent' => '"{$foo()}"', + ], + 'Type 2: chaining various syntaxes' => [ + 'testMarker' => '/* testChain1 */', + 'expectedContent' => '"{$foo[\'bar\']->baz()()}"', + ], + 'Type 4: variable variables' => [ + 'testMarker' => '/* testVariableVar1 */', + 'expectedContent' => '"${$bar}"', + ], + 'Type 4: variable constants' => [ + 'testMarker' => '/* testVariableVar2 */', + 'expectedContent' => '"${(foo)}"', + ], + 'Type 4: object property' => [ + 'testMarker' => '/* testVariableVar3 */', + 'expectedContent' => '"${foo->bar}"', + ], + 'Type 4: variable variable nested in array offset' => [ + 'testMarker' => '/* testNested1 */', + 'expectedContent' => '"${foo["${bar}"]}"', + ], + 'Type 4: variable array offset nested in array offset' => [ + 'testMarker' => '/* testNested2 */', + 'expectedContent' => '"${foo["${bar[\'baz\']}"]}"', + ], + 'Type 4: variable object property' => [ + 'testMarker' => '/* testNested3 */', + 'expectedContent' => '"${foo->{$baz}}"', + ], + 'Type 4: variable object property - complex with single quotes' => [ + 'testMarker' => '/* testNested4 */', + 'expectedContent' => '"${foo->{${\'a\'}}}"', + ], + 'Type 4: variable object property - complex with single and double quotes' => [ + 'testMarker' => '/* testNested5 */', + 'expectedContent' => '"${foo->{"${\'a\'}"}}"', + ], + 'Type 4: live coding/parse error' => [ + 'testMarker' => '/* testParseError */', + 'expectedContent' => '"${foo["${bar +', + ], + ]; + + }//end dataDoubleQuotedString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/EnumCaseTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/EnumCaseTest.inc new file mode 100644 index 000000000..13b87242e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/EnumCaseTest.inc @@ -0,0 +1,95 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class EnumCaseTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the enum "case" is converted to T_ENUM_CASE. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataEnumCases + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testEnumCases($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $enumCase = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$enumCase]; + + $this->assertSame(T_ENUM_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM_CASE (code)'); + $this->assertSame('T_ENUM_CASE', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM_CASE (type)'); + + }//end testEnumCases() + + + /** + * Data provider. + * + * @see testEnumCases() + * + * @return array> + */ + public static function dataEnumCases() + { + return [ + 'enum case, no value' => ['/* testPureEnumCase */'], + 'enum case, integer value' => ['/* testBackingIntegerEnumCase */'], + 'enum case, string value' => ['/* testBackingStringEnumCase */'], + 'enum case, integer value in more complex enum' => ['/* testEnumCaseInComplexEnum */'], + 'enum case, keyword in mixed case' => ['/* testEnumCaseIsCaseInsensitive */'], + 'enum case, after switch statement' => ['/* testEnumCaseAfterSwitch */'], + 'enum case, after switch statement using alternative syntax' => ['/* testEnumCaseAfterSwitchWithEndSwitch */'], + ]; + + }//end dataEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNotEnumCases + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotEnumCases($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $case = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$case]; + + $this->assertSame(T_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (code)'); + $this->assertSame('T_CASE', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (type)'); + + }//end testNotEnumCases() + + + /** + * Data provider. + * + * @see testNotEnumCases() + * + * @return array> + */ + public static function dataNotEnumCases() + { + return [ + 'switch case with constant, semicolon condition end' => ['/* testCaseWithSemicolonIsNotEnumCase */'], + 'switch case with constant, colon condition end' => ['/* testCaseWithConstantIsNotEnumCase */'], + 'switch case with constant, comparison' => ['/* testCaseWithConstantAndIdenticalIsNotEnumCase */'], + 'switch case with constant, assignment' => ['/* testCaseWithAssigmentToConstantIsNotEnumCase */'], + 'switch case with constant, keyword in mixed case' => ['/* testIsNotEnumCaseIsCaseInsensitive */'], + 'switch case, body in curlies declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], + 'switch case, body after semicolon declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], + ]; + + }//end dataNotEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataKeywordAsEnumCaseNameShouldBeString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testKeywordAsEnumCaseNameShouldBeString($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $enumCaseName = $this->getTargetToken($testMarker, [T_STRING, T_INTERFACE, T_TRAIT, T_ENUM, T_FUNCTION, T_FALSE, T_DEFAULT, T_ARRAY]); + $tokenArray = $tokens[$enumCaseName]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testKeywordAsEnumCaseNameShouldBeString() + + + /** + * Data provider. + * + * @see testKeywordAsEnumCaseNameShouldBeString() + * + * @return array> + */ + public static function dataKeywordAsEnumCaseNameShouldBeString() + { + return [ + '"interface" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString1 */'], + '"trait" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString2 */'], + '"enum" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString3 */'], + '"function" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString4 */'], + '"false" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString5 */'], + '"default" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString6 */'], + '"array" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString7 */'], + ]; + + }//end dataKeywordAsEnumCaseNameShouldBeString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.inc new file mode 100644 index 000000000..e65600b6b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.inc @@ -0,0 +1,40 @@ +finally = 'foo'; + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.php new file mode 100644 index 000000000..e73dde122 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/FinallyTest.php @@ -0,0 +1,98 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class FinallyTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the finally keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataFinallyKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testFinallyKeyword($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_FINALLY, T_STRING]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_FINALLY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_FINALLY (code)'); + $this->assertSame('T_FINALLY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_FINALLY (type)'); + + }//end testFinallyKeyword() + + + /** + * Data provider. + * + * @see testFinallyKeyword() + * + * @return array> + */ + public static function dataFinallyKeyword() + { + return [ + 'finally after try and catch' => ['/* testTryCatchFinally */'], + 'finally between try and catch' => ['/* testTryFinallyCatch */'], + 'finally after try, no catch' => ['/* testTryFinally */'], + ]; + + }//end dataFinallyKeyword() + + + /** + * Test that 'finally' when not used as the reserved keyword is tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataFinallyNonKeyword + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testFinallyNonKeyword($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_FINALLY, T_STRING]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testFinallyNonKeyword() + + + /** + * Data provider. + * + * @see testFinallyNonKeyword() + * + * @return array> + */ + public static function dataFinallyNonKeyword() + { + return [ + 'finally used as class constant name' => ['/* testFinallyUsedAsClassConstantName */'], + 'finally used as method name' => ['/* testFinallyUsedAsMethodName */'], + 'finally used as property name' => ['/* testFinallyUsedAsPropertyName */'], + ]; + + }//end dataFinallyNonKeyword() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.inc new file mode 100644 index 000000000..12df5d296 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.inc @@ -0,0 +1,56 @@ + +
    + +property: + // Do something. + break; +} + +switch (true) { + /* testNotGotoDeclarationGlobalConstantInTernary */ + case $x === ($cond) ? CONST_A : CONST_B: + // Do something. + break; +} + +/* testNotGotoDeclarationEnumWithType */ +enum Suit: string implements Colorful, CardGame {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.php new file mode 100644 index 000000000..1b7422014 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/GotoLabelTest.php @@ -0,0 +1,176 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class GotoLabelTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that the label in a goto statement is tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataGotoStatement + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testGotoStatement($testMarker, $testContent) + { + $tokens = $this->phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, T_STRING); + + $this->assertTrue(is_int($label)); + $this->assertSame($testContent, $tokens[$label]['content']); + + }//end testGotoStatement() + + + /** + * Data provider. + * + * @see testGotoStatement() + * + * @return array> + */ + public static function dataGotoStatement() + { + return [ + 'label for goto statement' => [ + 'testMarker' => '/* testGotoStatement */', + 'testContent' => 'marker', + ], + 'label for goto statement in loop, keyword capitalized' => [ + 'testMarker' => '/* testGotoStatementInLoop */', + 'testContent' => 'end', + ], + ]; + + }//end dataGotoStatement() + + + /** + * Verify that the label in a goto declaration is tokenized as T_GOTO_LABEL. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataGotoDeclaration + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testGotoDeclaration($testMarker, $testContent) + { + $tokens = $this->phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, T_GOTO_LABEL); + + $this->assertTrue(is_int($label)); + $this->assertSame($testContent, $tokens[$label]['content']); + + }//end testGotoDeclaration() + + + /** + * Data provider. + * + * @see testGotoDeclaration() + * + * @return array> + */ + public static function dataGotoDeclaration() + { + return [ + 'label in goto declaration - marker' => [ + 'testMarker' => '/* testGotoDeclaration */', + 'testContent' => 'marker:', + ], + 'label in goto declaration - end' => [ + 'testMarker' => '/* testGotoDeclarationOutsideLoop */', + 'testContent' => 'end:', + ], + ]; + + }//end dataGotoDeclaration() + + + /** + * Verify that the constant used in a switch - case statement is not confused with a goto label. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to expect. + * + * @dataProvider dataNotAGotoDeclaration + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNotAGotoDeclaration($testMarker, $testContent) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_GOTO_LABEL, T_STRING], $testContent); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testNotAGotoDeclaration() + + + /** + * Data provider. + * + * @see testNotAGotoDeclaration() + * + * @return array> + */ + public static function dataNotAGotoDeclaration() + { + return [ + 'not goto label - global constant followed by switch-case colon' => [ + 'testMarker' => '/* testNotGotoDeclarationGlobalConstant */', + 'testContent' => 'CONSTANT', + ], + 'not goto label - namespaced constant followed by switch-case colon' => [ + 'testMarker' => '/* testNotGotoDeclarationNamespacedConstant */', + 'testContent' => 'CONSTANT', + ], + 'not goto label - class constant followed by switch-case colon' => [ + 'testMarker' => '/* testNotGotoDeclarationClassConstant */', + 'testContent' => 'CONSTANT', + ], + 'not goto label - class property use followed by switch-case colon' => [ + 'testMarker' => '/* testNotGotoDeclarationClassProperty */', + 'testContent' => 'property', + ], + 'not goto label - global constant followed by ternary else' => [ + 'testMarker' => '/* testNotGotoDeclarationGlobalConstantInTernary */', + 'testContent' => 'CONST_A', + ], + 'not goto label - global constant after ternary else' => [ + 'testMarker' => '/* testNotGotoDeclarationGlobalConstantInTernary */', + 'testContent' => 'CONST_B', + ], + 'not goto label - name of backed enum' => [ + 'testMarker' => '/* testNotGotoDeclarationEnumWithType */', + 'testContent' => 'Suit', + ], + ]; + + }//end dataNotAGotoDeclaration() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocNowdocTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocNowdocTest.inc new file mode 100644 index 000000000..5041dda15 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocNowdocTest.inc @@ -0,0 +1,39 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Tests the tokenization for heredoc/nowdoc constructs. + * + * Verifies that: + * - Nowdoc opener/closers are retokenized from `T_[START_|END_]HEREDOC` to `T_[START_|END_]NOWDOC`. + * - The contents of the heredoc/nowdoc is tokenized as `T_HEREDOC`/`T_NOWDOC`. + * - Each line of the contents has its own token, which includes the new line char. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + */ +final class HeredocNowdocTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify tokenization a heredoc construct. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testHeredocSingleLine() + { + $expectedSequence = [ + [T_START_HEREDOC => '<< 'Some $var text'."\n"], + [T_END_HEREDOC => 'EOD'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_START_HEREDOC); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testHeredocSingleLine() + + + /** + * Verify tokenization a nowdoc construct. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testNowdocSingleLine() + { + $expectedSequence = [ + [T_START_NOWDOC => "<<<'MARKER'\n"], + [T_NOWDOC => 'Some text'."\n"], + [T_END_NOWDOC => 'MARKER'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_START_NOWDOC); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testNowdocSingleLine() + + + /** + * Verify tokenization a multiline heredoc construct. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testHeredocMultiLine() + { + $expectedSequence = [ + [T_START_HEREDOC => '<<<"😬"'."\n"], + [T_HEREDOC => 'Lorum ipsum'."\n"], + [T_HEREDOC => 'Some $var text'."\n"], + [T_HEREDOC => 'dolor sit amet'."\n"], + [T_END_HEREDOC => '😬'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_START_HEREDOC); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testHeredocMultiLine() + + + /** + * Verify tokenization a multiline testNowdocSingleLine construct. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testNowdocMultiLine() + { + $expectedSequence = [ + [T_START_NOWDOC => "<<<'multi_line'\n"], + [T_NOWDOC => 'Lorum ipsum'."\n"], + [T_NOWDOC => 'Some text'."\n"], + [T_NOWDOC => 'dolor sit amet'."\n"], + [T_END_NOWDOC => 'multi_line'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_START_NOWDOC); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testNowdocMultiLine() + + + /** + * Verify tokenization a multiline heredoc construct. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testHeredocEndsOnBlankLine() + { + $expectedSequence = [ + [T_START_HEREDOC => '<< 'Lorum ipsum'."\n"], + [T_HEREDOC => 'dolor sit amet'."\n"], + [T_HEREDOC => "\n"], + [T_END_HEREDOC => 'EOD'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_START_HEREDOC); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testHeredocEndsOnBlankLine() + + + /** + * Verify tokenization a multiline testNowdocSingleLine construct. + * + * @phpcs:disable Squiz.Arrays.ArrayDeclaration.SpaceBeforeDoubleArrow -- Readability is better with alignment. + * + * @return void + */ + public function testNowdocEndsOnBlankLine() + { + $expectedSequence = [ + [T_START_NOWDOC => "<<<'EOD'\n"], + [T_NOWDOC => 'Lorum ipsum'."\n"], + [T_NOWDOC => 'dolor sit amet'."\n"], + [T_NOWDOC => "\n"], + [T_END_NOWDOC => 'EOD'], + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_START_NOWDOC); + + $this->checkTokenSequence($target, $expectedSequence); + + }//end testNowdocEndsOnBlankLine() + + + /** + * Test helper. Check a token sequence complies with an expected token sequence. + * + * @param int $startPtr The position in the file to start checking from. + * @param array> $expectedSequence The consecutive token constants and their contents to expect. + * + * @return void + */ + private function checkTokenSequence($startPtr, array $expectedSequence) + { + $tokens = $this->phpcsFile->getTokens(); + + $sequenceKey = 0; + $sequenceCount = count($expectedSequence); + + for ($i = $startPtr; $sequenceKey < $sequenceCount; $i++, $sequenceKey++) { + $currentItem = $expectedSequence[$sequenceKey]; + $expectedCode = key($currentItem); + $expectedType = Tokens::tokenName($expectedCode); + $expectedContent = current($currentItem); + $errorMsgSuffix = PHP_EOL.'(StackPtr: '.$i.' | Position in sequence: '.$sequenceKey.' | Expected: '.$expectedType.')'; + + $this->assertSame( + $expectedCode, + $tokens[$i]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$i]['code']).', not '.$expectedType.' (code)'.$errorMsgSuffix + ); + + $this->assertSame( + $expectedType, + $tokens[$i]['type'], + 'Token tokenized as '.$tokens[$i]['type'].', not '.$expectedType.' (type)'.$errorMsgSuffix + ); + + $this->assertSame( + $expectedContent, + $tokens[$i]['content'], + 'Token content did not match expectations'.$errorMsgSuffix + ); + }//end for + + }//end checkTokenSequence() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.inc new file mode 100644 index 000000000..d552b1283 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.inc @@ -0,0 +1,11 @@ +>>>>>> master diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.php new file mode 100644 index 000000000..877706fb4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocParseErrorTest.php @@ -0,0 +1,41 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +/** + * Tests the tokenization for an unclosed heredoc construct. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + */ +final class HeredocParseErrorTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that a heredoc (and nowdoc) start token is retokenized to T_STRING if no closer is found. + * + * @return void + */ + public function testMergeConflict() + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testUnclosedHeredoc */', [T_START_HEREDOC, T_STRING], '<<< HEAD'."\n"); + $tokenArray = $tokens[$token]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_START_HEREDOC (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_START_HEREDOC (type)'); + + }//end testMergeConflict() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.inc new file mode 100644 index 000000000..ae43e24a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.inc @@ -0,0 +1,193 @@ +bar +EOD; + +/* testProperty2 */ +$heredoc = <<<"EOD" +{$foo->bar} +EOD; + +/* testMethod1 */ +$heredoc = <<bar()} +EOD; + +/* testClosure1 */ +$heredoc = <<<"EOD" +{$foo()} +EOD; + +/* testChain1 */ +$heredoc = <<baz()()} +EOD; + +/* testVariableVar1 */ +$heredoc = <<<"EOD" +${$bar} +EOD; + +/* testVariableVar2 */ +$heredoc = <<bar} +EOD; + +/* testNested1 */ +$heredoc = <<{$baz}} +EOD; + +/* testNested4 */ +$heredoc = <<<"EOD" +${foo->{${'a'}}} +EOD; + +/* testNested5 */ +$heredoc = <<{"${'a'}"}} +EOD; + +/* testSimple1Wrapped */ +$heredoc = <<bar Something +EOD; + +/* testProperty2Wrapped */ +$heredoc = <<<"EOD" +Do {$foo->bar} Something +EOD; + +/* testMethod1Wrapped */ +$heredoc = <<bar()} Something +EOD; + +/* testClosure1Wrapped */ +$heredoc = <<<"EOD" +Do {$foo()} Something +EOD; + +/* testChain1Wrapped */ +$heredoc = <<baz()()} Something +EOD; + +/* testVariableVar1Wrapped */ +$heredoc = <<<"EOD" +Do ${$bar} Something +EOD; + +/* testVariableVar2Wrapped */ +$heredoc = <<bar} Something +EOD; + +/* testNested1Wrapped */ +$heredoc = <<{$baz}} Something +EOD; + +/* testNested4Wrapped */ +$heredoc = <<<"EOD" +Do ${foo->{${'a'}}} Something +EOD; + +/* testNested5Wrapped */ +$heredoc = <<{"${'a'}"}} Something +EOD; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.php new file mode 100644 index 000000000..c31c17538 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/HeredocStringTest.php @@ -0,0 +1,161 @@ + + * @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class HeredocStringTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that heredoc strings contain the complete interpolated string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent The expected content of the heredoc string. + * + * @dataProvider dataHeredocString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testHeredocString($testMarker, $expectedContent) + { + $tokens = $this->phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, T_HEREDOC); + $this->assertSame($expectedContent."\n", $tokens[$target]['content']); + + }//end testHeredocString() + + + /** + * Test that heredoc strings contain the complete interpolated string when combined with other texts. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent The expected content of the heredoc string. + * + * @dataProvider dataHeredocString + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testHeredocStringWrapped($testMarker, $expectedContent) + { + $tokens = $this->phpcsFile->getTokens(); + + $testMarker = substr($testMarker, 0, -3).'Wrapped */'; + $target = $this->getTargetToken($testMarker, T_HEREDOC); + $this->assertSame('Do '.$expectedContent." Something\n", $tokens[$target]['content']); + + }//end testHeredocStringWrapped() + + + /** + * Data provider. + * + * Type reference: + * 1. Directly embedded variables. + * 2. Braces outside the variable. + * 3. Braces after the dollar sign. + * 4. Variable variables and expressions. + * + * @link https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation + * + * @see testHeredocString() + * + * @return array> + */ + public static function dataHeredocString() + { + return [ + 'Type 1: simple variable' => [ + 'testMarker' => '/* testSimple1 */', + 'expectedContent' => '$foo', + ], + 'Type 2: simple variable' => [ + 'testMarker' => '/* testSimple2 */', + 'expectedContent' => '{$foo}', + ], + 'Type 3: simple variable' => [ + 'testMarker' => '/* testSimple3 */', + 'expectedContent' => '${foo}', + ], + 'Type 1: array offset' => [ + 'testMarker' => '/* testDIM1 */', + 'expectedContent' => '$foo[bar]', + ], + 'Type 2: array offset' => [ + 'testMarker' => '/* testDIM2 */', + 'expectedContent' => '{$foo[\'bar\']}', + ], + 'Type 3: array offset' => [ + 'testMarker' => '/* testDIM3 */', + 'expectedContent' => '${foo[\'bar\']}', + ], + 'Type 1: object property' => [ + 'testMarker' => '/* testProperty1 */', + 'expectedContent' => '$foo->bar', + ], + 'Type 2: object property' => [ + 'testMarker' => '/* testProperty2 */', + 'expectedContent' => '{$foo->bar}', + ], + 'Type 2: object method call' => [ + 'testMarker' => '/* testMethod1 */', + 'expectedContent' => '{$foo->bar()}', + ], + 'Type 2: closure function call' => [ + 'testMarker' => '/* testClosure1 */', + 'expectedContent' => '{$foo()}', + ], + 'Type 2: chaining various syntaxes' => [ + 'testMarker' => '/* testChain1 */', + 'expectedContent' => '{$foo[\'bar\']->baz()()}', + ], + 'Type 4: variable variables' => [ + 'testMarker' => '/* testVariableVar1 */', + 'expectedContent' => '${$bar}', + ], + 'Type 4: variable constants' => [ + 'testMarker' => '/* testVariableVar2 */', + 'expectedContent' => '${(foo)}', + ], + 'Type 4: object property' => [ + 'testMarker' => '/* testVariableVar3 */', + 'expectedContent' => '${foo->bar}', + ], + 'Type 4: variable variable nested in array offset' => [ + 'testMarker' => '/* testNested1 */', + 'expectedContent' => '${foo["${bar}"]}', + ], + 'Type 4: variable array offset nested in array offset' => [ + 'testMarker' => '/* testNested2 */', + 'expectedContent' => '${foo["${bar[\'baz\']}"]}', + ], + 'Type 4: variable object property' => [ + 'testMarker' => '/* testNested3 */', + 'expectedContent' => '${foo->{$baz}}', + ], + 'Type 4: variable object property - complex with single quotes' => [ + 'testMarker' => '/* testNested4 */', + 'expectedContent' => '${foo->{${\'a\'}}}', + ], + 'Type 4: variable object property - complex with single and double quotes' => [ + 'testMarker' => '/* testNested5 */', + 'expectedContent' => '${foo->{"${\'a\'}"}}', + ], + ]; + + }//end dataHeredocString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.inc new file mode 100644 index 000000000..2f1d20bf0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.inc @@ -0,0 +1,407 @@ +getPos(skip: false), + count: count(array_or_countable: $array), + value: 50 +); + +array_fill( + start_index: /* testNestedFunctionCallInner1 */ $obj->getPos(skip: false), + count: /* testNestedFunctionCallInner2 */ count(array_or_countable: $array), + value: 50 +); + +/* testNamespaceRelativeFunction */ +namespace\function_name(label:$string, more: false); + +/* testPartiallyQualifiedFunction */ +Partially\Qualified\function_name(label:$string, more: false); + +/* testFullyQualifiedFunction */ +\Fully\Qualified\function_name(label: $string, more:false); + +/* testVariableFunction */ +$fn(label: $string, more:false); + +/* testVariableVariableFunction */ +${$fn}(label: $string, more:false); + +/* testMethodCall */ +$obj->methodName(label: $foo, more: $bar); + +/* testVariableMethodCall */ +$obj->{$var}(label: $foo, more: $bar); + +/* testClassInstantiation */ +$obj = new MyClass(label: $string, more:false); + +/* testClassInstantiationSelf */ +$obj = new self(label: $string, more:true); + +/* testClassInstantiationStatic */ +$obj = new static(label: $string, more:false); + +/* testAnonClass */ +$anon = new class(label: $string, more: false) { + public function __construct($label, $more) {} +}; + +function myfoo( $💩💩💩, $ПаÑха, $_valid) {} +/* testNonAsciiNames */ +foo(💩💩💩: [], ПаÑха: 'text', _valid: 123); + +/* testMixedPositionalAndNamedArgsWithTernary */ +foo( $cond ? true : false, name: $value2 ); + +/* testNamedArgWithTernary */ +foo( label: $cond ? true : false, more: $cond ? CONSTANT_A : CONSTANT_B ); + +/* testTernaryWithFunctionCallsInThenElse */ +echo $cond ? foo( label: $something ) : foo( more: $something_else ); + +/* testTernaryWithConstantsInThenElse */ +echo $cond ? CONSTANT_NAME : OTHER_CONSTANT; + +switch ($s) { + /* testSwitchCaseWithConstant */ + case MY_CONSTANT: + // Do something. + break; + + /* testSwitchCaseWithClassProperty */ + case $obj->property: + // Do something. + break; + + /* testSwitchDefault */ + default: + // Do something. + break; +} + +/* testTernaryWithClosuresAndReturnTypes */ +$closure = $cond ? function() : bool {return true;} : function() : int {return 123;}; + +/* testTernaryWithArrowFunctionsAndReturnTypes */ +$fn = $cond ? fn() : bool => true : fn() : int => 123; + + +/* testCompileErrorNamedBeforePositional */ +// Not the concern of PHPCS. Should still be handled. +test(param: $bar, $foo); + +/* testDuplicateName1 */ +// Error Exception, but not the concern of PHPCS. Should still be handled. +test(param: 1, /* testDuplicateName2 */ param: 2); + +/* testIncorrectOrderWithVariadic */ +// Error Exception, but not the concern of PHPCS. Should still be handled. +array_fill(start_index: 0, ...[100, 50]); + +/* testCompileErrorIncorrectOrderWithVariadic */ +// Not the concern of PHPCS. Should still be handled. +test(...$values, param: $value); // Compile-time error + +/* testParseErrorNoValue */ +// Not the concern of PHPCS. Should still be handled. +test(param1:, param2:); + +/* testParseErrorDynamicName */ +// Parse error. Ignore. +function_name($variableStoringParamName: $value); + +/* testParseErrorExit */ +// Exit is a language construct, not a function. Named params not supported, handle it anyway. +exit(status: $value); + +/* testParseErrorEmpty */ +// Empty is a language construct, not a function. Named params not supported, handle it anyway. +empty(variable: $value); + +/* testParseErrorEval */ +// Eval is a language construct, not a function. Named params not supported, handle it anyway. +eval(code: $value); + +/* testParseErrorArbitraryParentheses */ +// Parse error. Not named param, handle it anyway. +$calc = (something: $value / $other); + + +/* testReservedKeywordAbstract1 */ +foobar(abstract: $value, /* testReservedKeywordAbstract2 */ abstract: $value); + +/* testReservedKeywordAnd1 */ +foobar(and: $value, /* testReservedKeywordAnd2 */ and: $value); + +/* testReservedKeywordArray1 */ +foobar(array: $value, /* testReservedKeywordArray2 */ array: $value); + +/* testReservedKeywordAs1 */ +foobar(as: $value, /* testReservedKeywordAs2 */ as: $value); + +/* testReservedKeywordBreak1 */ +foobar(break: $value, /* testReservedKeywordBreak2 */ break: $value); + +/* testReservedKeywordCallable1 */ +foobar(callable: $value, /* testReservedKeywordCallable2 */ callable: $value); + +/* testReservedKeywordCase1 */ +foobar(case: $value, /* testReservedKeywordCase2 */ case: $value); + +/* testReservedKeywordCatch1 */ +foobar(catch: $value, /* testReservedKeywordCatch2 */ catch: $value); + +/* testReservedKeywordClass1 */ +foobar(class: $value, /* testReservedKeywordClass2 */ class: $value); + +/* testReservedKeywordClone1 */ +foobar(clone: $value, /* testReservedKeywordClone2 */ clone: $value); + +/* testReservedKeywordConst1 */ +foobar(const: $value, /* testReservedKeywordConst2 */ const: $value); + +/* testReservedKeywordContinue1 */ +foobar(continue: $value, /* testReservedKeywordContinue2 */ continue: $value); + +/* testReservedKeywordDeclare1 */ +foobar(declare: $value, /* testReservedKeywordDeclare2 */ declare: $value); + +/* testReservedKeywordDefault1 */ +foobar(default: $value, /* testReservedKeywordDefault2 */ default: $value); + +/* testReservedKeywordDie1 */ +foobar(die: $value, /* testReservedKeywordDie2 */ die: $value); + +/* testReservedKeywordDo1 */ +foobar(do: $value, /* testReservedKeywordDo2 */ do: $value); + +/* testReservedKeywordEcho1 */ +foobar(echo: $value, /* testReservedKeywordEcho2 */ echo: $value); + +/* testReservedKeywordElse1 */ +foobar(else: $value, /* testReservedKeywordElse2 */ else: $value); + +/* testReservedKeywordElseif1 */ +foobar(elseif: $value, /* testReservedKeywordElseif2 */ elseif: $value); + +/* testReservedKeywordEmpty1 */ +foobar(empty: $value, /* testReservedKeywordEmpty2 */ empty: $value); + +/* testReservedKeywordEnum1 */ +foobar(enum: $value, /* testReservedKeywordEnum2 */ enum: $value); + +/* testReservedKeywordEnddeclare1 */ +foobar(enddeclare: $value, /* testReservedKeywordEnddeclare2 */ enddeclare: $value); + +/* testReservedKeywordEndfor1 */ +foobar(endfor: $value, /* testReservedKeywordEndfor2 */ endfor: $value); + +/* testReservedKeywordEndforeach1 */ +foobar(endforeach: $value, /* testReservedKeywordEndforeach2 */ endforeach: $value); + +/* testReservedKeywordEndif1 */ +foobar(endif: $value, /* testReservedKeywordEndif2 */ endif: $value); + +/* testReservedKeywordEndswitch1 */ +foobar(endswitch: $value, /* testReservedKeywordEndswitch2 */ endswitch: $value); + +/* testReservedKeywordEndwhile1 */ +foobar(endwhile: $value, /* testReservedKeywordEndwhile2 */ endwhile: $value); + +/* testReservedKeywordEval1 */ +foobar(eval: $value, /* testReservedKeywordEval2 */ eval: $value); + +/* testReservedKeywordExit1 */ +foobar(exit: $value, /* testReservedKeywordExit2 */ exit: $value); + +/* testReservedKeywordExtends1 */ +foobar(extends: $value, /* testReservedKeywordExtends2 */ extends: $value); + +/* testReservedKeywordFinal1 */ +foobar(final: $value, /* testReservedKeywordFinal2 */ final: $value); + +/* testReservedKeywordFinally1 */ +foobar(finally: $value, /* testReservedKeywordFinally2 */ finally: $value); + +/* testReservedKeywordFn1 */ +foobar(fn: $value, /* testReservedKeywordFn2 */ fn: $value); + +/* testReservedKeywordFor1 */ +foobar(for: $value, /* testReservedKeywordFor2 */ for: $value); + +/* testReservedKeywordForeach1 */ +foobar(foreach: $value, /* testReservedKeywordForeach2 */ foreach: $value); + +/* testReservedKeywordFunction1 */ +foobar(function: $value, /* testReservedKeywordFunction2 */ function: $value); + +/* testReservedKeywordGlobal1 */ +foobar(global: $value, /* testReservedKeywordGlobal2 */ global: $value); + +/* testReservedKeywordGoto1 */ +foobar(goto: $value, /* testReservedKeywordGoto2 */ goto: $value); + +/* testReservedKeywordIf1 */ +foobar(if: $value, /* testReservedKeywordIf2 */ if: $value); + +/* testReservedKeywordImplements1 */ +foobar(implements: $value, /* testReservedKeywordImplements2 */ implements: $value); + +/* testReservedKeywordInclude1 */ +foobar(include: $value, /* testReservedKeywordInclude2 */ include: $value); + +/* testReservedKeywordInclude_once1 */ +foobar(include_once: $value, /* testReservedKeywordInclude_once2 */ include_once: $value); + +/* testReservedKeywordInstanceof1 */ +foobar(instanceof: $value, /* testReservedKeywordInstanceof2 */ instanceof: $value); + +/* testReservedKeywordInsteadof1 */ +foobar(insteadof: $value, /* testReservedKeywordInsteadof2 */ insteadof: $value); + +/* testReservedKeywordInterface1 */ +foobar(interface: $value, /* testReservedKeywordInterface2 */ interface: $value); + +/* testReservedKeywordIsset1 */ +foobar(isset: $value, /* testReservedKeywordIsset2 */ isset: $value); + +/* testReservedKeywordList1 */ +foobar(list: $value, /* testReservedKeywordList2 */ list: $value); + +/* testReservedKeywordMatch1 */ +foobar(match: $value, /* testReservedKeywordMatch2 */ match: $value); + +/* testReservedKeywordNamespace1 */ +foobar(namespace: $value, /* testReservedKeywordNamespace2 */ namespace: $value); + +/* testReservedKeywordNew1 */ +foobar(new: $value, /* testReservedKeywordNew2 */ new: $value); + +/* testReservedKeywordOr1 */ +foobar(or: $value, /* testReservedKeywordOr2 */ or: $value); + +/* testReservedKeywordPrint1 */ +foobar(print: $value, /* testReservedKeywordPrint2 */ print: $value); + +/* testReservedKeywordPrivate1 */ +foobar(private: $value, /* testReservedKeywordPrivate2 */ private: $value); + +/* testReservedKeywordProtected1 */ +foobar(protected: $value, /* testReservedKeywordProtected2 */ protected: $value); + +/* testReservedKeywordPublic1 */ +foobar(public: $value, /* testReservedKeywordPublic2 */ public: $value); + +/* testReservedKeywordReadonly1 */ +foobar(readonly: $value, /* testReservedKeywordReadonly2 */ readonly: $value); + +/* testReservedKeywordRequire1 */ +foobar(require: $value, /* testReservedKeywordRequire2 */ require: $value); + +/* testReservedKeywordRequire_once1 */ +foobar(require_once: $value, /* testReservedKeywordRequire_once2 */ require_once: $value); + +/* testReservedKeywordReturn1 */ +foobar(return: $value, /* testReservedKeywordReturn2 */ return: $value); + +/* testReservedKeywordStatic1 */ +foobar(static: $value, /* testReservedKeywordStatic2 */ static: $value); + +/* testReservedKeywordSwitch1 */ +foobar(switch: $value, /* testReservedKeywordSwitch2 */ switch: $value); + +/* testReservedKeywordThrow1 */ +foobar(throw: $value, /* testReservedKeywordThrow2 */ throw: $value); + +/* testReservedKeywordTrait1 */ +foobar(trait: $value, /* testReservedKeywordTrait2 */ trait: $value); + +/* testReservedKeywordTry1 */ +foobar(try: $value, /* testReservedKeywordTry2 */ try: $value); + +/* testReservedKeywordUnset1 */ +foobar(unset: $value, /* testReservedKeywordUnset2 */ unset: $value); + +/* testReservedKeywordUse1 */ +foobar(use: $value, /* testReservedKeywordUse2 */ use: $value); + +/* testReservedKeywordVar1 */ +foobar(var: $value, /* testReservedKeywordVar2 */ var: $value); + +/* testReservedKeywordWhile1 */ +foobar(while: $value, /* testReservedKeywordWhile2 */ while: $value); + +/* testReservedKeywordXor1 */ +foobar(xor: $value, /* testReservedKeywordXor2 */ xor: $value); + +/* testReservedKeywordYield1 */ +foobar(yield: $value, /* testReservedKeywordYield2 */ yield: $value); + +/* testReservedKeywordInt1 */ +foobar(int: $value, /* testReservedKeywordInt2 */ int: $value); + +/* testReservedKeywordFloat1 */ +foobar(float: $value, /* testReservedKeywordFloat2 */ float: $value); + +/* testReservedKeywordBool1 */ +foobar(bool: $value, /* testReservedKeywordBool2 */ bool: $value); + +/* testReservedKeywordString1 */ +foobar(string: $value, /* testReservedKeywordString2 */ string: $value); + +/* testReservedKeywordTrue1 */ +foobar(true: $value, /* testReservedKeywordTrue2 */ true: $value); + +/* testReservedKeywordFalse1 */ +foobar(false: $value, /* testReservedKeywordFalse2 */ false: $value); + +/* testReservedKeywordNull1 */ +foobar(null: $value, /* testReservedKeywordNull2 */ null: $value); + +/* testReservedKeywordVoid1 */ +foobar(void: $value, /* testReservedKeywordVoid2 */ void: $value); + +/* testReservedKeywordIterable1 */ +foobar(iterable: $value, /* testReservedKeywordIterable2 */ iterable: $value); + +/* testReservedKeywordObject1 */ +foobar(object: $value, /* testReservedKeywordObject2 */ object: $value); + +/* testReservedKeywordResource1 */ +foobar(resource: $value, /* testReservedKeywordResource2 */ resource: $value); + +/* testReservedKeywordMixed1 */ +foobar(mixed: $value, /* testReservedKeywordMixed2 */ mixed: $value); + +/* testReservedKeywordNumeric1 */ +foobar(numeric: $value, /* testReservedKeywordNumeric2 */ numeric: $value); + +/* testReservedKeywordParent1 */ +foobar(parent: $value, /* testReservedKeywordParent2 */ parent: $value); + +/* testReservedKeywordSelf1 */ +foobar(self: $value, /* testReservedKeywordSelf2 */ self: $value); + +/* testReservedKeywordNever1 */ +foobar(never: $value, /* testReservedKeywordNever2 */ never: $value); diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.php new file mode 100644 index 000000000..df124e913 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NamedFunctionCallArgumentsTest.php @@ -0,0 +1,974 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class NamedFunctionCallArgumentsTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that parameter labels are tokenized as T_PARAM_NAME and that + * the colon after it is tokenized as a T_COLON. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $parameters The token content for each parameter label to look for. + * + * @dataProvider dataNamedFunctionCallArguments + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNamedFunctionCallArguments($testMarker, $parameters) + { + $tokens = $this->phpcsFile->getTokens(); + + foreach ($parameters as $content) { + $label = $this->getTargetToken($testMarker, [T_STRING, T_PARAM_NAME], $content); + + $this->assertSame( + T_PARAM_NAME, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (code)' + ); + $this->assertSame( + 'T_PARAM_NAME', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (type)' + ); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + }//end foreach + + }//end testNamedFunctionCallArguments() + + + /** + * Data provider. + * + * @see testNamedFunctionCallArguments() + * + * @return array>> + */ + public static function dataNamedFunctionCallArguments() + { + return [ + 'function call, single line, all named args' => [ + 'testMarker' => '/* testNamedArgs */', + 'parameters' => [ + 'start_index', + 'count', + 'value', + ], + ], + 'function call, multi-line, all named args' => [ + 'testMarker' => '/* testNamedArgsMultiline */', + 'parameters' => [ + 'start_index', + 'count', + 'value', + ], + ], + 'function call, single line, all named args; comments and whitespace' => [ + 'testMarker' => '/* testNamedArgsWithWhitespaceAndComments */', + 'parameters' => [ + 'start_index', + 'count', + 'value', + ], + ], + 'function call, single line, mixed positional and named args' => [ + 'testMarker' => '/* testMixedPositionalAndNamedArgs */', + 'parameters' => [ + 'double_encode', + ], + ], + 'function call containing nested function call values' => [ + 'testMarker' => '/* testNestedFunctionCallOuter */', + 'parameters' => [ + 'start_index', + 'count', + 'value', + ], + ], + 'function call nested in named arg [1]' => [ + 'testMarker' => '/* testNestedFunctionCallInner1 */', + 'parameters' => [ + 'skip', + ], + ], + 'function call nested in named arg [2]' => [ + 'testMarker' => '/* testNestedFunctionCallInner2 */', + 'parameters' => [ + 'array_or_countable', + ], + ], + 'namespace relative function call' => [ + 'testMarker' => '/* testNamespaceRelativeFunction */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'partially qualified function call' => [ + 'testMarker' => '/* testPartiallyQualifiedFunction */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'fully qualified function call' => [ + 'testMarker' => '/* testFullyQualifiedFunction */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'variable function call' => [ + 'testMarker' => '/* testVariableFunction */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'variable variable function call' => [ + 'testMarker' => '/* testVariableVariableFunction */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'method call' => [ + 'testMarker' => '/* testMethodCall */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'variable method call' => [ + 'testMarker' => '/* testVariableMethodCall */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'class instantiation' => [ + 'testMarker' => '/* testClassInstantiation */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'class instantiation with "self"' => [ + 'testMarker' => '/* testClassInstantiationSelf */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'class instantiation with "static"' => [ + 'testMarker' => '/* testClassInstantiationStatic */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'anonymous class instantiation' => [ + 'testMarker' => '/* testAnonClass */', + 'parameters' => [ + 'label', + 'more', + ], + ], + 'function call with non-ascii characters in the variable name labels' => [ + 'testMarker' => '/* testNonAsciiNames */', + 'parameters' => [ + '💩💩💩', + 'ПаÑха', + '_valid', + ], + ], + + // Coding errors which should still be handled. + 'invalid: named arg before positional (compile error)' => [ + 'testMarker' => '/* testCompileErrorNamedBeforePositional */', + 'parameters' => [ + 'param', + ], + ], + 'invalid: duplicate parameter name [1]' => [ + 'testMarker' => '/* testDuplicateName1 */', + 'parameters' => [ + 'param', + ], + ], + 'invalid: duplicate parameter name [2]' => [ + 'testMarker' => '/* testDuplicateName2 */', + 'parameters' => [ + 'param', + ], + ], + 'invalid: named arg before variadic (error exception)' => [ + 'testMarker' => '/* testIncorrectOrderWithVariadic */', + 'parameters' => [ + 'start_index', + ], + ], + 'invalid: named arg after variadic (compile error)' => [ + 'testMarker' => '/* testCompileErrorIncorrectOrderWithVariadic */', + 'parameters' => [ + 'param', + ], + ], + 'invalid: named arg without value (parse error)' => [ + 'testMarker' => '/* testParseErrorNoValue */', + 'parameters' => [ + 'param1', + 'param2', + ], + ], + 'invalid: named arg in exit() (parse error)' => [ + 'testMarker' => '/* testParseErrorExit */', + 'parameters' => [ + 'status', + ], + ], + 'invalid: named arg in empty() (parse error)' => [ + 'testMarker' => '/* testParseErrorEmpty */', + 'parameters' => [ + 'variable', + ], + ], + 'invalid: named arg in eval() (parse error)' => [ + 'testMarker' => '/* testParseErrorEval */', + 'parameters' => [ + 'code', + ], + ], + 'invalid: named arg in arbitrary parentheses (parse error)' => [ + 'testMarker' => '/* testParseErrorArbitraryParentheses */', + 'parameters' => [ + 'something', + ], + ], + ]; + + }//end dataNamedFunctionCallArguments() + + + /** + * Verify that other T_STRING tokens within a function call are still tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $content The token content to look for. + * + * @dataProvider dataOtherTstringInFunctionCall + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testOtherTstringInFunctionCall($testMarker, $content) + { + $tokens = $this->phpcsFile->getTokens(); + + $label = $this->getTargetToken($testMarker, [T_STRING, T_PARAM_NAME], $content); + + $this->assertSame( + T_STRING, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_STRING (code)' + ); + $this->assertSame( + 'T_STRING', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_STRING (type)' + ); + + }//end testOtherTstringInFunctionCall() + + + /** + * Data provider. + * + * @see testOtherTstringInFunctionCall() + * + * @return array> + */ + public static function dataOtherTstringInFunctionCall() + { + return [ + 'not arg name - global constant' => [ + 'testMarker' => '/* testPositionalArgs */', + 'content' => 'START_INDEX', + ], + 'not arg name - fully qualified constant' => [ + 'testMarker' => '/* testPositionalArgs */', + 'content' => 'COUNT', + ], + 'not arg name - namespace relative constant' => [ + 'testMarker' => '/* testPositionalArgs */', + 'content' => 'VALUE', + ], + 'not arg name - unqualified function call' => [ + 'testMarker' => '/* testNestedFunctionCallInner2 */', + 'content' => 'count', + ], + ]; + + }//end dataOtherTstringInFunctionCall() + + + /** + * Verify whether the colons are tokenized correctly when a ternary is used in a mixed + * positional and named arguments function call. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testMixedPositionalAndNamedArgsWithTernary() + { + $tokens = $this->phpcsFile->getTokens(); + + $true = $this->getTargetToken('/* testMixedPositionalAndNamedArgsWithTernary */', T_TRUE); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + $label = $this->getTargetToken('/* testMixedPositionalAndNamedArgsWithTernary */', T_PARAM_NAME, 'name'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testMixedPositionalAndNamedArgsWithTernary() + + + /** + * Verify whether the colons are tokenized correctly when a ternary is used + * in a named arguments function call. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNamedArgWithTernary() + { + $tokens = $this->phpcsFile->getTokens(); + + /* + * First argument. + */ + + $label = $this->getTargetToken('/* testNamedArgWithTernary */', T_PARAM_NAME, 'label'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'First arg: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'First arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'First arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $true = $this->getTargetToken('/* testNamedArgWithTernary */', T_TRUE); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'First arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'First arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + /* + * Second argument. + */ + + $label = $this->getTargetToken('/* testNamedArgWithTernary */', T_PARAM_NAME, 'more'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Second arg: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Second arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Second arg: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $true = $this->getTargetToken('/* testNamedArgWithTernary */', T_STRING, 'CONSTANT_A'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($true + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Second arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Second arg ternary: Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + }//end testNamedArgWithTernary() + + + /** + * Verify whether the colons are tokenized correctly when named arguments + * function calls are used in a ternary. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryWithFunctionCallsInThenElse() + { + $tokens = $this->phpcsFile->getTokens(); + + /* + * Then. + */ + + $label = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_PARAM_NAME, 'label'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Function in then: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Function in then: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Function in then: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $closeParens = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_CLOSE_PARENTHESIS); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($closeParens + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + /* + * Else. + */ + + $label = $this->getTargetToken('/* testTernaryWithFunctionCallsInThenElse */', T_PARAM_NAME, 'more'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Function in else: Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Function in else: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Function in else: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testTernaryWithFunctionCallsInThenElse() + + + /** + * Verify whether the colons are tokenized correctly when constants are used in a ternary. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryWithConstantsInThenElse() + { + $tokens = $this->phpcsFile->getTokens(); + + $constant = $this->getTargetToken('/* testTernaryWithConstantsInThenElse */', T_STRING, 'CONSTANT_NAME'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($constant + 1), null, true); + + $this->assertSame( + T_INLINE_ELSE, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (code)' + ); + $this->assertSame( + 'T_INLINE_ELSE', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_INLINE_ELSE (type)' + ); + + }//end testTernaryWithConstantsInThenElse() + + + /** + * Verify whether the colons are tokenized correctly in a switch statement. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testSwitchStatement() + { + $tokens = $this->phpcsFile->getTokens(); + + $label = $this->getTargetToken('/* testSwitchCaseWithConstant */', T_STRING, 'MY_CONSTANT'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'First case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'First case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $label = $this->getTargetToken('/* testSwitchCaseWithClassProperty */', T_STRING, 'property'); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Second case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Second case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + $default = $this->getTargetToken('/* testSwitchDefault */', T_DEFAULT); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($default + 1), null, true); + + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Default case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Default case: Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testSwitchStatement() + + + /** + * Verify that a variable parameter label (parse error) is still tokenized as T_VARIABLE. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testParseErrorVariableLabel() + { + $tokens = $this->phpcsFile->getTokens(); + + $label = $this->getTargetToken('/* testParseErrorDynamicName */', [T_VARIABLE, T_PARAM_NAME], '$variableStoringParamName'); + + $this->assertSame( + T_VARIABLE, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_VARIABLE (code)' + ); + $this->assertSame( + 'T_VARIABLE', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_VARIABLE (type)' + ); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testParseErrorVariableLabel() + + + /** + * Verify whether the colons are tokenized correctly when a return type is used for an inline + * closure/arrow function declaration in a ternary. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataOtherColonsInTernary + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testOtherColonsInTernary($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $startOfStatement = $this->getTargetToken($testMarker, T_VARIABLE); + + // Walk the statement and check the tokenization. + // There should be no T_PARAM_NAME tokens. + // First colon should be T_COLON for the return type. + // Second colon should be T_INLINE_ELSE for the ternary. + // Third colon should be T_COLON for the return type. + $colonCount = 0; + for ($i = ($startOfStatement + 1); $tokens[$i]['line'] === $tokens[$startOfStatement]['line']; $i++) { + $this->assertNotEquals(T_PARAM_NAME, $tokens[$i]['code'], "Token $i is tokenized as parameter label"); + + if ($tokens[$i]['content'] === ':') { + ++$colonCount; + + if ($colonCount === 1) { + $this->assertSame(T_COLON, $tokens[$i]['code'], 'First colon is not tokenized as T_COLON'); + } else if ($colonCount === 2) { + $this->assertSame(T_INLINE_ELSE, $tokens[$i]['code'], 'Second colon is not tokenized as T_INLINE_ELSE'); + } else if ($colonCount === 3) { + $this->assertSame(T_COLON, $tokens[$i]['code'], 'Third colon is not tokenized as T_COLON'); + } else { + $this->fail('Unexpected colon encountered in statement'); + } + } + } + + }//end testOtherColonsInTernary() + + + /** + * Data provider. + * + * @see testOtherColonsInTernary() + * + * @return array> + */ + public static function dataOtherColonsInTernary() + { + return [ + 'closures with return types in ternary' => [ + 'testMarker' => '/* testTernaryWithClosuresAndReturnTypes */', + ], + 'arrow functions with return types in ternary' => [ + 'testMarker' => '/* testTernaryWithArrowFunctionsAndReturnTypes */', + ], + ]; + + }//end dataOtherColonsInTernary() + + + /** + * Verify that reserved keywords used as a parameter label are tokenized as T_PARAM_NAME + * and that the colon after it is tokenized as a T_COLON. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $tokenTypes The token codes to look for. + * @param string $tokenContent The token content to look for. + * + * @dataProvider dataReservedKeywordsAsName + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testReservedKeywordsAsName($testMarker, $tokenTypes, $tokenContent) + { + $tokens = $this->phpcsFile->getTokens(); + $label = $this->getTargetToken($testMarker, $tokenTypes, $tokenContent); + + $this->assertSame( + T_PARAM_NAME, + $tokens[$label]['code'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (code)' + ); + $this->assertSame( + 'T_PARAM_NAME', + $tokens[$label]['type'], + 'Token tokenized as '.$tokens[$label]['type'].', not T_PARAM_NAME (type)' + ); + + // Get the next non-empty token. + $colon = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($label + 1), null, true); + + $this->assertSame( + ':', + $tokens[$colon]['content'], + 'Next token after parameter name is not a colon. Found: '.$tokens[$colon]['content'] + ); + $this->assertSame( + T_COLON, + $tokens[$colon]['code'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (code)' + ); + $this->assertSame( + 'T_COLON', + $tokens[$colon]['type'], + 'Token tokenized as '.$tokens[$colon]['type'].', not T_COLON (type)' + ); + + }//end testReservedKeywordsAsName() + + + /** + * Data provider. + * + * @see testReservedKeywordsAsName() + * + * @return array>> + */ + public static function dataReservedKeywordsAsName() + { + $reservedKeywords = [ + // '__halt_compiler', NOT TESTABLE + 'abstract', + 'and', + 'array', + 'as', + 'break', + 'callable', + 'case', + 'catch', + 'class', + 'clone', + 'const', + 'continue', + 'declare', + 'default', + 'die', + 'do', + 'echo', + 'else', + 'elseif', + 'empty', + 'enddeclare', + 'endfor', + 'endforeach', + 'endif', + 'endswitch', + 'endwhile', + 'enum', + 'eval', + 'exit', + 'extends', + 'final', + 'finally', + 'fn', + 'for', + 'foreach', + 'function', + 'global', + 'goto', + 'if', + 'implements', + 'include', + 'include_once', + 'instanceof', + 'insteadof', + 'interface', + 'isset', + 'list', + 'match', + 'namespace', + 'new', + 'or', + 'print', + 'private', + 'protected', + 'public', + 'readonly', + 'require', + 'require_once', + 'return', + 'static', + 'switch', + 'throw', + 'trait', + 'try', + 'unset', + 'use', + 'var', + 'while', + 'xor', + 'yield', + 'int', + 'float', + 'bool', + 'string', + 'true', + 'false', + 'null', + 'void', + 'iterable', + 'object', + 'resource', + 'mixed', + 'numeric', + 'never', + + // Not reserved keyword, but do have their own token in PHPCS. + 'parent', + 'self', + ]; + + $data = []; + + foreach ($reservedKeywords as $keyword) { + $tokensTypes = [ + T_PARAM_NAME, + T_STRING, + T_GOTO_LABEL, + ]; + $tokenName = 'T_'.strtoupper($keyword); + + if ($keyword === 'and') { + $tokensTypes[] = T_LOGICAL_AND; + } else if ($keyword === 'die') { + $tokensTypes[] = T_EXIT; + } else if ($keyword === 'or') { + $tokensTypes[] = T_LOGICAL_OR; + } else if ($keyword === 'xor') { + $tokensTypes[] = T_LOGICAL_XOR; + } else if ($keyword === '__halt_compiler') { + $tokensTypes[] = T_HALT_COMPILER; + } else if (defined($tokenName) === true) { + $tokensTypes[] = constant($tokenName); + } + + $data[$keyword.'FirstParam'] = [ + '/* testReservedKeyword'.ucfirst($keyword).'1 */', + $tokensTypes, + $keyword, + ]; + + $data[$keyword.'SecondParam'] = [ + '/* testReservedKeyword'.ucfirst($keyword).'2 */', + $tokensTypes, + $keyword, + ]; + }//end foreach + + return $data; + + }//end dataReservedKeywordsAsName() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.inc new file mode 100644 index 000000000..982841eac --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.inc @@ -0,0 +1,29 @@ +foo; + +/* testNullsafeObjectOperator */ +echo $obj?->foo; + +/* testNullsafeObjectOperatorWriteContext */ +// Intentional parse error, but not the concern of the tokenizer. +$foo?->bar->baz = 'baz'; + +/* testTernaryThen */ +echo $obj ? $obj->prop : $other->prop; + +/* testParseErrorWhitespaceNotAllowed */ +echo $obj ? + -> foo; + +/* testParseErrorCommentNotAllowed */ +echo $obj ?/*comment*/-> foo; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +echo $obj? diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.php new file mode 100644 index 000000000..368fee4db --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/NullsafeObjectOperatorTest.php @@ -0,0 +1,144 @@ += 8.0 nullsafe object operator. + * + * @author Juliette Reinders Folmer + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class NullsafeObjectOperatorTest extends AbstractTokenizerTestCase +{ + + /** + * Tokens to search for. + * + * @var array + */ + protected $find = [ + T_NULLSAFE_OBJECT_OPERATOR, + T_OBJECT_OPERATOR, + T_INLINE_THEN, + ]; + + + /** + * Test that a normal object operator is still tokenized as such. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testObjectOperator() + { + $tokens = $this->phpcsFile->getTokens(); + + $operator = $this->getTargetToken('/* testObjectOperator */', $this->find); + $this->assertSame(T_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is object operator'); + $this->assertSame('T_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is object operator'); + + }//end testObjectOperator() + + + /** + * Test that a nullsafe object operator is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNullsafeObjectOperator + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testNullsafeObjectOperator($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $operator = $this->getTargetToken($testMarker, $this->find); + $this->assertSame(T_NULLSAFE_OBJECT_OPERATOR, $tokens[$operator]['code'], 'Failed asserting code is nullsafe object operator'); + $this->assertSame('T_NULLSAFE_OBJECT_OPERATOR', $tokens[$operator]['type'], 'Failed asserting type is nullsafe object operator'); + + }//end testNullsafeObjectOperator() + + + /** + * Data provider. + * + * @see testNullsafeObjectOperator() + * + * @return array> + */ + public static function dataNullsafeObjectOperator() + { + return [ + 'nullsafe operator' => ['/* testNullsafeObjectOperator */'], + 'illegal nullsafe operator (write context)' => ['/* testNullsafeObjectOperatorWriteContext */'], + ]; + + }//end dataNullsafeObjectOperator() + + + /** + * Test that a question mark not followed by an object operator is tokenized as T_TERNARY_THEN. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param bool $testObjectOperator Whether to test for the next non-empty token being tokenized + * as an object operator. + * + * @dataProvider dataTernaryThen + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryThen($testMarker, $testObjectOperator=false) + { + $tokens = $this->phpcsFile->getTokens(); + + $operator = $this->getTargetToken($testMarker, $this->find); + $this->assertSame(T_INLINE_THEN, $tokens[$operator]['code'], 'Failed asserting code is inline then'); + $this->assertSame('T_INLINE_THEN', $tokens[$operator]['type'], 'Failed asserting type is inline then'); + + if ($testObjectOperator === true) { + $next = $this->phpcsFile->findNext(Tokens::$emptyTokens, ($operator + 1), null, true); + $this->assertSame(T_OBJECT_OPERATOR, $tokens[$next]['code'], 'Failed asserting code is object operator'); + $this->assertSame('T_OBJECT_OPERATOR', $tokens[$next]['type'], 'Failed asserting type is object operator'); + } + + }//end testTernaryThen() + + + /** + * Data provider. + * + * @see testTernaryThen() + * + * @return array> + */ + public static function dataTernaryThen() + { + return [ + 'ternary then' => [ + 'testMarker' => '/* testTernaryThen */', + ], + 'whitespace between question mark and object operator' => [ + 'testMarker' => '/* testParseErrorWhitespaceNotAllowed */', + 'testObjectOperator' => true, + ], + 'comment between question mark and object operator' => [ + 'testMarker' => '/* testParseErrorCommentNotAllowed */', + 'testObjectOperator' => true, + ], + 'parse error/live coding' => [ + 'testMarker' => '/* testLiveCoding */', + ], + ]; + + }//end dataTernaryThen() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.inc new file mode 100644 index 000000000..ef89caaea --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.inc @@ -0,0 +1,247 @@ + $param->get(); + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.php new file mode 100644 index 000000000..872fab0d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/OtherContextSensitiveKeywordsTest.php @@ -0,0 +1,721 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +/** + * Tests the conversion of PHPCS native context sensitive keyword tokens to T_STRING. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::standardiseToken + */ +final class OtherContextSensitiveKeywordsTest extends AbstractTokenizerTestCase +{ + + + /** + * Clear the "resolved tokens" cache before running this test as otherwise the code + * under test may not be run during the test. + * + * @beforeClass + * + * @return void + */ + public static function clearTokenCache() + { + parent::clearResolvedTokensCache(); + + }//end clearTokenCache() + + + /** + * Test that context sensitive keyword is tokenized as string when it should be string. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataStrings + * + * @return void + */ + public function testStrings($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_STRING, T_NULL, T_FALSE, T_TRUE, T_PARENT, T_SELF]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testStrings() + + + /** + * Data provider. + * + * @see testStrings() + * + * @return array> + */ + public static function dataStrings() + { + return [ + 'constant declaration: parent' => ['/* testParent */'], + 'constant declaration: self' => ['/* testSelf */'], + 'constant declaration: false' => ['/* testFalse */'], + 'constant declaration: true' => ['/* testTrue */'], + 'constant declaration: null' => ['/* testNull */'], + + 'function declaration with return by ref: self' => ['/* testKeywordSelfAfterFunctionByRefShouldBeString */'], + 'function declaration with return by ref: parent' => ['/* testKeywordParentAfterFunctionByRefShouldBeString */'], + 'function declaration with return by ref: false' => ['/* testKeywordFalseAfterFunctionByRefShouldBeString */'], + 'function declaration with return by ref: true' => ['/* testKeywordTrueAfterFunctionByRefShouldBeString */'], + 'function declaration with return by ref: null' => ['/* testKeywordNullAfterFunctionByRefShouldBeString */'], + + 'function call: self' => ['/* testKeywordAsFunctionCallNameShouldBeStringSelf */'], + 'function call: parent' => ['/* testKeywordAsFunctionCallNameShouldBeStringParent */'], + 'function call: false' => ['/* testKeywordAsFunctionCallNameShouldBeStringFalse */'], + 'function call: true' => ['/* testKeywordAsFunctionCallNameShouldBeStringTrue */'], + 'function call: null; with comment between keyword and parentheses' => ['/* testKeywordAsFunctionCallNameShouldBeStringNull */'], + + 'class instantiation: false' => ['/* testClassInstantiationFalseIsString */'], + 'class instantiation: true' => ['/* testClassInstantiationTrueIsString */'], + 'class instantiation: null' => ['/* testClassInstantiationNullIsString */'], + + 'constant declaration: false as name after type' => ['/* testFalseIsNameForTypedConstant */'], + 'constant declaration: true as name after type' => ['/* testTrueIsNameForTypedConstant */'], + 'constant declaration: null as name after type' => ['/* testNullIsNameForTypedConstant */'], + 'constant declaration: self as name after type' => ['/* testSelfIsNameForTypedConstant */'], + 'constant declaration: parent as name after type' => ['/* testParentIsNameForTypedConstant */'], + ]; + + }//end dataStrings() + + + /** + * Test that context sensitive keyword is tokenized as keyword when it should be keyword. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedTokenType The expected token type. + * + * @dataProvider dataKeywords + * + * @return void + */ + public function testKeywords($testMarker, $expectedTokenType) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_STRING, T_NULL, T_FALSE, T_TRUE, T_PARENT, T_SELF]); + $tokenArray = $tokens[$target]; + + $this->assertSame( + constant($expectedTokenType), + $tokenArray['code'], + 'Token tokenized as '.$tokenArray['type'].', not '.$expectedTokenType.' (code)' + ); + $this->assertSame( + $expectedTokenType, + $tokenArray['type'], + 'Token tokenized as '.$tokenArray['type'].', not '.$expectedTokenType.' (type)' + ); + + }//end testKeywords() + + + /** + * Data provider. + * + * @see testKeywords() + * + * @return array + */ + public static function dataKeywords() + { + return [ + 'self: param type declaration' => [ + 'testMarker' => '/* testSelfIsKeyword */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: param type declaration' => [ + 'testMarker' => '/* testParentIsKeyword */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'parent: class instantiation' => [ + 'testMarker' => '/* testClassInstantiationParentIsKeyword */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: class instantiation' => [ + 'testMarker' => '/* testClassInstantiationSelfIsKeyword */', + 'expectedTokenType' => 'T_SELF', + ], + + 'false: param type declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsParamType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: param type declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsParamType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: param type declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsParamType */', + 'expectedTokenType' => 'T_NULL', + ], + 'false: return type declaration in union' => [ + 'testMarker' => '/* testFalseIsKeywordAsReturnType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: return type declaration in union' => [ + 'testMarker' => '/* testTrueIsKeywordAsReturnType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: return type declaration in union' => [ + 'testMarker' => '/* testNullIsKeywordAsReturnType */', + 'expectedTokenType' => 'T_NULL', + ], + 'false: in comparison' => [ + 'testMarker' => '/* testFalseIsKeywordInComparison */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: in comparison' => [ + 'testMarker' => '/* testTrueIsKeywordInComparison */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: in comparison' => [ + 'testMarker' => '/* testNullIsKeywordInComparison */', + 'expectedTokenType' => 'T_NULL', + ], + + 'false: type in OO constant declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: type in OO constant declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: type in OO constant declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstType */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: type in OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstType */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: type in OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstType */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: value in constant declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstDefault */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: value in constant declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstDefault */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: value in constant declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstDefault */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: value in constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstDefault */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: value in constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstDefault */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: type in property declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsPropertyType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: type in property declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsPropertyType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: type in property declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsPropertyType */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: type in property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyType */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: type in property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyType */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: value in property declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsPropertyDefault */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: value in property declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsPropertyDefault */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: value in property declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsPropertyDefault */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: value in property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyDefault */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: value in property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyDefault */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: first in union type for OO constant declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstUnionTypeFirst */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: first in union type for OO constant declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstUnionTypeFirst */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: first in union type for OO constant declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstUnionTypeFirst */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: first in union type for OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstUnionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in union type for OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstUnionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: middle in union type for OO constant declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstUnionTypeMiddle */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: middle in union type for OO constant declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstUnionTypeMiddle */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: middle in union type for OO constant declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstUnionTypeMiddle */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: middle in union type for OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstUnionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in union type for OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstUnionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: last in union type for OO constant declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstUnionTypeLast */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: last in union type for OO constant declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstUnionTypeLast */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: last in union type for OO constant declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstUnionTypeLast */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: last in union type for OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstUnionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in union type for OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstUnionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: first in union type for property declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsPropertyUnionTypeFirst */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: first in union type for property declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsPropertyUnionTypeFirst */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: first in union type for property declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsPropertyUnionTypeFirst */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: first in union type for property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyUnionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in union type for property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyUnionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: middle in union type for property declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsPropertyUnionTypeMiddle */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: middle in union type for property declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsPropertyUnionTypeMiddle */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: middle in union type for property declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsPropertyUnionTypeMiddle */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: middle in union type for property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyUnionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in union type for property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyUnionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: last in union type for property declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsPropertyUnionTypeLast */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: last in union type for property declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsPropertyUnionTypeLast */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: last in union type for property declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsPropertyUnionTypeLast */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: last in union type for property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyUnionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in union type for property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyUnionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: first in union type for param declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsParamUnionTypeFirst */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: first in union type for param declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsParamUnionTypeFirst */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: first in union type for param declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsParamUnionTypeFirst */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: first in union type for param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamUnionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in union type for param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamUnionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: middle in union type for param declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsParamUnionTypeMiddle */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: middle in union type for param declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsParamUnionTypeMiddle */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: middle in union type for param declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsParamUnionTypeMiddle */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: middle in union type for param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamUnionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in union type for param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamUnionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: last in union type for param declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsParamUnionTypeLast */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: last in union type for param declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsParamUnionTypeLast */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: last in union type for param declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsParamUnionTypeLast */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: last in union type for param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamUnionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in union type for param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamUnionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: first in union type for return declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsReturnUnionTypeFirst */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: first in union type for return declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsReturnUnionTypeFirst */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: first in union type for return declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsReturnUnionTypeFirst */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: first in union type for return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnUnionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in union type for return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnUnionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: middle in union type for return declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsReturnUnionTypeMiddle */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: middle in union type for return declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsReturnUnionTypeMiddle */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: middle in union type for return declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsReturnUnionTypeMiddle */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: middle in union type for return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnUnionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in union type for return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnUnionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: last in union type for return declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsReturnUnionTypeLast */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: last in union type for return declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsReturnUnionTypeLast */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: last in union type for return declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsReturnUnionTypeLast */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: last in union type for return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnUnionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in union type for return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnUnionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'self: first in intersection type for OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstIntersectionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in intersection type for OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstIntersectionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: middle in intersection type for OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in intersection type for OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: last in intersection type for OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstIntersectionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in intersection type for OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstIntersectionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'self: first in intersection type for property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyIntersectionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in intersection type for property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyIntersectionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: middle in intersection type for property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in intersection type for property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: last in intersection type for property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsPropertyIntersectionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in intersection type for property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsPropertyIntersectionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'self: first in intersection type for param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamIntersectionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in intersection type for param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamIntersectionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: middle in intersection type for param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in intersection type for param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: last in intersection type for param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamIntersectionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in intersection type for param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamIntersectionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'self: first in intersection type for return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnIntersectionTypeFirst */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: first in intersection type for return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnIntersectionTypeFirst */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: middle in intersection type for return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: middle in intersection type for return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnIntersectionTypeMiddle */', + 'expectedTokenType' => 'T_PARENT', + ], + 'self: last in intersection type for return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnIntersectionTypeLast */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: last in intersection type for return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnIntersectionTypeLast */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: DNF type in OO constant declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: DNF type in OO constant declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: DNF type in OO constant declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: DNF type in OO constant declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: DNF type in OO constant declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: DNF type in property declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: DNF type in property declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: DNF type in property declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: DNF type in property declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: DNF type in property declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsConstDNFType */', + 'expectedTokenType' => 'T_PARENT', + ], + + 'false: DNF type in function param declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsParamDNFType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'false: DNF type in function return declaration' => [ + 'testMarker' => '/* testFalseIsKeywordAsReturnDNFType */', + 'expectedTokenType' => 'T_FALSE', + ], + 'true: DNF type in function param declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsParamDNFType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'true: DNF type in function return declaration' => [ + 'testMarker' => '/* testTrueIsKeywordAsReturnDNFType */', + 'expectedTokenType' => 'T_TRUE', + ], + 'null: DNF type in function param declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsParamDNFType */', + 'expectedTokenType' => 'T_NULL', + ], + 'null: DNF type in function return declaration' => [ + 'testMarker' => '/* testNullIsKeywordAsReturnDNFType */', + 'expectedTokenType' => 'T_NULL', + ], + 'self: DNF type in function param declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsParamDNFType */', + 'expectedTokenType' => 'T_SELF', + ], + 'self: DNF type in function return declaration' => [ + 'testMarker' => '/* testSelfIsKeywordAsReturnDNFType */', + 'expectedTokenType' => 'T_SELF', + ], + 'parent: DNF type in function param declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsParamDNFType */', + 'expectedTokenType' => 'T_PARENT', + ], + 'parent: DNF type in function return declaration' => [ + 'testMarker' => '/* testParentIsKeywordAsReturnDNFType */', + 'expectedTokenType' => 'T_PARENT', + ], + + ]; + + }//end dataKeywords() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.inc new file mode 100644 index 000000000..d7383d8e6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.inc @@ -0,0 +1,51 @@ + $var; + +/* testBooleanNot */ +$a = ! $var; + +/* testComma */ +echo $a, $b, $c; + +/* testAsperand */ +$a = @callMe(); + +/* testDollarAndCurlies */ +echo ${$var}; + +/* testBacktick */ +$a = `ls -e`; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.php new file mode 100644 index 000000000..06a130c24 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ResolveSimpleTokenTest.php @@ -0,0 +1,433 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Tests that simple tokens are assigned the correct token type and code. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::resolveSimpleToken + */ +final class ResolveSimpleTokenTest extends AbstractTokenizerTestCase +{ + + + /** + * Clear the "resolved tokens" cache before running this test as otherwise the code + * under test may not be run during the test. + * + * @beforeClass + * + * @return void + */ + public static function clearTokenCache() + { + parent::clearResolvedTokensCache(); + + }//end clearTokenCache() + + + /** + * Verify tokenization of parentheses, square brackets, curly brackets and a switch colon. + * + * @return void + */ + public function testBracesAndColon() + { + $expectedSequence = [ + T_OPEN_PARENTHESIS, + T_VARIABLE, + T_OPEN_SQUARE_BRACKET, + T_LNUMBER, + T_CLOSE_SQUARE_BRACKET, + T_CLOSE_PARENTHESIS, + T_OPEN_CURLY_BRACKET, + T_CASE, + T_STRING, + T_COLON, + T_BREAK, + T_SEMICOLON, + T_CLOSE_CURLY_BRACKET, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_SWITCH); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testBracesAndColon() + + + /** + * Verify tokenization of colon after named parameter. + * + * @return void + */ + public function testNamedParamColon() + { + $expectedSequence = [ + T_OPEN_PARENTHESIS, + T_PARAM_NAME, + T_COLON, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_STRING); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testNamedParamColon() + + + /** + * Verify tokenization of colon for a return type. + * + * @return void + */ + public function testReturnTypeColon() + { + $expectedSequence = [ + T_EQUAL, + T_CLOSURE, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_COLON, + T_STRING, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_VARIABLE); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testReturnTypeColon() + + + /** + * Verify tokenization of a concatenation operator. + * + * @return void + */ + public function testConcat() + { + $expectedSequence = [ + T_STRING_CONCAT, + T_VARIABLE, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_CONSTANT_ENCAPSED_STRING); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testConcat() + + + /** + * Verify tokenization of simple math operators. + * + * @return void + */ + public function testSimpleMathTokens() + { + $expectedSequence = [ + T_EQUAL, + T_LNUMBER, + T_MULTIPLY, + T_LNUMBER, + T_DIVIDE, + T_LNUMBER, + T_PLUS, + T_LNUMBER, + T_MINUS, + T_LNUMBER, + T_MODULUS, + T_LNUMBER, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_VARIABLE); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testSimpleMathTokens() + + + /** + * Verify tokenization of unary plus/minus operators. + * + * @return void + */ + public function testUnaryPlusMinus() + { + $expectedSequence = [ + T_EQUAL, + T_PLUS, + T_LNUMBER, + T_DIVIDE, + T_MINUS, + T_LNUMBER, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_VARIABLE); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testUnaryPlusMinus() + + + /** + * Verify tokenization of bitwise operator tokens. + * + * @return void + */ + public function testBitwiseTokens() + { + $expectedSequence = [ + T_EQUAL, + T_STRING, + T_BITWISE_XOR, + T_STRING, + T_BITWISE_AND, + T_STRING, + T_BITWISE_OR, + T_STRING, + T_BITWISE_NOT, + T_STRING, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_VARIABLE); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testBitwiseTokens() + + + /** + * Verify tokenization of bitwise operator tokens. + * + * @return void + */ + public function testBitwiseOrInCatch() + { + $expectedSequence = [ + T_OPEN_PARENTHESIS, + T_STRING, + T_BITWISE_OR, + T_STRING, + T_VARIABLE, + T_CLOSE_PARENTHESIS, + T_OPEN_CURLY_BRACKET, + T_CLOSE_CURLY_BRACKET, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_CATCH); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testBitwiseOrInCatch() + + + /** + * Verify tokenization of a less than operator. + * + * @return void + */ + public function testLessThan() + { + $expectedSequence = [ + T_LESS_THAN, + T_VARIABLE, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_LNUMBER); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testLessThan() + + + /** + * Verify tokenization of a greater than operator. + * + * @return void + */ + public function testGreaterThan() + { + $expectedSequence = [ + T_GREATER_THAN, + T_VARIABLE, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_LNUMBER); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testGreaterThan() + + + /** + * Verify tokenization of a boolean not operator. + * + * @return void + */ + public function testBooleanNot() + { + $expectedSequence = [ + T_BOOLEAN_NOT, + T_VARIABLE, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_EQUAL); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testBooleanNot() + + + /** + * Verify tokenization of commas. + * + * @return void + */ + public function testComma() + { + $expectedSequence = [ + T_COMMA, + T_VARIABLE, + T_COMMA, + T_VARIABLE, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_VARIABLE); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testComma() + + + /** + * Verify tokenization of the silence operator. + * + * @return void + */ + public function testAsperand() + { + $expectedSequence = [ + T_ASPERAND, + T_STRING, + T_OPEN_PARENTHESIS, + T_CLOSE_PARENTHESIS, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_EQUAL); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testAsperand() + + + /** + * Verify tokenization of the dollar token and curlies for a variable variable. + * + * @return void + */ + public function testDollarAndCurlies() + { + $expectedSequence = [ + T_DOLLAR, + T_OPEN_CURLY_BRACKET, + T_VARIABLE, + T_CLOSE_CURLY_BRACKET, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_ECHO); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testDollarAndCurlies() + + + /** + * Verify tokenization of the backtick operator. + * + * @return void + */ + public function testBacktick() + { + $expectedSequence = [ + T_BACKTICK, + T_ENCAPSED_AND_WHITESPACE, + T_BACKTICK, + T_SEMICOLON, + ]; + + $target = $this->getTargetToken('/* '.__FUNCTION__.' */', T_EQUAL); + + $this->checkTokenSequence(($target + 1), $expectedSequence); + + }//end testBacktick() + + + /** + * Test helper. Check a token sequence complies with an expected token sequence. + * + * @param int $startPtr The position in the file to start checking from. + * @param array $expectedSequence The consecutive token constants to expect. + * + * @return void + */ + private function checkTokenSequence($startPtr, array $expectedSequence) + { + $tokens = $this->phpcsFile->getTokens(); + + $sequenceKey = 0; + $sequenceCount = count($expectedSequence); + + for ($i = $startPtr; $sequenceKey < $sequenceCount; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + // Ignore whitespace and comments, not interested in the tokenization of those for these tests. + continue; + } + + $expectedTokenName = Tokens::tokenName($expectedSequence[$sequenceKey]); + + $this->assertSame( + $expectedSequence[$sequenceKey], + $tokens[$i]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$i]['code']).', not '.$expectedTokenName.' (code)' + ); + + $this->assertSame( + $expectedTokenName, + $tokens[$i]['type'], + 'Token tokenized as '.$tokens[$i]['type'].', not '.$expectedTokenName.' (type)' + ); + + ++$sequenceKey; + }//end for + + }//end checkTokenSequence() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.inc new file mode 100644 index 000000000..60b23a51c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.inc @@ -0,0 +1,111 @@ +function_call()[$x]; + +/* testStaticMethodCallDereferencing */ +$var = ClassName::function_call()[$x]; + +/* testPropertyDereferencing */ +$var = $obj->property[2]; + +/* testPropertyDereferencingWithInaccessibleName */ +$var = $ref->{'ref-type'}[1]; + +/* testStaticPropertyDereferencing */ +$var ClassName::$property[2]; + +/* testStringDereferencing */ +$var = 'PHP'[1]; + +/* testStringDereferencingDoubleQuoted */ +$var = "PHP"[$y]; + +/* testConstantDereferencing */ +$var = MY_CONSTANT[1]; + +/* testClassConstantDereferencing */ +$var ClassName::CONSTANT_NAME[2]; + +/* testMagicConstantDereferencing */ +$var = __FILE__[0]; + +/* testArrayAccessCurlyBraces */ +$var = $array{'key'}['key']; + +/* testArrayLiteralDereferencing */ +echo array(1, 2, 3)[0]; + +echo [1, 2, 3]/* testShortArrayLiteralDereferencing */[0]; + +/* testClassMemberDereferencingOnInstantiation1 */ +(new foo)[0]; + +/* testClassMemberDereferencingOnInstantiation2 */ +$a = (new Foo( array(1, array(4, 5), 3) ))[1][0]; + +/* testClassMemberDereferencingOnClone */ +echo (clone $iterable)[20]; + +/* testNullsafeMethodCallDereferencing */ +$var = $obj?->function_call()[$x]; + +/* testInterpolatedStringDereferencing */ +$var = "PHP{$rocks}"[1]; + +/* + * Short array brackets. + */ + +/* testShortArrayDeclarationEmpty */ +$array = []; + +/* testShortArrayDeclarationWithOneValue */ +$array = [1]; + +/* testShortArrayDeclarationWithMultipleValues */ +$array = [1, 2, 3]; + +/* testShortArrayDeclarationWithDereferencing */ +echo [1, 2, 3][0]; + +/* testShortListDeclaration */ +[ $a, $b ] = $array; + +[ $a, $b, /* testNestedListDeclaration */, [$c, $d]] = $array; + +/* testArrayWithinFunctionCall */ +$var = functionCall([$x, $y]); + +if ( true ) { + /* testShortListDeclarationAfterBracedControlStructure */ + [ $a ] = [ 'hi' ]; +} + +if ( true ) + /* testShortListDeclarationAfterNonBracedControlStructure */ + [ $a ] = [ 'hi' ]; + +if ( true ) : + /* testShortListDeclarationAfterAlternativeControlStructure */ + [ $a ] = [ 'hi' ]; +endif; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +$array = [ diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.php new file mode 100644 index 000000000..da9c7c104 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/ShortArrayTest.php @@ -0,0 +1,141 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class ShortArrayTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that real square brackets are still tokenized as square brackets. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataSquareBrackets + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testSquareBrackets($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]); + $tokenArray = $tokens[$opener]; + + $this->assertSame(T_OPEN_SQUARE_BRACKET, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_OPEN_SQUARE_BRACKET (code)'); + $this->assertSame('T_OPEN_SQUARE_BRACKET', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_OPEN_SQUARE_BRACKET (type)'); + + if (isset($tokens[$opener]['bracket_closer']) === true) { + $closer = $tokens[$opener]['bracket_closer']; + $tokenArray = $tokens[$closer]; + + $this->assertSame(T_CLOSE_SQUARE_BRACKET, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CLOSE_SQUARE_BRACKET (code)'); + $this->assertSame('T_CLOSE_SQUARE_BRACKET', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_CLOSE_SQUARE_BRACKET (type)'); + } + + }//end testSquareBrackets() + + + /** + * Data provider. + * + * @see testSquareBrackets() + * + * @return array> + */ + public static function dataSquareBrackets() + { + return [ + 'array access 1' => ['/* testArrayAccess1 */'], + 'array access 2' => ['/* testArrayAccess2 */'], + 'array assignment' => ['/* testArrayAssignment */'], + 'function call dereferencing' => ['/* testFunctionCallDereferencing */'], + 'method call dereferencing' => ['/* testMethodCallDereferencing */'], + 'static method call dereferencing' => ['/* testStaticMethodCallDereferencing */'], + 'property dereferencing' => ['/* testPropertyDereferencing */'], + 'property dereferencing with inaccessable name' => ['/* testPropertyDereferencingWithInaccessibleName */'], + 'static property dereferencing' => ['/* testStaticPropertyDereferencing */'], + 'string dereferencing single quotes' => ['/* testStringDereferencing */'], + 'string dereferencing double quotes' => ['/* testStringDereferencingDoubleQuoted */'], + 'global constant dereferencing' => ['/* testConstantDereferencing */'], + 'class constant dereferencing' => ['/* testClassConstantDereferencing */'], + 'magic constant dereferencing' => ['/* testMagicConstantDereferencing */'], + 'array access with curly braces' => ['/* testArrayAccessCurlyBraces */'], + 'array literal dereferencing' => ['/* testArrayLiteralDereferencing */'], + 'short array literal dereferencing' => ['/* testShortArrayLiteralDereferencing */'], + 'class member dereferencing on instantiation 1' => ['/* testClassMemberDereferencingOnInstantiation1 */'], + 'class member dereferencing on instantiation 2' => ['/* testClassMemberDereferencingOnInstantiation2 */'], + 'class member dereferencing on clone' => ['/* testClassMemberDereferencingOnClone */'], + 'nullsafe method call dereferencing' => ['/* testNullsafeMethodCallDereferencing */'], + 'interpolated string dereferencing' => ['/* testInterpolatedStringDereferencing */'], + 'live coding' => ['/* testLiveCoding */'], + ]; + + }//end dataSquareBrackets() + + + /** + * Test that short arrays and short lists are still tokenized as short arrays. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataShortArrays + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testShortArrays($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $opener = $this->getTargetToken($testMarker, [T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY]); + $tokenArray = $tokens[$opener]; + + $this->assertSame(T_OPEN_SHORT_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_OPEN_SHORT_ARRAY (code)'); + $this->assertSame('T_OPEN_SHORT_ARRAY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_OPEN_SHORT_ARRAY (type)'); + + if (isset($tokens[$opener]['bracket_closer']) === true) { + $closer = $tokens[$opener]['bracket_closer']; + $tokenArray = $tokens[$closer]; + + $this->assertSame(T_CLOSE_SHORT_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CLOSE_SHORT_ARRAY (code)'); + $this->assertSame('T_CLOSE_SHORT_ARRAY', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_CLOSE_SHORT_ARRAY (type)'); + } + + }//end testShortArrays() + + + /** + * Data provider. + * + * @see testShortArrays() + * + * @return array> + */ + public static function dataShortArrays() + { + return [ + 'short array empty' => ['/* testShortArrayDeclarationEmpty */'], + 'short array with value' => ['/* testShortArrayDeclarationWithOneValue */'], + 'short array with values' => ['/* testShortArrayDeclarationWithMultipleValues */'], + 'short array with dereferencing' => ['/* testShortArrayDeclarationWithDereferencing */'], + 'short list' => ['/* testShortListDeclaration */'], + 'short list nested' => ['/* testNestedListDeclaration */'], + 'short array within function call' => ['/* testArrayWithinFunctionCall */'], + 'short list after braced control structure' => ['/* testShortListDeclarationAfterBracedControlStructure */'], + 'short list after non-braced control structure' => ['/* testShortListDeclarationAfterNonBracedControlStructure */'], + 'short list after alternative control structure' => ['/* testShortListDeclarationAfterAlternativeControlStructure */'], + ]; + + }//end dataShortArrays() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceTest.inc new file mode 100644 index 000000000..3bf013c66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceTest.inc @@ -0,0 +1,139 @@ + + + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class StableCommentWhitespaceTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that comment tokenization with new lines at the end of the comment is stable. + * + * @param string $testMarker The comment prefacing the test. + * @param array> $expectedTokens The tokenization expected. + * + * @dataProvider dataCommentTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testCommentTokenization($testMarker, $expectedTokens) + { + $tokens = $this->phpcsFile->getTokens(); + $comment = $this->getTargetToken($testMarker, Tokens::$commentTokens); + + foreach ($expectedTokens as $tokenInfo) { + $this->assertSame( + constant($tokenInfo['type']), + $tokens[$comment]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$comment]['code']).', not '.$tokenInfo['type'].' (code)' + ); + $this->assertSame( + $tokenInfo['type'], + $tokens[$comment]['type'], + 'Token tokenized as '.$tokens[$comment]['type'].', not '.$tokenInfo['type'].' (type)' + ); + $this->assertSame($tokenInfo['content'], $tokens[$comment]['content']); + + ++$comment; + } + + }//end testCommentTokenization() + + + /** + * Data provider. + * + * @see testCommentTokenization() + * + * @return array>>> + */ + public static function dataCommentTokenization() + { + return [ + 'slash comment, single line' => [ + 'testMarker' => '/* testSingleLineSlashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, single line, trailing' => [ + 'testMarker' => '/* testSingleLineSlashCommentTrailing */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash ignore annotation, single line' => [ + 'testMarker' => '/* testSingleLineSlashAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// phpcs:disable Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line' => [ + 'testMarker' => '/* testMultiLineSlashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, indented' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithIndent */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, ignore annotation as first line' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithAnnotationStart */', + 'expectedTokens' => [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, ignore annotation as middle line' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithAnnotationMiddle */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, ignore annotation as last line' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithAnnotationEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, single line' => [ + 'testMarker' => '/* testSingleLineStarComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Single line star comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, single line, trailing' => [ + 'testMarker' => '/* testSingleLineStarCommentTrailing */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star ignore annotation, single line' => [ + 'testMarker' => '/* testSingleLineStarAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '/* phpcs:ignore Stnd.Cat */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, multi-line' => [ + 'testMarker' => '/* testMultiLineStarComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, multi-line, indented' => [ + 'testMarker' => '/* testMultiLineStarCommentWithIndent */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, multi-line, ignore annotation as first line' => [ + 'testMarker' => '/* testMultiLineStarCommentWithAnnotationStart */', + 'expectedTokens' => [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '/* @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, multi-line, ignore annotation as middle line' => [ + 'testMarker' => '/* testMultiLineStarCommentWithAnnotationMiddle */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => ' * phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment3 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'star comment, multi-line, ignore annotation as last line' => [ + 'testMarker' => '/* testMultiLineStarCommentWithAnnotationEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' * Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => ' * phpcs:ignore Stnd.Cat */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + + 'docblock comment, single line' => [ + 'testMarker' => '/* testSingleLineDocblockComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'docblock comment, single line, trailing' => [ + 'testMarker' => '/* testSingleLineDocblockCommentTrailing */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'docblock ignore annotation, single line' => [ + 'testMarker' => '/* testSingleLineDocblockAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => 'phpcs:ignore Stnd.Cat.Sniff ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + + 'docblock comment, multi-line' => [ + 'testMarker' => '/* testMultiLineDocblockComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment1', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment2', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'docblock comment, multi-line, indented' => [ + 'testMarker' => '/* testMultiLineDocblockCommentWithIndent */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment1', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment2', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'docblock comment, multi-line, ignore annotation' => [ + 'testMarker' => '/* testMultiLineDocblockCommentWithAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => 'phpcs:ignore Stnd.Cat', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'docblock comment, multi-line, ignore annotation as tag' => [ + 'testMarker' => '/* testMultiLineDocblockCommentWithTagAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_DOC_COMMENT_OPEN_TAG', + 'content' => '/**', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '@phpcs:ignore Stnd.Cat', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STAR', + 'content' => '*', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_TAG', + 'content' => '@tag', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_STRING', + 'content' => 'Comment', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_DOC_COMMENT_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_DOC_COMMENT_CLOSE_TAG', + 'content' => '*/', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, single line' => [ + 'testMarker' => '/* testSingleLineHashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, single line, trailing' => [ + 'testMarker' => '/* testSingleLineHashCommentTrailing */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, multi-line' => [ + 'testMarker' => '/* testMultiLineHashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, multi-line, indented' => [ + 'testMarker' => '/* testMultiLineHashCommentWithIndent */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, single line, without new line at end' => [ + 'testMarker' => '/* testSingleLineSlashCommentNoNewLineAtEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Slash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + 'hash comment, single line, without new line at end' => [ + 'testMarker' => '/* testSingleLineHashCommentNoNewLineAtEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Hash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + 'unclosed star comment at end of file' => [ + 'testMarker' => '/* testCommentAtEndOfFile */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment', + ], + ], + ], + ]; + + }//end dataCommentTokenization() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceWinTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceWinTest.inc new file mode 100644 index 000000000..dc98eb018 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/StableCommentWhitespaceWinTest.inc @@ -0,0 +1,63 @@ + + + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class StableCommentWhitespaceWinTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that comment tokenization with new lines at the end of the comment is stable. + * + * @param string $testMarker The comment prefacing the test. + * @param array> $expectedTokens The tokenization expected. + * + * @dataProvider dataCommentTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testCommentTokenization($testMarker, $expectedTokens) + { + $tokens = $this->phpcsFile->getTokens(); + $comment = $this->getTargetToken($testMarker, Tokens::$commentTokens); + + foreach ($expectedTokens as $tokenInfo) { + $this->assertSame( + constant($tokenInfo['type']), + $tokens[$comment]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$comment]['code']).', not '.$tokenInfo['type'].' (code)' + ); + $this->assertSame( + $tokenInfo['type'], + $tokens[$comment]['type'], + 'Token tokenized as '.$tokens[$comment]['type'].', not '.$tokenInfo['type'].' (type)' + ); + $this->assertSame($tokenInfo['content'], $tokens[$comment]['content']); + + ++$comment; + } + + }//end testCommentTokenization() + + + /** + * Data provider. + * + * @see testCommentTokenization() + * + * @return array>>> + */ + public static function dataCommentTokenization() + { + return [ + 'slash comment, single line' => [ + 'testMarker' => '/* testSingleLineSlashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, single line, trailing' => [ + 'testMarker' => '/* testSingleLineSlashCommentTrailing */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash ignore annotation, single line' => [ + 'testMarker' => '/* testSingleLineSlashAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// phpcs:disable Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line' => [ + 'testMarker' => '/* testMultiLineSlashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, indented' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithIndent */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, ignore annotation as first line' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithAnnotationStart */', + 'expectedTokens' => [ + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, ignore annotation as middle line' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithAnnotationMiddle */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// @phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, multi-line, ignore annotation as last line' => [ + 'testMarker' => '/* testMultiLineSlashCommentWithAnnotationEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// Comment2 +', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'slash comment, single line, without new line at end' => [ + 'testMarker' => '/* testSingleLineSlashCommentNoNewLineAtEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '// Slash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + 'hash comment, single line' => [ + 'testMarker' => '/* testSingleLineHashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, single line, trailing' => [ + 'testMarker' => '/* testSingleLineHashCommentTrailing */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, multi-line' => [ + 'testMarker' => '/* testMultiLineHashComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, multi-line, indented' => [ + 'testMarker' => '/* testMultiLineHashCommentWithIndent */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment1 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment2 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '# Comment3 +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'hash comment, single line, without new line at end' => [ + 'testMarker' => '/* testSingleLineHashCommentNoNewLineAtEnd */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '# Hash ', + ], + [ + 'type' => 'T_CLOSE_TAG', + 'content' => '?> +', + ], + ], + ], + 'unclosed star comment at end of file' => [ + 'testMarker' => '/* testCommentAtEndOfFile */', + 'expectedTokens' => [ + [ + 'type' => 'T_COMMENT', + 'content' => '/* Comment', + ], + ], + ], + ]; + + }//end dataCommentTokenization() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.inc new file mode 100644 index 000000000..53177a531 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.inc @@ -0,0 +1,161 @@ + $param & $int; + +/* testTypeIntersectionArrowReturnType */ +$arrowWithReturnType = fn ($param) : Foo&Bar => $param * 10; + +/* testBitwiseAndInArrayKey */ +$array = array( + A & B => /* testBitwiseAndInArrayValue */ B & C +); + +/* testBitwiseAndInShortArrayKey */ +$array = [ + A & B => /* testBitwiseAndInShortArrayValue */ B & C +]; + +/* testBitwiseAndNonArrowFnFunctionCall */ +$obj->fn($something & $else); + +/* testBitwiseAnd6 */ +function &fn(/* testTypeIntersectionNonArrowFunctionDeclaration */ Foo&Bar $something) {} + +/* testTypeIntersectionWithInvalidTypes */ +function (int&string $var) {}; + +/* testLiveCoding */ +// Intentional parse error. This has to be the last test in the file. +return function( Foo& diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.php new file mode 100644 index 000000000..8ed951de8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypeIntersectionTest.php @@ -0,0 +1,157 @@ + + * @author Jaroslav Hanslík + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class TypeIntersectionTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that non-intersection type bitwise and tokens are still tokenized as bitwise and. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataBitwiseAnd + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testBitwiseAnd($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_BITWISE_AND, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_BITWISE_AND (code)'); + $this->assertSame('T_BITWISE_AND', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_BITWISE_AND (type)'); + + }//end testBitwiseAnd() + + + /** + * Data provider. + * + * @see testBitwiseAnd() + * + * @return array> + */ + public static function dataBitwiseAnd() + { + return [ + 'in simple assignment 1' => ['/* testBitwiseAnd1 */'], + 'in simple assignment 2' => ['/* testBitwiseAnd2 */'], + 'in OO constant default value' => ['/* testBitwiseAndOOConstDefaultValue */'], + 'in property default value' => ['/* testBitwiseAndPropertyDefaultValue */'], + 'in method parameter default value' => ['/* testBitwiseAndParamDefaultValue */'], + 'reference for method parameter' => ['/* testBitwiseAnd3 */'], + 'in return statement' => ['/* testBitwiseAnd4 */'], + 'reference for function parameter' => ['/* testBitwiseAnd5 */'], + 'in OO constant default value DNF-like' => ['/* testBitwiseAndOOConstDefaultValueDNF */'], + 'in property default value DNF-like' => ['/* testBitwiseAndPropertyDefaultValueDNF */'], + 'in method parameter default value DNF-like' => ['/* testBitwiseAndParamDefaultValueDNF */'], + 'in closure parameter default value' => ['/* testBitwiseAndClosureParamDefault */'], + 'in arrow function parameter default value' => ['/* testBitwiseAndArrowParamDefault */'], + 'in arrow function return expression' => ['/* testBitwiseAndArrowExpression */'], + 'in long array key' => ['/* testBitwiseAndInArrayKey */'], + 'in long array value' => ['/* testBitwiseAndInArrayValue */'], + 'in short array key' => ['/* testBitwiseAndInShortArrayKey */'], + 'in short array value' => ['/* testBitwiseAndInShortArrayValue */'], + 'in parameter in function call' => ['/* testBitwiseAndNonArrowFnFunctionCall */'], + 'function return by reference' => ['/* testBitwiseAnd6 */'], + 'live coding / undetermined' => ['/* testLiveCoding */'], + ]; + + }//end dataBitwiseAnd() + + + /** + * Test that bitwise and tokens when used as part of a intersection type are tokenized as `T_TYPE_INTERSECTION`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataTypeIntersection + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypeIntersection($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_BITWISE_AND, T_TYPE_INTERSECTION]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_TYPE_INTERSECTION, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_TYPE_INTERSECTION (code)'); + $this->assertSame('T_TYPE_INTERSECTION', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_TYPE_INTERSECTION (type)'); + + }//end testTypeIntersection() + + + /** + * Data provider. + * + * @see testTypeIntersection() + * + * @return array> + */ + public static function dataTypeIntersection() + { + return [ + 'type for OO constant' => ['/* testTypeIntersectionOOConstSimple */'], + 'type for OO constant, reversed modifier order' => ['/* testTypeIntersectionOOConstReverseModifierOrder */'], + 'type for OO constant, first of multi-intersect' => ['/* testTypeIntersectionOOConstMulti1 */'], + 'type for OO constant, middle of multi-intersect + comments' => ['/* testTypeIntersectionOOConstMulti2 */'], + 'type for OO constant, last of multi-intersect' => ['/* testTypeIntersectionOOConstMulti3 */'], + 'type for OO constant, using namespace relative names' => ['/* testTypeIntersectionOOConstNamespaceRelative */'], + 'type for OO constant, using partially qualified names' => ['/* testTypeIntersectionOOConstPartiallyQualified */'], + 'type for OO constant, using fully qualified names' => ['/* testTypeIntersectionOOConstFullyQualified */'], + 'type for static property' => ['/* testTypeIntersectionPropertySimple */'], + 'type for static property, reversed modifier order' => ['/* testTypeIntersectionPropertyReverseModifierOrder */'], + 'type for property, first of multi-intersect' => ['/* testTypeIntersectionPropertyMulti1 */'], + 'type for property, middle of multi-intersect, also comments' => ['/* testTypeIntersectionPropertyMulti2 */'], + 'type for property, last of multi-intersect' => ['/* testTypeIntersectionPropertyMulti3 */'], + 'type for property using namespace relative names' => ['/* testTypeIntersectionPropertyNamespaceRelative */'], + 'type for property using partially qualified names' => ['/* testTypeIntersectionPropertyPartiallyQualified */'], + 'type for property using fully qualified names' => ['/* testTypeIntersectionPropertyFullyQualified */'], + 'type for readonly property' => ['/* testTypeIntersectionPropertyWithReadOnlyKeyword */'], + 'type for static readonly property' => ['/* testTypeIntersectionPropertyWithStaticKeyword */'], + 'type for method parameter' => ['/* testTypeIntersectionParam1 */'], + 'type for method parameter, first in multi-intersect' => ['/* testTypeIntersectionParam2 */'], + 'type for method parameter, last in multi-intersect' => ['/* testTypeIntersectionParam3 */'], + 'type for method parameter with namespace relative names' => ['/* testTypeIntersectionParamNamespaceRelative */'], + 'type for method parameter with partially qualified names' => ['/* testTypeIntersectionParamPartiallyQualified */'], + 'type for method parameter with fully qualified names' => ['/* testTypeIntersectionParamFullyQualified */'], + 'type for property in constructor property promotion' => ['/* testTypeIntersectionConstructorPropertyPromotion */'], + 'return type for method' => ['/* testTypeIntersectionReturnType */'], + 'return type for method, first of multi-intersect' => ['/* testTypeIntersectionAbstractMethodReturnType1 */'], + 'return type for method, last of multi-intersect' => ['/* testTypeIntersectionAbstractMethodReturnType2 */'], + 'return type for method with namespace relative names' => ['/* testTypeIntersectionReturnTypeNamespaceRelative */'], + 'return type for method with partially qualified names' => ['/* testTypeIntersectionReturnPartiallyQualified */'], + 'return type for method with fully qualified names' => ['/* testTypeIntersectionReturnFullyQualified */'], + 'type for function parameter with reference' => ['/* testTypeIntersectionWithReference */'], + 'type for function parameter with spread operator' => ['/* testTypeIntersectionWithSpreadOperator */'], + 'DNF type for OO constant, union before DNF' => ['/* testTypeIntersectionConstantTypeUnionBeforeDNF */'], + 'DNF type for property, union after DNF' => ['/* testTypeIntersectionPropertyTypeUnionAfterDNF */'], + 'DNF type for function param, union before and after DNF' => ['/* testTypeIntersectionParamUnionBeforeAndAfterDNF */'], + 'DNF type for function return, union after DNF with null' => ['/* testTypeIntersectionReturnTypeUnionAfterDNF */'], + 'type for closure parameter with illegal nullable' => ['/* testTypeIntersectionClosureParamIllegalNullable */'], + 'return type for closure' => ['/* testTypeIntersectionClosureReturn */'], + 'type for arrow function parameter' => ['/* testTypeIntersectionArrowParam */'], + 'return type for arrow function' => ['/* testTypeIntersectionArrowReturnType */'], + 'type for function parameter, return by ref' => ['/* testTypeIntersectionNonArrowFunctionDeclaration */'], + 'type for function parameter with invalid types' => ['/* testTypeIntersectionWithInvalidTypes */'], + ]; + + }//end dataTypeIntersection() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.inc new file mode 100644 index 000000000..4c6212b78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.inc @@ -0,0 +1,156 @@ +const ? 0 : 1; + +/* testGlobalConstantCannotBeTyped */ +const GLOBAL_UNTYPED = true; + +/* testGlobalConstantTypedShouldStillBeHandled */ +const ?int GLOBAL_TYPED = true; + +class ClassWithPlainTypedConstants { + /* testClassConstFinalUntyped */ + final const FINAL_UNTYPED = true; + + /* testClassConstVisibilityUntyped */ + public const /*comment*/VISIBLE_UNTYPED = true; + + /* testClassConstTypedTrue */ + const true TYPED_TRUE = true; + /* testClassConstTypedFalse */ + final const false TYPED_FALSE = false; + /* testClassConstTypedNull */ + public const null TYPED_NULL = null; + /* testClassConstTypedBool */ + final protected const/*comment*/bool TYPED_BOOL = false; + /* testClassConstTypedInt */ + private const int TYPED_INT = 0; + /* testClassConstTypedFloat */ + const float TYPED_FLOAT = 0.5; + /* testClassConstTypedString */ + public final const string/*comment*/TYPED_STRING = 'string'; + /* testClassConstTypedArray */ + private final const array TYPED_ARRAY = []; + /* testClassConstTypedObject */ + const + object + TYPED_OBJECT = MyClass::getInstance(); + /* testClassConstTypedIterable */ + const iterable typed_iterable = []; + /* testClassConstTypedMixed */ + const mixed TYPED_MIXED = 'string'; + + /* testClassConstTypedClassUnqualified */ + const MyClass TYPED_UNQUALIFIED_CLASSNAME = MyClass::getInstance(); + /* testClassConstTypedClassFullyQualified */ + public const \MyClass TYPED_FULLY_QUALIFIED_CLASSNAME = MyClass::getInstance(); + /* testClassConstTypedClassNamespaceRelative */ + protected const namespace\MyClass TYPED_NAMESPACE_RELATIVE_CLASSNAME = MyClass::getInstance(); + /* testClassConstTypedClassPartiallyQualified */ + private const Partial\MyClass TYPED_PARTIALLY_QUALIFIED_CLASSNAME = MyClass::getInstance(); + /* testClassConstTypedParent */ + const parent TYPED_PARENT = parent::getInstance(); + + // Illegal types - the fact that these are not allowed in PHP is not the concern of the PHPCS tokenizer. + /* testClassConstTypedCallable */ + protected const callable TYPED_CALLABLE = 'function_name'; + /* testClassConstTypedVoid */ + protected const void TYPED_VOID = null; + /* testClassConstTypedNever */ + protected const NEVER TYPED_NEVER = null; +} + +trait TraitWithNullableTypedConstants { + /* testTraitConstTypedNullableTrue */ + const ?true TYPED_TRUE = true; + /* testTraitConstTypedNullableFalse */ + final const ?false TYPED_FALSE = false; + /* testTraitConstTypedNullableNull */ + public const ?null TYPED_NULL = null; + /* testTraitConstTypedNullableBool */ + final protected const ?bool TYPED_BOOL = false; + /* testTraitConstTypedNullableInt */ + private const ?int TYPED_INT = 0; + /* testTraitConstTypedNullableFloat */ + const ? /*comment*/ float TYPED_FLOAT = 0.5; + /* testTraitConstTypedNullableString */ + public final const ?string TYPED_STRING = 'string'; + /* testTraitConstTypedNullableArray */ + private final const ? array TYPED_ARRAY = []; + /* testTraitConstTypedNullableObject */ + const ?object TYPED_OBJECT = MyClass::getInstance(); + /* testTraitConstTypedNullableIterable */ + const ?iterable TYPED_ITERABLE = []; + /* testTraitConstTypedNullableMixed */ + const ?mixed TYPED_MIXED = 'string'; + + /* testTraitConstTypedNullableClassUnqualified */ + const ?MyClass TYPED_UNQUALIFIED_CLASSNAME = MyClass::getInstance(); + /* testTraitConstTypedNullableClassFullyQualified */ + public const ?\MyClass TYPED_FULLY_QUALIFIED_CLASSNAME = MyClass::getInstance(); + /* testTraitConstTypedNullableClassNamespaceRelative */ + protected const ?namespace\MyClass TYPED_NAMESPACE_RELATIVE_CLASSNAME = MyClass::getInstance(); + /* testTraitConstTypedNullableClassPartiallyQualified */ + private const ?Partial\MyClass TYPED_PARTIALLY_QUALIFIED_CLASSNAME = MyClass::getInstance(); + /* testTraitConstTypedNullableParent */ + const ?parent TYPED_PARENT = parent::getInstance(); +} + +interface InterfaceWithUnionTypedConstants { + /* testInterfaceConstTypedUnionTrueNull */ + const true|null /*comment*/ UNION_TRUE_NULL = true; + /* testInterfaceConstTypedUnionArrayObject */ + const array|object UNION_ARRAY_OBJECT = []; + /* testInterfaceConstTypedUnionStringArrayInt */ + const string | array | int UNION_STRING_ARRAY_INT = 'array middle'; + /* testInterfaceConstTypedUnionFloatBoolArray */ + const float /*comment*/| bool|array UNION_FLOAT_BOOL_ARRAY = false; + /* testInterfaceConstTypedUnionIterableFalse */ + const iterable|false UNION_ITERABLE_FALSE = false; + /* testInterfaceConstTypedUnionUnqualifiedNamespaceRelative */ + const Unqualified|namespace\Relative UNION_UNQUALIFIED_NSRELATIVE = new Unqualified(); + /* testInterfaceConstTypedUnionFullyQualifiedPartiallyQualified */ + const \Fully\Qualified|Partially\Qualified UNION_FQN_PARTIAL = new Partial\Qualified; +} + +enum EnumWithIntersectionTypedConstants { + // Illegal types in a class, but legal in an enum. + /* testEnumConstTypedSelf */ + final const self TYPED_SELF = self::getInstance(); + /* testEnumConstTypedStatic */ + const static TYPED_STATIC = static::getInstance(); + /* testEnumConstTypedNullableSelf */ + public const ?self TYPED_SELF = self::getInstance(); + /* testEnumConstTypedNullableStatic */ + const ?static TYPED_STATIC = static::getInstance(); + + /* testEnumConstTypedIntersectUnqualifiedNamespaceRelative */ + const Unqualified&namespace\Relative UNION_UNQUALIFIED_NSRELATIVE = new Unqualified(); + /* testEnumConstTypedIntersectFullyQualifiedPartiallyQualified */ + const \Fully\Qualified&Partially\Qualified UNION_FQN_PARTIAL = new Partial\Qualified; +} + +$anonClassWithDNFTypes = new class() extends Something { + /* testAnonClassConstDNFTypeNullAfter */ + const (A&B)|null DNF_OR_NULL_1 = null; + /* testAnonClassConstDNFTypeNullBefore */ + public final const NULL|(A&B) DNF_OR_NULL_2 = null; + /* testAnonClassConstDNFTypeFalseBefore */ + final const false|(C&D) DNF_OR_FALSE = false; + /* testAnonClassConstDNFTypeTrueAfter */ + private final const ( F & G ) | true DNF_OR_ARRAY = true; + /* testAnonClassConstDNFTypeTrueBeforeFalseAfter */ + public const TRUE|(SplBool&Stringable)|FALSE DNF_OR_BOOL = true; + /* testAnonClassConstDNFTypeArrayAfter */ + final protected const (Traversable&Countable)|array DNF_OR_ARRAY_1 = []; + /* testAnonClassConstDNFTypeArrayBefore */ + private const array /*comment*/ | ( Traversable /*comment*/ & Countable ) DNF_OR_ARRAY_2 = new MyClass; + /* testAnonClassConstDNFTypeInvalidNullable */ + const ? (Invalid&Fatal)|NullableNotAllowed DNF = null; + + /* testAnonClassConstDNFTypeFQNRelativePartiallyQualified */ + const (\FQN&namespace\Relative)|Partially\Qualified DNF_CLASSNAME = MyClass::getInstance(); + /* testAnonClassConstDNFTypeParentSelfStatic */ + const (parent&self)|static DNF_PARENT = parent::getInstance(); +}; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.php new file mode 100644 index 000000000..29a1fc7ad --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/TypedConstantsTest.php @@ -0,0 +1,668 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class TypedConstantsTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that a ? after a "const" which is not the constant keyword is tokenized as ternary then, not as the nullable operator. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testTernaryIsInlineThen() + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken('/* testTernaryIsTernaryAfterConst */', [T_NULLABLE, T_INLINE_THEN]); + + $this->assertSame( + T_INLINE_THEN, + $tokens[$target]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$target]['code']).', not T_INLINE_THEN (code)' + ); + $this->assertSame( + 'T_INLINE_THEN', + $tokens[$target]['type'], + 'Token tokenized as '.$tokens[$target]['type'].', not T_INLINE_THEN (type)' + ); + + }//end testTernaryIsInlineThen() + + + /** + * Test the token name for an untyped constant is tokenized as T_STRING. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataUntypedConstant + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testUntypedConstant($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, T_CONST); + + for ($i = ($target + 1); $tokens[$i]['code'] !== T_EQUAL; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + // Ignore whitespace and comments, not interested in the tokenization of those. + continue; + } + + $this->assertSame( + T_STRING, + $tokens[$i]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$i]['code']).', not T_STRING (code)' + ); + $this->assertSame( + 'T_STRING', + $tokens[$i]['type'], + 'Token tokenized as '.$tokens[$i]['type'].', not T_STRING (type)' + ); + } + + }//end testUntypedConstant() + + + /** + * Data provider. + * + * @see testUntypedConstant() + * + * @return array> + */ + public static function dataUntypedConstant() + { + return [ + 'non OO constant (untyped)' => [ + 'testMarker' => '/* testGlobalConstantCannotBeTyped */', + ], + 'OO constant, final, untyped' => [ + 'testMarker' => '/* testClassConstFinalUntyped */', + ], + 'OO constant, public, untyped, with comment' => [ + 'testMarker' => '/* testClassConstVisibilityUntyped */', + ], + ]; + + }//end dataUntypedConstant() + + + /** + * Test the tokens in the type of a typed constant as well as the constant name are tokenized correctly. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $sequence The expected token sequence. + * + * @dataProvider dataTypedConstant + * @dataProvider dataNullableTypedConstant + * @dataProvider dataUnionTypedConstant + * @dataProvider dataIntersectionTypedConstant + * @dataProvider dataDNFTypedConstant + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional + * + * @return void + */ + public function testTypedConstant($testMarker, array $sequence) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, T_CONST); + + $current = 0; + for ($i = ($target + 1); $tokens[$i]['code'] !== T_EQUAL; $i++) { + if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === true) { + // Ignore whitespace and comments, not interested in the tokenization of those. + continue; + } + + $this->assertSame( + $sequence[$current], + $tokens[$i]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$i]['code']).', not '.Tokens::tokenName($sequence[$current]).' (code)' + ); + + ++$current; + } + + }//end testTypedConstant() + + + /** + * Data provider. + * + * @see testTypedConstant() + * + * @return array>> + */ + public static function dataTypedConstant() + { + $data = [ + 'simple type: true' => [ + 'testMarker' => '/* testClassConstTypedTrue */', + 'sequence' => [T_TRUE], + ], + 'simple type: false' => [ + 'testMarker' => '/* testClassConstTypedFalse */', + 'sequence' => [T_FALSE], + ], + 'simple type: null' => [ + 'testMarker' => '/* testClassConstTypedNull */', + 'sequence' => [T_NULL], + ], + 'simple type: bool' => [ + 'testMarker' => '/* testClassConstTypedBool */', + 'sequence' => [T_STRING], + ], + 'simple type: int' => [ + 'testMarker' => '/* testClassConstTypedInt */', + 'sequence' => [T_STRING], + ], + 'simple type: float' => [ + 'testMarker' => '/* testClassConstTypedFloat */', + 'sequence' => [T_STRING], + ], + 'simple type: string' => [ + 'testMarker' => '/* testClassConstTypedString */', + 'sequence' => [T_STRING], + ], + 'simple type: array' => [ + 'testMarker' => '/* testClassConstTypedArray */', + 'sequence' => [T_STRING], + ], + 'simple type: object' => [ + 'testMarker' => '/* testClassConstTypedObject */', + 'sequence' => [T_STRING], + ], + 'simple type: iterable' => [ + 'testMarker' => '/* testClassConstTypedIterable */', + 'sequence' => [T_STRING], + ], + 'simple type: mixed' => [ + 'testMarker' => '/* testClassConstTypedMixed */', + 'sequence' => [T_STRING], + ], + 'simple type: unqualified name' => [ + 'testMarker' => '/* testClassConstTypedClassUnqualified */', + 'sequence' => [T_STRING], + ], + 'simple type: fully qualified name' => [ + 'testMarker' => '/* testClassConstTypedClassFullyQualified */', + 'sequence' => [ + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'simple type: namespace relative name' => [ + 'testMarker' => '/* testClassConstTypedClassNamespaceRelative */', + 'sequence' => [ + T_NAMESPACE, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'simple type: partially qualified name' => [ + 'testMarker' => '/* testClassConstTypedClassPartiallyQualified */', + 'sequence' => [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'simple type: parent' => [ + 'testMarker' => '/* testClassConstTypedParent */', + 'sequence' => [T_PARENT], + ], + + 'simple type: callable (invalid)' => [ + 'testMarker' => '/* testClassConstTypedCallable */', + 'sequence' => [T_CALLABLE], + ], + 'simple type: void (invalid)' => [ + 'testMarker' => '/* testClassConstTypedVoid */', + 'sequence' => [T_STRING], + ], + 'simple type: NEVER (invalid)' => [ + 'testMarker' => '/* testClassConstTypedNever */', + 'sequence' => [T_STRING], + ], + + 'simple type: self (only valid in enum)' => [ + 'testMarker' => '/* testEnumConstTypedSelf */', + 'sequence' => [T_SELF], + ], + 'simple type: static (only valid in enum)' => [ + 'testMarker' => '/* testEnumConstTypedStatic */', + 'sequence' => [T_STATIC], + ], + ]; + + // The constant name, as the last token in the sequence, is always T_STRING. + foreach ($data as $key => $value) { + $data[$key]['sequence'][] = T_STRING; + } + + return $data; + + }//end dataTypedConstant() + + + /** + * Data provider. + * + * @see testTypedConstant() + * + * @return array> + */ + public static function dataNullableTypedConstant() + { + $data = [ + // Global constants cannot be typed in PHP, but that's not our concern. + 'global typed constant, invalid, ?int' => [ + 'testMarker' => '/* testGlobalConstantTypedShouldStillBeHandled */', + 'sequence' => [T_STRING], + ], + + // OO constants. + 'nullable type: true' => [ + 'testMarker' => '/* testTraitConstTypedNullableTrue */', + 'sequence' => [T_TRUE], + ], + 'nullable type: false' => [ + 'testMarker' => '/* testTraitConstTypedNullableFalse */', + 'sequence' => [T_FALSE], + ], + 'nullable type: null' => [ + 'testMarker' => '/* testTraitConstTypedNullableNull */', + 'sequence' => [T_NULL], + ], + 'nullable type: bool' => [ + 'testMarker' => '/* testTraitConstTypedNullableBool */', + 'sequence' => [T_STRING], + ], + 'nullable type: int' => [ + 'testMarker' => '/* testTraitConstTypedNullableInt */', + 'sequence' => [T_STRING], + ], + 'nullable type: float' => [ + 'testMarker' => '/* testTraitConstTypedNullableFloat */', + 'sequence' => [T_STRING], + ], + 'nullable type: string' => [ + 'testMarker' => '/* testTraitConstTypedNullableString */', + 'sequence' => [T_STRING], + ], + 'nullable type: array' => [ + 'testMarker' => '/* testTraitConstTypedNullableArray */', + 'sequence' => [T_STRING], + ], + 'nullable type: object' => [ + 'testMarker' => '/* testTraitConstTypedNullableObject */', + 'sequence' => [T_STRING], + ], + 'nullable type: iterable' => [ + 'testMarker' => '/* testTraitConstTypedNullableIterable */', + 'sequence' => [T_STRING], + ], + 'nullable type: mixed' => [ + 'testMarker' => '/* testTraitConstTypedNullableMixed */', + 'sequence' => [T_STRING], + ], + 'nullable type: unqualified name' => [ + 'testMarker' => '/* testTraitConstTypedNullableClassUnqualified */', + 'sequence' => [T_STRING], + ], + 'nullable type: fully qualified name' => [ + 'testMarker' => '/* testTraitConstTypedNullableClassFullyQualified */', + 'sequence' => [ + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'nullable type: namespace relative name' => [ + 'testMarker' => '/* testTraitConstTypedNullableClassNamespaceRelative */', + 'sequence' => [ + T_NAMESPACE, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'nullable type: partially qualified name' => [ + 'testMarker' => '/* testTraitConstTypedNullableClassPartiallyQualified */', + 'sequence' => [ + T_STRING, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'nullable type: parent' => [ + 'testMarker' => '/* testTraitConstTypedNullableParent */', + 'sequence' => [T_PARENT], + ], + + 'nullable type: self (only valid in enum)' => [ + 'testMarker' => '/* testEnumConstTypedNullableSelf */', + 'sequence' => [T_SELF], + ], + 'nullable type: static (only valid in enum)' => [ + 'testMarker' => '/* testEnumConstTypedNullableStatic */', + 'sequence' => [T_STATIC], + ], + ]; + + // The nullable operator, as the first token in the sequence, is always T_NULLABLE. + // The constant name, as the last token in the sequence, is always T_STRING. + foreach ($data as $key => $value) { + array_unshift($data[$key]['sequence'], T_NULLABLE); + $data[$key]['sequence'][] = T_STRING; + } + + return $data; + + }//end dataNullableTypedConstant() + + + /** + * Data provider. + * + * @see testTypedConstant() + * + * @return array> + */ + public static function dataUnionTypedConstant() + { + $data = [ + 'union type: true|null' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionTrueNull */', + 'sequence' => [ + T_TRUE, + T_TYPE_UNION, + T_NULL, + ], + ], + 'union type: array|object' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionArrayObject */', + 'sequence' => [ + T_STRING, + T_TYPE_UNION, + T_STRING, + ], + ], + 'union type: string|array|int' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionStringArrayInt */', + 'sequence' => [ + T_STRING, + T_TYPE_UNION, + T_STRING, + T_TYPE_UNION, + T_STRING, + ], + ], + 'union type: float|bool|array' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionFloatBoolArray */', + 'sequence' => [ + T_STRING, + T_TYPE_UNION, + T_STRING, + T_TYPE_UNION, + T_STRING, + ], + ], + 'union type: iterable|false' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionIterableFalse */', + 'sequence' => [ + T_STRING, + T_TYPE_UNION, + T_FALSE, + ], + ], + 'union type: Unqualified|Namespace\Relative' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionUnqualifiedNamespaceRelative */', + 'sequence' => [ + T_STRING, + T_TYPE_UNION, + T_NAMESPACE, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'union type: FQN|Partial' => [ + 'testMarker' => '/* testInterfaceConstTypedUnionFullyQualifiedPartiallyQualified */', + 'sequence' => [ + T_NS_SEPARATOR, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_TYPE_UNION, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + ], + ], + ]; + + // The constant name, as the last token in the sequence, is always T_STRING. + foreach ($data as $key => $value) { + $data[$key]['sequence'][] = T_STRING; + } + + return $data; + + }//end dataUnionTypedConstant() + + + /** + * Data provider. + * + * @see testTypedConstant() + * + * @return array> + */ + public static function dataIntersectionTypedConstant() + { + $data = [ + 'intersection type: Unqualified&Namespace\Relative' => [ + 'testMarker' => '/* testEnumConstTypedIntersectUnqualifiedNamespaceRelative */', + 'sequence' => [ + T_STRING, + T_TYPE_INTERSECTION, + T_NAMESPACE, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'intersection type: FQN&Partial' => [ + 'testMarker' => '/* testEnumConstTypedIntersectFullyQualifiedPartiallyQualified */', + 'sequence' => [ + T_NS_SEPARATOR, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + ], + ], + ]; + + // The constant name, as the last token in the sequence, is always T_STRING. + foreach ($data as $key => $value) { + $data[$key]['sequence'][] = T_STRING; + } + + return $data; + + }//end dataIntersectionTypedConstant() + + + /** + * Data provider. + * + * @see testTypedConstant() + * + * @return array> + */ + public static function dataDNFTypedConstant() + { + $data = [ + 'DNF type: null after' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeNullAfter */', + 'sequence' => [ + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_NULL, + ], + ], + 'DNF type: null before' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeNullBefore */', + 'sequence' => [ + T_NULL, + T_TYPE_UNION, + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + ], + ], + 'DNF type: false before' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeFalseBefore */', + 'sequence' => [ + T_FALSE, + T_TYPE_UNION, + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + ], + ], + 'DNF type: true after' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeTrueAfter */', + 'sequence' => [ + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_TRUE, + ], + ], + 'DNF type: true before, false after' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeTrueBeforeFalseAfter */', + 'sequence' => [ + T_TRUE, + T_TYPE_UNION, + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_FALSE, + ], + ], + 'DNF type: array after' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeArrayAfter */', + 'sequence' => [ + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_STRING, + ], + ], + 'DNF type: array before' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeArrayBefore */', + 'sequence' => [ + T_STRING, + T_TYPE_UNION, + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + ], + ], + 'DNF type: invalid nullable DNF' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeInvalidNullable */', + 'sequence' => [ + T_NULLABLE, + T_TYPE_OPEN_PARENTHESIS, + T_STRING, + T_TYPE_INTERSECTION, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_STRING, + ], + ], + 'DNF type: FQN/namespace relative/partially qualified names' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeFQNRelativePartiallyQualified */', + 'sequence' => [ + T_TYPE_OPEN_PARENTHESIS, + T_NS_SEPARATOR, + T_STRING, + T_TYPE_INTERSECTION, + T_NAMESPACE, + T_NS_SEPARATOR, + T_STRING, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_STRING, + T_NS_SEPARATOR, + T_STRING, + ], + ], + 'DNF type: invalid self/parent/static' => [ + 'testMarker' => '/* testAnonClassConstDNFTypeParentSelfStatic */', + 'sequence' => [ + T_TYPE_OPEN_PARENTHESIS, + T_PARENT, + T_TYPE_INTERSECTION, + T_SELF, + T_TYPE_CLOSE_PARENTHESIS, + T_TYPE_UNION, + T_STATIC, + ], + ], + ]; + + // The constant name, as the last token in the sequence, is always T_STRING. + foreach ($data as $key => $value) { + $data[$key]['sequence'][] = T_STRING; + } + + return $data; + + }//end dataDNFTypedConstant() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/UndoNamespacedNameSingleTokenTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/UndoNamespacedNameSingleTokenTest.inc new file mode 100644 index 000000000..65c551a84 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/UndoNamespacedNameSingleTokenTest.inc @@ -0,0 +1,147 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +final class UndoNamespacedNameSingleTokenTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that identifier names are tokenized the same across PHP versions, based on the PHP 5/7 tokenization. + * + * @param string $testMarker The comment prefacing the test. + * @param array> $expectedTokens The tokenization expected. + * + * @dataProvider dataIdentifierTokenization + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + * + * @return void + */ + public function testIdentifierTokenization($testMarker, $expectedTokens) + { + $tokens = $this->phpcsFile->getTokens(); + $identifier = $this->getTargetToken($testMarker, constant($expectedTokens[0]['type'])); + + foreach ($expectedTokens as $tokenInfo) { + $this->assertSame( + constant($tokenInfo['type']), + $tokens[$identifier]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$identifier]['code']).', not '.$tokenInfo['type'].' (code)' + ); + $this->assertSame( + $tokenInfo['type'], + $tokens[$identifier]['type'], + 'Token tokenized as '.$tokens[$identifier]['type'].', not '.$tokenInfo['type'].' (type)' + ); + $this->assertSame($tokenInfo['content'], $tokens[$identifier]['content']); + + ++$identifier; + } + + }//end testIdentifierTokenization() + + + /** + * Data provider. + * + * @see testIdentifierTokenization() + * + * @return array>>> + */ + public static function dataIdentifierTokenization() + { + return [ + 'namespace declaration' => [ + 'testMarker' => '/* testNamespaceDeclaration */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Package', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'namespace declaration, multi-level' => [ + 'testMarker' => '/* testNamespaceDeclarationWithLevels */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Domain', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, class' => [ + 'testMarker' => '/* testUseStatement */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, class, multi-level' => [ + 'testMarker' => '/* testUseStatementWithLevels */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Domain', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, function' => [ + 'testMarker' => '/* testFunctionUseStatement */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, function, multi-level' => [ + 'testMarker' => '/* testFunctionUseStatementWithLevels */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_in_ns', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, constant' => [ + 'testMarker' => '/* testConstantUseStatement */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_NAME', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, constant, multi-level' => [ + 'testMarker' => '/* testConstantUseStatementWithLevels */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'OTHER_CONSTANT', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'import use statement, multi-statement, unqualified class' => [ + 'testMarker' => '/* testMultiUseUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'UnqualifiedClassName', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + 'import use statement, multi-statement, partially qualified class' => [ + 'testMarker' => '/* testMultiUsePartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'PartiallyClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'group use statement, multi-level prefix, mix inside group' => [ + 'testMarker' => '/* testGroupUseStatement */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_OPEN_USE_GROUP', + 'content' => '{', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'AnotherDomain', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_grouped', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_GROUPED', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sub', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'YetAnotherDomain', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevelA', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_grouped_too', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'const', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevelB', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'CONSTANT_GROUPED_TOO', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_CLOSE_USE_GROUP', + 'content' => '}', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'class declaration' => [ + 'testMarker' => '/* testClassName */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'MyClass', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'class declaration, extends fully qualified name' => [ + 'testMarker' => '/* testExtendedFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'FQN', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'class declaration, implements namespace relative name' => [ + 'testMarker' => '/* testImplementsRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + 'class declaration, implements fully qualified name' => [ + 'testMarker' => '/* testImplementsFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + 'class declaration, implements unqualified name' => [ + 'testMarker' => '/* testImplementsUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Unqualified', + ], + [ + 'type' => 'T_COMMA', + 'content' => ',', + ], + ], + ], + 'class declaration, implements partially qualified name' => [ + 'testMarker' => '/* testImplementsPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Sub', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'method declaration' => [ + 'testMarker' => '/* testFunctionName */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'param type declaration, namespace relative name' => [ + 'testMarker' => '/* testTypeDeclarationRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_TYPE_UNION', + 'content' => '|', + ], + [ + 'type' => 'T_STRING', + 'content' => 'object', + ], + ], + ], + 'param type declaration, fully qualified name' => [ + 'testMarker' => '/* testTypeDeclarationFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'param type declaration, unqualified name' => [ + 'testMarker' => '/* testTypeDeclarationUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Unqualified', + ], + [ + 'type' => 'T_TYPE_UNION', + 'content' => '|', + ], + [ + 'type' => 'T_FALSE', + 'content' => 'false', + ], + ], + ], + 'param type declaration, partially qualified name' => [ + 'testMarker' => '/* testTypeDeclarationPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_NULLABLE', + 'content' => '?', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'return type declaration, fully qualified name' => [ + 'testMarker' => '/* testReturnTypeFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NULLABLE', + 'content' => '?', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'function call, namespace relative name' => [ + 'testMarker' => '/* testFunctionCallRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'NameSpace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'function call, fully qualified name' => [ + 'testMarker' => '/* testFunctionCallFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Package', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'function call, unqualified name' => [ + 'testMarker' => '/* testFunctionCallUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'function call, partially qualified name' => [ + 'testMarker' => '/* testFunctionCallPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'catch, namespace relative name' => [ + 'testMarker' => '/* testCatchRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'SubLevel', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'catch, fully qualified name' => [ + 'testMarker' => '/* testCatchFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'catch, unqualified name' => [ + 'testMarker' => '/* testCatchUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'catch, partially qualified name' => [ + 'testMarker' => '/* testCatchPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Exception', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'class instantiation, namespace relative name' => [ + 'testMarker' => '/* testNewRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'class instantiation, fully qualified name' => [ + 'testMarker' => '/* testNewFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Vendor', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'class instantiation, unqualified name' => [ + 'testMarker' => '/* testNewUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'class instantiation, partially qualified name' => [ + 'testMarker' => '/* testNewPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'double colon class access, namespace relative name' => [ + 'testMarker' => '/* testDoubleColonRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + 'double colon class access, fully qualified name' => [ + 'testMarker' => '/* testDoubleColonFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + 'double colon class access, unqualified name' => [ + 'testMarker' => '/* testDoubleColonUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + 'double colon class access, partially qualified name' => [ + 'testMarker' => '/* testDoubleColonPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Level', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_DOUBLE_COLON', + 'content' => '::', + ], + ], + ], + 'instanceof, namespace relative name' => [ + 'testMarker' => '/* testInstanceOfRelative */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'instanceof, fully qualified name' => [ + 'testMarker' => '/* testInstanceOfFQN */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Full', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_CLOSE_PARENTHESIS', + 'content' => ')', + ], + ], + ], + 'instanceof, unqualified name' => [ + 'testMarker' => '/* testInstanceOfUnqualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'instanceof, partially qualified name' => [ + 'testMarker' => '/* testInstanceOfPartiallyQualified */', + 'expectedTokens' => [ + [ + 'type' => 'T_STRING', + 'content' => 'Partially', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'ClassName', + ], + [ + 'type' => 'T_SEMICOLON', + 'content' => ';', + ], + ], + ], + 'function call, namespace relative, with whitespace (invalid in PHP 8)' => [ + 'testMarker' => '/* testInvalidInPHP8Whitespace */', + 'expectedTokens' => [ + [ + 'type' => 'T_NAMESPACE', + 'content' => 'namespace', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Sublevel', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_STRING', + 'content' => 'function_name', + ], + [ + 'type' => 'T_OPEN_PARENTHESIS', + 'content' => '(', + ], + ], + ], + 'double colon class access, fully qualified, with whitespace and comments (invalid in PHP 8)' => [ + 'testMarker' => '/* testInvalidInPHP8Comments */', + 'expectedTokens' => [ + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Fully', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat.Sniff -- for reasons +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Qualified', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '/* comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_NS_SEPARATOR', + 'content' => '\\', + ], + [ + 'type' => 'T_STRING', + 'content' => 'Name', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + ]; + + }//end dataIdentifierTokenization() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.inc new file mode 100644 index 000000000..3130b8460 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.inc @@ -0,0 +1,77 @@ +yield; + + /* testYieldUsedAsPropertyName2 */ + echo $obj?->yield(); + + /* testYieldUsedForClassConstantAccess1 */ + echo MyClass::YIELD; + /* testFromUsedForClassConstantAccess1 */ + echo MyClass::FROM; + } + + /* testYieldUsedAsMethodNameReturnByRef */ + public function &yield() {} +} + +function myGen() { + /* testYieldLiveCoding */ + yield diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.php new file mode 100644 index 000000000..efb12096c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/PHP/YieldTest.php @@ -0,0 +1,448 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\PHP; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Tests the tokenization of the `yield` and `yield from` keywords. + * + * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize + */ +final class YieldTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the yield keyword is tokenized as such. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent Expected token content. + * + * @dataProvider dataYieldKeyword + * + * @return void + */ + public function testYieldKeyword($testMarker, $expectedContent) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_YIELD, T_YIELD_FROM, T_STRING]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_YIELD, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_YIELD (code)'); + + // This assertion would fail on PHP 5.4 with PHPUnit 4 as PHPUnit polyfills the `T_YIELD` token too, but + // with a different value, which causes the token 'type' to be set to `UNKNOWN`. + // This issue _only_ occurs when running the tests, not when running PHPCS outside of a test situation. + // The PHPUnit polyfilled token is declared in the PHP_CodeCoverage_Report_HTML_Renderer_File class + // in vendor/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/File.php. + if (PHP_VERSION_ID >= 50500) { + $this->assertSame('T_YIELD', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_YIELD (type)'); + } + + $this->assertSame($expectedContent, $tokenArray['content'], 'Token content does not match expectation'); + + }//end testYieldKeyword() + + + /** + * Data provider. + * + * @see testYieldKeyword() + * + * @return array> + */ + public static function dataYieldKeyword() + { + return [ + 'yield' => [ + 'testMarker' => '/* testYield */', + 'expectedContent' => 'yield', + ], + 'yield followed by comment' => [ + 'testMarker' => '/* testYieldFollowedByComment */', + 'expectedContent' => 'YIELD', + ], + 'yield at end of file, live coding' => [ + 'testMarker' => '/* testYieldLiveCoding */', + 'expectedContent' => 'yield', + ], + ]; + + }//end dataYieldKeyword() + + + /** + * Test that the yield from keyword is tokenized as a single token when it in on a single line + * and only has whitespace between the words. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param string $expectedContent Expected token content. + * + * @dataProvider dataYieldFromKeywordSingleToken + * + * @return void + */ + public function testYieldFromKeywordSingleToken($testMarker, $expectedContent) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_YIELD, T_YIELD_FROM, T_STRING]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_YIELD_FROM, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_YIELD_FROM (code)'); + $this->assertSame('T_YIELD_FROM', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_YIELD_FROM (type)'); + + if (isset($tokenArray['orig_content']) === true) { + $this->assertSame($expectedContent, $tokenArray['orig_content'], 'Token (orig) content does not match expectation'); + } else { + $this->assertSame($expectedContent, $tokenArray['content'], 'Token content does not match expectation'); + } + + }//end testYieldFromKeywordSingleToken() + + + /** + * Data provider. + * + * @see testYieldFromKeywordSingleToken() + * + * @return array> + */ + public static function dataYieldFromKeywordSingleToken() + { + return [ + 'yield from' => [ + 'testMarker' => '/* testYieldFrom */', + 'expectedContent' => 'yield from', + ], + 'yield from with extra space between' => [ + 'testMarker' => '/* testYieldFromWithExtraSpacesBetween */', + 'expectedContent' => 'Yield From', + ], + 'yield from with tab between' => [ + 'testMarker' => '/* testYieldFromWithTabBetween */', + 'expectedContent' => 'yield from', + ], + ]; + + }//end dataYieldFromKeywordSingleToken() + + + /** + * Test that the yield from keyword is tokenized as a single token when it in on a single line + * and only has whitespace between the words. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param array> $expectedTokens The tokenization expected. + * + * @dataProvider dataYieldFromKeywordMultiToken + * + * @return void + */ + public function testYieldFromKeywordMultiToken($testMarker, $expectedTokens) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_YIELD, T_YIELD_FROM, T_STRING]); + + foreach ($expectedTokens as $nr => $tokenInfo) { + $this->assertSame( + constant($tokenInfo['type']), + $tokens[$target]['code'], + 'Token tokenized as '.Tokens::tokenName($tokens[$target]['code']).', not '.$tokenInfo['type'].' (code)' + ); + $this->assertSame( + $tokenInfo['type'], + $tokens[$target]['type'], + 'Token tokenized as '.$tokens[$target]['type'].', not '.$tokenInfo['type'].' (type)' + ); + $this->assertSame( + $tokenInfo['content'], + $tokens[$target]['content'], + 'Content of token '.($nr + 1).' ('.$tokens[$target]['type'].') does not match expectations' + ); + + ++$target; + } + + }//end testYieldFromKeywordMultiToken() + + + /** + * Data provider. + * + * @see testYieldFromKeywordMultiToken() + * + * @return array>>> + */ + public static function dataYieldFromKeywordMultiToken() + { + return [ + 'yield from with new line' => [ + 'testMarker' => '/* testYieldFromSplitByNewLines */', + 'expectedTokens' => [ + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'yield', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'FROM', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'yield from with comment' => [ + 'testMarker' => '/* testYieldFromSplitByComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'yield', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '/* comment */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'from', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'yield from with trailing comment' => [ + 'testMarker' => '/* testYieldFromWithTrailingComment */', + 'expectedTokens' => [ + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'yield', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'from', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'yield from with trailing annotation' => [ + 'testMarker' => '/* testYieldFromWithTrailingAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'yield', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_IGNORE', + 'content' => '// phpcs:ignore Stnd.Cat.Sniff -- for reasons. +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'from', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + ], + ], + 'yield from with new line and comment' => [ + 'testMarker' => '/* testYieldFromSplitByNewLineAndComments */', + 'expectedTokens' => [ + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'yield', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '/* comment line 1 +', + ], + [ + 'type' => 'T_COMMENT', + 'content' => ' line 2 */', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_COMMENT', + 'content' => '// another comment +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'from', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + 'yield from with new line and annotation' => [ + 'testMarker' => '/* testYieldFromSplitByNewLineAndAnnotation */', + 'expectedTokens' => [ + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'YIELD', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_PHPCS_DISABLE', + 'content' => '// @phpcs:disable Stnd.Cat.Sniff -- for reasons. +', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' ', + ], + [ + 'type' => 'T_YIELD_FROM', + 'content' => 'From', + ], + [ + 'type' => 'T_WHITESPACE', + 'content' => ' +', + ], + ], + ], + ]; + + }//end dataYieldFromKeywordMultiToken() + + + /** + * Test that 'yield' or 'from' when not used as the reserved keyword are tokenized as `T_STRING`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataYieldNonKeyword + * + * @return void + */ + public function testYieldNonKeyword($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_YIELD, T_YIELD_FROM, T_STRING]); + $tokenArray = $tokens[$target]; + + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + $this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)'); + + }//end testYieldNonKeyword() + + + /** + * Data provider. + * + * @see testYieldNonKeyword() + * + * @return array> + */ + public static function dataYieldNonKeyword() + { + return [ + 'yield used as class name' => ['/* testYieldUsedAsClassName */'], + 'yield used as class constant name' => ['/* testYieldUsedAsClassConstantName */'], + 'yield used as method name' => ['/* testYieldUsedAsMethodName */'], + 'yield used as property access 1' => ['/* testYieldUsedAsPropertyName1 */'], + 'yield used as property access 2' => ['/* testYieldUsedAsPropertyName2 */'], + 'yield used as class constant access' => ['/* testYieldUsedForClassConstantAccess1 */'], + 'from used as class constant access' => ['/* testFromUsedForClassConstantAccess1 */'], + 'yield used as method name with ref' => ['/* testYieldUsedAsMethodNameReturnByRef */'], + ]; + + }//end dataYieldNonKeyword() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc new file mode 100644 index 000000000..89031bd19 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.inc @@ -0,0 +1,185 @@ + 10 ) {} + +/* testParensOwnerFor */ +for ($i =0; $i < /* testParensNoOwnerInForCondition */ ( CONST_A & CONST_B ); $i++ ); + +/* testParensOwnerMatch */ +$match = match(CONST_A & CONST_B) { + default => $a, +}; + +/* testParensOwnerArray */ +$array = array ( + 'text', + \CONST_A & \Fully\Qualified\CONST_B, + /* testParensNoOwnerFunctionCallWithAmpersandInCallable */ + do_something($a, /* testParensOwnerArrowFn */ fn($b) => $a & $b, $c), +); + +/* testParensOwnerListWithRefVars */ +list(&$a, &$b) = $array; + +/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */ +$obj->static((CONST_A&CONST_B)|CONST_C | $var); + + +/* + * DNF parentheses. + */ + +abstract class DNFTypes { + /* testDNFTypeOOConstUnqualifiedClasses */ + public const (A&B)|D UNQUALIFIED = new Foo; + + /* testDNFTypeOOConstReverseModifierOrder */ + protected final const int|(Foo&Bar)|float MODIFIERS_REVERSED /* testParensNoOwnerOOConstDefaultValue */ = (E_WARNING & E_NOTICE) | E_DEPRECATED; + + const + /* testDNFTypeOOConstMulti1 */ + (A&B) | + /* testDNFTypeOOConstMulti2 */ + (C&D) | // phpcs:ignore Stnd.Cat.Sniff + /* testDNFTypeOOConstMulti3 */ + (Y&D) + | null MULTI_DNF = null; + + /* testDNFTypeOOConstNamespaceRelative */ + final protected const (namespace\Sub\NameA&namespace\Sub\NameB)|namespace\Sub\NameC NAMESPACE_RELATIVE = new namespace\Sub\NameB; + + /* testDNFTypeOOConstPartiallyQualified */ + const Partially\Qualified\NameC|(Partially\Qualified\NameA&Partially\Qualified\NameB) PARTIALLY_QUALIFIED = new Partially\Qualified\NameA; + + /* testDNFTypeOOConstFullyQualified */ + const (\Fully\Qualified\NameA&\Fully\Qualified\NameB)|\Fully\Qualified\NameC FULLY_QUALIFIED = new \Fully\Qualified\NameB(); + + /* testDNFTypePropertyUnqualifiedClasses */ + public static (Foo&Bar)|array $obj; + + /* testDNFTypePropertyReverseModifierOrder */ + static protected string|(A&B)|int $dnf /* testParensNoOwnerPropertyDefaultValue1 */ = ( E_WARNING & E_NOTICE ) | /* testParensNoOwnerPropertyDefaultValue2 */ (E_ALL & E_DEPRECATED); + + private + /* testDNFTypePropertyMultiNamespaceRelative */ + (namespace\Sub\NameA&namespace\Sub\NameB) | + /* testDNFTypePropertyMultiPartiallyQualified */ + (Partially\Qualified\NameA&Partially\Qualified\NameB) | // phpcs:ignore Stnd.Cat.Sniff + false + /* testDNFTypePropertyMultiFullyQualified */ + | (\Fully\Qualified\NameA&\Fully\Qualified\NameB) $multiDnf; + + /* testDNFTypePropertyWithReadOnlyKeyword1 */ + protected readonly (A&B) | /* testDNFTypePropertyWithReadOnlyKeyword2 */ (C&D) $readonly; + + /* testDNFTypePropertyWithStaticAndReadOnlyKeywords */ + static readonly (A&B&C)|array $staticReadonly; + + /* testDNFTypePropertyWithOnlyStaticKeyword */ + static (A&B&C)|true $onlyStaticModified; + + public function paramTypes( + /* testDNFTypeParam1WithAttribute */ + #[MyAttribute] + (\Foo&Bar)|int|float $paramA /* testParensNoOwnerParamDefaultValue */ = SOMETHING | (CONSTANT_A & CONSTANT_B), + + /* testDNFTypeParam2 */ + (Foo&\Bar) /* testDNFTypeParam3 */ |(Baz&Fop) &...$paramB, + ) { + /* testParensNoOwnerInReturnValue1 */ + return ( + /* testParensNoOwnerInReturnValue2 */ + ($a1 & $b1) | + /* testParensNoOwnerInReturnValue3 */ + ($a2 & $b2) + ) + $c; + } + + public function identifierNames( + /* testDNFTypeParamNamespaceRelative */ + (namespace\Sub\NameA&namespace\Sub\NameB)|false $paramA, + /* testDNFTypeParamPartiallyQualified */ + Partially\Qualified\NameC|(Partially\Qualified\NameA&Partially\Qualified\NameB) $paramB, + /* testDNFTypeParamFullyQualified */ + name|(\Fully\Qualified\NameA&\Fully\Qualified\NameB) $paramC, + ) {} + + public function __construct( + /* testDNFTypeConstructorPropertyPromotion1 */ + public (A&B)| /* testDNFTypeConstructorPropertyPromotion2 */ (A&D) $property + ) {} + + public function returnType()/* testDNFTypeReturnType1 */ : A|(B&D)|/* testDNFTypeReturnType2 */(B&W)|null {} + + abstract public function abstractMethod(): /* testDNFTypeAbstractMethodReturnType1 */ (X&Y) /* testDNFTypeAbstractMethodReturnType2 */ |(W&Z); + + public function identifierNamesReturnRelative( + ) : /* testDNFTypeReturnTypeNamespaceRelative */ (namespace\Sub\NameA&namespace\Sub\NameB)|namespace\Sub\NameC {} + + public function identifierNamesReturnPQ( + ) : /* testDNFTypeReturnPartiallyQualified */Partially\Qualified\NameA|(Partially\Qualified\NameB&Partially\Qualified\NameC) {} + + // Illegal type: segments which are strict subsets of others are disallowed, but that's not the concern of the tokenizer. + public function identifierNamesReturnFQ( + ) /* testDNFTypeReturnFullyQualified */ : (\Fully\Qualified\NameA&\Fully\Qualified\NameB)|\Fully\Qualified\NameB {} +} + +function globalFunctionWithSpreadAndReference( + /* testDNFTypeWithReference */ + float|(B&A) &$paramA, + /* testDNFTypeWithSpreadOperator */ + string|(B&D) ...$paramB +) {} + + +$closureWithParamType = function ( /* testDNFTypeClosureParamIllegalNullable */ ?(A&B)|bool $string) {}; + +/* testParensOwnerClosureAmpersandInDefaultValue */ +$closureWithReturnType = function ($string = NONSENSE & FAKE) /* testDNFTypeClosureReturn */ : (\Package\MyA&PackageB)|null {}; + +/* testParensOwnerArrowDNFUsedWithin */ +$arrowWithParamType = fn ( + /* testDNFTypeArrowParam */ + int|(A&B&C)|array $param, + /* testParensNoOwnerAmpersandInDefaultValue */ ?int $int = (CONSTA & CONSTB )| CONST_C +) + /* testParensNoOwnerInArrowReturnExpression */ + => ($param & $foo ) | $int; + +$arrowWithReturnType = fn ($param) : /* testDNFTypeArrowReturnType */ int|(A&B) => $param * 10; + +$arrowWithParamReturnByRef = fn &( + /* testDNFTypeArrowParamWithReturnByRef */ + (A&B)|null $param +) => $param * 10; + +function InvalidSyntaxes( + /* testDNFTypeParamIllegalUnnecessaryParens */ + (A&B) $parensNotNeeded, + + /* testDNFTypeParamIllegalIntersectUnionReversed */ + A&(B|D) $onlyIntersectAllowedWithinParensAndUnionOutside, + + /* testDNFTypeParamIllegalNestedParens */ + A|(B&(D|W)|null) $nestedParensNotAllowed, +) {} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php new file mode 100644 index 000000000..91d10ac3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateParenthesisNestingMapDNFTypesTest.php @@ -0,0 +1,374 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class CreateParenthesisNestingMapDNFTypesTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that parentheses when **not** used in a type declaration are correctly tokenized. + * + * @param string $testMarker The comment prefacing the target token. + * @param int|false $owner Optional. The parentheses owner or false when no parentheses owner is expected. + * + * @dataProvider dataNormalParentheses + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createParenthesisNestingMap + * + * @return void + */ + public function testNormalParentheses($testMarker, $owner=false) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS]); + $opener = $tokens[$openPtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_OPEN_PARENTHESIS (code)'); + + if ($owner !== false) { + $this->assertArrayHasKey('parenthesis_owner', $opener, 'Parenthesis owner is not set'); + $this->assertSame(($openPtr + $owner), $opener['parenthesis_owner'], 'Opener parenthesis owner is not the expected token'); + } else { + $this->assertArrayNotHasKey('parenthesis_owner', $opener, 'Parenthesis owner is set'); + } + + $this->assertArrayHasKey('parenthesis_opener', $opener, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $opener, 'Parenthesis closer is not set'); + $this->assertSame($openPtr, $opener['parenthesis_opener'], 'Parenthesis opener is not the expected token'); + + $closePtr = $opener['parenthesis_closer']; + $closer = $tokens[$closePtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_CLOSE_PARENTHESIS (code)'); + + if ($owner !== false) { + $this->assertArrayHasKey('parenthesis_owner', $closer, 'Parenthesis owner is not set'); + $this->assertSame(($openPtr + $owner), $closer['parenthesis_owner'], 'Closer parenthesis owner is not the expected token'); + } else { + $this->assertArrayNotHasKey('parenthesis_owner', $closer, 'Parenthesis owner is set'); + } + + $this->assertArrayHasKey('parenthesis_opener', $closer, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $closer, 'Parenthesis closer is not set'); + $this->assertSame($closePtr, $closer['parenthesis_closer'], 'Parenthesis closer is not the expected token'); + + for ($i = ($openPtr + 1); $i < $closePtr; $i++) { + $this->assertArrayHasKey('nested_parenthesis', $tokens[$i], "Nested parenthesis key not set on token $i ({$tokens[$i]['type']})"); + $this->assertArrayHasKey($openPtr, $tokens[$i]['nested_parenthesis'], 'Nested parenthesis is missing target parentheses set'); + $this->assertSame($closePtr, $tokens[$i]['nested_parenthesis'][$openPtr], 'Nested parenthesis closer not set correctly'); + } + + }//end testNormalParentheses() + + + /** + * Data provider. + * + * @see testNormalParentheses() + * + * @return array> + */ + public static function dataNormalParentheses() + { + // "Owner" offsets are relative to the open parenthesis. + return [ + 'parens without owner' => [ + 'testMarker' => '/* testParensNoOwner */', + ], + 'parens without owner in ternary then' => [ + 'testMarker' => '/* testParensNoOwnerInTernary */', + ], + 'parens without owner in short ternary' => [ + 'testMarker' => '/* testParensNoOwnerInShortTernary */', + ], + 'parens with owner: function; & in default value' => [ + 'testMarker' => '/* testParensOwnerFunctionAmpersandInDefaultValue */', + 'owner' => -3, + ], + 'parens with owner: closure; param declared by & ref' => [ + 'testMarker' => '/* testParensOwnerClosureAmpersandParamRef */', + 'owner' => -1, + ], + 'parens with owner: if' => [ + 'testMarker' => '/* testParensOwnerIf */', + 'owner' => -2, + ], + 'parens without owner in if condition' => [ + 'testMarker' => '/* testParensNoOwnerInIfCondition */', + ], + 'parens with owner: for' => [ + 'testMarker' => '/* testParensOwnerFor */', + 'owner' => -2, + ], + 'parens without owner in for condition' => [ + 'testMarker' => '/* testParensNoOwnerInForCondition */', + ], + 'parens with owner: match' => [ + 'testMarker' => '/* testParensOwnerMatch */', + 'owner' => -1, + ], + 'parens with owner: array' => [ + 'testMarker' => '/* testParensOwnerArray */', + 'owner' => -2, + ], + 'parens without owner in array; function call with & in callable' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallWithAmpersandInCallable */', + ], + 'parens with owner: fn; & in return value' => [ + 'testMarker' => '/* testParensOwnerArrowFn */', + 'owner' => -1, + ], + 'parens with owner: list with reference vars' => [ + 'testMarker' => '/* testParensOwnerListWithRefVars */', + 'owner' => -1, + ], + 'parens without owner, function call with DNF look-a-like param' => [ + 'testMarker' => '/* testParensNoOwnerFunctionCallwithDNFLookALikeParam */', + ], + + 'parens without owner in OO const default value' => [ + 'testMarker' => '/* testParensNoOwnerOOConstDefaultValue */', + ], + 'parens without owner in property default 1' => [ + 'testMarker' => '/* testParensNoOwnerPropertyDefaultValue1 */', + ], + 'parens without owner in property default 2' => [ + 'testMarker' => '/* testParensNoOwnerPropertyDefaultValue2 */', + ], + 'parens without owner in param default value' => [ + 'testMarker' => '/* testParensNoOwnerParamDefaultValue */', + ], + 'parens without owner in return statement 1' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue1 */', + ], + 'parens without owner in return statement 2' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue2 */', + ], + 'parens without owner in return statement 3' => [ + 'testMarker' => '/* testParensNoOwnerInReturnValue3 */', + ], + 'parens with owner: closure; & in default value' => [ + 'testMarker' => '/* testParensOwnerClosureAmpersandInDefaultValue */', + 'owner' => -2, + ], + 'parens with owner: fn; dnf used within' => [ + 'testMarker' => '/* testParensOwnerArrowDNFUsedWithin */', + 'owner' => -2, + ], + 'parens without owner: default value for param in arrow function' => [ + 'testMarker' => '/* testParensNoOwnerAmpersandInDefaultValue */', + ], + 'parens without owner in arrow function return expression' => [ + 'testMarker' => '/* testParensNoOwnerInArrowReturnExpression */', + ], + ]; + + }//end dataNormalParentheses() + + + /** + * Test that parentheses when used in a DNF type declaration are correctly tokenized. + * + * Includes verifying that: + * - the tokens between the parentheses all have a "nested_parenthesis" key. + * - all ampersands between the parentheses are tokenized as T_TYPE_INTERSECTION. + * + * @param string $testMarker The comment prefacing the target token. + * + * @dataProvider dataDNFTypeParentheses + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createParenthesisNestingMap + * + * @return void + */ + public function testDNFTypeParentheses($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + + $openPtr = $this->getTargetToken($testMarker, [T_OPEN_PARENTHESIS, T_TYPE_OPEN_PARENTHESIS]); + $opener = $tokens[$openPtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_TYPE_OPEN_PARENTHESIS, $opener['code'], 'Token tokenized as '.$opener['type'].', not T_TYPE_OPEN_PARENTHESIS (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $opener, 'Parenthesis owner is set'); + $this->assertArrayHasKey('parenthesis_opener', $opener, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $opener, 'Parenthesis closer is not set'); + $this->assertSame($openPtr, $opener['parenthesis_opener'], 'Parenthesis opener is not the expected token'); + + $closePtr = $opener['parenthesis_closer']; + $closer = $tokens[$closePtr]; + + // Make sure we're looking at the right token. + $this->assertSame(T_TYPE_CLOSE_PARENTHESIS, $closer['code'], 'Token tokenized as '.$closer['type'].', not T_TYPE_CLOSE_PARENTHESIS (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $closer, 'Parenthesis owner is set'); + $this->assertArrayHasKey('parenthesis_opener', $closer, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $closer, 'Parenthesis closer is not set'); + $this->assertSame($closePtr, $closer['parenthesis_closer'], 'Parenthesis closer is not the expected token'); + + for ($i = ($openPtr + 1); $i < $closePtr; $i++) { + $this->assertArrayHasKey('nested_parenthesis', $tokens[$i], "Nested parenthesis key not set on token $i ({$tokens[$i]['type']})"); + $this->assertArrayHasKey($openPtr, $tokens[$i]['nested_parenthesis'], 'Nested parenthesis is missing target parentheses set'); + $this->assertSame($closePtr, $tokens[$i]['nested_parenthesis'][$openPtr], 'Nested parenthesis closer not set correctly'); + }//end for + + }//end testDNFTypeParentheses() + + + /** + * Data provider. + * + * @see testDNFTypeParentheses() + * + * @return array> + */ + public static function dataDNFTypeParentheses() + { + return [ + 'OO const type: unqualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstUnqualifiedClasses */', + ], + 'OO const type: modifiers in reverse order' => [ + 'testMarker' => '/* testDNFTypeOOConstReverseModifierOrder */', + ], + 'OO const type: multi-dnf part 1' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti1 */', + ], + 'OO const type: multi-dnf part 2' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti2 */', + ], + 'OO const type: multi-dnf part 3' => [ + 'testMarker' => '/* testDNFTypeOOConstMulti3 */', + ], + 'OO const type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeOOConstNamespaceRelative */', + ], + 'OO const type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstPartiallyQualified */', + ], + 'OO const type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeOOConstFullyQualified */', + ], + + 'OO property type: unqualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyUnqualifiedClasses */', + ], + 'OO property type: modifiers in reverse order' => [ + 'testMarker' => '/* testDNFTypePropertyReverseModifierOrder */', + ], + 'OO property type: multi-dnf namespace relative classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiNamespaceRelative */', + ], + 'OO property type: multi-dnf partially qualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiPartiallyQualified */', + ], + 'OO property type: multi-dnf fully qualified classes' => [ + 'testMarker' => '/* testDNFTypePropertyMultiFullyQualified */', + ], + + 'OO property type: multi-dnf with readonly keyword 1' => [ + 'testMarker' => '/* testDNFTypePropertyWithReadOnlyKeyword1 */', + ], + 'OO property type: multi-dnf with readonly keyword 2' => [ + 'testMarker' => '/* testDNFTypePropertyWithReadOnlyKeyword2 */', + ], + 'OO property type: with static and readonly keywords' => [ + 'testMarker' => '/* testDNFTypePropertyWithStaticAndReadOnlyKeywords */', + ], + 'OO property type: with only static keyword' => [ + 'testMarker' => '/* testDNFTypePropertyWithOnlyStaticKeyword */', + ], + 'OO method param type: first param' => [ + 'testMarker' => '/* testDNFTypeParam1WithAttribute */', + ], + 'OO method param type: second param, first DNF' => [ + 'testMarker' => '/* testDNFTypeParam2 */', + ], + 'OO method param type: second param, second DNF' => [ + 'testMarker' => '/* testDNFTypeParam3 */', + ], + 'OO method param type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeParamNamespaceRelative */', + ], + 'OO method param type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeParamPartiallyQualified */', + ], + 'OO method param type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeParamFullyQualified */', + ], + 'Constructor property promotion with multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeConstructorPropertyPromotion1 */', + ], + 'Constructor property promotion with multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeConstructorPropertyPromotion2 */', + ], + 'OO method return type: multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeReturnType1 */', + ], + 'OO method return type: multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeReturnType2 */', + ], + 'OO abstract method return type: multi DNF 1' => [ + 'testMarker' => '/* testDNFTypeAbstractMethodReturnType1 */', + ], + 'OO abstract method return type: multi DNF 2' => [ + 'testMarker' => '/* testDNFTypeAbstractMethodReturnType2 */', + ], + 'OO method return type: namespace relative classes' => [ + 'testMarker' => '/* testDNFTypeReturnTypeNamespaceRelative */', + ], + 'OO method return type: partially qualified classes' => [ + 'testMarker' => '/* testDNFTypeReturnPartiallyQualified */', + ], + 'OO method return type: fully qualified classes' => [ + 'testMarker' => '/* testDNFTypeReturnFullyQualified */', + ], + 'function param type: with reference' => [ + 'testMarker' => '/* testDNFTypeWithReference */', + ], + 'function param type: with spread' => [ + 'testMarker' => '/* testDNFTypeWithSpreadOperator */', + ], + 'closure param type: with illegal nullable' => [ + 'testMarker' => '/* testDNFTypeClosureParamIllegalNullable */', + ], + 'closure return type' => [ + 'testMarker' => '/* testDNFTypeClosureReturn */', + ], + 'arrow function param type' => [ + 'testMarker' => '/* testDNFTypeArrowParam */', + ], + 'arrow function return type' => [ + 'testMarker' => '/* testDNFTypeArrowReturnType */', + ], + 'arrow function param type with return by ref' => [ + 'testMarker' => '/* testDNFTypeArrowParamWithReturnByRef */', + ], + + 'illegal syntax: unnecessary parentheses (no union)' => [ + 'testMarker' => '/* testDNFTypeParamIllegalUnnecessaryParens */', + ], + 'illegal syntax: union within parentheses, intersect outside' => [ + 'testMarker' => '/* testDNFTypeParamIllegalIntersectUnionReversed */', + ], + 'illegal syntax: nested parentheses' => [ + 'testMarker' => '/* testDNFTypeParamIllegalNestedParens */', + ], + ]; + + }//end dataDNFTypeParentheses() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocCloserTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocCloserTest.inc new file mode 100644 index 000000000..a800980b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocCloserTest.inc @@ -0,0 +1,43 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +/** + * Heredoc/nowdoc closer token test. + * + * @requires PHP 7.3 + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + */ +final class CreatePositionMapHeredocNowdocCloserTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that leading (indent) whitespace in a heredoc/nowdoc closer token get the tab replacement treatment. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $expected Expectations for the token array. + * + * @dataProvider dataHeredocNowdocCloserTabReplacement + * + * @return void + */ + public function testHeredocNowdocCloserTabReplacement($testMarker, $expected) + { + $tokens = $this->phpcsFile->getTokens(); + + $closer = $this->getTargetToken($testMarker, [T_END_HEREDOC, T_END_NOWDOC]); + + foreach ($expected as $key => $value) { + if ($key === 'orig_content' && $value === null) { + $this->assertArrayNotHasKey($key, $tokens[$closer], "Unexpected 'orig_content' key found in the token array."); + continue; + } + + $this->assertArrayHasKey($key, $tokens[$closer], "Key $key not found in the token array."); + $this->assertSame($value, $tokens[$closer][$key], "Value for key $key does not match expectation."); + } + + }//end testHeredocNowdocCloserTabReplacement() + + + /** + * Data provider. + * + * @see testHeredocNowdocCloserTabReplacement() + * + * @return array>> + */ + public static function dataHeredocNowdocCloserTabReplacement() + { + return [ + 'Heredoc closer without indent' => [ + 'testMarker' => '/* testHeredocCloserNoIndent */', + 'expected' => [ + 'length' => 3, + 'content' => 'EOD', + 'orig_content' => null, + ], + ], + 'Nowdoc closer without indent' => [ + 'testMarker' => '/* testNowdocCloserNoIndent */', + 'expected' => [ + 'length' => 3, + 'content' => 'EOD', + 'orig_content' => null, + ], + ], + 'Heredoc closer with indent, spaces' => [ + 'testMarker' => '/* testHeredocCloserSpaceIndent */', + 'expected' => [ + 'length' => 7, + 'content' => ' END', + 'orig_content' => null, + ], + ], + 'Nowdoc closer with indent, spaces' => [ + 'testMarker' => '/* testNowdocCloserSpaceIndent */', + 'expected' => [ + 'length' => 8, + 'content' => ' END', + 'orig_content' => null, + ], + ], + 'Heredoc closer with indent, tabs' => [ + 'testMarker' => '/* testHeredocCloserTabIndent */', + 'expected' => [ + 'length' => 8, + 'content' => ' END', + 'orig_content' => ' END', + ], + ], + 'Nowdoc closer with indent, tabs' => [ + 'testMarker' => '/* testNowdocCloserTabIndent */', + 'expected' => [ + 'length' => 7, + 'content' => ' END', + 'orig_content' => ' END', + ], + ], + ]; + + }//end dataHeredocNowdocCloserTabReplacement() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocOpenerTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocOpenerTest.inc new file mode 100644 index 000000000..dc2b2f2dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapHeredocNowdocOpenerTest.inc @@ -0,0 +1,31 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +/** + * Heredoc/nowdoc opener token test. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + */ +final class CreatePositionMapHeredocNowdocOpenerTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that spaces/tabs in a heredoc/nowdoc opener token get the tab replacement treatment. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $expected Expectations for the token array. + * + * @dataProvider dataHeredocNowdocOpenerTabReplacement + * + * @return void + */ + public function testHeredocNowdocOpenerTabReplacement($testMarker, $expected) + { + $tokens = $this->phpcsFile->getTokens(); + $opener = $this->getTargetToken($testMarker, [T_START_HEREDOC, T_START_NOWDOC]); + + foreach ($expected as $key => $value) { + if ($key === 'orig_content' && $value === null) { + $this->assertArrayNotHasKey($key, $tokens[$opener], "Unexpected 'orig_content' key found in the token array."); + continue; + } + + $this->assertArrayHasKey($key, $tokens[$opener], "Key $key not found in the token array."); + $this->assertSame($value, $tokens[$opener][$key], "Value for key $key does not match expectation."); + } + + }//end testHeredocNowdocOpenerTabReplacement() + + + /** + * Data provider. + * + * @see testHeredocNowdocOpenerTabReplacement() + * + * @return array>> + */ + public static function dataHeredocNowdocOpenerTabReplacement() + { + return [ + 'Heredoc opener without space' => [ + 'testMarker' => '/* testHeredocOpenerNoSpace */', + 'expected' => [ + 'length' => 6, + 'content' => '<< null, + ], + ], + 'Nowdoc opener without space' => [ + 'testMarker' => '/* testNowdocOpenerNoSpace */', + 'expected' => [ + 'length' => 8, + 'content' => "<<<'EOD' +", + 'orig_content' => null, + ], + ], + 'Heredoc opener with space(s)' => [ + 'testMarker' => '/* testHeredocOpenerHasSpace */', + 'expected' => [ + 'length' => 7, + 'content' => '<<< END +', + 'orig_content' => null, + ], + ], + 'Nowdoc opener with space(s)' => [ + 'testMarker' => '/* testNowdocOpenerHasSpace */', + 'expected' => [ + 'length' => 21, + 'content' => "<<< 'END' +", + 'orig_content' => null, + ], + ], + 'Heredoc opener with tab(s)' => [ + 'testMarker' => '/* testHeredocOpenerHasTab */', + 'expected' => [ + 'length' => 18, + 'content' => '<<< "END" +', + 'orig_content' => '<<< "END" +', + ], + ], + 'Nowdoc opener with tab(s)' => [ + 'testMarker' => '/* testNowdocOpenerHasTab */', + 'expected' => [ + 'length' => 11, + 'content' => "<<< 'END' +", + 'orig_content' => "<<< 'END' +", + ], + ], + ]; + + }//end dataHeredocNowdocOpenerTabReplacement() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapTabWidth0Test.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapTabWidth0Test.php new file mode 100644 index 000000000..fd47bf7da --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapTabWidth0Test.php @@ -0,0 +1,107 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +/** + * Tab replacement test using tab width 0, means no tab replacement will take place. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + */ +final class CreatePositionMapTabWidth0Test extends ReplaceTabsInTokenTestCase +{ + + /** + * The tab width setting to use when tokenizing the file. + * + * @var integer + */ + protected $tabWidth = 0; + + + /** + * Data provider helper. + * + * @see ReplaceTabsInTokenTestCase::dataTabReplacement() + * + * @return array> + */ + public static function getTabReplacementExpected() + { + return [ + 'Tab indentation' => [ + 'length' => 2, + 'content' => ' ', + 'orig_content' => null, + ], + 'Mixed tab/space indentation' => [ + 'length' => 3, + 'content' => ' ', + 'orig_content' => null, + ], + 'Inline: single tab in text string' => [ + 'length' => 15, + 'content' => "'tab separated'", + 'orig_content' => null, + ], + 'Inline: single tab between each word in text string' => [ + 'length' => 24, + 'content' => '"tab $between each word"', + 'orig_content' => null, + ], + 'Inline: multiple tabs in heredoc' => [ + 'length' => 15, + 'content' => 'tab separated +', + 'orig_content' => null, + ], + 'Inline: multiple tabs between each word in nowdoc' => [ + 'length' => 27, + 'content' => 'tab between each word +', + 'orig_content' => null, + ], + 'Inline: mixed spaces/tabs in text string' => [ + 'length' => 20, + 'content' => "'tab separated'", + 'orig_content' => null, + ], + 'Inline: mixed spaces/tabs between each word in text string' => [ + 'length' => 31, + 'content' => '"tab $between each word"', + 'orig_content' => null, + ], + 'Inline: tab becomes single space in comment (with tabwidth 4)' => [ + 'length' => 50, + 'content' => '// -123 With tabwidth 4, the tab size should be 1. +', + 'orig_content' => null, + ], + 'Inline: tab becomes 2 spaces in comment (with tabwidth 4)' => [ + 'length' => 52, + 'content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + 'orig_content' => null, + ], + 'Inline: tab becomes 3 spaces in doc comment string (with tabwidth 4)' => [ + 'length' => 45, + 'content' => '-1 With tabwidth 4, the tab size should be 3.', + 'orig_content' => null, + ], + 'Inline: tab becomes 4 spaces in comment (with tabwidth 4)' => [ + 'length' => 47, + 'content' => '// - With tabwidth 4, the tab size should be 4. +', + 'orig_content' => null, + ], + ]; + + }//end getTabReplacementExpected() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapYieldFromTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapYieldFromTest.inc new file mode 100644 index 000000000..59365dd5c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreatePositionMapYieldFromTest.inc @@ -0,0 +1,15 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +/** + * Yield from token test. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createPositionMap + */ +final class CreatePositionMapYieldFromTest extends AbstractTokenizerTestCase +{ + + + /** + * Verify that spaces/tabs in "yield from" tokens get the tab replacement treatment. + * + * @param string $testMarker The comment prefacing the target token. + * @param array $expected Expectations for the token array. + * @param string $content Optional. The test token content to search for. + * Defaults to null. + * + * @dataProvider dataYieldFromTabReplacement + * + * @return void + */ + public function testYieldFromTabReplacement($testMarker, $expected, $content=null) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, [T_YIELD_FROM], $content); + + foreach ($expected as $key => $value) { + if ($key === 'orig_content' && $value === null) { + $this->assertArrayNotHasKey($key, $tokens[$target], "Unexpected 'orig_content' key found in the token array."); + continue; + } + + $this->assertArrayHasKey($key, $tokens[$target], "Key $key not found in the token array."); + $this->assertSame($value, $tokens[$target][$key], "Value for key $key does not match expectation."); + } + + }//end testYieldFromTabReplacement() + + + /** + * Data provider. + * + * @see testYieldFromTabReplacement() + * + * @return array>> + */ + public static function dataYieldFromTabReplacement() + { + return [ + 'Yield from, single line, single space' => [ + 'testMarker' => '/* testYieldFromHasSingleSpace */', + 'expected' => [ + 'length' => 10, + 'content' => 'yield from', + 'orig_content' => null, + ], + ], + 'Yield from, single line, multiple spaces' => [ + 'testMarker' => '/* testYieldFromHasMultiSpace */', + 'expected' => [ + 'length' => 14, + 'content' => 'yield from', + 'orig_content' => null, + ], + ], + 'Yield from, single line, has tabs' => [ + 'testMarker' => '/* testYieldFromHasTabs */', + 'expected' => [ + 'length' => 16, + 'content' => 'yield from', + 'orig_content' => 'yield from', + ], + ], + 'Yield from, single line, mix of tabs and spaces' => [ + 'testMarker' => '/* testYieldFromMixedTabsSpaces */', + 'expected' => [ + 'length' => 20, + 'content' => 'Yield From', + 'orig_content' => 'Yield From', + ], + ], + ]; + + }//end dataYieldFromTabReplacement() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.inc new file mode 100644 index 000000000..6d8adfcba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.inc @@ -0,0 +1,58 @@ + 10); + +/* testArrayWithComment */ +$var = Array /*comment*/ (1 => 10); + +/* testNestingArray */ +$var = array( + /* testNestedArray */ + array( + 'key' => 'value', + + /* testClosureReturnType */ + 'closure' => function($a) use($global) : Array {}, + ), +); + +/* testFunctionDeclarationParamType */ +function typedParam(array $a) {} + +/* testFunctionDeclarationReturnType */ +function returnType($a) : int|array|null {} + +class Bar { + /* testClassConst */ + const ARRAY = []; + + /* testClassMethod */ + public function array() {} + + /* testOOConstType */ + const array /* testTypedOOConstName */ ARRAY = /* testOOConstDefault */ array(); + + /* testOOPropertyType */ + protected array $property; +} + +class DNFTypes { + /* testOOConstDNFType */ + const (A&B)|array|(C&D) NAME = []; + + /* testOOPropertyDNFType */ + protected (A&B)|ARRAY|null $property; + + /* testFunctionDeclarationParamDNFType */ + public function name(null|array|(A&B) $param) { + /* testClosureDeclarationParamDNFType */ + $cl = function ( array|(A&B) $param) {}; + + /* testArrowDeclarationReturnDNFType */ + $arrow = fn($a): (A&B)|Array => new $a; + } +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.php new file mode 100644 index 000000000..4b7ac382a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/CreateTokenMapArrayParenthesesTest.php @@ -0,0 +1,212 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class CreateTokenMapArrayParenthesesTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the array keyword is correctly tokenized as `T_ARRAY`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayKeyword($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_ARRAY, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ARRAY (code)'); + + $this->assertArrayHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is not set'); + $this->assertArrayHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is not set'); + $this->assertArrayHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is not set'); + + }//end testArrayKeyword() + + + /** + * Data provider. + * + * @see testArrayKeyword() + * + * @return array> + */ + public static function dataArrayKeyword() + { + return [ + 'empty array' => [ + 'testMarker' => '/* testEmptyArray */', + ], + 'array with space before parenthesis' => [ + 'testMarker' => '/* testArrayWithSpace */', + ], + 'array with comment before parenthesis' => [ + 'testMarker' => '/* testArrayWithComment */', + 'testContent' => 'Array', + ], + 'nested: outer array' => [ + 'testMarker' => '/* testNestingArray */', + ], + 'nested: inner array' => [ + 'testMarker' => '/* testNestedArray */', + ], + 'OO constant default value' => [ + 'testMarker' => '/* testOOConstDefault */', + ], + ]; + + }//end dataArrayKeyword() + + + /** + * Test that the array keyword when used in a type declaration is correctly tokenized as `T_STRING`. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent Optional. The token content to look for. + * + * @dataProvider dataArrayType + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testArrayType($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testArrayType() + + + /** + * Data provider. + * + * @see testArrayType() + * + * @return array> + */ + public static function dataArrayType() + { + return [ + 'closure return type' => [ + 'testMarker' => '/* testClosureReturnType */', + 'testContent' => 'Array', + ], + 'function param type' => [ + 'testMarker' => '/* testFunctionDeclarationParamType */', + ], + 'function union return type' => [ + 'testMarker' => '/* testFunctionDeclarationReturnType */', + ], + 'OO constant type' => [ + 'testMarker' => '/* testOOConstType */', + ], + 'OO property type' => [ + 'testMarker' => '/* testOOPropertyType */', + ], + + 'OO constant DNF type' => [ + 'testMarker' => '/* testOOConstDNFType */', + ], + 'OO property DNF type' => [ + 'testMarker' => '/* testOOPropertyDNFType */', + 'testContent' => 'ARRAY', + ], + 'function param DNF type' => [ + 'testMarker' => '/* testFunctionDeclarationParamDNFType */', + ], + 'closure param DNF type' => [ + 'testMarker' => '/* testClosureDeclarationParamDNFType */', + ], + 'arrow return DNF type' => [ + 'testMarker' => '/* testArrowDeclarationReturnDNFType */', + 'testContent' => 'Array', + ], + ]; + + }//end dataArrayType() + + + /** + * Verify that the retokenization of `T_ARRAY` tokens to `T_STRING` is handled correctly + * for tokens with the contents 'array' which aren't in actual fact the array keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotArrayKeyword + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::createTokenMap + * + * @return void + */ + public function testNotArrayKeyword($testMarker, $testContent='array') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_ARRAY, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('parenthesis_owner', $tokenArray, 'Parenthesis owner is set'); + $this->assertArrayNotHasKey('parenthesis_opener', $tokenArray, 'Parenthesis opener is set'); + $this->assertArrayNotHasKey('parenthesis_closer', $tokenArray, 'Parenthesis closer is set'); + + }//end testNotArrayKeyword() + + + /** + * Data provider. + * + * @see testNotArrayKeyword() + * + * @return array> + */ + public static function dataNotArrayKeyword() + { + return [ + 'class-constant-name' => [ + 'testMarker' => '/* testClassConst */', + 'testContent' => 'ARRAY', + ], + 'class-method-name' => [ + 'testMarker' => '/* testClassMethod */', + ], + 'class-constant-name-after-type' => [ + 'testMarker' => '/* testTypedOOConstName */', + 'testContent' => 'ARRAY', + ], + ]; + + }//end dataNotArrayKeyword() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc new file mode 100644 index 000000000..13b87242e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapCaseKeywordConditionsTest.inc @@ -0,0 +1,95 @@ + + * @copyright 2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class RecurseScopeMapCaseKeywordConditionsTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the enum "case" is converted to T_ENUM_CASE. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataEnumCases + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testEnumCases($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $enumCase = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$enumCase]; + + // Make sure we're looking at the right token. + $this->assertSame(T_ENUM_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_ENUM_CASE (code)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testEnumCases() + + + /** + * Data provider. + * + * @see testEnumCases() + * + * @return array> + */ + public static function dataEnumCases() + { + return [ + 'enum case, no value' => ['/* testPureEnumCase */'], + 'enum case, integer value' => ['/* testBackingIntegerEnumCase */'], + 'enum case, string value' => ['/* testBackingStringEnumCase */'], + 'enum case, integer value in more complex enum' => ['/* testEnumCaseInComplexEnum */'], + 'enum case, keyword in mixed case' => ['/* testEnumCaseIsCaseInsensitive */'], + 'enum case, after switch statement' => ['/* testEnumCaseAfterSwitch */'], + 'enum case, after switch statement using alternative syntax' => ['/* testEnumCaseAfterSwitchWithEndSwitch */'], + ]; + + }//end dataEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataNotEnumCases + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testNotEnumCases($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $case = $this->getTargetToken($testMarker, [T_ENUM_CASE, T_CASE]); + $tokenArray = $tokens[$case]; + + // Make sure we're looking at the right token. + $this->assertSame(T_CASE, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_CASE (code)'); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + + }//end testNotEnumCases() + + + /** + * Data provider. + * + * @see testNotEnumCases() + * + * @return array> + */ + public static function dataNotEnumCases() + { + return [ + 'switch case with constant, semicolon condition end' => ['/* testCaseWithSemicolonIsNotEnumCase */'], + 'switch case with constant, colon condition end' => ['/* testCaseWithConstantIsNotEnumCase */'], + 'switch case with constant, comparison' => ['/* testCaseWithConstantAndIdenticalIsNotEnumCase */'], + 'switch case with constant, assignment' => ['/* testCaseWithAssigmentToConstantIsNotEnumCase */'], + 'switch case with constant, keyword in mixed case' => ['/* testIsNotEnumCaseIsCaseInsensitive */'], + 'switch case, body in curlies declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch1 */'], + 'switch case, body after semicolon declares enum' => ['/* testCaseInSwitchWhenCreatingEnumInSwitch2 */'], + ]; + + }//end dataNotEnumCases() + + + /** + * Test that "case" that is not enum case is still tokenized as `T_CASE`. + * + * @param string $testMarker The comment which prefaces the target token in the test file. + * + * @dataProvider dataKeywordAsEnumCaseNameShouldBeString + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testKeywordAsEnumCaseNameShouldBeString($testMarker) + { + $tokens = $this->phpcsFile->getTokens(); + $enumCaseName = $this->getTargetToken($testMarker, [T_STRING, T_INTERFACE, T_TRAIT, T_ENUM, T_FUNCTION, T_FALSE, T_DEFAULT, T_ARRAY]); + $tokenArray = $tokens[$enumCaseName]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testKeywordAsEnumCaseNameShouldBeString() + + + /** + * Data provider. + * + * @see testKeywordAsEnumCaseNameShouldBeString() + * + * @return array> + */ + public static function dataKeywordAsEnumCaseNameShouldBeString() + { + return [ + '"interface" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString1 */'], + '"trait" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString2 */'], + '"enum" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString3 */'], + '"function" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString4 */'], + '"false" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString5 */'], + '"default" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString6 */'], + '"array" as case name' => ['/* testKeywordAsEnumCaseNameShouldBeString7 */'], + ]; + + }//end dataKeywordAsEnumCaseNameShouldBeString() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc new file mode 100644 index 000000000..648149d2f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.inc @@ -0,0 +1,203 @@ + 1, + 2 => 2, + /* testSimpleMatchDefault */ + default => 'default', + }; +} + +function switchWithDefault($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefault */ + default: + return 'default'; + } +} + +function switchWithDefaultAndCurlies($i) { + switch ($i) { + case 1: + return 1; + case 2: + return 2; + /* testSimpleSwitchDefaultWithCurlies */ + default: { + return 'default'; + } + } +} + +function matchWithDefaultInSwitch() { + switch ($something) { + case 'foo': + $var = [1, 2, 3]; + $var = match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase1 */ + default => 'default', + }; + continue; + + case 'bar' : + $i = callMe($a, $b); + return match ($i) { + 1 => 1, + /* testMatchDefaultNestedInSwitchCase2 */ + default => 'default', + }; + + /* testSwitchDefault */ + default; + echo 'something', match ($i) { + 1, => 1, + /* testMatchDefaultNestedInSwitchDefault */ + default, => 'default', + }; + break; + } +} + +function switchWithDefaultInMatch() { + $x = match ($y) { + 5, 8 => function($z) { + switch($z) { + case 'a'; + $var = [1, 2, 3]; + return 'a'; + /* testSwitchDefaultNestedInMatchCase */ + default: + $var = [1, 2, 3]; + return 'default1'; + } + }, + /* testMatchDefault */ + default => function($z) { + switch($z) { + case 'a': + $i = callMe($a, $b); + return 'b'; + /* testSwitchDefaultNestedInMatchDefault */ + default: + $i = callMe($a, $b); + return 'default2'; + } + } + }; +} + +function shortArrayWithConstantKey() { + $arr = [ + /* testClassConstantAsShortArrayKey */ + SomeClass::DEFAULT => 1, + /* testClassPropertyAsShortArrayKey */ + SomeClass->DEFAULT => 1, + /* testNamespacedConstantAsShortArrayKey */ + // Intentional parse error PHP < 8.0. Reserved keyword used as namespaced constant. + SomeNamespace\DEFAULT => 1, + /* testFQNGlobalConstantAsShortArrayKey */ + // Intentional parse error in PHP < 8.0. Reserved keyword used as global constant. + \DEFAULT => 1, + ]; +} + +function longArrayWithConstantKey() { + $arr = array( + /* testClassConstantAsLongArrayKey */ + SomeClass::DEFAULT => 1, + ); +} + +function yieldWithConstantKey() { + /* testClassConstantAsYieldKey */ + yield SomeClass::DEFAULT => 1; +} + +function longArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKey */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */ + DEFAULT => array( + /* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ), + }, + ), + }; +} + +function shortArrayWithConstantKeyNestedInMatch() { + return match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKey */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */ + DEFAULT => [ + /* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */ + SomeClass::DEFAULT => 1, + ], + }, + ], + }; +} + + +function longArrayWithConstantKeyWithNestedMatch() { + return array( + /* testClassConstantAsLongArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInLongArray */ + DEFAULT => 'foo' + }, + ); +} + +function shortArrayWithConstantKeyWithNestedMatch() { + return [ + /* testClassConstantAsShortArrayKeyWithNestedMatch */ + SomeClass::DEFAULT => match($x) { + /* testMatchDefaultNestedInShortArray */ + DEFAULT => 'foo' + }, + ]; +} + +function switchWithConstantNonDefault($i) { + switch ($i) { + /* testClassConstantInSwitchCase */ + case SomeClass::DEFAULT: + return 1; + + /* testClassPropertyInSwitchCase */ + case SomeClass->DEFAULT: + return 2; + + /* testNamespacedConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as constant. + case SomeNamespace\DEFAULT: + return 2; + + /* testNamespaceRelativeConstantInSwitchCase */ + // Intentional parse error PHP < 8.0. Reserved keyword used as global constant. + case namespace\DEFAULT: + return 2; + } +} + +class Foo { + /* testClassConstant */ + const DEFAULT = 'foo'; + + /* testMethodDeclaration */ + public function default() {} +} diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php new file mode 100644 index 000000000..064ce8f40 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapDefaultKeywordConditionsTest.php @@ -0,0 +1,347 @@ + + * @copyright 2020-2021 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class RecurseScopeMapDefaultKeywordConditionsTest extends AbstractTokenizerTestCase +{ + + + /** + * Test the retokenization of the `default` keyword for match structure to `T_MATCH_DEFAULT`. + * + * Note: Cases and default structures within a match structure do *NOT* get case/default scope + * conditions, in contrast to case and default structures in switch control structures. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataMatchDefault + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testMatchDefault($testMarker, $testContent='default') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testMatchDefault() + + + /** + * Data provider. + * + * @see testMatchDefault() + * + * @return array> + */ + public static function dataMatchDefault() + { + return [ + 'simple_match_default' => [ + 'testMarker' => '/* testSimpleMatchDefault */', + ], + 'match_default_in_switch_case_1' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchCase1 */', + ], + 'match_default_in_switch_case_2' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchCase2 */', + ], + 'match_default_in_switch_default' => [ + 'testMarker' => '/* testMatchDefaultNestedInSwitchDefault */', + ], + 'match_default_containing_switch' => [ + 'testMarker' => '/* testMatchDefault */', + ], + + 'match_default_with_nested_long_array_and_default_key' => [ + 'testMarker' => '/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_long_array_and_default_key_2' => [ + 'testMarker' => '/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key' => [ + 'testMarker' => '/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */', + 'testContent' => 'DEFAULT', + ], + 'match_default_with_nested_short_array_and_default_key_2' => [ + 'testMarker' => '/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */', + 'testContent' => 'DEFAULT', + ], + 'match_default_in_long_array' => [ + 'testMarker' => '/* testMatchDefaultNestedInLongArray */', + 'testContent' => 'DEFAULT', + ], + 'match_default_in_short_array' => [ + 'testMarker' => '/* testMatchDefaultNestedInShortArray */', + 'testContent' => 'DEFAULT', + ], + ]; + + }//end dataMatchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_DEFAULT` tokens in switch control structures. + * + * Note: Cases and default structures within a switch control structure *do* get case/default scope + * conditions. + * + * @param string $testMarker The comment prefacing the target token. + * @param int $openerOffset The expected offset of the scope opener in relation to the testMarker. + * @param int $closerOffset The expected offset of the scope closer in relation to the testMarker. + * @param int|null $conditionStop The expected offset at which tokens stop having T_DEFAULT as a scope condition. + * @param string $testContent The token content to look for. + * + * @dataProvider dataSwitchDefault + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testSwitchDefault($testMarker, $openerOffset, $closerOffset, $conditionStop=null, $testContent='default') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + $expectedScopeOpener = ($token + $openerOffset); + $expectedScopeCloser = ($token + $closerOffset); + + // Make sure we're looking at the right token. + $this->assertSame(T_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_DEFAULT (code)'); + + $this->assertArrayHasKey('scope_condition', $tokenArray, 'Scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokenArray, 'Scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokenArray, 'Scope closer is not set'); + $this->assertSame($token, $tokenArray['scope_condition'], 'Scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokenArray['scope_opener'], 'Scope opener of the T_DEFAULT token incorrect'); + $this->assertSame($expectedScopeCloser, $tokenArray['scope_closer'], 'Scope closer of the T_DEFAULT token incorrect'); + + $opener = $tokenArray['scope_opener']; + $this->assertArrayHasKey('scope_condition', $tokens[$opener], 'Opener scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Opener scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Opener scope closer is not set'); + $this->assertSame($token, $tokens[$opener]['scope_condition'], 'Opener scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokens[$opener]['scope_opener'], 'T_DEFAULT opener scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$opener]['scope_closer'], 'T_DEFAULT opener scope closer token incorrect'); + + $closer = $tokenArray['scope_closer']; + $this->assertArrayHasKey('scope_condition', $tokens[$closer], 'Closer scope condition is not set'); + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Closer scope opener is not set'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Closer scope closer is not set'); + $this->assertSame($token, $tokens[$closer]['scope_condition'], 'Closer scope condition is not the T_DEFAULT token'); + $this->assertSame($expectedScopeOpener, $tokens[$closer]['scope_opener'], 'T_DEFAULT closer scope opener token incorrect'); + $this->assertSame($expectedScopeCloser, $tokens[$closer]['scope_closer'], 'T_DEFAULT closer scope closer token incorrect'); + + if (($opener + 1) !== $closer) { + $end = $closer; + if (isset($conditionStop) === true) { + $end = $conditionStop; + } + + for ($i = ($opener + 1); $i < $end; $i++) { + $this->assertArrayHasKey( + $token, + $tokens[$i]['conditions'], + 'T_DEFAULT condition not added for token belonging to the T_DEFAULT structure' + ); + } + } + + }//end testSwitchDefault() + + + /** + * Data provider. + * + * @see testSwitchDefault() + * + * @return array> + */ + public static function dataSwitchDefault() + { + return [ + 'simple_switch_default' => [ + 'testMarker' => '/* testSimpleSwitchDefault */', + 'openerOffset' => 1, + 'closerOffset' => 4, + ], + 'simple_switch_default_with_curlies' => [ + // For a default structure with curly braces, the scope opener + // will be the open curly and the closer the close curly. + // However, scope conditions will not be set for open to close, + // but only for the open token up to the "break/return/continue" etc. + 'testMarker' => '/* testSimpleSwitchDefaultWithCurlies */', + 'openerOffset' => 3, + 'closerOffset' => 12, + 'conditionStop' => 6, + ], + 'switch_default_toplevel' => [ + 'testMarker' => '/* testSwitchDefault */', + 'openerOffset' => 1, + 'closerOffset' => 43, + ], + 'switch_default_nested_in_match_case' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchCase */', + 'openerOffset' => 1, + 'closerOffset' => 20, + ], + 'switch_default_nested_in_match_default' => [ + 'testMarker' => '/* testSwitchDefaultNestedInMatchDefault */', + 'openerOffset' => 1, + 'closerOffset' => 18, + ], + ]; + + }//end dataSwitchDefault() + + + /** + * Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively + * impact the tokenization of `T_STRING` tokens with the contents 'default' which aren't in + * actual fact the default keyword. + * + * @param string $testMarker The comment prefacing the target token. + * @param string $testContent The token content to look for. + * + * @dataProvider dataNotDefaultKeyword + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT') + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent); + $tokenArray = $tokens[$token]; + + // Make sure we're looking at the right token. + $this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)'); + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testNotDefaultKeyword() + + + /** + * Data provider. + * + * @see testNotDefaultKeyword() + * + * @return array> + */ + public static function dataNotDefaultKeyword() + { + return [ + 'class-constant-as-short-array-key' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKey */', + ], + 'class-property-as-short-array-key' => [ + 'testMarker' => '/* testClassPropertyAsShortArrayKey */', + ], + 'namespaced-constant-as-short-array-key' => [ + 'testMarker' => '/* testNamespacedConstantAsShortArrayKey */', + ], + 'fqn-global-constant-as-short-array-key' => [ + 'testMarker' => '/* testFQNGlobalConstantAsShortArrayKey */', + ], + 'class-constant-as-long-array-key' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKey */', + ], + 'class-constant-as-yield-key' => [ + 'testMarker' => '/* testClassConstantAsYieldKey */', + ], + + 'class-constant-as-long-array-key-nested-in-match' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyNestedInMatch */', + ], + 'class-constant-as-long-array-key-nested-in-match-2' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */', + ], + 'class-constant-as-short-array-key-nested-in-match' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyNestedInMatch */', + ], + 'class-constant-as-short-array-key-nested-in-match-2' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */', + ], + 'class-constant-as-long-array-key-with-nested-match' => [ + 'testMarker' => '/* testClassConstantAsLongArrayKeyWithNestedMatch */', + ], + 'class-constant-as-short-array-key-with-nested-match' => [ + 'testMarker' => '/* testClassConstantAsShortArrayKeyWithNestedMatch */', + ], + + 'class-constant-in-switch-case' => [ + 'testMarker' => '/* testClassConstantInSwitchCase */', + ], + 'class-property-in-switch-case' => [ + 'testMarker' => '/* testClassPropertyInSwitchCase */', + ], + 'namespaced-constant-in-switch-case' => [ + 'testMarker' => '/* testNamespacedConstantInSwitchCase */', + ], + 'namespace-relative-constant-in-switch-case' => [ + 'testMarker' => '/* testNamespaceRelativeConstantInSwitchCase */', + ], + + 'class-constant-declaration' => [ + 'testMarker' => '/* testClassConstant */', + ], + 'class-method-declaration' => [ + 'testMarker' => '/* testMethodDeclaration */', + 'testContent' => 'default', + ], + ]; + + }//end dataNotDefaultKeyword() + + + /** + * Test a specific edge case where a scope opener would be incorrectly set. + * + * @link https://github.com/squizlabs/PHP_CodeSniffer/issues/3326 + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testIssue3326() + { + $tokens = $this->phpcsFile->getTokens(); + + $token = $this->getTargetToken('/* testClassConstant */', [T_SEMICOLON]); + $tokenArray = $tokens[$token]; + + $this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set'); + $this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set'); + $this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set'); + + }//end testIssue3326() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.inc new file mode 100644 index 000000000..38e5a47d5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.inc @@ -0,0 +1,19 @@ + new namespace\Baz; diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.php new file mode 100644 index 000000000..8ed593bf9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/RecurseScopeMapWithNamespaceOperatorTest.php @@ -0,0 +1,98 @@ + + * @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +final class RecurseScopeMapWithNamespaceOperatorTest extends AbstractTokenizerTestCase +{ + + + /** + * Test that the scope opener/closers are set correctly when the namespace keyword is encountered as an operator. + * + * @param string $testMarker The comment which prefaces the target tokens in the test file. + * @param array $tokenTypes The token type to search for. + * @param array $open Optional. The token type for the scope opener. + * @param array $close Optional. The token type for the scope closer. + * + * @dataProvider dataScopeSetting + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap + * + * @return void + */ + public function testScopeSetting($testMarker, $tokenTypes, $open=T_OPEN_CURLY_BRACKET, $close=T_CLOSE_CURLY_BRACKET) + { + $tokens = $this->phpcsFile->getTokens(); + + $target = $this->getTargetToken($testMarker, $tokenTypes); + $opener = $this->getTargetToken($testMarker, $open); + $closer = $this->getTargetToken($testMarker, $close); + + $this->assertArrayHasKey('scope_opener', $tokens[$target], 'Scope opener missing'); + $this->assertArrayHasKey('scope_closer', $tokens[$target], 'Scope closer missing'); + $this->assertSame($opener, $tokens[$target]['scope_opener'], 'Scope opener not same'); + $this->assertSame($closer, $tokens[$target]['scope_closer'], 'Scope closer not same'); + + $this->assertArrayHasKey('scope_opener', $tokens[$opener], 'Scope opener missing for open curly'); + $this->assertArrayHasKey('scope_closer', $tokens[$opener], 'Scope closer missing for open curly'); + $this->assertSame($opener, $tokens[$opener]['scope_opener'], 'Scope opener not same for open curly'); + $this->assertSame($closer, $tokens[$opener]['scope_closer'], 'Scope closer not same for open curly'); + + $this->assertArrayHasKey('scope_opener', $tokens[$closer], 'Scope opener missing for close curly'); + $this->assertArrayHasKey('scope_closer', $tokens[$closer], 'Scope closer missing for close curly'); + $this->assertSame($opener, $tokens[$closer]['scope_opener'], 'Scope opener not same for close curly'); + $this->assertSame($closer, $tokens[$closer]['scope_closer'], 'Scope closer not same for close curly'); + + }//end testScopeSetting() + + + /** + * Data provider. + * + * @see testScopeSetting() + * + * @return array>> + */ + public static function dataScopeSetting() + { + return [ + 'class which extends namespace relative name' => [ + 'testMarker' => '/* testClassExtends */', + 'tokenTypes' => [T_CLASS], + ], + 'class which implements namespace relative name' => [ + 'testMarker' => '/* testClassImplements */', + 'tokenTypes' => [T_ANON_CLASS], + ], + 'interface which extend namespace relative name' => [ + 'testMarker' => '/* testInterfaceExtends */', + 'tokenTypes' => [T_INTERFACE], + ], + 'namespace relative name in function return type' => [ + 'testMarker' => '/* testFunctionReturnType */', + 'tokenTypes' => [T_FUNCTION], + ], + 'namespace relative name in closure return type' => [ + 'testMarker' => '/* testClosureReturnType */', + 'tokenTypes' => [T_CLOSURE], + ], + 'namespace relative name in arrow function return type' => [ + 'testMarker' => '/* testArrowFunctionReturnType */', + 'tokenTypes' => [T_FN], + 'open' => [T_FN_ARROW], + 'close' => [T_SEMICOLON], + ], + ]; + + }//end dataScopeSetting() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenMiscTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenMiscTest.php new file mode 100644 index 000000000..f4bd711a6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenMiscTest.php @@ -0,0 +1,124 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use PHP_CodeSniffer\Files\DummyFile; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHPUnit\Framework\TestCase; + +/** + * Miscellaneous tests for tab replacement. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::replaceTabsInToken + */ +final class ReplaceTabsInTokenMiscTest extends TestCase +{ + + + /** + * Test that when no tab width is set or passed, the tab width will be set to 1. + * + * @return void + */ + public function testTabWidthNotSet() + { + $config = new ConfigDouble(); + $ruleset = new Ruleset($config); + + $content = <<parse(); + + $tokens = $phpcsFile->getTokens(); + $target = $phpcsFile->findNext(T_WHITESPACE, 0); + + // Verify initial state. + $this->assertTrue(is_int($target), 'Target token was not found'); + $this->assertSame(' ', $tokens[$target]['content'], 'Content after initial parsing does not contain tabs'); + $this->assertSame(2, $tokens[$target]['length'], 'Length after initial parsing is not as expected'); + $this->assertArrayNotHasKey('orig_content', $tokens[$target], "Key 'orig_content' found in the initial token array."); + + $phpcsFile->tokenizer->replaceTabsInToken($tokens[$target]); + + // Verify tab replacement. + $this->assertSame(' ', $tokens[$target]['content'], 'Content after tab replacement is not as expected'); + $this->assertSame(2, $tokens[$target]['length'], 'Length after tab replacement is not as expected'); + $this->assertArrayHasKey('orig_content', $tokens[$target], "Key 'orig_content' not found in the token array."); + + }//end testTabWidthNotSet() + + + /** + * Test that the length calculation handles text in non-ascii encodings correctly. + * + * @requires extension iconv + * + * @return void + */ + public function testLengthSettingRespectsEncoding() + { + $config = new ConfigDouble(); + $config->tabWidth = 4; + $ruleset = new Ruleset($config); + + $content = <<parse(); + + $tokens = $phpcsFile->getTokens(); + $target = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, 0); + + $this->assertTrue(is_int($target), 'Target token was not found'); + $this->assertSame("'паÑха паÑха'", $tokens[$target]['content'], 'Content is not as expected'); + $this->assertSame(17, $tokens[$target]['length'], 'Length is not as expected'); + $this->assertArrayHasKey('orig_content', $tokens[$target], "Key 'orig_content' not found in the token array."); + $this->assertSame("'паÑха паÑха'", $tokens[$target]['orig_content'], 'Orig_content is not as expected'); + + }//end testLengthSettingRespectsEncoding() + + + /** + * Test that the length calculation falls back to byte length if iconv detects an illegal character. + * + * @requires extension iconv + * + * @return void + */ + public function testLengthSettingFallsBackToBytesWhenTextContainsIllegalChars() + { + $config = new ConfigDouble(); + $config->tabWidth = 4; + $ruleset = new Ruleset($config); + + $content = <<parse(); + + $tokens = $phpcsFile->getTokens(); + $target = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, 0); + + $this->assertTrue(is_int($target), 'Target token was not found'); + $this->assertSame(11, $tokens[$target]['length'], 'Length is not as expected'); + $this->assertArrayHasKey('orig_content', $tokens[$target], "Key 'orig_content' not found in the token array."); + + }//end testLengthSettingFallsBackToBytesWhenTextContainsIllegalChars() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth1Test.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth1Test.php new file mode 100644 index 000000000..296215345 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth1Test.php @@ -0,0 +1,111 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +/** + * Tab replacement test using tab width 1. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::replaceTabsInToken + */ +final class ReplaceTabsInTokenTabWidth1Test extends ReplaceTabsInTokenTestCase +{ + + /** + * The tab width setting to use when tokenizing the file. + * + * @var integer + */ + protected $tabWidth = 1; + + + /** + * Data provider helper. + * + * @see ReplaceTabsInTokenTestCase::dataTabReplacement() + * + * @return array> + */ + public static function getTabReplacementExpected() + { + return [ + 'Tab indentation' => [ + 'length' => 2, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Mixed tab/space indentation' => [ + 'length' => 3, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Inline: single tab in text string' => [ + 'length' => 15, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: single tab between each word in text string' => [ + 'length' => 24, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: multiple tabs in heredoc' => [ + 'length' => 15, + 'content' => 'tab separated +', + 'orig_content' => 'tab separated +', + ], + 'Inline: multiple tabs between each word in nowdoc' => [ + 'length' => 27, + 'content' => 'tab between each word +', + 'orig_content' => 'tab between each word +', + ], + 'Inline: mixed spaces/tabs in text string' => [ + 'length' => 20, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: mixed spaces/tabs between each word in text string' => [ + 'length' => 31, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: tab becomes single space in comment (with tabwidth 4)' => [ + 'length' => 50, + 'content' => '// -123 With tabwidth 4, the tab size should be 1. +', + 'orig_content' => '// -123 With tabwidth 4, the tab size should be 1. +', + ], + 'Inline: tab becomes 2 spaces in comment (with tabwidth 4)' => [ + 'length' => 52, + 'content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + 'orig_content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + ], + 'Inline: tab becomes 3 spaces in doc comment string (with tabwidth 4)' => [ + 'length' => 45, + 'content' => '-1 With tabwidth 4, the tab size should be 3.', + 'orig_content' => '-1 With tabwidth 4, the tab size should be 3.', + ], + 'Inline: tab becomes 4 spaces in comment (with tabwidth 4)' => [ + 'length' => 47, + 'content' => '// - With tabwidth 4, the tab size should be 4. +', + 'orig_content' => '// - With tabwidth 4, the tab size should be 4. +', + ], + ]; + + }//end getTabReplacementExpected() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth2Test.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth2Test.php new file mode 100644 index 000000000..92de221d8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth2Test.php @@ -0,0 +1,111 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +/** + * Tab replacement test using tab width 2. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::replaceTabsInToken + */ +final class ReplaceTabsInTokenTabWidth2Test extends ReplaceTabsInTokenTestCase +{ + + /** + * The tab width setting to use when tokenizing the file. + * + * @var integer + */ + protected $tabWidth = 2; + + + /** + * Data provider helper. + * + * @see ReplaceTabsInTokenTestCase::dataTabReplacement() + * + * @return array> + */ + public static function getTabReplacementExpected() + { + return [ + 'Tab indentation' => [ + 'length' => 4, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Mixed tab/space indentation' => [ + 'length' => 4, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Inline: single tab in text string' => [ + 'length' => 15, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: single tab between each word in text string' => [ + 'length' => 26, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: multiple tabs in heredoc' => [ + 'length' => 17, + 'content' => 'tab separated +', + 'orig_content' => 'tab separated +', + ], + 'Inline: multiple tabs between each word in nowdoc' => [ + 'length' => 34, + 'content' => 'tab between each word +', + 'orig_content' => 'tab between each word +', + ], + 'Inline: mixed spaces/tabs in text string' => [ + 'length' => 23, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: mixed spaces/tabs between each word in text string' => [ + 'length' => 32, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: tab becomes single space in comment (with tabwidth 4)' => [ + 'length' => 50, + 'content' => '// -123 With tabwidth 4, the tab size should be 1. +', + 'orig_content' => '// -123 With tabwidth 4, the tab size should be 1. +', + ], + 'Inline: tab becomes 2 spaces in comment (with tabwidth 4)' => [ + 'length' => 53, + 'content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + 'orig_content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + ], + 'Inline: tab becomes 3 spaces in doc comment string (with tabwidth 4)' => [ + 'length' => 45, + 'content' => '-1 With tabwidth 4, the tab size should be 3.', + 'orig_content' => '-1 With tabwidth 4, the tab size should be 3.', + ], + 'Inline: tab becomes 4 spaces in comment (with tabwidth 4)' => [ + 'length' => 48, + 'content' => '// - With tabwidth 4, the tab size should be 4. +', + 'orig_content' => '// - With tabwidth 4, the tab size should be 4. +', + ], + ]; + + }//end getTabReplacementExpected() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth4Test.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth4Test.php new file mode 100644 index 000000000..5f7418798 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth4Test.php @@ -0,0 +1,111 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +/** + * Tab replacement test using tab width 4. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::replaceTabsInToken + */ +final class ReplaceTabsInTokenTabWidth4Test extends ReplaceTabsInTokenTestCase +{ + + /** + * The tab width setting to use when tokenizing the file. + * + * @var integer + */ + protected $tabWidth = 4; + + + /** + * Data provider helper. + * + * @see ReplaceTabsInTokenTestCase::dataTabReplacement() + * + * @return array> + */ + public static function getTabReplacementExpected() + { + return [ + 'Tab indentation' => [ + 'length' => 8, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Mixed tab/space indentation' => [ + 'length' => 6, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Inline: single tab in text string' => [ + 'length' => 17, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: single tab between each word in text string' => [ + 'length' => 32, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: multiple tabs in heredoc' => [ + 'length' => 21, + 'content' => 'tab separated +', + 'orig_content' => 'tab separated +', + ], + 'Inline: multiple tabs between each word in nowdoc' => [ + 'length' => 48, + 'content' => 'tab between each word +', + 'orig_content' => 'tab between each word +', + ], + 'Inline: mixed spaces/tabs in text string' => [ + 'length' => 25, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: mixed spaces/tabs between each word in text string' => [ + 'length' => 36, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: tab becomes single space in comment (with tabwidth 4)' => [ + 'length' => 50, + 'content' => '// -123 With tabwidth 4, the tab size should be 1. +', + 'orig_content' => '// -123 With tabwidth 4, the tab size should be 1. +', + ], + 'Inline: tab becomes 2 spaces in comment (with tabwidth 4)' => [ + 'length' => 53, + 'content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + 'orig_content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + ], + 'Inline: tab becomes 3 spaces in doc comment string (with tabwidth 4)' => [ + 'length' => 47, + 'content' => '-1 With tabwidth 4, the tab size should be 3.', + 'orig_content' => '-1 With tabwidth 4, the tab size should be 3.', + ], + 'Inline: tab becomes 4 spaces in comment (with tabwidth 4)' => [ + 'length' => 50, + 'content' => '// - With tabwidth 4, the tab size should be 4. +', + 'orig_content' => '// - With tabwidth 4, the tab size should be 4. +', + ], + ]; + + }//end getTabReplacementExpected() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth5Test.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth5Test.php new file mode 100644 index 000000000..361894fb9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTabWidth5Test.php @@ -0,0 +1,111 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +/** + * Tab replacement test using tab width 5. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::replaceTabsInToken + */ +final class ReplaceTabsInTokenTabWidth5Test extends ReplaceTabsInTokenTestCase +{ + + /** + * The tab width setting to use when tokenizing the file. + * + * @var integer + */ + protected $tabWidth = 5; + + + /** + * Data provider helper. + * + * @see ReplaceTabsInTokenTestCase::dataTabReplacement() + * + * @return array> + */ + public static function getTabReplacementExpected() + { + return [ + 'Tab indentation' => [ + 'length' => 10, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Mixed tab/space indentation' => [ + 'length' => 7, + 'content' => ' ', + 'orig_content' => ' ', + ], + 'Inline: single tab in text string' => [ + 'length' => 15, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: single tab between each word in text string' => [ + 'length' => 25, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: multiple tabs in heredoc' => [ + 'length' => 24, + 'content' => 'tab separated +', + 'orig_content' => 'tab separated +', + ], + 'Inline: multiple tabs between each word in nowdoc' => [ + 'length' => 54, + 'content' => 'tab between each word +', + 'orig_content' => 'tab between each word +', + ], + 'Inline: mixed spaces/tabs in text string' => [ + 'length' => 30, + 'content' => "'tab separated'", + 'orig_content' => "'tab separated'", + ], + 'Inline: mixed spaces/tabs between each word in text string' => [ + 'length' => 35, + 'content' => '"tab $between each word"', + 'orig_content' => '"tab $between each word"', + ], + 'Inline: tab becomes single space in comment (with tabwidth 4)' => [ + 'length' => 52, + 'content' => '// -123 With tabwidth 4, the tab size should be 1. +', + 'orig_content' => '// -123 With tabwidth 4, the tab size should be 1. +', + ], + 'Inline: tab becomes 2 spaces in comment (with tabwidth 4)' => [ + 'length' => 55, + 'content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + 'orig_content' => '/* -12 With tabwidth 4, the tab size should be 2. */', + ], + 'Inline: tab becomes 3 spaces in doc comment string (with tabwidth 4)' => [ + 'length' => 49, + 'content' => '-1 With tabwidth 4, the tab size should be 3.', + 'orig_content' => '-1 With tabwidth 4, the tab size should be 3.', + ], + 'Inline: tab becomes 4 spaces in comment (with tabwidth 4)' => [ + 'length' => 47, + 'content' => '// - With tabwidth 4, the tab size should be 4. +', + 'orig_content' => '// - With tabwidth 4, the tab size should be 4. +', + ], + ]; + + }//end getTabReplacementExpected() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTest.inc b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTest.inc new file mode 100644 index 000000000..e6046500e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Tokenizers/Tokenizer/ReplaceTabsInTokenTest.inc @@ -0,0 +1,46 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Tokenizers\Tokenizer; + +use Exception; +use PHP_CodeSniffer\Tests\Core\Tokenizers\AbstractTokenizerTestCase; + +/** + * Tab replacement test case. + * + * @covers PHP_CodeSniffer\Tokenizers\Tokenizer::replaceTabsInToken + */ +abstract class ReplaceTabsInTokenTestCase extends AbstractTokenizerTestCase +{ + + /** + * The name of the test case file used by this test. + * + * @var string + */ + private static $caseFileName; + + + /** + * Make a copy the test case file we want to use for this test (as the file will be used by multiple tests). + * + * @beforeClass + * + * @return void + * + * @throws \Exception In case the base test case file would not be available. + */ + public static function copyCaseFile() + { + $relativeCN = str_replace(__NAMESPACE__.'\\', '', get_called_class()); + self::$caseFileName = __DIR__.DIRECTORY_SEPARATOR.$relativeCN.'.inc'; + + $baseFileName = realpath(__DIR__.'/ReplaceTabsInTokenTest.inc'); + if (is_string($baseFileName) === false) { + throw new Exception('Base test case file "ReplaceTabsInTokenTest.inc" not found'); + } + + if (copy($baseFileName, self::$caseFileName) === false) { + throw new Exception(sprintf('Failed to copy test case file "ReplaceTabsInTokenTest.inc" to %s', self::$caseFileName)); + } + + }//end copyCaseFile() + + + /** + * Delete the copied test case file after use. + * + * @afterClass + * + * @return void + */ + public static function deleteCaseFile() + { + @unlink(self::$caseFileName); + + }//end deleteCaseFile() + + + /** + * Verify that if a token not containing tabs would be passed to the replaceTabsInToken() method, + * yes, the `orig_content` key is added, but no changes are made to the token `content` or `length` values. + * + * @param string $testMarker The comment prefacing the target token. + * @param int|string $testTarget Token code to look for. + * @param array $expected Expectations for the token array. + * @param int $offset Optional. Offset from the target token to get to the _real_ target. + * This is specifically needed to target indentation whitespace. + * + * @dataProvider dataNoReplacementsAreMadeWhenNoTabsAreFound + * + * @return void + */ + public function testNoReplacementsAreMadeWhenNoTabsAreFound($testMarker, $testTarget, $expected, $offset=0) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, $testTarget); + $target += $offset; + + foreach ($expected as $key => $value) { + if ($key === 'orig_content' && $value === null) { + $this->assertArrayNotHasKey($key, $tokens[$target], "Unexpected 'orig_content' key found in the token array."); + continue; + } + + $this->assertArrayHasKey($key, $tokens[$target], "Key $key not found in the token array."); + $this->assertSame($value, $tokens[$target][$key], "Value for key $key does not match expectation."); + } + + }//end testNoReplacementsAreMadeWhenNoTabsAreFound() + + + /** + * Data provider. + * + * @see testNoReplacementsAreMadeWhenNoTabsAreFound() + * + * @return array>> + */ + public static function dataNoReplacementsAreMadeWhenNoTabsAreFound() + { + return [ + 'Indentation whitespace, only spaces' => [ + 'testMarker' => '/* testNoReplacementNeeded */', + 'testTarget' => T_WHITESPACE, + 'expected' => [ + 'length' => 4, + 'content' => ' ', + 'orig_content' => null, + ], + 'offset' => 1, + ], + 'Trailing comment not containing any tabs' => [ + 'testMarker' => '/* testNoReplacementNeeded */', + 'testTarget' => T_COMMENT, + 'expected' => [ + 'length' => 35, + 'content' => '// Comment not containing any tabs. +', + 'orig_content' => null, + ], + ], + ]; + + }//end dataNoReplacementsAreMadeWhenNoTabsAreFound() + + + /** + * Test tab replacement in tokens. + * + * @param string $testMarker The comment prefacing the target token. + * @param int|string $testTarget Token code to look for. + * @param array $expected Expectations for the token array. + * @param int $offset Optional. Offset from the target token to get to the _real_ target. + * This is specifically needed to target indentation whitespace. + * + * @dataProvider dataTabReplacement + * + * @return void + */ + public function testTabReplacement($testMarker, $testTarget, $expected, $offset=0) + { + $tokens = $this->phpcsFile->getTokens(); + $target = $this->getTargetToken($testMarker, $testTarget); + $target += $offset; + + foreach ($expected as $key => $value) { + if ($key === 'orig_content' && $value === null) { + $this->assertArrayNotHasKey($key, $tokens[$target], "Unexpected 'orig_content' key found in the token array."); + continue; + } + + $this->assertArrayHasKey($key, $tokens[$target], "Key $key not found in the token array."); + $this->assertSame($value, $tokens[$target][$key], "Value for key $key does not match expectation."); + } + + }//end testTabReplacement() + + + /** + * Data provider. + * + * @see testTabReplacement() + * + * @return array>> + * + * @throws \Exception When the getTabReplacementExpected() method doesn't provide data in the correct format. + */ + public static function dataTabReplacement() + { + $data = [ + 'Tab indentation' => [ + 'testMarker' => '/* testTabIndentation */', + 'testTarget' => T_WHITESPACE, + ], + 'Mixed tab/space indentation' => [ + 'testMarker' => '/* testMixedIndentation */', + 'testTarget' => T_WHITESPACE, + ], + 'Inline: single tab in text string' => [ + 'testMarker' => '/* testInlineSingleTab */', + 'testTarget' => T_CONSTANT_ENCAPSED_STRING, + ], + 'Inline: single tab between each word in text string' => [ + 'testMarker' => '/* testInlineSingleTabBetweenEachWord */', + 'testTarget' => T_DOUBLE_QUOTED_STRING, + ], + 'Inline: multiple tabs in heredoc' => [ + 'testMarker' => '/* testInlineMultiTab */', + 'testTarget' => T_HEREDOC, + ], + 'Inline: multiple tabs between each word in nowdoc' => [ + 'testMarker' => '/* testInlineMultipleTabsBetweenEachWord */', + 'testTarget' => T_NOWDOC, + ], + 'Inline: mixed spaces/tabs in text string' => [ + 'testMarker' => '/* testInlineMixedSpacesTabs */', + 'testTarget' => T_CONSTANT_ENCAPSED_STRING, + ], + 'Inline: mixed spaces/tabs between each word in text string' => [ + 'testMarker' => '/* testInlineMixedSpacesTabsBetweenEachWord */', + 'testTarget' => T_DOUBLE_QUOTED_STRING, + ], + 'Inline: tab becomes single space in comment (with tabwidth 4)' => [ + 'testMarker' => '/* testInlineSize1 */', + 'testTarget' => T_COMMENT, + ], + 'Inline: tab becomes 2 spaces in comment (with tabwidth 4)' => [ + 'testMarker' => '/* testInlineSize2 */', + 'testTarget' => T_COMMENT, + ], + 'Inline: tab becomes 3 spaces in doc comment string (with tabwidth 4)' => [ + 'testMarker' => '/* testInlineSize3 */', + 'testTarget' => T_DOC_COMMENT_STRING, + ], + 'Inline: tab becomes 4 spaces in comment (with tabwidth 4)' => [ + 'testMarker' => '/* testInlineSize4 */', + 'testTarget' => T_COMMENT, + ], + ]; + + $expectations = static::getTabReplacementExpected(); + + foreach ($data as $key => $value) { + if (isset($expectations[$key]) === false || is_array($expectations[$key]) === false) { + throw new Exception( + sprintf('Invalid getTabReplacementExpected() method. Missing expectation array for the "%s" test case', $key) + ); + } + + if (isset($expectations[$key]['length'], $expectations[$key]['content']) === false + || array_key_exists('orig_content', $expectations[$key]) === false + ) { + throw new Exception( + sprintf('Invalid expectation array for the "%s" test case. The array must contain the "length", "content" and "orig_content" keys', $key) + ); + } + + $data[$key]['expected'] = $expectations[$key]; + } + + // Set offset for test cases targetting whitespace. + $data['Tab indentation']['offset'] = 1; + $data['Mixed tab/space indentation']['offset'] = 1; + + return $data; + + }//end dataTabReplacement() + + + /** + * Data provider helper. + * + * Should be declared in child classes to set the expectations for the token array. + * + * @see dataTabReplacement() + * + * @return array> + */ + abstract public static function getTabReplacementExpected(); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/EscapeshellcmdTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/EscapeshellcmdTest.php new file mode 100644 index 000000000..d5b35b0ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/EscapeshellcmdTest.php @@ -0,0 +1,91 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Common; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Common::escapeshellcmd() method. + * + * @covers \PHP_CodeSniffer\Util\Common::escapeshellcmd + * @group Windows + */ +final class EscapeshellcmdTest extends TestCase +{ + + + /** + * Test escaping shell commands. + * + * @param string $command The command provided. + * @param string $expected Expected function output. + * @param string $expectedWin Optional. Expected function output on Windows. + * Only needs to be passed if the output on Windows would be different. + * + * @dataProvider dataEscapeshellcmd + * + * @return void + */ + public function testEscapeshellcmd($command, $expected, $expectedWin=null) + { + if (stripos(PHP_OS, 'WIN') === 0 && empty($expectedWin) === false) { + $expected = $expectedWin; + } + + $this->assertSame($expected, Common::escapeshellcmd($command)); + + }//end testEscapeshellcmd() + + + /** + * Data provider. + * + * Note: we're only testing the PHPCS functionality, not the PHP native `escapeshellcmd()` + * function (as that's not our responsibility). + * + * @see testEscapeshellcmd() + * + * @return array> + */ + public static function dataEscapeshellcmd() + { + return [ + 'Command is empty string' => [ + 'text' => '', + 'expected' => '', + ], + 'Command is simple string' => [ + 'text' => 'csslint', + 'expected' => 'csslint', + ], + 'Command containing characters which PHP escapes' => [ + 'text' => '&#;`|*?~<>^()[]{}$\,%!', + 'expected' => '\&\#\;\`\|\*\?\~\<\>\^\(\)\[\]\{\}\$\\\\,%!', + 'expectedWin' => '^&^#^;^`^|^*^?^~^<^>^^^(^)^[^]^{^}^$^\,^%^!', + ], + // @link https://github.com/squizlabs/PHP_CodeSniffer/pull/3214 + 'Command containing spaces, which can cause problems on Windows' => [ + 'text' => 'C:\Program Files\nodejs\csslint.cmd', + 'expected' => 'C:\\\\Program Files\\\\nodejs\\\\csslint.cmd', + 'expectedWin' => 'C:^\Program^ Files^\nodejs^\csslint.cmd', + ], + // @link https://github.com/php/doc-en/pull/511 + 'Command containing spaces with additional arguments' => [ + 'text' => 'php -f ./~home/path to/file.php', + 'expected' => 'php -f ./\~home/path to/file.php', + 'expectedWin' => 'php^ -f^ ./^~home/path^ to/file.php', + ], + ]; + + }//end dataEscapeshellcmd() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/GetSniffCodeTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/GetSniffCodeTest.php new file mode 100644 index 000000000..48161f1ce --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/GetSniffCodeTest.php @@ -0,0 +1,200 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Common; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Common::getSniffCode() method. + * + * @covers \PHP_CodeSniffer\Util\Common::getSniffCode + */ +final class GetSniffCodeTest extends TestCase +{ + + + /** + * Test receiving an expected exception when the $sniffClass parameter is not passed a string value or is passed an empty string. + * + * @param string $input NOT a fully qualified sniff class name. + * + * @dataProvider dataGetSniffCodeThrowsExceptionOnInvalidInput + * + * @return void + */ + public function testGetSniffCodeThrowsExceptionOnInvalidInput($input) + { + $exception = 'InvalidArgumentException'; + $message = 'The $sniffClass parameter must be a non-empty string'; + + if (method_exists($this, 'expectException') === true) { + // PHPUnit 5+. + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + // PHPUnit 4. + $this->setExpectedException($exception, $message); + } + + Common::getSniffCode($input); + + }//end testGetSniffCodeThrowsExceptionOnInvalidInput() + + + /** + * Data provider. + * + * @see testGetSniffCodeThrowsExceptionOnInvalidInput() + * + * @return array> + */ + public static function dataGetSniffCodeThrowsExceptionOnInvalidInput() + { + return [ + 'Class name is not a string' => [true], + 'Class name is empty' => [''], + ]; + + }//end dataGetSniffCodeThrowsExceptionOnInvalidInput() + + + /** + * Test receiving an expected exception when the $sniffClass parameter is not passed a value which + * could be a fully qualified sniff(test) class name. + * + * @param string $input String input which can not be a fully qualified sniff(test) class name. + * + * @dataProvider dataGetSniffCodeThrowsExceptionOnInputWhichIsNotASniffTestClass + * + * @return void + */ + public function testGetSniffCodeThrowsExceptionOnInputWhichIsNotASniffTestClass($input) + { + $exception = 'InvalidArgumentException'; + $message = 'The $sniffClass parameter was not passed a fully qualified sniff(test) class name. Received:'; + + if (method_exists($this, 'expectException') === true) { + // PHPUnit 5+. + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + // PHPUnit 4. + $this->setExpectedException($exception, $message); + } + + Common::getSniffCode($input); + + }//end testGetSniffCodeThrowsExceptionOnInputWhichIsNotASniffTestClass() + + + /** + * Data provider. + * + * @see testGetSniffCodeThrowsExceptionOnInputWhichIsNotASniffTestClass() + * + * @return array> + */ + public static function dataGetSniffCodeThrowsExceptionOnInputWhichIsNotASniffTestClass() + { + return [ + 'Unqualified class name' => ['ClassName'], + 'Fully qualified class name, not enough parts' => ['Fully\\Qualified\\ClassName'], + 'Fully qualified class name, doesn\'t end on Sniff or UnitTest' => ['Fully\\Sniffs\\Qualified\\ClassName'], + ]; + + }//end dataGetSniffCodeThrowsExceptionOnInputWhichIsNotASniffTestClass() + + + /** + * Test transforming a sniff class name to a sniff code. + * + * @param string $fqnClass A fully qualified sniff class name. + * @param string $expected Expected function output. + * + * @dataProvider dataGetSniffCode + * + * @return void + */ + public function testGetSniffCode($fqnClass, $expected) + { + $this->assertSame($expected, Common::getSniffCode($fqnClass)); + + }//end testGetSniffCode() + + + /** + * Data provider. + * + * @see testGetSniffCode() + * + * @return array> + */ + public static function dataGetSniffCode() + { + return [ + 'PHPCS native sniff' => [ + 'fqnClass' => 'PHP_CodeSniffer\\Standards\\Generic\\Sniffs\\Arrays\\ArrayIndentSniff', + 'expected' => 'Generic.Arrays.ArrayIndent', + ], + 'Class is a PHPCS native test class' => [ + 'fqnClass' => 'PHP_CodeSniffer\\Standards\\Generic\\Tests\\Arrays\\ArrayIndentUnitTest', + 'expected' => 'Generic.Arrays.ArrayIndent', + ], + 'Sniff in external standard without namespace prefix' => [ + 'fqnClass' => 'MyStandard\\Sniffs\\PHP\\MyNameSniff', + 'expected' => 'MyStandard.PHP.MyName', + ], + 'Test in external standard without namespace prefix' => [ + 'fqnClass' => 'MyStandard\\Tests\\PHP\\MyNameSniff', + 'expected' => 'MyStandard.PHP.MyName', + ], + 'Sniff in external standard with namespace prefix' => [ + 'fqnClass' => 'Vendor\\Package\\MyStandard\\Sniffs\\Category\\AnalyzeMeSniff', + 'expected' => 'MyStandard.Category.AnalyzeMe', + ], + 'Test in external standard with namespace prefix' => [ + 'fqnClass' => 'Vendor\\Package\\MyStandard\\Tests\\Category\\AnalyzeMeUnitTest', + 'expected' => 'MyStandard.Category.AnalyzeMe', + ], + + /* + * These are not valid sniff codes and is an undesirable result, but can't be helped + * as changing this would be a BC-break. + * Supporting these to allow for tags directly including sniff files. + * See: https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/675 + */ + + 'Fully qualified class name, ends on Sniff, but isn\'t' => [ + 'fqnClass' => 'Fully\\Sniffs\\AbstractSomethingSniff', + 'expected' => '.Sniffs.AbstractSomething', + ], + 'Sniff provided via file include and doesn\'t comply with naming conventions [1]' => [ + 'fqnClass' => 'CheckMeSniff', + 'expected' => '..CheckMe', + ], + 'Sniff provided via file include and doesn\'t comply with naming conventions [2]' => [ + 'fqnClass' => 'CompanyName\\CheckMeSniff', + 'expected' => '.CompanyName.CheckMe', + ], + 'Sniff provided via file include and doesn\'t comply with naming conventions [3]' => [ + 'fqnClass' => 'CompanyName\\Sniffs\\CheckMeSniff', + 'expected' => '.Sniffs.CheckMe', + ], + 'Sniff provided via file include and doesn\'t comply with naming conventions [4]' => [ + 'fqnClass' => 'CompanyName\\CustomSniffs\\Whatever\\CheckMeSniff', + 'expected' => 'CompanyName.Whatever.CheckMe', + ], + ]; + + }//end dataGetSniffCode() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/IsCamelCapsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/IsCamelCapsTest.php new file mode 100644 index 000000000..951d76187 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/IsCamelCapsTest.php @@ -0,0 +1,140 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Common; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Common::isCamelCaps method. + * + * @covers \PHP_CodeSniffer\Util\Common::isCamelCaps + */ +final class IsCamelCapsTest extends TestCase +{ + + + /** + * Test valid public function/method names. + * + * @return void + */ + public function testValidNotClassFormatPublic() + { + $this->assertTrue(Common::isCamelCaps('thisIsCamelCaps', false, true, true)); + $this->assertTrue(Common::isCamelCaps('thisISCamelCaps', false, true, false)); + + }//end testValidNotClassFormatPublic() + + + /** + * Test invalid public function/method names. + * + * @return void + */ + public function testInvalidNotClassFormatPublic() + { + $this->assertFalse(Common::isCamelCaps('_thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('thisISCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('ThisIsCamelCaps', false, true, true)); + + $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, true, true)); + + $this->assertFalse(Common::isCamelCaps('this*IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this-IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this_IsCamelCaps', false, true, true)); + $this->assertFalse(Common::isCamelCaps('this_is_camel_caps', false, true, true)); + + }//end testInvalidNotClassFormatPublic() + + + /** + * Test valid private method names. + * + * @return void + */ + public function testValidNotClassFormatPrivate() + { + $this->assertTrue(Common::isCamelCaps('_thisIsCamelCaps', false, false, true)); + $this->assertTrue(Common::isCamelCaps('_thisISCamelCaps', false, false, false)); + $this->assertTrue(Common::isCamelCaps('_i18N', false, false, true)); + $this->assertTrue(Common::isCamelCaps('_i18n', false, false, true)); + + }//end testValidNotClassFormatPrivate() + + + /** + * Test invalid private method names. + * + * @return void + */ + public function testInvalidNotClassFormatPrivate() + { + $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_thisISCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('__thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('__thisISCamelCaps', false, false, false)); + + $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, false, true)); + $this->assertFalse(Common::isCamelCaps('_this_is_camel_caps', false, false, true)); + + }//end testInvalidNotClassFormatPrivate() + + + /** + * Test valid class names. + * + * @return void + */ + public function testValidClassFormatPublic() + { + $this->assertTrue(Common::isCamelCaps('ThisIsCamelCaps', true, true, true)); + $this->assertTrue(Common::isCamelCaps('ThisISCamelCaps', true, true, false)); + $this->assertTrue(Common::isCamelCaps('This3IsCamelCaps', true, true, false)); + + }//end testValidClassFormatPublic() + + + /** + * Test invalid class names. + * + * @return void + */ + public function testInvalidClassFormat() + { + $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', true)); + $this->assertFalse(Common::isCamelCaps('This-IsCamelCaps', true)); + $this->assertFalse(Common::isCamelCaps('This_Is_Camel_Caps', true)); + + }//end testInvalidClassFormat() + + + /** + * Test invalid class names with the private flag set. + * + * Note that the private flag is ignored if the class format + * flag is set, so these names are all invalid. + * + * @return void + */ + public function testInvalidClassFormatPrivate() + { + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, true)); + $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, false)); + + }//end testInvalidClassFormatPrivate() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/PrepareForOutputTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/PrepareForOutputTest.php new file mode 100644 index 000000000..8eb2fc22f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/PrepareForOutputTest.php @@ -0,0 +1,113 @@ +assertSame($expected, Common::prepareForOutput($content, $exclude)); + + }//end testPrepareForOutput() + + + /** + * Test formatting whitespace characters, on Windows. + * + * @param string $content The content to prepare. + * @param string[] $exclude A list of characters to leave invisible. + * @param string $expected Expected function output (unused in this test). + * @param string $expectedWin Expected function output on Windows. + * + * @requires OS ^WIN.*. + * @dataProvider dataPrepareForOutput + * + * @return void + */ + public function testPrepareForOutputWindows($content, $exclude, $expected, $expectedWin) + { + $this->assertSame($expectedWin, Common::prepareForOutput($content, $exclude)); + + }//end testPrepareForOutputWindows() + + + /** + * Data provider. + * + * @see testPrepareForOutput() + * @see testPrepareForOutputWindows() + * + * @return array> + */ + public static function dataPrepareForOutput() + { + return [ + 'Special characters are replaced with their escapes' => [ + 'content' => "\r\n\t", + 'exclude' => [], + 'expected' => "\033[30;1m\\r\033[0m\033[30;1m\\n\033[0m\033[30;1m\\t\033[0m", + 'expectedWin' => "\\r\\n\\t", + ], + 'Spaces are replaced with a unique mark' => [ + 'content' => " ", + 'exclude' => [], + 'expected' => "\033[30;1m·\033[0m\033[30;1m·\033[0m\033[30;1m·\033[0m\033[30;1m·\033[0m", + 'expectedWin' => " ", + ], + 'Other characters are unaffected' => [ + 'content' => "{echo 1;}", + 'exclude' => [], + 'expected' => "{echo\033[30;1m·\033[0m1;}", + 'expectedWin' => "{echo 1;}", + ], + 'No replacements' => [ + 'content' => 'nothing-should-be-replaced', + 'exclude' => [], + 'expected' => 'nothing-should-be-replaced', + 'expectedWin' => 'nothing-should-be-replaced', + ], + 'Excluded whitespace characters are unaffected' => [ + 'content' => "\r\n\t ", + 'exclude' => [ + "\r", + "\n", + ], + 'expected' => "\r\n\033[30;1m\\t\033[0m\033[30;1m·\033[0m", + 'expectedWin' => "\r\n\\t ", + ], + ]; + + }//end dataPrepareForOutput() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/StripColorsTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/StripColorsTest.php new file mode 100644 index 000000000..ff253b8b8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/StripColorsTest.php @@ -0,0 +1,96 @@ + + * @copyright 2024 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Common; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Common::stripColors() method. + * + * @covers \PHP_CodeSniffer\Util\Common::stripColors + */ +final class StripColorsTest extends TestCase +{ + + + /** + * Test stripping color codes from a text. + * + * @param string $text The text provided. + * @param string $expected Expected function output. + * + * @dataProvider dataStripColors + * + * @return void + */ + public function testStripColors($text, $expected) + { + $this->assertSame($expected, Common::stripColors($text)); + + }//end testStripColors() + + + /** + * Data provider. + * + * @see testStripColors() + * + * @return array> + */ + public static function dataStripColors() + { + return [ + 'Text is empty' => [ + 'text' => '', + 'expected' => '', + ], + 'Text enclosed in color code' => [ + 'text' => "\033[36mSome text\033[0m", + 'expected' => 'Some text', + ], + 'Text containing color code' => [ + 'text' => "Some text \033[33mSome other text", + 'expected' => 'Some text Some other text', + ], + 'Text enclosed in color code, bold' => [ + 'text' => "\033[1;32mSome text\033[0m", + 'expected' => 'Some text', + ], + 'Text enclosed in color code, with escaped text' => [ + 'text' => "\033[30;1m\\n\033[0m", + 'expected' => '\n', + ], + 'Text enclosed in color code, bold, dark, italic' => [ + 'text' => "\033[1;2;3mtext\033[0m", + 'expected' => 'text', + ], + 'Text enclosed in color code, foreground color' => [ + 'text' => "\033[38;5;255mtext\033[0m", + 'expected' => 'text', + ], + 'Text enclosed in color code, foreground color and background color' => [ + 'text' => "\033[38;5;200;48;5;255mtext\033[0m", + 'expected' => 'text', + ], + 'Multiline text containing multiple color codes' => [ + 'text' => "First \033[36mSecond\033[0m +Third \033[1;2;3mFourth +Next line\033[0m Last", + 'expected' => 'First Second +Third Fourth +Next line Last', + ], + ]; + + }//end dataStripColors() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/SuggestTypeTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/SuggestTypeTest.php new file mode 100644 index 000000000..48bb6df1d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Common/SuggestTypeTest.php @@ -0,0 +1,224 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Common; + +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Common::suggestType() method. + * + * @covers \PHP_CodeSniffer\Util\Common::suggestType + */ +final class SuggestTypeTest extends TestCase +{ + + + /** + * Test passing an empty type to the suggestType() method. + * + * @return void + */ + public function testSuggestTypeEmpty() + { + $this->assertSame('', Common::suggestType('')); + + }//end testSuggestTypeEmpty() + + + /** + * Test passing one of the allowed types to the suggestType() method. + * + * @param string $varType The type. + * + * @dataProvider dataSuggestTypeAllowedType + * + * @return void + */ + public function testSuggestTypeAllowedType($varType) + { + $result = Common::suggestType($varType); + $this->assertSame($varType, $result); + + }//end testSuggestTypeAllowedType() + + + /** + * Data provider. + * + * @see testSuggestTypeAllowedType() + * + * @return array> + */ + public static function dataSuggestTypeAllowedType() + { + $data = []; + foreach (Common::$allowedTypes as $type) { + $data['Type: '.$type] = [$type]; + } + + return $data; + + }//end dataSuggestTypeAllowedType() + + + /** + * Test passing one of the allowed types in the wrong case to the suggestType() method. + * + * @param string $varType The type found. + * @param string $expected Expected suggested type. + * + * @dataProvider dataSuggestTypeAllowedTypeWrongCase + * + * @return void + */ + public function testSuggestTypeAllowedTypeWrongCase($varType, $expected) + { + $result = Common::suggestType($varType); + $this->assertSame($expected, $result); + + }//end testSuggestTypeAllowedTypeWrongCase() + + + /** + * Data provider. + * + * @see testSuggestTypeAllowedTypeWrongCase() + * + * @return array> + */ + public static function dataSuggestTypeAllowedTypeWrongCase() + { + $data = []; + foreach (Common::$allowedTypes as $type) { + $data['Mixed case: '.$type] = [ + 'varType' => ucfirst($type), + 'expected' => $type, + ]; + $data['Uppercase: '.$type] = [ + 'varType' => strtoupper($type), + 'expected' => $type, + ]; + } + + return $data; + + }//end dataSuggestTypeAllowedTypeWrongCase() + + + /** + * Test the suggestType() method for all other cases. + * + * @param string $varType The type found. + * @param string $expected Expected suggested type. + * + * @dataProvider dataSuggestTypeOther + * + * @return void + */ + public function testSuggestTypeOther($varType, $expected) + { + $result = Common::suggestType($varType); + $this->assertSame($expected, $result); + + }//end testSuggestTypeOther() + + + /** + * Data provider. + * + * @see testSuggestTypeOther() + * + * @return array> + */ + public static function dataSuggestTypeOther() + { + return [ + // Short forms. + 'Short form type: bool, lowercase' => [ + 'varType' => 'bool', + 'expected' => 'boolean', + ], + 'Short form type: bool, uppercase' => [ + 'varType' => 'BOOL', + 'expected' => 'boolean', + ], + 'Short form type: double, lowercase' => [ + 'varType' => 'double', + 'expected' => 'float', + ], + 'Short form type: real, mixed case' => [ + 'varType' => 'Real', + 'expected' => 'float', + ], + 'Short form type: double, mixed case' => [ + 'varType' => 'DoUbLe', + 'expected' => 'float', + ], + 'Short form type: int, lowercase' => [ + 'varType' => 'int', + 'expected' => 'integer', + ], + 'Short form type: int, uppercase' => [ + 'varType' => 'INT', + 'expected' => 'integer', + ], + + // Array types. + 'Array type: mixed case keyword, empty parentheses' => [ + 'varType' => 'Array()', + 'expected' => 'array', + ], + 'Array type: short form type as value within the parentheses' => [ + 'varType' => 'array(real)', + 'expected' => 'array(float)', + ], + 'Array type: short form type as key within the parentheses' => [ + 'varType' => 'array(int => object)', + 'expected' => 'array(integer => object)', + ], + 'Array type: valid specification' => [ + 'varType' => 'array(integer => array(string => resource))', + 'expected' => 'array(integer => array(string => resource))', + ], + 'Array type: short form + uppercase types within the parentheses' => [ + 'varType' => 'ARRAY(BOOL => DOUBLE)', + 'expected' => 'array(boolean => float)', + ], + 'Array type: no space around the arrow within the parentheses' => [ + 'varType' => 'array(string=>resource)', + 'expected' => 'array(string => resource)', + ], + + // Incomplete array type. + 'Array type: incomplete specification' => [ + 'varType' => 'array(int =>', + 'expected' => 'array', + ], + + // Custom types are returned unchanged. + 'Unknown type: " => "' => [ + 'varType' => ' => ', + 'expected' => ' => ', + ], + 'Unknown type: "string[]"' => [ + 'varType' => 'string[]', + 'expected' => 'string[]', + ], + 'Unknown type: "\DateTime"' => [ + 'varType' => '\DateTime', + 'expected' => '\DateTime', + ], + ]; + + }//end dataSuggestTypeOther() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Help/HelpTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Help/HelpTest.php new file mode 100644 index 000000000..f09a4c179 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Help/HelpTest.php @@ -0,0 +1,725 @@ + + * @copyright 2024 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Help; + +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHP_CodeSniffer\Util\Help; +use PHPUnit\Framework\TestCase; +use ReflectionMethod; +use ReflectionProperty; + +/** + * Test the Help class. + * + * @covers \PHP_CodeSniffer\Util\Help + */ +final class HelpTest extends TestCase +{ + + + /** + * QA check: verify that the category names are at most the minimum screen width + * and that option argument names are always at most half the length of the minimum screen width. + * + * If this test would start failing, either wrapping of argument info would need to be implemented + * or the minimum screen width needs to be upped. + * + * @coversNothing + * + * @return void + */ + public function testQaArgumentNamesAreWithinAcceptableBounds() + { + $help = new Help(new ConfigDouble(), []); + + $reflMethod = new ReflectionMethod($help, 'getAllOptions'); + $reflMethod->setAccessible(true); + $allOptions = $reflMethod->invoke($help); + $reflMethod->setAccessible(false); + + $this->assertGreaterThan(0, count($allOptions), 'No categories found'); + + $minScreenWidth = Help::MIN_WIDTH; + $maxArgWidth = ($minScreenWidth / 2); + + foreach ($allOptions as $category => $options) { + $this->assertLessThanOrEqual( + Help::MIN_WIDTH, + strlen($category), + "Category name $category is longer than the minimum screen width of $minScreenWidth" + ); + + foreach ($options as $option) { + if (isset($option['argument']) === false) { + continue; + } + + $this->assertLessThanOrEqual( + $maxArgWidth, + strlen($option['argument']), + "Option name {$option['argument']} is longer than the half the minimum screen width of $minScreenWidth" + ); + } + } + + }//end testQaArgumentNamesAreWithinAcceptableBounds() + + + /** + * QA check: verify that each option only contains a spacer, text or argument + description combo. + * + * @coversNothing + * + * @return void + */ + public function testQaValidCategoryOptionDefinitions() + { + $help = new Help(new ConfigDouble(), []); + + $reflMethod = new ReflectionMethod($help, 'getAllOptions'); + $reflMethod->setAccessible(true); + $allOptions = $reflMethod->invoke($help); + $reflMethod->setAccessible(false); + + $this->assertGreaterThan(0, count($allOptions), 'No categories found'); + + foreach ($allOptions as $category => $options) { + $this->assertGreaterThan(0, count($options), "No options found in category $category"); + + foreach ($options as $name => $option) { + if (isset($option['spacer']) === true) { + $this->assertStringStartsWith('blank-line', $name, 'The name for spacer items should start with "blank-line"'); + } + + $this->assertFalse( + isset($option['spacer'], $option['text']), + "Option $name: spacer and text should not be combined in one option" + ); + $this->assertFalse( + isset($option['spacer'], $option['argument']), + "Option $name: spacer and argument should not be combined in one option" + ); + $this->assertFalse( + isset($option['spacer'], $option['description']), + "Option $name: spacer and description should not be combined in one option" + ); + $this->assertFalse( + isset($option['text'], $option['argument']), + "Option $name: text and argument should not be combined in one option" + ); + $this->assertFalse( + isset($option['text'], $option['description']), + "Option $name: text and description should not be combined in one option" + ); + + if (isset($option['argument']) === true) { + $this->assertArrayHasKey( + 'description', + $option, + "Option $name: an argument should always be accompanied by a description" + ); + } + + if (isset($option['description']) === true) { + $this->assertArrayHasKey( + 'argument', + $option, + "Option $name: a description should always be accompanied by an argument" + ); + } + }//end foreach + }//end foreach + + }//end testQaValidCategoryOptionDefinitions() + + + /** + * Test receiving an expected exception when the shortOptions parameter is not passed a string value. + * + * @return void + */ + public function testConstructorInvalidArgumentException() + { + $exception = 'InvalidArgumentException'; + $message = 'The $shortOptions parameter must be a string'; + + if (method_exists($this, 'expectException') === true) { + // PHPUnit 5+. + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + // PHPUnit 4. + $this->setExpectedException($exception, $message); + } + + new Help(new ConfigDouble(), [], []); + + }//end testConstructorInvalidArgumentException() + + + /** + * Test filtering of the options by requested options. + * + * Tests that: + * - Options not explicitly requested are removed. + * - Short options passed via the longOptions array are still respected. + * - A category gets removed if all options are removed, even if the category still has spacers. + * + * @param array $longOptions The long options which should be displayed. + * @param string $shortOptions The short options which should be displayed. + * @param array $expected The categories expected after filtering with the number + * of expected help items per category. + * + * @dataProvider dataOptionFiltering + * + * @return void + */ + public function testOptionFiltering($longOptions, $shortOptions, $expected) + { + $help = new Help(new ConfigDouble(), $longOptions, $shortOptions); + + $reflProperty = new ReflectionProperty($help, 'activeOptions'); + $reflProperty->setAccessible(true); + $activeOptions = $reflProperty->getValue($help); + $reflProperty->setAccessible(false); + + // Simplify the value to make it comparible. + foreach ($activeOptions as $category => $options) { + $activeOptions[$category] = count($options); + } + + $this->assertSame($expected, $activeOptions, 'Option count per category does not match'); + + }//end testOptionFiltering() + + + /** + * Data provider. + * + * @return array|array>> + */ + public static function dataOptionFiltering() + { + $allLongOptions = explode(',', Help::DEFAULT_LONG_OPTIONS); + $allLongOptions[] = 'cache'; + $allLongOptions[] = 'no-cache'; + $allLongOptions[] = 'report'; + $allLongOptions[] = 'report-file'; + $allLongOptions[] = 'report-report'; + $allLongOptions[] = 'runtime-set'; + $allLongOptions[] = 'config-explain'; + $allLongOptions[] = 'config-set'; + $allLongOptions[] = 'config-delete'; + $allLongOptions[] = 'config-show'; + $allLongOptions[] = 'generator'; + $allLongOptions[] = 'suffix'; + + $allShortOptions = Help::DEFAULT_SHORT_OPTIONS.'saem'; + + return [ + 'No options' => [ + 'longOptions' => [], + 'shortOptions' => '', + 'expected' => [], + ], + 'Invalid options have no influence' => [ + 'longOptions' => [ + 'doesnotexist', + 'invalid', + ], + 'shortOptions' => 'bjrz', + 'expected' => [], + ], + 'Short options passed as long options works fine' => [ + 'longOptions' => [ + 's', + 'suffix', + 'a', + 'e', + 'colors', + ], + 'shortOptions' => '', + 'expected' => [ + 'Rule Selection Options' => 1, + 'Run Options' => 2, + 'Reporting Options' => 2, + ], + ], + 'All options' => [ + 'longOptions' => $allLongOptions, + 'shortOptions' => $allShortOptions, + 'expected' => [ + 'Scan targets' => 8, + 'Rule Selection Options' => 7, + 'Run Options' => 8, + 'Reporting Options' => 19, + 'Configuration Options' => 8, + 'Miscellaneous Options' => 5, + ], + ], + 'Default options only' => [ + 'longOptions' => explode(',', Help::DEFAULT_LONG_OPTIONS), + 'shortOptions' => Help::DEFAULT_SHORT_OPTIONS, + 'expected' => [ + 'Scan targets' => 8, + 'Rule Selection Options' => 5, + 'Run Options' => 4, + 'Reporting Options' => 14, + 'Configuration Options' => 4, + 'Miscellaneous Options' => 5, + ], + ], + 'Only one category' => [ + 'longOptions' => [ + 'file', + 'stdin-path', + 'file-list', + 'filter', + 'ignore', + 'extensions', + ], + 'shortOptions' => '-l', + 'expected' => [ + 'Scan targets' => 8, + ], + ], + 'All except one category' => [ + 'longOptions' => array_diff($allLongOptions, ['version', 'vv', 'vvv']), + 'shortOptions' => str_replace(['h', 'v'], '', $allShortOptions), + 'expected' => [ + 'Scan targets' => 8, + 'Rule Selection Options' => 7, + 'Run Options' => 8, + 'Reporting Options' => 19, + 'Configuration Options' => 8, + ], + ], + ]; + + }//end dataOptionFiltering() + + + /** + * Test filtering of the options by requested options does not leave stray spacers at the start + * or end of a category and that a category does not contain two consecutive spacers. + * + * {@internal Careful! This test may need updates to still test what it is supposed to test + * if/when the defined options in Help::getAllOptions() change.} + * + * @param array $longOptions The long options which should be displayed. + * @param string $shortOptions The short options which should be displayed. + * + * @dataProvider dataOptionFilteringSpacerHandling + * + * @return void + */ + public function testOptionFilteringSpacerHandling($longOptions, $shortOptions) + { + $help = new Help(new ConfigDouble(), $longOptions, $shortOptions); + + $reflProperty = new ReflectionProperty($help, 'activeOptions'); + $reflProperty->setAccessible(true); + $activeOptions = $reflProperty->getValue($help); + $reflProperty->setAccessible(false); + + $this->assertNotEmpty($activeOptions, 'Active options is empty, test is invalid'); + + foreach ($activeOptions as $options) { + $first = reset($options); + $this->assertArrayNotHasKey('spacer', $first, 'Found spacer at start of category'); + + $last = end($options); + $this->assertArrayNotHasKey('spacer', $last, 'Found spacer at end of category'); + + $previousWasSpacer = false; + foreach ($options as $option) { + $this->assertFalse((isset($option['spacer']) && $previousWasSpacer === true), 'Consecutive spacers found'); + $previousWasSpacer = isset($option['spacer']); + } + } + + }//end testOptionFilteringSpacerHandling() + + + /** + * Data provider. + * + * @return array>> + */ + public static function dataOptionFilteringSpacerHandling() + { + return [ + 'No spacer at start of category' => [ + 'longOptions' => ['generator'], + 'shortOptions' => 'ie', + ], + 'No spacer at end of category' => [ + 'longOptions' => [ + 'encoding', + 'tab-width', + ], + 'shortOptions' => '', + ], + 'No consecutive spacers within category' => [ + 'longOptions' => [ + 'report', + 'report-file', + 'report-report', + 'report-width', + 'basepath', + 'ignore-annotations', + 'colors', + 'no-colors', + ], + 'shortOptions' => 'spqm', + ], + ]; + + }//end dataOptionFilteringSpacerHandling() + + + /** + * Test that if no short/long options are passed, only usage information is displayed (and displayed correctly). + * + * @param array $cliArgs Command line arguments. + * @param string $expectedRegex Regex to validate expected output. + * + * @dataProvider dataDisplayUsage + * + * @return void + */ + public function testDisplayUsage($cliArgs, $expectedRegex) + { + $help = new Help(new ConfigDouble($cliArgs), []); + + $this->expectOutputRegex($expectedRegex); + + $help->display(); + + }//end testDisplayUsage() + + + /** + * Data provider. + * + * @return array>> + */ + public static function dataDisplayUsage() + { + return [ + 'Usage without colors' => [ + 'cliArgs' => ['--no-colors'], + 'expectedRegex' => '`^\s*Usage:\s+phpc(bf|s) \[options\] \\s+$`', + ], + 'Usage with colors' => [ + 'cliArgs' => ['--colors'], + 'expectedRegex' => '`^\s*\\033\[33mUsage:\\033\[0m\s+phpc(bf|s) \[options\] \\s+$`', + ], + ]; + + }//end dataDisplayUsage() + + + /** + * Test the column width calculations. + * + * This tests the following aspects: + * 1. That the report width is never less than Help::MIN_WIDTH, even when a smaller width is passed. + * 2. That the first column width is calculated correctly and is based on the longest argument. + * 3. That the word wrapping of the description respects the maximum report width. + * 4. That if the description is being wrapped, the indent for the second line is calculated correctly. + * + * @param int $reportWidth Report width for the test. + * @param array $longOptions The long options which should be displayed. + * @param string $expectedOutput Expected output. + * + * @dataProvider dataReportWidthCalculations + * + * @return void + */ + public function testReportWidthCalculations($reportWidth, $longOptions, $expectedOutput) + { + $config = new ConfigDouble(["--report-width=$reportWidth", '--no-colors']); + $help = new Help($config, $longOptions); + + $reflMethod = new ReflectionMethod($help, 'printCategories'); + $reflMethod->setAccessible(true); + $reflMethod->invoke($help); + $reflMethod->setAccessible(false); + + $this->expectOutputString($expectedOutput); + + }//end testReportWidthCalculations() + + + /** + * Data provider. + * + * @return array>> + */ + public static function dataReportWidthCalculations() + { + $longOptions = [ + 'e', + 'generator', + ]; + + // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- Test readability is more important. + return [ + 'Report width small: 40; forces report width to minimum width of 60' => [ + 'reportWidth' => 40, + 'longOptions' => $longOptions, + 'expectedOutput' => PHP_EOL.'Rule Selection Options:'.PHP_EOL + .' -e Explain a standard by showing the'.PHP_EOL + .' names of all the sniffs it'.PHP_EOL + .' includes.'.PHP_EOL + .' --generator= Show documentation for a standard.'.PHP_EOL + .' Use either the "HTML", "Markdown"'.PHP_EOL + .' or "Text" generator.'.PHP_EOL, + ], + 'Report width is minimum: 60 (= self::MIN_WIDTH)' => [ + 'reportWidth' => Help::MIN_WIDTH, + 'longOptions' => $longOptions, + 'expectedOutput' => PHP_EOL.'Rule Selection Options:'.PHP_EOL + .' -e Explain a standard by showing the'.PHP_EOL + .' names of all the sniffs it'.PHP_EOL + .' includes.'.PHP_EOL + .' --generator= Show documentation for a standard.'.PHP_EOL + .' Use either the "HTML", "Markdown"'.PHP_EOL + .' or "Text" generator.'.PHP_EOL, + ], + 'Report width matches length for one line, not the other: 96; only one should wrap' => [ + 'reportWidth' => 96, + 'longOptions' => $longOptions, + 'expectedOutput' => PHP_EOL.'Rule Selection Options:'.PHP_EOL + .' -e Explain a standard by showing the names of all the sniffs it includes.'.PHP_EOL + .' --generator= Show documentation for a standard. Use either the "HTML", "Markdown"'.PHP_EOL + .' or "Text" generator.'.PHP_EOL, + ], + 'Report width matches longest line: 119; the messages should not wrap and there should be no stray new line at the end' => [ + 'reportWidth' => 119, + 'longOptions' => $longOptions, + 'expectedOutput' => PHP_EOL.'Rule Selection Options:'.PHP_EOL + .' -e Explain a standard by showing the names of all the sniffs it includes.'.PHP_EOL + .' --generator= Show documentation for a standard. Use either the "HTML", "Markdown" or "Text" generator.'.PHP_EOL, + ], + ]; + // phpcs:enable + + }//end dataReportWidthCalculations() + + + /** + * Verify that variable elements in an argument specification get colorized correctly. + * + * @param string $input String to colorize. + * @param string $expected Expected function output. + * + * @dataProvider dataColorizeVariableInput + * + * @return void + */ + public function testColorizeVariableInput($input, $expected) + { + $help = new Help(new ConfigDouble(), []); + + $reflMethod = new ReflectionMethod($help, 'colorizeVariableInput'); + $reflMethod->setAccessible(true); + $result = $reflMethod->invoke($help, $input); + $reflMethod->setAccessible(false); + + $this->assertSame($expected, $result); + + }//end testColorizeVariableInput() + + + /** + * Data provider. + * + * @return array>> + */ + public static function dataColorizeVariableInput() + { + return [ + 'Empty string' => [ + 'input' => '', + 'expected' => '', + ], + 'String without variable element(s)' => [ + 'input' => 'This is text', + 'expected' => 'This is text', + ], + 'String with variable element' => [ + 'input' => 'This text', + 'expected' => "This \033[36m\033[32m text", + ], + 'String with multiple variable elements' => [ + 'input' => ' is ', + 'expected' => "\033[36m\033[32m is \033[36m\033[32m", + ], + 'String with unclosed variable element' => [ + 'input' => 'This 'This [ + 'input' => ' text>', + 'expected' => "\033[36m text>\033[32m", + ], + 'String with nested elements and surrounding text' => [ + 'input' => 'Start text> end', + 'expected' => "Start \033[36m text>\033[32m end", + ], + ]; + + }//end dataColorizeVariableInput() + + + /** + * Test the various option types within a category get displayed correctly. + * + * @param array> $input The options to print. + * @param array $expectedRegex Regexes to validate expected output. + * + * @dataProvider dataPrintCategoryOptions + * + * @return void + */ + public function testPrintCategoryOptionsNoColor($input, $expectedRegex) + { + $config = new ConfigDouble(['--no-colors']); + $help = new Help($config, []); + + $reflProperty = new ReflectionProperty($help, 'activeOptions'); + $reflProperty->setAccessible(true); + $reflProperty->setValue($help, ['cat' => $input]); + $reflProperty->setAccessible(false); + + $reflMethod = new ReflectionMethod($help, 'setMaxOptionNameLength'); + $reflMethod->setAccessible(true); + $reflMethod->invoke($help); + $reflMethod->setAccessible(false); + + $reflMethod = new ReflectionMethod($help, 'printCategoryOptions'); + $reflMethod->setAccessible(true); + $reflMethod->invoke($help, $input); + $reflMethod->setAccessible(false); + + $this->expectOutputRegex($expectedRegex['no-color']); + + }//end testPrintCategoryOptionsNoColor() + + + /** + * Test the various option types within a category get displayed correctly. + * + * @param array> $input The options to print. + * @param array $expectedRegex Regexes to validate expected output. + * + * @dataProvider dataPrintCategoryOptions + * + * @return void + */ + public function testPrintCategoryOptionsColor($input, $expectedRegex) + { + $config = new ConfigDouble(['--colors']); + $help = new Help($config, []); + + $reflProperty = new ReflectionProperty($help, 'activeOptions'); + $reflProperty->setAccessible(true); + $reflProperty->setValue($help, ['cat' => $input]); + $reflProperty->setAccessible(false); + + $reflMethod = new ReflectionMethod($help, 'setMaxOptionNameLength'); + $reflMethod->setAccessible(true); + $reflMethod->invoke($help); + $reflMethod->setAccessible(false); + + $reflMethod = new ReflectionMethod($help, 'printCategoryOptions'); + $reflMethod->setAccessible(true); + $reflMethod->invoke($help, $input); + $reflMethod->setAccessible(false); + + $this->expectOutputRegex($expectedRegex['color']); + + }//end testPrintCategoryOptionsColor() + + + /** + * Data provider. + * + * @return array>|array>> + */ + public static function dataPrintCategoryOptions() + { + $indentLength = strlen(Help::INDENT); + $gutterLength = strlen(Help::GUTTER); + + // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- Test readability is more important. + // phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found -- Test readability is more important. + return [ + 'Input: arg, spacer, arg; new lines in description get preserved' => [ + 'input' => [ + 'short-option' => [ + 'argument' => '-a', + 'description' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + ], + 'blank-line' => [ + 'spacer' => '', + ], + 'long-option-multi-line-description' => [ + 'argument' => '--something=', + 'description' => 'Proin sit amet malesuada libero, finibus bibendum tortor. Nulla vitae quam nec orci finibus pharetra.' + ."\n".'Nam eget blandit dui.', + ], + ], + 'expectedRegex' => [ + 'no-color' => '`^ {'.$indentLength.'}-a {15} {'.$gutterLength.'}Lorem ipsum dolor sit amet, consectetur adipiscing elit\.\R' + .'\R' + .' {'.$indentLength.'}--something= {'.$gutterLength.'}Proin sit amet malesuada libero, finibus bibendum tortor\.\R' + .' {'.($indentLength + 17).'} {'.$gutterLength.'}Nulla vitae quam nec orci finibus pharetra\.\R' + .' {'.($indentLength + 17).'} {'.$gutterLength.'}Nam eget blandit dui\.\R$`', + 'color' => '`^ {'.$indentLength.'}\\033\[32m-a {15}\\033\[0m {'.$gutterLength.'}Lorem ipsum dolor sit amet, consectetur adipiscing elit\.\R' + .'\R' + .' {'.$indentLength.'}\\033\[32m--something=\\033\[36m\\033\[32m\\033\[0m {'.$gutterLength.'}Proin sit amet malesuada libero, finibus bibendum tortor\.\R' + .' {'.($indentLength + 17).'} {'.$gutterLength.'}Nulla vitae quam nec orci finibus pharetra\.\R' + .' {'.($indentLength + 17).'} {'.$gutterLength.'}Nam eget blandit dui\.\R$`', + ], + ], + 'Input: text, arg, text; multi-line text gets wrapped' => [ + 'input' => [ + 'single-line-text' => [ + 'text' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + ], + 'argument-description' => [ + 'argument' => '--something', + 'description' => 'Fusce dapibus sodales est eu sodales.', + ], + 'multi-line-text-gets-wrapped' => [ + 'text' => 'Maecenas vulputate ligula vel feugiat finibus. Mauris sem dui, pretium in turpis auctor, consectetur ultrices lorem.', + ], + ], + 'expectedRegex' => [ + 'no-color' => '`^ {'.$indentLength.'}Lorem ipsum dolor sit amet, consectetur adipiscing elit\.\R' + .' {'.$indentLength.'}--something {'.$gutterLength.'}Fusce dapibus sodales est eu sodales\.\R' + .' {'.$indentLength.'}Maecenas vulputate ligula vel feugiat finibus. Mauris sem dui, pretium in\R' + .' {'.$indentLength.'}turpis auctor, consectetur ultrices lorem\.\R$`', + 'color' => '`^ {'.$indentLength.'}Lorem ipsum dolor sit amet, consectetur adipiscing elit\.\R' + .' {'.$indentLength.'}\\033\[32m--something\\033\[0m {'.$gutterLength.'}Fusce dapibus sodales est eu sodales\.\R' + .' {'.$indentLength.'}Maecenas vulputate ligula vel feugiat finibus. Mauris sem dui, pretium in\R' + .' {'.$indentLength.'}turpis auctor, consectetur ultrices lorem\.\R$`', + ], + ], + ]; + // phpcs:enable + + }//end dataPrintCategoryOptions() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/GetHumanReadableDurationTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/GetHumanReadableDurationTest.php new file mode 100644 index 000000000..93b3d05e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/GetHumanReadableDurationTest.php @@ -0,0 +1,114 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Timing; + +use PHP_CodeSniffer\Util\Timing; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Timing::getHumanReadableDuration() method. + * + * @covers \PHP_CodeSniffer\Util\Timing::getHumanReadableDuration + */ +final class GetHumanReadableDurationTest extends TestCase +{ + + + /** + * Test the method. + * + * @param int|float $duration A duration in milliseconds. + * @param string $expected The expected human readable string. + * + * @dataProvider dataGetHumanReadableDuration + * + * @return void + */ + public function testGetHumanReadableDuration($duration, $expected) + { + $this->assertSame($expected, Timing::getHumanReadableDuration($duration)); + + }//end testGetHumanReadableDuration() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataGetHumanReadableDuration() + { + return [ + 'Duration: 0' => [ + 'duration' => 0, + 'expected' => '0ms', + ], + 'Duration: 13 milliseconds' => [ + 'duration' => 13.232101565, + 'expected' => '13ms', + ], + 'Duration: 14 milliseconds' => [ + 'duration' => 13.916015625, + 'expected' => '14ms', + ], + 'Duration: 999 milliseconds' => [ + 'duration' => 999.2236, + 'expected' => '999ms', + ], + 'Duration: 999+ milliseconds' => [ + 'duration' => 999.89236, + 'expected' => '1000ms', + ], + 'Duration: 1 second' => [ + 'duration' => 1000, + 'expected' => '1 secs', + ], + 'Duration: slightly more than 1 second' => [ + 'duration' => 1001.178215, + 'expected' => '1 secs', + ], + 'Duration: just under a 1 minute' => [ + 'duration' => 59999.3851, + 'expected' => '60 secs', + ], + 'Duration: exactly 1 minute' => [ + 'duration' => 60000, + 'expected' => '1 mins', + ], + 'Duration: slightly more than 1 minute' => [ + 'duration' => 60001.7581235, + 'expected' => '1 mins', + ], + 'Duration: 1 minute, just under half a second' => [ + 'duration' => 60499.83639, + 'expected' => '1 mins, 0.5 secs', + ], + 'Duration: 1 minute, just over half a second' => [ + 'duration' => 60501.961238, + 'expected' => '1 mins, 0.5 secs', + ], + 'Duration: 1 minute, 1 second' => [ + 'duration' => 61000, + 'expected' => '1 mins, 1 secs', + ], + 'Duration: exactly 1 hour' => [ + 'duration' => 3600000, + 'expected' => '60 mins', + ], + 'Duration: 89.4 mins' => [ + 'duration' => 5364000, + 'expected' => '89 mins, 24 secs', + ], + ]; + + }//end dataGetHumanReadableDuration() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/TimingTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/TimingTest.php new file mode 100644 index 000000000..79952c8c7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Timing/TimingTest.php @@ -0,0 +1,123 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Timing; + +use PHP_CodeSniffer\Util\Timing; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Timing class. + * + * {@internal These tests need to run in separate processes as the Timing class uses static properties + * to keep track of the start time and whether or not the runtime has been printed and these + * can't be unset/reset once set.} + * + * @covers \PHP_CodeSniffer\Util\Timing + * + * @runTestsInSeparateProcesses + * @preserveGlobalState disabled + */ +final class TimingTest extends TestCase +{ + + + /** + * Verify that getDuration() returns 0 when the timer wasn't started. + * + * @return void + */ + public function testGetDurationWithoutStartReturnsZero() + { + $this->assertSame(0, Timing::getDuration()); + + }//end testGetDurationWithoutStartReturnsZero() + + + /** + * Verify that getDuration() returns 0 when the timer wasn't started. + * + * @return void + */ + public function testGetDurationWithStartReturnsMilliseconds() + { + Timing::startTiming(); + usleep(1500); + $duration = Timing::getDuration(); + + $this->assertTrue(is_float($duration)); + $this->assertGreaterThan(1, $duration); + $this->assertLessThan(15, $duration); + + }//end testGetDurationWithStartReturnsMilliseconds() + + + /** + * Verify that printRunTime() doesn't print anything if the timer wasn't started. + * + * @return void + */ + public function testTimeIsNotPrintedIfTimerWasNeverStarted() + { + $this->expectOutputString(''); + Timing::printRunTime(); + + }//end testTimeIsNotPrintedIfTimerWasNeverStarted() + + + /** + * Verify that printRunTime() doesn't print anything if the timer wasn't started. + * + * @return void + */ + public function testTimeIsNotPrintedIfTimerWasNeverStartedEvenWhenForced() + { + $this->expectOutputString(''); + Timing::printRunTime(true); + + }//end testTimeIsNotPrintedIfTimerWasNeverStartedEvenWhenForced() + + + /** + * Verify that printRunTime() when called multiple times only prints the runtime information once. + * + * @return void + */ + public function testTimeIsPrintedOnlyOnce() + { + $this->expectOutputRegex('`^Time: [0-9]+ms; Memory: [0-9\.]+MB'.PHP_EOL.PHP_EOL.'$`'); + + Timing::startTiming(); + usleep(2000); + Timing::printRunTime(); + Timing::printRunTime(); + Timing::printRunTime(); + + }//end testTimeIsPrintedOnlyOnce() + + + /** + * Verify that printRunTime() when called multiple times prints the runtime information multiple times if forced. + * + * @return void + */ + public function testTimeIsPrintedMultipleTimesOnlyIfForced() + { + $this->expectOutputRegex('`^(Time: [0-9]+ms; Memory: [0-9\.]+MB'.PHP_EOL.PHP_EOL.'){3}$`'); + + Timing::startTiming(); + usleep(2000); + Timing::printRunTime(true); + Timing::printRunTime(true); + Timing::printRunTime(true); + + }//end testTimeIsPrintedMultipleTimesOnlyIfForced() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/GetHighestWeightedTokenTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/GetHighestWeightedTokenTest.php new file mode 100644 index 000000000..f03d20a39 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/GetHighestWeightedTokenTest.php @@ -0,0 +1,162 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Tokens; + +use PHP_CodeSniffer\Util\Tokens; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Tokens::getHighestWeightedToken() method. + * + * @covers \PHP_CodeSniffer\Util\Tokens::getHighestWeightedToken + */ +final class GetHighestWeightedTokenTest extends TestCase +{ + + + /** + * Test the method. + * + * @param array $tokens The tokens to find the heighest weighted one. + * @param int|false $expected The expected function return value. + * + * @dataProvider dataGetHighestWeightedToken + * + * @return void + */ + public function testGetHighestWeightedToken($tokens, $expected) + { + $this->assertSame($expected, Tokens::getHighestWeightedToken($tokens)); + + }//end testGetHighestWeightedToken() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataGetHighestWeightedToken() + { + $data = [ + 'Array of non-tokens passed, returns first' => [ + 'tokens' => [ + PHP_SAPI, + PHP_MAJOR_VERSION, + PHP_OS, + ], + 'expected' => PHP_SAPI, + ], + 'No weightings available for any of the selected tokens, first one wins' => [ + 'tokens' => [ + T_VARIABLE, + T_STRING, + T_EXTENDS, + T_IMPLEMENTS, + ], + 'expected' => T_VARIABLE, + ], + 'single token always returns that token' => [ + 'tokens' => [T_VARIABLE], + 'expected' => T_VARIABLE, + ], + 'Unknown and known token, known token wins' => [ + 'tokens' => [ + T_VARIABLE, + T_SELF, + ], + 'expected' => T_SELF, + ], + 'Known and unknown token, known token wins' => [ + 'tokens' => [ + T_CLOSURE, + T_STRING, + ], + 'expected' => T_CLOSURE, + ], + 'Two tokens with equal weights passed, first one wins' => [ + 'tokens' => [ + T_CLOSURE, + T_FUNCTION, + ], + 'expected' => T_CLOSURE, + ], + 'Five tokens with equal weights passed, first one wins' => [ + 'tokens' => [ + T_NAMESPACE, + T_TRAIT, + T_ENUM, + T_CLASS, + T_INTERFACE, + ], + 'expected' => T_NAMESPACE, + ], + 'Tokens with different weights passed, heightest (25) wins' => [ + 'tokens' => [ + T_BITWISE_OR, + T_SELF, + T_MUL_EQUAL, + ], + 'expected' => T_SELF, + ], + 'Tokens with different weights passed, heightest (50) wins' => [ + 'tokens' => [ + T_BITWISE_XOR, + T_CATCH, + T_SPACESHIP, + T_PARENT, + ], + 'expected' => T_CATCH, + ], + ]; + + $high100 = [ + T_MULTIPLY, + T_BITWISE_AND, + T_SELF, + T_FOREACH, + T_CLOSURE, + ]; + $data['Tokens with different weights passed, ordered low-high, heightest (100) wins'] = [ + 'tokens' => $high100, + 'expected' => T_CLOSURE, + ]; + + shuffle($high100); + $data['Tokens with different weights passed, order random, heightest (100) wins'] = [ + 'tokens' => $high100, + 'expected' => T_CLOSURE, + ]; + + $high1000 = [ + T_ENUM, + T_FUNCTION, + T_ELSEIF, + T_PARENT, + T_BITWISE_OR, + T_MODULUS, + ]; + $data['Tokens with different weights passed, ordered low-high, heightest (1000) wins'] = [ + 'tokens' => $high1000, + 'expected' => T_ENUM, + ]; + + shuffle($high1000); + $data['Tokens with different weights passed, order random, heightest (1000) wins'] = [ + 'tokens' => $high1000, + 'expected' => T_ENUM, + ]; + + return $data; + + }//end dataGetHighestWeightedToken() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/TokenNameTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/TokenNameTest.php new file mode 100644 index 000000000..435df0713 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Core/Util/Tokens/TokenNameTest.php @@ -0,0 +1,81 @@ + + * @copyright 2024 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Core\Util\Tokens; + +use PHP_CodeSniffer\Util\Tokens; +use PHPUnit\Framework\TestCase; + +/** + * Tests for the \PHP_CodeSniffer\Util\Tokens::tokenName() method. + * + * @covers \PHP_CodeSniffer\Util\Tokens::tokenName + */ +final class TokenNameTest extends TestCase +{ + + + /** + * Test the method. + * + * @param int|string $tokenCode The PHP/PHPCS token code to get the name for. + * @param string $expected The expected token name. + * + * @dataProvider dataTokenName + * + * @return void + */ + public function testTokenName($tokenCode, $expected) + { + $this->assertSame($expected, Tokens::tokenName($tokenCode)); + + }//end testTokenName() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataTokenName() + { + return [ + 'PHP native token: T_ECHO' => [ + 'tokenCode' => T_ECHO, + 'expected' => 'T_ECHO', + ], + 'PHP native token: T_FUNCTION' => [ + 'tokenCode' => T_FUNCTION, + 'expected' => 'T_FUNCTION', + ], + 'PHPCS native token: T_CLOSURE' => [ + 'tokenCode' => T_CLOSURE, + 'expected' => 'T_CLOSURE', + ], + 'PHPCS native token: T_STRING_CONCAT' => [ + 'tokenCode' => T_STRING_CONCAT, + 'expected' => 'T_STRING_CONCAT', + ], + + // Document the current behaviour for invalid input. + // This behaviour is subject to change. + 'Non-token integer passed' => [ + 'tokenCode' => 100000, + 'expected' => 'UNKNOWN', + ], + 'Non-token string passed' => [ + 'tokenCode' => 'something', + 'expected' => 'ing', + ], + ]; + + }//end dataTokenName() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/FileList.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/FileList.php new file mode 100644 index 000000000..ac3c944f3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/FileList.php @@ -0,0 +1,98 @@ + + * @copyright 2019 Juliette Reinders Folmer. All rights reserved. + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RegexIterator; + +class FileList +{ + + /** + * The path to the project root directory. + * + * @var string + */ + protected $rootPath; + + /** + * Recursive directory iterator. + * + * @var \DirectoryIterator + */ + public $fileIterator; + + /** + * Base regex to use if no filter regex is provided. + * + * Matches based on: + * - File path starts with the project root (replacement done in constructor). + * - Don't match .git/ files. + * - Don't match dot files, i.e. "." or "..". + * - Don't match backup files. + * - Match everything else in a case-insensitive manner. + * + * @var string + */ + private $baseRegex = '`^%s(?!\.git/)(?!(.*/)?\.+$)(?!.*\.(bak|orig)).*$`Dix'; + + + /** + * Constructor. + * + * @param string $directory The directory to examine. + * @param string $rootPath Path to the project root. + * @param string $filter PCRE regular expression to filter the file list with. + */ + public function __construct($directory, $rootPath='', $filter='') + { + $this->rootPath = $rootPath; + + $directory = new RecursiveDirectoryIterator( + $directory, + RecursiveDirectoryIterator::UNIX_PATHS + ); + $flattened = new RecursiveIteratorIterator( + $directory, + RecursiveIteratorIterator::LEAVES_ONLY, + RecursiveIteratorIterator::CATCH_GET_CHILD + ); + + if ($filter === '') { + $filter = sprintf($this->baseRegex, preg_quote($this->rootPath)); + } + + $this->fileIterator = new RegexIterator($flattened, $filter); + + return $this; + + }//end __construct() + + + /** + * Retrieve the filtered file list as an array. + * + * @return array + */ + public function getList() + { + $fileList = []; + + foreach ($this->fileIterator as $file) { + $fileList[] = str_replace($this->rootPath, '', $file); + } + + return $fileList; + + }//end getList() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php new file mode 100644 index 000000000..ccd90c513 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php @@ -0,0 +1,468 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use DirectoryIterator; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Files\LocalFile; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Tests\ConfigDouble; +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +abstract class AbstractSniffUnitTest extends TestCase +{ + + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * Overwrite this attribute in a child class of TestCase. + * Setting this attribute in setUp() has no effect! + * + * @var boolean + */ + protected $backupGlobals = false; + + /** + * The path to the standard's main directory. + * + * @var string + */ + public $standardsDir = null; + + /** + * The path to the standard's test directory. + * + * @var string + */ + public $testsDir = null; + + + /** + * Sets up this unit test. + * + * @before + * + * @return void + */ + protected function setUpPrerequisites() + { + $class = get_class($this); + $this->standardsDir = $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$class]; + $this->testsDir = $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$class]; + + }//end setUpPrerequisites() + + + /** + * Get a list of all test files to check. + * + * These will have the same base as the sniff name but different extensions. + * We ignore the .php file as it is the class. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = []; + + $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); + $di = new DirectoryIterator($dir); + + foreach ($di as $file) { + $path = $file->getPathname(); + if (substr($path, 0, strlen($testFileBase)) === $testFileBase) { + if ($path !== $testFileBase.'php' && substr($path, -5) !== 'fixed' && substr($path, -4) !== '.bak') { + $testFiles[] = $path; + } + } + } + + // Put them in order. + sort($testFiles, SORT_NATURAL); + + return $testFiles; + + }//end getTestFiles() + + + /** + * Should this test be skipped for some reason. + * + * @return boolean + */ + protected function shouldSkipTest() + { + return false; + + }//end shouldSkipTest() + + + /** + * Tests the extending classes Sniff class. + * + * @return void + * @throws \PHPUnit\Framework\Exception + */ + final public function testSniff() + { + // Skip this test if we can't run in this environment. + if ($this->shouldSkipTest() === true) { + $this->markTestSkipped(); + } + + $sniffCode = Common::getSniffCode(get_class($this)); + list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); + + $testFileBase = $this->testsDir.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'UnitTest.'; + + // Get a list of all test files to check. + $testFiles = $this->getTestFiles($testFileBase); + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'][] = $testFiles; + + if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG']) === true) { + $config = $GLOBALS['PHP_CODESNIFFER_CONFIG']; + } else { + $config = new ConfigDouble(); + $config->cache = false; + $GLOBALS['PHP_CODESNIFFER_CONFIG'] = $config; + } + + $config->standards = [$standardName]; + $config->sniffs = [$sniffCode]; + $config->ignored = []; + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS']) === false) { + $GLOBALS['PHP_CODESNIFFER_RULESETS'] = []; + } + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]) === false) { + $ruleset = new Ruleset($config); + $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName] = $ruleset; + } + + $ruleset = $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]; + + $sniffFile = $this->standardsDir.DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'Sniff.php'; + + $sniffClassName = substr(get_class($this), 0, -8).'Sniff'; + $sniffClassName = str_replace('\Tests\\', '\Sniffs\\', $sniffClassName); + $sniffClassName = Common::cleanSniffClass($sniffClassName); + + $restrictions = [strtolower($sniffClassName) => true]; + $ruleset->registerSniffs([$sniffFile], $restrictions, []); + $ruleset->populateTokenListeners(); + + $failureMessages = []; + foreach ($testFiles as $testFile) { + $filename = basename($testFile); + $oldConfig = $config->getSettings(); + + try { + $this->setCliValues($filename, $config); + $phpcsFile = new LocalFile($testFile, $ruleset, $config); + $phpcsFile->process(); + } catch (RuntimeException $e) { + $this->fail('An unexpected exception has been caught: '.$e->getMessage()); + } + + $failures = $this->generateFailureMessages($phpcsFile); + $failureMessages = array_merge($failureMessages, $failures); + + if ($phpcsFile->getFixableCount() > 0) { + // Attempt to fix the errors. + $phpcsFile->fixer->fixFile(); + $fixable = $phpcsFile->getFixableCount(); + if ($fixable > 0) { + $failureMessages[] = "Failed to fix $fixable fixable violations in $filename"; + } + + // Check for a .fixed file to check for accuracy of fixes. + $fixedFile = $testFile.'.fixed'; + $filename = basename($testFile); + if (file_exists($fixedFile) === true) { + if ($phpcsFile->fixer->getContents() !== file_get_contents($fixedFile)) { + // Only generate the (expensive) diff if a difference is expected. + $diff = $phpcsFile->fixer->generateDiff($fixedFile); + if (trim($diff) !== '') { + $fixedFilename = basename($fixedFile); + $failureMessages[] = "Fixed version of $filename does not match expected version in $fixedFilename; the diff is\n$diff"; + } + } + } else if (is_callable([$this, 'addWarning']) === true) { + $this->addWarning("Missing fixed version of $filename to verify the accuracy of fixes, while the sniff is making fixes against the test case file"); + } + }//end if + + // Restore the config. + $config->setSettings($oldConfig); + }//end foreach + + if (empty($failureMessages) === false) { + $this->fail(implode(PHP_EOL, $failureMessages)); + } + + }//end testSniff() + + + /** + * Generate a list of test failures for a given sniffed file. + * + * @param \PHP_CodeSniffer\Files\LocalFile $file The file being tested. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function generateFailureMessages(LocalFile $file) + { + $testFile = $file->getFilename(); + + $foundErrors = $file->getErrors(); + $foundWarnings = $file->getWarnings(); + $expectedErrors = $this->getErrorList(basename($testFile)); + $expectedWarnings = $this->getWarningList(basename($testFile)); + + if (is_array($expectedErrors) === false) { + throw new RuntimeException('getErrorList() must return an array'); + } + + if (is_array($expectedWarnings) === false) { + throw new RuntimeException('getWarningList() must return an array'); + } + + /* + We merge errors and warnings together to make it easier + to iterate over them and produce the errors string. In this way, + we can report on errors and warnings in the same line even though + it's not really structured to allow that. + */ + + $allProblems = []; + $failureMessages = []; + + foreach ($foundErrors as $line => $lineErrors) { + foreach ($lineErrors as $column => $errors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundErrorsTemp = []; + foreach ($allProblems[$line]['found_errors'] as $foundError) { + $foundErrorsTemp[] = $foundError; + } + + $errorsTemp = []; + foreach ($errors as $foundError) { + $errorsTemp[] = $foundError['message'].' ('.$foundError['source'].')'; + + $source = $foundError['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($foundError['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); + }//end foreach + + if (isset($expectedErrors[$line]) === true) { + $allProblems[$line]['expected_errors'] = $expectedErrors[$line]; + } else { + $allProblems[$line]['expected_errors'] = 0; + } + + unset($expectedErrors[$line]); + }//end foreach + + foreach ($expectedErrors as $line => $numErrors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_errors'] = $numErrors; + } + + foreach ($foundWarnings as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $warnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundWarningsTemp = []; + foreach ($allProblems[$line]['found_warnings'] as $foundWarning) { + $foundWarningsTemp[] = $foundWarning; + } + + $warningsTemp = []; + foreach ($warnings as $warning) { + $warningsTemp[] = $warning['message'].' ('.$warning['source'].')'; + + $source = $warning['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'], true) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($warning['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'], true) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp); + }//end foreach + + if (isset($expectedWarnings[$line]) === true) { + $allProblems[$line]['expected_warnings'] = $expectedWarnings[$line]; + } else { + $allProblems[$line]['expected_warnings'] = 0; + } + + unset($expectedWarnings[$line]); + }//end foreach + + foreach ($expectedWarnings as $line => $numWarnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_warnings'] = $numWarnings; + } + + // Order the messages by line number. + ksort($allProblems); + + foreach ($allProblems as $line => $problems) { + $numErrors = count($problems['found_errors']); + $numWarnings = count($problems['found_warnings']); + $expectedErrors = $problems['expected_errors']; + $expectedWarnings = $problems['expected_warnings']; + + $errors = ''; + $foundString = ''; + + if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) { + $lineMessage = "[LINE $line]"; + $expectedMessage = 'Expected '; + $foundMessage = 'in '.basename($testFile).' but found '; + + if ($expectedErrors !== $numErrors) { + $expectedMessage .= "$expectedErrors error(s)"; + $foundMessage .= "$numErrors error(s)"; + if ($numErrors !== 0) { + $foundString .= 'error(s)'; + $errors .= implode(PHP_EOL.' -> ', $problems['found_errors']); + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= ' and '; + $foundMessage .= ' and '; + if ($numWarnings !== 0) { + if ($foundString !== '') { + $foundString .= ' and '; + } + } + } + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= "$expectedWarnings warning(s)"; + $foundMessage .= "$numWarnings warning(s)"; + if ($numWarnings !== 0) { + $foundString .= 'warning(s)'; + if (empty($errors) === false) { + $errors .= PHP_EOL.' -> '; + } + + $errors .= implode(PHP_EOL.' -> ', $problems['found_warnings']); + } + } + + $fullMessage = "$lineMessage $expectedMessage $foundMessage."; + if ($errors !== '') { + $fullMessage .= " The $foundString found were:".PHP_EOL." -> $errors"; + } + + $failureMessages[] = $fullMessage; + }//end if + }//end foreach + + return $failureMessages; + + }//end generateFailureMessages() + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $filename The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function setCliValues($filename, $config) + { + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array + */ + abstract protected function getErrorList(); + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array + */ + abstract protected function getWarningList(); + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php new file mode 100644 index 000000000..1e273e28e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php @@ -0,0 +1,114 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use PHP_CodeSniffer\Autoload; +use PHP_CodeSniffer\Util\Standards; +use PHPUnit\Framework\TestSuite; +use PHPUnit\TextUI\TestRunner; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; + +class AllSniffs +{ + + + /** + * Prepare the test runner. + * + * @return void + */ + public static function main() + { + TestRunner::run(self::suite()); + + }//end main() + + + /** + * Add all sniff unit tests into a test suite. + * + * Sniff unit tests are found by recursing through the 'Tests' directory + * of each installed coding standard. + * + * @return \PHPUnit\Framework\TestSuite + */ + public static function suite() + { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = []; + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = []; + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'] = []; + + $suite = new TestSuite('PHP CodeSniffer Standards'); + + // Optionally allow for ignoring the tests for one or more standards. + $ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS'); + if ($ignoreTestsForStandards === false) { + $ignoreTestsForStandards = []; + } else { + $ignoreTestsForStandards = explode(',', $ignoreTestsForStandards); + } + + $installedStandards = self::getInstalledStandardDetails(); + + foreach ($installedStandards as $standard => $details) { + Autoload::addSearchPath($details['path'], $details['namespace']); + + if (in_array($standard, $ignoreTestsForStandards, true) === true) { + continue; + } + + $testsDir = $details['path'].DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR; + if (is_dir($testsDir) === false) { + // No tests for this standard. + continue; + } + + $di = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($testsDir)); + + foreach ($di as $file) { + // Skip hidden files. + if (substr($file->getFilename(), 0, 1) === '.') { + continue; + } + + // Tests must have the extension 'php'. + $parts = explode('.', $file); + $ext = array_pop($parts); + if ($ext !== 'php') { + continue; + } + + $className = Autoload::loadFile($file->getPathname()); + $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$className] = $details['path']; + $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$className] = $testsDir; + $suite->addTestSuite($className); + } + }//end foreach + + return $suite; + + }//end suite() + + + /** + * Get the details of all coding standards installed. + * + * @return array + * @see Standards::getInstalledStandardDetails() + */ + protected static function getInstalledStandardDetails() + { + return Standards::getInstalledStandardDetails(true); + + }//end getInstalledStandardDetails() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite.php new file mode 100644 index 000000000..4598a8562 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite.php @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; + +class TestSuite extends PHPUnit_TestSuite +{ + + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param \PHPUnit\Framework\TestResult $result A test result. + * + * @return \PHPUnit\Framework\TestResult + */ + public function run(TestResult $result=null) + { + $result = parent::run($result); + printPHPCodeSnifferTestOutput(); + return $result; + + }//end run() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php new file mode 100644 index 000000000..ad0947c58 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/TestSuite7.php @@ -0,0 +1,35 @@ + + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests; + +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite as PHPUnit_TestSuite; + +class TestSuite extends PHPUnit_TestSuite +{ + + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param \PHPUnit\Framework\TestResult|null $result A test result. + * + * @return \PHPUnit\Framework\TestResult + */ + public function run(?TestResult $result=null): TestResult + { + $result = parent::run($result); + printPHPCodeSnifferTestOutput(); + return $result; + + }//end run() + + +}//end class diff --git a/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/bootstrap.php b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/bootstrap.php new file mode 100644 index 000000000..cf4936daa --- /dev/null +++ b/.extlib/simplesamlphp/vendor/squizlabs/php_codesniffer/tests/bootstrap.php @@ -0,0 +1,80 @@ + + * @copyright 2006-2017 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +if (defined('PHP_CODESNIFFER_IN_TESTS') === false) { + define('PHP_CODESNIFFER_IN_TESTS', true); +} + +if (defined('PHP_CODESNIFFER_CBF') === false) { + define('PHP_CODESNIFFER_CBF', false); +} + +if (defined('PHP_CODESNIFFER_VERBOSITY') === false) { + define('PHP_CODESNIFFER_VERBOSITY', 0); +} + +require_once __DIR__.'/../autoload.php'; + +$tokens = new \PHP_CodeSniffer\Util\Tokens(); + +// Compatibility for PHPUnit < 6 and PHPUnit 6+. +if (class_exists('PHPUnit_Framework_TestSuite') === true && class_exists('PHPUnit\Framework\TestSuite') === false) { + class_alias('PHPUnit_Framework_TestSuite', 'PHPUnit'.'\Framework\TestSuite'); +} + +if (class_exists('PHPUnit_Framework_TestCase') === true && class_exists('PHPUnit\Framework\TestCase') === false) { + class_alias('PHPUnit_Framework_TestCase', 'PHPUnit'.'\Framework\TestCase'); +} + +if (class_exists('PHPUnit_TextUI_TestRunner') === true && class_exists('PHPUnit\TextUI\TestRunner') === false) { + class_alias('PHPUnit_TextUI_TestRunner', 'PHPUnit'.'\TextUI\TestRunner'); +} + +if (class_exists('PHPUnit_Framework_TestResult') === true && class_exists('PHPUnit\Framework\TestResult') === false) { + class_alias('PHPUnit_Framework_TestResult', 'PHPUnit'.'\Framework\TestResult'); +} + + +/** + * A global util function to help print unit test fixing data. + * + * @return void + */ +function printPHPCodeSnifferTestOutput() +{ + echo PHP_EOL.PHP_EOL; + + $output = 'The test files'; + $data = []; + + $codeCount = count($GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']); + if (empty($GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']) === false) { + $files = call_user_func_array('array_merge', $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES']); + $files = array_unique($files); + $fileCount = count($files); + + $output = '%d sniff test files'; + $data[] = $fileCount; + } + + $output .= ' generated %d unique error codes'; + $data[] = $codeCount; + + if ($codeCount > 0) { + $fixes = count($GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']); + $percent = round(($fixes / $codeCount * 100), 2); + + $output .= '; %d were fixable (%d%%)'; + $data[] = $fixes; + $data[] = $percent; + } + + vprintf($output, $data); + +}//end printPHPCodeSnifferTestOutput() diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/CopyTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/CopyTrait.php new file mode 100644 index 000000000..a271a9d10 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/CopyTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.8.1', '>=')) { + /** + * @internal + */ + trait CopyTrait + { + public function copy($src, $dst, $options = null): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait CopyTrait + { + public function copy($src, $dst, $options = null): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php new file mode 100644 index 000000000..88ed1e9d3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GeosearchTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait GeosearchTrait + { + public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GeosearchTrait + { + public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php new file mode 100644 index 000000000..4522d20b5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/GetrangeTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait GetrangeTrait + { + public function getrange($key, $start, $end): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GetrangeTrait + { + public function getrange($key, $start, $end): \Relay\Relay|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/HsetTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/HsetTrait.php new file mode 100644 index 000000000..a7cb8fff0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/HsetTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait HsetTrait + { + public function hset($key, ...$keys_and_vals): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait HsetTrait + { + public function hset($key, $mem, $val, ...$kvals): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/MoveTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/MoveTrait.php new file mode 100644 index 000000000..d00735ddb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/MoveTrait.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 Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait MoveTrait + { + public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args()); + } + + public function lmove($srckey, $dstkey, $srcpos, $dstpos): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait MoveTrait + { + public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): \Relay\Relay|false|null|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args()); + } + + public function lmove($srckey, $dstkey, $srcpos, $dstpos): \Relay\Relay|false|null|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php new file mode 100644 index 000000000..0b7409045 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/NullableReturnTrait.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait NullableReturnTrait + { + public function dump($key): \Relay\Relay|false|string|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args()); + } + + public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args()); + } + + public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args()); + } + + public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args()); + } + + public function zscore($key, $member): \Relay\Relay|false|float|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait NullableReturnTrait + { + public function dump($key): \Relay\Relay|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args()); + } + + public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args()); + } + + public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args()); + } + + public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args()); + } + + public function zscore($key, $member): \Relay\Relay|false|float + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/PfcountTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/PfcountTrait.php new file mode 100644 index 000000000..340db8af7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/Relay/PfcountTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait PfcountTrait + { + public function pfcount($key_or_keys): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait PfcountTrait + { + public function pfcount($key): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args()); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxy.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxy.php index 96d7d19b4..e86c2102a 100644 --- a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxy.php +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxy.php @@ -11,6 +11,13 @@ namespace Symfony\Component\Cache\Traits; +use Symfony\Component\Cache\Traits\Relay\CopyTrait; +use Symfony\Component\Cache\Traits\Relay\GeosearchTrait; +use Symfony\Component\Cache\Traits\Relay\GetrangeTrait; +use Symfony\Component\Cache\Traits\Relay\HsetTrait; +use Symfony\Component\Cache\Traits\Relay\MoveTrait; +use Symfony\Component\Cache\Traits\Relay\NullableReturnTrait; +use Symfony\Component\Cache\Traits\Relay\PfcountTrait; use Symfony\Component\VarExporter\LazyObjectInterface; use Symfony\Component\VarExporter\LazyProxyTrait; use Symfony\Contracts\Service\ResetInterface; @@ -25,9 +32,16 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); */ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInterface { + use CopyTrait; + use GeosearchTrait; + use GetrangeTrait; + use HsetTrait; use LazyProxyTrait { resetLazyObject as reset; } + use MoveTrait; + use NullableReturnTrait; + use PfcountTrait; use RelayProxyTrait; private const LAZY_OBJECT_PROPERTY_SCOPES = []; @@ -267,11 +281,6 @@ public function dbsize(): \Relay\Relay|false|int return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbsize(...\func_get_args()); } - public function dump($key): \Relay\Relay|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); - } - public function replicaof($host = null, $port = 0): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->replicaof(...\func_get_args()); @@ -392,11 +401,6 @@ public function geoadd($key, $lng, $lat, $member, ...$other_triples_and_options) return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args()); } - public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args()); - } - public function geohash($key, $member, ...$other_members): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args()); @@ -422,11 +426,6 @@ public function georadius_ro($key, $lng, $lat, $radius, $unit, $options = []): m return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args()); } - public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args()); - } - public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearchstore(...\func_get_args()); @@ -442,11 +441,6 @@ public function getset($key, $value): mixed return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getset(...\func_get_args()); } - public function getrange($key, $start, $end): \Relay\Relay|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args()); - } - public function setrange($key, $start, $value): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setrange(...\func_get_args()); @@ -527,11 +521,6 @@ public function pfadd($key, $elements): \Relay\Relay|false|int return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args()); } - public function pfcount($key): \Relay\Relay|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args()); - } - public function pfmerge($dst, $srckeys): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args()); @@ -642,16 +631,6 @@ public function type($key): \Relay\Relay|bool|int|string return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args()); } - public function lmove($srckey, $dstkey, $srcpos, $dstpos): \Relay\Relay|false|null|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args()); - } - - public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): \Relay\Relay|false|null|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args()); - } - public function lrange($key, $start, $stop): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args()); @@ -807,11 +786,6 @@ public function hmget($hash, $members): \Relay\Relay|array|false return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmget(...\func_get_args()); } - public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args()); - } - public function hmset($hash, $members): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmset(...\func_get_args()); @@ -827,11 +801,6 @@ public function hsetnx($hash, $member, $value): \Relay\Relay|bool return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetnx(...\func_get_args()); } - public function hset($key, $mem, $val, ...$kvals): \Relay\Relay|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args()); - } - public function hdel($key, $mem, ...$mems): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hdel(...\func_get_args()); @@ -1097,11 +1066,6 @@ public function xack($key, $group, $ids): \Relay\Relay|false|int return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args()); } - public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args()); - } - public function xclaim($key, $group, $consumer, $min_idle, $ids, $options): \Relay\Relay|array|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args()); @@ -1207,16 +1171,6 @@ public function zrevrangebylex($key, $max, $min, $offset = -1, $count = -1): \Re return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebylex(...\func_get_args()); } - public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args()); - } - - public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args()); - } - public function zrem($key, ...$args): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrem(...\func_get_args()); @@ -1272,11 +1226,6 @@ public function zmscore($key, ...$mems): \Relay\Relay|array|false return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmscore(...\func_get_args()); } - public function zscore($key, $member): \Relay\Relay|false|float - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args()); - } - public function zinter($keys, $weights = null, $options = null): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinter(...\func_get_args()); diff --git a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxyTrait.php b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxyTrait.php index a1d252b96..c35b5fa01 100644 --- a/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxyTrait.php +++ b/.extlib/simplesamlphp/vendor/symfony/cache/Traits/RelayProxyTrait.php @@ -17,11 +17,6 @@ */ trait RelayProxyTrait { - public function copy($src, $dst, $options = null): \Relay\Relay|bool - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); - } - public function jsonArrAppend($key, $value_or_array, $path = null): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrAppend(...\func_get_args()); @@ -148,9 +143,5 @@ public function jsonType($key, $path = null): \Relay\Relay|array|false */ trait RelayProxyTrait { - public function copy($src, $dst, $options = null): \Relay\Relay|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); - } } } diff --git a/.extlib/simplesamlphp/vendor/symfony/dependency-injection/Attribute/AutowireLocator.php b/.extlib/simplesamlphp/vendor/symfony/dependency-injection/Attribute/AutowireLocator.php index 853a18a82..5d3cf374f 100644 --- a/.extlib/simplesamlphp/vendor/symfony/dependency-injection/Attribute/AutowireLocator.php +++ b/.extlib/simplesamlphp/vendor/symfony/dependency-injection/Attribute/AutowireLocator.php @@ -28,8 +28,8 @@ class AutowireLocator extends Autowire /** * @see ServiceSubscriberInterface::getSubscribedServices() * - * @param string|array $services An explicit list of services or a tag name - * @param string|string[] $exclude A service or a list of services to exclude + * @param string|array $services An explicit list of services or a tag name + * @param string|string[] $exclude A service or a list of services to exclude */ public function __construct( string|array $services, diff --git a/.extlib/simplesamlphp/vendor/symfony/dependency-injection/ContainerBuilder.php b/.extlib/simplesamlphp/vendor/symfony/dependency-injection/ContainerBuilder.php index 62b41a06c..5be5b76f5 100644 --- a/.extlib/simplesamlphp/vendor/symfony/dependency-injection/ContainerBuilder.php +++ b/.extlib/simplesamlphp/vendor/symfony/dependency-injection/ContainerBuilder.php @@ -360,7 +360,7 @@ public function getReflectionClass(?string $class, bool $throw = true): ?\Reflec $resource = new ClassExistenceResource($class, false); $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } else { - $classReflector = class_exists($class) ? new \ReflectionClass($class) : false; + $classReflector = class_exists($class) || interface_exists($class, false) ? new \ReflectionClass($class) : false; } } catch (\ReflectionException $e) { if ($throw) { diff --git a/.extlib/simplesamlphp/vendor/symfony/error-handler/Resources/bin/extract-tentative-return-types.php b/.extlib/simplesamlphp/vendor/symfony/error-handler/Resources/bin/extract-tentative-return-types.php old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/symfony/error-handler/Resources/bin/patch-type-declarations b/.extlib/simplesamlphp/vendor/symfony/error-handler/Resources/bin/patch-type-declarations old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/symfony/http-foundation/Request.php b/.extlib/simplesamlphp/vendor/symfony/http-foundation/Request.php index c45170e3f..922014133 100644 --- a/.extlib/simplesamlphp/vendor/symfony/http-foundation/Request.php +++ b/.extlib/simplesamlphp/vendor/symfony/http-foundation/Request.php @@ -351,13 +351,7 @@ public static function create(string $uri, string $method = 'GET', array $parame $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); - if (false === ($components = parse_url($uri)) && '/' === ($uri[0] ?? '')) { - trigger_deprecation('symfony/http-foundation', '6.3', 'Calling "%s()" with an invalid URI is deprecated.', __METHOD__); - $components = parse_url($uri.'#'); - unset($components['fragment']); - } - - if (false === $components) { + if (false === $components = parse_url(\strlen($uri) !== strcspn($uri, '?#') ? $uri : $uri.'#')) { throw new BadRequestException('Invalid URI.'); } diff --git a/.extlib/simplesamlphp/vendor/symfony/http-kernel/HttpCache/HttpCache.php b/.extlib/simplesamlphp/vendor/symfony/http-kernel/HttpCache/HttpCache.php index 6ffe88905..3b484e5c3 100644 --- a/.extlib/simplesamlphp/vendor/symfony/http-kernel/HttpCache/HttpCache.php +++ b/.extlib/simplesamlphp/vendor/symfony/http-kernel/HttpCache/HttpCache.php @@ -17,6 +17,7 @@ namespace Symfony\Component\HttpKernel\HttpCache; +use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -725,7 +726,11 @@ private function getTraceKey(Request $request): string $path .= '?'.$qs; } - return $request->getMethod().' '.$path; + try { + return $request->getMethod().' '.$path; + } catch (SuspiciousOperationException $e) { + return '_BAD_METHOD_ '.$path; + } } /** diff --git a/.extlib/simplesamlphp/vendor/symfony/http-kernel/Kernel.php b/.extlib/simplesamlphp/vendor/symfony/http-kernel/Kernel.php index e2e4423b2..e4d06fad6 100644 --- a/.extlib/simplesamlphp/vendor/symfony/http-kernel/Kernel.php +++ b/.extlib/simplesamlphp/vendor/symfony/http-kernel/Kernel.php @@ -76,11 +76,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.4.15'; - public const VERSION_ID = 60415; + public const VERSION = '6.4.16'; + public const VERSION_ID = 60416; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 15; + public const RELEASE_VERSION = 16; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2026'; diff --git a/.extlib/simplesamlphp/vendor/symfony/intl/Resources/bin/compile b/.extlib/simplesamlphp/vendor/symfony/intl/Resources/bin/compile old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/symfony/intl/Resources/bin/compress b/.extlib/simplesamlphp/vendor/symfony/intl/Resources/bin/compress old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CHANGELOG.md b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CHANGELOG.md new file mode 100644 index 000000000..3c7470257 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CHANGELOG.md @@ -0,0 +1,108 @@ +CHANGELOG +========= + +7.2 +--- + + * Add a PHPUnit extension that registers the clock mock and DNS mock and the `DebugClassLoader` from the ErrorHandler component if present + * Add `ExpectUserDeprecationMessageTrait` with a polyfill of PHPUnit's `expectUserDeprecationMessage()` + * Use `total` for asserting deprecation count when a group is not defined + +6.4 +--- + + * Allow setting the locale using `SYMFONY_PHPUNIT_LOCALE` env var + +6.3 +--- + + * Add support for mocking the `enum_exists` function + * Enable reporting of deprecations triggered by Doctrine by default + +6.2 +--- + + * Add support for mocking the `hrtime()` function + +6.1 +--- + + * Add option `ignoreFile` to configure a file that lists deprecation messages to ignore + +6.0 +--- + + * Remove `SetUpTearDownTrait` + +5.3 +--- + + * bumped the minimum PHP version to 7.1.3 + * bumped the minimum PHPUnit version to 7.5 + * deprecated the `SetUpTearDownTrait` trait, use original methods with "void" return typehint. + * added `logFile` option to write deprecations to a file instead of echoing them + +5.1.0 +----- + + * ignore verbosity settings when the build fails because of deprecations + * added per-group verbosity + * added `ExpectDeprecationTrait` to be able to define an expected deprecation from inside a test + * deprecated the `@expectedDeprecation` annotation, use the `ExpectDeprecationTrait::expectDeprecation()` method instead + +5.0.0 +----- + + * removed `weak_vendor` mode, use `max[self]=0` instead + +4.4.0 +----- + + * made the bridge act as a polyfill for newest PHPUnit features + * added `SetUpTearDownTrait` to allow working around the `void` return-type added by PHPUnit 8 + * added namespace aliases for PHPUnit < 6 + +4.3.0 +----- + + * added `ClassExistsMock` + * bumped PHP version from 5.3.3 to 5.5.9 + * split simple-phpunit bin into php file with code and a shell script + +4.1.0 +----- + + * Search for `SYMFONY_PHPUNIT_VERSION`, `SYMFONY_PHPUNIT_REMOVE`, + `SYMFONY_PHPUNIT_DIR` env var in `phpunit.xml` then in `phpunit.xml.dist` + +4.0.0 +----- + + * support for the `testLegacy` prefix in method names to mark a test as legacy + has been dropped, use the `@group legacy` notation instead + * support for the `Legacy` prefix in class names to mark tests as legacy has + been dropped, use the `@group legacy` notation instead + * support for passing an array of mocked namespaces not indexed by the mock + feature to the constructor of the `SymfonyTestsListenerTrait` class was + dropped + +3.4.0 +----- + + * added a `CoverageListener` to enhance the code coverage report + * all deprecations but those from tests marked with `@group legacy` are always + displayed when not in `weak` mode + +3.3.0 +----- + + * using the `testLegacy` prefix in method names to mark a test as legacy is + deprecated, use the `@group legacy` notation instead + * using the `Legacy` prefix in class names to mark a test as legacy is deprecated, + use the `@group legacy` notation instead + +3.1.0 +----- + + * passing a numerically indexed array to the constructor of the `SymfonyTestsListenerTrait` + is deprecated, pass an array of namespaces indexed by the mocked feature instead diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ClassExistsMock.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ClassExistsMock.php new file mode 100644 index 000000000..72ec51e05 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ClassExistsMock.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +/** + * @author Roland Franssen + */ +class ClassExistsMock +{ + private static $classes = []; + + private static $enums = []; + + /** + * Configures the classes to be checked upon existence. + * + * @param array $classes Mocked class names as keys (case-sensitive, without leading root namespace slash) and booleans as values + */ + public static function withMockedClasses(array $classes): void + { + self::$classes = $classes; + } + + /** + * Configures the enums to be checked upon existence. + * + * @param array $enums Mocked enums names as keys (case-sensitive, without leading root namespace slash) and booleans as values + */ + public static function withMockedEnums(array $enums): void + { + self::$enums = $enums; + self::$classes += $enums; + } + + public static function class_exists($name, $autoload = true): bool + { + $name = ltrim($name, '\\'); + + return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \class_exists($name, $autoload); + } + + public static function interface_exists($name, $autoload = true): bool + { + $name = ltrim($name, '\\'); + + return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \interface_exists($name, $autoload); + } + + public static function trait_exists($name, $autoload = true): bool + { + $name = ltrim($name, '\\'); + + return isset(self::$classes[$name]) ? (bool) self::$classes[$name] : \trait_exists($name, $autoload); + } + + public static function enum_exists($name, $autoload = true):bool + { + $name = ltrim($name, '\\'); + + return isset(self::$enums[$name]) ? (bool) self::$enums[$name] : \enum_exists($name, $autoload); + } + + public static function register($class): void + { + $self = static::class; + + $mockedNs = [substr($class, 0, strrpos($class, '\\'))]; + if (0 < strpos($class, '\\Tests\\')) { + $ns = str_replace('\\Tests\\', '\\', $class); + $mockedNs[] = substr($ns, 0, strrpos($ns, '\\')); + } elseif (0 === strpos($class, 'Tests\\')) { + $mockedNs[] = substr($class, 6, strrpos($class, '\\') - 6); + } + foreach ($mockedNs as $ns) { + foreach (['class', 'interface', 'trait', 'enum'] as $type) { + if (\function_exists($ns.'\\'.$type.'_exists')) { + continue; + } + eval(<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +/** + * @author Nicolas Grekas + * @author Dominic Tubach + */ +class ClockMock +{ + private static $now; + + public static function withClockMock($enable = null): ?bool + { + if (null === $enable) { + return null !== self::$now; + } + + self::$now = is_numeric($enable) ? (float) $enable : ($enable ? microtime(true) : null); + + return null; + } + + public static function time(): int + { + if (null === self::$now) { + return \time(); + } + + return (int) self::$now; + } + + public static function sleep($s): int + { + if (null === self::$now) { + return \sleep($s); + } + + self::$now += (int) $s; + + return 0; + } + + public static function usleep($us): void + { + if (null === self::$now) { + \usleep($us); + } else { + self::$now += $us / 1000000; + } + } + + /** + * @return string|float + */ + public static function microtime($asFloat = false) + { + if (null === self::$now) { + return \microtime($asFloat); + } + + if ($asFloat) { + return self::$now; + } + + return \sprintf('%0.6f00 %d', self::$now - (int) self::$now, (int) self::$now); + } + + public static function date($format, $timestamp = null): string + { + if (null === $timestamp) { + $timestamp = self::time(); + } + + return \date($format, $timestamp); + } + + public static function gmdate($format, $timestamp = null): string + { + if (null === $timestamp) { + $timestamp = self::time(); + } + + return \gmdate($format, $timestamp); + } + + /** + * @return array|int|float + */ + public static function hrtime($asNumber = false) + { + $ns = (self::$now - (int) self::$now) * 1000000000; + + if ($asNumber) { + $number = \sprintf('%d%d', (int) self::$now, $ns); + + return \PHP_INT_SIZE === 8 ? (int) $number : (float) $number; + } + + return [(int) self::$now, (int) $ns]; + } + + public static function register($class): void + { + $self = static::class; + + $mockedNs = [substr($class, 0, strrpos($class, '\\'))]; + if (0 < strpos($class, '\\Tests\\')) { + $ns = str_replace('\\Tests\\', '\\', $class); + $mockedNs[] = substr($ns, 0, strrpos($ns, '\\')); + } elseif (0 === strpos($class, 'Tests\\')) { + $mockedNs[] = substr($class, 6, strrpos($class, '\\') - 6); + } + foreach ($mockedNs as $ns) { + if (\function_exists($ns.'\time')) { + continue; + } + eval(<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Framework\Constraint\Constraint; + +$r = new \ReflectionClass(Constraint::class); +if ($r->getProperty('exporter')->isProtected()) { + trait ConstraintTrait + { + use Legacy\ConstraintTraitForV7; + } +} elseif (!$r->getMethod('evaluate')->hasReturnType()) { + trait ConstraintTrait + { + use Legacy\ConstraintTraitForV8; + } +} else { + trait ConstraintTrait + { + use Legacy\ConstraintTraitForV9; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CoverageListener.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CoverageListener.php new file mode 100644 index 000000000..65d6aa9dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/CoverageListener.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestListenerDefaultImplementation; +use PHPUnit\Framework\Warning; +use PHPUnit\Util\Annotation\Registry; +use PHPUnit\Util\Test as TestUtil; + +class CoverageListener implements TestListener +{ + use TestListenerDefaultImplementation; + + private $sutFqcnResolver; + private $warningOnSutNotFound; + + public function __construct(?callable $sutFqcnResolver = null, bool $warningOnSutNotFound = false) + { + $this->sutFqcnResolver = $sutFqcnResolver ?? static function (Test $test): ?string { + $class = \get_class($test); + + $sutFqcn = str_replace('\\Tests\\', '\\', $class); + $sutFqcn = preg_replace('{Test$}', '', $sutFqcn); + + return class_exists($sutFqcn) ? $sutFqcn : null; + }; + + $this->warningOnSutNotFound = $warningOnSutNotFound; + } + + public function startTest(Test $test): void + { + if (!$test instanceof TestCase) { + return; + } + + $annotations = TestUtil::parseTestMethodAnnotations(\get_class($test), $test->getName(false)); + + $ignoredAnnotations = ['covers', 'coversDefaultClass', 'coversNothing']; + + foreach ($ignoredAnnotations as $annotation) { + if (isset($annotations['class'][$annotation]) || isset($annotations['method'][$annotation])) { + return; + } + } + + $sutFqcn = ($this->sutFqcnResolver)($test); + if (!$sutFqcn) { + if ($this->warningOnSutNotFound) { + $test->getTestResultObject()->addWarning($test, new Warning('Could not find the tested class.'), 0); + } + + return; + } + + $covers = $sutFqcn; + if (!\is_array($sutFqcn)) { + $covers = [$sutFqcn]; + while ($parent = get_parent_class($sutFqcn)) { + $covers[] = $parent; + $sutFqcn = $parent; + } + } + + if (class_exists(Registry::class)) { + $this->addCoversForDocBlockInsideRegistry($test, $covers); + + return; + } + + $this->addCoversForClassToAnnotationCache($test, $covers); + } + + private function addCoversForClassToAnnotationCache(Test $test, array $covers): void + { + $r = new \ReflectionProperty(TestUtil::class, 'annotationCache'); + $r->setAccessible(true); + + $cache = $r->getValue(); + $cache = array_replace_recursive($cache, [ + \get_class($test) => [ + 'covers' => $covers, + ], + ]); + + $r->setValue(TestUtil::class, $cache); + } + + private function addCoversForDocBlockInsideRegistry(Test $test, array $covers): void + { + $docBlock = Registry::getInstance()->forClassName(\get_class($test)); + + $symbolAnnotations = new \ReflectionProperty($docBlock, 'symbolAnnotations'); + $symbolAnnotations->setAccessible(true); + + // Exclude internal classes; PHPUnit 9.1+ is picky about tests covering, say, a \RuntimeException + $covers = array_filter($covers, function (string $class) { + $reflector = new \ReflectionClass($class); + + return $reflector->isUserDefined(); + }); + + $symbolAnnotations->setValue($docBlock, array_replace($docBlock->symbolAnnotations(), [ + 'covers' => $covers, + ])); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php new file mode 100644 index 000000000..e59790886 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php @@ -0,0 +1,444 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestResult; +use PHPUnit\Runner\ErrorHandler; +use PHPUnit\Util\Error\Handler; +use PHPUnit\Util\ErrorHandler as UtilErrorHandler; +use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Configuration; +use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation; +use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\DeprecationGroup; +use Symfony\Component\ErrorHandler\DebugClassLoader; + +/** + * Catch deprecation notices and print a summary report at the end of the test suite. + * + * @author Nicolas Grekas + */ +class DeprecationErrorHandler +{ + public const MODE_DISABLED = 'disabled'; + public const MODE_WEAK = 'max[total]=999999&verbose=0'; + public const MODE_STRICT = 'max[total]=0'; + + private $mode; + private $configuration; + + /** + * @var DeprecationGroup[] + */ + private $deprecationGroups = []; + + private static $isRegistered = false; + private static $errorHandler; + + public function __construct() + { + $this->resetDeprecationGroups(); + } + + /** + * Registers and configures the deprecation handler. + * + * The mode is a query string with options: + * - "disabled" to enable/disable the deprecation handler + * - "verbose" to enable/disable displaying the deprecation report + * - "quiet" to disable displaying the deprecation report only for some groups (i.e. quiet[]=other) + * - "max" to configure the number of deprecations to allow before exiting with a non-zero + * status code; it's an array with keys "total", "self", "direct" and "indirect" + * + * The default mode is "max[total]=0&verbose=1". + * + * The mode can alternatively be "/some-regexp/" to stop the test suite whenever + * a deprecation message matches the given regular expression. + * + * @param int|string|false $mode The reporting mode, defaults to not allowing any deprecations + */ + public static function register($mode = 0) + { + if (self::$isRegistered) { + return; + } + + $handler = new self(); + $oldErrorHandler = set_error_handler([$handler, 'handleError']); + + if (null !== $oldErrorHandler) { + restore_error_handler(); + + if ( + $oldErrorHandler instanceof UtilErrorHandler + || [UtilErrorHandler::class, 'handleError'] === $oldErrorHandler + || $oldErrorHandler instanceof ErrorHandler + || [ErrorHandler::class, 'handleError'] === $oldErrorHandler + ) { + restore_error_handler(); + self::register($mode); + } + } else { + $handler->mode = $mode; + self::$isRegistered = true; + register_shutdown_function([$handler, 'shutdown']); + } + } + + public static function collectDeprecations($outputFile) + { + $deprecations = []; + $previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$previousErrorHandler) { + if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || false === strpos($msg, '" targeting switch is equivalent to "break'))) { + if ($previousErrorHandler) { + return $previousErrorHandler($type, $msg, $file, $line, $context); + } + + return \call_user_func(self::getPhpUnitErrorHandler(), $type, $msg, $file, $line, $context); + } + + $filesStack = []; + foreach (debug_backtrace() as $frame) { + if (!isset($frame['file']) || \in_array($frame['function'], ['require', 'require_once', 'include', 'include_once'], true)) { + continue; + } + + $filesStack[] = $frame['file']; + } + + $deprecations[] = [error_reporting() & $type, $msg, $file, $filesStack]; + + return null; + }); + + register_shutdown_function(function () use ($outputFile, &$deprecations) { + file_put_contents($outputFile, serialize($deprecations)); + }); + } + + /** + * @internal + */ + public function handleError($type, $msg, $file, $line, $context = []) + { + if ((\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type && (\E_WARNING !== $type || false === strpos($msg, '" targeting switch is equivalent to "break'))) || !$this->getConfiguration()->isEnabled()) { + return \call_user_func(self::getPhpUnitErrorHandler(), $type, $msg, $file, $line, $context); + } + + $trace = debug_backtrace(); + + if (isset($trace[1]['function'], $trace[1]['args'][0]) && ('trigger_error' === $trace[1]['function'] || 'user_error' === $trace[1]['function'])) { + $msg = $trace[1]['args'][0]; + } + + $deprecation = new Deprecation($msg, $trace, $file, \E_DEPRECATED === $type); + if ($deprecation->isMuted()) { + return null; + } + if ($this->getConfiguration()->isIgnoredDeprecation($deprecation)) { + return null; + } + if ($this->getConfiguration()->isBaselineDeprecation($deprecation)) { + return null; + } + + $msg = $deprecation->getMessage(); + + if (\E_DEPRECATED !== $type && (error_reporting() & $type)) { + $group = 'unsilenced'; + } elseif ($deprecation->isLegacy()) { + $group = 'legacy'; + } else { + $group = [ + Deprecation::TYPE_SELF => 'self', + Deprecation::TYPE_DIRECT => 'direct', + Deprecation::TYPE_INDIRECT => 'indirect', + Deprecation::TYPE_UNDETERMINED => 'other', + ][$deprecation->getType()]; + } + + if ($this->getConfiguration()->shouldDisplayStackTrace($msg)) { + echo "\n".ucfirst($group).' '.$deprecation->toString(); + + exit(1); + } + + if ('legacy' === $group) { + $this->deprecationGroups[$group]->addNotice(); + } elseif ($deprecation->originatesFromAnObject()) { + $class = $deprecation->originatingClass(); + $method = $deprecation->originatingMethod(); + $this->deprecationGroups[$group]->addNoticeFromObject($msg, $class, $method); + } else { + $this->deprecationGroups[$group]->addNoticeFromProceduralCode($msg); + } + + return null; + } + + /** + * @internal + */ + public function shutdown() + { + $configuration = $this->getConfiguration(); + + if ($configuration->isInRegexMode()) { + return; + } + + if (class_exists(DebugClassLoader::class, false)) { + DebugClassLoader::checkClasses(); + } + $currErrorHandler = set_error_handler('is_int'); + restore_error_handler(); + + if ($currErrorHandler !== [$this, 'handleError']) { + echo "\n", self::colorize('THE ERROR HANDLER HAS CHANGED!', true), "\n"; + } + + $groups = array_keys($this->deprecationGroups); + + // store failing status + $isFailing = !$configuration->tolerates($this->deprecationGroups); + + $this->displayDeprecations($groups, $configuration); + + $this->resetDeprecationGroups(); + + register_shutdown_function(function () use ($isFailing, $groups, $configuration) { + foreach ($this->deprecationGroups as $group) { + if ($group->count() > 0) { + echo "Shutdown-time deprecations:\n"; + break; + } + } + + $isFailingAtShutdown = !$configuration->tolerates($this->deprecationGroups); + $this->displayDeprecations($groups, $configuration); + + if ($configuration->isGeneratingBaseline()) { + $configuration->writeBaseline(); + } + + if ($isFailing || $isFailingAtShutdown) { + exit(1); + } + }); + } + + private function resetDeprecationGroups() + { + $this->deprecationGroups = [ + 'unsilenced' => new DeprecationGroup(), + 'self' => new DeprecationGroup(), + 'direct' => new DeprecationGroup(), + 'indirect' => new DeprecationGroup(), + 'legacy' => new DeprecationGroup(), + 'other' => new DeprecationGroup(), + ]; + } + + private function getConfiguration() + { + if (null !== $this->configuration) { + return $this->configuration; + } + if (false === $mode = $this->mode) { + $mode = $_SERVER['SYMFONY_DEPRECATIONS_HELPER'] ?? $_ENV['SYMFONY_DEPRECATIONS_HELPER'] ?? getenv('SYMFONY_DEPRECATIONS_HELPER'); + } + if ('strict' === $mode) { + return $this->configuration = Configuration::inStrictMode(); + } + if (self::MODE_DISABLED === $mode) { + return $this->configuration = Configuration::inDisabledMode(); + } + if ('weak' === $mode) { + return $this->configuration = Configuration::inWeakMode(); + } + if (isset($mode[0]) && '/' === $mode[0]) { + return $this->configuration = Configuration::fromRegex($mode); + } + + if (preg_match('/^[1-9][0-9]*$/', (string) $mode)) { + return $this->configuration = Configuration::fromNumber($mode); + } + + if (!$mode) { + return $this->configuration = Configuration::fromNumber(0); + } + + return $this->configuration = Configuration::fromUrlEncodedString((string) $mode); + } + + private static function colorize(string $str, bool $red): string + { + if (!self::hasColorSupport()) { + return $str; + } + + $color = $red ? '41;37' : '43;30'; + + return "\x1B[{$color}m{$str}\x1B[0m"; + } + + /** + * @param string[] $groups + */ + private function displayDeprecations(array $groups, Configuration $configuration): void + { + $cmp = function ($a, $b) { + return $b->count() - $a->count(); + }; + + if ($configuration->shouldWriteToLogFile()) { + if (false === $handle = @fopen($file = $configuration->getLogFile(), 'a')) { + throw new \InvalidArgumentException(\sprintf('The configured log file "%s" is not writeable.', $file)); + } + } else { + $handle = fopen('php://output', 'w'); + } + + foreach ($groups as $group) { + if ($this->deprecationGroups[$group]->count()) { + $deprecationGroupMessage = \sprintf( + '%s deprecation notices (%d)', + \in_array($group, ['direct', 'indirect', 'self'], true) ? "Remaining $group" : ucfirst($group), + $this->deprecationGroups[$group]->count() + ); + if ($configuration->shouldWriteToLogFile()) { + fwrite($handle, "\n$deprecationGroupMessage\n"); + } else { + fwrite($handle, "\n".self::colorize($deprecationGroupMessage, 'legacy' !== $group && 'indirect' !== $group)."\n"); + } + + // Skip the verbose output if the group is quiet and not failing according to its threshold: + if ('legacy' !== $group && !$configuration->verboseOutput($group) && $configuration->toleratesForGroup($group, $this->deprecationGroups)) { + continue; + } + $notices = $this->deprecationGroups[$group]->notices(); + uasort($notices, $cmp); + + foreach ($notices as $msg => $notice) { + fwrite($handle, \sprintf("\n %sx: %s\n", $notice->count(), $msg)); + + $countsByCaller = $notice->getCountsByCaller(); + arsort($countsByCaller); + $limit = 5; + + foreach ($countsByCaller as $method => $count) { + if ('count' !== $method) { + if (!$limit--) { + fwrite($handle, " ...\n"); + break; + } + fwrite($handle, \sprintf(" %dx in %s\n", $count, preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method))); + } + } + } + } + } + + if (!empty($notices)) { + fwrite($handle, "\n"); + } + } + + private static function getPhpUnitErrorHandler(): callable + { + if (!$eh = self::$errorHandler) { + if (class_exists(Handler::class)) { + $eh = self::$errorHandler = Handler::class; + } elseif (method_exists(UtilErrorHandler::class, '__invoke')) { + $eh = self::$errorHandler = UtilErrorHandler::class; + } elseif (method_exists(ErrorHandler::class, '__invoke')) { + $eh = self::$errorHandler = ErrorHandler::class; + } else { + return self::$errorHandler = 'PHPUnit\Util\ErrorHandler::handleError'; + } + } + + if ('PHPUnit\Util\ErrorHandler::handleError' === $eh) { + return $eh; + } + + foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { + if (!isset($frame['object'])) { + continue; + } + + if ($frame['object'] instanceof TestResult) { + return new $eh( + $frame['object']->getConvertDeprecationsToExceptions(), + $frame['object']->getConvertErrorsToExceptions(), + $frame['object']->getConvertNoticesToExceptions(), + $frame['object']->getConvertWarningsToExceptions() + ); + } elseif (ErrorHandler::class === $eh && $frame['object'] instanceof TestCase) { + return function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) { + ErrorHandler::instance()($errorNumber, $errorString, $errorFile, $errorLine); + + return true; + }; + } + } + + return function () { return false; }; + } + + /** + * Returns true if STDOUT is defined and supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + */ + private static function hasColorSupport(): bool + { + if (!\defined('STDOUT')) { + return false; + } + + // Follow https://no-color.org/ + if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) { + return false; + } + + // Follow https://force-color.org/ + if ('' !== (($_SERVER['FORCE_COLOR'] ?? getenv('FORCE_COLOR'))[0] ?? '')) { + return true; + } + + // Detect msysgit/mingw and assume this is a tty because detection + // does not work correctly, see https://github.com/composer/composer/issues/9690 + if (!@stream_isatty(\STDOUT) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support(\STDOUT)) { + return true; + } + + if ('Hyper' === getenv('TERM_PROGRAM') + || false !== getenv('COLORTERM') + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + ) { + return true; + } + + if ('dumb' === $term = (string) getenv('TERM')) { + return false; + } + + // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157 + return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Configuration.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Configuration.php new file mode 100644 index 000000000..c984b73d7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Configuration.php @@ -0,0 +1,388 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler; + +/** + * @internal + */ +class Configuration +{ + /** + * @var int[] + */ + private $thresholds; + + /** + * @var string + */ + private $regex; + + /** + * @var bool + */ + private $enabled = true; + + /** + * @var bool[] + */ + private $verboseOutput; + + /** + * @var string[] + */ + private $ignoreDeprecationPatterns = []; + + /** + * @var bool + */ + private $generateBaseline = false; + + /** + * @var string + */ + private $baselineFile = ''; + + /** + * @var array + */ + private $baselineDeprecations = []; + + /** + * @var string|null + */ + private $logFile; + + /** + * @param int[] $thresholds A hash associating groups to thresholds + * @param string $regex Will be matched against messages, to decide whether to display a stack trace + * @param bool[] $verboseOutput Keyed by groups + * @param string $ignoreFile The path to the ignore deprecation patterns file + * @param bool $generateBaseline Whether to generate or update the baseline file + * @param string $baselineFile The path to the baseline file + * @param string|null $logFile The path to the log file + */ + private function __construct(array $thresholds = [], string $regex = '', array $verboseOutput = [], string $ignoreFile = '', bool $generateBaseline = false, string $baselineFile = '', ?string $logFile = null) + { + $groups = ['total', 'indirect', 'direct', 'self']; + + foreach ($thresholds as $group => $threshold) { + if (!\in_array($group, $groups, true)) { + throw new \InvalidArgumentException(\sprintf('Unrecognized threshold "%s", expected one of "%s".', $group, implode('", "', $groups))); + } + if (!is_numeric($threshold)) { + throw new \InvalidArgumentException(\sprintf('Threshold for group "%s" has invalid value "%s".', $group, $threshold)); + } + $this->thresholds[$group] = (int) $threshold; + } + if (isset($this->thresholds['direct'])) { + $this->thresholds += [ + 'self' => $this->thresholds['direct'], + ]; + } + if (isset($this->thresholds['indirect'])) { + $this->thresholds += [ + 'direct' => $this->thresholds['indirect'], + 'self' => $this->thresholds['indirect'], + ]; + } + foreach ($groups as $group) { + if (!isset($this->thresholds[$group])) { + $this->thresholds[$group] = $this->thresholds['total'] ?? 999999; + } + } + $this->regex = $regex; + + $this->verboseOutput = [ + 'unsilenced' => true, + 'direct' => true, + 'indirect' => true, + 'self' => true, + 'other' => true, + ]; + + foreach ($verboseOutput as $group => $status) { + if (!isset($this->verboseOutput[$group])) { + throw new \InvalidArgumentException(\sprintf('Unsupported verbosity group "%s", expected one of "%s".', $group, implode('", "', array_keys($this->verboseOutput)))); + } + $this->verboseOutput[$group] = $status; + } + + if ($ignoreFile) { + if (!is_file($ignoreFile)) { + throw new \InvalidArgumentException(\sprintf('The ignoreFile "%s" does not exist.', $ignoreFile)); + } + set_error_handler(static function ($t, $m) use ($ignoreFile, &$line) { + throw new \RuntimeException(\sprintf('Invalid pattern found in "%s" on line "%d"', $ignoreFile, 1 + $line).substr($m, 12)); + }); + try { + foreach (file($ignoreFile) as $line => $pattern) { + if ('#' !== (trim($pattern)[0] ?? '#')) { + preg_match($pattern, ''); + $this->ignoreDeprecationPatterns[] = $pattern; + } + } + } finally { + restore_error_handler(); + } + } + + if ($generateBaseline && !$baselineFile) { + throw new \InvalidArgumentException('You cannot use the "generateBaseline" configuration option without providing a "baselineFile" configuration option.'); + } + $this->generateBaseline = $generateBaseline; + $this->baselineFile = $baselineFile; + if ($this->baselineFile && !$this->generateBaseline) { + if (is_file($this->baselineFile)) { + $map = json_decode(file_get_contents($this->baselineFile)); + foreach ($map as $baseline_deprecation) { + $this->baselineDeprecations[$baseline_deprecation->location][$baseline_deprecation->message] = $baseline_deprecation->count; + } + } else { + throw new \InvalidArgumentException(\sprintf('The baselineFile "%s" does not exist.', $this->baselineFile)); + } + } + + $this->logFile = $logFile; + } + + public function isEnabled(): bool + { + return $this->enabled; + } + + /** + * @param DeprecationGroup[] $deprecationGroups + */ + public function tolerates(array $deprecationGroups): bool + { + $grandTotal = 0; + + foreach ($deprecationGroups as $name => $group) { + if ('legacy' !== $name) { + $grandTotal += $group->count(); + } + } + + if ($grandTotal > $this->thresholds['total']) { + return false; + } + + foreach (['self', 'direct', 'indirect'] as $deprecationType) { + if ($deprecationGroups[$deprecationType]->count() > $this->thresholds[$deprecationType]) { + return false; + } + } + + return true; + } + + public function isIgnoredDeprecation(Deprecation $deprecation): bool + { + if (!$this->ignoreDeprecationPatterns) { + return false; + } + $result = @preg_filter($this->ignoreDeprecationPatterns, '$0', $deprecation->getMessage()); + if (\PREG_NO_ERROR !== preg_last_error()) { + throw new \RuntimeException(preg_last_error_msg()); + } + + return (bool) $result; + } + + /** + * @param array $deprecationGroups + * + * @return bool true if the threshold is not reached for the deprecation type nor for the total + */ + public function toleratesForGroup(string $groupName, array $deprecationGroups): bool + { + $grandTotal = 0; + + foreach ($deprecationGroups as $type => $group) { + if ('legacy' !== $type) { + $grandTotal += $group->count(); + } + } + + if ($grandTotal > $this->thresholds['total']) { + return false; + } + + if (\in_array($groupName, ['self', 'direct', 'indirect'], true) && $deprecationGroups[$groupName]->count() > $this->thresholds[$groupName]) { + return false; + } + + return true; + } + + public function isBaselineDeprecation(Deprecation $deprecation): bool + { + if ($deprecation->isLegacy()) { + return false; + } + + if ($deprecation->originatesFromDebugClassLoader()) { + $location = $deprecation->triggeringClass(); + } elseif ($deprecation->originatesFromAnObject()) { + $location = $deprecation->originatingClass().'::'.$deprecation->originatingMethod(); + } else { + $location = 'procedural code'; + } + + $message = $deprecation->getMessage(); + $result = isset($this->baselineDeprecations[$location][$message]) && $this->baselineDeprecations[$location][$message] > 0; + if ($this->generateBaseline) { + if ($result) { + ++$this->baselineDeprecations[$location][$message]; + } else { + $this->baselineDeprecations[$location][$message] = 1; + $result = true; + } + } elseif ($result) { + --$this->baselineDeprecations[$location][$message]; + } + + return $result; + } + + public function isGeneratingBaseline(): bool + { + return $this->generateBaseline; + } + + public function getBaselineFile(): string + { + return $this->baselineFile; + } + + public function writeBaseline(): void + { + $map = []; + foreach ($this->baselineDeprecations as $location => $messages) { + foreach ($messages as $message => $count) { + $map[] = [ + 'location' => $location, + 'message' => $message, + 'count' => $count, + ]; + } + } + file_put_contents($this->baselineFile, json_encode($map, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); + } + + public function shouldDisplayStackTrace(string $message): bool + { + return '' !== $this->regex && preg_match($this->regex, $message); + } + + public function isInRegexMode(): bool + { + return '' !== $this->regex; + } + + public function verboseOutput($group): bool + { + return $this->verboseOutput[$group]; + } + + public function shouldWriteToLogFile(): bool + { + return null !== $this->logFile; + } + + public function getLogFile(): ?string + { + return $this->logFile; + } + + /** + * @param string $serializedConfiguration An encoded string, for instance max[total]=1234&max[indirect]=42 + */ + public static function fromUrlEncodedString(string $serializedConfiguration): self + { + parse_str($serializedConfiguration, $normalizedConfiguration); + foreach (array_keys($normalizedConfiguration) as $key) { + if (!\in_array($key, ['max', 'disabled', 'verbose', 'quiet', 'ignoreFile', 'generateBaseline', 'baselineFile', 'logFile'], true)) { + throw new \InvalidArgumentException(\sprintf('Unknown configuration option "%s".', $key)); + } + } + + $normalizedConfiguration += [ + 'max' => ['total' => 0], + 'disabled' => false, + 'verbose' => true, + 'quiet' => [], + 'ignoreFile' => '', + 'generateBaseline' => false, + 'baselineFile' => '', + 'logFile' => null, + ]; + + if ('' === $normalizedConfiguration['disabled'] || filter_var($normalizedConfiguration['disabled'], \FILTER_VALIDATE_BOOLEAN)) { + return self::inDisabledMode(); + } + + $verboseOutput = []; + foreach (['unsilenced', 'direct', 'indirect', 'self', 'other'] as $group) { + $verboseOutput[$group] = filter_var($normalizedConfiguration['verbose'], \FILTER_VALIDATE_BOOLEAN); + } + + if (\is_array($normalizedConfiguration['quiet'])) { + foreach ($normalizedConfiguration['quiet'] as $shushedGroup) { + $verboseOutput[$shushedGroup] = false; + } + } + + return new self( + $normalizedConfiguration['max'], + '', + $verboseOutput, + $normalizedConfiguration['ignoreFile'], + filter_var($normalizedConfiguration['generateBaseline'], \FILTER_VALIDATE_BOOLEAN), + $normalizedConfiguration['baselineFile'], + $normalizedConfiguration['logFile'] + ); + } + + public static function inDisabledMode(): self + { + $configuration = new self(); + $configuration->enabled = false; + + return $configuration; + } + + public static function inStrictMode(): self + { + return new self(['total' => 0]); + } + + public static function inWeakMode(): self + { + $verboseOutput = []; + foreach (['unsilenced', 'direct', 'indirect', 'self', 'other'] as $group) { + $verboseOutput[$group] = false; + } + + return new self([], '', $verboseOutput); + } + + public static function fromNumber($upperBound): self + { + return new self(['total' => $upperBound]); + } + + public static function fromRegex($regex): self + { + return new self([], $regex); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Deprecation.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Deprecation.php new file mode 100644 index 000000000..822e9800b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/Deprecation.php @@ -0,0 +1,400 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler; + +use Doctrine\Deprecations\Deprecation as DoctrineDeprecation; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Metadata\Api\Groups; +use PHPUnit\Util\Test; +use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor; +use Symfony\Component\ErrorHandler\DebugClassLoader; + +class_exists(Groups::class); + +/** + * @internal + */ +class Deprecation +{ + public const PATH_TYPE_VENDOR = 'path_type_vendor'; + public const PATH_TYPE_SELF = 'path_type_internal'; + public const PATH_TYPE_UNDETERMINED = 'path_type_undetermined'; + + public const TYPE_SELF = 'type_self'; + public const TYPE_DIRECT = 'type_direct'; + public const TYPE_INDIRECT = 'type_indirect'; + public const TYPE_UNDETERMINED = 'type_undetermined'; + + private $trace = []; + private $message; + private $languageDeprecation; + private $originClass; + private $originMethod; + private $triggeringFile; + private $triggeringClass; + + /** @var string[] Absolute paths to vendor directories */ + private static $vendors; + + /** + * @var string[] Absolute paths to source or tests of the project, cache + * directories excluded because it is based on autoloading + * rules and cache systems typically do not use those + */ + private static $internalPaths = []; + + private $originalFilesStack; + + public function __construct(string $message, array $trace, string $file, bool $languageDeprecation = false) + { + if (DebugClassLoader::class === ($trace[2]['class'] ?? '')) { + $this->triggeringClass = $trace[2]['args'][0]; + } + + switch ($trace[2]['function'] ?? '') { + case 'trigger_deprecation': + $file = $trace[2]['file']; + array_splice($trace, 1, 1); + break; + + case 'delegateTriggerToBackend': + if (DoctrineDeprecation::class === ($trace[2]['class'] ?? '')) { + $file = $trace[3]['file']; + array_splice($trace, 1, 2); + } + break; + } + + $this->trace = $trace; + $this->message = $message; + $this->languageDeprecation = $languageDeprecation; + + $i = \count($trace); + while (1 < $i && $this->lineShouldBeSkipped($trace[--$i])) { + // No-op + } + + $line = $trace[$i]; + $this->triggeringFile = $file; + + for ($j = 1; $j < $i; ++$j) { + if (!isset($trace[$j]['function'], $trace[1 + $j]['class'], $trace[1 + $j]['args'][0])) { + continue; + } + + if ('trigger_error' === $trace[$j]['function'] && !isset($trace[$j]['class'])) { + if (DebugClassLoader::class === $trace[1 + $j]['class']) { + $class = $trace[1 + $j]['args'][0]; + $this->triggeringFile = isset($trace[1 + $j]['args'][1]) ? realpath($trace[1 + $j]['args'][1]) : (new \ReflectionClass($class))->getFileName(); + $this->getOriginalFilesStack(); + array_splice($this->originalFilesStack, 0, $j, [$this->triggeringFile]); + + if (preg_match('/(?|"([^"]++)" that is deprecated|should implement method "(?:static )?([^:]++))/', $message, $m) || (false === strpos($message, '()" will return') && false === strpos($message, 'native return type declaration') && preg_match('/^(?:The|Method) "([^":]++)/', $message, $m))) { + $this->triggeringFile = (new \ReflectionClass($m[1]))->getFileName(); + array_unshift($this->originalFilesStack, $this->triggeringFile); + } + } + + break; + } + } + + if (!isset($line['object']) && !isset($line['class'])) { + return; + } + + set_error_handler(function () {}); + try { + $parsedMsg = unserialize($this->message); + } finally { + restore_error_handler(); + } + if ($parsedMsg && isset($parsedMsg['deprecation'])) { + $this->message = $parsedMsg['deprecation']; + $this->originClass = $parsedMsg['class']; + $this->originMethod = $parsedMsg['method']; + if (isset($parsedMsg['files_stack'])) { + $this->originalFilesStack = $parsedMsg['files_stack']; + } + // If the deprecation has been triggered via + // \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest() + // then we need to use the serialized information to determine + // if the error has been triggered from vendor code. + if (isset($parsedMsg['triggering_file'])) { + $this->triggeringFile = $parsedMsg['triggering_file']; + } + + return; + } + + if (!isset($line['class'], $trace[$i - 2]['function']) || 0 !== strpos($line['class'], SymfonyTestsListenerFor::class)) { + $this->originClass = isset($line['object']) ? \get_class($line['object']) : $line['class']; + $this->originMethod = $line['function']; + + return; + } + + $test = $line['args'][0] ?? null; + + if (($test instanceof TestCase || $test instanceof TestSuite) && ('trigger_error' !== $trace[$i - 2]['function'] || isset($trace[$i - 2]['class']))) { + $this->originClass = \get_class($test); + $this->originMethod = $test->getName(); + } + } + + private function lineShouldBeSkipped(array $line): bool + { + if (!isset($line['class'])) { + return true; + } + $class = $line['class']; + + return 'ReflectionMethod' === $class || 0 === strpos($class, 'PHPUnit\\'); + } + + public function originatesFromDebugClassLoader(): bool + { + return isset($this->triggeringClass); + } + + public function triggeringClass(): string + { + if (null === $this->triggeringClass) { + throw new \LogicException('Check with originatesFromDebugClassLoader() before calling this method.'); + } + + return $this->triggeringClass; + } + + public function originatesFromAnObject(): bool + { + return isset($this->originClass); + } + + public function originatingClass(): string + { + if (null === $this->originClass) { + throw new \LogicException('Check with originatesFromAnObject() before calling this method.'); + } + + $class = $this->originClass; + + return false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; + } + + public function originatingMethod(): string + { + if (null === $this->originMethod) { + throw new \LogicException('Check with originatesFromAnObject() before calling this method.'); + } + + return $this->originMethod; + } + + public function getMessage(): string + { + return $this->message; + } + + public function isLegacy(): bool + { + if (!$this->originClass || (new \ReflectionClass($this->originClass))->isInternal()) { + return false; + } + + $method = $this->originatingMethod(); + $groups = class_exists(Groups::class, false) ? [new Groups(), 'groups'] : [Test::class, 'getGroups']; + + return 0 === strpos($method, 'testLegacy') + || 0 === strpos($method, 'provideLegacy') + || 0 === strpos($method, 'getLegacy') + || strpos($this->originClass, '\Legacy') + || \in_array('legacy', $groups($this->originClass, $method), true); + } + + public function isMuted(): bool + { + if ('Function ReflectionType::__toString() is deprecated' !== $this->message) { + return false; + } + if (isset($this->trace[1]['class'])) { + return 0 === strpos($this->trace[1]['class'], 'PHPUnit\\'); + } + + return false !== strpos($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR); + } + + /** + * Tells whether both the calling package and the called package are vendor + * packages. + */ + public function getType(): string + { + $pathType = $this->getPathType($this->triggeringFile); + if ($this->languageDeprecation && self::PATH_TYPE_VENDOR === $pathType) { + // the triggering file must be used for language deprecations + return self::TYPE_INDIRECT; + } + if (self::PATH_TYPE_SELF === $pathType) { + return self::TYPE_SELF; + } + if (self::PATH_TYPE_UNDETERMINED === $pathType) { + return self::TYPE_UNDETERMINED; + } + $erroringFile = $erroringPackage = null; + + foreach ($this->getOriginalFilesStack() as $file) { + if ('-' === $file || 'Standard input code' === $file || !realpath($file)) { + continue; + } + if (self::PATH_TYPE_SELF === $pathType = $this->getPathType($file)) { + return self::TYPE_DIRECT; + } + if (self::PATH_TYPE_UNDETERMINED === $pathType) { + return self::TYPE_UNDETERMINED; + } + if (null !== $erroringFile && null !== $erroringPackage) { + $package = $this->getPackage($file); + if ('composer' !== $package && $package !== $erroringPackage) { + return self::TYPE_INDIRECT; + } + continue; + } + $erroringFile = $file; + $erroringPackage = $this->getPackage($file); + } + + return self::TYPE_DIRECT; + } + + private function getOriginalFilesStack() + { + if (null === $this->originalFilesStack) { + $this->originalFilesStack = []; + foreach ($this->trace as $frame) { + if (!isset($frame['file'], $frame['function']) || (!isset($frame['class']) && \in_array($frame['function'], ['require', 'require_once', 'include', 'include_once'], true))) { + continue; + } + + $this->originalFilesStack[] = $frame['file']; + } + } + + return $this->originalFilesStack; + } + + /** + * getPathType() should always be called prior to calling this method. + */ + private function getPackage(string $path): string + { + $path = realpath($path) ?: $path; + foreach (self::getVendors() as $vendorRoot) { + if (0 === strpos($path, $vendorRoot)) { + $relativePath = substr($path, \strlen($vendorRoot) + 1); + $vendor = strstr($relativePath, \DIRECTORY_SEPARATOR, true); + if (false === $vendor) { + return 'symfony'; + } + + return rtrim($vendor.'/'.strstr(substr($relativePath, \strlen($vendor) + 1), \DIRECTORY_SEPARATOR, true), '/'); + } + } + + throw new \RuntimeException(\sprintf('No vendors found for path "%s".', $path)); + } + + /** + * @return string[] + */ + private static function getVendors(): array + { + if (null === self::$vendors) { + self::$vendors = $paths = []; + self::$vendors[] = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Legacy'; + if (class_exists(DebugClassLoader::class, false)) { + self::$vendors[] = \dirname((new \ReflectionClass(DebugClassLoader::class))->getFileName()); + } + foreach (get_declared_classes() as $class) { + if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $v = \dirname($r->getFileName(), 2); + if (file_exists($v.'/composer/installed.json')) { + self::$vendors[] = $v; + $loader = require $v.'/autoload.php'; + $paths = self::addSourcePathsFromPrefixes( + array_merge($loader->getPrefixes(), $loader->getPrefixesPsr4()), + $paths + ); + } + } + } + foreach ($paths as $path) { + foreach (self::$vendors as $vendor) { + if (0 !== strpos($path, $vendor)) { + self::$internalPaths[] = $path; + } + } + } + } + + return self::$vendors; + } + + private static function addSourcePathsFromPrefixes(array $prefixesByNamespace, array $paths): array + { + foreach ($prefixesByNamespace as $prefixes) { + foreach ($prefixes as $prefix) { + if (false !== realpath($prefix)) { + $paths[] = realpath($prefix); + } + } + } + + return $paths; + } + + private function getPathType(string $path): string + { + $realPath = realpath($path); + if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) { + return self::PATH_TYPE_UNDETERMINED; + } + foreach (self::getVendors() as $vendor) { + if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { + return self::PATH_TYPE_VENDOR; + } + } + + foreach (self::$internalPaths as $internalPath) { + if (0 === strpos($realPath, $internalPath)) { + return self::PATH_TYPE_SELF; + } + } + + return self::PATH_TYPE_UNDETERMINED; + } + + public function toString(): string + { + $exception = new \Exception($this->message); + $reflection = new \ReflectionProperty($exception, 'trace'); + $reflection->setAccessible(true); + $reflection->setValue($exception, $this->trace); + + return ($this->originatesFromAnObject() ? 'deprecation triggered by '.$this->originatingClass().'::'.$this->originatingMethod().":\n" : '') + .$this->message."\n" + ."Stack trace:\n" + .str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $exception->getTraceAsString())."\n"; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationGroup.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationGroup.php new file mode 100644 index 000000000..cc4b9c046 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationGroup.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler; + +/** + * @internal + */ +final class DeprecationGroup +{ + private $count = 0; + + /** + * @var DeprecationNotice[] keys are messages + */ + private $deprecationNotices = []; + + public function addNoticeFromObject(string $message, string $class, string $method): void + { + $this->deprecationNotice($message)->addObjectOccurrence($class, $method); + $this->addNotice(); + } + + public function addNoticeFromProceduralCode(string $message): void + { + $this->deprecationNotice($message)->addProceduralOccurrence(); + $this->addNotice(); + } + + public function addNotice() + { + ++$this->count; + } + + private function deprecationNotice(string $message): DeprecationNotice + { + return $this->deprecationNotices[$message] ?? $this->deprecationNotices[$message] = new DeprecationNotice(); + } + + public function count(): int + { + return $this->count; + } + + public function notices(): array + { + return $this->deprecationNotices; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationNotice.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationNotice.php new file mode 100644 index 000000000..7cb77b892 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DeprecationErrorHandler/DeprecationNotice.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler; + +/** + * @internal + */ +final class DeprecationNotice +{ + private $count = 0; + + /** + * @var int[] + */ + private $countsByCaller = []; + + public function addObjectOccurrence($class, $method) + { + if (!isset($this->countsByCaller["$class::$method"])) { + $this->countsByCaller["$class::$method"] = 0; + } + ++$this->countsByCaller["$class::$method"]; + ++$this->count; + } + + public function addProceduralOccurrence() + { + ++$this->count; + } + + public function getCountsByCaller(): array + { + return $this->countsByCaller; + } + + public function count(): int + { + return $this->count; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DnsMock.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DnsMock.php new file mode 100644 index 000000000..c558cd0be --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/DnsMock.php @@ -0,0 +1,226 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +/** + * @author Nicolas Grekas + */ +class DnsMock +{ + private static $hosts = []; + private static $dnsTypes = [ + 'A' => \DNS_A, + 'MX' => \DNS_MX, + 'NS' => \DNS_NS, + 'SOA' => \DNS_SOA, + 'PTR' => \DNS_PTR, + 'CNAME' => \DNS_CNAME, + 'AAAA' => \DNS_AAAA, + 'A6' => \DNS_A6, + 'SRV' => \DNS_SRV, + 'NAPTR' => \DNS_NAPTR, + 'TXT' => \DNS_TXT, + 'HINFO' => \DNS_HINFO, + ]; + + /** + * Configures the mock values for DNS queries. + * + * @param array $hosts Mocked hosts as keys, arrays of DNS records as returned by dns_get_record() as values + */ + public static function withMockedHosts(array $hosts): void + { + self::$hosts = $hosts; + } + + public static function checkdnsrr($hostname, $type = 'MX'): bool + { + if (!self::$hosts) { + return \checkdnsrr($hostname, $type); + } + if (isset(self::$hosts[$hostname])) { + $type = strtoupper($type); + + foreach (self::$hosts[$hostname] as $record) { + if ($record['type'] === $type) { + return true; + } + if ('ANY' === $type && isset(self::$dnsTypes[$record['type']]) && 'HINFO' !== $record['type']) { + return true; + } + } + } + + return false; + } + + public static function getmxrr($hostname, &$mxhosts, &$weight = null): bool + { + if (!self::$hosts) { + return \getmxrr($hostname, $mxhosts, $weight); + } + $mxhosts = $weight = []; + + if (isset(self::$hosts[$hostname])) { + foreach (self::$hosts[$hostname] as $record) { + if ('MX' === $record['type']) { + $mxhosts[] = $record['host']; + $weight[] = $record['pri']; + } + } + } + + return (bool) $mxhosts; + } + + public static function gethostbyaddr($ipAddress) + { + if (!self::$hosts) { + return \gethostbyaddr($ipAddress); + } + foreach (self::$hosts as $hostname => $records) { + foreach ($records as $record) { + if ('A' === $record['type'] && $ipAddress === $record['ip']) { + return $hostname; + } + if ('AAAA' === $record['type'] && $ipAddress === $record['ipv6']) { + return $hostname; + } + } + } + + return $ipAddress; + } + + public static function gethostbyname($hostname) + { + if (!self::$hosts) { + return \gethostbyname($hostname); + } + if (isset(self::$hosts[$hostname])) { + foreach (self::$hosts[$hostname] as $record) { + if ('A' === $record['type']) { + return $record['ip']; + } + } + } + + return $hostname; + } + + public static function gethostbynamel($hostname) + { + if (!self::$hosts) { + return \gethostbynamel($hostname); + } + $ips = false; + + if (isset(self::$hosts[$hostname])) { + $ips = []; + + foreach (self::$hosts[$hostname] as $record) { + if ('A' === $record['type']) { + $ips[] = $record['ip']; + } + } + } + + return $ips; + } + + public static function dns_get_record($hostname, $type = \DNS_ANY, &$authns = null, &$addtl = null, $raw = false) + { + if (!self::$hosts) { + return \dns_get_record($hostname, $type, $authns, $addtl, $raw); + } + + $records = false; + + if (isset(self::$hosts[$hostname])) { + if (\DNS_ANY === $type) { + $type = \DNS_ALL; + } + $records = []; + + foreach (self::$hosts[$hostname] as $record) { + if ((self::$dnsTypes[$record['type']] ?? 0) & $type) { + $records[] = array_merge(['host' => $hostname, 'class' => 'IN', 'ttl' => 1, 'type' => $record['type']], $record); + } + } + } + + return $records; + } + + public static function register($class): void + { + $self = static::class; + + $mockedNs = [substr($class, 0, strrpos($class, '\\'))]; + if (0 < strpos($class, '\\Tests\\')) { + $ns = str_replace('\\Tests\\', '\\', $class); + $mockedNs[] = substr($ns, 0, strrpos($ns, '\\')); + } elseif (0 === strpos($class, 'Tests\\')) { + $mockedNs[] = substr($class, 6, strrpos($class, '\\') - 6); + } + foreach ($mockedNs as $ns) { + if (\function_exists($ns.'\checkdnsrr')) { + continue; + } + eval(<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use Symfony\Bridge\PhpUnit\Legacy\ExpectDeprecationTraitBeforeV8_4; +use Symfony\Bridge\PhpUnit\Legacy\ExpectDeprecationTraitForV8_4; + +if (version_compare(\PHPUnit\Runner\Version::id(), '8.4.0', '<')) { + trait ExpectDeprecationTrait + { + use ExpectDeprecationTraitBeforeV8_4; + } +} else { + /** + * @method void expectDeprecation(string $message) + */ + trait ExpectDeprecationTrait + { + use ExpectDeprecationTraitForV8_4; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ExpectUserDeprecationMessageTrait.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ExpectUserDeprecationMessageTrait.php new file mode 100644 index 000000000..ed94c84f2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/ExpectUserDeprecationMessageTrait.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Runner\Version; + +if (version_compare(Version::id(), '11.0.0', '<')) { + trait ExpectUserDeprecationMessageTrait + { + use ExpectDeprecationTrait; + + final protected function expectUserDeprecationMessage(string $expectedUserDeprecationMessage): void + { + $this->expectDeprecation(str_replace('%', '%%', $expectedUserDeprecationMessage)); + } + } +} else { + trait ExpectUserDeprecationMessageTrait + { + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableClockMockSubscriber.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableClockMockSubscriber.php new file mode 100644 index 000000000..885e6ea58 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableClockMockSubscriber.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 Symfony\Bridge\PhpUnit\Extension; + +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; +use PHPUnit\Metadata\Group; +use Symfony\Bridge\PhpUnit\ClockMock; + +/** + * @internal + */ +class DisableClockMockSubscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $test = $event->test(); + + if (!$test instanceof TestMethod) { + return; + } + + foreach ($test->metadata() as $metadata) { + if ($metadata instanceof Group && 'time-sensitive' === $metadata->groupName()) { + ClockMock::withClockMock(false); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableDnsMockSubscriber.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableDnsMockSubscriber.php new file mode 100644 index 000000000..fc3e754d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/DisableDnsMockSubscriber.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 Symfony\Bridge\PhpUnit\Extension; + +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Test\Finished; +use PHPUnit\Event\Test\FinishedSubscriber; +use PHPUnit\Metadata\Group; +use Symfony\Bridge\PhpUnit\DnsMock; + +/** + * @internal + */ +class DisableDnsMockSubscriber implements FinishedSubscriber +{ + public function notify(Finished $event): void + { + $test = $event->test(); + + if (!$test instanceof TestMethod) { + return; + } + + foreach ($test->metadata() as $metadata) { + if ($metadata instanceof Group && 'dns-sensitive' === $metadata->groupName()) { + DnsMock::withMockedHosts([]); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/EnableClockMockSubscriber.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/EnableClockMockSubscriber.php new file mode 100644 index 000000000..c10c5dcd1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/EnableClockMockSubscriber.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 Symfony\Bridge\PhpUnit\Extension; + +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\Test\PreparationStarted; +use PHPUnit\Event\Test\PreparationStartedSubscriber; +use PHPUnit\Metadata\Group; +use Symfony\Bridge\PhpUnit\ClockMock; + +/** + * @internal + */ +class EnableClockMockSubscriber implements PreparationStartedSubscriber +{ + public function notify(PreparationStarted $event): void + { + $test = $event->test(); + + if (!$test instanceof TestMethod) { + return; + } + + foreach ($test->metadata() as $metadata) { + if ($metadata instanceof Group && 'time-sensitive' === $metadata->groupName()) { + ClockMock::withClockMock(true); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterClockMockSubscriber.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterClockMockSubscriber.php new file mode 100644 index 000000000..e2955fe60 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterClockMockSubscriber.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 Symfony\Bridge\PhpUnit\Extension; + +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\TestSuite\Loaded; +use PHPUnit\Event\TestSuite\LoadedSubscriber; +use PHPUnit\Metadata\Group; +use Symfony\Bridge\PhpUnit\ClockMock; + +/** + * @internal + */ +class RegisterClockMockSubscriber implements LoadedSubscriber +{ + public function notify(Loaded $event): void + { + foreach ($event->testSuite()->tests() as $test) { + if (!$test instanceof TestMethod) { + continue; + } + + foreach ($test->metadata() as $metadata) { + if ($metadata instanceof Group && 'time-sensitive' === $metadata->groupName()) { + ClockMock::register($test->className()); + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterDnsMockSubscriber.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterDnsMockSubscriber.php new file mode 100644 index 000000000..81382d5e1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Extension/RegisterDnsMockSubscriber.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 Symfony\Bridge\PhpUnit\Extension; + +use PHPUnit\Event\Code\TestMethod; +use PHPUnit\Event\TestSuite\Loaded; +use PHPUnit\Event\TestSuite\LoadedSubscriber; +use PHPUnit\Metadata\Group; +use Symfony\Bridge\PhpUnit\DnsMock; + +/** + * @internal + */ +class RegisterDnsMockSubscriber implements LoadedSubscriber +{ + public function notify(Loaded $event): void + { + foreach ($event->testSuite()->tests() as $test) { + if (!$test instanceof TestMethod) { + continue; + } + + foreach ($test->metadata() as $metadata) { + if ($metadata instanceof Group && 'dns-sensitive' === $metadata->groupName()) { + DnsMock::register($test->className()); + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/LICENSE b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/LICENSE new file mode 100644 index 000000000..29f72d5e9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-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/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV7.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV7.php new file mode 100644 index 000000000..99a1e6835 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV7.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\Command as BaseCommand; +use PHPUnit\TextUI\TestRunner as BaseRunner; +use PHPUnit\Util\Configuration; +use Symfony\Bridge\PhpUnit\SymfonyTestsListener; + +/** + * @internal + */ +class CommandForV7 extends BaseCommand +{ + protected function createRunner(): BaseRunner + { + $this->arguments['listeners'] ?? $this->arguments['listeners'] = []; + + $registeredLocally = false; + + foreach ($this->arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListener) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (isset($this->arguments['configuration'])) { + $configuration = $this->arguments['configuration']; + if (!$configuration instanceof Configuration) { + $configuration = Configuration::getInstance($this->arguments['configuration']); + } + foreach ($configuration->getListenerConfiguration() as $registeredListener) { + if ('Symfony\Bridge\PhpUnit\SymfonyTestsListener' === ltrim($registeredListener['class'], '\\')) { + $registeredLocally = true; + break; + } + } + } + + if (!$registeredLocally) { + $this->arguments['listeners'][] = new SymfonyTestsListener(); + } + + return parent::createRunner(); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV9.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV9.php new file mode 100644 index 000000000..6dd276736 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/CommandForV9.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\TextUI\Command as BaseCommand; +use PHPUnit\TextUI\Configuration\Configuration as LegacyConfiguration; +use PHPUnit\TextUI\Configuration\Registry; +use PHPUnit\TextUI\TestRunner as BaseRunner; +use PHPUnit\TextUI\XmlConfiguration\Configuration; +use PHPUnit\TextUI\XmlConfiguration\Loader; +use Symfony\Bridge\PhpUnit\SymfonyTestsListener; + +/** + * @internal + */ +class CommandForV9 extends BaseCommand +{ + protected function createRunner(): BaseRunner + { + $this->arguments['listeners'] ?? $this->arguments['listeners'] = []; + + $registeredLocally = false; + + foreach ($this->arguments['listeners'] as $registeredListener) { + if ($registeredListener instanceof SymfonyTestsListener) { + $registeredListener->globalListenerDisabled(); + $registeredLocally = true; + break; + } + } + + if (isset($this->arguments['configuration'])) { + $configuration = $this->arguments['configuration']; + + if (!class_exists(Configuration::class) && !$configuration instanceof LegacyConfiguration) { + $configuration = Registry::getInstance()->get($this->arguments['configuration']); + } elseif (class_exists(Configuration::class) && !$configuration instanceof Configuration) { + $configuration = (new Loader())->load($this->arguments['configuration']); + } + + foreach ($configuration->listeners() as $registeredListener) { + if ('Symfony\Bridge\PhpUnit\SymfonyTestsListener' === ltrim($registeredListener->className(), '\\')) { + $registeredLocally = true; + break; + } + } + } + + if (!$registeredLocally) { + $this->arguments['listeners'][] = new SymfonyTestsListener(); + } + + return parent::createRunner(); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintLogicTrait.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintLogicTrait.php new file mode 100644 index 000000000..e124358c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintLogicTrait.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * @internal + */ +trait ConstraintLogicTrait +{ + private function doEvaluate($other, $description, $returnResult) + { + $success = false; + + if ($this->matches($other)) { + $success = true; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + + return null; + } + + private function doAdditionalFailureDescription($other): string + { + return ''; + } + + private function doCount(): int + { + return 1; + } + + private function doFailureDescription($other): string + { + return $this->exporter()->export($other).' '.$this->toString(); + } + + private function doMatches($other): bool + { + return false; + } + + private function doToString(): string + { + return ''; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV7.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV7.php new file mode 100644 index 000000000..b132f473c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV7.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use SebastianBergmann\Exporter\Exporter; + +/** + * @internal + */ +trait ConstraintTraitForV7 +{ + use ConstraintLogicTrait; + + /** + * @return bool|null + */ + public function evaluate($other, $description = '', $returnResult = false) + { + return $this->doEvaluate($other, $description, $returnResult); + } + + public function count(): int + { + return $this->doCount(); + } + + public function toString(): string + { + return $this->doToString(); + } + + protected function additionalFailureDescription($other): string + { + return $this->doAdditionalFailureDescription($other); + } + + protected function exporter(): Exporter + { + if (null === $this->exporter) { + $this->exporter = new Exporter(); + } + + return $this->exporter; + } + + protected function failureDescription($other): string + { + return $this->doFailureDescription($other); + } + + protected function matches($other): bool + { + return $this->doMatches($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV8.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV8.php new file mode 100644 index 000000000..d31cc1215 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV8.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * @internal + */ +trait ConstraintTraitForV8 +{ + use ConstraintLogicTrait; + + /** + * @return bool|null + */ + public function evaluate($other, $description = '', $returnResult = false) + { + return $this->doEvaluate($other, $description, $returnResult); + } + + public function count(): int + { + return $this->doCount(); + } + + public function toString(): string + { + return $this->doToString(); + } + + protected function additionalFailureDescription($other): string + { + return $this->doAdditionalFailureDescription($other); + } + + protected function failureDescription($other): string + { + return $this->doFailureDescription($other); + } + + protected function matches($other): bool + { + return $this->doMatches($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV9.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV9.php new file mode 100644 index 000000000..66da873e4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ConstraintTraitForV9.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * @internal + */ +trait ConstraintTraitForV9 +{ + use ConstraintLogicTrait; + + public function evaluate($other, string $description = '', bool $returnResult = false): ?bool + { + return $this->doEvaluate($other, $description, $returnResult); + } + + public function count(): int + { + return $this->doCount(); + } + + public function toString(): string + { + return $this->doToString(); + } + + protected function additionalFailureDescription($other): string + { + return $this->doAdditionalFailureDescription($other); + } + + protected function failureDescription($other): string + { + return $this->doFailureDescription($other); + } + + protected function matches($other): bool + { + return $this->doMatches($other); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitBeforeV8_4.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitBeforeV8_4.php new file mode 100644 index 000000000..d60587eca --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitBeforeV8_4.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * @internal, use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait instead. + */ +trait ExpectDeprecationTraitBeforeV8_4 +{ + /** + * @param string $message + */ + protected function expectDeprecation($message): void + { + // Expected deprecations set by isolated tests need to be written to a file + // so that the test running process can take account of them. + if ($file = getenv('SYMFONY_EXPECTED_DEPRECATIONS_SERIALIZE')) { + $this->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything(false); + $expectedDeprecations = file_get_contents($file); + if ($expectedDeprecations) { + $expectedDeprecations = array_merge(unserialize($expectedDeprecations), [$message]); + } else { + $expectedDeprecations = [$message]; + } + file_put_contents($file, serialize($expectedDeprecations)); + + return; + } + + if (!SymfonyTestsListenerTrait::$previousErrorHandler) { + SymfonyTestsListenerTrait::$previousErrorHandler = set_error_handler([SymfonyTestsListenerTrait::class, 'handleError']); + } + + SymfonyTestsListenerTrait::$expectedDeprecations[] = $message; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitForV8_4.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitForV8_4.php new file mode 100644 index 000000000..d15963520 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/ExpectDeprecationTraitForV8_4.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * @internal use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait instead + */ +trait ExpectDeprecationTraitForV8_4 +{ + /** + * @param string $message + */ + public function expectDeprecation(): void + { + if (1 > \func_num_args() || !\is_string($message = func_get_arg(0))) { + throw new \InvalidArgumentException(sprintf('The "%s()" method requires the string $message argument.', __FUNCTION__)); + } + + // Expected deprecations set by isolated tests need to be written to a file + // so that the test running process can take account of them. + if ($file = getenv('SYMFONY_EXPECTED_DEPRECATIONS_SERIALIZE')) { + $this->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything(false); + $expectedDeprecations = file_get_contents($file); + if ($expectedDeprecations) { + $expectedDeprecations = array_merge(unserialize($expectedDeprecations), [$message]); + } else { + $expectedDeprecations = [$message]; + } + file_put_contents($file, serialize($expectedDeprecations)); + + return; + } + + if (!SymfonyTestsListenerTrait::$previousErrorHandler) { + SymfonyTestsListenerTrait::$previousErrorHandler = set_error_handler([SymfonyTestsListenerTrait::class, 'handleError']); + } + + SymfonyTestsListenerTrait::$expectedDeprecations[] = $message; + } + + /** + * @internal use expectDeprecation() instead + */ + public function expectDeprecationMessage(string $message): void + { + throw new \BadMethodCallException(sprintf('The "%s()" method is not supported by Symfony\'s PHPUnit Bridge ExpectDeprecationTrait, pass the message to expectDeprecation() instead.', __FUNCTION__)); + } + + /** + * @internal use expectDeprecation() instead + */ + public function expectDeprecationMessageMatches(string $regularExpression): void + { + throw new \BadMethodCallException(sprintf('The "%s()" method is not supported by Symfony\'s PHPUnit Bridge ExpectDeprecationTrait.', __FUNCTION__)); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillAssertTrait.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillAssertTrait.php new file mode 100644 index 000000000..7424b7226 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillAssertTrait.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\Framework\Constraint\LogicalNot; +use PHPUnit\Framework\Constraint\TraversableContains; + +/** + * This trait is @internal. + */ +trait PolyfillAssertTrait +{ + /** + * @param iterable $haystack + * @param string $message + * + * @return void + */ + public static function assertContainsEquals($needle, $haystack, $message = '') + { + $constraint = new TraversableContains($needle, false, false); + static::assertThat($haystack, $constraint, $message); + } + + /** + * @param iterable $haystack + * @param string $message + * + * @return void + */ + public static function assertNotContainsEquals($needle, $haystack, $message = '') + { + $constraint = new LogicalNot(new TraversableContains($needle, false, false)); + static::assertThat($haystack, $constraint, $message); + } + + /** + * @param string $filename + * @param string $message + * + * @return void + */ + public static function assertIsNotReadable($filename, $message = '') + { + static::assertNotIsReadable($filename, $message); + } + + /** + * @param string $filename + * @param string $message + * + * @return void + */ + public static function assertIsNotWritable($filename, $message = '') + { + static::assertNotIsWritable($filename, $message); + } + + /** + * @param string $directory + * @param string $message + * + * @return void + */ + public static function assertDirectoryDoesNotExist($directory, $message = '') + { + static::assertDirectoryNotExists($directory, $message); + } + + /** + * @param string $directory + * @param string $message + * + * @return void + */ + public static function assertDirectoryIsNotReadable($directory, $message = '') + { + static::assertDirectoryNotIsReadable($directory, $message); + } + + /** + * @param string $directory + * @param string $message + * + * @return void + */ + public static function assertDirectoryIsNotWritable($directory, $message = '') + { + static::assertDirectoryNotIsWritable($directory, $message); + } + + /** + * @param string $filename + * @param string $message + * + * @return void + */ + public static function assertFileDoesNotExist($filename, $message = '') + { + static::assertFileNotExists($filename, $message); + } + + /** + * @param string $filename + * @param string $message + * + * @return void + */ + public static function assertFileIsNotReadable($filename, $message = '') + { + static::assertFileNotIsReadable($filename, $message); + } + + /** + * @param string $filename + * @param string $message + * + * @return void + */ + public static function assertFileIsNotWritable($filename, $message = '') + { + static::assertFileNotIsWritable($filename, $message); + } + + /** + * @param string $pattern + * @param string $string + * @param string $message + * + * @return void + */ + public static function assertMatchesRegularExpression($pattern, $string, $message = '') + { + static::assertRegExp($pattern, $string, $message); + } + + /** + * @param string $pattern + * @param string $string + * @param string $message + * + * @return void + */ + public static function assertDoesNotMatchRegularExpression($pattern, $string, $message = '') + { + static::assertNotRegExp($pattern, $string, $message); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillTestCaseTrait.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillTestCaseTrait.php new file mode 100644 index 000000000..8673bdc0a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/PolyfillTestCaseTrait.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\Framework\Error\Error; +use PHPUnit\Framework\Error\Notice; +use PHPUnit\Framework\Error\Warning; + +/** + * This trait is @internal. + */ +trait PolyfillTestCaseTrait +{ + /** + * @param string $messageRegExp + * + * @return void + */ + public function expectExceptionMessageMatches($messageRegExp) + { + $this->expectExceptionMessageRegExp($messageRegExp); + } + + /** + * @return void + */ + public function expectNotice() + { + $this->expectException(Notice::class); + } + + /** + * @param string $message + * + * @return void + */ + public function expectNoticeMessage($message) + { + $this->expectExceptionMessage($message); + } + + /** + * @param string $regularExpression + * + * @return void + */ + public function expectNoticeMessageMatches($regularExpression) + { + $this->expectExceptionMessageMatches($regularExpression); + } + + /** + * @return void + */ + public function expectWarning() + { + $this->expectException(Warning::class); + } + + /** + * @param string $message + * + * @return void + */ + public function expectWarningMessage($message) + { + $this->expectExceptionMessage($message); + } + + /** + * @param string $regularExpression + * + * @return void + */ + public function expectWarningMessageMatches($regularExpression) + { + $this->expectExceptionMessageMatches($regularExpression); + } + + /** + * @return void + */ + public function expectError() + { + $this->expectException(Error::class); + } + + /** + * @param string $message + * + * @return void + */ + public function expectErrorMessage($message) + { + $this->expectExceptionMessage($message); + } + + /** + * @param string $regularExpression + * + * @return void + */ + public function expectErrorMessageMatches($regularExpression) + { + $this->expectExceptionMessageMatches($regularExpression); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerForV7.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerForV7.php new file mode 100644 index 000000000..15f60a453 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerForV7.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestListenerDefaultImplementation; +use PHPUnit\Framework\TestSuite; + +/** + * Collects and replays skipped tests. + * + * @author Nicolas Grekas + * + * @internal + */ +class SymfonyTestsListenerForV7 implements TestListener +{ + use TestListenerDefaultImplementation; + + private $trait; + + public function __construct(array $mockedNamespaces = []) + { + $this->trait = new SymfonyTestsListenerTrait($mockedNamespaces); + } + + public function globalListenerDisabled() + { + $this->trait->globalListenerDisabled(); + } + + public function startTestSuite(TestSuite $suite): void + { + $this->trait->startTestSuite($suite); + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + $this->trait->addSkippedTest($test, $t, $time); + } + + public function startTest(Test $test): void + { + $this->trait->startTest($test); + } + + public function endTest(Test $test, float $time): void + { + $this->trait->endTest($test, $time); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerTrait.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerTrait.php new file mode 100644 index 000000000..2b45051e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/Legacy/SymfonyTestsListenerTrait.php @@ -0,0 +1,364 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use Doctrine\Common\Annotations\AnnotationRegistry; +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\DataProviderTestSuite; +use PHPUnit\Framework\RiskyTestError; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Util\Blacklist; +use PHPUnit\Util\ExcludeList; +use PHPUnit\Util\Test; +use Symfony\Bridge\PhpUnit\ClockMock; +use Symfony\Bridge\PhpUnit\DnsMock; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\ErrorHandler\DebugClassLoader; + +/** + * PHP 5.3 compatible trait-like shared implementation. + * + * @author Nicolas Grekas + * + * @internal + */ +class SymfonyTestsListenerTrait +{ + public static $expectedDeprecations = []; + public static $previousErrorHandler; + private static $gatheredDeprecations = []; + private static $globallyEnabled = false; + private $state = -1; + private $skippedFile = false; + private $wasSkipped = []; + private $isSkipped = []; + private $runsInSeparateProcess = false; + private $checkNumAssertions = false; + + /** + * @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive) + */ + public function __construct(array $mockedNamespaces = []) + { + setlocale(\LC_ALL, $_ENV['SYMFONY_PHPUNIT_LOCALE'] ?? 'C'); + + if (class_exists(ExcludeList::class)) { + (new ExcludeList())->getExcludedDirectories(); + ExcludeList::addDirectory(\dirname((new \ReflectionClass(__CLASS__))->getFileName(), 2)); + } elseif (method_exists(Blacklist::class, 'addDirectory')) { + (new BlackList())->getBlacklistedDirectories(); + Blacklist::addDirectory(\dirname((new \ReflectionClass(__CLASS__))->getFileName(), 2)); + } else { + Blacklist::$blacklistedClassNames[__CLASS__] = 2; + } + + $enableDebugClassLoader = class_exists(DebugClassLoader::class); + + foreach ($mockedNamespaces as $type => $namespaces) { + if (!\is_array($namespaces)) { + $namespaces = [$namespaces]; + } + if ('time-sensitive' === $type) { + foreach ($namespaces as $ns) { + ClockMock::register($ns.'\DummyClass'); + } + } + if ('dns-sensitive' === $type) { + foreach ($namespaces as $ns) { + DnsMock::register($ns.'\DummyClass'); + } + } + if ('debug-class-loader' === $type) { + $enableDebugClassLoader = $namespaces && $namespaces[0]; + } + } + if ($enableDebugClassLoader) { + DebugClassLoader::enable(); + } + if (self::$globallyEnabled) { + $this->state = -2; + } else { + self::$globallyEnabled = true; + } + } + + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if (0 < $this->state) { + file_put_contents($this->skippedFile, 'isSkipped, true).';'); + } + } + + public function globalListenerDisabled(): void + { + self::$globallyEnabled = false; + $this->state = -1; + } + + public function startTestSuite($suite): void + { + $suiteName = $suite->getName(); + + foreach ($suite->tests() as $test) { + if (!$test instanceof TestCase) { + continue; + } + if (null === Test::getPreserveGlobalStateSettings(\get_class($test), $test->getName(false))) { + $test->setPreserveGlobalState(false); + } + } + + if (-1 === $this->state) { + echo "Testing $suiteName\n"; + $this->state = 0; + + if (!class_exists(AnnotationRegistry::class, false) && class_exists(AnnotationRegistry::class)) { + if (method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { + AnnotationRegistry::registerUniqueLoader('class_exists'); + } elseif (method_exists(AnnotationRegistry::class, 'registerLoader')) { + AnnotationRegistry::registerLoader('class_exists'); + } + } + + if ($this->skippedFile = getenv('SYMFONY_PHPUNIT_SKIPPED_TESTS')) { + $this->state = 1; + + if (file_exists($this->skippedFile)) { + $this->state = 2; + + if (!$this->wasSkipped = require $this->skippedFile) { + echo "All tests already ran successfully.\n"; + $suite->setTests([]); + } + } + } + $testSuites = [$suite]; + for ($i = 0; isset($testSuites[$i]); ++$i) { + foreach ($testSuites[$i]->tests() as $test) { + if ($test instanceof TestSuite) { + if (!class_exists($test->getName(), false)) { + $testSuites[] = $test; + continue; + } + $groups = Test::getGroups($test->getName()); + if (\in_array('time-sensitive', $groups, true)) { + ClockMock::register($test->getName()); + } + if (\in_array('dns-sensitive', $groups, true)) { + DnsMock::register($test->getName()); + } + } + } + } + } elseif (2 === $this->state) { + $suites = [$suite]; + $skipped = []; + while ($s = array_shift($suites)) { + foreach ($s->tests() as $test) { + if ($test instanceof TestSuite) { + $suites[] = $test; + continue; + } + if ($test instanceof TestCase + && isset($this->wasSkipped[\get_class($test)][$test->getName()]) + ) { + $skipped[] = $test; + } + } + } + $suite->setTests($skipped); + } + } + + public function addSkippedTest($test, \Exception $e, $time): void + { + if (0 < $this->state) { + if ($test instanceof DataProviderTestSuite) { + foreach ($test->tests() as $testWithDataProvider) { + $this->isSkipped[\get_class($testWithDataProvider)][$testWithDataProvider->getName()] = 1; + } + } else { + $this->isSkipped[\get_class($test)][$test->getName()] = 1; + } + } + } + + public function startTest($test): void + { + if (-2 < $this->state && $test instanceof TestCase) { + // This event is triggered before the test is re-run in isolation + if ($this->willBeIsolated($test)) { + $this->runsInSeparateProcess = tempnam(sys_get_temp_dir(), 'deprec'); + putenv('SYMFONY_DEPRECATIONS_SERIALIZE='.$this->runsInSeparateProcess); + putenv('SYMFONY_EXPECTED_DEPRECATIONS_SERIALIZE='.tempnam(sys_get_temp_dir(), 'expectdeprec')); + } + + $groups = Test::getGroups(\get_class($test), $test->getName(false)); + + if (!$this->runsInSeparateProcess) { + if (\in_array('time-sensitive', $groups, true)) { + ClockMock::register(\get_class($test)); + ClockMock::withClockMock(true); + } + if (\in_array('dns-sensitive', $groups, true)) { + DnsMock::register(\get_class($test)); + } + } + + if (!$test->getTestResultObject()) { + return; + } + + $annotations = Test::parseTestMethodAnnotations(\get_class($test), $test->getName(false)); + + if (isset($annotations['class']['expectedDeprecation'])) { + $test->getTestResultObject()->addError($test, new AssertionFailedError('"@expectedDeprecation" annotations are not allowed at the class level.'), 0); + } + if (isset($annotations['method']['expectedDeprecation']) || $this->checkNumAssertions = method_exists($test, 'expectDeprecation') && (new \ReflectionMethod($test, 'expectDeprecation'))->getFileName() === (new \ReflectionMethod(ExpectDeprecationTrait::class, 'expectDeprecation'))->getFileName()) { + if (isset($annotations['method']['expectedDeprecation'])) { + self::$expectedDeprecations = $annotations['method']['expectedDeprecation']; + self::$previousErrorHandler = set_error_handler([self::class, 'handleError']); + @trigger_error('Since symfony/phpunit-bridge 5.1: Using "@expectedDeprecation" annotations in tests is deprecated, use the "ExpectDeprecationTrait::expectDeprecation()" method instead.', \E_USER_DEPRECATED); + } + + if ($this->checkNumAssertions) { + $this->checkNumAssertions = $test->getTestResultObject()->isStrictAboutTestsThatDoNotTestAnything(); + } + + $test->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything(false); + } + } + } + + public function endTest($test, $time): void + { + if ($file = getenv('SYMFONY_EXPECTED_DEPRECATIONS_SERIALIZE')) { + putenv('SYMFONY_EXPECTED_DEPRECATIONS_SERIALIZE'); + $expectedDeprecations = file_get_contents($file); + if ($expectedDeprecations) { + self::$expectedDeprecations = array_merge(self::$expectedDeprecations, unserialize($expectedDeprecations)); + if (!self::$previousErrorHandler) { + self::$previousErrorHandler = set_error_handler([self::class, 'handleError']); + } + } + } + + if (class_exists(DebugClassLoader::class, false)) { + DebugClassLoader::checkClasses(); + } + + $className = \get_class($test); + $groups = Test::getGroups($className, $test->getName(false)); + + if ($this->checkNumAssertions) { + $assertions = \count(self::$expectedDeprecations) + $test->getNumAssertions(); + if ($test->doesNotPerformAssertions() && $assertions > 0) { + $test->getTestResultObject()->addFailure($test, new RiskyTestError(sprintf('This test is annotated with "@doesNotPerformAssertions", but performed %s assertions', $assertions)), $time); + } elseif ($assertions === 0 && !$test->doesNotPerformAssertions() && $test->getTestResultObject()->noneSkipped()) { + $test->getTestResultObject()->addFailure($test, new RiskyTestError('This test did not perform any assertions'), $time); + } + + $this->checkNumAssertions = false; + } + + if ($this->runsInSeparateProcess) { + $deprecations = file_get_contents($this->runsInSeparateProcess); + unlink($this->runsInSeparateProcess); + putenv('SYMFONY_DEPRECATIONS_SERIALIZE'); + foreach ($deprecations ? unserialize($deprecations) : [] as $deprecation) { + $error = serialize(['deprecation' => $deprecation[1], 'class' => $className, 'method' => $test->getName(false), 'triggering_file' => $deprecation[2] ?? null, 'files_stack' => $deprecation[3] ?? []]); + if ($deprecation[0]) { + // unsilenced on purpose + trigger_error($error, \E_USER_DEPRECATED); + } else { + @trigger_error($error, \E_USER_DEPRECATED); + } + } + $this->runsInSeparateProcess = false; + } + + if (self::$expectedDeprecations) { + if (!\in_array($test->getStatus(), [BaseTestRunner::STATUS_SKIPPED, BaseTestRunner::STATUS_INCOMPLETE], true)) { + $test->addToAssertionCount(\count(self::$expectedDeprecations)); + } + + restore_error_handler(); + + if (!\in_array('legacy', $groups, true)) { + $test->getTestResultObject()->addError($test, new AssertionFailedError('Only tests with the "@group legacy" annotation can expect a deprecation.'), 0); + } elseif (!\in_array($test->getStatus(), [BaseTestRunner::STATUS_SKIPPED, BaseTestRunner::STATUS_INCOMPLETE, BaseTestRunner::STATUS_FAILURE, BaseTestRunner::STATUS_ERROR], true)) { + try { + $prefix = "@expectedDeprecation:\n"; + $test->assertStringMatchesFormat($prefix.'%A '.implode("\n%A ", self::$expectedDeprecations)."\n%A", $prefix.' '.implode("\n ", self::$gatheredDeprecations)."\n"); + } catch (AssertionFailedError $e) { + $test->getTestResultObject()->addFailure($test, $e, $time); + } + } + + self::$expectedDeprecations = self::$gatheredDeprecations = []; + self::$previousErrorHandler = null; + } + if (!$this->runsInSeparateProcess && -2 < $this->state && $test instanceof TestCase) { + if (\in_array('time-sensitive', $groups, true)) { + ClockMock::withClockMock(false); + } + if (\in_array('dns-sensitive', $groups, true)) { + DnsMock::withMockedHosts([]); + } + } + } + + public static function handleError($type, $msg, $file, $line, $context = []) + { + if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) { + $h = self::$previousErrorHandler; + + return $h ? $h($type, $msg, $file, $line, $context) : false; + } + // If the message is serialized we need to extract the message. This occurs when the error is triggered by + // by the isolated test path in \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest(). + $parsedMsg = @unserialize($msg); + if (\is_array($parsedMsg)) { + $msg = $parsedMsg['deprecation']; + } + if (error_reporting() & $type) { + $msg = 'Unsilenced deprecation: '.$msg; + } + self::$gatheredDeprecations[] = $msg; + + return true; + } + + private function willBeIsolated(TestCase $test): bool + { + if ($test->isInIsolation()) { + return false; + } + + $r = new \ReflectionProperty($test, 'runTestInSeparateProcess'); + $r->setAccessible(true); + + return $r->getValue($test) ?? false; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/README.md b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/README.md new file mode 100644 index 000000000..b7c041a8e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/README.md @@ -0,0 +1,14 @@ +PHPUnit Bridge +============== + +The PHPUnit bridge provides utilities for [PHPUnit](https://phpunit.de/), +especially user deprecation notices management. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/phpunit_bridge.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/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyExtension.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyExtension.php new file mode 100644 index 000000000..1df4f2065 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyExtension.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Runner\Extension\Extension; +use PHPUnit\Runner\Extension\Facade; +use PHPUnit\Runner\Extension\ParameterCollection; +use PHPUnit\TextUI\Configuration\Configuration; +use Symfony\Bridge\PhpUnit\Extension\DisableClockMockSubscriber; +use Symfony\Bridge\PhpUnit\Extension\DisableDnsMockSubscriber; +use Symfony\Bridge\PhpUnit\Extension\EnableClockMockSubscriber; +use Symfony\Bridge\PhpUnit\Extension\RegisterClockMockSubscriber; +use Symfony\Bridge\PhpUnit\Extension\RegisterDnsMockSubscriber; +use Symfony\Component\ErrorHandler\DebugClassLoader; + +class SymfonyExtension implements Extension +{ + public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters): void + { + if (class_exists(DebugClassLoader::class)) { + DebugClassLoader::enable(); + } + + if ($parameters->has('clock-mock-namespaces')) { + foreach (explode(',', $parameters->get('clock-mock-namespaces')) as $namespace) { + ClockMock::register($namespace.'\DummyClass'); + } + } + + $facade->registerSubscriber(new RegisterClockMockSubscriber()); + $facade->registerSubscriber(new EnableClockMockSubscriber()); + $facade->registerSubscriber(new DisableClockMockSubscriber()); + + if ($parameters->has('dns-mock-namespaces')) { + foreach (explode(',', $parameters->get('dns-mock-namespaces')) as $namespace) { + DnsMock::register($namespace.'\DummyClass'); + } + } + + $facade->registerSubscriber(new RegisterDnsMockSubscriber()); + $facade->registerSubscriber(new DisableDnsMockSubscriber()); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php new file mode 100644 index 000000000..47f0f42af --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/SymfonyTestsListener.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); + +if (false) { + class SymfonyTestsListener + { + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/TextUI/Command.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/TextUI/Command.php new file mode 100644 index 000000000..3cc158f6b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/TextUI/Command.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\TextUI; + +if (version_compare(\PHPUnit\Runner\Version::id(), '9.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV7', 'Symfony\Bridge\PhpUnit\TextUI\Command'); +} else { + class_alias('Symfony\Bridge\PhpUnit\Legacy\CommandForV9', 'Symfony\Bridge\PhpUnit\TextUI\Command'); +} + +if (false) { + class Command + { + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit new file mode 100644 index 000000000..53305e5ee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit @@ -0,0 +1,13 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require __DIR__.DIRECTORY_SEPARATOR.'simple-phpunit.php'; diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php new file mode 100644 index 000000000..0472e8c1d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php @@ -0,0 +1,476 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +// Please update when phpunit needs to be reinstalled with fresh deps: +// Cache-Id: 2021-02-04 11:00 UTC + +if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + +error_reporting(-1); + +global $argv, $argc; +$argv = $_SERVER['argv'] ?? []; +$argc = $_SERVER['argc'] ?? 0; +$getEnvVar = function ($name, $default = false) use ($argv) { + if (false !== $value = getenv($name)) { + return $value; + } + + static $phpunitConfig = null; + if (null === $phpunitConfig) { + $phpunitConfigFilename = null; + $getPhpUnitConfig = function ($probableConfig) use (&$getPhpUnitConfig) { + if (!$probableConfig) { + return null; + } + if (is_dir($probableConfig)) { + return $getPhpUnitConfig($probableConfig.\DIRECTORY_SEPARATOR.'phpunit.xml'); + } + + if (file_exists($probableConfig)) { + return $probableConfig; + } + if (file_exists($probableConfig.'.dist')) { + return $probableConfig.'.dist'; + } + + return null; + }; + + foreach ($argv as $cliArgumentIndex => $cliArgument) { + if ('--' === $cliArgument) { + break; + } + // long option + if ('--configuration' === $cliArgument && array_key_exists($cliArgumentIndex + 1, $argv)) { + $phpunitConfigFilename = $getPhpUnitConfig($argv[$cliArgumentIndex + 1]); + break; + } + // short option + if (0 === strpos($cliArgument, '-c')) { + if ('-c' === $cliArgument && array_key_exists($cliArgumentIndex + 1, $argv)) { + $phpunitConfigFilename = $getPhpUnitConfig($argv[$cliArgumentIndex + 1]); + } else { + $phpunitConfigFilename = $getPhpUnitConfig(substr($cliArgument, 2)); + } + break; + } + } + + $phpunitConfigFilename = $phpunitConfigFilename ?: $getPhpUnitConfig('phpunit.xml'); + + if ($phpunitConfigFilename) { + $phpunitConfig = new DOMDocument(); + $phpunitConfig->load($phpunitConfigFilename); + } else { + $phpunitConfig = false; + } + } + if (false !== $phpunitConfig) { + $var = new DOMXPath($phpunitConfig); + foreach ($var->query('//php/server[@name="'.$name.'"]') as $var) { + return $var->getAttribute('value'); + } + foreach ($var->query('//php/env[@name="'.$name.'"]') as $var) { + return $var->getAttribute('value'); + } + } + + return $default; +}; + +$passthruOrFail = function ($command) { + passthru($command, $status); + + if ($status) { + exit($status); + } +}; + +if (\PHP_VERSION_ID >= 80000) { + $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '9.6') ?: '9.6'; +} else { + $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '8.5') ?: '8.5'; +} + +$MAX_PHPUNIT_VERSION = $getEnvVar('SYMFONY_MAX_PHPUNIT_VERSION', false); + +if ($MAX_PHPUNIT_VERSION && version_compare($MAX_PHPUNIT_VERSION, $PHPUNIT_VERSION, '<')) { + $PHPUNIT_VERSION = $MAX_PHPUNIT_VERSION; +} + +if (version_compare($PHPUNIT_VERSION, '10.0', '>=') && version_compare($PHPUNIT_VERSION, '11.0', '<')) { + fwrite(STDERR, 'This script does not work with PHPUnit 10.'.\PHP_EOL); + exit(1); +} + +$PHPUNIT_REMOVE_RETURN_TYPEHINT = filter_var($getEnvVar('SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT', '0'), \FILTER_VALIDATE_BOOLEAN); + +$COMPOSER_JSON = getenv('COMPOSER') ?: 'composer.json'; + +$root = __DIR__; +while (!file_exists($root.'/'.$COMPOSER_JSON) || file_exists($root.'/DeprecationErrorHandler.php')) { + if ($root === dirname($root)) { + break; + } + $root = dirname($root); +} + +$oldPwd = getcwd(); +$PHPUNIT_DIR = rtrim($getEnvVar('SYMFONY_PHPUNIT_DIR', $root.'/vendor/bin/.phpunit'), '/'.\DIRECTORY_SEPARATOR); +$PHP = defined('PHP_BINARY') ? \PHP_BINARY : 'php'; +$PHP = escapeshellarg($PHP); +if ('phpdbg' === \PHP_SAPI) { + $PHP .= ' -qrr'; +} + +$defaultEnvs = [ + 'COMPOSER' => 'composer.json', + 'COMPOSER_VENDOR_DIR' => 'vendor', + 'COMPOSER_BIN_DIR' => 'bin', + 'SYMFONY_SIMPLE_PHPUNIT_BIN_DIR' => __DIR__, +]; + +foreach ($defaultEnvs as $envName => $envValue) { + if ($envValue !== getenv($envName)) { + putenv("$envName=$envValue"); + $_SERVER[$envName] = $_ENV[$envName] = $envValue; + } +} + +if ('disabled' === $getEnvVar('SYMFONY_DEPRECATIONS_HELPER') || version_compare($PHPUNIT_VERSION, '11.0', '>=')) { + putenv('SYMFONY_DEPRECATIONS_HELPER=disabled'); +} + +if (!$getEnvVar('DOCTRINE_DEPRECATIONS')) { + putenv('DOCTRINE_DEPRECATIONS=trigger'); + $_SERVER['DOCTRINE_DEPRECATIONS'] = $_ENV['DOCTRINE_DEPRECATIONS'] = 'trigger'; +} + +$COMPOSER = ($COMPOSER = getenv('COMPOSER_BINARY')) + || file_exists($COMPOSER = $oldPwd.'/composer.phar') + || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', shell_exec('where.exe composer.phar 2> NUL')) : shell_exec('which composer.phar 2> /dev/null')))) + || ($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', shell_exec('where.exe composer 2> NUL')) : shell_exec('which composer 2> /dev/null')))) + || file_exists($COMPOSER = rtrim((string) ('\\' === \DIRECTORY_SEPARATOR ? shell_exec('git rev-parse --show-toplevel 2> NUL') : shell_exec('git rev-parse --show-toplevel 2> /dev/null'))).\DIRECTORY_SEPARATOR.'composer.phar') + ? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang + : 'composer'; + +$prevCacheDir = getenv('COMPOSER_CACHE_DIR'); +if ($prevCacheDir) { + if (false === $absoluteCacheDir = realpath($prevCacheDir)) { + @mkdir($prevCacheDir, 0777, true); + $absoluteCacheDir = realpath($prevCacheDir); + } + if ($absoluteCacheDir) { + putenv("COMPOSER_CACHE_DIR=$absoluteCacheDir"); + } else { + $prevCacheDir = false; + } +} +$SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml' : '')); +$SYMFONY_PHPUNIT_REQUIRE = $getEnvVar('SYMFONY_PHPUNIT_REQUIRE', ''); +$configurationHash = md5(implode(\PHP_EOL, [md5_file(__FILE__), $SYMFONY_PHPUNIT_REMOVE, $SYMFONY_PHPUNIT_REQUIRE, (int) $PHPUNIT_REMOVE_RETURN_TYPEHINT])); +$PHPUNIT_VERSION_DIR = sprintf('phpunit-%s-%d', $PHPUNIT_VERSION, $PHPUNIT_REMOVE_RETURN_TYPEHINT); +if (!file_exists("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit") || $configurationHash !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION_DIR.md5")) { + // Build a standalone phpunit without symfony/yaml nor prophecy by default + + @mkdir($PHPUNIT_DIR, 0777, true); + chdir($PHPUNIT_DIR); + if (file_exists("$PHPUNIT_VERSION_DIR")) { + passthru(sprintf('\\' === \DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s 2> NUL' : 'rm -rf %s', escapeshellarg("$PHPUNIT_VERSION_DIR.old"))); + rename("$PHPUNIT_VERSION_DIR", "$PHPUNIT_VERSION_DIR.old"); + passthru(sprintf('\\' === \DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s' : 'rm -rf %s', escapeshellarg("$PHPUNIT_VERSION_DIR.old"))); + } + + $info = []; + foreach (explode("\n", `$COMPOSER info --no-ansi -a -n phpunit/phpunit "$PHPUNIT_VERSION.*"`) as $line) { + $line = rtrim($line); + + if (!$info && preg_match('/^versions +: /', $line)) { + $info['versions'] = explode(', ', ltrim(substr($line, 9), ': ')); + } elseif (isset($info['requires'])) { + if ('' === $line) { + break; + } + + $line = explode(' ', $line, 2); + $info['requires'][$line[0]] = $line[1]; + } elseif ($info && 'requires' === $line) { + $info['requires'] = []; + } + } + + if (in_array('--colors=never', $argv, true) || (isset($argv[$i = array_search('never', $argv, true) - 1]) && '--colors' === $argv[$i])) { + $COMPOSER .= ' --no-ansi'; + } else { + $COMPOSER .= ' --ansi'; + } + + $info += [ + 'versions' => [], + 'requires' => ['php' => '*'], + ]; + + $stableVersions = array_filter($info['versions'], function ($v) { + return !preg_match('/-dev$|^dev-/', $v); + }); + + if (!$stableVersions) { + $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress -s dev phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\""); + } else { + $passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\""); + } + + @copy("$PHPUNIT_VERSION_DIR/phpunit.xsd", 'phpunit.xsd'); + chdir("$PHPUNIT_VERSION_DIR"); + if ($SYMFONY_PHPUNIT_REMOVE) { + $passthruOrFail("$COMPOSER remove --no-update --no-interaction ".$SYMFONY_PHPUNIT_REMOVE); + } + if ($SYMFONY_PHPUNIT_REQUIRE) { + $passthruOrFail("$COMPOSER require --no-update --no-interaction ".$SYMFONY_PHPUNIT_REQUIRE); + } + if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { + $passthruOrFail("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); + } + + if (preg_match('{\^((\d++\.)\d++)[\d\.]*$}', $info['requires']['php'], $phpVersion) && version_compare($phpVersion[2].'99', \PHP_VERSION, '<')) { + $passthruOrFail("$COMPOSER config platform.php \"$phpVersion[1].99\""); + } else { + $passthruOrFail("$COMPOSER config --unset platform.php"); + } + if (file_exists($path = $root.'/vendor/symfony/phpunit-bridge')) { + $haystack = "$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR"; + $rootLen = strlen($root); + + $p = ($rootLen <= strlen($haystack) ? str_repeat('../', substr_count($haystack, '/', $rootLen)) : '').'vendor/symfony/phpunit-bridge'; + if (realpath($p) === realpath($path)) { + $path = $p; + } + $passthruOrFail("$COMPOSER require --no-update symfony/phpunit-bridge \"*@dev\""); + $passthruOrFail("$COMPOSER config repositories.phpunit-bridge path ".escapeshellarg(str_replace('/', \DIRECTORY_SEPARATOR, $path))); + if ('\\' === \DIRECTORY_SEPARATOR) { + file_put_contents('composer.json', preg_replace('/^( {8})"phpunit-bridge": \{$/m', "$0\n$1 ".'"options": {"symlink": false},', file_get_contents('composer.json'))); + } + } else { + $passthruOrFail("$COMPOSER require --no-update symfony/phpunit-bridge \"*\""); + } + $prevRoot = getenv('COMPOSER_ROOT_VERSION'); + putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); + $q = '\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 80000 ? '"' : ''; + // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS + $exit = proc_close(proc_open("$q$COMPOSER update --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); + putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); + if ($prevCacheDir) { + putenv("COMPOSER_CACHE_DIR=$prevCacheDir"); + } + if ($exit) { + exit($exit); + } + + // Mutate TestCase code + if (version_compare($PHPUNIT_VERSION, '11.0', '<')) { + $alteredCode = file_get_contents($alteredFile = './src/Framework/TestCase.php'); + if ($PHPUNIT_REMOVE_RETURN_TYPEHINT) { + $alteredCode = preg_replace('/^ ((?:protected|public)(?: static)? function \w+\(\)): void/m', ' $1', $alteredCode); + } + $alteredCode = preg_replace('/abstract class TestCase[^\{]+\{/', '$0 '.\PHP_EOL." use \Symfony\Bridge\PhpUnit\Legacy\PolyfillTestCaseTrait;", $alteredCode, 1); + file_put_contents($alteredFile, $alteredCode); + + // Mutate Assert code + $alteredCode = file_get_contents($alteredFile = './src/Framework/Assert.php'); + $alteredCode = preg_replace('/abstract class Assert[^\{]+\{/', '$0 '.\PHP_EOL." use \Symfony\Bridge\PhpUnit\Legacy\PolyfillAssertTrait;", $alteredCode, 1); + file_put_contents($alteredFile, $alteredCode); + + file_put_contents('phpunit', <<<'EOPHP' +getExcludedDirectories(); + PHPUnit\Util\ExcludeList::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListPhpunit::class))->getFileName())); + class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\ExcludeList::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListSimplePhpunit::class))->getFileName())); +} elseif (method_exists(\PHPUnit\Util\Blacklist::class, 'addDirectory')) { + (new PHPUnit\Util\BlackList())->getBlacklistedDirectories(); + PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListPhpunit::class))->getFileName())); + class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass(\SymfonyExcludeListSimplePhpunit::class))->getFileName())); +} else { + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyExcludeListPhpunit'] = 1; + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyExcludeListSimplePhpunit'] = 1; +} + +Symfony\Bridge\PhpUnit\TextUI\Command::main(); + +EOPHP + ); + } + + chdir('..'); + file_put_contents(".$PHPUNIT_VERSION_DIR.md5", $configurationHash); + chdir($oldPwd); +} + +// Create a symlink with a predictable path pointing to the currently used version. +// This is useful for static analytics tools such as PHPStan having to load PHPUnit's classes +// and for other testing libraries such as Behat using PHPUnit's assertions. +chdir($PHPUNIT_DIR); +if ('\\' === \DIRECTORY_SEPARATOR) { + passthru('rmdir /S /Q phpunit 2> NUL'); + passthru(sprintf('mklink /j phpunit %s > NUL 2>&1', escapeshellarg($PHPUNIT_VERSION_DIR))); +} else { + if (file_exists('phpunit')) { + @unlink('phpunit'); + } + @symlink($PHPUNIT_VERSION_DIR, 'phpunit'); +} +chdir($oldPwd); + +if ($PHPUNIT_VERSION < 8.0) { + $argv = array_filter($argv, function ($v) use (&$argc) { + if ('--do-not-cache-result' !== $v) { + return true; + } + --$argc; + + return false; + }); +} elseif (filter_var(getenv('SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE'), \FILTER_VALIDATE_BOOLEAN)) { + $argv[] = '--do-not-cache-result'; + ++$argc; +} + +$components = []; +$cmd = array_map('escapeshellarg', $argv); +$exit = 0; + +if (isset($argv[1]) && 'symfony' === $argv[1] && !file_exists('symfony') && file_exists('src/Symfony')) { + $argv[1] = 'src/Symfony'; +} +if (isset($argv[1]) && is_dir($argv[1]) && !file_exists($argv[1].'/phpunit.xml.dist')) { + // Find Symfony components in plain php for Windows portability + + $finder = new RecursiveDirectoryIterator($argv[1], FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::UNIX_PATHS); + $finder = new RecursiveIteratorIterator($finder); + $finder->setMaxDepth(getenv('SYMFONY_PHPUNIT_MAX_DEPTH') ?: 3); + + foreach ($finder as $file => $fileInfo) { + if ('phpunit.xml.dist' === $file) { + $components[] = dirname($fileInfo->getPathname()); + } + } + if ($components) { + array_shift($cmd); + } +} + +$cmd[0] = sprintf('%s %s --colors=%s', $PHP, escapeshellarg("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit"), '' === $getEnvVar('NO_COLOR', '') ? 'always' : 'never'); +$cmd = str_replace('%', '%%', implode(' ', $cmd)).' %1$s'; + +if ('\\' === \DIRECTORY_SEPARATOR) { + $cmd = 'cmd /v:on /d /c "('.$cmd.')%2$s"'; +} else { + $cmd .= '%2$s'; +} + +if ($components) { + $skippedTests = $_SERVER['SYMFONY_PHPUNIT_SKIPPED_TESTS'] ?? false; + $runningProcs = []; + + foreach ($components as $component) { + // Run phpunit tests in parallel + + if ($skippedTests) { + putenv("SYMFONY_PHPUNIT_SKIPPED_TESTS=$component/$skippedTests"); + } + + $c = escapeshellarg($component); + + if ($proc = proc_open(sprintf($cmd, $c, " > $c/phpunit.stdout 2> $c/phpunit.stderr"), [], $pipes)) { + $runningProcs[$component] = $proc; + } else { + $exit = 1; + echo "\033[41mKO\033[0m $component\n\n"; + } + } + + $lastOutput = null; + $lastOutputTime = null; + + while ($runningProcs) { + usleep(300000); + $terminatedProcs = []; + foreach ($runningProcs as $component => $proc) { + $procStatus = proc_get_status($proc); + if (!$procStatus['running']) { + $terminatedProcs[$component] = $procStatus['exitcode']; + unset($runningProcs[$component]); + proc_close($proc); + } + } + + if (!$terminatedProcs && 1 === count($runningProcs)) { + $component = key($runningProcs); + + $output = file_get_contents("$component/phpunit.stdout"); + $output .= file_get_contents("$component/phpunit.stderr"); + + if ($lastOutput !== $output) { + $lastOutput = $output; + $lastOutputTime = microtime(true); + } elseif (microtime(true) - $lastOutputTime > 60) { + echo "\033[41mTimeout\033[0m $component\n\n"; + + if ('\\' === \DIRECTORY_SEPARATOR) { + exec(sprintf('taskkill /F /T /PID %d 2>&1', $procStatus['pid']), $output, $exitCode); + } else { + proc_terminate(current($runningProcs)); + } + } + } + + foreach ($terminatedProcs as $component => $procStatus) { + foreach (['out', 'err'] as $file) { + $file = "$component/phpunit.std$file"; + readfile($file); + unlink($file); + } + + // Fail on any individual component failures but ignore some error codes on Windows when APCu is enabled: + // STATUS_STACK_BUFFER_OVERRUN (-1073740791/0xC0000409) + // STATUS_ACCESS_VIOLATION (-1073741819/0xC0000005) + // STATUS_HEAP_CORRUPTION (-1073740940/0xC0000374) + if ($procStatus && ('\\' !== \DIRECTORY_SEPARATOR || !extension_loaded('apcu') || !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN) || !in_array($procStatus, [-1073740791, -1073741819, -1073740940]))) { + $exit = $procStatus; + echo "\033[41mKO\033[0m $component\n\n"; + } else { + echo "\033[32mOK\033[0m $component\n\n"; + } + } + } +} elseif (!isset($argv[1]) || 'install' !== $argv[1] || file_exists('install')) { + if (!class_exists(\SymfonyExcludeListSimplePhpunit::class, false)) { + class SymfonyExcludeListSimplePhpunit + { + } + } + array_splice($argv, 1, 0, ['--colors='.('' === $getEnvVar('NO_COLOR', '') ? 'always' : 'never')]); + $_SERVER['argv'] = $argv; + $_SERVER['argc'] = ++$argc; + include "$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit"; +} + +exit($exit); diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bootstrap.php b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bootstrap.php new file mode 100644 index 000000000..f11b7ab7f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/bootstrap.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Doctrine\Common\Annotations\AnnotationRegistry; +use Doctrine\Deprecations\Deprecation; +use Symfony\Bridge\PhpUnit\DeprecationErrorHandler; + +// Detect if we need to serialize deprecations to a file. +if (in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) { + DeprecationErrorHandler::collectDeprecations($file); + + return; +} + +// Detect if we're loaded by an actual run of phpunit +if (!defined('PHPUNIT_COMPOSER_INSTALL') && !class_exists(\PHPUnit\TextUI\Command::class, false)) { + return; +} + +if (isset($fileIdentifier)) { + unset($GLOBALS['__composer_autoload_files'][$fileIdentifier]); +} + +if (class_exists(Deprecation::class)) { + Deprecation::withoutDeduplication(); + + if (\PHP_VERSION_ID < 80000) { + // Ignore deprecations about the annotation mapping driver when it's not possible to move to the attribute driver yet + Deprecation::ignoreDeprecations('https://github.com/doctrine/orm/issues/10098'); + } +} + +if (!class_exists(AnnotationRegistry::class, false) && class_exists(AnnotationRegistry::class)) { + if (method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { + AnnotationRegistry::registerUniqueLoader('class_exists'); + } elseif (method_exists(AnnotationRegistry::class, 'registerLoader')) { + AnnotationRegistry::registerLoader('class_exists'); + } +} + +if ('disabled' !== getenv('SYMFONY_DEPRECATIONS_HELPER')) { + DeprecationErrorHandler::register(getenv('SYMFONY_DEPRECATIONS_HELPER')); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/composer.json b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/composer.json new file mode 100644 index 000000000..1283dfe33 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/phpunit-bridge/composer.json @@ -0,0 +1,49 @@ +{ + "name": "symfony/phpunit-bridge", + "type": "symfony-bridge", + "description": "Provides utilities for PHPUnit, especially user deprecation notices management", + "keywords": [], + "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 EVEN ON LATEST SYMFONY VERSIONS TO ALLOW USING", + "php": "THIS BRIDGE WHEN TESTING LOWEST SYMFONY VERSIONS.", + "php": ">=7.2.5" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/error-handler": "^5.4|^6.4|^7.0", + "symfony/polyfill-php81": "^1.27" + }, + "conflict": { + "phpunit/phpunit": "<7.5|9.1.2" + }, + "autoload": { + "files": [ "bootstrap.php" ], + "psr-4": { "Symfony\\Bridge\\PhpUnit\\": "" }, + "exclude-from-classmap": [ + "/Tests/", + "/bin/" + ] + }, + "bin": [ + "bin/simple-phpunit" + ], + "minimum-stability": "dev", + "extra": { + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php b/.extlib/simplesamlphp/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php index d275f6c67..1050bb0fb 100644 --- a/.extlib/simplesamlphp/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php +++ b/.extlib/simplesamlphp/vendor/symfony/routing/Loader/Configurator/Traits/HostTrait.php @@ -28,6 +28,7 @@ final protected function addHost(RouteCollection $routes, string|array $hosts): foreach ($routes->all() as $name => $route) { if (null === $locale = $route->getDefault('_locale')) { + $priority = $routes->getPriority($name) ?? 0; $routes->remove($name); foreach ($hosts as $locale => $host) { $localizedRoute = clone $route; @@ -35,14 +36,14 @@ final protected function addHost(RouteCollection $routes, string|array $hosts): $localizedRoute->setRequirement('_locale', preg_quote($locale)); $localizedRoute->setDefault('_canonical_route', $name); $localizedRoute->setHost($host); - $routes->add($name.'.'.$locale, $localizedRoute); + $routes->add($name.'.'.$locale, $localizedRoute, $priority); } } elseif (!isset($hosts[$locale])) { throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale)); } else { $route->setHost($hosts[$locale]); $route->setRequirement('_locale', preg_quote($locale)); - $routes->add($name, $route); + $routes->add($name, $route, $routes->getPriority($name) ?? 0); } } } diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/CHANGELOG.md b/.extlib/simplesamlphp/vendor/symfony/translation/CHANGELOG.md new file mode 100644 index 000000000..5f9098c07 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/CHANGELOG.md @@ -0,0 +1,205 @@ +CHANGELOG +========= + +6.4 +--- + + * Give current locale to `LocaleSwitcher::runWithLocale()`'s callback + * Add `--as-tree` option to `translation:pull` command to write YAML messages as a tree-like structure + * [BC BREAK] Add argument `$buildDir` to `DataCollectorTranslator::warmUp()` + * Add `DataCollectorTranslatorPass` and `LoggingTranslatorPass` (moved from `FrameworkBundle`) + * Add `PhraseTranslationProvider` + +6.2.7 +----- + + * [BC BREAK] The following data providers for `ProviderFactoryTestCase` are now static: + `supportsProvider()`, `createProvider()`, `unsupportedSchemeProvider()`and `incompleteDsnProvider()` + * [BC BREAK] `ProviderTestCase::toStringProvider()` is now static + +6.2 +--- + + * Deprecate `PhpStringTokenParser` + * Deprecate `PhpExtractor` in favor of `PhpAstExtractor` + * Add `PhpAstExtractor` (requires [nikic/php-parser](https://github.com/nikic/php-parser) to be installed) + +6.1 +--- + + * Parameters implementing `TranslatableInterface` are processed + * Add the file extension to the `XliffFileDumper` constructor + +5.4 +--- + + * Add `github` format & autodetection to render errors as annotations when + running the XLIFF linter command in a Github Actions environment. + * Translation providers are not experimental anymore + +5.3 +--- + + * Add `translation:pull` and `translation:push` commands to manage translations with third-party providers + * Add `TranslatorBagInterface::getCatalogues` method + * Add support to load XLIFF string in `XliffFileLoader` + +5.2.0 +----- + + * added support for calling `trans` with ICU formatted messages + * added `PseudoLocalizationTranslator` + * added `TranslatableMessage` objects that represent a message that can be translated + * added the `t()` function to easily create `TranslatableMessage` objects + * Added support for extracting messages from `TranslatableMessage` objects + +5.1.0 +----- + + * added support for `name` attribute on `unit` element from xliff2 to be used as a translation key instead of always the `source` element + +5.0.0 +----- + + * removed support for using `null` as the locale in `Translator` + * removed `TranslatorInterface` + * removed `MessageSelector` + * removed `ChoiceMessageFormatterInterface` + * removed `PluralizationRule` + * removed `Interval` + * removed `transChoice()` methods, use the trans() method instead with a %count% parameter + * removed `FileDumper::setBackup()` and `TranslationWriter::disableBackup()` + * removed `MessageFormatter::choiceFormat()` + * added argument `$filename` to `PhpExtractor::parseTokens()` + * removed support for implicit STDIN usage in the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit. + +4.4.0 +----- + + * deprecated support for using `null` as the locale in `Translator` + * deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit. + * Marked the `TranslationDataCollector` class as `@final`. + +4.3.0 +----- + + * Improved Xliff 1.2 loader to load the original file's metadata + * Added `TranslatorPathsPass` + +4.2.0 +----- + + * Started using ICU parent locales as fallback locales. + * allow using the ICU message format using domains with the "+intl-icu" suffix + * deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter + * deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface` + * deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead + * Added `IntlFormatter` and `IntlFormatterInterface` + * added support for multiple files and directories in `XliffLintCommand` + * Marked `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` as internal + +4.1.0 +----- + + * The `FileDumper::setBackup()` method is deprecated. + * The `TranslationWriter::disableBackup()` method is deprecated. + * The `XliffFileDumper` will write "name" on the "unit" node when dumping XLIFF 2.0. + +4.0.0 +----- + + * removed the backup feature of the `FileDumper` class + * removed `TranslationWriter::writeTranslations()` method + * removed support for passing `MessageSelector` instances to the constructor of the `Translator` class + +3.4.0 +----- + + * Added `TranslationDumperPass` + * Added `TranslationExtractorPass` + * Added `TranslatorPass` + * Added `TranslationReader` and `TranslationReaderInterface` + * Added `` section to the Xliff 2.0 dumper. + * Improved Xliff 2.0 loader to load `` section. + * Added `TranslationWriterInterface` + * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write` + * added support for adding custom message formatter and decoupling the default one. + * Added `PhpExtractor` + * Added `PhpStringTokenParser` + +3.2.0 +----- + + * Added support for escaping `|` in plural translations with double pipe. + +3.1.0 +----- + + * Deprecated the backup feature of the file dumper classes. + +3.0.0 +----- + + * removed `FileDumper::format()` method. + * Changed the visibility of the locale property in `Translator` from protected to private. + +2.8.0 +----- + + * deprecated FileDumper::format(), overwrite FileDumper::formatCatalogue() instead. + * deprecated Translator::getMessages(), rely on TranslatorBagInterface::getCatalogue() instead. + * added `FileDumper::formatCatalogue` which allows format the catalogue without dumping it into file. + * added option `json_encoding` to JsonFileDumper + * added options `as_tree`, `inline` to YamlFileDumper + * added support for XLIFF 2.0. + * added support for XLIFF target and tool attributes. + * added message parameters to DataCollectorTranslator. + * [DEPRECATION] The `DiffOperation` class has been deprecated and + will be removed in Symfony 3.0, since its operation has nothing to do with 'diff', + so the class name is misleading. The `TargetOperation` class should be used for + this use-case instead. + +2.7.0 +----- + + * added DataCollectorTranslator for collecting the translated messages. + +2.6.0 +----- + + * added possibility to cache catalogues + * added TranslatorBagInterface + * added LoggingTranslator + * added Translator::getMessages() for retrieving the message catalogue as an array + +2.5.0 +----- + + * added relative file path template to the file dumpers + * added optional backup to the file dumpers + * changed IcuResFileDumper to extend FileDumper + +2.3.0 +----- + + * added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues) + * added Translator::getFallbackLocales() + * deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method + +2.2.0 +----- + + * QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3. + * [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now + throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found + and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid. + * changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException + (IcuDatFileLoader, IcuResFileLoader and QtFileLoader) + +2.1.0 +----- + + * added support for more than one fallback locale + * added support for extracting translation messages from templates (Twig and PHP) + * added dumpers for translation catalogs + * added support for QT, gettext, and ResourceBundles diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/AbstractOperation.php b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/AbstractOperation.php new file mode 100644 index 000000000..7dff58ff4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/AbstractOperation.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Base catalogues binary operation class. + * + * A catalogue binary operation performs operation on + * source (the left argument) and target (the right argument) catalogues. + * + * @author Jean-François Simon + */ +abstract class AbstractOperation implements OperationInterface +{ + public const OBSOLETE_BATCH = 'obsolete'; + public const NEW_BATCH = 'new'; + public const ALL_BATCH = 'all'; + + protected $source; + protected $target; + protected $result; + + /** + * This array stores 'all', 'new' and 'obsolete' messages for all valid domains. + * + * The data structure of this array is as follows: + * + * [ + * 'domain 1' => [ + * 'all' => [...], + * 'new' => [...], + * 'obsolete' => [...] + * ], + * 'domain 2' => [ + * 'all' => [...], + * 'new' => [...], + * 'obsolete' => [...] + * ], + * ... + * ] + * + * @var array The array that stores 'all', 'new' and 'obsolete' messages + */ + protected $messages; + + private array $domains; + + /** + * @throws LogicException + */ + public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target) + { + if ($source->getLocale() !== $target->getLocale()) { + throw new LogicException('Operated catalogues must belong to the same locale.'); + } + + $this->source = $source; + $this->target = $target; + $this->result = new MessageCatalogue($source->getLocale()); + $this->messages = []; + } + + public function getDomains(): array + { + if (!isset($this->domains)) { + $domains = []; + foreach ([$this->source, $this->target] as $catalogue) { + foreach ($catalogue->getDomains() as $domain) { + $domains[$domain] = $domain; + + if ($catalogue->all($domainIcu = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX)) { + $domains[$domainIcu] = $domainIcu; + } + } + } + + $this->domains = array_values($domains); + } + + return $this->domains; + } + + public function getMessages(string $domain): array + { + if (!\in_array($domain, $this->getDomains())) { + throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain)); + } + + if (!isset($this->messages[$domain][self::ALL_BATCH])) { + $this->processDomain($domain); + } + + return $this->messages[$domain][self::ALL_BATCH]; + } + + public function getNewMessages(string $domain): array + { + if (!\in_array($domain, $this->getDomains())) { + throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain)); + } + + if (!isset($this->messages[$domain][self::NEW_BATCH])) { + $this->processDomain($domain); + } + + return $this->messages[$domain][self::NEW_BATCH]; + } + + public function getObsoleteMessages(string $domain): array + { + if (!\in_array($domain, $this->getDomains())) { + throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain)); + } + + if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) { + $this->processDomain($domain); + } + + return $this->messages[$domain][self::OBSOLETE_BATCH]; + } + + public function getResult(): MessageCatalogueInterface + { + foreach ($this->getDomains() as $domain) { + if (!isset($this->messages[$domain])) { + $this->processDomain($domain); + } + } + + return $this->result; + } + + /** + * @param self::*_BATCH $batch + */ + public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void + { + // If MessageFormatter class does not exists, intl domains are not supported. + if (!class_exists(\MessageFormatter::class)) { + return; + } + + foreach ($this->getDomains() as $domain) { + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + $messages = match ($batch) { + self::OBSOLETE_BATCH => $this->getObsoleteMessages($domain), + self::NEW_BATCH => $this->getNewMessages($domain), + self::ALL_BATCH => $this->getMessages($domain), + default => throw new \InvalidArgumentException(sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH)), + }; + + if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) { + continue; + } + + $result = $this->getResult(); + $allIntlMessages = $result->all($intlDomain); + $currentMessages = array_diff_key($messages, $result->all($domain)); + $result->replace($currentMessages, $domain); + $result->replace($allIntlMessages + $messages, $intlDomain); + } + } + + /** + * Performs operation on source and target catalogues for the given domain and + * stores the results. + * + * @param string $domain The domain which the operation will be performed for + * + * @return void + */ + abstract protected function processDomain(string $domain); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/MergeOperation.php b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/MergeOperation.php new file mode 100644 index 000000000..1b777a843 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/MergeOperation.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Merge operation between two catalogues as follows: + * all = source ∪ target = {x: x ∈ source ∨ x ∈ target} + * new = all ∖ source = {x: x ∈ target ∧ x ∉ source} + * obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅ + * Basically, the result contains messages from both catalogues. + * + * @author Jean-François Simon + */ +class MergeOperation extends AbstractOperation +{ + /** + * @return void + */ + protected function processDomain(string $domain) + { + $this->messages[$domain] = [ + 'all' => [], + 'new' => [], + 'obsolete' => [], + ]; + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + + foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) { + if (null === $this->result->getCatalogueMetadata($key, $domain)) { + $this->result->setCatalogueMetadata($key, $value, $domain); + } + } + + foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) { + if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) { + $this->result->setCatalogueMetadata($key, $value, $intlDomain); + } + } + + foreach ($this->source->all($domain) as $id => $message) { + $this->messages[$domain]['all'][$id] = $message; + $d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain; + $this->result->add([$id => $message], $d); + if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) { + $this->result->setMetadata($id, $keyMetadata, $d); + } + } + + foreach ($this->target->all($domain) as $id => $message) { + if (!$this->source->has($id, $domain)) { + $this->messages[$domain]['all'][$id] = $message; + $this->messages[$domain]['new'][$id] = $message; + $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain; + $this->result->add([$id => $message], $d); + if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) { + $this->result->setMetadata($id, $keyMetadata, $d); + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/OperationInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/OperationInterface.php new file mode 100644 index 000000000..1fe9534e8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/OperationInterface.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Represents an operation on catalogue(s). + * + * An instance of this interface performs an operation on one or more catalogues and + * stores intermediate and final results of the operation. + * + * The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and + * the following results are stored: + * + * Messages: also called 'all', are valid messages for the given domain after the operation is performed. + * + * New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}). + * + * Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}). + * + * Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'. + * + * @author Jean-François Simon + */ +interface OperationInterface +{ + /** + * Returns domains affected by operation. + */ + public function getDomains(): array; + + /** + * Returns all valid messages ('all') after operation. + */ + public function getMessages(string $domain): array; + + /** + * Returns new messages ('new') after operation. + */ + public function getNewMessages(string $domain): array; + + /** + * Returns obsolete messages ('obsolete') after operation. + */ + public function getObsoleteMessages(string $domain): array; + + /** + * Returns resulting catalogue ('result'). + */ + public function getResult(): MessageCatalogueInterface; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/TargetOperation.php b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/TargetOperation.php new file mode 100644 index 000000000..2c0ec722e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Catalogue/TargetOperation.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Catalogue; + +use Symfony\Component\Translation\MessageCatalogueInterface; + +/** + * Target operation between two catalogues: + * intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target} + * all = intersection ∪ (target ∖ intersection) = target + * new = all ∖ source = {x: x ∈ target ∧ x ∉ source} + * obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target} + * Basically, the result contains messages from the target catalogue. + * + * @author Michael Lee + */ +class TargetOperation extends AbstractOperation +{ + /** + * @return void + */ + protected function processDomain(string $domain) + { + $this->messages[$domain] = [ + 'all' => [], + 'new' => [], + 'obsolete' => [], + ]; + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + + foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) { + if (null === $this->result->getCatalogueMetadata($key, $domain)) { + $this->result->setCatalogueMetadata($key, $value, $domain); + } + } + + foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) { + if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) { + $this->result->setCatalogueMetadata($key, $value, $intlDomain); + } + } + + // For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``, + // because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback} + // + // For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));`` + // because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback} + // + // For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))`` + // because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback} + + foreach ($this->source->all($domain) as $id => $message) { + if ($this->target->has($id, $domain)) { + $this->messages[$domain]['all'][$id] = $message; + $d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain; + $this->result->add([$id => $message], $d); + if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) { + $this->result->setMetadata($id, $keyMetadata, $d); + } + } else { + $this->messages[$domain]['obsolete'][$id] = $message; + } + } + + foreach ($this->target->all($domain) as $id => $message) { + if (!$this->source->has($id, $domain)) { + $this->messages[$domain]['all'][$id] = $message; + $this->messages[$domain]['new'][$id] = $message; + $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain; + $this->result->add([$id => $message], $d); + if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) { + $this->result->setMetadata($id, $keyMetadata, $d); + } + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/CatalogueMetadataAwareInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/CatalogueMetadataAwareInterface.php new file mode 100644 index 000000000..c845959f1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/CatalogueMetadataAwareInterface.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 Symfony\Component\Translation; + +/** + * This interface is used to get, set, and delete metadata about the Catalogue. + * + * @author Hugo Alliaume + */ +interface CatalogueMetadataAwareInterface +{ + /** + * Gets catalogue metadata for the given domain and key. + * + * Passing an empty domain will return an array with all catalogue metadata indexed by + * domain and then by key. Passing an empty key will return an array with all + * catalogue metadata for the given domain. + * + * @return mixed The value that was set or an array with the domains/keys or null + */ + public function getCatalogueMetadata(string $key = '', string $domain = 'messages'): mixed; + + /** + * Adds catalogue metadata to a message domain. + * + * @return void + */ + public function setCatalogueMetadata(string $key, mixed $value, string $domain = 'messages'); + + /** + * Deletes catalogue metadata for the given key and domain. + * + * Passing an empty domain will delete all catalogue metadata. Passing an empty key will + * delete all metadata for the given domain. + * + * @return void + */ + public function deleteCatalogueMetadata(string $key = '', string $domain = 'messages'); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPullCommand.php b/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPullCommand.php new file mode 100644 index 000000000..5d9c092c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPullCommand.php @@ -0,0 +1,184 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Command; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\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\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Translation\Catalogue\TargetOperation; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Provider\TranslationProviderCollection; +use Symfony\Component\Translation\Reader\TranslationReaderInterface; +use Symfony\Component\Translation\Writer\TranslationWriterInterface; + +/** + * @author Mathieu Santostefano + */ +#[AsCommand(name: 'translation:pull', description: 'Pull translations from a given provider.')] +final class TranslationPullCommand extends Command +{ + use TranslationTrait; + + private TranslationProviderCollection $providerCollection; + private TranslationWriterInterface $writer; + private TranslationReaderInterface $reader; + private string $defaultLocale; + private array $transPaths; + private array $enabledLocales; + + public function __construct(TranslationProviderCollection $providerCollection, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, array $transPaths = [], array $enabledLocales = []) + { + $this->providerCollection = $providerCollection; + $this->writer = $writer; + $this->reader = $reader; + $this->defaultLocale = $defaultLocale; + $this->transPaths = $transPaths; + $this->enabledLocales = $enabledLocales; + + parent::__construct(); + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('provider')) { + $suggestions->suggestValues($this->providerCollection->keys()); + + return; + } + + if ($input->mustSuggestOptionValuesFor('domains')) { + $provider = $this->providerCollection->get($input->getArgument('provider')); + + if (method_exists($provider, 'getDomains')) { + $suggestions->suggestValues($provider->getDomains()); + } + + return; + } + + if ($input->mustSuggestOptionValuesFor('locales')) { + $suggestions->suggestValues($this->enabledLocales); + + return; + } + + if ($input->mustSuggestOptionValuesFor('format')) { + $suggestions->suggestValues(['php', 'xlf', 'xlf12', 'xlf20', 'po', 'mo', 'yml', 'yaml', 'ts', 'csv', 'json', 'ini', 'res']); + } + } + + protected function configure(): void + { + $keys = $this->providerCollection->keys(); + $defaultProvider = 1 === \count($keys) ? $keys[0] : null; + + $this + ->setDefinition([ + new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider), + new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'), + new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'), + new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'), + new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'), + new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf12'), + new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Write messages as a tree-like structure. Needs --format=yaml. The given value defines the level where to switch to inline YAML'), + ]) + ->setHelp(<<<'EOF' +The %command.name% command pulls translations from the given provider. Only +new translations are pulled, existing ones are not overwritten. + +You can overwrite existing translations (and remove the missing ones on local side) by using the --force flag: + + php %command.full_name% --force provider + +Full example: + + php %command.full_name% provider --force --domains=messages --domains=validators --locales=en + +This command pulls all translations associated with the messages and validators domains for the en locale. +Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case. +Local translations for others domains and locales are ignored. +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $provider = $this->providerCollection->get($input->getArgument('provider')); + $force = $input->getOption('force'); + $intlIcu = $input->getOption('intl-icu'); + $locales = $input->getOption('locales') ?: $this->enabledLocales; + $domains = $input->getOption('domains'); + $format = $input->getOption('format'); + $asTree = (int) $input->getOption('as-tree'); + $xliffVersion = '1.2'; + + if ($intlIcu && !$force) { + $io->note('--intl-icu option only has an effect when used with --force. Here, it will be ignored.'); + } + + switch ($format) { + case 'xlf20': $xliffVersion = '2.0'; + // no break + case 'xlf12': $format = 'xlf'; + } + + $writeOptions = [ + 'path' => end($this->transPaths), + 'xliff_version' => $xliffVersion, + 'default_locale' => $this->defaultLocale, + 'as_tree' => (bool) $asTree, + 'inline' => $asTree, + ]; + + if (!$domains) { + $domains = $provider->getDomains(); + } + + $providerTranslations = $provider->read($domains, $locales); + + if ($force) { + foreach ($providerTranslations->getCatalogues() as $catalogue) { + $operation = new TargetOperation(new MessageCatalogue($catalogue->getLocale()), $catalogue); + if ($intlIcu) { + $operation->moveMessagesToIntlDomainsIfPossible(); + } + $this->writer->write($operation->getResult(), $format, $writeOptions); + } + + $io->success(sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains))); + + return 0; + } + + $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths); + + // Append pulled translations to local ones. + $localTranslations->addBag($providerTranslations->diff($localTranslations)); + + foreach ($localTranslations->getCatalogues() as $catalogue) { + $this->writer->write($catalogue, $format, $writeOptions); + } + + $io->success(sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains))); + + return 0; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPushCommand.php b/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPushCommand.php new file mode 100644 index 000000000..1d04adbc9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationPushCommand.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Command; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Translation\Provider\FilteringProvider; +use Symfony\Component\Translation\Provider\TranslationProviderCollection; +use Symfony\Component\Translation\Reader\TranslationReaderInterface; +use Symfony\Component\Translation\TranslatorBag; + +/** + * @author Mathieu Santostefano + */ +#[AsCommand(name: 'translation:push', description: 'Push translations to a given provider.')] +final class TranslationPushCommand extends Command +{ + use TranslationTrait; + + private TranslationProviderCollection $providers; + private TranslationReaderInterface $reader; + private array $transPaths; + private array $enabledLocales; + + public function __construct(TranslationProviderCollection $providers, TranslationReaderInterface $reader, array $transPaths = [], array $enabledLocales = []) + { + $this->providers = $providers; + $this->reader = $reader; + $this->transPaths = $transPaths; + $this->enabledLocales = $enabledLocales; + + parent::__construct(); + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestArgumentValuesFor('provider')) { + $suggestions->suggestValues($this->providers->keys()); + + return; + } + + if ($input->mustSuggestOptionValuesFor('domains')) { + $provider = $this->providers->get($input->getArgument('provider')); + + if ($provider && method_exists($provider, 'getDomains')) { + $domains = $provider->getDomains(); + $suggestions->suggestValues($domains); + } + + return; + } + + if ($input->mustSuggestOptionValuesFor('locales')) { + $suggestions->suggestValues($this->enabledLocales); + } + } + + protected function configure(): void + { + $keys = $this->providers->keys(); + $defaultProvider = 1 === \count($keys) ? $keys[0] : null; + + $this + ->setDefinition([ + new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider), + new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'), + new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'), + new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'), + new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales), + ]) + ->setHelp(<<<'EOF' +The %command.name% command pushes translations to the given provider. Only new +translations are pushed, existing ones are not overwritten. + +You can overwrite existing translations by using the --force flag: + + php %command.full_name% --force provider + +You can delete provider translations which are not present locally by using the --delete-missing flag: + + php %command.full_name% --delete-missing provider + +Full example: + + php %command.full_name% provider --force --delete-missing --domains=messages --domains=validators --locales=en + +This command pushes all translations associated with the messages and validators domains for the en locale. +Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case. +Provider translations for others domains and locales are ignored. +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $provider = $this->providers->get($input->getArgument('provider')); + + if (!$this->enabledLocales) { + throw new InvalidArgumentException(sprintf('You must define "framework.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME))); + } + + $io = new SymfonyStyle($input, $output); + $domains = $input->getOption('domains'); + $locales = $input->getOption('locales'); + $force = $input->getOption('force'); + $deleteMissing = $input->getOption('delete-missing'); + + if (!$domains && $provider instanceof FilteringProvider) { + $domains = $provider->getDomains(); + } + + // Reading local translations must be done after retrieving the domains from the provider + // in order to manage only translations from configured domains + $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths); + + if (!$domains) { + $domains = $this->getDomainsFromTranslatorBag($localTranslations); + } + + if (!$deleteMissing && $force) { + $provider->write($localTranslations); + + $io->success(sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains))); + + return 0; + } + + $providerTranslations = $provider->read($domains, $locales); + + if ($deleteMissing) { + $provider->delete($providerTranslations->diff($localTranslations)); + + $io->success(sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains))); + + // Read provider translations again, after missing translations deletion, + // to avoid push freshly deleted translations. + $providerTranslations = $provider->read($domains, $locales); + } + + $translationsToWrite = $localTranslations->diff($providerTranslations); + + if ($force) { + $translationsToWrite->addBag($localTranslations->intersect($providerTranslations)); + } + + $provider->write($translationsToWrite); + + $io->success(sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains))); + + return 0; + } + + private function getDomainsFromTranslatorBag(TranslatorBag $translatorBag): array + { + $domains = []; + + foreach ($translatorBag->getCatalogues() as $catalogue) { + $domains += $catalogue->getDomains(); + } + + return array_unique($domains); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationTrait.php b/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationTrait.php new file mode 100644 index 000000000..eafaffd3f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Command/TranslationTrait.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Command; + +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\MessageCatalogueInterface; +use Symfony\Component\Translation\TranslatorBag; + +/** + * @internal + */ +trait TranslationTrait +{ + private function readLocalTranslations(array $locales, array $domains, array $transPaths): TranslatorBag + { + $bag = new TranslatorBag(); + + foreach ($locales as $locale) { + $catalogue = new MessageCatalogue($locale); + foreach ($transPaths as $path) { + $this->reader->read($path, $catalogue); + } + + if ($domains) { + foreach ($domains as $domain) { + $bag->addCatalogue($this->filterCatalogue($catalogue, $domain)); + } + } else { + $bag->addCatalogue($catalogue); + } + } + + return $bag; + } + + private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue + { + $filteredCatalogue = new MessageCatalogue($catalogue->getLocale()); + + // extract intl-icu messages only + $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX; + if ($intlMessages = $catalogue->all($intlDomain)) { + $filteredCatalogue->add($intlMessages, $intlDomain); + } + + // extract all messages and subtract intl-icu messages + if ($messages = array_diff($catalogue->all($domain), $intlMessages)) { + $filteredCatalogue->add($messages, $domain); + } + foreach ($catalogue->getResources() as $resource) { + $filteredCatalogue->addResource($resource); + } + + if ($metadata = $catalogue->getMetadata('', $intlDomain)) { + foreach ($metadata as $k => $v) { + $filteredCatalogue->setMetadata($k, $v, $intlDomain); + } + } + + if ($metadata = $catalogue->getMetadata('', $domain)) { + foreach ($metadata as $k => $v) { + $filteredCatalogue->setMetadata($k, $v, $domain); + } + } + + return $filteredCatalogue; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Command/XliffLintCommand.php b/.extlib/simplesamlphp/vendor/symfony/translation/Command/XliffLintCommand.php new file mode 100644 index 000000000..ba946389e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Command/XliffLintCommand.php @@ -0,0 +1,285 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Command; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\CI\GithubActionReporter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Util\XliffUtils; + +/** + * Validates XLIFF files syntax and outputs encountered errors. + * + * @author Grégoire Pineau + * @author Robin Chalas + * @author Javier Eguiluz + */ +#[AsCommand(name: 'lint:xliff', description: 'Lint an XLIFF file and outputs encountered errors')] +class XliffLintCommand extends Command +{ + private string $format; + private bool $displayCorrectFiles; + private ?\Closure $directoryIteratorProvider; + private ?\Closure $isReadableProvider; + private bool $requireStrictFileNames; + + public function __construct(?string $name = null, ?callable $directoryIteratorProvider = null, ?callable $isReadableProvider = null, bool $requireStrictFileNames = true) + { + parent::__construct($name); + + $this->directoryIteratorProvider = null === $directoryIteratorProvider ? null : $directoryIteratorProvider(...); + $this->isReadableProvider = null === $isReadableProvider ? null : $isReadableProvider(...); + $this->requireStrictFileNames = $requireStrictFileNames; + } + + /** + * @return void + */ + protected function configure() + { + $this + ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') + ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions()))) + ->setHelp(<<%command.name% command lints an XLIFF file and outputs to STDOUT +the first encountered syntax error. + +You can validates XLIFF contents passed from STDIN: + + cat filename | php %command.full_name% - + +You can also validate the syntax of a file: + + php %command.full_name% filename + +Or of a whole directory: + + php %command.full_name% dirname + php %command.full_name% dirname --format=json + +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $filenames = (array) $input->getArgument('filename'); + $this->format = $input->getOption('format') ?? (GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt'); + $this->displayCorrectFiles = $output->isVerbose(); + + if (['-'] === $filenames) { + return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]); + } + + if (!$filenames) { + throw new RuntimeException('Please provide a filename or pipe file content to STDIN.'); + } + + $filesInfo = []; + foreach ($filenames as $filename) { + if (!$this->isReadable($filename)) { + throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename)); + } + + foreach ($this->getFiles($filename) as $file) { + $filesInfo[] = $this->validate(file_get_contents($file), $file); + } + } + + return $this->display($io, $filesInfo); + } + + private function validate(string $content, ?string $file = null): array + { + $errors = []; + + // Avoid: Warning DOMDocument::loadXML(): Empty string supplied as input + if ('' === trim($content)) { + return ['file' => $file, 'valid' => true]; + } + + $internal = libxml_use_internal_errors(true); + + $document = new \DOMDocument(); + $document->loadXML($content); + + if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) { + $normalizedLocalePattern = sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/')); + // strict file names require translation files to be named '____.locale.xlf' + // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed + // also, the regexp matching must be case-insensitive, as defined for 'target-language' values + // http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language + $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern); + + if (0 === preg_match($expectedFilenamePattern, basename($file))) { + $errors[] = [ + 'line' => -1, + 'column' => -1, + 'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage), + ]; + } + } + + foreach (XliffUtils::validateSchema($document) as $xmlError) { + $errors[] = [ + 'line' => $xmlError['line'], + 'column' => $xmlError['column'], + 'message' => $xmlError['message'], + ]; + } + + libxml_clear_errors(); + libxml_use_internal_errors($internal); + + return ['file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors]; + } + + private function display(SymfonyStyle $io, array $files): int + { + return match ($this->format) { + 'txt' => $this->displayTxt($io, $files), + 'json' => $this->displayJson($io, $files), + 'github' => $this->displayTxt($io, $files, true), + default => throw new InvalidArgumentException(sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))), + }; + } + + private function displayTxt(SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false): int + { + $countFiles = \count($filesInfo); + $erroredFiles = 0; + $githubReporter = $errorAsGithubAnnotations ? new GithubActionReporter($io) : null; + + foreach ($filesInfo as $info) { + if ($info['valid'] && $this->displayCorrectFiles) { + $io->comment('OK'.($info['file'] ? sprintf(' in %s', $info['file']) : '')); + } elseif (!$info['valid']) { + ++$erroredFiles; + $io->text(' ERROR '.($info['file'] ? sprintf(' in %s', $info['file']) : '')); + $io->listing(array_map(function ($error) use ($info, $githubReporter) { + // general document errors have a '-1' line number + $line = -1 === $error['line'] ? null : $error['line']; + + $githubReporter?->error($error['message'], $info['file'], $line, null !== $line ? $error['column'] : null); + + return null === $line ? $error['message'] : sprintf('Line %d, Column %d: %s', $line, $error['column'], $error['message']); + }, $info['messages'])); + } + } + + if (0 === $erroredFiles) { + $io->success(sprintf('All %d XLIFF files contain valid syntax.', $countFiles)); + } else { + $io->warning(sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles)); + } + + return min($erroredFiles, 1); + } + + private function displayJson(SymfonyStyle $io, array $filesInfo): int + { + $errors = 0; + + array_walk($filesInfo, function (&$v) use (&$errors) { + $v['file'] = (string) $v['file']; + if (!$v['valid']) { + ++$errors; + } + }); + + $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES)); + + return min($errors, 1); + } + + /** + * @return iterable<\SplFileInfo> + */ + private function getFiles(string $fileOrDirectory): iterable + { + if (is_file($fileOrDirectory)) { + yield new \SplFileInfo($fileOrDirectory); + + return; + } + + foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) { + if (!\in_array($file->getExtension(), ['xlf', 'xliff'])) { + continue; + } + + yield $file; + } + } + + /** + * @return iterable<\SplFileInfo> + */ + private function getDirectoryIterator(string $directory): iterable + { + $default = fn ($directory) => new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + + if (null !== $this->directoryIteratorProvider) { + return ($this->directoryIteratorProvider)($directory, $default); + } + + return $default($directory); + } + + private function isReadable(string $fileOrDirectory): bool + { + $default = fn ($fileOrDirectory) => is_readable($fileOrDirectory); + + if (null !== $this->isReadableProvider) { + return ($this->isReadableProvider)($fileOrDirectory, $default); + } + + return $default($fileOrDirectory); + } + + private function getTargetLanguageFromFile(\DOMDocument $xliffContents): ?string + { + foreach ($xliffContents->getElementsByTagName('file')[0]->attributes ?? [] as $attribute) { + if ('target-language' === $attribute->nodeName) { + return $attribute->nodeValue; + } + } + + return null; + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestOptionValuesFor('format')) { + $suggestions->suggestValues($this->getAvailableFormatOptions()); + } + } + + private function getAvailableFormatOptions(): array + { + return ['txt', 'json', 'github']; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DataCollector/TranslationDataCollector.php b/.extlib/simplesamlphp/vendor/symfony/translation/DataCollector/TranslationDataCollector.php new file mode 100644 index 000000000..d4f49cc66 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DataCollector/TranslationDataCollector.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; +use Symfony\Component\Translation\DataCollectorTranslator; +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * @author Abdellatif Ait boudad + * + * @final + */ +class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface +{ + private DataCollectorTranslator $translator; + + public function __construct(DataCollectorTranslator $translator) + { + $this->translator = $translator; + } + + public function lateCollect(): void + { + $messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages()); + + $this->data += $this->computeCount($messages); + $this->data['messages'] = $messages; + + $this->data = $this->cloneVar($this->data); + } + + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void + { + $this->data['locale'] = $this->translator->getLocale(); + $this->data['fallback_locales'] = $this->translator->getFallbackLocales(); + } + + public function reset(): void + { + $this->data = []; + } + + public function getMessages(): array|Data + { + return $this->data['messages'] ?? []; + } + + public function getCountMissings(): int + { + return $this->data[DataCollectorTranslator::MESSAGE_MISSING] ?? 0; + } + + public function getCountFallbacks(): int + { + return $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] ?? 0; + } + + public function getCountDefines(): int + { + return $this->data[DataCollectorTranslator::MESSAGE_DEFINED] ?? 0; + } + + public function getLocale(): ?string + { + return !empty($this->data['locale']) ? $this->data['locale'] : null; + } + + /** + * @internal + */ + public function getFallbackLocales(): Data|array + { + return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : []; + } + + public function getName(): string + { + return 'translation'; + } + + private function sanitizeCollectedMessages(array $messages): array + { + $result = []; + foreach ($messages as $key => $message) { + $messageId = $message['locale'].$message['domain'].$message['id']; + + if (!isset($result[$messageId])) { + $message['count'] = 1; + $message['parameters'] = !empty($message['parameters']) ? [$message['parameters']] : []; + $messages[$key]['translation'] = $this->sanitizeString($message['translation']); + $result[$messageId] = $message; + } else { + if (!empty($message['parameters'])) { + $result[$messageId]['parameters'][] = $message['parameters']; + } + + ++$result[$messageId]['count']; + } + + unset($messages[$key]); + } + + return $result; + } + + private function computeCount(array $messages): array + { + $count = [ + DataCollectorTranslator::MESSAGE_DEFINED => 0, + DataCollectorTranslator::MESSAGE_MISSING => 0, + DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0, + ]; + + foreach ($messages as $message) { + ++$count[$message['state']]; + } + + return $count; + } + + private function sanitizeString(string $string, int $length = 80): string + { + $string = trim(preg_replace('/\s+/', ' ', $string)); + + if (false !== $encoding = mb_detect_encoding($string, null, true)) { + if (mb_strlen($string, $encoding) > $length) { + return mb_substr($string, 0, $length - 3, $encoding).'...'; + } + } elseif (\strlen($string) > $length) { + return substr($string, 0, $length - 3).'...'; + } + + return $string; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DataCollectorTranslator.php b/.extlib/simplesamlphp/vendor/symfony/translation/DataCollectorTranslator.php new file mode 100644 index 000000000..a2832ee8e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DataCollectorTranslator.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Abdellatif Ait boudad + */ +class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, WarmableInterface +{ + public const MESSAGE_DEFINED = 0; + public const MESSAGE_MISSING = 1; + public const MESSAGE_EQUALS_FALLBACK = 2; + + private TranslatorInterface $translator; + private array $messages = []; + + /** + * @param TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator + */ + public function __construct(TranslatorInterface $translator) + { + if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) { + throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator))); + } + + $this->translator = $translator; + } + + public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string + { + $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale); + $this->collectMessage($locale, $domain, $id, $trans, $parameters); + + return $trans; + } + + /** + * @return void + */ + public function setLocale(string $locale) + { + $this->translator->setLocale($locale); + } + + public function getLocale(): string + { + return $this->translator->getLocale(); + } + + public function getCatalogue(?string $locale = null): MessageCatalogueInterface + { + return $this->translator->getCatalogue($locale); + } + + public function getCatalogues(): array + { + return $this->translator->getCatalogues(); + } + + public function warmUp(string $cacheDir, ?string $buildDir = null): array + { + if ($this->translator instanceof WarmableInterface) { + return (array) $this->translator->warmUp($cacheDir, $buildDir); + } + + return []; + } + + /** + * Gets the fallback locales. + */ + public function getFallbackLocales(): array + { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { + return $this->translator->getFallbackLocales(); + } + + return []; + } + + /** + * @return mixed + */ + public function __call(string $method, array $args) + { + return $this->translator->{$method}(...$args); + } + + public function getCollectedMessages(): array + { + return $this->messages; + } + + private function collectMessage(?string $locale, ?string $domain, string $id, string $translation, ?array $parameters = []): void + { + $domain ??= 'messages'; + + $catalogue = $this->translator->getCatalogue($locale); + $locale = $catalogue->getLocale(); + $fallbackLocale = null; + if ($catalogue->defines($id, $domain)) { + $state = self::MESSAGE_DEFINED; + } elseif ($catalogue->has($id, $domain)) { + $state = self::MESSAGE_EQUALS_FALLBACK; + + $fallbackCatalogue = $catalogue->getFallbackCatalogue(); + while ($fallbackCatalogue) { + if ($fallbackCatalogue->defines($id, $domain)) { + $fallbackLocale = $fallbackCatalogue->getLocale(); + break; + } + $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue(); + } + } else { + $state = self::MESSAGE_MISSING; + } + + $this->messages[] = [ + 'locale' => $locale, + 'fallbackLocale' => $fallbackLocale, + 'domain' => $domain, + 'id' => $id, + 'translation' => $translation, + 'parameters' => $parameters, + 'state' => $state, + 'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null, + ]; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php new file mode 100644 index 000000000..cdf63be4b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Translation\TranslatorBagInterface; + +/** + * @author Christian Flothmann + */ +class DataCollectorTranslatorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->has('translator')) { + return; + } + + $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); + + if (!is_subclass_of($translatorClass, TranslatorBagInterface::class)) { + $container->removeDefinition('translator.data_collector'); + $container->removeDefinition('data_collector.translation'); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php new file mode 100644 index 000000000..c21552f97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Abdellatif Ait boudad + */ +class LoggingTranslatorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) { + return; + } + + if (!$container->hasParameter('translator.logging') || !$container->getParameter('translator.logging')) { + return; + } + + $translatorAlias = $container->getAlias('translator'); + $definition = $container->getDefinition((string) $translatorAlias); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); + + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias)); + } + + if (!$r->isSubclassOf(TranslatorInterface::class) || !$r->isSubclassOf(TranslatorBagInterface::class)) { + return; + } + + $container->getDefinition('translator.logging')->setDecoratedService('translator'); + $warmer = $container->getDefinition('translation.warmer'); + $subscriberAttributes = $warmer->getTag('container.service_subscriber'); + $warmer->clearTag('container.service_subscriber'); + + foreach ($subscriberAttributes as $k => $v) { + if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) { + $warmer->addTag('container.service_subscriber', $v); + } + } + $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php new file mode 100644 index 000000000..2ece6ac7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged translation.formatter services to translation writer. + */ +class TranslationDumperPass implements CompilerPassInterface +{ + /** + * @return void + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('translation.writer')) { + return; + } + + $definition = $container->getDefinition('translation.writer'); + + foreach ($container->findTaggedServiceIds('translation.dumper', true) as $id => $attributes) { + $definition->addMethodCall('addDumper', [$attributes[0]['alias'], new Reference($id)]); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php new file mode 100644 index 000000000..1baf9341e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged translation.extractor services to translation extractor. + */ +class TranslationExtractorPass implements CompilerPassInterface +{ + /** + * @return void + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('translation.extractor')) { + return; + } + + $definition = $container->getDefinition('translation.extractor'); + + foreach ($container->findTaggedServiceIds('translation.extractor', true) as $id => $attributes) { + if (!isset($attributes[0]['alias'])) { + throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id)); + } + + $definition->addMethodCall('addExtractor', [$attributes[0]['alias'], new Reference($id)]); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPass.php b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPass.php new file mode 100644 index 000000000..dd6ea3c83 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPass.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 Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class TranslatorPass implements CompilerPassInterface +{ + /** + * @return void + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('translator.default')) { + return; + } + + $loaders = []; + $loaderRefs = []; + foreach ($container->findTaggedServiceIds('translation.loader', true) as $id => $attributes) { + $loaderRefs[$id] = new Reference($id); + $loaders[$id][] = $attributes[0]['alias']; + if (isset($attributes[0]['legacy-alias'])) { + $loaders[$id][] = $attributes[0]['legacy-alias']; + } + } + + if ($container->hasDefinition('translation.reader')) { + $definition = $container->getDefinition('translation.reader'); + foreach ($loaders as $id => $formats) { + foreach ($formats as $format) { + $definition->addMethodCall('addLoader', [$format, $loaderRefs[$id]]); + } + } + } + + $container + ->findDefinition('translator.default') + ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs)) + ->replaceArgument(3, $loaders) + ; + + if ($container->hasDefinition('validator') && $container->hasDefinition('translation.extractor.visitor.constraint')) { + $constraintVisitorDefinition = $container->getDefinition('translation.extractor.visitor.constraint'); + $constraintClassNames = []; + + foreach ($container->getDefinitions() as $definition) { + if (!$definition->hasTag('validator.constraint_validator')) { + continue; + } + // Resolve constraint validator FQCN even if defined as %foo.validator.class% parameter + $className = $container->getParameterBag()->resolveValue($definition->getClass()); + // Extraction of the constraint class name from the Constraint Validator FQCN + $constraintClassNames[] = str_replace('Validator', '', substr(strrchr($className, '\\'), 1)); + } + + $constraintVisitorDefinition->setArgument(0, $constraintClassNames); + } + + if (!$container->hasParameter('twig.default_path')) { + return; + } + + $paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(1)); + if ($container->hasDefinition('console.command.translation_debug')) { + $definition = $container->getDefinition('console.command.translation_debug'); + $definition->replaceArgument(4, $container->getParameter('twig.default_path')); + + if (\count($definition->getArguments()) > 6) { + $definition->replaceArgument(6, $paths); + } + } + if ($container->hasDefinition('console.command.translation_extract')) { + $definition = $container->getDefinition('console.command.translation_extract'); + $definition->replaceArgument(5, $container->getParameter('twig.default_path')); + + if (\count($definition->getArguments()) > 7) { + $definition->replaceArgument(7, $paths); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php new file mode 100644 index 000000000..1756e3c8c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; + +/** + * @author Yonel Ceruto + */ +class TranslatorPathsPass extends AbstractRecursivePass +{ + protected bool $skipScalars = true; + + private int $level = 0; + + /** + * @var array + */ + private array $paths = []; + + /** + * @var array + */ + private array $definitions = []; + + /** + * @var array> + */ + private array $controllers = []; + + /** + * @return void + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('translator')) { + return; + } + + foreach ($this->findControllerArguments($container) as $controller => $argument) { + $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller)); + if ($container->hasDefinition($id)) { + [$locatorRef] = $argument->getValues(); + $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true; + } + } + + try { + parent::process($container); + + $paths = []; + foreach ($this->paths as $class => $_) { + if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) { + $paths[] = $r->getFileName(); + foreach ($r->getTraits() as $trait) { + $paths[] = $trait->getFileName(); + } + } + } + if ($paths) { + if ($container->hasDefinition('console.command.translation_debug')) { + $definition = $container->getDefinition('console.command.translation_debug'); + $definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths)); + } + if ($container->hasDefinition('console.command.translation_extract')) { + $definition = $container->getDefinition('console.command.translation_extract'); + $definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths)); + } + } + } finally { + $this->level = 0; + $this->paths = []; + $this->definitions = []; + } + } + + protected function processValue(mixed $value, bool $isRoot = false): mixed + { + if ($value instanceof Reference) { + if ('translator' === (string) $value) { + for ($i = $this->level - 1; $i >= 0; --$i) { + $class = $this->definitions[$i]->getClass(); + + if (ServiceLocator::class === $class) { + if (!isset($this->controllers[$this->currentId])) { + continue; + } + foreach ($this->controllers[$this->currentId] as $class => $_) { + $this->paths[$class] = true; + } + } else { + $this->paths[$class] = true; + } + + break; + } + } + + return $value; + } + + if ($value instanceof Definition) { + $this->definitions[$this->level++] = $value; + $value = parent::processValue($value, $isRoot); + unset($this->definitions[--$this->level]); + + return $value; + } + + return parent::processValue($value, $isRoot); + } + + private function findControllerArguments(ContainerBuilder $container): array + { + if (!$container->has('argument_resolver.service')) { + return []; + } + $resolverDef = $container->findDefinition('argument_resolver.service'); + + if (TraceableValueResolver::class === $resolverDef->getClass()) { + $resolverDef = $container->getDefinition($resolverDef->getArgument(0)); + } + + $argument = $resolverDef->getArgument(0); + if ($argument instanceof Reference) { + $argument = $container->getDefinition($argument); + } + + return $argument->getArgument(0); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/CsvFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/CsvFileDumper.php new file mode 100644 index 000000000..a4ae476b3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/CsvFileDumper.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * CsvFileDumper generates a csv formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class CsvFileDumper extends FileDumper +{ + private string $delimiter = ';'; + private string $enclosure = '"'; + + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $handle = fopen('php://memory', 'r+'); + + foreach ($messages->all($domain) as $source => $target) { + fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure, '\\'); + } + + rewind($handle); + $output = stream_get_contents($handle); + fclose($handle); + + return $output; + } + + /** + * Sets the delimiter and escape character for CSV. + * + * @return void + */ + public function setCsvControl(string $delimiter = ';', string $enclosure = '"') + { + $this->delimiter = $delimiter; + $this->enclosure = $enclosure; + } + + protected function getExtension(): string + { + return 'csv'; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/DumperInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/DumperInterface.php new file mode 100644 index 000000000..6bf42931e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/DumperInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * DumperInterface is the interface implemented by all translation dumpers. + * There is no common option. + * + * @author Michel Salib + */ +interface DumperInterface +{ + /** + * Dumps the message catalogue. + * + * @param array $options Options that are used by the dumper + * + * @return void + */ + public function dump(MessageCatalogue $messages, array $options = []); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/FileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/FileDumper.php new file mode 100644 index 000000000..e30d4770e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/FileDumper.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s). + * + * Options: + * - path (mandatory): the directory where the files should be saved + * + * @author Michel Salib + */ +abstract class FileDumper implements DumperInterface +{ + /** + * A template for the relative paths to files. + * + * @var string + */ + protected $relativePathTemplate = '%domain%.%locale%.%extension%'; + + /** + * Sets the template for the relative paths to files. + * + * @return void + */ + public function setRelativePathTemplate(string $relativePathTemplate) + { + $this->relativePathTemplate = $relativePathTemplate; + } + + /** + * @return void + */ + public function dump(MessageCatalogue $messages, array $options = []) + { + if (!\array_key_exists('path', $options)) { + throw new InvalidArgumentException('The file dumper needs a path option.'); + } + + // save a file for each domain + foreach ($messages->getDomains() as $domain) { + $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale()); + if (!file_exists($fullpath)) { + $directory = \dirname($fullpath); + if (!file_exists($directory) && !@mkdir($directory, 0777, true)) { + throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory)); + } + } + + $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX; + $intlMessages = $messages->all($intlDomain); + + if ($intlMessages) { + $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale()); + file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options)); + + $messages->replace([], $intlDomain); + + try { + if ($messages->all($domain)) { + file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options)); + } + continue; + } finally { + $messages->replace($intlMessages, $intlDomain); + } + } + + file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options)); + } + } + + /** + * Transforms a domain of a message catalogue to its string representation. + */ + abstract public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string; + + /** + * Gets the file extension of the dumper. + */ + abstract protected function getExtension(): string; + + /** + * Gets the relative file path using the template. + */ + private function getRelativePath(string $domain, string $locale): string + { + return strtr($this->relativePathTemplate, [ + '%domain%' => $domain, + '%locale%' => $locale, + '%extension%' => $this->getExtension(), + ]); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/IcuResFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/IcuResFileDumper.php new file mode 100644 index 000000000..72c1ec089 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/IcuResFileDumper.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class IcuResFileDumper extends FileDumper +{ + protected $relativePathTemplate = '%domain%/%locale%.%extension%'; + + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $data = $indexes = $resources = ''; + + foreach ($messages->all($domain) as $source => $target) { + $indexes .= pack('v', \strlen($data) + 28); + $data .= $source."\0"; + } + + $data .= $this->writePadding($data); + + $keyTop = $this->getPosition($data); + + foreach ($messages->all($domain) as $source => $target) { + $resources .= pack('V', $this->getPosition($data)); + + $data .= pack('V', \strlen($target)) + .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8') + .$this->writePadding($data) + ; + } + + $resOffset = $this->getPosition($data); + + $data .= pack('v', \count($messages->all($domain))) + .$indexes + .$this->writePadding($data) + .$resources + ; + + $bundleTop = $this->getPosition($data); + + $root = pack('V7', + $resOffset + (2 << 28), // Resource Offset + Resource Type + 6, // Index length + $keyTop, // Index keys top + $bundleTop, // Index resources top + $bundleTop, // Index bundle top + \count($messages->all($domain)), // Index max table length + 0 // Index attributes + ); + + $header = pack('vC2v4C12@32', + 32, // Header size + 0xDA, 0x27, // Magic number 1 and 2 + 20, 0, 0, 2, // Rest of the header, ..., Size of a char + 0x52, 0x65, 0x73, 0x42, // Data format identifier + 1, 2, 0, 0, // Data version + 1, 4, 0, 0 // Unicode version + ); + + return $header.$root.$data; + } + + private function writePadding(string $data): ?string + { + $padding = \strlen($data) % 4; + + return $padding ? str_repeat("\xAA", 4 - $padding) : null; + } + + private function getPosition(string $data): float|int + { + return (\strlen($data) + 28) / 4; + } + + protected function getExtension(): string + { + return 'res'; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/IniFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/IniFileDumper.php new file mode 100644 index 000000000..6cbdef606 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/IniFileDumper.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 Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IniFileDumper generates an ini formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class IniFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $output = ''; + + foreach ($messages->all($domain) as $source => $target) { + $escapeTarget = str_replace('"', '\"', $target); + $output .= $source.'="'.$escapeTarget."\"\n"; + } + + return $output; + } + + protected function getExtension(): string + { + return 'ini'; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/JsonFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/JsonFileDumper.php new file mode 100644 index 000000000..e5035397f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/JsonFileDumper.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * JsonFileDumper generates an json formatted string representation of a message catalogue. + * + * @author singles + */ +class JsonFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT; + + return json_encode($messages->all($domain), $flags); + } + + protected function getExtension(): string + { + return 'json'; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/MoFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/MoFileDumper.php new file mode 100644 index 000000000..9ded5f4ef --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/MoFileDumper.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Loader\MoFileLoader; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * MoFileDumper generates a gettext formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class MoFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $sources = $targets = $sourceOffsets = $targetOffsets = ''; + $offsets = []; + $size = 0; + + foreach ($messages->all($domain) as $source => $target) { + $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]); + $sources .= "\0".$source; + $targets .= "\0".$target; + ++$size; + } + + $header = [ + 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC, + 'formatRevision' => 0, + 'count' => $size, + 'offsetId' => MoFileLoader::MO_HEADER_SIZE, + 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size), + 'sizeHashes' => 0, + 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size), + ]; + + $sourcesSize = \strlen($sources); + $sourcesStart = $header['offsetHashes'] + 1; + + foreach ($offsets as $offset) { + $sourceOffsets .= $this->writeLong($offset[1]) + .$this->writeLong($offset[0] + $sourcesStart); + $targetOffsets .= $this->writeLong($offset[3]) + .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize); + } + + $output = implode('', array_map($this->writeLong(...), $header)) + .$sourceOffsets + .$targetOffsets + .$sources + .$targets + ; + + return $output; + } + + protected function getExtension(): string + { + return 'mo'; + } + + private function writeLong(mixed $str): string + { + return pack('V*', $str); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/PhpFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/PhpFileDumper.php new file mode 100644 index 000000000..51e90665d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/PhpFileDumper.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PhpFileDumper generates PHP files from a message catalogue. + * + * @author Michel Salib + */ +class PhpFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + return "all($domain), true).";\n"; + } + + protected function getExtension(): string + { + return 'php'; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/PoFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/PoFileDumper.php new file mode 100644 index 000000000..a2d0deb78 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/PoFileDumper.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PoFileDumper generates a gettext formatted string representation of a message catalogue. + * + * @author Stealth35 + */ +class PoFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $output = 'msgid ""'."\n"; + $output .= 'msgstr ""'."\n"; + $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n"; + $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n"; + $output .= '"Language: '.$messages->getLocale().'\n"'."\n"; + $output .= "\n"; + + $newLine = false; + foreach ($messages->all($domain) as $source => $target) { + if ($newLine) { + $output .= "\n"; + } else { + $newLine = true; + } + $metadata = $messages->getMetadata($source, $domain); + + if (isset($metadata['comments'])) { + $output .= $this->formatComments($metadata['comments']); + } + if (isset($metadata['flags'])) { + $output .= $this->formatComments(implode(',', (array) $metadata['flags']), ','); + } + if (isset($metadata['sources'])) { + $output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':'); + } + + $sourceRules = $this->getStandardRules($source); + $targetRules = $this->getStandardRules($target); + if (2 == \count($sourceRules) && [] !== $targetRules) { + $output .= sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0])); + $output .= sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1])); + foreach ($targetRules as $i => $targetRule) { + $output .= sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule)); + } + } else { + $output .= sprintf('msgid "%s"'."\n", $this->escape($source)); + $output .= sprintf('msgstr "%s"'."\n", $this->escape($target)); + } + } + + return $output; + } + + private function getStandardRules(string $id): array + { + // Partly copied from TranslatorTrait::trans. + $parts = []; + if (preg_match('/^\|++$/', $id)) { + $parts = explode('|', $id); + } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) { + $parts = $matches[0]; + } + + $intervalRegexp = <<<'EOF' +/^(?P + ({\s* + (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) + \s*}) + + | + + (?P[\[\]]) + \s* + (?P-Inf|\-?\d+(\.\d+)?) + \s*,\s* + (?P\+?Inf|\-?\d+(\.\d+)?) + \s* + (?P[\[\]]) +)\s*(?P.*?)$/xs +EOF; + + $standardRules = []; + foreach ($parts as $part) { + $part = trim(str_replace('||', '|', $part)); + + if (preg_match($intervalRegexp, $part)) { + // Explicit rule is not a standard rule. + return []; + } else { + $standardRules[] = $part; + } + } + + return $standardRules; + } + + protected function getExtension(): string + { + return 'po'; + } + + private function escape(string $str): string + { + return addcslashes($str, "\0..\37\42\134"); + } + + private function formatComments(string|array $comments, string $prefix = ''): ?string + { + $output = null; + + foreach ((array) $comments as $comment) { + $output .= sprintf('#%s %s'."\n", $prefix, $comment); + } + + return $output; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/QtFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/QtFileDumper.php new file mode 100644 index 000000000..0373e9c10 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/QtFileDumper.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * QtFileDumper generates ts files from a message catalogue. + * + * @author Benjamin Eberlei + */ +class QtFileDumper extends FileDumper +{ + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->formatOutput = true; + $ts = $dom->appendChild($dom->createElement('TS')); + $context = $ts->appendChild($dom->createElement('context')); + $context->appendChild($dom->createElement('name', $domain)); + + foreach ($messages->all($domain) as $source => $target) { + $message = $context->appendChild($dom->createElement('message')); + $metadata = $messages->getMetadata($source, $domain); + if (isset($metadata['sources'])) { + foreach ((array) $metadata['sources'] as $location) { + $loc = explode(':', $location, 2); + $location = $message->appendChild($dom->createElement('location')); + $location->setAttribute('filename', $loc[0]); + if (isset($loc[1])) { + $location->setAttribute('line', $loc[1]); + } + } + } + $message->appendChild($dom->createElement('source', $source)); + $message->appendChild($dom->createElement('translation', $target)); + } + + return $dom->saveXML(); + } + + protected function getExtension(): string + { + return 'ts'; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/XliffFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/XliffFileDumper.php new file mode 100644 index 000000000..d0f016b23 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/XliffFileDumper.php @@ -0,0 +1,221 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * XliffFileDumper generates xliff files from a message catalogue. + * + * @author Michel Salib + */ +class XliffFileDumper extends FileDumper +{ + public function __construct( + private string $extension = 'xlf', + ) { + } + + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + $xliffVersion = '1.2'; + if (\array_key_exists('xliff_version', $options)) { + $xliffVersion = $options['xliff_version']; + } + + if (\array_key_exists('default_locale', $options)) { + $defaultLocale = $options['default_locale']; + } else { + $defaultLocale = \Locale::getDefault(); + } + + if ('1.2' === $xliffVersion) { + return $this->dumpXliff1($defaultLocale, $messages, $domain, $options); + } + if ('2.0' === $xliffVersion) { + return $this->dumpXliff2($defaultLocale, $messages, $domain); + } + + throw new InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion)); + } + + protected function getExtension(): string + { + return $this->extension; + } + + private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = []): string + { + $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony']; + if (\array_key_exists('tool_info', $options)) { + $toolInfo = array_merge($toolInfo, $options['tool_info']); + } + + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->formatOutput = true; + + $xliff = $dom->appendChild($dom->createElement('xliff')); + $xliff->setAttribute('version', '1.2'); + $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2'); + + $xliffFile = $xliff->appendChild($dom->createElement('file')); + $xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale)); + $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale())); + $xliffFile->setAttribute('datatype', 'plaintext'); + $xliffFile->setAttribute('original', 'file.ext'); + + $xliffHead = $xliffFile->appendChild($dom->createElement('header')); + $xliffTool = $xliffHead->appendChild($dom->createElement('tool')); + foreach ($toolInfo as $id => $value) { + $xliffTool->setAttribute($id, $value); + } + + if ($catalogueMetadata = $messages->getCatalogueMetadata('', $domain) ?? []) { + $xliffPropGroup = $xliffHead->appendChild($dom->createElement('prop-group')); + foreach ($catalogueMetadata as $key => $value) { + $xliffProp = $xliffPropGroup->appendChild($dom->createElement('prop')); + $xliffProp->setAttribute('prop-type', $key); + $xliffProp->appendChild($dom->createTextNode($value)); + } + } + + $xliffBody = $xliffFile->appendChild($dom->createElement('body')); + foreach ($messages->all($domain) as $source => $target) { + $translation = $dom->createElement('trans-unit'); + + $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); + $translation->setAttribute('resname', $source); + + $s = $translation->appendChild($dom->createElement('source')); + $s->appendChild($dom->createTextNode($source)); + + // Does the target contain characters requiring a CDATA section? + $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target); + + $targetElement = $dom->createElement('target'); + $metadata = $messages->getMetadata($source, $domain); + if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) { + foreach ($metadata['target-attributes'] as $name => $value) { + $targetElement->setAttribute($name, $value); + } + } + $t = $translation->appendChild($targetElement); + $t->appendChild($text); + + if ($this->hasMetadataArrayInfo('notes', $metadata)) { + foreach ($metadata['notes'] as $note) { + if (!isset($note['content'])) { + continue; + } + + $n = $translation->appendChild($dom->createElement('note')); + $n->appendChild($dom->createTextNode($note['content'])); + + if (isset($note['priority'])) { + $n->setAttribute('priority', $note['priority']); + } + + if (isset($note['from'])) { + $n->setAttribute('from', $note['from']); + } + } + } + + $xliffBody->appendChild($translation); + } + + return $dom->saveXML(); + } + + private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain): string + { + $dom = new \DOMDocument('1.0', 'utf-8'); + $dom->formatOutput = true; + + $xliff = $dom->appendChild($dom->createElement('xliff')); + $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0'); + $xliff->setAttribute('version', '2.0'); + $xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale)); + $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale())); + + $xliffFile = $xliff->appendChild($dom->createElement('file')); + if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) { + $xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale()); + } else { + $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale()); + } + + if ($catalogueMetadata = $messages->getCatalogueMetadata('', $domain) ?? []) { + $xliff->setAttribute('xmlns:m', 'urn:oasis:names:tc:xliff:metadata:2.0'); + $xliffMetadata = $xliffFile->appendChild($dom->createElement('m:metadata')); + foreach ($catalogueMetadata as $key => $value) { + $xliffMeta = $xliffMetadata->appendChild($dom->createElement('prop')); + $xliffMeta->setAttribute('type', $key); + $xliffMeta->appendChild($dom->createTextNode($value)); + } + } + + foreach ($messages->all($domain) as $source => $target) { + $translation = $dom->createElement('unit'); + $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); + + if (\strlen($source) <= 80) { + $translation->setAttribute('name', $source); + } + + $metadata = $messages->getMetadata($source, $domain); + + // Add notes section + if ($this->hasMetadataArrayInfo('notes', $metadata)) { + $notesElement = $dom->createElement('notes'); + foreach ($metadata['notes'] as $note) { + $n = $dom->createElement('note'); + $n->appendChild($dom->createTextNode($note['content'] ?? '')); + unset($note['content']); + + foreach ($note as $name => $value) { + $n->setAttribute($name, $value); + } + $notesElement->appendChild($n); + } + $translation->appendChild($notesElement); + } + + $segment = $translation->appendChild($dom->createElement('segment')); + + $s = $segment->appendChild($dom->createElement('source')); + $s->appendChild($dom->createTextNode($source)); + + // Does the target contain characters requiring a CDATA section? + $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target); + + $targetElement = $dom->createElement('target'); + if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) { + foreach ($metadata['target-attributes'] as $name => $value) { + $targetElement->setAttribute($name, $value); + } + } + $t = $segment->appendChild($targetElement); + $t->appendChild($text); + + $xliffFile->appendChild($translation); + } + + return $dom->saveXML(); + } + + private function hasMetadataArrayInfo(string $key, ?array $metadata = null): bool + { + return is_iterable($metadata[$key] ?? null); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/YamlFileDumper.php b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/YamlFileDumper.php new file mode 100644 index 000000000..d2670331e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Dumper/YamlFileDumper.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Dumper; + +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Util\ArrayConverter; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlFileDumper generates yaml files from a message catalogue. + * + * @author Michel Salib + */ +class YamlFileDumper extends FileDumper +{ + private string $extension; + + public function __construct(string $extension = 'yml') + { + $this->extension = $extension; + } + + public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string + { + if (!class_exists(Yaml::class)) { + throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.'); + } + + $data = $messages->all($domain); + + if (isset($options['as_tree']) && $options['as_tree']) { + $data = ArrayConverter::expandToTree($data); + } + + if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) { + return Yaml::dump($data, $inline); + } + + return Yaml::dump($data); + } + + protected function getExtension(): string + { + return $this->extension; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ExceptionInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ExceptionInterface.php new file mode 100644 index 000000000..8f9c54ef7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Exception interface for all exceptions thrown by the component. + * + * @author Fabien Potencier + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/IncompleteDsnException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/IncompleteDsnException.php new file mode 100644 index 000000000..b304bde01 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/IncompleteDsnException.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +class IncompleteDsnException extends InvalidArgumentException +{ + public function __construct(string $message, ?string $dsn = null, ?\Throwable $previous = null) + { + if ($dsn) { + $message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message; + } + + parent::__construct($message, 0, $previous); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidArgumentException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..90d06690f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Base InvalidArgumentException for the Translation component. + * + * @author Abdellatif Ait boudad + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidResourceException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidResourceException.php new file mode 100644 index 000000000..cf079432c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/InvalidResourceException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Thrown when a resource cannot be loaded. + * + * @author Fabien Potencier + */ +class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/LogicException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/LogicException.php new file mode 100644 index 000000000..9019c7e7b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/LogicException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Base LogicException for Translation component. + * + * @author Abdellatif Ait boudad + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/MissingRequiredOptionException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/MissingRequiredOptionException.php new file mode 100644 index 000000000..46152e254 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/MissingRequiredOptionException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * @author Oskar Stark + */ +class MissingRequiredOptionException extends IncompleteDsnException +{ + public function __construct(string $option, ?string $dsn = null, ?\Throwable $previous = null) + { + $message = sprintf('The option "%s" is required but missing.', $option); + + parent::__construct($message, $dsn, $previous); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/NotFoundResourceException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/NotFoundResourceException.php new file mode 100644 index 000000000..cff73ae30 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/NotFoundResourceException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Thrown when a resource does not exist. + * + * @author Fabien Potencier + */ +class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderException.php new file mode 100644 index 000000000..f2981f58b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderException.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 Symfony\Component\Translation\Exception; + +use Symfony\Contracts\HttpClient\ResponseInterface; + +/** + * @author Fabien Potencier + */ +class ProviderException extends RuntimeException implements ProviderExceptionInterface +{ + private ResponseInterface $response; + private string $debug; + + public function __construct(string $message, ResponseInterface $response, int $code = 0, ?\Exception $previous = null) + { + $this->response = $response; + $this->debug = $response->getInfo('debug') ?? ''; + + parent::__construct($message, $code, $previous); + } + + public function getResponse(): ResponseInterface + { + return $this->response; + } + + public function getDebug(): string + { + return $this->debug; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderExceptionInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderExceptionInterface.php new file mode 100644 index 000000000..922e82726 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/ProviderExceptionInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * @author Fabien Potencier + */ +interface ProviderExceptionInterface extends ExceptionInterface +{ + /* + * Returns debug info coming from the Symfony\Contracts\HttpClient\ResponseInterface + */ + public function getDebug(): string; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/RuntimeException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/RuntimeException.php new file mode 100644 index 000000000..dcd794082 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +/** + * Base RuntimeException for the Translation component. + * + * @author Abdellatif Ait boudad + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Exception/UnsupportedSchemeException.php b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/UnsupportedSchemeException.php new file mode 100644 index 000000000..8d3295184 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Exception/UnsupportedSchemeException.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Exception; + +use Symfony\Component\Translation\Bridge; +use Symfony\Component\Translation\Provider\Dsn; + +class UnsupportedSchemeException extends LogicException +{ + private const SCHEME_TO_PACKAGE_MAP = [ + 'crowdin' => [ + 'class' => Bridge\Crowdin\CrowdinProviderFactory::class, + 'package' => 'symfony/crowdin-translation-provider', + ], + 'loco' => [ + 'class' => Bridge\Loco\LocoProviderFactory::class, + 'package' => 'symfony/loco-translation-provider', + ], + 'lokalise' => [ + 'class' => Bridge\Lokalise\LokaliseProviderFactory::class, + 'package' => 'symfony/lokalise-translation-provider', + ], + 'phrase' => [ + 'class' => Bridge\Phrase\PhraseProviderFactory::class, + 'package' => 'symfony/phrase-translation-provider', + ], + ]; + + public function __construct(Dsn $dsn, ?string $name = null, array $supported = []) + { + $provider = $dsn->getScheme(); + if (false !== $pos = strpos($provider, '+')) { + $provider = substr($provider, 0, $pos); + } + $package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null; + if ($package && !class_exists($package['class'])) { + parent::__construct(sprintf('Unable to synchronize translations via "%s" as the provider is not installed. Try running "composer require %s".', $provider, $package['package'])); + + return; + } + + $message = sprintf('The "%s" scheme is not supported', $dsn->getScheme()); + if ($name && $supported) { + $message .= sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported)); + } + + parent::__construct($message.'.'); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/AbstractFileExtractor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/AbstractFileExtractor.php new file mode 100644 index 000000000..4c088b94f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/AbstractFileExtractor.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * Base class used by classes that extract translation messages from files. + * + * @author Marcos D. Sánchez + */ +abstract class AbstractFileExtractor +{ + protected function extractFiles(string|iterable $resource): iterable + { + if (is_iterable($resource)) { + $files = []; + foreach ($resource as $file) { + if ($this->canBeExtracted($file)) { + $files[] = $this->toSplFileInfo($file); + } + } + } elseif (is_file($resource)) { + $files = $this->canBeExtracted($resource) ? [$this->toSplFileInfo($resource)] : []; + } else { + $files = $this->extractFromDirectory($resource); + } + + return $files; + } + + private function toSplFileInfo(string $file): \SplFileInfo + { + return new \SplFileInfo($file); + } + + /** + * @throws InvalidArgumentException + */ + protected function isFile(string $file): bool + { + if (!is_file($file)) { + throw new InvalidArgumentException(sprintf('The "%s" file does not exist.', $file)); + } + + return true; + } + + /** + * @return bool + */ + abstract protected function canBeExtracted(string $file); + + /** + * @return iterable + */ + abstract protected function extractFromDirectory(string|array $resource); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/ChainExtractor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/ChainExtractor.php new file mode 100644 index 000000000..d36f7f385 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/ChainExtractor.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * ChainExtractor extracts translation messages from template files. + * + * @author Michel Salib + */ +class ChainExtractor implements ExtractorInterface +{ + /** + * The extractors. + * + * @var ExtractorInterface[] + */ + private array $extractors = []; + + /** + * Adds a loader to the translation extractor. + * + * @return void + */ + public function addExtractor(string $format, ExtractorInterface $extractor) + { + $this->extractors[$format] = $extractor; + } + + /** + * @return void + */ + public function setPrefix(string $prefix) + { + foreach ($this->extractors as $extractor) { + $extractor->setPrefix($prefix); + } + } + + /** + * @return void + */ + public function extract(string|iterable $directory, MessageCatalogue $catalogue) + { + foreach ($this->extractors as $extractor) { + $extractor->extract($directory, $catalogue); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/ExtractorInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/ExtractorInterface.php new file mode 100644 index 000000000..642130af7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/ExtractorInterface.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 Symfony\Component\Translation\Extractor; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * Extracts translation messages from a directory or files to the catalogue. + * New found messages are injected to the catalogue using the prefix. + * + * @author Michel Salib + */ +interface ExtractorInterface +{ + /** + * Extracts translation messages from files, a file or a directory to the catalogue. + * + * @param string|iterable $resource Files, a file or a directory + * + * @return void + */ + public function extract(string|iterable $resource, MessageCatalogue $catalogue); + + /** + * Sets the prefix that should be used for new found messages. + * + * @return void + */ + public function setPrefix(string $prefix); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpAstExtractor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpAstExtractor.php new file mode 100644 index 000000000..06fc77de3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpAstExtractor.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 Symfony\Component\Translation\Extractor; + +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor; +use PhpParser\Parser; +use PhpParser\ParserFactory; +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\Extractor\Visitor\AbstractVisitor; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PhpAstExtractor extracts translation messages from a PHP AST. + * + * @author Mathieu Santostefano + */ +final class PhpAstExtractor extends AbstractFileExtractor implements ExtractorInterface +{ + private Parser $parser; + + public function __construct( + /** + * @param iterable $visitors + */ + private readonly iterable $visitors, + private string $prefix = '', + ) { + if (!class_exists(ParserFactory::class)) { + throw new \LogicException(sprintf('You cannot use "%s" as the "nikic/php-parser" package is not installed. Try running "composer require nikic/php-parser".', static::class)); + } + + $this->parser = (new ParserFactory())->createForHostVersion(); + } + + public function extract(iterable|string $resource, MessageCatalogue $catalogue): void + { + foreach ($this->extractFiles($resource) as $file) { + $traverser = new NodeTraverser(); + + // This is needed to resolve namespaces in class methods/constants. + $nameResolver = new NodeVisitor\NameResolver(); + $traverser->addVisitor($nameResolver); + + /** @var AbstractVisitor&NodeVisitor $visitor */ + foreach ($this->visitors as $visitor) { + $visitor->initialize($catalogue, $file, $this->prefix); + $traverser->addVisitor($visitor); + } + + $nodes = $this->parser->parse(file_get_contents($file)); + $traverser->traverse($nodes); + } + } + + public function setPrefix(string $prefix): void + { + $this->prefix = $prefix; + } + + protected function canBeExtracted(string $file): bool + { + return 'php' === pathinfo($file, \PATHINFO_EXTENSION) + && $this->isFile($file) + && preg_match('/\bt\(|->trans\(|TranslatableMessage|Symfony\\\\Component\\\\Validator\\\\Constraints/i', file_get_contents($file)); + } + + protected function extractFromDirectory(array|string $resource): iterable|Finder + { + if (!class_exists(Finder::class)) { + throw new \LogicException(sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class)); + } + + return (new Finder())->files()->name('*.php')->in($resource); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpExtractor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpExtractor.php new file mode 100644 index 000000000..7ff27f7c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpExtractor.php @@ -0,0 +1,333 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +trigger_deprecation('symfony/translation', '6.2', '"%s" is deprecated, use "%s" instead.', PhpExtractor::class, PhpAstExtractor::class); + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PhpExtractor extracts translation messages from a PHP template. + * + * @author Michel Salib + * + * @deprecated since Symfony 6.2, use the PhpAstExtractor instead + */ +class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface +{ + public const MESSAGE_TOKEN = 300; + public const METHOD_ARGUMENTS_TOKEN = 1000; + public const DOMAIN_TOKEN = 1001; + + /** + * Prefix for new found message. + */ + private string $prefix = ''; + + /** + * The sequence that captures translation messages. + */ + protected $sequences = [ + [ + '->', + 'trans', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + '->', + 'trans', + '(', + self::MESSAGE_TOKEN, + ], + [ + 'new', + 'TranslatableMessage', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + 'new', + 'TranslatableMessage', + '(', + self::MESSAGE_TOKEN, + ], + [ + 'new', + '\\', + 'Symfony', + '\\', + 'Component', + '\\', + 'Translation', + '\\', + 'TranslatableMessage', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + 'new', + '\Symfony\Component\Translation\TranslatableMessage', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + 'new', + '\\', + 'Symfony', + '\\', + 'Component', + '\\', + 'Translation', + '\\', + 'TranslatableMessage', + '(', + self::MESSAGE_TOKEN, + ], + [ + 'new', + '\Symfony\Component\Translation\TranslatableMessage', + '(', + self::MESSAGE_TOKEN, + ], + [ + 't', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ], + [ + 't', + '(', + self::MESSAGE_TOKEN, + ], + ]; + + /** + * @return void + */ + public function extract(string|iterable $resource, MessageCatalogue $catalog) + { + $files = $this->extractFiles($resource); + foreach ($files as $file) { + $this->parseTokens(token_get_all(file_get_contents($file)), $catalog, $file); + + gc_mem_caches(); + } + } + + /** + * @return void + */ + public function setPrefix(string $prefix) + { + $this->prefix = $prefix; + } + + /** + * Normalizes a token. + */ + protected function normalizeToken(mixed $token): ?string + { + if (isset($token[1]) && 'b"' !== $token) { + return $token[1]; + } + + return $token; + } + + /** + * Seeks to a non-whitespace token. + */ + private function seekToNextRelevantToken(\Iterator $tokenIterator): void + { + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + if (\T_WHITESPACE !== $t[0]) { + break; + } + } + } + + private function skipMethodArgument(\Iterator $tokenIterator): void + { + $openBraces = 0; + + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + + if ('[' === $t[0] || '(' === $t[0]) { + ++$openBraces; + } + + if (']' === $t[0] || ')' === $t[0]) { + --$openBraces; + } + + if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) { + break; + } + } + } + + /** + * Extracts the message from the iterator while the tokens + * match allowed message tokens. + */ + private function getValue(\Iterator $tokenIterator): string + { + $message = ''; + $docToken = ''; + $docPart = ''; + + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + if ('.' === $t) { + // Concatenate with next token + continue; + } + if (!isset($t[1])) { + break; + } + + switch ($t[0]) { + case \T_START_HEREDOC: + $docToken = $t[1]; + break; + case \T_ENCAPSED_AND_WHITESPACE: + case \T_CONSTANT_ENCAPSED_STRING: + if ('' === $docToken) { + $message .= PhpStringTokenParser::parse($t[1]); + } else { + $docPart = $t[1]; + } + break; + case \T_END_HEREDOC: + if ($indentation = strspn($t[1], ' ')) { + $docPartWithLineBreaks = $docPart; + $docPart = ''; + + foreach (preg_split('~(\r\n|\n|\r)~', $docPartWithLineBreaks, -1, \PREG_SPLIT_DELIM_CAPTURE) as $str) { + if (\in_array($str, ["\r\n", "\n", "\r"], true)) { + $docPart .= $str; + } else { + $docPart .= substr($str, $indentation); + } + } + } + + $message .= PhpStringTokenParser::parseDocString($docToken, $docPart); + $docToken = ''; + $docPart = ''; + break; + case \T_WHITESPACE: + break; + default: + break 2; + } + } + + return $message; + } + + /** + * Extracts trans message from PHP tokens. + * + * @return void + */ + protected function parseTokens(array $tokens, MessageCatalogue $catalog, string $filename) + { + $tokenIterator = new \ArrayIterator($tokens); + + for ($key = 0; $key < $tokenIterator->count(); ++$key) { + foreach ($this->sequences as $sequence) { + $message = ''; + $domain = 'messages'; + $tokenIterator->seek($key); + + foreach ($sequence as $sequenceKey => $item) { + $this->seekToNextRelevantToken($tokenIterator); + + if ($this->normalizeToken($tokenIterator->current()) === $item) { + $tokenIterator->next(); + continue; + } elseif (self::MESSAGE_TOKEN === $item) { + $message = $this->getValue($tokenIterator); + + if (\count($sequence) === ($sequenceKey + 1)) { + break; + } + } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) { + $this->skipMethodArgument($tokenIterator); + } elseif (self::DOMAIN_TOKEN === $item) { + $domainToken = $this->getValue($tokenIterator); + if ('' !== $domainToken) { + $domain = $domainToken; + } + + break; + } else { + break; + } + } + + if ($message) { + $catalog->set($message, $this->prefix.$message, $domain); + $metadata = $catalog->getMetadata($message, $domain) ?? []; + $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $filename); + $metadata['sources'][] = $normalizedFilename.':'.$tokens[$key][2]; + $catalog->setMetadata($message, $metadata, $domain); + break; + } + } + } + } + + /** + * @throws \InvalidArgumentException + */ + protected function canBeExtracted(string $file): bool + { + return $this->isFile($file) && 'php' === pathinfo($file, \PATHINFO_EXTENSION); + } + + protected function extractFromDirectory(string|array $directory): iterable + { + if (!class_exists(Finder::class)) { + throw new \LogicException(sprintf('You cannot use "%s" as the "symfony/finder" package is not installed. Try running "composer require symfony/finder".', static::class)); + } + + $finder = new Finder(); + + return $finder->files()->name('*.php')->in($directory); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpStringTokenParser.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpStringTokenParser.php new file mode 100644 index 000000000..2dfc1e387 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/PhpStringTokenParser.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +trigger_deprecation('symfony/translation', '6.2', '"%s" is deprecated.', PhpStringTokenParser::class); + +/* + * The following is derived from code at http://github.com/nikic/PHP-Parser + * + * Copyright (c) 2011 by Nikita Popov + * + * Some 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. + * + * * The names of the contributors may not 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. + */ + +/** + * @deprecated since Symfony 6.2 + */ +class PhpStringTokenParser +{ + protected static $replacements = [ + '\\' => '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ]; + + /** + * Parses a string token. + * + * @param string $str String token content + */ + public static function parse(string $str): string + { + $bLength = 0; + if ('b' === $str[0]) { + $bLength = 1; + } + + if ('\'' === $str[$bLength]) { + return str_replace( + ['\\\\', '\\\''], + ['\\', '\''], + substr($str, $bLength + 1, -1) + ); + } else { + return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"'); + } + } + + /** + * Parses escape sequences in strings (all string types apart from single quoted). + * + * @param string $str String without quotes + * @param string|null $quote Quote type + */ + public static function parseEscapeSequences(string $str, ?string $quote = null): string + { + if (null !== $quote) { + $str = str_replace('\\'.$quote, $quote, $str); + } + + return preg_replace_callback( + '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~', + [__CLASS__, 'parseCallback'], + $str + ); + } + + private static function parseCallback(array $matches): string + { + $str = $matches[1]; + + if (isset(self::$replacements[$str])) { + return self::$replacements[$str]; + } elseif ('x' === $str[0] || 'X' === $str[0]) { + return \chr(hexdec($str)); + } else { + return \chr(octdec($str)); + } + } + + /** + * Parses a constant doc string. + * + * @param string $startToken Doc string start token content (<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor\Visitor; + +use PhpParser\Node; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * @author Mathieu Santostefano + */ +abstract class AbstractVisitor +{ + private MessageCatalogue $catalogue; + private \SplFileInfo $file; + private string $messagePrefix; + + public function initialize(MessageCatalogue $catalogue, \SplFileInfo $file, string $messagePrefix): void + { + $this->catalogue = $catalogue; + $this->file = $file; + $this->messagePrefix = $messagePrefix; + } + + protected function addMessageToCatalogue(string $message, ?string $domain, int $line): void + { + $domain ??= 'messages'; + $this->catalogue->set($message, $this->messagePrefix.$message, $domain); + $metadata = $this->catalogue->getMetadata($message, $domain) ?? []; + $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $this->file); + $metadata['sources'][] = $normalizedFilename.':'.$line; + $this->catalogue->setMetadata($message, $metadata, $domain); + } + + protected function getStringArguments(Node\Expr\CallLike|Node\Attribute|Node\Expr\New_ $node, int|string $index, bool $indexIsRegex = false): array + { + if (\is_string($index)) { + return $this->getStringNamedArguments($node, $index, $indexIsRegex); + } + + $args = $node instanceof Node\Expr\CallLike ? $node->getRawArgs() : $node->args; + + if (!($arg = $args[$index] ?? null) instanceof Node\Arg) { + return []; + } + + return (array) $this->getStringValue($arg->value); + } + + protected function hasNodeNamedArguments(Node\Expr\CallLike|Node\Attribute|Node\Expr\New_ $node): bool + { + $args = $node instanceof Node\Expr\CallLike ? $node->getRawArgs() : $node->args; + + foreach ($args as $arg) { + if ($arg instanceof Node\Arg && null !== $arg->name) { + return true; + } + } + + return false; + } + + protected function nodeFirstNamedArgumentIndex(Node\Expr\CallLike|Node\Attribute|Node\Expr\New_ $node): int + { + $args = $node instanceof Node\Expr\CallLike ? $node->getRawArgs() : $node->args; + + foreach ($args as $i => $arg) { + if ($arg instanceof Node\Arg && null !== $arg->name) { + return $i; + } + } + + return \PHP_INT_MAX; + } + + private function getStringNamedArguments(Node\Expr\CallLike|Node\Attribute $node, ?string $argumentName = null, bool $isArgumentNamePattern = false): array + { + $args = $node instanceof Node\Expr\CallLike ? $node->getArgs() : $node->args; + $argumentValues = []; + + foreach ($args as $arg) { + if (!$isArgumentNamePattern && $arg->name?->toString() === $argumentName) { + $argumentValues[] = $this->getStringValue($arg->value); + } elseif ($isArgumentNamePattern && preg_match($argumentName, $arg->name?->toString() ?? '') > 0) { + $argumentValues[] = $this->getStringValue($arg->value); + } + } + + return array_filter($argumentValues); + } + + private function getStringValue(Node $node): ?string + { + if ($node instanceof Node\Scalar\String_) { + return $node->value; + } + + if ($node instanceof Node\Expr\BinaryOp\Concat) { + if (null === $left = $this->getStringValue($node->left)) { + return null; + } + + if (null === $right = $this->getStringValue($node->right)) { + return null; + } + + return $left.$right; + } + + if ($node instanceof Node\Expr\Assign && $node->expr instanceof Node\Scalar\String_) { + return $node->expr->value; + } + + if ($node instanceof Node\Expr\ClassConstFetch) { + try { + $reflection = new \ReflectionClass($node->class->toString()); + $constant = $reflection->getReflectionConstant($node->name->toString()); + if (false !== $constant && \is_string($constant->getValue())) { + return $constant->getValue(); + } + } catch (\ReflectionException) { + } + } + + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/ConstraintVisitor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/ConstraintVisitor.php new file mode 100644 index 000000000..00fb9eedc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/ConstraintVisitor.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor\Visitor; + +use PhpParser\Node; +use PhpParser\NodeVisitor; + +/** + * @author Mathieu Santostefano + * + * Code mostly comes from https://github.com/php-translation/extractor/blob/master/src/Visitor/Php/Symfony/Constraint.php + */ +final class ConstraintVisitor extends AbstractVisitor implements NodeVisitor +{ + public function __construct( + private readonly array $constraintClassNames = [] + ) { + } + + public function beforeTraverse(array $nodes): ?Node + { + return null; + } + + public function enterNode(Node $node): ?Node + { + return null; + } + + public function leaveNode(Node $node): ?Node + { + if (!$node instanceof Node\Expr\New_ && !$node instanceof Node\Attribute) { + return null; + } + + $className = $node instanceof Node\Attribute ? $node->name : $node->class; + if (!$className instanceof Node\Name) { + return null; + } + + $parts = $className->getParts(); + $isConstraintClass = false; + + foreach ($parts as $part) { + if (\in_array($part, $this->constraintClassNames, true)) { + $isConstraintClass = true; + + break; + } + } + + if (!$isConstraintClass) { + return null; + } + + $arg = $node->args[0] ?? null; + if (!$arg instanceof Node\Arg) { + return null; + } + + if ($this->hasNodeNamedArguments($node)) { + $messages = $this->getStringArguments($node, '/message/i', true); + } else { + if (!$arg->value instanceof Node\Expr\Array_) { + // There is no way to guess which argument is a message to be translated. + return null; + } + + $messages = []; + $options = $arg->value; + + /** @var Node\Expr\ArrayItem $item */ + foreach ($options->items as $item) { + if (!$item->key instanceof Node\Scalar\String_) { + continue; + } + + if (false === stripos($item->key->value ?? '', 'message')) { + continue; + } + + if (!$item->value instanceof Node\Scalar\String_) { + continue; + } + + $messages[] = $item->value->value; + + break; + } + } + + foreach ($messages as $message) { + $this->addMessageToCatalogue($message, 'validators', $node->getStartLine()); + } + + return null; + } + + public function afterTraverse(array $nodes): ?Node + { + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TransMethodVisitor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TransMethodVisitor.php new file mode 100644 index 000000000..a3dcd6d2b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TransMethodVisitor.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor\Visitor; + +use PhpParser\Node; +use PhpParser\NodeVisitor; + +/** + * @author Mathieu Santostefano + */ +final class TransMethodVisitor extends AbstractVisitor implements NodeVisitor +{ + public function beforeTraverse(array $nodes): ?Node + { + return null; + } + + public function enterNode(Node $node): ?Node + { + return null; + } + + public function leaveNode(Node $node): ?Node + { + if (!$node instanceof Node\Expr\MethodCall && !$node instanceof Node\Expr\FuncCall) { + return null; + } + + if (!\is_string($node->name) && !$node->name instanceof Node\Identifier && !$node->name instanceof Node\Name) { + return null; + } + + $name = $node->name instanceof Node\Name ? $node->name->getLast() : (string) $node->name; + + if ('trans' === $name || 't' === $name) { + $firstNamedArgumentIndex = $this->nodeFirstNamedArgumentIndex($node); + + if (!$messages = $this->getStringArguments($node, 0 < $firstNamedArgumentIndex ? 0 : 'id')) { + return null; + } + + $domain = $this->getStringArguments($node, 2 < $firstNamedArgumentIndex ? 2 : 'domain')[0] ?? null; + + foreach ($messages as $message) { + $this->addMessageToCatalogue($message, $domain, $node->getStartLine()); + } + } + + return null; + } + + public function afterTraverse(array $nodes): ?Node + { + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php new file mode 100644 index 000000000..6bd8bb022 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Extractor/Visitor/TranslatableMessageVisitor.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor\Visitor; + +use PhpParser\Node; +use PhpParser\NodeVisitor; + +/** + * @author Mathieu Santostefano + */ +final class TranslatableMessageVisitor extends AbstractVisitor implements NodeVisitor +{ + public function beforeTraverse(array $nodes): ?Node + { + return null; + } + + public function enterNode(Node $node): ?Node + { + return null; + } + + public function leaveNode(Node $node): ?Node + { + if (!$node instanceof Node\Expr\New_) { + return null; + } + + if (!($className = $node->class) instanceof Node\Name) { + return null; + } + + if (!\in_array('TranslatableMessage', $className->getParts(), true)) { + return null; + } + + $firstNamedArgumentIndex = $this->nodeFirstNamedArgumentIndex($node); + + if (!$messages = $this->getStringArguments($node, 0 < $firstNamedArgumentIndex ? 0 : 'message')) { + return null; + } + + $domain = $this->getStringArguments($node, 2 < $firstNamedArgumentIndex ? 2 : 'domain')[0] ?? null; + + foreach ($messages as $message) { + $this->addMessageToCatalogue($message, $domain, $node->getStartLine()); + } + + return null; + } + + public function afterTraverse(array $nodes): ?Node + { + return null; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatter.php b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatter.php new file mode 100644 index 000000000..e62de253f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatter.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\LogicException; + +/** + * @author Guilherme Blanco + * @author Abdellatif Ait boudad + */ +class IntlFormatter implements IntlFormatterInterface +{ + private bool $hasMessageFormatter; + private array $cache = []; + + public function formatIntl(string $message, string $locale, array $parameters = []): string + { + // MessageFormatter constructor throws an exception if the message is empty + if ('' === $message) { + return ''; + } + + if (!$formatter = $this->cache[$locale][$message] ?? null) { + if (!$this->hasMessageFormatter ??= class_exists(\MessageFormatter::class)) { + throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.'); + } + try { + $this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message); + } catch (\IntlException $e) { + throw new InvalidArgumentException(sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e); + } + } + + foreach ($parameters as $key => $value) { + if (\in_array($key[0] ?? null, ['%', '{'], true)) { + unset($parameters[$key]); + $parameters[trim($key, '%{ }')] = $value; + } + } + + if (false === $message = $formatter->format($parameters)) { + throw new InvalidArgumentException(sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage()); + } + + return $message; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatterInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatterInterface.php new file mode 100644 index 000000000..02fc6acbd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/IntlFormatterInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +/** + * Formats ICU message patterns. + * + * @author Nicolas Grekas + */ +interface IntlFormatterInterface +{ + /** + * Formats a localized message using rules defined by ICU MessageFormat. + * + * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details + */ + public function formatIntl(string $message, string $locale, array $parameters = []): string; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatter.php b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatter.php new file mode 100644 index 000000000..d5255bdcb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatter.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 Symfony\Component\Translation\Formatter; + +use Symfony\Component\Translation\IdentityTranslator; +use Symfony\Contracts\Translation\TranslatorInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(IntlFormatter::class); + +/** + * @author Abdellatif Ait boudad + */ +class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterface +{ + private TranslatorInterface $translator; + private IntlFormatterInterface $intlFormatter; + + /** + * @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization + */ + public function __construct(?TranslatorInterface $translator = null, ?IntlFormatterInterface $intlFormatter = null) + { + $this->translator = $translator ?? new IdentityTranslator(); + $this->intlFormatter = $intlFormatter ?? new IntlFormatter(); + } + + public function format(string $message, string $locale, array $parameters = []): string + { + return $this->translator->trans($message, $parameters, null, $locale); + } + + public function formatIntl(string $message, string $locale, array $parameters = []): string + { + return $this->intlFormatter->formatIntl($message, $locale, $parameters); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatterInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatterInterface.php new file mode 100644 index 000000000..d5c41c190 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Formatter/MessageFormatterInterface.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +/** + * @author Guilherme Blanco + * @author Abdellatif Ait boudad + */ +interface MessageFormatterInterface +{ + /** + * Formats a localized message pattern with given arguments. + * + * @param string $message The message (may also be an object that can be cast to string) + * @param string $locale The message locale + * @param array $parameters An array of parameters for the message + */ + public function format(string $message, string $locale, array $parameters = []): string; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/IdentityTranslator.php b/.extlib/simplesamlphp/vendor/symfony/translation/IdentityTranslator.php new file mode 100644 index 000000000..46875edf2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/IdentityTranslator.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorTrait; + +/** + * IdentityTranslator does not translate anything. + * + * @author Fabien Potencier + */ +class IdentityTranslator implements TranslatorInterface, LocaleAwareInterface +{ + use TranslatorTrait; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/LICENSE b/.extlib/simplesamlphp/vendor/symfony/translation/LICENSE new file mode 100644 index 000000000..0138f8f07 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/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/.extlib/simplesamlphp/vendor/symfony/translation/Loader/ArrayLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/ArrayLoader.php new file mode 100644 index 000000000..e63a7d05b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/ArrayLoader.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * ArrayLoader loads translations from a PHP array. + * + * @author Fabien Potencier + */ +class ArrayLoader implements LoaderInterface +{ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue + { + $resource = $this->flatten($resource); + $catalogue = new MessageCatalogue($locale); + $catalogue->add($resource, $domain); + + return $catalogue; + } + + /** + * Flattens an nested array of translations. + * + * The scheme used is: + * 'key' => ['key2' => ['key3' => 'value']] + * Becomes: + * 'key.key2.key3' => 'value' + */ + private function flatten(array $messages): array + { + $result = []; + foreach ($messages as $key => $value) { + if (\is_array($value)) { + foreach ($this->flatten($value) as $k => $v) { + if (null !== $v) { + $result[$key.'.'.$k] = $v; + } + } + } elseif (null !== $value) { + $result[$key] = $value; + } + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/CsvFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/CsvFileLoader.php new file mode 100644 index 000000000..93bee730b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/CsvFileLoader.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\NotFoundResourceException; + +/** + * CsvFileLoader loads translations from CSV files. + * + * @author SaÅ¡a Stamenković + */ +class CsvFileLoader extends FileLoader +{ + private string $delimiter = ';'; + private string $enclosure = '"'; + private string $escape = ''; + + protected function loadResource(string $resource): array + { + $messages = []; + + try { + $file = new \SplFileObject($resource, 'rb'); + } catch (\RuntimeException $e) { + throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e); + } + + $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY); + $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape); + + foreach ($file as $data) { + if (false === $data) { + continue; + } + + if (!str_starts_with($data[0], '#') && isset($data[1]) && 2 === \count($data)) { + $messages[$data[0]] = $data[1]; + } + } + + return $messages; + } + + /** + * Sets the delimiter, enclosure, and escape character for CSV. + * + * @return void + */ + public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '') + { + $this->delimiter = $delimiter; + $this->enclosure = $enclosure; + $this->escape = $escape; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/FileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/FileLoader.php new file mode 100644 index 000000000..877c3bbc7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/FileLoader.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * @author Abdellatif Ait boudad + */ +abstract class FileLoader extends ArrayLoader +{ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue + { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + $messages = $this->loadResource($resource); + + // empty resource + $messages ??= []; + + // not an array + if (!\is_array($messages)) { + throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource)); + } + + $catalogue = parent::load($messages, $locale, $domain); + + if (class_exists(FileResource::class)) { + $catalogue->addResource(new FileResource($resource)); + } + + return $catalogue; + } + + /** + * @throws InvalidResourceException if stream content has an invalid format + */ + abstract protected function loadResource(string $resource): array; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuDatFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuDatFileLoader.php new file mode 100644 index 000000000..76e4e7f02 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuDatFileLoader.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IcuResFileLoader loads translations from a resource bundle. + * + * @author stealth35 + */ +class IcuDatFileLoader extends IcuResFileLoader +{ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue + { + if (!stream_is_local($resource.'.dat')) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource.'.dat')) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + try { + $rb = new \ResourceBundle($locale, $resource); + } catch (\Exception) { + $rb = null; + } + + if (!$rb) { + throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource)); + } elseif (intl_is_failure($rb->getErrorCode())) { + throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); + } + + $messages = $this->flatten($rb); + $catalogue = new MessageCatalogue($locale); + $catalogue->add($messages, $domain); + + if (class_exists(FileResource::class)) { + $catalogue->addResource(new FileResource($resource.'.dat')); + } + + return $catalogue; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuResFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuResFileLoader.php new file mode 100644 index 000000000..949dd9792 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IcuResFileLoader.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * IcuResFileLoader loads translations from a resource bundle. + * + * @author stealth35 + */ +class IcuResFileLoader implements LoaderInterface +{ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue + { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!is_dir($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + try { + $rb = new \ResourceBundle($locale, $resource); + } catch (\Exception) { + $rb = null; + } + + if (!$rb) { + throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource)); + } elseif (intl_is_failure($rb->getErrorCode())) { + throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode()); + } + + $messages = $this->flatten($rb); + $catalogue = new MessageCatalogue($locale); + $catalogue->add($messages, $domain); + + if (class_exists(DirectoryResource::class)) { + $catalogue->addResource(new DirectoryResource($resource)); + } + + return $catalogue; + } + + /** + * Flattens an ResourceBundle. + * + * The scheme used is: + * key { key2 { key3 { "value" } } } + * Becomes: + * 'key.key2.key3' => 'value' + * + * This function takes an array by reference and will modify it + * + * @param \ResourceBundle $rb The ResourceBundle that will be flattened + * @param array $messages Used internally for recursive calls + * @param string|null $path Current path being parsed, used internally for recursive calls + */ + protected function flatten(\ResourceBundle $rb, array &$messages = [], ?string $path = null): array + { + foreach ($rb as $key => $value) { + $nodePath = $path ? $path.'.'.$key : $key; + if ($value instanceof \ResourceBundle) { + $this->flatten($value, $messages, $nodePath); + } else { + $messages[$nodePath] = $value; + } + } + + return $messages; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IniFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IniFileLoader.php new file mode 100644 index 000000000..3126896c8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/IniFileLoader.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +/** + * IniFileLoader loads translations from an ini file. + * + * @author stealth35 + */ +class IniFileLoader extends FileLoader +{ + protected function loadResource(string $resource): array + { + return parse_ini_file($resource, true); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/JsonFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/JsonFileLoader.php new file mode 100644 index 000000000..385553ef6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/JsonFileLoader.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; + +/** + * JsonFileLoader loads translations from an json file. + * + * @author singles + */ +class JsonFileLoader extends FileLoader +{ + protected function loadResource(string $resource): array + { + $messages = []; + if ($data = file_get_contents($resource)) { + $messages = json_decode($data, true); + + if (0 < $errorCode = json_last_error()) { + throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode)); + } + } + + return $messages; + } + + /** + * Translates JSON_ERROR_* constant into meaningful message. + */ + private function getJSONErrorMessage(int $errorCode): string + { + return match ($errorCode) { + \JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', + \JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', + \JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', + \JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', + \JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', + default => 'Unknown error', + }; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/LoaderInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/LoaderInterface.php new file mode 100644 index 000000000..29d5560d1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/LoaderInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * LoaderInterface is the interface implemented by all translation loaders. + * + * @author Fabien Potencier + */ +interface LoaderInterface +{ + /** + * Loads a locale. + * + * @throws NotFoundResourceException when the resource cannot be found + * @throws InvalidResourceException when the resource cannot be loaded + */ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/MoFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/MoFileLoader.php new file mode 100644 index 000000000..8427c393e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/MoFileLoader.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; + +/** + * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/) + */ +class MoFileLoader extends FileLoader +{ + /** + * Magic used for validating the format of an MO file as well as + * detecting if the machine used to create that file was little endian. + */ + public const MO_LITTLE_ENDIAN_MAGIC = 0x950412DE; + + /** + * Magic used for validating the format of an MO file as well as + * detecting if the machine used to create that file was big endian. + */ + public const MO_BIG_ENDIAN_MAGIC = 0xDE120495; + + /** + * The size of the header of an MO file in bytes. + */ + public const MO_HEADER_SIZE = 28; + + /** + * Parses machine object (MO) format, independent of the machine's endian it + * was created on. Both 32bit and 64bit systems are supported. + */ + protected function loadResource(string $resource): array + { + $stream = fopen($resource, 'r'); + + $stat = fstat($stream); + + if ($stat['size'] < self::MO_HEADER_SIZE) { + throw new InvalidResourceException('MO stream content has an invalid format.'); + } + $magic = unpack('V1', fread($stream, 4)); + $magic = hexdec(substr(dechex(current($magic)), -8)); + + if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) { + $isBigEndian = false; + } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) { + $isBigEndian = true; + } else { + throw new InvalidResourceException('MO stream content has an invalid format.'); + } + + // formatRevision + $this->readLong($stream, $isBigEndian); + $count = $this->readLong($stream, $isBigEndian); + $offsetId = $this->readLong($stream, $isBigEndian); + $offsetTranslated = $this->readLong($stream, $isBigEndian); + // sizeHashes + $this->readLong($stream, $isBigEndian); + // offsetHashes + $this->readLong($stream, $isBigEndian); + + $messages = []; + + for ($i = 0; $i < $count; ++$i) { + $pluralId = null; + $translated = null; + + fseek($stream, $offsetId + $i * 8); + + $length = $this->readLong($stream, $isBigEndian); + $offset = $this->readLong($stream, $isBigEndian); + + if ($length < 1) { + continue; + } + + fseek($stream, $offset); + $singularId = fread($stream, $length); + + if (str_contains($singularId, "\000")) { + [$singularId, $pluralId] = explode("\000", $singularId); + } + + fseek($stream, $offsetTranslated + $i * 8); + $length = $this->readLong($stream, $isBigEndian); + $offset = $this->readLong($stream, $isBigEndian); + + if ($length < 1) { + continue; + } + + fseek($stream, $offset); + $translated = fread($stream, $length); + + if (str_contains($translated, "\000")) { + $translated = explode("\000", $translated); + } + + $ids = ['singular' => $singularId, 'plural' => $pluralId]; + $item = compact('ids', 'translated'); + + if (!empty($item['ids']['singular'])) { + $id = $item['ids']['singular']; + if (isset($item['ids']['plural'])) { + $id .= '|'.$item['ids']['plural']; + } + $messages[$id] = stripcslashes(implode('|', (array) $item['translated'])); + } + } + + fclose($stream); + + return array_filter($messages); + } + + /** + * Reads an unsigned long from stream respecting endianness. + * + * @param resource $stream + */ + private function readLong($stream, bool $isBigEndian): int + { + $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4)); + $result = current($result); + + return (int) substr($result, -8); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/PhpFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/PhpFileLoader.php new file mode 100644 index 000000000..541b6c832 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/PhpFileLoader.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +/** + * PhpFileLoader loads translations from PHP files returning an array of translations. + * + * @author Fabien Potencier + */ +class PhpFileLoader extends FileLoader +{ + private static ?array $cache = []; + + protected function loadResource(string $resource): array + { + if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOL) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true) || filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOL))) { + self::$cache = null; + } + + if (null === self::$cache) { + return require $resource; + } + + return self::$cache[$resource] ??= require $resource; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/PoFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/PoFileLoader.php new file mode 100644 index 000000000..620d97339 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/PoFileLoader.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +/** + * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium + * @copyright Copyright (c) 2012, Clemens Tolboom + */ +class PoFileLoader extends FileLoader +{ + /** + * Parses portable object (PO) format. + * + * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files + * we should be able to parse files having: + * + * white-space + * # translator-comments + * #. extracted-comments + * #: reference... + * #, flag... + * #| msgid previous-untranslated-string + * msgid untranslated-string + * msgstr translated-string + * + * extra or different lines are: + * + * #| msgctxt previous-context + * #| msgid previous-untranslated-string + * msgctxt context + * + * #| msgid previous-untranslated-string-singular + * #| msgid_plural previous-untranslated-string-plural + * msgid untranslated-string-singular + * msgid_plural untranslated-string-plural + * msgstr[0] translated-string-case-0 + * ... + * msgstr[N] translated-string-case-n + * + * The definition states: + * - white-space and comments are optional. + * - msgid "" that an empty singleline defines a header. + * + * This parser sacrifices some features of the reference implementation the + * differences to that implementation are as follows. + * - No support for comments spanning multiple lines. + * - Translator and extracted comments are treated as being the same type. + * - Message IDs are allowed to have other encodings as just US-ASCII. + * + * Items with an empty id are ignored. + */ + protected function loadResource(string $resource): array + { + $stream = fopen($resource, 'r'); + + $defaults = [ + 'ids' => [], + 'translated' => null, + ]; + + $messages = []; + $item = $defaults; + $flags = []; + + while ($line = fgets($stream)) { + $line = trim($line); + + if ('' === $line) { + // Whitespace indicated current item is done + if (!\in_array('fuzzy', $flags)) { + $this->addMessage($messages, $item); + } + $item = $defaults; + $flags = []; + } elseif (str_starts_with($line, '#,')) { + $flags = array_map('trim', explode(',', substr($line, 2))); + } elseif (str_starts_with($line, 'msgid "')) { + // We start a new msg so save previous + // TODO: this fails when comments or contexts are added + $this->addMessage($messages, $item); + $item = $defaults; + $item['ids']['singular'] = substr($line, 7, -1); + } elseif (str_starts_with($line, 'msgstr "')) { + $item['translated'] = substr($line, 8, -1); + } elseif ('"' === $line[0]) { + $continues = isset($item['translated']) ? 'translated' : 'ids'; + + if (\is_array($item[$continues])) { + end($item[$continues]); + $item[$continues][key($item[$continues])] .= substr($line, 1, -1); + } else { + $item[$continues] .= substr($line, 1, -1); + } + } elseif (str_starts_with($line, 'msgid_plural "')) { + $item['ids']['plural'] = substr($line, 14, -1); + } elseif (str_starts_with($line, 'msgstr[')) { + $size = strpos($line, ']'); + $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1); + } + } + // save last item + if (!\in_array('fuzzy', $flags)) { + $this->addMessage($messages, $item); + } + fclose($stream); + + return $messages; + } + + /** + * Save a translation item to the messages. + * + * A .po file could contain by error missing plural indexes. We need to + * fix these before saving them. + */ + private function addMessage(array &$messages, array $item): void + { + if (!empty($item['ids']['singular'])) { + $id = stripcslashes($item['ids']['singular']); + if (isset($item['ids']['plural'])) { + $id .= '|'.stripcslashes($item['ids']['plural']); + } + + $translated = (array) $item['translated']; + // PO are by definition indexed so sort by index. + ksort($translated); + // Make sure every index is filled. + end($translated); + $count = key($translated); + // Fill missing spots with '-'. + $empties = array_fill(0, $count + 1, '-'); + $translated += $empties; + ksort($translated); + + $messages[$id] = stripcslashes(implode('|', $translated)); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/QtFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/QtFileLoader.php new file mode 100644 index 000000000..235f85ee9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/QtFileLoader.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * QtFileLoader loads translations from QT Translations XML files. + * + * @author Benjamin Eberlei + */ +class QtFileLoader implements LoaderInterface +{ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue + { + if (!class_exists(XmlUtils::class)) { + throw new RuntimeException('Loading translations from the QT format requires the Symfony Config component.'); + } + + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + try { + $dom = XmlUtils::loadFile($resource); + } catch (\InvalidArgumentException $e) { + throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e); + } + + $internalErrors = libxml_use_internal_errors(true); + libxml_clear_errors(); + + $xpath = new \DOMXPath($dom); + $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]'); + + $catalogue = new MessageCatalogue($locale); + if (1 == $nodes->length) { + $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message'); + foreach ($translations as $translation) { + $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue; + + if (!empty($translationValue)) { + $catalogue->set( + (string) $translation->getElementsByTagName('source')->item(0)->nodeValue, + $translationValue, + $domain + ); + } + } + + if (class_exists(FileResource::class)) { + $catalogue->addResource(new FileResource($resource)); + } + } + + libxml_use_internal_errors($internalErrors); + + return $catalogue; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Loader/XliffFileLoader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/XliffFileLoader.php new file mode 100644 index 000000000..ffe4bbbd8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Loader/XliffFileLoader.php @@ -0,0 +1,241 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Util\Exception\InvalidXmlException; +use Symfony\Component\Config\Util\Exception\XmlParsingException; +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Util\XliffUtils; + +/** + * XliffFileLoader loads translations from XLIFF files. + * + * @author Fabien Potencier + */ +class XliffFileLoader implements LoaderInterface +{ + public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue + { + if (!class_exists(XmlUtils::class)) { + throw new RuntimeException('Loading translations from the Xliff format requires the Symfony Config component.'); + } + + if (!$this->isXmlString($resource)) { + if (!stream_is_local($resource)) { + throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource)); + } + + if (!file_exists($resource)) { + throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource)); + } + + if (!is_file($resource)) { + throw new InvalidResourceException(sprintf('This is neither a file nor an XLIFF string "%s".', $resource)); + } + } + + try { + if ($this->isXmlString($resource)) { + $dom = XmlUtils::parse($resource); + } else { + $dom = XmlUtils::loadFile($resource); + } + } catch (\InvalidArgumentException|XmlParsingException|InvalidXmlException $e) { + throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e); + } + + if ($errors = XliffUtils::validateSchema($dom)) { + throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors)); + } + + $catalogue = new MessageCatalogue($locale); + $this->extract($dom, $catalogue, $domain); + + if (is_file($resource) && class_exists(FileResource::class)) { + $catalogue->addResource(new FileResource($resource)); + } + + return $catalogue; + } + + private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain): void + { + $xliffVersion = XliffUtils::getVersionNumber($dom); + + if ('1.2' === $xliffVersion) { + $this->extractXliff1($dom, $catalogue, $domain); + } + + if ('2.0' === $xliffVersion) { + $this->extractXliff2($dom, $catalogue, $domain); + } + } + + /** + * Extract messages and metadata from DOMDocument into a MessageCatalogue. + */ + private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain): void + { + $xml = simplexml_import_dom($dom); + $encoding = $dom->encoding ? strtoupper($dom->encoding) : null; + + $namespace = 'urn:oasis:names:tc:xliff:document:1.2'; + $xml->registerXPathNamespace('xliff', $namespace); + + foreach ($xml->xpath('//xliff:file') as $file) { + $fileAttributes = $file->attributes(); + + $file->registerXPathNamespace('xliff', $namespace); + + foreach ($file->xpath('.//xliff:prop') as $prop) { + $catalogue->setCatalogueMetadata($prop->attributes()['prop-type'], (string) $prop, $domain); + } + + foreach ($file->xpath('.//xliff:trans-unit') as $translation) { + $attributes = $translation->attributes(); + + if (!(isset($attributes['resname']) || isset($translation->source))) { + continue; + } + + $source = (string) (isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source); + + if (isset($translation->target) + && 'needs-translation' === (string) $translation->target->attributes()['state'] + && \in_array((string) $translation->target, [$source, (string) $translation->source], true) + ) { + continue; + } + + // If the xlf file has another encoding specified, try to convert it because + // simple_xml will always return utf-8 encoded values + $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding); + + $catalogue->set($source, $target, $domain); + + $metadata = [ + 'source' => (string) $translation->source, + 'file' => [ + 'original' => (string) $fileAttributes['original'], + ], + ]; + if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) { + $metadata['notes'] = $notes; + } + + if (isset($translation->target) && $translation->target->attributes()) { + $metadata['target-attributes'] = []; + foreach ($translation->target->attributes() as $key => $value) { + $metadata['target-attributes'][$key] = (string) $value; + } + } + + if (isset($attributes['id'])) { + $metadata['id'] = (string) $attributes['id']; + } + + $catalogue->setMetadata($source, $metadata, $domain); + } + } + } + + private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain): void + { + $xml = simplexml_import_dom($dom); + $encoding = $dom->encoding ? strtoupper($dom->encoding) : null; + + $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0'); + + foreach ($xml->xpath('//xliff:unit') as $unit) { + foreach ($unit->segment as $segment) { + $attributes = $unit->attributes(); + $source = $attributes['name'] ?? $segment->source; + + // If the xlf file has another encoding specified, try to convert it because + // simple_xml will always return utf-8 encoded values + $target = $this->utf8ToCharset((string) ($segment->target ?? $segment->source), $encoding); + + $catalogue->set((string) $source, $target, $domain); + + $metadata = []; + if (isset($segment->target) && $segment->target->attributes()) { + $metadata['target-attributes'] = []; + foreach ($segment->target->attributes() as $key => $value) { + $metadata['target-attributes'][$key] = (string) $value; + } + } + + if (isset($unit->notes)) { + $metadata['notes'] = []; + foreach ($unit->notes->note as $noteNode) { + $note = []; + foreach ($noteNode->attributes() as $key => $value) { + $note[$key] = (string) $value; + } + $note['content'] = (string) $noteNode; + $metadata['notes'][] = $note; + } + } + + $catalogue->setMetadata((string) $source, $metadata, $domain); + } + } + } + + /** + * Convert a UTF8 string to the specified encoding. + */ + private function utf8ToCharset(string $content, ?string $encoding = null): string + { + if ('UTF-8' !== $encoding && !empty($encoding)) { + return mb_convert_encoding($content, $encoding, 'UTF-8'); + } + + return $content; + } + + private function parseNotesMetadata(?\SimpleXMLElement $noteElement = null, ?string $encoding = null): array + { + $notes = []; + + if (null === $noteElement) { + return $notes; + } + + /** @var \SimpleXMLElement $xmlNote */ + foreach ($noteElement as $xmlNote) { + $noteAttributes = $xmlNote->attributes(); + $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)]; + if (isset($noteAttributes['priority'])) { + $note['priority'] = (int) $noteAttributes['priority']; + } + + if (isset($noteAttributes['from'])) { + $note['from'] = (string) $noteAttributes['from']; + } + + $notes[] = $note; + } + + return $notes; + } + + private function isXmlString(string $resource): bool + { + return str_starts_with($resource, ' + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Loader; + +use Symfony\Component\Translation\Exception\InvalidResourceException; +use Symfony\Component\Translation\Exception\LogicException; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Parser as YamlParser; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlFileLoader loads translations from Yaml files. + * + * @author Fabien Potencier + */ +class YamlFileLoader extends FileLoader +{ + private YamlParser $yamlParser; + + protected function loadResource(string $resource): array + { + if (!isset($this->yamlParser)) { + if (!class_exists(\Symfony\Component\Yaml\Parser::class)) { + throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.'); + } + + $this->yamlParser = new YamlParser(); + } + + try { + $messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT); + } catch (ParseException $e) { + throw new InvalidResourceException(sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e); + } + + if (null !== $messages && !\is_array($messages)) { + throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource)); + } + + return $messages ?: []; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/LocaleSwitcher.php b/.extlib/simplesamlphp/vendor/symfony/translation/LocaleSwitcher.php new file mode 100644 index 000000000..4950a56bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/LocaleSwitcher.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 Symfony\Component\Translation; + +use Symfony\Component\Routing\RequestContext; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +/** + * @author Kevin Bond + */ +class LocaleSwitcher implements LocaleAwareInterface +{ + private string $defaultLocale; + + /** + * @param LocaleAwareInterface[] $localeAwareServices + */ + public function __construct( + private string $locale, + private iterable $localeAwareServices, + private ?RequestContext $requestContext = null, + ) { + $this->defaultLocale = $locale; + } + + public function setLocale(string $locale): void + { + // Silently ignore if the intl extension is not loaded + try { + if (class_exists(\Locale::class, false)) { + \Locale::setDefault($locale); + } + } catch (\Exception) { + } + + $this->locale = $locale; + $this->requestContext?->setParameter('_locale', $locale); + + foreach ($this->localeAwareServices as $service) { + $service->setLocale($locale); + } + } + + public function getLocale(): string + { + return $this->locale; + } + + /** + * Switch to a new locale, execute a callback, then switch back to the original. + * + * @template T + * + * @param callable(string $locale):T $callback + * + * @return T + */ + public function runWithLocale(string $locale, callable $callback): mixed + { + $original = $this->getLocale(); + $this->setLocale($locale); + + try { + return $callback($locale); + } finally { + $this->setLocale($original); + } + } + + public function reset(): void + { + $this->setLocale($this->defaultLocale); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/LoggingTranslator.php b/.extlib/simplesamlphp/vendor/symfony/translation/LoggingTranslator.php new file mode 100644 index 000000000..4a560bd6a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/LoggingTranslator.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Abdellatif Ait boudad + */ +class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface +{ + private TranslatorInterface $translator; + private LoggerInterface $logger; + + /** + * @param TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator The translator must implement TranslatorBagInterface + */ + public function __construct(TranslatorInterface $translator, LoggerInterface $logger) + { + if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) { + throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator))); + } + + $this->translator = $translator; + $this->logger = $logger; + } + + public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string + { + $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale); + $this->log($id, $domain, $locale); + + return $trans; + } + + /** + * @return void + */ + public function setLocale(string $locale) + { + $prev = $this->translator->getLocale(); + $this->translator->setLocale($locale); + if ($prev === $locale) { + return; + } + + $this->logger->debug(sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale)); + } + + public function getLocale(): string + { + return $this->translator->getLocale(); + } + + public function getCatalogue(?string $locale = null): MessageCatalogueInterface + { + return $this->translator->getCatalogue($locale); + } + + public function getCatalogues(): array + { + return $this->translator->getCatalogues(); + } + + /** + * Gets the fallback locales. + */ + public function getFallbackLocales(): array + { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { + return $this->translator->getFallbackLocales(); + } + + return []; + } + + /** + * @return mixed + */ + public function __call(string $method, array $args) + { + return $this->translator->{$method}(...$args); + } + + /** + * Logs for missing translations. + */ + private function log(string $id, ?string $domain, ?string $locale): void + { + $domain ??= 'messages'; + + $catalogue = $this->translator->getCatalogue($locale); + if ($catalogue->defines($id, $domain)) { + return; + } + + if ($catalogue->has($id, $domain)) { + $this->logger->debug('Translation use fallback catalogue.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]); + } else { + $this->logger->warning('Translation not found.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogue.php b/.extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogue.php new file mode 100644 index 000000000..d56f04393 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogue.php @@ -0,0 +1,338 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Translation\Exception\LogicException; + +/** + * @author Fabien Potencier + */ +class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface, CatalogueMetadataAwareInterface +{ + private array $messages = []; + private array $metadata = []; + private array $catalogueMetadata = []; + private array $resources = []; + private string $locale; + private ?MessageCatalogueInterface $fallbackCatalogue = null; + private ?self $parent = null; + + /** + * @param array $messages An array of messages classified by domain + */ + public function __construct(string $locale, array $messages = []) + { + $this->locale = $locale; + $this->messages = $messages; + } + + public function getLocale(): string + { + return $this->locale; + } + + public function getDomains(): array + { + $domains = []; + + foreach ($this->messages as $domain => $messages) { + if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) { + $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX)); + } + $domains[$domain] = $domain; + } + + return array_values($domains); + } + + public function all(?string $domain = null): array + { + if (null !== $domain) { + // skip messages merge if intl-icu requested explicitly + if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) { + return $this->messages[$domain] ?? []; + } + + return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []); + } + + $allMessages = []; + + foreach ($this->messages as $domain => $messages) { + if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) { + $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX)); + $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []); + } else { + $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages; + } + } + + return $allMessages; + } + + /** + * @return void + */ + public function set(string $id, string $translation, string $domain = 'messages') + { + $this->add([$id => $translation], $domain); + } + + public function has(string $id, string $domain = 'messages'): bool + { + if (isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) { + return true; + } + + if (null !== $this->fallbackCatalogue) { + return $this->fallbackCatalogue->has($id, $domain); + } + + return false; + } + + public function defines(string $id, string $domain = 'messages'): bool + { + return isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]); + } + + public function get(string $id, string $domain = 'messages'): string + { + if (isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) { + return $this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]; + } + + if (isset($this->messages[$domain][$id])) { + return $this->messages[$domain][$id]; + } + + if (null !== $this->fallbackCatalogue) { + return $this->fallbackCatalogue->get($id, $domain); + } + + return $id; + } + + /** + * @return void + */ + public function replace(array $messages, string $domain = 'messages') + { + unset($this->messages[$domain], $this->messages[$domain.self::INTL_DOMAIN_SUFFIX]); + + $this->add($messages, $domain); + } + + /** + * @return void + */ + public function add(array $messages, string $domain = 'messages') + { + $altDomain = str_ends_with($domain, self::INTL_DOMAIN_SUFFIX) ? substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX)) : $domain.self::INTL_DOMAIN_SUFFIX; + foreach ($messages as $id => $message) { + unset($this->messages[$altDomain][$id]); + $this->messages[$domain][$id] = $message; + } + + if ([] === ($this->messages[$altDomain] ?? null)) { + unset($this->messages[$altDomain]); + } + } + + /** + * @return void + */ + public function addCatalogue(MessageCatalogueInterface $catalogue) + { + if ($catalogue->getLocale() !== $this->locale) { + throw new LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale)); + } + + foreach ($catalogue->all() as $domain => $messages) { + if ($intlMessages = $catalogue->all($domain.self::INTL_DOMAIN_SUFFIX)) { + $this->add($intlMessages, $domain.self::INTL_DOMAIN_SUFFIX); + $messages = array_diff_key($messages, $intlMessages); + } + $this->add($messages, $domain); + } + + foreach ($catalogue->getResources() as $resource) { + $this->addResource($resource); + } + + if ($catalogue instanceof MetadataAwareInterface) { + $metadata = $catalogue->getMetadata('', ''); + $this->addMetadata($metadata); + } + + if ($catalogue instanceof CatalogueMetadataAwareInterface) { + $catalogueMetadata = $catalogue->getCatalogueMetadata('', ''); + $this->addCatalogueMetadata($catalogueMetadata); + } + } + + /** + * @return void + */ + public function addFallbackCatalogue(MessageCatalogueInterface $catalogue) + { + // detect circular references + $c = $catalogue; + while ($c = $c->getFallbackCatalogue()) { + if ($c->getLocale() === $this->getLocale()) { + throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); + } + } + + $c = $this; + do { + if ($c->getLocale() === $catalogue->getLocale()) { + throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale())); + } + + foreach ($catalogue->getResources() as $resource) { + $c->addResource($resource); + } + } while ($c = $c->parent); + + $catalogue->parent = $this; + $this->fallbackCatalogue = $catalogue; + + foreach ($catalogue->getResources() as $resource) { + $this->addResource($resource); + } + } + + public function getFallbackCatalogue(): ?MessageCatalogueInterface + { + return $this->fallbackCatalogue; + } + + public function getResources(): array + { + return array_values($this->resources); + } + + /** + * @return void + */ + public function addResource(ResourceInterface $resource) + { + $this->resources[$resource->__toString()] = $resource; + } + + public function getMetadata(string $key = '', string $domain = 'messages'): mixed + { + if ('' == $domain) { + return $this->metadata; + } + + if (isset($this->metadata[$domain])) { + if ('' == $key) { + return $this->metadata[$domain]; + } + + if (isset($this->metadata[$domain][$key])) { + return $this->metadata[$domain][$key]; + } + } + + return null; + } + + /** + * @return void + */ + public function setMetadata(string $key, mixed $value, string $domain = 'messages') + { + $this->metadata[$domain][$key] = $value; + } + + /** + * @return void + */ + public function deleteMetadata(string $key = '', string $domain = 'messages') + { + if ('' == $domain) { + $this->metadata = []; + } elseif ('' == $key) { + unset($this->metadata[$domain]); + } else { + unset($this->metadata[$domain][$key]); + } + } + + public function getCatalogueMetadata(string $key = '', string $domain = 'messages'): mixed + { + if (!$domain) { + return $this->catalogueMetadata; + } + + if (isset($this->catalogueMetadata[$domain])) { + if (!$key) { + return $this->catalogueMetadata[$domain]; + } + + if (isset($this->catalogueMetadata[$domain][$key])) { + return $this->catalogueMetadata[$domain][$key]; + } + } + + return null; + } + + /** + * @return void + */ + public function setCatalogueMetadata(string $key, mixed $value, string $domain = 'messages') + { + $this->catalogueMetadata[$domain][$key] = $value; + } + + /** + * @return void + */ + public function deleteCatalogueMetadata(string $key = '', string $domain = 'messages') + { + if (!$domain) { + $this->catalogueMetadata = []; + } elseif (!$key) { + unset($this->catalogueMetadata[$domain]); + } else { + unset($this->catalogueMetadata[$domain][$key]); + } + } + + /** + * Adds current values with the new values. + * + * @param array $values Values to add + */ + private function addMetadata(array $values): void + { + foreach ($values as $domain => $keys) { + foreach ($keys as $key => $value) { + $this->setMetadata($key, $value, $domain); + } + } + } + + private function addCatalogueMetadata(array $values): void + { + foreach ($values as $domain => $keys) { + foreach ($keys as $key => $value) { + $this->setCatalogueMetadata($key, $value, $domain); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogueInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogueInterface.php new file mode 100644 index 000000000..fd0d26d7e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/MessageCatalogueInterface.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * MessageCatalogueInterface. + * + * @author Fabien Potencier + */ +interface MessageCatalogueInterface +{ + public const INTL_DOMAIN_SUFFIX = '+intl-icu'; + + /** + * Gets the catalogue locale. + */ + public function getLocale(): string; + + /** + * Gets the domains. + */ + public function getDomains(): array; + + /** + * Gets the messages within a given domain. + * + * If $domain is null, it returns all messages. + */ + public function all(?string $domain = null): array; + + /** + * Sets a message translation. + * + * @param string $id The message id + * @param string $translation The messages translation + * @param string $domain The domain name + * + * @return void + */ + public function set(string $id, string $translation, string $domain = 'messages'); + + /** + * Checks if a message has a translation. + * + * @param string $id The message id + * @param string $domain The domain name + */ + public function has(string $id, string $domain = 'messages'): bool; + + /** + * Checks if a message has a translation (it does not take into account the fallback mechanism). + * + * @param string $id The message id + * @param string $domain The domain name + */ + public function defines(string $id, string $domain = 'messages'): bool; + + /** + * Gets a message translation. + * + * @param string $id The message id + * @param string $domain The domain name + */ + public function get(string $id, string $domain = 'messages'): string; + + /** + * Sets translations for a given domain. + * + * @param array $messages An array of translations + * @param string $domain The domain name + * + * @return void + */ + public function replace(array $messages, string $domain = 'messages'); + + /** + * Adds translations for a given domain. + * + * @param array $messages An array of translations + * @param string $domain The domain name + * + * @return void + */ + public function add(array $messages, string $domain = 'messages'); + + /** + * Merges translations from the given Catalogue into the current one. + * + * The two catalogues must have the same locale. + * + * @return void + */ + public function addCatalogue(self $catalogue); + + /** + * Merges translations from the given Catalogue into the current one + * only when the translation does not exist. + * + * This is used to provide default translations when they do not exist for the current locale. + * + * @return void + */ + public function addFallbackCatalogue(self $catalogue); + + /** + * Gets the fallback catalogue. + */ + public function getFallbackCatalogue(): ?self; + + /** + * Returns an array of resources loaded to build this collection. + * + * @return ResourceInterface[] + */ + public function getResources(): array; + + /** + * Adds a resource for this collection. + * + * @return void + */ + public function addResource(ResourceInterface $resource); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/MetadataAwareInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/MetadataAwareInterface.php new file mode 100644 index 000000000..39e5326c3 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/MetadataAwareInterface.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 Symfony\Component\Translation; + +/** + * This interface is used to get, set, and delete metadata about the translation messages. + * + * @author Fabien Potencier + */ +interface MetadataAwareInterface +{ + /** + * Gets metadata for the given domain and key. + * + * Passing an empty domain will return an array with all metadata indexed by + * domain and then by key. Passing an empty key will return an array with all + * metadata for the given domain. + * + * @return mixed The value that was set or an array with the domains/keys or null + */ + public function getMetadata(string $key = '', string $domain = 'messages'): mixed; + + /** + * Adds metadata to a message domain. + * + * @return void + */ + public function setMetadata(string $key, mixed $value, string $domain = 'messages'); + + /** + * Deletes metadata for the given key and domain. + * + * Passing an empty domain will delete all metadata. Passing an empty key will + * delete all metadata for the given domain. + * + * @return void + */ + public function deleteMetadata(string $key = '', string $domain = 'messages'); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/AbstractProviderFactory.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/AbstractProviderFactory.php new file mode 100644 index 000000000..f0c11d85d --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/AbstractProviderFactory.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\Exception\IncompleteDsnException; + +abstract class AbstractProviderFactory implements ProviderFactoryInterface +{ + public function supports(Dsn $dsn): bool + { + return \in_array($dsn->getScheme(), $this->getSupportedSchemes(), true); + } + + /** + * @return string[] + */ + abstract protected function getSupportedSchemes(): array; + + protected function getUser(Dsn $dsn): string + { + return $dsn->getUser() ?? throw new IncompleteDsnException('User is not set.', $dsn->getScheme().'://'.$dsn->getHost()); + } + + protected function getPassword(Dsn $dsn): string + { + return $dsn->getPassword() ?? throw new IncompleteDsnException('Password is not set.', $dsn->getOriginalDsn()); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/Dsn.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/Dsn.php new file mode 100644 index 000000000..1d90e27f9 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/Dsn.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\MissingRequiredOptionException; + +/** + * @author Fabien Potencier + * @author Oskar Stark + */ +final class Dsn +{ + private ?string $scheme; + private ?string $host; + private ?string $user; + private ?string $password; + private ?int $port; + private ?string $path; + private array $options = []; + private string $originalDsn; + + public function __construct(#[\SensitiveParameter] string $dsn) + { + $this->originalDsn = $dsn; + + if (false === $params = parse_url($dsn)) { + throw new InvalidArgumentException('The translation provider DSN is invalid.'); + } + + if (!isset($params['scheme'])) { + throw new InvalidArgumentException('The translation provider DSN must contain a scheme.'); + } + $this->scheme = $params['scheme']; + + if (!isset($params['host'])) { + throw new InvalidArgumentException('The translation provider DSN must contain a host (use "default" by default).'); + } + $this->host = $params['host']; + + $this->user = '' !== ($params['user'] ?? '') ? rawurldecode($params['user']) : null; + $this->password = '' !== ($params['pass'] ?? '') ? rawurldecode($params['pass']) : null; + $this->port = $params['port'] ?? null; + $this->path = $params['path'] ?? null; + parse_str($params['query'] ?? '', $this->options); + } + + public function getScheme(): string + { + return $this->scheme; + } + + public function getHost(): string + { + return $this->host; + } + + public function getUser(): ?string + { + return $this->user; + } + + public function getPassword(): ?string + { + return $this->password; + } + + public function getPort(?int $default = null): ?int + { + return $this->port ?? $default; + } + + public function getOption(string $key, mixed $default = null): mixed + { + return $this->options[$key] ?? $default; + } + + public function getRequiredOption(string $key): mixed + { + if (!\array_key_exists($key, $this->options) || '' === trim($this->options[$key])) { + throw new MissingRequiredOptionException($key); + } + + return $this->options[$key]; + } + + public function getOptions(): array + { + return $this->options; + } + + public function getPath(): ?string + { + return $this->path; + } + + public function getOriginalDsn(): string + { + return $this->originalDsn; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/FilteringProvider.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/FilteringProvider.php new file mode 100644 index 000000000..d4465b9fd --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/FilteringProvider.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\TranslatorBag; +use Symfony\Component\Translation\TranslatorBagInterface; + +/** + * Filters domains and locales between the Translator config values and those specific to each provider. + * + * @author Mathieu Santostefano + */ +class FilteringProvider implements ProviderInterface +{ + private ProviderInterface $provider; + private array $locales; + private array $domains; + + public function __construct(ProviderInterface $provider, array $locales, array $domains = []) + { + $this->provider = $provider; + $this->locales = $locales; + $this->domains = $domains; + } + + public function __toString(): string + { + return (string) $this->provider; + } + + public function write(TranslatorBagInterface $translatorBag): void + { + $this->provider->write($translatorBag); + } + + public function read(array $domains, array $locales): TranslatorBag + { + $domains = !$this->domains ? $domains : array_intersect($this->domains, $domains); + $locales = array_intersect($this->locales, $locales); + + return $this->provider->read($domains, $locales); + } + + public function delete(TranslatorBagInterface $translatorBag): void + { + $this->provider->delete($translatorBag); + } + + public function getDomains(): array + { + return $this->domains; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProvider.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProvider.php new file mode 100644 index 000000000..f00392ea0 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProvider.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 Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\TranslatorBag; +use Symfony\Component\Translation\TranslatorBagInterface; + +/** + * @author Mathieu Santostefano + */ +class NullProvider implements ProviderInterface +{ + public function __toString(): string + { + return 'null'; + } + + public function write(TranslatorBagInterface $translatorBag, bool $override = false): void + { + } + + public function read(array $domains, array $locales): TranslatorBag + { + return new TranslatorBag(); + } + + public function delete(TranslatorBagInterface $translatorBag): void + { + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProviderFactory.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProviderFactory.php new file mode 100644 index 000000000..f350f1602 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/NullProviderFactory.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\Exception\UnsupportedSchemeException; + +/** + * @author Mathieu Santostefano + */ +final class NullProviderFactory extends AbstractProviderFactory +{ + public function create(Dsn $dsn): ProviderInterface + { + if ('null' === $dsn->getScheme()) { + return new NullProvider(); + } + + throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes()); + } + + protected function getSupportedSchemes(): array + { + return ['null']; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderFactoryInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderFactoryInterface.php new file mode 100644 index 000000000..3fd4494b4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderFactoryInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\Exception\IncompleteDsnException; +use Symfony\Component\Translation\Exception\UnsupportedSchemeException; + +interface ProviderFactoryInterface +{ + /** + * @throws UnsupportedSchemeException + * @throws IncompleteDsnException + */ + public function create(Dsn $dsn): ProviderInterface; + + public function supports(Dsn $dsn): bool; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderInterface.php new file mode 100644 index 000000000..0e47083b6 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/ProviderInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\TranslatorBag; +use Symfony\Component\Translation\TranslatorBagInterface; + +interface ProviderInterface extends \Stringable +{ + /** + * Translations available in the TranslatorBag only must be created. + * Translations available in both the TranslatorBag and on the provider + * must be overwritten. + * Translations available on the provider only must be kept. + */ + public function write(TranslatorBagInterface $translatorBag): void; + + public function read(array $domains, array $locales): TranslatorBag; + + public function delete(TranslatorBagInterface $translatorBag): void; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollection.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollection.php new file mode 100644 index 000000000..b917415ba --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollection.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * @author Mathieu Santostefano + */ +final class TranslationProviderCollection +{ + /** + * @var array + */ + private array $providers; + + /** + * @param array $providers + */ + public function __construct(iterable $providers) + { + $this->providers = \is_array($providers) ? $providers : iterator_to_array($providers); + } + + public function __toString(): string + { + return '['.implode(',', array_keys($this->providers)).']'; + } + + public function has(string $name): bool + { + return isset($this->providers[$name]); + } + + public function get(string $name): ProviderInterface + { + if (!$this->has($name)) { + throw new InvalidArgumentException(sprintf('Provider "%s" not found. Available: "%s".', $name, (string) $this)); + } + + return $this->providers[$name]; + } + + public function keys(): array + { + return array_keys($this->providers); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php new file mode 100644 index 000000000..6300c8750 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Provider; + +use Symfony\Component\Translation\Exception\UnsupportedSchemeException; + +/** + * @author Mathieu Santostefano + */ +class TranslationProviderCollectionFactory +{ + private iterable $factories; + private array $enabledLocales; + + /** + * @param iterable $factories + */ + public function __construct(iterable $factories, array $enabledLocales) + { + $this->factories = $factories; + $this->enabledLocales = $enabledLocales; + } + + public function fromConfig(array $config): TranslationProviderCollection + { + $providers = []; + foreach ($config as $name => $currentConfig) { + $providers[$name] = $this->fromDsnObject( + new Dsn($currentConfig['dsn']), + !$currentConfig['locales'] ? $this->enabledLocales : $currentConfig['locales'], + !$currentConfig['domains'] ? [] : $currentConfig['domains'] + ); + } + + return new TranslationProviderCollection($providers); + } + + public function fromDsnObject(Dsn $dsn, array $locales, array $domains = []): ProviderInterface + { + foreach ($this->factories as $factory) { + if ($factory->supports($dsn)) { + return new FilteringProvider($factory->create($dsn), $locales, $domains); + } + } + + throw new UnsupportedSchemeException($dsn); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/PseudoLocalizationTranslator.php b/.extlib/simplesamlphp/vendor/symfony/translation/PseudoLocalizationTranslator.php new file mode 100644 index 000000000..f26909f5e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/PseudoLocalizationTranslator.php @@ -0,0 +1,365 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * This translator should only be used in a development environment. + */ +final class PseudoLocalizationTranslator implements TranslatorInterface +{ + private const EXPANSION_CHARACTER = '~'; + + private TranslatorInterface $translator; + private bool $accents; + private float $expansionFactor; + private bool $brackets; + private bool $parseHTML; + + /** + * @var string[] + */ + private array $localizableHTMLAttributes; + + /** + * Available options: + * * accents: + * type: boolean + * default: true + * description: replace ASCII characters of the translated string with accented versions or similar characters + * example: if true, "foo" => "ƒöö". + * + * * expansion_factor: + * type: float + * default: 1 + * validation: it must be greater than or equal to 1 + * description: expand the translated string by the given factor with spaces and tildes + * example: if 2, "foo" => "~foo ~" + * + * * brackets: + * type: boolean + * default: true + * description: wrap the translated string with brackets + * example: if true, "foo" => "[foo]" + * + * * parse_html: + * type: boolean + * default: false + * description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand ot when it contains HTML + * warning: unclosed tags are unsupported, they will be fixed (closed) by the parser - eg, "foo
    bar" => "foo
    bar
    " + * + * * localizable_html_attributes: + * type: string[] + * default: [] + * description: the list of HTML attributes whose values can be altered - it is only useful when the "parse_html" option is set to true + * example: if ["title"], and with the "accents" option set to true, "Profile" => "Þŕöƒîļé" - if "title" was not in the "localizable_html_attributes" list, the title attribute data would be left unchanged. + */ + public function __construct(TranslatorInterface $translator, array $options = []) + { + $this->translator = $translator; + $this->accents = $options['accents'] ?? true; + + if (1.0 > ($this->expansionFactor = $options['expansion_factor'] ?? 1.0)) { + throw new \InvalidArgumentException('The expansion factor must be greater than or equal to 1.'); + } + + $this->brackets = $options['brackets'] ?? true; + + $this->parseHTML = $options['parse_html'] ?? false; + if ($this->parseHTML && !$this->accents && 1.0 === $this->expansionFactor) { + $this->parseHTML = false; + } + + $this->localizableHTMLAttributes = $options['localizable_html_attributes'] ?? []; + } + + public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string + { + $trans = ''; + $visibleText = ''; + + foreach ($this->getParts($this->translator->trans($id, $parameters, $domain, $locale)) as [$visible, $localizable, $text]) { + if ($visible) { + $visibleText .= $text; + } + + if (!$localizable) { + $trans .= $text; + + continue; + } + + $this->addAccents($trans, $text); + } + + $this->expand($trans, $visibleText); + + $this->addBrackets($trans); + + return $trans; + } + + public function getLocale(): string + { + return $this->translator->getLocale(); + } + + private function getParts(string $originalTrans): array + { + if (!$this->parseHTML) { + return [[true, true, $originalTrans]]; + } + + $html = mb_encode_numericentity($originalTrans, [0x80, 0x10FFFF, 0, 0x1FFFFF], mb_detect_encoding($originalTrans, null, true) ?: 'UTF-8'); + + $useInternalErrors = libxml_use_internal_errors(true); + + $dom = new \DOMDocument(); + $dom->loadHTML(''.$html.''); + + libxml_clear_errors(); + libxml_use_internal_errors($useInternalErrors); + + return $this->parseNode($dom->childNodes->item(1)->childNodes->item(0)->childNodes->item(0)); + } + + private function parseNode(\DOMNode $node): array + { + $parts = []; + + foreach ($node->childNodes as $childNode) { + if (!$childNode instanceof \DOMElement) { + $parts[] = [true, true, $childNode->nodeValue]; + + continue; + } + + $parts[] = [false, false, '<'.$childNode->tagName]; + + /** @var \DOMAttr $attribute */ + foreach ($childNode->attributes as $attribute) { + $parts[] = [false, false, ' '.$attribute->nodeName.'="']; + + $localizableAttribute = \in_array($attribute->nodeName, $this->localizableHTMLAttributes, true); + foreach (preg_split('/(&(?:amp|quot|#039|lt|gt);+)/', htmlspecialchars($attribute->nodeValue, \ENT_QUOTES, 'UTF-8'), -1, \PREG_SPLIT_DELIM_CAPTURE) as $i => $match) { + if ('' === $match) { + continue; + } + + $parts[] = [false, $localizableAttribute && 0 === $i % 2, $match]; + } + + $parts[] = [false, false, '"']; + } + + $parts[] = [false, false, '>']; + + $parts = array_merge($parts, $this->parseNode($childNode, $parts)); + + $parts[] = [false, false, 'tagName.'>']; + } + + return $parts; + } + + private function addAccents(string &$trans, string $text): void + { + $trans .= $this->accents ? strtr($text, [ + ' ' => ' ', + '!' => '¡', + '"' => '″', + '#' => '♯', + '$' => '€', + '%' => '‰', + '&' => 'â…‹', + '\'' => '´', + '(' => '{', + ')' => '}', + '*' => 'âŽ', + '+' => 'âº', + ',' => 'ØŒ', + '-' => 'â€', + '.' => '·', + '/' => 'â„', + '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' => 'Ž', + '[' => 'â…', + '\\' => '∖', + ']' => 'â†', + '^' => 'Ë„', + '_' => '‿', + '`' => '‵', + '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' => 'ž', + '{' => '(', + '|' => '¦', + '}' => ')', + '~' => 'Ëž', + ]) : $text; + } + + private function expand(string &$trans, string $visibleText): void + { + if (1.0 >= $this->expansionFactor) { + return; + } + + $visibleLength = $this->strlen($visibleText); + $missingLength = (int) ceil($visibleLength * $this->expansionFactor) - $visibleLength; + if ($this->brackets) { + $missingLength -= 2; + } + + if (0 >= $missingLength) { + return; + } + + $words = []; + $wordsCount = 0; + foreach (preg_split('/ +/', $visibleText, -1, \PREG_SPLIT_NO_EMPTY) as $word) { + $wordLength = $this->strlen($word); + + if ($wordLength >= $missingLength) { + continue; + } + + if (!isset($words[$wordLength])) { + $words[$wordLength] = 0; + } + + ++$words[$wordLength]; + ++$wordsCount; + } + + if (!$words) { + $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1); + + return; + } + + arsort($words, \SORT_NUMERIC); + + $longestWordLength = max(array_keys($words)); + + while (true) { + $r = mt_rand(1, $wordsCount); + + foreach ($words as $length => $count) { + $r -= $count; + if ($r <= 0) { + break; + } + } + + $trans .= ' '.str_repeat(self::EXPANSION_CHARACTER, $length); + + $missingLength -= $length + 1; + + if (0 === $missingLength) { + return; + } + + while ($longestWordLength >= $missingLength) { + $wordsCount -= $words[$longestWordLength]; + unset($words[$longestWordLength]); + + if (!$words) { + $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1); + + return; + } + + $longestWordLength = max(array_keys($words)); + } + } + } + + private function addBrackets(string &$trans): void + { + if (!$this->brackets) { + return; + } + + $trans = '['.$trans.']'; + } + + private function strlen(string $s): int + { + return false === ($encoding = mb_detect_encoding($s, null, true)) ? \strlen($s) : mb_strlen($s, $encoding); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/README.md b/.extlib/simplesamlphp/vendor/symfony/translation/README.md new file mode 100644 index 000000000..32e4017b7 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/README.md @@ -0,0 +1,40 @@ +Translation Component +===================== + +The Translation component provides tools to internationalize your application. + +Getting Started +--------------- + +``` +$ composer require symfony/translation +``` + +```php +use Symfony\Component\Translation\Translator; +use Symfony\Component\Translation\Loader\ArrayLoader; + +$translator = new Translator('fr_FR'); +$translator->addLoader('array', new ArrayLoader()); +$translator->addResource('array', [ + 'Hello World!' => 'Bonjour !', +], 'fr_FR'); + +echo $translator->trans('Hello World!'); // outputs « Bonjour ! » +``` + +Sponsor +------- + +Help Symfony by [sponsoring][1] its development! + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/translation.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/sponsor diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReader.php b/.extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReader.php new file mode 100644 index 000000000..01408d4dc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReader.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Reader; + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationReader reads translation messages from translation files. + * + * @author Michel Salib + */ +class TranslationReader implements TranslationReaderInterface +{ + /** + * Loaders used for import. + * + * @var array + */ + private array $loaders = []; + + /** + * Adds a loader to the translation extractor. + * + * @param string $format The format of the loader + * + * @return void + */ + public function addLoader(string $format, LoaderInterface $loader) + { + $this->loaders[$format] = $loader; + } + + /** + * @return void + */ + public function read(string $directory, MessageCatalogue $catalogue) + { + if (!is_dir($directory)) { + return; + } + + foreach ($this->loaders as $format => $loader) { + // load any existing translation files + $finder = new Finder(); + $extension = $catalogue->getLocale().'.'.$format; + $files = $finder->files()->name('*.'.$extension)->in($directory); + foreach ($files as $file) { + $domain = substr($file->getFilename(), 0, -1 * \strlen($extension) - 1); + $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain)); + } + } + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReaderInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReaderInterface.php new file mode 100644 index 000000000..ea74dc23f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Reader/TranslationReaderInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Reader; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationReader reads translation messages from translation files. + * + * @author Tobias Nyholm + */ +interface TranslationReaderInterface +{ + /** + * Reads translation messages from a directory to the catalogue. + * + * @return void + */ + public function read(string $directory, MessageCatalogue $catalogue); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Resources/bin/translation-status.php b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/bin/translation-status.php new file mode 100644 index 000000000..42fa1c69b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/bin/translation-status.php @@ -0,0 +1,274 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + +$usageInstructions = << false, + // NULL = analyze all locales + 'locale_to_analyze' => null, + // append --incomplete to only show incomplete languages + 'include_completed_languages' => true, + // the reference files all the other translations are compared to + 'original_files' => [ + 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf', + 'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf', + 'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf', + ], +]; + +$argc = $_SERVER['argc']; +$argv = $_SERVER['argv']; + +if ($argc > 4) { + echo str_replace('translation-status.php', $argv[0], $usageInstructions); + exit(1); +} + +foreach (array_slice($argv, 1) as $argumentOrOption) { + if ('--incomplete' === $argumentOrOption) { + $config['include_completed_languages'] = false; + continue; + } + + if (str_starts_with($argumentOrOption, '-')) { + $config['verbose_output'] = true; + } else { + $config['locale_to_analyze'] = $argumentOrOption; + } +} + +foreach ($config['original_files'] as $originalFilePath) { + if (!file_exists($originalFilePath)) { + echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s %s', \PHP_EOL, $originalFilePath); + exit(1); + } +} + +$totalMissingTranslations = 0; +$totalTranslationMismatches = 0; + +foreach ($config['original_files'] as $originalFilePath) { + $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']); + $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths); + + $totalMissingTranslations += array_sum(array_map(fn ($translation) => count($translation['missingKeys']), array_values($translationStatus))); + $totalTranslationMismatches += array_sum(array_map(fn ($translation) => count($translation['mismatches']), array_values($translationStatus))); + + printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output'], $config['include_completed_languages']); +} + +exit($totalTranslationMismatches > 0 ? 1 : 0); + +function findTranslationFiles($originalFilePath, $localeToAnalyze): array +{ + $translations = []; + + $translationsDir = dirname($originalFilePath); + $originalFileName = basename($originalFilePath); + $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName); + + $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern, \GLOB_NOSORT); + sort($translationFiles); + foreach ($translationFiles as $filePath) { + $locale = extractLocaleFromFilePath($filePath); + + if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) { + continue; + } + + $translations[$locale] = $filePath; + } + + return $translations; +} + +function calculateTranslationStatus($originalFilePath, $translationFilePaths): array +{ + $translationStatus = []; + $allTranslationKeys = extractTranslationKeys($originalFilePath); + + foreach ($translationFilePaths as $locale => $translationPath) { + $translatedKeys = extractTranslationKeys($translationPath); + $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys); + $mismatches = findTransUnitMismatches($allTranslationKeys, $translatedKeys); + + $translationStatus[$locale] = [ + 'total' => count($allTranslationKeys), + 'translated' => count($translatedKeys), + 'missingKeys' => $missingKeys, + 'mismatches' => $mismatches, + ]; + $translationStatus[$locale]['is_completed'] = isTranslationCompleted($translationStatus[$locale]); + } + + return $translationStatus; +} + +function isTranslationCompleted(array $translationStatus): bool +{ + return $translationStatus['total'] === $translationStatus['translated'] && 0 === count($translationStatus['mismatches']); +} + +function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput, $includeCompletedLanguages) +{ + printTitle($originalFilePath); + printTable($translationStatus, $verboseOutput, $includeCompletedLanguages); + echo \PHP_EOL.\PHP_EOL; +} + +function extractLocaleFromFilePath($filePath) +{ + $parts = explode('.', $filePath); + + return $parts[count($parts) - 2]; +} + +function extractTranslationKeys($filePath): array +{ + $translationKeys = []; + $contents = new SimpleXMLElement(file_get_contents($filePath)); + + foreach ($contents->file->body->{'trans-unit'} as $translationKey) { + $translationId = (string) $translationKey['id']; + $translationKey = (string) ($translationKey['resname'] ?? $translationKey->source); + + $translationKeys[$translationId] = $translationKey; + } + + return $translationKeys; +} + +/** + * Check whether the trans-unit id and source match with the base translation. + */ +function findTransUnitMismatches(array $baseTranslationKeys, array $translatedKeys): array +{ + $mismatches = []; + + foreach ($baseTranslationKeys as $translationId => $translationKey) { + if (!isset($translatedKeys[$translationId])) { + continue; + } + if ($translatedKeys[$translationId] !== $translationKey) { + $mismatches[$translationId] = [ + 'found' => $translatedKeys[$translationId], + 'expected' => $translationKey, + ]; + } + } + + return $mismatches; +} + +function printTitle($title) +{ + echo $title.\PHP_EOL; + echo str_repeat('=', strlen($title)).\PHP_EOL.\PHP_EOL; +} + +function printTable($translations, $verboseOutput, bool $includeCompletedLanguages) +{ + if (0 === count($translations)) { + echo 'No translations found'; + + return; + } + $longestLocaleNameLength = max(array_map('strlen', array_keys($translations))); + + foreach ($translations as $locale => $translation) { + if (!$includeCompletedLanguages && $translation['is_completed']) { + continue; + } + + if ($translation['translated'] > $translation['total']) { + textColorRed(); + } elseif (count($translation['mismatches']) > 0) { + textColorRed(); + } elseif ($translation['is_completed']) { + textColorGreen(); + } + + echo sprintf( + '| Locale: %-'.$longestLocaleNameLength.'s | Translated: %2d/%2d | Mismatches: %d |', + $locale, + $translation['translated'], + $translation['total'], + count($translation['mismatches']) + ).\PHP_EOL; + + textColorNormal(); + + $shouldBeClosed = false; + if (true === $verboseOutput && count($translation['missingKeys']) > 0) { + echo '| Missing Translations:'.\PHP_EOL; + + foreach ($translation['missingKeys'] as $id => $content) { + echo sprintf('| (id=%s) %s', $id, $content).\PHP_EOL; + } + $shouldBeClosed = true; + } + if (true === $verboseOutput && count($translation['mismatches']) > 0) { + echo '| Mismatches between trans-unit id and source:'.\PHP_EOL; + + foreach ($translation['mismatches'] as $id => $content) { + echo sprintf('| (id=%s) Expected: %s', $id, $content['expected']).\PHP_EOL; + echo sprintf('| Found: %s', $content['found']).\PHP_EOL; + } + $shouldBeClosed = true; + } + if ($shouldBeClosed) { + echo str_repeat('-', 80).\PHP_EOL; + } + } +} + +function textColorGreen() +{ + echo "\033[32m"; +} + +function textColorRed() +{ + echo "\033[31m"; +} + +function textColorNormal() +{ + echo "\033[0m"; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Resources/data/parents.json b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/data/parents.json new file mode 100644 index 000000000..24d4d119e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/data/parents.json @@ -0,0 +1,142 @@ +{ + "az_Cyrl": "root", + "bs_Cyrl": "root", + "en_150": "en_001", + "en_AG": "en_001", + "en_AI": "en_001", + "en_AT": "en_150", + "en_AU": "en_001", + "en_BB": "en_001", + "en_BE": "en_150", + "en_BM": "en_001", + "en_BS": "en_001", + "en_BW": "en_001", + "en_BZ": "en_001", + "en_CC": "en_001", + "en_CH": "en_150", + "en_CK": "en_001", + "en_CM": "en_001", + "en_CX": "en_001", + "en_CY": "en_001", + "en_DE": "en_150", + "en_DG": "en_001", + "en_DK": "en_150", + "en_DM": "en_001", + "en_ER": "en_001", + "en_FI": "en_150", + "en_FJ": "en_001", + "en_FK": "en_001", + "en_FM": "en_001", + "en_GB": "en_001", + "en_GD": "en_001", + "en_GG": "en_001", + "en_GH": "en_001", + "en_GI": "en_001", + "en_GM": "en_001", + "en_GY": "en_001", + "en_HK": "en_001", + "en_ID": "en_001", + "en_IE": "en_001", + "en_IL": "en_001", + "en_IM": "en_001", + "en_IN": "en_001", + "en_IO": "en_001", + "en_JE": "en_001", + "en_JM": "en_001", + "en_KE": "en_001", + "en_KI": "en_001", + "en_KN": "en_001", + "en_KY": "en_001", + "en_LC": "en_001", + "en_LR": "en_001", + "en_LS": "en_001", + "en_MG": "en_001", + "en_MO": "en_001", + "en_MS": "en_001", + "en_MT": "en_001", + "en_MU": "en_001", + "en_MV": "en_001", + "en_MW": "en_001", + "en_MY": "en_001", + "en_NA": "en_001", + "en_NF": "en_001", + "en_NG": "en_001", + "en_NL": "en_150", + "en_NR": "en_001", + "en_NU": "en_001", + "en_NZ": "en_001", + "en_PG": "en_001", + "en_PK": "en_001", + "en_PN": "en_001", + "en_PW": "en_001", + "en_RW": "en_001", + "en_SB": "en_001", + "en_SC": "en_001", + "en_SD": "en_001", + "en_SE": "en_150", + "en_SG": "en_001", + "en_SH": "en_001", + "en_SI": "en_150", + "en_SL": "en_001", + "en_SS": "en_001", + "en_SX": "en_001", + "en_SZ": "en_001", + "en_TC": "en_001", + "en_TK": "en_001", + "en_TO": "en_001", + "en_TT": "en_001", + "en_TV": "en_001", + "en_TZ": "en_001", + "en_UG": "en_001", + "en_VC": "en_001", + "en_VG": "en_001", + "en_VU": "en_001", + "en_WS": "en_001", + "en_ZA": "en_001", + "en_ZM": "en_001", + "en_ZW": "en_001", + "es_AR": "es_419", + "es_BO": "es_419", + "es_BR": "es_419", + "es_BZ": "es_419", + "es_CL": "es_419", + "es_CO": "es_419", + "es_CR": "es_419", + "es_CU": "es_419", + "es_DO": "es_419", + "es_EC": "es_419", + "es_GT": "es_419", + "es_HN": "es_419", + "es_MX": "es_419", + "es_NI": "es_419", + "es_PA": "es_419", + "es_PE": "es_419", + "es_PR": "es_419", + "es_PY": "es_419", + "es_SV": "es_419", + "es_US": "es_419", + "es_UY": "es_419", + "es_VE": "es_419", + "ff_Adlm": "root", + "hi_Latn": "en_IN", + "ks_Deva": "root", + "nb": "no", + "nn": "no", + "pa_Arab": "root", + "pt_AO": "pt_PT", + "pt_CH": "pt_PT", + "pt_CV": "pt_PT", + "pt_GQ": "pt_PT", + "pt_GW": "pt_PT", + "pt_LU": "pt_PT", + "pt_MO": "pt_PT", + "pt_MZ": "pt_PT", + "pt_ST": "pt_PT", + "pt_TL": "pt_PT", + "sd_Deva": "root", + "sr_Latn": "root", + "uz_Arab": "root", + "uz_Cyrl": "root", + "zh_Hant": "root", + "zh_Hant_MO": "zh_Hant_HK" +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Resources/functions.php b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/functions.php new file mode 100644 index 000000000..0d2a037a2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/functions.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +if (!\function_exists(t::class)) { + /** + * @author Nate Wiebe + */ + function t(string $message, array $parameters = [], ?string $domain = null): TranslatableMessage + { + return new TranslatableMessage($message, $parameters, $domain); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-transitional.xsd b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-transitional.xsd new file mode 100644 index 000000000..1f38de72f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-transitional.xsd @@ -0,0 +1,2261 @@ + + + + + + + + + + + + + + Values for the attribute 'context-type'. + + + + + Indicates a database content. + + + + + Indicates the content of an element within an XML document. + + + + + Indicates the name of an element within an XML document. + + + + + Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found. + + + + + Indicates a the number of parameters contained within the <source>. + + + + + Indicates notes pertaining to the parameters in the <source>. + + + + + Indicates the content of a record within a database. + + + + + Indicates the name of a record within a database. + + + + + Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file. + + + + + + + Values for the attribute 'count-type'. + + + + + Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts. + + + + + Indicates the count units are translation units existing already in the same document. + + + + + Indicates a total count. + + + + + + + Values for the attribute 'ctype' when used other elements than <ph> or <x>. + + + + + Indicates a run of bolded text. + + + + + Indicates a run of text in italics. + + + + + Indicates a run of underlined text. + + + + + Indicates a run of hyper-text. + + + + + + + Values for the attribute 'ctype' when used with <ph> or <x>. + + + + + Indicates a inline image. + + + + + Indicates a page break. + + + + + Indicates a line break. + + + + + + + + + + + + Values for the attribute 'datatype'. + + + + + Indicates Active Server Page data. + + + + + Indicates C source file data. + + + + + Indicates Channel Definition Format (CDF) data. + + + + + Indicates ColdFusion data. + + + + + Indicates C++ source file data. + + + + + Indicates C-Sharp data. + + + + + Indicates strings from C, ASM, and driver files data. + + + + + Indicates comma-separated values data. + + + + + Indicates database data. + + + + + Indicates portions of document that follows data and contains metadata. + + + + + Indicates portions of document that precedes data and contains metadata. + + + + + Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import). + + + + + Indicates standard user input screen data. + + + + + Indicates HyperText Markup Language (HTML) data - document instance. + + + + + Indicates content within an HTML document’s <body> element. + + + + + Indicates Windows INI file data. + + + + + Indicates Interleaf data. + + + + + Indicates Java source file data (extension '.java'). + + + + + Indicates Java property resource bundle data. + + + + + Indicates Java list resource bundle data. + + + + + Indicates JavaScript source file data. + + + + + Indicates JScript source file data. + + + + + Indicates information relating to formatting. + + + + + Indicates LISP source file data. + + + + + Indicates information relating to margin formats. + + + + + Indicates a file containing menu. + + + + + Indicates numerically identified string table. + + + + + Indicates Maker Interchange Format (MIF) data. + + + + + Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute. + + + + + Indicates GNU Machine Object data. + + + + + Indicates Message Librarian strings created by Novell's Message Librarian Tool. + + + + + Indicates information to be displayed at the bottom of each page of a document. + + + + + Indicates information to be displayed at the top of each page of a document. + + + + + Indicates a list of property values (e.g., settings within INI files or preferences dialog). + + + + + Indicates Pascal source file data. + + + + + Indicates Hypertext Preprocessor data. + + + + + Indicates plain text file (no formatting other than, possibly, wrapping). + + + + + Indicates GNU Portable Object file. + + + + + Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc. + + + + + Indicates Windows .NET binary resources. + + + + + Indicates Windows .NET Resources. + + + + + Indicates Rich Text Format (RTF) data. + + + + + Indicates Standard Generalized Markup Language (SGML) data - document instance. + + + + + Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD). + + + + + Indicates Scalable Vector Graphic (SVG) data. + + + + + Indicates VisualBasic Script source file. + + + + + Indicates warning message. + + + + + Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file). + + + + + Indicates Extensible HyperText Markup Language (XHTML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - document instance. + + + + + Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD). + + + + + Indicates Extensible Stylesheet Language (XSL) data. + + + + + Indicates XUL elements. + + + + + + + Values for the attribute 'mtype'. + + + + + Indicates the marked text is an abbreviation. + + + + + ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept. + + + + + ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective'). + + + + + ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging'). + + + + + ISO-12620: A proper-name term, such as the name of an agency or other proper entity. + + + + + ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another. + + + + + ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language. + + + + + Indicates the marked text is a date and/or time. + + + + + ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign. + + + + + ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form. + + + + + ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula. + + + + + ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record. + + + + + ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy'). + + + + + ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body. + + + + + ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages. + + + + + ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like. + + + + + ISO-12620 2.1.17: A unit to track object. + + + + + Indicates the marked text is a name. + + + + + ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others. + + + + + ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system. + + + + + Indicates the marked text is a phrase. + + + + + ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase. + + + + + Indicates the marked text should not be translated. + + + + + ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet. + + + + + Indicates that the marked text represents a segment. + + + + + ISO-12620 2.1.18.2: A fixed, lexicalized phrase. + + + + + ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs'). + + + + + ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system. + + + + + ISO-12620 2.1.19: A fixed chunk of recurring text. + + + + + ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof. + + + + + ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry. + + + + + ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language. + + + + + Indicates the marked text is a term. + + + + + ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted. + + + + + ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system. + + + + + ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza'). + + + + + ISO-12620 2.1.9: One of the alternate forms of a term. + + + + + + + Values for the attribute 'restype'. + + + + + Indicates a Windows RC AUTO3STATE control. + + + + + Indicates a Windows RC AUTOCHECKBOX control. + + + + + Indicates a Windows RC AUTORADIOBUTTON control. + + + + + Indicates a Windows RC BEDIT control. + + + + + Indicates a bitmap, for example a BITMAP resource in Windows. + + + + + Indicates a button object, for example a BUTTON control Windows. + + + + + Indicates a caption, such as the caption of a dialog box. + + + + + Indicates the cell in a table, for example the content of the <td> element in HTML. + + + + + Indicates check box object, for example a CHECKBOX control in Windows. + + + + + Indicates a menu item with an associated checkbox. + + + + + Indicates a list box, but with a check-box for each item. + + + + + Indicates a color selection dialog. + + + + + Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows. + + + + + Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234). + + + + + Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403). + + + + + Indicates a UI base class element that cannot be represented by any other element. + + + + + Indicates a context menu. + + + + + Indicates a Windows RC CTEXT control. + + + + + Indicates a cursor, for example a CURSOR resource in Windows. + + + + + Indicates a date/time picker. + + + + + Indicates a Windows RC DEFPUSHBUTTON control. + + + + + Indicates a dialog box. + + + + + Indicates a Windows RC DLGINIT resource block. + + + + + Indicates an edit box object, for example an EDIT control in Windows. + + + + + Indicates a filename. + + + + + Indicates a file dialog. + + + + + Indicates a footnote. + + + + + Indicates a font name. + + + + + Indicates a footer. + + + + + Indicates a frame object. + + + + + Indicates a XUL grid element. + + + + + Indicates a groupbox object, for example a GROUPBOX control in Windows. + + + + + Indicates a header item. + + + + + Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML. + + + + + Indicates a Windows RC HEDIT control. + + + + + Indicates a horizontal scrollbar. + + + + + Indicates an icon, for example an ICON resource in Windows. + + + + + Indicates a Windows RC IEDIT control. + + + + + Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF. + + + + + Indicates a label object. + + + + + Indicates a label that is also a HTML link (not necessarily a URL). + + + + + Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML). + + + + + Indicates a listbox object, for example an LISTBOX control in Windows. + + + + + Indicates an list item (an entry in a list). + + + + + Indicates a Windows RC LTEXT control. + + + + + Indicates a menu (a group of menu-items). + + + + + Indicates a toolbar containing one or more tope level menus. + + + + + Indicates a menu item (an entry in a menu). + + + + + Indicates a XUL menuseparator element. + + + + + Indicates a message, for example an entry in a MESSAGETABLE resource in Windows. + + + + + Indicates a calendar control. + + + + + Indicates an edit box beside a spin control. + + + + + Indicates a catch all for rectangular areas. + + + + + Indicates a standalone menu not necessarily associated with a menubar. + + + + + Indicates a pushbox object, for example a PUSHBOX control in Windows. + + + + + Indicates a Windows RC PUSHBUTTON control. + + + + + Indicates a radio button object. + + + + + Indicates a menuitem with associated radio button. + + + + + Indicates raw data resources for an application. + + + + + Indicates a row in a table. + + + + + Indicates a Windows RC RTEXT control. + + + + + Indicates a user navigable container used to show a portion of a document. + + + + + Indicates a generic divider object (e.g. menu group separator). + + + + + Windows accelerators, shortcuts in resource or property files. + + + + + Indicates a UI control to indicate process activity but not progress. + + + + + Indicates a splitter bar. + + + + + Indicates a Windows RC STATE3 control. + + + + + Indicates a window for providing feedback to the users, like 'read-only', etc. + + + + + Indicates a string, for example an entry in a STRINGTABLE resource in Windows. + + + + + Indicates a layers of controls with a tab to select layers. + + + + + Indicates a display and edits regular two-dimensional tables of cells. + + + + + Indicates a XUL textbox element. + + + + + Indicates a UI button that can be toggled to on or off state. + + + + + Indicates an array of controls, usually buttons. + + + + + Indicates a pop up tool tip text. + + + + + Indicates a bar with a pointer indicating a position within a certain range. + + + + + Indicates a control that displays a set of hierarchical data. + + + + + Indicates a URI (URN or URL). + + + + + Indicates a Windows RC USERBUTTON control. + + + + + Indicates a user-defined control like CONTROL control in Windows. + + + + + Indicates the text of a variable. + + + + + Indicates version information about a resource like VERSIONINFO in Windows. + + + + + Indicates a vertical scrollbar. + + + + + Indicates a graphical window. + + + + + + + Values for the attribute 'size-unit'. + + + + + Indicates a size in 8-bit bytes. + + + + + Indicates a size in Unicode characters. + + + + + Indicates a size in columns. Used for HTML text area. + + + + + Indicates a size in centimeters. + + + + + Indicates a size in dialog units, as defined in Windows resources. + + + + + Indicates a size in 'font-size' units (as defined in CSS). + + + + + Indicates a size in 'x-height' units (as defined in CSS). + + + + + Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster' + + + + + Indicates a size in inches. + + + + + Indicates a size in millimeters. + + + + + Indicates a size in percentage. + + + + + Indicates a size in pixels. + + + + + Indicates a size in point. + + + + + Indicates a size in rows. Used for HTML text area. + + + + + + + Values for the attribute 'state'. + + + + + Indicates the terminating state. + + + + + Indicates only non-textual information needs adaptation. + + + + + Indicates both text and non-textual information needs adaptation. + + + + + Indicates only non-textual information needs review. + + + + + Indicates both text and non-textual information needs review. + + + + + Indicates that only the text of the item needs to be reviewed. + + + + + Indicates that the item needs to be translated. + + + + + Indicates that the item is new. For example, translation units that were not in a previous version of the document. + + + + + Indicates that changes are reviewed and approved. + + + + + Indicates that the item has been translated. + + + + + + + Values for the attribute 'state-qualifier'. + + + + + Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously. + + + + + Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.). + + + + + Indicates a match based on matching IDs (in addition to matching text). + + + + + Indicates a translation derived from a glossary. + + + + + Indicates a translation derived from existing translation. + + + + + Indicates a translation derived from machine translation. + + + + + Indicates a translation derived from a translation repository. + + + + + Indicates a translation derived from a translation memory. + + + + + Indicates the translation is suggested by machine translation. + + + + + Indicates that the item has been rejected because of incorrect grammar. + + + + + Indicates that the item has been rejected because it is incorrect. + + + + + Indicates that the item has been rejected because it is too long or too short. + + + + + Indicates that the item has been rejected because of incorrect spelling. + + + + + Indicates the translation is suggested by translation memory. + + + + + + + Values for the attribute 'unit'. + + + + + Refers to words. + + + + + Refers to pages. + + + + + Refers to <trans-unit> elements. + + + + + Refers to <bin-unit> elements. + + + + + Refers to glyphs. + + + + + Refers to <trans-unit> and/or <bin-unit> elements. + + + + + Refers to the occurrences of instances defined by the count-type value. + + + + + Refers to characters. + + + + + Refers to lines. + + + + + Refers to sentences. + + + + + Refers to paragraphs. + + + + + Refers to segments. + + + + + Refers to placeables (inline elements). + + + + + + + Values for the attribute 'priority'. + + + + + Highest priority. + + + + + High priority. + + + + + High priority, but not as important as 2. + + + + + High priority, but not as important as 3. + + + + + Medium priority, but more important than 6. + + + + + Medium priority, but less important than 5. + + + + + Low priority, but more important than 8. + + + + + Low priority, but more important than 9. + + + + + Low priority. + + + + + Lowest priority. + + + + + + + + + This value indicates that all properties can be reformatted. This value must be used alone. + + + + + This value indicates that no properties should be reformatted. This value must be used alone. + + + + + + + + + + + + + This value indicates that all information in the coord attribute can be modified. + + + + + This value indicates that the x information in the coord attribute can be modified. + + + + + This value indicates that the y information in the coord attribute can be modified. + + + + + This value indicates that the cx information in the coord attribute can be modified. + + + + + This value indicates that the cy information in the coord attribute can be modified. + + + + + This value indicates that all the information in the font attribute can be modified. + + + + + This value indicates that the name information in the font attribute can be modified. + + + + + This value indicates that the size information in the font attribute can be modified. + + + + + This value indicates that the weight information in the font attribute can be modified. + + + + + This value indicates that the information in the css-style attribute can be modified. + + + + + This value indicates that the information in the style attribute can be modified. + + + + + This value indicates that the information in the exstyle attribute can be modified. + + + + + + + + + + + + + Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document. + + + + + Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed. + + + + + Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed. + + + + + + + + + Represents a translation proposal from a translation memory or other resource. + + + + + Represents a previous version of the target element. + + + + + Represents a rejected version of the target element. + + + + + Represents a translation to be used for reference purposes only, for example from a related product or a different language. + + + + + Represents a proposed translation that was used for the translation of the trans-unit, possibly modified. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Values for the attribute 'coord'. + + + + + + + + Version values: 1.0 and 1.1 are allowed for backward compatibility. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd new file mode 100644 index 000000000..963232f97 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xml.xsd b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xml.xsd new file mode 100644 index 000000000..a46162a7a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Resources/schemas/xml.xsd @@ -0,0 +1,309 @@ + + + + + + +
    +

    About the XML namespace

    + +
    +

    + + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

    +

    + See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

    + +

    + Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

    +

    + See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

    +
    +
    + +
    +
    + + + + +
    + +

    lang (as an attribute name)

    +

    + + denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

    + +
    +
    +

    Notes

    +

    + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

    +

    + + See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

    +

    + + The union allows for the 'un-declaration' of xml:lang with + the empty string. +

    +
    +
    +
    + + + + + + + + + + +
    + + + + + +
    + +

    space (as an attribute name)

    +

    + denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

    + +
    +
    +
    + + + + + + + +
    + + + + +
    + +

    base (as an attribute name)

    +

    + denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

    + +

    + See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

    + +
    +
    +
    +
    + + + + +
    + +

    id (as an attribute name)

    +

    + + denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

    + +

    + See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

    +
    +
    +
    + +
    + + + + + + + + + + + +
    + +

    Father (in any context at all)

    + +
    +

    + denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

    +
    +

    + + In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

    +
    +
    +
    +
    +
    + + + + +
    +

    About this schema document

    + +
    +

    + This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

    + +

    + To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

    +
    +          <schema.. .>
    +          .. .
    +           <import namespace="http://www.w3.org/XML/1998/namespace"
    +                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
    +     
    +

    + or +

    +
    +
    +           <import namespace="http://www.w3.org/XML/1998/namespace"
    +                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
    +     
    +

    + Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

    +
    +          <type.. .>
    +          .. .
    +           <attributeGroup ref="xml:specialAttrs"/>
    +     
    +

    + will define a type which will schema-validate an instance element + with any of those attributes. +

    + +
    +
    +
    +
    + + + +
    +

    Versioning policy for this schema document

    + +
    +

    + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

    +

    + At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

    + +

    + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

    +

    + + Previous dated (and unchanging) versions of this schema + document are at: +

    + +
    +
    +
    +
    + +
    diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderFactoryTestCase.php b/.extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderFactoryTestCase.php new file mode 100644 index 000000000..95ffcb1e5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderFactoryTestCase.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Test; + +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\Translation\Dumper\XliffFileDumper; +use Symfony\Component\Translation\Exception\IncompleteDsnException; +use Symfony\Component\Translation\Exception\UnsupportedSchemeException; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\Provider\Dsn; +use Symfony\Component\Translation\Provider\ProviderFactoryInterface; +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * A test case to ease testing a translation provider factory. + * + * @author Mathieu Santostefano + */ +abstract class ProviderFactoryTestCase extends TestCase +{ + protected HttpClientInterface $client; + protected LoggerInterface|MockObject $logger; + protected string $defaultLocale; + protected LoaderInterface|MockObject $loader; + protected XliffFileDumper|MockObject $xliffFileDumper; + protected TranslatorBagInterface|MockObject $translatorBag; + + abstract public function createFactory(): ProviderFactoryInterface; + + /** + * @return iterable + */ + abstract public static function supportsProvider(): iterable; + + /** + * @return iterable + */ + abstract public static function createProvider(): iterable; + + /** + * @return iterable + */ + public static function unsupportedSchemeProvider(): iterable + { + return []; + } + + /** + * @return iterable + */ + public static function incompleteDsnProvider(): iterable + { + return []; + } + + /** + * @dataProvider supportsProvider + */ + public function testSupports(bool $expected, string $dsn) + { + $factory = $this->createFactory(); + + $this->assertSame($expected, $factory->supports(new Dsn($dsn))); + } + + /** + * @dataProvider createProvider + */ + public function testCreate(string $expected, string $dsn) + { + $factory = $this->createFactory(); + $provider = $factory->create(new Dsn($dsn)); + + $this->assertSame($expected, (string) $provider); + } + + /** + * @dataProvider unsupportedSchemeProvider + */ + public function testUnsupportedSchemeException(string $dsn, ?string $message = null) + { + $factory = $this->createFactory(); + + $dsn = new Dsn($dsn); + + $this->expectException(UnsupportedSchemeException::class); + if (null !== $message) { + $this->expectExceptionMessage($message); + } + + $factory->create($dsn); + } + + /** + * @dataProvider incompleteDsnProvider + */ + public function testIncompleteDsnException(string $dsn, ?string $message = null) + { + $factory = $this->createFactory(); + + $dsn = new Dsn($dsn); + + $this->expectException(IncompleteDsnException::class); + if (null !== $message) { + $this->expectExceptionMessage($message); + } + + $factory->create($dsn); + } + + protected function getClient(): HttpClientInterface + { + return $this->client ??= new MockHttpClient(); + } + + protected function getLogger(): LoggerInterface + { + return $this->logger ??= $this->createMock(LoggerInterface::class); + } + + protected function getDefaultLocale(): string + { + return $this->defaultLocale ??= 'en'; + } + + protected function getLoader(): LoaderInterface + { + return $this->loader ??= $this->createMock(LoaderInterface::class); + } + + protected function getXliffFileDumper(): XliffFileDumper + { + return $this->xliffFileDumper ??= $this->createMock(XliffFileDumper::class); + } + + protected function getTranslatorBag(): TranslatorBagInterface + { + return $this->translatorBag ??= $this->createMock(TranslatorBagInterface::class); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderTestCase.php b/.extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderTestCase.php new file mode 100644 index 000000000..a8fa0b8bb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Test/ProviderTestCase.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Test; + +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\Translation\Dumper\XliffFileDumper; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\Provider\ProviderInterface; +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * A test case to ease testing a translation provider. + * + * @author Mathieu Santostefano + */ +abstract class ProviderTestCase extends TestCase +{ + protected HttpClientInterface $client; + protected LoggerInterface|MockObject $logger; + protected string $defaultLocale; + protected LoaderInterface|MockObject $loader; + protected XliffFileDumper|MockObject $xliffFileDumper; + protected TranslatorBagInterface|MockObject $translatorBag; + + abstract public static function createProvider(HttpClientInterface $client, LoaderInterface $loader, LoggerInterface $logger, string $defaultLocale, string $endpoint): ProviderInterface; + + /** + * @return iterable + */ + abstract public static function toStringProvider(): iterable; + + /** + * @dataProvider toStringProvider + */ + public function testToString(ProviderInterface $provider, string $expected) + { + $this->assertSame($expected, (string) $provider); + } + + protected function getClient(): MockHttpClient + { + return $this->client ??= new MockHttpClient(); + } + + protected function getLoader(): LoaderInterface + { + return $this->loader ??= $this->createMock(LoaderInterface::class); + } + + protected function getLogger(): LoggerInterface + { + return $this->logger ??= $this->createMock(LoggerInterface::class); + } + + protected function getDefaultLocale(): string + { + return $this->defaultLocale ??= 'en'; + } + + protected function getXliffFileDumper(): XliffFileDumper + { + return $this->xliffFileDumper ??= $this->createMock(XliffFileDumper::class); + } + + protected function getTranslatorBag(): TranslatorBagInterface + { + return $this->translatorBag ??= $this->createMock(TranslatorBagInterface::class); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/TranslatableMessage.php b/.extlib/simplesamlphp/vendor/symfony/translation/TranslatableMessage.php new file mode 100644 index 000000000..c591e68c2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/TranslatableMessage.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 Symfony\Component\Translation; + +use Symfony\Contracts\Translation\TranslatableInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Nate Wiebe + */ +class TranslatableMessage implements TranslatableInterface +{ + private string $message; + private array $parameters; + private ?string $domain; + + public function __construct(string $message, array $parameters = [], ?string $domain = null) + { + $this->message = $message; + $this->parameters = $parameters; + $this->domain = $domain; + } + + public function __toString(): string + { + return $this->getMessage(); + } + + public function getMessage(): string + { + return $this->message; + } + + public function getParameters(): array + { + return $this->parameters; + } + + public function getDomain(): ?string + { + return $this->domain; + } + + public function trans(TranslatorInterface $translator, ?string $locale = null): string + { + return $translator->trans($this->getMessage(), array_map( + static fn ($parameter) => $parameter instanceof TranslatableInterface ? $parameter->trans($translator, $locale) : $parameter, + $this->getParameters() + ), $this->getDomain(), $locale); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Translator.php b/.extlib/simplesamlphp/vendor/symfony/translation/Translator.php new file mode 100644 index 000000000..1973d079f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Translator.php @@ -0,0 +1,472 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Config\ConfigCacheFactory; +use Symfony\Component\Config\ConfigCacheFactoryInterface; +use Symfony\Component\Config\ConfigCacheInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\NotFoundResourceException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\Formatter\IntlFormatterInterface; +use Symfony\Component\Translation\Formatter\MessageFormatter; +use Symfony\Component\Translation\Formatter\MessageFormatterInterface; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatableInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +// Help opcache.preload discover always-needed symbols +class_exists(MessageCatalogue::class); + +/** + * @author Fabien Potencier + */ +class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface +{ + /** + * @var MessageCatalogueInterface[] + */ + protected $catalogues = []; + + private string $locale; + + /** + * @var string[] + */ + private array $fallbackLocales = []; + + /** + * @var LoaderInterface[] + */ + private array $loaders = []; + + private array $resources = []; + + private MessageFormatterInterface $formatter; + + private ?string $cacheDir; + + private bool $debug; + + private array $cacheVary; + + private ?ConfigCacheFactoryInterface $configCacheFactory; + + private array $parentLocales; + + private bool $hasIntlFormatter; + + /** + * @throws InvalidArgumentException If a locale contains invalid characters + */ + public function __construct(string $locale, ?MessageFormatterInterface $formatter = null, ?string $cacheDir = null, bool $debug = false, array $cacheVary = []) + { + $this->setLocale($locale); + + $this->formatter = $formatter ??= new MessageFormatter(); + $this->cacheDir = $cacheDir; + $this->debug = $debug; + $this->cacheVary = $cacheVary; + $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface; + } + + /** + * @return void + */ + public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) + { + $this->configCacheFactory = $configCacheFactory; + } + + /** + * Adds a Loader. + * + * @param string $format The name of the loader (@see addResource()) + * + * @return void + */ + public function addLoader(string $format, LoaderInterface $loader) + { + $this->loaders[$format] = $loader; + } + + /** + * Adds a Resource. + * + * @param string $format The name of the loader (@see addLoader()) + * @param mixed $resource The resource name + * + * @return void + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null) + { + $domain ??= 'messages'; + + $this->assertValidLocale($locale); + $locale ?: $locale = class_exists(\Locale::class) ? \Locale::getDefault() : 'en'; + + $this->resources[$locale][] = [$format, $resource, $domain]; + + if (\in_array($locale, $this->fallbackLocales)) { + $this->catalogues = []; + } else { + unset($this->catalogues[$locale]); + } + } + + /** + * @return void + */ + public function setLocale(string $locale) + { + $this->assertValidLocale($locale); + $this->locale = $locale; + } + + public function getLocale(): string + { + return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en'); + } + + /** + * Sets the fallback locales. + * + * @param string[] $locales + * + * @return void + * + * @throws InvalidArgumentException If a locale contains invalid characters + */ + public function setFallbackLocales(array $locales) + { + // needed as the fallback locales are linked to the already loaded catalogues + $this->catalogues = []; + + foreach ($locales as $locale) { + $this->assertValidLocale($locale); + } + + $this->fallbackLocales = $this->cacheVary['fallback_locales'] = $locales; + } + + /** + * Gets the fallback locales. + * + * @internal + */ + public function getFallbackLocales(): array + { + return $this->fallbackLocales; + } + + public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string + { + if (null === $id || '' === $id) { + return ''; + } + + $domain ??= 'messages'; + + $catalogue = $this->getCatalogue($locale); + $locale = $catalogue->getLocale(); + while (!$catalogue->defines($id, $domain)) { + if ($cat = $catalogue->getFallbackCatalogue()) { + $catalogue = $cat; + $locale = $catalogue->getLocale(); + } else { + break; + } + } + + $parameters = array_map(fn ($parameter) => $parameter instanceof TranslatableInterface ? $parameter->trans($this, $locale) : $parameter, $parameters); + + $len = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX); + if ($this->hasIntlFormatter + && ($catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX) + || (\strlen($domain) > $len && 0 === substr_compare($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX, -$len, $len))) + ) { + return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters); + } + + return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters); + } + + public function getCatalogue(?string $locale = null): MessageCatalogueInterface + { + if (!$locale) { + $locale = $this->getLocale(); + } else { + $this->assertValidLocale($locale); + } + + if (!isset($this->catalogues[$locale])) { + $this->loadCatalogue($locale); + } + + return $this->catalogues[$locale]; + } + + public function getCatalogues(): array + { + return array_values($this->catalogues); + } + + /** + * Gets the loaders. + * + * @return LoaderInterface[] + */ + protected function getLoaders(): array + { + return $this->loaders; + } + + /** + * @return void + */ + protected function loadCatalogue(string $locale) + { + if (null === $this->cacheDir) { + $this->initializeCatalogue($locale); + } else { + $this->initializeCacheCatalogue($locale); + } + } + + /** + * @return void + */ + protected function initializeCatalogue(string $locale) + { + $this->assertValidLocale($locale); + + try { + $this->doLoadCatalogue($locale); + } catch (NotFoundResourceException $e) { + if (!$this->computeFallbackLocales($locale)) { + throw $e; + } + } + $this->loadFallbackCatalogues($locale); + } + + private function initializeCacheCatalogue(string $locale): void + { + if (isset($this->catalogues[$locale])) { + /* Catalogue already initialized. */ + return; + } + + $this->assertValidLocale($locale); + $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale), + function (ConfigCacheInterface $cache) use ($locale) { + $this->dumpCatalogue($locale, $cache); + } + ); + + if (isset($this->catalogues[$locale])) { + /* Catalogue has been initialized as it was written out to cache. */ + return; + } + + /* Read catalogue from cache. */ + $this->catalogues[$locale] = include $cache->getPath(); + } + + private function dumpCatalogue(string $locale, ConfigCacheInterface $cache): void + { + $this->initializeCatalogue($locale); + $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]); + + $content = sprintf(<<getAllMessages($this->catalogues[$locale]), true), + $fallbackContent + ); + + $cache->write($content, $this->catalogues[$locale]->getResources()); + } + + private function getFallbackContent(MessageCatalogue $catalogue): string + { + $fallbackContent = ''; + $current = ''; + $replacementPattern = '/[^a-z0-9_]/i'; + $fallbackCatalogue = $catalogue->getFallbackCatalogue(); + while ($fallbackCatalogue) { + $fallback = $fallbackCatalogue->getLocale(); + $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback)); + $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current)); + + $fallbackContent .= sprintf(<<<'EOF' +$catalogue%s = new MessageCatalogue('%s', %s); +$catalogue%s->addFallbackCatalogue($catalogue%s); + +EOF + , + $fallbackSuffix, + $fallback, + var_export($this->getAllMessages($fallbackCatalogue), true), + $currentSuffix, + $fallbackSuffix + ); + $current = $fallbackCatalogue->getLocale(); + $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue(); + } + + return $fallbackContent; + } + + private function getCatalogueCachePath(string $locale): string + { + return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->cacheVary), true)), 0, 7), '/', '_').'.php'; + } + + /** + * @internal + */ + protected function doLoadCatalogue(string $locale): void + { + $this->catalogues[$locale] = new MessageCatalogue($locale); + + if (isset($this->resources[$locale])) { + foreach ($this->resources[$locale] as $resource) { + if (!isset($this->loaders[$resource[0]])) { + if (\is_string($resource[1])) { + throw new RuntimeException(sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1])); + } + + throw new RuntimeException(sprintf('No loader is registered for the "%s" format.', $resource[0])); + } + $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2])); + } + } + } + + private function loadFallbackCatalogues(string $locale): void + { + $current = $this->catalogues[$locale]; + + foreach ($this->computeFallbackLocales($locale) as $fallback) { + if (!isset($this->catalogues[$fallback])) { + $this->initializeCatalogue($fallback); + } + + $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback])); + foreach ($this->catalogues[$fallback]->getResources() as $resource) { + $fallbackCatalogue->addResource($resource); + } + $current->addFallbackCatalogue($fallbackCatalogue); + $current = $fallbackCatalogue; + } + } + + /** + * @return array + */ + protected function computeFallbackLocales(string $locale) + { + $this->parentLocales ??= json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true); + + $originLocale = $locale; + $locales = []; + + while ($locale) { + $parent = $this->parentLocales[$locale] ?? null; + + if ($parent) { + $locale = 'root' !== $parent ? $parent : null; + } elseif (\function_exists('locale_parse')) { + $localeSubTags = locale_parse($locale); + $locale = null; + if (1 < \count($localeSubTags)) { + array_pop($localeSubTags); + $locale = locale_compose($localeSubTags) ?: null; + } + } elseif ($i = strrpos($locale, '_') ?: strrpos($locale, '-')) { + $locale = substr($locale, 0, $i); + } else { + $locale = null; + } + + if (null !== $locale) { + $locales[] = $locale; + } + } + + foreach ($this->fallbackLocales as $fallback) { + if ($fallback === $originLocale) { + continue; + } + + $locales[] = $fallback; + } + + return array_unique($locales); + } + + /** + * Asserts that the locale is valid, throws an Exception if not. + * + * @return void + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + protected function assertValidLocale(string $locale) + { + if (!preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) { + throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale)); + } + } + + /** + * Provides the ConfigCache factory implementation, falling back to a + * default implementation if necessary. + */ + private function getConfigCacheFactory(): ConfigCacheFactoryInterface + { + $this->configCacheFactory ??= new ConfigCacheFactory($this->debug); + + return $this->configCacheFactory; + } + + private function getAllMessages(MessageCatalogueInterface $catalogue): array + { + $allMessages = []; + + foreach ($catalogue->all() as $domain => $messages) { + if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) { + $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages; + $messages = array_diff_key($messages, $intlMessages); + } + if ($messages) { + $allMessages[$domain] = $messages; + } + } + + return $allMessages; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/TranslatorBag.php b/.extlib/simplesamlphp/vendor/symfony/translation/TranslatorBag.php new file mode 100644 index 000000000..3b47aecee --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/TranslatorBag.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Translation\Catalogue\AbstractOperation; +use Symfony\Component\Translation\Catalogue\TargetOperation; + +final class TranslatorBag implements TranslatorBagInterface +{ + /** @var MessageCatalogue[] */ + private array $catalogues = []; + + public function addCatalogue(MessageCatalogue $catalogue): void + { + if (null !== $existingCatalogue = $this->getCatalogue($catalogue->getLocale())) { + $catalogue->addCatalogue($existingCatalogue); + } + + $this->catalogues[$catalogue->getLocale()] = $catalogue; + } + + public function addBag(TranslatorBagInterface $bag): void + { + foreach ($bag->getCatalogues() as $catalogue) { + $this->addCatalogue($catalogue); + } + } + + public function getCatalogue(?string $locale = null): MessageCatalogueInterface + { + if (null === $locale || !isset($this->catalogues[$locale])) { + $this->catalogues[$locale] = new MessageCatalogue($locale); + } + + return $this->catalogues[$locale]; + } + + public function getCatalogues(): array + { + return array_values($this->catalogues); + } + + public function diff(TranslatorBagInterface $diffBag): self + { + $diff = new self(); + + foreach ($this->catalogues as $locale => $catalogue) { + if (null === $diffCatalogue = $diffBag->getCatalogue($locale)) { + $diff->addCatalogue($catalogue); + + continue; + } + + $operation = new TargetOperation($diffCatalogue, $catalogue); + $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::NEW_BATCH); + $newCatalogue = new MessageCatalogue($locale); + + foreach ($catalogue->getDomains() as $domain) { + $newCatalogue->add($operation->getNewMessages($domain), $domain); + } + + $diff->addCatalogue($newCatalogue); + } + + return $diff; + } + + public function intersect(TranslatorBagInterface $intersectBag): self + { + $diff = new self(); + + foreach ($this->catalogues as $locale => $catalogue) { + if (null === $intersectCatalogue = $intersectBag->getCatalogue($locale)) { + continue; + } + + $operation = new TargetOperation($catalogue, $intersectCatalogue); + $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::OBSOLETE_BATCH); + $obsoleteCatalogue = new MessageCatalogue($locale); + + foreach ($operation->getDomains() as $domain) { + $obsoleteCatalogue->add( + array_diff($operation->getMessages($domain), $operation->getNewMessages($domain)), + $domain + ); + } + + $diff->addCatalogue($obsoleteCatalogue); + } + + return $diff; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/TranslatorBagInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/TranslatorBagInterface.php new file mode 100644 index 000000000..365d1f13b --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/TranslatorBagInterface.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; + +/** + * @author Abdellatif Ait boudad + */ +interface TranslatorBagInterface +{ + /** + * Gets the catalogue by locale. + * + * @param string|null $locale The locale or null to use the default + * + * @throws InvalidArgumentException If the locale contains invalid characters + */ + public function getCatalogue(?string $locale = null): MessageCatalogueInterface; + + /** + * Returns all catalogues of the instance. + * + * @return MessageCatalogueInterface[] + */ + public function getCatalogues(): array; +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Util/ArrayConverter.php b/.extlib/simplesamlphp/vendor/symfony/translation/Util/ArrayConverter.php new file mode 100644 index 000000000..64e15b485 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Util/ArrayConverter.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 Symfony\Component\Translation\Util; + +/** + * ArrayConverter generates tree like structure from a message catalogue. + * e.g. this + * 'foo.bar1' => 'test1', + * 'foo.bar2' => 'test2' + * converts to follows: + * foo: + * bar1: test1 + * bar2: test2. + * + * @author Gennady Telegin + */ +class ArrayConverter +{ + /** + * Converts linear messages array to tree-like array. + * For example this array('foo.bar' => 'value') will be converted to ['foo' => ['bar' => 'value']]. + * + * @param array $messages Linear messages array + */ + public static function expandToTree(array $messages): array + { + $tree = []; + + foreach ($messages as $id => $value) { + $referenceToElement = &self::getElementByPath($tree, self::getKeyParts($id)); + + $referenceToElement = $value; + + unset($referenceToElement); + } + + return $tree; + } + + private static function &getElementByPath(array &$tree, array $parts): mixed + { + $elem = &$tree; + $parentOfElem = null; + + foreach ($parts as $i => $part) { + if (isset($elem[$part]) && \is_string($elem[$part])) { + /* Process next case: + * 'foo': 'test1', + * 'foo.bar': 'test2' + * + * $tree['foo'] was string before we found array {bar: test2}. + * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2'; + */ + $elem = &$elem[implode('.', \array_slice($parts, $i))]; + break; + } + + $parentOfElem = &$elem; + $elem = &$elem[$part]; + } + + if ($elem && \is_array($elem) && $parentOfElem) { + /* Process next case: + * 'foo.bar': 'test1' + * 'foo': 'test2' + * + * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`. + * Cancel treating $tree['foo'] as array and cancel back it expansion, + * e.g. make it $tree['foo.bar'] = 'test1' again. + */ + self::cancelExpand($parentOfElem, $part, $elem); + } + + return $elem; + } + + private static function cancelExpand(array &$tree, string $prefix, array $node): void + { + $prefix .= '.'; + + foreach ($node as $id => $value) { + if (\is_string($value)) { + $tree[$prefix.$id] = $value; + } else { + self::cancelExpand($tree, $prefix.$id, $value); + } + } + } + + /** + * @return string[] + */ + private static function getKeyParts(string $key): array + { + $parts = explode('.', $key); + $partsCount = \count($parts); + + $result = []; + $buffer = ''; + + foreach ($parts as $index => $part) { + if (0 === $index && '' === $part) { + $buffer = '.'; + + continue; + } + + if ($index === $partsCount - 1 && '' === $part) { + $buffer .= '.'; + $result[] = $buffer; + + continue; + } + + if (isset($parts[$index + 1]) && '' === $parts[$index + 1]) { + $buffer .= $part; + + continue; + } + + if ($buffer) { + $result[] = $buffer.$part; + $buffer = ''; + + continue; + } + + $result[] = $part; + } + + return $result; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Util/XliffUtils.php b/.extlib/simplesamlphp/vendor/symfony/translation/Util/XliffUtils.php new file mode 100644 index 000000000..335c34beb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Util/XliffUtils.php @@ -0,0 +1,191 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Util; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\InvalidResourceException; + +/** + * Provides some utility methods for XLIFF translation files, such as validating + * their contents according to the XSD schema. + * + * @author Fabien Potencier + */ +class XliffUtils +{ + /** + * Gets xliff file version based on the root "version" attribute. + * + * Defaults to 1.2 for backwards compatibility. + * + * @throws InvalidArgumentException + */ + public static function getVersionNumber(\DOMDocument $dom): string + { + /** @var \DOMNode $xliff */ + foreach ($dom->getElementsByTagName('xliff') as $xliff) { + $version = $xliff->attributes->getNamedItem('version'); + if ($version) { + return $version->nodeValue; + } + + $namespace = $xliff->attributes->getNamedItem('xmlns'); + if ($namespace) { + if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) { + throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s".', $namespace)); + } + + return substr($namespace, 34); + } + } + + // Falls back to v1.2 + return '1.2'; + } + + /** + * Validates and parses the given file into a DOMDocument. + * + * @throws InvalidResourceException + */ + public static function validateSchema(\DOMDocument $dom): array + { + $xliffVersion = static::getVersionNumber($dom); + $internalErrors = libxml_use_internal_errors(true); + if ($shouldEnable = self::shouldEnableEntityLoader()) { + $disableEntities = libxml_disable_entity_loader(false); + } + try { + $isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion)); + if (!$isValid) { + return self::getXmlErrors($internalErrors); + } + } finally { + if ($shouldEnable) { + libxml_disable_entity_loader($disableEntities); + } + } + + $dom->normalizeDocument(); + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return []; + } + + private static function shouldEnableEntityLoader(): bool + { + static $dom, $schema; + if (null === $dom) { + $dom = new \DOMDocument(); + $dom->loadXML(''); + + $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); + register_shutdown_function(static function () use ($tmpfile) { + @unlink($tmpfile); + }); + $schema = ' + + +'; + file_put_contents($tmpfile, ' + + + +'); + } + + return !@$dom->schemaValidateSource($schema); + } + + public static function getErrorsAsString(array $xmlErrors): string + { + $errorsAsString = ''; + + foreach ($xmlErrors as $error) { + $errorsAsString .= sprintf("[%s %s] %s (in %s - line %d, column %d)\n", + \LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR', + $error['code'], + $error['message'], + $error['file'], + $error['line'], + $error['column'] + ); + } + + return $errorsAsString; + } + + private static function getSchema(string $xliffVersion): string + { + if ('1.2' === $xliffVersion) { + $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-1.2-transitional.xsd'); + $xmlUri = 'http://www.w3.org/2001/xml.xsd'; + } elseif ('2.0' === $xliffVersion) { + $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd'); + $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd'; + } else { + throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion)); + } + + return self::fixXmlLocation($schemaSource, $xmlUri); + } + + /** + * Internally changes the URI of a dependent xsd to be loaded locally. + */ + private static function fixXmlLocation(string $schemaSource, string $xmlUri): string + { + $newPath = str_replace('\\', '/', __DIR__).'/../Resources/schemas/xml.xsd'; + $parts = explode('/', $newPath); + $locationstart = 'file:///'; + if (0 === stripos($newPath, 'phar://')) { + $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); + if ($tmpfile) { + copy($newPath, $tmpfile); + $parts = explode('/', str_replace('\\', '/', $tmpfile)); + } else { + array_shift($parts); + $locationstart = 'phar:///'; + } + } + + $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; + $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); + + return str_replace($xmlUri, $newPath, $schemaSource); + } + + /** + * Returns the XML errors of the internal XML parser. + */ + private static function getXmlErrors(bool $internalErrors): array + { + $errors = []; + foreach (libxml_get_errors() as $error) { + $errors[] = [ + 'level' => \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', + 'code' => $error->code, + 'message' => trim($error->message), + 'file' => $error->file ?: 'n/a', + 'line' => $error->line, + 'column' => $error->column, + ]; + } + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return $errors; + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriter.php b/.extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriter.php new file mode 100644 index 000000000..61e03cb0e --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriter.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 Symfony\Component\Translation\Writer; + +use Symfony\Component\Translation\Dumper\DumperInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\RuntimeException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationWriter writes translation messages. + * + * @author Michel Salib + */ +class TranslationWriter implements TranslationWriterInterface +{ + /** + * @var array + */ + private array $dumpers = []; + + /** + * Adds a dumper to the writer. + * + * @return void + */ + public function addDumper(string $format, DumperInterface $dumper) + { + $this->dumpers[$format] = $dumper; + } + + /** + * Obtains the list of supported formats. + */ + public function getFormats(): array + { + return array_keys($this->dumpers); + } + + /** + * Writes translation from the catalogue according to the selected format. + * + * @param string $format The format to use to dump the messages + * @param array $options Options that are passed to the dumper + * + * @return void + * + * @throws InvalidArgumentException + */ + public function write(MessageCatalogue $catalogue, string $format, array $options = []) + { + if (!isset($this->dumpers[$format])) { + throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format)); + } + + // get the right dumper + $dumper = $this->dumpers[$format]; + + if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0777, true) && !is_dir($options['path'])) { + throw new RuntimeException(sprintf('Translation Writer was not able to create directory "%s".', $options['path'])); + } + + // save + $dumper->dump($catalogue, $options); + } +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriterInterface.php b/.extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriterInterface.php new file mode 100644 index 000000000..5ebb9794a --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/Writer/TranslationWriterInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Writer; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationWriter writes translation messages. + * + * @author Michel Salib + */ +interface TranslationWriterInterface +{ + /** + * Writes translation from the catalogue according to the selected format. + * + * @param string $format The format to use to dump the messages + * @param array $options Options that are passed to the dumper + * + * @return void + * + * @throws InvalidArgumentException + */ + public function write(MessageCatalogue $catalogue, string $format, array $options = []); +} diff --git a/.extlib/simplesamlphp/vendor/symfony/translation/composer.json b/.extlib/simplesamlphp/vendor/symfony/translation/composer.json new file mode 100644 index 000000000..af6f7a3df --- /dev/null +++ b/.extlib/simplesamlphp/vendor/symfony/translation/composer.json @@ -0,0 +1,60 @@ +{ + "name": "symfony/translation", + "type": "library", + "description": "Provides tools to internationalize your application", + "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": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.18|^5.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4", + "symfony/console": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "autoload": { + "files": [ "Resources/functions.php" ], + "psr-4": { "Symfony\\Component\\Translation\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/.extlib/simplesamlphp/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/.extlib/simplesamlphp/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index 757606971..a0afb5eef 100644 --- a/.extlib/simplesamlphp/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/.extlib/simplesamlphp/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -15,6 +15,7 @@ use Symfony\Bridge\Twig\Node\TransNode; use Twig\Environment; use Twig\Node\BlockNode; +use Twig\Node\EmptyNode; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\AssignNameExpression; use Twig\Node\Expression\ConstantExpression; @@ -70,6 +71,12 @@ public function enterNode(Node $node, Environment $env): Node if ($node instanceof FilterExpression && 'trans' === ($node->hasAttribute('twig_callable') ? $node->getAttribute('twig_callable')->getName() : $node->getNode('filter')->getAttribute('value'))) { $arguments = $node->getNode('arguments'); + + if ($arguments instanceof EmptyNode) { + $arguments = new Nodes(); + $node->setNode('arguments', $arguments); + } + if ($this->isNamedArguments($arguments)) { if (!$arguments->hasNode('domain') && !$arguments->hasNode(1)) { $arguments->setNode('domain', $this->scope->get('domain')); diff --git a/.extlib/simplesamlphp/vendor/symfony/var-dumper/Resources/bin/var-dump-server b/.extlib/simplesamlphp/vendor/symfony/var-dumper/Resources/bin/var-dump-server old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/symfony/yaml/Resources/bin/yaml-lint b/.extlib/simplesamlphp/vendor/symfony/yaml/Resources/bin/yaml-lint old mode 100755 new mode 100644 diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/CHANGELOG.md b/.extlib/simplesamlphp/vendor/theseer/tokenizer/CHANGELOG.md new file mode 100644 index 000000000..d867649fb --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/CHANGELOG.md @@ -0,0 +1,87 @@ +# Changelog + +All notable changes to Tokenizer are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [1.2.3] - 2024-03-03 + +### Changed + +* Do not use implicitly nullable parameters + +## [1.2.2] - 2023-11-20 + +### Fixed + +* [#18](https://github.com/theseer/tokenizer/issues/18): Tokenizer fails on protobuf metadata files + + +## [1.2.1] - 2021-07-28 + +### Fixed + +* [#13](https://github.com/theseer/tokenizer/issues/13): Fatal error when tokenizing files that contain only a single empty line + + +## [1.2.0] - 2020-07-13 + +This release is now PHP 8.0 compliant. + +### Fixed + +* Whitespace handling in general (only noticable in the intermediate `TokenCollection`) is now consitent + +### Changed + +* Updated `Tokenizer` to deal with changed whitespace handling in PHP 8.0 + The XMLSerializer was unaffected. + + +## [1.1.3] - 2019-06-14 + +### Changed + +* Ensure XMLSerializer can deal with empty token collections + +### Fixed + +* [#2](https://github.com/theseer/tokenizer/issues/2): Fatal error in infection / phpunit + + +## [1.1.2] - 2019-04-04 + +### Changed + +* Reverted PHPUnit 8 test update to stay PHP 7.0 compliant + + +## [1.1.1] - 2019-04-03 + +### Fixed + +* [#1](https://github.com/theseer/tokenizer/issues/1): Empty file causes invalid array read + +### Changed + +* Tests should now be PHPUnit 8 compliant + + +## [1.1.0] - 2017-04-07 + +### Added + +* Allow use of custom namespace for XML serialization + + +## [1.0.0] - 2017-04-05 + +Initial Release + +[1.2.3]: https://github.com/theseer/tokenizer/compare/1.2.2...1.2.3 +[1.2.2]: https://github.com/theseer/tokenizer/compare/1.2.1...1.2.2 +[1.2.1]: https://github.com/theseer/tokenizer/compare/1.2.0...1.2.1 +[1.2.0]: https://github.com/theseer/tokenizer/compare/1.1.3...1.2.0 +[1.1.3]: https://github.com/theseer/tokenizer/compare/1.1.2...1.1.3 +[1.1.2]: https://github.com/theseer/tokenizer/compare/1.1.1...1.1.2 +[1.1.1]: https://github.com/theseer/tokenizer/compare/1.1.0...1.1.1 +[1.1.0]: https://github.com/theseer/tokenizer/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/theseer/tokenizer/compare/b2493e57de80c1b7414219b28503fa5c6b4d0a98...1.0.0 diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/LICENSE b/.extlib/simplesamlphp/vendor/theseer/tokenizer/LICENSE new file mode 100644 index 000000000..e9694ad61 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/LICENSE @@ -0,0 +1,30 @@ +Tokenizer + +Copyright (c) 2017 Arne Blankerts and contributors +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 Arne Blankerts nor the names of 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 HOLDER 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/.extlib/simplesamlphp/vendor/theseer/tokenizer/README.md b/.extlib/simplesamlphp/vendor/theseer/tokenizer/README.md new file mode 100644 index 000000000..a5f891b48 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/README.md @@ -0,0 +1,47 @@ +# Tokenizer + +A small library for converting tokenized PHP source code into XML. + +[![Test](https://github.com/theseer/tokenizer/actions/workflows/ci.yml/badge.svg)](https://github.com/theseer/tokenizer/actions/workflows/ci.yml) + +## Installation + +You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): + + composer require theseer/tokenizer + +If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: + + composer require --dev theseer/tokenizer + +## Usage examples + +```php +$tokenizer = new TheSeer\Tokenizer\Tokenizer(); +$tokens = $tokenizer->parse(file_get_contents(__DIR__ . '/src/XMLSerializer.php')); + +$serializer = new TheSeer\Tokenizer\XMLSerializer(); +$xml = $serializer->toXML($tokens); + +echo $xml; +``` + +The generated XML structure looks something like this: + +```xml + + + + <?php + declare + ( + strict_types + + = + + 1 + ) + ; + + +``` diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/composer.json b/.extlib/simplesamlphp/vendor/theseer/tokenizer/composer.json new file mode 100644 index 000000000..3f452a9fc --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/composer.json @@ -0,0 +1,27 @@ +{ + "name": "theseer/tokenizer", + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "support": { + "issues": "https://github.com/theseer/tokenizer/issues" + }, + "require": { + "php": "^7.2 || ^8.0", + "ext-xmlwriter": "*", + "ext-dom": "*", + "ext-tokenizer": "*" + }, + "autoload": { + "classmap": [ + "src/" + ] + } +} + diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/composer.lock b/.extlib/simplesamlphp/vendor/theseer/tokenizer/composer.lock new file mode 100644 index 000000000..07fba9b50 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/composer.lock @@ -0,0 +1,22 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "b010f1b3d9d47d431ee1cb54ac1de755", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.2 || ^8.0", + "ext-xmlwriter": "*", + "ext-dom": "*", + "ext-tokenizer": "*" + }, + "platform-dev": [] +} diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/Exception.php b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/Exception.php new file mode 100644 index 000000000..71fc117a5 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/Exception.php @@ -0,0 +1,5 @@ +ensureValidUri($value); + $this->value = $value; + } + + public function asString(): string { + return $this->value; + } + + private function ensureValidUri($value): void { + if (\strpos($value, ':') === false) { + throw new NamespaceUriException( + \sprintf("Namespace URI '%s' must contain at least one colon", $value) + ); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/NamespaceUriException.php b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/NamespaceUriException.php new file mode 100644 index 000000000..ab1c48d29 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/NamespaceUriException.php @@ -0,0 +1,5 @@ +line = $line; + $this->name = $name; + $this->value = $value; + } + + public function getLine(): int { + return $this->line; + } + + public function getName(): string { + return $this->name; + } + + public function getValue(): string { + return $this->value; + } +} diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollection.php b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollection.php new file mode 100644 index 000000000..e5e6e401c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollection.php @@ -0,0 +1,93 @@ +tokens[] = $token; + } + + public function current(): Token { + return \current($this->tokens); + } + + public function key(): int { + return \key($this->tokens); + } + + public function next(): void { + \next($this->tokens); + $this->pos++; + } + + public function valid(): bool { + return $this->count() > $this->pos; + } + + public function rewind(): void { + \reset($this->tokens); + $this->pos = 0; + } + + public function count(): int { + return \count($this->tokens); + } + + public function offsetExists($offset): bool { + return isset($this->tokens[$offset]); + } + + /** + * @throws TokenCollectionException + */ + public function offsetGet($offset): Token { + if (!$this->offsetExists($offset)) { + throw new TokenCollectionException( + \sprintf('No Token at offest %s', $offset) + ); + } + + return $this->tokens[$offset]; + } + + /** + * @param Token $value + * + * @throws TokenCollectionException + */ + public function offsetSet($offset, $value): void { + if (!\is_int($offset)) { + $type = \gettype($offset); + + throw new TokenCollectionException( + \sprintf( + 'Offset must be of type integer, %s given', + $type === 'object' ? \get_class($value) : $type + ) + ); + } + + if (!$value instanceof Token) { + $type = \gettype($value); + + throw new TokenCollectionException( + \sprintf( + 'Value must be of type %s, %s given', + Token::class, + $type === 'object' ? \get_class($value) : $type + ) + ); + } + $this->tokens[$offset] = $value; + } + + public function offsetUnset($offset): void { + unset($this->tokens[$offset]); + } +} diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollectionException.php b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollectionException.php new file mode 100644 index 000000000..4291ce0c4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/TokenCollectionException.php @@ -0,0 +1,5 @@ + 'T_OPEN_BRACKET', + ')' => 'T_CLOSE_BRACKET', + '[' => 'T_OPEN_SQUARE', + ']' => 'T_CLOSE_SQUARE', + '{' => 'T_OPEN_CURLY', + '}' => 'T_CLOSE_CURLY', + ';' => 'T_SEMICOLON', + '.' => 'T_DOT', + ',' => 'T_COMMA', + '=' => 'T_EQUAL', + '<' => 'T_LT', + '>' => 'T_GT', + '+' => 'T_PLUS', + '-' => 'T_MINUS', + '*' => 'T_MULT', + '/' => 'T_DIV', + '?' => 'T_QUESTION_MARK', + '!' => 'T_EXCLAMATION_MARK', + ':' => 'T_COLON', + '"' => 'T_DOUBLE_QUOTES', + '@' => 'T_AT', + '&' => 'T_AMPERSAND', + '%' => 'T_PERCENT', + '|' => 'T_PIPE', + '$' => 'T_DOLLAR', + '^' => 'T_CARET', + '~' => 'T_TILDE', + '`' => 'T_BACKTICK' + ]; + + public function parse(string $source): TokenCollection { + $result = new TokenCollection(); + + if ($source === '') { + return $result; + } + + $tokens = \token_get_all($source); + + $lastToken = new Token( + $tokens[0][2], + 'Placeholder', + '' + ); + + foreach ($tokens as $pos => $tok) { + if (\is_string($tok)) { + $token = new Token( + $lastToken->getLine(), + $this->map[$tok], + $tok + ); + $result->addToken($token); + $lastToken = $token; + + continue; + } + + $line = $tok[2]; + $values = \preg_split('/\R+/Uu', $tok[1]); + + if (!$values) { + $result->addToken( + new Token( + $line, + \token_name($tok[0]), + '{binary data}' + ) + ); + + continue; + } + + foreach ($values as $v) { + $token = new Token( + $line, + \token_name($tok[0]), + $v + ); + $lastToken = $token; + $line++; + + if ($v === '') { + continue; + } + + $result->addToken($token); + } + } + + return $this->fillBlanks($result, $lastToken->getLine()); + } + + private function fillBlanks(TokenCollection $tokens, int $maxLine): TokenCollection { + $prev = new Token( + 0, + 'Placeholder', + '' + ); + + $final = new TokenCollection(); + + foreach ($tokens as $token) { + $gap = $token->getLine() - $prev->getLine(); + + while ($gap > 1) { + $linebreak = new Token( + $prev->getLine() + 1, + 'T_WHITESPACE', + '' + ); + $final->addToken($linebreak); + $prev = $linebreak; + $gap--; + } + + $final->addToken($token); + $prev = $token; + } + + $gap = $maxLine - $prev->getLine(); + + while ($gap > 0) { + $linebreak = new Token( + $prev->getLine() + 1, + 'T_WHITESPACE', + '' + ); + $final->addToken($linebreak); + $prev = $linebreak; + $gap--; + } + + return $final; + } +} diff --git a/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/XMLSerializer.php b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/XMLSerializer.php new file mode 100644 index 000000000..518bfb06f --- /dev/null +++ b/.extlib/simplesamlphp/vendor/theseer/tokenizer/src/XMLSerializer.php @@ -0,0 +1,79 @@ +xmlns = $xmlns; + } + + public function toDom(TokenCollection $tokens): DOMDocument { + $dom = new DOMDocument(); + $dom->preserveWhiteSpace = false; + $dom->loadXML($this->toXML($tokens)); + + return $dom; + } + + public function toXML(TokenCollection $tokens): string { + $this->writer = new \XMLWriter(); + $this->writer->openMemory(); + $this->writer->setIndent(true); + $this->writer->startDocument(); + $this->writer->startElement('source'); + $this->writer->writeAttribute('xmlns', $this->xmlns->asString()); + + if (\count($tokens) > 0) { + $this->writer->startElement('line'); + $this->writer->writeAttribute('no', '1'); + + $this->previousToken = $tokens[0]; + + foreach ($tokens as $token) { + $this->addToken($token); + } + } + + $this->writer->endElement(); + $this->writer->endElement(); + $this->writer->endDocument(); + + return $this->writer->outputMemory(); + } + + private function addToken(Token $token): void { + if ($this->previousToken->getLine() < $token->getLine()) { + $this->writer->endElement(); + + $this->writer->startElement('line'); + $this->writer->writeAttribute('no', (string)$token->getLine()); + $this->previousToken = $token; + } + + if ($token->getValue() !== '') { + $this->writer->startElement('token'); + $this->writer->writeAttribute('name', $token->getName()); + $this->writer->writeRaw(\htmlspecialchars($token->getValue(), \ENT_NOQUOTES | \ENT_DISALLOWED | \ENT_XML1)); + $this->writer->endElement(); + } + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/CHANGELOG b/.extlib/simplesamlphp/vendor/twig/twig/CHANGELOG index 276abe722..6f3062d3f 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/CHANGELOG +++ b/.extlib/simplesamlphp/vendor/twig/twig/CHANGELOG @@ -1,3 +1,50 @@ +# 3.16.0 (2024-XX-XX) + + * Deprecate `InlinePrint` + * Fix having macro variables starting with an underscore + * Deprecate not passing a `Source` instance to `TokenStream` + * Deprecate returning `null` from `TwigFilter::getSafe()` and `TwigFunction::getSafe()`, return `[]` instead + +# 3.15.0 (2024-11-17) + + * [BC BREAK] Add support for accessing class constants with the dot operator; + this can be a BC break if you don't use UPPERCASE constant names + * Add Spanish inflector support for the `plural` and `singular` filters in the String extension + * Deprecate `TempNameExpression` in favor of `LocalVariable` + * Deprecate `NameExpression` in favor of `ContextVariable` + * Deprecate `AssignNameExpression` in favor of `AssignContextVariable` + * Remove `MacroAutoImportNodeVisitor` + * Deprecate `MethodCallExpression` in favor of `MacroReferenceExpression` + * Fix support for the "is defined" test on `_self.xxx` (auto-imported) macros + * Fix support for the "is defined" test on inherited macros + * Add named arguments support for the dot operator arguments (`foo.bar(some: arg)`) + * Add named arguments support for macros + * Add a new `guard` tag that allows to test if some Twig callables are available at compilation time + * Allow arrow functions everywhere + * Deprecate passing a string or an array to Twig callable arguments accepting arrow functions (pass a `\Closure`) + * Add support for triggering deprecations for future operator precedence changes + * Deprecate using the `not` unary operator in an expression with ``*``, ``/``, ``//``, or ``%`` without using explicit parentheses to clarify precedence + * Deprecate using the `??` binary operator without explicit parentheses + * Deprecate using the `~` binary operator in an expression with `+` or `-` without using parentheses to clarify precedence + * Deprecate not passing `AbstractExpression` args to most constructor arguments for classes extending `AbstractExpression` + * Fix `power` expressions with a negative number in parenthesis (`(-1) ** 2`) + * Deprecate instantiating `Node` directly. Use `EmptyNode` or `Nodes` instead. + * Add support for inline comments + * Add `Profile::getStartTime()` and `Profile::getEndTime()` + * Fix "ignore missing" when used on an "embed" tag + * Fix the possibility to override an aliased block (via use) + * Add template cache hot reload + * Allow Twig callable argument names to be free-form (snake-case or camelCase) independently of the PHP callable signature + They were automatically converted to snake-cased before + * Deprecate the `attribute` function; use the `.` notation and wrap the name with parenthesis instead + * Add support for argument unpackaging + * Add JSON support for the file extension escaping strategy + * Support Markup instances (and any other \Stringable) as dynamic mapping keys + * Deprecate the `sandbox` tag + * Improve the way one can deprecate a Twig callable (use `deprecation_info` instead of the other callable options) + * Add the `enum` function + * Add support for logical `xor` operator + # 3.14.2 (2024-11-07) * Fix an infinite recursion in the sandbox code diff --git a/.extlib/simplesamlphp/vendor/twig/twig/composer.json b/.extlib/simplesamlphp/vendor/twig/twig/composer.json index e0c3e6c6c..079f1daf3 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/composer.json +++ b/.extlib/simplesamlphp/vendor/twig/twig/composer.json @@ -32,7 +32,8 @@ }, "require-dev": { "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0", - "psr/container": "^1.0|^2.0" + "psr/container": "^1.0|^2.0", + "phpstan/phpstan": "^2.0" }, "autoload": { "files": [ diff --git a/.extlib/simplesamlphp/vendor/twig/twig/phpstan-baseline.neon b/.extlib/simplesamlphp/vendor/twig/twig/phpstan-baseline.neon new file mode 100644 index 000000000..1121ae1b2 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/phpstan-baseline.neon @@ -0,0 +1,25 @@ +parameters: + ignoreErrors: + - # The method is dynamically generated by the CheckSecurityNode + message: '#^Call to an undefined method Twig\\Template\:\:checkSecurity\(\)\.$#' + identifier: method.notFound + count: 1 + path: src/Extension/CoreExtension.php + + - # Avoid BC-break + message: '#^Constructor of class Twig\\Node\\ForNode has an unused parameter \$ifexpr\.$#' + identifier: constructor.unusedParameter + count: 1 + path: src/Node/ForNode.php + + - # 2 parameters will be required + message: '#^Method Twig\\Node\\IncludeNode\:\:addGetTemplate\(\) invoked with 2 parameters, 1 required\.$#' + identifier: arguments.count + count: 1 + path: src/Node/IncludeNode.php + + - # int|string will be supported in 4.x + message: '#^PHPDoc tag @param for parameter $name with type int|string is not subtype of native type string\.$#' + identifier: parameter.phpDocType + count: 5 + path: src/Node/Node.php diff --git a/.extlib/simplesamlphp/vendor/twig/twig/phpstan.neon.dist b/.extlib/simplesamlphp/vendor/twig/twig/phpstan.neon.dist new file mode 100644 index 000000000..6d94e4109 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/phpstan.neon.dist @@ -0,0 +1,9 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 3 + paths: + - src + excludePaths: + - src/Test diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/AbstractTwigCallable.php b/.extlib/simplesamlphp/vendor/twig/twig/src/AbstractTwigCallable.php index f67184300..d85f0f861 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/AbstractTwigCallable.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/AbstractTwigCallable.php @@ -33,10 +33,35 @@ public function __construct(string $name, $callable = null, array $options = []) 'needs_context' => false, 'needs_charset' => false, 'is_variadic' => false, + 'deprecation_info' => null, 'deprecated' => false, 'deprecating_package' => '', 'alternative' => null, ], $options); + + if ($this->options['deprecation_info'] && !$this->options['deprecation_info'] instanceof DeprecatedCallableInfo) { + throw new \LogicException(\sprintf('The "deprecation_info" option must be an instance of "%s".', DeprecatedCallableInfo::class)); + } + + if ($this->options['deprecated']) { + if ($this->options['deprecation_info']) { + throw new \LogicException('When setting the "deprecation_info" option, you need to remove the obsolete deprecated options.'); + } + + trigger_deprecation('twig/twig', '3.15', 'Using the "deprecated", "deprecating_package", and "alternative" options is deprecated, pass a "deprecation_info" one instead.'); + + $this->options['deprecation_info'] = new DeprecatedCallableInfo( + $this->options['deprecating_package'], + $this->options['deprecated'], + null, + $this->options['alternative'], + ); + } + + if ($this->options['deprecation_info']) { + $this->options['deprecation_info']->setName($name); + $this->options['deprecation_info']->setType($this->getType()); + } } public function __toString(): string @@ -79,6 +104,9 @@ public function needsContext(): bool return $this->options['needs_context']; } + /** + * @return static + */ public function withDynamicArguments(string $name, string $dynamicName, array $arguments): self { $new = clone $this; @@ -111,21 +139,41 @@ public function isVariadic(): bool public function isDeprecated(): bool { - return (bool) $this->options['deprecated']; + return (bool) $this->options['deprecation_info']; + } + + public function triggerDeprecation(?string $file = null, ?int $line = null): void + { + $this->options['deprecation_info']->triggerDeprecation($file, $line); } + /** + * @deprecated since Twig 3.15 + */ public function getDeprecatingPackage(): string { + trigger_deprecation('twig/twig', '3.15', 'The "%s" method is deprecated, use "%s::triggerDeprecation()" instead.', __METHOD__, static::class); + return $this->options['deprecating_package']; } + /** + * @deprecated since Twig 3.15 + */ public function getDeprecatedVersion(): string { + trigger_deprecation('twig/twig', '3.15', 'The "%s" method is deprecated, use "%s::triggerDeprecation()" instead.', __METHOD__, static::class); + return \is_bool($this->options['deprecated']) ? '' : $this->options['deprecated']; } + /** + * @deprecated since Twig 3.15 + */ public function getAlternative(): ?string { + trigger_deprecation('twig/twig', '3.15', 'The "%s" method is deprecated, use "%s::triggerDeprecation()" instead.', __METHOD__, static::class); + return $this->options['alternative']; } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/ChainCache.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/ChainCache.php index c94afdb43..1c2098f1f 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/ChainCache.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/ChainCache.php @@ -19,7 +19,7 @@ * * @author Quentin Devos */ -final class ChainCache implements CacheInterface +final class ChainCache implements CacheInterface, RemovableCacheInterface { /** * @param iterable $caches The ordered list of caches used to store and fetch cached items @@ -69,6 +69,15 @@ public function getTimestamp(string $key): int return 0; } + public function remove(string $name, string $cls): void + { + foreach ($this->caches as $cache) { + if ($cache instanceof RemovableCacheInterface) { + $cache->remove($name, $cls); + } + } + } + /** * @return string[] */ diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/FilesystemCache.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/FilesystemCache.php index 2e79fac05..5840585e3 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/FilesystemCache.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/FilesystemCache.php @@ -16,7 +16,7 @@ * * @author Andrew Tch */ -class FilesystemCache implements CacheInterface +class FilesystemCache implements CacheInterface, RemovableCacheInterface { public const FORCE_BYTECODE_INVALIDATION = 1; @@ -76,6 +76,14 @@ public function write(string $key, string $content): void throw new \RuntimeException(\sprintf('Failed to write cache file "%s".', $key)); } + public function remove(string $name, string $cls): void + { + $key = $this->generateKey($name, $cls); + if (!@unlink($key) && file_exists($key)) { + throw new \RuntimeException(\sprintf('Failed to delete cache file "%s".', $key)); + } + } + public function getTimestamp(string $key): int { if (!is_file($key)) { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/NullCache.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/NullCache.php index 8d20d59d8..1ae216928 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/NullCache.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/NullCache.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -final class NullCache implements CacheInterface +final class NullCache implements CacheInterface, RemovableCacheInterface { public function generateKey(string $name, string $className): string { @@ -35,4 +35,8 @@ public function getTimestamp(string $key): int { return 0; } + + public function remove(string $name, string $cls): void + { + } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/RemovableCacheInterface.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/RemovableCacheInterface.php new file mode 100644 index 000000000..05da56913 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Cache/RemovableCacheInterface.php @@ -0,0 +1,20 @@ + + */ +interface RemovableCacheInterface +{ + public function remove(string $name, string $cls): void; +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Compiler.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Compiler.php index 1a43aa7f6..3166841e3 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Compiler.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Compiler.php @@ -74,7 +74,7 @@ public function compile(Node $node, int $indentation = 0) $node->compile($this); if ($this->didUseEcho) { - trigger_deprecation('twig/twig', '3.9', 'Using "%s" is deprecated, use "yield" instead in "%s", then flag the class with #[YieldReady].', $this->didUseEcho, \get_class($node)); + trigger_deprecation('twig/twig', '3.9', 'Using "%s" is deprecated, use "yield" instead in "%s", then flag the class with #[\Twig\Attribute\YieldReady].', $this->didUseEcho, \get_class($node)); } return $this; @@ -99,7 +99,7 @@ public function subcompile(Node $node, bool $raw = true) $node->compile($this); if ($this->didUseEcho) { - trigger_deprecation('twig/twig', '3.9', 'Using "%s" is deprecated, use "yield" instead in "%s", then flag the class with #[YieldReady].', $this->didUseEcho, \get_class($node)); + trigger_deprecation('twig/twig', '3.9', 'Using "%s" is deprecated, use "yield" instead in "%s", then flag the class with #[\Twig\Attribute\YieldReady].', $this->didUseEcho, \get_class($node)); } return $this; @@ -243,7 +243,7 @@ public function outdent(int $step = 1) public function getVarName(): string { - return \sprintf('__internal_compile_%d', $this->varNameSalt++); + return \sprintf('_v%d', $this->varNameSalt++); } private function checkForEcho(string $string): void diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/DeprecatedCallableInfo.php b/.extlib/simplesamlphp/vendor/twig/twig/src/DeprecatedCallableInfo.php new file mode 100644 index 000000000..2db9f3d28 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/DeprecatedCallableInfo.php @@ -0,0 +1,67 @@ + + */ +final class DeprecatedCallableInfo +{ + private string $type; + private string $name; + + public function __construct( + private string $package, + private string $version, + private ?string $altName = null, + private ?string $altPackage = null, + private ?string $altVersion = null, + ) { + } + + public function setType(string $type): void + { + $this->type = $type; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function triggerDeprecation(?string $file = null, ?int $line = null): void + { + $message = \sprintf('Twig %s "%s" is deprecated', ucfirst($this->type), $this->name); + + if ($this->altName) { + $message .= \sprintf('; use "%s"', $this->altName); + if ($this->altPackage) { + $message .= \sprintf(' from the "%s" package', $this->altPackage); + } + if ($this->altVersion) { + $message .= \sprintf(' (available since version %s)', $this->altVersion); + } + $message .= ' instead'; + } + + if ($file) { + $message .= \sprintf(' in %s', $file); + if ($line) { + $message .= \sprintf(' at line %d', $line); + } + } + + $message .= '.'; + + trigger_deprecation($this->package, $this->version, $message); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Environment.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Environment.php index b6554e8e0..bc064e445 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Environment.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Environment.php @@ -14,6 +14,7 @@ use Twig\Cache\CacheInterface; use Twig\Cache\FilesystemCache; use Twig\Cache\NullCache; +use Twig\Cache\RemovableCacheInterface; use Twig\Error\Error; use Twig\Error\LoaderError; use Twig\Error\RuntimeError; @@ -43,11 +44,11 @@ */ class Environment { - public const VERSION = '3.14.2'; - public const VERSION_ID = 31402; + public const VERSION = '3.16.0'; + public const VERSION_ID = 31600; public const MAJOR_VERSION = 3; - public const MINOR_VERSION = 14; - public const RELEASE_VERSION = 2; + public const MINOR_VERSION = 16; + public const RELEASE_VERSION = 0; public const EXTRA_VERSION = ''; private $charset; @@ -71,6 +72,7 @@ class Environment /** @var bool */ private $useYield; private $defaultRuntimeLoader; + private array $hotCache = []; /** * Constructor. @@ -233,6 +235,18 @@ public function isStrictVariables() return $this->strictVariables; } + public function removeCache(string $name): void + { + $cls = $this->getTemplateClass($name); + $this->hotCache[$name] = $cls.'_'.bin2hex(random_bytes(16)); + + if ($this->cache instanceof RemovableCacheInterface) { + $this->cache->remove($name, $cls); + } else { + throw new \LogicException(\sprintf('The "%s" cache class does not support removing template cache as it does not implement the "RemovableCacheInterface" interface.', \get_class($this->cache))); + } + } + /** * Gets the current cache implementation. * @@ -287,7 +301,7 @@ public function setCache($cache) */ public function getTemplateClass(string $name, ?int $index = null): string { - $key = $this->getLoader()->getCacheKey($name).$this->optionsHash; + $key = ($this->hotCache[$name] ?? $this->getLoader()->getCacheKey($name)).$this->optionsHash; return '__TwigTemplate_'.hash(\PHP_VERSION_ID < 80100 ? 'sha256' : 'xxh128', $key).(null === $index ? '' : '___'.$index); } @@ -379,8 +393,10 @@ public function loadTemplate(string $cls, string $name, ?int $index = null): Tem if (!class_exists($cls, false)) { $source = $this->getLoader()->getSourceContext($name); $content = $this->compileSource($source); - $this->cache->write($key, $content); - $this->cache->load($key); + if (!isset($this->hotCache[$name])) { + $this->cache->write($key, $content); + $this->cache->load($key); + } if (!class_exists($mainCls, false)) { /* Last line of defense if either $this->bcWriteCacheFile was used, @@ -813,8 +829,6 @@ public function addGlobal(string $name, $value) } /** - * @internal - * * @return array */ public function getGlobals(): array diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/ExpressionParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/ExpressionParser.php index dc4a6015d..2fb528518 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/ExpressionParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/ExpressionParser.php @@ -14,23 +14,29 @@ use Twig\Attribute\FirstClassTwigCallableReady; use Twig\Error\SyntaxError; +use Twig\Node\EmptyNode; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\ArrowFunctionExpression; -use Twig\Node\Expression\AssignNameExpression; use Twig\Node\Expression\Binary\AbstractBinary; use Twig\Node\Expression\Binary\ConcatBinary; use Twig\Node\Expression\ConditionalExpression; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Expression\GetAttrExpression; -use Twig\Node\Expression\MethodCallExpression; +use Twig\Node\Expression\MacroReferenceExpression; use Twig\Node\Expression\NameExpression; use Twig\Node\Expression\TestExpression; use Twig\Node\Expression\Unary\AbstractUnary; use Twig\Node\Expression\Unary\NegUnary; use Twig\Node\Expression\Unary\NotUnary; use Twig\Node\Expression\Unary\PosUnary; +use Twig\Node\Expression\Unary\SpreadUnary; +use Twig\Node\Expression\Variable\AssignContextVariable; +use Twig\Node\Expression\Variable\ContextVariable; +use Twig\Node\Expression\Variable\LocalVariable; +use Twig\Node\Expression\Variable\TemplateVariable; use Twig\Node\Node; +use Twig\Node\Nodes; /** * Parses expressions. @@ -47,11 +53,13 @@ class ExpressionParser public const OPERATOR_LEFT = 1; public const OPERATOR_RIGHT = 2; - /** @var array}> */ + /** @var array}> */ private $unaryOperators; - /** @var array, associativity: self::OPERATOR_*}> */ + /** @var array, associativity: self::OPERATOR_*}> */ private $binaryOperators; private $readyNodes = []; + private array $precedenceChanges = []; + private bool $deprecationCheck = true; public function __construct( private Parser $parser, @@ -59,11 +67,36 @@ public function __construct( ) { $this->unaryOperators = $env->getUnaryOperators(); $this->binaryOperators = $env->getBinaryOperators(); + + $ops = []; + foreach ($this->unaryOperators as $n => $c) { + $ops[] = $c + ['name' => $n, 'type' => 'unary']; + } + foreach ($this->binaryOperators as $n => $c) { + $ops[] = $c + ['name' => $n, 'type' => 'binary']; + } + foreach ($ops as $config) { + if (!isset($config['precedence_change'])) { + continue; + } + $name = $config['type'].'_'.$config['name']; + $min = min($config['precedence_change']->getNewPrecedence(), $config['precedence']); + $max = max($config['precedence_change']->getNewPrecedence(), $config['precedence']); + foreach ($ops as $c) { + if ($c['precedence'] > $min && $c['precedence'] < $max) { + $this->precedenceChanges[$c['type'].'_'.$c['name']][] = $name; + } + } + } } - public function parseExpression($precedence = 0, $allowArrow = false) + public function parseExpression($precedence = 0) { - if ($allowArrow && $arrow = $this->parseArrow()) { + if (func_num_args() > 1) { + trigger_deprecation('twig/twig', '3.15', 'Passing a second argument ($allowArrow) to "%s()" is deprecated.', __METHOD__); + } + + if ($arrow = $this->parseArrow()) { return $arrow; } @@ -80,11 +113,20 @@ public function parseExpression($precedence = 0, $allowArrow = false) } elseif (isset($op['callable'])) { $expr = $op['callable']($this->parser, $expr); } else { - $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence'], true); + $previous = $this->setDeprecationCheck(true); + try { + $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); + } finally { + $this->setDeprecationCheck($previous); + } $class = $op['class']; $expr = new $class($expr, $expr1, $token->getLine()); } + $expr->setAttribute('operator', 'binary_'.$token->getValue()); + + $this->triggerPrecedenceDeprecations($expr); + $token = $this->parser->getCurrentToken(); } @@ -95,6 +137,43 @@ public function parseExpression($precedence = 0, $allowArrow = false) return $expr; } + private function triggerPrecedenceDeprecations(AbstractExpression $expr): void + { + // Check that the all nodes that are between the 2 precedences have explicit parentheses + if (!$expr->hasAttribute('operator') || !isset($this->precedenceChanges[$expr->getAttribute('operator')])) { + return; + } + + if (str_starts_with($unaryOp = $expr->getAttribute('operator'), 'unary')) { + if ($expr->hasExplicitParentheses()) { + return; + } + $target = explode('_', $unaryOp)[1]; + $change = $this->unaryOperators[$target]['precedence_change']; + /** @var AbstractExpression $node */ + $node = $expr->getNode('node'); + foreach ($this->precedenceChanges as $operatorName => $changes) { + if (!in_array($unaryOp, $changes)) { + continue; + } + if ($node->hasAttribute('operator') && $operatorName === $node->getAttribute('operator')) { + trigger_deprecation($change->getPackage(), $change->getVersion(), \sprintf('Add explicit parentheses around the "%s" unary operator to avoid behavior change in the next major version as its precedence will change in "%s" at line %d.', $target, $this->parser->getStream()->getSourceContext()->getName(), $node->getTemplateLine())); + } + } + } else { + foreach ($this->precedenceChanges[$expr->getAttribute('operator')] as $operatorName) { + foreach ($expr as $node) { + /** @var AbstractExpression $node */ + if ($node->hasAttribute('operator') && $operatorName === $node->getAttribute('operator') && !$node->hasExplicitParentheses()) { + $op = explode('_', $operatorName)[1]; + $change = $this->binaryOperators[$op]['precedence_change']; + trigger_deprecation($change->getPackage(), $change->getVersion(), \sprintf('Add explicit parentheses around the "%s" binary operator to avoid behavior change in the next major version as its precedence will change in "%s" at line %d.', $op, $this->parser->getStream()->getSourceContext()->getName(), $node->getTemplateLine())); + } + } + } + } + } + /** * @return ArrowFunctionExpression|null */ @@ -106,10 +185,10 @@ private function parseArrow() if ($stream->look(1)->test(Token::ARROW_TYPE)) { $line = $stream->getCurrent()->getLine(); $token = $stream->expect(Token::NAME_TYPE); - $names = [new AssignNameExpression($token->getValue(), $token->getLine())]; + $names = [new AssignContextVariable($token->getValue(), $token->getLine())]; $stream->expect(Token::ARROW_TYPE); - return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); + return new ArrowFunctionExpression($this->parseExpression(), new Nodes($names), $line); } // first, determine if we are parsing an arrow function by finding => (long form) @@ -141,7 +220,7 @@ private function parseArrow() $names = []; while (true) { $token = $stream->expect(Token::NAME_TYPE); - $names[] = new AssignNameExpression($token->getValue(), $token->getLine()); + $names[] = new AssignContextVariable($token->getValue(), $token->getLine()); if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { break; @@ -150,7 +229,7 @@ private function parseArrow() $stream->expect(Token::PUNCTUATION_TYPE, ')'); $stream->expect(Token::ARROW_TYPE); - return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); + return new ArrowFunctionExpression($this->parseExpression(), new Nodes($names), $line); } private function getPrimary(): AbstractExpression @@ -163,10 +242,22 @@ private function getPrimary(): AbstractExpression $expr = $this->parseExpression($operator['precedence']); $class = $operator['class']; - return $this->parsePostfixExpression(new $class($expr, $token->getLine())); + $expr = new $class($expr, $token->getLine()); + $expr->setAttribute('operator', 'unary_'.$token->getValue()); + + if ($this->deprecationCheck) { + $this->triggerPrecedenceDeprecations($expr); + } + + return $this->parsePostfixExpression($expr); } elseif ($token->test(Token::PUNCTUATION_TYPE, '(')) { $this->parser->getStream()->next(); - $expr = $this->parseExpression(); + $previous = $this->setDeprecationCheck(false); + try { + $expr = $this->parseExpression()->setExplicitParentheses(); + } finally { + $this->setDeprecationCheck($previous); + } $this->parser->getStream()->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); return $this->parsePostfixExpression($expr); @@ -237,7 +328,7 @@ public function parsePrimaryExpression() if ('(' === $this->parser->getCurrentToken()->getValue()) { $node = $this->getFunctionNode($token->getValue(), $token->getLine()); } else { - $node = new NameExpression($token->getValue(), $token->getLine()); + $node = new ContextVariable($token->getValue(), $token->getLine()); } } break; @@ -252,38 +343,29 @@ public function parsePrimaryExpression() $node = $this->parseStringExpression(); break; + case Token::PUNCTUATION_TYPE: + $node = match ($token->getValue()) { + '[' => $this->parseSequenceExpression(), + '{' => $this->parseMappingExpression(), + default => throw new SyntaxError(\sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()), + }; + break; + case Token::OPERATOR_TYPE: if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { // in this context, string operators are variable names $this->parser->getStream()->next(); - $node = new NameExpression($token->getValue(), $token->getLine()); + $node = new ContextVariable($token->getValue(), $token->getLine()); break; } - if (isset($this->unaryOperators[$token->getValue()])) { - $class = $this->unaryOperators[$token->getValue()]['class']; - if (!\in_array($class, [NegUnary::class, PosUnary::class])) { - throw new SyntaxError(\sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } - - $this->parser->getStream()->next(); - $expr = $this->parsePrimaryExpression(); - - $node = new $class($expr, $token->getLine()); - break; + if ('=' === $token->getValue() && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { + throw new SyntaxError(\sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } // no break default: - if ($token->test(Token::PUNCTUATION_TYPE, '[')) { - $node = $this->parseSequenceExpression(); - } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { - $node = $this->parseMappingExpression(); - } elseif ($token->test(Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { - throw new SyntaxError(\sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } else { - throw new SyntaxError(\sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } + throw new SyntaxError(\sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } return $this->parsePostfixExpression($node); @@ -318,7 +400,7 @@ public function parseStringExpression() } /** - * @deprecated since 3.11, use parseSequenceExpression() instead + * @deprecated since Twig 3.11, use parseSequenceExpression() instead */ public function parseArrayExpression() { @@ -345,8 +427,7 @@ public function parseSequenceExpression() } $first = false; - if ($stream->test(Token::SPREAD_TYPE)) { - $stream->next(); + if ($stream->nextIf(Token::SPREAD_TYPE)) { $expr = $this->parseExpression(); $expr->setAttribute('spread', true); $node->addElement($expr); @@ -360,7 +441,7 @@ public function parseSequenceExpression() } /** - * @deprecated since 3.11, use parseMappingExpression() instead + * @deprecated since Twig 3.11, use parseMappingExpression() instead */ public function parseHashExpression() { @@ -387,8 +468,7 @@ public function parseMappingExpression() } $first = false; - if ($stream->test(Token::SPREAD_TYPE)) { - $stream->next(); + if ($stream->nextIf(Token::SPREAD_TYPE)) { $value = $this->parseExpression(); $value->setAttribute('spread', true); $node->addElement($value); @@ -406,7 +486,7 @@ public function parseMappingExpression() // {a} is a shortcut for {a:a} if ($stream->test(Token::PUNCTUATION_TYPE, [',', '}'])) { - $value = new NameExpression($key->getAttribute('value'), $key->getTemplateLine()); + $value = new ContextVariable($key->getAttribute('value'), $key->getTemplateLine()); $node->addElement($value, $key); continue; } @@ -453,22 +533,14 @@ public function parsePostfixExpression($node) public function getFunctionNode($name, $line) { if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { - $arguments = new ArrayExpression([], $line); - foreach ($this->parseArguments() as $n) { - $arguments->addElement($n); - } - - $node = new MethodCallExpression($alias['node'], $alias['name'], $arguments, $line); - $node->setAttribute('safe', true); - - return $node; + return new MacroReferenceExpression($alias['node']->getNode('var'), $alias['name'], $this->createArguments($line), $line); } - $args = $this->parseArguments(true); + $args = $this->parseOnlyArguments(); $function = $this->getFunction($name, $line); if ($function->getParserCallable()) { - $fakeNode = new Node(lineno: $line); + $fakeNode = new EmptyNode($line); $fakeNode->setSourceContext($this->parser->getStream()->getSourceContext()); return ($function->getParserCallable())($this->parser, $fakeNode, $args, $line); @@ -487,76 +559,11 @@ public function getFunctionNode($name, $line) public function parseSubscriptExpression($node) { - $stream = $this->parser->getStream(); - $token = $stream->next(); - $lineno = $token->getLine(); - $arguments = new ArrayExpression([], $lineno); - $type = Template::ANY_CALL; - if ('.' == $token->getValue()) { - $token = $stream->next(); - if ( - Token::NAME_TYPE == $token->getType() - || - Token::NUMBER_TYPE == $token->getType() - || - (Token::OPERATOR_TYPE == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue())) - ) { - $arg = new ConstantExpression($token->getValue(), $lineno); - - if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { - $type = Template::METHOD_CALL; - foreach ($this->parseArguments() as $n) { - $arguments->addElement($n); - } - } - } else { - throw new SyntaxError(\sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $lineno, $stream->getSourceContext()); - } - - if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { - $name = $arg->getAttribute('value'); - - $node = new MethodCallExpression($node, 'macro_'.$name, $arguments, $lineno); - $node->setAttribute('safe', true); - - return $node; - } - } else { - $type = Template::ARRAY_CALL; - - // slice? - $slice = false; - if ($stream->test(Token::PUNCTUATION_TYPE, ':')) { - $slice = true; - $arg = new ConstantExpression(0, $token->getLine()); - } else { - $arg = $this->parseExpression(); - } - - if ($stream->nextIf(Token::PUNCTUATION_TYPE, ':')) { - $slice = true; - } - - if ($slice) { - if ($stream->test(Token::PUNCTUATION_TYPE, ']')) { - $length = new ConstantExpression(null, $token->getLine()); - } else { - $length = $this->parseExpression(); - } - - $filter = $this->getFilter('slice', $token->getLine()); - $arguments = new Node([$arg, $length]); - $filter = new ($filter->getNodeClass())($node, $filter, $arguments, $token->getLine()); - - $stream->expect(Token::PUNCTUATION_TYPE, ']'); - - return $filter; - } - - $stream->expect(Token::PUNCTUATION_TYPE, ']'); + if ('.' === $this->parser->getStream()->next()->getValue()) { + return $this->parseSubscriptExpressionDot($node); } - return new GetAttrExpression($node, $arg, $arguments, $type, $lineno); + return $this->parseSubscriptExpressionArray($node); } public function parseFilterExpression($node) @@ -576,9 +583,9 @@ public function parseFilterExpressionRaw($node) $token = $this->parser->getStream()->expect(Token::NAME_TYPE); if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '(')) { - $arguments = new Node(); + $arguments = new EmptyNode(); } else { - $arguments = $this->parseArguments(true, false, true); + $arguments = $this->parseOnlyArguments(); } $filter = $this->getFilter($token->getValue(), $token->getLine()); @@ -607,21 +614,29 @@ public function parseFilterExpressionRaw($node) /** * Parses arguments. * - * @param bool $namedArguments Whether to allow named arguments or not - * @param bool $definition Whether we are parsing arguments for a function (or macro) definition - * * @return Node * * @throws SyntaxError */ - public function parseArguments($namedArguments = false, $definition = false, $allowArrow = false) + public function parseArguments() { + $namedArguments = false; + $definition = false; + if (func_num_args() > 1) { + $definition = func_get_arg(1); + } + if (func_num_args() > 0) { + trigger_deprecation('twig/twig', '3.15', 'Passing arguments to "%s()" is deprecated.', __METHOD__); + $namedArguments = func_get_arg(0); + } + $args = []; $stream = $this->parser->getStream(); $stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + $hasSpread = false; while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) { - if (!empty($args)) { + if ($args) { $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); // if the comma above was a trailing comma, early exit the argument parse loop @@ -632,26 +647,33 @@ public function parseArguments($namedArguments = false, $definition = false, $al if ($definition) { $token = $stream->expect(Token::NAME_TYPE, null, 'An argument must be a name'); - $value = new NameExpression($token->getValue(), $this->parser->getCurrentToken()->getLine()); + $value = new ContextVariable($token->getValue(), $this->parser->getCurrentToken()->getLine()); } else { - $value = $this->parseExpression(0, $allowArrow); + if ($stream->nextIf(Token::SPREAD_TYPE)) { + $hasSpread = true; + $value = new SpreadUnary($this->parseExpression(), $stream->getCurrent()->getLine()); + } elseif ($hasSpread) { + throw new SyntaxError('Normal arguments must be placed before argument unpacking.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } else { + $value = $this->parseExpression(); + } } $name = null; - if ($namedArguments && (($token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) || ($token = $stream->nextIf(Token::PUNCTUATION_TYPE, ':')))) { + if ($namedArguments && (($token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) || (!$definition && $token = $stream->nextIf(Token::PUNCTUATION_TYPE, ':')))) { if (!$value instanceof NameExpression) { throw new SyntaxError(\sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); } $name = $value->getAttribute('name'); if ($definition) { - $value = $this->parsePrimaryExpression(); + $value = $this->getPrimary(); if (!$this->checkConstantExpression($value)) { throw new SyntaxError('A default value for an argument must be a constant (a boolean, a string, a number, a sequence, or a mapping).', $token->getLine(), $stream->getSourceContext()); } } else { - $value = $this->parseExpression(0, $allowArrow); + $value = $this->parseExpression(); } } @@ -672,7 +694,7 @@ public function parseArguments($namedArguments = false, $definition = false, $al } $stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); - return new Node($args); + return new Nodes($args); } public function parseAssignmentExpression() @@ -687,18 +709,14 @@ public function parseAssignmentExpression() } else { $stream->expect(Token::NAME_TYPE, null, 'Only variables can be assigned to'); } - $value = $token->getValue(); - if (\in_array(strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), ['true', 'false', 'none', 'null'])) { - throw new SyntaxError(\sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); - } - $targets[] = new AssignNameExpression($value, $token->getLine()); + $targets[] = new AssignContextVariable($token->getValue(), $token->getLine()); if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { break; } } - return new Node($targets); + return new Nodes($targets); } public function parseMultitargetExpression() @@ -711,7 +729,7 @@ public function parseMultitargetExpression() } } - return new Node($targets); + return new Nodes($targets); } private function parseNotTestExpression(Node $node): NotUnary @@ -726,14 +744,13 @@ private function parseTestExpression(Node $node): TestExpression $arguments = null; if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { - $arguments = $this->parseArguments(true); + $arguments = $this->parseOnlyArguments(); } elseif ($test->hasOneMandatoryArgument()) { - $arguments = new Node([0 => $this->parsePrimaryExpression()]); + $arguments = new Nodes([0 => $this->getPrimary()]); } if ('defined' === $test->getName() && $node instanceof NameExpression && null !== $alias = $this->parser->getImportedSymbol('function', $node->getAttribute('name'))) { - $node = new MethodCallExpression($alias['node'], $alias['name'], new ArrayExpression([], $node->getTemplateLine()), $node->getTemplateLine()); - $node->setAttribute('safe', true); + $node = new MacroReferenceExpression($alias['node']->getNode('var'), $alias['name'], new ArrayExpression([], $node->getTemplateLine()), $node->getTemplateLine()); } $ready = $test instanceof TwigTest; @@ -765,6 +782,9 @@ private function getTest(int $line): TwigTest } if (!$test) { + if ($this->parser->shouldIgnoreUnknownTwigCallables()) { + return new TwigTest($name, fn () => ''); + } $e = new SyntaxError(\sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getTests())); @@ -773,15 +793,8 @@ private function getTest(int $line): TwigTest if ($test->isDeprecated()) { $stream = $this->parser->getStream(); - $message = \sprintf('Twig Test "%s" is deprecated', $test->getName()); - - if ($test->getAlternative()) { - $message .= \sprintf('. Use "%s" instead', $test->getAlternative()); - } $src = $stream->getSourceContext(); - $message .= \sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $stream->getCurrent()->getLine()); - - trigger_deprecation($test->getDeprecatingPackage(), $test->getDeprecatedVersion(), $message); + $test->triggerDeprecation($src->getPath() ?: $src->getName(), $stream->getCurrent()->getLine()); } return $test; @@ -790,6 +803,9 @@ private function getTest(int $line): TwigTest private function getFunction(string $name, int $line): TwigFunction { if (!$function = $this->env->getFunction($name)) { + if ($this->parser->shouldIgnoreUnknownTwigCallables()) { + return new TwigFunction($name, fn () => ''); + } $e = new SyntaxError(\sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFunctions())); @@ -797,14 +813,8 @@ private function getFunction(string $name, int $line): TwigFunction } if ($function->isDeprecated()) { - $message = \sprintf('Twig Function "%s" is deprecated', $function->getName()); - if ($function->getAlternative()) { - $message .= \sprintf('. Use "%s" instead', $function->getAlternative()); - } $src = $this->parser->getStream()->getSourceContext(); - $message .= \sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); - - trigger_deprecation($function->getDeprecatingPackage(), $function->getDeprecatedVersion(), $message); + $function->triggerDeprecation($src->getPath() ?: $src->getName(), $line); } return $function; @@ -813,6 +823,9 @@ private function getFunction(string $name, int $line): TwigFunction private function getFilter(string $name, int $line): TwigFilter { if (!$filter = $this->env->getFilter($name)) { + if ($this->parser->shouldIgnoreUnknownTwigCallables()) { + return new TwigFilter($name, fn () => ''); + } $e = new SyntaxError(\sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFilters())); @@ -820,20 +833,15 @@ private function getFilter(string $name, int $line): TwigFilter } if ($filter->isDeprecated()) { - $message = \sprintf('Twig Filter "%s" is deprecated', $filter->getName()); - if ($filter->getAlternative()) { - $message .= \sprintf('. Use "%s" instead', $filter->getAlternative()); - } $src = $this->parser->getStream()->getSourceContext(); - $message .= \sprintf(' in %s at line %d.', $src->getPath() ?: $src->getName(), $line); - - trigger_deprecation($filter->getDeprecatingPackage(), $filter->getDeprecatedVersion(), $message); + $filter->triggerDeprecation($src->getPath() ?: $src->getName(), $line); } return $filter; } // checks that the node only contains "constant" elements + // to be removed in 4.0 private function checkConstantExpression(Node $node): bool { if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression @@ -850,4 +858,154 @@ private function checkConstantExpression(Node $node): bool return true; } + + private function setDeprecationCheck(bool $deprecationCheck): bool + { + $current = $this->deprecationCheck; + $this->deprecationCheck = $deprecationCheck; + + return $current; + } + + private function createArguments(int $line): ArrayExpression + { + $arguments = new ArrayExpression([], $line); + foreach ($this->parseOnlyArguments() as $k => $n) { + $arguments->addElement($n, new LocalVariable($k, $line)); + } + + return $arguments; + } + + public function parseOnlyArguments() + { + $args = []; + $stream = $this->parser->getStream(); + $stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + $hasSpread = false; + while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) { + if ($args) { + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); + + // if the comma above was a trailing comma, early exit the argument parse loop + if ($stream->test(Token::PUNCTUATION_TYPE, ')')) { + break; + } + } + + if ($stream->nextIf(Token::SPREAD_TYPE)) { + $hasSpread = true; + $value = new SpreadUnary($this->parseExpression(), $stream->getCurrent()->getLine()); + } elseif ($hasSpread) { + throw new SyntaxError('Normal arguments must be placed before argument unpacking.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } else { + $value = $this->parseExpression(); + } + + $name = null; + if (($token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) || ($token = $stream->nextIf(Token::PUNCTUATION_TYPE, ':'))) { + if (!$value instanceof NameExpression) { + throw new SyntaxError(\sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); + } + $name = $value->getAttribute('name'); + $value = $this->parseExpression(); + } + + if (null === $name) { + $args[] = $value; + } else { + $args[$name] = $value; + } + } + $stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); + + return new Nodes($args); + } + + private function parseSubscriptExpressionDot(Node $node): AbstractExpression + { + $stream = $this->parser->getStream(); + $token = $stream->getCurrent(); + $lineno = $token->getLine(); + $arguments = new ArrayExpression([], $lineno); + $type = Template::ANY_CALL; + + if ($stream->nextIf(Token::PUNCTUATION_TYPE, '(')) { + $attribute = $this->parseExpression(); + $stream->expect(Token::PUNCTUATION_TYPE, ')'); + } else { + $token = $stream->next(); + if ( + Token::NAME_TYPE == $token->getType() + || + Token::NUMBER_TYPE == $token->getType() + || + (Token::OPERATOR_TYPE == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue())) + ) { + $attribute = new ConstantExpression($token->getValue(), $token->getLine()); + } else { + throw new SyntaxError(\sprintf('Expected name or number, got value "%s" of type %s.', $token->getValue(), Token::typeToEnglish($token->getType())), $token->getLine(), $stream->getSourceContext()); + } + } + + if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { + $type = Template::METHOD_CALL; + $arguments = $this->createArguments($token->getLine()); + } + + if ( + $node instanceof NameExpression + && + ( + null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name')) + || + '_self' === $node->getAttribute('name') && $attribute instanceof ConstantExpression + ) + ) { + return new MacroReferenceExpression(new TemplateVariable($node->getAttribute('name'), $node->getTemplateLine()), 'macro_'.$attribute->getAttribute('value'), $arguments, $node->getTemplateLine()); + } + + return new GetAttrExpression($node, $attribute, $arguments, $type, $lineno); + } + + private function parseSubscriptExpressionArray(Node $node): AbstractExpression + { + $stream = $this->parser->getStream(); + $token = $stream->getCurrent(); + $lineno = $token->getLine(); + $arguments = new ArrayExpression([], $lineno); + + // slice? + $slice = false; + if ($stream->test(Token::PUNCTUATION_TYPE, ':')) { + $slice = true; + $attribute = new ConstantExpression(0, $token->getLine()); + } else { + $attribute = $this->parseExpression(); + } + + if ($stream->nextIf(Token::PUNCTUATION_TYPE, ':')) { + $slice = true; + } + + if ($slice) { + if ($stream->test(Token::PUNCTUATION_TYPE, ']')) { + $length = new ConstantExpression(null, $token->getLine()); + } else { + $length = $this->parseExpression(); + } + + $filter = $this->getFilter('slice', $token->getLine()); + $arguments = new Nodes([$attribute, $length]); + $filter = new ($filter->getNodeClass())($node, $filter, $arguments, $token->getLine()); + + $stream->expect(Token::PUNCTUATION_TYPE, ']'); + + return $filter; + } + + $stream->expect(Token::PUNCTUATION_TYPE, ']'); + + return new GetAttrExpression($node, $attribute, $arguments, Template::ARRAY_CALL, $lineno); + } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/CoreExtension.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/CoreExtension.php index e1fd3962e..429763ad1 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/CoreExtension.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/CoreExtension.php @@ -11,6 +11,7 @@ namespace Twig\Extension; +use Twig\DeprecatedCallableInfo; use Twig\Environment; use Twig\Error\LoaderError; use Twig\Error\RuntimeError; @@ -46,9 +47,11 @@ use Twig\Node\Expression\Binary\SpaceshipBinary; use Twig\Node\Expression\Binary\StartsWithBinary; use Twig\Node\Expression\Binary\SubBinary; +use Twig\Node\Expression\Binary\XorBinary; use Twig\Node\Expression\BlockReferenceExpression; use Twig\Node\Expression\Filter\DefaultFilter; use Twig\Node\Expression\FunctionNode\EnumCasesFunction; +use Twig\Node\Expression\FunctionNode\EnumFunction; use Twig\Node\Expression\GetAttrExpression; use Twig\Node\Expression\NullCoalesceExpression; use Twig\Node\Expression\ParentExpression; @@ -63,7 +66,7 @@ use Twig\Node\Expression\Unary\NotUnary; use Twig\Node\Expression\Unary\PosUnary; use Twig\Node\Node; -use Twig\NodeVisitor\MacroAutoImportNodeVisitor; +use Twig\OperatorPrecedenceChange; use Twig\Parser; use Twig\Sandbox\SecurityNotAllowedMethodError; use Twig\Sandbox\SecurityNotAllowedPropertyError; @@ -79,6 +82,7 @@ use Twig\TokenParser\FlushTokenParser; use Twig\TokenParser\ForTokenParser; use Twig\TokenParser\FromTokenParser; +use Twig\TokenParser\GuardTokenParser; use Twig\TokenParser\IfTokenParser; use Twig\TokenParser\ImportTokenParser; use Twig\TokenParser\IncludeTokenParser; @@ -108,6 +112,8 @@ final class CoreExtension extends AbstractExtension 'WeakMap', ]; + private const DEFAULT_TRIM_CHARS = " \t\n\r\0\x0B"; + private $dateFormats = ['F j, Y H:i', '%d days']; private $numberFormat = [0, '.', ',']; private $timezone = null; @@ -205,6 +211,7 @@ public function getTokenParsers(): array new EmbedTokenParser(), new WithTokenParser(), new DeprecatedTokenParser(), + new GuardTokenParser(), ]; } @@ -233,7 +240,7 @@ public function getFilters(): array new TwigFilter('striptags', [self::class, 'striptags']), new TwigFilter('trim', [self::class, 'trim']), new TwigFilter('nl2br', [self::class, 'nl2br'], ['pre_escape' => 'html', 'is_safe' => ['html']]), - new TwigFilter('spaceless', [self::class, 'spaceless'], ['is_safe' => ['html'], 'deprecated' => '3.12', 'deprecating_package' => 'twig/twig']), + new TwigFilter('spaceless', [self::class, 'spaceless'], ['is_safe' => ['html'], 'deprecation_info' => new DeprecatedCallableInfo('twig/twig', '3.12')]), // array helpers new TwigFilter('join', [self::class, 'join']), @@ -277,6 +284,7 @@ public function getFunctions(): array new TwigFunction('include', [self::class, 'include'], ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]), new TwigFunction('source', [self::class, 'source'], ['needs_environment' => true, 'is_safe' => ['all']]), new TwigFunction('enum_cases', [self::class, 'enumCases'], ['node_class' => EnumCasesFunction::class]), + new TwigFunction('enum', [self::class, 'enum'], ['node_class' => EnumFunction::class]), ]; } @@ -300,19 +308,20 @@ public function getTests(): array public function getNodeVisitors(): array { - return [new MacroAutoImportNodeVisitor()]; + return []; } public function getOperators(): array { return [ [ - 'not' => ['precedence' => 50, 'class' => NotUnary::class], + 'not' => ['precedence' => 50, 'precedence_change' => new OperatorPrecedenceChange('twig/twig', '3.15', 70), 'class' => NotUnary::class], '-' => ['precedence' => 500, 'class' => NegUnary::class], '+' => ['precedence' => 500, 'class' => PosUnary::class], ], [ 'or' => ['precedence' => 10, 'class' => OrBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'xor' => ['precedence' => 12, 'class' => XorBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], 'and' => ['precedence' => 15, 'class' => AndBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], 'b-or' => ['precedence' => 16, 'class' => BitwiseOrBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], 'b-xor' => ['precedence' => 17, 'class' => BitwiseXorBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], @@ -334,7 +343,7 @@ public function getOperators(): array '..' => ['precedence' => 25, 'class' => RangeBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '+' => ['precedence' => 30, 'class' => AddBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '-' => ['precedence' => 30, 'class' => SubBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], - '~' => ['precedence' => 40, 'class' => ConcatBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], + '~' => ['precedence' => 40, 'precedence_change' => new OperatorPrecedenceChange('twig/twig', '3.15', 27), 'class' => ConcatBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '*' => ['precedence' => 60, 'class' => MulBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '/' => ['precedence' => 60, 'class' => DivBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], '//' => ['precedence' => 60, 'class' => FloorDivBinary::class, 'associativity' => ExpressionParser::OPERATOR_LEFT], @@ -342,7 +351,7 @@ public function getOperators(): array 'is' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], 'is not' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], '**' => ['precedence' => 200, 'class' => PowerBinary::class, 'associativity' => ExpressionParser::OPERATOR_RIGHT], - '??' => ['precedence' => 300, 'class' => NullCoalesceExpression::class, 'associativity' => ExpressionParser::OPERATOR_RIGHT], + '??' => ['precedence' => 300, 'precedence_change' => new OperatorPrecedenceChange('twig/twig', '3.15', 5), 'class' => NullCoalesceExpression::class, 'associativity' => ExpressionParser::OPERATOR_RIGHT], ], ]; } @@ -351,7 +360,7 @@ public function getOperators(): array * Cycles over a sequence. * * @param array|\ArrayAccess $values A non-empty sequence of values - * @param positive-int $position The position of the value to return in the cycle + * @param int<0, max> $position The position of the value to return in the cycle * * @return mixed The value at the given position in the sequence, wrapping around as needed * @@ -377,7 +386,7 @@ public static function cycle($values, $position): mixed } if (!$count = \count($values)) { - throw new RuntimeError('The "cycle" function does not work on empty sequences.'); + throw new RuntimeError('The "cycle" function expects a non-empty sequence.'); } return $values[$position % $count]; @@ -447,7 +456,7 @@ public static function random(string $charset, $values = null, $max = null) $values = self::toArray($values); if (0 === \count($values)) { - throw new RuntimeError('The random function cannot pick from an empty sequence/mapping.'); + throw new RuntimeError('The "random" function cannot pick from an empty sequence or mapping.'); } return $values[array_rand($values, 1)]; @@ -458,9 +467,9 @@ public static function random(string $charset, $values = null, $max = null) * * {{ post.published_at|date("m/d/Y") }} * - * @param \DateTimeInterface|\DateInterval|string $date A date - * @param string|null $format The target format, null to use the default - * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged + * @param \DateTimeInterface|\DateInterval|string|int|null $date A date, a timestamp or null to use the current time + * @param string|null $format The target format, null to use the default + * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged */ public function formatDate($date, $format = null, $timezone = null): string { @@ -481,8 +490,8 @@ public function formatDate($date, $format = null, $timezone = null): string * * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }} * - * @param \DateTimeInterface|string $date A date - * @param string $modifier A modifier string + * @param \DateTimeInterface|string|int|null $date A date, a timestamp or null to use the current time + * @param string $modifier A modifier string * * @return \DateTime|\DateTimeImmutable * @@ -521,8 +530,8 @@ public static function dateConverter(Environment $env, $date, $format = null, $t * {# do something #} * {% endif %} * - * @param \DateTimeInterface|string|null $date A date or null to use the current time - * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged + * @param \DateTimeInterface|string|int|null $date A date, a timestamp or null to use the current time + * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged * * @return \DateTime|\DateTimeImmutable */ @@ -560,7 +569,7 @@ public function convertDate($date = null, $timezone = null) } $asString = (string) $date; - if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { + if (ctype_digit($asString) || ('' !== $asString && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { $date = new \DateTime('@'.$date); } else { $date = new \DateTime($date, $this->getTimezone()); @@ -584,7 +593,7 @@ public function convertDate($date = null, $timezone = null) public static function replace($str, $from): string { if (!is_iterable($from)) { - throw new RuntimeError(\sprintf('The "replace" filter expects a sequence/mapping or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from))); + throw new RuntimeError(\sprintf('The "replace" filter expects a sequence or a mapping, got "%s".', get_debug_type($from))); } return strtr($str ?? '', self::toArray($from)); @@ -593,11 +602,11 @@ public static function replace($str, $from): string /** * Rounds a number. * - * @param int|float|string|null $value The value to round - * @param int|float $precision The rounding precision - * @param string $method The method to use for rounding + * @param int|float|string|null $value The value to round + * @param int|float $precision The rounding precision + * @param 'common'|'ceil'|'floor' $method The method to use for rounding * - * @return int|float The rounded number + * @return float The rounded number * * @internal */ @@ -610,7 +619,7 @@ public static function round($value, $precision = 0, $method = 'common') } if ('ceil' !== $method && 'floor' !== $method) { - throw new RuntimeError('The round filter only supports the "common", "ceil", and "floor" methods.'); + throw new RuntimeError('The "round" filter only supports the "common", "ceil", and "floor" methods.'); } return $method($value * 10 ** $precision) / 10 ** $precision; @@ -681,7 +690,7 @@ public static function merge(...$arrays): array foreach ($arrays as $argNumber => $array) { if (!is_iterable($array)) { - throw new RuntimeError(\sprintf('The merge filter only works with sequences/mappings or "Traversable", got "%s" for argument %d.', \gettype($array), $argNumber + 1)); + throw new RuntimeError(\sprintf('The "merge" filter expects a sequence or a mapping, got "%s" for argument %d.', get_debug_type($array), $argNumber + 1)); } $result = array_merge($result, self::toArray($array)); @@ -773,9 +782,9 @@ public static function last(string $charset, $item) * {{ [1, 2, 3]|join }} * {# returns 123 #} * - * @param array $value An array - * @param string $glue The separator - * @param string|null $and The separator for the last pair + * @param iterable|array|string|float|int|bool|null $value An array + * @param string $glue The separator + * @param string|null $and The separator for the last pair * * @internal */ @@ -980,6 +989,7 @@ public static function shuffle(string $charset, $item) * Sorts an array. * * @param array|\Traversable $array + * @param ?\Closure $arrow * * @internal */ @@ -988,11 +998,11 @@ public static function sort(Environment $env, $array, $arrow = null): array if ($array instanceof \Traversable) { $array = iterator_to_array($array); } elseif (!\is_array($array)) { - throw new RuntimeError(\sprintf('The sort filter only works with sequences/mappings or "Traversable", got "%s".', \gettype($array))); + throw new RuntimeError(\sprintf('The "sort" filter expects a sequence or a mapping, got "%s".', get_debug_type($array))); } if (null !== $arrow) { - self::checkArrowInSandbox($env, $arrow, 'sort', 'filter'); + self::checkArrow($env, $arrow, 'sort', 'filter'); uasort($array, $arrow); } else { @@ -1131,30 +1141,29 @@ public static function matches(string $regexp, ?string $str): int /** * Returns a trimmed string. * - * @param string|null $string - * @param string|null $characterMask - * @param string $side + * @param string|\Stringable|null $string + * @param string|null $characterMask + * @param string $side left, right, or both * - * @throws RuntimeError When an invalid trimming side is used (not a string or not 'left', 'right', or 'both') + * @throws RuntimeError When an invalid trimming side is used * * @internal */ - public static function trim($string, $characterMask = null, $side = 'both'): string + public static function trim($string, $characterMask = null, $side = 'both'): string|\Stringable { if (null === $characterMask) { - $characterMask = " \t\n\r\0\x0B"; + $characterMask = self::DEFAULT_TRIM_CHARS; } - switch ($side) { - case 'both': - return trim($string ?? '', $characterMask); - case 'left': - return ltrim($string ?? '', $characterMask); - case 'right': - return rtrim($string ?? '', $characterMask); - default: - throw new RuntimeError('Trimming side must be "left", "right" or "both".'); - } + $trimmed = match ($side) { + 'both' => trim($string ?? '', $characterMask), + 'left' => ltrim($string ?? '', $characterMask), + 'right' => rtrim($string ?? '', $characterMask), + default => throw new RuntimeError('Trimming side must be "left", "right" or "both".'), + }; + + // trimming a safe string with the default character mask always returns a safe string (independently of the context) + return $string instanceof Markup && self::DEFAULT_TRIM_CHARS === $characterMask ? new Markup($trimmed, $string->getCharset()) : $trimmed; } /** @@ -1292,6 +1301,8 @@ public static function capitalize(string $charset, $string): string /** * @internal + * + * to be removed in 4.0 */ public static function callMacro(Template $template, string $method, array $args, int $lineno, array $context, Source $source) { @@ -1515,6 +1526,30 @@ public static function enumCases(string $enum): array return $enum::cases(); } + /** + * Provides the ability to access enums by their class names. + * + * @template T of \UnitEnum + * + * @param class-string $enum + * + * @return T + * + * @internal + */ + public static function enum(string $enum): \UnitEnum + { + if (!enum_exists($enum)) { + throw new RuntimeError(sprintf('"%s" is not an enum.', $enum)); + } + + if (!$cases = $enum::cases()) { + throw new RuntimeError(sprintf('"%s" is an empty enum.', $enum)); + } + + return $cases[0]; + } + /** * Provides the ability to get constants from instances as well as class/global constants. * @@ -1544,7 +1579,7 @@ public static function constant($constant, $object = null, bool $checkDefined = } if ('::class' === strtolower(substr($constant, -7))) { - throw new RuntimeError(\sprintf('You cannot use the Twig function "constant()" to access "%s". You could provide an object and call constant("class", $object) or use the class name directly as a string.', $constant)); + throw new RuntimeError(\sprintf('You cannot use the Twig function "constant" to access "%s". You could provide an object and call constant("class", $object) or use the class name directly as a string.', $constant)); } throw new RuntimeError(\sprintf('Constant "%s" is undefined.', $constant)); @@ -1565,7 +1600,7 @@ public static function constant($constant, $object = null, bool $checkDefined = public static function batch($items, $size, $fill = null, $preserveKeys = true): array { if (!is_iterable($items)) { - throw new RuntimeError(\sprintf('The "batch" filter expects a sequence/mapping or "Traversable", got "%s".', \is_object($items) ? \get_class($items) : \gettype($items))); + throw new RuntimeError(\sprintf('The "batch" filter expects a sequence or a mapping, got "%s".', get_debug_type($items))); } $size = (int) ceil($size); @@ -1607,7 +1642,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $ // array if (Template::METHOD_CALL !== $type) { - $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item; + $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item = (string) $item; if ($sandboxed && $object instanceof \ArrayAccess && !\in_array($object::class, self::ARRAY_LIKE_CLASSES, true)) { try { @@ -1617,9 +1652,11 @@ public static function getAttribute(Environment $env, Source $source, $object, $ } } - if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, (array) $object))) - || ($object instanceof \ArrayAccess && isset($object[$arrayItem])) - ) { + if (match (true) { + \is_array($object) => \array_key_exists($arrayItem, $object), + $object instanceof \ArrayAccess => $object->offsetExists($arrayItem), + default => false, + }) { if ($isDefinedTest) { return true; } @@ -1641,7 +1678,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $ } elseif (\is_object($object)) { $message = \sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object)); } elseif (\is_array($object)) { - if (empty($object)) { + if (!$object) { $message = \sprintf('Key "%s" does not exist as the sequence/mapping is empty.', $arrayItem); } else { $message = \sprintf('Key "%s" for sequence/mapping with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); @@ -1650,18 +1687,20 @@ public static function getAttribute(Environment $env, Source $source, $object, $ if (null === $object) { $message = \sprintf('Impossible to access a key ("%s") on a null variable.', $item); } else { - $message = \sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + $message = \sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, get_debug_type($object), $object); } } elseif (null === $object) { $message = \sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); } else { - $message = \sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + $message = \sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, get_debug_type($object), $object); } throw new RuntimeError($message, $lineno, $source); } } + $item = (string) $item; + if (!\is_object($object)) { if ($isDefinedTest) { return false; @@ -1676,7 +1715,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $ } elseif (\is_array($object)) { $message = \sprintf('Impossible to invoke a method ("%s") on a sequence/mapping.', $item); } else { - $message = \sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + $message = \sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, get_debug_type($object), $object); } throw new RuntimeError($message, $lineno, $source); @@ -1696,13 +1735,33 @@ public static function getAttribute(Environment $env, Source $source, $object, $ } } - if (isset($object->$item) || \array_key_exists((string) $item, (array) $object)) { + static $propertyCheckers = []; + + if (isset($object->$item) + || ($propertyCheckers[$object::class][$item] ??= self::getPropertyChecker($object::class, $item))($object, $item) + ) { if ($isDefinedTest) { return true; } return $object->$item; } + + if ($object instanceof \DateTimeInterface && \in_array($item, ['date', 'timezone', 'timezone_type'], true)) { + if ($isDefinedTest) { + return true; + } + + return ((array) $object)[$item]; + } + + if (\defined($object::class.'::'.$item)) { + if ($isDefinedTest) { + return true; + } + + return \constant($object::class.'::'.$item); + } } methodCheck: @@ -1716,7 +1775,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $ if (!isset($cache[$class])) { $methods = get_class_methods($object); sort($methods); - $lcMethods = array_map(function ($value) { return strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); }, $methods); + $lcMethods = array_map('strtolower', $methods); $classCache = []; foreach ($methods as $i => $method) { $classCache[$method] = $method; @@ -1755,7 +1814,7 @@ public static function getAttribute(Environment $env, Source $source, $object, $ $call = false; if (isset($cache[$class][$item])) { $method = $cache[$class][$item]; - } elseif (isset($cache[$class][$lcItem = strtr($item, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')])) { + } elseif (isset($cache[$class][$lcItem = strtolower($item)])) { $method = $cache[$class][$lcItem]; } elseif (isset($cache[$class]['__call'])) { $method = $item; @@ -1831,25 +1890,29 @@ public static function getAttribute(Environment $env, Source $source, $object, $ */ public static function column($array, $name, $index = null): array { + if (!is_iterable($array)) { + throw new RuntimeError(\sprintf('The "column" filter expects a sequence or a mapping, got "%s".', get_debug_type($array))); + } + if ($array instanceof \Traversable) { $array = iterator_to_array($array); - } elseif (!\is_array($array)) { - throw new RuntimeError(\sprintf('The column filter only works with sequences/mappings or "Traversable", got "%s" as first argument.', \gettype($array))); } return array_column($array, $name, $index); } /** + * @param \Closure $arrow + * * @internal */ public static function filter(Environment $env, $array, $arrow) { if (!is_iterable($array)) { - throw new RuntimeError(\sprintf('The "filter" filter expects a sequence/mapping or "Traversable", got "%s".', \is_object($array) ? \get_class($array) : \gettype($array))); + throw new RuntimeError(\sprintf('The "filter" filter expects a sequence/mapping or "Traversable", got "%s".', get_debug_type($array))); } - self::checkArrowInSandbox($env, $arrow, 'filter', 'filter'); + self::checkArrow($env, $arrow, 'filter', 'filter'); if (\is_array($array)) { return array_filter($array, $arrow, \ARRAY_FILTER_USE_BOTH); @@ -1860,11 +1923,17 @@ public static function filter(Environment $env, $array, $arrow) } /** + * @param \Closure $arrow + * * @internal */ public static function find(Environment $env, $array, $arrow) { - self::checkArrowInSandbox($env, $arrow, 'find', 'filter'); + if (!is_iterable($array)) { + throw new RuntimeError(\sprintf('The "find" filter expects a sequence or a mapping, got "%s".', get_debug_type($array))); + } + + self::checkArrow($env, $arrow, 'find', 'filter'); foreach ($array as $k => $v) { if ($arrow($v, $k)) { @@ -1876,15 +1945,17 @@ public static function find(Environment $env, $array, $arrow) } /** + * @param \Closure $arrow + * * @internal */ public static function map(Environment $env, $array, $arrow) { if (!is_iterable($array)) { - throw new RuntimeError(\sprintf('The "map" filter expects a sequence/mapping or "Traversable", got "%s".', get_debug_type($array))); + throw new RuntimeError(\sprintf('The "map" filter expects a sequence or a mapping, got "%s".', get_debug_type($array))); } - self::checkArrowInSandbox($env, $arrow, 'map', 'filter'); + self::checkArrow($env, $arrow, 'map', 'filter'); $r = []; foreach ($array as $k => $v) { @@ -1895,16 +1966,18 @@ public static function map(Environment $env, $array, $arrow) } /** + * @param \Closure $arrow + * * @internal */ public static function reduce(Environment $env, $array, $arrow, $initial = null) { - self::checkArrowInSandbox($env, $arrow, 'reduce', 'filter'); - - if (!\is_array($array) && !$array instanceof \Traversable) { - throw new RuntimeError(\sprintf('The "reduce" filter only works with sequences/mappings or "Traversable", got "%s" as first argument.', \gettype($array))); + if (!is_iterable($array)) { + throw new RuntimeError(\sprintf('The "reduce" filter expects a sequence or a mapping, got "%s".', get_debug_type($array))); } + self::checkArrow($env, $arrow, 'reduce', 'filter'); + $accumulator = $initial; foreach ($array as $key => $value) { $accumulator = $arrow($accumulator, $value, $key); @@ -1914,11 +1987,17 @@ public static function reduce(Environment $env, $array, $arrow, $initial = null) } /** + * @param \Closure $arrow + * * @internal */ public static function arraySome(Environment $env, $array, $arrow) { - self::checkArrowInSandbox($env, $arrow, 'has some', 'operator'); + if (!is_iterable($array)) { + throw new RuntimeError(\sprintf('The "has some" test expects a sequence or a mapping, got "%s".', get_debug_type($array))); + } + + self::checkArrow($env, $arrow, 'has some', 'operator'); foreach ($array as $k => $v) { if ($arrow($v, $k)) { @@ -1930,11 +2009,17 @@ public static function arraySome(Environment $env, $array, $arrow) } /** + * @param \Closure $arrow + * * @internal */ public static function arrayEvery(Environment $env, $array, $arrow) { - self::checkArrowInSandbox($env, $arrow, 'has every', 'operator'); + if (!is_iterable($array)) { + throw new RuntimeError(\sprintf('The "has every" test expects a sequence or a mapping, got "%s".', get_debug_type($array))); + } + + self::checkArrow($env, $arrow, 'has every', 'operator'); foreach ($array as $k => $v) { if (!$arrow($v, $k)) { @@ -1948,11 +2033,17 @@ public static function arrayEvery(Environment $env, $array, $arrow) /** * @internal */ - public static function checkArrowInSandbox(Environment $env, $arrow, $thing, $type) + public static function checkArrow(Environment $env, $arrow, $thing, $type) { - if (!$arrow instanceof \Closure && $env->hasExtension(SandboxExtension::class) && $env->getExtension(SandboxExtension::class)->isSandboxed()) { + if ($arrow instanceof \Closure) { + return; + } + + if ($env->hasExtension(SandboxExtension::class) && $env->getExtension(SandboxExtension::class)->isSandboxed()) { throw new RuntimeError(\sprintf('The callable passed to the "%s" %s must be a Closure in sandbox mode.', $thing, $type)); } + + trigger_deprecation('twig/twig', '3.15', 'Passing a callable that is not a PHP \Closure as an argument to the "%s" %s is deprecated.', $thing, $type); } /** @@ -2013,6 +2104,38 @@ public static function parseAttributeFunction(Parser $parser, Node $fakeNode, $a $fakeFunction = new TwigFunction('attribute', fn ($variable, $attribute, $arguments = null) => null); $args = (new CallableArgumentsExtractor($fakeNode, $fakeFunction))->extractArguments($args); + /* + Deprecation to uncomment sometimes during the lifetime of the 4.x branch + $src = $parser->getStream()->getSourceContext(); + $dep = new DeprecatedCallableInfo('twig/twig', '3.15', 'The "attribute" function is deprecated, use the "." notation instead.'); + $dep->setName('attribute'); + $dep->setType('function'); + $dep->triggerDeprecation($src->getPath() ?: $src->getName(), $line); + */ + return new GetAttrExpression($args[0], $args[1], $args[2] ?? null, Template::ANY_CALL, $line); } + + private static function getPropertyChecker(string $class, string $property): \Closure + { + static $classReflectors = []; + + $class = $classReflectors[$class] ??= new \ReflectionClass($class); + + if (!$class->hasProperty($property)) { + static $propertyExists; + + return $propertyExists ??= \Closure::fromCallable('property_exists'); + } + + $property = $class->getProperty($property); + + if (!$property->isPublic()) { + static $false; + + return $false ??= static fn () => false; + } + + return static fn ($object) => $property->isInitialized($object); + } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/ExtensionInterface.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/ExtensionInterface.php index 10a42b6b1..717ef9cec 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/ExtensionInterface.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Extension/ExtensionInterface.php @@ -14,6 +14,7 @@ use Twig\ExpressionParser; use Twig\Node\Expression\AbstractExpression; use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\OperatorPrecedenceChange; use Twig\TokenParser\TokenParserInterface; use Twig\TwigFilter; use Twig\TwigFunction; @@ -67,8 +68,8 @@ public function getFunctions(); * @return array First array of unary operators, second array of binary operators * * @psalm-return array{ - * array}>, - * array, associativity: ExpressionParser::OPERATOR_*}> + * array}>, + * array, associativity: ExpressionParser::OPERATOR_*}> * } */ public function getOperators(); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/ExtensionSet.php b/.extlib/simplesamlphp/vendor/twig/twig/src/ExtensionSet.php index 28d57a41c..99fcfe56b 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/ExtensionSet.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/ExtensionSet.php @@ -16,8 +16,6 @@ use Twig\Extension\GlobalsInterface; use Twig\Extension\StagingExtension; use Twig\Node\Expression\AbstractExpression; -use Twig\Node\Expression\Binary\AbstractBinary; -use Twig\Node\Expression\Unary\AbstractUnary; use Twig\NodeVisitor\NodeVisitorInterface; use Twig\TokenParser\TokenParserInterface; @@ -50,7 +48,7 @@ final class ExtensionSet private $unaryOperators; /** @var array, associativity: ExpressionParser::OPERATOR_*}> */ private $binaryOperators; - /** @var array */ + /** @var array|null */ private $globals; private $functionCallbacks = []; private $filterCallbacks = []; @@ -474,7 +472,7 @@ private function initExtension(ExtensionInterface $extension): void // operators if ($operators = $extension->getOperators()) { if (!\is_array($operators)) { - throw new \InvalidArgumentException(\sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators))); + throw new \InvalidArgumentException(\sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), get_debug_type($operators).(\is_resource($operators) ? '' : '#'.$operators))); } if (2 !== \count($operators)) { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/FileExtensionEscapingStrategy.php b/.extlib/simplesamlphp/vendor/twig/twig/src/FileExtensionEscapingStrategy.php index 812071bf9..5308158d3 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/FileExtensionEscapingStrategy.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/FileExtensionEscapingStrategy.php @@ -45,6 +45,7 @@ public static function guess(string $name) switch ($extension) { case 'js': + case 'json': return 'js'; case 'css': diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Lexer.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Lexer.php index 28feaa2c1..4983313cf 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Lexer.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Lexer.php @@ -48,6 +48,7 @@ class Lexer public const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; public const REGEX_DQ_STRING_DELIM = '/"/A'; public const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; + public const REGEX_INLINE_COMMENT = '/#[^\n]*/A'; public const PUNCTUATION = '()[]{}?:.,|'; private const SPECIAL_CHARS = [ @@ -217,7 +218,7 @@ public function tokenize(Source $source): TokenStream $this->pushToken(Token::EOF_TYPE); - if (!empty($this->brackets)) { + if ($this->brackets) { [$expect, $lineno] = array_pop($this->brackets); throw new SyntaxError(\sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } @@ -292,7 +293,7 @@ private function lexData(): void private function lexBlock(): void { - if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, 0, $this->cursor)) { + if (!$this->brackets && preg_match($this->regexes['lex_block'], $this->code, $match, 0, $this->cursor)) { $this->pushToken(Token::BLOCK_END_TYPE); $this->moveCursor($match[0]); $this->popState(); @@ -303,7 +304,7 @@ private function lexBlock(): void private function lexVar(): void { - if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, 0, $this->cursor)) { + if (!$this->brackets && preg_match($this->regexes['lex_var'], $this->code, $match, 0, $this->cursor)) { $this->pushToken(Token::VAR_END_TYPE); $this->moveCursor($match[0]); $this->popState(); @@ -360,7 +361,7 @@ private function lexExpression(): void } // closing bracket elseif (str_contains(')]}', $this->code[$this->cursor])) { - if (empty($this->brackets)) { + if (!$this->brackets) { throw new SyntaxError(\sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } @@ -384,6 +385,10 @@ private function lexExpression(): void $this->pushState(self::STATE_STRING); $this->moveCursor($match[0]); } + // inline comment + elseif (preg_match(self::REGEX_INLINE_COMMENT, $this->code, $match, 0, $this->cursor)) { + $this->moveCursor($match[0]); + } // unlexable else { throw new SyntaxError(\sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); @@ -418,7 +423,7 @@ private function stripcslashes(string $str, string $quoteType): string $result .= $nextChar; } elseif ("'" === $nextChar || '"' === $nextChar) { if ($nextChar !== $quoteType) { - trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.', $nextChar, $i + 1); + trigger_deprecation('twig/twig', '3.12', 'Character "%s" should not be escaped; the "\" character is ignored in Twig 3 but will not be in Twig 4. Please remove the extra "\" character at position %d in "%s" at line %d.', $nextChar, $i + 1, $this->source->getName(), $this->lineno); } $result .= $nextChar; } elseif ('#' === $nextChar && $i + 1 < $length && '{' === $str[$i + 1]) { @@ -437,7 +442,7 @@ private function stripcslashes(string $str, string $quoteType): string } $result .= \chr(octdec($octal)); } else { - trigger_deprecation('twig/twig', '3.12', 'Character "%s" at position %d should not be escaped; the "\" character is ignored in Twig v3 but will not be in v4. Please remove the extra "\" character.', $nextChar, $i + 1); + trigger_deprecation('twig/twig', '3.12', 'Character "%s" should not be escaped; the "\" character is ignored in Twig 3 but will not be in Twig 4. Please remove the extra "\" character at position %d in "%s" at line %d.', $nextChar, $i + 1, $this->source->getName(), $this->lineno); $result .= $nextChar; } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Loader/FilesystemLoader.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Loader/FilesystemLoader.php index c60964f5f..cad163ead 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Loader/FilesystemLoader.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Loader/FilesystemLoader.php @@ -24,6 +24,9 @@ class FilesystemLoader implements LoaderInterface /** Identifier of the main namespace. */ public const MAIN_NAMESPACE = '__main__'; + /** + * @var array> + */ protected $paths = []; protected $cache = []; protected $errorCache = []; @@ -31,7 +34,7 @@ class FilesystemLoader implements LoaderInterface private $rootPath; /** - * @param string|array $paths A path or an array of paths where to look for templates + * @param string|string[] $paths A path or an array of paths where to look for templates * @param string|null $rootPath The root path common to all relative paths (null for getcwd()) */ public function __construct($paths = [], ?string $rootPath = null) @@ -48,6 +51,8 @@ public function __construct($paths = [], ?string $rootPath = null) /** * Returns the paths to the templates. + * + * @return list */ public function getPaths(string $namespace = self::MAIN_NAMESPACE): array { @@ -58,6 +63,8 @@ public function getPaths(string $namespace = self::MAIN_NAMESPACE): array * Returns the path namespaces. * * The main namespace is always defined. + * + * @return list */ public function getNamespaces(): array { @@ -65,7 +72,7 @@ public function getNamespaces(): array } /** - * @param string|array $paths A path or an array of paths where to look for templates + * @param string|string[] $paths A path or an array of paths where to look for templates */ public function setPaths($paths, string $namespace = self::MAIN_NAMESPACE): void { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Markup.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Markup.php index 4fae779ee..c7aa65bda 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Markup.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Markup.php @@ -32,6 +32,11 @@ public function __toString() return $this->content; } + public function getCharset(): string + { + return $this->charset; + } + /** * @return int */ diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmbedNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmbedNode.php index 4cd3b38f2..597f95e44 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmbedNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmbedNode.php @@ -33,10 +33,10 @@ public function __construct(string $name, int $index, ?AbstractExpression $varia $this->setAttribute('index', $index); } - protected function addGetTemplate(Compiler $compiler): void + protected function addGetTemplate(Compiler $compiler, string $template = ''): void { $compiler - ->write('$this->loadTemplate(') + ->raw('$this->loadTemplate(') ->string($this->getAttribute('name')) ->raw(', ') ->repr($this->getTemplateName()) @@ -46,5 +46,11 @@ protected function addGetTemplate(Compiler $compiler): void ->string($this->getAttribute('index')) ->raw(')') ; + if ($this->getAttribute('ignore_missing')) { + $compiler + ->raw(";\n") + ->write(\sprintf("\$%s->getParent(\$context);\n", $template)) + ; + } } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmptyNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmptyNode.php new file mode 100644 index 000000000..fd4717ff4 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/EmptyNode.php @@ -0,0 +1,33 @@ + + */ +#[YieldReady] +final class EmptyNode extends Node +{ + public function __construct(int $lineno = 0) + { + parent::__construct([], [], $lineno); + } + + public function setNode(string $name, Node $node): void + { + throw new \LogicException('EmptyNode cannot have children.'); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AbstractExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AbstractExpression.php index 1692f5671..22d8617cd 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AbstractExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AbstractExpression.php @@ -25,4 +25,19 @@ public function isGenerator(): bool { return $this->hasAttribute('is_generator') && $this->getAttribute('is_generator'); } + + /** + * @return static + */ + public function setExplicitParentheses(): self + { + $this->setAttribute('with_parentheses', true); + + return $this; + } + + public function hasExplicitParentheses(): bool + { + return $this->hasAttribute('with_parentheses') && $this->getAttribute('with_parentheses'); + } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/ArrayExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/ArrayExpression.php index 5f8b0f63f..9769b719e 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/ArrayExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/ArrayExpression.php @@ -12,6 +12,7 @@ namespace Twig\Node\Expression; use Twig\Compiler; +use Twig\Node\Expression\Unary\StringCastUnary; class ArrayExpression extends AbstractExpression { @@ -97,7 +98,17 @@ public function compile(Compiler $compiler): void $compiler->raw('...')->subcompile($pair['value']); ++$nextIndex; } else { - $key = $pair['key'] instanceof ConstantExpression ? $pair['key']->getAttribute('value') : null; + $key = null; + if ($pair['key'] instanceof NameExpression) { + $pair['key'] = new StringCastUnary($pair['key'], $pair['key']->getTemplateLine()); + } + if ($pair['key'] instanceof TempNameExpression) { + $key = $pair['key']->getAttribute('name'); + $pair['key'] = new ConstantExpression($key, $pair['key']->getTemplateLine()); + } + if ($pair['key'] instanceof ConstantExpression) { + $key = $pair['key']->getAttribute('value'); + } if ($nextIndex !== $key) { if (\is_int($key)) { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php index 7dd1bc4a3..c2cbb8e4a 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php @@ -13,9 +13,25 @@ namespace Twig\Node\Expression; use Twig\Compiler; +use Twig\Error\SyntaxError; +use Twig\Node\Expression\Variable\AssignContextVariable; class AssignNameExpression extends NameExpression { + public function __construct(string $name, int $lineno) + { + if (self::class === static::class) { + trigger_deprecation('twig/twig', '3.15', 'The "%s" class is deprecated, use "%s" instead.', self::class, AssignContextVariable::class); + } + + // All names supported by ExpressionParser::parsePrimaryExpression() should be excluded + if (\in_array(strtolower($name), ['true', 'false', 'none', 'null'])) { + throw new SyntaxError(\sprintf('You cannot assign a value to "%s".', $name), $lineno); + } + + parent::__construct($name, $lineno); + } + public function compile(Compiler $compiler): void { $compiler diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php index c424e5cc5..ccd3be44f 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php @@ -18,8 +18,19 @@ abstract class AbstractBinary extends AbstractExpression { + /** + * @param AbstractExpression $left + * @param AbstractExpression $right + */ public function __construct(Node $left, Node $right, int $lineno) { + if (!$left instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "left" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($left)); + } + if (!$right instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "right" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($right)); + } + parent::__construct(['left' => $left, 'right' => $right], [], $lineno); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php index 4669044e0..0a523c216 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php @@ -12,9 +12,27 @@ namespace Twig\Node\Expression\Binary; use Twig\Compiler; +use Twig\Error\SyntaxError; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Node; class MatchesBinary extends AbstractBinary { + public function __construct(Node $left, Node $right, int $lineno) + { + if ($right instanceof ConstantExpression) { + $regexp = $right->getAttribute('value'); + set_error_handler(static fn ($t, $m) => throw new SyntaxError(\sprintf('Regexp "%s" passed to "matches" is not valid: %s.', $regexp, substr($m, 14)), $lineno)); + try { + preg_match($regexp, ''); + } finally { + restore_error_handler(); + } + } + + parent::__construct($left, $right, $lineno); + } + public function compile(Compiler $compiler): void { $compiler diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/XorBinary.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/XorBinary.php new file mode 100644 index 000000000..d8ccd7853 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Binary/XorBinary.php @@ -0,0 +1,23 @@ +raw('xor'); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php index acd231e15..0094c7adb 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php @@ -22,8 +22,15 @@ */ class BlockReferenceExpression extends AbstractExpression { + /** + * @param AbstractExpression $name + */ public function __construct(Node $name, ?Node $template, int $lineno) { + if (!$name instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($name)); + } + $nodes = ['name' => $name]; if (null !== $template) { $nodes['template'] = $template; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/CallExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/CallExpression.php index 6fc6f66e0..8e999c7eb 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/CallExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/CallExpression.php @@ -128,7 +128,7 @@ protected function compileArguments(Compiler $compiler, $isArray = false): void } /** - * @deprecated since 3.12, use Twig\Util\CallableArgumentsExtractor::getArguments() instead + * @deprecated since Twig 3.12, use Twig\Util\CallableArgumentsExtractor::getArguments() instead */ protected function getArguments($callable, $arguments) { @@ -208,7 +208,7 @@ protected function getArguments($callable, $arguments) } elseif ($callableParameter->isDefaultValueAvailable()) { $optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1); } elseif ($callableParameter->isOptional()) { - if (empty($parameters)) { + if (!$parameters) { break; } else { $missingArguments[] = $name; @@ -235,7 +235,7 @@ protected function getArguments($callable, $arguments) } } - if (!empty($parameters)) { + if ($parameters) { $unknownParameter = null; foreach ($parameters as $parameter) { if ($parameter instanceof Node) { @@ -258,7 +258,7 @@ protected function getArguments($callable, $arguments) } /** - * @deprecated since 3.12 + * @deprecated since Twig 3.12 */ protected function normalizeName(string $name): string { @@ -334,7 +334,7 @@ private function getTwigCallable(): TwigCallableInterface [ 'is_variadic' => $this->hasAttribute('is_variadic') ? $this->getAttribute('is_variadic') : $current->isVariadic(), ], - ))->withDynamicArguments($this->getAttribute('name'), $this->hasAttribute('dynamic_name') ? $this->getAttribute('dynamic_name') : $current->getDynamicName(), $this->hasAttribute('arguments') ?: $current->getArguments()), + ))->withDynamicArguments($this->getAttribute('name'), $this->hasAttribute('dynamic_name') ? $this->getAttribute('dynamic_name') : $current->getDynamicName(), $this->hasAttribute('arguments') ? $this->getAttribute('arguments') : $current->getArguments()), 'function' => (new TwigFunction( $this->hasAttribute('name') ? $this->getAttribute('name') : $current->getName(), $this->hasAttribute('callable') ? $this->getAttribute('callable') : $current->getCallable(), @@ -344,7 +344,7 @@ private function getTwigCallable(): TwigCallableInterface 'needs_charset' => $this->hasAttribute('needs_charset') ? $this->getAttribute('needs_charset') : $current->needsCharset(), 'is_variadic' => $this->hasAttribute('is_variadic') ? $this->getAttribute('is_variadic') : $current->isVariadic(), ], - ))->withDynamicArguments($this->getAttribute('name'), $this->hasAttribute('dynamic_name') ? $this->getAttribute('dynamic_name') : $current->getDynamicName(), $this->hasAttribute('arguments') ?: $current->getArguments()), + ))->withDynamicArguments($this->getAttribute('name'), $this->hasAttribute('dynamic_name') ? $this->getAttribute('dynamic_name') : $current->getDynamicName(), $this->hasAttribute('arguments') ? $this->getAttribute('arguments') : $current->getArguments()), 'filter' => (new TwigFilter( $this->getAttribute('name'), $this->hasAttribute('callable') ? $this->getAttribute('callable') : $current->getCallable(), @@ -354,7 +354,7 @@ private function getTwigCallable(): TwigCallableInterface 'needs_charset' => $this->hasAttribute('needs_charset') ? $this->getAttribute('needs_charset') : $current->needsCharset(), 'is_variadic' => $this->hasAttribute('is_variadic') ? $this->getAttribute('is_variadic') : $current->isVariadic(), ], - ))->withDynamicArguments($this->getAttribute('name'), $this->hasAttribute('dynamic_name') ? $this->getAttribute('dynamic_name') : $current->getDynamicName(), $this->hasAttribute('arguments') ?: $current->getArguments()), + ))->withDynamicArguments($this->getAttribute('name'), $this->hasAttribute('dynamic_name') ? $this->getAttribute('dynamic_name') : $current->getDynamicName(), $this->hasAttribute('arguments') ? $this->getAttribute('arguments') : $current->getArguments()), }); return $this->getAttribute('twig_callable'); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php index 75b6d18c2..a3ee66e47 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php @@ -14,6 +14,8 @@ use Twig\Attribute\FirstClassTwigCallableReady; use Twig\Compiler; use Twig\Extension\CoreExtension; +use Twig\Node\EmptyNode; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ConditionalExpression; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Expression\FilterExpression; @@ -33,9 +35,16 @@ */ class DefaultFilter extends FilterExpression { + /** + * @param AbstractExpression $node + */ #[FirstClassTwigCallableReady] public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno) { + if (!$node instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($node)); + } + if ($filter instanceof TwigFilter) { $name = $filter->getName(); $default = new FilterExpression($node, $filter, $arguments, $node->getTemplateLine()); @@ -45,7 +54,7 @@ public function __construct(Node $node, TwigFilter|ConstantExpression $filter, N } if ('default' === $name && ($node instanceof NameExpression || $node instanceof GetAttrExpression)) { - $test = new DefinedTest(clone $node, new TwigTest('defined'), new Node(), $node->getTemplateLine()); + $test = new DefinedTest(clone $node, new TwigTest('defined'), new EmptyNode(), $node->getTemplateLine()); $false = \count($arguments) ? $arguments->getNode('0') : new ConstantExpression('', $node->getTemplateLine()); $node = new ConditionalExpression($test, $default, $false, $node->getTemplateLine()); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php index e115ab194..e70501e24 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Filter/RawFilter.php @@ -13,6 +13,8 @@ use Twig\Attribute\FirstClassTwigCallableReady; use Twig\Compiler; +use Twig\Node\EmptyNode; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Expression\FilterExpression; use Twig\Node\Node; @@ -23,10 +25,17 @@ */ class RawFilter extends FilterExpression { + /** + * @param AbstractExpression $node + */ #[FirstClassTwigCallableReady] public function __construct(Node $node, TwigFilter|ConstantExpression|null $filter = null, ?Node $arguments = null, int $lineno = 0) { - parent::__construct($node, $filter ?: new TwigFilter('raw', null, ['is_safe' => ['all']]), $arguments ?: new Node(), $lineno ?: $node->getTemplateLine()); + if (!$node instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($node)); + } + + parent::__construct($node, $filter ?: new TwigFilter('raw', null, ['is_safe' => ['all']]), $arguments ?: new EmptyNode(), $lineno ?: $node->getTemplateLine()); } public function compile(Compiler $compiler): void diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FilterExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FilterExpression.php index efc91193e..31fb90f1e 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FilterExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FilterExpression.php @@ -20,9 +20,16 @@ class FilterExpression extends CallExpression { + /** + * @param AbstractExpression $node + */ #[FirstClassTwigCallableReady] public function __construct(Node $node, TwigFilter|ConstantExpression $filter, Node $arguments, int $lineno) { + if (!$node instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($node)); + } + if ($filter instanceof TwigFilter) { $name = $filter->getName(); $filterName = new ConstantExpression($name, $lineno); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FunctionNode/EnumFunction.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FunctionNode/EnumFunction.php new file mode 100644 index 000000000..1f8b0ecf1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/FunctionNode/EnumFunction.php @@ -0,0 +1,45 @@ +getNode('arguments'); + if ($arguments->hasNode('enum')) { + $firstArgument = $arguments->getNode('enum'); + } elseif ($arguments->hasNode('0')) { + $firstArgument = $arguments->getNode('0'); + } else { + $firstArgument = null; + } + + if (!$firstArgument instanceof ConstantExpression || 1 !== \count($arguments)) { + parent::compile($compiler); + + return; + } + + $value = $firstArgument->getAttribute('value'); + + if (!\is_string($value)) { + throw new SyntaxError('The first argument of the "enum" function must be a string.', $this->getTemplateLine(), $this->getSourceContext()); + } + + if (!enum_exists($value)) { + throw new SyntaxError(\sprintf('The first argument of the "enum" function must be the name of an enum, "%s" given.', $value), $this->getTemplateLine(), $this->getSourceContext()); + } + + if (!$cases = $value::cases()) { + throw new SyntaxError(\sprintf('The first argument of the "enum" function must be a non-empty enum, "%s" given.', $value), $this->getTemplateLine(), $this->getSourceContext()); + } + + $compiler->raw(\sprintf('%s::%s', $value, $cases[0]->name)); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php index 2181b0f78..e7373de11 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php @@ -18,6 +18,10 @@ class GetAttrExpression extends AbstractExpression { + + /** + * @param ArrayExpression|NameExpression|null $arguments + */ public function __construct(AbstractExpression $node, AbstractExpression $attribute, ?AbstractExpression $arguments, string $type, int $lineno) { $nodes = ['node' => $node, 'attribute' => $attribute]; @@ -25,6 +29,10 @@ public function __construct(AbstractExpression $node, AbstractExpression $attrib $nodes['arguments'] = $arguments; } + if ($arguments && !$arguments instanceof ArrayExpression && !$arguments instanceof NameExpression) { + trigger_deprecation('twig/twig', '3.15', \sprintf('Not passing a "%s" instance as the "arguments" argument of the "%s" constructor is deprecated ("%s" given).', ArrayExpression::class, static::class, $arguments::class)); + } + parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'optimizable' => true], $lineno); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/InlinePrint.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/InlinePrint.php index 0a3c2e4f9..5509f7942 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/InlinePrint.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/InlinePrint.php @@ -19,8 +19,13 @@ */ final class InlinePrint extends AbstractExpression { + /** + * @param AbstractExpression $node + */ public function __construct(Node $node, int $lineno) { + trigger_deprecation('twig/twig', '3.16', \sprintf('The "%s" class is deprecated with no replacement.', static::class)); + parent::__construct(['node' => $node], [], $lineno); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MacroReferenceExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MacroReferenceExpression.php new file mode 100644 index 000000000..abe99aa35 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MacroReferenceExpression.php @@ -0,0 +1,56 @@ + + */ +class MacroReferenceExpression extends AbstractExpression +{ + public function __construct(TemplateVariable $template, string $name, AbstractExpression $arguments, int $lineno) + { + parent::__construct(['template' => $template, 'arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno); + } + + public function compile(Compiler $compiler): void + { + if ($this->getAttribute('is_defined_test')) { + $compiler + ->subcompile($this->getNode('template')) + ->raw('->hasMacro(') + ->repr($this->getAttribute('name')) + ->raw(', $context') + ->raw(')') + ; + + return; + } + + $compiler + ->subcompile($this->getNode('template')) + ->raw('->getTemplateForMacro(') + ->repr($this->getAttribute('name')) + ->raw(', $context, ') + ->repr($this->getTemplateLine()) + ->raw(', $this->getSourceContext())') + ->raw(\sprintf('->%s', $this->getAttribute('name'))) + ->raw('(...') + ->subcompile($this->getNode('arguments')) + ->raw(')') + ; + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php index 01806f91d..9aede826c 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php @@ -17,6 +17,8 @@ class MethodCallExpression extends AbstractExpression { public function __construct(AbstractExpression $node, string $method, ArrayExpression $arguments, int $lineno) { + trigger_deprecation('twig/twig', '3.15', 'The "%s" class is deprecated, use "%s" instead.', __CLASS__, MacroReferenceExpression::class); + parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false, 'is_defined_test' => false], $lineno); if ($node instanceof NameExpression) { @@ -43,21 +45,9 @@ public function compile(Compiler $compiler): void ->repr($this->getNode('node')->getAttribute('name')) ->raw('], ') ->repr($this->getAttribute('method')) - ->raw(', [') - ; - $first = true; - /** @var ArrayExpression */ - $args = $this->getNode('arguments'); - foreach ($args->getKeyValuePairs() as $pair) { - if (!$first) { - $compiler->raw(', '); - } - $first = false; - - $compiler->subcompile($pair['value']); - } - $compiler - ->raw('], ') + ->raw(', ') + ->subcompile($this->getNode('arguments')) + ->raw(', ') ->repr($this->getTemplateLine()) ->raw(', $context, $this->getSourceContext())'); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NameExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NameExpression.php index 286aa5ae2..78ae51f03 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NameExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NameExpression.php @@ -13,6 +13,7 @@ namespace Twig\Node\Expression; use Twig\Compiler; +use Twig\Node\Expression\Variable\ContextVariable; class NameExpression extends AbstractExpression { @@ -24,6 +25,10 @@ class NameExpression extends AbstractExpression public function __construct(string $name, int $lineno) { + if (self::class === static::class) { + trigger_deprecation('twig/twig', '3.15', 'The "%s" class is deprecated, use "%s" instead.', self::class, ContextVariable::class); + } + parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php index 98630f7f0..1a5d90286 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php @@ -12,6 +12,7 @@ namespace Twig\Node\Expression; use Twig\Compiler; +use Twig\Node\EmptyNode; use Twig\Node\Expression\Binary\AndBinary; use Twig\Node\Expression\Test\DefinedTest; use Twig\Node\Expression\Test\NullTest; @@ -21,14 +22,25 @@ class NullCoalesceExpression extends ConditionalExpression { + /** + * @param AbstractExpression $left + * @param AbstractExpression $right + */ public function __construct(Node $left, Node $right, int $lineno) { - $test = new DefinedTest(clone $left, new TwigTest('defined'), new Node(), $left->getTemplateLine()); + if (!$left instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "left" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($left)); + } + if (!$right instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "right" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($right)); + } + + $test = new DefinedTest(clone $left, new TwigTest('defined'), new EmptyNode(), $left->getTemplateLine()); // for "block()", we don't need the null test as the return value is always a string if (!$left instanceof BlockReferenceExpression) { $test = new AndBinary( $test, - new NotUnary(new NullTest($left, new TwigTest('null'), new Node(), $left->getTemplateLine()), $left->getTemplateLine()), + new NotUnary(new NullTest($left, new TwigTest('null'), new EmptyNode(), $left->getTemplateLine()), $left->getTemplateLine()), $left->getTemplateLine() ); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TempNameExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TempNameExpression.php index 004c704a5..925b0e7b3 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TempNameExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TempNameExpression.php @@ -12,20 +12,38 @@ namespace Twig\Node\Expression; use Twig\Compiler; +use Twig\Error\SyntaxError; class TempNameExpression extends AbstractExpression { - public function __construct(string $name, int $lineno) + public const RESERVED_NAMES = ['varargs', 'context', 'macros', 'blocks', 'this']; + + public function __construct(string|int|null $name, int $lineno) { + // All names supported by ExpressionParser::parsePrimaryExpression() should be excluded + if ($name && \in_array(strtolower($name), ['true', 'false', 'none', 'null'])) { + throw new SyntaxError(\sprintf('You cannot assign a value to "%s".', $name), $lineno); + } + + if (self::class === static::class) { + trigger_deprecation('twig/twig', '3.15', 'The "%s" class is deprecated.', self::class); + } + + if (null !== $name && (is_int($name) || ctype_digit($name))) { + $name = (int) $name; + } elseif (in_array($name, self::RESERVED_NAMES)) { + $name = "\u{035C}".$name; + } + parent::__construct([], ['name' => $name], $lineno); } public function compile(Compiler $compiler): void { - $compiler - ->raw('$_') - ->raw($this->getAttribute('name')) - ->raw('_') - ; + if (null === $this->getAttribute('name')) { + $this->setAttribute('name', $compiler->getVarName()); + } + + $compiler->raw('$'.$this->getAttribute('name')); } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php index 24d3ee82c..b6c3ff6f9 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php @@ -14,11 +14,13 @@ use Twig\Attribute\FirstClassTwigCallableReady; use Twig\Compiler; use Twig\Error\SyntaxError; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\BlockReferenceExpression; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Expression\FunctionExpression; use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\MacroReferenceExpression; use Twig\Node\Expression\MethodCallExpression; use Twig\Node\Expression\NameExpression; use Twig\Node\Expression\TestExpression; @@ -37,9 +39,16 @@ */ class DefinedTest extends TestExpression { + /** + * @param AbstractExpression $node + */ #[FirstClassTwigCallableReady] public function __construct(Node $node, TwigTest|string $name, ?Node $arguments, int $lineno) { + if (!$node instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($node)); + } + if ($node instanceof NameExpression) { $node->setAttribute('is_defined_test', true); } elseif ($node instanceof GetAttrExpression) { @@ -47,6 +56,8 @@ public function __construct(Node $node, TwigTest|string $name, ?Node $arguments, $this->changeIgnoreStrictCheck($node); } elseif ($node instanceof BlockReferenceExpression) { $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof MacroReferenceExpression) { + $node->setAttribute('is_defined_test', true); } elseif ($node instanceof FunctionExpression && 'constant' === $node->getAttribute('name')) { $node->setAttribute('is_defined_test', true); } elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TestExpression.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TestExpression.php index 080d85aaa..3ad6ac557 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TestExpression.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/TestExpression.php @@ -20,8 +20,15 @@ class TestExpression extends CallExpression { #[FirstClassTwigCallableReady] + /** + * @param AbstractExpression $node + */ public function __construct(Node $node, string|TwigTest $test, ?Node $arguments, int $lineno) { + if (!$node instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($node)); + } + $nodes = ['node' => $node]; if (null !== $arguments) { $nodes['arguments'] = $arguments; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php index e31e3f84b..96739e2b8 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php @@ -18,16 +18,30 @@ abstract class AbstractUnary extends AbstractExpression { + /** + * @param AbstractExpression $node + */ public function __construct(Node $node, int $lineno) { - parent::__construct(['node' => $node], [], $lineno); + if (!$node instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance argument to "%s" is deprecated ("%s" given).', AbstractExpression::class, static::class, get_class($node)); + } + + parent::__construct(['node' => $node], ['with_parentheses' => false], $lineno); } public function compile(Compiler $compiler): void { - $compiler->raw(' '); + if ($this->hasExplicitParentheses()) { + $compiler->raw('('); + } else { + $compiler->raw(' '); + } $this->operator($compiler); $compiler->subcompile($this->getNode('node')); + if ($this->hasExplicitParentheses()) { + $compiler->raw(')'); + } } abstract public function operator(Compiler $compiler): Compiler; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/SpreadUnary.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/SpreadUnary.php new file mode 100644 index 000000000..f99072c25 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/SpreadUnary.php @@ -0,0 +1,22 @@ +raw('...'); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/StringCastUnary.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/StringCastUnary.php new file mode 100644 index 000000000..87ea17ca8 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Unary/StringCastUnary.php @@ -0,0 +1,22 @@ +raw('(string)'); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/AssignContextVariable.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/AssignContextVariable.php new file mode 100644 index 000000000..30d810675 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/AssignContextVariable.php @@ -0,0 +1,18 @@ + $var], ['global' => $global], $var->getTemplateLine()); + } + + public function compile(Compiler $compiler): void + { + /** @var TemplateVariable $var */ + $var = $this->nodes['var']; + + $compiler + ->addDebugInfo($this) + ->write('$macros[') + ->string($var->getName($compiler)) + ->raw('] = ') + ; + + if ($this->getAttribute('global')) { + $compiler + ->raw('$this->macros[') + ->string($var->getName($compiler)) + ->raw('] = ') + ; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/ContextVariable.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/ContextVariable.php new file mode 100644 index 000000000..cabc16a43 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Expression/Variable/ContextVariable.php @@ -0,0 +1,18 @@ +getAttribute('name')) { + $this->setAttribute('name', $compiler->getVarName()); + } + + return $this->getAttribute('name'); + } + + public function compile(Compiler $compiler): void + { + $name = $this->getName($compiler); + + if ('_self' === $name) { + $compiler->raw('$this'); + } else { + $compiler + ->raw('$macros[') + ->string($name) + ->raw(']') + ; + } + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ForNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ForNode.php index 2fc014792..53a950a90 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ForNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ForNode.php @@ -29,7 +29,7 @@ class ForNode extends Node public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, ?Node $ifexpr, Node $body, ?Node $else, int $lineno) { - $body = new Node([$body, $this->loop = new ForLoopNode($lineno)]); + $body = new Nodes([$body, $this->loop = new ForLoopNode($lineno)]); $nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body]; if (null !== $else) { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ImportNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ImportNode.php index 9a6033f21..124c41ba9 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ImportNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ImportNode.php @@ -15,6 +15,7 @@ use Twig\Compiler; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\Variable\AssignTemplateVariable; /** * Represents an import node. @@ -24,37 +25,24 @@ #[YieldReady] class ImportNode extends Node { - /** - * @param bool $global - */ - public function __construct(AbstractExpression $expr, AbstractExpression $var, int $lineno, $global = true) + public function __construct(AbstractExpression $expr, AbstractExpression|AssignTemplateVariable $var, int $lineno) { - if (null === $global || \is_string($global)) { - trigger_deprecation('twig/twig', '3.12', 'Passing a tag to %s() is deprecated.', __METHOD__); - $global = \func_num_args() > 4 ? func_get_arg(4) : true; - } elseif (!\is_bool($global)) { - throw new \TypeError(\sprintf('Argument 4 passed to "%s()" must be a boolean, "%s" given.', __METHOD__, get_debug_type($global))); + if (\func_num_args() > 3) { + trigger_deprecation('twig/twig', '3.15', \sprintf('Passing more than 3 arguments to "%s()" is deprecated.', __METHOD__)); } - parent::__construct(['expr' => $expr, 'var' => $var], ['global' => $global], $lineno); + if (!$var instanceof AssignTemplateVariable) { + trigger_deprecation('twig/twig', '3.15', \sprintf('Passing a "%s" instance as the second argument of "%s" is deprecated, pass a "%s" instead.', $var::class, __CLASS__, AssignTemplateVariable::class)); + + $var = new AssignTemplateVariable($var->getAttribute('name'), $lineno); + } + + parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno); } public function compile(Compiler $compiler): void { - $compiler - ->addDebugInfo($this) - ->write('$macros[') - ->repr($this->getNode('var')->getAttribute('name')) - ->raw('] = ') - ; - - if ($this->getAttribute('global')) { - $compiler - ->raw('$this->macros[') - ->repr($this->getNode('var')->getAttribute('name')) - ->raw('] = ') - ; - } + $compiler->subcompile($this->getNode('var')); if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) { $compiler->raw('$this'); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/IncludeNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/IncludeNode.php index 1c18292c5..5e0c6deb0 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/IncludeNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/IncludeNode.php @@ -42,13 +42,12 @@ public function compile(Compiler $compiler): void $template = $compiler->getVarName(); $compiler - ->write(\sprintf("$%s = null;\n", $template)) ->write("try {\n") ->indent() ->write(\sprintf('$%s = ', $template)) ; - $this->addGetTemplate($compiler); + $this->addGetTemplate($compiler, $template); $compiler ->raw(";\n") @@ -56,6 +55,7 @@ public function compile(Compiler $compiler): void ->write("} catch (LoaderError \$e) {\n") ->indent() ->write("// ignore missing template\n") + ->write(\sprintf("\$$template = null;\n", $template)) ->outdent() ->write("}\n") ->write(\sprintf("if ($%s) {\n", $template)) @@ -78,10 +78,10 @@ public function compile(Compiler $compiler): void } } - protected function addGetTemplate(Compiler $compiler) + protected function addGetTemplate(Compiler $compiler/* , string $template = '' */) { $compiler - ->write('$this->loadTemplate(') + ->raw('$this->loadTemplate(') ->subcompile($this->getNode('expr')) ->raw(', ') ->repr($this->getTemplateName()) diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/MacroNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/MacroNode.php index 5a2543a9f..ab37d85a5 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/MacroNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/MacroNode.php @@ -14,6 +14,8 @@ use Twig\Attribute\YieldReady; use Twig\Compiler; use Twig\Error\SyntaxError; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\Variable\LocalVariable; /** * Represents a macro node. @@ -26,17 +28,28 @@ class MacroNode extends Node public const VARARGS_NAME = 'varargs'; /** - * @param BodyNode $body + * @param BodyNode $body + * @param ArrayExpression $arguments */ public function __construct(string $name, Node $body, Node $arguments, int $lineno) { if (!$body instanceof BodyNode) { - trigger_deprecation('twig/twig', '3.12', \sprintf('Not passing a "%s" instance as the "body" argument of the "%s" constructor is deprecated.', BodyNode::class, static::class)); + trigger_deprecation('twig/twig', '3.12', \sprintf('Not passing a "%s" instance as the "body" argument of the "%s" constructor is deprecated ("%s" given).', BodyNode::class, static::class, $body::class)); } - foreach ($arguments as $argumentName => $argument) { - if (self::VARARGS_NAME === $argumentName) { - throw new SyntaxError(\sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine(), $argument->getSourceContext()); + if (!$arguments instanceof ArrayExpression) { + trigger_deprecation('twig/twig', '3.15', \sprintf('Not passing a "%s" instance as the "arguments" argument of the "%s" constructor is deprecated ("%s" given).', ArrayExpression::class, static::class, $arguments::class)); + + $args = new ArrayExpression([], $arguments->getTemplateLine()); + foreach ($arguments as $name => $default) { + $args->addElement($default, new LocalVariable($name, $default->getTemplateLine())); + } + $arguments = $args; + } + + foreach ($arguments->getKeyValuePairs() as $pair) { + if ("\u{035C}".self::VARARGS_NAME === $pair['key']->getAttribute('name')) { + throw new SyntaxError(\sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $pair['value']->getTemplateLine(), $pair['value']->getSourceContext()); } } @@ -50,26 +63,22 @@ public function compile(Compiler $compiler): void ->write(\sprintf('public function macro_%s(', $this->getAttribute('name'))) ; - $count = \count($this->getNode('arguments')); - $pos = 0; - foreach ($this->getNode('arguments') as $name => $default) { + /** @var ArrayExpression $arguments */ + $arguments = $this->getNode('arguments'); + foreach ($arguments->getKeyValuePairs() as $pair) { + $name = $pair['key']; + $default = $pair['value']; $compiler - ->raw('$__'.$name.'__ = ') + ->subcompile($name) + ->raw(' = ') ->subcompile($default) + ->raw(', ') ; - - if (++$pos < $count) { - $compiler->raw(', '); - } - } - - if ($count) { - $compiler->raw(', '); } $compiler - ->raw('...$__varargs__') - ->raw(")\n") + ->raw('...$varargs') + ->raw("): string|Markup\n") ->write("{\n") ->indent() ->write("\$macros = \$this->macros;\n") @@ -77,11 +86,17 @@ public function compile(Compiler $compiler): void ->indent() ; - foreach ($this->getNode('arguments') as $name => $default) { + foreach ($arguments->getKeyValuePairs() as $pair) { + $name = $pair['key']; + $var = $name->getAttribute('name'); + if (str_starts_with($var, "\u{035C}")) { + $var = substr($var, \strlen("\u{035C}")); + } $compiler ->write('') - ->string($name) - ->raw(' => $__'.$name.'__') + ->string($var) + ->raw(' => ') + ->subcompile($name) ->raw(",\n") ; } @@ -92,7 +107,7 @@ public function compile(Compiler $compiler): void ->write('') ->string(self::VARARGS_NAME) ->raw(' => ') - ->raw("\$__varargs__,\n") + ->raw("\$varargs,\n") ->outdent() ->write("] + \$this->env->getGlobals();\n\n") ->write("\$blocks = [];\n\n") diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ModuleNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ModuleNode.php index d2fb216b1..97c2089fd 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ModuleNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/ModuleNode.php @@ -44,11 +44,11 @@ public function __construct(Node $body, ?AbstractExpression $parent, Node $block 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits, - 'display_start' => new Node(), - 'display_end' => new Node(), - 'constructor_start' => new Node(), - 'constructor_end' => new Node(), - 'class_end' => new Node(), + 'display_start' => new Nodes(), + 'display_end' => new Nodes(), + 'constructor_start' => new Nodes(), + 'constructor_end' => new Nodes(), + 'class_end' => new Nodes(), ]; if (null !== $parent) { $nodes['parent'] = $parent; @@ -244,7 +244,11 @@ protected function compileConstructor(Compiler $compiler) ->string($key) ->raw(\sprintf(']; unset($_trait_%s_blocks[', $i)) ->string($key) - ->raw("]);\n\n") + ->raw("]); \$this->traitAliases[") + ->subcompile($value) + ->raw("] = ") + ->string($key) + ->raw(";\n\n") ; } } @@ -410,7 +414,7 @@ protected function compileIsTraitable(Compiler $compiler) } if (!\count($nodes)) { - $nodes = new Node([$nodes]); + $nodes = new Nodes([$nodes]); } foreach ($nodes as $node) { diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Node.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Node.php index 2ccbcf610..7b4044c3f 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Node.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Node.php @@ -20,6 +20,8 @@ * Represents a node in the AST. * * @author Fabien Potencier + * + * @implements \IteratorAggregate */ #[YieldReady] class Node implements \Countable, \IteratorAggregate @@ -45,9 +47,13 @@ class Node implements \Countable, \IteratorAggregate */ public function __construct(array $nodes = [], array $attributes = [], int $lineno = 0) { + if (self::class === static::class) { + trigger_deprecation('twig/twig', '3.15', \sprintf('Instantiating "%s" directly is deprecated; the class will become abstract in 4.0.', self::class)); + } + foreach ($nodes as $name => $node) { if (!$node instanceof self) { - throw new \InvalidArgumentException(\sprintf('Using "%s" for the value of node "%s" of "%s" is not supported. You must pass a \Twig\Node\Node instance.', \is_object($node) ? $node::class : (null === $node ? 'null' : \gettype($node)), $name, static::class)); + throw new \InvalidArgumentException(\sprintf('Using "%s" for the value of node "%s" of "%s" is not supported. You must pass a \Twig\Node\Node instance.', get_debug_type($node), $name, static::class)); } } $this->nodes = $nodes; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Nodes.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Nodes.php new file mode 100644 index 000000000..bd67053ab --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/Nodes.php @@ -0,0 +1,28 @@ + + */ +#[YieldReady] +final class Nodes extends Node +{ + public function __construct(array $nodes = [], int $lineno = 0) + { + parent::__construct($nodes, [], $lineno); + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/SetNode.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/SetNode.php index 67725104e..6e0661edb 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Node/SetNode.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Node/SetNode.php @@ -33,9 +33,16 @@ public function __construct(bool $capture, Node $names, Node $values, int $linen $safe = false; if ($capture) { $safe = true; - if ($values instanceof TextNode) { + // Node::class === get_class($values) should be removed in Twig 4.0 + if (($values instanceof Nodes || Node::class === get_class($values)) && !count($values)) { + $values = new ConstantExpression('', $values->getTemplateLine()); + $capture = false; + } elseif ($values instanceof TextNode) { $values = new ConstantExpression($values->getAttribute('data'), $values->getTemplateLine()); $capture = false; + } elseif ($values instanceof PrintNode && $values->getNode('expr') instanceof ConstantExpression) { + $values = $values->getNode('expr'); + $capture = false; } else { $values = new CaptureNode($values, $values->getTemplateLine()); } @@ -78,11 +85,23 @@ public function compile(Compiler $compiler): void $compiler->raw(']'); } else { if ($this->getAttribute('safe')) { - $compiler - ->raw("('' === \$tmp = ") - ->subcompile($this->getNode('values')) - ->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())") - ; + if ($this->getNode('values') instanceof ConstantExpression) { + if ('' === $this->getNode('values')->getAttribute('value')) { + $compiler->raw('""'); + } else { + $compiler + ->raw('new Markup(') + ->subcompile($this->getNode('values')) + ->raw(', $this->env->getCharset())') + ; + } + } else { + $compiler + ->raw("('' === \$tmp = ") + ->subcompile($this->getNode('values')) + ->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())") + ; + } } else { $compiler->subcompile($this->getNode('values')); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php index 32f49ab1e..9640c541b 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php @@ -16,14 +16,14 @@ use Twig\Node\AutoEscapeNode; use Twig\Node\BlockNode; use Twig\Node\BlockReferenceNode; -use Twig\Node\DoNode; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ConditionalExpression; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Expression\FilterExpression; -use Twig\Node\Expression\InlinePrint; use Twig\Node\ImportNode; use Twig\Node\ModuleNode; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\Node\PrintNode; use Twig\NodeTraverser; @@ -59,7 +59,7 @@ public function enterNode(Node $node, Environment $env): Node } elseif ($node instanceof BlockNode) { $this->statusStack[] = $this->blocks[$node->getAttribute('name')] ?? $this->needEscaping(); } elseif ($node instanceof ImportNode) { - $this->safeVars[] = $node->getNode('var')->getAttribute('name'); + $this->safeVars[] = $node->getNode('var')->getNode('var')->getAttribute('name'); } return $node; @@ -75,11 +75,13 @@ public function leaveNode(Node $node, Environment $env): ?Node return $this->preEscapeFilterNode($node, $env); } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping()) { $expression = $node->getNode('expr'); - if ($expression instanceof ConditionalExpression && $this->shouldUnwrapConditional($expression, $env, $type)) { - return new DoNode($this->unwrapConditional($expression, $env, $type), $expression->getTemplateLine()); + if ($expression instanceof ConditionalExpression) { + $this->escapeConditional($expression, $env, $type); + } else { + $node->setNode('expr', $this->escapeExpression($expression, $env, $type)); } - return $this->escapePrintNode($node, $env, $type); + return $node; } if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) { @@ -91,55 +93,28 @@ public function leaveNode(Node $node, Environment $env): ?Node return $node; } - private function shouldUnwrapConditional(ConditionalExpression $expression, Environment $env, string $type): bool - { - $expr2Safe = $this->isSafeFor($type, $expression->getNode('expr2'), $env); - $expr3Safe = $this->isSafeFor($type, $expression->getNode('expr3'), $env); - - return $expr2Safe !== $expr3Safe; - } - - private function unwrapConditional(ConditionalExpression $expression, Environment $env, string $type): ConditionalExpression + private function escapeConditional(ConditionalExpression $expression, Environment $env, string $type): void { - // convert "echo a ? b : c" to "a ? echo b : echo c" recursively + /** @var AbstractExpression $expr2 */ $expr2 = $expression->getNode('expr2'); - if ($expr2 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr2, $env, $type)) { - $expr2 = $this->unwrapConditional($expr2, $env, $type); + if ($expr2 instanceof ConditionalExpression) { + $this->escapeConditional($expr2, $env, $type); } else { - $expr2 = $this->escapeInlinePrintNode(new InlinePrint($expr2, $expr2->getTemplateLine()), $env, $type); + $expression->setNode('expr2', $this->escapeExpression($expr2, $env, $type)); } + + /** @var AbstractExpression $expr3 */ $expr3 = $expression->getNode('expr3'); - if ($expr3 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr3, $env, $type)) { - $expr3 = $this->unwrapConditional($expr3, $env, $type); + if ($expr3 instanceof ConditionalExpression) { + $this->escapeConditional($expr3, $env, $type); } else { - $expr3 = $this->escapeInlinePrintNode(new InlinePrint($expr3, $expr3->getTemplateLine()), $env, $type); + $expression->setNode('expr3', $this->escapeExpression($expr3, $env, $type)); } - - return new ConditionalExpression($expression->getNode('expr1'), $expr2, $expr3, $expression->getTemplateLine()); } - private function escapeInlinePrintNode(InlinePrint $node, Environment $env, string $type): Node + private function escapeExpression(AbstractExpression $expression, Environment $env, string $type): AbstractExpression { - $expression = $node->getNode('node'); - - if ($this->isSafeFor($type, $expression, $env)) { - return $node; - } - - return new InlinePrint($this->getEscaperFilter($env, $type, $expression), $node->getTemplateLine()); - } - - private function escapePrintNode(PrintNode $node, Environment $env, string $type): Node - { - $expression = $node->getNode('expr'); - - if ($this->isSafeFor($type, $expression, $env)) { - return $node; - } - - $class = \get_class($node); - - return new $class($this->getEscaperFilter($env, $type, $expression), $node->getTemplateLine()); + return $this->isSafeFor($type, $expression, $env) ? $expression : $this->getEscaperFilter($env, $type, $expression); } private function preEscapeFilterNode(FilterExpression $filter, Environment $env): FilterExpression @@ -156,6 +131,7 @@ private function preEscapeFilterNode(FilterExpression $filter, Environment $env) return $filter; } + /** @var AbstractExpression $node */ $node = $filter->getNode('node'); if ($this->isSafeFor($type, $node, $env)) { return $filter; @@ -166,11 +142,11 @@ private function preEscapeFilterNode(FilterExpression $filter, Environment $env) return $filter; } - private function isSafeFor(string $type, Node $expression, Environment $env): bool + private function isSafeFor(string $type, AbstractExpression $expression, Environment $env): bool { $safe = $this->safeAnalysis->getSafe($expression); - if (null === $safe) { + if (!$safe) { if (null === $this->traverser) { $this->traverser = new NodeTraverser($env, [$this->safeAnalysis]); } @@ -193,11 +169,11 @@ private function needEscaping() return $this->defaultStrategy ?: false; } - private function getEscaperFilter(Environment $env, string $type, Node $node): FilterExpression + private function getEscaperFilter(Environment $env, string $type, AbstractExpression $node): FilterExpression { $line = $node->getTemplateLine(); $filter = $env->getFilter('escape'); - $args = new Node([new ConstantExpression($type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]); + $args = new Nodes([new ConstantExpression($type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]); return new FilterExpression($node, $filter, $args, $line); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php deleted file mode 100644 index 01d5a997f..000000000 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/MacroAutoImportNodeVisitor.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * @internal - */ -final class MacroAutoImportNodeVisitor implements NodeVisitorInterface -{ - private $inAModule = false; - private $hasMacroCalls = false; - - public function enterNode(Node $node, Environment $env): Node - { - if ($node instanceof ModuleNode) { - $this->inAModule = true; - $this->hasMacroCalls = false; - } - - return $node; - } - - public function leaveNode(Node $node, Environment $env): Node - { - if ($node instanceof ModuleNode) { - $this->inAModule = false; - if ($this->hasMacroCalls) { - $node->getNode('constructor_end')->setNode('_auto_macro_import', new ImportNode(new NameExpression('_self', 0), new AssignNameExpression('_self', 0), 0, true)); - } - } elseif ($this->inAModule) { - if ( - $node instanceof GetAttrExpression - && $node->getNode('node') instanceof NameExpression - && '_self' === $node->getNode('node')->getAttribute('name') - && $node->getNode('attribute') instanceof ConstantExpression - ) { - $this->hasMacroCalls = true; - - $name = $node->getNode('attribute')->getAttribute('value'); - $node = new MethodCallExpression($node->getNode('node'), 'macro_'.$name, $node->getNode('arguments'), $node->getTemplateLine()); - $node->setAttribute('safe', true); - } - } - - return $node; - } - - public function getPriority(): int - { - // we must be ran before auto-escaping - return -10; - } -} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php index 07672164e..9eda8c8e1 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php @@ -18,6 +18,7 @@ use Twig\Node\Expression\FilterExpression; use Twig\Node\Expression\FunctionExpression; use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\MacroReferenceExpression; use Twig\Node\Expression\MethodCallExpression; use Twig\Node\Expression\NameExpression; use Twig\Node\Expression\ParentExpression; @@ -36,11 +37,14 @@ public function setSafeVars(array $safeVars): void $this->safeVars = $safeVars; } + /** + * @return array + */ public function getSafe(Node $node) { $hash = spl_object_hash($node); if (!isset($this->data[$hash])) { - return; + return []; } foreach ($this->data[$hash] as $bucket) { @@ -54,6 +58,8 @@ public function getSafe(Node $node) return $bucket['value']; } + + return []; } private function setSafe(Node $node, array $safe): void @@ -106,11 +112,14 @@ public function leaveNode(Node $node, Environment $env): ?Node if ($filter) { $safe = $filter->getSafe($node->getNode('arguments')); if (null === $safe) { + trigger_deprecation('twig/twig', '3.16', 'The "%s::getSafe()" method should not return "null" anymore, return "[]" instead.', $filter::class); + $safe = []; + } + + if (!$safe) { $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety()); } $this->setSafe($node, $safe); - } else { - $this->setSafe($node, []); } } elseif ($node instanceof FunctionExpression) { // function expression is safe when the function is safe @@ -122,33 +131,29 @@ public function leaveNode(Node $node, Environment $env): ?Node } if ($function) { - $this->setSafe($node, $function->getSafe($node->getNode('arguments'))); - } else { - $this->setSafe($node, []); - } - } elseif ($node instanceof MethodCallExpression) { - if ($node->getAttribute('safe')) { - $this->setSafe($node, ['all']); - } else { - $this->setSafe($node, []); + $safe = $function->getSafe($node->getNode('arguments')); + if (null === $safe) { + trigger_deprecation('twig/twig', '3.16', 'The "%s::getSafe()" method should not return "null" anymore, return "[]" instead.', $function::class); + $safe = []; + } + $this->setSafe($node, $safe); } + } elseif ($node instanceof MethodCallExpression || $node instanceof MacroReferenceExpression) { + // all macro calls are safe + $this->setSafe($node, ['all']); } elseif ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression) { $name = $node->getNode('node')->getAttribute('name'); if (\in_array($name, $this->safeVars)) { $this->setSafe($node, ['all']); - } else { - $this->setSafe($node, []); } - } else { - $this->setSafe($node, []); } return $node; } - private function intersectSafe(?array $a = null, ?array $b = null): array + private function intersectSafe(array $a, array $b): array { - if (null === $a || null === $b) { + if (!$a || !$b) { return []; } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php index 8c15db0d6..74b686f6e 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php @@ -25,6 +25,7 @@ use Twig\Node\Expression\Unary\SpreadUnary; use Twig\Node\ModuleNode; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\Node\PrintNode; use Twig\Node\SetNode; @@ -107,8 +108,8 @@ public function leaveNode(Node $node, Environment $env): ?Node if ($node instanceof ModuleNode) { $this->inAModule = false; - $node->setNode('constructor_end', new Node([new CheckSecurityCallNode(), $node->getNode('constructor_end')])); - $node->setNode('class_end', new Node([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('class_end')])); + $node->setNode('constructor_end', new Nodes([new CheckSecurityCallNode(), $node->getNode('constructor_end')])); + $node->setNode('class_end', new Nodes([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('class_end')])); } elseif ($this->inAModule) { if ($node instanceof PrintNode || $node instanceof SetNode) { $this->needsToStringWrap = false; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php index 4b190b414..3c9786275 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/NodeVisitor/YieldNotReadyNodeVisitor.php @@ -38,10 +38,10 @@ public function enterNode(Node $node, Environment $env): Node if (!$this->yieldReadyNodes[$class] = (bool) (new \ReflectionClass($class))->getAttributes(YieldReady::class)) { if ($this->useYield) { - throw new \LogicException(\sprintf('You cannot enable the "use_yield" option of Twig as node "%s" is not marked as ready for it; please make it ready and then flag it with the #[YieldReady] attribute.', $class)); + throw new \LogicException(\sprintf('You cannot enable the "use_yield" option of Twig as node "%s" is not marked as ready for it; please make it ready and then flag it with the #[\Twig\Attribute\YieldReady] attribute.', $class)); } - trigger_deprecation('twig/twig', '3.9', 'Twig node "%s" is not marked as ready for using "yield" instead of "echo"; please make it ready and then flag it with the #[YieldReady] attribute.', $class); + trigger_deprecation('twig/twig', '3.9', 'Twig node "%s" is not marked as ready for using "yield" instead of "echo"; please make it ready and then flag it with the #[\Twig\Attribute\YieldReady] attribute.', $class); } return $node; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/OperatorPrecedenceChange.php b/.extlib/simplesamlphp/vendor/twig/twig/src/OperatorPrecedenceChange.php new file mode 100644 index 000000000..1d9edefd1 --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/OperatorPrecedenceChange.php @@ -0,0 +1,42 @@ + + */ +class OperatorPrecedenceChange +{ + public function __construct( + private string $package, + private string $version, + private int $newPrecedence, + ) { + } + + public function getPackage(): string + { + return $this->package; + } + + public function getVersion(): string + { + return $this->version; + } + + public function getNewPrecedence(): int + { + return $this->newPrecedence; + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Parser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Parser.php index 40370bb1b..7bf51b73c 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Parser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Parser.php @@ -16,12 +16,16 @@ use Twig\Node\BlockNode; use Twig\Node\BlockReferenceNode; use Twig\Node\BodyNode; +use Twig\Node\EmptyNode; use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\Variable\AssignTemplateVariable; +use Twig\Node\Expression\Variable\TemplateVariable; use Twig\Node\MacroNode; use Twig\Node\ModuleNode; use Twig\Node\Node; use Twig\Node\NodeCaptureInterface; use Twig\Node\NodeOutputInterface; +use Twig\Node\Nodes; use Twig\Node\PrintNode; use Twig\Node\TextNode; use Twig\TokenParser\TokenParserInterface; @@ -44,14 +48,22 @@ class Parser private $traits; private $embeddedTemplates = []; private $varNameSalt = 0; + private $ignoreUnknownTwigCallables = false; public function __construct( private Environment $env, ) { } + public function getEnvironment(): Environment + { + return $this->env; + } + public function getVarName(): string { + trigger_deprecation('twig/twig', '3.15', 'The "%s()" method is deprecated.', __METHOD__); + return \sprintf('__internal_parse_%d', $this->varNameSalt++); } @@ -83,7 +95,7 @@ public function parse(TokenStream $stream, $test = null, bool $dropNeedle = fals $body = $this->subparse($test, $dropNeedle); if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) { - $body = new Node(); + $body = new EmptyNode(); } } catch (SyntaxError $e) { if (!$e->getSourceContext()) { @@ -97,7 +109,7 @@ public function parse(TokenStream $stream, $test = null, bool $dropNeedle = fals throw $e; } - $node = new ModuleNode(new BodyNode([$body]), $this->parent, new Node($this->blocks), new Node($this->macros), new Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); + $node = new ModuleNode(new BodyNode([$body]), $this->parent, new Nodes($this->blocks), new Nodes($this->macros), new Nodes($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); $traverser = new NodeTraverser($this->env, $this->visitors); @@ -114,6 +126,22 @@ public function parse(TokenStream $stream, $test = null, bool $dropNeedle = fals return $node; } + public function shouldIgnoreUnknownTwigCallables(): bool + { + return $this->ignoreUnknownTwigCallables; + } + + public function subparseIgnoreUnknownTwigCallables($test, bool $dropNeedle = false): void + { + $previous = $this->ignoreUnknownTwigCallables; + $this->ignoreUnknownTwigCallables = true; + try { + $this->subparse($test, $dropNeedle); + } finally { + $this->ignoreUnknownTwigCallables = $previous; + } + } + public function subparse($test, bool $dropNeedle = false): Node { $lineno = $this->getCurrentToken()->getLine(); @@ -149,7 +177,7 @@ public function subparse($test, bool $dropNeedle = false): Node return $rv[0]; } - return new Node($rv, [], $lineno); + return new Nodes($rv, $lineno); } if (!$subparser = $this->env->getTokenParser($token->getValue())) { @@ -189,7 +217,7 @@ public function subparse($test, bool $dropNeedle = false): Node return $rv[0]; } - return new Node($rv, [], $lineno); + return new Nodes($rv, $lineno); } public function getBlockStack(): array @@ -268,9 +296,15 @@ public function embedTemplate(ModuleNode $template) $this->embeddedTemplates[] = $template; } - public function addImportedSymbol(string $type, string $alias, ?string $name = null, ?AbstractExpression $node = null): void + public function addImportedSymbol(string $type, string $alias, ?string $name = null, AbstractExpression|AssignTemplateVariable|null $internalRef = null): void { - $this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node]; + if ($internalRef && !$internalRef instanceof AssignTemplateVariable) { + trigger_deprecation('twig/twig', '3.15', 'Not passing a "%s" instance as an internal reference is deprecated ("%s" given).', __METHOD__, AssignTemplateVariable::class, $internalRef::class); + + $internalRef = new AssignTemplateVariable(new TemplateVariable($internalRef->getAttribute('name'), $internalRef->getTemplateLine()), $internalRef->getAttribute('global')); + } + + $this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $internalRef]; } public function getImportedSymbol(string $type, string $alias) @@ -371,7 +405,8 @@ private function filterBodyNodes(Node $node, bool $nested = false): ?Node // here, $nested means "being at the root level of a child template" // we need to discard the wrapping "Node" for the "body" node - $nested = $nested || Node::class !== \get_class($node); + // Node::class !== \get_class($node) should be removed in Twig 4.0 + $nested = $nested || (Node::class !== \get_class($node) && !$node instanceof Nodes); foreach ($node as $k => $n) { if (null !== $n && null === $this->filterBodyNodes($n, $nested)) { $node->removeNode($k); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php index 1458bc5fc..4c5c2005d 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php @@ -17,6 +17,7 @@ use Twig\Node\MacroNode; use Twig\Node\ModuleNode; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\NodeVisitor\NodeVisitorInterface; use Twig\Profiler\Node\EnterProfileNode; use Twig\Profiler\Node\LeaveProfileNode; @@ -43,8 +44,8 @@ public function enterNode(Node $node, Environment $env): Node public function leaveNode(Node $node, Environment $env): ?Node { if ($node instanceof ModuleNode) { - $node->setNode('display_start', new Node([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $this->varName), $node->getNode('display_start')])); - $node->setNode('display_end', new Node([new LeaveProfileNode($this->varName), $node->getNode('display_end')])); + $node->setNode('display_start', new Nodes([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $this->varName), $node->getNode('display_start')])); + $node->setNode('display_end', new Nodes([new LeaveProfileNode($this->varName), $node->getNode('display_end')])); } elseif ($node instanceof BlockNode) { $node->setNode('body', new BodyNode([ new EnterProfileNode($this->extensionName, Profile::BLOCK, $node->getAttribute('name'), $this->varName), diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/Profile.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/Profile.php index 2928e1646..a3c6ee02e 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/Profile.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Profiler/Profile.php @@ -99,6 +99,22 @@ public function getDuration(): float return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0; } + /** + * Returns the start time in microseconds. + */ + public function getStartTime(): float + { + return $this->starts['wt'] ?? 0.0; + } + + /** + * Returns the end time in microseconds. + */ + public function getEndTime(): float + { + return $this->ends['wt'] ?? 0.0; + } + /** * Returns the memory usage in bytes. */ diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Resources/core.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Resources/core.php index 6e2fcfb07..bc0b27104 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Resources/core.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Resources/core.php @@ -537,5 +537,5 @@ function twig_check_arrow_in_sandbox(Environment $env, $arrow, $thing, $type) { trigger_deprecation('twig/twig', '3.9', 'Using the internal "%s" function is deprecated.', __FUNCTION__); - return CoreExtension::checkArrowInSandbox($env, $arrow, $thing, $type); + CoreExtension::checkArrow($env, $arrow, $thing, $type); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Runtime/EscaperRuntime.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Runtime/EscaperRuntime.php index a3ce17146..ce41e0a8b 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Runtime/EscaperRuntime.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Runtime/EscaperRuntime.php @@ -52,6 +52,9 @@ public function getEscapers() return $this->escapers; } + /** + * @param array, string[]> $safeClasses + */ public function setSafeClasses(array $safeClasses = []) { $this->safeClasses = []; @@ -61,6 +64,10 @@ public function setSafeClasses(array $safeClasses = []) } } + /** + * @param class-string<\Stringable> $class + * @param string[] $strategies + */ public function addSafeClass(string $class, array $strategies) { $class = ltrim($class, '\\'); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Sandbox/SecurityPolicy.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Sandbox/SecurityPolicy.php index 988e37216..b0d054260 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Sandbox/SecurityPolicy.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Sandbox/SecurityPolicy.php @@ -50,7 +50,7 @@ public function setAllowedMethods(array $methods): void { $this->allowedMethods = []; foreach ($methods as $class => $m) { - $this->allowedMethods[$class] = array_map(function ($value) { return strtr($value, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); }, \is_array($m) ? $m : [$m]); + $this->allowedMethods[$class] = array_map('strtolower', \is_array($m) ? $m : [$m]); } } @@ -98,7 +98,7 @@ public function checkMethodAllowed($obj, $method): void } $allowed = false; - $method = strtr($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + $method = strtolower($method); foreach ($this->allowedMethods as $class => $methods) { if ($obj instanceof $class && \in_array($method, $methods)) { $allowed = true; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Template.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Template.php index 7b3ce8161..26f5b5d81 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Template.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Template.php @@ -13,7 +13,6 @@ namespace Twig; use Twig\Error\Error; -use Twig\Error\LoaderError; use Twig\Error\RuntimeError; /** @@ -37,6 +36,7 @@ abstract class Template protected $parents = []; protected $blocks = []; protected $traits = []; + protected $traitAliases = []; protected $extensions = []; protected $sandbox; @@ -80,23 +80,16 @@ public function getParent(array $context): self|TemplateWrapper|false return $this->parent; } - try { - if (!$parent = $this->doGetParent($context)) { - return false; - } - - if ($parent instanceof self || $parent instanceof TemplateWrapper) { - return $this->parents[$parent->getSourceContext()->getName()] = $parent; - } + if (!$parent = $this->doGetParent($context)) { + return false; + } - if (!isset($this->parents[$parent])) { - $this->parents[$parent] = $this->loadTemplate($parent); - } - } catch (LoaderError $e) { - $e->setSourceContext(null); - $e->guess(); + if ($parent instanceof self || $parent instanceof TemplateWrapper) { + return $this->parents[$parent->getSourceContext()->getName()] = $parent; + } - throw $e; + if (!isset($this->parents[$parent])) { + $this->parents[$parent] = $this->loadTemplate($parent); } return $this->parents[$parent]; @@ -325,6 +318,7 @@ protected function loadTemplate($template, $templateName = null, $line = null, $ /** * @internal + * @return $this */ public function unwrap(): self { @@ -477,7 +471,7 @@ public function yieldBlock($name, array $context, array $blocks = [], $useBlocks public function yieldParentBlock($name, array $context, array $blocks = []): iterable { if (isset($this->traits[$name])) { - yield from $this->traits[$name][0]->yieldBlock($name, $context, $blocks, false); + yield from $this->traits[$name][0]->yieldBlock($this->traitAliases[$name] ?? $name, $context, $blocks, false); } elseif ($parent = $this->getParent($context)) { yield from $parent->unwrap()->yieldBlock($name, $context, $blocks, false); } else { @@ -485,6 +479,35 @@ public function yieldParentBlock($name, array $context, array $blocks = []): ite } } + protected function hasMacro(string $name, array $context): bool + { + if (method_exists($this, $name)) { + return true; + } + + if (!$parent = $this->getParent($context)) { + return false; + } + + return $parent->hasMacro($name, $context); + } + + protected function getTemplateForMacro(string $name, array $context, int $line, Source $source): Template + { + if (method_exists($this, $name)) { + return $this; + } + + $parent = $this; + while ($parent = $parent->getParent($context)) { + if (method_exists($parent, $name)) { + return $parent; + } + } + + throw new RuntimeError(\sprintf('Macro "%s" is not defined in template "%s".', substr($name, \strlen('macro_')), $this->getTemplateName()), $line, $source); + } + /** * Auto-generated method to display the template with the given context. * diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Test/IntegrationTestCase.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Test/IntegrationTestCase.php index 8690a809e..8c9d41f2a 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Test/IntegrationTestCase.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Test/IntegrationTestCase.php @@ -146,10 +146,10 @@ public function getTests($name, $legacyTests = false) throw new \InvalidArgumentException(\sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); } - $tests[] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs, $deprecation]; + $tests[str_replace($fixturesDir.'/', '', $file)] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs, $deprecation]; } - if ($legacyTests && empty($tests)) { + if ($legacyTests && !$tests) { // add a dummy test to avoid a PHPUnit message return [['not', '-', '', [], '', []]]; } @@ -245,7 +245,7 @@ protected function doIntegrationTest($file, $message, $condition, $templates, $e $output = trim($template->render(eval($match[1].';')), "\n "); } catch (\Exception $e) { if (false !== $exception) { - $this->assertSame(trim($exception), trim(\sprintf('%s: %s', \get_class($e), $e->getMessage()))); + $this->assertStringMatchesFormat(trim($exception), trim(\sprintf('%s: %s', \get_class($e), $e->getMessage()))); return; } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php index 0a6c1afb5..0c9507482 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php @@ -11,8 +11,9 @@ namespace Twig\TokenParser; -use Twig\Node\Expression\TempNameExpression; +use Twig\Node\Expression\Variable\LocalVariable; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\Node\PrintNode; use Twig\Node\SetNode; use Twig\Token; @@ -31,21 +32,17 @@ final class ApplyTokenParser extends AbstractTokenParser public function parse(Token $token): Node { $lineno = $token->getLine(); - $name = $this->parser->getVarName(); - - $ref = new TempNameExpression($name, $lineno); - $ref->setAttribute('always_defined', true); - + $ref = new LocalVariable(null, $lineno); $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref); $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); $body = $this->parser->subparse([$this, 'decideApplyEnd'], true); $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - return new Node([ + return new Nodes([ new SetNode(true, $ref, $body, $lineno), new PrintNode($filter, $lineno), - ], [], $lineno); + ], $lineno); } public function decideApplyEnd(Token $token): bool diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/BlockTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/BlockTokenParser.php index 81d675db0..3561b99cd 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/BlockTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/BlockTokenParser.php @@ -15,7 +15,9 @@ use Twig\Error\SyntaxError; use Twig\Node\BlockNode; use Twig\Node\BlockReferenceNode; +use Twig\Node\EmptyNode; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\Node\PrintNode; use Twig\Token; @@ -36,7 +38,7 @@ public function parse(Token $token): Node $lineno = $token->getLine(); $stream = $this->parser->getStream(); $name = $stream->expect(Token::NAME_TYPE)->getValue(); - $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); + $this->parser->setBlock($name, $block = new BlockNode($name, new EmptyNode(), $lineno)); $this->parser->pushLocalScope(); $this->parser->pushBlockStack($name); @@ -50,7 +52,7 @@ public function parse(Token $token): Node } } } else { - $body = new Node([ + $body = new Nodes([ new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), ]); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php index 86ddfdfba..a93afe8cd 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php @@ -13,6 +13,7 @@ namespace Twig\TokenParser; use Twig\Error\SyntaxError; +use Twig\Node\EmptyNode; use Twig\Node\Node; use Twig\Token; @@ -39,7 +40,7 @@ public function parse(Token $token): Node $stream->expect(Token::BLOCK_END_TYPE); - return new Node([], [], $token->getLine()); + return new EmptyNode($token->getLine()); } public function getTag(): string diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ForTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ForTokenParser.php index cf655f842..c0a0e3c29 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ForTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ForTokenParser.php @@ -12,7 +12,7 @@ namespace Twig\TokenParser; -use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\Variable\AssignContextVariable; use Twig\Node\ForNode; use Twig\Node\Node; use Twig\Token; @@ -50,13 +50,13 @@ public function parse(Token $token): Node if (\count($targets) > 1) { $keyTarget = $targets->getNode('0'); - $keyTarget = new AssignNameExpression($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); + $keyTarget = new AssignContextVariable($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); $valueTarget = $targets->getNode('1'); } else { - $keyTarget = new AssignNameExpression('_key', $lineno); + $keyTarget = new AssignContextVariable('_key', $lineno); $valueTarget = $targets->getNode('0'); } - $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); + $valueTarget = new AssignContextVariable($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); return new ForNode($keyTarget, $valueTarget, $seq, null, $body, $else, $lineno); } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/FromTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/FromTokenParser.php index 2ccff5fbe..3bb4201a3 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/FromTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/FromTokenParser.php @@ -11,7 +11,9 @@ namespace Twig\TokenParser; -use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\Variable\AssignContextVariable; +use Twig\Node\Expression\Variable\AssignTemplateVariable; +use Twig\Node\Expression\Variable\TemplateVariable; use Twig\Node\ImportNode; use Twig\Node\Node; use Twig\Token; @@ -35,9 +37,10 @@ public function parse(Token $token): Node while (true) { $name = $stream->expect(Token::NAME_TYPE)->getValue(); - $alias = $name; if ($stream->nextIf('as')) { - $alias = $stream->expect(Token::NAME_TYPE)->getValue(); + $alias = new AssignContextVariable($stream->expect(Token::NAME_TYPE)->getValue(), $token->getLine()); + } else { + $alias = new AssignContextVariable($name, $token->getLine()); } $targets[$name] = $alias; @@ -49,11 +52,11 @@ public function parse(Token $token): Node $stream->expect(Token::BLOCK_END_TYPE); - $var = new AssignNameExpression($this->parser->getVarName(), $token->getLine()); - $node = new ImportNode($macro, $var, $token->getLine(), $this->parser->isMainScope()); + $internalRef = new AssignTemplateVariable(new TemplateVariable(null, $token->getLine()), $this->parser->isMainScope()); + $node = new ImportNode($macro, $internalRef, $token->getLine()); foreach ($targets as $name => $alias) { - $this->parser->addImportedSymbol('function', $alias, 'macro_'.$name, $var); + $this->parser->addImportedSymbol('function', $alias->getAttribute('name'), 'macro_'.$name, $internalRef); } return $node; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/GuardTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/GuardTokenParser.php new file mode 100644 index 000000000..17b221d4c --- /dev/null +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/GuardTokenParser.php @@ -0,0 +1,69 @@ +parser->getStream(); + $typeToken = $stream->expect(Token::NAME_TYPE); + if (!in_array($typeToken->getValue(), ['function', 'filter', 'test'])) { + throw new SyntaxError(\sprintf('Supported guard types are function, filter and test, "%s" given.', $typeToken->getValue()), $typeToken->getLine(), $stream->getSourceContext()); + } + $method = 'get'.$typeToken->getValue(); + + $nameToken = $stream->expect(Token::NAME_TYPE); + + $exists = null !== $this->parser->getEnvironment()->$method($nameToken->getValue()); + + $stream->expect(Token::BLOCK_END_TYPE); + if ($exists) { + $body = $this->parser->subparse([$this, 'decideGuardFork']); + } else { + $body = new EmptyNode(); + $this->parser->subparseIgnoreUnknownTwigCallables([$this, 'decideGuardFork']); + } + $else = new EmptyNode(); + if ('else' === $stream->next()->getValue()) { + $stream->expect(Token::BLOCK_END_TYPE); + $else = $this->parser->subparse([$this, 'decideGuardEnd'], true); + } + $stream->expect(Token::BLOCK_END_TYPE); + + return new Nodes([$exists ? $body : $else]); + } + + public function decideGuardFork(Token $token): bool + { + return $token->test(['else', 'endguard']); + } + + public function decideGuardEnd(Token $token): bool + { + return $token->test(['endguard']); + } + + public function getTag(): string + { + return 'guard'; + } +} diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/IfTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/IfTokenParser.php index 4ea6f3df9..6b9010563 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/IfTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/IfTokenParser.php @@ -15,6 +15,7 @@ use Twig\Error\SyntaxError; use Twig\Node\IfNode; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\Token; /** @@ -69,7 +70,7 @@ public function parse(Token $token): Node $stream->expect(Token::BLOCK_END_TYPE); - return new IfNode(new Node($tests), $else, $lineno); + return new IfNode(new Nodes($tests), $else, $lineno); } public function decideIfFork(Token $token): bool diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ImportTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ImportTokenParser.php index f20f35ab3..5b3a5f2b8 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ImportTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/ImportTokenParser.php @@ -11,7 +11,8 @@ namespace Twig\TokenParser; -use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\Variable\AssignTemplateVariable; +use Twig\Node\Expression\Variable\TemplateVariable; use Twig\Node\ImportNode; use Twig\Node\Node; use Twig\Token; @@ -29,12 +30,12 @@ public function parse(Token $token): Node { $macro = $this->parser->getExpressionParser()->parseExpression(); $this->parser->getStream()->expect(Token::NAME_TYPE, 'as'); - $var = new AssignNameExpression($this->parser->getStream()->expect(Token::NAME_TYPE)->getValue(), $token->getLine()); + $name = $this->parser->getStream()->expect(Token::NAME_TYPE)->getValue(); + $var = new AssignTemplateVariable(new TemplateVariable($name, $token->getLine()), $this->parser->isMainScope()); $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + $this->parser->addImportedSymbol('template', $name); - $this->parser->addImportedSymbol('template', $var->getAttribute('name')); - - return new ImportNode($macro, $var, $token->getLine(), $this->parser->isMainScope()); + return new ImportNode($macro, $var, $token->getLine()); } public function getTag(): string diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/MacroTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/MacroTokenParser.php index c7762075c..7d47821b2 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/MacroTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/MacroTokenParser.php @@ -13,6 +13,12 @@ use Twig\Error\SyntaxError; use Twig\Node\BodyNode; +use Twig\Node\EmptyNode; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\Unary\NegUnary; +use Twig\Node\Expression\Unary\PosUnary; +use Twig\Node\Expression\Variable\LocalVariable; use Twig\Node\MacroNode; use Twig\Node\Node; use Twig\Token; @@ -33,8 +39,7 @@ public function parse(Token $token): Node $lineno = $token->getLine(); $stream = $this->parser->getStream(); $name = $stream->expect(Token::NAME_TYPE)->getValue(); - - $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); + $arguments = $this->parseDefinition(); $stream->expect(Token::BLOCK_END_TYPE); $this->parser->pushLocalScope(); @@ -51,7 +56,7 @@ public function parse(Token $token): Node $this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno)); - return new Node([], [], $lineno); + return new EmptyNode($lineno); } public function decideBlockEnd(Token $token): bool @@ -63,4 +68,56 @@ public function getTag(): string { return 'macro'; } + + private function parseDefinition(): ArrayExpression + { + $arguments = new ArrayExpression([], $this->parser->getCurrentToken()->getLine()); + $stream = $this->parser->getStream(); + $stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) { + if (count($arguments)) { + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); + + // if the comma above was a trailing comma, early exit the argument parse loop + if ($stream->test(Token::PUNCTUATION_TYPE, ')')) { + break; + } + } + + $token = $stream->expect(Token::NAME_TYPE, null, 'An argument must be a name'); + $name = new LocalVariable($token->getValue(), $this->parser->getCurrentToken()->getLine()); + if ($token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) { + $default = $this->parser->getExpressionParser()->parseExpression(); + } else { + $default = new ConstantExpression(null, $this->parser->getCurrentToken()->getLine()); + $default->setAttribute('is_implicit', true); + } + + if (!$this->checkConstantExpression($default)) { + throw new SyntaxError('A default value for an argument must be a constant (a boolean, a string, a number, a sequence, or a mapping).', $token->getLine(), $stream->getSourceContext()); + } + $arguments->addElement($default, $name); + } + $stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); + + return $arguments; + } + + // checks that the node only contains "constant" elements + private function checkConstantExpression(Node $node): bool + { + if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression + || $node instanceof NegUnary || $node instanceof PosUnary + )) { + return false; + } + + foreach ($node as $n) { + if (!$this->checkConstantExpression($n)) { + return false; + } + } + + return true; + } } diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php index 70869fbc5..a7260ac46 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php @@ -34,6 +34,8 @@ final class SandboxTokenParser extends AbstractTokenParser public function parse(Token $token): Node { $stream = $this->parser->getStream(); + trigger_deprecation('twig/twig', '3.15', \sprintf('The "sandbox" tag is deprecated in "%s" at line %d.', $stream->getSourceContext()->getName(), $token->getLine())); + $stream->expect(Token::BLOCK_END_TYPE); $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); $stream->expect(Token::BLOCK_END_TYPE); diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/TypesTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/TypesTokenParser.php index 2e0850e7e..b97eb3b2e 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/TypesTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/TypesTokenParser.php @@ -20,7 +20,7 @@ /** * Declare variable types. * - * {% types {foo: 'int', bar?: 'string'} %} + * {% types {foo: 'number', bar?: 'string'} %} * * @author Jeroen Versteeg * diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/UseTokenParser.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/UseTokenParser.php index 1b96b4047..ebd95aa31 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/UseTokenParser.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenParser/UseTokenParser.php @@ -12,8 +12,10 @@ namespace Twig\TokenParser; use Twig\Error\SyntaxError; +use Twig\Node\EmptyNode; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Node; +use Twig\Node\Nodes; use Twig\Token; /** @@ -61,9 +63,9 @@ public function parse(Token $token): Node $stream->expect(Token::BLOCK_END_TYPE); - $this->parser->addTrait(new Node(['template' => $template, 'targets' => new Node($targets)])); + $this->parser->addTrait(new Nodes(['template' => $template, 'targets' => new Nodes($targets)])); - return new Node([], [], $token->getLine()); + return new EmptyNode($token->getLine()); } public function getTag(): string diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenStream.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenStream.php index c91701bfe..35aa9714f 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TokenStream.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TokenStream.php @@ -27,7 +27,11 @@ public function __construct( private array $tokens, private ?Source $source = null, ) { - $this->source = $source ?: new Source('', ''); + if (null === $this->source) { + trigger_deprecation('twig/twig', '3.16', \sprintf('Not passing a "%s" object to "%s" constructor is deprecated.', Source::class, __CLASS__)); + + $this->source = new Source('', ''); + } } public function __toString() @@ -117,11 +121,6 @@ public function getCurrent(): Token return $this->tokens[$this->current]; } - /** - * Gets the source associated with this stream. - * - * @internal - */ public function getSourceContext(): Source { return $this->source; diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/TwigFilter.php b/.extlib/simplesamlphp/vendor/twig/twig/src/TwigFilter.php index 70b1f8f3f..dece51843 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/TwigFilter.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/TwigFilter.php @@ -54,12 +54,12 @@ public function getSafe(Node $filterArgs): ?array return $this->options['is_safe_callback']($filterArgs); } - return null; + return []; } - public function getPreservesSafety(): ?array + public function getPreservesSafety(): array { - return $this->options['preserves_safety']; + return $this->options['preserves_safety'] ?? []; } public function getPreEscape(): ?string diff --git a/.extlib/simplesamlphp/vendor/twig/twig/src/Util/CallableArgumentsExtractor.php b/.extlib/simplesamlphp/vendor/twig/twig/src/Util/CallableArgumentsExtractor.php index 8811ca9c8..d8625169d 100644 --- a/.extlib/simplesamlphp/vendor/twig/twig/src/Util/CallableArgumentsExtractor.php +++ b/.extlib/simplesamlphp/vendor/twig/twig/src/Util/CallableArgumentsExtractor.php @@ -40,22 +40,25 @@ public function __construct( public function extractArguments(Node $arguments): array { $extractedArguments = []; + $extractedArgumentNameMap = []; $named = false; foreach ($arguments as $name => $node) { if (!\is_int($name)) { $named = true; - $name = $this->normalizeName($name); } elseif ($named) { throw new SyntaxError(\sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); } - $extractedArguments[$name] = $node; + $extractedArguments[$normalizedName = $this->normalizeName($name)] = $node; + $extractedArgumentNameMap[$normalizedName] = $name; } if (!$named && !$this->twigCallable->isVariadic()) { $min = $this->twigCallable->getMinimalNumberOfRequiredArguments(); if (\count($extractedArguments) < $this->rc->getReflector()->getNumberOfRequiredParameters() - $min) { - throw new SyntaxError(\sprintf('Value for argument "%s" is required for %s "%s".', $this->rc->getReflector()->getParameters()[$min + \count($extractedArguments)]->getName(), $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); + $argName = $this->toSnakeCase($this->rc->getReflector()->getParameters()[$min + \count($extractedArguments)]->getName()); + + throw new SyntaxError(\sprintf('Value for argument "%s" is required for %s "%s".', $argName, $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); } return $extractedArguments; @@ -71,37 +74,38 @@ public function extractArguments(Node $arguments): array [$callableParameters, $isPhpVariadic] = $this->getCallableParameters(); $arguments = []; - $names = []; + $callableParameterNames = []; $missingArguments = []; $optionalArguments = []; $pos = 0; foreach ($callableParameters as $callableParameter) { - $name = $this->normalizeName($callableParameter->name); + $callableParameterName = $callableParameter->name; if (\PHP_VERSION_ID >= 80000 && 'range' === $callable) { - if ('start' === $name) { - $name = 'low'; - } elseif ('end' === $name) { - $name = 'high'; + if ('start' === $callableParameterName) { + $callableParameterName = 'low'; + } elseif ('end' === $callableParameterName) { + $callableParameterName = 'high'; } } - $names[] = $name; + $callableParameterNames[] = $callableParameterName; + $normalizedCallableParameterName = $this->normalizeName($callableParameterName); - if (\array_key_exists($name, $extractedArguments)) { + if (\array_key_exists($normalizedCallableParameterName, $extractedArguments)) { if (\array_key_exists($pos, $extractedArguments)) { - throw new SyntaxError(\sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); + throw new SyntaxError(\sprintf('Argument "%s" is defined twice for %s "%s".', $callableParameterName, $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); } if (\count($missingArguments)) { throw new SyntaxError(\sprintf( 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".', - $name, $this->twigCallable->getType(), $this->twigCallable->getName(), implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments) + $callableParameterName, $this->twigCallable->getType(), $this->twigCallable->getName(), implode(', ', array_map([$this, 'toSnakeCase'], $callableParameterNames)), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments) ), $this->node->getTemplateLine(), $this->node->getSourceContext()); } $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $extractedArguments[$name]; - unset($extractedArguments[$name]); + $arguments[] = $extractedArguments[$normalizedCallableParameterName]; + unset($extractedArguments[$normalizedCallableParameterName]); $optionalArguments = []; } elseif (\array_key_exists($pos, $extractedArguments)) { $arguments = array_merge($arguments, $optionalArguments); @@ -116,9 +120,9 @@ public function extractArguments(Node $arguments): array break; } - $missingArguments[] = $name; + $missingArguments[] = $callableParameterName; } else { - throw new SyntaxError(\sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); + throw new SyntaxError(\sprintf('Value for argument "%s" is required for %s "%s".', $this->toSnakeCase($callableParameterName), $this->twigCallable->getType(), $this->twigCallable->getName()), $this->node->getTemplateLine(), $this->node->getSourceContext()); } } @@ -128,7 +132,13 @@ public function extractArguments(Node $arguments): array if (\is_int($key)) { $arbitraryArguments->addElement($value); } else { - $arbitraryArguments->addElement($value, new ConstantExpression($key, $this->node->getTemplateLine())); + $originalKey = $extractedArgumentNameMap[$key]; + if ($originalKey !== $this->toSnakeCase($originalKey)) { + trigger_deprecation('twig/twig', '3.15', \sprintf('Using "snake_case" for variadic arguments is required for a smooth upgrade with Twig 4.0; rename "%s" to "%s" in "%s" at line %d.', $originalKey, $this->toSnakeCase($originalKey), $this->node->getSourceContext()->getName(), $this->node->getTemplateLine())); + } + $arbitraryArguments->addElement($value, new ConstantExpression($this->toSnakeCase($originalKey), $this->node->getTemplateLine())); + // I Twig 4.0, don't convert the key: + // $arbitraryArguments->addElement($value, new ConstantExpression($originalKey, $this->node->getTemplateLine())); } unset($extractedArguments[$key]); } @@ -151,7 +161,7 @@ public function extractArguments(Node $arguments): array throw new SyntaxError( \sprintf( 'Unknown argument%s "%s" for %s "%s(%s)".', - \count($extractedArguments) > 1 ? 's' : '', implode('", "', array_keys($extractedArguments)), $this->twigCallable->getType(), $this->twigCallable->getName(), implode(', ', $names) + \count($extractedArguments) > 1 ? 's' : '', implode('", "', array_keys($extractedArguments)), $this->twigCallable->getType(), $this->twigCallable->getName(), implode(', ', array_map([$this, 'toSnakeCase'], $callableParameterNames)) ), $unknownArgument ? $unknownArgument->getTemplateLine() : $this->node->getTemplateLine(), $unknownArgument ? $unknownArgument->getSourceContext() : $this->node->getSourceContext() @@ -163,7 +173,12 @@ public function extractArguments(Node $arguments): array private function normalizeName(string $name): string { - return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $name)); + return strtolower(str_replace('_', '', $name)); + } + + private function toSnakeCase(string $name): string + { + return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z0-9])([A-Z])/'], '\1_\2', $name)); } private function getCallableParameters(): array